1
0
mirror of synced 2026-05-23 03:03:15 +00:00

Compare commits

...

16 Commits

Author SHA1 Message Date
Yury Semikhatsky 71ea72ba53 chore: bump version to 1.28.1 (#1134) 2022-11-28 16:14:43 -08:00
Yury Semikhatsky 7d69f7a087 chore: roll driver to 1.28.1 (#1133) 2022-11-28 16:01:51 -08:00
Yury Semikhatsky 04158db747 cherry-pick(#1131): fix: implement LocatorImpl.getByRole (#1132)
Fixes https://github.com/microsoft/playwright-java/issues/1130
2022-11-28 15:13:25 -08:00
Yury Semikhatsky e47d0ab16c chore: set release version to 1.28.0 (#1125) 2022-11-16 12:42:59 -08:00
Yury Semikhatsky a061ba0f30 chore: roll driver to 1.28.0 (#1124) 2022-11-16 11:47:17 -08:00
Yury Semikhatsky 5a3daf64b9 chore: roll driver to 1.28.0-beta-1668481322000 (#1123) 2022-11-14 22:08:11 -08:00
Yury Semikhatsky 170d07a005 feat: roll driver to 1.29.0-alpha-1668454236000 (#1121) 2022-11-14 14:16:32 -08:00
Yury Semikhatsky 1674f95bd1 fix: do not fail on a bad file name in stack trace (#1120) 2022-11-11 18:42:11 -08:00
Yury Semikhatsky 3cc198ea26 fix: NPE in setInputFiles (#1113) 2022-11-04 16:55:01 -07:00
Yury Semikhatsky 071ca8b90c test: cleanup user-data-dir after tests in TestDefaultBrowserContext2 (#1112) 2022-11-04 16:16:51 -07:00
Max Schmitt 805fa3a8cb devops: update repo for internal tests 2022-10-30 21:30:22 -07:00
Yury Semikhatsky 1825c13fde fix: use internal:text* selectors (#1108) 2022-10-26 11:18:13 -07:00
Yury Semikhatsky 48d9528675 chore: roll driver to 1.28.0-alpha-oct-26-2022 (#1106) 2022-10-26 10:34:05 -07:00
Yury Semikhatsky 4275ee3455 feat(docker): set JAVA_HOME to openjdk 17 (#1105) 2022-10-25 10:38:11 -07:00
Yury Semikhatsky 69f81ea8e9 docs: update version in readme 2022-10-10 12:20:58 -07:00
Yury Semikhatsky 261160e4cf chore: bump dev version to 1.28.0-SNAPSHOT (#1094) 2022-10-07 17:29:18 -07:00
50 changed files with 1256 additions and 401 deletions
+1 -1
View File
@@ -16,6 +16,6 @@ jobs:
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token ${GH_TOKEN}" \
--data "{\"event_type\": \"playwright_tests_java\", \"client_payload\": {\"ref\": \"${GITHUB_SHA}\"}}" \
https://api.github.com/repos/microsoft/playwright-internal/dispatches
https://api.github.com/repos/microsoft/playwright-browsers/dispatches
env:
GH_TOKEN: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
+5 -5
View File
@@ -11,9 +11,9 @@ Playwright is a Java library to automate [Chromium](https://www.chromium.org/Hom
| | Linux | macOS | Windows |
| :--- | :---: | :---: | :---: |
| Chromium <!-- GEN:chromium-version -->107.0.5304.18<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| WebKit <!-- GEN:webkit-version -->16.0<!-- GEN:stop --> | ✅ | ✅ | ✅ |
| Firefox <!-- GEN:firefox-version -->105.0.1<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Chromium <!-- GEN:chromium-version -->108.0.5359.29<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| WebKit <!-- GEN:webkit-version -->16.4<!-- GEN:stop --> | ✅ | ✅ | ✅ |
| Firefox <!-- GEN:firefox-version -->106.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
Headless execution is supported for all the browsers on all platforms. Check out [system requirements](https://playwright.dev/java/docs/next/intro/#system-requirements) for details.
@@ -43,7 +43,7 @@ To run Playwright simply add following dependency to your Maven project:
<dependency>
<groupId>com.microsoft.playwright</groupId>
<artifactId>playwright</artifactId>
<version>1.26.0</version>
<version>1.27.0</version>
</dependency>
```
@@ -51,7 +51,7 @@ To run Playwright using Gradle add following dependency to your build.gradle fil
```gradle
dependencies {
implementation group: 'com.microsoft.playwright', name: 'playwright', version: '1.26.0'
implementation group: 'com.microsoft.playwright', name: 'playwright', version: '1.27.0'
}
```
+1 -1
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>com.microsoft.playwright</groupId>
<artifactId>parent-pom</artifactId>
<version>1.27.0-SNAPSHOT</version>
<version>1.28.1</version>
</parent>
<artifactId>driver-bundle</artifactId>
@@ -17,13 +17,11 @@
package com.microsoft.playwright.impl.driver.jar;
import com.microsoft.playwright.impl.driver.Driver;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.ServerSocket;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
+1 -1
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>com.microsoft.playwright</groupId>
<artifactId>parent-pom</artifactId>
<version>1.27.0-SNAPSHOT</version>
<version>1.28.1</version>
</parent>
<artifactId>driver</artifactId>
+1 -1
View File
@@ -6,7 +6,7 @@
<groupId>org.example</groupId>
<artifactId>examples</artifactId>
<version>1.27.0-SNAPSHOT</version>
<version>1.28.1</version>
<name>Playwright Client Examples</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+1 -1
View File
@@ -7,7 +7,7 @@
<parent>
<groupId>com.microsoft.playwright</groupId>
<artifactId>parent-pom</artifactId>
<version>1.27.0-SNAPSHOT</version>
<version>1.28.1</version>
</parent>
<artifactId>playwright</artifactId>
@@ -81,9 +81,10 @@ public interface Browser extends AutoCloseable {
public Boolean bypassCSP;
/**
* Emulates {@code "prefers-colors-scheme"} media feature, supported values are {@code "light"}, {@code "dark"}, {@code "no-preference"}. See
* {@link Page#emulateMedia Page.emulateMedia()} for more details. Defaults to {@code "light"}.
* {@link Page#emulateMedia Page.emulateMedia()} for more details. Passing {@code null} resets emulation to system defaults.
* Defaults to {@code "light"}.
*/
public ColorScheme colorScheme;
public Optional<ColorScheme> colorScheme;
/**
* Specify device scale factor (can be thought of as dpr). Defaults to {@code 1}.
*/
@@ -94,9 +95,9 @@ public interface Browser extends AutoCloseable {
public Map<String, String> extraHTTPHeaders;
/**
* Emulates {@code "forced-colors"} media feature, supported values are {@code "active"}, {@code "none"}. See {@link Page#emulateMedia
* Page.emulateMedia()} for more details. Defaults to {@code "none"}.
* Page.emulateMedia()} for more details. Passing {@code null} resets emulation to system defaults. Defaults to {@code "none"}.
*/
public ForcedColors forcedColors;
public Optional<ForcedColors> forcedColors;
public Geolocation geolocation;
/**
* Specifies if viewport supports touch events. Defaults to false.
@@ -176,9 +177,10 @@ public interface Browser extends AutoCloseable {
public RecordVideoSize recordVideoSize;
/**
* Emulates {@code "prefers-reduced-motion"} media feature, supported values are {@code "reduce"}, {@code "no-preference"}. See {@link
* Page#emulateMedia Page.emulateMedia()} for more details. Defaults to {@code "no-preference"}.
* Page#emulateMedia Page.emulateMedia()} for more details. Passing {@code null} resets emulation to system defaults. Defaults to
* {@code "no-preference"}.
*/
public ReducedMotion reducedMotion;
public Optional<ReducedMotion> reducedMotion;
/**
* Emulates consistent window screen size available inside web page via {@code window.screen}. Is only used when the {@code viewport}
* is set.
@@ -258,10 +260,11 @@ public interface Browser extends AutoCloseable {
}
/**
* Emulates {@code "prefers-colors-scheme"} media feature, supported values are {@code "light"}, {@code "dark"}, {@code "no-preference"}. See
* {@link Page#emulateMedia Page.emulateMedia()} for more details. Defaults to {@code "light"}.
* {@link Page#emulateMedia Page.emulateMedia()} for more details. Passing {@code null} resets emulation to system defaults.
* Defaults to {@code "light"}.
*/
public NewContextOptions setColorScheme(ColorScheme colorScheme) {
this.colorScheme = colorScheme;
this.colorScheme = Optional.ofNullable(colorScheme);
return this;
}
/**
@@ -280,10 +283,10 @@ public interface Browser extends AutoCloseable {
}
/**
* Emulates {@code "forced-colors"} media feature, supported values are {@code "active"}, {@code "none"}. See {@link Page#emulateMedia
* Page.emulateMedia()} for more details. Defaults to {@code "none"}.
* Page.emulateMedia()} for more details. Passing {@code null} resets emulation to system defaults. Defaults to {@code "none"}.
*/
public NewContextOptions setForcedColors(ForcedColors forcedColors) {
this.forcedColors = forcedColors;
this.forcedColors = Optional.ofNullable(forcedColors);
return this;
}
public NewContextOptions setGeolocation(double latitude, double longitude) {
@@ -447,10 +450,11 @@ public interface Browser extends AutoCloseable {
}
/**
* Emulates {@code "prefers-reduced-motion"} media feature, supported values are {@code "reduce"}, {@code "no-preference"}. See {@link
* Page#emulateMedia Page.emulateMedia()} for more details. Defaults to {@code "no-preference"}.
* Page#emulateMedia Page.emulateMedia()} for more details. Passing {@code null} resets emulation to system defaults. Defaults to
* {@code "no-preference"}.
*/
public NewContextOptions setReducedMotion(ReducedMotion reducedMotion) {
this.reducedMotion = reducedMotion;
this.reducedMotion = Optional.ofNullable(reducedMotion);
return this;
}
/**
@@ -561,9 +565,10 @@ public interface Browser extends AutoCloseable {
public Boolean bypassCSP;
/**
* Emulates {@code "prefers-colors-scheme"} media feature, supported values are {@code "light"}, {@code "dark"}, {@code "no-preference"}. See
* {@link Page#emulateMedia Page.emulateMedia()} for more details. Defaults to {@code "light"}.
* {@link Page#emulateMedia Page.emulateMedia()} for more details. Passing {@code null} resets emulation to system defaults.
* Defaults to {@code "light"}.
*/
public ColorScheme colorScheme;
public Optional<ColorScheme> colorScheme;
/**
* Specify device scale factor (can be thought of as dpr). Defaults to {@code 1}.
*/
@@ -574,9 +579,9 @@ public interface Browser extends AutoCloseable {
public Map<String, String> extraHTTPHeaders;
/**
* Emulates {@code "forced-colors"} media feature, supported values are {@code "active"}, {@code "none"}. See {@link Page#emulateMedia
* Page.emulateMedia()} for more details. Defaults to {@code "none"}.
* Page.emulateMedia()} for more details. Passing {@code null} resets emulation to system defaults. Defaults to {@code "none"}.
*/
public ForcedColors forcedColors;
public Optional<ForcedColors> forcedColors;
public Geolocation geolocation;
/**
* Specifies if viewport supports touch events. Defaults to false.
@@ -656,9 +661,10 @@ public interface Browser extends AutoCloseable {
public RecordVideoSize recordVideoSize;
/**
* Emulates {@code "prefers-reduced-motion"} media feature, supported values are {@code "reduce"}, {@code "no-preference"}. See {@link
* Page#emulateMedia Page.emulateMedia()} for more details. Defaults to {@code "no-preference"}.
* Page#emulateMedia Page.emulateMedia()} for more details. Passing {@code null} resets emulation to system defaults. Defaults to
* {@code "no-preference"}.
*/
public ReducedMotion reducedMotion;
public Optional<ReducedMotion> reducedMotion;
/**
* Emulates consistent window screen size available inside web page via {@code window.screen}. Is only used when the {@code viewport}
* is set.
@@ -738,10 +744,11 @@ public interface Browser extends AutoCloseable {
}
/**
* Emulates {@code "prefers-colors-scheme"} media feature, supported values are {@code "light"}, {@code "dark"}, {@code "no-preference"}. See
* {@link Page#emulateMedia Page.emulateMedia()} for more details. Defaults to {@code "light"}.
* {@link Page#emulateMedia Page.emulateMedia()} for more details. Passing {@code null} resets emulation to system defaults.
* Defaults to {@code "light"}.
*/
public NewPageOptions setColorScheme(ColorScheme colorScheme) {
this.colorScheme = colorScheme;
this.colorScheme = Optional.ofNullable(colorScheme);
return this;
}
/**
@@ -760,10 +767,10 @@ public interface Browser extends AutoCloseable {
}
/**
* Emulates {@code "forced-colors"} media feature, supported values are {@code "active"}, {@code "none"}. See {@link Page#emulateMedia
* Page.emulateMedia()} for more details. Defaults to {@code "none"}.
* Page.emulateMedia()} for more details. Passing {@code null} resets emulation to system defaults. Defaults to {@code "none"}.
*/
public NewPageOptions setForcedColors(ForcedColors forcedColors) {
this.forcedColors = forcedColors;
this.forcedColors = Optional.ofNullable(forcedColors);
return this;
}
public NewPageOptions setGeolocation(double latitude, double longitude) {
@@ -927,10 +934,11 @@ public interface Browser extends AutoCloseable {
}
/**
* Emulates {@code "prefers-reduced-motion"} media feature, supported values are {@code "reduce"}, {@code "no-preference"}. See {@link
* Page#emulateMedia Page.emulateMedia()} for more details. Defaults to {@code "no-preference"}.
* Page#emulateMedia Page.emulateMedia()} for more details. Passing {@code null} resets emulation to system defaults. Defaults to
* {@code "no-preference"}.
*/
public NewPageOptions setReducedMotion(ReducedMotion reducedMotion) {
this.reducedMotion = reducedMotion;
this.reducedMotion = Optional.ofNullable(reducedMotion);
return this;
}
/**
@@ -185,7 +185,8 @@ public interface BrowserContext extends AutoCloseable {
*/
public HarNotFound notFound;
/**
* If specified, updates the given HAR with the actual network information instead of serving from file.
* If specified, updates the given HAR with the actual network information instead of serving from file. The file is
* written to disk when {@link BrowserContext#close BrowserContext.close()} is called.
*/
public Boolean update;
/**
@@ -207,7 +208,8 @@ public interface BrowserContext extends AutoCloseable {
return this;
}
/**
* If specified, updates the given HAR with the actual network information instead of serving from file.
* If specified, updates the given HAR with the actual network information instead of serving from file. The file is
* written to disk when {@link BrowserContext#close BrowserContext.close()} is called.
*/
public RouteFromHAROptions setUpdate(boolean update) {
this.update = update;
@@ -407,9 +407,10 @@ public interface BrowserType {
public Boolean chromiumSandbox;
/**
* Emulates {@code "prefers-colors-scheme"} media feature, supported values are {@code "light"}, {@code "dark"}, {@code "no-preference"}. See
* {@link Page#emulateMedia Page.emulateMedia()} for more details. Defaults to {@code "light"}.
* {@link Page#emulateMedia Page.emulateMedia()} for more details. Passing {@code null} resets emulation to system defaults.
* Defaults to {@code "light"}.
*/
public ColorScheme colorScheme;
public Optional<ColorScheme> colorScheme;
/**
* Specify device scale factor (can be thought of as dpr). Defaults to {@code 1}.
*/
@@ -441,9 +442,9 @@ public interface BrowserType {
public Map<String, String> extraHTTPHeaders;
/**
* Emulates {@code "forced-colors"} media feature, supported values are {@code "active"}, {@code "none"}. See {@link Page#emulateMedia
* Page.emulateMedia()} for more details. Defaults to {@code "none"}.
* Page.emulateMedia()} for more details. Passing {@code null} resets emulation to system defaults. Defaults to {@code "none"}.
*/
public ForcedColors forcedColors;
public Optional<ForcedColors> forcedColors;
public Geolocation geolocation;
/**
* Close the browser process on SIGHUP. Defaults to {@code true}.
@@ -548,9 +549,10 @@ public interface BrowserType {
public RecordVideoSize recordVideoSize;
/**
* Emulates {@code "prefers-reduced-motion"} media feature, supported values are {@code "reduce"}, {@code "no-preference"}. See {@link
* Page#emulateMedia Page.emulateMedia()} for more details. Defaults to {@code "no-preference"}.
* Page#emulateMedia Page.emulateMedia()} for more details. Passing {@code null} resets emulation to system defaults. Defaults to
* {@code "no-preference"}.
*/
public ReducedMotion reducedMotion;
public Optional<ReducedMotion> reducedMotion;
/**
* Emulates consistent window screen size available inside web page via {@code window.screen}. Is only used when the {@code viewport}
* is set.
@@ -666,10 +668,11 @@ public interface BrowserType {
}
/**
* Emulates {@code "prefers-colors-scheme"} media feature, supported values are {@code "light"}, {@code "dark"}, {@code "no-preference"}. See
* {@link Page#emulateMedia Page.emulateMedia()} for more details. Defaults to {@code "light"}.
* {@link Page#emulateMedia Page.emulateMedia()} for more details. Passing {@code null} resets emulation to system defaults.
* Defaults to {@code "light"}.
*/
public LaunchPersistentContextOptions setColorScheme(ColorScheme colorScheme) {
this.colorScheme = colorScheme;
this.colorScheme = Optional.ofNullable(colorScheme);
return this;
}
/**
@@ -721,10 +724,10 @@ public interface BrowserType {
}
/**
* Emulates {@code "forced-colors"} media feature, supported values are {@code "active"}, {@code "none"}. See {@link Page#emulateMedia
* Page.emulateMedia()} for more details. Defaults to {@code "none"}.
* Page.emulateMedia()} for more details. Passing {@code null} resets emulation to system defaults. Defaults to {@code "none"}.
*/
public LaunchPersistentContextOptions setForcedColors(ForcedColors forcedColors) {
this.forcedColors = forcedColors;
this.forcedColors = Optional.ofNullable(forcedColors);
return this;
}
public LaunchPersistentContextOptions setGeolocation(double latitude, double longitude) {
@@ -927,10 +930,11 @@ public interface BrowserType {
}
/**
* Emulates {@code "prefers-reduced-motion"} media feature, supported values are {@code "reduce"}, {@code "no-preference"}. See {@link
* Page#emulateMedia Page.emulateMedia()} for more details. Defaults to {@code "no-preference"}.
* Page#emulateMedia Page.emulateMedia()} for more details. Passing {@code null} resets emulation to system defaults. Defaults to
* {@code "no-preference"}.
*/
public LaunchPersistentContextOptions setReducedMotion(ReducedMotion reducedMotion) {
this.reducedMotion = reducedMotion;
this.reducedMotion = Optional.ofNullable(reducedMotion);
return this;
}
/**
@@ -438,6 +438,12 @@ public interface ElementHandle extends JSHandle {
* modifiers back. If not specified, currently pressed modifiers are used.
*/
public List<KeyboardModifier> modifiers;
/**
* Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can
* opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to
* inaccessible pages. Defaults to {@code false}.
*/
public Boolean noWaitAfter;
/**
* A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of the
* element.
@@ -472,6 +478,15 @@ public interface ElementHandle extends JSHandle {
this.modifiers = modifiers;
return this;
}
/**
* Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can
* opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to
* inaccessible pages. Defaults to {@code false}.
*/
public HoverOptions setNoWaitAfter(boolean noWaitAfter) {
this.noWaitAfter = noWaitAfter;
return this;
}
/**
* A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of the
* element.
@@ -607,7 +622,7 @@ public interface ElementHandle extends JSHandle {
public Integer quality;
/**
* When set to {@code "css"}, screenshot will have a single pixel per each css pixel on the page. For high-dpi devices, this will
* keep screenshots small. Using {@code "device"} option will produce a single pixel per each device pixel, so screenhots of
* keep screenshots small. Using {@code "device"} option will produce a single pixel per each device pixel, so screenshots of
* high-dpi devices will be twice as large or even larger.
*
* <p> Defaults to {@code "device"}.
@@ -680,7 +695,7 @@ public interface ElementHandle extends JSHandle {
}
/**
* When set to {@code "css"}, screenshot will have a single pixel per each css pixel on the page. For high-dpi devices, this will
* keep screenshots small. Using {@code "device"} option will produce a single pixel per each device pixel, so screenhots of
* keep screenshots small. Using {@code "device"} option will produce a single pixel per each device pixel, so screenshots of
* high-dpi devices will be twice as large or even larger.
*
* <p> Defaults to {@code "device"}.
@@ -1438,7 +1453,7 @@ public interface ElementHandle extends JSHandle {
*
* @param selector A selector to query for. See <a href="https://playwright.dev/java/docs/selectors">working with selectors</a> for more
* details.
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @param expression JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the function is
* automatically invoked.
*/
default Object evalOnSelector(String selector, String expression) {
@@ -1464,7 +1479,7 @@ public interface ElementHandle extends JSHandle {
*
* @param selector A selector to query for. See <a href="https://playwright.dev/java/docs/selectors">working with selectors</a> for more
* details.
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @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}.
*/
@@ -1489,7 +1504,7 @@ public interface ElementHandle extends JSHandle {
*
* @param selector A selector to query for. See <a href="https://playwright.dev/java/docs/selectors">working with selectors</a> for more
* details.
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @param expression JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the function is
* automatically invoked.
*/
default Object evalOnSelectorAll(String selector, String expression) {
@@ -1515,7 +1530,7 @@ public interface ElementHandle extends JSHandle {
*
* @param selector A selector to query for. See <a href="https://playwright.dev/java/docs/selectors">working with selectors</a> for more
* details.
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @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}.
*/
@@ -797,13 +797,13 @@ public interface Frame {
class GetByAltTextOptions {
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public Boolean exact;
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public GetByAltTextOptions setExact(boolean exact) {
this.exact = exact;
@@ -813,13 +813,13 @@ public interface Frame {
class GetByLabelOptions {
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public Boolean exact;
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public GetByLabelOptions setExact(boolean exact) {
this.exact = exact;
@@ -829,13 +829,13 @@ public interface Frame {
class GetByPlaceholderOptions {
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public Boolean exact;
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public GetByPlaceholderOptions setExact(boolean exact) {
this.exact = exact;
@@ -844,27 +844,31 @@ public interface Frame {
}
class GetByRoleOptions {
/**
* An attribute that is usually set by {@code aria-checked} or native {@code <input type=checkbox>} controls. Available values for
* checked are {@code true}, {@code false} and {@code "mixed"}.
* An attribute that is usually set by {@code aria-checked} or native {@code <input type=checkbox>} controls.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-checked">{@code aria-checked}</a>.
*/
public Boolean checked;
/**
* A boolean attribute that is usually set by {@code aria-disabled} or {@code disabled}.
* An attribute that is usually set by {@code aria-disabled} or {@code disabled}.
*
* <p> <strong>NOTE:</strong> Unlike most other attributes, {@code disabled} is inherited through the DOM hierarchy. Learn more about <a
* href="https://www.w3.org/TR/wai-aria-1.2/#aria-disabled">{@code aria-disabled}</a>.
*/
public Boolean disabled;
/**
* A boolean attribute that is usually set by {@code aria-expanded}.
* Whether {@code name} is matched exactly: case-sensitive and whole-string. Defaults to false. Ignored when {@code name} is a regular
* expression. Note that exact match still trims whitespace.
*/
public Boolean exact;
/**
* An attribute that is usually set by {@code aria-expanded}.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-expanded">{@code aria-expanded}</a>.
*/
public Boolean expanded;
/**
* A boolean attribute that controls whether hidden elements are matched. By default, only non-hidden elements, as <a
* Option that controls whether hidden elements are matched. By default, only non-hidden elements, as <a
* href="https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion">defined by ARIA</a>, are matched by role selector.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-hidden">{@code aria-hidden}</a>.
@@ -878,27 +882,27 @@ public interface Frame {
*/
public Integer level;
/**
* A string attribute that matches <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
* Option to match the <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>. By default,
* matching is case-insensitive and searches for a substring, use {@code exact} to control this behavior.
*
* <p> Learn more about <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
*/
public Object name;
/**
* An attribute that is usually set by {@code aria-pressed}. Available values for pressed are {@code true}, {@code false} and {@code "mixed"}.
* An attribute that is usually set by {@code aria-pressed}.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-pressed">{@code aria-pressed}</a>.
*/
public Boolean pressed;
/**
* A boolean attribute that is usually set by {@code aria-selected}.
* An attribute that is usually set by {@code aria-selected}.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-selected">{@code aria-selected}</a>.
*/
public Boolean selected;
/**
* An attribute that is usually set by {@code aria-checked} or native {@code <input type=checkbox>} controls. Available values for
* checked are {@code true}, {@code false} and {@code "mixed"}.
* An attribute that is usually set by {@code aria-checked} or native {@code <input type=checkbox>} controls.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-checked">{@code aria-checked}</a>.
*/
@@ -907,7 +911,7 @@ public interface Frame {
return this;
}
/**
* A boolean attribute that is usually set by {@code aria-disabled} or {@code disabled}.
* An attribute that is usually set by {@code aria-disabled} or {@code disabled}.
*
* <p> <strong>NOTE:</strong> Unlike most other attributes, {@code disabled} is inherited through the DOM hierarchy. Learn more about <a
* href="https://www.w3.org/TR/wai-aria-1.2/#aria-disabled">{@code aria-disabled}</a>.
@@ -917,7 +921,15 @@ public interface Frame {
return this;
}
/**
* A boolean attribute that is usually set by {@code aria-expanded}.
* Whether {@code name} is matched exactly: case-sensitive and whole-string. Defaults to false. Ignored when {@code name} is a regular
* expression. Note that exact match still trims whitespace.
*/
public GetByRoleOptions setExact(boolean exact) {
this.exact = exact;
return this;
}
/**
* An attribute that is usually set by {@code aria-expanded}.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-expanded">{@code aria-expanded}</a>.
*/
@@ -926,7 +938,7 @@ public interface Frame {
return this;
}
/**
* A boolean attribute that controls whether hidden elements are matched. By default, only non-hidden elements, as <a
* Option that controls whether hidden elements are matched. By default, only non-hidden elements, as <a
* href="https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion">defined by ARIA</a>, are matched by role selector.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-hidden">{@code aria-hidden}</a>.
@@ -946,7 +958,8 @@ public interface Frame {
return this;
}
/**
* A string attribute that matches <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
* Option to match the <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>. By default,
* matching is case-insensitive and searches for a substring, use {@code exact} to control this behavior.
*
* <p> Learn more about <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
*/
@@ -955,7 +968,8 @@ public interface Frame {
return this;
}
/**
* A string attribute that matches <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
* Option to match the <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>. By default,
* matching is case-insensitive and searches for a substring, use {@code exact} to control this behavior.
*
* <p> Learn more about <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
*/
@@ -964,7 +978,7 @@ public interface Frame {
return this;
}
/**
* An attribute that is usually set by {@code aria-pressed}. Available values for pressed are {@code true}, {@code false} and {@code "mixed"}.
* An attribute that is usually set by {@code aria-pressed}.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-pressed">{@code aria-pressed}</a>.
*/
@@ -973,7 +987,7 @@ public interface Frame {
return this;
}
/**
* A boolean attribute that is usually set by {@code aria-selected}.
* An attribute that is usually set by {@code aria-selected}.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-selected">{@code aria-selected}</a>.
*/
@@ -985,13 +999,13 @@ public interface Frame {
class GetByTextOptions {
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public Boolean exact;
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public GetByTextOptions setExact(boolean exact) {
this.exact = exact;
@@ -1001,13 +1015,13 @@ public interface Frame {
class GetByTitleOptions {
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public Boolean exact;
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public GetByTitleOptions setExact(boolean exact) {
this.exact = exact;
@@ -1081,6 +1095,12 @@ public interface Frame {
* modifiers back. If not specified, currently pressed modifiers are used.
*/
public List<KeyboardModifier> modifiers;
/**
* Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can
* opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to
* inaccessible pages. Defaults to {@code false}.
*/
public Boolean noWaitAfter;
/**
* A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of the
* element.
@@ -1120,6 +1140,15 @@ public interface Frame {
this.modifiers = modifiers;
return this;
}
/**
* Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can
* opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to
* inaccessible pages. Defaults to {@code false}.
*/
public HoverOptions setNoWaitAfter(boolean noWaitAfter) {
this.noWaitAfter = noWaitAfter;
return this;
}
/**
* A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of the
* element.
@@ -2629,7 +2658,7 @@ public interface Frame {
*
* @param selector A selector to query for. See <a href="https://playwright.dev/java/docs/selectors">working with selectors</a> for more
* details.
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @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}.
*/
@@ -2659,7 +2688,7 @@ public interface Frame {
*
* @param selector A selector to query for. See <a href="https://playwright.dev/java/docs/selectors">working with selectors</a> for more
* details.
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @param expression JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the function is
* automatically invoked.
*/
default Object evalOnSelector(String selector, String expression) {
@@ -2688,7 +2717,7 @@ public interface Frame {
*
* @param selector A selector to query for. See <a href="https://playwright.dev/java/docs/selectors">working with selectors</a> for more
* details.
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @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}.
*/
@@ -2714,7 +2743,7 @@ public interface Frame {
*
* @param selector A selector to query for. See <a href="https://playwright.dev/java/docs/selectors">working with selectors</a> for more
* details.
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @param expression JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the function is
* automatically invoked.
*/
default Object evalOnSelectorAll(String selector, String expression) {
@@ -2741,7 +2770,7 @@ public interface Frame {
*
* @param selector A selector to query for. See <a href="https://playwright.dev/java/docs/selectors">working with selectors</a> for more
* details.
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @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}.
*/
@@ -2775,7 +2804,7 @@ public interface Frame {
* bodyHandle.dispose();
* }</pre>
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @param expression JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the function is
* automatically invoked.
*/
default Object evaluate(String expression) {
@@ -2810,7 +2839,7 @@ public interface Frame {
* bodyHandle.dispose();
* }</pre>
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @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}.
*/
@@ -2842,7 +2871,7 @@ public interface Frame {
* resultHandle.dispose();
* }</pre>
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @param expression JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the function is
* automatically invoked.
*/
default JSHandle evaluateHandle(String expression) {
@@ -2875,7 +2904,7 @@ public interface Frame {
* resultHandle.dispose();
* }</pre>
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @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}.
*/
@@ -3009,7 +3038,7 @@ public interface Frame {
Locator getByAltText(Pattern text, GetByAltTextOptions options);
/**
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text Password in the following DOM:
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
*/
@@ -3018,14 +3047,14 @@ public interface Frame {
}
/**
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text Password in the following DOM:
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
*/
Locator getByLabel(String text, GetByLabelOptions options);
/**
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text Password in the following DOM:
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
*/
@@ -3034,7 +3063,7 @@ public interface Frame {
}
/**
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text Password in the following DOM:
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
*/
@@ -3111,7 +3140,34 @@ public interface Frame {
*/
Locator getByTestId(String testId);
/**
* Allows locating elements that contain given text.
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
* // Matches <span>
* page.getByText("world")
*
* // Matches first <div>
* page.getByText("Hello world")
*
* // Matches second <div>
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
*
* // Matches both <div>s
* page.getByText(Pattern.compile("Hello"))
*
* // Matches second <div>
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text content. For example,
* locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
*/
@@ -3119,13 +3175,67 @@ public interface Frame {
return getByText(text, null);
}
/**
* Allows locating elements that contain given text.
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
* // Matches <span>
* page.getByText("world")
*
* // Matches first <div>
* page.getByText("Hello world")
*
* // Matches second <div>
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
*
* // Matches both <div>s
* page.getByText(Pattern.compile("Hello"))
*
* // Matches second <div>
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text content. For example,
* locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
*/
Locator getByText(String text, GetByTextOptions options);
/**
* Allows locating elements that contain given text.
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
* // Matches <span>
* page.getByText("world")
*
* // Matches first <div>
* page.getByText("Hello world")
*
* // Matches second <div>
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
*
* // Matches both <div>s
* page.getByText(Pattern.compile("Hello"))
*
* // Matches second <div>
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text content. For example,
* locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
*/
@@ -3133,13 +3243,40 @@ public interface Frame {
return getByText(text, null);
}
/**
* Allows locating elements that contain given text.
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
* // Matches <span>
* page.getByText("world")
*
* // Matches first <div>
* page.getByText("Hello world")
*
* // Matches second <div>
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
*
* // Matches both <div>s
* page.getByText(Pattern.compile("Hello"))
*
* // Matches second <div>
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text content. For example,
* locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
*/
Locator getByText(Pattern text, GetByTextOptions options);
/**
* Allows locating elements by their title. For example, this method will find the button by its title "Submit":
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
*/
@@ -3147,13 +3284,13 @@ public interface Frame {
return getByTitle(text, null);
}
/**
* Allows locating elements by their title. For example, this method will find the button by its title "Submit":
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
*/
Locator getByTitle(String text, GetByTitleOptions options);
/**
* Allows locating elements by their title. For example, this method will find the button by its title "Submit":
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
*/
@@ -3161,7 +3298,7 @@ public interface Frame {
return getByTitle(text, null);
}
/**
* Allows locating elements by their title. For example, this method will find the button by its title "Submit":
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
*/
@@ -4270,7 +4407,7 @@ public interface Frame {
* frame.waitForFunction("selector => !!document.querySelector(selector)", selector);
* }</pre>
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @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}.
*/
@@ -4304,7 +4441,7 @@ public interface Frame {
* frame.waitForFunction("selector => !!document.querySelector(selector)", selector);
* }</pre>
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @param expression JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the function is
* automatically invoked.
*/
default JSHandle waitForFunction(String expression) {
@@ -4337,7 +4474,7 @@ public interface Frame {
* frame.waitForFunction("selector => !!document.querySelector(selector)", selector);
* }</pre>
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @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}.
*/
@@ -24,7 +24,7 @@ import java.util.regex.Pattern;
* and locate elements in that iframe. FrameLocator can be created with either {@link Page#frameLocator
* Page.frameLocator()} or {@link Locator#frameLocator Locator.frameLocator()} method.
* <pre>{@code
* Locator locator = page.frameLocator("#my-frame").locator("text=Submit");
* Locator locator = page.frameLocator("#my-frame").getByText("Submit");
* locator.click();
* }</pre>
*
@@ -52,13 +52,13 @@ public interface FrameLocator {
class GetByAltTextOptions {
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public Boolean exact;
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public GetByAltTextOptions setExact(boolean exact) {
this.exact = exact;
@@ -68,13 +68,13 @@ public interface FrameLocator {
class GetByLabelOptions {
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public Boolean exact;
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public GetByLabelOptions setExact(boolean exact) {
this.exact = exact;
@@ -84,13 +84,13 @@ public interface FrameLocator {
class GetByPlaceholderOptions {
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public Boolean exact;
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public GetByPlaceholderOptions setExact(boolean exact) {
this.exact = exact;
@@ -99,27 +99,31 @@ public interface FrameLocator {
}
class GetByRoleOptions {
/**
* An attribute that is usually set by {@code aria-checked} or native {@code <input type=checkbox>} controls. Available values for
* checked are {@code true}, {@code false} and {@code "mixed"}.
* An attribute that is usually set by {@code aria-checked} or native {@code <input type=checkbox>} controls.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-checked">{@code aria-checked}</a>.
*/
public Boolean checked;
/**
* A boolean attribute that is usually set by {@code aria-disabled} or {@code disabled}.
* An attribute that is usually set by {@code aria-disabled} or {@code disabled}.
*
* <p> <strong>NOTE:</strong> Unlike most other attributes, {@code disabled} is inherited through the DOM hierarchy. Learn more about <a
* href="https://www.w3.org/TR/wai-aria-1.2/#aria-disabled">{@code aria-disabled}</a>.
*/
public Boolean disabled;
/**
* A boolean attribute that is usually set by {@code aria-expanded}.
* Whether {@code name} is matched exactly: case-sensitive and whole-string. Defaults to false. Ignored when {@code name} is a regular
* expression. Note that exact match still trims whitespace.
*/
public Boolean exact;
/**
* An attribute that is usually set by {@code aria-expanded}.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-expanded">{@code aria-expanded}</a>.
*/
public Boolean expanded;
/**
* A boolean attribute that controls whether hidden elements are matched. By default, only non-hidden elements, as <a
* Option that controls whether hidden elements are matched. By default, only non-hidden elements, as <a
* href="https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion">defined by ARIA</a>, are matched by role selector.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-hidden">{@code aria-hidden}</a>.
@@ -133,27 +137,27 @@ public interface FrameLocator {
*/
public Integer level;
/**
* A string attribute that matches <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
* Option to match the <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>. By default,
* matching is case-insensitive and searches for a substring, use {@code exact} to control this behavior.
*
* <p> Learn more about <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
*/
public Object name;
/**
* An attribute that is usually set by {@code aria-pressed}. Available values for pressed are {@code true}, {@code false} and {@code "mixed"}.
* An attribute that is usually set by {@code aria-pressed}.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-pressed">{@code aria-pressed}</a>.
*/
public Boolean pressed;
/**
* A boolean attribute that is usually set by {@code aria-selected}.
* An attribute that is usually set by {@code aria-selected}.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-selected">{@code aria-selected}</a>.
*/
public Boolean selected;
/**
* An attribute that is usually set by {@code aria-checked} or native {@code <input type=checkbox>} controls. Available values for
* checked are {@code true}, {@code false} and {@code "mixed"}.
* An attribute that is usually set by {@code aria-checked} or native {@code <input type=checkbox>} controls.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-checked">{@code aria-checked}</a>.
*/
@@ -162,7 +166,7 @@ public interface FrameLocator {
return this;
}
/**
* A boolean attribute that is usually set by {@code aria-disabled} or {@code disabled}.
* An attribute that is usually set by {@code aria-disabled} or {@code disabled}.
*
* <p> <strong>NOTE:</strong> Unlike most other attributes, {@code disabled} is inherited through the DOM hierarchy. Learn more about <a
* href="https://www.w3.org/TR/wai-aria-1.2/#aria-disabled">{@code aria-disabled}</a>.
@@ -172,7 +176,15 @@ public interface FrameLocator {
return this;
}
/**
* A boolean attribute that is usually set by {@code aria-expanded}.
* Whether {@code name} is matched exactly: case-sensitive and whole-string. Defaults to false. Ignored when {@code name} is a regular
* expression. Note that exact match still trims whitespace.
*/
public GetByRoleOptions setExact(boolean exact) {
this.exact = exact;
return this;
}
/**
* An attribute that is usually set by {@code aria-expanded}.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-expanded">{@code aria-expanded}</a>.
*/
@@ -181,7 +193,7 @@ public interface FrameLocator {
return this;
}
/**
* A boolean attribute that controls whether hidden elements are matched. By default, only non-hidden elements, as <a
* Option that controls whether hidden elements are matched. By default, only non-hidden elements, as <a
* href="https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion">defined by ARIA</a>, are matched by role selector.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-hidden">{@code aria-hidden}</a>.
@@ -201,7 +213,8 @@ public interface FrameLocator {
return this;
}
/**
* A string attribute that matches <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
* Option to match the <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>. By default,
* matching is case-insensitive and searches for a substring, use {@code exact} to control this behavior.
*
* <p> Learn more about <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
*/
@@ -210,7 +223,8 @@ public interface FrameLocator {
return this;
}
/**
* A string attribute that matches <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
* Option to match the <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>. By default,
* matching is case-insensitive and searches for a substring, use {@code exact} to control this behavior.
*
* <p> Learn more about <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
*/
@@ -219,7 +233,7 @@ public interface FrameLocator {
return this;
}
/**
* An attribute that is usually set by {@code aria-pressed}. Available values for pressed are {@code true}, {@code false} and {@code "mixed"}.
* An attribute that is usually set by {@code aria-pressed}.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-pressed">{@code aria-pressed}</a>.
*/
@@ -228,7 +242,7 @@ public interface FrameLocator {
return this;
}
/**
* A boolean attribute that is usually set by {@code aria-selected}.
* An attribute that is usually set by {@code aria-selected}.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-selected">{@code aria-selected}</a>.
*/
@@ -240,13 +254,13 @@ public interface FrameLocator {
class GetByTextOptions {
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public Boolean exact;
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public GetByTextOptions setExact(boolean exact) {
this.exact = exact;
@@ -256,13 +270,13 @@ public interface FrameLocator {
class GetByTitleOptions {
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public Boolean exact;
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public GetByTitleOptions setExact(boolean exact) {
this.exact = exact;
@@ -355,7 +369,7 @@ public interface FrameLocator {
Locator getByAltText(Pattern text, GetByAltTextOptions options);
/**
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text Password in the following DOM:
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
*/
@@ -364,14 +378,14 @@ public interface FrameLocator {
}
/**
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text Password in the following DOM:
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
*/
Locator getByLabel(String text, GetByLabelOptions options);
/**
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text Password in the following DOM:
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
*/
@@ -380,7 +394,7 @@ public interface FrameLocator {
}
/**
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text Password in the following DOM:
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
*/
@@ -457,7 +471,34 @@ public interface FrameLocator {
*/
Locator getByTestId(String testId);
/**
* Allows locating elements that contain given text.
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
* // Matches <span>
* page.getByText("world")
*
* // Matches first <div>
* page.getByText("Hello world")
*
* // Matches second <div>
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
*
* // Matches both <div>s
* page.getByText(Pattern.compile("Hello"))
*
* // Matches second <div>
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text content. For example,
* locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
*/
@@ -465,13 +506,67 @@ public interface FrameLocator {
return getByText(text, null);
}
/**
* Allows locating elements that contain given text.
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
* // Matches <span>
* page.getByText("world")
*
* // Matches first <div>
* page.getByText("Hello world")
*
* // Matches second <div>
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
*
* // Matches both <div>s
* page.getByText(Pattern.compile("Hello"))
*
* // Matches second <div>
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text content. For example,
* locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
*/
Locator getByText(String text, GetByTextOptions options);
/**
* Allows locating elements that contain given text.
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
* // Matches <span>
* page.getByText("world")
*
* // Matches first <div>
* page.getByText("Hello world")
*
* // Matches second <div>
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
*
* // Matches both <div>s
* page.getByText(Pattern.compile("Hello"))
*
* // Matches second <div>
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text content. For example,
* locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
*/
@@ -479,13 +574,40 @@ public interface FrameLocator {
return getByText(text, null);
}
/**
* Allows locating elements that contain given text.
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
* // Matches <span>
* page.getByText("world")
*
* // Matches first <div>
* page.getByText("Hello world")
*
* // Matches second <div>
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
*
* // Matches both <div>s
* page.getByText(Pattern.compile("Hello"))
*
* // Matches second <div>
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text content. For example,
* locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
*/
Locator getByText(Pattern text, GetByTextOptions options);
/**
* Allows locating elements by their title. For example, this method will find the button by its title "Submit":
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
*/
@@ -493,13 +615,13 @@ public interface FrameLocator {
return getByTitle(text, null);
}
/**
* Allows locating elements by their title. For example, this method will find the button by its title "Submit":
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
*/
Locator getByTitle(String text, GetByTitleOptions options);
/**
* Allows locating elements by their title. For example, this method will find the button by its title "Submit":
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
*/
@@ -507,7 +629,7 @@ public interface FrameLocator {
return getByTitle(text, null);
}
/**
* Allows locating elements by their title. For example, this method will find the button by its title "Submit":
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
*/
@@ -57,7 +57,7 @@ public interface JSHandle {
* assertEquals("10 retweets", tweetHandle.evaluate("node => node.innerText"));
* }</pre>
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @param expression JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the function is
* automatically invoked.
*/
default Object evaluate(String expression) {
@@ -78,7 +78,7 @@ public interface JSHandle {
* assertEquals("10 retweets", tweetHandle.evaluate("node => node.innerText"));
* }</pre>
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @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}.
*/
@@ -97,7 +97,7 @@ public interface JSHandle {
*
* <p> See {@link Page#evaluateHandle Page.evaluateHandle()} for more details.
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @param expression JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the function is
* automatically invoked.
*/
default JSHandle evaluateHandle(String expression) {
@@ -117,7 +117,7 @@ public interface JSHandle {
*
* <p> See {@link Page#evaluateHandle Page.evaluateHandle()} for more details.
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @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}.
*/
@@ -20,7 +20,7 @@ import com.microsoft.playwright.options.*;
/**
* Keyboard provides an api for managing a virtual keyboard. The high level api is {@link Keyboard#type Keyboard.type()},
* which takes raw characters and generates proper keydown, keypress/input, and keyup events on your page.
* which takes raw characters and generates proper {@code keydown}, {@code keypress}/{@code input}, and {@code keyup} events on your page.
*
* <p> For finer control, you can use {@link Keyboard#down Keyboard.down()}, {@link Keyboard#up Keyboard.up()}, and {@link
* Keyboard#insertText Keyboard.insertText()} to manually fire events as if they were generated from a real keyboard.
@@ -29,6 +29,24 @@ import java.util.regex.Pattern;
* <p> <a href="https://playwright.dev/java/docs/locators">Learn more about locators</a>.
*/
public interface Locator {
class BlurOptions {
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass {@code 0} to disable timeout. The default value can be changed by
* using the {@link BrowserContext#setDefaultTimeout BrowserContext.setDefaultTimeout()} or {@link Page#setDefaultTimeout
* Page.setDefaultTimeout()} methods.
*/
public Double timeout;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass {@code 0} to disable timeout. The default value can be changed by
* using the {@link BrowserContext#setDefaultTimeout BrowserContext.setDefaultTimeout()} or {@link Page#setDefaultTimeout
* Page.setDefaultTimeout()} methods.
*/
public BlurOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
class BoundingBoxOptions {
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass {@code 0} to disable timeout. The default value can be changed by
@@ -128,6 +146,52 @@ public interface Locator {
return this;
}
}
class ClearOptions {
/**
* Whether to bypass the <a href="https://playwright.dev/java/docs/actionability">actionability</a> checks. Defaults to
* {@code false}.
*/
public Boolean force;
/**
* Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can
* opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to
* inaccessible pages. Defaults to {@code false}.
*/
public Boolean noWaitAfter;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass {@code 0} to disable timeout. The default value can be changed by
* using the {@link BrowserContext#setDefaultTimeout BrowserContext.setDefaultTimeout()} or {@link Page#setDefaultTimeout
* Page.setDefaultTimeout()} methods.
*/
public Double timeout;
/**
* Whether to bypass the <a href="https://playwright.dev/java/docs/actionability">actionability</a> checks. Defaults to
* {@code false}.
*/
public ClearOptions setForce(boolean force) {
this.force = force;
return this;
}
/**
* Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can
* opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to
* inaccessible pages. Defaults to {@code false}.
*/
public ClearOptions setNoWaitAfter(boolean noWaitAfter) {
this.noWaitAfter = noWaitAfter;
return this;
}
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass {@code 0} to disable timeout. The default value can be changed by
* using the {@link BrowserContext#setDefaultTimeout BrowserContext.setDefaultTimeout()} or {@link Page#setDefaultTimeout
* Page.setDefaultTimeout()} methods.
*/
public ClearOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
class ClickOptions {
/**
* Defaults to {@code left}.
@@ -673,13 +737,13 @@ public interface Locator {
class GetByAltTextOptions {
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public Boolean exact;
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public GetByAltTextOptions setExact(boolean exact) {
this.exact = exact;
@@ -689,13 +753,13 @@ public interface Locator {
class GetByLabelOptions {
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public Boolean exact;
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public GetByLabelOptions setExact(boolean exact) {
this.exact = exact;
@@ -705,13 +769,13 @@ public interface Locator {
class GetByPlaceholderOptions {
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public Boolean exact;
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public GetByPlaceholderOptions setExact(boolean exact) {
this.exact = exact;
@@ -720,27 +784,31 @@ public interface Locator {
}
class GetByRoleOptions {
/**
* An attribute that is usually set by {@code aria-checked} or native {@code <input type=checkbox>} controls. Available values for
* checked are {@code true}, {@code false} and {@code "mixed"}.
* An attribute that is usually set by {@code aria-checked} or native {@code <input type=checkbox>} controls.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-checked">{@code aria-checked}</a>.
*/
public Boolean checked;
/**
* A boolean attribute that is usually set by {@code aria-disabled} or {@code disabled}.
* An attribute that is usually set by {@code aria-disabled} or {@code disabled}.
*
* <p> <strong>NOTE:</strong> Unlike most other attributes, {@code disabled} is inherited through the DOM hierarchy. Learn more about <a
* href="https://www.w3.org/TR/wai-aria-1.2/#aria-disabled">{@code aria-disabled}</a>.
*/
public Boolean disabled;
/**
* A boolean attribute that is usually set by {@code aria-expanded}.
* Whether {@code name} is matched exactly: case-sensitive and whole-string. Defaults to false. Ignored when {@code name} is a regular
* expression. Note that exact match still trims whitespace.
*/
public Boolean exact;
/**
* An attribute that is usually set by {@code aria-expanded}.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-expanded">{@code aria-expanded}</a>.
*/
public Boolean expanded;
/**
* A boolean attribute that controls whether hidden elements are matched. By default, only non-hidden elements, as <a
* Option that controls whether hidden elements are matched. By default, only non-hidden elements, as <a
* href="https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion">defined by ARIA</a>, are matched by role selector.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-hidden">{@code aria-hidden}</a>.
@@ -754,27 +822,27 @@ public interface Locator {
*/
public Integer level;
/**
* A string attribute that matches <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
* Option to match the <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>. By default,
* matching is case-insensitive and searches for a substring, use {@code exact} to control this behavior.
*
* <p> Learn more about <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
*/
public Object name;
/**
* An attribute that is usually set by {@code aria-pressed}. Available values for pressed are {@code true}, {@code false} and {@code "mixed"}.
* An attribute that is usually set by {@code aria-pressed}.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-pressed">{@code aria-pressed}</a>.
*/
public Boolean pressed;
/**
* A boolean attribute that is usually set by {@code aria-selected}.
* An attribute that is usually set by {@code aria-selected}.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-selected">{@code aria-selected}</a>.
*/
public Boolean selected;
/**
* An attribute that is usually set by {@code aria-checked} or native {@code <input type=checkbox>} controls. Available values for
* checked are {@code true}, {@code false} and {@code "mixed"}.
* An attribute that is usually set by {@code aria-checked} or native {@code <input type=checkbox>} controls.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-checked">{@code aria-checked}</a>.
*/
@@ -783,7 +851,7 @@ public interface Locator {
return this;
}
/**
* A boolean attribute that is usually set by {@code aria-disabled} or {@code disabled}.
* An attribute that is usually set by {@code aria-disabled} or {@code disabled}.
*
* <p> <strong>NOTE:</strong> Unlike most other attributes, {@code disabled} is inherited through the DOM hierarchy. Learn more about <a
* href="https://www.w3.org/TR/wai-aria-1.2/#aria-disabled">{@code aria-disabled}</a>.
@@ -793,7 +861,15 @@ public interface Locator {
return this;
}
/**
* A boolean attribute that is usually set by {@code aria-expanded}.
* Whether {@code name} is matched exactly: case-sensitive and whole-string. Defaults to false. Ignored when {@code name} is a regular
* expression. Note that exact match still trims whitespace.
*/
public GetByRoleOptions setExact(boolean exact) {
this.exact = exact;
return this;
}
/**
* An attribute that is usually set by {@code aria-expanded}.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-expanded">{@code aria-expanded}</a>.
*/
@@ -802,7 +878,7 @@ public interface Locator {
return this;
}
/**
* A boolean attribute that controls whether hidden elements are matched. By default, only non-hidden elements, as <a
* Option that controls whether hidden elements are matched. By default, only non-hidden elements, as <a
* href="https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion">defined by ARIA</a>, are matched by role selector.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-hidden">{@code aria-hidden}</a>.
@@ -822,7 +898,8 @@ public interface Locator {
return this;
}
/**
* A string attribute that matches <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
* Option to match the <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>. By default,
* matching is case-insensitive and searches for a substring, use {@code exact} to control this behavior.
*
* <p> Learn more about <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
*/
@@ -831,7 +908,8 @@ public interface Locator {
return this;
}
/**
* A string attribute that matches <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
* Option to match the <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>. By default,
* matching is case-insensitive and searches for a substring, use {@code exact} to control this behavior.
*
* <p> Learn more about <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
*/
@@ -840,7 +918,7 @@ public interface Locator {
return this;
}
/**
* An attribute that is usually set by {@code aria-pressed}. Available values for pressed are {@code true}, {@code false} and {@code "mixed"}.
* An attribute that is usually set by {@code aria-pressed}.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-pressed">{@code aria-pressed}</a>.
*/
@@ -849,7 +927,7 @@ public interface Locator {
return this;
}
/**
* A boolean attribute that is usually set by {@code aria-selected}.
* An attribute that is usually set by {@code aria-selected}.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-selected">{@code aria-selected}</a>.
*/
@@ -861,13 +939,13 @@ public interface Locator {
class GetByTextOptions {
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public Boolean exact;
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public GetByTextOptions setExact(boolean exact) {
this.exact = exact;
@@ -877,13 +955,13 @@ public interface Locator {
class GetByTitleOptions {
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public Boolean exact;
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public GetByTitleOptions setExact(boolean exact) {
this.exact = exact;
@@ -901,6 +979,12 @@ public interface Locator {
* modifiers back. If not specified, currently pressed modifiers are used.
*/
public List<KeyboardModifier> modifiers;
/**
* Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can
* opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to
* inaccessible pages. Defaults to {@code false}.
*/
public Boolean noWaitAfter;
/**
* A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of the
* element.
@@ -935,6 +1019,15 @@ public interface Locator {
this.modifiers = modifiers;
return this;
}
/**
* Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can
* opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to
* inaccessible pages. Defaults to {@code false}.
*/
public HoverOptions setNoWaitAfter(boolean noWaitAfter) {
this.noWaitAfter = noWaitAfter;
return this;
}
/**
* A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of the
* element.
@@ -1254,7 +1347,7 @@ public interface Locator {
public Integer quality;
/**
* When set to {@code "css"}, screenshot will have a single pixel per each css pixel on the page. For high-dpi devices, this will
* keep screenshots small. Using {@code "device"} option will produce a single pixel per each device pixel, so screenhots of
* keep screenshots small. Using {@code "device"} option will produce a single pixel per each device pixel, so screenshots of
* high-dpi devices will be twice as large or even larger.
*
* <p> Defaults to {@code "device"}.
@@ -1327,7 +1420,7 @@ public interface Locator {
}
/**
* When set to {@code "css"}, screenshot will have a single pixel per each css pixel on the page. For high-dpi devices, this will
* keep screenshots small. Using {@code "device"} option will produce a single pixel per each device pixel, so screenhots of
* keep screenshots small. Using {@code "device"} option will produce a single pixel per each device pixel, so screenshots of
* high-dpi devices will be twice as large or even larger.
*
* <p> Defaults to {@code "device"}.
@@ -1852,6 +1945,16 @@ public interface Locator {
* Returns an array of {@code node.textContent} values for all matching nodes.
*/
List<String> allTextContents();
/**
* Calls <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/blur">blur</a> on the element.
*/
default void blur() {
blur(null);
}
/**
* Calls <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/blur">blur</a> on the element.
*/
void blur(BlurOptions options);
/**
* This method returns the bounding box of the element, or {@code null} if the element is not visible. The bounding box is
* calculated relative to the main frame viewport - which is usually the same as the browser window.
@@ -1932,6 +2035,28 @@ public interface Locator {
* zero timeout disables this.
*/
void check(CheckOptions options);
/**
* This method waits for <a href="https://playwright.dev/java/docs/actionability">actionability</a> checks, focuses the
* element, clears it and triggers an {@code input} event after clearing.
*
* <p> If the target element is not an {@code <input>}, {@code <textarea>} or {@code [contenteditable]} element, this method throws an error.
* However, if the element is inside the {@code <label>} element that has an associated <a
* href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control">control</a>, the control will be
* cleared instead.
*/
default void clear() {
clear(null);
}
/**
* This method waits for <a href="https://playwright.dev/java/docs/actionability">actionability</a> checks, focuses the
* element, clears it and triggers an {@code input} event after clearing.
*
* <p> If the target element is not an {@code <input>}, {@code <textarea>} or {@code [contenteditable]} element, this method throws an error.
* However, if the element is inside the {@code <label>} element that has an associated <a
* href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control">control</a>, the control will be
* cleared instead.
*/
void clear(ClearOptions options);
/**
* This method clicks the element by performing the following steps:
* <ol>
@@ -2183,7 +2308,7 @@ public interface Locator {
* assertEquals("10 retweets", tweets.evaluate("node => node.innerText"));
* }</pre>
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @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}.
*/
@@ -2205,7 +2330,7 @@ public interface Locator {
* assertEquals("10 retweets", tweets.evaluate("node => node.innerText"));
* }</pre>
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @param expression JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the function is
* automatically invoked.
*/
default Object evaluate(String expression) {
@@ -2226,7 +2351,7 @@ public interface Locator {
* assertEquals("10 retweets", tweets.evaluate("node => node.innerText"));
* }</pre>
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @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}.
*/
@@ -2245,7 +2370,7 @@ public interface Locator {
* boolean divCounts = (boolean) elements.evaluateAll("(divs, min) => divs.length >= min", 10);
* }</pre>
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @param expression JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the function is
* automatically invoked.
*/
default Object evaluateAll(String expression) {
@@ -2265,7 +2390,7 @@ public interface Locator {
* boolean divCounts = (boolean) elements.evaluateAll("(divs, min) => divs.length >= min", 10);
* }</pre>
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @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}.
*/
@@ -2284,7 +2409,7 @@ public interface Locator {
*
* <p> See {@link Page#evaluateHandle Page.evaluateHandle()} for more details.
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @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}.
*/
@@ -2305,7 +2430,7 @@ public interface Locator {
*
* <p> See {@link Page#evaluateHandle Page.evaluateHandle()} for more details.
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @param expression JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the function is
* automatically invoked.
*/
default JSHandle evaluateHandle(String expression) {
@@ -2325,7 +2450,7 @@ public interface Locator {
*
* <p> See {@link Page#evaluateHandle Page.evaluateHandle()} for more details.
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @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}.
*/
@@ -2464,7 +2589,7 @@ public interface Locator {
Locator getByAltText(Pattern text, GetByAltTextOptions options);
/**
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text Password in the following DOM:
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
*/
@@ -2473,14 +2598,14 @@ public interface Locator {
}
/**
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text Password in the following DOM:
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
*/
Locator getByLabel(String text, GetByLabelOptions options);
/**
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text Password in the following DOM:
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
*/
@@ -2489,7 +2614,7 @@ public interface Locator {
}
/**
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text Password in the following DOM:
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
*/
@@ -2566,7 +2691,34 @@ public interface Locator {
*/
Locator getByTestId(String testId);
/**
* Allows locating elements that contain given text.
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
* // Matches <span>
* page.getByText("world")
*
* // Matches first <div>
* page.getByText("Hello world")
*
* // Matches second <div>
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
*
* // Matches both <div>s
* page.getByText(Pattern.compile("Hello"))
*
* // Matches second <div>
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text content. For example,
* locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
*/
@@ -2574,13 +2726,67 @@ public interface Locator {
return getByText(text, null);
}
/**
* Allows locating elements that contain given text.
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
* // Matches <span>
* page.getByText("world")
*
* // Matches first <div>
* page.getByText("Hello world")
*
* // Matches second <div>
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
*
* // Matches both <div>s
* page.getByText(Pattern.compile("Hello"))
*
* // Matches second <div>
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text content. For example,
* locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
*/
Locator getByText(String text, GetByTextOptions options);
/**
* Allows locating elements that contain given text.
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
* // Matches <span>
* page.getByText("world")
*
* // Matches first <div>
* page.getByText("Hello world")
*
* // Matches second <div>
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
*
* // Matches both <div>s
* page.getByText(Pattern.compile("Hello"))
*
* // Matches second <div>
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text content. For example,
* locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
*/
@@ -2588,13 +2794,40 @@ public interface Locator {
return getByText(text, null);
}
/**
* Allows locating elements that contain given text.
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
* // Matches <span>
* page.getByText("world")
*
* // Matches first <div>
* page.getByText("Hello world")
*
* // Matches second <div>
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
*
* // Matches both <div>s
* page.getByText(Pattern.compile("Hello"))
*
* // Matches second <div>
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text content. For example,
* locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
*/
Locator getByText(Pattern text, GetByTextOptions options);
/**
* Allows locating elements by their title. For example, this method will find the button by its title "Submit":
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
*/
@@ -2602,13 +2835,13 @@ public interface Locator {
return getByTitle(text, null);
}
/**
* Allows locating elements by their title. For example, this method will find the button by its title "Submit":
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
*/
Locator getByTitle(String text, GetByTitleOptions options);
/**
* Allows locating elements by their title. For example, this method will find the button by its title "Submit":
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
*/
@@ -2616,7 +2849,7 @@ public interface Locator {
return getByTitle(text, null);
}
/**
* Allows locating elements by their title. For example, this method will find the button by its title "Submit":
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
*/
@@ -1145,13 +1145,13 @@ public interface Page extends AutoCloseable {
class GetByAltTextOptions {
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public Boolean exact;
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public GetByAltTextOptions setExact(boolean exact) {
this.exact = exact;
@@ -1161,13 +1161,13 @@ public interface Page extends AutoCloseable {
class GetByLabelOptions {
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public Boolean exact;
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public GetByLabelOptions setExact(boolean exact) {
this.exact = exact;
@@ -1177,13 +1177,13 @@ public interface Page extends AutoCloseable {
class GetByPlaceholderOptions {
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public Boolean exact;
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public GetByPlaceholderOptions setExact(boolean exact) {
this.exact = exact;
@@ -1192,27 +1192,31 @@ public interface Page extends AutoCloseable {
}
class GetByRoleOptions {
/**
* An attribute that is usually set by {@code aria-checked} or native {@code <input type=checkbox>} controls. Available values for
* checked are {@code true}, {@code false} and {@code "mixed"}.
* An attribute that is usually set by {@code aria-checked} or native {@code <input type=checkbox>} controls.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-checked">{@code aria-checked}</a>.
*/
public Boolean checked;
/**
* A boolean attribute that is usually set by {@code aria-disabled} or {@code disabled}.
* An attribute that is usually set by {@code aria-disabled} or {@code disabled}.
*
* <p> <strong>NOTE:</strong> Unlike most other attributes, {@code disabled} is inherited through the DOM hierarchy. Learn more about <a
* href="https://www.w3.org/TR/wai-aria-1.2/#aria-disabled">{@code aria-disabled}</a>.
*/
public Boolean disabled;
/**
* A boolean attribute that is usually set by {@code aria-expanded}.
* Whether {@code name} is matched exactly: case-sensitive and whole-string. Defaults to false. Ignored when {@code name} is a regular
* expression. Note that exact match still trims whitespace.
*/
public Boolean exact;
/**
* An attribute that is usually set by {@code aria-expanded}.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-expanded">{@code aria-expanded}</a>.
*/
public Boolean expanded;
/**
* A boolean attribute that controls whether hidden elements are matched. By default, only non-hidden elements, as <a
* Option that controls whether hidden elements are matched. By default, only non-hidden elements, as <a
* href="https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion">defined by ARIA</a>, are matched by role selector.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-hidden">{@code aria-hidden}</a>.
@@ -1226,27 +1230,27 @@ public interface Page extends AutoCloseable {
*/
public Integer level;
/**
* A string attribute that matches <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
* Option to match the <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>. By default,
* matching is case-insensitive and searches for a substring, use {@code exact} to control this behavior.
*
* <p> Learn more about <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
*/
public Object name;
/**
* An attribute that is usually set by {@code aria-pressed}. Available values for pressed are {@code true}, {@code false} and {@code "mixed"}.
* An attribute that is usually set by {@code aria-pressed}.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-pressed">{@code aria-pressed}</a>.
*/
public Boolean pressed;
/**
* A boolean attribute that is usually set by {@code aria-selected}.
* An attribute that is usually set by {@code aria-selected}.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-selected">{@code aria-selected}</a>.
*/
public Boolean selected;
/**
* An attribute that is usually set by {@code aria-checked} or native {@code <input type=checkbox>} controls. Available values for
* checked are {@code true}, {@code false} and {@code "mixed"}.
* An attribute that is usually set by {@code aria-checked} or native {@code <input type=checkbox>} controls.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-checked">{@code aria-checked}</a>.
*/
@@ -1255,7 +1259,7 @@ public interface Page extends AutoCloseable {
return this;
}
/**
* A boolean attribute that is usually set by {@code aria-disabled} or {@code disabled}.
* An attribute that is usually set by {@code aria-disabled} or {@code disabled}.
*
* <p> <strong>NOTE:</strong> Unlike most other attributes, {@code disabled} is inherited through the DOM hierarchy. Learn more about <a
* href="https://www.w3.org/TR/wai-aria-1.2/#aria-disabled">{@code aria-disabled}</a>.
@@ -1265,7 +1269,15 @@ public interface Page extends AutoCloseable {
return this;
}
/**
* A boolean attribute that is usually set by {@code aria-expanded}.
* Whether {@code name} is matched exactly: case-sensitive and whole-string. Defaults to false. Ignored when {@code name} is a regular
* expression. Note that exact match still trims whitespace.
*/
public GetByRoleOptions setExact(boolean exact) {
this.exact = exact;
return this;
}
/**
* An attribute that is usually set by {@code aria-expanded}.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-expanded">{@code aria-expanded}</a>.
*/
@@ -1274,7 +1286,7 @@ public interface Page extends AutoCloseable {
return this;
}
/**
* A boolean attribute that controls whether hidden elements are matched. By default, only non-hidden elements, as <a
* Option that controls whether hidden elements are matched. By default, only non-hidden elements, as <a
* href="https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion">defined by ARIA</a>, are matched by role selector.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-hidden">{@code aria-hidden}</a>.
@@ -1294,7 +1306,8 @@ public interface Page extends AutoCloseable {
return this;
}
/**
* A string attribute that matches <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
* Option to match the <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>. By default,
* matching is case-insensitive and searches for a substring, use {@code exact} to control this behavior.
*
* <p> Learn more about <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
*/
@@ -1303,7 +1316,8 @@ public interface Page extends AutoCloseable {
return this;
}
/**
* A string attribute that matches <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
* Option to match the <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>. By default,
* matching is case-insensitive and searches for a substring, use {@code exact} to control this behavior.
*
* <p> Learn more about <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
*/
@@ -1312,7 +1326,7 @@ public interface Page extends AutoCloseable {
return this;
}
/**
* An attribute that is usually set by {@code aria-pressed}. Available values for pressed are {@code true}, {@code false} and {@code "mixed"}.
* An attribute that is usually set by {@code aria-pressed}.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-pressed">{@code aria-pressed}</a>.
*/
@@ -1321,7 +1335,7 @@ public interface Page extends AutoCloseable {
return this;
}
/**
* A boolean attribute that is usually set by {@code aria-selected}.
* An attribute that is usually set by {@code aria-selected}.
*
* <p> Learn more about <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-selected">{@code aria-selected}</a>.
*/
@@ -1333,13 +1347,13 @@ public interface Page extends AutoCloseable {
class GetByTextOptions {
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public Boolean exact;
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public GetByTextOptions setExact(boolean exact) {
this.exact = exact;
@@ -1349,13 +1363,13 @@ public interface Page extends AutoCloseable {
class GetByTitleOptions {
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public Boolean exact;
/**
* Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular
* expression.
* expression. Note that exact match still trims whitespace.
*/
public GetByTitleOptions setExact(boolean exact) {
this.exact = exact;
@@ -1515,6 +1529,12 @@ public interface Page extends AutoCloseable {
* modifiers back. If not specified, currently pressed modifiers are used.
*/
public List<KeyboardModifier> modifiers;
/**
* Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can
* opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to
* inaccessible pages. Defaults to {@code false}.
*/
public Boolean noWaitAfter;
/**
* A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of the
* element.
@@ -1554,6 +1574,15 @@ public interface Page extends AutoCloseable {
this.modifiers = modifiers;
return this;
}
/**
* Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can
* opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to
* inaccessible pages. Defaults to {@code false}.
*/
public HoverOptions setNoWaitAfter(boolean noWaitAfter) {
this.noWaitAfter = noWaitAfter;
return this;
}
/**
* A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of the
* element.
@@ -2222,7 +2251,8 @@ public interface Page extends AutoCloseable {
*/
public HarNotFound notFound;
/**
* If specified, updates the given HAR with the actual network information instead of serving from file.
* If specified, updates the given HAR with the actual network information instead of serving from file. The file is
* written to disk when {@link BrowserContext#close BrowserContext.close()} is called.
*/
public Boolean update;
/**
@@ -2244,7 +2274,8 @@ public interface Page extends AutoCloseable {
return this;
}
/**
* If specified, updates the given HAR with the actual network information instead of serving from file.
* If specified, updates the given HAR with the actual network information instead of serving from file. The file is
* written to disk when {@link BrowserContext#close BrowserContext.close()} is called.
*/
public RouteFromHAROptions setUpdate(boolean update) {
this.update = update;
@@ -2315,7 +2346,7 @@ public interface Page extends AutoCloseable {
public Integer quality;
/**
* When set to {@code "css"}, screenshot will have a single pixel per each css pixel on the page. For high-dpi devices, this will
* keep screenshots small. Using {@code "device"} option will produce a single pixel per each device pixel, so screenhots of
* keep screenshots small. Using {@code "device"} option will produce a single pixel per each device pixel, so screenshots of
* high-dpi devices will be twice as large or even larger.
*
* <p> Defaults to {@code "device"}.
@@ -2409,7 +2440,7 @@ public interface Page extends AutoCloseable {
}
/**
* When set to {@code "css"}, screenshot will have a single pixel per each css pixel on the page. For high-dpi devices, this will
* keep screenshots small. Using {@code "device"} option will produce a single pixel per each device pixel, so screenhots of
* keep screenshots small. Using {@code "device"} option will produce a single pixel per each device pixel, so screenshots of
* high-dpi devices will be twice as large or even larger.
*
* <p> Defaults to {@code "device"}.
@@ -3917,7 +3948,7 @@ public interface Page extends AutoCloseable {
*
* @param selector A selector to query for. See <a href="https://playwright.dev/java/docs/selectors">working with selectors</a> for more
* details.
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @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}.
*/
@@ -3946,7 +3977,7 @@ public interface Page extends AutoCloseable {
*
* @param selector A selector to query for. See <a href="https://playwright.dev/java/docs/selectors">working with selectors</a> for more
* details.
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @param expression JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the function is
* automatically invoked.
*/
default Object evalOnSelector(String selector, String expression) {
@@ -3974,7 +4005,7 @@ public interface Page extends AutoCloseable {
*
* @param selector A selector to query for. See <a href="https://playwright.dev/java/docs/selectors">working with selectors</a> for more
* details.
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @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}.
*/
@@ -3997,7 +4028,7 @@ public interface Page extends AutoCloseable {
*
* @param selector A selector to query for. See <a href="https://playwright.dev/java/docs/selectors">working with selectors</a> for more
* details.
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @param expression JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the function is
* automatically invoked.
*/
default Object evalOnSelectorAll(String selector, String expression) {
@@ -4021,7 +4052,7 @@ public interface Page extends AutoCloseable {
*
* @param selector A selector to query for. See <a href="https://playwright.dev/java/docs/selectors">working with selectors</a> for more
* details.
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @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}.
*/
@@ -4059,7 +4090,7 @@ public interface Page extends AutoCloseable {
*
* <p> Shortcut for main frame's {@link Frame#evaluate Frame.evaluate()}.
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @param expression JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the function is
* automatically invoked.
*/
default Object evaluate(String expression) {
@@ -4098,7 +4129,7 @@ public interface Page extends AutoCloseable {
*
* <p> Shortcut for main frame's {@link Frame#evaluate Frame.evaluate()}.
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @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}.
*/
@@ -4130,7 +4161,7 @@ public interface Page extends AutoCloseable {
* resultHandle.dispose();
* }</pre>
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @param expression JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the function is
* automatically invoked.
*/
default JSHandle evaluateHandle(String expression) {
@@ -4163,7 +4194,7 @@ public interface Page extends AutoCloseable {
* resultHandle.dispose();
* }</pre>
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @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}.
*/
@@ -4502,7 +4533,7 @@ public interface Page extends AutoCloseable {
Locator getByAltText(Pattern text, GetByAltTextOptions options);
/**
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text Password in the following DOM:
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
*/
@@ -4511,14 +4542,14 @@ public interface Page extends AutoCloseable {
}
/**
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text Password in the following DOM:
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
*/
Locator getByLabel(String text, GetByLabelOptions options);
/**
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text Password in the following DOM:
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
*/
@@ -4527,7 +4558,7 @@ public interface Page extends AutoCloseable {
}
/**
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text Password in the following DOM:
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
*/
@@ -4604,7 +4635,34 @@ public interface Page extends AutoCloseable {
*/
Locator getByTestId(String testId);
/**
* Allows locating elements that contain given text.
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
* // Matches <span>
* page.getByText("world")
*
* // Matches first <div>
* page.getByText("Hello world")
*
* // Matches second <div>
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
*
* // Matches both <div>s
* page.getByText(Pattern.compile("Hello"))
*
* // Matches second <div>
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text content. For example,
* locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
*/
@@ -4612,13 +4670,67 @@ public interface Page extends AutoCloseable {
return getByText(text, null);
}
/**
* Allows locating elements that contain given text.
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
* // Matches <span>
* page.getByText("world")
*
* // Matches first <div>
* page.getByText("Hello world")
*
* // Matches second <div>
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
*
* // Matches both <div>s
* page.getByText(Pattern.compile("Hello"))
*
* // Matches second <div>
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text content. For example,
* locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
*/
Locator getByText(String text, GetByTextOptions options);
/**
* Allows locating elements that contain given text.
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
* // Matches <span>
* page.getByText("world")
*
* // Matches first <div>
* page.getByText("Hello world")
*
* // Matches second <div>
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
*
* // Matches both <div>s
* page.getByText(Pattern.compile("Hello"))
*
* // Matches second <div>
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text content. For example,
* locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
*/
@@ -4626,13 +4738,40 @@ public interface Page extends AutoCloseable {
return getByText(text, null);
}
/**
* Allows locating elements that contain given text.
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
* // Matches <span>
* page.getByText("world")
*
* // Matches first <div>
* page.getByText("Hello world")
*
* // Matches second <div>
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
*
* // Matches both <div>s
* page.getByText(Pattern.compile("Hello"))
*
* // Matches second <div>
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text content. For example,
* locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
*/
Locator getByText(Pattern text, GetByTextOptions options);
/**
* Allows locating elements by their title. For example, this method will find the button by its title "Submit":
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
*/
@@ -4640,13 +4779,13 @@ public interface Page extends AutoCloseable {
return getByTitle(text, null);
}
/**
* Allows locating elements by their title. For example, this method will find the button by its title "Submit":
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
*/
Locator getByTitle(String text, GetByTitleOptions options);
/**
* Allows locating elements by their title. For example, this method will find the button by its title "Submit":
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
*/
@@ -4654,7 +4793,7 @@ public interface Page extends AutoCloseable {
return getByTitle(text, null);
}
/**
* Allows locating elements by their title. For example, this method will find the button by its title "Submit":
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
*/
@@ -6523,7 +6662,7 @@ public interface Page extends AutoCloseable {
*
* <p> Shortcut for main frame's {@link Frame#waitForFunction Frame.waitForFunction()}.
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @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}.
*/
@@ -6559,7 +6698,7 @@ public interface Page extends AutoCloseable {
*
* <p> Shortcut for main frame's {@link Frame#waitForFunction Frame.waitForFunction()}.
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @param expression JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the function is
* automatically invoked.
*/
default JSHandle waitForFunction(String expression) {
@@ -6594,7 +6733,7 @@ public interface Page extends AutoCloseable {
*
* <p> Shortcut for main frame's {@link Frame#waitForFunction Frame.waitForFunction()}.
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @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}.
*/
@@ -34,7 +34,7 @@ import java.util.*;
* <p> <strong>NOTE:</strong> HTTP Error responses, such as 404 or 503, are still successful responses from HTTP standpoint, so request will complete
* with {@code "requestfinished"} event.
*
* <p> If request gets a 'redirect' response, the request is successfully finished with the 'requestfinished' event, and a new
* <p> If request gets a 'redirect' response, the request is successfully finished with the {@code requestfinished} event, and a new
* request is issued to a redirected url.
*/
public interface Request {
@@ -71,7 +71,7 @@ public interface Worker {
* Worker#evaluate Worker.evaluate()} returns {@code undefined}. Playwright also supports transferring some additional values
* that are not serializable by {@code JSON}: {@code -0}, {@code NaN}, {@code Infinity}, {@code -Infinity}.
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @param expression JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the function is
* automatically invoked.
*/
default Object evaluate(String expression) {
@@ -88,7 +88,7 @@ public interface Worker {
* Worker#evaluate Worker.evaluate()} returns {@code undefined}. Playwright also supports transferring some additional values
* that are not serializable by {@code JSON}: {@code -0}, {@code NaN}, {@code Infinity}, {@code -Infinity}.
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @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}.
*/
@@ -103,7 +103,7 @@ public interface Worker {
* href='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise'>Promise</a>, then {@link
* Worker#evaluateHandle Worker.evaluateHandle()} would wait for the promise to resolve and return its value.
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @param expression JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the function is
* automatically invoked.
*/
default JSHandle evaluateHandle(String expression) {
@@ -119,7 +119,7 @@ public interface Worker {
* href='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise'>Promise</a>, then {@link
* Worker#evaluateHandle Worker.evaluateHandle()} would wait for the promise to resolve and return its value.
*
* @param expression JavaScript expression to be evaluated in the browser context. If the expresion evaluates to a function, the function is
* @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}.
*/
@@ -26,7 +26,6 @@ import java.nio.file.Path;
import static com.microsoft.playwright.impl.Utils.writeToFile;
class ArtifactImpl extends ChannelOwner {
boolean isRemote;
public ArtifactImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
super(parent, type, guid, initializer);
}
@@ -57,7 +56,7 @@ class ArtifactImpl extends ChannelOwner {
}
public Path pathAfterFinished() {
if (isRemote) {
if (connection.isRemote) {
throw new PlaywrightException("Path is not available when using browserType.connect(). Use download.saveAs() to save a local copy.");
}
JsonObject json = sendMessage("pathAfterFinished").getAsJsonObject();
@@ -65,7 +64,7 @@ class ArtifactImpl extends ChannelOwner {
}
public void saveAs(Path path) {
if (isRemote) {
if (connection.isRemote) {
JsonObject jsonObject = sendMessage("saveAsStream").getAsJsonObject();
Stream stream = connection.getExistingObject(jsonObject.getAsJsonObject("stream").get("guid").getAsString());
writeToFile(stream.stream(), path);
@@ -49,7 +49,15 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
private boolean isClosedOrClosing;
final Map<String, BindingCallback> bindings = new HashMap<>();
PageImpl ownerPage;
private final ListenerCollection<EventType> listeners = new ListenerCollection<>();
private static final Map<EventType, String> eventSubscriptions() {
Map<EventType, String> result = new HashMap<>();
result.put(EventType.REQUEST, "request");
result.put(EventType.RESPONSE, "response");
result.put(EventType.REQUESTFINISHED, "requestFinished");
result.put(EventType.REQUESTFAILED, "requestFailed");
return result;
}
private final ListenerCollection<EventType> listeners = new ListenerCollection<>(eventSubscriptions(), this);
final TimeoutSettings timeoutSettings = new TimeoutSettings();
Path videosDir;
URL baseUrl;
@@ -82,7 +90,6 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
browser = null;
}
this.tracing = connection.getExistingObject(initializer.getAsJsonObject("tracing").get("guid").getAsString());
tracing.isRemote = browser != null && browser.isRemote;
this.request = connection.getExistingObject(initializer.getAsJsonObject("requestContext").get("guid").getAsString());
}
@@ -201,12 +208,6 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
params.addProperty("harId", entry.getKey());
JsonObject json = sendMessage("harExport", params).getAsJsonObject();
ArtifactImpl artifact = connection.getExistingObject(json.getAsJsonObject("artifact").get("guid").getAsString());
// In case of CDP connection browser is null but since the connection is established by
// the driver it is safe to consider the artifact local.
if (browser() != null && browser().isRemote) {
artifact.isRemote = true;
}
// Server side will compress artifact if content is attach or if file is .zip.
HarRecorder harParams = entry.getValue();
boolean isCompressed = harParams.contentPolicy == HarContentPolicy.ATTACH || harParams.path.toString().endsWith(".zip");
@@ -38,7 +38,6 @@ import static com.microsoft.playwright.impl.Utils.convertType;
class BrowserImpl extends ChannelOwner implements Browser {
final Set<BrowserContextImpl> contexts = new HashSet<>();
private final ListenerCollection<EventType> listeners = new ListenerCollection<>();
boolean isRemote;
boolean isConnectedOverWebSocket;
private boolean isConnected = true;
BrowserTypeImpl browserType;
@@ -97,7 +97,6 @@ class BrowserTypeImpl extends ChannelOwner implements BrowserType {
}
playwright.initSharedSelectors(this.connection.getExistingObject("Playwright"));
BrowserImpl browser = connection.getExistingObject(playwright.initializer.getAsJsonObject("preLaunchedBrowser").get("guid").getAsString());
browser.isRemote = true;
browser.isConnectedOverWebSocket = true;
browser.browserType = this;
Consumer<JsonPipe> connectionCloseListener = t -> browser.notifyRemoteClosed();
@@ -132,7 +131,6 @@ class BrowserTypeImpl extends ChannelOwner implements BrowserType {
JsonObject json = sendMessage("connectOverCDP", params).getAsJsonObject();
BrowserImpl browser = connection.getExistingObject(json.getAsJsonObject("browser").get("guid").getAsString());
browser.isRemote = true;
browser.browserType = this;
if (json.has("defaultContext")) {
String contextId = json.getAsJsonObject("defaultContext").get("guid").getAsString();
@@ -55,6 +55,7 @@ public class Connection {
private final Transport transport;
private final Map<String, ChannelOwner> objects = new HashMap<>();
private final Root root;
final boolean isRemote;
private int lastId = 0;
private final StackTraceCollector stackTraceCollector;
private final Map<Integer, WaitableResult<JsonElement>> callbacks = new HashMap<>();
@@ -81,12 +82,17 @@ public class Connection {
}
Connection(Transport pipe, Map<String, String> env, LocalUtils localUtils) {
this(pipe, env);
this(pipe, env, true);
this.localUtils = localUtils;
}
Connection(Transport transport, Map<String, String> env) {
this(transport, env, false);
}
private Connection(Transport transport, Map<String, String> env, boolean isRemote) {
this.env = env;
this.isRemote = isRemote;
if (isLogging) {
transport = new TransportLogger(transport);
}
@@ -16,14 +16,23 @@
package com.microsoft.playwright.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import com.google.gson.JsonObject;
import java.util.*;
import java.util.function.Consumer;
class ListenerCollection <EventType> {
private final HashMap<EventType, List<Consumer<?>>> listeners = new HashMap<>();
private final Map<EventType, String> eventSubscriptions;
private final ChannelOwner channelOwner;
ListenerCollection() {
this(null, null);
}
ListenerCollection(Map<EventType, String> eventSubscriptions, ChannelOwner channelOwner) {
this.eventSubscriptions = eventSubscriptions;
this.channelOwner = channelOwner;
}
<T> void notify(EventType eventType, T param) {
List<Consumer<?>> list = listeners.get(eventType);
@@ -41,6 +50,7 @@ class ListenerCollection <EventType> {
if (list == null) {
list = new ArrayList<>();
listeners.put(type, list);
updateSubscription(type, true);
}
list.add(listener);
}
@@ -52,6 +62,7 @@ class ListenerCollection <EventType> {
}
list.removeAll(Collections.singleton(listener));
if (list.isEmpty()) {
updateSubscription(type, false);
listeners.remove(type);
}
}
@@ -59,4 +70,18 @@ class ListenerCollection <EventType> {
boolean hasListeners(EventType type) {
return listeners.containsKey(type);
}
private void updateSubscription(EventType eventType, boolean enabled) {
if (eventSubscriptions == null) {
return;
}
String protocolEvent = eventSubscriptions.get(eventType);
if (protocolEvent == null) {
return;
}
JsonObject params = new JsonObject();
params.addProperty("event", protocolEvent);
params.addProperty("enabled", enabled);
channelOwner.sendMessageAsync("updateSubscription", params);
}
}
@@ -26,8 +26,7 @@ class LocatorImpl implements Locator {
this.frame = frame;
if (options != null) {
if (options.hasText != null) {
String textSelector = "text=" + escapeForTextSelector(options.hasText, false);
selector += " >> internal:has=" + gson().toJson(textSelector);
selector += " >> internal:has-text=" + escapeForTextSelector(options.hasText, false);
}
if (options.has != null) {
LocatorImpl locator = (LocatorImpl) options.has;
@@ -72,6 +71,21 @@ class LocatorImpl implements Locator {
return (List<String>) frame.evalOnSelectorAll(selector, "ee => ee.map(e => e.textContent || '')");
}
@Override
public void blur(BlurOptions options) {
frame.withLogging("Locator.blur", () -> blurImpl(options));
}
private void blurImpl(BlurOptions options) {
if (options == null) {
options = new BlurOptions();
}
JsonObject params = gson().toJsonTree(options).getAsJsonObject();
params.addProperty("selector", selector);
params.addProperty("strict", true);
frame.sendMessage("blur", params);
}
@Override
public BoundingBox boundingBox(BoundingBoxOptions options) {
return withElement((h, o) -> h.boundingBox(), options);
@@ -85,6 +99,11 @@ class LocatorImpl implements Locator {
frame.check(selector, convertType(options, Frame.CheckOptions.class).setStrict(true));
}
@Override
public void clear(ClearOptions options) {
fill("", convertType(options, FillOptions.class));
}
@Override
public void click(ClickOptions options) {
if (options == null) {
@@ -226,7 +245,7 @@ class LocatorImpl implements Locator {
@Override
public Locator getByRole(AriaRole role, GetByRoleOptions options) {
return null;
return locator(getByRoleSelector(role, options));
}
@Override
@@ -14,14 +14,9 @@ public class LocatorUtils {
testIdAttributeName = name;
}
static String getByTextSelector(String text, Locator.GetByTextOptions options) {
static String getByTextSelector(Object text, Locator.GetByTextOptions options) {
boolean exact = options != null && options.exact != null && options.exact;
return "text=" + escapeForTextSelector(text, exact);
}
static String getByTextSelector(Pattern text, Locator.GetByTextOptions options) {
boolean exact = options != null && options.exact != null && options.exact;
return "text=" + escapeForTextSelector(text, exact);
return "internal:text=" + escapeForTextSelector(text, exact);
}
static String getByLabelSelector(Object text, Locator.GetByLabelOptions options) {
@@ -61,7 +56,7 @@ public class LocatorUtils {
static String getByRoleSelector(AriaRole role, Locator.GetByRoleOptions options) {
StringBuilder result = new StringBuilder();
result.append("role=").append(role.name().toLowerCase());
result.append("internal:role=").append(role.name().toLowerCase());
if (options != null) {
if (options.checked != null)
addAttr(result, "checked", options.checked.toString());
@@ -78,7 +73,7 @@ public class LocatorUtils {
if (options.name != null) {
String name;
if (options.name instanceof String) {
name = escapeForAttributeSelector((String) options.name, false);
name = escapeForAttributeSelector((String) options.name, options.exact != null && options.exact);
} else if (options.name instanceof Pattern) {
name = toJsRegExp((Pattern) options.name);
} else {
@@ -48,23 +48,16 @@ public class PageImpl extends ChannelOwner implements Page {
private ViewportSize viewport;
private final Router routes = new Router();
private final Set<FrameImpl> frames = new LinkedHashSet<>();
final ListenerCollection<EventType> listeners = new ListenerCollection<EventType>() {
@Override
void add(EventType eventType, Consumer<?> listener) {
if (eventType == EventType.FILECHOOSER) {
willAddFileChooserListener();
}
super.add(eventType, listener);
}
@Override
void remove(EventType eventType, Consumer<?> listener) {
super.remove(eventType, listener);
if (eventType == EventType.FILECHOOSER) {
didRemoveFileChooserListener();
}
}
};
private static final Map<EventType, String> eventSubscriptions() {
Map<EventType, String> result = new HashMap<>();
result.put(EventType.REQUEST, "request");
result.put(EventType.RESPONSE, "response");
result.put(EventType.REQUESTFINISHED, "requestFinished");
result.put(EventType.REQUESTFAILED, "requestFailed");
result.put(EventType.FILECHOOSER, "fileChooser");
return result;
}
final ListenerCollection<EventType> listeners = new ListenerCollection<EventType>(eventSubscriptions(), this);
final Map<String, BindingCallback> bindings = new HashMap<>();
BrowserContextImpl ownedContext;
private boolean isClosed;
@@ -151,7 +144,6 @@ public class PageImpl extends ChannelOwner implements Page {
} else if ("download".equals(event)) {
String artifactGuid = params.getAsJsonObject("artifact").get("guid").getAsString();
ArtifactImpl artifact = connection.getExistingObject(artifactGuid);
artifact.isRemote = browserContext.browser() != null && browserContext.browser().isRemote;
DownloadImpl download = new DownloadImpl(this, artifact, params);
listeners.notify(EventType.DOWNLOAD, download);
} else if ("fileChooser".equals(event)) {
@@ -233,24 +225,6 @@ public class PageImpl extends ChannelOwner implements Page {
listeners.notify(EventType.CLOSE, this);
}
private void willAddFileChooserListener() {
if (!listeners.hasListeners(EventType.FILECHOOSER)) {
updateFileChooserInterception(true);
}
}
private void didRemoveFileChooserListener() {
if (!listeners.hasListeners(EventType.FILECHOOSER)) {
updateFileChooserInterception(false);
}
}
private void updateFileChooserInterception(boolean enabled) {
JsonObject params = new JsonObject();
params.addProperty("intercepted", enabled);
sendMessage("setFileChooserInterceptedNoReply", params);
}
@Override
public void onClose(Consumer<Page> handler) {
listeners.add(EventType.CLOSE, handler);
@@ -378,7 +378,7 @@ class Serialization {
public JsonElement serialize(Optional<?> src, Type typeOfSrc, JsonSerializationContext context) {
assert isSupported(typeOfSrc) : "Unexpected optional type: " + typeOfSrc.getTypeName();
if (!src.isPresent()) {
return new JsonPrimitive("null");
return new JsonPrimitive("no-override");
}
return context.serialize(src.get());
}
@@ -69,7 +69,13 @@ class StackTraceCollector {
if (file == null) {
return "";
}
return resolveSourcePath(Paths.get(pkg).resolve(file));
try {
// The file name can contain an arbitrary string which may cause Path implementation
// to throw. See https://github.com/microsoft/playwright-java/issues/1115
return resolveSourcePath(Paths.get(pkg).resolve(file));
} catch (RuntimeException e) {
return "";
}
}
private String resolveSourcePath(Path relativePath) {
@@ -26,8 +26,6 @@ import java.nio.file.Path;
import static com.microsoft.playwright.impl.Serialization.gson;
class TracingImpl extends ChannelOwner implements Tracing {
boolean isRemote;
TracingImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
super(parent, type, guid, initializer);
}
@@ -36,7 +34,7 @@ class TracingImpl extends ChannelOwner implements Tracing {
JsonObject params = new JsonObject();
String mode = "doNotSave";
if (path != null) {
if (isRemote) {
if (connection.isRemote) {
mode = "compressTrace";
} else {
mode = "compressTraceAndSources";
@@ -48,16 +46,13 @@ class TracingImpl extends ChannelOwner implements Tracing {
return;
}
ArtifactImpl artifact = connection.getExistingObject(json.getAsJsonObject("artifact").get("guid").getAsString());
// In case of CDP connection browser is null but since the connection is established by
// the driver it is safe to consider the artifact local.
if (isRemote) {
artifact.isRemote = true;
}
artifact.saveAs(path);
artifact.delete();
// Add local sources to the remote trace if necessary.
if (isRemote && json.has("sourceEntries")) {
// In case of CDP connection since the connection is established by
// the driver it is safe to consider the artifact local.
if (connection.isRemote && json.has("sourceEntries")) {
JsonArray entries = json.getAsJsonArray("sourceEntries");
connection.localUtils.zip(path, entries);
}
@@ -165,7 +165,7 @@ class Utils {
}
static void addLargeFileUploadParams(Path[] files, JsonObject params, BrowserContextImpl context) {
if (context.browser().isRemote) {
if (context.connection.isRemote) {
List<WritableStream> streams = new ArrayList<>();
JsonArray jsonStreams = new JsonArray();
for (Path path : files) {
@@ -27,16 +27,13 @@ import static java.util.Arrays.asList;
class VideoImpl implements Video {
private final PageImpl page;
private final WaitableResult<ArtifactImpl> waitableArtifact = new WaitableResult<>();
private final boolean isRemote;
VideoImpl(PageImpl page) {
this.page = page;
BrowserImpl browser = page.context().browser();
isRemote = browser != null && browser.isRemote;
}
void setArtifact(ArtifactImpl artifact) {
artifact.isRemote = isRemote;
waitableArtifact.complete(artifact);
}
@@ -58,7 +55,7 @@ class VideoImpl implements Video {
@Override
public Path path() {
return page.withLogging("Video.path", () -> {
if (isRemote) {
if (page.connection.isRemote) {
throw new PlaywrightException("Path is not available when using browserType.connect(). Use saveAs() to save a local copy.");
}
try {
@@ -98,5 +98,5 @@ public enum AriaRole {
TOOLTIP,
TREE,
TREEGRID,
TREEITE
TREEITEM
}
@@ -2,13 +2,19 @@ package com.microsoft.playwright;
import com.microsoft.playwright.options.Geolocation;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIf;
import org.junit.jupiter.api.io.TempDir;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.stream.Collectors;
@@ -22,6 +28,7 @@ public class TestDefaultBrowserContext2 extends TestBase {
private BrowserContext persistentContext;
@TempDir Path tempDir;
@AfterEach
private void closePersistentContext() {
@@ -36,12 +43,7 @@ public class TestDefaultBrowserContext2 extends TestBase {
}
private Page launchPersistent(BrowserType.LaunchPersistentContextOptions options) {
Path userDataDir = null;
try {
userDataDir = Files.createTempDirectory("user-data-dir-");
} catch (IOException e) {
throw new RuntimeException(e);
}
Path userDataDir = tempDir.resolve("user-data-dir");
assertNull(persistentContext);
persistentContext = browserType.launchPersistentContext(userDataDir, options);
return persistentContext.pages().get(0);
@@ -118,7 +120,7 @@ public class TestDefaultBrowserContext2 extends TestBase {
@Test
void shouldAcceptUserDataDir() throws IOException {
// TODO: test.flaky(browserName === "chromium");
Path userDataDir = Files.createTempDirectory("user-data-dir-");
Path userDataDir = tempDir.resolve("user-data-dir");
BrowserContext context = browserType.launchPersistentContext(userDataDir);
assertTrue(userDataDir.toFile().listFiles().length > 0);
context.close();
@@ -128,7 +130,7 @@ public class TestDefaultBrowserContext2 extends TestBase {
@Test
void shouldRestoreStateFromUserDataDir() throws IOException {
// TODO: test.slow();
Path userDataDir = Files.createTempDirectory("user-data-dir-");
Path userDataDir = tempDir.resolve("user-data-dir");
BrowserType.LaunchPersistentContextOptions browserOptions = null;
BrowserContext browserContext = browserType.launchPersistentContext(userDataDir, browserOptions);
Page page = browserContext.newPage();
@@ -142,7 +144,7 @@ public class TestDefaultBrowserContext2 extends TestBase {
assertEquals("hello", page2.evaluate("localStorage.hey"));
browserContext2.close();
Path userDataDir2 = Files.createTempDirectory("user-data-dir-");
Path userDataDir2 = tempDir.resolve("user-data-dir-2");
BrowserContext browserContext3 = browserType.launchPersistentContext(userDataDir2, browserOptions);
Page page3 = browserContext3.newPage();
page3.navigate(server.EMPTY_PAGE);
@@ -153,7 +155,7 @@ public class TestDefaultBrowserContext2 extends TestBase {
@Test
void shouldRestoreCookiesFromUserDataDir() throws IOException {
// TODO: test.flaky(browserName === "chromium");
Path userDataDir = Files.createTempDirectory("user-data-dir-");
Path userDataDir = tempDir.resolve("user-data-dir");
BrowserType.LaunchPersistentContextOptions browserOptions = null;
BrowserContext browserContext = browserType.launchPersistentContext(userDataDir, browserOptions);
Page page = browserContext.newPage();
@@ -171,7 +173,7 @@ public class TestDefaultBrowserContext2 extends TestBase {
assertEquals("doSomethingOnlyOnce=true", page2.evaluate("() => document.cookie"));
browserContext2.close();
Path userDataDir2 = Files.createTempDirectory("user-data-dir-");
Path userDataDir2 = tempDir.resolve("user-data-dir-2");
BrowserContext browserContext3 = browserType.launchPersistentContext(userDataDir2, browserOptions);
Page page3 = browserContext3.newPage();
page3.navigate(server.EMPTY_PAGE);
@@ -191,7 +193,7 @@ public class TestDefaultBrowserContext2 extends TestBase {
void shouldThrowIfPageArgumentIsPassed() throws IOException {
BrowserType.LaunchPersistentContextOptions options = new BrowserType.LaunchPersistentContextOptions()
.setArgs(asList(server.EMPTY_PAGE));
Path userDataDir = Files.createTempDirectory("user-data-dir-");
Path userDataDir = tempDir.resolve("user-data-dir");
PlaywrightException e = assertThrows(PlaywrightException.class, () -> {
browserType.launchPersistentContext(userDataDir, options);
});
@@ -254,4 +256,43 @@ public class TestDefaultBrowserContext2 extends TestBase {
assertEquals("hello", page.innerHTML("defaultContextCSS=div"));
}
}
@Test
void shouldUploadLargeFile(@TempDir Path tmpDir) throws IOException, ExecutionException, InterruptedException {
Assumptions.assumeTrue(3 <= (Runtime.getRuntime().maxMemory() >> 30), "Fails if max heap size is < 3Gb");
Page page = launchPersistent();
page.navigate(server.PREFIX + "/input/fileupload.html");
Path uploadFile = tmpDir.resolve("200MB.zip");
String str = String.join("", Collections.nCopies(4 * 1024, "A"));
try (Writer stream = new OutputStreamWriter(Files.newOutputStream(uploadFile))) {
for (int i = 0; i < 50 * 1024; i++) {
stream.write(str);
}
}
Locator input = page.locator("input[type='file']");
JSHandle events = input.evaluateHandle("e => {\n" +
" const events = [];\n" +
" e.addEventListener('input', () => events.push('input'));\n" +
" e.addEventListener('change', () => events.push('change'));\n" +
" return events;\n" +
" }");
input.setInputFiles(uploadFile);
assertEquals("200MB.zip", input.evaluate("e => e.files[0].name"));
assertEquals(asList("input", "change"), events.evaluate("e => e"));
CompletableFuture<MultipartFormData> formData = new CompletableFuture<>();
server.setRoute("/upload", exchange -> {
try {
MultipartFormData multipartFormData = MultipartFormData.parseRequest(exchange);
formData.complete(multipartFormData);
} catch (Exception e) {
e.printStackTrace();
formData.completeExceptionally(e);
}
exchange.sendResponseHeaders(200, -1);
});
page.click("input[type=submit]", new Page.ClickOptions().setTimeout(90_000));
List<MultipartFormData.Field> fields = formData.get().fields;
assertEquals(1, fields.size());
assertEquals("200MB.zip", fields.get(0).filename);
assertEquals(200 * 1024 * 1024, fields.get(0).content.length());
}}
@@ -104,7 +104,7 @@ public class TestLocatorFrame extends TestBase {
PlaywrightException e = assertThrows(PlaywrightException.class, () -> {
page.frameLocator("iframe").locator("span").click(new Locator.ClickOptions().setTimeout(300));
});
assertTrue(e.getMessage().contains("waiting for frame \"iframe\""), e.getMessage());
assertTrue(e.getMessage().contains("waiting for frameLocator(\"iframe\")"), e.getMessage());
}
@Test
@@ -228,7 +228,7 @@ public class TestLocatorFrame extends TestBase {
page.navigate(server.EMPTY_PAGE);
Locator button = page.locator("body").frameLocator("iframe").locator("button");
PlaywrightException e = assertThrows(PlaywrightException.class, () -> button.waitFor());
assertTrue(e.getMessage().contains("Error: strict mode violation: \"body >> iframe\" resolved to 3 elements"), e.getMessage());
assertTrue(e.getMessage().contains("Error: strict mode violation: locator(\"body\").locator(\"iframe\") resolved to 3 elements"), e.getMessage());
}
@Test
@@ -66,4 +66,40 @@ public class TestLocatorMisc extends TestBase{
assertTrue(e.getMessage().contains("Драматург"), e.getMessage());
}
}
@Test
void shouldClearInput() {
page.navigate(server.PREFIX + "/input/textarea.html");
Locator handle = page.locator("input");
handle.fill("some value");
assertEquals("some value", page.evaluate("() => window['result']"));
handle.clear();
assertEquals("", page.evaluate("() => window['result']"));
}
@Test
void shouldFocusAndBlurAButton() {
page.navigate(server.PREFIX + "/input/button.html");
Locator button = page.locator("button");
assertEquals(false, button.evaluate("button => document.activeElement === button"));
boolean[] focused = {false};
boolean[] blurred = {false};
page.exposeFunction("focusEvent", e -> focused[0] = true);
page.exposeFunction("blurEvent", e -> blurred[0] = true);
button.evaluate("button => {\n" +
" button.addEventListener('focus', window['focusEvent']);\n" +
" button.addEventListener('blur', window['blurEvent']);\n" +
" }");
button.focus();
assertTrue(focused[0]);
assertFalse(blurred[0]);
assertEquals(true, button.evaluate("button => document.activeElement === button"));
button.blur();
assertTrue(focused[0]);
assertTrue(blurred[0]);
assertEquals(false, button.evaluate("button => document.activeElement === button"));
}
}
@@ -243,4 +243,13 @@ public class TestPageFill extends TestBase {
page.fill("input", "");
assertEquals("", page.inputValue("input"));
}
@Test
void shouldBeAbleToClearUsingFill() {
page.navigate(server.PREFIX + "/input/textarea.html");
page.fill("input", "some value");
assertEquals("some value", page.evaluate("() => window['result']"));
page.fill("input", "");
assertEquals("", page.evaluate("() => window['result']"));
}
}
@@ -142,8 +142,16 @@ public class TestPopup extends TestBase {
page.navigate(server.EMPTY_PAGE);
Object[] size = {null};
Page popup = page.waitForPopup(() -> {
size[0] = page.evaluate("() => {\n" +
size[0] = page.evaluate("async () => {\n" +
" const win = window.open(window.location.href, 'Title', 'toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=600,height=300,top=0,left=0');\n" +
" await new Promise(resolve => {\n" +
" const interval = setInterval(() => {\n" +
" if (win.innerWidth === 600 && win.innerHeight === 300) {\n" +
" clearInterval(interval);\n" +
" resolve();\n" +
" }\n" +
" }, 10);\n" +
" });\n" +
" return { width: win.innerWidth, height: win.innerHeight };\n" +
"}");
});
@@ -1,13 +1,14 @@
package com.microsoft.playwright;
import com.microsoft.playwright.options.AriaRole;
import org.junit.jupiter.api.Test;
import java.util.Collections;
import java.util.regex.Pattern;
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.*;
public class TestSelectorsGetBy extends TestBase {
@Test
@@ -139,4 +140,43 @@ public class TestSelectorsGetBy extends TestBase {
assertThat(page.getByAltText("hello my\nworld")).hasAttribute("id", "control");
assertThat(page.getByTitle("hello my\nworld")).hasAttribute("id", "control");
}
@Test
void getByRoleEscaping() {
page.setContent("<a href=\"https://playwright.dev\">issues 123</a>\n" +
" <a href=\"https://playwright.dev\">he llo 56</a>\n" +
" <button>Click me</button>");
assertEquals(
asList("<button>Click me</button>"),
page.getByRole(AriaRole.BUTTON).evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(
asList("<a href=\"https://playwright.dev\">issues 123</a>", "<a href=\"https://playwright.dev\">he llo 56</a>"),
page.getByRole(AriaRole.LINK).evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(
asList("<a href=\"https://playwright.dev\">issues 123</a>"),
page.getByRole(AriaRole.LINK, new Page.GetByRoleOptions().setName("issues 123")).evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(
asList("<a href=\"https://playwright.dev\">issues 123</a>"),
page.getByRole(AriaRole.LINK, new Page.GetByRoleOptions().setName("sues")).evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(
asList("<a href=\"https://playwright.dev\">he llo 56</a>"),
page.getByRole( AriaRole.LINK, new Page.GetByRoleOptions().setName(" he \n llo ")).evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(
asList(),
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("issues")).evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(
asList(),
page.getByRole(AriaRole.LINK, new Page.GetByRoleOptions().setName("sues").setExact(true)).evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(
asList("<a href=\"https://playwright.dev\">he llo 56</a>"),
page.getByRole(AriaRole.LINK, new Page.GetByRoleOptions().setName(" he \n llo 56 ").setExact(true)).evaluateAll("els => els.map(e => e.outerHTML)"));
}
@Test
void locatorGetByRole() {
page.setContent("<div><button>Click me</button></div>");
assertEquals(
asList("<button>Click me</button>"),
page.locator("div").getByRole(AriaRole.BUTTON).evaluateAll("els => els.map(e => e.outerHTML)"));
}
}
@@ -153,26 +153,35 @@ public class TestSelectorsRole extends TestBase {
@Test
void shouldSupportExpanded() {
page.setContent("<button>Hi</button>\n" +
" <button aria-expanded=\"true\">Hello</button>\n" +
" <button aria-expanded=\"false\">Bye</button>");
page.setContent("<div role=\"treeitem\">Hi</div>\n" +
" <div role=\"treeitem\" aria-expanded=\"true\">Hello</div>\n" +
" <div role=\"treeitem\" aria-expanded=\"false\">Bye</div>");
assertEquals(asList(
"<button aria-expanded=\"true\">Hello</button>"
), page.locator("role=button[expanded]").evaluateAll("els => els.map(e => e.outerHTML)"));
"<div role=\"treeitem\">Hi</div>",
"<div role=\"treeitem\" aria-expanded=\"true\">Hello</div>",
"<div role=\"treeitem\" aria-expanded=\"false\">Bye</div>"
), page.locator("role=treeitem").evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(asList(
"<button aria-expanded=\"true\">Hello</button>"
), page.locator("role=button[expanded=true]").evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(asList(
"<button aria-expanded=\"true\">Hello</button>"
), page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setExpanded(true)).evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(asList(
"<button>Hi</button>",
"<button aria-expanded=\"false\">Bye</button>"
), page.locator("role=button[expanded=false]").evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(asList(
"<button>Hi</button>",
"<button aria-expanded=\"false\">Bye</button>"
), page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setExpanded(false)).evaluateAll("els => els.map(e => e.outerHTML)"));
"<div role=\"treeitem\">Hi</div>",
"<div role=\"treeitem\" aria-expanded=\"true\">Hello</div>",
"<div role=\"treeitem\" aria-expanded=\"false\">Bye</div>"
), page.getByRole(AriaRole.TREEITEM).evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(asList("<div role=\"treeitem\" aria-expanded=\"true\">Hello</div>"),
page.locator("role=treeitem[expanded]").evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(asList("<div role=\"treeitem\" aria-expanded=\"true\">Hello</div>"),
page.locator("role=treeitem[expanded=true]").evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(asList("<div role=\"treeitem\" aria-expanded=\"true\">Hello</div>"),
page.getByRole(AriaRole.TREEITEM, new Page.GetByRoleOptions().setExpanded(true)).evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(asList("<div role=\"treeitem\" aria-expanded=\"false\">Bye</div>"),
page.locator("role=treeitem[expanded=false]").evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(asList("<div role=\"treeitem\" aria-expanded=\"false\">Bye</div>"),
page.getByRole(AriaRole.TREEITEM, new Page.GetByRoleOptions().setExpanded(false)).evaluateAll("els => els.map(e => e.outerHTML)"));
// Workaround for expanded='none'.
assertEquals(asList("<div role=\"treeitem\">Hi</div>"),
page.locator("[role=treeitem]:not([aria-expanded])").evaluateAll("els => els.map(e => e.outerHTML)"));
}
@Test
@@ -297,16 +306,19 @@ public class TestSelectorsRole extends TestBase {
@Test
void shouldSupportName() {
page.setContent("<div role=\"button\" aria-label=\"Hello\"></div>\n" +
page.setContent("<div role=\"button\" aria-label=\" Hello \"></div>\n" +
" <div role=\"button\" aria-label=\"Hallo\"></div>\n" +
" <div role=\"button\" aria-label=\"Hello\" aria-hidden=\"true\"></div>\n" +
" <div role=\"button\" aria-label=\"123\" aria-hidden=\"true\"></div>\n" +
" <div role=\"button\" aria-label='foo\"bar' aria-hidden=\"true\"></div>");
assertEquals(asList(
"<div role=\"button\" aria-label=\"Hello\"></div>"
"<div role=\"button\" aria-label=\" Hello \"></div>"
), page.locator("role=button[name='Hello']").evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(asList(
"<div role=\"button\" aria-label=\"Hello\"></div>"
"<div role=\"button\" aria-label=\" Hello \"></div>"
), page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName(" \n Hello ")).evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(asList(
"<div role=\"button\" aria-label=\" Hello \"></div>"
), page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Hello")).evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(asList(
@@ -314,38 +326,38 @@ public class TestSelectorsRole extends TestBase {
), page.locator("role=button[name*='all']").evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(asList(
"<div role=\"button\" aria-label=\"Hello\"></div>",
"<div role=\"button\" aria-label=\" Hello \"></div>",
"<div role=\"button\" aria-label=\"Hallo\"></div>"
), page.locator("role=button[name=/^H[ae]llo$/]").evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(asList(
"<div role=\"button\" aria-label=\"Hello\"></div>",
"<div role=\"button\" aria-label=\" Hello \"></div>",
"<div role=\"button\" aria-label=\"Hallo\"></div>"
), page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName(Pattern.compile("^H[ae]llo$"))).evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(asList(
"<div role=\"button\" aria-label=\"Hello\"></div>",
"<div role=\"button\" aria-label=\" Hello \"></div>",
"<div role=\"button\" aria-label=\"Hallo\"></div>"
), page.locator("role=button[name=/h.*o/i]").evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(asList(
"<div role=\"button\" aria-label=\"Hello\"></div>",
"<div role=\"button\" aria-label=\" Hello \"></div>",
"<div role=\"button\" aria-label=\"Hallo\"></div>"
), page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName(Pattern.compile("h.*o", Pattern.CASE_INSENSITIVE))).evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(asList(
"<div role=\"button\" aria-label=\"Hello\"></div>",
"<div role=\"button\" aria-label=\" Hello \"></div>",
"<div role=\"button\" aria-label=\"Hello\" aria-hidden=\"true\"></div>"
), page.locator("role=button[name='Hello'][include-hidden]").evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(asList(
"<div role=\"button\" aria-label=\"Hello\"></div>",
"<div role=\"button\" aria-label=\" Hello \"></div>",
"<div role=\"button\" aria-label=\"Hello\" aria-hidden=\"true\"></div>"
), page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Hello").setIncludeHidden(true)).evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(asList(
"<div role=\"button\" aria-label=\"Hello\"></div>",
"<div role=\"button\" aria-label=\" Hello \"></div>",
"<div role=\"button\" aria-label=\"Hello\" aria-hidden=\"true\"></div>"
), page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("hello").setIncludeHidden(true)).evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(asList(
"<div role=\"button\" aria-label=\"Hello\"></div>"
"<div role=\"button\" aria-label=\" Hello \"></div>"
), page.locator("role=button[name=Hello]").evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(asList(
"<div role=\"button\" aria-label=\"123\" aria-hidden=\"true\"></div>"
@@ -0,0 +1,28 @@
package com.microsoft.playwright;
import org.junit.jupiter.api.Test;
import java.util.regex.Pattern;
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestSelectorsText extends TestBase {
@Test
void hasTextAndInternalTextShouldMatchFullNodeTextInStrictMode() {
page.setContent("<div id=div1>hello<span>world</span></div>\n" +
" <div id=div2>hello</div>");
assertThat(page.getByText("helloworld", new Page.GetByTextOptions().setExact(true))).hasId("div1");
assertThat(page.getByText("hello", new Page.GetByTextOptions().setExact(true))).hasId("div2");
assertThat(page.locator("div", new Page.LocatorOptions().setHasText(Pattern.compile("^helloworld$")))).hasId("div1");
assertThat(page.locator("div", new Page.LocatorOptions().setHasText(Pattern.compile("^hello$")))).hasId("div2");
page.setContent("<div id=div1><span id=span1>hello</span>world</div>\n" +
" <div id=div2><span id=span2>hello</span></div>");
assertThat(page.getByText("helloworld", new Page.GetByTextOptions().setExact(true))).hasId("div1");
assertEquals(asList("span1", "span2"), page.getByText("hello", new Page.GetByTextOptions().setExact(true)).evaluateAll("els => els.map(e => e.id)"));
assertThat(page.locator("div", new Page.LocatorOptions().setHasText(Pattern.compile("^helloworld$")))).hasId("div1");
assertThat(page.locator("div", new Page.LocatorOptions().setHasText(Pattern.compile("^hello$")))).hasId("div2");
}
}
+1 -1
View File
@@ -6,7 +6,7 @@
<groupId>com.microsoft.playwright</groupId>
<artifactId>parent-pom</artifactId>
<version>1.27.0-SNAPSHOT</version>
<version>1.28.1</version>
<packaging>pom</packaging>
<name>Playwright Parent Project</name>
<description>Java library to automate Chromium, Firefox and WebKit with a single API.
+1 -1
View File
@@ -1 +1 @@
1.27.0
1.28.1
+1 -1
View File
@@ -6,7 +6,7 @@
<groupId>com.microsoft.playwright</groupId>
<artifactId>api-generator</artifactId>
<version>1.27.0-SNAPSHOT</version>
<version>1.28.1</version>
<name>Playwright - API Generator</name>
<description>
This is an internal module used to generate Java API from the upstream Playwright
+1 -1
View File
@@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.microsoft.playwright</groupId>
<artifactId>test-cli-version</artifactId>
<version>1.27.0-SNAPSHOT</version>
<version>1.28.1</version>
<name>Test Playwright Command Line Version</name>
<properties>
<compiler.version>1.8</compiler.version>
+1 -1
View File
@@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.microsoft.playwright</groupId>
<artifactId>test-local-installation</artifactId>
<version>1.27.0-SNAPSHOT</version>
<version>1.28.1</version>
<name>Test local installation</name>
<description>Runs Playwright test suite (copied from playwright module) against locally cached Playwright</description>
<properties>
+1 -1
View File
@@ -9,7 +9,7 @@
</parent>
<groupId>com.microsoft.playwright</groupId>
<artifactId>test-spring-boot-starter</artifactId>
<version>1.27.0-SNAPSHOT</version>
<version>1.28.1</version>
<name>Test Playwright With Spring Boot</name>
<properties>
<spring.version>2.4.3</spring.version>
+1 -1
View File
@@ -6,7 +6,7 @@
<groupId>com.microsoft.playwright</groupId>
<artifactId>update-version</artifactId>
<version>1.27.0-SNAPSHOT</version>
<version>1.28.1</version>
<name>Playwright - Update Version in Documentation</name>
<description>
This is an internal module used to update versions in the documentation based on
+11 -2
View File
@@ -5,8 +5,13 @@ ARG DOCKER_IMAGE_NAME_TEMPLATE="mcr.microsoft.com/playwright/java:v%version%-foc
# === INSTALL JDK and Maven ===
RUN apt-get update && \
# Install install jdk 17 in a separate apt-get command so that
# installing maven doesn't bring in jdk 11
apt-get install -y --no-install-recommends openjdk-17-jdk && \
apt-get install -y --no-install-recommends \
openjdk-17-jdk maven \
# Ubuntu 22.04 and earlier come with Maven 3.6.3 which fails with
# Java 17, so we install latest Maven from Apache instead.
# maven \
# Install utilities required for downloading browsers
curl \
# Install utilities required for downloading driver
@@ -17,8 +22,12 @@ RUN apt-get update && \
# Create the pwuser
adduser pwuser
RUN VERSION=3.8.6 && \
curl -o - https://dlcdn.apache.org/maven/maven-3/$VERSION/binaries/apache-maven-$VERSION-bin.tar.gz | tar zxfv - -C /opt/ && \
ln -s /opt/apache-maven-$VERSION/bin/mvn /usr/local/bin/
ARG PW_TARGET_ARCH
ENV JAVA_HOME=/usr/lib/jvm/java-11-openjdk-${PW_TARGET_ARCH}
ENV JAVA_HOME=/usr/lib/jvm/java-17-openjdk-${PW_TARGET_ARCH}
# === BAKE BROWSERS INTO IMAGE ===