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