FN-5640: refresh PR status from Check PR Status footer action
Fusion-Task-Id: FN-5640 Fusion-Task-Lineage: 80074933-2486-4aa6-b23d-1d0e049808cb
This commit is contained in:
@@ -19,7 +19,7 @@ import {
|
||||
resolveTaskPlanningModel,
|
||||
resolveTaskValidatorModel,
|
||||
} from "@fusion/core";
|
||||
import { uploadAttachment, deleteAttachment, updateTask, pauseTask, unpauseTask, fetchTaskDetail, fetchSettings, fetchGlobalSettings, requestSpecRevision, rebuildTaskSpec, approvePlan, rejectPlan, refineTask, fetchWorkflowResults, assignTask, fetchAgents, fetchAgent, recoverBranchBinding } from "../api";
|
||||
import { uploadAttachment, deleteAttachment, updateTask, pauseTask, unpauseTask, fetchTaskDetail, fetchSettings, fetchGlobalSettings, requestSpecRevision, rebuildTaskSpec, approvePlan, rejectPlan, refineTask, fetchWorkflowResults, assignTask, fetchAgents, fetchAgent, recoverBranchBinding, refreshPrStatus } from "../api";
|
||||
import type { RecoverBranchBindingOutcome } from "../api";
|
||||
import type { ToastType } from "../hooks/useToast";
|
||||
import { useAgentLogs } from "../hooks/useAgentLogs";
|
||||
@@ -649,6 +649,7 @@ export function TaskDetailContent({
|
||||
const [githubRepoOverrideError, setGithubRepoOverrideError] = useState<string | null>(null);
|
||||
const [isSavingGithubTracking, setIsSavingGithubTracking] = useState(false);
|
||||
const [isRecoveringBranchBinding, setIsRecoveringBranchBinding] = useState(false);
|
||||
const [isCheckingPrStatus, setIsCheckingPrStatus] = useState(false);
|
||||
const [recoverBranchBindingOutcome, setRecoverBranchBindingOutcome] = useState<RecoverBranchBindingOutcome | null>(null);
|
||||
const moveMenuRef = useRef<HTMLDivElement>(null);
|
||||
const activityListRef = useRef<HTMLDivElement>(null);
|
||||
@@ -1798,6 +1799,25 @@ export function TaskDetailContent({
|
||||
void handleMerge();
|
||||
}, [closeMenus, handleMerge]);
|
||||
|
||||
const handleCheckPrStatus = useCallback(async () => {
|
||||
if (isCheckingPrStatus) return;
|
||||
closeMenus();
|
||||
setIsCheckingPrStatus(true);
|
||||
try {
|
||||
const result = await refreshPrStatus(task.id, projectId);
|
||||
addToast("PR status refreshed", "success");
|
||||
onTaskUpdated?.({
|
||||
...task,
|
||||
prInfo: result.prInfo,
|
||||
prInfos: result.all?.map((entry) => entry.prInfo) ?? task.prInfos,
|
||||
});
|
||||
} catch (err) {
|
||||
addToast(getErrorMessage(err), "error");
|
||||
} finally {
|
||||
setIsCheckingPrStatus(false);
|
||||
}
|
||||
}, [addToast, closeMenus, isCheckingPrStatus, onTaskUpdated, projectId, task]);
|
||||
|
||||
const handleCloseRefineModal = useCallback(() => {
|
||||
setShowRefineModal(false);
|
||||
setRefineFeedback("");
|
||||
@@ -3826,7 +3846,11 @@ export function TaskDetailContent({
|
||||
{prAutomationLabel}
|
||||
</button>
|
||||
) : (
|
||||
<button className="btn btn-primary btn-sm" onClick={handleMergeMenuItemClick}>
|
||||
<button
|
||||
className="btn btn-primary btn-sm"
|
||||
onClick={manualReviewActionLabel === "Check PR Status" ? handleCheckPrStatus : handleMergeMenuItemClick}
|
||||
disabled={manualReviewActionLabel === "Check PR Status" && isCheckingPrStatus}
|
||||
>
|
||||
{manualReviewActionLabel}
|
||||
</button>
|
||||
)}
|
||||
|
||||
@@ -572,6 +572,114 @@ describe("TaskDetailModal", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("refreshes PR status for Check PR Status without merge prompt", async () => {
|
||||
const { fetchSettings, refreshPrStatus } = await import("../../api");
|
||||
const addToast = vi.fn();
|
||||
const onMergeTask = vi.fn(async () => ({ merged: false } as MergeResult));
|
||||
const onTaskUpdated = vi.fn();
|
||||
|
||||
vi.mocked(fetchSettings).mockResolvedValueOnce({
|
||||
modelPresets: [],
|
||||
autoSelectModelPreset: false,
|
||||
defaultPresetBySize: {},
|
||||
mergeStrategy: "pull-request",
|
||||
autoMerge: false,
|
||||
});
|
||||
vi.mocked(refreshPrStatus).mockResolvedValueOnce({
|
||||
prInfo: {
|
||||
url: "https://github.com/owner/repo/pull/42",
|
||||
number: 42,
|
||||
status: "open",
|
||||
title: "Task",
|
||||
headBranch: "fusion/fn-099",
|
||||
baseBranch: "main",
|
||||
commentCount: 1,
|
||||
},
|
||||
all: [],
|
||||
});
|
||||
|
||||
render(
|
||||
<TaskDetailModal
|
||||
task={makeTask({
|
||||
column: "in-review" as Column,
|
||||
prInfo: {
|
||||
url: "https://github.com/owner/repo/pull/42",
|
||||
number: 42,
|
||||
status: "open",
|
||||
title: "Task",
|
||||
headBranch: "fusion/fn-099",
|
||||
baseBranch: "main",
|
||||
commentCount: 0,
|
||||
},
|
||||
})}
|
||||
onClose={noop}
|
||||
onMoveTask={noopMove}
|
||||
onDeleteTask={noopDelete}
|
||||
onMergeTask={onMergeTask}
|
||||
onOpenDetail={noopOpenDetail}
|
||||
onTaskUpdated={onTaskUpdated}
|
||||
addToast={addToast}
|
||||
projectId="project-1"
|
||||
/>,
|
||||
);
|
||||
|
||||
fireEvent.click(await screen.findByRole("button", { name: "Check PR Status" }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(refreshPrStatus).toHaveBeenCalledWith("FN-099", "project-1");
|
||||
});
|
||||
expect(onMergeTask).not.toHaveBeenCalled();
|
||||
expect(mockConfirm).not.toHaveBeenCalled();
|
||||
expect(addToast).toHaveBeenCalledWith("PR status refreshed", "success");
|
||||
});
|
||||
|
||||
it("shows error toast when Check PR Status refresh fails", async () => {
|
||||
const { fetchSettings, refreshPrStatus } = await import("../../api");
|
||||
const addToast = vi.fn();
|
||||
const onMergeTask = vi.fn(async () => ({ merged: false } as MergeResult));
|
||||
|
||||
vi.mocked(fetchSettings).mockResolvedValueOnce({
|
||||
modelPresets: [],
|
||||
autoSelectModelPreset: false,
|
||||
defaultPresetBySize: {},
|
||||
mergeStrategy: "pull-request",
|
||||
autoMerge: false,
|
||||
});
|
||||
vi.mocked(refreshPrStatus).mockRejectedValueOnce(new Error("refresh failed"));
|
||||
|
||||
render(
|
||||
<TaskDetailModal
|
||||
task={makeTask({
|
||||
column: "in-review" as Column,
|
||||
prInfo: {
|
||||
url: "https://github.com/owner/repo/pull/42",
|
||||
number: 42,
|
||||
status: "open",
|
||||
title: "Task",
|
||||
headBranch: "fusion/fn-099",
|
||||
baseBranch: "main",
|
||||
commentCount: 0,
|
||||
},
|
||||
})}
|
||||
onClose={noop}
|
||||
onMoveTask={noopMove}
|
||||
onDeleteTask={noopDelete}
|
||||
onMergeTask={onMergeTask}
|
||||
onOpenDetail={noopOpenDetail}
|
||||
addToast={addToast}
|
||||
/>,
|
||||
);
|
||||
|
||||
fireEvent.click(await screen.findByRole("button", { name: "Check PR Status" }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(refreshPrStatus).toHaveBeenCalledWith("FN-099", undefined);
|
||||
});
|
||||
expect(onMergeTask).not.toHaveBeenCalled();
|
||||
expect(mockConfirm).not.toHaveBeenCalled();
|
||||
expect(addToast).toHaveBeenCalledWith("refresh failed", "error");
|
||||
});
|
||||
|
||||
it.each([
|
||||
[{ status: "open" as const }, "Check PR Status"],
|
||||
[{ status: "merged" as const }, "Finish & Close"],
|
||||
|
||||
Reference in New Issue
Block a user