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

com.nordstrom.automation.selenium.SeleniumConfig Maven / Gradle / Ivy

Go to download

Selenium Foundation is an automation framework designed to extend and enhance the capabilities provided by Selenium (WebDriver).

There is a newer version: 28.3.1-s4
Show newest version
package com.nordstrom.automation.selenium;

import static org.openqa.selenium.json.Json.LIST_OF_MAPS_TYPE;
import static org.openqa.selenium.json.Json.MAP_TYPE;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Reader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.lang3.StringUtils;
import org.openqa.selenium.Capabilities;
import org.openqa.selenium.MutableCapabilities;
import org.openqa.selenium.grid.config.ConfigException;
import org.openqa.selenium.json.Json;

import com.nordstrom.automation.selenium.core.GridUtility;
import com.nordstrom.automation.settings.SettingsCore;

/**
 * This class declares settings and methods related to WebDriver and Grid configuration specific to the Selenium 3 API.
 * 
 * @see SettingsCore
 */
public class SeleniumConfig extends AbstractSeleniumConfig {
    
    private static final String DEFAULT_GRID_LAUNCHER = "org.openqa.selenium.grid.Bootstrap";
    private static final String DEFAULT_HUB_PORT = "4446";
    private static final String DEFAULT_HUB_CONFIG = "hubConfig-s4.json";
    private static final String DEFAULT_NODE_CONFIG = "nodeConfig-s4.json";
    
    /**
     * org.openqa.selenium.grid.Main
     * 
     * 
<dependency>
     *  <groupId>org.seleniumhq.selenium</groupId>
     *  <artifactId>selenium-grid</artifactId>
     *  <version>4.9.1</version>
     *</dependency>
* * org.openqa.selenium.io.Zip * *
<dependency>
     *  <groupId>org.seleniumhq.selenium</groupId>
     *  <artifactId>selenium-remote-driver</artifactId>
     *  <version>4.9.1</version>
     *</dependency>
* * org.openqa.selenium.remote.http.Route * *
<dependency>
     *  <groupId>org.seleniumhq.selenium</groupId>
     *  <artifactId>selenium-http</artifactId>
     *  <version>4.9.1</version>
     *</dependency>
* * org.openqa.selenium.net.Urls * *
<dependency>
     *  <groupId>org.seleniumhq.selenium</groupId>
     *  <artifactId>selenium-api</artifactId>
     *  <version>4.9.1</version>
     *</dependency>
* * org.openqa.selenium.json.Json * *
<dependency>
     *  <groupId>org.seleniumhq.selenium</groupId>
     *  <artifactId>selenium-json</artifactId>
     *  <version>4.9.1</version>
     *</dependency>
* * com.google.common.base.Utf8 * *
<dependency>
     *  <groupId>com.google.guava</groupId>
     *  <artifactId>guava</artifactId>
     *  <version>31.1-jre</version>
     *</dependency>
* * com.beust.jcommander.Strings * *
<dependency>
     *  <groupId>com.beust</groupId>
     *  <artifactId>jcommander</artifactId>
     *  <version>1.82</version>
     *</dependency>
* * io.opentelemetry.sdk.autoconfigure.SpiUtil * *
<dependency>
     *  <groupId>io.opentelemetry</groupId>
     *  <artifactId>opentelemetry-sdk-extension-autoconfigure</artifactId>
     *  <version>1.25.0-alpha</version>
     *</dependency>
* * io.opentelemetry.sdk.autoconfigure.spi.Ordered * *
<dependency>
     *  <groupId>io.opentelemetry</groupId>
     *  <artifactId>opentelemetry-sdk-extension-autoconfigure-spi</artifactId>
     *  <version>1.25.0</version>
     *</dependency>
* * io.opentelemetry.api.trace.Span * *
<dependency>
     *  <groupId>io.opentelemetry</groupId>
     *  <artifactId>opentelemetry-api</artifactId>
     *  <version>1.25.0</version>
     *</dependency>
* * io.opentelemetry.api.logs.Logger * *
<dependency>
     *  <groupId>io.opentelemetry</groupId>
     *  <artifactId>opentelemetry-api-logs</artifactId>
     *  <version>1.25.0-alpha</version>
     *</dependency>
* * io.opentelemetry.api.events.EventEmitter * *
<dependency>
     *  <groupId>io.opentelemetry</groupId>
     *  <artifactId>opentelemetry-api-events</artifactId>
     *  <version>1.25.0-alpha</version>
     *</dependency>
* * io.opentelemetry.sdk.trace.SdkSpan * *
<dependency>
     *  <groupId>io.opentelemetry</groupId>
     *  <artifactId>opentelemetry-sdk-trace</artifactId>
     *  <version>1.25.0</version>
     *</dependency>
* * io.opentelemetry.context.Scope * *
<dependency>
     *  <groupId>io.opentelemetry</groupId>
     *  <artifactId>opentelemetry-context</artifactId>
     *  <version>1.25.0</version>
     *</dependency>
* * io.opentelemetry.sdk.metrics.View * *
<dependency>
     *  <groupId>io.opentelemetry</groupId>
     *  <artifactId>opentelemetry-sdk-metrics</artifactId>
     *  <version>1.25.0</version>
     *</dependency>
* * io.opentelemetry.sdk.logs.LogLimits * *
<dependency>
     *  <groupId>io.opentelemetry</groupId>
     *  <artifactId>opentelemetry-sdk-logs</artifactId>
     *  <version>1.25.0-alpha</version>
     *</dependency>
* * io.opentelemetry.sdk.common.Clock * *
<dependency>
     *  <groupId>io.opentelemetry</groupId>
     *  <artifactId>opentelemetry-sdk-common</artifactId>
     *  <version>1.25.0</version>
     *</dependency>
* * io.opentelemetry.semconv.trace.attributes.SemanticAttributes * *
<dependency>
     *  <groupId>io.opentelemetry</groupId>
     *  <artifactId>opentelemetry-semconv</artifactId>
     *  <version>1.25.0-alpha</version>
     *</dependency>
* * io.opentelemetry.sdk.OpenTelemetrySdk * *
<dependency>
     *  <groupId>io.opentelemetry</groupId>
     *  <artifactId>opentelemetry-sdk</artifactId>
     *  <version>1.25.0</version>
     *</dependency>
* * org.zeromq.Utils * *
<dependency>
     *  <groupId>org.zeromq</groupId>
     *  <artifactId>jeromq</artifactId>
     *  <version>0.5.3</version>
     *</dependency>
* * dev.failsafe.Call * *
<dependency>
     *  <groupId>dev.failsafe</groupId>
     *  <artifactId>failsafe</artifactId>
     *  <version>3.3.1</version>
     *</dependency>
* * graphql.Assert * *
<dependency>
     *  <groupId>com.graphql-java</groupId>
     *  <artifactId>graphql-java</artifactId>
     *  <version>20.2</version>
     *</dependency>
* * org.dataloader.DataLoader * *
<dependency>
     *  <groupId>com.graphql-java</groupId>
     *  <artifactId>java-dataloader</artifactId>
     *  <version>3.2.0</version>
     *</dependency>
* * org.slf4j.MDC * *
<dependency>
     *  <groupId>org.slf4j</groupId>
     *  <artifactId>slf4j-api</artifactId>
     *  <version>1.7.36</version>
     *</dependency>
* * io.netty.channel.Channel * *
<dependency>
     *  <groupId>io.netty</groupId>
     *  <artifactId>netty-transport</artifactId>
     *  <version>4.1.91.Final</version>
     *</dependency>
* * io.netty.util.Timer * *
<dependency>
     *  <groupId>io.netty</groupId>
     *  <artifactId>netty-common</artifactId>
     *  <version>4.1.91.Final</version>
     *</dependency>
* * io.netty.handler.ssl.SslUtils * *
<dependency>
     *  <groupId>io.netty</groupId>
     *  <artifactId>netty-handler</artifactId>
     *  <version>4.1.91.Final</version>
     *</dependency>
* * org.slf4j.impl.StaticLoggerBinder * *
<dependency>
     *  <groupId>ch.qos.logback</groupId>
     *  <artifactId>logback-classic</artifactId>
     *  <version>1.2.11</version>
     *</dependency>
* * ch.qos.logback.core.Layout * *
<dependency>
     *  <groupId>ch.qos.logback</groupId>
     *  <artifactId>logback-core</artifactId>
     *  <version>1.2.11</version>
     *</dependency>
* * io.netty.buffer.ByteBuf * *
<dependency>
     *  <groupId>io.netty</groupId>
     *  <artifactId>netty-buffer</artifactId>
     *  <version>4.1.91.Final</version>
     *</dependency>
* * io.netty.handler.codec.http.Cookie * *
<dependency>
     *  <groupId>io.netty</groupId>
     *  <artifactId>netty-codec-http</artifactId>
     *  <version>4.1.91.Final</version>
     *</dependency>
* * io.netty.handler.codec.Headers * *
<dependency>
     *  <groupId>io.netty</groupId>
     *  <artifactId>netty-codec</artifactId>
     *  <version>4.1.91.Final</version>
     *</dependency>
* * com.google.common.util.concurrent.internal.InternalFutures * *
<dependency>
     *  <groupId>com.google.guava</groupId>
     *  <artifactId>failureaccess</artifactId>
     *  <version>1.0.1</version>
     *</dependency>
*/ private static final String[] DEPENDENCY_CONTEXTS = { "org.openqa.selenium.grid.Main", "com.beust.jcommander.Strings", "org.openqa.selenium.remote.http.Route", "com.google.common.base.Utf8", "org.openqa.selenium.Keys", "org.openqa.selenium.remote.tracing.Tracer", "org.openqa.selenium.json.Json", "io.opentelemetry.sdk.autoconfigure.ResourceConfiguration", "io.opentelemetry.sdk.autoconfigure.spi.Ordered", "io.opentelemetry.api.trace.Span", "io.opentelemetry.sdk.trace.SdkSpan", "io.opentelemetry.context.Scope", "io.opentelemetry.sdk.metrics.View", "io.opentelemetry.sdk.logs.LogLimits", "io.opentelemetry.sdk.common.Clock", "io.opentelemetry.sdk.OpenTelemetrySdk", "io.opentelemetry.semconv.SemanticAttributes", "io.opentelemetry.api.incubator.events.EventLoggerProvider", "org.zeromq.Utils", "dev.failsafe.Call", "graphql.Assert", "org.slf4j.MDC", "io.netty.channel.Channel", "io.netty.util.Timer", "io.netty.handler.ssl.SslUtils", "io.netty.buffer.ByteBuf", "io.netty.handler.codec.Headers", "io.netty.handler.codec.http.Cookie", "org.openqa.selenium.io.Zip", "org.slf4j.impl.StaticLoggerBinder", "ch.qos.logback.core.Layout", "io.netty.resolver.NameResolver", "io.opentelemetry.api.logs.Logger", "org.openqa.selenium.net.Urls", "org.dataloader.DataLoader", "com.google.common.util.concurrent.internal.InternalFutures", "org.eclipse.jetty.server.Server", "org.reactivestreams.Publisher", "org.openqa.selenium.manager.SeleniumManager", "org.apache.commons.exec.Executor", "io.netty.buffer.ByteBufUtil" }; static { try { seleniumConfig = new SeleniumConfig(); } catch (ConfigurationException | IOException e) { throw new RuntimeException("Failed to instantiate settings", e); } } /** * Instantiate a Selenium Foundation configuration object. * * @throws ConfigurationException If a failure is encountered while initializing this configuration object. * @throws IOException If a failure is encountered while reading from a configuration input stream. */ public SeleniumConfig() throws ConfigurationException, IOException { super(); } /** * Get the Selenium configuration object. * * @return Selenium configuration object */ public static SeleniumConfig getConfig() { return seleniumConfig; } public int getVersion() { return 4; } /** * {@inheritDoc} */ @Override protected Map getDefaults() { Map defaults = super.getDefaults(); defaults.put(SeleniumSettings.GRID_LAUNCHER.key(), DEFAULT_GRID_LAUNCHER); defaults.put(SeleniumSettings.LAUNCHER_DEPS.key(), StringUtils.join(DEPENDENCY_CONTEXTS, File.pathSeparator)); defaults.put(SeleniumSettings.HUB_PORT.key(), DEFAULT_HUB_PORT); defaults.put(SeleniumSettings.HUB_CONFIG.key(), DEFAULT_HUB_CONFIG); defaults.put(SeleniumSettings.NODE_CONFIG.key(), DEFAULT_NODE_CONFIG); return defaults; } /** * {@inheritDoc} */ @Override public Path createHubConfig() throws IOException { return getHubConfigPath(); } /** * {@inheritDoc} */ @SuppressWarnings("unchecked") @Override public Path createNodeConfig(String capabilities, URL hubUrl) throws IOException { Map nodeConfig; // get path to node configuration template String nodeConfigPath = getNodeConfigPath().toString(); // create node configuration from template try (Reader reader = Files.newBufferedReader(getNodeConfigPath())) { nodeConfig = new Json().toType(reader, MAP_TYPE); Map nodeOption = (Map) nodeConfig.computeIfAbsent("node", k -> new HashMap<>()); nodeOption.put("hub", hubUrl.toString()); nodeOption.computeIfAbsent("detect-drivers", k -> false); nodeOption.computeIfAbsent("driver-configuration", k -> new ArrayList<>()); } catch (IOException e) { throw new ConfigException("Failed reading node configuration template.", e); } catch (ClassCastException e) { throw new ConfigException("Failed unwrapping [node.driver-configuration] option", e); } // convert capabilities string to List> List> capsMapList = new Json().toType("[" + capabilities + "]", LIST_OF_MAPS_TYPE); List capabilitiesList = capsMapList.stream() .map(MutableCapabilities::new) .map(theseCaps -> theseCaps.merge(getModifications(theseCaps, NODE_MODS_SUFFIX))) .collect(Collectors.toList()); // strip extension to get template base path String configPathBase = nodeConfigPath.substring(0, nodeConfigPath.length() - 5); // get hash code of capabilities list and hub URL as 8-digit hexadecimal string String hashCode = String.format("%08X", Objects.hash(capabilitiesList, hubUrl)); // assemble node configuration file path with aggregated hash code Path filePath = Paths.get(configPathBase + "-" + hashCode + ".json"); // if assembled path does not exist if (filePath.toFile().createNewFile()) { Map nodeOption = (Map) nodeConfig.get("node"); List driverConfiguration = (List) nodeOption.get("driver-configuration"); capabilitiesList.stream().forEach(theseCaps -> { Map thisConfig = new HashMap<>(); thisConfig.put("display-name", GridUtility.getPersonality(theseCaps)); thisConfig.put("stereotype", theseCaps); driverConfiguration.add(thisConfig); }); try (OutputStream fos = new FileOutputStream(filePath.toFile()); OutputStream out = new BufferedOutputStream(fos)) { out.write(new Json().toJson(nodeConfig).getBytes(StandardCharsets.UTF_8)); } } return filePath; } /** * {@inheritDoc} */ @Override public Capabilities[] getCapabilitiesForJson(String capabilities) { List> capsMapList = new Json().toType("[" + capabilities + "]", LIST_OF_MAPS_TYPE); return capsMapList.stream().map(MutableCapabilities::new).collect(Collectors.toList()).toArray(new Capabilities[0]); } /** * {@inheritDoc} */ @Override public Capabilities mergeCapabilities(Capabilities target, Capabilities change) { return target.merge(change); } /** * {@inheritDoc} */ @Override public String toJson(Object obj) { return new Json().toJson(obj); } }