diff --git a/app/client/cypress/e2e/Regression/ClientSide/Widgets/Custom/CustomWidget_PropertyPane_Validation.ts b/app/client/cypress/e2e/Regression/ClientSide/Widgets/Custom/CustomWidget_PropertyPane_Validation.ts new file mode 100644 index 000000000000..060edac878e4 --- /dev/null +++ b/app/client/cypress/e2e/Regression/ClientSide/Widgets/Custom/CustomWidget_PropertyPane_Validation.ts @@ -0,0 +1,112 @@ +import { + agHelper, + assertHelper, + locators, + propPane, +} from "../../../../../support/Objects/ObjectsCore"; + +import EditorNavigation, { + EntityType, +} from "../../../../../support/Pages/EditorNavigation"; + +describe("Custom widget Tests", {}, function () { + before(() => { + agHelper.AddDsl("customWidgetWithSrc"); + }); + + const getIframeBody = () => { + // get the iframe > document > body + // and retry until the body element is not empty + return cy + .get(".t--widget-customwidget iframe") + .last() + .its("0.contentDocument.body") + .should("not.be.empty") + .then(cy.wrap); + }; + + it("should check that custom widget property pane details are coming up properly", () => { + const defaultModel = `{ + "tips": [ + "Pass data to this widget in the default model field", + "data in the javascript file using the appsmith.model variable", + "Create events in the widget and trigger them in the javascript file using appsmith.triggerEvent('eventName')", + "Access data in CSS as var(--appsmith-model-{property-name})" + ] + }`; + const custom2WidgetBoundary = + "//div[@data-widgetname-cy='Custom2']//div[contains(@class,'widget-component-boundary')]//div//div"; + + EditorNavigation.SelectEntityByName("Custom2", EntityType.Widget); + getIframeBody().find(".tip-container").should("exist"); + getIframeBody() + .find(".tip-container p") + .should( + "have.text", + "Pass data to this widget in the default model field", + ); + + agHelper.UpdateCodeInput(propPane._propDefaultModel, defaultModel); + + getIframeBody().find("button.primary").trigger("click"); + + getIframeBody() + .find(".tip-container p") + .should( + "have.text", + "data in the javascript file using the appsmith.model variable", + ); + + EditorNavigation.SelectEntityByName("Custom1", EntityType.Widget); + propPane.TogglePropertyState("Visible", "Off"); + agHelper.GetNClick(locators._previewModeToggle("edit")); + agHelper.AssertElementAbsence(locators._widgetByName("Custom1")); + agHelper.GetNClick(locators._previewModeToggle("preview")); + propPane.TogglePropertyState("Visible", "On"); + + EditorNavigation.SelectEntityByName("Custom2", EntityType.Widget); + + propPane.ToggleJSMode("onResetClick"); + propPane.EnterJSContext( + "onResetClick", + `{{showAlert('Reset Clicked', 'error');}}`, + ); + getIframeBody().find("button.reset").trigger("click"); + agHelper.ValidateToastMessage("Reset Clicked"); + + propPane.MoveToTab("Style"); + // Background color + agHelper.GetNClick(propPane._propertyControlColorPicker("backgroundcolor")); + agHelper.AssertElementVisibility(propPane._colorPickerV2Color); + propPane.ToggleJSMode("backgroundcolor", true); + propPane.UpdatePropertyFieldValue("Background color", "#eab308"); + agHelper.AssertCSS( + `(${locators._draggableCustomWidget}//div)[10]`, + "background-color", + "rgb(239, 117, 65)", + ); + propPane.ToggleJSMode("backgroundcolor", false); + + // Border Color + propPane.SelectColorFromColorPicker("bordercolor", 13); + assertHelper.AssertNetworkStatus("@updateLayout"); + + agHelper + .GetWidgetCSSFrAttribute(propPane._borderColorCursor, "background-color") + .then((color) => { + agHelper + .GetWidgetCSSFrAttribute(custom2WidgetBoundary, "border-color") + .then((bgcolor) => { + expect(color).to.eq(bgcolor); + }); + }); + + // Verify border width + propPane.UpdatePropertyFieldValue("Border width", "7"); + agHelper + .GetWidgetCSSFrAttribute(custom2WidgetBoundary, "border-width") + .then((width) => { + expect(width).to.eq("7px"); + }); + }); +}); diff --git a/app/client/cypress/fixtures/customWidgetWithSrc.json b/app/client/cypress/fixtures/customWidgetWithSrc.json new file mode 100644 index 000000000000..6e503437e5fa --- /dev/null +++ b/app/client/cypress/fixtures/customWidgetWithSrc.json @@ -0,0 +1,149 @@ +{ + "dsl": { + "widgetName": "MainContainer", + "backgroundColor": "none", + "rightColumn": 4896, + "snapColumns": 64, + "detachFromLayout": true, + "widgetId": "0", + "topRow": 0, + "bottomRow": 730, + "containerStyle": "none", + "snapRows": 124, + "parentRowSpace": 1, + "type": "CANVAS_WIDGET", + "canExtend": true, + "version": 91, + "minHeight": 1292, + "dynamicTriggerPathList": [], + "parentColumnSpace": 1, + "dynamicBindingPathList": [], + "leftColumn": 0, + "children": [ + { + "needsErrorInfo": false, + "boxShadow": "{{appsmith.theme.boxShadow.appBoxShadow}}", + "mobileBottomRow": 42, + "widgetName": "Custom1", + "borderColor": "#E0DEDE", + "srcDoc": { + "html": " \n
", + "css": ".table-container {\n padding: 20px;\n background-color: #f9f9f9;\n border-radius: 8px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n}\n\n.table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.table th, .table td {\n padding: 12px;\n border-bottom: 1px solid #ddd;\n text-align: left;\n}\n\n.table th {\n background-color: #f1f1f1;\n font-weight: bold;\n}\n\n.table tr:hover {\n background-color: #f5f5f5;\n}", + "js": "import React from 'https://cdn.jsdelivr.net/npm/react@18.2.0/+esm';\nimport ReactDOM from 'https://cdn.jsdelivr.net/npm/react-dom@18.2.0/+esm';\nfunction TableWidget() {\n // Mock data for the table\n const [data, setData] = React.useState(appsmith.model.data || [{\n name: 'John Doe',\n age: 28,\n occupation: 'Engineer'\n }, {\n name: 'Jane Smith',\n age: 34,\n occupation: 'Designer'\n }, {\n name: 'Sam Green',\n age: 45,\n occupation: 'Manager'\n }]);\n React.useEffect(() => {\n appsmith.onModelChange((model, prevModel) => {\n if (JSON.stringify(model.data) !== JSON.stringify(prevModel?.data)) {\n setData(model.data);\n }\n });\n }, []);\n return /*#__PURE__*/React.createElement(\"div\", {\n className: \"table-container\"\n }, /*#__PURE__*/React.createElement(\"table\", {\n className: \"table\"\n }, /*#__PURE__*/React.createElement(\"thead\", null, /*#__PURE__*/React.createElement(\"tr\", null, /*#__PURE__*/React.createElement(\"th\", null, \"Name\"), /*#__PURE__*/React.createElement(\"th\", null, \"Age\"), /*#__PURE__*/React.createElement(\"th\", null, \"Occupation\"))), /*#__PURE__*/React.createElement(\"tbody\", null, data.map((row, index) => /*#__PURE__*/React.createElement(\"tr\", {\n key: index\n }, /*#__PURE__*/React.createElement(\"td\", null, row.name), /*#__PURE__*/React.createElement(\"td\", null, row.age), /*#__PURE__*/React.createElement(\"td\", null, row.occupation))))));\n}\nappsmith.onReady(() => {\n ReactDOM.render( /*#__PURE__*/React.createElement(TableWidget, null), document.getElementById(\"root\"));\n});" + }, + "isCanvas": false, + "topRow": 10, + "bottomRow": 40, + "parentRowSpace": 10, + "type": "CUSTOM_WIDGET", + "mobileRightColumn": 31, + "dynamicTriggerPathList": [ + { + "key": "onResetClick" + } + ], + "parentColumnSpace": 7.890625, + "dynamicBindingPathList": [ + { + "key": "theme" + }, + { + "key": "borderRadius" + }, + { + "key": "boxShadow" + } + ], + "leftColumn": 8, + "defaultModel": "{\n \"tips\": [\n \"Pass data to this widget in the default model field\",\n \"Access data in the javascript file using the appsmith.model variable\",\n \"Create events in the widget and trigger them in the javascript file using appsmith.triggerEvent('eventName')\",\n \"Access data in CSS as var(--appsmith-model-{property-name})\"\n ]\n}", + "borderWidth": "1", + "theme": "{{appsmith.theme}}", + "onResetClick": "{{showAlert('Successfully reset!!', '');}}", + "events": ["onResetClick"], + "key": "podxgd85w9", + "backgroundColor": "#FFFFFF", + "rightColumn": 56, + "dynamicHeight": "FIXED", + "isSearchWildcard": true, + "widgetId": "zkhwsvct6f", + "isVisible": true, + "version": 1, + "uncompiledSrcDoc": { + "html": " \n ", + "css": ".table-container {\n padding: 20px;\n background-color: #f9f9f9;\n border-radius: 8px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n }\n .table {\n width: 100%;\n border-collapse: collapse;\n }\n .table th, .table td {\n padding: 12px;\n border-bottom: 1px solid #ddd;\n text-align: left;\n }\n .table th {\n background-color: #f1f1f1;\n font-weight: bold;\n }\n .table tr:hover {\n background-color: #f5f5f5;\n }", + "js": " import React from 'https://cdn.jsdelivr.net/npm/react@18.2.0/+esm';\n import ReactDOM from 'https://cdn.jsdelivr.net/npm/react-dom@18.2.0/+esm';\n function TableWidget() {\n // Mock data for the table\n const [data, setData] = React.useState(appsmith.model.data || [\n { name: 'John Doe', age: 28, occupation: 'Engineer' },\n { name: 'Jane Smith', age: 34, occupation: 'Designer' },\n { name: 'Sam Green', age: 45, occupation: 'Manager' }\n ]);\n React.useEffect(() => {\n appsmith.onModelChange((model, prevModel) => {\n if (JSON.stringify(model.data) !== JSON.stringify(prevModel?.data)) {\n setData(model.data);\n }\n });\n }, []);\n return (\n| Name | \nAge | \nOccupation | \n
|---|---|---|
| {row.name} | \n{row.age} | \n{row.occupation} | \n