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

com.codacy.scoobydoo.BaseTest Maven / Gradle / Ivy

package com.codacy.scoobydoo;

import com.codacy.scoobydoo.Constant.Attribute;
import com.codacy.scoobydoo.Constant.Browser;
import com.codacy.scoobydoo.Constant.Status;
import com.codacy.scoobydoo.Constant.TestType;
import com.codacy.scoobydoo.configuration.Configuration;
import com.codacy.scoobydoo.web.ScreenShotHelper;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.PageLoadStrategy;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.HasDevTools;
import org.openqa.selenium.devtools.v109.network.Network;
import org.openqa.selenium.remote.Augmenter;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.ITestContext;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;

import java.net.URL;
import java.util.Arrays;

public abstract class BaseTest {

    protected Configuration config;
    protected RemoteWebDriver driver;

    // Or either the driver is always called directly or this get method is always used instead. Using both doesn't make sense.
    @Deprecated
    public RemoteWebDriver getDriver() {
        return driver;
    }

    @BeforeSuite(alwaysRun = true)
    public void setupTestSuite() {
        // necessary for the driver Augmenter to work.
        System.setProperty("webdriver.http.factory", "jdk-http-client");
    }

    @BeforeTest(alwaysRun = true)
    @Parameters({"type", "environment", "browser", "aws"})
    public void configFactory(ITestContext testContext,
                              String type,
                              String environment,
                              @Optional String browser,
                              @Optional(Status.ENABLED) String aws) {

        switch (type.toLowerCase()) {
            case TestType.API -> setConfiguration(environment, aws);
            case TestType.END, TestType.WEB -> {
                setConfiguration(environment, aws);
                setDriver(browser);
                setTestContext(testContext);
            }
            default -> throw logAndGetIllegalArgumentException("type", type);
        }
    }

    @AfterTest(alwaysRun = true)
    public void cleanup() {
        try {
            if (driver != null) {
                LoggingHelper.info("Deleting all cookies and quitting driver.");
                driver.manage().deleteAllCookies();
                driver.quit();
            }
        } catch (Exception e) {
            LoggingHelper.error("Error doing the test cleanup.", e);
        } finally {
            driver = null;
        }
    }



    private void blockChatPopups() {
        DevTools devTools = ((HasDevTools) new Augmenter().augment(driver)).getDevTools();
        // DevTools logging is too verbose, so it was disabled.
        // Do NOT import java.util.logging, since otherwise it will break javadoc generation for Java >8 due to
        // conflicts with jackson-annotations, for some reason.
        java.util.logging.Logger.getLogger("org.openqa.selenium.devtools").setLevel(java.util.logging.Level.OFF);
        devTools.createSession();
        java.util.Optional empty = java.util.Optional.empty();
        devTools.send(Network.enable(empty, empty, empty));
        devTools.send(Network.setBlockedURLs(Arrays.asList(
                "https://api-iam.intercom.io/*",
                "https://codacy.zendesk.com/*",
                "https://api.segment.io/*",
                "https://q.clarity.ms/*",
                "https://surveystats.hotjar.io/*",
                "https://script.hotjar.com/*"
        )));
    }

    private IllegalArgumentException logAndGetIllegalArgumentException(String variableName, String variableValue) {
        final String errorMessage = String.format("The %s [%s] is not known.", variableName, variableValue);
        IllegalArgumentException exception = new IllegalArgumentException(errorMessage);
        LoggingHelper.error(errorMessage, exception);
        return exception;
    }

    private void setConfiguration(String environment, String aws) {

        LoggingHelper.info("Setting environment configuration for [" + environment + "].");

        try {
            config = new Configuration(environment, aws);

        } catch (Exception e) {
            LoggingHelper.error("Failed while setting environment configuration.", e);
            if(driver != null) {
                driver.quit();
            }
            throw e;
        }
    }

    private void setDriver(String browser) {

        int retries = 0;
        String hubUrl = config.getData("HUB_URL");
        boolean isHeadless = config.getProperty("headlessMode").equals(Constant.Status.ENABLED);

        if (Browser.CHROME.equalsIgnoreCase(browser)) {

            ChromeOptions options = new ChromeOptions();
            options.addArguments("--disable-dev-shm-usage"); // overcome limited resource problems
            options.addArguments("--disable-blink-features=AutomationControlled");
            options.addArguments("--start-maximized");
            // if some external sites (apart from Google and GitLab) start to block our calls, review this argument.
            options.addArguments("--enable-automation");
            options.setPageLoadStrategy(PageLoadStrategy.EAGER);
            options.setScriptTimeout(config.getTimeout().SCRIPT_TIMEOUT);

            if(isHeadless) {
                LoggingHelper.info("Activating headless mode for Chrome.");
                options.addArguments("--headless=new");
            }

            while (retries <= 5) {
                try {

                    driver = new RemoteWebDriver(new URL(hubUrl), options, false);

                    if(isHeadless) {
                        // This prevents cropped screenshots, since for some reason the headless option breaks the
                        // default window size. Note that the screen dimensions are, for now, hardcoded to Selenium
                        // Grid's default resolution.
                        Dimension seleniumGridDefaultResolution = new Dimension(1300, 1000);
                        driver.manage().window().setSize(seleniumGridDefaultResolution);
                    }

                    blockChatPopups();

                    break;
                } catch (Exception e) {
                    LoggingHelper.error("Retrying Webdriver after error.", e);
                    if(driver != null) {
                        driver.navigate().refresh();
                    }
                    retries++;
                }
            }

        } else {
            throw new IllegalArgumentException("No logic is currently implemented for browser [" + browser + "].");
        }

        if(driver == null) {
            throw new NullPointerException("Driver did not started correctly. Check previously logged error messages. \n" +
                    "If you're running in a local machine, ensure that Selenium Grid is running (i.e. check your docker container status).");
        }

        // To prevent Selenium logging messages, set this logging level BELOW the root level set in the logback.xml file.
        // Do NOT import java.util.logging, since otherwise it will break javadoc generation for Java >8 due to
        // conflicts with jackson-annotations, for some reason.
        driver.setLogLevel(java.util.logging.Level.CONFIG);
        driver.manage().timeouts().implicitlyWait(config.getTimeout().LONG_POLLING);
        driver.manage().timeouts().pageLoadTimeout(config.getTimeout().PAGE_LOAD_TIMEOUT);
    }

    private void setTestContext(ITestContext testContext) {
        testContext.setAttribute(Attribute.WEB_DRIVER, driver);
        testContext.setAttribute(Attribute.SCREENSHOT_HELPER, new ScreenShotHelper(driver, config));
        testContext.setAttribute(Attribute.SHOULD_LOG_PAGE_SOURCE, shouldLogPageSource());
    }

    private boolean shouldLogPageSource() {
        final String status = config.getProperty("logPageSourceOnError");
        switch (status) {
            case Status.ENABLED, Status.ENABLED_ON_FAILURE -> {return true;}
            case Status.DISABLED -> {return false;}
            default -> throw logAndGetIllegalArgumentException("status", status);
        }
    }
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy