diff --git a/CHANGELOG.md b/CHANGELOG.md index 208b90faf636..52487eeaf581 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - `[expect]` Improve report when mock-spy matcher fails, part 4 ([#8710](https://github.com/facebook/jest/pull/8710)) - `[expect]` Throw matcher error when received cannot be jasmine spy ([#8747](https://github.com/facebook/jest/pull/8747)) - `[jest-snapshot]` Highlight substring differences when matcher fails, part 3 ([#8569](https://github.com/facebook/jest/pull/8569)) +- `[jest-core]` Improve report when snapshots are obsolete ([#8448](https://github.com/facebook/jest/pull/8665)) - `[jest-cli]` Improve chai support (with detailed output, to match jest exceptions) ([#8454](https://github.com/facebook/jest/pull/8454)) - `[*]` Manage the global timeout with `--testTimeout` command line argument. ([#8456](https://github.com/facebook/jest/pull/8456)) - `[pretty-format]` Render custom displayName of memoized components diff --git a/e2e/__tests__/snapshot-unknown.test.ts b/e2e/__tests__/snapshot-unknown.test.ts new file mode 100644 index 000000000000..b1697cae7077 --- /dev/null +++ b/e2e/__tests__/snapshot-unknown.test.ts @@ -0,0 +1,20 @@ +/** + * 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. + */ + +import runJest from '../runJest'; + +describe('Snapshot serializers', () => { + it('renders snapshot', () => { + const result = runJest('snapshot-unknown', ['-w=1']); + const stderr = result.stderr; + + expect(stderr).toMatch('2 snapshot files obsolete'); + expect(stderr).toMatch('__tests__/__snapshots__/fails.test.js.snap'); + expect(stderr).toMatch('__tests__/__snapshots__/fails2.test.js.snap'); + expect(result.status).toBe(1); + }); +}); diff --git a/e2e/snapshot-unknown/__tests__/__snapshots__/fails.test.js.snap b/e2e/snapshot-unknown/__tests__/__snapshots__/fails.test.js.snap new file mode 100644 index 000000000000..2c4c1a181285 --- /dev/null +++ b/e2e/snapshot-unknown/__tests__/__snapshots__/fails.test.js.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`snapshot this one makes not toMatchSnapshot assertion, but has a .snap file 1`] = `"normal"`; diff --git a/e2e/snapshot-unknown/__tests__/__snapshots__/fails2.test.js.snap b/e2e/snapshot-unknown/__tests__/__snapshots__/fails2.test.js.snap new file mode 100644 index 000000000000..2c4c1a181285 --- /dev/null +++ b/e2e/snapshot-unknown/__tests__/__snapshots__/fails2.test.js.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`snapshot this one makes not toMatchSnapshot assertion, but has a .snap file 1`] = `"normal"`; diff --git a/e2e/snapshot-unknown/__tests__/__snapshots__/works.test.js.snap b/e2e/snapshot-unknown/__tests__/__snapshots__/works.test.js.snap new file mode 100644 index 000000000000..2a8b56674496 --- /dev/null +++ b/e2e/snapshot-unknown/__tests__/__snapshots__/works.test.js.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`snapshot some snapshots exists and are fine 1`] = `"normal"`; diff --git a/e2e/snapshot-unknown/__tests__/works.test.js b/e2e/snapshot-unknown/__tests__/works.test.js new file mode 100644 index 000000000000..a02cba20cbef --- /dev/null +++ b/e2e/snapshot-unknown/__tests__/works.test.js @@ -0,0 +1,14 @@ +/** + * 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. + * + */ +'use strict'; + +describe('snapshot', () => { + it('some snapshots exists and are fine', () => { + expect('normal').toMatchSnapshot(); + }); +}); diff --git a/e2e/snapshot-unknown/package.json b/e2e/snapshot-unknown/package.json new file mode 100644 index 000000000000..148788b25446 --- /dev/null +++ b/e2e/snapshot-unknown/package.json @@ -0,0 +1,5 @@ +{ + "jest": { + "testEnvironment": "node" + } +} diff --git a/packages/jest-core/src/TestScheduler.ts b/packages/jest-core/src/TestScheduler.ts index ff29bde939b2..bce8ca39125d 100644 --- a/packages/jest-core/src/TestScheduler.ts +++ b/packages/jest-core/src/TestScheduler.ts @@ -145,9 +145,13 @@ export default class TestScheduler { context.hasteFS, this._globalConfig.updateSnapshot, snapshot.buildSnapshotResolver(context.config), + context.config.testPathIgnorePatterns, ); aggregatedResults.snapshot.filesRemoved += status.filesRemoved; + aggregatedResults.snapshot.filesRemovedList = ( + aggregatedResults.snapshot.filesRemovedList || [] + ).concat(status.filesRemovedList); }); const updateAll = this._globalConfig.updateSnapshot === 'all'; aggregatedResults.snapshot.didUpdate = updateAll; diff --git a/packages/jest-reporters/src/__tests__/get_snapshot_summary.test.js b/packages/jest-reporters/src/__tests__/get_snapshot_summary.test.js index c2a911d22365..fb76b156b1e2 100644 --- a/packages/jest-reporters/src/__tests__/get_snapshot_summary.test.js +++ b/packages/jest-reporters/src/__tests__/get_snapshot_summary.test.js @@ -21,6 +21,7 @@ test('creates a snapshot summary', () => { didUpdate: false, filesAdded: 1, filesRemoved: 1, + filesRemovedList: [], filesUnmatched: 1, filesUpdated: 1, matched: 2, @@ -49,6 +50,7 @@ test('creates a snapshot summary after an update', () => { didUpdate: true, filesAdded: 1, filesRemoved: 1, + filesRemovedList: [], filesUnmatched: 1, filesUpdated: 1, unchecked: 1, @@ -75,6 +77,7 @@ it('creates a snapshot summary with multiple snapshot being written/updated', () didUpdate: false, filesAdded: 2, filesRemoved: 2, + filesRemovedList: [], filesUnmatched: 2, filesUpdated: 2, unchecked: 2, @@ -105,6 +108,7 @@ it('returns nothing if there are no updates', () => { didUpdate: false, filesAdded: 0, filesRemoved: 0, + filesRemovedList: [], filesUnmatched: 0, filesUpdated: 0, unchecked: 0, diff --git a/packages/jest-reporters/src/__tests__/summary_reporter.test.js b/packages/jest-reporters/src/__tests__/summary_reporter.test.js index b4b56758a6c7..ead47477fc61 100644 --- a/packages/jest-reporters/src/__tests__/summary_reporter.test.js +++ b/packages/jest-reporters/src/__tests__/summary_reporter.test.js @@ -70,6 +70,7 @@ test('snapshots needs update with yarn test', () => { numTotalTestSuites: 1, numTotalTests: 1, snapshot: { + filesRemovedList: [], filesUnmatched: 1, total: 2, uncheckedKeysByFile: [], @@ -98,6 +99,7 @@ test('snapshots all have results (no update)', () => { didUpdate: false, filesAdded: 1, filesRemoved: 1, + filesRemovedList: [], filesUnmatched: 1, filesUpdated: 1, matched: 2, @@ -134,6 +136,7 @@ test('snapshots all have results (after update)', () => { didUpdate: true, filesAdded: 1, filesRemoved: 1, + filesRemovedList: [], filesUnmatched: 1, filesUpdated: 1, matched: 2, diff --git a/packages/jest-reporters/src/get_snapshot_summary.ts b/packages/jest-reporters/src/get_snapshot_summary.ts index 902cb79b7034..214963b0edf4 100644 --- a/packages/jest-reporters/src/get_snapshot_summary.ts +++ b/packages/jest-reporters/src/get_snapshot_summary.ts @@ -84,6 +84,14 @@ export default ( ); } } + if (snapshots.filesRemovedList && snapshots.filesRemovedList.length) { + const [head, ...tail] = snapshots.filesRemovedList; + summary.push(` ${DOWN_ARROW} ${DOT}${formatTestPath(globalConfig, head)}`); + + tail.forEach(key => { + summary.push(` ${DOT}${formatTestPath(globalConfig, key)}`); + }); + } if (snapshots.unchecked) { if (snapshots.didUpdate) { diff --git a/packages/jest-snapshot/src/index.ts b/packages/jest-snapshot/src/index.ts index dd9978d1acb5..a6de3a1a9ddd 100644 --- a/packages/jest-snapshot/src/index.ts +++ b/packages/jest-snapshot/src/index.ts @@ -122,22 +122,39 @@ const cleanup = ( hasteFS: HasteFS, update: Config.SnapshotUpdateState, snapshotResolver: JestSnapshotResolver, -) => { + testPathIgnorePatterns?: Config.ProjectConfig['testPathIgnorePatterns'], +): { + filesRemoved: number; + filesRemovedList: Array; +} => { const pattern = '\\.' + EXTENSION + '$'; const files = hasteFS.matchFiles(pattern); - const filesRemoved = files.reduce((acc, snapshotFile) => { - if (!fileExists(snapshotResolver.resolveTestPath(snapshotFile), hasteFS)) { + let testIgnorePatternsRegex: RegExp | null = null; + if (testPathIgnorePatterns && testPathIgnorePatterns.length > 0) { + testIgnorePatternsRegex = new RegExp(testPathIgnorePatterns.join('|')); + } + + const list = files.filter(snapshotFile => { + const testPath = snapshotResolver.resolveTestPath(snapshotFile); + + // ignore snapshots of ignored tests + if (testIgnorePatternsRegex && testIgnorePatternsRegex.test(testPath)) { + return false; + } + + if (!fileExists(testPath, hasteFS)) { if (update === 'all') { fs.unlinkSync(snapshotFile); } - return acc + 1; + return true; } - return acc; - }, 0); + return false; + }); return { - filesRemoved, + filesRemoved: list.length, + filesRemovedList: list, }; }; diff --git a/packages/jest-test-result/src/helpers.ts b/packages/jest-test-result/src/helpers.ts index 202cd2bf6e8c..6020142861bc 100644 --- a/packages/jest-test-result/src/helpers.ts +++ b/packages/jest-test-result/src/helpers.ts @@ -27,6 +27,7 @@ export const makeEmptyAggregatedTestResult = (): AggregatedResult => ({ filesAdded: 0, // combines individual test results + removed files after the full run filesRemoved: 0, + filesRemovedList: [], filesUnmatched: 0, filesUpdated: 0, matched: 0, diff --git a/packages/jest-test-result/src/types.ts b/packages/jest-test-result/src/types.ts index e9acdc40fc86..a9427cd7abb2 100644 --- a/packages/jest-test-result/src/types.ts +++ b/packages/jest-test-result/src/types.ts @@ -181,6 +181,7 @@ export type SnapshotSummary = { failure: boolean; filesAdded: number; filesRemoved: number; + filesRemovedList: Array; filesUnmatched: number; filesUpdated: number; matched: number;