From 1b0a8f9b2d71fe1840e3066bd2911f08213bfe2d Mon Sep 17 00:00:00 2001 From: fabon Date: Sun, 12 Jul 2026 03:33:34 +0900 Subject: [PATCH 1/5] feat!: enable mocking Temporal without fake timers --- .../vitest/src/integrations/mock/temporal.ts | 69 +++++++++++++++++++ .../vitest/src/integrations/mock/timers.ts | 4 ++ test/unit/test/temporal-mock.test.ts | 47 +++++++++++++ 3 files changed, 120 insertions(+) create mode 100644 packages/vitest/src/integrations/mock/temporal.ts create mode 100644 test/unit/test/temporal-mock.test.ts diff --git a/packages/vitest/src/integrations/mock/temporal.ts b/packages/vitest/src/integrations/mock/temporal.ts new file mode 100644 index 000000000000..915f6abd0f39 --- /dev/null +++ b/packages/vitest/src/integrations/mock/temporal.ts @@ -0,0 +1,69 @@ +let now: number | undefined + +let RealTemporal: typeof Temporal | undefined +let MockedTemporal: typeof Temporal | undefined + +function currentZonedDateTime( + RealTemporal: typeof Temporal, + currentTime: number, + timeZoneLike: any, +): Temporal.ZonedDateTime { + const timeZone = timeZoneLike === undefined ? RealTemporal.Now.timeZoneId() : timeZoneLike + return RealTemporal.Instant.fromEpochMilliseconds(currentTime).toZonedDateTimeISO(timeZone) +} + +function createMockedTemporal(RealTemporal: typeof Temporal): typeof Temporal { + const propertyDescriptors = Object.getOwnPropertyDescriptors(RealTemporal) + propertyDescriptors.Now.value = { + timeZoneId: RealTemporal.Now.timeZoneId, + instant() { + if (now !== undefined) { + return RealTemporal.Instant.fromEpochMilliseconds(now) + } + return RealTemporal.Now.instant() + }, + zonedDateTimeISO(timeZoneLike?: any) { + if (now !== undefined) { + return currentZonedDateTime(RealTemporal, now, timeZoneLike) + } + return RealTemporal.Now.zonedDateTimeISO(timeZoneLike) + }, + plainDateTimeISO(timeZoneLike?: any) { + if (now !== undefined) { + return currentZonedDateTime(RealTemporal, now, timeZoneLike).toPlainDateTime() + } + return RealTemporal.Now.plainDateTimeISO(timeZoneLike) + }, + plainDateISO(timeZoneLike?: any) { + if (now !== undefined) { + return currentZonedDateTime(RealTemporal, now, timeZoneLike).toPlainDate() + } + return RealTemporal.Now.plainDateISO(timeZoneLike) + }, + plainTimeISO(timeZoneLike?: any) { + if (now !== undefined) { + return currentZonedDateTime(RealTemporal, now, timeZoneLike).toPlainTime() + } + return RealTemporal.Now.plainTimeISO(timeZoneLike) + }, + } + const MockedTemporal = {} as typeof Temporal + Object.defineProperties(MockedTemporal, propertyDescriptors) + return MockedTemporal +} + +export function mockTemporal(date: Date): void { + now = date.valueOf() + RealTemporal = globalThis.Temporal as typeof Temporal | undefined + if (RealTemporal !== undefined) { + MockedTemporal ??= createMockedTemporal(RealTemporal) + globalThis.Temporal = MockedTemporal + } +} + +export function resetTemporal(): void { + now = undefined + if (RealTemporal !== undefined) { + globalThis.Temporal = RealTemporal + } +} diff --git a/packages/vitest/src/integrations/mock/timers.ts b/packages/vitest/src/integrations/mock/timers.ts index 688441eb08cb..9d1c0be596a2 100644 --- a/packages/vitest/src/integrations/mock/timers.ts +++ b/packages/vitest/src/integrations/mock/timers.ts @@ -14,6 +14,7 @@ import type { import { withGlobal } from '@sinonjs/fake-timers' import { isChildProcess } from '../../runtime/utils' import { mockDate, RealDate, resetDate } from './date' +import { mockTemporal, resetTemporal } from './temporal' export class FakeTimers { private _global: typeof globalThis @@ -135,6 +136,7 @@ export class FakeTimers { useRealTimers(): void { if (this._fakingDate) { resetDate() + resetTemporal() this._fakingDate = null } @@ -148,6 +150,7 @@ export class FakeTimers { const fakeDate = this._fakingDate || Date.now() if (this._fakingDate) { resetDate() + resetTemporal() this._fakingDate = null } @@ -199,6 +202,7 @@ export class FakeTimers { else { this._fakingDate = date ?? new Date(this.getRealSystemTime()) mockDate(this._fakingDate) + mockTemporal(this._fakingDate) } } diff --git a/test/unit/test/temporal-mock.test.ts b/test/unit/test/temporal-mock.test.ts new file mode 100644 index 000000000000..12750f51ffb5 --- /dev/null +++ b/test/unit/test/temporal-mock.test.ts @@ -0,0 +1,47 @@ +import { afterEach, describe, expect, it, vi } from 'vitest' + +// use polyfill for node < 26 +if (!globalThis.Temporal) { + await import('temporal-polyfill/global') +} + +describe('testing Temporal mock functionality', () => { + afterEach(() => { + vi.useRealTimers() + }) + + it('setting time', () => { + const date = new Date(2000, 0, 1) + vi.setSystemTime(date) + + expect(Temporal.Now.instant().epochMilliseconds).toEqual(date.getTime()) + expect(Temporal.Now.zonedDateTimeISO().epochMilliseconds).toEqual(date.getTime()) + expect(Temporal.Now.plainDateISO()).toEqual(Temporal.PlainDate.from('2000-01-01')) + expect(Temporal.Now.plainDateTimeISO()).toEqual(Temporal.PlainDateTime.from('2000-01-01T00:00:00')) + expect(Temporal.Now.plainTimeISO()).toEqual(Temporal.PlainTime.from('00:00:00')) + + vi.useRealTimers() + + expect(Temporal.Now.instant().epochMilliseconds).not.toEqual(date.getTime()) + expect(Temporal.Now.zonedDateTimeISO().epochMilliseconds).not.toEqual(date.getTime()) + expect(Temporal.Now.plainDateISO()).not.toEqual(Temporal.PlainDate.from('2000-01-01')) + expect(Temporal.Now.plainDateTimeISO()).not.toEqual(Temporal.PlainDateTime.from('2000-01-01T00:00:00')) + expect(Temporal.Now.plainTimeISO()).not.toEqual(Temporal.PlainTime.from('00:00:00')) + }) + + it('getting current date in the specific time zone', () => { + vi.setSystemTime(new Date('2000-01-01T00:00:00Z')) + + const timeZone = 'America/Los_Angeles' + const timeZoneLike = new Temporal.ZonedDateTime(0n, timeZone) + + for (const tz of [timeZone, timeZoneLike]) { + expect(Temporal.Now.zonedDateTimeISO(tz)).toEqual( + Temporal.ZonedDateTime.from('1999-12-31T16:00:00-08:00[America/Los_Angeles]'), + ) + expect(Temporal.Now.plainDateISO(tz)).toEqual(Temporal.PlainDate.from('1999-12-31')) + expect(Temporal.Now.plainDateTimeISO(tz)).toEqual(Temporal.PlainDateTime.from('1999-12-31T16:00:00')) + expect(Temporal.Now.plainTimeISO(tz)).toEqual(Temporal.PlainTime.from('16:00:00')) + } + }) +}) From 08b64a94304c4e714b856b452b7b75a8632b3b65 Mon Sep 17 00:00:00 2001 From: fabon Date: Sun, 12 Jul 2026 04:04:30 +0900 Subject: [PATCH 2/5] docs: update --- docs/api/vi.md | 2 +- docs/guide/migration.md | 9 +++++++++ docs/guide/mocking.md | 4 +++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/docs/api/vi.md b/docs/api/vi.md index 3d84ea781bd9..913251988ef9 100644 --- a/docs/api/vi.md +++ b/docs/api/vi.md @@ -1159,7 +1159,7 @@ await vi.runOnlyPendingTimersAsync() function setSystemTime(date: string | number | Date): Vitest ``` -If fake timers are enabled, this method simulates a user changing the system clock (will affect date related API like `hrtime`, `performance.now` or `new Date()`) - however, it will not fire any timers. If fake timers are not enabled, this method will only mock `Date.*` calls. +If fake timers are enabled, this method simulates a user changing the system clock (will affect date related API like `hrtime`, `performance.now` or `new Date()`) - however, it will not fire any timers. If fake timers are not enabled, this method will only mock `Date.*` and `Temporal.Now.*` calls. Useful if you need to test anything that depends on the current date - for example [Luxon](https://github.com/moment/luxon/) calls inside your code. diff --git a/docs/guide/migration.md b/docs/guide/migration.md index 972aa5927f57..0e7cb33258f5 100644 --- a/docs/guide/migration.md +++ b/docs/guide/migration.md @@ -147,6 +147,15 @@ Temporal.Now.instant().epochMilliseconds // 0 (was the real time in v4) vi.useFakeTimers({ toNotFake: ['Temporal'] }) ``` +### `setSystemTime` Now Mocks Temporal + +Previously `vi.setSystemTime` mocked only `Date` without fake timers, but now it also mocks methods of `Temporal.Now`. + +```ts +vi.setSystemTime(0) +Temporal.Now.instant().epochMilliseconds // 0 (was the real time in v4) +``` + ### `toThrow("")` Matches Any Error Message [`toThrow`](/api/expect#tothrow) (and its alias `toThrowError`) treats a string argument as a substring of the error message. In Vitest 4 an empty string was special-cased to the `/^$/` pattern, so it matched only an error whose message was empty. It now behaves like any other substring, and an empty string is contained in every message: diff --git a/docs/guide/mocking.md b/docs/guide/mocking.md index 57d2abb22bf0..6f93ec314bb5 100644 --- a/docs/guide/mocking.md +++ b/docs/guide/mocking.md @@ -171,7 +171,7 @@ Don't forget that this only [mocks _external_ access](/guide/mocking/modules#moc ### Mock the current date -To mock `Date`'s time, you can use `vi.setSystemTime` helper function. This value will **not** automatically reset between different tests. +To mock `Date` and `Temporal`'s time, you can use `vi.setSystemTime` helper function. This value will **not** automatically reset between different tests. Beware that using `vi.useFakeTimers` also changes the `Date`'s time. @@ -180,6 +180,8 @@ const mockDate = new Date(2022, 0, 1) vi.setSystemTime(mockDate) const now = new Date() expect(now.valueOf()).toBe(mockDate.valueOf()) +const nowInstant = Temporal.Now.instant() +expect(nowInstant.epochMilliseconds).toBe(mockDate.valueOf()) // reset mocked time vi.useRealTimers() ``` From 35fba579c2d1fdc4bbd9567ded5e2af3a842eb7d Mon Sep 17 00:00:00 2001 From: fabon Date: Sun, 12 Jul 2026 04:57:39 +0900 Subject: [PATCH 3/5] Fix type errors --- packages/vitest/src/integrations/mock/temporal.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/vitest/src/integrations/mock/temporal.ts b/packages/vitest/src/integrations/mock/temporal.ts index 915f6abd0f39..b7fd809c1af0 100644 --- a/packages/vitest/src/integrations/mock/temporal.ts +++ b/packages/vitest/src/integrations/mock/temporal.ts @@ -46,6 +46,7 @@ function createMockedTemporal(RealTemporal: typeof Temporal): typeof Temporal { } return RealTemporal.Now.plainTimeISO(timeZoneLike) }, + [Symbol.toStringTag]: 'Temporal.Now', } const MockedTemporal = {} as typeof Temporal Object.defineProperties(MockedTemporal, propertyDescriptors) From 556c6b19bd8e094d818d3fdc6682d40d27f8739c Mon Sep 17 00:00:00 2001 From: fabon Date: Tue, 14 Jul 2026 03:10:25 +0900 Subject: [PATCH 4/5] Replace mockdate with fake timers --- packages/vitest/src/integrations/mock/date.ts | 110 ------------------ .../vitest/src/integrations/mock/temporal.ts | 70 ----------- .../vitest/src/integrations/mock/timers.ts | 26 +++-- packages/vitest/src/runtime/console.ts | 3 +- 4 files changed, 19 insertions(+), 190 deletions(-) delete mode 100644 packages/vitest/src/integrations/mock/date.ts delete mode 100644 packages/vitest/src/integrations/mock/temporal.ts diff --git a/packages/vitest/src/integrations/mock/date.ts b/packages/vitest/src/integrations/mock/date.ts deleted file mode 100644 index 97cbb1241fb6..000000000000 --- a/packages/vitest/src/integrations/mock/date.ts +++ /dev/null @@ -1,110 +0,0 @@ -/* Ported from https://github.com/boblauer/MockDate/blob/master/src/mockdate.ts */ -/* -The MIT License (MIT) - -Copyright (c) 2014 Bob Lauer - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -export const RealDate: DateConstructor = Date - -let now: null | number = null - -class MockDate extends RealDate { - constructor() - constructor(value: number | string) - constructor( - year: number, - month: number, - date?: number, - hours?: number, - minutes?: number, - seconds?: number, - ms?: number - ) - constructor( - y?: number | string, - m?: number, - d?: number, - h?: number, - M?: number, - s?: number, - ms?: number, - ) { - super() - - let date: any - switch (arguments.length) { - case 0: - if (now !== null) { - date = new RealDate(now.valueOf()) - } - else { - date = new RealDate() - } - break - case 1: - date = new RealDate(y!) - break - default: - d = typeof d === 'undefined' ? 1 : d - h = h || 0 - M = M || 0 - s = s || 0 - ms = ms || 0 - date = new RealDate(y as number, m!, d, h, M, s, ms) - break - } - - Object.setPrototypeOf(date, MockDate.prototype) - - return date - } -} - -MockDate.UTC = RealDate.UTC - -MockDate.now = function () { - return new MockDate().valueOf() -} - -MockDate.parse = function (dateString) { - return RealDate.parse(dateString) -} - -MockDate.toString = function () { - return RealDate.toString() -} - -export function mockDate(date: string | number | Date): void { - const dateObj = new RealDate(date.valueOf()) - if (Number.isNaN(dateObj.getTime())) { - throw new TypeError(`mockdate: The time set is an invalid date: ${date}`) - } - - // @ts-expect-error global - globalThis.Date = MockDate - - now = dateObj.valueOf() -} - -export function resetDate(): void { - globalThis.Date = RealDate -} diff --git a/packages/vitest/src/integrations/mock/temporal.ts b/packages/vitest/src/integrations/mock/temporal.ts deleted file mode 100644 index b7fd809c1af0..000000000000 --- a/packages/vitest/src/integrations/mock/temporal.ts +++ /dev/null @@ -1,70 +0,0 @@ -let now: number | undefined - -let RealTemporal: typeof Temporal | undefined -let MockedTemporal: typeof Temporal | undefined - -function currentZonedDateTime( - RealTemporal: typeof Temporal, - currentTime: number, - timeZoneLike: any, -): Temporal.ZonedDateTime { - const timeZone = timeZoneLike === undefined ? RealTemporal.Now.timeZoneId() : timeZoneLike - return RealTemporal.Instant.fromEpochMilliseconds(currentTime).toZonedDateTimeISO(timeZone) -} - -function createMockedTemporal(RealTemporal: typeof Temporal): typeof Temporal { - const propertyDescriptors = Object.getOwnPropertyDescriptors(RealTemporal) - propertyDescriptors.Now.value = { - timeZoneId: RealTemporal.Now.timeZoneId, - instant() { - if (now !== undefined) { - return RealTemporal.Instant.fromEpochMilliseconds(now) - } - return RealTemporal.Now.instant() - }, - zonedDateTimeISO(timeZoneLike?: any) { - if (now !== undefined) { - return currentZonedDateTime(RealTemporal, now, timeZoneLike) - } - return RealTemporal.Now.zonedDateTimeISO(timeZoneLike) - }, - plainDateTimeISO(timeZoneLike?: any) { - if (now !== undefined) { - return currentZonedDateTime(RealTemporal, now, timeZoneLike).toPlainDateTime() - } - return RealTemporal.Now.plainDateTimeISO(timeZoneLike) - }, - plainDateISO(timeZoneLike?: any) { - if (now !== undefined) { - return currentZonedDateTime(RealTemporal, now, timeZoneLike).toPlainDate() - } - return RealTemporal.Now.plainDateISO(timeZoneLike) - }, - plainTimeISO(timeZoneLike?: any) { - if (now !== undefined) { - return currentZonedDateTime(RealTemporal, now, timeZoneLike).toPlainTime() - } - return RealTemporal.Now.plainTimeISO(timeZoneLike) - }, - [Symbol.toStringTag]: 'Temporal.Now', - } - const MockedTemporal = {} as typeof Temporal - Object.defineProperties(MockedTemporal, propertyDescriptors) - return MockedTemporal -} - -export function mockTemporal(date: Date): void { - now = date.valueOf() - RealTemporal = globalThis.Temporal as typeof Temporal | undefined - if (RealTemporal !== undefined) { - MockedTemporal ??= createMockedTemporal(RealTemporal) - globalThis.Temporal = MockedTemporal - } -} - -export function resetTemporal(): void { - now = undefined - if (RealTemporal !== undefined) { - globalThis.Temporal = RealTemporal - } -} diff --git a/packages/vitest/src/integrations/mock/timers.ts b/packages/vitest/src/integrations/mock/timers.ts index 9d1c0be596a2..89e502814c5a 100644 --- a/packages/vitest/src/integrations/mock/timers.ts +++ b/packages/vitest/src/integrations/mock/timers.ts @@ -13,8 +13,8 @@ import type { } from '@sinonjs/fake-timers' import { withGlobal } from '@sinonjs/fake-timers' import { isChildProcess } from '../../runtime/utils' -import { mockDate, RealDate, resetDate } from './date' -import { mockTemporal, resetTemporal } from './temporal' + +const RealDate = globalThis.Date export class FakeTimers { private _global: typeof globalThis @@ -135,8 +135,7 @@ export class FakeTimers { useRealTimers(): void { if (this._fakingDate) { - resetDate() - resetTemporal() + this._clock.uninstall() this._fakingDate = null } @@ -149,8 +148,7 @@ export class FakeTimers { useFakeTimers(): void { const fakeDate = this._fakingDate || Date.now() if (this._fakingDate) { - resetDate() - resetTemporal() + this._clock.uninstall() this._fakingDate = null } @@ -200,9 +198,19 @@ export class FakeTimers { this._clock.setSystemTime(date) } else { - this._fakingDate = date ?? new Date(this.getRealSystemTime()) - mockDate(this._fakingDate) - mockTemporal(this._fakingDate) + const newFakingDate = date ?? new Date(this.getRealSystemTime()) + if (this._fakingDate) { + this._fakingDate = newFakingDate + this._clock.setSystemTime(newFakingDate) + } + else { + this._fakingDate = newFakingDate + this._clock = this._fakeTimers.install({ + now: newFakingDate, + toFake: ['Date', 'Temporal'], + ignoreMissingTimers: true, + }) + } } } diff --git a/packages/vitest/src/runtime/console.ts b/packages/vitest/src/runtime/console.ts index ff4b6aa8cb47..ca805d491e8e 100644 --- a/packages/vitest/src/runtime/console.ts +++ b/packages/vitest/src/runtime/console.ts @@ -4,9 +4,10 @@ import { relative } from 'node:path' import { Writable } from 'node:stream' import { getSafeTimers } from '@vitest/utils/timers' import c from 'tinyrainbow' -import { RealDate } from '../integrations/mock/date' import { getWorkerState } from './utils' +const RealDate = globalThis.Date + export const UNKNOWN_TEST_ID = '__vitest__unknown_test__' function getTaskIdByStack(root: string) { From 6b4c98801eb30313052bdaf58840630c56d0806d Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa <4232207+hi-ogawa@users.noreply.github.com> Date: Tue, 14 Jul 2026 11:25:35 +0900 Subject: [PATCH 5/5] test: consolidate Temporal timer tests Co-authored-by: OpenCode --- test/unit/test/temporal-mock.test.ts | 47 -------------------------- test/unit/test/timers-temporal.test.ts | 20 +++++++++++ 2 files changed, 20 insertions(+), 47 deletions(-) delete mode 100644 test/unit/test/temporal-mock.test.ts diff --git a/test/unit/test/temporal-mock.test.ts b/test/unit/test/temporal-mock.test.ts deleted file mode 100644 index 12750f51ffb5..000000000000 --- a/test/unit/test/temporal-mock.test.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { afterEach, describe, expect, it, vi } from 'vitest' - -// use polyfill for node < 26 -if (!globalThis.Temporal) { - await import('temporal-polyfill/global') -} - -describe('testing Temporal mock functionality', () => { - afterEach(() => { - vi.useRealTimers() - }) - - it('setting time', () => { - const date = new Date(2000, 0, 1) - vi.setSystemTime(date) - - expect(Temporal.Now.instant().epochMilliseconds).toEqual(date.getTime()) - expect(Temporal.Now.zonedDateTimeISO().epochMilliseconds).toEqual(date.getTime()) - expect(Temporal.Now.plainDateISO()).toEqual(Temporal.PlainDate.from('2000-01-01')) - expect(Temporal.Now.plainDateTimeISO()).toEqual(Temporal.PlainDateTime.from('2000-01-01T00:00:00')) - expect(Temporal.Now.plainTimeISO()).toEqual(Temporal.PlainTime.from('00:00:00')) - - vi.useRealTimers() - - expect(Temporal.Now.instant().epochMilliseconds).not.toEqual(date.getTime()) - expect(Temporal.Now.zonedDateTimeISO().epochMilliseconds).not.toEqual(date.getTime()) - expect(Temporal.Now.plainDateISO()).not.toEqual(Temporal.PlainDate.from('2000-01-01')) - expect(Temporal.Now.plainDateTimeISO()).not.toEqual(Temporal.PlainDateTime.from('2000-01-01T00:00:00')) - expect(Temporal.Now.plainTimeISO()).not.toEqual(Temporal.PlainTime.from('00:00:00')) - }) - - it('getting current date in the specific time zone', () => { - vi.setSystemTime(new Date('2000-01-01T00:00:00Z')) - - const timeZone = 'America/Los_Angeles' - const timeZoneLike = new Temporal.ZonedDateTime(0n, timeZone) - - for (const tz of [timeZone, timeZoneLike]) { - expect(Temporal.Now.zonedDateTimeISO(tz)).toEqual( - Temporal.ZonedDateTime.from('1999-12-31T16:00:00-08:00[America/Los_Angeles]'), - ) - expect(Temporal.Now.plainDateISO(tz)).toEqual(Temporal.PlainDate.from('1999-12-31')) - expect(Temporal.Now.plainDateTimeISO(tz)).toEqual(Temporal.PlainDateTime.from('1999-12-31T16:00:00')) - expect(Temporal.Now.plainTimeISO(tz)).toEqual(Temporal.PlainTime.from('16:00:00')) - } - }) -}) diff --git a/test/unit/test/timers-temporal.test.ts b/test/unit/test/timers-temporal.test.ts index e10eaac66674..697e8e012da9 100644 --- a/test/unit/test/timers-temporal.test.ts +++ b/test/unit/test/timers-temporal.test.ts @@ -24,3 +24,23 @@ it('Temporal.Now follows fake timers', () => { expect(globalThis.Temporal).toBe(real) expect(globalThis.Temporal.Now.instant().epochMilliseconds).not.toBe(1234) }) + +it('Temporal.Now follows setSystemTime without fake timers', () => { + const real = globalThis.Temporal + + expect(vi.isFakeTimers()).toBe(false) + vi.setSystemTime(0) + expect(vi.isFakeTimers()).toBe(false) + expect(globalThis.Temporal).not.toBe(real) + expect(globalThis.Temporal.Now.instant().epochMilliseconds).toBe(0) + + vi.setSystemTime(1234) + expect(vi.isFakeTimers()).toBe(false) + expect(globalThis.Temporal.Now.instant().epochMilliseconds).toBe(1234) + + // restore + vi.useRealTimers() + expect(vi.isFakeTimers()).toBe(false) + expect(globalThis.Temporal).toBe(real) + expect(globalThis.Temporal.Now.instant().epochMilliseconds).not.toBe(1234) +})