## Description Refactored getUnevaluatedDataTree selector to be more resilient to state changes thereby reselect cache gets triggered less often. Identified an action which was firing the selectors unnecessarily, fixed that as well. For our customer during page load it used to take about 800ms cumulatively, it has now dropped to about 160ms by about 80%. This is also an impactful selector which cumulatively takes about 50,000 seconds for all our client systems per week, hence we focussed our optimisation here ## Automation /ok-to-test tags="@tag.All" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/11658078700> > Commit: 557172d47b2232800355e1dc78c921d9cb56c725 > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=11658078700&attempt=2" target="_blank">Cypress dashboard</a>. > Tags: `@tag.All` > Spec: > <hr>Mon, 04 Nov 2024 06:00:06 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary by CodeRabbit - **Bug Fixes** - Improved state management by preventing unnecessary updates to loading entities, enhancing app performance. - **Refactor** - Updated the `loadingEntitiesReducer` to include an equality check for loading entities before state updates. - Enhanced date handling capabilities in the DatePicker widget tests and commands. - Restructured the `DataTreeFactory` class for improved modularity and clarity in data tree creation. - Simplified selector functions for better readability and maintainability in data tree selectors. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1380 lines
44 KiB
JavaScript
1380 lines
44 KiB
JavaScript
/* eslint-disable cypress/no-unnecessary-waiting */
|
|
/* eslint-disable cypress/no-assigning-return-values */
|
|
/* This file is used to maintain comman methods across tests , refer other *.js files for adding common methods */
|
|
import { ANVIL_EDITOR_TEST } from "./Constants.js";
|
|
import advancedFormat from "dayjs/plugin/advancedFormat";
|
|
|
|
import EditorNavigation, {
|
|
EntityType,
|
|
AppSidebar,
|
|
PageLeftPane,
|
|
PagePaneSegment,
|
|
} from "./Pages/EditorNavigation";
|
|
|
|
require("cy-verify-downloads").addCustomCommand();
|
|
require("cypress-file-upload");
|
|
const path = require("path");
|
|
import { v4 as uuidv4 } from "uuid";
|
|
|
|
const dayjs = require("dayjs");
|
|
const loginPage = require("../locators/LoginPage.json");
|
|
import homePage from "../locators/HomePage";
|
|
dayjs.extend(advancedFormat);
|
|
|
|
const commonlocators = require("../locators/commonlocators.json");
|
|
const widgetsPage = require("../locators/Widgets.json");
|
|
import ApiEditor from "../locators/ApiEditor";
|
|
import { CURRENT_REPO, REPO } from "../fixtures/REPO";
|
|
|
|
const apiwidget = require("../locators/apiWidgetslocator.json");
|
|
const explorer = require("../locators/explorerlocators.json");
|
|
const datasource = require("../locators/DatasourcesEditor.json");
|
|
const jsEditorLocators = require("../locators/JSEditor.json");
|
|
const queryLocators = require("../locators/QueryEditor.json");
|
|
const welcomePage = require("../locators/welcomePage.json");
|
|
import { ObjectsRegistry } from "../support/Objects/Registry";
|
|
import RapidMode from "./RapidMode";
|
|
import { featureFlagIntercept } from "./Objects/FeatureFlags";
|
|
|
|
const propPane = ObjectsRegistry.PropertyPane;
|
|
const agHelper = ObjectsRegistry.AggregateHelper;
|
|
const locators = ObjectsRegistry.CommonLocators;
|
|
const onboarding = ObjectsRegistry.Onboarding;
|
|
const apiPage = ObjectsRegistry.ApiPage;
|
|
const deployMode = ObjectsRegistry.DeployMode;
|
|
const assertHelper = ObjectsRegistry.AssertHelper;
|
|
const homePageTS = ObjectsRegistry.HomePage;
|
|
const table = ObjectsRegistry.Table;
|
|
|
|
const chainStart = Symbol();
|
|
|
|
export const initLocalstorage = () => {
|
|
cy.window().then((window) => {
|
|
window.localStorage.setItem("ShowCommentsButtonToolTip", "");
|
|
window.localStorage.setItem("updateDismissed", "true");
|
|
});
|
|
};
|
|
|
|
export const addIndexedDBKey = (key, value) => {
|
|
cy.window().then((window) => {
|
|
// Opening the database
|
|
const request = window.indexedDB.open("Appsmith", 2);
|
|
|
|
// Handling database opening success
|
|
request.onsuccess = (event) => {
|
|
const db = event.target.result;
|
|
|
|
// Creating a transaction to access the object store : keyvaluepairs
|
|
const transaction = db.transaction(["keyvaluepairs"], "readwrite");
|
|
const objectStore = transaction.objectStore("keyvaluepairs");
|
|
|
|
// Adding the key
|
|
const addRequest = objectStore.put(value, key);
|
|
|
|
// Handling add success
|
|
addRequest.onsuccess = () => {
|
|
console.log("Key added successfully");
|
|
// Closing the database connection
|
|
db.close();
|
|
};
|
|
|
|
// Handling add error
|
|
addRequest.onerror = (event) => {
|
|
console.log("Error adding key:", event.target.error);
|
|
// Closing the database connection
|
|
db.close();
|
|
};
|
|
};
|
|
|
|
// Handling database opening error
|
|
request.onerror = (event) => {
|
|
console.log("Error opening database:", event.target.error);
|
|
};
|
|
});
|
|
};
|
|
|
|
Cypress.Commands.add("stubPostHeaderReq", () => {
|
|
cy.intercept("POST", "/api/v1/users/invite", (req) => {
|
|
req.headers["origin"] = "Cypress";
|
|
}).as("mockPostInvite");
|
|
cy.intercept("POST", "/api/v1/applications/invite", (req) => {
|
|
req.headers["origin"] = "Cypress";
|
|
}).as("mockPostAppInvite");
|
|
});
|
|
|
|
Cypress.Commands.add("testSelfSignedCertificateSettingsInREST", (isOAuth2) => {
|
|
cy.get(datasource.useCertInAuth).should("not.exist");
|
|
cy.get(datasource.certificateDetails).should("not.exist");
|
|
// cy.TargetDropdownAndSelectOption(datasource.useSelfSignedCert, "Yes");
|
|
agHelper.CheckUncheck(datasource.useSelfSignedCert);
|
|
cy.get(datasource.useSelfSignedCert).should("be.checked");
|
|
if (isOAuth2) {
|
|
cy.get(datasource.useCertInAuth).should("exist");
|
|
} else {
|
|
cy.get(datasource.useCertInAuth).should("not.exist");
|
|
}
|
|
agHelper.CheckUncheck(datasource.useSelfSignedCert, false);
|
|
});
|
|
|
|
Cypress.Commands.add("addBasicProfileDetails", (username, password) => {
|
|
cy.get(datasource.authType).click();
|
|
cy.xpath(datasource.basic).click();
|
|
cy.get(datasource.basicUsername).type(username);
|
|
cy.get(datasource.basicPassword).type(password);
|
|
});
|
|
|
|
Cypress.Commands.add("GetUrlQueryParams", () => {
|
|
return cy.url().then((url) => {
|
|
const arr = url.split("?")[1]?.split("&");
|
|
const paramObj = {};
|
|
arr &&
|
|
arr.forEach((param) => {
|
|
const [key, value] = param.split("=");
|
|
paramObj[key] = value;
|
|
});
|
|
return cy.wrap(paramObj);
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add("LogOutUser", () => {
|
|
cy.wait(1000); //waiting for window to load
|
|
homePageTS.InvokeDispatchOnStore();
|
|
//Logout is still a POST request in CE
|
|
if (CURRENT_REPO === REPO.CE) {
|
|
assertHelper.AssertNetworkStatus("@postLogout", 200);
|
|
}
|
|
});
|
|
|
|
Cypress.Commands.add("LoginUser", (uname, pword, goToLoginPage = true) => {
|
|
goToLoginPage && cy.visit("/user/login", { timeout: 60000 });
|
|
cy.wait(3000); //for login page to load fully for CI runs
|
|
cy.wait("@getConsolidatedData");
|
|
agHelper.AssertElementVisibility(loginPage.username);
|
|
cy.get(loginPage.username).type(uname);
|
|
cy.get(loginPage.password).type(pword, { log: false });
|
|
cy.get(loginPage.submitBtn).click();
|
|
cy.wait("@getConsolidatedData");
|
|
cy.wait(3000);
|
|
});
|
|
|
|
Cypress.Commands.add("LogintoApp", (uname, pword) => {
|
|
cy.LogOutUser();
|
|
cy.LoginUser(uname, pword);
|
|
if (CURRENT_REPO === REPO.CE) {
|
|
cy.get(".createnew").should("be.visible");
|
|
cy.get(".createnew").should("be.enabled");
|
|
}
|
|
initLocalstorage();
|
|
});
|
|
|
|
Cypress.Commands.add("LoginFromAPI", (uname, pword) => {
|
|
homePageTS.LogOutviaAPI();
|
|
let baseURL = Cypress.config().baseUrl;
|
|
baseURL = baseURL.endsWith("/") ? baseURL.slice(0, -1) : baseURL;
|
|
|
|
// Clear cookies to avoid stale cookies on cypress CI
|
|
cy.clearCookie("SESSION");
|
|
|
|
cy.visit({
|
|
method: "POST",
|
|
url: "api/v1/login",
|
|
headers: {
|
|
origin: baseURL,
|
|
},
|
|
followRedirect: true,
|
|
body: {
|
|
username: uname,
|
|
password: pword,
|
|
},
|
|
timeout: 60000,
|
|
});
|
|
|
|
// Check if cookie is present
|
|
cy.getCookie("SESSION").then((cookie) => {
|
|
expect(cookie).to.not.be.null;
|
|
cy.log("cookie.value is: " + cookie.value);
|
|
|
|
if (CURRENT_REPO === REPO.EE) {
|
|
cy.wait(2000);
|
|
cy.url().then((url) => {
|
|
if (url.indexOf("/license") > -1) {
|
|
cy.validateLicense();
|
|
}
|
|
});
|
|
}
|
|
|
|
cy.location().should((loc) => {
|
|
expect(loc.href).to.eq(loc.origin + "/applications");
|
|
});
|
|
|
|
if (CURRENT_REPO === REPO.EE) {
|
|
cy.wait(2000);
|
|
} else {
|
|
assertHelper.AssertNetworkStatus("getAllWorkspaces");
|
|
assertHelper.AssertNetworkStatus("getConsolidatedData");
|
|
}
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add("LogOut", (toCheckgetPluginForm = true) => {
|
|
agHelper.WaitUntilAllToastsDisappear();
|
|
|
|
// Logout is a POST request in CE
|
|
let httpMethod = "POST";
|
|
if (CURRENT_REPO === REPO.EE) {
|
|
httpMethod = "GET";
|
|
}
|
|
|
|
if (CURRENT_REPO === REPO.CE)
|
|
toCheckgetPluginForm &&
|
|
assertHelper.AssertNetworkResponseData("@getConsolidatedData", false);
|
|
|
|
cy.request({
|
|
method: httpMethod,
|
|
url: "/api/v1/logout",
|
|
headers: {
|
|
"X-Requested-By": "Appsmith",
|
|
},
|
|
}).then((response) => {
|
|
expect(response.status).equal(200); //Verifying logout is success
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add("SearchApp", (appname) => {
|
|
cy.get(homePage.searchInput).type(appname, { force: true });
|
|
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
cy.wait(2000);
|
|
cy.get(homePage.applicationCard)
|
|
.first()
|
|
.trigger("mouseover", { force: true });
|
|
cy.get(homePage.appEditIcon).first().click({ force: true });
|
|
cy.get("#loading").should("not.exist");
|
|
// Wait added because after opening the application editor, sometimes it takes a little time.
|
|
});
|
|
|
|
Cypress.Commands.add("WaitAutoSave", () => {
|
|
// wait for save query to trigger
|
|
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
cy.wait(3000);
|
|
cy.wait("@saveAction");
|
|
});
|
|
|
|
Cypress.Commands.add("SelectAction", (action) => {
|
|
cy.get(ApiEditor.ApiVerb).first().click({ force: true });
|
|
cy.xpath(action).should("be.visible").click({ force: true });
|
|
});
|
|
|
|
Cypress.Commands.add("ClearSearch", () => {
|
|
cy.get(commonlocators.entityExplorersearch).clear({ force: true });
|
|
});
|
|
|
|
Cypress.Commands.add("clickTest", (testbutton) => {
|
|
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
cy.wait(2000);
|
|
cy.wait("@saveAction");
|
|
cy.get(testbutton).first().click({ force: true });
|
|
cy.wait("@postExecute");
|
|
});
|
|
|
|
Cypress.Commands.add(
|
|
"EvaluateCurrentValue",
|
|
(currentValue, isValueToBeEvaluatedDynamic = false) => {
|
|
// if the value is not dynamic, evaluated popup must be hidden
|
|
if (!isValueToBeEvaluatedDynamic) {
|
|
cy.get(commonlocators.evaluatedCurrentValue).should("not.exist");
|
|
} else {
|
|
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
cy.wait(3000);
|
|
cy.get(commonlocators.evaluatedCurrentValue)
|
|
.first()
|
|
.should("be.visible")
|
|
.should("not.have.text", "undefined");
|
|
cy.get(commonlocators.evaluatedCurrentValue)
|
|
.first()
|
|
//.should("be.visible")
|
|
.click({ force: true })
|
|
.then(($text) => {
|
|
if ($text.text()) expect($text.text()).to.eq(currentValue);
|
|
});
|
|
}
|
|
},
|
|
);
|
|
|
|
Cypress.Commands.add("tabPopertyUpdate", (tabId, newTabName) => {
|
|
cy.get("[data-rbd-draggable-id='" + tabId + "'] input")
|
|
.scrollIntoView()
|
|
.should("be.visible")
|
|
.click({
|
|
force: true,
|
|
});
|
|
cy.get("[data-rbd-draggable-id='" + tabId + "'] input").clear({
|
|
force: true,
|
|
});
|
|
cy.get("[data-rbd-draggable-id='" + tabId + "'] input").type(newTabName, {
|
|
force: true,
|
|
});
|
|
cy.get(`.t--tabid-${tabId}`).contains(newTabName).should("be.visible");
|
|
});
|
|
|
|
Cypress.Commands.add("generateUUID", () => {
|
|
let id = uuidv4();
|
|
return id.split("-")[0];
|
|
});
|
|
|
|
Cypress.Commands.add("addDsl", (dsl) => {
|
|
let pageid, layoutId, appId;
|
|
cy.url().then((url) => {
|
|
if (RapidMode.config.enabled && RapidMode.config.usesDSL) {
|
|
pageid = RapidMode.config.pageID;
|
|
} else {
|
|
pageid = agHelper.extractPageIdFromUrl(url);
|
|
expect(pageid).to.not.be.null;
|
|
}
|
|
|
|
//Fetch the layout id
|
|
cy.request("GET", "api/v1/pages/" + pageid).then((response) => {
|
|
const respBody = JSON.stringify(response.body);
|
|
const data = JSON.parse(respBody).data;
|
|
layoutId = data.layouts[0].id;
|
|
appId = data.applicationId;
|
|
// Dumping the DSL to the created page
|
|
cy.request({
|
|
method: "PUT",
|
|
url:
|
|
"api/v1/layouts/" +
|
|
layoutId +
|
|
"/pages/" +
|
|
pageid +
|
|
"?applicationId=" +
|
|
appId,
|
|
body: dsl,
|
|
headers: {
|
|
"X-Requested-By": "Appsmith",
|
|
},
|
|
}).then((response) => {
|
|
cy.log(response.body);
|
|
expect(response.status).equal(200);
|
|
if (RapidMode.config.enabled && RapidMode.config.usesDSL) {
|
|
cy.visit(RapidMode.url());
|
|
} else {
|
|
cy.reload();
|
|
}
|
|
|
|
cy.wait("@getWorkspace");
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add("DeleteAppByApi", () => {
|
|
const appId = localStorage.getItem("applicationId");
|
|
if (appId !== null) {
|
|
cy.log("appId to delete is:" + appId);
|
|
cy.request({
|
|
method: "DELETE",
|
|
url: "api/v1/applications/" + appId,
|
|
failOnStatusCode: false,
|
|
headers: {
|
|
"X-Requested-By": "Appsmith",
|
|
},
|
|
}).then((response) => {
|
|
cy.log(response.body);
|
|
cy.log(response.status);
|
|
});
|
|
}
|
|
});
|
|
|
|
Cypress.Commands.add("DeleteWorkspaceByApi", () => {
|
|
const workspaceId = localStorage.getItem("workspaceId");
|
|
if (workspaceId !== null) {
|
|
cy.log("workspaceId to delete is:" + workspaceId);
|
|
cy.request({
|
|
method: "DELETE",
|
|
url: "api/v1/workspaces/" + workspaceId,
|
|
failOnStatusCode: false,
|
|
headers: {
|
|
"X-Requested-By": "Appsmith",
|
|
},
|
|
}).then((response) => {
|
|
cy.log(response.body);
|
|
cy.log(response.status);
|
|
});
|
|
}
|
|
});
|
|
|
|
Cypress.Commands.add("NavigateToJSEditor", () => {
|
|
PageLeftPane.switchSegment(PagePaneSegment.JS);
|
|
PageLeftPane.switchToAddNew();
|
|
});
|
|
|
|
Cypress.Commands.add("selectAction", (option) => {
|
|
cy.get(".ads-v2-menu__menu-item-children")
|
|
.contains(option)
|
|
.click({ force: true });
|
|
});
|
|
|
|
Cypress.Commands.add("dragAndDropToCanvas", (widgetType, { x, y }) => {
|
|
PageLeftPane.switchSegment(PagePaneSegment.UI);
|
|
PageLeftPane.switchToAddNew();
|
|
const selector = `.t--widget-card-draggable-${widgetType}`;
|
|
cy.wait(500);
|
|
cy.get(selector)
|
|
.first()
|
|
.trigger("dragstart", { force: true })
|
|
.trigger("mousemove", x, y, { force: true });
|
|
|
|
const option = { eventConstructor: "MouseEvent", scrollBehavior: false };
|
|
|
|
cy.get(explorer.dropHere)
|
|
.trigger("mousemove", x, y, option)
|
|
.trigger("mousemove", x, y, option)
|
|
.trigger("mouseup", x, y, option);
|
|
agHelper.AssertAutoSave();
|
|
});
|
|
|
|
Cypress.Commands.add(
|
|
"dragAndDropToWidget",
|
|
(widgetType, destinationWidget, { x, y }) => {
|
|
PageLeftPane.switchSegment(PagePaneSegment.UI);
|
|
PageLeftPane.switchToAddNew();
|
|
const selector = `.t--widget-card-draggable-${widgetType}`;
|
|
cy.wait(800);
|
|
cy.get(selector)
|
|
.first()
|
|
.scrollIntoView()
|
|
.trigger("dragstart", { force: true })
|
|
.trigger("mousemove", x, y, { force: true });
|
|
const selector2 = `.t--draggable-${destinationWidget}`;
|
|
cy.get(selector2)
|
|
.first()
|
|
.scrollIntoView()
|
|
.trigger("mousemove", x, y, { eventConstructor: "MouseEvent" })
|
|
.trigger("mousemove", x, y, { eventConstructor: "MouseEvent" })
|
|
.trigger("mouseup", x, y, { eventConstructor: "MouseEvent" });
|
|
},
|
|
);
|
|
|
|
Cypress.Commands.add(
|
|
"dragAndDropToWidgetBySelector",
|
|
(widgetType, destinationSelector, { x, y }) => {
|
|
PageLeftPane.switchSegment(PagePaneSegment.UI);
|
|
PageLeftPane.switchToAddNew();
|
|
const selector = `.t--widget-card-draggable-${widgetType}`;
|
|
cy.wait(800);
|
|
cy.get(selector)
|
|
.first()
|
|
.scrollIntoView()
|
|
.trigger("dragstart", { force: true })
|
|
.trigger("mousemove", x, y, { force: true });
|
|
cy.get(destinationSelector)
|
|
.first()
|
|
.scrollIntoView()
|
|
.scrollTo("top", { ensureScrollable: false })
|
|
.trigger("mousemove", x, y, { eventConstructor: "MouseEvent" })
|
|
.trigger("mousemove", x, y, { eventConstructor: "MouseEvent" })
|
|
.trigger("mouseup", x, y, { eventConstructor: "MouseEvent" });
|
|
},
|
|
);
|
|
|
|
Cypress.Commands.add("changeButtonColor", (buttonColor) => {
|
|
cy.get(widgetsPage.buttonColor)
|
|
.click({ force: true })
|
|
.clear()
|
|
.type(buttonColor, { delay: 0 });
|
|
deployMode.DeployApp();
|
|
cy.get(widgetsPage.widgetBtn).should(
|
|
"have.css",
|
|
"background-color",
|
|
buttonColor,
|
|
);
|
|
cy.wait(1000);
|
|
});
|
|
|
|
Cypress.Commands.add("closePropertyPane", () => {
|
|
cy.get(commonlocators.canvas).click({ force: true });
|
|
});
|
|
|
|
Cypress.Commands.add(
|
|
"onClickActions",
|
|
(forSuccess, forFailure, actionType, actionValue, idx = 0) => {
|
|
propPane.SelectActionByTitleAndValue(actionType, actionValue);
|
|
|
|
agHelper.Sleep();
|
|
|
|
// add a success callback
|
|
cy.get(propPane._actionAddCallback("success")).click().wait(500);
|
|
cy.get(locators._dropDownValue("Show alert")).click().wait(500);
|
|
agHelper.TypeText(
|
|
propPane._actionSelectorFieldByLabel("Message"),
|
|
forSuccess,
|
|
);
|
|
agHelper.GetNClick(propPane._actionSelectorPopupClose);
|
|
|
|
// add a failure callback
|
|
cy.get(propPane._actionAddCallback("failure")).click().wait(500);
|
|
cy.get(locators._dropDownValue("Show alert")).click().wait(500);
|
|
agHelper.TypeText(
|
|
propPane._actionSelectorFieldByLabel("Message"),
|
|
forFailure,
|
|
);
|
|
agHelper.GetNClick(propPane._actionSelectorPopupClose);
|
|
},
|
|
);
|
|
|
|
Cypress.Commands.add("getDate", (date, dateFormate) => {
|
|
const eDate = dayjs().add(date, "days").format(dateFormate);
|
|
return eDate;
|
|
});
|
|
|
|
Cypress.Commands.add("setDate", (date) => {
|
|
const expDate = dayjs().add(date, "days").format("dddd, MMMM Do, YYYY");
|
|
cy.get(`.react-datepicker__day[aria-label^="Choose ${expDate}"]`).click();
|
|
});
|
|
|
|
Cypress.Commands.add("validateDisableWidget", (widgetCss, disableCss) => {
|
|
cy.get(widgetCss + disableCss).should("exist");
|
|
});
|
|
|
|
Cypress.Commands.add("validateToolbarVisible", (widgetCss, toolbarCss) => {
|
|
cy.get(widgetCss + toolbarCss).should("exist");
|
|
});
|
|
|
|
Cypress.Commands.add("validateToolbarHidden", (widgetCss, toolbarCss) => {
|
|
cy.get(widgetCss + toolbarCss).should("not.exist");
|
|
});
|
|
|
|
Cypress.Commands.add("validateEnableWidget", (widgetCss, disableCss) => {
|
|
cy.get(widgetCss + disableCss).should("not.exist");
|
|
});
|
|
|
|
Cypress.Commands.add("validateHTMLText", (widgetCss, htmlTag, value) => {
|
|
cy.get(widgetCss + " iframe").then(($iframe) => {
|
|
const $body = $iframe.contents().find("body");
|
|
cy.wrap($body).find(htmlTag).should("have.text", value);
|
|
});
|
|
});
|
|
Cypress.Commands.add("setTinyMceContent", (tinyMceId, content) => {
|
|
cy.window().then((win) => {
|
|
const editor = win.tinymce.EditorManager.get(tinyMceId);
|
|
editor.setContent(content);
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add("startServerAndRoutes", () => {
|
|
//To update route with intercept after working on alias wrt wait and alias
|
|
//cy.server();
|
|
cy.intercept("PUT", "/api/v1/themes/applications/*").as("updateTheme");
|
|
cy.intercept("POST", "/api/v1/datasources/test").as("testDatasource");
|
|
cy.intercept("POST", "/api/v1/datasources").as("saveDatasource");
|
|
cy.intercept("GET", "/api/v1/applications/new").as("applications");
|
|
cy.intercept("GET", "/api/v1/users/profile").as("getUser");
|
|
cy.intercept("GET", "/api/v1/plugins?workspaceId=*").as("getPlugins");
|
|
|
|
if (CURRENT_REPO === REPO.CE) {
|
|
cy.intercept("POST", "/api/v1/logout").as("postLogout");
|
|
} else if (CURRENT_REPO === REPO.EE) {
|
|
cy.intercept("GET", "/api/v1/logout").as("postLogout");
|
|
}
|
|
cy.intercept("GET", "/api/v1/datasources?workspaceId=*").as("getDataSources");
|
|
cy.intercept("GET", "/api/v1/pages?*mode=EDIT").as("getPagesForCreateApp");
|
|
cy.intercept("GET", "/api/v1/pages?*mode=PUBLISHED").as("getPagesForViewApp");
|
|
cy.intercept("GET", "/api/v1/applications/releaseItems").as(
|
|
"getReleaseItems",
|
|
);
|
|
cy.intercept("GET", "/api/v1/workspaces/home").as("getAllWorkspaces");
|
|
cy.intercept("GET", "/api/v1/applications/home?workspaceId=*").as(
|
|
"getApplicationsOfWorkspace",
|
|
);
|
|
|
|
cy.intercept("POST");
|
|
cy.intercept("GET", "/api/v1/pages/*").as("getPage");
|
|
cy.intercept("GET", "/api/v1/applications/*/pages/*/edit").as(
|
|
"getAppPageEdit",
|
|
);
|
|
cy.intercept("GET", "/api/v1/actions*").as("getActions");
|
|
cy.intercept("PUT", "/api/v1/pages/*").as("updatePage");
|
|
cy.intercept("PUT", "api/v1/applications/*/page/*/makeDefault").as(
|
|
"makePageDefault",
|
|
);
|
|
cy.intercept("DELETE", "/api/v1/applications/*").as("deleteApp");
|
|
cy.intercept("DELETE", "/api/v1/pages/*").as("deletePage");
|
|
//cy.intercept("POST", "/api/v1/datasources").as("createDatasource");
|
|
cy.intercept("DELETE", "/api/v1/datasources/*").as("deleteDatasource");
|
|
cy.intercept("GET", "/api/v1/datasources/*/structure?ignoreCache=*").as(
|
|
"getDatasourceStructure",
|
|
);
|
|
cy.intercept("PUT", "/api/v1/datasources/datasource-query/*").as(
|
|
"datasourceQuery",
|
|
);
|
|
|
|
cy.intercept("POST", "/api/v1/datasources/*/trigger").as("trigger");
|
|
|
|
cy.intercept("PUT", "/api/v1/pages/crud-page/*").as(
|
|
"replaceLayoutWithCRUDPage",
|
|
);
|
|
cy.intercept("POST", "/api/v1/pages/crud-page").as("generateCRUDPage");
|
|
|
|
cy.intercept("GET", "/api/v1/workspaces").as("workspaces");
|
|
cy.intercept("GET", "/api/v1/workspaces/*").as("getWorkspace");
|
|
|
|
cy.intercept("POST", "/api/v1/applications/publish/*").as("publishApp");
|
|
cy.intercept("PUT", "/api/v1/layouts/*/pages/*").as("updateLayout");
|
|
|
|
cy.intercept("POST", "/track/*").as("postTrack");
|
|
cy.intercept("PUT", "/api/v1/actions/executeOnLoad/*").as("setExecuteOnLoad");
|
|
|
|
cy.intercept("POST", "/api/v1/actions").as("createNewApi");
|
|
cy.intercept("POST", "/api/v1/import?type=CURL&contextId=*&name=*").as(
|
|
"curlImport",
|
|
);
|
|
cy.intercept("DELETE", "/api/v1/actions/*").as("deleteAction");
|
|
|
|
cy.intercept("GET", "/api/v1/plugins/*/form").as("getPluginForm");
|
|
cy.intercept("DELETE", "/api/v1/applications/*").as("deleteApplication");
|
|
cy.intercept("POST", "/api/v1/applications").as("createNewApplication");
|
|
cy.intercept("PUT", "/api/v1/applications/*").as("updateApplication");
|
|
cy.intercept("PUT", "/api/v1/actions/*").as("saveAction");
|
|
cy.intercept("PUT", "/api/v1/actions/move").as("moveAction");
|
|
|
|
cy.intercept("POST", "/api/v1/workspaces").as("createWorkspace");
|
|
cy.intercept("POST", "api/v1/applications/import/*").as(
|
|
"importNewApplication",
|
|
);
|
|
cy.intercept("GET", "api/v1/applications/export/*").as("exportApplication");
|
|
cy.intercept("GET", "/api/v1/workspaces/*/permissionGroups").as("getRoles");
|
|
cy.intercept("GET", "/api/v1/users/me").as("getMe");
|
|
cy.intercept("POST", "/api/v1/pages").as("createPage");
|
|
cy.intercept("POST", "/api/v1/pages/clone/*").as("clonePage");
|
|
cy.intercept("POST", "/api/v1/applications/clone/*").as("cloneApp");
|
|
cy.intercept("PUT", "/api/v1/applications/*/changeAccess").as("changeAccess");
|
|
|
|
cy.intercept("PUT", "/api/v1/workspaces/*").as("updateWorkspace");
|
|
cy.intercept("GET", "/api/v1/pages/view/application/*").as("viewApp");
|
|
cy.intercept("GET", "/api/v1/pages/*/view?*").as("viewPage");
|
|
cy.intercept("POST", "/api/v1/workspaces/*/logo").as("updateLogo");
|
|
cy.intercept("DELETE", "/api/v1/workspaces/*/logo").as("deleteLogo");
|
|
cy.intercept("POST", "/api/v1/applications/*/fork/*").as(
|
|
"postForkAppWorkspace",
|
|
);
|
|
cy.intercept("PUT", "/api/v1/users/leaveWorkspace/*").as(
|
|
"leaveWorkspaceApiCall",
|
|
);
|
|
cy.intercept("DELETE", "api/v1/workspaces/*").as("deleteWorkspaceApiCall");
|
|
|
|
cy.intercept("POST", "/api/v1/comments/threads").as("createNewThread");
|
|
cy.intercept("POST", "/api/v1/comments?threadId=*").as("createNewComment");
|
|
|
|
cy.intercept("POST", "api/v1/git/commit/app/*").as("commit");
|
|
cy.intercept("POST", "/api/v1/git/import/*").as("importFromGit");
|
|
cy.intercept("POST", "/api/v1/git/merge/app/*").as("mergeBranch");
|
|
cy.intercept("POST", "/api/v1/git/merge/status/app/*").as("mergeStatus");
|
|
cy.intercept("PUT", "api/v1/collections/actions/refactor").as(
|
|
"renameJsAction",
|
|
);
|
|
|
|
cy.intercept("POST", "/api/v1/collections/actions").as(
|
|
"createNewJSCollection",
|
|
);
|
|
cy.intercept("POST", "/api/v1/pages/crud-page").as(
|
|
"replaceLayoutWithCRUDPage",
|
|
);
|
|
|
|
cy.intercept("PUT", "api/v1/collections/actions/*").as("jsCollections");
|
|
cy.intercept("DELETE", "/api/v1/collections/actions/*").as(
|
|
"deleteJSCollection",
|
|
);
|
|
cy.intercept("POST", "/api/v1/users/super").as("createSuperUser");
|
|
cy.intercept("POST", "/api/v1/actions/execute").as("postExecute");
|
|
cy.intercept("GET", "/api/v1/admin/env").as("getEnvVariables");
|
|
cy.intercept("DELETE", "/api/v1/git/branch/app/*").as("deleteBranch");
|
|
cy.intercept("GET", "/api/v1/git/branch/app/*").as("getBranch");
|
|
cy.intercept("POST", "/api/v1/git/create-branch/app/*").as("createBranch");
|
|
cy.intercept("GET", "/api/v1/git/status/app/*").as("gitStatus");
|
|
cy.intercept("PUT", "/api/v1/layouts/refactor").as("updateWidgetName");
|
|
cy.intercept("GET", "/api/v1/workspaces/*/members").as("getMembers");
|
|
cy.intercept("POST", "/api/v1/datasources/mocks").as("getMockDb");
|
|
cy.intercept("GET", "/api/v1/app-templates").as("fetchTemplate");
|
|
cy.intercept("POST", "/api/v1/app-templates/*").as("importTemplate");
|
|
cy.intercept("GET", /\/api\/v1\/app-templates\/(?!(filters)).*/).as(
|
|
"getTemplatePages",
|
|
);
|
|
cy.intercept("PUT", "/api/v1/datasources/*").as("updateDatasource");
|
|
cy.intercept("POST", "/api/v1/applications/ssh-keypair/*").as("generateKey");
|
|
cy.intercept("GET", "/api/v1/applications/ssh-keypair/*").as("generatedKey");
|
|
cy.intercept("POST", "/api/v1/applications/snapshot/*").as("snapshotSuccess");
|
|
cy.intercept("GET", "/api/v1/applications/snapshot/*").as("pageSnap");
|
|
cy.intercept(
|
|
{
|
|
method: "POST",
|
|
url: "/api/v1/git/connect/app/*",
|
|
hostname: window.location.host,
|
|
},
|
|
(req) => {
|
|
req.headers["origin"] = "Cypress";
|
|
},
|
|
).as("connectGitLocalRepo");
|
|
|
|
cy.intercept("POST", "https://api.segment.io/v1/b", (req) => {
|
|
req.reply({
|
|
statusCode: 200,
|
|
body: {
|
|
success: false, //since anything can be faked!
|
|
},
|
|
});
|
|
});
|
|
|
|
cy.intercept("PUT", "/api/v1/admin/env", (req) => {
|
|
req.headers["origin"] = "Cypress";
|
|
}).as("postEnv");
|
|
|
|
cy.intercept("GET", "/settings/general").as("getGeneral");
|
|
cy.intercept("GET", "/api/v1/tenants/current").as("signUpLogin");
|
|
cy.intercept("PUT", "/api/v1/tenants", (req) => {
|
|
req.headers["origin"] = "Cypress";
|
|
}).as("postTenant");
|
|
cy.intercept("PUT", "/api/v1/git/discard/app/*").as("discardChanges");
|
|
cy.intercept("GET", "/api/v1/libraries/*").as("getLibraries");
|
|
|
|
if (Cypress.currentTest.titlePath[0].includes(ANVIL_EDITOR_TEST)) {
|
|
// intercept features call for creating pages that support Anvil + WDS tests
|
|
featureFlagIntercept({ release_anvil_enabled: true }, false);
|
|
} else {
|
|
featureFlagIntercept({}, false);
|
|
}
|
|
|
|
cy.intercept(
|
|
{
|
|
method: "GET",
|
|
url: "/api/v1/product-alert/alert",
|
|
},
|
|
(req) => {
|
|
req.reply((res) => {
|
|
if (res) {
|
|
if (res.statusCode === 200) {
|
|
// Modify the response body to have empty data
|
|
res.send({
|
|
responseMeta: {
|
|
status: 200,
|
|
success: true,
|
|
},
|
|
data: {},
|
|
errorDisplay: "",
|
|
});
|
|
}
|
|
} else {
|
|
// Do nothing or handle the case where the response object is not present
|
|
}
|
|
});
|
|
},
|
|
).as("productAlert");
|
|
cy.intercept(
|
|
{
|
|
method: "GET",
|
|
url: /domain\/docs\.appsmith\.com\/token$/,
|
|
},
|
|
{
|
|
statusCode: 200,
|
|
},
|
|
).as("docsCall");
|
|
cy.intercept("POST", "/api/v1/datasources/*/schema-preview").as(
|
|
"schemaPreview",
|
|
);
|
|
cy.intercept("GET", "/api/v1/pages/*/view?v=*").as("templatePreview");
|
|
});
|
|
|
|
Cypress.Commands.add("startErrorRoutes", () => {
|
|
cy.intercept("POST", "/api/v1/actions/execute", { statusCode: 500 }).as(
|
|
"postExecuteError",
|
|
);
|
|
});
|
|
|
|
Cypress.Commands.add("NavigateToPaginationTab", () => {
|
|
apiPage.SelectPaneTab("Pagination");
|
|
agHelper.GetNClick(ApiEditor.apiPaginationTab);
|
|
});
|
|
|
|
Cypress.Commands.add("ValidatePaginateResponseUrlData", (runTestCss) => {
|
|
EditorNavigation.SelectEntityByName("Api2", EntityType.Api);
|
|
cy.wait(3000);
|
|
cy.NavigateToPaginationTab();
|
|
cy.RunAPI();
|
|
cy.get(ApiEditor.apiPaginationNextTest).click();
|
|
cy.wait("@postExecute");
|
|
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
cy.wait(2000);
|
|
cy.get(runTestCss).click();
|
|
cy.wait(2000);
|
|
cy.xpath("//div[@class='tr'][1]//div[@class='td'][6]//span")
|
|
.invoke("text")
|
|
.then((valueToTest) => {
|
|
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
cy.get(ApiEditor.ApiRunBtn).should("not.be.disabled");
|
|
EditorNavigation.SelectEntityByName("Table1", EntityType.Widget);
|
|
table.SelectTableRow(0);
|
|
cy.readTabledata("0", "5").then((tabData) => {
|
|
const tableData = tabData;
|
|
expect(valueToTest).contains(tableData);
|
|
});
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add("ValidatePaginateResponseUrlDataV2", (runTestCss) => {
|
|
EditorNavigation.SelectEntityByName("Api2", EntityType.Api);
|
|
cy.wait(3000);
|
|
cy.NavigateToPaginationTab();
|
|
cy.RunAPI();
|
|
cy.get(ApiEditor.apiPaginationNextTest).click();
|
|
cy.wait("@postExecute");
|
|
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
cy.wait(2000);
|
|
cy.get(runTestCss).click();
|
|
cy.wait(2000);
|
|
cy.xpath("//div[@class='tr'][1]//div[@class='td'][6]//span")
|
|
.invoke("text")
|
|
.then((valueToTest) => {
|
|
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
cy.get(ApiEditor.ApiRunBtn).should("not.be.disabled");
|
|
EditorNavigation.SelectEntityByName("Table1", EntityType.Widget);
|
|
cy.wait(2000);
|
|
table.SelectTableRow(0, 0, true, "v2");
|
|
cy.readTableV2data("0", "5").then((tabData) => {
|
|
const tableData = tabData;
|
|
cy.log(valueToTest);
|
|
expect(valueToTest).contains(tableData);
|
|
});
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add("CheckForPageSaveError", () => {
|
|
// Wait for "saving" status to disappear
|
|
cy.get(commonlocators.statusSaving, {
|
|
timeout: 30000,
|
|
}).should("not.exist");
|
|
// Check for page save error
|
|
cy.get("body").then(($ele) => {
|
|
if ($ele.find(commonlocators.saveStatusError).length) {
|
|
cy.reload();
|
|
}
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add(
|
|
"validateCodeEditorContent",
|
|
(selector, contentToValidate) => {
|
|
cy.get(selector).within(() => {
|
|
cy.get(".CodeMirror-code").should("have.text", contentToValidate);
|
|
});
|
|
},
|
|
);
|
|
|
|
Cypress.Commands.add("createSuperUser", () => {
|
|
cy.wait(1000);
|
|
cy.get(welcomePage.firstName).should("be.visible");
|
|
cy.get(welcomePage.lastName).should("be.visible");
|
|
cy.get(welcomePage.email).should("be.visible");
|
|
cy.get(welcomePage.password).should("be.visible");
|
|
cy.get(welcomePage.verifyPassword).should("be.visible");
|
|
cy.get(welcomePage.continueButton).should("be.disabled");
|
|
|
|
cy.get(welcomePage.firstName).type(Cypress.env("USERNAME"));
|
|
cy.get(welcomePage.continueButton).should("be.disabled");
|
|
cy.get(welcomePage.email).type(Cypress.env("USERNAME"));
|
|
cy.get(welcomePage.continueButton).should("be.disabled");
|
|
cy.get(welcomePage.password).type(Cypress.env("PASSWORD"));
|
|
cy.get(welcomePage.continueButton).should("be.disabled");
|
|
cy.get(welcomePage.verifyPassword).type(Cypress.env("PASSWORD"));
|
|
cy.get(welcomePage.continueButton).should("not.be.disabled");
|
|
cy.get(welcomePage.continueButton).click();
|
|
|
|
cy.get(welcomePage.proficiencyGroupButton).eq(0).click();
|
|
cy.get(welcomePage.submitButton).should("be.disabled");
|
|
cy.get(welcomePage.useCaseGroupButton).eq(0).click();
|
|
cy.get(welcomePage.submitButton).should("not.be.disabled");
|
|
|
|
cy.get(welcomePage.submitButton).click();
|
|
//in case of airgapped both anonymous data and newsletter are disabled
|
|
if (Cypress.env("AIRGAPPED")) {
|
|
cy.wait("@createSuperUser").then((interception) => {
|
|
expect(interception.request.body).to.not.contain(
|
|
"allowCollectingAnonymousData=true",
|
|
);
|
|
expect(interception.request.body).to.not.contain(
|
|
"signupForNewsletter=true",
|
|
);
|
|
});
|
|
} else {
|
|
cy.wait("@createSuperUser").then((interception) => {
|
|
expect(interception.request.body).contains(
|
|
"allowCollectingAnonymousData=true",
|
|
);
|
|
expect(interception.request.body).contains("signupForNewsletter=true");
|
|
});
|
|
}
|
|
|
|
cy.wait(2000);
|
|
|
|
if (CURRENT_REPO === REPO.CE) {
|
|
assertHelper.AssertNetworkStatus("@getApplicationsOfWorkspace");
|
|
agHelper.WaitUntilEleAppear(onboarding.locators.skipStartFromData);
|
|
agHelper.GetNClick(onboarding.locators.skipStartFromData);
|
|
cy.get("#loading").should("not.exist");
|
|
AppSidebar.assertVisible();
|
|
}
|
|
|
|
cy.LogOut();
|
|
cy.wait(2000);
|
|
});
|
|
|
|
Cypress.Commands.add("SignupFromAPI", (uname, pword) => {
|
|
cy.request({
|
|
method: "POST",
|
|
url: "api/v1/users",
|
|
headers: {
|
|
"content-type": "application/json",
|
|
},
|
|
followRedirect: false,
|
|
form: true,
|
|
body: {
|
|
name: uname,
|
|
email: uname,
|
|
password: pword,
|
|
},
|
|
}).then((response) => {
|
|
expect(response.status).equal(302);
|
|
cy.log(response.body);
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add("startInterceptRoutesForS3", () => {
|
|
cy.intercept("POST", "/api/v1/datasources/test").as("testDatasource");
|
|
cy.intercept("PUT", "/api/v1/datasources/datasource-query/*").as(
|
|
"put_datasources",
|
|
);
|
|
cy.intercept("GET", "/api/v1/datasources/*/structure?ignoreCache=*").as(
|
|
"getDatasourceStructure",
|
|
);
|
|
cy.intercept("PUT", "/api/v1/pages/crud-page/*").as("put_replaceLayoutCRUD");
|
|
cy.intercept("POST", "/api/v1/pages/crud-page").as("post_replaceLayoutCRUD");
|
|
cy.intercept("GET", "/api/v1/actions*").as("get_Actions");
|
|
cy.intercept("POST", "/api/v1/actions/execute").as("post_Execute");
|
|
});
|
|
|
|
// the way we target form controls from now on has to change
|
|
// we would be getting the form controls by their class names and not their xpaths.
|
|
// the xpath method is flaky and highly subjected to change.
|
|
Cypress.Commands.add(
|
|
"typeValueNValidate",
|
|
(valueToType, fieldName = "", isDynamic = false) => {
|
|
cy.wait(2000);
|
|
if (fieldName) {
|
|
cy.get(fieldName).then(($field) => {
|
|
cy.updateCodeInput($field, valueToType);
|
|
});
|
|
} else {
|
|
cy.xpath("//div[@class='CodeEditorTarget']").then(($field) => {
|
|
cy.updateCodeInput($field, valueToType);
|
|
});
|
|
}
|
|
cy.EvaluateCurrentValue(valueToType, isDynamic);
|
|
},
|
|
);
|
|
|
|
Cypress.Commands.add("clickButton", (btnVisibleText, toForceClick = true) => {
|
|
cy.xpath("//span[text()='" + btnVisibleText + "']/ancestor::button")
|
|
.first()
|
|
.scrollIntoView()
|
|
.click({ force: toForceClick });
|
|
});
|
|
|
|
Cypress.Commands.add(
|
|
"EvaluatFieldValue",
|
|
(fieldName = "", currentValue = "") => {
|
|
let val = "";
|
|
if (fieldName) {
|
|
cy.get(fieldName).click();
|
|
val = cy.get(fieldName).then(($field) => {
|
|
cy.wrap($field).find(".CodeMirror-code span").first().invoke("text");
|
|
});
|
|
} else {
|
|
cy.xpath("//div[@class='CodeMirror-code']").first().click();
|
|
val = cy
|
|
.xpath(
|
|
"//div[@class='CodeMirror-code']//span[contains(@class,'cm-m-javascript')]",
|
|
)
|
|
.then(($field) => {
|
|
cy.wrap($field).invoke("text");
|
|
});
|
|
}
|
|
if (currentValue) expect(val).to.eq(currentValue);
|
|
|
|
return val;
|
|
},
|
|
);
|
|
|
|
// Cypress >=8.3.x onwards
|
|
cy.all = function (...commands) {
|
|
const _ = Cypress._;
|
|
// eslint-disable-next-line
|
|
const chain = cy.wrap(null, { log: false });
|
|
const stopCommand = _.find(cy.queue.get(), {
|
|
attributes: { chainerId: chain.chainerId },
|
|
});
|
|
const startCommand = _.find(cy.queue.get(), {
|
|
attributes: { chainerId: commands[0].chainerId },
|
|
});
|
|
const p = chain.then(() => {
|
|
return _(commands)
|
|
.map((cmd) => {
|
|
return cmd[chainStart]
|
|
? cmd[chainStart].attributes
|
|
: _.find(cy.queue.get(), {
|
|
attributes: { chainerId: cmd.chainerId },
|
|
}).attributes;
|
|
})
|
|
.concat(stopCommand.attributes)
|
|
.slice(1)
|
|
.flatMap((cmd) => {
|
|
return cmd.prev.get("subject");
|
|
})
|
|
.value();
|
|
});
|
|
p[chainStart] = startCommand;
|
|
return p;
|
|
};
|
|
|
|
Cypress.Commands.add("getEntityName", () => {
|
|
let entityName = cy.get(apiwidget.ApiName).invoke("text");
|
|
return entityName;
|
|
});
|
|
|
|
Cypress.Commands.add("VerifyErrorMsgAbsence", (errorMsgToVerifyAbsence) => {
|
|
cy.xpath(
|
|
"//div[@class='Toastify']//span[contains(text(),'" +
|
|
errorMsgToVerifyAbsence +
|
|
"')]",
|
|
{ timeout: 0 },
|
|
).should("not.exist");
|
|
});
|
|
|
|
Cypress.Commands.add("VerifyErrorMsgPresence", (errorMsgToVerifyAbsence) => {
|
|
cy.xpath(
|
|
"//div[@class='Toastify']//span[contains(text(),'" +
|
|
errorMsgToVerifyAbsence +
|
|
"')]",
|
|
{ timeout: 0 },
|
|
).should("exist");
|
|
});
|
|
|
|
Cypress.Commands.add("setQueryTimeout", (timeout) => {
|
|
cy.get(queryLocators.settings).click();
|
|
cy.xpath(queryLocators.queryTimeout).clear().type(timeout);
|
|
cy.xpath(queryLocators.query).click();
|
|
});
|
|
|
|
Cypress.Commands.add("isInViewport", (element) => {
|
|
cy.xpath(element)
|
|
.scrollIntoView()
|
|
.then(($el) => {
|
|
const bottom = Cypress.$(cy.state("window")).height();
|
|
const rect = $el[0].getBoundingClientRect();
|
|
|
|
expect(rect.top).not.to.be.greaterThan(bottom);
|
|
expect(rect.bottom).not.to.be.greaterThan(bottom);
|
|
expect(rect.top).not.to.be.greaterThan(bottom);
|
|
expect(rect.bottom).not.to.be.greaterThan(bottom);
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add("validateEvaluatedValue", (value) => {
|
|
cy.get(".t-property-evaluated-value").should("contain", value);
|
|
});
|
|
|
|
Cypress.Commands.add("DeleteEntityStateLocalStorage", () => {
|
|
let currentURL;
|
|
let appId;
|
|
cy.url().then((url) => {
|
|
currentURL = url;
|
|
const myRegexp = /applications(.*)/;
|
|
const match = myRegexp.exec(currentURL);
|
|
appId = match ? match[1].split("/")[1] : null;
|
|
|
|
if (appId !== null) {
|
|
window.localStorage.removeItem(`explorerState_${appId}`);
|
|
}
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add("checkLabelForWidget", (options) => {
|
|
// Variables
|
|
const widgetName = options.widgetName;
|
|
const labelText = options.labelText;
|
|
const parentColumnSpace = options.parentColumnSpace;
|
|
const isCompact = options.isCompact;
|
|
const widgetSelector = `.t--widget-${widgetName}`;
|
|
const labelSelector = `${widgetSelector} label`;
|
|
const labelContainer = `${widgetSelector} .label-container`;
|
|
const containerSelector = `${widgetSelector} ${options.containerSelector}`;
|
|
const labelPositionSelector = ".t--property-control-position";
|
|
const labelAlignmentRightSelector =
|
|
".t--property-control-alignment .ads-v2-segmented-control__segments-container-segment[data-value='right']";
|
|
const labelWidth = options.labelWidth;
|
|
|
|
// Drag a widget
|
|
cy.dragAndDropToCanvas(widgetName, { x: 300, y: 300 });
|
|
cy.get(`.t--widget-${widgetName}`).should("exist");
|
|
|
|
// Set the label text
|
|
cy.updateCodeInput(".t--property-control-text", labelText);
|
|
// Assert label presence
|
|
cy.get(labelSelector).first().contains(labelText);
|
|
|
|
// Set the label position: Auto
|
|
cy.get(".ads-v2-segmented-control-value-Auto").click({ force: true });
|
|
// Assert label position: Auto
|
|
cy.get(containerSelector).should("have.css", "flex-direction", "column");
|
|
|
|
// Change the label position to Top
|
|
cy.get(".ads-v2-segmented-control-value-Top").click({ force: true });
|
|
// Assert label position: Top
|
|
cy.get(containerSelector).should("have.css", "flex-direction", "column");
|
|
|
|
// Change the label position to Left
|
|
cy.get(".ads-v2-segmented-control-value-Left").click({ force: true });
|
|
// Assert label position: Left
|
|
cy.get(containerSelector).should("have.css", "flex-direction", "row");
|
|
|
|
// Set the label alignment to RIGHT
|
|
cy.get(labelAlignmentRightSelector).click();
|
|
// Assert label alignment
|
|
cy.get(labelSelector).first().should("have.css", "text-align", "right");
|
|
|
|
// Clean up the widget
|
|
cy.deleteWidget(widgetSelector);
|
|
});
|
|
let LOCAL_STORAGE_MEMORY = {};
|
|
|
|
Cypress.Commands.add("StopContainer", (path, containerName) => {
|
|
cy.request({
|
|
method: "GET",
|
|
url: path,
|
|
qs: {
|
|
cmd: "docker stop " + containerName,
|
|
},
|
|
}).then((res) => {
|
|
cy.log(res.body.stdout, res.body.stderr);
|
|
expect(res.status).equal(200);
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add(
|
|
"StartNewContainer",
|
|
(url, path, version, containerName) => {
|
|
let comm =
|
|
"docker run -d --name " +
|
|
containerName +
|
|
' -p 8081:80 -p 9002:9002 -v "' +
|
|
path +
|
|
'/stacks:/appsmith-stacks" ' +
|
|
version;
|
|
|
|
cy.log(comm);
|
|
cy.request({
|
|
method: "GET",
|
|
url: url,
|
|
qs: {
|
|
cmd: comm,
|
|
},
|
|
}).then((res) => {
|
|
cy.log("ContainerID", res.body.stdout);
|
|
cy.log(res.body.stderr);
|
|
expect(res.status).equal(200);
|
|
});
|
|
},
|
|
);
|
|
|
|
Cypress.Commands.add("GetPath", (path, containerName) => {
|
|
cy.request({
|
|
method: "GET",
|
|
url: path,
|
|
qs: {
|
|
cmd:
|
|
"docker inspect -f '{{ .Mounts }}' " +
|
|
containerName +
|
|
"|awk '{print $2}'",
|
|
},
|
|
}).then((res) => {
|
|
return res.body.stdout;
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add("GetAndVerifyLogs", (path, containerName) => {
|
|
cy.request({
|
|
method: "GET",
|
|
url: path,
|
|
qs: {
|
|
cmd: "docker logs " + containerName + " 2>&1 | grep 'APPLIED'",
|
|
},
|
|
}).then((res) => {
|
|
expect(res.status).equal(200);
|
|
//expect(res.body.stdout).not.equal("");
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add("forceVisit", (url) => {
|
|
cy.window().then((win) => {
|
|
return win.open(url, "_self");
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add("SelectDropDown", (dropdownOption) => {
|
|
cy.wait(1000);
|
|
cy.get(".t--widget-selectwidget button").first().scrollIntoView().click();
|
|
cy.get(".t--widget-selectwidget button .cancel-icon")
|
|
.first()
|
|
.click({ force: true })
|
|
.wait(1000);
|
|
cy.get(".t--widget-selectwidget button").first().click({ force: true });
|
|
cy.document()
|
|
.its("body")
|
|
.find(".menu-item-link:contains('" + dropdownOption + "')")
|
|
.click({
|
|
force: true,
|
|
})
|
|
.wait(1000);
|
|
});
|
|
|
|
Cypress.Commands.add("RemoveAllSelections", () => {
|
|
cy.get(`.rc-select-selection-overflow-item .remove-icon`).each(($each) => {
|
|
cy.wrap($each).click({ force: true }).wait(1000);
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add("SelectFromMultiSelect", (options) => {
|
|
const option = (value) =>
|
|
`.rc-select-item-option[title=${value}] input[type='checkbox']`;
|
|
cy.get(" .t--widget-multiselectwidgetv2 div.rc-select-selector")
|
|
.eq(0)
|
|
.scrollIntoView()
|
|
.then(($element) => {
|
|
// here, we try to click on downArrow in dropdown of multiSelect.
|
|
// the position is calculated from top left of the element
|
|
const dropdownCenterPosition = +$element.height / 2;
|
|
const dropdownArrowApproxPosition = +$element.width - 10;
|
|
cy.get($element).click(
|
|
dropdownArrowApproxPosition,
|
|
dropdownCenterPosition,
|
|
{
|
|
force: true,
|
|
},
|
|
);
|
|
});
|
|
|
|
options.forEach(($each) => {
|
|
cy.document()
|
|
.its("body")
|
|
.find(".rc-select-dropdown.multi-select-dropdown")
|
|
.not(".rc-select-dropdown-hidden")
|
|
.find(option($each))
|
|
.check({ force: true })
|
|
.wait(1000);
|
|
cy.document().its("body").find(option($each)).should("be.checked");
|
|
});
|
|
//Closing dropdown
|
|
cy.get(" .t--widget-multiselectwidgetv2 div.rc-select-selector")
|
|
.eq(0)
|
|
.scrollIntoView()
|
|
.then(($element) => {
|
|
// here, we try to click on downArrow in dropdown of multiSelect.
|
|
// the position is calculated from top left of the element
|
|
const dropdownCenterPosition = +$element.height / 2;
|
|
const dropdownArrowApproxPosition = +$element.width - 10;
|
|
cy.get($element).click(
|
|
dropdownArrowApproxPosition,
|
|
dropdownCenterPosition,
|
|
{
|
|
force: true,
|
|
},
|
|
);
|
|
});
|
|
//cy.document().its("body").type("{esc}");
|
|
});
|
|
|
|
Cypress.Commands.add("skipSignposting", () => {
|
|
onboarding.skipSignposting();
|
|
});
|
|
|
|
Cypress.Commands.add("stubPricingPage", () => {
|
|
cy.window().then((win) => {
|
|
cy.stub(win, "open", (url) => {
|
|
win.location.href = "https://www.appsmith.com/pricing?";
|
|
}).as("pricingPage");
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add("stubCustomerPortalPage", () => {
|
|
cy.window().then((win) => {
|
|
cy.stub(win, "open", (url) => {
|
|
win.location.href = "https://customer.appsmith.com?";
|
|
}).as("customerPortalPage");
|
|
});
|
|
});
|
|
|
|
/**
|
|
* @param tooltipSelector
|
|
* @param expectedText
|
|
* @returns
|
|
*
|
|
*
|
|
*/
|
|
Cypress.Commands.add(
|
|
"assertTooltipPresence",
|
|
(tooltipSelector = "", expectedText) => {
|
|
cy.get(tooltipSelector).should("be.visible").and("contain", expectedText);
|
|
},
|
|
);
|
|
|
|
Cypress.Commands.add(
|
|
"paste",
|
|
{ prevSubject: true },
|
|
(selector, pastePayload) => {
|
|
cy.wrap(selector).then(($destination) => {
|
|
const pasteEvent = Object.assign(
|
|
new Event("paste", { bubbles: true, cancelable: true }),
|
|
{
|
|
clipboardData: {
|
|
getData: () => pastePayload,
|
|
},
|
|
},
|
|
);
|
|
$destination[0].dispatchEvent(pasteEvent);
|
|
});
|
|
},
|
|
);
|
|
|
|
Cypress.Commands.add("LogintoAppTestUser", (uname, pword) => {
|
|
cy.LogOutUser();
|
|
cy.LoginUser(uname, pword);
|
|
initLocalstorage();
|
|
});
|
|
|
|
Cypress.Commands.add("createJSObject", (JSCode) => {
|
|
cy.NavigateToJSEditor();
|
|
cy.wait(1000);
|
|
cy.get(".CodeMirror textarea")
|
|
.first()
|
|
.focus()
|
|
.type("{downarrow}{downarrow}{downarrow}{downarrow} ")
|
|
.type(JSCode);
|
|
cy.wait(1000);
|
|
cy.get(jsEditorLocators.runButton).first().click();
|
|
});
|
|
|
|
Cypress.Commands.add("CheckAndUnfoldEntityItem", (item) => {
|
|
PageLeftPane.expandCollapseItem(item);
|
|
});
|
|
|
|
Cypress.Commands.add("text", { prevSubject: true }, (subject, text) => {
|
|
subject.val(text);
|
|
return cy.wrap(subject);
|
|
});
|