diff --git a/docs/ExpectAPI.md b/docs/ExpectAPI.md index 3cde3304fe71..43a39820e975 100644 --- a/docs/ExpectAPI.md +++ b/docs/ExpectAPI.md @@ -292,6 +292,48 @@ it('observes something', async () => { }); ``` +#### Bail out + +Usually `jest` tries to match every snapshot that is expected in a test. + +Sometimes it might not make sense to continue the test if a prior snapshot failed. For example, when you make snapshots of a state-machine after various transitions you can abort the test once one transition produced the wrong state. + +In that case you can implement a custom snapshot matcher that throws on the first mismatch instead of collecting every mismatch. + +```js +const {toMatchInlineSnapshot} = require('jest-snapshot'); + +expect.extend({ + toMatchStateInlineSnapshot(...args) { + this.dontThrow = () => {}; + + return toMatchInlineSnapshot.call(this, ...args); + }, +}); + +let state = 'initial'; + +function transition() { + // Typo in the implementation should cause the test to fail + if (state === 'INITIAL') { + state = 'pending'; + } else if (state === 'pending') { + state = 'done'; + } +} + +it('transitions as expected', () => { + expect(state).toMatchStateInlineSnapshot(`"initial"`); + + transition(); + // Already produces a mismatch. No point in continuing the test. + expect(state).toMatchStateInlineSnapshot(`"loading"`); + + transition(); + expect(state).toMatchStateInlineSnapshot(`"done"`); +}); +``` + ### `expect.anything()` `expect.anything()` matches anything but `null` or `undefined`. You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. For example, if you want to check that a mock function is called with a non-null argument: diff --git a/e2e/__tests__/__snapshots__/customInlineSnapshotMatchers.test.ts.snap b/e2e/__tests__/__snapshots__/customInlineSnapshotMatchers.test.ts.snap index b26f7240ca99..f64495ccbfaa 100644 --- a/e2e/__tests__/__snapshots__/customInlineSnapshotMatchers.test.ts.snap +++ b/e2e/__tests__/__snapshots__/customInlineSnapshotMatchers.test.ts.snap @@ -1,5 +1,33 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`can bail with a custom inline snapshot matcher 1`] = ` +FAIL __tests__/bail.test.js + ✕ transitions as expected + + ● transitions as expected + + expect(received).toMatchInlineSnapshot(snapshot) + + Snapshot name: \`transitions as expected 2\` + + Snapshot: "loading" + Received: "initial" + + 28 | transition(); + 29 | // Already produces a mismatch. No point in continuing the test. + > 30 | expect(state).toMatchStateInlineSnapshot(\`"loading"\`); + | ^ + 31 | transition(); + 32 | expect(state).toMatchStateInlineSnapshot(\`"done"\`); + 33 | }); + + at Object.toMatchStateInlineSnapshot (__tests__/bail.test.js:30:17) + + › 1 snapshot failed. +Snapshot Summary + › 1 snapshot failed from 1 test suite. Inspect your code changes or re-run jest with \`-u\` to update them. +`; + exports[`works with custom inline snapshot matchers 1`] = ` FAIL __tests__/asynchronous.test.js ✕ new async, inline snapshots diff --git a/e2e/__tests__/customInlineSnapshotMatchers.test.ts b/e2e/__tests__/customInlineSnapshotMatchers.test.ts index a644c74ab270..c6f5234f8533 100644 --- a/e2e/__tests__/customInlineSnapshotMatchers.test.ts +++ b/e2e/__tests__/customInlineSnapshotMatchers.test.ts @@ -25,3 +25,20 @@ test('works with custom inline snapshot matchers', () => { expect(wrap(rest)).toMatchSnapshot(); }); + +test('can bail with a custom inline snapshot matcher', () => { + const {stderr} = runJest('custom-inline-snapshot-matchers', [ + // Prevent adding new snapshots or rather changing the test. + '--ci', + 'bail.test.js', + ]); + + let {rest} = extractSummary(stderr); + + rest = rest + .split('\n') + .filter(line => line.indexOf('at Error (native)') < 0) + .join('\n'); + + expect(wrap(rest)).toMatchSnapshot(); +}); diff --git a/e2e/custom-inline-snapshot-matchers/__tests__/bail.test.js b/e2e/custom-inline-snapshot-matchers/__tests__/bail.test.js new file mode 100644 index 000000000000..2ce01beb73fa --- /dev/null +++ b/e2e/custom-inline-snapshot-matchers/__tests__/bail.test.js @@ -0,0 +1,33 @@ +/** + * 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. + */ +const {toMatchInlineSnapshot} = require('jest-snapshot'); + +expect.extend({ + toMatchStateInlineSnapshot(...args) { + this.dontThrow = () => {}; + return toMatchInlineSnapshot.call(this, ...args); + }, +}); + +let state = 'initial'; +function transition() { + // Typo in the implementation should cause the test to fail + if (state === 'INITIAL') { + state = 'pending'; + } else if (state === 'pending') { + state = 'done'; + } +} + +it('transitions as expected', () => { + expect(state).toMatchStateInlineSnapshot(`"initial"`); + transition(); + // Already produces a mismatch. No point in continuing the test. + expect(state).toMatchStateInlineSnapshot(`"loading"`); + transition(); + expect(state).toMatchStateInlineSnapshot(`"done"`); +}); diff --git a/website/versioned_docs/version-25.x/ExpectAPI.md b/website/versioned_docs/version-25.x/ExpectAPI.md index e90c7921fbf0..1cd94b7aa1d2 100644 --- a/website/versioned_docs/version-25.x/ExpectAPI.md +++ b/website/versioned_docs/version-25.x/ExpectAPI.md @@ -257,6 +257,48 @@ it('stores only 10 characters', () => { }); ``` +#### Bail out + +Usually `jest` tries to match every snapshot that is expected in a test. + +Sometimes it might not make sense to continue the test if a prior snapshot failed. For example, when you make snapshots of a state-machine after various transitions you can abort the test once one transition produced the wrong state. + +In that case you can implement a custom snapshot matcher that throws on the first mismatch instead of collecting every mismatch. + +```js +const {toMatchInlineSnapshot} = require('jest-snapshot'); + +expect.extend({ + toMatchStateInlineSnapshot(...args) { + this.dontThrow = () => {}; + + return toMatchInlineSnapshot.call(this, ...args); + }, +}); + +let state = 'initial'; + +function transition() { + // Typo in the implementation should cause the test to fail + if (state === 'INITIAL') { + state = 'pending'; + } else if (state === 'pending') { + state = 'done'; + } +} + +it('transitions as expected', () => { + expect(state).toMatchStateInlineSnapshot(`"initial"`); + + transition(); + // Already produces a mismatch. No point in continuing the test. + expect(state).toMatchStateInlineSnapshot(`"loading"`); + + transition(); + expect(state).toMatchStateInlineSnapshot(`"done"`); +}); +``` + ### `expect.anything()` `expect.anything()` matches anything but `null` or `undefined`. You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. For example, if you want to check that a mock function is called with a non-null argument: diff --git a/website/versioned_docs/version-26.x/ExpectAPI.md b/website/versioned_docs/version-26.x/ExpectAPI.md index 30f3f4ad95fd..272d707236b9 100644 --- a/website/versioned_docs/version-26.x/ExpectAPI.md +++ b/website/versioned_docs/version-26.x/ExpectAPI.md @@ -257,6 +257,48 @@ it('stores only 10 characters', () => { }); ``` +#### Bail out + +Usually `jest` tries to match every snapshot that is expected in a test. + +Sometimes it might not make sense to continue the test if a prior snapshot failed. For example, when you make snapshots of a state-machine after various transitions you can abort the test once one transition produced the wrong state. + +In that case you can implement a custom snapshot matcher that throws on the first mismatch instead of collecting every mismatch. + +```js +const {toMatchInlineSnapshot} = require('jest-snapshot'); + +expect.extend({ + toMatchStateInlineSnapshot(...args) { + this.dontThrow = () => {}; + + return toMatchInlineSnapshot.call(this, ...args); + }, +}); + +let state = 'initial'; + +function transition() { + // Typo in the implementation should cause the test to fail + if (state === 'INITIAL') { + state = 'pending'; + } else if (state === 'pending') { + state = 'done'; + } +} + +it('transitions as expected', () => { + expect(state).toMatchStateInlineSnapshot(`"initial"`); + + transition(); + // Already produces a mismatch. No point in continuing the test. + expect(state).toMatchStateInlineSnapshot(`"loading"`); + + transition(); + expect(state).toMatchStateInlineSnapshot(`"done"`); +}); +``` + ### `expect.anything()` `expect.anything()` matches anything but `null` or `undefined`. You can use it inside `toEqual` or `toBeCalledWith` instead of a literal value. For example, if you want to check that a mock function is called with a non-null argument: