Compare commits

...

2 Commits

Author SHA1 Message Date
Ashcon Partovi
3ca374ff82 Fix formatting 2023-06-10 11:16:29 -07:00
Ashcon Partovi
e4352a490e Implement 2023-06-10 11:10:19 -07:00
7 changed files with 64 additions and 10 deletions

View File

@@ -1028,6 +1028,11 @@ declare namespace JestMock {
* List of the call arguments of all calls that have been made to the mock.
*/
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.
*/
@@ -1041,11 +1046,6 @@ declare namespace JestMock {
* invocations of all mocks in a test file. The index is starting with `1`.
*/
// 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.
*/

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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!

View File

@@ -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()) {

View File

@@ -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]);
});