diff options
author | 2023-07-02 22:42:13 -0700 | |
---|---|---|
committer | 2023-07-02 22:42:13 -0700 | |
commit | f0a795b568b741f71945e1078b87355d3217cc23 (patch) | |
tree | 25854f39b097f5cd9fbb0c53f11bbd24a7469b59 | |
parent | aa38e51afb73dab3071addc07f82fd96153ff450 (diff) | |
download | bun-f0a795b568b741f71945e1078b87355d3217cc23.tar.gz bun-f0a795b568b741f71945e1078b87355d3217cc23.tar.zst bun-f0a795b568b741f71945e1078b87355d3217cc23.zip |
Stub out `useFakeTimers` and `useRealTimers`
-rw-r--r-- | packages/bun-types/bun-test.d.ts | 30 | ||||
-rw-r--r-- | src/bun.js/bindings/JSMockFunction.cpp | 12 | ||||
-rw-r--r-- | src/bun.js/test/jest.zig | 31 | ||||
-rw-r--r-- | test/js/bun/test/test-timers.test.ts | 35 |
4 files changed, 96 insertions, 12 deletions
diff --git a/packages/bun-types/bun-test.d.ts b/packages/bun-types/bun-test.d.ts index 156585766..5182f7e93 100644 --- a/packages/bun-types/bun-test.d.ts +++ b/packages/bun-types/bun-test.d.ts @@ -29,6 +29,36 @@ declare module "bun:test" { <T extends AnyFunction>(Function: T): Mock<T>; }; + /** + * Control the system time used by: + * - `Date.now()` + * - `new Date()` + * - `Intl.DateTimeFormat().format()` + * + * In the future, we may add support for more functions, but we haven't done that yet. + * + * @param now The time to set the system time to. If not provided, the system time will be reset. + * @returns `this` + * @since v0.6.13 + * + * ## Set Date to a specific time + * + * ```js + * import { setSystemTime } from 'bun:test'; + * + * setSystemTime(new Date('2020-01-01T00:00:00.000Z')); + * console.log(new Date().toISOString()); // 2020-01-01T00:00:00.000Z + * ``` + * ## Reset Date to the current time + * + * ```js + * import { setSystemTime } from 'bun:test'; + * + * setSystemTime(); + * ``` + */ + export function setSystemTime(now?: Date | number): ThisType<void>; + interface Jest { restoreAllMocks(): void; fn<T extends AnyFunction>(func?: T): Mock<T>; diff --git a/src/bun.js/bindings/JSMockFunction.cpp b/src/bun.js/bindings/JSMockFunction.cpp index 0e24e761c..3a84f0139 100644 --- a/src/bun.js/bindings/JSMockFunction.cpp +++ b/src/bun.js/bindings/JSMockFunction.cpp @@ -66,6 +66,18 @@ JSC_DECLARE_HOST_FUNCTION(jsMockFunctionMockRejectedValueOnce); JSC_DECLARE_HOST_FUNCTION(jsMockFunctionWithImplementationCleanup); JSC_DECLARE_HOST_FUNCTION(jsMockFunctionWithImplementation); +// This is a stub. Exists so that the same code can be run in Jest +extern "C" EncodedJSValue JSMock__jsUseFakeTimers(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) +{ + return JSValue::encode(callFrame->thisValue()); +} + +extern "C" EncodedJSValue JSMock__jsUseRealTimers(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) +{ + globalObject->overridenDateNow = -1; + return JSValue::encode(callFrame->thisValue()); +} + extern "C" EncodedJSValue JSMock__jsNow(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) { return JSValue::encode(jsNumber(globalObject->jsDateNow())); diff --git a/src/bun.js/test/jest.zig b/src/bun.js/test/jest.zig index 727466835..55600ded8 100644 --- a/src/bun.js/test/jest.zig +++ b/src/bun.js/test/jest.zig @@ -333,7 +333,7 @@ pub const Jest = struct { pub fn Bun__Jest__createTestModuleObject(globalObject: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { JSC.markBinding(@src()); - const module = JSC.JSValue.createEmptyObject(globalObject, 12); + const module = JSC.JSValue.createEmptyObject(globalObject, 13); const test_fn = JSC.NewFunction(globalObject, ZigString.static("test"), 2, TestScope.call, false); module.put( @@ -431,17 +431,40 @@ pub const Jest = struct { Expect.getConstructor(globalObject), ); + const setSystemTime = JSC.NewFunction(globalObject, ZigString.static("setSystemTime"), 0, JSMock__jsSetSystemTime, false); + module.put( + globalObject, + ZigString.static("setSystemTime"), + setSystemTime, + ); + const useFakeTimers = JSC.NewFunction(globalObject, ZigString.static("useFakeTimers"), 0, JSMock__jsUseFakeTimers, false); + const useRealTimers = JSC.NewFunction(globalObject, ZigString.static("useRealTimers"), 0, JSMock__jsUseRealTimers, false); + const mockFn = JSC.NewFunction(globalObject, ZigString.static("fn"), 1, JSMock__jsMockFn, false); const spyOn = JSC.NewFunction(globalObject, ZigString.static("spyOn"), 2, JSMock__jsSpyOn, false); const restoreAllMocks = JSC.NewFunction(globalObject, ZigString.static("restoreAllMocks"), 2, JSMock__jsRestoreAllMocks, false); module.put(globalObject, ZigString.static("mock"), mockFn); - const jest = JSValue.createEmptyObject(globalObject, 3); + const jest = JSValue.createEmptyObject(globalObject, 7); jest.put(globalObject, ZigString.static("fn"), mockFn); jest.put(globalObject, ZigString.static("spyOn"), spyOn); jest.put(globalObject, ZigString.static("restoreAllMocks"), restoreAllMocks); + jest.put( + globalObject, + ZigString.static("setSystemTime"), + setSystemTime, + ); + jest.put( + globalObject, + ZigString.static("useFakeTimers"), + useFakeTimers, + ); + jest.put( + globalObject, + ZigString.static("useRealTimers"), + useRealTimers, + ); jest.put(globalObject, ZigString.static("now"), JSC.NewFunction(globalObject, ZigString.static("now"), 0, JSMock__jsNow, false)); - jest.put(globalObject, ZigString.static("setSystemTime"), JSC.NewFunction(globalObject, ZigString.static("setSystemTime"), 0, JSMock__jsSetSystemTime, false)); module.put(globalObject, ZigString.static("jest"), jest); module.put(globalObject, ZigString.static("spyOn"), spyOn); @@ -462,6 +485,8 @@ pub const Jest = struct { extern fn JSMock__jsSetSystemTime(*JSC.JSGlobalObject, *JSC.CallFrame) JSC.JSValue; extern fn JSMock__jsRestoreAllMocks(*JSC.JSGlobalObject, *JSC.CallFrame) JSC.JSValue; extern fn JSMock__jsSpyOn(*JSC.JSGlobalObject, *JSC.CallFrame) JSC.JSValue; + extern fn JSMock__jsUseFakeTimers(*JSC.JSGlobalObject, *JSC.CallFrame) JSC.JSValue; + extern fn JSMock__jsUseRealTimers(*JSC.JSGlobalObject, *JSC.CallFrame) JSC.JSValue; pub fn call( _: void, diff --git a/test/js/bun/test/test-timers.test.ts b/test/js/bun/test/test-timers.test.ts index 64da0abda..963467dee 100644 --- a/test/js/bun/test/test-timers.test.ts +++ b/test/js/bun/test/test-timers.test.ts @@ -1,11 +1,28 @@ test("we can go back in time", () => { - const dateNow = Date.now; - // jest.useFakeTimers(); - jest.setSystemTime(new Date("2020-01-01T00:00:00.000Z")); - expect(new Date().toISOString()).toBe("2020-01-01T00:00:00.000Z"); - expect(Date.now()).toBe(1577836800000); - expect(dateNow).toBe(Date.now); - - jest.setSystemTime(); - expect(new Date().toISOString()).not.toBe("2020-01-01T00:00:00.000Z"); + const DateBeforeMocked = Date; + const orig = new Date(); + orig.setHours(0, 0, 0, 0); + jest.useFakeTimers(); + jest.setSystemTime(new Date("1995-12-19T00:00:00.000Z")); + + expect(new Date().toISOString()).toBe("1995-12-19T00:00:00.000Z"); + expect(Date.now()).toBe(819331200000); + + if (typeof Bun !== "undefined") { + // In bun, the Date object remains the same despite being mocked. + // This prevents a whole bunch of subtle bugs in tests. + expect(DateBeforeMocked).toBe(Date); + expect(DateBeforeMocked.now).toBe(Date.now); + + // Jest doesn't property mock new Intl.DateTimeFormat().format() + expect(new Intl.DateTimeFormat().format()).toBe("12/19/1995"); + } else { + expect(DateBeforeMocked).not.toBe(Date); + expect(DateBeforeMocked.now).not.toBe(Date.now); + } + + jest.useRealTimers(); + const now = new Date(); + now.setHours(0, 0, 0, 0); + expect(now.toISOString()).toBe(orig.toISOString()); }); |