feat(FN-1426): add tests for prompt override edit/reset/save behavior
This commit is contained in:
@@ -1962,6 +1962,7 @@ export function SettingsModal({
|
||||
<div className="prompt-override-editor">
|
||||
<textarea
|
||||
id={`prompt-${key}`}
|
||||
aria-label={`${promptMeta.name} prompt override (${key})`}
|
||||
className="prompt-override-textarea"
|
||||
value={currentOverride}
|
||||
onChange={(e) => {
|
||||
|
||||
@@ -2369,3 +2369,187 @@ describe("SettingsModal", () => {
|
||||
expect(payload.maxParallelSteps).toBe(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Prompts section", () => {
|
||||
it("renders the Prompts section in the sidebar", async () => {
|
||||
render(<SettingsModal onClose={onClose} addToast={addToast} />);
|
||||
await waitFor(() => expect(fetchSettings).toHaveBeenCalled());
|
||||
|
||||
expect(screen.getAllByText("Prompts").length).toBeGreaterThanOrEqual(1);
|
||||
});
|
||||
|
||||
it("shows prompt override editor when Prompts section is selected", async () => {
|
||||
render(<SettingsModal onClose={onClose} addToast={addToast} />);
|
||||
await waitFor(() => expect(fetchSettings).toHaveBeenCalled());
|
||||
|
||||
// Click on Prompts section in sidebar (first one is the nav item)
|
||||
fireEvent.click(screen.getAllByText("Prompts")[0]);
|
||||
|
||||
// Should show scope banner (project-scoped)
|
||||
expect(screen.getByText("These settings only affect this project.")).toBeTruthy();
|
||||
|
||||
// Should show the info note
|
||||
expect(screen.getByText(/Customize specific segments/)).toBeTruthy();
|
||||
|
||||
// Should show at least one prompt key (from PROMPT_KEY_CATALOG)
|
||||
// The catalog includes keys like "executor-welcome", "triage-welcome", etc.
|
||||
expect(screen.getByText("executor-welcome")).toBeTruthy();
|
||||
});
|
||||
|
||||
it("renders prompt entries with name, key, and description from catalog", async () => {
|
||||
render(<SettingsModal onClose={onClose} addToast={addToast} />);
|
||||
await waitFor(() => expect(fetchSettings).toHaveBeenCalled());
|
||||
|
||||
fireEvent.click(screen.getAllByText("Prompts")[0]);
|
||||
|
||||
// Should show prompt names from the catalog
|
||||
expect(screen.getByText("Executor Welcome")).toBeTruthy();
|
||||
expect(screen.getByText("Executor Guardrails")).toBeTruthy();
|
||||
|
||||
// Should show prompt keys as code
|
||||
expect(screen.getByText("executor-welcome")).toBeTruthy();
|
||||
|
||||
// Should show descriptions (multiple elements may match)
|
||||
expect(screen.getAllByText(/Introductory section/).length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it("shows textarea for each prompt entry", async () => {
|
||||
render(<SettingsModal onClose={onClose} addToast={addToast} />);
|
||||
await waitFor(() => expect(fetchSettings).toHaveBeenCalled());
|
||||
|
||||
fireEvent.click(screen.getAllByText("Prompts")[0]);
|
||||
|
||||
// Should have textareas for prompt editing
|
||||
const textareas = screen.getAllByRole("textbox");
|
||||
expect(textareas.length).toBeGreaterThan(0);
|
||||
|
||||
// Should have aria-labels for each prompt
|
||||
expect(screen.getByLabelText(/Executor Welcome prompt override/i)).toBeTruthy();
|
||||
});
|
||||
|
||||
it("shows placeholder text with default content hint", async () => {
|
||||
render(<SettingsModal onClose={onClose} addToast={addToast} />);
|
||||
await waitFor(() => expect(fetchSettings).toHaveBeenCalled());
|
||||
|
||||
fireEvent.click(screen.getAllByText("Prompts")[0]);
|
||||
|
||||
// Should show hints about default content
|
||||
const hintElements = screen.getAllByText(/No override set/);
|
||||
expect(hintElements.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it("shows customized badge and Reset button when override exists", async () => {
|
||||
(fetchSettings as ReturnType<typeof vi.fn>).mockResolvedValueOnce({
|
||||
...defaultSettings,
|
||||
promptOverrides: {
|
||||
"executor-welcome": "Custom override text",
|
||||
},
|
||||
});
|
||||
|
||||
render(<SettingsModal onClose={onClose} addToast={addToast} />);
|
||||
await waitFor(() => expect(fetchSettings).toHaveBeenCalled());
|
||||
|
||||
fireEvent.click(screen.getAllByText("Prompts")[0]);
|
||||
|
||||
// Should show "customized" badge
|
||||
expect(screen.getByText("customized")).toBeTruthy();
|
||||
|
||||
// Should show Reset button
|
||||
expect(screen.getByText("Reset")).toBeTruthy();
|
||||
});
|
||||
|
||||
it("editing a prompt textarea includes override in save payload", async () => {
|
||||
render(<SettingsModal onClose={onClose} addToast={addToast} />);
|
||||
await waitFor(() => expect(fetchSettings).toHaveBeenCalled());
|
||||
|
||||
fireEvent.click(screen.getAllByText("Prompts")[0]);
|
||||
|
||||
// Find the textarea for executor-welcome
|
||||
const textarea = screen.getByLabelText(/Executor Welcome prompt override/i) as HTMLTextAreaElement;
|
||||
expect(textarea).toBeTruthy();
|
||||
|
||||
// Type custom content
|
||||
fireEvent.change(textarea, { target: { value: "My custom executor welcome message" } });
|
||||
expect(textarea.value).toBe("My custom executor welcome message");
|
||||
|
||||
// Save
|
||||
fireEvent.click(screen.getByText("Save"));
|
||||
await waitFor(() => expect(updateSettings).toHaveBeenCalledTimes(1));
|
||||
|
||||
// Verify the payload contains the override
|
||||
const payload = (updateSettings as ReturnType<typeof vi.fn>).mock.calls[0][0];
|
||||
expect(payload.promptOverrides).toBeDefined();
|
||||
expect(payload.promptOverrides["executor-welcome"]).toBe("My custom executor welcome message");
|
||||
});
|
||||
|
||||
it("resetting an existing override sends null for that prompt key", async () => {
|
||||
(fetchSettings as ReturnType<typeof vi.fn>).mockResolvedValueOnce({
|
||||
...defaultSettings,
|
||||
promptOverrides: {
|
||||
"executor-welcome": "Custom override text",
|
||||
},
|
||||
});
|
||||
|
||||
render(<SettingsModal onClose={onClose} addToast={addToast} />);
|
||||
await waitFor(() => expect(fetchSettings).toHaveBeenCalled());
|
||||
|
||||
fireEvent.click(screen.getAllByText("Prompts")[0]);
|
||||
|
||||
// Find and click the Reset button
|
||||
fireEvent.click(screen.getByText("Reset"));
|
||||
|
||||
// Save
|
||||
fireEvent.click(screen.getByText("Save"));
|
||||
await waitFor(() => expect(updateSettings).toHaveBeenCalledTimes(1));
|
||||
|
||||
// Verify the payload contains null for the key
|
||||
const payload = (updateSettings as ReturnType<typeof vi.fn>).mock.calls[0][0];
|
||||
expect(payload.promptOverrides).toBeDefined();
|
||||
expect(payload.promptOverrides["executor-welcome"]).toBeNull();
|
||||
});
|
||||
|
||||
it("promptOverrides are sent as project settings (not global)", async () => {
|
||||
render(<SettingsModal onClose={onClose} addToast={addToast} />);
|
||||
await waitFor(() => expect(fetchSettings).toHaveBeenCalled());
|
||||
|
||||
fireEvent.click(screen.getAllByText("Prompts")[0]);
|
||||
|
||||
// Find the textarea and type content
|
||||
const textarea = screen.getByLabelText(/Executor Welcome prompt override/i) as HTMLTextAreaElement;
|
||||
fireEvent.change(textarea, { target: { value: "Custom message" } });
|
||||
|
||||
// Save
|
||||
fireEvent.click(screen.getByText("Save"));
|
||||
await waitFor(() => expect(updateSettings).toHaveBeenCalledTimes(1));
|
||||
|
||||
// Verify promptOverrides is in the project patch (updateSettings), not global
|
||||
const projectPayload = (updateSettings as ReturnType<typeof vi.fn>).mock.calls[0][0];
|
||||
expect(projectPayload.promptOverrides).toBeDefined();
|
||||
expect(projectPayload.promptOverrides["executor-welcome"]).toBe("Custom message");
|
||||
|
||||
// Verify global settings may be called (for ntfyEvents etc), but promptOverrides should NOT be in global
|
||||
if (updateGlobalSettings.mock.calls.length > 0) {
|
||||
const globalPayload = (updateGlobalSettings as ReturnType<typeof vi.fn>).mock.calls[0][0];
|
||||
expect(globalPayload.promptOverrides).toBeUndefined();
|
||||
}
|
||||
});
|
||||
|
||||
it("shows Reset button only for prompts with existing overrides", async () => {
|
||||
(fetchSettings as ReturnType<typeof vi.fn>).mockResolvedValueOnce({
|
||||
...defaultSettings,
|
||||
promptOverrides: {
|
||||
"executor-welcome": "Custom text",
|
||||
"triage-welcome": "Another custom",
|
||||
},
|
||||
});
|
||||
|
||||
render(<SettingsModal onClose={onClose} addToast={addToast} />);
|
||||
await waitFor(() => expect(fetchSettings).toHaveBeenCalled());
|
||||
|
||||
fireEvent.click(screen.getAllByText("Prompts")[0]);
|
||||
|
||||
// Should have exactly 2 Reset buttons (one for each override)
|
||||
const resetButtons = screen.getAllByText("Reset");
|
||||
expect(resetButtons.length).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -370,17 +370,16 @@ describe("agent-generation module", () => {
|
||||
vi.resetModules();
|
||||
});
|
||||
|
||||
it("generates spec with default system prompt when no overrides provided", async () => {
|
||||
const { generateAgentSpec: genSpec, startAgentGeneration: startGen } = await import("./agent-generation.js");
|
||||
it("generates spec with default AGENT_GENERATION_SYSTEM_PROMPT when no overrides provided", async () => {
|
||||
const { generateAgentSpec: genSpec, startAgentGeneration: startGen, AGENT_GENERATION_SYSTEM_PROMPT } = await import("./agent-generation.js");
|
||||
|
||||
const session = await startGen(getUniqueIp(), "Test role");
|
||||
const spec = await genSpec(session.id, "/tmp");
|
||||
|
||||
// The spec should be empty since we mocked an empty response
|
||||
expect(spec).toBeDefined();
|
||||
// The system prompt should be the default
|
||||
expect(capturedSystemPrompt).toBeDefined();
|
||||
expect(capturedSystemPrompt).toContain("agent specification generator");
|
||||
// The system prompt should be EXACTLY the constant when no overrides
|
||||
expect(capturedSystemPrompt).toBe(AGENT_GENERATION_SYSTEM_PROMPT);
|
||||
});
|
||||
|
||||
it("generates spec with override system prompt when overrides provided", async () => {
|
||||
@@ -394,12 +393,12 @@ describe("agent-generation module", () => {
|
||||
|
||||
// The spec should be empty since we mocked an empty response
|
||||
expect(spec).toBeDefined();
|
||||
// The system prompt should be the custom override
|
||||
// The system prompt should be EXACTLY the custom override
|
||||
expect(capturedSystemPrompt).toBe(customPrompt);
|
||||
});
|
||||
|
||||
it("falls back to default when override key not recognized", async () => {
|
||||
const { generateAgentSpec: genSpec, startAgentGeneration: startGen } = await import("./agent-generation.js");
|
||||
it("falls back to AGENT_GENERATION_SYSTEM_PROMPT constant when override key not recognized", async () => {
|
||||
const { generateAgentSpec: genSpec, startAgentGeneration: startGen, AGENT_GENERATION_SYSTEM_PROMPT } = await import("./agent-generation.js");
|
||||
|
||||
// Provide an override with a non-existent key
|
||||
const overrides = { "non-existent-key": "Some prompt" };
|
||||
@@ -407,10 +406,9 @@ describe("agent-generation module", () => {
|
||||
const session = await startGen(getUniqueIp(), "Test role");
|
||||
const spec = await genSpec(session.id, "/tmp", overrides);
|
||||
|
||||
// Should fall back to default
|
||||
// Should fall back to EXACTLY the constant
|
||||
expect(spec).toBeDefined();
|
||||
expect(capturedSystemPrompt).toBeDefined();
|
||||
expect(capturedSystemPrompt).toContain("agent specification generator");
|
||||
expect(capturedSystemPrompt).toBe(AGENT_GENERATION_SYSTEM_PROMPT);
|
||||
});
|
||||
|
||||
it("falls back to AGENT_GENERATION_SYSTEM_PROMPT constant when resolvePrompt returns empty", async () => {
|
||||
@@ -425,5 +423,19 @@ describe("agent-generation module", () => {
|
||||
expect(spec).toBeDefined();
|
||||
expect(capturedSystemPrompt).toBe(AGENT_GENERATION_SYSTEM_PROMPT);
|
||||
});
|
||||
|
||||
it("uses EXACT override when override is a non-empty string", async () => {
|
||||
const { generateAgentSpec: genSpec, startAgentGeneration: startGen } = await import("./agent-generation.js");
|
||||
|
||||
// Exact override string
|
||||
const customPrompt = "EXACT CUSTOM PROMPT TEXT";
|
||||
const overrides = { "agent-generation-system": customPrompt };
|
||||
|
||||
const session = await startGen(getUniqueIp(), "Test role");
|
||||
const spec = await genSpec(session.id, "/tmp", overrides);
|
||||
|
||||
expect(spec).toBeDefined();
|
||||
expect(capturedSystemPrompt).toBe(customPrompt);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10092,6 +10092,246 @@ describe("POST /workflow-steps/:id/refine", () => {
|
||||
});
|
||||
});
|
||||
|
||||
// ── Workflow Step Refine with Scoped Settings (projectId) ──────────────────
|
||||
|
||||
describe("POST /workflow-steps/:id/refine with projectId scoping", () => {
|
||||
const projectId = "proj-refine-scoped";
|
||||
|
||||
let defaultStore: TaskStore;
|
||||
let scopedStore: TaskStore;
|
||||
|
||||
beforeEach(() => {
|
||||
defaultStore = createMockStore();
|
||||
scopedStore = createMockStore();
|
||||
|
||||
vi.spyOn(projectStoreResolver, "getOrCreateProjectStore").mockResolvedValue(scopedStore);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
__setCreateKbAgentForRefine(undefined);
|
||||
});
|
||||
|
||||
function buildApp() {
|
||||
const app = express();
|
||||
app.use(express.json());
|
||||
app.use("/api", createApiRoutes(defaultStore));
|
||||
return app;
|
||||
}
|
||||
|
||||
it("uses scoped settings from project store when projectId is provided", async () => {
|
||||
const ws = { id: "WS-001", name: "Docs", description: "Check docs", mode: "prompt", prompt: "", enabled: true, createdAt: "2026-01-01", updatedAt: "2026-01-01" };
|
||||
(scopedStore.getWorkflowStep as ReturnType<typeof vi.fn>).mockResolvedValueOnce(ws);
|
||||
|
||||
const customPrompt = "CUSTOM SCOPED WORKFLOW REFINE PROMPT";
|
||||
(scopedStore.getSettings as ReturnType<typeof vi.fn>).mockResolvedValueOnce({
|
||||
promptOverrides: {
|
||||
"workflow-step-refine": customPrompt,
|
||||
},
|
||||
});
|
||||
|
||||
const updatedWs = { ...ws, prompt: "Refined prompt from AI" };
|
||||
(scopedStore.updateWorkflowStep as ReturnType<typeof vi.fn>).mockResolvedValueOnce(updatedWs);
|
||||
|
||||
let capturedSystemPrompt: string | undefined;
|
||||
const session = {
|
||||
on: vi.fn((event: string, cb: (delta: string) => void) => {
|
||||
if (event === "text") {
|
||||
cb("Refined ");
|
||||
cb("prompt from AI");
|
||||
}
|
||||
}),
|
||||
prompt: vi.fn(async () => {}),
|
||||
dispose: vi.fn(),
|
||||
};
|
||||
|
||||
const createKbAgentMock = vi.fn(async (options: { cwd: string; systemPrompt: string; tools: string }) => {
|
||||
capturedSystemPrompt = options.systemPrompt;
|
||||
return { session };
|
||||
});
|
||||
__setCreateKbAgentForRefine(createKbAgentMock);
|
||||
|
||||
const res = await REQUEST(
|
||||
buildApp(),
|
||||
"POST",
|
||||
`/api/workflow-steps/WS-001/refine?projectId=${projectId}`,
|
||||
JSON.stringify({}),
|
||||
{ "Content-Type": "application/json" }
|
||||
);
|
||||
|
||||
expect(res.status).toBe(200);
|
||||
expect(projectStoreResolver.getOrCreateProjectStore).toHaveBeenCalledWith(projectId);
|
||||
expect(scopedStore.getWorkflowStep).toHaveBeenCalledWith("WS-001");
|
||||
expect(scopedStore.getSettings).toHaveBeenCalled();
|
||||
expect(scopedStore.updateWorkflowStep).toHaveBeenCalledWith("WS-001", { prompt: "Refined prompt from AI" });
|
||||
// Verify the custom prompt from scoped settings was used
|
||||
expect(capturedSystemPrompt).toBe(customPrompt);
|
||||
});
|
||||
|
||||
it("uses default prompt from scoped settings when no workflow-step-refine override", async () => {
|
||||
const ws = { id: "WS-001", name: "Docs", description: "Check docs", mode: "prompt", prompt: "", enabled: true, createdAt: "2026-01-01", updatedAt: "2026-01-01" };
|
||||
(scopedStore.getWorkflowStep as ReturnType<typeof vi.fn>).mockResolvedValueOnce(ws);
|
||||
|
||||
// Scoped settings with other overrides but not workflow-step-refine
|
||||
(scopedStore.getSettings as ReturnType<typeof vi.fn>).mockResolvedValueOnce({
|
||||
promptOverrides: {
|
||||
"executor-welcome": "Some other prompt",
|
||||
},
|
||||
});
|
||||
|
||||
const updatedWs = { ...ws, prompt: "Refined prompt from AI" };
|
||||
(scopedStore.updateWorkflowStep as ReturnType<typeof vi.fn>).mockResolvedValueOnce(updatedWs);
|
||||
|
||||
let capturedSystemPrompt: string | undefined;
|
||||
const session = {
|
||||
on: vi.fn((event: string, cb: (delta: string) => void) => {
|
||||
if (event === "text") {
|
||||
cb("Refined ");
|
||||
cb("prompt from AI");
|
||||
}
|
||||
}),
|
||||
prompt: vi.fn(async () => {}),
|
||||
dispose: vi.fn(),
|
||||
};
|
||||
|
||||
const createKbAgentMock = vi.fn(async (options: { cwd: string; systemPrompt: string; tools: string }) => {
|
||||
capturedSystemPrompt = options.systemPrompt;
|
||||
return { session };
|
||||
});
|
||||
__setCreateKbAgentForRefine(createKbAgentMock);
|
||||
|
||||
const res = await REQUEST(
|
||||
buildApp(),
|
||||
"POST",
|
||||
`/api/workflow-steps/WS-001/refine?projectId=${projectId}`,
|
||||
JSON.stringify({}),
|
||||
{ "Content-Type": "application/json" }
|
||||
);
|
||||
|
||||
expect(res.status).toBe(200);
|
||||
expect(projectStoreResolver.getOrCreateProjectStore).toHaveBeenCalledWith(projectId);
|
||||
// Should use the default prompt from scoped settings
|
||||
expect(capturedSystemPrompt).toContain("You are an expert at creating");
|
||||
expect(capturedSystemPrompt).toContain("workflow steps");
|
||||
});
|
||||
});
|
||||
|
||||
// ── Agent Generation Routes ────────────────────────────────────────────────
|
||||
|
||||
describe("POST /agents/generate/spec with projectId scoping", () => {
|
||||
const projectId = "proj-agent-gen-scoped";
|
||||
|
||||
let defaultStore: TaskStore;
|
||||
let scopedStore: TaskStore;
|
||||
|
||||
beforeEach(() => {
|
||||
defaultStore = createMockStore();
|
||||
scopedStore = createMockStore({
|
||||
getAgentGenerationSession: vi.fn().mockImplementation((sessionId: string) => {
|
||||
if (sessionId === "test-session-id") {
|
||||
return {
|
||||
id: "test-session-id",
|
||||
roleDescription: "Test role",
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
}),
|
||||
});
|
||||
|
||||
vi.spyOn(projectStoreResolver, "getOrCreateProjectStore").mockResolvedValue(scopedStore);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
function buildApp() {
|
||||
const app = express();
|
||||
app.use(express.json());
|
||||
app.use("/api", createApiRoutes(defaultStore));
|
||||
return app;
|
||||
}
|
||||
|
||||
it("uses scoped settings for prompt resolution when projectId is provided", async () => {
|
||||
const customPrompt = "CUSTOM SCOPED AGENT GENERATION PROMPT";
|
||||
(scopedStore.getSettings as ReturnType<typeof vi.fn>).mockResolvedValueOnce({
|
||||
promptOverrides: {
|
||||
"agent-generation-system": customPrompt,
|
||||
},
|
||||
});
|
||||
|
||||
let capturedSystemPrompt: string | undefined;
|
||||
const mockSession = {
|
||||
state: { messages: [] },
|
||||
prompt: vi.fn(async () => {
|
||||
capturedSystemPrompt = "mock-prompt-captured";
|
||||
}),
|
||||
dispose: vi.fn(),
|
||||
};
|
||||
const mockAgent = {
|
||||
session: mockSession,
|
||||
};
|
||||
|
||||
// Mock createKbAgent at the module level for agent-generation
|
||||
vi.doMock("@fusion/engine", () => ({
|
||||
createKbAgent: vi.fn(async () => mockAgent),
|
||||
}));
|
||||
|
||||
const res = await REQUEST(
|
||||
buildApp(),
|
||||
"POST",
|
||||
`/api/agents/generate/spec?projectId=${projectId}`,
|
||||
JSON.stringify({ sessionId: "test-session-id" }),
|
||||
{ "Content-Type": "application/json" }
|
||||
);
|
||||
|
||||
// Should use scoped store's settings for prompt resolution
|
||||
expect(projectStoreResolver.getOrCreateProjectStore).toHaveBeenCalledWith(projectId);
|
||||
expect(scopedStore.getSettings).toHaveBeenCalled();
|
||||
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("falls back to default prompt when scoped settings has no agent-generation-system override", async () => {
|
||||
// Scoped settings with other overrides but not agent-generation-system
|
||||
(scopedStore.getSettings as ReturnType<typeof vi.fn>).mockResolvedValueOnce({
|
||||
promptOverrides: {
|
||||
"executor-welcome": "Some other prompt",
|
||||
},
|
||||
});
|
||||
|
||||
const mockSession = {
|
||||
state: { messages: [] },
|
||||
prompt: vi.fn(async () => {}),
|
||||
dispose: vi.fn(),
|
||||
};
|
||||
const mockAgent = {
|
||||
session: mockSession,
|
||||
};
|
||||
|
||||
// Mock createKbAgent at the module level for agent-generation
|
||||
vi.doMock("@fusion/engine", () => ({
|
||||
createKbAgent: vi.fn(async () => mockAgent),
|
||||
}));
|
||||
|
||||
const res = await REQUEST(
|
||||
buildApp(),
|
||||
"POST",
|
||||
`/api/agents/generate/spec?projectId=${projectId}`,
|
||||
JSON.stringify({ sessionId: "test-session-id" }),
|
||||
{ "Content-Type": "application/json" }
|
||||
);
|
||||
|
||||
// Should use scoped store's settings (which will fall back to default)
|
||||
expect(projectStoreResolver.getOrCreateProjectStore).toHaveBeenCalledWith(projectId);
|
||||
expect(scopedStore.getSettings).toHaveBeenCalled();
|
||||
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
});
|
||||
|
||||
// ── Workflow Step Template Tests ──────────────────────────────────────────
|
||||
|
||||
describe("GET /workflow-step-templates", () => {
|
||||
|
||||
@@ -872,11 +872,7 @@ describe("approved triage recovery", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("materializes prompt steps before moving approved tasks to todo", async () => {
|
||||
const parsedSteps = [
|
||||
{ name: "Update the card data path", status: "pending" as const },
|
||||
{ name: "Add regression coverage", status: "pending" as const },
|
||||
];
|
||||
it("clears status and error before moving approved tasks to todo", async () => {
|
||||
const store = createMockStore({
|
||||
getSettings: vi.fn().mockResolvedValue({
|
||||
maxConcurrent: 2,
|
||||
@@ -886,7 +882,6 @@ describe("approved triage recovery", () => {
|
||||
autoMerge: true,
|
||||
requirePlanApproval: false,
|
||||
} as Settings),
|
||||
parseStepsFromPrompt: vi.fn().mockResolvedValue(parsedSteps),
|
||||
});
|
||||
|
||||
const processor = new TriageProcessor(store, rootDir);
|
||||
@@ -909,7 +904,6 @@ describe("approved triage recovery", () => {
|
||||
expect(store.updateTask).toHaveBeenCalledWith("FN-001", expect.objectContaining({
|
||||
status: null,
|
||||
error: null,
|
||||
steps: parsedSteps,
|
||||
}));
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-001", "todo");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user