feat: add resolveSnapshotPath option (#1101)

This commit is contained in:
Vladimir 2022-04-05 13:04:33 +03:00 committed by GitHub
parent 6f552751df
commit 5cc592be97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 70 additions and 16 deletions

View File

@ -431,3 +431,18 @@ Overrides Vite mode.
Run tests only against changed files. If no value is provided, it will run tests against uncomitted changes (includes staged and unstaged).
To run tests against changes made in last commit, you can use `--changed HEAD~1`. You can also pass commit hash or branch name.
### resolveSnapshotPath
- **Type**: `(testPath: string, snapExtension: string) => string`
- **Default**: stores snapshot files in `__snapshots__` directory
Overrides default snapshot path. For example, to store snapshots next to test files:
```ts
export default {
test: {
resolveSnapshotPath: (testPath, snapExtension) => testPath + snapExtension,
},
}
```

View File

@ -1,4 +1,3 @@
import path from 'pathe'
import { expect } from 'chai'
import type { SnapshotResult, Test } from '../../types'
import { rpc } from '../../runtime/rpc'
@ -13,18 +12,12 @@ export interface Context {
fullTitle?: string
}
const resolveSnapshotPath = (testPath: string) =>
path.join(
path.join(path.dirname(testPath), '__snapshots__'),
`${path.basename(testPath)}.snap`,
)
export class SnapshotClient {
test: Test | undefined
testFile = ''
snapshotState: SnapshotState | undefined
setTest(test: Test) {
async setTest(test: Test) {
this.test = test
if (this.testFile !== this.test.file!.filepath) {
@ -33,7 +26,7 @@ export class SnapshotClient {
this.testFile = this.test!.file!.filepath
this.snapshotState = new SnapshotState(
resolveSnapshotPath(this.testFile),
await rpc().resolveSnapshotPath(this.testFile),
getWorkerState().config.snapshotOptions,
)
}

View File

@ -1,19 +1,33 @@
import type { ResolvedConfig, SnapshotResult, SnapshotStateOptions, SnapshotSummary } from '../../types'
import { basename, dirname, join } from 'pathe'
import type { SnapshotResult, SnapshotStateOptions, SnapshotSummary } from '../../types'
export class SnapshotManager {
summary: SnapshotSummary = undefined!
extension = '.snap'
constructor(public config: ResolvedConfig) {
constructor(public options: SnapshotStateOptions) {
this.clear()
}
clear() {
this.summary = emptySummary(this.config.snapshotOptions)
this.summary = emptySummary(this.options)
}
add(result: SnapshotResult) {
addSnapshotResult(this.summary, result)
}
resolvePath(testPath: string) {
const resolver = this.options.resolveSnapshotPath || (() => {
return join(
join(
dirname(testPath), '__snapshots__'),
`${basename(testPath)}${this.extension}`,
)
})
return resolver(testPath, this.extension)
}
}
export function emptySummary(options: SnapshotStateOptions): SnapshotSummary {

View File

@ -110,8 +110,12 @@ export function resolveConfig(
: UPDATE_SNAPSHOT
? 'all'
: 'new',
resolveSnapshotPath: options.resolveSnapshotPath,
}
if (options.resolveSnapshotPath)
delete (resolved as UserConfig).resolveSnapshotPath
if (process.env.VITEST_MAX_THREADS)
resolved.maxThreads = parseInt(process.env.VITEST_MAX_THREADS)

View File

@ -62,7 +62,7 @@ export class Vitest {
this.server = server
this.config = resolved
this.state = new StateManager()
this.snapshot = new SnapshotManager(resolved)
this.snapshot = new SnapshotManager({ ...resolved.snapshotOptions })
this.reporters = resolved.reporters
.map((i) => {
if (typeof i === 'string') {
@ -91,6 +91,11 @@ export class Vitest {
const hasCustomReporter = toArray(this.config.reporters)
.some(reporter => typeof reporter !== 'string')
// cannot be serialized for sending to workers
// reimplemented on rpc
if (this.config.snapshotOptions.resolveSnapshotPath)
this.config.snapshotOptions.resolveSnapshotPath = undefined
if (!hasCustomReporter && !this.configOverride)
return this.config

View File

@ -118,6 +118,9 @@ function createChannel(ctx: Vitest) {
snapshotSaved(snapshot) {
ctx.snapshot.add(snapshot)
},
resolveSnapshotPath(testPath: string) {
return ctx.snapshot.resolvePath(testPath)
},
async getSourceMap(id, force) {
if (force) {
const mod = ctx.server.moduleGraph.getModuleById(id)

View File

@ -78,7 +78,7 @@ export async function runTest(test: Test) {
clearModuleMocks()
getSnapshotClient().setTest(test)
await getSnapshotClient().setTest(test)
const workerState = getWorkerState()

View File

@ -290,6 +290,11 @@ export interface InlineConfig {
* Format options for snapshot testing.
*/
snapshotFormat?: PrettyFormatOptions
/**
* Resolve custom snapshot path
*/
resolveSnapshotPath?: (path: string, extension: string) => string
}
export interface UserConfig extends InlineConfig {
@ -338,7 +343,7 @@ export interface UserConfig extends InlineConfig {
changed?: boolean | string
}
export interface ResolvedConfig extends Omit<Required<UserConfig>, 'config' | 'filters' | 'coverage' | 'testNamePattern' | 'related' | 'api' | 'reporters'> {
export interface ResolvedConfig extends Omit<Required<UserConfig>, 'config' | 'filters' | 'coverage' | 'testNamePattern' | 'related' | 'api' | 'reporters' | 'resolveSnapshotPath'> {
base?: string
config?: string

View File

@ -8,6 +8,7 @@ export interface SnapshotStateOptions {
updateSnapshot: SnapshotUpdateState
expand?: boolean
snapshotFormat?: PrettyFormatOptions
resolveSnapshotPath?: (path: string, extension: string) => string
}
export interface SnapshotMatchOptions {

View File

@ -29,6 +29,7 @@ export interface WorkerRPC {
onTaskUpdate: (pack: TaskResultPack[]) => void
snapshotSaved: (snapshot: SnapshotResult) => void
resolveSnapshotPath: (testPath: string) => string
}
export interface WorkerGlobalState {

View File

@ -0,0 +1,5 @@
import { expect, test } from 'vitest'
test('snapshot is stored close to file', () => {
expect('moved snapshot').toMatchSnapshot()
})

View File

@ -0,0 +1,3 @@
// Vitest Snapshot v1
exports[`snapshot is stored close to file 1`] = `"moved snapshot"`;

View File

@ -1,4 +1,4 @@
import { resolve } from 'pathe'
import { basename, dirname, join, resolve } from 'pathe'
import { defineConfig } from 'vite'
export default defineConfig({
@ -45,5 +45,10 @@ export default defineConfig({
coverage: {
reporter: ['text', 'html'],
},
resolveSnapshotPath: (path, extension) => {
if (path.includes('moved-snapshot'))
return path + extension
return join(dirname(path), '__snapshots__', `${basename(path)}${extension}`)
},
},
})