| diff --git a/java/client/src/org/openqa/selenium/chrome/ChromeOptions.java b/java/client/src/org/openqa/selenium/chrome/ChromeOptions.java |
| index 2a72c55ab7..4cfabe2510 100644 |
| --- a/java/client/src/org/openqa/selenium/chrome/ChromeOptions.java |
| +++ b/java/client/src/org/openqa/selenium/chrome/ChromeOptions.java |
| @@ -70,6 +70,9 @@ |
| public static final String CAPABILITY = "goog:chromeOptions"; |
| |
| private String binary; |
| + private String androidPackage; |
| + private String androidActivity; |
| + private String androidProcess; |
| private List<String> args = new ArrayList<>(); |
| private List<File> extensionFiles = new ArrayList<>(); |
| private List<String> extensions = new ArrayList<>(); |
| @@ -109,6 +112,36 @@ public ChromeOptions setBinary(String path) { |
| return this; |
| } |
| |
| + /** |
| + * Sets the Android package name for Chrome or a WebView app. The package should already exist |
| + * on the Android device. |
| + * |
| + * @param package_name Package name for Chrome or a WebView app |
| + */ |
| + public void setAndroidPackage(String package_name) { |
| + androidPackage = checkNotNull(package_name); |
| + } |
| + |
| + /** |
| + * Sets the name of the Activity hosting the WebView under test. |
| + * |
| + * @param package_name Android Activity class name |
| + */ |
| + public void setAndroidActivity(String activity_name) { |
| + androidActivity = checkNotNull(activity_name); |
| + } |
| + |
| + /** |
| + * Sets the process name for the Activity hosting the WebView under test. |
| + * |
| + * @param package_name Android process name |
| + */ |
| + public void setAndroidProcess(String process_name) { |
| + androidProcess = checkNotNull(process_name); |
| + } |
| + |
| + /** |
| + |
| /** |
| * @param arguments The arguments to use when starting Chrome. |
| * @see #addArguments(java.util.List) |
| diff --git a/java/client/src/org/openqa/selenium/net/PortProber.java b/java/client/src/org/openqa/selenium/net/PortProber.java |
| index 3aee1e5c70..758898b2e1 100644 |
| --- a/java/client/src/org/openqa/selenium/net/PortProber.java |
| +++ b/java/client/src/org/openqa/selenium/net/PortProber.java |
| @@ -49,7 +49,7 @@ |
| } |
| |
| public static final int HIGHEST_PORT = 65535; |
| - public static final int START_OF_USER_PORTS = 1024; |
| + public static final int START_OF_USER_PORTS = 6700; |
| |
| private PortProber() { |
| // Utility class |
| diff --git a/java/client/test/org/openqa/selenium/WindowTest.java b/java/client/test/org/openqa/selenium/WindowTest.java |
| index 574a794d52..a5c0e2674f 100644 |
| --- a/java/client/test/org/openqa/selenium/WindowTest.java |
| +++ b/java/client/test/org/openqa/selenium/WindowTest.java |
| @@ -107,7 +107,7 @@ public void testSetsThePositionOfTheCurrentWindow() { |
| // off-screen. Therefore, try to stay on-screen. Hopefully you have more than 210 px, |
| // or this may fail. |
| window.setSize(new Dimension(200, 200)); |
| - Point targetPosition = new Point(position.x + 10, position.y + 10); |
| + Point targetPosition = new Point(position.x + 30, position.y + 30); |
| window.setPosition(targetPosition); |
| |
| wait.until($ -> window.getPosition().x == targetPosition.x); |
| @@ -125,7 +125,7 @@ public void testCanMaximizeTheWindow() { |
| // though others aren't defined in org.openqa.selenium.Platform). |
| assumeFalse(TestUtilities.getEffectivePlatform(driver).is(ANDROID)); |
| |
| - changeSizeTo(new Dimension(640, 323)); |
| + changeSizeTo(new Dimension(640, 398)); |
| enlargeBy(WebDriver.Window::maximize); |
| } |
| |
| @@ -139,7 +139,7 @@ public void testCanMaximizeTheWindowFromFrame() { |
| assumeFalse(TestUtilities.getEffectivePlatform(driver).is(ANDROID)); |
| |
| driver.get(pages.framesetPage); |
| - changeSizeTo(new Dimension(640, 324)); |
| + changeSizeTo(new Dimension(640, 399)); |
| |
| driver.switchTo().frame("fourth"); |
| enlargeBy(WebDriver.Window::maximize); |
| @@ -155,7 +155,7 @@ public void testCanMaximizeTheWindowFromIframe() { |
| assumeFalse(TestUtilities.getEffectivePlatform(driver).is(ANDROID)); |
| |
| driver.get(pages.iframePage); |
| - changeSizeTo(new Dimension(640, 325)); |
| + changeSizeTo(new Dimension(640, 400)); |
| |
| driver.switchTo().frame("iframe1-name"); |
| enlargeBy(WebDriver.Window::maximize); |
| @@ -170,7 +170,7 @@ public void canFullscreenTheWindow() { |
| // though others aren't defined in org.openqa.selenium.Platform). |
| assumeFalse(TestUtilities.getEffectivePlatform(driver).is(ANDROID)); |
| |
| - changeSizeTo(new Dimension(640, 323)); |
| + changeSizeTo(new Dimension(640, 398)); |
| enlargeBy(WebDriver.Window::fullscreen); |
| } |
| |
| @@ -185,7 +185,7 @@ public void canFullscreenTheWindowFromFrame() { |
| assumeFalse(TestUtilities.getEffectivePlatform(driver).is(ANDROID)); |
| |
| driver.get(pages.framesetPage); |
| - changeSizeTo(new Dimension(640, 324)); |
| + changeSizeTo(new Dimension(640, 399)); |
| |
| driver.switchTo().frame("fourth"); |
| enlargeBy(WebDriver.Window::fullscreen); |
| @@ -202,7 +202,7 @@ public void canFullscreenTheWindowFromIframe() { |
| assumeFalse(TestUtilities.getEffectivePlatform(driver).is(ANDROID)); |
| |
| driver.get(pages.iframePage); |
| - changeSizeTo(new Dimension(640, 325)); |
| + changeSizeTo(new Dimension(640, 400)); |
| |
| driver.switchTo().frame("iframe1-name"); |
| enlargeBy(WebDriver.Window::fullscreen); |
| diff --git a/java/client/test/org/openqa/selenium/chrome/ChromeOptionsFunctionalTest.java b/java/client/test/org/openqa/selenium/chrome/ChromeOptionsFunctionalTest.java |
| index 232718f92b..3df6752a3a 100644 |
| --- a/java/client/test/org/openqa/selenium/chrome/ChromeOptionsFunctionalTest.java |
| +++ b/java/client/test/org/openqa/selenium/chrome/ChromeOptionsFunctionalTest.java |
| @@ -52,6 +52,7 @@ public void tearDown() { |
| public void canStartChromeWithCustomOptions() { |
| ChromeOptions options = new ChromeOptions(); |
| options.addArguments("user-agent=foo;bar"); |
| + setWebDriverChromeBinary(options); |
| driver = new ChromeDriver(options); |
| |
| driver.get(pages.clickJacker); |
| @@ -74,6 +75,7 @@ public void optionsStayEqualAfterSerialization() { |
| public void canSetAcceptInsecureCerts() { |
| ChromeOptions options = new ChromeOptions(); |
| options.setAcceptInsecureCerts(true); |
| + setWebDriverChromeBinary(options); |
| driver = new ChromeDriver(options); |
| |
| assertThat(driver.getCapabilities().getCapability(ACCEPT_SSL_CERTS)).isEqualTo(true); |
| @@ -84,6 +86,7 @@ public void canSetAcceptInsecureCerts() { |
| public void canAddExtensionFromFile() { |
| ChromeOptions options = new ChromeOptions(); |
| options.addExtensions(InProject.locate(EXT_PATH).toFile()); |
| + setWebDriverChromeBinary(options); |
| driver = new ChromeDriver(options); |
| |
| driver.get(pages.clicksPage); |
| @@ -101,6 +104,7 @@ public void canAddExtensionFromStringEncodedInBase64() throws IOException { |
| ChromeOptions options = new ChromeOptions(); |
| options.addEncodedExtensions(Base64.getEncoder().encodeToString( |
| Files.readAllBytes(InProject.locate(EXT_PATH)))); |
| + setWebDriverChromeBinary(options); |
| driver = new ChromeDriver(options); |
| |
| driver.get(pages.clicksPage); |
| @@ -112,4 +116,10 @@ public void canAddExtensionFromStringEncodedInBase64() throws IOException { |
| new WebDriverWait(driver, 10).until(titleIs("clicks")); |
| } |
| |
| + private void setWebDriverChromeBinary(ChromeOptions options) { |
| + String chromePath = System.getProperty("webdriver.chrome.binary"); |
| + if (chromePath != null) { |
| + options.setBinary(chromePath); |
| + } |
| + } |
| } |
| diff --git a/java/client/test/org/openqa/selenium/environment/webserver/JettyAppServer.java b/java/client/test/org/openqa/selenium/environment/webserver/JettyAppServer.java |
| index f9277d1bb4..7ccd02c9e7 100644 |
| --- a/java/client/test/org/openqa/selenium/environment/webserver/JettyAppServer.java |
| +++ b/java/client/test/org/openqa/selenium/environment/webserver/JettyAppServer.java |
| @@ -113,10 +113,6 @@ public JettyAppServer(String hostName, int httpPort, int httpsPort) { |
| Path webSrc = locate("common/src/web"); |
| ServletContextHandler defaultContext = addResourceHandler( |
| DEFAULT_CONTEXT_PATH, webSrc); |
| - ServletContextHandler jsContext = addResourceHandler( |
| - JS_SRC_CONTEXT_PATH, locate("javascript")); |
| - addResourceHandler(CLOSURE_CONTEXT_PATH, locate("third_party/closure/goog")); |
| - addResourceHandler(THIRD_PARTY_JS_CONTEXT_PATH, locate("third_party/js")); |
| |
| TemporaryFilesystem tempFs = TemporaryFilesystem.getDefaultTmpFS(); |
| tempPageDir = tempFs.createTempDir("pages", "test"); |
| diff --git a/java/client/test/org/openqa/selenium/testing/JUnit4TestBase.java b/java/client/test/org/openqa/selenium/testing/JUnit4TestBase.java |
| index 1cd5ef93ab..49b3a64b69 100644 |
| --- a/java/client/test/org/openqa/selenium/testing/JUnit4TestBase.java |
| +++ b/java/client/test/org/openqa/selenium/testing/JUnit4TestBase.java |
| @@ -30,6 +30,7 @@ |
| import org.junit.runners.model.Statement; |
| import org.openqa.selenium.Capabilities; |
| import org.openqa.selenium.WebDriver; |
| +import org.openqa.selenium.WebDriverException; |
| import org.openqa.selenium.environment.GlobalTestEnvironment; |
| import org.openqa.selenium.environment.InProcessTestEnvironment; |
| import org.openqa.selenium.environment.TestEnvironment; |
| @@ -163,10 +164,25 @@ private boolean notImplemented(Stream<NotYetImplemented> nyi) { |
| return nyi.anyMatch(driver -> matches(current, new Browser[]{driver.value()})); |
| } |
| |
| + private boolean isReadyToRun(Description description) { |
| + String name = description.getTestClass().getSimpleName() + "." + description.getMethodName(); |
| + String readyToRunFilter = System.getProperty("readyToRun"); |
| + if (readyToRunFilter != null) { |
| + String[] readyToRunTests = readyToRunFilter.split(":"); |
| + for (int i = 0; i < readyToRunTests.length; i++) { |
| + if (name.matches(readyToRunTests[i])) { |
| + return true; |
| + } |
| + } |
| + } |
| + return false; |
| + } |
| + |
| @Override |
| public Statement apply(final Statement base, final Description description) { |
| - if (notImplemented(description.getAnnotation(NotYetImplementedList.class)) || |
| - notImplemented(description.getAnnotation(NotYetImplemented.class))) { |
| + if ((notImplemented(description.getAnnotation(NotYetImplementedList.class)) || |
| + notImplemented(description.getAnnotation(NotYetImplemented.class))) |
| + && !isReadyToRun(description)) { |
| return new Statement() { |
| @Override |
| public void evaluate() throws Throwable { |
| @@ -207,10 +223,32 @@ public void createNewDriver(Capabilities capabilities) { |
| |
| private static WebDriver actuallyCreateDriver() { |
| WebDriver driver = storedDriver.get(); |
| + // If the driver is left in a bad state, create a new one. |
| + // This happens on Android after any test that creates its own driver. |
| + // Since only one instance of Chrome can run on Android at a time, the |
| + // stored driver's browser is destroyed. |
| + try |
| + { |
| + if (driver != null) |
| + { |
| + driver.getCurrentUrl(); |
| + } |
| + } |
| + catch (WebDriverException e) |
| + { |
| + try |
| + { |
| + driver.quit(); |
| + } |
| + catch (RuntimeException ignored) |
| + { |
| + System.exit(1); |
| + } |
| + driver = null; |
| + } |
| |
| if (driver == null || |
| (driver instanceof RemoteWebDriver && ((RemoteWebDriver)driver).getSessionId() == null)) { |
| - StaticResources.ensureAvailable(); |
| driver = new WebDriverBuilder().get(); |
| storedDriver.set(driver); |
| } |
| @@ -219,6 +257,29 @@ private static WebDriver actuallyCreateDriver() { |
| |
| private static WebDriver actuallyCreateDriver(Capabilities capabilities) { |
| WebDriver driver = storedDriver.get(); |
| + // If the driver is left in a bad state, create a new one. |
| + // This happens on Android after any test that creates its own driver. |
| + // Since only one instance of Chrome can run on Android at a time, the |
| + // stored driver's browser is destroyed. |
| + try |
| + { |
| + if (driver != null) |
| + { |
| + driver.getCurrentUrl(); |
| + } |
| + } |
| + catch (WebDriverException e) |
| + { |
| + try |
| + { |
| + driver.quit(); |
| + } |
| + catch (RuntimeException ignored) |
| + { |
| + System.exit(1); |
| + } |
| + driver = null; |
| + } |
| |
| if (driver == null || |
| (driver instanceof RemoteWebDriver && ((RemoteWebDriver)driver).getSessionId() == null)) { |
| diff --git a/java/client/test/org/openqa/selenium/testing/TestIgnorance.java b/java/client/test/org/openqa/selenium/testing/TestIgnorance.java |
| index 0912d363a6..3465bfbe50 100644 |
| --- a/java/client/test/org/openqa/selenium/testing/TestIgnorance.java |
| +++ b/java/client/test/org/openqa/selenium/testing/TestIgnorance.java |
| @@ -63,20 +63,44 @@ public TestIgnorance(Browser driver) { |
| } |
| |
| public boolean isIgnored(Description method) { |
| - boolean ignored = ignoreComparator.shouldIgnore(method.getTestClass().getAnnotation(IgnoreList.class)) || |
| - ignoreComparator.shouldIgnore(method.getTestClass().getAnnotation(Ignore.class)) || |
| - ignoreComparator.shouldIgnore(method.getAnnotation(IgnoreList.class)) || |
| - ignoreComparator.shouldIgnore(method.getAnnotation(Ignore.class)); |
| - |
| - ignored |= isIgnoredBecauseOfJUnit4Ignore(method.getTestClass().getAnnotation(org.junit.Ignore.class)); |
| - ignored |= isIgnoredBecauseOfJUnit4Ignore(method.getAnnotation(org.junit.Ignore.class)); |
| - if (Boolean.getBoolean("ignored_only")) { |
| - ignored = !ignored; |
| + |
| + String name = method.getTestClass().getSimpleName() + "." + method.getMethodName(); |
| + String filter = System.getProperty("filter", ".*"); |
| + String[] patternGroups = filter.split("-"); |
| + String[] positivePatterns = patternGroups[0].split(":"); |
| + String[] negativePatterns = new String[0]; |
| + |
| + if (patternGroups.length > 1) { |
| + negativePatterns = patternGroups[1].split(":"); |
| + |
| + for (int i = 0; i < negativePatterns.length; i++) { |
| + if (name.matches(negativePatterns[i])) { |
| + return true; |
| + } |
| + } |
| } |
| |
| - ignored |= isIgnoredDueToEnvironmentVariables(method); |
| + for (int i = 0; i < positivePatterns.length; i++) { |
| + if (name.matches(positivePatterns[i])) { |
| + |
| + boolean ignored = ignoreComparator.shouldIgnore(method.getTestClass().getAnnotation(IgnoreList.class)) || |
| + ignoreComparator.shouldIgnore(method.getTestClass().getAnnotation(Ignore.class)) || |
| + ignoreComparator.shouldIgnore(method.getAnnotation(IgnoreList.class)) || |
| + ignoreComparator.shouldIgnore(method.getAnnotation(Ignore.class)); |
| |
| - return ignored; |
| + ignored |= isIgnoredBecauseOfJUnit4Ignore(method.getTestClass().getAnnotation(org.junit.Ignore.class)); |
| + ignored |= isIgnoredBecauseOfJUnit4Ignore(method.getAnnotation(org.junit.Ignore.class)); |
| + |
| + if (Boolean.getBoolean("ignored_only")) { |
| + ignored = !ignored; |
| + } |
| + |
| + ignored |= isIgnoredDueToEnvironmentVariables(method); |
| + |
| + return ignored; |
| + } |
| + } |
| + return true; |
| } |
| |
| private boolean isIgnoredBecauseOfJUnit4Ignore(org.junit.Ignore annotation) { |
| diff --git a/java/client/test/org/openqa/selenium/testing/drivers/TestChromeDriver.java b/java/client/test/org/openqa/selenium/testing/drivers/TestChromeDriver.java |
| index 6177c2a4bc..8b10ff727f 100644 |
| --- a/java/client/test/org/openqa/selenium/testing/drivers/TestChromeDriver.java |
| +++ b/java/client/test/org/openqa/selenium/testing/drivers/TestChromeDriver.java |
| @@ -61,13 +61,11 @@ public TestChromeDriver(Capabilities capabilities) { |
| private static URL getServiceUrl() { |
| try { |
| if (service == null) { |
| - Path logFile = Files.createTempFile("chromedriver", ".log"); |
| service = new ChromeDriverService.Builder() |
| .withVerbose(true) |
| - .withLogFile(logFile.toFile()) |
| .build(); |
| - LOG.info("chromedriver will log to " + logFile); |
| service.start(); |
| + System.clearProperty("webdriver.chrome.logfile"); |
| // Fugly. |
| Runtime.getRuntime().addShutdownHook(new Thread(() -> service.stop())); |
| } |
| @@ -80,15 +78,39 @@ private static URL getServiceUrl() { |
| private static Capabilities chromeWithCustomCapabilities(Capabilities originalCapabilities) { |
| ChromeOptions options = new ChromeOptions(); |
| options.addArguments("disable-extensions", "disable-infobars", "disable-breakpad"); |
| - Map<String, Object> prefs = new HashMap<>(); |
| - prefs.put("exit_type", "None"); |
| - prefs.put("exited_cleanly", true); |
| - options.setExperimentalOption("prefs", prefs); |
| + String androidPackage = System.getProperty("webdriver.chrome.android_package"); |
| + |
| + if (androidPackage == null) { |
| + Map<String, Object> prefs = new HashMap<>(); |
| + prefs.put("exit_type", "None"); |
| + prefs.put("exited_cleanly", true); |
| + options.setExperimentalOption("prefs", prefs); |
| + } |
| + |
| String chromePath = System.getProperty("webdriver.chrome.binary"); |
| if (chromePath != null) { |
| options.setBinary(new File(chromePath)); |
| } |
| |
| + if (androidPackage != null) { |
| + options.setExperimentalOption("androidPackage", androidPackage); |
| + options.setAndroidPackage(androidPackage); |
| + } |
| + |
| + String androidActivity = System.getProperty("webdriver.chrome.android_activity"); |
| + |
| + if (androidActivity != null) { |
| + options.setExperimentalOption("androidActivity", androidActivity); |
| + options.setAndroidActivity(androidActivity); |
| + } |
| + |
| + String androidProcess = System.getProperty("webdriver.chrome.android_process"); |
| + |
| + if (androidProcess != null) { |
| + options.setExperimentalOption("androidProcess", androidProcess); |
| + options.setAndroidProcess(androidProcess); |
| + } |
| + |
| if (originalCapabilities != null) { |
| options.merge(originalCapabilities); |
| } |
| diff --git a/java/client/test/org/openqa/selenium/testing/drivers/WebDriverBuilder.java b/java/client/test/org/openqa/selenium/testing/drivers/WebDriverBuilder.java |
| index 0a19551a9a..bbf82e7a38 100644 |
| --- a/java/client/test/org/openqa/selenium/testing/drivers/WebDriverBuilder.java |
| +++ b/java/client/test/org/openqa/selenium/testing/drivers/WebDriverBuilder.java |
| @@ -47,8 +47,12 @@ |
| private static LinkedList<Runnable> shutdownActions = new LinkedList<>(); |
| private static Set<WebDriver> managedDrivers = new HashSet<>(); |
| static { |
| - shutdownActions.add(() -> managedDrivers.forEach(WebDriver::quit)); |
| - Runtime.getRuntime().addShutdownHook(new Thread(() -> shutdownActions.forEach(Runnable::run))); |
| + Runtime.getRuntime().addShutdownHook(new Thread( () -> { |
| + try { |
| + managedDrivers.forEach(WebDriver::quit); |
| + } catch (Exception a ) { |
| + } |
| + })); |
| } |
| |
| static void addShutdownAction(Runnable action) { |