Compare commits

...

1 Commits

Author SHA1 Message Date
Claude Bot
132c73363b fix(test): use "Received value" instead of "Expected value" in error messages
When `expect()` receives a non-function for `.toThrow()` or a non-mock for
mock matchers, the error message said "Expected value must be..." which is
ambiguous — in testing terminology, "expected" refers to the matcher argument
while "received" refers to the value passed to `expect()`. This aligns with
Jest's behavior.

Closes #26996

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-13 08:27:34 +00:00
10 changed files with 52 additions and 11 deletions

View File

@@ -554,7 +554,7 @@ pub const Expect = struct {
return .{ value, return_value_from_function };
}
return globalThis.throw("Expected value must be a function", .{});
return globalThis.throw("Received value must be a function", .{});
}
var return_value: JSValue = .zero;
@@ -2002,7 +2002,7 @@ pub const mock = struct {
if (!returns.jsType().isArray()) {
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
defer formatter.deinit();
return globalThis.throw("Expected value must be a mock function: {f}", .{value.toFmt(&formatter)});
return globalThis.throw("Received value must be a mock function: {f}", .{value.toFmt(&formatter)});
}
return try returns.arrayIterator(globalThis);
@@ -2015,7 +2015,7 @@ pub const mock = struct {
}
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
defer formatter.deinit();
return globalThis.throw("Expected value must be a mock function with returns: {f}", .{value.toFmt(&formatter)});
return globalThis.throw("Received value must be a mock function with returns: {f}", .{value.toFmt(&formatter)});
}
pub fn jestMockReturnObject_value(globalThis: *JSGlobalObject, value: bun.jsc.JSValue) bun.JSError!JSValue {
return (try value.get(globalThis, "value")) orelse .js_undefined;

View File

@@ -22,7 +22,7 @@ pub fn toContainKey(
const not = this.flags.not;
if (!value.isObject()) {
return globalThis.throwInvalidArguments("Expected value must be an object\nReceived: {f}", .{value.toFmt(&formatter)});
return globalThis.throwInvalidArguments("Received value must be an object\nReceived: {f}", .{value.toFmt(&formatter)});
}
var pass = try value.hasOwnPropertyValue(globalThis, expected);

View File

@@ -15,7 +15,7 @@ pub fn toHaveBeenCalled(this: *Expect, globalThis: *JSGlobalObject, callframe: *
if (!calls.jsType().isArray()) {
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
defer formatter.deinit();
return globalThis.throw("Expected value must be a mock function: {f}", .{value.toFmt(&formatter)});
return globalThis.throw("Received value must be a mock function: {f}", .{value.toFmt(&formatter)});
}
const calls_length = try calls.getLength(globalThis);

View File

@@ -11,7 +11,7 @@ pub fn toHaveBeenCalledOnce(this: *Expect, globalThis: *JSGlobalObject, callfram
if (!calls.jsType().isArray()) {
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
defer formatter.deinit();
return globalThis.throw("Expected value must be a mock function: {f}", .{value.toFmt(&formatter)});
return globalThis.throw("Received value must be a mock function: {f}", .{value.toFmt(&formatter)});
}
const calls_length = try calls.getLength(globalThis);

View File

@@ -13,7 +13,7 @@ pub fn toHaveBeenCalledTimes(this: *Expect, globalThis: *JSGlobalObject, callfra
if (!calls.jsType().isArray()) {
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
defer formatter.deinit();
return globalThis.throw("Expected value must be a mock function: {f}", .{value.toFmt(&formatter)});
return globalThis.throw("Received value must be a mock function: {f}", .{value.toFmt(&formatter)});
}
if (arguments.len < 1 or !arguments[0].isUInt32AsAnyInt()) {

View File

@@ -26,7 +26,7 @@ pub fn toHaveBeenLastCalledWith(this: *Expect, globalThis: *JSGlobalObject, call
if (!lastCallValue.jsType().isArray()) {
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
defer formatter.deinit();
return globalThis.throw("Expected value must be a mock function with calls: {f}", .{value.toFmt(&formatter)});
return globalThis.throw("Received value must be a mock function with calls: {f}", .{value.toFmt(&formatter)});
}
if (try lastCallValue.getLength(globalThis) != arguments.len) {

View File

@@ -13,7 +13,7 @@ pub fn toHaveLastReturnedWith(this: *Expect, globalThis: *JSGlobalObject, callfr
if (!returns.jsType().isArray()) {
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
defer formatter.deinit();
return globalThis.throw("Expected value must be a mock function: {f}", .{value.toFmt(&formatter)});
return globalThis.throw("Received value must be a mock function: {f}", .{value.toFmt(&formatter)});
}
const calls_count = @as(u32, @intCast(try returns.getLength(globalThis)));

View File

@@ -21,7 +21,7 @@ pub fn toHaveNthReturnedWith(this: *Expect, globalThis: *JSGlobalObject, callfra
if (!returns.jsType().isArray()) {
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
defer formatter.deinit();
return globalThis.throw("Expected value must be a mock function: {f}", .{value.toFmt(&formatter)});
return globalThis.throw("Received value must be a mock function: {f}", .{value.toFmt(&formatter)});
}
const calls_count = @as(u32, @intCast(try returns.getLength(globalThis)));

View File

@@ -13,7 +13,7 @@ pub fn toHaveReturnedWith(this: *Expect, globalThis: *JSGlobalObject, callframe:
if (!returns.jsType().isArray()) {
var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true };
defer formatter.deinit();
return globalThis.throw("Expected value must be a mock function: {f}", .{value.toFmt(&formatter)});
return globalThis.throw("Received value must be a mock function: {f}", .{value.toFmt(&formatter)});
}
const calls_count = @as(u32, @intCast(try returns.getLength(globalThis)));

View File

@@ -0,0 +1,41 @@
import { expect, test } from "bun:test";
// https://github.com/oven-sh/bun/issues/26996
// Error messages should say "Received value" (the value passed to expect()),
// not "Expected value" (which refers to the matcher argument in testing terminology).
test("toThrow on non-function says 'Received value'", () => {
try {
expect(123).toThrow(Error);
throw new Error("should not reach here");
} catch (e: any) {
expect(e.message).toBe("Received value must be a function");
}
});
test("toHaveBeenCalled on non-mock says 'Received value'", () => {
try {
expect(123).toHaveBeenCalled();
throw new Error("should not reach here");
} catch (e: any) {
expect(e.message).toContain("Received value must be a mock function");
}
});
test("toHaveBeenCalledTimes on non-mock says 'Received value'", () => {
try {
expect(123).toHaveBeenCalledTimes(1);
throw new Error("should not reach here");
} catch (e: any) {
expect(e.message).toContain("Received value must be a mock function");
}
});
test("toContainKey on non-object says 'Received value'", () => {
try {
expect(123).toContainKey("foo");
throw new Error("should not reach here");
} catch (e: any) {
expect(e.message).toContain("Received value must be an object");
}
});