feat(FN-4739): complete Step 6 — intercept room clear slash commands
Fusion-Task-Id: FN-4739 Fusion-Task-Lineage: fc120dfa-d1b2-4065-9595-d0bc6304d2af
This commit is contained in:
committed by
gsxdsm
parent
355aa6487c
commit
a5eba7dfdb
@@ -1678,6 +1678,16 @@ export function ChatView({ projectId, addToast, experimentalFeatures }: ChatView
|
||||
return;
|
||||
}
|
||||
|
||||
if (trimmed === "/clear" || trimmed === "/new") {
|
||||
clearComposerState();
|
||||
try {
|
||||
await rooms.clearRoom(rooms.activeRoom.id);
|
||||
} catch {
|
||||
addToast("Failed to clear room conversation", "error");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const previousInput = messageInput;
|
||||
clearComposerState();
|
||||
|
||||
@@ -1694,7 +1704,7 @@ export function ChatView({ projectId, addToast, experimentalFeatures }: ChatView
|
||||
}
|
||||
|
||||
handleSend();
|
||||
}, [messageInput, chatRoomsEnabled, chatScope, rooms, clearComposerState, addToast, handleSend]);
|
||||
}, [messageInput, chatRoomsEnabled, chatScope, rooms, rooms.clearRoom, clearComposerState, addToast, handleSend]);
|
||||
|
||||
const handleSkillSelect = useCallback(
|
||||
(skill: DiscoveredSkill) => {
|
||||
|
||||
@@ -90,6 +90,7 @@ const defaultRoomsState: UseChatRoomsResult = {
|
||||
createRoom: vi.fn(),
|
||||
deleteRoom: vi.fn(),
|
||||
sendRoomMessage: vi.fn(),
|
||||
clearRoom: vi.fn(),
|
||||
refreshRooms: vi.fn(),
|
||||
};
|
||||
|
||||
@@ -379,6 +380,69 @@ describe("ChatView — rooms (FN-3805..FN-3811 contract)", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("intercepts exact /clear in rooms scope and clears active room", async () => {
|
||||
const clearRoom = vi.fn().mockResolvedValue(undefined);
|
||||
const sendRoomMessage = vi.fn().mockResolvedValue(undefined);
|
||||
setup({}, { clearRoom, sendRoomMessage, activeRoom: roomA });
|
||||
|
||||
render(<ChatView projectId="proj-123" addToast={vi.fn()} experimentalFeatures={{ chatRooms: true }} />);
|
||||
|
||||
const textarea = screen.getByTestId("chat-input") as HTMLTextAreaElement;
|
||||
await userEvent.type(textarea, " /clear {enter}");
|
||||
|
||||
await waitFor(() => {
|
||||
expect(clearRoom).toHaveBeenCalledWith("room-a");
|
||||
});
|
||||
expect(sendRoomMessage).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("intercepts exact /new in rooms scope and clears active room", async () => {
|
||||
const clearRoom = vi.fn().mockResolvedValue(undefined);
|
||||
const sendRoomMessage = vi.fn().mockResolvedValue(undefined);
|
||||
setup({}, { clearRoom, sendRoomMessage, activeRoom: roomA });
|
||||
|
||||
render(<ChatView projectId="proj-123" addToast={vi.fn()} experimentalFeatures={{ chatRooms: true }} />);
|
||||
|
||||
const textarea = screen.getByTestId("chat-input") as HTMLTextAreaElement;
|
||||
await userEvent.type(textarea, " /new {enter}");
|
||||
|
||||
await waitFor(() => {
|
||||
expect(clearRoom).toHaveBeenCalledWith("room-a");
|
||||
});
|
||||
expect(sendRoomMessage).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not intercept /clear substring commands in rooms scope", async () => {
|
||||
const clearRoom = vi.fn().mockResolvedValue(undefined);
|
||||
const sendRoomMessage = vi.fn().mockResolvedValue(undefined);
|
||||
setup({}, { clearRoom, sendRoomMessage, activeRoom: roomA });
|
||||
|
||||
render(<ChatView projectId="proj-123" addToast={vi.fn()} experimentalFeatures={{ chatRooms: true }} />);
|
||||
|
||||
const textarea = screen.getByTestId("chat-input") as HTMLTextAreaElement;
|
||||
await userEvent.type(textarea, "/clear now{enter}");
|
||||
|
||||
await waitFor(() => {
|
||||
expect(sendRoomMessage).toHaveBeenCalledWith("/clear now");
|
||||
});
|
||||
expect(clearRoom).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("toasts error when room clear command fails", async () => {
|
||||
const addToast = vi.fn();
|
||||
const clearRoom = vi.fn().mockRejectedValue(new Error("clear failed"));
|
||||
setup({}, { clearRoom, activeRoom: roomA });
|
||||
|
||||
render(<ChatView projectId="proj-123" addToast={addToast} experimentalFeatures={{ chatRooms: true }} />);
|
||||
|
||||
const textarea = screen.getByTestId("chat-input") as HTMLTextAreaElement;
|
||||
await userEvent.type(textarea, "/clear{enter}");
|
||||
|
||||
await waitFor(() => {
|
||||
expect(addToast).toHaveBeenCalledWith("Failed to clear room conversation", "error");
|
||||
});
|
||||
});
|
||||
|
||||
it("supports delete-room confirm/cancel and rerenders messages from hook state", async () => {
|
||||
const deleteRoom = vi.fn().mockResolvedValue(undefined);
|
||||
const rerenderedRooms = {
|
||||
|
||||
Reference in New Issue
Block a user