Skip to content

Commit

Permalink
[jest-each] Add each array validation check (#7033)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattphillips authored and SimenB committed Sep 23, 2018
1 parent 7478a79 commit e2ebcd0
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

### Fixes

- `[jest-each]` Add each array validation check ([#7033](https://github.com/facebook/jest/pull/7033))
- `[jest-haste-map]` [**BREAKING**] Replace internal data structures to improve performance ([#6960](https://github.com/facebook/jest/pull/6960))
- `[jest-haste-map]` Do not visit again files with the same sha-1 ([#6990](https://github.com/facebook/jest/pull/6990))
- `[jest-jasmine2]` Fix memory leak in Error objects hold by the framework ([#6965](https://github.com/facebook/jest/pull/6965))
Expand Down
57 changes: 57 additions & 0 deletions packages/jest-each/src/__tests__/__snapshots__/array.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`jest-each .describe throws an error when not called with an array 1`] = `
"\`.each\` must be called with an Array or Tagged Template String.
Instead was called with: undefined
"
`;

exports[`jest-each .describe.only throws an error when not called with an array 1`] = `
"\`.each\` must be called with an Array or Tagged Template String.
Instead was called with: undefined
"
`;

exports[`jest-each .fdescribe throws an error when not called with an array 1`] = `
"\`.each\` must be called with an Array or Tagged Template String.
Instead was called with: undefined
"
`;

exports[`jest-each .fit throws an error when not called with an array 1`] = `
"\`.each\` must be called with an Array or Tagged Template String.
Instead was called with: undefined
"
`;

exports[`jest-each .it throws an error when not called with an array 1`] = `
"\`.each\` must be called with an Array or Tagged Template String.
Instead was called with: undefined
"
`;

exports[`jest-each .it.only throws an error when not called with an array 1`] = `
"\`.each\` must be called with an Array or Tagged Template String.
Instead was called with: undefined
"
`;

exports[`jest-each .test throws an error when not called with an array 1`] = `
"\`.each\` must be called with an Array or Tagged Template String.
Instead was called with: undefined
"
`;

exports[`jest-each .test.only throws an error when not called with an array 1`] = `
"\`.each\` must be called with an Array or Tagged Template String.
Instead was called with: undefined
"
`;
13 changes: 13 additions & 0 deletions packages/jest-each/src/__tests__/array.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,19 @@ describe('jest-each', () => {
['describe', 'only'],
].forEach(keyPath => {
describe(`.${keyPath.join('.')}`, () => {
test('throws an error when not called with an array', () => {
const globalTestMocks = getGlobalTestMocks();
const eachObject = each.withGlobal(globalTestMocks)(undefined);
const testFunction = get(eachObject, keyPath);

testFunction('expected string', noop);
const globalMock = get(globalTestMocks, keyPath);

expect(() =>
globalMock.mock.calls[0][1](),
).toThrowErrorMatchingSnapshot();
});

test('calls global with given title', () => {
const globalTestMocks = getGlobalTestMocks();
const eachObject = each.withGlobal(globalTestMocks)([[]]);
Expand Down
36 changes: 28 additions & 8 deletions packages/jest-each/src/bind.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,35 @@ const SUPPORTED_PLACEHOLDERS = /%[sdifjoOp%]/g;
const PRETTY_PLACEHOLDER = '%p';
const INDEX_PLACEHOLDER = '%#';

const errorWithStack = (message, callsite) => {
const error = new Error(message);
if (Error.captureStackTrace) {
Error.captureStackTrace(error, callsite);
}
return error;
};

export default (cb: Function, supportsDone: boolean = true) => (...args: any) =>
function eachBind(title: string, test: Function, timeout: number): void {
if (args.length === 1) {
const table: Table = args[0].every(Array.isArray)
? args[0]
: args[0].map(entry => [entry]);
const [tableArg] = args;

if (!Array.isArray(tableArg)) {
const error = errorWithStack(
'`.each` must be called with an Array or Tagged Template String.\n\n' +
`Instead was called with: ${pretty(tableArg, {
maxDepth: 1,
min: true,
})}\n`,
eachBind,
);
return cb(title, () => {
throw error;
});
}
const table: Table = tableArg.every(Array.isArray)
? tableArg
: tableArg.map(entry => [entry]);
return table.forEach((row, i) =>
cb(
arrayFormat(title, i, ...row),
Expand All @@ -47,7 +70,7 @@ export default (cb: Function, supportsDone: boolean = true) => (...args: any) =>
const missingData = data.length % keys.length;

if (missingData > 0) {
const error = new Error(
const error = errorWithStack(
'Not enough arguments supplied for given headings:\n' +
EXPECTED_COLOR(keys.join(' | ')) +
'\n\n' +
Expand All @@ -58,12 +81,9 @@ export default (cb: Function, supportsDone: boolean = true) => (...args: any) =>
'argument',
missingData,
)}`,
eachBind,
);

if (Error.captureStackTrace) {
Error.captureStackTrace(error, eachBind);
}

return cb(title, () => {
throw error;
});
Expand Down

0 comments on commit e2ebcd0

Please sign in to comment.