All skills
fugazi avatar

/webapp-selenium-testing

@ef704d5

Author and maintain versioned Selenium WebDriver tests with Java and JUnit 5. Use for creating, debugging, or running Selenium specs, implementing Page Objects, handling explicit waits, capturing screenshots, or setting up Maven test projects. Supports Chrome, Firefox, and Edge. Keywords: Selenium WebDriver, Java, JUnit 5, Page Object Model, explicit waits, Maven, screenshots.

Use this Skill: https://skilld.dev/gh/fugazi/test-automation-skills-agents/webapp-selenium-testing

This session only. Nothing lands on disk.

referenceswait-strategies-custom-waits.md

≈1.4k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Wait Strategies Custom Conditions And Patterns

Part of the webapp-selenium-testing skill. See SKILL.md for full context.

Related: this file was split from the original wait-strategies.md. See the other related files in this folder.

Custom Wait Conditions

Using Lambda Expressions

// Wait for specific number of elements
wait.until(driver ->
    driver.findElements(By.cssSelector(".item")).size() >= 5
);

// Wait for element attribute to change
wait.until(driver -> {
    String value = driver.findElement(By.id("status")).getAttribute("data-state");
    return "complete".equals(value);
});

// Wait for JavaScript variable
wait.until(driver ->
    ((JavascriptExecutor) driver).executeScript("return window.appReady === true")
);

// Wait for AJAX to complete (jQuery)
wait.until(driver ->
    (Boolean) ((JavascriptExecutor) driver).executeScript(
        "return jQuery.active === 0"
    )
);

Creating Reusable Custom Conditions

public class CustomExpectedConditions {

    /**
     * Wait for element's text to change from initial value
     */
    public static ExpectedCondition<Boolean> textToChange(By locator, String initialText) {
        return driver -> {
            try {
                String currentText = driver.findElement(locator).getText();
                return !currentText.equals(initialText);
            } catch (StaleElementReferenceException e) {
                return true;  // Element changed
            }
        };
    }

    /**
     * Wait for element count to be at least N
     */
    public static ExpectedCondition<Boolean> elementCountAtLeast(By locator, int count) {
        return driver -> driver.findElements(locator).size() >= count;
    }

    /**
     * Wait for element to have non-empty text
     */
    public static ExpectedCondition<WebElement> elementHasText(By locator) {
        return driver -> {
            WebElement element = driver.findElement(locator);
            String text = element.getText();
            return (text != null && !text.trim().isEmpty()) ? element : null;
        };
    }

    /**
     * Wait for page to finish loading (document.readyState)
     */
    public static ExpectedCondition<Boolean> pageLoadComplete() {
        return driver -> {
            String state = ((JavascriptExecutor) driver)
                .executeScript("return document.readyState")
                .toString();
            return "complete".equals(state);
        };
    }

    /**
     * Wait for element to stop moving (animations)
     */
    public static ExpectedCondition<Boolean> elementStoppedMoving(WebElement element) {
        return new ExpectedCondition<>() {
            private Point lastLocation;

            @Override
            public Boolean apply(WebDriver driver) {
                Point currentLocation = element.getLocation();
                boolean stopped = currentLocation.equals(lastLocation);
                lastLocation = currentLocation;
                return stopped;
            }
        };
    }
}

// Usage
wait.until(CustomExpectedConditions.textToChange(By.id("status"), "Loading"));
wait.until(CustomExpectedConditions.elementCountAtLeast(By.cssSelector(".row"), 10));

Common Wait Patterns

Wait for Page Load After Click

@Step("Click and wait for navigation")
protected void clickAndWaitForUrl(By locator, String expectedUrlPart) {
    click(locator);
    wait.until(ExpectedConditions.urlContains(expectedUrlPart));
}

// Usage
clickAndWaitForUrl(loginButton, "/dashboard");

Wait for Loading Spinner

@Step("Wait for loading to complete")
protected void waitForLoading() {
    // Wait for spinner to appear (if it will)
    try {
        shortWait.until(ExpectedConditions.visibilityOfElementLocated(loadingSpinner));
    } catch (TimeoutException e) {
        // Spinner may already be gone or loading was instant
        return;
    }
    // Wait for spinner to disappear
    wait.until(ExpectedConditions.invisibilityOfElementLocated(loadingSpinner));
}

Wait for Modal

private final By modal = By.cssSelector("[role='dialog']");
private final By modalBackdrop = By.cssSelector(".modal-backdrop");

@Step("Wait for modal to open")
protected void waitForModalOpen() {
    wait.until(ExpectedConditions.visibilityOfElementLocated(modal));
}

@Step("Wait for modal to close")
protected void waitForModalClose() {
    wait.until(ExpectedConditions.invisibilityOfElementLocated(modal));
    wait.until(ExpectedConditions.invisibilityOfElementLocated(modalBackdrop));
}

Wait for Table Data

@Step("Wait for table to have data")
protected void waitForTableData(By tableRows, int minRows) {
    wait.until(driver ->
        driver.findElements(tableRows).size() >= minRows
    );
}

// Usage
waitForTableData(By.cssSelector("table tbody tr"), 5);

Wait with Retry on Stale Element

@Step("Click with stale element retry")
protected void clickWithRetry(By locator) {
    wait.until(driver -> {
        try {
            driver.findElement(locator).click();
            return true;
        } catch (StaleElementReferenceException e) {
            return false;  // Retry
        }
    });
}

Wait for File Download

@Step("Wait for file download")
protected void waitForFileDownload(Path downloadDir, String fileNamePattern, Duration timeout) {
    WebDriverWait downloadWait = new WebDriverWait(driver, timeout);
    downloadWait.until(driver -> {
        try {
            return Files.list(downloadDir)
                .anyMatch(file -> file.getFileName().toString().matches(fileNamePattern));
        } catch (IOException e) {
            return false;
        }
    });
}

Source: SKILL.md on GitHub

1 warning13d4 checks · Risk SAFE
  • Gen Agent Trust Hub13d

    The skill provides templates and scripts for Selenium WebDriver testing in Java. It is categorized as low risk due to potential indirect prompt injection vulnerabilities inherent in browser automation and the use of JavaScript execution in the browser context.

  • Socket13d

    No alerts

  • Snyk13d

    Risk: LOW · No issues

  • Runlayer6mo

    1/6 files flagged

Signed by skilld at ef704d5. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 4 days ago.

Activeupdated 2 months ago

README badge

README badge for fugazi/test-automation-skills-agents/webapp-selenium-testing