Add TTRPG Player marketing landing site.
React/Vite landing with RU/EN i18n, live USD pricing, download links to updates.mailib.ru, and donate.stream checkout. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { describe, it } from "node:test";
|
||||
|
||||
import {
|
||||
DOWNLOAD_ARTIFACTS,
|
||||
DOWNLOAD_LINKS,
|
||||
FAQ_IDS,
|
||||
FEATURE_VARIANTS,
|
||||
NAV_LINK_KEYS,
|
||||
NAV_HREFS,
|
||||
PRICING_TIER_IDS,
|
||||
RECOMMENDED_PRICING_TIER,
|
||||
REQUIRED_SECTION_IDS,
|
||||
SITE_LINKS,
|
||||
UPDATE_FEED_BASE,
|
||||
} from "./data/siteContent";
|
||||
import {
|
||||
SCREENSHOT_SRC,
|
||||
getEffectsScreenshotDisplaySize,
|
||||
} from "./data/siteAssets";
|
||||
import { MESSAGES, inferLocaleFromLanguages } from "./i18n/messages";
|
||||
import {
|
||||
detectCpuArch,
|
||||
detectOs,
|
||||
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.mailib.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 and external buy link", () => {
|
||||
assert.equal(SITE_LINKS.download, "#platforms");
|
||||
assert.equal(SITE_LINKS.buy, "https://donate.stream/ttrpgplayer");
|
||||
});
|
||||
|
||||
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 buy 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");
|
||||
});
|
||||
});
|
||||
|
||||
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("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,
|
||||
}),
|
||||
DOWNLOAD_LINKS.macos.x64,
|
||||
);
|
||||
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,
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user