├── .github
└── FUNDING.yml
├── License.md
└── Readme.md
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: sapegin
2 | ko_fi: sapegin
3 | custom: https://www.buymeacoffee.com/sapegin
4 |
--------------------------------------------------------------------------------
/License.md:
--------------------------------------------------------------------------------
1 | CC0 1.0 Universal
2 |
3 | Statement of Purpose
4 |
5 | The laws of most jurisdictions throughout the world automatically confer
6 | exclusive Copyright and Related Rights (defined below) upon the creator and
7 | subsequent owner(s) (each and all, an "owner") of an original work of
8 | authorship and/or a database (each, a "Work").
9 |
10 | Certain owners wish to permanently relinquish those rights to a Work for the
11 | purpose of contributing to a commons of creative, cultural and scientific
12 | works ("Commons") that the public can reliably and without fear of later
13 | claims of infringement build upon, modify, incorporate in other works, reuse
14 | and redistribute as freely as possible in any form whatsoever and for any
15 | purposes, including without limitation commercial purposes. These owners may
16 | contribute to the Commons to promote the ideal of a free culture and the
17 | further production of creative, cultural and scientific works, or to gain
18 | reputation or greater distribution for their Work in part through the use and
19 | efforts of others.
20 |
21 | For these and/or other purposes and motivations, and without any expectation
22 | of additional consideration or compensation, the person associating CC0 with a
23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
25 | and publicly distribute the Work under its terms, with knowledge of his or her
26 | Copyright and Related Rights in the Work and the meaning and intended legal
27 | effect of CC0 on those rights.
28 |
29 | 1. Copyright and Related Rights. A Work made available under CC0 may be
30 | protected by copyright and related or neighboring rights ("Copyright and
31 | Related Rights"). Copyright and Related Rights include, but are not limited
32 | to, the following:
33 |
34 | i. the right to reproduce, adapt, distribute, perform, display, communicate,
35 | and translate a Work;
36 |
37 | ii. moral rights retained by the original author(s) and/or performer(s);
38 |
39 | iii. publicity and privacy rights pertaining to a person's image or likeness
40 | depicted in a Work;
41 |
42 | iv. rights protecting against unfair competition in regards to a Work,
43 | subject to the limitations in paragraph 4(a), below;
44 |
45 | v. rights protecting the extraction, dissemination, use and reuse of data in
46 | a Work;
47 |
48 | vi. database rights (such as those arising under Directive 96/9/EC of the
49 | European Parliament and of the Council of 11 March 1996 on the legal
50 | protection of databases, and under any national implementation thereof,
51 | including any amended or successor version of such directive); and
52 |
53 | vii. other similar, equivalent or corresponding rights throughout the world
54 | based on applicable law or treaty, and any national implementations thereof.
55 |
56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of,
57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
59 | and Related Rights and associated claims and causes of action, whether now
60 | known or unknown (including existing as well as future claims and causes of
61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum
62 | duration provided by applicable law or treaty (including future time
63 | extensions), (iii) in any current or future medium and for any number of
64 | copies, and (iv) for any purpose whatsoever, including without limitation
65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
66 | the Waiver for the benefit of each member of the public at large and to the
67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver
68 | shall not be subject to revocation, rescission, cancellation, termination, or
69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work
70 | by the public as contemplated by Affirmer's express Statement of Purpose.
71 |
72 | 3. Public License Fallback. Should any part of the Waiver for any reason be
73 | judged legally invalid or ineffective under applicable law, then the Waiver
74 | shall be preserved to the maximum extent permitted taking into account
75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
76 | is so judged Affirmer hereby grants to each affected person a royalty-free,
77 | non transferable, non sublicensable, non exclusive, irrevocable and
78 | unconditional license to exercise Affirmer's Copyright and Related Rights in
79 | the Work (i) in all territories worldwide, (ii) for the maximum duration
80 | provided by applicable law or treaty (including future time extensions), (iii)
81 | in any current or future medium and for any number of copies, and (iv) for any
82 | purpose whatsoever, including without limitation commercial, advertising or
83 | promotional purposes (the "License"). The License shall be deemed effective as
84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the
85 | License for any reason be judged legally invalid or ineffective under
86 | applicable law, such partial invalidity or ineffectiveness shall not
87 | invalidate the remainder of the License, and in such case Affirmer hereby
88 | affirms that he or she will not (i) exercise any of his or her remaining
89 | Copyright and Related Rights in the Work or (ii) assert any associated claims
90 | and causes of action with respect to the Work, in either case contrary to
91 | Affirmer's express Statement of Purpose.
92 |
93 | 4. Limitations and Disclaimers.
94 |
95 | a. No trademark or patent rights held by Affirmer are waived, abandoned,
96 | surrendered, licensed or otherwise affected by this document.
97 |
98 | b. Affirmer offers the Work as-is and makes no representations or warranties
99 | of any kind concerning the Work, express, implied, statutory or otherwise,
100 | including without limitation warranties of title, merchantability, fitness
101 | for a particular purpose, non infringement, or the absence of latent or
102 | other defects, accuracy, or the present or absence of errors, whether or not
103 | discoverable, all to the greatest extent permissible under applicable law.
104 |
105 | c. Affirmer disclaims responsibility for clearing rights of other persons
106 | that may apply to the Work or any use thereof, including without limitation
107 | any person's Copyright and Related Rights in the Work. Further, Affirmer
108 | disclaims responsibility for obtaining any necessary consents, permissions
109 | or other rights required for any use of the Work.
110 |
111 | d. Affirmer understands and acknowledges that Creative Commons is not a
112 | party to this document and has no duty or obligation with respect to this
113 | CC0 or use of the Work.
114 |
115 | For more information, please see
116 |
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |

12 |
13 |
Jest cheat sheet
14 |
15 |
16 |
17 | _Migrating to Vitest? [Check out Vitest cheat sheet](https://github.com/sapegin/vitest-cheat-sheet)._
18 |
19 | _I recommend [Mrm](https://github.com/sapegin/mrm/tree/master/packages/mrm-task-jest) and [jest-codemods](https://github.com/skovhus/jest-codemods) for single-command Jest installation and easy migration from other frameworks._
20 |
21 | [](https://sapegin.me/book/)
22 |
23 | ## Table of contents
24 |
25 |
26 |
27 | - [Test structure](#test-structure)
28 | - [Matchers](#matchers)
29 | - [Basic matchers](#basic-matchers)
30 | - [Truthiness](#truthiness)
31 | - [Numbers](#numbers)
32 | - [Strings](#strings)
33 | - [Arrays](#arrays)
34 | - [Objects](#objects)
35 | - [Exceptions](#exceptions)
36 | - [Snapshots](#snapshots)
37 | - [Mock functions](#mock-functions)
38 | - [Misc](#misc)
39 | - [Promise matchers (Jest 20+)](#promise-matchers-jest-20)
40 | - [Async tests](#async-tests)
41 | - [async/await](#asyncawait)
42 | - [Promises](#promises)
43 | - [done() callback](#done-callback)
44 | - [Mocks](#mocks)
45 | - [Mock functions](#mock-functions-1)
46 | - [Returning, resolving and rejecting values](#returning-resolving-and-rejecting-values)
47 | - [Mock modules using `jest.mock` method](#mock-modules-using-jestmock-method)
48 | - [Mock modules using a mock file](#mock-modules-using-a-mock-file)
49 | - [Mock object methods](#mock-object-methods)
50 | - [Mock getters and setters (Jest 22.1.0+)](#mock-getters-and-setters-jest-2210)
51 | - [Mock getters and setters](#mock-getters-and-setters)
52 | - [Clearing and restoring mocks](#clearing-and-restoring-mocks)
53 | - [Accessing the original module when using mocks](#accessing-the-original-module-when-using-mocks)
54 | - [Timer mocks](#timer-mocks)
55 | - [Data-driven tests (Jest 23+)](#data-driven-tests-jest-23)
56 | - [Skipping tests](#skipping-tests)
57 | - [Testing modules with side effects](#testing-modules-with-side-effects)
58 | - [Usage with Babel and TypeScript](#usage-with-babel-and-typescript)
59 | - [Resources](#resources)
60 | - [You may also like](#you-may-also-like)
61 | - [Contributing](#contributing)
62 | - [Sponsoring](#sponsoring)
63 | - [Author and license](#author-and-license)
64 |
65 |
66 |
67 | ## Test structure
68 |
69 | ```js
70 | describe('makePoniesPink', () => {
71 | beforeAll(() => {
72 | /* Runs before all tests */
73 | })
74 | afterAll(() => {
75 | /* Runs after all tests */
76 | })
77 | beforeEach(() => {
78 | /* Runs before each test */
79 | })
80 | afterEach(() => {
81 | /* Runs after each test */
82 | })
83 |
84 | test('make each pony pink', () => {
85 | const actual = fn(['Alice', 'Bob', 'Eve'])
86 | expect(actual).toEqual(['Pink Alice', 'Pink Bob', 'Pink Eve'])
87 | })
88 | })
89 | ```
90 |
91 | ## Matchers
92 |
93 | [Using matchers](http://jestjs.io/docs/en/using-matchers), [matchers docs](https://jestjs.io/docs/en/expect)
94 |
95 | ### Basic matchers
96 |
97 | ```js
98 | expect(42).toBe(42) // Strict equality (===)
99 | expect(42).not.toBe(3) // Strict equality (!==)
100 | expect([1, 2]).toEqual([1, 2]) // Deep equality
101 | expect({ a: undefined, b: 2 }).toEqual({ b: 2 }) // Deep equality
102 | expect({ a: undefined, b: 2 }).not.toStrictEqual({ b: 2 }) // Strict equality (Jest 23+)
103 | ```
104 |
105 | ### Truthiness
106 |
107 | ```js
108 | // Matches anything that an if statement treats as true (true, 1, 'hello', {}, [], 5.3)
109 | expect('foo').toBeTruthy()
110 | // Matches anything that an if statement treats as false (false, 0, '', null, undefined, NaN)
111 | expect('').toBeFalsy()
112 | // Matches only null
113 | expect(null).toBeNull()
114 | // Matches only undefined
115 | expect(undefined).toBeUndefined()
116 | // The opposite of toBeUndefined
117 | expect(7).toBeDefined()
118 | // Matches true or false
119 | expect(true).toEqual(expect.any(Boolean))
120 | ```
121 |
122 | ### Numbers
123 |
124 | ```js
125 | expect(2).toBeGreaterThan(1)
126 | expect(1).toBeGreaterThanOrEqual(1)
127 | expect(1).toBeLessThan(2)
128 | expect(1).toBeLessThanOrEqual(1)
129 | expect(0.2 + 0.1).toBeCloseTo(0.3, 5)
130 | expect(NaN).toEqual(expect.any(Number))
131 | ```
132 |
133 | ### Strings
134 |
135 | ```js
136 | expect('long string').toMatch('str')
137 | expect('string').toEqual(expect.any(String))
138 | expect('coffee').toMatch(/ff/)
139 | expect('pizza').not.toMatch('coffee')
140 | expect(['pizza', 'coffee']).toEqual([expect.stringContaining('zz'), expect.stringMatching(/ff/)])
141 | ```
142 |
143 | ### Arrays
144 |
145 | ```js
146 | expect([]).toEqual(expect.any(Array))
147 | expect(['Alice', 'Bob', 'Eve']).toHaveLength(3)
148 | expect(['Alice', 'Bob', 'Eve']).toContain('Alice')
149 | expect([{ a: 1 }, { a: 2 }]).toContainEqual({ a: 1 })
150 | expect(['Alice', 'Bob', 'Eve']).toEqual(expect.arrayContaining(['Alice', 'Bob']))
151 | ```
152 |
153 | ### Objects
154 |
155 | ```js
156 | expect({ a: 1 }).toHaveProperty('a')
157 | expect({ a: 1 }).toHaveProperty('a', 1)
158 | expect({ a: { b: 1 } }).toHaveProperty('a.b')
159 | expect({ a: 1, b: 2 }).toMatchObject({ a: 1 })
160 | expect({ a: 1, b: 2 }).toMatchObject({
161 | a: expect.any(Number),
162 | b: expect.any(Number),
163 | })
164 | expect([{ a: 1 }, { b: 2 }]).toEqual([
165 | expect.objectContaining({ a: expect.any(Number) }),
166 | expect.anything(),
167 | ])
168 | ```
169 |
170 | ### Exceptions
171 |
172 | ```js
173 | // const fn = () => { throw new Error('Out of cheese!') }
174 | expect(fn).toThrow()
175 | expect(fn).toThrow('Out of cheese')
176 | expect(fn).toThrowErrorMatchingSnapshot()
177 | ```
178 |
179 |
180 | Aliases
181 |
182 | - `toThrowError` → `toThrow`
183 |
184 |
185 | ### Snapshots
186 |
187 | ```js
188 | expect(node).toMatchSnapshot()
189 | // Jest 23+
190 | expect(user).toMatchSnapshot({
191 | date: expect.any(Date),
192 | })
193 | expect(user).toMatchInlineSnapshot()
194 | ```
195 |
196 | ### Mock functions
197 |
198 | ```js
199 | // const fn = jest.fn()
200 | // const fn = jest.fn().mockName('Unicorn') -- named mock, Jest 22+
201 | expect(fn).toBeCalled() // Function was called
202 | expect(fn).not.toBeCalled() // Function was *not* called
203 | expect(fn).toHaveBeenCalledTimes(1) // Function was called only once
204 | expect(fn).toBeCalledWith(arg1, arg2) // Any of calls was with these arguments
205 | expect(fn).toHaveBeenLastCalledWith(arg1, arg2) // Last call was with these arguments
206 | expect(fn).toHaveBeenNthCalledWith(callNumber, args) // Nth call was with these arguments (Jest 23+)
207 | expect(fn).toHaveReturnedTimes(2) // Function was returned without throwing an error (Jest 23+)
208 | expect(fn).toHaveReturnedWith(value) // Function returned a value (Jest 23+)
209 | expect(fn).toHaveLastReturnedWith(value) // Last function call returned a value (Jest 23+)
210 | expect(fn).toHaveNthReturnedWith(value) // Nth function call returned a value (Jest 23+)
211 | expect(fn.mock.calls).toEqual([
212 | ['first', 'call', 'args'],
213 | ['second', 'call', 'args'],
214 | ]) // Multiple calls
215 | expect(fn.mock.calls[0][0]).toBe(2) // fn.mock.calls[0][0] — the first argument of the first call
216 | ```
217 |
218 |
219 | Aliases
220 |
221 | - `toBeCalled` → `toHaveBeenCalled`
222 | - `toBeCalledWith` → `toHaveBeenCalledWith`
223 | - `lastCalledWith` → `toHaveBeenLastCalledWith`
224 | - `nthCalledWith` → `toHaveBeenNthCalledWith`
225 | - `toReturnTimes` → `toHaveReturnedTimes`
226 | - `toReturnWith` → `toHaveReturnedWith`
227 | - `lastReturnedWith` → `toHaveLastReturnedWith`
228 | - `nthReturnedWith` → `toHaveNthReturnedWith`
229 |
230 |
231 | ### Misc
232 |
233 | ```js
234 | expect(new A()).toBeInstanceOf(A)
235 | expect(() => {}).toEqual(expect.any(Function))
236 | expect('pizza').toEqual(expect.anything())
237 | ```
238 |
239 | ### Promise matchers (Jest 20+)
240 |
241 | ```js
242 | test('resolve to lemon', () => {
243 | expect.assertions(1)
244 | // Make sure to add a return statement
245 | return expect(Promise.resolve('lemon')).resolves.toBe('lemon')
246 | return expect(Promise.reject('octopus')).rejects.toBeDefined()
247 | return expect(Promise.reject(Error('pizza'))).rejects.toThrow()
248 | })
249 | ```
250 |
251 | Or with async/await:
252 |
253 | ```js
254 | test('resolve to lemon', async () => {
255 | expect.assertions(2)
256 | await expect(Promise.resolve('lemon')).resolves.toBe('lemon')
257 | await expect(Promise.resolve('lemon')).resolves.not.toBe('octopus')
258 | })
259 | ```
260 |
261 | [resolves docs](https://jestjs.io/docs/en/expect#resolves)
262 |
263 | ## Async tests
264 |
265 | See [more examples](https://jestjs.io/docs/en/tutorial-async) in Jest docs.
266 |
267 | It’s a good practice to specify a number of expected assertions in async tests, so the test will fail if your assertions weren’t called at all.
268 |
269 | ```js
270 | test('async test', () => {
271 | expect.assertions(3) // Exactly three assertions are called during a test
272 | // OR
273 | expect.hasAssertions() // At least one assertion is called during a test
274 |
275 | // Your async tests
276 | })
277 | ```
278 |
279 | You can also do this per file, outside any `describe` and `test`:
280 |
281 | ```js
282 | beforeEach(expect.hasAssertions)
283 | ```
284 |
285 | This will verify the presence of at least one assertion per test case. It also plays nice with more specific `expect.assertions(3)` declarations.
286 |
287 | In addition, you can enforce it globally, across all test files (instead of having to repeat per file) by adding the exact same line into one of the scripts referenced by the `setupFilesAfterEnv` configuration option. (For example, `setupTests.ts` and that is referenced via a `setupFilesAfterEnv: ['/setupTests.ts']` entry in `jest.config.ts`.)
288 |
289 | ### async/await
290 |
291 | ```js
292 | test('async test', async () => {
293 | expect.assertions(1)
294 | const result = await runAsyncOperation()
295 | expect(result).toBe(true)
296 | })
297 | ```
298 |
299 | ### Promises
300 |
301 | _Return_ a Promise from your test:
302 |
303 | ```js
304 | test('async test', () => {
305 | expect.assertions(1)
306 | return runAsyncOperation().then((result) => {
307 | expect(result).toBe(true)
308 | })
309 | })
310 | ```
311 |
312 | ### done() callback
313 |
314 | Wrap your assertions in try/catch block, otherwise Jest will ignore failures:
315 |
316 | ```js
317 | test('async test', (done) => {
318 | expect.assertions(1)
319 | runAsyncOperation()
320 | setTimeout(() => {
321 | try {
322 | const result = getAsyncOperationResult()
323 | expect(result).toBe(true)
324 | done()
325 | } catch (err) {
326 | done.fail(err)
327 | }
328 | })
329 | })
330 | ```
331 |
332 | ## Mocks
333 |
334 | ### Mock functions
335 |
336 | ```js
337 | test('call the callback', () => {
338 | const callback = jest.fn()
339 | fn(callback)
340 | expect(callback).toBeCalled()
341 | expect(callback.mock.calls[0][1].baz).toBe('pizza') // Second argument of the first call
342 | // Match the first and the last arguments but ignore the second argument
343 | expect(callback).toHaveBeenLastCalledWith('meal', expect.anything(), 'margarita')
344 | })
345 | ```
346 |
347 | You can also use snapshots:
348 |
349 | ```js
350 | test('call the callback', () => {
351 | const callback = jest.fn().mockName('Unicorn') // mockName is available in Jest 22+
352 | fn(callback)
353 | expect(callback).toMatchSnapshot()
354 | // ->
355 | // [MockFunction Unicorn] {
356 | // "calls": Array [
357 | // ...
358 | })
359 | ```
360 |
361 | And pass an implementation to `jest.fn` function:
362 |
363 | ```js
364 | const callback = jest.fn(() => true)
365 | ```
366 |
367 | [Mock functions docs](https://jestjs.io/docs/en/mock-function-api)
368 |
369 | ### Returning, resolving and rejecting values
370 |
371 | Your mocks can return values:
372 |
373 | ```js
374 | const callback = jest.fn().mockReturnValue(true)
375 | const callbackOnce = jest.fn().mockReturnValueOnce(true)
376 | ```
377 |
378 | Or resolve values:
379 |
380 | ```js
381 | const promise = jest.fn().mockResolvedValue(true)
382 | const promiseOnce = jest.fn().mockResolvedValueOnce(true)
383 | ```
384 |
385 | They can even reject values:
386 |
387 | ```js
388 | const failedPromise = jest.fn().mockRejectedValue('Error')
389 | const failedPromiseOnce = jest.fn().mockRejectedValueOnce('Error')
390 | ```
391 |
392 | You can even combine these:
393 |
394 | ```js
395 | const callback = jest.fn().mockReturnValueOnce(false).mockReturnValue(true)
396 |
397 | // ->
398 | // call 1: false
399 | // call 2+: true
400 | ```
401 |
402 | ### Mock modules using `jest.mock` method
403 |
404 | ```js
405 | jest.mock('lodash/memoize', () => (a) => a) // The original lodash/memoize should exist
406 | jest.mock('lodash/memoize', () => (a) => a, { virtual: true }) // The original lodash/memoize isn’t required
407 | ```
408 |
409 | [jest.mock docs](https://jestjs.io/docs/en/jest-object#jestmockmodulename-factory-options)
410 |
411 | > [!NOTE]
412 | > When using `babel-jest`, calls to `jest.mock` will automatically be hoisted to the top of the code block. Use `jest.doMock` if you want to explicitly avoid this behavior.
413 |
414 | ### Mock modules using a mock file
415 |
416 | 1. Create a file like `__mocks__/lodash/memoize.js`:
417 |
418 | ```js
419 | module.exports = (a) => a
420 | ```
421 |
422 | 2. Add to your test:
423 |
424 | ```js
425 | jest.mock('lodash/memoize')
426 | ```
427 |
428 | > [!NOTE]
429 | > When using `babel-jest`, calls to `jest.mock` will automatically be hoisted to the top of the code block. Use `jest.doMock` if you want to explicitly avoid this behavior.
430 |
431 | [Manual mocks docs](https://jestjs.io/docs/en/manual-mocks)
432 |
433 | ### Mock object methods
434 |
435 | ```js
436 | const spy = jest.spyOn(console, 'log').mockImplementation(() => {})
437 | expect(console.log.mock.calls).toEqual([['dope'], ['nope']])
438 | spy.mockRestore()
439 | ```
440 |
441 | ```js
442 | const spy = jest.spyOn(ajax, 'request').mockImplementation(() => Promise.resolve({ success: true }))
443 | expect(spy).toHaveBeenCalled()
444 | spy.mockRestore()
445 | ```
446 |
447 | ### Mock getters and setters (Jest 22.1.0+)
448 |
449 | ```js
450 | const location = {}
451 | const getTitle = jest.spyOn(location, 'title', 'get').mockImplementation(() => 'pizza')
452 | const setTitle = jest.spyOn(location, 'title', 'set').mockImplementation(() => {})
453 | ```
454 |
455 | ### Mock getters and setters
456 |
457 | ```js
458 | const getTitle = jest.fn(() => 'pizza')
459 | const setTitle = jest.fn()
460 | const location = {}
461 | Object.defineProperty(location, 'title', {
462 | get: getTitle,
463 | set: setTitle,
464 | })
465 | ```
466 |
467 | ### Clearing and restoring mocks
468 |
469 | For one mock:
470 |
471 | ```js
472 | fn.mockClear() // Clears mock usage date (fn.mock.calls, fn.mock.instances)
473 | fn.mockReset() // Clears and removes any mocked return values or implementations
474 | fn.mockRestore() // Resets and restores the initial implementation
475 | ```
476 |
477 | > [!NOTE]
478 | > The `mockRestore` works only with mocks created by `jest.spyOn`.
479 |
480 | For all mocks:
481 |
482 | ```js
483 | jest.clearAllMocks()
484 | jest.resetAllMocks()
485 | jest.restoreAllMocks()
486 | ```
487 |
488 | ### Accessing the original module when using mocks
489 |
490 | ```js
491 | jest.mock('fs')
492 | const fs = require('fs') // Mocked module
493 | const fs = require.requireActual('fs') // Original module
494 | ```
495 |
496 | ### Timer mocks
497 |
498 | Write synchronous test for code that uses native timer functions (`setTimeout`, `setInterval`, `clearTimeout`, `clearInterval`).
499 |
500 | ```js
501 | // Enable fake timers
502 | jest.useFakeTimers()
503 |
504 | test('kill the time', () => {
505 | const callback = jest.fn()
506 |
507 | // Run some code that uses setTimeout or setInterval
508 | const actual = someFunctionThatUseTimers(callback)
509 |
510 | // Fast-forward until all timers have been executed
511 | jest.runAllTimers()
512 |
513 | // Check the results synchronously
514 | expect(callback).toHaveBeenCalledTimes(1)
515 | })
516 | ```
517 |
518 | Or adjust timers by time with [advanceTimersByTime()](https://jestjs.io/docs/en/timer-mocks#advance-timers-by-time):
519 |
520 | ```js
521 | // Enable fake timers
522 | jest.useFakeTimers()
523 |
524 | test('kill the time', () => {
525 | const callback = jest.fn()
526 |
527 | // Run some code that uses setTimeout or setInterval
528 | const actual = someFunctionThatUseTimers(callback)
529 |
530 | // Fast-forward for 250 ms
531 | jest.advanceTimersByTime(250)
532 |
533 | // Check the results synchronously
534 | expect(callback).toHaveBeenCalledTimes(1)
535 | })
536 | ```
537 |
538 | Use [jest.runOnlyPendingTimers()](https://jestjs.io/docs/en/timer-mocks#run-pending-timers) for special cases.
539 |
540 | > [!NOTE]
541 | > You should call `jest.useFakeTimers()` in your test case to use other fake timer methods.
542 |
543 | ## Data-driven tests (Jest 23+)
544 |
545 | Run the same test with different data:
546 |
547 | ```js
548 | test.each([
549 | [1, 1, 2],
550 | [1, 2, 3],
551 | [2, 1, 3],
552 | ])('.add(%s, %s)', (a, b, expected) => {
553 | expect(a + b).toBe(expected)
554 | })
555 | ```
556 |
557 | Or the same using template literals:
558 |
559 | ```js
560 | test.each`
561 | a | b | expected
562 | ${1} | ${1} | ${2}
563 | ${1} | ${2} | ${3}
564 | ${2} | ${1} | ${3}
565 | `('returns $expected when $a is added $b', ({ a, b, expected }) => {
566 | expect(a + b).toBe(expected)
567 | })
568 | ```
569 |
570 | Or on `describe` level:
571 |
572 | ```js
573 | describe.each([['mobile'], ['tablet'], ['desktop']])('checkout flow on %s', (viewport) => {
574 | test('displays success page', () => {
575 | //
576 | })
577 | })
578 | ```
579 |
580 | [describe.each() docs](https://jestjs.io/docs/en/api#describeeachtablename-fn-timeout), [test.each() docs](https://jestjs.io/docs/en/api#testeachtablename-fn-timeout),
581 |
582 | ## Skipping tests
583 |
584 | Don’t run these tests:
585 |
586 | ```js
587 | describe.skip('makePoniesPink'...
588 | tests.skip('make each pony pink'...
589 | ```
590 |
591 | Run only these tests:
592 |
593 | ```js
594 | describe.only('makePoniesPink'...
595 | tests.only('make each pony pink'...
596 | ```
597 |
598 | ## Testing modules with side effects
599 |
600 | Node.js and Jest will cache modules you `require`. To test modules with side effects you’ll need to reset the module registry between tests:
601 |
602 | ```js
603 | const modulePath = '../module-to-test'
604 |
605 | afterEach(() => {
606 | jest.resetModules()
607 | })
608 |
609 | test('first test', () => {
610 | // Prepare conditions for the first test
611 | const result = require(modulePath)
612 | expect(result).toMatchSnapshot()
613 | })
614 |
615 | test('second text', () => {
616 | // Prepare conditions for the second test
617 | const fn = () => require(modulePath)
618 | expect(fn).toThrow()
619 | })
620 | ```
621 |
622 | ## Usage with Babel and TypeScript
623 |
624 | Add [babel-jest](https://github.com/facebook/jest/tree/master/packages/babel-jest) or [ts-jest](https://github.com/kulshekhar/ts-jest). Check their docs for installation instructions.
625 |
626 | ## Resources
627 |
628 | - [Jest site](https://facebook.github.io/jest/)
629 | - [Modern React testing, part 1: best practices](https://blog.sapegin.me/all/react-testing-1-best-practices/) by Artem Sapegin
630 | - [Modern React testing, part 2: Jest and Enzyme](https://blog.sapegin.me/all/react-testing-2-jest-and-enzyme/) by Artem Sapegin
631 | - [Modern React testing, part 3: Jest and React Testing Library](https://blog.sapegin.me/all/react-testing-3-jest-and-react-testing-library/) by Artem Sapegin
632 | - [Modern React testing, part 4: Cypress and Cypress Testing Library](https://sapegin.me/blog/react-testing-4-cypress/) by Artem Sapegin
633 | - [Modern React testing, part 5: Playwright](https://sapegin.me/blog/react-testing-5-playwright/) by Artem Sapegin
634 | - [React Testing Examples](https://react-testing-examples.com/)
635 | - [Testing React Applications](https://youtu.be/59Ndb3YkLKA) by Max Stoiber
636 | - [Effective Snapshot Testing](https://blog.kentcdodds.com/effective-snapshot-testing-e0d1a2c28eca) by Kent C. Dodds
637 | - [Migrating to Jest](https://medium.com/@kentcdodds/migrating-to-jest-881f75366e7e#.pc4s5ut6z) by Kent C. Dodds
638 | - [Migrating AVA to Jest](http://browniefed.com/blog/migrating-ava-to-jest/) by Jason Brown
639 | - [How to Test React and MobX with Jest](https://semaphoreci.com/community/tutorials/how-to-test-react-and-mobx-with-jest) by Will Stern
640 | - [Testing React Intl components with Jest and Enzyme](https://medium.com/@sapegin/testing-react-intl-components-with-jest-and-enzyme-f9d43d9c923e) by Artem Sapegin
641 | - [Testing with Jest: 15 Awesome Tips and Tricks](https://medium.com/@stipsan/testing-with-jest-15-awesome-tips-and-tricks-42150ec4c262) by Stian Didriksen
642 | - Taking Advantage of Jest Matchers by Ben McCormick: [Part 1](https://benmccormick.org/2017/08/15/jest-matchers-1/), [Part 2](https://benmccormick.org/2017/09/04/jest-matchers-2/)
643 |
644 | ---
645 |
646 | ## You may also like
647 |
648 | - [Opinionated list of React components](https://github.com/sapegin/react-components)
649 |
650 | ## Contributing
651 |
652 | Improvements are welcome! Open an issue or send a pull request.
653 |
654 | ## Sponsoring
655 |
656 | This software has been developed with lots of coffee, buy me one more cup to keep it going.
657 |
658 |
659 |
660 | ## Author and license
661 |
662 | [Artem Sapegin](https://sapegin.me/), a frontend engineer at [Stage+](https://www.stage-plus.com) and the creator of [React Styleguidist](https://react-styleguidist.js.org/). I also write about frontend at [my blog](https://sapegin.me/blog/).
663 |
664 | CC0 1.0 Universal license, see the included [License.md](/License.md) file.
665 |
--------------------------------------------------------------------------------