// F5 — PWA behaviour against a production preview build (see
// playwright.pwa.config.ts). Covers the manifest, service-worker
// registration, offline-from-cache load, and the version-keyed cache
// (a new deploy's `version` makes a new cache and `activate` drops the
// old one — verified here as "exactly one galaxy cache, version-keyed").
// The single-URL app-shell boots at the app base (`/`); with no seeded
// session the dispatcher renders the login screen, so the shell's
// `#main-content` region is the boot signal here.

import { expect, test } from "@playwright/test";

test.describe("PWA", () => {
	test("links a web manifest with installable icons", async ({ page }) => {
		await page.goto("/");
		const href = await page
			.locator('head link[rel="manifest"]')
			.getAttribute("href");
		expect(href).toMatch(/manifest\.webmanifest$/);

		const manifest = await page.request
			.get(href!)
			.then((r) => r.json());
		expect(manifest.name).toBe("Galaxy");
		// Relative so the manifest is base-agnostic: served under the app
		// base (`/` at the root, `/game/` in the single-origin deploy) it
		// resolves to the app root either way.
		expect(manifest.start_url).toBe("./");
		expect(manifest.display).toBe("standalone");
		const sizes = (manifest.icons as { sizes: string }[]).map((i) => i.sizes);
		expect(sizes).toContain("192x192");
		expect(sizes).toContain("512x512");
		const purposes = (manifest.icons as { purpose?: string }[]).map(
			(i) => i.purpose,
		);
		expect(purposes).toContain("maskable");
	});

	test("registers a service worker that controls the page", async ({ page }) => {
		await page.goto("/");
		await page.waitForFunction(
			() => navigator.serviceWorker.controller !== null,
			null,
			{ timeout: 20_000 },
		);
		const cacheNames: string[] = await page.evaluate(() => caches.keys());
		const galaxy = cacheNames.filter((n) => n.startsWith("galaxy-cache-"));
		// Exactly one, version-keyed cache (old versions purged on activate).
		expect(galaxy).toHaveLength(1);
		expect(galaxy[0]).toMatch(/^galaxy-cache-.+/);
	});

	test("serves the app shell offline from the cache", async ({
		page,
		context,
	}) => {
		await page.goto("/");
		await page.waitForFunction(
			() => navigator.serviceWorker.controller !== null,
			null,
			{ timeout: 20_000 },
		);
		await expect(page.locator("#main-content")).toBeVisible();

		await context.setOffline(true);
		try {
			await page.reload();
			// The cached shell boots offline — the login main region renders.
			await expect(page.locator("#main-content")).toBeVisible({
				timeout: 15_000,
			});
		} finally {
			await context.setOffline(false);
		}
	});
});
