diff --git a/docs-site/docs/guides/wait-engine.md b/docs-site/docs/guides/wait-engine.md index 525a87f..13ce39e 100644 --- a/docs-site/docs/guides/wait-engine.md +++ b/docs-site/docs/guides/wait-engine.md @@ -36,7 +36,22 @@ getWait().waitForText(By.cssSelector("h1"), "Welcome back"); ### Attribute value ```java -getWait().waitForAttributeContains(By.id("status"), "class", "active"); +getWait().waitForAttributeContains(By.id("status"), "class", "active"); // substring +getWait().waitForAttribute(By.id("status"), "aria-expanded", "true"); // exact match +``` + +### Text matches (regex) + +```java +// Wait until the element's visible text matches a regular expression +getWait().waitForTextMatches(By.cssSelector(".total"), "\\$\\d+\\.\\d{2}"); +``` + +### URL matches (regex) + +```java +getWait().waitForUrlContains("/orders"); // substring +getWait().waitForUrlMatches(".*/orders/\\d+"); // regular expression ``` ### DOM staleness diff --git a/src/main/java/com/seleniumboot/wait/WaitEngine.java b/src/main/java/com/seleniumboot/wait/WaitEngine.java index 74cd08c..8e93ed0 100644 --- a/src/main/java/com/seleniumboot/wait/WaitEngine.java +++ b/src/main/java/com/seleniumboot/wait/WaitEngine.java @@ -17,6 +17,7 @@ import org.openqa.selenium.support.ui.WebDriverWait; import java.time.Duration; +import java.util.regex.Pattern; /** * Centralized explicit wait handler. @@ -90,6 +91,31 @@ public static WebElement waitForAttributeContains(By locator, String attribute, return DriverManager.getDriver().findElement(locator); } + /** + * Waits until the element's attribute equals {@code value} exactly. + * Use {@link #waitForAttributeContains(By, String, String)} for a substring match. + * + *
+ * WaitEngine.waitForAttribute(By.id("status"), "aria-expanded", "true");
+ *
+ */
+ public static WebElement waitForAttribute(By locator, String attribute, String value) {
+ createWait().until(ExpectedConditions.attributeToBe(locator, attribute, value));
+ return DriverManager.getDriver().findElement(locator);
+ }
+
+ /**
+ * Waits until the element's visible text matches the given regular expression.
+ *
+ *
+ * WaitEngine.waitForTextMatches(By.cssSelector(".total"), "\\$\\d+\\.\\d{2}");
+ *
+ */
+ public static WebElement waitForTextMatches(By locator, String textRegex) {
+ createWait().until(ExpectedConditions.textMatches(locator, Pattern.compile(textRegex)));
+ return DriverManager.getDriver().findElement(locator);
+ }
+
// ----------------------------------------------------------
// Navigation
// ----------------------------------------------------------
@@ -104,6 +130,19 @@ public static boolean waitForUrlContains(String partialUrl) {
.until(ExpectedConditions.urlContains(partialUrl));
}
+ /**
+ * Waits until the current URL matches the given regular expression.
+ * Use {@link #waitForUrlContains(String)} for a simple substring match.
+ *
+ *
+ * WaitEngine.waitForUrlMatches(".*/orders/\\d+");
+ *
+ */
+ public static boolean waitForUrlMatches(String urlRegex) {
+ return createWait()
+ .until(ExpectedConditions.urlMatches(urlRegex));
+ }
+
public static void waitForPageLoad() {
createWait().until(driver ->
"complete".equals(((JavascriptExecutor) driver)
diff --git a/src/test/java/com/seleniumboot/unit/WaitEngineTest.java b/src/test/java/com/seleniumboot/unit/WaitEngineTest.java
new file mode 100644
index 0000000..2fe03be
--- /dev/null
+++ b/src/test/java/com/seleniumboot/unit/WaitEngineTest.java
@@ -0,0 +1,92 @@
+package com.seleniumboot.unit;
+
+import com.seleniumboot.config.SeleniumBootConfig;
+import com.seleniumboot.driver.DriverManager;
+import com.seleniumboot.internal.SeleniumBootContext;
+import com.seleniumboot.wait.WaitEngine;
+import org.mockito.MockedStatic;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.*;
+
+/**
+ * Unit tests for the newer {@link WaitEngine} conditions
+ * ({@code waitForAttribute}, {@code waitForUrlMatches}, {@code waitForTextMatches}).
+ *
+ * Uses a mocked {@link WebDriver} whose state already satisfies each condition,
+ * so {@code WebDriverWait} succeeds on the first poll — no real browser required.
+ */
+public class WaitEngineTest {
+
+ private WebDriver mockDriver;
+ private MockedStatic