mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-04-30 03:00:41 -04:00
test(frontend/builder): add run_agent tool-call detection tests and capture setQueryStates
Adds four tests covering run_agent tool-call handling in useBuilderChatPanel: - sets flowExecutionID via setQueryStates when execution_id is valid - skips setQueryStates when output has no execution_id - rejects path-traversal execution_id (security: /^[\w-]+$/i validation) - deduplicates run_agent via processedToolCallsRef Captures mockSetQueryStates from nuqs mock so run_agent assertions can verify the correct query-state mutation rather than just the absence of errors.
This commit is contained in:
@@ -86,10 +86,11 @@ vi.mock("ai", () => ({
|
||||
}));
|
||||
|
||||
let mockFlowID: string | null = null;
|
||||
const mockSetQueryStates = vi.fn();
|
||||
|
||||
vi.mock("nuqs", () => ({
|
||||
parseAsString: { withDefault: (d: string) => d },
|
||||
useQueryStates: () => [{ flowID: mockFlowID }, vi.fn()],
|
||||
useQueryStates: () => [{ flowID: mockFlowID }, mockSetQueryStates],
|
||||
}));
|
||||
|
||||
// Import after mocks
|
||||
@@ -111,6 +112,7 @@ beforeEach(() => {
|
||||
mockSendMessage.mockClear();
|
||||
mockSetMessages.mockClear();
|
||||
mockToast.mockClear();
|
||||
mockSetQueryStates.mockClear();
|
||||
clearGraphSessionCacheForTesting();
|
||||
});
|
||||
|
||||
@@ -1570,6 +1572,99 @@ describe("useBuilderChatPanel – tool call detection", () => {
|
||||
|
||||
expect(onGraphEdited).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("calls setQueryStates with execution_id when run_agent tool call completes with valid id", async () => {
|
||||
mockChatStatus = "ready";
|
||||
mockChatMessages = [
|
||||
{
|
||||
id: "m1",
|
||||
role: "assistant",
|
||||
parts: [
|
||||
makeDynamicToolPart("run_agent", "tc-run", "output-available", {
|
||||
execution_id: "exec-abc123",
|
||||
}),
|
||||
],
|
||||
},
|
||||
];
|
||||
renderHook(() => useBuilderChatPanel());
|
||||
|
||||
await act(async () => {
|
||||
await new Promise<void>((r) => setTimeout(r, 0));
|
||||
});
|
||||
|
||||
expect(mockSetQueryStates).toHaveBeenCalledWith({
|
||||
flowExecutionID: "exec-abc123",
|
||||
});
|
||||
});
|
||||
|
||||
it("does NOT call setQueryStates when run_agent output has no execution_id", async () => {
|
||||
mockChatStatus = "ready";
|
||||
mockChatMessages = [
|
||||
{
|
||||
id: "m1",
|
||||
role: "assistant",
|
||||
parts: [
|
||||
makeDynamicToolPart("run_agent", "tc-run-null", "output-available", {
|
||||
other_field: "something",
|
||||
}),
|
||||
],
|
||||
},
|
||||
];
|
||||
renderHook(() => useBuilderChatPanel());
|
||||
|
||||
await act(async () => {
|
||||
await new Promise<void>((r) => setTimeout(r, 0));
|
||||
});
|
||||
|
||||
expect(mockSetQueryStates).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does NOT call setQueryStates when run_agent execution_id contains path-traversal characters", async () => {
|
||||
mockChatStatus = "ready";
|
||||
mockChatMessages = [
|
||||
{
|
||||
id: "m1",
|
||||
role: "assistant",
|
||||
parts: [
|
||||
makeDynamicToolPart("run_agent", "tc-run-bad", "output-available", {
|
||||
execution_id: "../../admin",
|
||||
}),
|
||||
],
|
||||
},
|
||||
];
|
||||
renderHook(() => useBuilderChatPanel());
|
||||
|
||||
await act(async () => {
|
||||
await new Promise<void>((r) => setTimeout(r, 0));
|
||||
});
|
||||
|
||||
expect(mockSetQueryStates).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does NOT process run_agent tool call twice (deduplication)", async () => {
|
||||
mockChatStatus = "ready";
|
||||
const part = makeDynamicToolPart(
|
||||
"run_agent",
|
||||
"tc-run-dedup",
|
||||
"output-available",
|
||||
{
|
||||
execution_id: "exec-dedup",
|
||||
},
|
||||
);
|
||||
mockChatMessages = [{ id: "m1", role: "assistant", parts: [part] }];
|
||||
|
||||
const { rerender } = renderHook(() => useBuilderChatPanel());
|
||||
|
||||
await act(async () => {
|
||||
await new Promise<void>((r) => setTimeout(r, 0));
|
||||
});
|
||||
|
||||
expect(mockSetQueryStates).toHaveBeenCalledOnce();
|
||||
|
||||
act(() => rerender());
|
||||
|
||||
expect(mockSetQueryStates).toHaveBeenCalledOnce();
|
||||
});
|
||||
});
|
||||
|
||||
describe("useBuilderChatPanel – prototype pollution blocklist (no-schema nodes)", () => {
|
||||
|
||||
Reference in New Issue
Block a user