From 50bc2f69174202ec027b3ca43406c5ee2f708bc9 Mon Sep 17 00:00:00 2001 From: Aishwarya-U-R <91450662+Aishwarya-U-R@users.noreply.github.com> Date: Sun, 19 Mar 2023 01:12:01 +0530 Subject: [PATCH] test: Cypress - Automated tests for Airtable datasource (#21550) ## Description - This PR includes tests for Airtable ds - along with connection & querying & usage of various fields in the query page ## Type of change - New script (non-breaking change which test functionality of Airtable data-source) ## How Has This Been Tested? - Cypress CI runs ## Checklist: ### QA activity: - [X] Added Test Plan Approved label after reviewing all changes --- .../workflows/integration-tests-command.yml | 2 +- app/client/cypress/fixtures/datasources.json | 3 + .../BugTests/AbortAction_Spec.ts | 2 +- .../ClientSideTests/BugTests/Bug14037_Spec.ts | 5 +- .../Datasources/Airtable_Basic_Spec.ts | 361 ++++++++++++++++++ .../Datasources/MsSQL_Basic_Spec.ts | 4 +- .../GenerateCRUD/MySQL1_Spec.ts | 2 +- .../GenerateCRUD/Postgres2_Spec.ts | 2 +- .../MySQL_Datatypes/Basic_Spec.ts | 2 +- .../MySQL_Datatypes/False_Spec.ts | 3 +- .../ServerSideTests/QueryPane/Mongo_Spec.js | 22 +- .../ServerSideTests/QueryPane/Mongo_Spec.ts | 2 +- .../ServerSideTests/QueryPane/S3_1_spec.js | 4 +- .../cypress/support/Pages/AggregateHelper.ts | 12 +- app/client/cypress/support/Pages/ApiPage.ts | 6 - .../cypress/support/Pages/DataSources.ts | 36 +- 16 files changed, 428 insertions(+), 40 deletions(-) create mode 100644 app/client/cypress/integration/Regression_TestSuite/ServerSideTests/Datasources/Airtable_Basic_Spec.ts diff --git a/.github/workflows/integration-tests-command.yml b/.github/workflows/integration-tests-command.yml index 743b5d129f..d8fcafc839 100644 --- a/.github/workflows/integration-tests-command.yml +++ b/.github/workflows/integration-tests-command.yml @@ -162,7 +162,7 @@ jobs: with: issue-number: ${{ github.event.client_payload.pull_request.number }} body: | - The following are new failures, please fix them before merging the PR: \n ${{ env.new_failed_spec_env }} + The following are new failures, please fix them before merging the PR: ${{env.new_failed_spec_env}} # Update check run called "ci-test-result" - name: Mark ci-test-result job as complete diff --git a/app/client/cypress/fixtures/datasources.json b/app/client/cypress/fixtures/datasources.json index 31a84c2c61..3e63bdd628 100644 --- a/app/client/cypress/fixtures/datasources.json +++ b/app/client/cypress/fixtures/datasources.json @@ -47,6 +47,9 @@ "OAuth_AuthUrl": "http://localhost:6001/oauth/authorize", "OAuth_RedirectUrl":"http://localhost/api/v1/datasources/authorize", + "AirtableBase": "appubHrVbovcudwN6", + "AirtableTable":"tblsFCQSskVFf7xNd", + "mockApiUrl":"http://host.docker.internal:5001/v1/mock-api?records=10", "echoApiUrl":"http://host.docker.internal:5001/v1/mock-api/echo", diff --git a/app/client/cypress/integration/Regression_TestSuite/ClientSideTests/BugTests/AbortAction_Spec.ts b/app/client/cypress/integration/Regression_TestSuite/ClientSideTests/BugTests/AbortAction_Spec.ts index 5a69436d4d..001325ed20 100644 --- a/app/client/cypress/integration/Regression_TestSuite/ClientSideTests/BugTests/AbortAction_Spec.ts +++ b/app/client/cypress/integration/Regression_TestSuite/ClientSideTests/BugTests/AbortAction_Spec.ts @@ -31,7 +31,7 @@ describe("Abort Action Execution", function () { "AbortQuery", ); _.dataSources.SetQueryTimeout(0); - _.dataSources.RunQuery(false, false, 0); + _.dataSources.RunQuery({toValidateResponse: false, waitTimeInterval:0}); _.agHelper.GetNClick(_.locators._cancelActionExecution, 0, true); _.agHelper.AssertContains( createMessage(ACTION_EXECUTION_CANCELLED, "AbortQuery"), diff --git a/app/client/cypress/integration/Regression_TestSuite/ClientSideTests/BugTests/Bug14037_Spec.ts b/app/client/cypress/integration/Regression_TestSuite/ClientSideTests/BugTests/Bug14037_Spec.ts index 85e1d5dfaa..fd7a287442 100644 --- a/app/client/cypress/integration/Regression_TestSuite/ClientSideTests/BugTests/Bug14037_Spec.ts +++ b/app/client/cypress/integration/Regression_TestSuite/ClientSideTests/BugTests/Bug14037_Spec.ts @@ -1,13 +1,12 @@ import * as _ from "../../../../support/Objects/ObjectsCore"; +import { Widgets } from "../../../../support/Pages/DataSources"; describe("Error logged when adding a suggested table widget", function () { it("Bug 14037: User gets an error even when table widget is added from the API page successfully", function () { cy.fixture("datasources").then((datasourceFormData: any) => { _.apiPage.CreateAndFillApi(datasourceFormData["mockApiUrl"], "Api1"); _.apiPage.RunAPI(); - - _.apiPage.AddSuggestedWidget("TABLE_WIDGET_V2"); - + _.dataSources.AddSuggesstedWidget(Widgets.Table) _.debuggerHelper.AssertErrorCount(0); }); }); diff --git a/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/Datasources/Airtable_Basic_Spec.ts b/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/Datasources/Airtable_Basic_Spec.ts new file mode 100644 index 0000000000..1d771d9cc9 --- /dev/null +++ b/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/Datasources/Airtable_Basic_Spec.ts @@ -0,0 +1,361 @@ +import * as _ from "../../../../support/Objects/ObjectsCore"; +import datasourceFormData from "../../../../fixtures/datasources.json"; + +let dsName: any, jsonSpecies: any, offset: any, insertedRecordId: any; +describe("Validate Airtable Ds", () => { + before("Create a new Airtable DS", () => { + _.dataSources.CreateDataSource("Airtable", true, false); + cy.get("@dsName").then(($dsName) => { + dsName = $dsName; + }); + }); + + it("1. Validate List Records", () => { + var specieslist = new Array(); + _.dataSources.CreateQueryAfterDSSaved(); + + //List all records + _.dataSources.ValidateNSelectDropdown( + "Commands", + "Please select an option.", + "List Records", + ); + + _.agHelper.EnterValue(datasourceFormData.AirtableBase, { + propFieldName: "", + directInput: false, + inputFieldName: "Base ID ", + }); + _.agHelper.EnterValue(datasourceFormData.AirtableTable, { + propFieldName: "", + directInput: false, + inputFieldName: "Table Name", + }); + + _.dataSources.RunQuery(); + cy.get("@postExecute").then((resObj: any) => { + jsonSpecies = JSON.parse(resObj.response.body.data.body); + jsonSpecies.records.forEach((record: { fields: any }) => { + specieslist.push(record.fields.Species_ID); + }); + expect(specieslist.length).eq(53); //making sure all fields are returned + }); + + //Filter Species_ID & Species fields only + _.agHelper.EnterValue( + "fields%5B%5D=Species_ID&fields%5B%5D=Species&fields%5B%5D=Taxa", + { + propFieldName: "", + directInput: false, + inputFieldName: "Fields", + }, + ); + + _.dataSources.RunQuery({ waitTimeInterval: 2000 }); + cy.get("@postExecute").then((resObj: any) => { + jsonSpecies = JSON.parse(resObj.response.body.data.body); + const hasOnlyAllowedKeys = jsonSpecies.records.every((record: any) => { + const fieldKeys = Object.keys(record.fields); + return ( + fieldKeys.includes("Species_ID") && + fieldKeys.includes("Species") && + fieldKeys.includes("Taxa") && + fieldKeys.length === 3 + ); + }); + expect(hasOnlyAllowedKeys).to.be.true; //making sure all records have only Filters fields returned in results + }); + + //Validate Max records + _.agHelper.EnterValue("11", { + propFieldName: "", + directInput: false, + inputFieldName: "Max Records", + }); + _.agHelper.EnterValue("", { + propFieldName: "", + directInput: false, + inputFieldName: "Page Size", + }); + _.dataSources.RunQuery({ waitTimeInterval: 2000 }); + cy.get("@postExecute").then((resObj: any) => { + jsonSpecies = JSON.parse(resObj.response.body.data.body); + expect(jsonSpecies.records.length).to.eq(11); //making sure only 11 record fields are returned + }); + + //Validate Page Size + _.agHelper.EnterValue("6", { + propFieldName: "", + directInput: false, + inputFieldName: "Page Size", + }); + + _.dataSources.RunQuery({ waitTimeInterval: 2000 }); + cy.get("@postExecute").then((resObj: any) => { + jsonSpecies = JSON.parse(resObj.response.body.data.body); + expect(jsonSpecies.records.length).to.eq(6); //making sure only 6 record fields are returned, honouring the PageSize + + //Validating offset + offset = jsonSpecies.offset; + _.agHelper.EnterValue(offset, { + propFieldName: "", + directInput: false, + inputFieldName: "Offset", + }); + + _.dataSources.RunQuery({ waitTimeInterval: 2000 }); + cy.get("@postExecute").then((resObj: any) => { + jsonSpecies = JSON.parse(resObj.response.body.data.body); + expect(jsonSpecies.records.length).to.eq(5); //making sure only remaining records are returned + }); + }); + + //Validate Filter by Formula + //let asc_specieslist = new Array(); //emptying array, specieslist.length = 0 did not work! + _.agHelper.EnterValue("", { + propFieldName: "", + directInput: false, + inputFieldName: "Offset", + }); //Removing Offset + _.agHelper.EnterValue('NOT({Taxa} = "Rodent")', { + propFieldName: "", + directInput: false, + inputFieldName: "Filter by Formula", + }); + + _.dataSources.RunQuery({ waitTimeInterval: 2000 }); + cy.get("@postExecute").then((resObj: any) => { + jsonSpecies = JSON.parse(resObj.response.body.data.body); + const allRecordsWithRodentTaxa = jsonSpecies.records.filter( + (record: { fields: { Taxa: string } }) => + record.fields.Taxa === "Rodent", + ); + expect(allRecordsWithRodentTaxa.length).to.eq(0); + }); + + //Validate Sort - asc + let asc_specieslist = new Array(); //emptying array, specieslist.length = 0 did not work! + _.agHelper.EnterValue("", { + propFieldName: "", + directInput: false, + inputFieldName: "Page Size", + }); //Removing Page Size + _.agHelper.EnterValue("", { + propFieldName: "", + directInput: false, + inputFieldName: "Filter by Formula", + }); //Removing Filter by Formula + _.agHelper.EnterValue("10", { + propFieldName: "", + directInput: false, + inputFieldName: "Max Records", + }); + _.agHelper.EnterValue("sort%5B0%5D%5Bfield%5D=Species_ID", { + propFieldName: "", + directInput: false, + inputFieldName: "Sort", + }); //Sort by default ascending, descneding is thrown error, checking with Felix + + _.dataSources.RunQuery({ waitTimeInterval: 2000 }); + cy.get("@postExecute").then((resObj: any) => { + jsonSpecies = JSON.parse(resObj.response.body.data.body); + const sorted = jsonSpecies.records.every( + (record: { fields: { Species_ID: string } }, i: number) => { + if (i === 0) { + asc_specieslist.push(record.fields.Species_ID); + return true; + } + if ( + record.fields.Species_ID >= + jsonSpecies.records[i - 1].fields.Species_ID + ) { + asc_specieslist.push(record.fields.Species_ID); + return true; + } + return false; + }, + ); + cy.log("Sorted specieslist is :" + asc_specieslist); + expect(sorted).to.be.true; //making records returned are Sorted by Species_ID - in ascending + }); + + //Validate Sort - desc + let desc_specieslist = new Array(); //emptying array, specieslist.length = 0 did not work! + _.agHelper.EnterValue( + "sort%5B0%5D%5Bfield%5D=Species_ID&sort%5B0%5D%5Bdirection%5D=desc", + { + propFieldName: "", + directInput: false, + inputFieldName: "Sort", + }, + ); //Sort by descending + + _.dataSources.RunQuery({ waitTimeInterval: 2000 }); + cy.get("@postExecute").then((resObj: any) => { + jsonSpecies = JSON.parse(resObj.response.body.data.body); + const sorted = jsonSpecies.records.every( + (record: { fields: { Species_ID: string } }, i: number) => { + if (i === 0) { + desc_specieslist.push(record.fields.Species_ID); + return true; + } + if ( + record.fields.Species_ID <= + jsonSpecies.records[i - 1].fields.Species_ID + ) { + desc_specieslist.push(record.fields.Species_ID); + return true; + } + return false; + }, + ); + cy.log("Desc Sorted specieslist is :" + desc_specieslist); + expect(sorted).to.be.true; //making records returned are Sorted by Species_ID - in descending + }); + + //Validate View - desc + let view_specieslist = new Array(); + const isValidSpeciesID = (id: string) => ["EO", "PE"].includes(id); + _.agHelper.EnterValue("", { + propFieldName: "", + directInput: false, + inputFieldName: "Sort", + }); //Removing Sort + + _.agHelper.EnterValue("GridView_CI", { + propFieldName: "", + directInput: false, + inputFieldName: "View", + }); + + _.dataSources.RunQuery({ waitTimeInterval: 2000 }); + cy.get("@postExecute").then((resObj: any) => { + jsonSpecies = JSON.parse(resObj.response.body.data.body); + const isJSONValid = jsonSpecies.records.every( + (record: { fields: { Species_ID: any } }) => { + const speciesID = record.fields.Species_ID; + view_specieslist.push(record.fields.Species_ID); + return isValidSpeciesID(speciesID); + }, + ); + cy.log("View specieslist is :" + view_specieslist); + expect(isJSONValid).to.be.true; //Verify if records Species_ID is part of View data + }); + }); + + it("2. Create/Retrieve/Update/Delete records", () => { + let createReq = `[{"fields": { + "Species_ID": "SF", + "Genus": "Sigmodon", + "Species": "fulviventer", + "Taxa": "Rodent" + }}]`; + + //Create + _.dataSources.ValidateNSelectDropdown( + "Commands", + "List Records", + "Create Records", + ); + _.agHelper.EnterValue(createReq, { + propFieldName: "", + directInput: false, + inputFieldName: "Records", + }); + _.agHelper.Sleep(500); // for the Records field to settle + + _.dataSources.RunQuery({ waitTimeInterval: 2000 }); + cy.get("@postExecute").then((resObj: any) => { + jsonSpecies = JSON.parse(resObj.response.body.data.body); + //cy.log("jsonSpecies is"+ jsonSpecies) + expect(jsonSpecies.records.length).to.eq(1); //making sure only inserted record is returned + + //Retrieve a record + insertedRecordId = jsonSpecies.records[0].id; + _.dataSources.ValidateNSelectDropdown( + "Commands", + "Create Records", + "Retrieve A Record", + ); + _.agHelper.EnterValue(insertedRecordId, { + propFieldName: "", + directInput: false, + inputFieldName: "Record ID ", + }); + + _.dataSources.RunQuery({ waitTimeInterval: 2000 }); + cy.get("@postExecute").then((resObj: any) => { + jsonSpecies = JSON.parse(resObj.response.body.data.body); + const hasOnlyInsertedRecord = () => { + return ( + jsonSpecies.fields.Species_ID === "SF" && + jsonSpecies.fields.Genus === "Sigmodon" && + jsonSpecies.fields.Species === "fulviventer" && + jsonSpecies.fields.Taxa === "Rodent" + ); + }; + expect(hasOnlyInsertedRecord()).to.be.true; + }); + + //Update Records + _.dataSources.ValidateNSelectDropdown( + "Commands", + "Retrieve A Record", + "Update Records", + ); + _.agHelper.EnterValue( + `[{ "id" : ${insertedRecordId}, + fields: { + Species_ID: "SG", + Genus: "Spizella", + Species: "clarki", + Taxa: "Bird", + }}]`, + { + propFieldName: "", + directInput: false, + inputFieldName: "Records", + }, + ); + + _.dataSources.RunQuery({ waitTimeInterval: 2000 }); + cy.get("@postExecute").then((resObj: any) => { + jsonSpecies = JSON.parse(resObj.response.body.data.body); + const hasOnlyUpdatedRecord = () => { + return ( + jsonSpecies.records[0].fields.Species_ID === "SG" && + jsonSpecies.records[0].fields.Genus === "Spizella" && + jsonSpecies.records[0].fields.Species === "clarki" && + jsonSpecies.records[0].fields.Taxa === "Bird" + ); + }; + expect(hasOnlyUpdatedRecord()).to.be.true; + }); + + //Delete A record + //insertedRecordId = jsonSpecies.id; + _.dataSources.ValidateNSelectDropdown( + "Commands", + "Update Records", + "Delete A Record", + ); + + _.dataSources.RunQuery({ waitTimeInterval: 2000 }); + cy.get("@postExecute").then((resObj: any) => { + jsonSpecies = JSON.parse(resObj.response.body.data.body); + expect(jsonSpecies.deleted).to.be.true; + }); + }); + }); + + after("Delete the query & datasource", () => { + _.agHelper.ActionContextMenuWithInPane("Delete"); + _.entityExplorer.SelectEntityByName(dsName, "Datasources"); + _.entityExplorer.ActionContextMenuByEntityName( + dsName, + "Delete", + "Are you sure?", + ); + _.agHelper.ValidateNetworkStatus("@deleteDatasource", 200); + }); +}); diff --git a/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/Datasources/MsSQL_Basic_Spec.ts b/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/Datasources/MsSQL_Basic_Spec.ts index 026b7c1bb3..e81ea453cb 100644 --- a/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/Datasources/MsSQL_Basic_Spec.ts +++ b/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/Datasources/MsSQL_Basic_Spec.ts @@ -4,7 +4,7 @@ import { Widgets } from "../../../../support/Pages/DataSources"; let dsName: any, query: string; describe("Validate MsSQL connection & basic querying with UI flows", () => { - before("Create a new MySQL DS", () => { + before("Create a new MySQL DS & adding data into it", () => { _.dataSources.CreateDataSource("MsSql"); cy.get("@dsName").then(($dsName) => { dsName = $dsName; @@ -71,7 +71,7 @@ describe("Validate MsSQL connection & basic querying with UI flows", () => { //_.agHelper.ActionContextMenuWithInPane("Delete"); Since next case can continue in same template }); - it("1. Validate Show all existing tables, Describe table & verify query responses", () => { + it("1. Validate simple queries - Show all existing tables, Describe table & verify query responses", () => { runQueryNValidate( "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE';", ["TABLE_CATALOG", "TABLE_SCHEMA", "TABLE_NAME", "TABLE_TYPE"], diff --git a/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/GenerateCRUD/MySQL1_Spec.ts b/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/GenerateCRUD/MySQL1_Spec.ts index 2a009993d4..9bb0a66ae0 100644 --- a/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/GenerateCRUD/MySQL1_Spec.ts +++ b/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/GenerateCRUD/MySQL1_Spec.ts @@ -270,7 +270,7 @@ describe("Validate MySQL Generate CRUD with JSON Form", () => { it("10. Verify application does not break when user runs the query with wrong table name", function () { ee.SelectEntityByName("DropProductlines", "Queries/JS"); - dataSources.RunQuery(false); + dataSources.RunQuery({toValidateResponse:false}); cy.wait("@postExecute").then(({ response }) => { expect(response?.body.data.isExecutionSuccess).to.eq(false); expect( diff --git a/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/GenerateCRUD/Postgres2_Spec.ts b/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/GenerateCRUD/Postgres2_Spec.ts index 397ddc85dd..698cd7ac88 100644 --- a/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/GenerateCRUD/Postgres2_Spec.ts +++ b/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/GenerateCRUD/Postgres2_Spec.ts @@ -624,7 +624,7 @@ describe("Validate Postgres Generate CRUD with JSON Form", () => { it("18. Verify application does not break when user runs the query with wrong table name", function () { ee.SelectEntityByName("DropVessels", "Queries/JS"); - dataSources.RunQuery(false); + dataSources.RunQuery({toValidateResponse:false}); cy.wait("@postExecute").then(({ response }) => { expect(response?.body.data.isExecutionSuccess).to.eq(false); expect( diff --git a/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/MySQL_Datatypes/Basic_Spec.ts b/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/MySQL_Datatypes/Basic_Spec.ts index 7e9cbed57e..caac419f54 100644 --- a/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/MySQL_Datatypes/Basic_Spec.ts +++ b/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/MySQL_Datatypes/Basic_Spec.ts @@ -104,7 +104,7 @@ describe("MySQL Datatype tests", function () { _.deployMode.NavigateBacktoEditor(); _.entityExplorer.ExpandCollapseEntity("Queries/JS"); _.entityExplorer.SelectEntityByName("selectRecords"); - _.dataSources.RunQuery(false); + _.dataSources.RunQuery({toValidateResponse:false}); cy.wait("@postExecute").then((intercept) => { expect( typeof intercept.response?.body.data.body[5].varchar_column, diff --git a/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/MySQL_Datatypes/False_Spec.ts b/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/MySQL_Datatypes/False_Spec.ts index 9fca7f83c0..431374a2b8 100644 --- a/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/MySQL_Datatypes/False_Spec.ts +++ b/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/MySQL_Datatypes/False_Spec.ts @@ -36,7 +36,7 @@ describe("MySQL Datatype tests", function () { ? `INSERT INTO ${inputData.tableName} (${inputData.inputFieldName[i]}) VALUES ({{"${value}"}})` : `INSERT INTO ${inputData.tableName} (${inputData.inputFieldName[i]}) VALUES ({{${value}}})`; _.dataSources.EnterQuery(query); - _.dataSources.RunQuery(true, false); + _.dataSources.RunQuery({ expectedStatus: false }); }); }); _.agHelper.Sleep(2000); @@ -45,6 +45,7 @@ describe("MySQL Datatype tests", function () { //This is a special case. //Added due to server side checks, which was handled in Datatype handling. //Long Integer as query param + query = `SELECT * FROM ${inputData.tableName} LIMIT {{2147483648}}`; _.dataSources.EnterQuery(query); _.dataSources.RunQuery(); diff --git a/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/QueryPane/Mongo_Spec.js b/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/QueryPane/Mongo_Spec.js index 6ed61ee8a1..b6fa34e948 100644 --- a/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/QueryPane/Mongo_Spec.js +++ b/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/QueryPane/Mongo_Spec.js @@ -7,7 +7,7 @@ import * as _ from "../../../../support/Objects/ObjectsCore"; let datasourceName; -describe("Create a query with a mongo datasource, run, save and then delete the query", function () { +describe("Validate Mongo query commands", function () { // afterEach(function() { // if (this.currentTest.state === "failed") { // Cypress.runner.stop(); @@ -111,7 +111,7 @@ describe("Create a query with a mongo datasource, run, save and then delete the inputFieldName: "Limit", }); //Limit field - _.dataSources.RunQuery(false); + _.dataSources.RunQuery({ toValidateResponse: false }); cy.wait("@postExecute").then(({ response }) => { expect(response.body.data.body[0].description).to.contains( "The ideal apartment to visit the magnificent city of Porto and the northern region of Portugal, with family or with a couple of friends", @@ -125,7 +125,7 @@ describe("Create a query with a mongo datasource, run, save and then delete the directInput: false, inputFieldName: "Skip", }); - _.dataSources.RunQuery(false); + _.dataSources.RunQuery({ toValidateResponse: false }); cy.wait("@postExecute").then(({ response }) => { expect(response.body.data.body[0].description).to.contains( "My place is close to the beach, family-friendly activities, great views, and a short drive to art and culture, and restaurants and dining", @@ -154,7 +154,7 @@ describe("Create a query with a mongo datasource, run, save and then delete the directInput: false, inputFieldName: "Query", }); - _.dataSources.RunQuery(false); + _.dataSources.RunQuery({ toValidateResponse: false }); cy.wait("@postExecute").then(({ response }) => { expect(response.body.data.body.n).to.be.above( 0, @@ -186,7 +186,7 @@ describe("Create a query with a mongo datasource, run, save and then delete the directInput: false, inputFieldName: "Key", }); - _.dataSources.RunQuery(false); + _.dataSources.RunQuery({ toValidateResponse: false }); cy.wait("@postExecute").then(({ response }) => { expect(response.body.data.body.values[0]).to.eq( "Aparthotel", @@ -214,7 +214,7 @@ describe("Create a query with a mongo datasource, run, save and then delete the inputFieldName: "Array of Pipelines", }); - _.dataSources.RunQuery(false); + _.dataSources.RunQuery({ toValidateResponse: false }); cy.wait("@postExecute").then(({ request, response }) => { // cy.log(request.method + ": is req.method") //expect(request.method).to.equal('POST') @@ -499,7 +499,7 @@ describe("Create a query with a mongo datasource, run, save and then delete the // "{$set:{ 'Frõ': 'InActive'}}", // formControls.mongoUpdateManyUpdate, // ); - _.dataSources.RunQuery(false); + _.dataSources.RunQuery({ toValidateResponse: false }); cy.wait("@postExecute").then(({ response }) => { expect(response.body.data.body.nModified).to.eq(1); }); @@ -537,7 +537,7 @@ describe("Create a query with a mongo datasource, run, save and then delete the formControls.mongoDeleteLimitDropdown, "Single Document", ); - _.dataSources.RunQuery(false); + _.dataSources.RunQuery({ toValidateResponse: false }); cy.wait("@postExecute").then(({ response }) => { expect(response.body.data.body.n).to.eq(1); @@ -557,7 +557,7 @@ describe("Create a query with a mongo datasource, run, save and then delete the "Single Document", "All Matching Documents", ); - _.dataSources.RunQuery(false); + _.dataSources.RunQuery({ toValidateResponse: false }); cy.wait("@postExecute").then(({ response }) => { expect(response.body.data.body.n).to.eq(2); }); @@ -568,7 +568,7 @@ describe("Create a query with a mongo datasource, run, save and then delete the "Delete Document(s)", "Find Document(s)", ); - _.dataSources.RunQuery(false); + _.dataSources.RunQuery({ toValidateResponse: false }); cy.wait("@postExecute").then(({ response }) => { expect(response.body.data.body.length).to.eq(0); //checking that body is empty array }); @@ -581,7 +581,7 @@ describe("Create a query with a mongo datasource, run, save and then delete the ); cy.typeValueNValidate('{"drop": "NonAsciiTest"}', formControls.rawBody); cy.wait(1000); //Waiting a bit before runing the command - _.dataSources.RunQuery(true, true, 2000); + _.dataSources.RunQuery({ waitTimeInterval: 2000 }); cy.CheckAndUnfoldEntityItem("Datasources"); cy.get("@dSName").then((dbName) => { cy.actionContextMenuByEntityName(dbName, "Refresh"); diff --git a/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/QueryPane/Mongo_Spec.ts b/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/QueryPane/Mongo_Spec.ts index bcabe4671d..9adebe9469 100644 --- a/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/QueryPane/Mongo_Spec.ts +++ b/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/QueryPane/Mongo_Spec.ts @@ -661,7 +661,7 @@ describe("Validate Mongo Query Pane Validations", () => { agHelper.FocusElement(locator._codeMirrorTextArea); //agHelper.VerifyEvaluatedValue(tableCreateQuery); - dataSources.RunQuery(true, false); + dataSources.RunQuery({expectedStatus: false}); agHelper .GetText(dataSources._queryError) .then(($errorText) => expect($errorText).to.eq("ns not found.")); diff --git a/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/QueryPane/S3_1_spec.js b/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/QueryPane/S3_1_spec.js index b548c7d452..11c50d793b 100644 --- a/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/QueryPane/S3_1_spec.js +++ b/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/QueryPane/S3_1_spec.js @@ -46,7 +46,7 @@ describe("Validate CRUD queries for Amazon S3 along with UI flow verifications", formControls.commandDropdown, "List files in bucket", ); - _.dataSources.RunQuery(false); + _.dataSources.RunQuery({ toValidateResponse: false }); cy.wait("@postExecute").should(({ response }) => { expect(response.body.data.isExecutionSuccess).to.eq(false); expect(response.body.data.body).to.contains( @@ -55,7 +55,7 @@ describe("Validate CRUD queries for Amazon S3 along with UI flow verifications", }); cy.typeValueNValidate("AutoTest", formControls.s3BucketName); - _.dataSources.RunQuery(false); + _.dataSources.RunQuery({ toValidateResponse: false }); cy.wait(3000); //for new postExecute to come thru cy.wait("@postExecute").then(({ response }) => { expect(response.body.data.isExecutionSuccess).to.eq(false); diff --git a/app/client/cypress/support/Pages/AggregateHelper.ts b/app/client/cypress/support/Pages/AggregateHelper.ts index a99a99ca1d..affdf660ed 100644 --- a/app/client/cypress/support/Pages/AggregateHelper.ts +++ b/app/client/cypress/support/Pages/AggregateHelper.ts @@ -139,16 +139,19 @@ export class AggregateHelper { cy.get("body").then(($ele) => { if ($ele.find(this.locator._saveStatusError).length) { this.RefreshPage(); + return false; } }); + return true; } public AssertAutoSave() { - this.CheckForPageSaveError(); + let saveStatus = this.CheckForPageSaveError(); // wait for save query to trigger & n/w call to finish occuring - cy.get(this.locator._saveStatusContainer, { timeout: 30000 }).should( - "not.exist", - ); //adding timeout since waiting more time is not worth it! + if (!saveStatus) + cy.get(this.locator._saveStatusContainer, { timeout: 30000 }).should( + "not.exist", + ); //adding timeout since waiting more time is not worth it! //this.ValidateNetworkStatus("@sucessSave", 200); } @@ -818,6 +821,7 @@ export class AggregateHelper { input.setValue(value); this.Sleep(200); }); + this.Sleep(500);//for value set to settle } public UpdateInput(selector: string, value: string) { diff --git a/app/client/cypress/support/Pages/ApiPage.ts b/app/client/cypress/support/Pages/ApiPage.ts index b9ad3eaf3c..2b210f321b 100644 --- a/app/client/cypress/support/Pages/ApiPage.ts +++ b/app/client/cypress/support/Pages/ApiPage.ts @@ -53,8 +53,6 @@ export class ApiPage { verb + "')]"; private _bodySubTab = (subTab: string) => `[data-cy='tab--${subTab}']`; - private _suggestedWidget = (widget: string) => - `.t--suggested-widget-${widget}`; private _rightPaneTab = (tab: string) => `[data-cy='t--tab-${tab}']`; _visibleTextSpan = (spanText: string) => "//span[text()='" + spanText + "']"; _visibleTextDiv = (divText: string) => "//div[text()='" + divText + "']"; @@ -406,8 +404,4 @@ export class ApiPage { if (apiName) this.agHelper.RenameWithInPane(apiName); cy.get(this._resourceUrl).should("be.visible"); } - - AddSuggestedWidget(widgetName: string) { - this.agHelper.GetNClick(this._suggestedWidget(widgetName)); - } } diff --git a/app/client/cypress/support/Pages/DataSources.ts b/app/client/cypress/support/Pages/DataSources.ts index 7c88947c01..f80b4efb54 100644 --- a/app/client/cypress/support/Pages/DataSources.ts +++ b/app/client/cypress/support/Pages/DataSources.ts @@ -8,6 +8,7 @@ const DataSourceKVP = { MySql: "MySQL", UnAuthenticatedGraphQL: "GraphQL API", MsSql: "Microsoft SQL Server", + Airtable: "Airtable", }; //DataSources KeyValuePair export enum Widgets { @@ -17,6 +18,11 @@ export enum Widgets { Text, } +interface RunQueryParams { + toValidateResponse?: boolean; + expectedStatus?: boolean; + waitTimeInterval?: number; +} export class DataSources { private agHelper = ObjectsRegistry.AggregateHelper; private table = ObjectsRegistry.Table; @@ -408,6 +414,19 @@ export class DataSources { ); } + public FillAirtableDSForm() { + this.ValidateNSelectDropdown( + "Authentication Type", + "Please select an option.", + "Bearer Token", + ); + this.agHelper.UpdateInput( + this.locator._inputFieldByName("Bearer Token"), + Cypress.env("AIRTABLE_BEARER"), + ); + this.agHelper.Sleep(); + } + public FillFirestoreDSForm() { cy.xpath(this.locator._inputFieldByName("Database URL") + "//input").type( datasourceFormData["database-url"], @@ -628,14 +647,14 @@ export class DataSources { }); } - RunQuery( + RunQuery({ toValidateResponse = true, expectedStatus = true, waitTimeInterval = 500, - ) { + }: Partial = {}) { this.agHelper.GetNClick(this._runQueryBtn, 0, true, waitTimeInterval); if (toValidateResponse) { - this.agHelper.Sleep(1000); + this.agHelper.Sleep(); this.agHelper.ValidateNetworkExecutionSuccess( "@postExecute", expectedStatus, @@ -717,7 +736,13 @@ export class DataSources { } public CreateDataSource( - dsType: "Postgres" | "Mongo" | "MySql" | "UnAuthenticatedGraphQL" | "MsSql", + dsType: + | "Postgres" + | "Mongo" + | "MySql" + | "UnAuthenticatedGraphQL" + | "MsSql" + | "Airtable", navigateToCreateNewDs = true, testNSave = true, ) { @@ -737,6 +762,7 @@ export class DataSources { else if (DataSourceKVP[dsType] == "MongoDB") this.FillMongoDSForm(); else if (DataSourceKVP[dsType] == "Microsoft SQL Server") this.FillMsSqlDSForm(); + else if (DataSourceKVP[dsType] == "Airtable") this.FillAirtableDSForm(); if (testNSave) { this.TestSaveDatasource(); @@ -930,7 +956,7 @@ export class DataSources { public FillMongoDatasourceFormWithURI(uri: string) { this.ValidateNSelectDropdown("Use Mongo Connection String URI", "", "Yes"); - this.agHelper.TypeText( + this.agHelper.UpdateInputValue( this.locator._inputFieldByName("Connection String URI") + "//input", uri, );