import type { FileDiffMetadata } from "@pierre/diffs"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { getPatchStream, startPatchStream } from "$lib/api/patchStream"; const streamPatchInWorker = vi.hoisted(() => vi.fn()); vi.mock("$lib/components/repo/diffRpc", () => ({ streamPatchInWorker })); const file = (name: string, prevName?: string) => ({ name, prevName, hunks: [] }) as unknown as FileDiffMetadata; describe("startPatchStream", () => { beforeEach(() => { streamPatchInWorker.mockReset(); }); it("indexes every landed file by its name and by the name it had before", async () => { streamPatchInWorker.mockImplementation( async (_url: string, land: (files: FileDiffMetadata[]) => void) => { land([file("src/new.ts", "src/old.ts")]); } ); const stream = startPatchStream("/patch"); await expect(stream.done).resolves.toBe(true); expect(stream.byName.get("src/new.ts")).toBe(stream.byName.get("src/old.ts")); }); it("reports a failed patch instead of throwing at whoever waits for it", async () => { streamPatchInWorker.mockRejectedValue(new Error("mirror is down")); await expect(startPatchStream("/patch").done).resolves.toBe(false); }); it("drops batches that land after the reader walked away", async () => { let land: (files: FileDiffMetadata[]) => void = () => undefined; streamPatchInWorker.mockImplementation( (_url: string, listener: (files: FileDiffMetadata[]) => void) => { land = listener; return new Promise(() => undefined); } ); const stream = startPatchStream("/patch"); const seen: FileDiffMetadata[][] = []; stream.subscribe((files) => seen.push(files)); stream.stop(); land([file("src/late.ts")]); expect(seen).toEqual([]); expect(stream.byName.size).toBe(0); }); }); describe("getPatchStream", () => { beforeEach(() => { streamPatchInWorker.mockReset(); streamPatchInWorker.mockImplementation(() => new Promise(() => undefined)); }); it("shares one download between every caller asking for the same patch", () => { expect(getPatchStream("/shared")).toBe(getPatchStream("/shared")); }); it("keeps the last couple of patches and stops the ones before them", () => { const first = getPatchStream("/first"); const stopped = vi.spyOn(first, "stop"); getPatchStream("/second"); getPatchStream("/third"); expect(stopped).toHaveBeenCalled(); expect(getPatchStream("/first")).not.toBe(first); }); });