mirror of
https://github.com/denoland/std.git
synced 2024-11-21 12:40:03 +00:00
fix(expect): support expect.objectContaining
(#6065)
Co-authored-by: Yoshiya Hinosawa <stibium121@gmail.com>
This commit is contained in:
parent
a541fb468c
commit
ae7048f9ca
@ -1,6 +1,8 @@
|
|||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
// deno-lint-ignore-file no-explicit-any
|
// deno-lint-ignore-file no-explicit-any
|
||||||
|
|
||||||
|
import { equal } from "./_equal.ts";
|
||||||
|
|
||||||
export abstract class AsymmetricMatcher<T> {
|
export abstract class AsymmetricMatcher<T> {
|
||||||
constructor(
|
constructor(
|
||||||
protected value: T,
|
protected value: T,
|
||||||
@ -145,3 +147,31 @@ export class StringMatching extends AsymmetricMatcher<RegExp> {
|
|||||||
export function stringMatching(pattern: string | RegExp): StringMatching {
|
export function stringMatching(pattern: string | RegExp): StringMatching {
|
||||||
return new StringMatching(pattern);
|
return new StringMatching(pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class ObjectContaining
|
||||||
|
extends AsymmetricMatcher<Record<string, unknown>> {
|
||||||
|
constructor(obj: Record<string, unknown>) {
|
||||||
|
super(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
equals(other: Record<string, unknown>): boolean {
|
||||||
|
const keys = Object.keys(this.value);
|
||||||
|
|
||||||
|
for (const key of keys) {
|
||||||
|
if (
|
||||||
|
!Object.hasOwn(other, key) ||
|
||||||
|
!equal(this.value[key], other[key])
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function objectContaining(
|
||||||
|
obj: Record<string, unknown>,
|
||||||
|
): ObjectContaining {
|
||||||
|
return new ObjectContaining(obj);
|
||||||
|
}
|
||||||
|
50
expect/_object_containing_test.ts
Normal file
50
expect/_object_containing_test.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
import { Buffer } from "node:buffer";
|
||||||
|
import { Buffer as DenoBuffer } from "@std/io/buffer";
|
||||||
|
import { expect } from "./expect.ts";
|
||||||
|
|
||||||
|
Deno.test("expect.objectContaining()", () => {
|
||||||
|
expect({ bar: "baz" }).toEqual(expect.objectContaining({ bar: "baz" }));
|
||||||
|
expect({ foo: undefined }).toEqual(
|
||||||
|
expect.objectContaining({ foo: undefined }),
|
||||||
|
);
|
||||||
|
expect({ bar: "baz" }).not.toEqual(expect.objectContaining({ foo: "bar" }));
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test("expect.objectContaining() with nested objects", () => {
|
||||||
|
expect({ foo: { bar: "baz" } }).toEqual(
|
||||||
|
expect.objectContaining({ foo: { bar: "baz" } }),
|
||||||
|
);
|
||||||
|
expect({ foo: { bar: "baz" } }).not.toEqual(
|
||||||
|
expect.objectContaining({ foo: { bar: "bar" } }),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test("expect.objectContaining() with symbols", () => {
|
||||||
|
const foo = Symbol("foo");
|
||||||
|
expect({ [foo]: { bar: "baz" } }).toEqual(
|
||||||
|
expect.objectContaining({ [foo]: { bar: "baz" } }),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test("expect.objectContaining() with nested arrays", () => {
|
||||||
|
expect({ foo: ["bar", "baz"] }).toEqual(
|
||||||
|
expect.objectContaining({ foo: ["bar", "baz"] }),
|
||||||
|
);
|
||||||
|
expect({ foo: ["bar", "baz"] }).not.toEqual(
|
||||||
|
expect.objectContaining({ foo: ["bar", "bar"] }),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test("expect.objectContaining() with Node Buffer", () => {
|
||||||
|
expect({ foo: Buffer.from("foo") }).toEqual(
|
||||||
|
expect.objectContaining({ foo: Buffer.from("foo") }),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test("expect.objectContaining() with Deno Buffer", () => {
|
||||||
|
expect({ foo: new DenoBuffer([1, 2, 3]) }).toEqual(
|
||||||
|
expect.objectContaining({ foo: new DenoBuffer([1, 2, 3]) }),
|
||||||
|
);
|
||||||
|
});
|
@ -509,3 +509,21 @@ expect.stringMatching = asymmetricMatchers.stringMatching as (
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
expect.hasAssertions = hasAssertions as () => void;
|
expect.hasAssertions = hasAssertions as () => void;
|
||||||
|
/**
|
||||||
|
* `expect.objectContaining(object)` matches any received object that recursively matches the expected properties.
|
||||||
|
* That is, the expected object is not a subset of the received object. Therefore, it matches a received object
|
||||||
|
* which contains properties that are not in the expected object.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* import { expect } from "@std/expect";
|
||||||
|
*
|
||||||
|
* Deno.test("example", () => {
|
||||||
|
* expect({ bar: 'baz' }).toEqual(expect.objectContaining({ bar: 'bar'}));
|
||||||
|
* expect({ bar: 'baz' }).not.toEqual(expect.objectContaining({ foo: 'bar'}));
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
expect.objectContaining = asymmetricMatchers.objectContaining as (
|
||||||
|
obj: Record<string, unknown>,
|
||||||
|
) => ReturnType<typeof asymmetricMatchers.objectContaining>;
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
* - {@linkcode expect.anything}
|
* - {@linkcode expect.anything}
|
||||||
* - {@linkcode expect.any}
|
* - {@linkcode expect.any}
|
||||||
* - {@linkcode expect.arrayContaining}
|
* - {@linkcode expect.arrayContaining}
|
||||||
|
* - {@linkcode expect.objectContaining}
|
||||||
* - {@linkcode expect.closeTo}
|
* - {@linkcode expect.closeTo}
|
||||||
* - {@linkcode expect.stringContaining}
|
* - {@linkcode expect.stringContaining}
|
||||||
* - {@linkcode expect.stringMatching}
|
* - {@linkcode expect.stringMatching}
|
||||||
@ -69,7 +70,6 @@
|
|||||||
* - `toThrowErrorMatchingSnapshot`
|
* - `toThrowErrorMatchingSnapshot`
|
||||||
* - `toThrowErrorMatchingInlineSnapshot`
|
* - `toThrowErrorMatchingInlineSnapshot`
|
||||||
* - Asymmetric matchers:
|
* - Asymmetric matchers:
|
||||||
* - `expect.objectContaining`
|
|
||||||
* - `expect.not.objectContaining`
|
* - `expect.not.objectContaining`
|
||||||
* - Utilities:
|
* - Utilities:
|
||||||
* - `expect.assertions`
|
* - `expect.assertions`
|
||||||
|
Loading…
Reference in New Issue
Block a user