mirror of
https://github.com/denoland/deno.git
synced 2024-11-29 16:30:56 -05:00
b40086fd7d
This commit changes "include_js_files!" macro from "deno_core" in a way that "dir" option doesn't cause specifiers to be rewritten to include it. Example: ``` include_js_files! { dir "js", "hello.js", } ``` The above definition required embedders to use: `import ... from "internal:<ext_name>/js/hello.js"`. But with this change, the "js" directory in which the files are stored is an implementation detail, which for embedders results in: `import ... from "internal:<ext_name>/hello.js"`. The directory the files are stored in, is an implementation detail and in some cases might result in a significant size difference for the snapshot. As an example, in "deno_node" extension, we store the source code in "polyfills" directory; which resulted in each specifier to look like "internal:deno_node/polyfills/<module_name>", but with this change it's "internal:deno_node/<module_name>". Given that "deno_node" has over 100 files, many of them having several import specifiers to the same extension, this change removes 10 characters from each import specifier.
940 lines
23 KiB
TypeScript
940 lines
23 KiB
TypeScript
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
|
// deno-lint-ignore-file ban-types
|
|
import {
|
|
AssertionError,
|
|
AssertionErrorConstructorOptions,
|
|
} from "internal:deno_node/assertion_error.ts";
|
|
import * as asserts from "internal:deno_node/_util/std_asserts.ts";
|
|
import { inspect } from "internal:deno_node/util.ts";
|
|
import {
|
|
ERR_AMBIGUOUS_ARGUMENT,
|
|
ERR_INVALID_ARG_TYPE,
|
|
ERR_INVALID_ARG_VALUE,
|
|
ERR_INVALID_RETURN_VALUE,
|
|
ERR_MISSING_ARGS,
|
|
} from "internal:deno_node/internal/errors.ts";
|
|
import { isDeepEqual } from "internal:deno_node/internal/util/comparisons.ts";
|
|
|
|
function innerFail(obj: {
|
|
actual?: unknown;
|
|
expected?: unknown;
|
|
message?: string | Error;
|
|
operator?: string;
|
|
}) {
|
|
if (obj.message instanceof Error) {
|
|
throw obj.message;
|
|
}
|
|
|
|
throw new AssertionError({
|
|
actual: obj.actual,
|
|
expected: obj.expected,
|
|
message: obj.message,
|
|
operator: obj.operator,
|
|
});
|
|
}
|
|
|
|
interface ExtendedAssertionErrorConstructorOptions
|
|
extends AssertionErrorConstructorOptions {
|
|
generatedMessage?: boolean;
|
|
}
|
|
|
|
// TODO(uki00a): This function is a workaround for setting the `generatedMessage` property flexibly.
|
|
function createAssertionError(
|
|
options: ExtendedAssertionErrorConstructorOptions,
|
|
): AssertionError {
|
|
const error = new AssertionError(options);
|
|
if (options.generatedMessage) {
|
|
error.generatedMessage = true;
|
|
}
|
|
return error;
|
|
}
|
|
|
|
/** Converts the std assertion error to node.js assertion error */
|
|
function toNode(
|
|
fn: () => void,
|
|
opts?: {
|
|
actual: unknown;
|
|
expected: unknown;
|
|
message?: string | Error;
|
|
operator?: string;
|
|
},
|
|
) {
|
|
const { operator, message, actual, expected } = opts || {};
|
|
try {
|
|
fn();
|
|
} catch (e) {
|
|
if (e instanceof asserts.AssertionError) {
|
|
if (typeof message === "string") {
|
|
throw new AssertionError({
|
|
operator,
|
|
message,
|
|
actual,
|
|
expected,
|
|
});
|
|
} else if (message instanceof Error) {
|
|
throw message;
|
|
} else {
|
|
throw new AssertionError({
|
|
operator,
|
|
message: e.message,
|
|
actual,
|
|
expected,
|
|
});
|
|
}
|
|
}
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
function assert(actual: unknown, message?: string | Error): asserts actual {
|
|
if (arguments.length === 0) {
|
|
throw new AssertionError({
|
|
message: "No value argument passed to `assert.ok()`",
|
|
});
|
|
}
|
|
toNode(
|
|
() => asserts.assert(actual),
|
|
{ message, actual, expected: true },
|
|
);
|
|
}
|
|
const ok = assert;
|
|
|
|
function throws(
|
|
fn: () => void,
|
|
error?: RegExp | Function | Error,
|
|
message?: string,
|
|
) {
|
|
// Check arg types
|
|
if (typeof fn !== "function") {
|
|
throw new ERR_INVALID_ARG_TYPE("fn", "function", fn);
|
|
}
|
|
if (
|
|
typeof error === "object" && error !== null &&
|
|
Object.getPrototypeOf(error) === Object.prototype &&
|
|
Object.keys(error).length === 0
|
|
) {
|
|
// error is an empty object
|
|
throw new ERR_INVALID_ARG_VALUE(
|
|
"error",
|
|
error,
|
|
"may not be an empty object",
|
|
);
|
|
}
|
|
if (typeof message === "string") {
|
|
if (
|
|
!(error instanceof RegExp) && typeof error !== "function" &&
|
|
!(error instanceof Error) && typeof error !== "object"
|
|
) {
|
|
throw new ERR_INVALID_ARG_TYPE("error", [
|
|
"Function",
|
|
"Error",
|
|
"RegExp",
|
|
"Object",
|
|
], error);
|
|
}
|
|
} else {
|
|
if (
|
|
typeof error !== "undefined" && typeof error !== "string" &&
|
|
!(error instanceof RegExp) && typeof error !== "function" &&
|
|
!(error instanceof Error) && typeof error !== "object"
|
|
) {
|
|
throw new ERR_INVALID_ARG_TYPE("error", [
|
|
"Function",
|
|
"Error",
|
|
"RegExp",
|
|
"Object",
|
|
], error);
|
|
}
|
|
}
|
|
|
|
// Checks test function
|
|
try {
|
|
fn();
|
|
} catch (e) {
|
|
if (
|
|
validateThrownError(e, error, message, {
|
|
operator: throws,
|
|
})
|
|
) {
|
|
return;
|
|
}
|
|
}
|
|
if (message) {
|
|
let msg = `Missing expected exception: ${message}`;
|
|
if (typeof error === "function" && error?.name) {
|
|
msg = `Missing expected exception (${error.name}): ${message}`;
|
|
}
|
|
throw new AssertionError({
|
|
message: msg,
|
|
operator: "throws",
|
|
actual: undefined,
|
|
expected: error,
|
|
});
|
|
} else if (typeof error === "string") {
|
|
// Use case of throws(fn, message)
|
|
throw new AssertionError({
|
|
message: `Missing expected exception: ${error}`,
|
|
operator: "throws",
|
|
actual: undefined,
|
|
expected: undefined,
|
|
});
|
|
} else if (typeof error === "function" && error?.prototype !== undefined) {
|
|
throw new AssertionError({
|
|
message: `Missing expected exception (${error.name}).`,
|
|
operator: "throws",
|
|
actual: undefined,
|
|
expected: error,
|
|
});
|
|
} else {
|
|
throw new AssertionError({
|
|
message: "Missing expected exception.",
|
|
operator: "throws",
|
|
actual: undefined,
|
|
expected: error,
|
|
});
|
|
}
|
|
}
|
|
|
|
function doesNotThrow(
|
|
fn: () => void,
|
|
message?: string,
|
|
): void;
|
|
function doesNotThrow(
|
|
fn: () => void,
|
|
error?: Function,
|
|
message?: string | Error,
|
|
): void;
|
|
function doesNotThrow(
|
|
fn: () => void,
|
|
error?: RegExp,
|
|
message?: string,
|
|
): void;
|
|
function doesNotThrow(
|
|
fn: () => void,
|
|
expected?: Function | RegExp | string,
|
|
message?: string | Error,
|
|
) {
|
|
// Check arg type
|
|
if (typeof fn !== "function") {
|
|
throw new ERR_INVALID_ARG_TYPE("fn", "function", fn);
|
|
} else if (
|
|
!(expected instanceof RegExp) && typeof expected !== "function" &&
|
|
typeof expected !== "string" && typeof expected !== "undefined"
|
|
) {
|
|
throw new ERR_INVALID_ARG_TYPE("expected", ["Function", "RegExp"], fn);
|
|
}
|
|
|
|
// Checks test function
|
|
try {
|
|
fn();
|
|
} catch (e) {
|
|
gotUnwantedException(e, expected, message, doesNotThrow);
|
|
}
|
|
}
|
|
|
|
function equal(
|
|
actual: unknown,
|
|
expected: unknown,
|
|
message?: string | Error,
|
|
) {
|
|
if (arguments.length < 2) {
|
|
throw new ERR_MISSING_ARGS("actual", "expected");
|
|
}
|
|
|
|
if (actual == expected) {
|
|
return;
|
|
}
|
|
|
|
if (Number.isNaN(actual) && Number.isNaN(expected)) {
|
|
return;
|
|
}
|
|
|
|
if (typeof message === "string") {
|
|
throw new AssertionError({
|
|
message,
|
|
});
|
|
} else if (message instanceof Error) {
|
|
throw message;
|
|
}
|
|
|
|
toNode(
|
|
() => asserts.assertStrictEquals(actual, expected),
|
|
{
|
|
message: message || `${actual} == ${expected}`,
|
|
operator: "==",
|
|
actual,
|
|
expected,
|
|
},
|
|
);
|
|
}
|
|
function notEqual(
|
|
actual: unknown,
|
|
expected: unknown,
|
|
message?: string | Error,
|
|
) {
|
|
if (arguments.length < 2) {
|
|
throw new ERR_MISSING_ARGS("actual", "expected");
|
|
}
|
|
|
|
if (Number.isNaN(actual) && Number.isNaN(expected)) {
|
|
throw new AssertionError({
|
|
message: `${actual} != ${expected}`,
|
|
operator: "!=",
|
|
actual,
|
|
expected,
|
|
});
|
|
}
|
|
if (actual != expected) {
|
|
return;
|
|
}
|
|
|
|
if (typeof message === "string") {
|
|
throw new AssertionError({
|
|
message,
|
|
});
|
|
} else if (message instanceof Error) {
|
|
throw message;
|
|
}
|
|
|
|
toNode(
|
|
() => asserts.assertNotStrictEquals(actual, expected),
|
|
{
|
|
message: message || `${actual} != ${expected}`,
|
|
operator: "!=",
|
|
actual,
|
|
expected,
|
|
},
|
|
);
|
|
}
|
|
function strictEqual(
|
|
actual: unknown,
|
|
expected: unknown,
|
|
message?: string | Error,
|
|
) {
|
|
if (arguments.length < 2) {
|
|
throw new ERR_MISSING_ARGS("actual", "expected");
|
|
}
|
|
|
|
toNode(
|
|
() => asserts.assertStrictEquals(actual, expected),
|
|
{ message, operator: "strictEqual", actual, expected },
|
|
);
|
|
}
|
|
function notStrictEqual(
|
|
actual: unknown,
|
|
expected: unknown,
|
|
message?: string | Error,
|
|
) {
|
|
if (arguments.length < 2) {
|
|
throw new ERR_MISSING_ARGS("actual", "expected");
|
|
}
|
|
|
|
toNode(
|
|
() => asserts.assertNotStrictEquals(actual, expected),
|
|
{ message, actual, expected, operator: "notStrictEqual" },
|
|
);
|
|
}
|
|
|
|
function deepEqual(
|
|
actual: unknown,
|
|
expected: unknown,
|
|
message?: string | Error,
|
|
) {
|
|
if (arguments.length < 2) {
|
|
throw new ERR_MISSING_ARGS("actual", "expected");
|
|
}
|
|
|
|
if (!isDeepEqual(actual, expected)) {
|
|
innerFail({ actual, expected, message, operator: "deepEqual" });
|
|
}
|
|
}
|
|
function notDeepEqual(
|
|
actual: unknown,
|
|
expected: unknown,
|
|
message?: string | Error,
|
|
) {
|
|
if (arguments.length < 2) {
|
|
throw new ERR_MISSING_ARGS("actual", "expected");
|
|
}
|
|
|
|
if (isDeepEqual(actual, expected)) {
|
|
innerFail({ actual, expected, message, operator: "notDeepEqual" });
|
|
}
|
|
}
|
|
function deepStrictEqual(
|
|
actual: unknown,
|
|
expected: unknown,
|
|
message?: string | Error,
|
|
) {
|
|
if (arguments.length < 2) {
|
|
throw new ERR_MISSING_ARGS("actual", "expected");
|
|
}
|
|
|
|
toNode(
|
|
() => asserts.assertEquals(actual, expected),
|
|
{ message, actual, expected, operator: "deepStrictEqual" },
|
|
);
|
|
}
|
|
function notDeepStrictEqual(
|
|
actual: unknown,
|
|
expected: unknown,
|
|
message?: string | Error,
|
|
) {
|
|
if (arguments.length < 2) {
|
|
throw new ERR_MISSING_ARGS("actual", "expected");
|
|
}
|
|
|
|
toNode(
|
|
() => asserts.assertNotEquals(actual, expected),
|
|
{ message, actual, expected, operator: "deepNotStrictEqual" },
|
|
);
|
|
}
|
|
|
|
function fail(message?: string | Error): never {
|
|
if (typeof message === "string" || message == null) {
|
|
throw createAssertionError({
|
|
message: message ?? "Failed",
|
|
operator: "fail",
|
|
generatedMessage: message == null,
|
|
});
|
|
} else {
|
|
throw message;
|
|
}
|
|
}
|
|
function match(actual: string, regexp: RegExp, message?: string | Error) {
|
|
if (arguments.length < 2) {
|
|
throw new ERR_MISSING_ARGS("actual", "regexp");
|
|
}
|
|
if (!(regexp instanceof RegExp)) {
|
|
throw new ERR_INVALID_ARG_TYPE("regexp", "RegExp", regexp);
|
|
}
|
|
|
|
toNode(
|
|
() => asserts.assertMatch(actual, regexp),
|
|
{ message, actual, expected: regexp, operator: "match" },
|
|
);
|
|
}
|
|
|
|
function doesNotMatch(
|
|
string: string,
|
|
regexp: RegExp,
|
|
message?: string | Error,
|
|
) {
|
|
if (arguments.length < 2) {
|
|
throw new ERR_MISSING_ARGS("string", "regexp");
|
|
}
|
|
if (!(regexp instanceof RegExp)) {
|
|
throw new ERR_INVALID_ARG_TYPE("regexp", "RegExp", regexp);
|
|
}
|
|
if (typeof string !== "string") {
|
|
if (message instanceof Error) {
|
|
throw message;
|
|
}
|
|
throw new AssertionError({
|
|
message: message ||
|
|
`The "string" argument must be of type string. Received type ${typeof string} (${
|
|
inspect(string)
|
|
})`,
|
|
actual: string,
|
|
expected: regexp,
|
|
operator: "doesNotMatch",
|
|
});
|
|
}
|
|
|
|
toNode(
|
|
() => asserts.assertNotMatch(string, regexp),
|
|
{ message, actual: string, expected: regexp, operator: "doesNotMatch" },
|
|
);
|
|
}
|
|
|
|
function strict(actual: unknown, message?: string | Error): asserts actual {
|
|
if (arguments.length === 0) {
|
|
throw new AssertionError({
|
|
message: "No value argument passed to `assert.ok()`",
|
|
});
|
|
}
|
|
assert(actual, message);
|
|
}
|
|
|
|
function rejects(
|
|
// deno-lint-ignore no-explicit-any
|
|
asyncFn: Promise<any> | (() => Promise<any>),
|
|
error?: RegExp | Function | Error,
|
|
): Promise<void>;
|
|
|
|
function rejects(
|
|
// deno-lint-ignore no-explicit-any
|
|
asyncFn: Promise<any> | (() => Promise<any>),
|
|
message?: string,
|
|
): Promise<void>;
|
|
|
|
// Intentionally avoid using async/await because test-assert-async.js requires it
|
|
function rejects(
|
|
// deno-lint-ignore no-explicit-any
|
|
asyncFn: Promise<any> | (() => Promise<any>),
|
|
error?: RegExp | Function | Error | string,
|
|
message?: string,
|
|
) {
|
|
let promise: Promise<void>;
|
|
if (typeof asyncFn === "function") {
|
|
try {
|
|
promise = asyncFn();
|
|
} catch (err) {
|
|
// If `asyncFn` throws an error synchronously, this function returns a rejected promise.
|
|
return Promise.reject(err);
|
|
}
|
|
|
|
if (!isValidThenable(promise)) {
|
|
return Promise.reject(
|
|
new ERR_INVALID_RETURN_VALUE(
|
|
"instance of Promise",
|
|
"promiseFn",
|
|
promise,
|
|
),
|
|
);
|
|
}
|
|
} else if (!isValidThenable(asyncFn)) {
|
|
return Promise.reject(
|
|
new ERR_INVALID_ARG_TYPE("promiseFn", ["function", "Promise"], asyncFn),
|
|
);
|
|
} else {
|
|
promise = asyncFn;
|
|
}
|
|
|
|
function onFulfilled() {
|
|
let message = "Missing expected rejection";
|
|
if (typeof error === "string") {
|
|
message += `: ${error}`;
|
|
} else if (typeof error === "function" && error.prototype !== undefined) {
|
|
message += ` (${error.name}).`;
|
|
} else {
|
|
message += ".";
|
|
}
|
|
return Promise.reject(createAssertionError({
|
|
message,
|
|
operator: "rejects",
|
|
generatedMessage: true,
|
|
}));
|
|
}
|
|
|
|
// deno-lint-ignore camelcase
|
|
function rejects_onRejected(e: Error) { // TODO(uki00a): In order to `test-assert-async.js` pass, intentionally adds `rejects_` as a prefix.
|
|
if (
|
|
validateThrownError(e, error, message, {
|
|
operator: rejects,
|
|
validationFunctionName: "validate",
|
|
})
|
|
) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
return promise.then(onFulfilled, rejects_onRejected);
|
|
}
|
|
|
|
function doesNotReject(
|
|
// deno-lint-ignore no-explicit-any
|
|
asyncFn: Promise<any> | (() => Promise<any>),
|
|
error?: RegExp | Function,
|
|
): Promise<void>;
|
|
|
|
function doesNotReject(
|
|
// deno-lint-ignore no-explicit-any
|
|
asyncFn: Promise<any> | (() => Promise<any>),
|
|
message?: string,
|
|
): Promise<void>;
|
|
|
|
// Intentionally avoid using async/await because test-assert-async.js requires it
|
|
function doesNotReject(
|
|
// deno-lint-ignore no-explicit-any
|
|
asyncFn: Promise<any> | (() => Promise<any>),
|
|
error?: RegExp | Function | string,
|
|
message?: string,
|
|
) {
|
|
// deno-lint-ignore no-explicit-any
|
|
let promise: Promise<any>;
|
|
if (typeof asyncFn === "function") {
|
|
try {
|
|
const value = asyncFn();
|
|
if (!isValidThenable(value)) {
|
|
return Promise.reject(
|
|
new ERR_INVALID_RETURN_VALUE(
|
|
"instance of Promise",
|
|
"promiseFn",
|
|
value,
|
|
),
|
|
);
|
|
}
|
|
promise = value;
|
|
} catch (e) {
|
|
// If `asyncFn` throws an error synchronously, this function returns a rejected promise.
|
|
return Promise.reject(e);
|
|
}
|
|
} else if (!isValidThenable(asyncFn)) {
|
|
return Promise.reject(
|
|
new ERR_INVALID_ARG_TYPE("promiseFn", ["function", "Promise"], asyncFn),
|
|
);
|
|
} else {
|
|
promise = asyncFn;
|
|
}
|
|
|
|
return promise.then(
|
|
() => {},
|
|
(e) => gotUnwantedException(e, error, message, doesNotReject),
|
|
);
|
|
}
|
|
|
|
function gotUnwantedException(
|
|
// deno-lint-ignore no-explicit-any
|
|
e: any,
|
|
expected: RegExp | Function | string | null | undefined,
|
|
message: string | Error | null | undefined,
|
|
operator: Function,
|
|
): never {
|
|
if (typeof expected === "string") {
|
|
// The use case of doesNotThrow(fn, message);
|
|
throw new AssertionError({
|
|
message:
|
|
`Got unwanted exception: ${expected}\nActual message: "${e.message}"`,
|
|
operator: operator.name,
|
|
});
|
|
} else if (
|
|
typeof expected === "function" && expected.prototype !== undefined
|
|
) {
|
|
// The use case of doesNotThrow(fn, Error, message);
|
|
if (e instanceof expected) {
|
|
let msg = `Got unwanted exception: ${e.constructor?.name}`;
|
|
if (message) {
|
|
msg += ` ${String(message)}`;
|
|
}
|
|
throw new AssertionError({
|
|
message: msg,
|
|
operator: operator.name,
|
|
});
|
|
} else if (expected.prototype instanceof Error) {
|
|
throw e;
|
|
} else {
|
|
const result = expected(e);
|
|
if (result === true) {
|
|
let msg = `Got unwanted rejection.\nActual message: "${e.message}"`;
|
|
if (message) {
|
|
msg += ` ${String(message)}`;
|
|
}
|
|
throw new AssertionError({
|
|
message: msg,
|
|
operator: operator.name,
|
|
});
|
|
}
|
|
}
|
|
throw e;
|
|
} else {
|
|
if (message) {
|
|
throw new AssertionError({
|
|
message: `Got unwanted exception: ${message}\nActual message: "${
|
|
e ? e.message : String(e)
|
|
}"`,
|
|
operator: operator.name,
|
|
});
|
|
}
|
|
throw new AssertionError({
|
|
message: `Got unwanted exception.\nActual message: "${
|
|
e ? e.message : String(e)
|
|
}"`,
|
|
operator: operator.name,
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Throws `value` if the value is not `null` or `undefined`.
|
|
*
|
|
* @param err
|
|
*/
|
|
// deno-lint-ignore no-explicit-any
|
|
function ifError(err: any) {
|
|
if (err !== null && err !== undefined) {
|
|
let message = "ifError got unwanted exception: ";
|
|
|
|
if (typeof err === "object" && typeof err.message === "string") {
|
|
if (err.message.length === 0 && err.constructor) {
|
|
message += err.constructor.name;
|
|
} else {
|
|
message += err.message;
|
|
}
|
|
} else {
|
|
message += inspect(err);
|
|
}
|
|
|
|
const newErr = new AssertionError({
|
|
actual: err,
|
|
expected: null,
|
|
operator: "ifError",
|
|
message,
|
|
stackStartFn: ifError,
|
|
});
|
|
|
|
// Make sure we actually have a stack trace!
|
|
const origStack = err.stack;
|
|
|
|
if (typeof origStack === "string") {
|
|
// This will remove any duplicated frames from the error frames taken
|
|
// from within `ifError` and add the original error frames to the newly
|
|
// created ones.
|
|
const tmp2 = origStack.split("\n");
|
|
tmp2.shift();
|
|
|
|
// Filter all frames existing in err.stack.
|
|
let tmp1 = newErr!.stack?.split("\n");
|
|
|
|
for (const errFrame of tmp2) {
|
|
// Find the first occurrence of the frame.
|
|
const pos = tmp1?.indexOf(errFrame);
|
|
|
|
if (pos !== -1) {
|
|
// Only keep new frames.
|
|
tmp1 = tmp1?.slice(0, pos);
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
newErr.stack = `${tmp1?.join("\n")}\n${tmp2.join("\n")}`;
|
|
}
|
|
|
|
throw newErr;
|
|
}
|
|
}
|
|
|
|
interface ValidateThrownErrorOptions {
|
|
operator: Function;
|
|
validationFunctionName?: string;
|
|
}
|
|
|
|
function validateThrownError(
|
|
// deno-lint-ignore no-explicit-any
|
|
e: any,
|
|
error: RegExp | Function | Error | string | null | undefined,
|
|
message: string | undefined | null,
|
|
options: ValidateThrownErrorOptions,
|
|
): boolean {
|
|
if (typeof error === "string") {
|
|
if (message != null) {
|
|
throw new ERR_INVALID_ARG_TYPE(
|
|
"error",
|
|
["Object", "Error", "Function", "RegExp"],
|
|
error,
|
|
);
|
|
} else if (typeof e === "object" && e !== null) {
|
|
if (e.message === error) {
|
|
throw new ERR_AMBIGUOUS_ARGUMENT(
|
|
"error/message",
|
|
`The error message "${e.message}" is identical to the message.`,
|
|
);
|
|
}
|
|
} else if (e === error) {
|
|
throw new ERR_AMBIGUOUS_ARGUMENT(
|
|
"error/message",
|
|
`The error "${e}" is identical to the message.`,
|
|
);
|
|
}
|
|
message = error;
|
|
error = undefined;
|
|
}
|
|
if (
|
|
error instanceof Function && error.prototype !== undefined &&
|
|
error.prototype instanceof Error
|
|
) {
|
|
// error is a constructor
|
|
if (e instanceof error) {
|
|
return true;
|
|
}
|
|
throw createAssertionError({
|
|
message:
|
|
`The error is expected to be an instance of "${error.name}". Received "${e?.constructor?.name}"\n\nError message:\n\n${e?.message}`,
|
|
actual: e,
|
|
expected: error,
|
|
operator: options.operator.name,
|
|
generatedMessage: true,
|
|
});
|
|
}
|
|
if (error instanceof Function) {
|
|
const received = error(e);
|
|
if (received === true) {
|
|
return true;
|
|
}
|
|
throw createAssertionError({
|
|
message: `The ${
|
|
options.validationFunctionName
|
|
? `"${options.validationFunctionName}" validation`
|
|
: "validation"
|
|
} function is expected to return "true". Received ${
|
|
inspect(received)
|
|
}\n\nCaught error:\n\n${e}`,
|
|
actual: e,
|
|
expected: error,
|
|
operator: options.operator.name,
|
|
generatedMessage: true,
|
|
});
|
|
}
|
|
if (error instanceof RegExp) {
|
|
if (error.test(String(e))) {
|
|
return true;
|
|
}
|
|
throw createAssertionError({
|
|
message:
|
|
`The input did not match the regular expression ${error.toString()}. Input:\n\n'${
|
|
String(e)
|
|
}'\n`,
|
|
actual: e,
|
|
expected: error,
|
|
operator: options.operator.name,
|
|
generatedMessage: true,
|
|
});
|
|
}
|
|
if (typeof error === "object" && error !== null) {
|
|
const keys = Object.keys(error);
|
|
if (error instanceof Error) {
|
|
keys.push("name", "message");
|
|
}
|
|
for (const k of keys) {
|
|
if (e == null) {
|
|
throw createAssertionError({
|
|
message: message || "object is expected to thrown, but got null",
|
|
actual: e,
|
|
expected: error,
|
|
operator: options.operator.name,
|
|
generatedMessage: message == null,
|
|
});
|
|
}
|
|
|
|
if (typeof e === "string") {
|
|
throw createAssertionError({
|
|
message: message ||
|
|
`object is expected to thrown, but got string: ${e}`,
|
|
actual: e,
|
|
expected: error,
|
|
operator: options.operator.name,
|
|
generatedMessage: message == null,
|
|
});
|
|
}
|
|
if (typeof e === "number") {
|
|
throw createAssertionError({
|
|
message: message ||
|
|
`object is expected to thrown, but got number: ${e}`,
|
|
actual: e,
|
|
expected: error,
|
|
operator: options.operator.name,
|
|
generatedMessage: message == null,
|
|
});
|
|
}
|
|
if (!(k in e)) {
|
|
throw createAssertionError({
|
|
message: message || `A key in the expected object is missing: ${k}`,
|
|
actual: e,
|
|
expected: error,
|
|
operator: options.operator.name,
|
|
generatedMessage: message == null,
|
|
});
|
|
}
|
|
const actual = e[k];
|
|
// deno-lint-ignore no-explicit-any
|
|
const expected = (error as any)[k];
|
|
if (typeof actual === "string" && expected instanceof RegExp) {
|
|
match(actual, expected);
|
|
} else {
|
|
deepStrictEqual(actual, expected);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
if (typeof error === "undefined") {
|
|
return true;
|
|
}
|
|
throw createAssertionError({
|
|
message: `Invalid expectation: ${error}`,
|
|
operator: options.operator.name,
|
|
generatedMessage: true,
|
|
});
|
|
}
|
|
|
|
// deno-lint-ignore no-explicit-any
|
|
function isValidThenable(maybeThennable: any): boolean {
|
|
if (!maybeThennable) {
|
|
return false;
|
|
}
|
|
|
|
if (maybeThennable instanceof Promise) {
|
|
return true;
|
|
}
|
|
|
|
const isThenable = typeof maybeThennable.then === "function" &&
|
|
typeof maybeThennable.catch === "function";
|
|
|
|
return isThenable && typeof maybeThennable !== "function";
|
|
}
|
|
|
|
Object.assign(strict, {
|
|
AssertionError,
|
|
deepEqual: deepStrictEqual,
|
|
deepStrictEqual,
|
|
doesNotMatch,
|
|
doesNotReject,
|
|
doesNotThrow,
|
|
equal: strictEqual,
|
|
fail,
|
|
ifError,
|
|
match,
|
|
notDeepEqual: notDeepStrictEqual,
|
|
notDeepStrictEqual,
|
|
notEqual: notStrictEqual,
|
|
notStrictEqual,
|
|
ok,
|
|
rejects,
|
|
strict,
|
|
strictEqual,
|
|
throws,
|
|
});
|
|
|
|
export default Object.assign(assert, {
|
|
AssertionError,
|
|
deepEqual,
|
|
deepStrictEqual,
|
|
doesNotMatch,
|
|
doesNotReject,
|
|
doesNotThrow,
|
|
equal,
|
|
fail,
|
|
ifError,
|
|
match,
|
|
notDeepEqual,
|
|
notDeepStrictEqual,
|
|
notEqual,
|
|
notStrictEqual,
|
|
ok,
|
|
rejects,
|
|
strict,
|
|
strictEqual,
|
|
throws,
|
|
});
|
|
|
|
export {
|
|
AssertionError,
|
|
deepEqual,
|
|
deepStrictEqual,
|
|
doesNotMatch,
|
|
doesNotReject,
|
|
doesNotThrow,
|
|
equal,
|
|
fail,
|
|
ifError,
|
|
match,
|
|
notDeepEqual,
|
|
notDeepStrictEqual,
|
|
notEqual,
|
|
notStrictEqual,
|
|
ok,
|
|
rejects,
|
|
strict,
|
|
strictEqual,
|
|
throws,
|
|
};
|