Jest: Difference between revisions
Line 240: | Line 240: | ||
=Matchers in Jest= | =Matchers in Jest= | ||
These can be found [https://facebook.github.io/jest/docs/en/expect.html] | These can be found [https://facebook.github.io/jest/docs/en/expect.html] | ||
Some of them for quick reference. | |||
expect(value) | |||
expect.extend(matchers) | |||
expect.anything() | |||
expect.any(constructor) | |||
expect.arrayContaining(array) | |||
expect.assertions(number) | |||
expect.hasAssertions() | |||
expect.not.arrayContaining(array) | |||
expect.not.objectContaining(object) | |||
expect.not.stringContaining(string) | |||
expect.not.stringMatching(string | regexp) | |||
expect.objectContaining(object) | |||
expect.stringContaining(string) | |||
expect.stringMatching(string | regexp) | |||
expect.addSnapshotSerializer(serializer) |
Revision as of 01:07, 28 May 2020
Why Not Enzyme
This has over 200+ issues open and 26 of these are bugs. Jest is recommended by the react team.
Naming Test
__tests__/*.js *.spec.js *.test.js
Example Test
Describe is the suite, it is the test
describe("The question list ", ()=> { it ("should display a list of items", ()=> { expect(2+2).toEqual(4); })
it ("should display a list of items", ()=> { expect(2+4).toEqual(6); })
})
Setup and Teardown
This can be done using
BeforeEach BeforeAll
beforeAll(()=>{ console.log("Hello"); });
and
AfterEach AfterAll
afterAll(()=>{ console.log("Hello"); });
Note does not matter what order you write them in.
Skipping and Isolating Tests
Add keyword only to include tests
it.only ("should display a list of items", ()=> { expect(2+2).toEqual(4); })
Add keyword skip to exlude tests
it.skip ("should display a list of items", ()=> { expect(2+2).toEqual(4); })
Async Tests
it('async test 1', done=> { setTimeout(done, 100) });
it('async test 2',()=> { return new Promise( resolve => setTimeout(resolve,100) ); });
it('async test 1', async ()=> await delay(100) );
Mocking
Create directory __mocking__ at the same level as node_modules
Here is an example for mocking fetch package isomorphic-fetch
let __value = 42;
const isomorphicFetch = jest.fn( ()=> __value);
isomorphicFetch.__setValue = v => __value = v;
export default isomorphicFetch;
And the test case. We import the function to be mocked from out __mocks__/isomorphic-fetch.js
import { handleFetchQuestion } from './fetch-question-saga';
import fetch from 'isomorphic-fetch';
describe("Fetch question s saga", ()=>{
beforeAll( () => {
fetch.__setValue([{question_id:42}] );
});
it ("should fetch the question saga", async ()=> {
const gen = handleFetchQuestion({question_id:42});
const { value } = await gen.next();
expect(value).toEqual( [{question_id:42}] )
expect(fetch).toHaveBeenCalledWith('/api/questions/42');
});
});
Redux and Testing mapStateToProps
You can easily test the map from state to props. e.g.
import { mapStateToProps } from '../QuestionDetail';
it("should map the state to props correctly", () => {
// Sample App State with sampleQuestion being object in state
const sampleQuestion {
question_id:42,
body: "Space is big"
};
const appState = {
questions: [sampleQuestion]
};
// Sample Props
const ownProps = {
question:42
});
const componentState = mapStateToProps(appState, ownProps)
expect(componentState).toEqual(sampleQuestion);
}
Sample test with state
Bit of a lot of code but here goes
Create component to test
import React from 'react';
export default class extends React.Component {
constructor)(...args) {
super(...args);
this.state = {
count: -1
}
}
async comonentDidMount () {
let { count } = await NotificationService.GetNotification();
this.setState( {
count
});
}
render() {
return (
<section className="mt-3 mb-2">
<div className="notifications">
{this.state.count != -1 ? '${this.state.count} Notifications Awaiting!' : 'Loading...'}
</div>
</section>
)
}
}
Create a Service
export default {
async GetNoitifications() {
console.warning("REAL NOTIFICATION SERVICE!");
await delay(1000);
return { count: 42 };
}
}
Test Case
import NotificationsViewer from '../NotificationsViewer';
import renderer from 'react-test-renderer';
import React from 'react';
import delay from 'redux-saga';
// NOTE Local module you need to pass in url of notification service
jest.mock('../../services/NotificationService');
// NOTE 2 this needs to be a require and needs to be after the jest. Making it
// an import will fail
const notificationService = require('../../services/NotificationService').default;
describe("The notification viewer", () => {
beforeAll( ()=> {
notificationService.__setCount(5);
});
it("should display the correct number of notifications", async()=> {
const tree = renderer
.create(
<NoticationsViewer/>
)
await delay();
const instance = tree.root;
// find by className the component
const component = instance.findByProps( { className: 'notificiations' });
const text = component.children[0];
export(text).toEqual("5 Notifications");
});
});
Mocked Service src\services\__mocks__\NotificationService.js
let count = 0;
export default {
__setCount(__count) {
count = _count;
},
async GetNotifications() {
console.warn("Good Job! Using Mock");
}
}
Matchers in Jest
These can be found [1]
Some of them for quick reference.
expect(value) expect.extend(matchers) expect.anything() expect.any(constructor) expect.arrayContaining(array) expect.assertions(number) expect.hasAssertions() expect.not.arrayContaining(array) expect.not.objectContaining(object) expect.not.stringContaining(string) expect.not.stringMatching(string | regexp) expect.objectContaining(object) expect.stringContaining(string) expect.stringMatching(string | regexp) expect.addSnapshotSerializer(serializer)