feat(webui): polish agent output and app discovery
This commit is contained in:
@@ -511,13 +511,13 @@ describe("MessageBubble", () => {
|
||||
const video = screen.getByLabelText(/video attachment/i);
|
||||
expect(video.tagName).toBe("VIDEO");
|
||||
expect(video).toHaveAttribute("src", "/api/media/sig/payload");
|
||||
expect(video).toHaveAttribute("preload", "auto");
|
||||
expect(video).toHaveAttribute("preload", "metadata");
|
||||
expect(container.querySelector("video[controls]")).toBeInTheDocument();
|
||||
expect(screen.queryByText("Preview")).not.toBeInTheDocument();
|
||||
expect(screen.queryByText("Code")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("auto-expands the reasoning trace while streaming with a shimmer header", () => {
|
||||
it("renders streaming reasoning as one compact activity line", () => {
|
||||
const message: UIMessage = {
|
||||
id: "a-reasoning-streaming",
|
||||
role: "assistant",
|
||||
@@ -529,15 +529,19 @@ describe("MessageBubble", () => {
|
||||
|
||||
const { container } = render(<MessageBubble message={message} />);
|
||||
|
||||
expect(screen.getByText("Thinking…")).toBeInTheDocument();
|
||||
expect(screen.getByText(/Step 1: parse intent\./)).toBeInTheDocument();
|
||||
const preview = screen.getByText("Step 1: parse intent. Step 2: compute.");
|
||||
expect(preview).toBeInTheDocument();
|
||||
expect(container.querySelector(".reasoning-sheen-stripe")).not.toBeInTheDocument();
|
||||
expect(screen.getByText("Thinking…")).toHaveClass("streaming-text-sheen");
|
||||
expect(screen.getByText("Thinking…")).toHaveAttribute("data-sheen-text", "Thinking…");
|
||||
expect(screen.getByRole("button", { name: /thinking/i }).parentElement).not.toHaveClass("mb-2");
|
||||
expect(preview).toHaveClass("streaming-text-sheen");
|
||||
expect(preview).toHaveAttribute(
|
||||
"data-sheen-text",
|
||||
"Step 1: parse intent. Step 2: compute.",
|
||||
);
|
||||
expect(screen.queryByText("Thinking…")).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: /thinking/i })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("collapses the reasoning section by default once streaming ends", () => {
|
||||
it("keeps completed reasoning on one line above the answer", () => {
|
||||
const message: UIMessage = {
|
||||
id: "a-reasoning-done",
|
||||
role: "assistant",
|
||||
@@ -549,17 +553,15 @@ describe("MessageBubble", () => {
|
||||
|
||||
render(<MessageBubble message={message} />);
|
||||
|
||||
expect(screen.getByText("Thinking")).toBeInTheDocument();
|
||||
const preview = screen.getByText("hidden until expanded");
|
||||
expect(preview).toBeInTheDocument();
|
||||
expect(screen.getByText("The answer is 42.")).toBeInTheDocument();
|
||||
expect(screen.queryByText("hidden until expanded")).not.toBeInTheDocument();
|
||||
expect(screen.getByRole("button", { name: /thinking/i }).parentElement).toHaveClass("mb-2");
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: /thinking/i }));
|
||||
expect(screen.getByText("hidden until expanded")).toBeInTheDocument();
|
||||
expect(preview.closest('[data-testid="activity-step"]')).toHaveClass("mb-2");
|
||||
expect(screen.queryByText("Thinking")).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: /thinking/i })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders reasoning body as markdown so headings are not left as raw ###", async () => {
|
||||
await import("@/components/MarkdownTextRenderer");
|
||||
it("compacts reasoning markdown into plain single-line text", () => {
|
||||
const message: UIMessage = {
|
||||
id: "a-reasoning-md",
|
||||
role: "assistant",
|
||||
@@ -570,13 +572,10 @@ describe("MessageBubble", () => {
|
||||
};
|
||||
|
||||
const { container } = render(<MessageBubble message={message} />);
|
||||
fireEvent.click(screen.getByRole("button", { name: /thinking/i }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(container.querySelector("h3")?.textContent).toBe("Section title");
|
||||
});
|
||||
expect(screen.getByText("Section title Body line.")).toBeInTheDocument();
|
||||
expect(container.textContent).not.toContain("###");
|
||||
expect(screen.getByText("Body line.")).toBeInTheDocument();
|
||||
expect(container.querySelector("h3")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders inline file paths as compact file references", async () => {
|
||||
|
||||
Reference in New Issue
Block a user