All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.codacy.scoobydoo.web.WebFragment Maven / Gradle / Ivy

There is a newer version: 3.30.0
Show newest version
package com.codacy.scoobydoo.web;

import com.codacy.scoobydoo.LoggingHelper;
import com.codacy.scoobydoo.configuration.Configuration;
import com.codacy.scoobydoo.utils.Utils;
import com.codacy.scoobydoo.utils.WebUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.Keys;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Action;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.FluentWait;

import java.time.Duration;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;

public abstract class WebFragment {

    public Configuration config;
    public RemoteWebDriver driver;
    public ScreenShotHelper screenShotHelper;
    public WebUtils webUtils;

    public WebFragment(RemoteWebDriver driver, Configuration configuration) {
        Objects.requireNonNull(driver, "Driver cannot be null. Please ensure that the 'type' value is 'end' or 'web' on the test suite file you are running.");
        this.driver = driver;
        config = configuration;
        screenShotHelper = new ScreenShotHelper(driver, configuration);
        webUtils = new WebUtils(driver, configuration);
    }

    public void assertElementDoesNotExist(By elementLocator) {
        boolean elementExists;
        try {
            driver.findElement(elementLocator);
            elementExists = true;
        } catch(NoSuchElementException ignored) {
            elementExists = false;
        }
        assertThat("Element with locator [" + elementLocator + "] exists but it shouldn't.", elementExists, is(false));
    }

    // use getElement(elementLocator) (.assertIsDisplayed()) .assertHasExactText(expectedText) instead.
    @Deprecated
    public void assertElementHasVisibleText(By elementLocator, String expectedText) {
        assertElementHasVisibleText(driver.findElement(elementLocator), expectedText);
    }

    // use getElement(elementLocator) (.assertIsDisplayed()) .assertHasExactText(expectedText) instead.
    @Deprecated
    public void assertElementHasVisibleText(WebElement targetElement, String expectedText) {
        assertTrue(targetElement.isDisplayed());
        assertEquals(targetElement.getText(), expectedText);
    }

    // Use this when the equivalent assertElementHasVisibleText method doesn't work.
    public void assertElementHasVisibleTextValue(By elementLocator, String expectedText) {
        assertElementHasVisibleTextValue(driver.findElement(elementLocator), expectedText);
    }

    // Use this when the equivalent assertElementHasVisibleText method doesn't work.
    public void assertElementHasVisibleTextValue(WebElement targetElement, String expectedText) {
        assertTrue(targetElement.isDisplayed());
        assertEquals(targetElement.getAttribute("value"), expectedText);
    }

    // Use getElement(elementLocator) (.assertIsDisplayed()) .assertTextMatchesRegEx(expectedTextRegEx) instead.
    @Deprecated
    public void assertElementHasVisibleTextWithRegEx(By elementLocator, String expectedTextRegEx) {
        assertElementHasVisibleTextWithRegEx(driver.findElement(elementLocator), expectedTextRegEx);
    }

    // Use getElement(elementLocator) (.assertIsDisplayed()) .assertTextMatchesRegEx(expectedTextRegEx) instead.
    @Deprecated
    public void assertElementHasVisibleTextWithRegEx(WebElement targetElement, String expectedTextRegEx) {
        assertTrue(targetElement.isDisplayed());
        final String targetElementText = targetElement.getText();
        assertTrue(targetElementText.matches(expectedTextRegEx),
                "Target element text [" + targetElementText + "] does not matches expected RegEx [" + expectedTextRegEx + "].");
    }

    // use getElement(locator).assertIsDisplayed() instead.
    @Deprecated
    public void assertElementIsDisplayed(By locator) {
        assertTrue(isElementDisplayed(locator), "Element with locator [" + locator + "] should be displayed but it isn't.");
    }

    // use assertElementDoesNotExist(locator) or getElement(locator).assertIsNotDisplayed() instead.
    @Deprecated
    public void assertElementIsNotDisplayed(By locator) {
        assertFalse(isElementDisplayed(locator), "Element with locator [" + locator + "] should not be displayed but it is.");
    }

    public boolean doesElementExists(By locator) {
        return driver.findElements(locator).size() > 0;
    }

    // Use this only when default method element.clear() doesn't work.
    @Deprecated
    public void forceClear(WebElementWrapper element) {
        element.sendKeys(Keys.chord(Keys.CONTROL, "a", Keys.DELETE));
    }

    public WebDriver getDriver() {
        return driver;
    }

    public WebElementWrapper getElement(By locator) {
        return new WebElementWrapper(driver, config, locator);
    }

    public WebElementWrapper getElement(By locator, Duration timeout, Duration polling) {
        return new WebElementWrapper(driver, config, locator, timeout, polling);
    }

    // use getElement(by).click() instead.
    @Deprecated
    public WebElementWrapper getElementWhenClickable(By by) {
        return this.getElementWhenClickable(by, config.getTimeout().FIND_ELEMENT_WAIT_TIMEOUT, config.getTimeout().DEFAULT_POLLING);
    }

    // use getElement(by).click() instead.
    @Deprecated
    public WebElementWrapper getElementWhenClickable(By by, Duration timeout, Duration polling) {

        String infoMessage = Utils.getWaitLogMessage(by, Utils.ElementProperty.CLICKABLE, timeout, polling);
        String errorMessage = Utils.getWaitErrorLogMessage(by, Utils.ElementProperty.CLICKABLE, timeout);

        waitForElementWithCondition(timeout, polling, ExpectedConditions.elementToBeClickable(by), infoMessage, errorMessage);
        return new WebElementWrapper(driver, config, by);
    }

    // this should be private.
    @Deprecated
    public WebElementWrapper getElementWhenVisible(By locator) {
        getElementWhenVisibleWithConfigurableTimeout(locator, config.getTimeout().FIND_ELEMENT_WAIT_TIMEOUT, config.getTimeout().DEFAULT_POLLING);
        return new WebElementWrapper(driver, config, locator);
    }

    // this should be private.
    @Deprecated
    public WebElementWrapper getElementWhenVisibleWithConfigurableTimeout(By locator, Duration timeout, Duration polling) {

        String infoMessage = Utils.getWaitLogMessage(locator, Utils.ElementProperty.VISIBLE, timeout, polling);
        String errorMessage = Utils.getWaitErrorLogMessage(locator, Utils.ElementProperty.VISIBLE, timeout);

        waitForElementWithCondition(timeout, polling, ExpectedConditions.visibilityOfElementLocated(locator), infoMessage, errorMessage);
        return new WebElementWrapper(driver, config, locator);
    }

    public List getElements(By locator) {
        List elements = driver.findElements(locator);
        if(elements.isEmpty()) {
            waitForElementToBeVisible(locator);
            elements = driver.findElements(locator);
        }
        return elements;
    }

    public List getElementsByType(String elementType) {
        return this.driver.findElements(By.tagName(elementType));
    }

    public List getVisibleElementsByType(String elementType) {
        return getElementsByType(elementType)
                .stream()
                .filter(WebElement::isDisplayed)
                .toList();
    }

    public void hoverMouseOverElement(By locator) {

        WebElement targetElement = getElementWhenVisible(locator).getWebElement();

        Action action = new Actions(getDriver())
                .moveToElement(targetElement)
                .build();

        action.perform(); // for some reason, this had to be broken in 2 steps, otherwise no action would be performed.
    }

    public boolean isCheckboxChecked(By checkboxLocator) {
        return getElement(checkboxLocator).getAttribute("checked") != null;
    }

    public boolean isElementDisplayed(By locator) {
        try {
            return driver.findElement(locator).isDisplayed();
        } catch(NoSuchElementException ignored) {
            return false;
        }
    }

    public boolean retryStaleElement(By by, Consumer consumer) throws InterruptedException {
        int attempts = 0;
        while (attempts < 20) {
            try {
                Thread.sleep(500);
                WebElement a = getDriver().findElement(by);
                consumer.accept(a);
                return true;
            } catch (NoSuchElementException | TimeoutException | StaleElementReferenceException ignored) {
                //Swallow
            }
            attempts++;
        }
        return false;
    }

    public boolean retryStaleElementClick(By by) {
        try {
            return retryStaleElement(by, WebElement::click);
        } catch (InterruptedException e) {
            e.printStackTrace();
            return false;
        }
    }

    public boolean retryStaleElementDisplay(By by) {
        try {
            return retryStaleElement(by, WebElement::isDisplayed);
        } catch (InterruptedException e) {
            e.printStackTrace();
            return false;
        }
    }

    public void scrollDown() {
        JavascriptExecutor js = (JavascriptExecutor) getDriver();
        js.executeScript("window.scrollBy(0,1000)");
    }

    public WebElementWrapper waitForElementToBeVisible(By locator) {
        return waitForElementToBeVisible(locator, config.getTimeout().FIND_ELEMENT_WAIT_TIMEOUT);
    }

    public WebElementWrapper waitForElementToBeVisible(By locator, Duration timeout) {
        webUtils.waitForCondition(timeout, ExpectedConditions.visibilityOfElementLocated(locator));
        return getElement(locator);
    }

    public void waitForElementWithCondition(Duration timeout, Duration polling, ExpectedCondition expectedCondition, String infoMessage, String errorMessage) {
        try {
            screenShotHelper.takesScreenshotOnAction(infoMessage);
            new FluentWait<>(driver)
                .withTimeout(timeout)
                .pollingEvery(polling)
                .ignoreAll(Arrays.asList(StaleElementReferenceException.class, NoSuchElementException.class))
                .until(expectedCondition);
        } catch (Exception e) {
            screenShotHelper.takesScreenshotOnError(errorMessage, e);
            throw e;
        }
    }

    // use waitForPageToLoad() instead.
    @Deprecated
    public void waitPageToLoad() {
        waitForPageToLoad();
    }

    // use waitForPageToLoad(timeout) instead.
    @Deprecated
    public void waitPageToLoad(Duration timeout) {
        waitForPageToLoad(timeout);
    }

    public void waitForPageToLoad() {
        waitForPageToLoad(config.getTimeout().PAGE_LOAD_TIMEOUT, config.getTimeout().LONG_POLLING);
    }

    public void waitForPageToLoad(Duration timeout) {
        waitForPageToLoad(timeout, config.getTimeout().LONG_POLLING);
    }

    public void waitForPageToLoad(Duration timeout, Duration polling) {
        webUtils.waitForFunction(
                webDriver -> ((JavascriptExecutor) webDriver).executeScript("return document.readyState").equals("complete"),
                timeout, polling);
        LoggingHelper.info("Page is loaded.");
    }

    public void waitForTextToBe(By locator, String targetText) {
        waitForTextToBe(locator, targetText, config.getTimeout().FIND_ELEMENT_WAIT_TIMEOUT);
    }

    // Unfortunately this can't be moved to WebElementWrapper since Selenium does not provide a condition using element instead of locator.
    public void waitForTextToBe(By locator, String targetText, Duration timeout) {
        webUtils.waitForCondition(timeout, ExpectedConditions.textToBe(locator, targetText));
    }

    public void waitForTextToContain(By locator, String targetSubstring) {
        waitForTextToContain(locator, targetSubstring, config.getTimeout().FIND_ELEMENT_WAIT_TIMEOUT);
    }

    public void waitForTextToContain(By locator, String targetSubstring, Duration timeout) {
        webUtils.waitForCondition(timeout, ExpectedConditions.textToBePresentInElementLocated(locator, targetSubstring));
    }

    public void waitUntilElementDisappears(By selector) {
        waitUntilElementDisappears(selector, config.getTimeout().LONG_WAIT_TIMEOUT, config.getTimeout().LONG_POLLING);
    }

    public void waitUntilElementDisappears(By selector, Duration timeout, Duration polling) {
        try {
            screenShotHelper.takesScreenshotOnAction("Wait for element [" + selector + "] to disappear.");
            webUtils.waitForFunction(x -> getDriver().findElements(selector).size() == 0, timeout, polling);
        } catch (Exception e) {
            screenShotHelper.takesScreenshotOnError("Element [" + selector + "] did not disappear.", e);
            throw e;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy