Jest can do whaaat?

A presentation at React Open Source Berlin in November 2017 in Berlin, Germany by Robin Pokorny

Slide 1

Slide 1

JEST can do whaaat? @robinpokorny React Open Source Berlin 1 November 2017

Slide 2

Slide 2

INFO Slides accompany a talk. Here, the talk is missing. For the full experience see the recording. I welcome any feedback!

Slide 3

Slide 3

WHAT IS JEST delightful, zero configuration testing platform Jasmine’s and Expect’s successor practical utilities for awesome DX http://facebook.github.io/jest/

Slide 4

Slide 4

SNAPSHOT TESTING

Slide 5

Slide 5

Slide 6

Slide 6

Slide 7

Slide 7

describe(‘method’, () !=> { test(‘works’, () !=> { const full = { number: 1975, bool: true, string: ‘Hello, Vanek’, promise: Promise.resolve(‘Better job’), symbol: Symbol(‘brewery’), [Symbol.for(‘brewmaster’)]: ‘Next beer!’, … }; expect(full).toMatchSnapshot(); expect(1936).toMatchSnapshot(); }); }); TEST

Slide 8

Slide 8

!// Jest Snapshot v1, https:!//goo.gl/fbAQLP exports[method works 1] = Object { "bool": true, … "undefined": undefined, Symbol(brewmaster): "Next beer!", }; exports[method works 2] = 1936; SNAPSHOT

Slide 9

Slide 9

` Object { “bool”: true, “func”: [Function], “map”: Map { “position1” !=> “workman”, “position2” !=> “stockkeeper”, }, “null”: null, “number”: 1975, “promise”: Promise {}, SNAPSHOT

Slide 10

Slide 10

SNAPSHOT } ` “set”: Set { “think”, “write”, “snitch”, }, “string”: “Hello, Vanek”, “symbol”: Symbol(brewery), “undefined”: undefined, Symbol(brewmaster): “Next beer!”,

Slide 11

Slide 11

describe(‘method’, () !=> { test(‘works’, () !=> { const full = { … }; TEST expect(full).toMatchSnapshot(‘new name’); }); }); SNAPSHOT exports[new name 1] =

Slide 12

Slide 12

test(‘mock function’, () !=> { const fn = jest.fn(); TEST fn(‘Vanek’); fn(‘Ferdinand’, ‘Vanek’); expect(fn).toHaveBeenCalledWith(‘Vanek’); expect(fn).toHaveBeenCalledWith(‘Ferdinand’, ‘Vanek’); expect(fn).toHaveBeenCalledTimes(2); !// vs expect(fn.mock.calls).toMatchSnapshot(); });

Slide 13

Slide 13

exports[method mock function 1] = Array [ Array [ "Vanek", ], Array [ "Ferdinand", "Vanek", ], ]; SNAPSHOT

Slide 14

Slide 14

?

Slide 15

Slide 15

exports[component with defaults] = ` <div style={ Object { “backgroundColor”: “black”, “display”: “flex”, “flexDirection”: “column”, } }> <h1> … SNAPSHOT

Slide 16

Slide 16

TEST expect(Immutable.Map({ a: 1, b: 2 })).toMatchSnapshot(); exports[method immutable 1] = Immutable.Map { "a": 1, "b": 2, }; SNAPSHOT

Slide 17

Slide 17

const plugin = { SERIALISER test(val) { return val !&& val.isPlay; }, serialize(val, config, indent, depth, refs, printer) { const name = val.constructor.name; const newIndent = indent + config.indent; return ( Play <${val.title}>: + printer(val.content, config, newIndent, depth!++, refs) ); } };

Slide 18

Slide 18

expect.addSnapshotSerializer(plugin); or // package.json { … “jest”: { “snapshotSerializers”: [“plugin.js”] } } SERIALISER

Slide 19

Slide 19

test(‘play’, () !=> { const play = { isPlay: true, title: ‘Audience’, content: { scenes: 1 } }; expect([ play ]).toMatchSnapshot(); }); TEST

Slide 20

Slide 20

SNAPSHOT exports[method play 1] = Array [ Play <Audience>: Object { "scenes": 1, }, ];

Slide 21

Slide 21

TEST test(‘diff’, () !=> { const play = { title: ‘Audience’, characters: 2 }; expect(play).toMatchSnapshot(); expect({ !!…play, characters: 3 }).toMatchSnapshot(); });

Slide 22

Slide 22

exports[diff 1] = Object { "characters": 2, "title": "Audience", }; exports[diff 2] = Object { "characters": 3, "title": "Audience", }; SNAPSHOT

Slide 23

Slide 23

const { toMatchDiffSnapshot } = require(‘snapshot-diff’); expect.extend({ toMatchDiffSnapshot }); test(‘diff’, () !=> { const play = { title: ‘Audience’, characters: 2 }; expect(play) .toMatchDiffSnapshot({ !!…play, characters: 3 }); });

Slide 24

Slide 24

exports[diff 1] = "Snapshot Diff: - First value + Second value Object { !\\"characters!\\": 2, + !\\"characters!\\": 3, !\\"title!\\": !\\"Audience!\\", }"; SNAPSHOT

Slide 25

Slide 25

TDD ✖ SNAPSHOTS algorithms structures write before concurrent or after part whole inside codebase

Slide 26

Slide 26

watch

Slide 27

Slide 27

$ jest !—watch $ npm test !— !—watch

Slide 28

Slide 28

understands dependencies filter by Path or Test name Update snapshots failed re-run first

Slide 29

Slide 29

!// moduleA.spec.js const moduleA = require(‘./moduleA’); test(‘moduleA’, () !=> { expect(moduleA()).toBe(true); }); !// moduleA.js const moduleB = require(‘./moduleB’); DEPS

Slide 30

Slide 30

Slide 31

Slide 31

Slide 32

Slide 32

ASYNC in JEST testing

Slide 33

Slide 33

CALLBACK test(‘promise’, done !=> { Promise.resolve(7) .then(n !=> { expect(n).toBe(7); }) .then(done) .catch(done.fail); });

Slide 34

Slide 34

test(‘promises’, () !=> { Promise.resolve(8).then(n !=> { expect(n).toBe(7); }); return Promise.resolve(7).then(n !=> { expect(n).toBe(7); }); }); PROMISES

Slide 35

Slide 35

Slide 36

Slide 36

test(‘reject’, () !=> { return Promise.reject(0).catch(n !=> { expect(n).toBe(0); }); }); REJECTION

Slide 37

Slide 37

test(‘reject’, () !=> { return Promise.reject(0).catch(n !=> { expect(n).toBe(0); }); }); test(‘reject’, () !=> { return Promise.resolve(7).catch(n !=> { expect(n).toBe(0); }); }); REJECTION

Slide 38

Slide 38

test(‘reject’, () !=> { expect.assertions(1); return Promise.resolve(7) .then(() !=> { throw new Error(‘Not rejected!’); }) .catch(n !=> { expect(n).toBe(0); }); }); REJECTION

Slide 39

Slide 39

Slide 40

Slide 40

test(‘async’, async () !=> { const n = await Promise.resolve(7) const m = await Promise.resolve(42) expect(n).toBe(7) expect(m).toBe(42) }) ASYNC AWAIT

Slide 41

Slide 41

test(‘async’, async () !=> { const n = Promise.resolve(7) const m = await Promise.resolve(42) expect(n).toBe(7) expect(m).toBe(42) }) ASYNC AWAIT

Slide 42

Slide 42

Slide 43

Slide 43

test(‘async rejection’, async () !=> { try { await Promise.reject(0); } catch (e) { expect(e).toBe(0); } }); ASYNC REJECTION

Slide 44

Slide 44

test(‘async rejection’, async () !=> { try { await Promise.resolve(7); } catch (e) { expect(e).toBe(0); } }); ASYNC REJECTION

Slide 45

Slide 45

test(‘async rejection’, async () !=> { try { await Promise.resolve(0); expect(true).toBe(false); } catch (e) { expect(e).toBe(0); } }); ASYNC REJECTION

Slide 46

Slide 46

.RESOLVES & .REJECTS test(‘resolves/rejects’, async () !=> { await expect(Promise.resolve(7)).resolves.toBe(7); await expect(Promise.reject(0)).rejects.not.toBe(7); });

Slide 47

Slide 47

Slide 48

Slide 48

JEST can do will do whaaat?

Slide 49

Slide 49

test(‘mockName’, () !=> { const mockFn = jest.fn(); expect(mockFn).toHaveBeenCalled(); }); MOCK NAME

Slide 50

Slide 50

Slide 51

Slide 51

test(‘mockName’, () !=> { const mockFn = jest.fn(); MOCK NAME expect(mockFn).toHaveBeenCalled(); }); test(‘mockName’, () !=> { const mockFn = jest.fn().mockName(‘mockedFunction’); expect(mockFn).toHaveBeenCalled(); });

Slide 52

Slide 52

INFO GIF not supported in PDF

Slide 53

Slide 53

$ jest packages/moduleA $ jest packages/moduleA !—passWithNoTests

Slide 54

Slide 54

INFO GIF not supported in PDF by @kentcdodds

Slide 55

Slide 55

RELATED • • • • • • • github.com/robinpokorny/jest-can-do-whaaat Jest Snapshots and Beyond by Rogelio Guzman (recording) Writing snapshot plugins in the docs Effective Snapshot Testing by Kent C. Dodds Async testing in Jest (recording) Snapshot testing in Jest (recording) Async testing Koa with Jest INFO Full links in the description

Slide 56

Slide 56

Help others to go JEST can do whaaat? @robinpokorny