blob: 1b57f03abf424ea84bf2fd4856b592cc302c23fb [file] [log] [blame]
philip.zeyliger41682632025-06-09 22:23:25 +00001import { test, expect } from "@sand4rt/experimental-ct-web";
2import { MobileChat } from "./mobile-chat";
3import { AgentMessage } from "../types";
4
5// Helper function to create mock messages
6function createMockMessage(props: Partial<AgentMessage> = {}): AgentMessage {
7 return {
8 idx: props.idx || 0,
9 type: props.type || "agent",
10 content: props.content || "Hello world",
11 timestamp: props.timestamp || "2023-05-15T12:00:00Z",
12 elapsed: props.elapsed || 1500000000, // 1.5 seconds in nanoseconds
13 end_of_turn: props.end_of_turn || false,
14 conversation_id: props.conversation_id || "conv123",
15 ...props,
16 };
17}
18
19test("renders basic chat messages", async ({ mount }) => {
20 const messages = [
21 createMockMessage({
22 type: "user",
23 content: "Hello, this is a user message",
24 }),
25 createMockMessage({
26 type: "agent",
27 content: "Hello, this is an agent response",
28 }),
29 ];
30
31 const component = await mount(MobileChat, {
32 props: {
33 messages: messages,
34 },
35 });
36
37 await expect(component.locator(".message.user")).toBeVisible();
38 await expect(component.locator(".message.assistant")).toBeVisible();
39 await expect(
40 component.locator(".message.user .message-bubble"),
41 ).toContainText("Hello, this is a user message");
42 await expect(
43 component.locator(".message.assistant .message-bubble"),
44 ).toContainText("Hello, this is an agent response");
45});
46
47test("renders error messages with red styling", async ({ mount }) => {
48 const messages = [
49 createMockMessage({
50 type: "error",
51 content: "This is an error message",
52 }),
53 ];
54
55 const component = await mount(MobileChat, {
56 props: {
57 messages: messages,
58 },
59 });
60
61 // Check that error message is visible
62 await expect(component.locator(".message.error")).toBeVisible();
63 await expect(
64 component.locator(".message.error .message-bubble"),
65 ).toContainText("This is an error message");
66
67 // Check that error message has red styling
68 const errorBubble = component.locator(".message.error .message-bubble");
69 await expect(errorBubble).toBeVisible();
70
banksean23a35b82025-07-20 21:18:31 +000071 // Verify the element has the correct CSS classes for red styling
72 const errorBubbleClasses = await errorBubble.getAttribute("class");
73 expect(errorBubbleClasses).toContain("bg-red-50");
74 expect(errorBubbleClasses).toContain("text-red-700");
philip.zeyliger41682632025-06-09 22:23:25 +000075});
76
77test("filters messages correctly", async ({ mount }) => {
78 const messages = [
79 createMockMessage({
80 type: "user",
81 content: "User message",
82 }),
83 createMockMessage({
84 type: "agent",
85 content: "Agent message",
86 }),
87 createMockMessage({
88 type: "error",
89 content: "Error message",
90 }),
91 createMockMessage({
92 type: "tool",
93 content: "", // Empty content should be filtered out
94 }),
95 createMockMessage({
96 type: "agent",
97 content: " ", // Whitespace-only content should be filtered out
98 }),
99 ];
100
101 const component = await mount(MobileChat, {
102 props: {
103 messages: messages,
104 },
105 });
106
107 // Should show user, agent, and error messages with content
108 await expect(component.locator(".message.user")).toBeVisible();
109 await expect(component.locator(".message.assistant")).toHaveCount(1); // Only one agent message with content
110 await expect(component.locator(".message.error")).toBeVisible();
111});
112
113test("shows thinking indicator", async ({ mount }) => {
114 const component = await mount(MobileChat, {
115 props: {
116 messages: [],
117 isThinking: true,
118 },
119 });
120
121 await expect(component.locator(".thinking-message")).toBeVisible();
122 await expect(component.locator(".thinking-text")).toContainText(
123 "Sketch is thinking",
124 );
125 await expect(component.locator(".thinking-dots")).toBeVisible();
126});
127
128test("shows empty state when no messages", async ({ mount }) => {
129 const component = await mount(MobileChat, {
130 props: {
131 messages: [],
132 isThinking: false,
133 },
134 });
135
136 await expect(component.locator(".empty-state")).toBeVisible();
137 await expect(component.locator(".empty-state")).toContainText(
138 "Start a conversation with Sketch...",
139 );
140});
141
142test("renders markdown content in assistant messages", async ({ mount }) => {
143 const messages = [
144 createMockMessage({
145 type: "agent",
146 content: "# Heading\n\n- List item 1\n- List item 2\n\n`code block`",
147 }),
148 ];
149
150 const component = await mount(MobileChat, {
151 props: {
152 messages: messages,
153 },
154 });
155
156 await expect(component.locator(".markdown-content")).toBeVisible();
157
158 // Check that markdown is rendered as HTML
159 const html = await component
160 .locator(".markdown-content")
161 .evaluate((element) => element.innerHTML);
162 expect(html).toContain("<h1>");
163 expect(html).toContain("<ul>");
164 expect(html).toContain("<code>");
165});