// node --test site/: the update feed's notes follow the app's language // (freecss on Discord). GitHub and the edge cache are stood in for. import { test } from "node:test"; import assert from "node:assert/strict"; import worker, { served, goTarget } from "./worker.js"; const EN = "### Features\n\n- One thing (#1)\n\n### Install\n\nDownload it."; const ZH = "### 新功能\n\n- 一件事 (#1)"; const BODIES = { "v0.1.3": `${EN}\n\n\n\n${ZH}\n`, "v0.1.2": "### Fixes\n\n- Older, English alone", "v0.1.1": "- first", }; const store = new Map(); globalThis.caches = { default: { match: async (req) => (store.has(req.url) ? new Response(store.get(req.url)) : undefined), put: async (req, res) => void store.set(req.url, await res.text()), }, }; // apiDown stands in for GitHub's API limiting the worker's shared IP (#661); // pagesDown for github.com itself failing too. seen keeps each API ask's // headers. let apiDown = false, pagesDown = false; const seen = []; const FEED = ` tag:github.com,2008:Repository/1/v0.1.3 2026-10-03T08:54:51Z magpie v0.1.3 <h3>Features</h3> <ul> <li>One thing (#1)</li> </ul> <h3>Install</h3> <p>Download it.</p> <h3>新功能</h3> <ul> <li>一件事 (#1)</li> </ul> tag:github.com,2008:Repository/1/v0.1.2 2026-10-02T08:54:51Z <h3>Fixes</h3> <ul> <li>Older, <strong>English</strong> alone, <code>a &amp;lt; b</code> <a href="https://x.dev/">link</a></li> </ul> `; // what the worker sent PostHog const captured = []; globalThis.fetch = async (u, init = {}) => { u = String(u); if (u === "https://us.i.posthog.com/i/v0/e/") { captured.push(JSON.parse(init.body)); return new Response("{}"); } if (u.startsWith("https://api.github.com/")) { seen.push(new Headers(init.headers)); if (apiDown) return new Response('{"message":"API rate limit exceeded"}', { status: 403 }); } else if (pagesDown) return new Response("unicorn", { status: 503 }); if (u === "https://github.com/yetone/magpie-releases/releases/latest") return new Response(null, { status: 302, headers: { Location: "https://github.com/yetone/magpie-releases/releases/tag/v0.1.3" } }); if (u.endsWith("/releases.atom")) return new Response(FEED); const gh = (tag) => ({ tag_name: tag, body: BODIES[tag], html_url: "https://github.com/r/" + tag, published_at: "2026-10-01T00:00:00Z", draft: false, prerelease: false, assets: [{ name: "magpie-linux-amd64", size: 1, browser_download_url: "https://dl/x" }] }); if (u.endsWith("/releases/latest")) return Response.json(gh("v0.1.3")); if (u.includes("/releases?per_page=")) return Response.json(Object.keys(BODIES).map(gh)); if (u.endsWith("/SHA256SUMS")) return new Response("abc magpie-linux-amd64\n"); return new Response("not found", { status: 404 }); }; const ctx = { waitUntil: (p) => p }; const get = async (path) => { const res = await worker.fetch(new Request("https://usemagpie.ai" + path), {}, ctx); assert.equal(res.status, 200, path); return { body: await res.json(), cc: res.headers.get("Cache-Control") }; }; test("latest: the English alone without lang, the Chinese with zh", async () => { for (const q of ["", "?lang=en", "?lang=fr"]) { const { body, cc } = await get("/api/latest" + q); assert.equal(body.version, "0.1.3"); assert.equal(body.notes, EN, q); assert.match(cc, /max-age=/); } for (const q of ["?lang=zh", "?lang=zh-CN", "?lang=zh_Hans"]) { assert.equal((await get("/api/latest" + q)).body.notes, ZH, q); } // asked in Chinese first, the edge's copy still has both assert.equal((await get("/api/latest")).body.notes, EN); }); test("notes: each release in the language, English where it has no Chinese", async () => { const zh = (await get("/api/notes?after=0.1.1&upto=0.1.3&lang=zh")).body.releases; assert.deepEqual(zh.map((r) => [r.version, r.notes]), [["0.1.3", ZH], ["0.1.2", BODIES["v0.1.2"]]]); const en = (await get("/api/notes?after=0.1.1&upto=0.1.3")).body.releases; assert.deepEqual(en.map((r) => [r.version, r.notes]), [["0.1.3", EN], ["0.1.2", BODIES["v0.1.2"]]]); const again = (await get("/api/notes?after=0.1.1&upto=0.1.3&lang=zh")).body.releases; assert.equal(again[0].notes, ZH); }); test("i18n: every string the home page marks has its Chinese, and no other", async () => { const { readFile } = await import("node:fs/promises"); const { LANGS } = await import("./i18n.js"); const html = await readFile(new URL("./public/index.html", import.meta.url), "utf8"); const keys = new Set(); for (const [, k] of html.matchAll(/data-i18n="([^"]+)"/g)) keys.add(k); for (const [, pairs] of html.matchAll(/data-i18n-attr="([^"]+)"/g)) for (const p of pairs.split(",")) keys.add(p.split(":")[1]); for (const [lang, { dict }] of Object.entries(LANGS)) { assert.deepEqual([...keys].filter((k) => !(k in dict)), [], `${lang} lacks`); assert.deepEqual(Object.keys(dict).filter((k) => !keys.has(k)), [], `${lang} has unused`); } }); test("home: / sends a browser that prefers Chinese, Japanese or German to its page, until a language is picked", async () => { const env = { ASSETS: { fetch: async () => new Response("", { headers: { "Content-Type": "text/plain" } }) } }; const home = (headers) => worker.fetch(new Request("https://usemagpie.ai/", { headers }), env, ctx); const to = async (headers) => { const res = await home(headers); assert.match(res.headers.get("Vary") || "", /Accept-Language/); return res.status === 302 ? res.headers.get("Location") : null; }; assert.equal(await to({}), null); assert.equal(await to({ "Accept-Language": "en-US,en;q=0.9,zh;q=0.8" }), null); assert.equal(await to({ "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8" }), "/zh/"); assert.equal(await to({ "Accept-Language": "zh-TW" }), "/zh/"); assert.equal(await to({ "Accept-Language": "fr-FR,zh;q=0.5,en;q=0.4" }), "/zh/"); assert.equal(await to({ "Accept-Language": "en;q=0.2,zh;q=0.8" }), "/zh/"); assert.equal(await to({ "Accept-Language": "zh-CN", Cookie: "a=b; lang=en" }), null); assert.equal(await to({ Cookie: "lang=zh" }), "/zh/"); assert.equal(await to({ "Accept-Language": "ja-JP,ja;q=0.9,en;q=0.8" }), "/ja/"); assert.equal(await to({ "Accept-Language": "ja", Cookie: "lang=zh" }), "/zh/"); assert.equal(await to({ Cookie: "lang=ja" }), "/ja/"); assert.equal(await to({ "Accept-Language": "de-DE,de;q=0.9,en;q=0.8" }), "/de/"); assert.equal(await to({ "Accept-Language": "de-AT" }), "/de/"); assert.equal(await to({ "Accept-Language": "de", Cookie: "lang=en" }), null); assert.equal(await to({ Cookie: "lang=de" }), "/de/"); for (const lang of ["zh", "de"]) { const res = await worker.fetch(new Request("https://usemagpie.ai/" + lang), env, ctx); assert.equal(res.status, 301); assert.equal(new URL(res.headers.get("Location")).pathname, `/${lang}/`); } }); test("docs: the bare docs paths open each language's guide", async () => { const env = { ASSETS: { fetch: async () => new Response("asset") } }; for (const [from, to] of [["/docs", "/docs/start"], ["/docs/zh/", "/docs/zh/start"], ["/docs/ja", "/docs/ja/start"]]) { const res = await worker.fetch(new Request("https://usemagpie.ai" + from), env, ctx); assert.equal(new URL(res.headers.get("Location"), "https://usemagpie.ai").pathname, to, from); } }); // #661: the update window showed no notes while GitHub's API limited the // worker, and the failure was kept for five minutes. const ask = (path, env = {}) => worker.fetch(new Request("https://usemagpie.ai" + path), env, ctx); test("latest: with the API limited, the notes come from the releases feed, kept briefly", async () => { store.clear(); apiDown = true; try { const res = await ask("/api/latest"); assert.equal(res.status, 200); const body = await res.json(); assert.equal(body.version, "0.1.3"); assert.match(body.notes, /One thing \(#1\)/); assert.doesNotMatch(body.notes, /一件事/); assert.equal(body.assets["magpie-linux-amd64"].sha256, "abc"); assert.equal(res.headers.get("Cache-Control"), "public, max-age=60"); const zh = await (await ask("/api/latest?lang=zh")).json(); assert.match(zh.notes, /^### 新功能\n\n- 一件事 \(#1\)$/); } finally { apiDown = false; } }); test("notes: with the API limited, the releases feed's notes, in either language", async () => { store.clear(); apiDown = true; try { const res = await ask("/api/notes?after=0.1.1&upto=0.1.3&lang=zh"); assert.equal(res.status, 200); assert.equal(res.headers.get("Cache-Control"), "public, max-age=60"); const list = (await res.json()).releases; assert.deepEqual(list.map((r) => r.version), ["0.1.3", "0.1.2"]); assert.equal(list[0].notes, "### 新功能\n\n- 一件事 (#1)"); assert.equal(list[1].notes, "### Fixes\n\n- Older, **English** alone, `a < b` [link](https://x.dev/)"); assert.equal(list[0].url, "https://github.com/yetone/magpie-releases/releases/tag/v0.1.3"); } finally { apiDown = false; } }); test("notes and latest: GitHub failing altogether is an error never kept, then the last whole answer", async () => { store.clear(); apiDown = pagesDown = true; try { for (const path of ["/api/notes?upto=0.1.3", "/api/latest"]) { const res = await ask(path); assert.equal(res.status, 503, path); assert.equal(res.headers.get("Cache-Control"), "no-store", path); } // a whole answer once, then GitHub fails again: that one, kept briefly apiDown = pagesDown = false; assert.equal((await ask("/api/notes?upto=0.1.3")).headers.get("Cache-Control"), "public, max-age=300"); assert.equal((await ask("/api/latest")).status, 200); for (const k of ["https://usemagpie.ai/__v2/releases", "https://usemagpie.ai/__v2/latest"]) store.delete(k); apiDown = pagesDown = true; const res = await ask("/api/notes?upto=0.1.3"); assert.equal(res.status, 200); assert.equal(res.headers.get("Cache-Control"), "public, max-age=60"); assert.equal((await res.json()).releases[0].notes, EN); const lat = await ask("/api/latest"); assert.equal(lat.status, 200); assert.equal((await lat.json()).notes, EN); } finally { apiDown = pagesDown = false; } }); test("api: a GITHUB_TOKEN secret is sent to GitHub's API, and none without it", async () => { store.clear(); seen.length = 0; await ask("/api/notes?upto=0.1.3", { GITHUB_TOKEN: "ghp_x" }); assert.equal(seen.at(-1).get("Authorization"), "Bearer ghp_x"); store.clear(); await ask("/api/notes?upto=0.1.3"); assert.equal(seen.at(-1).get("Authorization"), null); }); test("cache: what an older worker kept, in its own shape, is never read as this one's", async () => { store.clear(); store.set("https://usemagpie.ai/__latest", JSON.stringify({ version: "0.1.1", notes: "", assets: {} })); store.set("https://usemagpie.ai/__releases", JSON.stringify([{ version: "0.1.1", notes: "old" }])); store.set("https://usemagpie.ai/__v2/latest", JSON.stringify({ version: "0.1.1" })); store.set("https://usemagpie.ai/__v2/releases", JSON.stringify([{ version: "0.1.1" }])); const notes = await ask("/api/notes?upto=0.1.3"); assert.equal(notes.status, 200); assert.equal((await notes.json()).releases[0].version, "0.1.3"); const lat = await ask("/api/latest"); assert.equal(lat.status, 200); assert.equal((await lat.json()).version, "0.1.3"); }); test("download: a platform's link goes to that asset of the latest release", async () => { const res = await ask("/download/linux"); assert.equal(res.status, 302); assert.equal(res.headers.get("Location"), "https://dl/x"); assert.equal((await ask("/download/nothing-like-it")).status, 404); }); test("docs: an English docs page sends a browser that prefers Chinese or Japanese to its own, until a language is picked", async () => { const have = new Set(["/docs/start", "/docs/zh/start", "/docs/ja/start", "/docs/only-en"]); const env = { ASSETS: { fetch: async (r) => new Response(have.has(new URL(r.url).pathname) ? "" : "nf", { status: have.has(new URL(r.url).pathname) ? 200 : 404, headers: { "Content-Type": "text/plain" } }) } }; const to = async (path, headers) => { const res = await worker.fetch(new Request("https://usemagpie.ai" + path, { headers }), env, ctx); assert.match(res.headers.get("Vary") || "", /Accept-Language/); return res.status === 302 ? res.headers.get("Location") : res.status; }; assert.equal(await to("/docs/start", {}), 200); assert.equal(await to("/docs/start", { "Accept-Language": "en-US,en;q=0.9,zh;q=0.8" }), 200); assert.equal(await to("/docs/start", { "Accept-Language": "zh-CN,zh;q=0.9" }), "/docs/zh/start"); assert.equal(await to("/docs/start?omarchy=1", { "Accept-Language": "ja-JP" }), "/docs/ja/start?omarchy=1"); assert.equal(await to("/docs/start", { "Accept-Language": "zh-CN", Cookie: "lang=en" }), 200); assert.equal(await to("/docs/start", { Cookie: "lang=ja" }), "/docs/ja/start"); // German has no docs: English assert.equal(await to("/docs/start", { "Accept-Language": "de-DE" }), 200); // a page not written in Chinese yet assert.equal(await to("/docs/only-en", { "Accept-Language": "zh-CN" }), 200); // a language's own page is never moved const res = await worker.fetch(new Request("https://usemagpie.ai/docs/zh/start", { headers: { Cookie: "lang=en" } }), env, ctx); assert.equal(res.status, 200); }); // /api/partners is partners.js, cached ten minutes; every entry keeps the // rules the app checks (internal/provider/partners.go), so none is dropped // there unseen. test("partners", async () => { const { PARTNERS } = await import("./partners.js"); const res = await ask("/api/partners"); assert.equal(res.status, 200); assert.equal(res.headers.get("Cache-Control"), "public, max-age=600"); const { partners } = await res.json(); assert.deepEqual(partners, served(PARTNERS, Date.now())); assert(partners.length <= 12); const ids = new Set(); for (const p of PARTNERS) { assert.match(p.id, /^[a-z0-9][a-z0-9-]{1,40}$/, p.id); assert(!ids.has(p.id), p.id + " twice"); ids.add(p.id); assert(p.name?.trim(), p.id + " has no name"); assert(p.chat || p.responses || p.anthropic || p.regions?.length, p.id + " has no endpoint"); const urls = [p.chat, p.responses, p.anthropic, p.website, p.keysUrl, p.iconUrl, ...(p.regions || []).flatMap((r) => [r.chat, r.responses, r.anthropic, r.keysUrl, r.website])]; for (const u of urls.filter(Boolean)) assert.equal(new URL(u).protocol, "https:", p.id + ": " + u); for (const t of [p.from, p.until].filter(Boolean)) assert(!isNaN(Date.parse(t)), p.id + ": " + t); } }); // The website and key links the app gets go through /go, which counts the // click and sends the browser on; one whose term ended leaves the list but // its links, kept in the providers added from it, still go. const LIST = [ { id: "acme", name: "Acme", chat: "https://api.acme.example/v1", website: "https://acme.example/", keysUrl: "https://acme.example/keys", iconUrl: "https://acme.example/i.png", regions: [{ id: "cn", name: "China", chat: "https://cn.acme.example/v1", keysUrl: "https://cn.acme.example/keys" }, { id: "us east", name: "US", chat: "https://us.acme.example/v1" }] }, { id: "plain", name: "Plain", chat: "https://api.plain.example/v1" }, { id: "gone", name: "Gone", chat: "https://api.gone.example/v1", keysUrl: "https://gone.example/keys", until: "2026-01-01T00:00:00Z" }, ]; const NOW = Date.parse("2026-10-10T00:00:00Z"); test("partners: links go through /go", () => { const out = served(LIST, NOW); assert.deepEqual(out.map((p) => p.id), ["acme", "plain"]); const [acme, plain] = out; assert.equal(acme.website, "https://usemagpie.ai/go/acme/site"); assert.equal(acme.keysUrl, "https://usemagpie.ai/go/acme/keys"); assert.equal(acme.iconUrl, LIST[0].iconUrl); assert.equal(acme.chat, LIST[0].chat); assert.equal(acme.regions[0].keysUrl, "https://usemagpie.ai/go/acme/keys/cn"); assert.equal(acme.regions[0].website, undefined); assert.equal(acme.regions[1].keysUrl, undefined); assert.deepEqual(plain, LIST[1]); // partners.js itself is left as it is assert.equal(LIST[0].keysUrl, "https://acme.example/keys"); assert.equal(served([{ ...LIST[0], until: "2026-10-10T00:00:01Z" }], NOW).length, 1); }); test("partners: /go sends the browser on, saying it came from magpie", () => { assert.equal(goTarget(LIST, "acme", "keys"), "https://acme.example/keys?ref=magpie"); assert.equal(goTarget(LIST, "acme", "site"), "https://acme.example/?ref=magpie"); assert.equal(goTarget(LIST, "acme", "keys", "cn"), "https://cn.acme.example/keys?ref=magpie"); // a region without its own page has the partner's assert.equal(goTarget(LIST, "acme", "keys", "us east"), "https://acme.example/keys?ref=magpie"); assert.equal(goTarget(LIST, "acme", "site", "cn"), "https://acme.example/?ref=magpie"); // ended, still goes assert.equal(goTarget(LIST, "gone", "keys"), "https://gone.example/keys?ref=magpie"); // the partner's own query and fragment stay; its own ref is its referral code and stays as it is const own = [{ id: "own", keysUrl: "https://own.example/keys?aff=7#signup", website: "https://own.example/?ref=abc" }]; assert.equal(goTarget(own, "own", "keys"), "https://own.example/keys?aff=7&ref=magpie#signup"); assert.equal(goTarget(own, "own", "site"), "https://own.example/?ref=abc"); for (const [id, what, region] of [["nobody", "keys"], ["acme", "chat"], ["acme", "keys", "mars"], ["plain", "keys"], ["acme", "constructor"]]) assert.equal(goTarget(LIST, id, what, region), "", [id, what, region].join(" ")); }); test("partners: /go counts the click", async () => { const { PARTNERS } = await import("./partners.js"); const p = PARTNERS.find((x) => x.keysUrl || x.website); if (!p) { // nobody listed: every /go is not found, and nothing is sent captured.length = 0; for (const path of ["/go/acme/keys", "/go/%E0/keys", "/go/"]) assert.equal((await ask(path)).status, 404, path); assert.deepEqual(captured, []); return; } const what = p.keysUrl ? "keys" : "site"; captured.length = 0; const res = await worker.fetch(new Request("https://usemagpie.ai/go/" + p.id + "/" + what), {}, ctx); assert.equal(res.status, 302); assert.equal(res.headers.get("Location"), goTarget(PARTNERS, p.id, what)); assert.equal(new URL(res.headers.get("Location")).searchParams.has("ref"), true); await Promise.resolve(); assert.equal(captured.length, 1); assert.equal(captured[0].event, "magpie partner go"); assert.equal(captured[0].properties.id, p.id); assert.equal(captured[0].properties.what, what); assert.equal(captured[0].properties.$process_person_profile, false); // a HEAD goes on but isn't counted captured.length = 0; const head = await worker.fetch(new Request("https://usemagpie.ai/go/" + p.id + "/" + what, { method: "HEAD" }), {}, ctx); assert.equal(head.status, 302); assert.deepEqual(captured, []); assert.equal((await ask("/go/nobody-at-all/keys")).status, 404); assert.equal((await ask("/go/%E0/keys")).status, 404); }); test("partners: the list's fetches are counted, one in ten", async () => { const { PARTNERS } = await import("./partners.js"); const anyLive = PARTNERS.some((p) => (!p.from || Date.parse(p.from) <= Date.now()) && (!p.until || Date.now() < Date.parse(p.until))); const random = Math.random; try { for (const [r, sent] of [[0.05, anyLive], [0.5, false]]) { Math.random = () => r; captured.length = 0; const res = await ask("/api/partners"); assert.equal(res.status, 200); await new Promise((ok) => setTimeout(ok, 0)); assert.equal(captured.length, sent ? 1 : 0, "random " + r); if (sent) { assert.equal(captured[0].event, "magpie partners fetch"); assert.equal(captured[0].properties.weight, 10); } } } finally { Math.random = random; } });