// ♓🌟 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 <https://mozilla.org/MPL/2.0/>.
+import {
+ assertEquals,
+ assertStrictEquals,
+ describe,
+ it,
+} from "./dev-deps.js";
import {
composeReference,
escapeForIRI,
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": {
},
};
+// If `path` is non·empty, it must contain an IRI character for tests
+// to pass.
const exampleIRIReferences = {
...exampleURIReferences,
"http://ヒキワリ.ナットウ.ニホン": {
},
};
+// If `path` is non·empty, it must contain an LEIRI character for tests
+// to pass.
const exampleLEIRIReferences = {
...exampleIRIReferences,
"http://example.com/ foo /": {
},
};
+// These will not parse, so the parse result must be empty.
const exampleReferences = {
...exampleLEIRIReferences,
"\uD800": {},
"\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");
"http://a/b/c/g#s/../x",
);
assertStrictEquals(resolveReference("http:g", base), "http:g");
- },
+ });
});