X-Git-Url: https://git.ladys.computer/Pisces/blobdiff_plain/32e1e0ba06627f2ed6c3f99c415ef6b9c0f7de4d..edbef3a179c4404eb02a83860a76c1f11b9b63d2:/iri.test.js diff --git a/iri.test.js b/iri.test.js new file mode 100644 index 0000000..51749cd --- /dev/null +++ b/iri.test.js @@ -0,0 +1,333 @@ +// ♓🌟 Piscēs ∷ iri.test.js +// ==================================================================== +// +// Copyright © 2020–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 { + composeReference, + iri2uri, + isAbsoluteIRI, + isAbsoluteURI, + isIRI, + isIRIReference, + isURI, + isURIReference, + parseReference, + removeDotSegments, + resolveReference, +} from "./iri.js"; +import { + assert, + assertEquals, + assertStrictEquals, +} from "./dev-deps.js"; + +const exampleURIs = { + "ftp://ftp.is.co.za/rfc/rfc1808.txt": { + scheme: "ftp", + authority: "ftp.is.co.za", + path: "/rfc/rfc1808.txt", + }, + "http://www.ietf.org/rfc/rfc2396.txt": { + scheme: "http", + authority: "www.ietf.org", + path: "/rfc/rfc2396.txt", + }, + "ldap://[2001:db8::7]/c=GB?objectClass?one": { + scheme: "ldap", + authority: "[2001:db8::7]", + path: "/c=GB", + query: "objectClass?one", + }, + "mailto:John.Doe@example.com": { + scheme: "mailto", + path: "John.Doe@example.com", + }, + "news:comp.infosystems.www.servers.unix": { + scheme: "news", + path: "comp.infosystems.www.servers.unix", + }, + "tel:+1-816-555-1212": { + scheme: "tel", + path: "+1-816-555-1212", + }, + "telnet://192.0.2.16:80/": { + scheme: "telnet", + authority: "192.0.2.16:80", + path: "/", + }, + "urn:oasis:names:specification:docbook:dtd:xml:4.1.2": { + scheme: "urn", + path: "oasis:names:specification:docbook:dtd:xml:4.1.2", + }, + "foo://example.com:8042/over/there?name=ferret#nose": { + scheme: "foo", + authority: "example.com:8042", + path: "/over/there", + query: "name=ferret", + fragment: "nose", + }, +}; + +const exampleURIReferences = { + ...exampleURIs, + "./this:that": { + path: "./this:that", + }, +}; + +const exampleIRIs = { + ...exampleURIs, + "http://ヒキワリ.ナットウ.ニホン": { + scheme: "http", + authority: "ヒキワリ.ナットウ.ニホン", + path: "", + }, + "http://JP納豆.例.jp/dir1/引き割り.html": { + scheme: "http", + authority: "JP納豆.例.jp", + path: "/dir1/引き割り.html", + }, +}; + +const exampleIRIReferences = { + ...exampleURIReferences, + ...exampleIRIs, +}; + +Deno.test({ + name: "Identifies U·R·Is.", + fn: () => { + for (const uri of Object.keys(exampleURIs)) { + assert(isURI(uri)); + } + }, +}); + +Deno.test({ + name: "Identifies absolute U·R·Is.", + fn: () => { + for (const [uri, { fragment }] of Object.entries(exampleURIs)) { + assertStrictEquals(isAbsoluteURI(uri), fragment == null); + } + }, +}); + +Deno.test({ + name: "Identifies U·R·I references.", + fn: () => { + for (const uri of Object.keys(exampleURIReferences)) { + assert(isURIReference(uri)); + } + }, +}); + +Deno.test({ + name: "Identifies I·R·Is.", + fn: () => { + for (const iri of Object.keys(exampleIRIs)) { + assert(isIRI(iri)); + } + }, +}); + +Deno.test({ + name: "Identifies absolute I·R·Is.", + fn: () => { + for (const [iri, { fragment }] of Object.entries(exampleIRIs)) { + assertStrictEquals(isAbsoluteIRI(iri), fragment == null); + } + }, +}); + +Deno.test({ + name: "Identifies I·R·I references.", + fn: () => { + for (const iri of Object.keys(exampleIRIReferences)) { + assert(isIRIReference(iri)); + } + }, +}); + +Deno.test({ + name: "Correctly parses references.", + fn: () => { + for (const [iri, value] of Object.entries(exampleIRIReferences)) { + assertEquals(parseReference(iri), { + scheme: undefined, + authority: undefined, + path: undefined, + query: undefined, + fragment: undefined, + ...value, + }); + } + }, +}); + +Deno.test({ + name: "Correctly composes references.", + fn: () => { + for (const [iri, value] of Object.entries(exampleIRIReferences)) { + assertStrictEquals(composeReference(value), iri); + } + }, +}); + +Deno.test({ + name: "Converts IRIs to URIs.", + fn: () => { + assertStrictEquals( + iri2uri("/dir1/引き割り.html"), + "/dir1/%E5%BC%95%E3%81%8D%E5%89%B2%E3%82%8A.html", + ); + }, +}); + +Deno.test({ + name: "Correctly removes dot segments.", + fn: () => { + assertStrictEquals(removeDotSegments("/a/b/c/./../../g"), "/a/g"); + assertStrictEquals( + removeDotSegments("mid/content=5/../6"), + "mid/6", + ); + }, +}); + +Deno.test({ + name: "Correctly resolves references.", + fn: () => { + 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"); + assertStrictEquals( + resolveReference("./g", base), + "http://a/b/c/g", + ); + assertStrictEquals( + resolveReference("g/", base), + "http://a/b/c/g/", + ); + assertStrictEquals(resolveReference("/g", base), "http://a/g"); + assertStrictEquals(resolveReference("//g", base), "http://g"); + assertStrictEquals( + resolveReference("?y", base), + "http://a/b/c/d;p?y", + ); + assertStrictEquals( + resolveReference("g?y", base), + "http://a/b/c/g?y", + ); + assertStrictEquals( + resolveReference("#s", base), + "http://a/b/c/d;p?q#s", + ); + assertStrictEquals( + resolveReference("g#s", base), + "http://a/b/c/g#s", + ); + assertStrictEquals( + resolveReference("g?y#s", base), + "http://a/b/c/g?y#s", + ); + assertStrictEquals( + resolveReference(";x", base), + "http://a/b/c/;x", + ); + assertStrictEquals( + resolveReference("g;x", base), + "http://a/b/c/g;x", + ); + assertStrictEquals( + resolveReference("g;x?y#s", base), + "http://a/b/c/g;x?y#s", + ); + assertStrictEquals( + resolveReference("", base), + "http://a/b/c/d;p?q", + ); + assertStrictEquals(resolveReference(".", base), "http://a/b/c/"); + assertStrictEquals(resolveReference("./", base), "http://a/b/c/"); + assertStrictEquals(resolveReference("..", base), "http://a/b/"); + assertStrictEquals(resolveReference("../", base), "http://a/b/"); + assertStrictEquals(resolveReference("../g", base), "http://a/b/g"); + assertStrictEquals(resolveReference("../..", base), "http://a/"); + assertStrictEquals(resolveReference("../../", base), "http://a/"); + assertStrictEquals( + resolveReference("../../g", base), + "http://a/g", + ); + assertStrictEquals( + resolveReference("../../../g", base), + "http://a/g", + ); + assertStrictEquals( + resolveReference("../../../../g", base), + "http://a/g", + ); + assertStrictEquals(resolveReference("/./g", base), "http://a/g"); + assertStrictEquals(resolveReference("/../g", base), "http://a/g"); + assertStrictEquals( + resolveReference("g.", base), + "http://a/b/c/g.", + ); + assertStrictEquals( + resolveReference(".g", base), + "http://a/b/c/.g", + ); + assertStrictEquals( + resolveReference("g..", base), + "http://a/b/c/g..", + ); + assertStrictEquals( + resolveReference("..g", base), + "http://a/b/c/..g", + ); + assertStrictEquals( + resolveReference("./../g", base), + "http://a/b/g", + ); + assertStrictEquals( + resolveReference("./g/.", base), + "http://a/b/c/g/", + ); + assertStrictEquals( + resolveReference("g/./h", base), + "http://a/b/c/g/h", + ); + assertStrictEquals( + resolveReference("g/../h", base), + "http://a/b/c/h", + ); + assertStrictEquals( + resolveReference("g;x=1/./y", base), + "http://a/b/c/g;x=1/y", + ); + assertStrictEquals( + resolveReference("g;x=1/../y", base), + "http://a/b/c/y", + ); + assertStrictEquals( + resolveReference("g?y/./x", base), + "http://a/b/c/g?y/./x", + ); + assertStrictEquals( + resolveReference("g?y/../x", base), + "http://a/b/c/g?y/../x", + ); + assertStrictEquals( + resolveReference("g#s/./x", base), + "http://a/b/c/g#s/./x", + ); + assertStrictEquals( + resolveReference("g#s/../x", base), + "http://a/b/c/g#s/../x", + ); + assertStrictEquals(resolveReference("http:g", base), "http:g"); + }, +});