// Copyright 2018-2026 the Deno authors. MIT license.
// This module is browser compatible.
import { equal } from "./equal.ts";
import { format } from "@std/internal/format";
import { AssertionError } from "./assertion_error.ts";
/** An array-like object (`Array`, `Uint8Array`, `NodeList`, etc.) that is not a string */
export type ArrayLikeArg<T> = ArrayLike<T> & object;
function isPrimitive(value: unknown): boolean {
return value === null ||
typeof value !== "object" && typeof value !== "function";
}
/**
* Asserts that `actual` contains all values in `expected`, using deep equality
* for non-primitive values.
*
* @example Usage with primitives
* ```ts ignore
* import { assertArrayIncludes } from "@std/assert";
*
* assertArrayIncludes([1, 2, 3], [2, 3]); // Passes
* assertArrayIncludes([1, 2, 3], [4]); // Throws
* ```
*
* @example Usage with objects (deep equality)
* ```ts ignore
* import { assertArrayIncludes } from "@std/assert";
*
* assertArrayIncludes([{ a: 1 }, { b: 2 }], [{ a: 1 }]); // Passes
* ```
*
* @typeParam T The element type of the arrays.
* @param actual The array-like object to search within.
* @param expected The values that must be present in `actual`.
* @param msg Optional message to display on failure.
* @throws {AssertionError} If any value in `expected` is not found in `actual`.
*/
export function assertArrayIncludes<T>(
actual: ArrayLikeArg<T>,
expected: ArrayLikeArg<T>,
msg?: string,
): void {
const missing: unknown[] = [];
const expectedLen = expected.length;
const actualLen = actual.length;
for (let i = 0; i < expectedLen; i++) {
const item = expected[i];
let found: boolean;
if (isPrimitive(item)) {
// Fast path
found = Array.prototype.includes.call(actual, item);
} else {
found = false;
for (let j = 0; j < actualLen; j++) {
if (equal(item, actual[j])) {
found = true;
break;
}
}
}
if (!found) {
missing.push(item);
}
}
if (missing.length === 0) {
return;
}
const msgSuffix = msg ? `: ${msg}` : ".";
msg = `Expected actual: "${format(actual)}" to include: "${
format(expected)
}"${msgSuffix}\nmissing: ${format(missing)}`;
throw new AssertionError(msg);
}
|