import { chromium, expect, test } from "@playwright/test"; const BACKEND_BASE_URL = "http://127.0.0.1:5150"; const FRONTEND_BASE_URL = "http://127.0.0.1:4321"; type AdminSubscriptionRecord = { id: number; channel_type: string; target: string; }; type AdminSubscriptionListResponse = { subscriptions: AdminSubscriptionRecord[]; }; declare global { interface Window { __termiPushMessages?: unknown[]; __termiSubscriptionPopupReady?: boolean; } } test("浏览器订阅后可以收到测试推送", async ({ request }, testInfo) => { const context = await chromium.launchPersistentContext( testInfo.outputPath("web-push-user-data"), { headless: true, viewport: { width: 1280, height: 800 }, }, ); try { await context.grantPermissions(["notifications"], { origin: FRONTEND_BASE_URL, }); const page = context.pages()[0] ?? (await context.newPage()); await page.addInitScript(() => { window.__termiPushMessages = []; navigator.serviceWorker?.addEventListener("message", (event) => { if (event.data?.type === "termi:web-push-received") { window.__termiPushMessages?.push(event.data.payload ?? null); } }); }); await page.goto(`${FRONTEND_BASE_URL}/maintenance?returnTo=%2F`); await page.getByLabel("访问口令").fill("termi"); await page.getByRole("button", { name: "进入站点" }).click(); await page.waitForURL(`${FRONTEND_BASE_URL}/`); await page.waitForFunction( () => window.__termiSubscriptionPopupReady === true, ); await page.locator("[data-subscription-popup-open]").click(); const subscribeResponsePromise = page.waitForResponse( (response) => response.url().includes("/api/subscriptions/combined") && response.request().method() === "POST", ); await page.locator("[data-subscription-popup-submit]").click(); const subscribeResponse = await subscribeResponsePromise; expect(subscribeResponse.ok()).toBeTruthy(); await expect( page.locator('[data-subscription-popup-status][data-state="success"]'), ).toBeVisible(); const endpoint = await page.evaluate(async () => { const registration = await navigator.serviceWorker.ready; const subscription = await registration.pushManager.getSubscription(); return subscription?.endpoint ?? null; }); expect(endpoint).toBeTruthy(); const loginResponse = await request.post( `${BACKEND_BASE_URL}/api/admin/session/login`, { data: { username: "admin", password: "admin123", }, }, ); expect(loginResponse.ok()).toBeTruthy(); const subscriptionsResponse = await request.get( `${BACKEND_BASE_URL}/api/admin/subscriptions`, ); expect(subscriptionsResponse.ok()).toBeTruthy(); const subscriptionsPayload = (await subscriptionsResponse.json()) as AdminSubscriptionListResponse; const subscription = subscriptionsPayload.subscriptions.find( (item) => item.channel_type === "web_push" && item.target === endpoint, ); expect(subscription).toBeTruthy(); const testResponse = await request.post( `${BACKEND_BASE_URL}/api/admin/subscriptions/${subscription?.id}/test`, ); expect(testResponse.ok()).toBeTruthy(); await page.waitForFunction( () => Array.isArray(window.__termiPushMessages) && window.__termiPushMessages.length > 0, undefined, { timeout: 45_000 }, ); const messages = await page.evaluate(() => window.__termiPushMessages ?? []); expect(messages.length).toBeGreaterThan(0); } finally { await context.close(); } });