From e345af50d1c0d54080f75f7ff01b024699d374dc Mon Sep 17 00:00:00 2001 From: Andrei Solntsev Date: Mon, 30 Mar 2026 23:51:12 +0300 Subject: [PATCH 1/7] enable BrowserCommandsTest for Firefox Seems that `setDownloadBehavior` has been implemented in Firefox meanwhile. --- .../org/openqa/selenium/bidi/browser/BrowserCommandsTest.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/java/test/org/openqa/selenium/bidi/browser/BrowserCommandsTest.java b/java/test/org/openqa/selenium/bidi/browser/BrowserCommandsTest.java index 45c65f6fafe7e..77dadbf3baa06 100644 --- a/java/test/org/openqa/selenium/bidi/browser/BrowserCommandsTest.java +++ b/java/test/org/openqa/selenium/bidi/browser/BrowserCommandsTest.java @@ -47,7 +47,6 @@ import org.openqa.selenium.support.ui.WebDriverWait; import org.openqa.selenium.testing.JupiterTestBase; import org.openqa.selenium.testing.NeedsFreshDriver; -import org.openqa.selenium.testing.NotYetImplemented; class BrowserCommandsTest extends JupiterTestBase { @@ -133,7 +132,6 @@ void canGetClientWindows() { @Test @NeedsFreshDriver - @NotYetImplemented(FIREFOX) void canSetDownloadBehaviorAllowed() { browser.setDownloadBehavior(new SetDownloadBehaviorParameters(allowed(tmpDir))); @@ -148,7 +146,6 @@ void canSetDownloadBehaviorAllowed() { @Test @NeedsFreshDriver - @NotYetImplemented(FIREFOX) void canSetDownloadBehaviorDenied() throws InterruptedException { browser.setDownloadBehavior(new SetDownloadBehaviorParameters(denied())); @@ -168,7 +165,6 @@ void canSetDownloadBehaviorDenied() throws InterruptedException { @Test @NeedsFreshDriver - @NotYetImplemented(FIREFOX) void canSetDownloadBehaviorWithUserContext() throws InterruptedException { String userContext = browser.createUserContext(); From f545be74757d5979d3a4a9a084715f90aff34bfa Mon Sep 17 00:00:00 2001 From: Andrei Solntsev Date: Mon, 30 Mar 2026 23:52:21 +0300 Subject: [PATCH 2/7] ignore SetNetworkConditionsTest for FireFox beta Seems that `setNetworkConditions` has been enabled in FireFox beat meanwhile (but not in Firefox yet). But we don't have annotation like `@NotYetImplemented(FIREFOX-BETA)`. --- .skipped-tests | 1 + 1 file changed, 1 insertion(+) diff --git a/.skipped-tests b/.skipped-tests index fe68c8b4b9d72..94f46748b3fc1 100644 --- a/.skipped-tests +++ b/.skipped-tests @@ -24,4 +24,5 @@ -//java/test/org/openqa/selenium/bidi/browsingcontext:BrowsingContextInspectorTest-firefox-beta-remote -//java/test/org/openqa/selenium/bidi/browsingcontext:BrowsingContextTest-firefox-beta -//java/test/org/openqa/selenium/bidi/browsingcontext:BrowsingContextTest-firefox-beta-remote +-//java/test/org/openqa/selenium/bidi/emulation:SetNetworkConditionsTest-firefox-beta -//rb/spec/integration/selenium/webdriver/bidi:browsing_context-firefox-beta-bidi From c4e151462ff8dfd45682268ab43b3aed61bc511e Mon Sep 17 00:00:00 2001 From: Andrei Solntsev Date: Mon, 30 Mar 2026 23:53:08 +0300 Subject: [PATCH 3/7] enable showing alerts in Firefox Seems that Firefox behavior with alerts was changed. Without "unhandledPromptBehavior" capability, command `wait.until(alertIsPresent())` is always failing in FireFox. --- java/test/org/openqa/selenium/testing/drivers/Browser.java | 1 + 1 file changed, 1 insertion(+) diff --git a/java/test/org/openqa/selenium/testing/drivers/Browser.java b/java/test/org/openqa/selenium/testing/drivers/Browser.java index 27fdc93b0abcf..3ba9a46fd71a0 100644 --- a/java/test/org/openqa/selenium/testing/drivers/Browser.java +++ b/java/test/org/openqa/selenium/testing/drivers/Browser.java @@ -135,6 +135,7 @@ public Capabilities getCapabilities() { @Override public Capabilities getCapabilities() { FirefoxOptions options = new FirefoxOptions().configureFromEnv(); + options.setCapability("unhandledPromptBehavior", "ignore"); resolveDriverPath("webdriver.gecko.driver"); String binary = InProject.resolveRunfilesPath(System.getProperty("webdriver.firefox.bin")); From 7a852adc52d00fc6fac86637f7c4fe7f5b77c59c Mon Sep 17 00:00:00 2001 From: Andrei Solntsev Date: Tue, 31 Mar 2026 21:49:04 +0300 Subject: [PATCH 4/7] improve `WebScriptTest` tests for `unpinScript` and `addDomMutationHandler` instead of just waiting to latch, collect the logs to a list and assert this list. It gives much clearer assertion error. --- .../org/openqa/selenium/WebScriptTest.java | 119 ++++++++++-------- 1 file changed, 68 insertions(+), 51 deletions(-) diff --git a/java/test/org/openqa/selenium/WebScriptTest.java b/java/test/org/openqa/selenium/WebScriptTest.java index 3db3bcd00db8c..492d84277bb4d 100644 --- a/java/test/org/openqa/selenium/WebScriptTest.java +++ b/java/test/org/openqa/selenium/WebScriptTest.java @@ -17,33 +17,37 @@ package org.openqa.selenium; +import static java.time.Instant.ofEpochMilli; +import static java.time.ZoneId.systemDefault; import static java.util.concurrent.TimeUnit.SECONDS; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.openqa.selenium.support.ui.ExpectedConditions.visibilityOf; import java.time.Duration; +import java.time.format.DateTimeFormatter; +import java.util.List; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.openqa.selenium.bidi.log.ConsoleLogEntry; import org.openqa.selenium.bidi.log.JavascriptLogEntry; import org.openqa.selenium.bidi.log.LogLevel; import org.openqa.selenium.remote.DomMutation; import org.openqa.selenium.remote.RemoteWebDriver; +import org.openqa.selenium.remote.Script; import org.openqa.selenium.support.ui.WebDriverWait; import org.openqa.selenium.testing.JupiterTestBase; import org.openqa.selenium.testing.NeedsFreshDriver; class WebScriptTest extends JupiterTestBase { - String page; + private String page; @Test @NeedsFreshDriver @@ -182,58 +186,52 @@ void canAddMultipleHandlers() throws ExecutionException, InterruptedException, T @Test @NeedsFreshDriver - void canAddDomMutationHandler() throws InterruptedException { - AtomicReference seen = new AtomicReference<>(); - CountDownLatch latch = new CountDownLatch(1); + void canAddDomMutationHandler() { + List mutations = new CopyOnWriteArrayList<>(); - ((RemoteWebDriver) driver) - .script() - .addDomMutationHandler( - mutation -> { - seen.set(mutation); - latch.countDown(); - }); + Script script = ((RemoteWebDriver) driver).script(); + script.addDomMutationHandler(mutationHandler(mutations)); driver.get(pages.dynamicPage); + triggerDomMutation(); - WebElement reveal = driver.findElement(By.id("reveal")); - reveal.click(); - WebElement revealed = driver.findElement(By.id("revealed")); - - new WebDriverWait(driver, Duration.ofSeconds(10)).until(visibilityOf(revealed)); - - Assertions.assertThat(latch.await(10, SECONDS)).isTrue(); - assertThat(seen.get().getAttributeName()).isEqualTo("style"); - assertThat(seen.get().getCurrentValue()).isEmpty(); - assertThat(seen.get().getOldValue()).isEqualTo("display:none;"); + assertThat(mutations).isNotEmpty(); + assertThat(lastOf(mutations)).isEqualTo("style: 'display:none;' -> ''"); } @Test @NeedsFreshDriver - void canRemoveDomMutationHandler() throws InterruptedException { - AtomicReference seen = new AtomicReference<>(); - CountDownLatch latch = new CountDownLatch(1); - - long id = - ((RemoteWebDriver) driver) - .script() - .addDomMutationHandler( - mutation -> { - seen.set(mutation); - latch.countDown(); - }); + void canRemoveDomMutationHandler() { + List mutations = new CopyOnWriteArrayList<>(); + Script script = ((RemoteWebDriver) driver).script(); + long id = script.addDomMutationHandler(mutationHandler(mutations)); driver.get(pages.dynamicPage); + triggerDomMutation(); + assertThat(mutations).isNotEmpty(); + + script.removeDomMutationHandler(id); - ((RemoteWebDriver) driver).script().removeDomMutationHandler(id); + mutations.clear(); + driver.get(pages.dynamicPage); + triggerDomMutation(); + assertThat(mutations).isEmpty(); + } + private void triggerDomMutation() { WebElement reveal = driver.findElement(By.id("reveal")); reveal.click(); WebElement revealed = driver.findElement(By.id("revealed")); - new WebDriverWait(driver, Duration.ofSeconds(10)).until(visibilityOf(revealed)); + } - Assertions.assertThat(latch.await(10, SECONDS)).isFalse(); + private static Consumer mutationHandler(List mutations) { + return mutation -> { + mutations.add( + String.format( + "%s: '%s' -> '%s'", + mutation.getAttributeName(), mutation.getOldValue(), mutation.getCurrentValue())); + }; } @Test @@ -257,27 +255,46 @@ void canPinScript() throws ExecutionException, InterruptedException, TimeoutExce @Test @NeedsFreshDriver - void canUnpinScript() { - CountDownLatch latch = new CountDownLatch(2); + void canUnpinScript() throws InterruptedException { + List logs = new CopyOnWriteArrayList<>(); + CountDownLatch latch = new CountDownLatch(1); + + Script script = ((RemoteWebDriver) driver).script(); + String pinnedScript = script.pin("() => { console.log('Hello!'); }"); - String pinnedScript = - ((RemoteWebDriver) driver).script().pin("() => { console.log('Hello!'); }"); + DateTimeFormatter formatter = + DateTimeFormatter.ofPattern("HH:mm:ss:SSS").withZone(systemDefault()); long id = - ((RemoteWebDriver) driver) - .script() - .addConsoleMessageHandler(consoleLogEntry -> latch.countDown()); + script.addConsoleMessageHandler( + log -> { + String time = formatter.format(ofEpochMilli(log.getTimestamp())); + String message = String.format("%s %s", log.getText(), time); + logs.add(message); + latch.countDown(); + }); - page = appServer.whereIs("/bidi/logEntryAdded.html"); + try { + page = appServer.whereIs("/bidi/logEntryAdded.html"); + assertThat(logs).hasSize(0); - driver.get(page); + driver.get(page); + assertThat(latch.await(10, SECONDS)).isTrue(); - ((RemoteWebDriver) driver).script().unpin(pinnedScript); + assertThat(logs).as("Chrome logs once, FireFox logs twice").isNotEmpty(); + assertThat(logs.get(0)).startsWith("Hello!"); - driver.get(page); + script.unpin(pinnedScript); - assertThat(latch.getCount()).isEqualTo(1L); + logs.clear(); + driver.get(page); + assertThat(logs).as("Script has been unpinned, no logs anymore.").isEmpty(); + } finally { + script.removeConsoleMessageHandler(id); + } + } - ((RemoteWebDriver) driver).script().removeConsoleMessageHandler(id); + private static T lastOf(List list) { + return list.get(list.size() - 1); } } From a93aec780d7ea4b4d39a9caeac48ae93647472ef Mon Sep 17 00:00:00 2001 From: Andrei Solntsev Date: Wed, 1 Apr 2026 08:21:39 +0300 Subject: [PATCH 5/7] fixup: browser behavior in ff --- .../openqa/selenium/bidi/browser/BrowserCommandsTest.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/java/test/org/openqa/selenium/bidi/browser/BrowserCommandsTest.java b/java/test/org/openqa/selenium/bidi/browser/BrowserCommandsTest.java index 77dadbf3baa06..5307c436a98bf 100644 --- a/java/test/org/openqa/selenium/bidi/browser/BrowserCommandsTest.java +++ b/java/test/org/openqa/selenium/bidi/browser/BrowserCommandsTest.java @@ -22,8 +22,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.openqa.selenium.bidi.browser.DownloadBehavior.allowed; import static org.openqa.selenium.bidi.browser.DownloadBehavior.denied; -import static org.openqa.selenium.testing.drivers.Browser.FIREFOX; -import static org.openqa.selenium.testing.drivers.Browser.detect; import java.io.IOException; import java.io.UncheckedIOException; @@ -61,9 +59,7 @@ final void setUp() { @AfterEach final void resetDownloadBehavior() { - if (detect() != FIREFOX) { - browser.setDownloadBehavior(new SetDownloadBehaviorParameters(null)); - } + browser.setDownloadBehavior(new SetDownloadBehaviorParameters(null)); } @AfterEach From 7b346deb295bfe7282c9e37a99641f173fbba846 Mon Sep 17 00:00:00 2001 From: Andrei Solntsev Date: Wed, 1 Apr 2026 08:25:39 +0300 Subject: [PATCH 6/7] fixup: alerts --- .../org/openqa/selenium/UnexpectedAlertBehaviorTest.java | 5 ++++- java/test/org/openqa/selenium/testing/drivers/Browser.java | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/java/test/org/openqa/selenium/UnexpectedAlertBehaviorTest.java b/java/test/org/openqa/selenium/UnexpectedAlertBehaviorTest.java index 2126d99aa3415..24ee6cf14d8e4 100644 --- a/java/test/org/openqa/selenium/UnexpectedAlertBehaviorTest.java +++ b/java/test/org/openqa/selenium/UnexpectedAlertBehaviorTest.java @@ -18,11 +18,13 @@ package org.openqa.selenium; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.openqa.selenium.UnexpectedAlertBehaviour.DISMISS_AND_NOTIFY; import static org.openqa.selenium.UnexpectedAlertBehaviour.IGNORE; import static org.openqa.selenium.WaitingConditions.elementTextToEqual; import static org.openqa.selenium.remote.CapabilityType.UNHANDLED_PROMPT_BEHAVIOUR; import static org.openqa.selenium.testing.drivers.Browser.CHROME; import static org.openqa.selenium.testing.drivers.Browser.EDGE; +import static org.openqa.selenium.testing.drivers.Browser.FIREFOX; import static org.openqa.selenium.testing.drivers.Browser.SAFARI; import java.time.Duration; @@ -58,7 +60,7 @@ public void canSilentlyAcceptUnhandledAlert() { @Ignore(value = EDGE, reason = "Unstable Chrome behavior") @NoDriverBeforeTest public void canDismissUnhandledAlert() { - runScenarioWithUnhandledAlert(UnexpectedAlertBehaviour.DISMISS_AND_NOTIFY, "null", false); + runScenarioWithUnhandledAlert(DISMISS_AND_NOTIFY, "null", false); } @Test @@ -72,6 +74,7 @@ public void canSilentlyDismissUnhandledAlert() { @Test @Ignore(value = CHROME, reason = "Chrome uses IGNORE mode by default") @Ignore(value = EDGE, reason = "Edge uses IGNORE mode by default") + @Ignore(value = FIREFOX, reason = "Browser#FIREFOX sets IGNORE mode by default") @NoDriverBeforeTest public void canDismissUnhandledAlertsByDefault() { runScenarioWithUnhandledAlert(null, "null", false); diff --git a/java/test/org/openqa/selenium/testing/drivers/Browser.java b/java/test/org/openqa/selenium/testing/drivers/Browser.java index 3ba9a46fd71a0..a1afac2972437 100644 --- a/java/test/org/openqa/selenium/testing/drivers/Browser.java +++ b/java/test/org/openqa/selenium/testing/drivers/Browser.java @@ -17,6 +17,7 @@ package org.openqa.selenium.testing.drivers; +import static org.openqa.selenium.UnexpectedAlertBehaviour.IGNORE; import static org.openqa.selenium.remote.CapabilityType.BROWSER_NAME; import static org.openqa.selenium.remote.CapabilityType.UNHANDLED_PROMPT_BEHAVIOUR; @@ -135,7 +136,7 @@ public Capabilities getCapabilities() { @Override public Capabilities getCapabilities() { FirefoxOptions options = new FirefoxOptions().configureFromEnv(); - options.setCapability("unhandledPromptBehavior", "ignore"); + options.setCapability(UNHANDLED_PROMPT_BEHAVIOUR, IGNORE); resolveDriverPath("webdriver.gecko.driver"); String binary = InProject.resolveRunfilesPath(System.getProperty("webdriver.firefox.bin")); From d7bfd69b146a78d43706680526953e650aaed771 Mon Sep 17 00:00:00 2001 From: Andrei Solntsev Date: Thu, 2 Apr 2026 00:23:05 +0300 Subject: [PATCH 7/7] ignore SetNetworkConditionsTest on "firefox-beta-remote" --- .skipped-tests | 1 + 1 file changed, 1 insertion(+) diff --git a/.skipped-tests b/.skipped-tests index 94f46748b3fc1..8534b5ce424e5 100644 --- a/.skipped-tests +++ b/.skipped-tests @@ -25,4 +25,5 @@ -//java/test/org/openqa/selenium/bidi/browsingcontext:BrowsingContextTest-firefox-beta -//java/test/org/openqa/selenium/bidi/browsingcontext:BrowsingContextTest-firefox-beta-remote -//java/test/org/openqa/selenium/bidi/emulation:SetNetworkConditionsTest-firefox-beta +-//java/test/org/openqa/selenium/bidi/emulation:SetNetworkConditionsTest-firefox-beta-remote -//rb/spec/integration/selenium/webdriver/bidi:browsing_context-firefox-beta-bidi