diff --git a/src/main/java/com/xceptance/neodymium/common/browser/BrowserRunnerHelper.java b/src/main/java/com/xceptance/neodymium/common/browser/BrowserRunnerHelper.java index 8c7f884c1..059dd1529 100644 --- a/src/main/java/com/xceptance/neodymium/common/browser/BrowserRunnerHelper.java +++ b/src/main/java/com/xceptance/neodymium/common/browser/BrowserRunnerHelper.java @@ -23,7 +23,6 @@ import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.chrome.ChromeDriverService; import org.openqa.selenium.chrome.ChromeOptions; import org.openqa.selenium.firefox.FirefoxBinary; import org.openqa.selenium.firefox.FirefoxDriver; @@ -31,9 +30,7 @@ import org.openqa.selenium.firefox.FirefoxProfile; import org.openqa.selenium.firefox.GeckoDriverService; import org.openqa.selenium.ie.InternetExplorerDriver; -import org.openqa.selenium.ie.InternetExplorerDriverService; import org.openqa.selenium.ie.InternetExplorerOptions; -import org.openqa.selenium.os.ExecutableFinder; import org.openqa.selenium.remote.CapabilityType; import org.openqa.selenium.remote.HttpCommandExecutor; import org.openqa.selenium.remote.RemoteWebDriver; @@ -181,7 +178,7 @@ private static FirefoxBinary createFirefoxBinary(final String pathToBrowser) * if Selenium grid is * used and the given grid URL is invalid */ - public static WebDriverStateContainer createWebDriverStateContainer(final BrowserConfiguration config, final Object testClassInstance) + public static WebDriverStateContainer createWebDriverStateContainer(final BrowserConfiguration config, Object testClassInstance) throws MalformedURLException { final MutableCapabilities capabilities = config.getCapabilities(); @@ -189,7 +186,7 @@ public static WebDriverStateContainer createWebDriverStateContainer(final Browse SelenideProxyServer selenideProxyServer = null; if (Neodymium.configuration().useLocalProxy()) { - final BrowserUpProxy proxy = setupEmbeddedProxy(); + BrowserUpProxy proxy = setupEmbeddedProxy(); // set the Proxy for later usage wDSC.setProxy(proxy); @@ -206,17 +203,16 @@ else if (Neodymium.configuration().useProxy()) { if (Neodymium.configuration().enableSelenideProxy()) { - final SelenideProxyServerFactory selenideProxyServerFactory = Plugins.inject(SelenideProxyServerFactory.class); + SelenideProxyServerFactory selenideProxyServerFactory = Plugins.inject(SelenideProxyServerFactory.class); selenideProxyServer = selenideProxyServerFactory.create(new SelenideConfig(), (Proxy) capabilities.getCapability(CapabilityType.PROXY)); - final var proxy = selenideProxyServer.getSeleniumProxy(); + var proxy = selenideProxyServer.getSeleniumProxy(); capabilities.setCapability(CapabilityType.PROXY, proxy); } final String browserName = capabilities.getBrowserName(); if (chromeBrowsers.contains(browserName)) { - final ChromeOptions options = new ChromeOptions(); - final String driverInPathPath = new ExecutableFinder().find("chromedriver"); + final ChromeOptions options = (ChromeOptions) capabilities; // do we have a custom path? final String pathToBrowser = Neodymium.configuration().getChromeBrowserPath(); @@ -238,10 +234,9 @@ else if (Neodymium.configuration().useProxy()) options.setExperimentalOption("prefs", config.getPreferences()); } - if ((config.getPreferences() != null && !config.getPreferences().isEmpty()) || - StringUtils.isNotBlank(config.getDownloadDirectory())) + if ((config.getPreferences() != null && !config.getPreferences().isEmpty()) || StringUtils.isNotBlank(config.getDownloadDirectory())) { - final HashMap prefs = new HashMap<>(); + HashMap prefs = new HashMap<>(); // if we have configured prefs, we need to add all to the experimental options if (config.getPreferences() != null && !config.getPreferences().isEmpty()) @@ -257,14 +252,12 @@ else if (Neodymium.configuration().useProxy()) options.setExperimentalOption("prefs", prefs); } - wDSC.setWebDriver(new ChromeDriver(new ChromeDriverService.Builder() - .usingDriverExecutable(new File(driverInPathPath)) - .build(), options.merge(capabilities))); + + wDSC.setWebDriver(new ChromeDriver(options)); } else if (firefoxBrowsers.contains(browserName)) { - final FirefoxOptions options = new FirefoxOptions(); - final String driverInPathPath = new ExecutableFinder().find("geckodriver"); + final FirefoxOptions options = new FirefoxOptions().merge(capabilities); options.setBinary(createFirefoxBinary(Neodymium.configuration().getFirefoxBrowserPath())); if (config.isHeadless()) { @@ -274,10 +267,9 @@ else if (firefoxBrowsers.contains(browserName)) { options.addArguments(config.getArguments()); } - if ((config.getPreferences() != null && !config.getPreferences().isEmpty()) || - StringUtils.isNotBlank(config.getDownloadDirectory())) + if ((config.getPreferences() != null && !config.getPreferences().isEmpty()) || StringUtils.isNotBlank(config.getDownloadDirectory())) { - final FirefoxProfile profile = new FirefoxProfile(); + FirefoxProfile profile = new FirefoxProfile(); // if we have configured prefs, we need to add all to the experimental options if (config.getPreferences() != null && !config.getPreferences().isEmpty()) @@ -310,52 +302,45 @@ else if (StringUtils.isNumeric(val.toString())) options.setProfile(profile); } - wDSC.setWebDriver(new FirefoxDriver(new GeckoDriverService.Builder().withAllowHosts("localhost") - .usingDriverExecutable(new File(driverInPathPath)) - .build(), options.merge(capabilities))); + wDSC.setWebDriver(new FirefoxDriver(new GeckoDriverService.Builder().withAllowHosts("localhost").build(), options)); } else if (internetExplorerBrowsers.contains(browserName)) { - final InternetExplorerOptions options = new InternetExplorerOptions(); - final String driverInPathPath = new ExecutableFinder().find("IEDriverServer"); + final InternetExplorerOptions options = new InternetExplorerOptions().merge(capabilities); if (config.getArguments() != null && config.getArguments().size() > 0) { - for (final String argument : config.getArguments()) + for (String argument : config.getArguments()) { options.addCommandSwitches(argument); } } - wDSC.setWebDriver(new InternetExplorerDriver(new InternetExplorerDriverService.Builder() - .usingDriverExecutable(new File(driverInPathPath)) - .build(), options.merge(capabilities))); + wDSC.setWebDriver(new InternetExplorerDriver(options)); } else if (safariBrowsers.contains(browserName)) { - // safari driver is not expected to be in PATH, it will be looked in - // /usr/bin/safaridriver and /Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver - final SafariOptions options = new SafariOptions(); + final SafariOptions options = (SafariOptions) capabilities; wDSC.setWebDriver(new SafariDriver(options)); } else { - wDSC.setWebDriver(new RemoteWebDriver(capabilities.merge(capabilities))); + wDSC.setWebDriver(new RemoteWebDriver(capabilities)); } } else { // establish connection to target website - final TestEnvironment testEnvironmentProperties = MultibrowserConfiguration.getInstance().getTestEnvironment(testEnvironment); + TestEnvironment testEnvironmentProperties = MultibrowserConfiguration.getInstance().getTestEnvironment(testEnvironment); if (testEnvironmentProperties == null) { throw new IllegalArgumentException("No properties found for test environment: \"" + testEnvironment + "\""); } - final String testEnvironmentUrl = testEnvironmentProperties.getUrl(); + String testEnvironmentUrl = testEnvironmentProperties.getUrl(); ClientConfig configClient = ClientConfig.defaultConfig(); configClient = configClient.baseUrl(new URL(testEnvironmentUrl)); config.getGridProperties().put("userName", testEnvironmentProperties.getUsername()); config.getGridProperties().put("accessKey", testEnvironmentProperties.getPassword()); - final String buildId = StringUtils.isBlank(System.getenv("BUILD_NUMBER")) ? "local run" : System.getenv("BUILD_NUMBER"); + String buildId = StringUtils.isBlank(System.getenv("BUILD_NUMBER")) ? "local run" : System.getenv("BUILD_NUMBER"); config.getGridProperties().put("sessionName", testClassInstance.getClass().toString()); config.getGridProperties().put("buildName", "Test Automation"); config.getGridProperties().put("buildIdentifier", buildId); @@ -369,10 +354,10 @@ else if (testEnvironmentUrl.contains("saucelabs")) } else { - final String optionsTag = testEnvironmentProperties.getOptionsTag(); + String optionsTag = testEnvironmentProperties.getOptionsTag(); if (StringUtils.isBlank(optionsTag)) { - for (final String key : config.getGridProperties().keySet()) + for (String key : config.getGridProperties().keySet()) { capabilities.setCapability(key, config.getGridProperties().get(key)); } @@ -384,7 +369,7 @@ else if (testEnvironmentUrl.contains("saucelabs")) } wDSC.setWebDriver(new RemoteWebDriver(new HttpCommandExecutor(new HashMap<>(), configClient, new NeodymiumProxyHttpClientFactory(testEnvironmentProperties)), capabilities)); } - final WebDriver decoratedDriver = new EventFiringDecorator(new NeodymiumWebDriverListener()).decorate(wDSC.getWebDriver()); + WebDriver decoratedDriver = new EventFiringDecorator(new NeodymiumWebDriverListener()).decorate(wDSC.getWebDriver()); wDSC.setDecoratedWebDriver(decoratedDriver); WebDriverRunner.setWebDriver(decoratedDriver, selenideProxyServer); return wDSC; @@ -398,8 +383,7 @@ private static BrowserUpProxy setupEmbeddedProxy() if (Neodymium.configuration().useLocalProxyWithSelfSignedCertificate()) { final CertificateAndKeySource rootCertificateSource = createLocalProxyRootCertSource(); - final ImpersonatingMitmManager mitmManager = ImpersonatingMitmManager.builder().rootCertificateSource(rootCertificateSource) - .build(); + final ImpersonatingMitmManager mitmManager = ImpersonatingMitmManager.builder().rootCertificateSource(rootCertificateSource).build(); proxy.setMitmManager(mitmManager); } else @@ -467,10 +451,8 @@ public static Proxy createProxyCapabilities() final Proxy webdriverProxy = new Proxy(); webdriverProxy.setHttpProxy(proxyHost); webdriverProxy.setSslProxy(proxyHost); - if (!StringUtils.isAllEmpty(Neodymium.configuration().getProxySocketUsername(), - Neodymium.configuration().getProxySocketPassword()) - || - Neodymium.configuration().getProxySocketVersion() != null) + if (!StringUtils.isAllEmpty(Neodymium.configuration().getProxySocketUsername(), Neodymium.configuration().getProxySocketPassword()) + || Neodymium.configuration().getProxySocketVersion() != null) { webdriverProxy.setSocksProxy(proxyHost); if (StringUtils.isNoneEmpty(Neodymium.configuration().getProxySocketUsername(), @@ -501,12 +483,11 @@ private static String popularContentTypes() { try { - final List popularContentTypes = IOUtils.readLines(BrowserConfigurationMapper.class.getResourceAsStream("/content-types.properties"), - UTF_8); + List popularContentTypes = IOUtils.readLines(BrowserConfigurationMapper.class.getResourceAsStream("/content-types.properties"), UTF_8); popularContentTypes.add("application/x-download"); return String.join(";", popularContentTypes); } - catch (final Exception e) + catch (Exception e) { return "text/plain;text/csv;application/zip;application/pdf;application/octet-stream;" + "application/msword;application/vnd.ms-excel;text/css;text/html"; diff --git a/src/main/java/com/xceptance/neodymium/util/NeoWaitTime.java b/src/main/java/com/xceptance/neodymium/util/NeoWaitTime.java new file mode 100644 index 000000000..71def92d9 --- /dev/null +++ b/src/main/java/com/xceptance/neodymium/util/NeoWaitTime.java @@ -0,0 +1,67 @@ +package com.xceptance.neodymium.util; + +import java.util.Map; + +import com.codeborne.selenide.Selenide; + +public class NeoWaitTime +{ + private final int standardWait, shortWait, doubleWait, longWait; + + private final Map customWaitTimeMap; + + private static NeoWaitTime INSTANCE; + + private NeoWaitTime() { + this.standardWait = Neodymium.configuration().getStandardWaitTime(); + this.shortWait = Neodymium.configuration().getShortWaitTime(); + this.doubleWait = Neodymium.configuration().getDoubleWaitTime(); + this.longWait = Neodymium.configuration().getLongWaitTime(); + this.customWaitTimeMap = PropertiesUtil.getPropertiesMapForCustomIdentifier("neodymium.waitTime.custom"); + } + + public static void waitStandardWaitTime() + { + if (INSTANCE == null) + { + INSTANCE = new NeoWaitTime(); + } + Selenide.sleep(INSTANCE.standardWait); + } + + public static void waitShortWaitTime() + { + if (INSTANCE == null) + { + INSTANCE = new NeoWaitTime(); + } + Selenide.sleep(INSTANCE.shortWait); + } + + public static void waitDoubleWaitTime() + { + if (INSTANCE == null) + { + INSTANCE = new NeoWaitTime(); + } + Selenide.sleep(INSTANCE.doubleWait); + } + + public static void waitLongWaitTime() + { + if (INSTANCE == null) + { + INSTANCE = new NeoWaitTime(); + } + Selenide.sleep(INSTANCE.longWait); + } + + public static void waitCustomWaitTime(String key) + { + if (INSTANCE == null) + { + INSTANCE = new NeoWaitTime(); + } + Selenide.sleep(Integer.valueOf(INSTANCE.customWaitTimeMap.get(key))); + } +} diff --git a/src/main/java/com/xceptance/neodymium/util/NeodymiumConfiguration.java b/src/main/java/com/xceptance/neodymium/util/NeodymiumConfiguration.java index a6d4a7bee..05e411966 100644 --- a/src/main/java/com/xceptance/neodymium/util/NeodymiumConfiguration.java +++ b/src/main/java/com/xceptance/neodymium/util/NeodymiumConfiguration.java @@ -267,4 +267,20 @@ public interface NeodymiumConfiguration extends Mutable @Key("neodymium.logNeoVersion") @DefaultValue("true") public boolean logNeoVersion(); + + @Key("neodymium.waitTime.standard") + @DefaultValue("100") + public int getStandardWaitTime(); + + @Key("neodymium.waitTime.short") + @DefaultValue("50") + public int getShortWaitTime(); + + @Key("neodymium.waitTime.double") + @DefaultValue("200") + public int getDoubleWaitTime(); + + @Key("neodymium.waitTime.long") + @DefaultValue("500") + public int getLongWaitTime(); } diff --git a/src/main/java/com/xceptance/neodymium/util/PropertiesUtil.java b/src/main/java/com/xceptance/neodymium/util/PropertiesUtil.java new file mode 100644 index 000000000..fe8f49134 --- /dev/null +++ b/src/main/java/com/xceptance/neodymium/util/PropertiesUtil.java @@ -0,0 +1,129 @@ +package com.xceptance.neodymium.util; + +import java.io.File; +import java.io.FileInputStream; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Properties; +import java.util.Set; + +import org.aeonbits.owner.ConfigFactory; +import org.apache.commons.lang3.StringUtils; + +public class PropertiesUtil +{ + public static Set getSubkeysForPrefix(Properties properties, String prefix) + { + Set keys = new HashSet(); + + for (Object key : properties.keySet()) + { + String keyString = (String) key; + if (keyString.toLowerCase().startsWith(prefix.toLowerCase())) + { + // cut off prefix + keyString = keyString.substring(prefix.length()); + + // split on the next dots + String[] split = keyString.split("\\."); + if (split != null && split.length > 0) + { + // the first entry in the resulting array will be the key we are searching for + String newKey = split[0]; + if (StringUtils.isNotBlank(newKey)) + { + keys.add(newKey); + } + } + } + } + + return keys; + } + + public static void loadPropertiesFromFile(String path, Properties properties) + { + try + { + File source = new File(path); + if (source.exists()) + { + FileInputStream fileInputStream = new FileInputStream(source); + properties.load(fileInputStream); + fileInputStream.close(); + } + } + catch (Exception e) + { + throw new RuntimeException(e); + } + } + + public static Map getDataMapForIdentifier(String identifier, Properties properties) + { + Map resultMap = new HashMap(); + for (Entry entry : properties.entrySet()) + { + String key = (String) entry.getKey(); + if (key.contains(identifier)) + { + String cleanedKey = key.replace(identifier, ""); + cleanedKey = cleanedKey.replaceAll("\\.", ""); + resultMap.put(cleanedKey, (String) entry.getValue()); + } + } + return resultMap; + } + + public static Map mapPutAllIfAbsent(Map map, Map changeSet) + { + if (!changeSet.isEmpty()) + { + for (Entry entry : changeSet.entrySet()) + { + map.putIfAbsent(entry.getKey(), entry.getValue()); + } + } + return map; + } + + public static Map addMissingPropertiesFromFile(String fileLocation, String identifier, Map dataMap) + { + Properties properties = new Properties(); + PropertiesUtil.loadPropertiesFromFile(fileLocation, properties); + return PropertiesUtil.mapPutAllIfAbsent(dataMap, + PropertiesUtil.getDataMapForIdentifier(identifier, + properties)); + } + + public static Map getPropertiesMapForCustomIdentifier(String customIdentifier) + { + Map dataMap = new HashMap(); + dataMap = PropertiesUtil.addMissingPropertiesFromFile("./config/dev-neodymium.properties", customIdentifier, dataMap); + + Map systemEnvMap = new HashMap(); + for (Map.Entry entry : System.getenv().entrySet()) + { + String key = (String) entry.getKey(); + if (key.contains(customIdentifier)) + { + String cleanedKey = key.replace(customIdentifier, ""); + cleanedKey = cleanedKey.replaceAll("\\.", ""); + systemEnvMap.put(cleanedKey, (String) entry.getValue()); + } + } + dataMap = PropertiesUtil.mapPutAllIfAbsent(dataMap, systemEnvMap); + dataMap = PropertiesUtil.mapPutAllIfAbsent(dataMap, + PropertiesUtil.getDataMapForIdentifier(customIdentifier, + System.getProperties())); + dataMap = PropertiesUtil.addMissingPropertiesFromFile("./config/credentials.properties", customIdentifier, dataMap); + dataMap = PropertiesUtil.addMissingPropertiesFromFile("./config/neodymium.properties", customIdentifier, dataMap); + dataMap = PropertiesUtil.addMissingPropertiesFromFile(ConfigFactory.getProperty(Neodymium.TEMPORARY_CONFIG_FILE_PROPERTY_NAME) + .replaceAll("file:", "./"), + customIdentifier, + dataMap); + return dataMap; + } +} \ No newline at end of file