diff --git a/assert/assert_almost_equals_test.ts b/assert/assert_almost_equals_test.ts index a28a809b2..ec94d7aa7 100644 --- a/assert/assert_almost_equals_test.ts +++ b/assert/assert_almost_equals_test.ts @@ -51,3 +51,11 @@ Deno.test("assertAlmostEquals() throws when special numbers do not match", () => 'Expected actual: "Infinity" to be close to "NaN"', ); }); + +Deno.test("assertAlmostEquals() throws with custom message", () => { + assertThrows( + () => assertAlmostEquals(-Infinity, +Infinity, 1e-17, "CUSTOM MESSAGE"), + AssertionError, + `Expected actual: "-Infinity" to be close to "Infinity": delta "Infinity" is greater than "1e-17": CUSTOM MESSAGE`, + ); +}); diff --git a/assert/assert_array_includes_test.ts b/assert/assert_array_includes_test.ts index bda1e10f1..a987d3569 100644 --- a/assert/assert_array_includes_test.ts +++ b/assert/assert_array_includes_test.ts @@ -56,6 +56,23 @@ missing: [ ); }); +Deno.test("assertArrayIncludes() throws with custom message", () => { + assertThrows( + () => assertArrayIncludes(["a"], ["b"], "CUSTOM MESSAGE"), + AssertionError, + ` +Expected actual: "[ + "a", +]" to include: "[ + "b", +]": CUSTOM MESSAGE +missing: [ + "b", +] +`.trim(), + ); +}); + // https://github.com/denoland/deno_std/issues/3372 Deno.test("assertArrayIncludes() type-checks failing cases", () => { // @ts-expect-error 2nd arg - 'string' is not assignable to 'ArrayLikeArg'. diff --git a/assert/assert_equals_test.ts b/assert/assert_equals_test.ts index 19c8fb1c4..6f8d1c165 100644 --- a/assert/assert_equals_test.ts +++ b/assert/assert_equals_test.ts @@ -1,6 +1,8 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. import { assertEquals, AssertionError, assertThrows } from "./mod.ts"; import { bold, gray, green, red, stripAnsiCode, yellow } from "@std/fmt/colors"; +import { _internals } from "@std/internal"; +import { stub } from "@std/testing/mock"; const createHeader = (): string[] => [ "", @@ -151,9 +153,27 @@ Deno.test({ }, }); -Deno.test( - "assertEquals() compares objects structurally if one object's constructor is undefined and the other is Object", - () => { +Deno.test({ + name: "assertEquals() throws with [Cannot display] if diffing fails", + fn() { + using _ = stub(_internals, "diff", () => { + throw new Error(); + }); + assertThrows( + () => assertEquals("1", "2"), + AssertionError, + [ + "Values are not equal.", + "[Cannot display]", + ].join("\n"), + ); + }, +}); + +Deno.test({ + name: + "assertEquals() compares objects structurally if one object's constructor is undefined and the other is Object", + fn() { const a = Object.create(null); a.prop = "test"; const b = { @@ -163,50 +183,56 @@ Deno.test( assertEquals(a, b); assertEquals(b, a); }, -); +}); -Deno.test("assertEquals() orders diff for differently ordered objects", () => { - assertThrows( - () => { - assertEquals( - { - aaaaaaaaaaaaaaaaaaaaaaaa: 0, - bbbbbbbbbbbbbbbbbbbbbbbb: 0, - ccccccccccccccccccccccc: 0, - }, - { - ccccccccccccccccccccccc: 1, - aaaaaaaaaaaaaaaaaaaaaaaa: 0, - bbbbbbbbbbbbbbbbbbbbbbbb: 0, - }, - ); - }, - AssertionError, - ` +Deno.test({ + name: "assertEquals() orders diff for differently ordered objects", + fn() { + assertThrows( + () => { + assertEquals( + { + aaaaaaaaaaaaaaaaaaaaaaaa: 0, + bbbbbbbbbbbbbbbbbbbbbbbb: 0, + ccccccccccccccccccccccc: 0, + }, + { + ccccccccccccccccccccccc: 1, + aaaaaaaaaaaaaaaaaaaaaaaa: 0, + bbbbbbbbbbbbbbbbbbbbbbbb: 0, + }, + ); + }, + AssertionError, + ` { aaaaaaaaaaaaaaaaaaaaaaaa: 0, bbbbbbbbbbbbbbbbbbbbbbbb: 0, - ccccccccccccccccccccccc: 0, + ccccccccccccccccccccccc: 1, }`, - ); + ); + }, }); -Deno.test("assertEquals() matches same Set with object keys", () => { - const data = [ - { - id: "_1p7ZED73OF98VbT1SzSkjn", - type: { id: "_ETGENUS" }, - name: "Thuja", - friendlyId: "g-thuja", - }, - { - id: "_567qzghxZmeQ9pw3q09bd3", - type: { id: "_ETGENUS" }, - name: "Pinus", - friendlyId: "g-pinus", - }, - ]; - assertEquals(data, data); - assertEquals(new Set(data), new Set(data)); +Deno.test({ + name: "assertEquals() matches same Set with object keys", + fn() { + const data = [ + { + id: "_1p7ZED73OF98VbT1SzSkjn", + type: { id: "_ETGENUS" }, + name: "Thuja", + friendlyId: "g-thuja", + }, + { + id: "_567qzghxZmeQ9pw3q09bd3", + type: { id: "_ETGENUS" }, + name: "Pinus", + friendlyId: "g-pinus", + }, + ]; + assertEquals(data, data); + assertEquals(new Set(data), new Set(data)); + }, }); diff --git a/assert/assert_exists_test.ts b/assert/assert_exists_test.ts index b84c50b2d..ff0314058 100644 --- a/assert/assert_exists_test.ts +++ b/assert/assert_exists_test.ts @@ -32,3 +32,11 @@ Deno.test("assertExists() throws when value is null or undefined", () => { 'Expected actual: "null" to not be null or undefined.', ); }); + +Deno.test("assertExists() throws with custom message", () => { + assertThrows( + () => assertExists(undefined, "CUSTOM MESSAGE"), + AssertionError, + 'Expected actual: "undefined" to not be null or undefined: CUSTOM MESSAGE', + ); +}); diff --git a/assert/assert_instance_of_test.ts b/assert/assert_instance_of_test.ts index 7871ddcf8..b728c4520 100644 --- a/assert/assert_instance_of_test.ts +++ b/assert/assert_instance_of_test.ts @@ -33,9 +33,9 @@ Deno.test({ // Custom message assertThrows( - () => assertInstanceOf(new Date(), RegExp, "Custom message"), + () => assertInstanceOf(new Date(), RegExp, "CUSTOM MESSAGE"), AssertionError, - "Custom message", + "CUSTOM MESSAGE", ); // Edge cases diff --git a/assert/assert_is_error.ts b/assert/assert_is_error.ts index bcc185678..04c1f9308 100644 --- a/assert/assert_is_error.ts +++ b/assert/assert_is_error.ts @@ -34,9 +34,8 @@ export function assertIsError( ); } if (ErrorClass && !(error instanceof ErrorClass)) { - msg = `Expected error to be instance of "${ErrorClass.name}", but was "${ - typeof error === "object" ? error?.constructor?.name : "[not an object]" - }"${msgSuffix}`; + msg = + `Expected error to be instance of "${ErrorClass.name}", but was "${error?.constructor?.name}"${msgSuffix}`; throw new AssertionError(msg); } let msgCheck; @@ -54,11 +53,7 @@ export function assertIsError( msgMatches instanceof RegExp ? msgMatches.toString() : JSON.stringify(msgMatches) - }, but got ${ - error instanceof Error - ? JSON.stringify(error.message) - : '"[not an Error]"' // TODO(kt3k): show more useful information - }${msgSuffix}`; + }, but got ${JSON.stringify(error?.message)}${msgSuffix}`; throw new AssertionError(msg); } } diff --git a/assert/assert_is_error_test.ts b/assert/assert_is_error_test.ts index ccaf58751..0aa9fd779 100644 --- a/assert/assert_is_error_test.ts +++ b/assert/assert_is_error_test.ts @@ -58,3 +58,17 @@ Deno.test("assertIsError() throws when given value doesn't match regex ", () => `Expected error message to include /egg/, but got "Regex test"`, ); }); + +Deno.test("assertIsError() throws with custom message", () => { + assertThrows( + () => + assertIsError( + new CustomError("failed"), + AnotherCustomError, + "fail", + "CUSTOM MESSAGE", + ), + AssertionError, + 'Expected error to be instance of "AnotherCustomError", but was "CustomError": CUSTOM MESSAGE', + ); +}); diff --git a/assert/assert_match_test.ts b/assert/assert_match_test.ts index d6f52b00e..ff1d0ee18 100644 --- a/assert/assert_match_test.ts +++ b/assert/assert_match_test.ts @@ -1,21 +1,28 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -import { assert, AssertionError, assertMatch } from "./mod.ts"; +import { assertThrows } from "./assert_throws.ts"; +import { AssertionError, assertMatch } from "./mod.ts"; -Deno.test("AssertStringMatching", function () { +Deno.test("assertMatch()", () => { assertMatch("foobar@deno.com", RegExp(/[a-zA-Z]+@[a-zA-Z]+.com/)); }); -Deno.test("AssertStringMatchingThrows", function () { - let didThrow = false; - try { - assertMatch("Denosaurus from Jurassic", RegExp(/Raptor/)); - } catch (e) { - assert(e instanceof AssertionError); - assert( - e.message === - `Expected actual: "Denosaurus from Jurassic" to match: "/Raptor/".`, - ); - didThrow = true; - } - assert(didThrow); +Deno.test("assertMatch() throws", () => { + assertThrows( + () => assertMatch("Denosaurus from Jurassic", RegExp(/Raptor/)), + AssertionError, + `Expected actual: "Denosaurus from Jurassic" to match: "/Raptor/".`, + ); +}); + +Deno.test("assertMatch() throws with custom message", () => { + assertThrows( + () => + assertMatch( + "Denosaurus from Jurassic", + RegExp(/Raptor/), + "CUSTOM MESSAGE", + ), + AssertionError, + `Expected actual: "Denosaurus from Jurassic" to match: "/Raptor/": CUSTOM MESSAGE`, + ); }); diff --git a/assert/assert_not_equals_test.ts b/assert/assert_not_equals_test.ts index cc472c980..481419086 100644 --- a/assert/assert_not_equals_test.ts +++ b/assert/assert_not_equals_test.ts @@ -1,28 +1,46 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -import { - assert, - assertEquals, - AssertionError, - assertNotEquals, -} from "./mod.ts"; +import { AssertionError, assertNotEquals, assertThrows } from "./mod.ts"; +import { stub } from "@std/testing/mock"; -Deno.test("NotEquals", function () { - const a = { foo: "bar" }; - const b = { bar: "foo" }; - assertNotEquals(a, b); +Deno.test("assertNotEquals()", () => { + assertNotEquals({ foo: "bar" }, { bar: "foo" }); assertNotEquals("Denosaurus", "Tyrannosaurus"); assertNotEquals( new Date(2019, 0, 3, 4, 20, 1, 10), new Date(2019, 0, 3, 4, 20, 1, 20), ); assertNotEquals(new Date("invalid"), new Date(2019, 0, 3, 4, 20, 1, 20)); - let didThrow; - try { - assertNotEquals("Raptor", "Raptor"); - didThrow = false; - } catch (e) { - assert(e instanceof AssertionError); - didThrow = true; - } - assertEquals(didThrow, true); +}); + +Deno.test("assertNotEquals() throws", () => { + assertThrows( + () => { + assertNotEquals("foo", "foo"); + }, + AssertionError, + "Expected actual: foo not to be: foo.", + ); +}); + +Deno.test("assertNotEquals() throws with custom message", () => { + assertThrows( + () => { + assertNotEquals("foo", "foo", "CUSTOM MESSAGE"); + }, + AssertionError, + "Expected actual: foo not to be: foo: CUSTOM MESSAGE", + ); +}); + +Deno.test("assertNotEquals() throws with [Cannot display]", () => { + using _ = stub(globalThis, "String", () => { + throw new Error(); + }); + assertThrows( + () => { + assertNotEquals("a", "a"); + }, + AssertionError, + `Expected actual: [Cannot display] not to be: [Cannot display].`, + ); }); diff --git a/assert/assert_not_instance_of_test.ts b/assert/assert_not_instance_of_test.ts index 6b547d743..7888a055a 100644 --- a/assert/assert_not_instance_of_test.ts +++ b/assert/assert_not_instance_of_test.ts @@ -1,11 +1,33 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -import { assertNotInstanceOf } from "./mod.ts"; +import { AssertionError, assertNotInstanceOf, assertThrows } from "./mod.ts"; Deno.test({ - name: "assertNotInstanceOf", + name: "assertNotInstanceOf()", fn() { assertNotInstanceOf("not a number", Number); assertNotInstanceOf(42, String); assertNotInstanceOf(new URL("http://example.com"), Boolean); }, }); + +Deno.test({ + name: "assertNotInstanceOf() throws", + fn() { + assertThrows( + () => assertNotInstanceOf(new Date(), Date), + AssertionError, + 'Expected object to not be an instance of "function".', + ); + }, +}); + +Deno.test({ + name: "assertNotInstanceOf() throws with custom message", + fn() { + assertThrows( + () => assertNotInstanceOf(new Date(), Date, "CUSTOM MESSAGE"), + AssertionError, + 'Expected object to not be an instance of "function": CUSTOM MESSAGE', + ); + }, +}); diff --git a/assert/assert_not_match_test.ts b/assert/assert_not_match_test.ts index 89b079170..682572034 100644 --- a/assert/assert_not_match_test.ts +++ b/assert/assert_not_match_test.ts @@ -1,21 +1,27 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -import { assert, AssertionError, assertNotMatch } from "./mod.ts"; +import { AssertionError, assertNotMatch, assertThrows } from "./mod.ts"; -Deno.test("AssertStringNotMatching", function () { +Deno.test("assertNotMatch()", () => { assertNotMatch("foobar.deno.com", RegExp(/[a-zA-Z]+@[a-zA-Z]+.com/)); }); -Deno.test("AssertStringNotMatchingThrows", function () { - let didThrow = false; - try { - assertNotMatch("Denosaurus from Jurassic", RegExp(/from/)); - } catch (e) { - assert(e instanceof AssertionError); - assert( - e.message === - `Expected actual: "Denosaurus from Jurassic" to not match: "/from/".`, - ); - didThrow = true; - } - assert(didThrow); +Deno.test("assertNotMatch() throws", () => { + assertThrows( + () => assertNotMatch("Denosaurus from Jurassic", RegExp(/from/)), + AssertionError, + `Expected actual: "Denosaurus from Jurassic" to not match: "/from/".`, + ); +}); + +Deno.test("assertNotMatch() throws with custom message", () => { + assertThrows( + () => + assertNotMatch( + "Denosaurus from Jurassic", + RegExp(/from/), + "CUSTOM MESSAGE", + ), + AssertionError, + `Expected actual: "Denosaurus from Jurassic" to not match: "/from/": CUSTOM MESSAGE`, + ); }); diff --git a/assert/assert_object_match.ts b/assert/assert_object_match.ts index ee46c6a46..03c1dd540 100644 --- a/assert/assert_object_match.ts +++ b/assert/assert_object_match.ts @@ -40,7 +40,7 @@ export function assertObjectMatch( a === null ? null : `type ${typeof a}` }`, ); - } else throw err; + } } // Filter keys and symbols which are present in both actual and expected const filtered = {} as loose; diff --git a/assert/assert_object_match_test.ts b/assert/assert_object_match_test.ts index 44d7b3b4e..a0f265c25 100644 --- a/assert/assert_object_match_test.ts +++ b/assert/assert_object_match_test.ts @@ -295,7 +295,7 @@ Deno.test("assertObjectMatch() throws assertion error when in the first argument ); }); -Deno.test("assertObjectMatch() throws readable type error for non mapable primative types", () => { +Deno.test("assertObjectMatch() throws readable type error for non mappable primitive types", () => { assertThrows( // @ts-expect-error Argument of type 'null' is not assignable to parameter of type 'Record' () => assertObjectMatch(null, { foo: 42 }), diff --git a/assert/assert_rejects.ts b/assert/assert_rejects.ts index d3e50a202..541a1ca60 100644 --- a/assert/assert_rejects.ts +++ b/assert/assert_rejects.ts @@ -81,6 +81,8 @@ export async function assertRejects( ) { isPromiseReturned = true; await possiblePromise; + } else { + throw Error(); } } catch (error) { if (!isPromiseReturned) { @@ -89,7 +91,7 @@ export async function assertRejects( ); } if (ErrorClass) { - if (error instanceof Error === false) { + if (!(error instanceof Error)) { throw new AssertionError(`A non-Error object was rejected${msgSuffix}`); } assertIsError( diff --git a/assert/assert_rejects_test.ts b/assert/assert_rejects_test.ts index b1a0ef464..73e9fe90a 100644 --- a/assert/assert_rejects_test.ts +++ b/assert/assert_rejects_test.ts @@ -1,13 +1,13 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. import { assert, assertEquals, AssertionError, assertRejects } from "./mod.ts"; -Deno.test("assertRejects with return type", async () => { +Deno.test("assertRejects() with return type", async () => { await assertRejects(() => { return Promise.reject(new Error()); }); }); -Deno.test("assertRejects with synchronous function that throws", async () => { +Deno.test("assertRejects() with synchronous function that throws", async () => { await assertRejects(() => assertRejects(() => { throw new Error(); @@ -23,7 +23,7 @@ Deno.test("assertRejects with synchronous function that throws", async () => { ); }); -Deno.test("assertRejects with PromiseLike", async () => { +Deno.test("assertRejects() with PromiseLike", async () => { await assertRejects( () => ({ then() { @@ -35,7 +35,7 @@ Deno.test("assertRejects with PromiseLike", async () => { ); }); -Deno.test("assertRejects with non-error value rejected and error class", async () => { +Deno.test("assertRejects() with non-error value rejected and error class", async () => { await assertRejects( () => { return assertRejects( @@ -51,7 +51,7 @@ Deno.test("assertRejects with non-error value rejected and error class", async ( ); }); -Deno.test("assertRejects with non-error value rejected", async () => { +Deno.test("assertRejects() with non-error value rejected", async () => { await assertRejects(() => { return Promise.reject(null); }); @@ -60,7 +60,7 @@ Deno.test("assertRejects with non-error value rejected", async () => { }); }); -Deno.test("assertRejects with error class", async () => { +Deno.test("assertRejects() with error class", async () => { await assertRejects( () => { return Promise.reject(new Error("foo")); @@ -70,7 +70,7 @@ Deno.test("assertRejects with error class", async () => { ); }); -Deno.test("assertRejects resolves with caught error", async () => { +Deno.test("assertRejects() resolves with caught error", async () => { const error = await assertRejects( () => { return Promise.reject(new Error("foo")); @@ -80,7 +80,7 @@ Deno.test("assertRejects resolves with caught error", async () => { assertEquals(error.message, "foo"); }); -Deno.test("Assert Throws Async Parent Error", async () => { +Deno.test("assertRejects() throws async parent error ", async () => { await assertRejects( () => { return Promise.reject(new AssertionError("Fail!")); @@ -91,7 +91,7 @@ Deno.test("Assert Throws Async Parent Error", async () => { }); Deno.test( - "Assert Throws Async promise rejected with custom Error", + "assertRejects() throws with custom Error", async () => { class CustomError extends Error {} class AnotherCustomError extends Error {} @@ -107,3 +107,32 @@ Deno.test( ); }, ); + +Deno.test("assertRejects() throws when no promise is returned", async () => { + await assertRejects( + // @ts-expect-error - testing invalid input + async () => await assertRejects(() => {}), + AssertionError, + "Function throws when expected to reject.", + ); +}); + +Deno.test("assertRejects() throws when the promise doesn't reject", async () => { + await assertRejects( + async () => await assertRejects(async () => await Promise.resolve(42)), + AssertionError, + "Expected function to reject.", + ); +}); + +Deno.test("assertRejects() throws with custom message", async () => { + await assertRejects( + async () => + await assertRejects( + async () => await Promise.resolve(42), + "CUSTOM MESSAGE", + ), + AssertionError, + "Expected function to reject: CUSTOM MESSAGE", + ); +}); diff --git a/assert/assert_strict_equals_test.ts b/assert/assert_strict_equals_test.ts index 06f12dc81..bcbc4b664 100644 --- a/assert/assert_strict_equals_test.ts +++ b/assert/assert_strict_equals_test.ts @@ -1,8 +1,28 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. import { AssertionError, assertStrictEquals, assertThrows } from "./mod.ts"; +import { _internals } from "@std/internal"; +import { stub } from "@std/testing/mock"; Deno.test({ - name: "strict types test", + name: "assertStrictEquals()", + fn() { + assertStrictEquals(true, true); + assertStrictEquals(10, 10); + assertStrictEquals("abc", "abc"); + assertStrictEquals(NaN, NaN); + + const xs = [1, false, "foo"]; + const ys = xs; + assertStrictEquals(xs, ys); + + const x = { a: 1 }; + const y = x; + assertStrictEquals(x, y); + }, +}); + +Deno.test({ + name: "assertStrictEquals() types test", fn() { const x = { number: 2 }; @@ -26,25 +46,7 @@ Deno.test({ }); Deno.test({ - name: "strict pass case", - fn() { - assertStrictEquals(true, true); - assertStrictEquals(10, 10); - assertStrictEquals("abc", "abc"); - assertStrictEquals(NaN, NaN); - - const xs = [1, false, "foo"]; - const ys = xs; - assertStrictEquals(xs, ys); - - const x = { a: 1 }; - const y = x; - assertStrictEquals(x, y); - }, -}); - -Deno.test({ - name: "strict failed with structure diff", + name: "assertStrictEquals() throws with structure diff", fn() { assertThrows( () => assertStrictEquals({ a: 1, b: 2 }, { a: 1, c: [3] }), @@ -62,7 +64,7 @@ Deno.test({ }); Deno.test({ - name: "strict failed with reference diff", + name: "assertStrictEquals() throws with reference diff", fn() { assertThrows( () => assertStrictEquals({ a: 1, b: 2 }, { a: 1, b: 2 }), @@ -78,7 +80,7 @@ Deno.test({ }); Deno.test({ - name: "strict failed with custom msg", + name: "assertStrictEquals() throws with custom message", fn() { assertThrows( () => assertStrictEquals({ a: 1 }, { a: 1 }, "CUSTOM MESSAGE"), @@ -91,3 +93,17 @@ Deno.test({ ); }, }); + +Deno.test({ + name: "assertStrictEquals() throws with [Cannot display] if diffing fails", + fn() { + using _ = stub(_internals, "diff", () => { + throw new Error(); + }); + assertThrows( + () => assertStrictEquals("1", "2"), + AssertionError, + "\n[Cannot display] + \n\n", + ); + }, +}); diff --git a/assert/assert_string_includes_test.ts b/assert/assert_string_includes_test.ts index 54e848a2c..194b500ef 100644 --- a/assert/assert_string_includes_test.ts +++ b/assert/assert_string_includes_test.ts @@ -4,9 +4,10 @@ import { assertEquals, AssertionError, assertStringIncludes, + assertThrows, } from "./mod.ts"; -Deno.test("AssertStringIncludes", function () { +Deno.test("assertStringIncludes()", () => { assertStringIncludes("Denosaurus", "saur"); assertStringIncludes("Denosaurus", "Deno"); assertStringIncludes("Denosaurus", "rus"); @@ -21,17 +22,23 @@ Deno.test("AssertStringIncludes", function () { assertEquals(didThrow, true); }); -Deno.test("AssertStringContainsThrow", function () { - let didThrow = false; - try { - assertStringIncludes("Denosaurus from Jurassic", "Raptor"); - } catch (e) { - assert(e instanceof AssertionError); - assert( - e.message === - `Expected actual: "Denosaurus from Jurassic" to contain: "Raptor".`, - ); - didThrow = true; - } - assert(didThrow); +Deno.test("assertStringIncludes() throws", () => { + assertThrows( + () => assertStringIncludes("Denosaurus from Jurassic", "Raptor"), + AssertionError, + `Expected actual: "Denosaurus from Jurassic" to contain: "Raptor".`, + ); +}); + +Deno.test("assertStringIncludes() with custom message", () => { + assertThrows( + () => + assertStringIncludes( + "Denosaurus from Jurassic", + "Raptor", + "CUSTOM MESSAGE", + ), + AssertionError, + `Expected actual: "Denosaurus from Jurassic" to contain: "Raptor": CUSTOM MESSAGE`, + ); }); diff --git a/assert/assert_throws.ts b/assert/assert_throws.ts index 7c4da3fc2..69f36ab35 100644 --- a/assert/assert_throws.ts +++ b/assert/assert_throws.ts @@ -62,8 +62,8 @@ export function assertThrows( if (typeof errorClassOrMsg !== "string") { if ( errorClassOrMsg === undefined || - errorClassOrMsg.prototype instanceof Error || - errorClassOrMsg.prototype === Error.prototype + errorClassOrMsg?.prototype instanceof Error || + errorClassOrMsg?.prototype === Error.prototype ) { // deno-lint-ignore no-explicit-any ErrorClass = errorClassOrMsg as new (...args: any[]) => E; diff --git a/assert/assert_throws_test.ts b/assert/assert_throws_test.ts index 8b245102e..dcf8efd05 100644 --- a/assert/assert_throws_test.ts +++ b/assert/assert_throws_test.ts @@ -127,3 +127,34 @@ Deno.test("assertThrows() matches subclass of expected error", () => { "Fail!", ); }); + +Deno.test("assertThrows() throws when input function does not throw", () => { + assertThrows( + () => { + assertThrows(() => {}); + }, + AssertionError, + "Expected function to throw.", + ); +}); + +Deno.test("assertThrows() throws with custom message", () => { + assertThrows( + () => { + assertThrows(() => {}, "CUSTOM MESSAGE"); + }, + AssertionError, + "Expected function to throw: CUSTOM MESSAGE", + ); +}); + +Deno.test("assertThrows() throws with custom message and no error class", () => { + assertThrows( + () => { + // @ts-expect-error testing invalid input + assertThrows(() => {}, null, "CUSTOM MESSAGE"); + }, + AssertionError, + "Expected function to throw: CUSTOM MESSAGE", + ); +}); diff --git a/assert/equal.ts b/assert/equal.ts index eb94480e8..d0e2c90ed 100644 --- a/assert/equal.ts +++ b/assert/equal.ts @@ -64,10 +64,14 @@ export function equal(c: unknown, d: unknown): boolean { if (!(a instanceof WeakSet && b instanceof WeakSet)) return false; throw new TypeError("cannot compare WeakSet instances"); } + if (a instanceof WeakRef || b instanceof WeakRef) { + if (!(a instanceof WeakRef && b instanceof WeakRef)) return false; + return compare(a.deref(), b.deref()); + } if (seen.get(a) === b) { return true; } - if (Object.keys(a || {}).length !== Object.keys(b || {}).length) { + if (Object.keys(a).length !== Object.keys(b).length) { return false; } seen.set(a, b); @@ -109,10 +113,6 @@ export function equal(c: unknown, d: unknown): boolean { return false; } } - if (a instanceof WeakRef || b instanceof WeakRef) { - if (!(a instanceof WeakRef && b instanceof WeakRef)) return false; - return compare(a.deref(), b.deref()); - } return true; } return false; diff --git a/assert/equal_test.ts b/assert/equal_test.ts index 4a5487b2c..407b1eb72 100644 --- a/assert/equal_test.ts +++ b/assert/equal_test.ts @@ -1,7 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. import { assert, assertFalse, assertThrows, equal } from "./mod.ts"; -Deno.test("EqualDifferentZero", () => { +Deno.test("equal() different zero", () => { assert(equal(0, -0)); assert(equal(0, +0)); assert(equal(+0, -0)); @@ -13,7 +13,7 @@ Deno.test("EqualDifferentZero", () => { assert(equal({ msg: "hello", array: [0] }, { msg: "hello", array: [-0] })); }); -Deno.test("Equal", function () { +Deno.test("equal()", () => { assert(equal("world", "world")); assert(!equal("hello", "world")); assertFalse(equal("hello", "world")); @@ -21,9 +21,13 @@ Deno.test("Equal", function () { assert(!equal(5, 6)); assertFalse(equal(5, 6)); assert(equal(NaN, NaN)); + assert(equal(null, null)); + assertFalse(equal(null, undefined)); assert(equal({ hello: "world" }, { hello: "world" })); assert(!equal({ world: "hello" }, { hello: "world" })); + assertFalse(equal({}, { hello: "world" })); assertFalse(equal({ world: "hello" }, { hello: "world" })); + assertFalse(equal({ hello: "world", world: "hello" }, { world: "hello" })); assert( equal( { hello: "world", hi: { there: "everyone" } }, @@ -251,7 +255,7 @@ Deno.test("Equal", function () { ); }); -Deno.test("EqualCircular", () => { +Deno.test("equal() circular", () => { const objA: { prop?: unknown } = {}; objA.prop = objA; const objB: { prop?: unknown } = {}; @@ -264,3 +268,11 @@ Deno.test("EqualCircular", () => { mapB.set("prop", mapB); assert(equal(mapA, mapB)); }); + +Deno.test("equal() WeakMap, WeakRef and WeakSet", () => { + assertThrows(() => equal(new WeakMap(), new WeakMap())); + assertThrows(() => equal(new WeakSet(), new WeakSet())); + assertFalse(equal(new WeakMap(), { constructor: WeakMap })); + assertFalse(equal(new WeakSet(), { constructor: WeakSet })); + assertFalse(equal(new WeakRef({}), { constructor: WeakRef })); +}); diff --git a/assert/unimplemented_test.ts b/assert/unimplemented_test.ts index c961b1ed1..dee993849 100644 --- a/assert/unimplemented_test.ts +++ b/assert/unimplemented_test.ts @@ -1,14 +1,14 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -import { assert, AssertionError, unimplemented } from "./mod.ts"; +import { AssertionError, assertThrows, unimplemented } from "./mod.ts"; -Deno.test("AssertsUnimplemented", function () { - let didThrow = false; - try { - unimplemented(); - } catch (e) { - assert(e instanceof AssertionError); - assert(e.message === "Unimplemented."); - didThrow = true; - } - assert(didThrow); +Deno.test("unimplemented() throws", function () { + assertThrows(() => unimplemented(), AssertionError, "Unimplemented."); +}); + +Deno.test("unimplemented() throws with custom message", function () { + assertThrows( + () => unimplemented("CUSTOM MESSAGE"), + AssertionError, + "Unimplemented: CUSTOM MESSAGE", + ); }); diff --git a/expect/_assert_equals_test.ts b/expect/_assert_equals_test.ts index d16fb6605..ce84ce9ea 100644 --- a/expect/_assert_equals_test.ts +++ b/expect/_assert_equals_test.ts @@ -139,7 +139,7 @@ Deno.test({ }); Deno.test({ - name: "assertEquals() throws with given custom messages", + name: "assertEquals() throws with custom message", fn() { assertThrows( () => assertEquals(1, 2, { msg: "CUSTOM MESSAGE" }), diff --git a/expect/_to_equal_test.ts b/expect/_to_equal_test.ts index fd3ab3e8b..9a1ce3725 100644 --- a/expect/_to_equal_test.ts +++ b/expect/_to_equal_test.ts @@ -136,7 +136,7 @@ Deno.test({ }); Deno.test({ - name: "expect().toEqual() throws with a custom message", + name: "expect().toEqual() throws with custom message", fn() { assertThrows( () => expect(1, "CUSTOM MESSAGE").toEqual(2), diff --git a/internal/diff.ts b/internal/diff.ts index 520c1fb60..c92ba9f0b 100644 --- a/internal/diff.ts +++ b/internal/diff.ts @@ -338,7 +338,7 @@ export function diffstr(A: string, B: string): DiffResult[] { } // Compute multi-line diff - const diffResult = diff( + const diffResult = _internals.diff( tokenize(`${unescape(A)}\n`), tokenize(`${unescape(B)}\n`), ); @@ -369,7 +369,7 @@ export function diffstr(A: string, B: string): DiffResult[] { tokenize(b?.value ?? "", { wordDiff: true }), ] as [string[], string[]]; if (hasMoreRemovedLines) tokenized.reverse(); - tokens = diff(tokenized[0], tokenized[1]); + tokens = _internals.diff(tokenized[0], tokenized[1]); if ( tokens.some(({ type, value }) => type === DiffType.common && value.trim().length @@ -455,3 +455,5 @@ export function buildMessage( return messages; } + +export const _internals = { diff, diffstr };