UNPKG

11.1 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- `.describe` to runs test suites with parameterised data
23- `.describe.only` to only run the parameterised suite of tests
24 - Also under the aliases: `.fdescribe`
25- `.describe.skip` to skip the parameterised suite of tests
26 - Also under the aliases: `.xdescribe`
27- Asynchronous tests with `done`
28- Unique test titles with [`printf` formatting](https://nodejs.org/api/util.html#util_util_format_format_args):
29 - `%p` - [pretty-format](https://www.npmjs.com/package/pretty-format).
30 - `%s`- String.
31 - `%d`- Number.
32 - `%i` - Integer.
33 - `%f` - Floating point value.
34 - `%j` - JSON.
35 - `%o` - Object.
36 - `%#` - Index of the test case.
37 - `%%` - single percent sign ('%'). This does not consume an argument.
38- 🖖 Spock like data tables with [Tagged Template Literals](#tagged-template-literal-of-rows)
39
40---
41
42- [Demo](#demo)
43- [Installation](#installation)
44- [Importing](#importing)
45- APIs
46 - [Array of Rows](#array-of-rows)
47 - [Usage](#usage)
48 - [Tagged Template Literal of rows](#tagged-template-literal-of-rows)
49 - [Usage](#usage-1)
50
51## Demo
52
53#### Tests without jest-each
54
55![Current jest tests](assets/default-demo.gif)
56
57#### Tests can be re-written with jest-each to:
58
59**`.test`**
60
61![Current jest tests](assets/test-demo.gif)
62
63**`.test` with Tagged Template Literals**
64
65![Current jest tests](assets/tagged-template-literal.gif)
66
67**`.describe`**
68
69![Current jest tests](assets/describe-demo.gif)
70
71## Installation
72
73`npm i --save-dev jest-each`
74
75`yarn add -D jest-each`
76
77## Importing
78
79jest-each is a default export so it can be imported with whatever name you like.
80
81```js
82// es6
83import each from 'jest-each';
84```
85
86```js
87// es5
88const each = require('jest-each');
89```
90
91## Array of rows
92
93### API
94
95#### `each([parameters]).test(name, testFn)`
96
97##### `each`:
98
99- parameters: `Array` of Arrays with the arguments that are passed into the `testFn` for each row
100 - _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]]`
101
102##### `.test`:
103
104- name: `String` the title of the `test`.
105 - Generate unique test titles by positionally injecting parameters with [`printf` formatting](https://nodejs.org/api/util.html#util_util_format_format_args):
106 - `%p` - [pretty-format](https://www.npmjs.com/package/pretty-format).
107 - `%s`- String.
108 - `%d`- Number.
109 - `%i` - Integer.
110 - `%f` - Floating point value.
111 - `%j` - JSON.
112 - `%o` - Object.
113 - `%#` - Index of the test case.
114 - `%%` - single percent sign ('%'). This does not consume an argument.
115- testFn: `Function` the test logic, this is the function that will receive the parameters of each row as function arguments
116
117#### `each([parameters]).describe(name, suiteFn)`
118
119##### `each`:
120
121- parameters: `Array` of Arrays with the arguments that are passed into the `suiteFn` for each row
122 - _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]]`
123
124##### `.describe`:
125
126- name: `String` the title of the `describe`
127 - Generate unique test titles by positionally injecting parameters with [`printf` formatting](https://nodejs.org/api/util.html#util_util_format_format_args):
128 - `%p` - [pretty-format](https://www.npmjs.com/package/pretty-format).
129 - `%s`- String.
130 - `%d`- Number.
131 - `%i` - Integer.
132 - `%f` - Floating point value.
133 - `%j` - JSON.
134 - `%o` - Object.
135 - `%#` - Index of the test case.
136 - `%%` - single percent sign ('%'). This does not consume an argument.
137- 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
138
139### Usage
140
141#### `.test(name, fn)`
142
143Alias: `.it(name, fn)`
144
145```js
146each([[1, 1, 2], [1, 2, 3], [2, 1, 3]]).test(
147 'returns the result of adding %d to %d',
148 (a, b, expected) => {
149 expect(a + b).toBe(expected);
150 },
151);
152```
153
154#### `.test.only(name, fn)`
155
156Aliases: `.it.only(name, fn)` or `.fit(name, fn)`
157
158```js
159each([[1, 1, 2], [1, 2, 3], [2, 1, 3]]).test.only(
160 'returns the result of adding %d to %d',
161 (a, b, expected) => {
162 expect(a + b).toBe(expected);
163 },
164);
165```
166
167#### `.test.skip(name, fn)`
168
169Aliases: `.it.skip(name, fn)` or `.xit(name, fn)` or `.xtest(name, fn)`
170
171```js
172each([[1, 1, 2][(1, 2, 3)], [2, 1, 3]]).test.skip(
173 'returns the result of adding %d to %d',
174 (a, b, expected) => {
175 expect(a + b).toBe(expected);
176 },
177);
178```
179
180#### Asynchronous `.test(name, fn(done))`
181
182Alias: `.it(name, fn(done))`
183
184```js
185each([['hello'], ['mr'], ['spy']]).test(
186 'gives 007 secret message: %s',
187 (str, done) => {
188 const asynchronousSpy = message => {
189 expect(message).toBe(str);
190 done();
191 };
192 callSomeAsynchronousFunction(asynchronousSpy)(str);
193 },
194);
195```
196
197#### `.describe(name, fn)`
198
199```js
200each([[1, 1, 2], [1, 2, 3], [2, 1, 3]]).describe(
201 '.add(%d, %d)',
202 (a, b, expected) => {
203 test(`returns ${expected}`, () => {
204 expect(a + b).toBe(expected);
205 });
206
207 test('does not mutate first arg', () => {
208 a + b;
209 expect(a).toBe(a);
210 });
211
212 test('does not mutate second arg', () => {
213 a + b;
214 expect(b).toBe(b);
215 });
216 },
217);
218```
219
220#### `.describe.only(name, fn)`
221
222Aliases: `.fdescribe(name, fn)`
223
224```js
225each([[1, 1, 2], [1, 2, 3], [2, 1, 3]]).describe.only(
226 '.add(%d, %d)',
227 (a, b, expected) => {
228 test(`returns ${expected}`, () => {
229 expect(a + b).toBe(expected);
230 });
231 },
232);
233```
234
235#### `.describe.skip(name, fn)`
236
237Aliases: `.xdescribe(name, fn)`
238
239```js
240each([[1, 1, 2], [1, 2, 3], [2, 1, 3]]).describe.skip(
241 '.add(%d, %d)',
242 (a, b, expected) => {
243 test(`returns ${expected}`, () => {
244 expect(a + b).toBe(expected);
245 });
246 },
247);
248```
249
250---
251
252## Tagged Template Literal of rows
253
254### API
255
256#### `each[tagged template].test(name, suiteFn)`
257
258```js
259each`
260 a | b | expected
261 ${1} | ${1} | ${2}
262 ${1} | ${2} | ${3}
263 ${2} | ${1} | ${3}
264`.test('returns $expected when adding $a to $b', ({a, b, expected}) => {
265 expect(a + b).toBe(expected);
266});
267```
268
269##### `each` takes a tagged template string with:
270
271- First row of variable name column headings seperated with `|`
272- One or more subsequent rows of data supplied as template literal expressions using `${value}` syntax.
273
274##### `.test`:
275
276- 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
277 - To inject nested object values use you can supply a keyPath i.e. `$variable.path.to.value`
278- testFn: `Function` the test logic, this is the function that will receive the parameters of each row as function arguments
279
280#### `each[tagged template].describe(name, suiteFn)`
281
282```js
283each`
284 a | b | expected
285 ${1} | ${1} | ${2}
286 ${1} | ${2} | ${3}
287 ${2} | ${1} | ${3}
288`.describe('$a + $b', ({a, b, expected}) => {
289 test(`returns ${expected}`, () => {
290 expect(a + b).toBe(expected);
291 });
292
293 test('does not mutate first arg', () => {
294 a + b;
295 expect(a).toBe(a);
296 });
297
298 test('does not mutate second arg', () => {
299 a + b;
300 expect(b).toBe(b);
301 });
302});
303```
304
305##### `each` takes a tagged template string with:
306
307- First row of variable name column headings seperated with `|`
308- One or more subsequent rows of data supplied as template literal expressions using `${value}` syntax.
309
310##### `.describe`:
311
312- 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
313 - To inject nested object values use you can supply a keyPath i.e. `$variable.path.to.value`
314- 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
315
316### Usage
317
318#### `.test(name, fn)`
319
320Alias: `.it(name, fn)`
321
322```js
323each`
324 a | b | expected
325 ${1} | ${1} | ${2}
326 ${1} | ${2} | ${3}
327 ${2} | ${1} | ${3}
328`.test('returns $expected when adding $a to $b', ({a, b, expected}) => {
329 expect(a + b).toBe(expected);
330});
331```
332
333#### `.test.only(name, fn)`
334
335Aliases: `.it.only(name, fn)` or `.fit(name, fn)`
336
337```js
338each`
339 a | b | expected
340 ${1} | ${1} | ${2}
341 ${1} | ${2} | ${3}
342 ${2} | ${1} | ${3}
343`.test.only('returns $expected when adding $a to $b', ({a, b, expected}) => {
344 expect(a + b).toBe(expected);
345});
346```
347
348#### `.test.skip(name, fn)`
349
350Aliases: `.it.skip(name, fn)` or `.xit(name, fn)` or `.xtest(name, fn)`
351
352```js
353each`
354 a | b | expected
355 ${1} | ${1} | ${2}
356 ${1} | ${2} | ${3}
357 ${2} | ${1} | ${3}
358`.test.skip('returns $expected when adding $a to $b', ({a, b, expected}) => {
359 expect(a + b).toBe(expected);
360});
361```
362
363#### Asynchronous `.test(name, fn(done))`
364
365Alias: `.it(name, fn(done))`
366
367```js
368each`
369 str
370 ${'hello'}
371 ${'mr'}
372 ${'spy'}
373`.test('gives 007 secret message: $str', ({str}, done) => {
374 const asynchronousSpy = message => {
375 expect(message).toBe(str);
376 done();
377 };
378 callSomeAsynchronousFunction(asynchronousSpy)(str);
379});
380```
381
382#### `.describe(name, fn)`
383
384```js
385each`
386 a | b | expected
387 ${1} | ${1} | ${2}
388 ${1} | ${2} | ${3}
389 ${2} | ${1} | ${3}
390`.describe('$a + $b', ({a, b, expected}) => {
391 test(`returns ${expected}`, () => {
392 expect(a + b).toBe(expected);
393 });
394
395 test('does not mutate first arg', () => {
396 a + b;
397 expect(a).toBe(a);
398 });
399
400 test('does not mutate second arg', () => {
401 a + b;
402 expect(b).toBe(b);
403 });
404});
405```
406
407#### `.describe.only(name, fn)`
408
409Aliases: `.fdescribe(name, fn)`
410
411```js
412each`
413 a | b | expected
414 ${1} | ${1} | ${2}
415 ${1} | ${2} | ${3}
416 ${2} | ${1} | ${3}
417`.describe.only('$a + $b', ({a, b, expected}) => {
418 test(`returns ${expected}`, () => {
419 expect(a + b).toBe(expected);
420 });
421});
422```
423
424#### `.describe.skip(name, fn)`
425
426Aliases: `.xdescribe(name, fn)`
427
428```js
429each`
430 a | b | expected
431 ${1} | ${1} | ${2}
432 ${1} | ${2} | ${3}
433 ${2} | ${1} | ${3}
434`.describe.skip('$a + $b', ({a, b, expected}) => {
435 test(`returns ${expected}`, () => {
436 expect(a + b).toBe(expected);
437 });
438});
439```
440
441## License
442
443MIT