diff options
author | 2023-06-10 11:10:19 -0700 | |
---|---|---|
committer | 2023-06-10 11:10:19 -0700 | |
commit | e4352a490e30ff398e12a76ff84d561d9b80cf3e (patch) | |
tree | 6d37d272ceca5e56597aa9f438275196251b6532 | |
parent | a2ec2ea397e96dd7bb64177964e11bf4c9a4b91b (diff) | |
download | bun-e4352a490e30ff398e12a76ff84d561d9b80cf3e.tar.gz bun-e4352a490e30ff398e12a76ff84d561d9b80cf3e.tar.zst bun-e4352a490e30ff398e12a76ff84d561d9b80cf3e.zip |
Implement
-rw-r--r-- | packages/bun-types/bun-test.d.ts | 10 | ||||
-rw-r--r-- | src/bun.js/bindings/JSMockFunction.cpp | 34 | ||||
-rw-r--r-- | src/bun.js/bindings/JSSink.cpp | 2 | ||||
-rw-r--r-- | src/bun.js/bindings/JSSink.h | 2 | ||||
-rw-r--r-- | src/bun.js/bindings/JSSinkLookupTable.h | 2 | ||||
-rw-r--r-- | src/bun.js/test/jest.zig | 2 | ||||
-rw-r--r-- | test/js/bun/test/mock-test.test.ts | 22 |
7 files changed, 64 insertions, 10 deletions
diff --git a/packages/bun-types/bun-test.d.ts b/packages/bun-types/bun-test.d.ts index 8c429d6fc..b1b4e88dd 100644 --- a/packages/bun-types/bun-test.d.ts +++ b/packages/bun-types/bun-test.d.ts @@ -1029,6 +1029,11 @@ declare namespace JestMock { */ calls: Array<Parameters<T>>; /** + * List of the call arguments of the last call that was made to the mock. + * If the function was not called, it will return `undefined`. + */ + lastCall?: Parameters<T>; + /** * List of all the object instances that have been instantiated from the mock. */ instances: Array<ReturnType<T>>; @@ -1042,11 +1047,6 @@ declare namespace JestMock { */ // invocationCallOrder: Array<number>; /** - * List of the call arguments of the last call that was made to the mock. - * If the function was not called, it will return `undefined`. - */ - // lastCall?: Parameters<T>; - /** * List of the results of all calls that have been made to the mock. */ results: Array<MockFunctionResult<T>>; diff --git a/src/bun.js/bindings/JSMockFunction.cpp b/src/bun.js/bindings/JSMockFunction.cpp index 6aeb44ded..5607f4042 100644 --- a/src/bun.js/bindings/JSMockFunction.cpp +++ b/src/bun.js/bindings/JSMockFunction.cpp @@ -23,6 +23,7 @@ namespace Bun { JSC_DECLARE_HOST_FUNCTION(jsMockFunctionCall); JSC_DECLARE_CUSTOM_GETTER(jsMockFunctionGetter_protoImpl); JSC_DECLARE_CUSTOM_GETTER(jsMockFunctionGetter_mock); +JSC_DECLARE_CUSTOM_GETTER(jsMockFunctionGetter_mockGetLastCall); JSC_DECLARE_HOST_FUNCTION(jsMockFunctionGetMockImplementation); JSC_DECLARE_HOST_FUNCTION(jsMockFunctionGetMockName); JSC_DECLARE_HOST_FUNCTION(jsMockFunctionMockClear); @@ -218,6 +219,9 @@ public: object->putDirectOffset(init.vm, 1, mock->getContexts()); object->putDirectOffset(init.vm, 2, mock->getInstances()); object->putDirectOffset(init.vm, 3, mock->getReturnValues()); + object->putDirectCustomAccessor(init.vm, JSC::Identifier::fromString(init.vm, "lastCall"_s), + JSC::CustomGetterSetter::create(init.vm, jsMockFunctionGetter_mockGetLastCall, nullptr), + JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); init.set(object); }); } @@ -582,7 +586,7 @@ JSMockModule JSMockModule::create(JSC::JSGlobalObject* globalObject) JSC::Structure* structure = globalObject->structureCache().emptyObjectStructureForPrototype( globalObject, globalObject->objectPrototype(), - 4); + 5); JSC::PropertyOffset offset; structure = structure->addPropertyTransition( init.vm, @@ -608,6 +612,12 @@ JSMockModule JSMockModule::create(JSC::JSGlobalObject* globalObject) JSC::Identifier::fromString(init.vm, "results"_s), JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly, offset); + structure = structure->addPropertyTransition( + init.vm, + structure, + JSC::Identifier::fromString(init.vm, "lastCall"_s), + JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Accessor, + offset); init.set(structure); }); @@ -841,6 +851,27 @@ JSC_DEFINE_CUSTOM_GETTER(jsMockFunctionGetter_protoImpl, (JSC::JSGlobalObject * return JSValue::encode(jsUndefined()); } +JSC_DEFINE_CUSTOM_GETTER(jsMockFunctionGetter_mockGetLastCall, (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName)) +{ + JSValue thisObject = JSValue::decode(thisValue); + auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); + if (UNLIKELY(!thisObject.isObject())) { + throwTypeError(globalObject, scope, "Expected Mock"_s); + return {}; + } + JSValue callsValue = thisObject.get(globalObject, Identifier::fromString(globalObject->vm(), "calls"_s)); + if (UNLIKELY(!callsValue.isCell() || !callsValue.asCell()->inherits<JSArray>())) { + throwTypeError(globalObject, scope, "Expected Mock"_s); + return {}; + } + JSArray *callsArray = jsCast<JSArray*>(callsValue); + auto len = callsArray->length(); + if (len == 0) + return JSValue::encode(jsUndefined()); + + return JSValue::encode(callsArray->getIndex(globalObject, len - 1)); +} + extern "C" EncodedJSValue JSMockFunction__createObject(Zig::GlobalObject* globalObject) { return JSValue::encode( @@ -858,6 +889,7 @@ extern "C" EncodedJSValue JSMockFunction__getCalls(EncodedJSValue encodedValue) return JSValue::encode({}); } + extern "C" EncodedJSValue JSMockFunction__getReturns(EncodedJSValue encodedValue) { JSValue value = JSValue::decode(encodedValue); diff --git a/src/bun.js/bindings/JSSink.cpp b/src/bun.js/bindings/JSSink.cpp index 36be334dd..f0887d907 100644 --- a/src/bun.js/bindings/JSSink.cpp +++ b/src/bun.js/bindings/JSSink.cpp @@ -1,6 +1,6 @@ // AUTO-GENERATED FILE. DO NOT EDIT. -// Generated by 'make generate-sink' at 2023-05-18T01:04:00.447Z +// Generated by 'make generate-sink' at 2023-06-10T17:38:55.944Z // To regenerate this file, run: // // make generate-sink diff --git a/src/bun.js/bindings/JSSink.h b/src/bun.js/bindings/JSSink.h index 5bbfab777..4785f637a 100644 --- a/src/bun.js/bindings/JSSink.h +++ b/src/bun.js/bindings/JSSink.h @@ -1,6 +1,6 @@ // AUTO-GENERATED FILE. DO NOT EDIT. -// Generated by 'make generate-sink' at 2023-05-18T01:04:00.446Z +// Generated by 'make generate-sink' at 2023-06-10T17:38:55.943Z // #pragma once diff --git a/src/bun.js/bindings/JSSinkLookupTable.h b/src/bun.js/bindings/JSSinkLookupTable.h index a4ace6dc3..7ff4c3f9c 100644 --- a/src/bun.js/bindings/JSSinkLookupTable.h +++ b/src/bun.js/bindings/JSSinkLookupTable.h @@ -1,4 +1,4 @@ -// Automatically generated from src/bun.js/bindings/JSSink.cpp using /Users/jarred/Code/bun/src/bun.js/WebKit/Source/JavaScriptCore/create_hash_table. DO NOT EDIT! +// Automatically generated from src/bun.js/bindings/JSSink.cpp using /Users/ashcon/Desktop/code/bun/src/bun.js/WebKit/Source/JavaScriptCore/create_hash_table. DO NOT EDIT! diff --git a/src/bun.js/test/jest.zig b/src/bun.js/test/jest.zig index 93edb8abd..b33c5131a 100644 --- a/src/bun.js/test/jest.zig +++ b/src/bun.js/test/jest.zig @@ -3861,6 +3861,7 @@ pub const Expect = struct { return .zero; }; + JSC.markBinding(@src()); const calls = JSMockFunction__getCalls(value); active_test_expectation_counter.actual += 1; @@ -3911,6 +3912,7 @@ pub const Expect = struct { active_test_expectation_counter.actual += 1; + JSC.markBinding(@src()); const calls = JSMockFunction__getCalls(value); if (calls == .zero or !calls.jsType().isArray()) { diff --git a/test/js/bun/test/mock-test.test.ts b/test/js/bun/test/mock-test.test.ts index e51d9fcc7..c5f2f3eec 100644 --- a/test/js/bun/test/mock-test.test.ts +++ b/test/js/bun/test/mock-test.test.ts @@ -2,17 +2,24 @@ import { test, mock, expect, spyOn, jest } from "bun:test"; test("are callable", () => { const fn = mock(() => 42); + expect(fn).not.toHaveBeenCalled(); + expect(fn).not.toHaveBeenCalledTimes(1); + expect(fn.mock.calls).toBeEmpty(); + expect(fn.mock.lastCall).toBeUndefined(); + expect(fn()).toBe(42); expect(fn).toHaveBeenCalled(); expect(fn).toHaveBeenCalledTimes(1); expect(fn.mock.calls).toHaveLength(1); expect(fn.mock.calls[0]).toBeEmpty(); + expect(fn.mock.lastCall).not.toBeUndefined(); expect(fn()).toBe(42); expect(fn).toHaveBeenCalledTimes(2); - + expect(fn).not.toHaveBeenCalledTimes(1); expect(fn.mock.calls).toHaveLength(2); expect(fn.mock.calls[1]).toBeEmpty(); + expect(fn.mock.lastCall).toBe(fn.mock.calls[1]); // should refer to the same object }); test("include arguments", () => { @@ -23,6 +30,7 @@ test("include arguments", () => { value: 43, }); expect(fn.mock.calls[0]).toEqual([43]); + expect(fn.mock.lastCall).toEqual([43]); }); test("works when throwing", () => { @@ -36,6 +44,7 @@ test("works when throwing", () => { value: instance, }); expect(fn.mock.calls[0]).toEqual([43]); + expect(fn.mock.lastCall).toEqual([43]); }); test("mockReset works", () => { @@ -49,6 +58,7 @@ test("mockReset works", () => { value: instance, }); expect(fn.mock.calls[0]).toEqual([43]); + expect(fn.mock.lastCall).toEqual([43]); fn.mockReset(); @@ -63,6 +73,7 @@ test("mockReset works", () => { value: instance, }); expect(fn.mock.calls[0]).toEqual([43]); + expect(fn.mock.lastCall).toEqual([43]); }); test("spyOn works on functions", () => { @@ -133,3 +144,12 @@ test("spyOn works on globalThis", () => { }); // spyOn does not work with getters/setters yet. + +test("lastCall works", () => { + const fn = mock((v) => -v); + expect(fn.mock.lastCall).toBeUndefined(); + expect(fn(1)).toBe(-1); + expect(fn.mock.lastCall).toEqual([1]); + expect(fn(-2)).toBe(2); + expect(fn.mock.lastCall).toEqual([-2]); +}); |