// @ts-check // Verifies the opt-in production bundle (npm run minify → static/dist/main.min.js): // the app must load and behave identically through the single-bundle path. const { test, expect } = require('@playwright/test'); // Block the service worker so request visibility is deterministic (the SW can serve // cached responses without a network request, hiding them from page.on('request')). test.use({ serviceWorkers: 'block' }); test('app works through the production bundle (?bundle=1)', async ({ page }) => { const errors = []; page.on('pageerror', (e) => errors.push(String(e))); let bundleRequested = false; page.on('request', (r) => { if (r.url().includes('/static/dist/main.min.js')) bundleRequested = true; }); await page.addInitScript(() => { window.APP_USE_BUNDLE = true; }); await page.goto('/?bundle=1', { waitUntil: 'domcontentloaded' }); await expect(page.locator('#sidebar')).toBeVisible(); // Wait for the JS pipeline to finish (navTo is defined by nav.js, loaded AFTER the // feature bundle) — only then is it valid to check what was loaded. await page.waitForFunction(() => typeof window.navTo === 'function', null, { timeout: 15_000 }); // The bundle (not the individual feature files) must have served the modules expect(bundleRequested).toBeTruthy(); // Global API from a bundled module must still be reachable (names are preserved) await page.evaluate(() => window.navTo('s-clone')); await expect(page.getByText(/Clone a Voice/i).first()).toBeVisible({ timeout: 10_000 }); const real = errors.filter(e => /ReferenceError|TypeError|SyntaxError|is not defined|is not a function/.test(e)); expect(real, real.join('\n')).toHaveLength(0); });