Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] Inline Snapshots #6380

Merged
merged 34 commits into from
Jun 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
fed959f
[RFC] Inline Snapshots
azz Jun 2, 2018
c639484
Fix typechecking and refactor
azz Jun 2, 2018
396b20b
Refactor State#match
azz Jun 2, 2018
2816e7d
Fix stacktrace regression
azz Jun 2, 2018
a215e16
Remove unused argument
azz Jun 2, 2018
8c821a1
Fix support for property matchers
azz Jun 2, 2018
bbe79ba
Fix tests after State#match refactor
azz Jun 2, 2018
d5d349b
Fix toThrowErrorMatchingInlineSnapshot
azz Jun 2, 2018
190df70
Optimize snapshot lookup
azz Jun 3, 2018
05f94df
Support flow parser
azz Jun 3, 2018
eb6d86d
Relax prettier version requirement
azz Jun 3, 2018
14b8b90
Fix TypeScript support
azz Jun 3, 2018
af1696e
Support toMatchInlineSnapshot from external files
azz Jun 3, 2018
91e3482
Add tests for saveInlineSnapshots()
azz Jun 3, 2018
8334b6f
Fix InlineSnapshot type definition
azz Jun 3, 2018
80f75ee
Escape backtick strings
azz Jun 5, 2018
b3f462d
Add test for escaping backticks
azz Jun 6, 2018
8ed6096
Code review fixes
azz Jun 7, 2018
c07788a
Support project option for prettier
azz Jun 9, 2018
657f10e
Refactor configuration
azz Jun 9, 2018
97c054a
Fix typechecking
azz Jun 9, 2018
6537c33
Set default value in cli/options
azz Jun 9, 2018
51c42ef
Fix typechecking
azz Jun 9, 2018
cc0bcdd
Write E2E tests for toMatchInlineSnapshot
azz Jun 9, 2018
58e6f59
Fix bad copy/paste
azz Jun 9, 2018
e1ffa94
Parameterize saveInlineSnapshots test with jest-each
azz Jun 10, 2018
408bad4
Write E2E tests for toThrowErrorMatchingInlineSnapshot
azz Jun 10, 2018
3f6531b
Write more aync tests
azz Jun 10, 2018
8c9a441
Skip currently failing test
azz Jun 10, 2018
52740e1
Remove unused testPath property from State
azz Jun 10, 2018
dcbaec8
Write documentation
azz Jun 10, 2018
436cd7f
Support async matchers
azz Jun 12, 2018
f653fdf
Fix links in docs
azz Jun 12, 2018
5f89615
Merge branch 'master' into jest-inline-snapshots
azz Jun 27, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
## master

### Features

- `[jest-snapshot]` Introduce `toMatchInlineSnapshot` and `toThrowErrorMatchingInlineSnapshot` matchers ([#6380](https://github.com/facebook/jest/pull/6380))

### Chore & Maintenance

- `[website]` Switch domain to https://jestjs.io ([#6549](https://github.com/facebook/jest/pull/6549))
Expand Down
1 change: 1 addition & 0 deletions TestUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ const DEFAULT_PROJECT_CONFIG: ProjectConfig = {
modulePathIgnorePatterns: [],
modulePaths: [],
name: 'test_name',
prettier: 'prettier',
resetMocks: false,
resetModules: false,
resolver: null,
Expand Down
6 changes: 6 additions & 0 deletions docs/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,12 @@ Presets may also be relative filesystem paths.
}
```

### `prettier` [string]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prettierPath? Not sure


Default: `'prettier'`

Sets the path to the [`prettier`](https://prettier.io/) node module used to update inline snapshots.

### `projects` [array<string | ProjectConfig>]

Default: `undefined`
Expand Down
14 changes: 13 additions & 1 deletion docs/ExpectAPI.md
Original file line number Diff line number Diff line change
Expand Up @@ -1025,12 +1025,18 @@ test('this house has my desired features', () => {

This ensures that a value matches the most recent snapshot. Check out [the Snapshot Testing guide](SnapshotTesting.md) for more information.

The optional propertyMatchers argument allows you to specify asymmetric matchers which are verified instead of the exact values.
The optional `propertyMatchers` argument allows you to specify asymmetric matchers which are verified instead of the exact values.

The last argument allows you option to specify a snapshot name. Otherwise, the name is inferred from the test.

_Note: While snapshot testing is most commonly used with React components, any serializable value can be used as a snapshot._

### `.toMatchInlineSnapshot(propertyMatchers, inlineSnapshot)`

Ensures that a value matches the most recent snapshot. Unlike [`.toMatchSnapshot()`](#tomatchsnapshotpropertymatchers-snapshotname), the snapshots will be written to the current source file, inline.

Check out the section on [Inline Snapshots](./SnapshotTesting.md#inline-snapshots) for more info.

### `.toStrictEqual(value)`

Use `.toStrictEqual` to test that objects have the same types as well as structure.
Expand Down Expand Up @@ -1134,3 +1140,9 @@ exports[`drinking flavors throws on octopus 1`] = `"yuck, octopus flavor"`;
```

Check out [React Tree Snapshot Testing](http://facebook.github.io/jest/blog/2016/07/27/jest-14.html) for more information on snapshot testing.

### `.toThrowErrorMatchingInlineSnapshot()`

This matcher is much like [`.toThrowErrorMatchingSnapshot`](#tothrowerrormatchingsnapshot), except instead of writing the snapshot value to a `.snap` file, it will be written into the source code automatically.

Check out the section on [Inline Snapshots](./SnapshotTesting.md#inline-snapshots) for more info.
43 changes: 43 additions & 0 deletions docs/SnapshotTesting.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,49 @@ Once you're finished, Jest will give you a summary before returning back to watc

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

### Inline Snapshots

Inline snapshots behave identically to external snapshots (`.snap` files), except the snapshot values are written automatically back into the source code. This means you can get the benefits of automatically generated snapshots without having to switch to an external file to make sure the correct value was written.

> Inline snapshots are powered by [Prettier](https://prettier.io). To use inline snapshots you must have `prettier` installed in your project. Your Prettier configuration will be respected when writing to test files.
>
> If you have `prettier` installed in a location where Jest can't find it, you can tell Jest how to find it using the [`"prettier"`](./Configuration.md#prettier-string) configuration property.

**Example:**

First, you write a test, calling `.toMatchInlineSnapshot()` with no arguments:

```javascript
it('renders correctly', () => {
const tree = renderer
.create(<Link page="https://prettier.io">Prettier</Link>)
.toJSON();
expect(tree).toMatchInlineSnapshot();
});
```

The next time you run Jest, `tree` will be evaluated, and a snapshot will be written as an argument to `toMatchInlineSnapshot`:

```javascript
it('renders correctly', () => {
const tree = renderer
.create(<Link page="https://prettier.io">Prettier</Link>)
.toJSON();
expect(tree).toMatchInlineSnapshot(`
<a
className="normal"
href="https://prettier.io"
onMouseEnter={[Function]}
onMouseLeave={[Function]}
>
Prettier
</a>
`);
});
```

That's all there is to it! You can even update the snapshots with `--updateSnapshot` or using the `u` key in `--watch` mode.

### Property Matchers

Often there are fields in the object you want to snapshot which are generated (like IDs and Dates). If you try to snapshot these objects, they will force the snapshot to fail on every run:
Expand Down
1 change: 1 addition & 0 deletions e2e/__tests__/__snapshots__/show_config.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ exports[`--showConfig outputs config info and exits 1`] = `
\\"moduleNameMapper\\": {},
\\"modulePathIgnorePatterns\\": [],
\\"name\\": \\"[md5 hash]\\",
\\"prettier\\": null,
\\"resetMocks\\": false,
\\"resetModules\\": false,
\\"resolver\\": null,
Expand Down
115 changes: 115 additions & 0 deletions e2e/__tests__/__snapshots__/to_match_inline_snapshot.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`basic support: initial write 1`] = `
"test('inline snapshots', () =>
expect({apple: 'original value'}).toMatchInlineSnapshot(\`
Object {
\\"apple\\": \\"original value\\",
}
\`));
"
`;

exports[`basic support: snapshot mismatch 1`] = `
"test('inline snapshots', () =>
expect({apple: 'updated value'}).toMatchInlineSnapshot(\`
Object {
\\"apple\\": \\"original value\\",
}
\`));
"
`;

exports[`basic support: snapshot passed 1`] = `
"test('inline snapshots', () =>
expect({apple: 'original value'}).toMatchInlineSnapshot(\`
Object {
\\"apple\\": \\"original value\\",
}
\`));
"
`;

exports[`basic support: snapshot updated 1`] = `
"test('inline snapshots', () =>
expect({apple: 'updated value'}).toMatchInlineSnapshot(\`
Object {
\\"apple\\": \\"updated value\\",
}
\`));
"
`;

exports[`handles property matchers: initial write 1`] = `
"test('handles property matchers', () => {
expect({createdAt: new Date()}).toMatchInlineSnapshot(
{createdAt: expect.any(Date)},
\`
Object {
\\"createdAt\\": Any<Date>,
}
\`,
);
});
"
`;

exports[`handles property matchers: snapshot failed 1`] = `
"test('handles property matchers', () => {
expect({createdAt: \\"string\\"}).toMatchInlineSnapshot(
{createdAt: expect.any(Date)},
\`
Object {
\\"createdAt\\": Any<Date>,
}
\`,
);
});
"
`;

exports[`handles property matchers: snapshot passed 1`] = `
"test('handles property matchers', () => {
expect({createdAt: new Date()}).toMatchInlineSnapshot(
{createdAt: expect.any(Date)},
\`
Object {
\\"createdAt\\": Any<Date>,
}
\`,
);
});
"
`;

exports[`handles property matchers: snapshot updated 1`] = `
"test('handles property matchers', () => {
expect({createdAt: 'string'}).toMatchInlineSnapshot(
{createdAt: expect.any(String)},
\`
Object {
\\"createdAt\\": Any<String>,
}
\`,
);
});
"
`;

exports[`supports async matchers 1`] = `
"test('inline snapshots', async () => {
expect(Promise.resolve('success')).resolves.toMatchInlineSnapshot(
\`\\"success\\"\`,
);
expect(Promise.reject('fail')).rejects.toMatchInlineSnapshot(\`\\"fail\\"\`);
});
"
`;

exports[`supports async tests 1`] = `
"test('inline snapshots', async () => {
await 'next tick';
expect(42).toMatchInlineSnapshot(\`42\`);
});
"
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should support rejecting promises 1`] = `
"test('should support rejecting promises', async () => {
await expect(
Promise.reject(new Error('octopus')),
).rejects.toThrowErrorMatchingInlineSnapshot(\`\\"octopus\\"\`);
});
"
`;

exports[`updates existing snapshot: updated snapshot 1`] = `
"test('updates existing snapshot', () => {
expect(() => {
throw new Error('apple');
}).toThrowErrorMatchingInlineSnapshot(\`\\"apple\\"\`);
});
"
`;

exports[`works fine when function throws error: initial write 1`] = `
"test('works fine when function throws error', () => {
expect(() => {
throw new Error('apple');
}).toThrowErrorMatchingInlineSnapshot(\`\\"apple\\"\`);
});
"
`;
Loading