From b1e633ce2415a0acaf418807eb789cf6402c801a Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Mon, 2 Dec 2024 17:13:32 +0200 Subject: [PATCH 1/9] canvas tests (#258, #262) --- e2e/logic/POM/codeGraph.ts | 22 ++++++++++++++++++---- e2e/tests/codeGraph.spec.ts | 28 +++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 3f8e3d60..e8479711 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -136,7 +136,15 @@ export default class CodeGraph extends BasePage { private get removeNodeViaElementMenu(): Locator { return this.page.locator("//button[@title='Remove']"); } - + + private get codeGraphCheckbox(): (checkbox: string) => Locator { + return (checkbox: string) => this.page.locator(`(//button[@role='checkbox'])[${checkbox}]`); + } + + private get clearGraphBtn(): Locator { + return this.page.locator("//button[p[text()='Clear Graph']]"); + } + /* NavBar functionality */ async clickOnFalkorDbLogo(): Promise { await this.page.waitForLoadState('networkidle'); @@ -266,7 +274,6 @@ export default class CodeGraph extends BasePage { return await this.searchBarInput.inputValue(); } - async scrollToBottomInSearchBarList(): Promise { await this.searchBarList.evaluate((element) => { element.scrollTop = element.scrollHeight; @@ -279,7 +286,7 @@ export default class CodeGraph extends BasePage { } /* Canvas functionality */ - + async getCanvasAnalysis(): Promise { await delay(2000); return await analyzeCanvasWithLocator(this.canvasElement); @@ -307,5 +314,12 @@ export default class CodeGraph extends BasePage { const adjustedY = boundingBox.y + Math.round(y); await this.page.mouse.click(adjustedX, adjustedY, { button: 'right' }); } - + + async selectCodeGraphCheckbox(checkbox: string): Promise { + await this.codeGraphCheckbox(checkbox).click(); + } + + async clickOnClearGraphBtn(): Promise { + await this.clearGraphBtn.click(); + } } diff --git a/e2e/tests/codeGraph.spec.ts b/e2e/tests/codeGraph.spec.ts index f2eaa60f..de29cb9f 100644 --- a/e2e/tests/codeGraph.spec.ts +++ b/e2e/tests/codeGraph.spec.ts @@ -2,7 +2,7 @@ import { test, expect } from "@playwright/test"; import BrowserWrapper from "../infra/ui/browserWrapper"; import CodeGraph from "../logic/POM/codeGraph"; import urls from "../config/urls.json"; -import { GRAPH_ID } from "../config/constants"; +import { GRAPH_ID, Node_Add_Edge, Node_Import_Data } from "../config/constants"; import { delay } from "../logic/utils"; import { searchData, specialCharacters } from "../config/testData"; import { CanvasAnalysisResult } from "../logic/canvasAnalysis"; @@ -126,4 +126,30 @@ test.describe("Code graph tests", () => { expect(initialNodeAnalysis.red.length).toBeGreaterThan(updatedNodeAnalysis.red.length); }); + colors.forEach((color, index) => { + const checkboxIndex = index + 1; + test(`Verify that unchecking the ${color} checkbox hides ${color} nodes on the canvas`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + await codeGraph.selectCodeGraphCheckbox(checkboxIndex.toString()); + const result = await codeGraph.getCanvasAnalysis(); + expect(result[color].length).toBe(0); + }); + }) + + test(`Verify "Clear graph" button resets canvas view`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + const initialAnalysis = await codeGraph.getCanvasAnalysis(); + const initialNodeCount = initialAnalysis.green.length + initialAnalysis.yellow.length + initialAnalysis.red.length; + await codeGraph.clickOnshowPathBtn(); + await codeGraph.insertInputForShowPath("1", Node_Import_Data); + await codeGraph.insertInputForShowPath("2", Node_Add_Edge); + await codeGraph.clickOnClearGraphBtn(); + const finalAnalysis = await codeGraph.getCanvasAnalysis(); + const finalNodeCount = finalAnalysis.green.length + finalAnalysis.yellow.length + finalAnalysis.red.length; + expect(initialNodeCount).toBe(finalNodeCount); + + }); + }); From a4f60a9af1b0a3b1888830f8594ff744607b511a Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Tue, 3 Dec 2024 17:40:09 +0200 Subject: [PATCH 2/9] tests (#265, #287, #288, #289) --- app/components/chat.tsx | 2 +- e2e/logic/POM/codeGraph.ts | 72 +++++++++++++++++++++++++++++++++++++ e2e/tests/chat.spec.ts | 16 +++++++-- e2e/tests/codeGraph.spec.ts | 24 ++++++++++++- e2e/tests/navBar.spec.ts | 8 +++++ 5 files changed, 118 insertions(+), 4 deletions(-) diff --git a/app/components/chat.tsx b/app/components/chat.tsx index 80d55fb3..572feae1 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -498,7 +498,7 @@ export function Chat({ repo, path, setPath, graph, chartRef, selectedPathId, isP
- diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index e8479711..3db304da 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -21,6 +21,18 @@ export default class CodeGraph extends BasePage { return this.page.locator("//div[@role='dialog']") } + private get tipBtn(): Locator { + return this.page.locator("//button[@title='Tip']") + } + + private get genericMenu(): Locator { + return this.page.locator("//div[contains(@role, 'menu')]") + } + + private get tipMenuCloseBtn(): Locator { + return this.page.locator("//div[@role='menu']//button[@title='Close']") + } + /* CodeGraph Locators*/ private get comboBoxbtn(): Locator { return this.page.locator("//button[@role='combobox']") @@ -115,6 +127,22 @@ export default class CodeGraph extends BasePage { return this.page.locator("//div[@role='region']//ol//li"); } + private get notificationErrorCloseBtn(): Locator { + return this.page.locator("//div[@role='region']//ol//li/button"); + } + + private get questionOptionsMenu(): Locator { + return this.page.locator("//button[@data-name='questionOptionsMenu']"); + } + + private get selectQuestionInMenu(): (questionNumber: string) => Locator { + return (questionNumber: string) => this.page.locator(`//div[contains(@role, 'menu')]/button[${questionNumber}]`); + } + + private get lastQuestionInChat(): Locator { + return this.page.locator("//main[@data-name='main-chat']/*[last()-1]/p"); + } + /* Canvas Locators*/ private get canvasElement(): Locator { @@ -172,6 +200,18 @@ export default class CodeGraph extends BasePage { return await this.createNewProjectDialog.isVisible(); } + async clickonTipBtn(): Promise { + await this.tipBtn.click(); + } + + async isTipMenuVisible(): Promise { + return await this.genericMenu.isVisible(); + } + + async clickonTipMenuCloseBtn(): Promise { + await this.tipMenuCloseBtn.click(); + } + /* Chat functionality */ async clickOnshowPathBtn(): Promise { await this.showPathBtn.click(); @@ -232,9 +272,27 @@ export default class CodeGraph extends BasePage { } async isNotificationError(): Promise { + await delay(500); return await this.notificationError.isVisible(); } + async clickOnNotificationErrorCloseBtn(): Promise { + await this.notificationErrorCloseBtn.click(); + } + + async clickOnQuestionOptionsMenu(): Promise { + await this.questionOptionsMenu.click(); + } + + async selectAndGetQuestionInOptionsMenu(questionNumber: string): Promise { + await this.selectQuestionInMenu(questionNumber).click(); + return await this.selectQuestionInMenu(questionNumber).innerHTML(); + } + + async getLastQuestionInChat(): Promise { + return await this.lastQuestionInChat.innerText(); + } + /* CodeGraph functionality */ async selectGraph(graph: string): Promise { await this.comboBoxbtn.click(); @@ -322,4 +380,18 @@ export default class CodeGraph extends BasePage { async clickOnClearGraphBtn(): Promise { await this.clearGraphBtn.click(); } + + async changeNodePosition(x: number, y: number): Promise { + const box = (await this.canvasElement.boundingBox())!; + const targetX = x + 100; + const targetY = y + 50; + const absStartX = box.x + x; + const absStartY = box.y + y; + const absEndX = box.x + targetX; + const absEndY = box.y + targetY; + await this.page.mouse.move(absStartX, absStartY); + await this.page.mouse.down(); + await this.page.mouse.move(absEndX, absEndY); + await this.page.mouse.up(); + } } diff --git a/e2e/tests/chat.spec.ts b/e2e/tests/chat.spec.ts index 02e20253..81f47046 100644 --- a/e2e/tests/chat.spec.ts +++ b/e2e/tests/chat.spec.ts @@ -76,12 +76,24 @@ test.describe("Chat tests", () => { expect(await chat.isNotificationError()).toBe(true); }); - test("Validate error notification when sending an empty question in chat", async () => { + test("Validate error notification and its closure when sending an empty question in chat", async () => { const chat = await browser.createNewPage(CodeGraph, urls.baseUrl); await chat.selectGraph(GRAPH_ID); await chat.clickAskquestionBtn(); - await delay(500); expect(await chat.isNotificationError()).toBe(true); + await chat.clickOnNotificationErrorCloseBtn(); + expect(await chat.isNotificationError()).toBe(false); }); + + for (let index = 0; index < 5; index++) { + const questionNumber = index + 1; + test(`Validate displaying question ${index} in chat after selection from options menu`, async () => { + const chat = await browser.createNewPage(CodeGraph, urls.baseUrl); + await chat.selectGraph(GRAPH_ID); + await chat.clickOnQuestionOptionsMenu(); + const selectedQuestion = await chat.selectAndGetQuestionInOptionsMenu(questionNumber.toString()); + expect(selectedQuestion).toEqual(await chat.getLastQuestionInChat()) + }); + } }); diff --git a/e2e/tests/codeGraph.spec.ts b/e2e/tests/codeGraph.spec.ts index de29cb9f..4d6b0d6c 100644 --- a/e2e/tests/codeGraph.spec.ts +++ b/e2e/tests/codeGraph.spec.ts @@ -149,7 +149,29 @@ test.describe("Code graph tests", () => { const finalAnalysis = await codeGraph.getCanvasAnalysis(); const finalNodeCount = finalAnalysis.green.length + finalAnalysis.yellow.length + finalAnalysis.red.length; expect(initialNodeCount).toBe(finalNodeCount); - }); + for (let index = 0; index < 3; index++) { + const checkboxIndex = index + 1; + test(`Verify selecting different graphs displays nodes in canvas - Iteration ${index + 1}`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(checkboxIndex.toString()); + const result = await codeGraph.getCanvasAnalysis(); + const nodesLength = result.green.length + result.yellow.length + result.red.length; + expect(nodesLength).toBeGreaterThan(1); + }); + } + + colors.forEach((color) => { + test(`Validate canvas node dragging for color: ${color}`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + const initialAnalysis = await codeGraph.getCanvasAnalysis(); + await codeGraph.changeNodePosition(initialAnalysis[color][0].x, initialAnalysis[color][0].y); + const finalAnalysis = await codeGraph.getCanvasAnalysis(); + expect(finalAnalysis[color][0].x).not.toBe(initialAnalysis.green[0].x); + expect(finalAnalysis[color][0].y).not.toBe(initialAnalysis.green[0].y); + }); + }) + }); diff --git a/e2e/tests/navBar.spec.ts b/e2e/tests/navBar.spec.ts index b6706cbf..9f294a75 100644 --- a/e2e/tests/navBar.spec.ts +++ b/e2e/tests/navBar.spec.ts @@ -38,4 +38,12 @@ test.describe(' Navbar tests', () => { await navBar.clickCreateNewProjectBtn(); expect(await navBar.isCreateNewProjectDialog()).toBe(true) }) + + test("Validate Tip popup visibility and closure functionality", async () => { + const navBar = await browser.createNewPage(CodeGraph, urls.baseUrl); + await navBar.clickonTipBtn(); + expect(await navBar.isTipMenuVisible()).toBe(true); + await navBar.clickonTipMenuCloseBtn(); + expect(await navBar.isTipMenuVisible()).toBe(false); + }); }); From 8f8d8ee46982f0d1a48276c7af82d68d1dd817b8 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Tue, 3 Dec 2024 18:11:26 +0200 Subject: [PATCH 3/9] test update & workers - adding delay for tip popup dismissal - update node drag test for correct validation - increase playwright workers number --- e2e/logic/POM/codeGraph.ts | 1 + e2e/tests/codeGraph.spec.ts | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 3db304da..47d39827 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -205,6 +205,7 @@ export default class CodeGraph extends BasePage { } async isTipMenuVisible(): Promise { + await delay(500); return await this.genericMenu.isVisible(); } diff --git a/e2e/tests/codeGraph.spec.ts b/e2e/tests/codeGraph.spec.ts index 4d6b0d6c..b4583819 100644 --- a/e2e/tests/codeGraph.spec.ts +++ b/e2e/tests/codeGraph.spec.ts @@ -169,8 +169,8 @@ test.describe("Code graph tests", () => { const initialAnalysis = await codeGraph.getCanvasAnalysis(); await codeGraph.changeNodePosition(initialAnalysis[color][0].x, initialAnalysis[color][0].y); const finalAnalysis = await codeGraph.getCanvasAnalysis(); - expect(finalAnalysis[color][0].x).not.toBe(initialAnalysis.green[0].x); - expect(finalAnalysis[color][0].y).not.toBe(initialAnalysis.green[0].y); + expect(finalAnalysis[color][0].x).not.toBe(initialAnalysis[color][0].x); + expect(finalAnalysis[color][0].y).not.toBe(initialAnalysis[color][0].y); }); }) From 15b8f3aa77752b7845cb6199ed4601c46bdad85c Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Mon, 9 Dec 2024 10:00:17 +0200 Subject: [PATCH 4/9] tests (#307, #306, #305, #263, #266) - Update codeGraph Locators - Update code graph workers - Update projectInfo api call --- app/components/code-graph.tsx | 4 +- app/components/dataPanel.tsx | 2 +- e2e/config/constants.ts | 2 +- e2e/logic/POM/codeGraph.ts | 44 +++- e2e/logic/api/apiCalls.ts | 4 +- e2e/tests/chat.spec.ts | 26 +++ e2e/tests/codeGraph.spec.ts | 394 +++++++++++++++++++++------------- playwright.config.ts | 2 +- 8 files changed, 318 insertions(+), 160 deletions(-) diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index 7034a6a7..d125e795 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -432,8 +432,8 @@ export function CodeGraph({ } -
-
+
+

{nodesCount} Nodes

{edgesCount} Edges

diff --git a/app/components/dataPanel.tsx b/app/components/dataPanel.tsx index b38d40a5..e8c0da38 100644 --- a/app/components/dataPanel.tsx +++ b/app/components/dataPanel.tsx @@ -36,7 +36,7 @@ export default function DataPanel({ obj, setObj, url }: Props) { const object = Object.entries(obj).filter(([k]) => !excludedProperties.includes(k)) return ( -
+

{label.toUpperCase()}