Skip to content

Commit

Permalink
[jest-each]: Add test/describe timeout support (#6660)
Browse files Browse the repository at this point in the history
## Summary

Add test/describe timeout support

 - Fixes feature parity to [testname-fn-timeout](https://jestjs.io/docs/en/api#testname-fn-timeout) etc

Fixes #6749
## Test plan

 - Updated `jest-each` unit tests
 - Remove duplicate unit tests in `jest-jasmine2` (we have integration tests that cover this so no need to maintain the unit tests in two places)
  • Loading branch information
mattphillips authored and thymikee committed Aug 9, 2018
1 parent cefc342 commit ebaf934
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 462 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
- `[jest-config]` Update default config for testURL from 'about:blank' to 'http://localhost' to address latest JSDOM security warning. ([#6792](https://github.com/facebook/jest/pull/6792))
- `[jest-cli]` Fix `testMatch` not working with negations ([#6648](https://github.com/facebook/jest/pull/6648))
- `[jest-cli]` Don't report promises as open handles ([#6716](https://github.com/facebook/jest/pull/6716))
- `[jest-each]` Add timeout support to parameterised tests ([#6660](https://github.com/facebook/jest/pull/6660))

## 23.4.2

Expand Down
16 changes: 10 additions & 6 deletions docs/GlobalAPI.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,13 +222,13 @@ describe('binaryStringToNumber', () => {
});
```

### `describe.each(table)(name, fn)`
### `describe.each(table)(name, fn, timeout)`

Use `describe.each` if you keep duplicating the same test suites with different data. `describe.each` allows you to write the test suite once and pass data in.

`describe.each` is available with two APIs:

#### 1. `describe.each(table)(name, fn)`
#### 1. `describe.each(table)(name, fn, timeout)`

- `table`: `Array` of Arrays with the arguments that are passed into the `fn` 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]]`
Expand All @@ -244,6 +244,7 @@ Use `describe.each` if you keep duplicating the same test suites with different
- `%#` - Index of the test case.
- `%%` - single percent sign ('%'). This does not consume an argument.
- `fn`: `Function` the suite of tests to be ran, this is the function that will receive the parameters in each row as function arguments.
- Optionally, you can provide a `timeout` (in milliseconds) for specifying how long to wait for each row before aborting. _Note: The default timeout is 5 seconds._

Example:

Expand All @@ -266,14 +267,15 @@ describe.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])(
);
```

#### 2. `` describe.each`table`(name, fn) ``
#### 2. `` describe.each`table`(name, fn, timeout) ``

- `table`: `Tagged Template Literal`
- First row of variable name column headings separated with `|`
- One or more subsequent rows of data supplied as template literal expressions using `${value}` syntax.
- `name`: `String` the title of the test suite, use `$variable` to inject test data into the suite title from the tagged template expressions.
- To inject nested object values use you can supply a keyPath i.e. `$variable.path.to.value`
- `fn`: `Function` the suite of tests to be ran, this is the function that will receive the test data object.
- Optionally, you can provide a `timeout` (in milliseconds) for specifying how long to wait for each row before aborting. _Note: The default timeout is 5 seconds._

Example:

Expand Down Expand Up @@ -468,15 +470,15 @@ test('has lemon in it', () => {

Even though the call to `test` will return right away, the test doesn't complete until the promise resolves as well.

### `test.each(table)(name, fn)`
### `test.each(table)(name, fn, timeout)`

Also under the alias: `it.each(table)(name, fn)` and `` it.each`table`(name, fn) ``

Use `test.each` if you keep duplicating the same test with different data. `test.each` allows you to write the test once and pass data in.

`test.each` is available with two APIs:

#### 1. `test.each(table)(name, fn)`
#### 1. `test.each(table)(name, fn, timeout)`

- `table`: `Array` of Arrays with the arguments that are passed into the test `fn` 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]]`
Expand All @@ -492,6 +494,7 @@ Use `test.each` if you keep duplicating the same test with different data. `test
- `%#` - Index of the test case.
- `%%` - single percent sign ('%'). This does not consume an argument.
- `fn`: `Function` the test to be ran, this is the function that will receive the parameters in each row as function arguments.
- Optionally, you can provide a `timeout` (in milliseconds) for specifying how long to wait for each row before aborting. _Note: The default timeout is 5 seconds._

Example:

Expand All @@ -504,14 +507,15 @@ test.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])(
);
```

#### 2. `` test.each`table`(name, fn) ``
#### 2. `` test.each`table`(name, fn, timeout) ``

- `table`: `Tagged Template Literal`
- First row of variable name column headings separated with `|`
- One or more subsequent rows of data supplied as template literal expressions using `${value}` syntax.
- `name`: `String` the title of the test, use `$variable` to inject test data 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`
- `fn`: `Function` the test to be ran, this is the function that will receive the test data object.
- Optionally, you can provide a `timeout` (in milliseconds) for specifying how long to wait for each row before aborting. _Note: The default timeout is 5 seconds._

Example:

Expand Down
29 changes: 29 additions & 0 deletions packages/jest-each/src/__tests__/array.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ describe('jest-each', () => {
expect(globalMock).toHaveBeenCalledWith(
'expected string',
expectFunction,
undefined,
);
});

Expand All @@ -66,10 +67,12 @@ describe('jest-each', () => {
expect(globalMock).toHaveBeenCalledWith(
'expected string',
expectFunction,
undefined,
);
expect(globalMock).toHaveBeenCalledWith(
'expected string',
expectFunction,
undefined,
);
});

Expand Down Expand Up @@ -111,12 +114,14 @@ describe('jest-each', () => {
foo: 'bar',
})} () => {} [] Infinity NaN 0`,
expectFunction,
undefined,
);
expect(globalMock).toHaveBeenCalledWith(
`expected string: world 1 null undefined 1.2 ${JSON.stringify({
baz: 'qux',
})} () => {} [] Infinity NaN 1`,
expectFunction,
undefined,
);
});

Expand All @@ -134,10 +139,12 @@ describe('jest-each', () => {
expect(globalMock).toHaveBeenCalledWith(
'expected string: hello',
expectFunction,
undefined,
);
expect(globalMock).toHaveBeenCalledWith(
'expected string: world',
expectFunction,
undefined,
);
});

Expand All @@ -157,12 +164,14 @@ describe('jest-each', () => {
'pretty2',
)}`,
expectFunction,
undefined,
);
expect(globalMock).toHaveBeenCalledWith(
`expected string: string1 ${pretty('pretty1')} string2 ${pretty(
'pretty2',
)}`,
expectFunction,
undefined,
);
});

Expand All @@ -180,10 +189,12 @@ describe('jest-each', () => {
expect(globalMock).toHaveBeenCalledWith(
`expected string: string1 ${pretty('pretty1')} string2 %p`,
expectFunction,
undefined,
);
expect(globalMock).toHaveBeenCalledWith(
`expected string: string1 ${pretty('pretty1')} string2 %p`,
expectFunction,
undefined,
);
});

Expand Down Expand Up @@ -237,6 +248,20 @@ describe('jest-each', () => {
});
get(globalTestMocks, keyPath).mock.calls[0][1]('DONE');
});

test('calls global with given timeout', () => {
const globalTestMocks = getGlobalTestMocks();
const eachObject = each.withGlobal(globalTestMocks)([['hello']]);

const testFunction = get(eachObject, keyPath);
testFunction('some test', noop, 10000);
const globalMock = get(globalTestMocks, keyPath);
expect(globalMock).toHaveBeenCalledWith(
'some test',
expect.any(Function),
10000,
);
});
});
});

Expand Down Expand Up @@ -278,6 +303,7 @@ describe('jest-each', () => {
expect(globalMock).toHaveBeenCalledWith(
'expected string',
expectFunction,
undefined,
);
});

Expand All @@ -292,6 +318,7 @@ describe('jest-each', () => {
expect(globalMock).toHaveBeenCalledWith(
'expected string',
expectFunction,
undefined,
);
});

Expand All @@ -309,10 +336,12 @@ describe('jest-each', () => {
expect(globalMock).toHaveBeenCalledWith(
'expected string: hello 1',
expectFunction,
undefined,
);
expect(globalMock).toHaveBeenCalledWith(
'expected string: world 2',
expectFunction,
undefined,
);
});
});
Expand Down
31 changes: 31 additions & 0 deletions packages/jest-each/src/__tests__/template.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ describe('jest-each', () => {
expect(globalMock).toHaveBeenCalledWith(
'expected string',
expectFunction,
undefined,
);
});

Expand All @@ -109,10 +110,12 @@ describe('jest-each', () => {
expect(globalMock).toHaveBeenCalledWith(
'expected string',
expectFunction,
undefined,
);
expect(globalMock).toHaveBeenCalledWith(
'expected string',
expectFunction,
undefined,
);
});

Expand All @@ -131,10 +134,12 @@ describe('jest-each', () => {
expect(globalMock).toHaveBeenCalledWith(
'expected string: a=0, b=1, expected=1',
expectFunction,
undefined,
);
expect(globalMock).toHaveBeenCalledWith(
'expected string: a=1, b=1, expected=2',
expectFunction,
undefined,
);
});

Expand All @@ -156,10 +161,12 @@ describe('jest-each', () => {
expect(globalMock).toHaveBeenCalledWith(
'add(0, 1) expected string: a=0, b=1, expected=1',
expectFunction,
undefined,
);
expect(globalMock).toHaveBeenCalledWith(
'add(1, 1) expected string: a=1, b=1, expected=2',
expectFunction,
undefined,
);
});

Expand All @@ -177,6 +184,7 @@ describe('jest-each', () => {
expect(globalMock).toHaveBeenCalledWith(
'interpolates object keyPath to value: "baz"',
expectFunction,
undefined,
);
});

Expand All @@ -194,6 +202,7 @@ describe('jest-each', () => {
expect(globalMock).toHaveBeenCalledWith(
'interpolates object keyPath to value: {"bar": "baz"}',
expectFunction,
undefined,
);
});

Expand Down Expand Up @@ -234,6 +243,23 @@ describe('jest-each', () => {
});
get(globalTestMocks, keyPath).mock.calls[0][1]('DONE');
});

test('calls global with given timeout', () => {
const globalTestMocks = getGlobalTestMocks();
const eachObject = each.withGlobal(globalTestMocks)`
a | b | expected
${0} | ${1} | ${1}
`;

const testFunction = get(eachObject, keyPath);
testFunction('some test', noop, 10000);
const globalMock = get(globalTestMocks, keyPath);
expect(globalMock).toHaveBeenCalledWith(
'some test',
expect.any(Function),
10000,
);
});
});
});

Expand Down Expand Up @@ -278,6 +304,7 @@ describe('jest-each', () => {
expect(globalMock).toHaveBeenCalledWith(
'expected string',
expectFunction,
undefined,
);
});

Expand All @@ -296,10 +323,12 @@ describe('jest-each', () => {
expect(globalMock).toHaveBeenCalledWith(
'expected string',
expectFunction,
undefined,
);
expect(globalMock).toHaveBeenCalledWith(
'expected string',
expectFunction,
undefined,
);
});

Expand All @@ -318,10 +347,12 @@ describe('jest-each', () => {
expect(globalMock).toHaveBeenCalledWith(
'expected string: a=0, b=1, expected=1',
expectFunction,
undefined,
);
expect(globalMock).toHaveBeenCalledWith(
'expected string: a=1, b=1, expected=2',
expectFunction,
undefined,
);
});
});
Expand Down
6 changes: 3 additions & 3 deletions packages/jest-each/src/bind.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ const PRETTY_PLACEHOLDER = '%p';
const INDEX_PLACEHOLDER = '%#';

export default (cb: Function) => (...args: any) =>
function eachBind(title: string, test: Function): void {
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]);
return table.forEach((row, i) =>
cb(arrayFormat(title, i, ...row), applyRestParams(row, test)),
cb(arrayFormat(title, i, ...row), applyRestParams(row, test), timeout),
);
}

Expand Down Expand Up @@ -66,7 +66,7 @@ export default (cb: Function) => (...args: any) =>
}

return table.forEach(row =>
cb(interpolate(title, row), applyObjectParams(row, test)),
cb(interpolate(title, row), applyObjectParams(row, test), timeout),
);
};

Expand Down
12 changes: 6 additions & 6 deletions packages/jest-each/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,22 @@ type GlobalCallbacks = {
};

const install = (g: GlobalCallbacks, ...args: Array<mixed>) => {
const test = (title: string, test: Function) =>
bind(g.test)(...args)(title, test);
const test = (title: string, test: Function, timeout: number) =>
bind(g.test)(...args)(title, test, timeout);
test.skip = bind(g.test.skip)(...args);
test.only = bind(g.test.only)(...args);

const it = (title: string, test: Function) =>
bind(g.it)(...args)(title, test);
const it = (title: string, test: Function, timeout: number) =>
bind(g.it)(...args)(title, test, timeout);
it.skip = bind(g.it.skip)(...args);
it.only = bind(g.it.only)(...args);

const xit = bind(g.xit)(...args);
const fit = bind(g.fit)(...args);
const xtest = bind(g.xtest)(...args);

const describe = (title: string, suite: Function) =>
bind(g.describe)(...args)(title, suite);
const describe = (title: string, suite: Function, timeout: number) =>
bind(g.describe)(...args)(title, suite, timeout);
describe.skip = bind(g.describe.skip)(...args);
describe.only = bind(g.describe.only)(...args);
const fdescribe = bind(g.fdescribe)(...args);
Expand Down
Loading

0 comments on commit ebaf934

Please sign in to comment.