diff --git a/e2e-test/pom.xml b/e2e-test/pom.xml new file mode 100644 index 000000000..ead3869b6 --- /dev/null +++ b/e2e-test/pom.xml @@ -0,0 +1,123 @@ + + + + 4.0.0 + + io.cdap.plugin + e2e-test + 2.9.0-SNAPSHOT + + 8 + 8 + + + + e2e-tests + + e2e-test/src/test + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.18.1 + + true + + + + + org.apache.maven.plugins + maven-failsafe-plugin + 3.0.0-M5 + + + TestRunner.java + + + + + + integration-test + + + + + + + net.masterthought + maven-cucumber-reporting + 5.5.0 + + + + execution + verify + + generate + + + Cucumber Reports + target/cucumber-reports/advanced-reports + 1 + false + ${project.build.directory}/cucumber-reports + + **/*.json + + ${project.build.directory}/cucumber-reports + true + + + + + + + + + io.cdap.tests.e2e + cdap-e2e-framework + 0.0.1-SNAPSHOT + test + + + mysql + mysql-connector-java + 8.0.26 + + + org.springframework + spring-jdbc + 5.3.13 + + + com.google.cloud.sql + mysql-socket-factory-connector-j-8 + 1.0.16 + + + com.zaxxer + HikariCP + 4.0.3 + + + + + diff --git a/e2e-test/src/test/features/Cloudsqlmysql_sink_designtime.feature b/e2e-test/src/test/features/Cloudsqlmysql_sink_designtime.feature new file mode 100755 index 000000000..16735b64d --- /dev/null +++ b/e2e-test/src/test/features/Cloudsqlmysql_sink_designtime.feature @@ -0,0 +1,64 @@ +Feature: CloudSQLMySQl Sink Design Time + + @CLDMYSQL @TC-Mandatory-fields + Scenario Outline:Verify CloudSQLMYSQL Sink properties validation errors for mandatory fields + Given Open DataFusion Project to configure pipeline + When Target is CloudSQLMySQL + Then Open CloudSQLMySQL Properties + Then Enter the CloudSQLMySQL Sink Properties with blank property "" + Then Validate mandatory property error for "" + Examples: + | property | + | referenceName | + | database | + | connectionName | + | tableName | + | jdbcPluginName | + + @CLDMYSQL @TC-Invalid-TestData-for-DriverName_Field: + Scenario: TC-CLDMYSQL-DSGN-02:Verify Driver Name field validation error with invalid test data + Given Open DataFusion Project to configure pipeline + When Target is CloudSQLMySQL + Then Open CloudSQLMySQL Properties + Then Enter Reference Name "clsReferenceNameValid" & Database Name "clsDatabaseName" with Test Data + Then Enter Table Name "clsTableNameBQCS" and Connection Name "clsConnectionNameValid" + Then Validate Connector properties + Then Enter Driver Name with Invalid value for Driver name field "clsDriverNameInvalid" + Then Verify invalid Driver name error message is displayed for Driver "clsDriverNameInvalid" + Then Verify plugin validation fails with error + Then Close the CloudSQLMySQL Properties + + @CLDMYSQL @TC-Invalid-TestData-for-ReferenceName&ConnectionName + Scenario: TC-CLDMYSQL-DSGN-03:Verify properties validation errors for invalid test data for Reference name & connection name + Given Open DataFusion Project to configure pipeline + When Target is CloudSQLMySQL + Then Enter Reference Name & Connection Name with Invalid Test Data in Sink + Then Verify Reference Name "clsReferenceNameInvalid" Field with Invalid Test Data + Then Verify Connection Name "clsConnectionNameInvalid" fields with Invalid Test Data + Then Enter Connection Name with private instance type + Then Verify Connection Name with private instance type "clsConnectionNameInvalid" + Then Close the CloudSQLMySQL Properties + + @CLDMYSQL @TC-Add-Comments + Scenario: TC-CLDMYSQL-DSGN-04:Verify the Add Comments functionality for CloudSQL MySQL connector + Given Open DataFusion Project to configure pipeline + When Target is CloudSQLMySQL + Then Add and Save Comments sink "clsPluginComment" + Then Validate Sink Comment + + @CLDMYSQL @TC-Edit-Comments + Scenario: TC-CLDMYSQL-DSGN-05:Verify the Edit added Comments functionality for CloudSQL MySQL connector + Given Open DataFusion Project to configure pipeline + When Target is CloudSQLMySQL + Then Add and Save Comments sink "clsPluginComment" + Then Edit Sink Comments "clsPluginUpdateComment" + Then Validate Sink Update Comment + + @CLDMYSQL @TC-Delete-Comments + Scenario: TC-CLDMYSQL-DSGN-06:Verify the Delete added Comments functionality for CloudSQL MySQL connector + Given Open DataFusion Project to configure pipeline + When Target is CloudSQLMySQL + Then Add and Save Comments sink "clsPluginComment" + Then Edit Sink Comments "clsPluginUpdateComment" + Then Delete Comments + Then Validate Comment has been deleted successfully diff --git a/e2e-test/src/test/features/Cloudsqlmysql_sink_runtime.feature b/e2e-test/src/test/features/Cloudsqlmysql_sink_runtime.feature new file mode 100755 index 000000000..7cca3419b --- /dev/null +++ b/e2e-test/src/test/features/Cloudsqlmysql_sink_runtime.feature @@ -0,0 +1,120 @@ +Feature: BigQuery to CloudSqlMySql and GCS to CloudSqlMySql Runtime + + @CLDMYSQL @TC-Runtime-BigQuery-to-CLOUDSqlMYSQL: + Scenario: TC-CLDMYSQL-RNTM-01:Verify user is able to transferred data from BigQuery to CloudSqlMysql with mandatory fields + Given Open DataFusion Project to configure pipeline + When Source is BigQuery + When Target is CloudSQLMySQL + Then Link BigQuery to CloudSQLMySQL to establish connection + Then Enter the Source BigQuery Properties for table "clsTableNameBQ" + Then Validate the Schema + Then Verify the Connector status + Then Close the BigQuery Properties + Then Enter the sink CloudSQLMySQL Properties for table "clsTableNameBQCS" + Then Click on Validate button + Then Verify the Connector status + Then Close the CloudSQLMySQL Properties + Then Save the pipeline + Then Preview and run the pipeline + Then Verify the preview of pipeline is "success" + Then Click on PreviewData for CloudSQL MySQL + Then Verify Preview output schema matches the outputSchema captured in properties + Then Close the Preview + Then Pre records count from CloudSQLMySQL table "clsTableNameBQCS" + Then Deploy the pipeline + Then Run the Pipeline in Runtime + Then Wait till pipeline is in running state + Then Open and capture Logs + Then Verify the pipeline status is "Succeeded" + Then Post records count from CloudSQLMySQL table "clsTableNameBQCS" + Then Validate the output record count + Then Validate successMessage is displayed + Then Validate the count of records transferred from BigQuery "clsTableNameBQ" to CloudSqlMySql "clsTableNameBQCS" + + @CLDMYSQL @TC-Runtime-BigQuery-to-CLOUDSqlMYSQL: + Scenario: TC-CLDMYSQL-RNTM-02:Verify user is able to transferred data from BigQuery to CloudSqlMysql with filter + Given Open DataFusion Project to configure pipeline + When Source is BigQuery + When Target is CloudSQLMySQL + Then Link BigQuery to CloudSQLMySQL to establish connection + Then Enter the Source BigQuery Properties for table "clsTableNameBQ1" + Then Enter the Source BigQuery with filter "clsFilterBigQuery" option + Then Validate the Schema + Then Verify the Connector status + Then Close the BigQuery Properties + Then Enter the sink CloudSQLMySQL Properties for table "clsTableNameBQCS1" + Then Click on Validate button + Then Verify the Connector status + Then Close the CloudSQLMySQL Properties + Then Save the pipeline + Then Preview and run the pipeline + Then Verify the preview of pipeline is "success" + Then Click on PreviewData for CloudSQL MySQL + Then Verify Preview output schema matches the outputSchema captured in properties + Then Close the Preview + Then Pre records count from CloudSQLMySQL table "clsTableNameBQCS1" + Then Deploy the pipeline + Then Run the Pipeline in Runtime + Then Wait till pipeline is in running state + Then Open and capture Logs + Then Verify the pipeline status is "Succeeded" + Then Post records count from CloudSQLMySQL table "clsTableNameBQCS1" + Then Validate the output record count + Then Validate successMessage is displayed + Then Validate the count of records transferred from BigQuery "clsTableNameBQ1" to CloudSqlMySql with filter "clsFilterBigQuery" + + @CLDMYSQL @TC-Runtime-GCS-to-CLOUDSQLMYSQL: + Scenario: TC-CLDMYSQL-RNTM-03:Verify user is able to transferred data from GCS to CloudSQLMySQL with mandatory fields + Given Open DataFusion Project to configure pipeline + When Source is GCS bucket + When Target is CloudSQLMySQL + Then Link GCS to CloudSQLMySQL to establish connection + Then Enter the GCS Properties with "clsBucket" GCS bucket and format "clsFormatType" + Then Validate the Schema + Then Verify the Connector status + Then Close the GCS Properties + Then Enter the sink CloudSQLMySQL Properties for table "clsTableNameGCSCS" + Then Click on Validate button + Then Verify the Connector status + Then Close the CloudSQLMySQL Properties + Then Save the pipeline + Then Preview and run the pipeline + Then Verify the preview of pipeline is "success" + Then Click on PreviewData for CloudSQL MySQL + Then Verify Preview output schema matches the outputSchema captured in properties + Then Close the Preview + Then Deploy the pipeline + Then Run the Pipeline in Runtime + Then Wait till pipeline is in running state + Then Open and capture Logs + Then Verify the pipeline status is "Succeeded" + Then Validate the output record count + Then Validate successMessage is displayed + + @CLDMYSQL @TC-Runtime-GCS-to-CLOUDSQLMYSQL: + Scenario: TC-CLDMYSQL-RNTM-04:Verify user is able to Duplicate the pipeline + Given Open DataFusion Project to configure pipeline + When Source is GCS bucket + When Target is CloudSQLMySQL + Then Link GCS to CloudSQLMySQL to establish connection + Then Enter the GCS Properties with "clsBucket" GCS bucket and format "clsFormatType" + Then Validate the Schema + Then Verify the Connector status + Then Close the GCS Properties + Then Enter the sink CloudSQLMySQL Properties for table "clsTableNameGCSCS" + Then Click on Validate button + Then Verify the Connector status + Then Close the CloudSQLMySQL Properties + Then Save the pipeline + Then Preview and run the pipeline + Then Verify the preview of pipeline is "success" + Then Click on PreviewData for CloudSQL MySQL + Then Verify Preview output schema matches the outputSchema captured in properties + Then Close the Preview + Then Deploy the pipeline + Then Run the Pipeline in Runtime + Then Wait till pipeline is in running state + Then Verify the pipeline status is "Succeeded" + Then Validate the output record count + Then Create Duplicate pipeline + Then Validate studio is opened with duplicate pipeline diff --git a/e2e-test/src/test/features/Cloudsqlmysql_source_designtime.feature b/e2e-test/src/test/features/Cloudsqlmysql_source_designtime.feature new file mode 100755 index 000000000..b60c64fa2 --- /dev/null +++ b/e2e-test/src/test/features/Cloudsqlmysql_source_designtime.feature @@ -0,0 +1,95 @@ +Feature: CloudSqlMySql Source Design Time + + @CLDMYSQL @TC-Mandatory-fields + Scenario Outline:Verify CloudSQLMYSQL Source properties validation errors for mandatory fields + Given Open DataFusion Project to configure pipeline + When Source is CloudSQLMySQL + Then Open CloudSQLMySQL Properties + Then Enter the CloudSQLMySQL Source Properties with blank property "" + Then Validate mandatory property error for "" + Examples: + | property | + | referenceName | + | database | + | connectionName | + | importQuery | + | jdbcPluginName | + + @CLDMYSQL @TC-Invalid-TestData-for-DriverName_Field: + Scenario: TC-CLDMYSQL-DSGN-02:Verify Driver Name field validation error with invalid test data + Given Open DataFusion Project to configure pipeline + When Source is CloudSQLMySQL + Then Open CloudSQLMySQL Properties + Then Enter Reference Name "clsReferenceNameValid" & Database Name "clsDatabaseName" with Test Data + Then Enter Connection Name "clsConnectionNameValid" and Import Query "clsImportQuery" + Then Enter Driver Name with Invalid value for Driver name field "clsDriverNameInvalid" + Then Verify invalid Driver name error message is displayed for Driver "clsDriverNameInvalid" + Then Verify plugin validation fails with error + Then Close the CloudSQLMySQL Properties + + @CLDMYSQL @TC-Invalid-TestData-for-ImportQuery_Field: + Scenario: TC-CLDMYSQL-DSGN-03:Verify ImportQuery Field validation error with invalid test data + Given Open DataFusion Project to configure pipeline + When Source is CloudSQLMySQL + Then Open CloudSQLMySQL Properties + Then Enter Reference Name "clsReferenceNameValid" & Database Name "clsDatabaseName" with Test Data + Then Enter Connection Name "clsConnectionNameValid" and Import Query "clsInvalidImportQuery" + Then Validate Connector properties + Then Verify invalid import query error message is displayed for import query "clsInvalidImportQuery" + Then Verify plugin validation fails with error + Then Close the CloudSQLMySQL Properties + + @CLDMYSQL @TC-Invalid-TestData-for-ReferenceName&ConnectionName + Scenario: TC-CLDMYSQL-DSGN-04:Verify Reference Name & Connection Name field validation errors with invalid test data + Given Open DataFusion Project to configure pipeline + When Source is CloudSQLMySQL + Then Enter Reference Name & Connection Name with Invalid Test Data and import query "clsImportQuery" + Then Verify Reference Name "clsReferenceNameInvalid" Field with Invalid Test Data + Then Verify Connection Name "clsConnectionNameInvalid" fields with Invalid Test Data + Then Enter Connection Name with private instance type + Then Verify Connection Name with private instance type "clsConnectionNameInvalid" + Then Close the CloudSQLMySQL Properties + + @CLDMYSQL @TC-Blank-value-error-Validation-for-SplitColumn-Invalid-value-for-Number-of-splits: + Scenario: TC-CLDMYSQL-DSGN-05:Verify the Split-By field validation error and invalid Number of Splits + Given Open DataFusion Project to configure pipeline + When Source is CloudSQLMySQL + Then Enter the source CloudSQLMySQL properties with import query "clsImportQuery1" bounding query "clsBoundingQuery" + Then Provide blank values in Split column and invalid Number of splits + Then Click on Validate button + Then Verify Split-by column field error + Then Verify Number of splits field error + Then Close the CloudSQLMySQL Properties + + @CLDMYSQL @TC-Blank-value-error-Validation-for-Bounding-Query: + Scenario: TC-CLDMYSQL-DSGN-06:Verify the Bounding Query validation error when values are not given + Given Open DataFusion Project to configure pipeline + When Source is CloudSQLMySQL + Then Enter the source CloudSQL-MySQL properties with import query "clsImportQuery1" and blank bounding query + Then Provide blank values in Split column and invalid Number of splits + Then Verify Bounding Query field error + Then Close the CloudSQLMySQL Properties + + @CLDMYSQL @TC-Add-Comments + Scenario: TC-CLDMYSQL-DSGN-07:Verify the Add Comments functionality for CloudSQL MySQL connector + Given Open DataFusion Project to configure pipeline + When Source is CloudSQLMySQL + Then Add and Save Comments "clsPluginComment" + Then Validate Source Comment + + @CLDMYSQL @TC-Edit-Comments + Scenario: TC-CLDMYSQL-DSGN-08:Verify the Edit added Comments functionality for CloudSQL MySQL connector + Given Open DataFusion Project to configure pipeline + When Source is CloudSQLMySQL + Then Add and Save Comments "clsPluginComment" + Then Edit Source Comments "clsPluginUpdateComment" + Then Validate Source Update Comment + + @CLDMYSQL @TC-Delete-Comments + Scenario: TC-CLDMYSQL-DSGN-09:Verify the Delete added Comments functionality for CloudSQL MySQL connector + Given Open DataFusion Project to configure pipeline + When Source is CloudSQLMySQL + Then Add and Save Comments "clsPluginComment" + Then Edit Source Comments "clsPluginUpdateComment" + Then Delete Comments + Then Validate Comment has been deleted successfully diff --git a/e2e-test/src/test/features/Cloudsqlmysql_source_runtime.feature b/e2e-test/src/test/features/Cloudsqlmysql_source_runtime.feature new file mode 100755 index 000000000..a0c86742d --- /dev/null +++ b/e2e-test/src/test/features/Cloudsqlmysql_source_runtime.feature @@ -0,0 +1,154 @@ +Feature: CloudSqlMySql to BigQuery and CloudSqlMySql to GCS Run-Time + + @CLDMYSQL @TC-Runtime-CLOUDSQLMYSQL-to-BigQuery: + Scenario Outline:Verify data transferred from CloudSql-Mysql to BigQuery with mandatory fields + Given Open DataFusion Project to configure pipeline + When Source is CloudSQLMySQL + When Target is BigQuery + Then Link CloudSQLMySQL to BigQuery to establish connection + Then Enter the source CloudSQLMySQL Properties with import query "" + Then Click on Validate button + Then Validate the Schema + Then Verify the Connector status + Then Close the CloudSQLMySQL Properties + Then Enter the BigQuery Properties for table "clsMySQLBQTableName" + Then Verify the Connector status + Then Close the BigQuery Properties + Then Save the pipeline + Then Preview and run the pipeline + Then Verify the preview of pipeline is "success" + Then Click on PreviewData for BigQuery + Then Verify Preview output schema matches the outputSchema captured in properties + Then Close the Preview + Then Deploy the pipeline + Then Run the Pipeline in Runtime + Then Wait till pipeline is in running state + Then Open and capture Logs + Then Verify the pipeline status is "Succeeded" + Then Validate the output record count + Then Validate successMessage is displayed + Then Validate count of records transferred from importQuery "" to BigQuery in "clsMySQLBQTableName" + Then Delete the table "clsMySQLBQTableName" + Examples: + | importQuery | + | clsImportQuery | + | clsImportQuery2 | + + @CLDMYSQL @TC-Runtime-CLOUDSQLMYSQL-to-BigQuery: + Scenario:Verify user is able to transferred data from CloudSql-Mysql to BigQuery with Advanced + Given Open DataFusion Project to configure pipeline + When Source is CloudSQLMySQL + When Target is BigQuery + Then Link CloudSQLMySQL to BigQuery to establish connection + Then Enter the source CloudSQLMySQL properties with import query "clsImportQuery1" bounding query "clsBoundingQuery" + Then Enter the source CloudSQL-MySQL with Split and Number of splits CloudSQLMySQL properties + Then Click on Validate button + Then Validate the Schema + Then Verify the Connector status + Then Close the CloudSQLMySQL Properties + Then Enter the BigQuery Properties for table "clsMySQLBQTableName" + Then Verify the Connector status + Then Close the BigQuery Properties + Then Save the pipeline + Then Preview and run the pipeline + Then Verify the preview of pipeline is "success" + Then Click on PreviewData for BigQuery + Then Verify Preview output schema matches the outputSchema captured in properties + Then Close the Preview + Then Deploy the pipeline + Then Run the Pipeline in Runtime + Then Wait till pipeline is in running state + Then Open and capture Logs + Then Verify the pipeline status is "Succeeded" + Then Validate the output record count + Then Validate successMessage is displayed + Then Get Count of no of records transferred to BigQuery in "clsMySQLBQTableName" + Then Delete the table "clsMySQLBQTableName" + + @CLDMYSQL @TC-Runtime-CLOUDSQLMYSQL-to-GCS: + Scenario Outline:Verify user is able to transferred data from CloudSql-Mysql to GCS with mandatory fields + Given Open DataFusion Project to configure pipeline + Given Cloud Storage bucket should not exist in "projectId" with the name "clsFileBucketCreate" + When Source is CloudSQLMySQL + When Target is GCS + Then Link CloudSQLMySQL to GCS to establish connection + Then Enter the source CloudSQLMySQL Properties with import query "clsImportQuery" + Then Click on Validate button + Then Validate the Schema + Then Verify the Connector status + Then Close the CloudSQLMySQL Properties + Then Enter the GCS Properties and "" file format + Then Verify the Connector status + Then Close the GCS Properties + Then Save the pipeline + Then Preview and run the pipeline + Then Verify the preview of pipeline is "success" + Then Click on PreviewData for GCS + Then Verify Preview output schema matches the outputSchema captured in properties + Then Close the Preview + Then Deploy the pipeline + Then Run the Pipeline in Runtime + Then Wait till pipeline is in running state + Then Verify the pipeline status is "Succeeded" + Then Validate the output record count + Then Verify the folder created in "projectId" with bucket name "clsFileBucketCreate" + Then Open and capture Logs + Then Validate successMessage is displayed + Examples: + | format | + | avro | + | csv | + | parquet | + | tsv | + | delimited | + | json | + | orc | + + @CLDMYSQL @TC-Runtime-CLOUDSQLMYSQL-to-GCS: + Scenario:Verify user is able to Duplicate the pipeline + Given Open DataFusion Project to configure pipeline + Given Cloud Storage bucket should not exist in "projectId" with the name "clsFileBucketCreate" + When Source is CloudSQLMySQL + When Target is GCS + Then Link CloudSQLMySQL to GCS to establish connection + Then Enter the source CloudSQLMySQL Properties with import query "clsImportQuery" + Then Click on Validate button + Then Validate the Schema + Then Verify the Connector status + Then Close the CloudSQLMySQL Properties + Then Enter the GCS Properties and "csv" file format + Then Verify the Connector status + Then Close the GCS Properties + Then Save the pipeline + Then Preview and run the pipeline + Then Verify the preview of pipeline is "success" + Then Click on PreviewData for GCS + Then Verify Preview output schema matches the outputSchema captured in properties + Then Close the Preview + Then Deploy the pipeline + Then Run the Pipeline in Runtime + Then Wait till pipeline is in running state + Then Verify the pipeline status is "Succeeded" + Then Validate the output record count + Then Verify the folder created in "projectId" with bucket name "clsFileBucketCreate" + Then Create Duplicate pipeline + Then Validate studio is opened with duplicate pipeline + + @CLDMYSQL @TC-Runtime-CLOUDSQLMYSQL-to-BigQuery: + Scenario:Verify preview gets failed when incorrect values in Split column CloudSql-Mysql + Given Open DataFusion Project to configure pipeline + When Source is CloudSQLMySQL + When Target is BigQuery + Then Link CloudSQLMySQL to BigQuery to establish connection + Then Enter the source CloudSQLMySQL properties with import query "clsImportQuery1" bounding query "clsBoundingQuery" + Then Enter the incorrect values in split column with number of splits + Then Click on Validate button + Then Verify the Connector status + Then Capture output schema + Then Close the CloudSQLMySQL Properties + Then Enter the BigQuery Properties for table "clsMySQLBQTableName" + Then Verify the Connector status + Then Close the BigQuery Properties + Then Save the pipeline + Then Preview and run the pipeline + Then Verify the preview of pipeline is "failed" diff --git a/e2e-test/src/test/java/io/cdap/plugin/cloudsqlmysql/actions/CdfCloudSqlMySqlActions.java b/e2e-test/src/test/java/io/cdap/plugin/cloudsqlmysql/actions/CdfCloudSqlMySqlActions.java new file mode 100755 index 000000000..82ec428fa --- /dev/null +++ b/e2e-test/src/test/java/io/cdap/plugin/cloudsqlmysql/actions/CdfCloudSqlMySqlActions.java @@ -0,0 +1,181 @@ +/* + * Copyright © 2021 Cask Data, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package io.cdap.plugin.cloudsqlmysql.actions; + +import io.cdap.e2e.pages.actions.CdfStudioActions; +import io.cdap.e2e.pages.locators.CdfBigQueryPropertiesLocators; +import io.cdap.e2e.pages.locators.CdfStudioLocators; +import io.cdap.e2e.utils.SeleniumHelper; +import io.cdap.plugin.cloudsqlmysql.locators.CdfCloudSqlMySqlLocators; +import io.cdap.plugin.utils.E2ETestUtils; +import org.junit.Assert; +import org.openqa.selenium.WebElement; + +import java.io.IOException; + +/** + * cloudSqlMySql connector related Step Actions. + */ + +public class CdfCloudSqlMySqlActions { + + static { + SeleniumHelper.getPropertiesLocators(CdfCloudSqlMySqlLocators.class); + SeleniumHelper.getPropertiesLocators(CdfBigQueryPropertiesLocators.class); + SeleniumHelper.getPropertiesLocators(CdfStudioLocators.class); + } + + public static void clickActionButton() { + SeleniumHelper.waitAndClick(CdfCloudSqlMySqlLocators.clickAction); + } + + public static void enterReferenceName(String reference) { + CdfCloudSqlMySqlLocators.referenceName.sendKeys(reference); + } + + public static void enterDriverName(String driver) { + CdfCloudSqlMySqlLocators.driverName.sendKeys(driver); + } + + public static void enterDefaultDriver(String driverNameValid) { + SeleniumHelper.replaceElementValue(CdfCloudSqlMySqlLocators.driverName, driverNameValid); + } + + public static void enterDatabaseName(String database) { + CdfCloudSqlMySqlLocators.database.sendKeys(database); + } + + public static void enterUserName(String username) { + CdfCloudSqlMySqlLocators.username.sendKeys(username); + } + + public static void enterPassword(String password) { + CdfCloudSqlMySqlLocators.password.sendKeys(password); + } + + public static void enterConnectionName(String connection) { + CdfCloudSqlMySqlLocators.connectionName.sendKeys(connection); + } + + public static void enterSplitColumn(String splitColumn) { + CdfCloudSqlMySqlLocators.splitColumn.sendKeys(splitColumn); + } + + public static void enterNumberOfSplits(String numberOfSplits) { + SeleniumHelper.replaceElementValue(CdfCloudSqlMySqlLocators.numberOfSplits, numberOfSplits); + } + + public static void enterImportQuery(String query) throws IOException, InterruptedException { + CdfCloudSqlMySqlLocators.importQuery.sendKeys(query); + } + + public static void enterBoundingQuery(String boundingQuery) throws IOException, InterruptedException { + CdfCloudSqlMySqlLocators.boundingQuery.sendKeys(boundingQuery); + } + + public static void enterTableName(String table) { + CdfCloudSqlMySqlLocators.sqlTableName.sendKeys(table); + } + + public static void enterConnectionTimeout(String connectionTimeout) { + SeleniumHelper.replaceElementValue(CdfCloudSqlMySqlLocators.connectionTimeout, connectionTimeout); + } + public static void clickDuplicateButton() { + CdfCloudSqlMySqlLocators.actionDuplicateButton.click(); + } + + public static void closeButton() { + CdfCloudSqlMySqlLocators.closeButton.click(); + } + + public static void clickCloudSqlMySqlProperties() { + CdfCloudSqlMySqlLocators.cloudSqlMySqlProperties.click(); + } + + public static void clickValidateButton() { + CdfCloudSqlMySqlLocators.validateButton.click(); + } + + public static void getSchema() { + CdfCloudSqlMySqlLocators.getSchemaButton.click(); + } + + public static void addComment(String comment) throws IOException { + CdfCloudSqlMySqlLocators.addComment.sendKeys(comment); + } + + public static void addCommentSink(String sinkComment) throws IOException { + CdfCloudSqlMySqlLocators.addCommentSink.sendKeys(sinkComment); + } + + public static void updateSourceComment(String updateComment) throws IOException { + CdfCloudSqlMySqlLocators.addComment.sendKeys(updateComment); + } + + public static void updateSinkComment(String updateComment) throws IOException { + CdfCloudSqlMySqlLocators.addCommentSink.sendKeys(updateComment); + } + + public static void clickComment() { + CdfCloudSqlMySqlLocators.clickComment.click(); + } + + public static void clickPrivateInstance() { + CdfCloudSqlMySqlLocators.instanceType.click(); + } + + public static void saveComment() throws IOException { + CdfCloudSqlMySqlLocators.saveComment.click(); + } + + public static void editComment() { + SeleniumHelper.waitElementIsVisible(CdfCloudSqlMySqlLocators.editComment, 1); + CdfCloudSqlMySqlLocators.editComment.click(); + } + + public static void clickEdit() { + CdfCloudSqlMySqlLocators.clickEdit.click(); + } + + public static void clickDelete() { + CdfCloudSqlMySqlLocators.clickDelete.click(); + } + + public static void validateComment(String expected, String actual) throws IOException { + Assert.assertEquals(expected, actual); + } + + public static void selectCloudSQLMySQL() throws InterruptedException { + SeleniumHelper.waitAndClick(CdfCloudSqlMySqlLocators.cloudSqlMysqlSource); + } + + public static void sinkCloudSQLMySQL() { + CdfCloudSqlMySqlLocators.sink.click(); + SeleniumHelper.waitAndClick(CdfCloudSqlMySqlLocators.cloudSqlMysqlSink); + } + + public static void selectBigQuerySource() throws InterruptedException { + SeleniumHelper.waitAndClick(CdfCloudSqlMySqlLocators.selectBigQuerySource); + } + + public static void clickCloudSqlPreviewData() { + CdfCloudSqlMySqlLocators.previewData.click(); + } + + public static void clickPreviewCloseButton() { + SeleniumHelper.waitAndClick(CdfCloudSqlMySqlLocators.previewClose); + } +} diff --git a/e2e-test/src/test/java/io/cdap/plugin/cloudsqlmysql/actions/package-info.java b/e2e-test/src/test/java/io/cdap/plugin/cloudsqlmysql/actions/package-info.java new file mode 100755 index 000000000..b176a9c98 --- /dev/null +++ b/e2e-test/src/test/java/io/cdap/plugin/cloudsqlmysql/actions/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright © 2021 Cask Data, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +/** + * Package contains step actions for the CloudSqlMySQL features. + */ +package io.cdap.plugin.cloudsqlmysql.actions; diff --git a/e2e-test/src/test/java/io/cdap/plugin/cloudsqlmysql/locators/CdfCloudSqlMySqlLocators.java b/e2e-test/src/test/java/io/cdap/plugin/cloudsqlmysql/locators/CdfCloudSqlMySqlLocators.java new file mode 100755 index 000000000..dd469bd16 --- /dev/null +++ b/e2e-test/src/test/java/io/cdap/plugin/cloudsqlmysql/locators/CdfCloudSqlMySqlLocators.java @@ -0,0 +1,191 @@ +/* + * Copyright © 2021 Cask Data, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package io.cdap.plugin.cloudsqlmysql.locators; + +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.FindBy; +import org.openqa.selenium.support.How; + +import java.util.List; + +/** + * CloudSqlMySql Connector Locators. + */ + +public class CdfCloudSqlMySqlLocators { + + @FindBy(how = How.XPATH, using = "//*[@data-cy='plugin-CloudSQLMySQL-batchsource']") + public static WebElement cloudSqlMysqlSource; + + @FindBy(how = How.XPATH, using = "//*[@data-cy='plugin-CloudSQLMySQL-batchsink']") + public static WebElement cloudSqlMysqlSink; + + @FindBy(how = How.XPATH, using = "//*[text()='Sink ']") + public static WebElement sink; + + @FindBy(how = How.XPATH, using = "//*[contains(@class,'plugin-endpoint_CloudSQL-MySQL')]") + public static WebElement fromCloudSqlMysqlSource; + + @FindBy(how = How.XPATH, using = "//*[@data-cy='CloudSQLMySQL-preview-data-btn']") + public static WebElement previewData; + + @FindBy(how = How.XPATH, using = "//*[@class='fa fa-remove']") + public static WebElement previewClose; + + @FindBy(how = How.XPATH, using = "//*[contains(@class,'plugin-endpoint_BigQuery')]") + public static WebElement fromBigQuerySource; + + @FindBy(how = How.XPATH, using = "//*[@title=\"CloudSQL MySQL\"]//following-sibling::div") + public static WebElement toCloudSqlMysqlSink; + + @FindBy(how = How.XPATH, using = "//*[@data-cy='referenceName' and @class='MuiInputBase-input']") + public static WebElement referenceName; + + @FindBy(how = How.XPATH, using = "//*[@data-cy='jdbcPluginName' and @class='MuiInputBase-input']") + public static WebElement driverName; + + @FindBy(how = How.XPATH, using = "//*[@data-cy='database' and @class='MuiInputBase-input']") + public static WebElement database; + + @FindBy(how = How.XPATH, using = "//*[@data-cy='importQuery']//textarea") + public static WebElement importQuery; + + @FindBy(how = How.XPATH, using = "//*[@data-cy='boundingQuery']//textarea") + public static WebElement boundingQuery; + + @FindBy(how = How.XPATH, using = "//*[@data-cy='user' and @class='MuiInputBase-input']") + public static WebElement username; + + @FindBy(how = How.XPATH, using = "//*[@placeholder='The password to use to connect to the CloudSQL database']") + public static WebElement password; + + @FindBy(how = How.XPATH, using = "//input [@type='radio' and @value='private']") + public static WebElement instanceType; + + @FindBy(how = How.XPATH, using = "//*[@data-cy='connectionName' and @class='MuiInputBase-input']") + public static WebElement connectionName; + + @FindBy(how = How.XPATH, using = "//*[@data-cy='property-row-error' and contains(text(),'Split-By Field')]") + public static WebElement splitColumnError; + + @FindBy(how = How.XPATH, using = "//*[@data-cy='property-row-error' and contains(text(),'Invalid value')]") + public static WebElement numberOfSplitError; + + @FindBy(how = How.XPATH, using = "//*[@data-cy='property-row-error' and contains(text(),'Bounding Query must')]") + public static WebElement boundingQueryError; + + @FindBy(how = How.XPATH, using = "//*[@data-cy='splitBy' and @class='MuiInputBase-input']") + public static WebElement splitColumn; + + @FindBy(how = How.XPATH, using = "//*[@data-cy='numSplits' and @class='MuiInputBase-input']") + public static WebElement numberOfSplits; + + @FindBy(how = How.XPATH, using = "//*[@data-cy='tableName' and @class='MuiInputBase-input']") + public static WebElement sqlTableName; + + @FindBy(how = How.XPATH, using = "//*[@data-cy='connectionTimeout' and @class='MuiInputBase-input']") + public static WebElement connectionTimeout; + + @FindBy(how = How.XPATH, using = "//*[@class='plugin-comments-wrapper ng-scope']") + public static WebElement clickComment; + + @FindBy(how = How.XPATH, using = "(//div[contains(@class,'MuiPaper-rounded')])[4]/div/textarea[1]") + public static WebElement addComment; + + @FindBy(how = How.XPATH, using = "(//div[contains(@class,'MuiPaper-rounded')])[4]/div[2]/div/p") + public static WebElement validateComment; + + @FindBy(how = How.XPATH, using = "(//div[contains(@class,'MuiPaper-rounded')])[3]/div[2]/div/p") + public static WebElement validateSinkComment; + + @FindBy(how = How.XPATH, using = "(//*[contains(text(), 'Comment')])[2]") + public static WebElement saveComment; + + @FindBy(how = How.XPATH, using = "(//*[contains(@class,'MuiIconButton-sizeSmall') and @tabindex='0'])") + public static WebElement editComment; + + @FindBy(how = How.XPATH, using = "(//*[@id='menu-list-grow']//child::li)[1]") + public static WebElement clickEdit; + + @FindBy(how = How.XPATH, using = "(//*[@id='menu-list-grow']//child::li)[2]") + public static WebElement clickDelete; + + @FindBy(how = How.XPATH, using = "//*[@class='fa fa-remove']") + public static WebElement closeButton; + + @FindBy(how = How.XPATH, using = "//*[@data-cy='plugin-properties-validate-btn']") + public static WebElement validateButton; + + @FindBy(how = How.XPATH, using = "//*[@class='text-danger']") + public static WebElement importQueryError; + + @FindBy(how = How.XPATH, using = "//*[@title=\"CloudSQL MySQL\"]//following-sibling::div") + public static WebElement cloudSqlMySqlProperties; + + @FindBy(how = How.XPATH, using = "//*[contains(text(),'Get Schema')]") + public static WebElement getSchemaButton; + + @FindBy(how = How.XPATH, using = "//*[@class='btn pipeline-action-btn pipeline-actions-btn']") + public static WebElement clickAction; + + @FindBy(how = How.XPATH, using = "//*[contains(text(),'Duplicate')]") + public static WebElement actionDuplicateButton; + + @FindBy(how = How.XPATH, using = "(//*[@data-cy='plugin-properties-errors-found']") + public static WebElement getSchemaStatus; + + @FindBy(how = How.XPATH, using = "//*[@data-cy='plugin-BigQueryTable-batchsource']") + public static WebElement selectBigQuerySource; + + @FindBy(how = How.XPATH, using = "//*[@placeholder='Add a comment']") + public static WebElement addCommentSink; + + @FindBy(how = How.XPATH, using = "//*[contains(@class,'Mui-disabled Mui-disabled')]") + public static WebElement disabledComment; + + @FindBy(how = How.XPATH, using = "//*[@data-cy='get-schema-btn']//span[text()='Get Schema']") + public static WebElement getSchemaLoadComplete; + + @FindBy(how = How.XPATH, + using = "//div[@data-cy='Output Schema']//div[@data-cy='schema-fields-list']//*[@placeholder='Field name']") + public static List outputSchemaColumnNames; + + @FindBy(how = How.XPATH, + using = "//div[@data-cy='Output Schema']//div[@data-cy='schema-fields-list']//select") + public static List outputSchemaDataTypes; + + @FindBy(how = How.XPATH, + using = "//div[@data-cy='Input Schema']//div[@data-cy='schema-fields-list']//*[@placeholder='Field name']") + public static List inputSchemaColumnNames; + + @FindBy(how = How.XPATH, + using = "//div[@data-cy='Input Schema']//div[@data-cy='schema-fields-list']//select") + public static List inputSchemaDataTypes; + + @FindBy(how = How.XPATH, using = "(//h2[text()='Input Records']/parent::div/div/div/div/div)[1]//div[text()!='']") + public static List previewInputRecordColumnNames; + + @FindBy(how = How.XPATH, using = "(//h2[text()='Output Records']/parent::div/div/div/div/div)[1]//div[text()!='']") + public static List previewOutputRecordColumnNames; + + @FindBy(how = How.XPATH, using = "//*[@role='tablist']/li[contains(text(),'Properties')]") + public static WebElement previewPropertiesTab; + + @FindBy(how = How.XPATH, using = "//*[contains(@data-cy,'GCS') and contains(@data-cy,'-preview-data-btn') and " + + "@class='node-preview-data-btn ng-scope']") + public static WebElement gcsPreviewData; + +} diff --git a/e2e-test/src/test/java/io/cdap/plugin/cloudsqlmysql/locators/package-info.java b/e2e-test/src/test/java/io/cdap/plugin/cloudsqlmysql/locators/package-info.java new file mode 100755 index 000000000..40c03a877 --- /dev/null +++ b/e2e-test/src/test/java/io/cdap/plugin/cloudsqlmysql/locators/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright © 2021 Cask Data, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +/** + * Package contains the locators for the cloudSqlMySql features. + */ +package io.cdap.plugin.cloudsqlmysql.locators; diff --git a/e2e-test/src/test/java/io/cdap/plugin/cloudsqlmysql/stepsdesign/CloudSqlMySql.java b/e2e-test/src/test/java/io/cdap/plugin/cloudsqlmysql/stepsdesign/CloudSqlMySql.java new file mode 100755 index 000000000..c34542b6e --- /dev/null +++ b/e2e-test/src/test/java/io/cdap/plugin/cloudsqlmysql/stepsdesign/CloudSqlMySql.java @@ -0,0 +1,846 @@ +/* + * Copyright © 2021 Cask Data, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package io.cdap.plugin.cloudsqlmysql.stepsdesign; + +import io.cdap.e2e.pages.actions.CdfBigQueryPropertiesActions; +import io.cdap.e2e.pages.actions.CdfGcsActions; +import io.cdap.e2e.pages.actions.CdfLogActions; +import io.cdap.e2e.pages.actions.CdfPipelineRunAction; +import io.cdap.e2e.pages.actions.CdfStudioActions; +import io.cdap.e2e.pages.locators.CdfStudioLocators; +import io.cdap.e2e.utils.CdfHelper; +import io.cdap.e2e.utils.GcpClient; +import io.cdap.e2e.utils.SeleniumDriver; +import io.cdap.e2e.utils.SeleniumHelper; +import io.cdap.plugin.cloudsqlmysql.actions.CdfCloudSqlMySqlActions; +import io.cdap.plugin.cloudsqlmysql.locators.CdfCloudSqlMySqlLocators; +import io.cdap.plugin.utils.CloudMySqlClient; +import io.cdap.plugin.utils.E2ETestConstants; +import io.cdap.plugin.utils.E2ETestUtils; +import io.cucumber.java.en.Given; +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; +import org.junit.Assert; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.ExpectedConditions; +import org.openqa.selenium.support.ui.WebDriverWait; +import stepsdesign.BeforeActions; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +/**a + * CloudSqlMySql related step design. + */ +public class CloudSqlMySql implements CdfHelper { + public static String folderName; + List propertiesSchemaColumnList = new ArrayList<>(); + Map sourcePropertiesOutputSchema = new HashMap<>(); + int cloudSqlMySqlPreRecordsCount; + int cloudSqlMySqlPostRecordsCount; + + @Given("Open DataFusion Project to configure pipeline") + public void openDataFusionProjectToConfigurePipeline() throws IOException, InterruptedException { + openCdf(); + } + + @When("Source is GCS bucket") + public void sourceIsGCSBucket() throws InterruptedException { + CdfStudioActions.selectGCS(); + } + + @When("Source is CloudSQLMySQL") + public void sourceIsCloudSQLMySQL() throws InterruptedException { + CdfCloudSqlMySqlActions.selectCloudSQLMySQL(); + } + + @When("Source is BigQuery") + public void sourceIsBigQuery() throws InterruptedException { + CdfCloudSqlMySqlActions.selectBigQuerySource(); + } + + @When("Target is CloudSQLMySQL") + public void targetIsCloudSQLMySQL() { + CdfCloudSqlMySqlActions.sinkCloudSQLMySQL(); + } + + @When("Target is GCS") + public void targetIsGCS() throws InterruptedException { + CdfStudioActions.sinkGcs(); + } + + @Then("Open CloudSQLMySQL Properties") + public void openCloudSQLMySQLProperties() throws InterruptedException { + CdfCloudSqlMySqlActions.clickCloudSqlMySqlProperties(); + SeleniumHelper.waitElementIsVisible(CdfCloudSqlMySqlLocators.validateButton, 10); + } + + @Then("Validate Connector properties") + public void validatePipeline() throws InterruptedException { + CdfCloudSqlMySqlActions.clickValidateButton(); + SeleniumHelper.waitElementIsVisible(CdfCloudSqlMySqlLocators.closeButton, 10); + } + + @Then("Enter the CloudSQLMySQL Source Properties with blank property {string}") + public void enterTheCloudSQLMySQLSourcePropertiesWithBlankProperty(String property) throws IOException, + InterruptedException { + if (property.equalsIgnoreCase("referenceName")) { + CdfCloudSqlMySqlActions.enterDatabaseName(E2ETestUtils.pluginProp("clsDatabaseName")); + CdfCloudSqlMySqlActions.enterConnectionName(E2ETestUtils.pluginProp("clsConnectionNameValid")); + CdfCloudSqlMySqlActions.enterImportQuery(E2ETestUtils.pluginProp("clsImportQuery")); + } else if (property.equalsIgnoreCase("database")) { + CdfCloudSqlMySqlActions.enterReferenceName(E2ETestUtils.pluginProp("clsReferenceNameValid")); + CdfCloudSqlMySqlActions.enterConnectionName(E2ETestUtils.pluginProp("clsConnectionNameValid")); + CdfCloudSqlMySqlActions.enterImportQuery(E2ETestUtils.pluginProp("clsImportQuery")); + } else if (property.equalsIgnoreCase("connectionName")) { + CdfCloudSqlMySqlActions.enterReferenceName(E2ETestUtils.pluginProp("clsReferenceNameValid")); + CdfCloudSqlMySqlActions.enterDatabaseName(E2ETestUtils.pluginProp("clsDatabaseName")); + CdfCloudSqlMySqlActions.enterImportQuery(E2ETestUtils.pluginProp("clsImportQuery")); + } else if (property.equalsIgnoreCase("importQuery")) { + CdfCloudSqlMySqlActions.enterReferenceName(E2ETestUtils.pluginProp("clsReferenceNameValid")); + CdfCloudSqlMySqlActions.enterDatabaseName(E2ETestUtils.pluginProp("clsDatabaseName")); + CdfCloudSqlMySqlActions.enterConnectionName(E2ETestUtils.pluginProp("clsConnectionNameValid")); + } else if (property.equalsIgnoreCase("jdbcPluginName")) { + CdfCloudSqlMySqlActions.enterReferenceName(E2ETestUtils.pluginProp("clsReferenceNameValid")); + SeleniumHelper.replaceElementValue(CdfCloudSqlMySqlLocators.driverName, ""); + CdfCloudSqlMySqlActions.enterDatabaseName(E2ETestUtils.pluginProp("clsDatabaseName")); + CdfCloudSqlMySqlActions.enterConnectionName(E2ETestUtils.pluginProp("clsConnectionNameValid")); + CdfCloudSqlMySqlActions.enterImportQuery(E2ETestUtils.pluginProp("clsImportQuery")); + } else { + Assert.fail("Invalid CloudSQlMySQL source mandatory field " + property); + } + } + + @Then("Enter the CloudSQLMySQL Sink Properties with blank property {string}") + public void enterTheCloudSQLMySQLSinkPropertiesWithBlankProperty(String property) throws IOException, + InterruptedException { + if (property.equalsIgnoreCase("referenceName")) { + CdfCloudSqlMySqlActions.enterDatabaseName(E2ETestUtils.pluginProp("clsDatabaseName")); + CdfCloudSqlMySqlActions.enterConnectionName(E2ETestUtils.pluginProp("clsConnectionNameValid")); + CdfCloudSqlMySqlActions.enterTableName(E2ETestUtils.pluginProp("clsTableNameBQCS")); + } else if (property.equalsIgnoreCase("database")) { + CdfCloudSqlMySqlActions.enterReferenceName(E2ETestUtils.pluginProp("clsReferenceNameValid")); + CdfCloudSqlMySqlActions.enterConnectionName(E2ETestUtils.pluginProp("clsConnectionNameValid")); + CdfCloudSqlMySqlActions.enterTableName(E2ETestUtils.pluginProp("clsTableNameBQCS")); + } else if (property.equalsIgnoreCase("connectionName")) { + CdfCloudSqlMySqlActions.enterReferenceName(E2ETestUtils.pluginProp("clsReferenceNameValid")); + CdfCloudSqlMySqlActions.enterDatabaseName(E2ETestUtils.pluginProp("clsDatabaseName")); + CdfCloudSqlMySqlActions.enterTableName(E2ETestUtils.pluginProp("clsTableNameBQCS")); + } else if (property.equalsIgnoreCase("tableName")) { + CdfCloudSqlMySqlActions.enterReferenceName(E2ETestUtils.pluginProp("clsReferenceNameValid")); + CdfCloudSqlMySqlActions.enterDatabaseName(E2ETestUtils.pluginProp("clsDatabaseName")); + CdfCloudSqlMySqlActions.enterConnectionName(E2ETestUtils.pluginProp("clsConnectionNameValid")); + } else if (property.equalsIgnoreCase("jdbcPluginName")) { + CdfCloudSqlMySqlActions.enterReferenceName(E2ETestUtils.pluginProp("clsReferenceNameValid")); + SeleniumHelper.replaceElementValue(CdfCloudSqlMySqlLocators.driverName, ""); + CdfCloudSqlMySqlActions.enterDatabaseName(E2ETestUtils.pluginProp("clsDatabaseName")); + CdfCloudSqlMySqlActions.enterConnectionName(E2ETestUtils.pluginProp("clsConnectionNameValid")); + CdfCloudSqlMySqlActions.enterTableName(E2ETestUtils.pluginProp("clsTableNameBQCS")); + } else { + Assert.fail("Invalid CloudSQLMYSQL sink mandatory field " + property); + } + } + + @Then("Validate mandatory property error for {string}") + public void validateMandatoryPropertyErrorFor(String property) { + CdfGcsActions.clickValidateButton(); + SeleniumHelper.waitElementIsVisible(CdfStudioLocators.validateButton, 7L); + E2ETestUtils.validateMandatoryPropertyError(property); + } + + @Then("Enter Reference Name & Connection Name with Invalid Test Data and import query {string}") + public void enterReferenceNameConnectionNameWthTheInvalidTestData(String query) throws InterruptedException, + IOException { + CdfCloudSqlMySqlActions.clickCloudSqlMySqlProperties(); + CdfCloudSqlMySqlActions.enterReferenceName(E2ETestUtils.pluginProp("clsReferenceNameInvalid")); + CdfCloudSqlMySqlActions.enterDatabaseName(E2ETestUtils.pluginProp("clsDatabaseName")); + CdfCloudSqlMySqlActions.enterConnectionName(E2ETestUtils.pluginProp("clsConnectionNameInvalid")); + CdfCloudSqlMySqlActions.enterImportQuery(E2ETestUtils.pluginProp(query)); + } + + @Then("Validate CloudSQLMySQL properties") + public void validateCloudSQLMySQLProperties() { + CdfGcsActions.clickValidateButton(); + String expectedErrorMessage = E2ETestUtils.errorProp(E2ETestConstants.ERROR_MSG_VALIDATION); + String actualErrorMessage = CdfStudioLocators.pluginValidationSuccessMsg.getText(); + Assert.assertEquals(expectedErrorMessage, actualErrorMessage); + } + + @Then("Enter Connection Name with private instance type") + public void enterTheInvalidPrivate() throws InterruptedException, IOException { + CdfCloudSqlMySqlActions.clickPrivateInstance(); + CdfCloudSqlMySqlActions.clickValidateButton(); + } + + @Then("Enter Reference Name & Connection Name with Invalid Test Data in Sink") + public void enterReferenceNameConnectionNameWithInvalidTestDataInSink() throws InterruptedException, IOException { + CdfCloudSqlMySqlActions.clickCloudSqlMySqlProperties(); + CdfCloudSqlMySqlActions.enterReferenceName(E2ETestUtils.pluginProp("clsReferenceNameInvalid")); + CdfCloudSqlMySqlActions.enterDatabaseName(E2ETestUtils.pluginProp("clsDatabaseName")); + CdfCloudSqlMySqlActions.enterConnectionName(E2ETestUtils.pluginProp("clsConnectionNameInvalid")); + CdfCloudSqlMySqlActions.enterTableName(E2ETestUtils.pluginProp("clsTableNameBQCS")); + } + + @Then("Verify Reference Name {string} Field with Invalid Test Data") + public void verifyReferenceNameFieldWithInvalidTestData(String referenceName) throws InterruptedException { + CdfCloudSqlMySqlActions.clickValidateButton(); + SeleniumHelper.waitElementIsVisible(CdfCloudSqlMySqlLocators.validateButton); + String expectedErrorMessage = E2ETestUtils.errorProp(E2ETestConstants.ERROR_MSG_INVALID_REFERENCE_NAME) + .replace("REFERENCE_NAME", E2ETestUtils.pluginProp(referenceName)); + String actualErrorMessage = E2ETestUtils.findPropertyErrorElement("referenceName").getText(); + Assert.assertEquals(expectedErrorMessage, actualErrorMessage); + String actualColor = E2ETestUtils.getErrorColor(E2ETestUtils.findPropertyErrorElement("referenceName")); + String expectedColor = E2ETestUtils.errorProp(E2ETestConstants.ERROR_MSG_COLOR); + Assert.assertEquals(expectedColor, actualColor); + CdfCloudSqlMySqlActions.clickValidateButton(); + } + + @Then("Verify Connection Name with private instance type {string}") + public void verifyConnectionNameWithPrivateInstanceType(String connectionName) throws InterruptedException { + SeleniumHelper.waitElementIsVisible(CdfCloudSqlMySqlLocators.validateButton); + String expectedErrorMessage = E2ETestUtils.errorProp(E2ETestConstants.ERROR_MSG_INVALID_CONNECTION_PRIVATE) + .replace("CONNECTION_NAME", E2ETestUtils.pluginProp(connectionName)); + String actualErrorMessage = E2ETestUtils.findPropertyErrorElement("connectionName").getText(); + Assert.assertEquals(expectedErrorMessage, actualErrorMessage); + String actualColor = E2ETestUtils.getErrorColor(E2ETestUtils.findPropertyErrorElement("connectionName")); + String expectedColor = E2ETestUtils.errorProp(E2ETestConstants.ERROR_MSG_COLOR); + Assert.assertEquals(expectedColor, actualColor); + CdfCloudSqlMySqlActions.clickValidateButton(); + } + + @Then("Close the CloudSQLMySQL Properties") + public void closeTheCloudSQLMySQLProperties() { + CdfCloudSqlMySqlActions.closeButton(); + } + + @Then("Enter the source CloudSQLMySQL Properties with import query {string}") + public void enterTheSourceCloudSQLMySQLPropertiesWithImportQuery(String query) throws IOException, + InterruptedException { + CdfCloudSqlMySqlActions.clickCloudSqlMySqlProperties(); + CdfCloudSqlMySqlActions.enterReferenceName(E2ETestUtils.pluginProp("clsReferenceNameValid")); + CdfCloudSqlMySqlActions.enterDefaultDriver(E2ETestUtils.pluginProp("clsDriverNameValid")); + CdfCloudSqlMySqlActions.enterDatabaseName(E2ETestUtils.pluginProp("clsDatabaseName")); + CdfCloudSqlMySqlActions.enterUserName(System.getenv("Cloud_Mysql_User_Name")); + CdfCloudSqlMySqlActions.enterPassword(System.getenv("Cloud_Mysql_Password")); + CdfCloudSqlMySqlActions.clickPrivateInstance(); + CdfCloudSqlMySqlActions.enterConnectionName(E2ETestUtils.pluginProp("clsConnectionNameValid")); + CdfCloudSqlMySqlActions.enterImportQuery(E2ETestUtils.pluginProp(query)); + CdfCloudSqlMySqlActions.getSchema(); + SeleniumHelper.waitElementIsVisible(CdfCloudSqlMySqlLocators.getSchemaButton, 30); + } + + @Then("Enter the sink CloudSQLMySQL Properties for table {string}") + public void enterSinkMandatoryFields(String tableName) throws IOException, InterruptedException { + CdfCloudSqlMySqlActions.clickCloudSqlMySqlProperties(); + CdfCloudSqlMySqlActions.enterReferenceName(E2ETestUtils.pluginProp("clsReferenceNameValid")); + CdfCloudSqlMySqlActions.enterDefaultDriver(E2ETestUtils.pluginProp("clsDriverNameValid")); + CdfCloudSqlMySqlActions.enterDatabaseName(E2ETestUtils.pluginProp("clsDatabaseName")); + CdfCloudSqlMySqlActions.enterUserName(System.getenv("Cloud_Mysql_User_Name")); + CdfCloudSqlMySqlActions.enterPassword(System.getenv("Cloud_Mysql_Password")); + CdfCloudSqlMySqlActions.enterTableName(E2ETestUtils.pluginProp(tableName)); + CdfCloudSqlMySqlActions.clickPrivateInstance(); + CdfCloudSqlMySqlActions.enterConnectionName(E2ETestUtils.pluginProp("clsConnectionNameValid")); + CdfCloudSqlMySqlActions.enterConnectionTimeout(E2ETestUtils.pluginProp("clsConnectionTimeout")); + } + + @Then("Click on Validate button") + public void clickValidate() throws IOException, InterruptedException { + CdfCloudSqlMySqlActions.clickValidateButton(); + } + + @Then("Enter Reference Name {string} & Database Name {string} with Test Data") + public void enterReferenceNameDatabaseNameWithValidTestData(String referenceName, String databaseName) + throws InterruptedException, + IOException { + CdfCloudSqlMySqlActions.enterReferenceName(E2ETestUtils.pluginProp(referenceName)); + CdfCloudSqlMySqlActions.enterDatabaseName(E2ETestUtils.pluginProp(databaseName)); + } + + @Then("Verify the get schema status") + public void verifyTheGetSchemaStatus() throws InterruptedException { + Assert.assertFalse(CdfCloudSqlMySqlLocators.getSchemaStatus.isDisplayed()); + } + + @Then("Validate the Schema") + public void validateTheSchema() throws InterruptedException { + CdfCloudSqlMySqlActions.getSchema(); + SeleniumHelper.waitElementIsVisible(CdfCloudSqlMySqlLocators.getSchemaLoadComplete, 10L); + SeleniumHelper.waitElementIsVisible(CdfCloudSqlMySqlLocators.outputSchemaColumnNames.get(0), 2L); + int index = 0; + for (WebElement element : CdfCloudSqlMySqlLocators.outputSchemaColumnNames) { + propertiesSchemaColumnList.add(element.getAttribute("value")); + sourcePropertiesOutputSchema.put(element.getAttribute("value"), + CdfCloudSqlMySqlLocators.outputSchemaDataTypes.get(index).getAttribute("title")); + index++; + } + Assert.assertTrue(propertiesSchemaColumnList.size() >= 1); + } + + @Then("Verify the Connector status") + public void verifyTheConnectorStatus() throws InterruptedException { + CdfStudioActions.clickValidateButton(); + SeleniumHelper.waitElementIsVisible(CdfStudioLocators.pluginValidationSuccessMsg, 20); + Assert.assertTrue(SeleniumDriver.getDriver().findElement + (By.xpath("//*[@data-cy='plugin-validation-success-msg']")).isDisplayed()); + } + + @When("Target is BigQuery") + public void targetIsBigQuery() { + CdfStudioActions.sinkBigQuery(); + } + + @Then("Add and Save Comments {string}") + public void addComments(String comment) throws InterruptedException, IOException { + CdfCloudSqlMySqlActions.clickCloudSqlMySqlProperties(); + CdfCloudSqlMySqlActions.clickComment(); + CdfCloudSqlMySqlActions.addComment(E2ETestUtils.pluginProp(comment)); + CdfCloudSqlMySqlActions.saveComment(); + } + + @Then("Add and Save Comments sink {string}") + public void addCommentSink(String sinkComment) throws InterruptedException, IOException { + CdfCloudSqlMySqlActions.clickCloudSqlMySqlProperties(); + CdfCloudSqlMySqlActions.clickComment(); + CdfCloudSqlMySqlActions.addCommentSink(E2ETestUtils.pluginProp(sinkComment)); + CdfCloudSqlMySqlActions.saveComment(); + } + + @Then("Edit Source Comments {string}") + public void editComments(String updateComment) throws InterruptedException, IOException { + CdfCloudSqlMySqlActions.editComment(); + CdfCloudSqlMySqlActions.clickEdit(); + CdfCloudSqlMySqlActions.updateSourceComment(E2ETestUtils.pluginProp(updateComment)); + CdfCloudSqlMySqlActions.saveComment(); + } + + @Then("Edit Sink Comments {string}") + public void editSinkComments(String updateComment) throws InterruptedException, IOException { + CdfCloudSqlMySqlActions.editComment(); + CdfCloudSqlMySqlActions.clickEdit(); + CdfCloudSqlMySqlActions.updateSinkComment(E2ETestUtils.pluginProp(updateComment)); + CdfCloudSqlMySqlActions.saveComment(); + } + + @Then("Delete Comments") + public void deleteComments() throws InterruptedException { + CdfCloudSqlMySqlActions.editComment(); + CdfCloudSqlMySqlActions.clickDelete(); + } + + @Then("Validate Source Comment") + public void validateSourceComment() throws InterruptedException, IOException { + CdfCloudSqlMySqlActions.validateComment + (E2ETestUtils.pluginProp("clsPluginValidateComment"), + CdfCloudSqlMySqlLocators.validateComment.getText()); + } + + @Then("Validate Sink Comment") + public void validateSinkComment() throws InterruptedException, IOException { + CdfCloudSqlMySqlActions.validateComment + (E2ETestUtils.pluginProp("clsPluginValidateComment"), + CdfCloudSqlMySqlLocators.validateSinkComment.getText()); + } + + @Then("Validate Source Update Comment") + public void validateSourceUpdateComment() throws InterruptedException, IOException { + CdfCloudSqlMySqlActions.validateComment + (E2ETestUtils.pluginProp("clsPluginValidateUpdateComment"), + CdfCloudSqlMySqlLocators.validateComment.getText()); + } + + @Then("Link CloudSQLMySQL to BigQuery to establish connection") + public void linkCldMySqlToBQEstablishConnection() throws InterruptedException { + SeleniumHelper.waitElementIsVisible(CdfStudioLocators.toBigQiery); + SeleniumHelper.dragAndDrop(CdfCloudSqlMySqlLocators.fromCloudSqlMysqlSource, CdfStudioLocators.toBigQiery); + } + + @Then("Link CloudSQLMySQL to GCS to establish connection") + public void linkCldMySqlToGCSEstablishConnection() throws InterruptedException { + SeleniumHelper.waitElementIsVisible(CdfStudioLocators.toGCS); + SeleniumHelper.dragAndDrop(CdfCloudSqlMySqlLocators.fromCloudSqlMysqlSource, CdfStudioLocators.toGCS); + } + + @Then("Enter the GCS Properties and {string} file format") + public void enterTheGCSProperties(String fileFormat) throws InterruptedException, IOException { + CdfGcsActions.gcsProperties(); + CdfGcsActions.enterReferenceName(); + CdfGcsActions.enterProjectId(); + CdfGcsActions.getGcsBucket(E2ETestUtils.pluginProp("clsGCSFilePath")); + CdfGcsActions.selectFormat(fileFormat); + CdfGcsActions.clickValidateButton(); + } + + @Then("Enter the Source BigQuery Properties for table {string}") + public void enterTheBQSourceProperties(String tableName) throws InterruptedException, IOException { + CdfStudioActions.clickProperties("BigQuery"); + CdfBigQueryPropertiesActions.enterProjectId(E2ETestUtils.pluginProp("clsProjectID")); + CdfBigQueryPropertiesActions.enterBigQueryReferenceName(E2ETestUtils.pluginProp("clsReferenceNameValid")); + CdfBigQueryPropertiesActions.enterBigQueryDataset(E2ETestUtils.pluginProp("clsDataset")); + CdfBigQueryPropertiesActions.enterBigQueryTable(E2ETestUtils.pluginProp(tableName)); + } + + @Then("Enter the Source BigQuery with filter {string} option") + public void enterTheBQSourcePropertiesFilter(String filter) throws InterruptedException, IOException { + CdfBigQueryPropertiesActions.enterFilter(E2ETestUtils.pluginProp(filter)); + } + + @Then("Link GCS to CloudSQLMySQL to establish connection") + public void linkGCStoCloudSQLMySQLEstablishConnection() throws InterruptedException { + SeleniumHelper.waitElementIsVisible(CdfCloudSqlMySqlLocators.toCloudSqlMysqlSink); + SeleniumHelper.dragAndDrop(CdfStudioLocators.fromGCS, CdfCloudSqlMySqlLocators.toCloudSqlMysqlSink); + } + + @Then("Enter the GCS Properties with {string} GCS bucket and format {string}") + public void enterTheGCSPropertiesWithGCSBucket(String bucket, String format) throws InterruptedException, + IOException { + CdfGcsActions.gcsProperties(); + CdfGcsActions.enterReferenceName(); + CdfGcsActions.enterProjectId(); + CdfGcsActions.getGcsBucket(E2ETestUtils.pluginProp(bucket)); + CdfGcsActions.selectFormat(E2ETestUtils.pluginProp(format)); + CdfGcsActions.skipHeader(); + CdfGcsActions.getSchema(); + SeleniumHelper.waitElementIsVisible(CdfCloudSqlMySqlLocators.getSchemaButton, 30); + } + + @Then("Run and Preview") + public void runAndPreview() throws InterruptedException { + CdfStudioActions.runAndPreviewData(); + } + + @Then("Save and Deploy Pipeline") + public void saveAndDeployPipeline() throws InterruptedException { + CdfStudioActions.pipelineName(); + CdfStudioActions.pipelineNameIp("TestPipeline" + UUID.randomUUID().toString()); + CdfStudioActions.pipelineSave(); + SeleniumHelper.waitElementIsVisible(CdfStudioLocators.statusBanner); + CdfStudioActions.pipelineDeploy(); + } + + @Then("Run the Pipeline in Runtime") + public void runThePipelineInRuntime() throws InterruptedException { + CdfPipelineRunAction.runClick(); + } + + @Then("Wait till pipeline is in running state") + public void waitTillPipelineIsInRunningState() throws InterruptedException { + Boolean bool = true; + WebDriverWait wait = new WebDriverWait(SeleniumDriver.getDriver(), 240000); + wait.until(ExpectedConditions.or(ExpectedConditions. + visibilityOfElementLocated(By.xpath("//*[@data-cy='Succeeded']")), + ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@data-cy='Failed']")))); + } + + @Then("Verify the pipeline status is {string}") + public void verifyThePipelineStatusIs(String status) { + boolean webelement = false; + webelement = SeleniumHelper.verifyElementPresent("//*[@data-cy='" + status + "']"); + Assert.assertTrue(webelement); + } + + @Then("Open and capture Logs") + public void openAndCaptureLogs() throws FileNotFoundException { + captureLogs(); + } + + @Then("Validate successMessage is displayed") + public void validateSuccessMessageIsDisplayed() { + CdfLogActions.validateSucceeded(); + } + + @Then("Click on Advance logs and validate the success message") + public void clickOnAdvanceLogsAndValidateTheSuccessMessage() { + CdfLogActions.goToAdvanceLogs(); + CdfLogActions.validateSucceeded(); + } + + @Then("Enter the BigQuery Properties for table {string}") + public void enterTheBigQueryPropertiesForTable(String tableName) throws InterruptedException, IOException { + CdfBigQueryPropertiesActions.enterBigQueryProperties(E2ETestUtils.pluginProp(tableName)); + } + + @Then("Verify Schema in output") + public void verifySchemaInOutput() { + CdfGcsActions.validateSchema(); + } + + @Then("Close the GCS Properties") + public void closeTheGCSProperties() { + CdfGcsActions.closeButton(); + } + + @Then("Close the BigQuery Properties") + public void closeTheBigQueryProperties() { + CdfGcsActions.closeButton(); + } + + @Then("Get Count of no of records transferred to BigQuery in {string}") + public void getCountOfNoOfRecordsTransferredToBigQueryIn(String table) throws IOException, InterruptedException { + int countRecords; + countRecords = GcpClient.countBqQuery(E2ETestUtils.pluginProp(table)); + BeforeActions.scenario.write("**********No of Records Transferred******************:" + countRecords); + Assert.assertEquals(countRecords, recordOut()); + } + + @Then("Validate count of records transferred from importQuery {string} to BigQuery in {string}") + public void validateCountOfRecordsTransferredFromImportQueryToBigQueryIn(String importQuery, String bqTable) throws + IOException, InterruptedException { + int bqRecordsCount = GcpClient.countBqQuery(E2ETestUtils.pluginProp(bqTable)); + BeforeActions.scenario.write("**No of Records Transferred to BQ ******************:" + bqRecordsCount); + int cloudSqlMySqlRecordsCount = CloudMySqlClient.getRecordsCount(E2ETestUtils.pluginProp(importQuery)); + BeforeActions.scenario.write("**No of Records fetched with cloudSqlMySql import query ******************:" + + cloudSqlMySqlRecordsCount); + Assert.assertEquals(cloudSqlMySqlRecordsCount, bqRecordsCount); + } + + @Then("Delete the table {string}") + public void deleteTheTable(String table) throws IOException, InterruptedException { + GcpClient.dropBqQuery(E2ETestUtils.pluginProp(table)); + BeforeActions.scenario.write("Table Deleted Successfully"); + } + + @Then("Verify Split-by column field error") + public void verifySplitByColumnFieldError() throws Exception { + CdfCloudSqlMySqlActions.clickValidateButton(); + SeleniumHelper.waitElementIsVisible(CdfCloudSqlMySqlLocators.splitColumnError, 10L); + String expectedErrorMessage = E2ETestUtils.errorProp(E2ETestConstants.ERROR_MESSAGE_SPLIT_COLUMN_NAME); + String actualErrorMessage = CdfCloudSqlMySqlLocators.splitColumnError.getText(); + Assert.assertEquals(expectedErrorMessage, actualErrorMessage); + } + + @Then("Verify Number of splits field error") + public void verifyNumberOfSplitsFieldError() throws Exception { + SeleniumHelper.waitElementIsVisible(CdfCloudSqlMySqlLocators.numberOfSplitError, 10L); + String expectedErrorMessage = E2ETestUtils.errorProp(E2ETestConstants.ERROR_MESSAGE_NUMBER_OF_SPLITS_NAME); + String actualErrorMessage = CdfCloudSqlMySqlLocators.numberOfSplitError.getText(); + Assert.assertEquals(expectedErrorMessage, actualErrorMessage); + } + + @Then("Verify Bounding Query field error") + public void verifyBoundingQueryFieldError() throws Exception { + CdfCloudSqlMySqlActions.clickValidateButton(); + SeleniumHelper.waitElementIsVisible(CdfCloudSqlMySqlLocators.boundingQueryError, 10L); + String expectedErrorMessage = E2ETestUtils.errorProp(E2ETestConstants.ERROR_MESSAGE_BOUNDING_QUERY); + String actualErrorMessage = CdfCloudSqlMySqlLocators.boundingQueryError.getText(); + Assert.assertEquals(expectedErrorMessage, actualErrorMessage); + } + + @Then("Link BigQuery to CloudSQLMySQL to establish connection") + public void linkBigQueryToCloudSQLMySQLToEstablishConnection() { + SeleniumHelper.waitElementIsVisible(CdfCloudSqlMySqlLocators.fromBigQuerySource); + SeleniumHelper.dragAndDrop( + CdfCloudSqlMySqlLocators.fromBigQuerySource, CdfCloudSqlMySqlLocators.toCloudSqlMysqlSink); + } + + @Then("Enter Table Name {string} and Connection Name {string}") + public void enterTableNameInTableField(String tableName, String connectionName) throws IOException { + CdfCloudSqlMySqlActions.enterTableName(E2ETestUtils.pluginProp(tableName)); + CdfCloudSqlMySqlActions.clickPrivateInstance(); + CdfCloudSqlMySqlActions.enterConnectionName(E2ETestUtils.pluginProp(connectionName)); + } + + @Then("Enter Connection Name {string} and Import Query {string}") + public void enterConnectionImportField(String connection, String query) throws IOException, InterruptedException { + CdfCloudSqlMySqlActions.enterUserName(System.getenv("Cloud_Mysql_User_Name")); + CdfCloudSqlMySqlActions.enterPassword(System.getenv("Cloud_Mysql_Password")); + CdfCloudSqlMySqlActions.clickPrivateInstance(); + CdfCloudSqlMySqlActions.enterConnectionName(E2ETestUtils.pluginProp(connection)); + CdfCloudSqlMySqlActions.enterImportQuery(E2ETestUtils.pluginProp(query)); + } + + @Then("Replace and enter Invalid Driver value") + public void enterInvalidDriverName() throws IOException { + SeleniumHelper.replaceElementValue(CdfCloudSqlMySqlLocators.driverName, + E2ETestUtils.pluginProp("clsDriverNameInvalid")); + } + + @Then("Enter Driver Name with Invalid value for Driver name field {string}") + public void enterDriverNameDefaultValue(String driverName) throws IOException { + CdfCloudSqlMySqlActions.enterDefaultDriver(E2ETestUtils.pluginProp(driverName)); + } + + @Then("Create Duplicate pipeline") + public void createDuplicatePipeline() throws InterruptedException { + CdfCloudSqlMySqlActions.clickActionButton(); + CdfCloudSqlMySqlActions.clickDuplicateButton(); + } + + @Then("Verify invalid Driver name error message is displayed for Driver {string}") + public void verifyInvalidDriverNameErrorMessageIsDisplayedForDriver(String driverName) { + CdfCloudSqlMySqlActions.clickValidateButton(); + SeleniumHelper.waitElementIsVisible(CdfCloudSqlMySqlLocators.validateButton); + String expectedErrorMessage = E2ETestUtils.errorProp(E2ETestConstants.ERROR_MSG_INVALID_DRIVER_NAME) + .replaceAll("DRIVER_NAME", E2ETestUtils.pluginProp(driverName)); + String actualErrorMessage = E2ETestUtils.findPropertyErrorElement("jdbcPluginName").getText(); + Assert.assertEquals(expectedErrorMessage, actualErrorMessage); + String actualColor = E2ETestUtils.getErrorColor(E2ETestUtils.findPropertyErrorElement("jdbcPluginName")); + String expectedColor = E2ETestUtils.errorProp(E2ETestConstants.ERROR_MSG_COLOR); + Assert.assertEquals(expectedColor, actualColor); + } + + @Then("Validate the output record count") + public void validateTheOutputRecordCount() { + Assert.assertTrue(recordIn() > 0); + } + + @Then("Validate studio is opened with duplicate pipeline") + public void validateStudioIsOpened() { + Assert.assertTrue(CdfStudioLocators.pipelineDeploy.isDisplayed()); + } + + @Then("Enter the source CloudSQLMySQL properties with import query {string} bounding query {string}") + public void enterTheAdvancedSourceCloudSQLMySQLProperties(String importQuery, + String boundingQuery) throws IOException, + InterruptedException { + CdfCloudSqlMySqlActions.clickCloudSqlMySqlProperties(); + CdfCloudSqlMySqlActions.enterReferenceName(E2ETestUtils.pluginProp("clsReferenceNameValid")); + CdfCloudSqlMySqlActions.enterDefaultDriver(E2ETestUtils.pluginProp("clsDriverNameValid")); + CdfCloudSqlMySqlActions.enterDatabaseName(E2ETestUtils.pluginProp("clsDatabaseName")); + CdfCloudSqlMySqlActions.enterUserName(System.getenv("Cloud_Mysql_User_Name")); + CdfCloudSqlMySqlActions.enterPassword(System.getenv("Cloud_Mysql_Password")); + CdfCloudSqlMySqlActions.clickPrivateInstance(); + CdfCloudSqlMySqlActions.enterConnectionName(E2ETestUtils.pluginProp("clsConnectionNameValid")); + CdfCloudSqlMySqlActions.enterImportQuery(E2ETestUtils.pluginProp(importQuery)); + CdfCloudSqlMySqlActions.getSchema(); + CdfCloudSqlMySqlActions.enterBoundingQuery(E2ETestUtils.pluginProp(boundingQuery)); + } + + @Then("Enter the source CloudSQL-MySQL properties with import query {string} and blank bounding query") + public void enterTheSplitColumnInSourceCloudSQLMySQLProperties(String importQuery) throws IOException, + InterruptedException { + CdfCloudSqlMySqlActions.clickCloudSqlMySqlProperties(); + CdfCloudSqlMySqlActions.enterReferenceName(E2ETestUtils.pluginProp("clsReferenceNameValid")); + CdfCloudSqlMySqlActions.enterDefaultDriver(E2ETestUtils.pluginProp("clsDriverNameValid")); + CdfCloudSqlMySqlActions.enterDatabaseName(E2ETestUtils.pluginProp("clsDatabaseName")); + CdfCloudSqlMySqlActions.enterUserName(System.getenv("Cloud_Mysql_User_Name")); + CdfCloudSqlMySqlActions.enterPassword(System.getenv("Cloud_Mysql_Password")); + CdfCloudSqlMySqlActions.clickPrivateInstance(); + CdfCloudSqlMySqlActions.enterConnectionName(E2ETestUtils.pluginProp("clsConnectionNameValid")); + CdfCloudSqlMySqlActions.enterImportQuery(E2ETestUtils.pluginProp(importQuery)); + } + + @Then("Enter the source CloudSQL-MySQL with Split and Number of splits CloudSQLMySQL properties") + public void enterSplitNumberOfSplitsCloudSQLMySQLProperties() throws IOException, InterruptedException { + CdfCloudSqlMySqlActions.enterSplitColumn(E2ETestUtils.pluginProp("clsSplitColumn")); + CdfCloudSqlMySqlActions.enterNumberOfSplits(E2ETestUtils.pluginProp("clsNumberOfSplits")); + } + + @Then("Capture output schema") + public void captureOutputSchema() { + CdfCloudSqlMySqlActions.getSchema(); + SeleniumHelper.waitElementIsVisible(CdfCloudSqlMySqlLocators.getSchemaLoadComplete, 10L); + SeleniumHelper.waitElementIsVisible(CdfCloudSqlMySqlLocators.outputSchemaColumnNames.get(0), 2L); + int index = 0; + for (WebElement element : CdfCloudSqlMySqlLocators.outputSchemaColumnNames) { + propertiesSchemaColumnList.add(element.getAttribute("value")); + sourcePropertiesOutputSchema.put(element.getAttribute("value"), + CdfCloudSqlMySqlLocators.outputSchemaDataTypes.get(index).getAttribute("title")); + index++; + } + Assert.assertTrue(propertiesSchemaColumnList.size() >= 1); + } + + @Then("Save the pipeline") + public void saveThePipeline() { + CdfStudioActions.pipelineName(); + CdfStudioActions.pipelineNameIp("CloudSQLMySQL" + UUID.randomUUID().toString()); + CdfStudioActions.pipelineSave(); + SeleniumHelper.waitElementIsVisible(CdfStudioLocators.statusBanner); + WebDriverWait wait = new WebDriverWait(SeleniumDriver.getDriver(), 5); + wait.until(ExpectedConditions.invisibilityOf(CdfStudioLocators.statusBanner)); + } + + @Then("Preview and run the pipeline") + public void previewAndRunThePipeline() { + SeleniumHelper.waitElementIsVisible(CdfStudioLocators.preview, 5); + CdfStudioLocators.preview.click(); + CdfStudioLocators.runButton.click(); + } + + @Then("Verify the preview of pipeline is {string}") + public void verifyThePreviewOfPipelineIs(String previewStatus) { + WebDriverWait wait = new WebDriverWait(SeleniumDriver.getDriver(), 180); + wait.until(ExpectedConditions.visibilityOfElementLocated( + By.xpath("//*[@data-cy='valium-banner-hydrator']//span[contains(text(),'" + previewStatus + "')]"))); + if (!previewStatus.equalsIgnoreCase("failed")) { + wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//*[@data-cy=" + + "'valium-banner-hydrator']"))); + } + } + + @Then("Click on PreviewData for CloudSQL MySQL") + public void clickOnPreviewDataForCloudSql() { + CdfCloudSqlMySqlActions.clickCloudSqlPreviewData(); + } + + @Then("Verify Preview output schema matches the outputSchema captured in properties") + public void verifyPreviewOutputSchemaMatchesTheOutputSchemaCapturedInProperties() { + List previewSchemaColumnList = new ArrayList<>(); + for (WebElement element : CdfCloudSqlMySqlLocators.previewInputRecordColumnNames) { + previewSchemaColumnList.add(element.getAttribute("title")); + } + Assert.assertTrue(previewSchemaColumnList.equals(propertiesSchemaColumnList)); + CdfCloudSqlMySqlLocators.previewPropertiesTab.click(); + Map previewSinkInputSchema = new HashMap<>(); + int index = 0; + for (WebElement element : CdfCloudSqlMySqlLocators.inputSchemaColumnNames) { + previewSinkInputSchema.put(element.getAttribute("value"), + CdfCloudSqlMySqlLocators.inputSchemaDataTypes.get(index).getAttribute("title")); + index++; + } + Assert.assertTrue(previewSinkInputSchema.equals(sourcePropertiesOutputSchema)); + } + + @Then("Close the Preview") + public void closeThePreview() { + CdfCloudSqlMySqlActions.clickPreviewCloseButton(); + CdfStudioActions.previewSelect(); + } + + @Then("Deploy the pipeline") + public void deployThePipeline() { + SeleniumHelper.waitElementIsVisible(CdfStudioLocators.pipelineDeploy, 2); + CdfStudioActions.pipelineDeploy(); + } + + @Then("Enter the incorrect values in split column with number of splits") + public void enterTheIncorrectValuesInSplitColumnWithDefaultNumberOfSplits() throws IOException { + CdfCloudSqlMySqlLocators.splitColumn.sendKeys(E2ETestUtils.pluginProp("clsIncorrectSplit")); + SeleniumHelper.replaceElementValue(CdfCloudSqlMySqlLocators.numberOfSplits, + E2ETestUtils.pluginProp("clsNumberOfSplits")); + } + + @Then("Provide blank values in Split column and invalid Number of splits") + public void provideBlankValuesInSplitColumnAndNumberOfSplitsFields() throws IOException { + SeleniumHelper.replaceElementValue(CdfCloudSqlMySqlLocators.numberOfSplits, + E2ETestUtils.pluginProp("clsInvalidNumberOfSplits")); + } + + @Then("Click on PreviewData for BigQuery") + public void clickOnPreviewDataForBigQuery() { + CdfBigQueryPropertiesActions.clickPreviewData(); + } + + @Then("Click on PreviewData for GCS") + public void clickOnPreviewDataForGCS() { + CdfCloudSqlMySqlLocators.gcsPreviewData.click(); + } + + @Then("Validate Comment has been deleted successfully") + public void validateCommentHasBeenDeletedSuccessfully() throws IOException { + CdfCloudSqlMySqlActions.closeButton(); + CdfCloudSqlMySqlActions.clickCloudSqlMySqlProperties(); + CdfCloudSqlMySqlActions.clickComment(); + Assert.assertFalse(CdfCloudSqlMySqlLocators.disabledComment.isEnabled()); + } + + @Then("Verify invalid import query error message is displayed for import query {string}") + public void verifyInvalidImportQueryErrorMessageIsDisplayedForImportQuery(String importQuery) { + SeleniumHelper.waitElementIsVisible(CdfCloudSqlMySqlLocators.importQueryError, 10L); + String expectedErrorMessage = E2ETestUtils.errorProp(E2ETestConstants.ERROR_MSG_INVALID_IMPORT_QUERY); + String actualErrorMessage = CdfCloudSqlMySqlLocators.importQueryError.getText(); + Assert.assertEquals(expectedErrorMessage, actualErrorMessage); + } + + @Then("Verify plugin validation fails with error") + public void verifyPluginValidationFailsWithError() { + CdfStudioActions.clickValidateButton(); + SeleniumHelper.waitElementIsVisible(CdfStudioLocators.pluginValidationErrorMsg, 10L); + String expectedErrorMessage = E2ETestUtils.errorProp(E2ETestConstants.ERROR_MSG_ERROR_FOUND_VALIDATION); + String actualErrorMessage = CdfStudioLocators.pluginValidationErrorMsg.getText(); + Assert.assertEquals(expectedErrorMessage, actualErrorMessage); + } + + @Then("Verify Connection Name {string} fields with Invalid Test Data") + public void verifyConnectionNameFieldsWithInvalidTestData(String connectionName) { + SeleniumHelper.waitElementIsVisible(CdfCloudSqlMySqlLocators.validateButton); + String expectedErrorMessage = E2ETestUtils.errorProp(E2ETestConstants.ERROR_MSG_INVALID_CONNECTION_PUBLIC) + .replace("CONNECTION_NAME", E2ETestUtils.pluginProp(connectionName)); + String actualErrorMessage = E2ETestUtils.findPropertyErrorElement("connectionName").getText(); + Assert.assertEquals(expectedErrorMessage, actualErrorMessage); + String actualColor = E2ETestUtils.getErrorColor(E2ETestUtils.findPropertyErrorElement("connectionName")); + String expectedColor = E2ETestUtils.errorProp(E2ETestConstants.ERROR_MSG_COLOR); + Assert.assertEquals(expectedColor, actualColor); + CdfCloudSqlMySqlActions.clickValidateButton(); + } + + @Given("Cloud Storage bucket should not exist in {string} with the name {string}") + public void projectIdCloudStorageBucketShouldNotExistInWithTheName(String projectId, String bucketName) { + E2ETestUtils.deleteBucket(E2ETestUtils.pluginProp(projectId), E2ETestUtils.pluginProp(bucketName)); + } + + @Then("Verify the folder created in {string} with bucket name {string}") + public void verifyTheFolderCreatedInWithBucketName(String projectID, String bucketName) { + folderName = E2ETestUtils.listObjects(E2ETestUtils.pluginProp(projectID), + E2ETestUtils.pluginProp(bucketName)); + Assert.assertTrue(folderName != null); + } + + @Then("Validate the count of records transferred from BigQuery {string} to CloudSqlMySql {string}") + public void validateTheCountOfRecordsTransferredFromBigQueryToCloudSqlMySql(String bqTable, String sqlTable) throws + IOException, InterruptedException { + int bqRecordsCount = GcpClient.countBqQuery(E2ETestUtils.pluginProp(bqTable)); + BeforeActions.scenario.write("**No of Records Transferred from BQ ******************:" + bqRecordsCount); + int cloudSqlMySqlRecordsCount = cloudSqlMySqlPostRecordsCount - cloudSqlMySqlPreRecordsCount; + BeforeActions.scenario.write("**No of Records Transferred into the cloudSqlMySql table ******************:" + + cloudSqlMySqlRecordsCount); + Assert.assertEquals(bqRecordsCount, cloudSqlMySqlRecordsCount); + } + + @Then("Pre records count from CloudSQLMySQL table {string}") + public void preRecordsCountFromCloudSQLMySQLTable(String sqlTable) { + cloudSqlMySqlPreRecordsCount = CloudMySqlClient.countCloudSqlMySqlQuery(E2ETestUtils.pluginProp(sqlTable)); + } + + @Then("Post records count from CloudSQLMySQL table {string}") + public void postRecordsCountFromCloudSQLMySQLTable(String sqlTable) { + cloudSqlMySqlPostRecordsCount = CloudMySqlClient.countCloudSqlMySqlQuery(E2ETestUtils.pluginProp(sqlTable)); + } + + public int getRowCountFromBigQueryTableOnTheBasisOfFilter(String bqTable, String filter) + throws IOException, InterruptedException { + String projectId = (E2ETestUtils.pluginProp("clsProjectID")); + String datasetName = (E2ETestUtils.pluginProp("clsDataset")); + String selectQuery = "SELECT count(*) FROM `" + projectId + "." + datasetName + "." + E2ETestUtils.pluginProp + (bqTable) + "` WHERE " + + E2ETestUtils.pluginProp(filter); + int rowCount = GcpClient.getSoleQueryResult(selectQuery).map(Integer::parseInt).orElse(0);; + return rowCount; + } + + @Then("Validate the count of records transferred from BigQuery {string} to CloudSqlMySql with filter {string}") + public void validateTheCountOfRecordsTransferredFromBigQueryToCloudSqlMySqlWithFilter(String bqTable, String filter) + throws IOException, InterruptedException { + int bqRecordsCount = getRowCountFromBigQueryTableOnTheBasisOfFilter(bqTable, filter); + BeforeActions.scenario.write("**No of Records Transferred from BQ ******************:" + bqRecordsCount); + int cloudSqlMySqlRecordsCount = cloudSqlMySqlPostRecordsCount - cloudSqlMySqlPreRecordsCount; + BeforeActions.scenario.write("**No of Records Transferred into the cloudSqlMySql table ******************:" + + cloudSqlMySqlRecordsCount); + Assert.assertEquals(bqRecordsCount, cloudSqlMySqlRecordsCount); + } + + @Then("Validate Sink Update Comment") + public void validateSinkUpdateComment() throws IOException { + CdfCloudSqlMySqlActions.validateComment + (E2ETestUtils.pluginProp("clsPluginValidateUpdateComment"), + CdfCloudSqlMySqlLocators.validateSinkComment.getText()); + } +} diff --git a/e2e-test/src/test/java/io/cdap/plugin/cloudsqlmysql/stepsdesign/package-info.java b/e2e-test/src/test/java/io/cdap/plugin/cloudsqlmysql/stepsdesign/package-info.java new file mode 100755 index 000000000..8a4b3cd79 --- /dev/null +++ b/e2e-test/src/test/java/io/cdap/plugin/cloudsqlmysql/stepsdesign/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright © 2021 Cask Data, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +/** + * Package contains the stepDesign for the CloudSqlMySql features. + */ +package io.cdap.plugin.cloudsqlmysql.stepsdesign; diff --git a/e2e-test/src/test/java/io/cdap/plugin/cloudsqlmysql/tests/runner/TestRunner.java b/e2e-test/src/test/java/io/cdap/plugin/cloudsqlmysql/tests/runner/TestRunner.java new file mode 100755 index 000000000..66962fb5f --- /dev/null +++ b/e2e-test/src/test/java/io/cdap/plugin/cloudsqlmysql/tests/runner/TestRunner.java @@ -0,0 +1,34 @@ +/* + * Copyright © 2021 Cask Data, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package io.cdap.plugin.cloudsqlmysql.tests.runner; +import io.cucumber.junit.Cucumber; +import io.cucumber.junit.CucumberOptions; +import org.junit.runner.RunWith; + +/** + * Test Runner to execute cases. + */ +@RunWith(Cucumber.class) +@CucumberOptions( + features = {"src/test/features"}, + glue = {"io.cdap.plugin.cloudsqlmysql.stepsdesign", "stepsdesign"}, + tags = {"@CLDMYSQL"}, + monochrome = true, + plugin = {"pretty", "html:target/cucumber-html-report", "json:target/cucumber-reports/cucumber.json", + "junit:target/cucumber-reports/cucumber.xml"} +) +public class TestRunner { +} diff --git a/e2e-test/src/test/java/io/cdap/plugin/cloudsqlmysql/tests/runner/package-info.java b/e2e-test/src/test/java/io/cdap/plugin/cloudsqlmysql/tests/runner/package-info.java new file mode 100755 index 000000000..871ff5163 --- /dev/null +++ b/e2e-test/src/test/java/io/cdap/plugin/cloudsqlmysql/tests/runner/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright © 2021 Cask Data, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +/** + * Package contains the runner for the CloudSqlMySQL features. + */ +package io.cdap.plugin.cloudsqlmysql.tests.runner; diff --git a/e2e-test/src/test/java/io/cdap/plugin/utils/CloudMySqlClient.java b/e2e-test/src/test/java/io/cdap/plugin/utils/CloudMySqlClient.java new file mode 100644 index 000000000..efb8f19f6 --- /dev/null +++ b/e2e-test/src/test/java/io/cdap/plugin/utils/CloudMySqlClient.java @@ -0,0 +1,91 @@ +/* + * Copyright © 2021 Cask Data, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package io.cdap.plugin.utils; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import org.apache.log4j.Logger; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Optional; + +/** + * CloudSQLMYSQL database operations client. + */ +public class CloudMySqlClient { + + private static final Logger logger = Logger.getLogger(CloudMySqlClient.class); + static Connection connection = null; + + private static Connection getCloudMySqlConnection() { + if (connection == null) { + HikariConfig config = new HikariConfig(); + config.setJdbcUrl("jdbc:mysql:/" + E2ETestUtils.pluginProp("clsDatabaseName")); + config.setUsername(System.getenv("Cloud_Mysql_User_Name")); + config.setPassword(System.getenv("Cloud_Mysql_Password")); + config.addDataSourceProperty("socketFactory", "com.google.cloud.sql.mysql.SocketFactory"); + config.addDataSourceProperty("cloudSqlInstance", E2ETestUtils.pluginProp("cloudSqlInstance")); + config.addDataSourceProperty("ipTypes", "PRIVATE"); + config.setMaximumPoolSize(5); + config.setMinimumIdle(5); + config.setConnectionTimeout(10000); + config.setIdleTimeout(600000); + config.setMaxLifetime(1800000); + HikariDataSource pool = new HikariDataSource(config); + try { + connection = pool.getConnection(); + } catch (SQLException e) { + logger.error("Error while creating CloudSqlMySql connection : " + e); + } + } + return connection; + } + + public static Optional getSoleQueryResult(String query) { + String outputRowValue = null; + try (PreparedStatement createTableStatement = getCloudMySqlConnection().prepareStatement(query);) { + ResultSet resultSet = createTableStatement.executeQuery(); + if (resultSet.next()) { + outputRowValue = resultSet.getString(1); + } + } catch (SQLException e) { + logger.error("Error while executing CloudSqlMySql query : " + e); + } + return Optional.ofNullable(outputRowValue); + } + + public static int countCloudSqlMySqlQuery(String table) { + String query = "SELECT count(*) from " + table; + return getSoleQueryResult(query).map(Integer::parseInt).orElse(0); + } + + public static int getRecordsCount(String query) { + int count = 0; + try (PreparedStatement createTableStatement = getCloudMySqlConnection() + .prepareStatement(query, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) { + ResultSet resultSet = createTableStatement.executeQuery(); + if (resultSet.last()) { + count = resultSet.getRow(); + } + } catch (SQLException e) { + logger.error("Error while getting CloudSqlMySQL records count : " + e); + } + return count; + } +} diff --git a/e2e-test/src/test/java/io/cdap/plugin/utils/E2ETestConstants.java b/e2e-test/src/test/java/io/cdap/plugin/utils/E2ETestConstants.java new file mode 100644 index 000000000..5fa1f1a2e --- /dev/null +++ b/e2e-test/src/test/java/io/cdap/plugin/utils/E2ETestConstants.java @@ -0,0 +1,34 @@ +/* + * Copyright © 2021 Cask Data, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package io.cdap.plugin.utils; + +/** + * E2E test constants. + */ +public class E2ETestConstants { + public static final String ERROR_MSG_VALIDATION = "errorMessageValidation"; + public static final String ERROR_MSG_INVALID_DRIVER_NAME = "errorMessageDriverName"; + public static final String ERROR_MSG_COLOR = "errorMessageColor"; + public static final String ERROR_MSG_MANDATORY = "errorMessageMandatory"; + public static final String ERROR_MSG_ERROR_FOUND_VALIDATION = "errorMessageErrorFoundValidation"; + public static final String ERROR_MSG_INVALID_IMPORT_QUERY = "errorMessageImportQuery"; + public static final String ERROR_MSG_INVALID_REFERENCE_NAME = "errorMessageReferenceName"; + public static final String ERROR_MSG_INVALID_CONNECTION_PUBLIC = "errorMessagePublicConnectionName"; + public static final String ERROR_MSG_INVALID_CONNECTION_PRIVATE = "errorMessagePrivateConnectionName"; + public static final String ERROR_MESSAGE_SPLIT_COLUMN_NAME = "errorMessageSplitColumn"; + public static final String ERROR_MESSAGE_NUMBER_OF_SPLITS_NAME = "errorMessageNumberOfSplit"; + public static final String ERROR_MESSAGE_BOUNDING_QUERY = "errorMessageBoundingQuery"; +} diff --git a/e2e-test/src/test/java/io/cdap/plugin/utils/E2ETestUtils.java b/e2e-test/src/test/java/io/cdap/plugin/utils/E2ETestUtils.java new file mode 100644 index 000000000..072b04e2e --- /dev/null +++ b/e2e-test/src/test/java/io/cdap/plugin/utils/E2ETestUtils.java @@ -0,0 +1,120 @@ +/* + * Copyright © 2021 Cask Data, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package io.cdap.plugin.utils; + +import com.google.api.gax.paging.Page; +import com.google.cloud.storage.Blob; +import com.google.cloud.storage.Bucket; +import com.google.cloud.storage.Storage; +import com.google.cloud.storage.StorageOptions; +import io.cdap.e2e.utils.ConstantsUtil; +import io.cdap.e2e.utils.SeleniumDriver; +import org.apache.log4j.Logger; +import org.junit.Assert; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; +import stepsdesign.BeforeActions; + +import java.io.IOException; +import java.util.Properties; + +/** + * E2ETestUtils contains the helper functions. + */ + +public class E2ETestUtils { + private static Properties pluginProperties = new Properties(); + private static Properties errorProperties = new Properties(); + private static final Logger logger = Logger.getLogger(E2ETestUtils.class); + + static { + + try { + pluginProperties.load(E2ETestUtils.class.getResourceAsStream("/pluginParameters.properties")); + errorProperties.load(E2ETestUtils.class.getResourceAsStream("/errorMessage.properties")); + } catch (IOException e) { + logger.error("Error while reading properties file" + e); + } + } + + public static String pluginProp(String property) { + return pluginProperties.getProperty(property); + } + + public static String errorProp(String property) { + return errorProperties.getProperty(property); + } + + public static void validateMandatoryPropertyError(String property) { + String expectedErrorMessage = errorProp(E2ETestConstants.ERROR_MSG_MANDATORY) + .replaceAll("PROPERTY", property); + String actualErrorMessage = findPropertyErrorElement(property).getText(); + Assert.assertEquals(expectedErrorMessage, actualErrorMessage); + String actualColor = E2ETestUtils.getErrorColor(E2ETestUtils.findPropertyErrorElement(property)); + String expectedColor = E2ETestUtils.errorProp(E2ETestConstants.ERROR_MSG_COLOR); + Assert.assertEquals(expectedColor, actualColor); + } + + public static WebElement findPropertyErrorElement(String property) { + return SeleniumDriver.getDriver().findElement( + By.xpath("//*[@data-cy='" + property + "']/following-sibling::div[@data-cy='property-row-error']")); + } + + public static String getErrorColor(WebElement element) { + String color = element.getCssValue(ConstantsUtil.COLOR); + String[] hexValue = color.replace("rgba(", ""). + replace(")", "").split(","); + int hexValue1 = Integer.parseInt(hexValue[0]); + hexValue[1] = hexValue[1].trim(); + int hexValue2 = Integer.parseInt(hexValue[1]); + hexValue[2] = hexValue[2].trim(); + int hexValue3 = Integer.parseInt(hexValue[2]); + return String.format("#%02x%02x%02x", hexValue1, hexValue2, hexValue3); + } + + public static void deleteBucket(String projectId, String bucketName) { + try { + Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService(); + Bucket bucket = storage.get(bucketName); + StorageOptions.Builder optionsBuilder = StorageOptions.newBuilder(); + Iterable blobs = storage.list(bucketName, + Storage.BlobListOption.prefix("")).iterateAll(); + for (Blob blob : blobs) { + blob.delete(Blob.BlobSourceOption.generationMatch()); + } + + storage.delete(bucketName, + Storage.BucketSourceOption.userProject(projectId)); + bucket.delete(); + BeforeActions.scenario.write("Bucket " + bucket.getName() + " was deleted"); + } catch (Exception e) { + BeforeActions.scenario.write("Bucket doesn't exist"); + } + } + + public static String listObjects(String projectId, String bucketName) { + String folderName = null; + Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService(); + Page blobs = storage.list(bucketName); + for (Blob blob : blobs.iterateAll()) { + if (blob.getName().contains("part")) { + folderName = blob.getName(); + break; + } + } + return folderName; + } +} diff --git a/e2e-test/src/test/java/io/cdap/plugin/utils/package-info.java b/e2e-test/src/test/java/io/cdap/plugin/utils/package-info.java new file mode 100644 index 000000000..aa77fdc52 --- /dev/null +++ b/e2e-test/src/test/java/io/cdap/plugin/utils/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright © 2021 Cask Data, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +/** + * Package contains the helper utils. + */ +package io.cdap.plugin.utils; diff --git a/e2e-test/src/test/resources/errorMessage.properties b/e2e-test/src/test/resources/errorMessage.properties new file mode 100644 index 000000000..34ab74e3b --- /dev/null +++ b/e2e-test/src/test/resources/errorMessage.properties @@ -0,0 +1,17 @@ +errorMessageColor=#a40403 +errorMessageMandatory=Required property 'PROPERTY' has no value. +errorMessageSplitColumn=Split-By Field Name must be specified if Number of Splits is not set to 1. +errorMessageNumberOfSplit=Invalid value for numSplits '0'. Must be at least 1. +errorMessageBoundingQuery=Bounding Query must be specified if Number of Splits is not set to 1. +errorMessageValidation=No errors found. +errorMessageErrorFoundValidation=1 error found +errorMessageDriverName=Unable to load JDBC Driver class for plugin name 'DRIVER_NAME'. Ensure that the \ + plugin 'DRIVER_NAME' of type 'jdbc' containing the driver has been installed correctly. +errorMessageImportQuery=SQL error while getting query schema: You have an error in your SQL syntax; check the manual \ + that corresponds to your MySQL server version for the right syntax to use near 'query' at line 1 +errorMessageReferenceName=Invalid reference name 'REFERENCE_NAME'. Supported characters are: letters, numbers, \ + and '_', '-', '.', or '$'. +errorMessagePublicConnectionName=Connection Name must be in the format :: to \ + connect to a public CloudSQL MySQL instance. +errorMessagePrivateConnectionName=Enter the internal IP address of the Compute Engine VM cloudsql proxy is running on,\ + \ to connect to a private CloudSQL MySQL instance. diff --git a/e2e-test/src/test/resources/pluginParameters.properties b/e2e-test/src/test/resources/pluginParameters.properties new file mode 100644 index 000000000..617c45bbd --- /dev/null +++ b/e2e-test/src/test/resources/pluginParameters.properties @@ -0,0 +1,41 @@ +projectId=cdf-athena +dataset=test_automation +windowSize=1920x1040 +clsErrorMessageColor=#a40403 +clsPluginComment=Comment for Plugin +clsPluginUpdateComment=CloudSQL MySQL +clsPluginValidateComment=Comment for Plugin +clsPluginValidateUpdateComment=CloudSQL MySQL Comment for Plugin +clsReferenceNameInvalid=#@#@#@#@#@ +clsReferenceNameValid=TestReference +clsDriverNameInvalid=@@!67RTC +clsDriverNameValid=cloudsql-mysql +clsDatabaseName=cdfdb +cloudSqlInstance=cdf-athena:europe-west1:cdf-qa-testdb +ipTypes=PRIVATE +clsConnectionNameInvalid=10 +clsImportQuery=select * from cdftest4; +clsInvalidImportQuery=import query; +clsImportQuery1=select * from cdftest4 where $CONDITIONS; +clsImportQuery2=select * from cdftest4 where parent_id=2056; +clsBoundingQuery=select MIN(s_no),MAX(s_no) from cdftest4; +clsConnectionNameValid=10.232.15.232 +clsConnectionTimeout=20 +clsSplitColumn=s_no +clsIncorrectSplit=@#*() +clsNumberOfSplits=3 +clsInvalidNumberOfSplits=0 +clsTableNameBQCS=cdftest2 +clsTableNameGCSCS=cdftest3 +clsTableNameBQCS1=cdftest4 +clsPathGCS=gs://cdf-athena-test/cloudmysql +clsDataset=test_abc +clsProjectID=cdf-athena +clsTableNameBQ=tableabc +clsTableNameBQ1=tablecloud +clsBucket=gs://cdf-athena-test/TestingGCS.csv +clsFormatType=csv +clsFilterBigQuery=country_code='RS' +clsMySQLBQTableName=DemoCheck1 +clsGCSFilePath=gs://cloudmysqlfilegcs +clsFileBucketCreate=cloudmysqlfilegcs diff --git a/pom.xml b/pom.xml index f305ecea5..57f3033aa 100644 --- a/pom.xml +++ b/pom.xml @@ -469,6 +469,14 @@ **/org/apache/hadoop/** **/resources/** + e2e-test/**/*.properties + e2e-test/**/*.feature + e2e-test/**/cucumber**/** + e2e-test/**/maven-status/** + e2e-test/**/failsafe-reports/** + e2e-test/**/e2e-debug/** + e2e-test/**/*-result.xml + e2e-test/e2e-test.iml