@@ -120,6 +120,10 @@ export default class CodeGraph extends BasePage {
120120 return this . page . locator ( "//main[@data-name='main-chat']/*[last()-2]//img[@alt='Waiting for response']" )
121121 }
122122
123+ private get waitingForResponseImage ( ) : Locator {
124+ return this . page . locator ( "//img[@alt='Waiting for response']" )
125+ }
126+
123127 private get selectInputForShowPath ( ) : ( inputNum : string ) => Locator {
124128 return ( inputNum : string ) => this . page . locator ( `(//main[@data-name='main-chat']//input)[${ inputNum } ]` ) ;
125129 }
@@ -189,6 +193,10 @@ export default class CodeGraph extends BasePage {
189193 private get nodeDetailsPanel ( ) : Locator {
190194 return this . page . locator ( "//div[@data-name='node-details-panel']" ) ;
191195 }
196+
197+ private get elementMenu ( ) : Locator {
198+ return this . page . locator ( "//div[@id='elementMenu']" ) ;
199+ }
192200
193201 private get nodedetailsPanelHeader ( ) : Locator {
194202 return this . page . locator ( "//div[@data-name='node-details-panel']/header/p" ) ;
@@ -277,7 +285,12 @@ export default class CodeGraph extends BasePage {
277285 }
278286
279287 async getTextInLastChatElement ( ) : Promise < string > {
280- await delay ( 2500 ) ;
288+ // Wait for loading indicator to disappear
289+ await this . waitingForResponseImage . waitFor ( { state : 'hidden' , timeout : 15000 } ) ;
290+
291+ // Short delay to ensure text is fully rendered
292+ await delay ( 1000 ) ;
293+
281294 return ( await this . lastElementInChat . textContent ( ) ) ! ;
282295 }
283296
@@ -416,8 +429,18 @@ export default class CodeGraph extends BasePage {
416429 }
417430
418431 async nodeClick ( x : number , y : number ) : Promise < void > {
419- await this . canvasElement . hover ( { position : { x, y } } ) ;
420- await this . canvasElement . click ( { position : { x, y } } ) ;
432+ await this . waitForCanvasAnimationToEnd ( ) ;
433+ for ( let attempt = 1 ; attempt <= 3 ; attempt ++ ) {
434+ await this . canvasElement . hover ( { position : { x, y } } ) ;
435+ await this . page . waitForTimeout ( 500 ) ;
436+ await this . canvasElement . click ( { position : { x, y } , button : 'left' } ) ;
437+ if ( await this . elementMenu . isVisible ( ) ) {
438+ return ;
439+ }
440+ await this . page . waitForTimeout ( 1000 ) ;
441+ }
442+
443+ throw new Error ( `Failed to click, elementMenu not visible after multiple attempts.` ) ;
421444 }
422445
423446 async selectCodeGraphCheckbox ( checkbox : string ) : Promise < void > {
@@ -493,42 +516,39 @@ export default class CodeGraph extends BasePage {
493516 return Promise . all ( elements . map ( element => element . innerHTML ( ) ) ) ;
494517 }
495518
496- async getGraphDetails ( ) : Promise < any > {
497- await this . canvasElementBeforeGraphSelection . waitFor ( { state : 'detached' } ) ;
498- await delay ( 2000 )
499- await this . page . waitForFunction ( ( ) => ! ! window . graph ) ;
519+ async getGraphNodes ( ) : Promise < any [ ] > {
520+ await this . waitForCanvasAnimationToEnd ( ) ;
500521
501522 const graphData = await this . page . evaluate ( ( ) => {
502- return window . graph ;
503- } ) ;
504-
505- return graphData ;
506- }
507-
508- async transformNodeCoordinates ( graphData : any ) : Promise < any [ ] > {
509- const { canvasLeft, canvasTop, canvasWidth, canvasHeight, transform } = await this . canvasElement . evaluate ( ( canvas : HTMLCanvasElement ) => {
510- const rect = canvas . getBoundingClientRect ( ) ;
511- const ctx = canvas . getContext ( '2d' ) ;
512- const transform = ctx ?. getTransform ( ) ! ;
513- return {
514- canvasLeft : rect . left ,
515- canvasTop : rect . top ,
516- canvasWidth : rect . width ,
517- canvasHeight : rect . height ,
518- transform,
519- } ;
523+ return ( window as any ) . graph ;
520524 } ) ;
521-
522- const screenCoordinates = graphData . elements . nodes . map ( ( node : any ) => {
523- const adjustedX = node . x * transform . a + transform . e ;
524- const adjustedY = node . y * transform . d + transform . f ;
525- const screenX = canvasLeft + adjustedX - 35 ;
526- const screenY = canvasTop + adjustedY - 190 ;
527525
528- return { ...node , screenX, screenY, } ;
529- } ) ;
526+ let transformData : any = null ;
527+ for ( let attempt = 0 ; attempt < 3 ; attempt ++ ) {
528+ await this . page . waitForTimeout ( 1000 ) ;
529+
530+ transformData = await this . canvasElement . evaluate ( ( canvas : HTMLCanvasElement ) => {
531+ const rect = canvas . getBoundingClientRect ( ) ;
532+ const ctx = canvas . getContext ( '2d' ) ;
533+ return {
534+ left : rect . left ,
535+ top : rect . top ,
536+ transform : ctx ?. getTransform ( ) || null ,
537+ } ;
538+ } ) ;
530539
531- return screenCoordinates ;
540+ if ( transformData . transform ) break ;
541+ console . warn ( `Attempt ${ attempt + 1 } : Transform data not available, retrying...` ) ;
542+ }
543+
544+ if ( ! transformData ?. transform ) throw new Error ( "Canvas transform data not available!" ) ;
545+
546+ const { a, e, d, f } = transformData . transform ;
547+ return graphData . elements . nodes . map ( ( node : any ) => ( {
548+ ...node ,
549+ screenX : transformData . left + node . x * a + e - 35 ,
550+ screenY : transformData . top + node . y * d + f - 190 ,
551+ } ) ) ;
532552 }
533553
534554 async getCanvasScaling ( ) : Promise < { scaleX : number ; scaleY : number } > {
@@ -543,4 +563,63 @@ export default class CodeGraph extends BasePage {
543563 return { scaleX, scaleY } ;
544564 }
545565
566+ async getGraphDetails ( ) : Promise < any > {
567+ await this . canvasElementBeforeGraphSelection . waitFor ( { state : 'detached' } ) ;
568+ await this . waitForCanvasAnimationToEnd ( ) ;
569+ await this . page . waitForFunction ( ( ) => ! ! window . graph ) ;
570+
571+ const graphData = await this . page . evaluate ( ( ) => {
572+ return window . graph ;
573+ } ) ;
574+
575+ return graphData ;
576+ }
577+
578+ async waitForCanvasAnimationToEnd ( timeout = 15000 , checkInterval = 500 ) : Promise < void > {
579+ const canvasHandle = await this . canvasElement . elementHandle ( ) ;
580+
581+ if ( ! canvasHandle ) {
582+ throw new Error ( "Canvas element not found!" ) ;
583+ }
584+
585+ await this . page . waitForFunction (
586+ async ( { canvas, checkInterval, timeout } ) => {
587+ const ctx = canvas . getContext ( '2d' ) ;
588+ if ( ! ctx ) return false ;
589+
590+ const width = canvas . width ;
591+ const height = canvas . height ;
592+
593+ let previousData = ctx . getImageData ( 0 , 0 , width , height ) . data ;
594+ const startTime = Date . now ( ) ;
595+
596+ return new Promise < boolean > ( ( resolve ) => {
597+ const checkCanvas = ( ) => {
598+ if ( Date . now ( ) - startTime > timeout ) {
599+ resolve ( true ) ;
600+ return ;
601+ }
602+
603+ setTimeout ( ( ) => {
604+ const currentData = ctx . getImageData ( 0 , 0 , width , height ) . data ;
605+ if ( JSON . stringify ( previousData ) === JSON . stringify ( currentData ) ) {
606+ resolve ( true ) ;
607+ } else {
608+ previousData = currentData ;
609+ checkCanvas ( ) ;
610+ }
611+ } , checkInterval ) ;
612+ } ;
613+ checkCanvas ( ) ;
614+ } ) ;
615+ } ,
616+ {
617+ canvas : await canvasHandle . evaluateHandle ( ( el ) => el as HTMLCanvasElement ) ,
618+ checkInterval,
619+ timeout
620+ } ,
621+ { timeout }
622+ ) ;
623+ }
624+
546625}
0 commit comments