diff --git a/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/ClearStore_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/ClearStore_spec.ts index 988a497ac1f4..84b6a484a6d3 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/ClearStore_spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/ClearStore_spec.ts @@ -79,6 +79,241 @@ describe( agHelper.ClickButton("ClearStore"); agHelper.AssertContains(JSON.stringify({})); deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + agHelper.GetNClick(propPane._deleteWidget); + EditorNavigation.SelectEntityByName("Button2", EntityType.Widget); + agHelper.GetNClick(propPane._deleteWidget); + }); + + it("2. To verify both persistent and session-specific stored values are cleared when clearStore() is called.", function () { + entityExplorer.DragDropWidgetNVerify("buttonwidget", 100, 100); + const JS_OBJECT_BODY = `export default { + storePersistentValue: async () => { + let values = [ + storeValue('persistentVal1', 'persistent value 1', true), + storeValue('persistentVal2', 'persistent value 2', true), + storeValue('sessionVal1', 'session value 1'), + storeValue('sessionVal2', 'session value 2'), + ]; + await Promise.all(values); + await showAlert(JSON.stringify(appsmith.store)); + }, + clearStore: async () => { + await clearStore(); + await showAlert(JSON.stringify(appsmith.store)); + } + }`; + + jsEditor.CreateJSObject(JS_OBJECT_BODY, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.UpdatePropertyFieldValue("Label", ""); + propPane.TypeTextIntoField("Label", "StorePersistentValue"); + cy.get("@jsObjName").then((jsObj: any) => { + propPane.SelectJSFunctionToExecute( + "onClick", + jsObj as string, + "storePersistentValue", + ); + }); + + entityExplorer.DragDropWidgetNVerify("buttonwidget", 200, 300); + EditorNavigation.SelectEntityByName("Button2", EntityType.Widget); + propPane.UpdatePropertyFieldValue("Label", ""); + propPane.TypeTextIntoField("Label", "ClearStore"); + cy.get("@jsObjName").then((jsObj: any) => { + propPane.SelectJSFunctionToExecute( + "onClick", + jsObj as string, + "clearStore", + ); + }); + + deployMode.DeployApp(); + agHelper.ClickButton("StorePersistentValue"); + agHelper.AssertContains( + JSON.stringify({ + persistentVal1: "persistent value 1", + persistentVal2: "persistent value 2", + sessionVal1: "session value 1", + sessionVal2: "session value 2", + }), + ); + agHelper.ClickButton("ClearStore"); + agHelper.AssertContains(JSON.stringify({})); + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + agHelper.GetNClick(propPane._deleteWidget); + EditorNavigation.SelectEntityByName("Button2", EntityType.Widget); + agHelper.GetNClick(propPane._deleteWidget); + }); + + it("3. To verify that clearStore() only removes values stored by the application and does not affect other unrelated data in the browser's local storage.", function () { + entityExplorer.DragDropWidgetNVerify("buttonwidget", 100, 100); + // Set some unrelated local storage data + cy.window().then((win) => { + win.localStorage.setItem("unrelatedKey1", "unrelated value 1"); + win.localStorage.setItem("unrelatedKey2", "unrelated value 2"); + }); + + entityExplorer.DragDropWidgetNVerify("buttonwidget", 100, 100); + const JS_OBJECT_BODY = `export default { + storeValue: async () => { + let values = [ + storeValue('val1', 'value 1'), + storeValue('val2', 'value 2'), + ]; + await Promise.all(values); + await showAlert(JSON.stringify(appsmith.store)); + }, + clearStore: async () => { + await clearStore(); + await showAlert(JSON.stringify(appsmith.store)); + } + }`; + + jsEditor.CreateJSObject(JS_OBJECT_BODY, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.UpdatePropertyFieldValue("Label", ""); + propPane.TypeTextIntoField("Label", "StoreValue"); + cy.get("@jsObjName").then((jsObj: any) => { + propPane.SelectJSFunctionToExecute( + "onClick", + jsObj as string, + "storeValue", + ); + }); + + entityExplorer.DragDropWidgetNVerify("buttonwidget", 200, 200); + EditorNavigation.SelectEntityByName("Button2", EntityType.Widget); + propPane.UpdatePropertyFieldValue("Label", ""); + propPane.TypeTextIntoField("Label", "ClearStore"); + cy.get("@jsObjName").then((jsObj: any) => { + propPane.SelectJSFunctionToExecute( + "onClick", + jsObj as string, + "clearStore", + ); + }); + + deployMode.DeployApp(); + agHelper.ClickButton("StoreValue"); + agHelper.AssertContains( + JSON.stringify({ + val1: "value 1", + val2: "value 2", + }), + ); + agHelper.ClickButton("ClearStore"); + agHelper.AssertContains(JSON.stringify({})); + + // Verify unrelated local storage data is not cleared + cy.window().then((win) => { + expect(win.localStorage.getItem("unrelatedKey1")).to.equal( + "unrelated value 1", + ); + expect(win.localStorage.getItem("unrelatedKey2")).to.equal( + "unrelated value 2", + ); + }); + + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + agHelper.GetNClick(propPane._deleteWidget); + EditorNavigation.SelectEntityByName("Button2", EntityType.Widget); + agHelper.GetNClick(propPane._deleteWidget); + }); + + it("4. To verify that clearStore() only affects the current tab's storage and does not inadvertently impact session storage across tabs.", function () { + entityExplorer.DragDropWidgetNVerify("buttonwidget", 100, 100); + const JS_OBJECT_BODY = `export default { + storeValue: async () => { + let values = [ + storeValue('val1', 'value 1'), + storeValue('val2', 'value 2'), + ]; + await Promise.all(values); + await showAlert(JSON.stringify(appsmith.store)); + }, + clearStore: async () => { + await clearStore(); + await showAlert(JSON.stringify(appsmith.store)); + } + }`; + + jsEditor.CreateJSObject(JS_OBJECT_BODY, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.UpdatePropertyFieldValue("Label", ""); + propPane.TypeTextIntoField("Label", "StoreValue"); + cy.get("@jsObjName").then((jsObj: any) => { + propPane.SelectJSFunctionToExecute( + "onClick", + jsObj as string, + "storeValue", + ); + }); + + entityExplorer.DragDropWidgetNVerify("buttonwidget", 200, 200); + EditorNavigation.SelectEntityByName("Button2", EntityType.Widget); + propPane.UpdatePropertyFieldValue("Label", ""); + propPane.TypeTextIntoField("Label", "ClearStore"); + cy.get("@jsObjName").then((jsObj: any) => { + propPane.SelectJSFunctionToExecute( + "onClick", + jsObj as string, + "clearStore", + ); + }); + + deployMode.DeployApp(); + agHelper.ClickButton("StoreValue"); + agHelper.AssertContains( + JSON.stringify({ + val1: "value 1", + val2: "value 2", + }), + ); + + // Open a new tab and verify the storage is not affected + cy.window().then((win) => { + const newTab = win.open(win.location.href, "_blank"); + if (newTab) { + cy.wrap(newTab).should(() => { + const isEmpty = Object.keys(newTab.localStorage).length === 0; + expect(isEmpty).to.be.false; + }); + newTab.close(); + } + }); + + agHelper.ClickButton("ClearStore"); + agHelper.AssertContains(JSON.stringify({})); + + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + agHelper.GetNClick(propPane._deleteWidget); + EditorNavigation.SelectEntityByName("Button2", EntityType.Widget); + agHelper.GetNClick(propPane._deleteWidget); }); }, ); diff --git a/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_ActionSelector_General_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_ActionSelector_General_spec.ts new file mode 100644 index 000000000000..977418d18044 --- /dev/null +++ b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_ActionSelector_General_spec.ts @@ -0,0 +1,216 @@ +import { + agHelper, + appSettings, + deployMode, + draggableWidgets, + entityExplorer, + homePage, + locators, + partialImportExport, + propPane, +} from "../../../../support/Objects/ObjectsCore"; +import EditorNavigation, { + EntityType, +} from "../../../../support/Pages/EditorNavigation"; +import PageList from "../../../../support/Pages/PageList"; + +describe( + "To verify action selector - action selector general functions", + { tags: ["@tag.JS"] }, + () => { + let modalTextValue: string, + currentAppName: string = "ActionSelectorAppNew", + currentWorkspace: string, + forkWorkspaceName: string; + + before(() => { + entityExplorer.DragDropWidgetNVerify(draggableWidgets.BUTTON); + cy.get("@workspaceName").then((workspaceName: any) => { + currentWorkspace = workspaceName; + }); + }); + + it("1. Verify that actions can be configured ", () => { + propPane.EnterJSContext( + "onClick", + `{{showAlert("Action Selector Test Message", '')}}`, + true, + ); + propPane.ToggleJSMode("onClick", false); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Action Selector Test Message", 0, 1); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Action Selector Test Message", 0, 1); + deployMode.NavigateBacktoEditor(); + }); + + it("2. Verify that callbacks can be configured with a success event", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.EnterJSContext( + "onClick", + `{{showAlert("Action Success Message", '')}}`, + ); + propPane.ToggleJSMode("onClick", false); + + agHelper.GetNClick(propPane._actionCardByTitle("Show alert")); + + // add a success callback + agHelper.GetNClick(propPane._actionAddCallback("success")); + agHelper.GetNClick(locators._dropDownValue("Show alert")); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Message"), + "Success Callback", + ); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Success Callback", 0, 1); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Success Callback", 0, 1); + deployMode.NavigateBacktoEditor(); + }); + + it("3. Verify that callbacks can be configured with a failure event", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + propPane.EnterJSContext("onClick", `{{showModal()}}`, true); + propPane.ToggleJSMode("onClick", false); + agHelper.GetHoverNClick(propPane._actionCallbacks); + + agHelper.GetNClick(propPane._actionAddCallback("failure")); + agHelper.GetNClick(locators._dropDownValue("Show alert")); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Message"), + "Failure Callback", + ); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Failure Callback", 0, 1); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Failure Callback", 0, 1); + deployMode.NavigateBacktoEditor(); + }); + + it("4. Verify that callbacks can be chained", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + agHelper.GetHoverNClick(propPane._actionCallbacks); + + agHelper.GetNClick(propPane._actionAddCallback("failure")); + agHelper.GetNClick(locators._dropDownValue("Show alert")); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Message"), + "Second Failure Callback", + ); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Second Failure Callback", 0, 1); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Second Failure Callback", 0, 1); + deployMode.NavigateBacktoEditor(); + }); + + it("5. Verify that the Callbacks section reflects the number of active callbacks accurately", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + agHelper.GetHoverNClick(propPane._actionCallbacks); + agHelper + .GetText(propPane._getActionCardSelector("modal")) + .then(($count) => { + modalTextValue = $count as string; + expect(modalTextValue).to.contain("+2"); + }); + }); + + it("6. Verify that callbacks can be deleted", () => { + agHelper.GetNClick(propPane._getActionCardSelector("alert"), 1); + agHelper.GetNClick(propPane._actionSelectorDelete, 0); + agHelper + .GetText(propPane._getActionCardSelector("modal")) + .then(($count) => { + modalTextValue = $count as string; + expect(modalTextValue).to.contain("+1"); + }); + }); + + it("7. Verify that configured actions stay intact on partial import of a page", () => { + PageList.AddNewPage("New blank page"); + partialImportExport.OpenImportModalWithPage("Page2"); + + // Import Widgets + partialImportExport.ImportPartiallyExportedFile( + "frameworkFunPartialPage.json", + "Widgets", + ["Button1"], + ); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("success alert", 0, 1); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("success alert", 0, 1); + deployMode.NavigateBacktoEditor(); + }); + + it("8. Verify that configured actions stay intact on navigating between pages", () => { + EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Failure Callback", 0, 1); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Failure Callback", 0, 1); + deployMode.NavigateBacktoEditor(); + }); + + it("9. Verify that configured actions stay intact on forking an app", () => { + homePage.RenameApplication("ActionSelectorAppNew"); + forkWorkspaceName = "ForkAppWorkspace"; + homePage.CreateNewWorkspace(forkWorkspaceName, true); + homePage.SelectWorkspace(currentWorkspace); + homePage.ForkApplication(currentAppName, forkWorkspaceName); + + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Failure Callback", 0, 1); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Failure Callback", 0, 1); + deployMode.NavigateBacktoEditor(); + }); + + it("10. Verify that configured actions stay intact on import of an app", () => { + homePage.NavigateToHome(); + homePage.ImportApp( + "ActionSelectorAppNewExported.json", + "ForkAppWorkspace", + ); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + agHelper + .GetText(propPane._getActionCardSelector("modal")) + .then(($count) => { + modalTextValue = $count as string; + expect(modalTextValue).to.contain("+1"); + }); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Failure Callback", 0, 1); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Failure Callback", 0, 1); + }); + }, +); diff --git a/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_ClearIntervalFunctions_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_ClearIntervalFunctions_spec.ts new file mode 100644 index 000000000000..f9ce06f5c26a --- /dev/null +++ b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_ClearIntervalFunctions_spec.ts @@ -0,0 +1,258 @@ +import { + agHelper, + appSettings, + deployMode, + homePage, + locators, +} from "../../../../support/Objects/ObjectsCore"; + +describe( + "To verify action selector - clearInterval function", + { tags: ["@tag.JS"] }, + () => { + before(() => { + homePage.NavigateToHome(); + homePage.ImportApp("clearIntervalApp.json"); + }); + + it("1. To verify that calling clearInterval() stops the interval from executing further.", () => { + agHelper.ClickButton("clearAllInterval"); + //Buttom mode verification + agHelper.ClickButton("setIntvl"); + agHelper.ValidateToastMessage("Interval started.", 0, 2); + agHelper.ClickButton("Submit1_1"); + agHelper.Sleep(6000); // This is mandatory sleep as we need to check interval is cleared. + agHelper.AssertElementAbsence(locators._toastMsg); + + //Deploy mode verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("setIntvl"); + agHelper.ValidateToastMessage("Interval started.", 0, 2); + agHelper.ClickButton("Submit1_1"); + agHelper.Sleep(6000); // This is mandatory sleep as we need to check interval is cleared. + agHelper.AssertElementAbsence(locators._toastMsg); + deployMode.NavigateBacktoEditor(); + + //JSObject mode verification + agHelper.ClickButton("clearAllInterval"); + agHelper.ClickButton("setIntvl"); + agHelper.ValidateToastMessage("Interval started.", 0, 2); + agHelper.ClickButton("Submit1_2"); + agHelper.Sleep(6000); // This is mandatory sleep as we need to check interval is cleared. + agHelper.AssertElementAbsence(locators._toastMsg); + + //Deploy mode verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("setIntvl"); + agHelper.ValidateToastMessage("Interval started.", 0, 2); + agHelper.ClickButton("Submit1_2"); + agHelper.Sleep(6000); // This is mandatory sleep as we need to check interval is cleared. + agHelper.AssertElementAbsence(locators._toastMsg); + deployMode.NavigateBacktoEditor(); + }); + + it("2. Verify the behaviour while clearing interval using wrong ID. The interval should not be cleared.", () => { + agHelper.ClickButton("clearAllInterval"); + //Buttom mode verification + agHelper.ClickButton("setIntvl"); + agHelper.ValidateToastMessage("Interval started.", 0, 2); + agHelper.ClickButton("Submit2_1"); + agHelper.Sleep(6000); // This is mandatory sleep as we need to check interval is not cleared. + agHelper.ValidateToastMessage("Interval started.", 0, 2); + + //Deploy mode verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("setIntvl"); + agHelper.ValidateToastMessage("Interval started.", 0, 2); + agHelper.ClickButton("Submit2_1"); + agHelper.Sleep(6000); // This is mandatory sleep as we need to check interval is not cleared. + agHelper.ValidateToastMessage("Interval started.", 0, 2); + deployMode.NavigateBacktoEditor(); + + //JSObject mode verification + agHelper.ClickButton("clearAllInterval"); + agHelper.ClickButton("setIntvl"); + agHelper.ValidateToastMessage("Interval started.", 0, 2); + agHelper.ClickButton("Submit2_2"); + agHelper.Sleep(6000); // This is mandatory sleep as we need to check interval is not cleared. + agHelper.ValidateToastMessage("Interval started.", 0, 2); + + //Deploy mode verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("setIntvl"); + agHelper.ValidateToastMessage("Interval started.", 0, 2); + agHelper.ClickButton("Submit2_2"); + agHelper.Sleep(6000); // This is mandatory sleep as we need to check interval is notcleared. + agHelper.ValidateToastMessage("Interval started.", 0, 2); + deployMode.NavigateBacktoEditor(); + }); + + it("3. Verify behavior when calling clearInterval() with an invalid or non-existent ID. No interval should be cleared, and the system should handle the invalid ID gracefully without errors.", () => { + agHelper.ClickButton("clearAllInterval"); + //Buttom mode verification + agHelper.ClickButton("setIntvl"); + agHelper.ValidateToastMessage("Interval started.", 0, 2); + agHelper.ClickButton("Submit3_1"); + agHelper.Sleep(6000); // This is mandatory sleep as we need to check interval is not cleared. + agHelper.ValidateToastMessage("Interval started.", 0, 2); + + //Deploy mode verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("setIntvl"); + agHelper.ValidateToastMessage("Interval started.", 0, 2); + agHelper.ClickButton("Submit3_1"); + agHelper.Sleep(6000); // This is mandatory sleep as we need to check interval is not cleared. + agHelper.ValidateToastMessage("Interval started.", 0, 2); + deployMode.NavigateBacktoEditor(); + + //JSObject mode verification + agHelper.ClickButton("clearAllInterval"); + agHelper.ClickButton("setIntvl"); + agHelper.ValidateToastMessage("Interval started.", 0, 2); + agHelper.ClickButton("Submit3_2"); + agHelper.Sleep(6000); // This is mandatory sleep as we need to check interval is not cleared. + agHelper.ValidateToastMessage("Interval started.", 0, 2); + + //Deploy mode verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("setIntvl"); + agHelper.ValidateToastMessage("Interval started.", 0, 2); + agHelper.ClickButton("Submit3_2"); + agHelper.Sleep(6000); // This is mandatory sleep as we need to check interval is not cleared. + agHelper.ValidateToastMessage("Interval started.", 0, 2); + deployMode.NavigateBacktoEditor(); + }); + + it("4. Verify that multiple intervals can be cleared simultaneously without any issues.", () => { + agHelper.ClickButton("clearAllInterval"); + //Buttom mode verification + agHelper.ClickButton("setMulIntrvl"); + agHelper.ValidateToastMessage("Interval 1", 0, 2); + agHelper.ValidateToastMessage("Interval 2", 0, 2); + agHelper.ClickButton("Submit4_1"); + agHelper.Sleep(6000); // This is mandatory sleep as we need to check interval is cleared. + agHelper.AssertElementAbsence(locators._toastMsg); + + //Deploy mode verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("setMulIntrvl"); + agHelper.ValidateToastMessage("Interval 1", 0, 2); + agHelper.ValidateToastMessage("Interval 2", 0, 2); + agHelper.ClickButton("Submit4_1"); + agHelper.Sleep(6000); // This is mandatory sleep as we need to check interval is cleared. + agHelper.AssertElementAbsence(locators._toastMsg); + deployMode.NavigateBacktoEditor(); + + //JSObject mode verification + agHelper.ClickButton("clearAllInterval"); + agHelper.ClickButton("setMulIntrvl"); + agHelper.ValidateToastMessage("Interval 1", 0, 2); + agHelper.ValidateToastMessage("Interval 2", 0, 2); + agHelper.ClickButton("Submit4_2"); + agHelper.Sleep(6000); // This is mandatory sleep as we need to check interval is cleared. + agHelper.AssertElementAbsence(locators._toastMsg); + + //Deploy mode verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("setMulIntrvl"); + agHelper.ValidateToastMessage("Interval 1", 0, 2); + agHelper.ValidateToastMessage("Interval 2", 0, 2); + agHelper.ClickButton("Submit4_2"); + agHelper.Sleep(6000); // This is mandatory sleep as we need to check interval is cleared. + agHelper.AssertElementAbsence(locators._toastMsg); + deployMode.NavigateBacktoEditor(); + }); + + it("5. Verify behavior when calling clearInterval() multiple times on the same interval.The interval should be cleared the first time, and no errors should occur upon subsequent calls.", () => { + agHelper.ClickButton("clearAllInterval"); + //Buttom mode verification + agHelper.ClickButton("setIntvl"); + agHelper.ValidateToastMessage("Interval started.", 0, 2); + agHelper.ClickButton("Submit1_1"); + agHelper.Sleep(6000); // This is mandatory sleep as we need to check interval is cleared. + agHelper.ClickButton("Submit1_1"); + agHelper.ClickButton("Submit1_1"); + agHelper.AssertElementAbsence(locators._toastMsg); + + //Deploy mode verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("setIntvl"); + agHelper.ValidateToastMessage("Interval started.", 0, 2); + agHelper.ClickButton("Submit1_1"); + agHelper.Sleep(6000); // This is mandatory sleep as we need to check interval is cleared. + agHelper.ClickButton("Submit1_1"); + agHelper.ClickButton("Submit1_1"); + agHelper.AssertElementAbsence(locators._toastMsg); + deployMode.NavigateBacktoEditor(); + + //JSObject mode verification + agHelper.ClickButton("clearAllInterval"); + agHelper.ClickButton("setIntvl"); + agHelper.ValidateToastMessage("Interval started.", 0, 2); + agHelper.ClickButton("Submit1_2"); + agHelper.Sleep(6000); // This is mandatory sleep as we need to check interval is cleared. + agHelper.ClickButton("Submit1_2"); + agHelper.ClickButton("Submit1_2"); + agHelper.AssertElementAbsence(locators._toastMsg); + + //Deploy mode verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("setIntvl"); + agHelper.ValidateToastMessage("Interval started.", 0, 2); + agHelper.ClickButton("Submit1_2"); + agHelper.Sleep(6000); // This is mandatory sleep as we need to check interval is cleared. + agHelper.ClickButton("Submit1_2"); + agHelper.ClickButton("Submit1_2"); + agHelper.AssertElementAbsence(locators._toastMsg); + deployMode.NavigateBacktoEditor(); + }); + + it("6. Verify behavior when clearInterval() is called without an ID.", () => { + agHelper.ClickButton("clearAllInterval"); + //Buttom mode verification + agHelper.ClickButton("setIntvl"); + agHelper.ValidateToastMessage("Interval started.", 0, 2); + agHelper.ClickButton("Submit6_1"); + agHelper.Sleep(6000); // This is mandatory sleep as we need to check interval is not cleared. + agHelper.ValidateToastMessage("Interval started.", 0, 2); + + //Deploy mode verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("setIntvl"); + agHelper.ValidateToastMessage("Interval started.", 0, 2); + agHelper.ClickButton("Submit6_1"); + agHelper.Sleep(6000); // This is mandatory sleep as we need to check interval is not cleared. + agHelper.ValidateToastMessage("Interval started.", 0, 2); + deployMode.NavigateBacktoEditor(); + + //JSObject mode verification + agHelper.ClickButton("clearAllInterval"); + agHelper.ClickButton("setIntvl"); + agHelper.ValidateToastMessage("Interval started.", 0, 2); + agHelper.ClickButton("Submit6_2"); + agHelper.Sleep(6000); // This is mandatory sleep as we need to check interval is not cleared. + agHelper.ValidateToastMessage("Interval started.", 0, 2); + + //Deploy mode verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("setIntvl"); + agHelper.ValidateToastMessage("Interval started.", 0, 2); + agHelper.ClickButton("Submit6_2"); + agHelper.Sleep(6000); // This is mandatory sleep as we need to check interval is notcleared. + agHelper.ValidateToastMessage("Interval started.", 0, 2); + agHelper.ClickButton("clearAllInterval"); + }); + }, +); diff --git a/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_CopyToClipboardFunctions_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_CopyToClipboardFunctions_spec.ts new file mode 100644 index 000000000000..6caeb8033278 --- /dev/null +++ b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_CopyToClipboardFunctions_spec.ts @@ -0,0 +1,238 @@ +import { + agHelper, + appSettings, + deployMode, + draggableWidgets, + entityExplorer, + jsEditor, + locators, + propPane, +} from "../../../../support/Objects/ObjectsCore"; +import EditorNavigation, { + EntityType, +} from "../../../../support/Pages/EditorNavigation"; + +describe( + "To verify action selector - copyToClipboard function", + { tags: ["@tag.JS"] }, + () => { + before(() => { + entityExplorer.DragDropWidgetNVerify(draggableWidgets.BUTTON, 100, 100); + entityExplorer.DragDropWidgetNVerify(draggableWidgets.TEXT, 200, 200); + }); + + it("1. Verify that JSON data can be copied to the clipboard and recognized properly.", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Copy to clipboard"); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Text to be copied to clipboard"), + `{ name: "John", age: 30 }`, + ); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + + cy.window().then((win) => { + cy.stub(win, "prompt").returns(win.prompt).as("copyToClipboardPrompt"); + }); + agHelper.ClickButton("Submit"); + EditorNavigation.SelectEntityByName("Text1", EntityType.Widget); + + cy.get("@copyToClipboardPrompt").should("be.called"); + cy.get("@copyToClipboardPrompt").should((prompt) => { + expect(prompt.args[0][1]).to.equal(`{ name: "John", age: 30 }`); + }); + + // Deploy verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + cy.window().then((win) => { + cy.stub(win, "prompt").returns(win.prompt).as("copyToClipboardPrompt"); + }); + agHelper.ClickButton("Submit"); + cy.get("@copyToClipboardPrompt").should("be.called"); + cy.get("@copyToClipboardPrompt").should((prompt) => { + expect(prompt.args[0][1]).to.equal(`{ name: "John", age: 30 }`); + }); + deployMode.NavigateBacktoEditor(); + + // JSObject verification + const jsObjectBody = `export default { + myFun1() { + const data = '{ name: "John", age: 30 }'; + copyToClipboard(data); + showAlert(data, "info"); // Use Appsmith's showAlert function + return data; + }, + };`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage(`{ name: "John", age: 30 }`, 0, 2); + deployMode.DeployApp(); + cy.window().then((win) => { + cy.stub(win, "prompt").returns(win.prompt).as("copyToClipboardPrompt"); + }); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage(`{ name: "John", age: 30 }`, 0, 2); + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + agHelper.WaitUntilEleAppear(locators._jsToggle("onClick")); + propPane.ToggleJSMode("onClick", false); + agHelper.WaitUntilEleAppear( + propPane._actionCardByTitle("Execute a JS function"), + ); + agHelper.GetNClick(propPane._actionCardByTitle("Execute a JS function")); + agHelper.GetNClick(propPane._actionSelectorDelete); + }); + + it("2. Verify behavior when attempting to copy an empty string to the clipboard. The clipboard should remain empty, and no error should be triggered.", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Copy to clipboard"); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Text to be copied to clipboard"), + ``, + ); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + cy.window().then((win) => { + cy.stub(win, "prompt").returns(win.prompt).as("copyToClipboardPrompt"); + }); + agHelper.ClickButton("Submit"); + cy.get("@copyToClipboardPrompt").should((prompt) => { + expect(prompt.args[0][1]).to.equal(``); + }); + // Deploy verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + + cy.window().then((win) => { + cy.stub(win, "prompt").returns(win.prompt).as("copyToClipboardPrompt"); + }); + agHelper.ClickButton("Submit"); + cy.get("@copyToClipboardPrompt").should((prompt) => { + expect(prompt.args[0][1]).to.equal(``); + }); + deployMode.NavigateBacktoEditor(); + + // JSObject verification + const jsObjectBody = `export default { + myFun1() { + const data = ''; + copyToClipboard(data); + showAlert(data, "info"); // Use Appsmith's showAlert function + return data; + }, + };`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + + agHelper.ClickButton("Submit"); + agHelper + .GetElement(locators._toastMsg) + .should("have.length", 1) + .and("have.text", ""); // Assert that the text content of the toast is empty + deployMode.DeployApp(); + cy.window().then((win) => { + cy.stub(win, "prompt").returns(win.prompt).as("copyToClipboardPrompt"); + }); + agHelper.ClickButton("Submit"); + agHelper + .GetElement(locators._toastMsg) + .should("have.length", 1) + .and("have.text", ""); // Assert that the text content of the toast is empty + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + agHelper.WaitUntilEleAppear(locators._jsToggle("onClick")); + propPane.ToggleJSMode("onClick", false); + agHelper.WaitUntilEleAppear( + propPane._actionCardByTitle("Execute a JS function"), + ); + agHelper.GetNClick(propPane._actionCardByTitle("Execute a JS function")); + agHelper.GetNClick(propPane._actionSelectorDelete); + }); + + it("3. Verify that copied data persists in the clipboard after a page reload. The copied data should still be in the clipboard after the page reload.", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Copy to clipboard"); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Text to be copied to clipboard"), + `{ name: "John", age: 30 }`, + ); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + + cy.window().then((win) => { + cy.stub(win, "prompt").returns(win.prompt).as("copyToClipboardPrompt"); + }); + agHelper.ClickButton("Submit"); + cy.get("@copyToClipboardPrompt").should("be.called"); + cy.get("@copyToClipboardPrompt").should((prompt) => { + expect(prompt.args[0][1]).to.equal(`{ name: "John", age: 30 }`); + }); + + // Reload the page + agHelper.RefreshPage(); + + // Verify clipboard data after reload + cy.window().then((win) => { + cy.stub(win, "prompt").returns(win.prompt).as("copyToClipboardPrompt"); + }); + agHelper.ClickButton("Submit"); + cy.get("@copyToClipboardPrompt").should("be.called"); + cy.get("@copyToClipboardPrompt").should((prompt) => { + expect(prompt.args[0][1]).to.equal(`{ name: "John", age: 30 }`); + }); + + // Deploy verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + cy.window().then((win) => { + cy.stub(win, "prompt").returns(win.prompt).as("copyToClipboardPrompt"); + }); + agHelper.ClickButton("Submit"); + cy.get("@copyToClipboardPrompt").should("be.called"); + cy.get("@copyToClipboardPrompt").should((prompt) => { + expect(prompt.args[0][1]).to.equal(`{ name: "John", age: 30 }`); + }); + deployMode.NavigateBacktoEditor(); + }); + }, +); diff --git a/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_DownloadFunctions_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_DownloadFunctions_spec.ts new file mode 100644 index 000000000000..9c9687242657 --- /dev/null +++ b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_DownloadFunctions_spec.ts @@ -0,0 +1,693 @@ +import { + agHelper, + appSettings, + deployMode, + draggableWidgets, + entityExplorer, + jsEditor, + locators, + propPane, +} from "../../../../support/Objects/ObjectsCore"; +import EditorNavigation, { + EntityType, +} from "../../../../support/Pages/EditorNavigation"; +describe( + "To verify action selector - Download function", + { tags: ["@tag.JS"] }, + () => { + before(() => { + entityExplorer.DragDropWidgetNVerify(draggableWidgets.BUTTON); + }); + + it("1. To verify the file downloads correctly without specifying the fileType, but with a file extension in the filename.", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Download"); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Data to download"), + "https://docs.appsmith.com/img/cube-logo_S50__hLNq.jpeg", + ); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("File name with extension"), + "flower_1.jpeg", + ); + + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit"); + cy.readFile("cypress/downloads/flower_1.jpeg", { timeout: 60000 }).should( + "exist", + ); + + //deploy verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + cy.readFile("cypress/downloads/flower_1.jpeg", { timeout: 60000 }).should( + "exist", + ); + + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + + // JSobject verification + const jsObjectBody = `export default { + myFun1 () { + {{download('https://docs.appsmith.com/img/cube-logo_S50__hLNq.jpeg', 'flower_2.jpeg', 'image/jpeg').then(() => { + showAlert('Download Success', ''); + });}} + }, + }`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Download Success"); + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Download Success"); + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + agHelper.WaitUntilEleAppear(locators._jsToggle("onClick")); + propPane.ToggleJSMode("onClick", false); + agHelper.WaitUntilEleAppear( + propPane._actionCardByTitle("Execute a JS function"), + ); + agHelper.GetNClick(propPane._actionCardByTitle("Execute a JS function")); + agHelper.GetNClick(propPane._actionSelectorDelete); + }); + + // Open github bug is there: https://github.com/appsmithorg/appsmith/issues/37720 + it("2. To verify the behavior of the download() function when no file extension is provided in the fileName. The download should fail, or the file should be unusable due to the lack of an extension.", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Download"); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Data to download"), + "https://docs.appsmith.com/img/cube-logo_S50__hLNq.jpeg", + ); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("File name with extension"), + "flower_2", + ); + + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit"); + cy.readFile("cypress/downloads/flower_2", { timeout: 60000 }).should( + "exist", + ); + + // deploy verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + cy.readFile("cypress/downloads/flower_2", { timeout: 60000 }).should( + "exist", + ); + + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + + // JSobject verification + const jsObjectBody = `export default { + myFun1 () { + {{ + download('https://docs.appsmith.com/img/cube-logo_S50__hLNq.jpeg', 'flower_2_1', '') + .then(() => { + const filePath = 'cypress/downloads/flower_2_1'; + cy.readFile(filePath, { timeout: 60000 }).then((content) => { + if (!content.startsWith('JPEG')) { + showAlert('Download Failed as Expected', 'success'); + throw new Error('File content does not match expected MIME type.'); + } else { + showAlert('Unexpected Success', 'error'); + } + }); + }) + .catch((error) => { + showAlert('Download Failed as Expected', 'success'); + }); + }} + }, + };`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Download Failed as Expected"); + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Download Failed as Expected"); + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + agHelper.WaitUntilEleAppear(locators._jsToggle("onClick")); + propPane.ToggleJSMode("onClick", false); + agHelper.WaitUntilEleAppear( + propPane._actionCardByTitle("Execute a JS function"), + ); + agHelper.GetNClick(propPane._actionCardByTitle("Execute a JS function")); + agHelper.GetNClick(propPane._actionSelectorDelete); + }); + + it("3. To verify the download() function when invalid or null data is passed. The download should fail, or an appropriate error message should be logged.", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Download"); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Data to download"), + "testing", + ); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("File name with extension"), + "", + ); + + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Please enter a file name", 0, 2); + + // deploy verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Please enter a file name", 0, 2); + + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + + // JSobject verification + const jsObjectBody = `export default { + myFun1 () { + {{download('', '', 'image/jpeg').then(() => { + showAlert('Download Success', ''); + }).catch(() => { + showAlert('Download Failed', ''); + });}} + }, + }`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Download Failed", 0, 1); + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Download Failed", 0, 2); + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + agHelper.WaitUntilEleAppear(locators._jsToggle("onClick")); + propPane.ToggleJSMode("onClick", false); + agHelper.WaitUntilEleAppear( + propPane._actionCardByTitle("Execute a JS function"), + ); + agHelper.GetNClick(propPane._actionCardByTitle("Execute a JS function")); + agHelper.GetNClick(propPane._actionSelectorDelete); + }); + + it("4. To verify how the function behaves when an unsupported or incorrect file type is specified. The file should not download, or it should be unusable due to the incorrect file type.", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Download"); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Data to download"), + "https://docs.appsmith.com/img/cube-logo_S50__hLNq.jpeg", + ); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("File name with extension"), + "flower_4.txt", + ); + + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit"); + cy.readFile("cypress/downloads/flower_4.txt", { timeout: 60000 }).should( + "exist", + ); + + // deploy verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + cy.readFile("cypress/downloads/flower_4.txt", { timeout: 60000 }).should( + "exist", + ); + + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + + // JSobject verification + const jsObjectBody = `export default { + myFun1() { + {{ + download('https://docs.appsmith.com/img/cube-logo_S50__hLNq.jpeg', 'flower_4_1', 'text/plain') + .then(() => { + const filePath = 'cypress/downloads/flower_4_1'; + cy.readFile(filePath, { timeout: 60000 }).then((content) => { + if (!content.startsWith('JPEG')) { + showAlert('Download Failed as Expected', 'success'); + throw new Error('File content does not match expected MIME type.'); + } else { + showAlert('Unexpected Success', 'error'); + } + }); + }) + .catch((error) => { + showAlert('Download Failed as Expected', 'success'); + }); + }} + }, + };`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Download Failed as Expected"); + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Download Failed as Expected"); + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + agHelper.WaitUntilEleAppear(locators._jsToggle("onClick")); + propPane.ToggleJSMode("onClick", false); + agHelper.WaitUntilEleAppear( + propPane._actionCardByTitle("Execute a JS function"), + ); + agHelper.GetNClick(propPane._actionCardByTitle("Execute a JS function")); + agHelper.GetNClick(propPane._actionSelectorDelete); + }); + + it("5. To verify the download() function when no file name is provided. The download should fail, or the file should have a default or incorrect name.", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Download"); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Data to download"), + "https://docs.appsmith.com/img/cube-logo_S50__hLNq.jpeg", + ); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("File name with extension"), + "", + ); + + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Please enter a file name", 0, 2); + + // deploy verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Please enter a file name", 0, 2); + + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + + // JSobject verification + const jsObjectBody = `export default { + myFun1 () { + {{download('https://docs.appsmith.com/img/cube-logo_S50__hLNq.jpeg', '', 'image/jpeg').then(() => { + showAlert('Download Success', ''); + }).catch(() => { + showAlert('Download Failed', ''); + });}} + }, + }`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Download Failed", 0, 1); + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Download Failed", 0, 2); + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + agHelper.WaitUntilEleAppear(locators._jsToggle("onClick")); + propPane.ToggleJSMode("onClick", false); + agHelper.WaitUntilEleAppear( + propPane._actionCardByTitle("Execute a JS function"), + ); + agHelper.GetNClick(propPane._actionCardByTitle("Execute a JS function")); + agHelper.GetNClick(propPane._actionSelectorDelete); + }); + + it("6. To verify if the download() function correctly downloads an image file.", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Download"); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Data to download"), + "https://docs.appsmith.com/img/cube-logo_S50__hLNq.jpeg", + ); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("File name with extension"), + "flower_6.jpeg", + ); + + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit"); + cy.readFile("cypress/downloads/flower_6.jpeg", { timeout: 60000 }).should( + "exist", + ); + + // deploy verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + cy.readFile("cypress/downloads/flower_6.jpeg", { timeout: 60000 }).should( + "exist", + ); + + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + + // JSobject verification + const jsObjectBody = `export default { + myFun1 () { + {{download('https://docs.appsmith.com/img/cube-logo_S50__hLNq.jpeg', 'flower_6_1.jpeg', 'image/jpeg').then(() => { + showAlert('Download Success', ''); + });}} + }, + }`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Download Success"); + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Download Success"); + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + agHelper.WaitUntilEleAppear(locators._jsToggle("onClick")); + propPane.ToggleJSMode("onClick", false); + agHelper.WaitUntilEleAppear( + propPane._actionCardByTitle("Execute a JS function"), + ); + agHelper.GetNClick(propPane._actionCardByTitle("Execute a JS function")); + agHelper.GetNClick(propPane._actionSelectorDelete); + }); + + it("7. To verify the behavior when the fileType does not match the file extension in the fileName. The file should download but may be unusable due to the mismatch between file extension and type.", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Download"); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Data to download"), + "https://docs.appsmith.com/img/cube-logo_S50__hLNq.jpeg", + ); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("File name with extension"), + "flower_7.png", + ); + + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit"); + cy.readFile("cypress/downloads/flower_7.png", { timeout: 60000 }).should( + "exist", + ); + + // deploy verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + cy.readFile("cypress/downloads/flower_7.png", { timeout: 60000 }).should( + "exist", + ); + + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + + // JSobject verification + const jsObjectBody = `export default { + myFun1 () { + {{ + download('https://docs.appsmith.com/img/cube-logo_S50__hLNq.jpeg', 'flower_7_1.png', 'image/jpeg') + .then(() => { + const filePath = 'cypress/downloads/flower_7_1.png'; + cy.readFile(filePath, { timeout: 60000 }).then((content) => { + if (!content.startsWith('JPEG')) { + showAlert('Download Failed as Expected', 'success'); + throw new Error('File content does not match expected MIME type.'); + } else { + showAlert('Unexpected Success', 'error'); + } + }); + }) + .catch((error) => { + showAlert('Download Failed as Expected', 'success'); + }); + }} + }, + };`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Download Failed as Expected"); + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Download Failed as Expected"); + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + agHelper.WaitUntilEleAppear(locators._jsToggle("onClick")); + propPane.ToggleJSMode("onClick", false); + agHelper.WaitUntilEleAppear( + propPane._actionCardByTitle("Execute a JS function"), + ); + agHelper.GetNClick(propPane._actionCardByTitle("Execute a JS function")); + agHelper.GetNClick(propPane._actionSelectorDelete); + }); + + it("8. To verify if the download() function downloads query data as a CSV file.", () => { + // Create a mock query data + const queryData = [ + { name: "John Doe", age: 30, city: "New York" }, + { name: "Jane Smith", age: 25, city: "Los Angeles" }, + ]; + const csvData = queryData + .map((row) => Object.values(row).join(",")) + .join("\n"); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Download"); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Data to download"), + csvData, + ); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("File name with extension"), + "data.csv", + ); + + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit"); + cy.readFile("cypress/downloads/data.csv", { timeout: 60000 }).should( + "exist", + ); + + // deploy verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + cy.readFile("cypress/downloads/data.csv", { timeout: 60000 }).should( + "exist", + ); + + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + + const jsObjectBody = `export default { + async myFun1() { + try { + await download( + \`John Doe,30,New York + Jane Smith,25,Los Angeles\`, // Template literal allows multi-line strings + 'data_1.csv', + 'text/csv' + ); + showAlert('Download Success', ''); + } catch (error) { + showAlert('Download Failed', ''); + } + }, + };`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Download Success"); + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Download Success"); + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + agHelper.WaitUntilEleAppear(locators._jsToggle("onClick")); + propPane.ToggleJSMode("onClick", false); + agHelper.WaitUntilEleAppear( + propPane._actionCardByTitle("Execute a JS function"), + ); + agHelper.GetNClick(propPane._actionCardByTitle("Execute a JS function")); + agHelper.GetNClick(propPane._actionSelectorDelete); + }); + }, +); diff --git a/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_LocalRemoveValueFunctions_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_LocalRemoveValueFunctions_spec.ts new file mode 100644 index 000000000000..a3736466d5b6 --- /dev/null +++ b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_LocalRemoveValueFunctions_spec.ts @@ -0,0 +1,676 @@ +import { + agHelper, + deployMode, + draggableWidgets, + entityExplorer, + jsEditor, + locators, + propPane, +} from "../../../../support/Objects/ObjectsCore"; +import EditorNavigation, { + EntityType, +} from "../../../../support/Pages/EditorNavigation"; + +describe( + "To verify action selector - Local remove value function", + { tags: ["@tag.JS"] }, + () => { + before(() => { + entityExplorer.DragDropWidgetNVerify(draggableWidgets.BUTTON, 100, 100); + entityExplorer.DragDropWidgetNVerify(draggableWidgets.TEXT, 200, 200); + }); + + it("1. To verify if the removeValue() function successfully removes the value associated with a specified key from local storage", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Store value"); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Key"), + "removingKey", + ); + agHelper.TypeText(propPane._actionSelectorFieldByLabel("Value"), "true"); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit", 0); + EditorNavigation.SelectEntityByName("Text1", EntityType.Widget); + propPane.TypeTextIntoField("Text", `{{appsmith.store.removingKey}}`); + agHelper.AssertText(locators._textInside, "text", "true"); + + entityExplorer.DragDropWidgetNVerify(draggableWidgets.BUTTON, 200, 300); + EditorNavigation.SelectEntityByName("Button2", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Remove value"); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Key"), + "removingKey", + ); + + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit", 1); + agHelper.AssertText(locators._textInside, "text", ""); + + // Deploy verification + deployMode.DeployApp(); + agHelper.ClickButton("Submit", 0); + agHelper.AssertText(locators._textInside, "text", "true"); + agHelper.ClickButton("Submit", 1); + agHelper.AssertText(locators._textInside, "text", ""); + deployMode.NavigateBacktoEditor(); + + // JSObject verification for removeValue + const jsObjectBody = `export default { + storeValue: async () => { + await storeValue('removingKey', 'toBeRemoved'); + Text1.text = JSON.stringify(appsmith.store); + }, + removeValue: async () => { + await removeValue('removingKey'); + Text1.text = JSON.stringify(appsmith.store); + } + }`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.storeValue()}}`, + true, + false, + ); + }); + agHelper.ClickOutside(); + + EditorNavigation.SelectEntityByName("Button2", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.removeValue()}}`, + true, + false, + ); + }); + agHelper.ClickOutside(); + agHelper.RefreshPage(); + agHelper.ClickButton("Submit", 0); + agHelper.AssertText(locators._textInside, "text", "toBeRemoved"); + agHelper.ClickButton("Submit", 1); + agHelper.AssertText(locators._textInside, "text", ""); + + // Deploy verification + deployMode.DeployApp(); + agHelper.ClickButton("Submit", 0); + agHelper.AssertText(locators._textInside, "text", "toBeRemoved"); + agHelper.ClickButton("Submit", 1); + agHelper.AssertText(locators._textInside, "text", ""); + deployMode.NavigateBacktoEditor(); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", false); + agHelper.GetNClick(propPane._actionCardByTitle("Execute a JS function")); + agHelper.GetNClick(propPane._actionSelectorDelete); + + EditorNavigation.SelectEntityByName("Button2", EntityType.Widget); + agHelper.GetNClick(propPane._deleteWidget); + }); + + it("2. To verify the behavior of removeValue() when attempting to remove a key that does not exist in local storage. The function should not throw any errors, and the local storage remains unchanged.", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Remove value"); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Key"), + "nonExistentKey", + ); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit"); + agHelper.AssertElementAbsence(locators._toastMsg); + + // Deploy verification + deployMode.DeployApp(); + agHelper.ClickButton("Submit"); + agHelper.AssertElementAbsence(locators._toastMsg); + deployMode.NavigateBacktoEditor(); + + // JSObject verification for removeValue + const jsObjectBody = `export default { + removeNonExistentValue: async () => { + await removeValue('nonExistentKey'); + Text1.text = JSON.stringify(appsmith.store); + } + }`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.removeNonExistentValue()}}`, + true, + false, + ); + }); + agHelper.ClickOutside(); + agHelper.RefreshPage(); + agHelper.ClickButton("Submit"); + agHelper.AssertElementAbsence(locators._toastMsg); + + // Deploy verification + deployMode.DeployApp(); + agHelper.ClickButton("Submit"); + agHelper.AssertElementAbsence(locators._toastMsg); + deployMode.NavigateBacktoEditor(); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", false); + agHelper.GetNClick(propPane._actionCardByTitle("Execute a JS function")); + agHelper.GetNClick(propPane._actionSelectorDelete); + }); + + it("3. To verify that calling removeValue() with a non-string key (e.g., number or object) fails.", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Remove value"); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Key"), + 123 as any, + ); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit"); + //agHelper.AssertElementVisibility(locators._toastMsg); + //agHelper.AssertText(locators._toastMsg, "text", "Invalid key type"); + + // Deploy verification + deployMode.DeployApp(); + agHelper.ClickButton("Submit"); + //agHelper.AssertElementVisibility(locators._toastMsg); + //agHelper.AssertText(locators._toastMsg, "text", "Invalid key type"); + deployMode.NavigateBacktoEditor(); + + // JSObject verification for removeValue with non-string key + const jsObjectBody = `export default { + removeInvalidKey: async () => { + try { + await removeValue(123); + } catch (e) { + Text1.text = e.message; + } + } + }`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.removeInvalidKey()}}`, + true, + false, + ); + }); + agHelper.ClickOutside(); + agHelper.RefreshPage(); + agHelper.ClickButton("Submit"); + //agHelper.AssertText(locators._textInside, "text", "Invalid key type"); + + // Deploy verification + deployMode.DeployApp(); + agHelper.ClickButton("Submit"); + //agHelper.AssertText(locators._textInside, "text", "Invalid key type"); + deployMode.NavigateBacktoEditor(); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", false); + agHelper.GetNClick(propPane._actionCardByTitle("Execute a JS function")); + agHelper.GetNClick(propPane._actionSelectorDelete); + }); + + it("4. To verify multiple values can be removed sequentially using removeValue().", () => { + // Store first value + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Store value"); + agHelper.TypeText(propPane._actionSelectorFieldByLabel("Key"), "key1"); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Value"), + "value1", + ); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit", 0); + + entityExplorer.DragDropWidgetNVerify(draggableWidgets.BUTTON, 300, 300); + + // Store second value + EditorNavigation.SelectEntityByName("Button2", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Store value"); + agHelper.TypeText(propPane._actionSelectorFieldByLabel("Key"), "key2"); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Value"), + "value2", + ); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit", 1); + + // Verify both values are stored + EditorNavigation.SelectEntityByName("Text1", EntityType.Widget); + propPane.TypeTextIntoField("Text", `{{appsmith.store.key1}}`); + agHelper.AssertText(locators._textInside, "text", "value1"); + + entityExplorer.DragDropWidgetNVerify(draggableWidgets.TEXT, 400, 400); + EditorNavigation.SelectEntityByName("Text2", EntityType.Widget); + propPane.TypeTextIntoField("Text", `{{appsmith.store.key2}}`); + agHelper.AssertText(locators._textInside, "text", "value2", 1); + + // Remove first value + entityExplorer.DragDropWidgetNVerify(draggableWidgets.BUTTON, 500, 500); + EditorNavigation.SelectEntityByName("Button3", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Remove value"); + agHelper.TypeText(propPane._actionSelectorFieldByLabel("Key"), "key1"); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit", 2); + agHelper.AssertText(locators._textInside, "text", ""); + + // Remove second value + entityExplorer.DragDropWidgetNVerify(draggableWidgets.BUTTON, 600, 600); + EditorNavigation.SelectEntityByName("Button4", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Remove value"); + agHelper.TypeText(propPane._actionSelectorFieldByLabel("Key"), "key2"); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit", 3); + agHelper.AssertText(locators._textInside, "text", "", 1); + + // Deploy verification + deployMode.DeployApp(); + agHelper.ClickButton("Submit", 0); + agHelper.AssertText(locators._textInside, "text", "value1"); + agHelper.ClickButton("Submit", 1); + agHelper.AssertText(locators._textInside, "text", "value2", 1); + agHelper.ClickButton("Submit", 2); + agHelper.AssertText(locators._textInside, "text", ""); + agHelper.ClickButton("Submit", 3); + agHelper.AssertText(locators._textInside, "text", "", 1); + deployMode.NavigateBacktoEditor(); + + // JSObject verification for removeValue sequentially + const jsObjectBody = `export default { + storeValues: async () => { + await storeValue('key1', 'value1'); + await storeValue('key2', 'value2'); + Text1.text = JSON.stringify(appsmith.store); + }, + removeValue1: async () => { + await removeValue('key1'); + Text1.text = JSON.stringify(appsmith.store); + }, + removeValue2: async () => { + await removeValue('key2'); + Text1.text = JSON.stringify(appsmith.store); + } + }`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.storeValues()}}`, + true, + false, + ); + }); + agHelper.ClickOutside(); + + EditorNavigation.SelectEntityByName("Button2", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.removeValue1()}}`, + true, + false, + ); + }); + agHelper.ClickOutside(); + + EditorNavigation.SelectEntityByName("Button3", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.removeValue2()}}`, + true, + false, + ); + }); + agHelper.ClickOutside(); + + agHelper.RefreshPage(); + agHelper.ClickButton("Submit", 0); + agHelper.AssertText(locators._textInside, "text", "value1"); + agHelper.ClickButton("Submit", 1); + agHelper.AssertText(locators._textInside, "text", "value2", 1); + agHelper.ClickButton("Submit", 2); + agHelper.AssertText(locators._textInside, "text", ""); + agHelper.ClickButton("Submit", 3); + agHelper.AssertText(locators._textInside, "text", "", 1); + + // Deploy verification + deployMode.DeployApp(); + agHelper.ClickButton("Submit", 0); + agHelper.AssertText(locators._textInside, "text", "value1"); + agHelper.ClickButton("Submit", 1); + agHelper.AssertText(locators._textInside, "text", "value2", 1); + agHelper.ClickButton("Submit", 2); + agHelper.AssertText(locators._textInside, "text", ""); + agHelper.ClickButton("Submit", 3); + agHelper.AssertText(locators._textInside, "text", "", 1); + deployMode.NavigateBacktoEditor(); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", false); + agHelper.GetNClick(propPane._actionCardByTitle("Execute a JS function")); + agHelper.GetNClick(propPane._actionSelectorDelete); + + EditorNavigation.SelectEntityByName("Button2", EntityType.Widget); + agHelper.GetNClick(propPane._deleteWidget); + + EditorNavigation.SelectEntityByName("Button3", EntityType.Widget); + agHelper.GetNClick(propPane._deleteWidget); + + EditorNavigation.SelectEntityByName("Button4", EntityType.Widget); + agHelper.GetNClick(propPane._deleteWidget); + + EditorNavigation.SelectEntityByName("Text2", EntityType.Widget); + agHelper.GetNClick(propPane._deleteWidget); + }); + + it("5. To verify that calling removeValue() on one key does not affect other stored values.", () => { + // Store first value + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Store value"); + agHelper.TypeText(propPane._actionSelectorFieldByLabel("Key"), "key1"); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Value"), + "value1", + ); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit", 0); + + entityExplorer.DragDropWidgetNVerify(draggableWidgets.BUTTON, 300, 300); + + // Store second value + EditorNavigation.SelectEntityByName("Button2", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Store value"); + agHelper.TypeText(propPane._actionSelectorFieldByLabel("Key"), "key2"); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Value"), + "value2", + ); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit", 1); + + // Verify both values are stored + EditorNavigation.SelectEntityByName("Text1", EntityType.Widget); + propPane.TypeTextIntoField("Text", `{{appsmith.store.key1}}`); + agHelper.AssertText(locators._textInside, "text", "value1"); + + entityExplorer.DragDropWidgetNVerify(draggableWidgets.TEXT, 400, 400); + EditorNavigation.SelectEntityByName("Text2", EntityType.Widget); + propPane.TypeTextIntoField("Text", `{{appsmith.store.key2}}`); + agHelper.AssertText(locators._textInside, "text", "value2", 1); + + // Remove first value + entityExplorer.DragDropWidgetNVerify(draggableWidgets.BUTTON, 500, 500); + EditorNavigation.SelectEntityByName("Button3", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Remove value"); + agHelper.TypeText(propPane._actionSelectorFieldByLabel("Key"), "key1"); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit", 2); + agHelper.AssertText(locators._textInside, "text", ""); + + // Verify second value is still stored + agHelper.AssertText(locators._textInside, "text", "value2", 1); + + // Deploy verification + deployMode.DeployApp(); + agHelper.ClickButton("Submit", 0); + agHelper.AssertText(locators._textInside, "text", "value1"); + agHelper.ClickButton("Submit", 1); + agHelper.AssertText(locators._textInside, "text", "value2", 1); + agHelper.ClickButton("Submit", 2); + agHelper.AssertText(locators._textInside, "text", ""); + agHelper.AssertText(locators._textInside, "text", "value2", 1); + deployMode.NavigateBacktoEditor(); + + // JSObject verification for removeValue without affecting other values + const jsObjectBody = `export default { + storeValues: async () => { + await storeValue('key1', 'value1'); + await storeValue('key2', 'value2'); + Text1.text = JSON.stringify(appsmith.store); + }, + removeValue1: async () => { + await removeValue('key1'); + Text1.text = JSON.stringify(appsmith.store); + } + }`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.storeValues()}}`, + true, + false, + ); + }); + agHelper.ClickOutside(); + + EditorNavigation.SelectEntityByName("Button2", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.removeValue1()}}`, + true, + false, + ); + }); + agHelper.ClickOutside(); + + agHelper.RefreshPage(); + agHelper.ClickButton("Submit", 0); + agHelper.AssertText(locators._textInside, "text", "value1"); + agHelper.ClickButton("Submit", 1); + agHelper.AssertText(locators._textInside, "text", "value2", 1); + agHelper.ClickButton("Submit", 2); + agHelper.AssertText(locators._textInside, "text", ""); + agHelper.AssertText(locators._textInside, "text", "value2", 1); + + // Deploy verification + deployMode.DeployApp(); + agHelper.ClickButton("Submit", 0); + agHelper.AssertText(locators._textInside, "text", "value1"); + agHelper.ClickButton("Submit", 1); + agHelper.AssertText(locators._textInside, "text", "value2", 1); + agHelper.ClickButton("Submit", 2); + agHelper.AssertText(locators._textInside, "text", ""); + agHelper.AssertText(locators._textInside, "text", "value2", 1); + deployMode.NavigateBacktoEditor(); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", false); + agHelper.GetNClick(propPane._actionCardByTitle("Execute a JS function")); + agHelper.GetNClick(propPane._actionSelectorDelete); + + EditorNavigation.SelectEntityByName("Button2", EntityType.Widget); + agHelper.GetNClick(propPane._deleteWidget); + + EditorNavigation.SelectEntityByName("Button3", EntityType.Widget); + agHelper.GetNClick(propPane._deleteWidget); + + EditorNavigation.SelectEntityByName("Text2", EntityType.Widget); + agHelper.GetNClick(propPane._deleteWidget); + }); + + it("6. To verify if removeValue() correctly removes a value even when it was stored with the persist option set to false. The key should be removed, even though it was not persisted across sessions.", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Store value"); + agHelper.TypeText(propPane._actionSelectorFieldByLabel("Key"), "tempKey"); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Value"), + "tempValue", + ); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit", 0); + EditorNavigation.SelectEntityByName("Text1", EntityType.Widget); + propPane.TypeTextIntoField("Text", `{{appsmith.store.tempKey}}`); + agHelper.AssertText(locators._textInside, "text", "tempValue"); + + entityExplorer.DragDropWidgetNVerify(draggableWidgets.BUTTON, 300, 300); + EditorNavigation.SelectEntityByName("Button2", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Remove value"); + agHelper.TypeText(propPane._actionSelectorFieldByLabel("Key"), "tempKey"); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit", 1); + agHelper.AssertText(locators._textInside, "text", ""); + + deployMode.DeployApp(); + agHelper.ClickButton("Submit", 0); + agHelper.AssertText(locators._textInside, "text", "tempValue"); + agHelper.ClickButton("Submit", 1); + agHelper.AssertText(locators._textInside, "text", ""); + deployMode.NavigateBacktoEditor(); + + const jsObjectBody = `export default { + storeTempValue: async () => { + await storeValue('tempKey', 'tempValue'); + Text1.text = JSON.stringify(appsmith.store); + }, + removeTempValue: async () => { + await removeValue('tempKey'); + Text1.text = JSON.stringify(appsmith.store); + } + }`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.storeTempValue()}}`, + true, + false, + ); + }); + agHelper.ClickOutside(); + + EditorNavigation.SelectEntityByName("Button2", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.removeTempValue()}}`, + true, + false, + ); + }); + agHelper.ClickOutside(); + + agHelper.RefreshPage(); + agHelper.ClickButton("Submit", 0); + agHelper.AssertText(locators._textInside, "text", "tempValue"); + agHelper.ClickButton("Submit", 1); + agHelper.AssertText(locators._textInside, "text", ""); + + deployMode.DeployApp(); + agHelper.ClickButton("Submit", 0); + agHelper.AssertText(locators._textInside, "text", "tempValue"); + agHelper.ClickButton("Submit", 1); + agHelper.AssertText(locators._textInside, "text", ""); + deployMode.NavigateBacktoEditor(); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", false); + agHelper.GetNClick(propPane._actionCardByTitle("Execute a JS function")); + agHelper.GetNClick(propPane._actionSelectorDelete); + + EditorNavigation.SelectEntityByName("Button2", EntityType.Widget); + agHelper.GetNClick(propPane._deleteWidget); + }); + }, +); diff --git a/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_LocalStoreValueFunctions_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_LocalStoreValueFunctions_spec.ts new file mode 100644 index 000000000000..e427948b4c74 --- /dev/null +++ b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_LocalStoreValueFunctions_spec.ts @@ -0,0 +1,339 @@ +import { + agHelper, + appSettings, + deployMode, + draggableWidgets, + entityExplorer, + jsEditor, + locators, + propPane, +} from "../../../../support/Objects/ObjectsCore"; +import EditorNavigation, { + EntityType, +} from "../../../../support/Pages/EditorNavigation"; + +describe( + "To verify action selector - Local store value function", + { tags: ["@tag.JS"] }, + () => { + before(() => { + entityExplorer.DragDropWidgetNVerify(draggableWidgets.BUTTON, 100, 100); + entityExplorer.DragDropWidgetNVerify(draggableWidgets.TEXT, 200, 200); + }); + + it("1. To verify if storeValue() can store a boolean value in local storage.", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Store value"); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Key"), + "booleanKey", + ); + agHelper.TypeText(propPane._actionSelectorFieldByLabel("Value"), "true"); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit"); + EditorNavigation.SelectEntityByName("Text1", EntityType.Widget); + propPane.TypeTextIntoField( + "Text", + `{{localStorage.getItem("booleanKey")}}`, + ); + agHelper.AssertText(locators._textInside, "text", "true"); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + + //deploy verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.AssertText(locators._textInside, "text", "true"); + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + + // JSobject verification + const jsObjectBody = `export default { + myFun1 () { + {{storeValue('booleanKey', 'true');}} + }, + }`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + agHelper.ClickButton("Submit"); + agHelper.AssertText(locators._textInside, "text", "true"); + EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.AssertText(locators._textInside, "text", "true"); + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", false); + agHelper.GetNClick(propPane._actionCardByTitle("Execute a JS function")); + agHelper.GetNClick(propPane._actionSelectorDelete); + }); + + it("2. To verify that when the persist parameter is set to false, the value is not saved after refreshing the page.", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", false); + propPane.SelectPlatformFunction("onClick", "Store value"); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Key"), + "booleanKey", + ); + agHelper.TypeText(propPane._actionSelectorFieldByLabel("Value"), "false"); + agHelper.RefreshPage(); + agHelper.AssertText(locators._textInside, "text", "true"); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", false); + agHelper.GetNClick(propPane._actionCardByTitle("Store value")); + agHelper.GetNClick(propPane._actionSelectorDelete); + }); + + it("3. To verify value stored under a key can be successfully overwritten.", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Store value"); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Key"), + "booleanKey", + ); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Value"), + "oldValue", + ); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit"); + EditorNavigation.SelectEntityByName("Text1", EntityType.Widget); + propPane.TypeTextIntoField( + "Text", + `{{localStorage.getItem("booleanKey")}}`, + ); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + agHelper.GetNClick(propPane._actionCardByTitle("Store value")); + agHelper.RemoveChars( + propPane._actionSelectorFieldByLabel("Value"), + 20, + 0, + ); + + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Value"), + "newValue", + ); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit"); + + EditorNavigation.SelectEntityByName("Text1", EntityType.Widget); + agHelper.WaitUntilEleAppear(locators._textInside); + propPane.TypeTextIntoField( + "Text", + `{{localStorage.getItem("booleanKey")}}`, + ); + + agHelper.AssertText(locators._textInside, "text", "newValue"); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + agHelper.GetNClick(propPane._actionCardByTitle("Store value")); + agHelper.GetNClick(propPane._actionSelectorDelete); + }); + + // Open bug present : https://github.com/appsmithorg/appsmith/issues/37671 + it.skip("4. To verify that calling storeValue() without a key parameter does not store any value.", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Store value"); + agHelper.TypeText(propPane._actionSelectorFieldByLabel("Value"), "true"); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit"); + EditorNavigation.SelectEntityByName("Text1", EntityType.Widget); + propPane.TypeTextIntoField("Text", `{{localStorage.getItem("")}}`, true); + agHelper.AssertText(locators._textInside, "text", "true"); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + agHelper.GetNClick(propPane._actionCardByTitle("Store value")); + agHelper.GetNClick(propPane._actionSelectorDelete); + }); + + // Open bug present : https://github.com/appsmithorg/appsmith/issues/37671 + it.skip("5. To verify that calling storeValue() with a non-string key fails. The value should not be stored, and an error should be thrown due to an invalid key type.", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Store value"); + agHelper.TypeText(propPane._actionSelectorFieldByLabel("Value"), "true"); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit"); + EditorNavigation.SelectEntityByName("Text1", EntityType.Widget); + propPane.TypeTextIntoField("Text", `{{localStorage.getItem("")}}`, true); + agHelper.ClickOutside(); + agHelper.ClickButton("Submit"); + agHelper.AssertText(locators._textInside, "text", "true"); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + agHelper.GetNClick(propPane._actionCardByTitle("Store value")); + agHelper.GetNClick(propPane._actionSelectorDelete); + }); + + it("6. To verify if the value stored using storeValue() can be accessed through appsmith.store", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Store value"); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Key"), + "booleanKey", + ); + agHelper.TypeText(propPane._actionSelectorFieldByLabel("Value"), "true"); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit"); + EditorNavigation.SelectEntityByName("Text1", EntityType.Widget); + propPane.TypeTextIntoField("Text", `{{appsmith.store.booleanKey}}`); + agHelper.AssertText(locators._textInside, "text", "true"); + + // Deploy verification for both key-value pairs + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.AssertText(locators._textInside, "text", "true"); + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + + // JSObject verification for both key-value pairs + const jsObjectBody = `export default { + myFun1 () { + {{appsmith.store.booleanKey}} + }, + }`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + agHelper.ClickButton("Submit"); + agHelper.AssertText(locators._textInside, "text", "true"); + EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.AssertText(locators._textInside, "text", "true"); + deployMode.NavigateBacktoEditor(); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", false); + agHelper.GetNClick(propPane._actionCardByTitle("Execute a JS function")); + agHelper.GetNClick(propPane._actionSelectorDelete); + }); + + it("7. To verify if multiple values can be stored at once using an object.", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Store value"); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Key"), + "objectKey", + ); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Value"), + JSON.stringify({ key1: "value1", key2: "value2" }), + ); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit"); + + entityExplorer.DragDropWidgetNVerify(draggableWidgets.TEXT, 200, 700); + EditorNavigation.SelectEntityByName("Text1", EntityType.Widget); + propPane.TypeTextIntoField( + "Text", + `{{JSON.parse(localStorage.getItem("objectKey")).key1}}`, + ); + agHelper.AssertText(locators._textInside, "text", "value1"); + + EditorNavigation.SelectEntityByName("Text2", EntityType.Widget); + propPane.TypeTextIntoField( + "Text", + `{{JSON.parse(localStorage.getItem("objectKey")).key2}}`, + ); + agHelper.AssertText(locators._textInside, "text", "value2", 1); + + // Deploy verification for both key-value pairs + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.AssertText(locators._textInside, "text", "value1"); + agHelper.AssertText(locators._textInside, "text", "value2", 1); + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + + // JSObject verification for both key-value pairs + const jsObjectBody = `export default { + myFun1 () { + {{storeValue('objectKey', JSON.stringify({ key1: 'value1', key2: 'value2' }));}} + }, + }`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + agHelper.ClickButton("Submit"); + agHelper.AssertText(locators._textInside, "text", "value1"); + agHelper.AssertText(locators._textInside, "text", "value2", 1); + EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.AssertText(locators._textInside, "text", "value1"); + agHelper.AssertText(locators._textInside, "text", "value2", 1); + deployMode.NavigateBacktoEditor(); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", false); + agHelper.GetNClick(propPane._actionCardByTitle("Execute a JS function")); + agHelper.GetNClick(propPane._actionSelectorDelete); + }); + }, +); diff --git a/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_NavigateToFunctions_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_NavigateToFunctions_spec.ts new file mode 100644 index 000000000000..173e6437e981 --- /dev/null +++ b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_NavigateToFunctions_spec.ts @@ -0,0 +1,323 @@ +import { + agHelper, + appSettings, + dataSources, + deployMode, + draggableWidgets, + entityExplorer, + jsEditor, + propPane, +} from "../../../../support/Objects/ObjectsCore"; +import { EntityItems } from "../../../../support/Pages/AssertHelper"; +import EditorNavigation, { + EntityType, +} from "../../../../support/Pages/EditorNavigation"; +import PageList from "../../../../support/Pages/PageList"; + +describe( + "To verify action selector navigate to functions", + { tags: ["@tag.JS"] }, + () => { + let pageTwoUrl: string = ""; + before(() => { + entityExplorer.DragDropWidgetNVerify(draggableWidgets.BUTTON); + PageList.AddNewPage(); + cy.url().then((url) => { + pageTwoUrl = url; + }); + EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + }); + + it("1. To verify trigger the action without editing any field - error should be for missing navigation path and not something arbitrary like unexpected token", () => { + propPane.EnterJSContext("onClick", "{{navigateTo()}}", true, false); + propPane.ToggleJSMode("onClick", false); + + agHelper.GetNAssertElementText( + propPane._actionCard, + "Navigate toSelect page", + "have.text", + 0, + ); + agHelper.GetNClick(propPane._actionCard, 0); + + agHelper.AssertElementVisibility(propPane._navigateToType("Page name")); + + dataSources.ValidateNSelectDropdown( + "Choose page", + "Select page", + "Page2", + ); + + agHelper.GetNAssertElementText( + propPane._actionPopupTextLabel, + "Query params", + "have.text", + 0, + ); + + agHelper.GetNClick(propPane._actionCollapsibleHeader("Query params")); + propPane.UpdatePropertyFieldValue( + "Query params", + `{{ + { + + } + }}`, + ); + agHelper.ClickButton("Submit"); + agHelper.AssertURL(pageTwoUrl); + EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.AssertURL(pageTwoUrl); + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + + const jsObjectBody = `export default { + myFun1 () { + {{navigateTo('Page2', { + + }, 'SAME_WINDOW');}} + }, + }`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + agHelper.ClickButton("Submit"); + agHelper.AssertURL(pageTwoUrl); + EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.AssertURL(pageTwoUrl); + deployMode.NavigateBacktoEditor(); + }); + + it("2. To verify add a widget navigation using URL containing widgetID", () => { + EditorNavigation.SelectEntityByName("Page2", EntityType.Page); + entityExplorer.DragDropWidgetNVerify(draggableWidgets.TEXT, 200, 600); + cy.url().then((url) => { + pageTwoUrl = url; + }); + EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", false); + propPane.SelectPlatformFunction("onClick", "Navigate to"); + propPane.SelectActionByTitleAndValue("Navigate to", "Select page"); + agHelper.GetNClick(propPane._navigateToType("URL")); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Enter URL"), + pageTwoUrl, + ); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit"); + agHelper.AssertURL(pageTwoUrl); + EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.AssertURL(pageTwoUrl); + EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + + const jsObjectBody = `export default { + myFun1 () { + {{navigateTo('${pageTwoUrl}', {}, 'SAME_WINDOW');}} + }, + }`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + agHelper.ClickButton("Submit"); + agHelper.AssertURL(pageTwoUrl); + EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.AssertURL(pageTwoUrl); + }); + + it("3. To verify add a navigation using URL containing links to third party websites", () => { + EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", false); + const thirdPartyUrl = "https://www.google.com/"; + propPane.SelectPlatformFunction("onClick", "Navigate to"); + propPane.SelectActionByTitleAndValue("Navigate to", "Select page"); + agHelper.GetNClick(propPane._navigateToType("URL")); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Enter URL"), + thirdPartyUrl, + ); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit"); + agHelper.AssertURL(thirdPartyUrl); + agHelper.VisitNAssert(pageTwoUrl); + EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.AssertURL(thirdPartyUrl); + agHelper.VisitNAssert(pageTwoUrl); + EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + + const jsObjectBody = `export default { + myFun1 () { + {{navigateTo('${thirdPartyUrl}', {}, 'SAME_WINDOW');}} + }, + }`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + agHelper.ClickButton("Submit"); + agHelper.AssertURL(thirdPartyUrl); + agHelper.VisitNAssert(pageTwoUrl); + EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.AssertURL(thirdPartyUrl); + agHelper.VisitNAssert(pageTwoUrl); + EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + }); + + it("4. To verify navigation to a hidden page in same as well a new window", () => { + PageList.AddNewPage(); + entityExplorer.ActionContextMenuByEntityName({ + entityNameinLeftSidebar: "Page3", + action: "Hide", + entityType: EntityItems.Page, + }); + EditorNavigation.SelectEntityByName("Page3", EntityType.Page); + cy.url().then((url) => { + pageTwoUrl = url; + }); + EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", false); + propPane.SelectPlatformFunction("onClick", "Navigate to"); + propPane.SelectActionByTitleAndValue("Navigate to", "Select page"); + agHelper.GetNClick(propPane._navigateToType("URL")); + agHelper.TypeText( + propPane._actionSelectorFieldByLabel("Enter URL"), + pageTwoUrl, + ); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit"); + agHelper.AssertURL(pageTwoUrl); + EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.AssertURL(pageTwoUrl); + EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + + const jsObjectBody = `export default { + myFun1 () { + {{navigateTo('${pageTwoUrl}', {}, 'SAME_WINDOW');}} + }, + }`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + agHelper.ClickButton("Submit"); + agHelper.AssertURL(pageTwoUrl); + EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.AssertURL(pageTwoUrl); + EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + }); + }, +); diff --git a/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_PostWindowFunctions_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_PostWindowFunctions_spec.ts new file mode 100644 index 000000000000..ae8c1ae22a76 --- /dev/null +++ b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_PostWindowFunctions_spec.ts @@ -0,0 +1,74 @@ +import { + agHelper, + debuggerHelper, + deployMode, + draggableWidgets, + entityExplorer, + homePage, + jsEditor, + locators, + propPane, +} from "../../../../support/Objects/ObjectsCore"; +import EditorNavigation, { + EntityType, +} from "../../../../support/Pages/EditorNavigation"; + +describe( + "To verify action selector - PostWindow function", + { tags: ["@tag.JS"] }, + () => { + before(() => { + homePage.ImportApp("IframeWidgetPostMessage.json"); + }); + + const getIframeBody = (i: number) => { + return cy + .get(".t--draggable-iframewidget iframe") + .eq(i) + .its("0.contentDocument.body") + .should("not.be.empty") + .then(cy.wrap); + }; + + it("1. Verify that postWindowMessage() can successfully send a message to the parent application’s window.", () => { + agHelper.ClickButton("Submit", { force: true }); + getIframeBody(0) + .find("input") + .should("be.visible") + .invoke("val") + .then((inputValue) => { + expect(inputValue).to.equal("submitclicked"); + }); + }); + + it("2. Verify that postWindowMessage() can successfully send a message to a specified iframe embedded within Appsmith.", () => { + getIframeBody(0).find("#test > input").clear().type("Sample Text"); + agHelper.ClickButton("Submit", { force: true }); + agHelper.ValidateToastMessage("Hey Iframe Called."); + }); + + it("3. Verify the behavior of postWindowMessage() when sending an empty message.", () => { + entityExplorer.DragDropWidgetNVerify(draggableWidgets.BUTTON, 200, 200); + propPane.SelectPlatformFunction("onClick", "Post message"); + agHelper.EnterActionValue("Message", ""); + agHelper.GetNClick(propPane._windowTargetDropdown); + agHelper.GetNClick(locators._dropDownValue("Iframe1"), 0, true); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit"); + agHelper.AssertElementAbsence(locators._toastMsg); + + deployMode.DeployApp(); + agHelper.ClickButton("Submit"); + agHelper.AssertElementAbsence(locators._toastMsg); + deployMode.NavigateBacktoEditor(); + }); + + it("4. Verify behavior when an invalid or malformed URL is provided as targetOrigin.", () => { + entityExplorer.DragDropWidgetNVerify(draggableWidgets.IFRAME, 200, 300); + EditorNavigation.SelectEntityByName("Iframe2", EntityType.Widget); + propPane.UpdatePropertyFieldValue("URL", " "); + agHelper.SelectNRemoveLineText(locators._existingFieldTextByName("URL")); + agHelper.AssertContains("Valid source URL is required"); + }); + }, +); diff --git a/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_ResetWidgetFunctions_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_ResetWidgetFunctions_spec.ts new file mode 100644 index 000000000000..4b258b26cb58 --- /dev/null +++ b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_ResetWidgetFunctions_spec.ts @@ -0,0 +1,239 @@ +import { + agHelper, + appSettings, + dataSources, + deployMode, + draggableWidgets, + entityExplorer, + jsEditor, + locators, + propPane, +} from "../../../../support/Objects/ObjectsCore"; +import EditorNavigation, { + EntityType, +} from "../../../../support/Pages/EditorNavigation"; + +describe( + "To verify action selector - reset widget function", + { tags: ["@tag.JS"] }, + () => { + before(() => { + entityExplorer.DragDropWidgetNVerify(draggableWidgets.BUTTON, 100, 100); + entityExplorer.DragDropWidgetNVerify(draggableWidgets.INPUT_V2, 200, 200); + }); + + it("1. Verify the behavior when an invalid widget name is provided. The function should not reset any widget, and an appropriate error should be logged.", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.EnterJSContext( + "onClick", + `{{resetWidget("Input2", true);}}`, + true, + false, + ); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage(`Widget Input2 not found`, 0, 2); + + // Deploy verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage(`Widget Input2 not found`, 0, 2); + deployMode.NavigateBacktoEditor(); + + // JSObject verification + const jsObjectBody = `export default { + myFun1() { + try { + const result = resetWidget("Input2", true); + return result; + } catch (error) { + showAlert("Error: " + error.message); + return null; + } + }, + };`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage(`Widget Input2 not found`, 0, 2); + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage(`Widget Input2 not found`, 0, 2); + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + agHelper.WaitUntilEleAppear(locators._jsToggle("onClick")); + propPane.ToggleJSMode("onClick", false); + agHelper.WaitUntilEleAppear( + propPane._actionCardByTitle("Execute a JS function"), + ); + agHelper.GetNClick(propPane._actionCardByTitle("Execute a JS function")); + agHelper.GetNClick(propPane._actionSelectorDelete); + }); + + it("2. Verify the behavior when attempting to reset a widget that has no child widgets, but resetChildren is set to true.", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.EnterJSContext( + "onClick", + `{{resetWidget("Input1", true);}}`, + true, + false, + ); + propPane.ToggleJSMode("onClick", false); + propPane.SelectPlatformFunction("onClick", "Reset widget"); + dataSources.ValidateNSelectDropdown("Widget", "Select widget", "Input1"); + agHelper.GetNClick(propPane._actionSelectorPopupClose); + agHelper.ClickButton("Submit"); + agHelper.AssertElementAbsence(locators._toastMsg); + + // Deploy verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.AssertElementAbsence(locators._toastMsg); + deployMode.NavigateBacktoEditor(); + + // JSObject verification + const jsObjectBody = `export default { + myFun1() { + try { + const result = resetWidget("Input1", true); + return result; + } catch (error) { + showAlert("Error: " + error.message); + return null; + } + }, + };`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + + agHelper.ClickButton("Submit"); + agHelper.AssertElementAbsence(locators._toastMsg); + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.AssertElementAbsence(locators._toastMsg); + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + agHelper.WaitUntilEleAppear(locators._jsToggle("onClick")); + propPane.ToggleJSMode("onClick", false); + agHelper.WaitUntilEleAppear( + propPane._actionCardByTitle("Execute a JS function"), + ); + agHelper.GetNClick(propPane._actionCardByTitle("Execute a JS function")); + agHelper.GetNClick(propPane._actionSelectorDelete); + }); + + it("3. Verify behavior when trying to reset a widget that does not exist on the page. No widget should reset, and an appropriate error or message should be logged.", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.EnterJSContext( + "onClick", + `{{resetWidget("NonExistentWidget", false);}}`, + true, + false, + ); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage(`Widget NonExistentWidget not found`, 0, 2); + + // Deploy verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage(`Widget NonExistentWidget not found`, 0, 2); + deployMode.NavigateBacktoEditor(); + + // JSObject verification + const jsObjectBody = `export default { + myFun1() { + try { + const result = resetWidget("NonExistentWidget", false); + return result; + } catch (error) { + showAlert("Error: " + error.message); + return null; + } + }, + };`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage(`Widget NonExistentWidget not found`, 0, 2); + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage(`Widget NonExistentWidget not found`, 0, 2); + deployMode.NavigateBacktoEditor(); + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + agHelper.WaitUntilEleAppear(locators._jsToggle("onClick")); + propPane.ToggleJSMode("onClick", false); + agHelper.WaitUntilEleAppear( + propPane._actionCardByTitle("Execute a JS function"), + ); + agHelper.GetNClick(propPane._actionCardByTitle("Execute a JS function")); + agHelper.GetNClick(propPane._actionSelectorDelete); + }); + }, +); diff --git a/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_SetIntervalFunctions_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_SetIntervalFunctions_spec.ts new file mode 100644 index 000000000000..c9a3682d055f --- /dev/null +++ b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_SetIntervalFunctions_spec.ts @@ -0,0 +1,153 @@ +import { + agHelper, + appSettings, + assertHelper, + dataSources, + debuggerHelper, + deployMode, + homePage, + jsEditor, + locators, + propPane, +} from "../../../../support/Objects/ObjectsCore"; +import EditorNavigation, { + EntityType, +} from "../../../../support/Pages/EditorNavigation"; + +describe( + "To verify action selector - setInterval function", + { tags: ["@tag.JS"] }, + () => { + before(() => { + homePage.NavigateToHome(); + homePage.ImportApp("setIntervalApp.json"); + }); + + it("1. Verify that the callback function is executed at regular intervals specified by the setInterval() function.", () => { + //Buttom mode verification + agHelper.ClickButton("Submit1_1"); + assertHelper.AssertNetworkStatus("postExecute"); + assertHelper.AssertNetworkStatus("postExecute"); + //Deploy mode verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit1_1"); + assertHelper.AssertNetworkStatus("postExecute"); + assertHelper.AssertNetworkStatus("postExecute"); + deployMode.NavigateBacktoEditor(); + + //JS Object verification + EditorNavigation.SelectEntityByName("Submit1_2", EntityType.Widget); + agHelper.ClickButton("Submit1_2"); + agHelper.ValidateToastMessage( + "Interval started successfully with jsobject.", + 0, + 2, + ); + assertHelper.AssertNetworkStatus("postExecute"); + assertHelper.AssertNetworkStatus("postExecute"); + //Deploy mode verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit1_2"); + agHelper.ValidateToastMessage( + "Interval started successfully with jsobject.", + 0, + 2, + ); + assertHelper.AssertNetworkStatus("postExecute"); + assertHelper.AssertNetworkStatus("postExecute"); + deployMode.NavigateBacktoEditor(); + agHelper.RefreshPage(); + }); + + it("2. Verify that multiple setInterval() functions can run at the same time.", () => { + //Buttom mode verification + agHelper.ClickButton("Submit2_1"); + assertHelper.AssertNetworkStatus("postExecute"); + assertHelper.AssertNetworkStatus("postExecute"); + //Deploy mode verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit2_1"); + assertHelper.AssertNetworkStatus("postExecute"); + assertHelper.AssertNetworkStatus("postExecute"); + deployMode.NavigateBacktoEditor(); + + //JS Object verification + EditorNavigation.SelectEntityByName("Submit2_2", EntityType.Widget); + agHelper.ClickButton("Submit2_2"); + agHelper.ValidateToastMessage("Api1 executed", 0, 2); + agHelper.ValidateToastMessage("Api2 executed", 0, 2); + assertHelper.AssertNetworkStatus("postExecute"); + assertHelper.AssertNetworkStatus("postExecute"); + //Deploy mode verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit2_2"); + agHelper.ValidateToastMessage("Api1 executed", 0, 2); + agHelper.ValidateToastMessage("Api2 executed", 0, 2); + assertHelper.AssertNetworkStatus("postExecute"); + assertHelper.AssertNetworkStatus("postExecute"); + deployMode.NavigateBacktoEditor(); + agHelper.RefreshPage(); + }); + + it("3. Verify behavior when an invalid callback function is passed to setInterval(). An error should be thrown, and no interval should be set.", () => { + //JS Object verification + EditorNavigation.SelectEntityByName("Submit3_2", EntityType.Widget); + propPane.EnterJSContext( + "onClick", + `{{setInterval(() => { + testInvalid123(); + }, 2000, "testingFun");}}`, + ); + agHelper.ClickButton("Submit3_2"); + debuggerHelper.AssertDebugError( + "'testInvalid123' is not defined.", + "", + true, + false, + ); + agHelper.RefreshPage(); + }); + + it("4. Verify behavior when an invalid time interval is provided. An error should be thrown, and no interval should be set.", () => { + //JS Object verification + EditorNavigation.SelectEntityByName("Submit4_2", EntityType.Widget); + agHelper.ClickButton("Submit4_2"); + agHelper.ValidateToastMessage("dasdas is not defined", 0, 2); + + //Deploy mode verification + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit4_2"); + agHelper.ValidateToastMessage("dasdas is not defined", 0, 2); + + deployMode.NavigateBacktoEditor(); + agHelper.RefreshPage(); + }); + + it("5. Verify that intervals are cleared after a page refresh.", () => { + agHelper.RefreshPage(); + EditorNavigation.SelectEntityByName("Submit5_2", EntityType.Widget); + agHelper.ClickButton("Submit5_2"); + agHelper.ValidateToastMessage("Interval started successfully.", 0, 2); + agHelper.ValidateToastMessage("Interval triggered!", 0, 2); + agHelper.RefreshPage(); + agHelper.Sleep(5000); // This sleep is needed for mandatory verification of 5 second interval. + agHelper.AssertElementAbsence(locators._toastMsg); + + //Deploy mode verification + deployMode.DeployApp(); + agHelper.ClickButton("Submit5_2"); + agHelper.ValidateToastMessage("Interval started successfully.", 0, 2); + agHelper.ValidateToastMessage("Interval triggered!", 0, 2); + cy.reload(); + agHelper.Sleep(5000); // This sleep is needed for mandatory verification of 5 second interval. + agHelper.AssertElementAbsence(locators._toastMsg); + deployMode.NavigateBacktoEditor(); + agHelper.RefreshPage(); + }); + }, +); diff --git a/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_ShowAlertFunctions_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_ShowAlertFunctions_spec.ts new file mode 100644 index 000000000000..9ea7b04c0f62 --- /dev/null +++ b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_ShowAlertFunctions_spec.ts @@ -0,0 +1,433 @@ +import { + agHelper, + appSettings, + deployMode, + draggableWidgets, + entityExplorer, + jsEditor, + locators, + propPane, +} from "../../../../support/Objects/ObjectsCore"; +import commonlocators from "../../../../locators/commonlocators.json"; +import EditorNavigation, { + EntityType, +} from "../../../../support/Pages/EditorNavigation"; + +describe( + "To verify the action selector - Show Alert functions", + { tags: ["@tag.JS"] }, + () => { + before(() => { + entityExplorer.DragDropWidgetNVerify(draggableWidgets.BUTTON); + }); + + //Please check requirement for this test case + it("1. To verify trigger the action without editing any field in the action selector dropdown - error should be for missing (blank) message and not something arbitrary like unexpected token", () => { + propPane.EnterJSContext("onClick", `{{showAlert("", '')}}`, true); + propPane.ToggleJSMode("onClick", false); + agHelper.ClickButton("Submit"); + agHelper.AssertElementVisibility(locators._toastMsg); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.AssertElementVisibility(locators._toastMsg); + deployMode.NavigateBacktoEditor(); + + const jsObjectBody = `export default { + myFun1 () { + {{showAlert("", '')}} + }, + }`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + agHelper.ClickButton("Submit"); + agHelper.AssertElementVisibility(locators._toastMsg); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.AssertElementVisibility(locators._toastMsg); + deployMode.NavigateBacktoEditor(); + }); + + it("2. To verify Select alert type without adding any message and execute trigger - no error should be displayed", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.EnterJSContext("onClick", `{{showAlert("", '')}}`, true); + propPane.ToggleJSMode("onClick", false); + agHelper.GetNClick(propPane._actionCard, 0); + agHelper.EnterValue(propPane._actionPopupTextLabel); + propPane.UpdatePropertyFieldValue("Message", `_`); + agHelper.ClickButton("Submit"); + agHelper.AssertElementVisibility(locators._toastMsg); + agHelper.ValidateToastMessage("_", 0, 1); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.AssertElementVisibility(locators._toastMsg); + agHelper.ValidateToastMessage("_", 0, 1); + deployMode.NavigateBacktoEditor(); + + const jsObjectBody = `export default { + myFun1 () { + {{showAlert("_", '')}} + }, + }`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + agHelper.ClickButton("Submit"); + agHelper.AssertElementVisibility(locators._toastMsg); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.AssertElementVisibility(locators._toastMsg); + deployMode.NavigateBacktoEditor(); + }); + + it("3. To verify different message types works as expected when selected from the dropdown or added through code", () => { + //Info alert + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.EnterJSContext("onClick", `{{showAlert("", '')}}`, true); + propPane.ToggleJSMode("onClick", false); + agHelper.GetNClick(propPane._actionCard, 0); + agHelper.EnterValue(propPane._actionPopupTextLabel); + propPane.UpdatePropertyFieldValue("Message", "Info Message"); + agHelper.GetNClick(propPane._dropdownSelectType, 0, true); + agHelper.GetNClickByContains(commonlocators.selectMenuItem, `Info`); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Info Message", 0, 2); + agHelper + .GetAttribute(commonlocators.tostifyIcon, "type") + .then((labelValue) => { + expect(labelValue).to.contain("info"); + }); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Info Message", 0, 2); + agHelper + .GetAttribute(commonlocators.tostifyIcon, "type") + .then((labelValue) => { + expect(labelValue).to.contain("info"); + }); + deployMode.NavigateBacktoEditor(); + + let jsObjectBody = `export default { + myFun1 () { + {{showAlert('Info Message', 'info');}} + }, + }`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Info Message", 0, 2); + agHelper + .GetAttribute(commonlocators.tostifyIcon, "type") + .then((labelValue) => { + expect(labelValue).to.contain("info"); + }); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Info Message", 0, 2); + agHelper + .GetAttribute(commonlocators.tostifyIcon, "type") + .then((labelValue) => { + expect(labelValue).to.contain("info"); + }); + deployMode.NavigateBacktoEditor(); + + //Success alert + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.EnterJSContext("onClick", `{{showAlert("", '')}}`, true); + propPane.ToggleJSMode("onClick", false); + agHelper.GetNClick(propPane._actionCard, 0); + agHelper.EnterValue(propPane._actionPopupTextLabel); + propPane.UpdatePropertyFieldValue("Message", "Success Message"); + agHelper.GetNClick(propPane._dropdownSelectType, 0, true); + agHelper.GetNClickByContains(commonlocators.selectMenuItem, `Success`); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Success Message", 0, 2); + agHelper + .GetAttribute(commonlocators.tostifyIcon, "type") + .then((labelValue) => { + expect(labelValue).to.contain("success"); + }); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Success Message", 0, 2); + agHelper + .GetAttribute(commonlocators.tostifyIcon, "type") + .then((labelValue) => { + expect(labelValue).to.contain("success"); + }); + deployMode.NavigateBacktoEditor(); + + jsObjectBody = `export default { + myFun1 () { + {{showAlert('Success Message', 'success');}} + }, + }`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Success Message", 0, 2); + agHelper + .GetAttribute(commonlocators.tostifyIcon, "type") + .then((labelValue) => { + expect(labelValue).to.contain("success"); + }); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Success Message", 0, 2); + agHelper + .GetAttribute(commonlocators.tostifyIcon, "type") + .then((labelValue) => { + expect(labelValue).to.contain("success"); + }); + deployMode.NavigateBacktoEditor(); + + //Warning alert + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.EnterJSContext("onClick", `{{showAlert("", '')}}`, true); + propPane.ToggleJSMode("onClick", false); + agHelper.GetNClick(propPane._actionCard, 0); + agHelper.EnterValue(propPane._actionPopupTextLabel); + propPane.UpdatePropertyFieldValue("Message", "Warning Message"); + agHelper.GetNClick(propPane._dropdownSelectType, 0, true); + agHelper.GetNClickByContains(commonlocators.selectMenuItem, `Warning`); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Warning Message", 0, 2); + agHelper + .GetAttribute(commonlocators.tostifyIcon, "type") + .then((labelValue) => { + expect(labelValue).to.contain("warning"); + }); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Warning Message", 0, 2); + agHelper + .GetAttribute(commonlocators.tostifyIcon, "type") + .then((labelValue) => { + expect(labelValue).to.contain("warning"); + }); + deployMode.NavigateBacktoEditor(); + + jsObjectBody = `export default { + myFun1 () { + {{showAlert('Warning Message', 'warning');}} + }, + }`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Warning Message", 0, 2); + agHelper + .GetAttribute(commonlocators.tostifyIcon, "type") + .then((labelValue) => { + expect(labelValue).to.contain("warning"); + }); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Warning Message", 0, 2); + agHelper + .GetAttribute(commonlocators.tostifyIcon, "type") + .then((labelValue) => { + expect(labelValue).to.contain("warning"); + }); + deployMode.NavigateBacktoEditor(); + + //Error alert + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.EnterJSContext("onClick", `{{showAlert("", '')}}`, true); + propPane.ToggleJSMode("onClick", false); + agHelper.GetNClick(propPane._actionCard, 0); + agHelper.EnterValue(propPane._actionPopupTextLabel); + propPane.UpdatePropertyFieldValue("Message", "Error Message"); + agHelper.GetNClick(propPane._dropdownSelectType, 0, true); + agHelper.GetNClickByContains(commonlocators.selectMenuItem, `Error`); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Error Message", 0, 2); + agHelper + .GetAttribute(commonlocators.tostifyIcon, "type") + .then((labelValue) => { + expect(labelValue).to.contain("error"); + }); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Error Message", 0, 2); + agHelper + .GetAttribute(commonlocators.tostifyIcon, "type") + .then((labelValue) => { + expect(labelValue).to.contain("error"); + }); + deployMode.NavigateBacktoEditor(); + + jsObjectBody = `export default { + myFun1 () { + {{showAlert('Error Message', 'error');}} + }, + }`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Error Message", 0, 2); + agHelper + .GetAttribute(commonlocators.tostifyIcon, "type") + .then((labelValue) => { + expect(labelValue).to.contain("error"); + }); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Error Message", 0, 2); + agHelper + .GetAttribute(commonlocators.tostifyIcon, "type") + .then((labelValue) => { + expect(labelValue).to.contain("error"); + }); + deployMode.NavigateBacktoEditor(); + }); + }, +); diff --git a/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_ShowCloseModalFunctions_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_ShowCloseModalFunctions_spec.ts new file mode 100644 index 000000000000..2fef0c704cef --- /dev/null +++ b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_ShowCloseModalFunctions_spec.ts @@ -0,0 +1,198 @@ +import { + agHelper, + apiPage, + appSettings, + deployMode, + draggableWidgets, + entityExplorer, + jsEditor, + locators, + propPane, +} from "../../../../support/Objects/ObjectsCore"; +import EditorNavigation, { + EntityType, + PageLeftPane, +} from "../../../../support/Pages/EditorNavigation"; + +describe( + "To verify action selector - Show Modal function", + { tags: ["@tag.JS"] }, + () => { + before(() => { + entityExplorer.DragDropWidgetNVerify(draggableWidgets.BUTTON); + }); + + it("1. To verify a modal is displayed automatically when the page loads using a JSObject with 'Run on Page Load' enabled.", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.CreateModal("onClick"); + agHelper.GetNClick(locators._closeModal, 0, true, 0); + + const jsObjectBody = `export default { + myFun1 () { + {{showModal(Modal1.name);}} + }, + }`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + apiPage.clickSettingIcon(true); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + agHelper.RefreshPage(); + agHelper.AssertElementVisibility(locators._modalWrapper); + agHelper.AssertText(locators._modalButtonText, "text", "Confirm", 2); + agHelper.AssertText(locators._modalButtonText, "text", "Close", 1); + agHelper.GetNClick(locators._closeModal, 0, true, 0); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.RefreshPage(); + agHelper.AssertElementVisibility(locators._modalWrapper); + agHelper.AssertText(locators._modalButtonText, "text", "Confirm", 2); + agHelper.AssertText(locators._modalButtonText, "text", "Close", 1); + agHelper.GetNClick(locators._closeModal, 0, true, 0); + deployMode.NavigateBacktoEditor(); + }); + + it("2. To verify the modal remains in focus after it is opened using the showModal() function preventing interaction with the underlying page.", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + agHelper.ClickButton("Submit"); + cy.get(locators._closeModal).focus().should("have.focus"); + agHelper.RefreshPage(); + }); + + it("3. To verify the behavior when an invalid modal name is provided to the showModal() function. The modal should not open, and an error should be thrown.", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.EnterJSContext("onClick", `{{showModal(Modal2.name);}}`, true); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Modal2 is not defined", 0, 1); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Modal2 is not defined", 0, 1); + deployMode.NavigateBacktoEditor(); + + const jsObjectBody = `export default { + myFun1 () { + {{showModal(Modal2.name);}} + }, + }`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Modal2 is not defined", 0, 1); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Modal2 is not defined", 0, 1); + deployMode.NavigateBacktoEditor(); + }); + + it("4. To verify the behavior when an invalid modal name is provided to the closeModal() function. The modal should not close, and there should be no action and an error should be thrown", () => { + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.EnterJSContext("onClick", `{{showModal(Modal1.name);}}`, true); + agHelper.ClickButton("Submit"); + PageLeftPane.expandCollapseItem("Modal1"); + EditorNavigation.SelectEntityByName("IconButton1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + propPane.EnterJSContext("onClick", `{{closeModal(Modal2.name);}}`, true); + agHelper.RefreshPage(); + agHelper.ClickButton("Submit"); + agHelper.GetNClick(locators._modalButtonText, 0, true, 0); + agHelper.ValidateToastMessage("Modal2 is not defined", 0, 1); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.GetNClick(locators._modalButtonText, 0, true, 0); + agHelper.ValidateToastMessage("Modal2 is not defined", 0, 1); + deployMode.NavigateBacktoEditor(); + agHelper.GetNClick(locators._closeModal, 0, true, 0); + const jsObjectBody = `export default { + myFun1 () { + {{closeModal(Modal2.name);}} + }, + }`; + + jsEditor.CreateJSObject(jsObjectBody, { + paste: true, + completeReplace: true, + toRun: false, + prettify: false, + shouldCreateNewJSObj: true, + }); + agHelper.GetText(jsEditor._jsObjName).then((jsObjectName: string) => { + cy.wrap(jsObjectName).as("jsObjectName"); + }); + + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.EnterJSContext("onClick", `{{showModal(Modal1.name);}}`, true); + PageLeftPane.expandCollapseItem("Modal1"); + EditorNavigation.SelectEntityByName("IconButton1", EntityType.Widget); + propPane.ToggleJSMode("onClick", true); + cy.get("@jsObjectName").then((jsObjectName: string) => { + console.log("Mera variable: ", jsObjectName); + propPane.EnterJSContext( + "onClick", + `{{${jsObjectName}.myFun1()}}`, + true, + false, + ); + }); + agHelper.RefreshPage(); + agHelper.ClickButton("Submit"); + agHelper.GetNClick(locators._modalButtonText, 0, true, 0); + agHelper.ValidateToastMessage("Modal2 is not defined", 0, 1); + + deployMode.DeployApp(); + agHelper.AssertElementVisibility(appSettings.locators._header); + agHelper.ClickButton("Submit"); + agHelper.GetNClick(locators._modalButtonText, 0, true, 0); + agHelper.ValidateToastMessage("Modal2 is not defined", 0, 1); + deployMode.NavigateBacktoEditor(); + }); + }, +); diff --git a/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_StopWatchGeoLocationFunctions_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_StopWatchGeoLocationFunctions_spec.ts new file mode 100644 index 000000000000..b3e470b8911a --- /dev/null +++ b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_StopWatchGeoLocationFunctions_spec.ts @@ -0,0 +1,120 @@ +import { + agHelper, + deployMode, + draggableWidgets, + entityExplorer, + locators, + propPane, +} from "../../../../support/Objects/ObjectsCore"; +import EditorNavigation, { + EntityType, +} from "../../../../support/Pages/EditorNavigation"; + +describe( + "To verify action selector - StopWatchGeoLocation function", + { tags: ["@tag.JS"] }, + () => { + before(() => { + entityExplorer.DragDropWidgetNVerify(draggableWidgets.TEXT, 100, 100); + entityExplorer.DragDropWidgetNVerify(draggableWidgets.BUTTON, 100, 200); + }); + + it("1. Verify that calling geolocation.clearWatch() when no geolocation watch is active throws an error.", () => { + // Mock geolocation permissions + cy.window().then((win) => { + cy.stub(win.navigator.permissions, "query").resolves({ + state: "granted", + }); + }); + + // Try to clear watch without active watch + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Stop watching geolocation"); + agHelper.ClickButton("Submit"); + + // Verify error message with wait + agHelper.ValidateToastMessage("No location watch active", 0, 1); + + // Verify same behavior in deploy mode + deployMode.DeployApp(); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("No location watch active", 0, 1); + deployMode.NavigateBacktoEditor(); + }); + + it("2. Verify that geolocation.clearWatch() allows clearing the current watch, and a new geolocation watch can be started immediately after.", () => { + // Mock geolocation with changing positions + let watchCallback: ((position: GeolocationPosition) => void) | null = + null; + + cy.window().then((win) => { + cy.stub(win.navigator.permissions, "query").resolves({ + state: "granted", + }); + cy.stub(win.navigator.geolocation, "watchPosition").callsFake( + (success) => { + watchCallback = success; + success({ + coords: { + latitude: 37.7749, + longitude: -122.4194, + accuracy: 10, + altitude: null, + altitudeAccuracy: null, + heading: null, + speed: null, + }, + timestamp: Date.now(), + }); + return 0; + }, + ); + }); + + // Set up text widget to display coordinates + EditorNavigation.SelectEntityByName("Text1", EntityType.Widget); + propPane.UpdatePropertyFieldValue( + "Text", + "{{appsmith.geolocation.currentPosition.coords.latitude}}, {{appsmith.geolocation.currentPosition.coords.longitude}}", + ); + + // Start watching position + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Watch geolocation"); + agHelper.ClickButton("Submit"); + + // Verify initial position + cy.get(locators._textWidget) + .first() + .should("contain", "37.7749, -122.4194"); + + // Clear watch + propPane.SelectPlatformFunction("onClick", "Stop watching geolocation"); + agHelper.ClickButton("Submit"); + + // Start new watch + propPane.SelectPlatformFunction("onClick", "Watch geolocation"); + agHelper.ClickButton("Submit"); + + // Verify new watch works + cy.window().then(() => { + watchCallback?.({ + coords: { + latitude: 40.7128, + longitude: -74.006, + accuracy: 10, + altitude: null, + altitudeAccuracy: null, + heading: null, + speed: null, + }, + timestamp: Date.now(), + }); + }); + + cy.get(locators._textWidget) + .first() + .should("contain", "40.7128, -74.006"); + }); + }, +); diff --git a/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_WatchGeoLocationFunctions_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_WatchGeoLocationFunctions_spec.ts new file mode 100644 index 000000000000..5e03965a22e4 --- /dev/null +++ b/app/client/cypress/e2e/Regression/ClientSide/ActionExecution/FrameworkFunctions_WatchGeoLocationFunctions_spec.ts @@ -0,0 +1,245 @@ +import { + agHelper, + deployMode, + draggableWidgets, + entityExplorer, + locators, + propPane, +} from "../../../../support/Objects/ObjectsCore"; +import EditorNavigation, { + EntityType, +} from "../../../../support/Pages/EditorNavigation"; + +describe( + "To verify action selector - WatchGeoLocation function", + { tags: ["@tag.JS"] }, + () => { + before(() => { + entityExplorer.DragDropWidgetNVerify(draggableWidgets.TEXT, 100, 100); + entityExplorer.DragDropWidgetNVerify(draggableWidgets.BUTTON, 100, 200); + }); + + it("1. Verify that getCurrentPosition successfully retrieves the current position and automatically updates appsmith.geolocation.currentPosition.coords", () => { + // Mock geolocation permissions + cy.window().then((win) => { + cy.stub(win.navigator.permissions, "query").resolves({ + state: "granted", + }); + }); + + // Mock geolocation with changing positions + let watchCallback: ((position: GeolocationPosition) => void) | null = + null; + + cy.window().then((win) => { + cy.stub(win.navigator.geolocation, "watchPosition").callsFake( + (success) => { + watchCallback = success; + // Initial position + success({ + coords: { + latitude: 37.7749, + longitude: -122.4194, + accuracy: 10, + altitude: null, + altitudeAccuracy: null, + heading: null, + speed: null, + }, + timestamp: Date.now(), + }); + return 0; + }, + ); + }); + + // Set up text widget to display coordinates + EditorNavigation.SelectEntityByName("Text1", EntityType.Widget); + propPane.UpdatePropertyFieldValue( + "Text", + "{{appsmith.geolocation.currentPosition.coords.latitude}}, {{appsmith.geolocation.currentPosition.coords.longitude}}", + ); + + // Start watching position + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Watch geolocation"); + agHelper.ClickButton("Submit"); + + // Verify first position update + cy.get(locators._textWidget) + .first() + .should("contain", "37.7749, -122.4194"); + + // Simulate position change + cy.window().then(() => { + watchCallback?.({ + coords: { + latitude: 40.7128, + longitude: -74.006, + accuracy: 10, + altitude: null, + altitudeAccuracy: null, + heading: null, + speed: null, + }, + timestamp: Date.now(), + }); + }); + + // Verify position update + cy.get(locators._textWidget) + .first() + .should("contain", "40.7128") + .and("contain", "-74.006"); + }); + + it("2. Verify that calling getCurrentPosition when a geolocation watch is active throws an error.", () => { + // Start watching position + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.SelectPlatformFunction("onClick", "Watch geolocation"); + agHelper.ClickButton("Submit"); + + // Try to call getCurrentPosition while watch is active + propPane.SelectPlatformFunction("onClick", "Get geolocation"); + agHelper.ClickButton("Submit"); + + // Verify error message + agHelper.ValidateToastMessage( + "A watchLocation is already active. Clear it before before starting a new one", + ); + + // Clear the watch + propPane.SelectPlatformFunction("onClick", "Stop watching geolocation"); + agHelper.ClickButton("Submit"); + + // Now getCurrentPosition should work + propPane.SelectPlatformFunction("onClick", "Get geolocation"); + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage( + "A watchLocation is already active. Clear it before before starting a new one", + ); // No error message + }); + + it("3. Verify that the error callback is executed when getCurrentPosition encounters an error (e.g., location services disabled or permission denied).", () => { + // Mock geolocation with error + cy.window().then((win) => { + cy.stub(win.navigator.permissions, "query").resolves({ + state: "denied", + }); + cy.stub(win.navigator.geolocation, "watchPosition").callsFake( + (success, error) => { + error({ + code: 1, + message: + "A watchLocation is already active. Clear it before before starting a new one", + }); + return 0; + }, + ); + }); + + // Set up watch position with error callback + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.EnterJSContext( + "onClick", + `{{appsmith.geolocation.watchPosition( + () => showAlert('Success'), + (error) => showAlert(error.message) + )}}`, + true, + false, + ); + + // Trigger watch and verify error + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage( + "A watchLocation is already active. Clear it before before starting a new one", + ); + }); + + it.skip("4. Verify that getCurrentPosition correctly handles the options parameter for maximumAge, timeout, and enableHighAccuracy.", () => { + // Mock geolocation with options verification + cy.window().then((win) => { + cy.stub(win.navigator.geolocation, "watchPosition").callsFake( + (success, error, options) => { + // Verify options are passed correctly + expect(options).to.deep.equal({ + maximumAge: 1000, + timeout: 5000, + enableHighAccuracy: true, + }); + + success({ + coords: { + latitude: 37.7749, + longitude: -122.4194, + accuracy: 10, + altitude: null, + altitudeAccuracy: null, + heading: null, + speed: null, + }, + timestamp: Date.now(), + }); + return 0; + }, + ); + }); + + // Set up watch position with options + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.EnterJSContext( + "onClick", + `{{appsmith.geolocation.watchPosition( + () => showAlert('Success'), + (error) => showAlert(error.message), + { + maximumAge: 1000, + timeout: 5000, + enableHighAccuracy: true + } + )}}`, + true, + false, + ); + + // Verify in edit mode + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Success"); + + // Verify in deploy mode + deployMode.DeployApp(); + + // Re-mock geolocation for deploy mode + cy.window().then((win) => { + cy.stub(win.navigator.geolocation, "watchPosition").callsFake( + (success, error, options) => { + expect(options).to.deep.equal({ + maximumAge: 1000, + timeout: 5000, + enableHighAccuracy: true, + }); + + success({ + coords: { + latitude: 37.7749, + longitude: -122.4194, + accuracy: 10, + altitude: null, + altitudeAccuracy: null, + heading: null, + speed: null, + }, + timestamp: Date.now(), + }); + return 0; + }, + ); + }); + + agHelper.ClickButton("Submit"); + agHelper.ValidateToastMessage("Success"); + deployMode.NavigateBacktoEditor(); + }); + }, +); diff --git a/app/client/cypress/e2e/Regression/ClientSide/Widgets/Radio/Radio2_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/Widgets/Radio/Radio2_spec.ts index b01f39c2ac92..70e29026b49b 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Widgets/Radio/Radio2_spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/Widgets/Radio/Radio2_spec.ts @@ -37,8 +37,9 @@ describe( }, ); entityExplorer.DragDropWidgetNVerify(draggableWidgets.RADIO_GROUP); - propPane.EnterJSContext("Options", "{{JSObject1.myFun1()}}"); + propPane.ToggleJSModeByIndex("options", true, 1); + propPane.EnterJSContext("Options", "{{JSObject1.myFun1()}}"); deployMode.DeployApp( locators._widgetInDeployed(draggableWidgets.RADIO_GROUP), ); diff --git a/app/client/cypress/e2e/Regression/ClientSide/Widgets/Sliders/CategorySlider_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/Widgets/Sliders/CategorySlider_spec.ts index 9b7ab1312679..59469c25bd6a 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Widgets/Sliders/CategorySlider_spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/Widgets/Sliders/CategorySlider_spec.ts @@ -107,6 +107,7 @@ describe( }); it("3. Does not crash if an invalid mark option is passed", function () { + propPane.ToggleJSModeByIndex("options", true, 1); propPane.EnterJSContext("Options", "[[]]"); assertHelper.AssertContains( "Oops, Something went wrong.", @@ -176,7 +177,7 @@ describe( it("6. Data section Options tests", () => { propPane.MoveToTab("Content"); - propPane.ToggleJSMode("options", false); + propPane.ToggleJSModeByIndex("options", false, 1); // User should be able to add and delete options agHelper.GetElementLength(propPane._placeholderName).then((len) => { agHelper.GetNClick(propPane._addOptionProperty); @@ -208,7 +209,7 @@ describe( it("7. General section properties tests", () => { // Verify Show marks toggle - propPane.ToggleJSMode("options"); + propPane.ToggleJSModeByIndex("options", true, 1); propPane.UpdatePropertyFieldValue("Options", options); agHelper.AssertContains("md", "be.visible", "p"); propPane.TogglePropertyState("showmarks", "Off"); diff --git a/app/client/cypress/fixtures/ActionSelectorAppNewExported.json b/app/client/cypress/fixtures/ActionSelectorAppNewExported.json new file mode 100644 index 000000000000..7d35d2431e11 --- /dev/null +++ b/app/client/cypress/fixtures/ActionSelectorAppNewExported.json @@ -0,0 +1 @@ +{"artifactJsonType":"APPLICATION","clientSchemaVersion":1.0,"serverSchemaVersion":11.0,"exportedApplication":{"name":"ActionSelectorAppNew (2)","isPublic":false,"pages":[{"id":"Page1","isDefault":true},{"id":"Page2","isDefault":false}],"publishedPages":[{"id":"Page1","isDefault":true},{"id":"Page2","isDefault":false}],"viewMode":false,"appIsExample":false,"unreadCommentThreads":0.0,"clonedFromApplicationId":"6757fbf1747bef33b4a0a9e8","unpublishedApplicationDetail":{"appPositioning":{"type":"FIXED"},"navigationSetting":{},"themeSetting":{"sizing":1.0,"density":1.0,"appMaxWidth":"LARGE"}},"publishedApplicationDetail":{"appPositioning":{"type":"FIXED"},"navigationSetting":{},"themeSetting":{"sizing":1.0,"density":1.0,"appMaxWidth":"LARGE"}},"color":"#FFEBFB","icon":"alien","slug":"actionselectorappnew-2","unpublishedCustomJSLibs":[],"publishedCustomJSLibs":[],"evaluationVersion":2.0,"applicationVersion":2.0,"collapseInvisibleWidgets":true,"isManualUpdate":false,"isCommunityTemplate":false,"deleted":false},"datasourceList":[],"customJSLibList":[],"pageList":[{"unpublishedPage":{"name":"Page1","slug":"page1","layouts":[{"viewMode":false,"dsl":{"widgetName":"MainContainer","backgroundColor":"none","rightColumn":4896.0,"snapColumns":64.0,"detachFromLayout":true,"widgetId":"0","topRow":0.0,"bottomRow":380.0,"containerStyle":"none","snapRows":124.0,"parentRowSpace":1.0,"type":"CANVAS_WIDGET","canExtend":true,"version":90.0,"minHeight":1292.0,"dynamicTriggerPathList":[],"parentColumnSpace":1.0,"dynamicBindingPathList":[],"leftColumn":0.0,"children":[{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":11.0,"widgetName":"Button1","onClick":"{{showModal().catch(() => {\n showAlert('Failure Callback', '');\n});}}","buttonColor":"{{appsmith.theme.colors.primaryColor}}","dynamicPropertyPathList":[],"topRow":7.0,"bottomRow":11.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":25.0,"animateLoading":true,"parentColumnSpace":12.4375,"dynamicTriggerPathList":[{"key":"onClick"}],"leftColumn":9.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"Submit","isDisabled":false,"key":"kcco8g7h4l","rightColumn":25.0,"isDefaultClickDisabled":true,"widgetId":"6pyc3sxek8","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":7.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":9.0,"buttonVariant":"PRIMARY","placement":"CENTER"}]},"layoutOnLoadActions":[],"layoutOnLoadActionErrors":[],"validOnPageLoadActions":true,"id":"Page1","deleted":false,"policies":[],"userPermissions":[]}],"userPermissions":[],"policyMap":{}},"publishedPage":{"name":"Page1","slug":"page1","layouts":[{"viewMode":false,"dsl":{"widgetName":"MainContainer","backgroundColor":"none","rightColumn":4896.0,"snapColumns":64.0,"detachFromLayout":true,"widgetId":"0","topRow":0.0,"bottomRow":380.0,"containerStyle":"none","snapRows":124.0,"parentRowSpace":1.0,"type":"CANVAS_WIDGET","canExtend":true,"version":90.0,"minHeight":1292.0,"dynamicTriggerPathList":[],"parentColumnSpace":1.0,"dynamicBindingPathList":[],"leftColumn":0.0,"children":[{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":11.0,"widgetName":"Button1","onClick":"{{showModal().catch(() => {\n showAlert('Failure Callback', '');\n});}}","buttonColor":"{{appsmith.theme.colors.primaryColor}}","dynamicPropertyPathList":[],"topRow":7.0,"bottomRow":11.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":25.0,"animateLoading":true,"parentColumnSpace":12.4375,"dynamicTriggerPathList":[{"key":"onClick"}],"leftColumn":9.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"Submit","isDisabled":false,"key":"kcco8g7h4l","rightColumn":25.0,"isDefaultClickDisabled":true,"widgetId":"6pyc3sxek8","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":7.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":9.0,"buttonVariant":"PRIMARY","placement":"CENTER"}]},"layoutOnLoadActions":[],"layoutOnLoadActionErrors":[],"validOnPageLoadActions":true,"id":"Page1","deleted":false,"policies":[],"userPermissions":[]}],"userPermissions":[],"policyMap":{}},"gitSyncId":"6757fca9747bef33b4a0a9fa_0a866ce4-b725-4867-b5cc-c721ff1671b1","deleted":false},{"unpublishedPage":{"name":"Page2","slug":"page2","layouts":[{"viewMode":false,"dsl":{"widgetName":"MainContainer","backgroundColor":"none","rightColumn":1224.0,"snapColumns":64.0,"detachFromLayout":true,"widgetId":"0","topRow":0.0,"bottomRow":380.0,"containerStyle":"none","snapRows":103.0,"parentRowSpace":1.0,"type":"CANVAS_WIDGET","canExtend":true,"version":90.0,"minHeight":1050.0,"parentColumnSpace":1.0,"dynamicBindingPathList":[],"leftColumn":0.0,"children":[{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":17.0,"widgetName":"Button1","onClick":"{{showAlert('main alert', '').then(() => {\n showAlert('success alert', 'success');\n});}}","buttonColor":"{{appsmith.theme.colors.primaryColor}}","dynamicPropertyPathList":[],"topRow":1.0,"bottomRow":5.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":28.0,"animateLoading":true,"parentColumnSpace":13.0625,"dynamicTriggerPathList":[{"key":"onClick"}],"leftColumn":12.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"Submit","isDisabled":false,"key":"06wp4fr6dl","rightColumn":28.0,"isDefaultClickDisabled":true,"widgetId":"kcjwx0c5mv","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":13.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":12.0,"buttonVariant":"PRIMARY","placement":"CENTER"}]},"layoutOnLoadActions":[],"layoutOnLoadActionErrors":[],"validOnPageLoadActions":true,"id":"Page2","deleted":false,"policies":[],"userPermissions":[]}],"userPermissions":[],"policyMap":{}},"publishedPage":{"name":"Page2","slug":"page2","layouts":[{"viewMode":false,"dsl":{"widgetName":"MainContainer","backgroundColor":"none","rightColumn":1224.0,"snapColumns":64.0,"detachFromLayout":true,"widgetId":"0","topRow":0.0,"bottomRow":380.0,"containerStyle":"none","snapRows":103.0,"parentRowSpace":1.0,"type":"CANVAS_WIDGET","canExtend":true,"version":90.0,"minHeight":1050.0,"parentColumnSpace":1.0,"dynamicBindingPathList":[],"leftColumn":0.0,"children":[{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":17.0,"widgetName":"Button1","onClick":"{{showAlert('main alert', '').then(() => {\n showAlert('success alert', 'success');\n});}}","buttonColor":"{{appsmith.theme.colors.primaryColor}}","dynamicPropertyPathList":[],"topRow":1.0,"bottomRow":5.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":28.0,"animateLoading":true,"parentColumnSpace":13.0625,"dynamicTriggerPathList":[{"key":"onClick"}],"leftColumn":12.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"Submit","isDisabled":false,"key":"06wp4fr6dl","rightColumn":28.0,"isDefaultClickDisabled":true,"widgetId":"kcjwx0c5mv","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":13.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":12.0,"buttonVariant":"PRIMARY","placement":"CENTER"}]},"layoutOnLoadActions":[],"layoutOnLoadActionErrors":[],"validOnPageLoadActions":true,"id":"Page2","deleted":false,"policies":[],"userPermissions":[]}],"userPermissions":[],"policyMap":{}},"gitSyncId":"6757fca9747bef33b4a0a9fa_d339d325-80e3-4ab3-a1b3-a202017a5499","deleted":false}],"actionList":[],"actionCollectionList":[],"editModeTheme":{"name":"Default-New","displayName":"Modern","isSystemTheme":true,"deleted":false},"publishedTheme":{"name":"Default-New","displayName":"Modern","isSystemTheme":true,"deleted":false}} \ No newline at end of file diff --git a/app/client/cypress/fixtures/PartialImportExport/frameworkFunPartialPage.json b/app/client/cypress/fixtures/PartialImportExport/frameworkFunPartialPage.json new file mode 100644 index 000000000000..993d2091dc3f --- /dev/null +++ b/app/client/cypress/fixtures/PartialImportExport/frameworkFunPartialPage.json @@ -0,0 +1 @@ +{"artifactJsonType":"APPLICATION","clientSchemaVersion":1,"serverSchemaVersion":11,"widgets":"{\"layoutSystemType\":\"FIXED\",\"widgets\":[{\"hierarchy\":4,\"list\":[{\"isVisible\":true,\"type\":\"BUTTON_WIDGET\",\"animateLoading\":true,\"text\":\"Submit\",\"buttonVariant\":\"PRIMARY\",\"placement\":\"CENTER\",\"widgetName\":\"Button1\",\"isDisabled\":false,\"isDefaultClickDisabled\":true,\"disabledWhenInvalid\":false,\"resetFormOnClick\":false,\"recaptchaType\":\"V3\",\"version\":1,\"responsiveBehavior\":\"hug\",\"minWidth\":120,\"key\":\"06wp4fr6dl\",\"needsErrorInfo\":false,\"widgetId\":\"5zzrhqzs88\",\"renderMode\":\"CANVAS\",\"buttonColor\":\"{{appsmith.theme.colors.primaryColor}}\",\"borderRadius\":\"{{appsmith.theme.borderRadius.appBorderRadius}}\",\"boxShadow\":\"none\",\"isLoading\":false,\"parentColumnSpace\":13.0625,\"parentRowSpace\":10,\"leftColumn\":12,\"rightColumn\":28,\"topRow\":13,\"bottomRow\":17,\"mobileLeftColumn\":12,\"mobileRightColumn\":28,\"mobileTopRow\":13,\"mobileBottomRow\":17,\"parentId\":\"0\",\"dynamicBindingPathList\":[{\"key\":\"buttonColor\"},{\"key\":\"borderRadius\"}],\"onClick\":\"{{showAlert('main alert', '').then(() => {\\n showAlert('success alert', 'success');\\n});}}\",\"dynamicPropertyPathList\":[],\"dynamicTriggerPathList\":[{\"key\":\"onClick\"}]}],\"parentId\":\"0\",\"widgetId\":\"5zzrhqzs88\",\"widgetPositionInfo\":null}],\"flexLayers\":[]}"} \ No newline at end of file diff --git a/app/client/cypress/fixtures/clearIntervalApp.json b/app/client/cypress/fixtures/clearIntervalApp.json new file mode 100644 index 000000000000..2d1e4b7adeba --- /dev/null +++ b/app/client/cypress/fixtures/clearIntervalApp.json @@ -0,0 +1 @@ +{"artifactJsonType":"APPLICATION","clientSchemaVersion":1.0,"serverSchemaVersion":11.0,"exportedApplication":{"name":"Untitled application 2","isPublic":false,"pages":[{"id":"Page1","isDefault":true}],"publishedPages":[{"id":"Page1","isDefault":true}],"viewMode":false,"appIsExample":false,"unreadCommentThreads":0.0,"unpublishedApplicationDetail":{"appPositioning":{"type":"FIXED"},"navigationSetting":{},"themeSetting":{"sizing":1.0,"density":1.0,"appMaxWidth":"LARGE"}},"publishedApplicationDetail":{"appPositioning":{"type":"FIXED"},"navigationSetting":{},"themeSetting":{"sizing":1.0,"density":1.0,"appMaxWidth":"LARGE"}},"color":"#FFEFDB","icon":"shop","slug":"untitled-application-2","unpublishedCustomJSLibs":[],"publishedCustomJSLibs":[],"evaluationVersion":2.0,"applicationVersion":2.0,"collapseInvisibleWidgets":true,"isManualUpdate":false,"deleted":false},"datasourceList":[],"customJSLibList":[],"pageList":[{"unpublishedPage":{"name":"Page1","slug":"page1","layouts":[{"viewMode":false,"dsl":{"widgetName":"MainContainer","backgroundColor":"none","rightColumn":4896.0,"snapColumns":64.0,"detachFromLayout":true,"widgetId":"0","topRow":0.0,"bottomRow":380.0,"containerStyle":"none","snapRows":124.0,"parentRowSpace":1.0,"type":"CANVAS_WIDGET","canExtend":true,"version":90.0,"minHeight":1292.0,"dynamicTriggerPathList":[],"parentColumnSpace":1.0,"dynamicBindingPathList":[],"leftColumn":0.0,"children":[{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":15.0,"widgetName":"Submit1_1","onClick":"{{clearInterval('setIntvl');}}","buttonColor":"{{appsmith.theme.colors.primaryColor}}","dynamicPropertyPathList":[{"key":"onClick"}],"topRow":13.0,"bottomRow":17.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":20.0,"animateLoading":true,"parentColumnSpace":13.0625,"dynamicTriggerPathList":[{"key":"onClick"}],"leftColumn":4.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"Submit1_1","isDisabled":false,"key":"gnjuy982el","rightColumn":20.0,"isDefaultClickDisabled":true,"widgetId":"6lqrwf8bc5","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":11.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":4.0,"buttonVariant":"PRIMARY","placement":"CENTER"},{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":14.0,"widgetName":"Submit1_2","onClick":"{{JSObject1.myFun1()}}","buttonColor":"{{appsmith.theme.colors.primaryColor}}","dynamicPropertyPathList":[{"key":"onClick"}],"topRow":13.0,"bottomRow":17.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":42.0,"animateLoading":true,"parentColumnSpace":13.0625,"dynamicTriggerPathList":[{"key":"onClick"}],"leftColumn":26.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"Submit1_2","isDisabled":false,"key":"gnjuy982el","rightColumn":42.0,"isDefaultClickDisabled":true,"widgetId":"0o2itc3v54","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":10.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":26.0,"buttonVariant":"PRIMARY","placement":"CENTER"},{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":8.0,"widgetName":"setIntvl","onClick":"{{setInterval(() => { \n showAlert(\"Interval started.\", \"info\");\n}, 5000, 'setIntvl');}}","buttonColor":"{{appsmith.theme.colors.primaryColor}}","dynamicPropertyPathList":[{"key":"onClick"}],"topRow":4.0,"bottomRow":8.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":30.0,"animateLoading":true,"parentColumnSpace":13.0625,"dynamicTriggerPathList":[{"key":"onClick"}],"leftColumn":4.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"setIntvl","isDisabled":false,"key":"gnjuy982el","rightColumn":20.0,"isDefaultClickDisabled":true,"widgetId":"crd9lxw3ni","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":4.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":14.0,"buttonVariant":"PRIMARY","placement":"CENTER"},{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":8.0,"widgetName":"setMulIntrvl","onClick":"{{ \n setInterval(() => { \n showAlert(\"Interval 1\", \"info\");\n }, 5000, 'setIntvl1'); \n\n setInterval(() => { \n showAlert(\"Interval 2\", \"info\");\n }, 5000, 'setIntvl2'); \n}}","buttonColor":"{{appsmith.theme.colors.primaryColor}}","dynamicPropertyPathList":[{"key":"onClick"}],"topRow":4.0,"bottomRow":8.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":30.0,"animateLoading":true,"parentColumnSpace":13.0625,"dynamicTriggerPathList":[{"key":"onClick"}],"leftColumn":26.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"setMulIntrvl","isDisabled":false,"key":"gnjuy982el","rightColumn":42.0,"isDefaultClickDisabled":true,"widgetId":"ly3iyui2ky","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":4.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":14.0,"buttonVariant":"PRIMARY","placement":"CENTER"},{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":21.0,"widgetName":"Submit2_1","onClick":"{{clearInterval('nonExit');}}","buttonColor":"{{appsmith.theme.colors.primaryColor}}","dynamicPropertyPathList":[{"key":"onClick"}],"topRow":18.0,"bottomRow":22.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":20.0,"animateLoading":true,"parentColumnSpace":13.0625,"dynamicTriggerPathList":[{"key":"onClick"}],"leftColumn":4.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"Submit2_1","isDisabled":false,"key":"gnjuy982el","rightColumn":20.0,"isDefaultClickDisabled":true,"widgetId":"w29uc8a4r1","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":17.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":4.0,"buttonVariant":"PRIMARY","placement":"CENTER"},{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":21.0,"widgetName":"Submit2_2","onClick":"{{JSObject2.myFun1()}}","buttonColor":"{{appsmith.theme.colors.primaryColor}}","dynamicPropertyPathList":[{"key":"onClick"}],"topRow":18.0,"bottomRow":22.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":20.0,"animateLoading":true,"parentColumnSpace":13.0625,"dynamicTriggerPathList":[{"key":"onClick"}],"leftColumn":26.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"Submit2_2","isDisabled":false,"key":"gnjuy982el","rightColumn":42.0,"isDefaultClickDisabled":true,"widgetId":"eqrcfq2942","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":17.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":4.0,"buttonVariant":"PRIMARY","placement":"CENTER"},{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":27.0,"widgetName":"Submit3_1","onClick":"{{clearInterval(123);}}","buttonColor":"{{appsmith.theme.colors.primaryColor}}","dynamicPropertyPathList":[{"key":"onClick"}],"topRow":23.0,"bottomRow":27.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":20.0,"animateLoading":true,"parentColumnSpace":13.0625,"dynamicTriggerPathList":[{"key":"onClick"}],"leftColumn":4.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"Submit3_1","isDisabled":false,"key":"gnjuy982el","rightColumn":20.0,"isDefaultClickDisabled":true,"widgetId":"w87utw65es","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":23.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":4.0,"buttonVariant":"PRIMARY","placement":"CENTER"},{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":27.0,"widgetName":"Submit3_2","onClick":"{{JSObject3.myFun1()}}","buttonColor":"{{appsmith.theme.colors.primaryColor}}","dynamicPropertyPathList":[{"key":"onClick"}],"topRow":23.0,"bottomRow":27.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":20.0,"animateLoading":true,"parentColumnSpace":13.0625,"dynamicTriggerPathList":[{"key":"onClick"}],"leftColumn":26.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"Submit3_2","isDisabled":false,"key":"gnjuy982el","rightColumn":42.0,"isDefaultClickDisabled":true,"widgetId":"zbb2qf4oh9","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":23.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":4.0,"buttonVariant":"PRIMARY","placement":"CENTER"},{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":33.0,"widgetName":"Submit4_1","onClick":"{{ \n clearInterval('setIntvl1'); \n clearInterval('setIntvl2'); \n}}","buttonColor":"{{appsmith.theme.colors.primaryColor}}","dynamicPropertyPathList":[{"key":"onClick"}],"topRow":28.0,"bottomRow":32.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":20.0,"animateLoading":true,"parentColumnSpace":13.0625,"dynamicTriggerPathList":[{"key":"onClick"}],"leftColumn":4.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"Submit4_1","isDisabled":false,"key":"gnjuy982el","rightColumn":20.0,"isDefaultClickDisabled":true,"widgetId":"csd7das6oq","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":29.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":4.0,"buttonVariant":"PRIMARY","placement":"CENTER"},{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":33.0,"widgetName":"Submit4_2","onClick":"{{JSObject4.myFun1()}}","buttonColor":"{{appsmith.theme.colors.primaryColor}}","dynamicPropertyPathList":[{"key":"onClick"}],"topRow":28.0,"bottomRow":32.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":20.0,"animateLoading":true,"parentColumnSpace":13.0625,"dynamicTriggerPathList":[{"key":"onClick"}],"leftColumn":26.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"Submit4_2","isDisabled":false,"key":"gnjuy982el","rightColumn":42.0,"isDefaultClickDisabled":true,"widgetId":"3m9kn08zn6","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":29.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":4.0,"buttonVariant":"PRIMARY","placement":"CENTER"},{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":38.0,"widgetName":"Submit6_1","onClick":"{{clearInterval(); }}","buttonColor":"{{appsmith.theme.colors.primaryColor}}","dynamicPropertyPathList":[{"key":"onClick"}],"topRow":34.0,"bottomRow":38.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":20.0,"animateLoading":true,"parentColumnSpace":13.0625,"dynamicTriggerPathList":[{"key":"onClick"}],"leftColumn":4.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"Submit6_1","isDisabled":false,"key":"gnjuy982el","rightColumn":20.0,"isDefaultClickDisabled":true,"widgetId":"gnkizbkfgg","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":34.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":4.0,"buttonVariant":"PRIMARY","placement":"CENTER"},{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":38.0,"widgetName":"Submit6_2","buttonColor":"{{appsmith.theme.colors.primaryColor}}","topRow":34.0,"bottomRow":38.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":20.0,"animateLoading":true,"parentColumnSpace":13.0625,"dynamicTriggerPathList":[],"leftColumn":26.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"Submit6_2","isDisabled":false,"key":"gnjuy982el","rightColumn":42.0,"isDefaultClickDisabled":true,"widgetId":"q6ss3o2l74","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":34.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":4.0,"buttonVariant":"PRIMARY","placement":"CENTER"},{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":8.0,"widgetName":"clearAllInterval","onClick":"{{ \n clearInterval('setIntvl1'); \n clearInterval('setIntvl2');\n\tclearInterval('setIntvl');\n}}","buttonColor":"{{appsmith.theme.colors.primaryColor}}","dynamicPropertyPathList":[{"key":"onClick"}],"topRow":4.0,"bottomRow":8.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":61.0,"animateLoading":true,"parentColumnSpace":13.0625,"dynamicTriggerPathList":[{"key":"onClick"}],"leftColumn":45.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"clearAllInterval","isDisabled":false,"key":"gnjuy982el","rightColumn":61.0,"isDefaultClickDisabled":true,"widgetId":"njpwn3ucdb","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":4.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":45.0,"buttonVariant":"PRIMARY","placement":"CENTER"}]},"layoutOnLoadActions":[],"layoutOnLoadActionErrors":[],"validOnPageLoadActions":true,"id":"Page1","deleted":false,"policies":[],"userPermissions":[]}],"userPermissions":[],"policyMap":{}},"publishedPage":{"name":"Page1","slug":"page1","layouts":[{"viewMode":false,"dsl":{"widgetName":"MainContainer","backgroundColor":"none","rightColumn":1224.0,"snapColumns":16.0,"detachFromLayout":true,"widgetId":"0","topRow":0.0,"bottomRow":1250.0,"containerStyle":"none","snapRows":33.0,"parentRowSpace":1.0,"type":"CANVAS_WIDGET","canExtend":true,"version":4.0,"minHeight":1292.0,"dynamicTriggerPathList":[],"parentColumnSpace":1.0,"dynamicBindingPathList":[],"leftColumn":0.0,"children":[]},"validOnPageLoadActions":true,"id":"Page1","deleted":false,"policies":[],"userPermissions":[]}],"userPermissions":[],"policyMap":{}},"gitSyncId":"674e894855991c29a2fde4cb_f4b7407e-c4df-46b1-a5d4-0d66672cd442","deleted":false}],"actionList":[{"pluginType":"JS","pluginId":"js-plugin","unpublishedAction":{"name":"myFun1","fullyQualifiedName":"JSObject1.myFun1","datasource":{"name":"UNUSED_DATASOURCE","pluginId":"js-plugin","messages":[],"isAutoGenerated":false,"deleted":false,"policyMap":{},"policies":[],"userPermissions":[]},"pageId":"Page1","collectionId":"Page1_JSObject1","actionConfiguration":{"timeoutInMillisecond":10000.0,"paginationType":"NONE","encodeParamsToggle":true,"body":"function () {\n {\n {\n clearInterval('setIntvl');\n }\n }\n}","selfReferencingDataPaths":[],"jsArguments":[]},"executeOnLoad":false,"dynamicBindingPathList":[{"key":"body"}],"isValid":true,"invalids":[],"messages":[],"jsonPathKeys":["function () {\n {\n {\n clearInterval('setIntvl');\n }\n }\n}"],"userSetOnLoad":false,"confirmBeforeExecute":false,"policyMap":{},"userPermissions":[],"createdAt":"2024-12-03T04:36:13Z"},"publishedAction":{"datasource":{"messages":[],"isAutoGenerated":false,"deleted":false,"policyMap":{},"policies":[],"userPermissions":[]},"messages":[],"userSetOnLoad":false,"confirmBeforeExecute":false,"policyMap":{},"userPermissions":[],"createdAt":"2024-12-03T04:36:13Z"},"gitSyncId":"674e894855991c29a2fde4cb_9cc5f7ae-1e6c-4234-ad47-3edeaeaf6dd1","id":"Page1_JSObject1.myFun1","deleted":false},{"pluginType":"JS","pluginId":"js-plugin","unpublishedAction":{"name":"myFun1","fullyQualifiedName":"JSObject2.myFun1","datasource":{"name":"UNUSED_DATASOURCE","pluginId":"js-plugin","messages":[],"isAutoGenerated":false,"deleted":false,"policyMap":{},"policies":[],"userPermissions":[]},"pageId":"Page1","collectionId":"Page1_JSObject2","actionConfiguration":{"timeoutInMillisecond":10000.0,"paginationType":"NONE","encodeParamsToggle":true,"body":"function () {\n {\n {\n clearInterval('nonExit');\n }\n }\n}","selfReferencingDataPaths":[],"jsArguments":[]},"executeOnLoad":false,"clientSideExecution":true,"dynamicBindingPathList":[{"key":"body"}],"isValid":true,"invalids":[],"messages":[],"jsonPathKeys":["function () {\n {\n {\n clearInterval('nonExit');\n }\n }\n}"],"userSetOnLoad":false,"confirmBeforeExecute":false,"policyMap":{},"userPermissions":[],"createdAt":"2024-12-03T04:38:51Z"},"publishedAction":{"datasource":{"messages":[],"isAutoGenerated":false,"deleted":false,"policyMap":{},"policies":[],"userPermissions":[]},"messages":[],"userSetOnLoad":false,"confirmBeforeExecute":false,"policyMap":{},"userPermissions":[],"createdAt":"2024-12-03T04:38:51Z"},"gitSyncId":"674e894855991c29a2fde4cb_7ac73939-4113-44eb-b995-7a8d5661b7b3","id":"Page1_JSObject2.myFun1","deleted":false},{"pluginType":"JS","pluginId":"js-plugin","unpublishedAction":{"name":"myFun1","fullyQualifiedName":"JSObject3.myFun1","datasource":{"name":"UNUSED_DATASOURCE","pluginId":"js-plugin","messages":[],"isAutoGenerated":false,"deleted":false,"policyMap":{},"policies":[],"userPermissions":[]},"pageId":"Page1","collectionId":"Page1_JSObject3","actionConfiguration":{"timeoutInMillisecond":10000.0,"paginationType":"NONE","encodeParamsToggle":true,"body":"function () {\n {\n {\n clearInterval(123);\n }\n }\n}","selfReferencingDataPaths":[],"jsArguments":[]},"executeOnLoad":false,"clientSideExecution":true,"dynamicBindingPathList":[{"key":"body"}],"isValid":true,"invalids":[],"messages":[],"jsonPathKeys":["function () {\n {\n {\n clearInterval(123);\n }\n }\n}"],"userSetOnLoad":false,"confirmBeforeExecute":false,"policyMap":{},"userPermissions":[],"createdAt":"2024-12-03T04:41:16Z"},"publishedAction":{"datasource":{"messages":[],"isAutoGenerated":false,"deleted":false,"policyMap":{},"policies":[],"userPermissions":[]},"messages":[],"userSetOnLoad":false,"confirmBeforeExecute":false,"policyMap":{},"userPermissions":[],"createdAt":"2024-12-03T04:41:16Z"},"gitSyncId":"674e894855991c29a2fde4cb_e03eb3d2-c68d-40d3-86db-b0a08ec1cdd3","id":"Page1_JSObject3.myFun1","deleted":false},{"pluginType":"JS","pluginId":"js-plugin","unpublishedAction":{"name":"myFun1","fullyQualifiedName":"JSObject4.myFun1","datasource":{"name":"UNUSED_DATASOURCE","pluginId":"js-plugin","messages":[],"isAutoGenerated":false,"deleted":false,"policyMap":{},"policies":[],"userPermissions":[]},"pageId":"Page1","collectionId":"Page1_JSObject4","actionConfiguration":{"timeoutInMillisecond":10000.0,"paginationType":"NONE","encodeParamsToggle":true,"body":"function () {\n {\n {\n clearInterval('setIntvl1');\n clearInterval('setIntvl2');\n }\n }\n}","selfReferencingDataPaths":[],"jsArguments":[]},"executeOnLoad":false,"clientSideExecution":true,"dynamicBindingPathList":[{"key":"body"}],"isValid":true,"invalids":[],"messages":[],"jsonPathKeys":["function () {\n {\n {\n clearInterval('setIntvl1');\n clearInterval('setIntvl2');\n }\n }\n}"],"userSetOnLoad":false,"confirmBeforeExecute":false,"policyMap":{},"userPermissions":[],"createdAt":"2024-12-03T04:58:59Z"},"publishedAction":{"datasource":{"messages":[],"isAutoGenerated":false,"deleted":false,"policyMap":{},"policies":[],"userPermissions":[]},"messages":[],"userSetOnLoad":false,"confirmBeforeExecute":false,"policyMap":{},"userPermissions":[],"createdAt":"2024-12-03T04:58:59Z"},"gitSyncId":"674e894855991c29a2fde4cb_2e371e33-8fa3-43d9-a6a0-5d51788e9c7a","id":"Page1_JSObject4.myFun1","deleted":false},{"pluginType":"JS","pluginId":"js-plugin","unpublishedAction":{"name":"myFun1","fullyQualifiedName":"JSObject6.myFun1","datasource":{"name":"UNUSED_DATASOURCE","pluginId":"js-plugin","messages":[],"isAutoGenerated":false,"deleted":false,"policyMap":{},"policies":[],"userPermissions":[]},"pageId":"Page1","collectionId":"Page1_JSObject6","actionConfiguration":{"timeoutInMillisecond":10000.0,"paginationType":"NONE","encodeParamsToggle":true,"body":"function () {\n {\n {\n clearInterval();\n }\n }\n}","selfReferencingDataPaths":[],"jsArguments":[]},"executeOnLoad":false,"clientSideExecution":true,"dynamicBindingPathList":[{"key":"body"}],"isValid":true,"invalids":[],"messages":[],"jsonPathKeys":["function () {\n {\n {\n clearInterval();\n }\n }\n}"],"userSetOnLoad":false,"confirmBeforeExecute":false,"policyMap":{},"userPermissions":[],"createdAt":"2024-12-03T05:01:53Z"},"publishedAction":{"datasource":{"messages":[],"isAutoGenerated":false,"deleted":false,"policyMap":{},"policies":[],"userPermissions":[]},"messages":[],"userSetOnLoad":false,"confirmBeforeExecute":false,"policyMap":{},"userPermissions":[],"createdAt":"2024-12-03T05:01:53Z"},"gitSyncId":"674e894855991c29a2fde4cb_ced20a12-b4ec-4302-8f39-13bb61ce6243","id":"Page1_JSObject6.myFun1","deleted":false}],"actionCollectionList":[{"unpublishedCollection":{"name":"JSObject1","pageId":"Page1","pluginId":"js-plugin","pluginType":"JS","actions":[],"archivedActions":[],"body":"export default {\n\tmyFun1() {\n\t\t{{clearInterval('setIntvl');}}\n\t},\n};","variables":[],"userPermissions":[]},"gitSyncId":"674e894855991c29a2fde4cb_27978052-a32f-4afb-a67f-f1440e13cfef","id":"Page1_JSObject1","deleted":false},{"unpublishedCollection":{"name":"JSObject2","pageId":"Page1","pluginId":"js-plugin","pluginType":"JS","actions":[],"archivedActions":[],"body":"export default {\n\tmyFun1() {\n\t\t{{clearInterval('nonExit');}}\n\t},\n};","variables":[],"userPermissions":[]},"gitSyncId":"674e894855991c29a2fde4cb_e51c2b48-e9c6-48ab-9783-b2c7fd9dfae8","id":"Page1_JSObject2","deleted":false},{"unpublishedCollection":{"name":"JSObject3","pageId":"Page1","pluginId":"js-plugin","pluginType":"JS","actions":[],"archivedActions":[],"body":"export default {\n\tmyFun1() {\n\t\t{{clearInterval(123);}}\n\t},\n};","variables":[],"userPermissions":[]},"gitSyncId":"674e894855991c29a2fde4cb_d3ad93b8-df05-4afa-958f-bccb820c84b6","id":"Page1_JSObject3","deleted":false},{"unpublishedCollection":{"name":"JSObject4","pageId":"Page1","pluginId":"js-plugin","pluginType":"JS","actions":[],"archivedActions":[],"body":"export default {\n\tmyFun1() {\n\t\t{{ \n\t\t\tclearInterval('setIntvl1'); \n\t\t\tclearInterval('setIntvl2'); \n\t\t}}\n\t},\n};\n\n","variables":[],"userPermissions":[]},"gitSyncId":"674e894855991c29a2fde4cb_b67816f8-de30-4a87-a034-73f1bbd63fb3","id":"Page1_JSObject4","deleted":false},{"unpublishedCollection":{"name":"JSObject6","pageId":"Page1","pluginId":"js-plugin","pluginType":"JS","actions":[],"archivedActions":[],"body":"export default {\n\tmyFun1() {\n\t\t{{clearInterval(); }}\n\t},\n};\n\n","variables":[],"userPermissions":[]},"gitSyncId":"674e894855991c29a2fde4cb_3a92e6bc-b3e9-4310-aaef-6b34d58d23b1","id":"Page1_JSObject6","deleted":false}],"editModeTheme":{"name":"Default-New","displayName":"Modern","isSystemTheme":true,"deleted":false},"publishedTheme":{"name":"Default-New","displayName":"Modern","isSystemTheme":true,"deleted":false}} \ No newline at end of file diff --git a/app/client/cypress/fixtures/setIntervalApp.json b/app/client/cypress/fixtures/setIntervalApp.json new file mode 100644 index 000000000000..db70418ab494 --- /dev/null +++ b/app/client/cypress/fixtures/setIntervalApp.json @@ -0,0 +1 @@ +{"artifactJsonType":"APPLICATION","clientSchemaVersion":1.0,"serverSchemaVersion":11.0,"exportedApplication":{"name":"setIntervalApp","isPublic":false,"pages":[{"id":"Page1","isDefault":true}],"publishedPages":[{"id":"Page1","isDefault":true}],"viewMode":false,"appIsExample":false,"unreadCommentThreads":0.0,"unpublishedApplicationDetail":{"appPositioning":{"type":"FIXED"},"navigationSetting":{},"themeSetting":{"sizing":1.0,"density":1.0,"appMaxWidth":"LARGE"}},"publishedApplicationDetail":{"appPositioning":{"type":"FIXED"},"navigationSetting":{},"themeSetting":{"sizing":1.0,"density":1.0,"appMaxWidth":"LARGE"}},"color":"#C7F3E3","icon":"pie-chart","slug":"setintervalapp","unpublishedCustomJSLibs":[],"publishedCustomJSLibs":[],"evaluationVersion":2.0,"applicationVersion":2.0,"collapseInvisibleWidgets":true,"isManualUpdate":false,"deleted":false},"datasourceList":[],"customJSLibList":[],"pageList":[{"unpublishedPage":{"name":"Page1","slug":"page1","layouts":[{"viewMode":false,"dsl":{"widgetName":"MainContainer","backgroundColor":"none","rightColumn":4896.0,"snapColumns":64.0,"detachFromLayout":true,"widgetId":"0","topRow":0.0,"bottomRow":470.0,"containerStyle":"none","snapRows":124.0,"parentRowSpace":1.0,"type":"CANVAS_WIDGET","canExtend":true,"version":90.0,"minHeight":1292.0,"dynamicTriggerPathList":[],"parentColumnSpace":1.0,"dynamicBindingPathList":[],"leftColumn":0.0,"children":[{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":13.0,"widgetName":"Submit1_1","onClick":"{{setInterval(() => { Api1.run();}, 5000, 'myInterval');}}","buttonColor":"{{appsmith.theme.colors.primaryColor}}","dynamicPropertyPathList":[{"key":"onClick"}],"topRow":13.0,"bottomRow":17.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":26.0,"animateLoading":true,"parentColumnSpace":13.0625,"dynamicTriggerPathList":[{"key":"onClick"}],"leftColumn":9.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"Submit1_1","isDisabled":false,"key":"nralwhect9","rightColumn":25.0,"isDefaultClickDisabled":true,"widgetId":"30pcv6i9zq","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":9.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":10.0,"buttonVariant":"PRIMARY","placement":"CENTER"},{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":24.0,"widgetName":"Submit1_2","onClick":"{{JSObject1.myFun1()}}","buttonColor":"{{appsmith.theme.colors.primaryColor}}","dynamicPropertyPathList":[{"key":"onClick"}],"topRow":13.0,"bottomRow":17.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":25.0,"animateLoading":true,"parentColumnSpace":13.0625,"dynamicTriggerPathList":[{"key":"onClick"}],"leftColumn":28.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"Submit1_2","isDisabled":false,"key":"nralwhect9","rightColumn":44.0,"isDefaultClickDisabled":true,"widgetId":"5dmjgaqauo","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":20.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":9.0,"buttonVariant":"PRIMARY","placement":"CENTER"},{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":32.0,"widgetName":"Submit2_1","onClick":"{{setInterval(() => {\n Api1.run();\n}, 5000, 'interval1');\nsetInterval(() => {\n Api2.run();\n}, 5000, 'interval2');}}","buttonColor":"{{appsmith.theme.colors.primaryColor}}","dynamicPropertyPathList":[{"key":"onClick"}],"topRow":22.0,"bottomRow":26.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":25.0,"animateLoading":true,"parentColumnSpace":13.0625,"dynamicTriggerPathList":[{"key":"onClick"}],"leftColumn":9.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"Submit2_1","isDisabled":false,"key":"nralwhect9","rightColumn":25.0,"isDefaultClickDisabled":true,"widgetId":"slmn11a8b5","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":28.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":9.0,"buttonVariant":"PRIMARY","placement":"CENTER"},{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":32.0,"widgetName":"Submit3_1","onClick":"setInterval(() => {\n\t\t\t\ttestInvalid();\n\t\t}, 2000, \"testingFun\");","buttonColor":"{{appsmith.theme.colors.primaryColor}}","dynamicPropertyPathList":[{"key":"onClick"}],"topRow":30.0,"bottomRow":34.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":25.0,"animateLoading":true,"parentColumnSpace":13.0625,"dynamicTriggerPathList":[{"key":"onClick"}],"leftColumn":9.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"Submit3_1","isDisabled":false,"key":"nralwhect9","rightColumn":25.0,"isDefaultClickDisabled":true,"widgetId":"t0fen8486b","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":28.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":9.0,"buttonVariant":"PRIMARY","placement":"CENTER"},{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":32.0,"widgetName":"Submit4_1","onClick":"{{setInterval(() => {\n Api1.run();\n}, 0, 'interval4');}}","buttonColor":"{{appsmith.theme.colors.primaryColor}}","dynamicPropertyPathList":[],"topRow":37.0,"bottomRow":41.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":25.0,"animateLoading":true,"parentColumnSpace":13.0625,"dynamicTriggerPathList":[{"key":"onClick"}],"leftColumn":9.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"Submit4_1","isDisabled":false,"key":"nralwhect9","rightColumn":25.0,"isDefaultClickDisabled":true,"widgetId":"80kl08cwxg","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":28.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":9.0,"buttonVariant":"PRIMARY","placement":"CENTER"},{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":32.0,"widgetName":"Submit3_2","onClick":"{{JSObject3.myFun1()}}","buttonColor":"{{appsmith.theme.colors.primaryColor}}","dynamicPropertyPathList":[{"key":"onClick"}],"topRow":30.0,"bottomRow":34.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":25.0,"animateLoading":true,"parentColumnSpace":13.0625,"dynamicTriggerPathList":[{"key":"onClick"}],"leftColumn":28.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"Submit3_2","isDisabled":false,"key":"nralwhect9","rightColumn":44.0,"isDefaultClickDisabled":true,"widgetId":"kd9ao1c9de","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":28.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":9.0,"buttonVariant":"PRIMARY","placement":"CENTER"},{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":32.0,"widgetName":"Submit4_2","onClick":"{{JSObject4.myFun1()}}","buttonColor":"{{appsmith.theme.colors.primaryColor}}","dynamicPropertyPathList":[{"key":"onClick"}],"topRow":37.0,"bottomRow":41.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":25.0,"animateLoading":true,"parentColumnSpace":13.0625,"dynamicTriggerPathList":[{"key":"onClick"}],"leftColumn":28.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"Submit4_2","isDisabled":false,"key":"nralwhect9","rightColumn":44.0,"isDefaultClickDisabled":true,"widgetId":"xi8n1covr5","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":28.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":9.0,"buttonVariant":"PRIMARY","placement":"CENTER"},{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":40.0,"widgetName":"Submit2_2","onClick":"{{JSObject2.myFun1()}}","buttonColor":"{{appsmith.theme.colors.primaryColor}}","dynamicPropertyPathList":[{"key":"onClick"}],"topRow":22.0,"bottomRow":26.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":25.0,"animateLoading":true,"parentColumnSpace":13.0625,"dynamicTriggerPathList":[{"key":"onClick"}],"leftColumn":28.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"Submit2_2","isDisabled":false,"key":"nralwhect9","rightColumn":44.0,"isDefaultClickDisabled":true,"widgetId":"xdg1oyxpkc","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":36.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":9.0,"buttonVariant":"PRIMARY","placement":"CENTER"},{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":47.0,"widgetName":"Submit5_1","onClick":"{{setInterval(() => { Api1.run();}, 5000, 'myInterval');}}","buttonColor":"{{appsmith.theme.colors.primaryColor}}","dynamicPropertyPathList":[{"key":"onClick"}],"topRow":43.0,"bottomRow":47.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":25.0,"animateLoading":true,"parentColumnSpace":13.0625,"dynamicTriggerPathList":[{"key":"onClick"}],"leftColumn":9.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"Submit5_1","isDisabled":false,"key":"ryj6cfbny5","rightColumn":25.0,"isDefaultClickDisabled":true,"widgetId":"33qn3gqqpx","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":43.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":9.0,"buttonVariant":"PRIMARY","placement":"CENTER"},{"resetFormOnClick":false,"needsErrorInfo":false,"boxShadow":"none","mobileBottomRow":47.0,"widgetName":"Submit5_2","onClick":"{{JSObject5.myFun1()}}","buttonColor":"{{appsmith.theme.colors.primaryColor}}","dynamicPropertyPathList":[{"key":"onClick"}],"topRow":43.0,"bottomRow":47.0,"parentRowSpace":10.0,"type":"BUTTON_WIDGET","mobileRightColumn":25.0,"animateLoading":true,"parentColumnSpace":13.0625,"dynamicTriggerPathList":[{"key":"onClick"}],"leftColumn":29.0,"dynamicBindingPathList":[{"key":"buttonColor"},{"key":"borderRadius"}],"text":"Submit5_2","isDisabled":false,"key":"ryj6cfbny5","rightColumn":45.0,"isDefaultClickDisabled":true,"widgetId":"yr9ol12udw","minWidth":120.0,"isVisible":true,"recaptchaType":"V3","version":1.0,"parentId":"0","renderMode":"CANVAS","isLoading":false,"mobileTopRow":43.0,"responsiveBehavior":"hug","disabledWhenInvalid":false,"borderRadius":"{{appsmith.theme.borderRadius.appBorderRadius}}","mobileLeftColumn":9.0,"buttonVariant":"PRIMARY","placement":"CENTER"}]},"layoutOnLoadActions":[],"layoutOnLoadActionErrors":[],"validOnPageLoadActions":true,"id":"Page1","deleted":false,"policies":[],"userPermissions":[]}],"userPermissions":[],"policyMap":{}},"publishedPage":{"name":"Page1","slug":"page1","layouts":[{"viewMode":false,"dsl":{"widgetName":"MainContainer","backgroundColor":"none","rightColumn":1224.0,"snapColumns":16.0,"detachFromLayout":true,"widgetId":"0","topRow":0.0,"bottomRow":1250.0,"containerStyle":"none","snapRows":33.0,"parentRowSpace":1.0,"type":"CANVAS_WIDGET","canExtend":true,"version":4.0,"minHeight":1292.0,"dynamicTriggerPathList":[],"parentColumnSpace":1.0,"dynamicBindingPathList":[],"leftColumn":0.0,"children":[]},"validOnPageLoadActions":true,"id":"Page1","deleted":false,"policies":[],"userPermissions":[]}],"userPermissions":[],"policyMap":{}},"gitSyncId":"674bfbf855991c29a2fddc76_7ff887c3-3c71-45d9-bd59-caada11bfa82","deleted":false}],"actionList":[{"pluginType":"API","pluginId":"restapi-plugin","unpublishedAction":{"name":"Api1","datasource":{"name":"DEFAULT_REST_DATASOURCE","pluginId":"restapi-plugin","datasourceConfiguration":{"url":"http://host.docker.internal:5001"},"invalids":[],"messages":[],"isAutoGenerated":false,"deleted":false,"policyMap":{},"policies":[],"userPermissions":[]},"pageId":"Page1","actionConfiguration":{"timeoutInMillisecond":10000.0,"paginationType":"NONE","path":"/v1/mock-api","headers":[],"autoGeneratedHeaders":[],"encodeParamsToggle":true,"queryParameters":[{"key":"records","value":"10"}],"body":"","bodyFormData":[],"httpMethod":"GET","httpVersion":"HTTP11","selfReferencingDataPaths":[],"pluginSpecifiedTemplates":[{"value":true}],"formData":{"apiContentType":"none"}},"executeOnLoad":false,"dynamicBindingPathList":[],"isValid":true,"invalids":[],"messages":[],"jsonPathKeys":[],"userSetOnLoad":false,"confirmBeforeExecute":false,"policyMap":{},"userPermissions":[],"createdAt":"2024-12-01T06:04:05Z"},"publishedAction":{"datasource":{"messages":[],"isAutoGenerated":false,"deleted":false,"policyMap":{},"policies":[],"userPermissions":[]},"messages":[],"userSetOnLoad":false,"confirmBeforeExecute":false,"policyMap":{},"userPermissions":[],"createdAt":"2024-12-01T06:04:05Z"},"gitSyncId":"674bfbf855991c29a2fddc76_136ab971-6f56-4e60-9907-cab28b5a1a34","id":"Page1_Api1","deleted":false},{"pluginType":"API","pluginId":"restapi-plugin","unpublishedAction":{"name":"Api2","datasource":{"name":"DEFAULT_REST_DATASOURCE","pluginId":"restapi-plugin","datasourceConfiguration":{"url":"http://host.docker.internal:5001"},"invalids":[],"messages":[],"isAutoGenerated":false,"deleted":false,"policyMap":{},"policies":[],"userPermissions":[]},"pageId":"Page1","actionConfiguration":{"timeoutInMillisecond":10000.0,"paginationType":"NONE","path":"/v1/genderize_agify","headers":[],"autoGeneratedHeaders":[],"encodeParamsToggle":true,"queryParameters":[{"key":"name","value":"sagar"}],"body":"","bodyFormData":[],"httpMethod":"GET","httpVersion":"HTTP11","selfReferencingDataPaths":[],"pluginSpecifiedTemplates":[{"value":true}],"formData":{"apiContentType":"none"}},"executeOnLoad":false,"dynamicBindingPathList":[],"isValid":true,"invalids":[],"messages":[],"jsonPathKeys":[],"userSetOnLoad":false,"confirmBeforeExecute":false,"policyMap":{},"userPermissions":[],"createdAt":"2024-12-01T06:04:36Z"},"publishedAction":{"datasource":{"messages":[],"isAutoGenerated":false,"deleted":false,"policyMap":{},"policies":[],"userPermissions":[]},"messages":[],"userSetOnLoad":false,"confirmBeforeExecute":false,"policyMap":{},"userPermissions":[],"createdAt":"2024-12-01T06:04:36Z"},"gitSyncId":"674bfbf855991c29a2fddc76_e373d147-f457-4785-bdb1-5ba234535435","id":"Page1_Api2","deleted":false},{"pluginType":"JS","pluginId":"js-plugin","unpublishedAction":{"name":"myFun1","fullyQualifiedName":"JSObject4.myFun1","datasource":{"name":"UNUSED_DATASOURCE","pluginId":"js-plugin","messages":[],"isAutoGenerated":false,"deleted":false,"policyMap":{},"policies":[],"userPermissions":[]},"pageId":"Page1","collectionId":"Page1_JSObject4","actionConfiguration":{"timeoutInMillisecond":10000.0,"paginationType":"NONE","encodeParamsToggle":true,"body":"function () {\n setInterval(() => {\n console.log(\"This interval will not work properly due to an invalid callback function.\");\n }, dasdas, \"myInterval\");\n}","selfReferencingDataPaths":[],"jsArguments":[]},"executeOnLoad":false,"clientSideExecution":true,"dynamicBindingPathList":[{"key":"body"}],"isValid":true,"invalids":[],"messages":[],"jsonPathKeys":["function () {\n setInterval(() => {\n console.log(\"This interval will not work properly due to an invalid callback function.\");\n }, dasdas, \"myInterval\");\n}"],"userSetOnLoad":false,"confirmBeforeExecute":false,"policyMap":{},"userPermissions":[],"createdAt":"2024-12-01T06:08:15Z"},"publishedAction":{"datasource":{"messages":[],"isAutoGenerated":false,"deleted":false,"policyMap":{},"policies":[],"userPermissions":[]},"messages":[],"userSetOnLoad":false,"confirmBeforeExecute":false,"policyMap":{},"userPermissions":[],"createdAt":"2024-12-01T06:08:15Z"},"gitSyncId":"674bfbf855991c29a2fddc76_b503731a-1d91-401d-a4af-0f2d0f17364f","id":"Page1_JSObject4.myFun1","deleted":false},{"pluginType":"JS","pluginId":"js-plugin","unpublishedAction":{"name":"myFun1","fullyQualifiedName":"JSObject1.myFun1","datasource":{"name":"UNUSED_DATASOURCE","pluginId":"js-plugin","messages":[],"isAutoGenerated":false,"deleted":false,"policyMap":{},"policies":[],"userPermissions":[]},"pageId":"Page1","collectionId":"Page1_JSObject1","actionConfiguration":{"timeoutInMillisecond":10000.0,"paginationType":"NONE","encodeParamsToggle":true,"body":"function () {\n try {\n {\n {\n clearInterval('myInterval');\n }\n }\n ;\n setInterval(() => {\n Api1.run();\n }, 5000, 'myInterval');\n showAlert('Interval started successfully with jsobject.');\n } catch (error) {\n showAlert('Error: ' + error.message);\n }\n}","selfReferencingDataPaths":[],"jsArguments":[]},"executeOnLoad":false,"dynamicBindingPathList":[{"key":"body"}],"isValid":true,"invalids":[],"messages":[],"jsonPathKeys":["function () {\n try {\n {\n {\n clearInterval('myInterval');\n }\n }\n ;\n setInterval(() => {\n Api1.run();\n }, 5000, 'myInterval');\n showAlert('Interval started successfully with jsobject.');\n } catch (error) {\n showAlert('Error: ' + error.message);\n }\n}"],"userSetOnLoad":false,"confirmBeforeExecute":false,"policyMap":{},"userPermissions":[],"createdAt":"2024-12-01T06:19:06Z"},"publishedAction":{"datasource":{"messages":[],"isAutoGenerated":false,"deleted":false,"policyMap":{},"policies":[],"userPermissions":[]},"messages":[],"userSetOnLoad":false,"confirmBeforeExecute":false,"policyMap":{},"userPermissions":[],"createdAt":"2024-12-01T06:19:06Z"},"gitSyncId":"674bfbf855991c29a2fddc76_893463d3-162a-4440-b571-5610a3966e28","id":"Page1_JSObject1.myFun1","deleted":false},{"pluginType":"JS","pluginId":"js-plugin","unpublishedAction":{"name":"myFun1","fullyQualifiedName":"JSObject3.myFun1","datasource":{"name":"UNUSED_DATASOURCE","pluginId":"js-plugin","messages":[],"isAutoGenerated":false,"deleted":false,"policyMap":{},"policies":[],"userPermissions":[]},"pageId":"Page1","collectionId":"Page1_JSObject3","actionConfiguration":{"timeoutInMillisecond":10000.0,"paginationType":"NONE","encodeParamsToggle":true,"body":"function () {\n setInterval(() => {\n testInvalid();\n }, 2000, \"testingFun\");\n}","selfReferencingDataPaths":[],"jsArguments":[]},"executeOnLoad":false,"dynamicBindingPathList":[{"key":"body"}],"isValid":true,"invalids":[],"messages":[],"jsonPathKeys":["function () {\n setInterval(() => {\n testInvalid();\n }, 2000, \"testingFun\");\n}"],"userSetOnLoad":false,"confirmBeforeExecute":false,"policyMap":{},"userPermissions":[],"createdAt":"2024-12-01T06:32:08Z"},"publishedAction":{"datasource":{"messages":[],"isAutoGenerated":false,"deleted":false,"policyMap":{},"policies":[],"userPermissions":[]},"messages":[],"userSetOnLoad":false,"confirmBeforeExecute":false,"policyMap":{},"userPermissions":[],"createdAt":"2024-12-01T06:32:08Z"},"gitSyncId":"674bfbf855991c29a2fddc76_fbf9f4c6-f168-47bf-bc64-0b6faa21175c","id":"Page1_JSObject3.myFun1","deleted":false},{"pluginType":"JS","pluginId":"js-plugin","unpublishedAction":{"name":"myFun1","fullyQualifiedName":"JSObject5.myFun1","datasource":{"name":"UNUSED_DATASOURCE","pluginId":"js-plugin","messages":[],"isAutoGenerated":false,"deleted":false,"policyMap":{},"policies":[],"userPermissions":[]},"pageId":"Page1","collectionId":"Page1_JSObject5","actionConfiguration":{"timeoutInMillisecond":10000.0,"paginationType":"NONE","encodeParamsToggle":true,"body":"function () {\n try {\n if (window.myInterval) {\n clearInterval(window.myInterval);\n }\n window.myInterval = setInterval(() => {\n showAlert('Interval triggered!');\n }, 5000);\n showAlert('Interval started successfully.');\n } catch (error) {\n showAlert('Error: ' + error.message);\n }\n}","selfReferencingDataPaths":[],"jsArguments":[]},"executeOnLoad":false,"clientSideExecution":true,"dynamicBindingPathList":[{"key":"body"}],"isValid":true,"invalids":[],"messages":[],"jsonPathKeys":["function () {\n try {\n if (window.myInterval) {\n clearInterval(window.myInterval);\n }\n window.myInterval = setInterval(() => {\n showAlert('Interval triggered!');\n }, 5000);\n showAlert('Interval started successfully.');\n } catch (error) {\n showAlert('Error: ' + error.message);\n }\n}"],"userSetOnLoad":false,"confirmBeforeExecute":false,"policyMap":{},"userPermissions":[],"createdAt":"2024-12-01T06:42:54Z"},"publishedAction":{"datasource":{"messages":[],"isAutoGenerated":false,"deleted":false,"policyMap":{},"policies":[],"userPermissions":[]},"messages":[],"userSetOnLoad":false,"confirmBeforeExecute":false,"policyMap":{},"userPermissions":[],"createdAt":"2024-12-01T06:42:54Z"},"gitSyncId":"674bfbf855991c29a2fddc76_d4f8d500-9c10-444e-828b-d0d41f299a67","id":"Page1_JSObject5.myFun1","deleted":false},{"pluginType":"JS","pluginId":"js-plugin","unpublishedAction":{"name":"myFun1","fullyQualifiedName":"JSObject2.myFun1","datasource":{"name":"UNUSED_DATASOURCE","pluginId":"js-plugin","messages":[],"isAutoGenerated":false,"deleted":false,"policyMap":{},"policies":[],"userPermissions":[]},"pageId":"Page1","collectionId":"Page1_JSObject2","actionConfiguration":{"timeoutInMillisecond":10000.0,"paginationType":"NONE","encodeParamsToggle":true,"body":"function () {\n try {\n setTimeout(() => {\n Api1.run();\n showAlert('Api1 executed');\n }, 5000);\n setTimeout(() => {\n Api2.run();\n showAlert('Api2 executed');\n }, 5000);\n } catch (error) {\n showAlert('Error: ' + error.message);\n }\n}","selfReferencingDataPaths":[],"jsArguments":[]},"executeOnLoad":false,"dynamicBindingPathList":[{"key":"body"}],"isValid":true,"invalids":[],"messages":[],"jsonPathKeys":["function () {\n try {\n setTimeout(() => {\n Api1.run();\n showAlert('Api1 executed');\n }, 5000);\n setTimeout(() => {\n Api2.run();\n showAlert('Api2 executed');\n }, 5000);\n } catch (error) {\n showAlert('Error: ' + error.message);\n }\n}"],"userSetOnLoad":false,"confirmBeforeExecute":false,"policyMap":{},"userPermissions":[],"createdAt":"2024-12-02T05:04:36Z"},"publishedAction":{"datasource":{"messages":[],"isAutoGenerated":false,"deleted":false,"policyMap":{},"policies":[],"userPermissions":[]},"messages":[],"userSetOnLoad":false,"confirmBeforeExecute":false,"policyMap":{},"userPermissions":[],"createdAt":"2024-12-02T05:04:36Z"},"gitSyncId":"674bfbf855991c29a2fddc76_dc1d4be7-85fd-4899-9041-808fe25a6a3a","id":"Page1_JSObject2.myFun1","deleted":false},{"pluginType":"JS","pluginId":"js-plugin","unpublishedAction":{"name":"stopInterval","fullyQualifiedName":"JSObject5.stopInterval","datasource":{"name":"UNUSED_DATASOURCE","pluginId":"js-plugin","messages":[],"isAutoGenerated":false,"deleted":false,"policyMap":{},"policies":[],"userPermissions":[]},"pageId":"Page1","collectionId":"Page1_JSObject5","actionConfiguration":{"timeoutInMillisecond":0.0,"paginationType":"NONE","encodeParamsToggle":true,"body":"function () {\n try {\n if (window.myInterval) {\n clearInterval(window.myInterval);\n showAlert('Interval stopped successfully.');\n } else {\n showAlert('No active interval to stop.');\n }\n } catch (error) {\n showAlert('Error: ' + error.message);\n }\n}","selfReferencingDataPaths":[],"jsArguments":[]},"executeOnLoad":false,"dynamicBindingPathList":[{"key":"body"}],"isValid":true,"invalids":[],"messages":[],"jsonPathKeys":["function () {\n try {\n if (window.myInterval) {\n clearInterval(window.myInterval);\n showAlert('Interval stopped successfully.');\n } else {\n showAlert('No active interval to stop.');\n }\n } catch (error) {\n showAlert('Error: ' + error.message);\n }\n}"],"userSetOnLoad":false,"confirmBeforeExecute":false,"policyMap":{},"userPermissions":[],"createdAt":"2024-12-02T07:51:11Z"},"publishedAction":{"datasource":{"messages":[],"isAutoGenerated":false,"deleted":false,"policyMap":{},"policies":[],"userPermissions":[]},"messages":[],"userSetOnLoad":false,"confirmBeforeExecute":false,"policyMap":{},"userPermissions":[],"createdAt":"2024-12-02T07:51:11Z"},"gitSyncId":"674bfbf855991c29a2fddc76_df3a71cf-4cb4-4c43-b422-f67a84d96ab4","id":"Page1_JSObject5.stopInterval","deleted":false}],"actionCollectionList":[{"unpublishedCollection":{"name":"JSObject1","pageId":"Page1","pluginId":"js-plugin","pluginType":"JS","actions":[],"archivedActions":[],"body":"export default {\n\tmyFun1() {\n\t\ttry {\n\t\t\t{{clearInterval('myInterval')}}; // Clear the existing interval with ID 'few'\n\t\t\tsetInterval(() => {\n\t\t\t\tApi1.run();\n\t\t\t}, 5000, 'myInterval'); // Start a new interval with the same ID\n\t\t\tshowAlert('Interval started successfully with jsobject.');\n\t\t} catch (error) {\n\t\t\tshowAlert('Error: ' + error.message);\n\t\t}\n\t},\n};","variables":[],"userPermissions":[]},"gitSyncId":"674bfbf855991c29a2fddc76_9cc0e611-e5a4-4e57-a490-8e8ef0d47e3a","id":"Page1_JSObject1","deleted":false},{"unpublishedCollection":{"name":"JSObject2","pageId":"Page1","pluginId":"js-plugin","pluginType":"JS","actions":[],"archivedActions":[],"body":"export default {\n\tmyFun1() {\n\t\ttry {\n\t\t\tsetTimeout(() => {\n\t\t\t\tApi1.run();\n\t\t\t\tshowAlert('Api1 executed');\n\t\t\t}, 5000);\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tApi2.run();\n\t\t\t\tshowAlert('Api2 executed');\n\t\t\t}, 5000);\n\t\t} catch (error) {\n\t\t\tshowAlert('Error: ' + error.message);\n\t\t}\n\t},\n};","variables":[],"userPermissions":[]},"gitSyncId":"674bfbf855991c29a2fddc76_63702513-362a-4594-bf88-adad6614e783","id":"Page1_JSObject2","deleted":false},{"unpublishedCollection":{"name":"JSObject3","pageId":"Page1","pluginId":"js-plugin","pluginType":"JS","actions":[],"archivedActions":[],"body":"export default {\n\tmyFun1() {\n\t\tsetInterval(() => {\n\t\t\t\ttestInvalid();\n\t\t}, 2000, \"testingFun\");\n\t},\n};","variables":[],"userPermissions":[]},"gitSyncId":"674bfbf855991c29a2fddc76_bbfa5493-5794-432e-8796-1b0a34ff83dc","id":"Page1_JSObject3","deleted":false},{"unpublishedCollection":{"name":"JSObject4","pageId":"Page1","pluginId":"js-plugin","pluginType":"JS","actions":[],"archivedActions":[],"body":"export default {\n\tmyFun1() {\n\t\tsetInterval(() => {\n\t\t\tconsole.log(\"This interval will not work properly due to an invalid callback function.\");\n\t\t}, dasdas, \"myInterval\");\n\t},\n};","variables":[],"userPermissions":[]},"gitSyncId":"674bfbf855991c29a2fddc76_196398d2-ee0f-4486-9a53-0b5ca63b6fbd","id":"Page1_JSObject4","deleted":false},{"unpublishedCollection":{"name":"JSObject5","pageId":"Page1","pluginId":"js-plugin","pluginType":"JS","actions":[],"archivedActions":[],"body":"export default {\n myFun1() {\n try {\n // Clear any existing interval with ID 'myInterval'\n if (window.myInterval) {\n clearInterval(window.myInterval);\n }\n\n // Start a new interval to run every 5 seconds\n window.myInterval = setInterval(() => {\n showAlert('Interval triggered!'); // Show alert every 5 seconds\n }, 5000);\n\n showAlert('Interval started successfully.');\n } catch (error) {\n showAlert('Error: ' + error.message);\n }\n },\n\n stopInterval() {\n try {\n if (window.myInterval) {\n clearInterval(window.myInterval); // Clear the existing interval\n showAlert('Interval stopped successfully.');\n } else {\n showAlert('No active interval to stop.');\n }\n } catch (error) {\n showAlert('Error: ' + error.message);\n }\n },\n};","variables":[],"userPermissions":[]},"gitSyncId":"674bfbf855991c29a2fddc76_2a42ff86-6858-4a1f-836b-45706db2ddfa","id":"Page1_JSObject5","deleted":false}],"editModeTheme":{"name":"Default-New","displayName":"Modern","isSystemTheme":true,"deleted":false},"publishedTheme":{"name":"Default-New","displayName":"Modern","isSystemTheme":true,"deleted":false}} \ No newline at end of file diff --git a/app/client/cypress/locators/commonlocators.json b/app/client/cypress/locators/commonlocators.json index a7c83551105f..e639171dd524 100644 --- a/app/client/cypress/locators/commonlocators.json +++ b/app/client/cypress/locators/commonlocators.json @@ -243,5 +243,7 @@ "allowsearchingInputTypeCheckbox": ".t--property-control-allowsearching input[type='checkbox']", "clientSideSearch": ".t--property-control-clientsidesearch input[type='checkbox']", "enableClientSideSearch": ".t--property-control-enableclientsidesearch input[type='checkbox']", - "fixedFooterInput": ".t--property-control-fixedfooter input" + "fixedFooterInput": ".t--property-control-fixedfooter input", + "tostifyIcon": ".Toastify--animate-icon > span", + "downloadFileType": "button[class*='t--open-dropdown-Select-file-type'] > span:first-of-type" } diff --git a/app/client/cypress/support/Objects/CommonLocators.ts b/app/client/cypress/support/Objects/CommonLocators.ts index 85f7e173b819..07006699a065 100644 --- a/app/client/cypress/support/Objects/CommonLocators.ts +++ b/app/client/cypress/support/Objects/CommonLocators.ts @@ -102,7 +102,7 @@ export class CommonLocators { entityNameinLeftSidebar + "']/parent::div[contains(@class, 't--entity-name editing')]/input"; _jsToggle = (controlToToggle: string) => - ".t--property-control-" + controlToToggle + " .t--js-toggle"; + `.t--property-control-${controlToToggle} .t--js-toggle, [data-guided-tour-iid='${controlToToggle}']`; _buttonByText = (btnVisibleText: string) => `//span[text()="${btnVisibleText}"]/ancestor::button | //button[text()="${btnVisibleText}" or @title="${btnVisibleText}"]`; _selectPropPageDropdown = (ddName: string) => @@ -342,6 +342,8 @@ export class CommonLocators { _propertyCollapseBody = ".bp3-collapse-body"; _propertyCollapse = ".bp3-collapse"; _widgetBorder = ".t--draggable-tabswidget div div div"; + _modalButtonText = "[data-testid='modal-wrapper'] .bp3-button"; + _showBoundary = ".show-boundary"; _entityItem = "[data-testid='t--entity-item-Api1']"; _rowData = "[data-colindex='0'][data-rowindex='0']"; } diff --git a/app/client/cypress/support/Pages/AggregateHelper.ts b/app/client/cypress/support/Pages/AggregateHelper.ts index 47afccae890e..c07b6a8151dd 100644 --- a/app/client/cypress/support/Pages/AggregateHelper.ts +++ b/app/client/cypress/support/Pages/AggregateHelper.ts @@ -1943,4 +1943,60 @@ export class AggregateHelper { valueToValidate, ); } + + public RemoveChars(selector: string, charCount = 0, index = 0) { + if (charCount > 0) + this.GetElement(selector) + .eq(index) + .focus() + .type("{backspace}".repeat(charCount), { timeout: 2, force: true }) + .wait(50); + else { + if (charCount == -1) this.GetElement(selector).eq(index).clear(); + } + } + + public captureConsoleLogs(): void { + cy.window() + .its("console") + .then((console) => { + cy.spy(console, "log").as("log"); + cy.spy(console, "error").as("error"); + cy.spy(console, "warn").as("warn"); + }); + } + + public verifyConsoleLogNotContainingError(): void { + cy.get("@error") + .invoke("getCalls") + .then((calls) => { + console.table(calls); + cy.wrap(calls).each((call) => { + (call as any).args.forEach((arg: any) => { + expect(arg).to.not.contain("error"); + }); + }); + }); + } + + public verifyConsoleLogContainsExpectedMessage(message: string): void { + cy.get("@log") + .invoke("getCalls") + .then((calls) => { + console.table(calls); + cy.wrap(calls).each((call) => { + (call as any).args.forEach((arg: any) => { + expect(arg).to.contain(message); + }); + }); + }); + } + + public clearConsoleLogs(): void { + cy.window().then((win) => { + cy.spy(win.console, "log").as("log"); + cy.spy(win.console, "error").as("error"); + cy.spy(win.console, "warn").as("warn"); + }); + } } diff --git a/app/client/cypress/support/Pages/ApiPage.ts b/app/client/cypress/support/Pages/ApiPage.ts index a963cb413c72..de42a2cb0f90 100644 --- a/app/client/cypress/support/Pages/ApiPage.ts +++ b/app/client/cypress/support/Pages/ApiPage.ts @@ -100,6 +100,9 @@ export class ApiPage { private curlImport = ".t--datasoucre-create-option-new_curl_import"; private _curlTextArea = "//label[text()='Paste CURL Code Here']/parent::form/div"; + private runOnPageLoadJSObject = + "input[name^='execute-on-page-load'][type='checkbox']"; + public settingsTriggerLocator = "[data-testid='t--js-settings-trigger']"; CreateApi( apiName = "", @@ -495,4 +498,16 @@ export class ApiPage { ); this.RunAPI(); } + + ToggleOnPageLoadRunJsObject(enable = true || false) { + this.SelectPaneTab("Settings"); + if (enable) this.agHelper.CheckUncheck(this.runOnPageLoadJSObject, true); + else this.agHelper.CheckUncheck(this.runOnPageLoadJSObject, false); + } + + public clickSettingIcon(enable: boolean) { + this.agHelper.GetNClick(this.settingsTriggerLocator); + if (enable) this.agHelper.CheckUncheck(this.runOnPageLoadJSObject, true); + else this.agHelper.CheckUncheck(this.runOnPageLoadJSObject, false); + } } diff --git a/app/client/cypress/support/Pages/JSEditor.ts b/app/client/cypress/support/Pages/JSEditor.ts index 09802ef2d7e2..a6a0eba855df 100644 --- a/app/client/cypress/support/Pages/JSEditor.ts +++ b/app/client/cypress/support/Pages/JSEditor.ts @@ -336,5 +336,7 @@ export class JSEditor { ); //Asserting NO is not clicked } - //#endregion + public currentJSObjectName(): Cypress.Chainable { + return cy.get(this._jsObjName).invoke("text"); + } } diff --git a/app/client/cypress/support/Pages/PartialImportExport.ts b/app/client/cypress/support/Pages/PartialImportExport.ts index de1b0df74c93..b8a6e5c0ef49 100644 --- a/app/client/cypress/support/Pages/PartialImportExport.ts +++ b/app/client/cypress/support/Pages/PartialImportExport.ts @@ -214,4 +214,16 @@ export default class PartialImportExport { Cypress.env("MESSAGES").ERROR_IN_EXPORTING_APP(), ); } + + OpenImportModalWithPage(pageName: string) { + AppSidebar.navigate(AppSidebarButton.Editor); + + this.entityExplorer.ActionContextMenuByEntityName({ + entityNameinLeftSidebar: pageName, + action: "Import", + entityType: EntityItems.Page, + }); + + this.agHelper.AssertElementVisibility(this.locators.import.importModal); + } } diff --git a/app/client/cypress/support/Pages/PropertyPane.ts b/app/client/cypress/support/Pages/PropertyPane.ts index 5a15ee560a0d..7b97287dfbe6 100644 --- a/app/client/cypress/support/Pages/PropertyPane.ts +++ b/app/client/cypress/support/Pages/PropertyPane.ts @@ -178,6 +178,9 @@ export class PropertyPane { _iconDropdown = "[data-test-id='virtuoso-scroller']"; _dropdownControlError = "[data-testid='t---dropdown-control-error']"; _borderColorCursor = ".t--property-control-bordercolor .bp3-input-group div"; + _buttonWidget = "[data-widgetname-cy='Button1']"; + _getActionCardSelector = (type: string) => + `[data-testid='action-card-Show ${type}']`; public OpenJsonFormFieldSettings(fieldName: string) { this.agHelper.GetNClick(this._jsonFieldEdit(fieldName)); @@ -703,4 +706,25 @@ export class PropertyPane { }); }); } + + public ToggleJSModeByIndex( + endp: string, + toToggleOnJS: true | false = true, + index: number = 0, + ) { + const toggleLocator = this.locator._jsToggle( + endp.replace(/ +/g, "").toLowerCase(), + ); + + cy.get(toggleLocator) + .eq(index) // Use the index to interact with a specific toggle + .invoke("attr", "class") + .then((classes: string) => { + if (toToggleOnJS && !classes.includes("is-active")) { + this.agHelper.GetNClick(toggleLocator, index, true); + } else if (!toToggleOnJS && classes.includes("is-active")) { + this.agHelper.GetNClick(toggleLocator, index, true); + } + }); + } }