
Security News
arXiv Is Rate Limiting Authors Following a Flood of AI Slop Submissions
arXiv now limits authors to two submissions a month as AI slop overwhelms moderators, delays good papers, and sparks debate over applying the limit to everyone.
jest-each
Advanced tools
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.
.test to runs multiple tests with parameterised data
.it.test.only to only run the parameterised tests
.it.only or .fit.test.skip to skip the parameterised tests
.it.skip or .xit or .xtest.test.concurrent
.it.concurrent.test.concurrent.only
.it.concurrent.only.test.concurrent.skip
.it.concurrent.skip.describe to runs test suites with parameterised data.describe.only to only run the parameterised suite of tests
.fdescribe.describe.skip to skip the parameterised suite of tests
.xdescribedoneprintf 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.
.test

.test with Tagged Template Literals

.describe

npm i --save-dev jest-each
yarn add -D jest-each
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;
each([parameters]).test(name, testFn)each:Array of Arrays with the arguments that are passed into the testFn for each row
[1, 2, 3] -> [[1], [2], [3]].test:String the title of the test.
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.$variable
$variable.path.to.value (only works for "own" properties, e.g. $variable.constructor.name wouldn't work)$# to inject the index of the test case$variable with the printf formatting except for %%Function the test logic, this is the function that will receive the parameters of each row as function argumentseach([parameters]).describe(name, suiteFn)each:Array of Arrays with the arguments that are passed into the suiteFn for each row
[1, 2, 3] -> [[1], [2], [3]].describe:String the title of the describe
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.$variable
$variable.path.to.value (only works for "own" properties, e.g. $variable.constructor.name wouldn't work)$# to inject the index of the test case$variable with the printf formatting except for %%Function the suite of test/its to be ran, this is the function that will receive the parameters in each row as function arguments.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);
},
);
.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);
});
});
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:|${value} syntax..test: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
$variable.path.to.value (only works for "own" properties, e.g. $variable.constructor.name wouldn't work)$# to inject the index of the table row.Function the test logic, this is the function that will receive the parameters of each row as function argumentseach[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:|${value} syntax..describe: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
$variable.path.to.value (only works for "own" properties, e.g. $variable.constructor.name wouldn't work)Function the suite of test/its to be ran, this is the function that will receive the parameters in each row as function arguments.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);
});
.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);
});
});
MIT
Mocha is a feature-rich JavaScript test framework running on Node.js and in the browser. It allows for flexible and accurate reporting, while mapping uncaught exceptions to the correct test cases. Mocha can be used with various assertion libraries, and while it doesn't have built-in support for parameterized tests like jest-each, it can achieve similar functionality with the help of additional libraries like 'mocha-each'.
AVA is a test runner for Node.js with a concise API, detailed error output, and process isolation. It supports running tests concurrently, which can lead to faster test execution. AVA supports parameterized tests through its 'test.each' method, similar to jest-each, making it a good alternative for those looking for a minimalistic and fast testing framework.
Tape is a minimalist JavaScript test runner that works in both Node.js and the browser. It does not have built-in support for parameterized tests, but you can achieve similar functionality by writing loops within your test cases. Tape is known for its simplicity and ease of use, making it a good choice for smaller projects or those who prefer a lightweight testing solution.
FAQs
Parameterised tests for Jest
The npm package jest-each receives a total of 28,517,570 weekly downloads. As such, jest-each popularity was classified as popular.
We found that jest-each demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 6 open source maintainers collaborating on the project.

Security News
arXiv now limits authors to two submissions a month as AI slop overwhelms moderators, delays good papers, and sparks debate over applying the limit to everyone.

Research
/Security News
A new GhostAction wave hits hundreds of GitHub repos, expanding CI/CD secret theft to cloud and AI credentials in source code and git history.

Research
/Security News
Tensorlake npm SDK version 0.5.144 was compromised in a ChainDrop / Shai-Hulud attack, delivering credential-stealing malware.