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

com.nordstrom.automation.selenium.AbstractSeleniumConfig 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 java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.FileSystemAlreadyExistsException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.configuration2.io.FileHandler;
import org.apache.commons.configuration2.io.FileLocationStrategy;
import org.apache.commons.configuration2.io.FileLocator;
import org.apache.commons.configuration2.io.FileLocatorUtils;
import org.apache.commons.configuration2.io.FileSystem;
import org.apache.http.client.utils.URIBuilder;
import org.openqa.selenium.Capabilities;
import org.openqa.selenium.SearchContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.nordstrom.automation.selenium.core.GridUtility;
import com.nordstrom.automation.selenium.core.SeleniumGrid;
import com.nordstrom.automation.selenium.servlet.ExamplePageLauncher;
import com.nordstrom.automation.selenium.servlet.ExamplePageServlet;
import com.nordstrom.automation.selenium.servlet.ExamplePageServlet.FrameA_Servlet;
import com.nordstrom.automation.selenium.servlet.ExamplePageServlet.FrameB_Servlet;
import com.nordstrom.automation.selenium.servlet.ExamplePageServlet.FrameC_Servlet;
import com.nordstrom.automation.selenium.servlet.ExamplePageServlet.FrameD_Servlet;
import com.nordstrom.automation.selenium.support.SearchContextWait;
import com.nordstrom.automation.settings.SettingsCore;
import com.nordstrom.common.base.UncheckedThrow;
import com.nordstrom.common.file.PathUtils;

/**
 * This class declares settings and methods related to WebDriver and Grid configuration for Selenium 3 and Selenium 4.
 */
public abstract class AbstractSeleniumConfig extends
                SettingsCore {

    private static final String SETTINGS_FILE = "settings.properties";

    protected static final String NODE_MODS_SUFFIX = ".node.mods";
    private static final String CAPS_MODS_SUFFIX = ".caps.mods";
    
    private static final String APPIUM_PATH = "APPIUM_BINARY_PATH";
    private static final String NODE_PATH = "NODE_BINARY_PATH";
    
    private static final Logger LOGGER = LoggerFactory.getLogger(SeleniumConfig.class);
    
    private static final String APPIUM_HOST = "\"appium:host\":\"0.0.0.0\",";
    private static final String PERSONALITY = "\"nord:options\":{\"personality\":\"%s\"}";
        
    /**
     * This enumeration declares the settings that enable you to control the parameters used by
     * Selenium Foundation.
     * 

* Each setting is defined by a constant name and System property key. Many settings also define * default values. Note that all of these settings can be overridden via the * {@code settings.properties} file and System property declarations. */ public enum SeleniumSettings implements SettingsCore.SettingsAPI { /** * Scheme component for the {@link AbstractSeleniumConfig#getTargetUri target URI}. *

* name: selenium.target.scheme
* default: http */ TARGET_SCHEME("selenium.target.scheme", "http"), /** * Credentials component for the {@link AbstractSeleniumConfig#getTargetUri target URI}. *

* name: selenium.target.creds
* default: {@code null} */ TARGET_CREDS("selenium.target.creds", null), /** * Host component for the {@link AbstractSeleniumConfig#getTargetUri target URI}. *

* name: selenium.target.host
* default: localhost */ TARGET_HOST("selenium.target.host", "localhost"), /** * Port component for the {@link AbstractSeleniumConfig#getTargetUri target URI}. *

* name: selenium.target.port
* default: {@code null} */ TARGET_PORT("selenium.target.port", null), /** * Path component for the {@link AbstractSeleniumConfig#getTargetUri target URI}. *

* name: selenium.target.path
* default: / */ TARGET_PATH("selenium.target.path", "/"), /** * This setting specifies a path-delimited list of fully-qualified names of local Selenium Grid driver * plugin classes. *

* NOTE: Defining a value for this setting overrides the ServiceLoader specification defined * by the associated provider configuration file (com.nordstrom.automation.selenium.DriverPlugin). *

* name: selenium.grid.plugins
* default: {@code null} */ GRID_PLUGINS("selenium.grid.plugins", null), /** * This setting specifies whether the local Selenium Grid instance will be shut down at the end of the * test run. *

* name: selenium.grid.shutdown
* default: true */ SHUTDOWN_GRID("selenium.grid.shutdown", "true"), /** * This setting specifies the fully-qualified name of the GridLauncher class, which provides a * command-line interface for configuring and launching Selenium Grid servers implemented in Java. *

* name: selenium.grid.launcher
* default: (populated by {@link SeleniumConfig#getDefaults() getDefaults()}) *

    *
  • Selenium 3: org.openqa.grid.selenium.GridLauncherV3
  • *
  • Selenium 4: org.openqa.selenium.grid.Bootstrap
  • *
*/ GRID_LAUNCHER("selenium.grid.launcher", null), /** * This setting specifies a path-delimited list of fully-qualified names of context classes for the * dependencies of the {@link #GRID_LAUNCHER} class. *

* name: selenium.launcher.deps
* default: (populated by {@link SeleniumConfig#getDefaults() getDefaults()}) */ LAUNCHER_DEPS("selenium.launcher.deps", null), /** * This setting specifies the configuration file name/path for the local Selenium Grid hub server. *

* name: selenium.hub.config
* Selenium 3: hubConfig-s3.json
* Selenium 4: hubConfig-s4.json */ HUB_CONFIG("selenium.hub.config", null), /** * This is the URL for the Selenium Grid endpoint: [scheme:][//authority]/wd/hub *

* name: selenium.hub.host
* Selenium 3: http://<{@code localhost}>:4445/wd/hub
* Selenium 4: http://<{@code localhost}>:4446/wd/hub */ HUB_HOST("selenium.hub.host", null), /** * This is the port assigned to the local Selenium Grid hub server. *

* name: selenium.hub.port
* Selenium 3: 4445
* Selenium 4: 4446 */ HUB_PORT("selenuim.hub.port", null), /** * This setting specifies a comma-delimited list of fully-qualified names of servlet classes to extend the * capabilities of the local Selenium Grid hub server. *

* name: selenium.hub.servlets
* default: {@code null} */ HUB_SERVLETS("selenium.hub.servlets", null), /** * This setting specifies whether to launch the local Selenium Grid hub server with JDWP debugging. *

* name: selenium.hub.debug
* default: {@code false} */ HUB_DEBUG("selenium.hub.debug", "false"), /** * This setting specifies the configuration template name/path for local Selenium Grid node servers. *

* name: selenium.node.config
* Selenium 3: nodeConfig-s3.json
* Selenium 4: nodeConfig-s4.json */ NODE_CONFIG("selenium.node.config", null), /** * This setting specifies a comma-delimited list of fully-qualified names of servlet classes to extend the * capabilities of local Selenium Grid node servers. *

* name: selenium.node.servlets
* default: {@code null} */ NODE_SERVLETS("selenium.node.servlets", null), /** * This setting specifies whether to launch the local Selenium Grid node server with JDWP debugging. *

* name: selenium.node.debug
* default: {@code false} */ NODE_DEBUG("selenium.node.debug", "false"), /** * This setting specifies the browser name or "personality" for new session requests. *

* name: selenium.browser.name
* default: {@code null} */ BROWSER_NAME("selenium.browser.name", null), /** * If {@link #BROWSER_NAME} is undefined, this setting specifies the {@link Capabilities} for new session * requests. This can be either a file path (absolute, relative, or simple filename) or a direct value. *

* name: selenium.browser.caps
* default: {@code null} */ BROWSER_CAPS("selenium.browser.caps", null), /** * This setting specifies the maximum allowed interval for a page to finish loading. *

* name: selenium.timeout.pageload
* default: 30 */ PAGE_LOAD_TIMEOUT("selenium.timeout.pageload", "30"), /** * This setting specifies the maximum amount of time the driver will search for an element. *

* name: selenium.timeout.implied
* default: 15 */ IMPLIED_TIMEOUT("selenium.timeout.implied", "15"), /** * This setting specifies the maximum allowed interval for an asynchronous script to finish. *

* name: selenium.timeout.script
* default: 30 */ SCRIPT_TIMEOUT("selenium.timeout.script", "30"), /** * This setting specifies the maximum amount of time to wait for a search context event. *

* name: selenium.timeout.wait
* default: 15 */ WAIT_TIMEOUT("selenium.timeout.wait", "15"), /** * This setting specifies the maximum amount of time to wait for a Grid server to launch. *

* name: selenium.timeout.host
* default: 30 */ HOST_TIMEOUT("selenium.timeout.host", "30"), /** * This setting specifies the working directory for local Selenium Grid server processes. *

* name: selenium.grid.working.dir
* default: {@code null} */ GRID_WORKING_DIR("selenium.grid.working.dir", null), /** * This setting specifies the log file folder for local Selenium Grid server processes. *

* NOTE: If a relative path is specified, {@link #GRID_WORKING_DIR} is used as parent. If that's * unspecified, the working directory for the current Java process is used (i.e. - {@code user.dir}). *

* name: selenium.grid.log.folder
* default: logs */ GRID_LOGS_FOLDER("selenium.grid.log.folder", "logs"), /** * This setting specifies whether output from local Selenium Grid servers is captured in log files. *

* name: selenium.grid.no.redirect
* default: {@code false} */ GRID_NO_REDIRECT("selenium.grid.no.redirect", "false"), /** * This setting specifies whether the ExamplePageServlet is installed on the hub server of the local * Selenium Grid instance. This servlet provides the example page used by the Selenium Foundation * unit tests. *

* name: selenium.grid.examples
* default: {@code true} */ GRID_EXAMPLES("selenium.grid.examples", "true"), /** * This setting specifies whether the LifecycleServlet is installed on the hub and node servers of the * local Selenium Grid instance. This servlet implements a remote shutdown feature for Grid servers. *

* name: selenium.grid.lifecycle
* default: {@code true} */ GRID_LIFECYCLE("selenium.grid.lifecycle", "true"), /** * This setting specifies the target platform for the current test context. *

* name: selenium.context.platform
* default: support */ CONTEXT_PLATFORM("selenium.context.platform", "support"), /** * This setting specifies server arguments passed on to {@code Appium} when it's launched as a local * Selenium Grid node server. *

* NOTE: This setting can define multiple {@code Appium} server arguments together, and can be * declared multiple times when specified in the settings.properties file. *

* name: appium.cli.args
* default: {@code null} */ APPIUM_CLI_ARGS("appium.cli.args", null), /** * This setting specifies the path to the {@code Appium} main script file. *

* NOTE: If this setting is undefined, Selenium Foundation will check for the main script file in * the {@code Appium} package in the global Node package repository. *

* name: appium.binary.path
* default: value of APPIUM_BINARY_PATH environment variable */ APPIUM_BINARY_PATH("appium.binary.path", null), /** * This setting specifies the path to the {@code NodeJS} JavaScript runtime. *

* NOTE: If this setting is unspecified, Selenium Foundation will search for {@code NodeJS} on * the System path. *

* name: node.binary.path
* default: value of NODE_BINARY_PATH environment variable */ NODE_BINARY_PATH("node.binary.path", null), /** * This setting specifies the path to the {@code NPM} (Node Package Manager) utility. *

* NOTE: If this setting is unspecified, Selenium Foundation will search for {@code NPM} on the * System path. *

* name: npm.binary.path
* default: {@code null} */ NPM_BINARY_PATH("npm.binary.path", null), /** * This setting specifies the path to the {@code PM2} (Process Manager) utility. *

* NOTE: If this setting is unspecified, Selenium Foundation will search for {@code PM2} on the * System path. *

* name: pm2.binary.path
* default: {@code null} */ PM2_BINARY_PATH("pm2.binary.path", null), /** * This setting specifies that the {@code Appium} server should be managed by the {@code PM2} utility. *

* NOTE: {@code Appium} requires an active execution context. To run {@code Appium} as a stand-alone * Selenium Grid node, the server must to executed as a daemon process. Starting the server via the * {@code PM2} utility provides the required persistent execution context. * *

* name: appium.with.pm2
* default: {@code false} */ APPIUM_WITH_PM2("appium.with.pm2", "false"); private String propertyName; private String defaultValue; /** * Constructor for SeleniumSettings enumeration * * @param propertyName setting property name * @param defaultValue setting default value */ SeleniumSettings(final String propertyName, final String defaultValue) { this.propertyName = propertyName; this.defaultValue = defaultValue; } /** * {@inheritDoc} */ @Override public String key() { return propertyName; } /** * {@inheritDoc} */ @Override public String val() { return defaultValue; } } /** * This enumeration provides easy access to the timeout intervals defined in {@link SeleniumSettings}. */ public enum WaitType { /** * purpose: The maximum allowed interval for a page to finish loading.
* setting: {@link SeleniumSettings#PAGE_LOAD_TIMEOUT page load timeout} */ PAGE_LOAD(SeleniumSettings.PAGE_LOAD_TIMEOUT), /** * purpose: The maximum amount of time the driver will search for an element.
* setting: {@link SeleniumSettings#IMPLIED_TIMEOUT implicit timeout} */ IMPLIED(SeleniumSettings.IMPLIED_TIMEOUT), /** * purpose: The maximum allowed interval for an asynchronous script to finish.
* setting: {@link SeleniumSettings#SCRIPT_TIMEOUT script timeout} */ SCRIPT(SeleniumSettings.SCRIPT_TIMEOUT), /** * purpose: The maximum amount of time to wait for a search context event.
* setting: {@link SeleniumSettings#WAIT_TIMEOUT wait timeout} */ WAIT(SeleniumSettings.WAIT_TIMEOUT), /** * purpose: The maximum amount of time to wait for a Grid server to launch.
* setting: {@link SeleniumSettings#HOST_TIMEOUT host timeout} */ HOST(SeleniumSettings.HOST_TIMEOUT); private SeleniumSettings timeoutSetting; private Long timeoutInterval; /** * Constructor for WaitType enumeration * * @param timeoutSetting timeout setting constant */ WaitType(final SeleniumSettings timeoutSetting) { this.timeoutSetting = timeoutSetting; } /** * Get the timeout interval for this wait type * * @return wait type timeout interval */ public long getInterval() { return getInterval(getConfig()); } /** * Get the timeout interval for this wait type. * * @param config {@link SeleniumConfig} object to interrogate * @return wait type timeout interval */ public long getInterval(final SeleniumConfig config) { if (timeoutInterval == null) { Objects.requireNonNull(config, "[config] must be non-null"); timeoutInterval = config.getLong(timeoutSetting.key()); } return timeoutInterval; } /** * Get a search context wait object for the specified context * * @param context context for which timeout is needed * @return {@link SearchContextWait} object for the specified context */ public SearchContextWait getWait(final SearchContext context) { return new SearchContextWait(context, getInterval()); } } protected static SeleniumConfig seleniumConfig; private URI targetUri; private Path nodeConfigPath; private Path hubConfigPath; private URL hubUrl; private SeleniumGrid seleniumGrid; public AbstractSeleniumConfig() throws ConfigurationException, IOException { super(SeleniumSettings.class); } /** * {@inheritDoc} */ @Override protected Map getDefaults() { Map defaults = super.getDefaults(); Map env = System.getenv(); String appiumPath = env.get(APPIUM_PATH); String nodePath = env.get(NODE_PATH); if (appiumPath != null) { defaults.put(SeleniumSettings.APPIUM_BINARY_PATH.key(), appiumPath); } if (nodePath != null) { defaults.put(SeleniumSettings.NODE_BINARY_PATH.key(), nodePath); } return defaults; } /** * Get the Selenium configuration object. * * @return Selenium configuration object */ public static SeleniumConfig getConfig() { if (seleniumConfig != null) { return seleniumConfig; } throw new IllegalStateException("SELENIUM_CONFIG must be populated by subclass static initializer"); } public abstract int getVersion(); /** * Resolve the specified property name to its value. * *

    *
  • If the property value refers to an existing resource file, the file contents are returned;
  • *
  • ... otherwise, the property value itself is returned (may be {@code null})
  • *
* * @param propertyName name of the property to resolve * @return resolved property value (see description); may be {@code null} */ public String resolveString(String propertyName) { String propertyValue = getString(propertyName); if (propertyValue != null) { // try to resolve property value as file path String valuePath = getConfigPath(propertyValue); // if value file found if (valuePath != null) { try { // load contents of value file Path path = Paths.get(valuePath); try (Stream lines = Files.lines(path)) { propertyValue = lines.collect(Collectors.joining("\n")); } } catch (IOException eaten) { // nothing to do here } } } return propertyValue; } /** * Get the URL for the configured Selenium Grid hub host. * * @return {@link URL} for hub host; {@code null} if hub host is unspecified */ public synchronized URL getHubUrl() { if (hubUrl == null) { String hostStr = getString(SeleniumSettings.HUB_HOST.key()); if (hostStr != null) { try { hubUrl = new URL(hostStr); } catch (MalformedURLException e) { throw UncheckedThrow.throwUnchecked(e); } } } return hubUrl; } /** * Get object that represents the active Selenium Grid. * * @return {@link SeleniumGrid} object */ public SeleniumGrid getSeleniumGrid() { synchronized(SeleniumGrid.class) { if (seleniumGrid == null) { try { seleniumGrid = SeleniumGrid.create(getConfig(), getHubUrl()); } catch (IOException e) { throw UncheckedThrow.throwUnchecked(e); } } return seleniumGrid; } } /** * Shutdown the active Selenium Grid. * * @param localOnly {@code true} to target only local Grid servers * @return {@code false} if non-local Grid server encountered; otherwise {@code true} * @throws InterruptedException if this thread was interrupted */ public boolean shutdownGrid(final boolean localOnly) throws InterruptedException { boolean result = true; synchronized(SeleniumGrid.class) { if (seleniumGrid != null) { result = seleniumGrid.shutdown(localOnly); if (result) { ExamplePageLauncher.getLauncher().shutdown(); seleniumGrid = null; } } else { ExamplePageLauncher.getLauncher().shutdown(); } return result; } } /** * Get the configured target URI as specified by its component parts. *

* NOTE: The target URI is assembled from following components: * {@link SeleniumSettings#TARGET_SCHEME scheme}, {@link SeleniumSettings#TARGET_CREDS credentials}, * {@link SeleniumSettings#TARGET_HOST host}, {@link SeleniumSettings#TARGET_PORT port}, and * {@link SeleniumSettings#TARGET_PATH base path} * * @return assembled target URI */ public URI getTargetUri() { if (targetUri == null) { URIBuilder builder = new URIBuilder().setPath(getString(SeleniumSettings.TARGET_PATH.key()) + "/") .setScheme(getString(SeleniumSettings.TARGET_SCHEME.key())) .setHost(getString(SeleniumSettings.TARGET_HOST.key())); String creds = getString(SeleniumSettings.TARGET_CREDS.key()); if (creds != null) { builder.setUserInfo(creds); } String port = getString(SeleniumSettings.TARGET_PORT.key()); if (port != null) { builder.setPort(Integer.parseInt(port)); } try { targetUri = builder.build().normalize(); } catch (URISyntaxException eaten) { LOGGER.error("Specified target URI '{}' could not be parsed: {}", builder, eaten.getMessage()); } } return targetUri; } /** * Set the target URI. *

* NOTE: This method also updates the following target URI components: * {@link SeleniumSettings#TARGET_SCHEME scheme}, {@link SeleniumSettings#TARGET_CREDS credentials}, * {@link SeleniumSettings#TARGET_HOST host}, {@link SeleniumSettings#TARGET_PORT port}, and * {@link SeleniumSettings#TARGET_PATH base path} * * @param targetUri target URI */ public void setTargetUri(URI targetUri) { this.targetUri = targetUri; System.setProperty(SeleniumSettings.TARGET_PATH.key(), targetUri.getPath()); System.setProperty(SeleniumSettings.TARGET_SCHEME.key(), targetUri.getScheme()); System.setProperty(SeleniumSettings.TARGET_HOST.key(), targetUri.getHost()); System.setProperty(SeleniumSettings.TARGET_PORT.key(), Integer.toString(targetUri.getPort())); String userInfo = targetUri.getUserInfo(); if (userInfo != null) { System.setProperty(SeleniumSettings.TARGET_CREDS.key(), userInfo); } else { System.clearProperty(SeleniumSettings.TARGET_CREDS.key()); } } /** * Get the path to the Selenium Grid node configuration. * * @return Selenium Grid node configuration path */ protected Path getNodeConfigPath() { if (nodeConfigPath == null) { String nodeConfig = getConfigPath(getString(SeleniumSettings.NODE_CONFIG.key())); LOGGER.debug("nodeConfig = {}", nodeConfig); nodeConfigPath = Paths.get(nodeConfig); } return nodeConfigPath; } /** * Get the path to the Selenium Grid hub configuration. * * @return Selenium Grid hub configuration path */ public Path getHubConfigPath() { if (hubConfigPath == null) { String hubConfig = getConfigPath(getString(SeleniumSettings.HUB_CONFIG.key())); LOGGER.debug("hubConfig = {}", hubConfig); hubConfigPath = Paths.get(hubConfig); } return hubConfigPath; } /** * Convert the configured browser specification from JSON to {@link Capabilities} object. * * @return {@link Capabilities} object for the configured browser specification * @throws IllegalArgumentException if {@code BROWSER_NAME} specifies a "personality" * that isn't supported by the active Grid */ public Capabilities getCurrentCapabilities() { Capabilities capabilities = null; String browserName = getString(SeleniumSettings.BROWSER_NAME.key()); String browserCaps = resolveString(SeleniumSettings.BROWSER_CAPS.key()); if (!(browserName == null || browserName.isEmpty())) { capabilities = getSeleniumGrid().getPersonality(getConfig(), browserName); } else if (!(browserCaps == null || browserCaps.isEmpty())) { capabilities = getCapabilitiesForJson(browserCaps)[0]; } else { throw new IllegalStateException("Neither browser name nor capabilities are specified"); } capabilities = mergeCapabilities(capabilities, getModifications(capabilities, CAPS_MODS_SUFFIX)); String personality = GridUtility.getPersonality(capabilities); String defaultCaps = String.format(PERSONALITY, personality); if ("Espresso".equals(personality)) { defaultCaps = APPIUM_HOST + defaultCaps; } return mergeCapabilities(getCapabilitiesForJson("{" + defaultCaps + "}")[0], capabilities); } /** * Get the configured modifier for the specified Capabilities object. *

* NOTE: Modifiers are specified in the configuration as either JSON strings or file paths * (absolute, relative, or simple filename). Property names for modifiers correspond to "personality" * values within the capabilities themselves (in order of precedence): * *

    *
  • personality: Selenium Foundation "personality" name
  • *
  • automationName: 'appium' automation engine name
  • *
  • browserName: Selenium driver browser name
  • *
* * The first defined value is selected as the "personality" of the specified Capabilities object. * The full name of the property used to specify modifiers is the "personality" plus a context-specific * suffix: * *
    *
  • For node configuration capabilities: <personality>.node.mods
  • *
  • For "desired capabilities" requests: <personality>.caps.mods
  • *
* * @param capabilities target capabilities object * @param propertySuffix suffix for configuration property name * @return configured modifier; {@code null} if none configured */ protected Capabilities getModifications(final Capabilities capabilities, final String propertySuffix) { String personality = GridUtility.getPersonality(capabilities); if (personality == null) return null; String propertyName = personality + propertySuffix; String modsJson = resolveString(propertyName); // return mods as [Capabilities] object, or 'null' if none configured return (modsJson != null) ? getCapabilitiesForJson(modsJson)[0] : null; } /** * Generate a list of browser capabilities objects for the specified name. * * @param browserName browser name * @return list of {@link Capabilities} objects */ public Capabilities[] getCapabilitiesForName(final String browserName) { return getCapabilitiesForJson(String.format("{\"browserName\":\"%s\"}", browserName)); } /** * Convert the specified JSON string into a list of browser capabilities objects. * * @param capabilities browser capabilities as JSON string * @return list of {@link Capabilities} objects */ public abstract Capabilities[] getCapabilitiesForJson(final String capabilities); /** * Apply the indicated modifications to the specified Capabilities object. * * @param target target capabilities object * @param change revisions being merged (may be {@code null}) * @return target capabilities object with revisions applied */ public abstract Capabilities mergeCapabilities(final Capabilities target, final Capabilities change); /** * Convert the specified browser capabilities object to a JSON string. * * @param capabilities {@link Capabilities} object * @return specified capabilities as a JSON string */ public String toJson(final Capabilities capabilities) { return toJson(capabilities.asMap()); } /** * Convert the specified object to a JSON string. * * @param obj object to be converted * @return specified object as a JSON string */ public abstract String toJson(final Object obj); /** * Get the path to the specified configuration file. * * @param path configuration file path (absolute, relative, or simple filename) * @return resolved absolute path of specified file; {@code null} if file not found */ private static String getConfigPath(final String path) { FileHandler handler = new FileHandler(); handler.setPath(path); FileLocator locator = handler.getFileLocator(); FileSystem fileSystem = FileLocatorUtils.DEFAULT_FILE_SYSTEM; FileLocationStrategy strategy = FileLocatorUtils.DEFAULT_LOCATION_STRATEGY; URL url = strategy.locate(fileSystem, locator); if (url != null) { try { URI uri = getConfigUri(path, url); File file = new File(uri); return file.getAbsolutePath(); } catch (URISyntaxException eaten) { LOGGER.warn("Invalid URL returned by file locator: {}", eaten.getMessage()); } catch (IOException eaten) { LOGGER.warn("Failed to construct file system or extract configuration file: {}", eaten.getMessage()); } } return null; } /** * Get the URI of the specified configuration file from its resolved URL. * * @param path configuration file path (absolute, relative, or simple filename) * @param url resolved configuration file URL * @return resolved configuration file URI * @throws URISyntaxException if specified URL is invalid * @throws IOException on failure to construct file system or extract configuration file */ private static URI getConfigUri(final String path, final URL url) throws URISyntaxException, IOException { URI uri = url.toURI(); if ("jar".equals(uri.getScheme())) { try { FileSystems.newFileSystem(uri, Collections.emptyMap()); } catch (FileSystemAlreadyExistsException eaten) { LOGGER.warn("Specified file system already exists: {}", eaten.getMessage()); } String outputDir = PathUtils.getBaseDir(); File outputFile = new File(outputDir, path); Path outputPath = outputFile.toPath(); if (!outputPath.toFile().exists()) { Files.copy(Paths.get(uri), outputPath); } uri = outputPath.toUri(); } return uri; } /** * Get fully-qualified names of context classes for Selenium Grid dependencies. * * @return context class names for Selenium Grid dependencies */ public String[] getDependencyContexts() { String gridLauncher = getString(SeleniumSettings.GRID_LAUNCHER.key()); if (gridLauncher != null) { String dependencies = getString(SeleniumSettings.LAUNCHER_DEPS.key()); if (dependencies != null) { return (gridLauncher + File.pathSeparator + dependencies).split(File.pathSeparator); } else { return new String[] { gridLauncher }; } } else { return new String[] {}; } } /** * Create hub configuration file. * * @return {@link Path} object for the created (or previously existing) configuration file * @throws IOException on failure to create configuration file */ public abstract Path createHubConfig() throws IOException; /** * Create node configuration file from the specified JSON string, to be registered with the indicated hub. * * @param capabilities node configuration as JSON string * @param hubUrl URL of hub host with which to register * @return {@link Path} object for the created (or previously existing) configuration file * @throws IOException on failure to create configuration file */ public abstract Path createNodeConfig(String capabilities, URL hubUrl) throws IOException; /** * Get the collection of servlets to install on Selenium Grid hub. * * @return collection of specified hub servlets (may be empty) */ public Set getHubServlets() { Set servlets = new HashSet<>(); // get specified hub servlet classes String hubServlets = getString(SeleniumSettings.HUB_SERVLETS.key()); // if servlets are specified if (!(hubServlets == null || hubServlets.isEmpty())) { // collect servlet names, minus leading/trailing white space servlets.addAll(Arrays.asList(hubServlets.trim().split("\\s*,\\s*"))); } // if example page feature is specified if (getBoolean(SeleniumSettings.GRID_EXAMPLES.key())) { // add example page servlets to the collection servlets.add(ExamplePageServlet.class.getName()); servlets.add(FrameA_Servlet.class.getName()); servlets.add(FrameB_Servlet.class.getName()); servlets.add(FrameC_Servlet.class.getName()); servlets.add(FrameD_Servlet.class.getName()); } return servlets; } /** * Get the collection of servlets to install on Selenium Grid nodes. * * @return collection of specified node servlets (may be empty) */ public Set getNodeServlets() { Set servlets = new HashSet<>(); // get specified node servlet classes String nodeServlets = getString(SeleniumSettings.NODE_SERVLETS.key()); // if servlets are specified if (!(nodeServlets == null || nodeServlets.isEmpty())) { // collect servlet names, minus leading/trailing white space servlets.addAll(Arrays.asList(nodeServlets.trim().split("\\s*,\\s*"))); } return servlets; } /** * Get the target platform for the current test context. * * @return target platform for the current test context */ public String getContextPlatform() { return getConfig().getString(SeleniumSettings.CONTEXT_PLATFORM.key()); } /** * {@inheritDoc} */ @Override public String getSettingsPath() { return SETTINGS_FILE; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy