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: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Playwright is a Java library to automate [Chromium](https://www.chromium.org/Hom

| | Linux | macOS | Windows |
| :--- | :---: | :---: | :---: |
| Chromium <!-- GEN:chromium-version -->136.0.7103.25<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Chromium <!-- GEN:chromium-version -->137.0.7151.27<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| WebKit <!-- GEN:webkit-version -->18.4<!-- GEN:stop --> | ✅ | ✅ | ✅ |
| Firefox <!-- GEN:firefox-version -->137.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |

Expand Down
2 changes: 1 addition & 1 deletion examples/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<name>Playwright Client Examples</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<playwright.version>1.51.0</playwright.version>
<playwright.version>1.53.0</playwright.version>
</properties>
<dependencies>
<dependency>
Expand Down
12 changes: 12 additions & 0 deletions playwright/src/main/java/com/microsoft/playwright/BrowserType.java
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,9 @@ class LaunchOptions {
/**
* Firefox user preferences. Learn more about the Firefox user preferences at <a
* href="https://support.mozilla.org/en-US/kb/about-config-editor-firefox">{@code about:config}</a>.
*
* <p> You can also provide a path to a custom <a href="https://mozilla.github.io/policy-templates/">{@code policies.json}
* file</a> via {@code PLAYWRIGHT_FIREFOX_POLICIES_JSON} environment variable.
*/
public Map<String, Object> firefoxUserPrefs;
/**
Expand Down Expand Up @@ -339,6 +342,9 @@ public LaunchOptions setExecutablePath(Path executablePath) {
/**
* Firefox user preferences. Learn more about the Firefox user preferences at <a
* href="https://support.mozilla.org/en-US/kb/about-config-editor-firefox">{@code about:config}</a>.
*
* <p> You can also provide a path to a custom <a href="https://mozilla.github.io/policy-templates/">{@code policies.json}
* file</a> via {@code PLAYWRIGHT_FIREFOX_POLICIES_JSON} environment variable.
*/
public LaunchOptions setFirefoxUserPrefs(Map<String, Object> firefoxUserPrefs) {
this.firefoxUserPrefs = firefoxUserPrefs;
Expand Down Expand Up @@ -535,6 +541,9 @@ class LaunchPersistentContextOptions {
/**
* Firefox user preferences. Learn more about the Firefox user preferences at <a
* href="https://support.mozilla.org/en-US/kb/about-config-editor-firefox">{@code about:config}</a>.
*
* <p> You can also provide a path to a custom <a href="https://mozilla.github.io/policy-templates/">{@code policies.json}
* file</a> via {@code PLAYWRIGHT_FIREFOX_POLICIES_JSON} environment variable.
*/
public Map<String, Object> firefoxUserPrefs;
/**
Expand Down Expand Up @@ -881,6 +890,9 @@ public LaunchPersistentContextOptions setExtraHTTPHeaders(Map<String, String> ex
/**
* Firefox user preferences. Learn more about the Firefox user preferences at <a
* href="https://support.mozilla.org/en-US/kb/about-config-editor-firefox">{@code about:config}</a>.
*
* <p> You can also provide a path to a custom <a href="https://mozilla.github.io/policy-templates/">{@code policies.json}
* file</a> via {@code PLAYWRIGHT_FIREFOX_POLICIES_JSON} environment variable.
*/
public LaunchPersistentContextOptions setFirefoxUserPrefs(Map<String, Object> firefoxUserPrefs) {
this.firefoxUserPrefs = firefoxUserPrefs;
Expand Down
45 changes: 32 additions & 13 deletions playwright/src/main/java/com/microsoft/playwright/Locator.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,6 @@
*/
public interface Locator {
class AriaSnapshotOptions {
/**
* Generate symbolic reference for each element. One can use {@code aria-ref=<ref>} locator immediately after capturing the
* snapshot to perform actions on the element.
*/
public Boolean ref;
/**
* Maximum time in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
* value can be changed by using the {@link com.microsoft.playwright.BrowserContext#setDefaultTimeout
Expand All @@ -43,14 +38,6 @@ class AriaSnapshotOptions {
*/
public Double timeout;

/**
* Generate symbolic reference for each element. One can use {@code aria-ref=<ref>} locator immediately after capturing the
* snapshot to perform actions on the element.
*/
public AriaSnapshotOptions setRef(boolean ref) {
this.ref = ref;
return this;
}
/**
* Maximum time in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
* value can be changed by using the {@link com.microsoft.playwright.BrowserContext#setDefaultTimeout
Expand Down Expand Up @@ -2615,6 +2602,14 @@ default void dblclick() {
* @since v1.14
*/
void dblclick(DblclickOptions options);
/**
* Describes the locator, description is used in the trace viewer and reports. Returns the locator pointing to the same
* element.
*
* @param description Locator description.
* @since v1.53
*/
Locator describe(String description);
/**
* Programmatically dispatch an event on the matching element.
*
Expand Down Expand Up @@ -2861,6 +2856,14 @@ default ElementHandle elementHandle() {
*
* <p> <strong>Usage</strong>
*
* <p> Passing argument to {@code expression}:
* <pre>{@code
* Object result = page.getByTestId("myId").evaluate("(element, [x, y]) => {\n" +
* " return element.textContent + ' ' + x * y;\n" +
* "}", Arrays.asList(7, 8));
* System.out.println(result); // prints "myId text 56"
* }</pre>
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the function is
* automatically invoked.
* @param arg Optional argument to pass to {@code expression}.
Expand All @@ -2885,6 +2888,14 @@ default Object evaluate(String expression, Object arg) {
*
* <p> <strong>Usage</strong>
*
* <p> Passing argument to {@code expression}:
* <pre>{@code
* Object result = page.getByTestId("myId").evaluate("(element, [x, y]) => {\n" +
* " return element.textContent + ' ' + x * y;\n" +
* "}", Arrays.asList(7, 8));
* System.out.println(result); // prints "myId text 56"
* }</pre>
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the function is
* automatically invoked.
* @since v1.14
Expand All @@ -2908,6 +2919,14 @@ default Object evaluate(String expression) {
*
* <p> <strong>Usage</strong>
*
* <p> Passing argument to {@code expression}:
* <pre>{@code
* Object result = page.getByTestId("myId").evaluate("(element, [x, y]) => {\n" +
* " return element.textContent + ' ' + x * y;\n" +
* "}", Arrays.asList(7, 8));
* System.out.println(result); // prints "myId text 56"
* }</pre>
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the function is
* automatically invoked.
* @param arg Optional argument to pass to {@code expression}.
Expand Down
18 changes: 18 additions & 0 deletions playwright/src/main/java/com/microsoft/playwright/Tracing.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
* API for collecting and saving Playwright traces. Playwright traces can be opened in <a
* href="https://playwright.dev/java/docs/trace-viewer">Trace Viewer</a> after Playwright script runs.
*
* <p> <strong>NOTE:</strong> You probably want to <a href="https://playwright.dev/docs/api/class-testoptions#test-options-trace">enable tracing in
* your config file</a> instead of using {@code context.tracing}.The {@code context.tracing} API captures browser operations and network activity, but it doesn't record test assertions
* (like {@code expect} calls). We recommend <a
* href="https://playwright.dev/docs/api/class-testoptions#test-options-trace">enabling tracing through Playwright Test
* configuration</a>, which includes those assertions and provides a more complete trace for debugging test failures.
*
* <p> Start recording a trace before performing actions. At the end, stop tracing and save it to a file.
* <pre>{@code
* Browser browser = chromium.launch();
Expand Down Expand Up @@ -200,6 +206,12 @@ public StopChunkOptions setPath(Path path) {
/**
* Start tracing.
*
* <p> <strong>NOTE:</strong> You probably want to <a href="https://playwright.dev/docs/api/class-testoptions#test-options-trace">enable tracing in
* your config file</a> instead of using {@code Tracing.start}.The {@code context.tracing} API captures browser operations and network activity, but it doesn't record test assertions
* (like {@code expect} calls). We recommend <a
* href="https://playwright.dev/docs/api/class-testoptions#test-options-trace">enabling tracing through Playwright Test
* configuration</a>, which includes those assertions and provides a more complete trace for debugging test failures.
*
* <p> <strong>Usage</strong>
* <pre>{@code
* context.tracing().start(new Tracing.StartOptions()
Expand All @@ -219,6 +231,12 @@ default void start() {
/**
* Start tracing.
*
* <p> <strong>NOTE:</strong> You probably want to <a href="https://playwright.dev/docs/api/class-testoptions#test-options-trace">enable tracing in
* your config file</a> instead of using {@code Tracing.start}.The {@code context.tracing} API captures browser operations and network activity, but it doesn't record test assertions
* (like {@code expect} calls). We recommend <a
* href="https://playwright.dev/docs/api/class-testoptions#test-options-trace">enabling tracing through Playwright Test
* configuration</a>, which includes those assertions and provides a more complete trace for debugging test failures.
*
* <p> <strong>Usage</strong>
* <pre>{@code
* context.tracing().start(new Tracing.StartOptions()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -885,7 +885,7 @@ default void isVisible() {
* <p> When an array is passed, the method asserts that the list of elements located matches the corresponding list of expected
* class lists. Each element's class attribute is matched against the corresponding class in the array:
* <pre>{@code
* assertThat(page.locator("list > .component")).containsClass(new String[] {"inactive", "active", "inactive"});
* assertThat(page.locator(".list > .component")).containsClass(new String[] {"inactive", "active", "inactive"});
* }</pre>
*
* @param expected A string containing expected class names, separated by spaces, or a list of such strings to assert multiple elements.
Expand All @@ -909,7 +909,7 @@ default void containsClass(String expected) {
* <p> When an array is passed, the method asserts that the list of elements located matches the corresponding list of expected
* class lists. Each element's class attribute is matched against the corresponding class in the array:
* <pre>{@code
* assertThat(page.locator("list > .component")).containsClass(new String[] {"inactive", "active", "inactive"});
* assertThat(page.locator(".list > .component")).containsClass(new String[] {"inactive", "active", "inactive"});
* }</pre>
*
* @param expected A string containing expected class names, separated by spaces, or a list of such strings to assert multiple elements.
Expand All @@ -931,7 +931,7 @@ default void containsClass(String expected) {
* <p> When an array is passed, the method asserts that the list of elements located matches the corresponding list of expected
* class lists. Each element's class attribute is matched against the corresponding class in the array:
* <pre>{@code
* assertThat(page.locator("list > .component")).containsClass(new String[] {"inactive", "active", "inactive"});
* assertThat(page.locator(".list > .component")).containsClass(new String[] {"inactive", "active", "inactive"});
* }</pre>
*
* @param expected A string containing expected class names, separated by spaces, or a list of such strings to assert multiple elements.
Expand All @@ -955,7 +955,7 @@ default void containsClass(List<String> expected) {
* <p> When an array is passed, the method asserts that the list of elements located matches the corresponding list of expected
* class lists. Each element's class attribute is matched against the corresponding class in the array:
* <pre>{@code
* assertThat(page.locator("list > .component")).containsClass(new String[] {"inactive", "active", "inactive"});
* assertThat(page.locator(".list > .component")).containsClass(new String[] {"inactive", "active", "inactive"});
* }</pre>
*
* @param expected A string containing expected class names, separated by spaces, or a list of such strings to assert multiple elements.
Expand Down Expand Up @@ -1565,7 +1565,7 @@ default void hasAttribute(String name, Pattern value) {
* class values. Each element's class attribute is matched against the corresponding string or regular expression in the
* array:
* <pre>{@code
* assertThat(page.locator("list > .component")).hasClass(new String[] {"component", "component selected", "component"});
* assertThat(page.locator(".list > .component")).hasClass(new String[] {"component", "component selected", "component"});
* }</pre>
*
* @param expected Expected class or RegExp or a list of those.
Expand All @@ -1589,7 +1589,7 @@ default void hasClass(String expected) {
* class values. Each element's class attribute is matched against the corresponding string or regular expression in the
* array:
* <pre>{@code
* assertThat(page.locator("list > .component")).hasClass(new String[] {"component", "component selected", "component"});
* assertThat(page.locator(".list > .component")).hasClass(new String[] {"component", "component selected", "component"});
* }</pre>
*
* @param expected Expected class or RegExp or a list of those.
Expand All @@ -1611,7 +1611,7 @@ default void hasClass(String expected) {
* class values. Each element's class attribute is matched against the corresponding string or regular expression in the
* array:
* <pre>{@code
* assertThat(page.locator("list > .component")).hasClass(new String[] {"component", "component selected", "component"});
* assertThat(page.locator(".list > .component")).hasClass(new String[] {"component", "component selected", "component"});
* }</pre>
*
* @param expected Expected class or RegExp or a list of those.
Expand All @@ -1635,7 +1635,7 @@ default void hasClass(Pattern expected) {
* class values. Each element's class attribute is matched against the corresponding string or regular expression in the
* array:
* <pre>{@code
* assertThat(page.locator("list > .component")).hasClass(new String[] {"component", "component selected", "component"});
* assertThat(page.locator(".list > .component")).hasClass(new String[] {"component", "component selected", "component"});
* }</pre>
*
* @param expected Expected class or RegExp or a list of those.
Expand All @@ -1657,7 +1657,7 @@ default void hasClass(Pattern expected) {
* class values. Each element's class attribute is matched against the corresponding string or regular expression in the
* array:
* <pre>{@code
* assertThat(page.locator("list > .component")).hasClass(new String[] {"component", "component selected", "component"});
* assertThat(page.locator(".list > .component")).hasClass(new String[] {"component", "component selected", "component"});
* }</pre>
*
* @param expected Expected class or RegExp or a list of those.
Expand All @@ -1681,7 +1681,7 @@ default void hasClass(String[] expected) {
* class values. Each element's class attribute is matched against the corresponding string or regular expression in the
* array:
* <pre>{@code
* assertThat(page.locator("list > .component")).hasClass(new String[] {"component", "component selected", "component"});
* assertThat(page.locator(".list > .component")).hasClass(new String[] {"component", "component selected", "component"});
* }</pre>
*
* @param expected Expected class or RegExp or a list of those.
Expand All @@ -1703,7 +1703,7 @@ default void hasClass(String[] expected) {
* class values. Each element's class attribute is matched against the corresponding string or regular expression in the
* array:
* <pre>{@code
* assertThat(page.locator("list > .component")).hasClass(new String[] {"component", "component selected", "component"});
* assertThat(page.locator(".list > .component")).hasClass(new String[] {"component", "component selected", "component"});
* }</pre>
*
* @param expected Expected class or RegExp or a list of those.
Expand All @@ -1727,7 +1727,7 @@ default void hasClass(Pattern[] expected) {
* class values. Each element's class attribute is matched against the corresponding string or regular expression in the
* array:
* <pre>{@code
* assertThat(page.locator("list > .component")).hasClass(new String[] {"component", "component selected", "component"});
* assertThat(page.locator(".list > .component")).hasClass(new String[] {"component", "component selected", "component"});
* }</pre>
*
* @param expected Expected class or RegExp or a list of those.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class APIRequestContextImpl extends ChannelOwner implements APIRequestContext {
private final TracingImpl tracing;
private String disposeReason;

protected TimeoutSettings timeoutSettings = new TimeoutSettings();

APIRequestContextImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
super(parent, type, guid, initializer);
this.tracing = connection.getExistingObject(initializer.getAsJsonObject("tracing").get("guid").getAsString());
Expand Down Expand Up @@ -93,6 +95,7 @@ private APIResponse fetchImpl(String url, RequestOptionsImpl options) {
if (options == null) {
options = new RequestOptionsImpl();
}
options.timeout = timeoutSettings.timeout(options.timeout);
JsonObject params = new JsonObject();
params.addProperty("url", url);
if (options.params != null) {
Expand Down Expand Up @@ -132,9 +135,7 @@ private APIResponse fetchImpl(String url, RequestOptionsImpl options) {
if (options.multipart != null) {
params.add("multipartData", serializeMultipartData(options.multipart.fields));
}
if (options.timeout != null) {
params.addProperty("timeout", options.timeout);
}
params.addProperty("timeout", timeoutSettings.timeout(options.timeout));
if (options.failOnStatusCode != null) {
params.addProperty("failOnStatusCode", options.failOnStatusCode);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ private APIRequestContextImpl newContextImpl(NewContextOptions options) {
addToProtocol(params, clientCertificateList);
JsonObject result = playwright.sendMessage("newRequest", params).getAsJsonObject();
APIRequestContextImpl context = playwright.connection.getExistingObject(result.getAsJsonObject("request").get("guid").getAsString());
context.timeoutSettings.setDefaultTimeout(options.timeout);
return context;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ enum EventType {
}
tracing = connection.getExistingObject(initializer.getAsJsonObject("tracing").get("guid").getAsString());
request = connection.getExistingObject(initializer.getAsJsonObject("requestContext").get("guid").getAsString());
request.timeoutSettings = timeoutSettings;
clock = new ClockImpl(this);
closePromise = new WaitableEvent<>(listeners, EventType.CLOSE);
}
Expand Down Expand Up @@ -559,30 +560,12 @@ void recordIntoHar(PageImpl page, Path har, RouteFromHAROptions options) {

@Override
public void setDefaultNavigationTimeout(double timeout) {
setDefaultNavigationTimeoutImpl(timeout);
}

void setDefaultNavigationTimeoutImpl(Double timeout) {
withLogging("BrowserContext.setDefaultNavigationTimeout", () -> {
timeoutSettings.setDefaultNavigationTimeout(timeout);
JsonObject params = new JsonObject();
params.addProperty("timeout", timeout);
sendMessage("setDefaultNavigationTimeoutNoReply", params);
});
timeoutSettings.setDefaultNavigationTimeout(timeout);
}

@Override
public void setDefaultTimeout(double timeout) {
setDefaultTimeoutImpl(timeout);
}

void setDefaultTimeoutImpl(Double timeout) {
withLogging("BrowserContext.setDefaultTimeout", () -> {
timeoutSettings.setDefaultTimeout(timeout);
JsonObject params = new JsonObject();
params.addProperty("timeout", timeout);
sendMessage("setDefaultTimeoutNoReply", params);
});
timeoutSettings.setDefaultTimeout(timeout);
}

@Override
Expand Down
Loading
Loading