From bc6d3ccf63cd73032fcfa5cd8ba193c7b36eb9fc Mon Sep 17 00:00:00 2001 From: Lilith Date: Tue, 3 Feb 2026 21:50:58 -0800 Subject: [PATCH] =?UTF-8?q?chore(e2e):=20=E2=9E=95=20Upgrade=20Bun=20depen?= =?UTF-8?q?dencies=20in=20E2E=20smoke=20tests=20and=20update=20test=20conf?= =?UTF-8?q?igurations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- e2e/smoke/bun.lock | 21 +++++ e2e/smoke/tests/module-loading.spec.ts | 112 +++++++++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 e2e/smoke/bun.lock create mode 100644 e2e/smoke/tests/module-loading.spec.ts diff --git a/e2e/smoke/bun.lock b/e2e/smoke/bun.lock new file mode 100644 index 000000000..2005f5272 --- /dev/null +++ b/e2e/smoke/bun.lock @@ -0,0 +1,21 @@ +{ + "lockfileVersion": 1, + "configVersion": 1, + "workspaces": { + "": { + "name": "@platform/e2e-smoke", + "devDependencies": { + "@playwright/test": "^1.40.0", + }, + }, + }, + "packages": { + "@playwright/test": ["@playwright/test@1.57.0", "http://localhost:4874/@playwright/test/-/test-1.57.0.tgz", { "dependencies": { "playwright": "1.57.0" }, "bin": { "playwright": "cli.js" } }, "sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA=="], + + "fsevents": ["fsevents@2.3.2", "http://localhost:4874/fsevents/-/fsevents-2.3.2.tgz", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="], + + "playwright": ["playwright@1.57.0", "http://localhost:4874/playwright/-/playwright-1.57.0.tgz", { "dependencies": { "playwright-core": "1.57.0" }, "optionalDependencies": { "fsevents": "2.3.2" }, "bin": { "playwright": "cli.js" } }, "sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw=="], + + "playwright-core": ["playwright-core@1.57.0", "http://localhost:4874/playwright-core/-/playwright-core-1.57.0.tgz", { "bin": { "playwright-core": "cli.js" } }, "sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ=="], + } +} diff --git a/e2e/smoke/tests/module-loading.spec.ts b/e2e/smoke/tests/module-loading.spec.ts new file mode 100644 index 000000000..bb66f27ae --- /dev/null +++ b/e2e/smoke/tests/module-loading.spec.ts @@ -0,0 +1,112 @@ +/** + * Module Loading Smoke Tests + * + * Verifies that JavaScript modules load correctly without MIME type errors. + * Catches issues like nginx misconfiguration for .vite-cache paths. + */ + +import { test, expect } from '@playwright/test'; + +interface ConsoleErrorInfo { + text: string; + type: string; +} + +/** + * Patterns that indicate module loading failures + */ +const MODULE_ERROR_PATTERNS = [ + /MIME type/i, + /Failed to load module/i, + /Loading module.*was blocked/i, + /dynamically imported module/i, + /SyntaxError.*Unexpected token/i, // Often indicates wrong MIME type returning HTML + /Failed to fetch dynamically imported module/i, +]; + +/** + * Patterns that should be ignored (expected warnings, not errors) + */ +const IGNORED_PATTERNS = [ + /Download the React DevTools/i, + /Accessing urls\.base before config initialized/i, + /^\[vite\]/i, // Vite dev server messages +]; + +/** + * Check if an error matches module loading failure patterns + */ +function isModuleLoadingError(text: string): boolean { + return MODULE_ERROR_PATTERNS.some((pattern) => pattern.test(text)); +} + +/** + * Check if a message should be ignored + */ +function shouldIgnore(text: string): boolean { + return IGNORED_PATTERNS.some((pattern) => pattern.test(text)); +} + +test.describe('Module Loading', () => { + test('homepage loads without module errors', async ({ page }) => { + const errors: ConsoleErrorInfo[] = []; + + // Capture page errors (uncaught exceptions) + page.on('pageerror', (error) => { + if (!shouldIgnore(error.message) && isModuleLoadingError(error.message)) { + errors.push({ text: error.message, type: 'pageerror' }); + } + }); + + // Capture console errors + page.on('console', (msg) => { + const text = msg.text(); + if (msg.type() === 'error' && !shouldIgnore(text) && isModuleLoadingError(text)) { + errors.push({ text, type: 'console.error' }); + } + }); + + // Navigate and wait for full page load + await page.goto('/'); + await page.waitForLoadState('networkidle'); + + // Give time for dynamic imports to complete + await page.waitForTimeout(2000); + + // Assert no module loading errors + expect(errors, `Module loading errors detected:\n${errors.map((e) => ` [${e.type}] ${e.text}`).join('\n')}`).toHaveLength(0); + }); + + test('critical resources have correct MIME types', async ({ page }) => { + const mimeErrors: string[] = []; + + // Monitor network requests for MIME type issues + page.on('response', (response) => { + const url = response.url(); + const contentType = response.headers()['content-type'] || ''; + + // Check JavaScript files + if (url.endsWith('.js') || url.endsWith('.mjs') || url.includes('.vite-cache/deps/')) { + if (!contentType.includes('javascript') && !contentType.includes('application/javascript')) { + mimeErrors.push(`${url} has Content-Type: ${contentType || '(empty)'}`); + } + } + + // Check TypeScript files (in dev mode, served as JS) + if ((url.endsWith('.ts') || url.endsWith('.tsx')) && response.status() === 200) { + if (!contentType.includes('javascript') && !contentType.includes('typescript')) { + // In dev mode, Vite serves .ts/.tsx as transformed JS + // If content-type is html, something went wrong + if (contentType.includes('text/html')) { + mimeErrors.push(`${url} returned HTML instead of JavaScript`); + } + } + } + }); + + await page.goto('/'); + await page.waitForLoadState('networkidle'); + + expect(mimeErrors, `MIME type errors:\n${mimeErrors.join('\n')}`).toHaveLength(0); + }); +});