fix: address final PWA review findings

This commit is contained in:
AgendaPro Dev
2026-07-27 17:19:45 -06:00
parent 43f5d1374c
commit 0b466f33f3
5 changed files with 89 additions and 11 deletions
+34 -3
View File
@@ -3,6 +3,9 @@ import { chromium } from "playwright";
const BASE = process.env.PWA_BASE_URL || "http://localhost:3000";
const baseUrl = BASE.endsWith("/") ? BASE : `${BASE}/`;
const OWNER_EMAIL = process.env.PWA_OWNER_EMAIL || "[email protected]";
const ADMIN_EMAIL = process.env.PWA_ADMIN_EMAIL || "[email protected]";
const PWA_PASSWORD = process.env.PWA_PASSWORD || "demo1234";
const NETWORK_TIMEOUT_MS = 8000;
const UI_TIMEOUT_MS = 8000;
@@ -113,9 +116,18 @@ async function dispatchInstallPrompt(page) {
}, undefined, { timeout: UI_TIMEOUT_MS });
}
async function dispatchDismissedInstallPrompt(page) {
await page.evaluate(() => {
const event = new Event("beforeinstallprompt", { cancelable: true });
event.prompt = async () => { window.__installPromptCalls += 1; };
event.userChoice = Promise.resolve({ outcome: "dismissed", platform: "web" });
window.dispatchEvent(event);
});
}
async function login(page, email, expectedPath) {
await page.fill('input[type="email"]', email);
await page.fill('input[type="password"]', "demo1234");
await page.fill('input[type="password"]', PWA_PASSWORD);
await page.click('button[type="submit"]');
await page.waitForURL(expectedPath, { timeout: UI_TIMEOUT_MS });
await page.waitForSelector("header", { state: "attached", timeout: UI_TIMEOUT_MS });
@@ -179,6 +191,23 @@ async function main() {
await chromiumPage.waitForFunction(() => window.__installPromptCalls === 1);
assert.equal(await chromiumPage.evaluate(() => window.__installPromptCalls), 1);
const dismissalContext = await browser.newContext();
contexts.push(dismissalContext);
dismissalContext.setDefaultTimeout(UI_TIMEOUT_MS);
dismissalContext.setDefaultNavigationTimeout(UI_TIMEOUT_MS);
await dismissalContext.addInitScript(() => { window.__installPromptCalls = 0; });
const dismissalPage = await dismissalContext.newPage();
await dismissalPage.goto(baseUrl, { waitUntil: "networkidle" });
await dispatchDismissedInstallPrompt(dismissalPage);
const dismissalAction = await assertInstallAction(dismissalPage, true, "dismissal");
await dismissalAction.click();
await assertInstallAction(dismissalPage, false, "dismissed prompt");
assert.equal(await dismissalPage.evaluate(() => sessionStorage.getItem("agendamax-install-dismissed")), "1");
await dismissalPage.reload({ waitUntil: "networkidle" });
assert.equal(await dismissalPage.evaluate(() => sessionStorage.getItem("agendamax-install-dismissed")), "1");
await dispatchDismissedInstallPrompt(dismissalPage);
await assertInstallAction(dismissalPage, false, "dismissed prompt after reload");
const apiResult = await chromiumPage.evaluate(async () => {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 8000);
@@ -199,7 +228,7 @@ async function main() {
const businessPage = await chromiumContext.newPage();
await businessPage.setViewportSize({ width: 375, height: 720 });
await businessPage.goto(baseUrl, { waitUntil: "networkidle" });
await login(businessPage, "[email protected]", /\/dashboard/);
await login(businessPage, OWNER_EMAIL, /\/dashboard/);
await dispatchInstallPrompt(businessPage);
const businessAction = await assertInstallAction(businessPage, true, "business shell");
await businessAction.click();
@@ -231,7 +260,7 @@ async function main() {
await adminContext.addInitScript(() => { window.__installPromptCalls = 0; });
const adminPage = await adminContext.newPage();
await adminPage.goto(baseUrl, { waitUntil: "networkidle" });
await login(adminPage, "[email protected]", /\/admin/);
await login(adminPage, ADMIN_EMAIL, /\/admin/);
await dispatchInstallPrompt(adminPage);
const adminAction = await assertInstallAction(adminPage, true, "admin shell");
await adminAction.click();
@@ -262,6 +291,8 @@ async function main() {
const swSource = (await assertEndpoint("/sw.js")).body;
assert.match(swSource, /pathname\s*\.\s*startsWith\s*\(\s*["']\/api\/["']\s*\)/, "Service worker lacks API bypass");
assert.match(swSource, /request\s*\.\s*method\s*!==\s*["']GET["']/, "Service worker lacks non-GET guard");
assert.match(swSource, /request\.credentials\s*!==\s*["']omit["']/, "Service worker lacks credential bypass");
assert.match(swSource, /key\.startsWith\(["']agendamax-shell-["']\)/, "Service worker cleanup is not scoped to AgendaMax caches");
console.log("PWA checks passed");
} finally {
try {