1
0
mirror of synced 2026-05-25 20:23:16 +00:00

Compare commits

...

21 Commits

Author SHA1 Message Date
Andrey Lushnikov 1cc79c4c41 chore: mark v1.15.2 (#638) 2021-10-05 11:52:54 -07:00
Andrey Lushnikov 43da8b23e1 chore: roll to 1.15.2-1633455481000 (#637) 2021-10-05 11:30:26 -07:00
Andrey Lushnikov bcc240d5cb chore: mark v1.15.1 (#634) 2021-09-30 14:21:38 -07:00
Yury Semikhatsky 79668f877f chore(release-1.15): roll driver to 1.15.0-1633020276000 (#633) 2021-09-30 11:42:04 -07:00
Andrey Lushnikov e5e9a7db99 chore: roll Java to the new 1.15.1 driver (#625) 2021-09-23 16:53:09 +02:00
Max Schmitt 0c8706f1eb chore: mark 1.15.0 (#619) 2021-09-21 15:12:25 +02:00
Yury Semikhatsky b000a8b6df chore: simplify issue templates, align with upstream (#611) 2021-09-17 16:20:30 -07:00
Yury Semikhatsky 16cc466622 feat: roll driver, headerValue(s), wheel (#609) 2021-09-17 16:20:14 -07:00
codeboyzhou 958813201a docs: update maven version number for README.md (#605) 2021-09-17 09:03:05 -07:00
Yury Semikhatsky bc7a59d852 chore: more code reuse, enable 2 tests (#599) 2021-09-10 08:08:37 -07:00
Max Schmitt a073eb07ae docs(contributing): add note how to execute tests (#600) 2021-09-10 08:00:24 -07:00
Yury Semikhatsky 2dbc6194a3 feat: catch up with recent feature development upstream (#598) 2021-09-09 18:12:07 -07:00
Yury Semikhatsky 1d69d924cf fix: respect predicate in waitFor* methods (#596) 2021-09-07 12:59:28 -07:00
Max Schmitt a171c39601 feat(roll): roll Playwright to 1.15.0-next-1629487941000 (#583) 2021-08-24 18:26:01 +02:00
Yury Semikhatsky 46baa46e36 docs: update rolling instructions 2021-08-20 08:31:05 -07:00
Yury Semikhatsky cba51c5e96 docs: duplicate field docs to builder methods (#578) 2021-08-20 08:29:46 -07:00
Andrey Lushnikov c17d5d8a9a docs: add rolling.md (#580)
This docs describes how to roll to the Playwright driver.
2021-08-20 05:49:54 -07:00
Yury Semikhatsky 89894e15d2 docs: fix @link reference for method with alias (#577) 2021-08-19 14:52:35 -07:00
Yury Semikhatsky a012836779 chore: update driver, support context-level strict (#575) 2021-08-18 15:08:08 -07:00
Yury Semikhatsky 29c0df6443 devops: fix publish workflow (#565) 2021-08-13 16:47:14 -07:00
Yury Semikhatsky 33ec902eb9 chore: update current version to 1.15.0-SNAPSHOT (#563) 2021-08-13 14:38:07 -07:00
87 changed files with 5754 additions and 369 deletions
+41
View File
@@ -0,0 +1,41 @@
---
name: Bug Report
about: Something doesn't work like it should? Tell us!
title: "[BUG]"
labels: ''
assignees: ''
---
**Context:**
- Playwright Version: [what Playwright version do you use?]
- Operating System: [e.g. Windows, Linux or Mac]
- Browser: [e.g. All, Chromium, Firefox, WebKit]
- Extra: [any specific details about your environment]
<!-- CLI to auto-capture this info -->
<!-- npx envinfo --preset playwright --markdown -->
**Code Snippet**
Help us help you! Put down a short code snippet that illustrates your bug and
that we can run and debug locally. For example:
```java
import com.microsoft.playwright.*;
public class ExampleReproducible {
public static void main(String[] args) {
try (Playwright playwright = Playwright.create()) {
Browser browser = playwright.chromium().launch();
BrowserContext context = browser.newContext();
Page page = context.newPage();
// ...
}
}
}
```
**Describe the bug**
Add any other details about the problem here.
-75
View File
@@ -1,75 +0,0 @@
name: Bug Report
description: Something doesn't work like it should? Tell us!
title: "[Bug]: "
labels: []
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
- type: input
id: version
attributes:
label: Playwright version
description: Which version of of Playwright are you using?
placeholder: ex. 1.12.0
validations:
required: true
- type: dropdown
id: operating-system
attributes:
label: Operating system
multiple: true
description: What operating system are you running Playwright on?
options:
- Windows
- MacOS
- Linux
- type: dropdown
id: browsers
attributes:
label: What browsers are you seeing the problem on?
multiple: true
options:
- Chromium
- Firefox
- WebKit
- type: textarea
id: other-information
attributes:
label: Other information
description: ex. Java version, Linux distribution etc.
- type: textarea
id: what-happened
attributes:
label: What happened? / Describe the bug
description: Also tell us, what did you expect to happen?
placeholder: Tell us what you see!
validations:
required: true
- type: textarea
id: reproducible
attributes:
label: Code snippet to reproduce your bug
description: Help us help you! Put down a short code snippet that illustrates your bug and that we can run and debug locally. This will be automatically formatted into code, so no need for backticks.
render: shell
placeholder: |
import com.microsoft.playwright.*;
public class ExampleReproducible {
public static void main(String[] args) {
try (Playwright playwright = Playwright.create()) {
Browser browser = playwright.chromium().launch();
BrowserContext context = browser.newContext();
Page page = context.newPage();
// ...
}
}
}
- type: textarea
id: logs
attributes:
label: Relevant log output
description: Please copy and paste any relevant log output like [Playwright debug logs](https://playwright.dev/docs/debug#verbose-api-logs). This will be automatically formatted into code, so no need for backticks.
render: shell
+11
View File
@@ -0,0 +1,11 @@
---
name: Feature request
about: Request new features to be added
title: "[Feature]"
labels: ''
assignees: ''
---
Let us know what functionality you'd like to see in Playwright and what your use case is.
Do you think others might benefit from this as well?
@@ -1,18 +0,0 @@
name: Feature request
description: Request new features to be added
title: "[Feature]: "
labels: []
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this feature request!
- type: textarea
id: what-happened
attributes:
label: Feature request
description: |
Let us know what functionality you'd like to see in Playwright and what is your use case.
Do you think others might benefit from this as well?
validations:
required: true
+10
View File
@@ -0,0 +1,10 @@
---
name: I have a question
about: Feel free to ask us your questions!
title: "[Question]"
labels: ''
assignees: ''
---
-11
View File
@@ -1,11 +0,0 @@
name: I have a question
description: Feel free to ask us your questions!
title: "[Question]: "
labels: []
body:
- type: textarea
id: question
attributes:
label: Your question
validations:
required: true
+38
View File
@@ -0,0 +1,38 @@
---
name: Report regression
about: Functionality that used to work and does not any more
title: "[REGRESSION]: "
labels: ''
assignees: ''
---
**Context:**
- GOOD Playwright Version: [what Playwright version worked nicely?]
- BAD Playwright Version: [what Playwright version doesn't work any more?]
- Operating System: [e.g. Windows, Linux or Mac]
- Extra: [any specific details about your environment]
**Code Snippet**
Help us help you! Put down a short code snippet that illustrates your bug and
that we can run and debug locally. For example:
```java
import com.microsoft.playwright.*;
public class ExampleReproducible {
public static void main(String[] args) {
try (Playwright playwright = Playwright.create()) {
Browser browser = playwright.chromium().launch();
BrowserContext context = browser.newContext();
Page page = context.newPage();
// ...
}
}
}
```
**Describe the bug**
Add any other details about the problem here.
+1 -1
View File
@@ -1,6 +1,6 @@
name: Publish
on:
workflow_dispatch
workflow_dispatch:
push:
branches:
- master
+4
View File
@@ -33,6 +33,10 @@ Names of published driver archives can be found at https://github.com/microsoft/
```bash
mvn compile
mvn test
# Executing a single test
BROWSER=chromium mvn test -Dtest=TestPageNetworkSizes#shouldHaveTheCorrectResponseBodySize
# Executing a single test class
BROWSER=chromium mvn test -Dtest=TestPageNetworkSizes
```
### Generating API
+3 -3
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 -->94.0.4595.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Chromium <!-- GEN:chromium-version -->96.0.4641.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| WebKit <!-- GEN:webkit-version -->15.0<!-- GEN:stop --> | ✅ | ✅ | ✅ |
| Firefox <!-- GEN:firefox-version -->91.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Firefox <!-- GEN:firefox-version -->92.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.12.0</version>
<version>1.14.1</version>
</dependency>
```
+7
View File
@@ -0,0 +1,7 @@
# Rolling Playwright-Java to the latest Playwright driver
* make sure to have at least Java 8 and Maven 3.6.3
* clone playwright for java: http://github.com/microsoft/playwright-java
* set new driver version in `scripts/CLI_VERSION`
* regenerate API: `./scripts/download_driver_for_all_platforms.sh -f && ./scripts/generate_api.sh && ./scripts/update_readme.sh`
* commit & send PR with the roll
+1 -1
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>com.microsoft.playwright</groupId>
<artifactId>parent-pom</artifactId>
<version>1.14.0-SNAPSHOT</version>
<version>1.15.2</version>
</parent>
<artifactId>driver-bundle</artifactId>
+1 -1
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>com.microsoft.playwright</groupId>
<artifactId>parent-pom</artifactId>
<version>1.14.0-SNAPSHOT</version>
<version>1.15.2</version>
</parent>
<artifactId>driver</artifactId>
+1 -1
View File
@@ -6,7 +6,7 @@
<groupId>org.example</groupId>
<artifactId>examples</artifactId>
<version>1.14.0-SNAPSHOT</version>
<version>1.15.2</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.14.0-SNAPSHOT</version>
<version>1.15.2</version>
</parent>
<artifactId>playwright</artifactId>
@@ -61,10 +61,11 @@ public interface Browser extends AutoCloseable {
*/
public Boolean acceptDownloads;
/**
* When using {@link Page#goto Page.goto()}, {@link Page#route Page.route()}, {@link Page#waitForURL Page.waitForURL()},
* {@link Page#waitForRequest Page.waitForRequest()}, or {@link Page#waitForResponse Page.waitForResponse()} it takes the
* base URL in consideration by using the <a href="https://developer.mozilla.org/en-US/docs/Web/API/URL/URL">{@code URL()}</a>
* constructor for building the corresponding URL. Examples:
* When using {@link Page#navigate Page.navigate()}, {@link Page#route Page.route()}, {@link Page#waitForURL
* Page.waitForURL()}, {@link Page#waitForRequest Page.waitForRequest()}, or {@link Page#waitForResponse
* Page.waitForResponse()} it takes the base URL in consideration by using the <a
* href="https://developer.mozilla.org/en-US/docs/Web/API/URL/URL">{@code URL()}</a> constructor for building the corresponding
* URL. Examples:
* <ul>
* <li> baseURL: {@code http://localhost:3000} and navigating to {@code /bar.html} results in {@code http://localhost:3000/bar.html}</li>
* <li> baseURL: {@code http://localhost:3000/foo/} and navigating to {@code ./bar.html} results in {@code http://localhost:3000/foo/bar.html}</li>
@@ -85,9 +86,17 @@ public interface Browser extends AutoCloseable {
*/
public Double deviceScaleFactor;
/**
* An object containing additional HTTP headers to be sent with every request. All header values must be strings.
* An object containing additional HTTP headers to be sent with every request.
*/
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"}.
*
* <p> <strong>NOTE:</strong> It's not supported in WebKit, see <a href="https://bugs.webkit.org/show_bug.cgi?id=225281">here</a> in their issue
* tracker.
*/
public ForcedColors forcedColors;
public Geolocation geolocation;
/**
* Specifies if viewport supports touch events. Defaults to false.
@@ -98,7 +107,7 @@ public interface Browser extends AutoCloseable {
*/
public HttpCredentials httpCredentials;
/**
* Whether to ignore HTTPS errors during navigation. Defaults to {@code false}.
* Whether to ignore HTTPS errors when sending network requests. Defaults to {@code false}.
*/
public Boolean ignoreHTTPSErrors;
/**
@@ -174,6 +183,12 @@ public interface Browser extends AutoCloseable {
* state.
*/
public Path storageStatePath;
/**
* It specified, enables strict selectors mode for this context. In the strict selectors mode all operations on selectors
* that imply single target DOM element will throw when more than one element matches the selector. See {@code Locator} to learn
* more about the strict mode.
*/
public Boolean strictSelectors;
/**
* Changes the timezone of the context. See <a
* href="https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1">ICU's
@@ -189,30 +204,68 @@ public interface Browser extends AutoCloseable {
*/
public Optional<ViewportSize> viewportSize;
/**
* Whether to automatically download all the attachments. Defaults to {@code false} where all the downloads are canceled.
*/
public NewContextOptions setAcceptDownloads(boolean acceptDownloads) {
this.acceptDownloads = acceptDownloads;
return this;
}
/**
* When using {@link Page#navigate Page.navigate()}, {@link Page#route Page.route()}, {@link Page#waitForURL
* Page.waitForURL()}, {@link Page#waitForRequest Page.waitForRequest()}, or {@link Page#waitForResponse
* Page.waitForResponse()} it takes the base URL in consideration by using the <a
* href="https://developer.mozilla.org/en-US/docs/Web/API/URL/URL">{@code URL()}</a> constructor for building the corresponding
* URL. Examples:
* <ul>
* <li> baseURL: {@code http://localhost:3000} and navigating to {@code /bar.html} results in {@code http://localhost:3000/bar.html}</li>
* <li> baseURL: {@code http://localhost:3000/foo/} and navigating to {@code ./bar.html} results in {@code http://localhost:3000/foo/bar.html}</li>
* </ul>
*/
public NewContextOptions setBaseURL(String baseURL) {
this.baseURL = baseURL;
return this;
}
/**
* Toggles bypassing page's Content-Security-Policy.
*/
public NewContextOptions setBypassCSP(boolean bypassCSP) {
this.bypassCSP = bypassCSP;
return this;
}
/**
* 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"}.
*/
public NewContextOptions setColorScheme(ColorScheme colorScheme) {
this.colorScheme = colorScheme;
return this;
}
/**
* Specify device scale factor (can be thought of as dpr). Defaults to {@code 1}.
*/
public NewContextOptions setDeviceScaleFactor(double deviceScaleFactor) {
this.deviceScaleFactor = deviceScaleFactor;
return this;
}
/**
* An object containing additional HTTP headers to be sent with every request.
*/
public NewContextOptions setExtraHTTPHeaders(Map<String, String> extraHTTPHeaders) {
this.extraHTTPHeaders = extraHTTPHeaders;
return this;
}
/**
* 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"}.
*
* <p> <strong>NOTE:</strong> It's not supported in WebKit, see <a href="https://bugs.webkit.org/show_bug.cgi?id=225281">here</a> in their issue
* tracker.
*/
public NewContextOptions setForcedColors(ForcedColors forcedColors) {
this.forcedColors = forcedColors;
return this;
}
public NewContextOptions setGeolocation(double latitude, double longitude) {
return setGeolocation(new Geolocation(latitude, longitude));
}
@@ -220,97 +273,207 @@ public interface Browser extends AutoCloseable {
this.geolocation = geolocation;
return this;
}
/**
* Specifies if viewport supports touch events. Defaults to false.
*/
public NewContextOptions setHasTouch(boolean hasTouch) {
this.hasTouch = hasTouch;
return this;
}
/**
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>.
*/
public NewContextOptions setHttpCredentials(String username, String password) {
return setHttpCredentials(new HttpCredentials(username, password));
}
/**
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>.
*/
public NewContextOptions setHttpCredentials(HttpCredentials httpCredentials) {
this.httpCredentials = httpCredentials;
return this;
}
/**
* Whether to ignore HTTPS errors when sending network requests. Defaults to {@code false}.
*/
public NewContextOptions setIgnoreHTTPSErrors(boolean ignoreHTTPSErrors) {
this.ignoreHTTPSErrors = ignoreHTTPSErrors;
return this;
}
/**
* Whether the {@code meta viewport} tag is taken into account and touch events are enabled. Defaults to {@code false}. Not supported
* in Firefox.
*/
public NewContextOptions setIsMobile(boolean isMobile) {
this.isMobile = isMobile;
return this;
}
/**
* Whether or not to enable JavaScript in the context. Defaults to {@code true}.
*/
public NewContextOptions setJavaScriptEnabled(boolean javaScriptEnabled) {
this.javaScriptEnabled = javaScriptEnabled;
return this;
}
/**
* Specify user locale, for example {@code en-GB}, {@code de-DE}, etc. Locale will affect {@code navigator.language} value, {@code Accept-Language}
* request header value as well as number and date formatting rules.
*/
public NewContextOptions setLocale(String locale) {
this.locale = locale;
return this;
}
/**
* Whether to emulate network being offline. Defaults to {@code false}.
*/
public NewContextOptions setOffline(boolean offline) {
this.offline = offline;
return this;
}
/**
* A list of permissions to grant to all pages in this context. See {@link BrowserContext#grantPermissions
* BrowserContext.grantPermissions()} for more details.
*/
public NewContextOptions setPermissions(List<String> permissions) {
this.permissions = permissions;
return this;
}
/**
* Network proxy settings to use with this context.
*
* <p> <strong>NOTE:</strong> For Chromium on Windows the browser needs to be launched with the global proxy for this option to work. If all contexts
* override the proxy, global proxy will be never used and can be any string, for example {@code launch({ proxy: { server:
* 'http://per-context' } })}.
*/
public NewContextOptions setProxy(String server) {
return setProxy(new Proxy(server));
}
/**
* Network proxy settings to use with this context.
*
* <p> <strong>NOTE:</strong> For Chromium on Windows the browser needs to be launched with the global proxy for this option to work. If all contexts
* override the proxy, global proxy will be never used and can be any string, for example {@code launch({ proxy: { server:
* 'http://per-context' } })}.
*/
public NewContextOptions setProxy(Proxy proxy) {
this.proxy = proxy;
return this;
}
/**
* Optional setting to control whether to omit request content from the HAR. Defaults to {@code false}.
*/
public NewContextOptions setRecordHarOmitContent(boolean recordHarOmitContent) {
this.recordHarOmitContent = recordHarOmitContent;
return this;
}
/**
* Enables <a href="http://www.softwareishard.com/blog/har-12-spec">HAR</a> recording for all pages into the specified HAR
* file on the filesystem. If not specified, the HAR is not recorded. Make sure to call {@link BrowserContext#close
* BrowserContext.close()} for the HAR to be saved.
*/
public NewContextOptions setRecordHarPath(Path recordHarPath) {
this.recordHarPath = recordHarPath;
return this;
}
/**
* Enables video recording for all pages into the specified directory. If not specified videos are not recorded. Make sure
* to call {@link BrowserContext#close BrowserContext.close()} for videos to be saved.
*/
public NewContextOptions setRecordVideoDir(Path recordVideoDir) {
this.recordVideoDir = recordVideoDir;
return this;
}
/**
* Dimensions of the recorded videos. If not specified the size will be equal to {@code viewport} scaled down to fit into
* 800x800. If {@code viewport} is not configured explicitly the video size defaults to 800x450. Actual picture of each page will
* be scaled down if necessary to fit the specified size.
*/
public NewContextOptions setRecordVideoSize(int width, int height) {
return setRecordVideoSize(new RecordVideoSize(width, height));
}
/**
* Dimensions of the recorded videos. If not specified the size will be equal to {@code viewport} scaled down to fit into
* 800x800. If {@code viewport} is not configured explicitly the video size defaults to 800x450. Actual picture of each page will
* be scaled down if necessary to fit the specified size.
*/
public NewContextOptions setRecordVideoSize(RecordVideoSize recordVideoSize) {
this.recordVideoSize = recordVideoSize;
return this;
}
/**
* 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"}.
*/
public NewContextOptions setReducedMotion(ReducedMotion reducedMotion) {
this.reducedMotion = reducedMotion;
return this;
}
/**
* Emulates consistent window screen size available inside web page via {@code window.screen}. Is only used when the {@code viewport}
* is set.
*/
public NewContextOptions setScreenSize(int width, int height) {
return setScreenSize(new ScreenSize(width, height));
}
/**
* Emulates consistent window screen size available inside web page via {@code window.screen}. Is only used when the {@code viewport}
* is set.
*/
public NewContextOptions setScreenSize(ScreenSize screenSize) {
this.screenSize = screenSize;
return this;
}
/**
* Populates context with given storage state. This option can be used to initialize context with logged-in information
* obtained via {@link BrowserContext#storageState BrowserContext.storageState()}.
*/
public NewContextOptions setStorageState(String storageState) {
this.storageState = storageState;
return this;
}
/**
* Populates context with given storage state. This option can be used to initialize context with logged-in information
* obtained via {@link BrowserContext#storageState BrowserContext.storageState()}. Path to the file with saved storage
* state.
*/
public NewContextOptions setStorageStatePath(Path storageStatePath) {
this.storageStatePath = storageStatePath;
return this;
}
/**
* It specified, enables strict selectors mode for this context. In the strict selectors mode all operations on selectors
* that imply single target DOM element will throw when more than one element matches the selector. See {@code Locator} to learn
* more about the strict mode.
*/
public NewContextOptions setStrictSelectors(boolean strictSelectors) {
this.strictSelectors = strictSelectors;
return this;
}
/**
* Changes the timezone of the context. See <a
* href="https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1">ICU's
* metaZones.txt</a> for a list of supported timezone IDs.
*/
public NewContextOptions setTimezoneId(String timezoneId) {
this.timezoneId = timezoneId;
return this;
}
/**
* Specific user agent to use in this context.
*/
public NewContextOptions setUserAgent(String userAgent) {
this.userAgent = userAgent;
return this;
}
/**
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. {@code null} disables the default viewport.
*/
public NewContextOptions setViewportSize(int width, int height) {
return setViewportSize(new ViewportSize(width, height));
}
/**
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. {@code null} disables the default viewport.
*/
public NewContextOptions setViewportSize(ViewportSize viewportSize) {
this.viewportSize = Optional.ofNullable(viewportSize);
return this;
@@ -322,10 +485,11 @@ public interface Browser extends AutoCloseable {
*/
public Boolean acceptDownloads;
/**
* When using {@link Page#goto Page.goto()}, {@link Page#route Page.route()}, {@link Page#waitForURL Page.waitForURL()},
* {@link Page#waitForRequest Page.waitForRequest()}, or {@link Page#waitForResponse Page.waitForResponse()} it takes the
* base URL in consideration by using the <a href="https://developer.mozilla.org/en-US/docs/Web/API/URL/URL">{@code URL()}</a>
* constructor for building the corresponding URL. Examples:
* When using {@link Page#navigate Page.navigate()}, {@link Page#route Page.route()}, {@link Page#waitForURL
* Page.waitForURL()}, {@link Page#waitForRequest Page.waitForRequest()}, or {@link Page#waitForResponse
* Page.waitForResponse()} it takes the base URL in consideration by using the <a
* href="https://developer.mozilla.org/en-US/docs/Web/API/URL/URL">{@code URL()}</a> constructor for building the corresponding
* URL. Examples:
* <ul>
* <li> baseURL: {@code http://localhost:3000} and navigating to {@code /bar.html} results in {@code http://localhost:3000/bar.html}</li>
* <li> baseURL: {@code http://localhost:3000/foo/} and navigating to {@code ./bar.html} results in {@code http://localhost:3000/foo/bar.html}</li>
@@ -346,9 +510,17 @@ public interface Browser extends AutoCloseable {
*/
public Double deviceScaleFactor;
/**
* An object containing additional HTTP headers to be sent with every request. All header values must be strings.
* An object containing additional HTTP headers to be sent with every request.
*/
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"}.
*
* <p> <strong>NOTE:</strong> It's not supported in WebKit, see <a href="https://bugs.webkit.org/show_bug.cgi?id=225281">here</a> in their issue
* tracker.
*/
public ForcedColors forcedColors;
public Geolocation geolocation;
/**
* Specifies if viewport supports touch events. Defaults to false.
@@ -359,7 +531,7 @@ public interface Browser extends AutoCloseable {
*/
public HttpCredentials httpCredentials;
/**
* Whether to ignore HTTPS errors during navigation. Defaults to {@code false}.
* Whether to ignore HTTPS errors when sending network requests. Defaults to {@code false}.
*/
public Boolean ignoreHTTPSErrors;
/**
@@ -435,6 +607,12 @@ public interface Browser extends AutoCloseable {
* state.
*/
public Path storageStatePath;
/**
* It specified, enables strict selectors mode for this context. In the strict selectors mode all operations on selectors
* that imply single target DOM element will throw when more than one element matches the selector. See {@code Locator} to learn
* more about the strict mode.
*/
public Boolean strictSelectors;
/**
* Changes the timezone of the context. See <a
* href="https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1">ICU's
@@ -450,30 +628,68 @@ public interface Browser extends AutoCloseable {
*/
public Optional<ViewportSize> viewportSize;
/**
* Whether to automatically download all the attachments. Defaults to {@code false} where all the downloads are canceled.
*/
public NewPageOptions setAcceptDownloads(boolean acceptDownloads) {
this.acceptDownloads = acceptDownloads;
return this;
}
/**
* When using {@link Page#navigate Page.navigate()}, {@link Page#route Page.route()}, {@link Page#waitForURL
* Page.waitForURL()}, {@link Page#waitForRequest Page.waitForRequest()}, or {@link Page#waitForResponse
* Page.waitForResponse()} it takes the base URL in consideration by using the <a
* href="https://developer.mozilla.org/en-US/docs/Web/API/URL/URL">{@code URL()}</a> constructor for building the corresponding
* URL. Examples:
* <ul>
* <li> baseURL: {@code http://localhost:3000} and navigating to {@code /bar.html} results in {@code http://localhost:3000/bar.html}</li>
* <li> baseURL: {@code http://localhost:3000/foo/} and navigating to {@code ./bar.html} results in {@code http://localhost:3000/foo/bar.html}</li>
* </ul>
*/
public NewPageOptions setBaseURL(String baseURL) {
this.baseURL = baseURL;
return this;
}
/**
* Toggles bypassing page's Content-Security-Policy.
*/
public NewPageOptions setBypassCSP(boolean bypassCSP) {
this.bypassCSP = bypassCSP;
return this;
}
/**
* 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"}.
*/
public NewPageOptions setColorScheme(ColorScheme colorScheme) {
this.colorScheme = colorScheme;
return this;
}
/**
* Specify device scale factor (can be thought of as dpr). Defaults to {@code 1}.
*/
public NewPageOptions setDeviceScaleFactor(double deviceScaleFactor) {
this.deviceScaleFactor = deviceScaleFactor;
return this;
}
/**
* An object containing additional HTTP headers to be sent with every request.
*/
public NewPageOptions setExtraHTTPHeaders(Map<String, String> extraHTTPHeaders) {
this.extraHTTPHeaders = extraHTTPHeaders;
return this;
}
/**
* 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"}.
*
* <p> <strong>NOTE:</strong> It's not supported in WebKit, see <a href="https://bugs.webkit.org/show_bug.cgi?id=225281">here</a> in their issue
* tracker.
*/
public NewPageOptions setForcedColors(ForcedColors forcedColors) {
this.forcedColors = forcedColors;
return this;
}
public NewPageOptions setGeolocation(double latitude, double longitude) {
return setGeolocation(new Geolocation(latitude, longitude));
}
@@ -481,97 +697,207 @@ public interface Browser extends AutoCloseable {
this.geolocation = geolocation;
return this;
}
/**
* Specifies if viewport supports touch events. Defaults to false.
*/
public NewPageOptions setHasTouch(boolean hasTouch) {
this.hasTouch = hasTouch;
return this;
}
/**
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>.
*/
public NewPageOptions setHttpCredentials(String username, String password) {
return setHttpCredentials(new HttpCredentials(username, password));
}
/**
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>.
*/
public NewPageOptions setHttpCredentials(HttpCredentials httpCredentials) {
this.httpCredentials = httpCredentials;
return this;
}
/**
* Whether to ignore HTTPS errors when sending network requests. Defaults to {@code false}.
*/
public NewPageOptions setIgnoreHTTPSErrors(boolean ignoreHTTPSErrors) {
this.ignoreHTTPSErrors = ignoreHTTPSErrors;
return this;
}
/**
* Whether the {@code meta viewport} tag is taken into account and touch events are enabled. Defaults to {@code false}. Not supported
* in Firefox.
*/
public NewPageOptions setIsMobile(boolean isMobile) {
this.isMobile = isMobile;
return this;
}
/**
* Whether or not to enable JavaScript in the context. Defaults to {@code true}.
*/
public NewPageOptions setJavaScriptEnabled(boolean javaScriptEnabled) {
this.javaScriptEnabled = javaScriptEnabled;
return this;
}
/**
* Specify user locale, for example {@code en-GB}, {@code de-DE}, etc. Locale will affect {@code navigator.language} value, {@code Accept-Language}
* request header value as well as number and date formatting rules.
*/
public NewPageOptions setLocale(String locale) {
this.locale = locale;
return this;
}
/**
* Whether to emulate network being offline. Defaults to {@code false}.
*/
public NewPageOptions setOffline(boolean offline) {
this.offline = offline;
return this;
}
/**
* A list of permissions to grant to all pages in this context. See {@link BrowserContext#grantPermissions
* BrowserContext.grantPermissions()} for more details.
*/
public NewPageOptions setPermissions(List<String> permissions) {
this.permissions = permissions;
return this;
}
/**
* Network proxy settings to use with this context.
*
* <p> <strong>NOTE:</strong> For Chromium on Windows the browser needs to be launched with the global proxy for this option to work. If all contexts
* override the proxy, global proxy will be never used and can be any string, for example {@code launch({ proxy: { server:
* 'http://per-context' } })}.
*/
public NewPageOptions setProxy(String server) {
return setProxy(new Proxy(server));
}
/**
* Network proxy settings to use with this context.
*
* <p> <strong>NOTE:</strong> For Chromium on Windows the browser needs to be launched with the global proxy for this option to work. If all contexts
* override the proxy, global proxy will be never used and can be any string, for example {@code launch({ proxy: { server:
* 'http://per-context' } })}.
*/
public NewPageOptions setProxy(Proxy proxy) {
this.proxy = proxy;
return this;
}
/**
* Optional setting to control whether to omit request content from the HAR. Defaults to {@code false}.
*/
public NewPageOptions setRecordHarOmitContent(boolean recordHarOmitContent) {
this.recordHarOmitContent = recordHarOmitContent;
return this;
}
/**
* Enables <a href="http://www.softwareishard.com/blog/har-12-spec">HAR</a> recording for all pages into the specified HAR
* file on the filesystem. If not specified, the HAR is not recorded. Make sure to call {@link BrowserContext#close
* BrowserContext.close()} for the HAR to be saved.
*/
public NewPageOptions setRecordHarPath(Path recordHarPath) {
this.recordHarPath = recordHarPath;
return this;
}
/**
* Enables video recording for all pages into the specified directory. If not specified videos are not recorded. Make sure
* to call {@link BrowserContext#close BrowserContext.close()} for videos to be saved.
*/
public NewPageOptions setRecordVideoDir(Path recordVideoDir) {
this.recordVideoDir = recordVideoDir;
return this;
}
/**
* Dimensions of the recorded videos. If not specified the size will be equal to {@code viewport} scaled down to fit into
* 800x800. If {@code viewport} is not configured explicitly the video size defaults to 800x450. Actual picture of each page will
* be scaled down if necessary to fit the specified size.
*/
public NewPageOptions setRecordVideoSize(int width, int height) {
return setRecordVideoSize(new RecordVideoSize(width, height));
}
/**
* Dimensions of the recorded videos. If not specified the size will be equal to {@code viewport} scaled down to fit into
* 800x800. If {@code viewport} is not configured explicitly the video size defaults to 800x450. Actual picture of each page will
* be scaled down if necessary to fit the specified size.
*/
public NewPageOptions setRecordVideoSize(RecordVideoSize recordVideoSize) {
this.recordVideoSize = recordVideoSize;
return this;
}
/**
* 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"}.
*/
public NewPageOptions setReducedMotion(ReducedMotion reducedMotion) {
this.reducedMotion = reducedMotion;
return this;
}
/**
* Emulates consistent window screen size available inside web page via {@code window.screen}. Is only used when the {@code viewport}
* is set.
*/
public NewPageOptions setScreenSize(int width, int height) {
return setScreenSize(new ScreenSize(width, height));
}
/**
* Emulates consistent window screen size available inside web page via {@code window.screen}. Is only used when the {@code viewport}
* is set.
*/
public NewPageOptions setScreenSize(ScreenSize screenSize) {
this.screenSize = screenSize;
return this;
}
/**
* Populates context with given storage state. This option can be used to initialize context with logged-in information
* obtained via {@link BrowserContext#storageState BrowserContext.storageState()}.
*/
public NewPageOptions setStorageState(String storageState) {
this.storageState = storageState;
return this;
}
/**
* Populates context with given storage state. This option can be used to initialize context with logged-in information
* obtained via {@link BrowserContext#storageState BrowserContext.storageState()}. Path to the file with saved storage
* state.
*/
public NewPageOptions setStorageStatePath(Path storageStatePath) {
this.storageStatePath = storageStatePath;
return this;
}
/**
* It specified, enables strict selectors mode for this context. In the strict selectors mode all operations on selectors
* that imply single target DOM element will throw when more than one element matches the selector. See {@code Locator} to learn
* more about the strict mode.
*/
public NewPageOptions setStrictSelectors(boolean strictSelectors) {
this.strictSelectors = strictSelectors;
return this;
}
/**
* Changes the timezone of the context. See <a
* href="https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1">ICU's
* metaZones.txt</a> for a list of supported timezone IDs.
*/
public NewPageOptions setTimezoneId(String timezoneId) {
this.timezoneId = timezoneId;
return this;
}
/**
* Specific user agent to use in this context.
*/
public NewPageOptions setUserAgent(String userAgent) {
this.userAgent = userAgent;
return this;
}
/**
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. {@code null} disables the default viewport.
*/
public NewPageOptions setViewportSize(int width, int height) {
return setViewportSize(new ViewportSize(width, height));
}
/**
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. {@code null} disables the default viewport.
*/
public NewPageOptions setViewportSize(ViewportSize viewportSize) {
this.viewportSize = Optional.ofNullable(viewportSize);
return this;
@@ -591,14 +917,23 @@ public interface Browser extends AutoCloseable {
*/
public Boolean screenshots;
/**
* specify custom categories to use instead of default.
*/
public StartTracingOptions setCategories(List<String> categories) {
this.categories = categories;
return this;
}
/**
* A path to write the trace file to.
*/
public StartTracingOptions setPath(Path path) {
this.path = path;
return this;
}
/**
* captures screenshots in the trace.
*/
public StartTracingOptions setScreenshots(boolean screenshots) {
this.screenshots = screenshots;
return this;
@@ -137,6 +137,10 @@ public interface BrowserContext extends AutoCloseable {
*/
public Boolean handle;
/**
* Whether to pass the argument as a handle, instead of passing by value. When passing a handle, only one argument is
* supported. When passing by value, multiple arguments are supported.
*/
public ExposeBindingOptions setHandle(boolean handle) {
this.handle = handle;
return this;
@@ -148,11 +152,28 @@ public interface BrowserContext extends AutoCloseable {
*/
public String origin;
/**
* The [origin] to grant permissions to, e.g. "https://example.com".
*/
public GrantPermissionsOptions setOrigin(String origin) {
this.origin = origin;
return this;
}
}
class RouteOptions {
/**
* How often a route should be used. By default it will be used every time.
*/
public Integer times;
/**
* How often a route should be used. By default it will be used every time.
*/
public RouteOptions setTimes(int times) {
this.times = times;
return this;
}
}
class StorageStateOptions {
/**
* The file path to save the storage state to. If {@code path} is a relative path, then it is resolved relative to current
@@ -160,6 +181,10 @@ public interface BrowserContext extends AutoCloseable {
*/
public Path path;
/**
* The file path to save the storage state to. If {@code path} is a relative path, then it is resolved relative to current
* working directory. If no path is provided, storage state is still returned, but won't be saved to the disk.
*/
public StorageStateOptions setPath(Path path) {
this.path = path;
return this;
@@ -176,10 +201,17 @@ public interface BrowserContext extends AutoCloseable {
*/
public Double timeout;
/**
* Receives the {@code Page} object and resolves to truthy value when the waiting should resolve.
*/
public WaitForPageOptions setPredicate(Predicate<Page> predicate) {
this.predicate = predicate;
return this;
}
/**
* Maximum time to wait for in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
* value can be changed by using the {@link BrowserContext#setDefaultTimeout BrowserContext.setDefaultTimeout()}.
*/
public WaitForPageOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -519,6 +551,10 @@ public interface BrowserContext extends AutoCloseable {
* Routing provides the capability to modify network requests that are made by any page in the browser context. Once route
* is enabled, every request matching the url pattern will stall unless it's continued, fulfilled or aborted.
*
* <p> <strong>NOTE:</strong> {@link Page#route Page.route()} will not intercept requests intercepted by Service Worker. See <a
* href="https://github.com/microsoft/playwright/issues/1090">this</a> issue. We recommend disabling Service Workers when
* using request interception. Via {@code await context.addInitScript(() => delete window.navigator.serviceWorker);}
*
* <p> An example of a naive handler that aborts all image requests:
* <pre>{@code
* BrowserContext context = browser.newContext();
@@ -560,11 +596,17 @@ public interface BrowserContext extends AutoCloseable {
* href="https://developer.mozilla.org/en-US/docs/Web/API/URL/URL">{@code new URL()}</a> constructor.
* @param handler handler function to route the request.
*/
void route(String url, Consumer<Route> handler);
default void route(String url, Consumer<Route> handler) {
route(url, handler, null);
}
/**
* Routing provides the capability to modify network requests that are made by any page in the browser context. Once route
* is enabled, every request matching the url pattern will stall unless it's continued, fulfilled or aborted.
*
* <p> <strong>NOTE:</strong> {@link Page#route Page.route()} will not intercept requests intercepted by Service Worker. See <a
* href="https://github.com/microsoft/playwright/issues/1090">this</a> issue. We recommend disabling Service Workers when
* using request interception. Via {@code await context.addInitScript(() => delete window.navigator.serviceWorker);}
*
* <p> An example of a naive handler that aborts all image requests:
* <pre>{@code
* BrowserContext context = browser.newContext();
@@ -606,11 +648,15 @@ public interface BrowserContext extends AutoCloseable {
* href="https://developer.mozilla.org/en-US/docs/Web/API/URL/URL">{@code new URL()}</a> constructor.
* @param handler handler function to route the request.
*/
void route(Pattern url, Consumer<Route> handler);
void route(String url, Consumer<Route> handler, RouteOptions options);
/**
* Routing provides the capability to modify network requests that are made by any page in the browser context. Once route
* is enabled, every request matching the url pattern will stall unless it's continued, fulfilled or aborted.
*
* <p> <strong>NOTE:</strong> {@link Page#route Page.route()} will not intercept requests intercepted by Service Worker. See <a
* href="https://github.com/microsoft/playwright/issues/1090">this</a> issue. We recommend disabling Service Workers when
* using request interception. Via {@code await context.addInitScript(() => delete window.navigator.serviceWorker);}
*
* <p> An example of a naive handler that aborts all image requests:
* <pre>{@code
* BrowserContext context = browser.newContext();
@@ -652,13 +698,167 @@ public interface BrowserContext extends AutoCloseable {
* href="https://developer.mozilla.org/en-US/docs/Web/API/URL/URL">{@code new URL()}</a> constructor.
* @param handler handler function to route the request.
*/
void route(Predicate<String> url, Consumer<Route> handler);
default void route(Pattern url, Consumer<Route> handler) {
route(url, handler, null);
}
/**
* Routing provides the capability to modify network requests that are made by any page in the browser context. Once route
* is enabled, every request matching the url pattern will stall unless it's continued, fulfilled or aborted.
*
* <p> <strong>NOTE:</strong> {@link Page#route Page.route()} will not intercept requests intercepted by Service Worker. See <a
* href="https://github.com/microsoft/playwright/issues/1090">this</a> issue. We recommend disabling Service Workers when
* using request interception. Via {@code await context.addInitScript(() => delete window.navigator.serviceWorker);}
*
* <p> An example of a naive handler that aborts all image requests:
* <pre>{@code
* BrowserContext context = browser.newContext();
* context.route("**\/*.{png,jpg,jpeg}", route -> route.abort());
* Page page = context.newPage();
* page.navigate("https://example.com");
* browser.close();
* }</pre>
*
* <p> or the same snippet using a regex pattern instead:
* <pre>{@code
* BrowserContext context = browser.newContext();
* context.route(Pattern.compile("(\\.png$)|(\\.jpg$)"), route -> route.abort());
* Page page = context.newPage();
* page.navigate("https://example.com");
* browser.close();
* }</pre>
*
* <p> It is possible to examine the request to decide the route action. For example, mocking all requests that contain some
* post data, and leaving all other requests as is:
* <pre>{@code
* context.route("/api/**", route -> {
* if (route.request().postData().contains("my-string"))
* route.fulfill(new Route.FulfillOptions().setBody("mocked-data"));
* else
* route.resume();
* });
* }</pre>
*
* <p> Page routes (set up with {@link Page#route Page.route()}) take precedence over browser context routes when request
* matches both handlers.
*
* <p> To remove a route with its handler you can use {@link BrowserContext#unroute BrowserContext.unroute()}.
*
* <p> <strong>NOTE:</strong> Enabling routing disables http cache.
*
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while routing. When a {@code baseURL} via the context
* options was provided and the passed URL is a path, it gets merged via the <a
* href="https://developer.mozilla.org/en-US/docs/Web/API/URL/URL">{@code new URL()}</a> constructor.
* @param handler handler function to route the request.
*/
void route(Pattern url, Consumer<Route> handler, RouteOptions options);
/**
* Routing provides the capability to modify network requests that are made by any page in the browser context. Once route
* is enabled, every request matching the url pattern will stall unless it's continued, fulfilled or aborted.
*
* <p> <strong>NOTE:</strong> {@link Page#route Page.route()} will not intercept requests intercepted by Service Worker. See <a
* href="https://github.com/microsoft/playwright/issues/1090">this</a> issue. We recommend disabling Service Workers when
* using request interception. Via {@code await context.addInitScript(() => delete window.navigator.serviceWorker);}
*
* <p> An example of a naive handler that aborts all image requests:
* <pre>{@code
* BrowserContext context = browser.newContext();
* context.route("**\/*.{png,jpg,jpeg}", route -> route.abort());
* Page page = context.newPage();
* page.navigate("https://example.com");
* browser.close();
* }</pre>
*
* <p> or the same snippet using a regex pattern instead:
* <pre>{@code
* BrowserContext context = browser.newContext();
* context.route(Pattern.compile("(\\.png$)|(\\.jpg$)"), route -> route.abort());
* Page page = context.newPage();
* page.navigate("https://example.com");
* browser.close();
* }</pre>
*
* <p> It is possible to examine the request to decide the route action. For example, mocking all requests that contain some
* post data, and leaving all other requests as is:
* <pre>{@code
* context.route("/api/**", route -> {
* if (route.request().postData().contains("my-string"))
* route.fulfill(new Route.FulfillOptions().setBody("mocked-data"));
* else
* route.resume();
* });
* }</pre>
*
* <p> Page routes (set up with {@link Page#route Page.route()}) take precedence over browser context routes when request
* matches both handlers.
*
* <p> To remove a route with its handler you can use {@link BrowserContext#unroute BrowserContext.unroute()}.
*
* <p> <strong>NOTE:</strong> Enabling routing disables http cache.
*
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while routing. When a {@code baseURL} via the context
* options was provided and the passed URL is a path, it gets merged via the <a
* href="https://developer.mozilla.org/en-US/docs/Web/API/URL/URL">{@code new URL()}</a> constructor.
* @param handler handler function to route the request.
*/
default void route(Predicate<String> url, Consumer<Route> handler) {
route(url, handler, null);
}
/**
* Routing provides the capability to modify network requests that are made by any page in the browser context. Once route
* is enabled, every request matching the url pattern will stall unless it's continued, fulfilled or aborted.
*
* <p> <strong>NOTE:</strong> {@link Page#route Page.route()} will not intercept requests intercepted by Service Worker. See <a
* href="https://github.com/microsoft/playwright/issues/1090">this</a> issue. We recommend disabling Service Workers when
* using request interception. Via {@code await context.addInitScript(() => delete window.navigator.serviceWorker);}
*
* <p> An example of a naive handler that aborts all image requests:
* <pre>{@code
* BrowserContext context = browser.newContext();
* context.route("**\/*.{png,jpg,jpeg}", route -> route.abort());
* Page page = context.newPage();
* page.navigate("https://example.com");
* browser.close();
* }</pre>
*
* <p> or the same snippet using a regex pattern instead:
* <pre>{@code
* BrowserContext context = browser.newContext();
* context.route(Pattern.compile("(\\.png$)|(\\.jpg$)"), route -> route.abort());
* Page page = context.newPage();
* page.navigate("https://example.com");
* browser.close();
* }</pre>
*
* <p> It is possible to examine the request to decide the route action. For example, mocking all requests that contain some
* post data, and leaving all other requests as is:
* <pre>{@code
* context.route("/api/**", route -> {
* if (route.request().postData().contains("my-string"))
* route.fulfill(new Route.FulfillOptions().setBody("mocked-data"));
* else
* route.resume();
* });
* }</pre>
*
* <p> Page routes (set up with {@link Page#route Page.route()}) take precedence over browser context routes when request
* matches both handlers.
*
* <p> To remove a route with its handler you can use {@link BrowserContext#unroute BrowserContext.unroute()}.
*
* <p> <strong>NOTE:</strong> Enabling routing disables http cache.
*
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while routing. When a {@code baseURL} via the context
* options was provided and the passed URL is a path, it gets merged via the <a
* href="https://developer.mozilla.org/en-US/docs/Web/API/URL/URL">{@code new URL()}</a> constructor.
* @param handler handler function to route the request.
*/
void route(Predicate<String> url, Consumer<Route> handler, RouteOptions options);
/**
* This setting will change the default maximum navigation time for the following methods and related shortcuts:
* <ul>
* <li> {@link Page#goBack Page.goBack()}</li>
* <li> {@link Page#goForward Page.goForward()}</li>
* <li> {@link Page#goto Page.goto()}</li>
* <li> {@link Page#navigate Page.navigate()}</li>
* <li> {@link Page#reload Page.reload()}</li>
* <li> {@link Page#setContent Page.setContent()}</li>
* <li> {@link Page#waitForNavigation Page.waitForNavigation()}</li>
@@ -57,14 +57,25 @@ public interface BrowserType {
*/
public Double timeout;
/**
* Additional HTTP headers to be sent with web socket connect request. Optional.
*/
public ConnectOptions setHeaders(Map<String, String> headers) {
this.headers = headers;
return this;
}
/**
* Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going on.
* Defaults to 0.
*/
public ConnectOptions setSlowMo(double slowMo) {
this.slowMo = slowMo;
return this;
}
/**
* Maximum time in milliseconds to wait for the connection to be established. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to
* disable timeout.
*/
public ConnectOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -86,14 +97,25 @@ public interface BrowserType {
*/
public Double timeout;
/**
* Additional HTTP headers to be sent with connect request. Optional.
*/
public ConnectOverCDPOptions setHeaders(Map<String, String> headers) {
this.headers = headers;
return this;
}
/**
* Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going on.
* Defaults to 0.
*/
public ConnectOverCDPOptions setSlowMo(double slowMo) {
this.slowMo = slowMo;
return this;
}
/**
* Maximum time in milliseconds to wait for the connection to be established. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to
* disable timeout.
*/
public ConnectOverCDPOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -122,7 +144,8 @@ public interface BrowserType {
public Boolean devtools;
/**
* If specified, accepted downloads are downloaded into this directory. Otherwise, temporary directory is created and is
* deleted when browser is closed.
* deleted when browser is closed. In either case, the downloads are deleted when the browser context they were created in
* is closed.
*/
public Path downloadsPath;
/**
@@ -187,82 +210,159 @@ public interface BrowserType {
*/
public Path tracesDir;
/**
* Additional arguments to pass to the browser instance. The list of Chromium flags can be found <a
* href="http://peter.sh/experiments/chromium-command-line-switches/">here</a>.
*/
public LaunchOptions setArgs(List<String> args) {
this.args = args;
return this;
}
@Deprecated
/**
* Browser distribution channel. Supported values are "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge",
* "msedge-beta", "msedge-dev", "msedge-canary". Read more about using <a
* href="https://playwright.dev/java/docs/browsers/#google-chrome--microsoft-edge">Google Chrome and Microsoft Edge</a>.
*/
public LaunchOptions setChannel(BrowserChannel channel) {
this.channel = channel;
return this;
}
/**
* Browser distribution channel. Supported values are "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge",
* "msedge-beta", "msedge-dev", "msedge-canary". Read more about using <a
* href="https://playwright.dev/java/docs/browsers/#google-chrome--microsoft-edge">Google Chrome and Microsoft Edge</a>.
*/
public LaunchOptions setChannel(String channel) {
this.channel = channel;
return this;
}
/**
* Enable Chromium sandboxing. Defaults to {@code false}.
*/
public LaunchOptions setChromiumSandbox(boolean chromiumSandbox) {
this.chromiumSandbox = chromiumSandbox;
return this;
}
/**
* **Chromium-only** Whether to auto-open a Developer Tools panel for each tab. If this option is {@code true}, the {@code headless}
* option will be set {@code false}.
*/
public LaunchOptions setDevtools(boolean devtools) {
this.devtools = devtools;
return this;
}
/**
* If specified, accepted downloads are downloaded into this directory. Otherwise, temporary directory is created and is
* deleted when browser is closed. In either case, the downloads are deleted when the browser context they were created in
* is closed.
*/
public LaunchOptions setDownloadsPath(Path downloadsPath) {
this.downloadsPath = downloadsPath;
return this;
}
/**
* Specify environment variables that will be visible to the browser. Defaults to {@code process.env}.
*/
public LaunchOptions setEnv(Map<String, String> env) {
this.env = env;
return this;
}
/**
* Path to a browser executable to run instead of the bundled one. If {@code executablePath} is a relative path, then it is
* resolved relative to the current working directory. Note that Playwright only works with the bundled Chromium, Firefox
* or WebKit, use at your own risk.
*/
public LaunchOptions setExecutablePath(Path executablePath) {
this.executablePath = executablePath;
return this;
}
/**
* Firefox user preferences. Learn more about the Firefox user preferences at <a
* href="https://support.mozilla.org/en-US/kb/about-config-editor-firefox">{@code about:config}</a>.
*/
public LaunchOptions setFirefoxUserPrefs(Map<String, Object> firefoxUserPrefs) {
this.firefoxUserPrefs = firefoxUserPrefs;
return this;
}
/**
* Close the browser process on SIGHUP. Defaults to {@code true}.
*/
public LaunchOptions setHandleSIGHUP(boolean handleSIGHUP) {
this.handleSIGHUP = handleSIGHUP;
return this;
}
/**
* Close the browser process on Ctrl-C. Defaults to {@code true}.
*/
public LaunchOptions setHandleSIGINT(boolean handleSIGINT) {
this.handleSIGINT = handleSIGINT;
return this;
}
/**
* Close the browser process on SIGTERM. Defaults to {@code true}.
*/
public LaunchOptions setHandleSIGTERM(boolean handleSIGTERM) {
this.handleSIGTERM = handleSIGTERM;
return this;
}
/**
* Whether to run browser in headless mode. More details for <a
* href="https://developers.google.com/web/updates/2017/04/headless-chrome">Chromium</a> and <a
* href="https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Headless_mode">Firefox</a>. Defaults to {@code true} unless the
* {@code devtools} option is {@code true}.
*/
public LaunchOptions setHeadless(boolean headless) {
this.headless = headless;
return this;
}
/**
* If {@code true}, Playwright does not pass its own configurations args and only uses the ones from {@code args}. Dangerous option;
* use with care. Defaults to {@code false}.
*/
public LaunchOptions setIgnoreAllDefaultArgs(boolean ignoreAllDefaultArgs) {
this.ignoreAllDefaultArgs = ignoreAllDefaultArgs;
return this;
}
/**
* If {@code true}, Playwright does not pass its own configurations args and only uses the ones from {@code args}. Dangerous option;
* use with care.
*/
public LaunchOptions setIgnoreDefaultArgs(List<String> ignoreDefaultArgs) {
this.ignoreDefaultArgs = ignoreDefaultArgs;
return this;
}
/**
* Network proxy settings.
*/
public LaunchOptions setProxy(String server) {
return setProxy(new Proxy(server));
}
/**
* Network proxy settings.
*/
public LaunchOptions setProxy(Proxy proxy) {
this.proxy = proxy;
return this;
}
/**
* Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going on.
*/
public LaunchOptions setSlowMo(double slowMo) {
this.slowMo = slowMo;
return this;
}
/**
* Maximum time in milliseconds to wait for the browser instance to start. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to
* disable timeout.
*/
public LaunchOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
}
/**
* If specified, traces are saved into this directory.
*/
public LaunchOptions setTracesDir(Path tracesDir) {
this.tracesDir = tracesDir;
return this;
@@ -279,10 +379,11 @@ public interface BrowserType {
*/
public List<String> args;
/**
* When using {@link Page#goto Page.goto()}, {@link Page#route Page.route()}, {@link Page#waitForURL Page.waitForURL()},
* {@link Page#waitForRequest Page.waitForRequest()}, or {@link Page#waitForResponse Page.waitForResponse()} it takes the
* base URL in consideration by using the <a href="https://developer.mozilla.org/en-US/docs/Web/API/URL/URL">{@code URL()}</a>
* constructor for building the corresponding URL. Examples:
* When using {@link Page#navigate Page.navigate()}, {@link Page#route Page.route()}, {@link Page#waitForURL
* Page.waitForURL()}, {@link Page#waitForRequest Page.waitForRequest()}, or {@link Page#waitForResponse
* Page.waitForResponse()} it takes the base URL in consideration by using the <a
* href="https://developer.mozilla.org/en-US/docs/Web/API/URL/URL">{@code URL()}</a> constructor for building the corresponding
* URL. Examples:
* <ul>
* <li> baseURL: {@code http://localhost:3000} and navigating to {@code /bar.html} results in {@code http://localhost:3000/bar.html}</li>
* <li> baseURL: {@code http://localhost:3000/foo/} and navigating to {@code ./bar.html} results in {@code http://localhost:3000/foo/bar.html}</li>
@@ -319,7 +420,8 @@ public interface BrowserType {
public Boolean devtools;
/**
* If specified, accepted downloads are downloaded into this directory. Otherwise, temporary directory is created and is
* deleted when browser is closed.
* deleted when browser is closed. In either case, the downloads are deleted when the browser context they were created in
* is closed.
*/
public Path downloadsPath;
/**
@@ -333,9 +435,17 @@ public interface BrowserType {
*/
public Path executablePath;
/**
* An object containing additional HTTP headers to be sent with every request. All header values must be strings.
* An object containing additional HTTP headers to be sent with every request.
*/
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"}.
*
* <p> <strong>NOTE:</strong> It's not supported in WebKit, see <a href="https://bugs.webkit.org/show_bug.cgi?id=225281">here</a> in their issue
* tracker.
*/
public ForcedColors forcedColors;
public Geolocation geolocation;
/**
* Close the browser process on SIGHUP. Defaults to {@code true}.
@@ -375,7 +485,7 @@ public interface BrowserType {
*/
public List<String> ignoreDefaultArgs;
/**
* Whether to ignore HTTPS errors during navigation. Defaults to {@code false}.
* Whether to ignore HTTPS errors when sending network requests. Defaults to {@code false}.
*/
public Boolean ignoreHTTPSErrors;
/**
@@ -440,6 +550,12 @@ public interface BrowserType {
* Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going on.
*/
public Double slowMo;
/**
* It specified, enables strict selectors mode for this context. In the strict selectors mode all operations on selectors
* that imply single target DOM element will throw when more than one element matches the selector. See {@code Locator} to learn
* more about the strict mode.
*/
public Boolean strictSelectors;
/**
* Maximum time in milliseconds to wait for the browser instance to start. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to
* disable timeout.
@@ -464,63 +580,135 @@ public interface BrowserType {
*/
public Optional<ViewportSize> viewportSize;
/**
* Whether to automatically download all the attachments. Defaults to {@code false} where all the downloads are canceled.
*/
public LaunchPersistentContextOptions setAcceptDownloads(boolean acceptDownloads) {
this.acceptDownloads = acceptDownloads;
return this;
}
/**
* Additional arguments to pass to the browser instance. The list of Chromium flags can be found <a
* href="http://peter.sh/experiments/chromium-command-line-switches/">here</a>.
*/
public LaunchPersistentContextOptions setArgs(List<String> args) {
this.args = args;
return this;
}
/**
* When using {@link Page#navigate Page.navigate()}, {@link Page#route Page.route()}, {@link Page#waitForURL
* Page.waitForURL()}, {@link Page#waitForRequest Page.waitForRequest()}, or {@link Page#waitForResponse
* Page.waitForResponse()} it takes the base URL in consideration by using the <a
* href="https://developer.mozilla.org/en-US/docs/Web/API/URL/URL">{@code URL()}</a> constructor for building the corresponding
* URL. Examples:
* <ul>
* <li> baseURL: {@code http://localhost:3000} and navigating to {@code /bar.html} results in {@code http://localhost:3000/bar.html}</li>
* <li> baseURL: {@code http://localhost:3000/foo/} and navigating to {@code ./bar.html} results in {@code http://localhost:3000/foo/bar.html}</li>
* </ul>
*/
public LaunchPersistentContextOptions setBaseURL(String baseURL) {
this.baseURL = baseURL;
return this;
}
/**
* Toggles bypassing page's Content-Security-Policy.
*/
public LaunchPersistentContextOptions setBypassCSP(boolean bypassCSP) {
this.bypassCSP = bypassCSP;
return this;
}
@Deprecated
/**
* Browser distribution channel. Supported values are "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge",
* "msedge-beta", "msedge-dev", "msedge-canary". Read more about using <a
* href="https://playwright.dev/java/docs/browsers/#google-chrome--microsoft-edge">Google Chrome and Microsoft Edge</a>.
*/
public LaunchPersistentContextOptions setChannel(BrowserChannel channel) {
this.channel = channel;
return this;
}
/**
* Browser distribution channel. Supported values are "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge",
* "msedge-beta", "msedge-dev", "msedge-canary". Read more about using <a
* href="https://playwright.dev/java/docs/browsers/#google-chrome--microsoft-edge">Google Chrome and Microsoft Edge</a>.
*/
public LaunchPersistentContextOptions setChannel(String channel) {
this.channel = channel;
return this;
}
/**
* Enable Chromium sandboxing. Defaults to {@code false}.
*/
public LaunchPersistentContextOptions setChromiumSandbox(boolean chromiumSandbox) {
this.chromiumSandbox = chromiumSandbox;
return this;
}
/**
* 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"}.
*/
public LaunchPersistentContextOptions setColorScheme(ColorScheme colorScheme) {
this.colorScheme = colorScheme;
return this;
}
/**
* Specify device scale factor (can be thought of as dpr). Defaults to {@code 1}.
*/
public LaunchPersistentContextOptions setDeviceScaleFactor(double deviceScaleFactor) {
this.deviceScaleFactor = deviceScaleFactor;
return this;
}
/**
* **Chromium-only** Whether to auto-open a Developer Tools panel for each tab. If this option is {@code true}, the {@code headless}
* option will be set {@code false}.
*/
public LaunchPersistentContextOptions setDevtools(boolean devtools) {
this.devtools = devtools;
return this;
}
/**
* If specified, accepted downloads are downloaded into this directory. Otherwise, temporary directory is created and is
* deleted when browser is closed. In either case, the downloads are deleted when the browser context they were created in
* is closed.
*/
public LaunchPersistentContextOptions setDownloadsPath(Path downloadsPath) {
this.downloadsPath = downloadsPath;
return this;
}
/**
* Specify environment variables that will be visible to the browser. Defaults to {@code process.env}.
*/
public LaunchPersistentContextOptions setEnv(Map<String, String> env) {
this.env = env;
return this;
}
/**
* Path to a browser executable to run instead of the bundled one. If {@code executablePath} is a relative path, then it is
* resolved relative to the current working directory. Note that Playwright only works with the bundled Chromium, Firefox
* or WebKit, use at your own risk.
*/
public LaunchPersistentContextOptions setExecutablePath(Path executablePath) {
this.executablePath = executablePath;
return this;
}
/**
* An object containing additional HTTP headers to be sent with every request.
*/
public LaunchPersistentContextOptions setExtraHTTPHeaders(Map<String, String> extraHTTPHeaders) {
this.extraHTTPHeaders = extraHTTPHeaders;
return this;
}
/**
* 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"}.
*
* <p> <strong>NOTE:</strong> It's not supported in WebKit, see <a href="https://bugs.webkit.org/show_bug.cgi?id=225281">here</a> in their issue
* tracker.
*/
public LaunchPersistentContextOptions setForcedColors(ForcedColors forcedColors) {
this.forcedColors = forcedColors;
return this;
}
public LaunchPersistentContextOptions setGeolocation(double latitude, double longitude) {
return setGeolocation(new Geolocation(latitude, longitude));
}
@@ -528,125 +716,251 @@ public interface BrowserType {
this.geolocation = geolocation;
return this;
}
/**
* Close the browser process on SIGHUP. Defaults to {@code true}.
*/
public LaunchPersistentContextOptions setHandleSIGHUP(boolean handleSIGHUP) {
this.handleSIGHUP = handleSIGHUP;
return this;
}
/**
* Close the browser process on Ctrl-C. Defaults to {@code true}.
*/
public LaunchPersistentContextOptions setHandleSIGINT(boolean handleSIGINT) {
this.handleSIGINT = handleSIGINT;
return this;
}
/**
* Close the browser process on SIGTERM. Defaults to {@code true}.
*/
public LaunchPersistentContextOptions setHandleSIGTERM(boolean handleSIGTERM) {
this.handleSIGTERM = handleSIGTERM;
return this;
}
/**
* Specifies if viewport supports touch events. Defaults to false.
*/
public LaunchPersistentContextOptions setHasTouch(boolean hasTouch) {
this.hasTouch = hasTouch;
return this;
}
/**
* Whether to run browser in headless mode. More details for <a
* href="https://developers.google.com/web/updates/2017/04/headless-chrome">Chromium</a> and <a
* href="https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Headless_mode">Firefox</a>. Defaults to {@code true} unless the
* {@code devtools} option is {@code true}.
*/
public LaunchPersistentContextOptions setHeadless(boolean headless) {
this.headless = headless;
return this;
}
/**
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>.
*/
public LaunchPersistentContextOptions setHttpCredentials(String username, String password) {
return setHttpCredentials(new HttpCredentials(username, password));
}
/**
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>.
*/
public LaunchPersistentContextOptions setHttpCredentials(HttpCredentials httpCredentials) {
this.httpCredentials = httpCredentials;
return this;
}
/**
* If {@code true}, Playwright does not pass its own configurations args and only uses the ones from {@code args}. Dangerous option;
* use with care. Defaults to {@code false}.
*/
public LaunchPersistentContextOptions setIgnoreAllDefaultArgs(boolean ignoreAllDefaultArgs) {
this.ignoreAllDefaultArgs = ignoreAllDefaultArgs;
return this;
}
/**
* If {@code true}, Playwright does not pass its own configurations args and only uses the ones from {@code args}. Dangerous option;
* use with care.
*/
public LaunchPersistentContextOptions setIgnoreDefaultArgs(List<String> ignoreDefaultArgs) {
this.ignoreDefaultArgs = ignoreDefaultArgs;
return this;
}
/**
* Whether to ignore HTTPS errors when sending network requests. Defaults to {@code false}.
*/
public LaunchPersistentContextOptions setIgnoreHTTPSErrors(boolean ignoreHTTPSErrors) {
this.ignoreHTTPSErrors = ignoreHTTPSErrors;
return this;
}
/**
* Whether the {@code meta viewport} tag is taken into account and touch events are enabled. Defaults to {@code false}. Not supported
* in Firefox.
*/
public LaunchPersistentContextOptions setIsMobile(boolean isMobile) {
this.isMobile = isMobile;
return this;
}
/**
* Whether or not to enable JavaScript in the context. Defaults to {@code true}.
*/
public LaunchPersistentContextOptions setJavaScriptEnabled(boolean javaScriptEnabled) {
this.javaScriptEnabled = javaScriptEnabled;
return this;
}
/**
* Specify user locale, for example {@code en-GB}, {@code de-DE}, etc. Locale will affect {@code navigator.language} value, {@code Accept-Language}
* request header value as well as number and date formatting rules.
*/
public LaunchPersistentContextOptions setLocale(String locale) {
this.locale = locale;
return this;
}
/**
* Whether to emulate network being offline. Defaults to {@code false}.
*/
public LaunchPersistentContextOptions setOffline(boolean offline) {
this.offline = offline;
return this;
}
/**
* A list of permissions to grant to all pages in this context. See {@link BrowserContext#grantPermissions
* BrowserContext.grantPermissions()} for more details.
*/
public LaunchPersistentContextOptions setPermissions(List<String> permissions) {
this.permissions = permissions;
return this;
}
/**
* Network proxy settings.
*/
public LaunchPersistentContextOptions setProxy(String server) {
return setProxy(new Proxy(server));
}
/**
* Network proxy settings.
*/
public LaunchPersistentContextOptions setProxy(Proxy proxy) {
this.proxy = proxy;
return this;
}
/**
* Optional setting to control whether to omit request content from the HAR. Defaults to {@code false}.
*/
public LaunchPersistentContextOptions setRecordHarOmitContent(boolean recordHarOmitContent) {
this.recordHarOmitContent = recordHarOmitContent;
return this;
}
/**
* Enables <a href="http://www.softwareishard.com/blog/har-12-spec">HAR</a> recording for all pages into the specified HAR
* file on the filesystem. If not specified, the HAR is not recorded. Make sure to call {@link BrowserContext#close
* BrowserContext.close()} for the HAR to be saved.
*/
public LaunchPersistentContextOptions setRecordHarPath(Path recordHarPath) {
this.recordHarPath = recordHarPath;
return this;
}
/**
* Enables video recording for all pages into the specified directory. If not specified videos are not recorded. Make sure
* to call {@link BrowserContext#close BrowserContext.close()} for videos to be saved.
*/
public LaunchPersistentContextOptions setRecordVideoDir(Path recordVideoDir) {
this.recordVideoDir = recordVideoDir;
return this;
}
/**
* Dimensions of the recorded videos. If not specified the size will be equal to {@code viewport} scaled down to fit into
* 800x800. If {@code viewport} is not configured explicitly the video size defaults to 800x450. Actual picture of each page will
* be scaled down if necessary to fit the specified size.
*/
public LaunchPersistentContextOptions setRecordVideoSize(int width, int height) {
return setRecordVideoSize(new RecordVideoSize(width, height));
}
/**
* Dimensions of the recorded videos. If not specified the size will be equal to {@code viewport} scaled down to fit into
* 800x800. If {@code viewport} is not configured explicitly the video size defaults to 800x450. Actual picture of each page will
* be scaled down if necessary to fit the specified size.
*/
public LaunchPersistentContextOptions setRecordVideoSize(RecordVideoSize recordVideoSize) {
this.recordVideoSize = recordVideoSize;
return this;
}
/**
* 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"}.
*/
public LaunchPersistentContextOptions setReducedMotion(ReducedMotion reducedMotion) {
this.reducedMotion = reducedMotion;
return this;
}
/**
* Emulates consistent window screen size available inside web page via {@code window.screen}. Is only used when the {@code viewport}
* is set.
*/
public LaunchPersistentContextOptions setScreenSize(int width, int height) {
return setScreenSize(new ScreenSize(width, height));
}
/**
* Emulates consistent window screen size available inside web page via {@code window.screen}. Is only used when the {@code viewport}
* is set.
*/
public LaunchPersistentContextOptions setScreenSize(ScreenSize screenSize) {
this.screenSize = screenSize;
return this;
}
/**
* Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going on.
*/
public LaunchPersistentContextOptions setSlowMo(double slowMo) {
this.slowMo = slowMo;
return this;
}
/**
* It specified, enables strict selectors mode for this context. In the strict selectors mode all operations on selectors
* that imply single target DOM element will throw when more than one element matches the selector. See {@code Locator} to learn
* more about the strict mode.
*/
public LaunchPersistentContextOptions setStrictSelectors(boolean strictSelectors) {
this.strictSelectors = strictSelectors;
return this;
}
/**
* Maximum time in milliseconds to wait for the browser instance to start. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to
* disable timeout.
*/
public LaunchPersistentContextOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
}
/**
* Changes the timezone of the context. See <a
* href="https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1">ICU's
* metaZones.txt</a> for a list of supported timezone IDs.
*/
public LaunchPersistentContextOptions setTimezoneId(String timezoneId) {
this.timezoneId = timezoneId;
return this;
}
/**
* If specified, traces are saved into this directory.
*/
public LaunchPersistentContextOptions setTracesDir(Path tracesDir) {
this.tracesDir = tracesDir;
return this;
}
/**
* Specific user agent to use in this context.
*/
public LaunchPersistentContextOptions setUserAgent(String userAgent) {
this.userAgent = userAgent;
return this;
}
/**
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. {@code null} disables the default viewport.
*/
public LaunchPersistentContextOptions setViewportSize(int width, int height) {
return setViewportSize(new ViewportSize(width, height));
}
/**
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. {@code null} disables the default viewport.
*/
public LaunchPersistentContextOptions setViewportSize(ViewportSize viewportSize) {
this.viewportSize = Optional.ofNullable(viewportSize);
return this;
@@ -19,11 +19,11 @@ package com.microsoft.playwright;
import java.util.*;
/**
* {@code ConsoleMessage} objects are dispatched by page via the {@link Page#onConsole Page.onConsole()} event.
* {@code ConsoleMessage} objects are dispatched by page via the {@link Page#onConsoleMessage Page.onConsoleMessage()} event.
*/
public interface ConsoleMessage {
/**
* List of arguments passed to a {@code console} function call. See also {@link Page#onConsole Page.onConsole()}.
* List of arguments passed to a {@code console} function call. See also {@link Page#onConsoleMessage Page.onConsoleMessage()}.
*/
List<JSHandle> args();
/**
@@ -89,25 +89,52 @@ public interface ElementHandle extends JSHandle {
*/
public Boolean trial;
/**
* Whether to bypass the <a href="https://playwright.dev/java/docs/actionability/">actionability</a> checks. Defaults to
* {@code false}.
*/
public CheckOptions 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 CheckOptions 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.
*/
public CheckOptions setPosition(double x, double y) {
return setPosition(new Position(x, y));
}
/**
* A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of the
* element.
*/
public CheckOptions setPosition(Position position) {
this.position = position;
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 CheckOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
}
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public CheckOptions setTrial(boolean trial) {
this.trial = trial;
return this;
@@ -160,41 +187,81 @@ public interface ElementHandle extends JSHandle {
*/
public Boolean trial;
/**
* Defaults to {@code left}.
*/
public ClickOptions setButton(MouseButton button) {
this.button = button;
return this;
}
/**
* defaults to 1. See [UIEvent.detail].
*/
public ClickOptions setClickCount(int clickCount) {
this.clickCount = clickCount;
return this;
}
/**
* Time to wait between {@code mousedown} and {@code mouseup} in milliseconds. Defaults to 0.
*/
public ClickOptions setDelay(double delay) {
this.delay = delay;
return this;
}
/**
* Whether to bypass the <a href="https://playwright.dev/java/docs/actionability/">actionability</a> checks. Defaults to
* {@code false}.
*/
public ClickOptions setForce(boolean force) {
this.force = force;
return this;
}
/**
* Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores current
* modifiers back. If not specified, currently pressed modifiers are used.
*/
public ClickOptions setModifiers(List<KeyboardModifier> modifiers) {
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 ClickOptions 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.
*/
public ClickOptions setPosition(double x, double y) {
return setPosition(new Position(x, y));
}
/**
* A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of the
* element.
*/
public ClickOptions setPosition(Position position) {
this.position = position;
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 ClickOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
}
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public ClickOptions setTrial(boolean trial) {
this.trial = trial;
return this;
@@ -243,37 +310,74 @@ public interface ElementHandle extends JSHandle {
*/
public Boolean trial;
/**
* Defaults to {@code left}.
*/
public DblclickOptions setButton(MouseButton button) {
this.button = button;
return this;
}
/**
* Time to wait between {@code mousedown} and {@code mouseup} in milliseconds. Defaults to 0.
*/
public DblclickOptions setDelay(double delay) {
this.delay = delay;
return this;
}
/**
* Whether to bypass the <a href="https://playwright.dev/java/docs/actionability/">actionability</a> checks. Defaults to
* {@code false}.
*/
public DblclickOptions setForce(boolean force) {
this.force = force;
return this;
}
/**
* Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores current
* modifiers back. If not specified, currently pressed modifiers are used.
*/
public DblclickOptions setModifiers(List<KeyboardModifier> modifiers) {
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 DblclickOptions 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.
*/
public DblclickOptions setPosition(double x, double y) {
return setPosition(new Position(x, y));
}
/**
* A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of the
* element.
*/
public DblclickOptions setPosition(Position position) {
this.position = position;
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 DblclickOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
}
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public DblclickOptions setTrial(boolean trial) {
this.trial = trial;
return this;
@@ -298,14 +402,28 @@ public interface ElementHandle extends JSHandle {
*/
public Double timeout;
/**
* Whether to bypass the <a href="https://playwright.dev/java/docs/actionability/">actionability</a> checks. Defaults to
* {@code false}.
*/
public FillOptions 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 FillOptions 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 FillOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -340,25 +458,51 @@ public interface ElementHandle extends JSHandle {
*/
public Boolean trial;
/**
* Whether to bypass the <a href="https://playwright.dev/java/docs/actionability/">actionability</a> checks. Defaults to
* {@code false}.
*/
public HoverOptions setForce(boolean force) {
this.force = force;
return this;
}
/**
* Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores current
* modifiers back. If not specified, currently pressed modifiers are used.
*/
public HoverOptions setModifiers(List<KeyboardModifier> modifiers) {
this.modifiers = modifiers;
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.
*/
public HoverOptions setPosition(double x, double y) {
return setPosition(new Position(x, y));
}
/**
* A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of the
* element.
*/
public HoverOptions setPosition(Position position) {
this.position = position;
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 HoverOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
}
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public HoverOptions setTrial(boolean trial) {
this.trial = trial;
return this;
@@ -372,6 +516,11 @@ public interface ElementHandle extends JSHandle {
*/
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 InputValueOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -395,14 +544,27 @@ public interface ElementHandle extends JSHandle {
*/
public Double timeout;
/**
* Time to wait between {@code keydown} and {@code keyup} in milliseconds. Defaults to 0.
*/
public PressOptions setDelay(double delay) {
this.delay = delay;
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 PressOptions 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 PressOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -435,22 +597,42 @@ public interface ElementHandle extends JSHandle {
*/
public ScreenshotType type;
/**
* Hides default white background and allows capturing screenshots with transparency. Not applicable to {@code jpeg} images.
* Defaults to {@code false}.
*/
public ScreenshotOptions setOmitBackground(boolean omitBackground) {
this.omitBackground = omitBackground;
return this;
}
/**
* The file path to save the image to. The screenshot type will be inferred from file extension. If {@code path} is a relative
* path, then it is resolved relative to the current working directory. If no path is provided, the image won't be saved to
* the disk.
*/
public ScreenshotOptions setPath(Path path) {
this.path = path;
return this;
}
/**
* The quality of the image, between 0-100. Not applicable to {@code png} images.
*/
public ScreenshotOptions setQuality(int quality) {
this.quality = quality;
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 ScreenshotOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
}
/**
* Specify screenshot type, defaults to {@code png}.
*/
public ScreenshotOptions setType(ScreenshotType type) {
this.type = type;
return this;
@@ -464,6 +646,11 @@ public interface ElementHandle extends JSHandle {
*/
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 ScrollIntoViewIfNeededOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -488,14 +675,28 @@ public interface ElementHandle extends JSHandle {
*/
public Double timeout;
/**
* Whether to bypass the <a href="https://playwright.dev/java/docs/actionability/">actionability</a> checks. Defaults to
* {@code false}.
*/
public SelectOptionOptions 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 SelectOptionOptions 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 SelectOptionOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -514,15 +715,105 @@ public interface ElementHandle extends JSHandle {
*/
public Double timeout;
/**
* Whether to bypass the <a href="https://playwright.dev/java/docs/actionability/">actionability</a> checks. Defaults to
* {@code false}.
*/
public SelectTextOptions setForce(boolean force) {
this.force = force;
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 SelectTextOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
class SetCheckedOptions {
/**
* 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;
/**
* A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of the
* element.
*/
public Position position;
/**
* 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;
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public Boolean trial;
/**
* Whether to bypass the <a href="https://playwright.dev/java/docs/actionability/">actionability</a> checks. Defaults to
* {@code false}.
*/
public SetCheckedOptions 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 SetCheckedOptions 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.
*/
public SetCheckedOptions setPosition(double x, double y) {
return setPosition(new Position(x, y));
}
/**
* A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of the
* element.
*/
public SetCheckedOptions setPosition(Position position) {
this.position = position;
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 SetCheckedOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
}
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public SetCheckedOptions setTrial(boolean trial) {
this.trial = trial;
return this;
}
}
class SetInputFilesOptions {
/**
* Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can
@@ -537,10 +828,20 @@ public interface ElementHandle extends JSHandle {
*/
public Double timeout;
/**
* 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 SetInputFilesOptions 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 SetInputFilesOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -581,29 +882,60 @@ public interface ElementHandle extends JSHandle {
*/
public Boolean trial;
/**
* Whether to bypass the <a href="https://playwright.dev/java/docs/actionability/">actionability</a> checks. Defaults to
* {@code false}.
*/
public TapOptions setForce(boolean force) {
this.force = force;
return this;
}
/**
* Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores current
* modifiers back. If not specified, currently pressed modifiers are used.
*/
public TapOptions setModifiers(List<KeyboardModifier> modifiers) {
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 TapOptions 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.
*/
public TapOptions setPosition(double x, double y) {
return setPosition(new Position(x, y));
}
/**
* A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of the
* element.
*/
public TapOptions setPosition(Position position) {
this.position = position;
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 TapOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
}
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public TapOptions setTrial(boolean trial) {
this.trial = trial;
return this;
@@ -627,14 +959,27 @@ public interface ElementHandle extends JSHandle {
*/
public Double timeout;
/**
* Time to wait between key presses in milliseconds. Defaults to 0.
*/
public TypeOptions setDelay(double delay) {
this.delay = delay;
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 TypeOptions 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 TypeOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -670,25 +1015,52 @@ public interface ElementHandle extends JSHandle {
*/
public Boolean trial;
/**
* Whether to bypass the <a href="https://playwright.dev/java/docs/actionability/">actionability</a> checks. Defaults to
* {@code false}.
*/
public UncheckOptions 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 UncheckOptions 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.
*/
public UncheckOptions setPosition(double x, double y) {
return setPosition(new Position(x, y));
}
/**
* A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of the
* element.
*/
public UncheckOptions setPosition(Position position) {
this.position = position;
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 UncheckOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
}
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public UncheckOptions setTrial(boolean trial) {
this.trial = trial;
return this;
@@ -702,6 +1074,11 @@ public interface ElementHandle extends JSHandle {
*/
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 WaitForElementStateOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -720,6 +1097,11 @@ public interface ElementHandle extends JSHandle {
* </ul>
*/
public WaitForSelectorState state;
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
public Boolean strict;
/**
* 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
@@ -727,10 +1109,34 @@ public interface ElementHandle extends JSHandle {
*/
public Double timeout;
/**
* Defaults to {@code "visible"}. Can be either:
* <ul>
* <li> {@code "attached"} - wait for element to be present in DOM.</li>
* <li> {@code "detached"} - wait for element to not be present in DOM.</li>
* <li> {@code "visible"} - wait for element to have non-empty bounding box and no {@code visibility:hidden}. Note that element without any
* content or with {@code display:none} has an empty bounding box and is not considered visible.</li>
* <li> {@code "hidden"} - wait for element to be either detached from DOM, or have an empty bounding box or {@code visibility:hidden}. This
* is opposite to the {@code "visible"} option.</li>
* </ul>
*/
public WaitForSelectorOptions setState(WaitForSelectorState state) {
this.state = state;
return this;
}
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
public WaitForSelectorOptions setStrict(boolean strict) {
this.strict = strict;
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 WaitForSelectorOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -1610,6 +2016,46 @@ public interface ElementHandle extends JSHandle {
* the element and selects all its text content.
*/
void selectText(SelectTextOptions options);
/**
* This method checks or unchecks an element by performing the following steps:
* <ol>
* <li> Ensure that element is a checkbox or a radio input. If not, this method throws.</li>
* <li> If the element already has the right checked state, this method returns immediately.</li>
* <li> Wait for <a href="https://playwright.dev/java/docs/actionability/">actionability</a> checks on the matched element,
* unless {@code force} option is set. If the element is detached during the checks, the whole action is retried.</li>
* <li> Scroll the element into view if needed.</li>
* <li> Use {@link Page#mouse Page.mouse()} to click in the center of the element.</li>
* <li> Wait for initiated navigations to either succeed or fail, unless {@code noWaitAfter} option is set.</li>
* <li> Ensure that the element is now checked or unchecked. If not, this method throws.</li>
* </ol>
*
* <p> When all steps combined have not finished during the specified {@code timeout}, this method throws a {@code TimeoutError}. Passing
* zero timeout disables this.
*
* @param checked Whether to check or uncheck the checkbox.
*/
default void setChecked(boolean checked) {
setChecked(checked, null);
}
/**
* This method checks or unchecks an element by performing the following steps:
* <ol>
* <li> Ensure that element is a checkbox or a radio input. If not, this method throws.</li>
* <li> If the element already has the right checked state, this method returns immediately.</li>
* <li> Wait for <a href="https://playwright.dev/java/docs/actionability/">actionability</a> checks on the matched element,
* unless {@code force} option is set. If the element is detached during the checks, the whole action is retried.</li>
* <li> Scroll the element into view if needed.</li>
* <li> Use {@link Page#mouse Page.mouse()} to click in the center of the element.</li>
* <li> Wait for initiated navigations to either succeed or fail, unless {@code noWaitAfter} option is set.</li>
* <li> Ensure that the element is now checked or unchecked. If not, this method throws.</li>
* </ol>
*
* <p> When all steps combined have not finished during the specified {@code timeout}, this method throws a {@code TimeoutError}. Passing
* zero timeout disables this.
*
* @param checked Whether to check or uncheck the checkbox.
*/
void setChecked(boolean checked, SetCheckedOptions options);
/**
* This method expects {@code elementHandle} to point to an <a
* href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input">input element</a>.
@@ -42,10 +42,20 @@ public interface FileChooser {
*/
public Double timeout;
/**
* 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 SetFilesOptions 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 SetFilesOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
File diff suppressed because it is too large Load Diff
@@ -60,6 +60,9 @@ public interface Keyboard {
*/
public Double delay;
/**
* Time to wait between {@code keydown} and {@code keyup} in milliseconds. Defaults to 0.
*/
public PressOptions setDelay(double delay) {
this.delay = delay;
return this;
@@ -71,6 +74,9 @@ public interface Keyboard {
*/
public Double delay;
/**
* Time to wait between key presses in milliseconds. Defaults to 0.
*/
public TypeOptions setDelay(double delay) {
this.delay = delay;
return this;
@@ -47,6 +47,21 @@ import java.util.*;
* locator.hover();
* locator.click();
* }</pre>
*
* <p> **Strictness**
*
* <p> Locators are strict. This means that all operations on locators that imply some target DOM element will throw if more
* than one element matches given selector.
* <pre>{@code
* // Throws if there are several buttons in DOM:
* page.locator("button").click();
*
* // Works because we explicitly tell locator to pick the first element:
* page.locator("button").first().click();
*
* // Works because count knows what to do with multiple matches:
* page.locator("button").count();
* }</pre>
*/
public interface Locator {
class BoundingBoxOptions {
@@ -57,6 +72,11 @@ public interface Locator {
*/
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 BoundingBoxOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -92,25 +112,52 @@ public interface Locator {
*/
public Boolean trial;
/**
* Whether to bypass the <a href="https://playwright.dev/java/docs/actionability/">actionability</a> checks. Defaults to
* {@code false}.
*/
public CheckOptions 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 CheckOptions 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.
*/
public CheckOptions setPosition(double x, double y) {
return setPosition(new Position(x, y));
}
/**
* A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of the
* element.
*/
public CheckOptions setPosition(Position position) {
this.position = position;
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 CheckOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
}
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public CheckOptions setTrial(boolean trial) {
this.trial = trial;
return this;
@@ -163,41 +210,81 @@ public interface Locator {
*/
public Boolean trial;
/**
* Defaults to {@code left}.
*/
public ClickOptions setButton(MouseButton button) {
this.button = button;
return this;
}
/**
* defaults to 1. See [UIEvent.detail].
*/
public ClickOptions setClickCount(int clickCount) {
this.clickCount = clickCount;
return this;
}
/**
* Time to wait between {@code mousedown} and {@code mouseup} in milliseconds. Defaults to 0.
*/
public ClickOptions setDelay(double delay) {
this.delay = delay;
return this;
}
/**
* Whether to bypass the <a href="https://playwright.dev/java/docs/actionability/">actionability</a> checks. Defaults to
* {@code false}.
*/
public ClickOptions setForce(boolean force) {
this.force = force;
return this;
}
/**
* Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores current
* modifiers back. If not specified, currently pressed modifiers are used.
*/
public ClickOptions setModifiers(List<KeyboardModifier> modifiers) {
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 ClickOptions 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.
*/
public ClickOptions setPosition(double x, double y) {
return setPosition(new Position(x, y));
}
/**
* A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of the
* element.
*/
public ClickOptions setPosition(Position position) {
this.position = position;
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 ClickOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
}
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public ClickOptions setTrial(boolean trial) {
this.trial = trial;
return this;
@@ -246,37 +333,74 @@ public interface Locator {
*/
public Boolean trial;
/**
* Defaults to {@code left}.
*/
public DblclickOptions setButton(MouseButton button) {
this.button = button;
return this;
}
/**
* Time to wait between {@code mousedown} and {@code mouseup} in milliseconds. Defaults to 0.
*/
public DblclickOptions setDelay(double delay) {
this.delay = delay;
return this;
}
/**
* Whether to bypass the <a href="https://playwright.dev/java/docs/actionability/">actionability</a> checks. Defaults to
* {@code false}.
*/
public DblclickOptions setForce(boolean force) {
this.force = force;
return this;
}
/**
* Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores current
* modifiers back. If not specified, currently pressed modifiers are used.
*/
public DblclickOptions setModifiers(List<KeyboardModifier> modifiers) {
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 DblclickOptions 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.
*/
public DblclickOptions setPosition(double x, double y) {
return setPosition(new Position(x, y));
}
/**
* A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of the
* element.
*/
public DblclickOptions setPosition(Position position) {
this.position = position;
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 DblclickOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
}
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public DblclickOptions setTrial(boolean trial) {
this.trial = trial;
return this;
@@ -290,6 +414,11 @@ public interface Locator {
*/
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 DispatchEventOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -303,6 +432,11 @@ public interface Locator {
*/
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 ElementHandleOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -316,6 +450,11 @@ public interface Locator {
*/
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 EvaluateOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -329,6 +468,11 @@ public interface Locator {
*/
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 EvaluateHandleOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -353,14 +497,28 @@ public interface Locator {
*/
public Double timeout;
/**
* Whether to bypass the <a href="https://playwright.dev/java/docs/actionability/">actionability</a> checks. Defaults to
* {@code false}.
*/
public FillOptions 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 FillOptions 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 FillOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -374,6 +532,11 @@ public interface Locator {
*/
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 FocusOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -387,6 +550,11 @@ public interface Locator {
*/
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 GetAttributeOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -421,25 +589,51 @@ public interface Locator {
*/
public Boolean trial;
/**
* Whether to bypass the <a href="https://playwright.dev/java/docs/actionability/">actionability</a> checks. Defaults to
* {@code false}.
*/
public HoverOptions setForce(boolean force) {
this.force = force;
return this;
}
/**
* Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores current
* modifiers back. If not specified, currently pressed modifiers are used.
*/
public HoverOptions setModifiers(List<KeyboardModifier> modifiers) {
this.modifiers = modifiers;
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.
*/
public HoverOptions setPosition(double x, double y) {
return setPosition(new Position(x, y));
}
/**
* A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of the
* element.
*/
public HoverOptions setPosition(Position position) {
this.position = position;
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 HoverOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
}
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public HoverOptions setTrial(boolean trial) {
this.trial = trial;
return this;
@@ -453,6 +647,11 @@ public interface Locator {
*/
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 InnerHTMLOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -466,6 +665,11 @@ public interface Locator {
*/
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 InnerTextOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -479,6 +683,11 @@ public interface Locator {
*/
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 InputValueOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -492,6 +701,11 @@ public interface Locator {
*/
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 IsCheckedOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -505,6 +719,11 @@ public interface Locator {
*/
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 IsDisabledOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -518,6 +737,11 @@ public interface Locator {
*/
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 IsEditableOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -531,6 +755,11 @@ public interface Locator {
*/
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 IsEnabledOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -538,12 +767,15 @@ public interface Locator {
}
class IsHiddenOptions {
/**
* 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.
* **DEPRECATED** This option is ignored. {@link Locator#isHidden Locator.isHidden()} does not wait for the element to
* become hidden and returns immediately.
*/
public Double timeout;
/**
* **DEPRECATED** This option is ignored. {@link Locator#isHidden Locator.isHidden()} does not wait for the element to
* become hidden and returns immediately.
*/
public IsHiddenOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -551,12 +783,15 @@ public interface Locator {
}
class IsVisibleOptions {
/**
* 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.
* **DEPRECATED** This option is ignored. {@link Locator#isVisible Locator.isVisible()} does not wait for the element to
* become visible and returns immediately.
*/
public Double timeout;
/**
* **DEPRECATED** This option is ignored. {@link Locator#isVisible Locator.isVisible()} does not wait for the element to
* become visible and returns immediately.
*/
public IsVisibleOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -580,14 +815,27 @@ public interface Locator {
*/
public Double timeout;
/**
* Time to wait between {@code keydown} and {@code keyup} in milliseconds. Defaults to 0.
*/
public PressOptions setDelay(double delay) {
this.delay = delay;
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 PressOptions 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 PressOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -620,22 +868,42 @@ public interface Locator {
*/
public ScreenshotType type;
/**
* Hides default white background and allows capturing screenshots with transparency. Not applicable to {@code jpeg} images.
* Defaults to {@code false}.
*/
public ScreenshotOptions setOmitBackground(boolean omitBackground) {
this.omitBackground = omitBackground;
return this;
}
/**
* The file path to save the image to. The screenshot type will be inferred from file extension. If {@code path} is a relative
* path, then it is resolved relative to the current working directory. If no path is provided, the image won't be saved to
* the disk.
*/
public ScreenshotOptions setPath(Path path) {
this.path = path;
return this;
}
/**
* The quality of the image, between 0-100. Not applicable to {@code png} images.
*/
public ScreenshotOptions setQuality(int quality) {
this.quality = quality;
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 ScreenshotOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
}
/**
* Specify screenshot type, defaults to {@code png}.
*/
public ScreenshotOptions setType(ScreenshotType type) {
this.type = type;
return this;
@@ -649,6 +917,11 @@ public interface Locator {
*/
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 ScrollIntoViewIfNeededOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -673,14 +946,28 @@ public interface Locator {
*/
public Double timeout;
/**
* Whether to bypass the <a href="https://playwright.dev/java/docs/actionability/">actionability</a> checks. Defaults to
* {@code false}.
*/
public SelectOptionOptions 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 SelectOptionOptions 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 SelectOptionOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -699,15 +986,105 @@ public interface Locator {
*/
public Double timeout;
/**
* Whether to bypass the <a href="https://playwright.dev/java/docs/actionability/">actionability</a> checks. Defaults to
* {@code false}.
*/
public SelectTextOptions setForce(boolean force) {
this.force = force;
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 SelectTextOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
class SetCheckedOptions {
/**
* 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;
/**
* A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of the
* element.
*/
public Position position;
/**
* 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;
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public Boolean trial;
/**
* Whether to bypass the <a href="https://playwright.dev/java/docs/actionability/">actionability</a> checks. Defaults to
* {@code false}.
*/
public SetCheckedOptions 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 SetCheckedOptions 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.
*/
public SetCheckedOptions setPosition(double x, double y) {
return setPosition(new Position(x, y));
}
/**
* A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of the
* element.
*/
public SetCheckedOptions setPosition(Position position) {
this.position = position;
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 SetCheckedOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
}
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public SetCheckedOptions setTrial(boolean trial) {
this.trial = trial;
return this;
}
}
class SetInputFilesOptions {
/**
* Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can
@@ -722,10 +1099,20 @@ public interface Locator {
*/
public Double timeout;
/**
* 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 SetInputFilesOptions 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 SetInputFilesOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -766,29 +1153,60 @@ public interface Locator {
*/
public Boolean trial;
/**
* Whether to bypass the <a href="https://playwright.dev/java/docs/actionability/">actionability</a> checks. Defaults to
* {@code false}.
*/
public TapOptions setForce(boolean force) {
this.force = force;
return this;
}
/**
* Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores current
* modifiers back. If not specified, currently pressed modifiers are used.
*/
public TapOptions setModifiers(List<KeyboardModifier> modifiers) {
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 TapOptions 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.
*/
public TapOptions setPosition(double x, double y) {
return setPosition(new Position(x, y));
}
/**
* A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of the
* element.
*/
public TapOptions setPosition(Position position) {
this.position = position;
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 TapOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
}
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public TapOptions setTrial(boolean trial) {
this.trial = trial;
return this;
@@ -802,6 +1220,11 @@ public interface Locator {
*/
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 TextContentOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -825,14 +1248,27 @@ public interface Locator {
*/
public Double timeout;
/**
* Time to wait between key presses in milliseconds. Defaults to 0.
*/
public TypeOptions setDelay(double delay) {
this.delay = delay;
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 TypeOptions 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 TypeOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -868,25 +1304,52 @@ public interface Locator {
*/
public Boolean trial;
/**
* Whether to bypass the <a href="https://playwright.dev/java/docs/actionability/">actionability</a> checks. Defaults to
* {@code false}.
*/
public UncheckOptions 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 UncheckOptions 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.
*/
public UncheckOptions setPosition(double x, double y) {
return setPosition(new Position(x, y));
}
/**
* A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of the
* element.
*/
public UncheckOptions setPosition(Position position) {
this.position = position;
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 UncheckOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
}
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public UncheckOptions setTrial(boolean trial) {
this.trial = trial;
return this;
@@ -1964,6 +2427,46 @@ public interface Locator {
* the element and selects all its text content.
*/
void selectText(SelectTextOptions options);
/**
* This method checks or unchecks an element by performing the following steps:
* <ol>
* <li> Ensure that matched element is a checkbox or a radio input. If not, this method throws.</li>
* <li> If the element already has the right checked state, this method returns immediately.</li>
* <li> Wait for <a href="https://playwright.dev/java/docs/actionability/">actionability</a> checks on the matched element,
* unless {@code force} option is set. If the element is detached during the checks, the whole action is retried.</li>
* <li> Scroll the element into view if needed.</li>
* <li> Use {@link Page#mouse Page.mouse()} to click in the center of the element.</li>
* <li> Wait for initiated navigations to either succeed or fail, unless {@code noWaitAfter} option is set.</li>
* <li> Ensure that the element is now checked or unchecked. If not, this method throws.</li>
* </ol>
*
* <p> When all steps combined have not finished during the specified {@code timeout}, this method throws a {@code TimeoutError}. Passing
* zero timeout disables this.
*
* @param checked Whether to check or uncheck the checkbox.
*/
default void setChecked(boolean checked) {
setChecked(checked, null);
}
/**
* This method checks or unchecks an element by performing the following steps:
* <ol>
* <li> Ensure that matched element is a checkbox or a radio input. If not, this method throws.</li>
* <li> If the element already has the right checked state, this method returns immediately.</li>
* <li> Wait for <a href="https://playwright.dev/java/docs/actionability/">actionability</a> checks on the matched element,
* unless {@code force} option is set. If the element is detached during the checks, the whole action is retried.</li>
* <li> Scroll the element into view if needed.</li>
* <li> Use {@link Page#mouse Page.mouse()} to click in the center of the element.</li>
* <li> Wait for initiated navigations to either succeed or fail, unless {@code noWaitAfter} option is set.</li>
* <li> Ensure that the element is now checked or unchecked. If not, this method throws.</li>
* </ol>
*
* <p> When all steps combined have not finished during the specified {@code timeout}, this method throws a {@code TimeoutError}. Passing
* zero timeout disables this.
*
* @param checked Whether to check or uncheck the checkbox.
*/
void setChecked(boolean checked, SetCheckedOptions options);
/**
* This method expects {@code element} to point to an <a
* href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input">input element</a>.
@@ -49,14 +49,23 @@ public interface Mouse {
*/
public Double delay;
/**
* Defaults to {@code left}.
*/
public ClickOptions setButton(MouseButton button) {
this.button = button;
return this;
}
/**
* defaults to 1. See [UIEvent.detail].
*/
public ClickOptions setClickCount(int clickCount) {
this.clickCount = clickCount;
return this;
}
/**
* Time to wait between {@code mousedown} and {@code mouseup} in milliseconds. Defaults to 0.
*/
public ClickOptions setDelay(double delay) {
this.delay = delay;
return this;
@@ -72,10 +81,16 @@ public interface Mouse {
*/
public Double delay;
/**
* Defaults to {@code left}.
*/
public DblclickOptions setButton(MouseButton button) {
this.button = button;
return this;
}
/**
* Time to wait between {@code mousedown} and {@code mouseup} in milliseconds. Defaults to 0.
*/
public DblclickOptions setDelay(double delay) {
this.delay = delay;
return this;
@@ -91,10 +106,16 @@ public interface Mouse {
*/
public Integer clickCount;
/**
* Defaults to {@code left}.
*/
public DownOptions setButton(MouseButton button) {
this.button = button;
return this;
}
/**
* defaults to 1. See [UIEvent.detail].
*/
public DownOptions setClickCount(int clickCount) {
this.clickCount = clickCount;
return this;
@@ -106,6 +127,9 @@ public interface Mouse {
*/
public Integer steps;
/**
* defaults to 1. Sends intermediate {@code mousemove} events.
*/
public MoveOptions setSteps(int steps) {
this.steps = steps;
return this;
@@ -121,10 +145,16 @@ public interface Mouse {
*/
public Integer clickCount;
/**
* Defaults to {@code left}.
*/
public UpOptions setButton(MouseButton button) {
this.button = button;
return this;
}
/**
* defaults to 1. See [UIEvent.detail].
*/
public UpOptions setClickCount(int clickCount) {
this.clickCount = clickCount;
return this;
@@ -182,5 +212,15 @@ public interface Mouse {
* Dispatches a {@code mouseup} event.
*/
void up(UpOptions options);
/**
* Dispatches a {@code wheel} event.
*
* <p> <strong>NOTE:</strong> Wheel events may cause scrolling if they are not handled, and this method does not wait for the scrolling to finish
* before returning.
*
* @param deltaX Pixels to scroll horizontally.
* @param deltaY Pixels to scroll vertically.
*/
void wheel(double deltaX, double deltaY);
}
File diff suppressed because it is too large Load Diff
@@ -47,6 +47,10 @@ public interface Playwright extends AutoCloseable {
*/
public Map<String, String> env;
/**
* Additional environment variables that will be passed to the driver process. By default driver process inherits
* environment variables of the Playwright process.
*/
public CreateOptions setEnv(Map<String, String> env) {
this.env = env;
return this;
@@ -38,6 +38,10 @@ import java.util.*;
* request is issued to a redirected url.
*/
public interface Request {
/**
* An object with all the request HTTP headers associated with this request. The header names are lower-cased.
*/
Map<String, String> allHeaders();
/**
* The method returns {@code null} unless this request has failed, as reported by {@code requestfailed} event.
*
@@ -54,9 +58,22 @@ public interface Request {
*/
Frame frame();
/**
* An object with HTTP headers associated with the request. All header names are lower-case.
* **DEPRECATED** Incomplete list of headers as seen by the rendering engine. Use {@link Request#allHeaders
* Request.allHeaders()} instead.
*/
Map<String, String> headers();
/**
* An array with all the request HTTP headers associated with this request. Unlike {@link Request#allHeaders
* Request.allHeaders()}, header names are NOT lower-cased. Headers with multiple entries, such as {@code Set-Cookie}, appear in
* the array multiple times.
*/
List<HttpHeader> headersArray();
/**
* Returns the value of the header matching the name. The name is case insensitive.
*
* @param name Name of the header.
*/
String headerValue(String name);
/**
* Whether this request is driving frame's navigation.
*/
@@ -112,6 +129,10 @@ public interface Request {
* Returns the matching {@code Response} object, or {@code null} if the response was not received due to error.
*/
Response response();
/**
* Returns resource size information for given request.
*/
Sizes sizes();
/**
* Returns resource timing information for given request. Most of the timing values become available upon the response,
* {@code responseEnd} becomes available when request finishes. Find more information at <a
@@ -23,12 +23,16 @@ import java.util.*;
* {@code Response} class represents responses which are received by page.
*/
public interface Response {
/**
* An object with all the response HTTP headers associated with this response.
*/
Map<String, String> allHeaders();
/**
* Returns the buffer with response body.
*/
byte[] body();
/**
* Waits for this response to finish, returns failure error if request failed.
* Waits for this response to finish, returns always {@code null}.
*/
String finished();
/**
@@ -36,9 +40,30 @@ public interface Response {
*/
Frame frame();
/**
* Returns the object with HTTP headers associated with the response. All header names are lower-case.
* **DEPRECATED** Incomplete list of headers as seen by the rendering engine. Use {@link Response#allHeaders
* Response.allHeaders()} instead.
*/
Map<String, String> headers();
/**
* An array with all the request HTTP headers associated with this response. Unlike {@link Response#allHeaders
* Response.allHeaders()}, header names are NOT lower-cased. Headers with multiple entries, such as {@code Set-Cookie}, appear in
* the array multiple times.
*/
List<HttpHeader> headersArray();
/**
* Returns the value of the header matching the name. The name is case insensitive. If multiple headers have the same name
* (except {@code set-cookie}), they are returned as a list separated by {@code , }. For {@code set-cookie}, the {@code \n} separator is used. If
* no headers are found, {@code null} is returned.
*
* @param name Name of the header.
*/
String headerValue(String name);
/**
* Returns all values of the headers matching the name, for example {@code set-cookie}. The name is case insensitive.
*
* @param name Name of the header.
*/
List<String> headerValues(String name);
/**
* Contains a boolean stating whether the response was successful (status in the range 200-299) or not.
*/
@@ -43,22 +43,37 @@ public interface Route {
*/
public String url;
/**
* If set changes the request HTTP headers. Header values will be converted to a string.
*/
public ResumeOptions setHeaders(Map<String, String> headers) {
this.headers = headers;
return this;
}
/**
* If set changes the request method (e.g. GET or POST)
*/
public ResumeOptions setMethod(String method) {
this.method = method;
return this;
}
/**
* If set changes the post data of request
*/
public ResumeOptions setPostData(String postData) {
this.postData = postData;
return this;
}
/**
* If set changes the post data of request
*/
public ResumeOptions setPostData(byte[] postData) {
this.postData = postData;
return this;
}
/**
* If set changes the request URL. New URL must have same protocol as original one.
*/
public ResumeOptions setUrl(String url) {
this.url = url;
return this;
@@ -91,26 +106,45 @@ public interface Route {
*/
public Integer status;
/**
* Optional response body as text.
*/
public FulfillOptions setBody(String body) {
this.body = body;
return this;
}
/**
* Optional response body as raw bytes.
*/
public FulfillOptions setBodyBytes(byte[] bodyBytes) {
this.bodyBytes = bodyBytes;
return this;
}
/**
* If set, equals to setting {@code Content-Type} response header.
*/
public FulfillOptions setContentType(String contentType) {
this.contentType = contentType;
return this;
}
/**
* Response headers. Header values will be converted to a string.
*/
public FulfillOptions setHeaders(Map<String, String> headers) {
this.headers = headers;
return this;
}
/**
* File path to respond with. The content type will be inferred from file extension. If {@code path} is a relative path, then it
* is resolved relative to the current working directory.
*/
public FulfillOptions setPath(Path path) {
this.path = path;
return this;
}
/**
* Response status code, defaults to {@code 200}.
*/
public FulfillOptions setStatus(int status) {
this.status = status;
return this;
@@ -190,7 +224,7 @@ public interface Route {
* <p> An example of serving static file:
* <pre>{@code
* page.route("**\/xhr_endpoint", route -> route.fulfill(
* new Route.FulfillOptions().setPath(Paths.get("mock_data.json")));
* new Route.FulfillOptions().setPath(Paths.get("mock_data.json"))));
* }</pre>
*/
default void fulfill() {
@@ -212,7 +246,7 @@ public interface Route {
* <p> An example of serving static file:
* <pre>{@code
* page.route("**\/xhr_endpoint", route -> route.fulfill(
* new Route.FulfillOptions().setPath(Paths.get("mock_data.json")));
* new Route.FulfillOptions().setPath(Paths.get("mock_data.json"))));
* }</pre>
*/
void fulfill(FulfillOptions options);
@@ -32,6 +32,11 @@ public interface Selectors {
*/
public Boolean contentScript;
/**
* Whether to run this selector engine in isolated JavaScript environment. This environment has access to the same DOM, but
* not any JavaScript objects from the frame's scripts. Defaults to {@code false}. Note that running as a content script is not
* guaranteed when this engine is used together with other registered engines.
*/
public RegisterOptions setContentScript(boolean contentScript) {
this.contentScript = contentScript;
return this;
@@ -20,10 +20,10 @@ import java.nio.file.Path;
import java.util.*;
/**
* API for collecting and saving Playwright traces. Playwright traces can be opened using the Playwright CLI after
* Playwright script runs.
* API for collecting and saving Playwright traces. Playwright traces can be opened in <a
* href="https://playwright.dev/java/docs/trace-viewer/">Trace Viewer</a> after Playwright script runs.
*
* <p> Start with specifying the folder traces will be stored in:
* <p> Start recording a trace before performing actions. At the end, stop tracing and save it to a file.
* <pre>{@code
* Browser browser = chromium.launch();
* BrowserContext context = browser.newContext();
@@ -52,14 +52,24 @@ public interface Tracing {
*/
public Boolean snapshots;
/**
* If specified, the trace is going to be saved into the file with the given name inside the {@code tracesDir} folder specified
* in {@link BrowserType#launch BrowserType.launch()}.
*/
public StartOptions setName(String name) {
this.name = name;
return this;
}
/**
* Whether to capture screenshots during tracing. Screenshots are used to build a timeline preview.
*/
public StartOptions setScreenshots(boolean screenshots) {
this.screenshots = screenshots;
return this;
}
/**
* Whether to capture DOM snapshot on every action.
*/
public StartOptions setSnapshots(boolean snapshots) {
this.snapshots = snapshots;
return this;
@@ -67,15 +77,34 @@ public interface Tracing {
}
class StopOptions {
/**
* Export trace into the file with the given name.
* Export trace into the file with the given path.
*/
public Path path;
/**
* Export trace into the file with the given path.
*/
public StopOptions setPath(Path path) {
this.path = path;
return this;
}
}
class StopChunkOptions {
/**
* Export trace collected since the last {@link Tracing#startChunk Tracing.startChunk()} call into the file with the given
* path.
*/
public Path path;
/**
* Export trace collected since the last {@link Tracing#startChunk Tracing.startChunk()} call into the file with the given
* path.
*/
public StopChunkOptions setPath(Path path) {
this.path = path;
return this;
}
}
/**
* Start tracing.
* <pre>{@code
@@ -104,6 +133,31 @@ public interface Tracing {
* }</pre>
*/
void start(StartOptions options);
/**
* Start a new trace chunk. If you'd like to record multiple traces on the same {@code BrowserContext}, use {@link Tracing#start
* Tracing.start()} once, and then create multiple trace chunks with {@link Tracing#startChunk Tracing.startChunk()} and
* {@link Tracing#stopChunk Tracing.stopChunk()}.
* <pre>{@code
* context.tracing().start(new Tracing.StartOptions()
* .setScreenshots(true)
* .setSnapshots(true));
* Page page = context.newPage();
* page.navigate("https://playwright.dev");
*
* context.tracing().startChunk();
* page.click("text=Get Started");
* // Everything between startChunk and stopChunk will be recorded in the trace.
* context.tracing().stopChunk(new Tracing.StopChunkOptions()
* .setPath(Paths.get("trace1.zip")));
*
* context.tracing().startChunk();
* page.navigate("http://example.com");
* // Save a second trace file with different actions.
* context.tracing().stopChunk(new Tracing.StopChunkOptions()
* .setPath(Paths.get("trace2.zip")));
* }</pre>
*/
void startChunk();
/**
* Stop tracing.
*/
@@ -114,5 +168,15 @@ public interface Tracing {
* Stop tracing.
*/
void stop(StopOptions options);
/**
* Stop the trace chunk. See {@link Tracing#startChunk Tracing.startChunk()} for more details about multiple trace chunks.
*/
default void stopChunk() {
stopChunk(null);
}
/**
* Stop the trace chunk. See {@link Tracing#startChunk Tracing.startChunk()} for more details about multiple trace chunks.
*/
void stopChunk(StopChunkOptions options);
}
@@ -72,10 +72,17 @@ public interface WebSocket {
*/
public Double timeout;
/**
* Receives the {@code WebSocketFrame} object and resolves to truthy value when the waiting should resolve.
*/
public WaitForFrameReceivedOptions setPredicate(Predicate<WebSocketFrame> predicate) {
this.predicate = predicate;
return this;
}
/**
* Maximum time to wait for in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
* value can be changed by using the {@link BrowserContext#setDefaultTimeout BrowserContext.setDefaultTimeout()}.
*/
public WaitForFrameReceivedOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -92,10 +99,17 @@ public interface WebSocket {
*/
public Double timeout;
/**
* Receives the {@code WebSocketFrame} object and resolves to truthy value when the waiting should resolve.
*/
public WaitForFrameSentOptions setPredicate(Predicate<WebSocketFrame> predicate) {
this.predicate = predicate;
return this;
}
/**
* Maximum time to wait for in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
* value can be changed by using the {@link BrowserContext#setDefaultTimeout BrowserContext.setDefaultTimeout()}.
*/
public WaitForFrameSentOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -52,6 +52,10 @@ public interface Worker {
*/
public Double timeout;
/**
* Maximum time to wait for in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
* value can be changed by using the {@link BrowserContext#setDefaultTimeout BrowserContext.setDefaultTimeout()}.
*/
public WaitForCloseOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -56,6 +56,7 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
final TimeoutSettings timeoutSettings = new TimeoutSettings();
Path videosDir;
URL baseUrl;
Path recordHarPath;
enum EventType {
CLOSE,
@@ -144,9 +145,9 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
listeners.remove(EventType.RESPONSE, handler);
}
private <T> T waitForEventWithTimeout(EventType eventType, Runnable code, Double timeout) {
private <T> T waitForEventWithTimeout(EventType eventType, Runnable code, Predicate<T> predicate, Double timeout) {
List<Waitable<T>> waitables = new ArrayList<>();
waitables.add(new WaitableEvent<>(listeners, eventType));
waitables.add(new WaitableEvent<>(listeners, eventType, predicate));
waitables.add(new WaitableContextClose<>());
waitables.add(timeoutSettings.createWaitable(timeout));
return runUntil(code, new WaitableRace<>(waitables));
@@ -161,7 +162,7 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
if (options == null) {
options = new WaitForPageOptions();
}
return waitForEventWithTimeout(EventType.PAGE, code, options.timeout);
return waitForEventWithTimeout(EventType.PAGE, code, options.predicate, options.timeout);
}
@Override
@@ -180,6 +181,18 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
}
isClosedOrClosing = true;
try {
if (recordHarPath != null) {
JsonObject json = sendMessage("harExport").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;
}
artifact.saveAs(recordHarPath);
artifact.delete();
}
sendMessage("close");
} catch (PlaywrightException e) {
if (!isSafeCloseError(e)) {
@@ -317,23 +330,23 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
}
@Override
public void route(String url, Consumer<Route> handler) {
route(new UrlMatcher(this.baseUrl, url), handler);
public void route(String url, Consumer<Route> handler, RouteOptions options) {
route(new UrlMatcher(this.baseUrl, url), handler, options);
}
@Override
public void route(Pattern url, Consumer<Route> handler) {
route(new UrlMatcher(url), handler);
public void route(Pattern url, Consumer<Route> handler, RouteOptions options) {
route(new UrlMatcher(url), handler, options);
}
@Override
public void route(Predicate<String> url, Consumer<Route> handler) {
route(new UrlMatcher(url), handler);
public void route(Predicate<String> url, Consumer<Route> handler, RouteOptions options) {
route(new UrlMatcher(url), handler, options);
}
private void route(UrlMatcher matcher, Consumer<Route> handler) {
private void route(UrlMatcher matcher, Consumer<Route> handler, RouteOptions options) {
withLogging("BrowserContext.route", () -> {
routes.add(matcher, handler);
routes.add(matcher, handler, options == null ? null : options.times);
if (routes.size() == 1) {
JsonObject params = new JsonObject();
params.addProperty("enabled", true);
@@ -488,6 +501,7 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
} else if ("requestFailed".equals(event)) {
String guid = params.getAsJsonObject("request").get("guid").getAsString();
RequestImpl request = connection.getExistingObject(guid);
request.didFailOrFinish = true;
if (params.has("failureText")) {
request.failure = params.get("failureText").getAsString();
}
@@ -502,6 +516,7 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
} else if ("requestFinished".equals(event)) {
String guid = params.getAsJsonObject("request").get("guid").getAsString();
RequestImpl request = connection.getExistingObject(guid);
request.didFailOrFinish = true;
if (request.timing != null) {
request.timing.responseEnd = params.get("responseEndTiming").getAsDouble();
}
@@ -165,15 +165,13 @@ class BrowserImpl extends ChannelOwner implements Browser {
params.addProperty("noDefaultViewport", true);
}
}
params.addProperty("sdkLanguage", "java");
JsonElement result = sendMessage("newContext", params);
BrowserContextImpl context = connection.getExistingObject(result.getAsJsonObject().getAsJsonObject("context").get("guid").getAsString());
if (options.recordVideoDir != null) {
context.videosDir = options.recordVideoDir;
}
context.videosDir = options.recordVideoDir;
if (options.baseURL != null) {
context.setBaseUrl(options.baseURL);
}
context.recordHarPath = options.recordHarPath;
contexts.add(context);
return context;
}
@@ -75,7 +75,7 @@ class BrowserTypeImpl extends ChannelOwner implements BrowserType {
}
WebSocketTransport transport = new WebSocketTransport(new URI(wsEndpoint), headers, timeout, slowMo);
Connection connection = new Connection(transport);
PlaywrightImpl playwright = (PlaywrightImpl) connection.waitForObjectWithKnownName("Playwright");
PlaywrightImpl playwright = connection.initializePlaywright();
if (!playwright.initializer.has("preLaunchedBrowser")) {
try {
connection.close();
@@ -119,7 +119,6 @@ class BrowserTypeImpl extends ChannelOwner implements BrowserType {
}
JsonObject params = gson().toJsonTree(options).getAsJsonObject();
params.addProperty("sdkLanguage", "java");
params.addProperty("endpointURL", endpointURL);
JsonObject json = sendMessage("connectOverCDP", params).getAsJsonObject();
@@ -183,15 +182,13 @@ class BrowserTypeImpl extends ChannelOwner implements BrowserType {
params.addProperty("noDefaultViewport", true);
}
}
params.addProperty("sdkLanguage", "java");
JsonObject json = sendMessage("launchPersistentContext", params).getAsJsonObject();
BrowserContextImpl context = connection.getExistingObject(json.getAsJsonObject("context").get("guid").getAsString());
if (options.recordVideoDir != null) {
context.videosDir = options.recordVideoDir;
}
context.videosDir = options.recordVideoDir;
if (options.baseURL != null) {
context.setBaseUrl(options.baseURL);
}
context.recordHarPath = options.recordHarPath;
return context;
}
@@ -19,16 +19,12 @@ import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.microsoft.playwright.Playwright;
import com.microsoft.playwright.PlaywrightException;
import com.microsoft.playwright.TimeoutError;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -77,7 +73,14 @@ public class Connection {
class Root extends ChannelOwner {
Root(Connection connection) {
super(connection, "", "");
super(connection, "Root", "");
}
Playwright initialize() {
JsonObject params = new JsonObject();
params.addProperty("sdkLanguage", "java");
JsonElement result = sendMessage("initialize", params.getAsJsonObject());
return this.connection.getExistingObject(result.getAsJsonObject().getAsJsonObject("playwright").get("guid").getAsString());
}
}
@@ -177,11 +180,8 @@ public class Connection {
return result;
}
public ChannelOwner waitForObjectWithKnownName(String guid) {
while (!objects.containsKey(guid)) {
processOneMessage();
}
return objects.get(guid);
public PlaywrightImpl initializePlaywright() {
return (PlaywrightImpl) this.root.initialize();
}
public <T> T getExistingObject(String guid) {
@@ -305,6 +305,10 @@ public class Connection {
case "ElementHandle":
result = new ElementHandleImpl(parent, type, guid, initializer);
break;
case "FetchRequest":
// Create fake object as this API is experimental an only exposed in Node.js.
result = new ChannelOwner(parent, type, guid, initializer);
break;
case "Frame":
result = new FrameImpl(parent, type, guid, initializer);
break;
@@ -34,6 +34,7 @@ import java.util.Base64;
import java.util.List;
import static com.microsoft.playwright.impl.Serialization.*;
import static com.microsoft.playwright.impl.Utils.convertViaJson;
import static com.microsoft.playwright.options.ScreenshotType.JPEG;
import static com.microsoft.playwright.options.ScreenshotType.PNG;
@@ -431,6 +432,15 @@ public class ElementHandleImpl extends JSHandleImpl implements ElementHandle {
withLogging("ElementHandle.selectText", () -> selectTextImpl(options));
}
@Override
public void setChecked(boolean checked, SetCheckedOptions options) {
if (checked) {
check(convertViaJson(options, CheckOptions.class));
} else {
uncheck(convertViaJson(options, UncheckOptions.class));
}
}
@Override
public void setInputFiles(Path files, SetInputFilesOptions options) {
setInputFiles(new Path[]{files}, options);
@@ -643,6 +643,19 @@ public class FrameImpl extends ChannelOwner implements Frame {
return parseStringList(json.getAsJsonArray("values"));
}
@Override
public void setChecked(String selector, boolean checked, SetCheckedOptions options) {
withLogging("Frame.setChecked", () -> setCheckedImpl(selector, checked, options));
}
void setCheckedImpl(String selector, boolean checked, SetCheckedOptions options) {
if (checked) {
checkImpl(selector, convertViaJson(options, CheckOptions.class));
} else {
uncheckImpl(selector, convertViaJson(options, UncheckOptions.class));
}
}
@Override
public void setContent(String html, SetContentOptions options) {
withLogging("Frame.setContent", () -> setContentImpl(html, options));
@@ -327,6 +327,14 @@ class LocatorImpl implements Locator {
}, convertViaJson(options, ElementHandle.SelectTextOptions.class));
}
@Override
public void setChecked(boolean checked, SetCheckedOptions options) {
if (options == null) {
options = new SetCheckedOptions();
}
frame.setChecked(selector, checked, convertViaJson(options, Frame.SetCheckedOptions.class).setStrict(true));
}
@Override
public void setInputFiles(Path files, SetInputFilesOptions options) {
if (options == null) {
@@ -93,6 +93,16 @@ class MouseImpl implements Mouse {
page.withLogging("Mouse.up", () -> upImpl(options));
}
@Override
public void wheel(double deltaX, double deltaY) {
page.withLogging("Mouse.wheel", () -> {
JsonObject params = new JsonObject();
params.addProperty("deltaX", deltaX);
params.addProperty("deltaY", deltaY);
page.sendMessage("mouseWheel", params);
});
}
private void upImpl(UpOptions options) {
if (options == null) {
options = new UpOptions();
@@ -125,7 +125,14 @@ public class PageImpl extends ChannelOwner implements Page {
if (listeners.hasListeners(EventType.DIALOG)) {
listeners.notify(EventType.DIALOG, dialog);
} else {
dialog.dismiss();
if ("beforeunload".equals(dialog.type())) {
try {
dialog.accept();
} catch (PlaywrightException e) {
}
} else {
dialog.dismiss();
}
}
} else if ("worker".equals(event)) {
String guid = params.getAsJsonObject("worker").get("guid").getAsString();
@@ -445,7 +452,7 @@ public class PageImpl extends ChannelOwner implements Page {
if (options == null) {
options = new WaitForCloseOptions();
}
return waitForEventWithTimeout(EventType.CLOSE, code, options.timeout);
return waitForEventWithTimeout(EventType.CLOSE, code, null, options.timeout);
}
@Override
@@ -457,7 +464,7 @@ public class PageImpl extends ChannelOwner implements Page {
if (options == null) {
options = new WaitForConsoleMessageOptions();
}
return waitForEventWithTimeout(EventType.CONSOLE, code, options.timeout);
return waitForEventWithTimeout(EventType.CONSOLE, code, options.predicate, options.timeout);
}
@Override
@@ -469,7 +476,7 @@ public class PageImpl extends ChannelOwner implements Page {
if (options == null) {
options = new WaitForDownloadOptions();
}
return waitForEventWithTimeout(EventType.DOWNLOAD, code, options.timeout);
return waitForEventWithTimeout(EventType.DOWNLOAD, code, options.predicate, options.timeout);
}
@Override
@@ -482,7 +489,7 @@ public class PageImpl extends ChannelOwner implements Page {
if (options == null) {
options = new WaitForFileChooserOptions();
}
return waitForEventWithTimeout(EventType.FILECHOOSER, code, options.timeout);
return waitForEventWithTimeout(EventType.FILECHOOSER, code, options.predicate, options.timeout);
}
@Override
@@ -494,7 +501,7 @@ public class PageImpl extends ChannelOwner implements Page {
if (options == null) {
options = new WaitForPopupOptions();
}
return waitForEventWithTimeout(EventType.POPUP, code, options.timeout);
return waitForEventWithTimeout(EventType.POPUP, code, options.predicate, options.timeout);
}
@Override
@@ -506,7 +513,7 @@ public class PageImpl extends ChannelOwner implements Page {
if (options == null) {
options = new WaitForWebSocketOptions();
}
return waitForEventWithTimeout(EventType.WEBSOCKET, code, options.timeout);
return waitForEventWithTimeout(EventType.WEBSOCKET, code, options.predicate, options.timeout);
}
@Override
@@ -518,12 +525,12 @@ public class PageImpl extends ChannelOwner implements Page {
if (options == null) {
options = new WaitForWorkerOptions();
}
return waitForEventWithTimeout(EventType.WORKER, code, options.timeout);
return waitForEventWithTimeout(EventType.WORKER, code, options.predicate, options.timeout);
}
private <T> T waitForEventWithTimeout(EventType eventType, Runnable code, Double timeout) {
private <T> T waitForEventWithTimeout(EventType eventType, Runnable code, Predicate<T> predicate, Double timeout) {
List<Waitable<T>> waitables = new ArrayList<>();
waitables.add(new WaitableEvent<>(listeners, eventType));
waitables.add(new WaitableEvent<>(listeners, eventType, predicate));
waitables.add(createWaitForCloseHelper());
waitables.add(createWaitableTimeout(timeout));
return runUntil(code, new WaitableRace<>(waitables));
@@ -943,23 +950,23 @@ public class PageImpl extends ChannelOwner implements Page {
}
@Override
public void route(String url, Consumer<Route> handler) {
route(new UrlMatcher(browserContext.baseUrl, url), handler);
public void route(String url, Consumer<Route> handler, RouteOptions options) {
route(new UrlMatcher(browserContext.baseUrl, url), handler, options);
}
@Override
public void route(Pattern url, Consumer<Route> handler) {
route(new UrlMatcher(url), handler);
public void route(Pattern url, Consumer<Route> handler, RouteOptions options) {
route(new UrlMatcher(url), handler, options);
}
@Override
public void route(Predicate<String> url, Consumer<Route> handler) {
route(new UrlMatcher(url), handler);
public void route(Predicate<String> url, Consumer<Route> handler, RouteOptions options) {
route(new UrlMatcher(url), handler, options);
}
private void route(UrlMatcher matcher, Consumer<Route> handler) {
private void route(UrlMatcher matcher, Consumer<Route> handler, RouteOptions options) {
withLogging("Page.route", () -> {
routes.add(matcher, handler);
routes.add(matcher, handler, options == null ? null : options.times);
if (routes.size() == 1) {
JsonObject params = new JsonObject();
params.addProperty("enabled", true);
@@ -1042,6 +1049,12 @@ public class PageImpl extends ChannelOwner implements Page {
() -> mainFrame.selectOptionImpl(selector, values, convertViaJson(options, Frame.SelectOptionOptions.class)));
}
@Override
public void setChecked(String selector, boolean checked, SetCheckedOptions options) {
withLogging("Page.setChecked",
() -> mainFrame.setCheckedImpl(selector, checked, convertViaJson(options, Frame.SetCheckedOptions.class)));
}
@Override
public void setContent(String html, SetContentOptions options) {
withLogging("Page.setContent",
@@ -1312,12 +1325,7 @@ public class PageImpl extends ChannelOwner implements Page {
if (options == null) {
options = new WaitForRequestOptions();
}
List<Waitable<Request>> waitables = new ArrayList<>();
waitables.add(new WaitableEvent<>(listeners, EventType.REQUEST,
request -> predicate == null || predicate.test(request)));
waitables.add(createWaitForCloseHelper());
waitables.add(createWaitableTimeout(options.timeout));
return runUntil(code, new WaitableRace<>(waitables));
return waitForEventWithTimeout(EventType.REQUEST, code, predicate, options.timeout);
}
@Override
@@ -1329,13 +1337,7 @@ public class PageImpl extends ChannelOwner implements Page {
if (options == null) {
options = new WaitForRequestFinishedOptions();
}
List<Waitable<Request>> waitables = new ArrayList<>();
Predicate<Request> predicate = options.predicate;
waitables.add(new WaitableEvent<>(listeners, EventType.REQUESTFINISHED,
request -> predicate == null || predicate.test(request)));
waitables.add(createWaitForCloseHelper());
waitables.add(createWaitableTimeout(options.timeout));
return runUntil(code, new WaitableRace<>(waitables));
return waitForEventWithTimeout(EventType.REQUESTFINISHED, code, options.predicate, options.timeout);
}
@Override
@@ -1361,12 +1363,7 @@ public class PageImpl extends ChannelOwner implements Page {
if (options == null) {
options = new WaitForResponseOptions();
}
List<Waitable<Response>> waitables = new ArrayList<>();
waitables.add(new WaitableEvent<>(listeners, EventType.RESPONSE,
response -> predicate == null || predicate.test(response)));
waitables.add(createWaitForCloseHelper());
waitables.add(createWaitableTimeout(options.timeout));
return runUntil(code, new WaitableRace<>(waitables));
return waitForEventWithTimeout(EventType.RESPONSE, code, predicate, options.timeout);
}
@Override
@@ -42,7 +42,7 @@ public class PlaywrightImpl extends ChannelOwner implements Playwright {
pb.environment().putAll(env);
Process p = pb.start();
Connection connection = new Connection(new PipeTransport(p.getInputStream(), p.getOutputStream()));
PlaywrightImpl result = (PlaywrightImpl) connection.waitForObjectWithKnownName("Playwright");
PlaywrightImpl result = connection.initializePlaywright();
result.driverProcess = p;
result.initSharedSelectors(null);
return result;
@@ -0,0 +1,67 @@
/*
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.microsoft.playwright.impl;
import com.microsoft.playwright.options.HttpHeader;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
class RawHeaders {
private final List<HttpHeader> headersArray;
private final Map<String, List<String>> headersMap = new LinkedHashMap<>();
RawHeaders(List<HttpHeader> headers) {
headersArray = headers;
for (HttpHeader h: headers) {
String name = h.name.toLowerCase();
List<String> values = headersMap.get(name);
if (values == null) {
values = new ArrayList<>();
headersMap.put(name, values);
}
values.add(h.value);
}
}
String get(String name) {
List<String> values = getAll(name);
if (values == null) {
return null;
}
return String.join("set-cookie".equals(name.toLowerCase()) ? "\n" : ", ", values);
}
List<String> getAll(String name) {
return headersMap.get(name.toLowerCase());
}
Map<String, String> headers() {
Map<String, String> result = new LinkedHashMap<>();
for (String name: headersMap.keySet()) {
result.put(name, get(name));
}
return result;
}
List<HttpHeader> headersArray() {
return headersArray;
}
}
@@ -16,25 +16,32 @@
package com.microsoft.playwright.impl;
import com.google.gson.JsonElement;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.microsoft.playwright.Frame;
import com.microsoft.playwright.PlaywrightException;
import com.microsoft.playwright.Request;
import com.microsoft.playwright.Response;
import com.microsoft.playwright.options.HttpHeader;
import com.microsoft.playwright.options.Sizes;
import com.microsoft.playwright.options.Timing;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.microsoft.playwright.impl.Serialization.gson;
import static com.microsoft.playwright.impl.Utils.toHeadersMap;
import static java.util.Arrays.asList;
public class RequestImpl extends ChannelOwner implements Request {
private final byte[] postData;
private RequestImpl redirectedFrom;
private RequestImpl redirectedTo;
final Map<String, String> headers = new HashMap<>();
private final RawHeaders headers;
private RawHeaders rawHeaders;
String failure;
Timing timing;
boolean didFailOrFinish;
RequestImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
super(parent, type, guid, initializer);
@@ -43,10 +50,7 @@ public class RequestImpl extends ChannelOwner implements Request {
redirectedFrom = connection.getExistingObject(initializer.getAsJsonObject("redirectedFrom").get("guid").getAsString());
redirectedFrom.redirectedTo = this;
}
for (JsonElement e : initializer.getAsJsonArray("headers")) {
JsonObject item = e.getAsJsonObject();
headers.put(item.get("name").getAsString().toLowerCase(), item.get("value").getAsString());
}
headers = new RawHeaders(asList(gson().fromJson(initializer.getAsJsonArray("headers"), HttpHeader[].class)));
if (initializer.has("postData")) {
postData = Base64.getDecoder().decode(initializer.get("postData").getAsString());
} else {
@@ -54,19 +58,34 @@ public class RequestImpl extends ChannelOwner implements Request {
}
}
@Override
public Map<String, String> allHeaders() {
return withLogging("Request.allHeaders", () -> getRawHeaders().headers());
}
@Override
public String failure() {
return failure;
}
@Override
public Frame frame() {
public FrameImpl frame() {
return connection.getExistingObject(initializer.getAsJsonObject("frame").get("guid").getAsString());
}
@Override
public Map<String, String> headers() {
return headers;
return headers.headers();
}
@Override
public List<HttpHeader> headersArray() {
return withLogging("Request.headersArray", () -> getRawHeaders().headersArray());
}
@Override
public String headerValue(String name) {
return withLogging("Request.headerValue", () -> getRawHeaders().get(name));
}
@Override
@@ -108,7 +127,7 @@ public class RequestImpl extends ChannelOwner implements Request {
}
@Override
public Response response() {
public ResponseImpl response() {
return withLogging("Request.response", () -> {
JsonObject result = sendMessage("response").getAsJsonObject();
if (!result.has("response")) {
@@ -118,6 +137,18 @@ public class RequestImpl extends ChannelOwner implements Request {
});
}
@Override
public Sizes sizes() {
return withLogging("Request.sizes", () -> {
ResponseImpl response = response();
if (response == null) {
throw new PlaywrightException("Unable to fetch sizes for failed request");
}
JsonObject json = response.sendMessage("sizes").getAsJsonObject();
return gson().fromJson(json.getAsJsonObject("sizes"), Sizes.class);
});
}
@Override
public Timing timing() {
return timing;
@@ -132,4 +163,17 @@ public class RequestImpl extends ChannelOwner implements Request {
return redirectedTo != null ? redirectedTo.finalRequest() : this;
}
private RawHeaders getRawHeaders() {
if (rawHeaders != null) {
return rawHeaders;
}
JsonArray rawHeadersJson = withLogging("Request.allHeaders", () -> {
JsonObject result = sendMessage("rawRequestHeaders").getAsJsonObject();
return result.getAsJsonArray("headers");
});
// The field may have been initialized in a nested call but it is ok.
rawHeaders = new RawHeaders(asList(gson().fromJson(rawHeadersJson, HttpHeader[].class)));
return rawHeaders;
}
}
@@ -16,43 +16,40 @@
package com.microsoft.playwright.impl;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.microsoft.playwright.Frame;
import com.microsoft.playwright.Request;
import com.microsoft.playwright.Response;
import com.microsoft.playwright.options.HttpHeader;
import com.microsoft.playwright.options.SecurityDetails;
import com.microsoft.playwright.options.ServerAddr;
import com.microsoft.playwright.options.Timing;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.microsoft.playwright.impl.Serialization.gson;
import static java.util.Arrays.asList;
public class ResponseImpl extends ChannelOwner implements Response {
private final Map<String, String> headers = new HashMap<>();
private final RawHeaders headers;
private RawHeaders rawHeaders;
private final RequestImpl request;
ResponseImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
super(parent, type, guid, initializer);
for (JsonElement e : initializer.getAsJsonArray("headers")) {
JsonObject item = e.getAsJsonObject();
headers.put(item.get("name").getAsString().toLowerCase(), item.get("value").getAsString());
}
headers = new RawHeaders(asList(gson().fromJson(initializer.getAsJsonArray("headers"), HttpHeader[].class)));
request = connection.getExistingObject(initializer.getAsJsonObject("request").get("guid").getAsString());
request.headers.clear();
for (JsonElement e : initializer.getAsJsonArray("requestHeaders")) {
JsonObject item = e.getAsJsonObject();
request.headers.put(item.get("name").getAsString().toLowerCase(), item.get("value").getAsString());
}
request.timing = gson().fromJson(initializer.get("timing"), Timing.class);
}
@Override
public Map<String, String> allHeaders() {
return withLogging("Response.allHeaders", () -> getRawHeaders().headers());
}
@Override
public byte[] body() {
return withLogging("Response.body", () -> {
@@ -63,13 +60,22 @@ public class ResponseImpl extends ChannelOwner implements Response {
@Override
public String finished() {
return withLogging("Response.finished", () -> {
JsonObject json = sendMessage("finished").getAsJsonObject();
if (json.has("error")) {
return json.get("error").getAsString();
List<Waitable<String>> waitables = new ArrayList<>();
waitables.add(new WaitableNever<String>() {
@Override
public boolean isDone() {
return request.didFailOrFinish;
}
@Override
public String get() {
return request.failure();
}
return null;
});
PageImpl page = request.frame().page;
waitables.add(page.createWaitForCloseHelper());
waitables.add(page.createWaitableTimeout(null));
runUntil(() -> {}, new WaitableRace<>(waitables));
return request.failure();
}
@Override
@@ -79,7 +85,22 @@ public class ResponseImpl extends ChannelOwner implements Response {
@Override
public Map<String, String> headers() {
return headers;
return headers.headers();
}
@Override
public List<HttpHeader> headersArray() {
return withLogging("Response.headersArray", () -> getRawHeaders().headersArray());
}
@Override
public String headerValue(String name) {
return getRawHeaders().get(name);
}
@Override
public List<String> headerValues(String name) {
return getRawHeaders().getAll(name);
}
@Override
@@ -133,4 +154,12 @@ public class ResponseImpl extends ChannelOwner implements Response {
public String url() {
return initializer.get("url").getAsString();
}
private RawHeaders getRawHeaders() {
if (rawHeaders == null) {
JsonObject json = sendMessage("rawResponseHeaders").getAsJsonObject();
rawHeaders = new RawHeaders(asList(gson().fromJson(json.getAsJsonArray("headers"), HttpHeader[].class)));
}
return rawHeaders;
}
}
@@ -29,15 +29,31 @@ class Router {
private static class RouteInfo {
final UrlMatcher matcher;
final Consumer<Route> handler;
Integer times;
RouteInfo(UrlMatcher matcher, Consumer<Route> handler) {
RouteInfo(UrlMatcher matcher, Consumer<Route> handler, Integer times) {
this.matcher = matcher;
this.handler = handler;
this.times = times;
}
boolean handle(Route route) {
if (times != null && times <= 0) {
return false;
}
if (!matcher.test(route.request().url())) {
return false;
}
if (times != null) {
--times;
}
handler.accept(route);
return true;
}
}
void add(UrlMatcher matcher, Consumer<Route> handler) {
routes.add(0, new RouteInfo(matcher, handler));
void add(UrlMatcher matcher, Consumer<Route> handler, Integer times) {
routes.add(0, new RouteInfo(matcher, handler, times));
}
void remove(UrlMatcher matcher, Consumer<Route> handler) {
@@ -52,8 +68,7 @@ class Router {
boolean handle(Route route) {
for (RouteInfo info : routes) {
if (info.matcher.test(route.request().url())) {
info.handler.accept(route);
if (info.handle(route)) {
return true;
}
}
@@ -39,9 +39,11 @@ class Serialization {
if (gson == null) {
gson = new GsonBuilder()
.registerTypeAdapter(SameSiteAttribute.class, new SameSiteAdapter().nullSafe())
.registerTypeAdapter(BrowserChannel.class, new BrowserChannelSerializer())
.registerTypeAdapter(ColorScheme.class, new ColorSchemeAdapter().nullSafe())
.registerTypeAdapter(Media.class, new MediaSerializer())
.registerTypeAdapter(BrowserChannel.class, new ToLowerCaseAndDashSerializer<BrowserChannel>())
.registerTypeAdapter(ColorScheme.class, new ToLowerCaseAndDashSerializer<ColorScheme>())
.registerTypeAdapter(Media.class, new ToLowerCaseSerializer<Media>())
.registerTypeAdapter(ForcedColors.class, new ToLowerCaseSerializer<ForcedColors>())
.registerTypeAdapter(ReducedMotion.class, new ToLowerCaseAndDashSerializer<ReducedMotion>())
.registerTypeAdapter(ScreenshotType.class, new ToLowerCaseSerializer<ScreenshotType>())
.registerTypeAdapter(MouseButton.class, new ToLowerCaseSerializer<MouseButton>())
.registerTypeAdapter(LoadState.class, new ToLowerCaseSerializer<LoadState>())
@@ -255,6 +257,8 @@ class Serialization {
private static boolean isSupported(Type type) {
return new TypeToken<Optional<Media>>() {}.getType().getTypeName().equals(type.getTypeName()) ||
new TypeToken<Optional<ColorScheme>>() {}.getType().getTypeName().equals(type.getTypeName()) ||
new TypeToken<Optional<ForcedColors>>() {}.getType().getTypeName().equals(type.getTypeName()) ||
new TypeToken<Optional<ReducedMotion>>() {}.getType().getTypeName().equals(type.getTypeName()) ||
new TypeToken<Optional<ViewportSize>>() {}.getType().getTypeName().equals(type.getTypeName());
}
@@ -303,11 +307,10 @@ class Serialization {
return new JsonPrimitive(src.toString().toLowerCase().replace('_', '-'));
}
}
private static class MediaSerializer implements JsonSerializer<Media> {
private static class ToLowerCaseAndDashSerializer<E extends Enum<E>> implements JsonSerializer<E> {
@Override
public JsonElement serialize(Media src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.toString().toLowerCase());
public JsonElement serialize(E src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.toString().toLowerCase().replace('_', '-'));
}
}
@@ -351,37 +354,5 @@ class Serialization {
return SameSiteAttribute.valueOf(value.toUpperCase());
}
}
private static class ColorSchemeAdapter extends TypeAdapter<ColorScheme> {
@Override
public void write(JsonWriter out, ColorScheme value) throws IOException {
String stringValue;
switch (value) {
case DARK:
stringValue = "dark";
break;
case LIGHT:
stringValue = "light";
break;
case NO_PREFERENCE:
stringValue = "no-preference";
break;
default:
throw new PlaywrightException("Unexpected value: " + value);
}
out.value(stringValue);
}
@Override
public ColorScheme read(JsonReader in) throws IOException {
String value = in.nextString();
switch (value) {
case "dark": return ColorScheme.DARK;
case "light": return ColorScheme.LIGHT;
case "no-preference": return ColorScheme.NO_PREFERENCE;
default: throw new PlaywrightException("Unexpected value: " + value);
}
}
}
}
@@ -31,8 +31,13 @@ class TracingImpl implements Tracing {
this.context = context;
}
private void export(Path path) {
JsonObject json = context.sendMessage("tracingExport").getAsJsonObject();
private void stopChunkImpl(Path path) {
JsonObject params = new JsonObject();
params.addProperty("save", path != null);
JsonObject json = context.sendMessage("tracingStopChunk", params).getAsJsonObject();
if (!json.has("artifact")) {
return;
}
ArtifactImpl artifact = context.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.
@@ -48,21 +53,34 @@ class TracingImpl implements Tracing {
context.withLogging("Tracing.start", () -> startImpl(options));
}
@Override
public void startChunk() {
context.withLogging("Tracing.startChunk", () -> {
context.sendMessage("tracingStartChunk");
});
}
private void startImpl(StartOptions options) {
if (options == null) {
options = new StartOptions();
}
JsonObject params = gson().toJsonTree(options).getAsJsonObject();
context.sendMessage("tracingStart", params);
context.sendMessage("tracingStartChunk");
}
@Override
public void stop(StopOptions options) {
context.withLogging("Tracing.stop", () -> {
if (options != null && options.path != null) {
export(options.path);
}
stopChunkImpl(options == null ? null : options.path);
context.sendMessage("tracingStop");
});
}
@Override
public void stopChunk(StopChunkOptions options) {
context.withLogging("Tracing.stopChunk", () -> {
stopChunkImpl(options == null ? null : options.path);
});
}
}
@@ -19,6 +19,7 @@ package com.microsoft.playwright.impl;
import com.google.gson.*;
import com.microsoft.playwright.PlaywrightException;
import com.microsoft.playwright.options.FilePayload;
import com.microsoft.playwright.options.HttpHeader;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -187,4 +188,12 @@ class Utils {
}
return result.toString();
}
static Map<String, String> toHeadersMap(List<HttpHeader> headers) {
Map<String, String> map = new LinkedHashMap<>();
for (HttpHeader header: headers) {
map.put(header.name.toLowerCase(), header.value);
}
return map;
}
}
@@ -143,8 +143,7 @@ class WebSocketImpl extends ChannelOwner implements WebSocket {
private WebSocketFrame waitForEventWithTimeout(EventType eventType, Runnable code, Predicate<WebSocketFrame> predicate, Double timeout) {
List<Waitable<WebSocketFrame>> waitables = new ArrayList<>();
waitables.add(new WaitableEvent<>(listeners, eventType,
frame -> predicate == null || predicate.test(frame)));
waitables.add(new WaitableEvent<>(listeners, eventType, predicate));
waitables.add(new WaitableWebSocketClose<>());
waitables.add(new WaitableWebSocketError<>());
waitables.add(page.createWaitForCloseHelper());
@@ -52,30 +52,51 @@ public class Cookie {
this.name = name;
this.value = value;
}
/**
* either url or domain / path are required. Optional.
*/
public Cookie setUrl(String url) {
this.url = url;
return this;
}
/**
* either url or domain / path are required Optional.
*/
public Cookie setDomain(String domain) {
this.domain = domain;
return this;
}
/**
* either url or domain / path are required Optional.
*/
public Cookie setPath(String path) {
this.path = path;
return this;
}
/**
* Unix time in seconds. Optional.
*/
public Cookie setExpires(double expires) {
this.expires = expires;
return this;
}
/**
* Optional.
*/
public Cookie setHttpOnly(boolean httpOnly) {
this.httpOnly = httpOnly;
return this;
}
/**
* Optional.
*/
public Cookie setSecure(boolean secure) {
this.secure = secure;
return this;
}
/**
* Optional.
*/
public Cookie setSameSite(SameSiteAttribute sameSite) {
this.sameSite = sameSite;
return this;
@@ -0,0 +1,22 @@
/*
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.microsoft.playwright.options;
public enum ForcedColors {
ACTIVE,
NONE
}
@@ -34,6 +34,9 @@ public class Geolocation {
this.latitude = latitude;
this.longitude = longitude;
}
/**
* Non-negative accuracy value. Defaults to {@code 0}.
*/
public Geolocation setAccuracy(double accuracy) {
this.accuracy = accuracy;
return this;
@@ -0,0 +1,29 @@
/*
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.microsoft.playwright.options;
public class HttpHeader {
/**
* Name of the header.
*/
public String name;
/**
* Value of the header.
*/
public String value;
}
@@ -34,18 +34,30 @@ public class Margin {
*/
public String left;
/**
* Top margin, accepts values labeled with units. Defaults to {@code 0}.
*/
public Margin setTop(String top) {
this.top = top;
return this;
}
/**
* Right margin, accepts values labeled with units. Defaults to {@code 0}.
*/
public Margin setRight(String right) {
this.right = right;
return this;
}
/**
* Bottom margin, accepts values labeled with units. Defaults to {@code 0}.
*/
public Margin setBottom(String bottom) {
this.bottom = bottom;
return this;
}
/**
* Left margin, accepts values labeled with units. Defaults to {@code 0}.
*/
public Margin setLeft(String left) {
this.left = left;
return this;
@@ -38,14 +38,23 @@ public class Proxy {
public Proxy(String server) {
this.server = server;
}
/**
* Optional coma-separated domains to bypass proxy, for example {@code ".com, chromium.org, .domain.com"}.
*/
public Proxy setBypass(String bypass) {
this.bypass = bypass;
return this;
}
/**
* Optional username to use if HTTP proxy requires authentication.
*/
public Proxy setUsername(String username) {
this.username = username;
return this;
}
/**
* Optional password to use if HTTP proxy requires authentication.
*/
public Proxy setPassword(String password) {
this.password = password;
return this;
@@ -30,14 +30,23 @@ public class SelectOption {
*/
public Integer index;
/**
* Matches by {@code option.value}. Optional.
*/
public SelectOption setValue(String value) {
this.value = value;
return this;
}
/**
* Matches by {@code option.label}. Optional.
*/
public SelectOption setLabel(String label) {
this.label = label;
return this;
}
/**
* Matches by the index. Optional.
*/
public SelectOption setIndex(int index) {
this.index = index;
return this;
@@ -0,0 +1,37 @@
/*
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.microsoft.playwright.options;
public class Sizes {
/**
* Size of the request body (POST data payload) in bytes. Set to 0 if there was no body.
*/
public int requestBodySize;
/**
* Total number of bytes from the start of the HTTP request message until (and including) the double CRLF before the body.
*/
public int requestHeadersSize;
/**
* Size of the received response body (encoded) in bytes.
*/
public int responseBodySize;
/**
* Total number of bytes from the start of the HTTP response message until (and including) the double CRLF before the body.
*/
public int responseHeadersSize;
}
@@ -0,0 +1,30 @@
/*
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.microsoft.playwright;
import org.junit.jupiter.api.Test;
public class TestBeforeunload extends TestBase {
@Test
void shouldBeAbleToNavigateAwayFromPageWithBeforeunload() {
page.navigate(server.PREFIX + "/beforeunload.html");
// We have to interact with a page so that "beforeunload" handlers
// fire.
page.click("body");
page.navigate(server.EMPTY_PAGE);
}
}
@@ -115,10 +115,9 @@ public class TestBrowserContextBasic extends TestBase {
@Test
@Disabled("TODO: supported null viewport option")
void shouldNotAllowDeviceScaleFactorWithNullViewport() {
try {
browser.newContext(new Browser.NewContextOptions().setDeviceScaleFactor(1.0));
browser.newContext(new Browser.NewContextOptions().setDeviceScaleFactor(1.0).setViewportSize(null));
fail("did not throw");
} catch (PlaywrightException e) {
assertTrue(e.getMessage().contains("\"deviceScaleFactor\" option is not supported with null \"viewport\""));
@@ -126,10 +125,9 @@ public class TestBrowserContextBasic extends TestBase {
}
@Test
@Disabled("TODO: supported null viewport option")
void shouldNotAllowIsMobileWithNullViewport() {
try {
browser.newContext(new Browser.NewContextOptions().setIsMobile(true));
browser.newContext(new Browser.NewContextOptions().setIsMobile(true).setViewportSize(null));
fail("did not throw");
} catch (PlaywrightException e) {
assertTrue(e.getMessage().contains("\"isMobile\" option is not supported with null \"viewport\""));
@@ -121,4 +121,17 @@ public class TestBrowserContextRoute extends TestBase {
assertEquals("context", response.text());
context.close();
}
@Test
void shouldSupportTheTimesParameterWithRouteMatching() {
int[] intercepted = {0};
context.route("**/empty.html", route -> {
++intercepted[0];
route.resume();
}, new BrowserContext.RouteOptions().setTimes(2));
page.navigate(server.EMPTY_PAGE);
page.navigate(server.EMPTY_PAGE);
page.navigate(server.EMPTY_PAGE);
assertEquals(2, intercepted[0]);
}
}
@@ -0,0 +1,54 @@
/*
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.microsoft.playwright;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class TestBrowserContextStrict extends TestBase {
@Override
BrowserContext createContext() {
return browser.newContext(new Browser.NewContextOptions().setStrictSelectors(true));
}
@Test
void shouldNotFailPageTextContentInNonStrictMode() {
try (BrowserContext context = browser.newContext()) {
Page page = context.newPage();
page.setContent("<span>span1</span><div><span>target</span></div>");
assertEquals("span1", page.textContent("span"));
}
}
@Test
void shouldFailPageTextContentInStrictMode() {
page.setContent("<span>span1</span><div><span>target</span></div>");
try {
page.textContent("span");
fail("did not throw");
} catch (PlaywrightException e) {
assertTrue(e.getMessage().contains("strict mode violation"));
}
}
@Test
void shouldOptOutOfStrictMode() {
page.setContent("<span>span1</span><div><span>target</span></div>");
assertEquals("span1", page.textContent("span", new Page.TextContentOptions().setStrict(false)));
}
}
@@ -73,4 +73,14 @@ public class TestElementHandleMisc extends TestBase {
button.focus();
assertEquals(true, button.evaluate("button => document.activeElement === button"));
}
@Test
void shouldCheckTheBoxUsingSetChecked() {
page.setContent("<input id='checkbox' type='checkbox'></input>");
ElementHandle input = page.querySelector("input");
input.setChecked(true);
assertEquals(true, page.evaluate("checkbox.checked"));
input.setChecked(false);
assertEquals(false, page.evaluate("checkbox.checked"));
}
}
@@ -31,6 +31,7 @@ import java.io.IOException;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Instant;
import static com.microsoft.playwright.Utils.getOS;
import static com.microsoft.playwright.options.LoadState.DOMCONTENTLOADED;
@@ -103,7 +104,7 @@ public class TestHar extends TestBase {
assertEquals(1, log.getAsJsonArray("pages").size());
JsonObject pageEntry = log.getAsJsonArray("pages").get(0).getAsJsonObject();
assertEquals("page_0", pageEntry.get("id").getAsString());
assertNotNull(pageEntry.get("id").getAsString());
assertEquals("Hello", pageEntry.get("title").getAsString());
// expect(new Date(pageEntry.startedDateTime).valueOf()).toBeGreaterThan(Date.now() - 3600 * 1000);
assertTrue(pageEntry.getAsJsonObject("pageTimings").get("onContentLoad").getAsDouble() > 0);
@@ -129,7 +130,7 @@ public class TestHar extends TestBase {
}
assertEquals(1, log.getAsJsonArray("pages").size());
JsonObject pageEntry = log.getAsJsonArray("pages").get(0).getAsJsonObject();
assertEquals("page_0", pageEntry.get("id").getAsString());
assertNotNull(pageEntry.get("id").getAsString());
assertEquals("Hello", pageEntry.get("title").getAsString());
}
@@ -139,7 +140,8 @@ public class TestHar extends TestBase {
JsonObject log = pageWithHar.log();
assertEquals(1, log.getAsJsonArray("entries").size());
JsonObject entry = log.getAsJsonArray("entries").get(0).getAsJsonObject();
assertEquals("page_0", entry.get("pageref").getAsString());
String id = log.getAsJsonArray("pages").get(0).getAsJsonObject().get("id").getAsString();
assertEquals(id, entry.get("pageref").getAsString());
assertEquals(server.EMPTY_PAGE, entry.getAsJsonObject("request").get("url").getAsString());
assertEquals("GET", entry.getAsJsonObject("request").get("method").getAsString());
assertEquals("HTTP/1.1", entry.getAsJsonObject("request").get("httpVersion").getAsString());
@@ -0,0 +1,33 @@
/*
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.microsoft.playwright;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestLocatorMisc extends TestBase{
@Test
void shouldCheckTheBoxUsingSetChecked() {
page.setContent("<input id='checkbox' type='checkbox'></input>");
Locator input = page.locator("input");
input.setChecked(true);
assertEquals(true, page.evaluate("checkbox.checked"));
input.setChecked(false);
assertEquals(false, page.evaluate("checkbox.checked"));
}
}
@@ -73,6 +73,18 @@ public class TestNetworkRequest extends TestBase {
assertEquals(server.PREFIX + "/empty.html", requests.get(1).url());
}
@Test
void shouldWorkAllHeadersInsideRoute() {
List<Request> requests = new ArrayList<>();
page.route("**", route -> {
assertTrue(route.request().allHeaders().get("accept").length() > 5);
requests.add(route.request());
route.resume();
});
page.navigate(server.PREFIX + "/empty.html");
assertEquals(1, requests.size());
}
// https://github.com/microsoft/playwright/issues/3993
@Test
void shouldNotWorkForARedirectAndInterception() {
@@ -106,8 +118,12 @@ public class TestNetworkRequest extends TestBase {
return (isWebKit() && getOS() == Utils.OS.WINDOWS) || isChromium();
}
static boolean isWebKitWindows() {
return isWebKit() && getOS() == Utils.OS.WINDOWS;
}
@Test
@DisabledIf(value="isWebKitWindowsOrChromium", disabledReason="Flaky, see https://github.com/microsoft/playwright/issues/6690")
@DisabledIf(value="isWebKitWindows", disabledReason="Flaky, see https://github.com/microsoft/playwright/issues/6690")
void shouldGetTheSameHeadersAsTheServer() throws ExecutionException, InterruptedException {
Future<Server.Request> serverRequest = server.futureRequest("/empty.html");
server.setRoute("/empty.html", exchange -> {
@@ -119,7 +135,7 @@ public class TestNetworkRequest extends TestBase {
Response response = page.navigate(server.PREFIX + "/empty.html");
Map<String, String> expectedHeaders = serverRequest.get().headers.entrySet().stream().collect(
Collectors.toMap(e -> e.getKey().toLowerCase(), e -> e.getValue().get(0)));
assertEquals(expectedHeaders, response.request().headers());
assertEquals(expectedHeaders, response.request().allHeaders());
}
@Test
@@ -143,7 +159,7 @@ public class TestNetworkRequest extends TestBase {
});
Map<String, String> expectedHeaders = serverRequest.get().headers.entrySet().stream().collect(
Collectors.toMap(e -> e.getKey().toLowerCase(), e -> e.getValue().get(0)));
assertEquals(expectedHeaders, response.request().headers());
assertEquals(expectedHeaders, response.request().allHeaders());
}
@Test
@@ -39,7 +39,7 @@ public class TestPageBasic extends TestBase {
newPage.evaluate("() => new Promise(r => {})");
fail("evaluate should throw");
} catch (PlaywrightException e) {
assertTrue(e.getMessage().contains("Protocol error"));
assertTrue(e.getMessage().contains("Target closed"), e.getMessage());
}
}
@@ -0,0 +1,59 @@
/*
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.microsoft.playwright;
import com.microsoft.playwright.options.BoundingBox;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestPageCheck extends TestBase {
@Test
void shouldCheckTheLabelWithPosition() {
page.setContent("<input id='checkbox' type='checkbox' style='width: 5px; height: 5px;'>\n" +
" <label for='checkbox'>\n" +
" <a href=" + server.EMPTY_PAGE + ">I am a long link that goes away so that nothing good will happen if you click on me</a>\n" +
" Click me\n" +
" </label>");
BoundingBox box = page.querySelector("text=Click me").boundingBox();
page.check("text=Click me", new Page.CheckOptions().setPosition(box.width - 10, 2));
assertEquals(true, page.evalOnSelector("input", "input => input.checked"));
}
@Test
void trialRunShouldNotCheck() {
page.setContent("<input id='checkbox' type='checkbox'></input>");
page.check("input", new Page.CheckOptions().setTrial(true));
assertEquals(false, page.evaluate("() => window['checkbox'].checked"));
}
@Test
void trialRunShouldNotUncheck() {
page.setContent("<input id='checkbox' type='checkbox' checked></input>");
page.uncheck("input", new Page.UncheckOptions().setTrial(true));
assertEquals(true, page.evaluate("() => window['checkbox'].checked"));
}
@Test
void shouldCheckTheBoxUsingSetChecked() {
page.setContent("<input id='checkbox' type='checkbox'></input>");
page.setChecked("input", true);
assertEquals(true, page.evaluate("() => window['checkbox'].checked"));
page.setChecked("input", false);
assertEquals(false, page.evaluate("() => window['checkbox'].checked"));
}
}
@@ -16,7 +16,10 @@
package com.microsoft.playwright;
import com.microsoft.playwright.options.ForcedColors;
import com.microsoft.playwright.options.ReducedMotion;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIf;
import java.util.function.Supplier;
@@ -25,6 +28,7 @@ import static com.microsoft.playwright.options.ColorScheme.LIGHT;
import static com.microsoft.playwright.options.Media.PRINT;
import static com.microsoft.playwright.Utils.attachFrame;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class TestPageEmulateMedia extends TestBase {
@Test
@@ -141,4 +145,30 @@ public class TestPageEmulateMedia extends TestBase {
page.emulateMedia(new Page.EmulateMediaOptions().setColorScheme(LIGHT));
assertEquals("rgb(255, 255, 255)", backgroundColor.get());
}
@Test
void shouldEmulateReducedMotion() {
assertEquals(true, page.evaluate("() => matchMedia('(prefers-reduced-motion: no-preference)').matches"));
page.emulateMedia(new Page.EmulateMediaOptions().setReducedMotion(ReducedMotion.REDUCE));
assertEquals(true, page.evaluate("() => matchMedia('(prefers-reduced-motion: reduce)').matches"));
assertEquals(false, page.evaluate("() => matchMedia('(prefers-reduced-motion: no-preference)').matches"));
page.emulateMedia(new Page.EmulateMediaOptions().setReducedMotion(ReducedMotion.NO_PREFERENCE));
assertEquals(false, page.evaluate("() => matchMedia('(prefers-reduced-motion: reduce)').matches"));
assertEquals(true, page.evaluate("() => matchMedia('(prefers-reduced-motion: no-preference)').matches"));
page.emulateMedia(new Page.EmulateMediaOptions().setReducedMotion(null));
}
@Test
@DisabledIf(value="com.microsoft.playwright.TestBase#isWebKit", disabledReason="https://bugs.webkit.org/show_bug.cgi?id=225281")
void shouldEmulateForcedColors() {
assertEquals(true, page.evaluate("() => matchMedia('(forced-colors: none)').matches"));
page.emulateMedia(new Page.EmulateMediaOptions().setForcedColors(ForcedColors.NONE));
assertEquals(true, page.evaluate("() => matchMedia('(forced-colors: none)').matches"));
assertEquals(false, page.evaluate("() => matchMedia('(forced-colors: active)').matches"));
page.emulateMedia(new Page.EmulateMediaOptions().setForcedColors(ForcedColors.ACTIVE));
assertEquals(false, page.evaluate("() => matchMedia('(forced-colors: none)').matches"));
assertEquals(true, page.evaluate("() => matchMedia('(forced-colors: active)').matches"));
page.emulateMedia(new Page.EmulateMediaOptions().setForcedColors(null));
assertEquals(true, page.evaluate("() => matchMedia('(forced-colors: none)').matches"));
}
}
@@ -0,0 +1,133 @@
/*
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.microsoft.playwright;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIf;
import java.util.ArrayList;
import java.util.List;
import static com.microsoft.playwright.Utils.getOS;
import static com.microsoft.playwright.Utils.mapOf;
import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toList;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class TestPageEventConsole extends TestBase {
@Test
void shouldWork() {
ConsoleMessage[] event = {null};
page.onConsoleMessage(m -> event[0] = m);
ConsoleMessage message = page.waitForConsoleMessage(() -> page.evaluate("() => console.log('hello', 5, {foo: 'bar'});"));
if (isFirefox()) {
assertEquals("hello 5 JSHandle@object", message.text());
} else {
assertEquals("hello 5 {foo: bar}", message.text());
}
assertEquals("log", message.type());
assertEquals("hello", message.args().get(0).jsonValue());
assertEquals(5, message.args().get(1).jsonValue());
assertEquals(mapOf("foo", "bar"), message.args().get(2).jsonValue());
assertEquals(message, event[0]);
}
@Test
void shouldEmitSameLogTwice() {
List<String> messages = new ArrayList<>();
page.onConsoleMessage(m -> messages.add(m.text()));
page.evaluate("() => { for (let i = 0; i < 2; ++i) console.log('hello'); }");
assertEquals(asList("hello", "hello"), messages);
}
@Test
void shouldWorkForDifferentConsoleAPICalls() {
List<ConsoleMessage> messages = new ArrayList<>();
page.onConsoleMessage(msg -> messages.add(msg));
// All console events will be reported before "page.evaluate" is finished.
page.evaluate("() => {\n" +
" // A pair of time/timeEnd generates only one Console API call.\n" +
" console.time('calling console.time');\n" +
" console.timeEnd('calling console.time');\n" +
" console.trace('calling console.trace');\n" +
" console.dir('calling console.dir');\n" +
" console.warn('calling console.warn');\n" +
" console.error('calling console.error');\n" +
" console.log(Promise.resolve('should not wait until resolved!'));\n" +
" }");
assertEquals(asList("timeEnd", "trace", "dir", "warning", "error", "log"),
messages.stream().map(msg -> msg.type()).collect(toList()));
assertTrue(messages.get(0).text().contains("calling console.time"));
assertEquals(asList(
"calling console.trace",
"calling console.dir",
"calling console.warn",
"calling console.error",
"Promise"), messages.subList(1, messages.size()).stream().map(msg -> msg.text()).collect(toList()));
}
@Test
void shouldNotFailForWindowObject() {
ConsoleMessage message = page.waitForConsoleMessage(() -> page.evaluate("console.error(window)"));
if (isFirefox()) {
assertEquals("JSHandle@object", message.text());
} else {
assertEquals("Window", message.text());
}
}
static boolean isWebKitWindows() {
return isWebKit() && getOS() == Utils.OS.WINDOWS;
}
@Test
@DisabledIf(value="isWebKitWindows", disabledReason="Upstream issue https://bugs.webkit.org/show_bug.cgi?id=229515")
void shouldTriggerCorrectLog() {
page.navigate("about:blank");
ConsoleMessage message = page.waitForConsoleMessage(() -> {
page.evaluate("async url => fetch(url).catch(e => {})", server.EMPTY_PAGE);
});
assertTrue(message.text().contains("Access-Control-Allow-Origin"));
assertEquals("error", message.type());
}
@Test
void shouldHaveLocationForConsoleAPICalls() {
page.navigate(server.EMPTY_PAGE);
ConsoleMessage message = page.waitForConsoleMessage(
new Page.WaitForConsoleMessageOptions().setPredicate(m -> "yellow".equals(m.text())),
() -> page.navigate(server.PREFIX + "/consolelog.html"));
assertEquals("log", message.type());
// Engines have different column notion.
assertTrue(message.location().startsWith(server.PREFIX + "/consolelog.html:7:"), message.location());
}
@Test
void shouldSupportPredicate() {
page.navigate(server.EMPTY_PAGE);
ConsoleMessage message = page.waitForConsoleMessage(
new Page.WaitForConsoleMessageOptions().setPredicate(m -> "info".equals(m.type())),
() -> {
page.evaluate("console.log(1)");
page.evaluate("console.info(2)");
});
assertEquals("2", message.text());
assertEquals("info", message.type());
}
}
@@ -0,0 +1,96 @@
/*
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.microsoft.playwright;
import com.google.gson.Gson;
import com.microsoft.playwright.options.HttpHeader;
import org.junit.jupiter.api.Test;
import java.util.*;
import java.util.concurrent.Semaphore;
import java.util.stream.Collectors;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestPageNetworkRequest extends TestBase {
@Test
void shouldReportRawHeaders() throws InterruptedException {
List<HttpHeader> serverHeaders = new ArrayList<>();
Semaphore responseWritten = new Semaphore(0);
server.setRoute("/headers", exchange -> {
for (Map.Entry<String, List<String>> entry : exchange.getRequestHeaders().entrySet()) {
for (String value : entry.getValue()) {
HttpHeader header = new HttpHeader();
header.name = entry.getKey();
header.value = value;
serverHeaders.add(header);
}
}
exchange.sendResponseHeaders(200, 0);
exchange.getResponseBody().close();
responseWritten.release();
});
page.navigate(server.EMPTY_PAGE);
Request request = page.waitForRequest("**/*", () -> {
page.evaluate("() => fetch('/headers', {\n" +
" headers: [\n" +
" ['header-a', 'value-a'],\n" +
" ['header-b', 'value-b'],\n" +
" ['header-a', 'value-a-1'],\n" +
" ['header-a', 'value-a-2'],\n" +
" ]\n" +
" })");
});
responseWritten.acquire();
List<HttpHeader> expectedHeaders = serverHeaders;
if (isWebKit() && isWindows) {
expectedHeaders = expectedHeaders.stream()
.filter(h -> !"accept-encoding".equals(h.name.toLowerCase()) && !"accept-language".equals(h.name.toLowerCase()))
.collect(Collectors.toList());
}
List<HttpHeader> headers = request.headersArray();
// Java HTTP server normalizes header names, work around that:
expectedHeaders = expectedHeaders.stream().map(h -> {
h.name = h.name.toLowerCase();
return h;
}).collect(Collectors.toList());
headers = headers.stream().map(h -> {
h.name = h.name.toLowerCase();
return h;
}).collect(Collectors.toList());
Comparator<HttpHeader> comparator = Comparator.comparing(h -> h.name);
expectedHeaders.sort(comparator);
headers.sort(comparator);
assertEquals(new Gson().toJsonTree(expectedHeaders), new Gson().toJsonTree(headers));
assertEquals("value-a, value-a-1, value-a-2", request.headerValue("header-a"));
assertEquals(null, request.headerValue("not-there"));
}
@Test
void shouldReportAllCookiesInOneHeader() {
page.navigate(server.EMPTY_PAGE);
page.evaluate("() => {\n" +
" document.cookie = 'myCookie=myValue';\n" +
" document.cookie = 'myOtherCookie=myOtherValue';\n" +
" }");
Response response = page.navigate(server.EMPTY_PAGE);
String cookie = response.request().allHeaders().get("cookie");
assertEquals("myCookie=myValue; myOtherCookie=myOtherValue", cookie);
}
}
@@ -0,0 +1,48 @@
/*
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.microsoft.playwright;
import com.microsoft.playwright.options.HttpHeader;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.stream.Collectors;
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestPageNetworkResponse extends TestBase {
@Test
void shouldReportMultipleSetCookieHeaders() {
server.setRoute("/headers", exchange -> {
exchange.getResponseHeaders().add("Set-Cookie", "a=b");
exchange.getResponseHeaders().add("Set-Cookie", "c=d");
exchange.sendResponseHeaders(200, 0);
exchange.getResponseBody().close();
});
page.navigate(server.EMPTY_PAGE);
Response response = page.waitForResponse("**/*", () -> page.evaluate("fetch('/headers')"));
List<HttpHeader> headers = response.headersArray();
List<String> cookies = headers.stream().filter(
httpHeader -> "set-cookie".equals(httpHeader.name.toLowerCase())).map(h -> h.value).collect(Collectors.toList());
assertEquals(asList("a=b", "c=d"), cookies);
assertEquals(null, response.headerValue("not-there"));
assertEquals("a=b\nc=d", response.headerValue("set-cookie"));
assertEquals(asList("a=b", "c=d"), response.headerValues("set-cookie"));
}
}
@@ -0,0 +1,92 @@
/*
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.microsoft.playwright;
import com.microsoft.playwright.options.Sizes;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class TestPageNetworkSizes extends TestBase {
@Test
void shouldSetBodySizeAndHeadersSize() {
page.navigate(server.EMPTY_PAGE);
Request request = page.waitForRequest("**/*", () -> {
page.evaluate("() => fetch('./get', { method: 'POST', body: '12345' }).then(r => r.text())");
});
Sizes sizes = request.sizes();
assertEquals(5, sizes.requestBodySize);
assertTrue(sizes.requestHeadersSize >= 250);
}
@Test
void shouldSetBodySizeTo0IfThereWasNoBody() {
page.navigate(server.EMPTY_PAGE);
Request request = page.waitForRequest("**/*",
() -> page.evaluate("() => fetch('./get').then(r => r.text())"));
Sizes sizes = request.sizes();
assertEquals(0, sizes.requestBodySize);
assertTrue(sizes.requestHeadersSize >= 200);
}
@Test
@Disabled("responseBodySize == 16")
void shouldSetBodySizeHeadersSizeAndTransferSize() throws ExecutionException, InterruptedException {
server.setRoute("/get", exchange -> {
// In Firefox, |fetch| will be hanging until it receives |Content-Type| header
// from server.
exchange.getResponseHeaders().add("Content-Type", "text/plain; charset=utf-8");
exchange.sendResponseHeaders(200, 0);
try (OutputStreamWriter writer = new OutputStreamWriter(exchange.getResponseBody())) {
writer.write("abc134");
}
});
Future<Server.Request> request = server.futureRequest("/get");
page.navigate(server.EMPTY_PAGE);
Response response = page.waitForResponse("**/*",
() -> page.evaluate("async () => fetch('./get').then(r => r.text())"));
request.get();
Sizes sizes = response.request().sizes();
assertEquals(6, sizes.responseBodySize);
assertTrue(sizes.responseHeadersSize >= 100);
}
@Test
@Disabled("responseBodySize == 5")
void shouldSetBodySizeTo0WhenThereWasNoResponseBody() {
Response response = page.navigate(server.EMPTY_PAGE);
Sizes sizes = response.request().sizes();
assertEquals(0, sizes.responseBodySize);
assertTrue(sizes.responseHeadersSize >= 100, "" + sizes.responseHeadersSize);
}
@Test
@Disabled("responseBodySize == 0")
void shouldHaveTheCorrectResponseBodySize() throws IOException {
Response response = page.navigate(server.PREFIX + "/simplezip.json");
Sizes sizes = response.request().sizes();
assertEquals(Files.size(Paths.get("src/test/resources/simplezip.json")), sizes.responseBodySize);
}}
@@ -189,7 +189,9 @@ public class TestPageRoute extends TestBase {
void shouldWorkWithCustomRefererHeaders() {
page.setExtraHTTPHeaders(mapOf("referer", server.EMPTY_PAGE));
page.route("**/*", route -> {
assertEquals(server.EMPTY_PAGE, route.request().headers().get("referer"));
String referer = route.request().headers().get("referer");
assertNotNull(referer);
assertTrue(referer.contains(server.EMPTY_PAGE), referer);
route.resume();
});
Response response = page.navigate(server.EMPTY_PAGE);
@@ -517,7 +519,13 @@ public class TestPageRoute extends TestBase {
"}");
fail("did not throw");
} catch (PlaywrightException e) {
assertTrue(e.getMessage().contains("failed"));
if (isChromium()) {
assertTrue(e.getMessage().contains("Failed"), e.getMessage());
} else if (isWebKit()) {
assertTrue(e.getMessage().contains("TypeError"), e.getMessage());
} else if (isFirefox()) {
assertTrue(e.getMessage().contains("NetworkError"), e.getMessage());
}
}
}
}
@@ -637,4 +645,16 @@ public class TestPageRoute extends TestBase {
}
}
@Test
void shouldSupportTheTimesParameterWithRouteMatching() {
int[] intercepted = {0};
page.route("**/empty.html", route -> {
++intercepted[0];
route.resume();
}, new Page.RouteOptions().setTimes(1));
page.navigate(server.EMPTY_PAGE);
page.navigate(server.EMPTY_PAGE);
page.navigate(server.EMPTY_PAGE);
assertEquals(1, intercepted[0]);
}
}
@@ -77,4 +77,23 @@ public class TestTracing extends TestBase {
assertTrue(Files.exists(traceFile2));
}
@Test
void shouldWorkWithMultipleChunks(@TempDir Path tempDir) {
context.tracing().start(new Tracing.StartOptions().setScreenshots(true).setSnapshots(true));
page.navigate(server.PREFIX + "/frames/frame.html");
context.tracing().startChunk();
page.setContent("<button>Click</button>");
page.click("'Click'");
Path traceFile1 = tempDir.resolve("trace1.zip");
context.tracing().stopChunk(new Tracing.StopChunkOptions().setPath(traceFile1));
context.tracing().startChunk();
page.hover("'Click'");
Path traceFile2 = tempDir.resolve("trace2.zip");
context.tracing().stopChunk(new Tracing.StopChunkOptions().setPath(traceFile2));
assertTrue(Files.exists(traceFile1));
assertTrue(Files.exists(traceFile2));
}
}
@@ -0,0 +1,140 @@
/*
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.microsoft.playwright;
import org.junit.jupiter.api.Test;
import java.util.Map;
import static com.microsoft.playwright.Utils.mapOf;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestWheel extends TestBase {
@Test
void shouldDispatchWheelEvents() {
page.setContent("<div style='width: 5000px; height: 5000px;'></div>");
page.mouse().move(50, 60);
listenForWheelEvents(page, "div");
page.mouse().wheel(0, 100);
Map<String, Object> expected = mapOf(
"deltaX", 0,
"deltaY", 100,
"clientX", 50,
"clientY", 60,
"deltaMode", 0,
"ctrlKey", false,
"shiftKey", false,
"altKey", false,
"metaKey", false);
assertEquals(expected, page.evaluate("window.lastEvent"));
page.waitForFunction("window.scrollY === 100");
}
@Test
void shouldScrollWhenNobodyIsListening() {
page.navigate(server.PREFIX + "/input/scrollable.html");
page.mouse().move(50, 60);
page.mouse().wheel(0, 100);
page.waitForFunction("window.scrollY === 100");
}
@Test
void shouldSetTheModifiers() {
page.setContent("<div style='width: 5000px; height: 5000px;'></div>");
page.mouse().move(50, 60);
listenForWheelEvents(page, "div");
page.keyboard().down("Shift");
page.mouse().wheel(0, 100);
Map<String, Object> expected = mapOf(
"deltaX", 0,
"deltaY", 100,
"clientX", 50,
"clientY", 60,
"deltaMode", 0,
"ctrlKey", false,
"shiftKey", true,
"altKey", false,
"metaKey", false);
assertEquals(expected, page.evaluate("window.lastEvent"));
}
@Test
void shouldScrollHorizontally() {
page.setContent("<div style='width: 5000px; height: 5000px;'></div>");
page.mouse().move(50, 60);
listenForWheelEvents(page, "div");
page.mouse().wheel(100, 0);
Map<String, Object> expected = mapOf(
"deltaX", 100,
"deltaY", 0,
"clientX", 50,
"clientY", 60,
"deltaMode", 0,
"ctrlKey", false,
"shiftKey", false,
"altKey", false,
"metaKey", false);
assertEquals(expected, page.evaluate("window.lastEvent"));
page.waitForFunction("window.scrollX === 100");
}
@Test
void shouldWorkWhenTheEventIsCanceled() {
page.setContent("<div style='width: 5000px; height: 5000px;'></div>");
page.mouse().move(50, 60);
listenForWheelEvents(page, "div");
page.evaluate("() => {\n" +
" document.querySelector('div').addEventListener('wheel', e => e.preventDefault());\n" +
" }");
page.mouse().wheel(0, 100);
Map<String, Object> expected = mapOf(
"deltaX", 0,
"deltaY", 100,
"clientX", 50,
"clientY", 60,
"deltaMode", 0,
"ctrlKey", false,
"shiftKey", false,
"altKey", false,
"metaKey", false);
assertEquals(expected, page.evaluate("window.lastEvent"));
// give the page a chacne to scroll
page.waitForTimeout(100);
// ensure that it did not.
assertEquals(0, page.evaluate("window.scrollY"));
}
private static void listenForWheelEvents(Page page, String selector) {
page.evaluate("selector => {\n" +
" document.querySelector(selector).addEventListener('wheel', e => {\n" +
" window['lastEvent'] = {\n" +
" deltaX: e.deltaX,\n" +
" deltaY: e.deltaY,\n" +
" clientX: e.clientX,\n" +
" clientY: e.clientY,\n" +
" deltaMode: e.deltaMode,\n" +
" ctrlKey: e.ctrlKey,\n" +
" shiftKey: e.shiftKey,\n" +
" altKey: e.altKey,\n" +
" metaKey: e.metaKey,\n" +
" };\n" +
" }, { passive: false });\n" +
" }", selector);
}
}
@@ -51,7 +51,7 @@ public class TestWorkers extends TestBase {
try {
workerThisObj.getProperty("self");
} catch (PlaywrightException e) {
assertTrue(e.getMessage().contains("Most likely the worker has been closed."));
assertTrue(e.getMessage().contains("Target closed"), e.getMessage());
}
}
@@ -0,0 +1,340 @@
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
{"foo": "bar"}
+4 -1
View File
@@ -6,7 +6,7 @@
<groupId>com.microsoft.playwright</groupId>
<artifactId>parent-pom</artifactId>
<version>1.14.0-SNAPSHOT</version>
<version>1.15.2</version>
<packaging>pom</packaging>
<name>Playwright Parent Project</name>
<description>Java library to automate Chromium, Firefox and WebKit with a single API.
@@ -123,6 +123,9 @@
junit.jupiter.execution.parallel.config.dynamic.factor=0.5
</configurationParameters>
</properties>
<failIfNoTests>
false
</failIfNoTests>
</configuration>
</plugin>
<plugin>
+1 -1
View File
@@ -1 +1 @@
1.14.0-1628878084000
1.15.2-1633455481000
+1 -1
View File
@@ -6,7 +6,7 @@
<groupId>com.microsoft.playwright</groupId>
<artifactId>api-generator</artifactId>
<version>1.14.0-SNAPSHOT</version>
<version>1.15.2</version>
<name>Playwright - API Generator</name>
<description>
This is an internal module used to generate Java API from the upstream Playwright
@@ -160,6 +160,9 @@ abstract class Element {
while (matcher.find()) {
linkified += paragraph.substring(start, matcher.start());
String name = matcher.group(2);
if (ApiGenerator.aliases.containsKey(name)) {
name = ApiGenerator.aliases.get(name);
}
if ("event".equals(matcher.group(1))) {
String[] parts = name.split("\\.");
name = parts[0] + ".on" + toTitle(parts[1]);
@@ -249,6 +252,9 @@ class TypeRef extends Element {
customTypeNames.put("BrowserContext.addCookies.cookies", "Cookie");
customTypeNames.put("BrowserContext.cookies", "Cookie");
customTypeNames.put("Request.headersArray", "HttpHeader");
customTypeNames.put("Response.headersArray", "HttpHeader");
customTypeNames.put("Locator.selectOption.values", "SelectOption");
customTypeNames.put("ElementHandle.selectOption.values", "SelectOption");
customTypeNames.put("Frame.selectOption.values", "SelectOption");
@@ -790,6 +796,7 @@ class Field extends Element {
args.add(f.name);
}
if (!params.isEmpty()) {
writeJavadoc(output, offset, comment());
output.add(offset + "public " + parentClass + " set" + toTitle(name) + "(" + String.join(", ", params) + ") {");
output.add(offset + " return set" + toTitle(name) + "(new " + type.toJava() + "(" + String.join(", ", args) + "));");
output.add(offset + "}");
@@ -806,6 +813,7 @@ class Field extends Element {
}
private void writeGenericBuilderMethod(List<String> output, String offset, String parentClass, String paramType) {
writeJavadoc(output, offset, comment());
output.add(offset + "public " + parentClass + " set" + toTitle(name) + "(" + paramType + " " + name + ") {");
String rvalue = type.isNullable() ? "Optional.ofNullable(" + name + ")" : name;
output.add(offset + " this." + name + " = " + rvalue + ";");
@@ -1048,12 +1056,16 @@ class Enum extends TypeDefinition {
}
public class ApiGenerator {
// TODO: make it an instance field.
static final Map<String, String> aliases = new HashMap<>();
ApiGenerator(Reader reader) throws IOException {
JsonArray api = new Gson().fromJson(reader, JsonArray.class);
File cwd = FileSystems.getDefault().getPath(".").toFile();
File dir = new File(cwd, "playwright/src/main/java/com/microsoft/playwright");
System.out.println("Writing files to: " + dir.getCanonicalPath());
filterOtherLangs(api);
Stack<String> path = new Stack<>();
filterOtherLangs(api, path);
Map<String, TypeDefinition> topLevelTypes = new HashMap<>();
for (JsonElement entry: api) {
String name = entry.getAsJsonObject().get("name").getAsString();
@@ -1080,14 +1092,14 @@ public class ApiGenerator {
}
}
private static void filterOtherLangs(JsonElement json) {
private static void filterOtherLangs(JsonElement json, Stack<String> path) {
if (json.isJsonArray()) {
List<Integer> toRemove = new ArrayList<>();
JsonArray array = json.getAsJsonArray();
for (int i = 0; i < array.size(); i++) {
JsonElement item = array.get(i);
if (isSupported(item)) {
filterOtherLangs(item);
filterOtherLangs(item, path);
} else {
toRemove.add(i);
}
@@ -1099,19 +1111,25 @@ public class ApiGenerator {
} else if (json.isJsonObject()) {
List<String> toRemove = new ArrayList<>();
JsonObject object = json.getAsJsonObject();
path.push(object.has("name") ? object.get("name").getAsString() : "<none>");
String alias = alias(object);
if (alias != null) {
List<String> aliasPath = new ArrayList<>(path);
aliasPath.set(aliasPath.size() - 1, alias);
aliases.put(String.join(".", path), String.join(".", aliasPath));
// Rename in place.
object.addProperty("name", alias);
}
overrideType(object);
for (Map.Entry<String, JsonElement> entry : object.entrySet()) {
if (isSupported(entry.getValue())) {
filterOtherLangs(entry.getValue());
filterOtherLangs(entry.getValue(), path);
} else {
toRemove.add(entry.getKey());
}
}
path.pop();
for (String key : toRemove) {
object.remove(key);
}
+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.14.0-SNAPSHOT</version>
<version>1.15.2</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.14.0-SNAPSHOT</version>
<version>1.15.2</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.14.0-SNAPSHOT</version>
<version>1.15.2</version>
<name>Playwright - Update Version in Documentation</name>
<description>
This is an internal module used to update versions in the documentation based on