links.test.ts
4.5 kB · typescript · 120 lines
1import { expect, test } from "bun:test";2import { index, resolve, stamp } from "./links.ts";3import type { Input, Route, Site } from "./build.ts";45/* SITE */67const home = "/repo";8const net = `${home}/site`;910const input = (name: string, path: string): Input => ({ name, path, files: [], missing: false });1112const routes: Route[] = [13 { route: "/research/", kind: "research", source: `${home}/research/README.md` },14 { route: "/research/bases/", kind: "note", source: `${home}/research/bases.md` },15 { route: "/blog/hello/", kind: "post", source: `${net}/blog/hello.md` },16 { route: "/about/", kind: "page", source: `${net}/pages/about.md` },17 { route: "/contact/", kind: "page", source: `${net}/pages/contact.md` },18 {19 route: "/demos/",20 kind: "demos",21 source: `${net}/demos`,22 urls: [{ route: "/demos/spin/", source: `${net}/demos/spin` }],23 },24];2526const code: Route[] = [27 { route: "/git/", kind: "gitdir" },28 { route: "/git/crates/mrly/", kind: "gitdir" },29 { route: "/git/crates/mrly/README.md", kind: "gitfile" },30 { route: "/git/research/lab/walk.rs", kind: "gitfile" },31 { route: "/git/files/figures/carpet.png", kind: "gitfile" },32];3334function site(git: boolean): Site {35 const one = {36 root: net,37 config: { git: git ? { root: "..", slug: "mrlyprod/mrlyprod", branch: "main" } : { root: ".", slug: "acme/site" } },38 inputs: {39 research: input("research", `${home}/research`),40 blog: input("blog", `${net}/blog`),41 pages: input("pages", `${net}/pages`),42 demos: input("demos", `${net}/demos`),43 },44 routes: git ? [...routes, ...code] : routes,45 } as unknown as Site;46 one.index = index(one);47 return one;48}4950const mrly = site(true);5152/* ROUTES */5354test("a note link to a sibling note lands on that note's route", () => {55 expect(resolve(mrly, "research/core.md", "bases.md")).toBe("/research/bases/");56 expect(resolve(mrly, "research/core.md", "README.md")).toBe("/research/");57});5859test("a note link to a demo lands on the demo route", () => {60 expect(resolve(mrly, "research/core.md", "../demos/spin/")).toBe("/demos/spin/");61});6263test("a page link to a page lands on that page's route", () => {64 expect(resolve(mrly, "site/pages/about.md", "contact.md")).toBe("/contact/");65});6667test("a post link to a note lands on the research route", () => {68 expect(resolve(mrly, "site/blog/hello.md", "../../research/bases.md")).toBe("/research/bases/");69});7071test("a fragment and a query ride along", () => {72 expect(resolve(mrly, "research/core.md", "bases.md#lemma")).toBe("/research/bases/#lemma");73 expect(resolve(mrly, "research/core.md", "../demos/spin/?code=7")).toBe("/demos/spin/?code=7");74});7576/* STAMP */7778test("the stamp moves when a route a page could link to disappears", () => {79 const gone = { ...mrly, routes: mrly.routes.filter((one) => one.route !== "/research/bases/") } as Site;80 expect(stamp(index(gone))).not.toBe(stamp(mrly.index!));81});8283test("a source outside the repo never lands in the stamp", () => {84 const away = "/shelf/carpet/README.md";85 const wide = { ...mrly, routes: [...mrly.routes, { route: "/shelf/carpet/", kind: "note", source: away }] } as Site;86 expect(stamp(index(wide))).not.toContain(away);87});8889/* FALLBACK */9091test("a repo file with no route lands on its /git/ page", () => {92 expect(resolve(mrly, "research/core.md", "lab/walk.rs")).toBe("/git/research/lab/walk.rs");93 expect(resolve(mrly, "research/core.md", "../crates/mrly/README.md")).toBe("/git/crates/mrly/README.md");94});9596test("an image with no route lands on its raw bytes", () => {97 expect(resolve(mrly, "research/core.md", "../files/figures/carpet.png")).toBe("/raw/files/figures/carpet.png");98});99100test("an extensionless directory lands on its listing", () => {101 expect(resolve(mrly, "research/core.md", "../crates/mrly")).toBe("/git/crates/mrly/");102});103104test("a path the repo does not carry stays as written", () => {105 expect(resolve(mrly, "research/core.md", "lab/gone.rs")).toBe("lab/gone.rs");106});107108test("a site with no git routes falls to the github blob", () => {109 expect(resolve(site(false), "pages/about.md", "../lib/tree.js")).toBe("https://github.com/acme/site/blob/main/lib/tree.js");110});111112test("an outside link and a rooted link pass through", () => {113 for (const url of ["https://mrly.net", "http://mrly.net", "mailto:help@mrly.net", "tel:+1", "#top", "/demos/"]) {114 expect(resolve(mrly, "research/core.md", url)).toBe(url);115 }116});117118test("a target outside the repo stays as written", () => {119 expect(resolve(mrly, "../shelf/carpet/README.md", "paper.pdf")).toBe("paper.pdf");120});