Skip to content

Commit

Permalink
Merge branch 'master' into ts-jest-resolver
Browse files Browse the repository at this point in the history
  • Loading branch information
SimenB committed Feb 13, 2019
2 parents b909b2d + a4a04b2 commit b5dbcc1
Show file tree
Hide file tree
Showing 15 changed files with 409 additions and 326 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -2,9 +2,12 @@

### Features

- `[expect]`: Improve report when matcher fails, part 7 ([#7866](https://github.com/facebook/jest/pull/7866))

### Fixes

- `[jest-cli]` Refactor `-o` and `--coverage` combined ([#7611](https://github.com/facebook/jest/pull/7611))
- `[expect]` Fix custom async matcher stack trace ([#7652](https://github.com/facebook/jest/pull/7652))

### Chore & Maintenance

Expand All @@ -26,6 +29,7 @@
- `[jest-mock]`: Migrate to TypeScript ([#7847](https://github.com/facebook/jest/pull/7847), [#7850](https://github.com/facebook/jest/pull/7850))
- `[jest-worker]`: Migrate to TypeScript ([#7853](https://github.com/facebook/jest/pull/7853))
- `[jest-haste-map]`: Migrate to TypeScript ([#7854](https://github.com/facebook/jest/pull/7854))
- `[docs]`: Fix image paths in SnapshotTesting.md for current and version 24 ([#7872](https://github.com/facebook/jest/pull/7872))
- `[jest-resolve]`: Migrate to TypeScript ([#7871](https://github.com/facebook/jest/pull/7871))

### Performance
Expand Down
8 changes: 8 additions & 0 deletions CONTRIBUTING.md
Expand Up @@ -72,6 +72,14 @@ _Before_ submitting a pull request, please make sure the following is done…

1. If you haven't already, complete the CLA.

#### Changelog entries

All changes that add a feature to or fix a bug in any of Jest's packages require a changelog entry containing the names of the packages affected, a description of the change, and the number of and link to the pull request. Try to match the structure of the existing entries.

For significant changes to the documentation or website and things like cleanup, refactoring, and dependency updates, the "Chore & Maintenance" section of the changelog can be used.

You can add or edit the changelog entry in the GitHub web interface once you have opened the pull request and know the number and link to it.

#### Testing

Code that is written needs to be tested to ensure that it achieves the desired behaviour. Tests either fall into a unit test or an integration test.
Expand Down
11 changes: 5 additions & 6 deletions docs/SnapshotTesting.md
Expand Up @@ -41,8 +41,7 @@ exports[`renders correctly 1`] = `

The snapshot artifact should be committed alongside code changes, and reviewed as part of your code review process. Jest uses [pretty-format](https://github.com/facebook/jest/tree/master/packages/pretty-format) to make snapshots human-readable during code review. On subsequent test runs Jest will simply compare the rendered output with the previous snapshot. If they match, the test will pass. If they don't match, either the test runner found a bug in your code (in this case, it's `<Link>` component) that should be fixed, or the implementation has changed and the snapshot needs to be updated.

> Note: The snapshot is directly scoped to the data you render – in our example it's `<Link />` component with page prop passed to it. This implies that even if any other file has missing props (Say, `App.js`) in the `<Link />` component, it will still pass the test as the test doesn't know the usage of `<Link />` component and it's scoped only to the `Link.react.js`.
> Also, Rendering the same component with different props in other snapshot tests will not affect the first one, as the tests don't know about each other.
> Note: The snapshot is directly scoped to the data you render – in our example it's `<Link />` component with page prop passed to it. This implies that even if any other file has missing props (Say, `App.js`) in the `<Link />` component, it will still pass the test as the test doesn't know the usage of `<Link />` component and it's scoped only to the `Link.react.js`. Also, Rendering the same component with different props in other snapshot tests will not affect the first one, as the tests don't know about each other.
More information on how snapshot testing works and why we built it can be found on the [release blog post](https://jestjs.io/blog/2016/07/27/jest-14.html). We recommend reading [this blog post](http://benmccormick.org/2016/09/19/testing-with-jest-snapshots-first-impressions/) to get a good sense of when you should use snapshot testing. We also recommend watching this [egghead video](https://egghead.io/lessons/javascript-use-jest-s-snapshot-testing-feature?pl=testing-javascript-with-jest-a36c4074) on Snapshot Testing with Jest.

Expand All @@ -64,7 +63,7 @@ it('renders correctly', () => {

In that case, Jest will print this output:

![](/website/static/img/content/failedSnapshotTest.png)
![](/img/content/failedSnapshotTest.png)

Since we just updated our component to point to a different address, it's reasonable to expect changes in the snapshot for this component. Our snapshot test case is failing because the snapshot for our updated component no longer matches the snapshot artifact for this test case.

Expand All @@ -84,17 +83,17 @@ You can try out this functionality by cloning the [snapshot example](https://git

Failed snapshots can also be updated interactively in watch mode:

![](/website/static/img/content/interactiveSnapshot.png)
![](/img/content/interactiveSnapshot.png)

Once you enter Interactive Snapshot Mode, Jest will step you through the failed snapshots one test at a time and give you the opportunity to review the failed output.

From here you can choose to update that snapshot or skip to the next:

![](/website/static/img/content/interactiveSnapshotUpdate.gif)
![](/img/content/interactiveSnapshotUpdate.gif)

Once you're finished, Jest will give you a summary before returning back to watch mode:

![](/website/static/img/content/interactiveSnapshotDone.png)
![](/img/content/interactiveSnapshotDone.png)

### Inline Snapshots

Expand Down
33 changes: 26 additions & 7 deletions e2e/__tests__/__snapshots__/customMatcherStackTrace.test.js.snap
@@ -1,7 +1,26 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`custom async matchers 1`] = `
FAIL __tests__/asynchronous.test.js
✕ showing the stack trace for an async matcher
● showing the stack trace for an async matcher
We expect the stack trace and code fence for this matcher to be shown in the console.
9 |
10 | test('showing the stack trace for an async matcher', async () => {
> 11 | await expect(true).toThrowCustomAsyncMatcherError();
| ^
12 | });
13 |
14 | async function toThrowCustomAsyncMatcherError() {
at Object.toThrowCustomAsyncMatcherError (__tests__/asynchronous.test.js:11:22)
`;
exports[`works with custom matchers 1`] = `
FAIL __tests__/customMatcher.test.js
FAIL __tests__/sync.test.js
Custom matcher
passes
fails
Expand All @@ -19,10 +38,10 @@ FAIL __tests__/customMatcher.test.js
47 |
48 | // This expecation fails due to an error we throw (intentionally)
at Error (__tests__/customMatcher.test.js:45:13)
at baz (__tests__/customMatcher.test.js:43:23)
at bar (__tests__/customMatcher.test.js:42:23)
at foo (__tests__/customMatcher.test.js:52:7)
at Object.callback (__tests__/customMatcher.test.js:11:18)
at Object.toCustomMatch (__tests__/customMatcher.test.js:53:8)
at Error (__tests__/sync.test.js:45:13)
at baz (__tests__/sync.test.js:43:23)
at bar (__tests__/sync.test.js:42:23)
at foo (__tests__/sync.test.js:52:7)
at Object.callback (__tests__/sync.test.js:11:18)
at Object.toCustomMatch (__tests__/sync.test.js:53:8)
`;
80 changes: 45 additions & 35 deletions e2e/__tests__/__snapshots__/expectAsyncMatcher.test.js.snap
Expand Up @@ -10,22 +10,40 @@ FAIL __tests__/failure.test.js
● fail with expected non promise values
Expected value to have length:
2
Received:
1
received.length:
1
11 |
12 | it('fail with expected non promise values', () =>
> 13 | expect([1]).toHaveLengthAsync(Promise.resolve(2)));
| ^
14 |
15 | it('fail with expected non promise values and not', () =>
16 | expect([1, 2]).not.toHaveLengthAsync(Promise.resolve(2)));
2
Received:
1
received.length:
1
at Object.toHaveLengthAsync (__tests__/failure.test.js:13:15)
● fail with expected non promise values and not
Expected value to not have length:
2
Received:
1,2
received.length:
2
14 |
15 | it('fail with expected non promise values and not', () =>
> 16 | expect([1, 2]).not.toHaveLengthAsync(Promise.resolve(2)));
| ^
17 |
18 | it('fail with expected promise values', () =>
19 | expect(Promise.resolve([1])).resolves.toHaveLengthAsync(Promise.resolve(2)));
2
Received:
1,2
received.length:
2
at Object.toHaveLengthAsync (__tests__/failure.test.js:16:22)
● fail with expected promise values
Expand All @@ -36,19 +54,15 @@ FAIL __tests__/failure.test.js
received.length:
1
22 |
23 | it('fail with expected promise values', async () => {
> 24 | await (expect(Promise.resolve([1])): any).resolves.toHaveLengthAsync(
| ^
25 | Promise.resolve(2)
26 | );
27 | });
17 |
18 | it('fail with expected promise values', () =>
> 19 | expect(Promise.resolve([1])).resolves.toHaveLengthAsync(Promise.resolve(2)));
| ^
20 |
21 | it('fail with expected promise values and not', () =>
22 | expect(Promise.resolve([1, 2])).resolves.not.toHaveLengthAsync(
at Object.toHaveLengthAsync (__tests__/failure.test.js:24:54)
at asyncGeneratorStep (__tests__/failure.test.js:11:103)
at _next (__tests__/failure.test.js:13:194)
at __tests__/failure.test.js:13:364
at Object.<anonymous> (__tests__/failure.test.js:13:97)
at Object.toHaveLengthAsync (__tests__/failure.test.js:19:41)
● fail with expected promise values and not
Expand All @@ -59,17 +73,13 @@ FAIL __tests__/failure.test.js
received.length:
2
28 |
29 | it('fail with expected promise values and not', async () => {
> 30 | await (expect(Promise.resolve([1, 2])).resolves.not: any).toHaveLengthAsync(
| ^
31 | Promise.resolve(2)
32 | );
33 | });
at Object.toHaveLengthAsync (__tests__/failure.test.js:30:61)
at asyncGeneratorStep (__tests__/failure.test.js:11:103)
at _next (__tests__/failure.test.js:13:194)
at __tests__/failure.test.js:13:364
at Object.<anonymous> (__tests__/failure.test.js:13:97)
20 |
21 | it('fail with expected promise values and not', () =>
> 22 | expect(Promise.resolve([1, 2])).resolves.not.toHaveLengthAsync(
| ^
23 | Promise.resolve(2)
24 | ));
25 |
at Object.toHaveLengthAsync (__tests__/failure.test.js:22:48)
`;
12 changes: 11 additions & 1 deletion e2e/__tests__/customMatcherStackTrace.test.js
Expand Up @@ -12,7 +12,7 @@ import {extractSummary} from '../Utils';
import {wrap} from 'jest-snapshot-serializer-raw';

test('works with custom matchers', () => {
const {stderr} = runJest('custom-matcher-stack-trace');
const {stderr} = runJest('custom-matcher-stack-trace', ['sync.test.js']);

let {rest} = extractSummary(stderr);

Expand All @@ -23,3 +23,13 @@ test('works with custom matchers', () => {

expect(wrap(rest)).toMatchSnapshot();
});

test('custom async matchers', () => {
const {stderr} = runJest('custom-matcher-stack-trace', [
'asynchronous.test.js',
]);

const {rest} = extractSummary(stderr);

expect(wrap(rest)).toMatchSnapshot();
});
18 changes: 18 additions & 0 deletions e2e/custom-matcher-stack-trace/__tests__/asynchronous.test.js
@@ -0,0 +1,18 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. 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.
*/

expect.extend({toThrowCustomAsyncMatcherError});

test('showing the stack trace for an async matcher', async () => {
await expect(true).toThrowCustomAsyncMatcherError();
});

async function toThrowCustomAsyncMatcherError() {
const message = () =>
'We expect the stack trace and code fence for this matcher to be shown in the console.';
return {message, pass: false};
}
29 changes: 10 additions & 19 deletions e2e/expect-async-matcher/__tests__/failure.test.js
Expand Up @@ -4,30 +4,21 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';

import {toHaveLengthAsync} from '../matchers';

expect.extend({
toHaveLengthAsync,
});
expect.extend({toHaveLengthAsync});

it('fail with expected non promise values', async () => {
await (expect([1]): any).toHaveLengthAsync(Promise.resolve(2));
});
it('fail with expected non promise values', () =>
expect([1]).toHaveLengthAsync(Promise.resolve(2)));

it('fail with expected non promise values and not', async () => {
await (expect([1, 2]): any).not.toHaveLengthAsync(Promise.resolve(2));
});
it('fail with expected non promise values and not', () =>
expect([1, 2]).not.toHaveLengthAsync(Promise.resolve(2)));

it('fail with expected promise values', async () => {
await (expect(Promise.resolve([1])): any).resolves.toHaveLengthAsync(
Promise.resolve(2)
);
});
it('fail with expected promise values', () =>
expect(Promise.resolve([1])).resolves.toHaveLengthAsync(Promise.resolve(2)));

it('fail with expected promise values and not', async () => {
await (expect(Promise.resolve([1, 2])).resolves.not: any).toHaveLengthAsync(
it('fail with expected promise values and not', () =>
expect(Promise.resolve([1, 2])).resolves.not.toHaveLengthAsync(
Promise.resolve(2)
);
});
));
29 changes: 10 additions & 19 deletions e2e/expect-async-matcher/__tests__/success.test.js
Expand Up @@ -4,30 +4,21 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';

import {toHaveLengthAsync} from '../matchers';

expect.extend({
toHaveLengthAsync,
});
expect.extend({toHaveLengthAsync});

it('works with expected non promise values', async () => {
await (expect([1]): any).toHaveLengthAsync(Promise.resolve(1));
});
it('works with expected non promise values', () =>
expect([1]).toHaveLengthAsync(Promise.resolve(1)));

it('works with expected non promise values and not', async () => {
await (expect([1, 2]): any).not.toHaveLengthAsync(Promise.resolve(1));
});
it('works with expected non promise values and not', () =>
expect([1, 2]).not.toHaveLengthAsync(Promise.resolve(1)));

it('works with expected promise values', async () => {
await (expect(Promise.resolve([1])).resolves: any).toHaveLengthAsync(
Promise.resolve(1)
);
});
it('works with expected promise values', () =>
expect(Promise.resolve([1])).resolves.toHaveLengthAsync(Promise.resolve(1)));

it('works with expected promise values and not', async () => {
await (expect(Promise.resolve([1, 2])).resolves.not: any).toHaveLengthAsync(
it('works with expected promise values and not', () =>
expect(Promise.resolve([1, 2])).resolves.not.toHaveLengthAsync(
Promise.resolve(1)
);
});
));

0 comments on commit b5dbcc1

Please sign in to comment.