diff --git a/pom.xml b/pom.xml index e42a6a9a9..a86623054 100644 --- a/pom.xml +++ b/pom.xml @@ -30,6 +30,8 @@ + 1.8 + 1.8 UTF-8 UTF-8 ${project.version} diff --git a/vaadin-testbench-core/src/main/java/com/vaadin/testbench/parallel/ParallelRunner.java b/vaadin-testbench-core/src/main/java/com/vaadin/testbench/parallel/ParallelRunner.java index d2f0dc279..543f5a058 100644 --- a/vaadin-testbench-core/src/main/java/com/vaadin/testbench/parallel/ParallelRunner.java +++ b/vaadin-testbench-core/src/main/java/com/vaadin/testbench/parallel/ParallelRunner.java @@ -104,7 +104,8 @@ protected List computeTestMethods() { } if (SauceLabsIntegration.isConfiguredForSauceLabs()) { - methodCapabilities.setCapability( + SauceLabsIntegration.setSauceLabsOption( + methodCapabilities, SauceLabsIntegration.CapabilityType.NAME, method.getName()); } diff --git a/vaadin-testbench-core/src/main/java/com/vaadin/testbench/parallel/SauceLabsIntegration.java b/vaadin-testbench-core/src/main/java/com/vaadin/testbench/parallel/SauceLabsIntegration.java index 696646444..51e7fa424 100644 --- a/vaadin-testbench-core/src/main/java/com/vaadin/testbench/parallel/SauceLabsIntegration.java +++ b/vaadin-testbench-core/src/main/java/com/vaadin/testbench/parallel/SauceLabsIntegration.java @@ -10,60 +10,156 @@ package com.vaadin.testbench.parallel; import java.util.Arrays; +import java.util.HashMap; import java.util.Iterator; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.Map; + import org.openqa.selenium.remote.DesiredCapabilities; /** - * Integration methods for Sauce Labs testing used by {@link ParallelTest} + * Integration methods for Sauce Labs testing. * */ public class SauceLabsIntegration { private static final Logger logger = Logger .getLogger(SauceLabsIntegration.class.getName()); + private static final String SAUCE_DEFAULT_HUB_URL = "https://ondemand.us-west-1.saucelabs.com/wd/hub"; private static final String SAUCE_USERNAME_ENV = "SAUCE_USERNAME"; private static final String SAUCE_USERNAME_PROP = "sauce.user"; private static final String SAUCE_ACCESS_KEY_ENV = "SAUCE_ACCESS_KEY"; private static final String SAUCE_ACCESS_KEY_PROP = "sauce.sauceAccessKey"; + private static final String SAUCE_TUNNELID_PROP = "sauce.tunnelId"; + private static final String SAUCE_TUNNELID_ENV = "SAUCE_TUNNEL_ID"; + private static final String SAUCE_HUB_URL_PROP = "sauce.hubUrl"; + private static final String SAUCE_HUB_URL_ENV = "SAUCE_HUB_URL"; /** - * Sets needed desired capabilities, mainly tunnel identifier, based on the - * given sauce.options String. - * + * Sets needed desired capabilities for authentication and using the correct + * sauce tunnel (if in use). + *

+ * + * @see #getSauceUser() + * @see #getSauceAccessKey() + * @see #getSauceTunnelIdentifier() + * * @param desiredCapabilities - * DesiredCapabilities for RemoteWebDriver. Must not be null. - * @param sauceOptions - * options to be parsed and added as capabilities to the given - * DesiredCapabilities object + * the capabilities object to populate, not null */ - static void setDesiredCapabilities( + public static void setDesiredCapabilities( DesiredCapabilities desiredCapabilities) { - String sauceOptions = System.getProperty("sauce.options"); - if (sauceOptions == null || sauceOptions.isEmpty()) { - logger.log(Level.FINE, - "Null or empty sauce.options given. Ignoring."); - return; + + String username = getSauceUser(); + String accessKey = getSauceAccessKey(); + String tunnelId = getSauceTunnelIdentifier(); + + if (username != null) { + setSauceLabsOption(desiredCapabilities, "username", username); + } else { + logger.log(Level.FINE,"You can give a Sauce Labs user name using -D" + + SAUCE_USERNAME_PROP + "= or by " + + SAUCE_USERNAME_ENV + " environment variable."); + } + if (accessKey != null) { + setSauceLabsOption(desiredCapabilities, "access_key", accessKey); + } else { + logger.log(Level.FINE,"You can give a Sauce Labs access key using -D" + + SAUCE_ACCESS_KEY_PROP + "= or by " + + SAUCE_ACCESS_KEY_ENV + " environment variable."); } - String tunnelId = getTunnelIdentifier(sauceOptions, null); + if (tunnelId != null) { - desiredCapabilities.setCapability("tunnelIdentifier", tunnelId); + setSauceLabsOption(desiredCapabilities, "tunnelIdentifier", + tunnelId); + } + } + + /** + * Sets the given SauceLabs option to the given value. + *

+ * The available SauceLabs options are listed at + * https://docs.saucelabs.com/dev/test-configuration-options/. + * + * @param desiredCapabilities + * the desired capabilities object + * @param key + * the option key + * @param value + * the option value + */ + public static void setSauceLabsOption( + DesiredCapabilities desiredCapabilities, String key, Object value) { + // We always make a copy of the options because all clone/merge + // operations in + // DesiredCapability do a shallow clone + Map sauceOptions = new HashMap<>(); + Map currentOptions = getSauceLabsOptions( + desiredCapabilities); + if (currentOptions != null) { + sauceOptions.putAll(currentOptions); + } + sauceOptions.put(key, value); + + desiredCapabilities.setCapability("sauce:options", sauceOptions); + } + + private static Map getSauceLabsOptions( + DesiredCapabilities desiredCapabilities) { + return (Map) desiredCapabilities + .getCapability("sauce:options"); + } + + /** + * Gets the given SauceLabs option. + *

+ * The available SauceLabs options are listed at + * https://docs.saucelabs.com/dev/test-configuration-options/. + * + * @param desiredCapabilities + * the desired capabilities object + * @param key + * the option key + * @return the option value that was set or null + */ + public static Object getSauceLabsOption( + DesiredCapabilities desiredCapabilities, String key) { + Map sauceOptions = getSauceLabsOptions( + desiredCapabilities); + if (sauceOptions == null) { + return null; } + return sauceOptions.get(key); } /** - * @param options - * the command line options used to launch Sauce Connect - * @param defaultValue - * the default value to use for the identifier if none specified - * in the options - * @return String representing the tunnel identifier + * Gets the configured Saucelabs tunnel identifier. + *

+ * Reads from the {@value #SAUCE_TUNNELID_PROP} system property or the + * {@value #SAUCE_TUNNELID_ENV} environment variable. + *

+ * If both system property and environment variable are defined, the system + * property is used. + * + * @return the configured Saucelabs tunnel identifier or null */ - static String getTunnelIdentifier(String options, String defaultValue) { + public static String getSauceTunnelIdentifier() { + String tunnelId = getSystemPropertyOrEnv(SAUCE_TUNNELID_PROP, + SAUCE_TUNNELID_ENV); + if (tunnelId == null) { + // For backwards compatibility only + String sauceOptions = System.getProperty("sauce.options"); + tunnelId = getTunnelIdentifierFromOptions(sauceOptions); + } + + return tunnelId; + } + + private static String getTunnelIdentifierFromOptions(String options) { if (options == null || options.isEmpty()) { - return defaultValue; + return null; } Iterator tokensIterator = Arrays.asList(options.split(" ")) .iterator(); @@ -75,48 +171,65 @@ static String getTunnelIdentifier(String options, String defaultValue) { return tokensIterator.next(); } } - return defaultValue; + return null; } /** - * Returns the HubUrl for running tests in Sauce Labs tunnel. Reads required - * credentials from sauce.user and sauce.sauceAccessKey or environment - * variables SAUCE_USERNAME and SAUCE_ACCESS_KEY. If both system property - * and environment variable are defined, the system property is used. - * + * Returns the HubUrl for running tests in Sauce Labs. + *

+ * The available SauceLabs URLs are listed at + * https://docs.saucelabs.com/basics/data-center-endpoints/#data-center-endpoints. + * * @return url String to be used in Sauce Labs test run */ - static String getHubUrl() { - String username = getSauceUser(); - String accessKey = getSauceAccessKey(); - - if (username == null) { - logger.log(Level.FINE, - "You can give a Sauce Labs user name using -D" - + SAUCE_USERNAME_PROP + "= or by " - + SAUCE_USERNAME_ENV + " environment variable."); - } - if (accessKey == null) { - logger.log(Level.FINE, - "You can give a Sauce Labs access key using -D" - + SAUCE_ACCESS_KEY_PROP + "= or by " - + SAUCE_ACCESS_KEY_ENV + " environment variable."); + public static String getHubUrl() { + String hubUrl = getSystemPropertyOrEnv(SAUCE_HUB_URL_PROP, + SAUCE_HUB_URL_ENV); + if (hubUrl == null) { + hubUrl = SAUCE_DEFAULT_HUB_URL; } - return "http://" + username + ":" + accessKey - + "@localhost:4445/wd/hub"; + return hubUrl; } - static boolean isConfiguredForSauceLabs() { + /** + * Checks if parameters needed to run in Saucelabs have been set. + * + * @return true if the Saucelabs configuration was found + */ + public static boolean isConfiguredForSauceLabs() { String user = getSauceUser(); String accessKey = getSauceAccessKey(); - return user != null && !user.isEmpty() && accessKey != null && !accessKey.isEmpty(); + return user != null && !user.isEmpty() && accessKey != null + && !accessKey.isEmpty(); } - static String getSauceUser() { + /** + * Gets the configured Saucelabs user name. + *

+ * Reads from the {@value #SAUCE_USERNAME_PROP} system property or the + * {@value #SAUCE_USERNAME_ENV} environment variable. + *

+ * If both system property and environment variable are defined, the system + * property is used. + * + * @return the configured Saucelabs user name or null + */ + public static String getSauceUser() { return getSystemPropertyOrEnv(SAUCE_USERNAME_PROP, SAUCE_USERNAME_ENV); } - static String getSauceAccessKey() { + /** + * Gets the configured Saucelabs access key. + *

+ * Reads from the {@value #SAUCE_ACCESS_KEY_PROP} system property or the + * {@value #SAUCE_ACCESS_KEY_ENV} environment variable. + *

+ * If both system property and environment variable are defined, the system + * property is used. + * + * @return the configured Saucelabs access key or null + */ + public static String getSauceAccessKey() { return getSystemPropertyOrEnv(SAUCE_ACCESS_KEY_PROP, SAUCE_ACCESS_KEY_ENV); } diff --git a/vaadin-testbench-core/src/test/java/com/vaadin/testbench/parallel/JobNameCapabilitiesTest.java b/vaadin-testbench-core/src/test/java/com/vaadin/testbench/parallel/JobNameCapabilitiesTest.java index 8557b3b39..ae397c9b1 100644 --- a/vaadin-testbench-core/src/test/java/com/vaadin/testbench/parallel/JobNameCapabilitiesTest.java +++ b/vaadin-testbench-core/src/test/java/com/vaadin/testbench/parallel/JobNameCapabilitiesTest.java @@ -30,9 +30,14 @@ public void tbMethodNameInCapabilities() throws InitializationError { List testMethods = parallelRunner.computeTestMethods(); Assert.assertEquals(4, testMethods.size()); for (FrameworkMethod testMethod : testMethods) { - Assert.assertEquals(testMethod.getName(), - ((TBMethod) testMethod).getCapabilities().getCapability( - SauceLabsIntegration.CapabilityType.NAME)); + DesiredCapabilities cap = ((TBMethod) testMethod).getCapabilities(); + Assert.assertEquals("bar", + SauceLabsIntegration.getSauceLabsOption(cap, "foo")); + if (SauceLabsIntegration.isConfiguredForSauceLabs()) { + Assert.assertEquals(testMethod.getName(), + SauceLabsIntegration.getSauceLabsOption(cap, + SauceLabsIntegration.CapabilityType.NAME)); + } } } @@ -58,8 +63,13 @@ public void dummy2() { @BrowserConfiguration public List getBrowsers() { - return Arrays.asList(Browser.CHROME.getDesiredCapabilities(), + List caps = Arrays.asList( + Browser.CHROME.getDesiredCapabilities(), Browser.FIREFOX.getDesiredCapabilities()); + for (DesiredCapabilities cap : caps) { + SauceLabsIntegration.setSauceLabsOption(cap, "foo", "bar"); + } + return caps; } } } diff --git a/vaadin-testbench-core/src/test/java/com/vaadin/testbench/parallel/ParallelHubTest.java b/vaadin-testbench-core/src/test/java/com/vaadin/testbench/parallel/ParallelHubTest.java index 0810acf71..bea68a150 100644 --- a/vaadin-testbench-core/src/test/java/com/vaadin/testbench/parallel/ParallelHubTest.java +++ b/vaadin-testbench-core/src/test/java/com/vaadin/testbench/parallel/ParallelHubTest.java @@ -44,24 +44,4 @@ public void hubFromAnnotationOrSystemProperty() { } } - @Test - public void sauceURLFromSystemProperty() { - String oldUser = System.getProperty(SAUCE_USER_PROPERTY); - String oldAccess = System.getProperty(SAUCE_ACCESS_KEY_PROPERTY); - try { - System.setProperty(SAUCE_USER_PROPERTY, "user1234"); - System.setProperty(SAUCE_ACCESS_KEY_PROPERTY, "access1234"); - - Assert.assertEquals( - "http://user1234:access1234@localhost:4445/wd/hub", - getHubURL()); - } finally { - if (oldUser != null) { - System.setProperty(SAUCE_USER_PROPERTY, oldUser); - } - if (oldAccess != null) { - System.setProperty(SAUCE_ACCESS_KEY_PROPERTY, oldAccess); - } - } - } } diff --git a/vaadin-testbench-integration-tests/pom.xml b/vaadin-testbench-integration-tests/pom.xml index 381763230..35c605fc5 100644 --- a/vaadin-testbench-integration-tests/pom.xml +++ b/vaadin-testbench-integration-tests/pom.xml @@ -23,9 +23,6 @@ v8.1.2 v0.27.5 build-tools - --tunnel-identifier ${maven.build.timestamp} - 1.151 - yyyy-MM-dd'T'HHmmss.SSSZ false @@ -140,11 +137,6 @@ - - ${sauce.user} - ${sauce.sauceAccessKey} - ${sauce.options} - false @@ -182,43 +174,6 @@ - - com.saucelabs.maven.plugin - sauce-connect-plugin - 2.1.25 - - ${sauce.user} - ${sauce.sauceAccessKey} - ${sauce.options} - - - - com.saucelabs - ci-sauce - ${ci-sauce.version} - - - - - - start-sauceconnect - pre-integration-test - - start-sauceconnect - - - - - stop-sauceconnect - post-integration-test - - stop-sauceconnect - - - - org.codehaus.mojo properties-maven-plugin diff --git a/vaadin-testbench-integration-tests/reference-screenshots/button4_windows_chrome_107.png b/vaadin-testbench-integration-tests/reference-screenshots/button4_windows_chrome_107.png new file mode 100644 index 000000000..f993b5018 Binary files /dev/null and b/vaadin-testbench-integration-tests/reference-screenshots/button4_windows_chrome_107.png differ diff --git a/vaadin-testbench-integration-tests/reference-screenshots/button4_windows_chrome_83.png b/vaadin-testbench-integration-tests/reference-screenshots/button4_windows_chrome_83.png deleted file mode 100644 index c457b84d3..000000000 Binary files a/vaadin-testbench-integration-tests/reference-screenshots/button4_windows_chrome_83.png and /dev/null differ diff --git a/vaadin-testbench-integration-tests/reference-screenshots/layout_windows_chrome_107.png b/vaadin-testbench-integration-tests/reference-screenshots/layout_windows_chrome_107.png new file mode 100644 index 000000000..a6a43f0ec Binary files /dev/null and b/vaadin-testbench-integration-tests/reference-screenshots/layout_windows_chrome_107.png differ diff --git a/vaadin-testbench-integration-tests/reference-screenshots/layout_windows_chrome_83.png b/vaadin-testbench-integration-tests/reference-screenshots/layout_windows_chrome_83.png deleted file mode 100644 index c8cae1a7b..000000000 Binary files a/vaadin-testbench-integration-tests/reference-screenshots/layout_windows_chrome_83.png and /dev/null differ diff --git a/vaadin-testbench-integration-tests/src/test/java/com/vaadin/tests/TB6TestBrowserFactory.java b/vaadin-testbench-integration-tests/src/test/java/com/vaadin/tests/TB6TestBrowserFactory.java index 2912ecd17..a547765a5 100644 --- a/vaadin-testbench-integration-tests/src/test/java/com/vaadin/tests/TB6TestBrowserFactory.java +++ b/vaadin-testbench-integration-tests/src/test/java/com/vaadin/tests/TB6TestBrowserFactory.java @@ -24,6 +24,7 @@ import com.vaadin.testbench.parallel.Browser; import com.vaadin.testbench.parallel.DefaultBrowserFactory; +import com.vaadin.testbench.parallel.SauceLabsIntegration; /** * Specifies default browser configuration for {@link AbstractTB6Test} @@ -42,6 +43,11 @@ public class TB6TestBrowserFactory extends DefaultBrowserFactory { @Override public DesiredCapabilities create(Browser browser, String version, Platform platform) { + + if (browser != Browser.SAFARI) { + platform = Platform.WIN10; + } + DesiredCapabilities desiredCapabilities = super.create(browser, version, platform); @@ -51,7 +57,8 @@ public DesiredCapabilities create(Browser browser, String version, if(browser.equals(Browser.FIREFOX)) { desiredCapabilities.setCapability(FirefoxDriver.MARIONETTE, false); } - desiredCapabilities.setCapability("screenResolution", "1600x1200"); + SauceLabsIntegration.setSauceLabsOption(desiredCapabilities, + "screenResolution", "1600x1200"); return desiredCapabilities; } }