Files
nanobot/webui/src/tests/message-bubble.test.tsx
T

68 lines
2.1 KiB
TypeScript
Raw Normal View History

import { fireEvent, render, screen } from "@testing-library/react";
import { describe, expect, it } from "vitest";
import { MessageBubble } from "@/components/MessageBubble";
import type { UIMessage } from "@/lib/types";
describe("MessageBubble", () => {
it("renders user messages as right-aligned pills", () => {
const message: UIMessage = {
id: "u1",
role: "user",
content: "hello",
createdAt: Date.now(),
};
const { container } = render(<MessageBubble message={message} />);
const row = container.firstElementChild;
const pill = screen.getByText("hello");
expect(row).toHaveClass("ml-auto", "flex");
expect(pill).toHaveClass("ml-auto", "w-fit", "rounded-[18px]");
});
it("renders trace messages as collapsible tool groups", () => {
const message: UIMessage = {
id: "t1",
role: "tool",
kind: "trace",
content: 'search "hk weather"',
traces: ['weather("get")', 'search "hk weather"'],
createdAt: Date.now(),
};
render(<MessageBubble message={message} />);
const toggle = screen.getByRole("button", { name: /used 2 tools/i });
expect(screen.getByText('weather("get")')).toBeInTheDocument();
expect(screen.getByText('search "hk weather"')).toBeInTheDocument();
fireEvent.click(toggle);
expect(screen.queryByText('weather("get")')).not.toBeInTheDocument();
});
2026-04-24 19:17:58 +00:00
it("renders video media as an inline player", () => {
const message: UIMessage = {
id: "a1",
role: "assistant",
content: "here is the clip",
createdAt: Date.now(),
media: [
{
kind: "video",
url: "/api/media/sig/payload",
name: "demo.mp4",
},
],
};
const { container } = render(<MessageBubble message={message} />);
expect(screen.getByText("here is the clip")).toBeInTheDocument();
const video = screen.getByLabelText(/video attachment/i);
expect(video.tagName).toBe("VIDEO");
expect(video).toHaveAttribute("src", "/api/media/sig/payload");
expect(container.querySelector("video[controls]")).toBeInTheDocument();
});
});