Puzzle Frontend Kafi #9, 23.11.2017
Mathis Hofer, hofer@puzzle.ch
Jest
Goals
What is Jest and how can I use it?
How does snapshot testing work?
Introduction
License
Previously: BSD + Patents
Now: MIT
Advantages
Easy Setup
Instant Feedback
Snapshot Testing
No browser needed (Node/jsdom)
Parallelized
No webpack needed
Who uses it?

Basic testing
const sum = require('./sum');
describe('sum', () => {
beforeEach(() => ...);
afterEach(() => ...);
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
});test also under alias it
describe.only/test.only (alias fdescribe/fit)
describe.skip/test.skip (alias xdescribe/xit)
Structure and scoping
Matchers*
expect(result).toBe(obj)
expect(result).not.toEqual('foo')
expect(result).toBeDefined()
expect(result).toBeNull()
expect(result).toBeTruthy()
expect(getAllFlavors())
.toContain('lime');
expect(essayOnTheBestFlavor())
.toMatch(/grapefruit/);
expect(drinkOctopus)
.toThrowError(DisgustingFlavorError);*mostly Jasmine compatible
Asynchronous
it('works with function argument', (done) => {
user.getUserName(4).then(data => {
expect(data).toEqual('Mark');
done();
});
});
it('works with promises', () => {
expect.assertions(1);
return user.getUserName(4).then(data => expect(data).toEqual('Mark'));
});
it('works with resolves', () => {
expect.assertions(1);
return expect(user.getUserName(5)).resolves.toEqual('Paul');
});
it('works with async/await', async () => {
expect.assertions(1);
const data = await user.getUserName(4);
expect(data).toEqual('Mark');
});Running
# Run for (/__tests__/.*|\.(test|spec))\.(ts|js)$
jest
# Run continously only for changing files
jest --watch
# Run for files changed since last commit
jest -o
# Run on files changed in last commit
jest --lastCommit
# Run matching spec name
jest -t 'displays error on complete import failure'
# Run tests related to given files
jest --findRelatedTests path/to/file.jsDebugging
Run Jest as such:
node --inspect-brk node_modules/.bin/jest --runInBand [other arguments here]Open displayed link in Chrome
Mocking
Mock functions
let mockFunc = jest.fn();
mockFunc
.mockReturnValueOnce(10)
.mockReturnValueOnce('x')
.mockReturnValue(true);
mockFunc = jest.fn((a, b) => a + b);
expect(mockFunc).toBeCalled();
expect(mockFunc).toBeCalledWith(arg1, arg2);
expect(mockFunc.mock.calls.length).toEqual(2)Spies
const spy = jest.spyOn(video, 'play');
video.play();
expect(spy).toHaveBeenCalled();Mock modules
import importHelper from '../helpers/import';
jest.mock('../helpers/import', () => ({
importTabGroupsJson: jest.fn().mockImplementation(() => Promise.resolve()),
}));Mock timers
jest.useFakeTimers();
jest.advanceTimersByTime(1000);
jest.runAllTimers();Manual mocks
Put file in __mocks__/fs.js
In test do: jest.mock('fs');
Snapshot testing
Demo
But... what about TDD?
Snapshots help figuring out whether the output of the modules covered by tests is changed, rather than giving guidance to design the code in the first place.
Jest + Angular?
Yes, please!
Setup
Add TypeScript support
Install jest-preset-angular
Add file setupJest.ts:
"jest": {
"preset": "jest-preset-angular",
"setupTestFrameworkScriptFile": "./setupJest.ts"
}Add this to package.json:
import 'jest-preset-angular';Demo
Further topics
Babel
Add .babelrc
Install babel-jest
TypeScript
Install ts-jest
Configure transformer for *.ts in package.json
Coverage
jest --coverage
jest --coverage --coverageDirectory=reports/coverageJUnit XML
Install jest-junit
Set it as testResultsProcessor
Out of the box:
Migration
Codemods for Jasmine, Mocha, Chai etc.:
https://github.com/skovhus/jest-codemods
(based on jscodeshift)
Done.
Slides: https://slides.com/hupf/jest/
Examples: https://github.com/hupf/jest-example
JavaScript Testing with Jest
By Mathis Hofer
JavaScript Testing with Jest
- 1,380