diff --git a/e2e/__tests__/toMatchNamedSnapshot.test.ts b/e2e/__tests__/toMatchNamedSnapshot.test.ts new file mode 100644 index 000000000000..906a295bd5be --- /dev/null +++ b/e2e/__tests__/toMatchNamedSnapshot.test.ts @@ -0,0 +1,291 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import * as path from 'path'; +import {cleanup, makeTemplate, writeFiles} from '../Utils'; +import runJest from '../runJest'; + +const DIR = path.resolve(__dirname, '../to-match-named-snapshot'); +const TESTS_DIR = path.resolve(DIR, '__tests__'); + +beforeEach(() => cleanup(TESTS_DIR)); +afterAll(() => cleanup(TESTS_DIR)); + +test('basic support', () => { + const filename = 'basic-support.test.js'; + const template = makeTemplate( + "test('named snapshots', () => expect($1).toMatchNamedSnapshot('basic-support'));", + ); + + { + writeFiles(TESTS_DIR, { + [filename]: template(['{apple: "original value"}']), + }); + const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]); + expect(stderr).toMatch('1 snapshot written from 1 test suite.'); + expect(exitCode).toBe(0); + } + + { + const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]); + expect(stderr).toMatch('Snapshots: 1 passed, 1 total'); + expect(stderr).not.toMatch('1 snapshot written from 1 test suite.'); + expect(exitCode).toBe(0); + } + + { + writeFiles(TESTS_DIR, { + [filename]: template(['{apple: "updated value"}']), + }); + const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]); + expect(stderr).toMatch('Snapshot name: `named snapshots 1`'); + expect(exitCode).toBe(1); + } + + { + const {stderr, exitCode} = runJest(DIR, [ + '-w=1', + '--ci=false', + filename, + '-u', + ]); + expect(stderr).toMatch('1 snapshot updated from 1 test suite.'); + expect(exitCode).toBe(0); + } +}); + +test('error thrown before snapshot', () => { + const filename = 'error-thrown-before-snapshot.test.js'; + const template = makeTemplate(`test('snapshots', () => { + expect($1).toBeTruthy(); + expect($2).toMatchNamedSnapshot('error-thrown-before-snapshot-$3'); + });`); + + { + writeFiles(TESTS_DIR, { + [filename]: template(['true', '{a: "original"}', '1']), + }); + const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]); + expect(stderr).toMatch('1 snapshot written from 1 test suite.'); + expect(exitCode).toBe(0); + } + + { + const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]); + expect(stderr).toMatch('Snapshots: 1 passed, 1 total'); + expect(exitCode).toBe(0); + } + + { + writeFiles(TESTS_DIR, { + [filename]: template(['false', '{a: "original"}', '2']), + }); + const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]); + expect(stderr).not.toMatch('1 obsolete snapshot found'); + expect(exitCode).toBe(1); + } +}); + +test('first snapshot fails, second passes', () => { + const filename = 'first-snapshot-fails-second-passes.test.js'; + const template = makeTemplate(`test('named snapshots', () => { + expect($1).toMatchNamedSnapshot('test-snapshot'); + expect($2).toMatchNamedSnapshot('test-snapshot'); + });`); + + { + writeFiles(TESTS_DIR, {[filename]: template(["'apple'", "'banana'", '1'])}); + const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]); + expect(stderr).toMatch('2 snapshots written from 1 test suite.'); + expect(exitCode).toBe(0); + } + + { + writeFiles(TESTS_DIR, {[filename]: template(["'kiwi'", "'banana'", '2'])}); + const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]); + expect(stderr).toMatch('Snapshot name: `named snapshots 1`'); + // Match lines separately because empty line has been replaced with space: + expect(stderr).toMatch('Snapshot: "apple"'); + expect(stderr).toMatch('Received: "kiwi"'); + expect(stderr).not.toMatch('1 obsolete snapshot found'); + expect(exitCode).toBe(1); + } +}); + +test('does not mark snapshots as obsolete in skipped tests if snapshot name match test name', () => { + const filename = 'no-obsolete-if-skipped.test.js'; + const template = makeTemplate(`test('snapshots', () => { + expect(true).toBe(true); + }); + + $1('will be skipped', () => { + expect({a: 6}).toMatchNamedSnapshot('will be skipped'); + }); + `); + + { + writeFiles(TESTS_DIR, {[filename]: template(['test'])}); + const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]); + expect(stderr).toMatch('1 snapshot written from 1 test suite.'); + expect(exitCode).toBe(0); + } + + { + writeFiles(TESTS_DIR, {[filename]: template(['test.skip'])}); + const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]); + console.log(stderr); + expect(stderr).not.toMatch('1 obsolete snapshot found'); + expect(exitCode).toBe(0); + } +}); + +test('mark snapshots as obsolete in skipped tests if snapshot name does not match test name', () => { + const filename = 'no-obsolete-if-skipped.test.js'; + const template = makeTemplate(`test('snapshots', () => { + expect(true).toBe(true); + }); + + $1('will be skipped', () => { + expect({a: 6}).toMatchNamedSnapshot('will be obsolete'); + }); + `); + + { + writeFiles(TESTS_DIR, {[filename]: template(['test'])}); + const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]); + expect(stderr).toMatch('1 snapshot written from 1 test suite.'); + expect(exitCode).toBe(0); + } + + { + writeFiles(TESTS_DIR, {[filename]: template(['test.skip'])}); + const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]); + console.log(stderr); + expect(stderr).toMatch('1 snapshot obsolete'); + expect(exitCode).toBe(1); + } +}); + +test('accepts custom snapshot name', () => { + const filename = 'accept-custom-snapshot-name.test.js'; + const template = makeTemplate(`test('accepts custom snapshot name', () => { + expect(true).toMatchNamedSnapshot('custom-name'); + }); + `); + + { + writeFiles(TESTS_DIR, {[filename]: template()}); + const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]); + expect(stderr).toMatch('1 snapshot written from 1 test suite.'); + expect(exitCode).toBe(0); + } +}); + +test('handles property matchers', () => { + const filename = 'handle-property-matchers.test.js'; + const template = makeTemplate(`test('handles property matchers', () => { + expect({createdAt: $1}).toMatchNamedSnapshot({createdAt: expect.any(Date)}, 'property-matchers'); + }); + `); + + { + writeFiles(TESTS_DIR, {[filename]: template(['new Date()'])}); + const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]); + expect(stderr).toMatch('1 snapshot written from 1 test suite.'); + expect(exitCode).toBe(0); + } + + { + const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]); + expect(stderr).toMatch('Snapshots: 1 passed, 1 total'); + expect(exitCode).toBe(0); + } + + { + writeFiles(TESTS_DIR, {[filename]: template(['"string"'])}); + const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]); + expect(stderr).toMatch('Snapshot name: `handles property matchers 1`'); + expect(stderr).toMatch('Snapshots: 1 failed, 1 total'); + expect(exitCode).toBe(1); + } +}); + +test('handles invalid property matchers', () => { + const filename = 'handle-property-matchers.test.js'; + { + writeFiles(TESTS_DIR, { + [filename]: `test('invalid property matchers', () => { + expect({foo: 'bar'}).toMatchNamedSnapshot(null, 'null-property-matcher'); + }); + `, + }); + const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]); + expect(stderr).toMatch('Expected properties must be an object'); + expect(exitCode).toBe(1); + } + { + writeFiles(TESTS_DIR, { + [filename]: `test('invalid property matchers', () => { + expect({foo: 'bar'}).toMatchNamedSnapshot(undefined, 'undefined-property-matcher'); + }); + `, + }); + const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]); + expect(stderr).toMatch('Expected properties must be an object'); + expect(stderr).toMatch( + "To provide a snapshot name without properties: toMatchNamedSnapshot('snapshotName')", + ); + expect(exitCode).toBe(1); + } +}); + +test('handles property matchers with deep properties', () => { + const filename = 'handle-property-matchers-with-name.test.js'; + const template = + makeTemplate(`test('handles property matchers with deep properties', () => { + expect({ user: { createdAt: $1, name: $2 }}).toMatchNamedSnapshot({ user: { createdAt: expect.any(Date), name: $2 }}, 'deep-property-matchers'); + }); + `); + + { + writeFiles(TESTS_DIR, { + [filename]: template(['new Date()', '"Jest"']), + }); + const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]); + expect(stderr).toMatch('1 snapshot written from 1 test suite.'); + expect(exitCode).toBe(0); + } + + { + const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]); + expect(stderr).toMatch('Snapshots: 1 passed, 1 total'); + expect(exitCode).toBe(0); + } + + { + writeFiles(TESTS_DIR, {[filename]: template(['"string"', '"Jest"'])}); + const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]); + expect(stderr).toMatch( + 'Snapshot name: `handles property matchers with deep properties 1`', + ); + expect(stderr).toMatch('Expected properties'); + expect(stderr).toMatch('Snapshots: 1 failed, 1 total'); + expect(exitCode).toBe(1); + } + + { + writeFiles(TESTS_DIR, { + [filename]: template(['new Date()', '"CHANGED"']), + }); + const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]); + expect(stderr).toMatch( + 'Snapshot name: `handles property matchers with deep properties 1`', + ); + expect(stderr).toMatch('Snapshots: 1 failed, 1 total'); + expect(exitCode).toBe(1); + } +}); diff --git a/e2e/__tests__/toMatchSnapshot.test.ts b/e2e/__tests__/toMatchSnapshot.test.ts index c31bfaf4d623..7edc3c43cf2b 100644 --- a/e2e/__tests__/toMatchSnapshot.test.ts +++ b/e2e/__tests__/toMatchSnapshot.test.ts @@ -142,10 +142,10 @@ test('does not mark snapshots as obsolete in skipped tests', () => { } }); -test('accepts custom snapshot name', () => { +test('accepts snapshot hint', () => { const filename = 'accept-custom-snapshot-name.test.js'; - const template = makeTemplate(`test('accepts custom snapshot name', () => { - expect(true).toMatchSnapshot('custom-name'); + const template = makeTemplate(`test('accepts snapshot hint', () => { + expect(true).toMatchSnapshot('custom-hint'); }); `); diff --git a/e2e/to-match-named-snapshot/package.json b/e2e/to-match-named-snapshot/package.json new file mode 100644 index 000000000000..148788b25446 --- /dev/null +++ b/e2e/to-match-named-snapshot/package.json @@ -0,0 +1,5 @@ +{ + "jest": { + "testEnvironment": "node" + } +}