npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

jest-each

v30.5.1

Published

Parameterised tests for Jest

Readme

version downloads MIT License

A 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

  • .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:
    • %p - pretty-format.
    • %s- String.
    • %d- Number.
    • %i - Integer.
    • %f - Floating point value.
    • %j - JSON.
    • %o - Object.
    • %# - Index of the test case.
    • %$ - Number 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

Demo

Tests without jest-each

Current jest tests

Tests can be re-written with jest-each to:

.test

Current jest tests

.test with Tagged Template Literals

Current jest tests

.describe

Current jest tests

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: 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:
      • %p - pretty-format.
      • %s- String.
      • %d- Number.
      • %i - Integer.
      • %f - Floating point value.
      • %j - JSON.
      • %o - Object.
      • %# - Index of the test case.
      • %$ - Number 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 (only works for "own" properties, e.g. $variable.constructor.name wouldn't work)
      • 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:
      • %p - pretty-format.
      • %s- String.
      • %d- Number.
      • %i - Integer.
      • %f - Floating point value.
      • %j - JSON.
      • %o - Object.
      • %# - Index of the test case.
      • %$ - Number 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 (only works for "own" properties, e.g. $variable.constructor.name wouldn't work)
      • 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/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);
});
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)

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);
});

.test.concurrent(name, fn)

Aliases: .it.concurrent(name, fn)

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)

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)

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))

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);
  });
});
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)

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 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 (only works for "own" properties, e.g. $variable.constructor.name wouldn't work)
    • 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)

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 (only works for "own" properties, e.g. $variable.constructor.name wouldn't work)
  • suiteFn: Function the suite of test/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