diff --git a/app/client/cypress/integration/Smoke_TestSuite/ExplorerTests/Entity_Explorer_Widgets_Copy_Delete_Undo_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ExplorerTests/Entity_Explorer_Widgets_Copy_Delete_Undo_spec.js
new file mode 100644
index 0000000000..226fa6ca49
--- /dev/null
+++ b/app/client/cypress/integration/Smoke_TestSuite/ExplorerTests/Entity_Explorer_Widgets_Copy_Delete_Undo_spec.js
@@ -0,0 +1,65 @@
+const testdata = require("../../../fixtures/testdata.json");
+const apiwidget = require("../../../locators/apiWidgetslocator.json");
+const explorer = require("../../../locators/explorerlocators.json");
+const commonlocators = require("../../../locators/commonlocators.json");
+const formWidgetsPage = require("../../../locators/FormWidgets.json");
+const publish = require("../../../locators/publishWidgetspage.json");
+
+const pageid = "MyPage";
+
+describe("Test Suite to validate copy/delete/undo functionalites", function() {
+ it("Drag and drop form widget and validate copy widget via toast message", function() {
+ cy.log("Login Successful");
+ cy.get(explorer.addWidget).click();
+ cy.get(commonlocators.entityExplorersearch).should("be.visible");
+ cy.get(commonlocators.entityExplorersearch)
+ .clear()
+ .type("form");
+ cy.dragAndDropToCanvas("formwidget");
+ cy.widgetText(
+ "FormTest",
+ formWidgetsPage.formWidget,
+ formWidgetsPage.formInner,
+ );
+ cy.get(commonlocators.copyWidget).click();
+ cy.wait(500);
+ cy.get(commonlocators.toastBody)
+ .first()
+ .contains("Copied");
+ cy.get(commonlocators.editPropCrossButton).click();
+ cy.get(explorer.closeWidgets).click();
+ });
+
+ it("Delete Widget from sidebar and Undo action validation", function() {
+ cy.GlobalSearchEntity("FormTest");
+ cy.get(apiwidget.propertyList).then(function($lis) {
+ expect($lis).to.have.length(2);
+ expect($lis.eq(0)).to.contain("{{FormTest.isVisible}}");
+ expect($lis.eq(1)).to.contain("{{FormTest.data}}");
+ });
+ cy.DeleteWidgetFromSideBar();
+ cy.wait(500);
+ cy.get(apiwidget.propertyList).should("not.be.visible");
+ /*
+ To be enabled once widget delete click works
+ cy.get('.t--delete-widget')
+ .trigger("mouseover")
+ .click({ force: true });
+ */
+ cy.get(commonlocators.toastAction).should("be.visible");
+ cy.get(commonlocators.toastAction)
+ .contains("UNDO")
+ .click({ force: true });
+ cy.wait("@updateLayout").should(
+ "have.nested.property",
+ "response.body.responseMeta.status",
+ 200,
+ );
+ cy.wait(500);
+ cy.get(apiwidget.propertyList).then(function($lis) {
+ expect($lis).to.have.length(2);
+ expect($lis.eq(0)).to.contain("{{FormTest.isVisible}}");
+ expect($lis.eq(1)).to.contain("{{FormTest.data}}");
+ });
+ });
+});
diff --git a/app/client/cypress/integration/Smoke_TestSuite/ExplorerTests/Entity_Explorer_Widgets_Copy_Paste_Delete_Undo_Keyboard_Event_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ExplorerTests/Entity_Explorer_Widgets_Copy_Paste_Delete_Undo_Keyboard_Event_spec.js
new file mode 100644
index 0000000000..cc714f1b6b
--- /dev/null
+++ b/app/client/cypress/integration/Smoke_TestSuite/ExplorerTests/Entity_Explorer_Widgets_Copy_Paste_Delete_Undo_Keyboard_Event_spec.js
@@ -0,0 +1,55 @@
+const testdata = require("../../../fixtures/testdata.json");
+const apiwidget = require("../../../locators/apiWidgetslocator.json");
+const explorer = require("../../../locators/explorerlocators.json");
+const commonlocators = require("../../../locators/commonlocators.json");
+const formWidgetsPage = require("../../../locators/FormWidgets.json");
+const publish = require("../../../locators/publishWidgetspage.json");
+const widgetsPage = require("../../../locators/Widgets.json");
+
+const pageid = "MyPage";
+
+describe("Test Suite to validate copy/delete/undo functionalites", function() {
+ it("Drag and drop form widget and validate copy widget via toast message", function() {
+ cy.log("Login Successful");
+ cy.get(explorer.addWidget).click();
+ cy.get(commonlocators.entityExplorersearch).should("be.visible");
+ cy.get(commonlocators.entityExplorersearch)
+ .clear()
+ .type("form");
+ cy.dragAndDropToCanvas("formwidget");
+ cy.widgetText(
+ "FormTest",
+ formWidgetsPage.formWidget,
+ formWidgetsPage.formInner,
+ );
+ cy.get("body").click();
+ cy.get("body").type("{meta}c");
+ cy.wait(500);
+ cy.get(commonlocators.toastBody)
+ .first()
+ .contains("Copied");
+ cy.get("body").type("{meta}v", { force: true });
+ cy.wait("@updateLayout").should(
+ "have.nested.property",
+ "response.body.responseMeta.status",
+ 200,
+ );
+ cy.get("body").type("{del}", { force: true });
+ cy.wait("@updateLayout").should(
+ "have.nested.property",
+ "response.body.responseMeta.status",
+ 200,
+ );
+ cy.get(commonlocators.toastAction).should("be.visible");
+ cy.get(commonlocators.toastAction)
+ .contains("UNDO")
+ .click({ force: true });
+ cy.get(explorer.closeWidgets).click();
+ cy.GlobalSearchEntity("Form1");
+ cy.get(apiwidget.propertyList).then(function($lis) {
+ expect($lis).to.have.length(2);
+ expect($lis.eq(0)).to.contain("{{Form1.isVisible}}");
+ expect($lis.eq(1)).to.contain("{{Form1.data}}");
+ });
+ });
+});
diff --git a/app/client/cypress/locators/commonlocators.json b/app/client/cypress/locators/commonlocators.json
index 7b7e93205a..c718381186 100644
--- a/app/client/cypress/locators/commonlocators.json
+++ b/app/client/cypress/locators/commonlocators.json
@@ -65,5 +65,9 @@
"saveStatusSuccess": ".t--save-status-success",
"saveStatusError": ".t--save-status-error",
"tableNextPage": ".t--table-widget-next-page",
- "tablePrevPage": ".t--table-widget-prev-page"
+ "tablePrevPage": ".t--table-widget-prev-page",
+ "copyWidget": ".t--copy-widget",
+ "deleteWidget": ".t--delete-widget",
+ "toastAction": ".t--toast-action",
+ "toastBody":".Toastify__toast-body"
}
diff --git a/app/client/src/components/editorComponents/ToastComponent.tsx b/app/client/src/components/editorComponents/ToastComponent.tsx
index 68d128e5d1..1b56650eaf 100644
--- a/app/client/src/components/editorComponents/ToastComponent.tsx
+++ b/app/client/src/components/editorComponents/ToastComponent.tsx
@@ -68,6 +68,7 @@ const ToastComponent = (props: Props) => {
{props.message}
{props.action && (
{
dispatch(props.action?.dispatchableAction);
props.closeToast && props.closeToast();
diff --git a/app/client/src/pages/Editor/PropertyPaneTitle.tsx b/app/client/src/pages/Editor/PropertyPaneTitle.tsx
index 7298a1fe43..f4e25fd825 100644
--- a/app/client/src/pages/Editor/PropertyPaneTitle.tsx
+++ b/app/client/src/pages/Editor/PropertyPaneTitle.tsx
@@ -125,6 +125,7 @@ const PropertyPaneTitle = memo((props: PropertyPaneTitleProps) => {
hoverOpenDelay={200}
>
{
hoverOpenDelay={200}
>