Skip to content

Commit

Permalink
Add test.todo (#6996)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattphillips authored and SimenB committed Sep 29, 2018
1 parent 15b43d6 commit 49b2380
Show file tree
Hide file tree
Showing 29 changed files with 416 additions and 28 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

### Features

- `[jest-jasmine2/jest-circus/jest-cli]` Add test.todo ([#6996](https://github.com/facebook/jest/pull/6996))
- `[pretty-format]` Option to not escape strings in diff messages ([#5661](https://github.com/facebook/jest/pull/5661))
- `[jest-haste-map]` Add `getFileIterator` to `HasteFS` for faster file iteration ([#7010](https://github.com/facebook/jest/pull/7010)).
- `[jest-worker]` [**BREAKING**] Add functionality to call a `setup` method in the worker before the first call and a `teardown` method when ending the farm ([#7014](https://github.com/facebook/jest/pull/7014)).
Expand Down
18 changes: 18 additions & 0 deletions docs/GlobalAPI.md
Original file line number Diff line number Diff line change
Expand Up @@ -655,3 +655,21 @@ test('will be ran', () => {
expect(1 / 0).toBe(Infinity);
});
```

### `test.todo(name)`

Use `test.todo` when you are planning on writing tests. These tests will be highlighted in the summary output at the end so you know how many tests you still need todo.

_Note_: If you supply a test callback function then the `test.todo` will throw an error. If you have already implemented the test and it is broken and you do not want it to run, then use `test.skip` instead.

#### API

- `name`: `String` the title of the test plan.

Example:

```js
const add = (a, b) => a + b;

test.todo('add should be associative');
```
4 changes: 2 additions & 2 deletions e2e/__tests__/__snapshots__/globals.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ exports[`cannot test with no implementation 1`] = `
"FAIL __tests__/only-constructs.test.js
● Test suite failed to run
Missing second argument. It must be a callback function.
Missing second argument. It must be a callback function. Perhaps you want to use \`test.todo\` for a test placeholder.
1 |
2 | it('it', () => {});
Expand All @@ -50,7 +50,7 @@ exports[`cannot test with no implementation with expand arg 1`] = `
"FAIL __tests__/only-constructs.test.js
● Test suite failed to run
Missing second argument. It must be a callback function.
Missing second argument. It must be a callback function. Perhaps you want to use \`test.todo\` for a test placeholder.
1 |
2 | it('it', () => {});
Expand Down
79 changes: 79 additions & 0 deletions e2e/__tests__/__snapshots__/test-todo.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`shows error messages when called with invalid argument 1`] = `
"FAIL __tests__/todo_non_string.test.js
● Test suite failed to run
Todo must be called with only a description.
6 | */
7 |
> 8 | it.todo(() => {});
| ^
9 |
at __tests__/todo_non_string.test.js:8:4
"
`;

exports[`shows error messages when called with multiple arguments 1`] = `
"FAIL __tests__/todo_multiple_args.test.js
● Test suite failed to run
Todo must be called with only a description.
6 | */
7 |
> 8 | it.todo('todo later', () => {});
| ^
9 |
at __tests__/todo_multiple_args.test.js:8:4
"
`;

exports[`shows error messages when called with no arguments 1`] = `
"FAIL __tests__/todo_no_args.test.js
● Test suite failed to run
Todo must be called with only a description.
6 | */
7 |
> 8 | it.todo();
| ^
9 |
at __tests__/todo_no_args.test.js:8:4
"
`;

exports[`works with all statuses 1`] = `
"FAIL __tests__/statuses.test.js
✓ passes
✕ fails
○ skipped 1 test
✎ todo 1 test
● fails
expect(received).toBe(expected) // Object.is equality
Expected: 101
Received: 10
11 |
12 | it('fails', () => {
> 13 | expect(10).toBe(101);
| ^
14 | });
15 |
16 | it.skip('skips', () => {
at __tests__/statuses.test.js:13:14
"
`;
43 changes: 43 additions & 0 deletions e2e/__tests__/test-todo.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* Copyright (c) 2018-present, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

'use strict';

const path = require('path');
const runJest = require('../runJest');
const {extractSummary} = require('../Utils');
const dir = path.resolve(__dirname, '../test-todo');

test('works with all statuses', () => {
const result = runJest(dir, ['statuses.test.js']);
expect(result.status).toBe(1);
const {rest} = extractSummary(result.stderr);
expect(rest).toMatchSnapshot();
});

test('shows error messages when called with no arguments', () => {
const result = runJest(dir, ['todo_no_args.test.js']);
expect(result.status).toBe(1);
const {rest} = extractSummary(result.stderr);
expect(rest).toMatchSnapshot();
});

test('shows error messages when called with multiple arguments', () => {
const result = runJest(dir, ['todo_multiple_args.test.js']);
expect(result.status).toBe(1);
const {rest} = extractSummary(result.stderr);
expect(rest).toMatchSnapshot();
});

test('shows error messages when called with invalid argument', () => {
const result = runJest(dir, ['todo_non_string.test.js']);
expect(result.status).toBe(1);
const {rest} = extractSummary(result.stderr);
expect(rest).toMatchSnapshot();
});
20 changes: 20 additions & 0 deletions e2e/test-todo/__tests__/statuses.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Copyright (c) 2018-present, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

it('passes', () => {
expect(10).toBe(10);
});

it('fails', () => {
expect(10).toBe(101);
});

it.skip('skips', () => {
expect(10).toBe(101);
});

it.todo('todo');
8 changes: 8 additions & 0 deletions e2e/test-todo/__tests__/todo_multiple_args.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* Copyright (c) 2018-present, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

it.todo('todo later', () => {});
8 changes: 8 additions & 0 deletions e2e/test-todo/__tests__/todo_no_args.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* Copyright (c) 2018-present, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

it.todo();
8 changes: 8 additions & 0 deletions e2e/test-todo/__tests__/todo_non_string.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* Copyright (c) 2018-present, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

it.todo(() => {});
5 changes: 5 additions & 0 deletions e2e/test-todo/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"jest": {
"testEnvironment": "node"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ describe('test/it error throwing', () => {
expect(() => {
// $FlowFixMe: Easy, we're testing runitme errors here
circusIt('test2');
}).toThrowError('Missing second argument. It must be a callback function.');
}).toThrowError(
'Missing second argument. It must be a callback function. Perhaps you want to use `test.todo` for a test placeholder.',
);
});
it(`it throws an error when first argument isn't a string`, () => {
expect(() => {
Expand All @@ -62,7 +64,9 @@ describe('test/it error throwing', () => {
expect(() => {
// $FlowFixMe: Easy, we're testing runitme errors here
circusTest('test6');
}).toThrowError('Missing second argument. It must be a callback function.');
}).toThrowError(
'Missing second argument. It must be a callback function. Perhaps you want to use `test.todo` for a test placeholder.',
);
});
it(`test throws an error when first argument isn't a string`, () => {
expect(() => {
Expand Down
42 changes: 42 additions & 0 deletions packages/jest-circus/src/__tests__/circus_todo_test_error.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* Copyright (c) 2015-present, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
*/

'use strict';

let circusIt;

// using jest-jasmine2's 'it' to test jest-circus's 'it'. Had to differentiate
// the two with this alias.

const aliasCircusIt = () => {
const {it} = require('../index.js');
circusIt = it;
};

aliasCircusIt();

describe('test/it.todo error throwing', () => {
it('todo throws error when given no arguments', () => {
expect(() => {
// $FlowFixMe: Testing runitme errors here
circusIt.todo();
}).toThrowError('Todo must be called with only a description.');
});
it('todo throws error when given more than one argument', () => {
expect(() => {
circusIt.todo('test1', () => {});
}).toThrowError('Todo must be called with only a description.');
});
it('todo throws error when given none string description', () => {
expect(() => {
// $FlowFixMe: Testing runitme errors here
circusIt.todo(() => {});
}).toThrowError('Todo must be called with only a description.');
});
});
4 changes: 4 additions & 0 deletions packages/jest-circus/src/event_handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ const handler: EventHandler = (event, state): void => {
event.test.status = 'skip';
break;
}
case 'test_todo': {
event.test.status = 'todo';
break;
}
case 'test_done': {
event.test.duration = getTestDuration(event.test);
event.test.status = 'done';
Expand Down
30 changes: 29 additions & 1 deletion packages/jest-circus/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ const test = (testName: TestName, fn: TestFn, timeout?: number) => {
);
}
if (fn === undefined) {
throw new Error('Missing second argument. It must be a callback function.');
throw new Error(
'Missing second argument. It must be a callback function. Perhaps you want to use `test.todo` for a test placeholder.',
);
}
if (typeof fn !== 'function') {
throw new Error(
Expand Down Expand Up @@ -121,6 +123,32 @@ test.only = (testName: TestName, fn: TestFn, timeout?: number) => {
});
};

test.todo = (testName: TestName, ...rest: Array<mixed>) => {
if (rest.length > 0 || typeof testName !== 'string') {
const e = new Error('Todo must be called with only a description.');

if (Error.captureStackTrace) {
Error.captureStackTrace(e, test.todo);
}

throw e;
}

const asyncError = new Error();
if (Error.captureStackTrace) {
Error.captureStackTrace(asyncError, test);
}

return dispatch({
asyncError,
fn: () => {},
mode: 'todo',
name: 'add_test',
testName,
timeout: undefined,
});
};

test.each = bindEach(test);
test.only.each = bindEach(test.only);
test.skip.each = bindEach(test.skip);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,16 @@ export const runAndTransformResultsToJestFormat = async ({
let numFailingTests = 0;
let numPassingTests = 0;
let numPendingTests = 0;
let numTodoTests = 0;

const assertionResults = runResult.testResults.map(testResult => {
let status: Status;
if (testResult.status === 'skip') {
status = 'pending';
numPendingTests += 1;
} else if (testResult.status === 'todo') {
status = 'todo';
numTodoTests += 1;
} else if (testResult.errors.length) {
status = 'failed';
numFailingTests += 1;
Expand Down Expand Up @@ -190,6 +194,7 @@ export const runAndTransformResultsToJestFormat = async ({
numFailingTests,
numPassingTests,
numPendingTests,
numTodoTests,
openHandles: [],
perfStats: {
// populated outside
Expand Down
5 changes: 5 additions & 0 deletions packages/jest-circus/src/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ const _runTest = async (test: TestEntry): Promise<void> => {
return;
}

if (test.mode === 'todo') {
dispatch({name: 'test_todo', test});
return;
}

const {afterEach, beforeEach} = getEachHooksForTest(test);

for (const hook of beforeEach) {
Expand Down
1 change: 1 addition & 0 deletions packages/jest-cli/src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const ICONS = {
failed: isWindows ? '\u00D7' : '\u2715',
pending: '\u25CB',
success: isWindows ? '\u221A' : '\u2713',
todo: '\u270E',
};
export const PACKAGE_JSON = 'package.json';
export const JEST_CONFIG = 'jest.config.js';
Loading

0 comments on commit 49b2380

Please sign in to comment.