Skip to content

Commit 1cb120f

Browse files
committed
Refactor canvas functionality and update tests for improved graph handling
- Replaced canvas analytics with dataset when graph is created - Added node coordinate transformation for canvas locations - Updated all tests to align with dataset and coordinate changes - Implemented canvas scaling for zoom, and center functions -Split CodeGraph spec into SearchBar, Canvas, and NodeDetailsPanel - Added missing tests
1 parent ace86ce commit 1cb120f

File tree

11 files changed

+538
-535
lines changed

11 files changed

+538
-535
lines changed

app/page.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,10 @@ export default function Home() {
127127
}
128128

129129
const json = await result.json()
130-
setGraph(Graph.create(json.result.entities, graphName))
130+
const g = Graph.create(json.result.entities, graphName)
131+
setGraph(g)
132+
// @ts-ignore
133+
window.graph = g
131134
}
132135

133136
// Send the user query to the server to expand a node

e2e/config/constants.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,4 @@ export const GRAPH_ID = "GraphRAG-SDK";
22
export const PROJECT_NAME = "GraphRAG-SDK";
33
export const CHAT_OPTTIONS_COUNT = 1;
44
export const Node_Question = "how many nodes do we have?";
5-
export const Edge_Question = "how many edges do we have?";
6-
export const Node_Import_Data = "import_data";
7-
export const Node_Add_Edge = "add_edge";
5+
export const Edge_Question = "how many edges do we have?";

e2e/config/testData.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,13 @@ export const specialCharacters: { character: string; expectedRes: boolean }[] =
1717
export const nodesPath: { firstNode: string; secondNode: string }[] = [
1818
{ firstNode: "import_data", secondNode: "add_edge" },
1919
{ firstNode: "test_kg_delete", secondNode: "list_graphs" },
20-
];
20+
];
21+
22+
export const nodes: { nodeName: string; }[] = [
23+
{ nodeName: "import_data"},
24+
{ nodeName: "add_edge" },
25+
{ nodeName: "test_kg_delete"},
26+
{ nodeName: "list_graphs"}
27+
];
28+
29+
export const categories: string[] = ['File', 'Class', 'Function'];

e2e/logic/POM/codeGraph.ts

Lines changed: 100 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import { Locator, Page } from "playwright";
22
import BasePage from "../../infra/ui/basePage";
33
import { delay, waitToBeEnabled } from "../utils";
4-
import { analyzeCanvasNodes, CanvasAnalysisResult } from "../canvasAnalysis";
4+
5+
declare global {
6+
interface Window {
7+
graph: any;
8+
}
9+
}
510

611
export default class CodeGraph extends BasePage {
712
/* NavBar Locators*/
@@ -120,7 +125,7 @@ export default class CodeGraph extends BasePage {
120125
}
121126

122127
private get locateNodeInLastChatPath(): (node: string) => Locator {
123-
return (node: string) => this.page.locator(`//main[@data-name='main-chat']/*[last()]//span[contains(text(), '${node}')]`);
128+
return (node: string) => this.page.locator(`(//main[@data-name='main-chat']//span[contains(text(), '${node}')])[last()]`);
124129
}
125130

126131
private get selectFirstPathOption(): (inputNum: string) => Locator {
@@ -150,7 +155,7 @@ export default class CodeGraph extends BasePage {
150155
/* Canvas Locators*/
151156

152157
private get canvasElement(): Locator {
153-
return this.page.locator("//canvas[position()=3]");
158+
return this.page.locator("//canvas");
154159
}
155160

156161
private get zoomInBtn(): Locator {
@@ -170,12 +175,20 @@ export default class CodeGraph extends BasePage {
170175
}
171176

172177
private get clearGraphBtn(): Locator {
173-
return this.page.locator("//button[p[text()='Clear Graph']]");
178+
return this.page.locator("//button[p[text()='Reset Graph']]");
179+
}
180+
181+
private get unhideNodesBtn(): Locator {
182+
return this.page.locator("//button[p[text()='Unhide Nodes']]");
174183
}
175184

176185
private get elementMenuButton(): (buttonID: string) => Locator {
177186
return (buttonID: string) => this.page.locator(`//button[@title='${buttonID}']`);
178187
}
188+
189+
private get nodeDetailsPanel(): Locator {
190+
return this.page.locator("//div[@data-name='node-details-panel']");
191+
}
179192

180193
private get nodedetailsPanelHeader(): Locator {
181194
return this.page.locator("//div[@data-name='node-details-panel']/header/p");
@@ -196,6 +209,14 @@ export default class CodeGraph extends BasePage {
196209
return this.page.locator("//div[@data-name='node-details-panel']/main/div/p[1]");
197210
}
198211

212+
private get canvasElementBeforeGraphSelection(): Locator {
213+
return this.page.locator("//h1[contains(text(), 'Select a repo to show its graph here')]");
214+
}
215+
216+
private get copyToClipboardNodePanelDetails(): Locator {
217+
return this.page.locator(`//div[@data-name='node-details-panel']//button[@title='Copy src to clipboard']`);
218+
}
219+
199220
/* NavBar functionality */
200221
async clickOnFalkorDbLogo(): Promise<Page> {
201222
await this.page.waitForLoadState('networkidle');
@@ -377,11 +398,6 @@ export default class CodeGraph extends BasePage {
377398

378399
/* Canvas functionality */
379400

380-
async getCanvasAnalysis(): Promise<CanvasAnalysisResult> {
381-
await delay(2000);
382-
return await analyzeCanvasNodes(this.canvasElement);
383-
}
384-
385401
async clickZoomIn(): Promise<void> {
386402
await this.zoomInBtn.click();
387403
}
@@ -392,28 +408,29 @@ export default class CodeGraph extends BasePage {
392408

393409
async clickCenter(): Promise<void> {
394410
await this.centerBtn.click();
411+
await delay(1000); //animation delay
395412
}
396413

397414
async clickOnRemoveNodeViaElementMenu(): Promise<void> {
398415
await this.elementMenuButton("Remove").click();
399416
}
400417

401-
async rightClickOnNode(x: number, y: number): Promise<void> {
402-
const boundingBox = (await this.canvasElement.boundingBox())!;
403-
const devicePixelRatio = await this.page.evaluate(() => window.devicePixelRatio || 1);
404-
const adjustedX = boundingBox.x + Math.round(x * devicePixelRatio);
405-
const adjustedY = boundingBox.y + Math.round(y * devicePixelRatio);
406-
await this.page.mouse.click(adjustedX, adjustedY, { button: 'right' });
418+
async nodeClick(x: number, y: number): Promise<void> {
419+
await this.canvasElement.hover({ position: { x, y } });
420+
await this.canvasElement.click({ position: { x, y } });
407421
}
408422

409-
410423
async selectCodeGraphCheckbox(checkbox: string): Promise<void> {
411424
await this.codeGraphCheckbox(checkbox).click();
412425
}
413426

414427
async clickOnClearGraphBtn(): Promise<void> {
415428
await this.clearGraphBtn.click();
416-
}
429+
}
430+
431+
async clickOnUnhideNodesBtn(): Promise<void> {
432+
await this.unhideNodesBtn.click();
433+
}
417434

418435
async changeNodePosition(x: number, y: number): Promise<void> {
419436
const box = (await this.canvasElement.boundingBox())!;
@@ -429,6 +446,14 @@ export default class CodeGraph extends BasePage {
429446
await this.page.mouse.up();
430447
}
431448

449+
async isNodeDetailsPanel(): Promise<boolean> {
450+
return this.nodeDetailsPanel.isVisible();
451+
}
452+
453+
async clickOnViewNode(): Promise<void> {
454+
await this.elementMenuButton("View Node").click();
455+
}
456+
432457
async getNodeDetailsHeader(): Promise<string> {
433458
await this.elementMenuButton("View Node").click();
434459
const text = await this.nodedetailsPanelHeader.innerHTML();
@@ -445,7 +470,13 @@ export default class CodeGraph extends BasePage {
445470
return { nodes, edges }
446471
}
447472

448-
async clickOnCopySrcOnNode(): Promise<string> {
473+
async clickOnCopyToClipboardNodePanelDetails(): Promise<string> {
474+
await this.copyToClipboardNodePanelDetails.click();
475+
await delay(1000)
476+
return await this.page.evaluate(() => navigator.clipboard.readText());
477+
}
478+
479+
async clickOnCopyToClipboard(): Promise<string> {
449480
await this.elementMenuButton("Copy src to clipboard").click();
450481
await delay(1000)
451482
return await this.page.evaluate(() => navigator.clipboard.readText());
@@ -461,4 +492,55 @@ export default class CodeGraph extends BasePage {
461492
const elements = await this.nodedetailsPanelElements.all();
462493
return Promise.all(elements.map(element => element.innerHTML()));
463494
}
495+
496+
async getGraphDetails(): Promise<any> {
497+
await this.canvasElementBeforeGraphSelection.waitFor({ state: 'detached' });
498+
await delay(2000)
499+
await this.page.waitForFunction(() => !!window.graph);
500+
501+
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+
};
520+
});
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;
527+
528+
return {...node, screenX, screenY,};
529+
});
530+
531+
return screenCoordinates;
532+
}
533+
534+
async getCanvasScaling(): Promise<{ scaleX: number; scaleY: number }> {
535+
const { scaleX, scaleY } = await this.canvasElement.evaluate((canvas: HTMLCanvasElement) => {
536+
const ctx = canvas.getContext('2d');
537+
const transform = ctx?.getTransform();
538+
return {
539+
scaleX: transform?.a || 1,
540+
scaleY: transform?.d || 1,
541+
};
542+
});
543+
return { scaleX, scaleY };
544+
}
545+
464546
}

0 commit comments

Comments
 (0)