|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548 |
- <div align="center">
- <h1>jest-each</h1>
- Jest Parameterised Testing
- </div>
-
- <hr />
-
- [![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/main/LICENSE)
-
- A parameterised testing library for [Jest](https://jestjs.io/) inspired by [mocha-each](https://github.com/ryym/mocha-each).
-
- jest-each allows you to provide multiple arguments to your `test`/`describe` which results in the test/suite being run once per row of parameters.
-
- ## Features
-
- - `.test` to runs multiple tests with parameterised data
- - Also under the alias: `.it`
- - `.test.only` to only run the parameterised tests
- - Also under the aliases: `.it.only` or `.fit`
- - `.test.skip` to skip the parameterised tests
- - Also under the aliases: `.it.skip` or `.xit` or `.xtest`
- - `.test.concurrent`
- - Also under the alias: `.it.concurrent`
- - `.test.concurrent.only`
- - Also under the alias: `.it.concurrent.only`
- - `.test.concurrent.skip`
- - Also under the alias: `.it.concurrent.skip`
- - `.describe` to runs test suites with parameterised data
- - `.describe.only` to only run the parameterised suite of tests
- - Also under the aliases: `.fdescribe`
- - `.describe.skip` to skip the parameterised suite of tests
- - Also under the aliases: `.xdescribe`
- - Asynchronous tests with `done`
- - Unique test titles with [`printf` formatting](https://nodejs.org/api/util.html#util_util_format_format_args):
- - `%p` - [pretty-format](https://www.npmjs.com/package/pretty-format).
- - `%s`- String.
- - `%d`- Number.
- - `%i` - Integer.
- - `%f` - Floating point value.
- - `%j` - JSON.
- - `%o` - Object.
- - `%#` - Index of the test case.
- - `%%` - single percent sign ('%'). This does not consume an argument.
- - Unique test titles by injecting properties of test case object
- - 🖖 Spock like data tables with [Tagged Template Literals](#tagged-template-literal-of-rows)
-
- ---
-
- - [Demo](#demo)
- - [Installation](#installation)
- - [Importing](#importing)
- - APIs
- - [Array of Rows](#array-of-rows)
- - [Usage](#usage)
- - [Tagged Template Literal of rows](#tagged-template-literal-of-rows)
- - [Usage](#usage-1)
-
- ## Demo
-
- #### Tests without jest-each
-
- ![Current jest tests](assets/default-demo.gif)
-
- #### Tests can be re-written with jest-each to:
-
- **`.test`**
-
- ![Current jest tests](assets/test-demo.gif)
-
- **`.test` with Tagged Template Literals**
-
- ![Current jest tests](assets/tagged-template-literal.gif)
-
- **`.describe`**
-
- ![Current jest tests](assets/describe-demo.gif)
-
- ## Installation
-
- `npm i --save-dev jest-each`
-
- `yarn add -D jest-each`
-
- ## Importing
-
- jest-each is a default export so it can be imported with whatever name you like.
-
- ```js
- // es6
- import each from 'jest-each';
- ```
-
- ```js
- // es5
- const each = require('jest-each').default;
- ```
-
- ## Array of rows
-
- ### API
-
- #### `each([parameters]).test(name, testFn)`
-
- ##### `each`:
-
- - parameters: `Array` of Arrays with the arguments that are passed into the `testFn` for each row
- - _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]]`
-
- ##### `.test`:
-
- - name: `String` the title of the `test`.
- - Generate unique test titles by positionally injecting parameters with [`printf` formatting](https://nodejs.org/api/util.html#util_util_format_format_args):
- - `%p` - [pretty-format](https://www.npmjs.com/package/pretty-format).
- - `%s`- String.
- - `%d`- Number.
- - `%i` - Integer.
- - `%f` - Floating point value.
- - `%j` - JSON.
- - `%o` - Object.
- - `%#` - Index of the test case.
- - `%%` - single percent sign ('%'). This does not consume an argument.
- - Or generate unique test titles by injecting properties of test case object with `$variable`
- - To inject nested object values use you can supply a keyPath i.e. `$variable.path.to.value`
- - You can use `$#` to inject the index of the test case
- - You cannot use `$variable` with the `printf` formatting except for `%%`
- - testFn: `Function` the test logic, this is the function that will receive the parameters of each row as function arguments
-
- #### `each([parameters]).describe(name, suiteFn)`
-
- ##### `each`:
-
- - parameters: `Array` of Arrays with the arguments that are passed into the `suiteFn` for each row
- - _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]]`
-
- ##### `.describe`:
-
- - name: `String` the title of the `describe`
- - Generate unique test titles by positionally injecting parameters with [`printf` formatting](https://nodejs.org/api/util.html#util_util_format_format_args):
- - `%p` - [pretty-format](https://www.npmjs.com/package/pretty-format).
- - `%s`- String.
- - `%d`- Number.
- - `%i` - Integer.
- - `%f` - Floating point value.
- - `%j` - JSON.
- - `%o` - Object.
- - `%#` - Index of the test case.
- - `%%` - single percent sign ('%'). This does not consume an argument.
- - Or generate unique test titles by injecting properties of test case object with `$variable`
- - To inject nested object values use you can supply a keyPath i.e. `$variable.path.to.value`
- - You can use `$#` to inject the index of the test case
- - You cannot use `$variable` with the `printf` formatting except for `%%`
- - 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
-
- ### Usage
-
- #### `.test(name, fn)`
-
- Alias: `.it(name, fn)`
-
- ```js
- each([
- [1, 1, 2],
- [1, 2, 3],
- [2, 1, 3],
- ]).test('returns the result of adding %d to %d', (a, b, expected) => {
- expect(a + b).toBe(expected);
- });
- ```
-
- ```js
- each([
- {a: 1, b: 1, expected: 2},
- {a: 1, b: 2, expected: 3},
- {a: 2, b: 1, expected: 3},
- ]).test('returns the result of adding $a to $b', ({a, b, expected}) => {
- expect(a + b).toBe(expected);
- });
- ```
-
- #### `.test.only(name, fn)`
-
- Aliases: `.it.only(name, fn)` or `.fit(name, fn)`
-
- ```js
- each([
- [1, 1, 2],
- [1, 2, 3],
- [2, 1, 3],
- ]).test.only('returns the result of adding %d to %d', (a, b, expected) => {
- expect(a + b).toBe(expected);
- });
- ```
-
- #### `.test.skip(name, fn)`
-
- Aliases: `.it.skip(name, fn)` or `.xit(name, fn)` or `.xtest(name, fn)`
-
- ```js
- each([
- [1, 1, 2],
- [1, 2, 3],
- [2, 1, 3],
- ]).test.skip('returns the result of adding %d to %d', (a, b, expected) => {
- expect(a + b).toBe(expected);
- });
- ```
-
- #### `.test.concurrent(name, fn)`
-
- Aliases: `.it.concurrent(name, fn)`
-
- ```js
- each([
- [1, 1, 2],
- [1, 2, 3],
- [2, 1, 3],
- ]).test.concurrent(
- 'returns the result of adding %d to %d',
- (a, b, expected) => {
- expect(a + b).toBe(expected);
- },
- );
- ```
-
- #### `.test.concurrent.only(name, fn)`
-
- Aliases: `.it.concurrent.only(name, fn)`
-
- ```js
- each([
- [1, 1, 2],
- [1, 2, 3],
- [2, 1, 3],
- ]).test.concurrent.only(
- 'returns the result of adding %d to %d',
- (a, b, expected) => {
- expect(a + b).toBe(expected);
- },
- );
- ```
-
- #### `.test.concurrent.skip(name, fn)`
-
- Aliases: `.it.concurrent.skip(name, fn)`
-
- ```js
- each([
- [1, 1, 2],
- [1, 2, 3],
- [2, 1, 3],
- ]).test.concurrent.skip(
- 'returns the result of adding %d to %d',
- (a, b, expected) => {
- expect(a + b).toBe(expected);
- },
- );
- ```
-
- #### Asynchronous `.test(name, fn(done))`
-
- Alias: `.it(name, fn(done))`
-
- ```js
- each([['hello'], ['mr'], ['spy']]).test(
- 'gives 007 secret message: %s',
- (str, done) => {
- const asynchronousSpy = message => {
- expect(message).toBe(str);
- done();
- };
- callSomeAsynchronousFunction(asynchronousSpy)(str);
- },
- );
- ```
-
- #### `.describe(name, fn)`
-
- ```js
- each([
- [1, 1, 2],
- [1, 2, 3],
- [2, 1, 3],
- ]).describe('.add(%d, %d)', (a, b, expected) => {
- test(`returns ${expected}`, () => {
- expect(a + b).toBe(expected);
- });
-
- test('does not mutate first arg', () => {
- a + b;
- expect(a).toBe(a);
- });
-
- test('does not mutate second arg', () => {
- a + b;
- expect(b).toBe(b);
- });
- });
- ```
-
- ```js
- each([
- {a: 1, b: 1, expected: 2},
- {a: 1, b: 2, expected: 3},
- {a: 2, b: 1, expected: 3},
- ]).describe('.add($a, $b)', ({a, b, expected}) => {
- test(`returns ${expected}`, () => {
- expect(a + b).toBe(expected);
- });
-
- test('does not mutate first arg', () => {
- a + b;
- expect(a).toBe(a);
- });
-
- test('does not mutate second arg', () => {
- a + b;
- expect(b).toBe(b);
- });
- });
- ```
-
- #### `.describe.only(name, fn)`
-
- Aliases: `.fdescribe(name, fn)`
-
- ```js
- each([
- [1, 1, 2],
- [1, 2, 3],
- [2, 1, 3],
- ]).describe.only('.add(%d, %d)', (a, b, expected) => {
- test(`returns ${expected}`, () => {
- expect(a + b).toBe(expected);
- });
- });
- ```
-
- #### `.describe.skip(name, fn)`
-
- Aliases: `.xdescribe(name, fn)`
-
- ```js
- each([
- [1, 1, 2],
- [1, 2, 3],
- [2, 1, 3],
- ]).describe.skip('.add(%d, %d)', (a, b, expected) => {
- test(`returns ${expected}`, () => {
- expect(a + b).toBe(expected);
- });
- });
- ```
-
- ---
-
- ## Tagged Template Literal of rows
-
- ### API
-
- #### `each[tagged template].test(name, suiteFn)`
-
- ```js
- each`
- a | b | expected
- ${1} | ${1} | ${2}
- ${1} | ${2} | ${3}
- ${2} | ${1} | ${3}
- `.test('returns $expected when adding $a to $b', ({a, b, expected}) => {
- expect(a + b).toBe(expected);
- });
- ```
-
- ##### `each` takes a tagged template string with:
-
- - First row of variable name column headings separated with `|`
- - One or more subsequent rows of data supplied as template literal expressions using `${value}` syntax.
-
- ##### `.test`:
-
- - 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
- - To inject nested object values use you can supply a keyPath i.e. `$variable.path.to.value`
- - You can use `$#` to inject the index of the table row.
- - testFn: `Function` the test logic, this is the function that will receive the parameters of each row as function arguments
-
- #### `each[tagged template].describe(name, suiteFn)`
-
- ```js
- each`
- a | b | expected
- ${1} | ${1} | ${2}
- ${1} | ${2} | ${3}
- ${2} | ${1} | ${3}
- `.describe('$a + $b', ({a, b, expected}) => {
- test(`returns ${expected}`, () => {
- expect(a + b).toBe(expected);
- });
-
- test('does not mutate first arg', () => {
- a + b;
- expect(a).toBe(a);
- });
-
- test('does not mutate second arg', () => {
- a + b;
- expect(b).toBe(b);
- });
- });
- ```
-
- ##### `each` takes a tagged template string with:
-
- - First row of variable name column headings separated with `|`
- - One or more subsequent rows of data supplied as template literal expressions using `${value}` syntax.
-
- ##### `.describe`:
-
- - 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
- - To inject nested object values use you can supply a keyPath i.e. `$variable.path.to.value`
- - 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
-
- ### Usage
-
- #### `.test(name, fn)`
-
- Alias: `.it(name, fn)`
-
- ```js
- each`
- a | b | expected
- ${1} | ${1} | ${2}
- ${1} | ${2} | ${3}
- ${2} | ${1} | ${3}
- `.test('returns $expected when adding $a to $b', ({a, b, expected}) => {
- expect(a + b).toBe(expected);
- });
- ```
-
- #### `.test.only(name, fn)`
-
- Aliases: `.it.only(name, fn)` or `.fit(name, fn)`
-
- ```js
- each`
- a | b | expected
- ${1} | ${1} | ${2}
- ${1} | ${2} | ${3}
- ${2} | ${1} | ${3}
- `.test.only('returns $expected when adding $a to $b', ({a, b, expected}) => {
- expect(a + b).toBe(expected);
- });
- ```
-
- #### `.test.skip(name, fn)`
-
- Aliases: `.it.skip(name, fn)` or `.xit(name, fn)` or `.xtest(name, fn)`
-
- ```js
- each`
- a | b | expected
- ${1} | ${1} | ${2}
- ${1} | ${2} | ${3}
- ${2} | ${1} | ${3}
- `.test.skip('returns $expected when adding $a to $b', ({a, b, expected}) => {
- expect(a + b).toBe(expected);
- });
- ```
-
- #### Asynchronous `.test(name, fn(done))`
-
- Alias: `.it(name, fn(done))`
-
- ```js
- each`
- str
- ${'hello'}
- ${'mr'}
- ${'spy'}
- `.test('gives 007 secret message: $str', ({str}, done) => {
- const asynchronousSpy = message => {
- expect(message).toBe(str);
- done();
- };
- callSomeAsynchronousFunction(asynchronousSpy)(str);
- });
- ```
-
- #### `.describe(name, fn)`
-
- ```js
- each`
- a | b | expected
- ${1} | ${1} | ${2}
- ${1} | ${2} | ${3}
- ${2} | ${1} | ${3}
- `.describe('$a + $b', ({a, b, expected}) => {
- test(`returns ${expected}`, () => {
- expect(a + b).toBe(expected);
- });
-
- test('does not mutate first arg', () => {
- a + b;
- expect(a).toBe(a);
- });
-
- test('does not mutate second arg', () => {
- a + b;
- expect(b).toBe(b);
- });
- });
- ```
-
- #### `.describe.only(name, fn)`
-
- Aliases: `.fdescribe(name, fn)`
-
- ```js
- each`
- a | b | expected
- ${1} | ${1} | ${2}
- ${1} | ${2} | ${3}
- ${2} | ${1} | ${3}
- `.describe.only('$a + $b', ({a, b, expected}) => {
- test(`returns ${expected}`, () => {
- expect(a + b).toBe(expected);
- });
- });
- ```
-
- #### `.describe.skip(name, fn)`
-
- Aliases: `.xdescribe(name, fn)`
-
- ```js
- each`
- a | b | expected
- ${1} | ${1} | ${2}
- ${1} | ${2} | ${3}
- ${2} | ${1} | ${3}
- `.describe.skip('$a + $b', ({a, b, expected}) => {
- test(`returns ${expected}`, () => {
- expect(a + b).toBe(expected);
- });
- });
- ```
-
- ## License
-
- MIT
|