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: new setupOnce utils #967

Merged
merged 3 commits into from
Mar 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/vitest/src/index.ts
Expand Up @@ -3,8 +3,9 @@ import type { MatcherState, MatchersObject } from './integrations/chai/types'
import type { Constructable, InlineConfig } from './types'

export { suite, test, describe, it } from './runtime/suite'

export * from './runtime/hooks'

export { runOnce } from './integrations/run-once'
export * from './integrations/chai'
export * from './integrations/jest-mock'
export * from './integrations/vi'
Expand Down
34 changes: 34 additions & 0 deletions packages/vitest/src/integrations/run-once.ts
@@ -0,0 +1,34 @@
import type { Awaitable } from '../types'
import { getWorkerState } from '../utils'

const filesCount = new Map<string, number>()
const cache = new Map<string, any>()

/**
* This utils allows computational intensive tasks to only be ran once
* across test reruns to improve the watch mode performance.
*
* Currently only works with `isolate: false`
*
* @experimental
*/
export async function runOnce<T>(fn: (() => Awaitable<T>), key?: string): Promise<T> {
if (!key) {
const filepath = getWorkerState().filepath || '__unknown_files__'
filesCount.set(filepath, (filesCount.get(filepath) || 0) + 1)
const count = filesCount.get(filepath)!
key = `${filepath}:${count}`
}

if (!cache.has(key))
cache.set(key, fn())

return await cache.get(key)
}

/**
* @internal
*/
export function resetRunOnceCounter() {
filesCount.clear()
}
3 changes: 3 additions & 0 deletions packages/vitest/src/runtime/setup.ts
Expand Up @@ -4,10 +4,13 @@ import { environments } from '../integrations/env'
import type { ResolvedConfig } from '../types'
import { getWorkerState, toArray } from '../utils'
import * as VitestIndex from '../index'
import { resetRunOnceCounter } from '../integrations/run-once'
import { rpc } from './rpc'

let globalSetup = false
export async function setupGlobalEnv(config: ResolvedConfig) {
resetRunOnceCounter()

Object.defineProperty(globalThis, '__vitest_index__', {
value: VitestIndex,
enumerable: false,
Expand Down
20 changes: 13 additions & 7 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion test/core/vitest.config.ts
Expand Up @@ -38,7 +38,6 @@ export default defineConfig({
},
test: {
testTimeout: 2000,
// threads: false,
setupFiles: [
'./test/setup.ts',
],
Expand Down
11 changes: 11 additions & 0 deletions test/run-once/package.json
@@ -0,0 +1,11 @@
{
"name": "@vitest/test-run-once",
"private": true,
"scripts": {
"test": "vitest",
"coverage": "vitest run --coverage"
},
"devDependencies": {
"vitest": "workspace:*"
}
}
21 changes: 21 additions & 0 deletions test/run-once/test/run-once.test.ts
@@ -0,0 +1,21 @@
import { expect, it, runOnce } from 'vitest'

let dummy = 0

const one = await runOnce(() => {
dummy += 1
return 1
})

const two = await runOnce(async() => {
dummy += 1
return 2
})

it('run once', async() => {
expect(one).toBe(1)
expect(two).toBe(2)

// edit the file to trigger the hmr and dummy should be 0
expect(dummy).toBe(2)
})
7 changes: 7 additions & 0 deletions test/run-once/vitest.config.ts
@@ -0,0 +1,7 @@
import { defineConfig } from 'vite'

export default defineConfig({
test: {
isolate: false,
},
})