DEV Community

Cover image for TestFly Part 2: Accessibility-First Locators, BasePage & WaitEngine
Hakan GÜL
Hakan GÜL

Posted on Originally published at hakangul.lovable.app

TestFly Part 2: Accessibility-First Locators, BasePage & WaitEngine

Accessibility-First Semantic Locators

Traditional Selenium tests rely heavily on brittle CSS selectors or complex XPaths that break whenever the DOM hierarchy changes:

// Brittle — breaks on CSS redesigns:
find(By.cssSelector("div.modal > form button.btn-primary")).click();
Enter fullscreen mode Exit fullscreen mode

TestFly introduces Playwright-style Semantic Locators that target the accessibility tree—interacting with the page exactly as a real human perceives it:

getByRole(Role.BUTTON).withName("Submit").click();
getByLabel("Email address").type("user@testfly.io");
getByPlaceholder("Search products…").type("laptop");
getByText("Forgot password?").click();
getByTestId("checkout-cta").click();
Enter fullscreen mode Exit fullscreen mode

Every semantic locator returns an auto-waiting, chainable Locator instance with zero Thread.sleep().


Clean Page Objects with BasePage

BasePage provides wait-backed helper methods (type, click, getText, getAttribute, isDisplayed):

package io.testfly.examples.pages;

import io.testfly.test.BasePage;
import io.testfly.locator.Role;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;

public class LoginPage extends BasePage {

    private static final By USERNAME = By.id("username");
    private static final By PASSWORD = By.id("password");

    public LoginPage(WebDriver driver) {
        super(driver);
    }

    public void login(String user, String pass) {
        type(USERNAME, user);
        type(PASSWORD, pass);
        getByRole(Role.BUTTON).withName("Sign In").click();
    }
}
Enter fullscreen mode Exit fullscreen mode

Advanced Synchronization with WaitEngine

When writing custom wait conditions, WaitEngine centralizes explicit waits using timeouts.explicit from testfly.yml:

import io.testfly.wait.WaitEngine;

// Centralized explicit wait conditions:
WaitEngine.waitForVisible(By.id("dashboard-banner"));
WaitEngine.waitForClickable(By.id("pay-button"));
WaitEngine.waitForInvisible(By.cssSelector(".loading-spinner"));
Enter fullscreen mode Exit fullscreen mode

Top comments (0)