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: allow passing config to sinon/fake-timers #1261

Merged
merged 3 commits into from May 9, 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
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