blob: 54ddf2e578cc98ed913a6614cfabe0867878f441 [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
71 // Verify the background color and text color
72 const bgColor = await errorBubble.evaluate((el) => {
73 return window.getComputedStyle(el).backgroundColor;
74 });
75 const textColor = await errorBubble.evaluate((el) => {
76 return window.getComputedStyle(el).color;
77 });
78
79 // Check that we have red-ish colors (these will be RGB values)
80 expect(bgColor).toMatch(/rgb\(255, 235, 238\)/); // #ffebee
81 expect(textColor).toMatch(/rgb\(211, 47, 47\)/); // #d32f2f
82});
83
84test("filters messages correctly", async ({ mount }) => {
85 const messages = [
86 createMockMessage({
87 type: "user",
88 content: "User message",
89 }),
90 createMockMessage({
91 type: "agent",
92 content: "Agent message",
93 }),
94 createMockMessage({
95 type: "error",
96 content: "Error message",
97 }),
98 createMockMessage({
99 type: "tool",
100 content: "", // Empty content should be filtered out
101 }),
102 createMockMessage({
103 type: "agent",
104 content: " ", // Whitespace-only content should be filtered out
105 }),
106 ];
107
108 const component = await mount(MobileChat, {
109 props: {
110 messages: messages,
111 },
112 });
113
114 // Should show user, agent, and error messages with content
115 await expect(component.locator(".message.user")).toBeVisible();
116 await expect(component.locator(".message.assistant")).toHaveCount(1); // Only one agent message with content
117 await expect(component.locator(".message.error")).toBeVisible();
118});
119
120test("shows thinking indicator", async ({ mount }) => {
121 const component = await mount(MobileChat, {
122 props: {
123 messages: [],
124 isThinking: true,
125 },
126 });
127
128 await expect(component.locator(".thinking-message")).toBeVisible();
129 await expect(component.locator(".thinking-text")).toContainText(
130 "Sketch is thinking",
131 );
132 await expect(component.locator(".thinking-dots")).toBeVisible();
133});
134
135test("shows empty state when no messages", async ({ mount }) => {
136 const component = await mount(MobileChat, {
137 props: {
138 messages: [],
139 isThinking: false,
140 },
141 });
142
143 await expect(component.locator(".empty-state")).toBeVisible();
144 await expect(component.locator(".empty-state")).toContainText(
145 "Start a conversation with Sketch...",
146 );
147});
148
149test("renders markdown content in assistant messages", async ({ mount }) => {
150 const messages = [
151 createMockMessage({
152 type: "agent",
153 content: "# Heading\n\n- List item 1\n- List item 2\n\n`code block`",
154 }),
155 ];
156
157 const component = await mount(MobileChat, {
158 props: {
159 messages: messages,
160 },
161 });
162
163 await expect(component.locator(".markdown-content")).toBeVisible();
164
165 // Check that markdown is rendered as HTML
166 const html = await component
167 .locator(".markdown-content")
168 .evaluate((element) => element.innerHTML);
169 expect(html).toContain("<h1>");
170 expect(html).toContain("<ul>");
171 expect(html).toContain("<code>");
172});