Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/).

### Unreleased

- **JUnit Platform: suite-start hooks now fire** — `ExecutionHook.onSuiteStart()` was never called on the JUnit 5 path (only TestNG), so hooks that open a run or start a clock silently did nothing. `SeleniumBootLauncherListener` now bootstraps the framework and fires `onSuiteStart()` once per test plan.

- **Failed tests with trace links in GitHub Actions job summary** — when running inside GitHub Actions and `tracing.enabled: true` is 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 `failureDetail` object 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)
Expand Down
2 changes: 2 additions & 0 deletions docs-site/docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ All notable changes to Selenium Boot are documented here.

## [Unreleased]

- **JUnit Platform: suite-start hooks now fire** — `ExecutionHook.onSuiteStart()` was never called on the JUnit 5 path (only TestNG), so hooks that open a run or start a clock silently did nothing. `SeleniumBootLauncherListener` now bootstraps the framework and fires `onSuiteStart()` once per test plan.

- **Failed tests with trace links in GitHub Actions job summary** — when running inside GitHub Actions and `tracing.enabled: true` is 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 `failureDetail` object 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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.seleniumboot.flakiness.FlakinessAnalyzer;
import com.seleniumboot.hooks.HookRegistry;
import com.seleniumboot.internal.SeleniumBootContext;
import com.seleniumboot.lifecycle.FrameworkBootstrap;
import com.seleniumboot.metrics.ExecutionMetrics;
import com.seleniumboot.reporting.JUnitXmlReporter;
import com.seleniumboot.precondition.PreConditionRunner;
Expand All @@ -29,6 +30,22 @@
@SeleniumBootApi(since = "1.9.0")
public class SeleniumBootLauncherListener implements TestExecutionListener {

/**
* Fires suite-start hooks once per test plan — the JUnit 5 equivalent of
* {@code SuiteExecutionListener.onStart()}. Bootstrap is idempotent, so this is
* safe alongside {@link SeleniumBootExtension#beforeAll}. A bootstrap failure is
* left for the extension to surface with its full cause chain.
*/
@Override
public void testPlanExecutionStarted(TestPlan testPlan) {
try {
FrameworkBootstrap.initialize();
HookRegistry.onSuiteStart();
} catch (Exception e) {
System.err.println("[Selenium Boot] Suite start hooks skipped: " + e.getMessage());
}
}

@Override
public void testPlanExecutionFinished(TestPlan testPlan) {
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.seleniumboot.unit;

import com.seleniumboot.hooks.ExecutionHook;
import com.seleniumboot.hooks.HookRegistry;
import com.seleniumboot.junit5.SeleniumBootLauncherListener;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.Test;

import java.lang.reflect.Field;
import java.util.List;

import static org.testng.Assert.assertEquals;

/**
* Unit tests for {@link SeleniumBootLauncherListener} — the JUnit Platform
* counterpart of {@code SuiteExecutionListener}.
*/
public class SeleniumBootLauncherListenerTest {

@AfterMethod
public void resetRegistry() throws Exception {
Field f = HookRegistry.class.getDeclaredField("hooks");
f.setAccessible(true);
((List<?>) f.get(null)).clear();
}

@Test
public void testPlanExecutionStarted_firesSuiteStartHookOnce() {
CountingHook hook = new CountingHook();
HookRegistry.register(hook);

new SeleniumBootLauncherListener().testPlanExecutionStarted(null);

assertEquals(hook.suiteStarts, 1, "onSuiteStart must fire once per test plan");
}

private static final class CountingHook implements ExecutionHook {
int suiteStarts;

@Override
public void onSuiteStart() {
suiteStarts++;
}
}
}
Loading