diff --git a/.github/workflows/cypress-platform.yml b/.github/workflows/cypress-platform.yml index 112a10c199..d136991e38 100644 --- a/.github/workflows/cypress-platform.yml +++ b/.github/workflows/cypress-platform.yml @@ -79,7 +79,7 @@ jobs: - name: Set up environment variables run: | - echo "TOOLJET_EDITION=${{ matrix.edition == 'ee' && 'EE' || 'CE' }}" >> .env + echo "TOOLJET_EDITION=${{ matrix.edition == 'ee' && 'ee' || 'ce' }}" >> .env echo "TOOLJET_HOST=http://localhost:8082" >> .env echo "LOCKBOX_MASTER_KEY=cd97331a419c09387bef49787f7da8d2a81d30733f0de6bed23ad8356d2068b2" >> .env echo "SECRET_KEY_BASE=7073b9a35a15dd20914ae17e36a693093f25b74b96517a5fec461fc901c51e011cd142c731bee48c5081ec8bac321c1f259ef097ef2a16f25df17a3798c03426" >> .env diff --git a/cypress-tests/cypress/commands/commands.js b/cypress-tests/cypress/commands/commands.js index 0f9a6c9996..02933afd7a 100644 --- a/cypress-tests/cypress/commands/commands.js +++ b/cypress-tests/cypress/commands/commands.js @@ -116,8 +116,10 @@ Cypress.Commands.add( }); const splitIntoFlatArray = (value) => { - const regex = /(\{|\}|\(|\)|\[|\]|,|:|;|=>|'[^']*'|[a-zA-Z0-9._]+|\s+)/g; + const regex = + /(\{|\}|\(|\)|\[|\]|,|:|;|=>|'[^']*'|"[^"]*"|[a-zA-Z0-9._-]+|\s+)/g; let prefix = ""; + return ( value.match(regex)?.reduce((acc, part) => { if (part === "{{" || part === "((") { @@ -132,6 +134,10 @@ Cypress.Commands.add( acc.push(prefix + " "); } else if (part === ":") { acc.push(prefix + ":"); + } else if (part === '"') { + acc.push(prefix + '"'); + } else if (part.includes("-")) { + acc.push(prefix + part); // Ensure hyphen is included } else { acc.push(prefix + part); prefix = ""; @@ -142,13 +148,11 @@ Cypress.Commands.add( }; if (Array.isArray(value)) { - cy.wrap(subject) - .last() - .realType(value, { - parseSpecialCharSequences: false, - delay: 0, - force: true, - }); + cy.wrap(subject).last().realType(value, { + parseSpecialCharSequences: false, + delay: 0, + force: true, + }); } else { splitIntoFlatArray(value).forEach((i) => { cy.wrap(subject) @@ -228,9 +232,9 @@ Cypress.Commands.add( .invoke("text") .then((text) => { cy.wrap(subject).realType(createBackspaceText(text)), - { - delay: 0, - }; + { + delay: 0, + }; }); } ); diff --git a/cypress-tests/cypress/constants/selectors/Plugins.js b/cypress-tests/cypress/constants/selectors/Plugins.js new file mode 100644 index 0000000000..04481d09fa --- /dev/null +++ b/cypress-tests/cypress/constants/selectors/Plugins.js @@ -0,0 +1,40 @@ +export const pluginSelectors = { + regionField: '[data-cy="region-section"] .react-select__control', + regionFieldValue: '[data-cy="region-section"] .react-select__single-value', + amazonsesAccesKey: '[data-cy="access-key-text-field"]', + operationDropdown: '[data-cy="operation-select-dropdown"]', + sendEmailInputField: '[data-cy="send-mail-to-input-field"]', + ccEmailInputField: '[data-cy="cc-to-input-field"]', + bccEmailInputField: '[data-cy="bcc-to-input-field"]', + sendEmailFromInputField: '[data-cy="send-mail-from-input-field"]', + emailSubjetInputField: '[data-cy="subject-input-field"]', + emailbodyInputField: '[data-cy="body-input-field"]', + amazonAthenaDbName: '[data-cy="database-text-field"]', +}; + +export const baserowSelectors = { + hostField: '[data-cy="host-select-dropdown"]', + baserowApiKey: '[data-cy="api-token-text-field"]', + table: '[data-cy="table-id-input-field"]', + rowIdinputfield: '[data-cy="row-id-input-field"]', +}; + +export const appWriteSelectors = { + projectID: '[data-cy="project-id-text-field"]', + collectionId: '[data-cy="collectionid-input-field"]', + documentId: '[data-cy="documentid-input-field"]', + bodyInput: '[data-cy="body-input-field"]', +}; + +export const twilioSelectors = { + toNumberInputField: '[data-cy="to-number-input-field"]', + bodyInput: '[data-cy="body-input-field"]', +}; + +export const minioSelectors = { + sslToggle: 'data-cy="ssl-enabled-toggle-input"', + bucketNameInputField: '[data-cy="bucket-input-field"]', + objectNameInputField: '[data-cy="objectname-input-field"]', + contentTypeInputField: '[data-cy="contenttype-input-field"]', + dataInput: '[data-cy="data-input-field"]', +}; diff --git a/cypress-tests/cypress/constants/selectors/awss3.js b/cypress-tests/cypress/constants/selectors/awss3.js index 59bdebacff..81f1a6efe8 100644 --- a/cypress-tests/cypress/constants/selectors/awss3.js +++ b/cypress-tests/cypress/constants/selectors/awss3.js @@ -5,5 +5,5 @@ export const s3Selector = { regionLabel: '[data-cy="label-region"]', customEndpointLabel: '[data-cy="label-custom-endpoint"]', customEndpointInput: '[data-cy="undefined-text-field"]', - dataSourceNameInput: '[data-cy="data-source-name-input-filed"]', + dataSourceNameInput: '[data-cy="data-source-name-input-field"]', }; diff --git a/cypress-tests/cypress/constants/selectors/dataSource.js b/cypress-tests/cypress/constants/selectors/dataSource.js index bdf1677d91..8283eb2b92 100644 --- a/cypress-tests/cypress/constants/selectors/dataSource.js +++ b/cypress-tests/cypress/constants/selectors/dataSource.js @@ -14,7 +14,7 @@ export const dataSourceSelector = { dataSourceSearchInputField: '[data-cy="home-page-search-bar"]', postgresDataSource: "[data-cy='data-source-postgresql']", - dataSourceNameInputField: '[data-cy="data-source-name-input-filed"]', + dataSourceNameInputField: '[data-cy="data-source-name-input-field"]', labelHost: '[data-cy="label-host"]', labelPort: '[data-cy="label-port"]', labelSsl: '[data-cy="label-ssl"]', @@ -28,7 +28,7 @@ export const dataSourceSelector = { buttonTestConnection: '[data-cy="test-connection-button"]', connectionFailedText: '[data-cy="test-connection-failed-text"]', buttonSave: '[data-cy="db-connection-save-button"] > .tj-base-btn', - dangerAlertNotSupportSSL: '.go3958317564', + dangerAlertNotSupportSSL: ".go3958317564", passwordTextField: '[data-cy="password-text-field"]', textConnectionVerified: '[data-cy="test-connection-verified-text"]', @@ -97,11 +97,11 @@ export const dataSourceSelector = { eventQuerySelectionField: '[data-cy="query-selection-field"]', addedDsSearchIcon: '[data-cy="added-ds-search-icon"]', AddedDsSearchBar: '[data-cy="added-ds-search-bar"]', - dsNameInputField: '[data-cy="data-source-name-input-filed"]', + dsNameInputField: '[data-cy="data-source-name-input-field"]', unSavedModalTitle: '[data-cy="unsaved-changes-title"]', eventQuerySelectionField: '[data-cy="query-selection-field"]', connectionAlertText: '[data-cy="connection-alert-text"]', deleteDSButton: (datasourceName) => { - return `[data-cy="${cyParamName(datasourceName)}-delete-button"]` + return `[data-cy="${cyParamName(datasourceName)}-delete-button"]`; }, }; diff --git a/cypress-tests/cypress/constants/selectors/postgreSql.js b/cypress-tests/cypress/constants/selectors/postgreSql.js index 49e0351656..4f38357961 100644 --- a/cypress-tests/cypress/constants/selectors/postgreSql.js +++ b/cypress-tests/cypress/constants/selectors/postgreSql.js @@ -12,7 +12,7 @@ export const postgreSqlSelector = { dataSourceSearchInputField: '[data-cy="home-page-search-bar"]', postgresDataSource: "[data-cy='data-source-postgresql']", - dataSourceNameInputField: '[data-cy="data-source-name-input-filed"]', + dataSourceNameInputField: '[data-cy="data-source-name-input-field"]', labelHost: '[data-cy="label-host"]', labelPort: '[data-cy="label-port"]', labelSsl: '[data-cy="label-ssl"]', @@ -88,3 +88,11 @@ export const postgreSqlSelector = { eventQuerySelectionField: '[data-cy="query-selection-field"]', }; + +export const airTableSelector = { + operationSelectDropdown: '[data-cy="operation-select-dropdown"]', + baseIdInputField: '[data-cy="base-id-input-field"]', + tableNameInputField: '[data-cy="table-name-input-field"]', + recordIdInputField: '[data-cy="record-id-input-field"]', + bodyInputField: '[data-cy="body-input-field"]', +}; diff --git a/cypress-tests/cypress/constants/texts/airTable.js b/cypress-tests/cypress/constants/texts/airTable.js new file mode 100644 index 0000000000..44df3cf9e1 --- /dev/null +++ b/cypress-tests/cypress/constants/texts/airTable.js @@ -0,0 +1,6 @@ +export const airtableText = { + airtable: "Airtable", + cypressairtable: "cypress-Airtable", + ApiKey: "Personal access token", + apikeyPlaceholder: "**************", + }; \ No newline at end of file diff --git a/cypress-tests/cypress/constants/texts/amazonAthena.js b/cypress-tests/cypress/constants/texts/amazonAthena.js new file mode 100644 index 0000000000..794815d4a7 --- /dev/null +++ b/cypress-tests/cypress/constants/texts/amazonAthena.js @@ -0,0 +1,8 @@ +export const amazonAthenaText = { + AmazonAthena: "Amazon Athena", + cypressAmazonAthena: "cypress-Amazon Athena", + labelAccesskey: "Access key", + labelSecretKey: "Secret key", + placeholderEnteraAccessKey: "Enter access key", + placeholderSecretKey:"**************", + }; \ No newline at end of file diff --git a/cypress-tests/cypress/constants/texts/amazonSes.js b/cypress-tests/cypress/constants/texts/amazonSes.js new file mode 100644 index 0000000000..2abaed71ab --- /dev/null +++ b/cypress-tests/cypress/constants/texts/amazonSes.js @@ -0,0 +1,8 @@ +export const amazonSesText = { + AmazonSES: "Amazon SES", + cypressAmazonSES: "cypress-Amazon SES", + labelAccesskey: "Access key", + labelSecretKey: "Secret key", + placeholderAccessKey: "Enter access key", + placeholderSecretKey:"**************", + }; \ No newline at end of file diff --git a/cypress-tests/cypress/constants/texts/appwrite.js b/cypress-tests/cypress/constants/texts/appwrite.js new file mode 100644 index 0000000000..15b723d1cc --- /dev/null +++ b/cypress-tests/cypress/constants/texts/appwrite.js @@ -0,0 +1,12 @@ +export const appwriteText = { + appwrite: "Appwrite", + cypressAppwrite: "cypress-Appwrite", + host: "Host", + ProjectID: "Project ID", + DatabaseID: "Database ID", + SecretKey: "Secret Key", + SecretKeyPlaceholder: "**************", + hostPlaceholder: "Appwrite database host/endpoint", + projectIdPlaceholder: "Appwrite project id", + databaseIdPlaceholder: "Appwrite Database id", +}; diff --git a/cypress-tests/cypress/constants/texts/baseRow.js b/cypress-tests/cypress/constants/texts/baseRow.js new file mode 100644 index 0000000000..6f9958d979 --- /dev/null +++ b/cypress-tests/cypress/constants/texts/baseRow.js @@ -0,0 +1,6 @@ +export const baseRowText = { + baserow: "baserow", + cypressBaseRow: "cypress-baserow", + lableApiToken: "API token", + placeholderApiToken:"**************", + }; \ No newline at end of file diff --git a/cypress-tests/cypress/constants/texts/minio.js b/cypress-tests/cypress/constants/texts/minio.js new file mode 100644 index 0000000000..5afd1ed477 --- /dev/null +++ b/cypress-tests/cypress/constants/texts/minio.js @@ -0,0 +1,14 @@ +export const minioText = { + minio: "Minio", + cypressMinio: "cypressMinio", + hostLabel: "Host", + hostInputPlaceholder: "Enter host", + portLabel: "Port", + portPlaceholder: "Enter port", + labelAccesskey: "Access key", + labelSecretKey: "Secret key", + placeholderAccessKey: "Enter access key", + placeholderSecretKey: "**************", + bucketName: `my-second-bucket`, + objectName: `mybucket`, +}; diff --git a/cypress-tests/cypress/constants/texts/twilio.js b/cypress-tests/cypress/constants/texts/twilio.js new file mode 100644 index 0000000000..535bfb3b8a --- /dev/null +++ b/cypress-tests/cypress/constants/texts/twilio.js @@ -0,0 +1,11 @@ +export const twilioText = { + twilio: "Twilio", + cypresstwilio: "cypress-Twilio", + authTokenLabel: "Auth Token", + authTokenPlaceholder: "**************", + accountSidLabel: "Account SID", + accountSidPlaceholder: "Account SID for Twilio", + messagingSIDLabel: "Messaging Service SID", + messagingSIDPalceholder: "Messaging Service SID for Twilio", + messageText: "Sending test message to check twilio", +}; diff --git a/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/addAllPluginsToApp.cy.js b/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/addAllPluginsToApp.cy.js new file mode 100644 index 0000000000..fa0fad800f --- /dev/null +++ b/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/addAllPluginsToApp.cy.js @@ -0,0 +1,210 @@ +import { fake } from "Fixtures/fake"; +import { postgreSqlSelector } from "Selectors/postgreSql"; +import { postgreSqlText } from "Texts/postgreSql"; +import { commonSelectors } from "Selectors/common"; + +import { selectAndAddDataSource } from "Support/utils/postgreSql"; + +import { closeDSModal } from "Support/utils/dataSource"; + +const data = {}; +data.dsNamefake = fake.lastName.toLowerCase().replaceAll("[^A-Za-z]", ""); +data.dsNamefake1 = fake.lastName.toLowerCase().replaceAll("[^A-Za-z]", ""); +const cyParamName = (name) => name.toLowerCase().replace(/[^a-z0-9]/g, "-"); + +const dataSources = [ + "BigQuery", + "ClickHouse", + "CosmosDB", + "CouchDB", + "Databricks", + "DynamoDB", + "Elasticsearch", + "Firestore", + "InfluxDB", + "MariaDB", + "MongoDB", + "SQL Server", + "MySQL", + "Oracle DB", + "PostgreSQL", + "Redis", + "RethinkDB", + "SAP HANA", + "Snowflake", + "TypeSense", + "Airtable", + "Amazon SES", + "Appwrite", + "Amazon Athena", + "Baserow", + // "Google Sheets", need to remove + "GraphQL", + // "gRPC", need to remove + "Mailgun", + "n8n", + "Notion", + "OpenAPI", + "REST API", + "SendGrid", + // "Slack", need to remove + "SMTP", + "Stripe", + "Twilio", + "Woocommerce", + //"Zendesk", need to remove + "Azure Blob Storage", + "GCS", + "Minio", + "AWS S3", +]; + +describe("Add all Data sources to app", () => { + beforeEach(() => { + cy.apiLogin(); + cy.defaultWorkspaceLogin(); + }); + + it("Should verify global data source page", () => { + cy.get(commonSelectors.globalDataSourceIcon).click(); + closeDSModal(); + + cy.get(postgreSqlSelector.allDatasourceLabelAndCount).should( + "have.text", + postgreSqlText.allDataSources() + ); + cy.get(postgreSqlSelector.commonlyUsedLabelAndCount).should( + "have.text", + postgreSqlText.commonlyUsed + ); + cy.get(postgreSqlSelector.cloudStorageLabelAndCount).should( + "have.text", + postgreSqlText.allCloudStorage + ); + }); + + it("Should add all data sources in data source page", () => { + dataSources.forEach((dsName) => { + cy.get(commonSelectors.globalDataSourceIcon).click(); + selectAndAddDataSource("databases", dsName, dsName); // Using the correct fake name + + // Test connection + // cy.get(postgreSqlSelector.buttonTestConnection).click(); + // cy.get(postgreSqlSelector.textConnectionVerified, { + // timeout: 10000, + // }).should("have.text", postgreSqlText.labelConnectionVerified); + + // // Save data source + // cy.get(postgreSqlSelector.buttonSave).click(); + // cy.verifyToastMessage( + // commonSelectors.toastMessage, + // `Data Source ${dsName} saved.` + // ); + }); + }); + + it("Should add all data sources in the app", () => { + cy.get(commonSelectors.dashboardIcon).click(); + cy.get(commonSelectors.appCreateButton).click(); + cy.get(commonSelectors.appNameInput).click().type(data.dsNamefake); + cy.get(commonSelectors.createAppButton).click(); + cy.skipWalkthrough(); + + cy.wrap(dataSources).each((dsName) => { + cy.get('[data-cy="show-ds-popover-button"]').click(); + cy.get(".css-4e90k9").type( + `cypress-${cyParamName(dsName)}-${cyParamName(dsName)}` + ); + cy.wait(500); + + cy.contains( + `[id*="react-select-"]`, + `cypress-${cyParamName(dsName)}-${cyParamName(dsName)}` + ) + .should("be.visible") + .click(); + + cy.wait(500); + }); + }); + + it("Should install all makretplace plugins and add them into the app", () => { + const dataSourcesMarketplace = [ + "Plivo", + "GitHub", + "OpenAI", + "AWS Textract", + "HarperDB", + "AWS Redshift", + "PocketBase", + "AWS Lambda", + "Supabase", + "Engagespot", + // "Salesforce", need to remove + "Presto", + "Jira", + // "Sharepoint", need to remove + "Portkey", + "Pinecone", + "Hugging Face", + "Cohere", + "Gemini", + "Mistral", + "Anthropic", + "Qdrant", + "Weaviate DB", + ]; + + cy.get(commonSelectors.globalDataSourceIcon).click(); + + cy.window().then((win) => { + cy.stub(win, "open").callsFake((url) => { + win.location.href = url; + }); + }); + + cy.get('[data-cy="data-source-add-plugin"]').click(); + + cy.get(".marketplace-install").each(($el) => { + cy.wrap($el).click(); + cy.wait(500); + cy.get(commonSelectors.toastMessage).should("include.text", "installed"); + }); + cy.wait(1000); + + cy.get(commonSelectors.globalDataSourceIcon).click(); + cy.get(commonSelectors.pageSectionHeader).should( + "have.text", + "Data sources" + ); + + cy.wrap(dataSourcesMarketplace).each((dsName) => { + cy.get(commonSelectors.globalDataSourceIcon).click(); + selectAndAddDataSource("databases", dsName, dsName); + cy.wait(500); + }); + + cy.get(commonSelectors.dashboardIcon).click(); + cy.get(commonSelectors.appCreateButton).click(); + cy.get(commonSelectors.appNameInput).click().type(data.dsNamefake1); + cy.get(commonSelectors.createAppButton).click(); + cy.skipWalkthrough(); + + cy.wrap(dataSourcesMarketplace).each((dsName) => { + cy.get('[data-cy="show-ds-popover-button"]').click(); + cy.get(".css-4e90k9").type( + `cypress-${cyParamName(dsName)}-${cyParamName(dsName)}` + ); + cy.wait(500); + + cy.contains( + `[id*="react-select-"]`, + `cypress-${cyParamName(dsName)}-${cyParamName(dsName)}` + ) + .should("be.visible") + .click(); + + cy.wait(500); + }); + }); +}); diff --git a/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/airTable.cy.js b/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/airTable.cy.js new file mode 100644 index 0000000000..bade9e6c5c --- /dev/null +++ b/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/airTable.cy.js @@ -0,0 +1,289 @@ +import { fake } from "Fixtures/fake"; +import { postgreSqlSelector, airTableSelector } from "Selectors/postgreSql"; +import { postgreSqlText } from "Texts/postgreSql"; +import { airtableText } from "Texts/airTable"; +import { commonSelectors } from "Selectors/common"; +import { commonText } from "Texts/common"; + +import { + fillDataSourceTextField, + selectAndAddDataSource, +} from "Support/utils/postgreSql"; +import { redisText } from "Texts/redis"; + +import { + verifyCouldnotConnectWithAlert, + deleteDatasource, + closeDSModal, + addQuery, + addDsAndAddQuery, + selectDatasource, +} from "Support/utils/dataSource"; + +import { openQueryEditor } from "Support/utils/dataSource"; +import { dataSourceSelector } from "../../../../../constants/selectors/dataSource"; + +const data = {}; +data.dsName = fake.lastName.toLowerCase().replaceAll("[^A-Za-z]", ""); +data.dsName1 = fake.lastName.toLowerCase().replaceAll("[^A-Za-z]", ""); + +describe("Data source Airtable", () => { + beforeEach(() => { + cy.apiLogin(); + cy.defaultWorkspaceLogin(); + }); + + it("Should verify elements on connection AirTable form", () => { + cy.get(commonSelectors.globalDataSourceIcon).click(); + closeDSModal(); + + cy.get(postgreSqlSelector.allDatasourceLabelAndCount).should( + "have.text", + postgreSqlText.allDataSources() + ); + cy.get(postgreSqlSelector.commonlyUsedLabelAndCount).should( + "have.text", + postgreSqlText.commonlyUsed + ); + cy.get(postgreSqlSelector.databaseLabelAndCount).should( + "have.text", + postgreSqlText.allDatabase() + ); + cy.get(postgreSqlSelector.apiLabelAndCount).should( + "have.text", + postgreSqlText.allApis + ); + cy.get(postgreSqlSelector.cloudStorageLabelAndCount).should( + "have.text", + postgreSqlText.allCloudStorage + ); + + selectAndAddDataSource("databases", airtableText.airtable, data.dsName); + + cy.get(postgreSqlSelector.buttonSave).verifyVisibleElement( + "have.text", + postgreSqlText.buttonTextSave + ); + + cy.verifyToastMessage( + commonSelectors.toastMessage, + postgreSqlText.toastDSSaved + ); + deleteDatasource(`cypress-${data.dsName}-airtable`); + }); + + it("Should verify the functionality of AirTable connection form.", () => { + selectAndAddDataSource("databases", airtableText.airtable, data.dsName); + + fillDataSourceTextField( + airtableText.ApiKey, + airtableText.apikeyPlaceholder, + Cypress.env("airTable_apikey") + ); + cy.get(postgreSqlSelector.buttonSave).click(); + + cy.verifyToastMessage( + commonSelectors.toastMessage, + postgreSqlText.toastDSSaved + ); + + cy.get(commonSelectors.globalDataSourceIcon).click(); + cy.get( + `[data-cy="cypress-${data.dsName}-airtable-button"]` + ).verifyVisibleElement("have.text", `cypress-${data.dsName}-airtable`); + deleteDatasource(`cypress-${data.dsName}-airtable`); + }); + + it("Should able to run the query with valid conection", () => { + const airTable_apiKey = Cypress.env("airTable_apikey"); + const airTable_baseId = Cypress.env("airtabelbaseId"); + const airTable_tableName = Cypress.env("airtable_tableName"); + const airTable_recordID = Cypress.env("airtable_recordId"); + + selectAndAddDataSource("databases", airtableText.airtable, data.dsName); + + fillDataSourceTextField( + airtableText.ApiKey, + airtableText.apikeyPlaceholder, + airTable_apiKey + ); + + cy.wait(1000); + cy.get(postgreSqlSelector.buttonSave).click(); + cy.verifyToastMessage( + commonSelectors.toastMessage, + postgreSqlText.toastDSSaved + ); + + cy.get(commonSelectors.globalDataSourceIcon).click(); + cy.get( + `[data-cy="cypress-${data.dsName}-airtable-button"]` + ).verifyVisibleElement("have.text", `cypress-${data.dsName}-airtable`); + cy.get(commonSelectors.dashboardIcon).click(); + cy.get(commonSelectors.appCreateButton).click(); + cy.get(commonSelectors.appNameInput).click().type(data.dsName); + cy.get(commonSelectors.createAppButton).click(); + cy.skipWalkthrough(); + + cy.get('[data-cy="show-ds-popover-button"]').click(); + cy.get(".css-4e90k9").type(`${data.dsName}`); + cy.contains(`[id*="react-select-"]`, data.dsName).click(); + cy.get('[data-cy="query-rename-input"]').clear().type(data.dsName); + + // Verfiy List Recored operation + + cy.get(airTableSelector.operationSelectDropdown) + .click() + .type("List records{enter}"); + + cy.get(airTableSelector.baseIdInputField).clearAndTypeOnCodeMirror( + airTable_baseId + ); + + cy.get(airTableSelector.tableNameInputField).clearAndTypeOnCodeMirror( + airTable_tableName + ); + + cy.get(dataSourceSelector.queryPreviewButton).click(); + cy.verifyToastMessage( + commonSelectors.toastMessage, + `Query (${data.dsName}) completed.` + ); + + // Verfiy Retrieve record operation + + cy.get(airTableSelector.operationSelectDropdown) + .click() + .type("Retrieve record{enter}"); + + cy.get(airTableSelector.baseIdInputField).clearAndTypeOnCodeMirror( + airTable_baseId + ); + cy.get(airTableSelector.tableNameInputField).clearAndTypeOnCodeMirror( + airTable_tableName + ); + + cy.get(airTableSelector.recordIdInputField).clearAndTypeOnCodeMirror( + airTable_recordID + ); + + cy.get(dataSourceSelector.queryPreviewButton).click(); + cy.verifyToastMessage( + commonSelectors.toastMessage, + `Query (${data.dsName}) completed.` + ); + + // Verfiy Create record operation + + cy.get(airTableSelector.operationSelectDropdown) + .click() + .type("Create record{enter}"); + + cy.get(airTableSelector.baseIdInputField).clearAndTypeOnCodeMirror( + airTable_baseId + ); + + cy.get(airTableSelector.tableNameInputField).clearAndTypeOnCodeMirror( + airTable_tableName + ); + + cy.get(airTableSelector.bodyInputField) + .realClick() + .realType('[{"', { force: true, delay: 0 }) + .realType("fields", { force: true, delay: 0 }) + .realType('": {}', { force: true, delay: 0 }); + + cy.get(dataSourceSelector.queryPreviewButton).click(); + cy.verifyToastMessage( + commonSelectors.toastMessage, + `Query (${data.dsName}) completed.` + ); + + // Verfiy Update record operation + + cy.get('[data-cy="show-ds-popover-button"]').click(); + cy.get(".css-4e90k9").type(`${data.dsName}`); + cy.contains(`[id*="react-select-"]`, data.dsName).click(); + cy.get('[data-cy="query-rename-input"]').clear().type(data.dsName1); + + cy.get(airTableSelector.operationSelectDropdown) + .click() + .type("Update record{enter}"); + + cy.get(airTableSelector.baseIdInputField).clearAndTypeOnCodeMirror( + airTable_baseId + ); + cy.get(airTableSelector.tableNameInputField).clearAndTypeOnCodeMirror( + airTable_tableName + ); + + cy.get(airTableSelector.recordIdInputField).clearAndTypeOnCodeMirror( + airTable_recordID + ); + + cy.get(airTableSelector.bodyInputField) + .realClick() + .realType("{", { force: true, delay: 0 }) + .realType("{enter}", { force: true, delay: 0 }) + .realType('"Phone Number": "555_98"', { force: true, delay: 0 }); + + cy.get(dataSourceSelector.queryPreviewButton).click(); + cy.verifyToastMessage( + commonSelectors.toastMessage, + `Query (${data.dsName1}) completed.` + ); + + // Verify Delete record operation + + cy.get(airTableSelector.operationSelectDropdown) + .click() + .type("Delete record{enter}"); + + const recordId = Cypress._.uniqueId("recDummy_"); + + cy.request({ + method: "POST", + url: `https://api.airtable.com/v0/${airTable_baseId}/${airTable_tableName}`, + headers: { + Authorization: `Bearer ${Cypress.env("airTable_apikey")}`, + "Content-Type": "application/json", + }, + body: { + records: [ + { + fields: { + "Employee ID": "E005", + "First Name": "test", + "Last Name": "abc", + Email: "doe@example.com", + "Phone Number": "555-12", + }, + }, + ], + }, + }).then((createResponse) => { + const newRecordId = createResponse.body.records[0].id; + + cy.get(airTableSelector.operationSelectDropdown) + .click() + .type("Delete record{enter}"); + + cy.get(airTableSelector.baseIdInputField).clearAndTypeOnCodeMirror( + airTable_baseId + ); + cy.get(airTableSelector.tableNameInputField).clearAndTypeOnCodeMirror( + airTable_tableName + ); + + cy.get(airTableSelector.recordIdInputField).clearAndTypeOnCodeMirror( + newRecordId + ); + + cy.get(dataSourceSelector.queryPreviewButton).click(); + cy.verifyToastMessage( + commonSelectors.toastMessage, + `Query (${data.dsName1}) completed.` + ); + }); + }); +}); diff --git a/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/amazonAthena.cy.js b/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/amazonAthena.cy.js new file mode 100644 index 0000000000..41bf4183b8 --- /dev/null +++ b/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/amazonAthena.cy.js @@ -0,0 +1,207 @@ +import { fake } from "Fixtures/fake"; +import { postgreSqlSelector } from "Selectors/postgreSql"; +import { pluginSelectors } from "Selectors/plugins"; +import { postgreSqlText } from "Texts/postgreSql"; +import { amazonSesText } from "Texts/amazonSes"; +import { amazonAthenaText } from "Texts/amazonAthena"; +import { commonSelectors } from "Selectors/common"; +import { commonText } from "Texts/common"; + +import { + fillDataSourceTextField, + selectAndAddDataSource, +} from "Support/utils/postgreSql"; + +import { + verifyCouldnotConnectWithAlert, + deleteDatasource, + closeDSModal, + addQuery, + addDsAndAddQuery, +} from "Support/utils/dataSource"; + +import { openQueryEditor } from "Support/utils/dataSource"; +import { dataSourceSelector } from "../../../../../constants/selectors/dataSource"; + +const data = {}; +data.dsName = fake.lastName.toLowerCase().replaceAll("[^A-Za-z]", ""); + +describe("Data source amazon athena", () => { + beforeEach(() => { + cy.apiLogin(); + cy.defaultWorkspaceLogin(); + cy.intercept("POST", "/api/data_queries").as("createQuery"); + }); + + it("Should verify elements on amazon athena connection form", () => { + const Accesskey = Cypress.env("amazonathena_accessKey"); + const Secretkey = Cypress.env("amazonathena_secretKey"); + const DbName = Cypress.env("amazonathena_DbName"); + + cy.get(commonSelectors.globalDataSourceIcon).click(); + closeDSModal(); + + cy.get(postgreSqlSelector.allDatasourceLabelAndCount).should( + "have.text", + postgreSqlText.allDataSources() + ); + cy.get(postgreSqlSelector.commonlyUsedLabelAndCount).should( + "have.text", + postgreSqlText.commonlyUsed + ); + cy.get(postgreSqlSelector.databaseLabelAndCount).should( + "have.text", + postgreSqlText.allDatabase() + ); + cy.get(postgreSqlSelector.apiLabelAndCount).should( + "have.text", + postgreSqlText.allApis + ); + cy.get(postgreSqlSelector.cloudStorageLabelAndCount).should( + "have.text", + postgreSqlText.allCloudStorage + ); + + selectAndAddDataSource( + "databases", + amazonAthenaText.AmazonAthena, + data.dsName + ); + + cy.get(pluginSelectors.amazonAthenaDbName).click().type(DbName); + + cy.get(pluginSelectors.amazonsesAccesKey).click().type(" "); + + fillDataSourceTextField( + amazonSesText.labelSecretKey, + amazonAthenaText.placeholderSecretKey, + Secretkey + ); + + cy.get(".react-select__dropdown-indicator").eq(1).click(); + cy.get(".react-select__option").contains("US West (N. California)").click(); + + cy.get(postgreSqlSelector.buttonTestConnection) + .verifyVisibleElement( + "have.text", + postgreSqlText.buttonTextTestConnection + ) + .click(); + cy.get(postgreSqlSelector.connectionFailedText).verifyVisibleElement( + "have.text", + postgreSqlText.couldNotConnect + ); + cy.get(postgreSqlSelector.buttonSave) + .verifyVisibleElement("have.text", postgreSqlText.buttonTextSave) + .click(); + cy.verifyToastMessage( + commonSelectors.toastMessage, + postgreSqlText.toastDSSaved + ); + + deleteDatasource(`cypress-${data.dsName}-Amazon-Athena`); + }); + + it("Should verify the functionality of amazon athena connection form.", () => { + const Accesskey = Cypress.env("amazonathena_accessKey"); + const Secretkey = Cypress.env("amazonathena_secretKey"); + const DbName = Cypress.env("amazonathena_DbName"); + selectAndAddDataSource( + "databases", + amazonAthenaText.AmazonAthena, + data.dsName + ); + + cy.get(pluginSelectors.amazonAthenaDbName).click().type(DbName); + + cy.get(pluginSelectors.amazonsesAccesKey).click().type(Accesskey); + + fillDataSourceTextField( + amazonSesText.labelSecretKey, + amazonAthenaText.placeholderSecretKey, + Secretkey + ); + + cy.get(".react-select__dropdown-indicator").eq(1).click(); + cy.get(".react-select__option").contains("US West (N. California)").click(); + + cy.get(postgreSqlSelector.buttonTestConnection).click(); + cy.get(postgreSqlSelector.textConnectionVerified, { + timeout: 10000, + }).should("have.text", postgreSqlText.labelConnectionVerified); + cy.get(postgreSqlSelector.buttonSave).click(); + + cy.verifyToastMessage( + commonSelectors.toastMessage, + postgreSqlText.toastDSSaved + ); + + deleteDatasource(`cypress-${data.dsName}-amazon-Athena`); + }); + + it("Should able to run the query with valid conection", () => { + const Accesskey = Cypress.env("amazonathena_accessKey"); + const Secretkey = Cypress.env("amazonathena_secretKey"); + const DbName = Cypress.env("amazonathena_DbName"); + selectAndAddDataSource( + "databases", + amazonAthenaText.AmazonAthena, + data.dsName + ); + + cy.get(pluginSelectors.amazonAthenaDbName).click().type(DbName); + + fillDataSourceTextField( + amazonAthenaText.labelAccesskey, + amazonAthenaText.placeholderEnteraAccessKey, + Cypress.env("amazonathena_accessKey") + ); + fillDataSourceTextField( + amazonAthenaText.labelSecretKey, + amazonAthenaText.placeholderSecretKey, + Cypress.env("amazonathena_secretKey") + ); + + cy.get(".react-select__dropdown-indicator").eq(1).click(); + cy.get(".react-select__option").contains("US West (N. California)").click(); + + cy.get(postgreSqlSelector.buttonTestConnection).click(); + cy.get(postgreSqlSelector.textConnectionVerified, { + timeout: 10000, + }).should("have.text", postgreSqlText.labelConnectionVerified); + + cy.get(postgreSqlSelector.buttonSave).click(); + + cy.verifyToastMessage( + commonSelectors.toastMessage, + postgreSqlText.toastDSSaved + ); + + cy.get(commonSelectors.globalDataSourceIcon).click(); + cy.get( + `[data-cy="cypress-${data.dsName}-amazon-athena-button"]` + ).verifyVisibleElement("have.text", `cypress-${data.dsName}-amazon-athena`); + cy.wait(1000); + + cy.get(commonSelectors.dashboardIcon).click(); + cy.get(commonSelectors.appCreateButton).click(); + cy.get(commonSelectors.appNameInput).click().type(data.dsName); + cy.get(commonSelectors.createAppButton).click(); + cy.skipWalkthrough(); + + cy.get('[data-cy="show-ds-popover-button"]').click(); + cy.get(".css-4e90k9").type(`${data.dsName}`); + cy.contains(`[id*="react-select-"]`, data.dsName).click(); + cy.get('[data-cy="query-rename-input"]').clear().type(data.dsName); + + cy.get('[data-cy="query-input-field"]').clearAndTypeOnCodeMirror( + "SHOW DATABASES;" + ); + + cy.get(dataSourceSelector.queryPreviewButton).click(); + cy.verifyToastMessage( + commonSelectors.toastMessage, + `Query (${data.dsName}) completed.` + ); + }); +}); diff --git a/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/amazonses.cy.js b/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/amazonses.cy.js new file mode 100644 index 0000000000..d1ec035a69 --- /dev/null +++ b/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/amazonses.cy.js @@ -0,0 +1,204 @@ +import { fake } from "Fixtures/fake"; +import { postgreSqlSelector } from "Selectors/postgreSql"; +import { pluginSelectors } from "Selectors/plugins"; +import { postgreSqlText } from "Texts/postgreSql"; +import { amazonSesText } from "Texts/amazonSes"; +import { commonSelectors } from "Selectors/common"; +import { commonText } from "Texts/common"; + +import { + fillDataSourceTextField, + selectAndAddDataSource, +} from "Support/utils/postgreSql"; + +import { + verifyCouldnotConnectWithAlert, + deleteDatasource, + closeDSModal, + addQuery, + addDsAndAddQuery, +} from "Support/utils/dataSource"; + +import { openQueryEditor } from "Support/utils/dataSource"; +import { dataSourceSelector } from "../../../../../constants/selectors/dataSource"; + +const data = {}; +data.dsName = fake.lastName.toLowerCase().replaceAll("[^A-Za-z]", ""); + +describe("Data source amazon ses", () => { + beforeEach(() => { + cy.apiLogin(); + cy.defaultWorkspaceLogin(); + cy.intercept("POST", "/api/data_queries").as("createQuery"); + }); + + it("Should verify elements on amazonses connection form", () => { + const Accesskey = Cypress.env("amazonSes_accessKey"); + const Secretkey = Cypress.env("amazonSes_secretKey"); + + cy.get(commonSelectors.globalDataSourceIcon).click(); + closeDSModal(); + + cy.get(postgreSqlSelector.allDatasourceLabelAndCount).should( + "have.text", + postgreSqlText.allDataSources() + ); + cy.get(postgreSqlSelector.commonlyUsedLabelAndCount).should( + "have.text", + postgreSqlText.commonlyUsed + ); + cy.get(postgreSqlSelector.databaseLabelAndCount).should( + "have.text", + postgreSqlText.allDatabase() + ); + cy.get(postgreSqlSelector.apiLabelAndCount).should( + "have.text", + postgreSqlText.allApis + ); + cy.get(postgreSqlSelector.cloudStorageLabelAndCount).should( + "have.text", + postgreSqlText.allCloudStorage + ); + + selectAndAddDataSource("databases", amazonSesText.AmazonSES, data.dsName); + + cy.get(".react-select__dropdown-indicator").eq(1).click(); + cy.get(".react-select__option").contains("US West (N. California)").click(); + + cy.get(pluginSelectors.amazonsesAccesKey).click().type(Accesskey); + + fillDataSourceTextField( + amazonSesText.labelSecretKey, + "**************", + Secretkey + ); + + cy.get(postgreSqlSelector.buttonSave) + .verifyVisibleElement("have.text", postgreSqlText.buttonTextSave) + .click(); + cy.verifyToastMessage( + commonSelectors.toastMessage, + postgreSqlText.toastDSSaved + ); + + deleteDatasource(`cypress-${data.dsName}-Amazon-ses`); + }); + + it("Should verify the functionality of amazonses connection form.", () => { + selectAndAddDataSource("databases", amazonSesText.AmazonSES, data.dsName); + + cy.get(".react-select__dropdown-indicator").eq(1).click(); + cy.get(".react-select__option").contains("US West (N. California)").click(); + + fillDataSourceTextField( + amazonSesText.labelAccesskey, + amazonSesText.placeholderAccessKey, + Cypress.env("amazonSes_accessKey") + ); + fillDataSourceTextField( + amazonSesText.labelSecretKey, + amazonSesText.placeholderSecretKey, + Cypress.env("amazonSes_secretKey") + ); + + cy.get(postgreSqlSelector.buttonSave).click(); + + cy.verifyToastMessage( + commonSelectors.toastMessage, + postgreSqlText.toastDSSaved + ); + + cy.get(commonSelectors.globalDataSourceIcon).click(); + cy.get( + `[data-cy="cypress-${data.dsName}-amazon-ses-button"]` + ).verifyVisibleElement("have.text", `cypress-${data.dsName}-amazon-ses`); + + deleteDatasource(`cypress-${data.dsName}-amazon-ses`); + }); + + it("Should able to run the query with valid conection", () => { + const email = "adish" + "@" + "tooljet.com"; + selectAndAddDataSource("databases", amazonSesText.AmazonSES, data.dsName); + + cy.get(".react-select__dropdown-indicator").eq(1).click(); + cy.get(".react-select__option").contains("US West (N. California)").click(); + + fillDataSourceTextField( + amazonSesText.labelAccesskey, + amazonSesText.placeholderAccessKey, + Cypress.env("amazonSes_accessKey") + ); + fillDataSourceTextField( + amazonSesText.labelSecretKey, + amazonSesText.placeholderSecretKey, + Cypress.env("amazonSes_secretKey") + ); + + cy.get(postgreSqlSelector.buttonSave).click(); + + cy.verifyToastMessage( + commonSelectors.toastMessage, + postgreSqlText.toastDSSaved + ); + + cy.get(commonSelectors.globalDataSourceIcon).click(); + cy.get( + `[data-cy="cypress-${data.dsName}-amazon-ses-button"]` + ).verifyVisibleElement("have.text", `cypress-${data.dsName}-amazon-ses`); + cy.wait(1000); + + cy.get(commonSelectors.dashboardIcon).click(); + cy.get(commonSelectors.appCreateButton).click(); + cy.get(commonSelectors.appNameInput).click().type(data.dsName); + cy.get(commonSelectors.createAppButton).click(); + cy.skipWalkthrough(); + + cy.get('[data-cy="show-ds-popover-button"]').click(); + cy.get(".css-4e90k9").type(`${data.dsName}`); + cy.contains(`[id*="react-select-"]`, data.dsName).click(); + cy.get('[data-cy="query-rename-input"]').clear().type(data.dsName); + + cy.get(pluginSelectors.operationDropdown) + .click() + .type("Email service{enter}"); + + cy.wait(500); + + cy.get(pluginSelectors.sendEmailInputField) + .realClick() + .realType('{{["', { force: true, delay: 0 }) + .realType("mekhla@tooljet.com", { force: true, delay: 0 }); + + cy.get(pluginSelectors.ccEmailInputField) + .realClick() + .realType('{{["', { force: true, delay: 0 }) + .realType("mani@tooljet.com", { force: true, delay: 0 }); + + cy.get(pluginSelectors.bccEmailInputField) + .realClick() + .realType('{{["', { force: true, delay: 0 }) + .realType("midhun@tooljet.com", { force: true, delay: 0 }); + + cy.get(pluginSelectors.sendEmailFromInputField) + .realClick() + .realType("adish", { force: true, delay: 0 }) + .realType("@", { force: true, delay: 0 }) + .realType("tooljet.com", { force: true, delay: 0 }); + + cy.get(pluginSelectors.emailSubjetInputField).clearAndTypeOnCodeMirror( + "Testmail for amazon ses" + ); + + cy.get(pluginSelectors.emailbodyInputField).clearAndTypeOnCodeMirror( + "Body text for amazon ses" + ); + + cy.wait(1000); + + cy.get(dataSourceSelector.queryPreviewButton).click(); + cy.verifyToastMessage( + commonSelectors.toastMessage, + `Query (${data.dsName}) completed.` + ); + }); +}); diff --git a/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/appWrite.cy.js b/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/appWrite.cy.js new file mode 100644 index 0000000000..aeeb12529d --- /dev/null +++ b/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/appWrite.cy.js @@ -0,0 +1,308 @@ +import { fake } from "Fixtures/fake"; +import { postgreSqlSelector } from "Selectors/postgreSql"; +import { postgreSqlText } from "Texts/postgreSql"; +import { appwriteText } from "Texts/appWrite"; +import { appWriteSelectors } from "Selectors/Plugins"; +import { commonSelectors } from "Selectors/common"; +import { commonText } from "Texts/common"; + +import { + fillDataSourceTextField, + selectAndAddDataSource, +} from "Support/utils/postgreSql"; + +import { + verifyCouldnotConnectWithAlert, + deleteDatasource, + closeDSModal, + addQuery, + addDsAndAddQuery, +} from "Support/utils/dataSource"; + +import { openQueryEditor } from "Support/utils/dataSource"; +import { dataSourceSelector } from "../../../../../constants/selectors/dataSource"; + +const data = {}; +data.dsName = fake.lastName.toLowerCase().replaceAll("[^A-Za-z]", ""); + +describe("Data source AppWrite", () => { + beforeEach(() => { + cy.apiLogin(); + cy.defaultWorkspaceLogin(); + cy.intercept("POST", "/api/data_queries").as("createQuery"); + }); + + it("Should verify elements on appwrite connection form", () => { + const Host = Cypress.env("appwrite_host"); + const ProjectID = Cypress.env("appwrite_projectID"); + const DatabaseID = Cypress.env("appwrite_databaseID"); + const SecretKey = Cypress.env("appwrite_secretkey"); + + cy.get(commonSelectors.globalDataSourceIcon).click(); + closeDSModal(); + + cy.get(postgreSqlSelector.commonlyUsedLabelAndCount).should( + "have.text", + postgreSqlText.commonlyUsed + ); + + cy.get(postgreSqlSelector.apiLabelAndCount).should( + "have.text", + postgreSqlText.allApis + ); + cy.get(postgreSqlSelector.cloudStorageLabelAndCount).should( + "have.text", + postgreSqlText.allCloudStorage + ); + + selectAndAddDataSource("databases", appwriteText.appwrite, data.dsName); + + fillDataSourceTextField( + appwriteText.host, + appwriteText.hostPlaceholder, + Host + ); + + fillDataSourceTextField( + appwriteText.ProjectID, + appwriteText.projectIdPlaceholder, + ProjectID + ); + + fillDataSourceTextField( + appwriteText.DatabaseID, + appwriteText.databaseIdPlaceholder, + DatabaseID + ); + + fillDataSourceTextField( + appwriteText.SecretKey, + appwriteText.SecretKeyPlaceholder, + SecretKey + ); + + cy.get(postgreSqlSelector.buttonTestConnection).click(); + cy.get(postgreSqlSelector.textConnectionVerified, { + timeout: 10000, + }).should("have.text", postgreSqlText.labelConnectionVerified); + + cy.get(postgreSqlSelector.buttonSave) + .verifyVisibleElement("have.text", postgreSqlText.buttonTextSave) + .click(); + cy.verifyToastMessage( + commonSelectors.toastMessage, + postgreSqlText.toastDSSaved + ); + + deleteDatasource(`cypress-${data.dsName}-Appwrite`); + }); + + it("Should verify the functionality of appwrite connection form.", () => { + const Host = Cypress.env("appwrite_host"); + const ProjectID = Cypress.env("appwrite_projectID"); + const DatabaseID = Cypress.env("appwrite_databaseID"); + const SecretKey = Cypress.env("appwrite_secretkey"); + + cy.get(commonSelectors.globalDataSourceIcon).click(); + closeDSModal(); + + selectAndAddDataSource("databases", appwriteText.appwrite, data.dsName); + + fillDataSourceTextField( + appwriteText.host, + appwriteText.hostPlaceholder, + Host + ); + + fillDataSourceTextField( + appwriteText.ProjectID, + appwriteText.projectIdPlaceholder, + ProjectID + ); + + fillDataSourceTextField( + appwriteText.DatabaseID, + appwriteText.databaseIdPlaceholder, + DatabaseID + ); + + fillDataSourceTextField( + appwriteText.SecretKey, + appwriteText.SecretKeyPlaceholder, + SecretKey + ); + + cy.get(postgreSqlSelector.buttonTestConnection).click(); + cy.get(postgreSqlSelector.textConnectionVerified, { + timeout: 10000, + }).should("have.text", postgreSqlText.labelConnectionVerified); + + cy.get(postgreSqlSelector.buttonSave) + .verifyVisibleElement("have.text", postgreSqlText.buttonTextSave) + .click(); + cy.verifyToastMessage( + commonSelectors.toastMessage, + postgreSqlText.toastDSSaved + ); + deleteDatasource(`cypress-${data.dsName}-Appwrite`); + }); + + it("Should be able to run the query with a valid connection", () => { + const Host = Cypress.env("appwrite_host"); + const ProjectID = Cypress.env("appwrite_projectID"); + const DatabaseID = Cypress.env("appwrite_databaseID"); + const SecretKey = Cypress.env("appwrite_secretkey"); + const CollectionID = Cypress.env("appwrite_collectionID"); + + cy.get(commonSelectors.globalDataSourceIcon).click(); + closeDSModal(); + + selectAndAddDataSource("databases", appwriteText.appwrite, data.dsName); + + fillDataSourceTextField( + appwriteText.host, + appwriteText.hostPlaceholder, + Host + ); + fillDataSourceTextField( + appwriteText.ProjectID, + appwriteText.projectIdPlaceholder, + ProjectID + ); + fillDataSourceTextField( + appwriteText.DatabaseID, + appwriteText.databaseIdPlaceholder, + DatabaseID + ); + fillDataSourceTextField( + appwriteText.SecretKey, + appwriteText.SecretKeyPlaceholder, + SecretKey + ); + + cy.get(postgreSqlSelector.buttonTestConnection).click(); + + cy.get(postgreSqlSelector.textConnectionVerified, { + timeout: 10000, + }).should("have.text", postgreSqlText.labelConnectionVerified); + cy.get(postgreSqlSelector.buttonSave) + .verifyVisibleElement("have.text", postgreSqlText.buttonTextSave) + .click(); + + cy.verifyToastMessage( + commonSelectors.toastMessage, + postgreSqlText.toastDSSaved + ); + + cy.get(commonSelectors.globalDataSourceIcon).click(); + cy.get( + `[data-cy="cypress-${data.dsName}-appwrite-button"]` + ).verifyVisibleElement("have.text", `cypress-${data.dsName}-appwrite`); + cy.wait(1000); + + cy.get(commonSelectors.dashboardIcon).click(); + cy.get(commonSelectors.appCreateButton).click(); + cy.get(commonSelectors.appNameInput).click().type(data.dsName); + cy.get(commonSelectors.createAppButton).click(); + cy.skipWalkthrough(); + + cy.get('[data-cy="show-ds-popover-button"]').click(); + cy.get(".css-4e90k9").type(`${data.dsName}`); + cy.contains(`[id*="react-select-"]`, data.dsName).click(); + cy.get('[data-cy="query-rename-input"]').clear().type(data.dsName); + + // Create API document for delete operation + + cy.request({ + method: "POST", + url: `https://cloud.appwrite.io/v1/databases/${DatabaseID}/collections/${CollectionID}/documents`, + headers: { + "X-Appwrite-Project": ProjectID, + "X-Appwrite-Key": SecretKey, + "Content-Type": "application/json", + }, + body: { + documentId: "unique()", + data: { + User_name: "test", + User_ID: 30, + }, + permissions: ['read("any")'], + }, + }).then((response) => { + expect(response.status).to.eq(201); + cy.wrap(response.body.$id).as("documentId"); + }); + + // Verify all operations + const operations = [ + "List documents", + "Get document", + "Add Document to Collection", + "Update document", + "Delete document", + ]; + + cy.get("@documentId").then((documentId) => { + operations.forEach((operation) => { + cy.get(".react-select__input") + .eq(1) + .type(`${operation}{enter}`, { force: true }); + + if (operation === "Get document") { + cy.get(appWriteSelectors.collectionId).clearAndTypeOnCodeMirror( + CollectionID + ); + + cy.get(appWriteSelectors.documentId).clearAndTypeOnCodeMirror( + Cypress.env("appwrite_documentID") + ); + } + + if (operation === "Add Document to Collection") { + cy.get(appWriteSelectors.collectionId).clearAndTypeOnCodeMirror( + CollectionID + ); + cy.get(appWriteSelectors.bodyInput).clearAndTypeOnCodeMirror( + '{"User_name": "John Updated", "User_ID": 35}' + ); + } + + if (operation === "Update document") { + cy.get(appWriteSelectors.collectionId).clearAndTypeOnCodeMirror( + CollectionID + ); + + cy.get(appWriteSelectors.documentId).clearAndTypeOnCodeMirror( + Cypress.env("appwrite_documentID") + ); + cy.get(appWriteSelectors.bodyInput).clearAndTypeOnCodeMirror( + '{"User_name": "John Updated", "User_ID": 35}' + ); + } + + if (operation === "List documents") { + cy.get(appWriteSelectors.collectionId).clearAndTypeOnCodeMirror( + CollectionID + ); + } + + if (operation === "Delete document") { + cy.get(appWriteSelectors.collectionId).clearAndTypeOnCodeMirror( + CollectionID + ); + cy.get(appWriteSelectors.documentId).clearAndTypeOnCodeMirror( + documentId + ); + } + cy.get(dataSourceSelector.queryPreviewButton).click(); + + // Verify toast message + cy.verifyToastMessage( + commonSelectors.toastMessage, + `Query (${data.dsName}) completed.` + ); + }); + }); + }); +}); diff --git a/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/baseRow.cy.js b/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/baseRow.cy.js new file mode 100644 index 0000000000..4c0532a9ca --- /dev/null +++ b/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/baseRow.cy.js @@ -0,0 +1,219 @@ +import { fake } from "Fixtures/fake"; +import { postgreSqlSelector } from "Selectors/postgreSql"; +import { pluginSelectors, baserowSelectors } from "Selectors/plugins"; +import { postgreSqlText } from "Texts/postgreSql"; +import { amazonSesText } from "Texts/amazonSes"; +import { baseRowText } from "Texts/baseRow"; +import { amazonAthenaText } from "Texts/amazonAthena"; +import { commonSelectors } from "Selectors/common"; +import { commonText } from "Texts/common"; + +import { + fillDataSourceTextField, + selectAndAddDataSource, +} from "Support/utils/postgreSql"; + +import { + verifyCouldnotConnectWithAlert, + deleteDatasource, + closeDSModal, + addQuery, + addDsAndAddQuery, +} from "Support/utils/dataSource"; + +import { openQueryEditor } from "Support/utils/dataSource"; +import { dataSourceSelector } from "../../../../../constants/selectors/dataSource"; + +const data = {}; +data.dsName = fake.lastName.toLowerCase().replaceAll("[^A-Za-z]", ""); + +describe("Data source baserow", () => { + beforeEach(() => { + cy.apiLogin(); + cy.defaultWorkspaceLogin(); + cy.intercept("POST", "/api/data_queries").as("createQuery"); + }); + + it("Should verify elements on baserow connection form", () => { + const Apikey = Cypress.env("baserow_apikey"); + + cy.get(commonSelectors.globalDataSourceIcon).click(); + closeDSModal(); + + cy.get(postgreSqlSelector.allDatasourceLabelAndCount).should( + "have.text", + postgreSqlText.allDataSources() + ); + cy.get(postgreSqlSelector.commonlyUsedLabelAndCount).should( + "have.text", + postgreSqlText.commonlyUsed + ); + cy.get(postgreSqlSelector.databaseLabelAndCount).should( + "have.text", + postgreSqlText.allDatabase() + ); + cy.get(postgreSqlSelector.apiLabelAndCount).should( + "have.text", + postgreSqlText.allApis + ); + cy.get(postgreSqlSelector.cloudStorageLabelAndCount).should( + "have.text", + postgreSqlText.allCloudStorage + ); + + selectAndAddDataSource("databases", baseRowText.baserow, data.dsName); + + fillDataSourceTextField( + baseRowText.lableApiToken, + baseRowText.placeholderApiToken, + Apikey + ); + + cy.get(".react-select__control").eq(1).click(); + + cy.get(".react-select__option").contains("Baserow Cloud").click(); + + cy.get(postgreSqlSelector.buttonSave) + .verifyVisibleElement("have.text", postgreSqlText.buttonTextSave) + .click(); + cy.verifyToastMessage( + commonSelectors.toastMessage, + postgreSqlText.toastDSSaved + ); + + deleteDatasource(`cypress-${data.dsName}-baserow`); + }); + + it("Should verify the functionality of baserow connection form.", () => { + const Apikey = Cypress.env("baserow_apikey"); + + selectAndAddDataSource("databases", baseRowText.baserow, data.dsName); + + fillDataSourceTextField( + baseRowText.lableApiToken, + baseRowText.placeholderApiToken, + Apikey + ); + + cy.get(".react-select__control").eq(1).click(); + + cy.get(".react-select__option").contains("Baserow Cloud").click(); + + cy.get(postgreSqlSelector.buttonSave) + .verifyVisibleElement("have.text", postgreSqlText.buttonTextSave) + .click(); + cy.verifyToastMessage( + commonSelectors.toastMessage, + postgreSqlText.toastDSSaved + ); + deleteDatasource(`cypress-${data.dsName}-baserow`); + }); + + it("Should be able to run the query with a valid connection", () => { + const baserowTableID = Cypress.env("baserow_tableid"); + const baserowRowID = Cypress.env("baserow_rowid"); + const Apikey = Cypress.env("baserow_apikey"); + + selectAndAddDataSource("databases", baseRowText.baserow, data.dsName); + + fillDataSourceTextField( + baseRowText.lableApiToken, + baseRowText.placeholderApiToken, + Apikey + ); + + cy.get(".react-select__control").eq(1).click(); + cy.get(".react-select__option").contains("Baserow Cloud").click(); + + cy.get(postgreSqlSelector.buttonSave) + .verifyVisibleElement("have.text", postgreSqlText.buttonTextSave) + .click(); + cy.verifyToastMessage( + commonSelectors.toastMessage, + postgreSqlText.toastDSSaved + ); + + cy.get(commonSelectors.globalDataSourceIcon).click(); + cy.get( + `[data-cy="cypress-${data.dsName}-baserow-button"]` + ).verifyVisibleElement("have.text", `cypress-${data.dsName}-baserow`); + cy.wait(1000); + + cy.log("Baserow Table ID:", baserowTableID); + cy.log("Row ID:", baserowRowID); + cy.log("API Key:", Apikey); + + if (!baserowTableID || !Apikey) { + throw new Error("Missing required environment variables!"); + } + + cy.request({ + method: "POST", + url: `https://api.baserow.io/api/database/rows/table/${baserowTableID}/`, + headers: { Authorization: `Token ${Apikey}` }, + body: { + field_1: "Sample Data", + field_2: "Another Value", + }, + }).then((response) => { + expect(response.status).to.eq(200); + const rowId = response.body.id; + + cy.get(commonSelectors.dashboardIcon).click(); + cy.get(commonSelectors.appCreateButton).click(); + cy.get(commonSelectors.appNameInput).click().type(data.dsName); + cy.get(commonSelectors.createAppButton).click(); + cy.skipWalkthrough(); + + cy.get('[data-cy="show-ds-popover-button"]').click(); + cy.get(".css-4e90k9").type(`${data.dsName}`); + cy.contains(`[id*="react-select-"]`, data.dsName).click(); + cy.get('[data-cy="query-rename-input"]').clear().type(data.dsName); + + // Verify delete operation (Need to uncomment after bug fixes) + + // cy.get('[data-cy="operation-select-dropdown"]').click(); + // cy.get(".react-select__option").contains("Delete row").click(); + + // cy.get(baserowSelectors.baserowTabelId).clearAndTypeOnCodeMirror(baserowTableID); + // cy.get(baserowSelectors.rowIdinputfield).clearAndTypeOnCodeMirror(rowId.toString()); + + // cy.get(dataSourceSelector.queryPreviewButton).click(); + // cy.verifyToastMessage(commonSelectors.toastMessage, `Query (${data.dsName}) completed.`); + }); + + // Verify other operations + const operations = [ + "List fields", + "List rows", + "Get row", + "Create row", + "Update row", + "Move row", + ]; + + operations.forEach((operation) => { + cy.get(pluginSelectors.operationDropdown).click(); + cy.get(".react-select__option").contains(operation).click(); + + cy.get(baserowSelectors.table).clearAndTypeOnCodeMirror(baserowTableID); + + if (operation === "Get row") { + cy.get(baserowSelectors.rowIdinputfield).clearAndTypeOnCodeMirror( + baserowRowID + ); + } + if (operation === "Move row") { + cy.get('[data-cy="before-id-input-field"]').clearAndTypeOnCodeMirror( + "1" + ); + } + + cy.get(dataSourceSelector.queryPreviewButton).click(); + cy.verifyToastMessage( + commonSelectors.toastMessage, + `Query (${data.dsName}) completed.` + ); + }); + }); +}); diff --git a/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/minio.cy.js b/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/minio.cy.js new file mode 100644 index 0000000000..e25111b9b6 --- /dev/null +++ b/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/minio.cy.js @@ -0,0 +1,278 @@ +import { fake } from "Fixtures/fake"; +import { postgreSqlSelector } from "Selectors/postgreSql"; +import { postgreSqlText } from "Texts/postgreSql"; +import { minioText } from "Texts/minio"; +import { minioSelectors } from "Selectors/Plugins"; +import { commonSelectors } from "Selectors/common"; +import { commonText } from "Texts/common"; + +import { + fillDataSourceTextField, + selectAndAddDataSource, +} from "Support/utils/postgreSql"; + +import { + verifyCouldnotConnectWithAlert, + deleteDatasource, + closeDSModal, + addQuery, + addDsAndAddQuery, +} from "Support/utils/dataSource"; + +import { openQueryEditor } from "Support/utils/dataSource"; +import { dataSourceSelector } from "../../../../../constants/selectors/dataSource"; + +const data = {}; +data.dsName = fake.lastName.toLowerCase().replaceAll("[^A-Za-z]", ""); + +describe("Data source minio", () => { + beforeEach(() => { + cy.apiLogin(); + cy.defaultWorkspaceLogin(); + }); + + it("Should verify elements on minio connection form", () => { + const Host = Cypress.env("minio_host"); + const Port = Cypress.env("minio_port"); + const AccessKey = Cypress.env("minio_accesskey"); + const SecretKey = Cypress.env("minio_secretkey"); + + cy.get(commonSelectors.globalDataSourceIcon).click(); + closeDSModal(); + + cy.get(postgreSqlSelector.commonlyUsedLabelAndCount).should( + "have.text", + postgreSqlText.commonlyUsed + ); + + cy.get(postgreSqlSelector.apiLabelAndCount).should( + "have.text", + postgreSqlText.allApis + ); + + cy.get(postgreSqlSelector.cloudStorageLabelAndCount).should( + "have.text", + postgreSqlText.allCloudStorage + ); + + selectAndAddDataSource("databases", minioText.minio, data.dsName); + + fillDataSourceTextField( + minioText.hostLabel, + minioText.hostInputPlaceholder, + Host + ); + + fillDataSourceTextField( + minioText.portLabel, + minioText.portPlaceholder, + Port + ); + + cy.get(`[${minioSelectors.sslToggle}]`).click(); + + fillDataSourceTextField( + minioText.labelAccesskey, + minioText.placeholderAccessKey, + AccessKey + ); + + fillDataSourceTextField( + minioText.labelSecretKey, + minioText.placeholderSecretKey, + SecretKey + ); + + cy.get(postgreSqlSelector.buttonTestConnection).click(); + cy.get(postgreSqlSelector.textConnectionVerified, { + timeout: 10000, + }).should("have.text", postgreSqlText.labelConnectionVerified); + + cy.get(postgreSqlSelector.buttonSave) + .verifyVisibleElement("have.text", postgreSqlText.buttonTextSave) + .click(); + + cy.verifyToastMessage( + commonSelectors.toastMessage, + postgreSqlText.toastDSSaved + ); + + deleteDatasource(`cypress-${data.dsName}-minio`); + }); + + it("Should verify functionality of minio connection form", () => { + const Host = Cypress.env("minio_host"); + const Port = Cypress.env("minio_port"); + const AccessKey = Cypress.env("minio_accesskey"); + const SecretKey = Cypress.env("minio_secretkey"); + + cy.get(commonSelectors.globalDataSourceIcon).click(); + closeDSModal(); + + selectAndAddDataSource("databases", minioText.minio, data.dsName); + + fillDataSourceTextField( + minioText.hostLabel, + minioText.hostInputPlaceholder, + Host + ); + + fillDataSourceTextField( + minioText.portLabel, + minioText.portPlaceholder, + Port + ); + + cy.get(`[${minioSelectors.sslToggle}]`).click(); + + fillDataSourceTextField( + minioText.labelAccesskey, + minioText.placeholderAccessKey, + AccessKey + ); + + fillDataSourceTextField( + minioText.labelSecretKey, + minioText.placeholderSecretKey, + SecretKey + ); + + cy.get(postgreSqlSelector.buttonTestConnection).click(); + cy.get(postgreSqlSelector.textConnectionVerified, { + timeout: 10000, + }).should("have.text", postgreSqlText.labelConnectionVerified); + + cy.get(postgreSqlSelector.buttonSave) + .verifyVisibleElement("have.text", postgreSqlText.buttonTextSave) + .click(); + + cy.verifyToastMessage( + commonSelectors.toastMessage, + postgreSqlText.toastDSSaved + ); + + deleteDatasource(`cypress-${data.dsName}-minio`); + }); + + it("Should be able to run the query with a valid connection", () => { + const Host = Cypress.env("minio_host"); + const Port = Cypress.env("minio_port"); + const AccessKey = Cypress.env("minio_accesskey"); + const SecretKey = Cypress.env("minio_secretkey"); + + cy.get(commonSelectors.globalDataSourceIcon).click(); + closeDSModal(); + + selectAndAddDataSource("databases", minioText.minio, data.dsName); + + fillDataSourceTextField( + minioText.hostLabel, + minioText.hostInputPlaceholder, + Host + ); + + fillDataSourceTextField( + minioText.portLabel, + minioText.portPlaceholder, + Port + ); + + cy.get(`[${minioSelectors.sslToggle}]`).click(); + + fillDataSourceTextField( + minioText.labelAccesskey, + minioText.placeholderAccessKey, + AccessKey + ); + + fillDataSourceTextField( + minioText.labelSecretKey, + minioText.placeholderSecretKey, + SecretKey + ); + + cy.get(postgreSqlSelector.buttonTestConnection).click(); + cy.get(postgreSqlSelector.textConnectionVerified, { + timeout: 10000, + }).should("have.text", postgreSqlText.labelConnectionVerified); + + cy.get(postgreSqlSelector.buttonSave) + .verifyVisibleElement("have.text", postgreSqlText.buttonTextSave) + .click(); + + cy.verifyToastMessage( + commonSelectors.toastMessage, + postgreSqlText.toastDSSaved + ); + + cy.get(commonSelectors.dashboardIcon).click(); + cy.get(commonSelectors.appCreateButton).click(); + cy.get(commonSelectors.appNameInput).click().type(data.dsName); + cy.get(commonSelectors.createAppButton).click(); + cy.skipWalkthrough(); + + cy.get('[data-cy="show-ds-popover-button"]').click(); + cy.get(".css-4e90k9").type(`${data.dsName}`); + cy.contains(`[id*="react-select-"]`, data.dsName).click(); + cy.get('[data-cy="query-rename-input"]').clear().type(data.dsName); + + const operationsMinio = [ + "List buckets", + "Put object", + "List objects in a bucket", + "Read object", + "Presigned url for download", + "Presigned url for upload", + "Remove object", + ]; + + operationsMinio.forEach((operation) => { + cy.get(".react-select__input") + .eq(1) + .type(`${operation}{enter}`, { force: true }); + + if (operation === "List objects in a bucket") { + cy.get(minioSelectors.bucketNameInputField).clearAndTypeOnCodeMirror( + minioText.bucketName + ); + } + if (operation === "Read object" || operation === "Remove object") { + cy.get(minioSelectors.bucketNameInputField).clearAndTypeOnCodeMirror( + minioText.bucketName + ); + cy.get(minioSelectors.objectNameInputField).clearAndTypeOnCodeMirror( + minioText.objectName + ); + } + if (operation === "Put object") { + cy.get(minioSelectors.bucketNameInputField).clearAndTypeOnCodeMirror( + minioText.bucketName + ); + cy.get(minioSelectors.objectNameInputField).clearAndTypeOnCodeMirror( + minioText.objectName + ); + cy.get(minioSelectors.contentTypeInputField).clearAndTypeOnCodeMirror( + '"string"' + ); + cy.get(minioSelectors.dataInput).clearAndTypeOnCodeMirror(`test`); + } + if ( + operation === "Presigned url for download" || + operation === "Presigned url for upload" + ) { + cy.get(minioSelectors.bucketNameInputField).clearAndTypeOnCodeMirror( + minioText.bucketName + ); + cy.get(minioSelectors.objectNameInputField).clearAndTypeOnCodeMirror( + minioText.objectName + ); + } + + cy.get(dataSourceSelector.queryPreviewButton).click(); + cy.verifyToastMessage( + commonSelectors.toastMessage, + `Query (${data.dsName}) completed.` + ); + }); + }); +}); diff --git a/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/oracleDbHappyPath.cy.skip.js b/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/oracleDbHappyPath.cy.skip.js index c42bda600b..e7ae4f296b 100644 --- a/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/oracleDbHappyPath.cy.skip.js +++ b/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/oracleDbHappyPath.cy.skip.js @@ -123,7 +123,7 @@ describe("Data sources", () => { ); cy.clearAndType( - '[data-cy="data-source-name-input-filed"]', + '[data-cy="data-source-name-input-field"]', postgreSqlText.psqlName ); diff --git a/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/s3HappyPath.cy.js b/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/s3HappyPath.cy.js index 3e8a243c53..7a128c1470 100644 --- a/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/s3HappyPath.cy.js +++ b/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/s3HappyPath.cy.js @@ -19,7 +19,8 @@ const data = {}; describe("Data sources AWS S3", () => { beforeEach(() => { - cy.appUILogin(); + cy.apiLogin(); + cy.defaultWorkspaceLogin(); data.dataSourceName = fake.lastName .toLowerCase() .replaceAll("[^A-Za-z]", ""); diff --git a/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/sapHanaHappyPath.cy.skip.js b/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/sapHanaHappyPath.cy.skip.js index 813b2663c9..c240286274 100644 --- a/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/sapHanaHappyPath.cy.skip.js +++ b/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/sapHanaHappyPath.cy.skip.js @@ -108,7 +108,7 @@ describe("Data sources", () => { selectAndAddDataSource(postgreSqlText.postgreSQL); cy.clearAndType( - '[data-cy="data-source-name-input-filed"]', + '[data-cy="data-source-name-input-field"]', postgreSqlText.psqlName ); diff --git a/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/twilio.cy.js b/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/twilio.cy.js new file mode 100644 index 0000000000..824c8d3bbc --- /dev/null +++ b/cypress-tests/cypress/e2e/happyPath/marketplace/commonTestcases/data-source/twilio.cy.js @@ -0,0 +1,189 @@ +import { fake } from "Fixtures/fake"; +import { postgreSqlSelector } from "Selectors/postgreSql"; +import { postgreSqlText } from "Texts/postgreSql"; +import { twilioText } from "Texts/twilio"; +import { twilioSelectors } from "Selectors/Plugins"; +import { commonSelectors } from "Selectors/common"; +import { commonText } from "Texts/common"; + +import { + fillDataSourceTextField, + selectAndAddDataSource, +} from "Support/utils/postgreSql"; + +import { + verifyCouldnotConnectWithAlert, + deleteDatasource, + closeDSModal, + addQuery, + addDsAndAddQuery, +} from "Support/utils/dataSource"; + +import { openQueryEditor } from "Support/utils/dataSource"; +import { dataSourceSelector } from "../../../../../constants/selectors/dataSource"; +import { pluginSelectors } from "Selectors/plugins"; + +const data = {}; +data.dsName = fake.lastName.toLowerCase().replaceAll("[^A-Za-z]", ""); + +describe("Data source Twilio", () => { + beforeEach(() => { + cy.apiLogin(); + cy.defaultWorkspaceLogin(); + }); + + it("Should verify elements on Twilio connection form", () => { + const AuthToken = Cypress.env("twilio_auth_token"); + const AccountSID = Cypress.env("twilio_account_SID"); + const MessageSID = Cypress.env("twilio_messaging_service_SID"); + + cy.get(commonSelectors.globalDataSourceIcon).click(); + closeDSModal(); + + cy.get(postgreSqlSelector.commonlyUsedLabelAndCount).should( + "have.text", + postgreSqlText.commonlyUsed + ); + + cy.get(postgreSqlSelector.apiLabelAndCount).should( + "have.text", + postgreSqlText.allApis + ); + cy.get(postgreSqlSelector.cloudStorageLabelAndCount).should( + "have.text", + postgreSqlText.allCloudStorage + ); + + selectAndAddDataSource("databases", twilioText.twilio, data.dsName); + + fillDataSourceTextField( + twilioText.authTokenLabel, + twilioText.authTokenPlaceholder, + AuthToken + ); + + fillDataSourceTextField( + twilioText.accountSidLabel, + twilioText.accountSidPlaceholder, + AccountSID + ); + + fillDataSourceTextField( + twilioText.messagingSIDLabel, + twilioText.messagingSIDPalceholder, + MessageSID + ); + + cy.get(postgreSqlSelector.buttonSave) + .verifyVisibleElement("have.text", postgreSqlText.buttonTextSave) + .click(); + cy.verifyToastMessage( + commonSelectors.toastMessage, + postgreSqlText.toastDSSaved + ); + + deleteDatasource(`cypress-${data.dsName}-twilio`); + }); + + it("Should verify functionality of Twilio connection form", () => { + const AuthToken = Cypress.env("twilio_auth_token"); + const AccountSID = Cypress.env("twilio_account_SID"); + const MessageSID = Cypress.env("twilio_messaging_service_SID"); + + cy.get(commonSelectors.globalDataSourceIcon).click(); + closeDSModal(); + + selectAndAddDataSource("databases", twilioText.twilio, data.dsName); + + fillDataSourceTextField( + twilioText.authTokenLabel, + twilioText.authTokenPlaceholder, + AuthToken + ); + + fillDataSourceTextField( + twilioText.accountSidLabel, + twilioText.accountSidPlaceholder, + AccountSID + ); + + fillDataSourceTextField( + twilioText.messagingSIDLabel, + twilioText.messagingSIDPalceholder, + MessageSID + ); + + cy.get(postgreSqlSelector.buttonSave) + .verifyVisibleElement("have.text", postgreSqlText.buttonTextSave) + .click(); + cy.verifyToastMessage( + commonSelectors.toastMessage, + postgreSqlText.toastDSSaved + ); + + deleteDatasource(`cypress-${data.dsName}-twilio`); + }); + + it("Should be able to run the query with a valid connection", () => { + const AuthToken = Cypress.env("twilio_auth_token"); + const AccountSID = Cypress.env("twilio_account_SID"); + const MessageSID = Cypress.env("twilio_messaging_service_SID"); + const MessageNumber = Cypress.env("twilio_message_number"); + + cy.get(commonSelectors.globalDataSourceIcon).click(); + closeDSModal(); + + selectAndAddDataSource("databases", twilioText.twilio, data.dsName); + + fillDataSourceTextField( + twilioText.authTokenLabel, + twilioText.authTokenPlaceholder, + AuthToken + ); + + fillDataSourceTextField( + twilioText.accountSidLabel, + twilioText.accountSidPlaceholder, + AccountSID + ); + + fillDataSourceTextField( + twilioText.messagingSIDLabel, + twilioText.messagingSIDPalceholder, + MessageSID + ); + + cy.get(postgreSqlSelector.buttonSave) + .verifyVisibleElement("have.text", postgreSqlText.buttonTextSave) + .click(); + cy.verifyToastMessage( + commonSelectors.toastMessage, + postgreSqlText.toastDSSaved + ); + + cy.get(commonSelectors.dashboardIcon).click(); + cy.get(commonSelectors.appCreateButton).click(); + cy.get(commonSelectors.appNameInput).click().type(data.dsName); + cy.get(commonSelectors.createAppButton).click(); + cy.skipWalkthrough(); + + cy.get('[data-cy="show-ds-popover-button"]').click(); + cy.get(".css-4e90k9").type(`${data.dsName}`); + cy.contains(`[id*="react-select-"]`, data.dsName).click(); + cy.get('[data-cy="query-rename-input"]').clear().type(data.dsName); + + cy.get(pluginSelectors.operationDropdown).click().type("Send SMS{enter}"); + + cy.get(twilioSelectors.toNumberInputField).clearAndTypeOnCodeMirror( + MessageNumber + ); + cy.get(twilioSelectors.bodyInput).clearAndTypeOnCodeMirror( + twilioText.messageText + ); + cy.get(dataSourceSelector.queryPreviewButton).click(); + cy.verifyToastMessage( + commonSelectors.toastMessage, + `Query (${data.dsName}) completed.` + ); + }); +}); diff --git a/cypress-tests/cypress/support/utils/mongoDB.js b/cypress-tests/cypress/support/utils/mongoDB.js index 0ca418db9d..61107f639e 100644 --- a/cypress-tests/cypress/support/utils/mongoDB.js +++ b/cypress-tests/cypress/support/utils/mongoDB.js @@ -10,7 +10,7 @@ export const connectMongo = () => { selectAndAddDataSource(mongoDbText.mongoDb); cy.clearAndType( - '[data-cy="data-source-name-input-filed"]', + '[data-cy="data-source-name-input-field"]', mongoDbText.cypressMongoDb ); diff --git a/cypress-tests/cypress/support/utils/multipage.js b/cypress-tests/cypress/support/utils/multipage.js index 8821054af0..299986f47c 100644 --- a/cypress-tests/cypress/support/utils/multipage.js +++ b/cypress-tests/cypress/support/utils/multipage.js @@ -3,7 +3,7 @@ import { commonSelectors } from "../../constants/selectors/common"; export const searchPage = (pageName) => { cy.get('[title="Search"]').click(); - cy.get('[data-cy="search-input-filed"]').type(pageName); + cy.get('[data-cy="search-input-field"]').type(pageName); }; export const clearSearch = () => { diff --git a/cypress-tests/cypress/support/utils/postgreSql.js b/cypress-tests/cypress/support/utils/postgreSql.js index fc3f257627..72c4ce9cbc 100644 --- a/cypress-tests/cypress/support/utils/postgreSql.js +++ b/cypress-tests/cypress/support/utils/postgreSql.js @@ -48,27 +48,25 @@ export const selectAndAddDataSource = ( dataSourceName ) => { cy.get(commonSelectors.globalDataSourceIcon).click(); - cy.wait(1000) + cy.wait(1000); cy.get(`[data-cy="${cyParamName(dscategory)}-datasource-button"]`).click(); - cy.wait(500) + cy.wait(500); cy.get(postgreSqlSelector.dataSourceSearchInputField).type(dataSource); - cy.get(`[data-cy="data-source-${(dataSource).toLowerCase()}"]`) + cy.get(`[data-cy="data-source-${dataSource.toLowerCase()}"]`) .parent() .within(() => { cy.get( - `[data-cy="data-source-${( - dataSource - ).toLowerCase()}"]>>>.datasource-card-title` + `[data-cy="data-source-${dataSource.toLowerCase()}"]>>>.datasource-card-title` ).realHover("mouse"); cy.get( `[data-cy="${cyParamName(dataSource).toLowerCase()}-add-button"]` ).click(); }); - cy.wait(1000) - cy.get(postgreSqlSelector.buttonSave).should("be.disabled") + cy.wait(1000); + cy.get(postgreSqlSelector.buttonSave).should("be.disabled"); cy.clearAndType( - '[data-cy="data-source-name-input-filed"]', + '[data-cy="data-source-name-input-field"]', cyParamName(`cypress-${dataSourceName}-${dataSource}`) ); cy.get(postgreSqlSelector.buttonSave).click(); @@ -184,4 +182,4 @@ export const addWidgetsToAddUser = () => { addEventHandlerToRunQuery("add_data_using_widgets"); }; -export const addListviewToVerifyData = () => { }; \ No newline at end of file +export const addListviewToVerifyData = () => {}; diff --git a/docker/ee/ee-production.Dockerfile b/docker/ee/ee-production.Dockerfile index 230a2f8ebb..b69458daa1 100644 --- a/docker/ee/ee-production.Dockerfile +++ b/docker/ee/ee-production.Dockerfile @@ -62,8 +62,40 @@ FROM debian:11 RUN apt-get update -yq \ && apt-get install curl gnupg zip -yq \ && apt-get install -yq build-essential \ + && apt -y install redis \ && apt-get clean -y +# Install required dependencies for downloading and extracting files +RUN apt-get update && apt-get install -y \ + curl tar xz-utils postgresql postgresql-contrib postgresql-client && \ + apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install PostgREST from official Docker image +COPY --from=postgrest/postgrest:v12.2.0 /bin/postgrest /bin + +RUN apt-get update && apt-get install -y supervisor + +# Create supervisord configuration file +RUN echo "[supervisord]\n" \ + "nodaemon=true\n" \ + "\n" \ + "[program:postgrest]\n" \ + "command=/bin/postgrest \n" \ + "autostart=true\n" \ + "autorestart=true\n" \ + "stdout_logfile=/dev/stdout\n" \ + "stderr_logfile=/dev/stderr\n" \ + "stdout_logfile_maxbytes=0\n" \ + "stderr_logfile_maxbytes=0\n" \ + "\n" | sed 's/ //' > /etc/supervisor/conf.d/supervisord.conf + +# Create a wrapper for PostgREST to prefix its logs +RUN mv /bin/postgrest /bin/postgrest-original && \ + echo '#!/bin/bash\n\ +exec /bin/postgrest-original "$@" 2>&1 | sed "s/^/[PostgREST] /"\n\ +' > /bin/postgrest && \ + chmod +x /bin/postgrest + RUN curl -O https://nodejs.org/dist/v18.18.2/node-v18.18.2-linux-x64.tar.xz \ && tar -xf node-v18.18.2-linux-x64.tar.xz \ @@ -152,6 +184,25 @@ RUN mkdir -p /tmp/.npm/npm-cache/_logs \ && chmod g+s /tmp/.npm/npm-cache/_logs \ && chmod -R g=u /tmp/.npm/npm-cache/_logs +# Create Redis data, log, and configuration directories +RUN mkdir -p /var/lib/redis /var/log/redis /etc/redis \ + && chown -R appuser:0 /var/lib/redis /var/log/redis /etc/redis \ + && chmod g+s /var/lib/redis /var/log/redis /etc/redis \ + && chmod -R g=u /var/lib/redis /var/log/redis /etc/redis + +# Set permissions for PostgREST binary +RUN chown appuser:0 /bin/postgrest && chmod u+x /bin/postgrest && chmod g=u /bin/postgrest + +RUN touch /tmp/postgrest.conf \ + && chown appuser:0 /tmp/postgrest.conf \ + && chmod 640 /tmp/postgrest.conf + +# Create PostgREST data, log, and configuration directories +RUN mkdir -p /var/lib/postgrest /var/log/postgrest /etc/postgrest \ + && chown -R appuser:0 /var/lib/postgrest /var/log/postgrest /etc/postgrest \ + && chmod g+s /var/lib/postgrest /var/log/postgrest /etc/postgrest \ + && chmod -R g=u /var/lib/postgrest /var/log/postgrest /etc/postgrest + ENV HOME=/home/appuser # Switch back to appuser diff --git a/frontend/ee b/frontend/ee index d93ee7e131..715a830c7a 160000 --- a/frontend/ee +++ b/frontend/ee @@ -1 +1 @@ -Subproject commit d93ee7e1318f044ef2327671b8b257648071453d +Subproject commit 715a830c7a8d75efc7f77106292d9e4499005b69 diff --git a/frontend/src/AppBuilder/CodeEditor/SingleLineCodeEditor.jsx b/frontend/src/AppBuilder/CodeEditor/SingleLineCodeEditor.jsx index 1243f26f43..5506a94fed 100644 --- a/frontend/src/AppBuilder/CodeEditor/SingleLineCodeEditor.jsx +++ b/frontend/src/AppBuilder/CodeEditor/SingleLineCodeEditor.jsx @@ -336,7 +336,7 @@ const EditorInput = ({
{/* sticky element to position the preview box correctly on top without flowing out of container */}
{!isSpecificComponent && ( @@ -628,6 +629,7 @@ const DynamicForm = ({ {...getElementProps(obj[key])} {...computedProps[propertyKey]} data-cy={`${String(label).toLocaleLowerCase().replace(/\s+/g, '-')}-text-field`} + dataCy={obj[key].key.replace(/_/g, '-')} //to be removed after whole ui is same isHorizontalLayout={isHorizontalLayout} /> @@ -669,7 +671,7 @@ const DynamicForm = ({ )} -
+
keyValuePairValueChanged(e.target.value, 0, index)} @@ -47,6 +50,7 @@ export default ({ />