Skip to content

Commit

Permalink
feat(snapshot): provide config to resolveSnapshotPath (#6800)
Browse files Browse the repository at this point in the history
  • Loading branch information
hi-ogawa authored Nov 13, 2024
1 parent 697c35c commit 746d898
Show file tree
Hide file tree
Showing 13 changed files with 87 additions and 8 deletions.
2 changes: 1 addition & 1 deletion docs/config/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -1899,7 +1899,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
6 changes: 4 additions & 2 deletions packages/browser/src/node/rpc.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ErrorWithDiff } from 'vitest'
import type { BrowserCommandContext } from 'vitest/node'
import type { BrowserCommandContext, ResolveSnapshotPathHandlerContext } from 'vitest/node'
import type { WebSocket } from 'ws'
import type { BrowserServer } from './server'
import type { WebSocketBrowserEvents, WebSocketBrowserHandlers } from './types'
Expand Down 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<ResolveSnapshotPathHandlerContext>(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<T = any>(testPath: string, context?: T): string {
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
5 changes: 4 additions & 1 deletion packages/vitest/src/node/pools/rpc.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { RawSourceMap } from 'vite-node'
import type { RuntimeRPC } from '../../types/rpc'
import type { ResolveSnapshotPathHandlerContext } from '../types/config'
import type { WorkspaceProject } from '../workspace'
import { mkdir, writeFile } from 'node:fs/promises'
import { join } from 'pathe'
Expand All @@ -20,7 +21,9 @@ export function createMethodsRPC(project: WorkspaceProject, options: MethodsOpti
ctx.snapshot.add(snapshot)
},
resolveSnapshotPath(testPath: string) {
return ctx.snapshot.resolvePath(testPath)
return ctx.snapshot.resolvePath<ResolveSnapshotPathHandlerContext>(testPath, {
config: project.getSerializableConfig(),
})
},
async getSourceMap(id, force) {
if (force) {
Expand Down
11 changes: 10 additions & 1 deletion packages/vitest/src/node/types/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type { SerializedDiffOptions } from '@vitest/utils/diff'
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 @@ -225,6 +226,14 @@ type ReporterWithOptions<Name extends ReporterName = ReporterName> =
: [Name, Partial<BuiltinReporterOptions[Name]>]
: [Name, Record<string, unknown>]

export interface ResolveSnapshotPathHandlerContext { config: SerializedConfig }

export type ResolveSnapshotPathHandler = (
testPath: string,
snapExtension: string,
context: ResolveSnapshotPathHandlerContext
) => string

export interface InlineConfig {
/**
* Name of the project. Will be used to display in the reporter.
Expand Down Expand Up @@ -574,7 +583,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
2 changes: 2 additions & 0 deletions packages/vitest/src/public/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ export type {
ProjectConfig,
ResolvedConfig,
ResolvedProjectConfig,
ResolveSnapshotPathHandler,
ResolveSnapshotPathHandlerContext,
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",
}
`)
})

0 comments on commit 746d898

Please sign in to comment.