From 8861cb57314c984fd5b6b402c171d26a3fc7acd9 Mon Sep 17 00:00:00 2001 From: vipinbhatt Date: Tue, 18 Jul 2023 19:37:11 +0530 Subject: [PATCH] CDF Login --- .../pages/actions/CdfPipelineRunAction.java | 28 ++++++--- .../e2e/pages/actions/CdfSignInActions.java | 58 +++++++++++++++++++ .../e2e/pages/locators/CdfSignInLocator.java | 58 +++++++++++++++++++ .../java/io/cdap/e2e/utils/CdfHelper.java | 8 +++ .../java/io/cdap/e2e/utils/ConstantsUtil.java | 10 ++++ .../java/io/cdap/e2e/utils/ElementHelper.java | 26 +++++++++ .../java/io/cdap/e2e/utils/RetryUtils.java | 52 +++++++++++++++++ src/main/java/stepsdesign/PipelineSteps.java | 2 +- .../resources/connectionParameters.properties | 4 ++ 9 files changed, 238 insertions(+), 8 deletions(-) create mode 100644 src/main/java/io/cdap/e2e/pages/actions/CdfSignInActions.java create mode 100644 src/main/java/io/cdap/e2e/pages/locators/CdfSignInLocator.java create mode 100644 src/main/java/io/cdap/e2e/utils/RetryUtils.java diff --git a/src/main/java/io/cdap/e2e/pages/actions/CdfPipelineRunAction.java b/src/main/java/io/cdap/e2e/pages/actions/CdfPipelineRunAction.java index 5aa99a596..aa781b156 100644 --- a/src/main/java/io/cdap/e2e/pages/actions/CdfPipelineRunAction.java +++ b/src/main/java/io/cdap/e2e/pages/actions/CdfPipelineRunAction.java @@ -21,6 +21,7 @@ import io.cdap.e2e.utils.ConstantsUtil; import io.cdap.e2e.utils.ElementHelper; import io.cdap.e2e.utils.PageHelper; +import io.cdap.e2e.utils.RetryUtils; import io.cdap.e2e.utils.SeleniumDriver; import io.cdap.e2e.utils.SeleniumHelper; import io.cdap.e2e.utils.WaitHelper; @@ -85,6 +86,15 @@ public static Boolean isRunning() { return validatePipelineExpectedStatus(CdfPipelineRunLocators.runningStatus); } + /** + * Check if the pipeline is in Starting Status + * + * @return Boolean + */ + public static Boolean isStarting() { + return validatePipelineExpectedStatus(CdfPipelineRunLocators.startingStatus); + } + /** * Check if the pipeline is in Provisioning Status * @@ -107,14 +117,18 @@ public static void waitForPipelineToTransitionToStatus(String pipelineStatus, lo /** * Wait till the Pipeline's status changes (from Running) to either Succeeded, Failed or Stopped within the - * Timeout: {@link ConstantsUtil#PIPELINE_RUN_TIMEOUT_SECONDS} + * Timeout: {@link ConstantsUtil#IMPLICIT_TIMEOUT_SECONDS} */ - public static void waitTillPipelineRunCompletes() { - SeleniumDriver.getWaitDriver(ConstantsUtil.PIPELINE_RUN_TIMEOUT_SECONDS).until(ExpectedConditions.or( - ExpectedConditions.visibilityOf(CdfPipelineRunLocators.succeededStatus), - ExpectedConditions.visibilityOf(CdfPipelineRunLocators.failedStatus), - ExpectedConditions.visibilityOf(CdfPipelineRunLocators.stoppedStatus) - )); + public static void waitTillPipelineRunCompletes() throws InterruptedException { + // Adding a page refresh in case tests are running on CDF to update the pipeline status. + RetryUtils.retry(ConstantsUtil.PIPELINE_REFRESH_TIMEOUT_SECONDS, ConstantsUtil.PIPELINE_RUN_TIMEOUT_SECONDS, + 10, () -> { + PageHelper.refreshCurrentPage(); + return !(isRunning()); + } + ); + + waitTillPipelineRunCompletes(ConstantsUtil.IMPLICIT_TIMEOUT_SECONDS); } /** diff --git a/src/main/java/io/cdap/e2e/pages/actions/CdfSignInActions.java b/src/main/java/io/cdap/e2e/pages/actions/CdfSignInActions.java new file mode 100644 index 000000000..99abab6b0 --- /dev/null +++ b/src/main/java/io/cdap/e2e/pages/actions/CdfSignInActions.java @@ -0,0 +1,58 @@ +/* + * Copyright © 2023 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.e2e.pages.actions; + +import io.cdap.e2e.pages.locators.CdfSignInLocator; +import io.cdap.e2e.utils.ConstantsUtil; +import io.cdap.e2e.utils.ElementHelper; +import io.cdap.e2e.utils.SeleniumHelper; +import io.cdap.e2e.utils.WaitHelper; + +import java.io.IOException; + + + +/** + * Represents CdfSignInActions + */ +public class CdfSignInActions { + private static CdfSignInLocator cdfSignInLocator; + static { + cdfSignInLocator = SeleniumHelper.getPropertiesLocators(CdfSignInLocator.class); + } + + public static void login() throws IOException, InterruptedException { + ElementHelper.sendKeys(cdfSignInLocator.cdfUsername, SeleniumHelper.readParameters(ConstantsUtil.CDFUSERNAME)); + ElementHelper.clickOnElement(cdfSignInLocator.nextButton); + ElementHelper.sendKeys(cdfSignInLocator.cdfPassword, SeleniumHelper.readParameters(ConstantsUtil.CDFPASSWORD)); + ElementHelper.clickOnElement(cdfSignInLocator.nextButton); + + ElementHelper.clickIfDisplayed(cdfSignInLocator.selectTestAccount(ConstantsUtil.CDF_TEST_ACCOUNT_NAME), + ConstantsUtil.SMALL_TIMEOUT_SECONDS, cdfSignInLocator.clickOnContinueButton()); + + ElementHelper.clickIfDisplayed(cdfSignInLocator.clickOnContinueButton(), ConstantsUtil.SMALL_TIMEOUT_SECONDS, + cdfSignInLocator.locatePluginNameInList(ConstantsUtil.FIRST_PLUGIN_IN_LIST, "Source")); + + ElementHelper.clickIfDisplayed(cdfSignInLocator.clickOnAllowButton(), ConstantsUtil.SMALL_TIMEOUT_SECONDS, + cdfSignInLocator.locatePluginNameInList(ConstantsUtil.FIRST_PLUGIN_IN_LIST, "Source")); + + } + + public static boolean isUserLoggedInCDF() { + return !WaitHelper.waitForElementToBeOptionallyDisplayed( + CdfSignInLocator.locatorOfEmailTextBox(), ConstantsUtil.SMALL_TIMEOUT_SECONDS); + } +} diff --git a/src/main/java/io/cdap/e2e/pages/locators/CdfSignInLocator.java b/src/main/java/io/cdap/e2e/pages/locators/CdfSignInLocator.java new file mode 100644 index 000000000..4782ac307 --- /dev/null +++ b/src/main/java/io/cdap/e2e/pages/locators/CdfSignInLocator.java @@ -0,0 +1,58 @@ +/* + * Copyright © 2023 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.e2e.pages.locators; + +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.FindBy; +import org.openqa.selenium.support.How; + +/** + * Represents CdfSignInLocators + */ +public class CdfSignInLocator { + + @FindBy(how = How.XPATH, using = "//input[@name='identifier']") + public WebElement cdfUsername; + + @FindBy(how = How.XPATH, using = "//input[@name='Passwd']") + public WebElement cdfPassword; + + @FindBy(how = How.XPATH, using = "//*[contains(text(),'Next')]//parent::button") + public WebElement nextButton; + + public static By locatorOfEmailTextBox() { + return By.xpath("//input[@name='identifier']"); + } + + public By selectTestAccount(String testAccountName) { + return By.xpath("//*[contains(text(),'" + testAccountName + "')]"); + } + + public By clickOnAllowButton() { + return By.xpath("//button[contains(text(),'Allow')]"); + } + + public By clickOnContinueButton() { + return By.xpath("//span[contains(text(),'Continue')]"); + } + + public static By locatePluginNameInList(String pluginName, String pluginGroupName) { + return By.xpath("//div[@data-cy='plugin-" + pluginGroupName + "-group']" + + "//div[contains(@class, 'PluginNameContainer')][normalize-space(text()) = '" + pluginName + "' " + + "or translate(normalize-space(text()),' ','') = '" + pluginName + "']"); + } +} diff --git a/src/main/java/io/cdap/e2e/utils/CdfHelper.java b/src/main/java/io/cdap/e2e/utils/CdfHelper.java index 6e427c717..bbc1c99ff 100644 --- a/src/main/java/io/cdap/e2e/utils/CdfHelper.java +++ b/src/main/java/io/cdap/e2e/utils/CdfHelper.java @@ -19,6 +19,7 @@ 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.CdfSignInActions; import io.cdap.e2e.pages.actions.CdfStudioActions; import io.cdap.e2e.pages.actions.HdfSignInActions; import io.cdap.e2e.pages.locators.CdfGCSLocators; @@ -55,6 +56,13 @@ default void openCdf() throws IOException, InterruptedException { WaitHelper.waitForPageToLoad(); } + if (Boolean.parseBoolean(SeleniumHelper.readParameters(ConstantsUtil.TESTONCDF)) && !CdfSignInActions. + isUserLoggedInCDF()) { + CdfSignInActions.login(); + PageHelper.acceptAlertIfPresent(); + WaitHelper.waitForPageToLoad(); + } + /* TODO: Remove below wait once https://cdap.atlassian.net/browse/CDAP-18862 is fixed */ WaitHelper.waitForElementToBeDisplayed( CdfStudioLocators.locatePluginNameInList(ConstantsUtil.FIRST_PLUGIN_IN_LIST, "Source")); diff --git a/src/main/java/io/cdap/e2e/utils/ConstantsUtil.java b/src/main/java/io/cdap/e2e/utils/ConstantsUtil.java index f7c830e52..2f512497b 100644 --- a/src/main/java/io/cdap/e2e/utils/ConstantsUtil.java +++ b/src/main/java/io/cdap/e2e/utils/ConstantsUtil.java @@ -34,6 +34,10 @@ public class ConstantsUtil { public static final String GPAZWRD = "gPassword"; public static final String HDFUSERNAME = "hdfUsername"; public static final String HDFPAZWRD = "hdfPassword"; + public static final String CDFUSERNAME = "cdfUsername"; + public static final String CDFPASSWORD = "cdfPassword"; + public static final String TESTONCDF = "testOnCdf"; + public static final String CDF_TEST_ACCOUNT_NAME = "CloudDataFution Automation"; public static final String CDFURL = "cdfurl"; public static final String WRANGLER_CONNECTIONS_URL = "cdfConnectionsUrl"; public static final String REPLICATION_URL = "replicationUrl"; @@ -81,6 +85,10 @@ public class ConstantsUtil { * SMALL_TIMEOUT_SECONDS: To be used as a small static wait (only if needed) */ public static final int SMALL_TIMEOUT_SECONDS = 5; + /** + * MEDIUM_TIMEOUT_SECONDS: To be used as a medium static wait (only if needed) + */ + public static final int MEDIUM_TIMEOUT_SECONDS = 10; /** * PIPELINE_DEPLOY_TIMEOUT_SECONDS: To be used as a timeout for deploying the pipeline */ @@ -94,4 +102,6 @@ public class ConstantsUtil { * PIPELINE_RUN_TIMEOUT_SECONDS: To be used as a timeout for Pipeline Runs */ public static final int PIPELINE_RUN_TIMEOUT_SECONDS = 900; + + public static final int PIPELINE_REFRESH_TIMEOUT_SECONDS = 120; } diff --git a/src/main/java/io/cdap/e2e/utils/ElementHelper.java b/src/main/java/io/cdap/e2e/utils/ElementHelper.java index 58f435852..57693c44c 100644 --- a/src/main/java/io/cdap/e2e/utils/ElementHelper.java +++ b/src/main/java/io/cdap/e2e/utils/ElementHelper.java @@ -16,6 +16,7 @@ package io.cdap.e2e.utils; +import io.cdap.e2e.pages.actions.CdfPipelineRunAction; import org.junit.Assert; import org.openqa.selenium.By; import org.openqa.selenium.JavascriptExecutor; @@ -121,6 +122,31 @@ public static void clickIfDisplayed(By locator) { clickIfDisplayed(locator, ConstantsUtil.SMALL_TIMEOUT_SECONDS); } + /** + * Click on the WebElement if it was displayed within a small timeout: {@link ConstantsUtil#SMALL_TIMEOUT_SECONDS} + * + * If the next element which we are waiting for to be displayed is not displayed yet that means we were not able to + * click on the desired element, so we will retry to click on the element we wanted to click on. + * + * @param locatorToClick Locator of the WebElement we want to click on. + * @param timeOutInSeconds small timeout to wait before clicking. + * @param locatorToWaitFor Locator of the WebElement we want to be displayed next. + */ + public static void clickIfDisplayed(By locatorToClick, long timeOutInSeconds, By locatorToWaitFor) + throws InterruptedException { + clickIfDisplayed(locatorToClick, timeOutInSeconds); + + // If the next webElement is not displayed we will click on the desired element again. + if (!isElementDisplayed(locatorToWaitFor, timeOutInSeconds)) { + RetryUtils.retry(ConstantsUtil.SMALL_TIMEOUT_SECONDS, ConstantsUtil.MEDIUM_TIMEOUT_SECONDS, 2, + () -> { + logger.info("Retry : Click on " + locatorToClick); + clickIfDisplayed(locatorToClick); + return isElementDisplayed(locatorToWaitFor, timeOutInSeconds); + }); + } + } + /** * Send keys to a WebElement * diff --git a/src/main/java/io/cdap/e2e/utils/RetryUtils.java b/src/main/java/io/cdap/e2e/utils/RetryUtils.java new file mode 100644 index 000000000..65cdf770e --- /dev/null +++ b/src/main/java/io/cdap/e2e/utils/RetryUtils.java @@ -0,0 +1,52 @@ +/* + * Copyright © 2023 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.e2e.utils; + +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; + +/** + * Retry Util + */ +public class RetryUtils { + + /** + * Implements a retry functionality for an action if required. + * + * @param retryDelay Delay in seconds after which each retry should be performed. + * @param maxRetryDelay Max Delay in seconds after which retry logic should stop. + * @param maxRetryCount Max Retry count after which retry logic should stop. + * @param retryOperation Operation which needs to be performed while retrying. + * + */ + public static void retry(int retryDelay, int maxRetryDelay, int maxRetryCount, Supplier retryOperation) + throws InterruptedException { + int currentRetryDelay = 0; + TimeUnit wait = TimeUnit.SECONDS; + while (maxRetryCount > 0 && currentRetryDelay <= maxRetryDelay) { + if (retryOperation.get()) { + // If Operation succeeded, exit the retry loop. + return; + } + + currentRetryDelay += retryDelay; + maxRetryCount--; + + wait.sleep(retryDelay); + } + } +} diff --git a/src/main/java/stepsdesign/PipelineSteps.java b/src/main/java/stepsdesign/PipelineSteps.java index 61dea8b03..a16f96645 100644 --- a/src/main/java/stepsdesign/PipelineSteps.java +++ b/src/main/java/stepsdesign/PipelineSteps.java @@ -387,7 +387,7 @@ public void waitForPipelineToBeInStatus(String pipelineStatus, long timeoutInSec } @Then("Wait till pipeline is in running state") - public void waitTillPipelineIsInRunningState() { + public void waitTillPipelineIsInRunningState() throws Exception { CdfPipelineRunAction.waitTillPipelineRunCompletes(); } diff --git a/src/main/resources/connectionParameters.properties b/src/main/resources/connectionParameters.properties index c96ebcd5c..d70a475a3 100644 --- a/src/main/resources/connectionParameters.properties +++ b/src/main/resources/connectionParameters.properties @@ -11,6 +11,10 @@ testOnHdf=false hdfUsername=cdap hdfPassword=cdap123 +testOnCdf=false +cdfUsername=dummy +cdfPassword=dummy + screenshotForAllSteps=false # properties to be removed-start