@@ -11,16 +11,6 @@ import { createMockChat } from '../test/utils';
11
11
import type { AssistantMessage } from './compass-assistant-provider' ;
12
12
13
13
describe ( 'AssistantChat' , function ( ) {
14
- let originalScrollTo : typeof Element . prototype . scrollTo ;
15
- // Mock scrollTo method for DOM elements to prevent test failures
16
- before ( function ( ) {
17
- originalScrollTo = Element . prototype . scrollTo . bind ( Element . prototype ) ;
18
- Element . prototype . scrollTo = ( ) => { } ;
19
- } ) ;
20
- after ( function ( ) {
21
- Element . prototype . scrollTo = originalScrollTo ;
22
- } ) ;
23
-
24
14
const mockMessages : AssistantMessage [ ] = [
25
15
{
26
16
id : 'user' ,
@@ -41,8 +31,9 @@ describe('AssistantChat', function () {
41
31
42
32
function renderWithChat ( messages : AssistantMessage [ ] ) {
43
33
const chat = createMockChat ( { messages } ) ;
34
+ const result = render ( < AssistantChat chat = { chat } /> ) ;
44
35
return {
45
- result : render ( < AssistantChat chat = { chat } /> ) ,
36
+ result,
46
37
chat,
47
38
} ;
48
39
}
@@ -130,8 +121,9 @@ describe('AssistantChat', function () {
130
121
) ;
131
122
} ) ;
132
123
133
- it ( 'calls sendMessage when form is submitted' , function ( ) {
134
- const { chat } = renderWithChat ( [ ] ) ;
124
+ it ( 'calls sendMessage when form is submitted' , async function ( ) {
125
+ const { chat, result } = renderWithChat ( [ ] ) ;
126
+ const { track } = result ;
135
127
const inputField = screen . getByPlaceholderText (
136
128
'Ask MongoDB Assistant a question'
137
129
) ;
@@ -142,6 +134,12 @@ describe('AssistantChat', function () {
142
134
143
135
expect ( chat . sendMessage . calledWith ( { text : 'What is aggregation?' } ) ) . to . be
144
136
. true ;
137
+
138
+ await waitFor ( ( ) => {
139
+ expect ( track ) . to . have . been . calledWith ( 'Assistant Prompt Submitted' , {
140
+ user_input_length : 'What is aggregation?' . length ,
141
+ } ) ;
142
+ } ) ;
145
143
} ) ;
146
144
147
145
it ( 'clears input field after successful submission' , function ( ) {
@@ -159,8 +157,9 @@ describe('AssistantChat', function () {
159
157
expect ( inputField . value ) . to . equal ( '' ) ;
160
158
} ) ;
161
159
162
- it ( 'trims whitespace from input before sending' , function ( ) {
163
- const { chat } = renderWithChat ( [ ] ) ;
160
+ it ( 'trims whitespace from input before sending' , async function ( ) {
161
+ const { chat, result } = renderWithChat ( [ ] ) ;
162
+ const { track } = result ;
164
163
165
164
const inputField = screen . getByPlaceholderText (
166
165
'Ask MongoDB Assistant a question'
@@ -171,6 +170,12 @@ describe('AssistantChat', function () {
171
170
172
171
expect ( chat . sendMessage . calledWith ( { text : 'What is sharding?' } ) ) . to . be
173
172
. true ;
173
+
174
+ await waitFor ( ( ) => {
175
+ expect ( track ) . to . have . been . calledWith ( 'Assistant Prompt Submitted' , {
176
+ user_input_length : 'What is sharding?' . length ,
177
+ } ) ;
178
+ } ) ;
174
179
} ) ;
175
180
176
181
it ( 'does not call sendMessage when input is empty or whitespace-only' , function ( ) {
@@ -271,4 +276,143 @@ describe('AssistantChat', function () {
271
276
expect ( screen . queryByText ( 'Another part that should not display.' ) ) . to . not
272
277
. exist ;
273
278
} ) ;
279
+
280
+ describe ( 'feedback buttons' , function ( ) {
281
+ it ( 'shows feedback buttons only for assistant messages' , function ( ) {
282
+ renderWithChat ( mockMessages ) ;
283
+
284
+ const userMessage = screen . getByTestId ( 'assistant-message-user' ) ;
285
+ const assistantMessage = screen . getByTestId (
286
+ 'assistant-message-assistant'
287
+ ) ;
288
+
289
+ // User messages should not have feedback buttons
290
+ expect ( userMessage . querySelector ( '[aria-label="Thumbs Up Icon"]' ) ) . to . not
291
+ . exist ;
292
+ expect ( userMessage . querySelector ( '[aria-label="Thumbs Down Icon"]' ) ) . to
293
+ . not . exist ;
294
+
295
+ // Assistant messages should have feedback buttons
296
+ expect ( assistantMessage . querySelector ( '[aria-label="Thumbs Up Icon"]' ) ) . to
297
+ . exist ;
298
+ expect ( assistantMessage . querySelector ( '[aria-label="Thumbs Down Icon"]' ) )
299
+ . to . exist ;
300
+ } ) ;
301
+
302
+ it ( 'tracks positive feedback when thumbs up is clicked' , async function ( ) {
303
+ const { result } = renderWithChat ( mockMessages ) ;
304
+ const { track } = result ;
305
+
306
+ const assistantMessage = screen . getByTestId (
307
+ 'assistant-message-assistant'
308
+ ) ;
309
+
310
+ // Find and click the thumbs up button
311
+ const thumbsUpButton = assistantMessage . querySelector (
312
+ '[aria-label="Thumbs Up Icon"]'
313
+ ) as HTMLElement ;
314
+
315
+ userEvent . click ( thumbsUpButton ) ;
316
+
317
+ await waitFor ( ( ) => {
318
+ expect ( track ) . to . have . callCount ( 1 ) ;
319
+ expect ( track ) . to . have . been . calledWith ( 'Assistant Feedback Submitted' , {
320
+ feedback : 'positive' ,
321
+ text : undefined ,
322
+ request_id : null ,
323
+ } ) ;
324
+ } ) ;
325
+ } ) ;
326
+
327
+ it ( 'tracks negative feedback when thumbs down is clicked' , async function ( ) {
328
+ const { result } = renderWithChat ( mockMessages ) ;
329
+ const { track } = result ;
330
+
331
+ const assistantMessage = screen . getByTestId (
332
+ 'assistant-message-assistant'
333
+ ) ;
334
+
335
+ // Find and click the thumbs down button
336
+ const thumbsDownButton = assistantMessage . querySelector (
337
+ '[aria-label="Thumbs Down Icon"]'
338
+ ) as HTMLElement ;
339
+
340
+ userEvent . click ( thumbsDownButton ) ;
341
+
342
+ await waitFor ( ( ) => {
343
+ expect ( track ) . to . have . callCount ( 1 ) ;
344
+
345
+ expect ( track ) . to . have . been . calledWith ( 'Assistant Feedback Submitted' , {
346
+ feedback : 'negative' ,
347
+ text : undefined ,
348
+ request_id : null ,
349
+ } ) ;
350
+ } ) ;
351
+ } ) ;
352
+
353
+ it ( 'tracks detailed feedback when feedback text is submitted' , async function ( ) {
354
+ const { result } = renderWithChat ( mockMessages ) ;
355
+ const { track } = result ;
356
+
357
+ const assistantMessage = screen . getByTestId (
358
+ 'assistant-message-assistant'
359
+ ) ;
360
+
361
+ // First click thumbs down to potentially open feedback form
362
+ const thumbsDownButton = assistantMessage . querySelector (
363
+ '[aria-label="Thumbs Down Icon"]'
364
+ ) as HTMLElement ;
365
+
366
+ userEvent . click ( thumbsDownButton ) ;
367
+
368
+ // Look for feedback text area (the exact implementation depends on LeafyGreen)
369
+ const feedbackTextArea = screen . getByTestId (
370
+ 'lg-chat-message_actions-feedback_textarea'
371
+ ) ;
372
+
373
+ userEvent . type ( feedbackTextArea , 'This response was not helpful' ) ;
374
+
375
+ // Look for submit button
376
+ const submitButton = screen . getByText ( 'Submit' ) ;
377
+
378
+ userEvent . click ( submitButton ) ;
379
+
380
+ await waitFor ( ( ) => {
381
+ expect ( track ) . to . have . callCount ( 2 ) ;
382
+
383
+ expect ( track ) . to . have . been . calledWith ( 'Assistant Feedback Submitted' , {
384
+ feedback : 'negative' ,
385
+ text : undefined ,
386
+ request_id : null ,
387
+ } ) ;
388
+
389
+ expect ( track ) . to . have . been . calledWith ( 'Assistant Feedback Submitted' , {
390
+ feedback : 'negative' ,
391
+ text : 'This response was not helpful' ,
392
+ request_id : null ,
393
+ } ) ;
394
+ } ) ;
395
+ } ) ;
396
+
397
+ it ( 'does not show feedback buttons when there are no assistant messages' , function ( ) {
398
+ const userOnlyMessages : AssistantMessage [ ] = [
399
+ {
400
+ id : 'user1' ,
401
+ role : 'user' ,
402
+ parts : [ { type : 'text' , text : 'Hello!' } ] ,
403
+ } ,
404
+ {
405
+ id : 'user2' ,
406
+ role : 'user' ,
407
+ parts : [ { type : 'text' , text : 'How are you?' } ] ,
408
+ } ,
409
+ ] ;
410
+
411
+ renderWithChat ( userOnlyMessages ) ;
412
+
413
+ // Should not find any feedback buttons in the entire component
414
+ expect ( screen . queryByLabelText ( 'Thumbs Up Icon' ) ) . to . not . exist ;
415
+ expect ( screen . queryByLabelText ( 'Thumbs Down Icon' ) ) . to . not . exist ;
416
+ } ) ;
417
+ } ) ;
274
418
} ) ;
0 commit comments