// eslint-disable-next-line no-restricted-imports -- We need to import `expect` from "vitest" so that we can extend it import { expect } from "vitest"; interface CustomMatchers { toContainMatchingObject: (expected: object) => unknown; } declare module "vitest" { /* eslint-disable @typescript-eslint/no-empty-object-type -- Required for vitest module augmentation with empty interfaces */ interface Assertion extends CustomMatchers {} interface AsymmetricMatchersContaining extends CustomMatchers {} /* eslint-enable @typescript-eslint/no-empty-object-type */ } expect.extend({ // Extend vitest's expect object so that it has our new matcher toContainMatchingObject(received: object[], expected: object) { // const matcher = createMatcher(expected); const pass = received.some((item) => isSubset(expected, item)); return { message: () => `Entry was${this.isNot ? "" : " not"} found in array.`, pass, actual: received, expected: expected, }; function isSubset(subset: object, superset: object) { // Leverage the existing toMatchObject() behaviour to do the deep matching try { expect(superset).toMatchObject(subset); return true; } catch { return false; } } }, });