| 1 | import { afterEach, describe, expect, it, vi } from "vite-plus/test"; |
| 2 | import { |
| 3 | resolveServerBackedAppDisplayName, |
| 4 | resolveServerBackedAppStageLabel, |
| 5 | } from "./branding.logic"; |
| 6 | |
| 7 | const originalWindow = globalThis.window; |
| 8 | |
| 9 | afterEach(() => { |
| 10 | vi.resetModules(); |
| 11 | |
| 12 | if (originalWindow === undefined) { |
| 13 | Reflect.deleteProperty(globalThis, "window"); |
| 14 | return; |
| 15 | } |
| 16 | |
| 17 | globalThis.window = originalWindow; |
| 18 | }); |
| 19 | |
| 20 | describe("branding", () => { |
| 21 | it("uses injected desktop branding when available", async () => { |
| 22 | Object.defineProperty(globalThis, "window", { |
| 23 | configurable: true, |
| 24 | value: { |
| 25 | desktopBridge: { |
| 26 | getAppBranding: () => ({ |
| 27 | baseName: "The Knife", |
| 28 | stageLabel: "Nightly", |
| 29 | displayName: "The Knife (Nightly)", |
| 30 | }), |
| 31 | }, |
| 32 | }, |
| 33 | }); |
| 34 | |
| 35 | const branding = await import("./branding"); |
| 36 | |
| 37 | expect(branding.APP_BASE_NAME).toBe("The Knife"); |
| 38 | expect(branding.APP_STAGE_LABEL).toBe("Nightly"); |
| 39 | expect(branding.APP_DISPLAY_NAME).toBe("The Knife (Nightly)"); |
| 40 | }); |
| 41 | |
| 42 | it("normalizes hosted app channel metadata", async () => { |
| 43 | vi.stubEnv("VITE_HOSTED_APP_CHANNEL", "nightly"); |
| 44 | |
| 45 | const branding = await import("./branding"); |
| 46 | |
| 47 | expect(branding.HOSTED_APP_CHANNEL).toBe("nightly"); |
| 48 | expect(branding.HOSTED_APP_CHANNEL_LABEL).toBe("Nightly"); |
| 49 | expect(branding.APP_STAGE_LABEL).toBe("Nightly"); |
| 50 | expect(branding.APP_DISPLAY_NAME).toBe("The Knife (Nightly)"); |
| 51 | }); |
| 52 | |
| 53 | it("does not label the latest hosted app channel", async () => { |
| 54 | vi.stubEnv("VITE_HOSTED_APP_CHANNEL", "latest"); |
| 55 | |
| 56 | const branding = await import("./branding"); |
| 57 | |
| 58 | expect(branding.HOSTED_APP_CHANNEL).toBe("latest"); |
| 59 | expect(branding.HOSTED_APP_CHANNEL_LABEL).toBe("Latest"); |
| 60 | expect(branding.APP_STAGE_LABEL).toBe("Latest"); |
| 61 | expect(branding.APP_DISPLAY_NAME).toBe("The Knife"); |
| 62 | }); |
| 63 | |
| 64 | it("ignores unknown hosted app channels", async () => { |
| 65 | vi.stubEnv("VITE_HOSTED_APP_CHANNEL", "preview"); |
| 66 | |
| 67 | const branding = await import("./branding"); |
| 68 | |
| 69 | expect(branding.HOSTED_APP_CHANNEL).toBeNull(); |
| 70 | expect(branding.HOSTED_APP_CHANNEL_LABEL).toBeNull(); |
| 71 | }); |
| 72 | }); |
| 73 | |
| 74 | describe("branding logic", () => { |
| 75 | it("returns Nightly for nightly primary server versions", () => { |
| 76 | expect( |
| 77 | resolveServerBackedAppStageLabel({ |
| 78 | primaryServerVersion: "0.0.28-nightly.20260616.12", |
| 79 | fallbackStageLabel: "Alpha", |
| 80 | }), |
| 81 | ).toBe("Nightly"); |
| 82 | }); |
| 83 | |
| 84 | it("updates the display name for nightly primary server versions", () => { |
| 85 | expect( |
| 86 | resolveServerBackedAppDisplayName({ |
| 87 | baseName: "The Knife", |
| 88 | fallbackDisplayName: "The Knife (Alpha)", |
| 89 | fallbackStageLabel: "Alpha", |
| 90 | primaryServerVersion: "0.0.28-nightly.20260616.12", |
| 91 | }), |
| 92 | ).toBe("The Knife (Nightly)"); |
| 93 | }); |
| 94 | |
| 95 | it("keeps the fallback display name for stable primary server versions", () => { |
| 96 | expect( |
| 97 | resolveServerBackedAppDisplayName({ |
| 98 | baseName: "The Knife", |
| 99 | fallbackDisplayName: "The Knife (Alpha)", |
| 100 | fallbackStageLabel: "Alpha", |
| 101 | primaryServerVersion: "0.0.27", |
| 102 | }), |
| 103 | ).toBe("The Knife (Alpha)"); |
| 104 | }); |
| 105 | |
| 106 | it("keeps the fallback display name for malformed nightly primary server versions", () => { |
| 107 | expect( |
| 108 | resolveServerBackedAppDisplayName({ |
| 109 | baseName: "The Knife", |
| 110 | fallbackDisplayName: "The Knife (Alpha)", |
| 111 | fallbackStageLabel: "Alpha", |
| 112 | primaryServerVersion: "0.0.28-nightly.20260616", |
| 113 | }), |
| 114 | ).toBe("The Knife (Alpha)"); |
| 115 | }); |
| 116 | }); |