test(KB-159): update PlanningModeModal tests for streaming
This commit is contained in:
@@ -6,6 +6,8 @@ import type { Task, TaskDetail, PlanningQuestion, PlanningSummary, MergeResult }
|
|||||||
|
|
||||||
// Mock the API functions
|
// Mock the API functions
|
||||||
const mockStartPlanning = vi.fn();
|
const mockStartPlanning = vi.fn();
|
||||||
|
const mockStartPlanningStreaming = vi.fn();
|
||||||
|
const mockConnectPlanningStream = vi.fn();
|
||||||
const mockRespondToPlanning = vi.fn();
|
const mockRespondToPlanning = vi.fn();
|
||||||
const mockCancelPlanning = vi.fn();
|
const mockCancelPlanning = vi.fn();
|
||||||
const mockCreateTaskFromPlanning = vi.fn();
|
const mockCreateTaskFromPlanning = vi.fn();
|
||||||
@@ -22,6 +24,8 @@ const mockRefineTask = vi.fn();
|
|||||||
|
|
||||||
vi.mock("../api", () => ({
|
vi.mock("../api", () => ({
|
||||||
startPlanning: (...args: any[]) => mockStartPlanning(...args),
|
startPlanning: (...args: any[]) => mockStartPlanning(...args),
|
||||||
|
startPlanningStreaming: (...args: any[]) => mockStartPlanningStreaming(...args),
|
||||||
|
connectPlanningStream: (...args: any[]) => mockConnectPlanningStream(...args),
|
||||||
respondToPlanning: (...args: any[]) => mockRespondToPlanning(...args),
|
respondToPlanning: (...args: any[]) => mockRespondToPlanning(...args),
|
||||||
cancelPlanning: (...args: any[]) => mockCancelPlanning(...args),
|
cancelPlanning: (...args: any[]) => mockCancelPlanning(...args),
|
||||||
createTaskFromPlanning: (...args: any[]) => mockCreateTaskFromPlanning(...args),
|
createTaskFromPlanning: (...args: any[]) => mockCreateTaskFromPlanning(...args),
|
||||||
@@ -94,6 +98,21 @@ describe("PlanningModeModal", () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
vi.spyOn(window, "confirm").mockReturnValue(true);
|
vi.spyOn(window, "confirm").mockReturnValue(true);
|
||||||
|
|
||||||
|
// Default mock for streaming
|
||||||
|
mockStartPlanningStreaming.mockResolvedValue({ sessionId: "session-123" });
|
||||||
|
|
||||||
|
// Default: simulate receiving a question after a brief delay
|
||||||
|
mockConnectPlanningStream.mockImplementation((sessionId: string, handlers: any) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
handlers.onQuestion?.(mockQuestion);
|
||||||
|
}, 10);
|
||||||
|
|
||||||
|
return {
|
||||||
|
close: vi.fn(),
|
||||||
|
isConnected: vi.fn().mockReturnValue(true),
|
||||||
|
};
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Initial view", () => {
|
describe("Initial view", () => {
|
||||||
@@ -160,12 +179,6 @@ describe("PlanningModeModal", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("auto-starts planning when initialPlan prop is provided", async () => {
|
it("auto-starts planning when initialPlan prop is provided", async () => {
|
||||||
mockStartPlanning.mockResolvedValue({
|
|
||||||
sessionId: "session-123",
|
|
||||||
currentQuestion: mockQuestion,
|
|
||||||
summary: null,
|
|
||||||
});
|
|
||||||
|
|
||||||
render(
|
render(
|
||||||
<PlanningModeModal
|
<PlanningModeModal
|
||||||
isOpen={true}
|
isOpen={true}
|
||||||
@@ -176,9 +189,9 @@ describe("PlanningModeModal", () => {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
// Wait for startPlanning to be called
|
// Wait for startPlanningStreaming to be called
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(mockStartPlanning).toHaveBeenCalledWith("Build a login system from new task dialog");
|
expect(mockStartPlanningStreaming).toHaveBeenCalledWith("Build a login system from new task dialog");
|
||||||
});
|
});
|
||||||
|
|
||||||
// Should transition to question view
|
// Should transition to question view
|
||||||
@@ -188,12 +201,6 @@ describe("PlanningModeModal", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("sets initial plan text in textarea when initialPlan prop is provided", async () => {
|
it("sets initial plan text in textarea when initialPlan prop is provided", async () => {
|
||||||
mockStartPlanning.mockResolvedValue({
|
|
||||||
sessionId: "session-123",
|
|
||||||
currentQuestion: mockQuestion,
|
|
||||||
summary: null,
|
|
||||||
});
|
|
||||||
|
|
||||||
render(
|
render(
|
||||||
<PlanningModeModal
|
<PlanningModeModal
|
||||||
isOpen={true}
|
isOpen={true}
|
||||||
@@ -206,19 +213,13 @@ describe("PlanningModeModal", () => {
|
|||||||
|
|
||||||
// The auto-start should happen with the initial plan
|
// The auto-start should happen with the initial plan
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(mockStartPlanning).toHaveBeenCalledWith("Pre-filled plan from new task");
|
expect(mockStartPlanningStreaming).toHaveBeenCalledWith("Pre-filled plan from new task");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Planning flow", () => {
|
describe("Planning flow", () => {
|
||||||
it("starts planning and shows question view", async () => {
|
it("starts planning and shows question view", async () => {
|
||||||
mockStartPlanning.mockResolvedValue({
|
|
||||||
sessionId: "session-123",
|
|
||||||
currentQuestion: mockQuestion,
|
|
||||||
summary: null,
|
|
||||||
});
|
|
||||||
|
|
||||||
render(
|
render(
|
||||||
<PlanningModeModal
|
<PlanningModeModal
|
||||||
isOpen={true}
|
isOpen={true}
|
||||||
@@ -233,15 +234,29 @@ describe("PlanningModeModal", () => {
|
|||||||
|
|
||||||
fireEvent.click(screen.getByText("Start Planning"));
|
fireEvent.click(screen.getByText("Start Planning"));
|
||||||
|
|
||||||
|
// Wait for streaming to be called
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(mockStartPlanningStreaming).toHaveBeenCalledWith("Build auth system");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Should transition to question view via streaming
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(screen.getByText("What is the scope?")).toBeDefined();
|
expect(screen.getByText("What is the scope?")).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(mockStartPlanning).toHaveBeenCalledWith("Build auth system");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shows error message when planning fails", async () => {
|
it("shows error message when planning fails", async () => {
|
||||||
mockStartPlanning.mockRejectedValue(new Error("Rate limit exceeded"));
|
// Override the default mock to simulate an error
|
||||||
|
mockConnectPlanningStream.mockImplementationOnce((sessionId: string, handlers: any) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
handlers.onError?.("Rate limit exceeded");
|
||||||
|
}, 10);
|
||||||
|
|
||||||
|
return {
|
||||||
|
close: vi.fn(),
|
||||||
|
isConnected: vi.fn().mockReturnValue(true),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
render(
|
render(
|
||||||
<PlanningModeModal
|
<PlanningModeModal
|
||||||
@@ -274,12 +289,6 @@ describe("PlanningModeModal", () => {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
mockStartPlanning.mockResolvedValue({
|
|
||||||
sessionId: "session-123",
|
|
||||||
currentQuestion: mockQuestion,
|
|
||||||
summary: null,
|
|
||||||
});
|
|
||||||
|
|
||||||
const textarea = screen.getByPlaceholderText(/e.g., Build a user authentication/);
|
const textarea = screen.getByPlaceholderText(/e.g., Build a user authentication/);
|
||||||
fireEvent.change(textarea, { target: { value: "Build auth system" } });
|
fireEvent.change(textarea, { target: { value: "Build auth system" } });
|
||||||
fireEvent.click(screen.getByText("Start Planning"));
|
fireEvent.click(screen.getByText("Start Planning"));
|
||||||
@@ -297,10 +306,16 @@ describe("PlanningModeModal", () => {
|
|||||||
|
|
||||||
describe("Summary view", () => {
|
describe("Summary view", () => {
|
||||||
it("shows summary when planning is complete", async () => {
|
it("shows summary when planning is complete", async () => {
|
||||||
mockStartPlanning.mockResolvedValue({
|
// Override mock to return summary instead of question
|
||||||
sessionId: "session-123",
|
mockConnectPlanningStream.mockImplementationOnce((sessionId: string, handlers: any) => {
|
||||||
currentQuestion: null,
|
setTimeout(() => {
|
||||||
summary: mockSummary,
|
handlers.onSummary?.(mockSummary);
|
||||||
|
}, 10);
|
||||||
|
|
||||||
|
return {
|
||||||
|
close: vi.fn(),
|
||||||
|
isConnected: vi.fn().mockReturnValue(true),
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
@@ -339,10 +354,16 @@ describe("PlanningModeModal", () => {
|
|||||||
updatedAt: "2026-01-01T00:00:00.000Z",
|
updatedAt: "2026-01-01T00:00:00.000Z",
|
||||||
};
|
};
|
||||||
|
|
||||||
mockStartPlanning.mockResolvedValue({
|
// Override mock to return summary
|
||||||
sessionId: "session-123",
|
mockConnectPlanningStream.mockImplementationOnce((sessionId: string, handlers: any) => {
|
||||||
currentQuestion: null,
|
setTimeout(() => {
|
||||||
summary: mockSummary,
|
handlers.onSummary?.(mockSummary);
|
||||||
|
}, 10);
|
||||||
|
|
||||||
|
return {
|
||||||
|
close: vi.fn(),
|
||||||
|
isConnected: vi.fn().mockReturnValue(true),
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
mockCreateTaskFromPlanning.mockResolvedValue(createdTask);
|
mockCreateTaskFromPlanning.mockResolvedValue(createdTask);
|
||||||
|
|||||||
Reference in New Issue
Block a user