import path from "node:path"; import { expect, test } from "@playwright/test"; import { createServer, type ViteDevServer } from "../../ui/node_modules/vite/dist/node/index.js"; let server: ViteDevServer; let origin: string; const uiRoot = path.resolve(import.meta.dirname, "../../ui"); const probePath = path.join(uiRoot, "src/__company_context_probe.tsx"); // Use real Vite module instances and React contexts. Re-importing a refreshed // consumer must still see a provider retained from the previous module version. test.beforeAll(async () => { server = await createServer({ root: uiRoot, configFile: false, resolve: { alias: { "@": path.join(uiRoot, "src") } }, esbuild: { jsx: "automatic" }, server: { host: "127.0.0.1", port: 0 }, plugins: [{ name: "company-context-regression", resolveId(id) { if (id === "/src/__company_context_probe.tsx") return probePath; }, load(id) { if (id !== probePath) return; return ` import React from "react"; import { createRoot } from "react-dom/client"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { CompanyProvider, useCompany } from "/src/context/CompanyContext.tsx"; const root = createRoot(document.getElementById("root")); const client = new QueryClient({ defaultOptions: { queries: { retry: false } } }); function render(hook, generation) { function Consumer() { return
{generation + ":" + (hook().selectedCompanyId ?? "loading")}
; } root.render(); } render(useCompany, "initial"); window.refreshConsumer = async () => { const refreshed = await import(/* @vite-ignore */ "/src/context/CompanyContext.tsx?t=" + Date.now()); render(refreshed.useCompany, "refreshed"); }; `; }, configureServer(vite) { vite.middlewares.use((req, res, next) => { if (req.url !== "/") return next(); res.setHeader("Content-Type", "text/html"); res.end('
'); }); }, }], }); await server.listen(); const address = server.httpServer!.address(); if (!address || typeof address === "string") throw new Error("Missing test server address"); origin = `http://127.0.0.1:${address.port}`; }); test.afterAll(async () => { await server?.close(); }); test("a refreshed company consumer reads the retained provider", async ({ page }) => { await page.route("**/api/**", async (route) => { const pathname = new URL(route.request().url()).pathname; if (!pathname.startsWith("/api/")) return route.continue(); const body = pathname === "/api/auth/get-session" ? { user: { id: "test-user" }, session: { userId: "test-user" } } : pathname === "/api/companies" ? [{ id: "test-company", name: "Test company", status: "active" }] : []; await route.fulfill({ json: body }); }); const errors: string[] = []; page.on("pageerror", (error) => { errors.push(error.message); }); await page.goto(origin); await expect(page.getByRole("main")).toHaveText("initial:test-company"); await page.evaluate(() => (window as unknown as { refreshConsumer: () => Promise }).refreshConsumer()); await expect(page.getByRole("main")).toHaveText("refreshed:test-company"); expect(errors).toEqual([]); });