X-Git-Url: https://git.ladys.computer/Pisces/blobdiff_plain/1c80eb9624a66d32800885321f37c4b05161d607..6e6d4e3261c1c943fe44fa9e381bcf8bf1441fd6:/iri.test.js diff --git a/iri.test.js b/iri.test.js index a586629..f92957d 100644 --- a/iri.test.js +++ b/iri.test.js @@ -1,12 +1,18 @@ // ♓🌟 Piscēs ∷ iri.test.js // ==================================================================== // -// Copyright © 2020–2022 Lady [@ Lady’s Computer]. +// Copyright © 2022 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 // file, You can obtain one at . +import { + assertEquals, + assertStrictEquals, + describe, + it, +} from "./dev-deps.js"; import { composeReference, escapeForIRI, @@ -15,16 +21,22 @@ import { isAbsoluteLEIRI, isAbsoluteURI, isIRI, + isIRIPath, isIRIReference, + isIRISuffix, isLEIRI, + isLEIRIPath, isLEIRIReference, + isLEIRISuffix, isURI, + isURIPath, isURIReference, + isURISuffix, + mergePaths, parseReference, removeDotSegments, resolveReference, } from "./iri.js"; -import { assertEquals, assertStrictEquals } from "./dev-deps.js"; const exampleURIReferences = { "ftp://ftp.is.co.za/rfc/rfc1808.txt": { @@ -76,6 +88,8 @@ const exampleURIReferences = { }, }; +// If `path` is non·empty, it must contain an IRI character for tests +// to pass. const exampleIRIReferences = { ...exampleURIReferences, "http://ヒキワリ.ナットウ.ニホン": { @@ -93,6 +107,8 @@ const exampleIRIReferences = { }, }; +// If `path` is non·empty, it must contain an LEIRI character for tests +// to pass. const exampleLEIRIReferences = { ...exampleIRIReferences, "http://example.com/ foo /": { @@ -105,6 +121,7 @@ const exampleLEIRIReferences = { }, }; +// These will not parse, so the parse result must be empty. const exampleReferences = { ...exampleLEIRIReferences, "\uD800": {}, @@ -112,208 +129,328 @@ const exampleReferences = { "\uFFFF": {}, }; -Deno.test({ - name: "Identifies U·R·Is.", - fn: () => { +describe("composeReference", () => { + it("[[Call]] correctly composes references", () => { for ( - const [uri, { scheme }] of Object.entries(exampleReferences) + const [iri, value] of Object.entries(exampleLEIRIReferences) + ) { + assertStrictEquals(composeReference(value), iri); + } + }); +}); + +describe("escapeForIRI", () => { + it("[[Call]] converts L·E·I·R·Is to I·R·Is", () => { + assertStrictEquals( + escapeForIRI(" æ\0"), + "%20æ%00", + ); + assertStrictEquals( + escapeForIRI("\u{F0000}?\u{F0000}#\u{F0000}"), + "%F3%B0%80%80?\u{F0000}#%F3%B0%80%80", + ); + }); +}); + +describe("escapeForURI", () => { + it("[[Call]] converts L·E·I·R·Is to U·R·Is", () => { + assertStrictEquals( + escapeForURI("/dir1/引き割り.html"), + "/dir1/%E5%BC%95%E3%81%8D%E5%89%B2%E3%82%8A.html", + ); + assertStrictEquals( + escapeForURI(" æ\0"), + "%20%C3%A6%00", + ); + assertStrictEquals( + escapeForURI("\u{F0000}?\u{F0000}#\u{F0000}"), + "%F3%B0%80%80?%F3%B0%80%80#%F3%B0%80%80", + ); + }); +}); + +describe("isAbsoluteIRI", () => { + it("[[Call]] identifies absolute I·R·Is", () => { + for ( + const [iri, { scheme, fragment }] of Object.entries( + exampleReferences, + ) ) { assertStrictEquals( - isURI(uri), - uri in exampleURIReferences && scheme != null, + isAbsoluteIRI(iri), + iri in exampleIRIReferences && scheme != null && + fragment == null, + iri, ); } - }, + }); }); -Deno.test({ - name: "Identifies absolute U·R·Is.", - fn: () => { +describe("isAbsoluteLEIRI", () => { + it("[[Call]] identifies absolute L·E·I·R·Is", () => { for ( - const [uri, { scheme, fragment }] of Object.entries( + const [leiri, { scheme, fragment }] of Object.entries( exampleReferences, ) ) { assertStrictEquals( - isAbsoluteURI(uri), - uri in exampleURIReferences && scheme != null && + isAbsoluteLEIRI(leiri), + leiri in exampleLEIRIReferences && scheme != null && fragment == null, + leiri, ); } - }, + }); }); -Deno.test({ - name: "Identifies U·R·I references.", - fn: () => { - for (const uri of Object.keys(exampleReferences)) { +describe("isAbsoluteURI", () => { + it("[[Call]] identifies absolute U·R·Is", () => { + for ( + const [uri, { scheme, fragment }] of Object.entries( + exampleReferences, + ) + ) { assertStrictEquals( - isURIReference(uri), - uri in exampleURIReferences, + isAbsoluteURI(uri), + uri in exampleURIReferences && scheme != null && + fragment == null, + uri, ); } - }, + }); }); -Deno.test({ - name: "Identifies I·R·Is.", - fn: () => { +describe("isIRI", () => { + it("[[Call]] identifies I·R·Is", () => { for ( const [iri, { scheme }] of Object.entries(exampleReferences) ) { assertStrictEquals( isIRI(iri), iri in exampleIRIReferences && scheme != null, + iri, ); } - }, + }); }); -Deno.test({ - name: "Identifies absolute I·R·Is.", - fn: () => { - for ( - const [iri, { scheme, fragment }] of Object.entries( - exampleReferences, - ) - ) { - assertStrictEquals( - isAbsoluteIRI(iri), - iri in exampleIRIReferences && scheme != null && - fragment == null, - ); +describe("isIRIPath", () => { + it("[[Call]] identifies I·R·I paths", () => { + for (const [iri, { path }] of Object.entries(exampleReferences)) { + if (path === "") { + continue; + } else { + assertStrictEquals( + isIRIPath(path ?? iri), + iri in exampleIRIReferences, + path, + ); + } } - }, + }); }); -Deno.test({ - name: "Identifies I·R·I references.", - fn: () => { +describe("isIRIReference", () => { + it("[[Call]] identifies I·R·I references", () => { for (const iri of Object.keys(exampleReferences)) { assertStrictEquals( isIRIReference(iri), iri in exampleIRIReferences, + iri, ); } - }, + }); +}); + +describe("isIRISuffix", () => { + it("[[Call]] identifies I·R·I suffixes", () => { + for ( + const [iri, { authority, path }] of Object.entries( + exampleReferences, + ) + ) { + if (!authority) { + continue; + } else { + assertStrictEquals( + isIRISuffix(authority + path), + iri in exampleIRIReferences, + path, + ); + } + } + }); }); -Deno.test({ - name: "Identifies L·E·I·R·Is.", - fn: () => { +describe("isLEIRI", () => { + it("[[Call]] identifies L·E·I·R·Is", () => { for ( const [leiri, { scheme }] of Object.entries(exampleReferences) ) { assertStrictEquals( isLEIRI(leiri), leiri in exampleLEIRIReferences && scheme != null, + leiri, ); } - }, + }); }); -Deno.test({ - name: "Identifies absolute L·E·I·R·Is.", - fn: () => { +describe("isLEIRIPath", () => { + it("[[Call]] identifies L·E·I·R·I paths", () => { for ( - const [leiri, { scheme, fragment }] of Object.entries( - exampleReferences, - ) + const [leiri, { path }] of Object.entries(exampleReferences) ) { - assertStrictEquals( - isAbsoluteLEIRI(leiri), - leiri in exampleLEIRIReferences && scheme != null && - fragment == null, - ); + if (path === "") { + continue; + } else { + assertStrictEquals( + isLEIRIPath(path ?? leiri), + leiri in exampleLEIRIReferences, + path, + ); + } } - }, + }); }); -Deno.test({ - name: "Identifies L·E·I·R·I references.", - fn: () => { +describe("isLEIRIReference", () => { + it("[[Call]] identifies L·E·I·R·I references", () => { for (const leiri of Object.keys(exampleReferences)) { assertStrictEquals( isLEIRIReference(leiri), leiri in exampleLEIRIReferences, + leiri, ); } - }, + }); }); -Deno.test({ - name: "Correctly parses references.", - fn: () => { - for (const [iri, value] of Object.entries(exampleReferences)) { - assertEquals(parseReference(iri), { - scheme: undefined, - authority: undefined, - path: undefined, - query: undefined, - fragment: undefined, - ...value, - }); +describe("isLEIRISuffix", () => { + it("[[Call]] identifies L·E·I·R·I suffixes", () => { + for ( + const [leiri, { authority, path }] of Object.entries( + exampleReferences, + ) + ) { + if (!authority) { + continue; + } else { + assertStrictEquals( + isLEIRISuffix(authority + path), + leiri in exampleLEIRIReferences, + path, + ); + } } - }, + }); }); -Deno.test({ - name: "Correctly composes references.", - fn: () => { +describe("isURI", () => { + it("[[Call]] identifies U·R·Is", () => { for ( - const [iri, value] of Object.entries(exampleLEIRIReferences) + const [uri, { scheme }] of Object.entries(exampleReferences) ) { - assertStrictEquals(composeReference(value), iri); + assertStrictEquals( + isURI(uri), + uri in exampleURIReferences && scheme != null, + uri, + ); } - }, + }); }); -Deno.test({ - name: "Converts (L·E·)I·R·Is to U·R·Is.", - fn: () => { - assertStrictEquals( - escapeForURI("/dir1/引き割り.html"), - "/dir1/%E5%BC%95%E3%81%8D%E5%89%B2%E3%82%8A.html", - ); - assertStrictEquals( - escapeForURI(" æ\0"), - "%20%C3%A6%00", - ); - assertStrictEquals( - escapeForURI("\u{F0000}?\u{F0000}#\u{F0000}"), - "%F3%B0%80%80?%F3%B0%80%80#%F3%B0%80%80", - ); - }, +describe("isURIPath", () => { + it("[[Call]] identifies U·R·I paths", () => { + for (const [uri, { path }] of Object.entries(exampleReferences)) { + if (path === "") { + continue; + } else { + assertStrictEquals( + isURIPath(path ?? uri), + uri in exampleURIReferences, + path, + ); + } + } + }); +}); + +describe("isURIReference", () => { + it("[[Call]] identifies U·R·I references", () => { + for (const uri of Object.keys(exampleReferences)) { + assertStrictEquals( + isURIReference(uri), + uri in exampleURIReferences, + uri, + ); + } + }); +}); + +describe("isURISuffix", () => { + it("[[Call]] identifies U·R·I suffixes", () => { + for ( + const [uri, { authority, path }] of Object.entries( + exampleReferences, + ) + ) { + if (!authority) { + continue; + } else { + assertStrictEquals( + isURISuffix(authority + path), + uri in exampleURIReferences, + path, + ); + } + } + }); }); -Deno.test({ - name: "Converts L·E·I·R·Is to I·R·Is.", - fn: () => { +describe("mergePaths", () => { + it("[[Call]] handles the case of an empty base path", () => { assertStrictEquals( - escapeForIRI(" æ\0"), - "%20æ%00", + mergePaths("", "etaoin"), + "/etaoin", ); + }); + + it("[[Call]] handles the case of a non·empty base path", () => { assertStrictEquals( - escapeForIRI("\u{F0000}?\u{F0000}#\u{F0000}"), - "%F3%B0%80%80?\u{F0000}#%F3%B0%80%80", + mergePaths("/etaoin/cmfwyp", "shrdlu"), + "/etaoin/shrdlu", ); - }, + }); +}); + +describe("parseReference", () => { + it("[[Call]] correctly parses references", () => { + for (const [iri, value] of Object.entries(exampleReferences)) { + assertEquals(parseReference(iri), { + scheme: undefined, + authority: undefined, + path: undefined, + query: undefined, + fragment: undefined, + ...value, + }); + } + }); }); -Deno.test({ - name: "Correctly removes dot segments.", - fn: () => { +describe("removeDotSegments", () => { + it("[[Call]] correctly removes dot segments", () => { assertStrictEquals(removeDotSegments("/a/b/c/./../../g"), "/a/g"); assertStrictEquals( removeDotSegments("mid/content=5/../6"), "mid/6", ); - }, + }); }); -Deno.test({ - name: "Correctly resolves references.", - fn: () => { +describe("resolveReference", () => { + it("[[Call]] correctly resolves references", () => { const base = "http://a/b/c/d;p?q"; assertStrictEquals(resolveReference("g:h", base), "g:h"); assertStrictEquals(resolveReference("g", base), "http://a/b/c/g"); @@ -441,5 +578,5 @@ Deno.test({ "http://a/b/c/g#s/../x", ); assertStrictEquals(resolveReference("http:g", base), "http:g"); - }, + }); });