diff --git a/apps/web/package.json b/apps/web/package.json
index b540fe35fa1b668188a005f8e58adce4043ab2a1..aa934cf5758f71c707cb339111c629ada1368f79 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -50,6 +50,7 @@
"tailwindcss": "^4.0.0",
"typescript": "catalog:",
"vite": "^8.0.0-beta.12",
- "vitest": "catalog:"
+ "vitest": "catalog:",
+ "vitest-browser-react": "^2.0.5"
}
}
diff --git a/apps/web/src/components/ChatView.browser.tsx b/apps/web/src/components/ChatView.browser.tsx
index 5af8c217b594815e4379897785db0bb6bc8b0160..ba8e8ff7817b9e7f68e11e467266ee7ea4c19a1b 100644
--- a/apps/web/src/components/ChatView.browser.tsx
+++ b/apps/web/src/components/ChatView.browser.tsx
@@ -15,8 +15,8 @@ import {
import { RouterProvider, createMemoryHistory } from "@tanstack/react-router";
import { HttpResponse, http, ws } from "msw";
import { setupWorker } from "msw/browser";
-import { createRoot, type Root } from "react-dom/client";
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
+import { render } from "vitest-browser-react";
import { getRouter } from "../router";
import { useStore } from "../store";
@@ -92,11 +92,7 @@ function createUserMessage(options: {
};
}
-function createAssistantMessage(options: {
- id: MessageId;
- text: string;
- offsetSeconds: number;
-}) {
+function createAssistantMessage(options: { id: MessageId; text: string; offsetSeconds: number }) {
return {
id: options.id,
role: "assistant" as const,
@@ -359,8 +355,9 @@ async function renderAndMeasureUserRow(options: {
}),
);
- const root: Root = createRoot(host);
- root.render();
+ const screen = await render(, {
+ container: host,
+ });
try {
await waitForLayout();
@@ -372,7 +369,7 @@ async function renderAndMeasureUserRow(options: {
let row: HTMLElement | null = null;
const timeoutAt = performance.now() + 8_000;
- while (performance.now() < timeoutAt) {
+ while (performance.now() < timeoutAt) {
scrollContainer.scrollTop = 0;
scrollContainer.dispatchEvent(new Event("scroll"));
await waitForLayout();
@@ -424,7 +421,7 @@ async function renderAndMeasureUserRow(options: {
return { measuredRowHeightPx, timelineWidthMeasuredPx, renderedInVirtualizedRegion };
} finally {
- root.unmount();
+ await screen.unmount();
host.remove();
}
}
diff --git a/bun.lock b/bun.lock
index 312b75e9132ee6ba18453ec46537d9f95958c892..a5ed3cf6903caf79c6e3144376e98a07a62f8f36 100644
--- a/bun.lock
+++ b/bun.lock
@@ -100,6 +100,7 @@
"typescript": "catalog:",
"vite": "^8.0.0-beta.12",
"vitest": "catalog:",
+ "vitest-browser-react": "^2.0.5",
},
},
"packages/contracts": {
@@ -1506,6 +1507,8 @@
"vitest": ["vitest@4.0.18", "", { "dependencies": { "@vitest/expect": "4.0.18", "@vitest/mocker": "4.0.18", "@vitest/pretty-format": "4.0.18", "@vitest/runner": "4.0.18", "@vitest/snapshot": "4.0.18", "@vitest/spy": "4.0.18", "@vitest/utils": "4.0.18", "es-module-lexer": "^1.7.0", "expect-type": "^1.2.2", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^3.10.0", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.0.3", "vite": "^6.0.0 || ^7.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.0.18", "@vitest/browser-preview": "4.0.18", "@vitest/browser-webdriverio": "4.0.18", "@vitest/ui": "4.0.18", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ=="],
+ "vitest-browser-react": ["vitest-browser-react@2.0.5", "", { "peerDependencies": { "@types/react": "^18.0.0 || ^19.0.0", "@types/react-dom": "^18.0.0 || ^19.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0", "vitest": "^4.0.0" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-YODQX8mHTJCyKNVYTWJrLEYrUtw+QfLl78owgvuE7C5ydgmGBq6v5s4jK2w6wdPhIZsN9PpV1rQbmAevWJjO9g=="],
+
"wait-on": ["wait-on@8.0.5", "", { "dependencies": { "axios": "^1.12.1", "joi": "^18.0.1", "lodash": "^4.17.21", "minimist": "^1.2.8", "rxjs": "^7.8.2" }, "bin": { "wait-on": "bin/wait-on" } }, "sha512-J3WlS0txVHkhLRb2FsmRg3dkMTCV1+M6Xra3Ho7HzZDHpE7DCOnoSoCJsZotrmW3uRMhvIJGSKUKrh/MeF4iag=="],
"webpack-virtual-modules": ["webpack-virtual-modules@0.6.2", "", {}, "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="],