128 lines · 4.4 KB · TypeScript
RawDownload
import { FileFinder } from "@ff-labs/fff-node";import { afterEach, expect, it } from "@effect/vitest";import * as Effect from "effect/Effect";import { vi } from "vite-plus/test"; import * as WorkspaceSearchIndex from "./WorkspaceSearchIndex.ts"; afterEach(() => {  vi.restoreAllMocks();}); it.effect("preserves unexpected FileFinder creation failures", () =>  Effect.gen(function* () {    const cause = new Error("native initialization failed");    vi.spyOn(FileFinder, "create").mockImplementationOnce(() => {      throw cause;    });     const error = yield* Effect.flip(      Effect.scoped(WorkspaceSearchIndex.make("/workspace/project")),    );     expect(error).toMatchObject({      _tag: "WorkspaceSearchIndexCreateFailed",      cwd: "/workspace/project",      reason: "FileFinder.create threw unexpectedly.",      cause,    });  }),); it.effect("keeps returned FileFinder creation diagnostics out of the cause chain", () =>  Effect.gen(function* () {    vi.spyOn(FileFinder, "create").mockReturnValueOnce({      ok: false,      error: "native index rejected the directory",    });     const error = yield* Effect.flip(      Effect.scoped(WorkspaceSearchIndex.make("/workspace/project")),    );     expect(error).toMatchObject({      _tag: "WorkspaceSearchIndexCreateFailed",      cwd: "/workspace/project",      reason: "native index rejected the directory",    });    expect(error.cause).toBeUndefined();  }),); it.effect("preserves search and refresh failures with operation context", () =>  Effect.scoped(    Effect.gen(function* () {      const searchCause = new Error("native search failed");      const refreshCause = new Error("native scan failed");      const finder = {        destroy: vi.fn(),        isScanning: vi.fn(() => false),        mixedSearch: vi.fn(() => {          throw searchCause;        }),        scanFiles: vi.fn(() => {          throw refreshCause;        }),      } as unknown as FileFinder;      vi.spyOn(FileFinder, "create").mockReturnValueOnce({ ok: true, value: finder });       const searchIndex = yield* WorkspaceSearchIndex.make("/workspace/project");      const query = "authorization: Bearer secret-token";      const searchError = yield* Effect.flip(searchIndex.search(query, 3));      const refreshError = yield* Effect.flip(searchIndex.refresh());       expect(searchError).toMatchObject({        _tag: "WorkspaceSearchIndexSearchFailed",        cwd: "/workspace/project",        queryLength: query.length,        pageSize: 4,        reason: "FileFinder.mixedSearch threw unexpectedly.",        cause: searchCause,      });      expect(searchError).not.toHaveProperty("query");      expect(searchError.message).not.toMatch(/Bearer|secret-token/);      expect(refreshError).toMatchObject({        _tag: "WorkspaceSearchIndexRefreshFailed",        cwd: "/workspace/project",        reason: "FileFinder.scanFiles threw unexpectedly.",        cause: refreshCause,      });    }),  ),); it.effect("keeps returned search diagnostics out of the cause chain", () =>  Effect.scoped(    Effect.gen(function* () {      const finder = {        destroy: vi.fn(),        isScanning: vi.fn(() => false),        mixedSearch: vi.fn(() => ({ ok: false, error: "native query rejected" })),        scanFiles: vi.fn(() => ({ ok: false, error: "native refresh rejected" })),      } as unknown as FileFinder;      vi.spyOn(FileFinder, "create").mockReturnValueOnce({ ok: true, value: finder });       const searchIndex = yield* WorkspaceSearchIndex.make("/workspace/project");      const query = "authorization: Bearer secret-token";      const searchError = yield* Effect.flip(searchIndex.search(query, 3));      const refreshError = yield* Effect.flip(searchIndex.refresh());       expect(searchError).toMatchObject({        _tag: "WorkspaceSearchIndexSearchFailed",        cwd: "/workspace/project",        queryLength: query.length,        pageSize: 4,        reason: "native query rejected",      });      expect(searchError).not.toHaveProperty("query");      expect(searchError.message).not.toMatch(/Bearer|secret-token/);      expect(searchError.cause).toBeUndefined();      expect(refreshError).toMatchObject({        _tag: "WorkspaceSearchIndexRefreshFailed",        cwd: "/workspace/project",        reason: "native refresh rejected",      });      expect(refreshError.cause).toBeUndefined();    }),  ),);