Merge branch 'test/queryActions' into 'release'

Tests for query actions

See merge request theappsmith/internal-tools-client!560
This commit is contained in:
Hetu Nandu 2020-05-11 09:03:46 +00:00
commit 0bcb6c85f2
17 changed files with 244 additions and 58 deletions

View File

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

View File

@ -0,0 +1,4 @@
{
"postgresPackageName": "postgres-plugin",
"mongoPackageName": "mongo-plugin"
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,3 +1,11 @@
{
"datasourceEditorIcon": ".t--nav-link-datasource-editor"
}
"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']"
}

View File

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

View File

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

View File

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

View File

@ -272,6 +272,7 @@ const QueryEditorForm: React.FC<Props> = (props: Props) => {
</DropdownSelect>
<ActionButtons>
<ActionButton
className="t--delete-query"
text="Delete"
accent="error"
loading={isDeleting}
@ -291,6 +292,7 @@ const QueryEditorForm: React.FC<Props> = (props: Props) => {
portalClassName="helper-tooltip"
>
<ActionButton
className="t--run-query"
text="Run"
accent="primary"
loading={isRunning}
@ -316,6 +318,7 @@ const QueryEditorForm: React.FC<Props> = (props: Props) => {
</>
) : (
<ActionButton
className="t--run-query"
text="Run"
loading={isRunning}
accent="secondary"
@ -323,6 +326,7 @@ const QueryEditorForm: React.FC<Props> = (props: Props) => {
/>
)}
<ActionButton
className="t--save-query"
text="Save"
accent="primary"
filled

View File

@ -242,7 +242,10 @@ class QueryHomeScreen extends React.Component<QueryHomeScreenProps> {
alt="Datasource"
></img>
<p className="textBtn" title={dataSource.name}>
<p
className="textBtn t--datasource-name"
title={dataSource.name}
>
{dataSource.name}
</p>
</Card>

View File

@ -68,6 +68,7 @@ class TemplateMenu extends React.Component<Props> {
return (
<Container
className="t--template-menu"
ref={input => {
this.nameInput = input;
}}

View File

@ -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)) {