mirror of
https://github.com/oven-sh/bun
synced 2026-02-14 04:49:06 +00:00
fix: expect().resolves and expect().rejects now return promises
Previously, matchers under `expect().resolves` and `expect().rejects` would return `undefined` instead of a promise. This caused issues when trying to chain or await matcher results. This fix adds a helper function `returnMatcherValue()` that checks if async flags (.resolves/.rejects) are set and returns a resolved promise instead of undefined. All matchers now use this helper. Fixes #23420 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -848,7 +848,7 @@ pub const Expect = struct {
|
||||
if (existing_value) |saved_value| {
|
||||
if (strings.eqlLong(pretty_value.slice(), saved_value, true)) {
|
||||
Jest.runner.?.snapshots.passed += 1;
|
||||
return .js_undefined;
|
||||
return this.returnMatcherValue(globalThis);
|
||||
}
|
||||
|
||||
Jest.runner.?.snapshots.failed += 1;
|
||||
@@ -863,7 +863,7 @@ pub const Expect = struct {
|
||||
return globalThis.throwPretty(fmt, .{diff_format});
|
||||
}
|
||||
|
||||
return .js_undefined;
|
||||
return this.returnMatcherValue(globalThis);
|
||||
}
|
||||
|
||||
pub fn getStaticNot(globalThis: *JSGlobalObject, _: JSValue, _: JSValue) bun.JSError!JSValue {
|
||||
@@ -1231,6 +1231,16 @@ pub const Expect = struct {
|
||||
vm.autoGarbageCollect();
|
||||
}
|
||||
|
||||
/// Helper function for matchers to return the correct value based on whether
|
||||
/// .resolves or .rejects was used. When async flags are set, returns a resolved promise.
|
||||
/// Otherwise returns undefined.
|
||||
pub inline fn returnMatcherValue(this: *const Expect, globalThis: *JSGlobalObject) JSValue {
|
||||
if (this.flags.promise != .none) {
|
||||
return JSPromise.resolvedPromiseValue(globalThis, .js_undefined);
|
||||
}
|
||||
return .js_undefined;
|
||||
}
|
||||
|
||||
pub fn doUnreachable(globalThis: *JSGlobalObject, callframe: *CallFrame) bun.JSError!JSValue {
|
||||
const arg = callframe.arguments_old(1).ptr[0];
|
||||
|
||||
@@ -2246,6 +2256,7 @@ const strings = bun.strings;
|
||||
const jsc = bun.jsc;
|
||||
const CallFrame = jsc.CallFrame;
|
||||
const JSGlobalObject = jsc.JSGlobalObject;
|
||||
const JSPromise = jsc.JSPromise;
|
||||
const JSValue = jsc.JSValue;
|
||||
const VirtualMachine = jsc.VirtualMachine;
|
||||
const ZigString = jsc.ZigString;
|
||||
|
||||
@@ -22,7 +22,7 @@ pub fn toBe(
|
||||
var pass = try right.isSameValue(left, globalThis);
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
|
||||
@@ -9,7 +9,7 @@ pub fn toBeArray(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFra
|
||||
const not = this.flags.not;
|
||||
const pass = value.jsType().isArray() != not;
|
||||
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
defer formatter.deinit();
|
||||
|
||||
@@ -24,7 +24,7 @@ pub fn toBeArrayOfSize(this: *Expect, globalThis: *JSGlobalObject, callFrame: *C
|
||||
var pass = value.jsType().isArray() and @as(i32, @intCast(try value.getLength(globalThis))) == size.toInt32();
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
defer formatter.deinit();
|
||||
|
||||
@@ -9,7 +9,7 @@ pub fn toBeBoolean(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallF
|
||||
const not = this.flags.not;
|
||||
const pass = value.isBoolean() != not;
|
||||
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
defer formatter.deinit();
|
||||
|
||||
@@ -43,7 +43,7 @@ pub fn toBeCloseTo(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallF
|
||||
}
|
||||
|
||||
if (std.math.isPositiveInf(expected) and std.math.isPositiveInf(received)) {
|
||||
return .js_undefined;
|
||||
return this.returnMatcherValue(globalThis);
|
||||
}
|
||||
|
||||
const expected_diff = bun.pow(10, -precision) / 2;
|
||||
@@ -53,7 +53,7 @@ pub fn toBeCloseTo(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallF
|
||||
const not = this.flags.not;
|
||||
if (not) pass = !pass;
|
||||
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
defer formatter.deinit();
|
||||
|
||||
@@ -9,7 +9,7 @@ pub fn toBeDate(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFram
|
||||
const not = this.flags.not;
|
||||
const pass = value.isDate() != not;
|
||||
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
defer formatter.deinit();
|
||||
|
||||
@@ -9,7 +9,7 @@ pub fn toBeDefined(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallF
|
||||
const not = this.flags.not;
|
||||
var pass = !value.isUndefined();
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
|
||||
@@ -61,7 +61,7 @@ pub fn toBeEmpty(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFra
|
||||
}
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
if (not) {
|
||||
const signature = comptime getSignature("toBeEmpty", "", true);
|
||||
|
||||
@@ -10,7 +10,7 @@ pub fn toBeEmptyObject(this: *Expect, globalThis: *JSGlobalObject, callFrame: *C
|
||||
var pass = try value.isObjectEmpty(globalThis);
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return thisValue;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
defer formatter.deinit();
|
||||
|
||||
@@ -34,7 +34,7 @@ pub fn toBeEven(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFram
|
||||
}
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
|
||||
@@ -9,7 +9,7 @@ pub fn toBeFalse(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFra
|
||||
const not = this.flags.not;
|
||||
const pass = (value.isBoolean() and !value.toBoolean()) != not;
|
||||
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
defer formatter.deinit();
|
||||
|
||||
@@ -14,7 +14,7 @@ pub fn toBeFalsy(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFra
|
||||
if (!truthy) pass = true;
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
|
||||
@@ -15,7 +15,7 @@ pub fn toBeFinite(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFr
|
||||
const not = this.flags.not;
|
||||
if (not) pass = !pass;
|
||||
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
defer formatter.deinit();
|
||||
|
||||
@@ -9,7 +9,7 @@ pub fn toBeFunction(this: *Expect, globalThis: *JSGlobalObject, callFrame: *Call
|
||||
const not = this.flags.not;
|
||||
const pass = value.isCallable() != not;
|
||||
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
defer formatter.deinit();
|
||||
|
||||
@@ -38,7 +38,7 @@ pub fn toBeGreaterThan(this: *Expect, globalThis: *JSGlobalObject, callFrame: *C
|
||||
}
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
|
||||
@@ -38,7 +38,7 @@ pub fn toBeGreaterThanOrEqual(this: *Expect, globalThis: *JSGlobalObject, callFr
|
||||
}
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
|
||||
@@ -24,7 +24,7 @@ pub fn toBeInstanceOf(this: *Expect, globalThis: *JSGlobalObject, callFrame: *Ca
|
||||
const not = this.flags.not;
|
||||
var pass = value.isInstanceOf(globalThis, expected_value);
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
const expected_fmt = expected_value.toFmt(&formatter);
|
||||
|
||||
@@ -9,7 +9,7 @@ pub fn toBeInteger(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallF
|
||||
const not = this.flags.not;
|
||||
const pass = value.isAnyInt() != not;
|
||||
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
defer formatter.deinit();
|
||||
|
||||
@@ -38,7 +38,7 @@ pub fn toBeLessThan(this: *Expect, globalThis: *JSGlobalObject, callFrame: *Call
|
||||
}
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
|
||||
@@ -38,7 +38,7 @@ pub fn toBeLessThanOrEqual(this: *Expect, globalThis: *JSGlobalObject, callFrame
|
||||
}
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
|
||||
@@ -14,7 +14,7 @@ pub fn toBeNaN(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame
|
||||
}
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
|
||||
@@ -15,7 +15,7 @@ pub fn toBeNegative(this: *Expect, globalThis: *JSGlobalObject, callFrame: *Call
|
||||
const not = this.flags.not;
|
||||
if (not) pass = !pass;
|
||||
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
defer formatter.deinit();
|
||||
|
||||
@@ -9,7 +9,7 @@ pub fn toBeNil(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame
|
||||
const not = this.flags.not;
|
||||
const pass = value.isUndefinedOrNull() != not;
|
||||
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
defer formatter.deinit();
|
||||
|
||||
@@ -9,7 +9,7 @@ pub fn toBeNull(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFram
|
||||
const not = this.flags.not;
|
||||
var pass = value.isNull();
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
|
||||
@@ -9,7 +9,7 @@ pub fn toBeNumber(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFr
|
||||
const not = this.flags.not;
|
||||
const pass = value.isNumber() != not;
|
||||
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
defer formatter.deinit();
|
||||
|
||||
@@ -9,7 +9,7 @@ pub fn toBeObject(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFr
|
||||
const not = this.flags.not;
|
||||
const pass = value.isObject() != not;
|
||||
|
||||
if (pass) return thisValue;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
defer formatter.deinit();
|
||||
|
||||
@@ -32,7 +32,7 @@ pub fn toBeOdd(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame
|
||||
}
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
|
||||
@@ -61,7 +61,7 @@ pub fn toBeOneOf(
|
||||
}
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
|
||||
@@ -15,7 +15,7 @@ pub fn toBePositive(this: *Expect, globalThis: *JSGlobalObject, callFrame: *Call
|
||||
const not = this.flags.not;
|
||||
if (not) pass = !pass;
|
||||
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
defer formatter.deinit();
|
||||
|
||||
@@ -9,7 +9,7 @@ pub fn toBeString(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFr
|
||||
const not = this.flags.not;
|
||||
const pass = value.isString() != not;
|
||||
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
defer formatter.deinit();
|
||||
|
||||
@@ -9,7 +9,7 @@ pub fn toBeSymbol(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFr
|
||||
const not = this.flags.not;
|
||||
const pass = value.isSymbol() != not;
|
||||
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
defer formatter.deinit();
|
||||
|
||||
@@ -9,7 +9,7 @@ pub fn toBeTrue(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFram
|
||||
const not = this.flags.not;
|
||||
const pass = (value.isBoolean() and value.toBoolean()) != not;
|
||||
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
defer formatter.deinit();
|
||||
|
||||
@@ -12,7 +12,7 @@ pub fn toBeTruthy(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFr
|
||||
if (truthy) pass = true;
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
|
||||
@@ -65,7 +65,7 @@ pub fn toBeTypeOf(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFr
|
||||
pass = strings.eql(typeof, whatIsTheType);
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
defer formatter.deinit();
|
||||
|
||||
@@ -10,7 +10,7 @@ pub fn toBeUndefined(this: *Expect, globalThis: *JSGlobalObject, callFrame: *Cal
|
||||
if (value.isUndefined()) pass = true;
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
|
||||
@@ -10,7 +10,7 @@ pub fn toBeValidDate(this: *Expect, globalThis: *JSGlobalObject, callFrame: *Cal
|
||||
var pass = (value.isDate() and !std.math.isNan(value.getUnixTimestamp()));
|
||||
if (not) pass = !pass;
|
||||
|
||||
if (pass) return thisValue;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
defer formatter.deinit();
|
||||
|
||||
@@ -36,7 +36,7 @@ pub fn toBeWithin(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFr
|
||||
const not = this.flags.not;
|
||||
if (not) pass = !pass;
|
||||
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
defer formatter.deinit();
|
||||
|
||||
@@ -73,7 +73,7 @@ pub fn toContain(
|
||||
}
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
|
||||
@@ -43,7 +43,7 @@ pub fn toContainAllKeys(
|
||||
}
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return thisValue;
|
||||
if (pass) return this.returnMatcherValue(globalObject);
|
||||
|
||||
// handle failure
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalObject, .quote_strings = true };
|
||||
|
||||
@@ -48,7 +48,7 @@ pub fn toContainAllValues(
|
||||
}
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return thisValue;
|
||||
if (pass) return this.returnMatcherValue(globalObject);
|
||||
|
||||
// handle failure
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalObject, .quote_strings = true };
|
||||
|
||||
@@ -41,7 +41,7 @@ pub fn toContainAnyKeys(
|
||||
}
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return thisValue;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
|
||||
@@ -42,7 +42,7 @@ pub fn toContainAnyValues(
|
||||
}
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return thisValue;
|
||||
if (pass) return this.returnMatcherValue(globalObject);
|
||||
|
||||
// handle failure
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalObject, .quote_strings = true };
|
||||
|
||||
@@ -82,7 +82,7 @@ pub fn toContainEqual(
|
||||
}
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return thisValue;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
|
||||
@@ -28,7 +28,7 @@ pub fn toContainKey(
|
||||
var pass = try value.hasOwnPropertyValue(globalThis, expected);
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return thisValue;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ pub fn toContainKeys(
|
||||
};
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return thisValue;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
|
||||
@@ -33,7 +33,7 @@ pub fn toContainValue(
|
||||
}
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return thisValue;
|
||||
if (pass) return this.returnMatcherValue(globalObject);
|
||||
|
||||
// handle failure
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalObject, .quote_strings = true };
|
||||
|
||||
@@ -42,7 +42,7 @@ pub fn toContainValues(
|
||||
}
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return thisValue;
|
||||
if (pass) return this.returnMatcherValue(globalObject);
|
||||
|
||||
// handle failure
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalObject, .quote_strings = true };
|
||||
|
||||
@@ -32,7 +32,7 @@ pub fn toEndWith(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFra
|
||||
const not = this.flags.not;
|
||||
if (not) pass = !pass;
|
||||
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
defer formatter.deinit();
|
||||
|
||||
@@ -18,7 +18,7 @@ pub fn toEqual(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame
|
||||
var pass = try value.jestDeepEquals(expected, globalThis);
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
const diff_formatter = DiffFormatter{
|
||||
|
||||
@@ -60,7 +60,7 @@ pub fn toEqualIgnoringWhitespace(this: *Expect, globalThis: *JSGlobalObject, cal
|
||||
}
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
|
||||
@@ -23,7 +23,7 @@ pub fn toHaveBeenCalled(this: *Expect, globalThis: *JSGlobalObject, callframe: *
|
||||
|
||||
const not = this.flags.not;
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
if (not) {
|
||||
|
||||
@@ -19,7 +19,7 @@ pub fn toHaveBeenCalledOnce(this: *Expect, globalThis: *JSGlobalObject, callfram
|
||||
|
||||
const not = this.flags.not;
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
if (not) {
|
||||
|
||||
@@ -26,7 +26,7 @@ pub fn toHaveBeenCalledTimes(this: *Expect, globalThis: *JSGlobalObject, callfra
|
||||
|
||||
const not = this.flags.not;
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
if (not) {
|
||||
|
||||
@@ -47,7 +47,7 @@ pub fn toHaveBeenCalledWith(this: *Expect, globalThis: *JSGlobalObject, callfram
|
||||
}
|
||||
|
||||
if (pass != this.flags.not) {
|
||||
return .js_undefined;
|
||||
return this.returnMatcherValue(globalThis);
|
||||
}
|
||||
|
||||
// handle failure
|
||||
|
||||
@@ -43,7 +43,7 @@ pub fn toHaveBeenLastCalledWith(this: *Expect, globalThis: *JSGlobalObject, call
|
||||
}
|
||||
|
||||
if (pass != this.flags.not) {
|
||||
return .js_undefined;
|
||||
return this.returnMatcherValue(globalThis);
|
||||
}
|
||||
|
||||
// handle failure
|
||||
|
||||
@@ -51,7 +51,7 @@ pub fn toHaveBeenNthCalledWith(this: *Expect, globalThis: *JSGlobalObject, callf
|
||||
}
|
||||
|
||||
if (pass != this.flags.not) {
|
||||
return .js_undefined;
|
||||
return this.returnMatcherValue(globalThis);
|
||||
}
|
||||
|
||||
// handle failure
|
||||
|
||||
@@ -46,7 +46,7 @@ pub fn toHaveLastReturnedWith(this: *Expect, globalThis: *JSGlobalObject, callfr
|
||||
}
|
||||
|
||||
if (pass != this.flags.not) {
|
||||
return .js_undefined;
|
||||
return this.returnMatcherValue(globalThis);
|
||||
}
|
||||
|
||||
// Handle failure
|
||||
|
||||
@@ -50,7 +50,7 @@ pub fn toHaveLength(
|
||||
}
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
if (not) {
|
||||
|
||||
@@ -55,7 +55,7 @@ pub fn toHaveNthReturnedWith(this: *Expect, globalThis: *JSGlobalObject, callfra
|
||||
}
|
||||
|
||||
if (pass != this.flags.not) {
|
||||
return .js_undefined;
|
||||
return this.returnMatcherValue(globalThis);
|
||||
}
|
||||
|
||||
// Handle failure
|
||||
|
||||
@@ -39,7 +39,7 @@ pub fn toHaveProperty(this: *Expect, globalThis: *JSGlobalObject, callFrame: *Ca
|
||||
}
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
|
||||
@@ -43,7 +43,7 @@ inline fn toHaveReturnedTimesFn(this: *Expect, globalThis: *JSGlobalObject, call
|
||||
|
||||
const not = this.flags.not;
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
switch (not) {
|
||||
inline else => |is_not| {
|
||||
|
||||
@@ -52,7 +52,7 @@ pub fn toHaveReturnedWith(this: *Expect, globalThis: *JSGlobalObject, callframe:
|
||||
}
|
||||
|
||||
if (pass != this.flags.not) {
|
||||
return .js_undefined;
|
||||
return this.returnMatcherValue(globalThis);
|
||||
}
|
||||
|
||||
// Handle failure
|
||||
|
||||
@@ -32,7 +32,7 @@ pub fn toInclude(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFra
|
||||
const not = this.flags.not;
|
||||
if (not) pass = !pass;
|
||||
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
defer formatter.deinit();
|
||||
|
||||
@@ -57,7 +57,7 @@ pub fn toIncludeRepeated(this: *Expect, globalThis: *JSGlobalObject, callFrame:
|
||||
pass = actual_count == countAsNum;
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
defer formatter.deinit();
|
||||
|
||||
@@ -39,7 +39,7 @@ pub fn toMatch(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame
|
||||
};
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
const expected_fmt = expected_value.toFmt(&formatter);
|
||||
|
||||
@@ -37,7 +37,7 @@ pub fn toMatchObject(this: *Expect, globalThis: *JSGlobalObject, callFrame: *Cal
|
||||
var pass = try received_object.jestDeepMatch(property_matchers, globalThis, true);
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
const diff_formatter = DiffFormatter{
|
||||
|
||||
@@ -32,7 +32,7 @@ pub fn toSatisfy(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFra
|
||||
const not = this.flags.not;
|
||||
const pass = (result.isBoolean() and result.toBoolean()) != not;
|
||||
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
defer formatter.deinit();
|
||||
|
||||
@@ -32,7 +32,7 @@ pub fn toStartWith(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallF
|
||||
const not = this.flags.not;
|
||||
if (not) pass = !pass;
|
||||
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
defer formatter.deinit();
|
||||
|
||||
@@ -18,7 +18,7 @@ pub fn toStrictEqual(this: *Expect, globalThis: *JSGlobalObject, callFrame: *Cal
|
||||
var pass = try value.jestStrictDeepEquals(expected, globalThis);
|
||||
|
||||
if (not) pass = !pass;
|
||||
if (pass) return .js_undefined;
|
||||
if (pass) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// handle failure
|
||||
const diff_formatter = DiffFormatter{ .received = value, .expected = expected, .globalThis = globalThis, .not = not };
|
||||
|
||||
@@ -39,7 +39,7 @@ pub fn toThrow(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame
|
||||
if (not) {
|
||||
const signature = comptime getSignature("toThrow", "<green>expected<r>", true);
|
||||
|
||||
if (!did_throw) return .js_undefined;
|
||||
if (!did_throw) return this.returnMatcherValue(globalThis);
|
||||
|
||||
const result: JSValue = result_.?;
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
@@ -76,7 +76,7 @@ pub fn toThrow(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame
|
||||
defer expected_slice.deinit();
|
||||
const received_slice = try received_message.toSliceOrNull(globalThis);
|
||||
defer received_slice.deinit();
|
||||
if (!strings.contains(received_slice.slice(), expected_slice.slice())) return .js_undefined;
|
||||
if (!strings.contains(received_slice.slice(), expected_slice.slice())) return this.returnMatcherValue(globalThis);
|
||||
}
|
||||
|
||||
return this.throw(globalThis, signature, "\n\nExpected substring: not <green>{any}<r>\nReceived message: <red>{any}<r>\n", .{
|
||||
@@ -95,7 +95,7 @@ pub fn toThrow(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame
|
||||
// TODO: REMOVE THIS GETTER! Expose a binding to call .test on the RegExp object directly.
|
||||
if (try expected_value.get(globalThis, "test")) |test_fn| {
|
||||
const matches = test_fn.call(globalThis, expected_value, &.{received_message}) catch |err| globalThis.takeException(err);
|
||||
if (!matches.toBoolean()) return .js_undefined;
|
||||
if (!matches.toBoolean()) return this.returnMatcherValue(globalThis);
|
||||
}
|
||||
|
||||
return this.throw(globalThis, signature, "\n\nExpected pattern: not <green>{any}<r>\nReceived message: <red>{any}<r>\n", .{
|
||||
@@ -112,12 +112,12 @@ pub fn toThrow(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame
|
||||
if (globalThis.hasException()) return .zero;
|
||||
|
||||
// no partial match for this case
|
||||
if (!try expected_message.isSameValue(received_message, globalThis)) return .js_undefined;
|
||||
if (!try expected_message.isSameValue(received_message, globalThis)) return this.returnMatcherValue(globalThis);
|
||||
|
||||
return this.throw(globalThis, signature, "\n\nExpected message: not <green>{any}<r>\n", .{expected_message.toFmt(&formatter)});
|
||||
}
|
||||
|
||||
if (!result.isInstanceOf(globalThis, expected_value)) return .js_undefined;
|
||||
if (!result.isInstanceOf(globalThis, expected_value)) return this.returnMatcherValue(globalThis);
|
||||
|
||||
var expected_class = ZigString.Empty;
|
||||
try expected_value.getClassName(globalThis, &expected_class);
|
||||
@@ -126,7 +126,7 @@ pub fn toThrow(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame
|
||||
}
|
||||
|
||||
if (did_throw) {
|
||||
if (expected_value == .zero or expected_value.isUndefined()) return .js_undefined;
|
||||
if (expected_value == .zero or expected_value.isUndefined()) return this.returnMatcherValue(globalThis);
|
||||
|
||||
const result: JSValue = if (result_.?.toError()) |r|
|
||||
r
|
||||
@@ -146,7 +146,7 @@ pub fn toThrow(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame
|
||||
defer expected_slice.deinit();
|
||||
const received_slice = try received_message.toSlice(globalThis, globalThis.allocator());
|
||||
defer received_slice.deinit();
|
||||
if (strings.contains(received_slice.slice(), expected_slice.slice())) return .js_undefined;
|
||||
if (strings.contains(received_slice.slice(), expected_slice.slice())) return this.returnMatcherValue(globalThis);
|
||||
}
|
||||
|
||||
// error: message from received error does not match expected string
|
||||
@@ -171,7 +171,7 @@ pub fn toThrow(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame
|
||||
// TODO: REMOVE THIS GETTER! Expose a binding to call .test on the RegExp object directly.
|
||||
if (try expected_value.get(globalThis, "test")) |test_fn| {
|
||||
const matches = test_fn.call(globalThis, expected_value, &.{received_message}) catch |err| globalThis.takeException(err);
|
||||
if (matches.toBoolean()) return .js_undefined;
|
||||
if (matches.toBoolean()) return this.returnMatcherValue(globalThis);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,7 +202,7 @@ pub fn toThrow(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame
|
||||
}
|
||||
|
||||
if (is_equal) {
|
||||
return .js_undefined;
|
||||
return this.returnMatcherValue(globalThis);
|
||||
}
|
||||
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
@@ -219,7 +219,7 @@ pub fn toThrow(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame
|
||||
const signature = comptime getSignature("toThrow", "<green>expected<r>", false);
|
||||
|
||||
if (_received_message) |received_message| {
|
||||
if (try received_message.isSameValue(expected_message, globalThis)) return .js_undefined;
|
||||
if (try received_message.isSameValue(expected_message, globalThis)) return this.returnMatcherValue(globalThis);
|
||||
}
|
||||
|
||||
// error: message from received error does not match expected error message.
|
||||
@@ -237,7 +237,7 @@ pub fn toThrow(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame
|
||||
return this.throw(globalThis, signature, "\n\nExpected message: <green>{any}<r>\nReceived value: <red>{any}<r>\n", .{ expected_fmt, received_fmt });
|
||||
}
|
||||
|
||||
if (result.isInstanceOf(globalThis, expected_value)) return .js_undefined;
|
||||
if (result.isInstanceOf(globalThis, expected_value)) return this.returnMatcherValue(globalThis);
|
||||
|
||||
// error: received error not instance of received error constructor
|
||||
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
|
||||
|
||||
44
test/regression/issue/23420.test.ts
Normal file
44
test/regression/issue/23420.test.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { expect, test } from "bun:test";
|
||||
|
||||
test("resolves matcher returns a Promise", () => {
|
||||
const promise = Promise.resolve(42);
|
||||
const matcherResult = expect(promise).resolves.toBe(42);
|
||||
expect(matcherResult).toBeInstanceOf(Promise);
|
||||
return matcherResult;
|
||||
});
|
||||
|
||||
test("rejects matcher returns a Promise", () => {
|
||||
const promise = Promise.reject(new Error("test error"));
|
||||
const matcherResult = expect(promise).rejects.toThrow("test error");
|
||||
expect(matcherResult).toBeInstanceOf(Promise);
|
||||
return matcherResult;
|
||||
});
|
||||
|
||||
test("resolves.not matcher returns a Promise", () => {
|
||||
const promise = Promise.resolve(42);
|
||||
const matcherResult = expect(promise).resolves.not.toBe(100);
|
||||
expect(matcherResult).toBeInstanceOf(Promise);
|
||||
return matcherResult;
|
||||
});
|
||||
|
||||
test("rejects.not matcher returns a Promise", () => {
|
||||
const promise = Promise.reject(42);
|
||||
const matcherResult = expect(promise).rejects.not.toThrow("wrong error");
|
||||
expect(matcherResult).toBeInstanceOf(Promise);
|
||||
return matcherResult;
|
||||
});
|
||||
|
||||
test("multiple resolves matchers can be chained with await", async () => {
|
||||
const promise1 = Promise.resolve(1);
|
||||
const promise2 = Promise.resolve(2);
|
||||
|
||||
await expect(promise1).resolves.toBe(1);
|
||||
await expect(promise2).resolves.toBe(2);
|
||||
});
|
||||
|
||||
test("resolves.toEqual returns a Promise", async () => {
|
||||
const promise = Promise.resolve({ foo: "bar" });
|
||||
const matcherResult = expect(promise).resolves.toEqual({ foo: "bar" });
|
||||
expect(matcherResult).toBeInstanceOf(Promise);
|
||||
await matcherResult;
|
||||
});
|
||||
Reference in New Issue
Block a user