aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/bun-linux-build.yml4
-rw-r--r--.github/workflows/bun-mac-aarch64.yml2
-rw-r--r--.github/workflows/bun-mac-x64-baseline.yml2
-rw-r--r--.github/workflows/bun-mac-x64.yml2
-rwxr-xr-xbun.lockbbin63917 -> 63661 bytes
-rw-r--r--docs/runtime/modules.md4
-rw-r--r--packages/bun-types/bun-test.d.ts28
-rw-r--r--src/bun.js/bindings/JSBufferList.cpp2
-rw-r--r--src/bun.js/bindings/JSMockFunction.cpp711
-rw-r--r--src/bun.js/bindings/JSMockFunction.h34
-rw-r--r--src/bun.js/bindings/ZigGlobalObject.cpp2
-rw-r--r--src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h1
-rw-r--r--src/bun.js/bindings/webcore/DOMIsoSubspaces.h1
-rw-r--r--src/bun.js/test/jest.zig23
-rw-r--r--src/js/out/WebCoreJSBuiltins.cpp4
-rw-r--r--src/js/out/modules/node/http.js3
-rw-r--r--src/js/out/modules/node/net.js4
-rwxr-xr-xtest/bun.lockbbin51098 -> 56172 bytes
-rw-r--r--test/js/bun/test/bigint.test.js14
-rw-r--r--test/js/bun/test/bun-test.test.ts6
-rw-r--r--test/js/bun/test/expect.test.js2955
-rw-r--r--test/js/bun/test/expect.test.ts442
-rw-r--r--test/js/bun/test/jest-extended.test.js516
-rw-r--r--test/js/bun/test/jest.d.ts5
-rw-r--r--test/js/bun/test/mock-fn.test.js599
-rw-r--r--test/js/bun/test/mock-test.test.ts224
-rw-r--r--test/js/bun/test/test-interop.js45
-rw-r--r--test/js/bun/test/test-test.test.ts2736
-rw-r--r--test/package.json11
-rw-r--r--test/snippets/package-json-exports/_node_modules_copy/exact/package.json1
30 files changed, 4662 insertions, 3719 deletions
diff --git a/.github/workflows/bun-linux-build.yml b/.github/workflows/bun-linux-build.yml
index f7665ab9a..603c0ad3d 100644
--- a/.github/workflows/bun-linux-build.yml
+++ b/.github/workflows/bun-linux-build.yml
@@ -45,7 +45,7 @@ jobs:
tag: linux-x64
arch: x86_64
build_arch: amd64
- runner: ubuntu-latest-xl
+ runner: big-ubuntu
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20/bun-webkit-linux-amd64-lto.tar.gz"
webkit_basename: "bun-webkit-linux-amd64-lto"
build_machine_arch: x86_64
@@ -53,7 +53,7 @@ jobs:
tag: linux-x64-baseline
arch: x86_64
build_arch: amd64
- runner: ubuntu-latest-xl
+ runner: big-ubuntu
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20/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 038bf741f..6ac6b958e 100644
--- a/.github/workflows/bun-mac-aarch64.yml
+++ b/.github/workflows/bun-mac-aarch64.yml
@@ -32,7 +32,7 @@ on:
jobs:
macos-object-files:
name: macOS Object
- runs-on: ubuntu-latest-xl
+ runs-on: med-ubuntu
if: github.repository_owner == 'oven-sh'
strategy:
matrix:
diff --git a/.github/workflows/bun-mac-x64-baseline.yml b/.github/workflows/bun-mac-x64-baseline.yml
index 7effc5642..c7a021c66 100644
--- a/.github/workflows/bun-mac-x64-baseline.yml
+++ b/.github/workflows/bun-mac-x64-baseline.yml
@@ -32,7 +32,7 @@ on:
jobs:
macos-object-files:
name: macOS Object
- runs-on: ubuntu-latest-xl
+ runs-on: med-ubuntu
if: github.repository_owner == 'oven-sh'
strategy:
matrix:
diff --git a/.github/workflows/bun-mac-x64.yml b/.github/workflows/bun-mac-x64.yml
index b9522344c..d8402d95d 100644
--- a/.github/workflows/bun-mac-x64.yml
+++ b/.github/workflows/bun-mac-x64.yml
@@ -32,7 +32,7 @@ on:
jobs:
macos-object-files:
name: macOS Object
- runs-on: ubuntu-latest-xl
+ runs-on: med-ubuntu
if: github.repository_owner == 'oven-sh'
strategy:
matrix:
diff --git a/bun.lockb b/bun.lockb
index 8e51bf3e4..42721afe8 100755
--- a/bun.lockb
+++ b/bun.lockb
Binary files differ
diff --git a/docs/runtime/modules.md b/docs/runtime/modules.md
index 32bd78cc3..42f2a08e6 100644
--- a/docs/runtime/modules.md
+++ b/docs/runtime/modules.md
@@ -108,8 +108,8 @@ Once it finds the `foo` package, Bun reads the `package.json` to determine how t
"worker": "./index.js",
"module": "./index.js",
"node": "./index.js",
- "browser": "./index.js",
- "default": "./index.js" // lowest priority
+ "default": "./index.js",
+ "browser": "./index.js" // lowest priority
}
}
```
diff --git a/packages/bun-types/bun-test.d.ts b/packages/bun-types/bun-test.d.ts
index c26ece304..ba59966ad 100644
--- a/packages/bun-types/bun-test.d.ts
+++ b/packages/bun-types/bun-test.d.ts
@@ -442,7 +442,7 @@ declare module "bun:test" {
toBe(expected: T): void;
/**
* Asserts that a number is odd.
- *
+ *
* @link https://jest-extended.jestcommunity.dev/docs/matchers/number/#tobeodd
* @example
* expect(1).toBeOdd();
@@ -451,7 +451,7 @@ declare module "bun:test" {
toBeOdd(): void;
/**
* Asserts that a number is even.
- *
+ *
* @link https://jest-extended.jestcommunity.dev/docs/matchers/number/#tobeeven
* @example
* expect(2).toBeEven();
@@ -740,7 +740,7 @@ declare module "bun:test" {
toBeNil(): void;
/**
* Asserts that a value is a `array`.
- *
+ *
* @link https://jest-extended.jestcommunity.dev/docs/matchers/array/#tobearray
* @example
* expect([1]).toBeArray();
@@ -750,9 +750,9 @@ declare module "bun:test" {
toBeArray(): void;
/**
* Asserts that a value is a `array` of a certain length.
- *
+ *
* @link https://jest-extended.jestcommunity.dev/docs/matchers/array/#tobearrayofsize
- * @example
+ * @example
* expect([]).toBeArrayOfSize(0);
* expect([1]).toBeArrayOfSize(1);
* expect(new Array(1)).toBeArrayOfSize(1);
@@ -780,14 +780,24 @@ declare module "bun:test" {
toBeTrue(): void;
/**
* Asserts that a value matches a specific type.
- *
+ *
* @link https://vitest.dev/api/expect.html#tobetypeof
* @example
* expect(1).toBeTypeOf("number");
* expect("hello").toBeTypeOf("string");
* expect([]).not.toBeTypeOf("boolean");
*/
- toBeTypeOf(type: 'bigint' | 'boolean' | 'function' | 'number' | 'object' | 'string' | 'symbol' | 'undefined'): void;
+ toBeTypeOf(
+ type:
+ | "bigint"
+ | "boolean"
+ | "function"
+ | "number"
+ | "object"
+ | "string"
+ | "symbol"
+ | "undefined",
+ ): void;
/**
* Asserts that a value is `false`.
*
@@ -1089,12 +1099,12 @@ declare namespace JestMock {
* List of the call order indexes of the mock. Jest is indexing the order of
* invocations of all mocks in a test file. The index is starting with `1`.
*/
- // invocationCallOrder: Array<number>;
+ 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>;
+ lastCall?: Parameters<T>;
/**
* List of the results of all calls that have been made to the mock.
*/
diff --git a/src/bun.js/bindings/JSBufferList.cpp b/src/bun.js/bindings/JSBufferList.cpp
index 409d50df6..a8cefa710 100644
--- a/src/bun.js/bindings/JSBufferList.cpp
+++ b/src/bun.js/bindings/JSBufferList.cpp
@@ -445,4 +445,4 @@ void JSBufferListConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject*
const ClassInfo JSBufferListConstructor::s_info = { "BufferList"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSBufferListConstructor) };
-} // namespace Zig \ No newline at end of file
+} // namespace Zig
diff --git a/src/bun.js/bindings/JSMockFunction.cpp b/src/bun.js/bindings/JSMockFunction.cpp
index fcd80102b..b7c2659b4 100644
--- a/src/bun.js/bindings/JSMockFunction.cpp
+++ b/src/bun.js/bindings/JSMockFunction.cpp
@@ -22,9 +22,31 @@
namespace Bun {
+/**
+ * intended to be used in an if statement as an abstraction over this double if statement
+ *
+ * if(jsValue) {
+ * if(auto value = jsDynamicCast(jsValue)) {
+ * ...
+ * }
+ * }
+ *
+ * the reason this is needed is because jsDynamicCast will segfault if given a zero JSValue
+ */
+template<typename To>
+inline To tryJSDynamicCast(JSValue from)
+{
+ if (UNLIKELY(!from))
+ return nullptr;
+ if (UNLIKELY(!from.isCell()))
+ return nullptr;
+ return jsDynamicCast<To>(from.asCell());
+}
+
JSC_DECLARE_HOST_FUNCTION(jsMockFunctionCall);
JSC_DECLARE_CUSTOM_GETTER(jsMockFunctionGetter_protoImpl);
JSC_DECLARE_CUSTOM_GETTER(jsMockFunctionGetter_mock);
+JSC_DECLARE_HOST_FUNCTION(jsMockFunctionGetter_mockGetLastCall);
JSC_DECLARE_HOST_FUNCTION(jsMockFunctionGetMockImplementation);
JSC_DECLARE_HOST_FUNCTION(jsMockFunctionGetMockName);
JSC_DECLARE_HOST_FUNCTION(jsMockFunctionMockClear);
@@ -40,8 +62,10 @@ JSC_DECLARE_HOST_FUNCTION(jsMockFunctionMockResolvedValue);
JSC_DECLARE_HOST_FUNCTION(jsMockFunctionMockResolvedValueOnce);
JSC_DECLARE_HOST_FUNCTION(jsMockFunctionMockRejectedValue);
JSC_DECLARE_HOST_FUNCTION(jsMockFunctionMockRejectedValueOnce);
+JSC_DECLARE_HOST_FUNCTION(jsMockFunctionWithImplementationCleanup);
JSC_DECLARE_HOST_FUNCTION(jsMockFunctionWithImplementation);
-JSC_DECLARE_HOST_FUNCTION(jsMockFunctionMockImplementationOnce);
+
+uint64_t JSMockModule::s_nextInvocationId = 0;
// This is taken from JSWeakSet
// We only want to hold onto the list of active spies which haven't already been collected
@@ -79,9 +103,7 @@ class JSMockImplementation final : public JSNonFinalObject {
public:
enum class Kind : uint8_t {
Call,
- Promise,
ReturnValue,
- ThrowValue,
ReturnThis,
};
@@ -112,7 +134,14 @@ public:
static constexpr unsigned numberOfInternalFields = 2;
- mutable JSC::WriteBarrier<Unknown> internalFields[2];
+ // either a function or a return value, depends on kind
+ mutable JSC::WriteBarrier<Unknown> underlyingValue;
+
+ // a combination of a pointer to the next implementation and a flag indicating if this is a once implementation
+ // - undefined - no next value
+ // - jsNumber(1) - no next value + is a once implementation
+ // - JSMockImplementation - next value + is a once implementation
+ mutable JSC::WriteBarrier<Unknown> nextValueOrSentinel;
DECLARE_EXPORT_INFO;
DECLARE_VISIT_CHILDREN;
@@ -121,11 +150,7 @@ public:
bool isOnce()
{
- auto secondField = internalFields[1].get();
- if (secondField.isNumber() && secondField.asInt32() == 1) {
- return true;
- }
- return jsDynamicCast<JSMockImplementation*>(secondField.asCell());
+ return !nextValueOrSentinel.get().isUndefined();
}
JSMockImplementation(JSC::VM& vm, JSC::Structure* structure, Kind kind)
@@ -137,8 +162,8 @@ public:
void finishCreation(JSC::VM& vm, JSC::JSValue first, JSC::JSValue second)
{
Base::finishCreation(vm);
- this->internalFields[0].set(vm, this, first);
- this->internalFields[1].set(vm, this, second);
+ this->underlyingValue.set(vm, this, first);
+ this->nextValueOrSentinel.set(vm, this, second);
}
};
@@ -149,32 +174,17 @@ void JSMockImplementation::visitChildrenImpl(JSCell* cell, Visitor& visitor)
ASSERT_GC_OBJECT_INHERITS(fn, info());
Base::visitChildren(fn, visitor);
- visitor.append(fn->internalFields[0]);
- visitor.append(fn->internalFields[1]);
+ visitor.append(fn->underlyingValue);
+ visitor.append(fn->nextValueOrSentinel);
}
DEFINE_VISIT_CHILDREN(JSMockImplementation);
enum class CallbackKind : uint8_t {
- Wrapper,
Call,
GetterSetter,
};
-static NativeFunction jsMockFunctionForCallbackKind(CallbackKind kind)
-{
- switch (kind) {
- // return jsMockFunctionGetterSetter;
- case CallbackKind::Wrapper:
- return jsMockFunctionMockImplementation;
- case CallbackKind::GetterSetter:
- case CallbackKind::Call:
- return jsMockFunctionCall;
- default:
- RELEASE_ASSERT_NOT_REACHED();
- }
-}
-
const ClassInfo JSMockImplementation::s_info = { "MockImpl"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSMockImplementation) };
class JSMockFunction : public JSC::InternalFunction {
@@ -197,12 +207,20 @@ public:
DECLARE_VISIT_CHILDREN;
JSC::LazyProperty<JSMockFunction, JSObject> mock;
+ // three pointers to implementation objects
+ // head of the list, this one is run next
mutable JSC::WriteBarrier<JSC::Unknown> implementation;
+ // this contains the non-once implementation. there is only ever one of these
+ mutable JSC::WriteBarrier<JSC::Unknown> fallbackImplmentation;
+ // the last once implementation
+ mutable JSC::WriteBarrier<JSC::Unknown> tail;
+ // original implementation from spy. separate from `implementation` so restoration always works
+ mutable JSC::WriteBarrier<JSC::Unknown> spyOriginal;
mutable JSC::WriteBarrier<JSC::JSArray> calls;
mutable JSC::WriteBarrier<JSC::JSArray> contexts;
+ mutable JSC::WriteBarrier<JSC::JSArray> invocationCallOrder;
mutable JSC::WriteBarrier<JSC::JSArray> instances;
mutable JSC::WriteBarrier<JSC::JSArray> returnValues;
- mutable JSC::WriteBarrier<JSC::Unknown> tail;
JSC::Weak<JSObject> spyTarget;
JSC::Identifier spyIdentifier;
@@ -214,6 +232,28 @@ public:
this->putDirect(vm, vm.propertyNames->name, jsString(vm, name), JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::ReadOnly);
}
+ void copyNameAndLength(JSC::VM& vm, JSGlobalObject* global, JSC::JSValue value)
+ {
+ auto catcher = DECLARE_CATCH_SCOPE(vm);
+ WTF::String nameToUse;
+ if (auto* fn = jsDynamicCast<JSFunction*>(value)) {
+ nameToUse = fn->name(vm);
+ JSValue lengthJSValue = fn->get(global, vm.propertyNames->length);
+ if (lengthJSValue.isNumber()) {
+ this->putDirect(vm, vm.propertyNames->length, (lengthJSValue), JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::ReadOnly);
+ }
+ } else if (auto* fn = jsDynamicCast<InternalFunction*>(value)) {
+ nameToUse = fn->name();
+ } else {
+ nameToUse = "mockConstructor"_s;
+ }
+ this->setName(nameToUse);
+
+ if (catcher.exception()) {
+ catcher.clearException();
+ }
+ }
+
void initMock()
{
mock.initLater(
@@ -226,11 +266,12 @@ public:
object->putDirectOffset(init.vm, 1, mock->getContexts());
object->putDirectOffset(init.vm, 2, mock->getInstances());
object->putDirectOffset(init.vm, 3, mock->getReturnValues());
+ object->putDirectOffset(init.vm, 4, mock->getInvocationCallOrder());
init.set(object);
});
}
- void reset()
+ void clear()
{
this->calls.clear();
this->instances.clear();
@@ -242,12 +283,22 @@ public:
}
}
+ void reset()
+ {
+ this->clear();
+ this->implementation.clear();
+ this->fallbackImplmentation.clear();
+ this->tail.clear();
+ }
+
void clearSpy()
{
+ this->reset();
+
if (auto* target = this->spyTarget.get()) {
- JSValue implValue = jsUndefined();
- if (auto* impl = jsDynamicCast<JSMockImplementation*>(this->implementation.get())) {
- implValue = impl->internalFields[0].get();
+ JSValue implValue = this->spyOriginal.get();
+ if (!implValue) {
+ implValue = jsUndefined();
}
// Reset the spy back to the original value.
@@ -295,6 +346,15 @@ public:
}
return val;
}
+ JSArray* getInvocationCallOrder() const
+ {
+ JSArray* val = invocationCallOrder.get();
+ if (!val) {
+ val = JSC::constructEmptyArray(globalObject(), nullptr, 0);
+ this->invocationCallOrder.set(vm(), this, val);
+ }
+ return val;
+ }
template<typename, JSC::SubspaceAccess mode>
static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
@@ -310,7 +370,7 @@ public:
}
JSMockFunction(JSC::VM& vm, JSC::Structure* structure, CallbackKind wrapKind)
- : Base(vm, structure, jsMockFunctionForCallbackKind(wrapKind), jsMockFunctionForCallbackKind(wrapKind))
+ : Base(vm, structure, jsMockFunctionCall, jsMockFunctionCall)
{
initMock();
}
@@ -324,41 +384,56 @@ void JSMockFunction::visitChildrenImpl(JSCell* cell, Visitor& visitor)
Base::visitChildren(fn, visitor);
visitor.append(fn->implementation);
+ visitor.append(fn->tail);
+ visitor.append(fn->fallbackImplmentation);
visitor.append(fn->calls);
visitor.append(fn->contexts);
visitor.append(fn->instances);
visitor.append(fn->returnValues);
- visitor.append(fn->tail);
+ visitor.append(fn->invocationCallOrder);
fn->mock.visit(visitor);
}
DEFINE_VISIT_CHILDREN(JSMockFunction);
-static void pushImplInternal(JSMockFunction* fn, JSGlobalObject* jsGlobalObject, JSMockImplementation::Kind kind, JSValue value, bool isOnce)
+static void pushImpl(JSMockFunction* fn, JSGlobalObject* jsGlobalObject, JSMockImplementation::Kind kind, JSValue value)
{
Zig::GlobalObject* globalObject = jsCast<Zig::GlobalObject*>(jsGlobalObject);
auto& vm = globalObject->vm();
- JSMockImplementation* impl = JSMockImplementation::create(globalObject, globalObject->mockModule.mockImplementationStructure.getInitializedOnMainThread(globalObject), kind, value, isOnce);
- JSValue currentTail = fn->tail.get();
- JSValue currentImpl = fn->implementation.get();
- if (currentTail) {
- if (auto* current = jsDynamicCast<JSMockImplementation*>(currentTail)) {
- current->internalFields[1].set(vm, current, impl);
- }
+
+ if (auto* current = tryJSDynamicCast<JSMockImplementation*>(fn->fallbackImplmentation.get())) {
+ current->underlyingValue.set(vm, current, value);
+ current->kind = kind;
+ return;
}
- fn->tail.set(vm, fn, impl);
- if (!currentImpl || !currentImpl.inherits<JSMockImplementation>()) {
+
+ JSMockImplementation* impl = JSMockImplementation::create(globalObject, globalObject->mockModule.mockImplementationStructure.getInitializedOnMainThread(globalObject), kind, value, false);
+ fn->fallbackImplmentation.set(vm, fn, impl);
+ if (auto* tail = tryJSDynamicCast<JSMockImplementation*>(fn->tail.get())) {
+ tail->nextValueOrSentinel.set(vm, tail, impl);
+ } else {
fn->implementation.set(vm, fn, impl);
}
}
-static void pushImpl(JSMockFunction* fn, JSGlobalObject* globalObject, JSMockImplementation::Kind kind, JSValue value)
+static void pushImplOnce(JSMockFunction* fn, JSGlobalObject* jsGlobalObject, JSMockImplementation::Kind kind, JSValue value)
{
- pushImplInternal(fn, globalObject, kind, value, false);
-}
+ Zig::GlobalObject* globalObject = jsCast<Zig::GlobalObject*>(jsGlobalObject);
+ auto& vm = globalObject->vm();
-static void pushImplOnce(JSMockFunction* fn, JSGlobalObject* globalObject, JSMockImplementation::Kind kind, JSValue value)
-{
- pushImplInternal(fn, globalObject, kind, value, true);
+ JSMockImplementation* impl = JSMockImplementation::create(globalObject, globalObject->mockModule.mockImplementationStructure.getInitializedOnMainThread(globalObject), kind, value, true);
+
+ if (!fn->implementation.get()) {
+ fn->implementation.set(vm, fn, impl);
+ }
+ if (auto* tail = tryJSDynamicCast<JSMockImplementation*>(fn->tail.get())) {
+ tail->nextValueOrSentinel.set(vm, tail, impl);
+ } else {
+ fn->implementation.set(vm, fn, impl);
+ }
+ if (auto fallback = fn->fallbackImplmentation.get()) {
+ impl->nextValueOrSentinel.set(vm, impl, fallback);
+ }
+ fn->tail.set(vm, fn, impl);
}
class JSMockFunctionPrototype final : public JSC::JSNonFinalObject {
@@ -409,8 +484,8 @@ static const HashTableValue JSMockFunctionPrototypeTableValues[] = {
{ "mockReturnValueOnce"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), NoIntrinsic, { HashTableValue::NativeFunctionType, jsMockFunctionMockReturnValueOnce, 1 } },
{ "mockResolvedValue"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), NoIntrinsic, { HashTableValue::NativeFunctionType, jsMockFunctionMockResolvedValue, 1 } },
{ "mockResolvedValueOnce"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), NoIntrinsic, { HashTableValue::NativeFunctionType, jsMockFunctionMockResolvedValueOnce, 1 } },
- { "mockRejectedValueOnce"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), NoIntrinsic, { HashTableValue::NativeFunctionType, jsMockFunctionMockRejectedValue, 1 } },
- { "mockRejectedValue"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), NoIntrinsic, { HashTableValue::NativeFunctionType, jsMockFunctionMockRejectedValueOnce, 1 } },
+ { "mockRejectedValue"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), NoIntrinsic, { HashTableValue::NativeFunctionType, jsMockFunctionMockRejectedValue, 1 } },
+ { "mockRejectedValueOnce"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), NoIntrinsic, { HashTableValue::NativeFunctionType, jsMockFunctionMockRejectedValueOnce, 1 } },
};
const ClassInfo JSMockFunction::s_info = { "Mock"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSMockFunction) };
@@ -446,7 +521,6 @@ extern "C" void JSMock__resetSpies(Zig::GlobalObject* globalObject)
continue;
auto* spyObject = jsCast<JSMockFunction*>(spy);
- spyObject->reset();
spyObject->clearSpy();
}
globalObject->mockModule.activeSpies.clear();
@@ -508,20 +582,7 @@ extern "C" EncodedJSValue JSMock__spyOn(JSC::JSGlobalObject* lexicalGlobalObject
if (hasValue)
attributes = slot.attributes();
- {
- auto catcher = DECLARE_CATCH_SCOPE(vm);
- WTF::String nameToUse;
- if (auto* fn = jsDynamicCast<JSFunction*>(value)) {
- nameToUse = fn->name(vm);
- } else if (auto* fn = jsDynamicCast<InternalFunction*>(value)) {
- nameToUse = fn->name();
- }
- if (nameToUse.length()) {
- mock->setName(nameToUse);
- }
- if (catcher.exception())
- catcher.clearException();
- }
+ mock->copyNameAndLength(vm, globalObject, value);
attributes |= PropertyAttribute::Function;
object->putDirect(vm, propertyKey, mock, attributes);
@@ -534,11 +595,14 @@ extern "C" EncodedJSValue JSMock__spyOn(JSC::JSGlobalObject* lexicalGlobalObject
attributes |= PropertyAttribute::Accessor;
object->putDirect(vm, propertyKey, JSC::GetterSetter::create(vm, globalObject, mock, mock), attributes);
+ // mock->setName(propertyKey.publicName());
RETURN_IF_EXCEPTION(scope, {});
pushImpl(mock, globalObject, JSMockImplementation::Kind::ReturnValue, value);
}
+ mock->spyOriginal.set(vm, mock, value);
+
if (!globalObject->mockModule.activeSpies) {
ActiveSpySet* activeSpies = ActiveSpySet::create(vm, globalObject->mockModule.activeSpySetStructure.getInitializedOnMainThread(globalObject));
globalObject->mockModule.activeSpies.set(vm, activeSpies);
@@ -561,7 +625,6 @@ JSMockModule JSMockModule::create(JSC::JSGlobalObject* globalObject)
mock.mockFunctionStructure.initLater(
[](const JSC::LazyProperty<JSC::JSGlobalObject, JSC::Structure>::Initializer& init) {
auto* prototype = JSMockFunctionPrototype::create(init.vm, init.owner, JSMockFunctionPrototype::createStructure(init.vm, init.owner, init.owner->functionPrototype()));
-
init.set(JSMockFunction::createStructure(init.vm, init.owner, prototype));
});
mock.mockResultStructure.initLater(
@@ -602,10 +665,25 @@ JSMockModule JSMockModule::create(JSC::JSGlobalObject* globalObject)
mock.mockObjectStructure.initLater(
[](const JSC::LazyProperty<JSC::JSGlobalObject, JSC::Structure>::Initializer& init) {
Zig::GlobalObject* globalObject = jsCast<Zig::GlobalObject*>(init.owner);
- JSC::Structure* structure = globalObject->structureCache().emptyObjectStructureForPrototype(
+
+ auto* prototype = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype());
+ // `putDirectCustomAccessor` doesn't pass the `this` value as expected. unfortunatly we
+ // need to use a JSFunction for the getter and assign it via `putDirectAccessor` instead.
+ prototype->putDirectAccessor(
globalObject,
- globalObject->objectPrototype(),
- 4);
+ JSC::Identifier::fromString(init.vm, "lastCall"_s),
+ JSC::GetterSetter::create(
+ init.vm,
+ globalObject,
+ JSC::JSFunction::create(init.vm, init.owner, 0, "lastCall"_s, jsMockFunctionGetter_mockGetLastCall, ImplementationVisibility::Public),
+ jsUndefined()),
+ JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly);
+
+ JSC::Structure* structure
+ = globalObject->structureCache().emptyObjectStructureForPrototype(
+ globalObject,
+ prototype,
+ 5);
JSC::PropertyOffset offset;
structure = structure->addPropertyTransition(
init.vm,
@@ -631,9 +709,23 @@ 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, "invocationCallOrder"_s),
+ JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly,
+ offset);
init.set(structure);
});
+ mock.withImplementationCleanupFunction.initLater(
+ [](const JSC::LazyProperty<JSC::JSGlobalObject, JSC::JSFunction>::Initializer& init) {
+ init.set(JSC::JSFunction::create(init.vm, init.owner, 2, String(), jsMockFunctionWithImplementationCleanup, ImplementationVisibility::Public));
+ });
+ mock.mockWithImplementationCleanupDataStructure.initLater(
+ [](const JSC::LazyProperty<JSC::JSGlobalObject, Structure>::Initializer& init) {
+ init.set(Bun::MockWithImplementationCleanupData::createStructure(init.vm, init.owner, init.owner->objectPrototype()));
+ });
return mock;
}
@@ -705,8 +797,8 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionCall, (JSGlobalObject * lexicalGlobalObje
globalObject->arrayStructureForIndexingTypeDuringAllocation(JSC::ArrayWithContiguous),
1);
calls->initializeIndex(object, 0, argumentsArray);
+ fn->calls.set(vm, fn, calls);
}
- fn->calls.set(vm, fn, calls);
JSC::JSArray* contexts = fn->contexts.get();
if (contexts) {
@@ -718,39 +810,51 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionCall, (JSGlobalObject * lexicalGlobalObje
globalObject->arrayStructureForIndexingTypeDuringAllocation(JSC::ArrayWithContiguous),
1);
contexts->initializeIndex(object, 0, thisValue);
+ fn->contexts.set(vm, fn, contexts);
}
- fn->contexts.set(vm, fn, contexts);
- JSValue implementationValue = fn->implementation.get();
- if (!implementationValue)
- implementationValue = jsUndefined();
+ auto invocationId = JSMockModule::nextInvocationId();
+ JSC::JSArray* invocationCallOrder = fn->invocationCallOrder.get();
+ if (invocationCallOrder) {
+ invocationCallOrder->push(globalObject, jsNumber(invocationId));
+ } else {
+ JSC::ObjectInitializationScope object(vm);
+ invocationCallOrder = JSC::JSArray::tryCreateUninitializedRestricted(
+ object,
+ globalObject->arrayStructureForIndexingTypeDuringAllocation(JSC::ArrayWithContiguous),
+ 1);
+ invocationCallOrder->initializeIndex(object, 0, jsNumber(invocationId));
+ fn->invocationCallOrder.set(vm, fn, invocationCallOrder);
+ }
- if (auto* impl = jsDynamicCast<JSMockImplementation*>(implementationValue)) {
- if (JSValue nextValue = impl->internalFields[1].get()) {
- if (nextValue.inherits<JSMockImplementation>() || (nextValue.isInt32() && nextValue.asInt32() == 1)) {
- fn->implementation.set(vm, fn, nextValue);
- }
+ unsigned int returnValueIndex = 0;
+ auto setReturnValue = [&](JSC::JSValue value) -> void {
+ if (auto* returnValuesArray = fn->returnValues.get()) {
+ returnValuesArray->push(globalObject, value);
+ returnValueIndex = returnValuesArray->length() - 1;
+ } else {
+ JSC::ObjectInitializationScope object(vm);
+ returnValuesArray = JSC::JSArray::tryCreateUninitializedRestricted(
+ object,
+ globalObject->arrayStructureForIndexingTypeDuringAllocation(JSC::ArrayWithContiguous),
+ 1);
+ returnValuesArray->initializeIndex(object, 0, value);
+ fn->returnValues.set(vm, fn, returnValuesArray);
}
+ };
- unsigned int returnValueIndex = 0;
- auto setReturnValue = [&](JSC::JSValue value) -> void {
- if (auto* returnValuesArray = fn->returnValues.get()) {
- returnValuesArray->push(globalObject, value);
- returnValueIndex = returnValuesArray->length() - 1;
- } else {
- JSC::ObjectInitializationScope object(vm);
- returnValuesArray = JSC::JSArray::tryCreateUninitializedRestricted(
- object,
- globalObject->arrayStructureForIndexingTypeDuringAllocation(JSC::ArrayWithContiguous),
- 1);
- returnValuesArray->initializeIndex(object, 0, value);
- fn->returnValues.set(vm, fn, returnValuesArray);
+ if (auto* impl = tryJSDynamicCast<JSMockImplementation*>(fn->implementation.get())) {
+ if (impl->isOnce()) {
+ auto next = impl->nextValueOrSentinel.get();
+ fn->implementation.set(vm, fn, next);
+ if (next.isNumber() || !jsDynamicCast<JSMockImplementation*>(next)->isOnce()) {
+ fn->tail.clear();
}
- };
+ }
switch (impl->kind) {
case JSMockImplementation::Kind::Call: {
- JSValue result = impl->internalFields[0].get();
+ JSValue result = impl->underlyingValue.get();
JSC::CallData callData = JSC::getCallData(result);
if (UNLIKELY(callData.type == JSC::CallData::Type::None)) {
throwTypeError(globalObject, scope, "Expected mock implementation to be callable"_s);
@@ -783,9 +887,8 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionCall, (JSGlobalObject * lexicalGlobalObje
return JSValue::encode(returnValue);
}
- case JSMockImplementation::Kind::ReturnValue:
- case JSMockImplementation::Kind::Promise: {
- JSValue returnValue = impl->internalFields[0].get();
+ case JSMockImplementation::Kind::ReturnValue: {
+ JSValue returnValue = impl->underlyingValue.get();
setReturnValue(createMockResult(vm, globalObject, "return"_s, returnValue));
return JSValue::encode(returnValue);
}
@@ -799,6 +902,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionCall, (JSGlobalObject * lexicalGlobalObje
}
}
+ setReturnValue(createMockResult(vm, globalObject, "return"_s, jsUndefined()));
return JSValue::encode(jsUndefined());
}
@@ -820,10 +924,9 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionGetMockImplementation, (JSC::JSGlobalObje
throwTypeError(globalObject, scope, "Expected Mock"_s);
}
- JSValue impl = thisObject->implementation.get();
- if (auto* implementation = jsDynamicCast<JSMockImplementation*>(impl)) {
+ if (auto* implementation = tryJSDynamicCast<JSMockImplementation*>(thisObject->implementation.get())) {
if (implementation->kind == JSMockImplementation::Kind::Call) {
- RELEASE_AND_RETURN(scope, JSValue::encode(implementation->internalFields[0].get()));
+ RELEASE_AND_RETURN(scope, JSValue::encode(implementation->underlyingValue.get()));
}
}
@@ -851,41 +954,59 @@ JSC_DEFINE_CUSTOM_GETTER(jsMockFunctionGetter_protoImpl, (JSC::JSGlobalObject *
return {};
}
- if (auto implValue = thisObject->implementation.get()) {
- if (auto* impl = jsDynamicCast<JSMockImplementation*>(implValue)) {
- if (impl->kind == JSMockImplementation::Kind::Call) {
- return JSValue::encode(impl->internalFields[0].get());
- }
-
- return JSValue::encode(jsUndefined());
+ if (auto* impl = tryJSDynamicCast<JSMockImplementation*>(thisObject->implementation.get())) {
+ if (impl->kind == JSMockImplementation::Kind::Call) {
+ return JSValue::encode(impl->underlyingValue.get());
}
}
return JSValue::encode(jsUndefined());
}
-#define HANDLE_STATIC_CALL \
- if (!thisObject->implementation.get()) { \
- thisObject = JSMockFunction::create( \
- vm, \
- globalObject, \
- reinterpret_cast<Zig::GlobalObject*>(globalObject)->mockModule.mockFunctionStructure.getInitializedOnMainThread(globalObject), \
- CallbackKind::Call); \
+JSC_DEFINE_HOST_FUNCTION(jsMockFunctionConstructor, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callframe))
+{
+ auto& vm = lexicalGlobalObject->vm();
+ auto* globalObject = jsCast<Zig::GlobalObject*>(lexicalGlobalObject);
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ auto thisObject_ = callframe->thisValue().toThis(globalObject, JSC::ECMAMode::strict());
+ JSMockFunction* thisObject = JSMockFunction::create(
+ vm,
+ globalObject,
+ globalObject->mockModule.mockFunctionStructure.getInitializedOnMainThread(globalObject));
+
+ if (UNLIKELY(!thisObject)) {
+ throwOutOfMemoryError(globalObject, scope);
+ return {};
+ }
+
+ if (callframe->argumentCount() > 0) {
+ JSValue value = callframe->argument(0);
+ if (value.isCallable()) {
+ thisObject->copyNameAndLength(vm, lexicalGlobalObject, value);
+ pushImpl(thisObject, globalObject, JSMockImplementation::Kind::Call, value);
+ } else {
+ // jest doesn't support doing `jest.fn(10)`, but we support it.
+ pushImpl(thisObject, globalObject, JSMockImplementation::Kind::ReturnValue, value);
+ thisObject->setName("mockConstructor"_s);
+ }
+ } else {
+ thisObject->setName("mockConstructor"_s);
}
+ return JSValue::encode(thisObject);
+}
+
extern "C" EncodedJSValue JSMockFunction__createObject(Zig::GlobalObject* globalObject)
{
- return JSValue::encode(
- JSMockFunction::create(globalObject->vm(), globalObject, globalObject->mockModule.mockFunctionStructure.getInitializedOnMainThread(globalObject), CallbackKind::Wrapper));
+ 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);
- if (value) {
- if (auto* mock = jsDynamicCast<JSMockFunction*>(value)) {
- return JSValue::encode(mock->getCalls());
- }
+ if (auto* mock = tryJSDynamicCast<JSMockFunction*>(value)) {
+ return JSValue::encode(mock->getCalls());
}
return JSValue::encode({});
@@ -893,10 +1014,8 @@ extern "C" EncodedJSValue JSMockFunction__getCalls(EncodedJSValue encodedValue)
extern "C" EncodedJSValue JSMockFunction__getReturns(EncodedJSValue encodedValue)
{
JSValue value = JSValue::decode(encodedValue);
- if (value) {
- if (auto* mock = jsDynamicCast<JSMockFunction*>(value)) {
- return JSValue::encode(mock->getReturnValues());
- }
+ if (auto* mock = tryJSDynamicCast<JSMockFunction*>(value)) {
+ return JSValue::encode(mock->getReturnValues());
}
return JSValue::encode({});
@@ -911,19 +1030,16 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionGetMockName, (JSC::JSGlobalObject * globa
throwTypeError(globalObject, scope, "Expected Mock"_s);
}
- JSValue implValue = thisObject->implementation.get();
- if (!implValue) {
- implValue = jsUndefined();
- }
-
- if (auto* impl = jsDynamicCast<JSMockImplementation*>(implValue)) {
+ if (auto* impl = tryJSDynamicCast<JSMockImplementation*>(thisObject->implementation.get())) {
if (impl->kind == JSMockImplementation::Kind::Call) {
- JSObject* object = impl->internalFields[0].get().asCell()->getObject();
- if (auto nameValue = object->getIfPropertyExists(globalObject, PropertyName(vm.propertyNames->name))) {
- RELEASE_AND_RETURN(scope, JSValue::encode(nameValue));
- }
+ if (JSValue underlyingValue = impl->underlyingValue.get()) {
+ JSObject* object = underlyingValue.asCell()->getObject();
+ if (auto nameValue = object->getIfPropertyExists(globalObject, PropertyName(vm.propertyNames->name))) {
+ RELEASE_AND_RETURN(scope, JSValue::encode(nameValue));
+ }
- RETURN_IF_EXCEPTION(scope, {});
+ RETURN_IF_EXCEPTION(scope, {});
+ }
}
}
@@ -938,7 +1054,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockClear, (JSC::JSGlobalObject * globalO
throwTypeError(globalObject, scope, "Expected Mock"_s);
}
- thisObject->reset();
+ thisObject->clear();
RELEASE_AND_RETURN(scope, JSValue::encode(thisObject));
}
@@ -964,6 +1080,8 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockRestore, (JSC::JSGlobalObject * globa
throwTypeError(globalObject, scope, "Expected Mock"_s);
}
+ thisObject->clearSpy();
+
RELEASE_AND_RETURN(scope, JSValue::encode(thisObject));
}
JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockImplementation, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callframe))
@@ -971,37 +1089,20 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockImplementation, (JSC::JSGlobalObject
auto& vm = lexicalGlobalObject->vm();
auto* globalObject = jsCast<Zig::GlobalObject*>(lexicalGlobalObject);
auto scope = DECLARE_THROW_SCOPE(vm);
- JSMockFunction* thisObject = JSMockFunction::create(
- vm,
- globalObject,
- globalObject->mockModule.mockFunctionStructure.getInitializedOnMainThread(globalObject));
+ JSMockFunction* thisObject = jsDynamicCast<JSMockFunction*>(callframe->thisValue().toThis(globalObject, JSC::ECMAMode::strict()));
if (UNLIKELY(!thisObject)) {
throwOutOfMemoryError(globalObject, scope);
return {};
}
- if (callframe->argumentCount() > 0) {
- JSValue value = callframe->argument(0);
- if (value.isCallable()) {
- {
- auto catcher = DECLARE_CATCH_SCOPE(vm);
- WTF::String nameToUse;
- if (auto* fn = jsDynamicCast<JSFunction*>(value)) {
- nameToUse = fn->name(vm);
- } else if (auto* fn = jsDynamicCast<InternalFunction*>(value)) {
- nameToUse = fn->name();
- }
- if (nameToUse.length()) {
- thisObject->setName(nameToUse);
- }
- if (catcher.exception())
- catcher.clearException();
- }
- pushImpl(thisObject, globalObject, JSMockImplementation::Kind::Call, value);
- } else {
- pushImpl(thisObject, globalObject, JSMockImplementation::Kind::ReturnValue, value);
- }
+ JSValue value = callframe->argument(0);
+
+ // This check is for a jest edge case, truthy values will throw but not immediatly, and falsy values return undefined.
+ if (value.toBoolean(globalObject)) {
+ pushImpl(thisObject, globalObject, JSMockImplementation::Kind::Call, value);
+ } else {
+ pushImpl(thisObject, globalObject, JSMockImplementation::Kind::ReturnValue, jsUndefined());
}
return JSValue::encode(thisObject);
@@ -1018,59 +1119,16 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockImplementationOnce, (JSC::JSGlobalObj
return {};
}
- HANDLE_STATIC_CALL;
-
- if (callframe->argumentCount() > 0) {
- JSValue value = callframe->argument(0);
- if (value.isCallable()) {
- if (!thisObject->implementation) {
- auto catcher = DECLARE_CATCH_SCOPE(vm);
- WTF::String nameToUse;
- if (auto* fn = jsDynamicCast<JSFunction*>(value)) {
- nameToUse = fn->name(vm);
- } else if (auto* fn = jsDynamicCast<InternalFunction*>(value)) {
- nameToUse = fn->name();
- }
- if (nameToUse.length()) {
- thisObject->setName(nameToUse);
- }
- if (catcher.exception())
- catcher.clearException();
- }
-
- pushImpl(thisObject, globalObject, JSMockImplementation::Kind::Call, value);
- } else {
- pushImpl(thisObject, globalObject, JSMockImplementation::Kind::ReturnValue, value);
- }
- }
-
- return JSValue::encode(thisObject);
-}
-
-JSC_DEFINE_HOST_FUNCTION(jsMockFunctionWithImplementation, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe))
-{
- JSMockFunction* thisObject = jsDynamicCast<JSMockFunction*>(callframe->thisValue().toThis(globalObject, JSC::ECMAMode::strict()));
- auto& vm = globalObject->vm();
- auto scope = DECLARE_THROW_SCOPE(vm);
- if (UNLIKELY(!thisObject)) {
- throwTypeError(globalObject, scope, "Expected Mock"_s);
- RELEASE_AND_RETURN(scope, JSValue::encode(jsUndefined()));
- }
-
- HANDLE_STATIC_CALL;
-
- JSValue arg = callframe->argument(0);
+ JSValue value = callframe->argument(0);
- if (callframe->argumentCount() < 1 || arg.isEmpty() || arg.isUndefined()) {
- pushImpl(thisObject, globalObject, JSMockImplementation::Kind::ReturnValue, jsUndefined());
- } else if (arg.isCallable()) {
- pushImpl(thisObject, globalObject, JSMockImplementation::Kind::Call, arg);
+ // This check is for a jest edge case, truthy values will throw but not immediatly, and falsy values return undefined.
+ if (value.toBoolean(globalObject)) {
+ pushImplOnce(thisObject, globalObject, JSMockImplementation::Kind::Call, value);
} else {
- throwTypeError(globalObject, scope, "Expected a function or undefined"_s);
- RELEASE_AND_RETURN(scope, JSValue::encode(jsUndefined()));
+ pushImplOnce(thisObject, globalObject, JSMockImplementation::Kind::ReturnValue, jsUndefined());
}
- RELEASE_AND_RETURN(scope, JSValue::encode(thisObject));
+ return JSValue::encode(thisObject);
}
JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockName, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe))
{
@@ -1082,8 +1140,6 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockName, (JSC::JSGlobalObject * globalOb
return {};
}
- HANDLE_STATIC_CALL;
-
if (callframe->argumentCount() > 0) {
auto* newName = callframe->argument(0).toStringOrNull(globalObject);
if (UNLIKELY(!newName)) {
@@ -1105,7 +1161,6 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockReturnThis, (JSC::JSGlobalObject * gl
throwTypeError(globalObject, scope, "Expected Mock"_s);
}
- HANDLE_STATIC_CALL;
pushImpl(thisObject, globalObject, JSMockImplementation::Kind::ReturnThis, jsUndefined());
RELEASE_AND_RETURN(scope, JSValue::encode(thisObject));
@@ -1117,13 +1172,10 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockReturnValue, (JSC::JSGlobalObject * g
auto scope = DECLARE_THROW_SCOPE(vm);
if (UNLIKELY(!thisObject)) {
throwTypeError(globalObject, scope, "Expected Mock"_s);
+ return {};
}
- if (callframe->argumentCount() < 1) {
- pushImpl(thisObject, globalObject, JSMockImplementation::Kind::ReturnValue, jsUndefined());
- } else {
- pushImpl(thisObject, globalObject, JSMockImplementation::Kind::ReturnValue, callframe->argument(0));
- }
+ pushImpl(thisObject, globalObject, JSMockImplementation::Kind::ReturnValue, callframe->argument(0));
RELEASE_AND_RETURN(scope, JSValue::encode(thisObject));
}
@@ -1134,35 +1186,24 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockReturnValueOnce, (JSC::JSGlobalObject
auto scope = DECLARE_THROW_SCOPE(vm);
if (UNLIKELY(!thisObject)) {
throwTypeError(globalObject, scope, "Expected Mock"_s);
+ return {};
}
- HANDLE_STATIC_CALL;
- if (callframe->argumentCount() < 1) {
- pushImplOnce(thisObject, globalObject, JSMockImplementation::Kind::ReturnValue, jsUndefined());
- } else {
- pushImplOnce(thisObject, globalObject, JSMockImplementation::Kind::ReturnValue, callframe->argument(0));
- }
+ pushImplOnce(thisObject, globalObject, JSMockImplementation::Kind::ReturnValue, callframe->argument(0));
RELEASE_AND_RETURN(scope, JSValue::encode(thisObject));
}
-JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockResolvedValue, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callframe))
+JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockResolvedValue, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe))
{
- auto* globalObject = jsCast<Zig::GlobalObject*>(lexicalGlobalObject);
JSMockFunction* thisObject = jsDynamicCast<JSMockFunction*>(callframe->thisValue().toThis(globalObject, JSC::ECMAMode::strict()));
auto& vm = globalObject->vm();
-
auto scope = DECLARE_THROW_SCOPE(vm);
if (UNLIKELY(!thisObject)) {
throwTypeError(globalObject, scope, "Expected Mock"_s);
+ return {};
}
- HANDLE_STATIC_CALL;
-
- if (callframe->argumentCount() < 1) {
- pushImpl(thisObject, globalObject, JSMockImplementation::Kind::Promise, JSC::JSPromise::resolvedPromise(globalObject, jsUndefined()));
- } else {
- pushImpl(thisObject, globalObject, JSMockImplementation::Kind::Promise, JSC::JSPromise::resolvedPromise(globalObject, callframe->argument(0)));
- }
+ pushImpl(thisObject, globalObject, JSMockImplementation::Kind::ReturnValue, JSC::JSPromise::resolvedPromise(globalObject, callframe->argument(0)));
RELEASE_AND_RETURN(scope, JSValue::encode(thisObject));
}
@@ -1173,15 +1214,10 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockResolvedValueOnce, (JSC::JSGlobalObje
auto scope = DECLARE_THROW_SCOPE(vm);
if (UNLIKELY(!thisObject)) {
throwTypeError(globalObject, scope, "Expected Mock"_s);
+ return {};
}
- HANDLE_STATIC_CALL;
-
- if (callframe->argumentCount() < 1) {
- pushImplOnce(thisObject, globalObject, JSMockImplementation::Kind::Promise, JSC::JSPromise::resolvedPromise(globalObject, jsUndefined()));
- } else {
- pushImplOnce(thisObject, globalObject, JSMockImplementation::Kind::Promise, JSC::JSPromise::resolvedPromise(globalObject, callframe->argument(0)));
- }
+ pushImplOnce(thisObject, globalObject, JSMockImplementation::Kind::ReturnValue, JSC::JSPromise::resolvedPromise(globalObject, callframe->argument(0)));
RELEASE_AND_RETURN(scope, JSValue::encode(thisObject));
}
@@ -1192,15 +1228,10 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockRejectedValue, (JSC::JSGlobalObject *
auto scope = DECLARE_THROW_SCOPE(vm);
if (UNLIKELY(!thisObject)) {
throwTypeError(globalObject, scope, "Expected Mock"_s);
+ return {};
}
- HANDLE_STATIC_CALL;
-
- if (callframe->argumentCount() < 1) {
- pushImpl(thisObject, globalObject, JSMockImplementation::Kind::Promise, JSC::JSPromise::rejectedPromise(globalObject, jsUndefined()));
- } else {
- pushImpl(thisObject, globalObject, JSMockImplementation::Kind::Promise, JSC::JSPromise::rejectedPromise(globalObject, callframe->argument(0)));
- }
+ pushImpl(thisObject, globalObject, JSMockImplementation::Kind::ReturnValue, JSC::JSPromise::rejectedPromise(globalObject, callframe->argument(0)));
RELEASE_AND_RETURN(scope, JSValue::encode(thisObject));
}
@@ -1211,16 +1242,178 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockRejectedValueOnce, (JSC::JSGlobalObje
auto scope = DECLARE_THROW_SCOPE(vm);
if (UNLIKELY(!thisObject)) {
throwTypeError(globalObject, scope, "Expected Mock"_s);
+ return {};
}
- HANDLE_STATIC_CALL;
+ pushImplOnce(thisObject, globalObject, JSMockImplementation::Kind::ReturnValue, JSC::JSPromise::rejectedPromise(globalObject, callframe->argument(0)));
- if (callframe->argumentCount() < 1) {
- pushImplOnce(thisObject, globalObject, JSMockImplementation::Kind::Promise, JSC::JSPromise::rejectedPromise(globalObject, jsUndefined()));
- } else {
- pushImplOnce(thisObject, globalObject, JSMockImplementation::Kind::Promise, JSC::JSPromise::resolvedPromise(globalObject, callframe->argument(0)));
+ RELEASE_AND_RETURN(scope, JSValue::encode(thisObject));
+}
+JSC_DEFINE_HOST_FUNCTION(jsMockFunctionGetter_mockGetLastCall, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe))
+{
+ JSValue thisObject = callframe->thisValue();
+ if (UNLIKELY(!thisObject.isObject())) {
+ return JSValue::encode(jsUndefined());
}
+ JSValue callsValue = thisObject.get(globalObject, Identifier::fromString(globalObject->vm(), "calls"_s));
- RELEASE_AND_RETURN(scope, JSValue::encode(thisObject));
+ if (auto callsArray = jsDynamicCast<JSC::JSArray*>(callsValue)) {
+ auto len = callsArray->length();
+ if (len > 0) {
+ return JSValue::encode(callsArray->getIndex(globalObject, len - 1));
+ }
+ }
+ return JSValue::encode(jsUndefined());
+}
+
+const JSC::ClassInfo MockWithImplementationCleanupData::s_info = { "MockWithImplementationCleanupData"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(MockWithImplementationCleanupData) };
+
+template<typename, JSC::SubspaceAccess mode>
+JSC::GCClient::IsoSubspace* MockWithImplementationCleanupData::subspaceFor(JSC::VM& vm)
+{
+ return WebCore::subspaceForImpl<MockWithImplementationCleanupData, WebCore::UseCustomHeapCellType::No>(
+ vm,
+ [](auto& spaces) { return spaces.m_clientSubspaceForMockWithImplementationCleanupData.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForMockWithImplementationCleanupData = std::forward<decltype(space)>(space); },
+ [](auto& spaces) { return spaces.m_subspaceForMockWithImplementationCleanupData.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_subspaceForMockWithImplementationCleanupData = std::forward<decltype(space)>(space); });
+}
+
+MockWithImplementationCleanupData* MockWithImplementationCleanupData::create(VM& vm, Structure* structure)
+{
+ MockWithImplementationCleanupData* mod = new (NotNull, allocateCell<MockWithImplementationCleanupData>(vm)) MockWithImplementationCleanupData(vm, structure);
+ return mod;
+}
+Structure* MockWithImplementationCleanupData::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+{
+ return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
+}
+
+MockWithImplementationCleanupData::MockWithImplementationCleanupData(VM& vm, Structure* structure)
+ : Base(vm, structure)
+{
+}
+
+void MockWithImplementationCleanupData::finishCreation(VM& vm, JSMockFunction* fn, JSValue impl, JSValue tail, JSValue fallback)
+{
+ Base::finishCreation(vm);
+ this->internalField(0).set(vm, this, fn);
+ this->internalField(1).set(vm, this, impl);
+ this->internalField(2).set(vm, this, tail);
+ this->internalField(3).set(vm, this, fallback);
+}
+
+template<typename Visitor>
+void MockWithImplementationCleanupData::visitChildrenImpl(JSCell* cell, Visitor& visitor)
+{
+ auto* thisObject = jsCast<MockWithImplementationCleanupData*>(cell);
+ ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+ Base::visitChildren(thisObject, visitor);
+}
+
+DEFINE_VISIT_CHILDREN(MockWithImplementationCleanupData);
+
+MockWithImplementationCleanupData* MockWithImplementationCleanupData::create(JSC::JSGlobalObject* globalObject, JSMockFunction* fn, JSValue impl, JSValue tail, JSValue fallback)
+{
+ auto* obj = create(globalObject->vm(), reinterpret_cast<Zig::GlobalObject*>(globalObject)->mockModule.mockWithImplementationCleanupDataStructure.getInitializedOnMainThread(globalObject));
+ obj->finishCreation(globalObject->vm(), fn, impl, tail, fallback);
+ return obj;
+}
+
+JSC_DEFINE_HOST_FUNCTION(jsMockFunctionWithImplementationCleanup, (JSC::JSGlobalObject * jsGlobalObject, JSC::CallFrame* callframe))
+{
+ auto& vm = jsGlobalObject->vm();
+ auto count = callframe->argumentCount();
+ auto ctx = jsDynamicCast<MockWithImplementationCleanupData*>(callframe->argument(1));
+ if (!ctx) {
+ return JSValue::encode(jsUndefined());
+ }
+
+ auto fn = jsDynamicCast<JSMockFunction*>(ctx->internalField(0).get());
+ fn->implementation.set(vm, fn, ctx->internalField(1).get());
+ fn->tail.set(vm, fn, ctx->internalField(2).get());
+ fn->fallbackImplmentation.set(vm, fn, ctx->internalField(3).get());
+
+ return JSValue::encode(jsUndefined());
+}
+JSC_DEFINE_HOST_FUNCTION(jsMockFunctionWithImplementation, (JSC::JSGlobalObject * jsGlobalObject, JSC::CallFrame* callframe))
+{
+ Zig::GlobalObject* globalObject = jsCast<Zig::GlobalObject*>(jsGlobalObject);
+
+ JSMockFunction* thisObject = jsDynamicCast<JSMockFunction*>(callframe->thisValue().toThis(globalObject, JSC::ECMAMode::strict()));
+ auto& vm = globalObject->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ if (UNLIKELY(!thisObject)) {
+ throwTypeError(globalObject, scope, "Expected Mock"_s);
+ return {};
+ }
+
+ JSValue tempImplValue = callframe->argument(0);
+ JSValue callback = callframe->argument(1);
+ JSC::CallData callData = JSC::getCallData(callback);
+ if (UNLIKELY(callData.type == JSC::CallData::Type::None)) {
+ throwTypeError(globalObject, scope, "Expected mock implementation to be callable"_s);
+ return {};
+ }
+
+ auto lastImpl = thisObject->implementation.get();
+ auto lastTail = thisObject->tail.get();
+ auto lastFallback = thisObject->fallbackImplmentation.get();
+
+ JSMockImplementation* impl = JSMockImplementation::create(
+ globalObject,
+ globalObject->mockModule.mockImplementationStructure.getInitializedOnMainThread(globalObject),
+ JSMockImplementation::Kind::Call,
+ tempImplValue,
+ false);
+
+ thisObject->implementation.set(vm, thisObject, impl);
+ thisObject->fallbackImplmentation.clear();
+ thisObject->tail.clear();
+
+ MarkedArgumentBuffer args;
+ NakedPtr<Exception> exception;
+ JSValue returnValue = call(globalObject, callback, callData, jsUndefined(), args, exception);
+
+ if (auto promise = tryJSDynamicCast<JSC::JSPromise*>(returnValue)) {
+ auto capability = JSC::JSPromise::createNewPromiseCapability(globalObject, globalObject->promiseConstructor());
+ auto ctx = MockWithImplementationCleanupData::create(globalObject, thisObject, lastImpl, lastTail, lastFallback);
+
+ JSFunction* cleanup = globalObject->mockModule.withImplementationCleanupFunction.getInitializedOnMainThread(globalObject);
+ JSFunction* performPromiseThenFunction = globalObject->performPromiseThenFunction();
+ auto callData = JSC::getCallData(performPromiseThenFunction);
+ MarkedArgumentBuffer arguments;
+ arguments.append(promise);
+ arguments.append(cleanup);
+ arguments.append(cleanup);
+ arguments.append(capability);
+ arguments.append(ctx);
+ ASSERT(!arguments.hasOverflowed());
+ call(globalObject, performPromiseThenFunction, callData, jsUndefined(), arguments);
+
+ return JSC::JSValue::encode(promise);
+ }
+
+ thisObject->implementation.set(vm, thisObject, lastImpl);
+ thisObject->tail.set(vm, thisObject, lastImpl);
+ thisObject->fallbackImplmentation.set(vm, thisObject, lastFallback);
+
+ return JSC::JSValue::encode(jsUndefined());
+}
+} // namespace Bun
+
+namespace JSC {
+
+template<unsigned passedNumberOfInternalFields>
+template<typename Visitor>
+void JSInternalFieldObjectImpl<passedNumberOfInternalFields>::visitChildrenImpl(JSCell* cell, Visitor& visitor)
+{
+ auto* thisObject = jsCast<JSInternalFieldObjectImpl*>(cell);
+ ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+ Base::visitChildren(thisObject, visitor);
+ visitor.appendValues(thisObject->m_internalFields, numberOfInternalFields);
}
-} \ No newline at end of file
+
+DEFINE_VISIT_CHILDREN_WITH_MODIFIER(template<unsigned passedNumberOfInternalFields>, JSInternalFieldObjectImpl<passedNumberOfInternalFields>);
+
+} // namespace JSC
diff --git a/src/bun.js/bindings/JSMockFunction.h b/src/bun.js/bindings/JSMockFunction.h
index 288ca2e89..93c8bb015 100644
--- a/src/bun.js/bindings/JSMockFunction.h
+++ b/src/bun.js/bindings/JSMockFunction.h
@@ -16,15 +16,47 @@ class JSMockFunction;
class JSMockModule final {
public:
+ static uint64_t s_nextInvocationId;
+ static uint64_t nextInvocationId() { return ++s_nextInvocationId; }
+
LazyProperty<JSC::JSGlobalObject, Structure> mockFunctionStructure;
LazyProperty<JSC::JSGlobalObject, Structure> mockResultStructure;
LazyProperty<JSC::JSGlobalObject, Structure> mockImplementationStructure;
LazyProperty<JSC::JSGlobalObject, Structure> mockObjectStructure;
LazyProperty<JSC::JSGlobalObject, Structure> activeSpySetStructure;
+ LazyProperty<JSC::JSGlobalObject, JSFunction> withImplementationCleanupFunction;
+ LazyProperty<JSC::JSGlobalObject, JSC::Structure> mockWithImplementationCleanupDataStructure;
static JSMockModule create(JSC::JSGlobalObject*);
JSC::Strong<Unknown> activeSpies;
};
-} \ No newline at end of file
+class MockWithImplementationCleanupData : public JSC::JSInternalFieldObjectImpl<4> {
+public:
+ using Base = JSC::JSInternalFieldObjectImpl<4>;
+
+ template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm);
+
+ JS_EXPORT_PRIVATE static MockWithImplementationCleanupData* create(VM&, Structure*);
+ static MockWithImplementationCleanupData* create(JSC::JSGlobalObject* globalObject, JSMockFunction* fn, JSValue impl, JSValue tail, JSValue fallback);
+ static MockWithImplementationCleanupData* createWithInitialValues(VM&, Structure*);
+ static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
+
+ static std::array<JSValue, numberOfInternalFields> initialValues()
+ {
+ return { {
+ jsUndefined(),
+ jsUndefined(),
+ jsUndefined(),
+ jsUndefined(),
+ } };
+ }
+
+ DECLARE_EXPORT_INFO;
+ DECLARE_VISIT_CHILDREN;
+
+ MockWithImplementationCleanupData(JSC::VM&, JSC::Structure*);
+ void finishCreation(JSC::VM&, JSMockFunction* fn, JSValue impl, JSValue tail, JSValue fallback);
+};
+}
diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp
index 5589d2add..e49b94687 100644
--- a/src/bun.js/bindings/ZigGlobalObject.cpp
+++ b/src/bun.js/bindings/ZigGlobalObject.cpp
@@ -4042,6 +4042,8 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor)
thisObject->mockModule.mockImplementationStructure.visit(visitor);
thisObject->mockModule.mockObjectStructure.visit(visitor);
thisObject->mockModule.activeSpySetStructure.visit(visitor);
+ thisObject->mockModule.mockWithImplementationCleanupDataStructure.visit(visitor);
+ thisObject->mockModule.withImplementationCleanupFunction.visit(visitor);
for (auto& barrier : thisObject->m_thenables) {
visitor.append(barrier);
diff --git a/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h b/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h
index d595dc866..3997c1d88 100644
--- a/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h
+++ b/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h
@@ -36,6 +36,7 @@ public:
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForCommonJSModuleRecord;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForJSMockImplementation;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForJSMockFunction;
+ std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForMockWithImplementationCleanupData;
#include "ZigGeneratedClasses+DOMClientIsoSubspaces.h"
/* --- bun --- */
diff --git a/src/bun.js/bindings/webcore/DOMIsoSubspaces.h b/src/bun.js/bindings/webcore/DOMIsoSubspaces.h
index b4a5e9d55..4feca1754 100644
--- a/src/bun.js/bindings/webcore/DOMIsoSubspaces.h
+++ b/src/bun.js/bindings/webcore/DOMIsoSubspaces.h
@@ -36,6 +36,7 @@ public:
std::unique_ptr<IsoSubspace> m_subspaceForCommonJSModuleRecord;
std::unique_ptr<IsoSubspace> m_subspaceForJSMockImplementation;
std::unique_ptr<IsoSubspace> m_subspaceForJSMockFunction;
+ std::unique_ptr<IsoSubspace> m_subspaceForMockWithImplementationCleanupData;
#include "ZigGeneratedClasses+DOMIsoSubspaces.h"
/*-- BUN --*/
diff --git a/src/bun.js/test/jest.zig b/src/bun.js/test/jest.zig
index 6c77d7aaa..00cc954ad 100644
--- a/src/bun.js/test/jest.zig
+++ b/src/bun.js/test/jest.zig
@@ -698,22 +698,22 @@ pub const Jest = struct {
Expect.getConstructor(globalObject),
);
- const mock_object = JSMockFunction__createObject(globalObject);
+ const mock_fn = JSMockFunction__createObject(globalObject);
const spyOn = JSC.NewFunction(globalObject, ZigString.static("spyOn"), 2, JSMock__spyOn, false);
const restoreAllMocks = JSC.NewFunction(globalObject, ZigString.static("restoreAllMocks"), 2, jsFunctionResetSpies, false);
- module.put(
- globalObject,
- ZigString.static("mock"),
- mock_object,
- );
+ module.put(globalObject, ZigString.static("mock"), mock_fn);
const jest = JSValue.createEmptyObject(globalObject, 3);
- jest.put(globalObject, ZigString.static("fn"), mock_object);
+ jest.put(globalObject, ZigString.static("fn"), mock_fn);
jest.put(globalObject, ZigString.static("spyOn"), spyOn);
jest.put(globalObject, ZigString.static("restoreAllMocks"), restoreAllMocks);
module.put(globalObject, ZigString.static("jest"), jest);
module.put(globalObject, ZigString.static("spyOn"), spyOn);
+ const vi = JSValue.createEmptyObject(globalObject, 1);
+ vi.put(globalObject, ZigString.static("fn"), mock_fn);
+ module.put(globalObject, ZigString.static("vi"), vi);
+
return module;
}
@@ -989,15 +989,10 @@ pub const Expect = struct {
}
pub fn call(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue {
- const arguments_ = callframe.arguments(1);
- if (arguments_.len < 1) {
- globalObject.throw("expect() requires one argument\n", .{});
- return .zero;
- }
- const arguments = arguments_.ptr[0..arguments_.len];
+ const arguments = callframe.arguments(1);
+ const value = if (arguments.len < 1) JSC.JSValue.jsUndefined() else arguments.ptr[0];
var expect = globalObject.bunVM().allocator.create(Expect) catch unreachable;
- const value = arguments[0];
if (Jest.runner.?.pending_test == null) {
const err = globalObject.createErrorInstance("expect() must be called in a test", .{});
diff --git a/src/js/out/WebCoreJSBuiltins.cpp b/src/js/out/WebCoreJSBuiltins.cpp
index 55238274b..1fecb34e3 100644
--- a/src/js/out/WebCoreJSBuiltins.cpp
+++ b/src/js/out/WebCoreJSBuiltins.cpp
@@ -2916,9 +2916,9 @@ WEBCORE_FOREACH_WRITABLESTREAMDEFAULTCONTROLLER_BUILTIN_CODE(DEFINE_BUILTIN_GENE
const JSC::ConstructAbility s_eventSourceGetEventSourceCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
const JSC::ConstructorKind s_eventSourceGetEventSourceCodeConstructorKind = JSC::ConstructorKind::None;
const JSC::ImplementationVisibility s_eventSourceGetEventSourceCodeImplementationVisibility = JSC::ImplementationVisibility::Public;
-const int s_eventSourceGetEventSourceCodeLength = 5476;
+const int s_eventSourceGetEventSourceCodeLength = 5477;
static const JSC::Intrinsic s_eventSourceGetEventSourceCodeIntrinsic = JSC::NoIntrinsic;
-const char* const s_eventSourceGetEventSourceCode = "(function (){\"use strict\";class j extends EventTarget{#$;#j;#w;#A;#B;#F=!1;#G=null;#J=\"\";#K=\"\";#L=\"\";#M=!0;#O=0;#Q=0;#U=0;#V=null;static#W(w){w.#H()}static#X(w,A){const B=w.data,F=B.#L\?`Last-Event-ID: ${B.#L}\\r\\n`:\"\",G=`GET ${A.pathname}${A.search} HTTP/1.1\\r\\nHost: bun\\r\\nContent-type: text/event-stream\\r\\nContent-length: 0\\r\\n${F}\\r\\n`,J=w.write(G);if(J!==G.length)B.#K=G.substring(J)}static#Y(w,A,B){for(;;){if(B>=A.length)return;let F=-1,G=A.indexOf(\"\\r\\n\",B);const J=G+2;if(G>0)if(w.#O===0){const Q=parseInt(A.substring(B,G),16);if(Q===0){w.#j=2,w.#G\?.end();return}F=J+Q}else F=A.length;else{if(w.#J.length===0){w.#J+=A.substring(B);return}F=A.length}let K=A.substring(J,F);B=F+2;let L=0,M=K.indexOf(\"\\n\\n\");if(M==-1){w.#J+=A.substring(J);return}if(w.#J.length)w.#J+=K,K=w.#J,w.#J=\"\";let O=!0;while(O){const Q=K.substring(L,M);let U,V=\"\",W,X=0,Y=-1;for(;;){let z=Q.indexOf(\"\\n\",X);if(z===-1){if(X>=Q.length)break;z=Q.length}const H=Q.substring(X,z);if(H.startsWith(\"data:\"))if(V.length)V+=`\\n${H.substring(5).trim()}`;else V=H.substring(5).trim();else if(H.startsWith(\"event:\"))U=H.substring(6).trim();else if(H.startsWith(\"id:\"))W=H.substring(3).trim();else if(H.startsWith(\"retry:\")){if(Y=parseInt(H.substring(6).trim(),10),@isNaN(Y))Y=-1}X=z+1}if(w.#L=W||\"\",Y>=0)w.#U=Y;if(V||W||U)w.dispatchEvent(new MessageEvent(U||\"message\",{data:V||\"\",origin:w.#$.origin,source:w,lastEventId:W}));if(K.length===M+2){O=!1;break}const Z=K.indexOf(\"\\n\\n\",M+1);if(Z===-1)break;L=M,M=Z}}}static#Z={open(w){const A=w.data;if(A.#G=w,!A.#F)j.#X(w,A.#$)},handshake(w,A,B){const F=w.data;if(A)j.#X(w,F.#$);else F.#j=2,F.dispatchEvent(new ErrorEvent(\"error\",{error:B})),w.end()},data(w,A){const B=w.data;switch(B.#j){case 0:{let F=A.toString();const G=F.indexOf(\"\\r\\n\\r\\n\");if(G===-1){B.#J+=F;return}if(B.#J.length)B.#J+=F,F=B.#J,B.#J=\"\";const J=F.substring(0,G),K=J.indexOf(\"\\r\\n\");if(K===-1){B.#j=2,B.dispatchEvent(new ErrorEvent(\"error\",{error:new Error(\"Invalid HTTP request\")})),w.end();return}const L=J.substring(0,K);if(L!==\"HTTP/1.1 200 OK\"){B.#j=2,B.dispatchEvent(new ErrorEvent(\"error\",{error:new Error(L)})),w.end();return}let M=K+1,O=!1,Q=-1;for(;;){let V=J.indexOf(\"\\r\\n\",M);if(V===-1){if(M>=J.length){if(!O)B.#j=2,B.dispatchEvent(new ErrorEvent(\"error\",{error:new Error(`EventSource's response has no MIME type and \"text/event-stream\" is required. Aborting the connection.`)})),w.end();return}V=J.length}const W=J.substring(M+1,V),X=W.indexOf(\":\"),Y=W.substring(0,X),Z=Y.localeCompare(\"content-type\",@undefined,{sensitivity:\"accent\"})===0;if(M=V+1,Z)if(W.endsWith(\" text/event-stream\"))O=!0;else{B.#j=2,B.dispatchEvent(new ErrorEvent(\"error\",{error:new Error(`EventSource's response has a MIME type that is not \"text/event-stream\". Aborting the connection.`)})),w.end();return}else if(Y.localeCompare(\"content-length\",@undefined,{sensitivity:\"accent\"})===0){if(Q=parseInt(W.substring(X+1).trim(),10),@isNaN(Q)||Q<=0){B.dispatchEvent(new ErrorEvent(\"error\",{error:new Error(`EventSource's Content-Length is invalid. Aborting the connection.`)})),w.end();return}if(O)break}else if(Y.localeCompare(\"transfer-encoding\",@undefined,{sensitivity:\"accent\"})===0){if(W.substring(X+1).trim()!==\"chunked\"){B.dispatchEvent(new ErrorEvent(\"error\",{error:new Error(`EventSource's Transfer-Encoding is invalid. Aborting the connection.`)})),w.end();return}if(Q=0,O)break}}B.#O=Q,B.#j=1,B.dispatchEvent(new Event(\"open\"));const U=F.substring(G+4);if(j.#Y(B,U,0),B.#O>0){if(B.#Q+=U.length,B.#Q>=B.#O)B.#j=2,w.end()}return}case 1:if(j.#Y(B,A.toString(),2),B.#O>0){if(B.#Q+=A.byteLength,B.#Q>=B.#O)B.#j=2,w.end()}return;default:break}},drain(w){const A=w.data;if(A.#j===0){const B=A.#J;if(B.length){const F=w.write(B);if(F!==B.length)w.data.#K=B.substring(F);else w.data.#K=\"\"}}},close:j.#z,end(w){j.#z(w).dispatchEvent(new ErrorEvent(\"error\",{error:new Error(\"Connection closed by server\")}))},timeout(w){j.#z(w).dispatchEvent(new ErrorEvent(\"error\",{error:new Error(\"Timeout\")}))},binaryType:\"buffer\"};static#z(w){const A=w.data;if(A.#G=null,A.#Q=0,A.#j=2,A.#M){if(A.#V)clearTimeout(A.#V);A.#V=setTimeout(j.#W,A.#U,A)}return A}constructor(w,A=@undefined){super();const B=new URL(w);this.#F=B.protocol===\"https:\",this.#$=B,this.#j=2,process.nextTick(j.#W,this)}ref(){this.#V\?.ref(),this.#G\?.ref()}unref(){this.#V\?.unref(),this.#G\?.unref()}#H(){if(this.#j!==2)return;const w=this.#$,A=this.#F;this.#j=0,@Bun.connect({data:this,socket:j.#Z,hostname:w.hostname,port:parseInt(w.port||(A\?\"443\":\"80\"),10),tls:A\?{requestCert:!0,rejectUnauthorized:!1}:!1}).catch((B)=>{if(this.dispatchEvent(new ErrorEvent(\"error\",{error:B})),this.#M){if(this.#V)this.#V.unref\?.();this.#V=setTimeout(j.#W,1000,this)}})}get url(){return this.#$.href}get readyState(){return this.#j}close(){this.#M=!1,this.#j=2,this.#G\?.unref(),this.#G\?.end()}get onopen(){return this.#B}get onerror(){return this.#w}get onmessage(){return this.#A}set onopen(w){if(this.#B)super.removeEventListener(\"close\",this.#B);super.addEventListener(\"open\",w),this.#B=w}set onerror(w){if(this.#w)super.removeEventListener(\"error\",this.#w);super.addEventListener(\"error\",w),this.#w=w}set onmessage(w){if(this.#A)super.removeEventListener(\"message\",this.#A);super.addEventListener(\"message\",w),this.#A=w}}return Object.defineProperty(j.prototype,\"CONNECTING\",{enumerable:!0,value:0}),Object.defineProperty(j.prototype,\"OPEN\",{enumerable:!0,value:1}),Object.defineProperty(j.prototype,\"CLOSED\",{enumerable:!0,value:2}),j[Symbol.for(\"CommonJS\")]=0,j})\n";
+const char* const s_eventSourceGetEventSourceCode = "(function (){\"use strict\";class j extends EventTarget{#$;#j;#w;#A;#B;#F=!1;#G=null;#J=\"\";#K=\"\";#L=\"\";#M=!0;#O=0;#Q=0;#U=0;#V=null;static#W(w){w.#H()}static#X(w,A){const B=w.data,F=B.#L\?`Last-Event-ID: ${B.#L}\\r\\n`:\"\",G=`GET ${A.pathname}${A.search} HTTP/1.1\\r\\nHost: bun\\r\\nContent-type: text/event-stream\\r\\nContent-length: 0\\r\\n${F}\\r\\n`,J=w.write(G);if(J!==G.length)B.#K=G.substring(J)}static#Y(w,A,B){for(;;){if(B>=A.length)return;let F=-1,G=A.indexOf(\"\\r\\n\",B);const J=G+2;if(G>0)if(w.#O===0){const Q=parseInt(A.substring(B,G),16);if(Q===0){w.#j=2,w.#G\?.end();return}F=J+Q}else F=A.length;else{if(w.#J.length===0){w.#J+=A.substring(B);return}F=A.length}let K=A.substring(J,F);B=F+2;let L=0,M=K.indexOf(\"\\n\\n\");if(M==-1){w.#J+=A.substring(J);return}if(w.#J.length)w.#J+=K,K=w.#J,w.#J=\"\";let O=!0;while(O){const Q=K.substring(L,M);let U,V=\"\",W,X=0,Y=-1;for(;;){let z=Q.indexOf(\"\\n\",X);if(z===-1){if(X>=Q.length)break;z=Q.length}const H=Q.substring(X,z);if(H.startsWith(\"data:\"))if(V.length)V+=`\\n${H.substring(5).trim()}`;else V=H.substring(5).trim();else if(H.startsWith(\"event:\"))U=H.substring(6).trim();else if(H.startsWith(\"id:\"))W=H.substring(3).trim();else if(H.startsWith(\"retry:\")){if(Y=parseInt(H.substring(6).trim(),10),@isNaN(Y))Y=-1}X=z+1}if(w.#L=W||\"\",Y>=0)w.#U=Y;if(V||W||U)w.dispatchEvent(new MessageEvent(U||\"message\",{data:V||\"\",origin:w.#$.origin,source:w,lastEventId:W}));if(K.length===M+2){O=!1;break}const Z=K.indexOf(\"\\n\\n\",M+1);if(Z===-1)break;L=M,M=Z}}}static#Z={open(w){const A=w.data;if(A.#G=w,!A.#F)j.#X(w,A.#$)},handshake(w,A,B){const F=w.data;if(A)j.#X(w,F.#$);else F.#j=2,F.dispatchEvent(new ErrorEvent(\"error\",{error:B})),w.end()},data(w,A){const B=w.data;switch(B.#j){case 0:{let F=A.toString();const G=F.indexOf(\"\\r\\n\\r\\n\");if(G===-1){B.#J+=F;return}if(B.#J.length)B.#J+=F,F=B.#J,B.#J=\"\";const J=F.substring(0,G),K=J.indexOf(\"\\r\\n\");if(K===-1){B.#j=2,B.dispatchEvent(new ErrorEvent(\"error\",{error:new Error(\"Invalid HTTP request\")})),w.end();return}const L=J.substring(0,K);if(L!==\"HTTP/1.1 200 OK\"){B.#j=2,B.dispatchEvent(new ErrorEvent(\"error\",{error:new Error(L)})),w.end();return}let M=K+1,O=!1,Q=-1;for(;;){let V=J.indexOf(\"\\r\\n\",M);if(V===-1){if(M>=J.length){if(!O)B.#j=2,B.dispatchEvent(new ErrorEvent(\"error\",{error:new Error(`EventSource's response has no MIME type and \"text/event-stream\" is required. Aborting the connection.`)})),w.end();return}V=J.length}const W=J.substring(M+1,V),X=W.indexOf(\":\"),Y=W.substring(0,X),Z=Y.localeCompare(\"content-type\",@undefined,{sensitivity:\"accent\"})===0;if(M=V+1,Z)if(W.endsWith(\" text/event-stream\"))O=!0;else{B.#j=2,B.dispatchEvent(new ErrorEvent(\"error\",{error:new Error(`EventSource's response has a MIME type that is not \"text/event-stream\". Aborting the connection.`)})),w.end();return}else if(Y.localeCompare(\"content-length\",@undefined,{sensitivity:\"accent\"})===0){if(Q=parseInt(W.substring(X+1).trim(),10),@isNaN(Q)||Q<=0){B.dispatchEvent(new ErrorEvent(\"error\",{error:new Error(`EventSource's Content-Length is invalid. Aborting the connection.`)})),w.end();return}if(O)break}else if(Y.localeCompare(\"transfer-encoding\",@undefined,{sensitivity:\"accent\"})===0){if(W.substring(X+1).trim()!==\"chunked\"){B.dispatchEvent(new ErrorEvent(\"error\",{error:new Error(`EventSource's Transfer-Encoding is invalid. Aborting the connection.`)})),w.end();return}if(Q=0,O)break}}B.#O=Q,B.#j=1,B.dispatchEvent(new Event(\"open\"));const U=F.substring(G+4);if(j.#Y(B,U,0),B.#O>0){if(B.#Q+=U.length,B.#Q>=B.#O)B.#j=2,w.end()}return}case 1:if(j.#Y(B,A.toString(),2),B.#O>0){if(B.#Q+=A.byteLength,B.#Q>=B.#O)B.#j=2,w.end()}return;default:break}},drain(w){const A=w.data;if(A.#j===0){const B=A.#J;if(B.length){const F=w.write(B);if(F!==B.length)w.data.#K=B.substring(F);else w.data.#K=\"\"}}},close:j.#z,end(w){j.#z(w).dispatchEvent(new ErrorEvent(\"error\",{error:new Error(\"Connection closed by server\")}))},timeout(w){j.#z(w).dispatchEvent(new ErrorEvent(\"error\",{error:new Error(\"Timeout\")}))},binaryType:\"buffer\"};static#z(w){const A=w.data;if(A.#G=null,A.#Q=0,A.#j=2,A.#M){if(A.#V)clearTimeout(A.#V);A.#V=setTimeout(j.#W,A.#U,A)}return A}constructor(w,A=@undefined){super();const B=new URL(w);this.#F=B.protocol===\"https:\",this.#$=B,this.#j=2,process.nextTick(j.#W,this)}ref(){this.#V\?.ref(),this.#G\?.ref()}unref(){this.#V\?.unref(),this.#G\?.unref()}#H(){if(this.#j!==2)return;const w=this.#$,A=this.#F;this.#j=0,@Bun.connect({data:this,socket:j.#Z,hostname:w.hostname,port:parseInt(w.port||(A\?\"443\":\"80\"),10),tls:A\?{requestCert:!0,rejectUnauthorized:!1}:!1}).catch((B)=>{if(super.dispatchEvent(new ErrorEvent(\"error\",{error:B})),this.#M){if(this.#V)this.#V.unref\?.();this.#V=setTimeout(j.#W,1000,this)}})}get url(){return this.#$.href}get readyState(){return this.#j}close(){this.#M=!1,this.#j=2,this.#G\?.unref(),this.#G\?.end()}get onopen(){return this.#B}get onerror(){return this.#w}get onmessage(){return this.#A}set onopen(w){if(this.#B)super.removeEventListener(\"close\",this.#B);super.addEventListener(\"open\",w),this.#B=w}set onerror(w){if(this.#w)super.removeEventListener(\"error\",this.#w);super.addEventListener(\"error\",w),this.#w=w}set onmessage(w){if(this.#A)super.removeEventListener(\"message\",this.#A);super.addEventListener(\"message\",w),this.#A=w}}return Object.defineProperty(j.prototype,\"CONNECTING\",{enumerable:!0,value:0}),Object.defineProperty(j.prototype,\"OPEN\",{enumerable:!0,value:1}),Object.defineProperty(j.prototype,\"CLOSED\",{enumerable:!0,value:2}),j[Symbol.for(\"CommonJS\")]=0,j})\n";
#define DEFINE_BUILTIN_GENERATOR(codeName, functionName, overriddenName, argumentCount) \
JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \
diff --git a/src/js/out/modules/node/http.js b/src/js/out/modules/node/http.js
index 02e000138..dd007e740 100644
--- a/src/js/out/modules/node/http.js
+++ b/src/js/out/modules/node/http.js
@@ -93,8 +93,7 @@ function get(url, options, cb) {
return req.end(), req;
}
var { EventEmitter } = import.meta.require("node:events"), { isIPv6 } = import.meta.require("node:net"), { Readable, Writable, Duplex } = import.meta.require("node:stream"), { URL } = import.meta.require("node:url"), { newArrayWithSize, String, Object, Array } = import.meta.primordials, { isTypedArray } = import.meta.require("util/types"), globalReportError = globalThis.reportError, setTimeout = globalThis.setTimeout, fetch = Bun.fetch, nop = () => {
-}, __DEBUG__ = process.env.__DEBUG__, debug = __DEBUG__ ? (...args) => console.log("node:http", ...args) : nop, kEmptyObject = Object.freeze(Object.create(null)), kOutHeaders = Symbol.for("kOutHeaders"), kEndCalled = Symbol.for("kEndCalled"), kAbortController = Symbol.for("kAbortController"), kClearTimeout = Symbol("kClearTimeout"), kCorked = Symbol.for("kCorked"), searchParamsSymbol = Symbol.for("query"), StringPrototypeSlice = String.prototype.slice, StringPrototypeStartsWith = String.prototype.startsWith, StringPrototypeToUpperCase = String.prototype.toUpperCase, StringPrototypeIncludes = String.prototype.includes, StringPrototypeCharCodeAt = String.prototype.charCodeAt, StringPrototypeIndexOf = String.prototype.indexOf, ArrayIsArray = Array.isArray, RegExpPrototypeExec = RegExp.prototype.exec, ObjectAssign = Object.assign, ObjectPrototypeHasOwnProperty = Object.prototype.hasOwnProperty, INVALID_PATH_REGEX = /[^\u0021-\u00ff]/;
-var _globalAgent, _defaultHTTPSAgent, kInternalRequest = Symbol("kInternalRequest"), kInternalSocketData = Symbol.for("::bunternal::"), kEmptyBuffer = Buffer.alloc(0), FakeSocket = class Socket extends Duplex {
+}, __DEBUG__ = process.env.__DEBUG__, debug = __DEBUG__ ? (...args) => console.log("node:http", ...args) : nop, kEmptyObject = Object.freeze(Object.create(null)), kOutHeaders = Symbol.for("kOutHeaders"), kEndCalled = Symbol.for("kEndCalled"), kAbortController = Symbol.for("kAbortController"), kClearTimeout = Symbol("kClearTimeout"), kCorked = Symbol.for("kCorked"), searchParamsSymbol = Symbol.for("query"), StringPrototypeSlice = String.prototype.slice, StringPrototypeStartsWith = String.prototype.startsWith, StringPrototypeToUpperCase = String.prototype.toUpperCase, StringPrototypeIncludes = String.prototype.includes, StringPrototypeCharCodeAt = String.prototype.charCodeAt, StringPrototypeIndexOf = String.prototype.indexOf, ArrayIsArray = Array.isArray, RegExpPrototypeExec = RegExp.prototype.exec, ObjectAssign = Object.assign, ObjectPrototypeHasOwnProperty = Object.prototype.hasOwnProperty, INVALID_PATH_REGEX = /[^\u0021-\u00ff]/, NODE_HTTP_WARNING = "WARN: Agent is mostly unused in Bun's implementation of http. If you see strange behavior, this is probably the cause.", _globalAgent, _defaultHTTPSAgent, kInternalRequest = Symbol("kInternalRequest"), kInternalSocketData = Symbol.for("::bunternal::"), kEmptyBuffer = Buffer.alloc(0), FakeSocket = class Socket extends Duplex {
bytesRead = 0;
bytesWritten = 0;
connecting = !1;
diff --git a/src/js/out/modules/node/net.js b/src/js/out/modules/node/net.js
index 162da7754..ddd799cf2 100644
--- a/src/js/out/modules/node/net.js
+++ b/src/js/out/modules/node/net.js
@@ -24,9 +24,7 @@ var isIPv4 = function(s) {
self.emit("listening");
}, createServer = function(options, connectionListener) {
return new Server(options, connectionListener);
-};
-var IPv4Reg = new RegExp("^((?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])[.]){3}(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$");
-var IPv6Reg = new RegExp("^((?:(?:[0-9a-fA-F]{1,4}):){7}(?:(?:[0-9a-fA-F]{1,4})|:)|(?:(?:[0-9a-fA-F]{1,4}):){6}(?:((?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])[.]){3}(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])|:(?:[0-9a-fA-F]{1,4})|:)|(?:(?:[0-9a-fA-F]{1,4}):){5}(?::((?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])[.]){3}(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])|(:(?:[0-9a-fA-F]{1,4})){1,2}|:)|(?:(?:[0-9a-fA-F]{1,4}):){4}(?:(:(?:[0-9a-fA-F]{1,4})){0,1}:((?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])[.]){3}(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])|(:(?:[0-9a-fA-F]{1,4})){1,3}|:)|(?:(?:[0-9a-fA-F]{1,4}):){3}(?:(:(?:[0-9a-fA-F]{1,4})){0,2}:((?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])[.]){3}(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])|(:(?:[0-9a-fA-F]{1,4})){1,4}|:)|(?:(?:[0-9a-fA-F]{1,4}):){2}(?:(:(?:[0-9a-fA-F]{1,4})){0,3}:((?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])[.]){3}(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])|(:(?:[0-9a-fA-F]{1,4})){1,5}|:)|(?:(?:[0-9a-fA-F]{1,4}):){1}(?:(:(?:[0-9a-fA-F]{1,4})){0,4}:((?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])[.]){3}(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])|(:(?:[0-9a-fA-F]{1,4})){1,6}|:)|(?::((?::(?:[0-9a-fA-F]{1,4})){0,5}:((?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])[.]){3}(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])|(?::(?:[0-9a-fA-F]{1,4})){1,7}|:)))(%[0-9a-zA-Z-.:]{1,})?$"), { Bun, createFIFO, Object } = import.meta.primordials, { connect: bunConnect } = Bun, { Duplex } = import.meta.require("node:stream"), { EventEmitter } = import.meta.require("node:events"), { setTimeout } = globalThis, bunTlsSymbol = Symbol.for("::buntls::"), bunSocketServerHandlers = Symbol.for("::bunsocket_serverhandlers::"), bunSocketServerConnections = Symbol.for("::bunnetserverconnections::"), bunSocketServerOptions = Symbol.for("::bunnetserveroptions::"), SocketClass, Socket = function(InternalSocket) {
+}, v4Seg = "(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])", v4Str = "((?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])[.]){3}(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])", IPv4Reg = new RegExp("^((?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])[.]){3}(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$"), v6Seg = "(?:[0-9a-fA-F]{1,4})", IPv6Reg = new RegExp("^((?:(?:[0-9a-fA-F]{1,4}):){7}(?:(?:[0-9a-fA-F]{1,4})|:)|(?:(?:[0-9a-fA-F]{1,4}):){6}(?:((?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])[.]){3}(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])|:(?:[0-9a-fA-F]{1,4})|:)|(?:(?:[0-9a-fA-F]{1,4}):){5}(?::((?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])[.]){3}(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])|(:(?:[0-9a-fA-F]{1,4})){1,2}|:)|(?:(?:[0-9a-fA-F]{1,4}):){4}(?:(:(?:[0-9a-fA-F]{1,4})){0,1}:((?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])[.]){3}(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])|(:(?:[0-9a-fA-F]{1,4})){1,3}|:)|(?:(?:[0-9a-fA-F]{1,4}):){3}(?:(:(?:[0-9a-fA-F]{1,4})){0,2}:((?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])[.]){3}(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])|(:(?:[0-9a-fA-F]{1,4})){1,4}|:)|(?:(?:[0-9a-fA-F]{1,4}):){2}(?:(:(?:[0-9a-fA-F]{1,4})){0,3}:((?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])[.]){3}(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])|(:(?:[0-9a-fA-F]{1,4})){1,5}|:)|(?:(?:[0-9a-fA-F]{1,4}):){1}(?:(:(?:[0-9a-fA-F]{1,4})){0,4}:((?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])[.]){3}(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])|(:(?:[0-9a-fA-F]{1,4})){1,6}|:)|(?::((?::(?:[0-9a-fA-F]{1,4})){0,5}:((?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])[.]){3}(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])|(?::(?:[0-9a-fA-F]{1,4})){1,7}|:)))(%[0-9a-zA-Z-.:]{1,})?$"), { Bun, createFIFO, Object } = import.meta.primordials, { connect: bunConnect } = Bun, { Duplex } = import.meta.require("node:stream"), { EventEmitter } = import.meta.require("node:events"), { setTimeout } = globalThis, bunTlsSymbol = Symbol.for("::buntls::"), bunSocketServerHandlers = Symbol.for("::bunsocket_serverhandlers::"), bunSocketServerConnections = Symbol.for("::bunnetserverconnections::"), bunSocketServerOptions = Symbol.for("::bunnetserveroptions::"), SocketClass, Socket = function(InternalSocket) {
return SocketClass = InternalSocket, Object.defineProperty(SocketClass.prototype, Symbol.toStringTag, {
value: "Socket",
enumerable: !1
diff --git a/test/bun.lockb b/test/bun.lockb
index 64371cbb1..fc86845e1 100755
--- a/test/bun.lockb
+++ b/test/bun.lockb
Binary files differ
diff --git a/test/js/bun/test/bigint.test.js b/test/js/bun/test/bigint.test.js
deleted file mode 100644
index 46ad50b84..000000000
--- a/test/js/bun/test/bigint.test.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import { describe, expect, it } from "bun:test";
-
-describe("BigInt", () => {
- it("compares correctly (literal)", () => {
- expect(42n).toBe(42n);
- });
-
- it("compares correctly (object)", () => {
- expect(BigInt(42n)).toBe(BigInt(42n));
- expect(42n).toBe(BigInt(42n));
- expect(BigInt(Bun.inspect(42n).substring(0, 2))).toBe(BigInt(42n));
- expect(BigInt(42n).valueOf()).toBe(BigInt(42n));
- });
-});
diff --git a/test/js/bun/test/bun-test.test.ts b/test/js/bun/test/bun-test.test.ts
index cc6bf644a..5a8061e8c 100644
--- a/test/js/bun/test/bun-test.test.ts
+++ b/test/js/bun/test/bun-test.test.ts
@@ -4,3 +4,9 @@ test("Bun.version", () => {
expect(process.versions.bun).toBe(Bun.version);
expect(process.revision).toBe(Bun.revision);
});
+
+test("expect().not.not", () => {
+ // bun supports this but jest doesn't
+ expect(1).not.not.toBe(1);
+ expect(1).not.not.not.toBe(2);
+});
diff --git a/test/js/bun/test/expect.test.js b/test/js/bun/test/expect.test.js
new file mode 100644
index 000000000..f09f7d196
--- /dev/null
+++ b/test/js/bun/test/expect.test.js
@@ -0,0 +1,2955 @@
+"use strict";
+
+/** This file is meant to be runnable in both Jest and Bun.
+ * `bunx jest mock-fn.test.js`
+ */
+var { isBun, test, describe, expect, jest, vi, mock, bunTest, spyOn } = require("./test-interop.js")();
+
+describe("expect()", () => {
+ test("can call without an argument", () => {
+ expect().toBe(undefined);
+ });
+
+ test("toStrictEqual() vs toEqual()", () => {
+ expect([1, , 3]).toEqual([1, , 3]);
+ expect({}).toEqual({});
+ expect({}).toStrictEqual({});
+ expect({}).toEqual({ a: undefined });
+ expect({}).not.toStrictEqual({ a: undefined });
+
+ class C {
+ hi = 34;
+ }
+ class D {
+ hi = 34;
+ }
+ let c = new C();
+ let d = new D();
+
+ expect(d).toEqual(c);
+ expect(d).not.toStrictEqual(c);
+ expect({ a: 1, b: undefined }).toEqual({ a: 1 });
+ expect({ a: 1 }).toEqual({ a: 1, b: undefined });
+ expect({ a: 1, b: undefined }).toEqual({ a: 1, b: undefined });
+
+ expect({ a: 1, b: undefined }).not.toStrictEqual({ a: 1 });
+ expect({ a: 1 }).not.toStrictEqual({ a: 1, b: undefined });
+ expect({ a: 1, b: undefined }).toStrictEqual({ a: 1, b: undefined });
+
+ expect({ a: 1, b: null }).not.toEqual({ a: 1 });
+ expect({ a: 1 }).not.toEqual({ a: 1, b: null });
+ expect({ a: 1, b: null }).toEqual({ a: 1, b: null });
+
+ expect({ a: 1 }).not.toEqual({ a: true });
+ expect({ a: 1 }).not.toEqual({ a: "1" });
+ expect({ a: 1 }).not.toEqual({ a: 1, b: 2 });
+ expect({ a: 1, b: 2 }).not.toEqual({ a: 1 });
+ expect({ a: 1 }).not.toStrictEqual({ a: true });
+ expect({ a: 1 }).not.toStrictEqual({ a: "1" });
+ expect({ a: 1 }).not.toStrictEqual({ a: 1, b: 2 });
+ expect({ a: 1, b: 2 }).not.toStrictEqual({ a: 1 });
+ expect({ a: 1 }).toStrictEqual({ a: 1 });
+
+ expect([1, undefined, 3]).toEqual([1, undefined, 3]);
+ expect([1, undefined, 3]).toStrictEqual([1, undefined, 3]);
+ expect([1, undefined, 3]).not.toEqual([1, 2, 3]);
+ expect([1, undefined, 3]).not.toStrictEqual([1, 2, 3]);
+ expect([1, undefined, 3]).not.toEqual([1, 2]);
+ expect([1, undefined, 3]).not.toStrictEqual([1, 2]);
+ expect([1, undefined, 3]).not.toEqual([1]);
+ expect([1, undefined, 3]).not.toStrictEqual([1]);
+ expect([1, undefined, 3]).not.toEqual([]);
+ expect([1, undefined, 3]).not.toStrictEqual([]);
+ expect([1, undefined, 3]).not.toEqual([1, 3]);
+ expect([1, undefined, 3]).not.toStrictEqual([1, 3]);
+
+ expect([1, null, 3]).toEqual([1, null, 3]);
+ expect([1, null, 3]).toStrictEqual([1, null, 3]);
+ expect([1, null, 3]).not.toEqual([1, 2, 3]);
+ expect([1, null, 3]).not.toStrictEqual([1, 2, 3]);
+ expect([1, null, 3]).not.toEqual([1, 2]);
+ expect([1, null, 3]).not.toStrictEqual([1, 2]);
+ expect([1, null, 3]).not.toEqual([1]);
+ expect([1, null, 3]).not.toStrictEqual([1]);
+ expect([1, null, 3]).not.toEqual([]);
+ expect([1, null, 3]).not.toStrictEqual([]);
+ expect([1, null, 3]).not.toEqual([1, 3]);
+ expect([1, null, 3]).not.toStrictEqual([1, 3]);
+
+ expect([, 1]).toEqual([, 1]);
+ expect([, 1]).toStrictEqual([, 1]);
+ expect([, 1]).not.toEqual([1]);
+ expect([1]).not.toEqual([, 1]);
+ expect([, 1]).not.toStrictEqual([1]);
+ expect([1]).not.toStrictEqual([, 1]);
+ expect([, 1]).toEqual([undefined, 1]);
+ expect([, 1]).not.toStrictEqual([undefined, 1]);
+ expect([, 1]).not.toEqual([null, 1]);
+ expect([, 1]).not.toStrictEqual([null, 1]);
+ expect([undefined, 1]).toEqual([, 1]);
+ expect([undefined, 1]).not.toStrictEqual([, 1]);
+ expect([null, 1]).not.toEqual([, 1]);
+ expect([null, 1]).not.toStrictEqual([, 1]);
+ expect([undefined, 1]).toEqual([undefined, 1]);
+ expect([undefined, 1]).toStrictEqual([undefined, 1]);
+
+ expect([0, , 2]).toEqual([0, undefined, 2]);
+ expect([, "boo2"]).toEqual([undefined, "boo2"]);
+ expect([, "boo"]).toEqual([, "boo"]);
+ expect([, 1]).toEqual([undefined, 1]);
+
+ const s1 = Symbol("test1");
+ const s2 = Symbol("test2");
+
+ let a = { a: 1, b: 2 };
+ let b = { a: 1, b: 2 };
+ a[s1] = 1;
+ b[s1] = 1;
+ a[s2] = undefined;
+ b[s2] = null;
+ expect(a).not.toEqual(b);
+ class F extends String {
+ constructor() {
+ super();
+ }
+ }
+
+ let f = new F("hello");
+ let j = new String("hello");
+ expect(f).not.toEqual(j);
+ class LaCroix {
+ constructor(flavor) {
+ this.flavor = flavor;
+ }
+ }
+ expect(new LaCroix("pamplemousse")).not.toStrictEqual({
+ flavor: "pamplemousse",
+ });
+ expect(new LaCroix("pamplemousse")).toEqual({ flavor: "pamplemousse" });
+
+ expect([, 1]).not.toStrictEqual([undefined, 1]);
+
+ expect([0, , 2]).toEqual([0, undefined, 2]);
+ expect([, "boo2"]).toEqual([undefined, "boo2"]);
+ expect([, "boo"]).toEqual([, "boo"]);
+ expect([, 1]).toEqual([undefined, 1]);
+ });
+
+ describe("BigInt", () => {
+ it("compares correctly (literal)", () => {
+ expect(42n).toBe(42n);
+ });
+
+ it("compares correctly (object)", () => {
+ expect(BigInt(42n)).toBe(BigInt(42n));
+ expect(42n).toBe(BigInt(42n));
+ if (isBun) expect(BigInt(Bun.inspect(42n).substring(0, 2))).toBe(BigInt(42n));
+ expect(BigInt(42n).valueOf()).toBe(BigInt(42n));
+ });
+ });
+
+ function f1() {
+ return "hello!";
+ }
+ function f2() {
+ return "hey!";
+ }
+ test("deepEquals regex", () => {
+ expect(/a/imu).toEqual(/a/imu);
+ expect(/a/imu).not.toEqual(/ab/imu);
+
+ expect(new RegExp("s", "g")).toEqual(new RegExp("s", "g"));
+ expect(new RegExp("s", "g")).not.toEqual(new RegExp("s", "i"));
+ });
+
+ test("deepEquals works with accessors", () => {
+ {
+ let l1 = [1, undefined, 2];
+ let l2 = [1, undefined, 2];
+ Object.defineProperty(l1, 6, { get: () => 1 });
+ Object.defineProperty(l2, 6, { get: () => 1 });
+ expect(l1).toEqual(l2);
+ expect(l1).toStrictEqual(l2);
+ }
+ {
+ let l1 = [1, , 2];
+ let l2 = [1, undefined, 2];
+ Object.defineProperty(l1, 6, { get: () => 1 });
+ Object.defineProperty(l2, 6, { get: () => 2 });
+ expect(l1).toEqual(l2);
+ expect(l1).not.toStrictEqual(l2);
+ }
+ {
+ let l1 = [1, , 2];
+ let l2 = [1, , 2];
+ Object.defineProperty(l1, "hi", { get: () => 4 });
+ Object.defineProperty(l2, "hi", { get: () => 5 });
+ expect(l1).toEqual(l2);
+ expect(l1).toStrictEqual(l2);
+ }
+
+ {
+ let l1 = [1, , 2];
+ let l2 = [1, , 2];
+ Object.defineProperty(l1, "hi", { set: () => 4 });
+ Object.defineProperty(l2, "hi", { set: () => 5 });
+ expect(l1).toEqual(l2);
+ expect(l1).toStrictEqual(l2);
+ }
+
+ {
+ let o1 = { a: 1, c: undefined, b: 2 };
+ let o2 = { a: 1, c: undefined, b: 2 };
+ Object.defineProperty(o1, 6, { get: () => 1 });
+ Object.defineProperty(o2, 6, { get: () => 1 });
+ expect(o1).toEqual(o2);
+ expect(o1).toStrictEqual(o2);
+ }
+ {
+ let o1 = { a: 1, c: undefined, b: 2 };
+ let o2 = { a: 1, c: undefined, b: 2 };
+ Object.defineProperty(o1, 6, { get: () => 1 });
+ Object.defineProperty(o2, 6, { get: () => 2 });
+ expect(o1).toEqual(o2);
+ expect(o1).toStrictEqual(o2);
+ }
+ {
+ let o1 = { a: 1, c: undefined, b: 2 };
+ let o2 = { a: 1, c: undefined, b: 2 };
+ Object.defineProperty(o1, "hi", { get: () => 4 });
+ Object.defineProperty(o2, "hi", { get: () => 5 });
+ expect(o1).toEqual(o2);
+ expect(o1).toStrictEqual(o2);
+ }
+
+ {
+ let o1 = { a: 1, c: undefined, b: 2 };
+ let o2 = { a: 1, c: undefined, b: 2 };
+ Object.defineProperty(o1, "hi", { set: () => 4 });
+ Object.defineProperty(o2, "hi", { set: () => 5 });
+ expect(o1).toEqual(o2);
+ expect(o1).toStrictEqual(o2);
+ }
+ });
+
+ // Doesn't work on jest because of https://github.com/jestjs/jest/issues/10788
+ if (isBun) {
+ test("deepEquals works with proxies", () => {
+ {
+ let p1 = new Proxy({ a: 1, b: 2 }, {});
+ let p2 = new Proxy({ a: 1, b: 2 }, {});
+ expect(p1).toEqual(p2);
+ expect(p1).toStrictEqual(p2);
+ let p3 = new Proxy({ a: 1, b: 2 }, {});
+ let p4 = new Proxy({ a: 1, b: 3 }, {});
+ expect(p3).not.toEqual(p4);
+ expect(p3).not.toStrictEqual(p4);
+ }
+ {
+ let t1 = { a: 1, b: 2 };
+ let h1 = { get: (t, k) => t[k] };
+ let p1 = new Proxy(t1, h1);
+ let t2 = { a: 1, b: 2 };
+ let h2 = { get: (t, k) => 0 };
+ let p2 = new Proxy(t2, h2);
+ expect(p1).not.toEqual(p2);
+ expect(p1).not.toStrictEqual(p2);
+ }
+ {
+ let t1 = { a: 1, b: 2 };
+ let h1 = { get: (t, k) => t[k] + 2 };
+ let p1 = new Proxy(t1, h1);
+ let t2 = { a: 1, b: 2 };
+ let h2 = { get: (t, k) => t[k] + 2 };
+ let p2 = new Proxy(t2, h2);
+ expect(p1).toEqual(p2);
+ expect(p1).toStrictEqual(p2);
+ }
+ {
+ let t1 = { a: 1, b: 2 };
+ let h1 = { get: (t, k) => t[k] + 2 };
+ let p1 = new Proxy(t1, h1);
+ let t2 = { a: 1, b: 2 };
+ let h2 = { get: (t, k) => t[k] + 3 };
+ let p2 = new Proxy(t2, h2);
+ expect(p1).not.toEqual(p2);
+ expect(p1).not.toStrictEqual(p2);
+ }
+ {
+ // same handlers, different targets
+ let t1 = { a: 1, b: 2 };
+ let t2 = { a: 1, b: 2 };
+ let h1 = { get: (t, k) => t[k] + 2 };
+ let p1 = new Proxy(t1, h1);
+ let p2 = new Proxy(t2, h1);
+ expect(p1).toEqual(p2);
+ expect(p1).toStrictEqual(p2);
+ }
+ {
+ // same targets, different handlers
+ let t1 = { a: 1, b: 2 };
+ let h1 = { get: (t, k) => t[k] + 2 };
+ let h2 = { get: (t, k) => t[k] + 3 };
+ let p1 = new Proxy(t1, h1);
+ let p2 = new Proxy(t1, h2);
+ expect(p1).not.toEqual(p2);
+ expect(p1).not.toStrictEqual(p2);
+ }
+ {
+ // property with object
+ let t1 = { a: { b: 3 } };
+ let h1 = { get: (t, k) => t[k] };
+ let p1 = new Proxy(t1, h1);
+
+ let t2 = { a: { b: 3 } };
+ let h2 = { get: (t, k) => t[k] };
+ let p2 = new Proxy(t2, h2);
+
+ expect(p1).toEqual(p2);
+ expect(p1).toStrictEqual(p2);
+
+ let t3 = { a: { b: 3 } };
+ let h3 = { get: (t, k) => t[k] };
+ let p3 = new Proxy(t3, h3);
+
+ let t4 = { a: { b: 4 } };
+ let h4 = { get: (t, k) => t[k] };
+ let p4 = new Proxy(t4, h4);
+
+ expect(p3).not.toEqual(p4);
+ expect(p3).not.toStrictEqual(p4);
+ }
+ {
+ // proxy object equals itself
+ let t1 = { a: 1, b: 2 };
+ let h1 = { get: (t, k) => t[k] + 2 };
+ let p1 = new Proxy(t1, h1);
+ expect(p1).toEqual(p1);
+ expect(p1).toStrictEqual(p1);
+ }
+ {
+ let t1 = { a: 1, b: 2 };
+ let h1 = { get: (t, k) => k };
+ let p1 = new Proxy(t1, h1);
+
+ let t2 = { a: 1, b: 2 };
+ let h2 = { get: (t, k) => k };
+ let p2 = new Proxy(t2, h2);
+
+ expect(p1).toEqual(p2);
+ expect(p1).toStrictEqual(p2);
+ }
+ });
+ }
+
+ test("deepEquals works with sets/maps/dates/strings", () => {
+ const f = Symbol.for("foo");
+
+ let a = new Set();
+ a.add([1, 2, 3]);
+ a.add("hello");
+ a.add({ a: 1 });
+ a.add(89);
+
+ let b = new Set();
+ b.add(89);
+ b.add({ a: 1 });
+ b.add("hello");
+ b.add([1, 2, 3]);
+
+ expect(a).toEqual(b);
+ expect(b).toEqual(a);
+ expect(b).toEqual(b);
+
+ let obj = {};
+ var c = new Set();
+ obj.c = c;
+ obj.x = obj;
+ c.add(obj);
+ expect(obj).toEqual(obj);
+
+ let o1 = { a: new Set() };
+ o1.a.add(o1);
+ expect(o1).toEqual(o1);
+
+ let o2 = new Set();
+ let o3 = {};
+ o3.x = o3;
+ o2.add(o3);
+ expect(o2).toEqual(o2);
+
+ var d = new Date();
+ var e = new Date(d);
+ e[f] = "hello";
+
+ expect(d).toEqual(e);
+ expect(e).toEqual(d);
+
+ class Date2 extends Date {
+ constructor() {
+ super(...arguments);
+ }
+ }
+
+ class Date3 extends Date2 {
+ constructor() {
+ super(...arguments);
+ }
+ }
+
+ let d2 = new Date2();
+ let e2 = new Date(d2);
+ d2[f] = "hello";
+ expect(d2).toEqual(e2);
+ expect(e2).toEqual(d2);
+
+ let d3 = new Date3();
+ let e3 = new Date(d3);
+ d3[f] = "hello";
+ expect(d3).toEqual(e3);
+ expect(e3).toEqual(d3);
+
+ let d4 = new Date();
+ let e4 = new Date3(d4);
+ d4[f] = "hello";
+ expect(d4).toEqual(e4);
+ expect(e4).toEqual(d4);
+
+ let d5 = new Date2();
+ let e5 = new Date3(d5);
+ d5[f] = "hello";
+ expect(d5).toEqual(e5);
+ expect(e5).toEqual(d5);
+
+ expect(new String("a")).not.toEqual(new String("b"));
+
+ var s1 = new String("a");
+ var s2 = new String("a");
+ s1[f] = "hello";
+ expect(s1).toEqual(s2);
+
+ class String2 extends String {
+ constructor() {
+ super(...arguments);
+ }
+ }
+
+ class String3 extends String2 {
+ constructor() {
+ super(...arguments);
+ }
+ }
+
+ let string4 = {};
+ string4.__proto__ = String3.prototype;
+
+ var s3 = new String2("a");
+ var s4 = new String2("a");
+ s3[f] = "hello";
+ expect(s3).toEqual(s4);
+
+ var s5 = new String("a");
+ var s6 = new String3("a");
+ expect(s6).not.toEqual(s5);
+ expect(s5).not.toEqual(s6);
+
+ var s7 = new String2("a");
+ var s8 = new String3("a");
+ expect(s7).not.toEqual(s8);
+ expect(s8).not.toEqual(s7);
+
+ var s9 = new String2("a");
+ var s10 = new string4.constructor("a");
+ expect(s9).not.toEqual(s10);
+ expect(s10).not.toEqual(s9);
+
+ class F2 extends Function {}
+ class F3 extends F2 {}
+
+ var f1 = new Function();
+ var f2 = new F2();
+ var f3 = new F3();
+ expect(f1).not.toEqual(f2);
+ expect(f2).not.toEqual(f1);
+ expect(f2).not.toEqual(f3);
+ expect(f3).not.toEqual(f2);
+ });
+
+ describe("deepEquals with asymmetric matchers", () => {
+ it("should accept any string", () => {
+ expect({ name: "alice" }).toEqual({ name: expect.any(String) });
+ expect({ name: "bob" }).toEqual({ name: expect.any(String) });
+ expect({ name: "charlie" }).toEqual({ name: expect.any(String) });
+ });
+
+ it("should accept any number", () => {
+ expect({ age: 42 }).toEqual({ age: expect.any(Number) });
+ expect({ age: 69 }).toEqual({ age: expect.any(Number) });
+ expect({ age: 73 }).toEqual({ age: expect.any(Number) });
+ });
+
+ it("should accept any boolean", () => {
+ expect({ active: false }).toEqual({ active: expect.any(Boolean) });
+ expect({ active: true }).toEqual({ active: expect.any(Boolean) });
+ });
+
+ it("should not match the wrong constructors", () => {
+ function f() {
+ return 32;
+ }
+ Object.defineProperty(f, "name", { value: "String" });
+ expect({ a: "123" }).toEqual({ a: expect.any(String) });
+ expect({ a: "123" }).not.toEqual({ a: expect.any(f) });
+
+ function g() {
+ return 32;
+ }
+ Object.defineProperty(g, "name", { value: "BigInt" });
+ expect({ a: 123n }).toEqual({ a: expect.any(BigInt) });
+ expect({ a: 123n }).not.toEqual({ a: expect.any(g) });
+ });
+ });
+
+ test("toThrow", () => {
+ expect(() => {
+ throw new Error("hello");
+ }).toThrow("hello");
+
+ var err = new Error("bad");
+ expect(() => {
+ throw err;
+ }).toThrow(err);
+
+ expect(() => {
+ throw new Error("good");
+ }).toThrow();
+
+ expect(() => {
+ throw new Error("foo");
+ }).toThrow(/oo/);
+
+ expect(() =>
+ expect(() => {
+ throw new Error("bar");
+ }).toThrow(/baz/),
+ ).toThrow("/baz/");
+
+ expect(() => {
+ return true;
+ }).not.toThrow();
+
+ expect(() => {
+ return true;
+ }).not.toThrow(err);
+
+ const weirdThings = [
+ /watttt/g,
+ BigInt(123),
+ -42,
+ NaN,
+ Infinity,
+ -Infinity,
+ undefined,
+ null,
+ true,
+ false,
+ 0,
+ 1,
+ "",
+ "hello",
+ {},
+ [],
+ new Date(),
+ new Error(),
+ new RegExp("foo"),
+ new Map(),
+ new Set(),
+ Promise.resolve(),
+ Promise.reject(Symbol("123")).finally(() => {}),
+ Symbol("123"),
+ ];
+ for (const weirdThing of weirdThings) {
+ expect(() => {
+ throw weirdThing;
+ }).toThrow();
+ }
+
+ err.message = "null";
+ expect(() => {
+ throw null;
+ }).toThrow(err);
+ });
+
+ test("deepEquals derived strings and strings", () => {
+ let a = new String("hello");
+ let b = "hello";
+ expect(a).toEqual(a);
+ expect(b).toEqual(b);
+ expect(a).not.toEqual(b);
+ expect(b).not.toEqual(a);
+
+ class F extends String {
+ constructor() {
+ super();
+ }
+ }
+
+ let f = new F("hello");
+ expect(f).toEqual(f);
+ expect(f).not.toEqual(b);
+ expect(b).not.toEqual(f);
+
+ let j = new String("hello");
+ expect(f).not.toEqual(j);
+
+ class G extends String {
+ constructor() {
+ super();
+ this.x = 0;
+ }
+ }
+
+ let g = new G("hello");
+ expect(g).not.toEqual(f);
+ expect(f).not.toEqual(g);
+ expect(g).toEqual(g);
+ expect(g).not.toEqual(b);
+ expect(b).not.toEqual(g);
+ expect(g).not.toEqual(a);
+ });
+
+ test("deepEquals throw getters", () => {
+ let a = {
+ get x() {
+ throw new Error("a");
+ },
+ };
+
+ let b = {
+ get x() {
+ return 3;
+ },
+ };
+
+ try {
+ expect(a).not.toEqual(b);
+ } catch (e) {
+ expect(e.message).toContain("a");
+ }
+
+ class B {
+ get x() {
+ throw new Error("b");
+ }
+ }
+
+ class C {
+ get x() {
+ return 3;
+ }
+ }
+
+ expect(() => {
+ expect(new B()).not.toEqual(new C());
+ }).toThrow();
+
+ let o = [
+ {
+ get x() {
+ throw new Error("c");
+ },
+ },
+ ];
+
+ let p = [
+ {
+ get x() {
+ return 3;
+ },
+ },
+ ];
+
+ try {
+ expect(o).not.toEqual(p);
+ } catch (e) {
+ expect(e.message).toContain("c");
+ }
+
+ const s = Symbol("s");
+ let q = {
+ get x() {
+ throw new Error("d");
+ },
+ };
+ q[s] = 3;
+
+ let r = {
+ get x() {
+ return 3;
+ },
+ };
+ r[s] = 3;
+
+ try {
+ expect(q).not.toEqual(r);
+ } catch (e) {
+ expect(e.message).toContain("d");
+ }
+ });
+
+ test("deepEquals large object", () => {
+ let o = {};
+ for (let i = 0; i < 65; i++) {
+ o["bun" + i] = i;
+ }
+ expect(o).toEqual(o);
+ let b = {};
+ for (let i = 0; i < 63; i++) {
+ b["bun" + i] = i;
+ }
+ expect(b).toEqual(b);
+ expect(o).not.toEqual(b);
+ expect(b).not.toEqual(o);
+
+ let c = { d: [Array(o)] };
+ let d = { d: [Array(b)] };
+ expect(c).toEqual(c);
+ expect(d).toEqual(d);
+ expect(c).not.toEqual(d);
+ expect(d).not.toEqual(c);
+
+ let e = { d: [Array(o), Array(o)] };
+ let f = { d: [Array(b), Array(b)] };
+ expect(e).toEqual(e);
+ expect(f).toEqual(f);
+ expect(e).not.toEqual(f);
+ expect(f).not.toEqual(e);
+
+ let p = [];
+ p[0] = {};
+ for (let i = 0; i < 1000; i++) {
+ p[0]["bun" + i] = i;
+ }
+ let q = [];
+ q[0] = {};
+ for (let i = 0; i < 1000; i++) {
+ q[0]["bun" + i] = i;
+ }
+ expect(p).toEqual(p);
+ expect(q).toEqual(q);
+
+ q[0].bun789 = 788;
+ expect(p).not.toEqual(q);
+ expect(q).not.toEqual(p);
+
+ let r = { d: {} };
+ let s = { d: {} };
+ for (let i = 0; i < 1000; i++) {
+ r.d["bun" + i] = i;
+ s.d["bun" + i] = i;
+ }
+
+ expect(r).toEqual(r);
+ expect(s).toEqual(s);
+
+ r.d.bun790 = 791;
+ expect(r).not.toEqual(s);
+ expect(s).not.toEqual(r);
+
+ let t = [];
+ t[5] = {};
+ let u = [];
+ u[5] = {};
+ for (let i = 0; i < 1000; i++) {
+ t[5]["bun" + i] = i;
+ }
+ for (let i = 0; i < 30; i++) {
+ u[5]["bun" + i] = i;
+ }
+ expect(t).toEqual(t);
+ expect(u).toEqual(u);
+ expect(t).not.toEqual(u);
+ expect(u).not.toEqual(t);
+
+ let v = { j: {} };
+ let w = { j: {} };
+ for (let i = 0; i < 1000; i++) {
+ v.j["bun" + i] = i;
+ w.j["bun" + i] = i;
+ }
+
+ expect(v).toEqual(v);
+ expect(w).toEqual(w);
+
+ v.j.bun999 = 1000;
+ expect(v).not.toEqual(w);
+ expect(w).not.toEqual(v);
+ expect(v).toEqual(v);
+
+ v.j.bun999 = 999;
+ w.j.bun0 = 1;
+ expect(v).not.toEqual(w);
+ expect(w).not.toEqual(v);
+ expect(v).toEqual(v);
+ expect(w).toEqual(w);
+ });
+
+ test("deepEquals - Date", () => {
+ let d = new Date();
+ expect(d).toEqual(d);
+ let b = d;
+ expect(b).toEqual(d);
+ d.setFullYear(1998);
+ expect(b).toEqual(d);
+ expect(b).not.toEqual(new Date());
+
+ var date = new Date();
+ date.setFullYear(1995);
+ expect(new Date()).not.toEqual(date);
+ });
+
+ test("deepEquals toString and functions", () => {
+ expect({ toString: f1 }).toEqual({
+ toString: f1,
+ });
+ expect({ toString: f1 }).not.toEqual({
+ toString: f2,
+ });
+
+ expect(f1).toEqual(f1);
+ expect(f1).not.toEqual(f2);
+ });
+
+ test("deepEquals set and map", () => {
+ let e = new Map();
+ e.set("a", 1);
+ e.set("b", 2);
+ e.set("c", 3);
+ e.set(8, 6);
+
+ let d = new Map();
+ d.set("a", 1);
+ d.set("b", 2);
+ d.set("c", 3);
+ d.set(8, 6);
+
+ expect(e).toEqual(d);
+ expect(d).toEqual(e);
+
+ let f = new Map();
+ f.set("a", 1);
+ f.set("b", 2);
+ f.set("c", 3);
+ f.set(8, 7);
+ expect(e).not.toEqual(f);
+
+ let g = new Map();
+ g.set({ a: { b: { c: 89 } } }, 1);
+
+ let h = new Map();
+ h.set({ a: { b: { c: 89 } } }, 1);
+ expect(g).toEqual(h);
+
+ let i = new Map();
+ i.set({ a: { b: { c: 89 } } }, 1);
+ i.set({ a: { b: { c: 89 } } }, 1);
+ expect(g).not.toEqual(i);
+
+ let j = new Map();
+ j.set({ a: { b: { c: 89 } } }, 1);
+ j.set({ a: { b: { c: 89 } } }, 1);
+ expect(i).toEqual(j);
+
+ let p = new Map();
+ p.set({ a: { b: { c: 90 } } }, 1);
+ expect(p).not.toEqual(g);
+
+ let q = new Map();
+ q.set({ a: { b: { c: 90 } } }, { a: { b: 45 } });
+
+ let r = new Map();
+ r.set({ a: { b: { c: 90 } } }, { a: { b: 45 } });
+ expect(q).toEqual(r);
+
+ let s = new Map();
+ s.set({ a: { b: { c: 90 } } }, { a: { b: 49 } });
+ expect(q).not.toEqual(s);
+
+ const u = { a: 1, b: 2 };
+
+ let a = new Set();
+ a.add({ a: 1 });
+ a.add([1, 2, 3]);
+ a.add("hello");
+ a.add(89);
+
+ let b = new Set();
+ b.add({ a: 1 });
+ b.add("hello");
+ b.add([1, 2, 3]);
+ b.add(89);
+ expect(a).toEqual(b);
+ expect(b).toEqual(a);
+ let c = new Set();
+ c.add(89);
+ c.add("hello");
+ c.add({ a: 1 });
+ c.add([1, 2, 3, 4]);
+ expect(a).not.toEqual(c);
+ });
+
+ test("deepEquals - symbols", () => {
+ const x = [5, 6];
+ x[99] = 7;
+
+ const y = [5, 6];
+ y[99] = 7;
+
+ expect(x).toEqual(y);
+
+ const s1 = Symbol("test1");
+ const s2 = Symbol("test2");
+
+ const o = { a: 1 };
+ o[s1] = 45;
+ o[99] = 99;
+ o[s2] = 3;
+
+ const k = { a: 1 };
+ k[99] = 99;
+ k[s2] = 3;
+ k[s1] = 45;
+
+ expect(o).toEqual(k);
+ });
+
+ test("deepEquals should not segfault", () => {
+ const obj = { ...Object.fromEntries(Object.entries([1, 2, 3, 4])), length: 4 };
+ expect(() => {
+ expect(obj).toEqual([1, 2, 3, 4]);
+ }).toThrow();
+ expect(() => {
+ expect([1, 2, 3, 4]).toEqual(obj);
+ }).toThrow();
+ });
+
+ test("toEqual objects and arrays", () => {
+ {
+ let obj = { 0: 4, 1: 3, length: 2 };
+ expect(Array.from(obj)).toEqual([4, 3]);
+ expect(Array.from(obj)).toStrictEqual([4, 3]);
+ }
+ {
+ let obj = { 0: 4, 1: 3, length: 4 };
+ expect(Array.from(obj)).toEqual([4, 3]);
+ expect(Array.from(obj)).not.toStrictEqual([4, 3]);
+ expect(Array.from(obj)).toEqual([4, 3, undefined, undefined]);
+ expect(Array.from(obj)).toStrictEqual([4, 3, undefined, undefined]);
+ expect(Array.from(obj)).toEqual([4, 3, , ,]);
+ expect(Array.from(obj)).not.toStrictEqual([4, 3, , ,]);
+ }
+ {
+ let a1 = [1, undefined, 3, , 4, null];
+ let a2 = [1, undefined, 3, , 4, null, , ,];
+ expect(a1).toEqual(a2);
+ expect(a1).not.toStrictEqual(a2);
+ expect(a2).toEqual(a1);
+ expect(a2).not.toStrictEqual(a1);
+ }
+ {
+ let a1 = [, , , , , , , , , , , ,];
+ let a2 = [undefined];
+ expect(a1).toEqual(a2);
+ expect(a1).not.toStrictEqual(a2);
+ expect(a2).toEqual(a1);
+ expect(a2).not.toStrictEqual(a1);
+ }
+ {
+ const a = [1];
+ const b = [1];
+ expect(a).toEqual(b);
+ Object.preventExtensions(b);
+ expect(a).toEqual(b);
+ Object.preventExtensions(a);
+ expect(a).toEqual(b);
+ }
+ {
+ let o1 = { 1: 4, 6: 3 };
+ let o2 = { 1: 4, 6: 3 };
+ expect(o1).toEqual(o2);
+ expect(o1).toStrictEqual(o2);
+ }
+ {
+ let o1 = { 1: 4, 6: 2 };
+ let o2 = { 1: 4, 6: 3 };
+ expect(o1).not.toEqual(o2);
+ expect(o1).not.toStrictEqual(o2);
+ }
+
+ {
+ let o1 = { a: 1, 3: 0 };
+ let o2 = { a: 1, 3: 0 };
+ expect(o1).toEqual(o2);
+ expect(o1).toStrictEqual(o2);
+ }
+ {
+ let o1 = { a: 1, 3: 0 };
+ let o2 = { a: 1, 3: 1 };
+ expect(o1).not.toEqual(o2);
+ expect(o1).not.toStrictEqual(o2);
+ }
+ {
+ let o1 = { a: {}, 4: { b: 3, c: { 9: 2 } } };
+ let o2 = { a: {}, 4: { b: 3, c: { 9: 2 } } };
+ expect(o1).toEqual(o2);
+ expect(o1).toStrictEqual(o2);
+ }
+ {
+ let o1 = { a: {}, 4: { b: 3, c: { 9: 2 } } };
+ let o2 = { a: {}, 4: { b: 3, c: { 9: 3 } } };
+ expect(o1).not.toEqual(o2);
+ expect(o1).not.toStrictEqual(o2);
+ }
+
+ {
+ let o1 = { a: 1, b: 2, c: 3 };
+ let o2 = { a: 1, b: 2, c: 3, 0: 1 };
+ expect(o1).not.toEqual(o2);
+ expect(o1).not.toStrictEqual(o2);
+ }
+
+ {
+ let o1 = { a: 1, b: 2, c: 3, 0: 1 };
+ let o2 = { a: 1, b: 2, c: 3 };
+ expect(o1).not.toEqual(o2);
+ expect(o1).not.toStrictEqual(o2);
+ }
+
+ expect("hello").toEqual("hello");
+ const s1 = Symbol("test1");
+ const s2 = Symbol("test2");
+
+ expect({ a: 1, b: 2 }).toEqual({ b: 2, a: 1 });
+ expect([1, 2, 3]).toEqual([1, 2, 3]);
+ expect({ a: 1, b: 2 }).not.toEqual({ b: 2, a: 1, c: 3 });
+ expect([1, 2, 3]).not.toEqual([1, 2, 3, 4]);
+ expect({ a: 1, b: 2, c: 3 }).not.toEqual({ a: 1, b: 2 });
+ expect([1, 2, 3, 4]).not.toEqual([1, 2, 3]);
+
+ let a = [{ a: 1 }, { b: 2, c: 3, d: 4 }, { e: 5, f: 6 }];
+ let b = [{ a: 1 }, { b: 2, c: 3, d: 4 }, { e: 5, f: 6 }];
+ expect(a).toEqual(b);
+ expect(b).toEqual(a);
+ a[0].a = 2;
+ expect(a).not.toEqual(b);
+ expect(b).not.toEqual(a);
+
+ let c = { [Symbol("test")]: 1 };
+ let d = { [Symbol("test")]: 1 };
+ expect(c).not.toEqual(d);
+ expect(d).not.toEqual(c);
+
+ a = { [s1]: 1 };
+ a[s1] = 1;
+ b = { [s2]: 1 };
+ b[s2] = 1;
+ expect(a).not.toEqual(b);
+ expect(b).not.toEqual(a);
+
+ a = {};
+ b = {};
+ a[s1] = 1;
+ b[s1] = 1;
+ expect(a).toEqual(b);
+
+ a = {};
+ b = {};
+ a[s1] = 1;
+ b[s1] = 2;
+ expect(a).not.toEqual(b);
+
+ a = {};
+ b = {};
+ a[s1] = 1;
+ b[s1] = 1;
+ a[s2] = 2;
+ b[s2] = 2;
+ expect(a).toEqual(b);
+
+ a = {};
+ b = {};
+ a[s1] = 1;
+ b[s1] = 1;
+ a[s2] = 2;
+ b[s2] = 3;
+ expect(a).not.toEqual(b);
+
+ a = { a: 1, b: 2 };
+ b = { a: 1, b: 2 };
+ a[s1] = 1;
+ b[s1] = 1;
+ expect(a).toEqual(b);
+
+ a = { a: 2, b: 2 };
+ b = { a: 1, b: 2 };
+ a[s1] = 1;
+ b[s1] = 1;
+ expect(a).not.toEqual(b);
+
+ // do the same tests for arrays
+ a = [{ a: 1 }, { b: 2, c: 3, d: 4 }, { e: 5, f: 6 }];
+ b = [{ a: 1 }, { b: 2, c: 3, d: 4 }, { e: 5, f: 6 }];
+ expect(a).toEqual(b);
+ expect(b).toEqual(a);
+ a[0].a = 2;
+ expect(a).not.toEqual(b);
+ expect(b).not.toEqual(a);
+
+ a = [1, 2, 3];
+ b = [1, 2, 3];
+ a[s1] = 1;
+ b[s1] = 1;
+ expect(a).toEqual(b);
+
+ a = [1, 2, 3];
+ b = [1, 2, 3];
+ a[s1] = 1;
+ b[s1] = 2;
+ expect(a).not.toEqual(b);
+
+ a = [1, 2, 3];
+ b = [1, 2, 3];
+ a[s1] = 1;
+ b[s1] = 1;
+ a[s2] = 2;
+ b[s2] = 2;
+ expect(a).toEqual(b);
+
+ a = [1, 2, 3];
+ b = [1, 2, 3];
+ a[s1] = 1;
+ b[s1] = 1;
+ a[s2] = 2;
+ b[s2] = 3;
+ expect(a).not.toEqual(b);
+
+ a = [1, 2, 3];
+ b = [1, 2, 3];
+ a[s1] = 1;
+ b[s1] = 1;
+ expect(a).toEqual(b);
+
+ a = [2, 2, 3];
+ b = [1, 2, 3];
+ a[s1] = 1;
+ b[s1] = 1;
+ expect(a).not.toEqual(b);
+
+ // do the same tests for objects and arrays with null and undefined
+ a = { a: 1, b: 2 };
+ b = { a: 1, b: 2 };
+ a[s1] = 1;
+ b[s1] = 1;
+ a[s2] = null;
+ b[s2] = undefined;
+ expect(a).not.toEqual(b);
+
+ a = { a: 1, b: 2 };
+ b = { a: 1, b: 2 };
+ a[s1] = 1;
+ b[s1] = 1;
+ a[s2] = undefined;
+ b[s2] = null;
+ expect(a).not.toEqual(b);
+
+ a = { a: 1, b: 2 };
+ b = { a: 1, b: 2 };
+ a[s1] = 1;
+ b[s1] = 1;
+ a[s2] = null;
+ b[s2] = null;
+ expect(a).toEqual(b);
+
+ a = { a: 1, b: 2 };
+ b = { a: 1, b: 2 };
+ a[s1] = 1;
+ b[s1] = 1;
+ a[s2] = undefined;
+ b[s2] = undefined;
+ expect(a).toEqual(b);
+
+ a = [1, 2, 3];
+ b = [1, 2, 3];
+ a[s1] = 1;
+ b[s1] = 1;
+ a[s2] = null;
+ b[s2] = undefined;
+ expect(a).not.toEqual(b);
+
+ a = [1, 2, 3];
+ b = [1, 2, 3];
+ a[s1] = 1;
+ b[s1] = 1;
+ a[s2] = undefined;
+ b[s2] = null;
+ expect(a).not.toEqual(b);
+
+ a = [1, 2, 3];
+ b = [1, 2, 3];
+ a[s1] = 1;
+ b[s1] = 1;
+ a[s2] = null;
+ b[s2] = null;
+ expect(a).toEqual(b);
+
+ a = [1, 2, 3];
+ b = [1, 2, 3];
+ a[s1] = 1;
+ b[s1] = 1;
+ a[s2] = undefined;
+ b[s2] = undefined;
+ expect(a).toEqual(b);
+
+ // similar tests for indexed objects
+ a = { 0: 1, 1: 2, 2: 3 };
+ b = { 0: 1, 1: 2, 2: 3 };
+ a[s1] = 1;
+ b[s1] = 1;
+ expect(a).toEqual(b);
+
+ a = { 0: 1, 1: 2, 2: 3 };
+ b = { 0: 1, 1: 2, 2: 3 };
+ a[s1] = 1;
+ b[s1] = 1;
+ a[s2] = 2;
+ b[s2] = 3;
+ expect(a).not.toEqual(b);
+
+ a = { 0: 1, 1: 3, 2: 3 };
+ b = { 0: 1, 1: 2, 2: 3 };
+ a[s1] = 1;
+ b[s1] = 1;
+ a[s2] = 2;
+ b[s2] = 2;
+ expect(a).not.toEqual(b);
+
+ a = [1, 2, 3];
+ b = [1, 2, 3, 4];
+ expect(a).not.toEqual(b);
+
+ a = [1, 2, 3, 4];
+ b = [1, 2, 3];
+ expect(a).not.toEqual(b);
+
+ a = { a: 1, b: 2 };
+ b = { a: 1, b: 2, c: 3 };
+ expect(a).not.toEqual(b);
+
+ a = { a: 1, b: 2, c: 3 };
+ b = { a: 1, b: 2 };
+ expect(a).not.toEqual(b);
+ });
+
+ test("symbol based keys in arrays are processed correctly", () => {
+ const mySymbol = Symbol("test");
+
+ const actual1 = [];
+ actual1[mySymbol] = 3;
+
+ const actual2 = [];
+ actual2[mySymbol] = 4;
+
+ const expected = [];
+ expected[mySymbol] = 3;
+
+ expect(actual2).not.toEqual(expected);
+ expect(actual1).toEqual(expected);
+ });
+
+ test("non-enumerable members should be skipped during equal", () => {
+ const actual = {
+ x: 3,
+ };
+ Object.defineProperty(actual, "test", {
+ enumerable: false,
+ value: 5,
+ });
+ expect(actual).toEqual({ x: 3 });
+ });
+
+ test("non-enumerable symbolic members should be skipped during equal", () => {
+ const actual = {
+ x: 3,
+ };
+ const mySymbol = Symbol("test");
+ Object.defineProperty(actual, mySymbol, {
+ enumerable: false,
+ value: 5,
+ });
+ expect(actual).toEqual({ x: 3 });
+ });
+
+ test("properties with the same circularity are equal", () => {
+ const a = {};
+ a.x = a;
+ const b = {};
+ b.x = b;
+ expect(a).toEqual(b);
+ expect(b).toEqual(a);
+
+ const c = {
+ x: a,
+ };
+ const d = {
+ x: b,
+ };
+
+ expect(d).toEqual(c);
+ expect(c).toEqual(d);
+ });
+
+ test("toEqual() - arrays", () => {
+ expect([1, 2, 3]).toEqual([1, 2, 3]);
+ expect([1, 2, 3, 4]).not.toEqual([1, 2, 3]);
+ });
+
+ test("properties with different circularity are not equal", () => {
+ const a = {};
+ a.x = { y: a };
+ const b = {};
+ const bx = {};
+ b.x = bx;
+ bx.y = bx;
+ expect(a).not.toEqual(b);
+ expect(b).not.toEqual(a);
+
+ const c = {};
+ c.x = a;
+ const d = {};
+ d.x = b;
+ expect(c).not.toEqual(d);
+ expect(d).not.toEqual(c);
+ });
+
+ test("are not equal if circularity is not on the same property", () => {
+ const a = {};
+ const b = {};
+ a.a1 = a;
+ b.a1 = {};
+ b.a1.a1 = a;
+
+ expect(a).not.toEqual(b);
+ expect(b).not.toEqual(a);
+
+ const c = {};
+ c.x = { x: c };
+ const d = {};
+ d.x = d;
+
+ expect(d).not.toEqual(c);
+ expect(c).not.toEqual(d);
+ });
+
+ test("random isEqual tests", () => {
+ expect(1).toEqual(1);
+ expect(1).not.toEqual(2);
+ expect(1).not.toEqual("1");
+ expect(1).not.toEqual(true);
+ expect(1).not.toEqual(false);
+ expect(1).not.toEqual(null);
+ expect(1).not.toEqual(undefined);
+ expect(1).not.toEqual({});
+ expect(1).not.toEqual([]);
+ expect(1).not.toEqual([1]);
+ expect(1).not.toEqual([1, 2]);
+ expect(1).not.toEqual([1, 2, 3]);
+ expect(1).not.toEqual([1, 2, 3, 4]);
+ expect(1).not.toEqual([1, 2, 3, 4, 5]);
+ expect(1).not.toEqual([1, 2, 3, 4, 5, 6]);
+ expect(1).not.toEqual([1, 2, 3, 4, 5, 6, 7]);
+ expect(1).not.toEqual([1, 2, 3, 4, 5, 6, 7, 8]);
+ expect(1).not.toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9]);
+ expect(1).not.toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
+ expect(1).not.toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
+ expect(1).not.toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
+ expect(1).not.toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
+ expect(1).not.toEqual([1, 2, 3, 4, 5, 6, 7, 8]);
+
+ // test toEquals for objects with getters and setters
+
+ expect([]).toEqual([]);
+ expect([1]).toEqual([1]);
+ expect([1, 2]).toEqual([1, 2]);
+ expect([1, 2, 3]).toEqual([1, 2, 3]);
+ expect({}).toEqual({});
+ expect({}).not.toEqual([]);
+ expect([]).not.toEqual({});
+
+ const obj = {
+ get a() {
+ return 1;
+ },
+ };
+ expect(obj).toEqual({ a: 1 });
+ expect({ a: 1 }).toEqual(obj);
+ expect(obj).not.toEqual({ a: 2 });
+ expect({ a: 2 }).not.toEqual(obj);
+
+ let a = new Set();
+ a.add([1, 2, 3]);
+ a.add("hello");
+ a.add({ a: 1 });
+ a.add(89);
+ let b = new Set();
+ b.add(89);
+ b.add({ a: 1 });
+ b.add("hello");
+ b.add([1, 2, 3]);
+ expect(a).toEqual(b);
+ expect(b).toEqual(a);
+ let c = new Set();
+ c.add(89);
+ c.add("helo");
+ c.add({ a: 1 });
+ c.add([1, 2, 3]);
+ expect(a).not.toEqual(c);
+
+ a = new Map();
+ a.set(1, 89);
+ a.set("hello", 2);
+ a.set({ a: 1 }, 3);
+ a.set([1, 2, 3], 4);
+ b = new Map();
+ b.set(1, 89);
+ b.set("hello", 2);
+ b.set({ a: 1 }, 3);
+ b.set([1, 2, 3], 4);
+ expect(a).toEqual(b);
+ expect(b).toEqual(a);
+ c = new Map();
+ c.set({ a: 1 }, 3);
+ c.set(1, 80);
+ c.set([1, 2, 3], 4);
+ c.set("hello", 2);
+ expect(a).not.toEqual(c);
+
+ a = new Set();
+ a.add(89);
+ a.add("hello");
+ a.add({ a: 1 });
+ a.add([1, 2, 3]);
+ a.add(a);
+ b = new Set();
+ b.add(89);
+ b.add("hello");
+ b.add(b);
+ b.add({ a: 1 });
+ b.add([1, 2, 3]);
+ expect(a).toEqual(b);
+ expect(b).toEqual(a);
+ });
+ test("toHaveProperty() - emojis", () => {
+ expect({ "👍": "thumbs up" }).toHaveProperty("👍", "thumbs up");
+ expect({ "👩‍👩‍👧‍👧": "family" }).toHaveProperty("👩‍👩‍👧‍👧", "family");
+ expect({ "😶‍🌫️": "fog" }).toHaveProperty("😶‍🌫️", "fog");
+ expect({ "👩‍❤️‍👨": "couple" }).toHaveProperty("👩‍❤️‍👨", "couple");
+ expect({ "👩‍❤️‍👨‍👨‍👧‍👧": "family" }).toHaveProperty("👩‍❤️‍👨‍👨‍👧‍👧", "family");
+ expect({ "👩‍❤️‍👨‍👨‍👧": "family" }).toHaveProperty("👩‍❤️‍👨‍👨‍👧", "family");
+ expect({ "👩‍❤️‍👨‍👨‍👧": "family" }).not.toHaveProperty("👩‍❤️‍👨‍👨‍👧‍👧", "family");
+
+ // emojis in array
+ expect(["👍", "👎"]).toHaveProperty("0", "👍");
+ expect(["👍", "👎"]).toHaveProperty("1", "👎");
+ expect(["👍", "👎"]).not.toHaveProperty("0", "👎");
+ expect(["👍", "👎"]).not.toHaveProperty("1", "👍");
+ expect(["👩‍❤️‍👨‍👨‍👧‍👧"]).toHaveProperty("0", "👩‍❤️‍👨‍👨‍👧‍👧");
+ expect(["👩‍❤️‍👨‍👨‍👧‍👧"]).toHaveProperty([0], "👩‍❤️‍👨‍👨‍👧‍👧");
+ expect(["😶‍🌫️"]).toHaveProperty([0], "😶‍🌫️");
+ });
+
+ test("toHaveProperty() - dot and bracket notation edge cases", () => {
+ expect({ a: 1 }).not.toHaveProperty(".");
+ expect({ a: 1 }).not.toHaveProperty("]");
+ expect({ a: 1 }).not.toHaveProperty("[");
+ expect({ a: 1 }).not.toHaveProperty("[]");
+ expect({ a: 1 }).not.toHaveProperty("[[]]");
+ expect({ a: 1 }).not.toHaveProperty("[[");
+ expect({ a: 1 }).not.toHaveProperty("]]");
+ expect({ a: 1 }).not.toHaveProperty("[]]");
+ expect({ a: 1 }).not.toHaveProperty("[[]");
+ expect({ a: 1 }).not.toHaveProperty(".]");
+ expect({ a: 1 }).not.toHaveProperty(".[");
+ expect({ "": 1 }).toHaveProperty("[.", 1);
+ expect({ a: 1 }).not.toHaveProperty("[.");
+ expect({ a: 1 }).not.toHaveProperty("].");
+ expect({ a: 1 }).not.toHaveProperty("].[");
+ expect({ a: 1 }).not.toHaveProperty("].]");
+ expect({ a: 1 }).not.toHaveProperty("[.]");
+ expect({ a: 1 }).not.toHaveProperty("[.[");
+
+ expect([1]).toHaveProperty("[0]", 1);
+ expect([1]).toHaveProperty("[0][", 1);
+ expect([1]).toHaveProperty("[0]]", 1);
+ expect([1]).toHaveProperty("[0][[", 1);
+ expect([1]).toHaveProperty("[][[[0]", 1);
+ expect([1]).toHaveProperty("[][[[]][[][][.0", 1);
+ expect([1]).toHaveProperty("[][[[]][[][][.[][[][[[][][0", 1);
+ expect([1]).not.toHaveProperty("......1.............", 1);
+ expect([1]).not.toHaveProperty("......0.............", 1);
+ expect([1]).not.toHaveProperty(".0", 1);
+ expect([1]).not.toHaveProperty("0.", 1);
+ expect([{ "": 1 }]).toHaveProperty("0.", 1);
+ expect({ "": { "": 1 } }).toHaveProperty(".", 1);
+ expect({ "": { "": { "": 1 } } }).toHaveProperty("..", 1);
+ expect({ "": { "": { "": 1 } } }).not.toHaveProperty(".", 1);
+ expect({ "": { "": { "": 1 } } }).not.toHaveProperty("...", 1);
+ expect({ "": { "": { "": 1 } } }).not.toHaveProperty("....", 1);
+ expect([1]).toHaveProperty("0.[[[][][]][[[][[]]]]", 1);
+ expect([1]).not.toHaveProperty("[0].", 1);
+ expect([1]).toHaveProperty("0", 1);
+ expect([1]).toHaveProperty("[].0", 1);
+ expect([1]).toHaveProperty("[.0", 1);
+ expect([1]).toHaveProperty("].0", 1);
+ expect([1]).toHaveProperty("0[]][[[]", 1);
+ expect([1]).toHaveProperty("[[]][[[][][0", 1);
+ expect([1]).toHaveProperty("0", 1);
+ expect([1]).toHaveProperty("0.[", 1);
+ expect([1]).not.toHaveProperty("0........[", 1);
+ expect([1]).not.toHaveProperty("0..[", 1);
+ expect([1]).not.toHaveProperty(".0", 1);
+ expect([1]).toHaveProperty("[].0", 1);
+ expect([1]).not.toHaveProperty("[]..0", 1);
+ expect([1]).toHaveProperty("[.][.[[.]]]]].[.[].].]]]]].].].0", 1);
+ expect([1]).not.toHaveProperty("[.][.[[.]]]]].[.[].].]]0]]].].].", 1);
+ expect([1]).toHaveProperty("[.][.[[.]]]]].[.[].].]]0]]].].]", 1);
+ expect([1]).not.toHaveProperty("[.][.[[..]]]]].[.[].].]]0]]].].]", 1);
+ expect([1]).toHaveProperty("[.][.[[.]]]]].[.[].].0.]]]]].].]", 1);
+ expect([1]).not.toHaveProperty("[.][.[[.]]]]].[.[].].0.]]] ]].].]", 1);
+ expect([1]).not.toHaveProperty("0 ", 1);
+ expect([1]).not.toHaveProperty(" 0 ", 1);
+ expect([1]).not.toHaveProperty(" 0[] ", 1);
+ expect([1]).not.toHaveProperty(" 0] ", 1);
+ expect([1]).not.toHaveProperty(" .[0]", 1);
+
+ expect({ "": 1 }).not.toHaveProperty(".", 1);
+ expect({ "": 1 }).not.toHaveProperty("]", 1);
+ expect({ "": 1 }).not.toHaveProperty("[", 1);
+ expect({ "": 1 }).toHaveProperty("", 1);
+
+ expect({ "": 1 }).not.toHaveProperty("..", 1);
+ expect({ "": { "": 1 } }).not.toHaveProperty("..", 1);
+ expect([{ "": 1 }]).toHaveProperty("0.", 1);
+ expect([{ "": 1 }]).not.toHaveProperty(".0.", 1);
+ expect({ "": [1] }).toHaveProperty(".0", 1);
+ expect({ "": [1] }).not.toHaveProperty("..0", 1);
+ expect([{ "": 1 }]).not.toHaveProperty("0..", 1);
+ expect([{ "": { "": 1 } }]).toHaveProperty("0..", 1);
+
+ expect([1]).not.toHaveProperty("[0].", 1);
+ expect([1]).not.toHaveProperty("[0][0]", 1);
+ expect({ a: [1] }).toHaveProperty("a[[[[[[[[[0]]]", 1);
+ expect({ "[[[": 0 }).not.toHaveProperty("[[[", 0);
+ });
+
+ test("toHaveProperty() - with string or array", () => {
+ const a = new Array(["a", "b", "c"]);
+ expect(a).toHaveProperty("0.1", "b");
+ const b = new Array("a", "b", "c");
+ expect({ a: { b: { c: 1 } } }).toHaveProperty(b);
+ const c = {
+ a: { b: 1 },
+ "a.b": 2,
+ };
+ const d = new Array("a.b");
+ expect(c).toHaveProperty(d, 2);
+ const houseForSale = {
+ bath: true,
+ bedrooms: 4,
+ kitchen: {
+ amenities: ["oven", "stove", "washer"],
+ area: 20,
+ wallColor: "white",
+ "nice.oven": true,
+ },
+ livingroom: {
+ amenities: [
+ {
+ couch: [
+ ["large", { dimensions: [20, 20] }],
+ ["small", { dimensions: [10, 10] }],
+ ],
+ },
+ ],
+ },
+ sunroom: "yes",
+ "ceiling.height": 20,
+ "entrance.window": 3,
+ entrance: { window: 5 },
+ };
+ expect(houseForSale).toHaveProperty("entrance.window", 5);
+ expect(houseForSale).toHaveProperty(["entrance", "window"], 5);
+ expect(houseForSale).toHaveProperty(["entrance.window"], 3);
+ expect(houseForSale).toHaveProperty("bath");
+ expect(houseForSale).not.toHaveProperty("jacuzzi");
+ // expect(houseForSale).toHaveProperty("jacuzzi");
+ // expect(houseForSale).not.toHaveProperty("bath");
+ expect(houseForSale).toHaveProperty("bath", true);
+ expect(houseForSale).not.toHaveProperty("bath", false);
+ // expect(houseForSale).toHaveProperty("bath", false);
+ // expect(houseForSale).not.toHaveProperty("bath", true);
+ expect(houseForSale).toHaveProperty("bedrooms", 4);
+ expect(houseForSale).toHaveProperty(["sunroom"], "yes");
+ expect(houseForSale).toHaveProperty("kitchen.area", 20);
+ expect(houseForSale).toHaveProperty("kitchen.amenities", ["oven", "stove", "washer"]);
+ expect(houseForSale).not.toHaveProperty(["kitchen", "area"], 21);
+ expect(houseForSale).toHaveProperty(["kitchen", "area"], 20);
+ expect(houseForSale).not.toHaveProperty(["kitchen", "area"], 29);
+ expect(houseForSale).toHaveProperty(["kitchen", "amenities"], ["oven", "stove", "washer"]);
+ expect(houseForSale).toHaveProperty("kitchen.amenities[2]", "washer");
+ expect(houseForSale).toHaveProperty(["kitchen", "amenities", 1], "stove");
+ expect(houseForSale).toHaveProperty(["kitchen", "amenities", 0], "oven");
+ expect(houseForSale).toHaveProperty("livingroom.amenities[0].couch[0][1].dimensions[0]", 20);
+ expect(houseForSale).toHaveProperty(["kitchen", "nice.oven"]);
+ expect(houseForSale).not.toHaveProperty(["kitchen", "open"]);
+ expect(houseForSale).toHaveProperty(["ceiling.height"], 20);
+ expect({ a: { b: 1 } }).toHaveProperty("a.b");
+ expect({ a: [2, 3, 4] }).toHaveProperty("a.0");
+ expect({ a: [2, 3, 4] }).toHaveProperty("a.1");
+ expect({ a: [2, 3, 4] }).toHaveProperty("a.2");
+ expect({ a: [2, 3, 4] }).toHaveProperty("a[1]");
+ expect([2, 3, 4]).toHaveProperty("1");
+ expect([2, 3, 4]).toHaveProperty("[1]");
+ expect([2, [6, 9], 4]).toHaveProperty("1.1");
+ expect([2, [6, 9], 4]).toHaveProperty("1[1]");
+ expect([2, [6, 9], 4]).toHaveProperty("[1].1");
+ expect([2, [6, 9], 4]).toHaveProperty("[1][1]");
+ expect([2, [6, 9], 4]).toHaveProperty([0], 2);
+ expect({ a: { b: 1 } }).toHaveProperty("a.b");
+ expect({ a: [1, 2, [3, { b: 1 }]] }).toHaveProperty("a.2.1.b");
+ expect({ a: [1, 2, [3, { b: 1 }]] }).toHaveProperty("a");
+ expect({ a: [1, 2, [3, { b: 1 }]] }).toHaveProperty("a[2][1].b");
+ expect({ a: [1, 2, [3, { b: 1 }]] }).toHaveProperty("a[2][1]");
+ expect({ a: [1, 2, [3, { b: 1 }]] }).not.toHaveProperty("a[2][1].c");
+ expect("test").toHaveProperty("length");
+ expect({}).toHaveProperty("constructor");
+ expect({}).toHaveProperty("constructor.name");
+ expect({}).toHaveProperty("constructor.name", "Object");
+ expect(new Date()).toHaveProperty("getTime");
+ });
+
+ test("toHaveProperty() - all", () => {
+ expect({ a: 1 }).toHaveProperty("a");
+ expect({ a: 1 }).toHaveProperty("a", 1);
+ expect({ a: 1 }).not.toHaveProperty("b");
+ expect({ a: 1 }).not.toHaveProperty("a", 2);
+
+ // test with object with property "a" with all types of values (including undefined)
+ expect({ a: undefined }).toHaveProperty("a");
+ expect({ a: null }).toHaveProperty("a");
+ expect({ a: 0 }).toHaveProperty("a");
+ expect({ a: false }).toHaveProperty("a");
+ expect({ a: "" }).toHaveProperty("a");
+ expect({ a: {} }).toHaveProperty("a");
+ expect({ a: [] }).toHaveProperty("a");
+ expect({ a: () => {} }).toHaveProperty("a");
+
+ // test with object with property "a" with all types of values (including undefined)
+ expect({ a: undefined }).toHaveProperty("a", undefined);
+ expect({ a: null }).toHaveProperty("a", null);
+ expect({ a: 0 }).toHaveProperty("a", 0);
+ expect({ a: false }).toHaveProperty("a", false);
+ expect({ a: "" }).toHaveProperty("a", "");
+ expect({ a: {} }).toHaveProperty("a", {});
+ expect({ a: [] }).toHaveProperty("a", []);
+ expect({ a: () => {} }).not.toHaveProperty("a", () => {});
+
+ // test with object with property "a" with all types of values (including undefined)
+
+ expect({ a: undefined }).not.toHaveProperty("a", null);
+ expect({ a: null }).not.toHaveProperty("a", undefined);
+ expect({ a: 0 }).not.toHaveProperty("a", null);
+ expect({ a: false }).not.toHaveProperty("a", null);
+ expect({ a: "" }).not.toHaveProperty("a", null);
+ expect({ a: {} }).not.toHaveProperty("a", null);
+ expect({ a: [] }).not.toHaveProperty("a", null);
+ expect({ a: () => {} }).not.toHaveProperty("a", null);
+
+ expect({ a: undefined }).not.toHaveProperty("a", 0);
+ expect({ a: null }).not.toHaveProperty("a", 0);
+ expect({ a: 0 }).not.toHaveProperty("a", 1);
+ expect({ a: false }).not.toHaveProperty("a", 0);
+ expect({ a: "" }).not.toHaveProperty("a", 0);
+ expect({ a: {} }).not.toHaveProperty("a", 0);
+ expect({ a: [] }).not.toHaveProperty("a", 0);
+ expect({ a: () => {} }).not.toHaveProperty("a", 0);
+
+ expect({ a: undefined }).not.toHaveProperty("a", false);
+ expect({ a: null }).not.toHaveProperty("a", false);
+ expect({ a: 0 }).not.toHaveProperty("a", false);
+ expect({ a: false }).not.toHaveProperty("a", true);
+ expect({ a: "" }).not.toHaveProperty("a", false);
+ expect({ a: {} }).not.toHaveProperty("a", false);
+ expect({ a: [] }).not.toHaveProperty("a", false);
+ expect({ a: () => {} }).not.toHaveProperty("a", false);
+
+ expect({ a: undefined }).not.toHaveProperty("a", "");
+ expect({ a: null }).not.toHaveProperty("a", "");
+ expect({ a: 0 }).not.toHaveProperty("a", "");
+ expect({ a: false }).not.toHaveProperty("a", "");
+ expect({ a: "" }).not.toHaveProperty("a", "a");
+ expect({ a: {} }).not.toHaveProperty("a", "");
+ expect({ a: [] }).not.toHaveProperty("a", "");
+ expect({ a: () => {} }).not.toHaveProperty("a", "");
+
+ expect({ a: undefined }).not.toHaveProperty("a", {});
+ expect({ a: null }).not.toHaveProperty("a", {});
+ expect({ a: 0 }).not.toHaveProperty("a", {});
+ expect({ a: false }).not.toHaveProperty("a", {});
+ expect({ a: "" }).not.toHaveProperty("a", {});
+ expect({ a: {} }).not.toHaveProperty("a", { a: 1 });
+ expect({ a: [] }).not.toHaveProperty("a", {});
+ expect({ a: () => {} }).not.toHaveProperty("a", {});
+
+ // test object with property "a" with value set, map, string
+ expect({ a: new Set([1, 2, 3]) }).toHaveProperty("a", new Set([3, 2, 1]));
+ expect({ a: new Map([{ a: 1 }, { b: 2 }, { c: 3 }]) }).toHaveProperty("a", new Map([{ c: 3 }, { b: 2 }, { a: 1 }]));
+ expect({ a: new String("a") }).toHaveProperty("a", new String("a"));
+ expect({ a: new String("a") }).not.toHaveProperty("a", "a");
+ expect({ a: new String("a") }).not.toHaveProperty("a", "b");
+ expect({ a: new String("a") }).not.toHaveProperty("a", new String("b"));
+ expect({ a: new String("a") }).not.toHaveProperty("a", new Number(1));
+ expect({ a: new String("a") }).not.toHaveProperty("a", new Boolean(true));
+ expect({ a: new String("a") }).not.toHaveProperty("a", new Boolean(false));
+ expect({ a: new String("a") }).not.toHaveProperty("a", new Object());
+ expect({ a: new String("a") }).not.toHaveProperty("a", new Array());
+ expect({ a: new String("a") }).not.toHaveProperty("a", new Function());
+ expect({ a: new String("a") }).not.toHaveProperty("a", new Date());
+ expect({ a: new String("a") }).not.toHaveProperty("a", new RegExp());
+ expect({ a: new String("a") }).not.toHaveProperty("a", new Error());
+ expect({ a: new String("a") }).not.toHaveProperty("a", new Promise(() => {}));
+ expect({ a: new String("a") }).not.toHaveProperty("a", new WeakSet());
+ expect({ a: new String("a") }).not.toHaveProperty("a", new WeakMap());
+ expect({ a: new String("a") }).not.toHaveProperty("a", Symbol("a"));
+ expect({ a: new String("a") }).not.toHaveProperty("a", new Int8Array());
+ expect({ a: new String("a") }).not.toHaveProperty("a", new Uint8Array());
+ expect({ a: new String("a") }).not.toHaveProperty("a", new Uint8ClampedArray());
+ expect({ a: new String("a") }).not.toHaveProperty("a", new Int16Array());
+ expect({ a: new String("a") }).not.toHaveProperty("a", new Uint16Array());
+ expect({ a: new String("a") }).not.toHaveProperty("a", new Int32Array());
+ expect({ a: new String("a") }).not.toHaveProperty("a", new Uint32Array());
+ expect({ a: new String("a") }).not.toHaveProperty("a", new Float32Array());
+ expect({ a: new String("a") }).not.toHaveProperty("a", new Float64Array());
+ expect({ a: new String("a") }).not.toHaveProperty("a", new BigInt64Array());
+ expect({ a: new String("a") }).not.toHaveProperty("a", new BigUint64Array());
+ expect({ a: new String("a") }).not.toHaveProperty("a", new ArrayBuffer());
+ expect({ a: new String("a") }).not.toHaveProperty("a", new SharedArrayBuffer());
+ expect({ a: new String("a") }).not.toHaveProperty("a", new DataView(new ArrayBuffer(1)));
+
+ // test property equality with sets, maps, objects, arrays, and String
+ expect({ a: new Set([1, 2, 3]) }).toHaveProperty("a", new Set([1, 2, 3]));
+ expect({ a: new Map([{ a: 1 }, { b: 2 }, { c: 3 }]) }).toHaveProperty("a", new Map([{ a: 1 }, { b: 2 }, { c: 3 }]));
+ expect({ a: { a: 1, b: 2, c: 3 } }).toHaveProperty("a", { a: 1, b: 2, c: 3 });
+ expect({ a: [1, 2, 3] }).toHaveProperty("a", [1, 2, 3]);
+ expect({ a: "a" }).toHaveProperty("a", "a");
+ expect({ a: new String("a") }).toHaveProperty("a", new String("a"));
+ expect({ a: new String("a") }).not.toHaveProperty("a", "a");
+ });
+
+ test.todo("toHaveProperty() - null or undefined", () => {
+ expect(() => expect(null).toHaveProperty("length")).toThrow();
+ expect(() => expect(null).not.toHaveProperty("length")).toThrow();
+ expect(() => expect(undefined).toHaveProperty("length")).toThrow();
+ expect(() => expect(undefined).not.toHaveProperty("length")).toThrow();
+ });
+
+ test("toBe()", () => {
+ const a = 1;
+ const b = 1;
+ expect(a).toBe(a);
+ expect(a).toBe(b);
+ expect(a).toBe(1);
+ expect(1).toBe(a);
+ expect(b).toBe(a);
+
+ const c = { a: 1 };
+ const d = { a: 1 };
+ expect(c).toBe(c);
+ expect(c).not.toBe(d);
+ expect(c).not.toBe({ a: 1 });
+ expect({ a: 1 }).not.toBe(c);
+ expect(d).not.toBe(c);
+
+ expect(1).toBe(1);
+ // expect(1).not.toBe(1);
+
+ expect(1).not.toBe(2);
+ expect(1).not.toBe("1");
+ expect("hello test").toBe("hello test");
+ expect("hello test").not.toBe("hello test2");
+ });
+
+ test("toHaveLength()", () => {
+ expect({ length: Number.MAX_SAFE_INTEGER }).toHaveLength(Number.MAX_SAFE_INTEGER);
+ expect("123").toHaveLength(3);
+ expect([1, 2, 3]).toHaveLength(3);
+ expect([1, 2, 3]).not.toHaveLength(2);
+ expect("123").not.toHaveLength(2);
+ expect({ length: 3 }).toHaveLength(3);
+ expect({ length: 3 }).not.toHaveLength(2);
+ expect({ length: 3 }).not.toHaveLength(Number.MAX_SAFE_INTEGER);
+ expect({ length: Number.MAX_SAFE_INTEGER }).not.toHaveLength(Number.MAX_SAFE_INTEGER - 1);
+ expect({ length: 3.3 }).not.toHaveLength(3);
+ expect("123").not.toHaveLength(-0);
+ });
+
+ if (isBun) {
+ test("toHaveLength() extended", () => {
+ // Headers
+ expect(new Headers()).toHaveLength(0);
+ expect(new Headers({ a: "1" })).toHaveLength(1);
+
+ // FormData
+ const form = new FormData();
+ expect(form).toHaveLength(0);
+ form.append("a", "1");
+ expect(form).toHaveLength(1);
+
+ // URLSearchParams
+ expect(new URLSearchParams()).toHaveLength(0);
+ expect(new URLSearchParams("a=1")).toHaveLength(1);
+ expect(new URLSearchParams([["a", "1"]])).toHaveLength(1);
+
+ // files
+ const thisFile = Bun.file(__filename);
+ const thisFileSize = thisFile.size;
+
+ expect(thisFile).toHaveLength(thisFileSize);
+ expect(thisFile).toHaveLength(Bun.file(__filename).size);
+
+ // empty file should have length 0
+ require("fs").writeFileSync("/tmp/empty.txt", "");
+ expect(Bun.file("/tmp/empty.txt")).toHaveLength(0);
+
+ // if a file doesn't exist, it should throw (not return 0 size)
+ expect(() => expect(Bun.file("/does-not-exist/file.txt")).toHaveLength(0)).toThrow();
+
+ // Blob
+ expect(new Blob([1, 2, 3])).toHaveLength(3);
+ expect(new Blob()).toHaveLength(0);
+
+ // Set
+ expect(new Set()).toHaveLength(0);
+ expect(new Set([1, 2, 3])).toHaveLength(3);
+
+ // Map
+ expect(new Map()).toHaveLength(0);
+ expect(new Map([["a", 1]])).toHaveLength(1);
+
+ // WeakMap
+ expect(new WeakMap([[globalThis, 1]])).toHaveLength(1);
+ });
+ }
+
+ test("toContain()", () => {
+ const s1 = new String("123");
+ expect(s1).not.toContain("12");
+ const s2 = "123";
+ expect(s2).toContain("12");
+
+ expect("test").toContain("es");
+ expect("test").toContain("est");
+ // expect("test").not.toContain("test");
+ expect(["test", "es"]).toContain("es");
+ expect("").toContain("");
+ expect([""]).toContain("");
+
+ expect(["lemon", "lime"]).not.toContain("orange");
+ expect("citrus fruits").toContain("fruit");
+
+ const a = new Uint16Array([1, 2, 3]);
+ expect(a).toContain(2);
+ expect(a).not.toContain(4);
+ expect([2, "2335", 5, true, false, null, undefined]).toContain(5);
+ expect([2, "2335", 5, true, false, null, undefined]).toContain("2335");
+ expect([2, "2335", 5, true, false, null, undefined]).toContain(true);
+ expect([2, "2335", 5, true, false, null, undefined]).toContain(false);
+ expect([2, "2335", 5, true, false, null, undefined]).toContain(null);
+ expect([2, "2335", 5, true, false, null, undefined]).toContain(undefined);
+ expect([2, "2335", 5, true, false, null, undefined]).not.toContain(3);
+
+ // expect([4, 5, 6]).not.toContain(5);
+
+ expect([]).not.toContain([]);
+ });
+
+ test("toBeTruthy()", () => {
+ expect("test").toBeTruthy();
+ expect(true).toBeTruthy();
+ expect(1).toBeTruthy();
+ expect({}).toBeTruthy();
+ expect([]).toBeTruthy();
+ expect(() => {}).toBeTruthy();
+ // expect(() => {}).not.toBeTruthy();
+ expect(0.5).toBeTruthy();
+ expect(new Map()).toBeTruthy();
+
+ expect("").not.toBeTruthy();
+ expect(0).not.toBeTruthy();
+ expect(-0).not.toBeTruthy();
+ expect(NaN).not.toBeTruthy();
+ expect(0n).not.toBeTruthy();
+ expect(0.0e1).not.toBeTruthy();
+ expect(false).not.toBeTruthy();
+ expect(null).not.toBeTruthy();
+ expect(undefined).not.toBeTruthy();
+ });
+
+ test("toBeUndefined()", () => {
+ expect(undefined).toBeUndefined();
+ expect(() => expect(undefined).not.toBeUndefined()).toThrow();
+ expect(null).not.toBeUndefined();
+ expect(0).not.toBeUndefined();
+ expect("hello defined").not.toBeUndefined();
+ });
+
+ test("toBeNull()", () => {
+ expect(null).toBeNull();
+ // expect(null).not.toBeNull();
+
+ expect(undefined).not.toBeNull();
+ expect(0).not.toBeNull();
+ expect("hello not null").not.toBeNull();
+ });
+
+ test("toBeDefined()", () => {
+ expect(0).toBeDefined();
+ expect("hello defined").toBeDefined();
+ expect(null).toBeDefined();
+ // expect(null).not.toBeDefined();
+
+ expect(undefined).not.toBeDefined();
+ });
+
+ test("toBeFalsy()", () => {
+ expect("").toBeFalsy();
+ expect(0).toBeFalsy();
+ expect(-0).toBeFalsy();
+ expect(NaN).toBeFalsy();
+ expect(0n).toBeFalsy();
+ expect(false).toBeFalsy();
+ expect(null).toBeFalsy();
+ expect(undefined).toBeFalsy();
+ expect(() => expect("").not.toBeFalsy()).toThrow();
+ expect(() => expect(0).not.toBeFalsy()).toThrow();
+ expect(() => expect(-0).not.toBeFalsy()).toThrow();
+ expect(() => expect(NaN).not.toBeFalsy()).toThrow();
+ expect(() => expect(0n).not.toBeFalsy()).toThrow();
+ expect(() => expect(false).not.toBeFalsy()).toThrow();
+ expect(() => expect(null).not.toBeFalsy()).toThrow();
+ expect(() => expect(undefined).not.toBeFalsy()).toThrow();
+
+ expect("hello not falsy").not.toBeFalsy();
+ expect(1).not.toBeFalsy();
+ expect(true).not.toBeFalsy();
+ expect({}).not.toBeFalsy();
+ expect([]).not.toBeFalsy();
+ expect(() => {}).not.toBeFalsy();
+ expect(() => expect("hello not falsy").toBeFalsy()).toThrow();
+ expect(() => expect(1).toBeFalsy()).toThrow();
+ expect(() => expect(true).toBeFalsy()).toThrow();
+ expect(() => expect({}).toBeFalsy()).toThrow();
+ expect(() => expect([]).toBeFalsy()).toThrow();
+ expect(() => expect(() => {}).toBeFalsy()).toThrow();
+ });
+
+ test("toBeGreaterThan()", () => {
+ expect(3n).toBeGreaterThan(2);
+ expect(Number.MAX_VALUE).not.toBeGreaterThan(Number.MAX_VALUE);
+ expect(1).not.toBeGreaterThan(BigInt(Number.MAX_VALUE));
+ expect(1).not.toBeGreaterThan(Number.MAX_SAFE_INTEGER);
+ expect(1).not.toBeGreaterThan(BigInt(Number.MAX_SAFE_INTEGER));
+ expect(Number.MAX_SAFE_INTEGER).not.toBeGreaterThan(Number.MAX_SAFE_INTEGER);
+ expect(BigInt(Number.MAX_SAFE_INTEGER)).not.toBeGreaterThan(BigInt(Number.MAX_SAFE_INTEGER));
+
+ expect(Infinity).toBeGreaterThan(-Infinity);
+ expect(-Infinity).not.toBeGreaterThan(Infinity);
+
+ expect(NaN).not.toBeGreaterThan(NaN);
+ expect(NaN).not.toBeGreaterThan(-Infinity);
+
+ expect(10).toBeGreaterThan(9);
+ expect(10).not.toBeGreaterThan(10);
+ expect(10).not.toBeGreaterThan(11);
+ expect(10).not.toBeGreaterThan(Infinity);
+ expect(10).toBeGreaterThan(-Infinity);
+ expect(10).not.toBeGreaterThan(NaN);
+ expect(10).toBeGreaterThan(0);
+ expect(10).toBeGreaterThan(-0);
+ expect(10).toBeGreaterThan(0.1);
+ expect(10).toBeGreaterThan(-0.1);
+ expect(10).toBeGreaterThan(0.9);
+ expect(10).toBeGreaterThan(-0.9);
+ expect(10).toBeGreaterThan(1);
+ expect(10).toBeGreaterThan(-1);
+ // switch the order
+ expect(9).not.toBeGreaterThan(10);
+ expect(10).not.toBeGreaterThan(10);
+ expect(11).toBeGreaterThan(10);
+ expect(Infinity).toBeGreaterThan(10);
+ expect(-Infinity).not.toBeGreaterThan(10);
+ expect(NaN).not.toBeGreaterThan(10);
+ expect(0).not.toBeGreaterThan(10);
+ expect(-0).not.toBeGreaterThan(10);
+ expect(0.1).not.toBeGreaterThan(10);
+ expect(-0.1).not.toBeGreaterThan(10);
+ expect(0.9).not.toBeGreaterThan(10);
+ expect(-0.9).not.toBeGreaterThan(10);
+ expect(1).not.toBeGreaterThan(10);
+ expect(-1).not.toBeGreaterThan(10);
+
+ // same tests but use bigints
+ expect(10n).toBeGreaterThan(9n);
+ expect(10n).not.toBeGreaterThan(10n);
+ expect(10n).not.toBeGreaterThan(11n);
+ expect(10n).not.toBeGreaterThan(Infinity);
+ expect(10n).toBeGreaterThan(-Infinity);
+ expect(10n).not.toBeGreaterThan(NaN);
+ expect(10n).toBeGreaterThan(0n);
+ expect(10n).toBeGreaterThan(-0n);
+ expect(10n).toBeGreaterThan(1n);
+ expect(10n).toBeGreaterThan(-1n);
+ // switch the order
+ expect(9n).not.toBeGreaterThan(10n);
+ expect(10n).not.toBeGreaterThan(10n);
+ expect(11n).toBeGreaterThan(10n);
+ expect(Infinity).toBeGreaterThan(10n);
+ expect(-Infinity).not.toBeGreaterThan(10n);
+ expect(NaN).not.toBeGreaterThan(10n);
+ expect(0n).not.toBeGreaterThan(10n);
+ expect(-0n).not.toBeGreaterThan(10n);
+ expect(1n).not.toBeGreaterThan(10n);
+ expect(-1n).not.toBeGreaterThan(10n);
+
+ // use bigints and numbers
+ expect(10n).toBeGreaterThan(9);
+ expect(10n).not.toBeGreaterThan(10);
+ expect(10n).not.toBeGreaterThan(11);
+ expect(10n).not.toBeGreaterThan(Infinity);
+ expect(10n).toBeGreaterThan(-Infinity);
+ expect(10n).not.toBeGreaterThan(NaN);
+ expect(10n).toBeGreaterThan(0);
+ expect(10n).toBeGreaterThan(-0);
+ expect(10n).toBeGreaterThan(0.1);
+ expect(10n).toBeGreaterThan(-0.1);
+ expect(10n).toBeGreaterThan(0.9);
+ expect(10n).toBeGreaterThan(-0.9);
+ expect(10n).toBeGreaterThan(1);
+ expect(10n).toBeGreaterThan(-1);
+ // switch the order
+ expect(9n).not.toBeGreaterThan(10);
+ expect(10n).not.toBeGreaterThan(10);
+ expect(11n).toBeGreaterThan(10);
+ expect(Infinity).toBeGreaterThan(10n);
+ expect(-Infinity).not.toBeGreaterThan(10n);
+ expect(NaN).not.toBeGreaterThan(10n);
+ expect(0n).not.toBeGreaterThan(10);
+ expect(-0n).not.toBeGreaterThan(10);
+ expect(1n).not.toBeGreaterThan(10);
+ expect(-1n).not.toBeGreaterThan(10);
+
+ expect(1n).not.toBeGreaterThan(1);
+ expect(1n).not.toBeGreaterThan(Number.MAX_SAFE_INTEGER);
+ expect(1n).not.toBeGreaterThan(Number.MAX_VALUE);
+ expect(1).not.toBeGreaterThan(1n);
+ expect(Number.MAX_SAFE_INTEGER).toBeGreaterThan(1n);
+ expect(Number.MAX_VALUE).toBeGreaterThan(1n);
+
+ expect(BigInt(Number.MAX_SAFE_INTEGER)).toBeGreaterThan(1n);
+ expect(BigInt(Number.MAX_VALUE)).toBeGreaterThan(1n);
+ expect(1n).not.toBeGreaterThan(BigInt(Number.MAX_SAFE_INTEGER));
+ expect(1n).not.toBeGreaterThan(BigInt(Number.MAX_VALUE));
+
+ expect(BigInt(Number.MAX_SAFE_INTEGER)).toBeGreaterThan(1);
+ expect(BigInt(Number.MAX_VALUE)).toBeGreaterThan(1);
+ expect(1).not.toBeGreaterThan(BigInt(Number.MAX_SAFE_INTEGER));
+ });
+
+ test("toBeGreaterThanOrEqual()", () => {
+ expect(Number.MAX_VALUE).toBeGreaterThanOrEqual(Number.MAX_VALUE);
+ expect(1).not.toBeGreaterThanOrEqual(Number.MAX_SAFE_INTEGER);
+ expect(1).not.toBeGreaterThanOrEqual(BigInt(Number.MAX_SAFE_INTEGER));
+ expect(1).not.toBeGreaterThanOrEqual(BigInt(Number.MAX_VALUE));
+ expect(Number.MAX_SAFE_INTEGER).toBeGreaterThanOrEqual(Number.MAX_SAFE_INTEGER);
+ expect(BigInt(Number.MAX_SAFE_INTEGER)).toBeGreaterThanOrEqual(BigInt(Number.MAX_SAFE_INTEGER));
+
+ expect(Infinity).toBeGreaterThanOrEqual(-Infinity);
+ expect(-Infinity).not.toBeGreaterThanOrEqual(Infinity);
+
+ expect(NaN).not.toBeGreaterThanOrEqual(NaN);
+ expect(NaN).not.toBeGreaterThanOrEqual(-Infinity);
+
+ expect(10).toBeGreaterThanOrEqual(9);
+ expect(10).toBeGreaterThanOrEqual(10);
+ expect(10).not.toBeGreaterThanOrEqual(11);
+ expect(10).not.toBeGreaterThanOrEqual(Infinity);
+ expect(10).toBeGreaterThanOrEqual(-Infinity);
+ expect(10).not.toBeGreaterThanOrEqual(NaN);
+ expect(10).toBeGreaterThanOrEqual(0);
+ expect(10).toBeGreaterThanOrEqual(-0);
+ expect(10).toBeGreaterThanOrEqual(0.1);
+ expect(10).toBeGreaterThanOrEqual(-0.1);
+ expect(10).toBeGreaterThanOrEqual(0.9);
+ expect(10).toBeGreaterThanOrEqual(-0.9);
+ expect(10).toBeGreaterThanOrEqual(1);
+ expect(10).toBeGreaterThanOrEqual(-1);
+ // switch the order
+ expect(9).not.toBeGreaterThanOrEqual(10);
+ expect(10).toBeGreaterThanOrEqual(10);
+ expect(11).toBeGreaterThanOrEqual(10);
+ expect(Infinity).toBeGreaterThanOrEqual(10);
+ expect(-Infinity).not.toBeGreaterThanOrEqual(10);
+ expect(NaN).not.toBeGreaterThanOrEqual(10);
+ expect(0).not.toBeGreaterThanOrEqual(10);
+ expect(-0).not.toBeGreaterThanOrEqual(10);
+ expect(0.1).not.toBeGreaterThanOrEqual(10);
+ expect(-0.1).not.toBeGreaterThanOrEqual(10);
+ expect(0.9).not.toBeGreaterThanOrEqual(10);
+ expect(-0.9).not.toBeGreaterThanOrEqual(10);
+ expect(1).not.toBeGreaterThanOrEqual(10);
+ expect(-1).not.toBeGreaterThanOrEqual(10);
+
+ // same tests but use bigints
+ expect(10n).toBeGreaterThanOrEqual(9n);
+ expect(10n).toBeGreaterThanOrEqual(10n);
+ expect(10n).not.toBeGreaterThanOrEqual(11n);
+ expect(10n).not.toBeGreaterThanOrEqual(Infinity);
+ expect(10n).toBeGreaterThanOrEqual(-Infinity);
+ expect(10n).not.toBeGreaterThanOrEqual(NaN);
+ expect(10n).toBeGreaterThanOrEqual(0n);
+ expect(10n).toBeGreaterThanOrEqual(-0n);
+ expect(10n).toBeGreaterThanOrEqual(1n);
+ expect(10n).toBeGreaterThanOrEqual(-1n);
+ // switch the order
+ expect(9n).not.toBeGreaterThanOrEqual(10n);
+ expect(10n).toBeGreaterThanOrEqual(10n);
+ expect(11n).toBeGreaterThanOrEqual(10n);
+ expect(Infinity).toBeGreaterThanOrEqual(10n);
+ expect(-Infinity).not.toBeGreaterThanOrEqual(10n);
+ expect(NaN).not.toBeGreaterThanOrEqual(10n);
+ expect(0n).not.toBeGreaterThanOrEqual(10n);
+ expect(-0n).not.toBeGreaterThanOrEqual(10n);
+ expect(1n).not.toBeGreaterThanOrEqual(10n);
+ expect(-1n).not.toBeGreaterThanOrEqual(10n);
+
+ // use bigints and numbers
+ expect(10n).toBeGreaterThanOrEqual(9);
+ expect(10n).toBeGreaterThanOrEqual(10);
+ expect(10n).not.toBeGreaterThanOrEqual(11);
+ expect(10n).not.toBeGreaterThanOrEqual(Infinity);
+ expect(10n).toBeGreaterThanOrEqual(-Infinity);
+ expect(10n).not.toBeGreaterThanOrEqual(NaN);
+ expect(10n).toBeGreaterThanOrEqual(0);
+ expect(10n).toBeGreaterThanOrEqual(-0);
+ expect(10n).toBeGreaterThanOrEqual(0.1);
+ expect(10n).toBeGreaterThanOrEqual(-0.1);
+ expect(10n).toBeGreaterThanOrEqual(0.9);
+ expect(10n).toBeGreaterThanOrEqual(-0.9);
+ expect(10n).toBeGreaterThanOrEqual(1);
+ expect(10n).toBeGreaterThanOrEqual(-1);
+ // switch the order
+ expect(9n).not.toBeGreaterThanOrEqual(10);
+ expect(10n).toBeGreaterThanOrEqual(10);
+ expect(11n).toBeGreaterThanOrEqual(10);
+ expect(Infinity).toBeGreaterThanOrEqual(10n);
+ expect(-Infinity).not.toBeGreaterThanOrEqual(10n);
+ expect(NaN).not.toBeGreaterThanOrEqual(10n);
+ expect(0n).not.toBeGreaterThanOrEqual(10);
+ expect(-0n).not.toBeGreaterThanOrEqual(10);
+ expect(1n).not.toBeGreaterThanOrEqual(10);
+ expect(-1n).not.toBeGreaterThanOrEqual(10);
+
+ expect(1n).toBeGreaterThanOrEqual(1);
+ expect(1n).not.toBeGreaterThanOrEqual(Number.MAX_SAFE_INTEGER);
+ expect(1n).not.toBeGreaterThanOrEqual(Number.MAX_VALUE);
+ expect(1).toBeGreaterThanOrEqual(1n);
+ expect(Number.MAX_SAFE_INTEGER).toBeGreaterThanOrEqual(1n);
+ expect(Number.MAX_VALUE).toBeGreaterThanOrEqual(1n);
+
+ expect(1).not.toBeGreaterThanOrEqual(BigInt(Number.MAX_VALUE));
+ });
+
+ test("toBeLessThan()", () => {
+ expect(3n).not.toBeLessThan(2);
+ expect(Number.MAX_VALUE).not.toBeLessThan(Number.MAX_VALUE);
+ expect(1).toBeLessThan(BigInt(Number.MAX_VALUE));
+ expect(1).toBeLessThan(Number.MAX_SAFE_INTEGER);
+ expect(1).toBeLessThan(BigInt(Number.MAX_SAFE_INTEGER));
+ expect(Number.MAX_SAFE_INTEGER).not.toBeLessThan(Number.MAX_SAFE_INTEGER);
+ expect(BigInt(Number.MAX_SAFE_INTEGER)).not.toBeLessThan(BigInt(Number.MAX_SAFE_INTEGER));
+
+ expect(Number.MAX_VALUE).not.toBeLessThan(BigInt(Number.MAX_VALUE));
+
+ expect(NaN).not.toBeLessThan(NaN);
+ expect(NaN).not.toBeLessThan(-Infinity);
+
+ expect(10).not.toBeLessThan(9);
+ expect(10).not.toBeLessThan(10);
+ expect(10).toBeLessThan(11);
+ expect(10).toBeLessThan(Infinity);
+ expect(10).not.toBeLessThan(-Infinity);
+ expect(10).not.toBeLessThan(NaN);
+ expect(10).not.toBeLessThan(0);
+ expect(10).not.toBeLessThan(-0);
+ expect(10).not.toBeLessThan(0.1);
+ expect(10).not.toBeLessThan(-0.1);
+ expect(10).not.toBeLessThan(0.9);
+ expect(10).not.toBeLessThan(-0.9);
+ expect(10).not.toBeLessThan(1);
+ expect(10).not.toBeLessThan(-1);
+ // switch the order
+ expect(9).toBeLessThan(10);
+ expect(10).not.toBeLessThan(10);
+ expect(11).not.toBeLessThan(10);
+ expect(Infinity).not.toBeLessThan(10);
+ expect(-Infinity).toBeLessThan(10);
+ expect(NaN).not.toBeLessThan(10);
+ expect(0).toBeLessThan(10);
+ expect(-0).toBeLessThan(10);
+ expect(0.1).toBeLessThan(10);
+ expect(-0.1).toBeLessThan(10);
+ expect(0.9).toBeLessThan(10);
+ expect(-0.9).toBeLessThan(10);
+ expect(1).toBeLessThan(10);
+ expect(-1).toBeLessThan(10);
+
+ // same tests but use bigints
+ expect(10n).not.toBeLessThan(9n);
+ expect(10n).not.toBeLessThan(10n);
+ expect(10n).toBeLessThan(11n);
+ expect(10n).toBeLessThan(Infinity);
+ expect(10n).not.toBeLessThan(-Infinity);
+ expect(10n).not.toBeLessThan(NaN);
+ expect(10n).not.toBeLessThan(0n);
+ expect(10n).not.toBeLessThan(-0n);
+ expect(10n).not.toBeLessThan(1n);
+ expect(10n).not.toBeLessThan(-1n);
+ // switch the order
+ expect(9n).toBeLessThan(10n);
+ expect(10n).not.toBeLessThan(10n);
+ expect(11n).not.toBeLessThan(10n);
+ expect(Infinity).not.toBeLessThan(10n);
+ expect(-Infinity).toBeLessThan(10n);
+ expect(NaN).not.toBeLessThan(10n);
+ expect(0n).toBeLessThan(10n);
+ expect(-0n).toBeLessThan(10n);
+ expect(1n).toBeLessThan(10n);
+ expect(-1n).toBeLessThan(10n);
+
+ // use bigints and numbers
+ expect(10n).not.toBeLessThan(9);
+ expect(10n).not.toBeLessThan(10);
+ expect(10n).toBeLessThan(11);
+ expect(10n).toBeLessThan(Infinity);
+ expect(10n).not.toBeLessThan(-Infinity);
+ expect(10n).not.toBeLessThan(NaN);
+ expect(10n).not.toBeLessThan(0);
+ expect(10n).not.toBeLessThan(-0);
+ expect(10n).not.toBeLessThan(0.1);
+ expect(10n).not.toBeLessThan(-0.1);
+ expect(10n).not.toBeLessThan(0.9);
+ expect(10n).not.toBeLessThan(-0.9);
+ expect(10n).not.toBeLessThan(1);
+ expect(10n).not.toBeLessThan(-1);
+ // switch the order
+ expect(9n).toBeLessThan(10);
+ expect(10n).not.toBeLessThan(10);
+ expect(11n).not.toBeLessThan(10);
+ expect(Infinity).not.toBeLessThan(10n);
+ expect(-Infinity).toBeLessThan(10n);
+ expect(NaN).not.toBeLessThan(10n);
+ expect(0n).toBeLessThan(10);
+ expect(-0n).toBeLessThan(10);
+ expect(1n).toBeLessThan(10);
+ expect(-1n).toBeLessThan(10);
+
+ expect(1n).not.toBeLessThan(1);
+ expect(1n).toBeLessThan(Number.MAX_SAFE_INTEGER);
+ expect(1n).toBeLessThan(Number.MAX_VALUE);
+ expect(1).not.toBeLessThan(1n);
+ expect(Number.MAX_SAFE_INTEGER).not.toBeLessThan(1n);
+ expect(Number.MAX_VALUE).not.toBeLessThan(1n);
+
+ expect(BigInt(Number.MAX_SAFE_INTEGER)).not.toBeLessThan(1n);
+ expect(BigInt(Number.MAX_VALUE)).not.toBeLessThan(1n);
+ expect(1n).toBeLessThan(BigInt(Number.MAX_SAFE_INTEGER));
+ expect(1n).toBeLessThan(BigInt(Number.MAX_VALUE));
+
+ expect(BigInt(Number.MAX_SAFE_INTEGER)).not.toBeLessThan(1);
+ expect(BigInt(Number.MAX_VALUE)).not.toBeLessThan(1);
+ expect(1).toBeLessThan(BigInt(Number.MAX_SAFE_INTEGER));
+ });
+
+ test("toBeLessThanOrEqual()", () => {
+ expect(3n).not.toBeLessThanOrEqual(2);
+ expect(Number.MAX_VALUE).toBeLessThanOrEqual(Number.MAX_VALUE);
+ expect(1).toBeLessThanOrEqual(BigInt(Number.MAX_VALUE));
+ expect(1).toBeLessThanOrEqual(Number.MAX_SAFE_INTEGER);
+ expect(1).toBeLessThanOrEqual(BigInt(Number.MAX_SAFE_INTEGER));
+ expect(Number.MAX_SAFE_INTEGER).toBeLessThanOrEqual(Number.MAX_SAFE_INTEGER);
+ expect(BigInt(Number.MAX_SAFE_INTEGER)).toBeLessThanOrEqual(BigInt(Number.MAX_SAFE_INTEGER));
+
+ expect(Number.MAX_VALUE).toBeLessThanOrEqual(BigInt(Number.MAX_VALUE));
+ expect(BigInt(Number.MAX_VALUE)).toBeLessThanOrEqual(Number.MAX_VALUE);
+
+ expect(NaN).not.toBeLessThanOrEqual(NaN);
+ expect(NaN).not.toBeLessThanOrEqual(-Infinity);
+
+ expect(10).not.toBeLessThanOrEqual(9);
+ expect(10).toBeLessThanOrEqual(10);
+ expect(10).toBeLessThanOrEqual(11);
+ expect(10).toBeLessThanOrEqual(Infinity);
+ expect(10).not.toBeLessThanOrEqual(-Infinity);
+ expect(10).not.toBeLessThanOrEqual(NaN);
+ expect(10).not.toBeLessThanOrEqual(0);
+ expect(10).not.toBeLessThanOrEqual(-0);
+ expect(10).not.toBeLessThanOrEqual(0.1);
+ expect(10).not.toBeLessThanOrEqual(-0.1);
+ expect(10).not.toBeLessThanOrEqual(0.9);
+ expect(10).not.toBeLessThanOrEqual(-0.9);
+ expect(10).not.toBeLessThanOrEqual(1);
+ expect(10).not.toBeLessThanOrEqual(-1);
+ // switch the order
+ expect(9).toBeLessThanOrEqual(10);
+ expect(10).toBeLessThanOrEqual(10);
+ expect(11).not.toBeLessThanOrEqual(10);
+ expect(Infinity).not.toBeLessThanOrEqual(10);
+ expect(-Infinity).toBeLessThanOrEqual(10);
+ expect(NaN).not.toBeLessThanOrEqual(10);
+ expect(0).toBeLessThanOrEqual(10);
+ expect(-0).toBeLessThanOrEqual(10);
+ expect(0.1).toBeLessThanOrEqual(10);
+ expect(-0.1).toBeLessThanOrEqual(10);
+ expect(0.9).toBeLessThanOrEqual(10);
+ expect(-0.9).toBeLessThanOrEqual(10);
+ expect(1).toBeLessThanOrEqual(10);
+ expect(-1).toBeLessThanOrEqual(10);
+
+ // same tests but use bigints
+ expect(10n).not.toBeLessThanOrEqual(9n);
+ expect(10n).toBeLessThanOrEqual(10n);
+ expect(10n).toBeLessThanOrEqual(11n);
+ expect(10n).toBeLessThanOrEqual(Infinity);
+ expect(10n).not.toBeLessThanOrEqual(-Infinity);
+ expect(10n).not.toBeLessThanOrEqual(NaN);
+ expect(10n).not.toBeLessThanOrEqual(0n);
+ expect(10n).not.toBeLessThanOrEqual(-0n);
+ expect(10n).not.toBeLessThanOrEqual(1n);
+ expect(10n).not.toBeLessThanOrEqual(-1n);
+ // switch the order
+ expect(9n).toBeLessThanOrEqual(10n);
+ expect(10n).toBeLessThanOrEqual(10n);
+ expect(11n).not.toBeLessThanOrEqual(10n);
+ expect(Infinity).not.toBeLessThanOrEqual(10n);
+ expect(-Infinity).toBeLessThanOrEqual(10n);
+ expect(NaN).not.toBeLessThanOrEqual(10n);
+ expect(0n).toBeLessThanOrEqual(10n);
+ expect(-0n).toBeLessThanOrEqual(10n);
+ expect(1n).toBeLessThanOrEqual(10n);
+ expect(-1n).toBeLessThanOrEqual(10n);
+
+ // use bigints and numbers
+ expect(10n).not.toBeLessThanOrEqual(9);
+ expect(10n).toBeLessThanOrEqual(10);
+ expect(10n).toBeLessThanOrEqual(11);
+ expect(10n).toBeLessThanOrEqual(Infinity);
+ expect(10n).not.toBeLessThanOrEqual(-Infinity);
+ expect(10n).not.toBeLessThanOrEqual(NaN);
+ expect(10n).not.toBeLessThanOrEqual(0);
+ expect(10n).not.toBeLessThanOrEqual(-0);
+ expect(10n).not.toBeLessThanOrEqual(0.1);
+ expect(10n).not.toBeLessThanOrEqual(-0.1);
+ expect(10n).not.toBeLessThanOrEqual(0.9);
+ expect(10n).not.toBeLessThanOrEqual(-0.9);
+ expect(10n).not.toBeLessThanOrEqual(1);
+ expect(10n).not.toBeLessThanOrEqual(-1);
+ // switch the order
+ expect(9n).toBeLessThanOrEqual(10);
+ expect(10n).toBeLessThanOrEqual(10);
+ expect(11n).not.toBeLessThanOrEqual(10);
+ expect(Infinity).not.toBeLessThanOrEqual(10n);
+ expect(-Infinity).toBeLessThanOrEqual(10n);
+ expect(NaN).not.toBeLessThanOrEqual(10n);
+ expect(0n).toBeLessThanOrEqual(10);
+ expect(-0n).toBeLessThanOrEqual(10);
+ expect(1n).toBeLessThanOrEqual(10);
+ expect(-1n).toBeLessThanOrEqual(10);
+
+ expect(1n).toBeLessThanOrEqual(1);
+ expect(1n).toBeLessThanOrEqual(Number.MAX_SAFE_INTEGER);
+ expect(1n).toBeLessThanOrEqual(Number.MAX_VALUE);
+ expect(1).toBeLessThanOrEqual(1n);
+ expect(Number.MAX_SAFE_INTEGER).not.toBeLessThanOrEqual(1n);
+ expect(Number.MAX_VALUE).not.toBeLessThanOrEqual(1n);
+
+ expect(BigInt(Number.MAX_SAFE_INTEGER)).not.toBeLessThanOrEqual(1n);
+ expect(BigInt(Number.MAX_VALUE)).not.toBeLessThanOrEqual(1n);
+ expect(1n).toBeLessThanOrEqual(BigInt(Number.MAX_SAFE_INTEGER));
+ expect(1n).toBeLessThanOrEqual(BigInt(Number.MAX_VALUE));
+
+ expect(BigInt(Number.MAX_SAFE_INTEGER)).not.toBeLessThanOrEqual(1);
+ expect(BigInt(Number.MAX_VALUE)).not.toBeLessThanOrEqual(1);
+ expect(1).toBeLessThanOrEqual(BigInt(Number.MAX_SAFE_INTEGER));
+ });
+
+ describe("toMatchObject", () => {
+ if (isBun) {
+ test("with Bun.deepMatch", () => {
+ expect(Bun.deepMatch({ a: 1, b: 2 }, { a: 1 })).toBe(false);
+ expect(Bun.deepMatch({ a: 1 }, { a: 1, b: 2 })).toBe(true);
+ });
+ }
+ test("with expect matcher", () => {
+ const f = Symbol.for("foo");
+ const b = Symbol.for("bar");
+
+ class Number2 extends Number {
+ constructor(value) {
+ super(value);
+ }
+ }
+ class Number3 extends Number2 {
+ constructor(value) {
+ super(value);
+ }
+ }
+
+ class Boolean2 extends Boolean {
+ constructor(value) {
+ super(value);
+ }
+ }
+ expect({ [f]: 2 }).toMatchObject({ [f]: 2 });
+ expect({ [f]: 2 }).toMatchObject({ [f]: expect.anything() });
+ expect({ [f]: new Date() }).toMatchObject({ [f]: expect.any(Date) });
+ expect({ [f]: new Date() }).not.toMatchObject({ [f]: expect.any(RegExp) });
+ expect({ [f]: 3 }).not.toMatchObject({ [f]: 5 });
+ expect({ [f]: 3 }).not.toMatchObject({ [b]: 3 });
+ expect({}).toMatchObject({});
+ expect([5]).toMatchObject([5]);
+ expect([5]).not.toMatchObject([4]);
+ expect(() => {
+ expect({}).toMatchObject();
+ }).toThrow();
+ expect(() => {
+ expect(true).toMatchObject(true);
+ }).toThrow();
+ expect(() => {
+ expect(true).toMatchObject(true);
+ }).toThrow();
+ expect(() => {
+ expect(1).toMatchObject(1);
+ }).toThrow();
+ expect(() => {
+ expect("a").toMatchObject("a");
+ }).toThrow();
+ expect(() => {
+ expect(null).toMatchObject(null);
+ }).toThrow();
+ expect(() => {
+ expect(undefined).toMatchObject(undefined);
+ }).toThrow();
+ expect(() => {
+ expect(Symbol()).toMatchObject(Symbol());
+ }).toThrow();
+ expect(() => {
+ expect(BigInt(1)).toMatchObject(BigInt(1));
+ }).toThrow();
+ expect([]).toMatchObject([]);
+ expect([1]).toMatchObject([1]);
+ expect([1, 2]).toMatchObject([1, 2]);
+ expect(() => {
+ expect([1]).toMatchObject([1, 2]);
+ }).toThrow();
+ expect(() => {
+ expect([1, 2]).toMatchObject([1]);
+ }).toThrow();
+ expect([]).toMatchObject({});
+ expect([1]).toMatchObject({});
+ expect([1, 2]).toMatchObject({ 0: 1, 1: 2 });
+ expect([1, 2]).not.toMatchObject({ 0: 2 });
+ expect(() => {
+ expect({}).toMatchObject([]);
+ }).toThrow();
+ expect({ a: 1 }).toMatchObject({});
+ expect({ a: 1 }).toMatchObject({ a: expect.anything() });
+ expect({ a: 1, b: 2 }).toMatchObject({ a: 1 });
+ expect({ a: 1, b: 2 }).toMatchObject({ a: 1, b: 2 });
+ expect({ a: 1, b: 2 }).toMatchObject({ b: 2 });
+ expect({ a: 1, b: 2 }).toMatchObject({ b: 2, a: 1 });
+ expect({ a: 1, b: 2 }).toMatchObject({ a: 1, b: 2 });
+ expect({}).not.toMatchObject({ a: 1 });
+ expect({ a: 89 }).not.toMatchObject({ b: 90 });
+ expect({ a: 1, b: 2 }).not.toMatchObject({ a: 1, b: 3 });
+ expect({ a: 1, b: 2 }).not.toMatchObject({ a: 1, b: 2, c: 4 });
+ expect({ a: new Date(), b: "jj" }).not.toMatchObject({ b: expect.any(Number) });
+ expect({ a: "123" }).not.toMatchObject({ a: expect.stringContaining("4") });
+ class DString extends String {
+ constructor(str) {
+ super(str);
+ }
+ }
+ expect({ a: "hello world" }).toMatchObject({ a: expect.stringContaining("wor") });
+ expect({ a: "hello world" }).not.toMatchObject({ a: expect.stringContaining("wol") });
+ expect({ a: "hello String" }).toMatchObject({ a: expect.stringContaining(new String("Str")) });
+ expect({ a: "hello String" }).not.toMatchObject({ a: expect.stringContaining(new String("Strs")) });
+ expect({ a: "hello derived String" }).toMatchObject({ a: expect.stringContaining(new DString("riv")) });
+ expect({ a: "hello derived String" }).not.toMatchObject({ a: expect.stringContaining(new DString("rivd")) });
+ expect({ a: "hello world" }).toMatchObject({ a: expect.stringMatching("wor") });
+ expect({ a: "hello world" }).not.toMatchObject({ a: expect.stringMatching("word") });
+ expect({ a: "hello world" }).toMatchObject({ a: "hello world" });
+ expect({ a: "hello world" }).toMatchObject({ a: expect.stringMatching(/wor/) });
+ expect({ a: "hello world" }).not.toMatchObject({ a: expect.stringMatching(/word/) });
+ expect({ a: expect.stringMatching("wor") }).toMatchObject({ a: "hello world" });
+ expect({ a: expect.stringMatching("word") }).not.toMatchObject({ a: "hello world" });
+ expect({ a: expect.stringMatching(/wor/) }).toMatchObject({ a: "hello world" });
+ expect({ a: expect.stringMatching(/word/) }).not.toMatchObject({ a: "hello world" });
+ expect({ a: expect.stringMatching(/word/) }).toMatchObject({ a: "hello word" });
+ expect({ a: [1, 2, 3] }).toMatchObject({ a: [1, 2, 3] });
+ expect({ a: [1, 2, 3] }).toMatchObject({ a: [1, 2, 3] });
+ expect({ a: [1, 2, 4] }).not.toMatchObject({ a: [1, 2, 3] });
+
+ expect([]).toMatchObject([]);
+ expect([]).toMatchObject({});
+ expect({}).not.toMatchObject([]);
+ expect({ a: 1 }).toMatchObject({});
+ expect({ a: 1 }).toMatchObject({ a: 1 });
+
+ expect({ a: 1 }).toMatchObject({ a: expect.anything() });
+ expect({ a: null }).not.toMatchObject({ a: expect.anything() });
+ expect({ a: undefined }).not.toMatchObject({ a: expect.anything() });
+
+ expect({ a: new Date() }).toMatchObject({ a: expect.any(Date) });
+ expect({ a: new Date() }).not.toMatchObject({ a: expect.any(RegExp) });
+ expect({ a: new RegExp("a", "g") }).toMatchObject({ a: expect.any(RegExp) });
+ expect({ a: /a/g }).toMatchObject({ a: expect.any(RegExp) });
+
+ expect({
+ first: new Boolean2(false),
+ a: {
+ 4: [3, 2, 2],
+ j: new Date(),
+ b: {
+ c: {
+ num: 1,
+ d: {
+ e: {
+ bigint: 123n,
+ f: {
+ g: {
+ h: {
+ i: new Number3(2),
+ bool: true,
+ },
+ compare: "compare",
+ },
+ },
+ ignore1: 234,
+ ignore2: {
+ ignore3: 23421,
+ ignore4: {
+ ignore5: {
+ ignore6: "hello",
+ ignore7: "done",
+ },
+ },
+ },
+ },
+ },
+ string1: "hello",
+ string2: "hello",
+ string3: "hello",
+ },
+ },
+ },
+ }).toMatchObject({
+ first: expect.any(Boolean2),
+ a: {
+ 4: [3, 2, expect.any(Number)],
+
+ j: expect.any(Date),
+ b: {
+ c: {
+ num: expect.any(Number),
+ string1: expect.anything(),
+ string2: expect.stringContaining("ll"),
+ string3: expect.stringMatching(/ll/),
+ d: {
+ e: {
+ bigint: expect.any(BigInt),
+ f: {
+ g: {
+ compare: "compare",
+ h: {
+ i: expect.any(Number3),
+ bool: expect.any(Boolean),
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ });
+
+ var a1 = [1];
+ a1[f] = 99;
+ expect(a1).not.toMatchObject([1]);
+ expect([1]).not.toMatchObject(a1);
+ expect({ 1: 1 }).not.toMatchObject(a1);
+ expect(a1).not.toMatchObject({ 1: 1 });
+ expect(a1).toMatchObject(a1);
+ });
+ });
+
+ describe("toMatch()", () => {
+ const tests = [
+ {
+ label: "reguler expression",
+ value: "123",
+ matched: /123/,
+ },
+ {
+ label: "reguler expression object",
+ value: "123",
+ matched: new RegExp("123"),
+ },
+ {
+ label: "substring",
+ value: "123",
+ matched: "12",
+ },
+ {
+ label: "substring emojis",
+ value: "👍👎",
+ matched: "👍",
+ },
+ {
+ label: "substring UTF-16",
+ value: "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 ☺️ 😊 😇 🙂",
+ matched: "🥲 ☺️ 😊",
+ },
+ ];
+ for (const { label, value, matched } of tests) {
+ test(label, () => expect(value).toMatch(matched));
+ }
+ });
+
+ test("toBeNaN()", () => {
+ expect(NaN).toBeNaN();
+ expect(() => expect(NaN).not.toBeNaN()).toThrow();
+ expect(0).not.toBeNaN();
+ expect("hello not NaN").not.toBeNaN();
+ });
+
+ describe("toBeEmpty()", () => {
+ const values = [
+ "",
+ [],
+ {},
+ new Set(),
+ new Map(),
+ new String(),
+ new Array(),
+ new Uint8Array(),
+ new Object(),
+ Buffer.from(""),
+ ...(isBun ? [Bun.file("/tmp/empty.txt")] : []),
+ new Headers(),
+ new URLSearchParams(),
+ new FormData(),
+ (function* () {})(),
+ ];
+ for (const value of values) {
+ test(label(value), () => {
+ if (value && typeof value === "object" && value instanceof Blob) {
+ require("fs").writeFileSync("/tmp/empty.txt", "");
+ }
+
+ expect(value).toBeEmpty();
+ });
+ }
+ });
+
+ describe("not.toBeEmpty()", () => {
+ const values = [
+ " ",
+ [""],
+ [undefined],
+ { "": "" },
+ new Set([""]),
+ new Map([["", ""]]),
+ new String(" "),
+ new Array(1),
+ new Uint8Array(1),
+ Buffer.from(" "),
+ ...(isBun ? [Bun.file(__filename)] : []),
+ new Headers({
+ a: "b",
+ c: "d",
+ }),
+ new URL("https://example.com?d=e&f=g").searchParams,
+ (() => {
+ var a = new FormData();
+ a.append("a", "b");
+ a.append("c", "d");
+ return a;
+ })(),
+ (function* () {
+ yield "123";
+ })(),
+ ];
+ for (const value of values) {
+ test(label(value), () => {
+ expect(value).not.toBeEmpty();
+ });
+ }
+ });
+
+ test("toBeNil()", () => {
+ expect(null).toBeNil();
+ expect(undefined).toBeNil();
+ expect(false).not.toBeNil();
+ expect(0).not.toBeNil();
+ expect("").not.toBeNil();
+ expect([]).not.toBeNil();
+ expect(true).not.toBeNil();
+ expect({}).not.toBeNil();
+ });
+
+ test("toBeArray()", () => {
+ expect([]).toBeArray();
+ expect([1, 2, 3, "🫓"]).toBeArray();
+ expect(new Array()).toBeArray();
+ expect(new Array(1, 2, 3)).toBeArray();
+ expect({}).not.toBeArray();
+ expect("🫓").not.toBeArray();
+ expect(0).not.toBeArray();
+ expect(true).not.toBeArray();
+ expect(null).not.toBeArray();
+ });
+
+ test("toBeArrayOfSize()", () => {
+ expect([]).toBeArrayOfSize(0);
+ expect(new Array()).toBeArrayOfSize(0);
+ expect([1, 2, 3, "🫓"]).toBeArrayOfSize(4);
+ expect((new Array() < string) | (number > (1, 2, 3, "🫓"))).toBeArrayOfSize(4);
+ expect({}).not.toBeArrayOfSize(1);
+ expect("").not.toBeArrayOfSize(1);
+ expect(0).not.toBeArrayOfSize(1);
+ });
+
+ test("toBeTypeOf()", () => {
+ expect("Bun! 🫓").toBeTypeOf("string");
+ expect(0).toBeTypeOf("number");
+ expect(true).toBeTypeOf("boolean");
+ expect([]).toBeTypeOf("object");
+ expect({}).toBeTypeOf("object");
+ expect(null).toBeTypeOf("object");
+ expect(undefined).toBeTypeOf("undefined");
+ expect(() => {}).toBeTypeOf("function");
+ expect(function () {}).toBeTypeOf("function");
+ expect(async () => {}).toBeTypeOf("function");
+ expect(async function () {}).toBeTypeOf("function");
+ expect(function* () {}).toBeTypeOf("function");
+ expect(class {}).toBeTypeOf("function");
+ expect(new Array()).toBeTypeOf("object");
+ expect(BigInt(5)).toBeTypeOf("bigint");
+ expect(/(foo|bar)/g).toBeTypeOf("object");
+ expect(new RegExp("(foo|bar)", "g")).toBeTypeOf("object");
+ expect(new Date()).toBeTypeOf("object");
+
+ expect("Bun!").not.toBeTypeOf("number");
+ expect(0).not.toBeTypeOf("string");
+ expect(true).not.toBeTypeOf("number");
+ expect([]).not.toBeTypeOf("string");
+ expect({}).not.toBeTypeOf("number");
+ expect(null).not.toBeTypeOf("string");
+ expect(undefined).not.toBeTypeOf("boolean");
+ expect(() => {}).not.toBeTypeOf("string");
+ expect(function () {}).not.toBeTypeOf("boolean");
+ expect(async () => {}).not.toBeTypeOf("object");
+ expect(class {}).not.toBeTypeOf("bigint");
+ expect(/(foo|bar)/g).not.toBeTypeOf("string");
+ expect(new RegExp("(foo|bar)", "g")).not.toBeTypeOf("number");
+ expect(new Date()).not.toBeTypeOf("string");
+ });
+
+ test("toBeBoolean()", () => {
+ expect(true).toBeBoolean();
+ expect(false).toBeBoolean();
+ expect(0).not.toBeBoolean();
+ expect(1).not.toBeBoolean();
+ expect("").not.toBeBoolean();
+ expect({}).not.toBeBoolean();
+ });
+
+ test("toBeTrue()", () => {
+ expect(true).toBeTrue();
+ expect(false).not.toBeTrue();
+ expect(0).not.toBeTrue();
+ expect(1).not.toBeTrue();
+ expect("").not.toBeTrue();
+ expect({}).not.toBeTrue();
+ });
+
+ test("toBeFalse()", () => {
+ expect(false).toBeFalse();
+ expect(true).not.toBeFalse();
+ expect(0).not.toBeFalse();
+ expect(1).not.toBeFalse();
+ expect("").not.toBeFalse();
+ expect({}).not.toBeFalse();
+ });
+
+ test("toBeNumber()", () => {
+ expect(0).toBeNumber();
+ expect(1).toBeNumber();
+ expect(1.23).toBeNumber();
+ expect(Infinity).toBeNumber();
+ expect(-Infinity).toBeNumber();
+ expect(NaN).toBeNumber();
+ expect("").not.toBeNumber();
+ expect({}).not.toBeNumber();
+ });
+
+ test("toBeInteger()", () => {
+ expect(0).toBeInteger();
+ expect(1).toBeInteger();
+ expect(1.23).not.toBeInteger();
+ expect(Infinity).not.toBeInteger();
+ expect(-Infinity).not.toBeInteger();
+ expect(NaN).not.toBeInteger();
+ expect("").not.toBeInteger();
+ expect({}).not.toBeInteger();
+ });
+
+ test("toBeFinite()", () => {
+ expect(0).toBeFinite();
+ expect(1).toBeFinite();
+ expect(1.23).toBeFinite();
+ expect(Infinity).not.toBeFinite();
+ expect(-Infinity).not.toBeFinite();
+ expect(NaN).not.toBeFinite();
+ expect("").not.toBeFinite();
+ expect({}).not.toBeFinite();
+ });
+
+ test("toBePositive()", () => {
+ expect(1).toBePositive();
+ expect(1.23).toBePositive();
+ expect(Infinity).not.toBePositive();
+ expect(0).not.toBePositive();
+ expect(-Infinity).not.toBePositive();
+ expect(NaN).not.toBePositive();
+ expect("").not.toBePositive();
+ expect({}).not.toBePositive();
+ });
+
+ test("toBeNegative()", () => {
+ expect(-1).toBeNegative();
+ expect(-1.23).toBeNegative();
+ expect(-Infinity).not.toBeNegative();
+ expect(0).not.toBeNegative();
+ expect(Infinity).not.toBeNegative();
+ expect(NaN).not.toBeNegative();
+ expect("").not.toBeNegative();
+ expect({}).not.toBeNegative();
+ });
+
+ test("toBeWithin()", () => {
+ expect(0).toBeWithin(0, 1);
+ expect(3.14).toBeWithin(3, 3.141);
+ expect(-25).toBeWithin(-100, 0);
+ expect(0).not.toBeWithin(1, 2);
+ expect(3.14).not.toBeWithin(3.1, 3.14);
+ expect(99).not.toBeWithin(99, 99);
+ expect(100).not.toBeWithin(99, 100);
+ expect(NaN).not.toBeWithin(0, 1);
+ // expect("").not.toBeWithin(0, 1);
+ expect({}).not.toBeWithin(0, 1);
+ expect(Infinity).not.toBeWithin(-Infinity, Infinity);
+ });
+
+ test("toBeSymbol()", () => {
+ expect(Symbol()).toBeSymbol();
+ expect(Symbol("")).toBeSymbol();
+ expect(Symbol.iterator).toBeSymbol();
+ expect("").not.toBeSymbol();
+ expect({}).not.toBeSymbol();
+ });
+
+ test("toBeFunction()", () => {
+ expect(() => {}).toBeFunction();
+ expect(function () {}).toBeFunction();
+ expect(async function () {}).toBeFunction();
+ expect(async () => {}).toBeFunction();
+ expect(function* () {}).toBeFunction();
+ expect(async function* () {}).toBeFunction();
+ expect("").not.toBeFunction();
+ expect({}).not.toBeFunction();
+ expect(null).not.toBeFunction();
+ });
+
+ test("toBeDate()", () => {
+ expect(new Date()).toBeDate();
+ expect(new Date(0)).toBeDate();
+ expect(new Date("2021-01-01")).toBeDate();
+ expect("2021-01-01").not.toBeDate();
+ expect({}).not.toBeDate();
+ expect(null).not.toBeDate();
+ });
+
+ test.todo("toBeValidDate()", () => {
+ expect(new Date()).toBeValidDate();
+ expect(new Date(-1)).toBeValidDate();
+ expect("2021-01-01").not.toBeValidDate();
+ expect({}).not.toBeValidDate();
+ expect(null).not.toBeValidDate();
+ });
+
+ test("toBeString()", () => {
+ expect("").toBeString();
+ expect("123").toBeString();
+ expect(new String()).toBeString();
+ expect(new String("123")).toBeString();
+ expect(123).not.toBeString();
+ expect({}).not.toBeString();
+ });
+
+ test("toInclude()", () => {
+ expect("123").toInclude("1");
+ expect("abc").toInclude("abc");
+ expect(" 123 ").toInclude(" ");
+ expect("").toInclude("");
+ expect("bob").not.toInclude("alice");
+ });
+
+ test("toStartWith()", () => {
+ expect("123").toStartWith("1");
+ expect("abc").toStartWith("abc");
+ expect(" 123 ").toStartWith(" ");
+ expect(" ").toStartWith("");
+ expect("").toStartWith("");
+ expect("bob").not.toStartWith("alice");
+ });
+
+ test("toEndWith()", () => {
+ expect("123").toEndWith("3");
+ expect("abc").toEndWith("abc");
+ expect(" 123 ").toEndWith(" ");
+ expect(" ").toEndWith("");
+ expect("").toEndWith("");
+ expect("bob").not.toEndWith("alice");
+ });
+});
diff --git a/test/js/bun/test/expect.test.ts b/test/js/bun/test/expect.test.ts
deleted file mode 100644
index a511174ff..000000000
--- a/test/js/bun/test/expect.test.ts
+++ /dev/null
@@ -1,442 +0,0 @@
-import { inspect } from "bun";
-import { describe, test, expect } from "bun:test";
-
-describe("expect()", () => {
- describe("toBeInstanceOf()", () => {
- class Animal {}
- class Dog extends Animal {}
- const tests = [
- {
- label: "string",
- value: new String(""),
- instanceOf: String,
- },
- {
- label: "number",
- value: new Number(1),
- instanceOf: Number,
- },
- {
- label: "object",
- value: {},
- instanceOf: Object,
- },
- {
- label: "function",
- value: () => {},
- instanceOf: Function,
- },
- {
- label: "Class",
- value: new Animal(),
- instanceOf: Animal,
- },
- {
- label: "extends Class",
- value: new Dog(),
- instanceOf: Dog,
- },
- {
- label: "super Class",
- value: new Dog(),
- instanceOf: Animal,
- },
- ];
- for (const { label, value, instanceOf } of tests) {
- test(label, () => expect(value).toBeInstanceOf(instanceOf));
- }
- });
-
- describe("toMatch()", () => {
- const tests = [
- {
- label: "reguler expression",
- value: "123",
- matched: /123/,
- },
- {
- label: "reguler expression object",
- value: "123",
- matched: new RegExp("123"),
- },
- {
- label: "substring",
- value: "123",
- matched: "12",
- },
- {
- label: "substring emojis",
- value: "👍👎",
- matched: "👍",
- },
- {
- label: "substring UTF-16",
- value: "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 ☺️ 😊 😇 🙂",
- matched: "🥲 ☺️ 😊",
- },
- ];
- for (const { label, value, matched } of tests) {
- test(label, () => expect(value).toMatch(matched));
- }
- });
-
- describe("toBeCloseTo()", () => {
- const passTests = [
- [0, 0],
- [0, 0.001],
- [1.23, 1.229],
- [1.23, 1.226],
- [1.23, 1.225],
- [1.23, 1.234],
- [Infinity, Infinity],
- [-Infinity, -Infinity],
- [0, 0.1, 0],
- [0, 0.0001, 3],
- [0, 0.000004, 5],
- [2.0000002, 2, 5],
- ];
- for (const [actual, expected, precision] of passTests) {
- if (precision === undefined) {
- test(`actual = ${actual}, expected = ${expected}`, () => {
- expect(actual).toBeCloseTo(expected);
- });
- } else {
- test(`actual = ${actual}, expected = ${expected}, precision = ${precision}`, () => {
- expect(actual).toBeCloseTo(expected, precision);
- });
- }
- }
- const failTests = [
- [0, 0.01],
- [1, 1.23],
- [1.23, 1.2249999],
- [Infinity, -Infinity],
- [Infinity, 1.23],
- [-Infinity, -1.23],
- [3.141592e-7, 3e-7, 8],
- [56789, 51234, -4],
- ];
- for (const [actual, expected, precision] of failTests) {
- if (precision === undefined) {
- test(`actual = ${actual}, expected != ${expected}`, () => {
- expect(actual).not.toBeCloseTo(expected);
- });
- } else {
- test(`actual = ${actual}, expected != ${expected}, precision = ${precision}`, () => {
- expect(actual).not.toBeCloseTo(expected, precision);
- });
- }
- }
- });
-
- describe("toBeEmpty()", () => {
- const values = [
- "",
- [],
- {},
- new Set(),
- new Map(),
- new String(),
- new Array(),
- new Uint8Array(),
- new Object(),
- Buffer.from(""),
- Bun.file("/tmp/empty.txt"),
- new Headers(),
- new URLSearchParams(),
- new FormData(),
- (function* () {})(),
- ];
- for (const value of values) {
- test(label(value), () => {
- if (value && typeof value === "object" && value instanceof Blob) {
- require("fs").writeFileSync("/tmp/empty.txt", "");
- }
-
- expect(value).toBeEmpty();
- });
- }
- });
-
- describe("not.toBeEmpty()", () => {
- const values = [
- " ",
- [""],
- [undefined],
- { "": "" },
- new Set([""]),
- new Map([["", ""]]),
- new String(" "),
- new Array(1),
- new Uint8Array(1),
- Buffer.from(" "),
- Bun.file(import.meta.path),
- new Headers({
- a: "b",
- c: "d",
- }),
- new URL("https://example.com?d=e&f=g").searchParams,
- (() => {
- var a = new FormData();
- a.append("a", "b");
- a.append("c", "d");
- return a;
- })(),
- (function* () {
- yield "123";
- })(),
- ];
- for (const value of values) {
- test(label(value), () => {
- expect(value).not.toBeEmpty();
- });
- }
- });
-
- test("toBeNil()", () => {
- expect(null).toBeNil();
- expect(undefined).toBeNil();
- expect(false).not.toBeNil();
- expect(0).not.toBeNil();
- expect("").not.toBeNil();
- expect([]).not.toBeNil();
- expect(true).not.toBeNil();
- expect({}).not.toBeNil();
- });
-
- test("toBeArray()", () => {
- expect([]).toBeArray();
- expect([1, 2, 3, "🫓"]).toBeArray();
- expect(new Array()).toBeArray();
- expect(new Array(1, 2, 3)).toBeArray();
- expect({}).not.toBeArray();
- expect("🫓").not.toBeArray();
- expect(0).not.toBeArray();
- expect(true).not.toBeArray();
- expect(null).not.toBeArray();
- });
-
- test("toBeArrayOfSize()", () => {
- expect([]).toBeArrayOfSize(0);
- expect(new Array()).toBeArrayOfSize(0);
- expect([1, 2, 3, "🫓"]).toBeArrayOfSize(4);
- expect(new Array<string | number>(1, 2, 3, "🫓")).toBeArrayOfSize(4);
- expect({}).not.toBeArrayOfSize(1);
- expect("").not.toBeArrayOfSize(1);
- expect(0).not.toBeArrayOfSize(1);
- });
-
- test("toBeTypeOf()", () => {
- expect("Bun! 🫓").toBeTypeOf("string");
- expect(0).toBeTypeOf("number");
- expect(true).toBeTypeOf("boolean");
- expect([]).toBeTypeOf("object");
- expect({}).toBeTypeOf("object");
- expect(null).toBeTypeOf("object");
- expect(undefined).toBeTypeOf("undefined");
- expect(() => {}).toBeTypeOf("function");
- expect(function () {}).toBeTypeOf("function");
- expect(async () => {}).toBeTypeOf("function");
- expect(async function () {}).toBeTypeOf("function");
- expect(function* () {}).toBeTypeOf("function");
- expect(class {}).toBeTypeOf("function");
- expect(new Array()).toBeTypeOf("object");
- expect(BigInt(5)).toBeTypeOf("bigint");
- expect(/(foo|bar)/g).toBeTypeOf("object");
- expect(new RegExp("(foo|bar)", "g")).toBeTypeOf("object");
- expect(new Date()).toBeTypeOf("object");
-
- expect("Bun!").not.toBeTypeOf("number");
- expect(0).not.toBeTypeOf("string");
- expect(true).not.toBeTypeOf("number");
- expect([]).not.toBeTypeOf("string");
- expect({}).not.toBeTypeOf("number");
- expect(null).not.toBeTypeOf("string");
- expect(undefined).not.toBeTypeOf("boolean");
- expect(() => {}).not.toBeTypeOf("string");
- expect(function () {}).not.toBeTypeOf("boolean");
- expect(async () => {}).not.toBeTypeOf("object");
- expect(class {}).not.toBeTypeOf("bigint");
- expect(/(foo|bar)/g).not.toBeTypeOf("string");
- expect(new RegExp("(foo|bar)", "g")).not.toBeTypeOf("number");
- expect(new Date()).not.toBeTypeOf("string");
- });
-
- test("toBeBoolean()", () => {
- expect(true).toBeBoolean();
- expect(false).toBeBoolean();
- expect(0).not.toBeBoolean();
- expect(1).not.toBeBoolean();
- expect("").not.toBeBoolean();
- expect({}).not.toBeBoolean();
- });
-
- test("toBeTrue()", () => {
- expect(true).toBeTrue();
- expect(false).not.toBeTrue();
- expect(0).not.toBeTrue();
- expect(1).not.toBeTrue();
- expect("").not.toBeTrue();
- expect({}).not.toBeTrue();
- });
-
- test("toBeFalse()", () => {
- expect(false).toBeFalse();
- expect(true).not.toBeFalse();
- expect(0).not.toBeFalse();
- expect(1).not.toBeFalse();
- expect("").not.toBeFalse();
- expect({}).not.toBeFalse();
- });
-
- test("toBeNumber()", () => {
- expect(0).toBeNumber();
- expect(1).toBeNumber();
- expect(1.23).toBeNumber();
- expect(Infinity).toBeNumber();
- expect(-Infinity).toBeNumber();
- expect(NaN).toBeNumber();
- expect("").not.toBeNumber();
- expect({}).not.toBeNumber();
- });
-
- test("toBeInteger()", () => {
- expect(0).toBeInteger();
- expect(1).toBeInteger();
- expect(1.23).not.toBeInteger();
- expect(Infinity).not.toBeInteger();
- expect(-Infinity).not.toBeInteger();
- expect(NaN).not.toBeInteger();
- expect("").not.toBeInteger();
- expect({}).not.toBeInteger();
- });
-
- test("toBeFinite()", () => {
- expect(0).toBeFinite();
- expect(1).toBeFinite();
- expect(1.23).toBeFinite();
- expect(Infinity).not.toBeFinite();
- expect(-Infinity).not.toBeFinite();
- expect(NaN).not.toBeFinite();
- expect("").not.toBeFinite();
- expect({}).not.toBeFinite();
- });
-
- test("toBePositive()", () => {
- expect(1).toBePositive();
- expect(1.23).toBePositive();
- expect(Infinity).not.toBePositive();
- expect(0).not.toBePositive();
- expect(-Infinity).not.toBePositive();
- expect(NaN).not.toBePositive();
- expect("").not.toBePositive();
- expect({}).not.toBePositive();
- });
-
- test("toBeNegative()", () => {
- expect(-1).toBeNegative();
- expect(-1.23).toBeNegative();
- expect(-Infinity).not.toBeNegative();
- expect(0).not.toBeNegative();
- expect(Infinity).not.toBeNegative();
- expect(NaN).not.toBeNegative();
- expect("").not.toBeNegative();
- expect({}).not.toBeNegative();
- });
-
- test("toBeWithin()", () => {
- expect(0).toBeWithin(0, 1);
- expect(3.14).toBeWithin(3, 3.141);
- expect(-25).toBeWithin(-100, 0);
- expect(0).not.toBeWithin(1, 2);
- expect(3.14).not.toBeWithin(3.1, 3.14);
- expect(99).not.toBeWithin(99, 99);
- expect(100).not.toBeWithin(99, 100);
- expect(NaN).not.toBeWithin(0, 1);
- expect("").not.toBeWithin(0, 1);
- expect({}).not.toBeWithin(0, 1);
- expect(Infinity).not.toBeWithin(-Infinity, Infinity);
- });
-
- test("toBeSymbol()", () => {
- expect(Symbol()).toBeSymbol();
- expect(Symbol("")).toBeSymbol();
- expect(Symbol.iterator).toBeSymbol();
- expect("").not.toBeSymbol();
- expect({}).not.toBeSymbol();
- });
-
- test("toBeFunction()", () => {
- expect(() => {}).toBeFunction();
- expect(function () {}).toBeFunction();
- expect(async function () {}).toBeFunction();
- expect(async () => {}).toBeFunction();
- expect(function* () {}).toBeFunction();
- expect(async function* () {}).toBeFunction();
- expect("").not.toBeFunction();
- expect({}).not.toBeFunction();
- expect(null).not.toBeFunction();
- });
-
- test("toBeDate()", () => {
- expect(new Date()).toBeDate();
- expect(new Date(0)).toBeDate();
- expect(new Date("2021-01-01")).toBeDate();
- expect("2021-01-01").not.toBeDate();
- expect({}).not.toBeDate();
- expect(null).not.toBeDate();
- });
-
- test.todo("toBeValidDate()", () => {
- expect(new Date()).toBeValidDate();
- expect(new Date(-1)).not.toBeValidDate();
- expect("2021-01-01").not.toBeValidDate();
- expect({}).not.toBeValidDate();
- expect(null).not.toBeValidDate();
- });
-
- test("toBeString()", () => {
- expect("").toBeString();
- expect("123").toBeString();
- expect(new String()).toBeString();
- expect(new String("123")).toBeString();
- expect(123).not.toBeString();
- expect({}).not.toBeString();
- });
-
- test("toInclude()", () => {
- expect("123").toInclude("1");
- expect("abc").toInclude("abc");
- expect(" 123 ").toInclude(" ");
- expect("").toInclude("");
- expect("bob").not.toInclude("alice");
- });
-
- test("toStartWith()", () => {
- expect("123").toStartWith("1");
- expect("abc").toStartWith("abc");
- expect(" 123 ").toStartWith(" ");
- expect(" ").toStartWith("");
- expect("").toStartWith("");
- expect("bob").not.toStartWith("alice");
- });
-
- test("toEndWith()", () => {
- expect("123").toEndWith("3");
- expect("abc").toEndWith("abc");
- expect(" 123 ").toEndWith(" ");
- expect(" ").toEndWith("");
- expect("").toEndWith("");
- expect("bob").not.toEndWith("alice");
- });
-});
-
-function label(value: unknown): string {
- switch (typeof value) {
- case "object":
- const string = inspect(value).replace(/\n/g, "");
- return string || '""';
- default:
- return JSON.stringify(value);
- }
-}
diff --git a/test/js/bun/test/jest-extended.test.js b/test/js/bun/test/jest-extended.test.js
new file mode 100644
index 000000000..b03e0828f
--- /dev/null
+++ b/test/js/bun/test/jest-extended.test.js
@@ -0,0 +1,516 @@
+"use strict";
+
+/** This file is meant to be runnable in both Jest and Bun.
+ * `bunx jest jest-extended.test.js`
+ */
+
+const isBun = typeof Bun !== "undefined";
+if (!isBun) {
+ const extended = require("jest-extended");
+ expect.extend(extended);
+ test.todo = test;
+}
+
+const inspect = isBun ? Bun.inspect : require("util").inspect;
+
+// https://jest-extended.jestcommunity.dev/docs/matchers/
+describe("jest-extended", () => {
+ test.todo("pass()", () => {
+ expect(typeof expect().pass).toBe("function");
+ expect(() => expect().not.pass()).toThrow();
+ expect().pass();
+ expect().pass("message ignored");
+ });
+
+ test.todo("fail()", () => {
+ expect(typeof expect().fail).toBe("function");
+ expect(() => expect("ignored value").fail("message here")).toThrow("message here");
+ expect().not.fail();
+ });
+
+ describe("toBeEmpty()", () => {
+ const values = [
+ "",
+ [],
+ {},
+ new Set(),
+ new Map(),
+ new String(),
+ new Array(),
+ new Uint8Array(),
+ new Object(),
+ Buffer.from(""),
+ ...(isBun ? [Bun.file("/tmp/empty.txt")] : []),
+ new Headers(),
+ new URLSearchParams(),
+ new FormData(),
+ (function* () {})(),
+ ];
+ for (const value of values) {
+ test(label(value), () => {
+ if (value && typeof value === "object" && value instanceof Blob) {
+ require("fs").writeFileSync("/tmp/empty.txt", "");
+ }
+
+ expect(value).toBeEmpty();
+ });
+ }
+ });
+
+ describe("not.toBeEmpty()", () => {
+ const values = [
+ " ",
+ [""],
+ [undefined],
+ { "": "" },
+ new Set([""]),
+ new Map([["", ""]]),
+ new String(" "),
+ new Array(1),
+ new Uint8Array(1),
+ Buffer.from(" "),
+ ...(isBun ? [Bun.file(__filename)] : []),
+ new Headers({
+ a: "b",
+ c: "d",
+ }),
+ new URL("https://example.com?d=e&f=g").searchParams,
+ (() => {
+ var a = new FormData();
+ a.append("a", "b");
+ a.append("c", "d");
+ return a;
+ })(),
+ (function* () {
+ yield "123";
+ })(),
+ ];
+ for (const value of values) {
+ test(label(value), () => {
+ expect(value).not.toBeEmpty();
+ });
+ }
+ });
+
+ // toBeOneOf('toSatisfy()')
+
+ test("toBeNil()", () => {
+ expect(null).toBeNil();
+ expect(undefined).toBeNil();
+ expect(false).not.toBeNil();
+ expect(0).not.toBeNil();
+ expect("").not.toBeNil();
+ expect([]).not.toBeNil();
+ expect(true).not.toBeNil();
+ expect({}).not.toBeNil();
+ });
+
+ // test('toSatisfy()')
+
+ // Array
+
+ // test('toBeArray()')
+ // test('toBeArrayOfSize()')
+ // test('toIncludeAllMembers()')
+ // test('toIncludeAllPartialMembers()')
+ // test('toIncludeAnyMembers()')
+ // test('toIncludeSameMembers()')
+ // test('toPartiallyContain()')
+ // test('toSatisfyAll()')
+ // test('toSatisfyAny()')
+ // test('toBeInRange()')
+
+ // Boolean
+
+ test("toBeBoolean()", () => {
+ expect(true).toBeBoolean();
+ expect(false).toBeBoolean();
+ expect(0).not.toBeBoolean();
+ expect(1).not.toBeBoolean();
+ expect("").not.toBeBoolean();
+ expect({}).not.toBeBoolean();
+ });
+
+ test("toBeTrue()", () => {
+ expect(true).toBeTrue();
+ expect(false).not.toBeTrue();
+ expect(0).not.toBeTrue();
+ expect(1).not.toBeTrue();
+ expect("").not.toBeTrue();
+ expect({}).not.toBeTrue();
+ });
+
+ test("toBeFalse()", () => {
+ expect(false).toBeFalse();
+ expect(true).not.toBeFalse();
+ expect(0).not.toBeFalse();
+ expect(1).not.toBeFalse();
+ expect("").not.toBeFalse();
+ expect({}).not.toBeFalse();
+ });
+
+ // Date
+
+ test("toBeDate()", () => {
+ expect(new Date()).toBeDate();
+ expect(new Date(0)).toBeDate();
+ expect(new Date("2021-01-01")).toBeDate();
+ expect("2021-01-01").not.toBeDate();
+ expect({}).not.toBeDate();
+ expect(null).not.toBeDate();
+ });
+
+ test.todo("toBeValidDate()", () => {
+ expect(new Date()).toBeValidDate();
+ expect(new Date(-1)).toBeValidDate();
+ expect("2021-01-01").not.toBeValidDate();
+ expect({}).not.toBeValidDate();
+ expect(null).not.toBeValidDate();
+ });
+
+ // expect("toBeAfter()")
+ // expect("toBeBefore()")
+ // expect("toBeAfterOrEqualTo()")
+ // expect("toBeBeforeOrEqualTo()")
+ // expect("toBeBetween()")
+
+ // Function
+
+ test("toBeFunction()", () => {
+ expect(() => {}).toBeFunction();
+ expect(function () {}).toBeFunction();
+ expect(async function () {}).toBeFunction();
+ expect(async () => {}).toBeFunction();
+ expect(function* () {}).toBeFunction();
+ expect(async function* () {}).toBeFunction();
+ expect("").not.toBeFunction();
+ expect({}).not.toBeFunction();
+ expect(null).not.toBeFunction();
+ });
+
+ // expect('toThrowWithMessage()')
+
+ // Mock
+
+ // Number
+ test("toBeNumber()", () => {
+ expect(0).toBeNumber();
+ expect(1).toBeNumber();
+ expect(1.23).toBeNumber();
+ expect(Infinity).toBeNumber();
+ expect(-Infinity).toBeNumber();
+ expect(NaN).toBeNumber();
+ expect("").not.toBeNumber();
+ expect({}).not.toBeNumber();
+ });
+
+ test("toBeFinite()", () => {
+ expect(0).toBeFinite();
+ expect(1).toBeFinite();
+ expect(1.23).toBeFinite();
+ expect(Infinity).not.toBeFinite();
+ expect(-Infinity).not.toBeFinite();
+ expect(NaN).not.toBeFinite();
+ expect("").not.toBeFinite();
+ expect({}).not.toBeFinite();
+ });
+
+ test("toBePositive()", () => {
+ expect(1).toBePositive();
+ expect(1.23).toBePositive();
+ expect(Infinity).not.toBePositive();
+ expect(0).not.toBePositive();
+ expect(-Infinity).not.toBePositive();
+ expect(NaN).not.toBePositive();
+ expect("").not.toBePositive();
+ expect({}).not.toBePositive();
+ });
+
+ test("toBeNegative()", () => {
+ expect(-1).toBeNegative();
+ expect(-1.23).toBeNegative();
+ expect(-Infinity).not.toBeNegative();
+ expect(0).not.toBeNegative();
+ expect(Infinity).not.toBeNegative();
+ expect(NaN).not.toBeNegative();
+ expect("").not.toBeNegative();
+ expect({}).not.toBeNegative();
+ });
+
+ test("toBeWithin()", () => {
+ expect(0).toBeWithin(0, 1);
+ expect(3.14).toBeWithin(3, 3.141);
+ expect(-25).toBeWithin(-100, 0);
+ expect(0).not.toBeWithin(1, 2);
+ expect(3.14).not.toBeWithin(3.1, 3.14);
+ expect(99).not.toBeWithin(99, 99);
+ expect(100).not.toBeWithin(99, 100);
+ expect(NaN).not.toBeWithin(0, 1);
+ // expect("").not.toBeWithin(0, 1);
+ expect({}).not.toBeWithin(0, 1);
+ expect(Infinity).not.toBeWithin(-Infinity, Infinity);
+ });
+
+ test("toBeEven()", () => {
+ expect(1).not.toBeEven();
+ expect(2).toBeEven();
+ expect(3).not.toBeEven();
+ expect(3.1).not.toBeEven();
+ expect(2.1).not.toBeEven();
+ expect(4).toBeEven();
+ expect(5).not.toBeEven();
+ expect(6).toBeEven();
+ expect(0).toBeEven();
+ expect(-8).toBeEven();
+ expect(-0).toBeEven();
+ expect(NaN).not.toBeEven();
+ expect([]).not.toBeEven();
+ expect([1, 2]).not.toBeEven();
+ expect({}).not.toBeEven();
+ expect(() => {}).not.toBeEven();
+ expect("").not.toBeEven();
+ expect("string").not.toBeEven();
+ expect(undefined).not.toBeEven();
+ expect(Math.floor(Date.now() / 1000) * 2).toBeEven(); // Slight fuzz by using timestamp times 2
+ expect(Math.floor(Date.now() / 1000) * 4 - 1).not.toBeEven();
+ expect(4.0e1).toBeEven();
+ expect(6.2e1).toBeEven();
+ expect(6.3e1).not.toBeEven();
+ expect(6.33e1).not.toBeEven();
+ expect(3.3e-1).not.toBeEven(); //throw
+ expect(0.3).not.toBeEven(); //throw
+ expect(0.4).not.toBeEven();
+ expect(1).not.toBeEven();
+ expect(0).toBeEven();
+ expect(2.0).toBeEven();
+ expect(NaN).not.toBeEven();
+ expect(2n).toBeEven(); // BigInt at this time not supported in jest-extended
+ expect(3n).not.toBeEven();
+ expect(9007199254740990).toBeEven(); // manual typical max safe -1 // not int?
+ if (isBun) expect(9007199254740990n).toBeEven(); // manual typical max safe -1 as bigint
+ expect(Number.MAX_SAFE_INTEGER - 1).toBeEven(); // not int?
+ expect(Number.MAX_SAFE_INTEGER).not.toBeEven();
+ if (isBun) {
+ expect(BigInt(Number.MAX_SAFE_INTEGER) - 1n).toBeEven();
+ expect(BigInt(Number.MIN_SAFE_INTEGER) + 1n).toBeEven();
+ }
+ expect(BigInt(Number.MAX_SAFE_INTEGER)).not.toBeEven();
+ expect(BigInt(Number.MAX_VALUE - 1)).toBeEven();
+ expect(Number.MIN_SAFE_INTEGER + 1).toBeEven(); // not int?
+ expect(Number.MIN_SAFE_INTEGER).not.toBeEven();
+ expect(BigInt(Number.MIN_SAFE_INTEGER)).not.toBeEven();
+ expect(4 / Number.NEGATIVE_INFINITY).toBeEven(); // as in IEEE-754: + / -inf => neg zero
+ expect(5 / Number.NEGATIVE_INFINITY).toBeEven();
+ expect(-7 / Number.NEGATIVE_INFINITY).toBeEven(); // as in IEEE-754: - / -inf => zero
+ expect(-8 / Number.NEGATIVE_INFINITY).toBeEven();
+ expect(new WebAssembly.Global({ value: "i32", mutable: false }, 4).value).toBeEven();
+ expect(new WebAssembly.Global({ value: "i32", mutable: false }, 3).value).not.toBeEven();
+ expect(new WebAssembly.Global({ value: "i32", mutable: true }, 2).value).toBeEven();
+ expect(new WebAssembly.Global({ value: "i32", mutable: true }, 1).value).not.toBeEven();
+ if (isBun) {
+ expect(new WebAssembly.Global({ value: "i64", mutable: true }, -9223372036854775808n).value).toBeEven();
+ expect(new WebAssembly.Global({ value: "i64", mutable: false }, -9223372036854775808n).value).toBeEven();
+ expect(new WebAssembly.Global({ value: "i64", mutable: true }, 9223372036854775807n).value).not.toBeEven();
+ expect(new WebAssembly.Global({ value: "i64", mutable: false }, 9223372036854775807n).value).not.toBeEven();
+ }
+ expect(new WebAssembly.Global({ value: "f32", mutable: true }, 42.0).value).toBeEven();
+ expect(new WebAssembly.Global({ value: "f32", mutable: false }, 42.0).value).toBeEven();
+ expect(new WebAssembly.Global({ value: "f64", mutable: true }, 42.0).value).toBeEven();
+ expect(new WebAssembly.Global({ value: "f64", mutable: false }, 42.0).value).toBeEven();
+ expect(new WebAssembly.Global({ value: "f32", mutable: true }, 43.0).value).not.toBeEven();
+ expect(new WebAssembly.Global({ value: "f32", mutable: false }, 43.0).value).not.toBeEven();
+ expect(new WebAssembly.Global({ value: "f64", mutable: true }, 43.0).value).not.toBeEven();
+ expect(new WebAssembly.Global({ value: "f64", mutable: false }, 43.0).value).not.toBeEven();
+ expect(new WebAssembly.Global({ value: "f32", mutable: true }, 4.3).value).not.toBeEven();
+ expect(new WebAssembly.Global({ value: "f32", mutable: false }, 4.3).value).not.toBeEven();
+ expect(new WebAssembly.Global({ value: "f64", mutable: true }, 4.3).value).not.toBeEven();
+ expect(new WebAssembly.Global({ value: "f64", mutable: false }, 4.3).value).not.toBeEven();
+ // did not seem to support SIMD v128 type yet (which is not in W3C specs for JS but is a valid global type)
+ // FUTURE: expect(new WebAssembly.Global({value:'v128', mutable:false}, -170141183460469231731687303715884105728n).value).toBeEven();
+ // FUTURE: expect(new WebAssembly.Global({value:'v128', mutable:true}, -170141183460469231731687303715884105728n).value).toBeEven();
+ // FUTURE: expect(new WebAssembly.Global({value:'v128', mutable:true}, 170141183460469231731687303715884105727n).value).not.toBeEven();
+ // FUTURE: expect(new WebAssembly.Global({value:'v128', mutable:false}, 170141183460469231731687303715884105727n).value).not.toBeEven();
+ // FUTURE: with uintv128: expect(new WebAssembly.Global({value:'v128', mutable:false}, 340282366920938463463374607431768211456n).value).toThrow();
+ });
+
+ test("toBeOdd()", () => {
+ expect(1).toBeOdd();
+ expect(2).not.toBeOdd();
+ expect(3).toBeOdd();
+ expect(3.1).not.toBeOdd();
+ expect(2.1).not.toBeOdd();
+ expect(4).not.toBeOdd();
+ expect(5).toBeOdd();
+ expect(6).not.toBeOdd();
+ expect(0).not.toBeOdd();
+ expect(-8).not.toBeOdd();
+ expect(-0).not.toBeOdd();
+ expect(NaN).not.toBeOdd();
+ expect([]).not.toBeOdd();
+ // SHOULD FAIL: expect([]).toBeOdd();
+ expect([1, 2]).not.toBeOdd();
+ expect({}).not.toBeOdd();
+ expect(() => {}).not.toBeOdd();
+ expect("").not.toBeOdd();
+ expect("string").not.toBeOdd();
+ expect(undefined).not.toBeOdd();
+ expect(Math.floor(Date.now() / 1000) * 2 - 1).toBeOdd(); // Slight fuzz by using timestamp times 2
+ expect(Math.floor(Date.now() / 1000) * 4 - 1).toBeOdd();
+ expect(4.0e1).not.toBeOdd();
+ expect(6.2e1).not.toBeOdd();
+ expect(6.3e1).toBeOdd();
+ expect(6.33e1).not.toBeOdd();
+ expect(3.2e-3).not.toBeOdd();
+ expect(0.3).not.toBeOdd();
+ expect(0.4).not.toBeOdd();
+ expect(1).toBeOdd();
+ expect(0).not.toBeOdd();
+ expect(2.0).not.toBeOdd();
+ expect(NaN).not.toBeOdd();
+ if (isBun) expect(2n).not.toBeOdd(); // BigInt at this time not supported in jest-extended
+ if (isBun) expect(3n).toBeOdd();
+ expect(9007199254740990).not.toBeOdd(); // manual typical max safe -1
+ expect(9007199254740991).toBeOdd();
+ if (isBun) expect(9007199254740990n).not.toBeOdd(); // manual typical max safe -1 as bigint
+ if (isBun) expect(9007199254740991n).toBeOdd();
+ expect(Number.MAX_SAFE_INTEGER - 1).not.toBeOdd();
+ expect(Number.MAX_SAFE_INTEGER).toBeOdd();
+ expect(BigInt(Number.MAX_SAFE_INTEGER) - 1n).not.toBeOdd();
+ expect(BigInt(Number.MAX_SAFE_INTEGER)).toBeOdd();
+ expect(Number.MIN_SAFE_INTEGER + 1).not.toBeOdd();
+ expect(Number.MIN_SAFE_INTEGER).toBeOdd();
+ expect(BigInt(Number.MIN_SAFE_INTEGER) + 1n).not.toBeOdd();
+ expect(BigInt(Number.MIN_SAFE_INTEGER)).toBeOdd();
+ expect(4 / Number.NEGATIVE_INFINITY).not.toBeOdd(); // in IEEE-754: + / -inf => neg zero
+ expect(5 / Number.NEGATIVE_INFINITY).not.toBeOdd();
+ expect(-7 / Number.NEGATIVE_INFINITY).not.toBeOdd(); // in IEEE-754: - / -inf => zero
+ expect(-8 / Number.NEGATIVE_INFINITY).not.toBeOdd();
+ expect(new WebAssembly.Global({ value: "i32", mutable: false }, 4).value).not.toBeOdd();
+ expect(new WebAssembly.Global({ value: "i32", mutable: false }, 3).value).toBeOdd();
+ expect(new WebAssembly.Global({ value: "i32", mutable: true }, 2).value).not.toBeOdd();
+ expect(new WebAssembly.Global({ value: "i32", mutable: true }, 1).value).toBeOdd();
+ if (isBun) {
+ expect(new WebAssembly.Global({ value: "i64", mutable: true }, -9223372036854775808n).value).not.toBeOdd();
+ expect(new WebAssembly.Global({ value: "i64", mutable: false }, -9223372036854775808n).value).not.toBeOdd();
+ expect(new WebAssembly.Global({ value: "i64", mutable: true }, 9223372036854775807n).value).toBeOdd();
+ expect(new WebAssembly.Global({ value: "i64", mutable: false }, 9223372036854775807n).value).toBeOdd();
+ }
+ expect(new WebAssembly.Global({ value: "f32", mutable: true }, 42.0).value).not.toBeOdd();
+ expect(new WebAssembly.Global({ value: "f32", mutable: false }, 42.0).value).not.toBeOdd();
+ expect(new WebAssembly.Global({ value: "f64", mutable: true }, 42.0).value).not.toBeOdd();
+ expect(new WebAssembly.Global({ value: "f64", mutable: false }, 42.0).value).not.toBeOdd();
+ expect(new WebAssembly.Global({ value: "f32", mutable: true }, 43.0).value).toBeOdd();
+ expect(new WebAssembly.Global({ value: "f32", mutable: false }, 43.0).value).toBeOdd();
+ expect(new WebAssembly.Global({ value: "f64", mutable: true }, 43.0).value).toBeOdd();
+ expect(new WebAssembly.Global({ value: "f64", mutable: false }, 43.0).value).toBeOdd();
+ expect(new WebAssembly.Global({ value: "f32", mutable: true }, 4.3).value).not.toBeOdd();
+ expect(new WebAssembly.Global({ value: "f32", mutable: false }, 4.3).value).not.toBeOdd();
+ expect(new WebAssembly.Global({ value: "f64", mutable: true }, 4.3).value).not.toBeOdd();
+ expect(new WebAssembly.Global({ value: "f64", mutable: false }, 4.3).value).not.toBeOdd();
+ // did not seem to support SIMD v128 type yet
+ // FUTURE: expect(new WebAssembly.Global({value:'v128', mutable:false}, 42).value).not.toBeOdd();
+ // FUTURE: expect(new WebAssembly.Global({value:'v128', mutable:true}, 42).value).not.toBeOdd();
+ // FUTURE: expect(new WebAssembly.Global({value:'v128', mutable:true}, 43).value).toBeOdd();
+ });
+
+ test("toBeInteger()", () => {
+ expect(0).toBeInteger();
+ expect(1).toBeInteger();
+ expect(1.23).not.toBeInteger();
+ expect(Infinity).not.toBeInteger();
+ expect(-Infinity).not.toBeInteger();
+ expect(NaN).not.toBeInteger();
+ expect("").not.toBeInteger();
+ expect({}).not.toBeInteger();
+ });
+
+ // Object
+
+ // test("toBeObject()")
+ // test("toBeEmptyObject()")
+ // test("toContainKey()")
+ // test("toContainKeys()")
+ // test("toContainAllKeys()")
+ // test("toContainAnyKeys()")
+ // test("toContainValue()")
+ // test("toContainValues()")
+ // test("toContainAllValues()")
+ // test("toContainAnyValues()")
+ // test("toContainEntry()")
+ // test("toContainEntries()")
+ // test("toContainAllEntries()")
+ // test("toContainAnyEntries()")
+ // test("toBeExtensible()")
+ // test("toBeFrozen()")
+ // test("toBeSealed()")
+
+ // String
+
+ test("toBeString()", () => {
+ expect("").toBeString();
+ expect("123").toBeString();
+ expect(new String()).toBeString();
+ expect(new String("123")).toBeString();
+ expect(123).not.toBeString();
+ expect({}).not.toBeString();
+ });
+ // test("toBeHexadecimal()")
+ // test("toBeDateString()")
+ // test("toEqualCaseInsensitive()")
+
+ test("toStartWith()", () => {
+ expect("123").toStartWith("1");
+ expect("abc").toStartWith("abc");
+ expect(" 123 ").toStartWith(" ");
+ expect(" ").toStartWith("");
+ expect("").toStartWith("");
+ expect("bob").not.toStartWith("alice");
+ });
+
+ test("toEndWith()", () => {
+ expect("123").toEndWith("3");
+ expect("abc").toEndWith("abc");
+ expect(" 123 ").toEndWith(" ");
+ expect(" ").toEndWith("");
+ expect("").toEndWith("");
+ expect("bob").not.toEndWith("alice");
+ });
+
+ test("toInclude()", () => {
+ expect("123").toInclude("1");
+ expect("abc").toInclude("abc");
+ expect(" 123 ").toInclude(" ");
+ expect("").toInclude("");
+ expect("bob").not.toInclude("alice");
+ });
+
+ // test("toIncludeRepeated()")
+ // test("toIncludeMultiple()")
+ // test("toEqualIgnoringWhitespace()")
+
+ // Symbol
+
+ test("toBeSymbol()", () => {
+ expect(Symbol()).toBeSymbol();
+ expect(Symbol("")).toBeSymbol();
+ expect(Symbol.iterator).toBeSymbol();
+ expect("").not.toBeSymbol();
+ expect({}).not.toBeSymbol();
+ });
+});
+
+/**
+ * @param {string} value
+ * @returns {string}
+ */
+function label(value) {
+ switch (typeof value) {
+ case "object":
+ const string = inspect(value).replace(/\n/g, "");
+ return string || '""';
+ case "undefined":
+ return "undefined";
+ default:
+ return JSON.stringify(value);
+ }
+}
diff --git a/test/js/bun/test/jest.d.ts b/test/js/bun/test/jest.d.ts
new file mode 100644
index 000000000..fccb87b40
--- /dev/null
+++ b/test/js/bun/test/jest.d.ts
@@ -0,0 +1,5 @@
+declare var jest: typeof import("bun:test").jest;
+declare var describe: typeof import("bun:test").describe;
+declare var test: typeof import("bun:test").test;
+declare var expect: typeof import("bun:test").expect;
+declare var it: typeof import("bun:test").it;
diff --git a/test/js/bun/test/mock-fn.test.js b/test/js/bun/test/mock-fn.test.js
new file mode 100644
index 000000000..eac981fd1
--- /dev/null
+++ b/test/js/bun/test/mock-fn.test.js
@@ -0,0 +1,599 @@
+/**
+ * This file is meant to be runnable in both Jest and Bun.
+ * `bunx jest mock-fn.test.js`
+ */
+var { isBun, test, describe, expect, jest, vi, mock, bunTest, spyOn } = require("./test-interop.js")();
+
+async function expectResolves(promise) {
+ expect(promise).toBeInstanceOf(Promise);
+ return await promise;
+}
+
+async function expectRejects(promise) {
+ expect(promise).toBeInstanceOf(Promise);
+ var value;
+ try {
+ value = await promise;
+ } catch (e) {
+ return e;
+ }
+ throw new Error("Expected promise to reject, but it resolved to " + value);
+}
+
+describe("mock()", () => {
+ if (isBun) {
+ test("exists as jest.fn, bunTest.mock, and vi.fn", () => {
+ expect(jest.fn).toBe(mock);
+ expect(jest.fn).toBe(vi.fn);
+ });
+ }
+ test("are callable", () => {
+ const fn = jest.fn(() => 42);
+ 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()).toBe(42);
+ expect(fn).toHaveBeenCalledTimes(2);
+ expect(fn.mock.calls).toHaveLength(2);
+ expect(fn.mock.calls[1]).toBeEmpty();
+ });
+ test("passes this value", () => {
+ const fn = jest.fn(function hey() {
+ "use strict";
+ return this;
+ });
+ const obj = { fn };
+ expect(obj.fn()).toBe(obj);
+ });
+ if (isBun) {
+ test("jest.fn(10) return value shorthand", () => {
+ expect(jest.fn(10)()).toBe(10);
+ expect(jest.fn(null)()).toBe(null);
+ });
+ }
+ test("blank function still logs a return", () => {
+ const fn = jest.fn();
+ expect(fn()).toBe(undefined);
+ expect(fn.mock.results[0]).toEqual({
+ type: "return",
+ value: undefined,
+ });
+ });
+ test(".call passes this value", () => {
+ const fn = jest.fn(function () {
+ return this;
+ });
+ expect(Number(fn.call(123))).toBe(123);
+ });
+ test(".call works", () => {
+ const fn = jest.fn(function hey() {
+ return this;
+ });
+ expect(Number(fn.call(123))).toBe(123);
+ expect(fn).toHaveBeenCalled();
+ expect(fn).toHaveBeenCalledTimes(1);
+ expect(fn.mock.calls).toHaveLength(1);
+ expect(fn.mock.calls[0]).toBeEmpty();
+ expect(Number(fn.call(234))).toBe(234);
+ expect(fn).toHaveBeenCalledTimes(2);
+ expect(fn.mock.calls).toHaveLength(2);
+ expect(fn.mock.calls[1]).toBeEmpty();
+ });
+ test(".apply works", function () {
+ const fn = jest.fn(function hey() {
+ return this;
+ });
+ expect(Number(fn.apply(123))).toBe(123);
+ expect(fn).toHaveBeenCalled();
+ expect(fn).toHaveBeenCalledTimes(1);
+ expect(fn.mock.calls).toHaveLength(1);
+ expect(fn.mock.calls[0]).toBeEmpty();
+ expect(Number(fn.apply(234))).toBe(234);
+ expect(fn).toHaveBeenCalledTimes(2);
+ expect(fn.mock.calls).toHaveLength(2);
+ expect(fn.mock.calls[1]).toBeEmpty();
+ });
+ test(".bind works", () => {
+ const fn = jest.fn(function hey() {
+ return this;
+ });
+ expect(Number(fn.bind(123)())).toBe(123);
+ expect(fn).toHaveBeenCalled();
+ expect(fn).toHaveBeenCalledTimes(1);
+ expect(fn.mock.calls).toHaveLength(1);
+ expect(fn.mock.calls[0]).toBeEmpty();
+ expect(Number(fn.bind(234)())).toBe(234);
+ expect(fn).toHaveBeenCalledTimes(2);
+ expect(fn.mock.calls).toHaveLength(2);
+ expect(fn.mock.calls[1]).toBeEmpty();
+ });
+ test(".name works", () => {
+ const fn = jest.fn(function hey() {
+ return this;
+ });
+
+ if (isBun) {
+ expect(fn.name).toBe("hey");
+ }
+ expect(typeof fn.name).toBe("string");
+ });
+ test(".name without implementation", () => {
+ const fn = jest.fn();
+ expect(fn.name).toBe("mockConstructor");
+ });
+ test(".name throwing doesnt segfault", () => {
+ function baddie() {
+ return this;
+ }
+ Object.defineProperty(baddie, "name", {
+ get() {
+ throw new Error("foo");
+ },
+ });
+ const fn = jest.fn(baddie);
+ expect(typeof fn.name).toBe("string");
+ });
+ test(".length works", () => {
+ const fn = jest.fn(function hey(a, b, c) {
+ return this;
+ });
+
+ expect(fn.length).toBe(3);
+ });
+ test("include arguments", () => {
+ const fn = jest.fn(f => f);
+ expect(fn(43)).toBe(43);
+ expect(fn.mock.results[0]).toEqual({
+ type: "return",
+ value: 43,
+ });
+ expect(fn.mock.calls[0]).toEqual([43]);
+ });
+ test("works when throwing", () => {
+ const instance = new Error("foo");
+ const fn = jest.fn(f => {
+ throw instance;
+ });
+ expect(() => fn(43)).toThrow("foo");
+ expect(fn.mock.results[0]).toEqual({
+ type: "throw",
+ value: instance,
+ });
+ expect(fn.mock.calls[0]).toEqual([43]);
+ });
+ test("mockReset works", () => {
+ const instance = new Error("foo");
+ const fn = jest.fn(f => {
+ throw instance;
+ });
+ expect(() => fn(43)).toThrow("foo");
+ expect(fn.mock.results[0]).toEqual({
+ type: "throw",
+ value: instance,
+ });
+ expect(fn.mock.calls[0]).toEqual([43]);
+ fn.mockReset();
+ expect(fn.mock.calls).toBeEmpty();
+ expect(fn.mock.results).toBeEmpty();
+ expect(fn.mock.instances).toBeEmpty();
+ expect(fn).not.toHaveBeenCalled();
+ expect(() => expect(fn).toHaveBeenCalled()).toThrow();
+ expect(fn(43)).toBe(undefined);
+ expect(fn.mock.results).toEqual([
+ {
+ type: "return",
+ value: undefined,
+ },
+ ]);
+ expect(fn.mock.calls).toEqual([[43]]);
+ });
+ test("mockClear works", () => {
+ const instance = new Error("foo");
+ const fn = jest.fn(f => {
+ throw instance;
+ });
+ expect(() => fn(43)).toThrow("foo");
+ expect(fn.mock.results[0]).toEqual({
+ type: "throw",
+ value: instance,
+ });
+ expect(fn.mock.calls[0]).toEqual([43]);
+ fn.mockClear();
+ expect(fn.mock.calls).toBeEmpty();
+ expect(fn.mock.results).toBeEmpty();
+ expect(fn.mock.instances).toBeEmpty();
+ expect(fn).not.toHaveBeenCalled();
+ expect(() => fn(43)).toThrow("foo");
+ expect(fn.mock.results[0]).toEqual({
+ type: "throw",
+ value: instance,
+ });
+ expect(fn.mock.calls[0]).toEqual([43]);
+ });
+ // this is an implementation detail i don't think we *need* to support
+ test("mockClear doesnt update existing object", () => {
+ const instance = new Error("foo");
+ const fn = jest.fn(f => {
+ throw instance;
+ });
+ expect(() => fn(43)).toThrow("foo");
+ expect(fn.mock.results[0]).toEqual({
+ type: "throw",
+ value: instance,
+ });
+ expect(fn.mock.calls[0]).toEqual([43]);
+ const stolen = fn.mock;
+ fn.mockClear();
+ expect(stolen).not.toBe(fn.mock);
+ expect(fn.mock.calls).toBeEmpty();
+ expect(stolen.calls).not.toBeEmpty();
+ expect(fn.mock.results).toBeEmpty();
+ expect(stolen.results).not.toBeEmpty();
+ expect(fn.mock.instances).toBeEmpty();
+ expect(stolen.instances).not.toBe(fn.mock.instances);
+ expect(fn).not.toHaveBeenCalled();
+ expect(() => fn(43)).toThrow("foo");
+ expect(fn.mock.results[0]).toEqual({
+ type: "throw",
+ value: instance,
+ });
+ expect(fn.mock.calls[0]).toEqual([43]);
+ });
+ test("multiple calls work", () => {
+ const fn = jest.fn(f => f);
+ expect(fn(43)).toBe(43);
+ expect(fn(44)).toBe(44);
+ expect(fn.mock.calls[0]).toEqual([43]);
+ expect(fn.mock.results[0]).toEqual({
+ type: "return",
+ value: 43,
+ });
+ expect(fn.mock.calls[1]).toEqual([44]);
+ expect(fn.mock.results[1]).toEqual({
+ type: "return",
+ value: 44,
+ });
+ expect(fn.mock.contexts).toEqual([undefined, undefined]);
+ });
+ test("this arg", () => {
+ const fn = jest.fn(function (add) {
+ return this.foo + add;
+ });
+ const obj = { foo: 42, fn };
+ expect(obj.fn(2)).toBe(44);
+ expect(fn.mock.calls[0]).toEqual([2]);
+ expect(fn.mock.results[0]).toEqual({
+ type: "return",
+ value: 44,
+ });
+ });
+ test("looks like a function", () => {
+ const fn = jest.fn(function nameHere(a, b, c) {
+ return [a, b, c];
+ });
+ expect(typeof fn).toBe("function");
+ expect(typeof fn.name).toBe("string");
+ expect(fn.name.length).toBeGreaterThan(0);
+ expect(fn.toString).not.toBe(undefined);
+ expect(fn.bind).not.toBe(undefined);
+ expect(fn.call).not.toBe(undefined);
+ expect(fn.apply).not.toBe(undefined);
+ expect(typeof fn.length).toBe("number");
+ });
+ test("apply/call/bind", () => {
+ const fn = jest.fn(function (add) {
+ "use strict";
+ return this.foo + add;
+ });
+ const obj = { foo: 42, fn };
+ expect(obj.fn(2)).toBe(44);
+ const this2 = { foo: 43 };
+ expect(fn.call(this2, 2)).toBe(45);
+ const this3 = { foo: 44 };
+ expect(fn.apply(this3, [2])).toBe(46);
+ const this4 = { foo: 45 };
+ expect(fn.bind(this4)(3)).toBe(48);
+ const this5 = { foo: 45 };
+ expect(fn.bind(this5, 2)()).toBe(47);
+ expect(fn.mock.calls[0]).toEqual([2]);
+ expect(fn.mock.calls[1]).toEqual([2]);
+ expect(fn.mock.calls[2]).toEqual([2]);
+ expect(fn.mock.calls[3]).toEqual([3]);
+ expect(fn.mock.calls[4]).toEqual([2]);
+ expect(fn.mock.results[0]).toEqual({
+ type: "return",
+ value: 44,
+ });
+ expect(fn.mock.results[1]).toEqual({
+ type: "return",
+ value: 45,
+ });
+ expect(fn.mock.results[2]).toEqual({
+ type: "return",
+ value: 46,
+ });
+ expect(fn.mock.results[3]).toEqual({
+ type: "return",
+ value: 48,
+ });
+ expect(fn.mock.results[4]).toEqual({
+ type: "return",
+ value: 47,
+ });
+ });
+ test("mockReturnValueOnce with no implementation", () => {
+ const fn = jest.fn();
+ fn.mockReturnValueOnce(10);
+ expect(fn()).toBe(10);
+ expect(fn()).toBe(undefined);
+ fn.mockReturnValueOnce("x").mockReturnValue(true);
+ expect(fn()).toBe("x");
+ expect(fn()).toBe(true);
+ expect(fn()).toBe(true);
+ fn.mockReturnValue("y");
+ expect(fn()).toBe("y");
+ });
+ test("mockReturnValue then mockReturnValueOnce", () => {
+ const fn = jest.fn();
+ fn.mockReturnValue(true).mockReturnValueOnce(10).mockReturnValueOnce("x");
+ expect(fn()).toBe(10);
+ expect(fn()).toBe("x");
+ expect(fn()).toBe(true);
+ expect(fn()).toBe(true);
+ });
+ test("mockReturnValue then fallback to original", () => {
+ const fn = jest.fn(() => "fallback");
+ fn.mockReturnValueOnce(true).mockReturnValueOnce(10).mockReturnValueOnce("x");
+ expect(fn()).toBe(true);
+ expect(fn()).toBe(10);
+ expect(fn()).toBe("x");
+ expect(fn()).toBe("fallback");
+ });
+ test("mockImplementation", () => {
+ const fn = jest.fn();
+ fn.mockImplementation(a => !a);
+ expect(fn()).toBe(true);
+ expect(fn()).toBe(true);
+ fn.mockImplementation(a => a + 2);
+ expect(fn(8)).toBe(10);
+ });
+ test("mockImplementationOnce", () => {
+ const fn = jest.fn();
+ fn.mockImplementationOnce(a => ["a", a]);
+ fn.mockImplementationOnce(a => ["b", a]);
+ fn.mockImplementationOnce(a => ["c", a]);
+ fn.mockImplementation(a => ["d", a]);
+ expect(fn(1)).toEqual(["a", 1]);
+ expect(fn(2)).toEqual(["b", 2]);
+ expect(fn(3)).toEqual(["c", 3]);
+ expect(fn(4)).toEqual(["d", 4]);
+ expect(fn(5)).toEqual(["d", 5]);
+ fn.mockImplementationOnce(a => ["e", a]);
+ expect(fn(5)).toEqual(["e", 5]);
+ expect(fn(6)).toEqual(["d", 6]);
+ fn.mockImplementationOnce(a => ["f", a]);
+ fn.mockImplementation(a => ["g", a]);
+ expect(fn(7)).toEqual(["f", 7]);
+ expect(fn(8)).toEqual(["g", 8]);
+ expect(fn(9)).toEqual(["g", 9]);
+ });
+ test("mockImplementation falls back", () => {
+ const fn = jest.fn(() => "fallback");
+ fn.mockImplementationOnce(a => ["a", a]);
+ fn.mockImplementationOnce(a => ["b", a]);
+ expect(fn(1)).toEqual(["a", 1]);
+ expect(fn(2)).toEqual(["b", 2]);
+ expect(fn(3)).toEqual("fallback");
+ });
+ test("mixing mockImplementation and mockReturnValue", () => {
+ const fn = jest.fn(() => "fallback");
+ fn.mockReturnValueOnce(true).mockImplementationOnce(() => 12);
+ expect(fn()).toBe(true);
+ expect(fn()).toBe(12);
+ expect(fn()).toBe("fallback");
+ fn.mockImplementation(() => 13);
+ expect(fn()).toBe(13);
+ fn.mockReturnValue("FAIL").mockImplementation(() => 14);
+ expect(fn()).toBe(14);
+ fn.mockReturnValueOnce(15).mockImplementation(() => 16);
+ expect(fn()).toBe(15);
+ expect(fn()).toBe(16);
+ });
+ // these promise based tests were written before .resolves/.rejects were added to bun:test
+ test("mockResolvedValue", async () => {
+ const fn = jest.fn();
+ fn.mockResolvedValue(42);
+ expect(await expectResolves(fn())).toBe(42);
+ fn.mockResolvedValueOnce(43);
+ fn.mockResolvedValueOnce(44);
+ expect(await expectResolves(fn())).toBe(43);
+ expect(await expectResolves(fn())).toBe(44);
+ expect(await expectResolves(fn())).toBe(42);
+ });
+ test("mockRejectedValue", async () => {
+ const fn = jest.fn();
+ fn.mockRejectedValue(42);
+ expect(await expectRejects(fn())).toBe(42);
+ expect(await expectRejects(fn())).toBe(42);
+ fn.mockRejectedValueOnce(43);
+ fn.mockRejectedValueOnce(44);
+ expect(await expectRejects(fn())).toBe(43);
+ expect(await expectRejects(fn())).toBe(44);
+ expect(await expectRejects(fn())).toBe(42);
+ });
+ test("withImplementation (sync)", () => {
+ const fn = jest.fn(() => "1");
+ expect(fn()).toBe("1");
+ const result = fn.withImplementation(
+ () => "2",
+ function () {
+ expect(fn()).toBe("2");
+ expect(fn()).toBe("2");
+ return "3";
+ },
+ );
+ expect(result).toBe(undefined);
+ expect(fn()).toBe("1");
+ });
+ test("withImplementation (async)", async () => {
+ const fn = jest.fn(() => "1");
+ expect(fn()).toBe("1");
+ const result = fn.withImplementation(
+ () => "2",
+ async function () {
+ expect(fn()).toBe("2");
+ expect(fn()).toBe("2");
+ await new Promise(resolve => setTimeout(resolve, 10));
+ expect(fn()).toBe("2");
+ expect(fn()).toBe("2");
+ await new Promise(resolve => setTimeout(resolve, 10));
+ expect(fn()).toBe("2");
+ expect(fn()).toBe("2");
+ return "3";
+ },
+ );
+ await expectResolves(result);
+ expect(fn()).toBe("1");
+ await new Promise(resolve => setTimeout(resolve, 10));
+ expect(fn()).toBe("1");
+ });
+ test("lastCall works", () => {
+ const fn = jest.fn(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]);
+ });
+ test("invocationCallOrder works", () => {
+ const fn1 = jest.fn(v => -v);
+ const fn2 = jest.fn(v => -v);
+ fn1(1);
+ fn2(1);
+ fn2(1);
+ fn1(1);
+ const first = fn1.mock.invocationCallOrder[0];
+ expect(first).toBeGreaterThan(0);
+ expect(fn1.mock.invocationCallOrder).toEqual([first, first + 3]);
+ expect(fn2.mock.invocationCallOrder).toEqual([first + 1, first + 2]);
+ });
+});
+
+describe("spyOn", () => {
+ test("works on functions", () => {
+ var obj = {
+ original() {
+ return 42;
+ },
+ };
+ const fn = spyOn(obj, "original");
+ expect(fn).toBe(obj.original);
+ expect(fn).not.toHaveBeenCalled();
+ expect(() => expect(fn).toHaveBeenCalled()).toThrow();
+ expect(obj.original()).toBe(42);
+ expect(fn).toHaveBeenCalled();
+ expect(fn).toHaveBeenCalledTimes(1);
+ expect(() => expect(fn).not.toHaveBeenCalled()).toThrow();
+ expect(() => expect(fn).not.toHaveBeenCalledTimes(1)).toThrow();
+ expect(fn.mock.calls).toHaveLength(1);
+ expect(fn.mock.calls[0]).toBeEmpty();
+ jest.restoreAllMocks();
+ expect(() => expect(obj.original).toHaveBeenCalled()).toThrow();
+ expect(fn).not.toHaveBeenCalled();
+ expect(obj.original()).toBe(42);
+ expect(fn).not.toHaveBeenCalled();
+ });
+
+ test("override impl after doesnt break restore", () => {
+ var obj = {
+ original() {
+ return 42;
+ },
+ };
+ const fn = spyOn(obj, "original");
+ fn.mockImplementation(() => 43);
+ expect(fn).toBe(obj.original);
+ expect(obj.original()).toBe(43);
+ expect(fn).toHaveBeenCalled();
+ fn.mockRestore();
+ expect(obj.original()).toBe(42);
+ expect(fn).not.toHaveBeenCalled();
+ });
+
+ test("mockRestore works", () => {
+ var obj = {
+ original() {
+ return 42;
+ },
+ };
+ const fn = spyOn(obj, "original");
+ expect(fn).toBe(obj.original);
+ expect(fn).not.toHaveBeenCalled();
+ expect(() => expect(fn).toHaveBeenCalled()).toThrow();
+ expect(obj.original()).toBe(42);
+ expect(fn).toHaveBeenCalled();
+ expect(fn).toHaveBeenCalledTimes(1);
+ expect(() => expect(fn).not.toHaveBeenCalled()).toThrow();
+ expect(() => expect(fn).not.toHaveBeenCalledTimes(1)).toThrow();
+ expect(fn.mock.calls).toHaveLength(1);
+ expect(fn.mock.calls[0]).toBeEmpty();
+ fn.mockRestore();
+ expect(() => expect(obj.original).toHaveBeenCalled()).toThrow();
+ expect(fn).not.toHaveBeenCalled();
+ expect(obj.original()).toBe(42);
+ expect(fn).not.toHaveBeenCalled();
+ });
+
+ if (isBun) {
+ // Jest doesn't allow spying on properties
+ test("spyOn works on object", () => {
+ var obj = { original: 42 };
+ obj.original = 42;
+ const fn = spyOn(obj, "original");
+ expect(fn).not.toHaveBeenCalled();
+ expect(obj.original).toBe(42);
+ expect(fn).toHaveBeenCalled();
+ expect(fn).toHaveBeenCalledTimes(1);
+ expect(fn.mock.calls).toHaveLength(1);
+ expect(fn.mock.calls[0]).toBeEmpty();
+ jest.restoreAllMocks();
+ expect(() => expect(obj.original).toHaveBeenCalled()).toThrow();
+ });
+
+ test("spyOn on object doens't crash if object GC'd", () => {
+ const spies = new Array(1000);
+ (() => {
+ for (let i = 0; i < 1000; i++) {
+ var obj = { original: 42 };
+ obj.original = 42;
+ const fn = spyOn(obj, "original");
+ spies[i] = fn;
+ }
+ Bun.gc(true);
+ })();
+ Bun.gc(true);
+
+ jest.restoreAllMocks();
+ });
+
+ test("spyOn works on globalThis", () => {
+ var obj = globalThis;
+ obj.original = 42;
+ const fn = spyOn(obj, "original");
+ expect(fn).not.toHaveBeenCalled();
+ expect(obj.original).toBe(42);
+ expect(fn).toHaveBeenCalled();
+ expect(fn).toHaveBeenCalledTimes(1);
+ expect(fn.mock.calls).toHaveLength(1);
+ expect(fn.mock.calls[0]).toBeEmpty();
+ jest.restoreAllMocks();
+ expect(() => expect(obj.original).toHaveBeenCalled()).toThrow();
+ obj.original;
+ expect(fn).not.toHaveBeenCalled();
+ });
+ }
+
+ // spyOn does not work with getters/setters yet.
+});
diff --git a/test/js/bun/test/mock-test.test.ts b/test/js/bun/test/mock-test.test.ts
deleted file mode 100644
index 8c998942c..000000000
--- a/test/js/bun/test/mock-test.test.ts
+++ /dev/null
@@ -1,224 +0,0 @@
-import { test, mock, expect, spyOn, jest } from "bun:test";
-
-test("mockResolvedValue", async () => {
- const fn = mock.mockResolvedValueOnce(42).mockResolvedValue(43);
- expect(await fn()).toBe(42);
- expect(await fn()).toBe(43);
- expect(await fn()).toBe(43);
-});
-
-test("mockRejectedValue", async () => {
- const fn = mock.mockRejectedValue(42);
- expect(await fn()).toBe(42);
- fn.mockRejectedValue(43);
- expect(await fn()).toBe(43);
-});
-
-test("are callable", () => {
- const fn = mock(() => 42);
- 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()).toBe(42);
- expect(fn).toHaveBeenCalledTimes(2);
-
- expect(fn.mock.calls).toHaveLength(2);
- expect(fn.mock.calls[1]).toBeEmpty();
-});
-
-test(".call works", () => {
- const fn = mock(function hey() {
- // @ts-expect-error
- return this;
- });
- expect(fn.call(123)).toBe(123);
- expect(fn).toHaveBeenCalled();
- expect(fn).toHaveBeenCalledTimes(1);
- expect(fn.mock.calls).toHaveLength(1);
- expect(fn.mock.calls[0]).toBeEmpty();
-
- expect(fn()).toBe(undefined);
- expect(fn).toHaveBeenCalledTimes(2);
-
- expect(fn.mock.calls).toHaveLength(2);
- expect(fn.mock.calls[1]).toBeEmpty();
-});
-
-test(".apply works", () => {
- const fn = mock(function hey() {
- // @ts-expect-error
- return this;
- });
- expect(fn.apply(123)).toBe(123);
- expect(fn).toHaveBeenCalled();
- expect(fn).toHaveBeenCalledTimes(1);
- expect(fn.mock.calls).toHaveLength(1);
- expect(fn.mock.calls[0]).toBeEmpty();
-
- expect(fn.apply(undefined)).toBe(undefined);
- expect(fn).toHaveBeenCalledTimes(2);
-
- expect(fn.mock.calls).toHaveLength(2);
- expect(fn.mock.calls[1]).toBeEmpty();
-});
-
-test(".bind works", () => {
- const fn = mock(function hey() {
- // @ts-expect-error
- return this;
- });
- expect(fn.bind(123)()).toBe(123);
- expect(fn).toHaveBeenCalled();
- expect(fn).toHaveBeenCalledTimes(1);
- expect(fn.mock.calls).toHaveLength(1);
- expect(fn.mock.calls[0]).toBeEmpty();
-
- expect(fn.bind(undefined)()).toBe(undefined);
- expect(fn).toHaveBeenCalledTimes(2);
-
- expect(fn.mock.calls).toHaveLength(2);
- expect(fn.mock.calls[1]).toBeEmpty();
-});
-
-test(".name works", () => {
- const fn = mock(function hey() {
- // @ts-expect-error
- return this;
- });
- expect(fn.name).toBe("hey");
-});
-
-test(".name throwing doesnt segfault", () => {
- function baddie() {
- // @ts-expect-error
- return this;
- }
- Object.defineProperty(baddie, "name", {
- get() {
- throw new Error("foo");
- },
- });
-
- const fn = mock(baddie);
- fn.name;
-});
-
-test("include arguments", () => {
- const fn = mock(f => f);
- expect(fn(43)).toBe(43);
- expect(fn.mock.results[0]).toEqual({
- type: "return",
- value: 43,
- });
- expect(fn.mock.calls[0]).toEqual([43]);
-});
-
-test("works when throwing", () => {
- const instance = new Error("foo");
- const fn = mock(f => {
- throw instance;
- });
- expect(() => fn(43)).toThrow("foo");
- expect(fn.mock.results[0]).toEqual({
- type: "throw",
- value: instance,
- });
- expect(fn.mock.calls[0]).toEqual([43]);
-});
-
-test("mockReset works", () => {
- const instance = new Error("foo");
- const fn = mock(f => {
- throw instance;
- });
- expect(() => fn(43)).toThrow("foo");
- expect(fn.mock.results[0]).toEqual({
- type: "throw",
- value: instance,
- });
- expect(fn.mock.calls[0]).toEqual([43]);
-
- fn.mockReset();
-
- expect(fn.mock.calls).toBeEmpty();
- expect(fn.mock.results).toBeEmpty();
- expect(fn.mock.instances).toBeEmpty();
- expect(fn).not.toHaveBeenCalled();
-
- expect(() => fn(43)).toThrow("foo");
- expect(fn.mock.results[0]).toEqual({
- type: "throw",
- value: instance,
- });
- expect(fn.mock.calls[0]).toEqual([43]);
-});
-
-test("spyOn works on functions", () => {
- var obj = {
- original() {
- return 42;
- },
- };
- const fn = spyOn(obj, "original");
- expect(fn).not.toHaveBeenCalled();
- expect(obj.original()).toBe(42);
- expect(fn).toHaveBeenCalled();
- expect(fn).toHaveBeenCalledTimes(1);
- expect(fn.mock.calls).toHaveLength(1);
- expect(fn.mock.calls[0]).toBeEmpty();
- jest.restoreAllMocks();
- expect(() => expect(obj.original).toHaveBeenCalled()).toThrow();
-});
-
-test("spyOn works on object", () => {
- var obj = { original: 42 };
- obj.original = 42;
- const fn = spyOn(obj, "original");
- expect(fn).not.toHaveBeenCalled();
- expect(obj.original).toBe(42);
- expect(fn).toHaveBeenCalled();
- expect(fn).toHaveBeenCalledTimes(1);
- expect(fn.mock.calls).toHaveLength(1);
- expect(fn.mock.calls[0]).toBeEmpty();
- jest.restoreAllMocks();
- expect(() => expect(obj.original).toHaveBeenCalled()).toThrow();
-});
-
-test("spyOn on object doens't crash if object GC'd", () => {
- const spies = new Array(1000);
- (() => {
- for (let i = 0; i < 1000; i++) {
- var obj = { original: 42 };
- obj.original = 42;
- const fn = spyOn(obj, "original");
- spies[i] = fn;
- }
- Bun.gc(true);
- })();
- Bun.gc(true);
-
- jest.restoreAllMocks();
-});
-
-declare global {
- var original: number;
-}
-
-test("spyOn works on globalThis", () => {
- var obj = globalThis;
- obj.original = 42;
- const fn = spyOn(obj, "original");
- expect(fn).not.toHaveBeenCalled();
- expect(obj.original).toBe(42);
- expect(fn).toHaveBeenCalled();
- expect(fn).toHaveBeenCalledTimes(1);
- expect(fn.mock.calls).toHaveLength(1);
- expect(fn.mock.calls[0]).toBeEmpty();
- jest.restoreAllMocks();
- expect(() => expect(obj.original).toHaveBeenCalled()).toThrow();
- obj.original;
- expect(fn).not.toHaveBeenCalled();
-});
diff --git a/test/js/bun/test/test-interop.js b/test/js/bun/test/test-interop.js
new file mode 100644
index 000000000..5c41082d6
--- /dev/null
+++ b/test/js/bun/test/test-interop.js
@@ -0,0 +1,45 @@
+module.exports = () => {
+ if (globalThis.Bun) {
+ /** @type {import('bun:jsc')} */
+ const jsc = require("bun:jsc");
+ const source = Bun.fileURLToPath(jsc.callerSourceOrigin());
+ const bunTest = Bun.jest(source);
+ return {
+ isBun: true,
+ bunTest,
+ test: bunTest.test,
+ describe: bunTest.describe,
+ it: bunTest.it,
+ expect: bunTest.expect,
+ beforeEach: bunTest.beforeEach,
+ afterEach: bunTest.afterEach,
+ beforeAll: bunTest.beforeAll,
+ afterAll: bunTest.afterAll,
+ jest: bunTest.jest,
+ mock: bunTest.mock,
+ vi: bunTest.vi,
+ spyOn: bunTest.spyOn,
+ };
+ } else {
+ const globals = require("@jest/globals");
+ const extended = require("jest-extended");
+ globals.expect.extend(extended);
+ globals.test.todo = globals.test;
+ return {
+ isBun: false,
+ bunTest: null,
+ test: globals.test,
+ describe: globals.describe,
+ it: globals.it,
+ expect: globals.expect,
+ beforeEach: globals.beforeEach,
+ afterEach: globals.afterEach,
+ beforeAll: globals.beforeAll,
+ afterAll: globals.afterAll,
+ jest: globals.jest,
+ mock: null,
+ vi: null,
+ spyOn: globals.jest.spyOn,
+ };
+ }
+};
diff --git a/test/js/bun/test/test-test.test.ts b/test/js/bun/test/test-test.test.ts
index ed71e7652..7ecfdef11 100644
--- a/test/js/bun/test/test-test.test.ts
+++ b/test/js/bun/test/test-test.test.ts
@@ -50,1429 +50,6 @@ it("shouldn't crash when async test runner callback throws", async () => {
}
});
-test("toStrictEqual() vs toEqual()", () => {
- expect([1, , 3]).toEqual([1, , 3]);
- expect({}).toEqual({});
- expect({}).toStrictEqual({});
- expect({}).toEqual({ a: undefined });
- expect({}).not.toStrictEqual({ a: undefined });
-
- class C {
- hi = 34;
- }
- class D {
- hi = 34;
- }
- let c = new C();
- let d = new D();
-
- expect(d).toEqual(c);
- expect(d).not.toStrictEqual(c);
- expect({ a: 1, b: undefined }).toEqual({ a: 1 });
- expect({ a: 1 }).toEqual({ a: 1, b: undefined });
- expect({ a: 1, b: undefined }).toEqual({ a: 1, b: undefined });
-
- expect({ a: 1, b: undefined }).not.toStrictEqual({ a: 1 });
- expect({ a: 1 }).not.toStrictEqual({ a: 1, b: undefined });
- expect({ a: 1, b: undefined }).toStrictEqual({ a: 1, b: undefined });
-
- expect({ a: 1, b: null }).not.toEqual({ a: 1 });
- expect({ a: 1 }).not.toEqual({ a: 1, b: null });
- expect({ a: 1, b: null }).toEqual({ a: 1, b: null });
-
- expect({ a: 1 }).not.toEqual({ a: true });
- expect({ a: 1 }).not.toEqual({ a: "1" });
- expect({ a: 1 }).not.toEqual({ a: 1, b: 2 });
- expect({ a: 1, b: 2 }).not.toEqual({ a: 1 });
- expect({ a: 1 }).not.toStrictEqual({ a: true });
- expect({ a: 1 }).not.toStrictEqual({ a: "1" });
- expect({ a: 1 }).not.toStrictEqual({ a: 1, b: 2 });
- expect({ a: 1, b: 2 }).not.toStrictEqual({ a: 1 });
- expect({ a: 1 }).toStrictEqual({ a: 1 });
-
- expect([1, undefined, 3]).toEqual([1, undefined, 3]);
- expect([1, undefined, 3]).toStrictEqual([1, undefined, 3]);
- expect([1, undefined, 3]).not.toEqual([1, 2, 3]);
- expect([1, undefined, 3]).not.toStrictEqual([1, 2, 3]);
- expect([1, undefined, 3]).not.toEqual([1, 2]);
- expect([1, undefined, 3]).not.toStrictEqual([1, 2]);
- expect([1, undefined, 3]).not.toEqual([1]);
- expect([1, undefined, 3]).not.toStrictEqual([1]);
- expect([1, undefined, 3]).not.toEqual([]);
- expect([1, undefined, 3]).not.toStrictEqual([]);
- expect([1, undefined, 3]).not.toEqual([1, 3]);
- expect([1, undefined, 3]).not.toStrictEqual([1, 3]);
-
- expect([1, null, 3]).toEqual([1, null, 3]);
- expect([1, null, 3]).toStrictEqual([1, null, 3]);
- expect([1, null, 3]).not.toEqual([1, 2, 3]);
- expect([1, null, 3]).not.toStrictEqual([1, 2, 3]);
- expect([1, null, 3]).not.toEqual([1, 2]);
- expect([1, null, 3]).not.toStrictEqual([1, 2]);
- expect([1, null, 3]).not.toEqual([1]);
- expect([1, null, 3]).not.toStrictEqual([1]);
- expect([1, null, 3]).not.toEqual([]);
- expect([1, null, 3]).not.toStrictEqual([]);
- expect([1, null, 3]).not.toEqual([1, 3]);
- expect([1, null, 3]).not.toStrictEqual([1, 3]);
-
- expect([, 1]).toEqual([, 1]);
- expect([, 1]).toStrictEqual([, 1]);
- expect([, 1]).not.toEqual([1]);
- expect([1]).not.toEqual([, 1]);
- expect([, 1]).not.toStrictEqual([1]);
- expect([1]).not.toStrictEqual([, 1]);
- expect([, 1]).toEqual([undefined, 1]);
- expect([, 1]).not.toStrictEqual([undefined, 1]);
- expect([, 1]).not.toEqual([null, 1]);
- expect([, 1]).not.toStrictEqual([null, 1]);
- expect([undefined, 1]).toEqual([, 1]);
- expect([undefined, 1]).not.toStrictEqual([, 1]);
- expect([null, 1]).not.toEqual([, 1]);
- expect([null, 1]).not.toStrictEqual([, 1]);
- expect([undefined, 1]).toEqual([undefined, 1]);
- expect([undefined, 1]).toStrictEqual([undefined, 1]);
-
- expect([0, , 2]).toEqual([0, undefined, 2]);
- expect([, "boo2"]).toEqual([undefined, "boo2"]);
- expect([, "boo"]).toEqual([, "boo"]);
- expect([, 1]).toEqual([undefined, 1]);
-
- const s1 = Symbol("test1");
- const s2 = Symbol("test2");
-
- let a = { a: 1, b: 2 };
- let b = { a: 1, b: 2 };
- a[s1] = 1;
- b[s1] = 1;
- a[s2] = undefined;
- b[s2] = null;
- expect(a).not.toEqual(b);
- class F extends String {
- constructor() {
- super();
- }
- }
-
- let f = new F("hello");
- let j = new String("hello");
- expect(f).not.toEqual(j);
- class LaCroix {
- constructor(flavor) {
- this.flavor = flavor;
- }
- }
- expect(new LaCroix("pamplemousse")).not.toStrictEqual({
- flavor: "pamplemousse",
- });
- expect(new LaCroix("pamplemousse")).toEqual({ flavor: "pamplemousse" });
-
- expect([, 1]).not.toStrictEqual([undefined, 1]);
-
- expect([0, , 2]).toEqual([0, undefined, 2]);
- expect([, "boo2"]).toEqual([undefined, "boo2"]);
- expect([, "boo"]).toEqual([, "boo"]);
- expect([, 1]).toEqual([undefined, 1]);
-});
-
-function f1() {
- return "hello!";
-}
-function f2() {
- return "hey!";
-}
-test("deepEquals regex", () => {
- expect(/a/imu).toEqual(/a/imu);
- expect(/a/imu).not.toEqual(/ab/imu);
-
- expect(new RegExp("s", "g")).toEqual(new RegExp("s", "g"));
- expect(new RegExp("s", "g")).not.toEqual(new RegExp("s", "i"));
-});
-
-test("deepEquals works with accessors", () => {
- {
- let l1 = [1, undefined, 2];
- let l2 = [1, undefined, 2];
- Object.defineProperty(l1, 6, { get: () => 1 });
- Object.defineProperty(l2, 6, { get: () => 1 });
- expect(l1).toEqual(l2);
- expect(l1).toStrictEqual(l2);
- }
- {
- let l1 = [1, , 2];
- let l2 = [1, undefined, 2];
- Object.defineProperty(l1, 6, { get: () => 1 });
- Object.defineProperty(l2, 6, { get: () => 2 });
- expect(l1).toEqual(l2);
- expect(l1).not.toStrictEqual(l2);
- }
- {
- let l1 = [1, , 2];
- let l2 = [1, , 2];
- Object.defineProperty(l1, "hi", { get: () => 4 });
- Object.defineProperty(l2, "hi", { get: () => 5 });
- expect(l1).toEqual(l2);
- expect(l1).toStrictEqual(l2);
- }
-
- {
- let l1 = [1, , 2];
- let l2 = [1, , 2];
- Object.defineProperty(l1, "hi", { set: () => 4 });
- Object.defineProperty(l2, "hi", { set: () => 5 });
- expect(l1).toEqual(l2);
- expect(l1).toStrictEqual(l2);
- }
-
- {
- let o1 = { a: 1, c: undefined, b: 2 };
- let o2 = { a: 1, c: undefined, b: 2 };
- Object.defineProperty(o1, 6, { get: () => 1 });
- Object.defineProperty(o2, 6, { get: () => 1 });
- expect(o1).toEqual(o2);
- expect(o1).toStrictEqual(o2);
- }
- {
- let o1 = { a: 1, c: undefined, b: 2 };
- let o2 = { a: 1, c: undefined, b: 2 };
- Object.defineProperty(o1, 6, { get: () => 1 });
- Object.defineProperty(o2, 6, { get: () => 2 });
- expect(o1).toEqual(o2);
- expect(o1).toStrictEqual(o2);
- }
- {
- let o1 = { a: 1, c: undefined, b: 2 };
- let o2 = { a: 1, c: undefined, b: 2 };
- Object.defineProperty(o1, "hi", { get: () => 4 });
- Object.defineProperty(o2, "hi", { get: () => 5 });
- expect(o1).toEqual(o2);
- expect(o1).toStrictEqual(o2);
- }
-
- {
- let o1 = { a: 1, c: undefined, b: 2 };
- let o2 = { a: 1, c: undefined, b: 2 };
- Object.defineProperty(o1, "hi", { set: () => 4 });
- Object.defineProperty(o2, "hi", { set: () => 5 });
- expect(o1).toEqual(o2);
- expect(o1).toStrictEqual(o2);
- }
-});
-
-test("deepEquals works with proxies", () => {
- {
- let p1 = new Proxy({ a: 1, b: 2 }, {});
- let p2 = new Proxy({ a: 1, b: 2 }, {});
- expect(p1).toEqual(p2);
- expect(p1).toStrictEqual(p2);
- let p3 = new Proxy({ a: 1, b: 2 }, {});
- let p4 = new Proxy({ a: 1, b: 3 }, {});
- expect(p3).not.toEqual(p4);
- expect(p3).not.toStrictEqual(p4);
- }
- {
- let t1 = { a: 1, b: 2 };
- let h1 = { get: (t, k) => t[k] };
- let p1 = new Proxy(t1, h1);
- let t2 = { a: 1, b: 2 };
- let h2 = { get: (t, k) => 0 };
- let p2 = new Proxy(t2, h2);
- expect(p1).not.toEqual(p2);
- expect(p1).not.toStrictEqual(p2);
- }
- {
- let t1 = { a: 1, b: 2 };
- let h1 = { get: (t, k) => t[k] + 2 };
- let p1 = new Proxy(t1, h1);
- let t2 = { a: 1, b: 2 };
- let h2 = { get: (t, k) => t[k] + 2 };
- let p2 = new Proxy(t2, h2);
- expect(p1).toEqual(p2);
- expect(p1).toStrictEqual(p2);
- }
- {
- let t1 = { a: 1, b: 2 };
- let h1 = { get: (t, k) => t[k] + 2 };
- let p1 = new Proxy(t1, h1);
- let t2 = { a: 1, b: 2 };
- let h2 = { get: (t, k) => t[k] + 3 };
- let p2 = new Proxy(t2, h2);
- expect(p1).not.toEqual(p2);
- expect(p1).not.toStrictEqual(p2);
- }
- {
- // same handlers, different targets
- let t1 = { a: 1, b: 2 };
- let t2 = { a: 1, b: 2 };
- let h1 = { get: (t, k) => t[k] + 2 };
- let p1 = new Proxy(t1, h1);
- let p2 = new Proxy(t2, h1);
- expect(p1).toEqual(p2);
- expect(p1).toStrictEqual(p2);
- }
- {
- // same targets, different handlers
- let t1 = { a: 1, b: 2 };
- let h1 = { get: (t, k) => t[k] + 2 };
- let h2 = { get: (t, k) => t[k] + 3 };
- let p1 = new Proxy(t1, h1);
- let p2 = new Proxy(t1, h2);
- expect(p1).not.toEqual(p2);
- expect(p1).not.toStrictEqual(p2);
- }
- {
- // property with object
- let t1 = { a: { b: 3 } };
- let h1 = { get: (t, k) => t[k] };
- let p1 = new Proxy(t1, h1);
-
- let t2 = { a: { b: 3 } };
- let h2 = { get: (t, k) => t[k] };
- let p2 = new Proxy(t2, h2);
-
- expect(p1).toEqual(p2);
- expect(p1).toStrictEqual(p2);
-
- let t3 = { a: { b: 3 } };
- let h3 = { get: (t, k) => t[k] };
- let p3 = new Proxy(t3, h3);
-
- let t4 = { a: { b: 4 } };
- let h4 = { get: (t, k) => t[k] };
- let p4 = new Proxy(t4, h4);
-
- expect(p3).not.toEqual(p4);
- expect(p3).not.toStrictEqual(p4);
- }
- {
- // proxy object equals itself
- let t1 = { a: 1, b: 2 };
- let h1 = { get: (t, k) => t[k] + 2 };
- let p1 = new Proxy(t1, h1);
- expect(p1).toEqual(p1);
- expect(p1).toStrictEqual(p1);
- }
- {
- let t1 = { a: 1, b: 2 };
- let h1 = { get: (t, k) => k };
- let p1 = new Proxy(t1, h1);
-
- let t2 = { a: 1, b: 2 };
- let h2 = { get: (t, k) => k };
- let p2 = new Proxy(t2, h2);
-
- expect(p1).toEqual(p2);
- expect(p1).toStrictEqual(p2);
- }
-});
-
-test("deepEquals works with sets/maps/dates/strings", () => {
- const f = Symbol.for("foo");
-
- let a = new Set();
- a.add([1, 2, 3]);
- a.add("hello");
- a.add({ a: 1 });
- a.add(89);
-
- let b = new Set();
- b.add(89);
- b.add({ a: 1 });
- b.add("hello");
- b.add([1, 2, 3]);
-
- expect(a).toEqual(b);
- expect(b).toEqual(a);
- expect(b).toEqual(b);
-
- let obj = {};
- var c = new Set();
- obj.c = c;
- obj.x = obj;
- c.add(obj);
- expect(obj).toEqual(obj);
-
- let o1 = { a: new Set() };
- o1.a.add(o1);
- expect(o1).toEqual(o1);
-
- let o2 = new Set();
- let o3 = {};
- o3.x = o3;
- o2.add(o3);
- expect(o2).toEqual(o2);
-
- var d = new Date();
- var e = new Date(d);
- e[f] = "hello";
-
- expect(d).toEqual(e);
- expect(e).toEqual(d);
-
- class Date2 extends Date {
- constructor() {
- super(...arguments);
- }
- }
-
- class Date3 extends Date2 {
- constructor() {
- super(...arguments);
- }
- }
-
- let d2 = new Date2();
- let e2 = new Date(d2);
- d2[f] = "hello";
- expect(d2).toEqual(e2);
- expect(e2).toEqual(d2);
-
- let d3 = new Date3();
- let e3 = new Date(d3);
- d3[f] = "hello";
- expect(d3).toEqual(e3);
- expect(e3).toEqual(d3);
-
- let d4 = new Date();
- let e4 = new Date3(d4);
- d4[f] = "hello";
- expect(d4).toEqual(e4);
- expect(e4).toEqual(d4);
-
- let d5 = new Date2();
- let e5 = new Date3(d5);
- d5[f] = "hello";
- expect(d5).toEqual(e5);
- expect(e5).toEqual(d5);
-
- expect(new String("a")).not.toEqual(new String("b"));
-
- var s1 = new String("a");
- var s2 = new String("a");
- s1[f] = "hello";
- expect(s1).toEqual(s2);
-
- class String2 extends String {
- constructor() {
- super(...arguments);
- }
- }
-
- class String3 extends String2 {
- constructor() {
- super(...arguments);
- }
- }
-
- let string4 = {};
- string4.__proto__ = String3.prototype;
-
- var s3 = new String2("a");
- var s4 = new String2("a");
- s3[f] = "hello";
- expect(s3).toEqual(s4);
-
- var s5 = new String("a");
- var s6 = new String3("a");
- expect(s6).not.toEqual(s5);
- expect(s5).not.toEqual(s6);
-
- var s7 = new String2("a");
- var s8 = new String3("a");
- expect(s7).not.toEqual(s8);
- expect(s8).not.toEqual(s7);
-
- var s9 = new String2("a");
- var s10 = new string4.constructor("a");
- expect(s9).not.toEqual(s10);
- expect(s10).not.toEqual(s9);
-
- class F2 extends Function {}
- class F3 extends F2 {}
-
- var f1 = new Function();
- var f2 = new F2();
- var f3 = new F3();
- expect(f1).not.toEqual(f2);
- expect(f2).not.toEqual(f1);
- expect(f2).not.toEqual(f3);
- expect(f3).not.toEqual(f2);
-});
-
-describe("deepEquals with asymmetric matchers", () => {
- it("should accept any string", () => {
- expect({ name: "alice" }).toEqual({ name: expect.any(String) });
- expect({ name: "bob" }).toEqual({ name: expect.any(String) });
- expect({ name: "charlie" }).toEqual({ name: expect.any(String) });
- });
-
- it("should accept any number", () => {
- expect({ age: 42 }).toEqual({ age: expect.any(Number) });
- expect({ age: 69 }).toEqual({ age: expect.any(Number) });
- expect({ age: 73 }).toEqual({ age: expect.any(Number) });
- });
-
- it("should accept any boolean", () => {
- expect({ active: false }).toEqual({ active: expect.any(Boolean) });
- expect({ active: true }).toEqual({ active: expect.any(Boolean) });
- });
-
- it("should not match the wrong constructors", () => {
- function f() {
- return 32;
- }
- Object.defineProperty(f, "name", { value: "String" });
- expect({ a: "123" }).toEqual({ a: expect.any(String) });
- expect({ a: "123" }).not.toEqual({ a: expect.any(f) });
-
- function g() {
- return 32;
- }
- Object.defineProperty(g, "name", { value: "BigInt" });
- expect({ a: 123n }).toEqual({ a: expect.any(BigInt) });
- expect({ a: 123n }).not.toEqual({ a: expect.any(g) });
- });
-});
-
-test("toThrow", () => {
- expect(() => {
- throw new Error("hello");
- }).toThrow("hello");
-
- var err = new Error("bad");
- expect(() => {
- throw err;
- }).toThrow(err);
-
- expect(() => {
- throw new Error("good");
- }).toThrow();
-
- expect(() => {
- throw new Error("foo");
- }).toThrow(/oo/);
-
- expect(() =>
- expect(() => {
- throw new Error("bar");
- }).toThrow(/baz/),
- ).toThrow("/baz/");
-
- expect(() => {
- return true;
- }).not.toThrow();
-
- expect(() => {
- return true;
- }).not.toThrow(err);
-
- const weirdThings = [
- /watttt/g,
- BigInt(123),
- -42,
- NaN,
- Infinity,
- -Infinity,
- undefined,
- null,
- true,
- false,
- 0,
- 1,
- "",
- "hello",
- {},
- [],
- new Date(),
- new Error(),
- new RegExp("foo"),
- new Map(),
- new Set(),
- Promise.resolve(),
- Promise.reject(Symbol("123")).finally(() => {}),
- Symbol("123"),
- ];
- for (const weirdThing of weirdThings) {
- expect(() => {
- throw weirdThing;
- }).toThrow();
- }
-
- err.message = "null";
- expect(() => {
- throw null;
- }).toThrow(err);
-});
-
-test("deepEquals derived strings and strings", () => {
- let a = new String("hello");
- let b = "hello";
- expect(a).toEqual(a);
- expect(b).toEqual(b);
- expect(a).not.toEqual(b);
- expect(b).not.toEqual(a);
-
- class F extends String {
- constructor() {
- super();
- }
- }
-
- let f = new F("hello");
- expect(f).toEqual(f);
- expect(f).not.toEqual(b);
- expect(b).not.toEqual(f);
-
- let j = new String("hello");
- expect(f).not.toEqual(j);
-
- class G extends String {
- constructor() {
- super();
- this.x = 0;
- }
- }
-
- let g = new G("hello");
- expect(g).not.toEqual(f);
- expect(f).not.toEqual(g);
- expect(g).toEqual(g);
- expect(g).not.toEqual(b);
- expect(b).not.toEqual(g);
- expect(g).not.toEqual(a);
-});
-
-test("deepEquals throw getters", () => {
- let a = {
- get x() {
- throw new Error("a");
- },
- };
-
- let b = {
- get x() {
- return 3;
- },
- };
-
- try {
- expect(a).not.toEqual(b);
- } catch (e) {
- expect(e.message).toContain("a");
- }
-
- class B {
- get x() {
- throw new Error("b");
- }
- }
-
- class C {
- get x() {
- return 3;
- }
- }
-
- expect(() => {
- expect(new B()).not.toEqual(new C());
- }).toThrow();
-
- let o = [
- {
- get x() {
- throw new Error("c");
- },
- },
- ];
-
- let p = [
- {
- get x() {
- return 3;
- },
- },
- ];
-
- try {
- expect(o).not.toEqual(p);
- } catch (e) {
- expect(e.message).toContain("c");
- }
-
- const s = Symbol("s");
- let q = {
- get x() {
- throw new Error("d");
- },
- };
- q[s] = 3;
-
- let r = {
- get x() {
- return 3;
- },
- };
- r[s] = 3;
-
- try {
- expect(q).not.toEqual(r);
- } catch (e) {
- expect(e.message).toContain("d");
- }
-});
-
-test("deepEquals large object", () => {
- let o = {};
- for (let i = 0; i < 65; i++) {
- o["bun" + i] = i;
- }
- expect(o).toEqual(o);
- let b = {};
- for (let i = 0; i < 63; i++) {
- b["bun" + i] = i;
- }
- expect(b).toEqual(b);
- expect(o).not.toEqual(b);
- expect(b).not.toEqual(o);
-
- let c = { d: [Array(o)] };
- let d = { d: [Array(b)] };
- expect(c).toEqual(c);
- expect(d).toEqual(d);
- expect(c).not.toEqual(d);
- expect(d).not.toEqual(c);
-
- let e = { d: [Array(o), Array(o)] };
- let f = { d: [Array(b), Array(b)] };
- expect(e).toEqual(e);
- expect(f).toEqual(f);
- expect(e).not.toEqual(f);
- expect(f).not.toEqual(e);
-
- let p = [];
- p[0] = {};
- for (let i = 0; i < 1000; i++) {
- p[0]["bun" + i] = i;
- }
- let q = [];
- q[0] = {};
- for (let i = 0; i < 1000; i++) {
- q[0]["bun" + i] = i;
- }
- expect(p).toEqual(p);
- expect(q).toEqual(q);
-
- q[0].bun789 = 788;
- expect(p).not.toEqual(q);
- expect(q).not.toEqual(p);
-
- let r = { d: {} };
- let s = { d: {} };
- for (let i = 0; i < 1000; i++) {
- r.d["bun" + i] = i;
- s.d["bun" + i] = i;
- }
-
- expect(r).toEqual(r);
- expect(s).toEqual(s);
-
- r.d.bun790 = 791;
- expect(r).not.toEqual(s);
- expect(s).not.toEqual(r);
-
- let t = [];
- t[5] = {};
- let u = [];
- u[5] = {};
- for (let i = 0; i < 1000; i++) {
- t[5]["bun" + i] = i;
- }
- for (let i = 0; i < 30; i++) {
- u[5]["bun" + i] = i;
- }
- expect(t).toEqual(t);
- expect(u).toEqual(u);
- expect(t).not.toEqual(u);
- expect(u).not.toEqual(t);
-
- let v = { j: {} };
- let w = { j: {} };
- for (let i = 0; i < 1000; i++) {
- v.j["bun" + i] = i;
- w.j["bun" + i] = i;
- }
-
- expect(v).toEqual(v);
- expect(w).toEqual(w);
-
- v.j.bun999 = 1000;
- expect(v).not.toEqual(w);
- expect(w).not.toEqual(v);
- expect(v).toEqual(v);
-
- v.j.bun999 = 999;
- w.j.bun0 = 1;
- expect(v).not.toEqual(w);
- expect(w).not.toEqual(v);
- expect(v).toEqual(v);
- expect(w).toEqual(w);
-});
-
-test("deepEquals - Date", () => {
- let d = new Date();
- expect(d).toEqual(d);
- let b = d;
- expect(b).toEqual(d);
- d.setFullYear(1998);
- expect(b).toEqual(d);
- expect(b).not.toEqual(new Date());
-
- var date = new Date();
- date.setFullYear(1995);
- expect(new Date()).not.toEqual(date);
-});
-
-test("deepEquals toString and functions", () => {
- expect({ toString: f1 }).toEqual({
- toString: f1,
- });
- expect({ toString: f1 }).not.toEqual({
- toString: f2,
- });
-
- expect(f1).toEqual(f1);
- expect(f1).not.toEqual(f2);
-});
-
-test("deepEquals set and map", () => {
- let e = new Map();
- e.set("a", 1);
- e.set("b", 2);
- e.set("c", 3);
- e.set(8, 6);
-
- let d = new Map();
- d.set("a", 1);
- d.set("b", 2);
- d.set("c", 3);
- d.set(8, 6);
-
- expect(e).toEqual(d);
- expect(d).toEqual(e);
-
- let f = new Map();
- f.set("a", 1);
- f.set("b", 2);
- f.set("c", 3);
- f.set(8, 7);
- expect(e).not.toEqual(f);
-
- let g = new Map();
- g.set({ a: { b: { c: 89 } } }, 1);
-
- let h = new Map();
- h.set({ a: { b: { c: 89 } } }, 1);
- expect(g).toEqual(h);
-
- let i = new Map();
- i.set({ a: { b: { c: 89 } } }, 1);
- i.set({ a: { b: { c: 89 } } }, 1);
- expect(g).not.toEqual(i);
-
- let j = new Map();
- j.set({ a: { b: { c: 89 } } }, 1);
- j.set({ a: { b: { c: 89 } } }, 1);
- expect(i).toEqual(j);
-
- let p = new Map();
- p.set({ a: { b: { c: 90 } } }, 1);
- expect(p).not.toEqual(g);
-
- let q = new Map();
- q.set({ a: { b: { c: 90 } } }, { a: { b: 45 } });
-
- let r = new Map();
- r.set({ a: { b: { c: 90 } } }, { a: { b: 45 } });
- expect(q).toEqual(r);
-
- let s = new Map();
- s.set({ a: { b: { c: 90 } } }, { a: { b: 49 } });
- expect(q).not.toEqual(s);
-
- const u = { a: 1, b: 2 };
-
- let a = new Set();
- a.add({ a: 1 });
- a.add([1, 2, 3]);
- a.add("hello");
- a.add(89);
-
- let b = new Set();
- b.add({ a: 1 });
- b.add("hello");
- b.add([1, 2, 3]);
- b.add(89);
- expect(a).toEqual(b);
- expect(b).toEqual(a);
- let c = new Set();
- c.add(89);
- c.add("hello");
- c.add({ a: 1 });
- c.add([1, 2, 3, 4]);
- expect(a).not.toEqual(c);
-});
-
-test("deepEquals - symbols", () => {
- const x = [5, 6];
- x[99] = 7;
-
- const y = [5, 6];
- y[99] = 7;
-
- expect(x).toEqual(y);
-
- const s1 = Symbol("test1");
- const s2 = Symbol("test2");
-
- const o = { a: 1 };
- o[s1] = 45;
- o[99] = 99;
- o[s2] = 3;
-
- const k = { a: 1 };
- k[99] = 99;
- k[s2] = 3;
- k[s1] = 45;
-
- expect(o).toEqual(k);
-});
-
-test("deepEquals should not segfault", () => {
- const obj = { ...Object.fromEntries(Object.entries([1, 2, 3, 4])), length: 4 };
- expect(() => {
- expect(obj).toEqual([1, 2, 3, 4]);
- }).toThrow();
- expect(() => {
- expect([1, 2, 3, 4]).toEqual(obj);
- }).toThrow();
-});
-
-test("toEqual objects and arrays", () => {
- {
- let obj = { 0: 4, 1: 3, length: 2 };
- expect(Array.from(obj)).toEqual([4, 3]);
- expect(Array.from(obj)).toStrictEqual([4, 3]);
- }
- {
- let obj = { 0: 4, 1: 3, length: 4 };
- expect(Array.from(obj)).toEqual([4, 3]);
- expect(Array.from(obj)).not.toStrictEqual([4, 3]);
- expect(Array.from(obj)).toEqual([4, 3, undefined, undefined]);
- expect(Array.from(obj)).toStrictEqual([4, 3, undefined, undefined]);
- expect(Array.from(obj)).toEqual([4, 3, , ,]);
- expect(Array.from(obj)).not.toStrictEqual([4, 3, , ,]);
- }
- {
- let a1 = [1, undefined, 3, , 4, null];
- let a2 = [1, undefined, 3, , 4, null, , ,];
- expect(a1).toEqual(a2);
- expect(a1).not.toStrictEqual(a2);
- expect(a2).toEqual(a1);
- expect(a2).not.toStrictEqual(a1);
- }
- {
- let a1 = [, , , , , , , , , , , ,];
- let a2 = [undefined];
- expect(a1).toEqual(a2);
- expect(a1).not.toStrictEqual(a2);
- expect(a2).toEqual(a1);
- expect(a2).not.toStrictEqual(a1);
- }
- {
- const a = [1];
- const b = [1];
- expect(a).toEqual(b);
- Object.preventExtensions(b);
- expect(a).toEqual(b);
- Object.preventExtensions(a);
- expect(a).toEqual(b);
- }
- {
- let o1 = { 1: 4, 6: 3 };
- let o2 = { 1: 4, 6: 3 };
- expect(o1).toEqual(o2);
- expect(o1).toStrictEqual(o2);
- }
- {
- let o1 = { 1: 4, 6: 2 };
- let o2 = { 1: 4, 6: 3 };
- expect(o1).not.toEqual(o2);
- expect(o1).not.toStrictEqual(o2);
- }
-
- {
- let o1 = { a: 1, 3: 0 };
- let o2 = { a: 1, 3: 0 };
- expect(o1).toEqual(o2);
- expect(o1).toStrictEqual(o2);
- }
- {
- let o1 = { a: 1, 3: 0 };
- let o2 = { a: 1, 3: 1 };
- expect(o1).not.toEqual(o2);
- expect(o1).not.toStrictEqual(o2);
- }
- {
- let o1 = { a: {}, 4: { b: 3, c: { 9: 2 } } };
- let o2 = { a: {}, 4: { b: 3, c: { 9: 2 } } };
- expect(o1).toEqual(o2);
- expect(o1).toStrictEqual(o2);
- }
- {
- let o1 = { a: {}, 4: { b: 3, c: { 9: 2 } } };
- let o2 = { a: {}, 4: { b: 3, c: { 9: 3 } } };
- expect(o1).not.toEqual(o2);
- expect(o1).not.toStrictEqual(o2);
- }
-
- {
- let o1 = { a: 1, b: 2, c: 3 };
- let o2 = { a: 1, b: 2, c: 3, 0: 1 };
- expect(o1).not.toEqual(o2);
- expect(o1).not.toStrictEqual(o2);
- }
-
- {
- let o1 = { a: 1, b: 2, c: 3, 0: 1 };
- let o2 = { a: 1, b: 2, c: 3 };
- expect(o1).not.toEqual(o2);
- expect(o1).not.toStrictEqual(o2);
- }
-
- expect("hello").toEqual("hello");
- const s1 = Symbol("test1");
- const s2 = Symbol("test2");
-
- expect({ a: 1, b: 2 }).toEqual({ b: 2, a: 1 });
- expect([1, 2, 3]).toEqual([1, 2, 3]);
- expect({ a: 1, b: 2 }).not.toEqual({ b: 2, a: 1, c: 3 });
- expect([1, 2, 3]).not.toEqual([1, 2, 3, 4]);
- expect({ a: 1, b: 2, c: 3 }).not.toEqual({ a: 1, b: 2 });
- expect([1, 2, 3, 4]).not.toEqual([1, 2, 3]);
-
- let a = [{ a: 1 }, { b: 2, c: 3, d: 4 }, { e: 5, f: 6 }];
- let b = [{ a: 1 }, { b: 2, c: 3, d: 4 }, { e: 5, f: 6 }];
- expect(a).toEqual(b);
- expect(b).toEqual(a);
- a[0].a = 2;
- expect(a).not.toEqual(b);
- expect(b).not.toEqual(a);
-
- let c = { [Symbol("test")]: 1 };
- let d = { [Symbol("test")]: 1 };
- expect(c).not.toEqual(d);
- expect(d).not.toEqual(c);
-
- a = { [s1]: 1 };
- a[s1] = 1;
- b = { [s2]: 1 };
- b[s2] = 1;
- expect(a).not.toEqual(b);
- expect(b).not.toEqual(a);
-
- a = {};
- b = {};
- a[s1] = 1;
- b[s1] = 1;
- expect(a).toEqual(b);
-
- a = {};
- b = {};
- a[s1] = 1;
- b[s1] = 2;
- expect(a).not.toEqual(b);
-
- a = {};
- b = {};
- a[s1] = 1;
- b[s1] = 1;
- a[s2] = 2;
- b[s2] = 2;
- expect(a).toEqual(b);
-
- a = {};
- b = {};
- a[s1] = 1;
- b[s1] = 1;
- a[s2] = 2;
- b[s2] = 3;
- expect(a).not.toEqual(b);
-
- a = { a: 1, b: 2 };
- b = { a: 1, b: 2 };
- a[s1] = 1;
- b[s1] = 1;
- expect(a).toEqual(b);
-
- a = { a: 2, b: 2 };
- b = { a: 1, b: 2 };
- a[s1] = 1;
- b[s1] = 1;
- expect(a).not.toEqual(b);
-
- // do the same tests for arrays
- a = [{ a: 1 }, { b: 2, c: 3, d: 4 }, { e: 5, f: 6 }];
- b = [{ a: 1 }, { b: 2, c: 3, d: 4 }, { e: 5, f: 6 }];
- expect(a).toEqual(b);
- expect(b).toEqual(a);
- a[0].a = 2;
- expect(a).not.toEqual(b);
- expect(b).not.toEqual(a);
-
- a = [1, 2, 3];
- b = [1, 2, 3];
- a[s1] = 1;
- b[s1] = 1;
- expect(a).toEqual(b);
-
- a = [1, 2, 3];
- b = [1, 2, 3];
- a[s1] = 1;
- b[s1] = 2;
- expect(a).not.toEqual(b);
-
- a = [1, 2, 3];
- b = [1, 2, 3];
- a[s1] = 1;
- b[s1] = 1;
- a[s2] = 2;
- b[s2] = 2;
- expect(a).toEqual(b);
-
- a = [1, 2, 3];
- b = [1, 2, 3];
- a[s1] = 1;
- b[s1] = 1;
- a[s2] = 2;
- b[s2] = 3;
- expect(a).not.toEqual(b);
-
- a = [1, 2, 3];
- b = [1, 2, 3];
- a[s1] = 1;
- b[s1] = 1;
- expect(a).toEqual(b);
-
- a = [2, 2, 3];
- b = [1, 2, 3];
- a[s1] = 1;
- b[s1] = 1;
- expect(a).not.toEqual(b);
-
- // do the same tests for objects and arrays with null and undefined
- a = { a: 1, b: 2 };
- b = { a: 1, b: 2 };
- a[s1] = 1;
- b[s1] = 1;
- a[s2] = null;
- b[s2] = undefined;
- expect(a).not.toEqual(b);
-
- a = { a: 1, b: 2 };
- b = { a: 1, b: 2 };
- a[s1] = 1;
- b[s1] = 1;
- a[s2] = undefined;
- b[s2] = null;
- expect(a).not.toEqual(b);
-
- a = { a: 1, b: 2 };
- b = { a: 1, b: 2 };
- a[s1] = 1;
- b[s1] = 1;
- a[s2] = null;
- b[s2] = null;
- expect(a).toEqual(b);
-
- a = { a: 1, b: 2 };
- b = { a: 1, b: 2 };
- a[s1] = 1;
- b[s1] = 1;
- a[s2] = undefined;
- b[s2] = undefined;
- expect(a).toEqual(b);
-
- a = [1, 2, 3];
- b = [1, 2, 3];
- a[s1] = 1;
- b[s1] = 1;
- a[s2] = null;
- b[s2] = undefined;
- expect(a).not.toEqual(b);
-
- a = [1, 2, 3];
- b = [1, 2, 3];
- a[s1] = 1;
- b[s1] = 1;
- a[s2] = undefined;
- b[s2] = null;
- expect(a).not.toEqual(b);
-
- a = [1, 2, 3];
- b = [1, 2, 3];
- a[s1] = 1;
- b[s1] = 1;
- a[s2] = null;
- b[s2] = null;
- expect(a).toEqual(b);
-
- a = [1, 2, 3];
- b = [1, 2, 3];
- a[s1] = 1;
- b[s1] = 1;
- a[s2] = undefined;
- b[s2] = undefined;
- expect(a).toEqual(b);
-
- // similar tests for indexed objects
- a = { 0: 1, 1: 2, 2: 3 };
- b = { 0: 1, 1: 2, 2: 3 };
- a[s1] = 1;
- b[s1] = 1;
- expect(a).toEqual(b);
-
- a = { 0: 1, 1: 2, 2: 3 };
- b = { 0: 1, 1: 2, 2: 3 };
- a[s1] = 1;
- b[s1] = 1;
- a[s2] = 2;
- b[s2] = 3;
- expect(a).not.toEqual(b);
-
- a = { 0: 1, 1: 3, 2: 3 };
- b = { 0: 1, 1: 2, 2: 3 };
- a[s1] = 1;
- b[s1] = 1;
- a[s2] = 2;
- b[s2] = 2;
- expect(a).not.toEqual(b);
-
- a = [1, 2, 3];
- b = [1, 2, 3, 4];
- expect(a).not.toEqual(b);
-
- a = [1, 2, 3, 4];
- b = [1, 2, 3];
- expect(a).not.toEqual(b);
-
- a = { a: 1, b: 2 };
- b = { a: 1, b: 2, c: 3 };
- expect(a).not.toEqual(b);
-
- a = { a: 1, b: 2, c: 3 };
- b = { a: 1, b: 2 };
- expect(a).not.toEqual(b);
-});
-
-test("symbol based keys in arrays are processed correctly", () => {
- const mySymbol = Symbol("test");
-
- const actual1 = [];
- actual1[mySymbol] = 3;
-
- const actual2 = [];
- actual2[mySymbol] = 4;
-
- const expected = [];
- expected[mySymbol] = 3;
-
- expect(actual2).not.toEqual(expected);
- expect(actual1).toEqual(expected);
-});
-
-test("non-enumerable members should be skipped during equal", () => {
- const actual = {
- x: 3,
- };
- Object.defineProperty(actual, "test", {
- enumerable: false,
- value: 5,
- });
- expect(actual).toEqual({ x: 3 });
-});
-
-test("non-enumerable symbolic members should be skipped during equal", () => {
- const actual = {
- x: 3,
- };
- const mySymbol = Symbol("test");
- Object.defineProperty(actual, mySymbol, {
- enumerable: false,
- value: 5,
- });
- expect(actual).toEqual({ x: 3 });
-});
-
-test("properties with the same circularity are equal", () => {
- const a = {};
- a.x = a;
- const b = {};
- b.x = b;
- expect(a).toEqual(b);
- expect(b).toEqual(a);
-
- const c = {
- x: a,
- };
- const d = {
- x: b,
- };
-
- expect(d).toEqual(c);
- expect(c).toEqual(d);
-});
-
-test("toEqual() - arrays", () => {
- expect([1, 2, 3]).toEqual([1, 2, 3]);
- expect([1, 2, 3, 4]).not.toEqual([1, 2, 3]);
-});
-
-test("properties with different circularity are not equal", () => {
- const a = {};
- a.x = { y: a };
- const b = {};
- const bx = {};
- b.x = bx;
- bx.y = bx;
- expect(a).not.toEqual(b);
- expect(b).not.toEqual(a);
-
- const c = {};
- c.x = a;
- const d = {};
- d.x = b;
- expect(c).not.toEqual(d);
- expect(d).not.toEqual(c);
-});
-
-test("are not equal if circularity is not on the same property", () => {
- const a = {};
- const b = {};
- a.a1 = a;
- b.a1 = {};
- b.a1.a1 = a;
-
- expect(a).not.toEqual(b);
- expect(b).not.toEqual(a);
-
- const c = {};
- c.x = { x: c };
- const d = {};
- d.x = d;
-
- expect(d).not.toEqual(c);
- expect(c).not.toEqual(d);
-});
-
-test("random isEqual tests", () => {
- expect(1).toEqual(1);
- expect(1).not.toEqual(2);
- expect(1).not.toEqual("1");
- expect(1).not.toEqual(true);
- expect(1).not.toEqual(false);
- expect(1).not.toEqual(null);
- expect(1).not.toEqual(undefined);
- expect(1).not.toEqual({});
- expect(1).not.toEqual([]);
- expect(1).not.toEqual([1]);
- expect(1).not.toEqual([1, 2]);
- expect(1).not.toEqual([1, 2, 3]);
- expect(1).not.toEqual([1, 2, 3, 4]);
- expect(1).not.toEqual([1, 2, 3, 4, 5]);
- expect(1).not.toEqual([1, 2, 3, 4, 5, 6]);
- expect(1).not.toEqual([1, 2, 3, 4, 5, 6, 7]);
- expect(1).not.toEqual([1, 2, 3, 4, 5, 6, 7, 8]);
- expect(1).not.toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9]);
- expect(1).not.toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
- expect(1).not.toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
- expect(1).not.toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
- expect(1).not.toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
- expect(1).not.toEqual([1, 2, 3, 4, 5, 6, 7, 8]);
-
- // test toEquals for objects with getters and setters
-
- expect([]).toEqual([]);
- expect([1]).toEqual([1]);
- expect([1, 2]).toEqual([1, 2]);
- expect([1, 2, 3]).toEqual([1, 2, 3]);
- expect({}).toEqual({});
- expect({}).not.toEqual([]);
- expect([]).not.toEqual({});
-
- const obj = {
- get a() {
- return 1;
- },
- };
- expect(obj).toEqual({ a: 1 });
- expect({ a: 1 }).toEqual(obj);
- expect(obj).not.toEqual({ a: 2 });
- expect({ a: 2 }).not.toEqual(obj);
-
- let a = new Set();
- a.add([1, 2, 3]);
- a.add("hello");
- a.add({ a: 1 });
- a.add(89);
- let b = new Set();
- b.add(89);
- b.add({ a: 1 });
- b.add("hello");
- b.add([1, 2, 3]);
- expect(a).toEqual(b);
- expect(b).toEqual(a);
- let c = new Set();
- c.add(89);
- c.add("helo");
- c.add({ a: 1 });
- c.add([1, 2, 3]);
- expect(a).not.toEqual(c);
-
- a = new Map();
- a.set(1, 89);
- a.set("hello", 2);
- a.set({ a: 1 }, 3);
- a.set([1, 2, 3], 4);
- b = new Map();
- b.set(1, 89);
- b.set("hello", 2);
- b.set({ a: 1 }, 3);
- b.set([1, 2, 3], 4);
- expect(a).toEqual(b);
- expect(b).toEqual(a);
- c = new Map();
- c.set({ a: 1 }, 3);
- c.set(1, 80);
- c.set([1, 2, 3], 4);
- c.set("hello", 2);
- expect(a).not.toEqual(c);
-
- a = new Set();
- a.add(89);
- a.add("hello");
- a.add({ a: 1 });
- a.add([1, 2, 3]);
- a.add(a);
- b = new Set();
- b.add(89);
- b.add("hello");
- b.add(b);
- b.add({ a: 1 });
- b.add([1, 2, 3]);
- expect(a).toEqual(b);
- expect(b).toEqual(a);
-});
-
test("testing Bun.deepEquals() using isEqual()", () => {
const t = new Uint8Array([1, 2, 3, 4, 5]);
expect(t).toEqual(t.slice());
@@ -1586,1319 +163,6 @@ test("testing Bun.deepEquals() using isEqual()", () => {
expect(-Infinity).toEqual(-1 / 0);
});
-test("toHaveProperty() - emojis", () => {
- expect({ "👍": "thumbs up" }).toHaveProperty("👍", "thumbs up");
- expect({ "👩‍👩‍👧‍👧": "family" }).toHaveProperty("👩‍👩‍👧‍👧", "family");
- expect({ "😶‍🌫️": "fog" }).toHaveProperty("😶‍🌫️", "fog");
- expect({ "👩‍❤️‍👨": "couple" }).toHaveProperty("👩‍❤️‍👨", "couple");
- expect({ "👩‍❤️‍👨‍👨‍👧‍👧": "family" }).toHaveProperty("👩‍❤️‍👨‍👨‍👧‍👧", "family");
- expect({ "👩‍❤️‍👨‍👨‍👧": "family" }).toHaveProperty("👩‍❤️‍👨‍👨‍👧", "family");
- expect({ "👩‍❤️‍👨‍👨‍👧": "family" }).not.toHaveProperty("👩‍❤️‍👨‍👨‍👧‍👧", "family");
-
- // emojis in array
- expect(["👍", "👎"]).toHaveProperty("0", "👍");
- expect(["👍", "👎"]).toHaveProperty("1", "👎");
- expect(["👍", "👎"]).not.toHaveProperty("0", "👎");
- expect(["👍", "👎"]).not.toHaveProperty("1", "👍");
- expect(["👩‍❤️‍👨‍👨‍👧‍👧"]).toHaveProperty("0", "👩‍❤️‍👨‍👨‍👧‍👧");
- expect(["👩‍❤️‍👨‍👨‍👧‍👧"]).toHaveProperty([0], "👩‍❤️‍👨‍👨‍👧‍👧");
- expect(["😶‍🌫️"]).toHaveProperty([0], "😶‍🌫️");
-});
-
-test("toHaveProperty() - dot and bracket notation edge cases", () => {
- expect({ a: 1 }).not.toHaveProperty(".");
- expect({ a: 1 }).not.toHaveProperty("]");
- expect({ a: 1 }).not.toHaveProperty("[");
- expect({ a: 1 }).not.toHaveProperty("[]");
- expect({ a: 1 }).not.toHaveProperty("[[]]");
- expect({ a: 1 }).not.toHaveProperty("[[");
- expect({ a: 1 }).not.toHaveProperty("]]");
- expect({ a: 1 }).not.toHaveProperty("[]]");
- expect({ a: 1 }).not.toHaveProperty("[[]");
- expect({ a: 1 }).not.toHaveProperty(".]");
- expect({ a: 1 }).not.toHaveProperty(".[");
- expect({ "": 1 }).toHaveProperty("[.", 1);
- expect({ a: 1 }).not.toHaveProperty("[.");
- expect({ a: 1 }).not.toHaveProperty("].");
- expect({ a: 1 }).not.toHaveProperty("].[");
- expect({ a: 1 }).not.toHaveProperty("].]");
- expect({ a: 1 }).not.toHaveProperty("[.]");
- expect({ a: 1 }).not.toHaveProperty("[.[");
-
- expect([1]).toHaveProperty("[0]", 1);
- expect([1]).toHaveProperty("[0][", 1);
- expect([1]).toHaveProperty("[0]]", 1);
- expect([1]).toHaveProperty("[0][[", 1);
- expect([1]).toHaveProperty("[][[[0]", 1);
- expect([1]).toHaveProperty("[][[[]][[][][.0", 1);
- expect([1]).toHaveProperty("[][[[]][[][][.[][[][[[][][0", 1);
- expect([1]).not.toHaveProperty("......1.............", 1);
- expect([1]).not.toHaveProperty("......0.............", 1);
- expect([1]).not.toHaveProperty(".0", 1);
- expect([1]).not.toHaveProperty("0.", 1);
- expect([{ "": 1 }]).toHaveProperty("0.", 1);
- expect({ "": { "": 1 } }).toHaveProperty(".", 1);
- expect({ "": { "": { "": 1 } } }).toHaveProperty("..", 1);
- expect({ "": { "": { "": 1 } } }).not.toHaveProperty(".", 1);
- expect({ "": { "": { "": 1 } } }).not.toHaveProperty("...", 1);
- expect({ "": { "": { "": 1 } } }).not.toHaveProperty("....", 1);
- expect([1]).toHaveProperty("0.[[[][][]][[[][[]]]]", 1);
- expect([1]).not.toHaveProperty("[0].", 1);
- expect([1]).toHaveProperty("0", 1);
- expect([1]).toHaveProperty("[].0", 1);
- expect([1]).toHaveProperty("[.0", 1);
- expect([1]).toHaveProperty("].0", 1);
- expect([1]).toHaveProperty("0[]][[[]", 1);
- expect([1]).toHaveProperty("[[]][[[][][0", 1);
- expect([1]).toHaveProperty("0", 1);
- expect([1]).toHaveProperty("0.[", 1);
- expect([1]).not.toHaveProperty("0........[", 1);
- expect([1]).not.toHaveProperty("0..[", 1);
- expect([1]).not.toHaveProperty(".0", 1);
- expect([1]).toHaveProperty("[].0", 1);
- expect([1]).not.toHaveProperty("[]..0", 1);
- expect([1]).toHaveProperty("[.][.[[.]]]]].[.[].].]]]]].].].0", 1);
- expect([1]).not.toHaveProperty("[.][.[[.]]]]].[.[].].]]0]]].].].", 1);
- expect([1]).toHaveProperty("[.][.[[.]]]]].[.[].].]]0]]].].]", 1);
- expect([1]).not.toHaveProperty("[.][.[[..]]]]].[.[].].]]0]]].].]", 1);
- expect([1]).toHaveProperty("[.][.[[.]]]]].[.[].].0.]]]]].].]", 1);
- expect([1]).not.toHaveProperty("[.][.[[.]]]]].[.[].].0.]]] ]].].]", 1);
- expect([1]).not.toHaveProperty("0 ", 1);
- expect([1]).not.toHaveProperty(" 0 ", 1);
- expect([1]).not.toHaveProperty(" 0[] ", 1);
- expect([1]).not.toHaveProperty(" 0] ", 1);
- expect([1]).not.toHaveProperty(" .[0]", 1);
-
- expect({ "": 1 }).not.toHaveProperty(".", 1);
- expect({ "": 1 }).not.toHaveProperty("]", 1);
- expect({ "": 1 }).not.toHaveProperty("[", 1);
- expect({ "": 1 }).toHaveProperty("", 1);
-
- expect({ "": 1 }).not.toHaveProperty("..", 1);
- expect({ "": { "": 1 } }).not.toHaveProperty("..", 1);
- expect([{ "": 1 }]).toHaveProperty("0.", 1);
- expect([{ "": 1 }]).not.toHaveProperty(".0.", 1);
- expect({ "": [1] }).toHaveProperty(".0", 1);
- expect({ "": [1] }).not.toHaveProperty("..0", 1);
- expect([{ "": 1 }]).not.toHaveProperty("0..", 1);
- expect([{ "": { "": 1 } }]).toHaveProperty("0..", 1);
-
- expect([1]).not.toHaveProperty("[0].", 1);
- expect([1]).not.toHaveProperty("[0][0]", 1);
- expect({ a: [1] }).toHaveProperty("a[[[[[[[[[0]]]", 1);
- expect({ "[[[": 0 }).not.toHaveProperty("[[[", 0);
-});
-
-test("toHaveProperty() - with string or array", () => {
- const a = new Array(["a", "b", "c"]);
- expect(a).toHaveProperty("0.1", "b");
- const b = new Array("a", "b", "c");
- expect({ a: { b: { c: 1 } } }).toHaveProperty(b);
- const c = {
- a: { b: 1 },
- "a.b": 2,
- };
- const d = new Array("a.b");
- expect(c).toHaveProperty(d, 2);
- const houseForSale = {
- bath: true,
- bedrooms: 4,
- kitchen: {
- amenities: ["oven", "stove", "washer"],
- area: 20,
- wallColor: "white",
- "nice.oven": true,
- },
- livingroom: {
- amenities: [
- {
- couch: [
- ["large", { dimensions: [20, 20] }],
- ["small", { dimensions: [10, 10] }],
- ],
- },
- ],
- },
- sunroom: "yes",
- "ceiling.height": 20,
- "entrance.window": 3,
- entrance: { window: 5 },
- };
- expect(houseForSale).toHaveProperty("entrance.window", 5);
- expect(houseForSale).toHaveProperty(["entrance", "window"], 5);
- expect(houseForSale).toHaveProperty(["entrance.window"], 3);
- expect(houseForSale).toHaveProperty("bath");
- expect(houseForSale).not.toHaveProperty("jacuzzi");
- // expect(houseForSale).toHaveProperty("jacuzzi");
- // expect(houseForSale).not.toHaveProperty("bath");
- expect(houseForSale).toHaveProperty("bath", true);
- expect(houseForSale).not.toHaveProperty("bath", false);
- // expect(houseForSale).toHaveProperty("bath", false);
- // expect(houseForSale).not.toHaveProperty("bath", true);
- expect(houseForSale).toHaveProperty("bedrooms", 4);
- expect(houseForSale).toHaveProperty(["sunroom"], "yes");
- expect(houseForSale).toHaveProperty("kitchen.area", 20);
- expect(houseForSale).toHaveProperty("kitchen.amenities", ["oven", "stove", "washer"]);
- expect(houseForSale).not.toHaveProperty(["kitchen", "area"], 21);
- expect(houseForSale).toHaveProperty(["kitchen", "area"], 20);
- expect(houseForSale).not.toHaveProperty(["kitchen", "area"], 29);
- expect(houseForSale).toHaveProperty(["kitchen", "amenities"], ["oven", "stove", "washer"]);
- expect(houseForSale).toHaveProperty("kitchen.amenities[2]", "washer");
- expect(houseForSale).toHaveProperty(["kitchen", "amenities", 1], "stove");
- expect(houseForSale).toHaveProperty(["kitchen", "amenities", 0], "oven");
- expect(houseForSale).toHaveProperty("livingroom.amenities[0].couch[0][1].dimensions[0]", 20);
- expect(houseForSale).toHaveProperty(["kitchen", "nice.oven"]);
- expect(houseForSale).not.toHaveProperty(["kitchen", "open"]);
- expect(houseForSale).toHaveProperty(["ceiling.height"], 20);
- expect({ a: { b: 1 } }).toHaveProperty("a.b");
- expect({ a: [2, 3, 4] }).toHaveProperty("a.0");
- expect({ a: [2, 3, 4] }).toHaveProperty("a.1");
- expect({ a: [2, 3, 4] }).toHaveProperty("a.2");
- expect({ a: [2, 3, 4] }).toHaveProperty("a[1]");
- expect([2, 3, 4]).toHaveProperty("1");
- expect([2, 3, 4]).toHaveProperty("[1]");
- expect([2, [6, 9], 4]).toHaveProperty("1.1");
- expect([2, [6, 9], 4]).toHaveProperty("1[1]");
- expect([2, [6, 9], 4]).toHaveProperty("[1].1");
- expect([2, [6, 9], 4]).toHaveProperty("[1][1]");
- expect([2, [6, 9], 4]).toHaveProperty([0], 2);
- expect({ a: { b: 1 } }).toHaveProperty("a.b");
- expect({ a: [1, 2, [3, { b: 1 }]] }).toHaveProperty("a.2.1.b");
- expect({ a: [1, 2, [3, { b: 1 }]] }).toHaveProperty("a");
- expect({ a: [1, 2, [3, { b: 1 }]] }).toHaveProperty("a[2][1].b");
- expect({ a: [1, 2, [3, { b: 1 }]] }).toHaveProperty("a[2][1]");
- expect({ a: [1, 2, [3, { b: 1 }]] }).not.toHaveProperty("a[2][1].c");
- expect("test").toHaveProperty("length");
- expect({}).toHaveProperty("constructor");
- expect({}).toHaveProperty("constructor.name");
- expect({}).toHaveProperty("constructor.name", "Object");
- expect(new Date()).toHaveProperty("getTime");
-});
-
-test("toHaveProperty() - all", () => {
- expect({ a: 1 }).toHaveProperty("a");
- expect({ a: 1 }).toHaveProperty("a", 1);
- expect({ a: 1 }).not.toHaveProperty("b");
- expect({ a: 1 }).not.toHaveProperty("a", 2);
-
- // test with object with property "a" with all types of values (including undefined)
- expect({ a: undefined }).toHaveProperty("a");
- expect({ a: null }).toHaveProperty("a");
- expect({ a: 0 }).toHaveProperty("a");
- expect({ a: false }).toHaveProperty("a");
- expect({ a: "" }).toHaveProperty("a");
- expect({ a: {} }).toHaveProperty("a");
- expect({ a: [] }).toHaveProperty("a");
- expect({ a: () => {} }).toHaveProperty("a");
-
- // test with object with property "a" with all types of values (including undefined)
- expect({ a: undefined }).toHaveProperty("a", undefined);
- expect({ a: null }).toHaveProperty("a", null);
- expect({ a: 0 }).toHaveProperty("a", 0);
- expect({ a: false }).toHaveProperty("a", false);
- expect({ a: "" }).toHaveProperty("a", "");
- expect({ a: {} }).toHaveProperty("a", {});
- expect({ a: [] }).toHaveProperty("a", []);
- expect({ a: () => {} }).not.toHaveProperty("a", () => {});
-
- // test with object with property "a" with all types of values (including undefined)
-
- expect({ a: undefined }).not.toHaveProperty("a", null);
- expect({ a: null }).not.toHaveProperty("a", undefined);
- expect({ a: 0 }).not.toHaveProperty("a", null);
- expect({ a: false }).not.toHaveProperty("a", null);
- expect({ a: "" }).not.toHaveProperty("a", null);
- expect({ a: {} }).not.toHaveProperty("a", null);
- expect({ a: [] }).not.toHaveProperty("a", null);
- expect({ a: () => {} }).not.toHaveProperty("a", null);
-
- expect({ a: undefined }).not.toHaveProperty("a", 0);
- expect({ a: null }).not.toHaveProperty("a", 0);
- expect({ a: 0 }).not.toHaveProperty("a", 1);
- expect({ a: false }).not.toHaveProperty("a", 0);
- expect({ a: "" }).not.toHaveProperty("a", 0);
- expect({ a: {} }).not.toHaveProperty("a", 0);
- expect({ a: [] }).not.toHaveProperty("a", 0);
- expect({ a: () => {} }).not.toHaveProperty("a", 0);
-
- expect({ a: undefined }).not.toHaveProperty("a", false);
- expect({ a: null }).not.toHaveProperty("a", false);
- expect({ a: 0 }).not.toHaveProperty("a", false);
- expect({ a: false }).not.toHaveProperty("a", true);
- expect({ a: "" }).not.toHaveProperty("a", false);
- expect({ a: {} }).not.toHaveProperty("a", false);
- expect({ a: [] }).not.toHaveProperty("a", false);
- expect({ a: () => {} }).not.toHaveProperty("a", false);
-
- expect({ a: undefined }).not.toHaveProperty("a", "");
- expect({ a: null }).not.toHaveProperty("a", "");
- expect({ a: 0 }).not.toHaveProperty("a", "");
- expect({ a: false }).not.toHaveProperty("a", "");
- expect({ a: "" }).not.toHaveProperty("a", "a");
- expect({ a: {} }).not.toHaveProperty("a", "");
- expect({ a: [] }).not.toHaveProperty("a", "");
- expect({ a: () => {} }).not.toHaveProperty("a", "");
-
- expect({ a: undefined }).not.toHaveProperty("a", {});
- expect({ a: null }).not.toHaveProperty("a", {});
- expect({ a: 0 }).not.toHaveProperty("a", {});
- expect({ a: false }).not.toHaveProperty("a", {});
- expect({ a: "" }).not.toHaveProperty("a", {});
- expect({ a: {} }).not.toHaveProperty("a", { a: 1 });
- expect({ a: [] }).not.toHaveProperty("a", {});
- expect({ a: () => {} }).not.toHaveProperty("a", {});
-
- // test object with property "a" with value set, map, string
- expect({ a: new Set([1, 2, 3]) }).toHaveProperty("a", new Set([3, 2, 1]));
- expect({ a: new Map([{ a: 1 }, { b: 2 }, { c: 3 }]) }).toHaveProperty("a", new Map([{ c: 3 }, { b: 2 }, { a: 1 }]));
- expect({ a: new String("a") }).toHaveProperty("a", new String("a"));
- expect({ a: new String("a") }).not.toHaveProperty("a", "a");
- expect({ a: new String("a") }).not.toHaveProperty("a", "b");
- expect({ a: new String("a") }).not.toHaveProperty("a", new String("b"));
- expect({ a: new String("a") }).not.toHaveProperty("a", new Number(1));
- expect({ a: new String("a") }).not.toHaveProperty("a", new Boolean(true));
- expect({ a: new String("a") }).not.toHaveProperty("a", new Boolean(false));
- expect({ a: new String("a") }).not.toHaveProperty("a", new Object());
- expect({ a: new String("a") }).not.toHaveProperty("a", new Array());
- expect({ a: new String("a") }).not.toHaveProperty("a", new Function());
- expect({ a: new String("a") }).not.toHaveProperty("a", new Date());
- expect({ a: new String("a") }).not.toHaveProperty("a", new RegExp());
- expect({ a: new String("a") }).not.toHaveProperty("a", new Error());
- expect({ a: new String("a") }).not.toHaveProperty("a", new Promise(() => {}));
- expect({ a: new String("a") }).not.toHaveProperty("a", new WeakSet());
- expect({ a: new String("a") }).not.toHaveProperty("a", new WeakMap());
- expect({ a: new String("a") }).not.toHaveProperty("a", Symbol("a"));
- expect({ a: new String("a") }).not.toHaveProperty("a", new Int8Array());
- expect({ a: new String("a") }).not.toHaveProperty("a", new Uint8Array());
- expect({ a: new String("a") }).not.toHaveProperty("a", new Uint8ClampedArray());
- expect({ a: new String("a") }).not.toHaveProperty("a", new Int16Array());
- expect({ a: new String("a") }).not.toHaveProperty("a", new Uint16Array());
- expect({ a: new String("a") }).not.toHaveProperty("a", new Int32Array());
- expect({ a: new String("a") }).not.toHaveProperty("a", new Uint32Array());
- expect({ a: new String("a") }).not.toHaveProperty("a", new Float32Array());
- expect({ a: new String("a") }).not.toHaveProperty("a", new Float64Array());
- expect({ a: new String("a") }).not.toHaveProperty("a", new BigInt64Array());
- expect({ a: new String("a") }).not.toHaveProperty("a", new BigUint64Array());
- expect({ a: new String("a") }).not.toHaveProperty("a", new ArrayBuffer());
- expect({ a: new String("a") }).not.toHaveProperty("a", new SharedArrayBuffer());
- expect({ a: new String("a") }).not.toHaveProperty("a", new DataView(new ArrayBuffer(1)));
-
- // test property equality with sets, maps, objects, arrays, and String
- expect({ a: new Set([1, 2, 3]) }).toHaveProperty("a", new Set([1, 2, 3]));
- expect({ a: new Map([{ a: 1 }, { b: 2 }, { c: 3 }]) }).toHaveProperty("a", new Map([{ a: 1 }, { b: 2 }, { c: 3 }]));
- expect({ a: { a: 1, b: 2, c: 3 } }).toHaveProperty("a", { a: 1, b: 2, c: 3 });
- expect({ a: [1, 2, 3] }).toHaveProperty("a", [1, 2, 3]);
- expect({ a: "a" }).toHaveProperty("a", "a");
- expect({ a: new String("a") }).toHaveProperty("a", new String("a"));
- expect({ a: new String("a") }).not.toHaveProperty("a", "a");
-});
-
-test("toHaveProperty() - null or undefined", () => {
- expect(null).not.toHaveProperty("length");
- expect(undefined).not.toHaveProperty("length");
-});
-
-test("toBe()", () => {
- const a = 1;
- const b = 1;
- expect(a).toBe(a);
- expect(a).toBe(b);
- expect(a).toBe(1);
- expect(1).toBe(a);
- expect(b).toBe(a);
-
- const c = { a: 1 };
- const d = { a: 1 };
- expect(c).toBe(c);
- expect(c).not.toBe(d);
- expect(c).not.toBe({ a: 1 });
- expect({ a: 1 }).not.toBe(c);
- expect(d).not.toBe(c);
-
- expect(1).toBe(1);
- // expect(1).not.toBe(1);
-
- expect(1).not.toBe(2);
- expect(1).not.toBe("1");
- expect("hello test").toBe("hello test");
- expect("hello test").not.toBe("hello test2");
-});
-
-test("toHaveLength()", () => {
- expect({ length: Number.MAX_SAFE_INTEGER }).toHaveLength(Number.MAX_SAFE_INTEGER);
- expect("123").toHaveLength(3);
- expect([1, 2, 3]).toHaveLength(3);
- expect([1, 2, 3]).not.toHaveLength(2);
- expect("123").not.toHaveLength(2);
- expect({ length: 3 }).toHaveLength(3);
- expect({ length: 3 }).not.toHaveLength(2);
- expect({ length: 3 }).not.toHaveLength(Number.MAX_SAFE_INTEGER);
- expect({ length: Number.MAX_SAFE_INTEGER }).not.toHaveLength(Number.MAX_SAFE_INTEGER - 1);
- expect({ length: 3.3 }).not.toHaveLength(3);
- expect("123").not.toHaveLength(-0);
-});
-
-test("toHaveLength() extended", () => {
- // Headers
- expect(new Headers()).toHaveLength(0);
- expect(new Headers({ a: "1" })).toHaveLength(1);
-
- // FormData
- const form = new FormData();
- expect(form).toHaveLength(0);
- form.append("a", "1");
- expect(form).toHaveLength(1);
-
- // URLSearchParams
- expect(new URLSearchParams()).toHaveLength(0);
- expect(new URLSearchParams("a=1")).toHaveLength(1);
- expect(new URLSearchParams([["a", "1"]])).toHaveLength(1);
-
- // files
- const thisFile = Bun.file(import.meta.path);
- const thisFileSize = thisFile.size;
-
- expect(thisFile).toHaveLength(thisFileSize);
- expect(thisFile).toHaveLength(Bun.file(import.meta.path).size);
-
- // empty file should have length 0
- writeFileSync("/tmp/empty.txt", "");
- expect(Bun.file("/tmp/empty.txt")).toHaveLength(0);
-
- // if a file doesn't exist, it should throw (not return 0 size)
- expect(() => expect(Bun.file("/does-not-exist/file.txt")).toHaveLength(0)).toThrow();
-
- // Blob
- expect(new Blob([1, 2, 3])).toHaveLength(3);
- expect(new Blob()).toHaveLength(0);
-
- // Set
- expect(new Set()).toHaveLength(0);
- expect(new Set([1, 2, 3])).toHaveLength(3);
-
- // Map
- expect(new Map()).toHaveLength(0);
- expect(new Map([["a", 1]])).toHaveLength(1);
-
- // WeakMap
- expect(new WeakMap([[globalThis, 1]])).toHaveLength(1);
-});
-
-test("toContain()", () => {
- const s1 = new String("123");
- expect(s1).not.toContain("12");
- const s2 = "123";
- expect(s2).toContain("12");
-
- expect("test").toContain("es");
- expect("test").toContain("est");
- // expect("test").not.toContain("test");
- expect(["test", "es"]).toContain("es");
- expect("").toContain("");
- expect([""]).toContain("");
-
- expect(["lemon", "lime"]).not.toContain("orange");
- expect("citrus fruits").toContain("fruit");
-
- const a = new Uint16Array([1, 2, 3]);
- expect(a).toContain(2);
- expect(a).not.toContain(4);
- expect([2, "2335", 5, true, false, null, undefined]).toContain(5);
- expect([2, "2335", 5, true, false, null, undefined]).toContain("2335");
- expect([2, "2335", 5, true, false, null, undefined]).toContain(true);
- expect([2, "2335", 5, true, false, null, undefined]).toContain(false);
- expect([2, "2335", 5, true, false, null, undefined]).toContain(null);
- expect([2, "2335", 5, true, false, null, undefined]).toContain(undefined);
- expect([2, "2335", 5, true, false, null, undefined]).not.toContain(3);
- expect([2, "2335", 5, true, false, null, undefined]).not.not.not.toContain(3);
-
- // expect([4, 5, 6]).not.toContain(5);
-
- expect([]).not.toContain([]);
-});
-
-test("toBeEven()", () => {
- expect(1).not.toBeEven();
- expect(2).toBeEven();
- expect(3).not.toBeEven();
- expect(3.1).not.toBeEven();
- expect(2.1).not.toBeEven();
- expect(4).toBeEven();
- expect(5).not.toBeEven();
- expect(6).toBeEven();
- expect(0).toBeEven();
- expect(-8).toBeEven();
- expect(-0).toBeEven();
- expect(NaN).not.toBeEven();
- expect([]).not.toBeEven();
- expect([1, 2]).not.toBeEven();
- expect({}).not.toBeEven();
- expect(() => {}).not.toBeEven();
- expect("").not.toBeEven();
- expect("string").not.toBeEven();
- expect(undefined).not.toBeEven();
- expect(Math.floor(Date.now() / 1000) * 2).toBeEven(); // Slight fuzz by using timestamp times 2
- expect(Math.floor(Date.now() / 1000) * 4 - 1).not.toBeEven();
- expect(4.0e1).toBeEven();
- expect(6.2e1).toBeEven();
- expect(6.3e1).not.toBeEven();
- expect(6.33e1).not.toBeEven();
- expect(3.3e-1).not.toBeEven(); //throw
- expect(0.3).not.toBeEven(); //throw
- expect(0.4).not.toBeEven();
- expect(1).not.toBeEven();
- expect(0).toBeEven();
- expect(2.0).toBeEven();
- expect(NaN).not.toBeEven();
- expect(2n).toBeEven(); // BigInt at this time not supported in jest-extended
- expect(3n).not.toBeEven();
- expect(9007199254740990).toBeEven(); // manual typical max safe -1 // not int?
- expect(9007199254740990n).toBeEven(); // manual typical max safe -1 as bigint
- expect(Number.MAX_SAFE_INTEGER - 1).toBeEven(); // not int?
- expect(Number.MAX_SAFE_INTEGER).not.toBeEven();
- expect(BigInt(Number.MAX_SAFE_INTEGER) - 1n).toBeEven();
- expect(BigInt(Number.MAX_SAFE_INTEGER)).not.toBeEven();
- expect(BigInt(Number.MAX_VALUE - 1)).toBeEven();
- expect(Number.MIN_SAFE_INTEGER + 1).toBeEven(); // not int?
- expect(Number.MIN_SAFE_INTEGER).not.toBeEven();
- expect(BigInt(Number.MIN_SAFE_INTEGER) + 1n).toBeEven();
- expect(BigInt(Number.MIN_SAFE_INTEGER)).not.toBeEven();
- expect(4 / Number.NEGATIVE_INFINITY).toBeEven(); // as in IEEE-754: + / -inf => neg zero
- expect(5 / Number.NEGATIVE_INFINITY).toBeEven();
- expect(-7 / Number.NEGATIVE_INFINITY).toBeEven(); // as in IEEE-754: - / -inf => zero
- expect(-8 / Number.NEGATIVE_INFINITY).toBeEven();
- expect(new WebAssembly.Global({ value: "i32", mutable: false }, 4).value).toBeEven();
- expect(new WebAssembly.Global({ value: "i32", mutable: false }, 3).value).not.toBeEven();
- expect(new WebAssembly.Global({ value: "i32", mutable: true }, 2).value).toBeEven();
- expect(new WebAssembly.Global({ value: "i32", mutable: true }, 1).value).not.toBeEven();
- expect(new WebAssembly.Global({ value: "i64", mutable: true }, -9223372036854775808n).value).toBeEven();
- expect(new WebAssembly.Global({ value: "i64", mutable: false }, -9223372036854775808n).value).toBeEven();
- expect(new WebAssembly.Global({ value: "i64", mutable: true }, 9223372036854775807n).value).not.toBeEven();
- expect(new WebAssembly.Global({ value: "i64", mutable: false }, 9223372036854775807n).value).not.toBeEven();
- expect(new WebAssembly.Global({ value: "f32", mutable: true }, 42.0).value).toBeEven();
- expect(new WebAssembly.Global({ value: "f32", mutable: false }, 42.0).value).toBeEven();
- expect(new WebAssembly.Global({ value: "f64", mutable: true }, 42.0).value).toBeEven();
- expect(new WebAssembly.Global({ value: "f64", mutable: false }, 42.0).value).toBeEven();
- expect(new WebAssembly.Global({ value: "f32", mutable: true }, 43.0).value).not.toBeEven();
- expect(new WebAssembly.Global({ value: "f32", mutable: false }, 43.0).value).not.toBeEven();
- expect(new WebAssembly.Global({ value: "f64", mutable: true }, 43.0).value).not.toBeEven();
- expect(new WebAssembly.Global({ value: "f64", mutable: false }, 43.0).value).not.toBeEven();
- expect(new WebAssembly.Global({ value: "f32", mutable: true }, 4.3).value).not.toBeEven();
- expect(new WebAssembly.Global({ value: "f32", mutable: false }, 4.3).value).not.toBeEven();
- expect(new WebAssembly.Global({ value: "f64", mutable: true }, 4.3).value).not.toBeEven();
- expect(new WebAssembly.Global({ value: "f64", mutable: false }, 4.3).value).not.toBeEven();
- // did not seem to support SIMD v128 type yet (which is not in W3C specs for JS but is a valid global type)
- // FUTURE: expect(new WebAssembly.Global({value:'v128', mutable:false}, -170141183460469231731687303715884105728n).value).toBeEven();
- // FUTURE: expect(new WebAssembly.Global({value:'v128', mutable:true}, -170141183460469231731687303715884105728n).value).toBeEven();
- // FUTURE: expect(new WebAssembly.Global({value:'v128', mutable:true}, 170141183460469231731687303715884105727n).value).not.toBeEven();
- // FUTURE: expect(new WebAssembly.Global({value:'v128', mutable:false}, 170141183460469231731687303715884105727n).value).not.toBeEven();
- // FUTURE: with uintv128: expect(new WebAssembly.Global({value:'v128', mutable:false}, 340282366920938463463374607431768211456n).value).toThrow();
-});
-
-test("toBeTruthy()", () => {
- expect("test").toBeTruthy();
- expect(true).toBeTruthy();
- expect(1).toBeTruthy();
- expect({}).toBeTruthy();
- expect([]).toBeTruthy();
- expect(() => {}).toBeTruthy();
- // expect(() => {}).not.toBeTruthy();
- expect(0.5).toBeTruthy();
- expect(new Map()).toBeTruthy();
-
- expect("").not.toBeTruthy();
- expect(0).not.toBeTruthy();
- expect(-0).not.toBeTruthy();
- expect(NaN).not.toBeTruthy();
- expect(0n).not.toBeTruthy();
- expect(0.0e1).not.toBeTruthy();
- expect(false).not.toBeTruthy();
- expect(null).not.toBeTruthy();
- expect(undefined).not.toBeTruthy();
-});
-
-test("toBeUndefined()", () => {
- expect(undefined).toBeUndefined();
- // expect(undefined).not.toBeUndefined();
-
- expect(null).not.toBeUndefined();
- expect(null).not.not.not.toBeUndefined();
- expect(0).not.toBeUndefined();
- expect("hello defined").not.toBeUndefined();
-});
-
-test("toBeNaN()", () => {
- expect(NaN).toBeNaN();
- // expect(NaN).not.toBeNaN();
-
- expect(0).not.toBeNaN();
- expect("hello not NaN").not.toBeNaN();
-});
-
-test("toBeNull()", () => {
- expect(null).toBeNull();
- // expect(null).not.toBeNull();
-
- expect(undefined).not.toBeNull();
- expect(0).not.toBeNull();
- expect("hello not null").not.toBeNull();
-});
-
-test("toBeDefined()", () => {
- expect(0).toBeDefined();
- expect("hello defined").toBeDefined();
- expect(null).toBeDefined();
- // expect(null).not.toBeDefined();
-
- expect(undefined).not.toBeDefined();
-});
-
-test("toBeFalsy()", () => {
- expect("").toBeFalsy();
- expect(0).toBeFalsy();
- expect(-0).toBeFalsy();
- expect(NaN).toBeFalsy();
- expect(0n).toBeFalsy();
- expect(false).toBeFalsy();
- expect(null).toBeFalsy();
- expect(undefined).toBeFalsy();
- // expect(undefined).not.toBeFalsy();
-
- expect("hello not falsy").not.toBeFalsy();
- expect("hello not falsy").not.not.not.toBeFalsy();
- expect(1).not.toBeFalsy();
- expect(true).not.toBeFalsy();
- expect({}).not.toBeFalsy();
- expect([]).not.toBeFalsy();
- expect(() => {}).not.toBeFalsy();
-});
-
-test("toBeGreaterThan()", () => {
- expect(3n).toBeGreaterThan(2);
- expect(Number.MAX_VALUE).not.toBeGreaterThan(Number.MAX_VALUE);
- expect(1).not.toBeGreaterThan(BigInt(Number.MAX_VALUE));
- expect(1).not.toBeGreaterThan(Number.MAX_SAFE_INTEGER);
- expect(1).not.toBeGreaterThan(BigInt(Number.MAX_SAFE_INTEGER));
- expect(Number.MAX_SAFE_INTEGER).not.toBeGreaterThan(Number.MAX_SAFE_INTEGER);
- expect(BigInt(Number.MAX_SAFE_INTEGER)).not.toBeGreaterThan(BigInt(Number.MAX_SAFE_INTEGER));
-
- expect(Infinity).toBeGreaterThan(-Infinity);
- expect(-Infinity).not.toBeGreaterThan(Infinity);
-
- expect(NaN).not.toBeGreaterThan(NaN);
- expect(NaN).not.toBeGreaterThan(-Infinity);
-
- expect(10).toBeGreaterThan(9);
- expect(10).not.toBeGreaterThan(10);
- expect(10).not.toBeGreaterThan(11);
- expect(10).not.toBeGreaterThan(Infinity);
- expect(10).toBeGreaterThan(-Infinity);
- expect(10).not.toBeGreaterThan(NaN);
- expect(10).toBeGreaterThan(0);
- expect(10).toBeGreaterThan(-0);
- expect(10).toBeGreaterThan(0.1);
- expect(10).toBeGreaterThan(-0.1);
- expect(10).toBeGreaterThan(0.9);
- expect(10).toBeGreaterThan(-0.9);
- expect(10).toBeGreaterThan(1);
- expect(10).toBeGreaterThan(-1);
- // switch the order
- expect(9).not.toBeGreaterThan(10);
- expect(10).not.toBeGreaterThan(10);
- expect(11).toBeGreaterThan(10);
- expect(Infinity).toBeGreaterThan(10);
- expect(-Infinity).not.toBeGreaterThan(10);
- expect(NaN).not.toBeGreaterThan(10);
- expect(0).not.toBeGreaterThan(10);
- expect(-0).not.toBeGreaterThan(10);
- expect(0.1).not.toBeGreaterThan(10);
- expect(-0.1).not.toBeGreaterThan(10);
- expect(0.9).not.toBeGreaterThan(10);
- expect(-0.9).not.toBeGreaterThan(10);
- expect(1).not.toBeGreaterThan(10);
- expect(-1).not.toBeGreaterThan(10);
-
- // same tests but use bigints
- expect(10n).toBeGreaterThan(9n);
- expect(10n).not.toBeGreaterThan(10n);
- expect(10n).not.toBeGreaterThan(11n);
- expect(10n).not.toBeGreaterThan(Infinity);
- expect(10n).toBeGreaterThan(-Infinity);
- expect(10n).not.toBeGreaterThan(NaN);
- expect(10n).toBeGreaterThan(0n);
- expect(10n).toBeGreaterThan(-0n);
- expect(10n).toBeGreaterThan(1n);
- expect(10n).toBeGreaterThan(-1n);
- // switch the order
- expect(9n).not.toBeGreaterThan(10n);
- expect(10n).not.toBeGreaterThan(10n);
- expect(11n).toBeGreaterThan(10n);
- expect(Infinity).toBeGreaterThan(10n);
- expect(-Infinity).not.toBeGreaterThan(10n);
- expect(NaN).not.toBeGreaterThan(10n);
- expect(0n).not.toBeGreaterThan(10n);
- expect(-0n).not.toBeGreaterThan(10n);
- expect(1n).not.toBeGreaterThan(10n);
- expect(-1n).not.toBeGreaterThan(10n);
-
- // use bigints and numbers
- expect(10n).toBeGreaterThan(9);
- expect(10n).not.toBeGreaterThan(10);
- expect(10n).not.toBeGreaterThan(11);
- expect(10n).not.toBeGreaterThan(Infinity);
- expect(10n).toBeGreaterThan(-Infinity);
- expect(10n).not.toBeGreaterThan(NaN);
- expect(10n).toBeGreaterThan(0);
- expect(10n).toBeGreaterThan(-0);
- expect(10n).toBeGreaterThan(0.1);
- expect(10n).toBeGreaterThan(-0.1);
- expect(10n).toBeGreaterThan(0.9);
- expect(10n).toBeGreaterThan(-0.9);
- expect(10n).toBeGreaterThan(1);
- expect(10n).toBeGreaterThan(-1);
- // switch the order
- expect(9n).not.toBeGreaterThan(10);
- expect(10n).not.toBeGreaterThan(10);
- expect(11n).toBeGreaterThan(10);
- expect(Infinity).toBeGreaterThan(10n);
- expect(-Infinity).not.toBeGreaterThan(10n);
- expect(NaN).not.toBeGreaterThan(10n);
- expect(0n).not.toBeGreaterThan(10);
- expect(-0n).not.toBeGreaterThan(10);
- expect(1n).not.toBeGreaterThan(10);
- expect(-1n).not.toBeGreaterThan(10);
-
- expect(1n).not.toBeGreaterThan(1);
- expect(1n).not.toBeGreaterThan(Number.MAX_SAFE_INTEGER);
- expect(1n).not.toBeGreaterThan(Number.MAX_VALUE);
- expect(1).not.toBeGreaterThan(1n);
- expect(Number.MAX_SAFE_INTEGER).toBeGreaterThan(1n);
- expect(Number.MAX_VALUE).toBeGreaterThan(1n);
-
- expect(BigInt(Number.MAX_SAFE_INTEGER)).toBeGreaterThan(1n);
- expect(BigInt(Number.MAX_VALUE)).toBeGreaterThan(1n);
- expect(1n).not.toBeGreaterThan(BigInt(Number.MAX_SAFE_INTEGER));
- expect(1n).not.toBeGreaterThan(BigInt(Number.MAX_VALUE));
-
- expect(BigInt(Number.MAX_SAFE_INTEGER)).toBeGreaterThan(1);
- expect(BigInt(Number.MAX_VALUE)).toBeGreaterThan(1);
- expect(1).not.toBeGreaterThan(BigInt(Number.MAX_SAFE_INTEGER));
-});
-
-test("toBeGreaterThanOrEqual()", () => {
- expect(Number.MAX_VALUE).toBeGreaterThanOrEqual(Number.MAX_VALUE);
- expect(1).not.toBeGreaterThanOrEqual(Number.MAX_SAFE_INTEGER);
- expect(1).not.toBeGreaterThanOrEqual(BigInt(Number.MAX_SAFE_INTEGER));
- expect(1).not.toBeGreaterThanOrEqual(BigInt(Number.MAX_VALUE));
- expect(Number.MAX_SAFE_INTEGER).toBeGreaterThanOrEqual(Number.MAX_SAFE_INTEGER);
- expect(BigInt(Number.MAX_SAFE_INTEGER)).toBeGreaterThanOrEqual(BigInt(Number.MAX_SAFE_INTEGER));
-
- expect(Infinity).toBeGreaterThanOrEqual(-Infinity);
- expect(-Infinity).not.toBeGreaterThanOrEqual(Infinity);
-
- expect(NaN).not.toBeGreaterThanOrEqual(NaN);
- expect(NaN).not.toBeGreaterThanOrEqual(-Infinity);
-
- expect(10).toBeGreaterThanOrEqual(9);
- expect(10).toBeGreaterThanOrEqual(10);
- expect(10).not.toBeGreaterThanOrEqual(11);
- expect(10).not.toBeGreaterThanOrEqual(Infinity);
- expect(10).toBeGreaterThanOrEqual(-Infinity);
- expect(10).not.toBeGreaterThanOrEqual(NaN);
- expect(10).toBeGreaterThanOrEqual(0);
- expect(10).toBeGreaterThanOrEqual(-0);
- expect(10).toBeGreaterThanOrEqual(0.1);
- expect(10).toBeGreaterThanOrEqual(-0.1);
- expect(10).toBeGreaterThanOrEqual(0.9);
- expect(10).toBeGreaterThanOrEqual(-0.9);
- expect(10).toBeGreaterThanOrEqual(1);
- expect(10).toBeGreaterThanOrEqual(-1);
- // switch the order
- expect(9).not.toBeGreaterThanOrEqual(10);
- expect(10).toBeGreaterThanOrEqual(10);
- expect(11).toBeGreaterThanOrEqual(10);
- expect(Infinity).toBeGreaterThanOrEqual(10);
- expect(-Infinity).not.toBeGreaterThanOrEqual(10);
- expect(NaN).not.toBeGreaterThanOrEqual(10);
- expect(0).not.toBeGreaterThanOrEqual(10);
- expect(-0).not.toBeGreaterThanOrEqual(10);
- expect(0.1).not.toBeGreaterThanOrEqual(10);
- expect(-0.1).not.toBeGreaterThanOrEqual(10);
- expect(0.9).not.toBeGreaterThanOrEqual(10);
- expect(-0.9).not.toBeGreaterThanOrEqual(10);
- expect(1).not.toBeGreaterThanOrEqual(10);
- expect(-1).not.toBeGreaterThanOrEqual(10);
-
- // same tests but use bigints
- expect(10n).toBeGreaterThanOrEqual(9n);
- expect(10n).toBeGreaterThanOrEqual(10n);
- expect(10n).not.toBeGreaterThanOrEqual(11n);
- expect(10n).not.toBeGreaterThanOrEqual(Infinity);
- expect(10n).toBeGreaterThanOrEqual(-Infinity);
- expect(10n).not.toBeGreaterThanOrEqual(NaN);
- expect(10n).toBeGreaterThanOrEqual(0n);
- expect(10n).toBeGreaterThanOrEqual(-0n);
- expect(10n).toBeGreaterThanOrEqual(1n);
- expect(10n).toBeGreaterThanOrEqual(-1n);
- // switch the order
- expect(9n).not.toBeGreaterThanOrEqual(10n);
- expect(10n).toBeGreaterThanOrEqual(10n);
- expect(11n).toBeGreaterThanOrEqual(10n);
- expect(Infinity).toBeGreaterThanOrEqual(10n);
- expect(-Infinity).not.toBeGreaterThanOrEqual(10n);
- expect(NaN).not.toBeGreaterThanOrEqual(10n);
- expect(0n).not.toBeGreaterThanOrEqual(10n);
- expect(-0n).not.toBeGreaterThanOrEqual(10n);
- expect(1n).not.toBeGreaterThanOrEqual(10n);
- expect(-1n).not.toBeGreaterThanOrEqual(10n);
-
- // use bigints and numbers
- expect(10n).toBeGreaterThanOrEqual(9);
- expect(10n).toBeGreaterThanOrEqual(10);
- expect(10n).not.toBeGreaterThanOrEqual(11);
- expect(10n).not.toBeGreaterThanOrEqual(Infinity);
- expect(10n).toBeGreaterThanOrEqual(-Infinity);
- expect(10n).not.toBeGreaterThanOrEqual(NaN);
- expect(10n).toBeGreaterThanOrEqual(0);
- expect(10n).toBeGreaterThanOrEqual(-0);
- expect(10n).toBeGreaterThanOrEqual(0.1);
- expect(10n).toBeGreaterThanOrEqual(-0.1);
- expect(10n).toBeGreaterThanOrEqual(0.9);
- expect(10n).toBeGreaterThanOrEqual(-0.9);
- expect(10n).toBeGreaterThanOrEqual(1);
- expect(10n).toBeGreaterThanOrEqual(-1);
- // switch the order
- expect(9n).not.toBeGreaterThanOrEqual(10);
- expect(10n).toBeGreaterThanOrEqual(10);
- expect(11n).toBeGreaterThanOrEqual(10);
- expect(Infinity).toBeGreaterThanOrEqual(10n);
- expect(-Infinity).not.toBeGreaterThanOrEqual(10n);
- expect(NaN).not.toBeGreaterThanOrEqual(10n);
- expect(0n).not.toBeGreaterThanOrEqual(10);
- expect(-0n).not.toBeGreaterThanOrEqual(10);
- expect(1n).not.toBeGreaterThanOrEqual(10);
- expect(-1n).not.toBeGreaterThanOrEqual(10);
-
- expect(1n).toBeGreaterThanOrEqual(1);
- expect(1n).not.toBeGreaterThanOrEqual(Number.MAX_SAFE_INTEGER);
- expect(1n).not.toBeGreaterThanOrEqual(Number.MAX_VALUE);
- expect(1).toBeGreaterThanOrEqual(1n);
- expect(Number.MAX_SAFE_INTEGER).toBeGreaterThanOrEqual(1n);
- expect(Number.MAX_VALUE).toBeGreaterThanOrEqual(1n);
-
- expect(1).not.toBeGreaterThanOrEqual(BigInt(Number.MAX_VALUE));
-});
-
-test("toBeLessThan()", () => {
- expect(3n).not.toBeLessThan(2);
- expect(Number.MAX_VALUE).not.toBeLessThan(Number.MAX_VALUE);
- expect(1).toBeLessThan(BigInt(Number.MAX_VALUE));
- expect(1).toBeLessThan(Number.MAX_SAFE_INTEGER);
- expect(1).toBeLessThan(BigInt(Number.MAX_SAFE_INTEGER));
- expect(Number.MAX_SAFE_INTEGER).not.toBeLessThan(Number.MAX_SAFE_INTEGER);
- expect(BigInt(Number.MAX_SAFE_INTEGER)).not.toBeLessThan(BigInt(Number.MAX_SAFE_INTEGER));
-
- expect(Number.MAX_VALUE).not.toBeLessThan(BigInt(Number.MAX_VALUE));
-
- expect(NaN).not.toBeLessThan(NaN);
- expect(NaN).not.toBeLessThan(-Infinity);
-
- expect(10).not.toBeLessThan(9);
- expect(10).not.toBeLessThan(10);
- expect(10).toBeLessThan(11);
- expect(10).toBeLessThan(Infinity);
- expect(10).not.toBeLessThan(-Infinity);
- expect(10).not.toBeLessThan(NaN);
- expect(10).not.toBeLessThan(0);
- expect(10).not.toBeLessThan(-0);
- expect(10).not.toBeLessThan(0.1);
- expect(10).not.toBeLessThan(-0.1);
- expect(10).not.toBeLessThan(0.9);
- expect(10).not.toBeLessThan(-0.9);
- expect(10).not.toBeLessThan(1);
- expect(10).not.toBeLessThan(-1);
- // switch the order
- expect(9).toBeLessThan(10);
- expect(10).not.toBeLessThan(10);
- expect(11).not.toBeLessThan(10);
- expect(Infinity).not.toBeLessThan(10);
- expect(-Infinity).toBeLessThan(10);
- expect(NaN).not.toBeLessThan(10);
- expect(0).toBeLessThan(10);
- expect(-0).toBeLessThan(10);
- expect(0.1).toBeLessThan(10);
- expect(-0.1).toBeLessThan(10);
- expect(0.9).toBeLessThan(10);
- expect(-0.9).toBeLessThan(10);
- expect(1).toBeLessThan(10);
- expect(-1).toBeLessThan(10);
-
- // same tests but use bigints
- expect(10n).not.toBeLessThan(9n);
- expect(10n).not.toBeLessThan(10n);
- expect(10n).toBeLessThan(11n);
- expect(10n).toBeLessThan(Infinity);
- expect(10n).not.toBeLessThan(-Infinity);
- expect(10n).not.toBeLessThan(NaN);
- expect(10n).not.toBeLessThan(0n);
- expect(10n).not.toBeLessThan(-0n);
- expect(10n).not.toBeLessThan(1n);
- expect(10n).not.toBeLessThan(-1n);
- // switch the order
- expect(9n).toBeLessThan(10n);
- expect(10n).not.toBeLessThan(10n);
- expect(11n).not.toBeLessThan(10n);
- expect(Infinity).not.toBeLessThan(10n);
- expect(-Infinity).toBeLessThan(10n);
- expect(NaN).not.toBeLessThan(10n);
- expect(0n).toBeLessThan(10n);
- expect(-0n).toBeLessThan(10n);
- expect(1n).toBeLessThan(10n);
- expect(-1n).toBeLessThan(10n);
-
- // use bigints and numbers
- expect(10n).not.toBeLessThan(9);
- expect(10n).not.toBeLessThan(10);
- expect(10n).toBeLessThan(11);
- expect(10n).toBeLessThan(Infinity);
- expect(10n).not.toBeLessThan(-Infinity);
- expect(10n).not.toBeLessThan(NaN);
- expect(10n).not.toBeLessThan(0);
- expect(10n).not.toBeLessThan(-0);
- expect(10n).not.toBeLessThan(0.1);
- expect(10n).not.toBeLessThan(-0.1);
- expect(10n).not.toBeLessThan(0.9);
- expect(10n).not.toBeLessThan(-0.9);
- expect(10n).not.toBeLessThan(1);
- expect(10n).not.toBeLessThan(-1);
- // switch the order
- expect(9n).toBeLessThan(10);
- expect(10n).not.toBeLessThan(10);
- expect(11n).not.toBeLessThan(10);
- expect(Infinity).not.toBeLessThan(10n);
- expect(-Infinity).toBeLessThan(10n);
- expect(NaN).not.toBeLessThan(10n);
- expect(0n).toBeLessThan(10);
- expect(-0n).toBeLessThan(10);
- expect(1n).toBeLessThan(10);
- expect(-1n).toBeLessThan(10);
-
- expect(1n).not.toBeLessThan(1);
- expect(1n).toBeLessThan(Number.MAX_SAFE_INTEGER);
- expect(1n).toBeLessThan(Number.MAX_VALUE);
- expect(1).not.toBeLessThan(1n);
- expect(Number.MAX_SAFE_INTEGER).not.toBeLessThan(1n);
- expect(Number.MAX_VALUE).not.toBeLessThan(1n);
-
- expect(BigInt(Number.MAX_SAFE_INTEGER)).not.toBeLessThan(1n);
- expect(BigInt(Number.MAX_VALUE)).not.toBeLessThan(1n);
- expect(1n).toBeLessThan(BigInt(Number.MAX_SAFE_INTEGER));
- expect(1n).toBeLessThan(BigInt(Number.MAX_VALUE));
-
- expect(BigInt(Number.MAX_SAFE_INTEGER)).not.toBeLessThan(1);
- expect(BigInt(Number.MAX_VALUE)).not.toBeLessThan(1);
- expect(1).toBeLessThan(BigInt(Number.MAX_SAFE_INTEGER));
-});
-
-test("toBeLessThanOrEqual()", () => {
- expect(3n).not.toBeLessThanOrEqual(2);
- expect(Number.MAX_VALUE).toBeLessThanOrEqual(Number.MAX_VALUE);
- expect(1).toBeLessThanOrEqual(BigInt(Number.MAX_VALUE));
- expect(1).toBeLessThanOrEqual(Number.MAX_SAFE_INTEGER);
- expect(1).toBeLessThanOrEqual(BigInt(Number.MAX_SAFE_INTEGER));
- expect(Number.MAX_SAFE_INTEGER).toBeLessThanOrEqual(Number.MAX_SAFE_INTEGER);
- expect(BigInt(Number.MAX_SAFE_INTEGER)).toBeLessThanOrEqual(BigInt(Number.MAX_SAFE_INTEGER));
-
- expect(Number.MAX_VALUE).toBeLessThanOrEqual(BigInt(Number.MAX_VALUE));
- expect(BigInt(Number.MAX_VALUE)).toBeLessThanOrEqual(Number.MAX_VALUE);
-
- expect(NaN).not.toBeLessThanOrEqual(NaN);
- expect(NaN).not.toBeLessThanOrEqual(-Infinity);
-
- expect(10).not.toBeLessThanOrEqual(9);
- expect(10).toBeLessThanOrEqual(10);
- expect(10).toBeLessThanOrEqual(11);
- expect(10).toBeLessThanOrEqual(Infinity);
- expect(10).not.toBeLessThanOrEqual(-Infinity);
- expect(10).not.toBeLessThanOrEqual(NaN);
- expect(10).not.toBeLessThanOrEqual(0);
- expect(10).not.toBeLessThanOrEqual(-0);
- expect(10).not.toBeLessThanOrEqual(0.1);
- expect(10).not.toBeLessThanOrEqual(-0.1);
- expect(10).not.toBeLessThanOrEqual(0.9);
- expect(10).not.toBeLessThanOrEqual(-0.9);
- expect(10).not.toBeLessThanOrEqual(1);
- expect(10).not.toBeLessThanOrEqual(-1);
- // switch the order
- expect(9).toBeLessThanOrEqual(10);
- expect(10).toBeLessThanOrEqual(10);
- expect(11).not.toBeLessThanOrEqual(10);
- expect(Infinity).not.toBeLessThanOrEqual(10);
- expect(-Infinity).toBeLessThanOrEqual(10);
- expect(NaN).not.toBeLessThanOrEqual(10);
- expect(0).toBeLessThanOrEqual(10);
- expect(-0).toBeLessThanOrEqual(10);
- expect(0.1).toBeLessThanOrEqual(10);
- expect(-0.1).toBeLessThanOrEqual(10);
- expect(0.9).toBeLessThanOrEqual(10);
- expect(-0.9).toBeLessThanOrEqual(10);
- expect(1).toBeLessThanOrEqual(10);
- expect(-1).toBeLessThanOrEqual(10);
-
- // same tests but use bigints
- expect(10n).not.toBeLessThanOrEqual(9n);
- expect(10n).toBeLessThanOrEqual(10n);
- expect(10n).toBeLessThanOrEqual(11n);
- expect(10n).toBeLessThanOrEqual(Infinity);
- expect(10n).not.toBeLessThanOrEqual(-Infinity);
- expect(10n).not.toBeLessThanOrEqual(NaN);
- expect(10n).not.toBeLessThanOrEqual(0n);
- expect(10n).not.toBeLessThanOrEqual(-0n);
- expect(10n).not.toBeLessThanOrEqual(1n);
- expect(10n).not.toBeLessThanOrEqual(-1n);
- // switch the order
- expect(9n).toBeLessThanOrEqual(10n);
- expect(10n).toBeLessThanOrEqual(10n);
- expect(11n).not.toBeLessThanOrEqual(10n);
- expect(Infinity).not.toBeLessThanOrEqual(10n);
- expect(-Infinity).toBeLessThanOrEqual(10n);
- expect(NaN).not.toBeLessThanOrEqual(10n);
- expect(0n).toBeLessThanOrEqual(10n);
- expect(-0n).toBeLessThanOrEqual(10n);
- expect(1n).toBeLessThanOrEqual(10n);
- expect(-1n).toBeLessThanOrEqual(10n);
-
- // use bigints and numbers
- expect(10n).not.toBeLessThanOrEqual(9);
- expect(10n).toBeLessThanOrEqual(10);
- expect(10n).toBeLessThanOrEqual(11);
- expect(10n).toBeLessThanOrEqual(Infinity);
- expect(10n).not.toBeLessThanOrEqual(-Infinity);
- expect(10n).not.toBeLessThanOrEqual(NaN);
- expect(10n).not.toBeLessThanOrEqual(0);
- expect(10n).not.toBeLessThanOrEqual(-0);
- expect(10n).not.toBeLessThanOrEqual(0.1);
- expect(10n).not.toBeLessThanOrEqual(-0.1);
- expect(10n).not.toBeLessThanOrEqual(0.9);
- expect(10n).not.toBeLessThanOrEqual(-0.9);
- expect(10n).not.toBeLessThanOrEqual(1);
- expect(10n).not.toBeLessThanOrEqual(-1);
- // switch the order
- expect(9n).toBeLessThanOrEqual(10);
- expect(10n).toBeLessThanOrEqual(10);
- expect(11n).not.toBeLessThanOrEqual(10);
- expect(Infinity).not.toBeLessThanOrEqual(10n);
- expect(-Infinity).toBeLessThanOrEqual(10n);
- expect(NaN).not.toBeLessThanOrEqual(10n);
- expect(0n).toBeLessThanOrEqual(10);
- expect(-0n).toBeLessThanOrEqual(10);
- expect(1n).toBeLessThanOrEqual(10);
- expect(-1n).toBeLessThanOrEqual(10);
-
- expect(1n).toBeLessThanOrEqual(1);
- expect(1n).toBeLessThanOrEqual(Number.MAX_SAFE_INTEGER);
- expect(1n).toBeLessThanOrEqual(Number.MAX_VALUE);
- expect(1).toBeLessThanOrEqual(1n);
- expect(Number.MAX_SAFE_INTEGER).not.toBeLessThanOrEqual(1n);
- expect(Number.MAX_VALUE).not.toBeLessThanOrEqual(1n);
-
- expect(BigInt(Number.MAX_SAFE_INTEGER)).not.toBeLessThanOrEqual(1n);
- expect(BigInt(Number.MAX_VALUE)).not.toBeLessThanOrEqual(1n);
- expect(1n).toBeLessThanOrEqual(BigInt(Number.MAX_SAFE_INTEGER));
- expect(1n).toBeLessThanOrEqual(BigInt(Number.MAX_VALUE));
-
- expect(BigInt(Number.MAX_SAFE_INTEGER)).not.toBeLessThanOrEqual(1);
- expect(BigInt(Number.MAX_VALUE)).not.toBeLessThanOrEqual(1);
- expect(1).toBeLessThanOrEqual(BigInt(Number.MAX_SAFE_INTEGER));
-});
-
-test("toBeOdd()", () => {
- expect(1).toBeOdd();
- expect(2).not.toBeOdd();
- expect(3).toBeOdd();
- expect(3.1).not.toBeOdd();
- expect(2.1).not.toBeOdd();
- expect(4).not.toBeOdd();
- expect(5).toBeOdd();
- expect(6).not.toBeOdd();
- expect(0).not.toBeOdd();
- expect(-8).not.toBeOdd();
- expect(-0).not.toBeOdd();
- expect(NaN).not.toBeOdd();
- expect([]).not.toBeOdd();
- // SHOULD FAIL: expect([]).toBeOdd();
- expect([1, 2]).not.toBeOdd();
- expect({}).not.toBeOdd();
- expect(() => {}).not.toBeOdd();
- expect("").not.toBeOdd();
- expect("string").not.toBeOdd();
- expect(undefined).not.toBeOdd();
- expect(Math.floor(Date.now() / 1000) * 2 - 1).toBeOdd(); // Slight fuzz by using timestamp times 2
- expect(Math.floor(Date.now() / 1000) * 4 - 1).toBeOdd();
- expect(4.0e1).not.toBeOdd();
- expect(6.2e1).not.toBeOdd();
- expect(6.3e1).toBeOdd();
- expect(6.33e1).not.toBeOdd();
- expect(3.2e-3).not.toBeOdd();
- expect(0.3).not.toBeOdd();
- expect(0.4).not.toBeOdd();
- expect(1).toBeOdd();
- expect(0).not.toBeOdd();
- expect(2.0).not.toBeOdd();
- expect(NaN).not.toBeOdd();
- expect(2n).not.toBeOdd(); // BigInt at this time not supported in jest-extended
- expect(3n).toBeOdd();
- expect(9007199254740990).not.toBeOdd(); // manual typical max safe -1
- expect(9007199254740991).toBeOdd();
- expect(9007199254740990n).not.toBeOdd(); // manual typical max safe -1 as bigint
- expect(9007199254740991n).toBeOdd();
- expect(Number.MAX_SAFE_INTEGER - 1).not.toBeOdd();
- expect(Number.MAX_SAFE_INTEGER).toBeOdd();
- expect(BigInt(Number.MAX_SAFE_INTEGER) - 1n).not.toBeOdd();
- expect(BigInt(Number.MAX_SAFE_INTEGER)).toBeOdd();
- expect(Number.MIN_SAFE_INTEGER + 1).not.toBeOdd();
- expect(Number.MIN_SAFE_INTEGER).toBeOdd();
- expect(BigInt(Number.MIN_SAFE_INTEGER) + 1n).not.toBeOdd();
- expect(BigInt(Number.MIN_SAFE_INTEGER)).toBeOdd();
- expect(4 / Number.NEGATIVE_INFINITY).not.toBeOdd(); // in IEEE-754: + / -inf => neg zero
- expect(5 / Number.NEGATIVE_INFINITY).not.toBeOdd();
- expect(-7 / Number.NEGATIVE_INFINITY).not.toBeOdd(); // in IEEE-754: - / -inf => zero
- expect(-8 / Number.NEGATIVE_INFINITY).not.toBeOdd();
- expect(new WebAssembly.Global({ value: "i32", mutable: false }, 4).value).not.toBeOdd();
- expect(new WebAssembly.Global({ value: "i32", mutable: false }, 3).value).toBeOdd();
- expect(new WebAssembly.Global({ value: "i32", mutable: true }, 2).value).not.toBeOdd();
- expect(new WebAssembly.Global({ value: "i32", mutable: true }, 1).value).toBeOdd();
- expect(new WebAssembly.Global({ value: "i64", mutable: true }, -9223372036854775808n).value).not.toBeOdd();
- expect(new WebAssembly.Global({ value: "i64", mutable: false }, -9223372036854775808n).value).not.toBeOdd();
- expect(new WebAssembly.Global({ value: "i64", mutable: true }, 9223372036854775807n).value).toBeOdd();
- expect(new WebAssembly.Global({ value: "i64", mutable: false }, 9223372036854775807n).value).toBeOdd();
- expect(new WebAssembly.Global({ value: "f32", mutable: true }, 42.0).value).not.toBeOdd();
- expect(new WebAssembly.Global({ value: "f32", mutable: false }, 42.0).value).not.toBeOdd();
- expect(new WebAssembly.Global({ value: "f64", mutable: true }, 42.0).value).not.toBeOdd();
- expect(new WebAssembly.Global({ value: "f64", mutable: false }, 42.0).value).not.toBeOdd();
- expect(new WebAssembly.Global({ value: "f32", mutable: true }, 43.0).value).toBeOdd();
- expect(new WebAssembly.Global({ value: "f32", mutable: false }, 43.0).value).toBeOdd();
- expect(new WebAssembly.Global({ value: "f64", mutable: true }, 43.0).value).toBeOdd();
- expect(new WebAssembly.Global({ value: "f64", mutable: false }, 43.0).value).toBeOdd();
- expect(new WebAssembly.Global({ value: "f32", mutable: true }, 4.3).value).not.toBeOdd();
- expect(new WebAssembly.Global({ value: "f32", mutable: false }, 4.3).value).not.toBeOdd();
- expect(new WebAssembly.Global({ value: "f64", mutable: true }, 4.3).value).not.toBeOdd();
- expect(new WebAssembly.Global({ value: "f64", mutable: false }, 4.3).value).not.toBeOdd();
- // did not seem to support SIMD v128 type yet
- // FUTURE: expect(new WebAssembly.Global({value:'v128', mutable:false}, 42).value).not.toBeOdd();
- // FUTURE: expect(new WebAssembly.Global({value:'v128', mutable:true}, 42).value).not.toBeOdd();
- // FUTURE: expect(new WebAssembly.Global({value:'v128', mutable:true}, 43).value).toBeOdd();
-});
-
-describe("toMatchObject", () => {
- test("with Bun.deepMatch", () => {
- expect(Bun.deepMatch({ a: 1, b: 2 }, { a: 1 })).toBe(false);
- expect(Bun.deepMatch({ a: 1 }, { a: 1, b: 2 })).toBe(true);
- });
- test("with expect matcher", () => {
- const f = Symbol.for("foo");
- const b = Symbol.for("bar");
-
- class Number2 extends Number {
- constructor(value) {
- super(value);
- }
- }
- class Number3 extends Number2 {
- constructor(value) {
- super(value);
- }
- }
-
- class Boolean2 extends Boolean {
- constructor(value) {
- super(value);
- }
- }
- expect({ [f]: 2 }).toMatchObject({ [f]: 2 });
- expect({ [f]: 2 }).toMatchObject({ [f]: expect.anything() });
- expect({ [f]: new Date() }).toMatchObject({ [f]: expect.any(Date) });
- expect({ [f]: new Date() }).not.toMatchObject({ [f]: expect.any(RegExp) });
- expect({ [f]: 3 }).not.toMatchObject({ [f]: 5 });
- expect({ [f]: 3 }).not.toMatchObject({ [b]: 3 });
- expect({}).toMatchObject({});
- expect([5]).toMatchObject([5]);
- expect([5]).not.toMatchObject([4]);
- expect(() => {
- expect({}).toMatchObject();
- }).toThrow();
- expect(() => {
- expect(true).toMatchObject(true);
- }).toThrow();
- expect(() => {
- expect(true).toMatchObject(true);
- }).toThrow();
- expect(() => {
- expect(1).toMatchObject(1);
- }).toThrow();
- expect(() => {
- expect("a").toMatchObject("a");
- }).toThrow();
- expect(() => {
- expect(null).toMatchObject(null);
- }).toThrow();
- expect(() => {
- expect(undefined).toMatchObject(undefined);
- }).toThrow();
- expect(() => {
- expect(Symbol()).toMatchObject(Symbol());
- }).toThrow();
- expect(() => {
- expect(BigInt(1)).toMatchObject(BigInt(1));
- }).toThrow();
- expect([]).toMatchObject([]);
- expect([1]).toMatchObject([1]);
- expect([1, 2]).toMatchObject([1, 2]);
- expect(() => {
- expect([1]).toMatchObject([1, 2]);
- }).toThrow();
- expect(() => {
- expect([1, 2]).toMatchObject([1]);
- }).toThrow();
- expect([]).toMatchObject({});
- expect([1]).toMatchObject({});
- expect([1, 2]).toMatchObject({ 0: 1, 1: 2 });
- expect([1, 2]).not.toMatchObject({ 0: 2 });
- expect(() => {
- expect({}).toMatchObject([]);
- }).toThrow();
- expect({ a: 1 }).toMatchObject({});
- expect({ a: 1 }).toMatchObject({ a: expect.anything() });
- expect({ a: 1, b: 2 }).toMatchObject({ a: 1 });
- expect({ a: 1, b: 2 }).toMatchObject({ a: 1, b: 2 });
- expect({ a: 1, b: 2 }).toMatchObject({ b: 2 });
- expect({ a: 1, b: 2 }).toMatchObject({ b: 2, a: 1 });
- expect({ a: 1, b: 2 }).toMatchObject({ a: 1, b: 2 });
- expect({}).not.toMatchObject({ a: 1 });
- expect({ a: 89 }).not.toMatchObject({ b: 90 });
- expect({ a: 1, b: 2 }).not.toMatchObject({ a: 1, b: 3 });
- expect({ a: 1, b: 2 }).not.toMatchObject({ a: 1, b: 2, c: 4 });
- expect({ a: new Date(), b: "jj" }).not.toMatchObject({ b: expect.any(Number) });
- expect({ a: "123" }).not.toMatchObject({ a: expect.stringContaining("4") });
- class DString extends String {
- constructor(str) {
- super(str);
- }
- }
- expect({ a: "hello world" }).toMatchObject({ a: expect.stringContaining("wor") });
- expect({ a: "hello world" }).not.toMatchObject({ a: expect.stringContaining("wol") });
- expect({ a: "hello String" }).toMatchObject({ a: expect.stringContaining(new String("Str")) });
- expect({ a: "hello String" }).not.toMatchObject({ a: expect.stringContaining(new String("Strs")) });
- expect({ a: "hello derived String" }).toMatchObject({ a: expect.stringContaining(new DString("riv")) });
- expect({ a: "hello derived String" }).not.toMatchObject({ a: expect.stringContaining(new DString("rivd")) });
- expect({ a: "hello world" }).toMatchObject({ a: expect.stringMatching("wor") });
- expect({ a: "hello world" }).not.toMatchObject({ a: expect.stringMatching("word") });
- expect({ a: "hello world" }).toMatchObject({ a: "hello world" });
- expect({ a: "hello world" }).toMatchObject({ a: expect.stringMatching(/wor/) });
- expect({ a: "hello world" }).not.toMatchObject({ a: expect.stringMatching(/word/) });
- expect({ a: expect.stringMatching("wor") }).toMatchObject({ a: "hello world" });
- expect({ a: expect.stringMatching("word") }).not.toMatchObject({ a: "hello world" });
- expect({ a: expect.stringMatching(/wor/) }).toMatchObject({ a: "hello world" });
- expect({ a: expect.stringMatching(/word/) }).not.toMatchObject({ a: "hello world" });
- expect({ a: expect.stringMatching(/word/) }).toMatchObject({ a: "hello word" });
- expect({ a: [1, 2, 3] }).toMatchObject({ a: [1, 2, 3] });
- expect({ a: [1, 2, 3] }).toMatchObject({ a: [1, 2, 3] });
- expect({ a: [1, 2, 4] }).not.toMatchObject({ a: [1, 2, 3] });
-
- expect([]).toMatchObject([]);
- expect([]).toMatchObject({});
- expect({}).not.toMatchObject([]);
- expect({ a: 1 }).toMatchObject({});
- expect({ a: 1 }).toMatchObject({ a: 1 });
-
- expect({ a: 1 }).toMatchObject({ a: expect.anything() });
- expect({ a: null }).not.toMatchObject({ a: expect.anything() });
- expect({ a: undefined }).not.toMatchObject({ a: expect.anything() });
-
- expect({ a: new Date() }).toMatchObject({ a: expect.any(Date) });
- expect({ a: new Date() }).not.toMatchObject({ a: expect.any(RegExp) });
- expect({ a: new RegExp("a", "g") }).toMatchObject({ a: expect.any(RegExp) });
- expect({ a: /a/g }).toMatchObject({ a: expect.any(RegExp) });
-
- expect({
- first: new Boolean2(false),
- a: {
- 4: [3, 2, 2],
- j: new Date(),
- b: {
- c: {
- num: 1,
- d: {
- e: {
- bigint: 123n,
- f: {
- g: {
- h: {
- i: new Number3(2),
- bool: true,
- },
- compare: "compare",
- },
- },
- ignore1: 234,
- ignore2: {
- ignore3: 23421,
- ignore4: {
- ignore5: {
- ignore6: "hello",
- ignore7: "done",
- },
- },
- },
- },
- },
- string1: "hello",
- string2: "hello",
- string3: "hello",
- },
- },
- },
- }).toMatchObject({
- first: expect.any(Boolean2),
- a: {
- 4: [3, 2, expect.any(Number)],
-
- j: expect.any(Date),
- b: {
- c: {
- num: expect.any(Number),
- string1: expect.anything(),
- string2: expect.stringContaining("ll"),
- string3: expect.stringMatching(/ll/),
- d: {
- e: {
- bigint: expect.any(BigInt),
- f: {
- g: {
- compare: "compare",
- h: {
- i: expect.any(Number3),
- bool: expect.any(Boolean),
- },
- },
- },
- },
- },
- },
- },
- },
- });
-
- var a1 = [1];
- a1[f] = 99;
- expect(a1).not.toMatchObject([1]);
- expect([1]).not.toMatchObject(a1);
- expect({ 1: 1 }).not.toMatchObject(a1);
- expect(a1).not.toMatchObject({ 1: 1 });
- expect(a1).toMatchObject(a1);
- });
-});
-
try {
test("test this doesnt crash");
} catch (e) {}
diff --git a/test/package.json b/test/package.json
index 7722e0888..a9b8db913 100644
--- a/test/package.json
+++ b/test/package.json
@@ -4,6 +4,7 @@
"@types/dedent": "^0.7.0"
},
"dependencies": {
+ "@prisma/client": "4.15.0",
"@swc/core": "^1.3.38",
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
@@ -13,15 +14,15 @@
"esbuild": "^0.17.16",
"express": "^4.18.2",
"iconv-lite": "^0.6.3",
+ "jest-extended": "^4.0.0",
"lodash": "^4.17.21",
- "svelte": "^3.55.1",
- "typescript": "^5.0.2",
- "undici": "^5.20.0",
+ "prisma": "4.15.0",
"socket.io": "^4.6.1",
"socket.io-client": "^4.6.1",
"supertest": "^6.1.6",
- "@prisma/client": "4.15.0",
- "prisma": "4.15.0"
+ "svelte": "^3.55.1",
+ "typescript": "^5.0.2",
+ "undici": "^5.20.0"
},
"private": true,
"scripts": {
diff --git a/test/snippets/package-json-exports/_node_modules_copy/exact/package.json b/test/snippets/package-json-exports/_node_modules_copy/exact/package.json
index e69de29bb..0967ef424 100644
--- a/test/snippets/package-json-exports/_node_modules_copy/exact/package.json
+++ b/test/snippets/package-json-exports/_node_modules_copy/exact/package.json
@@ -0,0 +1 @@
+{}