import { describe, expect, it, vi } from "vite-plus/test";import type { EnvironmentId } from "@t3tools/contracts"; import { browserProfileRemovalAvailable, clearBrowserProfileData, importFailureReason,} from "./IntegrationsSettings"; const environmentId = "environment-a" as EnvironmentId;const secondEnvironmentId = "environment-b" as EnvironmentId; describe("clearBrowserProfileData", () => { it("waits for cookie and cache cleanup", async () => { const clearCookies = vi.fn().mockResolvedValue(undefined); const clearCache = vi.fn().mockResolvedValue(undefined); await clearBrowserProfileData({ clearCookies, clearCache }, [environmentId], "profile-a"); expect(clearCookies).toHaveBeenCalledWith(environmentId, "profile-a"); expect(clearCache).toHaveBeenCalledWith(environmentId, "profile-a"); }); it("clears every known environment before succeeding", async () => { const clearCookies = vi.fn().mockResolvedValue(undefined); const clearCache = vi.fn().mockResolvedValue(undefined); await clearBrowserProfileData( { clearCookies, clearCache }, [environmentId, secondEnvironmentId], "profile-a", ); expect(clearCookies.mock.calls).toEqual([ [environmentId, "profile-a"], [secondEnvironmentId, "profile-a"], ]); expect(clearCache.mock.calls).toEqual([ [environmentId, "profile-a"], [secondEnvironmentId, "profile-a"], ]); }); it("propagates cleanup failures", async () => { const failure = new Error("clear failed"); await expect( clearBrowserProfileData( { clearCookies: vi.fn().mockRejectedValue(failure), clearCache: vi.fn().mockResolvedValue(undefined), }, [environmentId], "profile-a", ), ).rejects.toBe(failure); }); it("does not report success without an environment or bridge", async () => { const bridge = { clearCookies: vi.fn().mockResolvedValue(undefined), clearCache: vi.fn().mockResolvedValue(undefined), }; await expect(clearBrowserProfileData(bridge, [], "profile-a")).rejects.toThrow(); await expect(clearBrowserProfileData(null, [environmentId], "profile-a")).rejects.toThrow(); expect(bridge.clearCookies).not.toHaveBeenCalled(); expect(bridge.clearCache).not.toHaveBeenCalled(); });}); describe("browserProfileRemovalAvailable", () => { it("requires a ready non-empty catalog and desktop bridge", () => { expect(browserProfileRemovalAvailable(true, true, 1)).toBe(true); expect(browserProfileRemovalAvailable(true, true, 0)).toBe(false); expect(browserProfileRemovalAvailable(true, false, 1)).toBe(false); expect(browserProfileRemovalAvailable(false, true, 1)).toBe(false); });}); // Mirrors `BrowserImportFailedError.message`, which IPC flattens to a string// before the renderer sees it.const failure = (reason: string) => ({ message: `Importing cookies from safari failed: ${reason}.`,}); describe("importFailureReason", () => { it("recovers the reason token from the flattened message", () => { expect(importFailureReason(failure("needsFullDiskAccess"))).toBe("needsFullDiskAccess"); expect(importFailureReason(failure("browserRunning"))).toBe("browserRunning"); expect(importFailureReason(failure("readFailed"))).toBe("readFailed"); expect(importFailureReason(failure("keychainUnavailable"))).toBe("keychainUnavailable"); // A settings write that fails after the cookies landed is its own case, // not a read failure over a database that was in fact read. expect(importFailureReason(failure("profileNotSaved"))).toBe("profileNotSaved"); expect(importFailureReason(failure("profileLimitReached"))).toBe("profileLimitReached"); }); it("falls back to readFailed for anything it cannot classify", () => { expect(importFailureReason(new Error("something else entirely"))).toBe("readFailed"); expect(importFailureReason(undefined)).toBe("readFailed"); });});
import { describe, expect, it, vi } from "vite-plus/test";
import type { EnvironmentId } from "@t3tools/contracts";
import {
browserProfileRemovalAvailable,
clearBrowserProfileData,
importFailureReason,
} from "./IntegrationsSettings";
const environmentId = "environment-a" as EnvironmentId;
const secondEnvironmentId = "environment-b" as EnvironmentId;
describe("clearBrowserProfileData", () => {
it("waits for cookie and cache cleanup", async () => {
const clearCookies = vi.fn().mockResolvedValue(undefined);
const clearCache = vi.fn().mockResolvedValue(undefined);
await clearBrowserProfileData({ clearCookies, clearCache }, [environmentId], "profile-a");
expect(clearCookies).toHaveBeenCalledWith(environmentId, "profile-a");
expect(clearCache).toHaveBeenCalledWith(environmentId, "profile-a");
});
it("clears every known environment before succeeding", async () => {
const clearCookies = vi.fn().mockResolvedValue(undefined);
const clearCache = vi.fn().mockResolvedValue(undefined);
await clearBrowserProfileData(
{ clearCookies, clearCache },
[environmentId, secondEnvironmentId],
"profile-a",
);
expect(clearCookies.mock.calls).toEqual([
[environmentId, "profile-a"],
[secondEnvironmentId, "profile-a"],
]);
expect(clearCache.mock.calls).toEqual([
[environmentId, "profile-a"],
[secondEnvironmentId, "profile-a"],
]);
});
it("propagates cleanup failures", async () => {
const failure = new Error("clear failed");
await expect(
clearBrowserProfileData(
{
clearCookies: vi.fn().mockRejectedValue(failure),
clearCache: vi.fn().mockResolvedValue(undefined),
},
[environmentId],
"profile-a",
),
).rejects.toBe(failure);
});
it("does not report success without an environment or bridge", async () => {
const bridge = {
clearCookies: vi.fn().mockResolvedValue(undefined),
clearCache: vi.fn().mockResolvedValue(undefined),
};
await expect(clearBrowserProfileData(bridge, [], "profile-a")).rejects.toThrow();
await expect(clearBrowserProfileData(null, [environmentId], "profile-a")).rejects.toThrow();
expect(bridge.clearCookies).not.toHaveBeenCalled();
expect(bridge.clearCache).not.toHaveBeenCalled();
});
});
describe("browserProfileRemovalAvailable", () => {
it("requires a ready non-empty catalog and desktop bridge", () => {
expect(browserProfileRemovalAvailable(true, true, 1)).toBe(true);
expect(browserProfileRemovalAvailable(true, true, 0)).toBe(false);
expect(browserProfileRemovalAvailable(true, false, 1)).toBe(false);
expect(browserProfileRemovalAvailable(false, true, 1)).toBe(false);
});
});
// Mirrors `BrowserImportFailedError.message`, which IPC flattens to a string
// before the renderer sees it.
const failure = (reason: string) => ({
message: `Importing cookies from safari failed: ${reason}.`,
});
describe("importFailureReason", () => {
it("recovers the reason token from the flattened message", () => {
expect(importFailureReason(failure("needsFullDiskAccess"))).toBe("needsFullDiskAccess");
expect(importFailureReason(failure("browserRunning"))).toBe("browserRunning");
expect(importFailureReason(failure("readFailed"))).toBe("readFailed");
expect(importFailureReason(failure("keychainUnavailable"))).toBe("keychainUnavailable");
// A settings write that fails after the cookies landed is its own case,
// not a read failure over a database that was in fact read.
expect(importFailureReason(failure("profileNotSaved"))).toBe("profileNotSaved");
expect(importFailureReason(failure("profileLimitReached"))).toBe("profileLimitReached");
});
it("falls back to readFailed for anything it cannot classify", () => {
expect(importFailureReason(new Error("something else entirely"))).toBe("readFailed");
expect(importFailureReason(undefined)).toBe("readFailed");
});
});