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

feat(jest-snapshot): migrate to ESM #12342

Merged
merged 4 commits into from Feb 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -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
Expand Down
Expand Up @@ -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');
Expand Down Expand Up @@ -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') {
Expand Down
Expand Up @@ -20,7 +20,6 @@ import {bind} from 'jest-each';
import {formatExecError, formatResultsErrors} from 'jest-message-util';
import {
SnapshotState,
SnapshotStateType,
addSerializer,
buildSnapshotResolver,
} from 'jest-snapshot';
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
12 changes: 6 additions & 6 deletions packages/jest-core/src/TestScheduler.ts
Expand Up @@ -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';
Expand Down Expand Up @@ -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,
Expand Down
9 changes: 3 additions & 6 deletions packages/jest-jasmine2/src/index.ts
Expand Up @@ -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';
Expand Down Expand Up @@ -138,7 +138,7 @@ export default async function jasmine2(
});
}

const snapshotState: SnapshotStateType = await runtime
const snapshotState: SnapshotState = await runtime
.requireInternalModule<typeof import('./setup_jest_globals')>(
path.resolve(__dirname, './setup_jest_globals.js'),
)
Expand Down Expand Up @@ -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
Expand Down
3 changes: 1 addition & 2 deletions packages/jest-jasmine2/src/setup_jest_globals.ts
Expand Up @@ -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';
Expand Down Expand Up @@ -94,7 +93,7 @@ export default async function setupJestGlobals({
globalConfig,
localRequire,
testPath,
}: SetupOptions): Promise<SnapshotStateType> {
}: SetupOptions): Promise<SnapshotState> {
// Jest tests snapshotSerializers in order preceding built-in serializers.
// Therefore, add in reverse because the last added is the first tested.
config.snapshotSerializers
Expand Down
4 changes: 2 additions & 2 deletions packages/jest-runtime/src/index.ts
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 1 addition & 3 deletions packages/jest-snapshot/src/__tests__/matcher.test.ts
Expand Up @@ -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';
Expand Down
14 changes: 6 additions & 8 deletions packages/jest-snapshot/src/__tests__/printSnapshot.test.ts
Expand Up @@ -19,7 +19,12 @@ import {
bForeground2,
bForeground3,
} from '../colors';
import jestSnapshot = require('../index');
import {
toMatchInlineSnapshot,
toMatchSnapshot,
toThrowErrorMatchingInlineSnapshot,
toThrowErrorMatchingSnapshot,
} from '../index';
import {
getReceivedColorForChalkInstance,
getSnapshotColorForChalkInstance,
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 1 addition & 3 deletions packages/jest-snapshot/src/__tests__/throwMatcher.test.ts
Expand Up @@ -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;

Expand Down
64 changes: 22 additions & 42 deletions packages/jest-snapshot/src/index.ts
Expand Up @@ -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,
Expand All @@ -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(
Expand All @@ -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 +
'`'
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -155,7 +157,7 @@ const cleanup = (
};
};

const toMatchSnapshot = function (
export const toMatchSnapshot = function (
this: Context,
received: unknown,
propertiesOrHint?: object | Config.Path,
Expand Down Expand Up @@ -214,7 +216,7 @@ const toMatchSnapshot = function (
});
};

const toMatchInlineSnapshot = function (
export const toMatchInlineSnapshot = function (
this: Context,
received: unknown,
propertiesOrSnapshot?: object | string,
Expand Down Expand Up @@ -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),
),
);
}
Expand Down Expand Up @@ -353,7 +355,7 @@ const _toMatchSnapshot = (config: MatchSnapshotConfig) => {
pass: false,
};
} else {
received = utils.deepMerge(received, properties);
received = deepMerge(received, properties);
}
}

Expand Down Expand Up @@ -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
Expand All @@ -431,7 +433,7 @@ const toThrowErrorMatchingSnapshot = function (
);
};

const toThrowErrorMatchingInlineSnapshot = function (
export const toThrowErrorMatchingInlineSnapshot = function (
this: Context,
received: unknown,
inlineSnapshot?: string,
Expand All @@ -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),
),
);
}
Expand Down Expand Up @@ -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;