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(snapshot): provide config to resolveSnapshotPath #6800

Merged
merged 13 commits into from
Nov 13, 2024
2 changes: 1 addition & 1 deletion docs/config/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -1887,7 +1887,7 @@ A list of paths to snapshot serializer modules for snapshot testing, useful if y

### resolveSnapshotPath<NonProjectOption />

- **Type**: `(testPath: string, snapExtension: string) => string`
- **Type**: `(testPath: string, snapExtension: string, context: { config: SerializedConfig }) => string`
- **Default**: stores snapshot files in `__snapshots__` directory

Overrides default snapshot path. For example, to store snapshots next to test files:
Expand Down
4 changes: 3 additions & 1 deletion packages/browser/src/node/rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ export function setupBrowserRpc(server: BrowserServer) {
return ctx.report('onUserConsoleLog', log)
},
resolveSnapshotPath(testPath) {
return ctx.snapshot.resolvePath(testPath)
return ctx.snapshot.resolvePath(testPath, {
config: project.getSerializableConfig(),
})
},
resolveSnapshotRawPath(testPath, rawPath) {
return ctx.snapshot.resolveRawPath(testPath, rawPath)
Expand Down
4 changes: 2 additions & 2 deletions packages/snapshot/src/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class SnapshotManager {
addSnapshotResult(this.summary, result)
}

resolvePath(testPath: string): string {
resolvePath(testPath: string, context?: any): string {
sheremet-va marked this conversation as resolved.
Show resolved Hide resolved
const resolver
= this.options.resolveSnapshotPath || (() => {
return join(
Expand All @@ -32,7 +32,7 @@ export class SnapshotManager {
)
})

const path = resolver(testPath, this.extension)
const path = resolver(testPath, this.extension, context)
return path
}

Expand Down
2 changes: 1 addition & 1 deletion packages/snapshot/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export interface SnapshotStateOptions {
snapshotEnvironment: SnapshotEnvironment
expand?: boolean
snapshotFormat?: PrettyFormatOptions
resolveSnapshotPath?: (path: string, extension: string) => string
resolveSnapshotPath?: (path: string, extension: string, context?: any) => string
}

export interface SnapshotMatchOptions {
Expand Down
4 changes: 3 additions & 1 deletion packages/vitest/src/node/pools/rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ export function createMethodsRPC(project: WorkspaceProject, options: MethodsOpti
ctx.snapshot.add(snapshot)
},
resolveSnapshotPath(testPath: string) {
return ctx.snapshot.resolvePath(testPath)
return ctx.snapshot.resolvePath(testPath, {
config: project.getSerializableConfig(),
})
},
async getSourceMap(id, force) {
if (force) {
Expand Down
9 changes: 8 additions & 1 deletion packages/vitest/src/node/types/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { SnapshotStateOptions } from '@vitest/snapshot'
import type { AliasOptions, ConfigEnv, DepOptimizationConfig, ServerOptions, UserConfig as ViteUserConfig } from 'vite'
import type { ViteNodeServerOptions } from 'vite-node'
import type { ChaiConfig } from '../../integrations/chai/config'
import type { SerializedConfig } from '../../runtime/config'
import type { EnvironmentOptions } from '../../types/environment'
import type { Arrayable, ErrorWithDiff, ParsedStack, ProvidedContext } from '../../types/general'
import type { HappyDOMOptions } from '../../types/happy-dom-options'
Expand Down Expand Up @@ -224,6 +225,12 @@ type ReporterWithOptions<Name extends ReporterName = ReporterName> =
: [Name, Partial<BuiltinReporterOptions[Name]>]
: [Name, Record<string, unknown>]

export type ResolveSnapshotPathHandler = (
testPath: string,
snapExtension: string,
context: { config: SerializedConfig }
) => string

export interface InlineConfig {
/**
* Name of the project. Will be used to display in the reporter.
Expand Down Expand Up @@ -573,7 +580,7 @@ export interface InlineConfig {
/**
* Resolve custom snapshot path
*/
resolveSnapshotPath?: (path: string, extension: string) => string
resolveSnapshotPath?: ResolveSnapshotPathHandler

/**
* Path to a custom snapshot environment module that has a default export of `SnapshotEnvironment` object.
Expand Down
1 change: 1 addition & 0 deletions packages/vitest/src/public/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export type {
ProjectConfig,
ResolvedConfig,
ResolvedProjectConfig,
ResolveSnapshotPathHandler,
RuntimeConfig,
SequenceHooks,
SequenceSetupFiles,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`basic 1`] = `"hello"`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`basic 1`] = `"hello"`;
5 changes: 5 additions & 0 deletions test/config/fixtures/snapshot-path-context/basic.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { test, expect } from 'vitest'

test('basic', () => {
expect('hello').toMatchSnapshot()
})
15 changes: 15 additions & 0 deletions test/config/fixtures/snapshot-path-context/vitest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { join, dirname, basename } from 'node:path';
import { defineConfig } from 'vitest/config';

export default defineConfig({
test: {
resolveSnapshotPath(path, extension, context) {
return join(
dirname(path),
'__snapshots__',
context.config.name ?? 'na',
basename(path) + extension
);
},
},
});
18 changes: 18 additions & 0 deletions test/config/fixtures/snapshot-path-context/vitest.workspace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { defineWorkspace } from 'vitest/config'

export default defineWorkspace([
{
extends: './vitest.config.ts',
test: {
name: 'project1',
root: import.meta.dirname,
}
},
{
extends: './vitest.config.ts',
test: {
name: 'project2',
root: import.meta.dirname,
}
}
])
19 changes: 19 additions & 0 deletions test/config/test/snapshot.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { expect, test } from 'vitest'
import { runVitest } from '../../test-utils'

test('resolveSnapshotPath context', async () => {
const { stderr, ctx } = await runVitest({
root: './fixtures/snapshot-path-context',
})
expect(stderr).toBe('')
expect(
Object.fromEntries(
ctx!.state.getFiles().map(f => [`${f.projectName}|${f.name}`, f.result?.state]),
),
).toMatchInlineSnapshot(`
{
"project1|basic.test.ts": "pass",
"project2|basic.test.ts": "pass",
}
`)
})