From c2d9d01ec7934965e7b7ca0d41c9e8a6063095f5 Mon Sep 17 00:00:00 2001 From: Milly Date: Mon, 12 Aug 2024 19:28:02 +0900 Subject: [PATCH 1/8] test[stringify]: clarify test messages --- _testutil.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/_testutil.ts b/_testutil.ts index e323b78..622a78e 100644 --- a/_testutil.ts +++ b/_testutil.ts @@ -57,6 +57,8 @@ export type Equal = (() => T extends X ? 1 : 2) extends export function stringify(x: unknown): string { if (x instanceof Date) return `Date(${x.valueOf()})`; if (x instanceof Promise) return "Promise"; + if (x instanceof Set) return `Set(${stringify([...x.values()])})`; + if (x instanceof Map) return `Map(${stringify([...x.entries()])})`; if (typeof x === "function") return x.toString(); if (typeof x === "bigint") return `${x}n`; if (typeof x === "symbol") return x.toString(); From 5bbc8796c15aa29f33dcbca09e6f2688824ea279 Mon Sep 17 00:00:00 2001 From: Milly Date: Mon, 12 Aug 2024 18:24:12 +0900 Subject: [PATCH 2/8] test[isParametersOf]: add proper true/false cases --- is/parameters_of_test.ts | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/is/parameters_of_test.ts b/is/parameters_of_test.ts index 478d806..6bf5840 100644 --- a/is/parameters_of_test.ts +++ b/is/parameters_of_test.ts @@ -35,11 +35,13 @@ Deno.test("isParametersOf", async (t) => { const predTup = [is.Number, is.String, as.Optional(is.Boolean)] as const; assertEquals(isParametersOf(predTup)([0, "a", true]), true); assertEquals(isParametersOf(predTup)([0, "a"]), true); + assertEquals(isParametersOf(predTup)([0, "a", undefined]), true); }); await t.step("returns false on non T tuple", () => { const predTup = [is.Number, is.String, as.Optional(is.Boolean)] as const; assertEquals(isParametersOf(predTup)([0, 1, 2]), false); + assertEquals(isParametersOf(predTup)([0]), false); assertEquals(isParametersOf(predTup)([0, "a", true, 0]), false); }); @@ -107,17 +109,42 @@ Deno.test("isParametersOf", async (t) => { await t.step("returns false on non T tuple", () => { const predTup = [is.Number, is.String, as.Optional(is.Boolean)] as const; const predRest = is.ArrayOf(is.String); - assertEquals(isParametersOf(predTup, predRest)([0, 1, 2, 0, 1, 2]), false); - assertEquals(isParametersOf(predTup, predRest)([0, "a", 0, 1, 2]), false); + assertEquals(isParametersOf(predTup, predRest)("a"), false, "Not an array"); + assertEquals( + isParametersOf(predTup, predRest)([0]), + false, + "Less than `predTup.length` - optional-count", + ); + assertEquals( + isParametersOf(predTup, predRest)([0, 1, 2]), + false, + "Not match `predTup` and no rest elements", + ); + assertEquals( + isParametersOf(predTup, predRest)([0, 1, 2, 0, 1, 2]), + false, + "Not match `predTup` and `predRest`", + ); assertEquals( isParametersOf(predTup, predRest)([0, "a", true, 0, 1, 2]), false, + "Match `predTup` but not match `predRest`", ); assertEquals( isParametersOf(predTup, predRest)([0, "a", undefined, 0, 1, 2]), false, + "Match `predTup` but not match `predRest`", + ); + assertEquals( + isParametersOf(predTup, predRest)([0, "a", "b", "a", "b", "c"]), + false, + "Match `predRest` but not match `predTup`", + ); + assertEquals( + isParametersOf(predTup, predRest)([0, "a", "a", "b", "c"]), + false, + "Match `predRest` but no optional parameters", ); - assertEquals(isParametersOf(predTup, predRest)([0, "a", "b"]), false); }); await t.step("predicated type is correct", () => { From 38b8807e367296b2dee0a4928e63d92ad985ca68 Mon Sep 17 00:00:00 2001 From: Milly Date: Mon, 12 Aug 2024 18:26:47 +0900 Subject: [PATCH 3/8] test[isSetOf]: add proper false cases --- is/set_of_test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/is/set_of_test.ts b/is/set_of_test.ts index 84498b4..b009562 100644 --- a/is/set_of_test.ts +++ b/is/set_of_test.ts @@ -18,6 +18,7 @@ Deno.test("isSetOf", async (t) => { }); await t.step("returns false on non T set", () => { + assertEquals(isSetOf(is.String)("a"), false, "Not a Set"); assertEquals(isSetOf(is.String)(new Set([0, 1, 2])), false); assertEquals(isSetOf(is.Number)(new Set(["a", "b", "c"])), false); assertEquals(isSetOf(is.String)(new Set([true, false, true])), false); From 40d20921b8875c88e44cbcd60b4b7bcb7f5e9454 Mon Sep 17 00:00:00 2001 From: Milly Date: Mon, 12 Aug 2024 19:39:40 +0900 Subject: [PATCH 4/8] test[isRecordOf]: add proper false cases --- is/record_of_test.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/is/record_of_test.ts b/is/record_of_test.ts index a91fc33..81d68f7 100644 --- a/is/record_of_test.ts +++ b/is/record_of_test.ts @@ -18,6 +18,7 @@ Deno.test("isRecordOf", async (t) => { }); await t.step("returns false on non T record", () => { + assertEquals(isRecordOf(is.String)("a"), false, "Not a Record"); assertEquals(isRecordOf(is.String)({ a: 0 }), false); assertEquals(isRecordOf(is.Number)({ a: "a" }), false); assertEquals(isRecordOf(is.String)({ a: true }), false); @@ -85,6 +86,7 @@ Deno.test("isRecordOf", async (t) => { }); await t.step("returns false on non T record", () => { + assertEquals(isRecordOf(is.String, is.String)("a"), false, "Not a Record"); assertEquals(isRecordOf(is.String, is.String)({ a: 0 }), false); assertEquals(isRecordOf(is.Number, is.String)({ a: "a" }), false); assertEquals(isRecordOf(is.String, is.String)({ a: true }), false); @@ -158,6 +160,11 @@ Deno.test("isRecordOf", async (t) => { }); await t.step("returns false on non T record", () => { + assertEquals( + isRecordOf(is.String, is.Symbol)("a"), + false, + "Not a Record", + ); assertEquals(isRecordOf(is.String, is.Symbol)({ [a]: 0 }), false); assertEquals(isRecordOf(is.Number, is.Symbol)({ [a]: "a" }), false); assertEquals(isRecordOf(is.String, is.Symbol)({ [a]: true }), false); From 10e6391d9794260d3568699504d939d7932ab630 Mon Sep 17 00:00:00 2001 From: Milly Date: Mon, 12 Aug 2024 19:46:21 +0900 Subject: [PATCH 5/8] test[isRecordObjectOf]: add proper false cases --- is/record_object_of_test.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/is/record_object_of_test.ts b/is/record_object_of_test.ts index 7ece23f..ba9f7ba 100644 --- a/is/record_object_of_test.ts +++ b/is/record_object_of_test.ts @@ -18,6 +18,7 @@ Deno.test("isRecordObjectOf", async (t) => { }); await t.step("returns false on non T record", () => { + assertEquals(isRecordObjectOf(is.String)("a"), false, "Not a Record"); assertEquals(isRecordObjectOf(is.String)({ a: 0 }), false); assertEquals(isRecordObjectOf(is.Number)({ a: "a" }), false); assertEquals(isRecordObjectOf(is.String)({ a: true }), false); @@ -91,6 +92,11 @@ Deno.test("isRecordObjectOf", async (t) => { }); await t.step("returns false on non K record", () => { + assertEquals( + isRecordObjectOf(is.String, is.String)("a"), + false, + "Not a Record", + ); assertEquals(isRecordObjectOf(is.Number, is.Number)({ a: 0 }), false); assertEquals(isRecordObjectOf(is.String, is.Number)({ a: "a" }), false); assertEquals(isRecordObjectOf(is.Boolean, is.Number)({ a: true }), false); @@ -161,6 +167,11 @@ Deno.test("isRecordObjectOf", async (t) => { }); await t.step("returns false on non T record", () => { + assertEquals( + isRecordObjectOf(is.String, is.Symbol)("a"), + false, + "Not a Record", + ); assertEquals(isRecordObjectOf(is.String, is.Symbol)({ [a]: 0 }), false); assertEquals(isRecordObjectOf(is.Number, is.Symbol)({ [a]: "a" }), false); assertEquals( From 3d2cf21ca27a3e80acac4f6b404c5e60030f14de Mon Sep 17 00:00:00 2001 From: Milly Date: Mon, 12 Aug 2024 20:06:13 +0900 Subject: [PATCH 6/8] test[assert]: add message test for anonymous predicate --- assert_test.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/assert_test.ts b/assert_test.ts index 3840b64..ee96eb2 100644 --- a/assert_test.ts +++ b/assert_test.ts @@ -29,6 +29,17 @@ Deno.test("assert", async (t) => { ); }); + await t.step( + "throws an `AssertError` on false predicate with an anonymous predicate", + () => { + assertThrows( + () => assert(x, (_x: unknown): _x is string => false), + AssertError, + `Expected a value that satisfies the predicate anonymous predicate, got symbol: undefined`, + ); + }, + ); + await t.step( "throws an `AssertError` on false predicate with a custom name", () => { From f2f7d3d76008d1f3c13b4623b0699fef4df5480b Mon Sep 17 00:00:00 2001 From: Milly Date: Mon, 12 Aug 2024 21:09:57 +0900 Subject: [PATCH 7/8] test[hasOptional]: add tests --- as/optional_test.ts | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/as/optional_test.ts b/as/optional_test.ts index f1e73a4..4fe66bf 100644 --- a/as/optional_test.ts +++ b/as/optional_test.ts @@ -2,7 +2,8 @@ import { assertEquals } from "@std/assert"; import { assertType } from "@std/testing/types"; import { type Equal, testWithExamples } from "../_testutil.ts"; import { is } from "../is/mod.ts"; -import { asOptional, asUnoptional } from "./optional.ts"; +import type { AsOptional } from "../_annotation.ts"; +import { asOptional, asUnoptional, hasOptional } from "./optional.ts"; Deno.test("asOptional", async (t) => { await t.step("returns a property named predicate function", () => { @@ -153,3 +154,23 @@ Deno.test("asUnoptional", async (t) => { }); }); }); + +Deno.test("hasOptional

", async (t) => { + await t.step("returns true on AsOptional predicate", () => { + const pred = asOptional(is.Number); + assertEquals(hasOptional(pred), true); + }); + + await t.step("returns true on non AsOptional predicate", () => { + const pred = is.Number; + assertEquals(hasOptional(pred), false); + }); + + await t.step("predicated type is correct", () => { + const pred = asOptional(is.Number); + type P = typeof pred; + if (hasOptional(pred)) { + assertType>>(true); + } + }); +}); From 20a84c2782b0578ce553ddef349545f7b5be1720 Mon Sep 17 00:00:00 2001 From: Milly Date: Mon, 12 Aug 2024 21:10:16 +0900 Subject: [PATCH 8/8] test[hasReadonly]: add tests --- as/readonly_test.ts | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/as/readonly_test.ts b/as/readonly_test.ts index 2bc6dd2..820086d 100644 --- a/as/readonly_test.ts +++ b/as/readonly_test.ts @@ -2,7 +2,8 @@ import { assertEquals } from "@std/assert"; import { assertType } from "@std/testing/types"; import { type Equal, testWithExamples } from "../_testutil.ts"; import { is } from "../is/mod.ts"; -import { asReadonly, asUnreadonly } from "./readonly.ts"; +import type { AsReadonly } from "../_annotation.ts"; +import { asReadonly, asUnreadonly, hasReadonly } from "./readonly.ts"; Deno.test("asReadonly", async (t) => { await t.step("returns a property named predicate function", () => { @@ -155,3 +156,23 @@ Deno.test("asUnreadonly", async (t) => { }); }); }); + +Deno.test("hasReadonly

", async (t) => { + await t.step("returns true on AsReadonly predicate", () => { + const pred = asReadonly(is.Number); + assertEquals(hasReadonly(pred), true); + }); + + await t.step("returns true on non AsReadonly predicate", () => { + const pred = is.Number; + assertEquals(hasReadonly(pred), false); + }); + + await t.step("predicated type is correct", () => { + const pred = asReadonly(is.Number); + type P = typeof pred; + if (hasReadonly(pred)) { + assertType>(true); + } + }); +});