mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-10-31 15:54:24 +00:00
Co-authored-by: Alan Buscaglia <gentlemanprogramming@gmail.com>
149 lines
3.7 KiB
TypeScript
149 lines
3.7 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import {
|
|
createInitialLighthouseV2StreamState,
|
|
reduceLighthouseV2Event,
|
|
} from "./event-reducer";
|
|
|
|
describe("event-reducer", () => {
|
|
it("should append message deltas", () => {
|
|
// Given
|
|
const state = createInitialLighthouseV2StreamState("task-1");
|
|
|
|
// When
|
|
const next = reduceLighthouseV2Event(state, {
|
|
type: "message.delta",
|
|
content: "Hello",
|
|
});
|
|
|
|
// Then
|
|
expect(next.assistantText).toBe("Hello");
|
|
expect(next.status).toBe("streaming");
|
|
});
|
|
|
|
it("should pair tool start and end events", () => {
|
|
// Given
|
|
const state = reduceLighthouseV2Event(
|
|
createInitialLighthouseV2StreamState("task-1"),
|
|
{
|
|
type: "tool_call.start",
|
|
toolCallId: "tool-1",
|
|
toolName: "search",
|
|
},
|
|
);
|
|
|
|
// When
|
|
const next = reduceLighthouseV2Event(state, {
|
|
type: "tool_call.end",
|
|
toolCallId: "tool-1",
|
|
outcome: "success",
|
|
});
|
|
|
|
// Then
|
|
expect(next.toolCalls).toEqual([
|
|
{
|
|
id: "tool-1",
|
|
name: "search",
|
|
status: "completed",
|
|
outcome: "success",
|
|
},
|
|
]);
|
|
});
|
|
|
|
it("should preserve the live display order of text and tool events", () => {
|
|
// Given
|
|
let state = createInitialLighthouseV2StreamState("task-1");
|
|
|
|
// When
|
|
state = reduceLighthouseV2Event(state, {
|
|
type: "message.delta",
|
|
content: "Voy a buscar los findings por severidad",
|
|
});
|
|
state = reduceLighthouseV2Event(state, {
|
|
type: "tool_call.start",
|
|
toolCallId: "tool-1",
|
|
toolName: "prowler_search_security_findings",
|
|
});
|
|
state = reduceLighthouseV2Event(state, {
|
|
type: "tool_call.end",
|
|
toolCallId: "tool-1",
|
|
outcome: "success",
|
|
});
|
|
state = reduceLighthouseV2Event(state, {
|
|
type: "message.delta",
|
|
content: "Ahora voy a buscar en los criticos",
|
|
});
|
|
|
|
// Then
|
|
expect(state.activityItems).toEqual([
|
|
{
|
|
id: "text-0",
|
|
type: "text",
|
|
text: "Voy a buscar los findings por severidad",
|
|
},
|
|
{
|
|
id: "tool-1",
|
|
type: "tool_call",
|
|
name: "prowler_search_security_findings",
|
|
status: "completed",
|
|
outcome: "success",
|
|
},
|
|
{
|
|
id: "text-2",
|
|
type: "text",
|
|
text: "Ahora voy a buscar en los criticos",
|
|
},
|
|
]);
|
|
});
|
|
|
|
it("should mark message end as completed", () => {
|
|
// Given
|
|
const state = createInitialLighthouseV2StreamState("task-1");
|
|
|
|
// When
|
|
const next = reduceLighthouseV2Event(state, {
|
|
type: "message.end",
|
|
messageId: "message-1",
|
|
});
|
|
|
|
// Then
|
|
expect(next.status).toBe("completed");
|
|
expect(next.messageId).toBe("message-1");
|
|
expect(next.activeTaskId).toBeNull();
|
|
});
|
|
|
|
it("should store terminal errors", () => {
|
|
// Given
|
|
const state = createInitialLighthouseV2StreamState("task-1");
|
|
|
|
// When
|
|
const next = reduceLighthouseV2Event(state, {
|
|
type: "error",
|
|
code: "llm_error",
|
|
detail: "Provider failed",
|
|
});
|
|
|
|
// Then
|
|
expect(next.status).toBe("error");
|
|
expect(next.error).toEqual({
|
|
code: "llm_error",
|
|
detail: "Provider failed",
|
|
});
|
|
expect(next.activeTaskId).toBeNull();
|
|
});
|
|
|
|
it("should clear the task gate on disconnect so retry can recover", () => {
|
|
// Given
|
|
const state = createInitialLighthouseV2StreamState("task-1");
|
|
|
|
// When
|
|
const next = reduceLighthouseV2Event(state, { type: "disconnect" });
|
|
|
|
// Then
|
|
expect(next.status).toBe("disconnected");
|
|
// activeTaskId must be cleared: leaving it set keeps canSend false and
|
|
// makes the Retry button a no-op after a dropped SSE connection.
|
|
expect(next.activeTaskId).toBeNull();
|
|
});
|
|
});
|