Files
TtrpgPlayerLanding/src/siteContent.test.ts
T
2026-09-16 12:33:59 +08:00

242 lines
7.3 KiB
TypeScript

import assert from "node:assert/strict";
import { describe, it } from "node:test";
import {
CROWDFUNDING_URL,
DOWNLOAD_ARTIFACTS,
DOWNLOAD_LINKS,
FAQ_IDS,
FEATURE_VARIANTS,
NAV_LINK_KEYS,
NAV_HREFS,
PRICING_TIER_BUY_URLS,
PRICING_TIER_IDS,
RECOMMENDED_PRICING_TIER,
REQUIRED_SECTION_IDS,
SITE_LINKS,
UPDATE_FEED_BASE,
VK_URL,
} from "./data/siteContent";
import {
SCREENSHOT_SRC,
getEffectsScreenshotDisplaySize,
} from "./data/siteAssets";
import { MESSAGES, inferLocaleFromLanguages } from "./i18n/messages";
import {
detectCpuArch,
detectOs,
parseUaDataArchitecture,
resolveDownloadHref,
resolvePlatformDownloadHref,
} from "./lib/detectOs";
describe("siteContent", () => {
it("exposes all required section anchor ids", () => {
for (const id of REQUIRED_SECTION_IDS) {
const inNav = NAV_LINK_KEYS.some((key) => NAV_HREFS[key] === `#${id}`);
assert.equal(inNav || id.length > 0, true, `missing section #${id}`);
}
});
it("defines four feature variants", () => {
assert.deepEqual(FEATURE_VARIANTS, [
"editor",
"control",
"presentation",
"atmosphere",
]);
});
it("defines three pricing tiers with one recommended", () => {
assert.equal(PRICING_TIER_IDS.length, 3);
assert.equal(RECOMMENDED_PRICING_TIER, "master");
});
it("includes five FAQ entries", () => {
assert.equal(FAQ_IDS.length, 5);
});
it("points download buttons to update feed artifacts", () => {
assert.equal(UPDATE_FEED_BASE, "https://updates.ttrpgplayer.ru/");
assert.equal(
DOWNLOAD_LINKS.windows,
`${UPDATE_FEED_BASE}${DOWNLOAD_ARTIFACTS.windows}`,
);
assert.equal(
DOWNLOAD_LINKS.macos.arm64,
`${UPDATE_FEED_BASE}${DOWNLOAD_ARTIFACTS.macos.arm64}`,
);
assert.equal(
DOWNLOAD_LINKS.linux.x64,
`${UPDATE_FEED_BASE}${DOWNLOAD_ARTIFACTS.linux.x64}`,
);
});
it("wires download anchor, crowdfunding, and VK urls", () => {
assert.equal(SITE_LINKS.download, "#platforms");
assert.equal(CROWDFUNDING_URL, "https://crowdrepublic.ru/projects/1073012");
assert.equal(VK_URL, "https://vk.com/ttrpgplayer");
});
it("maps each pricing tier to a VK market product url", () => {
assert.equal(
PRICING_TIER_BUY_URLS.basic,
"https://vk.ru/market/product/bazovy-klyuch-238917656-13366032",
);
assert.equal(
PRICING_TIER_BUY_URLS.master,
"https://vk.ru/market/product/klyuch-mastera-238917656-13366158",
);
assert.equal(
PRICING_TIER_BUY_URLS.legend,
"https://vk.ru/market/product/legenda-nri-238917656-13366160",
);
});
it("maps each feature variant to a screenshot asset", () => {
for (const variant of FEATURE_VARIANTS) {
assert.match(SCREENSHOT_SRC[variant], /^\/images\/screenshot-.+\.png$/u);
}
assert.equal(SCREENSHOT_SRC.atmosphere, "/images/screenshot-effects.png");
});
it("shows effects screenshot at 70% of intrinsic pixel size", () => {
const size = getEffectsScreenshotDisplaySize();
assert.equal(size.width, 206);
assert.equal(size.height, 220);
});
});
describe("i18n messages", () => {
it("has ru and en locales without DND key mentions", () => {
for (const locale of ["ru", "en"] as const) {
const json = JSON.stringify(MESSAGES[locale]);
assert.doesNotMatch(json, /DND-/u);
assert.doesNotMatch(json, /\.dnd\.zip/u);
assert.equal(Object.keys(MESSAGES[locale].faq.items).length, 5);
}
});
it("documents download and support labels in both locales", () => {
assert.equal(MESSAGES.ru.cta.download, "Скачать");
assert.equal(MESSAGES.en.cta.download, "Download");
assert.equal(MESSAGES.ru.cta.buy, "Купить");
assert.equal(MESSAGES.en.cta.buy, "Buy");
assert.equal(MESSAGES.ru.platforms.macosArch.arm64, "Apple Silicon");
assert.equal(MESSAGES.en.platforms.macosArch.x64, "Intel");
});
});
describe("inferLocaleFromLanguages", () => {
it("uses ru only for Russian browser languages", () => {
assert.equal(inferLocaleFromLanguages(["ru-RU"]), "ru");
assert.equal(inferLocaleFromLanguages(["ru"]), "ru");
assert.equal(inferLocaleFromLanguages(["ru-BY", "en-US"]), "ru");
});
it("defaults to en for non-Russian browser languages", () => {
assert.equal(inferLocaleFromLanguages(["en-US"]), "en");
assert.equal(inferLocaleFromLanguages(["de-DE"]), "en");
assert.equal(inferLocaleFromLanguages(["uk-UA"]), "en");
assert.equal(inferLocaleFromLanguages([]), "en");
});
});
describe("detectOs", () => {
it("detects Windows from user agent", () => {
assert.equal(detectOs("Mozilla/5.0 (Windows NT 10.0)"), "windows");
});
it("detects macOS from user agent", () => {
assert.equal(detectOs("Mozilla/5.0 (Macintosh; Intel Mac OS X)"), "macos");
});
it("detects Linux from user agent", () => {
assert.equal(detectOs("Mozilla/5.0 (X11; Linux x86_64)"), "linux");
});
it("detects Linux arm64 from user agent", () => {
assert.equal(detectCpuArch("Mozilla/5.0 (X11; Linux aarch64)"), "arm64");
});
it("parses Client Hints architecture tokens", () => {
assert.equal(parseUaDataArchitecture("arm"), "arm64");
assert.equal(parseUaDataArchitecture("x86"), "x64");
assert.equal(parseUaDataArchitecture("arm64"), "arm64");
assert.equal(parseUaDataArchitecture(undefined), "unknown");
});
it("does not guess Intel on opaque Mac user agents", () => {
assert.equal(
detectCpuArch("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)", 0),
"unknown",
);
assert.equal(
detectCpuArch("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)", 5),
"arm64",
);
assert.equal(
detectCpuArch(
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)",
0,
"arm",
),
"arm64",
);
});
it("resolves download href by OS", () => {
const hints = { userAgent: "Mozilla/5.0 (Windows NT 10.0)" };
assert.equal(
resolveDownloadHref("windows", DOWNLOAD_LINKS, hints),
DOWNLOAD_LINKS.windows,
);
assert.equal(
resolveDownloadHref("macos", DOWNLOAD_LINKS, {
userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X)",
maxTouchPoints: 0,
uaArchitecture: "x86",
}),
DOWNLOAD_LINKS.macos.x64,
);
assert.equal(
resolveDownloadHref("macos", DOWNLOAD_LINKS, {
userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X)",
maxTouchPoints: 0,
}),
DOWNLOAD_LINKS.macos.arm64,
);
assert.equal(
resolveDownloadHref("linux", DOWNLOAD_LINKS, {
userAgent: "Mozilla/5.0 (X11; Linux aarch64)",
}),
DOWNLOAD_LINKS.linux.arm64,
);
assert.equal(
resolveDownloadHref("unknown", DOWNLOAD_LINKS, hints),
DOWNLOAD_LINKS.windows,
);
});
it("resolves per-platform card href", () => {
assert.equal(
resolvePlatformDownloadHref("windows", DOWNLOAD_LINKS, {
userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X)",
}),
DOWNLOAD_LINKS.windows,
);
assert.equal(
resolvePlatformDownloadHref("macos", DOWNLOAD_LINKS, {
userAgent: "Mozilla/5.0 (Windows NT 10.0)",
}),
DOWNLOAD_LINKS.macos.arm64,
);
assert.equal(
resolvePlatformDownloadHref("linux", DOWNLOAD_LINKS, {
userAgent: "Mozilla/5.0 (X11; Linux x86_64)",
}),
DOWNLOAD_LINKS.linux.x64,
);
});
});