authorgravatar for me@t3.ggTheo Browne <me@t3.gg> 2026-09-03 19:50:20-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-03 19:50:20-07:00
logfee2e0ff8168b82ab19f496fcc874c1f3871f522
treee3c4d5e7e8e0c068300182b61a13e54e1a0ea5ae
parent9e1bc36a0843699db54ee28abbdac70584ae8f33
signature Signed by PGP key B5690EEEBB952194

test(web): fix flaky startup and Tailwind tests (#9558)


2 files changed, 21 insertions(+), 15 deletions(-)

apps/web/src/bootstrap.test.ts+4-3
......@@ -30,9 +30,6 @@ describe("app startup failures", () => {
3030
3131 beforeEach(() => {
3232 vi.resetModules();
33 vi.doMock("./main", () => {
34 throw new Error("@vitejs/plugin-react can't detect preamble. Something is wrong.");
35 });
3633 bootShell = new BootElement("div");
3734 vi.stubGlobal("document", {
3835 getElementById: () => bootShell,
......@@ -51,12 +48,16 @@ describe("app startup failures", () => {
5148 });
5249
5350 afterEach(() => {
51 vi.doUnmock("./main");
5452 vi.unstubAllGlobals();
5553 vi.unstubAllEnvs();
5654 vi.restoreAllMocks();
5755 });
5856
5957 it("replaces the splash when an app import throws before main can run", async () => {
58 vi.doMock("./main", () => {
59 throw new Error("@vitejs/plugin-react can't detect preamble. Something is wrong.");
60 });
6061 const reload = vi.fn();
6162 vi.stubGlobal("window", { location: { reload } });
6263
apps/web/src/bundledDev.test.ts+17-12
......@@ -147,7 +147,8 @@ it("hot updates Tailwind classes when a source file changes in bundled dev", asy
147147 );
148148 const logger = createLogger("silent");
149149 logger.error = (message) => events.emit("error", new Error(message));
150 const built = NodeEvents.EventEmitter.once(events, "built");
150 const connected = NodeEvents.EventEmitter.once(events, "connected");
151 const ready = NodeEvents.EventEmitter.once(events, "ready");
151152 server = await createServer({
152153 configFile: false,
153154 root,
......@@ -168,19 +169,18 @@ it("hot updates Tailwind classes when a source file changes in bundled dev", asy
168169 transform(code, id) {
169170 if (id.endsWith("/style.css")) css = code;
170171 },
171 generateBundle() {
172 events.emit("built");
172 async generateBundle() {
173 // Keep the build pending until the socket can receive Vite's ready message.
174 await connected;
173175 },
174176 },
175177 ],
176178 server: { host: "127.0.0.1", port: 0 },
177179 });
178180 await server.listen();
179 await built;
180181 const address = server.httpServer?.address();
181182 if (!address || typeof address === "string") throw new Error("Vite did not bind a port");
182183
183 const connected = NodeEvents.EventEmitter.once(events, "connected");
184184 server.ws.on("vite:client-connected", () => events.emit("connected"));
185185 socket = new WebSocket(
186186 `ws://127.0.0.1:${address.port}/?token=${server.config.webSocketToken}`,
......@@ -197,16 +197,21 @@ it("hot updates Tailwind classes when a source file changes in bundled dev", asy
197197 });
198198 socket.addEventListener("message", ({ data }) => {
199199 const message: unknown = JSON.parse(String(data));
200 if (
201 message !== null &&
202 typeof message === "object" &&
203 "type" in message &&
204 message.type === "bundled-dev-update"
205 ) {
206 events.emit("updated");
200 if (message !== null && typeof message === "object" && "type" in message) {
201 // generateBundle runs before Vite stores the files for HTTP requests.
202 if (
203 message.type === "full-reload" &&
204 "ifFallback" in message &&
205 message.ifFallback === true
206 ) {
207 events.emit("ready");
208 } else if (message.type === "bundled-dev-update") {
209 events.emit("updated");
210 }
207211 }
208212 });
209213 await connected;
214 await ready;
210215 const entry = await fetch(`http://127.0.0.1:${address.port}/assets/index.js`);
211216 expect(entry.headers.get("content-type")).toContain("javascript");
212217 await entry.text();