diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ActionExecution/ClearStore_spec.ts b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ActionExecution/ClearStore_spec.ts
index 0f2f4c6522..9f76e36b5e 100644
--- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ActionExecution/ClearStore_spec.ts
+++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ActionExecution/ClearStore_spec.ts
@@ -1,17 +1,9 @@
-import { ObjectsRegistry } from "../../../../support/Objects/Registry";
-
-const {
- AggregateHelper: agHelper,
- DeployMode: deployMode,
- EntityExplorer: ee,
- JSEditor: jsEditor,
- PropertyPane: propPane,
-} = ObjectsRegistry;
+import * as _objects from "../../../../support/Objects/ObjectsCore"
describe("clearStore Action test", () => {
before(() => {
- ee.DragDropWidgetNVerify("buttonwidget", 100, 100);
- ee.NavigateToSwitcher("explorer");
+ _objects.ee.DragDropWidgetNVerify("buttonwidget", 100, 100);
+ _objects.ee.NavigateToSwitcher("explorer");
});
it("1. Feature 11639 : Clear all store value", function() {
@@ -24,7 +16,7 @@ describe("clearStore Action test", () => {
storeValue('val3', 'value 3'),
];
await Promise.all(values);
- await showAlert(JSON.stringify(appsmith.store));
+ await showAlert(JSON.stringify(appsmith.store));
},
clearStore: async () => {
await clearStore();
@@ -33,7 +25,7 @@ describe("clearStore Action test", () => {
}`;
// Create js object
- jsEditor.CreateJSObject(JS_OBJECT_BODY, {
+ _objects.jsEditor.CreateJSObject(JS_OBJECT_BODY, {
paste: true,
completeReplace: true,
toRun: false,
@@ -41,40 +33,40 @@ describe("clearStore Action test", () => {
shouldCreateNewJSObj: true,
});
- ee.SelectEntityByName("Button1", "Widgets");
- propPane.UpdatePropertyFieldValue("Label", "");
- propPane.TypeTextIntoField("Label", "StoreValue");
+ _objects.ee.SelectEntityByName("Button1", "Widgets");
+ _objects.propPane.UpdatePropertyFieldValue("Label", "");
+ _objects.propPane.TypeTextIntoField("Label", "StoreValue");
cy.get("@jsObjName").then((jsObj: any) => {
- propPane.SelectJSFunctionToExecute(
+ _objects.propPane.SelectJSFunctionToExecute(
"onClick",
jsObj as string,
"storeValue",
);
});
- ee.DragDropWidgetNVerify("buttonwidget", 100, 200);
- ee.SelectEntityByName("Button2", "Widgets");
- propPane.UpdatePropertyFieldValue("Label", "");
- propPane.TypeTextIntoField("Label", "ClearStore");
+ _objects.ee.DragDropWidgetNVerify("buttonwidget", 100, 200);
+ _objects.ee.SelectEntityByName("Button2", "Widgets");
+ _objects.propPane.UpdatePropertyFieldValue("Label", "");
+ _objects.propPane.TypeTextIntoField("Label", "ClearStore");
cy.get("@jsObjName").then((jsObj: any) => {
- propPane.SelectJSFunctionToExecute(
+ _objects.propPane.SelectJSFunctionToExecute(
"onClick",
jsObj as string,
"clearStore",
);
});
- deployMode.DeployApp();
- agHelper.ClickButton("StoreValue");
- agHelper.AssertContains(
+ _objects.deployMode.DeployApp();
+ _objects.agHelper.ClickButton("StoreValue");
+ _objects.agHelper.AssertContains(
JSON.stringify({
val1: "value 1",
val2: "value 2",
val3: "value 3",
}),
);
- agHelper.ClickButton("ClearStore");
- agHelper.AssertContains(JSON.stringify({}));
- deployMode.NavigateBacktoEditor();
+ _objects.agHelper.ClickButton("ClearStore");
+ _objects.agHelper.AssertContains(JSON.stringify({}));
+ _objects.deployMode.NavigateBacktoEditor();
});
});
diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Git/GitImport/GitImport_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Git/GitImport/GitImport_spec.js
index 7c466b5177..fa13652707 100644
--- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Git/GitImport/GitImport_spec.js
+++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Git/GitImport/GitImport_spec.js
@@ -71,7 +71,7 @@ describe("Git import flow ", function() {
cy.connectToGitRepo(repoName);
});
});
- cy.wait(4000); // for git connection to settle!
+ cy.wait(5000); // for git connection to settle!
});
it("2. Import the previous app connected to Git and reconnect Postgres, MySQL and Mongo db ", () => {
@@ -90,7 +90,7 @@ describe("Git import flow ", function() {
.next()
.click();
cy.importAppFromGit(repoName);
- cy.wait(100);
+ cy.wait(5000);
cy.get(reconnectDatasourceModal.Modal).should("be.visible");
cy.ReconnectDatasource("TEDPostgres");
cy.wait(500);
@@ -142,7 +142,8 @@ describe("Git import flow ", function() {
// verify js object binded to input widget
cy.xpath("//input[@value='Success']").should("be.visible");
});
- // skipping these tests until bug #18776 is fixed
+
+ // skipping this due to open bug #18776
it.skip("4. Create a new branch, clone page and validate data on that branch in view and edit mode", () => {
cy.createGitBranch(newBranch);
cy.get(".tbody")
@@ -213,6 +214,7 @@ describe("Git import flow ", function() {
cy.wait(2000);
});
+ // skipping this due to open bug #18776
it.skip("5. Switch to master and verify data in edit and view mode", () => {
cy.switchGitBranch("master");
cy.wait(2000);
@@ -236,6 +238,7 @@ describe("Git import flow ", function() {
cy.wait(2000);
});
+ // skipping this due to open bug #18776
it.skip("6. Add widget to master, merge then checkout to child branch and verify data", () => {
cy.get(explorer.widgetSwitchId).click();
cy.wait(2000); // wait for transition
diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Git/GitWithTheming/GitWithTheming_spec.ts b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Git/GitWithTheming/GitWithTheming_spec.js
similarity index 98%
rename from app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Git/GitWithTheming/GitWithTheming_spec.ts
rename to app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Git/GitWithTheming/GitWithTheming_spec.js
index b59c84aa17..c5b03b0270 100644
--- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Git/GitWithTheming/GitWithTheming_spec.ts
+++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Git/GitWithTheming/GitWithTheming_spec.js
@@ -32,7 +32,7 @@ describe("Git with Theming:", function() {
});
});
it("Bug #13860 Theming is not getting applied on view mode when the app is connected to Git", function() {
- appSettings.OpenPaneFromCta();
+ appSettings.OpenAppSettings();
appSettings.GoToThemeSettings();
// apply theme on master branch and deploy
cy.get(commonlocators.changeThemeBtn).click({ force: true });
@@ -65,7 +65,7 @@ describe("Git with Theming:", function() {
cy.wait(1000);
cy.get("body").click(300, 300);
// change theme on tempBranch
- appSettings.OpenPaneFromCta();
+ appSettings.OpenAppSettings();
appSettings.GoToThemeSettings();
cy.get(commonlocators.changeThemeBtn).click({ force: true });
diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/SettingsPane/GeneralSettings_spec.ts b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/SettingsPane/GeneralSettings_spec.ts
index 065c875ddc..e5d6a7632f 100644
--- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/SettingsPane/GeneralSettings_spec.ts
+++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/SettingsPane/GeneralSettings_spec.ts
@@ -1,25 +1,43 @@
-import { ObjectsRegistry } from "../../../../support/Objects/Registry";
-import { checkUrl } from "../../../../support/Pages/AppSettings/Utils";
-
-const appSettings = ObjectsRegistry.AppSettings,
- deployMode = ObjectsRegistry.DeployMode,
- homePage = ObjectsRegistry.HomePage;
+import * as _ from "../../../../support/Objects/ObjectsCore";
+let guid: string;
describe("General Settings", () => {
- it("App name change updates URL", () => {
- appSettings.OpenPaneFromCta();
- appSettings.GoToGeneralSettings();
- appSettings.general.changeAppNameAndVerifyUrl(true, "myapp");
- homePage.GetAppName().then((appName) => {
- deployMode.DeployApp();
- checkUrl(appName as string, "Page1", undefined, false);
- deployMode.NavigateBacktoEditor();
+ before(() => {
+ _.agHelper.GenerateUUID();
+ cy.get("@guid").then((uid: any) => {
+ guid = uid;
});
});
- it("Handles app icon change", () => {
- appSettings.OpenPaneFromCta();
- appSettings.GoToGeneralSettings();
- appSettings.general.changeAppIcon();
+ it("1. App name change updates URL", () => {
+ _.appSettings.OpenAppSettings();
+ _.appSettings.GoToGeneralSettings();
+ _.generalSettings.UpdateAppNameAndVerifyUrl(true, guid);
+ _.homePage.GetAppName().then((appName) => {
+ _.deployMode.DeployApp();
+ _.appSettings.CheckUrl(appName as string, "Page1", undefined, false);
+ _.deployMode.NavigateBacktoEditor();
+ });
+ });
+
+ it("2. Handles app icon change", () => {
+ _.appSettings.OpenAppSettings();
+ _.appSettings.GoToGeneralSettings();
+ _.generalSettings.UpdateAppIcon();
+ _.appSettings.ClosePane();
+ });
+
+ it("3. App name allows special and accented character", () => {
+ _.appSettings.OpenAppSettings();
+ _.appSettings.GoToGeneralSettings();
+ _.generalSettings.UpdateAppNameAndVerifyUrl(true, guid + "!@#œ™¡", guid);
+ _.appSettings.ClosePane();
+ });
+
+ it("4. Veirfy App name doesn't allow empty", () => {
+ _.appSettings.OpenAppSettings();
+ _.appSettings.GoToGeneralSettings();
+ _.generalSettings.AssertAppErrorMessage("", "App name cannot be empty");
+ _.appSettings.ClosePane();
});
});
diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/SettingsPane/PageSettings_spec.ts b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/SettingsPane/PageSettings_spec.ts
index eb6a09513f..2ca83710af 100644
--- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/SettingsPane/PageSettings_spec.ts
+++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/SettingsPane/PageSettings_spec.ts
@@ -1,55 +1,101 @@
-import { ObjectsRegistry } from "../../../../support/Objects/Registry";
-import { checkUrl } from "../../../../support/Pages/AppSettings/Utils";
-
-const appSettings = ObjectsRegistry.AppSettings,
- ee = ObjectsRegistry.EntityExplorer,
- agHelper = ObjectsRegistry.AggregateHelper,
- commonLocators = ObjectsRegistry.CommonLocators,
- deployMode = ObjectsRegistry.DeployMode,
- homePage = ObjectsRegistry.HomePage;
+import * as _ from "../../../../support/Objects/ObjectsCore";
describe("Page Settings", () => {
- it("Page name change updates URL", () => {
- appSettings.OpenPaneFromCta();
- appSettings.GoToPageSettings("Page1");
- appSettings.page.changePageNameAndVerifyUrl("Page2");
- homePage.GetAppName().then((appName) => {
- deployMode.DeployApp();
- checkUrl(appName as string, "Page2", undefined, false);
- deployMode.NavigateBacktoEditor();
+ it("1. Page name change updates URL", () => {
+ _.appSettings.OpenAppSettings();
+ _.appSettings.GoToPageSettings("Page1");
+ _.pageSettings.UpdatePageNameAndVerifyUrl("Page2", undefined, false);
+ _.homePage.GetAppName().then((appName) => {
+ _.deployMode.DeployApp();
+ _.appSettings.CheckUrl(appName as string, "Page2", undefined, false);
+ _.deployMode.NavigateBacktoEditor();
});
- cy.wait(2000);
+ _.agHelper.Sleep();
});
- it("Custom slug change updates URL", () => {
- appSettings.OpenPaneFromCta();
- appSettings.GoToPageSettings("Page2");
- appSettings.page.changeCustomSlugAndVerifyUrl("custom");
- homePage.GetAppName().then((appName) => {
- deployMode.DeployApp();
- checkUrl(appName as string, "Page2", "custom", false);
- deployMode.NavigateBacktoEditor();
+ it("2. Custom slug change updates URL", () => {
+ _.appSettings.OpenAppSettings();
+ _.appSettings.GoToPageSettings("Page2");
+ _.pageSettings.UpdateCustomSlugAndVerifyUrl("custom");
+ _.homePage.GetAppName().then((appName) => {
+ _.deployMode.DeployApp();
+ _.appSettings.CheckUrl(appName as string, "Page2", "custom", false);
+ _.deployMode.NavigateBacktoEditor();
});
- cy.wait(2000);
+ _.agHelper.Sleep();
});
- it("Check default page is updated", () => {
- ee.AddNewPage();
- appSettings.OpenPaneFromCta();
- appSettings.GoToPageSettings("Page3");
- appSettings.page.setAsHomePage();
- appSettings.page.isHomePage("Page3");
+ it("3. Check SetAsHome page setting", () => {
+ _.ee.AddNewPage();
+ _.appSettings.OpenAppSettings();
+ _.appSettings.GoToPageSettings("Page3");
+ _.pageSettings.ToggleHomePage();
+ _.pageSettings.AssertHomePage("Page3");
});
- it("Check page navigation is updated", () => {
- agHelper.GetNClick(commonLocators._previewModeToggle);
- agHelper.AssertElementExist(commonLocators._deployedPage);
- agHelper.GetNClick(commonLocators._editModeToggle);
- appSettings.OpenPaneFromCta();
- appSettings.GoToPageSettings("Page2");
- appSettings.page.changePageNavigationSetting();
- agHelper.GetNClick(commonLocators._previewModeToggle);
- agHelper.AssertElementAbsence(commonLocators._deployedPage);
- agHelper.GetNClick(commonLocators._editModeToggle);
+ it("4. Check SetPageNavigation settings", () => {
+ _.agHelper.GetNClick(_.locators._previewModeToggle);
+ _.agHelper.AssertElementExist(_.locators._deployedPage);
+ _.agHelper.GetNClick(_.locators._editModeToggle);
+ _.appSettings.OpenAppSettings();
+ _.appSettings.GoToPageSettings("Page2");
+ _.pageSettings.TogglePageNavigation();
+ _.agHelper.GetNClick(_.locators._previewModeToggle);
+ _.agHelper.AssertElementAbsence(_.locators._deployedPage);
+ _.agHelper.GetNClick(_.locators._editModeToggle);
+ });
+
+ it("5. Page name allows accented character", () => {
+ _.appSettings.OpenAppSettings();
+ _.appSettings.GoToPageSettings("Page3");
+ _.pageSettings.UpdatePageNameAndVerifyUrl("Page3œßð", "Page3");
+ _.appSettings.ClosePane();
+ });
+
+ it("6. Page name doesn't allow special character", () => {
+ _.appSettings.OpenAppSettings();
+ _.appSettings.GoToPageSettings("Page3");
+ _.pageSettings.UpdatePageNameAndVerifyTextValue("Page3!@#", "Page3 ");
+ _.appSettings.ClosePane();
+ });
+
+ it("7. Page name doesn't allow empty", () => {
+ _.appSettings.OpenAppSettings();
+ _.appSettings.GoToPageSettings("Page3");
+ _.pageSettings.AssertPageErrorMessage(
+ "",
+ "Page name cannot be empty",
+ );
+ _.appSettings.ClosePane();
+ });
+
+ it("8. Bug #18698 : Page name doesn't allow duplicate name", () => {
+ _.appSettings.OpenAppSettings();
+ _.appSettings.GoToPageSettings("Page3");
+ _.pageSettings.AssertPageErrorMessage(
+ "Page2",
+ "Page2 is already being used.",
+ );
+ _.appSettings.ClosePane();
+ });
+
+ it("9. Page name doesn't allow keywords", () => {
+ _.appSettings.OpenAppSettings();
+ _.appSettings.GoToPageSettings("Page3");
+ _.pageSettings.AssertPageErrorMessage(
+ "appsmith",
+ "appsmith is already being used.",
+ );
+ _.appSettings.ClosePane();
+ });
+
+ it("10. Custom slug doesn't allow special/accented characters", () => {
+ _.appSettings.OpenAppSettings();
+ _.appSettings.GoToPageSettings("Page2");
+ _.pageSettings.UpdateCustomSlugAndVerifyTextValue(
+ "custom-slug!@#œßð",
+ "custom-slug",
+ );
+ _.appSettings.ClosePane();
});
});
diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ThemingTests/Basic_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ThemingTests/Basic_spec.js
index 3549574ce9..87b257a322 100644
--- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ThemingTests/Basic_spec.js
+++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ThemingTests/Basic_spec.js
@@ -26,7 +26,7 @@ describe("App Theming funtionality", function() {
themesSection(sectionName, themeName) + "/following-sibling::button";
it("1. Checks if theme can be changed to one of the existing themes", function() {
- appSettings.OpenPaneFromCta();
+ appSettings.OpenAppSettings();
appSettings.GoToThemeSettings();
cy.get(commonlocators.changeThemeBtn).click({ force: true });
@@ -70,7 +70,7 @@ describe("App Theming funtionality", function() {
.first(0)
.trigger("click", { force: true });
- appSettings.OpenPaneFromCta();
+ appSettings.OpenAppSettings();
appSettings.GoToThemeSettings();
//Click the back button //Commenting below since expanded by default
@@ -219,7 +219,7 @@ describe("App Theming funtionality", function() {
.first(0)
.trigger("click", { force: true });
- appSettings.OpenPaneFromCta();
+ appSettings.OpenAppSettings();
appSettings.GoToThemeSettings();
//#region Change Font & verify widgets:
// cy.contains("Font")
@@ -1009,7 +1009,7 @@ describe("App Theming funtionality", function() {
.first(0)
.trigger("click", { force: true });
- appSettings.OpenPaneFromCta();
+ appSettings.OpenAppSettings();
appSettings.GoToThemeSettings();
cy.get(commonlocators.changeThemeBtn).click({ force: true });
diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ThemingTests/ThemeReset_spec.ts b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ThemingTests/ThemeReset_spec.js
similarity index 97%
rename from app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ThemingTests/ThemeReset_spec.ts
rename to app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ThemingTests/ThemeReset_spec.js
index d5f914202c..dc5a8f3eac 100644
--- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ThemingTests/ThemeReset_spec.ts
+++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ThemingTests/ThemeReset_spec.js
@@ -24,7 +24,7 @@ describe("Theme validation usecases", function() {
// click on canvas to see the theming pane
cy.get("#canvas-selection-0").click({ force: true });
- appSettings.OpenPaneFromCta();
+ appSettings.OpenAppSettings();
appSettings.GoToThemeSettings();
// reset theme
cy.contains("Theme Properties")
diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ThemingTests/Theme_Default_spec.ts b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ThemingTests/Theme_Default_spec.js
similarity index 93%
rename from app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ThemingTests/Theme_Default_spec.ts
rename to app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ThemingTests/Theme_Default_spec.js
index b278a6b240..763b1c5ade 100644
--- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ThemingTests/Theme_Default_spec.ts
+++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ThemingTests/Theme_Default_spec.js
@@ -1,18 +1,14 @@
import { ObjectsRegistry } from "../../../../support/Objects/Registry";
-const testdata = require("../../../../fixtures/testdata.json");
-const apiwidget = require("../../../../locators/apiWidgetslocator.json");
const widgetsPage = require("../../../../locators/Widgets.json");
const explorer = require("../../../../locators/explorerlocators.json");
const commonlocators = require("../../../../locators/commonlocators.json");
const formWidgetsPage = require("../../../../locators/FormWidgets.json");
-const publish = require("../../../../locators/publishWidgetspage.json");
const themelocator = require("../../../../locators/ThemeLocators.json");
const appSettings = ObjectsRegistry.AppSettings;
let themeBackgroudColor;
-let themeFont;
describe("Theme validation for default data", function() {
it("Drag and drop form widget and validate Default color/font/shadow/border and list of font validation", function() {
@@ -33,7 +29,7 @@ describe("Theme validation for default data", function() {
cy.get(themelocator.canvas).click({ force: true });
cy.wait(2000);
- appSettings.OpenPaneFromCta();
+ appSettings.OpenAppSettings();
appSettings.GoToThemeSettings();
//Border validation
//cy.contains("Border").click({ force: true });
@@ -93,7 +89,7 @@ describe("Theme validation for default data", function() {
.should("have.css", "background-color")
.and("eq", "rgb(21, 128, 61)");
cy.get("#canvas-selection-0").click({ force: true });
- appSettings.OpenPaneFromCta();
+ appSettings.OpenAppSettings();
appSettings.GoToThemeSettings();
//Change the Theme
cy.get(commonlocators.changeThemeBtn).click({ force: true });
diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ThemingTests/Theme_FormWidget_spec.ts b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ThemingTests/Theme_FormWidget_spec.js
similarity index 99%
rename from app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ThemingTests/Theme_FormWidget_spec.ts
rename to app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ThemingTests/Theme_FormWidget_spec.js
index af99c37a6d..e41b1f1772 100644
--- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ThemingTests/Theme_FormWidget_spec.ts
+++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ThemingTests/Theme_FormWidget_spec.js
@@ -30,7 +30,7 @@ describe("Theme validation usecases", function() {
cy.get(themelocator.canvas).click({ force: true });
cy.wait(2000);
- appSettings.OpenPaneFromCta();
+ appSettings.OpenAppSettings();
appSettings.GoToThemeSettings();
//Border validation
//cy.contains("Border").click({ force: true });
@@ -185,7 +185,7 @@ describe("Theme validation usecases", function() {
.and("eq", "rgb(21, 128, 61)");
cy.get("#canvas-selection-0").click({ force: true });
- appSettings.OpenPaneFromCta();
+ appSettings.OpenAppSettings();
appSettings.GoToThemeSettings();
//Change the Theme
cy.get(commonlocators.changeThemeBtn).click({ force: true });
@@ -247,7 +247,7 @@ describe("Theme validation usecases", function() {
cy.get("#canvas-selection-0").click({ force: true });
- appSettings.OpenPaneFromCta();
+ appSettings.OpenAppSettings();
appSettings.GoToThemeSettings();
//Change the Theme
cy.get(commonlocators.changeThemeBtn).click({ force: true });
diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ThemingTests/Theme_MultiSelectWidget_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ThemingTests/Theme_MultiSelectWidget_spec.js
index 39210927b4..6552a77c27 100644
--- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ThemingTests/Theme_MultiSelectWidget_spec.js
+++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ThemingTests/Theme_MultiSelectWidget_spec.js
@@ -17,7 +17,7 @@ describe("Theme validation usecase for multi-select widget", function() {
cy.get(themelocator.canvas).click({ force: true });
cy.wait(2000);
- appSettings.OpenPaneFromCta();
+ appSettings.OpenAppSettings();
appSettings.GoToThemeSettings();
//Border validation
//cy.contains("Border").click({ force: true });
@@ -124,7 +124,7 @@ describe("Theme validation usecase for multi-select widget", function() {
it("3. Validate current theme feature", function() {
cy.get("#canvas-selection-0").click({ force: true });
- appSettings.OpenPaneFromCta();
+ appSettings.OpenAppSettings();
appSettings.GoToThemeSettings();
//Change the Theme
cy.get(commonlocators.changeThemeBtn).click({ force: true });
diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Widgets/Filepicker/FilePickerV2_Widget_Reskinning_spec.ts b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Widgets/Filepicker/FilePickerV2_Widget_Reskinning_spec.js
similarity index 96%
rename from app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Widgets/Filepicker/FilePickerV2_Widget_Reskinning_spec.ts
rename to app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Widgets/Filepicker/FilePickerV2_Widget_Reskinning_spec.js
index 854037cee9..b4294bbd8f 100644
--- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Widgets/Filepicker/FilePickerV2_Widget_Reskinning_spec.ts
+++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Widgets/Filepicker/FilePickerV2_Widget_Reskinning_spec.js
@@ -15,7 +15,7 @@ describe("Checkbox Widget Functionality", function() {
// Click on canvas to get global theme settings
cy.get(commonlocators.canvas).click({ force: true });
- appSettings.OpenPaneFromCta();
+ appSettings.OpenAppSettings();
appSettings.GoToThemeSettings();
cy.get(commonlocators.themeAppBorderRadiusBtn)
.last()
@@ -61,7 +61,7 @@ describe("Checkbox Widget Functionality", function() {
// Change the theme border radius to M and check if the remove file icon's border radius is 4px;
cy.get(commonlocators.canvas).click({ force: true });
- appSettings.OpenPaneFromCta();
+ appSettings.OpenAppSettings();
appSettings.GoToThemeSettings();
cy.get(commonlocators.themeAppBorderRadiusBtn)
.eq(1)
@@ -85,7 +85,7 @@ describe("Checkbox Widget Functionality", function() {
// Change the global theme primary color
cy.get(commonlocators.canvas).click({ force: true });
cy.wait(300);
- appSettings.OpenPaneFromCta();
+ appSettings.OpenAppSettings();
appSettings.GoToThemeSettings();
cy.get(themeLocator.inputColor).click({ force: true });
@@ -118,7 +118,7 @@ describe("Checkbox Widget Functionality", function() {
cy.get(".uppy-Dashboard-close").click({ force: true });
cy.get(commonlocators.canvas).click({ force: true });
cy.wait(300);
- appSettings.OpenPaneFromCta();
+ appSettings.OpenAppSettings();
appSettings.GoToThemeSettings();
cy.get(themeLocator.fontsSelected).click({ force: true });
diff --git a/app/client/cypress/support/Objects/ObjectsCore.ts b/app/client/cypress/support/Objects/ObjectsCore.ts
new file mode 100644
index 0000000000..d74b57dfce
--- /dev/null
+++ b/app/client/cypress/support/Objects/ObjectsCore.ts
@@ -0,0 +1,13 @@
+import { ObjectsRegistry } from "../Objects/Registry";
+
+export const agHelper = ObjectsRegistry.AggregateHelper;
+export const locators = ObjectsRegistry.CommonLocators;
+export const ee = ObjectsRegistry.EntityExplorer;
+export const jsEditor = ObjectsRegistry.JSEditor;
+export const propPane = ObjectsRegistry.PropertyPane;
+export const deployMode = ObjectsRegistry.DeployMode;
+export const appSettings = ObjectsRegistry.AppSettings;
+export const generalSettings = ObjectsRegistry.GeneralSettings;
+export const pageSettings = ObjectsRegistry.PageSettings;
+export const homePage = ObjectsRegistry.HomePage;
+export const theme = ObjectsRegistry.ThemeSettings;
diff --git a/app/client/cypress/support/Objects/Registry.ts b/app/client/cypress/support/Objects/Registry.ts
index 7965316a13..dffc1c7343 100644
--- a/app/client/cypress/support/Objects/Registry.ts
+++ b/app/client/cypress/support/Objects/Registry.ts
@@ -13,6 +13,9 @@ import { GitSync } from "../Pages/GitSync";
import { FakerHelper } from "../Pages/FakerHelper";
import { DebuggerHelper } from "../Pages/DebuggerHelper";
import { AppSettings } from "../Pages/AppSettings/AppSettings";
+import { GeneralSettings } from "../Pages/AppSettings/GeneralSettings";
+import { PageSettings } from "../Pages/AppSettings/PageSettings";
+import { ThemeSettings } from "../Pages/AppSettings/ThemeSettings";
export class ObjectsRegistry {
private static aggregateHelper__: AggregateHelper;
@@ -119,20 +122,44 @@ export class ObjectsRegistry {
return ObjectsRegistry.fakerHelper__;
}
- private static DebuggerHelper__: DebuggerHelper;
+ private static debuggerHelper__: DebuggerHelper;
static get DebuggerHelper(): DebuggerHelper {
- if (ObjectsRegistry.DebuggerHelper__ === undefined) {
- ObjectsRegistry.DebuggerHelper__ = new DebuggerHelper();
+ if (ObjectsRegistry.debuggerHelper__ === undefined) {
+ ObjectsRegistry.debuggerHelper__ = new DebuggerHelper();
}
- return ObjectsRegistry.DebuggerHelper__;
+ return ObjectsRegistry.debuggerHelper__;
}
- private static AppSettings__: AppSettings;
+ private static appSettings__: AppSettings;
static get AppSettings(): AppSettings {
- if (ObjectsRegistry.AppSettings__ === undefined) {
- ObjectsRegistry.AppSettings__ = new AppSettings();
+ if (ObjectsRegistry.appSettings__ === undefined) {
+ ObjectsRegistry.appSettings__ = new AppSettings();
}
- return ObjectsRegistry.AppSettings__;
+ return ObjectsRegistry.appSettings__;
+ }
+
+ private static generalSettings__: GeneralSettings;
+ static get GeneralSettings(): GeneralSettings {
+ if (ObjectsRegistry.generalSettings__ === undefined) {
+ ObjectsRegistry.generalSettings__ = new GeneralSettings();
+ }
+ return ObjectsRegistry.generalSettings__;
+ }
+
+ private static pageSettings__: PageSettings;
+ static get PageSettings(): PageSettings {
+ if (ObjectsRegistry.pageSettings__ === undefined) {
+ ObjectsRegistry.pageSettings__ = new PageSettings();
+ }
+ return ObjectsRegistry.pageSettings__;
+ }
+
+ private static themeSettings__: ThemeSettings;
+ static get ThemeSettings(): ThemeSettings {
+ if (ObjectsRegistry.themeSettings__ === undefined) {
+ ObjectsRegistry.themeSettings__ = new ThemeSettings();
+ }
+ return ObjectsRegistry.themeSettings__;
}
}
diff --git a/app/client/cypress/support/Pages/AggregateHelper.ts b/app/client/cypress/support/Pages/AggregateHelper.ts
index 7b6c999a87..4c713b36a8 100644
--- a/app/client/cypress/support/Pages/AggregateHelper.ts
+++ b/app/client/cypress/support/Pages/AggregateHelper.ts
@@ -526,10 +526,6 @@ export class AggregateHelper {
this.GetElement(selector).clear();
}
- public InvokeVal(selector: string) {
- return cy.get(selector).invoke("val");
- }
-
public TypeText(
selector: string,
value: string,
diff --git a/app/client/cypress/support/Pages/AppSettings/AppSettings.ts b/app/client/cypress/support/Pages/AppSettings/AppSettings.ts
index c523736cf6..699d75a2ce 100644
--- a/app/client/cypress/support/Pages/AppSettings/AppSettings.ts
+++ b/app/client/cypress/support/Pages/AppSettings/AppSettings.ts
@@ -1,12 +1,10 @@
import { ObjectsRegistry } from "../../Objects/Registry";
-import { ThemeSettings } from "./ThemeSettings";
-import { GeneralSettings } from "./GeneralSettings";
-import { PageSettings } from "./PageSettings";
-
export class AppSettings {
private agHelper = ObjectsRegistry.AggregateHelper;
+ private theme = ObjectsRegistry.ThemeSettings;
+
private locators = {
- _appSettings_cta: "#t--app-settings-cta",
+ _appSettings: "#t--app-settings-cta",
_closeSettings: "#t--close-app-settings-pane",
_themeSettingsHeader: "#t--theme-settings-header",
_generalSettingsHeader: "#t--general-settings-header",
@@ -14,12 +12,13 @@ export class AppSettings {
`#t--page-settings-${pageName}`,
};
- public readonly theme = new ThemeSettings();
- public readonly general = new GeneralSettings();
- public readonly page = new PageSettings();
+ public errorMessageSelector = (fieldId: string) => {
+ fieldId = fieldId[0] === "#" ? fieldId.slice(1, fieldId.length) : fieldId;
+ return `//input[@id='${fieldId}']/following-sibling::div/span`;
+ };
- public OpenPaneFromCta() {
- this.agHelper.GetNClick(this.locators._appSettings_cta);
+ public OpenAppSettings() {
+ this.agHelper.GetNClick(this.locators._appSettings);
}
public ClosePane() {
@@ -39,7 +38,7 @@ export class AppSettings {
}
public OpenPaneAndChangeTheme(themeName: string) {
- this.OpenPaneFromCta();
+ this.OpenAppSettings();
this.GoToThemeSettings();
this.theme.ChangeTheme(themeName);
this.ClosePane();
@@ -49,10 +48,70 @@ export class AppSettings {
primaryColorIndex: number,
backgroundColorIndex: number,
) {
- this.OpenPaneFromCta();
+ this.OpenAppSettings();
this.GoToThemeSettings();
this.theme.ChangeThemeColor(primaryColorIndex, "Primary");
this.theme.ChangeThemeColor(backgroundColorIndex, "Background");
this.ClosePane();
}
+
+ public CheckUrl(
+ appName: string,
+ pageName: string,
+ customSlug?: string,
+ editMode = true,
+ ) {
+ cy.location("pathname").then((pathname) => {
+ if (customSlug && customSlug.length > 0) {
+ const pageId = pathname
+ .split("/")[2]
+ ?.split("-")
+ .pop();
+ expect(pathname).to.be.equal(
+ `/app/${customSlug}-${pageId}${editMode ? "/edit" : ""}`.toLowerCase(),
+ );
+ } else {
+ const pageId = pathname
+ .split("/")[3]
+ ?.split("-")
+ .pop();
+ expect(pathname).to.be.equal(
+ `/app/${appName}/${pageName}-${pageId}${
+ editMode ? "/edit" : ""
+ }`.toLowerCase(),
+ );
+ }
+ });
+ };
+
+ public AssertErrorMessage(
+ fieldId: string,
+ newValue: string,
+ errorMessage: string,
+ resetValue = true,
+ ) {
+ this.agHelper.GetText(fieldId, "val").then((currentValue) => {
+ if (newValue.length === 0) this.agHelper.ClearTextField(fieldId);
+ else
+ this.agHelper.RemoveCharsNType(
+ fieldId,
+ (currentValue as string).length,
+ newValue,
+ );
+ this.agHelper.AssertText(
+ this.errorMessageSelector(fieldId),
+ "text",
+ errorMessage,
+ );
+ if (resetValue) {
+ this.agHelper.RemoveCharsNType(
+ fieldId,
+ newValue.length,
+ currentValue as string,
+ );
+ }
+ });
+ }
+
+
}
diff --git a/app/client/cypress/support/Pages/AppSettings/GeneralSettings.ts b/app/client/cypress/support/Pages/AppSettings/GeneralSettings.ts
index 92653276cc..6c46b860cd 100644
--- a/app/client/cypress/support/Pages/AppSettings/GeneralSettings.ts
+++ b/app/client/cypress/support/Pages/AppSettings/GeneralSettings.ts
@@ -1,45 +1,58 @@
import { ObjectsRegistry } from "../../Objects/Registry";
-import { checkUrl } from "./Utils";
export class GeneralSettings {
private agHelper = ObjectsRegistry.AggregateHelper;
+ private appSettings = ObjectsRegistry.AppSettings;
+
private locators = {
- appNameField: "#t--general-settings-app-name",
- appNonSelectedIcon: ".t--icon-not-selected",
- appIconSelector: "#t--general-settings-app-icon",
+ _appNameField: "#t--general-settings-app-name",
+ _appNonSelectedIcon: ".t--icon-not-selected",
+ _appIconSelector: "#t--general-settings-app-icon",
};
- changeAppNameAndVerifyUrl(
+ UpdateAppNameAndVerifyUrl(
reset: boolean,
newAppName: string,
+ verifyAppNameAs?: string,
pageName = "page1",
) {
+ const appNameToBeVerified = verifyAppNameAs ?? newAppName;
this.agHelper
- .InvokeVal(this.locators.appNameField)
+ .GetText(this.locators._appNameField, "val")
.then((currentAppName) => {
this.agHelper.RemoveCharsNType(
- this.locators.appNameField,
+ this.locators._appNameField,
(currentAppName as string).length,
newAppName,
);
this.agHelper.PressEnter();
+ this.agHelper.Sleep();
this.agHelper.ValidateNetworkStatus("@updateApplication", 200);
- checkUrl(newAppName, pageName);
+ this.appSettings.CheckUrl(appNameToBeVerified, pageName);
if (reset) {
this.agHelper.RemoveCharsNType(
- this.locators.appNameField,
+ this.locators._appNameField,
newAppName.length,
currentAppName as string,
);
this.agHelper.PressEnter();
this.agHelper.ValidateNetworkStatus("@updateApplication", 200);
- checkUrl(currentAppName as string, pageName);
+ this.appSettings.CheckUrl(currentAppName as string, pageName);
}
});
}
- changeAppIcon() {
- this.agHelper.GetNClick(this.locators.appNonSelectedIcon, 0);
+ AssertAppErrorMessage(newAppName: string, errorMessage: string) {
+ this.appSettings.AssertErrorMessage(
+ this.locators._appNameField,
+ newAppName,
+ errorMessage,
+ true,
+ );
+ }
+
+ UpdateAppIcon() {
+ this.agHelper.GetNClick(this.locators._appNonSelectedIcon, 0);
this.agHelper.ValidateNetworkStatus("@updateApplication", 200);
}
}
diff --git a/app/client/cypress/support/Pages/AppSettings/PageSettings.ts b/app/client/cypress/support/Pages/AppSettings/PageSettings.ts
index e09038fd9a..debe15f7f2 100644
--- a/app/client/cypress/support/Pages/AppSettings/PageSettings.ts
+++ b/app/client/cypress/support/Pages/AppSettings/PageSettings.ts
@@ -1,76 +1,145 @@
import { ObjectsRegistry } from "../../Objects/Registry";
-import { checkUrl } from "./Utils";
export class PageSettings {
private agHelper = ObjectsRegistry.AggregateHelper;
private homePage = ObjectsRegistry.HomePage;
+ private appSettings = ObjectsRegistry.AppSettings;
+
private locators = {
- pageNameField: "#t--page-settings-name",
- customSlugField: "#t--page-settings-custom-slug",
- showPageNavSwitch: "#t--page-settings-show-nav-control",
- setAsHomePageSwitch: "#t--page-settings-home-page-control",
- homePageHeader: "#t--page-settings-default-page",
+ _pageNameField: "#t--page-settings-name",
+ _customSlugField: "#t--page-settings-custom-slug",
+ _showPageNavSwitch: "#t--page-settings-show-nav-control",
+ _setAsHomePageSwitch: "#t--page-settings-home-page-control",
+ _setHomePageToggle : ".bp3-control-indicator",
+ _homePageHeader: "#t--page-settings-default-page",
};
- changePageNameAndVerifyUrl(newPageName: string) {
+ UpdatePageNameAndVerifyTextValue(newPageName: string, verifyPageNameAs: string) {
+ this.AssertPageValue(
+ this.locators._pageNameField,
+ newPageName,
+ verifyPageNameAs,
+ );
+ }
+
+ UpdateCustomSlugAndVerifyTextValue(
+ newCustomSlug: string,
+ verifyCustomSlugAs: string,
+ ) {
+ this.AssertPageValue(
+ this.locators._customSlugField,
+ newCustomSlug,
+ verifyCustomSlugAs,
+ );
+ }
+
+ public AssertPageValue(
+ locator: string,
+ newValue: string,
+ verifyValueAs: string,
+ ) {
+ this.agHelper.GetText(locator, "val").then((currentValue) => {
+ const currentValueLength = (currentValue as string).length;
+ if (currentValueLength === 0) this.agHelper.TypeText(locator, newValue);
+ else
+ this.agHelper.RemoveCharsNType(locator, currentValueLength, newValue);
+
+ this.agHelper.GetText(locator, "val").then((fieldValue) => {
+ expect(fieldValue).to.equal(verifyValueAs);
+ if (currentValueLength === 0) this.agHelper.ClearTextField(locator);
+ else
+ this.agHelper.RemoveCharsNType(
+ locator,
+ (fieldValue as string).length,
+ currentValue as string,
+ );
+ });
+ });
+ }
+
+ UpdatePageNameAndVerifyUrl(
+ newPageName: string,
+ verifyPageNameAs?: string,
+ reset = true,
+ ) {
+ const pageNameToBeVerified = verifyPageNameAs ?? newPageName;
this.agHelper
- .InvokeVal(this.locators.pageNameField)
+ .GetText(this.locators._pageNameField, "val")
.then((currentPageName) => {
const currentPageNameLength = (currentPageName as string).length;
this.homePage.GetAppName().then((appName) => {
this.agHelper.RemoveCharsNType(
- this.locators.pageNameField,
+ this.locators._pageNameField,
currentPageNameLength,
newPageName,
);
this.agHelper.PressEnter();
this.agHelper.ValidateNetworkStatus("@updatePage", 200);
- checkUrl(appName as string, newPageName);
+ this.appSettings.CheckUrl(appName as string, pageNameToBeVerified);
+ if (reset) {
+ this.agHelper.RemoveCharsNType(
+ this.locators._pageNameField,
+ newPageName.length,
+ currentPageName as string,
+ );
+ this.agHelper.PressEnter();
+ this.agHelper.ValidateNetworkStatus("@updatePage", 200);
+ this.appSettings.CheckUrl(appName as string, currentPageName as string);
+ }
});
});
}
- changeCustomSlugAndVerifyUrl(customSlug: string) {
+ UpdateCustomSlugAndVerifyUrl(customSlug: string) {
this.agHelper
- .InvokeVal(this.locators.customSlugField)
+ .GetText(this.locators._customSlugField, "val")
.then((currentCustomSlug) => {
const currentCustomSlugLength = (currentCustomSlug as string).length;
this.homePage.GetAppName().then((appName) => {
if (currentCustomSlugLength === 0) {
- this.agHelper.TypeText(this.locators.customSlugField, customSlug);
+ this.agHelper.TypeText(this.locators._customSlugField, customSlug);
} else {
this.agHelper.RemoveCharsNType(
- this.locators.customSlugField,
+ this.locators._customSlugField,
currentCustomSlugLength,
customSlug,
);
}
this.agHelper.PressEnter();
this.agHelper.ValidateNetworkStatus("@updatePage", 200);
- checkUrl(appName as string, "", customSlug);
+ this.appSettings.CheckUrl(appName as string, "", customSlug);
});
});
}
- changePageNavigationSetting() {
+ AssertPageErrorMessage(newPageName: string, errorMessage: string) {
+ this.appSettings.AssertErrorMessage(
+ this.locators._pageNameField,
+ newPageName,
+ errorMessage,
+ true,
+ );
+ }
+
+ TogglePageNavigation() {
this.agHelper.GetSiblingNClick(
- this.locators.showPageNavSwitch,
- ".bp3-control-indicator",
+ this.locators._showPageNavSwitch,
+ this.locators._setHomePageToggle,
);
this.agHelper.ValidateNetworkStatus("@updatePage", 200);
}
- setAsHomePage() {
+ ToggleHomePage() {
this.agHelper.GetSiblingNClick(
- this.locators.setAsHomePageSwitch,
- ".bp3-control-indicator",
+ this.locators._setAsHomePageSwitch,
+ this.locators._setHomePageToggle,
);
this.agHelper.ValidateNetworkStatus("@makePageDefault", 200);
}
- isHomePage(pageName: string) {
- this.agHelper.AssertText(this.locators.homePageHeader, "text", pageName);
+ AssertHomePage(pageName: string) {
+ this.agHelper.AssertText(this.locators._homePageHeader, "text", pageName);
}
}
diff --git a/app/client/src/ce/constants/messages.ts b/app/client/src/ce/constants/messages.ts
index 2afcaa6091..4308f6daa3 100644
--- a/app/client/src/ce/constants/messages.ts
+++ b/app/client/src/ce/constants/messages.ts
@@ -1391,12 +1391,14 @@ export const PAGE_SETTINGS_PAGE_URL_VERSION_UPDATE_3 = () =>
"your app URL to new readable format to change this";
export const PAGE_SETTINGS_SHOW_PAGE_NAV = () => "Show page navigation";
export const PAGE_SETTINGS_SHOW_PAGE_NAV_TOOLTIP = () =>
- "Hide or show the appsmith navbar containing the app name and page switcher";
+ "Show or hide the page in the appsmith navbar in view mode";
export const PAGE_SETTINGS_SET_AS_HOMEPAGE = () => "Set as home page";
export const PAGE_SETTINGS_SET_AS_HOMEPAGE_TOOLTIP = () =>
"This is the current home page, you can change this by setting another page as the home page";
export const PAGE_SETTINGS_SET_AS_HOMEPAGE_TOOLTIP_NON_HOME_PAGE = () =>
"Set this page as your home page. This will override your previously set home page.";
+export const PAGE_SETTINGS_ACTION_NAME_CONFLICT_ERROR = (name: string) =>
+ `${name} is already being used.`;
// Alert options and labels for showMessage types
export const ALERT_STYLE_OPTIONS = [
diff --git a/app/client/src/entities/URLRedirect/URLAssembly.ts b/app/client/src/entities/URLRedirect/URLAssembly.ts
index 50d81e181f..6950294984 100644
--- a/app/client/src/entities/URLRedirect/URLAssembly.ts
+++ b/app/client/src/entities/URLRedirect/URLAssembly.ts
@@ -169,7 +169,7 @@ export class URLBuilder {
baseURLRegistry[URL_TYPE.CUSTOM_SLUG][APP_MODE.PUBLISHED];
return generatePath(urlPattern, {
pageId,
- customSlug: `${customSlug.replaceAll(" ", "-")}-`,
+ customSlug: `${customSlug}-`,
}).toLowerCase();
}
@@ -182,7 +182,7 @@ export class URLBuilder {
const formattedParams = this.getFormattedParams(pageId);
- formattedParams.pageSlug = `${pageName.replaceAll(" ", "-")}-`;
+ formattedParams.pageSlug = `${pageName}-`;
return generatePath(urlPattern, formattedParams).toLowerCase();
}
diff --git a/app/client/src/pages/Editor/AppSettingsPane/AppSettings/GeneralSettings.tsx b/app/client/src/pages/Editor/AppSettingsPane/AppSettings/GeneralSettings.tsx
index 7a03176afd..f31903563d 100644
--- a/app/client/src/pages/Editor/AppSettingsPane/AppSettings/GeneralSettings.tsx
+++ b/app/client/src/pages/Editor/AppSettingsPane/AppSettings/GeneralSettings.tsx
@@ -4,7 +4,6 @@ import {
GENERAL_SETTINGS_APP_ICON_LABEL,
GENERAL_SETTINGS_APP_NAME_LABEL,
GENERAL_SETTINGS_NAME_EMPTY_MESSAGE,
- GENERAL_SETTINGS_NAME_SPECIAL_CHARACTER_ERROR,
} from "ce/constants/messages";
import classNames from "classnames";
import {
@@ -24,9 +23,7 @@ import {
} from "selectors/applicationSelectors";
import { getCurrentApplicationId } from "selectors/editorSelectors";
import styled from "styled-components";
-import { checkRegex } from "utils/validation/CheckRegex";
import TextLoaderIcon from "../Components/TextLoaderIcon";
-import { appNameRegex } from "../Utils";
const IconSelectorWrapper = styled.div`
position: relative;
@@ -60,8 +57,8 @@ function GeneralSettings() {
);
useEffect(() => {
- setApplicationName(application?.name);
- }, [application?.name]);
+ !isSavingAppName && setApplicationName(application?.name);
+ }, [application, application?.name, isSavingAppName]);
const updateAppSettings = useCallback(
debounce((icon?: AppIconName) => {
@@ -106,13 +103,20 @@ function GeneralSettings() {
}}
placeholder="App name"
type="input"
- validator={checkRegex(
- appNameRegex,
- GENERAL_SETTINGS_NAME_SPECIAL_CHARACTER_ERROR(),
- true,
- setIsAppNameValid,
- GENERAL_SETTINGS_NAME_EMPTY_MESSAGE(),
- )}
+ validator={(value: string) => {
+ let result: { isValid: boolean; message?: string } = {
+ isValid: true,
+ };
+ if (!value || value.trim().length === 0) {
+ setIsAppNameValid(false);
+ result = {
+ isValid: false,
+ message: GENERAL_SETTINGS_NAME_EMPTY_MESSAGE(),
+ };
+ }
+ setIsAppNameValid(result.isValid);
+ return result;
+ }}
value={applicationName}
/>
diff --git a/app/client/src/pages/Editor/AppSettingsPane/AppSettings/PageSettings.tsx b/app/client/src/pages/Editor/AppSettingsPane/AppSettings/PageSettings.tsx
index 47fed5b0a6..d828ad59c6 100644
--- a/app/client/src/pages/Editor/AppSettingsPane/AppSettings/PageSettings.tsx
+++ b/app/client/src/pages/Editor/AppSettingsPane/AppSettings/PageSettings.tsx
@@ -13,7 +13,7 @@ import {
PAGE_SETTINGS_NAME_EMPTY_MESSAGE,
PAGE_SETTINGS_SHOW_PAGE_NAV_TOOLTIP,
PAGE_SETTINGS_SET_AS_HOMEPAGE_TOOLTIP_NON_HOME_PAGE,
- PAGE_SETTINGS_NAME_SPECIAL_CHARACTER_ERROR as PAGE_SETTINGS_SPECIAL_CHARACTER_ERROR,
+ PAGE_SETTINGS_ACTION_NAME_CONFLICT_ERROR,
} from "ce/constants/messages";
import { Page } from "ce/constants/ReduxActionConstants";
import { hasManagePagePermission } from "@appsmith/utils/permissionHelpers";
@@ -24,7 +24,7 @@ import AdsSwitch from "design-system/build/Switch";
import ManualUpgrades from "pages/Editor/BottomBar/ManualUpgrades";
import PropertyHelpLabel from "pages/Editor/PropertyPane/PropertyHelpLabel";
import React, { useCallback, useEffect, useState } from "react";
-import { useDispatch, useSelector } from "react-redux";
+import { shallowEqual, useDispatch, useSelector } from "react-redux";
import {
getCurrentApplicationId,
selectApplicationVersion,
@@ -32,9 +32,11 @@ import {
import { getUpdatingEntity } from "selectors/explorerSelector";
import { getPageLoadingState } from "selectors/pageListSelectors";
import styled from "styled-components";
-import { checkRegex } from "utils/validation/CheckRegex";
import TextLoaderIcon from "../Components/TextLoaderIcon";
-import { getUrlPreview, specialCharacterCheckRegex } from "../Utils";
+import { getUrlPreview } from "../Utils";
+import { AppState } from "ce/reducers";
+import { getUsedActionNames } from "selectors/actionSelectors";
+import { isNameValid, resolveAsSpaceChar } from "utils/helpers";
const SwitchWrapper = styled.div`
&&&&&&&
@@ -79,6 +81,8 @@ const UrlPreviewScroll = styled.div`
}
`;
+const specialCharacterCheckRegex = /^[A-Za-z0-9\s\-]+$/g;
+
function PageSettings(props: { page: Page }) {
const dispatch = useDispatch();
const page = props.page;
@@ -100,7 +104,6 @@ function PageSettings(props: { page: Page }) {
const [isPageNameValid, setIsPageNameValid] = useState(true);
const [customSlug, setCustomSlug] = useState(page.customSlug);
- const [isCustomSlugValid, setIsCustomSlugValid] = useState(true);
const [isCustomSlugSaving, setIsCustomSlugSaving] = useState(false);
const [isShown, setIsShown] = useState(!!!page.isHidden);
@@ -117,6 +120,16 @@ function PageSettings(props: { page: Page }) {
page.customSlug,
])(page.pageId, pageName, page.pageName, customSlug, page.customSlug);
+ const conflictingNames = useSelector(
+ (state: AppState) => getUsedActionNames(state, ""),
+ shallowEqual,
+ );
+
+ const hasActionNameConflict = useCallback(
+ (name: string) => !isNameValid(name, conflictingNames),
+ [conflictingNames],
+ );
+
useEffect(() => {
setPageName(page.pageName);
setCustomSlug(page.customSlug || "");
@@ -151,15 +164,14 @@ function PageSettings(props: { page: Page }) {
}, [page.pageId, page.pageName, pageName, isPageNameValid]);
const saveCustomSlug = useCallback(() => {
- if (!canManagePages || !isCustomSlugValid || page.customSlug === customSlug)
- return;
+ if (!canManagePages || page.customSlug === customSlug) return;
const payload: UpdatePageRequest = {
id: page.pageId,
customSlug: customSlug || "",
};
setIsCustomSlugSaving(true);
dispatch(updatePage(payload));
- }, [page.pageId, page.customSlug, customSlug, isCustomSlugValid]);
+ }, [page.pageId, page.customSlug, customSlug]);
const saveIsShown = useCallback(
(isShown: boolean) => {
@@ -190,7 +202,9 @@ function PageSettings(props: { page: Page }) {
fill
id="t--page-settings-name"
onBlur={savePageName}
- onChange={setPageName}
+ onChange={(value: string) =>
+ setPageName(resolveAsSpaceChar(value, 30))
+ }
onKeyPress={(ev: React.KeyboardEvent) => {
if (ev.key === "Enter") {
savePageName();
@@ -198,13 +212,27 @@ function PageSettings(props: { page: Page }) {
}}
placeholder="Page name"
type="input"
- validator={checkRegex(
- specialCharacterCheckRegex,
- PAGE_SETTINGS_SPECIAL_CHARACTER_ERROR(),
- true,
- setIsPageNameValid,
- PAGE_SETTINGS_NAME_EMPTY_MESSAGE(),
- )}
+ validator={(value: string) => {
+ let result: { isValid: boolean; message?: string } = {
+ isValid: true,
+ };
+ if (!value || value.trim().length === 0) {
+ result = {
+ isValid: false,
+ message: PAGE_SETTINGS_NAME_EMPTY_MESSAGE(),
+ };
+ } else if (
+ value !== page.pageName &&
+ hasActionNameConflict(value)
+ ) {
+ result = {
+ isValid: false,
+ message: PAGE_SETTINGS_ACTION_NAME_CONFLICT_ERROR(value),
+ };
+ }
+ setIsPageNameValid(result.isValid);
+ return result;
+ }}
value={pageName}
/>
@@ -230,7 +258,6 @@ function PageSettings(props: { page: Page }) {
className={classNames({
"py-1 relative": true,
"pb-2": appNeedsUpdate,
- "pb-6": !appNeedsUpdate && !isCustomSlugValid,
})}
>
{isCustomSlugSaving && }
@@ -240,7 +267,11 @@ function PageSettings(props: { page: Page }) {
fill
id="t--page-settings-custom-slug"
onBlur={saveCustomSlug}
- onChange={setCustomSlug}
+ onChange={(value: string) =>
+ value.length > 0
+ ? specialCharacterCheckRegex.test(value) && setCustomSlug(value)
+ : setCustomSlug(value)
+ }
onKeyPress={(ev: React.KeyboardEvent) => {
if (ev.key === "Enter") {
saveCustomSlug();
@@ -249,12 +280,6 @@ function PageSettings(props: { page: Page }) {
placeholder="Page URL"
readOnly={appNeedsUpdate}
type="input"
- validator={checkRegex(
- specialCharacterCheckRegex,
- PAGE_SETTINGS_SPECIAL_CHARACTER_ERROR(),
- false,
- setIsCustomSlugValid,
- )}
value={customSlug}
/>
diff --git a/app/client/src/pages/Editor/AppSettingsPane/Utils.ts b/app/client/src/pages/Editor/AppSettingsPane/Utils.ts
index 2bda24f6d6..9a00aa9bc1 100644
--- a/app/client/src/pages/Editor/AppSettingsPane/Utils.ts
+++ b/app/client/src/pages/Editor/AppSettingsPane/Utils.ts
@@ -2,9 +2,6 @@ import { APP_MODE } from "entities/App";
import urlBuilder from "entities/URLRedirect/URLAssembly";
import { splitPathPreview } from "utils/helpers";
-export const specialCharacterCheckRegex = /^[A-Za-z0-9\s\-]+$/;
-export const appNameRegex = /^[A-Za-z0-9\s\-()]+$/;
-
export const getUrlPreview = (
pageId: string,
newPageName: string,
@@ -14,6 +11,13 @@ export const getUrlPreview = (
) => {
let relativePath: string;
+ newPageName = filterAccentedAndSpecialCharacters(newPageName);
+ currentPageName = filterAccentedAndSpecialCharacters(currentPageName);
+ newCustomSlug &&
+ (newCustomSlug = filterAccentedAndSpecialCharacters(newCustomSlug));
+ currentCustomSlug &&
+ (currentCustomSlug = filterAccentedAndSpecialCharacters(currentCustomSlug));
+
// when page name is changed
// and when custom slug doesn't exist
if (!newCustomSlug && newPageName !== currentPageName) {
@@ -41,3 +45,9 @@ export const getUrlPreview = (
splitRelativePath: splitPathPreview(relativePath, newCustomSlug),
};
};
+
+const filterAccentedAndSpecialCharacters = (value: string) => {
+ return decodeURI(value)
+ .replaceAll(" ", "-")
+ .replaceAll(/[^A-Za-z0-9-]/g, "");
+};
diff --git a/app/client/src/pages/Editor/CanvasPropertyPane/index.tsx b/app/client/src/pages/Editor/CanvasPropertyPane/index.tsx
index dea09461d7..3ad79ef85d 100644
--- a/app/client/src/pages/Editor/CanvasPropertyPane/index.tsx
+++ b/app/client/src/pages/Editor/CanvasPropertyPane/index.tsx
@@ -39,7 +39,7 @@ export function CanvasPropertyPane() {
position={PopoverPosition.BOTTOM}
>