Skip to content

Commit

Permalink
Adds options for configuring the snapshot and inline snapshot seriali…
Browse files Browse the repository at this point in the history
…zers (jestjs#11654)
  • Loading branch information
orta authored and splincode committed Aug 24, 2021
1 parent d2a41fb commit abc1644
Show file tree
Hide file tree
Showing 18 changed files with 140 additions and 15 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,8 @@

### Features

- `[jest-cli]` Adds a new config options `snapshotFormat` which offers a way to override any of the formatting settings which come with [pretty-format](https://www.npmjs.com/package/pretty-format#usage-with-options). ([#11654](https://github.com/facebook/jest/pull/11654))

### Fixes

- `[jest-types]` Compat with `@types/node` v16 ([#11645](https://github.com/facebook/jest/pull/11645))
Expand Down
35 changes: 35 additions & 0 deletions docs/Configuration.md
Expand Up @@ -945,6 +945,41 @@ Default: `5`

The number of seconds after which a test is considered as slow and reported as such in the results.

### `snapshotFormat` \[object]

Default: `undefined`

Allows overriding specific snapshot formatting options documented in the [pretty-format readme](https://www.npmjs.com/package/pretty-format#usage-with-options). For example, this config would have the snapshot formatter not print a prefix for "Object" and "Array":

```json
{
"jest": {
"snapshotFormat": {
"printBasicPrototype": false
}
}
}
```

```ts
import {expect, test} from '@jest/globals';

test('does not show prototypes for object and array inline', () => {
const object = {
array: [{hello: 'Danger'}],
};
expect(object).toMatchInlineSnapshot(`
{
"array": [
{
"hello": "Danger",
},
],
}
`);
});
```

### `snapshotResolver` \[string]

Default: `undefined`
Expand Down
@@ -0,0 +1,11 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`snapshot serializer uses 8 chars for indent, and shows no prototypes for object and array in a snapshot: no prototypes 1`] = `
{
"array": [
{
"hello": "Danger",
},
],
}
`;
32 changes: 32 additions & 0 deletions e2e/snapshot-formatting-changes/__tests__/snapshot.test.js
@@ -0,0 +1,32 @@
/**
* 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 serializer', () => {
it('does not show prototypes for object and array inline', () => {
const object = {
array: [{hello: 'Danger'}],
};
expect(object).toMatchInlineSnapshot(`
{
"array": [
{
"hello": "Danger",
},
],
}
`);
});

it('uses 8 chars for indent, and shows no prototypes for object and array in a snapshot', () => {
const object = {
array: [{hello: 'Danger'}],
};
expect(object).toMatchSnapshot('no prototypes');
});
});
9 changes: 9 additions & 0 deletions e2e/snapshot-formatting-changes/package.json
@@ -0,0 +1,9 @@
{
"jest": {
"testEnvironment": "node",
"snapshotFormat": {
"printBasicPrototype": false,
"indent": 8
}
}
}
Expand Up @@ -156,6 +156,7 @@ export const initialize = async ({
const snapshotState = new SnapshotState(snapshotPath, {
expand,
prettierPath: config.prettierPath,
snapshotFormat: config.snapshotFormat,
updateSnapshot,
});
// @ts-expect-error: snapshotState is a jest extension of `expect`
Expand Down
2 changes: 2 additions & 0 deletions packages/jest-config/src/ValidConfig.ts
Expand Up @@ -8,6 +8,7 @@
import type {Config} from '@jest/types';
import {replacePathSepForRegex} from 'jest-regex-util';
import {multipleValidOptions} from 'jest-validate';
import {DEFAULT_OPTIONS as PRETTY_FORMAT_DEFAULTS} from 'pretty-format';
import {NODE_MODULES} from './constants';

const NODE_MODULES_REGEXP = replacePathSepForRegex(NODE_MODULES);
Expand Down Expand Up @@ -109,6 +110,7 @@ const initialOptions: Config.InitialOptions = {
skipFilter: false,
skipNodeResolution: false,
slowTestThreshold: 5,
snapshotFormat: PRETTY_FORMAT_DEFAULTS,
snapshotResolver: '<rootDir>/snapshotResolver.js',
snapshotSerializers: ['my-serializer-module'],
testEnvironment: 'jest-environment-jsdom',
Expand Down
2 changes: 2 additions & 0 deletions packages/jest-config/src/index.ts
Expand Up @@ -149,6 +149,7 @@ const groupOptions = (
runTestsByPath: options.runTestsByPath,
silent: options.silent,
skipFilter: options.skipFilter,
snapshotFormat: options.snapshotFormat,
testFailureExitCode: options.testFailureExitCode,
testNamePattern: options.testNamePattern,
testPathPattern: options.testPathPattern,
Expand Down Expand Up @@ -204,6 +205,7 @@ const groupOptions = (
skipFilter: options.skipFilter,
skipNodeResolution: options.skipNodeResolution,
slowTestThreshold: options.slowTestThreshold,
snapshotFormat: options.snapshotFormat,
snapshotResolver: options.snapshotResolver,
snapshotSerializers: options.snapshotSerializers,
testEnvironment: options.testEnvironment,
Expand Down
1 change: 1 addition & 0 deletions packages/jest-config/src/normalize.ts
Expand Up @@ -997,6 +997,7 @@ export default async function normalize(
case 'skipFilter':
case 'skipNodeResolution':
case 'slowTestThreshold':
case 'snapshotFormat':
case 'testEnvironment':
case 'testEnvironmentOptions':
case 'testFailureExitCode':
Expand Down
Expand Up @@ -41,6 +41,7 @@ exports[`prints the config object 1`] = `
"skipFilter": false,
"skipNodeResolution": false,
"slowTestThreshold": 5,
"snapshotFormat": {},
"snapshotSerializers": [],
"testEnvironment": "node",
"testEnvironmentOptions": {},
Expand Down Expand Up @@ -94,6 +95,7 @@ exports[`prints the config object 1`] = `
"runTestsByPath": false,
"silent": false,
"skipFilter": false,
"snapshotFormat": {},
"testFailureExitCode": 1,
"testNamePattern": "",
"testPathPattern": "",
Expand Down
3 changes: 2 additions & 1 deletion packages/jest-jasmine2/src/setup_jest_globals.ts
Expand Up @@ -106,12 +106,13 @@ export default async ({

patchJasmine();
const {expand, updateSnapshot} = globalConfig;
const {prettierPath} = config;
const {prettierPath, snapshotFormat} = config;
const snapshotResolver = await buildSnapshotResolver(config, localRequire);
const snapshotPath = snapshotResolver.resolveSnapshotPath(testPath);
const snapshotState = new SnapshotState(snapshotPath, {
expand,
prettierPath,
snapshotFormat,
updateSnapshot,
});
// @ts-expect-error: snapshotState is a jest extension of `expect`
Expand Down
8 changes: 7 additions & 1 deletion packages/jest-snapshot/src/State.ts
Expand Up @@ -8,6 +8,7 @@
import * as fs from 'graceful-fs';
import type {Config} from '@jest/types';
import {getStackTraceLines, getTopFrame} from 'jest-message-util';
import type {OptionsReceived as PrettyFormatOptions} from 'pretty-format';
import {InlineSnapshot, saveInlineSnapshots} from './InlineSnapshots';
import type {SnapshotData} from './types';
import {
Expand All @@ -25,6 +26,7 @@ export type SnapshotStateOptions = {
updateSnapshot: Config.SnapshotUpdateState;
prettierPath: Config.Path;
expand?: boolean;
snapshotFormat: PrettyFormatOptions;
};

export type SnapshotMatchOptions = {
Expand Down Expand Up @@ -61,6 +63,7 @@ export default class SnapshotState {
private _inlineSnapshots: Array<InlineSnapshot>;
private _uncheckedKeys: Set<string>;
private _prettierPath: Config.Path;
private _snapshotFormat: PrettyFormatOptions;

added: number;
expand: boolean;
Expand Down Expand Up @@ -88,6 +91,7 @@ export default class SnapshotState {
this.unmatched = 0;
this._updateSnapshot = options.updateSnapshot;
this.updated = 0;
this._snapshotFormat = options.snapshotFormat;
}

markSnapshotsAsCheckedForTest(testName: string): void {
Expand Down Expand Up @@ -201,7 +205,9 @@ export default class SnapshotState {
this._uncheckedKeys.delete(key);
}

const receivedSerialized = addExtraLineBreaks(serialize(received));
const receivedSerialized = addExtraLineBreaks(
serialize(received, undefined, this._snapshotFormat),
);
const expected = isInline ? inlineSnapshot : this._snapshotData[key];
const pass = expected === receivedSerialized;
const hasSnapshot = expected !== undefined;
Expand Down
12 changes: 10 additions & 2 deletions packages/jest-snapshot/src/utils.ts
Expand Up @@ -10,7 +10,10 @@ import chalk = require('chalk');
import * as fs from 'graceful-fs';
import naturalCompare = require('natural-compare');
import type {Config} from '@jest/types';
import {format as prettyFormat} from 'pretty-format';
import {
OptionsReceived as PrettyFormatOptions,
format as prettyFormat,
} from 'pretty-format';
import {getSerializers} from './plugins';
import type {SnapshotData} from './types';

Expand Down Expand Up @@ -152,13 +155,18 @@ export const removeLinesBeforeExternalMatcherTrap = (stack: string): string => {
const escapeRegex = true;
const printFunctionName = false;

export const serialize = (val: unknown, indent = 2): string =>
export const serialize = (
val: unknown,
indent = 2,
formatOverrides: PrettyFormatOptions = {},
): string =>
normalizeNewlines(
prettyFormat(val, {
escapeRegex,
indent,
plugins: getSerializers(),
printFunctionName,
...formatOverrides,
}),
);

Expand Down

0 comments on commit abc1644

Please sign in to comment.