Repository: denoland/std (TypeScript)

Issue:
expect.arrayContaining + expect.objectContaining broken
A common use case in testing is making sure an array contains an object with a given shape. [This blog post](https://medium.com/@andrei.pfeiffer/jest-matching-objects-in-array-50fe2f4d6b98) discusses it. The code from the blog post works with Jet but fails with `@std/expect`. Example (with additional test) below.

**Steps to Reproduce**

```ts
import { test } from '@std/testing/bdd';
import { expect } from '@std/expect';

const a = [
  { foo: 'bar' },
  { foo: 'baz' },
];

test('matchObject on array', () => {
  expect(a).toEqual(expect.arrayContaining([
    expect.objectContaining({ foo: 'bar' }),
  ]));
});

const state = [
  { type: "START", data: "foo" },
  { type: "START", data: "baz" },
  { type: "END", data: "foo" },
];

test("test from blog post", () => {
  expect(state).toEqual(
    // 1
    expect.arrayContaining([
      // 2
      expect.objectContaining({
        // 3
        type: "END", // 4
      }),
    ])
  );
});

```

**Expected behavior**

[CodeSanbox](https://codesandbox.io/p/sandbox/deno-std-expect-arraycontaining-objectcontaining-broken-vds8wf?workspaceId=ws_Ga64P2NM3YRhX6z7UXGAW1)

**Environment**

- deno version: 2.1.3
- @std/expect version: 1.0.9



Discussion:
Thank you for your feedback, I'll check this case later.



Patch:
diff --git a/expect/_asymmetric_matchers.ts b/expect/_asymmetric_matchers.ts
index 7586f0b6f23d..1c6783870d0c 100644
--- a/expect/_asymmetric_matchers.ts
+++ b/expect/_asymmetric_matchers.ts
@@ -1,6 +1,7 @@
 // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
 // deno-lint-ignore-file no-explicit-any
 
+import { getCustomEqualityTesters } from "./_custom_equality_tester.ts";
 import { equal } from "./_equal.ts";
 
 export abstract class AsymmetricMatcher<T> {
@@ -76,7 +77,11 @@ export class ArrayContaining extends AsymmetricMatcher<any[]> {
 
   equals(other: any[]): boolean {
     const res = Array.isArray(other) &&
-      this.value.every((e) => other.includes(e));
+      this.value.every((e) =>
+        other.some((another) =>
+          equal(e, another, { customTesters: getCustomEqualityTesters() })
+        )
+      );
     return this.inverse ? !res : res;
   }
 }


Test patch:
diff --git a/expect/_array_containing_test.ts b/expect/_array_containing_test.ts
index 429184b15dd4..c2e1a25612e5 100644
--- a/expect/_array_containing_test.ts
+++ b/expect/_array_containing_test.ts
@@ -28,3 +28,30 @@ Deno.test("expect.arrayContaining() with array of mixed types", () => {
   expect([1, 2, 3, "hello", "bye"]).toEqual(expect.not.arrayContaining(arr));
   expect([4, "bye"]).not.toEqual(expect.arrayContaining(arr));
 });
+
+Deno.test("matchObject on array", () => {
+  const a = [
+    { foo: "bar" },
+    { foo: "baz" },
+  ];
+
+  expect(a).toEqual(expect.arrayContaining([
+    expect.objectContaining({ foo: "bar" }),
+  ]));
+});
+
+Deno.test("test from blog post", () => {
+  const state = [
+    { type: "START", data: "foo" },
+    { type: "START", data: "baz" },
+    { type: "END", data: "foo" },
+  ];
+
+  expect(state).toEqual(
+    expect.arrayContaining([
+      expect.objectContaining({
+        type: "END",
+      }),
+    ]),
+  );
+});