Skip to content

Commit

Permalink
[jest-each]: Add empty string/array validation check (#7249)
Browse files Browse the repository at this point in the history
* Add empty array check to jest-each

* Add changelog entry

* Add empty string check to jest-each

* Fix types in error messages

* Add tagged template literal with no data validation check
  • Loading branch information
mattphillips authored and SimenB committed Oct 30, 2018
1 parent 5cdfc22 commit 51e68e7
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

### Fixes

- `[jest-each]` Add empty array validation check ([#7249](https://github.com/facebook/jest/pull/7249))
- `[jest-cli]` Interrupt tests if interactive watch plugin key is pressed ([#7222](https://github.com/facebook/jest/pull/7222))
- `[jest-cli]` Fix coverage summary reporting ([#7058](https://github.com/facebook/jest/pull/7058))
- `[jest-each]` Add each array validation check ([#7033](https://github.com/facebook/jest/pull/7033))
Expand Down
56 changes: 48 additions & 8 deletions packages/jest-each/src/__tests__/__snapshots__/array.test.js.snap
Original file line number Diff line number Diff line change
@@ -1,56 +1,96 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`jest-each .describe throws an error when called with an empty array 1`] = `
"Error: \`.each\` called with an empty Array of table data.
"
`;

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.
"\`.each\` must be called with an Array or Tagged Template Literal.
Instead was called with: undefined
"
`;

exports[`jest-each .describe.only throws an error when called with an empty array 1`] = `
"Error: \`.each\` called with an empty Array of table data.
"
`;

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.
"\`.each\` must be called with an Array or Tagged Template Literal.
Instead was called with: undefined
"
`;

exports[`jest-each .fdescribe throws an error when called with an empty array 1`] = `
"Error: \`.each\` called with an empty Array of table data.
"
`;

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.
"\`.each\` must be called with an Array or Tagged Template Literal.
Instead was called with: undefined
"
`;

exports[`jest-each .fit throws an error when called with an empty array 1`] = `
"Error: \`.each\` called with an empty Array of table data.
"
`;

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.
"\`.each\` must be called with an Array or Tagged Template Literal.
Instead was called with: undefined
"
`;

exports[`jest-each .it throws an error when called with an empty array 1`] = `
"Error: \`.each\` called with an empty Array of table data.
"
`;

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.
"\`.each\` must be called with an Array or Tagged Template Literal.
Instead was called with: undefined
"
`;

exports[`jest-each .it.only throws an error when called with an empty array 1`] = `
"Error: \`.each\` called with an empty Array of table data.
"
`;

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.
"\`.each\` must be called with an Array or Tagged Template Literal.
Instead was called with: undefined
"
`;

exports[`jest-each .test throws an error when called with an empty array 1`] = `
"Error: \`.each\` called with an empty Array of table data.
"
`;

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.
"\`.each\` must be called with an Array or Tagged Template Literal.
Instead was called with: undefined
"
`;

exports[`jest-each .test.only throws an error when called with an empty array 1`] = `
"Error: \`.each\` called with an empty Array of table data.
"
`;

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.
"\`.each\` must be called with an Array or Tagged Template Literal.
Instead was called with: undefined
"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`jest-each .describe throws an error when called with an empty string 1`] = `
"Error: \`.each\` called with an empty Tagged Template Literal of table data.
"
`;

exports[`jest-each .describe throws error when there are fewer arguments than headings over multiple rows 1`] = `
"Not enough arguments supplied for given headings:
<green>a | b | expected</>
Expand Down Expand Up @@ -29,6 +34,16 @@ Received:
Missing <red>2</> arguments"
`;
exports[`jest-each .describe throws error when there are no arguments for given headings 1`] = `
"Error: \`.each\` called with a Tagged Template Literal with no data, remember to interpolate with \${expression} syntax.
"
`;
exports[`jest-each .describe.only throws an error when called with an empty string 1`] = `
"Error: \`.each\` called with an empty Tagged Template Literal of table data.
"
`;
exports[`jest-each .describe.only throws error when there are fewer arguments than headings over multiple rows 1`] = `
"Not enough arguments supplied for given headings:
<green>a | b | expected</>
Expand Down Expand Up @@ -58,6 +73,16 @@ Received:
Missing <red>2</> arguments"
`;
exports[`jest-each .describe.only throws error when there are no arguments for given headings 1`] = `
"Error: \`.each\` called with a Tagged Template Literal with no data, remember to interpolate with \${expression} syntax.
"
`;
exports[`jest-each .fdescribe throws an error when called with an empty string 1`] = `
"Error: \`.each\` called with an empty Tagged Template Literal of table data.
"
`;
exports[`jest-each .fdescribe throws error when there are fewer arguments than headings over multiple rows 1`] = `
"Not enough arguments supplied for given headings:
<green>a | b | expected</>
Expand Down Expand Up @@ -87,6 +112,16 @@ Received:
Missing <red>2</> arguments"
`;
exports[`jest-each .fdescribe throws error when there are no arguments for given headings 1`] = `
"Error: \`.each\` called with a Tagged Template Literal with no data, remember to interpolate with \${expression} syntax.
"
`;
exports[`jest-each .fit throws an error when called with an empty string 1`] = `
"Error: \`.each\` called with an empty Tagged Template Literal of table data.
"
`;
exports[`jest-each .fit throws error when there are fewer arguments than headings over multiple rows 1`] = `
"Not enough arguments supplied for given headings:
<green>a | b | expected</>
Expand Down Expand Up @@ -116,6 +151,16 @@ Received:
Missing <red>2</> arguments"
`;
exports[`jest-each .fit throws error when there are no arguments for given headings 1`] = `
"Error: \`.each\` called with a Tagged Template Literal with no data, remember to interpolate with \${expression} syntax.
"
`;
exports[`jest-each .it throws an error when called with an empty string 1`] = `
"Error: \`.each\` called with an empty Tagged Template Literal of table data.
"
`;
exports[`jest-each .it throws error when there are fewer arguments than headings over multiple rows 1`] = `
"Not enough arguments supplied for given headings:
<green>a | b | expected</>
Expand Down Expand Up @@ -145,6 +190,16 @@ Received:
Missing <red>2</> arguments"
`;
exports[`jest-each .it throws error when there are no arguments for given headings 1`] = `
"Error: \`.each\` called with a Tagged Template Literal with no data, remember to interpolate with \${expression} syntax.
"
`;
exports[`jest-each .it.only throws an error when called with an empty string 1`] = `
"Error: \`.each\` called with an empty Tagged Template Literal of table data.
"
`;
exports[`jest-each .it.only throws error when there are fewer arguments than headings over multiple rows 1`] = `
"Not enough arguments supplied for given headings:
<green>a | b | expected</>
Expand Down Expand Up @@ -174,6 +229,16 @@ Received:
Missing <red>2</> arguments"
`;
exports[`jest-each .it.only throws error when there are no arguments for given headings 1`] = `
"Error: \`.each\` called with a Tagged Template Literal with no data, remember to interpolate with \${expression} syntax.
"
`;
exports[`jest-each .test throws an error when called with an empty string 1`] = `
"Error: \`.each\` called with an empty Tagged Template Literal of table data.
"
`;
exports[`jest-each .test throws error when there are fewer arguments than headings over multiple rows 1`] = `
"Not enough arguments supplied for given headings:
<green>a | b | expected</>
Expand Down Expand Up @@ -203,6 +268,16 @@ Received:
Missing <red>2</> arguments"
`;
exports[`jest-each .test throws error when there are no arguments for given headings 1`] = `
"Error: \`.each\` called with a Tagged Template Literal with no data, remember to interpolate with \${expression} syntax.
"
`;
exports[`jest-each .test.only throws an error when called with an empty string 1`] = `
"Error: \`.each\` called with an empty Tagged Template Literal of table data.
"
`;
exports[`jest-each .test.only throws error when there are fewer arguments than headings over multiple rows 1`] = `
"Not enough arguments supplied for given headings:
<green>a | b | expected</>
Expand Down Expand Up @@ -231,3 +306,8 @@ Received:
Missing <red>2</> arguments"
`;
exports[`jest-each .test.only throws error when there are no arguments for given headings 1`] = `
"Error: \`.each\` called with a Tagged Template Literal with no data, remember to interpolate with \${expression} syntax.
"
`;
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 @@ -60,6 +60,19 @@ describe('jest-each', () => {
).toThrowErrorMatchingSnapshot();
});

test('throws an error when called with an empty array', () => {
const globalTestMocks = getGlobalTestMocks();
const eachObject = each.withGlobal(globalTestMocks)([]);
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
32 changes: 32 additions & 0 deletions packages/jest-each/src/__tests__/template.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,23 @@ describe('jest-each', () => {
['describe', 'only'],
].forEach(keyPath => {
describe(`.${keyPath.join('.')}`, () => {
test('throws error when there are no arguments for given headings', () => {
const globalTestMocks = getGlobalTestMocks();
const eachObject = each.withGlobal(globalTestMocks)`
a | b | expected
`;
const testFunction = get(eachObject, keyPath);
const testCallBack = jest.fn();
testFunction('this will blow up :(', testCallBack);

const globalMock = get(globalTestMocks, keyPath);

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

test('throws error when there are fewer arguments than headings when given one row', () => {
const globalTestMocks = getGlobalTestMocks();
const eachObject = each.withGlobal(globalTestMocks)`
Expand Down Expand Up @@ -83,6 +100,21 @@ describe('jest-each', () => {
expect(testCallBack).not.toHaveBeenCalled();
});

test('throws an error when called with an empty string', () => {
const globalTestMocks = getGlobalTestMocks();
const eachObject = each.withGlobal(globalTestMocks)` `;
const testFunction = get(eachObject, keyPath);
const testCallBack = jest.fn();
testFunction('this will blow up :(', testCallBack);

const globalMock = get(globalTestMocks, keyPath);

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

test('calls global with given title', () => {
const globalTestMocks = getGlobalTestMocks();
const eachObject = each.withGlobal(globalTestMocks)`
Expand Down
36 changes: 35 additions & 1 deletion packages/jest-each/src/bind.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export default (cb: Function, supportsDone: boolean = true) => (...args: any) =>

if (!Array.isArray(tableArg)) {
const error = new ErrorWithStack(
'`.each` must be called with an Array or Tagged Template String.\n\n' +
'`.each` must be called with an Array or Tagged Template Literal.\n\n' +
`Instead was called with: ${pretty(tableArg, {
maxDepth: 1,
min: true,
Expand All @@ -42,6 +42,36 @@ export default (cb: Function, supportsDone: boolean = true) => (...args: any) =>
throw error;
});
}

if (isTaggedTemplateLiteral(tableArg)) {
if (isEmptyString(tableArg[0])) {
const error = new ErrorWithStack(
'Error: `.each` called with an empty Tagged Template Literal of table data.\n',
eachBind,
);
return cb(title, () => {
throw error;
});
}

const error = new ErrorWithStack(
'Error: `.each` called with a Tagged Template Literal with no data, remember to interpolate with ${expression} syntax.\n',
eachBind,
);
return cb(title, () => {
throw error;
});
}

if (isEmptyTable(tableArg)) {
const error = new ErrorWithStack(
'Error: `.each` called with an empty Array of table data.\n',
eachBind,
);
return cb(title, () => {
throw error;
});
}
const table: Table = tableArg.every(Array.isArray)
? tableArg
: tableArg.map(entry => [entry]);
Expand Down Expand Up @@ -91,6 +121,10 @@ export default (cb: Function, supportsDone: boolean = true) => (...args: any) =>
);
};

const isTaggedTemplateLiteral = array => array.raw !== undefined;
const isEmptyTable = table => table.length === 0;
const isEmptyString = str => typeof str === 'string' && str.trim() === '';

const getPrettyIndexes = placeholders =>
placeholders.reduce(
(indexes, placeholder, index) =>
Expand Down

0 comments on commit 51e68e7

Please sign in to comment.