| import { test, expect } from "@sand4rt/experimental-ct-web"; |
| import { MobileChat } from "./mobile-chat"; |
| import { AgentMessage } from "../types"; |
| |
| // Helper function to create mock messages |
| function createMockMessage(props: Partial<AgentMessage> = {}): AgentMessage { |
| return { |
| idx: props.idx || 0, |
| type: props.type || "agent", |
| content: props.content || "Hello world", |
| timestamp: props.timestamp || "2023-05-15T12:00:00Z", |
| elapsed: props.elapsed || 1500000000, // 1.5 seconds in nanoseconds |
| end_of_turn: props.end_of_turn || false, |
| conversation_id: props.conversation_id || "conv123", |
| ...props, |
| }; |
| } |
| |
| test("renders basic chat messages", async ({ mount }) => { |
| const messages = [ |
| createMockMessage({ |
| type: "user", |
| content: "Hello, this is a user message", |
| }), |
| createMockMessage({ |
| type: "agent", |
| content: "Hello, this is an agent response", |
| }), |
| ]; |
| |
| const component = await mount(MobileChat, { |
| props: { |
| messages: messages, |
| }, |
| }); |
| |
| await expect(component.locator(".message.user")).toBeVisible(); |
| await expect(component.locator(".message.assistant")).toBeVisible(); |
| await expect( |
| component.locator(".message.user .message-bubble"), |
| ).toContainText("Hello, this is a user message"); |
| await expect( |
| component.locator(".message.assistant .message-bubble"), |
| ).toContainText("Hello, this is an agent response"); |
| }); |
| |
| test("renders error messages with red styling", async ({ mount }) => { |
| const messages = [ |
| createMockMessage({ |
| type: "error", |
| content: "This is an error message", |
| }), |
| ]; |
| |
| const component = await mount(MobileChat, { |
| props: { |
| messages: messages, |
| }, |
| }); |
| |
| // Check that error message is visible |
| await expect(component.locator(".message.error")).toBeVisible(); |
| await expect( |
| component.locator(".message.error .message-bubble"), |
| ).toContainText("This is an error message"); |
| |
| // Check that error message has red styling |
| const errorBubble = component.locator(".message.error .message-bubble"); |
| await expect(errorBubble).toBeVisible(); |
| |
| // Verify the element has the correct CSS classes for red styling |
| const errorBubbleClasses = await errorBubble.getAttribute("class"); |
| expect(errorBubbleClasses).toContain("bg-red-50"); |
| expect(errorBubbleClasses).toContain("text-red-700"); |
| }); |
| |
| test("filters messages correctly", async ({ mount }) => { |
| const messages = [ |
| createMockMessage({ |
| type: "user", |
| content: "User message", |
| }), |
| createMockMessage({ |
| type: "agent", |
| content: "Agent message", |
| }), |
| createMockMessage({ |
| type: "error", |
| content: "Error message", |
| }), |
| createMockMessage({ |
| type: "tool", |
| content: "", // Empty content should be filtered out |
| }), |
| createMockMessage({ |
| type: "agent", |
| content: " ", // Whitespace-only content should be filtered out |
| }), |
| ]; |
| |
| const component = await mount(MobileChat, { |
| props: { |
| messages: messages, |
| }, |
| }); |
| |
| // Should show user, agent, and error messages with content |
| await expect(component.locator(".message.user")).toBeVisible(); |
| await expect(component.locator(".message.assistant")).toHaveCount(1); // Only one agent message with content |
| await expect(component.locator(".message.error")).toBeVisible(); |
| }); |
| |
| test("shows thinking indicator", async ({ mount }) => { |
| const component = await mount(MobileChat, { |
| props: { |
| messages: [], |
| isThinking: true, |
| }, |
| }); |
| |
| await expect(component.locator(".thinking-message")).toBeVisible(); |
| await expect(component.locator(".thinking-text")).toContainText( |
| "Sketch is thinking", |
| ); |
| await expect(component.locator(".thinking-dots")).toBeVisible(); |
| }); |
| |
| test("shows empty state when no messages", async ({ mount }) => { |
| const component = await mount(MobileChat, { |
| props: { |
| messages: [], |
| isThinking: false, |
| }, |
| }); |
| |
| await expect(component.locator(".empty-state")).toBeVisible(); |
| await expect(component.locator(".empty-state")).toContainText( |
| "Start a conversation with Sketch...", |
| ); |
| }); |
| |
| test("renders markdown content in assistant messages", async ({ mount }) => { |
| const messages = [ |
| createMockMessage({ |
| type: "agent", |
| content: "# Heading\n\n- List item 1\n- List item 2\n\n`code block`", |
| }), |
| ]; |
| |
| const component = await mount(MobileChat, { |
| props: { |
| messages: messages, |
| }, |
| }); |
| |
| await expect(component.locator(".markdown-content")).toBeVisible(); |
| |
| // Check that markdown is rendered as HTML |
| const html = await component |
| .locator(".markdown-content") |
| .evaluate((element) => element.innerHTML); |
| expect(html).toContain("<h1>"); |
| expect(html).toContain("<ul>"); |
| expect(html).toContain("<code>"); |
| }); |