247 lines · 7.9 KB · TypeScript
RawDownload
import {  DEFAULT_SERVER_SETTINGS,  ProviderDriverKind,  ProviderInstanceId,} from "@t3tools/contracts";import { DEFAULT_CLIENT_SETTINGS } from "@t3tools/contracts/settings";import { beforeEach, describe, expect, it, vi } from "vite-plus/test"; import {  __resetClientSettingsPersistenceForTests,  __setClientSettingsForTests,  getClientSettings,  mergeEnvironmentSettings,  persistClientSettingsPatch,  persistClientSettingsUpdate,  resolveEnvironmentIdentificationMode,} from "./useSettings"; beforeEach(() => {  __resetClientSettingsPersistenceForTests();}); describe("persistClientSettingsUpdate", () => {  it("publishes the update only after persistence succeeds", async () => {    let finishPersistence!: () => void;    const persistence = new Promise<void>((resolve) => {      finishPersistence = resolve;    });    const setClientSettings = vi.fn(() => persistence);    __setClientSettingsForTests(DEFAULT_CLIENT_SETTINGS);     const pending = persistClientSettingsUpdate(      (current) => ({        ...current,        timestampFormat: "12-hour",      }),      setClientSettings,    );     expect(getClientSettings().timestampFormat).toBe(DEFAULT_CLIENT_SETTINGS.timestampFormat);    finishPersistence();    await expect(pending).resolves.toMatchObject({ timestampFormat: "12-hour" });    expect(getClientSettings().timestampFormat).toBe("12-hour");  });   it("keeps the current snapshot and propagates persistence failure", async () => {    const failure = new Error("disk full");    const setClientSettings = vi.fn().mockRejectedValue(failure);    __setClientSettingsForTests(DEFAULT_CLIENT_SETTINGS);     await expect(      persistClientSettingsUpdate(        (current) => ({ ...current, timestampFormat: "12-hour" }),        setClientSettings,      ),    ).rejects.toBe(failure);    expect(getClientSettings()).toBe(DEFAULT_CLIENT_SETTINGS);  });   it("preserves an optimistic write made while an awaited update persists", async () => {    let finishFirstPersistence!: () => void;    let durableSettings = DEFAULT_CLIENT_SETTINGS;    const firstPersistence = new Promise<void>((resolve) => {      finishFirstPersistence = resolve;    });    const persist = vi      .fn<(settings: typeof DEFAULT_CLIENT_SETTINGS) => Promise<void>>()      .mockImplementationOnce((settings) =>        firstPersistence.then(() => {          durableSettings = settings;        }),      )      .mockImplementation(async (settings) => {        durableSettings = settings;      });    __setClientSettingsForTests(DEFAULT_CLIENT_SETTINGS);    const importedProfile = { id: "profile-import", name: "Imported", kind: "persistent" as const };     const pending = persistClientSettingsUpdate(      (current) => ({        ...current,        browserProfiles: [...current.browserProfiles, importedProfile],      }),      persist,    );    await Promise.resolve();    persistClientSettingsPatch({ wordWrap: false }, persist);    finishFirstPersistence();    await pending;    await Promise.resolve();     expect(persist).toHaveBeenCalledTimes(3);    expect(persist.mock.calls[1]?.[0]).toMatchObject({      wordWrap: false,    });    expect(persist.mock.calls[1]?.[0].browserProfiles).toContainEqual(importedProfile);    expect(durableSettings.wordWrap).toBe(false);    expect(durableSettings.browserProfiles).toContainEqual(importedProfile);    expect(getClientSettings().wordWrap).toBe(false);    expect(getClientSettings().browserProfiles).toContainEqual(importedProfile);  });   it("orders an awaited update after an older optimistic write", async () => {    let finishOldWrite!: () => void;    let durableSettings = DEFAULT_CLIENT_SETTINGS;    const oldWrite = new Promise<void>((resolve) => {      finishOldWrite = resolve;    });    const persist = vi      .fn<(settings: typeof DEFAULT_CLIENT_SETTINGS) => Promise<void>>()      .mockImplementationOnce((settings) =>        oldWrite.then(() => {          durableSettings = settings;        }),      )      .mockImplementation(async (settings) => {        durableSettings = settings;      });    __setClientSettingsForTests(DEFAULT_CLIENT_SETTINGS);     persistClientSettingsPatch({ wordWrap: false }, persist);    const importedProfile = { id: "profile-import", name: "Imported", kind: "persistent" as const };    const registration = persistClientSettingsUpdate(      (current) => ({        ...current,        browserProfiles: [...current.browserProfiles, importedProfile],      }),      persist,    );    await Promise.resolve();    expect(persist).toHaveBeenCalledTimes(1);     finishOldWrite();    await registration;     expect(persist).toHaveBeenCalledTimes(2);    expect(durableSettings.wordWrap).toBe(false);    expect(durableSettings.browserProfiles).toContainEqual(importedProfile);  });   it("continues the queue after a rejected write", async () => {    const failure = new Error("disk full");    const persist = vi      .fn<(settings: typeof DEFAULT_CLIENT_SETTINGS) => Promise<void>>()      .mockRejectedValueOnce(failure)      .mockResolvedValue(undefined);    __setClientSettingsForTests(DEFAULT_CLIENT_SETTINGS);     await expect(      persistClientSettingsUpdate(        (current) => ({ ...current, timestampFormat: "12-hour" }),        persist,      ),    ).rejects.toBe(failure);    await expect(      persistClientSettingsUpdate((current) => ({ ...current, wordWrap: false }), persist),    ).resolves.toMatchObject({ wordWrap: false });  });}); describe("resolveEnvironmentIdentificationMode", () => {  it("keeps identification hidden until client settings hydrate", () => {    expect(resolveEnvironmentIdentificationMode({ mode: "artwork", settingsHydrated: false })).toBe(      "none",    );    expect(resolveEnvironmentIdentificationMode({ mode: "pill", settingsHydrated: true })).toBe(      "pill",    );  });   it("uses a pill instead of artwork with a palette theme", () => {    expect(      resolveEnvironmentIdentificationMode({        mode: "artwork",        settingsHydrated: true,        paletteThemeActive: true,      }),    ).toBe("pill");  });   it("respects none with a palette theme", () => {    expect(      resolveEnvironmentIdentificationMode({        mode: "none",        settingsHydrated: true,        paletteThemeActive: true,      }),    ).toBe("none");  });   it("keeps artwork when the palette theme opts into it", () => {    expect(      resolveEnvironmentIdentificationMode({        mode: "artwork",        settingsHydrated: true,        paletteThemeActive: true,        paletteThemeAllowsArtwork: true,      }),    ).toBe("artwork");  });}); describe("mergeEnvironmentSettings", () => {  it("combines the selected environment's server settings with client preferences", () => {    const serverSettings = {      ...DEFAULT_SERVER_SETTINGS,      providerInstances: {        [ProviderInstanceId.make("codex_remote")]: {          driver: ProviderDriverKind.make("codex"),          enabled: true,        },      },    };    const clientSettings = {      ...DEFAULT_CLIENT_SETTINGS,      favorites: [        {          provider: ProviderInstanceId.make("codex_remote"),          model: "gpt-5.4",        },      ],    };     const settings = mergeEnvironmentSettings(serverSettings, clientSettings);     expect(settings.providerInstances).toBe(serverSettings.providerInstances);    expect(settings.favorites).toBe(clientSettings.favorites);  });   it("keeps server settlement settings when legacy client data contains retired keys", () => {    const serverSettings = {      ...DEFAULT_SERVER_SETTINGS,      sidebarAutoSettleAfterDays: 14,      sidebarAutoSettleOnMerge: false,    };    const legacyClientSettings = {      ...DEFAULT_CLIENT_SETTINGS,      sidebarAutoSettleAfterDays: 1,      sidebarAutoSettleOnMerge: true,    };     const settings = mergeEnvironmentSettings(serverSettings, legacyClientSettings);     expect(settings.sidebarAutoSettleAfterDays).toBe(14);    expect(settings.sidebarAutoSettleOnMerge).toBe(false);  });});