X-Git-Url: https://git.ladys.computer/Pisces/blobdiff_plain/8669d6cba4a0e88ba9fb0e4f9f025bcb417c3cbc..83f6aae0d1b8181dc2b0c6ccdba9f2fe2fdba3e6:/string.test.js diff --git a/string.test.js b/string.test.js index f70faf6..e3d1096 100644 --- a/string.test.js +++ b/string.test.js @@ -1,7 +1,7 @@ // ♓🌟 Piscēs ∷ string.test.js // ==================================================================== // -// Copyright © 2022 Lady [@ Lady’s Computer]. +// Copyright © 2022–2023 Lady [@ Lady’s Computer]. // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -10,10 +10,12 @@ import { assert, assertEquals, + assertSpyCalls, assertStrictEquals, assertThrows, describe, it, + spy, } from "./dev-deps.js"; import { asciiLowercase, @@ -29,6 +31,7 @@ import { splitOnCommas, stripAndCollapseASCIIWhitespace, stripLeadingAndTrailingASCIIWhitespace, + toString, } from "./string.js"; describe("Matcher", () => { @@ -59,6 +62,10 @@ describe("Matcher", () => { assert(new Matcher("") instanceof RegExp); }); + it("[[Construct]] throws when provided with a noncallable, non·null third argument", () => { + assertThrows(() => new Matcher("", undefined, "failure")); + }); + describe("::dotAll", () => { it("[[Get]] returns true when the dotAll flag is present", () => { assertStrictEquals(new Matcher(/(?:)/su).dotAll, true); @@ -75,10 +82,48 @@ describe("Matcher", () => { [...new Matcher(/.(?(?:.(?=.))*)(.)?/u).exec("success")], ["success", "ucces", "s"], ); + assertEquals( + [...new Matcher( + /.(?(?:.(?=.))*)(.)?/u, + undefined, + ($) => $ === "success", + ).exec("success")], + ["success", "ucces", "s"], + ); + }); + + it("[[Call]] calls the constraint if the match succeeds", () => { + const constraint = spy((_) => true); + const matcher = new Matcher("(.).*", undefined, constraint); + const result = matcher.exec({ + toString() { + return "etaoin"; + }, + }); + assertEquals([...result], ["etaoin", "e"]); + assertSpyCalls(constraint, 1); + assertStrictEquals(constraint.calls[0].args[0], "etaoin"); + assertEquals([...constraint.calls[0].args[1]], ["etaoin", "e"]); + assertStrictEquals(constraint.calls[0].args[2], matcher); + assertStrictEquals(constraint.calls[0].self, undefined); + }); + + it("[[Call]] does not call the constraint if the match fails", () => { + const constraint = spy((_) => true); + const matcher = new Matcher("", undefined, constraint); + matcher.exec("failure"); + assertSpyCalls(constraint, 0); }); it("[[Call]] returns null given a partial match", () => { - assertEquals(new Matcher("").exec("failure"), null); + assertStrictEquals(new Matcher("").exec("failure"), null); + }); + + it("[[Call]] returns null if the constraint fails", () => { + assertStrictEquals( + new Matcher(".*", undefined, () => false).exec(""), + null, + ); }); }); @@ -139,6 +184,12 @@ describe("Matcher", () => { }); }); + describe("::toString", () => { + it("[[Get]] does not throw an error", () => { + new Matcher(/(?:)/u).toString(); + }); + }); + describe("::unicode", () => { it("[[Get]] returns true when the unicode flag is present", () => { assertStrictEquals(new Matcher(/(?:)/u).unicode, true); @@ -149,12 +200,43 @@ describe("Matcher", () => { it("[[Call]] returns true for a complete match", () => { assertStrictEquals(new Matcher("")(""), true); assertStrictEquals(new Matcher(/.*/su)("success\nyay"), true); + assertStrictEquals( + new Matcher(/.*/su, undefined, ($) => $ === "success")( + "success", + ), + true, + ); + }); + + it("[[Call]] calls the constraint if the match succeeds", () => { + const constraint = spy((_) => true); + const matcher = new Matcher("(.).*", undefined, constraint); + matcher("etaoin"); + assertSpyCalls(constraint, 1); + assertStrictEquals(constraint.calls[0].args[0], "etaoin"); + assertEquals([...constraint.calls[0].args[1]], ["etaoin", "e"]); + assertStrictEquals(constraint.calls[0].args[2], matcher); + assertStrictEquals(constraint.calls[0].self, undefined); + }); + + it("[[Call]] does not call the constraint if the match fails", () => { + const constraint = spy((_) => true); + const matcher = new Matcher("", undefined, constraint); + matcher("failure"); + assertSpyCalls(constraint, 0); }); it("[[Call]] returns false for a partial match", () => { assertStrictEquals(new Matcher("")("failure"), false); assertStrictEquals(new Matcher(/.*/u)("failure\nno"), false); }); + + it("[[Call]] returns false if the constraint fails", () => { + assertStrictEquals( + new Matcher(".*", undefined, () => false)(""), + false, + ); + }); }); describe("~lastIndex", () => { @@ -529,3 +611,20 @@ describe("stripLeadingAndTrailingASCIIWhitespace", () => { ); }); }); + +describe("toString", () => { + it("[[Call]] converts to a string", () => { + assertStrictEquals( + toString({ + toString() { + return "success"; + }, + }), + "success", + ); + }); + + it("[[Call]] throws when provided a symbol", () => { + assertThrows(() => toString(Symbol())); + }); +});