fix: update settings pane validations (#18739)
* init fix * button style update * decode url in preview * bring back custom slug validation * custom slug validation on type * remove imports * handle special characters in url preview * change label * code clean up * remove pageId from action name selector * messages clean up * tests for validations * cypress cases update * Renamed helper methods * add index for test cases * AppSettings specs script ts updates * Added Bud id in title #18698 * GIt Import spec fix * GItImport spec fix * Git import unskip * Skipping Git import Co-authored-by: Aishwarya UR <aishwarya@appsmith.com>
This commit is contained in:
parent
f67f8571ec
commit
284571803b
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 });
|
||||
|
||||
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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 });
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
@ -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 });
|
||||
|
|
@ -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 });
|
||||
|
|
@ -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 });
|
||||
|
|
|
|||
|
|
@ -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 });
|
||||
13
app/client/cypress/support/Objects/ObjectsCore.ts
Normal file
13
app/client/cypress/support/Objects/ObjectsCore.ts
Normal file
|
|
@ -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;
|
||||
|
|
@ -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__;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 = [
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -230,7 +258,6 @@ function PageSettings(props: { page: Page }) {
|
|||
className={classNames({
|
||||
"py-1 relative": true,
|
||||
"pb-2": appNeedsUpdate,
|
||||
"pb-6": !appNeedsUpdate && !isCustomSlugValid,
|
||||
})}
|
||||
>
|
||||
{isCustomSlugSaving && <TextLoaderIcon />}
|
||||
|
|
@ -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}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -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, "");
|
||||
};
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ export function CanvasPropertyPane() {
|
|||
position={PopoverPosition.BOTTOM}
|
||||
>
|
||||
<Button
|
||||
category={Category.tertiary}
|
||||
category={Category.secondary}
|
||||
fill
|
||||
id="t--app-settings-cta"
|
||||
onClick={openAppSettingsPane}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ export const GetNavigationMenuData = ({
|
|||
|
||||
return [
|
||||
{
|
||||
text: "Go to dashboard",
|
||||
text: "Home",
|
||||
onClick: () => history.replace(APPLICATIONS_URL),
|
||||
type: MenuTypes.MENU,
|
||||
isVisible: true,
|
||||
|
|
|
|||
|
|
@ -155,11 +155,6 @@ export function PageContextMenu(props: {
|
|||
</CustomLabel>
|
||||
) as ReactNode) as string,
|
||||
},
|
||||
{
|
||||
value: "settings",
|
||||
onSelect: openAppSettingsPane,
|
||||
label: createMessage(CONTEXT_SETTINGS),
|
||||
},
|
||||
!props.isDefaultPage &&
|
||||
canManagePages && {
|
||||
value: "setdefault",
|
||||
|
|
@ -173,6 +168,11 @@ export function PageContextMenu(props: {
|
|||
value: "setdefault",
|
||||
label: createMessage(CONTEXT_SET_AS_HOME_PAGE),
|
||||
},
|
||||
{
|
||||
value: "settings",
|
||||
onSelect: openAppSettingsPane,
|
||||
label: createMessage(CONTEXT_SETTINGS),
|
||||
},
|
||||
!props.isDefaultPage &&
|
||||
canDeletePages && {
|
||||
className: "t--apiFormDeleteBtn single-select",
|
||||
|
|
|
|||
|
|
@ -1,24 +0,0 @@
|
|||
export const checkRegex = (
|
||||
regex: RegExp,
|
||||
errorMessage: string,
|
||||
checkEmpty = true,
|
||||
callback?: (isValid: boolean) => void,
|
||||
emptyMessage = "Cannot be empty",
|
||||
) => {
|
||||
return (value: string) => {
|
||||
const isEmpty = value.length === 0;
|
||||
const regexMismatch = !isEmpty && !regex.test(value);
|
||||
const hasError = (checkEmpty && isEmpty) || regexMismatch;
|
||||
|
||||
callback?.(!hasError);
|
||||
|
||||
let message = "";
|
||||
if (checkEmpty && isEmpty) message = emptyMessage;
|
||||
else if (regexMismatch) message = errorMessage;
|
||||
|
||||
return {
|
||||
isValid: !hasError,
|
||||
message,
|
||||
};
|
||||
};
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user