Skip to content

Commit dbcbde6

Browse files
committed
Update dependencies and improve test configurations
- Bumped various dependencies including `next`, `playwright`, and `sharp` to their latest versions. - Updated Playwright configuration for improved test reporting and parallel execution. - Enhanced README for clarity on supported languages. - Refactored test cases for better maintainability and consistency in UI responses. - Added new utility functions and improved existing ones for better node handling in tests. - Fixed minor formatting issues in configuration files for consistency.
1 parent fea017b commit dbcbde6

12 files changed

Lines changed: 488 additions & 68 deletions

File tree

.github/workflows/playwright.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ jobs:
88
test:
99
timeout-minutes: 60
1010
runs-on: ubuntu-latest
11+
strategy:
12+
fail-fast: false
13+
matrix:
14+
shard: [1, 2]
1115
services:
1216
falkordb:
1317
image: falkordb/falkordb:latest
@@ -40,7 +44,7 @@ jobs:
4044
- uses: actions/upload-artifact@v4
4145
if: always()
4246
with:
43-
name: playwright-report
47+
name: playwright-report-shard-${{ matrix.shard }}
4448
path: playwright-report/
4549
retention-days: 30
4650
- name: Upload failed test screenshots

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,9 @@ curl -X POST http://127.0.0.1:5000/analyze_folder \
9292
-d '{"path": "<PATH_TO_LOCAL_REPO>", "ignore": ["./.github", "./sbin", "./.git", "./deps", "./bin", "./build"]}'
9393
```
9494

95-
**Note:** Currently, Code-Graph supports analyzing C and Python source files.
96-
Support for additional languages (e.g., JavaScript, Go, Java) is planned.
95+
Note: At the moment code-graph can analyze both the Java & Python source files.
96+
Support for additional languages e.g. C, JavaScript, Go is planned to be added
97+
in the future.
9798

9899
### 5. Access the Web Interface
99100

app/components/elementMenu.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export default function ElementMenu({ obj, objects, setPath, handleRemove, posit
4141
setContainerWidth(ref.clientWidth)
4242
}}
4343
className="absolute z-10 bg-black rounded-lg shadow-lg flex divide-x divide-[#434343]"
44+
id="elementMenu"
4445
style={{
4546
left: Math.max(8, Math.min(position.x - containerWidth / 2, (parentRef?.current?.clientWidth || 0) - containerWidth - 8)),
4647
top: Math.max(8, Math.min(position.y - 153, (parentRef?.current?.clientHeight || 0) - containerWidth - 8)),

e2e/config/testData.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@ export const specialCharacters: { character: string; expectedRes: boolean }[] =
1616

1717
export const nodesPath: { firstNode: string; secondNode: string }[] = [
1818
{ firstNode: "import_data", secondNode: "add_edge" },
19-
{ firstNode: "test_kg_delete", secondNode: "list_graphs" },
19+
{ firstNode: "delete", secondNode: "list_graphs" }
2020
];
2121

2222
export const nodes: { nodeName: string; }[] = [
2323
// { nodeName: "ask"},
2424
{ nodeName: "add_edge" },
25-
{ nodeName: "test_kg_delete"},
25+
{ nodeName: "delete"},
2626
{ nodeName: "list_graphs"}
2727
];
2828

e2e/logic/POM/codeGraph.ts

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ export default class CodeGraph extends BasePage {
136136
return this.scopedLocator("//main[@data-name='main-chat']/*[last()-2]//img[@alt='Waiting for response']")
137137
}
138138

139+
private get waitingForResponseImage(): Locator {
140+
return this.page.locator("//img[@alt='Waiting for response']")
141+
}
142+
139143
private get selectInputForShowPath(): (inputNum: string) => Locator {
140144
return (inputNum: string) => this.scopedLocator(`(//main[@data-name='main-chat']//input)[${inputNum}]`);
141145
}
@@ -211,7 +215,7 @@ export default class CodeGraph extends BasePage {
211215
}
212216

213217
private get elementMenu(): Locator {
214-
return this.scopedLocator("//div[@id='elementMenu']");
218+
return this.page.locator("//div[@id='elementMenu']");
215219
}
216220

217221
private get nodedetailsPanelHeader(): Locator {
@@ -450,15 +454,17 @@ export default class CodeGraph extends BasePage {
450454

451455
async clickZoomIn(): Promise<void> {
452456
await this.zoomInBtn.click();
457+
await this.waitForCanvasAnimationToEnd();
453458
}
454459

455460
async clickZoomOut(): Promise<void> {
456461
await this.zoomOutBtn.click();
462+
await this.waitForCanvasAnimationToEnd();
457463
}
458464

459465
async clickCenter(): Promise<void> {
460466
await this.centerBtn.click();
461-
await this.page.waitForTimeout(2000); //animation delay
467+
await this.waitForCanvasAnimationToEnd();
462468
}
463469

464470
async clickOnRemoveNodeViaElementMenu(): Promise<void> {
@@ -577,19 +583,6 @@ export default class CodeGraph extends BasePage {
577583
return Promise.all(elements.map(element => element.innerHTML()));
578584
}
579585

580-
async getGraphDetails(): Promise<any> {
581-
await this.canvasElementBeforeGraphSelection.waitFor({ state: 'detached' });
582-
await this.waitForCanvasAnimationToEnd();
583-
await this.page.waitForFunction(() => !!window.graph);
584-
585-
const graphData = await this.page.evaluate(() => {
586-
return window.graph;
587-
});
588-
589-
return graphData;
590-
}
591-
592-
593586
async getGraphNodes(): Promise<any[]> {
594587
await this.waitForCanvasAnimationToEnd();
595588

@@ -627,6 +620,7 @@ export default class CodeGraph extends BasePage {
627620

628621

629622
async getCanvasScaling(): Promise<{ scaleX: number; scaleY: number }> {
623+
await this.waitForCanvasAnimationToEnd();
630624
const { scaleX, scaleY } = await this.canvasElement.evaluate((canvas: HTMLCanvasElement) => {
631625
const ctx = canvas.getContext('2d');
632626
const transform = ctx?.getTransform();
@@ -668,6 +662,18 @@ export default class CodeGraph extends BasePage {
668662
await this.page.waitForTimeout(500);
669663
return await this.nodeToolTip(node).isVisible();
670664
}
665+
666+
async getGraphDetails(): Promise<any> {
667+
await this.canvasElementBeforeGraphSelection.waitFor({ state: 'detached' });
668+
await this.waitForCanvasAnimationToEnd();
669+
await this.page.waitForFunction(() => !!window.graph);
670+
671+
const graphData = await this.page.evaluate(() => {
672+
return window.graph;
673+
});
674+
675+
return graphData;
676+
}
671677

672678
async waitForCanvasAnimationToEnd(timeout = 15000, checkInterval = 500): Promise<void> {
673679
const canvasHandle = await this.canvasElement.elementHandle();

e2e/logic/utils.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,6 @@ export function findFirstNodeWithSrc(nodes: { src?: string }[]): any {
5757
return nodes.find((node) => node.src !== undefined);
5858
}
5959

60+
export function findNodeWithSpecificSrc(nodes: { src?: string }[], srcContent: string): any {
61+
return nodes.find((node) => node.src && node.src.includes(srcContent));
62+
}

e2e/tests/canvas.spec.ts

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import BrowserWrapper from "../infra/ui/browserWrapper";
33
import CodeGraph from "../logic/POM/codeGraph";
44
import urls from "../config/urls.json";
55
import { GRAPHRAG_SDK } from "../config/constants";
6-
import { delay, findNodeByName } from "../logic/utils";
6+
import { findNodeByName } from "../logic/utils";
77
import { nodesPath, categories, nodes, graphs } from "../config/testData";
88
import { ApiCalls } from "../logic/api/apiCalls";
99
import fs from 'fs';
@@ -50,8 +50,9 @@ test.describe("Canvas tests", () => {
5050
await codeGraph.clickZoomOut();
5151
await codeGraph.clickCenter();
5252
const updatedGraph = await codeGraph.getCanvasScaling();
53-
expect(Math.abs(initialGraph.scaleX - updatedGraph.scaleX)).toBeLessThanOrEqual(0.1);
54-
expect(Math.abs(initialGraph.scaleY - updatedGraph.scaleY)).toBeLessThanOrEqual(0.1);
53+
expect(Math.abs(initialGraph.scaleX - updatedGraph.scaleX)).toBeLessThanOrEqual(0.2);
54+
expect(Math.abs(initialGraph.scaleY - updatedGraph.scaleY)).toBeLessThanOrEqual(0.2);
55+
5556
})
5657

5758
nodes.slice(0,2).forEach((node) => {
@@ -62,8 +63,8 @@ test.describe("Canvas tests", () => {
6263
const targetNode = findNodeByName(initialGraph, node.nodeName);
6364
await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY);
6465
await codeGraph.clickOnRemoveNodeViaElementMenu();
65-
const updatedGraph = await codeGraph.getGraphDetails();
66-
const targetNodeForUpdateGraph = findNodeByName(updatedGraph.elements.nodes, node.nodeName);
66+
const updatedGraph = await codeGraph.getGraphNodes();
67+
const targetNodeForUpdateGraph = findNodeByName(updatedGraph, node.nodeName);
6768
expect(targetNodeForUpdateGraph.visible).toBe(false);
6869
});
6970
})
@@ -77,8 +78,8 @@ test.describe("Canvas tests", () => {
7778
await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY);
7879
await codeGraph.clickOnRemoveNodeViaElementMenu();
7980
await codeGraph.clickOnUnhideNodesBtn();
80-
const updatedGraph = await codeGraph.getGraphDetails();
81-
const targetNodeForUpdateGraph = findNodeByName(updatedGraph.elements.nodes, node.nodeName);
81+
const updatedGraph = await codeGraph.getGraphNodes();
82+
const targetNodeForUpdateGraph = findNodeByName(updatedGraph, node.nodeName);
8283
expect(targetNodeForUpdateGraph.visible).toBe(true);
8384
});
8485
})
@@ -89,9 +90,9 @@ test.describe("Canvas tests", () => {
8990
const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl);
9091
await codeGraph.selectGraph(GRAPHRAG_SDK);
9192
await codeGraph.selectCodeGraphCheckbox(checkboxIndex.toString());
92-
const result = await codeGraph.getGraphDetails();
93-
const findItem = result.categories.find((item: { name: string; }) => item.name === category)
94-
expect(findItem.show).toBe(false)
93+
const result = await codeGraph.getGraphNodes();
94+
const findItem = result.find((item: { category: string; }) => item.category === category);
95+
expect(findItem?.visible).toBe(false);
9596
});
9697
})
9798

@@ -103,15 +104,15 @@ test.describe("Canvas tests", () => {
103104
await codeGraph.clickOnShowPathBtn("Show the path");
104105
await codeGraph.insertInputForShowPath("1", path.firstNode);
105106
await codeGraph.insertInputForShowPath("2", path.secondNode);
106-
const initialGraph = await codeGraph.getGraphDetails();
107-
const firstNode = findNodeByName(initialGraph.elements.nodes, path.firstNode);
108-
const secondNode = findNodeByName(initialGraph.elements.nodes, path.secondNode);
107+
const initialGraph = await codeGraph.getGraphNodes();
108+
const firstNode = findNodeByName(initialGraph, path.firstNode);
109+
const secondNode = findNodeByName(initialGraph, path.secondNode);
109110
expect(firstNode.isPath).toBe(true);
110111
expect(secondNode.isPath).toBe(true);
111112
await codeGraph.clickOnClearGraphBtn();
112-
const updateGraph = await codeGraph.getGraphDetails();
113-
const firstNode1 = findNodeByName(updateGraph.elements.nodes, path.firstNode);
114-
const secondNode1 = findNodeByName(updateGraph.elements.nodes, path.secondNode);
113+
const updateGraph = await codeGraph.getGraphNodes();
114+
const firstNode1 = findNodeByName(updateGraph, path.firstNode);
115+
const secondNode1 = findNodeByName(updateGraph, path.secondNode);
115116
expect(firstNode1.isPath).toBe(false);
116117
expect(secondNode1.isPath).toBe(false);
117118
});

e2e/tests/chat.spec.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import BrowserWrapper from "../infra/ui/browserWrapper";
33
import urls from "../config/urls.json";
44
import { ApiCalls } from "../logic/api/apiCalls";
55
import CodeGraph from "../logic/POM/codeGraph";
6-
import { CHAT_OPTTIONS_COUNT, GRAPHRAG_SDK, Node_Question, } from "../config/constants";
6+
import { CHAT_OPTTIONS_COUNT, GRAPHRAG_SDK, Node_Question } from "../config/constants";
77
import { delay } from "../logic/utils";
88
import { nodesPath } from "../config/testData";
99

@@ -132,4 +132,33 @@ test.describe("Chat tests", () => {
132132
expect(result).toBeDefined();
133133
});
134134
}
135+
136+
test(`Validate consistent UI responses for repeated questions in chat`, async () => {
137+
const chat = await browser.createNewPage(CodeGraph, urls.baseUrl);
138+
await chat.selectGraph(GRAPHRAG_SDK);
139+
const responses: string[] = [];
140+
for (let i = 0; i < 3; i++) {
141+
await chat.sendMessage(Node_Question);
142+
const result = await chat.getTextInLastChatElement();
143+
const number = result.match(/\d+/g)?.[0]!;
144+
responses.push(number);
145+
await delay(3000); //delay before asking next question
146+
}
147+
const identicalResponses = responses.every((value) => value === responses[0]);
148+
expect(identicalResponses).toBe(true);
149+
});
150+
151+
test(`Validate UI response matches API response for a given question in chat`, async () => {
152+
const api = new ApiCalls();
153+
const apiResponse = await api.askQuestion(GRAPHRAG_SDK, Node_Question);
154+
155+
const chat = await browser.createNewPage(CodeGraph, urls.baseUrl);
156+
await chat.selectGraph(GRAPHRAG_SDK);
157+
158+
await chat.sendMessage(Node_Question);
159+
const uiResponse = await chat.getTextInLastChatElement();
160+
const number = uiResponse.match(/\d+/g)?.[0]!;
161+
162+
expect(number).toEqual(apiResponse.result.response.match(/\d+/g)?.[0]);
163+
});
135164
});

e2e/tests/nodeDetailsPanel.spec.ts

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ import { test, expect } from "@playwright/test";
22
import BrowserWrapper from "../infra/ui/browserWrapper";
33
import CodeGraph from "../logic/POM/codeGraph";
44
import urls from "../config/urls.json";
5-
import { GRAPHRAG_SDK, FLASK_GRAPH } from "../config/constants";
5+
import { FLASK_GRAPH, GRAPHRAG_SDK } from "../config/constants";
6+
import { findNodeByName } from "../logic/utils";
67
import { nodes } from "../config/testData";
78
import { ApiCalls } from "../logic/api/apiCalls";
8-
import { findNodeByName, findFirstNodeWithSrc } from "../logic/utils";
99

1010
test.describe("Node details panel tests", () => {
1111
let browser: BrowserWrapper;
@@ -39,8 +39,8 @@ test.describe("Node details panel tests", () => {
3939
await browser.setPageToFullScreen();
4040
await codeGraph.selectGraph(GRAPHRAG_SDK);
4141
const graphData = await codeGraph.getGraphNodes();
42-
const node1 = findNodeByName(graphData, node.nodeName);
43-
await codeGraph.nodeClick(node1.screenX, node1.screenY);
42+
const targetNode = findNodeByName(graphData, node.nodeName);
43+
await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY);
4444
await codeGraph.clickOnViewNode();
4545
await codeGraph.clickOnNodeDetailsCloseBtn();
4646
expect(await codeGraph.isNodeDetailsPanel()).toBe(false);
@@ -53,28 +53,29 @@ test.describe("Node details panel tests", () => {
5353
await browser.setPageToFullScreen();
5454
await codeGraph.selectGraph(GRAPHRAG_SDK);
5555
const graphData = await codeGraph.getGraphNodes();
56-
const node1 = findNodeByName(graphData, node.nodeName);
57-
await codeGraph.nodeClick(node1.screenX, node1.screenY);
58-
expect(await codeGraph.getNodeDetailsHeader()).toContain(
59-
node.nodeName.toUpperCase()
60-
);
61-
});
62-
});
56+
const targetNode = findNodeByName(graphData, node.nodeName);
57+
await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY);
58+
expect(await codeGraph.getNodeDetailsHeader()).toContain(node.nodeName.toUpperCase())
59+
})
60+
})
61+
6362

6463
test(`Validate copy functionality for node inside node details panel and verify with api`, async () => {
6564
const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl);
6665
await browser.setPageToFullScreen();
6766
await codeGraph.selectGraph(FLASK_GRAPH);
6867
const graphData = await codeGraph.getGraphNodes();
69-
const nodeData = findFirstNodeWithSrc(graphData);
70-
await codeGraph.nodeClick(nodeData.screenX, nodeData.screenY);
68+
69+
// Find a node that has src property (actual source code)
70+
const targetNode = graphData.find(node => node.src) || graphData[0];
71+
72+
await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY);
7173
await codeGraph.clickOnViewNode();
72-
const result = await codeGraph.clickOnCopyToClipboardNodePanelDetails();
73-
const api = new ApiCalls();
74-
const response = await api.getProject(FLASK_GRAPH);
75-
const foundNode = response.result.entities.nodes.find((nod) => nod.properties?.name === nodeData.name);
76-
expect(foundNode?.properties.src).toBe(result);
77-
});
74+
const copiedText = await codeGraph.clickOnCopyToClipboardNodePanelDetails();
75+
76+
// Verify the copied text matches the node's src property
77+
expect(copiedText).toBe(targetNode.src || "");
78+
});
7879

7980
nodes.slice(0, 2).forEach((node) => {
8081
test(`Validate view node panel keys via api for ${node.nodeName}`, async () => {

e2e/tests/searchBar.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import BrowserWrapper from "../infra/ui/browserWrapper";
33
import CodeGraph from "../logic/POM/codeGraph";
44
import urls from "../config/urls.json";
55
import { GRAPHRAG_SDK } from "../config/constants";
6-
import { delay, findFirstNodeWithSrc, findNodeByName } from "../logic/utils";
76
import { nodes, searchData, specialCharacters } from "../config/testData";
7+
import { delay } from "../logic/utils";
88
import { ApiCalls } from "../logic/api/apiCalls";
99

1010
test.describe("search bar tests", () => {

0 commit comments

Comments
 (0)