Skip to content

Commit

Permalink
Allow it to return <Promise>
Browse files Browse the repository at this point in the history
Summary:
to review: `jest-utils/jasmine-pit` and `__integration_tests_/promise_it/**`

It does not work with jasmine1 yet. If the direction is ok i'll add jasmine1 support to this PR.
Closes #970

Reviewed By: dmitriiabramov

Differential Revision: D3309064

fbshipit-source-id: ff597945554e8cad4f2add8232236429810a966c
  • Loading branch information
Dmitrii Abramov authored and Facebook Github Bot 3 committed May 17, 2016
1 parent 08a5cdd commit 644a512
Show file tree
Hide file tree
Showing 27 changed files with 425 additions and 123 deletions.
1 change: 0 additions & 1 deletion docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ Jest uses Jasmine 2 by default. An introduction to Jasmine 2 can be found
- `it(name, fn)`
- `fit(name, fn)` executes only this test. Useful when investigating a failure
- [`jest`](#the-jest-object)
- `pit(name, fn)` [async helper](/jest/docs/tutorial-async.html) for promises
- `require(module)`
- `require.requireActual(module)`
- `xdescribe(name, fn)`
Expand Down
8 changes: 3 additions & 5 deletions docs/GettingStarted.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,7 @@ project.

#### Async testing

Promises and even async/await can be tested easily. Jest provides a helper
called `pit` for any kind of async interaction.
Promises and even async/await can be tested easily.

Assume a `user.getUserName` function that returns a promise, now consider this
async test with Babel and
Expand All @@ -149,14 +148,13 @@ jest.unmock('../user');
import * as user from '../user';

describe('async tests', () => {
// Use `pit` instead of `it` for testing promises.
// The promise that is being tested should be returned.
pit('works with promises', () => {
it('works with promises', () => {
return user.getUserName(5)
.then(name => expect(name).toEqual('Paul'));
});

pit('works with async/await', async () => {
it('works with async/await', async () => {
const userName = await user.getUserName(4);
expect(userName).toEqual('Mark');
});
Expand Down
16 changes: 7 additions & 9 deletions docs/TutorialAsync.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,36 +69,34 @@ export default function request(url) {
}
```

Now let's write a test for our async functionality. Jest provides the `pit`
wrapper to test Promise based code or async/await:
Now let's write a test for our async functionality.
```js
// __tests__/user-test.js
jest.unmock('../user');

import * as user from '../user';

describe('async tests', () => {
// Use `pit` instead of `it` for testing promises.
// The promise that is being tested should be returned.
pit('works with promises', () => {
it('works with promises', () => {
return user.getUserName(5)
.then(name => expect(name).toEqual('Paul'));
});
});
```

`pit` expects the return value to be a Promise that is going to be resolved.
`it` expects the return value to be a Promise that is going to be resolved.
You can chain as many Promises as you like and call `expect` at any time, as
long as you return a Promise at the end.

### `async`/`await`

Writing tests using the `async`/`await` syntax is easy with `pit`. Here is
Writing tests using the `async`/`await` syntax is easy. Here is
how you'd write the same example from before:

```js
// async/await can also be used.
pit('works with async/await', async () => {
it('works with async/await', async () => {
const userName = await user.getUserName(4);
expect(userName).toEqual('Mark');
});
Expand All @@ -117,15 +115,15 @@ if a Promise throws and the error is not handled, the test will fail.

```js
// Testing for async errors can be done using `catch`.
pit('tests error with promises', () => {
it('tests error with promises', () => {
return user.getUserName(3)
.catch(e => expect(e).toEqual({
error: 'User with 3 not found.',
}));
});

// Or try-catch.
pit('tests error with async/await', async () => {
it('tests error with async/await', async () => {
try {
await user.getUserName(2);
} catch (object) {
Expand Down
8 changes: 4 additions & 4 deletions examples/async/__tests__/user-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,27 @@ import * as user from '../user';
describe('async tests', () => {
// Use `pit` instead of `it` for testing promises.
// The promise that is being tested should be returned.
pit('works with promises', () => {
it('works with promises', () => {
return user.getUserName(5)
.then(name => expect(name).toEqual('Paul'));
});

// async/await can also be used.
pit('works with async/await', async () => {
it('works with async/await', async () => {
const userName = await user.getUserName(4);
expect(userName).toEqual('Mark');
});

// Testing for async errors can be done using `catch`.
pit('tests error with promises', () => {
it('tests error with promises', () => {
return user.getUserName(3)
.catch(e => expect(e).toEqual({
error: 'User with 3 not found.',
}));
});

// Or try-catch.
pit('tests error with async/await', async () => {
it('tests error with async/await', async () => {
try {
await user.getUserName(2);
} catch (object) {
Expand Down
69 changes: 69 additions & 0 deletions integration_tests/__tests__/promise_it-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/

'use strict';

jest.unmock('../runJest');

const runJest = require('../runJest');

describe('promise it', () => {
it('works with fit', () => {
const result = runJest.json('promise_it', ['promise_fit-test.js']);
const json = result.json;

expect(json.numTotalTests).toBe(3);
expect(json.numPassedTests).toBe(1);
expect(json.numFailedTests).toBe(1);
expect(json.numPendingTests).toBe(1);
expect(json.testResults[0].message).toMatch(/will run and fail/);
});

it('works with xit', () => {
const result = runJest.json('promise_it', ['promise_xit-test.js']);
const json = result.json;

expect(json.numTotalTests).toBe(2);
expect(json.numPassedTests).toBe(1);
expect(json.numFailedTests).toBe(0);
expect(json.numPendingTests).toBe(1);
});

it('throws when not a promise is returned', () => {
const result = runJest.json('promise_it', ['returning_values-test.js']);
const json = result.json;

expect(json.numTotalTests).toBe(11);
expect(json.numPassedTests).toBe(0);
expect(json.numFailedTests).toBe(11);
expect(json.numPendingTests).toBe(0);
});

it('tests async promise code', () => {
const result = runJest.json('promise_it', ['promise_it-test.js']);
const json = result.json;
const message = json.testResults[0].message;

expect(json.numTotalTests).toBe(7);
expect(json.numPassedTests).toBe(4);
expect(json.numFailedTests).toBe(3);

expect(message).toMatch('fails if promise is rejected');
expect(message).toMatch('works with done.fail');
expect(message).toMatch('fails a sync test');
});

it('works with pit', () => {
const result = runJest.json('promise_it', ['pit-test.js']);
const json = result.json;
expect(json.numTotalTests).toBe(2);
expect(json.numPassedTests).toBe(1);
expect(json.numFailedTests).toBe(1);
expect(json.testResults[0].message).toMatch(/will run and fail/);
});
});
19 changes: 19 additions & 0 deletions integration_tests/promise_it/__tests__/pit-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/

'use strict';

describe('pit alias', () => {
pit('will run', () => {
return Promise.resolve();
});

pit('will run and fail', () => {
return Promise.reject();
});
});
23 changes: 23 additions & 0 deletions integration_tests/promise_it/__tests__/promise_fit-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/

'use strict';

describe('promise fit', () => {
it('fails but will be skipped', () => {
expect(true).toBe(false);
});

fit('will run', () => {
return Promise.resolve();
});

fit('will run and fail', () => {
return Promise.reject();
});
});
50 changes: 50 additions & 0 deletions integration_tests/promise_it/__tests__/promise_it-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/

'use strict';

describe('promise it', () => {
beforeEach(() => {
this.someContextValue = 'value';
});

// passing tests
it('passes a sync test', () => {
expect(1).toBe(1);
});

it('waits for promise to be resolved', () => {
return Promise.resolve();
});

it('works with done', done => {
done();
});

it('is bount to context object', () => {
return new Promise(resolve => {
if (this.someContextValue !== 'value') {
throw new Error('expected this.someContextValue to be set', this.someContextValue);
}
resolve();
});
});

// failing tests
it('fails if promise is rejected', () => {
return Promise.reject(new Error('rejected promise returned'));
});

it('works with done.fail', done => {
done.fail(new Error('done.fail was called'));
});

it('fails a sync test', () => {
expect('sync').toBe('failed');
});
});
19 changes: 19 additions & 0 deletions integration_tests/promise_it/__tests__/promise_xit-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/

'use strict';

describe('promise xit', () => {
xit('fails but will be skipped', () => {
expect(true).toBe(false);
});

it('will run', () => {
return Promise.resolve();
});
});
18 changes: 18 additions & 0 deletions integration_tests/promise_it/__tests__/returning_values-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/

'use strict';

describe('returning values', () => {
[1, 'string', 0.1, null, NaN, Infinity, true, false, [1], {}, () => {}]
.forEach(val => {
it(`throws if '${val}:${typeof val}' is returned`, () => {
return val;
});
});
});
1 change: 1 addition & 0 deletions integration_tests/promise_it/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
12 changes: 11 additions & 1 deletion integration_tests/runJest.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,18 @@ const JEST_PATH = path.resolve(__dirname, '../packages/jest-cli/bin/jest.js');
// return the result of the spawned proccess:
// [ 'status', 'signal', 'output', 'pid', 'stdout', 'stderr',
// 'envPairs', 'options', 'args', 'file' ]
module.exports = function runJest(dir, args) {
function runJest(dir, args) {
return spawnSync(JEST_PATH, args || [], {
cwd: path.resolve(__dirname, dir),
});
}

// Runs `jest` with `--json` option and adds `json` property to the result obj.
runJest.json = function(dir, args) {
args = Array.prototype.concat(args || [], '--json');
const result = runJest(dir, args);
result.json = JSON.parse((result.stdout || '').toString());
return result;
};

module.exports = runJest;
8 changes: 4 additions & 4 deletions packages/jest-cli/src/__tests__/TestRunner-fs-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe('TestRunner-fs', () => {

describe('testPathsMatching', () => {

pit('finds tests with default file extensions', () => {
it('finds tests with default file extensions', () => {
const rootDir = path.resolve(__dirname, 'test_root');
const runner = new TestRunner(normalizeConfig({
cacheDirectory: global.CACHE_DIRECTORY,
Expand All @@ -37,7 +37,7 @@ describe('TestRunner-fs', () => {
});
});

pit('finds tests with similar but custom file extensions', () => {
it('finds tests with similar but custom file extensions', () => {
const rootDir = path.resolve(__dirname, 'test_root');
const runner = new TestRunner(normalizeConfig({
cacheDirectory: global.CACHE_DIRECTORY,
Expand All @@ -54,7 +54,7 @@ describe('TestRunner-fs', () => {
});
});

pit('finds tests with totally custom foobar file extensions', () => {
it('finds tests with totally custom foobar file extensions', () => {
const rootDir = path.resolve(__dirname, 'test_root');
const runner = new TestRunner(normalizeConfig({
cacheDirectory: global.CACHE_DIRECTORY,
Expand All @@ -71,7 +71,7 @@ describe('TestRunner-fs', () => {
});
});

pit('finds tests with many kinds of file extensions', () => {
it('finds tests with many kinds of file extensions', () => {
const rootDir = path.resolve(__dirname, 'test_root');
const runner = new TestRunner(normalizeConfig({
cacheDirectory: global.CACHE_DIRECTORY,
Expand Down
Loading

0 comments on commit 644a512

Please sign in to comment.