feat(FN-3891): add verificationFixRetries merge control setting
Added a new `verificationFixRetries` merge control to the Settings modal, documented it in the settings reference, and added corresponding tests; a changeset was also included for the `@runfusion/fusion` package. Fusion-Task-Id: FN-3891
This commit is contained in:
@@ -368,6 +368,16 @@ describe("MissionStore", () => {
|
||||
expect(batchedResult.summary.completedFeatures).toBe(singleSummary.completedFeatures);
|
||||
expect(batchedResult.summary.progressPercent).toBe(singleSummary.progressPercent);
|
||||
});
|
||||
|
||||
it("preserves persisted interviewState when listing missions with summaries", () => {
|
||||
const interviewMission = store.createMission({ title: "Interview mission" });
|
||||
store.updateMissionInterviewState(interviewMission.id, "in_progress");
|
||||
|
||||
const listed = store.listMissionsWithSummaries().find((mission) => mission.id === interviewMission.id);
|
||||
|
||||
expect(listed).toBeDefined();
|
||||
expect(listed?.interviewState).toBe("in_progress");
|
||||
});
|
||||
});
|
||||
|
||||
// ── Batched Health Tests ──────────────────────────────────────────────
|
||||
|
||||
@@ -1777,14 +1777,66 @@ describe("MissionManager", () => {
|
||||
|
||||
expect(screen.queryByText("Should not render")).not.toBeInTheDocument();
|
||||
expect(screen.queryByText(/interview sessions pending/i)).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
const awaitingInterviewRow = screen.getByText("Payment workflow planning").closest(".mission-list__item");
|
||||
expect(awaitingInterviewRow).toBeTruthy();
|
||||
fireEvent.click(within(awaitingInterviewRow as HTMLElement).getByLabelText("Resume interview"));
|
||||
it("keeps persisted interview missions distinct from transient interview sessions", async () => {
|
||||
const missionsWithInterview = [
|
||||
{
|
||||
id: "M-PERSISTED-INTERVIEW",
|
||||
title: "Persisted mission interview",
|
||||
description: "Persisted mission row",
|
||||
status: "planning",
|
||||
interviewState: "in_progress",
|
||||
milestones: [],
|
||||
createdAt: "2026-01-06T00:00:00.000Z",
|
||||
updatedAt: "2026-01-06T00:00:00.000Z",
|
||||
},
|
||||
...mockMissions,
|
||||
];
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText("Plan Mission with AI")).toBeInTheDocument();
|
||||
mockFetchAiSessions.mockResolvedValueOnce([
|
||||
{
|
||||
id: "session-awaiting",
|
||||
type: "mission_interview",
|
||||
status: "awaiting_input",
|
||||
title: "Transient interview session",
|
||||
projectId: null,
|
||||
lockedByTab: null,
|
||||
updatedAt: "2026-01-03T00:00:00.000Z",
|
||||
},
|
||||
]);
|
||||
|
||||
globalThis.fetch = createFetchMockWithHealth(missionsWithInterview as Array<Record<string, unknown>>, {
|
||||
...mockMissionHealthById,
|
||||
"M-PERSISTED-INTERVIEW": {
|
||||
missionId: "M-PERSISTED-INTERVIEW",
|
||||
status: "planning",
|
||||
tasksCompleted: 0,
|
||||
tasksFailed: 0,
|
||||
tasksInFlight: 0,
|
||||
totalTasks: 0,
|
||||
estimatedCompletionPercent: 0,
|
||||
autopilotState: "inactive",
|
||||
autopilotEnabled: false,
|
||||
},
|
||||
});
|
||||
|
||||
render(<MissionManager isOpen={true} onClose={vi.fn()} addToast={vi.fn()} />);
|
||||
|
||||
const persistedTitle = await screen.findByText("Persisted mission interview");
|
||||
const transientTitle = await screen.findByText("Transient interview session");
|
||||
|
||||
const persistedRow = persistedTitle.closest(".mission-list__item");
|
||||
const transientRow = transientTitle.closest(".mission-list__item");
|
||||
|
||||
expect(persistedRow).toBeTruthy();
|
||||
expect(transientRow).toBeTruthy();
|
||||
expect(persistedRow).not.toBe(transientRow);
|
||||
|
||||
expect(within(persistedRow as HTMLElement).getByText("Interview in progress")).toBeInTheDocument();
|
||||
expect(within(transientRow as HTMLElement).getByText("Awaiting input")).toBeInTheDocument();
|
||||
expect(screen.queryByText(/interview sessions pending/i)).not.toBeInTheDocument();
|
||||
|
||||
});
|
||||
|
||||
it("only shows in-progress interview sessions scoped to the active project", async () => {
|
||||
|
||||
@@ -708,6 +708,24 @@ describe("Mission API", () => {
|
||||
expect(res.body).toHaveLength(2);
|
||||
});
|
||||
|
||||
it("returns persisted interview-stage missions from list endpoint", async () => {
|
||||
const { app, missionStore } = buildApp();
|
||||
const mission = missionStore.createMission({ title: "Interview draft" });
|
||||
missionStore.updateMissionInterviewState(mission.id, "in_progress");
|
||||
|
||||
const res = await get(app, "/api/missions");
|
||||
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.body).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: mission.id,
|
||||
interviewState: "in_progress",
|
||||
}),
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
it("should return empty array when no missions", async () => {
|
||||
const { app } = buildApp();
|
||||
const res = await get(app, "/api/missions");
|
||||
|
||||
Reference in New Issue
Block a user