diff --git a/ui/src/components/ChatAgentSelector.test.tsx b/ui/src/components/ChatAgentSelector.test.tsx new file mode 100644 index 00000000..bde7fc2c --- /dev/null +++ b/ui/src/components/ChatAgentSelector.test.tsx @@ -0,0 +1,9 @@ +import { describe, it } from "vitest"; + +describe("ChatAgentSelector", () => { + it.todo("renders active agent icon and name when agentId is set"); + it.todo("renders 'Select agent' placeholder when no agent selected"); + it.todo("lists all workspace agents in dropdown"); + it.todo("calls onAgentChange with new agentId on selection"); + it.todo("shows 'No agents configured' when agent list is empty"); +}); diff --git a/ui/src/components/ChatMentionPopover.test.tsx b/ui/src/components/ChatMentionPopover.test.tsx new file mode 100644 index 00000000..c1956822 --- /dev/null +++ b/ui/src/components/ChatMentionPopover.test.tsx @@ -0,0 +1,8 @@ +import { describe, it } from "vitest"; + +describe("ChatMentionPopover", () => { + it.todo("renders agent list filtered by query string"); + it.todo("shows agent icon, name, and role for each item"); + it.todo("calls onSelect with @agentName on item click"); + it.todo("shows 'No agents found' when filter matches nothing"); +}); diff --git a/ui/src/components/ChatMessage.test.tsx b/ui/src/components/ChatMessage.test.tsx new file mode 100644 index 00000000..2251af72 --- /dev/null +++ b/ui/src/components/ChatMessage.test.tsx @@ -0,0 +1,12 @@ +import { describe, it } from "vitest"; + +describe("ChatMessage", () => { + it.todo("renders user message as right-aligned bubble with plain text"); + it.todo("renders assistant message with ChatMarkdownMessage"); + it.todo("renders ChatMessageIdentityBar for assistant messages when agentName is provided"); + it.todo("shows edit pencil on hover for user messages"); + it.todo("shows retry button on hover for assistant messages"); + it.todo("hides retry button when isStreaming is true"); + it.todo("switches to inline edit textarea on pencil click"); + it.todo("renders ChatStreamingCursor when isStreaming is true"); +}); diff --git a/ui/src/components/ChatMessageIdentityBar.test.tsx b/ui/src/components/ChatMessageIdentityBar.test.tsx new file mode 100644 index 00000000..de028bd6 --- /dev/null +++ b/ui/src/components/ChatMessageIdentityBar.test.tsx @@ -0,0 +1,8 @@ +import { describe, it } from "vitest"; + +describe("ChatMessageIdentityBar", () => { + it.todo("renders agent icon at 16x16px"); + it.todo("renders agent name in semibold text"); + it.todo("renders timestamp in muted text"); + it.todo("applies role-specific color from agentRoleColors"); +}); diff --git a/ui/src/components/ChatMessageList.test.tsx b/ui/src/components/ChatMessageList.test.tsx new file mode 100644 index 00000000..71ad87ff --- /dev/null +++ b/ui/src/components/ChatMessageList.test.tsx @@ -0,0 +1,9 @@ +import { describe, it } from "vitest"; + +describe("ChatMessageList", () => { + it.todo("renders messages using virtualizer"); + it.todo("auto-scrolls to bottom when new messages arrive"); + it.todo("shows loading skeleton when isLoading"); + it.todo("shows empty state when no messages"); + it.todo("appends streaming message as synthetic entry"); +}); diff --git a/ui/src/components/ChatSlashCommandPopover.test.tsx b/ui/src/components/ChatSlashCommandPopover.test.tsx new file mode 100644 index 00000000..a469d652 --- /dev/null +++ b/ui/src/components/ChatSlashCommandPopover.test.tsx @@ -0,0 +1,9 @@ +import { describe, it } from "vitest"; + +describe("ChatSlashCommandPopover", () => { + it.todo("renders 5 slash command items when open"); + it.todo("filters commands by typed query"); + it.todo("calls onSelect with command string on item click"); + it.todo("closes on Escape key"); + it.todo("shows /search as greyed out with 'Coming soon' suffix"); +}); diff --git a/ui/src/hooks/useStreamingChat.test.ts b/ui/src/hooks/useStreamingChat.test.ts new file mode 100644 index 00000000..26f770b5 --- /dev/null +++ b/ui/src/hooks/useStreamingChat.test.ts @@ -0,0 +1,9 @@ +import { describe, it } from "vitest"; + +describe("useStreamingChat", () => { + it.todo("accumulates tokens from SSE data events into streamingContent"); + it.todo("sets isStreaming=true when stream starts, false when done"); + it.todo("clears streamingContent and invalidates query cache on done event"); + it.todo("stop() closes the EventSource and sets isStreaming=false"); + it.todo("handles SSE error event by closing connection"); +});