diff --git a/docker/Dockerfile b/docker/Dockerfile index d4aa23c499..588f59a4c9 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -291,8 +291,8 @@ RUN set -x \ # Sauce Connect Tunneling # # ------------------------# # https://docs.saucelabs.com/reference/sauce-connect/ -# Layer size: medium: 12.42 MB -ENV SAUCE_CONN_VER="sc-4.4.4-linux" \ +# Layer size: medium: ~13 MB +ENV SAUCE_CONN_VER="sc-4.4.5-linux" \ SAUCE_CONN_DOWN_URL="https://saucelabs.com/downloads" RUN cd /tmp \ && wget -nv "${SAUCE_CONN_DOWN_URL}/${SAUCE_CONN_VER}.tar.gz" \ diff --git a/docs/usage_examples.md b/docs/usage_examples.md index 72f828e847..b680538018 100644 --- a/docs/usage_examples.md +++ b/docs/usage_examples.md @@ -25,6 +25,7 @@ * [Test name](#test-name) * [Group name](#group-name) * [Idle Timeout](#idle-timeout) + * [Screen resolution](#screen-resolution) ## Initial setup @@ -246,4 +247,16 @@ capability in your test. Example code in Java for the capability (it sets the `i desiredCapabilities.setCapability("idleTimeout", 150); ``` +### Screen resolution +You can pass a custom screen resolution for your test, just include a `screenResolution` with the desired value. E.g. +`screenResolution=1280x1024`. Also supported for the same purpose `resolution` and `screen-resolution`. Example code +in Java for the capability `screenResolution` + + ```java + DesiredCapabilities desiredCapabilities = new DesiredCapabilities(); + desiredCapabilities.setCapability(CapabilityType.BROWSER_NAME, BrowserType.FIREFOX); + desiredCapabilities.setCapability(CapabilityType.PLATFORM, Platform.LINUX); + desiredCapabilities.setCapability("screenResolution", "1280x720"); + ``` + diff --git a/pom.xml b/pom.xml index e06368ed23..ce03c516ec 100644 --- a/pom.xml +++ b/pom.xml @@ -52,10 +52,10 @@ 0 8.1.2 4.12 - 2.7.17 + 2.7.18 2.0.0 6.11 - 1.7.24 + 1.7.25 2.19.1 1.8 1.8 diff --git a/src/main/java/de/zalando/tip/zalenium/proxy/DockerSeleniumRemoteProxy.java b/src/main/java/de/zalando/tip/zalenium/proxy/DockerSeleniumRemoteProxy.java index b86230b025..f4ba5eba0d 100644 --- a/src/main/java/de/zalando/tip/zalenium/proxy/DockerSeleniumRemoteProxy.java +++ b/src/main/java/de/zalando/tip/zalenium/proxy/DockerSeleniumRemoteProxy.java @@ -18,6 +18,7 @@ import org.openqa.grid.internal.SessionTerminationReason; import org.openqa.grid.internal.TestSession; import org.openqa.grid.internal.TestSlot; +import org.openqa.grid.internal.utils.CapabilityMatcher; import org.openqa.grid.selenium.proxy.DefaultRemoteProxy; import org.openqa.grid.web.servlet.handler.RequestType; import org.openqa.grid.web.servlet.handler.WebDriverRequest; @@ -64,6 +65,7 @@ public class DockerSeleniumRemoteProxy extends DefaultRemoteProxy { private boolean stopSessionRequestReceived = false; private DockerSeleniumNodePoller dockerSeleniumNodePollerThread = null; private GoogleAnalyticsApi ga = new GoogleAnalyticsApi(); + private CapabilityMatcher capabilityHelper; public DockerSeleniumRemoteProxy(RegistrationRequest request, Registry registry) { super(request, registry); @@ -136,6 +138,14 @@ public TestSession getNewSession(Map requestedCapability) { return null; } + @Override + public CapabilityMatcher getCapabilityHelper() { + if (capabilityHelper == null) { + capabilityHelper = new DockerSeleniumCapabilityMatcher(this); + } + return capabilityHelper; + } + private long getConfiguredIdleTimeout(Map requestedCapability) { long configuredIdleTimeout; try { @@ -332,7 +342,7 @@ void copyVideos(final String containerId) throws IOException, DockerException, I IOUtils.copy(tarStream, outputStream); outputStream.close(); Dashboard.updateDashboard(testInformation); - LOGGER.log(Level.INFO, "{0} Video files copies to: {1}", new Object[]{getId(), + LOGGER.log(Level.INFO, "{0} Video files copied to: {1}", new Object[]{getId(), testInformation.getVideoFolderPath()}); } } catch (Exception e) { @@ -399,6 +409,8 @@ public void run() { "thread, stopping thread execution.", e); Thread.currentThread().interrupt(); dockerSeleniumRemoteProxy.ga.trackException(e); + dockerSeleniumRemoteProxy.stopPolling(); + dockerSeleniumRemoteProxy.startPolling(); return; } } diff --git a/src/main/java/de/zalando/tip/zalenium/proxy/DockerSeleniumStarterRemoteProxy.java b/src/main/java/de/zalando/tip/zalenium/proxy/DockerSeleniumStarterRemoteProxy.java index 2b2448db03..dc36f278d4 100644 --- a/src/main/java/de/zalando/tip/zalenium/proxy/DockerSeleniumStarterRemoteProxy.java +++ b/src/main/java/de/zalando/tip/zalenium/proxy/DockerSeleniumStarterRemoteProxy.java @@ -81,7 +81,9 @@ public class DockerSeleniumStarterRemoteProxy extends DefaultRemoteProxy impleme private static int firefoxContainersOnStartup; private static int maxDockerSeleniumContainers; private static String timeZone; + private static int configuredScreenWidth; private static int screenWidth; + private static int configuredScreenHeight; private static int screenHeight; private static String containerName; private List allocatedPorts = new ArrayList<>(); @@ -110,9 +112,11 @@ private static void readConfigurationFromEnvVariables() { int sWidth = env.getIntEnvVariable(ZALENIUM_SCREEN_WIDTH, DEFAULT_SCREEN_WIDTH); setScreenWidth(sWidth); + setConfiguredScreenWidth(sWidth); int sHeight = env.getIntEnvVariable(ZALENIUM_SCREEN_HEIGHT, DEFAULT_SCREEN_HEIGHT); setScreenHeight(sHeight); + setConfiguredScreenHeight(sHeight); String tz = env.getStringEnvVariable(ZALENIUM_TZ, DEFAULT_TZ); setTimeZone(tz); @@ -263,6 +267,22 @@ protected static void setScreenHeight(int screenHeight) { DockerSeleniumStarterRemoteProxy.screenHeight = screenHeight <= 0 ? DEFAULT_SCREEN_HEIGHT : screenHeight; } + public static int getConfiguredScreenWidth() { + return configuredScreenWidth <= 0 ? DEFAULT_SCREEN_WIDTH : configuredScreenWidth; + } + + public static void setConfiguredScreenWidth(int configuredScreenWidth) { + DockerSeleniumStarterRemoteProxy.configuredScreenWidth = configuredScreenWidth; + } + + public static int getConfiguredScreenHeight() { + return configuredScreenHeight <= 0 ? DEFAULT_SCREEN_HEIGHT : configuredScreenHeight; + } + + public static void setConfiguredScreenHeight(int configuredScreenHeight) { + DockerSeleniumStarterRemoteProxy.configuredScreenHeight = configuredScreenHeight; + } + @VisibleForTesting protected static void setEnv(final Environment env) { DockerSeleniumStarterRemoteProxy.env = env; @@ -308,14 +328,37 @@ public TestSession getNewSession(Map requestedCapability) { return null; } - LOGGER.log(Level.INFO, LOGGING_PREFIX + "Starting new node for {0}.", requestedCapability); + // Check and configure specific screen resolution capabilities when they have been passed in the test config. + configureScreenResolutionFromCapabilities(requestedCapability); String browserName = requestedCapability.get(CapabilityType.BROWSER_NAME).toString(); /* Here a docker-selenium container will be started and it will register to the hub + We check first if a node has been created for this request already. If so, we skip it + but increment the number of times it has been received. In case something went wrong with the node + creation, we remove the mark* after 10 times and we create a node again. + * The mark is an added custom capability */ - startDockerSeleniumContainer(browserName); + String waitingForNode = String.format("waitingFor_%s_Node", browserName.toUpperCase()); + if (!requestedCapability.containsKey(waitingForNode)) { + LOGGER.log(Level.INFO, LOGGING_PREFIX + "Starting new node for {0}.", requestedCapability); + if (startDockerSeleniumContainer(browserName)) { + requestedCapability.put(waitingForNode, 1); + } + } else { + int attempts = (int) requestedCapability.get(waitingForNode); + attempts++; + if (attempts >= 20) { + LOGGER.log(Level.INFO, LOGGING_PREFIX + "Request has waited 20 attempts for a node, something " + + "went wrong with the previous attempts, creating a new node for {0}.", requestedCapability); + startDockerSeleniumContainer(browserName, true); + requestedCapability.put(waitingForNode, 1); + } else { + requestedCapability.put(waitingForNode, attempts); + LOGGER.log(Level.INFO, LOGGING_PREFIX + "Request waiting for a node new node for {0}.", requestedCapability); + } + } return null; } @@ -334,7 +377,7 @@ public void beforeRegistration() { @Override public CapabilityMatcher getCapabilityHelper() { if (capabilityHelper == null) { - capabilityHelper = new DockerSeleniumCapabilityMatcher(); + capabilityHelper = new DockerSeleniumCapabilityMatcher(this); } return capabilityHelper; } @@ -348,10 +391,14 @@ public float getResourceUsageInPercent() { return 98; } - @VisibleForTesting boolean startDockerSeleniumContainer(String browser) { + return startDockerSeleniumContainer(browser, false); + } + + @VisibleForTesting + boolean startDockerSeleniumContainer(String browser, boolean forceCreation) { - if (validateAmountOfDockerSeleniumContainers()) { + if (validateAmountOfDockerSeleniumContainers() || forceCreation) { String hostIpAddress = "localhost"; @@ -453,6 +500,48 @@ private void createStartupContainers() { }).start(); } + /* + This method will search for a screenResolution capability to be passed when creating a docker-selenium node. + */ + private void configureScreenResolutionFromCapabilities(Map requestedCapability) { + boolean wasConfiguredScreenWidthAndHeightChanged = false; + String[] screenResolutionNames = {"screenResolution", "resolution", "screen-resolution"}; + for (String screenResolutionName : screenResolutionNames) { + if (requestedCapability.containsKey(screenResolutionName)) { + String screenResolution = requestedCapability.get(screenResolutionName).toString(); + try { + int screenWidth = Integer.parseInt(screenResolution.split("x")[0]); + int screenHeight = Integer.parseInt(screenResolution.split("x")[1]); + if (screenWidth > 0 && screenHeight > 0) { + setScreenHeight(screenHeight); + setScreenWidth(screenWidth); + wasConfiguredScreenWidthAndHeightChanged = true; + } else { + setScreenWidth(getConfiguredScreenWidth()); + setScreenHeight(getConfiguredScreenHeight()); + LOGGER.log(Level.FINE, "One of the values provided for screenResolution is negative, " + + "defaults will be used. Passed value -> " + screenResolution); + } + } catch (Exception e) { + setScreenWidth(getConfiguredScreenWidth()); + setScreenHeight(getConfiguredScreenHeight()); + LOGGER.log(Level.FINE, "Values provided for screenResolution are not valid integers or " + + "either the width or the height is missing, defaults will be used. Passed value -> " + + screenResolution); + } + } + } + // If the screen resolution parameters were not changed, we just set the defaults again. + // Also in the capabilities, to avoid the situation where a request grabs the node from other request + // just because the platform, version, and browser match. + if (!wasConfiguredScreenWidthAndHeightChanged) { + setScreenWidth(getConfiguredScreenWidth()); + setScreenHeight(getConfiguredScreenHeight()); + String screenResolution = String.format("%sx%s", getScreenWidth(), getScreenHeight()); + requestedCapability.put("screenResolution", screenResolution); + } + } + private int getNumberOfRunningContainers() { try { List containerList = dockerClient.listContainers(DockerClient.ListContainersParam.allContainers()); diff --git a/src/main/java/de/zalando/tip/zalenium/util/Dashboard.java b/src/main/java/de/zalando/tip/zalenium/util/Dashboard.java index f21429134f..ecc766998f 100644 --- a/src/main/java/de/zalando/tip/zalenium/util/Dashboard.java +++ b/src/main/java/de/zalando/tip/zalenium/util/Dashboard.java @@ -17,6 +17,8 @@ public class Dashboard { private static CommonProxyUtilities commonProxyUtilities = new CommonProxyUtilities(); + private static int executedTests = 0; + public static synchronized void updateDashboard(TestInformation testInformation) throws IOException { String currentLocalPath = commonProxyUtilities.currentLocalPath(); String localVideosPath = currentLocalPath + "/" + VIDEOS_FOLDER_NAME; @@ -36,11 +38,16 @@ public static synchronized void updateDashboard(TestInformation testInformation) } FileUtils.writeStringToFile(testList, testEntry, StandardCharsets.UTF_8); + executedTests++; + File dashboardHtml = new File(localVideosPath, "dashboard.html"); String dashboard = FileUtils.readFileToString(new File(currentLocalPath, "dashboard_template.html"), StandardCharsets.UTF_8); dashboard = dashboard.replace("{testList}", testEntry); FileUtils.writeStringToFile(dashboardHtml, dashboard, StandardCharsets.UTF_8); + File testCountFile = new File(localVideosPath, "amount_of_run_tests.txt"); + FileUtils.writeStringToFile(testCountFile, String.valueOf(executedTests), StandardCharsets.UTF_8); + File zalandoIco = new File(localVideosPath, "zalando.ico"); if (!zalandoIco.exists()) { FileUtils.copyFile(new File(currentLocalPath, "zalando.ico"), zalandoIco); @@ -55,7 +62,6 @@ public static synchronized void updateDashboard(TestInformation testInformation) if (!jsFolder.exists()) { FileUtils.copyDirectory(new File(currentLocalPath + "/js"), jsFolder); } - } } diff --git a/src/main/java/de/zalando/tip/zalenium/util/DockerSeleniumCapabilityMatcher.java b/src/main/java/de/zalando/tip/zalenium/util/DockerSeleniumCapabilityMatcher.java index b1283992a7..e9d0ed72a6 100644 --- a/src/main/java/de/zalando/tip/zalenium/util/DockerSeleniumCapabilityMatcher.java +++ b/src/main/java/de/zalando/tip/zalenium/util/DockerSeleniumCapabilityMatcher.java @@ -1,6 +1,9 @@ package de.zalando.tip.zalenium.util; +import de.zalando.tip.zalenium.proxy.DockerSeleniumRemoteProxy; +import de.zalando.tip.zalenium.proxy.DockerSeleniumStarterRemoteProxy; import org.openqa.grid.internal.utils.DefaultCapabilityMatcher; +import org.openqa.grid.selenium.proxy.DefaultRemoteProxy; import org.openqa.selenium.remote.CapabilityType; import java.util.Map; @@ -11,7 +14,13 @@ * The purpose of this class is to let docker-selenium process requests where a capability "version=latest" is present */ public class DockerSeleniumCapabilityMatcher extends DefaultCapabilityMatcher { - private static final Logger logger = Logger.getLogger(DockerSeleniumCapabilityMatcher.class.getName()); + private final Logger logger = Logger.getLogger(DockerSeleniumCapabilityMatcher.class.getName()); + private DefaultRemoteProxy proxy; + + public DockerSeleniumCapabilityMatcher(DefaultRemoteProxy defaultRemoteProxy) { + super(); + proxy = defaultRemoteProxy; + } @Override public boolean matches(Map nodeCapability, Map requestedCapability) { @@ -23,18 +32,46 @@ public boolean matches(Map nodeCapability, Map r without the version. If not, we put the requested capability back in the requestedCapability object, so it can be matched by any of the Cloud Testing Providers. */ + boolean browserVersionCapabilityMatches = false; if (requestedCapability.containsKey(CapabilityType.VERSION)) { String requestedVersion = requestedCapability.get(CapabilityType.VERSION).toString(); if ("latest".equalsIgnoreCase(requestedVersion)) { requestedCapability.remove(CapabilityType.VERSION); if (super.matches(nodeCapability, requestedCapability)) { - return true; + browserVersionCapabilityMatches = true; } else { requestedCapability.put(CapabilityType.VERSION, requestedVersion); - return false; } } } - return super.matches(nodeCapability, requestedCapability); + + boolean screenResolutionCapabilityMatches = true; + boolean containsScreenResolutionCapability = false; + // This validation is only done for docker-selenium nodes + if (proxy instanceof DockerSeleniumRemoteProxy) { + String[] screenResolutionNames = {"screenResolution", "resolution", "screen-resolution"}; + for (String screenResolutionName : screenResolutionNames) { + if (requestedCapability.containsKey(screenResolutionName)) { + screenResolutionCapabilityMatches = nodeCapability.containsKey(screenResolutionName) && + requestedCapability.get(screenResolutionName).equals(nodeCapability.get(screenResolutionName)); + containsScreenResolutionCapability = true; + } + } + // This is done to avoid having the test run on a node with a configured screen resolution different from + // the global configured one. But not putting it to tests that should go to a cloud provider. + if (!containsScreenResolutionCapability && super.matches(nodeCapability, requestedCapability)) { + String screenResolution = String.format("%sx%s", DockerSeleniumStarterRemoteProxy.getConfiguredScreenWidth(), + DockerSeleniumStarterRemoteProxy.getConfiguredScreenHeight()); + requestedCapability.put("screenResolution", screenResolution); + } + } + + // If the browser version has been matched, then implicitly the matcher from the super class has also been + // invoked. + if (browserVersionCapabilityMatches) { + return screenResolutionCapabilityMatches; + } else { + return super.matches(nodeCapability, requestedCapability) && screenResolutionCapabilityMatches; + } } } diff --git a/src/test/java/de/zalando/tip/zalenium/proxy/DockerSeleniumRemoteProxyTest.java b/src/test/java/de/zalando/tip/zalenium/proxy/DockerSeleniumRemoteProxyTest.java index dd83d9b8ef..a0474e3edc 100644 --- a/src/test/java/de/zalando/tip/zalenium/proxy/DockerSeleniumRemoteProxyTest.java +++ b/src/test/java/de/zalando/tip/zalenium/proxy/DockerSeleniumRemoteProxyTest.java @@ -49,7 +49,7 @@ public void setUp() throws DockerException, InterruptedException, IOException { RegistrationRequest request = TestUtils.getRegistrationRequestForTesting(40000, DockerSeleniumRemoteProxy.class.getCanonicalName()); request.getConfiguration().capabilities.clear(); - request.getConfiguration().capabilities.addAll(DockerSeleniumStarterRemoteProxy.getCapabilities()); + request.getConfiguration().capabilities.addAll(TestUtils.getDockerSeleniumCapabilitiesForTesting()); // Creating the proxy proxy = DockerSeleniumRemoteProxy.getNewInstance(request, registry); diff --git a/src/test/java/de/zalando/tip/zalenium/proxy/DockerSeleniumStarterRemoteProxyTest.java b/src/test/java/de/zalando/tip/zalenium/proxy/DockerSeleniumStarterRemoteProxyTest.java index 5c3c1ea572..32111eaaba 100644 --- a/src/test/java/de/zalando/tip/zalenium/proxy/DockerSeleniumStarterRemoteProxyTest.java +++ b/src/test/java/de/zalando/tip/zalenium/proxy/DockerSeleniumStarterRemoteProxyTest.java @@ -26,6 +26,7 @@ import static java.util.concurrent.TimeUnit.SECONDS; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.Mockito.times; @@ -127,6 +128,80 @@ public void containerIsStartedWhenBrowserIsSupportedAndLatestIsUsedAsBrowserVers verify(spyProxy, times(1)).startDockerSeleniumContainer(BrowserType.CHROME); } + @Test + public void containerIsStartedWhenScreenResolutionIsProvided() { + // Supported desired capability for the test session + Map supportedCapability = new HashMap<>(); + supportedCapability.put(CapabilityType.BROWSER_NAME, BrowserType.FIREFOX); + supportedCapability.put(CapabilityType.PLATFORM, Platform.ANY); + supportedCapability.put("screenResolution", "1280x760"); + TestSession testSession = spyProxy.getNewSession(supportedCapability); + Assert.assertNull(testSession); + verify(spyProxy, times(1)).startDockerSeleniumContainer(BrowserType.FIREFOX); + Assert.assertEquals(1280, DockerSeleniumStarterRemoteProxy.getScreenWidth()); + Assert.assertEquals(760, DockerSeleniumStarterRemoteProxy.getScreenHeight()); + } + + @Test + public void containerIsStartedWhenResolutionIsProvided() { + // Supported desired capability for the test session + Map supportedCapability = new HashMap<>(); + supportedCapability.put(CapabilityType.BROWSER_NAME, BrowserType.CHROME); + supportedCapability.put(CapabilityType.PLATFORM, Platform.ANY); + supportedCapability.put("resolution", "1300x900"); + TestSession testSession = spyProxy.getNewSession(supportedCapability); + Assert.assertNull(testSession); + verify(spyProxy, times(1)).startDockerSeleniumContainer(BrowserType.CHROME); + Assert.assertEquals(1300, DockerSeleniumStarterRemoteProxy.getScreenWidth()); + Assert.assertEquals(900, DockerSeleniumStarterRemoteProxy.getScreenHeight()); + } + + @Test + public void containerIsStartedWhenCustomScreenResolutionIsProvided() { + // Supported desired capability for the test session + Map supportedCapability = new HashMap<>(); + supportedCapability.put(CapabilityType.BROWSER_NAME, BrowserType.FIREFOX); + supportedCapability.put(CapabilityType.PLATFORM, Platform.ANY); + supportedCapability.put("screen-resolution", "1500x1000"); + TestSession testSession = spyProxy.getNewSession(supportedCapability); + Assert.assertNull(testSession); + verify(spyProxy, times(1)).startDockerSeleniumContainer(BrowserType.FIREFOX); + Assert.assertEquals(1500, DockerSeleniumStarterRemoteProxy.getScreenWidth()); + Assert.assertEquals(1000, DockerSeleniumStarterRemoteProxy.getScreenHeight()); + } + + @Test + public void containerIsStartedWhenNegativeResolutionIsProvidedUsingDefaults() { + // Supported desired capability for the test session + Map supportedCapability = new HashMap<>(); + supportedCapability.put(CapabilityType.BROWSER_NAME, BrowserType.CHROME); + supportedCapability.put(CapabilityType.PLATFORM, Platform.ANY); + supportedCapability.put("resolution", "-1300x800"); + TestSession testSession = spyProxy.getNewSession(supportedCapability); + Assert.assertNull(testSession); + verify(spyProxy, times(1)).startDockerSeleniumContainer(BrowserType.CHROME); + Assert.assertEquals(DockerSeleniumStarterRemoteProxy.getConfiguredScreenWidth(), + DockerSeleniumStarterRemoteProxy.getScreenWidth()); + Assert.assertEquals(DockerSeleniumStarterRemoteProxy.getConfiguredScreenHeight(), + DockerSeleniumStarterRemoteProxy.getScreenHeight()); + } + + @Test + public void containerIsStartedWhenAnInvalidResolutionIsProvidedUsingDefaults() { + // Supported desired capability for the test session + Map supportedCapability = new HashMap<>(); + supportedCapability.put(CapabilityType.BROWSER_NAME, BrowserType.CHROME); + supportedCapability.put(CapabilityType.PLATFORM, Platform.ANY); + supportedCapability.put("screenResolution", "notAValidScreenResolution"); + TestSession testSession = spyProxy.getNewSession(supportedCapability); + Assert.assertNull(testSession); + verify(spyProxy, times(1)).startDockerSeleniumContainer(BrowserType.CHROME); + Assert.assertEquals(DockerSeleniumStarterRemoteProxy.getConfiguredScreenWidth(), + DockerSeleniumStarterRemoteProxy.getScreenWidth()); + Assert.assertEquals(DockerSeleniumStarterRemoteProxy.getConfiguredScreenHeight(), + DockerSeleniumStarterRemoteProxy.getScreenHeight()); + } + @Test public void containerIsStartedWhenFirefoxCapabilitiesAreSupported() { @@ -151,6 +226,29 @@ public void noContainerIsStartedWhenBrowserCapabilityIsAbsent() { verify(spyProxy, never()).startDockerSeleniumContainer(anyString()); } + @Test + public void noContainerIsStartedForAlreadyProcessedRequest() { + Map requestedCapability = new HashMap<>(); + requestedCapability.put(CapabilityType.BROWSER_NAME, BrowserType.CHROME); + requestedCapability.put(CapabilityType.PLATFORM, Platform.LINUX); + requestedCapability.put("waitingFor_CHROME_Node", 1); + TestSession testSession = spyProxy.getNewSession(requestedCapability); + Assert.assertNull(testSession); + verify(spyProxy, times(0)).startDockerSeleniumContainer(anyString()); + } + + @Test + public void containerIsStartedForRequestProcessedMoreThan20Times() { + Map requestedCapability = new HashMap<>(); + requestedCapability.put(CapabilityType.BROWSER_NAME, BrowserType.FIREFOX); + requestedCapability.put(CapabilityType.PLATFORM, Platform.LINUX); + requestedCapability.put("waitingFor_FIREFOX_Node", 21); + TestSession testSession = spyProxy.getNewSession(requestedCapability); + Assert.assertNull(testSession); + verify(spyProxy, times(1)).startDockerSeleniumContainer(anyString(), eq(true)); + } + + /* Tests checking the environment variables setup to have a given number of containers on startup */ diff --git a/src/test/java/de/zalando/tip/zalenium/util/TestUtils.java b/src/test/java/de/zalando/tip/zalenium/util/TestUtils.java index 6e49b4dbac..3f87ba6b1e 100644 --- a/src/test/java/de/zalando/tip/zalenium/util/TestUtils.java +++ b/src/test/java/de/zalando/tip/zalenium/util/TestUtils.java @@ -3,6 +3,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; +import de.zalando.tip.zalenium.proxy.DockerSeleniumStarterRemoteProxy; import org.apache.commons.io.FileUtils; import org.openqa.grid.common.RegistrationRequest; import org.openqa.grid.internal.utils.configuration.GridNodeConfiguration; @@ -12,13 +13,16 @@ import org.openqa.selenium.Platform; import org.openqa.selenium.remote.BrowserType; import org.openqa.selenium.remote.CapabilityType; +import org.openqa.selenium.remote.DesiredCapabilities; import java.io.File; import java.io.IOException; import java.net.URL; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; +import java.util.List; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -55,6 +59,25 @@ public static WebDriverRequest getMockedWebDriverRequestStartSession() { return request; } + public static List getDockerSeleniumCapabilitiesForTesting() { + String screenResolution = String.format("%sx%s", DockerSeleniumStarterRemoteProxy.getConfiguredScreenWidth(), + DockerSeleniumStarterRemoteProxy.getConfiguredScreenHeight()); + List dsCapabilities = new ArrayList<>(); + DesiredCapabilities firefoxCapabilities = new DesiredCapabilities(); + firefoxCapabilities.setBrowserName(BrowserType.FIREFOX); + firefoxCapabilities.setPlatform(Platform.LINUX); + firefoxCapabilities.setCapability(RegistrationRequest.MAX_INSTANCES, 1); + firefoxCapabilities.setCapability("screenResolution", screenResolution); + dsCapabilities.add(firefoxCapabilities); + DesiredCapabilities chromeCapabilities = new DesiredCapabilities(); + chromeCapabilities.setBrowserName(BrowserType.CHROME); + chromeCapabilities.setPlatform(Platform.LINUX); + chromeCapabilities.setCapability(RegistrationRequest.MAX_INSTANCES, 1); + chromeCapabilities.setCapability("screenResolution", screenResolution); + dsCapabilities.add(chromeCapabilities); + return dsCapabilities; + } + @SuppressWarnings("ConstantConditions") public static JsonElement getTestInformationSample(String fileName) throws IOException { URL testInfoLocation = TestUtils.class.getClassLoader().getResource(fileName);