import { describe, expect, it, vi } from "vitest"; import { createStorageDurabilityAdapter } from "../../src/adapters/browser-file-storage/storage-manager-adapter.ts"; describe("storage manager adapter", () => { it("classifies rough origin pressure without treating it as a reservation", async () => { const adapter = createStorageDurabilityAdapter({ estimate: async () => ({ usage: 75, quota: 100 }), persisted: async () => false, persist: async () => false, }); expect(await adapter.inspect()).toEqual({ ok: true, value: { usageBytes: 75, quotaBytes: 100, persisted: false, pressure: "PRESSURE", }, }); }); it("snapshots pressure thresholds when the adapter is composed", async () => { const policy = { pressureRatio: 0.7, criticalRatio: 0.85, }; const adapter = createStorageDurabilityAdapter( { estimate: async () => ({ usage: 50, quota: 100 }), }, policy, ); policy.pressureRatio = 0.1; policy.criticalRatio = 0.2; await expect(adapter.inspect()).resolves.toMatchObject({ ok: true, value: { pressure: "NORMAL" }, }); }); it("captures StorageManager methods when the adapter is composed", async () => { const manager = { estimate: async () => ({ usage: 10, quota: 100 }), persisted: async () => false, }; const adapter = createStorageDurabilityAdapter(manager); manager.estimate = async () => ({ usage: 100, quota: 100 }); manager.persisted = async () => true; await expect(adapter.inspect()).resolves.toEqual({ ok: true, value: { usageBytes: 10, quotaBytes: 100, persisted: false, pressure: "NORMAL", }, }); }); it("settles an aborted inspection while native reads remain pending", async () => { const never = new Promise(() => undefined); const estimate = vi.fn(() => never); const persisted = vi.fn(() => never); const adapter = createStorageDurabilityAdapter({ estimate, persisted, }); const controller = new AbortController(); const inspection = adapter.inspect(controller.signal); controller.abort(); await expect(inspection).resolves.toMatchObject({ ok: false, error: { code: "ABORTED", operation: "STORAGE_ESTIMATE" }, }); expect(estimate).toHaveBeenCalledOnce(); expect(persisted).toHaveBeenCalledOnce(); }); it("consumes a late native rejection when abort wins during invocation", async () => { const controller = new AbortController(); let rejectEstimate: ((reason: unknown) => void) | undefined; const estimateResult = new Promise( (_resolve, reject) => { rejectEstimate = reject; }, ); const unhandled: unknown[] = []; const onUnhandled = (reason: unknown): void => { unhandled.push(reason); }; process.on("unhandledRejection", onUnhandled); try { const adapter = createStorageDurabilityAdapter({ estimate: () => { controller.abort(); return estimateResult; }, }); await expect(adapter.inspect(controller.signal)).resolves.toMatchObject({ ok: false, error: { code: "ABORTED", operation: "STORAGE_ESTIMATE" }, }); rejectEstimate?.(new Error("late estimate rejection")); await new Promise((resolve) => { setTimeout(resolve, 0); }); expect(unhandled).toEqual([]); } finally { process.off("unhandledRejection", onUnhandled); } }); it("requests persistence only through the explicit user-initiated port", async () => { const persist = vi.fn(async () => true); const adapter = createStorageDurabilityAdapter({ estimate: async () => ({}), persist, }, undefined, { isActive: true }); expect( await adapter.requestPersistence({ reason: "PROTECT_UNSYNCED_USER_DATA", userInitiated: true, }), ).toEqual({ ok: true, value: "GRANTED" }); expect(persist).toHaveBeenCalledOnce(); }); it("requires real transient user activation before invoking persist", async () => { const persist = vi.fn(async () => true); const adapter = createStorageDurabilityAdapter( { estimate: async () => ({}), persist }, undefined, { isActive: false }, ); await expect( adapter.requestPersistence({ reason: "PROTECT_UNSYNCED_USER_DATA", userInitiated: true, }), ).resolves.toMatchObject({ ok: false, error: { code: "PERMISSION_DENIED" }, }); expect(persist).not.toHaveBeenCalled(); }); it("reports irreversible persist truth when abort wins after invocation", async () => { const controller = new AbortController(); const adapter = createStorageDurabilityAdapter( { estimate: async () => ({}), persist: async () => { controller.abort(); return true; }, }, undefined, { isActive: true }, ); await expect( adapter.requestPersistence({ reason: "PROTECT_UNSYNCED_USER_DATA", userInitiated: true, signal: controller.signal, }), ).resolves.toEqual({ ok: true, value: "GRANTED" }); }); it("keeps unsupported persistence state distinct from false", async () => { const adapter = createStorageDurabilityAdapter({ estimate: async () => ({ usage: 1, quota: 10 }), }); await expect(adapter.inspect()).resolves.toMatchObject({ ok: true, value: { persisted: null }, }); }); it("returns unsupported rather than inventing durable memory storage", async () => { const adapter = createStorageDurabilityAdapter(undefined); expect(await adapter.inspect()).toMatchObject({ ok: false, error: { code: "UNSUPPORTED", recovery: "ONLINE_ONLY", }, }); }); });