@@ -30,7 +30,15 @@ export default class CodeGraph extends BasePage {
3030 }
3131
3232 private get navBaritem ( ) : ( navItem : string ) => Locator {
33- return ( navItem : string ) => this . scopedLocator ( `//a[p[text() = '${ navItem } ']]` ) ;
33+ return ( navItem : string ) => {
34+ const navItemSelectors : Record < string , string > = {
35+ "Main Website" : "//a[@title='Home' or .//p[normalize-space()='Main Website'] or contains(@href, 'falkordb.com')]" ,
36+ "Github" : "//a[@title='Github' or .//p[normalize-space()='Github'] or contains(@href, 'github.com/FalkorDB/code-graph')]" ,
37+ "Discord" : "//a[@title='Discord' or .//p[normalize-space()='Discord'] or contains(@href, 'discord.gg/falkordb')]" ,
38+ } ;
39+ const selector = navItemSelectors [ navItem ] ?? `//a[@title='${ navItem } ' or .//p[normalize-space()='${ navItem } ']]` ;
40+ return this . scopedLocator ( selector ) . first ( ) ;
41+ } ;
3442 }
3543
3644 private get createNewProjectBtn ( ) : Locator {
@@ -186,6 +194,10 @@ export default class CodeGraph extends BasePage {
186194 return this . scopedLocator ( "//falkordb-canvas" ) . locator ( "canvas" ) . first ( ) ;
187195 }
188196
197+ private get canvasHost ( ) : Locator {
198+ return this . scopedLocator ( "falkordb-canvas" ) . first ( ) ;
199+ }
200+
189201 private get zoomInBtn ( ) : Locator {
190202 return this . scopedLocator ( "//button[@title='Zoom In']" ) ;
191203 }
@@ -203,11 +215,11 @@ export default class CodeGraph extends BasePage {
203215 }
204216
205217 private get clearGraphBtn ( ) : Locator {
206- return this . scopedLocator ( "// button[p[text()=' Reset Graph']]" ) ;
218+ return this . container . getByRole ( ' button' , { name : ' Reset Graph' } ) ;
207219 }
208220
209221 private get unhideNodesBtn ( ) : Locator {
210- return this . scopedLocator ( "// button[p[text()=' Unhide Nodes']]" ) ;
222+ return this . container . getByRole ( ' button' , { name : ' Unhide Nodes' } ) ;
211223 }
212224
213225 private get elementMenuButton ( ) : ( buttonID : string ) => Locator {
@@ -411,7 +423,14 @@ export default class CodeGraph extends BasePage {
411423 } else {
412424 await interactWhenVisible ( this . selectGraphInComboBoxByName ( graph ) , ( el ) => el . click ( ) , `Graph option ${ graph } ` ) ;
413425 }
414- await this . page . waitForTimeout ( 2000 ) ; // graph animation delay
426+ const graphGetter = this . isMobile ? "graphMobile" : "graphDesktop" ;
427+ await this . page . waitForFunction ( ( getterName ) => {
428+ const getter = ( window as any ) [ getterName ] ;
429+ const graphData = typeof getter === "function" ? getter ( ) : null ;
430+ const nodes = graphData ?. elements ?. nodes || graphData ?. nodes ;
431+ return Array . isArray ( nodes ) && nodes . length > 0 ;
432+ } , graphGetter , { timeout : 10000 } ) ;
433+ await this . page . waitForTimeout ( 3000 ) ;
415434 }
416435
417436 async createProject ( url : string ) : Promise < void > {
@@ -486,10 +505,14 @@ export default class CodeGraph extends BasePage {
486505
487506 async nodeClick ( x : number , y : number ) : Promise < void > {
488507 await this . waitForCanvasAnimationToEnd ( ) ;
508+ const boundingBox = await this . canvasElement . boundingBox ( ) ;
509+ if ( ! boundingBox ) throw new Error ( "Canvas bounding box not found" ) ;
510+ const targetX = Math . min ( Math . max ( x , boundingBox . x + 1 ) , boundingBox . x + boundingBox . width - 1 ) ;
511+ const targetY = Math . min ( Math . max ( y , boundingBox . y + 1 ) , boundingBox . y + boundingBox . height - 1 ) ;
489512 for ( let attempt = 1 ; attempt <= 3 ; attempt ++ ) {
490- await this . canvasElement . hover ( { position : { x , y } } ) ;
513+ await this . page . mouse . move ( targetX , targetY ) ;
491514 await this . page . waitForTimeout ( 500 ) ;
492- await this . canvasElement . click ( { position : { x , y } , button : 'right' } ) ;
515+ await this . page . mouse . click ( targetX , targetY , { button : 'right' } ) ;
493516 if ( await this . elementMenu . isVisible ( ) ) {
494517 return ;
495518 }
@@ -628,6 +651,10 @@ export default class CodeGraph extends BasePage {
628651 return {
629652 left : rect . left ,
630653 top : rect . top ,
654+ width : rect . width ,
655+ height : rect . height ,
656+ canvasWidth : canvas . width ,
657+ canvasHeight : canvas . height ,
631658 transform : ctx ?. getTransform ( ) || null ,
632659 } ;
633660 } ) ;
@@ -642,16 +669,20 @@ export default class CodeGraph extends BasePage {
642669 const nodes = graphData . elements ?. nodes || graphData . nodes ;
643670 if ( ! nodes ) throw new Error ( "No nodes found in graph data!" ) ;
644671
645- const { a, e, d, f } = transformData . transform ;
672+ const { a, b, c, d, e, f } = transformData . transform ;
673+ const cssScaleX = transformData . canvasWidth ? transformData . width / transformData . canvasWidth : 1 ;
674+ const cssScaleY = transformData . canvasHeight ? transformData . height / transformData . canvasHeight : 1 ;
646675 return nodes . map ( ( node : any ) => {
676+ const relativeX = ( node . x * a + node . y * c + e ) * cssScaleX ;
677+ const relativeY = ( node . x * b + node . y * d + f ) * cssScaleY ;
647678 // Canvas format has properties nested in 'data' object and 'labels' instead of 'category'
648679 // Flatten the structure for backward compatibility
649680 const flatNode = {
650681 ...node ,
651682 ...( node . data || { } ) , // Spread data properties to top level
652683 category : node . labels ?. [ 0 ] || node . category , // Use labels[0] or fallback to category
653- screenX : transformData . left + node . x * a + e - 35 ,
654- screenY : transformData . top + node . y * d + f - 190 ,
684+ screenX : transformData . left + relativeX ,
685+ screenY : transformData . top + relativeY ,
655686 } ;
656687 return flatNode ;
657688 } ) ;
@@ -660,15 +691,10 @@ export default class CodeGraph extends BasePage {
660691
661692 async getCanvasScaling ( ) : Promise < { scaleX : number ; scaleY : number } > {
662693 await this . waitForCanvasAnimationToEnd ( ) ;
663- const { scaleX, scaleY } = await this . canvasElement . evaluate ( ( canvas : HTMLCanvasElement ) => {
664- const ctx = canvas . getContext ( '2d' ) ;
665- const transform = ctx ?. getTransform ( ) ;
666- return {
667- scaleX : transform ?. a || 1 ,
668- scaleY : transform ?. d || 1 ,
669- } ;
694+ const zoom = await this . canvasHost . evaluate ( ( canvas : { getZoom ?: ( ) => number } ) => {
695+ return typeof canvas . getZoom === "function" ? canvas . getZoom ( ) : 1 ;
670696 } ) ;
671- return { scaleX, scaleY } ;
697+ return { scaleX : zoom , scaleY : zoom } ;
672698 }
673699
674700 async downloadImage ( ) : Promise < Download > {
0 commit comments