aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Ashcon Partovi <ashcon@partovi.net> 2023-06-10 11:10:19 -0700
committerGravatar Ashcon Partovi <ashcon@partovi.net> 2023-06-10 11:10:19 -0700
commite4352a490e30ff398e12a76ff84d561d9b80cf3e (patch)
tree6d37d272ceca5e56597aa9f438275196251b6532
parenta2ec2ea397e96dd7bb64177964e11bf4c9a4b91b (diff)
downloadbun-e4352a490e30ff398e12a76ff84d561d9b80cf3e.tar.gz
bun-e4352a490e30ff398e12a76ff84d561d9b80cf3e.tar.zst
bun-e4352a490e30ff398e12a76ff84d561d9b80cf3e.zip
Implement
-rw-r--r--packages/bun-types/bun-test.d.ts10
-rw-r--r--src/bun.js/bindings/JSMockFunction.cpp34
-rw-r--r--src/bun.js/bindings/JSSink.cpp2
-rw-r--r--src/bun.js/bindings/JSSink.h2
-rw-r--r--src/bun.js/bindings/JSSinkLookupTable.h2
-rw-r--r--src/bun.js/test/jest.zig2
-rw-r--r--test/js/bun/test/mock-test.test.ts22
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]);
+});