33// found in the LICENSE file.
44
55import * as Common from '../../../core/common/common.js' ;
6+ import * as AiAssistanceModels from '../../../models/ai_assistance/ai_assistance.js' ;
67import * as Trace from '../../../models/trace/trace.js' ;
8+ import { mockAidaClient } from '../../../testing/AiAssistanceHelpers.js' ;
79import { cleanTextContent , dispatchClickEvent } from '../../../testing/DOMHelpers.js' ;
810import { describeWithEnvironment , updateHostConfig } from '../../../testing/EnvironmentHelpers.js' ;
911import {
@@ -22,6 +24,9 @@ import * as Components from './components/components.js';
2224import * as Overlays from './overlays.js' ;
2325
2426const FAKE_OVERLAY_ENTRY_QUERIES : Overlays . Overlays . OverlayEntryQueries = {
27+ parsedTrace ( ) {
28+ return null ;
29+ } ,
2530 isEntryCollapsedByUser ( ) {
2631 return false ;
2732 } ,
@@ -277,7 +282,12 @@ describeWithEnvironment('Overlays', () => {
277282 network : networkFlameChartsContainer ,
278283 } ,
279284 charts,
280- entryQueries : FAKE_OVERLAY_ENTRY_QUERIES ,
285+ entryQueries : {
286+ ...FAKE_OVERLAY_ENTRY_QUERIES ,
287+ parsedTrace ( ) {
288+ return parsedTrace ;
289+ } ,
290+ } ,
281291 } ) ;
282292 const currManager = Timeline . ModificationsManager . ModificationsManager . activeManager ( ) ;
283293 // The Annotations Overlays are added through the ModificationsManager listener
@@ -322,6 +332,7 @@ describeWithEnvironment('Overlays', () => {
322332 inputField : HTMLElement ,
323333 overlays : Overlays . Overlays . Overlays ,
324334 event : Trace . Types . Events . Event ,
335+ component : Components . EntryLabelOverlay . EntryLabelOverlay ,
325336 } > {
326337 updateHostConfig ( {
327338 devToolsAiGeneratedTimelineLabels : {
@@ -341,6 +352,7 @@ describeWithEnvironment('Overlays', () => {
341352 label : label ?? '' ,
342353 } ) ;
343354 await overlays . update ( ) ;
355+ await RenderCoordinator . done ( ) ;
344356
345357 // Ensure that the overlay was created.
346358 const overlayDOM = container . querySelector < HTMLElement > ( '.overlay-type-ENTRY_LABEL' ) ;
@@ -353,7 +365,7 @@ describeWithEnvironment('Overlays', () => {
353365 const inputField = elementsWrapper . querySelector < HTMLElement > ( '.input-field' ) ;
354366 assert . isOk ( inputField ) ;
355367
356- return { elementsWrapper, inputField, overlays, event} ;
368+ return { elementsWrapper, inputField, overlays, event, component } ;
357369 }
358370
359371 it ( 'can render an entry selected overlay' , async function ( ) {
@@ -483,6 +495,7 @@ describeWithEnvironment('Overlays', () => {
483495
484496 // Double click on the label box to make it editable and focus on it
485497 inputField . dispatchEvent ( new FocusEvent ( 'dblclick' , { bubbles : true } ) ) ;
498+ await RenderCoordinator . done ( ) ;
486499
487500 const aiLabelButtonWrapper =
488501 elementsWrapper . querySelector < HTMLElement > ( '.ai-label-button-wrapper' ) as HTMLSpanElement ;
@@ -493,6 +506,7 @@ describeWithEnvironment('Overlays', () => {
493506 // This dialog should not be visible unless the `generate annotation` button is clicked
494507 assert . isFalse ( showFreDialogStub . called , 'Expected FreDialog to be not shown but it\'s shown' ) ;
495508 aiButton . dispatchEvent ( new FocusEvent ( 'click' , { bubbles : true } ) ) ;
509+ await RenderCoordinator . done ( ) ;
496510
497511 // This dialog should be visible
498512 assert . isTrue ( showFreDialogStub . called , 'Expected FreDialog to be shown but it\'s not shown' ) ;
@@ -558,6 +572,35 @@ describeWithEnvironment('Overlays', () => {
558572 assert . strictEqual ( inputField ?. innerText , 'entry label' ) ;
559573 } ) ;
560574
575+ it ( 'generates a label when the user clicks "Generate" if the setting is enabled' , async function ( ) {
576+ const { elementsWrapper, inputField, component} = await createAnnotationsLabelElement ( this , 'web-dev.json.gz' , 50 ) ;
577+ Common . Settings . moduleSetting ( 'ai-annotations-enabled' ) . set ( true ) ;
578+
579+ const generateButton = elementsWrapper . querySelector < HTMLElement > ( '.ai-label-button' ) ;
580+ assert . isOk ( generateButton , 'could not find "Generate label" button' ) ;
581+ assert . isTrue ( generateButton . classList . contains ( 'enabled' ) ) ;
582+ const agent = new AiAssistanceModels . PerformanceAgent ( {
583+ aidaClient : mockAidaClient ( [ [ {
584+ explanation : 'This is an interesting entry' ,
585+ metadata : {
586+ rpcGlobalId : 123 ,
587+ }
588+ } ] ] )
589+ } ) ;
590+ component . overrideAIAgentForTest ( agent ) ;
591+
592+ // The Agent call is async, so wait for the change event on the label to ensure the UI is updated.
593+ const changeEvent = new Promise < void > ( resolve => {
594+ component . addEventListener (
595+ Components . EntryLabelOverlay . EntryLabelChangeEvent . eventName , ( ) => resolve ( ) , { once : true } ) ;
596+ } ) ;
597+ dispatchClickEvent ( generateButton ) ;
598+ await RenderCoordinator . done ( ) ;
599+ await changeEvent ;
600+
601+ assert . strictEqual ( inputField . innerHTML , 'This is an interesting entry' ) ;
602+ } ) ;
603+
561604 it ( 'Correct security tooltip on the `generate ai label` info icon hover for the users with logging enabled' ,
562605 async function ( ) {
563606 const { elementsWrapper, inputField} =
0 commit comments