import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import path from "node:path";
import { JSDOM } from "jsdom";
const { test } = process.env.VITEST
? await import("vitest")
: await import("node:test");
const source = await readFile(path.resolve("sites/app.js"), "utf8");
const createMediaQueries = (window, legacy) => {
const queries = new Map();
window.matchMedia = (media) => {
if (!queries.has(media)) {
const listeners = new Set();
const query = {
media,
matches: media === "(max-width: 719px)",
addEventListener: legacy
? undefined
: (_type, listener) => listeners.add(listener),
addListener: legacy
? (listener) => listeners.add(listener)
: undefined,
dispatch(matches) {
query.matches = matches;
for (const listener of listeners) {
listener(query);
}
},
};
queries.set(media, query);
}
return queries.get(media);
};
return queries;
};
const renderApp = (legacy = false) => {
const dom = new JSDOM(
`
Skip
`,
{
runScripts: "outside-only",
url: "https://example.test/en.html?lang=en",
},
);
const { window } = dom;
const inertState = new WeakMap();
Object.defineProperty(window.HTMLElement.prototype, "inert", {
configurable: true,
get() {
return inertState.get(this) ?? false;
},
set(value) {
inertState.set(this, Boolean(value));
},
});
const queries = createMediaQueries(window, legacy);
window.eval(source);
return { dom, queries, window };
};
const renderLoongArchPreview = (payload) => {
const dom = new JSDOM(
`
下载 Linux 版(在新窗口打开)
`,
{
runScripts: "outside-only",
url: "https://example.test/",
},
);
const { window } = dom;
createMediaQueries(window, false);
window.TextDecoder = TextDecoder;
window.GoodBuddyReleaseIndex = {
maximumIndexBytes: 512 * 1024,
maximumPreviewIndexBytes: 16 * 1024,
validateReleaseIndex() {
throw new Error("正式发布索引在此测试中不可用");
},
validateLoongArchPreviewIndex(value) {
return value;
},
};
window.fetch = async (url) => {
if (!String(url).includes("/loongarch-preview/")) {
throw new Error("正式发布索引在此测试中不可用");
}
if (!payload) {
throw new Error("龙芯预览索引不可用");
}
const bytes = new TextEncoder().encode(JSON.stringify(payload));
let delivered = false;
return {
ok: true,
status: 200,
headers: {
get(name) {
return name === "content-length" ? String(bytes.length) : null;
},
},
body: {
getReader() {
return {
async read() {
if (delivered) {
return { done: true, value: undefined };
}
delivered = true;
return { done: false, value: bytes };
},
};
},
},
};
};
window.eval(source);
return { dom, window };
};
for (const legacy of [false, true]) {
test(
`mobile menu isolates content and restores focus with ${
legacy ? "legacy" : "modern"
} media listeners`,
async () => {
const { dom, queries, window } = renderApp(legacy);
const header = window.document.querySelector("[data-site-header]");
const toggle = window.document.querySelector("[data-menu-toggle]");
const firstLink = window.document.querySelector("#first-nav-link");
const main = window.document.querySelector("main");
const footer = window.document.querySelector("footer");
const skip = window.document.querySelector("#skip");
const backdrop = window.document.querySelector("[data-menu-backdrop]");
main.inert = true;
toggle.click();
assert.equal(header.classList.contains("is-menu-open"), true);
assert.equal(toggle.getAttribute("aria-expanded"), "true");
assert.equal(window.document.activeElement, firstLink);
assert.equal(skip.inert, true);
assert.equal(main.inert, true);
assert.equal(footer.inert, true);
assert.equal(backdrop.inert, false);
assert.equal(backdrop.classList.contains("is-active"), true);
window.document.dispatchEvent(
new window.KeyboardEvent("keydown", { key: "Escape", bubbles: true }),
);
assert.equal(header.classList.contains("is-menu-open"), false);
assert.equal(toggle.getAttribute("aria-expanded"), "false");
assert.equal(window.document.activeElement, toggle);
assert.equal(skip.inert, false);
assert.equal(main.inert, true);
assert.equal(footer.inert, false);
assert.equal(backdrop.classList.contains("is-active"), false);
toggle.click();
backdrop.click();
assert.equal(header.classList.contains("is-menu-open"), false);
assert.equal(window.document.activeElement, toggle);
toggle.click();
footer.click();
assert.equal(header.classList.contains("is-menu-open"), false);
assert.equal(window.document.activeElement, toggle);
toggle.click();
firstLink.click();
await new Promise((resolve) => window.setTimeout(resolve, 0));
assert.equal(header.classList.contains("is-menu-open"), false);
assert.equal(window.document.activeElement, toggle);
toggle.click();
queries.get("(max-width: 719px)").dispatch(false);
assert.equal(header.classList.contains("is-menu-open"), false);
assert.equal(toggle.getAttribute("aria-expanded"), "false");
assert.equal(footer.inert, false);
dom.window.close();
},
);
}
test("enables only a validated LoongArch preview download", async () => {
const artifactUrl =
"https://goodbuddy.oss-cn-beijing.aliyuncs.com/releases/loongarch-preview/v0.11.5/GoodBuddy-0.11.5-linux-loong64-preview.deb";
const { dom, window } = renderLoongArchPreview({
goodBuddyVersion: "0.11.5",
artifact: {
size: 186_853_872,
sha256: "a".repeat(64),
url: artifactUrl,
},
});
await new Promise((resolve) => window.setTimeout(resolve, 0));
const arch = window.document.querySelector("[data-download-arch]");
const format = window.document.querySelector(
"[data-download-format]",
);
const link = window.document.querySelector("[data-release-link]");
const meta = window.document.querySelector("[data-download-meta]");
arch.value = "loong64";
arch.dispatchEvent(new window.Event("change"));
assert.equal(format.value, "deb");
assert.equal(format.disabled, true);
assert.equal(format.options[0].hidden, true);
assert.equal(format.options[1].hidden, false);
assert.equal(format.options[2].hidden, true);
assert.equal(link.getAttribute("href"), artifactUrl);
assert.equal(link.getAttribute("target"), "_blank");
assert.equal(link.getAttribute("rel"), "noreferrer");
assert.equal(link.hasAttribute("aria-disabled"), false);
assert.equal(link.classList.contains("is-disabled"), false);
assert.equal(
meta.textContent,
"GoodBuddy 0.11.5 · 178 MB · 实验预览 · SHA-256 aaaaaaaaaaaa…",
);
dom.window.close();
});
test("keeps Chinese downloads disabled while the OSS indexes are loading", async () => {
const { dom, window } = renderLoongArchPreview({
goodBuddyVersion: "0.11.5",
artifact: {
size: 186_853_872,
sha256: "a".repeat(64),
url: "https://goodbuddy.oss-cn-beijing.aliyuncs.com/releases/loongarch-preview/v0.11.5/GoodBuddy-0.11.5-linux-loong64-preview.deb",
},
});
const arch = window.document.querySelector("[data-download-arch]");
const link = window.document.querySelector("[data-release-link]");
const meta = window.document.querySelector("[data-download-meta]");
assert.equal(link.hasAttribute("href"), false);
assert.equal(link.getAttribute("aria-disabled"), "true");
assert.equal(link.tabIndex, -1);
assert.equal(link.classList.contains("is-disabled"), true);
assert.equal(link.textContent, "正在获取 Linux 下载信息…(在新窗口打开)");
assert.equal(meta.textContent, "正在从 OSS 获取最新版本。");
arch.value = "loong64";
arch.dispatchEvent(new window.Event("change"));
assert.equal(link.hasAttribute("href"), false);
assert.equal(link.getAttribute("aria-disabled"), "true");
assert.equal(link.textContent, "正在获取龙芯预览版下载信息…(在新窗口打开)");
assert.equal(meta.textContent, "正在从 OSS 获取最新版本。");
await new Promise((resolve) => window.setTimeout(resolve, 0));
dom.window.close();
});
test("keeps the LoongArch preview disabled when its index is unavailable", async () => {
const { dom, window } = renderLoongArchPreview(null);
await new Promise((resolve) => window.setTimeout(resolve, 0));
const arch = window.document.querySelector("[data-download-arch]");
const format = window.document.querySelector(
"[data-download-format]",
);
const link = window.document.querySelector("[data-release-link]");
const meta = window.document.querySelector("[data-download-meta]");
arch.value = "loong64";
arch.dispatchEvent(new window.Event("change"));
assert.equal(format.value, "deb");
assert.equal(format.disabled, true);
assert.equal(link.hasAttribute("href"), false);
assert.equal(link.getAttribute("aria-disabled"), "true");
assert.equal(link.tabIndex, -1);
assert.equal(link.classList.contains("is-disabled"), true);
assert.equal(
meta.textContent,
"实验预览 · 仅 DEB · 索引尚未发布或校验失败。",
);
arch.value = "x64";
arch.dispatchEvent(new window.Event("change"));
assert.equal(format.disabled, false);
assert.equal(format.options[0].hidden, false);
assert.equal(link.getAttribute("href"), "https://github.com/mesalogo/goodbuddy/releases/latest");
assert.equal(link.hasAttribute("aria-disabled"), false);
dom.window.close();
});