feat: allow passing config to sinon/fake-timers (#1261)

* feat: allow passing config to sinon/fake-timers

* chore: fix timers test
This commit is contained in:
Vladimir 2022-05-09 11:38:23 +03:00 committed by GitHub
parent 7459ff8a46
commit d4e8060f68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 49 additions and 14 deletions

View File

@ -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,
@ -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)

View File

@ -6,6 +6,7 @@
*/
import type {
FakeTimerInstallOpts,
FakeTimerWithContext,
InstalledClock,
} from '@sinonjs/fake-timers'
@ -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
@ -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
@ -143,6 +143,10 @@ export class FakeTimers {
return 0
}
configure(config: FakeTimerInstallOpts): void {
this._userConfig = config
}
private _checkFakeTimers() {
if (!this._fakingTime) {
throw new Error(

View File

@ -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'
@ -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
@ -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
}

View File

@ -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'
@ -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 {

View File

@ -176,7 +176,7 @@ describe('FakeTimers', () => {
setTimeout,
}
const timers = new FakeTimers({ global, maxLoops: 100 })
const timers = new FakeTimers({ global, config: { loopLimit: 100 } })
timers.useFakeTimers()
@ -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() {