import { DEFAULT_BROWSER_PROFILE_ID, DEFAULT_CLIENT_SETTINGS, FILL_PREVIEW_VIEWPORT, type PreviewOpenInput, type PreviewSessionSnapshot, type ScopedThreadRef,} from "@t3tools/contracts";import * as Cause from "effect/Cause";import { AsyncResult } from "effect/unstable/reactivity";import { afterEach, beforeEach, describe, expect, it, vi } from "vite-plus/test"; import * as browserDefaults from "~/browser/browserDefaults";import { BrowserSettingsReadError, openUrlInPreview } from "~/browser/openFileInPreview";import { __setClientSettingsForTests } from "~/hooks/useSettings";import { readThreadPreviewState, resetPreviewStateForTests } from "~/previewStateStore"; import { openPreviewSession } from "./openPreviewSession"; const threadRef = { environmentId: "local" as ScopedThreadRef["environmentId"], threadId: "thread-1" as ScopedThreadRef["threadId"],}; const snapshot: PreviewSessionSnapshot = { threadId: threadRef.threadId, tabId: "tab-1", navStatus: { _tag: "Loading", url: "https://t3.chat/", title: "", }, canGoBack: false, canGoForward: false, updatedAt: "2026-06-11T23:00:00.000Z",}; beforeEach(() => { resetPreviewStateForTests(); __setClientSettingsForTests(DEFAULT_CLIENT_SETTINGS);}); afterEach(() => { vi.restoreAllMocks();}); describe("openPreviewSession", () => { it("creates an idle tab without recording a recently visited URL", async () => { const idleSnapshot: PreviewSessionSnapshot = { ...snapshot, tabId: "tab-blank", navStatus: { _tag: "Idle" }, }; const open = vi.fn(async (_input: PreviewOpenInput) => AsyncResult.success(idleSnapshot)); await openPreviewSession({ openPreview: ({ input }) => open(input), threadRef, }); expect(open).toHaveBeenCalledWith({ threadId: "thread-1", viewport: FILL_PREVIEW_VIEWPORT, profileId: DEFAULT_BROWSER_PROFILE_ID, }); expect(readThreadPreviewState(threadRef).snapshot).toEqual(idleSnapshot); expect(readThreadPreviewState(threadRef).recentlySeenUrls).toEqual([]); }); it("applies the RPC response without waiting for a preview event", async () => { const open = vi.fn(async (_input: PreviewOpenInput) => AsyncResult.success(snapshot)); await openPreviewSession({ openPreview: ({ input }) => open(input), threadRef, url: "t3.chat", }); expect(open).toHaveBeenCalledWith({ threadId: "thread-1", url: "t3.chat", viewport: FILL_PREVIEW_VIEWPORT, profileId: DEFAULT_BROWSER_PROFILE_ID, }); expect(readThreadPreviewState(threadRef).snapshot).toEqual(snapshot); expect(readThreadPreviewState(threadRef).recentlySeenUrls).toEqual(["https://t3.chat/"]); }); it("returns failures without mutating preview state", async () => { const failure = new Error("preview unavailable"); const result = await openPreviewSession({ openPreview: async () => AsyncResult.failure(Cause.fail(failure)), threadRef, url: "t3.chat", }); expect(result._tag).toBe("Failure"); expect(readThreadPreviewState(threadRef).snapshot).toBeNull(); expect(readThreadPreviewState(threadRef).recentlySeenUrls).toEqual([]); }); it.each(["session", "link"] as const)( "does not open a %s with unread settings and uses the saved profile on retry", async (entryPoint) => { const failure = new Error("Settings read failed"); vi.spyOn(browserDefaults, "resolveBrowserDefaults").mockRejectedValueOnce(failure); const viewport = { _tag: "freeform", width: 1280, height: 720 } as const; __setClientSettingsForTests({ ...DEFAULT_CLIENT_SETTINGS, browserDefaultViewport: viewport, browserDefaultProfileId: "work", browserProfiles: [{ id: "work", name: "Work", kind: "persistent" }], }); const openPreview = vi.fn(async () => AsyncResult.success(snapshot)); const input = { openPreview, threadRef, url: "https://t3.chat/" }; const open = entryPoint === "session" ? openPreviewSession : openUrlInPreview; const result = await open(input); expect(result._tag).toBe("Failure"); if (result._tag === "Failure") { expect(Cause.squash(result.cause)).toBeInstanceOf(BrowserSettingsReadError); expect(Cause.squash(result.cause)).toMatchObject({ cause: failure }); } expect(openPreview).not.toHaveBeenCalled(); expect(readThreadPreviewState(threadRef).snapshot).toBeNull(); expect(readThreadPreviewState(threadRef).recentlySeenUrls).toEqual([]); await expect(open(input)).resolves.toMatchObject({ _tag: "Success" }); expect(openPreview).toHaveBeenCalledExactlyOnceWith({ environmentId: threadRef.environmentId, input: { threadId: threadRef.threadId, url: input.url, viewport, profileId: "work", }, }); }, );});
import {
DEFAULT_BROWSER_PROFILE_ID,
DEFAULT_CLIENT_SETTINGS,
FILL_PREVIEW_VIEWPORT,
type PreviewOpenInput,
type PreviewSessionSnapshot,
type ScopedThreadRef,
} from "@t3tools/contracts";
import * as Cause from "effect/Cause";
import { AsyncResult } from "effect/unstable/reactivity";
import { afterEach, beforeEach, describe, expect, it, vi } from "vite-plus/test";
import * as browserDefaults from "~/browser/browserDefaults";
import { BrowserSettingsReadError, openUrlInPreview } from "~/browser/openFileInPreview";
import { __setClientSettingsForTests } from "~/hooks/useSettings";
import { readThreadPreviewState, resetPreviewStateForTests } from "~/previewStateStore";
import { openPreviewSession } from "./openPreviewSession";
const threadRef = {
environmentId: "local" as ScopedThreadRef["environmentId"],
threadId: "thread-1" as ScopedThreadRef["threadId"],
};
const snapshot: PreviewSessionSnapshot = {
threadId: threadRef.threadId,
tabId: "tab-1",
navStatus: {
_tag: "Loading",
url: "https://t3.chat/",
title: "",
},
canGoBack: false,
canGoForward: false,
updatedAt: "2026-06-11T23:00:00.000Z",
};
beforeEach(() => {
resetPreviewStateForTests();
__setClientSettingsForTests(DEFAULT_CLIENT_SETTINGS);
});
afterEach(() => {
vi.restoreAllMocks();
});
describe("openPreviewSession", () => {
it("creates an idle tab without recording a recently visited URL", async () => {
const idleSnapshot: PreviewSessionSnapshot = {
...snapshot,
tabId: "tab-blank",
navStatus: { _tag: "Idle" },
};
const open = vi.fn(async (_input: PreviewOpenInput) => AsyncResult.success(idleSnapshot));
await openPreviewSession({
openPreview: ({ input }) => open(input),
threadRef,
});
expect(open).toHaveBeenCalledWith({
threadId: "thread-1",
viewport: FILL_PREVIEW_VIEWPORT,
profileId: DEFAULT_BROWSER_PROFILE_ID,
});
expect(readThreadPreviewState(threadRef).snapshot).toEqual(idleSnapshot);
expect(readThreadPreviewState(threadRef).recentlySeenUrls).toEqual([]);
});
it("applies the RPC response without waiting for a preview event", async () => {
const open = vi.fn(async (_input: PreviewOpenInput) => AsyncResult.success(snapshot));
await openPreviewSession({
openPreview: ({ input }) => open(input),
threadRef,
url: "t3.chat",
});
expect(open).toHaveBeenCalledWith({
threadId: "thread-1",
url: "t3.chat",
viewport: FILL_PREVIEW_VIEWPORT,
profileId: DEFAULT_BROWSER_PROFILE_ID,
});
expect(readThreadPreviewState(threadRef).snapshot).toEqual(snapshot);
expect(readThreadPreviewState(threadRef).recentlySeenUrls).toEqual(["https://t3.chat/"]);
});
it("returns failures without mutating preview state", async () => {
const failure = new Error("preview unavailable");
const result = await openPreviewSession({
openPreview: async () => AsyncResult.failure(Cause.fail(failure)),
threadRef,
url: "t3.chat",
});
expect(result._tag).toBe("Failure");
expect(readThreadPreviewState(threadRef).snapshot).toBeNull();
expect(readThreadPreviewState(threadRef).recentlySeenUrls).toEqual([]);
});
it.each(["session", "link"] as const)(
"does not open a %s with unread settings and uses the saved profile on retry",
async (entryPoint) => {
const failure = new Error("Settings read failed");
vi.spyOn(browserDefaults, "resolveBrowserDefaults").mockRejectedValueOnce(failure);
const viewport = { _tag: "freeform", width: 1280, height: 720 } as const;
__setClientSettingsForTests({
...DEFAULT_CLIENT_SETTINGS,
browserDefaultViewport: viewport,
browserDefaultProfileId: "work",
browserProfiles: [{ id: "work", name: "Work", kind: "persistent" }],
});
const openPreview = vi.fn(async () => AsyncResult.success(snapshot));
const input = { openPreview, threadRef, url: "https://t3.chat/" };
const open = entryPoint === "session" ? openPreviewSession : openUrlInPreview;
const result = await open(input);
expect(result._tag).toBe("Failure");
if (result._tag === "Failure") {
expect(Cause.squash(result.cause)).toBeInstanceOf(BrowserSettingsReadError);
expect(Cause.squash(result.cause)).toMatchObject({ cause: failure });
}
expect(openPreview).not.toHaveBeenCalled();
expect(readThreadPreviewState(threadRef).snapshot).toBeNull();
expect(readThreadPreviewState(threadRef).recentlySeenUrls).toEqual([]);
await expect(open(input)).resolves.toMatchObject({ _tag: "Success" });
expect(openPreview).toHaveBeenCalledExactlyOnceWith({
environmentId: threadRef.environmentId,
input: {
threadId: threadRef.threadId,
url: input.url,
viewport,
profileId: "work",
},
});
},
);
});