diff --git a/docs/api/vi.md b/docs/api/vi.md index 748b68f35ae1..f335900cf33a 100644 --- a/docs/api/vi.md +++ b/docs/api/vi.md @@ -690,7 +690,7 @@ Removes all timers that are scheduled to run. These timers will never run in the - **Type**: `() => Date | null` -Returns mocked current date that was set using `setSystemTime`. If date is not mocked the method will return `null`. +Returns mocked current date. If date is not mocked the method will return `null`. ### vi.getRealSystemTime diff --git a/packages/vitest/src/integrations/mock/timers.ts b/packages/vitest/src/integrations/mock/timers.ts index 2554327265e0..964127747baf 100644 --- a/packages/vitest/src/integrations/mock/timers.ts +++ b/packages/vitest/src/integrations/mock/timers.ts @@ -17,8 +17,14 @@ import { mockDate, RealDate, resetDate } from './date' export class FakeTimers { private _global: typeof globalThis private _clock!: InstalledClock + // | _fakingTime | _fakingDate | + // +-------------+-------------+ + // | false | falsy | initial + // | false | truethy | vi.setSystemTime called first (for mocking only Date without fake timers) + // | true | falsy | vi.useFakeTimers called first + // | true | truethy | unreachable private _fakingTime: boolean - private _fakingDate: boolean + private _fakingDate: Date | null private _fakeTimers: FakeTimerWithContext private _userConfig?: FakeTimerInstallOpts private _now = RealDate.now @@ -32,7 +38,7 @@ export class FakeTimers { }) { this._userConfig = config - this._fakingDate = false + this._fakingDate = null this._fakingTime = false this._fakeTimers = withGlobal(global) @@ -129,7 +135,7 @@ export class FakeTimers { useRealTimers(): void { if (this._fakingDate) { resetDate() - this._fakingDate = false + this._fakingDate = null } if (this._fakingTime) { @@ -177,16 +183,21 @@ export class FakeTimers { } } - setSystemTime(now?: number | Date): void { + setSystemTime(now?: string | number | Date): void { + const date = (typeof now === 'undefined' || now instanceof Date) ? now : new Date(now) if (this._fakingTime) { - this._clock.setSystemTime(now) + this._clock.setSystemTime(date) } else { - mockDate(now ?? this.getRealSystemTime()) - this._fakingDate = true + this._fakingDate = date ?? new Date(this.getRealSystemTime()) + mockDate(this._fakingDate) } } + getMockedSystemTime(): Date | null { + return this._fakingTime ? new Date(this._clock.now) : this._fakingDate + } + getRealSystemTime(): number { return this._now() } diff --git a/packages/vitest/src/integrations/vi.ts b/packages/vitest/src/integrations/vi.ts index 402e35c24e0c..86e0605aef05 100644 --- a/packages/vitest/src/integrations/vi.ts +++ b/packages/vitest/src/integrations/vi.ts @@ -85,7 +85,7 @@ export interface VitestUtils { */ setSystemTime: (time: number | string | Date) => VitestUtils /** - * Returns mocked current date that was set using `setSystemTime`. If date is not mocked the method will return `null`. + * Returns mocked current date. If date is not mocked the method will return `null`. */ getMockedSystemTime: () => Date | null /** @@ -502,14 +502,12 @@ function createVitest(): VitestUtils { }, setSystemTime(time: number | string | Date) { - const date = time instanceof Date ? time : new Date(time) - _mockedDate = date - timers().setSystemTime(date) + timers().setSystemTime(time) return utils }, getMockedSystemTime() { - return _mockedDate + return timers().getMockedSystemTime() }, getRealSystemTime() { diff --git a/test/core/test/timers-getMockedSystemTime.test.ts b/test/core/test/timers-getMockedSystemTime.test.ts new file mode 100644 index 000000000000..559b6027b37b --- /dev/null +++ b/test/core/test/timers-getMockedSystemTime.test.ts @@ -0,0 +1,48 @@ +import { afterEach, expect, it, vi } from 'vitest' + +afterEach(() => { + vi.useRealTimers() +}) + +it('with fake timers', () => { + expect(vi.getMockedSystemTime()).toBe(null) + + vi.useFakeTimers() + expect(vi.getMockedSystemTime()).toEqual(new Date()) + + vi.setSystemTime(0) + expect(vi.getMockedSystemTime()).toEqual(new Date()) + expect(vi.getMockedSystemTime()).toEqual(new Date(0)) + + vi.advanceTimersByTime(1234) + expect(vi.getMockedSystemTime()).toEqual(new Date()) + expect(vi.getMockedSystemTime()).toEqual(new Date(1234)) + + vi.useRealTimers() + expect(vi.getMockedSystemTime()).toBe(null) + expect(new Date()).not.toEqual(new Date(1234)) + + vi.useFakeTimers({ now: 12345 }) + expect(vi.getMockedSystemTime()).toEqual(new Date()) + expect(vi.getMockedSystemTime()).toEqual(new Date(12345)) +}) + +it('without fake timers', () => { + expect(vi.getMockedSystemTime()).toBe(null) + + vi.setSystemTime(0) + expect(vi.getMockedSystemTime()).toEqual(new Date()) + expect(vi.getMockedSystemTime()).toEqual(new Date(0)) + + vi.setSystemTime(1234) + expect(vi.getMockedSystemTime()).toEqual(new Date()) + expect(vi.getMockedSystemTime()).toEqual(new Date(1234)) + + vi.useRealTimers() + expect(vi.getMockedSystemTime()).toBe(null) + expect(new Date()).not.toEqual(new Date(1234)) + + vi.setSystemTime(12345) + expect(vi.getMockedSystemTime()).toEqual(new Date()) + expect(vi.getMockedSystemTime()).toEqual(new Date(12345)) +})