From 0788a26dd6d7c3eeded3e5eaf87313ef9885d4dc Mon Sep 17 00:00:00 2001 From: Ivan Demchuk Date: Thu, 27 Jan 2022 02:11:02 +0200 Subject: [PATCH] feat: allow to mock date without fake timers (fix #621) (#639) Co-authored-by: Anthony Fu --- packages/vitest/package.json | 7 ++++--- packages/vitest/src/integrations/timers.ts | 22 +++++++++++++++++++++- pnpm-lock.yaml | 18 ++++++++++++------ test/core/test/date-mock.test.ts | 6 +----- test/core/test/timers.test.ts | 17 +++++++++++++++++ test/reporters/tests/reporters.spec.ts | 6 +----- 6 files changed, 56 insertions(+), 20 deletions(-) diff --git a/packages/vitest/package.json b/packages/vitest/package.json index ed6b7154f..f5d3ddd02 100644 --- a/packages/vitest/package.json +++ b/packages/vitest/package.json @@ -90,6 +90,7 @@ "magic-string": "^0.25.7", "micromatch": "^4.0.4", "mlly": "^0.3.19", + "mockdate": "^3.0.5", "natural-compare": "^1.4.0", "pathe": "^0.2.0", "picocolors": "^1.0.0", @@ -110,6 +111,9 @@ "jsdom": "*" }, "peerDependenciesMeta": { + "@vitest/ui": { + "optional": true + }, "c8": { "optional": true }, @@ -118,9 +122,6 @@ }, "jsdom": { "optional": true - }, - "@vitest/ui": { - "optional": true } }, "engines": { diff --git a/packages/vitest/src/integrations/timers.ts b/packages/vitest/src/integrations/timers.ts index 66f64ace0..2a0f4a242 100644 --- a/packages/vitest/src/integrations/timers.ts +++ b/packages/vitest/src/integrations/timers.ts @@ -12,10 +12,12 @@ import type { import { withGlobal, } from '@sinonjs/fake-timers' +import MockDate from 'mockdate' export class FakeTimers { private _clock!: InstalledClock private _fakingTime: boolean + private _fakingDate: boolean private _fakeTimers: FakeTimerWithContext private _maxLoops: number private _now = Date.now @@ -29,6 +31,8 @@ export class FakeTimers { }) { this._maxLoops = maxLoops + this._fakingDate = false + this._fakingTime = false this._fakeTimers = withGlobal(global) } @@ -78,6 +82,11 @@ export class FakeTimers { } useRealTimers(): void { + if (this._fakingDate) { + MockDate.reset() + this._fakingDate = false + } + if (this._fakingTime) { this._clock.uninstall() this._fakingTime = false @@ -85,6 +94,12 @@ export class FakeTimers { } useFakeTimers(): void { + if (this._fakingDate) { + throw new Error( + '"setSystemTime" was called already and date was mocked. Reset timers using `vi.useRealTimers()` if you want to use fake timers again.', + ) + } + if (!this._fakingTime) { const toFake = Object.keys(this._fakeTimers.timers) as Array @@ -108,8 +123,13 @@ export class FakeTimers { } setSystemTime(now?: number | Date): void { - if (this._checkFakeTimers()) + if (this._fakingTime) { this._clock.setSystemTime(now) + } + else { + MockDate.set(now ?? this.getRealSystemTime()) + this._fakingDate = true + } } getRealSystemTime(): number { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 86227264b..7498a8e9f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -106,7 +106,7 @@ importers: lit: 2.1.1 devDependencies: '@vitest/ui': link:../../packages/ui - happy-dom: 2.30.0 + happy-dom: 2.30.1 vite: 2.7.13 vitest: link:../../packages/vitest @@ -395,7 +395,7 @@ importers: devDependencies: '@vitejs/plugin-vue': 2.0.1_vite@2.7.13+vue@3.2.26 '@vue/test-utils': 2.0.0-rc.18_vue@3.2.26 - happy-dom: 2.30.0 + happy-dom: 2.30.1 unplugin-auto-import: 0.5.11_0300e2fc4592cc668512bad114c07138 unplugin-vue-components: 0.17.14_19c514bd5e4e89f4f64a7d4f3f15a1ba vitest: link:../../packages/vitest @@ -412,7 +412,7 @@ importers: devDependencies: '@vitejs/plugin-vue': 2.0.1_vite@2.7.13+vue@3.2.26 '@vue/test-utils': 2.0.0-rc.18_vue@3.2.26 - happy-dom: 2.30.0 + happy-dom: 2.30.1 vitest: link:../../packages/vitest examples/vue-jsx: @@ -428,7 +428,7 @@ importers: '@vitejs/plugin-vue': 2.0.1_vite@2.7.13+vue@3.2.26 '@vitejs/plugin-vue-jsx': 1.3.3 '@vue/test-utils': 2.0.0-rc.18_vue@3.2.26 - happy-dom: 2.30.0 + happy-dom: 2.30.1 vite: 2.7.13 vitest: link:../../packages/vitest vue: 3.2.26 @@ -533,6 +533,7 @@ importers: magic-string: ^0.25.7 micromatch: ^4.0.4 mlly: ^0.3.19 + mockdate: ^3.0.5 natural-compare: ^1.4.0 pathe: ^0.2.0 picocolors: ^1.0.0 @@ -583,6 +584,7 @@ importers: magic-string: 0.25.7 micromatch: 4.0.4 mlly: 0.3.19 + mockdate: 3.0.5 natural-compare: 1.4.0 pathe: 0.2.0 picocolors: 1.0.0 @@ -10785,8 +10787,8 @@ packages: whatwg-mimetype: 2.3.0 dev: true - /happy-dom/2.30.0: - resolution: {integrity: sha512-//9pqe00RsVdBIR340bM8KRF0pYtwgVEo10pOpkCT3bIl45NjYFYg89ZV8dzu1j7rsP6ECTUy+OqNFf1h2wlaA==} + /happy-dom/2.30.1: + resolution: {integrity: sha512-Qz3Z/zn/VeUCtVEGoSCDD+zzPcyOEdIYz4p1BvsXvrTSx6vXyGadMDAsxOKf8ZFCRfuyLpLKfqdRHFFPF77qPA==} dependencies: he: 1.2.0 node-fetch: 2.6.6 @@ -12597,6 +12599,10 @@ packages: /mlly/0.3.19: resolution: {integrity: sha512-zMq5n3cOf4fOzA4WoeulxagbAgMChdev3MgP6K51k7M0u2whTXxupfIY4VVzws4vxkiWhwH1rVQcsw7zDGfRhA==} + /mockdate/3.0.5: + resolution: {integrity: sha512-iniQP4rj1FhBdBYS/+eQv7j1tadJ9lJtdzgOpvsOHng/GbcDh2Fhdeq+ZRldrPYdXvCyfFUmFeEwEGXZB5I/AQ==} + dev: true + /moment/2.29.1: resolution: {integrity: sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==} dev: true diff --git a/test/core/test/date-mock.test.ts b/test/core/test/date-mock.test.ts index be7a88fa7..35ed4abf1 100644 --- a/test/core/test/date-mock.test.ts +++ b/test/core/test/date-mock.test.ts @@ -1,10 +1,6 @@ -import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest' +import { afterEach, describe, expect, test, vi } from 'vitest' describe('testing date mock functionality', () => { - beforeEach(() => { - vi.useFakeTimers() - }) - afterEach(() => { vi.useRealTimers() }) diff --git a/test/core/test/timers.test.ts b/test/core/test/timers.test.ts index dbcf97f75..5c6bba759 100644 --- a/test/core/test/timers.test.ts +++ b/test/core/test/timers.test.ts @@ -845,5 +845,22 @@ describe('FakeTimers', () => { expect(timers.getTimerCount()).toEqual(0) }) + + it('throws when using useFakeTimers after setSystemTime', () => { + const timers = new FakeTimers({ global }) + + const timeStr = 'Fri Feb 20 2015 19:29:31 GMT+0530' + const timeStrMs = 1424440771000 + + timers.setSystemTime(timeStr) + + expect(Date.now()).toBe(timeStrMs) + + expect(() => timers.useFakeTimers()).toThrowError(/date was mocked/) + + // Some test + + timers.useRealTimers() + }) }) }) diff --git a/test/reporters/tests/reporters.spec.ts b/test/reporters/tests/reporters.spec.ts index 6e66434ca..7e41d83cb 100644 --- a/test/reporters/tests/reporters.spec.ts +++ b/test/reporters/tests/reporters.spec.ts @@ -1,4 +1,4 @@ -import { afterEach, beforeEach, expect, test, vi } from 'vitest' +import { afterEach, expect, test, vi } from 'vitest' import { JsonReporter } from '../../../packages/vitest/src/node/reporters/json' import { JUnitReporter } from '../../../packages/vitest/src/node/reporters/junit' import { TapReporter } from '../../../packages/vitest/src/node/reporters/tap' @@ -6,10 +6,6 @@ import { TapFlatReporter } from '../../../packages/vitest/src/node/reporters/tap import { getContext } from '../src/context' import { files } from '../src/data' -beforeEach(() => { - vi.useFakeTimers() -}) - afterEach(() => { vi.useRealTimers() }) -- 2.51.2