diff --git a/CHANGELOG.md b/CHANGELOG.md index 40ef3898e1eb..177b286ed47f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - `[jest-environment-jsdom]` [**BREAKING**] Add default `browser` condition to `exportConditions` for `jsdom` environment ([#11924](https://github.com/facebook/jest/pull/11924)) - `[jest-environment-node]` [**BREAKING**] Add default `node` and `node-addon` conditions to `exportConditions` for `node` environment ([#11924](https://github.com/facebook/jest/pull/11924)) - `[@jest/expect-utils]` New module exporting utils for `expect` ([#12323](https://github.com/facebook/jest/pull/12323)) +- `[jest-snapshot]` [**BREAKING**] Migrate to ESM ([#12342](https://github.com/facebook/jest/pull/12342)) - `[jest-worker]` [**BREAKING**] Allow only absolute `workerPath` ([#12343](https://github.com/facebook/jest/pull/12343)) ### Fixes diff --git a/packages/jest-circus/src/legacy-code-todo-rewrite/jestAdapter.ts b/packages/jest-circus/src/legacy-code-todo-rewrite/jestAdapter.ts index 42113aa2c750..dc8059b39acf 100644 --- a/packages/jest-circus/src/legacy-code-todo-rewrite/jestAdapter.ts +++ b/packages/jest-circus/src/legacy-code-todo-rewrite/jestAdapter.ts @@ -9,7 +9,7 @@ import type {JestEnvironment} from '@jest/environment'; import type {TestFileEvent, TestResult} from '@jest/test-result'; import type {Config} from '@jest/types'; import type Runtime from 'jest-runtime'; -import type {SnapshotStateType} from 'jest-snapshot'; +import type {SnapshotState} from 'jest-snapshot'; import {deepCyclicCopy} from 'jest-util'; const FRAMEWORK_INITIALIZER = require.resolve('./jestAdapterInit'); @@ -101,7 +101,7 @@ const jestAdapter = async ( const _addSnapshotData = ( results: TestResult, - snapshotState: SnapshotStateType, + snapshotState: SnapshotState, ) => { results.testResults.forEach(({fullName, status}) => { if (status === 'pending' || status === 'failed') { diff --git a/packages/jest-circus/src/legacy-code-todo-rewrite/jestAdapterInit.ts b/packages/jest-circus/src/legacy-code-todo-rewrite/jestAdapterInit.ts index 43bf59f1af4e..6a41045dc70d 100644 --- a/packages/jest-circus/src/legacy-code-todo-rewrite/jestAdapterInit.ts +++ b/packages/jest-circus/src/legacy-code-todo-rewrite/jestAdapterInit.ts @@ -20,7 +20,6 @@ import {bind} from 'jest-each'; import {formatExecError, formatResultsErrors} from 'jest-message-util'; import { SnapshotState, - SnapshotStateType, addSerializer, buildSnapshotResolver, } from 'jest-snapshot'; @@ -62,7 +61,7 @@ export const initialize = async ({ setGlobalsForRuntime: (globals: JestGlobals) => void; }): Promise<{ globals: Global.TestFrameworkGlobals; - snapshotState: SnapshotStateType; + snapshotState: SnapshotState; }> => { if (globalConfig.testTimeout) { getRunnerState().testTimeout = globalConfig.testTimeout; @@ -268,7 +267,7 @@ export const runAndTransformResultsToJestFormat = async ({ }; const handleSnapshotStateAfterRetry = - (snapshotState: SnapshotStateType) => (event: Circus.Event) => { + (snapshotState: SnapshotState) => (event: Circus.Event) => { switch (event.name) { case 'test_retry': { // Clear any snapshot data that occurred in previous test run diff --git a/packages/jest-core/src/TestScheduler.ts b/packages/jest-core/src/TestScheduler.ts index 2786a65f6753..0f0ca9e4218c 100644 --- a/packages/jest-core/src/TestScheduler.ts +++ b/packages/jest-core/src/TestScheduler.ts @@ -31,7 +31,10 @@ import type {Config} from '@jest/types'; import {formatExecError} from 'jest-message-util'; import type TestRunner from 'jest-runner'; import type {Context} from 'jest-runtime'; -import snapshot = require('jest-snapshot'); +import { + buildSnapshotResolver, + cleanup as cleanupSnapshots, +} from 'jest-snapshot'; import {requireOrImportModule} from 'jest-util'; import ReporterDispatcher from './ReporterDispatcher'; import type TestWatcher from './TestWatcher'; @@ -170,15 +173,12 @@ class TestScheduler { const contextsWithSnapshotResolvers = await Promise.all( Array.from(contexts).map( async context => - [ - context, - await snapshot.buildSnapshotResolver(context.config), - ] as const, + [context, await buildSnapshotResolver(context.config)] as const, ), ); contextsWithSnapshotResolvers.forEach(([context, snapshotResolver]) => { - const status = snapshot.cleanup( + const status = cleanupSnapshots( context.hasteFS, this._globalConfig.updateSnapshot, snapshotResolver, diff --git a/packages/jest-jasmine2/src/index.ts b/packages/jest-jasmine2/src/index.ts index efd1b01c30ec..884cadf399b1 100644 --- a/packages/jest-jasmine2/src/index.ts +++ b/packages/jest-jasmine2/src/index.ts @@ -11,7 +11,7 @@ import {getCallsite} from '@jest/source-map'; import type {AssertionResult, TestResult} from '@jest/test-result'; import type {Config, Global} from '@jest/types'; import type Runtime from 'jest-runtime'; -import type {SnapshotStateType} from 'jest-snapshot'; +import type {SnapshotState} from 'jest-snapshot'; import installEach from './each'; import {installErrorOnPrivate} from './errorOnPrivate'; import type Spec from './jasmine/Spec'; @@ -138,7 +138,7 @@ export default async function jasmine2( }); } - const snapshotState: SnapshotStateType = await runtime + const snapshotState: SnapshotState = await runtime .requireInternalModule( path.resolve(__dirname, './setup_jest_globals.js'), ) @@ -178,10 +178,7 @@ export default async function jasmine2( return addSnapshotData(results, snapshotState); } -const addSnapshotData = ( - results: TestResult, - snapshotState: SnapshotStateType, -) => { +const addSnapshotData = (results: TestResult, snapshotState: SnapshotState) => { results.testResults.forEach(({fullName, status}: AssertionResult) => { if (status === 'pending' || status === 'failed') { // if test is skipped or failed, we don't want to mark diff --git a/packages/jest-jasmine2/src/setup_jest_globals.ts b/packages/jest-jasmine2/src/setup_jest_globals.ts index fbf00602d4fd..72a713708fcc 100644 --- a/packages/jest-jasmine2/src/setup_jest_globals.ts +++ b/packages/jest-jasmine2/src/setup_jest_globals.ts @@ -9,7 +9,6 @@ import type {Config, Global} from '@jest/types'; import {extractExpectedAssertionsErrors, getState, setState} from 'expect'; import { SnapshotState, - SnapshotStateType, addSerializer, buildSnapshotResolver, } from 'jest-snapshot'; @@ -94,7 +93,7 @@ export default async function setupJestGlobals({ globalConfig, localRequire, testPath, -}: SetupOptions): Promise { +}: SetupOptions): Promise { // Jest tests snapshotSerializers in order preceding built-in serializers. // Therefore, add in reverse because the last added is the first tested. config.snapshotSerializers diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 6d90e3845005..bb22dbcde7b8 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -50,7 +50,7 @@ import {formatStackTrace, separateMessageFromStack} from 'jest-message-util'; import type {MockFunctionMetadata, ModuleMocker} from 'jest-mock'; import {escapePathForRegex} from 'jest-regex-util'; import Resolver, {ResolveModuleConfig} from 'jest-resolve'; -import Snapshot = require('jest-snapshot'); +import {EXTENSION as SnapshotExtension} from 'jest-snapshot'; import {createDirectory, deepCyclicCopy} from 'jest-util'; import { createOutsideJestVmPath, @@ -373,7 +373,7 @@ export default class Runtime { console: options?.console, dependencyExtractor: config.dependencyExtractor, enableSymlinks: config.haste.enableSymlinks, - extensions: [Snapshot.EXTENSION].concat(config.moduleFileExtensions), + extensions: [SnapshotExtension].concat(config.moduleFileExtensions), forceNodeFilesystemAPI: config.haste.forceNodeFilesystemAPI, hasteImplModulePath: config.haste.hasteImplModulePath, hasteMapModulePath: config.haste.hasteMapModulePath, diff --git a/packages/jest-snapshot/src/__tests__/matcher.test.ts b/packages/jest-snapshot/src/__tests__/matcher.test.ts index 470f0eab9db5..f9cb3aa27247 100644 --- a/packages/jest-snapshot/src/__tests__/matcher.test.ts +++ b/packages/jest-snapshot/src/__tests__/matcher.test.ts @@ -5,9 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import jestSnapshot from '../'; - -const {toMatchSnapshot} = jestSnapshot; +import {toMatchSnapshot} from '../'; it('matcher returns matcher name, expected and actual values', () => { const actual = 'a'; diff --git a/packages/jest-snapshot/src/__tests__/printSnapshot.test.ts b/packages/jest-snapshot/src/__tests__/printSnapshot.test.ts index e3639ea3bf29..88bc60664c63 100644 --- a/packages/jest-snapshot/src/__tests__/printSnapshot.test.ts +++ b/packages/jest-snapshot/src/__tests__/printSnapshot.test.ts @@ -19,7 +19,12 @@ import { bForeground2, bForeground3, } from '../colors'; -import jestSnapshot = require('../index'); +import { + toMatchInlineSnapshot, + toMatchSnapshot, + toThrowErrorMatchingInlineSnapshot, + toThrowErrorMatchingSnapshot, +} from '../index'; import { getReceivedColorForChalkInstance, getSnapshotColorForChalkInstance, @@ -132,13 +137,6 @@ expect.addSnapshotSerializer({ }, }); -const { - toMatchInlineSnapshot, - toMatchSnapshot, - toThrowErrorMatchingInlineSnapshot, - toThrowErrorMatchingSnapshot, -} = jestSnapshot; - describe('chalk', () => { // Because these tests give code coverage of get functions // and give confidence that the escape sequences are correct, diff --git a/packages/jest-snapshot/src/__tests__/throwMatcher.test.ts b/packages/jest-snapshot/src/__tests__/throwMatcher.test.ts index aecbad73d34c..d17dfac04138 100644 --- a/packages/jest-snapshot/src/__tests__/throwMatcher.test.ts +++ b/packages/jest-snapshot/src/__tests__/throwMatcher.test.ts @@ -5,9 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import jestSnapshot from '..'; - -const {toThrowErrorMatchingSnapshot} = jestSnapshot; +import {toThrowErrorMatchingSnapshot} from '..'; let matchFn: jest.Mock; diff --git a/packages/jest-snapshot/src/index.ts b/packages/jest-snapshot/src/index.ts index 0c8e627f441e..ab9f1c1206bb 100644 --- a/packages/jest-snapshot/src/index.ts +++ b/packages/jest-snapshot/src/index.ts @@ -20,14 +20,7 @@ import { printWithType, stringify, } from 'jest-matcher-utils'; -import { - EXTENSION, - SnapshotResolver as JestSnapshotResolver, - buildSnapshotResolver, - isSnapshotPath, -} from './SnapshotResolver'; -import SnapshotState from './State'; -import {addSerializer, getSerializers} from './plugins'; +import {EXTENSION, SnapshotResolver} from './SnapshotResolver'; import { PROPERTIES_ARG, SNAPSHOT_ARG, @@ -40,7 +33,16 @@ import { printSnapshotAndReceived, } from './printSnapshot'; import type {Context, ExpectationResult, MatchSnapshotConfig} from './types'; -import * as utils from './utils'; +import {deepMerge, escapeBacktickString, serialize} from './utils'; + +export {addSerializer, getSerializers} from './plugins'; +export { + EXTENSION, + buildSnapshotResolver, + isSnapshotPath, +} from './SnapshotResolver'; +export type {SnapshotResolver} from './SnapshotResolver'; +export {default as SnapshotState} from './State'; const DID_NOT_THROW = 'Received function did not throw'; // same as toThrow const NOT_SNAPSHOT_MATCHERS = `Snapshot matchers cannot be used with ${BOLD_WEIGHT( @@ -61,9 +63,9 @@ const printSnapshotName = ( return ( 'Snapshot name: `' + - (hasNames ? utils.escapeBacktickString(concatenatedBlockNames) : '') + + (hasNames ? escapeBacktickString(concatenatedBlockNames) : '') + (hasNames && hasHint ? ': ' : '') + - (hasHint ? BOLD_WEIGHT(utils.escapeBacktickString(hint)) : '') + + (hasHint ? BOLD_WEIGHT(escapeBacktickString(hint)) : '') + ' ' + count + '`' @@ -115,10 +117,10 @@ function stripAddedIndentation(inlineSnapshot: string) { const fileExists = (filePath: Config.Path, hasteFS: HasteFS): boolean => hasteFS.exists(filePath) || fs.existsSync(filePath); -const cleanup = ( +export const cleanup = ( hasteFS: HasteFS, update: Config.SnapshotUpdateState, - snapshotResolver: JestSnapshotResolver, + snapshotResolver: SnapshotResolver, testPathIgnorePatterns?: Config.ProjectConfig['testPathIgnorePatterns'], ): { filesRemoved: number; @@ -155,7 +157,7 @@ const cleanup = ( }; }; -const toMatchSnapshot = function ( +export const toMatchSnapshot = function ( this: Context, received: unknown, propertiesOrHint?: object | Config.Path, @@ -214,7 +216,7 @@ const toMatchSnapshot = function ( }); }; -const toMatchInlineSnapshot = function ( +export const toMatchInlineSnapshot = function ( this: Context, received: unknown, propertiesOrSnapshot?: object | string, @@ -258,7 +260,7 @@ const toMatchInlineSnapshot = function ( matcherErrorMessage( matcherHint(matcherName, undefined, PROPERTIES_ARG, options), 'Inline snapshot must be a string', - printWithType('Inline snapshot', inlineSnapshot, utils.serialize), + printWithType('Inline snapshot', inlineSnapshot, serialize), ), ); } @@ -353,7 +355,7 @@ const _toMatchSnapshot = (config: MatchSnapshotConfig) => { pass: false, }; } else { - received = utils.deepMerge(received, properties); + received = deepMerge(received, properties); } } @@ -408,7 +410,7 @@ const _toMatchSnapshot = (config: MatchSnapshotConfig) => { }; }; -const toThrowErrorMatchingSnapshot = function ( +export const toThrowErrorMatchingSnapshot = function ( this: Context, received: unknown, hint: string | undefined, // because error TS1016 for hint?: string @@ -431,7 +433,7 @@ const toThrowErrorMatchingSnapshot = function ( ); }; -const toThrowErrorMatchingInlineSnapshot = function ( +export const toThrowErrorMatchingInlineSnapshot = function ( this: Context, received: unknown, inlineSnapshot?: string, @@ -450,7 +452,7 @@ const toThrowErrorMatchingInlineSnapshot = function ( matcherErrorMessage( matcherHint(matcherName, undefined, SNAPSHOT_ARG, options), 'Inline snapshot must be a string', - printWithType('Inline snapshot', inlineSnapshot, utils.serialize), + printWithType('Inline snapshot', inlineSnapshot, serialize), ), ); } @@ -532,25 +534,3 @@ const _toThrowErrorMatchingSnapshot = ( received: error.message, }); }; - -const JestSnapshot = { - EXTENSION, - SnapshotState, - addSerializer, - buildSnapshotResolver, - cleanup, - getSerializers, - isSnapshotPath, - toMatchInlineSnapshot, - toMatchSnapshot, - toThrowErrorMatchingInlineSnapshot, - toThrowErrorMatchingSnapshot, - utils, -}; - -declare namespace JestSnapshot { - export type SnapshotResolver = JestSnapshotResolver; - export type SnapshotStateType = SnapshotState; -} - -export = JestSnapshot;