test: stabilize dashboard PR repository fixtures (#1824)
## Summary
- Mocks `git remote get-url origin` for dashboard PR lifecycle tests via
`execFileSync`, matching the production repository resolver.
- Keeps the missing-repository error covered for cases where no project
remote is resolvable.
- Tightens dashboard PR lifecycle assertions so PR status checks use the
resolved owner/repo.
## Verification
- `corepack pnpm build` — pass
- `corepack pnpm --filter @runfusion/fusion exec vitest run
src/commands/__tests__/dashboard.test.ts --silent=passed-only
--reporter=dot --no-color` — pass, 86 tests
- `corepack pnpm --filter @runfusion/fusion exec vitest run
src/commands/__tests__/dashboard.test.ts -t
"processPullRequestMergeTask|PR-first auto-merge queue"
--silent=passed-only --reporter=dot --no-color` — pass, 7 tests
- Clean rebuilt stale bundled plugin dist, then `corepack pnpm --filter
@runfusion/fusion exec vitest run --changed
24d78816a0 --passWithNoTests
--silent=passed-only --reporter=dot --no-color` — pass, 75 files / 1186
tests
- `corepack pnpm check:changesets` — pass
- `corepack pnpm lint` — pass
- `corepack pnpm typecheck` — pass
No changeset: test-only fixture coverage; no package runtime behavior
changed.
## CI note
The current Gate failure is the pre-existing engine-core workflow
expectation drift fixed by PR #1822. Lint, Typecheck, Build, CodeRabbit,
and Greptile passed on this PR.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Tests**
* Expanded dashboard and pull request merge coverage to verify
repository detection and merge-status handling across merge lifecycle
paths.
* Added a failure-path assertion for when the app can’t determine the
current repository, ensuring the operation stops and surfaces the
expected error.
* Improved assertions for auto-merge and manual merge flows to confirm
the correct repository lookup occurs in each scenario.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Current Gate status
`Gate` is failing on current `origin/main` before these PR changes. I
reproduced the same engine-core failures directly on `origin/main`
(`task-pipeline-smoke.test.ts` and
`workflow-graph-executor-parity.test.ts`, caused by the new
`completion-summary` / `post-merge-verification` default workflow
nodes). The PR-local review feedback is addressed and focused validation
passes; the remaining Gate failure should be fixed in the upstream
workflow-test drift PR, not copied into this PR branch.
This commit is contained in:
@@ -261,6 +261,7 @@ vi.mock("@fusion/core", async (importOriginal) => {
|
||||
const {
|
||||
mockExec,
|
||||
mockExecSync,
|
||||
mockExecFileSync,
|
||||
mockFindPrForBranch,
|
||||
mockCreatePr,
|
||||
mockGetPrMergeStatus,
|
||||
@@ -282,6 +283,16 @@ const {
|
||||
};
|
||||
}),
|
||||
mockExecSync: vi.fn(() => ""),
|
||||
mockExecFileSync: vi.fn((file: string, args: readonly string[] = [], options?: { cwd?: string }) => {
|
||||
if (file === "git" && args.join(" ") === "remote get-url origin") {
|
||||
const effectiveCwd = options?.cwd ?? process.cwd();
|
||||
if (effectiveCwd !== "/repo" && effectiveCwd !== process.cwd()) {
|
||||
throw new Error(`unexpected repository cwd: ${options?.cwd ?? "<unset>"}`);
|
||||
}
|
||||
return "https://github.com/owner/repo.git\n";
|
||||
}
|
||||
return "";
|
||||
}),
|
||||
mockFindPrForBranch: vi.fn(),
|
||||
mockCreatePr: vi.fn(),
|
||||
mockGetPrMergeStatus: vi.fn(),
|
||||
@@ -307,6 +318,7 @@ vi.mock("node:child_process", async (importOriginal) => {
|
||||
exec: mockExec,
|
||||
execSync: mockExecSync,
|
||||
execFile: mockExecFile,
|
||||
execFileSync: mockExecFileSync,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -861,6 +873,18 @@ function resetGitHubMocks() {
|
||||
mockCreatePr.mockReset();
|
||||
mockGetPrMergeStatus.mockReset();
|
||||
mockMergePr.mockReset();
|
||||
mockExecFileSync.mockReset();
|
||||
|
||||
mockExecFileSync.mockImplementation((file: string, args: readonly string[] = [], options?: { cwd?: string }) => {
|
||||
if (file === "git" && args.join(" ") === "remote get-url origin") {
|
||||
const effectiveCwd = options?.cwd ?? process.cwd();
|
||||
if (effectiveCwd !== "/repo" && effectiveCwd !== process.cwd()) {
|
||||
throw new Error(`unexpected repository cwd: ${options?.cwd ?? "<unset>"}`);
|
||||
}
|
||||
return "https://github.com/owner/repo.git\n";
|
||||
}
|
||||
return "";
|
||||
});
|
||||
|
||||
mockFindPrForBranch.mockResolvedValue(null);
|
||||
mockCreatePr.mockResolvedValue({
|
||||
@@ -1006,6 +1030,36 @@ describe("processPullRequestMergeTask", () => {
|
||||
expect.objectContaining({ number: 42, status: "open" }),
|
||||
);
|
||||
expect(store.updateTask).toHaveBeenCalledWith("FN-093", { status: "awaiting-pr-checks" });
|
||||
expect(mockExecFileSync).toHaveBeenCalledWith(
|
||||
"git",
|
||||
["remote", "get-url", "origin"],
|
||||
expect.objectContaining({ cwd: "/repo" }),
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps the production missing-repository error when no project remote is resolvable", async () => {
|
||||
mockExecFileSync.mockImplementationOnce(() => {
|
||||
throw new Error("not a git repository");
|
||||
});
|
||||
const store = makeMockStore();
|
||||
store.getTask.mockResolvedValue({
|
||||
id: "FN-093",
|
||||
title: "Task",
|
||||
description: "Description",
|
||||
column: "in-review",
|
||||
paused: false,
|
||||
log: [],
|
||||
});
|
||||
|
||||
await expect(processPullRequestMergeTask(store as any, "/repo", "FN-093", {
|
||||
findPrForBranch: mockFindPrForBranch,
|
||||
createPr: mockCreatePr,
|
||||
getPrMergeStatus: mockGetPrMergeStatus,
|
||||
mergePr: mockMergePr,
|
||||
} as any, () => undefined)).rejects.toThrow("processPullRequestMergeTask: could not determine repository");
|
||||
|
||||
expect(mockCreatePr).not.toHaveBeenCalled();
|
||||
expect(mockGetPrMergeStatus).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("links an existing PR instead of creating a duplicate", async () => {
|
||||
@@ -1050,6 +1104,7 @@ describe("processPullRequestMergeTask", () => {
|
||||
} as any, mockGetTaskMergeBlocker);
|
||||
|
||||
expect(mockCreatePr).not.toHaveBeenCalled();
|
||||
expect(mockGetPrMergeStatus).toHaveBeenCalledWith("owner", "repo", 7);
|
||||
expect(store.logEntry).toHaveBeenCalledWith(
|
||||
"FN-093",
|
||||
"Linked existing PR",
|
||||
@@ -1114,6 +1169,7 @@ describe("processPullRequestMergeTask", () => {
|
||||
} as any, mockGetTaskMergeBlocker);
|
||||
|
||||
expect(result).toBe("merged");
|
||||
expect(mockGetPrMergeStatus).toHaveBeenCalledWith("owner", "repo", 42);
|
||||
expect(mockMergePr).toHaveBeenCalledWith({ number: 42, method: "squash" });
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-093", "done");
|
||||
// Check that exec was called with the expected commands (options object and callback may follow)
|
||||
@@ -1177,6 +1233,7 @@ describe("processPullRequestMergeTask", () => {
|
||||
} as any, mockGetTaskMergeBlocker);
|
||||
|
||||
expect(result).toBe("waiting");
|
||||
expect(mockGetPrMergeStatus).toHaveBeenCalledWith("owner", "repo", 42);
|
||||
expect(mockMergePr).not.toHaveBeenCalled();
|
||||
expect(store.moveTask).not.toHaveBeenCalled();
|
||||
expect(store.updateTask).toHaveBeenCalledWith("FN-093", { status: "awaiting-pr-checks" });
|
||||
@@ -1234,6 +1291,11 @@ describe("runDashboard — PR-first auto-merge queue", () => {
|
||||
head: "fusion/fn-093",
|
||||
base: "main",
|
||||
});
|
||||
expect(mockExecFileSync).toHaveBeenCalledWith(
|
||||
"git",
|
||||
["remote", "get-url", "origin"],
|
||||
expect.objectContaining({ cwd: process.cwd() }),
|
||||
);
|
||||
expect(aiMergeTask).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -1263,6 +1325,11 @@ describe("runDashboard — PR-first auto-merge queue", () => {
|
||||
head: "fusion/fn-093",
|
||||
base: "main",
|
||||
});
|
||||
expect(mockExecFileSync).toHaveBeenCalledWith(
|
||||
"git",
|
||||
["remote", "get-url", "origin"],
|
||||
expect.objectContaining({ cwd: process.cwd() }),
|
||||
);
|
||||
expect(aiMergeTask).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user