chore: Cypress - add pane interactions (#32091)
## Description Added cypress test for add pane interactions. Fixes #31868 ## Automation /ok-to-test tags="@tag.All" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!CAUTION] > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/8504922496> > Commit: `0c74a26f4c959c84bf308876e4c0740e0c45ca90` > Cypress dashboard: <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=8504922496&attempt=1&selectiontype=test&testsstatus=failed&specsstatus=fail" target="_blank"> Click here!</a> > The following are new failures, please fix them before merging the PR: <ol> > <li>cypress/e2e/Regression/ClientSide/AppNavigation/AppNavigationWithMultiplePages_spec.ts </ol> > To know the list of identified flaky tests - <a href="https://internal.appsmith.com/app/cypress-dashboard/identified-flaky-tests-65890b3c81d7400d08fa9ee3?branch=master" target="_blank">Refer here</a> <!-- end of auto-generated comment: Cypress test results --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced test cases for adding panes in the IDE, covering various tab interactions. - Added the ability to switch between full screen and split screen modes in the IDE. - **Tests** - Added a new Cypress custom command for easier test maintenance. - **Refactor** - Enhanced testability by adding `data-testid` attributes across various IDE components for improved element selection in tests. - Improved code clarity through reorganization and reformatting of component properties. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Hetu Nandu <hetunandu@gmail.com>
This commit is contained in:
parent
a38f7fbb5f
commit
834c0f8280
|
|
@ -0,0 +1,106 @@
|
|||
import EditorNavigation, {
|
||||
EditorViewMode,
|
||||
PageLeftPane,
|
||||
PagePaneSegment,
|
||||
} from "../../../../support/Pages/EditorNavigation";
|
||||
import { ObjectsRegistry } from "../../../../support/Objects/Registry";
|
||||
import FileTabs from "../../../../support/Pages/IDE/FileTabs";
|
||||
|
||||
const agHelper = ObjectsRegistry.AggregateHelper;
|
||||
const commonLocators = ObjectsRegistry.CommonLocators;
|
||||
|
||||
describe("IDE add pane interactions", { tags: ["@tag.IDE"] }, () => {
|
||||
it("1. UI tab add interactions", () => {
|
||||
// check add pane is open
|
||||
PageLeftPane.assertInAddView();
|
||||
// close add pane to show blank state
|
||||
PageLeftPane.closeAddView();
|
||||
// click on add button and check add state
|
||||
PageLeftPane.switchToAddNew();
|
||||
// check add pane
|
||||
PageLeftPane.assertInAddView();
|
||||
// drag and drop a widget and list view should be opened
|
||||
cy.dragAndDropToCanvas("textwidget", { x: 300, y: 200 });
|
||||
// check listing ui
|
||||
PageLeftPane.selectedItem().contains("Text1");
|
||||
// click add button
|
||||
PageLeftPane.switchToAddNew();
|
||||
// check add pane is open
|
||||
PageLeftPane.assertInAddView();
|
||||
// close add pane
|
||||
PageLeftPane.closeAddView();
|
||||
// click on canvas and check add pane visible or not
|
||||
agHelper.GetNClick(commonLocators._canvas).click();
|
||||
// check add pane
|
||||
PageLeftPane.assertInAddView();
|
||||
});
|
||||
|
||||
it("2. JS tab add interactions", () => {
|
||||
/** Fullscreen */
|
||||
// switch to JS tab from UI
|
||||
PageLeftPane.switchSegment(PagePaneSegment.JS);
|
||||
// check and click on blank state add button
|
||||
PageLeftPane.switchToAddNew();
|
||||
// check listing UI
|
||||
PageLeftPane.assertInListView();
|
||||
// click on add btn in the listing UI
|
||||
PageLeftPane.switchToAddNew();
|
||||
// check item got added or not
|
||||
PageLeftPane.assertInListView();
|
||||
PageLeftPane.assertItemCount(2);
|
||||
/** Splitscreen */
|
||||
// switch to splitscreen
|
||||
EditorNavigation.SwitchScreenMode(EditorViewMode.SplitScreen);
|
||||
// click on add
|
||||
FileTabs.switchToAddNew();
|
||||
// check tabs count to verify js added or not
|
||||
FileTabs.assertTabCount(3);
|
||||
// switch back to full screen
|
||||
EditorNavigation.SwitchScreenMode(EditorViewMode.FullScreen);
|
||||
// delete all js objects and check add screen
|
||||
cy.get(".editor-tab").each(($ele) => {
|
||||
cy.selectByTestId("more-action-trigger").click();
|
||||
cy.get(".t--apiFormDeleteBtn").click();
|
||||
cy.get(".t--apiFormDeleteBtn").click();
|
||||
});
|
||||
PageLeftPane.assertInAddView();
|
||||
});
|
||||
|
||||
it("3. Queries tab add interactions", () => {
|
||||
/** Fullscreen */
|
||||
// switch to Query tab from JS
|
||||
PageLeftPane.switchSegment(PagePaneSegment.Queries);
|
||||
// check and click on blank state add button
|
||||
PageLeftPane.switchToAddNew();
|
||||
// check add pane
|
||||
PageLeftPane.assertInAddView();
|
||||
// close add pane
|
||||
PageLeftPane.closeAddView();
|
||||
// open add pane to add item
|
||||
PageLeftPane.switchToAddNew();
|
||||
// add item
|
||||
cy.get(".t--new-blank-api").children("div").first().click();
|
||||
// check item added or not
|
||||
PageLeftPane.assertPresence("Api1");
|
||||
/** Splitscreen */
|
||||
// switch to splitscreen
|
||||
EditorNavigation.SwitchScreenMode(EditorViewMode.SplitScreen);
|
||||
// click on add
|
||||
FileTabs.switchToAddNew();
|
||||
// check add pane
|
||||
PageLeftPane.assertInAddView();
|
||||
// add item
|
||||
cy.get(".t--new-blank-api").children("div").first().click();
|
||||
// check tabs count to verify js added or not
|
||||
FileTabs.assertTabCount(2);
|
||||
// switch back to full screen
|
||||
EditorNavigation.SwitchScreenMode(EditorViewMode.FullScreen);
|
||||
// delete all queries and check add screen
|
||||
cy.get(".editor-tab").each(($ele) => {
|
||||
cy.selectByTestId("more-action-trigger").click();
|
||||
cy.get(".t--apiFormDeleteBtn").click();
|
||||
cy.get(".t--apiFormDeleteBtn").click();
|
||||
});
|
||||
PageLeftPane.assertInAddView();
|
||||
});
|
||||
});
|
||||
|
|
@ -19,6 +19,11 @@ export enum PagePaneSegment {
|
|||
JS = "JS",
|
||||
}
|
||||
|
||||
export enum EditorViewMode {
|
||||
FullScreen = "FullScreen",
|
||||
SplitScreen = "SplitScreen",
|
||||
}
|
||||
|
||||
const pagePaneListItemSelector = (name: string) =>
|
||||
"//div[contains(@class, 't--entity-name')][text()='" + name + "']";
|
||||
|
||||
|
|
@ -38,6 +43,12 @@ export enum EntityType {
|
|||
Page = "Page",
|
||||
}
|
||||
class EditorNavigation {
|
||||
public locators = {
|
||||
MaximizeBtn: "[data-testid='t--ide-maximize']",
|
||||
MinimizeBtn: "[data-testid='t--ide-minimize']",
|
||||
announcementCloseButton: "[data-testid='t--ide-close-announcement']",
|
||||
};
|
||||
|
||||
NavigateToDatasource(name: string) {
|
||||
AppSidebar.navigate(AppSidebarButton.Data);
|
||||
cy.get(datasource.datasourceCard)
|
||||
|
|
@ -119,6 +130,23 @@ class EditorNavigation {
|
|||
AppSidebar.navigate(AppSidebarButton.Editor);
|
||||
PageLeftPane.switchSegment(PagePaneSegment.UI);
|
||||
}
|
||||
|
||||
SwitchScreenMode(mode: EditorViewMode) {
|
||||
if (mode === EditorViewMode.FullScreen) {
|
||||
_.AggregateHelper.GetNClick(this.locators.MaximizeBtn);
|
||||
} else {
|
||||
_.AggregateHelper.GetNClick(this.locators.MinimizeBtn);
|
||||
cy.get("body").then(($body) => {
|
||||
if ($body.find(this.locators.announcementCloseButton).length > 0) {
|
||||
_.AggregateHelper.GetNClick(
|
||||
this.locators.announcementCloseButton,
|
||||
0,
|
||||
true,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new EditorNavigation();
|
||||
|
|
|
|||
28
app/client/cypress/support/Pages/IDE/AddView.ts
Normal file
28
app/client/cypress/support/Pages/IDE/AddView.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import { ObjectsRegistry } from "../../Objects/Registry";
|
||||
|
||||
class AddView {
|
||||
public locators = {
|
||||
closePaneButton: "[data-testid='t--add-pane-close-icon']",
|
||||
createOption: "[data-testid='t--create-option']",
|
||||
};
|
||||
|
||||
constructor() {
|
||||
//
|
||||
}
|
||||
|
||||
public assertInAddView() {
|
||||
ObjectsRegistry.AggregateHelper.AssertElementVisibility(
|
||||
this.locators.closePaneButton,
|
||||
);
|
||||
}
|
||||
|
||||
public closeAddView() {
|
||||
ObjectsRegistry.AggregateHelper.GetNClick(this.locators.closePaneButton);
|
||||
}
|
||||
|
||||
public getCreateOptions(): Cypress.Chainable {
|
||||
return cy.get(this.locators.createOption);
|
||||
}
|
||||
}
|
||||
|
||||
export default AddView;
|
||||
37
app/client/cypress/support/Pages/IDE/FileTabs.ts
Normal file
37
app/client/cypress/support/Pages/IDE/FileTabs.ts
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import { ObjectsRegistry } from "../../Objects/Registry";
|
||||
class FileTabs {
|
||||
locators = {
|
||||
container: "[data-testid='t--editor-tabs']",
|
||||
tabName: (name: string) => `[data-testid='t--ide-tab-${name}']`,
|
||||
tabs: ".editor-tab",
|
||||
addItem: "[data-testid='t--ide-split-screen-add-button']",
|
||||
};
|
||||
|
||||
assertVisibility() {
|
||||
ObjectsRegistry.AggregateHelper.AssertElementVisibility(
|
||||
this.locators.container,
|
||||
);
|
||||
}
|
||||
|
||||
assertTabCount(count: number) {
|
||||
ObjectsRegistry.AggregateHelper.GetElement(this.locators.tabs).should(
|
||||
"have.length",
|
||||
count,
|
||||
);
|
||||
}
|
||||
|
||||
switchToAddNew() {
|
||||
// for js it will directly add a new file
|
||||
cy.get("body").then(($body) => {
|
||||
if ($body.find(this.locators.addItem).length > 0) {
|
||||
ObjectsRegistry.AggregateHelper.GetNClick(
|
||||
this.locators.addItem,
|
||||
0,
|
||||
true,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new FileTabs();
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
import { ObjectsRegistry } from "../../Objects/Registry";
|
||||
import AddView from "./AddView";
|
||||
import ListView from "./ListView";
|
||||
|
||||
export class LeftPane {
|
||||
segments?: string[];
|
||||
|
|
@ -10,11 +12,13 @@ export class LeftPane {
|
|||
"//div[text()='" +
|
||||
name +
|
||||
"']/ancestor::div/span[contains(@class, 't--entity-collapse-toggle')]",
|
||||
addItem: "button.t--add-item",
|
||||
activeItemSelector: "",
|
||||
selector: "",
|
||||
};
|
||||
|
||||
private addView: AddView;
|
||||
private listView: ListView;
|
||||
|
||||
constructor(
|
||||
listItemSelector: (name: string) => string,
|
||||
selector: string,
|
||||
|
|
@ -25,6 +29,8 @@ export class LeftPane {
|
|||
this.segments = segments;
|
||||
this.locators.selector = selector;
|
||||
this.locators.activeItemSelector = activeItemSelector;
|
||||
this.addView = new AddView();
|
||||
this.listView = new ListView();
|
||||
}
|
||||
|
||||
public assertAbsence(name: string) {
|
||||
|
|
@ -96,15 +102,26 @@ export class LeftPane {
|
|||
}
|
||||
|
||||
public switchToAddNew() {
|
||||
// for js it will directly add a new file
|
||||
cy.get("body").then(($body) => {
|
||||
if ($body.find(this.locators.addItem).length > 0) {
|
||||
ObjectsRegistry.AggregateHelper.GetNClick(
|
||||
this.locators.addItem,
|
||||
0,
|
||||
true,
|
||||
);
|
||||
}
|
||||
});
|
||||
this.listView.switchToAddNew();
|
||||
}
|
||||
|
||||
public assertInAddView() {
|
||||
this.addView.assertInAddView();
|
||||
}
|
||||
|
||||
public closeAddView() {
|
||||
this.addView.closeAddView();
|
||||
}
|
||||
|
||||
public getCreateOptions() {
|
||||
return this.addView.getCreateOptions();
|
||||
}
|
||||
|
||||
public assertInListView() {
|
||||
this.listView.assertListVisibility();
|
||||
}
|
||||
|
||||
public assertItemCount(count: number) {
|
||||
this.listView.assertItemCount(count);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
47
app/client/cypress/support/Pages/IDE/ListView.ts
Normal file
47
app/client/cypress/support/Pages/IDE/ListView.ts
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
import { ObjectsRegistry } from "../../Objects/Registry";
|
||||
|
||||
class ListView {
|
||||
public locators = {
|
||||
list: "[data-testid='t--ide-list']",
|
||||
listItem: "[data-testid='t--ide-list-item']",
|
||||
addItem: "button.t--add-item",
|
||||
};
|
||||
|
||||
public assertListVisibility() {
|
||||
ObjectsRegistry.AggregateHelper.AssertElementVisibility(this.locators.list);
|
||||
}
|
||||
|
||||
public assertItemVisibility(name: string) {
|
||||
ObjectsRegistry.AggregateHelper.GetNAssertElementText(
|
||||
this.locators.listItem,
|
||||
name,
|
||||
);
|
||||
}
|
||||
|
||||
public getItem(name: string) {
|
||||
return ObjectsRegistry.AggregateHelper.GetElement(
|
||||
this.locators.listItem,
|
||||
).should("have.text", name);
|
||||
}
|
||||
|
||||
public assertItemCount(count: number) {
|
||||
return ObjectsRegistry.AggregateHelper.GetElement(
|
||||
this.locators.listItem,
|
||||
).should("have.length", count);
|
||||
}
|
||||
|
||||
switchToAddNew() {
|
||||
// for js it will directly add a new file
|
||||
cy.get("body").then(($body) => {
|
||||
if ($body.find(this.locators.addItem).length > 0) {
|
||||
ObjectsRegistry.AggregateHelper.GetNClick(
|
||||
this.locators.addItem,
|
||||
0,
|
||||
true,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default ListView;
|
||||
|
|
@ -2077,3 +2077,16 @@ Cypress.Commands.add("stubPricingPage", () => {
|
|||
}).as("pricingPage");
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* @param testID
|
||||
* @returns
|
||||
*
|
||||
* This function act as a data-testid selector. In
|
||||
* any case it is decided to rename the data-testid,
|
||||
* it's thing single function that needs to be updated.
|
||||
*
|
||||
*/
|
||||
Cypress.Commands.add("selectByTestId", (testId) => {
|
||||
return cy.get(`[data-testid="${testId}"]`);
|
||||
});
|
||||
|
|
|
|||
1
app/client/cypress/support/index.d.ts
vendored
1
app/client/cypress/support/index.d.ts
vendored
|
|
@ -175,5 +175,6 @@ declare namespace Cypress {
|
|||
skipSignposting();
|
||||
stubPricingPage();
|
||||
validateEvaluatedValue(value: string);
|
||||
selectByTestId(value: string): Chainable<JQuery<HTMLElement>>;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ export interface JSListItemProps {
|
|||
export const JSListItem = (props: JSListItemProps) => {
|
||||
const { isActive, item, parentEntityId, parentEntityType } = props;
|
||||
return (
|
||||
<Flex flexDirection={"column"}>
|
||||
<Flex data-testid="t--ide-list-item" flexDirection={"column"}>
|
||||
<ExplorerJSCollectionEntity
|
||||
id={item.key}
|
||||
isActive={isActive}
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ const ListJSObjects = () => {
|
|||
parentEntityType={ActionParentEntityType.PAGE}
|
||||
>
|
||||
<Flex
|
||||
data-testid="t--ide-list"
|
||||
flex="1"
|
||||
flexDirection="column"
|
||||
gap="spaces-4"
|
||||
|
|
|
|||
|
|
@ -81,7 +81,13 @@ const ListWidgets = () => {
|
|||
</Flex>
|
||||
) : null}
|
||||
{widgetsExist ? (
|
||||
<Flex flex="1" flexDirection={"column"} overflowY="auto" px="spaces-3">
|
||||
<Flex
|
||||
data-testid="t--ide-list"
|
||||
flex="1"
|
||||
flexDirection={"column"}
|
||||
overflowY="auto"
|
||||
px="spaces-3"
|
||||
>
|
||||
{widgets?.children?.map((child) => (
|
||||
<WidgetEntity
|
||||
childWidgets={child.children}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,12 @@ const Announcement = () => {
|
|||
|
||||
const modalFooter = () => (
|
||||
<>
|
||||
<Button kind="primary" onClick={tryClickHandler} size="md">
|
||||
<Button
|
||||
data-testid="t--ide-close-announcement"
|
||||
kind="primary"
|
||||
onClick={tryClickHandler}
|
||||
size="md"
|
||||
>
|
||||
Try it out
|
||||
</Button>
|
||||
<Button kind="tertiary" onClick={learnClickHandler} size="md">
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ const SegmentAddHeader = (props: Props) => {
|
|||
</Text>
|
||||
<Button
|
||||
aria-label="Close pane"
|
||||
data-testid="t--widget-add-pane-close-icon"
|
||||
data-testid="t--add-pane-close-icon"
|
||||
isIconButton
|
||||
kind={"tertiary"}
|
||||
onClick={props.onCloseClick}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user