com.github.mike10004.seleniumhelp.UnitTests.java Source code

Java tutorial

Introduction

Here is the source code for com.github.mike10004.seleniumhelp.UnitTests.java

Source

package com.github.mike10004.seleniumhelp;

import com.github.mike10004.nativehelper.Platforms;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.CharMatcher;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import io.github.bonigarcia.wdm.ChromeDriverManager;
import io.github.bonigarcia.wdm.FirefoxDriverManager;
import org.apache.commons.text.StringEscapeUtils;
import org.jsoup.Jsoup;
import org.openqa.selenium.Platform;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.firefox.FirefoxBinary;
import org.openqa.selenium.firefox.internal.Executable;
import org.openqa.selenium.os.ExecutableFinder;

import javax.annotation.Nullable;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toList;
import static org.openqa.selenium.Platform.MAC;
import static org.openqa.selenium.Platform.UNIX;
import static org.openqa.selenium.Platform.WINDOWS;
import static org.openqa.selenium.os.WindowsUtils.getPathsInProgramFiles;

/**
 * Static constants and utility methods to assist with tests.
 */
public class UnitTests {

    private static final String SYSPROP_CHROME_OPTIONS_EXTRA_ARGS = "selenium-help.chrome.options.extraArgs";
    private static final String SYSPROP_FIREFOX_EXECUTABLE_PATH = "selenium-help.firefox.executable.path";
    private static final String SYSPROP_CHROME_EXECUTABLE_PATH = "selenium-help.chrome.executable.path";
    public static final String SYSPROP_OPENSSL_TESTS_SKIP = "selenium-help.openssl.tests.skip";
    private static final String SYSPROP_OPENSSL_EXECUTABLE = "selenium-help.openssl.executable.path";
    private static final String SYSPROP_CHROME_HEADLESS_TESTS_DISABLED = "selenium-help.chrome.headless.tests.disabled";
    private static final String SYSPROP_DEBUG_ENVIRONMENT = "selenium-help.build.environment.debug";
    private static final String ENV_FIREFOX_BIN = "FIREFOX_BIN";
    private static final String ENV_CHROME_BIN = "CHROME_BIN";

    private UnitTests() {
    }

    @SuppressWarnings("SameParameterValue")
    private static void print(String key, @Nullable String value, PrintStream out) {
        value = value == null ? "" : StringEscapeUtils.escapeJava(value);
        out.format("%s=%s%n", key, value);
    }

    static {
        if (Boolean.parseBoolean(System.getProperty(SYSPROP_DEBUG_ENVIRONMENT))) {
            System.err.format("%s=true; describing build environment...%n%n", SYSPROP_DEBUG_ENVIRONMENT);
            System.err.format("environment variables:%n%n");
            for (String envVarName : new String[] { "CHROMEDRIVER_VERSION", "GECKODRIVER_VERSION", "DISPLAY",
                    ENV_CHROME_BIN, ENV_FIREFOX_BIN }) {
                print(envVarName, System.getenv(envVarName), System.err);
            }
            System.err.format("%nsystem properties:%n%n");
            for (String syspropName : new String[] { SYSPROP_CHROME_OPTIONS_EXTRA_ARGS,
                    SYSPROP_FIREFOX_EXECUTABLE_PATH, SYSPROP_CHROME_EXECUTABLE_PATH, SYSPROP_OPENSSL_TESTS_SKIP,
                    SYSPROP_OPENSSL_EXECUTABLE, SYSPROP_CHROME_HEADLESS_TESTS_DISABLED, "wdm.chromeDriverVersion",
                    "wdm.geckoDriverVersion", }) {
                String value = System.getProperty(syspropName);
                print(syspropName, value, System.err);
            }
            System.err.println();
        }
    }

    /**
     * Downloads and configures the JVM for use of a recommended version of ChromeDriver.
     */
    public static void setupRecommendedChromeDriver() {
        ChromeDriverManager.getInstance().setup(); // use system property wdm.chromeDriverManager to specify a chromedriver version
    }

    /**
     * Downloads and configures the JVM for use of a recommended version of GeckoDriver.
     */
    public static void setupRecommendedGeckoDriver() {
        FirefoxDriverManager.getInstance().setup();
    }

    public static boolean isHeadlessChromeTestsDisabled() {
        return Boolean.parseBoolean(System.getProperty(SYSPROP_CHROME_HEADLESS_TESTS_DISABLED, "false"));
    }

    @SuppressWarnings("deprecation")
    @Nullable
    static String getFirefoxExecutablePath() {
        return getExecutablePath(SYSPROP_FIREFOX_EXECUTABLE_PATH, ENV_FIREFOX_BIN, () -> {
            if (Platforms.getPlatform().isWindows()) {
                Stream<Executable> executables = locateFirefoxBinariesFromPlatform();
                File file = executables.map(Executable::getFile).filter(File::isFile).findFirst().orElse(null);
                if (file != null) {
                    return file.getAbsolutePath();
                }
            }
            return null;
        });
    }

    /**
     * Gets an executable path.
     * @return the executable path, or whatever is supplied by the defaulter; can be null if the defaulter returns null
     */
    private static String getExecutablePath(String systemPropertyName, String environmentVariableName,
            Supplier<String> defaulter) {
        String executablePath = Strings.emptyToNull(System.getProperty(systemPropertyName));
        if (executablePath == null && environmentVariableName != null) {
            executablePath = Strings.emptyToNull(System.getenv(environmentVariableName));
        }
        if (executablePath == null) {
            executablePath = defaulter.get();
        }
        return Strings.emptyToNull(executablePath);
    }

    @Nullable
    static String getChromeExecutablePath() {
        return getExecutablePath(SYSPROP_CHROME_EXECUTABLE_PATH, ENV_CHROME_BIN, () -> null);
    }

    // Licensed to the Software Freedom Conservancy (SFC) under one
    // or more contributor license agreements.  See the NOTICE file
    // distributed with this work for additional information
    // regarding copyright ownership.  The SFC licenses this file
    // to you 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.

    /**
     * Locates the firefox binary by platform.
     * <p>
     * Copied from Selenium's FirefoxBinary.java. See license above.
     */
    @SuppressWarnings("deprecation")
    private static Stream<Executable> locateFirefoxBinariesFromPlatform() {
        ImmutableList.Builder<Executable> executables = new ImmutableList.Builder<>();

        Platform current = Platform.getCurrent();
        if (current.is(WINDOWS)) {
            executables.addAll(Stream
                    .of(getPathsInProgramFiles("Mozilla Firefox\\firefox.exe"),
                            getPathsInProgramFiles("Firefox Developer Edition\\firefox.exe"),
                            getPathsInProgramFiles("Nightly\\firefox.exe"))
                    .flatMap(List::stream).map(File::new).filter(File::exists).map(Executable::new)
                    .collect(toList()));

        } else if (current.is(MAC)) {
            // system
            File binary = new File("/Applications/Firefox.app/Contents/MacOS/firefox-bin");
            if (binary.exists()) {
                executables.add(new Executable(binary));
            }

            // user home
            binary = new File(System.getProperty("user.home") + binary.getAbsolutePath());
            if (binary.exists()) {
                executables.add(new Executable(binary));
            }

        } else if (current.is(UNIX)) {
            String systemFirefoxBin = new ExecutableFinder().find("firefox-bin");
            if (systemFirefoxBin != null) {
                executables.add(new Executable(new File(systemFirefoxBin)));
            }
        }

        String systemFirefox = new ExecutableFinder().find("firefox");
        if (systemFirefox != null) {
            Path firefoxPath = new File(systemFirefox).toPath();
            if (Files.isSymbolicLink(firefoxPath)) {
                try {
                    Path realPath = firefoxPath.toRealPath();
                    File attempt1 = realPath.getParent().resolve("firefox").toFile();
                    if (attempt1.exists()) {
                        executables.add(new Executable(attempt1));
                    } else {
                        File attempt2 = realPath.getParent().resolve("firefox-bin").toFile();
                        if (attempt2.exists()) {
                            executables.add(new Executable(attempt2));
                        }
                    }
                } catch (IOException e) {
                    // ignore this path
                }

            } else {
                executables.add(new Executable(new File(systemFirefox)));
            }
        }

        return executables.build().stream();
    }

    public static Supplier<FirefoxBinary> createFirefoxBinarySupplier() {
        String executablePath = getFirefoxExecutablePath();
        if (Strings.isNullOrEmpty(executablePath)) {
            return FirefoxBinary::new;
        } else {
            File executableFile = new File(executablePath);
            if (!executableFile.isFile()) {
                throw new RuntimeException("not found: " + executablePath);
            }
            if (!executableFile.canExecute()) {
                throw new RuntimeException("not executable: " + executableFile);
            }
            return () -> new FirefoxBinary(executableFile);
        }
    }

    private static List<String> getChromeOptionsExtraArgs() {
        String tokensStr = System.getProperty(SYSPROP_CHROME_OPTIONS_EXTRA_ARGS);
        return getChromeOptionsExtraArgs(tokensStr);
    }

    private static final Splitter chromeExtraArgSplitter = Splitter.on(CharMatcher.breakingWhitespace())
            .trimResults().omitEmptyStrings();

    @VisibleForTesting
    static ImmutableList<String> getChromeOptionsExtraArgs(@Nullable String systemPropertyValue) {
        if (systemPropertyValue == null) {
            return ImmutableList.of();
        }
        return ImmutableList.copyOf(chromeExtraArgSplitter.split(systemPropertyValue));
    }

    /**
     * Creates a Chrome options object suitable for unit tests. Some build environments
     * (I'm looking at you, Travis) require some tweaks to the way Chrome is executed,
     * and this allows you to specify those tweaks with a system property. The value
     * of the property is tokenized on breaking whitespace, so there's no way to include
     * an actual space within an argument, but the need for that completeness is uncommon
     * enough that we'll ignore it for now. This also sets the Chrome executable from
     * system property {@link #SYSPROP_CHROME_EXECUTABLE_PATH} or environment variable
     * {@link #ENV_CHROME_BIN}.
     * @return an options object with parameters set
     */
    public static ChromeOptions createChromeOptions() {
        ChromeOptions options = new ChromeOptions();
        String executablePath = getChromeExecutablePath();
        if (executablePath != null) {
            options.setBinary(executablePath);
        }
        options.addArguments(getChromeOptionsExtraArgs());
        return options;
    }

    public static ExecutableConfig makeOpensslConfig() {
        String path = Strings.emptyToNull(System.getProperty(SYSPROP_OPENSSL_EXECUTABLE));
        if (path != null) {
            File file = new File(path);
            System.out.format("using openssl executable at %s%n", file);
            return ExecutableConfig.byPathOnly(file);
        }
        return ExecutableConfig.byNameOnly("openssl");
    }

    public static ExecutableConfig makeKeytoolConfig() {
        return ExecutableConfig.byNameOnly("keytool");
    }

    public static boolean isSkipOpensslTests() {
        return Boolean.parseBoolean(System.getProperty(SYSPROP_OPENSSL_TESTS_SKIP, "false"));
    }

    public static String removeHtmlWrapping(String html) {
        org.jsoup.nodes.Document doc = Jsoup.parse(html);
        return doc.text();
    }
}