Something went wrong. Try again.
Monorepo for the nibling.run platform
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345// node:assert: the truthiness, equality, match, throws and deep-equality assertions// with Node's AssertionError shape. The deep comparisons (util.isDeepStrictEqual and// friends) live in ./util/comparisons, ported from Node; AssertionError's exact// messages (the diffs, truncation, "Values identical but not reference-equal") are// ./assert/assertion_error, also ported; `assert(false)` without a message still// cannot quote its own call site, which Node reads from the source file.import { inspect } from "./inspect";import { invalidArgType, invalidArgValue, invalidReturnValue } from "./errors";import { isDeepEqual, isDeepStrictEqual, isPartialStrictEqual } from "./util/comparisons";import { buildAssertionMessage } from "./assert/assertion_error";
interface AssertionOptions { message?: string; actual?: unknown; expected?: unknown; operator?: string;}
export class AssertionError extends Error { actual: unknown; expected: unknown; operator: string | undefined; generatedMessage: boolean; code = "ERR_ASSERTION";
constructor(options: AssertionOptions) { if (options === null || typeof options !== "object") throw invalidArgType("options", "of type object", options); const { text, actual, expected } = buildAssertionMessage({ actual: options.actual, expected: options.expected, operator: options.operator, message: options.message, }); super(text); this.generatedMessage = options.message === undefined; this.actual = actual; this.expected = expected; this.operator = options.operator; }
override get name(): string { return "AssertionError"; }}
type Message = string | Error | undefined;
function raise(options: AssertionOptions, generated = options.message === undefined): never { const err = new AssertionError(options); err.generatedMessage = generated; (Error as { captureStackTrace?: (target: object, ctor: unknown) => void }).captureStackTrace?.(err, raise); throw err;}
function check(pass: boolean, message: Message, options: Omit<AssertionOptions, "message">): void { if (pass) return; if (message instanceof Error) throw message; raise({ ...options, message });}
function ok(...args: unknown[]): void { if (args.length === 0) raise({ message: "No value argument passed to `assert.ok()`", actual: undefined, expected: true, operator: "==" }, true); const [value, message] = args as [unknown, Message]; if (value) return; if (message instanceof Error) throw message; raise({ message: message ?? "The expression evaluated to a falsy value", actual: value, expected: true, operator: "==" }, message === undefined);}
const looseEqual = (a: unknown, b: unknown): boolean => a == b || (Number.isNaN(a) && Number.isNaN(b));
const equal = (actual: unknown, expected: unknown, message?: Message): void => check(looseEqual(actual, expected), message, { actual, expected, operator: "==" });const notEqual = (actual: unknown, expected: unknown, message?: Message): void => check(!looseEqual(actual, expected), message, { actual, expected, operator: "!=" });const strictEqual = (actual: unknown, expected: unknown, message?: Message): void => check(Object.is(actual, expected), message, { actual, expected, operator: "strictEqual" });const notStrictEqual = (actual: unknown, expected: unknown, message?: Message): void => check(!Object.is(actual, expected), message, { actual, expected, operator: "notStrictEqual" });
function matching(want: boolean, operator: string, describe: string) { return (string: unknown, regexp: RegExp, message?: Message): void => { if (!(regexp instanceof RegExp)) throw invalidArgType("regexp", "an instance of RegExp", regexp); if (typeof string === "string" && regexp.test(string) === want) return; if (message instanceof Error) throw message; raise({ actual: string, expected: regexp, operator, message: message ?? (typeof string !== "string" ? `The "string" argument must be of type string. Received type ${typeof string} (${inspect(string)})` : `The input ${describe} the regular expression ${inspect(regexp)}. Input:\n\n${inspect(string)}\n`), }, message === undefined); };}
type Expected = RegExp | (new (...args: never[]) => unknown) | ((err: unknown) => boolean) | undefined;
function matchesExpected(err: unknown, expected: Expected): boolean { if (expected === undefined) return true; if (expected instanceof RegExp) return expected.test(String(err)); if (expected.prototype !== undefined && err instanceof expected) return true; if (Error.isPrototypeOf(expected)) return false; return (expected as (err: unknown) => boolean).call({}, err) === true;}
function throws(fn: () => unknown, expected?: Expected | RejectExpected | string, message?: string): void { if (typeof fn !== "function") throw invalidArgType("fn", "of type function", fn); if (typeof expected === "string") [message, expected] = [expected, undefined]; try { fn(); } catch (err) { if (isObjectMatcher(expected as RejectExpected)) { matchesObjectError(err, expected as Record<string, unknown>, message, "throws"); return; } if (!matchesExpected(err, expected as Expected)) throw err; return; } const name = typeof expected === "function" && expected.name ? ` (${expected.name})` : ""; raise({ actual: undefined, expected, operator: "throws", message: `Missing expected exception${name}${message ? `: ${message}` : "."}` }, false);}
function doesNotThrow(fn: () => unknown, expected?: Expected | string, message?: string): void { if (typeof fn !== "function") throw invalidArgType("fn", "of type function", fn); if (typeof expected === "string") [message, expected] = [expected, undefined]; try { fn(); } catch (err) { if (!matchesExpected(err, expected)) throw err; const detail = err instanceof Error ? err.message : String(err); raise({ actual: err, expected, operator: "doesNotThrow", message: `Got unwanted exception${message ? `: ${message}` : "."}\nActual message: "${detail}"` }, false); }}
type RejectExpected = Expected | Record<string, unknown>;
/** An object (or Error instance) matcher needs property-by-property deep equality; * RegExp and function/class matchers don't. */function isObjectMatcher(expected: RejectExpected): expected is Record<string, unknown> { return typeof expected === "object" && expected !== null && !(expected instanceof RegExp);}
/** Node's `Comparison` placeholder class (lib/assert.js): an object built only from * the matcher's own keys, for a readable diff — a real class (not a plain object) so * `inspect()` labels it "Comparison {...}" exactly as Node's diff does. A key whose * matcher value is a RegExp that matches the actual string shows the actual string * instead of the pattern. */class Comparison { [key: string]: unknown; constructor(obj: Record<string, unknown>, keys: string[], actual?: Record<string, unknown>) { for (const key of keys) { if (!(key in obj)) continue; const a = actual?.[key]; this[key] = actual !== undefined && typeof a === "string" && obj[key] instanceof RegExp && (obj[key] as RegExp).test(a) ? a : obj[key]; } }}
/** Node's compareExceptionKey (lib/assert.js): one matcher key, deep-equal (strict). * A mismatch with no custom message raises `deepStrictEqual` against `Comparison` * placeholders (so the diff shows only the matcher's keys), then relabels itself as * `fnName` before escaping — exactly as Node's own AssertionError does it. */function compareExceptionKey(actual: Record<string, unknown>, expected: Record<string, unknown>, key: string, message: Message, keys: string[], fnName: string): void { if (key in actual && isDeepStrictEqual(actual[key], expected[key])) return; if (message === undefined) { const err = new AssertionError({ actual: new Comparison(actual, keys), expected: new Comparison(expected, keys, actual), operator: "deepStrictEqual" }); err.actual = actual; err.expected = expected; err.operator = fnName; throw err; } if (message instanceof Error) throw message; raise({ actual, expected, operator: fnName, message }, false);}
/** Node's object branch of expectedException (lib/assert.js): `expected` is a plain * object or an Error instance to match property-by-property (Error instances also * match `name` and `message`), used by throws()/rejects() only — doesNotThrow() and * doesNotReject() never take an object matcher. */function matchesObjectError(actual: unknown, expected: Record<string, unknown>, message: Message, fnName: string): void { if (typeof actual !== "object" || actual === null) { const err = new AssertionError({ actual, expected, message: message instanceof Error ? undefined : message, operator: "deepStrictEqual" }); err.operator = fnName; if (message instanceof Error) throw message; throw err; } const keys = Object.keys(expected); if (expected instanceof Error) keys.push("name", "message"); else if (keys.length === 0) throw invalidArgValue("error", expected, "may not be an empty object"); const actualRecord = actual as Record<string, unknown>; for (const key of keys) { const av = actualRecord[key]; if (typeof av === "string" && expected[key] instanceof RegExp && (expected[key] as RegExp).test(av)) continue; compareExceptionKey(actualRecord, expected, key, message, keys, fnName); }}
/** Node's name suffix on "Missing expected rejection": a class or named validator * function shows its name, as does an Error instance's constructor. */function expectedName(expected: RejectExpected): string { if (typeof expected === "function" && expected.name) return ` (${expected.name})`; if (expected instanceof Error && expected.constructor?.name) return ` (${expected.constructor.name})`; return "";}
/** Node's mismatch message for rejects()/doesNotReject(), one per matcher kind * `matchesExpected` recognizes (RegExp, Error-subclass, validator function). */function rejectionMismatchMessage(err: unknown, expected: Expected): string { if (expected instanceof RegExp) return `The input did not match the regular expression ${expected}. Input:\n\n'${String(err)}'\n`; if (typeof expected === "function" && expected.prototype !== undefined && Error.isPrototypeOf(expected)) { const detail = err instanceof Error ? `Received "${err.constructor?.name ?? err.name}"\n\nError message:\n\n${err.message}` : `Received "${inspect(err, { depth: -1 })}"`; return `The error is expected to be an instance of "${expected.name}". ${detail}`; } return `The validation function is expected to return "true". Received false\n\nCaught error:\n\n${String(err)}`;}
/** Runs `promiseFn` (a function or a Promise) and reports whether it rejected. * A synchronous throw from a promiseFn function propagates as-is (Node never * validates or matches it): awaiting that throw inside this async function turns it * into this call's own rejection, unexamined, exactly as Node's rejects()/ * doesNotReject() let it through. */async function settle(promiseFn: unknown): Promise<{ rejected: boolean; error?: unknown }> { if (typeof promiseFn !== "function" && !(promiseFn instanceof Promise)) { throw invalidArgType("promiseFn", "of type function or an instance of Promise", promiseFn); } const promise = typeof promiseFn === "function" ? promiseFn() : promiseFn; if (!(promise instanceof Promise)) throw invalidReturnValue("instance of Promise", "promiseFn", promise); try { await promise; return { rejected: false }; } catch (error) { return { rejected: true, error }; }}
/** `expected` is validated lazily, only once there's a rejection to match against * (a non-rejection, or a sync throw, never looks at it). `null` matches anything, * like `undefined` does. */function matchesRejection(err: unknown, expected: Expected): boolean { return expected === null || matchesExpected(err, expected);}
async function rejects(promiseFn: unknown, expected?: RejectExpected | string, message?: string): Promise<void> { if (typeof expected === "string") [message, expected] = [expected, undefined]; const { rejected, error } = await settle(promiseFn); if (!rejected) { raise({ actual: undefined, expected, operator: "rejects", message: `Missing expected rejection${expectedName(expected)}${message ? `: ${message}` : "."}`, }, false); } if (expected !== undefined && expected !== null && typeof expected !== "function" && !(expected instanceof RegExp) && typeof expected !== "object") { throw invalidArgType("error", "of type function or an instance of Error, RegExp, or Object", expected); } if (isObjectMatcher(expected)) { matchesObjectError(error, expected, message, "rejects"); return; } if (!matchesRejection(error, expected as Expected)) { raise({ actual: error, expected, operator: "rejects", message: message ?? rejectionMismatchMessage(error, expected as Expected) }, message === undefined); }}
async function doesNotReject(promiseFn: unknown, expected?: RejectExpected | string, message?: string): Promise<void> { if (typeof expected === "string") [message, expected] = [expected, undefined]; const { rejected, error } = await settle(promiseFn); if (!rejected) return; if (expected !== undefined && expected !== null && typeof expected !== "function" && !(expected instanceof RegExp)) { throw invalidArgType("expected", "of type function or an instance of RegExp", expected); } if (!matchesRejection(error, expected as Expected)) throw error; const detail = error instanceof Error ? error.message : String(error); raise({ actual: error, expected, operator: "doesNotReject", message: message ?? `Got unwanted rejection.\nActual message: "${detail}"` }, false);}
function ifError(value: unknown): void { if (value === null || value === undefined) return; const shown = value instanceof Error ? value.message : inspect(value); raise({ actual: value, expected: null, operator: "ifError", message: `ifError got unwanted exception: ${shown}` }, false);}
function fail(message?: Message): never { if (message instanceof Error) throw message; return raise({ actual: undefined, expected: undefined, operator: "fail", message: message ?? "Failed" }, message === undefined);}
const deepEqual = (actual: unknown, expected: unknown, message?: Message): void => check(isDeepEqual(actual, expected), message, { actual, expected, operator: "deepEqual" });const notDeepEqual = (actual: unknown, expected: unknown, message?: Message): void => check(!isDeepEqual(actual, expected), message, { actual, expected, operator: "notDeepEqual" });const deepStrictEqual = (actual: unknown, expected: unknown, message?: Message): void => check(isDeepStrictEqual(actual, expected), message, { actual, expected, operator: "deepStrictEqual" });const notDeepStrictEqual = (actual: unknown, expected: unknown, message?: Message): void => check(!isDeepStrictEqual(actual, expected), message, { actual, expected, operator: "notDeepStrictEqual" });const partialDeepStrictEqual = (actual: unknown, expected: unknown, message?: Message): void => check(isPartialStrictEqual(actual, expected), message, { actual, expected, operator: "partialDeepStrictEqual" });
const deep = { deepEqual, deepStrictEqual, notDeepEqual, notDeepStrictEqual, partialDeepStrictEqual };
const match = matching(true, "match", "did not match");const doesNotMatch = matching(false, "doesNotMatch", "was expected to not match");
const common = { fail, ok, strictEqual, notStrictEqual, throws, doesNotThrow, rejects, doesNotReject, ifError, AssertionError, ...deep, match, doesNotMatch,};
/** assert.Assert / assert/strict.Assert: a class wrapping the strict assertions as * instance methods (used by node:test's run() for `t.assert`). Always strict, so * equal/notEqual/deepEqual/notDeepEqual here are the strict forms, as on * assert/strict itself. */export class Assert {}Object.assign(Assert.prototype, { ok, fail, ifError, throws, doesNotThrow, rejects, doesNotReject, match, doesNotMatch, equal: strictEqual, notEqual: notStrictEqual, strictEqual, notStrictEqual, deepEqual: deep.deepStrictEqual, notDeepEqual: deep.notDeepStrictEqual, deepStrictEqual: deep.deepStrictEqual, notDeepStrictEqual: deep.notDeepStrictEqual, partialDeepStrictEqual: deep.partialDeepStrictEqual,});
/** node:assert/strict's callable export: a second function, distinct from `ok` * (verified against real Node — assert/strict's call signature and its own `.ok` * property are not the same function). */function strictFn(...args: unknown[]): void { ok(...args);}
/** node:assert's module export is literally the bare `ok` function (assert.ok === * ok in real Node) — every other property lives on `ok` itself, not on a wrapper. * That's also why assert/strict.ok carries the whole strict API: it's the very * same `ok`, Object.assign'd below, that assert/strict.ok points to. */Object.assign(ok, common, { equal, notEqual, deepEqual: deep.deepEqual, notDeepEqual: deep.notDeepEqual, Assert });Object.assign(strictFn, common, { equal: strictEqual, notEqual: notStrictEqual, deepEqual: deep.deepStrictEqual, notDeepEqual: deep.notDeepStrictEqual, Assert,});
type AssertModule = typeof ok & typeof common & { equal: typeof equal; notEqual: typeof notEqual; strict: StrictModule; Assert: typeof Assert };type StrictModule = typeof strictFn & typeof common & { equal: typeof strictEqual; notEqual: typeof notStrictEqual; strict: StrictModule; ok: AssertModule; Assert: typeof Assert;};
export const assert = ok as unknown as AssertModule;export const strict = strictFn as unknown as StrictModule;assert.strict = strict;Object.assign(strict, { strict, ok: assert });