UNPKG

13.5 kBMarkdownView Raw
1<div align="center">
2 <h1>jest-each</h1>
3 Jest Parameterised Testing
4</div>
5
6<hr />
7
8[![version](https://img.shields.io/npm/v/jest-each.svg?style=flat-square)](https://www.npmjs.com/package/jest-each) [![downloads](https://img.shields.io/npm/dm/jest-each.svg?style=flat-square)](http://npm-stat.com/charts.html?package=jest-each&from=2017-03-21) [![MIT License](https://img.shields.io/npm/l/jest-each.svg?style=flat-square)](https://github.com/facebook/jest/blob/master/LICENSE)
9
10A parameterised testing library for [Jest](https://jestjs.io/) inspired by [mocha-each](https://github.com/ryym/mocha-each).
11
12jest-each allows you to provide multiple arguments to your `test`/`describe` which results in the test/suite being run once per row of parameters.
13
14## Features
15
16- `.test` to runs multiple tests with parameterised data
17 - Also under the alias: `.it`
18- `.test.only` to only run the parameterised tests
19 - Also under the aliases: `.it.only` or `.fit`
20- `.test.skip` to skip the parameterised tests
21 - Also under the aliases: `.it.skip` or `.xit` or `.xtest`
22- `.test.concurrent`
23 - Also under the alias: `.it.concurrent`
24- `.test.concurrent.only`
25 - Also under the alias: `.it.concurrent.only`
26- `.test.concurrent.skip`
27 - Also under the alias: `.it.concurrent.skip`
28- `.describe` to runs test suites with parameterised data
29- `.describe.only` to only run the parameterised suite of tests
30 - Also under the aliases: `.fdescribe`
31- `.describe.skip` to skip the parameterised suite of tests
32 - Also under the aliases: `.xdescribe`
33- Asynchronous tests with `done`
34- Unique test titles with [`printf` formatting](https://nodejs.org/api/util.html#util_util_format_format_args):
35 - `%p` - [pretty-format](https://www.npmjs.com/package/pretty-format).
36 - `%s`- String.
37 - `%d`- Number.
38 - `%i` - Integer.
39 - `%f` - Floating point value.
40 - `%j` - JSON.
41 - `%o` - Object.
42 - `%#` - Index of the test case.
43 - `%%` - single percent sign ('%'). This does not consume an argument.
44- Unique test titles by injecting properties of test case object
45- 🖖 Spock like data tables with [Tagged Template Literals](#tagged-template-literal-of-rows)
46
47---
48
49- [Demo](#demo)
50- [Installation](#installation)
51- [Importing](#importing)
52- APIs
53 - [Array of Rows](#array-of-rows)
54 - [Usage](#usage)
55 - [Tagged Template Literal of rows](#tagged-template-literal-of-rows)
56 - [Usage](#usage-1)
57
58## Demo
59
60#### Tests without jest-each
61
62![Current jest tests](assets/default-demo.gif)
63
64#### Tests can be re-written with jest-each to:
65
66**`.test`**
67
68![Current jest tests](assets/test-demo.gif)
69
70**`.test` with Tagged Template Literals**
71
72![Current jest tests](assets/tagged-template-literal.gif)
73
74**`.describe`**
75
76![Current jest tests](assets/describe-demo.gif)
77
78## Installation
79
80`npm i --save-dev jest-each`
81
82`yarn add -D jest-each`
83
84## Importing
85
86jest-each is a default export so it can be imported with whatever name you like.
87
88```js
89// es6
90import each from 'jest-each';
91```
92
93```js
94// es5
95const each = require('jest-each').default;
96```
97
98## Array of rows
99
100### API
101
102#### `each([parameters]).test(name, testFn)`
103
104##### `each`:
105
106- parameters: `Array` of Arrays with the arguments that are passed into the `testFn` for each row
107 - _Note_ If you pass in a 1D array of primitives, internally it will be mapped to a table i.e. `[1, 2, 3] -> [[1], [2], [3]]`
108
109##### `.test`:
110
111- name: `String` the title of the `test`.
112 - Generate unique test titles by positionally injecting parameters with [`printf` formatting](https://nodejs.org/api/util.html#util_util_format_format_args):
113 - `%p` - [pretty-format](https://www.npmjs.com/package/pretty-format).
114 - `%s`- String.
115 - `%d`- Number.
116 - `%i` - Integer.
117 - `%f` - Floating point value.
118 - `%j` - JSON.
119 - `%o` - Object.
120 - `%#` - Index of the test case.
121 - `%%` - single percent sign ('%'). This does not consume an argument.
122 - Or generate unique test titles by injecting properties of test case object with `$variable`
123 - To inject nested object values use you can supply a keyPath i.e. `$variable.path.to.value`
124 - You can use `$#` to inject the index of the test case
125 - You cannot use `$variable` with the `printf` formatting except for `%%`
126- testFn: `Function` the test logic, this is the function that will receive the parameters of each row as function arguments
127
128#### `each([parameters]).describe(name, suiteFn)`
129
130##### `each`:
131
132- parameters: `Array` of Arrays with the arguments that are passed into the `suiteFn` for each row
133 - _Note_ If you pass in a 1D array of primitives, internally it will be mapped to a table i.e. `[1, 2, 3] -> [[1], [2], [3]]`
134
135##### `.describe`:
136
137- name: `String` the title of the `describe`
138 - Generate unique test titles by positionally injecting parameters with [`printf` formatting](https://nodejs.org/api/util.html#util_util_format_format_args):
139 - `%p` - [pretty-format](https://www.npmjs.com/package/pretty-format).
140 - `%s`- String.
141 - `%d`- Number.
142 - `%i` - Integer.
143 - `%f` - Floating point value.
144 - `%j` - JSON.
145 - `%o` - Object.
146 - `%#` - Index of the test case.
147 - `%%` - single percent sign ('%'). This does not consume an argument.
148 - Or generate unique test titles by injecting properties of test case object with `$variable`
149 - To inject nested object values use you can supply a keyPath i.e. `$variable.path.to.value`
150 - You can use `$#` to inject the index of the test case
151 - You cannot use `$variable` with the `printf` formatting except for `%%`
152- suiteFn: `Function` the suite of `test`/`it`s to be ran, this is the function that will receive the parameters in each row as function arguments
153
154### Usage
155
156#### `.test(name, fn)`
157
158Alias: `.it(name, fn)`
159
160```js
161each([
162 [1, 1, 2],
163 [1, 2, 3],
164 [2, 1, 3],
165]).test('returns the result of adding %d to %d', (a, b, expected) => {
166 expect(a + b).toBe(expected);
167});
168```
169
170```js
171each([
172 {a: 1, b: 1, expected: 2},
173 {a: 1, b: 2, expected: 3},
174 {a: 2, b: 1, expected: 3},
175]).test('returns the result of adding $a to $b', ({a, b, expected}) => {
176 expect(a + b).toBe(expected);
177});
178```
179
180#### `.test.only(name, fn)`
181
182Aliases: `.it.only(name, fn)` or `.fit(name, fn)`
183
184```js
185each([
186 [1, 1, 2],
187 [1, 2, 3],
188 [2, 1, 3],
189]).test.only('returns the result of adding %d to %d', (a, b, expected) => {
190 expect(a + b).toBe(expected);
191});
192```
193
194#### `.test.skip(name, fn)`
195
196Aliases: `.it.skip(name, fn)` or `.xit(name, fn)` or `.xtest(name, fn)`
197
198```js
199each([
200 [1, 1, 2],
201 [1, 2, 3],
202 [2, 1, 3],
203]).test.skip('returns the result of adding %d to %d', (a, b, expected) => {
204 expect(a + b).toBe(expected);
205});
206```
207
208#### `.test.concurrent(name, fn)`
209
210Aliases: `.it.concurrent(name, fn)`
211
212```js
213each([
214 [1, 1, 2],
215 [1, 2, 3],
216 [2, 1, 3],
217]).test.concurrent(
218 'returns the result of adding %d to %d',
219 (a, b, expected) => {
220 expect(a + b).toBe(expected);
221 },
222);
223```
224
225#### `.test.concurrent.only(name, fn)`
226
227Aliases: `.it.concurrent.only(name, fn)`
228
229```js
230each([
231 [1, 1, 2],
232 [1, 2, 3],
233 [2, 1, 3],
234]).test.concurrent.only(
235 'returns the result of adding %d to %d',
236 (a, b, expected) => {
237 expect(a + b).toBe(expected);
238 },
239);
240```
241
242#### `.test.concurrent.skip(name, fn)`
243
244Aliases: `.it.concurrent.skip(name, fn)`
245
246```js
247each([
248 [1, 1, 2],
249 [1, 2, 3],
250 [2, 1, 3],
251]).test.concurrent.skip(
252 'returns the result of adding %d to %d',
253 (a, b, expected) => {
254 expect(a + b).toBe(expected);
255 },
256);
257```
258
259#### Asynchronous `.test(name, fn(done))`
260
261Alias: `.it(name, fn(done))`
262
263```js
264each([['hello'], ['mr'], ['spy']]).test(
265 'gives 007 secret message: %s',
266 (str, done) => {
267 const asynchronousSpy = message => {
268 expect(message).toBe(str);
269 done();
270 };
271 callSomeAsynchronousFunction(asynchronousSpy)(str);
272 },
273);
274```
275
276#### `.describe(name, fn)`
277
278```js
279each([
280 [1, 1, 2],
281 [1, 2, 3],
282 [2, 1, 3],
283]).describe('.add(%d, %d)', (a, b, expected) => {
284 test(`returns ${expected}`, () => {
285 expect(a + b).toBe(expected);
286 });
287
288 test('does not mutate first arg', () => {
289 a + b;
290 expect(a).toBe(a);
291 });
292
293 test('does not mutate second arg', () => {
294 a + b;
295 expect(b).toBe(b);
296 });
297});
298```
299
300```js
301each([
302 {a: 1, b: 1, expected: 2},
303 {a: 1, b: 2, expected: 3},
304 {a: 2, b: 1, expected: 3},
305]).describe('.add($a, $b)', ({a, b, expected}) => {
306 test(`returns ${expected}`, () => {
307 expect(a + b).toBe(expected);
308 });
309
310 test('does not mutate first arg', () => {
311 a + b;
312 expect(a).toBe(a);
313 });
314
315 test('does not mutate second arg', () => {
316 a + b;
317 expect(b).toBe(b);
318 });
319});
320```
321
322#### `.describe.only(name, fn)`
323
324Aliases: `.fdescribe(name, fn)`
325
326```js
327each([
328 [1, 1, 2],
329 [1, 2, 3],
330 [2, 1, 3],
331]).describe.only('.add(%d, %d)', (a, b, expected) => {
332 test(`returns ${expected}`, () => {
333 expect(a + b).toBe(expected);
334 });
335});
336```
337
338#### `.describe.skip(name, fn)`
339
340Aliases: `.xdescribe(name, fn)`
341
342```js
343each([
344 [1, 1, 2],
345 [1, 2, 3],
346 [2, 1, 3],
347]).describe.skip('.add(%d, %d)', (a, b, expected) => {
348 test(`returns ${expected}`, () => {
349 expect(a + b).toBe(expected);
350 });
351});
352```
353
354---
355
356## Tagged Template Literal of rows
357
358### API
359
360#### `each[tagged template].test(name, suiteFn)`
361
362```js
363each`
364 a | b | expected
365 ${1} | ${1} | ${2}
366 ${1} | ${2} | ${3}
367 ${2} | ${1} | ${3}
368`.test('returns $expected when adding $a to $b', ({a, b, expected}) => {
369 expect(a + b).toBe(expected);
370});
371```
372
373##### `each` takes a tagged template string with:
374
375- First row of variable name column headings separated with `|`
376- One or more subsequent rows of data supplied as template literal expressions using `${value}` syntax.
377
378##### `.test`:
379
380- name: `String` the title of the `test`, use `$variable` in the name string to inject test values into the test title from the tagged template expressions
381 - To inject nested object values use you can supply a keyPath i.e. `$variable.path.to.value`
382 - You can use `$#` to inject the index of the table row.
383- testFn: `Function` the test logic, this is the function that will receive the parameters of each row as function arguments
384
385#### `each[tagged template].describe(name, suiteFn)`
386
387```js
388each`
389 a | b | expected
390 ${1} | ${1} | ${2}
391 ${1} | ${2} | ${3}
392 ${2} | ${1} | ${3}
393`.describe('$a + $b', ({a, b, expected}) => {
394 test(`returns ${expected}`, () => {
395 expect(a + b).toBe(expected);
396 });
397
398 test('does not mutate first arg', () => {
399 a + b;
400 expect(a).toBe(a);
401 });
402
403 test('does not mutate second arg', () => {
404 a + b;
405 expect(b).toBe(b);
406 });
407});
408```
409
410##### `each` takes a tagged template string with:
411
412- First row of variable name column headings separated with `|`
413- One or more subsequent rows of data supplied as template literal expressions using `${value}` syntax.
414
415##### `.describe`:
416
417- name: `String` the title of the `test`, use `$variable` in the name string to inject test values into the test title from the tagged template expressions
418 - To inject nested object values use you can supply a keyPath i.e. `$variable.path.to.value`
419- suiteFn: `Function` the suite of `test`/`it`s to be ran, this is the function that will receive the parameters in each row as function arguments
420
421### Usage
422
423#### `.test(name, fn)`
424
425Alias: `.it(name, fn)`
426
427```js
428each`
429 a | b | expected
430 ${1} | ${1} | ${2}
431 ${1} | ${2} | ${3}
432 ${2} | ${1} | ${3}
433`.test('returns $expected when adding $a to $b', ({a, b, expected}) => {
434 expect(a + b).toBe(expected);
435});
436```
437
438#### `.test.only(name, fn)`
439
440Aliases: `.it.only(name, fn)` or `.fit(name, fn)`
441
442```js
443each`
444 a | b | expected
445 ${1} | ${1} | ${2}
446 ${1} | ${2} | ${3}
447 ${2} | ${1} | ${3}
448`.test.only('returns $expected when adding $a to $b', ({a, b, expected}) => {
449 expect(a + b).toBe(expected);
450});
451```
452
453#### `.test.skip(name, fn)`
454
455Aliases: `.it.skip(name, fn)` or `.xit(name, fn)` or `.xtest(name, fn)`
456
457```js
458each`
459 a | b | expected
460 ${1} | ${1} | ${2}
461 ${1} | ${2} | ${3}
462 ${2} | ${1} | ${3}
463`.test.skip('returns $expected when adding $a to $b', ({a, b, expected}) => {
464 expect(a + b).toBe(expected);
465});
466```
467
468#### Asynchronous `.test(name, fn(done))`
469
470Alias: `.it(name, fn(done))`
471
472```js
473each`
474 str
475 ${'hello'}
476 ${'mr'}
477 ${'spy'}
478`.test('gives 007 secret message: $str', ({str}, done) => {
479 const asynchronousSpy = message => {
480 expect(message).toBe(str);
481 done();
482 };
483 callSomeAsynchronousFunction(asynchronousSpy)(str);
484});
485```
486
487#### `.describe(name, fn)`
488
489```js
490each`
491 a | b | expected
492 ${1} | ${1} | ${2}
493 ${1} | ${2} | ${3}
494 ${2} | ${1} | ${3}
495`.describe('$a + $b', ({a, b, expected}) => {
496 test(`returns ${expected}`, () => {
497 expect(a + b).toBe(expected);
498 });
499
500 test('does not mutate first arg', () => {
501 a + b;
502 expect(a).toBe(a);
503 });
504
505 test('does not mutate second arg', () => {
506 a + b;
507 expect(b).toBe(b);
508 });
509});
510```
511
512#### `.describe.only(name, fn)`
513
514Aliases: `.fdescribe(name, fn)`
515
516```js
517each`
518 a | b | expected
519 ${1} | ${1} | ${2}
520 ${1} | ${2} | ${3}
521 ${2} | ${1} | ${3}
522`.describe.only('$a + $b', ({a, b, expected}) => {
523 test(`returns ${expected}`, () => {
524 expect(a + b).toBe(expected);
525 });
526});
527```
528
529#### `.describe.skip(name, fn)`
530
531Aliases: `.xdescribe(name, fn)`
532
533```js
534each`
535 a | b | expected
536 ${1} | ${1} | ${2}
537 ${1} | ${2} | ${3}
538 ${2} | ${1} | ${3}
539`.describe.skip('$a + $b', ({a, b, expected}) => {
540 test(`returns ${expected}`, () => {
541 expect(a + b).toBe(expected);
542 });
543});
544```
545
546## License
547
548MIT