Changelog
All notable changes to Selenium Boot are documented here.
[Unreleased]
-
Failed tests with trace links in GitHub Actions job summary — when running inside GitHub Actions and
tracing.enabled: trueis on, failed tests are automatically summarized in a Markdown table (test name, error message, and path to the HTML trace file) appended to$GITHUB_STEP_SUMMARY. Triage failures and locate trace paths directly from the Actions job summary without downloading artifact bundles; no-op outside Actions or when all tests pass. (#137) -
Bounded failure detail record — every failed test now exports one optional-field
failureDetailobject with the failing locator, top application frame, last successful step, page URL/title, heal events, console errors, retry/history status, and representative same-cause context. The HTML failure panel and opt-in AI prompt reuse this record; raw errors and stack traces remain available. Text/list/URL limits and the exact AI data disclosure are documented. (#142) -
Locator:waitFor(State),allTextContents(), and elementscreenshot()—waitFor(State)(andwaitFor()) waits for an element to reach a target lifecycle state (VISIBLE,HIDDEN,ATTACHED,DETACHED), retrying up totimeouts.explicit.allTextContents()returns the text content of all matched elements in a single pass without waiting if empty, re-resolving if an element goes stale during read.screenshot()returns the element's PNG bytes, andscreenshot(Path)writes them to a file path; both terminal actions re-resolve on every poll to survive stale elements. (#135) -
flakiness.historyDir/-Dseleniumboot.history.dir— metrics history can now live outsidetarget/. Builds that cleantarget/or discard the CI workspace between runs had no history, so the Flakiness Radar and the newly/consistently-failing and intermittent statuses stayed empty. Point it at a directory your CI restores and saves (a cache or artifact store); the system property wins over the config. Default unchanged:<reports dir>/metrics-history. (#141) -
Retry- and history-aware test status — each test now gets a status from this run's retries and the earlier runs in
target/metrics-history/: Passed on retry, Newly failing (passed in every earlier run in the window), Consistently failing (failed in the two or more earlier runs) or Intermittent (mixed earlier results). A "Test status" card sits next to the Flakiness Radar, the status shows in the failure detail, and newly failing tests are listed first in the Failures tab. The metrics JSON gainstestStatus. Radar thresholds andfailOnHighFlakinessare unchanged. (#141) -
Failure grouping — the report's Failures tab now opens with a "N tests, same cause" panel: failed tests are grouped by a signature of category, exception type, normalised message (ids, numbers and quoted values stripped) and top application stack frame. The flat per-class list is unchanged below it. With
ai.failureAnalysison, one Claude call is made per group; the other tests in the group reuse its analysis. The metrics JSON gainsfailureSignature. (#140) -
Locatorform actions:clear(),check(),uncheck(),isChecked(),selectOption(text),selectOptionByValue(value),inputValue()— form controls can now be manipulated and inspected directly onLocatorwithout falling back toBasePagehelpers or rawWebElements.check()anduncheck()are idempotent (no click if already in the target state),isChecked()queries checked state without waiting, and terminal actions (clear,check,uncheck,selectOption,selectOptionByValue,inputValue) auto-wait, re-resolving from scratch on every poll to survive stale or late-appearing elements. (#133)
[Unreleased]
- Failure classification — every failed test is tagged with a category (
LOCATOR_NOT_FOUND,ELEMENT_NOT_INTERACTABLE,STALE_ELEMENT,TIMEOUT,ASSERTION_MISMATCH,NAVIGATION_ERROR,BROWSER_CRASH, orUNKNOWN) and the evidence for it, from the exception class chain and message alone. No AI, no API key, no network. Shown as a badge in the HTML report's failure panel, asfailureCategory/failureEvidencein the metrics JSON, and as thetypeof<failure>in the JUnit XML. The raw error and stack trace are unchanged. (#139)
[3.8.0] — 2026-10-11
-
Locator.first()andLocator.last()— narrow matches to the first or last matching element (e.g.getByRole(Role.LISTITEM).first()). Both resolve at action time, re-evaluating candidate elements on every poll and retrying stale/not-yet-present elements up totimeouts.explicit. (#132) -
HTML report: the "Avg Time (ms)" stat tile is now "Suite Time" — the wall-clock suite duration in
hh:mm:ss, matching the sidebar. -
HTML report: suite duration in
hh:mm:ss, wall-clock. The report previously showed the sum of every test's time in milliseconds, which overstates a parallel run. It now shows how long the suite actually ran (01:42:07; hours aren't capped). The metrics JSON gainssuiteDurationMs;totalTimeMs(summed test time) is unchanged. -
HTML report: results first. The dashboard now opens with a one-line run summary and the stat cards; the full run configuration moved into a collapsed "Run configuration" block at the bottom, with empty rows (Grid URL, unset CI fields) dropped. A "View failures" shortcut appears when any test failed.
[3.7.0] — 2026-10-04
Locator.dragTo(Locator)— drags one element onto another, including HTML5 drag-and-drop pages that ignore the native gesture. See Drag and drop. (#101)debug.slowMoMs/debug.highlight— dev-only live-triage aids: pause after eachLocatoraction and outline the element about to be acted on. Off by default, no cost when off; not for CI. See Debug. (#52)withNewWindow(opener, body)/withNewTab(...)onBasePage— run the click that opens a new window, switch to it, run your checks, close it and return to the original window, even if the checks throw. No window opening withintimeouts.explicitthrowsTimeoutException. See Handle new windows and tabs. (#49)browser.version— optional exact browser version for local Chrome/Firefox runs, resolved by Selenium Manager. Omit it to use the installed browser. (#51)
[3.6.0] — 2026-09-27
WaitEngine.waitForNetworkIdle()/waitForResponse(urlPattern)— waits until no network request has been in flight for a quiet period (default 500ms, or a customDuration), or until a response whose URL matches a glob pattern (same syntax asNetworkMock.stub) is observed, returning its HTTP status code. Both are bounded by the configured explicit timeout. Works on Chrome/Edge (via CDP) and any BiDi-capable browser such as Firefox; throwsUnsupportedOperationExceptionon others. Firefox sessions now request a BiDi connection by default (webSocketUrlcapability) so this works with no extra configuration — an explicit value in the user's ownbrowser.capabilitiesstill wins.open()namesexecution.baseUrlwhen the site can't be reached — a DNS or connection failure now readsCould not reach <url> (ERR_NAME_NOT_RESOLVED) — check execution.baseUrl in selenium-boot.yml …(the driver's error stays as the cause) instead of a barenet::ERR_NAME_NOT_RESOLVED. Applies toBaseTest,BaseJUnit5Test,BaseCucumberStepsandBaseConditions. Also fixesBaseJUnit5Test.open()with noexecution.baseUrlfailing with a bare driver error instead of naming the missing key. (#84)- Gradle projects now get their reports under
build/(#81) — the base directory is decided frombuild.gradle/build.gradle.kts(apom.xmlwins if both exist) instead of "doestarget/exist", which other components had already created. Flakiness report, healed locators, traces, recordings, Allure results, screenshots and JUnit XML all follow it;-Dseleniumboot.reports.dirstill overrides. - Docs: the Gradle
systemProperties System.propertiessnippet is replaced (#82) — copying every JVM property broke test runs when the test JVM differs from Gradle's. It now forwards onlybrowserandenv.
[3.5.0] — 2026-09-24
- Zero-config first run:
selenium-boot.ymlis now optional — with no defaultselenium-boot.ymlin the working directory or on the classpath, the framework runs on built-in defaults (browser.name: chrome,execution.mode: local,timeouts.explicit: 10,timeouts.pageLoad: 30) and prints one[Selenium Boot] No selenium-boot.yml found — running with built-in defaults ...notice line. Fields a file omits (and an empty file) fall back to the same defaults;browser.nameis only defaulted whenbrowser.matrixis not set, andSeleniumBootDefaultsoverrides still take precedence over the built-ins. Nothing that was an error before stops being one: a requested profile (-Dselenium.boot.profile) or explicit path (-Dselenium.boot.config) whose file is missing still throws, so a typo never silently runs on defaults, and present-but-invalid values (an unknownexecution.mode, a negative timeout) still fail validation. AddsConfigurationLoader.load(File, ClassLoader)(working directory and classpath supplied, for tests). (#66) - Terminal
Locatoractions wait for the element and re-resolve it on every poll —click(),type(),append(),getText(),getAttribute(),hover(),scrollIntoView(),jsClick()andelement()used to look the element up once and act on that cached reference, so a page that re-rendered it in between surfaced as aStaleElementReferenceException, and a locator that matched nothing yet threw immediately. They now resolve the locator from scratch on each poll, retrying on a stale or not-yet-present element untiltimeouts.explicitelapses. Behavior change: a locator that matches nothing is now retried for up totimeouts.explicitinstead of failing at once. If it never matches, the call still ends in aLocatorException(cause:TimeoutException), so existing catches keep working; an element that exists but never becomes visible/clickable still times out with aTimeoutException, as before.isVisible(),isHidden(),isEnabled()andcount()still never wait, androws()inherits the wait for its table throughelement(). (#67, #68) - JUnit Jupiter API bumped 5.10.2 → 6.1.3 (
junit-jupiter-api, optional dependency of the JUnit 5 bridge).junit-platform-launcheris now bumped to match (6.1.3, was 1.10.2), closing the pairing gap left by #64. Verified both directions against the consumer integration suite (11/11 real-browser JUnit 5 tests): a consumer still on JUnit 5.10.2 + launcher 1.10.2 keeps working unchanged, and a consumer on JUnit 6 (jupiter 6.1.3 + launcher 6.1.3) now works too. (#64) - Clearer error when
execution.baseUrlis unset —open()andopen(String)now throwexecution.baseUrl is not set — add it to selenium-boot.yml, or navigate with getDriver().get(url)instead ofbaseURL is null or empty. Message only; still anIllegalStateException. The getting-started guide now says Step 3 needs the Step 2 file, since zero-config has no defaultbaseUrl. (#77)
[3.4.0] — 2026-09-19
Added
Locator.rows()— resolves a locator to a<table>and returns its data rows as header-keyed maps (List<Map<String, String>>), one map per row, keyed by column header. Headers come from the first<thead>row with<th>cells, falling back to the first<tr>anywhere with<th>cells, then the first<tr>'s<td>cells; whichever row supplies headers is never returned as data. Short rows are padded with"", extra cells are dropped, and<th>-only rows (group headings) are skipped. Contributed by @timothytkim. (#54)
Fixed
- Bootstrap failures now expose their root cause — when framework initialization throws, the full cause chain is now logged to
System.err(walked down to the root) before the suite aborts, so the actual failure reason shows up in normal Maven/TestNG/Surefire output instead of being hidden behind the generic "failed to initialize" wrapper message. (Fixes #45)
Changed
- Selenium Java 4.40.0 → 4.49.0 (9 releases) — behavior-preserving upgrade.
NetworkMockandDeviceEmulatorare repointed from the removed CDPdevtools.v144module todevtools.v153, and two new trailingOptional.empty()arguments were added toEmulation.setDeviceMetricsOverride()calls to match v153's changed signature, preserving existing defaults. Verified with the full 508-test suite. - Docs — quickstart examples in the README and getting-started guide now lead with the locator API (
$(...)) instead ofgetDriver(), and the getting-started example runs as written.
[3.3.0] — 2026-08-15
Fixed
execution.parallelvalidation now matches TestNG's own parallel modes —testsandinstancesare legitimate TestNG modes that flow straight through toXmlSuite.setParallel()and behave exactly likemethods/classesdownstream, but Selenium Boot's bootstrap validator rejected both, reporting a misleading "Parallel execution configuration missing" for a value that was present but not on a hand-written allowlist. Validation now delegates to TestNG'sXmlSuite.ParallelModeenum directly, sonone,methods,classes,tests, andinstancesare all accepted, and an unrecognised value's error message names both the rejected value and the full valid set. (Fixes #35)
[3.2.0] — 2026-07-18
Added
- Three new
WaitEngineconditions, consistent with the existingwaitFor*naming:waitForAttribute(By, attribute, value)— waits for an exact attribute match (seewaitForAttributeContainsfor a substring match).waitForUrlMatches(String regex)— waits for the current URL to match a regular expression (seewaitForUrlContainsfor a substring match).waitForTextMatches(By, String regex)— waits for an element's visible text to match a regular expression.- Purely additive to the
@SeleniumBootApisurface — no breaking changes.
[3.1.1] — 2026-06-26
Fixed
- Report overwrite with multiple test engines — the metrics JSON, HTML report, and metrics history now honor the
seleniumboot.reports.dirsystem property (defaulttarget). When a TestNG suite (Surefire) and JUnit 5 tests (Failsafe) run in the same build, point each engine's run at its own directory (e.g.-Dseleniumboot.reports.dir=target/junit5) so they no longer overwrite each other's HTML report. NewReportPathshelper centralizes path resolution.
[3.1.0] — 2026-06-25
Added
- Accessibility-first locators — Playwright-style semantic locators available on
BaseTestandBasePage:getByRole,getByText,getByLabel,getByPlaceholder,getByTestId,getByAltText,getByTitle. They target the accessibility tree the user perceives rather than brittle CSS/DOM structure, so tests survive redesigns. getByRole(Role)— 38 WAI-ARIA roles, each matching implicit HTML elements (<button>,<a href>,<h1>…) and explicitrole="…"attributes. Refine with.withName("Submit")(accessible-name match, following ARIA precedence:aria-label→aria-labelledby→ associated<label>→ text →value/alt/title) and.withLevel(1)(heading level).- Case-insensitive substring matching by default, with
.exact()opt-in. All locators flow through the existing auto-waitLocatorchain — noThread.sleep, no explicit waits. toBy()escape hatch — every semantic locator can return its synthesized SeleniumByfor interop with raw Selenium orSmartLocator.- Configurable test-id attribute —
locators.testIdAttributeinselenium-boot.yml(defaultdata-testid).
[3.0.0] — 2026-06-21
Added
- TestRail Integration —
@TestRailCase("C1234")on any test method (or class) pushes results to TestRail automatically; supports multiple IDs (@TestRailCase({"C1234", "C5678"})); creates a named run on suite start (autoCreateRun: true); maps PASSED→1, FAILED→5, SKIPPED→Retest(4); failure exception message is sent as the result comment - Xray Integration —
@XrayTest("PROJ-123")pushes results to Xray Cloud or Xray Server/DC; Cloud uses OAuth2 client credentials; Server uses HTTP Basic auth against Jira; results are batch-imported at suite end - Zero extra dependencies — both clients use
java.net.http.HttpClient(built into Java 17) - TestNG + JUnit 5 — same annotations work in both test frameworks; framework automatically detects and routes to the correct listener
Config
testmanagement:
testrail:
enabled: true
url: https://yourcompany.testrail.io
username: user@example.com
apiKey: YOUR_API_KEY
projectId: 1
suiteId: 2 # optional — omit for single-suite projects
runName: "Selenium Boot – CI run"
autoCreateRun: true # set false and provide runId to use an existing run
xray:
enabled: true
mode: cloud # "cloud" (Jira Cloud) or "server" (Server / Data Center)
# Cloud fields:
clientId: YOUR_CLIENT_ID
clientSecret: YOUR_CLIENT_SECRET
# Server/DC fields:
# jiraUrl: https://jira.example.com
# username: admin
# password: secret
projectKey: PROJ
testPlanKey: PROJ-1 # optional — links the execution to a Test Plan
[2.6.0] — 2026-06-20
Added
- Gradle Build Support —
testImplementation 'io.github.seleniumboot:selenium-boot:2.6.0'+test { useTestNG() }is the complete Gradle setup; full docs cover Groovy DSL, Kotlin DSL, JUnit 5 bridge, parallel execution, optional dependencies, and./gradlew testequivalents for allmvncommands - JUnit XML auto-detection —
JUnitXmlReporternow detects the active build tool at runtime: writes tobuild/test-results/test/(Gradle) when only abuild/directory exists, ortarget/surefire-reports/(Maven) otherwise; override with-Dseleniumboot.reports.dir=system property - Cross-build-tool version reporting —
FrameworkVersion.get()now readsImplementation-Versionfrom the JAR'sMANIFEST.MFas the primary source (works with both Maven and Gradle); falls back toMETA-INF/maven/.../pom.properties(Maven-only) and then"0.0.0";maven-jar-pluginconfigured withaddDefaultImplementationEntries: trueto populate the manifest on every Maven build
[2.5.0] — 2026-06-20
Added
- Accessibility Assertions (axe-core) —
accessibility()inBaseTestandBaseJUnit5Testruns a full axe-core WCAG scan on the active page; axe-core 4.10.2 bundled in the JAR — no CDN, no extra Maven dependency required - Fluent builder:
.withTags("wcag2a", "wcag21aa")restricts rules to WCAG 2.1 AA;.withLevel(Impact.SERIOUS)filters violations by minimum severity;.excluding("#cookie-banner")skips known third-party elements;.withContext("#main-form")scopes the scan to a subtree .run()— asserts zero violations and throws a detailedAssertionErroron failure, showing rule ID, severity (CRITICAL/SERIOUS/MODERATE/MINOR), fix guidance, element CSS selector path, and link to the axe-core docs for each failing node.collect()— returns rawAccessibilityResultfor custom inspection without asserting;result.violations(),result.violationsAtLevel(Impact.SERIOUS),result.passCount()Impactenum with ordering:CRITICAL > SERIOUS > MODERATE > MINOR;Impact.fromString(str)parses axe-core impact stringsAccessibilityResult,AccessibilityViolation,AccessibilityViolation.NodeDetailall available viaaccessibility().collect()for custom reporting or soft assertions
[2.4.0] — 2026-05-19
Added
- Performance Assertions (Core Web Vitals) —
assertPerformance()collects LCP, FCP, TTFB, CLS, DOM load, and page load from the active browser page using browser-native APIs (window.performance.getEntriesByType()); no extra dependency or proxy required - Fluent assertion chain:
.lcp().isBelow(2500).fcp().isBelow(1800).ttfb().isBelow(600).cls().isBelow(0.1)with colour-coded error messages showing actual vs threshold values collectPerformance()— rawPerformanceMetricsaccess for custom assertions or logging- LCP/CLS available on Chrome/Edge only; assertions on unavailable metrics are silently skipped (not failed), enabling cross-browser test suites
performance.captureOnEveryTest: true— auto-captures metrics after every passing test; ⚡ Performance strip with green/yellow/red chips shown in the HTML report test detail panelPerformanceAssert,PerformanceMetrics,PerformanceCollectorall available viaclock()pattern inBaseTestandBaseJUnit5Test
Config
performance:
captureOnEveryTest: false # show metrics in HTML report for every test
lcpWarnMs: 2500
fcpWarnMs: 1800
ttfbWarnMs: 800
clsWarn: 0.1
[2.3.0] — 2026-05-17
Added
- Test Quarantine —
selenium-quarantine.ymlin the project root lists tests to skip permanently; committed to version control so it survives fresh CI clones; supports TestNG, JUnit 5, and Cucumber; two entry formats: plain string (com.example.LoginTest#method) and structured with optional reason (test: …\nreason: "JIRA-123") - Class-level quarantine — a class-only entry (
com.example.PaymentTest) skips every method in that class - Cucumber quarantine — two methods: (1) add
@quarantinetag to a scenario in the.featurefile; (2) list entries inselenium-quarantine.ymlusing any of three formats: by Cucumber tag ("@smoke"— bulk across all features carrying that tag), by feature file (login.feature— all scenarios in the file), or by feature+name ("login.feature#Login with expired session"— specific scenario without editing the feature file) quarantine.enabledflag — set tofalseto temporarily run the full suite without removing entries from the file- File resolution — system property
-Dselenium.boot.quarantine=, working directory, classpath (in that order); missing file = silent no-op
Config
quarantine:
enabled: true # false = disable without editing the file
cucumberTag: quarantine # Cucumber tag name (without @)
quarantine:
- com.example.tests.LoginTest#loginWithExpiredSession
- com.example.tests.PaymentTest # entire class
- test: com.example.tests.SearchTest#searchSpecial
reason: "JIRA-1234 — Unicode handling broken"
[2.2.0] — 2026-05-12
Added
- External
@TestDatasources —@TestDatanow acceptscsv:,excel:, anddb:prefixes in addition to the existing JSON/YAML files;sheetattribute selects an Excel worksheet;rowattribute picks the zero-based data row (header excluded); type coercion applied automatically (integers, doubles, booleans); Apache POI required for Excel (addpoi-ooxml:5.2.5to your project, optional dep) - CSV source —
@TestData("csv:testdata/logins.csv")— RFC 4180 quoting support, built-in parser, no extra dependency - Excel source —
@TestData(value = "excel:testdata/users.xlsx", sheet = "Login")— reads XLSX via Apache POI; cell type mapping (numeric →long/double, date-formatted → ISO string, boolean →Boolean) - DB source —
@TestData("db:SELECT username, password FROM test_users WHERE active=1")— executes against thedatabaseconfig block; first result row loaded; participates in per-test connection lifecycle TestClock—clock().set("2030-01-01T00:00:00Z")injects a JSDateoverride into the browser;clock().advance(Duration.ofDays(30))fast-forwards relative to the current mock;clock().reset()restores real time; all three available viaclock()inBaseTestandBaseJUnit5Test; auto-reset called automatically after every test (pass, fail, skip)clockconfig block:clock.injectHeader/clock.headerNamefor optional server-side date header propagation
Config
clock:
injectHeader: false # send X-Mock-Date header to server
headerName: X-Mock-Date
[2.1.0] — 2026-05-04
Added
- BrowserStack integration —
execution.mode: browserstack;BrowserStackProviderbuilds W3Cbstack:optionscapabilities from YAML config; supports desktop (os,osVersion,browser,browserVersion) and mobile (device,realMobile); rawbstack:optionsoverrides viacapabilitiesmap; zero test-code change — all framework features work identically - Sauce Labs integration —
execution.mode: saucelabs;SauceLabsProviderbuilds W3Csauce:optionscapabilities; three regions supported:us-west-1,eu-central,apac-southeast; rawsauce:optionsoverrides viacapabilitiesmap - Cloud session URL in HTML report — after driver creation on BrowserStack or Sauce Labs, the session dashboard URL is captured from the remote session ID and stored; HTML report shows a "☁ View Session" link in the test detail panel linking directly to the BrowserStack/Sauce video and logs
DriverManager.getCloudSessionUrl()— public accessor for the current thread's cloud session URL;nullwhen running locally or against a self-hosted grid
Config
execution:
mode: browserstack # or: saucelabs | remote | local
browserstack:
username: ${BS_USER}
accessKey: ${BS_KEY}
os: Windows
osVersion: "11"
browser: chrome
browserVersion: latest
saucelabs:
username: ${SAUCE_USER}
accessKey: ${SAUCE_KEY}
region: us-west-1 # us-west-1 | eu-central | apac-southeast
platformName: "Windows 11"
browser: chrome
browserVersion: latest
[2.0.0] — 2026-05-04
Added
- Email Verification —
mailbox().waitForEmail(criteria)polls the inbox until a matching email arrives or the configured timeout expires; fluent criteria:to(address),.subject(text),.containing(text),.timeout(seconds);Emailvalue object withassertSubject(),assertBodyContains(),extractLink(linkText)(finds href of anchor by visible text);mailbox().clear()purges the inbox;email.autoClear: trueclears automatically before each test;to(address)shorthand available directly inBaseTest/BaseJUnit5Test(no static import needed) - Mailhog provider — polls
GET /api/v2/messages, parses multipart MIME;DELETE /api/v1/messagesto clear; ideal for local dev and CI Docker - Mailtrap provider — Mailtrap v1 REST API;
Api-Tokenheader auth;PATCH /cleanto clear - Outlook / Office 365 provider — Microsoft Graph API with app-only OAuth2 client credentials (no user sign-in); token auto-refreshed and cached; reads
GET /users/{mailbox}/messages; deletes per-message; setup: register Azure AD app, grantMail.Read+Mail.ReadWriteapplication permissions, admin consent - IMAP provider — connects to any IMAP server (Gmail app passwords, Yahoo, corporate); SSL/STARTTLS configurable; requires optional
com.sun.mail:jakarta.mail:2.0.1consumer dependency; helpful error thrown if jar missing
Changed
BaseTest/BaseJUnit5Test— newmailbox()andto(address)protected methodsSeleniumBootConfig— newemailblock withprovider,timeoutSeconds,pollIntervalMs,autoClear,mailhog,mailtrap,outlook,imapsub-sections
[1.13.0] — 2026-05-03
Added
@NoBrowser— class- or method-level annotation that tells the framework to skip all browser operations for that test: noWebDrivercreated, no recording started, no screenshot captured, no trace saved, no driver quit; all other services (HTML report, step timeline,ExecutionMetrics, retry, CI gates, hooks,@TestData,ScenarioContext) continue to work; available inBaseTest(TestNG) andBaseJUnit5Test(JUnit 5); designed for database assertions, file checks, or any non-UI logic in tests that extendBaseTestrather thanBaseApiTest
[1.12.0] — 2026-05-03
Added
- Multi-Session Testing —
withSession("alice", () -> { ... })switches the active driver to a named session for the duration of the lambda and restores the previous driver on exit;session("name")returns the namedWebDriverdirectly; all named sessions are automatically closed at test end; nestedwithSession()calls supported via a stack-based override inDriverManager; available inBaseTest(TestNG),BaseJUnit5Test(JUnit 5), and throughMultiSessionManagerdirectly - Database Assertions — JDBC-backed
DbClientwithassertRowExists(table, conditions),assertNoRow(table, conditions),assertRowCount(table, expected),assertRowCount(table, where, expected),query(sql, params).assertValue(column, expected),query(sql, params).value(column), andscalar(sql, params); plainjava.sql.DriverManager— no ORM or extra dependency; named datasources viadb("reporting"); connections cached per thread and closed automatically at test end;DbAssertException extends AssertionErrorso failures appear as test failures sessions.maxPerTestanddatabaseconfig blocks added toSeleniumBootConfig
[1.11.0] — 2026-05-03
Added
@Retryablefor JUnit 5 —SeleniumBootExtensionimplementsInvocationInterceptor;interceptTestMethodcatches failures and retries the test method with full driver recreation between attempts;@Retryablecan be placed on the method or the class;maxAttemptsattribute overrides the globalretry.maxAttemptsconfig;WebDriverparameter arguments are re-resolved to the new driver on each retry attempt@Retryablefor Cucumber —RetryAnnotationTransformerapplies TestNG retry toAbstractTestNGCucumberTests.runScenario; the entire scenario reruns from step 1 with a fresh driver per retry;CucumberHooks.beforeScenariodetects retries (testId already in metrics) and records retry count so the HTML report shows the retry badge
Changed
@Retryable— addedmaxAttemptsattribute (default-1= use config); addedTYPEtarget so it can be placed on a class to retry all its test methods; fully backward-compatible — existing usages without the attribute continue to work
[1.10.0] — 2026-05-02
Added
- JUnit 5 Support —
SeleniumBootExtension(@ExtendWith) provides full lifecycle: driver creation inbeforeEach, screenshot + error recording + AI analysis + trace + recording inafterEach(viacontext.getExecutionException()), per-suite driver cleanup inafterAll;WebDriverinjectable as a test method parameter viaParameterResolver;BaseJUnit5Testbase class withgetDriver(),getWait(),open(),$(),assertThat(),step();@EnableSeleniumBootcomposed annotation;SeleniumBootLauncherListener(TestExecutionListener) generates HTML report, JSON metrics, and flakiness analysis when the JUnit Platform test plan finishes — registered automatically viaMETA-INF/services;junit-platform-launcherdeclared as optional dependency; parallel execution supported viajunit-platform.properties
[1.9.0] — 2026-05-02
Added
- BDD / Cucumber Integration —
BaseCucumberTest(runner base),BaseCucumberSteps(step definition base withgetDriver(),open(),$(),assertThat()),CucumberHooks(automatic driver lifecycle, metrics, screenshots, and report per scenario),CucumberStepLogger(Cucumber plugin that pipes Gherkin step names into the HTML report step timeline),CucumberContext(ThreadLocalScenarioholder); fully parallel-safe via ThreadLocal isolation; Scenario Outlines produce individual HTML report entries per example row;cucumber.propertiessupport for IDE single-scenario execution;cucumber-javaandcucumber-testngdeclared as optional dependencies — only pulled in by consumers who opt in
Changed
TestExecutionListener— skips allonTest*callbacks for Cucumber runner tests (AbstractTestNGCucumberTests#runScenario) to prevent duplicate HTML report entries when running BDD and TestNG tests in the same suiteExecutionHook.onTestEndjavadoc corrected: fires before driver quit, not after
[1.8.0] — 2026-04-16
Added
- Self-Healing Locators —
locators.selfHealing: true; whenwaitForVisible/waitForClickabletimes out the framework automatically tries fallback strategies derived from the originalBydescriptor: extractidfrom CSS#foo/ XPath@id,namefrom CSS[name]/ XPath@name, text from XPathtext(), class from CSS.className,data-testidandplaceholderattributes; healed tests get a⚠ healedbadge in the HTML report;target/healed-locators.jsonlists every healed locator for developer review - AI-Assisted Failure Analysis —
ai.failureAnalysis: true+ai.apiKey: ${CLAUDE_API_KEY}; on test failure callsclaude-haiku-4-5-20251001(configurable viaai.model) with error, stack trace, step log, URL, and page title; the plain-English root-cause analysis + suggested fix is embedded in the HTML report failure detail panel; call bounded byai.timeoutSeconds(default 20s); fully non-blocking — never affects suite outcome - Flakiness Prediction — reads last
NJSON run files fromtarget/metrics-history/; classifies each test asSTABLE(<10% failure rate),WATCH(10–threshold%), orHIGH(≥threshold); results shown in a new Flakiness Radar card on the HTML report Dashboard; exported totarget/flakiness-report.json; optionalflakiness.failOnHighFlakiness: trueCI gate
[1.7.0] — 2026-04-16
Added
- Trace Viewer —
tracing.enabled: trueinselenium-boot.ymlgenerates a self-contained HTML trace file per failed test attarget/traces/{ClassName}/{testMethod}-trace.html; the file embeds a clickable step timeline (each step shows its screenshot on click), a final-state screenshot taken at the moment of failure, the error message, and full stack trace; zero CDN dependencies — all CSS/JS are inlined;captureOnPass: trueoption to generate traces for passing tests too; HTML report shows a "View Trace" link in the failure detail panel
[1.6.0] — 2026-04-16
Added
- Visual regression testing —
VisualAssert.assertScreenshot(name)pixel-by-pixel screenshot comparison; baseline auto-created on first run; diff image written totarget/visual-diffs/;VisualTolerance.of(n)for configurable pixel-difference tolerance;-DupdateBaselines=truesystem property forces baseline regeneration; configurable dirs viavisual.baselineDir/visual.diffDirinselenium-boot.yml - Mobile device emulation —
DeviceEmulator.emulate("iPhone 14")/emulateDevice()+resetDevice()inBasePage/BaseTest; full CDP emulation on Chrome/Edge (viewport, device scale factor, user-agent); window-resize + JS UA override fallback on Firefox; 6 built-in profiles: iPhone 14, iPhone SE, Pixel 7, Galaxy S23, iPad, iPad Pro 12; register custom profiles viaDeviceProfiles.register() - Clipboard helpers —
ClipboardHelper.write()/read()/clear()backed by a reliable JS global store (window.__seleniumBootClipboard); async native clipboard attempted best-effort - GeoLocation mock —
GeoLocation.set(lat, lon)/clear(); CDPEmulation.setGeolocationOverrideon Chrome/Edge;navigator.geolocationJS override fallback on Firefox - Network interception —
NetworkMock.stub(urlPattern)with fluentStubBuilder; glob patterns (**/api/**); configurable response body, content-type, status code, and delay; auto-cleared after each test - Browser storage helpers —
StorageHelper.localStorage(),sessionStorage(),cookies()— read/write/clear browser storage from tests without JS boilerplate - Fluent Locator API —
$(css)/$(By)returning a chainableLocator; methods:filter(),withText(),within(),nth(); auto-wait terminal actions:click(),type(),getText(),isVisible(),count(),element(),elements() - Web-First Assertions —
assertThat(By)/assertThat(Locator)returningLocatorAssert; auto-retrying assertions:isVisible(),isHidden(),isEnabled(),hasText(),containsText(),hasValue(),hasAttribute(),hasClass(),count()
[1.3.0] — 2026-04-07
Added
- Shadow DOM helpers —
ShadowDomutility + 7BasePageprotected methods (shadowFind,shadowFindAll,shadowClick,shadowType,shadowGetText,shadowPierce,shadowExists) - Alert handling fix — set
unhandledPromptBehavior: ignoreon all driver providers so native alerts stay open;BasePage.getAndAcceptAlert()convenience method - Component-aware waits —
WaitEngine.waitForAngular()(Angular 2+ testability API + AngularJS 1.x fallback) andWaitEngine.waitForReactHydration()(React 18/17/16 fiber detection, Next.js aware) - Enhanced HTML report — pass rate gauge card, donut chart (Chart.js), retry badges, expandable inline error message + stack trace per failed row, filter buttons (
All / Passed / Failed / Skipped / Flaky), text search, dark mode toggle, slowest-5 tests section - JUnit XML error details —
<failure message>and element text now contain the actual assertion message and full stack trace instead of a generic placeholder - Allure adapter — opt-in Allure 2 result file generation; set
reporting.allureEnabled: trueinselenium-boot.yml; producestarget/allure-results/{uuid}-result.jsonper test - Slack / Teams notifications — configure
notifications.slack.webhookUrland/ornotifications.teams.webhookUrl; post-suite summary sent automatically;notifyOnFailureOnlyoption @DependsOnApi— method- or class-level annotation; skips test before browser opens if the specified HTTP endpoint is unreachable; repeatable (multiple URLs, all must be up); result cached per suite to avoid redundant probes
[1.1.1] — 2026-03-28
Added
- Schema validation —
ApiResponse.assertSchema("schemas/user.json")validates response body against a JSON Schema (Draft-07); requirescom.networknt:json-schema-validator:1.4.3as consumer dependency @UseAuthannotation — apply a named auth strategy fromapi.authconfig block to any test method/classApiAuth.oauth2()— OAuth2 client credentials flow; token fetched on first use and cached until expiryApiClient.setGlobalAuth()/clearGlobalAuth()— suite-level auth set once, applied to every request automatically; cleared by framework after each test
[1.1.0] — 2026-03-25
Added
BaseApiTest— pure API test base class; no browser started; full framework lifecycle (reporting,@TestData, retry, CI gates)ApiClient— fluent HTTP client backed by Java's built-inHttpClient;GET,POST,PUT,PATCH,DELETE; per-request auth; auto step-loggingApiResponse— JSONPath extraction ($.user.id),asObject(Class), fluent assertions (assertStatus,assertJson,assertBodyContains)ApiAuth—bearerToken(token),basicAuth(user, pass)ScenarioContext— thread-local in-test store;ctx().set/get; auto-cleared after each testSuiteContext— global thread-safe store for cross-test state sharing;suiteCtx().set/getapiClient(),ctx(),suiteCtx()added toBaseTestfor hybrid UI+API tests
[0.10.0] — 2026-03-22
Added
@TestData— declarative test data injection via annotation; loads.json,.yml,.yamlfromsrc/test/resources/testdata/; env-specific override when-Denv=<profile>is set;getTestData()returnsMap<String, Object>inBaseTest- Browser matrix —
browser.matrix: [chrome, firefox, edge]in YAML runs all tests on all browsers in one invocation;Browsercolumn added to HTML report; per-browserTEST-selenium-boot-<browser>.xmlfor Jenkins matrix view SessionCache— global (cross-thread) authenticated session store;store("name")captures cookies + localStorage;restore("name")applies them into the current driver and refreshes;invalidate()/clear()for teardown- SoftAssert —
softAssert().that(condition, "message")collects assertion failures without throwing; framework flushes atonTestSuccess; each failure logged asFAILstep entry; single screenshot at flush time; test markedFAILEDwith combined message
[0.9.6] — 2026-03-21
Added
- DownloadManager browser auto-configuration — Chrome sets
download.default_directoryvia experimental prefs; Firefox setsFirefoxProfiledownload preferences; both skipped whenexecution.mode: remote - File upload helper —
BasePage.upload(By, String)resolves absolute → classpath → project-root; CI-safe absolute path sent to Selenium
[0.9.5] — 2026-03-21
Added
- ConsoleErrorCollector auto-integration — JS shim auto-injected on every
open()call whenbrowser.captureConsoleErrors: true; errors auto-collected at test end asWARNstep entries in the HTML report failOnConsoleErrorsenforcement — passing test with JS errors is marked FAILED whenbrowser.failOnConsoleErrors: trueStepStatus.WARN— new step status for JS error entries
[0.9.4] — 2026-03-20
Added
- iFrame helpers expanded —
withinFrameName(String nameOrId, Runnable action)added toBasePage - Nested frame support —
withinFrame,withinFrameIndex,withinFrameNamenow use a thread-local depth counter; inner calls restore toparentFrame(), the outermost call restores todefaultContent()
[0.9.3] — 2026-03-20
Fixed
- Alert methods use
this.driver—acceptAlert,dismissAlert,getAlertText,typeInAlertinBasePagenow build theirWebDriverWaitfromthis.driver(the driver passed into the page object constructor) instead ofWaitEngine/DriverManager.getDriver(), eliminating the driver-mismatch that causedNoAlertPresentExceptionin precondition context @PreConditionerror message —PreConditionRunnernow unwrapsInvocationTargetExceptionto expose the real cause, so the failure message is meaningful instead of showing "null"
[0.9.2] — 2026-03-20
Fixed
@PreConditionfailure no longer triggers retry —TestExecutionListenernow catches precondition exceptions and re-throws asSkipException; the test is marked SKIPPED (not FAILED), the retry analyzer is not called, and no second browser is openedmaxAttempts: 0now respected in YAML —SeleniumBootConfig.Retry.maxAttemptschanged fromint(default1) to nullableInteger; the defaults loader now only applies a programmatic override when the value was not set at all (wasnull), not when explicitly set to0
[0.9.1] — 2026-03-19
Fixed
- Alert helpers now wait —
acceptAlert,dismissAlert,getAlertText,typeInAlertinBasePageuseWaitEngine.waitForAlert()instead of rawdriver.switchTo().alert(), preventingNoAlertPresentExceptionon slow pages
Added
WaitEngine.waitForAlert()— explicit wait for browser alert presenceBasePage.smartFind(By primary, By... fallbacks)— convenience wrapper aroundSmartLocator.find()for use inside page objects without passing the driver manually
[0.9.0] — 2026-03-18
Added
BasePageexpanded — dropdowns (selectByText,selectByValue,selectByIndex,getSelectedOption), alerts (acceptAlert,dismissAlert,getAlertText,typeInAlert), mouse actions (hover,doubleClick,rightClick), scroll (scrollTo,scrollToTop,scrollToBottom), JS fallbacks (jsClick,jsType)
[0.8.0] — 2026-03-17
Added
BasePage— page object base class withclick,type,getText,getAttribute,isDisplayed- iFrame helpers —
withinFrame(By, Runnable)andwithinFrameIndex(int, Runnable)inBasePage - File upload helper —
upload(By, String)inBasePage, resolves classpath and relative paths SmartLocator— tries multiple locator strategies in order, returns first visible elementDownloadManager—waitForFile,waitForAnyFile,clearDownloadswith partial-download detectionConsoleErrorCollector— JS console error capture via WebDriver logs (Chrome) or injected shim (Firefox)@PreCondition— session-aware pre-conditions with automatic cookie + localStorage caching@ConditionProvider— marks provider methods inBaseConditionssubclassesBaseConditions— base class for condition providers, givesgetDriver(),open(),click(),type()@SeleniumBootApi— annotation marking stable public API withsinceversionFrameworkVersion— runtime version access andrequireAtLeast()compatibility checkIncompatiblePluginException— thrown when plugin version requirements are not metminFrameworkVersion()— new method onSeleniumBootPluginfor version compatibility declarations- Config additions —
browser.downloadDir,browser.captureConsoleErrors,browser.failOnConsoleErrors
[0.7.0] — 2026-03-16
Added
- Browser lifecycle control —
browser.lifecycle: per-test | per-suitesetting - Per-suite driver management — browser stays open across tests when
per-suiteis configured - Step logging —
StepLogger.step()API for named test steps with optional screenshots and status badges - Step timeline — Step-by-step execution timeline in the HTML report detail panel
- Tabbed HTML report — Left sidebar navigation with Dashboard, Test Cases, and Failures tabs
- Failures tab — Pre-expanded failure details for faster debugging
- Inline step screenshots — Base64-embedded step screenshots with lightbox on click
Changed
- HTML report overhauled with tab-based layout and collapsible test rows
- Screenshot lightbox now opens full-size correctly
[0.6.0] — 2025-12-01
Added
- Advanced HTML reporting — Dashboard with metrics cards, test case table, retry summary
- Donut chart — Pass/fail/skip distribution chart on Dashboard tab
- Slowest tests — Top-5 slowest tests ranked by duration
- Pass rate gauge — Colour-coded pass rate percentage card
- Retry badge —
↻ Nxbadge on retried tests in the table
Changed
- Screenshots embedded as Base64 — report is now a single self-contained file
[0.5.0] — 2025-10-15
Added
- Retry support —
retry.enabled+retry.maxAttemptsinselenium-boot.yml @Retryableannotation — per-method retry override- RetryAnnotationTransformer — auto-registered via Java SPI, zero config
- Retry metrics — retry counts tracked in
ExecutionMetricsand exported to JSON
[0.4.0] — 2025-08-20
Added
WaitEngine— fluent explicit wait API (waitForVisible,waitForClickable,waitForText, etc.)- Timeout override —
getWait(seconds)for per-call timeout override waitForStaleness— wait for DOM element replacement after AJAX reload
[0.3.0] — 2025-06-10
Added
BasePage— page object base class withclick,type,getText,isDisplayed,getAttribute- Parallel execution —
parallel.enabled+parallel.threadCountconfiguration - Session semaphore —
browser.maxActiveSessionscap on concurrent browser instances - JUnit XML reporter —
target/surefire-reports/TEST-SeleniumBoot.xml
[0.2.0] — 2025-04-05
Added
BaseTest— test base class withopen(),open(path),getDriver(),getWait()SeleniumBootConfig— YAML configuration loader (selenium-boot.yml)DriverManager— ThreadLocal WebDriver lifecycle management- Automatic driver setup — WebDriverManager integration, no manual driver downloads
- Headless mode —
browser.headless: true - Basic HTML report — pass/fail/skip counts and duration
- Screenshot on failure — automatic capture, embedded in report