Skip to content

Commit

Permalink
refactor: add vitest/snapshot entry point
Browse files Browse the repository at this point in the history
  • Loading branch information
sheremet-va committed May 2, 2024
1 parent 31300c8 commit a54ed70
Show file tree
Hide file tree
Showing 16 changed files with 131 additions and 11 deletions.
4 changes: 3 additions & 1 deletion docs/config/index.md
Expand Up @@ -2201,7 +2201,7 @@ The `location` property has `column` and `line` values that correspond to the `t
This option has no effect if you do not use custom code that relies on this.
:::

### snapshotEnvironment <Badge type="info">1.5.0+</Badge> {#snapshotEnvironment}
### snapshotEnvironment <Version>1.6.0</Version> {#snapshotEnvironment}

- **Type:** `string`

Expand All @@ -2221,6 +2221,8 @@ export interface SnapshotEnvironment {
}
```

You can extend default `VitestSnapshotEnvironment` from `vitest/snapshot` entry point if you need to overwrite only a part of the API.

::: warning
This is a low-level option and should be used only for advanced cases where you don't have access to default Node.js APIs.

Expand Down
9 changes: 6 additions & 3 deletions packages/browser/src/client/runner.ts
Expand Up @@ -3,7 +3,7 @@ import type { ResolvedConfig } from 'vitest'
import type { VitestExecutor } from 'vitest/execute'
import { rpc } from './rpc'
import { getConfig, importId } from './utils'
import { BrowserSnapshotEnvironment } from './snapshot'
import { VitestBrowserSnapshotEnvironment } from './snapshot'

interface BrowserRunnerOptions {
config: ResolvedConfig
Expand Down Expand Up @@ -92,7 +92,10 @@ export async function initiateRunner() {
if (cachedRunner)
return cachedRunner
const config = getConfig()
const [{ VitestTestRunner, NodeBenchmarkRunner }, { takeCoverageInsideWorker, loadDiffConfig, loadSnapshotSerializers }] = await Promise.all([
const [
{ VitestTestRunner, NodeBenchmarkRunner },
{ takeCoverageInsideWorker, loadDiffConfig, loadSnapshotSerializers },
] = await Promise.all([
importId('vitest/runners') as Promise<typeof import('vitest/runners')>,
importId('vitest/browser') as Promise<typeof import('vitest/browser')>,
])
Expand All @@ -101,7 +104,7 @@ export async function initiateRunner() {
takeCoverage: () => takeCoverageInsideWorker(config.coverage, { executeId: importId }),
})
if (!config.snapshotOptions.snapshotEnvironment)
config.snapshotOptions.snapshotEnvironment = new BrowserSnapshotEnvironment()
config.snapshotOptions.snapshotEnvironment = new VitestBrowserSnapshotEnvironment()
const runner = new BrowserRunner({
config,
})
Expand Down
11 changes: 8 additions & 3 deletions packages/browser/src/client/snapshot.ts
@@ -1,7 +1,7 @@
import type { SnapshotEnvironment } from 'vitest'
import { rpc } from './rpc'
import type { VitestClient } from '@vitest/ws-client'
import type { SnapshotEnvironment } from 'vitest/snapshot'

export class BrowserSnapshotEnvironment implements SnapshotEnvironment {
export class VitestBrowserSnapshotEnvironment implements SnapshotEnvironment {
getVersion(): string {
return '1'
}
Expand Down Expand Up @@ -30,3 +30,8 @@ export class BrowserSnapshotEnvironment implements SnapshotEnvironment {
return rpc().removeSnapshotFile(filepath)
}
}

function rpc(): VitestClient['rpc'] {
// @ts-expect-error not typed global
return globalThis.__vitest_worker__.rpc
}
4 changes: 4 additions & 0 deletions packages/vitest/package.json
Expand Up @@ -91,6 +91,10 @@
"./reporters": {
"types": "./dist/reporters.d.ts",
"default": "./dist/reporters.js"
},
"./snapshot": {
"types": "./dist/snapshot.d.ts",
"default": "./dist/snapshot.js"
}
},
"main": "./dist/index.js",
Expand Down
3 changes: 3 additions & 0 deletions packages/vitest/rollup.config.js
Expand Up @@ -41,6 +41,8 @@ const entries = {
'workers/vmForks': 'src/runtime/workers/vmForks.ts',

'workers/runVmTests': 'src/runtime/runVmTests.ts',

'snapshot': 'src/snapshot.ts',
}

const dtsEntries = {
Expand All @@ -56,6 +58,7 @@ const dtsEntries = {
execute: 'src/public/execute.ts',
reporters: 'src/public/reporters.ts',
workers: 'src/workers.ts',
snapshot: 'src/snapshot.ts',
}

const external = [
Expand Down
1 change: 1 addition & 0 deletions packages/vitest/snapshot.d.ts
@@ -0,0 +1 @@
export * from './dist/snapshot.js'
1 change: 1 addition & 0 deletions packages/vitest/src/index.ts
Expand Up @@ -17,6 +17,7 @@ export * from './integrations/chai'
export * from './integrations/vi'
export * from './integrations/utils'
export { inject } from './integrations/inject'
// TODO: remove in 2.0.0, import from vitest/snapshot directly
export type { SnapshotEnvironment } from '@vitest/snapshot/environment'

export * from './types'
Expand Down
@@ -1,7 +1,7 @@
import { NodeSnapshotEnvironment } from '@vitest/snapshot/environment'
import { getWorkerState } from '../../../utils'

export class VitestSnapshotEnvironment extends NodeSnapshotEnvironment {
export class VitestNodeSnapshotEnvironment extends NodeSnapshotEnvironment {
getHeader(): string {
return `// Vitest Snapshot v${this.getVersion()}, https://vitest.dev/guide/snapshot.html`
}
Expand Down
@@ -1,17 +1,17 @@
import type { SnapshotEnvironment } from '@vitest/snapshot/environment'
import type { VitestExecutor } from '../../../runtime/execute'
import type { ResolvedConfig } from '../../../types'
import { VitestSnapshotEnvironment } from './node'
import { VitestNodeSnapshotEnvironment } from './node'

export async function resolveSnapshotEnvironment(
config: ResolvedConfig,
executor: VitestExecutor,
): Promise<SnapshotEnvironment> {
if (!config.snapshotEnvironment)
return new VitestSnapshotEnvironment()
return new VitestNodeSnapshotEnvironment()

const mod = await executor.executeId(config.snapshotEnvironment)
if (typeof mod.default !== 'object' && !mod.default)
if (typeof mod.default !== 'object' || !mod.default)
throw new Error('Snapshot environment module must have a default export object with a shape of `SnapshotEnvironment`')
return mod.default
}
4 changes: 4 additions & 0 deletions packages/vitest/src/snapshot.ts
@@ -0,0 +1,4 @@
export type { SnapshotEnvironment } from '@vitest/snapshot/environment'
export {
VitestNodeSnapshotEnvironment as VitestSnapshotEnvironment,
} from './integrations/snapshot/environments/node'
1 change: 1 addition & 0 deletions test/browser/custom-snapshot-env.ts
@@ -0,0 +1 @@
throw new Error('This file should not be executed')
2 changes: 2 additions & 0 deletions test/browser/vitest.config.mts
Expand Up @@ -20,6 +20,8 @@ export default defineConfig({
},
test: {
include: ['test/**.test.{ts,js}'],
// having a snapshot environment doesn't affect browser tests
snapshotEnvironment: './custom-snapshot-env.ts',
browser: {
enabled: true,
name: browser,
Expand Down
33 changes: 33 additions & 0 deletions test/snapshots/test/custom-environment.test.ts
@@ -0,0 +1,33 @@
import { readFileSync, rmSync, writeFileSync } from 'node:fs'
import { afterEach, expect, test } from 'vitest'
import { dirname, resolve } from 'pathe'
import { runVitest } from '../../test-utils'

const testFileName = resolve(import.meta.dirname, './fixtures/custom-snapshot-environment/test/snapshots.test.ts')
const snapshotFile = resolve(dirname(testFileName), './__snapshots__/snapshots.test.ts.snap')
const testFile = readFileSync(testFileName, 'utf-8')

afterEach(() => {
writeFileSync(testFileName, testFile)
rmSync(snapshotFile)
})

test('custom environment resolved correctly', async () => {
const { stdout, stderr } = await runVitest({
root: 'test/fixtures/custom-snapshot-environment',
update: true,
})

const snapshotLogs = stdout.split('\n').filter(i => i.startsWith('## ')).join('\n')
expect(stderr).toBe('')
expect(snapshotLogs).toMatchInlineSnapshot(`
"## resolvePath test/fixtures/custom-snapshot-environment/test/snapshots.test.ts
## readSnapshotFile test/fixtures/custom-snapshot-environment/test/__snapshots__/snapshots.test.ts.snap
## getHeader
## getVersion
## readSnapshotFile test/fixtures/custom-snapshot-environment/test/__snapshots__/snapshots.test.ts.snap
## saveSnapshotFile test/fixtures/custom-snapshot-environment/test/__snapshots__/snapshots.test.ts.snap
## readSnapshotFile test/fixtures/custom-snapshot-environment/test/snapshots.test.ts
## saveSnapshotFile test/fixtures/custom-snapshot-environment/test/snapshots.test.ts"
`)
})
@@ -0,0 +1,45 @@
import { relative as _relative } from 'pathe'
import { VitestSnapshotEnvironment } from 'vitest/snapshot'

function relative(file: string) {
return _relative(process.cwd(), file)
}

class CustomSnapshotEnvironment extends VitestSnapshotEnvironment {
getVersion(): string {
console.log('## getVersion')
return super.getVersion()
}

getHeader() {
console.log('## getHeader')
return super.getHeader()
}

resolvePath(filepath: string) {
console.log('## resolvePath', relative(filepath))
return super.resolvePath(filepath)
}

resolveRawPath(testPath: string, rawPath: string) {
console.log('## resolveRawPath', relative(testPath), relative(rawPath))
return super.resolveRawPath(testPath, rawPath)
}

saveSnapshotFile(filepath: string, snapshot: string) {
console.log('## saveSnapshotFile', relative(filepath))
return super.saveSnapshotFile(filepath, snapshot)
}

readSnapshotFile(filepath: string) {
console.log('## readSnapshotFile', relative(filepath))
return super.readSnapshotFile(filepath)
}

removeSnapshotFile(filepath: string) {
console.log('## removeSnapshotFile', relative(filepath))
return super.removeSnapshotFile(filepath)
}
}

export default new CustomSnapshotEnvironment()
@@ -0,0 +1,9 @@
import {test, expect} from 'vitest'

test('regular snapshot', () => {
expect({ a: 1 }).toMatchSnapshot()
})

test('inline snapshot', () => {
expect({ a: 1 }).toMatchInlineSnapshot()
})
@@ -0,0 +1,7 @@
import { defineConfig } from 'vitest/config';

export default defineConfig({
test: {
snapshotEnvironment: './snapshot-environment.ts'
}
})

0 comments on commit a54ed70

Please sign in to comment.