diff --git a/packages/pretty-format/src/types.ts b/packages/pretty-format/src/types.ts index bbfc77221..ad1b90898 100644 --- a/packages/pretty-format/src/types.ts +++ b/packages/pretty-format/src/types.ts @@ -24,6 +24,9 @@ export type Theme = Required<{ value?: string }> +/** + * compare function used when sorting object keys, `null` can be used to skip over sorting. + */ export type CompareKeys = ((a: string, b: string) => number) | null | undefined type RequiredOptions = Required diff --git a/packages/vitest/src/node/config/resolveConfig.ts b/packages/vitest/src/node/config/resolveConfig.ts index dd17b9c35..3ee4fb072 100644 --- a/packages/vitest/src/node/config/resolveConfig.ts +++ b/packages/vitest/src/node/config/resolveConfig.ts @@ -489,6 +489,10 @@ export function resolveConfig( if (resolved.snapshotFormat && 'plugins' in resolved.snapshotFormat) { (resolved.snapshotFormat as any).plugins = [] + // TODO: support it via separate config (like DiffOptions) or via `Function.toString()` + if (typeof resolved.snapshotFormat.compareKeys === 'function') { + throw new TypeError(`"snapshotFormat.compareKeys" function is not supported.`) + } } const UPDATE_SNAPSHOT = resolved.update || process.env.UPDATE_SNAPSHOT diff --git a/packages/vitest/src/node/config/serializeConfig.ts b/packages/vitest/src/node/config/serializeConfig.ts index b67b18b0a..4eda6a8f5 100644 --- a/packages/vitest/src/node/config/serializeConfig.ts +++ b/packages/vitest/src/node/config/serializeConfig.ts @@ -120,7 +120,6 @@ export function serializeConfig( updateSnapshot: coreConfig.snapshotOptions.updateSnapshot, snapshotFormat: { ...coreConfig.snapshotOptions.snapshotFormat, - compareKeys: undefined, }, expand: config.snapshotOptions.expand diff --git a/packages/vitest/src/node/types/config.ts b/packages/vitest/src/node/types/config.ts index 93bb3177a..7a05fadf4 100644 --- a/packages/vitest/src/node/types/config.ts +++ b/packages/vitest/src/node/types/config.ts @@ -568,7 +568,9 @@ export interface InlineConfig { /** * Format options for snapshot testing. */ - snapshotFormat?: Omit + snapshotFormat?: Omit & { + compareKeys?: null | undefined + } /** * Path to a module which has a default export of diff config. diff --git a/test/snapshots/test/compare-keys.test.ts b/test/snapshots/test/compare-keys.test.ts new file mode 100644 index 000000000..e1c442baa --- /dev/null +++ b/test/snapshots/test/compare-keys.test.ts @@ -0,0 +1,85 @@ +import fs from 'node:fs' +import { join } from 'node:path' +import { expect, test } from 'vitest' +import { runVitest } from '../../test-utils' + +test('compareKeys', async () => { + const root = join(import.meta.dirname, 'fixtures/compare-keys') + fs.rmSync(join(root, '__snapshots__'), { recursive: true, force: true }) + + // compareKeys null + let vitest = await runVitest({ + root, + update: true, + snapshotFormat: { + compareKeys: null, + }, + }) + expect(vitest.stderr).toBe('') + expect(fs.readFileSync(join(root, '__snapshots__/basic.test.ts.snap'), 'utf-8')).toMatchInlineSnapshot(` + "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + + exports[\`compareKeys 1\`] = \` + { + "a": 1, + "b": 2, + "c": 3, + } + \`; + + exports[\`compareKeys 2\`] = \` + { + "c": 1, + "b": 2, + "a": 3, + } + \`; + + exports[\`compareKeys 3\`] = \` + { + "b": 1, + "a": 2, + "c": 3, + } + \`; + " + `) + + // compareKeys undefined + vitest = await runVitest({ + root, + update: true, + snapshotFormat: { + compareKeys: undefined, + }, + }) + expect(vitest.stderr).toBe('') + expect(fs.readFileSync(join(root, '__snapshots__/basic.test.ts.snap'), 'utf-8')).toMatchInlineSnapshot(` + "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + + exports[\`compareKeys 1\`] = \` + { + "a": 1, + "b": 2, + "c": 3, + } + \`; + + exports[\`compareKeys 2\`] = \` + { + "a": 3, + "b": 2, + "c": 1, + } + \`; + + exports[\`compareKeys 3\`] = \` + { + "a": 2, + "b": 1, + "c": 3, + } + \`; + " + `) +}) diff --git a/test/snapshots/test/fixtures/compare-keys/__snapshots__/basic.test.ts.snap b/test/snapshots/test/fixtures/compare-keys/__snapshots__/basic.test.ts.snap new file mode 100644 index 000000000..b14ee3e77 --- /dev/null +++ b/test/snapshots/test/fixtures/compare-keys/__snapshots__/basic.test.ts.snap @@ -0,0 +1,25 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`compareKeys 1`] = ` +{ + "a": 1, + "b": 2, + "c": 3, +} +`; + +exports[`compareKeys 2`] = ` +{ + "a": 3, + "b": 2, + "c": 1, +} +`; + +exports[`compareKeys 3`] = ` +{ + "a": 2, + "b": 1, + "c": 3, +} +`; diff --git a/test/snapshots/test/fixtures/compare-keys/basic.test.ts b/test/snapshots/test/fixtures/compare-keys/basic.test.ts new file mode 100644 index 000000000..2cfda2ca5 --- /dev/null +++ b/test/snapshots/test/fixtures/compare-keys/basic.test.ts @@ -0,0 +1,21 @@ +import { test, expect } from 'vitest'; + +test('compareKeys', () => { + expect({ + a: 1, + b: 2, + c: 3, + }).toMatchSnapshot(); + + expect({ + c: 1, + b: 2, + a: 3, + }).toMatchSnapshot(); + + expect({ + b: 1, + a: 2, + c: 3, + }).toMatchSnapshot(); +}); diff --git a/test/snapshots/test/fixtures/compare-keys/vitest.config.ts b/test/snapshots/test/fixtures/compare-keys/vitest.config.ts new file mode 100644 index 000000000..4c2e06d40 --- /dev/null +++ b/test/snapshots/test/fixtures/compare-keys/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + snapshotFormat: { + // compareKeys: null, + } + } +})