From c8bd4717c9709255445af98ef503dc28982b4c65 Mon Sep 17 00:00:00 2001 From: "paseo-bot[bot]" <266920839+paseo-bot[bot]@users.noreply.github.com> Date: Fri, 6 Nov 2026 12:25:42 +0000 Subject: [PATCH] test(server): wait for Git ref observation before injecting events (#8924) Zero in-flight fetches also describes observation that has not started. Wait for the first fetch to start and settle, and exercise delayed watcher setup so missing callbacks cannot silently skip the test events. Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com> --- .../workspace-git-service.observation.test.ts | 124 ++++++++++-------- 1 file changed, 69 insertions(+), 55 deletions(-) diff --git a/packages/server/src/server/workspace-git-service.observation.test.ts b/packages/server/src/server/workspace-git-service.observation.test.ts index 04604cd1b5..86a49b55ac 100644 --- a/packages/server/src/server/workspace-git-service.observation.test.ts +++ b/packages/server/src/server/workspace-git-service.observation.test.ts @@ -811,64 +811,78 @@ describe("WorkspaceGitService checkout observation", () => { service.dispose(); }); - test("known packed remote refs materialize narrowly while namespace directories are ignored", async () => { - const watcher = createWatcherHarness(); - const getCheckoutSnapshotFacts = vi.fn(async (cwd: string) => ({ - ...createCheckoutFacts(cwd), - currentBranch: "feature", - remoteUrl: REMOTE_URL, - resolvedBaseRef: "main", - comparisonBaseRef: "origin/main", - })); - const getCheckoutRefDerivedState = vi.fn(async (_cwd, facts, current) => ({ - ...current, - upstreamStatus: facts.upstreamStatus, - })); - const service = createService(watcher, { - getCheckoutSnapshotFacts, - getCheckoutRefDerivedState, - hasOriginRemote: vi.fn(async () => true), - runGitFetch: vi.fn(async (_cwd, observer) => { - observer.onRefSnapshot("before"); - observer.onRefSnapshot("after"); - return { - changes: [], - nonRemoteRefsChanged: false, - remoteRefs: new Set(["origin/main", "origin/load/00001"]), - error: null, - }; - }), - }); - const subscription = service.registerWorkspace({ cwd: REPO_CWD }, vi.fn()); - await vi.waitFor(() => { - expect(service.getMetrics().fetchInFlightCount).toBe(0); + test.each([0, 100])( + "known packed remote refs materialize narrowly while namespace directories are ignored (watch setup delay %i ms)", + async (setupDelayMs) => { + const watcher = createWatcherHarness(); + let fetchStarted = false; + const getCheckoutSnapshotFacts = vi.fn(async (cwd: string) => ({ + ...createCheckoutFacts(cwd), + currentBranch: "feature", + remoteUrl: REMOTE_URL, + resolvedBaseRef: "main", + comparisonBaseRef: "origin/main", + })); + const getCheckoutRefDerivedState = vi.fn(async (_cwd, facts, current) => ({ + ...current, + upstreamStatus: facts.upstreamStatus, + })); + const service = createService(watcher, { + subscribe: async (...args: Parameters) => { + if (args[0] === GIT_DIR && setupDelayMs > 0) { + await new Promise((resolve) => setTimeout(resolve, setupDelayMs)); + } + return watcher.subscribe(...args); + }, + getCheckoutSnapshotFacts, + getCheckoutRefDerivedState, + hasOriginRemote: vi.fn(async () => true), + runGitFetch: vi.fn(async (_cwd, observer) => { + fetchStarted = true; + observer.onRefSnapshot("before"); + observer.onRefSnapshot("after"); + return { + changes: [], + nonRemoteRefsChanged: false, + remoteRefs: new Set(["origin/main", "origin/load/00001"]), + error: null, + }; + }), + }); + const subscription = service.registerWorkspace({ cwd: REPO_CWD }, vi.fn()); + await vi.waitFor(() => { + // An idle fetch count also holds before observation setup starts. + expect(fetchStarted).toBe(true); + expect(service.getMetrics().fetchInFlightCount).toBe(0); + expect(getCheckoutSnapshotFacts).toHaveBeenCalledTimes(1); + }); + + const repoWatcher = watcher.records.find((record) => record.directory === GIT_DIR)!; + expect(repoWatcher).toBeDefined(); + repoWatcher.callback(null, [ + { path: path.join(GIT_DIR, "refs", "remotes", "origin", "load"), type: "create" }, + { + path: path.join(GIT_DIR, "refs", "remotes", "origin", "load", "00001"), + type: "create", + }, + ]); + await vi.advanceTimersByTimeAsync(1_000); expect(getCheckoutSnapshotFacts).toHaveBeenCalledTimes(1); - }); + expect(getCheckoutRefDerivedState).not.toHaveBeenCalled(); - const repoWatcher = watcher.records.find((record) => record.directory === GIT_DIR); - repoWatcher?.callback(null, [ - { path: path.join(GIT_DIR, "refs", "remotes", "origin", "load"), type: "create" }, - { - path: path.join(GIT_DIR, "refs", "remotes", "origin", "load", "00001"), - type: "create", - }, - ]); - await vi.advanceTimersByTimeAsync(1_000); - expect(getCheckoutSnapshotFacts).toHaveBeenCalledTimes(1); - expect(getCheckoutRefDerivedState).not.toHaveBeenCalled(); + repoWatcher.callback(null, [ + { path: path.join(GIT_DIR, "refs", "remotes", "origin", "main"), type: "create" }, + ]); + await vi.advanceTimersByTimeAsync(1_000); + await vi.waitFor(() => { + expect(getCheckoutRefDerivedState).toHaveBeenCalledTimes(1); + }); + expect(getCheckoutSnapshotFacts).toHaveBeenCalledTimes(1); - repoWatcher?.callback(null, [ - { path: path.join(GIT_DIR, "refs", "remotes", "origin", "main"), type: "create" }, - ]); - await vi.advanceTimersByTimeAsync(1_000); - await vi.waitFor(() => { - expect(getCheckoutRefDerivedState).toHaveBeenCalledTimes(1); - }); - expect(getCheckoutSnapshotFacts).toHaveBeenCalledTimes(1); - - subscription.unsubscribe(); - service.dispose(); - }); + subscription.unsubscribe(); + await service.dispose(); + }, + ); test("a second remote-ref move during a narrow refresh queues a final calculation", async () => { const watcher = createWatcherHarness();