From 214172e2b6f184e25da442e7938a6a99a94e0d80 Mon Sep 17 00:00:00 2001 From: "Fusion (runfusion.ai)" Date: Sat, 16 May 2026 07:32:48 -0700 Subject: [PATCH] test(FN-4725): add stale-reference github tracking regressions Fusion-Task-Id: FN-4725 Fusion-Task-Lineage: 91058db5-9a5b-4506-89f4-8abf89b28862 --- .../__tests__/github-tracking-hook.test.ts | 31 +++++++++++++++++++ .../src/__tests__/github-tracking.test.ts | 22 +++++++++++++ 2 files changed, 53 insertions(+) diff --git a/packages/dashboard/src/__tests__/github-tracking-hook.test.ts b/packages/dashboard/src/__tests__/github-tracking-hook.test.ts index 7fb97c6af..7f0283439 100644 --- a/packages/dashboard/src/__tests__/github-tracking-hook.test.ts +++ b/packages/dashboard/src/__tests__/github-tracking-hook.test.ts @@ -21,6 +21,7 @@ vi.mock("../github-auth.js", () => ({ })); import { registerGithubTrackingHook } from "../github-tracking-hook.js"; +import { maybeCreateTrackingIssue } from "../github-tracking.js"; function makeTmpDir(): string { return mkdtempSync(join(tmpdir(), "kb-dashboard-github-tracking-hook-test-")); @@ -128,4 +129,34 @@ describe("registerGithubTrackingHook", () => { expect(task.id).toMatch(/^FN-/); expect(mockCreateIssue).toHaveBeenCalledTimes(1); }); + + it("creates one issue total across hook execution and follow-up stale reference call", async () => { + registerGithubTrackingHook(); + + await store.updateSettings({ + githubTrackingDefaultRepo: "o/r", + githubAuthMode: "token", + githubAuthToken: "tok", + }); + + const createdTask = await store.createTask({ + description: "stale follow up", + title: "Stale follow up", + githubTracking: { enabled: true }, + }); + + const staleTaskRef = { ...createdTask, githubTracking: { enabled: true } }; + const projectSettings = await store.getSettings(); + + const result = await maybeCreateTrackingIssue(staleTaskRef, { + taskStore: store, + projectSettings, + globalSettings: {}, + rootDir, + logger: { warn: vi.fn(), info: vi.fn() }, + }); + + expect(result).toEqual({ created: false, reason: "issue_already_linked" }); + expect(mockCreateIssue).toHaveBeenCalledTimes(1); + }); }); diff --git a/packages/dashboard/src/__tests__/github-tracking.test.ts b/packages/dashboard/src/__tests__/github-tracking.test.ts index e3b7e4b6e..78bbbaf48 100644 --- a/packages/dashboard/src/__tests__/github-tracking.test.ts +++ b/packages/dashboard/src/__tests__/github-tracking.test.ts @@ -186,6 +186,28 @@ describe("maybeCreateTrackingIssue", () => { expect(createIssueMock).not.toHaveBeenCalled(); }); + it("returns issue_already_linked when store refresh shows a linked issue on a stale task reference", async () => { + const staleTask = buildTask({ githubTracking: { enabled: true } }); + const getTask = vi.fn().mockResolvedValue(buildTask({ + id: staleTask.id, + githubTracking: { + enabled: true, + issue: { owner: "task", repo: "repo", number: 101, url: "https://github.com/task/repo/issues/101" }, + }, + })); + + const result = await maybeCreateTrackingIssue(staleTask, { + taskStore: { getTask } as any, + projectSettings: { githubTrackingDefaultRepo: "task/repo", githubAuthMode: "token", githubAuthToken: "tok" } as any, + globalSettings: {}, + rootDir, + }); + + expect(result).toEqual({ created: false, reason: "issue_already_linked" }); + expect(getTask).toHaveBeenCalledWith(staleTask.id); + expect(createIssueMock).not.toHaveBeenCalled(); + }); + it("returns no_repo_configured and records activity", async () => { const recordActivity = vi.fn(); const result = await maybeCreateTrackingIssue(buildTask({ githubTracking: { enabled: true } }), {