| ... | @@ -147,7 +147,8 @@ it("hot updates Tailwind classes when a source file changes in bundled dev", asy | ... | @@ -147,7 +147,8 @@ it("hot updates Tailwind classes when a source file changes in bundled dev", asy |
| 147 | ); | 147 | ); |
| 148 | const logger = createLogger("silent"); | 148 | const logger = createLogger("silent"); |
| 149 | logger.error = (message) => events.emit("error", new Error(message)); | 149 | 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"); |
| 151 | server = await createServer({ | 152 | server = await createServer({ |
| 152 | configFile: false, | 153 | configFile: false, |
| 153 | root, | 154 | root, |
| ... | @@ -168,19 +169,18 @@ it("hot updates Tailwind classes when a source file changes in bundled dev", asy | ... | @@ -168,19 +169,18 @@ it("hot updates Tailwind classes when a source file changes in bundled dev", asy |
| 168 | transform(code, id) { | 169 | transform(code, id) { |
| 169 | if (id.endsWith("/style.css")) css = code; | 170 | if (id.endsWith("/style.css")) css = code; |
| 170 | }, | 171 | }, |
| 171 | generateBundle() { | 172 | async generateBundle() { |
| 172 | events.emit("built"); | 173 | // Keep the build pending until the socket can receive Vite's ready message. |
| | 174 | await connected; |
| 173 | }, | 175 | }, |
| 174 | }, | 176 | }, |
| 175 | ], | 177 | ], |
| 176 | server: { host: "127.0.0.1", port: 0 }, | 178 | server: { host: "127.0.0.1", port: 0 }, |
| 177 | }); | 179 | }); |
| 178 | await server.listen(); | 180 | await server.listen(); |
| 179 | await built; | | |
| 180 | const address = server.httpServer?.address(); | 181 | const address = server.httpServer?.address(); |
| 181 | if (!address || typeof address === "string") throw new Error("Vite did not bind a port"); | 182 | if (!address || typeof address === "string") throw new Error("Vite did not bind a port"); |
| 182 | | 183 | |
| 183 | const connected = NodeEvents.EventEmitter.once(events, "connected"); | | |
| 184 | server.ws.on("vite:client-connected", () => events.emit("connected")); | 184 | server.ws.on("vite:client-connected", () => events.emit("connected")); |
| 185 | socket = new WebSocket( | 185 | socket = new WebSocket( |
| 186 | `ws://127.0.0.1:${address.port}/?token=${server.config.webSocketToken}`, | 186 | `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 | ... | @@ -197,16 +197,21 @@ it("hot updates Tailwind classes when a source file changes in bundled dev", asy |
| 197 | }); | 197 | }); |
| 198 | socket.addEventListener("message", ({ data }) => { | 198 | socket.addEventListener("message", ({ data }) => { |
| 199 | const message: unknown = JSON.parse(String(data)); | 199 | const message: unknown = JSON.parse(String(data)); |
| 200 | if ( | 200 | if (message !== null && typeof message === "object" && "type" in message) { |
| 201 | message !== null && | 201 | // generateBundle runs before Vite stores the files for HTTP requests. |
| 202 | typeof message === "object" && | 202 | if ( |
| 203 | "type" in message && | 203 | message.type === "full-reload" && |
| 204 | message.type === "bundled-dev-update" | 204 | "ifFallback" in message && |
| 205 | ) { | 205 | message.ifFallback === true |
| 206 | events.emit("updated"); | 206 | ) { |
| | 207 | events.emit("ready"); |
| | 208 | } else if (message.type === "bundled-dev-update") { |
| | 209 | events.emit("updated"); |
| | 210 | } |
| 207 | } | 211 | } |
| 208 | }); | 212 | }); |
| 209 | await connected; | 213 | await connected; |
| | 214 | await ready; |
| 210 | const entry = await fetch(`http://127.0.0.1:${address.port}/assets/index.js`); | 215 | const entry = await fetch(`http://127.0.0.1:${address.port}/assets/index.js`); |
| 211 | expect(entry.headers.get("content-type")).toContain("javascript"); | 216 | expect(entry.headers.get("content-type")).toContain("javascript"); |
| 212 | await entry.text(); | 217 | await entry.text(); |