mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-10-25 17:22:27 +08:00
The in-app updater only follows stable releases and its manifest notes just say "Release vX", so users jumping between stable versions never saw what the versions in between changed. The full release notes are too long for a popup. - Each version gets src/whats-new/<version>.json: up to 4 one-line items (new / fix / improve) in zh, zh-TW, en and ja, bundled into the app at build time. "items": [] marks a version that should not pop up. - On the first launch after an update, a dialog lists every non-empty version between the last one seen and the current one, newest first. Older versions beyond the first three are collapsed. Each version links to its page in the website changelog. - The last seen version is stored per device in settings.json (whatsNewSeenVersion) and only moves forward, so a downgrade and re-upgrade does not repeat anything. Without a record, only the current version is shown. When there is nothing to show, the version is recorded silently so the next update has a correct starting point. - The dialog waits for the welcome and new-layout dialogs. Confirming either of them also records the current version, so a 3.x user does not get two dialogs in a row. - Settings > About gets a "Recent updates" button to open the summaries again. The 4.0.0 summary is included so that list starts from 4.0; no update popup can reach it, since only 4.0.2 and later record a version. - The release workflow first requires the tagged version's summary file and validates every bundled summary with the unit test, since a malformed item would crash the dialog and put the whole app on the error screen.
97 lines
2.8 KiB
TypeScript
97 lines
2.8 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
changelogUrl,
|
|
entriesSince,
|
|
entriesUpTo,
|
|
isNewerThanSeen,
|
|
markSeen,
|
|
resolveWhatsNewLanguage,
|
|
type WhatsNewEntry,
|
|
} from "@/lib/whatsNew";
|
|
|
|
const item = (text: string) => ({
|
|
type: "fix" as const,
|
|
zh: text,
|
|
"zh-TW": text,
|
|
en: text,
|
|
ja: text,
|
|
});
|
|
|
|
// 新到旧,和 WHATS_NEW_ENTRIES 的顺序一致
|
|
const ENTRIES: WhatsNewEntry[] = [
|
|
{ version: "4.1.0", items: [item("future")] },
|
|
{ version: "4.0.4", items: [item("four")] },
|
|
{ version: "4.0.3", items: [] },
|
|
{ version: "4.0.2", items: [item("two")] },
|
|
{ version: "4.0.1", items: [item("one")] },
|
|
];
|
|
|
|
const versions = (entries: WhatsNewEntry[]) => entries.map((e) => e.version);
|
|
|
|
describe("entriesSince", () => {
|
|
it("returns versions after the seen one up to the current one, skipping empty ones", () => {
|
|
expect(versions(entriesSince(ENTRIES, "4.0.1", "4.0.4"))).toEqual([
|
|
"4.0.4",
|
|
"4.0.2",
|
|
]);
|
|
});
|
|
|
|
it("shows only the current version when nothing was recorded", () => {
|
|
expect(versions(entriesSince(ENTRIES, undefined, "4.0.2"))).toEqual([
|
|
"4.0.2",
|
|
]);
|
|
expect(entriesSince(ENTRIES, undefined, "4.0.3")).toEqual([]);
|
|
});
|
|
|
|
it("returns nothing on a downgrade", () => {
|
|
expect(entriesSince(ENTRIES, "4.0.4", "4.0.2")).toEqual([]);
|
|
});
|
|
|
|
it("treats a prerelease as older than its release", () => {
|
|
expect(versions(entriesSince(ENTRIES, "4.0.2-beta.1", "4.0.2"))).toEqual([
|
|
"4.0.2",
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe("entriesUpTo", () => {
|
|
it("lists non-empty versions up to the current one", () => {
|
|
expect(versions(entriesUpTo(ENTRIES, "4.0.4"))).toEqual([
|
|
"4.0.4",
|
|
"4.0.2",
|
|
"4.0.1",
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe("seen version", () => {
|
|
it("only moves forward", () => {
|
|
expect(markSeen(undefined, "4.0.2")).toBe("4.0.2");
|
|
expect(markSeen("4.0.1", "4.0.2")).toBe("4.0.2");
|
|
expect(markSeen("4.0.4", "4.0.2")).toBe("4.0.4");
|
|
expect(markSeen("4.0.1", undefined)).toBe("4.0.1");
|
|
});
|
|
|
|
it("is due only when the current version is newer", () => {
|
|
expect(isNewerThanSeen("4.0.2", undefined)).toBe(true);
|
|
expect(isNewerThanSeen("4.0.2", "4.0.1")).toBe(true);
|
|
expect(isNewerThanSeen("4.0.2", "4.0.2")).toBe(false);
|
|
expect(isNewerThanSeen("4.0.2", "4.0.4")).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("language and links", () => {
|
|
it("falls back to English for unknown languages", () => {
|
|
expect(resolveWhatsNewLanguage("zh-TW")).toBe("zh-TW");
|
|
expect(resolveWhatsNewLanguage("ja")).toBe("ja");
|
|
expect(resolveWhatsNewLanguage("fr")).toBe("en");
|
|
});
|
|
|
|
it("links to the website changelog, Traditional Chinese uses the zh pages", () => {
|
|
expect(changelogUrl("en", "4.0.2")).toBe(
|
|
"https://ccswitch.io/en/changelog/4.0.2",
|
|
);
|
|
expect(changelogUrl("zh-TW")).toBe("https://ccswitch.io/zh/changelog");
|
|
});
|
|
});
|