jest-each
Jest Parameterised TestingA parameterised testing library for Jest inspired by 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
- .testto runs multiple tests with parameterised data- Also under the alias: .it
 
- Also under the alias: 
- .test.onlyto only run the parameterised tests- Also under the aliases: .it.onlyor.fit
 
- Also under the aliases: 
- .test.skipto skip the parameterised tests- Also under the aliases: .it.skipor.xitor.xtest
 
- Also under the aliases: 
- .describeto runs test suites with parameterised data
- .describe.onlyto only run the parameterised suite of tests- Also under the aliases: .fdescribe
 
- Also under the aliases: 
- .describe.skipto skip the parameterised suite of tests- Also under the aliases: .xdescribe
 
- Also under the aliases: 
- Asynchronous tests with done
- Unique test titles with printfformatting:- %p- 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.
 
- 🖖 Spock like data tables with Tagged Template Literals
Demo
Tests without jest-each
Tests can be re-written with jest-each to:
.test
.test with Tagged Template Literals
.describe
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.
// es6
import each from 'jest-each';
// es5
const each = require('jest-each').default;
Array of rows
API
each([parameters]).test(name, testFn)
each:
- parameters: Arrayof Arrays with the arguments that are passed into thetestFnfor 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]]
 
- Note If you pass in a 1D array of primitives, internally it will be mapped to a table i.e. 
.test:
- name: Stringthe title of thetest.- Generate unique test titles by positionally injecting parameters with printfformatting:- %p- 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.
 
 
- Generate unique test titles by positionally injecting parameters with 
- testFn: Functionthe test logic, this is the function that will receive the parameters of each row as function arguments
each([parameters]).describe(name, suiteFn)
each:
- parameters: Arrayof Arrays with the arguments that are passed into thesuiteFnfor 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]]
 
- Note If you pass in a 1D array of primitives, internally it will be mapped to a table i.e. 
.describe:
- name: Stringthe title of thedescribe- Generate unique test titles by positionally injecting parameters with printfformatting:- %p- 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.
 
 
- Generate unique test titles by positionally injecting parameters with 
- suiteFn: Functionthe suite oftest/its 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)
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);
  },
);
.test.only(name, fn)
Aliases: .it.only(name, fn) or .fit(name, fn)
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)
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);
  },
);
Asynchronous .test(name, fn(done))
Alias: .it(name, fn(done))
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)
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);
    });
  },
);
.describe.only(name, fn)
Aliases: .fdescribe(name, fn)
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)
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)
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 seperated with |
- One or more subsequent rows of data supplied as template literal expressions using ${value}syntax.
.test:
- name: Stringthe title of thetest, use$variablein 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
 
- To inject nested object values use you can supply a keyPath i.e. 
- testFn: Functionthe test logic, this is the function that will receive the parameters of each row as function arguments
each[tagged template].describe(name, suiteFn)
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 seperated with |
- One or more subsequent rows of data supplied as template literal expressions using ${value}syntax.
.describe:
- name: Stringthe title of thetest, use$variablein 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
 
- To inject nested object values use you can supply a keyPath i.e. 
- suiteFn: Functionthe suite oftest/its 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)
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)
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)
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))
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)
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)
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)
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



