Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions expect/_build_message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,19 @@ import { diffStr } from "@std/internal/diff-str";
import { format } from "@std/internal/format";
import type { EqualOptions } from "./_types.ts";

type EqualErrorMessageOptions = Pick<
EqualOptions,
"formatter" | "msg"
>;
type EqualErrorMessageOptions =
& Pick<
EqualOptions,
"formatter" | "msg"
>
& {
/**
* Overrides the default "Values are not equal." headline. Set by matchers
* (such as toMatchObject) that don't actually test for equality and would
* otherwise mislead the reader.
*/
summary?: string;
};

function isString(value: unknown): value is string {
return typeof value === "string";
Expand All @@ -20,12 +29,13 @@ export function buildEqualErrorMessage<T>(
expected: T,
options: EqualErrorMessageOptions = {},
): string {
const { formatter = format, msg } = options;
const { formatter = format, msg, summary = "Values are not equal." } =
options;
const msgPrefix = msg ? `${msg}: ` : "";
const actualString = formatter(actual);
const expectedString = formatter(expected);

let message = `${msgPrefix}Values are not equal.`;
let message = `${msgPrefix}${summary}`;

const stringDiff = isString(actual) && isString(expected);
const diffResult = stringDiff
Expand Down
7 changes: 6 additions & 1 deletion expect/_matchers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,12 @@ export function toMatchObject(
);
} else {
const subset = getObjectSubset(received, expected, context.customTesters);
const defaultMessage = buildEqualErrorMessage(subset, expected);
// toMatchObject is a subset check, not equality. Override the default
// "Values are not equal." headline so the failure message describes
// what actually went wrong (see #6999).
const defaultMessage = buildEqualErrorMessage(subset, expected, {
summary: "Object does not match the expected pattern.",
});
throw new AssertionError(
context.customMessage
? `${context.customMessage}: ${defaultMessage}`
Expand Down
16 changes: 16 additions & 0 deletions expect/_to_match_object_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -299,3 +299,19 @@ Deno.test("expect().toMatchObject() displays a diff", async (t) => {
assertMatch(e.message, /999/);
});
});

Deno.test(
"expect().toMatchObject() failure headline describes a subset match, not equality (#6999)",
() => {
const e = assertThrows(
() =>
expect({ position: { x: 0, y: "string" } })
.toMatchObject({ position: { x: 0, y: 0 } }),
AssertionError,
);
// The headline must not claim equality, because toMatchObject is a
// subset check. The diff body is still produced by the same helper.
assertMatch(e.message, /Object does not match the expected pattern\./);
assertNotMatch(e.message, /Values are not equal\./);
},
);
Loading