Files
edgeever/tests/store-listing-metadata.test.ts
T
tianma-if 760e82ab50 fix(i18n): fall unmatched locales back to English
Unknown browser and system languages now resolve to English instead of
Simplified Chinese, and Japanese App Store / Play listing copy is kept
in store-assets for console publishing.
2026-09-14 10:56:53 +08:00

102 lines
3.9 KiB
TypeScript

import { readFileSync } from "node:fs";
import { describe, expect, test } from "bun:test";
const read = (relativePath: string) =>
readFileSync(new URL(`../${relativePath}`, import.meta.url), "utf8");
const APP_STORE_LIMITS = {
name: 30,
subtitle: 30,
promotionalText: 170,
description: 4000,
keywords: 100,
whatsNew: 4000,
};
const PLAY_LIMITS = {
title: 50,
shortDescription: 80,
fullDescription: 4000,
};
const field = (source: string, label: string) => {
const match = source.match(new RegExp(`^- ${label}: (.+)$`, "m"));
if (!match) {
throw new Error(`Missing field: ${label}`);
}
return match[1].trim();
};
const headingBlock = (source: string, heading: string) => {
const match = source.match(
new RegExp(`(?:### |## )${heading}\\n\\n([\\s\\S]*?)(?:\\n\\n(?:### |## )|\\n## |$)`),
);
if (!match) {
throw new Error(`Missing heading: ${heading}`);
}
return match[1].trim();
};
describe("App Store listing copy", () => {
const english = read("apps/mobile/store-assets/app-store/metadata.en-US.md");
const chinese = read("apps/mobile/store-assets/app-store/metadata.zh-CN.md");
const japanese = read("apps/mobile/store-assets/app-store/metadata.ja.md");
test("keeps Japanese fields within App Store Connect limits", () => {
expect(field(japanese, "Name").length).toBeLessThanOrEqual(APP_STORE_LIMITS.name);
expect(field(japanese, "Subtitle").length).toBeLessThanOrEqual(APP_STORE_LIMITS.subtitle);
expect(headingBlock(japanese, "Promotional text").length).toBeLessThanOrEqual(
APP_STORE_LIMITS.promotionalText,
);
expect(headingBlock(japanese, "Description").length).toBeLessThanOrEqual(
APP_STORE_LIMITS.description,
);
expect(headingBlock(japanese, "Keywords").length).toBeLessThanOrEqual(APP_STORE_LIMITS.keywords);
expect(headingBlock(japanese, "What's New").length).toBeLessThanOrEqual(APP_STORE_LIMITS.whatsNew);
});
test("points Japanese listing URLs at the English site and keeps the Evernote disclaimer", () => {
expect(field(japanese, "Privacy policy URL")).toBe("https://edgeever.org/en/privacy");
expect(japanese).toContain("https://edgeever.org/en/contact");
expect(japanese).toContain("https://edgeever.org/en/");
expect(headingBlock(japanese, "Description")).toContain("Evernote Corporation");
expect(headingBlock(japanese, "Keywords")).not.toContain("Evernote");
});
test("keeps App Review demo credentials in every App Store locale file", () => {
for (const source of [english, chinese, japanese]) {
expect(source).toContain("https://demo.edgeever.org");
expect(source).toContain("ee-demo");
expect(source).toContain("demo#dZ6Q29Zjfor%");
expect(source).not.toContain("notes.example.com");
}
});
});
describe("Google Play listing copy", () => {
const english = read("apps/mobile/store-assets/play/metadata.en-US.md");
const chinese = read("apps/mobile/store-assets/play/metadata.zh-CN.md");
const japanese = read("apps/mobile/store-assets/play/metadata.ja-JP.md");
test("keeps Play listing fields within Console limits", () => {
for (const [source, titleHeading, shortHeading, fullHeading] of [
[english, "Title", "Short description", "Full description"],
[chinese, "标题", "简短说明", "完整说明"],
[japanese, "Title", "Short description", "Full description"],
] as const) {
expect(headingBlock(source, titleHeading).length).toBeLessThanOrEqual(PLAY_LIMITS.title);
expect(headingBlock(source, shortHeading).length).toBeLessThanOrEqual(
PLAY_LIMITS.shortDescription,
);
expect(headingBlock(source, fullHeading).length).toBeLessThanOrEqual(
PLAY_LIMITS.fullDescription,
);
}
});
test("tells Japanese Play users that a self-hosted instance is required", () => {
expect(headingBlock(japanese, "Full description")).toContain("セルフホスト");
expect(headingBlock(japanese, "Full description")).toContain("edgeever.org");
});
});