diff --git a/.env.example b/.env.example index 91c1b675db..ef48c3bc9d 100644 --- a/.env.example +++ b/.env.example @@ -56,3 +56,5 @@ APPSMITH_MAIL_SMTP_TLS_ENABLED= #APPSMITH_SENTRY_DSN= #APPSMITH_SENTRY_ENVIRONMENT= +# Configure cloud services +# APPSMITH_CLOUD_SERVICES_BASE_URL \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/---epic.md b/.github/ISSUE_TEMPLATE/---epic.md index ec8e553d62..2a132b4026 100644 --- a/.github/ISSUE_TEMPLATE/---epic.md +++ b/.github/ISSUE_TEMPLATE/---epic.md @@ -6,24 +6,43 @@ labels: Epic, Product Note assignees: Nikhil-Nandagopal --- -## Problem statement - -Why is this needed? -What does it hope to achieve? +# Objective +Here you fill in the objective of the feature/product that you are writing about. ## Related issues - [ ] #issue1 -## Success criteria +# Success Metrics +List of all metrics you are tracking and the desired goal. +| Goal | Metric | +| ------------- | ------------- | +| e.g. Simplify user experience | Customer satisfaction score increases | +| e.g. Simplify onboarding flow | Decrease churn rate down to 30% | -How will we know the project succeeded? +# Assumptions +List any assumptions that you have about your users, technical constraints, or business goals (e.g., Most users will access this feature from tablet). -## User story +- Assumption 1 +- Assumption 2 +- Assumption 3 -How does a user use this feature? How does it relate to the problem? +# Requirements +| Requirement | User Story | Importance | Notes | +| ------------- | ------------- | ------------- | ------------- | +| e.g. Must be mobile responsive | e.g. as a user, I want to be able to access the platform via mobile phone | High, Low or Medium | Content Cell | +| e.g. The user should be able to leave a comment | e.g as a user, I want to be able to communicate with the other members on the canvas | High, Low or Medium | Content Cell | -## Details +# Out of Scope +List the things that are out of cope or might be revisited after the first release. +- Item 1 +- Item 2 +- Item 3 -What are the specifications of the implementation? -Product notes, designs etc. +# Developer Handoff Document in Figma +Link to the developer Handoff Document: + +# Questions +| Question | Answer | Date Answered | +| ------------- | ------------- | ------------- | +| e.g. How might we ensure that the comments section doesn't cover the canvas | Content Cell | Content Cell | +| Content Cell | Content Cell | Content Cell | diff --git a/.github/config.json b/.github/config.json index c16f3b48f2..48b03bac49 100644 --- a/.github/config.json +++ b/.github/config.json @@ -185,6 +185,11 @@ "color": "79e53b", "description": "An unexpected or annoying bug" }, + "List Widget": { + "name": "List Widget", + "color": "79e53b", + "description": "Issues Related to the list widget" + }, "Map Widget": { "name": "Map Widget", "color": "7eef7a", @@ -564,6 +569,11 @@ "type": "hasLabel", "value": true }, + { + "label": "List Widget", + "type": "hasLabel", + "value": true + }, { "label": "Map Widget", "type": "hasLabel", diff --git a/.github/workflows/client-build.yml b/.github/workflows/client-build.yml index b9c79b1e5c..396b2be215 100644 --- a/.github/workflows/client-build.yml +++ b/.github/workflows/client-build.yml @@ -99,7 +99,7 @@ jobs: - name: Run the jest tests if: github.event_name == 'pull_request' - uses: hetunandu/Jest-Coverage-Diff@fix/new-delete-file + uses: hetunandu/Jest-Coverage-Diff@feature/better-report-comments with: fullCoverageDiff: false runCommand: cd app/client && REACT_APP_ENVIRONMENT=${{steps.vars.outputs.REACT_APP_ENVIRONMENT}} yarn run test:unit diff --git a/.github/workflows/external-client-test.yml b/.github/workflows/external-client-test.yml index 2b41a166fa..f83389788e 100644 --- a/.github/workflows/external-client-test.yml +++ b/.github/workflows/external-client-test.yml @@ -38,7 +38,7 @@ jobs: - name: Set up JDK 1.11 uses: actions/setup-java@v1 with: - java-version: 1.11 + java-version: "11.0.10" # Retrieve maven dependencies from cache. After a successful run, these dependencies are cached again - name: Cache maven dependencies diff --git a/.github/workflows/server.yml b/.github/workflows/server.yml index d5a79b2dd9..3ac0df6d93 100644 --- a/.github/workflows/server.yml +++ b/.github/workflows/server.yml @@ -50,7 +50,7 @@ jobs: - name: Set up JDK 1.11 uses: actions/setup-java@v1 with: - java-version: 1.11 + java-version: "11.0.10" # Retrieve maven dependencies from cache. After a successful run, these dependencies are cached again - name: Cache maven dependencies diff --git a/.gitignore b/.gitignore index e7782c5131..2d1d9bda93 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ .idea *.iml .env +.vscode/* # test coverage -coverage-summary.json \ No newline at end of file +coverage-summary.json diff --git a/README.md b/README.md index 7488dc2567..2f0080c996 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@

- Try Online Sandbox + Try Online Sandbox

Documentation @@ -63,7 +63,7 @@ But if you’d rather check out some real applications that can be built with Ap The following steps introduce you to building a simple user-list dashboard on Appsmith. -1. [Sign up on Appsmith Cloud](https://bit.ly/appsmith-signup-github) or [Deploy Appsmith](https://docs.appsmith.com/setup). +1. [Sign up on Appsmith Cloud](https://app.appsmith.com/signup?utm_source=github&utm_medium=social&utm_content=website&utm_campaign=null&utm_term=website) or [Deploy Appsmith](https://docs.appsmith.com/setup). 2. Create a new app within the organization that has already been created for you. 3. Click on the `+` icon next to the `Queries` section to add a new query in the mock database 1. Name the query `usersQuery`. @@ -79,12 +79,12 @@ Connect your own data to build apps for your team. [Read more here.](https://doc ## 📚 Tutorials 1. [Building an Admin Panel on MongoDB using Appsmith](https://blog.appsmith.com/building-an-admin-panel-with-mongodb-using-appsmith) ([Video](https://www.youtube.com/watch?v=tisUaIgI86k)) -2. [Building a customer support dashboard in Appsmith](https://www.youtube.com/watch?v=-O_6OLREEzo&t=272s) -3. [Running CI/CD jobs manually using Appsmith](https://blog.appsmith.com/how-to-run-manual-jobs-in-gitlab-cicd) ([Video](https://www.youtube.com/watch?v=CYdeJcD4I8A)) -4. [Building a calendly clone in Appsmith](https://blog.appsmith.com/how-to-build-a-calendly-clone-in-30-minutes) -5. [Building Internal Tools with Appsmith](https://youtu.be/eYYYfuW-kEE) `Community` -6. [Building an Issue Tracker with Appsmith](https://dev.to/pjmantoss/how-to-build-an-issue-tracker-with-appsmith-204e) `Community` - +2. [Building a Customer Support Dashboard in Appsmith](https://www.youtube.com/watch?v=-O_6OLREEzo&t=272s) +3. [Building a Store Catalogue Management System using Appsmith and GraphQL](https://blog.appsmith.com/building-a-store-catalogue-management-system-using-appsmith-and-graphql) +4. [Running CI/CD Jobs Manually using Appsmith](https://blog.appsmith.com/how-to-run-manual-jobs-in-gitlab-cicd) ([Video](https://www.youtube.com/watch?v=CYdeJcD4I8A)) +5. [Building a Calendly Clone in Appsmith](https://blog.appsmith.com/how-to-build-a-calendly-clone-in-30-minutes) +6. [Building Internal Tools with Appsmith](https://youtu.be/eYYYfuW-kEE) `Community` +7. [Building an Issue Tracker with Appsmith](https://dev.to/pjmantoss/how-to-build-an-issue-tracker-with-appsmith-204e) `Community` ## 📕 Support & Troubleshooting diff --git a/app/client/.eslintrc.json b/app/client/.eslintrc.json index 0e6d1239e1..fe0ab77466 100644 --- a/app/client/.eslintrc.json +++ b/app/client/.eslintrc.json @@ -28,7 +28,13 @@ "react/prop-types": 0, "@typescript-eslint/explicit-module-boundary-types": 0, "cypress/no-unnecessary-waiting": 0, - "cypress/no-assigning-return-values": 0 + "cypress/no-assigning-return-values": 0, + "react/function-component-definition": "warn", + "react/jsx-boolean-value": "error", + "react/self-closing-comp": "error", + "react/jsx-sort-props": "error", + "react/jsx-fragments": "error", + "react/jsx-no-useless-fragment": "error" }, "settings": { "react": { diff --git a/app/client/.gitignore b/app/client/.gitignore index c5e430d2db..f801f7de68 100755 --- a/app/client/.gitignore +++ b/app/client/.gitignore @@ -43,3 +43,5 @@ storybook-static/* build-storybook.log .eslintcache +.vscode +TODO \ No newline at end of file diff --git a/app/client/README.md b/app/client/README.md index 0ae785bd51..2a275ea504 100755 --- a/app/client/README.md +++ b/app/client/README.md @@ -7,4 +7,3 @@ This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). For details on setting up your development machine, please refer to the [Setup Guide](https://github.com/appsmithorg/appsmith/blob/release/contributions/ClientSetup.md) - diff --git a/app/client/cypress/.eslintrc.json b/app/client/cypress/.eslintrc.json index cb810a1722..2772e19d62 100644 --- a/app/client/cypress/.eslintrc.json +++ b/app/client/cypress/.eslintrc.json @@ -2,6 +2,9 @@ "env": { "cypress/globals": true }, + "rules": { + "cypress/no-unnecessary-waiting": 0 + }, "extends": [ "plugin:cypress/recommended" ] diff --git a/app/client/cypress/fixtures/ChartTextDsl.json b/app/client/cypress/fixtures/ChartTextDsl.json index 12a7f6880d..ccaf55ba21 100644 --- a/app/client/cypress/fixtures/ChartTextDsl.json +++ b/app/client/cypress/fixtures/ChartTextDsl.json @@ -58,7 +58,9 @@ "chartType": "LINE_CHART", "chartName": "Sales on working days", "allowHorizontalScroll": false, - "chartData": [{"seriesName":"Sales","data":""}], + "chartData": { + "some-random-id": {"seriesName":"Sales","data": []} + }, "xAxisName": "Last Week", "yAxisName": "Total Order Revenue $", "type": "CHART_WIDGET", diff --git a/app/client/cypress/fixtures/example.json b/app/client/cypress/fixtures/example.json index 3e446160e2..598a710a31 100644 --- a/app/client/cypress/fixtures/example.json +++ b/app/client/cypress/fixtures/example.json @@ -102,6 +102,7 @@ "AlertModalName": "Alert_Modal", "FormModalName": "Form_Modal", "TextLabelValue": "Test Text Label", + "TextLabelValueScrollable": "Test Text Label to check scroll feature", "TextName": "TestTextBox", "TextLabel": "Paragraph", "TextBody": "Heading 2", diff --git a/app/client/cypress/fixtures/executionParamsDsl.json b/app/client/cypress/fixtures/executionParamsDsl.json index 32de9477c0..a98fadca24 100644 --- a/app/client/cypress/fixtures/executionParamsDsl.json +++ b/app/client/cypress/fixtures/executionParamsDsl.json @@ -114,7 +114,7 @@ "inputType": "TEXT", "label": "Endpoint", "widgetName": "EndpointInput", - "defaultText": "todos", + "defaultText": "offers", "type": "INPUT_WIDGET", "isLoading": false, "parentColumnSpace": 71.75, diff --git a/app/client/cypress/fixtures/listdsl.json b/app/client/cypress/fixtures/listdsl.json new file mode 100644 index 0000000000..25c0fb517a --- /dev/null +++ b/app/client/cypress/fixtures/listdsl.json @@ -0,0 +1,161 @@ +{ + "dsl": { + "widgetName": "MainContainer", + "backgroundColor": "none", + "rightColumn": 1224, + "snapColumns": 16, + "detachFromLayout": true, + "widgetId": "0", + "topRow": 0, + "bottomRow": 1280, + "containerStyle": "none", + "snapRows": 33, + "parentRowSpace": 1, + "type": "CANVAS_WIDGET", + "canExtend": true, + "version": 9, + "minHeight": 1292, + "parentColumnSpace": 1, + "dynamicBindingPathList": [], + "leftColumn": 0, + "children": [ + { + "isVisible": true, + "enhancements": true, + "backgroundColor": "", + "gridType": "vertical", + "gridGap": 0, + "items": "[\n {\n \"id\": 1,\n \"email\": \"michael.lawson@reqres.in\",\n \"first_name\": \"Michael\",\n \"last_name\": \"Lawson\",\n \"avatar\": \"https://reqres.in/img/faces/7-image.jpg\"\n },\n {\n \"id\": 2,\n \"email\": \"lindsay.ferguson@reqres.in\",\n \"first_name\": \"Lindsay\",\n \"last_name\": \"Ferguson\",\n \"avatar\": \"https://reqres.in/img/faces/8-image.jpg\"\n },\n {\n \"id\": 3,\n \"email\": \"brock.lesnar@reqres.in\",\n \"first_name\": \"Brock\",\n \"last_name\": \"Lesnar\",\n \"avatar\": \"https://reqres.in/img/faces/8-image.jpg\"\n }\n]", + "widgetName": "List1", + "children": [ + { + "isVisible": true, + "widgetName": "Canvas1", + "containerStyle": "none", + "canExtend": false, + "detachFromLayout": true, + "dropDisabled": true, + "children": [ + { + "isVisible": true, + "backgroundColor": "white", + "widgetName": "Container1", + "containerStyle": "card", + "children": [ + { + "isVisible": true, + "widgetName": "Canvas2", + "containerStyle": "none", + "canExtend": false, + "detachFromLayout": true, + "children": [ + { + "isVisible": true, + "text": "Label", + "textStyle": "LABEL", + "textAlign": "LEFT", + "widgetName": "Text1", + "type": "TEXT_WIDGET", + "isLoading": false, + "parentColumnSpace": 32, + "parentRowSpace": 40, + "leftColumn": 2, + "rightColumn": 6, + "topRow": 0, + "bottomRow": 1, + "parentId": "dinv2tsatk", + "widgetId": "k6ct7dxg4w" + }, + { + "isVisible":true, + "text":"Submit", + "buttonStyle":"PRIMARY_BUTTON", + "widgetName":"Button1", + "isDisabled":false, + "isDefaultClickDisabled":true, + "version":1, + "type":"BUTTON_WIDGET", + "isLoading":false, + "parentColumnSpace":29.25, + "parentRowSpace":40, + "leftColumn":6, + "rightColumn":8, + "topRow":1, + "bottomRow":2, + "parentId":"dinv2tsatk", + "widgetId":"fuw9p7cuek" + } + ], + "minHeight": null, + "type": "CANVAS_WIDGET", + "isLoading": false, + "parentColumnSpace": 1, + "parentRowSpace": 1, + "leftColumn": 0, + "rightColumn": null, + "topRow": 0, + "bottomRow": null, + "parentId": "4ruj7xl5ri", + "widgetId": "dinv2tsatk" + } + ], + "dragDisabled": true, + "isDeletable": false, + "disablePropertyPane": true, + "type": "CONTAINER_WIDGET", + "isLoading": false, + "leftColumn": 0, + "rightColumn": 16, + "topRow": 0, + "bottomRow": 4, + "parentId": "0pvmmqr77m", + "widgetId": "4ruj7xl5ri" + } + ], + "minHeight": 400, + "type": "CANVAS_WIDGET", + "isLoading": false, + "parentColumnSpace": 1, + "parentRowSpace": 1, + "leftColumn": 0, + "rightColumn": 592, + "topRow": 0, + "bottomRow": 400, + "parentId": "5bwz8xcvhj", + "widgetId": "0pvmmqr77m" + } + ], + "type": "LIST_WIDGET", + "isLoading": false, + "parentColumnSpace": 74, + "parentRowSpace": 40, + "leftColumn": 0, + "rightColumn": 8, + "topRow": 0, + "bottomRow": 10, + "parentId": "0", + "widgetId": "5bwz8xcvhj", + "dynamicBindingPathList": [], + "template": { + "Text1": { + "isVisible": true, + "text": "Label", + "textStyle": "LABEL", + "textAlign": "LEFT", + "widgetName": "Text1", + "type": "TEXT_WIDGET", + "isLoading": false, + "parentColumnSpace": 32, + "parentRowSpace": 40, + "leftColumn": 0, + "rightColumn": 4, + "topRow": 0, + "bottomRow": 1, + "parentId": "dinv2tsatk", + "widgetId": "k6ct7dxg4w" + } + } + } + ] + } +} diff --git a/app/client/cypress/fixtures/testFile2.mov b/app/client/cypress/fixtures/testFile2.mov new file mode 100644 index 0000000000..af5b36c705 Binary files /dev/null and b/app/client/cypress/fixtures/testFile2.mov differ diff --git a/app/client/cypress/fixtures/textDsl.json b/app/client/cypress/fixtures/textDsl.json new file mode 100644 index 0000000000..d9821d17da --- /dev/null +++ b/app/client/cypress/fixtures/textDsl.json @@ -0,0 +1,45 @@ +{ + "dsl": { + "widgetName": "MainContainer", + "backgroundColor": "none", + "rightColumn": 966, + "snapColumns": 16, + "detachFromLayout": true, + "widgetId": "0", + "topRow": 0, + "bottomRow": 240, + "containerStyle": "none", + "snapRows": 33, + "parentRowSpace": 1, + "type": "CANVAS_WIDGET", + "canExtend": true, + "version": 16, + "minHeight": 280, + "parentColumnSpace": 1, + "dynamicTriggerPathList": [], + "dynamicBindingPathList": [], + "leftColumn": 0, + "children": [ + { + "isVisible": true, + "text": "Label", + "fontSize": "PARAGRAPH", + "fontStyle": "BOLD", + "textAlign": "LEFT", + "textColor": "#231F20", + "widgetName": "Text1", + "version": 1, + "type": "TEXT_WIDGET", + "isLoading": false, + "parentColumnSpace": 57.875, + "parentRowSpace": 40, + "leftColumn": 4, + "rightColumn": 8, + "topRow": 1, + "bottomRow": 2, + "parentId": "0", + "widgetId": "266vj9u1mr" + } + ] + } +} \ No newline at end of file diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ActionExecution/ExecutionParams_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ActionExecution/ExecutionParams_spec.js index 32505c69b9..6e4a234a3b 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ActionExecution/ExecutionParams_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ActionExecution/ExecutionParams_spec.js @@ -1,33 +1,56 @@ const dsl = require("../../../../fixtures/executionParamsDsl.json"); const publishPage = require("../../../../locators/publishWidgetspage.json"); const commonlocators = require("../../../../locators/commonlocators.json"); +const queryLocators = require("../../../../locators/QueryEditor.json"); +const datasource = require("../../../../locators/DatasourcesEditor.json"); describe("API Panel Test Functionality", function() { + let datasourceName; before(() => { cy.addDsl(dsl); }); - it("Will pass execution params", function() { - // Create the Api - cy.NavigateToAPI_Panel(); - cy.CreateAPI("MultiApi"); - cy.enterDatasourceAndPath( - "https://jsonplaceholder.typicode.com/", - "{{this.params.endpoint || 'posts'}}", - ); - cy.WaitAutoSave(); - // Run it - cy.RunAPI(); + beforeEach(() => { + cy.startRoutesForDatasource(); + }); + it("Create a postgres datasource", function() { + cy.NavigateToDatasourceEditor(); + cy.get(datasource.PostgreSQL).click(); + cy.getPluginFormsAndCreateDatasource(); + + cy.fillPostgresDatasourceForm(); + + cy.testSaveDatasource(); + + cy.get("@createDatasource").then((httpResponse) => { + datasourceName = httpResponse.response.body.data.name; + }); + }); + it("Create and runs query", () => { + cy.NavigateToQueryEditor(); + cy.contains(".t--datasource-name", datasourceName) + .find(queryLocators.createQuery) + .click(); + + cy.get(queryLocators.templateMenu).click(); + cy.get(".CodeMirror textarea") + .first() + .focus() + .type("select * from {{ this.params.tableName || 'users' }} limit 10", { + force: true, + parseSpecialCharSequences: false, + }); + cy.WaitAutoSave(); + cy.runQuery(); + }); + it("Will pass execution params", function() { // Bind the table cy.SearchEntityandOpen("Table1"); - cy.testJsontext("tabledata", "{{MultiApi.data", false); + cy.testJsontext("tabledata", "{{Query1.data}}"); // Assert 'posts' data (default) - cy.readTabledataPublish("0", "2").then((cellData) => { - expect(cellData).to.be.equal( - "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", - ); + cy.readTabledataPublish("0", "1").then((cellData) => { + expect(cellData).to.be.equal("Ximenez Kainz"); }); - // Choose static button cy.SearchEntityandOpen("StaticButton"); // toggle js of onClick @@ -37,8 +60,7 @@ describe("API Panel Test Functionality", function() { // Bind with MultiApi with static value cy.testJsontext( "onclick", - "{{MultiApi.run(undefined, undefined, { endpoint: 'users", - false, + "{{Query1.run(undefined, undefined, { tableName: 'orders' })}}", ); cy.get(commonlocators.editPropCrossButton).click({ force: true }); @@ -51,8 +73,7 @@ describe("API Panel Test Functionality", function() { // Bind with MultiApi with dynamicValue value cy.testJsontext( "onclick", - "{{MultiApi.run(undefined, undefined, { endpoint: EndpointInput.text", - false, + "{{Query1.run(undefined, undefined, { tableName: EndpointInput.text })}}", ); // Publish the app @@ -60,10 +81,8 @@ describe("API Panel Test Functionality", function() { cy.wait("@postExecute"); // Assert on load data in table - cy.readTabledataPublish("0", "2").then((cellData) => { - expect(cellData).to.be.equal( - "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", - ); + cy.readTabledataPublish("0", "1").then((cellData) => { + expect(cellData).to.be.equal("Ximenez Kainz"); }); // Click Static button @@ -74,7 +93,7 @@ describe("API Panel Test Functionality", function() { cy.wait(2000); // Assert statically bound "users" data cy.readTabledataPublish("1", "1").then((cellData) => { - expect(cellData).to.be.equal("Ervin Howell"); + expect(cellData).to.be.equal("OUT_FOR_DELIVERY"); }); // Click dynamic button @@ -84,8 +103,8 @@ describe("API Panel Test Functionality", function() { // eslint-disable-next-line cypress/no-unnecessary-waiting cy.wait(2000); // Assert dynamically bound "todos" data - cy.readTabledataPublish("0", "2").then((cellData) => { - expect(cellData).to.be.equal("delectus aut autem"); + cy.readTabledataPublish("0", "1").then((cellData) => { + expect(cellData).to.be.equal("DISCOUNT"); }); }); }); diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ApiPaneTests/API_all_sidebar_actions_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ApiPaneTests/API_all_sidebar_actions_spec.js index b09e52daff..b718d908aa 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ApiPaneTests/API_all_sidebar_actions_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ApiPaneTests/API_all_sidebar_actions_spec.js @@ -15,6 +15,11 @@ describe("API Panel Test Functionality ", function() { .click({ force: true }); cy.CopyAPIToHome(); cy.GlobalSearchEntity("FirstAPICopy"); + // click on learn how link + cy.get(".t--learn-how-apis-link").click(); + // this should open in a global search modal + cy.get(commonlocators.globalSearchModal); + cy.get("body").click(0, 0); cy.DeleteAPIFromSideBar(); }); }); diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Binding/BindApi_withPageload_Input_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Binding/BindApi_withPageload_Input_spec.js index f6057bc596..163331e028 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Binding/BindApi_withPageload_Input_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Binding/BindApi_withPageload_Input_spec.js @@ -1,9 +1,7 @@ const testdata = require("../../../../fixtures/testdata.json"); const apiwidget = require("../../../../locators/apiWidgetslocator.json"); const commonlocators = require("../../../../locators/commonlocators.json"); -const formWidgetsPage = require("../../../../locators/FormWidgets.json"); const dsl = require("../../../../fixtures/MultipleInput.json"); -const pages = require("../../../../locators/Pages.json"); const widgetsPage = require("../../../../locators/Widgets.json"); const publish = require("../../../../locators/publishWidgetspage.json"); diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Debugger/Logs_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Debugger/Logs_spec.js new file mode 100644 index 0000000000..e884caf535 --- /dev/null +++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Debugger/Logs_spec.js @@ -0,0 +1,14 @@ +const dsl = require("../../../../fixtures/buttondsl.json"); + +describe("Debugger logs", function() { + before(() => { + cy.addDsl(dsl); + }); + it("Modifying widget properties should log the same", function() { + cy.openPropertyPane("buttonwidget"); + cy.testJsontext("label", "Test"); + + cy.get(".t--debugger").click(); + cy.get(".t--debugger-log-state").contains("Test"); + }); +}); diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/DisplayWidgets/Modal_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/DisplayWidgets/Modal_spec.js index 9bb36c8c10..ba257c5ae2 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/DisplayWidgets/Modal_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/DisplayWidgets/Modal_spec.js @@ -1,5 +1,4 @@ const dsl = require("../../../../fixtures/ModalDsl.json"); -const publishPage = require("../../../../locators/publishWidgetspage.json"); const explorer = require("../../../../locators/explorerlocators.json"); describe("Modal Widget Functionality", function() { diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/DisplayWidgets/Table_PropertyPane_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/DisplayWidgets/Table_PropertyPane_spec.js index 8329b92cda..1f2035eeab 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/DisplayWidgets/Table_PropertyPane_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/DisplayWidgets/Table_PropertyPane_spec.js @@ -10,21 +10,8 @@ describe("Table Widget property pane feature validation", function() { cy.addDsl(dsl); }); - it("Check collapse section feature in property pane", function() { - cy.openPropertyPane("tablewidget"); - //check open and collapse - cy.get(commonlocators.collapsesection) - .first() - .should("be.visible") - .click(); - cy.assertControlVisibility("tabledata"); - }); - it("Check open section and column data in property pane", function() { - cy.get(commonlocators.collapsesection) - .scrollIntoView() - .first() - .click(); + cy.openPropertyPane("tablewidget"); cy.tableColumnDataValidation("id"); cy.tableColumnDataValidation("email"); cy.tableColumnDataValidation("userName"); diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/DisplayWidgets/Text_new_feature_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/DisplayWidgets/Text_new_feature_spec.js new file mode 100644 index 0000000000..a35162eca6 --- /dev/null +++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/DisplayWidgets/Text_new_feature_spec.js @@ -0,0 +1,109 @@ +const commonlocators = require("../../../../locators/commonlocators.json"); +const widgetsPage = require("../../../../locators/Widgets.json"); +const publishPage = require("../../../../locators/publishWidgetspage.json"); +const dsl = require("../../../../fixtures/textDsl.json"); +const pages = require("../../../../locators/Pages.json"); + +describe("Text Widget color/font/alignment Functionality", function() { + before(() => { + cy.addDsl(dsl); + }); + + beforeEach(() => { + cy.openPropertyPane("textwidget"); + }); + + it("Text-TextStyle Heading, Text Name Validation", function() { + //changing the Text Name and verifying + cy.widgetText( + this.data.TextName, + widgetsPage.textWidget, + widgetsPage.textWidget + " " + commonlocators.widgetNameTag, + ); + + //Changing the text label + cy.testCodeMirror(this.data.TextLabelValueScrollable); + + cy.ChangeTextStyle( + this.data.TextHeading, + commonlocators.headingTextStyle, + this.data.TextLabelValueScrollable, + ); + cy.wait("@updateLayout"); + cy.PublishtheApp(); + cy.get(commonlocators.headingTextStyle) + .should("have.text", this.data.TextLabelValueScrollable) + .should("have.css", "font-size", "24px"); + cy.get(publishPage.backToEditor).click({ force: true }); + }); + + it("Test to validate text format", function() { + //Changing the Text Style's and validating + cy.get(widgetsPage.italics).click({ force: true }); + cy.readTextDataValidateCSS("font-style", "italic"); + cy.get(widgetsPage.bold).click({ force: true }); + cy.readTextDataValidateCSS("font-weight", "400"); + cy.get(widgetsPage.bold).click({ force: true }); + cy.readTextDataValidateCSS("font-weight", "700"); + cy.get(widgetsPage.italics).click({ force: true }); + cy.readTextDataValidateCSS("font-style", "normal"); + cy.closePropertyPane(); + }); + + it("Test to validate color changes in text and background", function() { + //Changing the Text Style's and validating + cy.get(widgetsPage.textColor) + .first() + .click({ force: true }); + cy.xpath(widgetsPage.greenColor).click(); + // eslint-disable-next-line cypress/no-unnecessary-waiting + cy.wait(500); + cy.wait("@updateLayout"); + cy.readTextDataValidateCSS("color", "rgb(3, 179, 101)"); + cy.get(widgetsPage.textColor) + .clear({ force: true }) + .type("purple", { force: true }); + cy.wait("@updateLayout"); + cy.readTextDataValidateCSS("color", "rgb(128, 0, 128)"); + cy.get(widgetsPage.backgroundColor) + .first() + .click({ force: true }); + // eslint-disable-next-line cypress/no-unnecessary-waiting + cy.wait(500); + cy.xpath(widgetsPage.greenColor) + .first() + .click(); + // eslint-disable-next-line cypress/no-unnecessary-waiting + cy.wait(500); + cy.wait("@updateLayout"); + cy.PublishtheApp(); + cy.get(publishPage.backToEditor).click({ force: true }); + }); + + it("Test to validate text alignment", function() { + cy.get(widgetsPage.centerAlign) + .first() + .click({ force: true }); + cy.readTextDataValidateCSS("text-align", "center"); + cy.get(widgetsPage.rightAlign) + .first() + .click({ force: true }); + cy.readTextDataValidateCSS("text-align", "right"); + cy.get(widgetsPage.leftAlign) + .first() + .click({ force: true }); + cy.readTextDataValidateCSS("text-align", "left"); + cy.closePropertyPane(); + }); + + it("Test to validate enable scroll feature", function() { + cy.get(".t--property-control-enablescroll .bp3-switch").click({ + force: true, + }); + cy.wait("@updateLayout"); + cy.get(commonlocators.headingTextStyle).trigger("mouseover", { + force: true, + }); + cy.get(commonlocators.headingTextStyle).scrollIntoView({ duration: 2000 }); + }); +}); diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/FormWidgets/FilePicker_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/FormWidgets/FilePicker_spec.js index 1a71d138c1..3330821242 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/FormWidgets/FilePicker_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/FormWidgets/FilePicker_spec.js @@ -43,6 +43,29 @@ describe("FilePicker Widget Functionality", function() { cy.get("button").contains("1 files selected"); }); + it("It checks the deletion of filepicker works as expected", function() { + cy.get(commonlocators.filePickerButton).click(); + cy.get(commonlocators.filePickerInput) + .first() + .attachFile("testFile.mov"); + cy.get(commonlocators.filePickerUploadButton).click(); + //eslint-disable-next-line cypress/no-unnecessary-waiting + cy.wait(500); + cy.get("button").contains("1 files selected"); + cy.get(commonlocators.filePickerButton).click(); + //eslint-disable-next-line cypress/no-unnecessary-waiting + cy.wait(200); + cy.get("button.uppy-Dashboard-Item-action--remove").click(); + cy.get("button.uppy-Dashboard-browse").click(); + cy.get(commonlocators.filePickerInput) + .first() + .attachFile("testFile2.mov"); + cy.get(commonlocators.filePickerUploadButton).click(); + //eslint-disable-next-line cypress/no-unnecessary-waiting + cy.wait(500); + cy.get("button").contains("1 files selected"); + }); + afterEach(() => { // put your clean up code if any }); diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/GlobalSearch/GlobalSearch_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/GlobalSearch/GlobalSearch_spec.js index 179a20bfce..3f60f9e819 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/GlobalSearch/GlobalSearch_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/GlobalSearch/GlobalSearch_spec.js @@ -54,14 +54,12 @@ describe("GlobalSearch", function() { cy.get(commonlocators.globalSearchTrigger).click({ force: true }); // eslint-disable-next-line cypress/no-unnecessary-waiting cy.wait(1000); - cy.get(commonlocators.globalSearchClearInput).click({ force: true }); cy.get(commonlocators.globalSearchInput).type("Page1"); cy.get("body").type("{enter}"); cy.get(commonlocators.globalSearchTrigger).click({ force: true }); // eslint-disable-next-line cypress/no-unnecessary-waiting cy.wait(1000); - cy.get(commonlocators.globalSearchClearInput).click({ force: true }); cy.get(commonlocators.globalSearchInput).type("SomeApi"); cy.get("body").type("{enter}"); cy.window() @@ -90,14 +88,12 @@ describe("GlobalSearch", function() { cy.get(commonlocators.globalSearchTrigger).click({ force: true }); // eslint-disable-next-line cypress/no-unnecessary-waiting cy.wait(1000); // modal open transition should be deterministic - cy.get(commonlocators.globalSearchClearInput).click({ force: true }); cy.get(commonlocators.globalSearchInput).type("Page1"); cy.get("body").type("{enter}"); cy.get(commonlocators.globalSearchTrigger).click({ force: true }); // eslint-disable-next-line cypress/no-unnecessary-waiting cy.wait(1000); // modal open transition should be deterministic - cy.get(commonlocators.globalSearchClearInput).click({ force: true }); cy.get(commonlocators.globalSearchInput).type(expectedDatasource.name); cy.get("body").type("{enter}"); cy.location().should((loc) => { @@ -111,7 +107,6 @@ describe("GlobalSearch", function() { cy.get(commonlocators.globalSearchTrigger).click({ force: true }); // eslint-disable-next-line cypress/no-unnecessary-waiting cy.wait(1000); - cy.get(commonlocators.globalSearchClearInput).click({ force: true }); cy.get(commonlocators.globalSearchInput).type("Page1"); cy.get("body").type("{enter}"); cy.window() diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/LayoutWidgets/Container_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/LayoutWidgets/Container_spec.js index 1729993c2d..883257100f 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/LayoutWidgets/Container_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/LayoutWidgets/Container_spec.js @@ -22,10 +22,13 @@ describe("Container Widget Functionality", function() { /** * @param{Text} Random Colour */ - cy.testCodeMirror(this.data.colour); + cy.get(widgetsPage.backgroundcolorPicker) + .first() + .click({ force: true }); + cy.xpath(widgetsPage.greenColor).click(); cy.get(widgetsPage.containerD) .should("have.css", "background-color") - .and("eq", this.data.rgbValue); + .and("eq", "rgb(3, 179, 101)"); /** * @param{toggleButton Css} Assert to be checked */ @@ -41,7 +44,7 @@ describe("Container Widget Functionality", function() { cy.get(widgetsPage.containerD) .eq(0) .should("have.css", "background-color") - .and("eq", this.data.rgbValue); + .and("eq", "rgb(3, 179, 101)"); }); afterEach(() => { // put your clean up code if any diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/QueryPaneTests/Datasourcedocs_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/QueryPaneTests/Datasourcedocs_spec.js new file mode 100644 index 0000000000..85badafaa2 --- /dev/null +++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/QueryPaneTests/Datasourcedocs_spec.js @@ -0,0 +1,56 @@ +const datasource = require("../../../../locators/DatasourcesEditor.json"); +const queryLocators = require("../../../../locators/QueryEditor.json"); +const commonlocators = require("../../../../locators/commonlocators.json"); + +describe("Check datasource doc links", function() { + let postgresDatasourceName; + + beforeEach(() => { + cy.startRoutesForDatasource(); + }); + + it("Create postgres datasource", function() { + cy.NavigateToDatasourceEditor(); + cy.get(datasource.PostgreSQL).click(); + cy.generateUUID().then((uid) => { + postgresDatasourceName = uid; + + cy.get(".t--edit-datasource-name").click(); + cy.get(".t--edit-datasource-name input") + .clear() + .type(postgresDatasourceName, { force: true }) + .should("have.value", postgresDatasourceName) + .blur(); + }); + cy.wait("@saveDatasource").should( + "have.nested.property", + "response.body.responseMeta.status", + 200, + ); + cy.fillPostgresDatasourceForm(); + cy.testSaveDatasource(); + }); + + it("Check that documentation opens global modal", function() { + cy.NavigateToQueryEditor(); + + cy.contains(".t--datasource-name", postgresDatasourceName) + .find(queryLocators.createQuery) + .click(); + + cy.get(".t--datasource-documentation-link").click(); + cy.get(commonlocators.globalSearchModal); + cy.get("body").click(0, 0); + }); + + it("Delete the query and datasources", function() { + cy.get(queryLocators.deleteQuery).click(); + cy.wait("@deleteAction").should( + "have.nested.property", + "response.body.responseMeta.status", + 200, + ); + + cy.deleteDatasource(postgresDatasourceName); + }); +}); diff --git a/app/client/cypress/integration/Smoke_TestSuite/LayoutWidgets/List_spec.js b/app/client/cypress/integration/Smoke_TestSuite/LayoutWidgets/List_spec.js new file mode 100644 index 0000000000..8221072b87 --- /dev/null +++ b/app/client/cypress/integration/Smoke_TestSuite/LayoutWidgets/List_spec.js @@ -0,0 +1,89 @@ +const commonlocators = require("../../../locators/commonlocators.json"); +const widgetsPage = require("../../../locators/Widgets.json"); +const dsl = require("../../../fixtures/listdsl.json"); +const publishPage = require("../../../locators/publishWidgetspage.json"); + +describe("Container Widget Functionality", function() { + const items = JSON.parse(dsl.dsl.children[0].items); + + before(() => { + cy.addDsl(dsl); + }); + + it("checks if list shows correct no. of items", function() { + cy.get(commonlocators.containerWidget).then(function($lis) { + expect($lis).to.have.length(2); + }); + }); + + it("checks currentItem binding", function() { + cy.SearchEntityandOpen("Text1"); + cy.getCodeMirror().then(($cm) => { + cy.get(".CodeMirror textarea") + .first() + .type(`{{currentItem.first_name}}`, { + force: true, + parseSpecialCharSequences: false, + }); + }); + + cy.wait(1000); + + cy.closePropertyPane(); + + cy.get(commonlocators.TextInside).then(function($lis) { + expect($lis.eq(0)).to.contain(items[0].first_name); + expect($lis.eq(1)).to.contain(items[1].first_name); + }); + }); + + it("checks button action", function() { + cy.SearchEntityandOpen("Button1"); + cy.getCodeMirror().then(($cm) => { + cy.get(".CodeMirror textarea") + .first() + .type(`{{currentItem.first_name}}`, { + force: true, + parseSpecialCharSequences: false, + }); + }); + cy.addAction("{{currentItem.first_name}}"); + + cy.PublishtheApp(); + + cy.get(`${widgetsPage.widgetBtn}`) + .first() + .click(); + + cy.get(commonlocators.toastmsg).contains(items[0].first_name); + }); + + it("it checks onListItem click action", function() { + cy.get(publishPage.backToEditor).click({ force: true }); + + cy.SearchEntityandOpen("List1"); + cy.addAction("{{currentItem.first_name}}"); + + cy.PublishtheApp(); + + cy.get( + "div[type='LIST_WIDGET'] .t--widget-containerwidget:first-child", + ).click(); + + cy.get(commonlocators.toastmsg).contains(items[0].first_name); + }); + + it("it checks pagination", function() { + // clicking on second pagination button + cy.get(`${commonlocators.paginationButton}-2`).click(); + + // now we are on the second page which shows first the 3rd item in the list + cy.get(commonlocators.TextInside).then(function($lis) { + expect($lis.eq(0)).to.contain(items[2].first_name); + }); + }); + + afterEach(() => { + // put your clean up code if any + }); +}); diff --git a/app/client/cypress/integration/Smoke_TestSuite/ServerSideTests/ApiPaneTests/API_All_Verb_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ServerSideTests/ApiPaneTests/API_All_Verb_spec.js index 84030d93bb..5411c7745f 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ServerSideTests/ApiPaneTests/API_All_Verb_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/ServerSideTests/ApiPaneTests/API_All_Verb_spec.js @@ -184,7 +184,7 @@ describe("API Panel Test Functionality", function() { ); cy.WaitAutoSave(); cy.RunAPI(); - cy.validateRequest(testdata.baseUrl, testdata.methods, testdata.Get); + cy.validateRequest(testdata.baseUrl, testdata.methods, testdata.Get, true); cy.ResponseStatusCheck("5000"); cy.log("Response code check successful"); cy.ResponseCheck("Invalid value for Content-Type"); diff --git a/app/client/cypress/integration/Smoke_TestSuite/ServerSideTests/QueryPane/AddWidget_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ServerSideTests/QueryPane/AddWidget_spec.js index 539900d5dc..281400a1ff 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ServerSideTests/QueryPane/AddWidget_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/ServerSideTests/QueryPane/AddWidget_spec.js @@ -24,7 +24,7 @@ describe("Add widget", function() { .focus() .type("select * from configs"); // eslint-disable-next-line cypress/no-unnecessary-waiting - cy.wait(500); + cy.WaitAutoSave(); cy.get(queryEditor.runQuery).click(); cy.wait("@postExecute").should( "have.nested.property", diff --git a/app/client/cypress/integration/Smoke_TestSuite/ServerSideTests/QueryPane/EmptyDataSource_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ServerSideTests/QueryPane/EmptyDataSource_spec.js index cf8ceae494..b4ce6a9abd 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ServerSideTests/QueryPane/EmptyDataSource_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/ServerSideTests/QueryPane/EmptyDataSource_spec.js @@ -31,10 +31,8 @@ describe("Create a query with a empty datasource, run, save the query", function cy.EvaluateCurrentValue("select * from users limit 10"); cy.runQuery(); - cy.get(".react-tabs p") - .last() - .contains( - "[Missing endpoint., Missing username for authentication., Missing password for authentication.]", - ); + cy.get(".t--query-error").contains( + "[Missing endpoint., Missing username for authentication., Missing password for authentication.]", + ); }); }); diff --git a/app/client/cypress/locators/Widgets.json b/app/client/cypress/locators/Widgets.json index fda4bfc2c6..3e67eecebb 100644 --- a/app/client/cypress/locators/Widgets.json +++ b/app/client/cypress/locators/Widgets.json @@ -65,6 +65,7 @@ "verticalCenter": ".t--icon-tab-CENTER", "verticalBottom": ".t--icon-tab-BOTTOM", "textColor": ".t--property-control-textcolor input", + "backgroundcolorPicker": ".t--property-control-backgroundcolor input", "greenColor": "//div[@color='rgb(3, 179, 101)']", "toggleJsColor": ".t--property-control-textcolor .t--js-toggle", "backgroundColor": ".t--property-control-cellbackground input", diff --git a/app/client/cypress/locators/commonlocators.json b/app/client/cypress/locators/commonlocators.json index d575271bcf..7248cf2091 100644 --- a/app/client/cypress/locators/commonlocators.json +++ b/app/client/cypress/locators/commonlocators.json @@ -100,11 +100,13 @@ "filePickerUploadButton": ".uppy-StatusBar-actionBtn--upload", "filePickerOnFilesSelected": ".t--property-control-onfilesselected", "dataType": ".t--property-control-datatype .bp3-popover-target", - "evaluateMsg": ".t--CodeEditor-evaluatedValue p", + "evaluateMsg": ".t--evaluatedPopup-error", "globalSearchModal": ".t--global-search-modal", "globalSearchInput": ".t--global-search-input", "globalSearchTrigger": ".t--global-search-modal-trigger", "globalSearchClearInput": ".t--global-clear-input", + "containerWidget": ".t--widget-containerwidget", + "paginationButton": ".rc-pagination-item", "switchWidgetActive": ".t--switch-widget-active", "switchWidgetInActive": ".t--switch-widget-inactive", "switchWidgetLoading": ".t--switch-widget-loading" diff --git a/app/client/cypress/manual_TestSuite/new_Table_Spec.js b/app/client/cypress/manual_TestSuite/new_Table_Spec.js index 9e74f08edd..1af26c075a 100644 --- a/app/client/cypress/manual_TestSuite/new_Table_Spec.js +++ b/app/client/cypress/manual_TestSuite/new_Table_Spec.js @@ -12,13 +12,11 @@ describe("Table functionality ", function() { // Navigate to add background colour and Text colour // Ensure the row colour gets overlapped on table colour }); - it("Collapse the tabs of Property pane", function() { // Add a table // Click on the property pane // Collapse the General ,Action and Tab option }); - it("Bind the column with same name", function() { // Add a table // Click on the property pane diff --git a/app/client/cypress/support/commands.js b/app/client/cypress/support/commands.js index fdfd69473f..781a118230 100644 --- a/app/client/cypress/support/commands.js +++ b/app/client/cypress/support/commands.js @@ -577,16 +577,26 @@ Cypress.Commands.add("SaveAndRunAPI", () => { cy.RunAPI(); }); -Cypress.Commands.add("validateRequest", (baseurl, path, verb) => { - cy.xpath(apiwidget.Request) - .should("be.visible") - .click({ force: true }); - cy.xpath(apiwidget.RequestURL).contains(baseurl.concat(path)); - cy.xpath(apiwidget.RequestMethod).contains(verb); - cy.xpath(apiwidget.Responsetab) - .should("be.visible") - .click({ force: true }); -}); +Cypress.Commands.add( + "validateRequest", + (baseurl, path, verb, error = false) => { + cy.get(".react-tabs__tab") + .contains("Logs") + .click(); + + if (!error) { + cy.get(".object-key") + .last() + .contains("request") + .click(); + } + cy.get(".string-value").contains(baseurl.concat(path)); + cy.get(".string-value").contains(verb); + cy.xpath(apiwidget.Responsetab) + .should("be.visible") + .click({ force: true }); + }, +); Cypress.Commands.add("SelectAction", (action) => { cy.get(ApiEditor.ApiVerb) @@ -1409,6 +1419,14 @@ Cypress.Commands.add( }, ); +Cypress.Commands.add("readTextDataValidateCSS", (cssProperty, cssValue) => { + cy.get(commonlocators.headingTextStyle).should( + "have.css", + cssProperty, + cssValue, + ); +}); + Cypress.Commands.add("evaluateErrorMessage", (value) => { cy.get(commonlocators.evaluateMsg) .first() @@ -1921,7 +1939,7 @@ Cypress.Commands.add("deleteDatasource", (datasourceName) => { }); Cypress.Commands.add("runQuery", () => { - cy.get(queryEditor.runQuery).click(); + cy.get(queryEditor.runQuery).click({ force: true }); cy.wait("@postExecute").should( "have.nested.property", "response.body.responseMeta.status", diff --git a/app/client/docker/templates/nginx-app.conf.template b/app/client/docker/templates/nginx-app.conf.template index 07e0ed2601..4b7c5fdf4e 100644 --- a/app/client/docker/templates/nginx-app.conf.template +++ b/app/client/docker/templates/nginx-app.conf.template @@ -47,6 +47,7 @@ server { sub_filter __APPSMITH_INTERCOM_APP_ID__ '${APPSMITH_INTERCOM_APP_ID}'; sub_filter __APPSMITH_MAIL_ENABLED__ '${APPSMITH_MAIL_ENABLED}'; sub_filter __APPSMITH_DISABLE_TELEMETRY__ '${APPSMITH_DISABLE_TELEMETRY}'; + sub_filter __APPSMITH_CLOUD_SERVICES_BASE_URL__ '${APPSMITH_CLOUD_SERVICES_BASE_URL}'; } location /f { diff --git a/app/client/jest.config.js b/app/client/jest.config.js index 43e381ac5f..6599de0964 100644 --- a/app/client/jest.config.js +++ b/app/client/jest.config.js @@ -15,7 +15,7 @@ module.exports = { moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node", "css"], moduleDirectories: ["node_modules", "src", "test"], transformIgnorePatterns: [ - "/node_modules/(?!codemirror|react-dnd|dnd-core|@babel|(@blueprintjs/core/lib/esnext)|(@blueprintjs/core/lib/esm)|@github)", + "/node_modules/(?!codemirror|react-dnd|dnd-core|@babel|(@blueprintjs/core/lib/esnext)|(@blueprintjs/core/lib/esm)|@github|lodash-es)", ], moduleNameMapper: { "\\.(css|less)$": "/test/__mocks__/styleMock.js", @@ -23,6 +23,7 @@ module.exports = { "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "/test/__mocks__/fileMock.js", "^worker-loader!": "/test/__mocks__/workerMock.js", + "^!!raw-loader!": "/test/__mocks__/derivedMock.js", "test/(.*)": "/test/$1", }, globals: { diff --git a/app/client/package.json b/app/client/package.json index 2e3b0c51c6..00fa708665 100644 --- a/app/client/package.json +++ b/app/client/package.json @@ -89,6 +89,7 @@ "popper.js": "^1.15.0", "prettier": "^1.18.2", "prismjs": "^1.23.0", + "rc-pagination": "^3.1.3", "re-reselect": "^3.4.0", "react": "^16.12.0", "react-base-table": "^1.9.1", @@ -131,7 +132,8 @@ "tinycolor2": "^1.4.1", "toposort": "^2.0.2", "ts-loader": "^6.0.4", - "typescript": "^3.9.2", + "tslib": "^2.1.0", + "typescript": "^4.1.3", "unescape-js": "^1.1.4", "url-search-params-polyfill": "^8.0.0", "worker-loader": "^3.0.2", @@ -150,6 +152,7 @@ "start-prod": "REACT_APP_ENVIRONMENT=PRODUCTION craco start", "cytest": "REACT_APP_TESTING=TESTING REACT_APP_ENVIRONMENT=DEVELOPMENT craco start & ./node_modules/.bin/cypress open", "test:unit": "$(npm bin)/jest -b --colors --no-cache --coverage --collectCoverage=true --coverageDirectory='../../' --coverageReporters='json-summary'", + "test:jest": "$(npm bin)/jest --watch", "storybook": "start-storybook -p 9009 -s public", "build-storybook": "build-storybook -s public" }, @@ -179,7 +182,7 @@ "@storybook/preset-create-react-app": "^3.1.4", "@storybook/react": "^5.3.19", "@testing-library/jest-dom": "^5.11.4", - "@testing-library/react": "^11.2.5", + "@testing-library/react": "^11.2.6", "@testing-library/user-event": "^13.1.1", "@types/codemirror": "^0.0.96", "@types/deep-diff": "^1.0.0", @@ -189,14 +192,15 @@ "@types/react-beautiful-dnd": "^11.0.4", "@types/react-select": "^3.0.5", "@types/react-tabs": "^2.3.1", + "@types/react-test-renderer": "^17.0.1", "@types/react-window": "^1.8.2", "@types/redux-form": "^8.1.9", "@types/redux-mock-store": "^1.0.2", "@types/styled-system": "^5.1.9", "@types/tern": "0.22.0", "@types/toposort": "^2.0.3", - "@typescript-eslint/eslint-plugin": "^4.6.0", - "@typescript-eslint/parser": "^4.6.0", + "@typescript-eslint/eslint-plugin": "^4.15.0", + "@typescript-eslint/parser": "^4.15.0", "babel-loader": "^8.1.0", "babel-plugin-styled-components": "^1.10.7", "craco-babel-loader": "^0.1.4", @@ -212,6 +216,7 @@ "eslint-plugin-prettier": "^3.1.4", "eslint-plugin-react": "^7.21.3", "eslint-plugin-react-hooks": "^2.3.0", + "factory.ts": "^0.5.1", "jest-canvas-mock": "^2.3.1", "mocha": "^7.1.0", "mocha-junit-reporter": "^1.23.3", diff --git a/app/client/public/index.html b/app/client/public/index.html index d4e841f00b..558f9ccca9 100755 --- a/app/client/public/index.html +++ b/app/client/public/index.html @@ -36,6 +36,46 @@

diff --git a/app/client/public/privacy-policy.html b/app/client/public/privacy-policy.html index e0938fe862..db20473ea4 100644 --- a/app/client/public/privacy-policy.html +++ b/app/client/public/privacy-policy.html @@ -72,7 +72,7 @@

At appsmith, accessible from www.appsmith.com, one of our main priorities is the privacy of our visitors. This Privacy Policy document contains types of information that is collected and recorded by - appsmith and + appsmith and its "Services" and how we use it.

If you have additional questions or require more information about our Privacy Policy, do not hesitate to @@ -99,13 +99,20 @@

How we use your information

We use the information we collect in various ways, including to: