I am trying to run a jest test(which renders a bpmn diagram) and I am using angular 11. Though i am getting
TypeError: this.getDefaultLayer(...).getBBox is not a function error. so probably i think we need to mock the bpmn-js.
You need to follow these steps (all in test file):
Import BpmnJS
We use these import to mock later the BpmnJs object.
import BpmnJs from 'bpmn-js/dist/bpmn-navigated-viewer.production.min'
Create a mock object with BpmnJs methods
Here you can mock any method of BpmnJs object. And we use this object to return to object instance.
const mockBpmn = {
get: jest.fn().mockReturnValue({
zoom: jest.fn,
stepZoom: jest.fn,
add: jest.fn,
}),
destroy: jest.fn,
on: jest.fn,
importXML: jest.fn,
}
Mock module and BpmnJS object
Here we tell mock module and object instantiation.
jest.mock('bpmn-js/dist/bpmn-navigated-viewer.production.min')
BpmnJs.mockImplementation(() => mockBpmn)
Now you can use BpmnJs in your React Component (or class under test) normally.
Related
I'm playing with mount() from vue-test-utils, have a component that imports services that should be mocked in the unit test.
I see that mount() has a mocks option, but trying to extrapolate the example given at guides, common-tips, mocking injections to the scenario of an injected service is eluding me.
mount(Component, {
mocks: {
...?
}
})
The component simply imports the service, which is plain JS
import DataService from '../services/data.service'
I can get it working using the inject-loader which is detailed here Testing With Mocks
The code that does work
const MyComponentInjector = require('!!vue-loader?inject!./MyComponent.vue')
const mockedServices = {
'../services/data.service': {
checkAll: () => { return Promise.resolve() }
},
}
const MyComponentWithMocks = MyComponentInjector(mockedServices)
const wrapper = mount(MyComponentWithMocks, { store: mockStore, router })
What is the syntax for mount(MyComponent, { mocks: ... })?
Since mount() has a mocks option, should it not be possible to pass mockedServices to it in some form?
mocks refers to the Vue instance. You're trying to mock a file dependency, which is a different problem. As you said, one solution is inject-loader. Another is the babel-plugin-rewire.
Let me clear up what the mocks option does.
mocks adds properties to the Vue instance.
If you have an app that injects $route, you might have a component that tries to access it: this.$route.path:
...
methods: {
logPath() {
console.log(this.$route.path)
}
}
...
If you try to mount this component without installing Vue router, it will throw an error. To solve this, you can use the mocks mount option to inject a mock $route object to the Vue instance:
const $route = { path: 'some/mock/value' }
mount(Component, {
mocks: {
$route
}
})
I use enzyme with sinon for unit testing React components. Normally, when it comes to testing instance methods I just spy on the method on instance of the component and assert respectively.
However, I have this global function that I use in many components of the app, which is a named export. sinon throws if I try to spy on that.
import { openModel } from '../global/handlers/';
<Block
onRemove={(data) => openModal(...args)}
/>
So, currently I am calling prop method onRemove to assert that openModal gets called with the arguments but I can't really spy on the exported method i.e. openModal.
I understand that I need to provide a context to this function to be able to spy on the underlying function but I am not really sure what's the preferred way of doing something like this.
PS: I would be happy to provide more details if need be.
If you are using webpack to build your test code, then you can use inject-loader to replace the imported module with a stub:
describe('Your component', () => {
let openModalSpy;
let Component;
// Use whatever the path to your component is
const injectImports = require('inject-loader!components/Component');
beforeEach(() => {
openModalSpy = sinon.spy();
Component = injectImports({
openModal: openModalSpy
}).default;
})
it('calls open modal with data argument', () => {
const wrapper = shallow(
<Component />
);
// Do something that will result in openModal being called
expect(openModalSpy).to.have.been.calledWith({
// some data
});
}
}
I am currently testing one of my React component like this:
it('renders correctly', () => {
const tree = renderer.create(<Scene {...props} />).toJSON();
expect(tree).toMatchSnapshot();
});
My component Scene imports a setting.json file. I have that file on my local instance, but I do not push it on my CI instance. So when it tries to import it, the file is not found.
Is there a way to mock this file in my test ?
You can either use moduleNameMapper in your jest settings to point the import to an mocked json file.
{
"moduleNameMapper": {
"setting.json": "<rootDir>/__mocks__/setting.json"
}
}
Or you can use jest.mock inside your test to mock the file directly, note that you have to add the { virtual: true } parameter.
jest.mock('path/to/setting.json', ()=>({
settings: 'someSetting'
}), { virtual: true })
For those looking to mock JSON in the form of an Array, just return an array from the callback.
jest.mock('./data.json', () => ([1, 2, 3]));
You can return other valid JSON types as well: Object, String, Number, Boolean, or Null.
Little exhausted here, may be that is why my title is not so accurate.
I am writing a unit test for my DummyService:
import {Injectable} from '#angular/core';
#Injectable()
export class DummyService {
getAllDataSources():Promise<Array<DummyData>> {
return new Promise<DummyData[]>(resolve =>
setTimeout(()=>resolve([]), 1000) // 1 seconds
);
}
}
Please assume am returning a list of DummyData objects from getAllDataSources.
Now, I have a structure/interface for the dummy data in the same service file:
export interface DummyData{
Name:string;
IsActive:boolean;
}
I tried to write unit test for this service:
import {DummyService, DummyData} from './dummy.service';
import {
beforeEachProviders
} from '#angular/core/testing';
import {provide} from '#angular/core';
export function main() {
describe('dummy.service', () => {
let dsService:DummyService;
it('should fetch data', ()=> {
dummyData: DummyData = new DummyData(); // >>>> culprit...
expect(1).toEqual(1);
});
});
}
This unit test seem little funny, as I am really not calling DummyServices function to get the list of DummyData.
I am doing this because I was getting some issue, due to which I was not able to see my test. I did some research, spent a whole day and finally found that this structure DummyData is the CULPRIT. I proved this to myself when I tried creating an object of it in my unit test (in the code above) and I got the following error:
FAILED TESTS:
dummy.service
✖ should fetch data
PhantomJS 2.1.1 (Linux 0.0.0)
Chrome 50.0.2661 (Linux 0.0.0)
ReferenceError: **DummyData is not defined**
at eval (/home/aodev/WebstormProjects/Data Federation App/data-mapping-app/dist/dev/app/shared/datasource.service.spec.js:8:28)
at Object.eval (/home/aodev/WebstormProjects/Data Federation App/data-mapping-app/node_modules/#angular/core/testing/testing.js:80:25)
So, can someone tell me please, what am I doing wrong?
Why I cannot create the object of DummyData inside my unit test?
Please help!
TypeScript interfaces exist only during compile time, runtime knows nothing about interfaces.
This is how you create instance that implements interface:
interface itest
{
success:boolean;
}
let a:itest = {success: true}; //compiler checks that object matches interface itest
I'm trying to mock out the window object for a component I'm using with just the four libraries listed above.
I know it can be done with JSDom but the client is against using it. Based on my research simply doing sinon.stub(window,'location') should work but when I run my tests I still get Window undefined in my component.
Currently the component is called within the render return {window.location.host}
any thoughts to what I am doing wrong to get sinon to stub out that one piece. Once I stub out that piece then I can focus on testing the other parts of that component that have nothing to do with window.
My Test Method:
import React from 'react';
import { shallow } from 'enzyme';
import chai from 'chai';
chai.should();
import sinon from 'sinon';
import BillingStatementRow from '../BillingStatementRow';
describe('Test <BillingStatementRow /> Component', function() {
context('Function Testing', function() {
it('Test - onFieldChange - Make sure it handles NaN', function() {
var e = {target: {value: NaN}};
var window = { location : { host : "..." } };
var mockedOnChange = sinon.spy();
const wrapper = shallow (
<BillingStatementRow slds={''} key={'1'}
Id={'1'} inputValue={'0'} salesInvoice={'SIN0001'}
invoicedAmount={1000} duedate={'1461628800000'}
outstandingBalance={1000} receiptRemaining={1000}
amountAllocated={1000} onChange={mockedOnChange.bind(this,'BS0001')} />
);
wrapper.instance().onFieldChange('amountAllocated', e);
wrapper.update();
})
});
});
Sinon stubs/spies/mocks only work with functions. In this case, you're trying to mock a global (nested) variable, for which Sinon isn't the right tool.
Instead, just like in a browser, you can create a global object that mocks just the right amount of window to work with your component, which is easy because it only accesses window.location.host.
So before instantiating the component, declare the following:
global.window = { location : { host : 'example.com' } };