fix(FN-XXX): show planning-created tasks without refresh

This commit is contained in:
gsxdsm
2026-04-29 15:25:06 -07:00
parent 2febbc9d3a
commit fb309e5eea
6 changed files with 153 additions and 27 deletions

View File

@@ -23,6 +23,7 @@ const CREATED_TASK: Task = {
function createOptions(overrides: Partial<Parameters<typeof useTaskHandlers>[0]> = {}): Parameters<typeof useTaskHandlers>[0] {
return {
createTask: vi.fn().mockResolvedValue(CREATED_TASK),
ingestCreatedTasks: vi.fn(),
onPlanningTaskCreated: vi.fn(),
onPlanningTasksCreated: vi.fn(),
onSubtaskTasksCreated: vi.fn(),
@@ -71,6 +72,7 @@ describe("useTaskHandlers", () => {
result.current.handlePlanningTaskCreated(CREATED_TASK);
});
expect(options.ingestCreatedTasks).toHaveBeenCalledWith([CREATED_TASK]);
expect(options.onPlanningTaskCreated).toHaveBeenCalledWith(CREATED_TASK, options.addToast);
});
@@ -82,6 +84,7 @@ describe("useTaskHandlers", () => {
result.current.handlePlanningTasksCreated([CREATED_TASK]);
});
expect(options.ingestCreatedTasks).toHaveBeenCalledWith([CREATED_TASK]);
expect(options.onPlanningTasksCreated).toHaveBeenCalledWith([CREATED_TASK], options.addToast);
});
@@ -93,6 +96,7 @@ describe("useTaskHandlers", () => {
result.current.handleSubtaskTasksCreated([CREATED_TASK]);
});
expect(options.ingestCreatedTasks).toHaveBeenCalledWith([CREATED_TASK]);
expect(options.onSubtaskTasksCreated).toHaveBeenCalledWith([CREATED_TASK], options.addToast);
});

View File

@@ -996,6 +996,60 @@ describe("useTasks", () => {
});
});
describe("ingestCreatedTasks", () => {
it("adds planning-created tasks to local state immediately", async () => {
mockFetchTasks.mockResolvedValueOnce([]);
const createdTask = createMockTask({ id: "FN-020", column: "triage" });
const { result } = renderHook(() => useTasks());
await waitFor(() => {
expect(MockEventSource.instances).toHaveLength(1);
});
act(() => {
result.current.ingestCreatedTasks([createdTask]);
});
expect(result.current.tasks).toHaveLength(1);
expect(result.current.tasks[0]?.id).toBe("FN-020");
});
it("does not overwrite fresher task data when SSE already updated the task", async () => {
mockFetchTasks.mockResolvedValueOnce([]);
const createdTask = createMockTask({
id: "FN-021",
updatedAt: "2026-01-01T00:00:00Z",
});
const refreshedTask = createMockTask({
id: "FN-021",
updatedAt: "2026-01-02T00:00:00Z",
size: "L",
});
const { result } = renderHook(() => useTasks());
await waitFor(() => {
expect(MockEventSource.instances).toHaveLength(1);
});
act(() => {
MockEventSource.instances[0]._emit("task:created", refreshedTask);
});
act(() => {
result.current.ingestCreatedTasks([createdTask]);
});
expect(result.current.tasks).toHaveLength(1);
expect(result.current.tasks[0]).toMatchObject({
id: "FN-021",
updatedAt: "2026-01-02T00:00:00Z",
size: "L",
});
});
});
describe("duplicateTask optimistic insertion", () => {
it("adds task to state immediately", async () => {
const original = createMockTask({ id: "FN-001", column: "todo" as Column });