@@ -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 }
@@ -131,8 +122,9 @@ describe('AssistantChat', function () {
131122 ) ;
132123 } ) ;
133124
134- it ( 'calls sendMessage when form is submitted' , function ( ) {
135- const { chat } = renderWithChat ( [ ] ) ;
125+ it ( 'calls sendMessage when form is submitted' , async function ( ) {
126+ const { chat, result } = renderWithChat ( [ ] ) ;
127+ const { track } = result ;
136128 const inputField = screen . getByPlaceholderText (
137129 'Ask MongoDB Assistant a question'
138130 ) ;
@@ -143,6 +135,12 @@ describe('AssistantChat', function () {
143135
144136 expect ( chat . sendMessage . calledWith ( { text : 'What is aggregation?' } ) ) . to . be
145137 . true ;
138+
139+ await waitFor ( ( ) => {
140+ expect ( track ) . to . have . been . calledWith ( 'Assistant Prompt Submitted' , {
141+ user_input_length : 'What is aggregation?' . length ,
142+ } ) ;
143+ } ) ;
146144 } ) ;
147145
148146 it ( 'clears input field after successful submission' , function ( ) {
@@ -160,8 +158,9 @@ describe('AssistantChat', function () {
160158 expect ( inputField . value ) . to . equal ( '' ) ;
161159 } ) ;
162160
163- it ( 'trims whitespace from input before sending' , function ( ) {
164- const { chat } = renderWithChat ( [ ] ) ;
161+ it ( 'trims whitespace from input before sending' , async function ( ) {
162+ const { chat, result } = renderWithChat ( [ ] ) ;
163+ const { track } = result ;
165164
166165 const inputField = screen . getByPlaceholderText (
167166 'Ask MongoDB Assistant a question'
@@ -172,6 +171,12 @@ describe('AssistantChat', function () {
172171
173172 expect ( chat . sendMessage . calledWith ( { text : 'What is sharding?' } ) ) . to . be
174173 . true ;
174+
175+ await waitFor ( ( ) => {
176+ expect ( track ) . to . have . been . calledWith ( 'Assistant Prompt Submitted' , {
177+ user_input_length : 'What is sharding?' . length ,
178+ } ) ;
179+ } ) ;
175180 } ) ;
176181
177182 it ( 'does not call sendMessage when input is empty or whitespace-only' , function ( ) {
@@ -272,4 +277,143 @@ describe('AssistantChat', function () {
272277 expect ( screen . queryByText ( 'Another part that should not display.' ) ) . to . not
273278 . exist ;
274279 } ) ;
280+
281+ describe ( 'feedback buttons' , function ( ) {
282+ it ( 'shows feedback buttons only for assistant messages' , function ( ) {
283+ renderWithChat ( mockMessages ) ;
284+
285+ const userMessage = screen . getByTestId ( 'assistant-message-user' ) ;
286+ const assistantMessage = screen . getByTestId (
287+ 'assistant-message-assistant'
288+ ) ;
289+
290+ // User messages should not have feedback buttons
291+ expect ( userMessage . querySelector ( '[aria-label="Thumbs Up Icon"]' ) ) . to . not
292+ . exist ;
293+ expect ( userMessage . querySelector ( '[aria-label="Thumbs Down Icon"]' ) ) . to
294+ . not . exist ;
295+
296+ // Assistant messages should have feedback buttons
297+ expect ( assistantMessage . querySelector ( '[aria-label="Thumbs Up Icon"]' ) ) . to
298+ . exist ;
299+ expect ( assistantMessage . querySelector ( '[aria-label="Thumbs Down Icon"]' ) )
300+ . to . exist ;
301+ } ) ;
302+
303+ it ( 'tracks positive feedback when thumbs up is clicked' , async function ( ) {
304+ const { result } = renderWithChat ( mockMessages ) ;
305+ const { track } = result ;
306+
307+ const assistantMessage = screen . getByTestId (
308+ 'assistant-message-assistant'
309+ ) ;
310+
311+ // Find and click the thumbs up button
312+ const thumbsUpButton = assistantMessage . querySelector (
313+ '[aria-label="Thumbs Up Icon"]'
314+ ) as HTMLElement ;
315+
316+ userEvent . click ( thumbsUpButton ) ;
317+
318+ await waitFor ( ( ) => {
319+ expect ( track ) . to . have . callCount ( 1 ) ;
320+ expect ( track ) . to . have . been . calledWith ( 'Assistant Feedback Submitted' , {
321+ feedback : 'positive' ,
322+ text : undefined ,
323+ request_id : null ,
324+ } ) ;
325+ } ) ;
326+ } ) ;
327+
328+ it ( 'tracks negative feedback when thumbs down is clicked' , async function ( ) {
329+ const { result } = renderWithChat ( mockMessages ) ;
330+ const { track } = result ;
331+
332+ const assistantMessage = screen . getByTestId (
333+ 'assistant-message-assistant'
334+ ) ;
335+
336+ // Find and click the thumbs down button
337+ const thumbsDownButton = assistantMessage . querySelector (
338+ '[aria-label="Thumbs Down Icon"]'
339+ ) as HTMLElement ;
340+
341+ userEvent . click ( thumbsDownButton ) ;
342+
343+ await waitFor ( ( ) => {
344+ expect ( track ) . to . have . callCount ( 1 ) ;
345+
346+ expect ( track ) . to . have . been . calledWith ( 'Assistant Feedback Submitted' , {
347+ feedback : 'negative' ,
348+ text : undefined ,
349+ request_id : null ,
350+ } ) ;
351+ } ) ;
352+ } ) ;
353+
354+ it ( 'tracks detailed feedback when feedback text is submitted' , async function ( ) {
355+ const { result } = renderWithChat ( mockMessages ) ;
356+ const { track } = result ;
357+
358+ const assistantMessage = screen . getByTestId (
359+ 'assistant-message-assistant'
360+ ) ;
361+
362+ // First click thumbs down to potentially open feedback form
363+ const thumbsDownButton = assistantMessage . querySelector (
364+ '[aria-label="Thumbs Down Icon"]'
365+ ) as HTMLElement ;
366+
367+ userEvent . click ( thumbsDownButton ) ;
368+
369+ // Look for feedback text area (the exact implementation depends on LeafyGreen)
370+ const feedbackTextArea = screen . getByTestId (
371+ 'lg-chat-message_actions-feedback_textarea'
372+ ) ;
373+
374+ userEvent . type ( feedbackTextArea , 'This response was not helpful' ) ;
375+
376+ // Look for submit button
377+ const submitButton = screen . getByText ( 'Submit' ) ;
378+
379+ userEvent . click ( submitButton ) ;
380+
381+ await waitFor ( ( ) => {
382+ expect ( track ) . to . have . callCount ( 2 ) ;
383+
384+ expect ( track ) . to . have . been . calledWith ( 'Assistant Feedback Submitted' , {
385+ feedback : 'negative' ,
386+ text : undefined ,
387+ request_id : null ,
388+ } ) ;
389+
390+ expect ( track ) . to . have . been . calledWith ( 'Assistant Feedback Submitted' , {
391+ feedback : 'negative' ,
392+ text : 'This response was not helpful' ,
393+ request_id : null ,
394+ } ) ;
395+ } ) ;
396+ } ) ;
397+
398+ it ( 'does not show feedback buttons when there are no assistant messages' , function ( ) {
399+ const userOnlyMessages : AssistantMessage [ ] = [
400+ {
401+ id : 'user1' ,
402+ role : 'user' ,
403+ parts : [ { type : 'text' , text : 'Hello!' } ] ,
404+ } ,
405+ {
406+ id : 'user2' ,
407+ role : 'user' ,
408+ parts : [ { type : 'text' , text : 'How are you?' } ] ,
409+ } ,
410+ ] ;
411+
412+ renderWithChat ( userOnlyMessages ) ;
413+
414+ // Should not find any feedback buttons in the entire component
415+ expect ( screen . queryByLabelText ( 'Thumbs Up Icon' ) ) . to . not . exist ;
416+ expect ( screen . queryByLabelText ( 'Thumbs Down Icon' ) ) . to . not . exist ;
417+ } ) ;
418+ } ) ;
275419} ) ;
0 commit comments