std/expect/_to_equal_test.ts
Yoshiya Hinosawa 90025e9db4
test(expect): add test of iterableEquality (#5222)
Co-authored-by: Asher Gomez <ashersaupingomez@gmail.com>
2024-07-01 16:06:52 +09:00

306 lines
7.7 KiB
TypeScript

// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
import { bold, gray, green, red, stripAnsiCode, yellow } from "@std/fmt/colors";
import { AssertionError, assertThrows } from "@std/assert";
import { expect } from "./expect.ts";
const createHeader = (): string[] => [
"",
"",
` ${gray(bold("[Diff]"))} ${red(bold("Actual"))} / ${
green(
bold("Expected"),
)
}`,
"",
"",
];
const added: (s: string) => string = (s: string): string =>
green(bold(stripAnsiCode(s)));
const removed: (s: string) => string = (s: string): string =>
red(bold(stripAnsiCode(s)));
Deno.test({
name: "expect().toEqual() matches when values are equal",
fn() {
expect({ a: 10 }).toEqual({ a: 10 });
expect(true).toEqual(true);
expect(10).toEqual(10);
expect("abc").toEqual("abc");
expect({ a: 10, b: { c: "1" } }).toEqual({ a: 10, b: { c: "1" } });
expect(new Date("invalid")).toEqual(new Date("invalid"));
},
});
Deno.test({
name: "expect().toEqual() throws when numbers are not equal",
fn() {
assertThrows(
() => expect(1).toEqual(2),
AssertionError,
[
"Values are not equal.",
...createHeader(),
removed(`- ${yellow("1")}`),
added(`+ ${yellow("2")}`),
"",
].join("\n"),
);
},
});
Deno.test({
name: "expect().toEqual() throws when compare number with string",
fn() {
assertThrows(
() => expect(1).toEqual("1"),
AssertionError,
[
"Values are not equal.",
...createHeader(),
removed(`- ${yellow("1")}`),
added(`+ "1"`),
].join("\n"),
);
},
});
Deno.test({
name: "expect().toEqual() throws when array are not equal",
fn() {
assertThrows(
() => expect([1, "2", 3]).toEqual(["1", "2", 3]),
AssertionError,
`
[
- 1,
+ "1",
"2",
3,
]`,
);
},
});
Deno.test({
name: "expect().toEqual() throws when objects are no equal",
fn() {
assertThrows(
() => expect({ a: 1, b: "2", c: 3 }).toEqual({ a: 1, b: 2, c: [3] }),
AssertionError,
`
{
a: 1,
+ b: 2,
+ c: [
+ 3,
+ ],
- b: "2",
- c: 3,
}`,
);
},
});
Deno.test({
name: "expect().toEqual() throws when date are not equal",
fn() {
assertThrows(
() =>
expect(new Date(2019, 0, 3, 4, 20, 1, 10)).toEqual(
new Date(2019, 0, 3, 4, 20, 1, 20),
),
AssertionError,
[
"Values are not equal.",
...createHeader(),
removed(`- ${new Date(2019, 0, 3, 4, 20, 1, 10).toISOString()}`),
added(`+ ${new Date(2019, 0, 3, 4, 20, 1, 20).toISOString()}`),
"",
].join("\n"),
);
assertThrows(
() =>
expect(new Date("invalid")).toEqual(new Date(2019, 0, 3, 4, 20, 1, 20)),
AssertionError,
[
"Values are not equal.",
...createHeader(),
removed(`- ${new Date("invalid")}`),
added(`+ ${new Date(2019, 0, 3, 4, 20, 1, 20).toISOString()}`),
"",
].join("\n"),
);
},
});
Deno.test({
name: "expect().toEqual() throws with custom message",
fn() {
assertThrows(
() => expect(1, "CUSTOM MESSAGE").toEqual(2),
AssertionError,
[
"Values are not equal: CUSTOM MESSAGE",
...createHeader(),
removed(`- ${yellow("1")}`),
added(`+ ${yellow("2")}`),
"",
].join("\n"),
);
},
});
Deno.test(
"expect().toEqual() compares objects structurally if one object's constructor is undefined and the other is Object",
() => {
const a = Object.create(null);
a.prop = "test";
const b = {
prop: "test",
};
expect(a).toEqual(b);
expect(b).toEqual(a);
},
);
Deno.test("expect().toEqual() diff for differently ordered objects", () => {
assertThrows(
() => {
expect({
aaaaaaaaaaaaaaaaaaaaaaaa: 0,
bbbbbbbbbbbbbbbbbbbbbbbb: 0,
ccccccccccccccccccccccc: 0,
}).toEqual(
{
ccccccccccccccccccccccc: 1,
aaaaaaaaaaaaaaaaaaaaaaaa: 0,
bbbbbbbbbbbbbbbbbbbbbbbb: 0,
},
);
},
AssertionError,
`
{
aaaaaaaaaaaaaaaaaaaaaaaa: 0,
bbbbbbbbbbbbbbbbbbbbbbbb: 0,
- ccccccccccccccccccccccc: 0,
+ ccccccccccccccccccccccc: 1,
}`,
);
});
Deno.test("expect().toEqual() same Set with object keys", () => {
const data = [
{
id: "_1p7ZED73OF98VbT1SzSkjn",
type: { id: "_ETGENUS" },
name: "Thuja",
friendlyId: "g-thuja",
},
{
id: "_567qzghxZmeQ9pw3q09bd3",
type: { id: "_ETGENUS" },
name: "Pinus",
friendlyId: "g-pinus",
},
];
expect(data).toEqual(data);
expect(new Set(data)).toEqual(new Set(data));
});
Deno.test("expect().toEqual() does not throw when a key with undfined value exists in only one of values", () => {
// bar: undefined is ignored in comparison
expect({ foo: 1, bar: undefined }).toEqual({ foo: 1 });
expect({ foo: 1, bar: undefined }).not.toEqual({ foo: undefined });
});
// https://github.com/denoland/deno_std/issues/4244
Deno.test("expect().toEqual() align to jest test cases", () => {
function create() {
class Person {
constructor(readonly name = "deno") {}
}
return new Person();
}
expect([create()]).toEqual([create()]);
expect(
new (class A {
#hello = "world";
})(),
).toEqual(
new (class B {
#hello = "world";
})(),
);
expect(
new WeakRef({ hello: "world" }),
).toEqual(
new (class<T extends object> extends WeakRef<T> {})({ hello: "world" }),
);
expect({ a: undefined, b: undefined }).toEqual({
a: undefined,
c: undefined,
});
expect({ a: undefined, b: undefined }).toEqual({ a: undefined });
class A {}
class B {}
expect(new A()).toEqual(new B());
assertThrows(() => {
expect(new A()).not.toEqual(new B());
}, AssertionError);
});
Deno.test("expect().toEqual() matches when Error Objects are equal", () => {
function getError() {
return new Error("missing param: name");
}
const expectErrObjectWithName = new Error("missing param: name");
expect(getError()).toEqual(expectErrObjectWithName);
const expectErrObjectWithEmail = new Error("missing param: email");
expect(getError()).not.toEqual(expectErrObjectWithEmail);
});
Deno.test("expect().toEqual() handles Sets", () => {
expect(new Set([1, 2, 3])).toEqual(new Set([1, 2, 3]));
expect(new Set([1, 2, 3])).not.toEqual(new Set([1, 2]));
expect(new Set([1, 2, 3])).not.toEqual(new Set([1, 2, 4]));
expect(new Set([1, 2, 3, 4])).not.toEqual(new Map([[1, 2], [3, 4]]));
expect(new Set([1, 2, new Set([0, 1])])).toEqual(
new Set([1, 2, new Set([0, 1])]),
);
// It handles circular reference structures
const a = new Set<unknown>([1, 2]);
a.add(a);
const b = new Set<unknown>([1, 2]);
b.add(b);
expect(a).toEqual(b);
});
Deno.test("expect().toEqual() handles Maps", () => {
expect(new Map([[1, 2], [3, 4]])).toEqual(new Map([[1, 2], [3, 4]]));
expect(new Map([[1, 2], [3, 4]])).not.toEqual(new Map([[1, 2], [3, 5]]));
});
// TODO(kt3k): Iterator global exists in the runtime but not in the TypeScript
// Remove the below lines when `Iterator` global is available in TypeScript
// deno-lint-ignore no-explicit-any
const Iterator = (globalThis as any).Iterator;
Deno.test("expect().toEqual() handles iterators", () => {
expect(Iterator.from([1, 2, 3])).toEqual(Iterator.from([1, 2, 3]));
expect(Iterator.from([1, 2, 3])).not.toEqual(Iterator.from([1, 2, 4]));
expect(Iterator.from([1, 2, 3])).not.toEqual(Iterator.from([1, 2, 3, 4]));
const iter0 = Iterator.from([1, 2, 3]);
const iter1 = Iterator.from([1, 2, 3]);
iter1.foo = 1;
expect(iter0).not.toEqual(iter1);
});