test: new test cases framework functions and Action selector (#37566)

## Description
E2E Test cases for framework function & Action selector.

Fixes [Issue
URL](https://app.zenhub.com/workspaces/stability-pod-6690c4814e31602e25cab7fd/issues/gh/appsmithorg/appsmith/37370)

## Automation

/ok-to-test tags="@tag.All"

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/12343756587>
> Commit: 56f7a2eb2acee62237f9dcd395b6a618956e38a2
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=12343756587&attempt=2"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Mon, 16 Dec 2024 03:08:25 UTC
<!-- end of auto-generated comment: Cypress test results  -->


## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [x] No


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
	- Enhanced property pane with new button widget identification.
	- New selectors for action cards and toast notifications.
	- Improved modal interaction with new properties for buttons.
	- Added functionality for toggling JavaScript execution on page load.
	- New methods for character manipulation and console log management.
	- Comprehensive application configurations for interval management.
- New applications and widgets for managing intervals and clipboard
functionality.
- New functionality for resetting widgets and handling navigation
actions.
	- Introduction of new JSON configurations for various applications.

- **Bug Fixes**
	- Improved error handling for various actions and functions.

- **Tests**
- Extensive test coverage for new and existing functionalities,
including action selectors, interval functions, alert handling, and
geolocation features.
- New tests for clipboard functionality, download actions, and local
storage operations.
- Enhanced tests for Radio and CategorySlider widgets to improve
validation of JavaScript context and error handling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: yatinappsmith <yatin@appsmith.com>
This commit is contained in:
Sagar Khalasi 2024-12-16 16:41:54 +05:30 committed by GitHub
parent f08dd29300
commit a5fa2aa7a1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 4565 additions and 6 deletions

View File

@ -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);
});
},
);

View File

@ -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);
});
},
);

View File

@ -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");
});
},
);

View File

@ -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();
});
},
);

View File

@ -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);
});
},
);

View File

@ -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);
});
},
);

View File

@ -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);
});
},
);

View File

@ -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);
});
},
);

View File

@ -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 applications 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");
});
},
);

View File

@ -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);
});
},
);

View File

@ -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();
});
},
);

View File

@ -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();
});
},
);

View File

@ -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();
});
},
);

View File

@ -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");
});
},
);

View File

@ -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();
});
},
);

View File

@ -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),
);

View File

@ -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");

File diff suppressed because one or more lines are too long

View File

@ -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\":[]}"}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -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"
}

View File

@ -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']";
}

View File

@ -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");
});
}
}

View File

@ -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);
}
}

View File

@ -336,5 +336,7 @@ export class JSEditor {
); //Asserting NO is not clicked
}
//#endregion
public currentJSObjectName(): Cypress.Chainable<string> {
return cy.get(this._jsObjName).invoke("text");
}
}

View File

@ -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);
}
}

View File

@ -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);
}
});
}
}