187 lines · 5.7 KB · TypeScript
RawDownload
import {  DEFAULT_PREVIEW_APPEARANCE,  DEFAULT_PREVIEW_ZOOM_FACTOR,  DEFAULT_CLIENT_SETTINGS,  EnvironmentId,  ThreadId,} from "@t3tools/contracts";import { afterEach, beforeEach, describe, expect, it, vi } from "vite-plus/test"; const { closeTab, createTab, stopBrowserRecording } = vi.hoisted(() => ({  closeTab: vi.fn<(tabId: string) => Promise<void>>(async () => undefined),  createTab: vi.fn<() => Promise<void>>(),  stopBrowserRecording: vi.fn(async () => null),})); vi.mock("~/components/preview/previewBridge", () => ({  previewBridge: { closeTab, createTab },})); vi.mock("./browserRecording", () => ({  stopBrowserRecording,})); import { acquireDesktopTab } from "./desktopTabLifetime";import * as browserDefaults from "./browserDefaults";import { __setClientSettingsForTests } from "~/hooks/useSettings"; /** Tests load default settings unless they select other preferences. */const DEFAULT_TAB_STATE = {  zoomFactor: DEFAULT_PREVIEW_ZOOM_FACTOR,  colorScheme: DEFAULT_PREVIEW_APPEARANCE,};import { previewRuntimeTabId } from "./previewRuntimeTabId"; describe("desktopTabLifetime", () => {  beforeEach(() => {    __setClientSettingsForTests(DEFAULT_CLIENT_SETTINGS);    closeTab.mockClear();    createTab.mockClear();    stopBrowserRecording.mockClear();    vi.stubGlobal("window", globalThis);  });   afterEach(() => {    vi.useRealTimers();    vi.unstubAllGlobals();    vi.restoreAllMocks();  });   it("does not create a desktop tab after a failed settings read and permits a later retry", async () => {    vi.useFakeTimers();    const failure = new Error("Settings read failed");    vi.spyOn(browserDefaults, "resolveBrowserDefaults").mockRejectedValueOnce(failure);    const failed = acquireDesktopTab("tab_settings_retry");     await expect(failed.ready).rejects.toBe(failure);    expect(createTab).not.toHaveBeenCalled();    failed.release();    await vi.advanceTimersByTimeAsync(0);     __setClientSettingsForTests({      ...DEFAULT_CLIENT_SETTINGS,      browserDefaultZoomFactor: 1.25,      browserDefaultAppearance: "dark",    });    createTab.mockResolvedValueOnce(undefined);    const retry = acquireDesktopTab("tab_settings_retry");    await retry.ready;     expect(createTab).toHaveBeenCalledExactlyOnceWith("tab_settings_retry", {      zoomFactor: 1.25,      colorScheme: "dark",    });    retry.release();    await vi.advanceTimersByTimeAsync(0);  });   it("shares tab creation readiness across concurrent leases", async () => {    let resolveCreation: (() => void) | undefined;    createTab.mockReturnValueOnce(      new Promise<void>((resolve) => {        resolveCreation = resolve;      }),    );     const first = acquireDesktopTab("tab_readiness");    const second = acquireDesktopTab("tab_readiness");     // Both leases share one creation, and it is still in flight: creation now    // waits for client settings to hydrate so the guest is born at the user's    // zoom and appearance rather than painting at the defaults first.    expect(first.ready).toBe(second.ready);     let ready = false;    void first.ready.then(() => {      ready = true;    });    await vi.waitFor(() => expect(createTab).toHaveBeenCalledOnce());    expect(ready).toBe(false);     resolveCreation?.();    await first.ready;    expect(ready).toBe(true);  });   it("keeps identical server tab ids from two environments in separate desktop slots", async () => {    vi.useFakeTimers();    createTab.mockResolvedValue(undefined);    const tabA = previewRuntimeTabId(      {        environmentId: EnvironmentId.make("environment-a"),        threadId: ThreadId.make("thread-a"),      },      "epoch-a",      "tab_1",    );    const tabB = previewRuntimeTabId(      {        environmentId: EnvironmentId.make("environment-b"),        threadId: ThreadId.make("thread-b"),      },      "epoch-b",      "tab_1",    );     const first = acquireDesktopTab(tabA);    const second = acquireDesktopTab(tabB);    await Promise.all([first.ready, second.ready]);     expect(createTab).toHaveBeenCalledWith(tabA, DEFAULT_TAB_STATE);    expect(createTab).toHaveBeenCalledWith(tabB, DEFAULT_TAB_STATE);    expect(createTab).toHaveBeenCalledTimes(2);     first.release();    second.release();    await vi.advanceTimersByTimeAsync(0);  });   it("stops recording before closing the final desktop tab lease", async () => {    vi.useFakeTimers();    let resolveStop: (() => void) | undefined;    stopBrowserRecording.mockReturnValueOnce(      new Promise<null>((resolve) => {        resolveStop = () => resolve(null);      }),    );    createTab.mockResolvedValueOnce(undefined);     const lease = acquireDesktopTab("tab_recording_cleanup");    await lease.ready;    lease.release();    await vi.advanceTimersByTimeAsync(0);     expect(stopBrowserRecording).toHaveBeenCalledWith("tab_recording_cleanup");    expect(closeTab).not.toHaveBeenCalled();     resolveStop?.();    await Promise.resolve();    await Promise.resolve();    expect(closeTab).toHaveBeenCalledWith("tab_recording_cleanup");  });   it("waits for an in-flight close before recreating a reacquired tab", async () => {    vi.useFakeTimers();    let resolveClose: (() => void) | undefined;    createTab.mockResolvedValue(undefined);    closeTab.mockReturnValueOnce(      new Promise<void>((resolve) => {        resolveClose = resolve;      }),    );     const initial = acquireDesktopTab("tab_close_reacquire");    await initial.ready;    initial.release();    await vi.advanceTimersByTimeAsync(0);     expect(closeTab).toHaveBeenCalledWith("tab_close_reacquire");     const reacquired = acquireDesktopTab("tab_close_reacquire");    expect(createTab).toHaveBeenCalledTimes(1);     resolveClose?.();    await reacquired.ready;    expect(createTab).toHaveBeenCalledTimes(2);  });});