test(FN-4748): complete Step 2 — reproduce tracking gaps with failing tests
Fusion-Task-Id: FN-4748 Fusion-Task-Lineage: b540f985-c20f-438e-8290-a07531c6612c
This commit is contained in:
committed by
gsxdsm
parent
51486b64a6
commit
d7b855c31d
@@ -0,0 +1,54 @@
|
|||||||
|
import { describe, expect, it, vi, type Mock } from "vitest";
|
||||||
|
import type { TaskStore } from "@fusion/core";
|
||||||
|
import { GitHubTrackingReconciler } from "../github-tracking-reconciler.js";
|
||||||
|
|
||||||
|
const { mockGetIssue, mockSetIssueState } = vi.hoisted(() => ({
|
||||||
|
mockGetIssue: vi.fn(),
|
||||||
|
mockSetIssueState: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const { mockResolveGithubTrackingAuth } = vi.hoisted(() => ({
|
||||||
|
mockResolveGithubTrackingAuth: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("../github.js", () => ({
|
||||||
|
GitHubClient: vi.fn().mockImplementation(() => ({
|
||||||
|
getIssue: (...args: unknown[]) => mockGetIssue(...args),
|
||||||
|
setIssueState: (...args: unknown[]) => mockSetIssueState(...args),
|
||||||
|
})),
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("../github-auth.js", () => ({
|
||||||
|
resolveGithubTrackingAuth: (...args: unknown[]) => mockResolveGithubTrackingAuth(...args),
|
||||||
|
}));
|
||||||
|
|
||||||
|
function createStore(tasks: Array<Record<string, unknown>>): TaskStore {
|
||||||
|
return {
|
||||||
|
listTasks: vi.fn().mockResolvedValue(tasks),
|
||||||
|
logEntry: vi.fn().mockResolvedValue(undefined),
|
||||||
|
getSettings: vi.fn().mockResolvedValue({ githubAuthMode: "token", githubAuthToken: "ghp_test" }),
|
||||||
|
getGlobalSettingsStore: vi.fn(() => ({ getSettings: vi.fn().mockResolvedValue({}) })),
|
||||||
|
} as unknown as TaskStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("GitHubTrackingReconciler", () => {
|
||||||
|
it("closes already-done tasks whose linked issue is still open", async () => {
|
||||||
|
mockResolveGithubTrackingAuth.mockReturnValue({ ok: true, auth: { mode: "token", token: "ghp_test" } });
|
||||||
|
mockGetIssue.mockResolvedValue({ state: "open" });
|
||||||
|
const store = createStore([
|
||||||
|
{
|
||||||
|
id: "FN-1",
|
||||||
|
status: "done",
|
||||||
|
githubTracking: {
|
||||||
|
enabled: true,
|
||||||
|
issue: { owner: "owner", repo: "repo", number: 42 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const reconciler = new GitHubTrackingReconciler();
|
||||||
|
await reconciler.reconcile(store);
|
||||||
|
|
||||||
|
expect(mockSetIssueState).toHaveBeenCalledWith("owner", "repo", 42, "closed", "completed");
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -255,6 +255,16 @@ describe("GitHubTrackingStateService", () => {
|
|||||||
expect(mockResolveGithubTrackingAuth).toHaveBeenCalledTimes(2);
|
expect(mockResolveGithubTrackingAuth).toHaveBeenCalledTimes(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("closes issue for late-registered project stores after service start", async () => {
|
||||||
|
const lateStore = new MockStore();
|
||||||
|
service.start();
|
||||||
|
|
||||||
|
lateStore.emit("task:moved", { task: createTask({ id: "FN-late" }), from: "todo", to: "done" });
|
||||||
|
await flushAsync();
|
||||||
|
|
||||||
|
expect(mockSetIssueState).toHaveBeenCalledWith("owner", "repo", 42, "closed", "completed");
|
||||||
|
});
|
||||||
|
|
||||||
it("emits close then reopen in order", async () => {
|
it("emits close then reopen in order", async () => {
|
||||||
service.start();
|
service.start();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user