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

com.codacy.scoobydoo.utils.WebUtils Maven / Gradle / Ivy

package com.codacy.scoobydoo.utils;

import com.codacy.scoobydoo.Constant.Key;
import com.codacy.scoobydoo.LoggingHelper;
import com.codacy.scoobydoo.configuration.Configuration;
import io.restassured.specification.RequestSpecification;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.logging.LogEntries;
import org.openqa.selenium.logging.LogEntry;
import org.openqa.selenium.logging.LogType;
import org.openqa.selenium.remote.RemoteExecuteMethod;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.remote.html5.RemoteWebStorage;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.asserts.SoftAssert;

import java.time.Duration;
import java.util.Arrays;
import java.util.Collection;
import java.util.Optional;
import java.util.function.Function;

import static io.restassured.RestAssured.given;

// Utils that are used by web and e2e tests but that don't interact with web pages directly.
//
// For methods that don't depend on neither configuration and driver, check if they could be moved to Utils instead.
// For methods that depend on locators and such, consider moving them to WebFragment or WebElementWrapper.
public class WebUtils {

    protected final Configuration config;
    protected final RemoteWebDriver driver;

    public WebUtils(RemoteWebDriver driver, Configuration configuration) {
        config = configuration;
        this.driver = driver;
    }

    public void assertJSBrowserLogs() {

        // flushes the browser logs, so the next time they're retrieved they'll be only related to the refreshed page.
        driver.manage().logs().get(LogType.BROWSER);

        refreshBrowser();
        waitForPageToLoad();
        LogEntries logs = driver.manage().logs().get(LogType.BROWSER);
        // Workaround, since sometimes the waitForPageToLoad can be called too soon.
        // We can't use a "wait" because it would throw a IllegalMonitorStateException.
        if(logs.getAll().isEmpty()) {
            waitForPageToLoad();
            logs = driver.manage().logs().get(LogType.BROWSER);
        }
        SoftAssert softAssertions = new SoftAssert();

        for (LogEntry logEntry : logs) {
            if (logEntry.getLevel().getName().contains("SEVERE")) {
                softAssertions.fail("Error Message in Console: " + logEntry.getMessage());
            } else if (logEntry.getLevel().getName().contains("WARNING")) {
                LoggingHelper.warn("Warning Message in Console: " + logEntry.getMessage());
            } else {
                LoggingHelper.info("Information Message in Console: " + logEntry.getMessage());
            }
        }
        softAssertions.assertAll();
    }

    public void deleteAllCookies() {
        LoggingHelper.info("Delete all cookies.");
        waitForFunction(x -> {
                    driver.manage().deleteAllCookies();
                    return driver.manage().getCookies().isEmpty();
                },
                config.getTimeout().DEFAULT_TIMEOUT,
                config.getTimeout().DEFAULT_POLLING);
    }

    public void deleteAllCookiesAndCache() {
        deleteAllCookies();
        deleteCache();
    }

    public void deleteCache() {
        if(!driver.getCurrentUrl().equals("data:,")) {
            LoggingHelper.info("Deleting cache.");
            RemoteExecuteMethod remoteExecuteMethod = new RemoteExecuteMethod(driver);
            RemoteWebStorage storage = new RemoteWebStorage(remoteExecuteMethod);
            storage.getSessionStorage().clear();
        }
    }

    public boolean doesCurrentUrlContains(String url) {
        return getCurrentUrl().contains(url);
    }

    // Use this to run test steps that can fail with an open popup.
    // If one of the steps fails, this will refresh the browser, hence closing the popup and falling back to a retryable state.
    public void executeCodeThatOpensPopUps(Runnable runnable) {
        executeCodeThatOpensPopUps(runnable, Optional.empty());
    }

    // Use this to run test steps that can fail with an open popup.
    // If one of the steps fails, this will run the resetBrowserInstruction, hence closing the popup and falling back to a retryable state.
    public void executeCodeThatOpensPopUps(Runnable runnable, Runnable resetBrowserInstruction) {
        executeCodeThatOpensPopUps(runnable, Optional.of(resetBrowserInstruction));
    }

    public String getCurrentUrl() {
        return driver.getCurrentUrl();
    }

    public boolean isCurrentUrl(String url) {
        return getCurrentUrl().equals(url);
    }

    // Can be used as a workaround to sometimes the toaster not appearing on screen.
    // For some reason, user interaction (pressing keys, moving the mouse...) seems to "unblock" the toaster.
    //
    // Maybe this method should move to a class 'WebActions' in the future if more actions are created.
    public void jiggleMouse() {
        final int offset = 25;
        new Actions(driver)
                .moveByOffset(offset, offset)
                .pause(Duration.ofMillis(500))
                .moveByOffset(Math.negateExact(offset), Math.negateExact(offset))
                .perform();
    }

    // Tries to keep the current webdriver session alive, to avoid losing it due to long waits, waiting for test methods to end.
    public void keepSessionAlive() {
        LoggingHelper.info("Try to keep the session alive.");
        driver.getCurrentUrl(); // just ping the browser and ignore the response.
    }

    public void navigateBack() {
        LoggingHelper.info("Navigate to the previous page.");
        driver.navigate().back();
    }

    public void navigateTo(String url) {
        LoggingHelper.info("Open page [" + url + "].");
        driver.navigate().to(url);
    }

    public void refreshBrowser() {
        LoggingHelper.info("Refresh the browser.");
        driver.navigate().refresh();
    }

    public int requestLinkHeadStatusCode(String urlLink) {

        RequestSpecification requestSpecification = given();

        // only codacy domain URLs should have the cookie rate limit.
        if(urlLink.contains(".codacy.")) {
            String cookieRateLimit = config.getProperty("cookieRateLimit");

            if (cookieRateLimit != null) {
                requestSpecification.header("cookie", cookieRateLimit);
            }
        }

        return requestSpecification
                .head(urlLink)
                .statusCode();
    }

    public void runConfigMethodWithRetries(Runnable runnable) {
        int maxRetries = Integer.parseInt(config.getData(Key.MAX_RETRIES_FOR_SETUP_AND_TEARDOWN_METHODS));
        Utils.runMethodWithRetries(runnable, maxRetries);
    }

    public void scrollIntoView(By locator) {
        WebElement targetElement = driver.findElement(locator);
        // The false value on scrollIntoView means that the bottom of the element will be aligned to the bottom of the
        // visible area of the scrollable ancestor. True would mean top instead of bottom.
        String script = "arguments[0].scrollIntoView(false);";
        driver.executeScript(script, targetElement);
    }

    public void scrollToBottom() {
        waitForPageToLoad();
        ((JavascriptExecutor) driver).executeScript("window.scrollTo(0, document.body.scrollHeight)");
    }

    public void scrollToTop() {
        ((JavascriptExecutor) driver).executeScript("window.scrollTo(0, 0);");
    }

    public  void waitForCondition(ExpectedCondition condition) {
        waitForCondition(config.getTimeout().DEFAULT_TIMEOUT, condition);
    }

    public  void waitForCondition(Duration timeout, ExpectedCondition condition) {
        waitForCondition(timeout, config.getTimeout().LONG_POLLING, condition);
    }

    public  void waitForCondition(Duration timeout, Duration polling, ExpectedCondition condition) {
        LoggingHelper.info("Wait for condition [" + condition.toString() + "] with a timeout of [" + timeout.toSeconds() + "] seconds.");
        new WebDriverWait(driver, timeout)
                .pollingEvery(polling)
                .ignoreAll(Arrays.asList(StaleElementReferenceException.class, NoSuchElementException.class, AssertionError.class))
                .until(condition);
    }

    public void waitForFunction(Function function, Duration timeout, Duration polling) {
        new FluentWait<>(driver)
                .withTimeout(timeout)
                .pollingEvery(polling)
                .until(function);
    }

    public void waitForFunction(Function function, Duration timeout, Duration polling,  Collection> ignore) {
        new FluentWait<>(driver)
                .withTimeout(timeout)
                .pollingEvery(polling)
                .ignoreAll(ignore)
                .until(function);
    }

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

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



    private void executeCodeThatOpensPopUps(Runnable runnable, Optional resetBrowserInstruction) {
        try {
            runnable.run();
        } catch (Exception e) {
            LoggingHelper.error("Going to try to close popup since a test step, that could cause a popup to be stuck, failed.", e);
            // tries to reset the browser to a retryable state, closing the popup.
            if(resetBrowserInstruction.isPresent()) {
                resetBrowserInstruction.get().run();
            } else {
                refreshBrowser();
            }
            throw e;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy