diff --git a/app/client/cypress/fixtures/datasources.json b/app/client/cypress/fixtures/datasources.json new file mode 100644 index 0000000000..794874c8c5 --- /dev/null +++ b/app/client/cypress/fixtures/datasources.json @@ -0,0 +1,15 @@ +{ + "mongo-host": "ds119422.mlab.com", + "mongo-port": 19422, + "mongo-databaseName": "heroku_bcmprc4k", + "mongo-username": "akash", + "mongo-password": "123wheel", + "mongo-authenticationAuthtype": "SCRAM-SHA-1", + "mongo-sslAuthtype": "No SSL", + "postgres-host": "appsmith-test-db.cgg2px8dsrli.ap-south-1.rds.amazonaws.com", + "postgres-port": 5432, + "postgres-databaseName": "postgres", + "postgres-username": "postgres", + "postgres-password": "qwerty1234", + "restapi-url": "https://my-json-server.typicode.com/typicode/demo/posts" +} \ No newline at end of file diff --git a/app/client/cypress/fixtures/plugins.json b/app/client/cypress/fixtures/plugins.json new file mode 100644 index 0000000000..4ba525dc19 --- /dev/null +++ b/app/client/cypress/fixtures/plugins.json @@ -0,0 +1,4 @@ +{ + "postgresPackageName": "postgres-plugin", + "mongoPackageName": "mongo-plugin" +} \ No newline at end of file diff --git a/app/client/cypress/integration/Smoke_TestSuite/ApiFlow/CreateApiAndDelete_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ApiFlow/CreateApiAndDelete_spec.js index 3bb3c6f493..812b19f887 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ApiFlow/CreateApiAndDelete_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/ApiFlow/CreateApiAndDelete_spec.js @@ -18,7 +18,7 @@ describe("Test Add blank API and delete flow", function() { cy.testDeleteApi(); cy.get(ApiEditor.ApiHomePage).should("be.visible"); cy.get(ApiEditor.formActionButtons).should("not.be.visible"); - cy.get("@deleteApi").then(httpResponse => { + cy.get("@deleteAction").then(httpResponse => { cy.expect(httpResponse.response.body.responseMeta.success).to.eq(true); }); }); diff --git a/app/client/cypress/integration/Smoke_TestSuite/ApiFlow/CurlImportApiAndDelete_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ApiFlow/CurlImportApiAndDelete_spec.js index 62cfbd00a3..4a325c0349 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ApiFlow/CurlImportApiAndDelete_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/ApiFlow/CurlImportApiAndDelete_spec.js @@ -20,7 +20,7 @@ describe("Test curl import api and delete flow", function() { cy.get(ApiEditor.ApiDeleteBtn).click(); cy.get(ApiEditor.ApiDeleteBtn).should("be.disabled"); cy.testDeleteApi(); - cy.get("@deleteApi").then(response => { + cy.get("@deleteAction").then(response => { cy.expect(response.response.body.responseMeta.success).to.eq(true); }); cy.get(ApiEditor.ApiHomePage).should("be.visible"); diff --git a/app/client/cypress/integration/Smoke_TestSuite/Datasources/MongoDatasource_spec.js b/app/client/cypress/integration/Smoke_TestSuite/Datasources/MongoDatasource_spec.js index d9f585dd08..90f1d18133 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/Datasources/MongoDatasource_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/Datasources/MongoDatasource_spec.js @@ -2,7 +2,6 @@ describe("Create, test, save then delete a mongo datasource", function() { it("Create, test, save then delete a mongo datasource", function() { cy.NavigateToDatasourceEditor(); cy.get("@getPlugins").then(httpResponse => { - // console.log(response, "response"); const pluginName = httpResponse.response.body.data.find( plugin => plugin.packageName === "mongo-plugin", ).name; @@ -14,35 +13,7 @@ describe("Create, test, save then delete a mongo datasource", function() { cy.getPluginFormsAndCreateDatasource(); - cy.get(`input[name="datasourceConfiguration.endpoints[0].host"]`).type( - "ds119422.mlab.com", - ); - cy.get(`input[name="datasourceConfiguration.endpoints[0].port"]`).type( - 19422, - ); - cy.get(`input[name="datasourceConfiguration.authentication.databaseName"]`) - .clear() - .type("heroku_bcmprc4k"); - cy.get( - `input[name="datasourceConfiguration.authentication.username"]`, - ).type("akash"); - cy.get( - `input[name="datasourceConfiguration.authentication.password"]`, - ).type("123wheel"); - - cy.get( - "[data-cy=datasourceConfiguration\\.authentication\\.authType]", - ).click(); - cy.contains("SCRAM-SHA-256").click({ - force: true, - }); - - cy.get( - "[data-cy=datasourceConfiguration\\.connection\\.ssl\\.authType]", - ).click(); - cy.contains("No SSL").click({ - force: true, - }); + cy.fillMongoDatasourceForm(); cy.testSaveDeleteDatasource(); }); diff --git a/app/client/cypress/integration/Smoke_TestSuite/Datasources/PostgresDatasource_spec.js b/app/client/cypress/integration/Smoke_TestSuite/Datasources/PostgresDatasource_spec.js index 26e896607e..a7607aedf6 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/Datasources/PostgresDatasource_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/Datasources/PostgresDatasource_spec.js @@ -2,7 +2,6 @@ describe("Create, test, save then delete a postgres datasource", function() { it("Create, test, save then delete a postgres datasource", function() { cy.NavigateToDatasourceEditor(); cy.get("@getPlugins").then(httpResponse => { - // console.log(response, "response"); const pluginName = httpResponse.response.body.data.find( plugin => plugin.packageName === "postgres-plugin", ).name; @@ -14,21 +13,7 @@ describe("Create, test, save then delete a postgres datasource", function() { cy.getPluginFormsAndCreateDatasource(); - cy.get(`input[name="datasourceConfiguration.endpoints[0].host"]`).type( - "appsmith-test-db.cgg2px8dsrli.ap-south-1.rds.amazonaws.com", - ); - cy.get(`input[name="datasourceConfiguration.endpoints[0].port"]`).type( - 5432, - ); - cy.get(`input[name="datasourceConfiguration.authentication.databaseName"]`) - .clear() - .type("postgres"); - cy.get( - `input[name="datasourceConfiguration.authentication.username"]`, - ).type("postgres"); - cy.get( - `input[name="datasourceConfiguration.authentication.password"]`, - ).type("qwerty1234"); + cy.fillPostgresDatasourceForm(); cy.testSaveDeleteDatasource(); }); diff --git a/app/client/cypress/integration/Smoke_TestSuite/Datasources/RestApiDatasource_spec.js b/app/client/cypress/integration/Smoke_TestSuite/Datasources/RestApiDatasource_spec.js index 7824c77d28..7f5b1596ff 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/Datasources/RestApiDatasource_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/Datasources/RestApiDatasource_spec.js @@ -1,8 +1,10 @@ +const datasourceEditor = require("../../../locators/DatasourcesEditor.json"); +const datasourceFormData = require("../../../fixtures/datasources.json"); + describe("Create, test, save then delete a restapi datasource", function() { it("Create, test, save then delete a restapi datasource", function() { cy.NavigateToDatasourceEditor(); cy.get("@getPlugins").then(httpResponse => { - // console.log(response, "response"); const pluginName = httpResponse.response.body.data.find( plugin => plugin.packageName === "restapi-plugin", ).name; @@ -14,9 +16,7 @@ describe("Create, test, save then delete a restapi datasource", function() { cy.getPluginFormsAndCreateDatasource(); - cy.get(`input[name="datasourceConfiguration.url"]`).type( - "https://my-json-server.typicode.com/typicode/demo/posts", - ); + cy.get(datasourceEditor.url).type(datasourceFormData["restapi-url"]); cy.testSaveDeleteDatasource(); }); diff --git a/app/client/cypress/integration/Smoke_TestSuite/QueryPane/MongoDatasource_spec.js b/app/client/cypress/integration/Smoke_TestSuite/QueryPane/MongoDatasource_spec.js new file mode 100644 index 0000000000..9a163a5483 --- /dev/null +++ b/app/client/cypress/integration/Smoke_TestSuite/QueryPane/MongoDatasource_spec.js @@ -0,0 +1,41 @@ +const queryLocators = require("../../../locators/QueryEditor.json"); +const plugins = require("../../../fixtures/plugins.json"); + +describe("Create a query with a mongo datasource, run, save and then delete the query", function() { + it("Create a query with a mongo datasource, run, save and then delete the query", function() { + cy.NavigateToDatasourceEditor(); + cy.get("@getPlugins").then(httpResponse => { + const pluginName = httpResponse.response.body.data.find( + plugin => plugin.packageName === plugins.mongoPackageName, + ).name; + + cy.get(".t--plugin-name") + .contains(pluginName) + .click(); + }); + + cy.getPluginFormsAndCreateDatasource(); + + cy.fillMongoDatasourceForm(); + + cy.testSaveDatasource(); + + cy.NavigateToQueryEditor(); + + cy.get("@createDatasource").then(httpResponse => { + const datasourceName = httpResponse.response.body.data.name; + + cy.get(".t--datasource-name") + .contains(datasourceName) + .click(); + }); + + cy.get(queryLocators.templateMenu).click(); + cy.get(".CodeMirror textarea") + .first() + .focus() + .type(`{"find": "planets"}`, { parseSpecialCharSequences: false }); + + cy.runSaveDeleteQuery(); + }); +}); diff --git a/app/client/cypress/integration/Smoke_TestSuite/QueryPane/PostgreDatasource_spec.js b/app/client/cypress/integration/Smoke_TestSuite/QueryPane/PostgreDatasource_spec.js new file mode 100644 index 0000000000..8928595a45 --- /dev/null +++ b/app/client/cypress/integration/Smoke_TestSuite/QueryPane/PostgreDatasource_spec.js @@ -0,0 +1,40 @@ +const queryLocators = require("../../../locators/QueryEditor.json"); + +describe("Create a query with a postgres datasource, run, save and then delete the query", function() { + it("Create a query with a postgres datasource, run, save and then delete the query", function() { + cy.NavigateToDatasourceEditor(); + cy.get("@getPlugins").then(httpResponse => { + const pluginName = httpResponse.response.body.data.find( + plugin => plugin.packageName === "postgres-plugin", + ).name; + + cy.get(".t--plugin-name") + .contains(pluginName) + .click(); + }); + + cy.getPluginFormsAndCreateDatasource(); + + cy.fillPostgresDatasourceForm(); + + cy.testSaveDatasource(); + + cy.NavigateToQueryEditor(); + + cy.get("@createDatasource").then(httpResponse => { + const datasourceName = httpResponse.response.body.data.name; + + cy.get(".t--datasource-name") + .contains(datasourceName) + .click(); + }); + + cy.get(queryLocators.templateMenu).click(); + cy.get(".CodeMirror textarea") + .first() + .focus() + .type("select * from users"); + + cy.runSaveDeleteQuery(); + }); +}); diff --git a/app/client/cypress/locators/DatasourcesEditor.json b/app/client/cypress/locators/DatasourcesEditor.json index 591e8bfef1..1857c50b78 100644 --- a/app/client/cypress/locators/DatasourcesEditor.json +++ b/app/client/cypress/locators/DatasourcesEditor.json @@ -1,3 +1,11 @@ { - "datasourceEditorIcon": ".t--nav-link-datasource-editor" -} \ No newline at end of file + "datasourceEditorIcon": ".t--nav-link-datasource-editor", + "host": "input[name='datasourceConfiguration.endpoints[0].host']", + "port": "input[name='datasourceConfiguration.endpoints[0].port']", + "databaseName": "input[name='datasourceConfiguration.authentication.databaseName']", + "username": "input[name='datasourceConfiguration.authentication.username']", + "password": "input[name='datasourceConfiguration.authentication.password']", + "authenticationAuthtype": "[data-cy=datasourceConfiguration\\.authentication\\.authType]", + "sslAuthtype": "[data-cy=datasourceConfiguration\\.connection\\.ssl\\.authType]", + "url": "input[name='datasourceConfiguration.url']" +} diff --git a/app/client/cypress/locators/QueryEditor.json b/app/client/cypress/locators/QueryEditor.json new file mode 100644 index 0000000000..1a7dbc1f0c --- /dev/null +++ b/app/client/cypress/locators/QueryEditor.json @@ -0,0 +1,7 @@ +{ + "queryEditorIcon": ".t--nav-link-query-editor", + "templateMenu": ".t--template-menu", + "runQuery": ".t--run-query", + "saveQuery": ".t--save-query", + "deleteQuery": ".t--delete-query" +} diff --git a/app/client/cypress/support/commands.js b/app/client/cypress/support/commands.js index 9bbb58ba44..83f3bbc424 100644 --- a/app/client/cypress/support/commands.js +++ b/app/client/cypress/support/commands.js @@ -2,7 +2,9 @@ const loginPage = require("../locators/LoginPage.json"); const homePage = require("../locators/HomePage.json"); const pages = require("../locators/Pages.json"); const datasourceEditor = require("../locators/DatasourcesEditor.json"); +const datasourceFormData = require("../fixtures/datasources.json"); const commonlocators = require("../locators/commonlocators.json"); +const queryEditor = require("../locators/QueryEditor.json"); const modalWidgetPage = require("../locators/ModalWidget.json"); const widgetsPage = require("../locators/Widgets.json"); const ApiEditor = require("../locators/ApiEditor.json"); @@ -288,7 +290,7 @@ Cypress.Commands.add("testSaveDeleteDatasource", () => { Cypress.Commands.add("testDeleteApi", () => { cy.get(ApiEditor.createBlankApiCard).click({ force: true }); - cy.wait("@deleteApi").should( + cy.wait("@deleteAction").should( "have.nested.property", "response.body.responseMeta.status", 200, @@ -304,6 +306,103 @@ Cypress.Commands.add("importCurl", () => { ); }); +Cypress.Commands.add("NavigateToDatasourceEditor", () => { + cy.get(datasourceEditor.datasourceEditorIcon).click({ force: true }); +}); + +Cypress.Commands.add("NavigateToQueryEditor", () => { + cy.get(queryEditor.queryEditorIcon).click({ force: true }); +}); + +Cypress.Commands.add("testSaveDatasource", () => { + cy.get(".t--test-datasource").click(); + cy.wait("@testDatasource").should( + "have.nested.property", + "response.body.data.success", + true, + ); + + cy.get(".t--save-datasource").click(); + cy.wait("@saveDatasource").should( + "have.nested.property", + "response.body.responseMeta.status", + 200, + ); +}); + +Cypress.Commands.add("fillMongoDatasourceForm", () => { + cy.get(datasourceEditor["host"]).type(datasourceFormData["mongo-host"]); + cy.get(datasourceEditor["port"]).type(datasourceFormData["mongo-port"]); + cy.get(datasourceEditor["databaseName"]) + .clear() + .type(datasourceFormData["mongo-databaseName"]); + cy.get(datasourceEditor["username"]).type( + datasourceFormData["mongo-username"], + ); + cy.get(datasourceEditor["password"]).type( + datasourceFormData["mongo-password"], + ); + + cy.get(datasourceEditor["authenticationAuthtype"]).click(); + cy.contains(datasourceFormData["mongo-authenticationAuthtype"]).click({ + force: true, + }); + + cy.get(datasourceEditor["sslAuthtype"]).click(); + cy.contains(datasourceFormData["mongo-sslAuthtype"]).click({ + force: true, + }); +}); + +Cypress.Commands.add("fillPostgresDatasourceForm", () => { + cy.get(datasourceEditor.host).type(datasourceFormData["postgres-host"]); + cy.get(datasourceEditor.port).type(datasourceFormData["postgres-port"]); + cy.get(datasourceEditor.databaseName) + .clear() + .type(datasourceFormData["postgres-databaseName"]); + cy.get(datasourceEditor.username).type( + datasourceFormData["postgres-username"], + ); + cy.get(datasourceEditor.password).type( + datasourceFormData["postgres-password"], + ); +}); + +Cypress.Commands.add("runSaveDeleteQuery", () => { + cy.get(queryEditor.runQuery).click(); + cy.wait("@executeAction").should( + "have.nested.property", + "response.body.responseMeta.status", + 200, + ); + + cy.get(queryEditor.saveQuery).click(); + cy.wait("@saveQuery").should( + "have.nested.property", + "response.body.responseMeta.status", + 200, + ); + + cy.get(queryEditor.deleteQuery).click(); + cy.wait("@deleteAction").should( + "have.nested.property", + "response.body.responseMeta.status", + 200, + ); +}); + +Cypress.Commands.add("getPluginFormsAndCreateDatasource", () => { + cy.wait("@getPluginForm").should( + "have.nested.property", + "response.body.responseMeta.status", + 200, + ); + cy.wait("@createDatasource").should( + "have.nested.property", + "response.body.responseMeta.status", + 201, + ); +}); Cypress.Commands.add("openPropertyPane", widgetType => { const selector = `.t--draggable-${widgetType}`; cy.get(selector) diff --git a/app/client/cypress/support/index.js b/app/client/cypress/support/index.js index 07c51c2440..381ab64ece 100644 --- a/app/client/cypress/support/index.js +++ b/app/client/cypress/support/index.js @@ -45,7 +45,7 @@ before(function() { cy.route("POST", "/api/v1/actions").as("createNewApi"); cy.route("POST", "/api/v1/import?type=CURL&pageId=*&name=*").as("curlImport"); - cy.route("DELETE", "/api/v1/actions/*").as("deleteApi"); + cy.route("DELETE", "/api/v1/actions/*").as("deleteAction"); cy.route("GET", "/api/v1/marketplace/providers?category=*&page=*&size=*").as( "get3PProviders", ); @@ -54,6 +54,14 @@ before(function() { ); cy.route("POST", "/api/v1/items/addToPage").as("add3PApiToPage"); + cy.route("GET", "/api/v1/plugins/*/form").as("getPluginForm"); + cy.route("POST", "/api/v1/datasources").as("createDatasource"); + cy.route("POST", "/api/v1/datasources/test").as("testDatasource"); + cy.route("PUT", "/api/v1/datasources/*").as("saveDatasource"); + cy.route("DELETE", "/api/v1/datasources/*").as("deleteDatasource"); + + cy.route("PUT", "/api/v1/actions/*").as("saveQuery"); + cy.LogintoApp(loginData.username, loginData.password); cy.generateUUID().then(id => { appId = id; diff --git a/app/client/src/pages/Editor/QueryEditor/Form.tsx b/app/client/src/pages/Editor/QueryEditor/Form.tsx index 5944cf81e9..3d1d914017 100644 --- a/app/client/src/pages/Editor/QueryEditor/Form.tsx +++ b/app/client/src/pages/Editor/QueryEditor/Form.tsx @@ -272,6 +272,7 @@ const QueryEditorForm: React.FC = (props: Props) => { = (props: Props) => { portalClassName="helper-tooltip" > = (props: Props) => { ) : ( = (props: Props) => { /> )} { alt="Datasource" > -

+

{dataSource.name}

diff --git a/app/client/src/pages/Editor/QueryEditor/TemplateMenu.tsx b/app/client/src/pages/Editor/QueryEditor/TemplateMenu.tsx index 3091495f86..58dac8cc7e 100644 --- a/app/client/src/pages/Editor/QueryEditor/TemplateMenu.tsx +++ b/app/client/src/pages/Editor/QueryEditor/TemplateMenu.tsx @@ -68,6 +68,7 @@ class TemplateMenu extends React.Component { return ( { this.nameInput = input; }} diff --git a/app/client/src/sagas/QueryPaneSagas.ts b/app/client/src/sagas/QueryPaneSagas.ts index 61c19a3dd4..fd2161d917 100644 --- a/app/client/src/sagas/QueryPaneSagas.ts +++ b/app/client/src/sagas/QueryPaneSagas.ts @@ -199,7 +199,7 @@ export function* executeQuerySaga( let jsonPathKeys = actionObject.jsonPathKeys; if (dirty) { - action = _.omit(transformRestAction(values), "id") as RestAction; + action = _.omit(values, "id") as RestAction; const actionString = JSON.stringify(action); if (isDynamicValue(actionString)) {