From 9f36391a83d6a1e6e38fc09b9ec730925a2da686 Mon Sep 17 00:00:00 2001 From: Andrei Solntsev Date: Tue, 9 Dec 2025 23:38:10 +0200 Subject: [PATCH 1/8] Open a blank page before every test It's a good practice to avoid tests affecting each other: 1. Open "about:blank" page - this stops any current activity / background requests / animations on the previous page 2. Open an empty page which clears sessionStorage, localStorage and cookies. This technique allows reusing the browser between tests, while keeping the tests independent. --- java/test/org/openqa/selenium/testing/JupiterTestBase.java | 6 ++++++ javascript/atoms/test/testdata/blank_page.html | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/java/test/org/openqa/selenium/testing/JupiterTestBase.java b/java/test/org/openqa/selenium/testing/JupiterTestBase.java index a540bafb7c849..43174905625e0 100644 --- a/java/test/org/openqa/selenium/testing/JupiterTestBase.java +++ b/java/test/org/openqa/selenium/testing/JupiterTestBase.java @@ -84,6 +84,12 @@ public void prepareEnvironment() { driver = seleniumExtension.getDriver(); wait = seleniumExtension::waitUntil; shortWait = seleniumExtension::shortWaitUntil; + + if (driver != null) { + driver.get("about:blank"); + driver.get(pages.blankPage); + driver.manage().deleteAllCookies(); + } } @AfterEach diff --git a/javascript/atoms/test/testdata/blank_page.html b/javascript/atoms/test/testdata/blank_page.html index ca07461eacd0a..e649a52f2f997 100644 --- a/javascript/atoms/test/testdata/blank_page.html +++ b/javascript/atoms/test/testdata/blank_page.html @@ -4,7 +4,10 @@ This page deliberately left blank - + From 5947387ac71292da2565f26add330df01e6c123d Mon Sep 17 00:00:00 2001 From: Andrei Solntsev Date: Tue, 9 Dec 2025 23:46:56 +0200 Subject: [PATCH 2/8] Avoid `sleep(2000)` in hover tests Instead of wasting 2 second (which doesn't guarantee the result), just wait for the needed element that should appear as a result of hovering. --- .../bidi/input/CombinedInputActionsTest.java | 43 ++++++++++--------- .../selenium/bidi/input/DefaultMouseTest.java | 35 +++++++++------ .../CombinedInputActionsTest.java | 42 +++++++++--------- .../interactions/DefaultMouseTest.java | 35 +++++++++------ .../selenium/interactions/PenPointerTest.java | 37 +++++++++------- 5 files changed, 107 insertions(+), 85 deletions(-) diff --git a/java/test/org/openqa/selenium/bidi/input/CombinedInputActionsTest.java b/java/test/org/openqa/selenium/bidi/input/CombinedInputActionsTest.java index 38b1e67e6b9ca..fd7230db98634 100644 --- a/java/test/org/openqa/selenium/bidi/input/CombinedInputActionsTest.java +++ b/java/test/org/openqa/selenium/bidi/input/CombinedInputActionsTest.java @@ -20,10 +20,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.data.Offset.offset; import static org.junit.jupiter.api.Assumptions.assumeFalse; -import static org.openqa.selenium.WaitingConditions.elementValueToEqual; -import static org.openqa.selenium.WaitingConditions.windowHandleCountToBe; -import static org.openqa.selenium.support.ui.ExpectedConditions.presenceOfElementLocated; -import static org.openqa.selenium.support.ui.ExpectedConditions.titleIs; +import static org.openqa.selenium.WaitingConditions.*; +import static org.openqa.selenium.support.ui.ExpectedConditions.*; import static org.openqa.selenium.testing.TestUtilities.getEffectivePlatform; import static org.openqa.selenium.testing.TestUtilities.getIEVersion; import static org.openqa.selenium.testing.TestUtilities.isInternetExplorer; @@ -40,7 +38,6 @@ import org.openqa.selenium.Keys; import org.openqa.selenium.Platform; import org.openqa.selenium.Point; -import org.openqa.selenium.WaitingConditions; import org.openqa.selenium.WebElement; import org.openqa.selenium.bidi.module.Input; import org.openqa.selenium.bidi.module.Script; @@ -416,28 +413,32 @@ public void testHoldingDownShiftKeyWhileClicking() { } @Test - public void canClickOnASuckerFishStyleMenu() throws InterruptedException { + public void canClickOnASuckerFishStyleMenu() { driver.get(pages.javascriptPage); + unfocusMenu(); - // Move to a different element to make sure the mouse is not over the - // element with id 'item1' (from a previous test). - new Actions(driver).moveToElement(driver.findElement(By.id("dynamo"))).build().perform(); - - WebElement element = driver.findElement(By.id("menu1")); + WebElement menu = driver.findElement(By.id("menu1")); + WebElement menuItem = driver.findElement(By.id("item1")); + assertThat(menuItem.isDisplayed()).isFalse(); + assertThat(driver.findElement(By.id("result")).getText()).isBlank(); - final WebElement item = driver.findElement(By.id("item1")); - assertThat(item.getText()).isEmpty(); - - ((JavascriptExecutor) driver).executeScript("arguments[0].style.background = 'green'", element); - input.perform(windowHandle, new Actions(driver).moveToElement(element).getSequences()); + // Hover the menu icon + input.perform(windowHandle, new Actions(driver).moveToElement(menu).getSequences()); + ((JavascriptExecutor) driver).executeScript("arguments[0].style.background = 'green'", menu); - // Intentionally wait to make sure hover persists. - Thread.sleep(2000); + // Wait until the menu items appear + shortWait.until(visibilityOf(menuItem)); - item.click(); + menuItem.click(); + wait.until(elementTextToEqual(By.id("result"), "item 1")); + } - WebElement result = driver.findElement(By.id("result")); - wait.until(WaitingConditions.elementTextToContain(result, "item 1")); + /** + * Move to a different element to make sure the mouse is not over the menu items (from a previous + * test). + */ + private void unfocusMenu() { + new Actions(driver).moveToElement(driver.findElement(By.id("dynamo"))).build().perform(); } @Test diff --git a/java/test/org/openqa/selenium/bidi/input/DefaultMouseTest.java b/java/test/org/openqa/selenium/bidi/input/DefaultMouseTest.java index 0807a06d7c3f1..73b7cc89e8553 100644 --- a/java/test/org/openqa/selenium/bidi/input/DefaultMouseTest.java +++ b/java/test/org/openqa/selenium/bidi/input/DefaultMouseTest.java @@ -288,26 +288,33 @@ public void testShouldAllowUsersToHoverOverElements() { } @Test - public void testHoverPersists() throws Exception { + public void testHoverPersists() { driver.get(pages.javascriptPage); - // Move to a different element to make sure the mouse is not over the - // element with id 'item1' (from a previous test). - getBuilder(driver).moveToElement(driver.findElement(By.id("dynamo"))).build().perform(); + unfocusMenu(); - WebElement element = driver.findElement(By.id("menu1")); + WebElement menu = driver.findElement(By.id("menu1")); + WebElement menuItem = driver.findElement(By.id("item1")); + assertThat(menuItem.isDisplayed()).isFalse(); + assertThat(driver.findElement(By.id("result")).getText()).isBlank(); - final WebElement item = driver.findElement(By.id("item1")); - assertThat(item.getText()).isEmpty(); + // Hover the menu icon + inputModule.perform(windowHandle, getBuilder(driver).moveToElement(menu).getSequences()); + ((JavascriptExecutor) driver).executeScript("arguments[0].style.background = 'green'", menu); - ((JavascriptExecutor) driver).executeScript("arguments[0].style.background = 'green'", element); - inputModule.perform(windowHandle, getBuilder(driver).moveToElement(element).getSequences()); + // Wait until the menu items appear + shortWait.until(visibilityOf(menuItem)); + assertThat(menuItem.getText()).isEqualTo("Item 1"); - // Intentionally wait to make sure hover persists. - Thread.sleep(2000); - - wait.until(not(elementTextToEqual(item, ""))); + menuItem.click(); + wait.until(elementTextToEqual(By.id("result"), "item 1")); + } - assertThat(item.getText()).isEqualTo("Item 1"); + /** + * Move to a different element to make sure the mouse is not over the menu items (from a previous + * test). + */ + private void unfocusMenu() { + getBuilder(driver).moveToElement(driver.findElement(By.id("dynamo"))).build().perform(); } @Test diff --git a/java/test/org/openqa/selenium/interactions/CombinedInputActionsTest.java b/java/test/org/openqa/selenium/interactions/CombinedInputActionsTest.java index 4eaed1b1321a9..f1d1269a8c305 100644 --- a/java/test/org/openqa/selenium/interactions/CombinedInputActionsTest.java +++ b/java/test/org/openqa/selenium/interactions/CombinedInputActionsTest.java @@ -19,10 +19,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assumptions.assumeFalse; -import static org.openqa.selenium.WaitingConditions.elementValueToEqual; -import static org.openqa.selenium.WaitingConditions.windowHandleCountToBe; -import static org.openqa.selenium.support.ui.ExpectedConditions.presenceOfElementLocated; -import static org.openqa.selenium.support.ui.ExpectedConditions.titleIs; +import static org.openqa.selenium.WaitingConditions.*; +import static org.openqa.selenium.support.ui.ExpectedConditions.*; import static org.openqa.selenium.testing.TestUtilities.getEffectivePlatform; import static org.openqa.selenium.testing.TestUtilities.getIEVersion; import static org.openqa.selenium.testing.TestUtilities.isInternetExplorer; @@ -40,7 +38,6 @@ import org.openqa.selenium.Keys; import org.openqa.selenium.Platform; import org.openqa.selenium.Point; -import org.openqa.selenium.WaitingConditions; import org.openqa.selenium.WebElement; import org.openqa.selenium.testing.Ignore; import org.openqa.selenium.testing.JupiterTestBase; @@ -385,26 +382,31 @@ public void testHoldingDownShiftKeyWhileClicking() { @NotYetImplemented(SAFARI) public void canClickOnASuckerFishStyleMenu() throws InterruptedException { driver.get(pages.javascriptPage); + unfocusMenu(); - // Move to a different element to make sure the mouse is not over the - // element with id 'item1' (from a previous test). - new Actions(driver).moveToElement(driver.findElement(By.id("dynamo"))).build().perform(); + WebElement menu = driver.findElement(By.id("menu1")); + WebElement menuItem = driver.findElement(By.id("item1")); + assertThat(menuItem.isDisplayed()).isFalse(); + assertThat(driver.findElement(By.id("result")).getText()).isBlank(); - WebElement element = driver.findElement(By.id("menu1")); - - final WebElement item = driver.findElement(By.id("item1")); - assertThat(item.getText()).isEmpty(); - - ((JavascriptExecutor) driver).executeScript("arguments[0].style.background = 'green'", element); - new Actions(driver).moveToElement(element).build().perform(); + // Hover the menu icon + new Actions(driver).moveToElement(menu).build().perform(); + ((JavascriptExecutor) driver).executeScript("arguments[0].style.background = 'green'", menu); - // Intentionally wait to make sure hover persists. - Thread.sleep(2000); + // Wait until the menu items appear + shortWait.until(visibilityOf(menuItem)); + assertThat(menuItem.getText()).isEqualTo("Item 1"); - item.click(); + menuItem.click(); + wait.until(elementTextToEqual(By.id("result"), "item 1")); + } - WebElement result = driver.findElement(By.id("result")); - wait.until(WaitingConditions.elementTextToContain(result, "item 1")); + /** + * Move to a different element to make sure the mouse is not over the menu items (from a previous + * test). + */ + private void unfocusMenu() { + driver.findElement(By.id("dynamo")).click(); } @Test diff --git a/java/test/org/openqa/selenium/interactions/DefaultMouseTest.java b/java/test/org/openqa/selenium/interactions/DefaultMouseTest.java index 00b00471a6833..09b2ee37d5bec 100644 --- a/java/test/org/openqa/selenium/interactions/DefaultMouseTest.java +++ b/java/test/org/openqa/selenium/interactions/DefaultMouseTest.java @@ -260,26 +260,33 @@ public void testShouldAllowUsersToHoverOverElements() { @Test @NotYetImplemented(SAFARI) - public void testHoverPersists() throws Exception { + public void testHoverPersists() { driver.get(pages.javascriptPage); - // Move to a different element to make sure the mouse is not over the - // element with id 'item1' (from a previous test). - getBuilder(driver).moveToElement(driver.findElement(By.id("dynamo"))).build().perform(); + unfocusMenu(); - WebElement element = driver.findElement(By.id("menu1")); + WebElement menu = driver.findElement(By.id("menu1")); + WebElement menuItem = driver.findElement(By.id("item1")); + assertThat(menuItem.isDisplayed()).isFalse(); + assertThat(driver.findElement(By.id("result")).getText()).isBlank(); - final WebElement item = driver.findElement(By.id("item1")); - assertThat(item.getText()).isEmpty(); + // Hover the menu icon + getBuilder(driver).moveToElement(menu).build().perform(); + ((JavascriptExecutor) driver).executeScript("arguments[0].style.background = 'green'", menu); - ((JavascriptExecutor) driver).executeScript("arguments[0].style.background = 'green'", element); - getBuilder(driver).moveToElement(element).build().perform(); + // Wait until the menu items appear + wait.until(visibilityOf(menuItem)); + assertThat(menuItem.getText()).isEqualTo("Item 1"); - // Intentionally wait to make sure hover persists. - Thread.sleep(2000); - - wait.until(not(elementTextToEqual(item, ""))); + menuItem.click(); + wait.until(elementTextToEqual(By.id("result"), "item 1")); + } - assertThat(item.getText()).isEqualTo("Item 1"); + /** + * Move to a different element to make sure the mouse is not over the menu items (from a previous + * test). + */ + private void unfocusMenu() { + getBuilder(driver).moveToElement(driver.findElement(By.id("dynamo"))).build().perform(); } @Test diff --git a/java/test/org/openqa/selenium/interactions/PenPointerTest.java b/java/test/org/openqa/selenium/interactions/PenPointerTest.java index 1dcb6affdcaf1..25d1f9ae38391 100644 --- a/java/test/org/openqa/selenium/interactions/PenPointerTest.java +++ b/java/test/org/openqa/selenium/interactions/PenPointerTest.java @@ -215,28 +215,33 @@ public void testShouldAllowUsersToHoverOverElements() { @Test @NotYetImplemented(SAFARI) - public void testHoverPersists() throws Exception { + public void testHoverPersists() { driver.get(pages.javascriptPage); - // Move to a different element to make sure the pen is not over the - // element with id 'item1' (from a previous test). + unfocusMenu(); - setDefaultPen(driver).moveToElement(driver.findElement(By.id("dynamo"))).build().perform(); + WebElement menu = driver.findElement(By.id("menu1")); + WebElement menuItem = driver.findElement(By.id("item1")); + assertThat(menuItem.isDisplayed()).isFalse(); + assertThat(driver.findElement(By.id("result")).getText()).isBlank(); - WebElement element = driver.findElement(By.id("menu1")); + // Hover the menu icon + setDefaultPen(driver).moveToElement(menu).build().perform(); + ((JavascriptExecutor) driver).executeScript("arguments[0].style.background = 'green'", menu); - final WebElement item = driver.findElement(By.id("item1")); - assertThat(item.getText()).isEmpty(); + // Wait until the menu items appear + wait.until(visibilityOf(menuItem)); + assertThat(menuItem.getText()).isEqualTo("Item 1"); - ((JavascriptExecutor) driver).executeScript("arguments[0].style.background = 'green'", element); - - setDefaultPen(driver).moveToElement(element).build().perform(); - - // Intentionally wait to make sure hover persists. - Thread.sleep(2000); - - wait.until(not(elementTextToEqual(item, ""))); + menuItem.click(); + wait.until(elementTextToEqual(By.id("result"), "item 1")); + } - assertThat(item.getText()).isEqualTo("Item 1"); + /** + * Move to a different element to make sure the mouse is not over the menu items (from a previous + * test). + */ + private void unfocusMenu() { + setDefaultPen(driver).moveToElement(driver.findElement(By.id("dynamo"))).build().perform(); } @Test From bf5d0926bcc9de36b06bed53e40f990cff93d731 Mon Sep 17 00:00:00 2001 From: Andrei Solntsev Date: Tue, 9 Dec 2025 23:56:24 +0200 Subject: [PATCH 3/8] use much shorter polling interval to speed up the tests if the first try failed, wasting the whole 0.5 second is a huge waste of time. Let's try sooner! --- java/test/org/openqa/selenium/testing/SeleniumExtension.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/test/org/openqa/selenium/testing/SeleniumExtension.java b/java/test/org/openqa/selenium/testing/SeleniumExtension.java index aa2b65429739c..0447443552a09 100644 --- a/java/test/org/openqa/selenium/testing/SeleniumExtension.java +++ b/java/test/org/openqa/selenium/testing/SeleniumExtension.java @@ -307,8 +307,8 @@ private static class Instances { public Instances(WebDriver driver, Duration regularWait, Duration shortWait) { this.driver = driver; - this.regularWait = new WebDriverWait(driver, regularWait); - this.shortWait = new WebDriverWait(driver, shortWait); + this.regularWait = new WebDriverWait(driver, regularWait, Duration.ofMillis(20)); + this.shortWait = new WebDriverWait(driver, shortWait, Duration.ofMillis(20)); } } From 1f4c5f24825b7047f120445f17f00d1a4f4675e2 Mon Sep 17 00:00:00 2001 From: Andrei Solntsev Date: Wed, 10 Dec 2025 00:02:33 +0200 Subject: [PATCH 4/8] Avoid `sleep` in drag'n'drop tests fix the test page usability: make the elements visible only after they are fully initialized. To force revealing potential flaky tests in the future, I've added a small pause for the initialization code. So the tests should wait until the element appears on the screen - then it's ready for manipulations. --- common/src/web/dragAndDropTest.html | 18 +++-- common/src/web/draggableLists.html | 9 ++- common/src/web/droppableItems.html | 43 ++++++------ common/src/web/macbeth.html | 2 + .../selenium/CorrectEventFiringTest.java | 26 +------- .../openqa/selenium/ElementAttributeTest.java | 9 --- .../openqa/selenium/WaitingConditions.java | 60 +++++++++++------ .../selenium/WaitingConditionsTest.java | 58 +++++++++++++++++ .../bidi/input/DefaultKeyboardTest.java | 28 ++++---- .../selenium/bidi/input/DefaultMouseTest.java | 52 +++------------ .../selenium/bidi/input/DragAndDropTest.java | 60 +++++------------ .../interactions/DefaultMouseTest.java | 44 +++---------- .../interactions/DragAndDropTest.java | 65 ++++++------------- .../selenium/interactions/PenPointerTest.java | 32 +++------ 14 files changed, 222 insertions(+), 284 deletions(-) create mode 100644 java/test/org/openqa/selenium/WaitingConditionsTest.java diff --git a/common/src/web/dragAndDropTest.html b/common/src/web/dragAndDropTest.html index fdee16b0b4ebe..5d8598f89f0a9 100644 --- a/common/src/web/dragAndDropTest.html +++ b/common/src/web/dragAndDropTest.html @@ -4,6 +4,7 @@ -
-
+
+
"Hi there
-
-
+
+
diff --git a/common/src/web/draggableLists.html b/common/src/web/draggableLists.html index df1fcdc538f65..81c9a7c432e50 100644 --- a/common/src/web/draggableLists.html +++ b/common/src/web/draggableLists.html @@ -14,6 +14,7 @@
-
    + -
      +