import { describe, expect, it } from "@effect/vitest";import * as Effect from "effect/Effect"; import { CONNECTION_CATALOG_KEY, LEGACY_CONNECTIONS_KEY, makeCatalogStore, type SecureCatalogStorage,} from "./catalog-store"; function makeStorage(initial: Readonly<Record<string, string>>) { const values = new Map(Object.entries(initial)); const deleted: Array<string> = []; const storage: SecureCatalogStorage = { getItem: (key) => Effect.sync(() => values.get(key) ?? null), setItem: (key, value) => Effect.sync(() => { values.set(key, value); }), deleteItem: (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* makeCatalogStore(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* makeCatalogStore(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* makeCatalogStore(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); }), );});
import { describe, expect, it } from "@effect/vitest";
import * as Effect from "effect/Effect";
import {
CONNECTION_CATALOG_KEY,
LEGACY_CONNECTIONS_KEY,
makeCatalogStore,
type SecureCatalogStorage,
} from "./catalog-store";
function makeStorage(initial: Readonly<Record<string, string>>) {
const values = new Map(Object.entries(initial));
const deleted: Array<string> = [];
const storage: SecureCatalogStorage = {
getItem: (key) => Effect.sync(() => values.get(key) ?? null),
setItem: (key, value) =>
Effect.sync(() => {
values.set(key, value);
}),
deleteItem: (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* makeCatalogStore(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* makeCatalogStore(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* makeCatalogStore(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);
}),
);
});