authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-10-05 21:42:09-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-10-05 21:42:09-07:00
logefeeb7737bed89bbfc6dc81662058f8ce7fba2ea
tree5a2ad66283b0f661de4f05b4d1ba65730c7e9239
parentc299308a832db382fce61233bd10a4bd13bbc60c
signature Signed by PGP key B5690EEEBB952194

refactor(web): import connection storage as a namespace in its test (#16315)

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

1 files changed, 18 insertions(+), 21 deletions(-)

apps/web/src/connection/storage.test.ts+18-21
...@@ -12,12 +12,7 @@ import * as Schema from "effect/Schema";...@@ -12,12 +12,7 @@ import * as Schema from "effect/Schema";
12import * as Stream from "effect/Stream";12import * as Stream from "effect/Stream";
13import { afterEach, vi } from "vite-plus/test";13import { afterEach, vi } from "vite-plus/test";
1414
15import {15import * as ConnectionStorage from "./storage";
16 makeBrowserGitHubRoutingPermissions,
17 makeCatalogBackend,
18 makeCatalogStore,
19 layer as connectionStorageLayer,
20} from "./storage";
2116
22const emptyCatalog = {17const emptyCatalog = {
23 schemaVersion: 1,18 schemaVersion: 1,
...@@ -35,12 +30,12 @@ afterEach(() => {...@@ -35,12 +30,12 @@ afterEach(() => {
35 vi.restoreAllMocks();30 vi.restoreAllMocks();
36});31});
3732
38describe("makeCatalogStore", () => {33describe("ConnectionStorage.makeCatalogStore", () => {
39 it.effect("quarantines malformed catalogs and starts from an empty document", () =>34 it.effect("quarantines malformed catalogs and starts from an empty document", () =>
40 Effect.gen(function* () {35 Effect.gen(function* () {
41 const writes: string[] = [];36 const writes: string[] = [];
42 const quarantined: string[] = [];37 const quarantined: string[] = [];
43 const store = yield* makeCatalogStore({38 const store = yield* ConnectionStorage.makeCatalogStore({
44 read: Effect.succeed("{not-json"),39 read: Effect.succeed("{not-json"),
45 write: (raw) => Effect.sync(() => writes.push(raw)),40 write: (raw) => Effect.sync(() => writes.push(raw)),
46 quarantine: (raw) => Effect.sync(() => quarantined.push(raw)),41 quarantine: (raw) => Effect.sync(() => quarantined.push(raw)),
...@@ -59,7 +54,7 @@ describe("makeCatalogStore", () => {...@@ -59,7 +54,7 @@ describe("makeCatalogStore", () => {
59 reason: "remote-unavailable",54 reason: "remote-unavailable",
60 detail: "permission denied",55 detail: "permission denied",
61 });56 });
62 const store = yield* makeCatalogStore({57 const store = yield* ConnectionStorage.makeCatalogStore({
63 read: Effect.fail(failure),58 read: Effect.fail(failure),
64 write: () => Effect.void,59 write: () => Effect.void,
65 });60 });
...@@ -74,7 +69,7 @@ const fixedHandle = (database: IDBDatabase) => ({...@@ -74,7 +69,7 @@ const fixedHandle = (database: IDBDatabase) => ({
74 invalidate: () => Effect.void,69 invalidate: () => Effect.void,
75});70});
7671
77describe("makeCatalogBackend", () => {72describe("ConnectionStorage.makeCatalogBackend", () => {
78 it.effect("reports a closed IndexedDB connection as a typed read and write failure", () =>73 it.effect("reports a closed IndexedDB connection as a typed read and write failure", () =>
79 Effect.gen(function* () {74 Effect.gen(function* () {
80 vi.stubGlobal("window", {});75 vi.stubGlobal("window", {});
...@@ -83,7 +78,7 @@ describe("makeCatalogBackend", () => {...@@ -83,7 +78,7 @@ describe("makeCatalogBackend", () => {
83 throw new DOMException("The database connection is closing.", "InvalidStateError");78 throw new DOMException("The database connection is closing.", "InvalidStateError");
84 },79 },
85 } as unknown as IDBDatabase;80 } as unknown as IDBDatabase;
86 const backend = makeCatalogBackend(fixedHandle(database));81 const backend = ConnectionStorage.makeCatalogBackend(fixedHandle(database));
8782
88 const readError = yield* Effect.flip(backend.read);83 const readError = yield* Effect.flip(backend.read);
89 const writeError = yield* Effect.flip(backend.write("{}"));84 const writeError = yield* Effect.flip(backend.write("{}"));
...@@ -103,7 +98,7 @@ describe("makeCatalogBackend", () => {...@@ -103,7 +98,7 @@ describe("makeCatalogBackend", () => {
103 setConnectionCatalog,98 setConnectionCatalog,
104 },99 },
105 });100 });
106 const backend = makeCatalogBackend(fixedHandle({} as IDBDatabase));101 const backend = ConnectionStorage.makeCatalogBackend(fixedHandle({} as IDBDatabase));
107102
108 const error = yield* backend.write("{}").pipe(Effect.flip);103 const error = yield* backend.write("{}").pipe(Effect.flip);
109104
...@@ -128,7 +123,7 @@ describe("makeCatalogBackend", () => {...@@ -128,7 +123,7 @@ describe("makeCatalogBackend", () => {
128 },123 },
129 }),124 }),
130 });125 });
131 const backend = makeCatalogBackend(126 const backend = ConnectionStorage.makeCatalogBackend(
132 fixedHandle({ transaction: () => transaction } as unknown as IDBDatabase),127 fixedHandle({ transaction: () => transaction } as unknown as IDBDatabase),
133 );128 );
134129
...@@ -176,7 +171,7 @@ describe("environment cache removal", () => {...@@ -176,7 +171,7 @@ describe("environment cache removal", () => {
176 ),171 ),
177 yield* Effect.flip(cache.clearVcsRefs(EnvironmentId.make("env"))),172 yield* Effect.flip(cache.clearVcsRefs(EnvironmentId.make("env"))),
178 ] as const;173 ] as const;
179 }).pipe(Effect.provide(connectionStorageLayer));174 }).pipe(Effect.provide(ConnectionStorage.layer));
180175
181 expect(threadError.message).toContain("Commit aborted");176 expect(threadError.message).toContain("Commit aborted");
182 expect(refsError.message).toContain("Commit aborted");177 expect(refsError.message).toContain("Commit aborted");
...@@ -201,7 +196,7 @@ describe("IndexedDB connection recovery", () => {...@@ -201,7 +196,7 @@ describe("IndexedDB connection recovery", () => {
201 cache.loadThread(EnvironmentId.make("env"), ThreadId.make("thread")),196 cache.loadThread(EnvironmentId.make("env"), ThreadId.make("thread")),
202 );197 );
203 expect(error.message).toContain("Storage is unavailable");198 expect(error.message).toContain("Storage is unavailable");
204 }).pipe(Effect.provide(connectionStorageLayer));199 }).pipe(Effect.provide(ConnectionStorage.layer));
205200
206 expect(open).toHaveBeenCalledOnce();201 expect(open).toHaveBeenCalledOnce();
207 }),202 }),
...@@ -254,7 +249,7 @@ describe("IndexedDB connection recovery", () => {...@@ -254,7 +249,7 @@ describe("IndexedDB connection recovery", () => {
254 );249 );
255 expect(recovered.every(Option.isNone)).toBe(true);250 expect(recovered.every(Option.isNone)).toBe(true);
256 expect(open).toHaveBeenCalledTimes(2);251 expect(open).toHaveBeenCalledTimes(2);
257 }).pipe(Effect.provide(connectionStorageLayer));252 }).pipe(Effect.provide(ConnectionStorage.layer));
258253
259 expect(first.close).not.toHaveBeenCalled();254 expect(first.close).not.toHaveBeenCalled();
260 expect(second.close).toHaveBeenCalledOnce();255 expect(second.close).toHaveBeenCalledOnce();
...@@ -302,7 +297,7 @@ describe("IndexedDB connection closed without a close event", () => {...@@ -302,7 +297,7 @@ describe("IndexedDB connection closed without a close event", () => {
302 const loaded = yield* cache.loadThread(EnvironmentId.make("env"), ThreadId.make("thread"));297 const loaded = yield* cache.loadThread(EnvironmentId.make("env"), ThreadId.make("thread"));
303 expect(Option.isNone(loaded)).toBe(true);298 expect(Option.isNone(loaded)).toBe(true);
304 expect(open).toHaveBeenCalledTimes(2);299 expect(open).toHaveBeenCalledTimes(2);
305 }).pipe(Effect.provide(connectionStorageLayer));300 }).pipe(Effect.provide(ConnectionStorage.layer));
306 }),301 }),
307 );302 );
308});303});
...@@ -329,8 +324,8 @@ describe("browser GitHub routing permissions", () => {...@@ -329,8 +324,8 @@ describe("browser GitHub routing permissions", () => {
329 };324 };
330 const firstBrowser = Object.assign(new EventTarget(), { localStorage });325 const firstBrowser = Object.assign(new EventTarget(), { localStorage });
331 const secondBrowser = Object.assign(new EventTarget(), { localStorage });326 const secondBrowser = Object.assign(new EventTarget(), { localStorage });
332 const first = makeBrowserGitHubRoutingPermissions(firstBrowser);327 const first = ConnectionStorage.makeBrowserGitHubRoutingPermissions(firstBrowser);
333 const second = makeBrowserGitHubRoutingPermissions(secondBrowser);328 const second = ConnectionStorage.makeBrowserGitHubRoutingPermissions(secondBrowser);
334 const entry = {329 const entry = {
335 target: new PrimaryConnectionTarget({330 target: new PrimaryConnectionTarget({
336 environmentId: EnvironmentId.make("first"),331 environmentId: EnvironmentId.make("first"),
...@@ -352,7 +347,7 @@ describe("browser GitHub routing permissions", () => {...@@ -352,7 +347,7 @@ describe("browser GitHub routing permissions", () => {
352 yield* first.set(entry, "read-write");347 yield* first.set(entry, "read-write");
353 expect(yield* second.get(entry)).toBe("read-write");348 expect(yield* second.get(entry)).toBe("read-write");
354 const oldPermissions = Option.getOrThrow(yield* Stream.runHead(first.changes));349 const oldPermissions = Option.getOrThrow(yield* Stream.runHead(first.changes));
355 const staleCatalog = yield* makeCatalogStore({350 const staleCatalog = yield* ConnectionStorage.makeCatalogStore({
356 read: Effect.succeed(351 read: Effect.succeed(
357 encodeCatalog({ ...emptyCatalog, githubRoutingPermissions: oldPermissions }),352 encodeCatalog({ ...emptyCatalog, githubRoutingPermissions: oldPermissions }),
358 ),353 ),
...@@ -377,7 +372,9 @@ describe("browser GitHub routing permissions", () => {...@@ -377,7 +372,9 @@ describe("browser GitHub routing permissions", () => {
377 yield* staleCatalog.update((document) => ({ ...document, accountId: "updated" }));372 yield* staleCatalog.update((document) => ({ ...document, accountId: "updated" }));
378 expect(yield* second.get(entry)).toBe("off");373 expect(yield* second.get(entry)).toBe("off");
379 expect(yield* first.get(other)).toBe("read");374 expect(yield* first.get(other)).toBe("read");
380 expect(yield* makeBrowserGitHubRoutingPermissions(firstBrowser).get(entry)).toBe("off");375 expect(
376 yield* ConnectionStorage.makeBrowserGitHubRoutingPermissions(firstBrowser).get(entry),
377 ).toBe("off");
381378
382 yield* first.set(entry, "read-write");379 yield* first.set(entry, "read-write");
383 yield* second.forget(entry.target.environmentId);380 yield* second.forget(entry.target.environmentId);