blob: 532ccf41add0da8bcad53012b1582aaa39641afe [file] [log] [blame]
Sean McCulloughb29f8912025-04-20 15:39:11 -07001import { test, expect } from "@sand4rt/experimental-ct-web";
Sean McCullough86b56862025-04-18 13:04:03 -07002import { SketchChatInput } from "./sketch-chat-input";
3
Sean McCulloughb29f8912025-04-20 15:39:11 -07004test("initializes with empty content by default", async ({ mount }) => {
5 const component = await mount(SketchChatInput, {});
6
7 // Check public property via component's evaluate method
8 const content = await component.evaluate((el: SketchChatInput) => el.content);
9 expect(content).toBe("");
10
11 // Check textarea value
12 await expect(component.locator("#chatInput")).toHaveValue("");
13});
14
15test("initializes with provided content", async ({ mount }) => {
16 const testContent = "Hello, world!";
17 const component = await mount(SketchChatInput, {
18 props: {
19 content: testContent,
20 },
Sean McCullough86b56862025-04-18 13:04:03 -070021 });
22
Sean McCulloughb29f8912025-04-20 15:39:11 -070023 // Check public property via component's evaluate method
24 const content = await component.evaluate((el: SketchChatInput) => el.content);
25 expect(content).toBe(testContent);
Sean McCullough86b56862025-04-18 13:04:03 -070026
Sean McCulloughb29f8912025-04-20 15:39:11 -070027 // Check textarea value
28 await expect(component.locator("#chatInput")).toHaveValue(testContent);
29});
30
31test("updates content when typing in the textarea", async ({ mount }) => {
32 const component = await mount(SketchChatInput, {});
33 const newValue = "New message";
34
35 // Fill the textarea with new content
36 await component.locator("#chatInput").fill(newValue);
37
38 // Check that the content property was updated
39 const content = await component.evaluate((el: SketchChatInput) => el.content);
40 expect(content).toBe(newValue);
41});
42
43test("sends message when clicking the send button", async ({ mount }) => {
44 const testContent = "Test message";
45 const component = await mount(SketchChatInput, {
46 props: {
47 content: testContent,
48 },
Sean McCullough86b56862025-04-18 13:04:03 -070049 });
50
Sean McCulloughb29f8912025-04-20 15:39:11 -070051 // Set up promise to wait for the event
52 const eventPromise = component.evaluate((el) => {
53 return new Promise((resolve) => {
54 el.addEventListener(
55 "send-chat",
56 (event) => {
57 resolve((event as CustomEvent).detail);
58 },
Philip Zeyliger72682df2025-04-23 13:09:46 -070059 { once: true },
Sean McCulloughb29f8912025-04-20 15:39:11 -070060 );
Sean McCullough86b56862025-04-18 13:04:03 -070061 });
Sean McCullough86b56862025-04-18 13:04:03 -070062 });
63
Sean McCulloughb29f8912025-04-20 15:39:11 -070064 // Click the send button
65 await component.locator("#sendChatButton").click();
Sean McCullough86b56862025-04-18 13:04:03 -070066
Sean McCulloughb29f8912025-04-20 15:39:11 -070067 // Wait for the event and check its details
68 const detail: any = await eventPromise;
69 expect(detail.message).toBe(testContent);
Sean McCulloughb29f8912025-04-20 15:39:11 -070070});
71
72test.skip("sends message when pressing Enter (without shift)", async ({
73 mount,
74}) => {
75 const testContent = "Test message";
76 const component = await mount(SketchChatInput, {
77 props: {
78 content: testContent,
79 },
80 });
81
82 // Set up promise to wait for the event
83 const eventPromise = component.evaluate((el) => {
84 return new Promise((resolve) => {
85 el.addEventListener(
86 "send-chat",
87 (event) => {
88 resolve((event as CustomEvent).detail);
89 },
Philip Zeyliger72682df2025-04-23 13:09:46 -070090 { once: true },
Sean McCulloughb29f8912025-04-20 15:39:11 -070091 );
92 });
93 });
94
95 // Press Enter in the textarea
96 await component.locator("#chatInput").press("Enter");
97
98 // Wait for the event and check its details
99 const detail: any = await eventPromise;
100 expect(detail.message).toBe(testContent);
101
102 // Check that content was cleared
103 const content = await component.evaluate((el: SketchChatInput) => el.content);
104 expect(content).toBe("");
105});
106
107test.skip("does not send message when pressing Shift+Enter", async ({
108 mount,
109}) => {
110 const testContent = "Test message";
111 const component = await mount(SketchChatInput, {
112 props: {
113 content: testContent,
114 },
115 });
116
117 // Set up to track if event fires
118 let eventFired = false;
119 await component.evaluate((el) => {
Sean McCullough86b56862025-04-18 13:04:03 -0700120 el.addEventListener("send-chat", () => {
Sean McCulloughb29f8912025-04-20 15:39:11 -0700121 (window as any).__eventFired = true;
Sean McCullough86b56862025-04-18 13:04:03 -0700122 });
Sean McCulloughb29f8912025-04-20 15:39:11 -0700123 (window as any).__eventFired = false;
Sean McCullough86b56862025-04-18 13:04:03 -0700124 });
125
Sean McCulloughb29f8912025-04-20 15:39:11 -0700126 // Press Shift+Enter in the textarea
127 await component.locator("#chatInput").press("Shift+Enter");
Sean McCullough86b56862025-04-18 13:04:03 -0700128
Sean McCulloughb29f8912025-04-20 15:39:11 -0700129 // Wait a short time and check if event fired
130 await new Promise((resolve) => setTimeout(resolve, 50));
131 eventFired = await component.evaluate(() => (window as any).__eventFired);
132 expect(eventFired).toBe(false);
Sean McCullough71941bd2025-04-18 13:31:48 -0700133
Sean McCulloughb29f8912025-04-20 15:39:11 -0700134 // Check that content was not cleared
135 const content = await component.evaluate((el: SketchChatInput) => el.content);
136 expect(content).toBe(testContent);
137});
138
Sean McCullough5164eee2025-04-21 18:20:23 -0700139test("resizes when user enters more text than will fit", async ({ mount }) => {
Sean McCullough07b3e392025-04-21 22:51:14 +0000140 const testContent = "Test message\n\n\n\n\n\n\n\n\n\n\n\n\nends here.";
141 const component = await mount(SketchChatInput, {
142 props: {
Sean McCullough5164eee2025-04-21 18:20:23 -0700143 content: "",
Sean McCullough07b3e392025-04-21 22:51:14 +0000144 },
145 });
Sean McCullough5164eee2025-04-21 18:20:23 -0700146 const origHeight = await component.evaluate(
Philip Zeyliger72682df2025-04-23 13:09:46 -0700147 (el: SketchChatInput) => el.chatInput.style.height,
Sean McCullough5164eee2025-04-21 18:20:23 -0700148 );
Sean McCullough07b3e392025-04-21 22:51:14 +0000149
150 // Enter very tall text in the textarea
151 await component.locator("#chatInput").fill(testContent);
152
Philip Zeyliger10a7ac12025-04-23 11:56:03 -0700153 // Wait for the requestAnimationFrame to complete
154 await component.evaluate(() => new Promise(requestAnimationFrame));
155
Sean McCullough07b3e392025-04-21 22:51:14 +0000156 // Check that textarea resized
Sean McCullough5164eee2025-04-21 18:20:23 -0700157 const newHeight = await component.evaluate(
Philip Zeyliger72682df2025-04-23 13:09:46 -0700158 (el: SketchChatInput) => el.chatInput.style.height,
Sean McCullough5164eee2025-04-21 18:20:23 -0700159 );
160 expect(Number.parseInt(newHeight)).toBeGreaterThan(
Philip Zeyliger72682df2025-04-23 13:09:46 -0700161 Number.parseInt(origHeight),
Sean McCullough5164eee2025-04-21 18:20:23 -0700162 );
Sean McCullough07b3e392025-04-21 22:51:14 +0000163});
Pokey Rule339b56e2025-05-15 14:48:07 +0000164
165test("shows drop overlay when file is dragged over", async ({ mount }) => {
166 const component = await mount(SketchChatInput, {});
167
168 // Simulate dragenter event
169 await component.evaluate((el: SketchChatInput) => {
Sean McCulloughb3795922025-06-27 01:59:41 +0000170 const container = el.querySelector(".chat-container");
Pokey Rule339b56e2025-05-15 14:48:07 +0000171 if (container) {
172 const event = new DragEvent("dragenter", { bubbles: true });
173 container.dispatchEvent(event);
174 }
175 });
176
177 // Check that the isDraggingOver state is true
178 const isDraggingOver = await component.evaluate(
179 (el: SketchChatInput) => el.isDraggingOver,
180 );
181 expect(isDraggingOver).toBe(true);
182
183 // Check that the drop zone overlay is visible
184 const overlay = await component.evaluate(
Sean McCulloughb3795922025-06-27 01:59:41 +0000185 (el: SketchChatInput) => el.querySelector(".drop-zone-overlay") !== null,
Pokey Rule339b56e2025-05-15 14:48:07 +0000186 );
187 expect(overlay).toBe(true);
188});
189
190test("hides drop overlay when drag leaves", async ({ mount }) => {
191 const component = await mount(SketchChatInput, {});
192
193 // First set isDraggingOver to true
194 await component.evaluate((el: SketchChatInput) => {
195 el.isDraggingOver = true;
196 });
197
198 // Simulate dragleave event
199 await component.evaluate((el: SketchChatInput) => {
Sean McCulloughb3795922025-06-27 01:59:41 +0000200 const container = el.querySelector(".chat-container");
Pokey Rule339b56e2025-05-15 14:48:07 +0000201 if (container) {
202 const event = new DragEvent("dragleave", { bubbles: true });
203 Object.defineProperty(event, "target", { value: container });
204 container.dispatchEvent(event);
205 }
206 });
207
208 // Check that the isDraggingOver state is false
209 const isDraggingOver = await component.evaluate(
210 (el: SketchChatInput) => el.isDraggingOver,
211 );
212 expect(isDraggingOver).toBe(false);
213});
214
215// Note: Testing actual file drop and upload would require mocking the fetch API
216// This is a simple test that the drop event handler exists
217test("has a drop event handler", async ({ mount }) => {
218 const component = await mount(SketchChatInput, {});
219
220 // Check that the component has the _handleDrop method
221 const hasDropHandler = await component.evaluate(
222 (el: SketchChatInput) => typeof (el as any)._handleDrop === "function",
223 );
224 expect(hasDropHandler).toBe(true);
225});