Skip to content

Commit

Permalink
feat: allow passing config to sinon/fake-timers (#1261)
Browse files Browse the repository at this point in the history
* feat: allow passing config to sinon/fake-timers

* chore: fix timers test
  • Loading branch information
sheremet-va committed May 9, 2022
1 parent 7459ff8 commit d4e8060
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 14 deletions.
15 changes: 15 additions & 0 deletions packages/vitest/src/defaults.ts
Expand Up @@ -33,6 +33,20 @@ const coverageConfigDefaults = {
extension: ['.js', '.cjs', '.mjs', '.ts', '.tsx', '.jsx', '.vue', '.svelte'],
} as ResolvedC8Options

export const fakeTimersDefaults = {
loopLimit: 10_000,
shouldClearNativeTimers: true,
toFake: [
'setTimeout',
'clearTimeout',
'setInterval',
'clearInterval',
'setImmediate',
'clearImmediate',
'Date',
],
} as NonNullable<UserConfig['fakeTimers']>

const config = {
allowOnly: !process.env.CI,
watch: !process.env.CI,
Expand All @@ -56,6 +70,7 @@ const config = {
uiBase: '/__vitest__/',
open: true,
coverage: coverageConfigDefaults,
fakeTimers: fakeTimersDefaults,
}

export const configDefaults: Required<Pick<UserConfig, keyof typeof config>> = Object.freeze(config)
16 changes: 10 additions & 6 deletions packages/vitest/src/integrations/timers.ts
Expand Up @@ -6,6 +6,7 @@
*/

import type {
FakeTimerInstallOpts,
FakeTimerWithContext,
InstalledClock,
} from '@sinonjs/fake-timers'
Expand All @@ -19,17 +20,17 @@ export class FakeTimers {
private _fakingTime: boolean
private _fakingDate: boolean
private _fakeTimers: FakeTimerWithContext
private _maxLoops: number
private _userConfig?: FakeTimerInstallOpts
private _now = RealDate.now

constructor({
global,
maxLoops = 10_000,
config,
}: {
global: typeof globalThis
maxLoops?: number
config: FakeTimerInstallOpts
}) {
this._maxLoops = maxLoops
this._userConfig = config

this._fakingDate = false

Expand Down Expand Up @@ -104,10 +105,9 @@ export class FakeTimers {
const toFake = Object.keys(this._fakeTimers.timers) as Array<keyof FakeTimerWithContext['timers']>

this._clock = this._fakeTimers.install({
loopLimit: this._maxLoops,
now: Date.now(),
toFake,
shouldClearNativeTimers: true,
...this._userConfig,
})

this._fakingTime = true
Expand Down Expand Up @@ -143,6 +143,10 @@ export class FakeTimers {
return 0
}

configure(config: FakeTimerInstallOpts): void {
this._userConfig = config
}

private _checkFakeTimers() {
if (!this._fakingTime) {
throw new Error(
Expand Down
22 changes: 16 additions & 6 deletions packages/vitest/src/integrations/vi.ts
@@ -1,8 +1,9 @@
/* eslint-disable @typescript-eslint/no-unused-vars */

import type { FakeTimerInstallOpts } from '@sinonjs/fake-timers'
import { parseStacktrace } from '../utils/source-map'
import type { VitestMocker } from '../runtime/mocker'
import { resetModules } from '../utils'
import { getWorkerState, resetModules } from '../utils'
import { FakeTimers } from './timers'
import type { EnhancedSpy, MaybeMocked, MaybeMockedDeep } from './spy'
import { fn, isMockFunction, spies, spyOn } from './spy'
Expand All @@ -13,10 +14,6 @@ class VitestUtils {
private _mocker: VitestMocker

constructor() {
this._timers = new FakeTimers({
global: globalThis,
maxLoops: 10_000,
})
// @ts-expect-error injected by vite-nide
this._mocker = typeof __vitest_mocker__ !== 'undefined' ? __vitest_mocker__ : null
this._mockedDate = null
Expand All @@ -30,11 +27,24 @@ class VitestUtils {
+ '\n- Otherwise, it might be a Vitest bug. Please report it to https://github.com/vitest-dev/vitest/issues\n'
throw new Error(errorMsg)
}

const workerState = getWorkerState()
this._timers = new FakeTimers({
global: globalThis,
config: workerState.config.fakeTimers,
})
}

// timers

public useFakeTimers() {
public useFakeTimers(config?: FakeTimerInstallOpts) {
if (config) {
this._timers.configure(config)
}
else {
const workerState = getWorkerState()
this._timers.configure(workerState.config.fakeTimers)
}
this._timers.useFakeTimers()
return this
}
Expand Down
6 changes: 6 additions & 0 deletions packages/vitest/src/types/config.ts
@@ -1,5 +1,6 @@
import type { CommonServerOptions } from 'vite'
import type { PrettyFormatOptions } from 'pretty-format'
import type { FakeTimerInstallOpts } from '@sinonjs/fake-timers'
import type { BuiltinReporters } from '../node/reporters'
import type { C8Options, ResolvedC8Options } from './coverage'
import type { JSDOMOptions } from './jsdom-options'
Expand Down Expand Up @@ -312,6 +313,11 @@ export interface InlineConfig {
* Show heap usage after each test. Usefull for debugging memory leaks.
*/
logHeapUsage?: boolean

/**
* Options for @sinon/fake-timers
*/
fakeTimers?: FakeTimerInstallOpts
}

export interface UserConfig extends InlineConfig {
Expand Down
4 changes: 2 additions & 2 deletions test/core/test/timers.test.ts
Expand Up @@ -176,7 +176,7 @@ describe('FakeTimers', () => {
setTimeout,
}

const timers = new FakeTimers({ global, maxLoops: 100 })
const timers = new FakeTimers({ global, config: { loopLimit: 100 } })

timers.useFakeTimers()

Expand Down Expand Up @@ -306,7 +306,7 @@ describe('FakeTimers', () => {

it('throws before allowing infinite recursion', () => {
const global = { Date: FakeDate, clearTimeout, process, setTimeout }
const timers = new FakeTimers({ global, maxLoops: 100 })
const timers = new FakeTimers({ global, config: { loopLimit: 100 } })
timers.useFakeTimers()

global.setTimeout(function infinitelyRecursingCallback() {
Expand Down

0 comments on commit d4e8060

Please sign in to comment.