Skip to content

Commit

Permalink
feat: add resolveSnapshotPath option (#1101)
Browse files Browse the repository at this point in the history
  • Loading branch information
sheremet-va committed Apr 5, 2022
1 parent 6f55275 commit 5cc592b
Show file tree
Hide file tree
Showing 13 changed files with 70 additions and 16 deletions.
15 changes: 15 additions & 0 deletions docs/config/index.md
Expand Up @@ -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,
},
}
```
11 changes: 2 additions & 9 deletions packages/vitest/src/integrations/snapshot/client.ts
@@ -1,4 +1,3 @@
import path from 'pathe'
import { expect } from 'chai'
import type { SnapshotResult, Test } from '../../types'
import { rpc } from '../../runtime/rpc'
Expand All @@ -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) {
Expand All @@ -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,
)
}
Expand Down
20 changes: 17 additions & 3 deletions packages/vitest/src/integrations/snapshot/manager.ts
@@ -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 {
Expand Down
4 changes: 4 additions & 0 deletions packages/vitest/src/node/config.ts
Expand Up @@ -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)

Expand Down
7 changes: 6 additions & 1 deletion packages/vitest/src/node/core.ts
Expand Up @@ -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') {
Expand Down Expand Up @@ -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

Expand Down
3 changes: 3 additions & 0 deletions packages/vitest/src/node/pool.ts
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion packages/vitest/src/runtime/run.ts
Expand Up @@ -78,7 +78,7 @@ export async function runTest(test: Test) {

clearModuleMocks()

getSnapshotClient().setTest(test)
await getSnapshotClient().setTest(test)

const workerState = getWorkerState()

Expand Down
7 changes: 6 additions & 1 deletion packages/vitest/src/types/config.ts
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions packages/vitest/src/types/snapshot.ts
Expand Up @@ -8,6 +8,7 @@ export interface SnapshotStateOptions {
updateSnapshot: SnapshotUpdateState
expand?: boolean
snapshotFormat?: PrettyFormatOptions
resolveSnapshotPath?: (path: string, extension: string) => string
}

export interface SnapshotMatchOptions {
Expand Down
1 change: 1 addition & 0 deletions packages/vitest/src/types/worker.ts
Expand Up @@ -29,6 +29,7 @@ export interface WorkerRPC {
onTaskUpdate: (pack: TaskResultPack[]) => void

snapshotSaved: (snapshot: SnapshotResult) => void
resolveSnapshotPath: (testPath: string) => string
}

export interface WorkerGlobalState {
Expand Down
5 changes: 5 additions & 0 deletions test/core/test/moved-snapshot.test.ts
@@ -0,0 +1,5 @@
import { expect, test } from 'vitest'

test('snapshot is stored close to file', () => {
expect('moved snapshot').toMatchSnapshot()
})
3 changes: 3 additions & 0 deletions test/core/test/moved-snapshot.test.ts.snap
@@ -0,0 +1,3 @@
// Vitest Snapshot v1

exports[`snapshot is stored close to file 1`] = `"moved snapshot"`;
7 changes: 6 additions & 1 deletion test/core/vitest.config.ts
@@ -1,4 +1,4 @@
import { resolve } from 'pathe'
import { basename, dirname, join, resolve } from 'pathe'
import { defineConfig } from 'vite'

export default defineConfig({
Expand Down Expand Up @@ -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}`)
},
},
})

0 comments on commit 5cc592b

Please sign in to comment.