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
1 change: 1 addition & 0 deletions java/docs/locator-engine-user-journey.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,4 @@ rememberMe.check();
- Action pipeline behavior is opt-in via locator actions and does not affect raw WebDriver calls.
- User journey remains valid as long as locators remain factory-created and strictness defaults are preserved.
- Stability signal sampling is non-blocking and only enriches diagnostics when used, so the existing journey does not change.
- Sync kernel readiness waits are opt-in and only apply when frameworks route actions through the SyncKernel helpers.
40 changes: 40 additions & 0 deletions java/docs/locator-sync-user-journey.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Locator Sync Kernel User Journey

This document describes the user journey for adopting the Sync Kernel readiness engine in Selenium Java.
It is opt-in and only applies when framework actions/assert helpers call the Sync Kernel APIs.

## Journey: Action Readiness via SyncKernel

1. **Create or obtain a SyncKernel**
- Use `SeleniumSyncKernelFactory` with a WebDriver, policy, and optional BiDi + stability services.
2. **Hook into action lifecycle**
- Framework calls `onBeforeAction` to capture baseline signals.
- Framework calls `onAfterAction` with action outcome to trigger readiness waits.
3. **Wait for intent-specific readiness**
- `waitReady` enforces gates based on intent (CLICK, TYPE, NAVIGATE, ASSERT, MODAL).
- BiDi-dependent gates are skipped when unsupported, with diagnostics noting degradation.
4. **Handle diagnostics on timeout**
- Failures return `SyncDiagnostics` that include gate states and last signal snapshots.

## Example Flow

```java
SyncKernel kernel = SeleniumSyncKernelFactory.create(driver, DefaultSyncPolicy.create(), bidi, stability);

ActionContext ctx = new ActionContext(
ActionType.CLICK,
new WaitTargetElement(buttonElement),
null,
WaitOptions.defaults(),
false);

kernel.onBeforeAction(ctx);
// perform click here
kernel.onAfterAction(ctx, ActionOutcome.SUCCESS);
```

## Impact Check

- The sync kernel does not intercept WebDriver globally; it is only used where actions are routed through it.
- Existing locator usage and diagnostics remain valid without changes.
- Readiness waits are bounded by policy timeouts and can be disabled per call using custom policy or options.
44 changes: 44 additions & 0 deletions java/src/org/openqa/selenium/locator/sync/ActionContext.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package org.openqa.selenium.locator.sync;

import java.util.Objects;

public final class ActionContext {
private final ActionType actionType;
private final WaitTarget target;
private final WaitTarget containerTarget;
private final WaitOptions waitOptions;
private final boolean jsFallbackUsed;

public ActionContext(
ActionType actionType,
WaitTarget target,
WaitTarget containerTarget,
WaitOptions waitOptions,
boolean jsFallbackUsed) {
this.actionType = Objects.requireNonNull(actionType, "actionType");
this.target = target;
this.containerTarget = containerTarget;
this.waitOptions = waitOptions == null ? WaitOptions.defaults() : waitOptions;
this.jsFallbackUsed = jsFallbackUsed;
}

public ActionType actionType() {
return actionType;
}

public WaitTarget target() {
return target;
}

public WaitTarget containerTarget() {
return containerTarget;
}

public WaitOptions waitOptions() {
return waitOptions;
}

public boolean jsFallbackUsed() {
return jsFallbackUsed;
}
}
7 changes: 7 additions & 0 deletions java/src/org/openqa/selenium/locator/sync/ActionOutcome.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.openqa.selenium.locator.sync;

public enum ActionOutcome {
SUCCESS,
FAILURE_RETRYABLE,
FAILURE_FATAL
}
19 changes: 19 additions & 0 deletions java/src/org/openqa/selenium/locator/sync/ActionType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.openqa.selenium.locator.sync;

public enum ActionType {
CLICK,
DBLCLICK,
RIGHT_CLICK,
HOVER,
TYPE,
CLEAR,
SELECT,
PRESS_KEY,
NAVIGATE_TO,
BACK,
FORWARD,
REFRESH,
UPLOAD_FILE,
SCROLL_INTO_VIEW,
CUSTOM_JS
}
8 changes: 8 additions & 0 deletions java/src/org/openqa/selenium/locator/sync/GateStatus.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.openqa.selenium.locator.sync;

public record GateStatus(
boolean active,
boolean satisfied,
String reason,
Long becameTrueAtEpochMs,
Long lastChangedAtEpochMs) {}
10 changes: 10 additions & 0 deletions java/src/org/openqa/selenium/locator/sync/Intent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.openqa.selenium.locator.sync;

public enum Intent {
CLICK,
TYPE,
NAVIGATE,
ASSERT,
OPEN_MODAL,
CLOSE_MODAL
}
24 changes: 24 additions & 0 deletions java/src/org/openqa/selenium/locator/sync/SyncDiagnostics.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.openqa.selenium.locator.sync;

import java.util.List;
import java.util.Map;
import org.openqa.selenium.locator.bidi.model.BidiCapability;
import org.openqa.selenium.locator.bidi.model.ConsoleSnapshot;
import org.openqa.selenium.locator.bidi.model.NavigationSnapshot;
import org.openqa.selenium.locator.bidi.model.NetworkSnapshot;
import org.openqa.selenium.locator.stability.model.StabilitySnapshot;

public record SyncDiagnostics(
Intent intent,
String currentUrl,
String title,
long elapsedMillis,
Map<String, GateStatus> gates,
BidiCapability bidiCapability,
NetworkSnapshot networkSnapshot,
ConsoleSnapshot consoleSnapshot,
NavigationSnapshot navigationSnapshot,
List<StabilitySnapshot> stabilitySamples,
String readyState,
List<String> notes) {}

13 changes: 13 additions & 0 deletions java/src/org/openqa/selenium/locator/sync/SyncKernel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.openqa.selenium.locator.sync;

public interface SyncKernel {
WaitResult waitReady(Intent intent, WaitTarget target, WaitOptions options);

default WaitResult waitReady(Intent intent) {
return waitReady(intent, new WaitTargetNone(), WaitOptions.defaults());
}

void onBeforeAction(ActionContext ctx);

void onAfterAction(ActionContext ctx, ActionOutcome outcome);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.openqa.selenium.locator.sync;

public class SyncTimeoutException extends RuntimeException {
private final WaitResult result;

public SyncTimeoutException(String message, WaitResult result) {
super(message);
this.result = result;
}

public WaitResult result() {
return result;
}
}
12 changes: 12 additions & 0 deletions java/src/org/openqa/selenium/locator/sync/WaitOptions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.openqa.selenium.locator.sync;

import java.time.Duration;

public record WaitOptions(
Duration timeoutOverride,
boolean includeDiagnostics,
boolean strictConsoleErrors) {
public static WaitOptions defaults() {
return new WaitOptions(null, true, false);
}
}
6 changes: 6 additions & 0 deletions java/src/org/openqa/selenium/locator/sync/WaitResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.openqa.selenium.locator.sync;

public record WaitResult(
boolean success,
long elapsedMillis,
SyncDiagnostics diagnostics) {}
3 changes: 3 additions & 0 deletions java/src/org/openqa/selenium/locator/sync/WaitTarget.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package org.openqa.selenium.locator.sync;

public interface WaitTarget {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package org.openqa.selenium.locator.sync;

public record WaitTargetContainer(Object elementHandle) implements WaitTarget {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package org.openqa.selenium.locator.sync;

public record WaitTargetElement(Object elementHandle) implements WaitTarget {}
3 changes: 3 additions & 0 deletions java/src/org/openqa/selenium/locator/sync/WaitTargetNone.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package org.openqa.selenium.locator.sync;

public record WaitTargetNone() implements WaitTarget {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.openqa.selenium.locator.sync.policy;

import java.util.List;
import java.util.regex.Pattern;

public record ConsolePolicy(
boolean requiredWhenSupported,
boolean treatWarnAsFailure,
List<Pattern> readinessDenylist,
List<Pattern> readinessAllowlist) {}
Loading