diff --git a/apps/dashboard/playwright.config.ts b/apps/dashboard/playwright.config.ts index f7c0d9055..39186a1fc 100644 --- a/apps/dashboard/playwright.config.ts +++ b/apps/dashboard/playwright.config.ts @@ -7,7 +7,9 @@ export default defineConfig({ forbidOnly: !!process.env.CI, fullyParallel: true, projects: [{ name: "chromium", use: { ...devices["Desktop Chrome"] } }], - reporter: process.env.CI ? [["list"], ["github"]] : [["list"]], + // "html" writes playwright-report/, which the e2e workflow uploads as an artifact on + // failure — without it a red nightly run leaves nothing to debug from. + reporter: process.env.CI ? [["list"], ["github"], ["html", { open: "never" }]] : [["list"]], retries: process.env.CI ? 2 : 0, testDir: "./e2e", timeout: 60_000, diff --git a/apps/frontend/package.json b/apps/frontend/package.json index 61a8b0b17..f971523e8 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -111,6 +111,7 @@ "eslint-plugin-storybook": "^9.1.4", "husky": ">=6", "jsdom": "26", + "lightningcss": "^1.32.0", "lint-staged": ">=10", "msw": "^2.14.6", "prettier": "catalog:", diff --git a/apps/frontend/playwright.config.ts b/apps/frontend/playwright.config.ts index bb4142e79..881ab9ce1 100644 --- a/apps/frontend/playwright.config.ts +++ b/apps/frontend/playwright.config.ts @@ -7,7 +7,9 @@ export default defineConfig({ forbidOnly: !!process.env.CI, fullyParallel: true, projects: [{ name: "chromium", use: { ...devices["Desktop Chrome"] } }], - reporter: process.env.CI ? [["list"], ["github"]] : [["list"]], + // "html" writes playwright-report/, which the e2e workflow uploads as an artifact on + // failure — without it a red nightly run leaves nothing to debug from. + reporter: process.env.CI ? [["list"], ["github"], ["html", { open: "never" }]] : [["list"]], retries: process.env.CI ? 2 : 0, testDir: "./e2e", timeout: 60_000, diff --git a/apps/frontend/src/tests/vite-single-instance.test.ts b/apps/frontend/src/tests/vite-single-instance.test.ts new file mode 100644 index 000000000..9e1d04bc8 --- /dev/null +++ b/apps/frontend/src/tests/vite-single-instance.test.ts @@ -0,0 +1,29 @@ +import { realpathSync } from "node:fs"; +import { createRequire } from "node:module"; +import { describe, expect, it } from "vitest"; + +// TanStack Start decides whether to install its SSR dev middleware with +// `isRunnableDevEnvironment(env)`, which is an `instanceof` check. If the plugin resolves a +// different copy of Vite than the one that created the dev server, that check silently fails, +// the middleware is never installed and every dev route falls through to a 404 — the app is +// unreachable locally and the Playwright webServer never becomes ready. +// +// Bun installs a separate copy of Vite per resolved optional-peer set, so this breaks as soon +// as the app and the plugin disagree on one of them (`lightningcss` is why the frontend depends +// on it directly). Compare the resolved module paths rather than trusting the version alone. +const require = createRequire(import.meta.url); + +function resolveViteFrom(requirer: NodeRequire): string { + return realpathSync(requirer.resolve("vite")); +} + +describe("Vite module identity", () => { + it("resolves the same Vite copy for the app and for the TanStack Start plugin", () => { + const appVite = resolveViteFrom(require); + + const reactStart = createRequire(require.resolve("@tanstack/react-start/package.json")); + const startPlugin = createRequire(reactStart.resolve("@tanstack/start-plugin-core/package.json")); + + expect(resolveViteFrom(startPlugin)).toBe(appVite); + }); +}); diff --git a/bun.lock b/bun.lock index 7f8145c57..283250bb7 100644 --- a/bun.lock +++ b/bun.lock @@ -260,6 +260,7 @@ "eslint-plugin-storybook": "^9.1.4", "husky": ">=6", "jsdom": "26", + "lightningcss": "^1.32.0", "lint-staged": ">=10", "msw": "^2.14.6", "prettier": "catalog:",