@@ -11,16 +11,6 @@ import { createMockChat } from '../test/utils';
1111import type { AssistantMessage } from './compass-assistant-provider' ;
1212
1313describe ( '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-
2414 const mockMessages : AssistantMessage [ ] = [
2515 {
2616 id : 'user' ,
@@ -41,8 +31,9 @@ describe('AssistantChat', function () {
4131
4232 function renderWithChat ( messages : AssistantMessage [ ] ) {
4333 const chat = createMockChat ( { messages } ) ;
34+ const result = render ( < AssistantChat chat = { chat } /> ) ;
4435 return {
45- result : render ( < AssistantChat chat = { chat } /> ) ,
36+ result,
4637 chat,
4738 } ;
4839 }
@@ -130,8 +121,9 @@ describe('AssistantChat', function () {
130121 ) ;
131122 } ) ;
132123
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 ;
135127 const inputField = screen . getByPlaceholderText (
136128 'Ask MongoDB Assistant a question'
137129 ) ;
@@ -142,6 +134,12 @@ describe('AssistantChat', function () {
142134
143135 expect ( chat . sendMessage . calledWith ( { text : 'What is aggregation?' } ) ) . to . be
144136 . 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+ } ) ;
145143 } ) ;
146144
147145 it ( 'clears input field after successful submission' , function ( ) {
@@ -159,8 +157,9 @@ describe('AssistantChat', function () {
159157 expect ( inputField . value ) . to . equal ( '' ) ;
160158 } ) ;
161159
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 ;
164163
165164 const inputField = screen . getByPlaceholderText (
166165 'Ask MongoDB Assistant a question'
@@ -171,6 +170,12 @@ describe('AssistantChat', function () {
171170
172171 expect ( chat . sendMessage . calledWith ( { text : 'What is sharding?' } ) ) . to . be
173172 . 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+ } ) ;
174179 } ) ;
175180
176181 it ( 'does not call sendMessage when input is empty or whitespace-only' , function ( ) {
@@ -271,4 +276,143 @@ describe('AssistantChat', function () {
271276 expect ( screen . queryByText ( 'Another part that should not display.' ) ) . to . not
272277 . exist ;
273278 } ) ;
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+ } ) ;
274418} ) ;
0 commit comments