97 lines · 3.2 KB · TypeScript
RawDownload
import { describe, expect, it } from "@effect/vitest";import * as Effect from "effect/Effect";import { vi } from "vite-plus/test"; vi.mock("react-native", () => ({  Platform: { OS: "ios" },})); vi.mock("expo-secure-store", () => ({  deleteItemAsync: vi.fn(),  getItemAsync: vi.fn(),  setItemAsync: vi.fn(),})); import { CONNECTION_CATALOG_KEY, LEGACY_CONNECTIONS_KEY, make } from "./catalog-store";import { MobileSecureStorage } from "../persistence/mobile-secure-storage"; function makeStorage(initial: Readonly<Record<string, string>>) {  const values = new Map(Object.entries(initial));  const deleted: Array<string> = [];  const storage = MobileSecureStorage.of({    getItem: (key) => Effect.sync(() => values.get(key) ?? null),    setItem: (key, value) =>      Effect.sync(() => {        values.set(key, value);      }),    removeItem: (key) =>      Effect.sync(() => {        deleted.push(key);        values.delete(key);      }),  });  return { deleted, storage, values };} describe("mobile connection catalog storage", () => {  it.effect("recovers from a corrupt current catalog", () =>    Effect.gen(function* () {      const memory = makeStorage({        [CONNECTION_CATALOG_KEY]: "{not-json",      });      const catalog = yield* make().pipe(        Effect.provideService(MobileSecureStorage, memory.storage),      );       expect((yield* catalog.read).targets).toEqual([]);      expect(memory.deleted).toEqual([CONNECTION_CATALOG_KEY]);    }),  );   it.effect("replaces and removes a corrupt legacy catalog", () =>    Effect.gen(function* () {      const memory = makeStorage({        [LEGACY_CONNECTIONS_KEY]: JSON.stringify({ connections: [{ invalid: true }] }),      });      const catalog = yield* make().pipe(        Effect.provideService(MobileSecureStorage, memory.storage),      );       expect((yield* catalog.read).targets).toEqual([]);      expect(memory.deleted).toEqual([LEGACY_CONNECTIONS_KEY]);      expect(memory.values.has(CONNECTION_CATALOG_KEY)).toBe(true);    }),  );   it.effect("falls back to valid legacy data when the current catalog is corrupt", () =>    Effect.gen(function* () {      const memory = makeStorage({        [CONNECTION_CATALOG_KEY]: "{not-json",        [LEGACY_CONNECTIONS_KEY]: JSON.stringify({          connections: [            {              environmentId: "legacy-environment",              environmentLabel: "Legacy",              pairingUrl: "https://legacy.example.test/pair",              displayUrl: "https://legacy.example.test",              httpBaseUrl: "https://legacy.example.test",              wsBaseUrl: "wss://legacy.example.test",              bearerToken: "legacy-token",              authenticationMethod: "bearer",            },          ],        }),      });      const catalog = yield* make().pipe(        Effect.provideService(MobileSecureStorage, memory.storage),      );       expect((yield* catalog.read).targets).toHaveLength(1);      expect(memory.deleted).toEqual([CONNECTION_CATALOG_KEY, LEGACY_CONNECTIONS_KEY]);       yield* catalog.update((document) => document);      expect(memory.values.has(CONNECTION_CATALOG_KEY)).toBe(true);      expect(memory.values.has(LEGACY_CONNECTIONS_KEY)).toBe(false);    }),  );});