From ceec1afec2bb187fecef0f5006dfe27ee3e1a9a6 Mon Sep 17 00:00:00 2001 From: dave caruso Date: Sat, 24 Jun 2023 02:24:05 -0400 Subject: Add vi.spyOn and clean up some mock function binding calls (#3376) * Add vi.spyOn and clean up some binding calls * add vi.restoreAllMocks * remove junk file --------- Co-authored-by: Jarred Sumner --- src/bun.js/bindings/JSMockFunction.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'src/bun.js/bindings/JSMockFunction.cpp') diff --git a/src/bun.js/bindings/JSMockFunction.cpp b/src/bun.js/bindings/JSMockFunction.cpp index b7c2659b4..fbfcf0c9e 100644 --- a/src/bun.js/bindings/JSMockFunction.cpp +++ b/src/bun.js/bindings/JSMockFunction.cpp @@ -391,6 +391,7 @@ void JSMockFunction::visitChildrenImpl(JSCell* cell, Visitor& visitor) visitor.append(fn->instances); visitor.append(fn->returnValues); visitor.append(fn->invocationCallOrder); + visitor.append(fn->spyOriginal); fn->mock.visit(visitor); } DEFINE_VISIT_CHILDREN(JSMockFunction); @@ -526,13 +527,13 @@ extern "C" void JSMock__resetSpies(Zig::GlobalObject* globalObject) globalObject->mockModule.activeSpies.clear(); } -extern "C" EncodedJSValue jsFunctionResetSpies(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe) +extern "C" EncodedJSValue JSMock__jsRestoreAllMocks(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe) { JSMock__resetSpies(jsCast(globalObject)); return JSValue::encode(jsUndefined()); } -extern "C" EncodedJSValue JSMock__spyOn(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callframe) +extern "C" EncodedJSValue JSMock__jsSpyOn(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callframe) { auto& vm = lexicalGlobalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); @@ -963,7 +964,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsMockFunctionGetter_protoImpl, (JSC::JSGlobalObject * return JSValue::encode(jsUndefined()); } -JSC_DEFINE_HOST_FUNCTION(jsMockFunctionConstructor, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callframe)) +extern "C" EncodedJSValue JSMock__jsMockFn(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callframe) { auto& vm = lexicalGlobalObject->vm(); auto* globalObject = jsCast(lexicalGlobalObject); @@ -997,11 +998,6 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionConstructor, (JSC::JSGlobalObject * lexic return JSValue::encode(thisObject); } -extern "C" EncodedJSValue JSMockFunction__createObject(Zig::GlobalObject* globalObject) -{ - auto& vm = globalObject->vm(); - return JSValue::encode(JSC::JSFunction::create(vm, globalObject, 0, "mock"_s, jsMockFunctionConstructor, ImplementationVisibility::Public)); -} extern "C" EncodedJSValue JSMockFunction__getCalls(EncodedJSValue encodedValue) { JSValue value = JSValue::decode(encodedValue); -- cgit v1.2.3 From ecb0bd39b6f7a0a69f0b92ddedc0af5d0e88e945 Mon Sep 17 00:00:00 2001 From: dave caruso Date: Mon, 26 Jun 2023 22:27:12 -0400 Subject: fix #3412 (#3422) --- src/bun.js/bindings/JSMockFunction.cpp | 12 ++++++++---- test/js/bun/test/mock-fn.test.js | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) (limited to 'src/bun.js/bindings/JSMockFunction.cpp') diff --git a/src/bun.js/bindings/JSMockFunction.cpp b/src/bun.js/bindings/JSMockFunction.cpp index fbfcf0c9e..33922c2b7 100644 --- a/src/bun.js/bindings/JSMockFunction.cpp +++ b/src/bun.js/bindings/JSMockFunction.cpp @@ -569,15 +569,19 @@ extern "C" EncodedJSValue JSMock__jsSpyOn(JSC::JSGlobalObject* lexicalGlobalObje // easymode: regular property or missing property if (!hasValue || slot.isValue()) { + JSValue value = jsUndefined(); + if (hasValue) { + value = slot.getValue(globalObject, propertyKey); + if (jsDynamicCast(value)) { + return JSValue::encode(value); + } + } + auto* mock = JSMockFunction::create(vm, globalObject, globalObject->mockModule.mockFunctionStructure.getInitializedOnMainThread(globalObject), CallbackKind::GetterSetter); mock->spyTarget = JSC::Weak(object, &weakValueHandleOwner(), nullptr); mock->spyIdentifier = propertyKey.isSymbol() ? Identifier::fromUid(vm, propertyKey.uid()) : Identifier::fromString(vm, propertyKey.publicName()); mock->spyAttributes = hasValue ? slot.attributes() : 0; unsigned attributes = 0; - JSValue value = jsUndefined(); - - if (hasValue) - value = slot.getValue(globalObject, propertyKey); if (hasValue && ((slot.attributes() & PropertyAttribute::Function) != 0 || (value.isCell() && value.isCallable()))) { if (hasValue) diff --git a/test/js/bun/test/mock-fn.test.js b/test/js/bun/test/mock-fn.test.js index 8504e3d70..ef3c4b7d3 100644 --- a/test/js/bun/test/mock-fn.test.js +++ b/test/js/bun/test/mock-fn.test.js @@ -603,5 +603,19 @@ describe("spyOn", () => { }); } + test("spyOn twice works", () => { + var obj = { + original() { + return 42; + }, + }; + const _original = obj.original; + const fn = spyOn(obj, "original"); + const fn2 = spyOn(obj, "original"); + expect(fn).toBe(obj.original); + expect(fn2).toBe(fn); + expect(fn).not.toBe(_original); + }); + // spyOn does not work with getters/setters yet. }); -- cgit v1.2.3 From aa38e51afb73dab3071addc07f82fd96153ff450 Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Sun, 2 Jul 2023 22:09:50 -0700 Subject: Support mocking `new Date()` & `Date.now()` in bun:test (#3501) * Support changing the time * Bump WebKit * Update bun.lockb --------- Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> --- .github/workflows/bun-linux-aarch64.yml | 2 +- .github/workflows/bun-linux-build.yml | 4 ++-- .github/workflows/bun-mac-aarch64.yml | 16 ++++++++-------- .github/workflows/bun-mac-x64-baseline.yml | 16 ++++++++-------- .github/workflows/bun-mac-x64.yml | 16 ++++++++-------- Dockerfile | 2 +- bun.lockb | Bin 72925 -> 72925 bytes package.json | 2 +- src/bun.js/WebKit | 2 +- src/bun.js/bindings/JSMockFunction.cpp | 24 ++++++++++++++++++++++++ src/bun.js/test/jest.zig | 5 +++++ test/js/bun/test/test-timers.test.ts | 11 +++++++++++ 12 files changed, 70 insertions(+), 30 deletions(-) create mode 100644 test/js/bun/test/test-timers.test.ts (limited to 'src/bun.js/bindings/JSMockFunction.cpp') diff --git a/.github/workflows/bun-linux-aarch64.yml b/.github/workflows/bun-linux-aarch64.yml index 01714460b..13dddece4 100644 --- a/.github/workflows/bun-linux-aarch64.yml +++ b/.github/workflows/bun-linux-aarch64.yml @@ -36,7 +36,7 @@ jobs: arch: aarch64 build_arch: arm64 runner: linux-arm64 - webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-linux-arm64-lto.tar.gz" + webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-linux-arm64-lto.tar.gz" webkit_basename: "bun-webkit-linux-arm64-lto" build_machine_arch: aarch64 diff --git a/.github/workflows/bun-linux-build.yml b/.github/workflows/bun-linux-build.yml index 798ffaf33..e992770f1 100644 --- a/.github/workflows/bun-linux-build.yml +++ b/.github/workflows/bun-linux-build.yml @@ -46,7 +46,7 @@ jobs: arch: x86_64 build_arch: amd64 runner: big-ubuntu - webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-linux-amd64-lto.tar.gz" + webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-linux-amd64-lto.tar.gz" webkit_basename: "bun-webkit-linux-amd64-lto" build_machine_arch: x86_64 - cpu: nehalem @@ -54,7 +54,7 @@ jobs: arch: x86_64 build_arch: amd64 runner: big-ubuntu - webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-linux-amd64-lto.tar.gz" + webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-linux-amd64-lto.tar.gz" webkit_basename: "bun-webkit-linux-amd64-lto" build_machine_arch: x86_64 diff --git a/.github/workflows/bun-mac-aarch64.yml b/.github/workflows/bun-mac-aarch64.yml index f281783bd..484c7035b 100644 --- a/.github/workflows/bun-mac-aarch64.yml +++ b/.github/workflows/bun-mac-aarch64.yml @@ -117,7 +117,7 @@ jobs: # obj: bun-obj-darwin-x64-baseline # runner: macos-11 # artifact: bun-obj-darwin-x64-baseline - # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-macos-amd64-lto.tar.gz" + # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-macos-amd64-lto.tar.gz" # dependencies: true # compile_obj: false # - cpu: haswell @@ -126,7 +126,7 @@ jobs: # obj: bun-obj-darwin-x64 # runner: macos-11 # artifact: bun-obj-darwin-x64 - # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-macos-amd64-lto.tar.gz" + # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-macos-amd64-lto.tar.gz" # dependencies: true # compile_obj: false # - cpu: nehalem @@ -135,7 +135,7 @@ jobs: # obj: bun-obj-darwin-x64-baseline # runner: macos-11 # artifact: bun-obj-darwin-x64-baseline - # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-macos-amd64-lto.tar.gz" + # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-macos-amd64-lto.tar.gz" # dependencies: false # compile_obj: true # - cpu: haswell @@ -144,7 +144,7 @@ jobs: # obj: bun-obj-darwin-x64 # runner: macos-11 # artifact: bun-obj-darwin-x64 - # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-macos-amd64-lto.tar.gz" + # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-macos-amd64-lto.tar.gz" # dependencies: false # compile_obj: true - cpu: native @@ -152,7 +152,7 @@ jobs: tag: bun-darwin-aarch64 obj: bun-obj-darwin-aarch64 artifact: bun-obj-darwin-aarch64 - webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-macos-arm64-lto.tar.gz" + webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-macos-arm64-lto.tar.gz" runner: macos-arm64 dependencies: true compile_obj: true @@ -257,7 +257,7 @@ jobs: # package: bun-darwin-x64 # runner: macos-11 # artifact: bun-obj-darwin-x64-baseline - # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-macos-amd64-lto.tar.gz" + # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-macos-amd64-lto.tar.gz" # - cpu: haswell # arch: x86_64 # tag: bun-darwin-x64 @@ -265,14 +265,14 @@ jobs: # package: bun-darwin-x64 # runner: macos-11 # artifact: bun-obj-darwin-x64 - # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-macos-amd64-lto.tar.gz" + # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-macos-amd64-lto.tar.gz" - cpu: native arch: aarch64 tag: bun-darwin-aarch64 obj: bun-obj-darwin-aarch64 package: bun-darwin-aarch64 artifact: bun-obj-darwin-aarch64 - webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-macos-arm64-lto.tar.gz" + webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-macos-arm64-lto.tar.gz" runner: macos-arm64 steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/bun-mac-x64-baseline.yml b/.github/workflows/bun-mac-x64-baseline.yml index b5f79a757..fe8f0b396 100644 --- a/.github/workflows/bun-mac-x64-baseline.yml +++ b/.github/workflows/bun-mac-x64-baseline.yml @@ -117,7 +117,7 @@ jobs: obj: bun-obj-darwin-x64-baseline runner: macos-11 artifact: bun-obj-darwin-x64-baseline - webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-macos-amd64-lto.tar.gz" + webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-macos-amd64-lto.tar.gz" dependencies: true compile_obj: false # - cpu: haswell @@ -126,7 +126,7 @@ jobs: # obj: bun-obj-darwin-x64 # runner: macos-11 # artifact: bun-obj-darwin-x64 - # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-macos-amd64-lto.tar.gz" + # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-macos-amd64-lto.tar.gz" # dependencies: true # compile_obj: false - cpu: nehalem @@ -135,7 +135,7 @@ jobs: obj: bun-obj-darwin-x64-baseline runner: macos-11 artifact: bun-obj-darwin-x64-baseline - webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-macos-amd64-lto.tar.gz" + webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-macos-amd64-lto.tar.gz" dependencies: false compile_obj: true # - cpu: haswell @@ -144,7 +144,7 @@ jobs: # obj: bun-obj-darwin-x64 # runner: macos-11 # artifact: bun-obj-darwin-x64 - # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-macos-amd64-lto.tar.gz" + # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-macos-amd64-lto.tar.gz" # dependencies: false # compile_obj: true # - cpu: native @@ -152,7 +152,7 @@ jobs: # tag: bun-darwin-aarch64 # obj: bun-obj-darwin-aarch64 # artifact: bun-obj-darwin-aarch64 - # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-macos-amd64-lto.tar.gz" + # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-macos-amd64-lto.tar.gz" # runner: macos-arm64 # dependencies: true # compile_obj: true @@ -258,7 +258,7 @@ jobs: package: bun-darwin-x64 runner: macos-11 artifact: bun-obj-darwin-x64-baseline - webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-macos-amd64-lto.tar.gz" + webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-macos-amd64-lto.tar.gz" # - cpu: haswell # arch: x86_64 # tag: bun-darwin-x64 @@ -266,14 +266,14 @@ jobs: # package: bun-darwin-x64 # runner: macos-11 # artifact: bun-obj-darwin-x64 - # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-macos-amd64-lto.tar.gz" + # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-macos-amd64-lto.tar.gz" # - cpu: native # arch: aarch64 # tag: bun-darwin-aarch64 # obj: bun-obj-darwin-aarch64 # package: bun-darwin-aarch64 # artifact: bun-obj-darwin-aarch64 - # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-macos-amd64-lto.tar.gz" + # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-macos-amd64-lto.tar.gz" # runner: macos-arm64 steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/bun-mac-x64.yml b/.github/workflows/bun-mac-x64.yml index 8b30321f0..ae265adab 100644 --- a/.github/workflows/bun-mac-x64.yml +++ b/.github/workflows/bun-mac-x64.yml @@ -117,7 +117,7 @@ jobs: # obj: bun-obj-darwin-x64-baseline # runner: macos-11 # artifact: bun-obj-darwin-x64-baseline - # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-macos-amd64-lto.tar.gz" + # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-macos-amd64-lto.tar.gz" # dependencies: true # compile_obj: false - cpu: haswell @@ -126,7 +126,7 @@ jobs: obj: bun-obj-darwin-x64 runner: macos-11 artifact: bun-obj-darwin-x64 - webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-macos-amd64-lto.tar.gz" + webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-macos-amd64-lto.tar.gz" dependencies: true compile_obj: false # - cpu: nehalem @@ -135,7 +135,7 @@ jobs: # obj: bun-obj-darwin-x64-baseline # runner: macos-11 # artifact: bun-obj-darwin-x64-baseline - # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-macos-amd64-lto.tar.gz" + # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-macos-amd64-lto.tar.gz" # dependencies: false # compile_obj: true - cpu: haswell @@ -144,7 +144,7 @@ jobs: obj: bun-obj-darwin-x64 runner: macos-11 artifact: bun-obj-darwin-x64 - webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-macos-amd64-lto.tar.gz" + webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-macos-amd64-lto.tar.gz" dependencies: false compile_obj: true # - cpu: native @@ -152,7 +152,7 @@ jobs: # tag: bun-darwin-aarch64 # obj: bun-obj-darwin-aarch64 # artifact: bun-obj-darwin-aarch64 - # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-macos-arm64-lto.tar.gz" + # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-macos-arm64-lto.tar.gz" # runner: macos-arm64 # dependencies: true # compile_obj: true @@ -260,7 +260,7 @@ jobs: # package: bun-darwin-x64 # runner: macos-11 # artifact: bun-obj-darwin-x64-baseline - # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-macos-amd64-lto.tar.gz" + # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-macos-amd64-lto.tar.gz" - cpu: haswell arch: x86_64 tag: bun-darwin-x64 @@ -268,14 +268,14 @@ jobs: package: bun-darwin-x64 runner: macos-11 artifact: bun-obj-darwin-x64 - webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-macos-amd64-lto.tar.gz" + webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-macos-amd64-lto.tar.gz" # - cpu: native # arch: aarch64 # tag: bun-darwin-aarch64 # obj: bun-obj-darwin-aarch64 # package: bun-darwin-aarch64 # artifact: bun-obj-darwin-aarch64 - # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-2/bun-webkit-macos-arm64-lto.tar.gz" + # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20-3/bun-webkit-macos-arm64-lto.tar.gz" # runner: macos-arm64 steps: - uses: actions/checkout@v3 diff --git a/Dockerfile b/Dockerfile index 5f66a5e04..66c3360af 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,7 +10,7 @@ ARG ARCH=x86_64 ARG BUILD_MACHINE_ARCH=x86_64 ARG TRIPLET=${ARCH}-linux-gnu ARG BUILDARCH=amd64 -ARG WEBKIT_TAG=may20-2 +ARG WEBKIT_TAG=may20-3 ARG ZIG_TAG=jul1 ARG ZIG_VERSION="0.11.0-dev.3737+9eb008717" ARG WEBKIT_BASENAME="bun-webkit-linux-$BUILDARCH" diff --git a/bun.lockb b/bun.lockb index e53db751b..69f9ded0b 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 4fe213747..f4bd86e76 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "@types/react": "^18.0.25", "@typescript-eslint/eslint-plugin": "^5.31.0", "@typescript-eslint/parser": "^5.31.0", - "bun-webkit": "0.0.1-8a03cf746abef8a48c932ab25f8821390632f2e2" + "bun-webkit": "0.0.1-26c819733315f0ab64ae8e8e65b77d77d31211e1" }, "version": "0.0.0", "prettier": "./.prettierrc.cjs" diff --git a/src/bun.js/WebKit b/src/bun.js/WebKit index 8a03cf746..26c819733 160000 --- a/src/bun.js/WebKit +++ b/src/bun.js/WebKit @@ -1 +1 @@ -Subproject commit 8a03cf746abef8a48c932ab25f8821390632f2e2 +Subproject commit 26c819733315f0ab64ae8e8e65b77d77d31211e1 diff --git a/src/bun.js/bindings/JSMockFunction.cpp b/src/bun.js/bindings/JSMockFunction.cpp index 33922c2b7..0e24e761c 100644 --- a/src/bun.js/bindings/JSMockFunction.cpp +++ b/src/bun.js/bindings/JSMockFunction.cpp @@ -19,6 +19,7 @@ #include #include #include +#include namespace Bun { @@ -65,6 +66,29 @@ JSC_DECLARE_HOST_FUNCTION(jsMockFunctionMockRejectedValueOnce); JSC_DECLARE_HOST_FUNCTION(jsMockFunctionWithImplementationCleanup); JSC_DECLARE_HOST_FUNCTION(jsMockFunctionWithImplementation); +extern "C" EncodedJSValue JSMock__jsNow(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) +{ + return JSValue::encode(jsNumber(globalObject->jsDateNow())); +} +extern "C" EncodedJSValue JSMock__jsSetSystemTime(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) +{ + JSValue argument0 = callFrame->argument(0); + + if (auto* dateInstance = jsDynamicCast(argument0)) { + if (std::isnormal(dateInstance->internalNumber())) { + globalObject->overridenDateNow = dateInstance->internalNumber(); + } + return JSValue::encode(callFrame->thisValue()); + } + + if (argument0.isNumber() && argument0.asNumber() > 0) { + globalObject->overridenDateNow = argument0.asNumber(); + } + + globalObject->overridenDateNow = -1; + return JSValue::encode(callFrame->thisValue()); +} + uint64_t JSMockModule::s_nextInvocationId = 0; // This is taken from JSWeakSet diff --git a/src/bun.js/test/jest.zig b/src/bun.js/test/jest.zig index 6e4cb827c..727466835 100644 --- a/src/bun.js/test/jest.zig +++ b/src/bun.js/test/jest.zig @@ -440,6 +440,9 @@ pub const Jest = struct { 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("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); @@ -455,6 +458,8 @@ pub const Jest = struct { extern fn Bun__Jest__testPreloadObject(*JSC.JSGlobalObject) JSC.JSValue; extern fn Bun__Jest__testModuleObject(*JSC.JSGlobalObject) JSC.JSValue; extern fn JSMock__jsMockFn(*JSC.JSGlobalObject, *JSC.CallFrame) JSC.JSValue; + extern fn JSMock__jsNow(*JSC.JSGlobalObject, *JSC.CallFrame) JSC.JSValue; + 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; diff --git a/test/js/bun/test/test-timers.test.ts b/test/js/bun/test/test-timers.test.ts new file mode 100644 index 000000000..64da0abda --- /dev/null +++ b/test/js/bun/test/test-timers.test.ts @@ -0,0 +1,11 @@ +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"); +}); -- cgit v1.2.3 From f0a795b568b741f71945e1078b87355d3217cc23 Mon Sep 17 00:00:00 2001 From: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> Date: Sun, 2 Jul 2023 22:42:13 -0700 Subject: Stub out `useFakeTimers` and `useRealTimers` --- packages/bun-types/bun-test.d.ts | 30 +++++++++++++++++++++++++++++ src/bun.js/bindings/JSMockFunction.cpp | 12 ++++++++++++ src/bun.js/test/jest.zig | 31 +++++++++++++++++++++++++++--- test/js/bun/test/test-timers.test.ts | 35 +++++++++++++++++++++++++--------- 4 files changed, 96 insertions(+), 12 deletions(-) (limited to 'src/bun.js/bindings/JSMockFunction.cpp') 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" { (Function: T): Mock; }; + /** + * 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; + interface Jest { restoreAllMocks(): void; fn(func?: T): Mock; 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()); }); -- cgit v1.2.3