import assert from "node:assert"; import path from "node:path"; import { describe, it, type TestContext } from "node:test"; import { Eta } from "eta"; import { createApp } from "./app.ts"; // The routes exercised here redirect without scraping, so no network is needed. const eta = new Eta({ views: path.join(import.meta.dirname, "..", "views") }); const app = createApp(eta); describe("branch picker", () => { const repo = { owner: "actions", name: "deploy-pages" }; const refs = [{ name: "main", isDefault: true }, { name: "v4" }]; it("should keep the current view and path", () => { const blob = eta.render("_refs.eta", { repo, refs, type: "branches", view: "blob", path: "src/main.ts", }); const tree = eta.render("_refs.eta", { repo, refs, type: "branches", view: "tree", path: "src", }); assert.match(blob, /href="\/actions\/deploy-pages\/blob\/main\/src\/main.ts"/); assert.match(blob, /href="\/actions\/deploy-pages\/blob\/v4\/src\/main.ts"/); assert.match(tree, /href="\/actions\/deploy-pages\/tree\/v4\/src"/); }); it("should link to the root tree without a path", () => { const html = eta.render("_refs.eta", { repo, refs, type: "branches", view: "tree", path: "" }); assert.match(html, /href="\/actions\/deploy-pages\/tree\/main"/); }); it("should not build ref links for views it does not serve", async () => { const res = await app.request("http://cgithub.example/api/a/b/refs/branches/raw/README.md"); assert.strictEqual(res.status, 404); }); it("should tell the refs endpoint where the picker was opened", () => { const nav = { repo, branch: "main", path: "src" }; const blob = eta.render("_nav.eta", { ...nav, view: "blob", path: "src/main.ts" }); assert.match(blob, /data-view="blob" data-path="src\/main.ts"/); assert.match( eta.render("_nav.eta", { ...nav, view: "tree" }), /data-view="tree" data-path="src"/, ); assert.doesNotMatch(eta.render("_nav.eta", { ...nav, view: "tree", path: "" }), /data-path=/); }); }); describe("sidebar fragment", () => { const repo = { owner: "actions", name: "deploy-pages" }; const languages = [{ name: "JavaScript", percentage: 100, color: "#f1e05a" }]; const latestRelease = { tag: "v5.0.0", publishedAt: "2026-03-25T16:59:14Z" }; // The release replaces the empty element it names, beside the release count. it("should render the latest release and the languages", () => { const html = eta.render("_sidebar.eta", { repo, languages, latestRelease }); assert.match(html, /\(2026-03-25<\/time>/); assert.match(html, /
/); }); it("should name a spot the repo page holds open", () => { const html = eta.render("repo.eta", { repo, branch: "main", path: "/", items: [], info: { description: null, website: null, stars: null, forks: null, numReleases: 38 }, }); assert.match(html, /<\/span>/); }); it("should render nothing when the repository has neither", () => { const html = eta.render("_sidebar.eta", { repo, languages: [], latestRelease: null }); assert.strictEqual(html.trim(), ""); }); }); describe("blob view", () => { const blob = { repo: { owner: "justrajdeep", name: "fonts" }, branch: "master", path: "Times New Roman.ttf", language: null, size: "815 KB", image: false, renderFileType: null, textLines: null, htmlLines: null, htmlContent: null, }; it("should embed a PDF", () => { const html = eta.render("blob.eta", { ...blob, path: "test/pdfs/basicapi.pdf", renderFileType: "pdf", }); assert.match(html, /]*type="application\/pdf"/); assert.match(html, /data="\/justrajdeep\/fonts\/embed\/pdf\/master\/test\/pdfs\/basicapi.pdf"/); }); it("should not embed a file type it has no viewer for", () => { const html = eta.render("blob.eta", { ...blob, renderFileType: "stl" }); assert.doesNotMatch(html, / { const html = eta.render("blob.eta", { ...blob, path: "src/app.ts", htmlLines: ['const x;', "x++;"], }); assert.match( html, /const<\/span> x;<\/span>\nx\+\+;<\/span><\/code>/, ); }); it("should give each plain-text line an anchor", () => { const html = eta.render("blob.eta", { ...blob, path: "notes.txt", textLines: ["a < b", "c"], }); assert.match(html, /a < b<\/span>\nc<\/span><\/code>/); }); it("should offer the raw file when there is nothing to display", () => { const html = eta.render("blob.eta", blob); assert.match(html, /This file cannot be displayed\./); assert.match(html, /href="\/justrajdeep\/fonts\/raw\/master\/Times New Roman.ttf">View raw/); }); }); describe("commit history", () => { const repo = { owner: "actions", name: "deploy-pages" }; const oid = "b39c421b98f49d83ae50ec502c3ddfc3bf28f2c6"; const commitGroups = [ { title: "Apr 18, 2023", commits: [ { oid, shortMessage: "Remove deprecated input parameters", authors: [{ login: "jmg" }] }, ], }, ]; const history = { repo, branch: "main", path: "src/index.js", commitGroups }; // A commits payload never says whether its path is a file or a directory, so // every link goes to the tree and GitHub redirects a file's to its blob. it("should browse a file's history at each of its commits", () => { const html = eta.render("commits.eta", history); assert.match(html, new RegExp(`href="/actions/deploy-pages/blob/${oid}/src/index.js">Browse`)); }); it("should browse a directory's history the same way", () => { const html = eta.render("commits.eta", { ...history, path: "src" }); assert.match(html, new RegExp(`href="/actions/deploy-pages/blob/${oid}/src">Browse`)); }); it("should browse the whole repository when the history has no path", () => { const html = eta.render("commits.eta", { ...history, path: "" }); assert.match(html, new RegExp(`href="/actions/deploy-pages/blob/${oid}">Browse`)); }); // Walking up from a history stays in the history, and its last crumb is the // page you are already on, just as a blob or a tree ends on itself. it("should walk up through the history of each parent directory", () => { const html = eta.render("commits.eta", { ...history, path: "src/lib/index.js" }); assert.match(html, /href="\/actions\/deploy-pages\/commits\/main">\(top\)srclib<\/a>\/index\.js/, ); }); it("should say so when a path has no history", () => { const html = eta.render("commits.eta", { ...history, commitGroups: [] }); assert.match(html, /No commits found\./); }); it("should link a blob to its own history", () => { const html = eta.render("blob.eta", { ...history, textLines: ["x"] }); assert.match(html, /href="\/actions\/deploy-pages\/commits\/main\/src\/index.js">History/); }); }); describe("embedded files", () => { function stubGitHub(t: TestContext, body: string, contentType: string, status = 200) { t.mock.method( globalThis, "fetch", async () => new Response(body, { status, headers: { "Content-Type": contentType } }), ); } it("should retype a PDF GitHub sends as a download", async (t) => { stubGitHub(t, "%PDF-1.6", "application/octet-stream"); const res = await app.request("http://cgithub.example/mozilla/pdf.js/embed/pdf/master/doc.pdf"); assert.strictEqual(res.status, 200); assert.strictEqual(res.headers.get("Content-Type"), "application/pdf"); assert.strictEqual(await res.text(), "%PDF-1.6"); }); it("should pass on a type GitHub already got right", async (t) => { stubGitHub(t, "%PDF-1.6", "application/pdf"); const res = await app.request("http://cgithub.example/mozilla/pdf.js/embed/pdf/master/doc.pdf"); assert.strictEqual(res.headers.get("Content-Type"), "application/pdf"); }); it("should not serve a file type it has no viewer for", async (t) => { stubGitHub(t, "