1import {
2 DEFAULT_BROWSER_PROFILE_ID,
3 DEFAULT_CLIENT_SETTINGS,
4 FILL_PREVIEW_VIEWPORT,
5 type PreviewOpenInput,
6 type PreviewSessionSnapshot,
7 type ScopedThreadRef,
8} from "@t3tools/contracts";
9import { AsyncResult } from "effect/reactivity";
10import { beforeEach, describe, expect, it, vi } from "vite-plus/test";
11
12import {
13 applyPreviewServerSnapshot,
14 readThreadPreviewState,
15 resetPreviewStateForTests,
16} from "~/previewStateStore";
17import { selectThreadRightPanelState, useRightPanelStore } from "~/rightPanelStore";
18import { __setClientSettingsForTests } from "~/hooks/useSettings";
19
20import { addBrowserSurface } from "./addBrowserSurface";
21
22const threadRef = {
23 environmentId: "local" as ScopedThreadRef["environmentId"],
24 threadId: "thread-1" as ScopedThreadRef["threadId"],
25};
26
27const snapshot = (tabId: string): PreviewSessionSnapshot => ({
28 threadId: threadRef.threadId,
29 tabId,
30 navStatus: { _tag: "Idle" },
31 canGoBack: false,
32 canGoForward: false,
33 updatedAt: `2026-06-18T19:00:0${tabId.at(-1) ?? "0"}.000Z`,
34});
35
36beforeEach(() => {
37 __setClientSettingsForTests(DEFAULT_CLIENT_SETTINGS);
38 resetPreviewStateForTests();
39 useRightPanelStore.setState({ byThreadKey: {}, threadPanelVisibilityByThreadKey: {} });
40});
41
42describe("addBrowserSurface", () => {
43 it("opens under the requested profile", async () => {
44 const openPreview = vi.fn(async (_input: PreviewOpenInput) =>
45 AsyncResult.success(snapshot("tab-1")),
46 );
47
48 await addBrowserSurface({
49 threadRef,
50 openPreview: ({ input }) => openPreview(input),
51 profileId: "profile-work",
52 });
53
54 expect(openPreview).toHaveBeenCalledWith({
55 threadId: "thread-1",
56 viewport: FILL_PREVIEW_VIEWPORT,
57 profileId: "profile-work",
58 });
59 });
60
61 it("creates another preview session when a browser tab is already active", async () => {
62 const first = snapshot("tab-1");
63 const second = snapshot("tab-2");
64 applyPreviewServerSnapshot(threadRef, first);
65 useRightPanelStore.getState().openBrowser(threadRef, first.tabId);
66 const openPreview = vi.fn(async (_input: PreviewOpenInput) => AsyncResult.success(second));
67
68 await addBrowserSurface({ threadRef, openPreview: ({ input }) => openPreview(input) });
69
70 expect(openPreview).toHaveBeenCalledWith({
71 threadId: "thread-1",
72 viewport: FILL_PREVIEW_VIEWPORT,
73 profileId: DEFAULT_BROWSER_PROFILE_ID,
74 });
75 expect(Object.keys(readThreadPreviewState(threadRef).sessions)).toEqual(["tab-1", "tab-2"]);
76 expect(
77 selectThreadRightPanelState(
78 useRightPanelStore.getState().byThreadKey,
79 threadRef,
80 ).surfaces.map((surface) => surface.id),
81 ).toEqual(["browser:tab-1", "browser:tab-2"]);
82 });
83});