From 213db55dd9a5dde455f6592c2df4ab27fb48abd1 Mon Sep 17 00:00:00 2001 From: shadabbuchh Date: Thu, 30 Jan 2025 14:31:20 +0530 Subject: [PATCH] test: Editor tests for renaming, copying, moving, and deleting APIs (#38896) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description This PR adds set of tests for API-related operations in the editor, including renaming, copying, moving, and validating tab behaviors triggered from debugger logs. ## Automation /ok-to-test tags="@tag.Datasource, @tag.Git, @tag.Sanity" ### :mag: Cypress test results > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: > Commit: 09e39298b5dc0d2f6e12057ac88954a967908458 > Cypress dashboard. > Tags: `@tag.Datasource, @tag.Git, @tag.Sanity` > Spec: >
Thu, 30 Jan 2025 08:38:58 UTC ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [x] No ## Summary by CodeRabbit ## Release Notes - **New Features** - Enhanced API management testing capabilities - Added support for renaming, copying, and moving APIs - Improved log-based tab navigation and reopening functionality - **Tests** - Introduced comprehensive test suite for API operations - Added test cases for API renaming, copying, moving, and deletion - Implemented log-based tab interaction tests These updates improve the testing infrastructure and validate key API management features in the application. --- .../ApiTests/API_Additional_Tests_spec.ts | 82 ++++++++++++++ app/client/cypress/support/Pages/ApiPage.ts | 101 +++++++++++++++++- app/client/cypress/support/Pages/PageList.ts | 1 + 3 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 app/client/cypress/e2e/Regression/ServerSide/ApiTests/API_Additional_Tests_spec.ts diff --git a/app/client/cypress/e2e/Regression/ServerSide/ApiTests/API_Additional_Tests_spec.ts b/app/client/cypress/e2e/Regression/ServerSide/ApiTests/API_Additional_Tests_spec.ts new file mode 100644 index 000000000000..3c08da808cf0 --- /dev/null +++ b/app/client/cypress/e2e/Regression/ServerSide/ApiTests/API_Additional_Tests_spec.ts @@ -0,0 +1,82 @@ +import { + agHelper, + debuggerHelper, + homePage, +} from "../../../../support/Objects/ObjectsCore"; +import { apiPage } from "../../../../support/Objects/ObjectsCore"; +import { + PageLeftPane, + PagePaneSegment, +} from "../../../../support/Pages/EditorNavigation"; +import FileTabs from "../../../../support/Pages/IDE/FileTabs"; +import PageList from "../../../../support/Pages/PageList"; + +describe( + "Additional API tests", + { tags: ["@tag.Datasource", "@tag.Git"] }, + () => { + it("1. Validate renaming & copying API from editor", () => { + // Create first API + apiPage.CreateApi(); + // Rename the API + apiPage.renameFromEditor("changedName"); + // Create second API + apiPage.CreateApi("secondApi", "GET"); + // Add a new blank page to the application + PageList.AddNewPage("New blank page"); + // Copy the API to the same page + apiPage.performActionFromEditor("copy", "changedName", "Page1", "Page1"); + // Copy the API to a different page + apiPage.performActionFromEditor("copy", "secondApi", "Page1", "Page2"); + }); + + it("2. Validate moving & deleting API from editor", () => { + // Create a new application + homePage.NavigateToHome(); + homePage.CreateNewApplication(); + // Create first API + apiPage.CreateApi("ApiToBeMoved", "GET"); + apiPage.CreateApi("ApiNotToBeMoved", "GET"); + // Having only one page in the app, check if the API is moved to the same page + apiPage.performActionFromEditor("move", "ApiToBeMoved", "Page1", "Page1"); + // Add a new blank page to the application + PageList.AddNewPage("New blank page"); + // Move the API to a different page & check if the source page does not have the API anymore + apiPage.performActionFromEditor("move", "ApiToBeMoved", "Page1", "Page2"); + apiPage.performActionFromEditor("move", "ApiToBeMoved", "Page2", "Page1"); + apiPage.deleteAPIFromEditor("ApiToBeMoved", "Page1"); + }); + + it("3. Validate whether correct tab opens up after clicking on link from logs", () => { + // Create a new application + homePage.NavigateToHome(); + homePage.CreateNewApplication(); + for (let i = 0; i < 4; i++) { + apiPage.CreateApi(``, "GET"); + } + debuggerHelper.OpenDebugger(); + //Navigate to the "Logs" tab in the debugger + debuggerHelper.ClickLogsTab(); + // Click on the entity link in the log entry at index 2 + debuggerHelper.ClicklogEntityLink(false, 2); + // Assert that the correct tab ("Api3") opens + agHelper.AssertClassExists(FileTabs.locators.tabName("Api3"), "active"); + }); + + it("4. Validate whether closed tab opens up after clicking on link from logs", () => { + // Close all the tabs (Api1 to Api4) + for (let i = 1; i < 5; i++) { + FileTabs.closeTab(`Api${i}`); + } + // Switch to the "UI" segment in the page left pane + PageLeftPane.switchSegment(PagePaneSegment.UI); + debuggerHelper.OpenDebugger(); + // Navigate to the "Logs" tab in the debugger + debuggerHelper.ClickLogsTab(); + // Click on the entity link in the log entry at index 1 + debuggerHelper.ClicklogEntityLink(false, 1); + // Assert that the correct tab ("Api2") reopens + agHelper.AssertClassExists(FileTabs.locators.tabName("Api2"), "active"); + }); + }, +); diff --git a/app/client/cypress/support/Pages/ApiPage.ts b/app/client/cypress/support/Pages/ApiPage.ts index a29e45df1359..2ee47618bd7c 100644 --- a/app/client/cypress/support/Pages/ApiPage.ts +++ b/app/client/cypress/support/Pages/ApiPage.ts @@ -1,5 +1,5 @@ import { ObjectsRegistry } from "../Objects/Registry"; -import { +import EditorNavigation, { AppSidebar, AppSidebarButton, PageLeftPane, @@ -9,6 +9,8 @@ import * as _ from "../Objects/ObjectsCore"; import ApiEditor from "../../locators/ApiEditor"; import { PluginActionForm } from "./PluginActionForm"; import BottomTabs from "./IDE/BottomTabs"; +import PageList from "./PageList"; +import FileTabs from "./IDE/FileTabs"; type RightPaneTabs = "datasources" | "connections"; @@ -102,6 +104,9 @@ export class ApiPage { "input[name^='execute-on-page-load'][type='checkbox']"; public settingsTriggerLocator = "[data-testid='t--js-settings-trigger']"; public splitPaneContextMenuTrigger = ".entity-context-menu"; + public moreActionsTrigger = "[data-testid='t--more-action-trigger']"; + private apiNameInput = ".editor-tab.active > .ads-v2-text input"; + public pageList = ".ads-v2-sub-menu > .ads-v2-menu__menu-item"; CreateApi( apiName = "", @@ -509,4 +514,98 @@ export class ApiPage { if (enable) this.agHelper.CheckUncheck(this.runOnPageLoadJSObject, true); else this.agHelper.CheckUncheck(this.runOnPageLoadJSObject, false); } + + public renameFromEditor(renameVal: string) { + cy.get(this.moreActionsTrigger).click(); + cy.contains("Rename").should("be.visible").click(); + + cy.get(this.apiNameInput).clear().type(renameVal, { force: true }).blur(); + + PageLeftPane.assertPresence(renameVal); + } + + public performActionFromEditor( + action: "copy" | "move", + apiName: string, + sourcePage: string, + targetPage: string, + ) { + // Navigate to the source page and select the API item + EditorNavigation.NavigateToPage(sourcePage); + PageLeftPane.selectItem(apiName); + this.agHelper.AssertClassExists( + FileTabs.locators.tabName(apiName), + "active", + ); + + PageList.ShowList(); + cy.get(PageList.numberOfPages).then(($el) => { + // Open the 'More Actions' menu and select the action + cy.get(this.moreActionsTrigger).should("be.visible").click(); // Open the 'More Actions' dropdown + cy.contains(action === "copy" ? "Copy to page" : "Move to page") + .should("be.visible") + .trigger("click", { force: true }); + if (action === "move" && $el.text().includes("All Pages (1)")) { + // Handle case where the target page list is empty during move operation + cy.get(this.pageList).should("have.text", "No pages"); + } else if (action === "move" && /All Pages \(\d+\)/.test($el.text())) { + cy.get(this.pageList) + .should("be.visible") + .should("not.have.text", sourcePage) + .contains(targetPage) + .should("be.visible") + .trigger("click", { force: true }); + + this.agHelper.ValidateToastMessage( + apiName + " action moved to page " + targetPage + " successfully", + ); + PageList.VerifyIsCurrentPage(targetPage); // Verify the target page is active + PageLeftPane.assertPresence(apiName); // Assert the API is present on the target page + EditorNavigation.NavigateToPage(sourcePage); + PageLeftPane.assertAbsence(apiName); // Assert the API is removed from the source page + } else { + // Select the target page from the page list + cy.get(this.pageList) + .should("be.visible") + .contains(targetPage) + .should("be.visible") + .trigger("click", { force: true }); + + // Validate the toast message and the current page + this.agHelper.ValidateToastMessage( + `${apiName} action ${action === "copy" ? "copied" : "moved"} to page ${targetPage} successfully`, + ); + PageList.VerifyIsCurrentPage(targetPage); // Verify the target page is active + + // Assert the presence of the API on the target page + apiName = + action === "copy" && sourcePage === targetPage + ? `${apiName}Copy` + : apiName; + PageLeftPane.assertPresence(apiName); + + if (action === "move") { + EditorNavigation.NavigateToPage(sourcePage); + PageLeftPane.assertAbsence(apiName); // Assert the API is removed from the source page + } + } + }); + } + + public deleteAPIFromEditor(apiName: string, sourcePage: string) { + // Navigate to the source page and select the API item + EditorNavigation.NavigateToPage(sourcePage); + PageLeftPane.selectItem(apiName); + this.agHelper.AssertClassExists( + FileTabs.locators.tabName(apiName), + "active", + ); + + this.agHelper.GetNClick(this.moreActionsTrigger); + this.agHelper.ContainsNClick("Delete", 0, true); + this.agHelper.ContainsNClick("Are you sure?", 0, true); + + // Validate the absence of the API from the source page + PageLeftPane.assertAbsence(apiName); + } } diff --git a/app/client/cypress/support/Pages/PageList.ts b/app/client/cypress/support/Pages/PageList.ts index 5dc58e20e17e..5d48942cf12f 100644 --- a/app/client/cypress/support/Pages/PageList.ts +++ b/app/client/cypress/support/Pages/PageList.ts @@ -16,6 +16,7 @@ class PageList { }; public DefaultPageName = PAGE_ENTITY_NAME + "1"; + public numberOfPages = `.pages > .ads-v2-text`; public AddNewPage( option: