chore: roll to 1.59.0-alpha (#1900)
This commit is contained in:
@@ -6,7 +6,7 @@ description: Roll Playwright Java to a new version
|
||||
Help the user roll to a new version of Playwright.
|
||||
ROLLING.md contains general instructions and scripts.
|
||||
|
||||
Start with updating the version and generating the API to see the state of things.
|
||||
Start with running ./scripts/roll_driver.sh to update the version and generate the API to see the state of things.
|
||||
Afterwards, work through the list of changes that need to be backported.
|
||||
You can find a list of pull requests that might need to be taking into account in the issue titled "Backport changes".
|
||||
Work through them one-by-one and check off the items that you have handled.
|
||||
@@ -16,6 +16,126 @@ Rolling includes:
|
||||
- updating client implementation to match changes in the upstream JS implementation (see ../playwright/packages/playwright-core/src/client)
|
||||
- adding a couple of new tests to verify new/changed functionality
|
||||
|
||||
## Mimicking the JavaScript implementation
|
||||
|
||||
The Java client is a port of the JS client in `../playwright/packages/playwright-core/src/client/`. When implementing a new or changed method, always read the corresponding JS file first and mirror its logic:
|
||||
|
||||
```
|
||||
../playwright/packages/playwright-core/src/client/browserContext.ts
|
||||
../playwright/packages/playwright-core/src/client/page.ts
|
||||
../playwright/packages/playwright-core/src/client/tracing.ts
|
||||
../playwright/packages/playwright-core/src/client/video.ts
|
||||
../playwright/packages/playwright-core/src/client/locator.ts
|
||||
../playwright/packages/playwright-core/src/client/network.ts
|
||||
...
|
||||
```
|
||||
|
||||
Key translation rules:
|
||||
|
||||
**Protocol calls** — `await this._channel.methodName(params)` → `sendMessage("methodName", params, NO_TIMEOUT)`
|
||||
|
||||
**Extracting a returned channel object from a result** — JS uses `SomeClass.from(result.foo)` which resolves the JS-side object for a channel reference. In Java, the object was already created when the server sent `__create__`, so extract it from the connection: `connection.getExistingObject(result.getAsJsonObject("foo").get("guid").getAsString())`
|
||||
|
||||
**Async/await** — all `await` calls become synchronous `sendMessage(...)` calls since the Java client is synchronous.
|
||||
|
||||
**`undefined` / optional params** — JS `options?.foo` checks translate to `if (options != null && options.foo != null)` null checks before adding to the params `JsonObject`.
|
||||
|
||||
**`_channel` fields** — the JS `this._channel.foo` maps to calling `sendMessage("foo", ...)` on `this` in the Impl class.
|
||||
|
||||
**Channel object references in params** — when a JS call passes a channel object as a param (e.g. `{ frame: frame._channel }`), in Java pass the guid: `params.addProperty("frame", ((FrameImpl) frame).guid)`.
|
||||
|
||||
## Fixing generator and compilation errors
|
||||
|
||||
After running `./scripts/roll_driver.sh`, the build often fails because the generated Java interfaces reference new types or methods that the generator doesn't know how to handle yet, and the `*Impl` classes don't implement new interface methods.
|
||||
|
||||
### ApiGenerator.java fixes (tools/api-generator/src/main/java/com/microsoft/playwright/tools/ApiGenerator.java)
|
||||
|
||||
The generator has hardcoded lists that control which imports are added to each generated file. When new classes appear in the API, add them to the relevant lists in `Interface.writeTo`:
|
||||
- `options.*` import list — add new classes that use types from the options package
|
||||
- `java.util.*` import list — add new classes that use `List`, `Map`, etc.
|
||||
- `java.util.function.Consumer` list — add new classes with `Consumer`-typed event handlers
|
||||
|
||||
Type mapping: when JS-only types (like `Disposable`) are used as return types in Java-compatible methods, add a mapping in `convertBuiltinType`. For example, `Disposable` → `AutoCloseable`.
|
||||
|
||||
Event handler generation: events with `void` type generate invalid `Consumer<void>`. Handle this case in `Event.writeListenerMethods` by emitting `Runnable` instead.
|
||||
|
||||
After editing the generator, recompile and re-run it:
|
||||
```
|
||||
mvn -f tools/api-generator/pom.xml compile -q
|
||||
mvn -f tools/api-generator/pom.xml exec:java -Dexec.mainClass=com.microsoft.playwright.tools.ApiGenerator
|
||||
```
|
||||
|
||||
### Impl class fixes (playwright/src/main/java/com/microsoft/playwright/impl/)
|
||||
|
||||
After regenerating, compile `playwright/` to find what's missing:
|
||||
```
|
||||
mvn -f playwright/pom.xml compile 2>&1 | grep "ERROR"
|
||||
```
|
||||
|
||||
Common patterns:
|
||||
|
||||
**Return type changed (e.g. `void` → `AutoCloseable`):** Update the method signature in the Impl class and return an appropriate `AutoCloseable`. Check the JS client to see what kind of disposable is used:
|
||||
- If JS returns `DisposableObject.from(result.disposable)` — the server created a disposable channel object. Extract its guid from the protocol result and return `connection.getExistingObject(guid)` (a `DisposableObject`).
|
||||
- If JS returns `new DisposableStub(() => this.someCleanup())` — it's a local callback. Return `new DisposableStub(this::someCleanup)` in Java.
|
||||
- Examples: `addInitScript`/`exposeBinding`/`exposeFunction` → `DisposableObject`; `route(...)` → `DisposableStub(() -> unroute(...))`; `Tracing.group` → `DisposableStub(this::groupEnd)`; `Video.start` → `DisposableStub(this::stop)`.
|
||||
|
||||
**New method missing:** Add a stub implementation. Common patterns:
|
||||
- Simple protocol message: `sendMessage("methodName", params, NO_TIMEOUT)`
|
||||
- New property accessor (e.g. from initializer): `return initializer.get("fieldName").getAsString()`
|
||||
- Delegation to mainFrame (for Page methods): `return mainFrame.locator(":root").method(...)`
|
||||
|
||||
**New interface entirely (e.g. `Debugger`):** Create a new `*Impl` class extending `ChannelOwner`, implement the interface, and register the type in `Connection.java`'s switch statement. Initialize the field from the parent's initializer in the parent's constructor (e.g. `connection.getExistingObject(initializer.getAsJsonObject("debugger").get("guid").getAsString())`).
|
||||
|
||||
**Field visibility:** If a field needs to be accessed from a sibling Impl class (e.g. setting `existingResponse` on `RequestImpl` from `BrowserContextImpl`), change it from `private` to package-private.
|
||||
|
||||
**`ListenerCollection` only supports `Consumer<T>`, not `Runnable`.** For void events that use `Runnable` handlers, maintain a plain `List<Runnable>` instead.
|
||||
|
||||
**Protocol changes that remove events** — when a method's response now returns an object directly instead of via a subsequent event, update the Impl to capture it from the `sendMessage` result and remove the old event handler. Example: `videoStart` used to fire a `"video"` page event to deliver the artifact; it now returns the artifact directly in the response. Check git history of the upstream JS client when tests hang unexpectedly.
|
||||
|
||||
**Protocol parameter renames** — protocol parameter names can change between versions (e.g. `wsEndpoint` → `endpoint` in `BrowserType.connect`). When a test fails with `expected string, got undefined` or similar validation errors from the driver, check `packages/protocol/src/protocol.yml` for the current parameter names and update the corresponding `params.addProperty(...)` call in the Impl class. Also check the JS client (`src/client/`) to see how it builds the params object.
|
||||
|
||||
## Porting and verifying tests
|
||||
|
||||
**Before porting an upstream test file, check the API exists in Java.** The upstream repo may have test files for brand-new APIs that haven't been added to the Java interface yet (e.g., `screencast.spec.ts` tests `page.screencast` which may not be in the generated `Page.java`). Check `git diff main --name-only` to see what interfaces were added this roll, and verify the method exists in the generated Java interface before porting.
|
||||
|
||||
**Java test file names don't always match upstream spec names.** `TestScreencast.java` tests `recordVideo` video-file recording (which corresponds to `video.spec.ts`), not the newer `page.screencast` streaming API (`screencast.spec.ts`). When comparing coverage, check test *content*, not just file names.
|
||||
|
||||
**Remove tests for behavior that was removed upstream.** When the JS client drops a client-side error check (e.g., "Page is not yet closed before saveAs", "Page did not produce any video frames"), delete the corresponding Java tests rather than trying to keep them passing. Check the upstream `tests/library/` spec to confirm the behavior is gone.
|
||||
|
||||
**Run the full suite to catch regressions, re-run flaky failures in isolation.** Some tests (e.g., `TestClientCertificates#shouldKeepSupportingHttp`) time out only under heavy parallel load. Run the failing test alone to confirm it's flaky before investigating further.
|
||||
|
||||
## Commit Convention
|
||||
|
||||
Semantic commit messages: `label(scope): description`
|
||||
|
||||
Labels: `fix`, `feat`, `chore`, `docs`, `test`, `devops`
|
||||
|
||||
```bash
|
||||
git checkout -b fix-39562
|
||||
# ... make changes ...
|
||||
git add <changed-files>
|
||||
git commit -m "$(cat <<'EOF'
|
||||
fix(proxy): handle SOCKS proxy authentication
|
||||
|
||||
Fixes: https://github.com/microsoft/playwright-java/issues/39562
|
||||
EOF
|
||||
)"
|
||||
git push origin fix-39562
|
||||
gh pr create --repo microsoft/playwright-java --head username:fix-39562 \
|
||||
--title "fix(proxy): handle SOCKS proxy authentication" \
|
||||
--body "$(cat <<'EOF'
|
||||
## Summary
|
||||
- <describe the change very! briefly>
|
||||
|
||||
Fixes https://github.com/microsoft/playwright-java/issues/39562
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
Never add Co-Authored-By agents in commit message.
|
||||
Never add "Generated with" in commit message.
|
||||
Branch naming for issue fixes: `fix-<issue-number>`
|
||||
|
||||
## Tips & Tricks
|
||||
- Project checkouts are in the parent directory (`../`).
|
||||
- When updating checkboxes, store the issue content into /tmp and edit it there, then update the issue based on the file
|
||||
|
||||
@@ -10,9 +10,9 @@ Playwright is a Java library to automate [Chromium](https://www.chromium.org/Hom
|
||||
|
||||
| | Linux | macOS | Windows |
|
||||
| :--- | :---: | :---: | :---: |
|
||||
| Chromium <!-- GEN:chromium-version -->145.0.7632.6<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| Chromium <!-- GEN:chromium-version -->146.0.7680.31<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| WebKit <!-- GEN:webkit-version -->26.0<!-- GEN:stop --> | ✅ | ✅ | ✅ |
|
||||
| Firefox <!-- GEN:firefox-version -->146.0.1<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| Firefox <!-- GEN:firefox-version -->148.0.2<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
+2
-14
@@ -2,18 +2,6 @@
|
||||
|
||||
* make sure to have at least Java 8 and Maven 3.6.3
|
||||
* clone playwright for java: http://github.com/microsoft/playwright-java
|
||||
* `./scripts/roll_driver.sh 1.47.0-beta-1726138322000`
|
||||
* roll the driver and update generated sources: `./scripts/roll_driver.sh next`
|
||||
* fix any errors
|
||||
* commit & send PR with the roll
|
||||
|
||||
## Finding driver version
|
||||
|
||||
For development versions of Playwright, you can find the latest version by looking at [publish_canary](https://github.com/microsoft/playwright/actions/workflows/publish_canary.yml) workflow -> `publish canary NPM & Publish canary Docker` -> `build & publish driver` step -> `PACKAGE_VERSION`
|
||||
<img width="960" alt="image" src="https://github.com/microsoft/playwright-java/assets/9798949/4f33a7f1-b39a-4179-8ae7-fb1d84094c75">
|
||||
|
||||
|
||||
# Updating Version
|
||||
|
||||
```bash
|
||||
./scripts/set_maven_version.sh 1.15.0
|
||||
```
|
||||
|
||||
|
||||
@@ -514,6 +514,12 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* @since v1.45
|
||||
*/
|
||||
Clock clock();
|
||||
/**
|
||||
* Debugger allows to pause and resume the execution.
|
||||
*
|
||||
* @since v1.59
|
||||
*/
|
||||
Debugger debugger();
|
||||
/**
|
||||
* Adds cookies into this browser context. All pages within this context will have these cookies installed. Cookies can be
|
||||
* obtained via {@link com.microsoft.playwright.BrowserContext#cookies BrowserContext.cookies()}.
|
||||
@@ -552,7 +558,7 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* @param script Script to be evaluated in all pages in the browser context.
|
||||
* @since v1.8
|
||||
*/
|
||||
void addInitScript(String script);
|
||||
AutoCloseable addInitScript(String script);
|
||||
/**
|
||||
* Adds a script which would be evaluated in one of the following scenarios:
|
||||
* <ul>
|
||||
@@ -579,7 +585,7 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* @param script Script to be evaluated in all pages in the browser context.
|
||||
* @since v1.8
|
||||
*/
|
||||
void addInitScript(Path script);
|
||||
AutoCloseable addInitScript(Path script);
|
||||
/**
|
||||
* @deprecated Background pages have been removed from Chromium together with Manifest V2 extensions.
|
||||
*
|
||||
@@ -730,8 +736,8 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* @param callback Callback function that will be called in the Playwright's context.
|
||||
* @since v1.8
|
||||
*/
|
||||
default void exposeBinding(String name, BindingCallback callback) {
|
||||
exposeBinding(name, callback, null);
|
||||
default AutoCloseable exposeBinding(String name, BindingCallback callback) {
|
||||
return exposeBinding(name, callback, null);
|
||||
}
|
||||
/**
|
||||
* The method adds a function called {@code name} on the {@code window} object of every frame in every page in the context.
|
||||
@@ -777,7 +783,7 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* @param callback Callback function that will be called in the Playwright's context.
|
||||
* @since v1.8
|
||||
*/
|
||||
void exposeBinding(String name, BindingCallback callback, ExposeBindingOptions options);
|
||||
AutoCloseable exposeBinding(String name, BindingCallback callback, ExposeBindingOptions options);
|
||||
/**
|
||||
* The method adds a function called {@code name} on the {@code window} object of every frame in every page in the context.
|
||||
* When called, the function executes {@code callback} and returns a <a
|
||||
@@ -836,7 +842,7 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* @param callback Callback function that will be called in the Playwright's context.
|
||||
* @since v1.8
|
||||
*/
|
||||
void exposeFunction(String name, FunctionCallback callback);
|
||||
AutoCloseable exposeFunction(String name, FunctionCallback callback);
|
||||
/**
|
||||
* Grants specified permissions to the browser context. Only grants corresponding permissions to the given origin if
|
||||
* specified.
|
||||
@@ -865,6 +871,7 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* <li> {@code "notifications"}</li>
|
||||
* <li> {@code "payment-handler"}</li>
|
||||
* <li> {@code "storage-access"}</li>
|
||||
* <li> {@code "screen-wake-lock"}</li>
|
||||
* </ul>
|
||||
* @since v1.8
|
||||
*/
|
||||
@@ -899,10 +906,17 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* <li> {@code "notifications"}</li>
|
||||
* <li> {@code "payment-handler"}</li>
|
||||
* <li> {@code "storage-access"}</li>
|
||||
* <li> {@code "screen-wake-lock"}</li>
|
||||
* </ul>
|
||||
* @since v1.8
|
||||
*/
|
||||
void grantPermissions(List<String> permissions, GrantPermissionsOptions options);
|
||||
/**
|
||||
* Indicates that the browser context is in the process of closing or has already been closed.
|
||||
*
|
||||
* @since v1.59
|
||||
*/
|
||||
boolean isClosed();
|
||||
/**
|
||||
* <strong>NOTE:</strong> CDP sessions are only supported on Chromium-based browsers.
|
||||
*
|
||||
@@ -994,8 +1008,8 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* @param handler handler function to route the request.
|
||||
* @since v1.8
|
||||
*/
|
||||
default void route(String url, Consumer<Route> handler) {
|
||||
route(url, handler, null);
|
||||
default AutoCloseable route(String url, Consumer<Route> handler) {
|
||||
return route(url, handler, null);
|
||||
}
|
||||
/**
|
||||
* Routing provides the capability to modify network requests that are made by any page in the browser context. Once route
|
||||
@@ -1050,7 +1064,7 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* @param handler handler function to route the request.
|
||||
* @since v1.8
|
||||
*/
|
||||
void route(String url, Consumer<Route> handler, RouteOptions options);
|
||||
AutoCloseable 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.
|
||||
@@ -1104,8 +1118,8 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* @param handler handler function to route the request.
|
||||
* @since v1.8
|
||||
*/
|
||||
default void route(Pattern url, Consumer<Route> handler) {
|
||||
route(url, handler, null);
|
||||
default AutoCloseable route(Pattern url, Consumer<Route> handler) {
|
||||
return route(url, handler, null);
|
||||
}
|
||||
/**
|
||||
* Routing provides the capability to modify network requests that are made by any page in the browser context. Once route
|
||||
@@ -1160,7 +1174,7 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* @param handler handler function to route the request.
|
||||
* @since v1.8
|
||||
*/
|
||||
void route(Pattern url, Consumer<Route> handler, RouteOptions options);
|
||||
AutoCloseable 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.
|
||||
@@ -1214,8 +1228,8 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* @param handler handler function to route the request.
|
||||
* @since v1.8
|
||||
*/
|
||||
default void route(Predicate<String> url, Consumer<Route> handler) {
|
||||
route(url, handler, null);
|
||||
default AutoCloseable route(Predicate<String> url, Consumer<Route> handler) {
|
||||
return route(url, handler, null);
|
||||
}
|
||||
/**
|
||||
* Routing provides the capability to modify network requests that are made by any page in the browser context. Once route
|
||||
@@ -1270,7 +1284,7 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* @param handler handler function to route the request.
|
||||
* @since v1.8
|
||||
*/
|
||||
void route(Predicate<String> url, Consumer<Route> handler, RouteOptions options);
|
||||
AutoCloseable route(Predicate<String> url, Consumer<Route> handler, RouteOptions options);
|
||||
/**
|
||||
* If specified the network requests that are made in the context will be served from the HAR file. Read more about <a
|
||||
* href="https://playwright.dev/java/docs/mock#replaying-from-har">Replaying from HAR</a>.
|
||||
@@ -1459,6 +1473,21 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* @since v1.8
|
||||
*/
|
||||
String storageState(StorageStateOptions options);
|
||||
/**
|
||||
* Clears the existing cookies, local storage and IndexedDB entries for all origins and sets the new storage state.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* // Load storage state from a file and apply it to the context.
|
||||
* context.setStorageState(Paths.get("state.json"));
|
||||
* }</pre>
|
||||
*
|
||||
* @param storageState Populates context with given storage state. This option can be used to initialize context with logged-in information
|
||||
* obtained via {@link com.microsoft.playwright.BrowserContext#storageState BrowserContext.storageState()}. Path to the
|
||||
* file with saved storage state.
|
||||
* @since v1.59
|
||||
*/
|
||||
void setStorageState(Path storageState);
|
||||
/**
|
||||
*
|
||||
*
|
||||
@@ -1476,7 +1505,7 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* Removes a route created with {@link com.microsoft.playwright.BrowserContext#route BrowserContext.route()}. When {@code
|
||||
* handler} is not specified, removes all routes for the {@code url}.
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] used to register a routing with {@link
|
||||
* @param url A glob pattern, regex pattern, or predicate receiving [URL] used to register a routing with {@link
|
||||
* com.microsoft.playwright.BrowserContext#route BrowserContext.route()}.
|
||||
* @since v1.8
|
||||
*/
|
||||
@@ -1487,7 +1516,7 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* Removes a route created with {@link com.microsoft.playwright.BrowserContext#route BrowserContext.route()}. When {@code
|
||||
* handler} is not specified, removes all routes for the {@code url}.
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] used to register a routing with {@link
|
||||
* @param url A glob pattern, regex pattern, or predicate receiving [URL] used to register a routing with {@link
|
||||
* com.microsoft.playwright.BrowserContext#route BrowserContext.route()}.
|
||||
* @param handler Optional handler function used to register a routing with {@link com.microsoft.playwright.BrowserContext#route
|
||||
* BrowserContext.route()}.
|
||||
@@ -1498,7 +1527,7 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* Removes a route created with {@link com.microsoft.playwright.BrowserContext#route BrowserContext.route()}. When {@code
|
||||
* handler} is not specified, removes all routes for the {@code url}.
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] used to register a routing with {@link
|
||||
* @param url A glob pattern, regex pattern, or predicate receiving [URL] used to register a routing with {@link
|
||||
* com.microsoft.playwright.BrowserContext#route BrowserContext.route()}.
|
||||
* @since v1.8
|
||||
*/
|
||||
@@ -1509,7 +1538,7 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* Removes a route created with {@link com.microsoft.playwright.BrowserContext#route BrowserContext.route()}. When {@code
|
||||
* handler} is not specified, removes all routes for the {@code url}.
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] used to register a routing with {@link
|
||||
* @param url A glob pattern, regex pattern, or predicate receiving [URL] used to register a routing with {@link
|
||||
* com.microsoft.playwright.BrowserContext#route BrowserContext.route()}.
|
||||
* @param handler Optional handler function used to register a routing with {@link com.microsoft.playwright.BrowserContext#route
|
||||
* BrowserContext.route()}.
|
||||
@@ -1520,7 +1549,7 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* Removes a route created with {@link com.microsoft.playwright.BrowserContext#route BrowserContext.route()}. When {@code
|
||||
* handler} is not specified, removes all routes for the {@code url}.
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] used to register a routing with {@link
|
||||
* @param url A glob pattern, regex pattern, or predicate receiving [URL] used to register a routing with {@link
|
||||
* com.microsoft.playwright.BrowserContext#route BrowserContext.route()}.
|
||||
* @since v1.8
|
||||
*/
|
||||
@@ -1531,7 +1560,7 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* Removes a route created with {@link com.microsoft.playwright.BrowserContext#route BrowserContext.route()}. When {@code
|
||||
* handler} is not specified, removes all routes for the {@code url}.
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] used to register a routing with {@link
|
||||
* @param url A glob pattern, regex pattern, or predicate receiving [URL] used to register a routing with {@link
|
||||
* com.microsoft.playwright.BrowserContext#route BrowserContext.route()}.
|
||||
* @param handler Optional handler function used to register a routing with {@link com.microsoft.playwright.BrowserContext#route
|
||||
* BrowserContext.route()}.
|
||||
|
||||
@@ -184,6 +184,12 @@ public interface BrowserType {
|
||||
* href="https://peter.sh/experiments/chromium-command-line-switches/">here</a>.
|
||||
*/
|
||||
public List<String> args;
|
||||
/**
|
||||
* If specified, artifacts (traces, videos, downloads, HAR files, etc.) are saved into this directory. The directory is not
|
||||
* cleaned up when the browser closes. If not specified, a temporary directory is used and cleaned up when the browser
|
||||
* closes.
|
||||
*/
|
||||
public Path artifactsDir;
|
||||
/**
|
||||
* Browser distribution channel.
|
||||
*
|
||||
@@ -279,6 +285,15 @@ public interface BrowserType {
|
||||
this.args = args;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* If specified, artifacts (traces, videos, downloads, HAR files, etc.) are saved into this directory. The directory is not
|
||||
* cleaned up when the browser closes. If not specified, a temporary directory is used and cleaned up when the browser
|
||||
* closes.
|
||||
*/
|
||||
public LaunchOptions setArtifactsDir(Path artifactsDir) {
|
||||
this.artifactsDir = artifactsDir;
|
||||
return this;
|
||||
}
|
||||
@Deprecated
|
||||
/**
|
||||
* Browser distribution channel.
|
||||
@@ -445,6 +460,12 @@ public interface BrowserType {
|
||||
* href="https://peter.sh/experiments/chromium-command-line-switches/">here</a>.
|
||||
*/
|
||||
public List<String> args;
|
||||
/**
|
||||
* If specified, artifacts (traces, videos, downloads, HAR files, etc.) are saved into this directory. The directory is not
|
||||
* cleaned up when the browser closes. If not specified, a temporary directory is used and cleaned up when the browser
|
||||
* closes.
|
||||
*/
|
||||
public Path artifactsDir;
|
||||
/**
|
||||
* When using {@link com.microsoft.playwright.Page#navigate Page.navigate()}, {@link com.microsoft.playwright.Page#route
|
||||
* Page.route()}, {@link com.microsoft.playwright.Page#waitForURL Page.waitForURL()}, {@link
|
||||
@@ -739,6 +760,15 @@ public interface BrowserType {
|
||||
this.args = args;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* If specified, artifacts (traces, videos, downloads, HAR files, etc.) are saved into this directory. The directory is not
|
||||
* cleaned up when the browser closes. If not specified, a temporary directory is used and cleaned up when the browser
|
||||
* closes.
|
||||
*/
|
||||
public LaunchPersistentContextOptions setArtifactsDir(Path artifactsDir) {
|
||||
this.artifactsDir = artifactsDir;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* When using {@link com.microsoft.playwright.Page#navigate Page.navigate()}, {@link com.microsoft.playwright.Page#route
|
||||
* Page.route()}, {@link com.microsoft.playwright.Page#waitForURL Page.waitForURL()}, {@link
|
||||
@@ -1224,11 +1254,11 @@ public interface BrowserType {
|
||||
* <p> <strong>NOTE:</strong> The major and minor version of the Playwright instance that connects needs to match the version of Playwright that
|
||||
* launches the browser (1.2.3 → is compatible with 1.2.x).
|
||||
*
|
||||
* @param wsEndpoint A Playwright browser websocket endpoint to connect to. You obtain this endpoint via {@code BrowserServer.wsEndpoint}.
|
||||
* @param endpoint A Playwright browser websocket endpoint to connect to. You obtain this endpoint via {@code BrowserServer.wsEndpoint}.
|
||||
* @since v1.8
|
||||
*/
|
||||
default Browser connect(String wsEndpoint) {
|
||||
return connect(wsEndpoint, null);
|
||||
default Browser connect(String endpoint) {
|
||||
return connect(endpoint, null);
|
||||
}
|
||||
/**
|
||||
* This method attaches Playwright to an existing browser instance created via {@code BrowserType.launchServer} in Node.js.
|
||||
@@ -1236,10 +1266,10 @@ public interface BrowserType {
|
||||
* <p> <strong>NOTE:</strong> The major and minor version of the Playwright instance that connects needs to match the version of Playwright that
|
||||
* launches the browser (1.2.3 → is compatible with 1.2.x).
|
||||
*
|
||||
* @param wsEndpoint A Playwright browser websocket endpoint to connect to. You obtain this endpoint via {@code BrowserServer.wsEndpoint}.
|
||||
* @param endpoint A Playwright browser websocket endpoint to connect to. You obtain this endpoint via {@code BrowserServer.wsEndpoint}.
|
||||
* @since v1.8
|
||||
*/
|
||||
Browser connect(String wsEndpoint, ConnectOptions options);
|
||||
Browser connect(String endpoint, ConnectOptions options);
|
||||
/**
|
||||
* This method attaches Playwright to an existing browser instance using the Chrome DevTools Protocol.
|
||||
*
|
||||
|
||||
@@ -48,6 +48,16 @@ import com.google.gson.JsonObject;
|
||||
* }</pre>
|
||||
*/
|
||||
public interface CDPSession {
|
||||
|
||||
/**
|
||||
* Emitted when the session is closed, either because the target was closed or {@code session.detach()} was called.
|
||||
*/
|
||||
void onClose(Consumer<CDPSession> handler);
|
||||
/**
|
||||
* Removes handler that was previously added with {@link #onClose onClose(handler)}.
|
||||
*/
|
||||
void offClose(Consumer<CDPSession> handler);
|
||||
|
||||
/**
|
||||
* Detaches the CDPSession from the target. Once detached, the CDPSession object won't emit any events and can't be used to
|
||||
* send messages.
|
||||
|
||||
@@ -69,6 +69,12 @@ public interface ConsoleMessage {
|
||||
* @since v1.8
|
||||
*/
|
||||
String text();
|
||||
/**
|
||||
* The timestamp of the console message in milliseconds since the Unix epoch.
|
||||
*
|
||||
* @since v1.59
|
||||
*/
|
||||
double timestamp();
|
||||
/**
|
||||
* One of the following values: {@code "log"}, {@code "debug"}, {@code "info"}, {@code "error"}, {@code "warning"}, {@code
|
||||
* "dir"}, {@code "dirxml"}, {@code "table"}, {@code "trace"}, {@code "clear"}, {@code "startGroup"}, {@code
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* API for controlling the Playwright debugger. The debugger allows pausing script execution and inspecting the page.
|
||||
* Obtain the debugger instance via {@link com.microsoft.playwright.BrowserContext#debugger BrowserContext.debugger()}.
|
||||
*/
|
||||
public interface Debugger {
|
||||
|
||||
/**
|
||||
* Emitted when the debugger pauses or resumes.
|
||||
*/
|
||||
void onPausedStateChanged(Runnable handler);
|
||||
/**
|
||||
* Removes handler that was previously added with {@link #onPausedStateChanged onPausedStateChanged(handler)}.
|
||||
*/
|
||||
void offPausedStateChanged(Runnable handler);
|
||||
|
||||
/**
|
||||
* Returns details about the currently paused calls. Returns an empty array if the debugger is not paused.
|
||||
*
|
||||
* @since v1.59
|
||||
*/
|
||||
List<PausedDetails> pausedDetails();
|
||||
/**
|
||||
* Configures the debugger to pause before the next action is executed.
|
||||
*
|
||||
* <p> Throws if the debugger is already paused. Use {@link com.microsoft.playwright.Debugger#next Debugger.next()} or {@link
|
||||
* com.microsoft.playwright.Debugger#runTo Debugger.runTo()} to step while paused.
|
||||
*
|
||||
* <p> Note that {@link com.microsoft.playwright.Page#pause Page.pause()} is equivalent to a "debugger" statement — it pauses
|
||||
* execution at the call site immediately. On the contrary, {@link com.microsoft.playwright.Debugger#pause
|
||||
* Debugger.pause()} is equivalent to "pause on next statement" — it configures the debugger to pause before the next
|
||||
* action is executed.
|
||||
*
|
||||
* @since v1.59
|
||||
*/
|
||||
void pause();
|
||||
/**
|
||||
* Resumes script execution. Throws if the debugger is not paused.
|
||||
*
|
||||
* @since v1.59
|
||||
*/
|
||||
void resume();
|
||||
/**
|
||||
* Resumes script execution and pauses again before the next action. Throws if the debugger is not paused.
|
||||
*
|
||||
* @since v1.59
|
||||
*/
|
||||
void next();
|
||||
/**
|
||||
* Resumes script execution and pauses when an action originates from the given source location. Throws if the debugger is
|
||||
* not paused.
|
||||
*
|
||||
* @param location The source location to pause at.
|
||||
* @since v1.59
|
||||
*/
|
||||
void runTo(Location location);
|
||||
}
|
||||
|
||||
@@ -2272,7 +2272,7 @@ public interface Frame {
|
||||
*/
|
||||
public Double timeout;
|
||||
/**
|
||||
* A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* A glob pattern, regex pattern, or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
@@ -2302,7 +2302,7 @@ public interface Frame {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* A glob pattern, regex pattern, or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
@@ -2311,7 +2311,7 @@ public interface Frame {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* A glob pattern, regex pattern, or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
@@ -2320,7 +2320,7 @@ public interface Frame {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* A glob pattern, regex pattern, or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
@@ -3380,7 +3380,7 @@ public interface Frame {
|
||||
*
|
||||
* <p> Consider the following DOM structure.
|
||||
*
|
||||
* <p> You can locate each element by it's implicit role:
|
||||
* <p> You can locate each element by its implicit role:
|
||||
* <pre>{@code
|
||||
* assertThat(page
|
||||
* .getByRole(AriaRole.HEADING,
|
||||
@@ -3423,7 +3423,7 @@ public interface Frame {
|
||||
*
|
||||
* <p> Consider the following DOM structure.
|
||||
*
|
||||
* <p> You can locate each element by it's implicit role:
|
||||
* <p> You can locate each element by its implicit role:
|
||||
* <pre>{@code
|
||||
* assertThat(page
|
||||
* .getByRole(AriaRole.HEADING,
|
||||
@@ -3462,7 +3462,7 @@ public interface Frame {
|
||||
*
|
||||
* <p> Consider the following DOM structure.
|
||||
*
|
||||
* <p> You can locate the element by it's test id:
|
||||
* <p> You can locate the element by its test id:
|
||||
* <pre>{@code
|
||||
* page.getByTestId("directions").click();
|
||||
* }</pre>
|
||||
@@ -3484,7 +3484,7 @@ public interface Frame {
|
||||
*
|
||||
* <p> Consider the following DOM structure.
|
||||
*
|
||||
* <p> You can locate the element by it's test id:
|
||||
* <p> You can locate the element by its test id:
|
||||
* <pre>{@code
|
||||
* page.getByTestId("directions").click();
|
||||
* }</pre>
|
||||
@@ -5139,7 +5139,7 @@ public interface Frame {
|
||||
* frame.waitForURL("**\/target.html");
|
||||
* }</pre>
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* @param url A glob pattern, regex pattern, or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
* @since v1.11
|
||||
@@ -5156,7 +5156,7 @@ public interface Frame {
|
||||
* frame.waitForURL("**\/target.html");
|
||||
* }</pre>
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* @param url A glob pattern, regex pattern, or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
* @since v1.11
|
||||
@@ -5171,7 +5171,7 @@ public interface Frame {
|
||||
* frame.waitForURL("**\/target.html");
|
||||
* }</pre>
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* @param url A glob pattern, regex pattern, or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
* @since v1.11
|
||||
@@ -5188,7 +5188,7 @@ public interface Frame {
|
||||
* frame.waitForURL("**\/target.html");
|
||||
* }</pre>
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* @param url A glob pattern, regex pattern, or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
* @since v1.11
|
||||
@@ -5203,7 +5203,7 @@ public interface Frame {
|
||||
* frame.waitForURL("**\/target.html");
|
||||
* }</pre>
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* @param url A glob pattern, regex pattern, or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
* @since v1.11
|
||||
@@ -5220,7 +5220,7 @@ public interface Frame {
|
||||
* frame.waitForURL("**\/target.html");
|
||||
* }</pre>
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* @param url A glob pattern, regex pattern, or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
* @since v1.11
|
||||
|
||||
@@ -602,7 +602,7 @@ public interface FrameLocator {
|
||||
*
|
||||
* <p> Consider the following DOM structure.
|
||||
*
|
||||
* <p> You can locate each element by it's implicit role:
|
||||
* <p> You can locate each element by its implicit role:
|
||||
* <pre>{@code
|
||||
* assertThat(page
|
||||
* .getByRole(AriaRole.HEADING,
|
||||
@@ -645,7 +645,7 @@ public interface FrameLocator {
|
||||
*
|
||||
* <p> Consider the following DOM structure.
|
||||
*
|
||||
* <p> You can locate each element by it's implicit role:
|
||||
* <p> You can locate each element by its implicit role:
|
||||
* <pre>{@code
|
||||
* assertThat(page
|
||||
* .getByRole(AriaRole.HEADING,
|
||||
@@ -684,7 +684,7 @@ public interface FrameLocator {
|
||||
*
|
||||
* <p> Consider the following DOM structure.
|
||||
*
|
||||
* <p> You can locate the element by it's test id:
|
||||
* <p> You can locate the element by its test id:
|
||||
* <pre>{@code
|
||||
* page.getByTestId("directions").click();
|
||||
* }</pre>
|
||||
@@ -706,7 +706,7 @@ public interface FrameLocator {
|
||||
*
|
||||
* <p> Consider the following DOM structure.
|
||||
*
|
||||
* <p> You can locate the element by it's test id:
|
||||
* <p> You can locate the element by its test id:
|
||||
* <pre>{@code
|
||||
* page.getByTestId("directions").click();
|
||||
* }</pre>
|
||||
|
||||
@@ -30,6 +30,15 @@ import java.util.regex.Pattern;
|
||||
*/
|
||||
public interface Locator {
|
||||
class AriaSnapshotOptions {
|
||||
/**
|
||||
* When specified, limits the depth of the snapshot.
|
||||
*/
|
||||
public Integer depth;
|
||||
/**
|
||||
* When set to {@code "ai"}, returns a snapshot optimized for AI consumption with element references. Defaults to {@code
|
||||
* "default"}.
|
||||
*/
|
||||
public AriaSnapshotMode mode;
|
||||
/**
|
||||
* Maximum time in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
|
||||
* value can be changed by using the {@link com.microsoft.playwright.BrowserContext#setDefaultTimeout
|
||||
@@ -38,6 +47,21 @@ public interface Locator {
|
||||
*/
|
||||
public Double timeout;
|
||||
|
||||
/**
|
||||
* When specified, limits the depth of the snapshot.
|
||||
*/
|
||||
public AriaSnapshotOptions setDepth(int depth) {
|
||||
this.depth = depth;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* When set to {@code "ai"}, returns a snapshot optimized for AI consumption with element references. Defaults to {@code
|
||||
* "default"}.
|
||||
*/
|
||||
public AriaSnapshotOptions setMode(AriaSnapshotMode mode) {
|
||||
this.mode = mode;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Maximum time in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
|
||||
* value can be changed by using the {@link com.microsoft.playwright.BrowserContext#setDefaultTimeout
|
||||
@@ -3492,7 +3516,7 @@ public interface Locator {
|
||||
*
|
||||
* <p> Consider the following DOM structure.
|
||||
*
|
||||
* <p> You can locate each element by it's implicit role:
|
||||
* <p> You can locate each element by its implicit role:
|
||||
* <pre>{@code
|
||||
* assertThat(page
|
||||
* .getByRole(AriaRole.HEADING,
|
||||
@@ -3535,7 +3559,7 @@ public interface Locator {
|
||||
*
|
||||
* <p> Consider the following DOM structure.
|
||||
*
|
||||
* <p> You can locate each element by it's implicit role:
|
||||
* <p> You can locate each element by its implicit role:
|
||||
* <pre>{@code
|
||||
* assertThat(page
|
||||
* .getByRole(AriaRole.HEADING,
|
||||
@@ -3574,7 +3598,7 @@ public interface Locator {
|
||||
*
|
||||
* <p> Consider the following DOM structure.
|
||||
*
|
||||
* <p> You can locate the element by it's test id:
|
||||
* <p> You can locate the element by its test id:
|
||||
* <pre>{@code
|
||||
* page.getByTestId("directions").click();
|
||||
* }</pre>
|
||||
@@ -3596,7 +3620,7 @@ public interface Locator {
|
||||
*
|
||||
* <p> Consider the following DOM structure.
|
||||
*
|
||||
* <p> You can locate the element by it's test id:
|
||||
* <p> You can locate the element by its test id:
|
||||
* <pre>{@code
|
||||
* page.getByTestId("directions").click();
|
||||
* }</pre>
|
||||
@@ -4245,6 +4269,14 @@ public interface Locator {
|
||||
* @since v1.14
|
||||
*/
|
||||
Locator locator(Locator selectorOrLocator, LocatorOptions options);
|
||||
/**
|
||||
* Returns a new locator that uses best practices for referencing the matched element, prioritizing test ids, aria roles,
|
||||
* and other user-facing attributes over CSS selectors. This is useful for converting implementation-detail selectors into
|
||||
* more resilient, human-readable locators.
|
||||
*
|
||||
* @since v1.59
|
||||
*/
|
||||
Locator normalize();
|
||||
/**
|
||||
* Returns locator to the n-th matching element. It's zero based, {@code nth(0)} selects the first element.
|
||||
*
|
||||
|
||||
@@ -1987,6 +1987,20 @@ public interface Page extends AutoCloseable {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
class ConsoleMessagesOptions {
|
||||
/**
|
||||
* Controls which messages are returned:
|
||||
*/
|
||||
public ConsoleMessagesFilter filter;
|
||||
|
||||
/**
|
||||
* Controls which messages are returned:
|
||||
*/
|
||||
public ConsoleMessagesOptions setFilter(ConsoleMessagesFilter filter) {
|
||||
this.filter = filter;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
class LocatorOptions {
|
||||
/**
|
||||
* Narrows down the results of the method to those which contain elements matching this relative locator. For example,
|
||||
@@ -2966,6 +2980,50 @@ public interface Page extends AutoCloseable {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
class AriaSnapshotOptions {
|
||||
/**
|
||||
* When specified, limits the depth of the snapshot.
|
||||
*/
|
||||
public Integer depth;
|
||||
/**
|
||||
* When set to {@code "ai"}, returns a snapshot optimized for AI consumption with element references. Defaults to {@code
|
||||
* "default"}.
|
||||
*/
|
||||
public AriaSnapshotMode mode;
|
||||
/**
|
||||
* Maximum time in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
|
||||
* value can be changed by using the {@link com.microsoft.playwright.BrowserContext#setDefaultTimeout
|
||||
* BrowserContext.setDefaultTimeout()} or {@link com.microsoft.playwright.Page#setDefaultTimeout Page.setDefaultTimeout()}
|
||||
* methods.
|
||||
*/
|
||||
public Double timeout;
|
||||
|
||||
/**
|
||||
* When specified, limits the depth of the snapshot.
|
||||
*/
|
||||
public AriaSnapshotOptions setDepth(int depth) {
|
||||
this.depth = depth;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* When set to {@code "ai"}, returns a snapshot optimized for AI consumption with element references. Defaults to {@code
|
||||
* "default"}.
|
||||
*/
|
||||
public AriaSnapshotOptions setMode(AriaSnapshotMode mode) {
|
||||
this.mode = mode;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Maximum time in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
|
||||
* value can be changed by using the {@link com.microsoft.playwright.BrowserContext#setDefaultTimeout
|
||||
* BrowserContext.setDefaultTimeout()} or {@link com.microsoft.playwright.Page#setDefaultTimeout Page.setDefaultTimeout()}
|
||||
* methods.
|
||||
*/
|
||||
public AriaSnapshotOptions setTimeout(double timeout) {
|
||||
this.timeout = timeout;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
class TapOptions {
|
||||
/**
|
||||
* Whether to bypass the <a href="https://playwright.dev/java/docs/actionability">actionability</a> checks. Defaults to
|
||||
@@ -3428,7 +3486,7 @@ public interface Page extends AutoCloseable {
|
||||
*/
|
||||
public Double timeout;
|
||||
/**
|
||||
* A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* A glob pattern, regex pattern, or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
@@ -3458,7 +3516,7 @@ public interface Page extends AutoCloseable {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* A glob pattern, regex pattern, or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
@@ -3467,7 +3525,7 @@ public interface Page extends AutoCloseable {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* A glob pattern, regex pattern, or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
@@ -3476,7 +3534,7 @@ public interface Page extends AutoCloseable {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* A glob pattern, regex pattern, or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
@@ -3812,7 +3870,7 @@ public interface Page extends AutoCloseable {
|
||||
* @param script Script to be evaluated in all pages in the browser context.
|
||||
* @since v1.8
|
||||
*/
|
||||
void addInitScript(String script);
|
||||
AutoCloseable addInitScript(String script);
|
||||
/**
|
||||
* Adds a script which would be evaluated in one of the following scenarios:
|
||||
* <ul>
|
||||
@@ -3839,7 +3897,7 @@ public interface Page extends AutoCloseable {
|
||||
* @param script Script to be evaluated in all pages in the browser context.
|
||||
* @since v1.8
|
||||
*/
|
||||
void addInitScript(Path script);
|
||||
AutoCloseable addInitScript(Path script);
|
||||
/**
|
||||
* Adds a {@code <script>} tag into the page with the desired url or content. Returns the added tag when the script's
|
||||
* onload fires or when the script content was injected into frame.
|
||||
@@ -3880,6 +3938,13 @@ public interface Page extends AutoCloseable {
|
||||
* @since v1.8
|
||||
*/
|
||||
void bringToFront();
|
||||
/**
|
||||
* Cancels an ongoing {@link com.microsoft.playwright.Page#pickLocator Page.pickLocator()} call by deactivating pick
|
||||
* locator mode. If no pick locator mode is active, this method is a no-op.
|
||||
*
|
||||
* @since v1.59
|
||||
*/
|
||||
void cancelPickLocator();
|
||||
/**
|
||||
* This method checks an element matching {@code selector} by performing the following steps:
|
||||
* <ol>
|
||||
@@ -4611,8 +4676,8 @@ public interface Page extends AutoCloseable {
|
||||
* @param callback Callback function that will be called in the Playwright's context.
|
||||
* @since v1.8
|
||||
*/
|
||||
default void exposeBinding(String name, BindingCallback callback) {
|
||||
exposeBinding(name, callback, null);
|
||||
default AutoCloseable exposeBinding(String name, BindingCallback callback) {
|
||||
return exposeBinding(name, callback, null);
|
||||
}
|
||||
/**
|
||||
* The method adds a function called {@code name} on the {@code window} object of every frame in this page. When called,
|
||||
@@ -4661,7 +4726,7 @@ public interface Page extends AutoCloseable {
|
||||
* @param callback Callback function that will be called in the Playwright's context.
|
||||
* @since v1.8
|
||||
*/
|
||||
void exposeBinding(String name, BindingCallback callback, ExposeBindingOptions options);
|
||||
AutoCloseable exposeBinding(String name, BindingCallback callback, ExposeBindingOptions options);
|
||||
/**
|
||||
* The method adds a function called {@code name} on the {@code window} object of every frame in the page. When called, the
|
||||
* function executes {@code callback} and returns a <a
|
||||
@@ -4723,7 +4788,7 @@ public interface Page extends AutoCloseable {
|
||||
* @param callback Callback function which will be called in Playwright's context.
|
||||
* @since v1.8
|
||||
*/
|
||||
void exposeFunction(String name, FunctionCallback callback);
|
||||
AutoCloseable exposeFunction(String name, FunctionCallback callback);
|
||||
/**
|
||||
* This method waits for an element matching {@code selector}, waits for <a
|
||||
* href="https://playwright.dev/java/docs/actionability">actionability</a> checks, focuses the element, fills it and
|
||||
@@ -5062,7 +5127,7 @@ public interface Page extends AutoCloseable {
|
||||
*
|
||||
* <p> Consider the following DOM structure.
|
||||
*
|
||||
* <p> You can locate each element by it's implicit role:
|
||||
* <p> You can locate each element by its implicit role:
|
||||
* <pre>{@code
|
||||
* assertThat(page
|
||||
* .getByRole(AriaRole.HEADING,
|
||||
@@ -5105,7 +5170,7 @@ public interface Page extends AutoCloseable {
|
||||
*
|
||||
* <p> Consider the following DOM structure.
|
||||
*
|
||||
* <p> You can locate each element by it's implicit role:
|
||||
* <p> You can locate each element by its implicit role:
|
||||
* <pre>{@code
|
||||
* assertThat(page
|
||||
* .getByRole(AriaRole.HEADING,
|
||||
@@ -5144,7 +5209,7 @@ public interface Page extends AutoCloseable {
|
||||
*
|
||||
* <p> Consider the following DOM structure.
|
||||
*
|
||||
* <p> You can locate the element by it's test id:
|
||||
* <p> You can locate the element by its test id:
|
||||
* <pre>{@code
|
||||
* page.getByTestId("directions").click();
|
||||
* }</pre>
|
||||
@@ -5166,7 +5231,7 @@ public interface Page extends AutoCloseable {
|
||||
*
|
||||
* <p> Consider the following DOM structure.
|
||||
*
|
||||
* <p> You can locate the element by it's test id:
|
||||
* <p> You can locate the element by its test id:
|
||||
* <pre>{@code
|
||||
* page.getByTestId("directions").click();
|
||||
* }</pre>
|
||||
@@ -5742,13 +5807,36 @@ public interface Page extends AutoCloseable {
|
||||
* @since v1.8
|
||||
*/
|
||||
Keyboard keyboard();
|
||||
/**
|
||||
* Clears all stored console messages from this page. Subsequent calls to {@link
|
||||
* com.microsoft.playwright.Page#consoleMessages Page.consoleMessages()} will only return messages logged after the clear.
|
||||
*
|
||||
* @since v1.59
|
||||
*/
|
||||
void clearConsoleMessages();
|
||||
/**
|
||||
* Clears all stored page errors from this page. Subsequent calls to {@link com.microsoft.playwright.Page#pageErrors
|
||||
* Page.pageErrors()} will only return errors thrown after the clear.
|
||||
*
|
||||
* @since v1.59
|
||||
*/
|
||||
void clearPageErrors();
|
||||
/**
|
||||
* Returns up to (currently) 200 last console messages from this page. See {@link
|
||||
* com.microsoft.playwright.Page#onConsoleMessage Page.onConsoleMessage()} for more details.
|
||||
*
|
||||
* @since v1.56
|
||||
*/
|
||||
List<ConsoleMessage> consoleMessages();
|
||||
default List<ConsoleMessage> consoleMessages() {
|
||||
return consoleMessages(null);
|
||||
}
|
||||
/**
|
||||
* Returns up to (currently) 200 last console messages from this page. See {@link
|
||||
* com.microsoft.playwright.Page#onConsoleMessage Page.onConsoleMessage()} for more details.
|
||||
*
|
||||
* @since v1.56
|
||||
*/
|
||||
List<ConsoleMessage> consoleMessages(ConsoleMessagesOptions options);
|
||||
/**
|
||||
* Returns up to (currently) 200 last page errors from this page. See {@link com.microsoft.playwright.Page#onPageError
|
||||
* Page.onPageError()} for more details.
|
||||
@@ -5964,6 +6052,19 @@ public interface Page extends AutoCloseable {
|
||||
* @since v1.8
|
||||
*/
|
||||
byte[] pdf(PdfOptions options);
|
||||
/**
|
||||
* Enters pick locator mode where hovering over page elements highlights them and shows the corresponding locator. Once the
|
||||
* user clicks an element, the mode is deactivated and the {@code Locator} for the picked element is returned.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* Locator locator = page.pickLocator();
|
||||
* System.out.println(locator);
|
||||
* }</pre>
|
||||
*
|
||||
* @since v1.59
|
||||
*/
|
||||
Locator pickLocator();
|
||||
/**
|
||||
* Focuses the element, and then uses {@link com.microsoft.playwright.Keyboard#down Keyboard.down()} and {@link
|
||||
* com.microsoft.playwright.Keyboard#up Keyboard.up()}.
|
||||
@@ -6352,6 +6453,8 @@ public interface Page extends AutoCloseable {
|
||||
* });
|
||||
* }</pre>
|
||||
*
|
||||
* <p> If a request matches multiple registered routes, the most recently registered route takes precedence.
|
||||
*
|
||||
* <p> Page routes take precedence over browser context routes (set up with {@link
|
||||
* com.microsoft.playwright.BrowserContext#route BrowserContext.route()}) when request matches both handlers.
|
||||
*
|
||||
@@ -6365,8 +6468,8 @@ public interface Page extends AutoCloseable {
|
||||
* @param handler handler function to route the request.
|
||||
* @since v1.8
|
||||
*/
|
||||
default void route(String url, Consumer<Route> handler) {
|
||||
route(url, handler, null);
|
||||
default AutoCloseable route(String url, Consumer<Route> handler) {
|
||||
return route(url, handler, null);
|
||||
}
|
||||
/**
|
||||
* Routing provides the capability to modify network requests that are made by a page.
|
||||
@@ -6411,6 +6514,8 @@ public interface Page extends AutoCloseable {
|
||||
* });
|
||||
* }</pre>
|
||||
*
|
||||
* <p> If a request matches multiple registered routes, the most recently registered route takes precedence.
|
||||
*
|
||||
* <p> Page routes take precedence over browser context routes (set up with {@link
|
||||
* com.microsoft.playwright.BrowserContext#route BrowserContext.route()}) when request matches both handlers.
|
||||
*
|
||||
@@ -6424,7 +6529,7 @@ public interface Page extends AutoCloseable {
|
||||
* @param handler handler function to route the request.
|
||||
* @since v1.8
|
||||
*/
|
||||
void route(String url, Consumer<Route> handler, RouteOptions options);
|
||||
AutoCloseable route(String url, Consumer<Route> handler, RouteOptions options);
|
||||
/**
|
||||
* Routing provides the capability to modify network requests that are made by a page.
|
||||
*
|
||||
@@ -6468,6 +6573,8 @@ public interface Page extends AutoCloseable {
|
||||
* });
|
||||
* }</pre>
|
||||
*
|
||||
* <p> If a request matches multiple registered routes, the most recently registered route takes precedence.
|
||||
*
|
||||
* <p> Page routes take precedence over browser context routes (set up with {@link
|
||||
* com.microsoft.playwright.BrowserContext#route BrowserContext.route()}) when request matches both handlers.
|
||||
*
|
||||
@@ -6481,8 +6588,8 @@ public interface Page extends AutoCloseable {
|
||||
* @param handler handler function to route the request.
|
||||
* @since v1.8
|
||||
*/
|
||||
default void route(Pattern url, Consumer<Route> handler) {
|
||||
route(url, handler, null);
|
||||
default AutoCloseable route(Pattern url, Consumer<Route> handler) {
|
||||
return route(url, handler, null);
|
||||
}
|
||||
/**
|
||||
* Routing provides the capability to modify network requests that are made by a page.
|
||||
@@ -6527,6 +6634,8 @@ public interface Page extends AutoCloseable {
|
||||
* });
|
||||
* }</pre>
|
||||
*
|
||||
* <p> If a request matches multiple registered routes, the most recently registered route takes precedence.
|
||||
*
|
||||
* <p> Page routes take precedence over browser context routes (set up with {@link
|
||||
* com.microsoft.playwright.BrowserContext#route BrowserContext.route()}) when request matches both handlers.
|
||||
*
|
||||
@@ -6540,7 +6649,7 @@ public interface Page extends AutoCloseable {
|
||||
* @param handler handler function to route the request.
|
||||
* @since v1.8
|
||||
*/
|
||||
void route(Pattern url, Consumer<Route> handler, RouteOptions options);
|
||||
AutoCloseable route(Pattern url, Consumer<Route> handler, RouteOptions options);
|
||||
/**
|
||||
* Routing provides the capability to modify network requests that are made by a page.
|
||||
*
|
||||
@@ -6584,6 +6693,8 @@ public interface Page extends AutoCloseable {
|
||||
* });
|
||||
* }</pre>
|
||||
*
|
||||
* <p> If a request matches multiple registered routes, the most recently registered route takes precedence.
|
||||
*
|
||||
* <p> Page routes take precedence over browser context routes (set up with {@link
|
||||
* com.microsoft.playwright.BrowserContext#route BrowserContext.route()}) when request matches both handlers.
|
||||
*
|
||||
@@ -6597,8 +6708,8 @@ public interface Page extends AutoCloseable {
|
||||
* @param handler handler function to route the request.
|
||||
* @since v1.8
|
||||
*/
|
||||
default void route(Predicate<String> url, Consumer<Route> handler) {
|
||||
route(url, handler, null);
|
||||
default AutoCloseable route(Predicate<String> url, Consumer<Route> handler) {
|
||||
return route(url, handler, null);
|
||||
}
|
||||
/**
|
||||
* Routing provides the capability to modify network requests that are made by a page.
|
||||
@@ -6643,6 +6754,8 @@ public interface Page extends AutoCloseable {
|
||||
* });
|
||||
* }</pre>
|
||||
*
|
||||
* <p> If a request matches multiple registered routes, the most recently registered route takes precedence.
|
||||
*
|
||||
* <p> Page routes take precedence over browser context routes (set up with {@link
|
||||
* com.microsoft.playwright.BrowserContext#route BrowserContext.route()}) when request matches both handlers.
|
||||
*
|
||||
@@ -6656,7 +6769,7 @@ public interface Page extends AutoCloseable {
|
||||
* @param handler handler function to route the request.
|
||||
* @since v1.8
|
||||
*/
|
||||
void route(Predicate<String> url, Consumer<Route> handler, RouteOptions options);
|
||||
AutoCloseable route(Predicate<String> url, Consumer<Route> handler, RouteOptions options);
|
||||
/**
|
||||
* If specified the network requests that are made in the page will be served from the HAR file. Read more about <a
|
||||
* href="https://playwright.dev/java/docs/mock#replaying-from-har">Replaying from HAR</a>.
|
||||
@@ -7414,6 +7527,22 @@ public interface Page extends AutoCloseable {
|
||||
* @since v1.8
|
||||
*/
|
||||
void setViewportSize(int width, int height);
|
||||
/**
|
||||
* Captures the aria snapshot of the page. Read more about <a href="https://playwright.dev/java/docs/aria-snapshots">aria
|
||||
* snapshots</a>.
|
||||
*
|
||||
* @since v1.59
|
||||
*/
|
||||
default String ariaSnapshot() {
|
||||
return ariaSnapshot(null);
|
||||
}
|
||||
/**
|
||||
* Captures the aria snapshot of the page. Read more about <a href="https://playwright.dev/java/docs/aria-snapshots">aria
|
||||
* snapshots</a>.
|
||||
*
|
||||
* @since v1.59
|
||||
*/
|
||||
String ariaSnapshot(AriaSnapshotOptions options);
|
||||
/**
|
||||
* This method taps an element matching {@code selector} by performing the following steps:
|
||||
* <ol>
|
||||
@@ -7561,7 +7690,7 @@ public interface Page extends AutoCloseable {
|
||||
* Removes a route created with {@link com.microsoft.playwright.Page#route Page.route()}. When {@code handler} is not
|
||||
* specified, removes all routes for the {@code url}.
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while routing.
|
||||
* @param url A glob pattern, regex pattern, or predicate receiving [URL] to match while routing.
|
||||
* @since v1.8
|
||||
*/
|
||||
default void unroute(String url) {
|
||||
@@ -7571,7 +7700,7 @@ public interface Page extends AutoCloseable {
|
||||
* Removes a route created with {@link com.microsoft.playwright.Page#route Page.route()}. When {@code handler} is not
|
||||
* specified, removes all routes for the {@code url}.
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while routing.
|
||||
* @param url A glob pattern, regex pattern, or predicate receiving [URL] to match while routing.
|
||||
* @param handler Optional handler function to route the request.
|
||||
* @since v1.8
|
||||
*/
|
||||
@@ -7580,7 +7709,7 @@ public interface Page extends AutoCloseable {
|
||||
* Removes a route created with {@link com.microsoft.playwright.Page#route Page.route()}. When {@code handler} is not
|
||||
* specified, removes all routes for the {@code url}.
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while routing.
|
||||
* @param url A glob pattern, regex pattern, or predicate receiving [URL] to match while routing.
|
||||
* @since v1.8
|
||||
*/
|
||||
default void unroute(Pattern url) {
|
||||
@@ -7590,7 +7719,7 @@ public interface Page extends AutoCloseable {
|
||||
* Removes a route created with {@link com.microsoft.playwright.Page#route Page.route()}. When {@code handler} is not
|
||||
* specified, removes all routes for the {@code url}.
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while routing.
|
||||
* @param url A glob pattern, regex pattern, or predicate receiving [URL] to match while routing.
|
||||
* @param handler Optional handler function to route the request.
|
||||
* @since v1.8
|
||||
*/
|
||||
@@ -7599,7 +7728,7 @@ public interface Page extends AutoCloseable {
|
||||
* Removes a route created with {@link com.microsoft.playwright.Page#route Page.route()}. When {@code handler} is not
|
||||
* specified, removes all routes for the {@code url}.
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while routing.
|
||||
* @param url A glob pattern, regex pattern, or predicate receiving [URL] to match while routing.
|
||||
* @since v1.8
|
||||
*/
|
||||
default void unroute(Predicate<String> url) {
|
||||
@@ -7609,7 +7738,7 @@ public interface Page extends AutoCloseable {
|
||||
* Removes a route created with {@link com.microsoft.playwright.Page#route Page.route()}. When {@code handler} is not
|
||||
* specified, removes all routes for the {@code url}.
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while routing.
|
||||
* @param url A glob pattern, regex pattern, or predicate receiving [URL] to match while routing.
|
||||
* @param handler Optional handler function to route the request.
|
||||
* @since v1.8
|
||||
*/
|
||||
@@ -7621,7 +7750,9 @@ public interface Page extends AutoCloseable {
|
||||
*/
|
||||
String url();
|
||||
/**
|
||||
* Video object associated with this page.
|
||||
* Video object associated with this page. Can be used to control video recording with {@link
|
||||
* com.microsoft.playwright.Video#start Video.start()} and {@link com.microsoft.playwright.Video#stop Video.stop()}, or to
|
||||
* access the video file when using the {@code recordVideo} context option.
|
||||
*
|
||||
* @since v1.8
|
||||
*/
|
||||
@@ -8447,7 +8578,7 @@ public interface Page extends AutoCloseable {
|
||||
* page.waitForURL("**\/target.html");
|
||||
* }</pre>
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* @param url A glob pattern, regex pattern, or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
* @since v1.11
|
||||
@@ -8464,7 +8595,7 @@ public interface Page extends AutoCloseable {
|
||||
* page.waitForURL("**\/target.html");
|
||||
* }</pre>
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* @param url A glob pattern, regex pattern, or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
* @since v1.11
|
||||
@@ -8479,7 +8610,7 @@ public interface Page extends AutoCloseable {
|
||||
* page.waitForURL("**\/target.html");
|
||||
* }</pre>
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* @param url A glob pattern, regex pattern, or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
* @since v1.11
|
||||
@@ -8496,7 +8627,7 @@ public interface Page extends AutoCloseable {
|
||||
* page.waitForURL("**\/target.html");
|
||||
* }</pre>
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* @param url A glob pattern, regex pattern, or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
* @since v1.11
|
||||
@@ -8511,7 +8642,7 @@ public interface Page extends AutoCloseable {
|
||||
* page.waitForURL("**\/target.html");
|
||||
* }</pre>
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* @param url A glob pattern, regex pattern, or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
* @since v1.11
|
||||
@@ -8528,7 +8659,7 @@ public interface Page extends AutoCloseable {
|
||||
* page.waitForURL("**\/target.html");
|
||||
* }</pre>
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* @param url A glob pattern, regex pattern, or predicate receiving [URL] to match while waiting for the navigation. Note that if the
|
||||
* parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
* @since v1.11
|
||||
|
||||
@@ -183,6 +183,16 @@ public interface Request {
|
||||
* @since v1.8
|
||||
*/
|
||||
Response response();
|
||||
/**
|
||||
* Returns the {@code Response} object if the response has already been received, {@code null} otherwise.
|
||||
*
|
||||
* <p> Unlike {@link com.microsoft.playwright.Request#response Request.response()}, this method does not wait for the response
|
||||
* to arrive. It returns immediately with the response object if the response has been received, or {@code null} if the
|
||||
* response has not been received yet.
|
||||
*
|
||||
* @since v1.59
|
||||
*/
|
||||
Response existingResponse();
|
||||
/**
|
||||
* Returns resource size information for given request.
|
||||
*
|
||||
|
||||
@@ -86,6 +86,12 @@ public interface Response {
|
||||
* @since v1.15
|
||||
*/
|
||||
List<String> headerValues(String name);
|
||||
/**
|
||||
* Returns the http version used by the response.
|
||||
*
|
||||
* @since v1.59
|
||||
*/
|
||||
String httpVersion();
|
||||
/**
|
||||
* Contains a boolean stating whether the response was successful (status in the range 200-299) or not.
|
||||
*
|
||||
|
||||
@@ -44,6 +44,12 @@ import java.nio.file.Path;
|
||||
*/
|
||||
public interface Tracing {
|
||||
class StartOptions {
|
||||
/**
|
||||
* When enabled, the trace is written to an unarchived file that is updated in real time as actions occur, instead of
|
||||
* caching changes and archiving them into a zip file at the end. This is useful for live trace viewing during test
|
||||
* execution.
|
||||
*/
|
||||
public Boolean live;
|
||||
/**
|
||||
* If specified, intermediate trace files are going to be saved into the files with the given name prefix inside the {@code
|
||||
* tracesDir} directory specified in {@link com.microsoft.playwright.BrowserType#launch BrowserType.launch()}. To specify
|
||||
@@ -74,6 +80,15 @@ public interface Tracing {
|
||||
*/
|
||||
public String title;
|
||||
|
||||
/**
|
||||
* When enabled, the trace is written to an unarchived file that is updated in real time as actions occur, instead of
|
||||
* caching changes and archiving them into a zip file at the end. This is useful for live trace viewing during test
|
||||
* execution.
|
||||
*/
|
||||
public StartOptions setLive(boolean live) {
|
||||
this.live = live;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* If specified, intermediate trace files are going to be saved into the files with the given name prefix inside the {@code
|
||||
* tracesDir} directory specified in {@link com.microsoft.playwright.BrowserType#launch BrowserType.launch()}. To specify
|
||||
@@ -333,8 +348,8 @@ public interface Tracing {
|
||||
* @param name Group name shown in the trace viewer.
|
||||
* @since v1.49
|
||||
*/
|
||||
default void group(String name) {
|
||||
group(name, null);
|
||||
default AutoCloseable group(String name) {
|
||||
return group(name, null);
|
||||
}
|
||||
/**
|
||||
* <strong>NOTE:</strong> Use {@code test.step} instead when available.
|
||||
@@ -356,7 +371,7 @@ public interface Tracing {
|
||||
* @param name Group name shown in the trace viewer.
|
||||
* @since v1.49
|
||||
*/
|
||||
void group(String name, GroupOptions options);
|
||||
AutoCloseable group(String name, GroupOptions options);
|
||||
/**
|
||||
* Closes the last group created by {@link com.microsoft.playwright.Tracing#group Tracing.group()}.
|
||||
*
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.microsoft.playwright;
|
||||
|
||||
import com.microsoft.playwright.options.*;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
@@ -23,8 +24,64 @@ import java.nio.file.Path;
|
||||
* <pre>{@code
|
||||
* System.out.println(page.video().path());
|
||||
* }</pre>
|
||||
*
|
||||
* <p> Alternatively, you can use {@link com.microsoft.playwright.Video#start Video.start()} and {@link
|
||||
* com.microsoft.playwright.Video#stop Video.stop()} to record video manually. This approach is mutually exclusive with the
|
||||
* {@code recordVideo} option.
|
||||
* <pre>{@code
|
||||
* page.video().start(new Video.StartOptions().setPath(Paths.get("video.webm")));
|
||||
* // ... perform actions ...
|
||||
* page.video().stop();
|
||||
* }</pre>
|
||||
*/
|
||||
public interface Video {
|
||||
class StartOptions {
|
||||
/**
|
||||
* If specified, enables visual annotations on interacted elements during video recording. Interacted elements are
|
||||
* highlighted with a semi-transparent blue box and click points are shown as red circles.
|
||||
*/
|
||||
public Annotate annotate;
|
||||
/**
|
||||
* Path where the video should be saved when the recording is stopped.
|
||||
*/
|
||||
public Path path;
|
||||
/**
|
||||
* Optional dimensions of the recorded video. If not specified the size will be equal to page viewport scaled down to fit
|
||||
* into 800x800. Actual picture of the page will be scaled down if necessary to fit the specified size.
|
||||
*/
|
||||
public Size size;
|
||||
|
||||
/**
|
||||
* If specified, enables visual annotations on interacted elements during video recording. Interacted elements are
|
||||
* highlighted with a semi-transparent blue box and click points are shown as red circles.
|
||||
*/
|
||||
public StartOptions setAnnotate(Annotate annotate) {
|
||||
this.annotate = annotate;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Path where the video should be saved when the recording is stopped.
|
||||
*/
|
||||
public StartOptions setPath(Path path) {
|
||||
this.path = path;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Optional dimensions of the recorded video. If not specified the size will be equal to page viewport scaled down to fit
|
||||
* into 800x800. Actual picture of the page will be scaled down if necessary to fit the specified size.
|
||||
*/
|
||||
public StartOptions setSize(int width, int height) {
|
||||
return setSize(new Size(width, height));
|
||||
}
|
||||
/**
|
||||
* Optional dimensions of the recorded video. If not specified the size will be equal to page viewport scaled down to fit
|
||||
* into 800x800. Actual picture of the page will be scaled down if necessary to fit the specified size.
|
||||
*/
|
||||
public StartOptions setSize(Size size) {
|
||||
this.size = size;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Deletes the video file. Will wait for the video to finish if necessary.
|
||||
*
|
||||
@@ -46,5 +103,39 @@ public interface Video {
|
||||
* @since v1.11
|
||||
*/
|
||||
void saveAs(Path path);
|
||||
/**
|
||||
* Starts video recording. This method is mutually exclusive with the {@code recordVideo} context option.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* page.video().start(new Video.StartOptions().setPath(Paths.get("video.webm")));
|
||||
* // ... perform actions ...
|
||||
* page.video().stop();
|
||||
* }</pre>
|
||||
*
|
||||
* @since v1.59
|
||||
*/
|
||||
default AutoCloseable start() {
|
||||
return start(null);
|
||||
}
|
||||
/**
|
||||
* Starts video recording. This method is mutually exclusive with the {@code recordVideo} context option.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* page.video().start(new Video.StartOptions().setPath(Paths.get("video.webm")));
|
||||
* // ... perform actions ...
|
||||
* page.video().stop();
|
||||
* }</pre>
|
||||
*
|
||||
* @since v1.59
|
||||
*/
|
||||
AutoCloseable start(StartOptions options);
|
||||
/**
|
||||
* Stops video recording started with {@link com.microsoft.playwright.Video#start Video.start()}.
|
||||
*
|
||||
* @since v1.59
|
||||
*/
|
||||
void stop();
|
||||
}
|
||||
|
||||
|
||||
+5
-2
@@ -37,8 +37,11 @@ package com.microsoft.playwright.assertions;
|
||||
*/
|
||||
public interface APIResponseAssertions {
|
||||
/**
|
||||
* Makes the assertion check for the opposite condition. For example, this code tests that the response status is not
|
||||
* successful:
|
||||
* Makes the assertion check for the opposite condition.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
*
|
||||
* <p> For example, this code tests that the response status is not successful:
|
||||
* <pre>{@code
|
||||
* assertThat(response).not().isOK();
|
||||
* }</pre>
|
||||
|
||||
@@ -563,8 +563,11 @@ public interface LocatorAssertions {
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Makes the assertion check for the opposite condition. For example, this code tests that the Locator doesn't contain text
|
||||
* {@code "error"}:
|
||||
* Makes the assertion check for the opposite condition.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
*
|
||||
* <p> For example, this code tests that the Locator doesn't contain text {@code "error"}:
|
||||
* <pre>{@code
|
||||
* assertThat(locator).not().containsText("error");
|
||||
* }</pre>
|
||||
|
||||
@@ -79,8 +79,11 @@ public interface PageAssertions {
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Makes the assertion check for the opposite condition. For example, this code tests that the page URL doesn't contain
|
||||
* {@code "error"}:
|
||||
* Makes the assertion check for the opposite condition.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
*
|
||||
* <p> For example, this code tests that the page URL doesn't contain {@code "error"}:
|
||||
* <pre>{@code
|
||||
* assertThat(page).not().hasURL("error");
|
||||
* }</pre>
|
||||
|
||||
@@ -43,6 +43,7 @@ import static java.util.Arrays.asList;
|
||||
class BrowserContextImpl extends ChannelOwner implements BrowserContext {
|
||||
protected BrowserImpl browser;
|
||||
private final TracingImpl tracing;
|
||||
private final DebuggerImpl debugger;
|
||||
private final APIRequestContextImpl request;
|
||||
private final ClockImpl clock;
|
||||
final List<PageImpl> pages = new ArrayList<>();
|
||||
@@ -94,6 +95,7 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
|
||||
BrowserContextImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
tracing = connection.getExistingObject(initializer.getAsJsonObject("tracing").get("guid").getAsString());
|
||||
debugger = connection.getExistingObject(initializer.getAsJsonObject("debugger").get("guid").getAsString());
|
||||
request = connection.getExistingObject(initializer.getAsJsonObject("requestContext").get("guid").getAsString());
|
||||
request.timeoutSettings = timeoutSettings;
|
||||
clock = new ClockImpl(this);
|
||||
@@ -268,6 +270,11 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
|
||||
return connection.getExistingObject(result.getAsJsonObject("session").get("guid").getAsString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClosed() {
|
||||
return closingOrClosed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(CloseOptions options) {
|
||||
if (!closingOrClosed) {
|
||||
@@ -318,17 +325,18 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInitScript(String script) {
|
||||
public AutoCloseable addInitScript(String script) {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty("source", script);
|
||||
sendMessage("addInitScript", params, NO_TIMEOUT);
|
||||
JsonObject result = sendMessage("addInitScript", params, NO_TIMEOUT).getAsJsonObject();
|
||||
return connection.getExistingObject(result.getAsJsonObject("disposable").get("guid").getAsString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInitScript(Path path) {
|
||||
public AutoCloseable addInitScript(Path path) {
|
||||
try {
|
||||
byte[] bytes = readAllBytes(path);
|
||||
addInitScript(new String(bytes, UTF_8));
|
||||
return addInitScript(new String(bytes, UTF_8));
|
||||
} catch (IOException e) {
|
||||
throw new PlaywrightException("Failed to read script from file", e);
|
||||
}
|
||||
@@ -384,11 +392,11 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exposeBinding(String name, BindingCallback playwrightBinding, ExposeBindingOptions options) {
|
||||
exposeBindingImpl(name, playwrightBinding, options);
|
||||
public AutoCloseable exposeBinding(String name, BindingCallback playwrightBinding, ExposeBindingOptions options) {
|
||||
return exposeBindingImpl(name, playwrightBinding, options);
|
||||
}
|
||||
|
||||
private void exposeBindingImpl(String name, BindingCallback playwrightBinding, ExposeBindingOptions options) {
|
||||
private AutoCloseable exposeBindingImpl(String name, BindingCallback playwrightBinding, ExposeBindingOptions options) {
|
||||
if (bindings.containsKey(name)) {
|
||||
throw new PlaywrightException("Function \"" + name + "\" has been already registered");
|
||||
}
|
||||
@@ -404,12 +412,13 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
|
||||
if (options != null && options.handle != null && options.handle) {
|
||||
params.addProperty("needsHandle", true);
|
||||
}
|
||||
sendMessage("exposeBinding", params, NO_TIMEOUT);
|
||||
JsonObject result = sendMessage("exposeBinding", params, NO_TIMEOUT).getAsJsonObject();
|
||||
return connection.getExistingObject(result.getAsJsonObject("disposable").get("guid").getAsString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exposeFunction(String name, FunctionCallback playwrightFunction) {
|
||||
exposeBindingImpl(name, (BindingCallback.Source source, Object... args) -> playwrightFunction.call(args), null);
|
||||
public AutoCloseable exposeFunction(String name, FunctionCallback playwrightFunction) {
|
||||
return exposeBindingImpl(name, (BindingCallback.Source source, Object... args) -> playwrightFunction.call(args), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -445,18 +454,21 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void route(String url, Consumer<Route> handler, RouteOptions options) {
|
||||
public AutoCloseable route(String url, Consumer<Route> handler, RouteOptions options) {
|
||||
route(UrlMatcher.forGlob(baseUrl(), url, this.connection.localUtils, false), handler, options);
|
||||
return new DisposableStub(() -> unroute(url, handler));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void route(Pattern url, Consumer<Route> handler, RouteOptions options) {
|
||||
public AutoCloseable route(Pattern url, Consumer<Route> handler, RouteOptions options) {
|
||||
route(new UrlMatcher(url), handler, options);
|
||||
return new DisposableStub(() -> unroute(url, handler));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void route(Predicate<String> url, Consumer<Route> handler, RouteOptions options) {
|
||||
public AutoCloseable route(Predicate<String> url, Consumer<Route> handler, RouteOptions options) {
|
||||
route(new UrlMatcher(url), handler, options);
|
||||
return new DisposableStub(() -> unroute(url, handler));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -563,6 +575,18 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
|
||||
sendMessage("setOffline", params, NO_TIMEOUT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStorageState(Path storageState) {
|
||||
try {
|
||||
String state = new String(readAllBytes(storageState), UTF_8);
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty("storageState", state);
|
||||
sendMessage("setStorageState", params, NO_TIMEOUT);
|
||||
} catch (IOException e) {
|
||||
throw new PlaywrightException("Failed to read storage state from file", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String storageState(StorageStateOptions options) {
|
||||
if (options == null) {
|
||||
@@ -579,6 +603,11 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
|
||||
return storageState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DebuggerImpl debugger() {
|
||||
return debugger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TracingImpl tracing() {
|
||||
return tracing;
|
||||
@@ -775,7 +804,8 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
|
||||
}
|
||||
} else if ("response".equals(event)) {
|
||||
String guid = params.getAsJsonObject("response").get("guid").getAsString();
|
||||
Response response = connection.getExistingObject(guid);
|
||||
ResponseImpl response = connection.getExistingObject(guid);
|
||||
response.request.existingResponse = response;
|
||||
listeners.notify(EventType.RESPONSE, response);
|
||||
if (params.has("page")) {
|
||||
PageImpl page = connection.getExistingObject(params.getAsJsonObject("page").get("guid").getAsString());
|
||||
|
||||
@@ -59,7 +59,7 @@ class BrowserTypeImpl extends ChannelOwner implements BrowserType {
|
||||
}
|
||||
// We don't use gson() here as the headers map should be serialized to a json object.
|
||||
JsonObject params = new Gson().toJsonTree(options).getAsJsonObject();
|
||||
params.addProperty("wsEndpoint", wsEndpoint);
|
||||
params.addProperty("endpoint", wsEndpoint);
|
||||
|
||||
if (!params.has("headers")) {
|
||||
params.add("headers", new JsonObject());
|
||||
|
||||
@@ -25,6 +25,11 @@ import java.util.function.Consumer;
|
||||
|
||||
public class CDPSessionImpl extends ChannelOwner implements CDPSession {
|
||||
private final ListenerCollection<String> listeners = new ListenerCollection<>(new HashMap<>(), this);
|
||||
private final ListenerCollection<EventType> typedListeners = new ListenerCollection<>(new HashMap<>(), this);
|
||||
|
||||
enum EventType {
|
||||
CLOSE,
|
||||
}
|
||||
|
||||
protected CDPSessionImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
@@ -40,9 +45,22 @@ public class CDPSessionImpl extends ChannelOwner implements CDPSession {
|
||||
params = parameters.get("params").getAsJsonObject();
|
||||
}
|
||||
listeners.notify(method, params);
|
||||
listeners.notify("event", parameters);
|
||||
} else if ("close".equals(event)) {
|
||||
typedListeners.notify(EventType.CLOSE, this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose(Consumer<CDPSession> handler) {
|
||||
typedListeners.add(EventType.CLOSE, handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void offClose(Consumer<CDPSession> handler) {
|
||||
typedListeners.remove(EventType.CLOSE, handler);
|
||||
}
|
||||
|
||||
public JsonObject send(String method) {
|
||||
return send(method, null);
|
||||
}
|
||||
|
||||
@@ -333,6 +333,9 @@ public class Connection {
|
||||
case "Dialog":
|
||||
result = new DialogImpl(parent, type, guid, initializer);
|
||||
break;
|
||||
case "Disposable":
|
||||
result = new DisposableObject(parent, type, guid, initializer);
|
||||
break;
|
||||
case "Electron":
|
||||
// result = new Playwright(parent, type, guid, initializer);
|
||||
break;
|
||||
@@ -378,6 +381,9 @@ public class Connection {
|
||||
break;
|
||||
case "SocksSupport":
|
||||
break;
|
||||
case "Debugger":
|
||||
result = new DebuggerImpl(parent, type, guid, initializer);
|
||||
break;
|
||||
case "Tracing":
|
||||
result = new TracingImpl(parent, type, guid, initializer);
|
||||
break;
|
||||
|
||||
@@ -38,6 +38,11 @@ public class ConsoleMessageImpl implements ConsoleMessage {
|
||||
this.initializer = initializer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double timestamp() {
|
||||
return initializer.get("timestamp").getAsDouble();
|
||||
}
|
||||
|
||||
public String type() {
|
||||
return initializer.get("type").getAsString();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.microsoft.playwright.Debugger;
|
||||
import com.microsoft.playwright.options.Location;
|
||||
import com.microsoft.playwright.options.PausedDetails;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static com.microsoft.playwright.impl.Serialization.gson;
|
||||
|
||||
class DebuggerImpl extends ChannelOwner implements Debugger {
|
||||
private final List<Runnable> pausedStateChangedHandlers = new ArrayList<>();
|
||||
private List<PausedDetails> pausedDetails = new ArrayList<>();
|
||||
|
||||
DebuggerImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleEvent(String event, JsonObject params) {
|
||||
if ("pausedStateChanged".equals(event)) {
|
||||
JsonArray details = params.getAsJsonArray("pausedDetails");
|
||||
pausedDetails = Arrays.asList(gson().fromJson(details, PausedDetails[].class));
|
||||
for (Runnable handler : new ArrayList<>(pausedStateChangedHandlers)) {
|
||||
handler.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPausedStateChanged(Runnable handler) {
|
||||
pausedStateChangedHandlers.add(handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void offPausedStateChanged(Runnable handler) {
|
||||
pausedStateChangedHandlers.remove(handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PausedDetails> pausedDetails() {
|
||||
return pausedDetails;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pause() {
|
||||
sendMessage("pause", new JsonObject(), NO_TIMEOUT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resume() {
|
||||
sendMessage("resume", new JsonObject(), NO_TIMEOUT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void next() {
|
||||
sendMessage("next", new JsonObject(), NO_TIMEOUT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runTo(Location location) {
|
||||
JsonObject params = gson().toJsonTree(location).getAsJsonObject();
|
||||
sendMessage("runTo", params, NO_TIMEOUT);
|
||||
}
|
||||
}
|
||||
@@ -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.impl;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
class DisposableObject extends ChannelOwner implements AutoCloseable {
|
||||
DisposableObject(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
sendMessage("dispose", new JsonObject(), NO_TIMEOUT);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
class DisposableStub implements AutoCloseable {
|
||||
private Runnable dispose;
|
||||
|
||||
DisposableStub(Runnable dispose) {
|
||||
this.dispose = dispose;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (dispose == null)
|
||||
return;
|
||||
Runnable d = dispose;
|
||||
dispose = null;
|
||||
d.run();
|
||||
}
|
||||
}
|
||||
@@ -108,6 +108,14 @@ class LocatorImpl implements Locator {
|
||||
return (List<String>) frame.evalOnSelectorAll(selector, "ee => ee.map(e => e.textContent || '')");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locator normalize() {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty("selector", selector);
|
||||
JsonObject result = frame.sendMessage("normalizeLocator", params, ChannelOwner.NO_TIMEOUT).getAsJsonObject();
|
||||
return new LocatorImpl(frame, result.get("selector").getAsString(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locator and(Locator locator) {
|
||||
LocatorImpl other = (LocatorImpl) locator;
|
||||
|
||||
@@ -143,6 +143,13 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
} else {
|
||||
opener = null;
|
||||
}
|
||||
if (initializer.has("video")) {
|
||||
String artifactGuid = initializer.getAsJsonObject("video").get("guid").getAsString();
|
||||
ArtifactImpl artifact = connection.getExistingObject(artifactGuid);
|
||||
video = new VideoImpl(this, artifact);
|
||||
} else {
|
||||
video = new VideoImpl(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -219,10 +226,6 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
if (!webSocketRoutes.handle(route)) {
|
||||
browserContext.handleWebSocketRoute(route);
|
||||
}
|
||||
} else if ("video".equals(event)) {
|
||||
String artifactGuid = params.getAsJsonObject("artifact").get("guid").getAsString();
|
||||
ArtifactImpl artifact = connection.getExistingObject(artifactGuid);
|
||||
forceVideo().setArtifact(artifact);
|
||||
} else if ("crash".equals(event)) {
|
||||
listeners.notify(EventType.CRASH, this);
|
||||
} else if ("close".equals(event)) {
|
||||
@@ -633,6 +636,16 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String ariaSnapshot(AriaSnapshotOptions options) {
|
||||
if (options == null) {
|
||||
options = new AriaSnapshotOptions();
|
||||
}
|
||||
JsonObject params = gson().toJsonTree(options).getAsJsonObject();
|
||||
JsonObject result = mainFrame.sendMessage("ariaSnapshot", params, mainFrame.timeout(options.timeout)).getAsJsonObject();
|
||||
return result.get("snapshot").getAsString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object evalOnSelector(String selector, String pageFunction, Object arg, EvalOnSelectorOptions options) {
|
||||
return mainFrame.evalOnSelectorImpl(
|
||||
@@ -645,25 +658,26 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInitScript(String script) {
|
||||
addInitScriptImpl(script);
|
||||
public AutoCloseable addInitScript(String script) {
|
||||
return addInitScriptImpl(script);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInitScript(Path path) {
|
||||
public AutoCloseable addInitScript(Path path) {
|
||||
try {
|
||||
byte[] bytes = readAllBytes(path);
|
||||
String script = addSourceUrlToScript(new String(bytes, UTF_8), path);
|
||||
addInitScriptImpl(script);
|
||||
return addInitScriptImpl(script);
|
||||
} catch (IOException e) {
|
||||
throw new PlaywrightException("Failed to read script from file", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void addInitScriptImpl(String script) {
|
||||
private AutoCloseable addInitScriptImpl(String script) {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty("source", script);
|
||||
sendMessage("addInitScript", params, NO_TIMEOUT);
|
||||
JsonObject result = sendMessage("addInitScript", params, NO_TIMEOUT).getAsJsonObject();
|
||||
return connection.getExistingObject(result.getAsJsonObject("disposable").get("guid").getAsString());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -735,11 +749,11 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exposeBinding(String name, BindingCallback playwrightBinding, ExposeBindingOptions options) {
|
||||
exposeBindingImpl(name, playwrightBinding, options);
|
||||
public AutoCloseable exposeBinding(String name, BindingCallback playwrightBinding, ExposeBindingOptions options) {
|
||||
return exposeBindingImpl(name, playwrightBinding, options);
|
||||
}
|
||||
|
||||
private void exposeBindingImpl(String name, BindingCallback playwrightBinding, ExposeBindingOptions options) {
|
||||
private AutoCloseable exposeBindingImpl(String name, BindingCallback playwrightBinding, ExposeBindingOptions options) {
|
||||
if (bindings.containsKey(name)) {
|
||||
throw new PlaywrightException("Function \"" + name + "\" has been already registered");
|
||||
}
|
||||
@@ -753,12 +767,13 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
if (options != null && options.handle != null && options.handle) {
|
||||
params.addProperty("needsHandle", true);
|
||||
}
|
||||
sendMessage("exposeBinding", params, NO_TIMEOUT);
|
||||
JsonObject result = sendMessage("exposeBinding", params, NO_TIMEOUT).getAsJsonObject();
|
||||
return connection.getExistingObject(result.getAsJsonObject("disposable").get("guid").getAsString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exposeFunction(String name, FunctionCallback playwrightFunction) {
|
||||
exposeBindingImpl(name, (BindingCallback.Source source, Object... args) -> playwrightFunction.call(args), null);
|
||||
public AutoCloseable exposeFunction(String name, FunctionCallback playwrightFunction) {
|
||||
return exposeBindingImpl(name, (BindingCallback.Source source, Object... args) -> playwrightFunction.call(args), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -998,8 +1013,9 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ConsoleMessage> consoleMessages() {
|
||||
JsonObject json = sendMessage("consoleMessages", new JsonObject(), NO_TIMEOUT).getAsJsonObject();
|
||||
public List<ConsoleMessage> consoleMessages(ConsoleMessagesOptions options) {
|
||||
JsonObject params = options != null ? gson().toJsonTree(options).getAsJsonObject() : new JsonObject();
|
||||
JsonObject json = sendMessage("consoleMessages", params, NO_TIMEOUT).getAsJsonObject();
|
||||
JsonArray messages = json.getAsJsonArray("messages");
|
||||
List<ConsoleMessage> result = new ArrayList<>();
|
||||
for (JsonElement item : messages) {
|
||||
@@ -1008,6 +1024,16 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearConsoleMessages() {
|
||||
sendMessage("clearConsoleMessages", new JsonObject(), NO_TIMEOUT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearPageErrors() {
|
||||
sendMessage("clearPageErrors", new JsonObject(), NO_TIMEOUT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> pageErrors() {
|
||||
JsonObject json = sendMessage("pageErrors", new JsonObject(), NO_TIMEOUT).getAsJsonObject();
|
||||
@@ -1043,6 +1069,17 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
return opener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelPickLocator() {
|
||||
sendMessage("cancelPickLocator", new JsonObject(), NO_TIMEOUT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locator pickLocator() {
|
||||
JsonObject result = sendMessage("pickLocator", new JsonObject(), NO_TIMEOUT).getAsJsonObject();
|
||||
return new LocatorImpl(mainFrame, result.get("selector").getAsString(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pause() {
|
||||
TimeoutSettings settings = browserContext.timeoutSettings;
|
||||
@@ -1105,18 +1142,21 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void route(String url, Consumer<Route> handler, RouteOptions options) {
|
||||
public AutoCloseable route(String url, Consumer<Route> handler, RouteOptions options) {
|
||||
route(UrlMatcher.forGlob(browserContext.baseUrl(), url, this.connection.localUtils, false), handler, options);
|
||||
return new DisposableStub(() -> unroute(url, handler));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void route(Pattern url, Consumer<Route> handler, RouteOptions options) {
|
||||
public AutoCloseable route(Pattern url, Consumer<Route> handler, RouteOptions options) {
|
||||
route(new UrlMatcher(url), handler, options);
|
||||
return new DisposableStub(() -> unroute(url, handler));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void route(Predicate<String> url, Consumer<Route> handler, RouteOptions options) {
|
||||
public AutoCloseable route(Predicate<String> url, Consumer<Route> handler, RouteOptions options) {
|
||||
route(new UrlMatcher(url), handler, options);
|
||||
return new DisposableStub(() -> unroute(url, handler));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1357,22 +1397,9 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
}
|
||||
|
||||
|
||||
private VideoImpl forceVideo() {
|
||||
if (video == null) {
|
||||
video = new VideoImpl(this);
|
||||
}
|
||||
return video;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VideoImpl video() {
|
||||
// Note: we are creating Video object lazily, because we do not know
|
||||
// BrowserContextOptions when constructing the page - it is assigned
|
||||
// too late during launchPersistentContext.
|
||||
if (browserContext.videosDir() == null) {
|
||||
return null;
|
||||
}
|
||||
return forceVideo();
|
||||
return video;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -42,6 +42,7 @@ public class RequestImpl extends ChannelOwner implements Request {
|
||||
String failure;
|
||||
Timing timing;
|
||||
boolean didFailOrFinish;
|
||||
ResponseImpl existingResponse;
|
||||
private FallbackOverrides fallbackOverrides;
|
||||
|
||||
static class FallbackOverrides {
|
||||
@@ -66,6 +67,11 @@ public class RequestImpl extends ChannelOwner implements Request {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseImpl existingResponse() {
|
||||
return existingResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> allHeaders() {
|
||||
return getRawHeaders().headers();
|
||||
|
||||
@@ -36,7 +36,7 @@ import static java.util.Arrays.asList;
|
||||
public class ResponseImpl extends ChannelOwner implements Response {
|
||||
private final RawHeaders headers;
|
||||
private RawHeaders rawHeaders;
|
||||
private final RequestImpl request;
|
||||
final RequestImpl request;
|
||||
|
||||
ResponseImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
@@ -86,6 +86,14 @@ public class ResponseImpl extends ChannelOwner implements Response {
|
||||
return initializer.get("fromServiceWorker").getAsBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String httpVersion() {
|
||||
if (initializer.has("httpVersion")) {
|
||||
return initializer.get("httpVersion").getAsString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> headers() {
|
||||
return headers.headers();
|
||||
|
||||
@@ -58,6 +58,8 @@ class Serialization {
|
||||
.registerTypeAdapter(ScreenshotCaret.class, new ToLowerCaseSerializer<ScreenshotCaret>())
|
||||
.registerTypeAdapter(ServiceWorkerPolicy.class, new ToLowerCaseAndDashSerializer<ServiceWorkerPolicy>())
|
||||
.registerTypeAdapter(MouseButton.class, new ToLowerCaseSerializer<MouseButton>())
|
||||
.registerTypeAdapter(ConsoleMessagesFilter.class, new ConsoleMessagesFilterSerializer())
|
||||
.registerTypeAdapter(AriaSnapshotMode.class, new ToLowerCaseSerializer<AriaSnapshotMode>())
|
||||
.registerTypeAdapter(LoadState.class, new ToLowerCaseSerializer<LoadState>())
|
||||
.registerTypeAdapter(WaitUntilState.class, new ToLowerCaseSerializer<WaitUntilState>())
|
||||
.registerTypeAdapter(WaitForSelectorState.class, new ToLowerCaseSerializer<WaitForSelectorState>())
|
||||
@@ -482,6 +484,17 @@ class Serialization {
|
||||
}
|
||||
}
|
||||
|
||||
private static class ConsoleMessagesFilterSerializer implements JsonSerializer<ConsoleMessagesFilter> {
|
||||
@Override
|
||||
public JsonElement serialize(ConsoleMessagesFilter src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
switch (src) {
|
||||
case ALL: return new JsonPrimitive("all");
|
||||
case SINCE_NAVIGATION: return new JsonPrimitive("sinceNavigation");
|
||||
default: throw new PlaywrightException("Unknown ConsoleMessagesFilter: " + src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class ToLowerCaseAndDashSerializer<E extends Enum<E>> implements JsonSerializer<E> {
|
||||
@Override
|
||||
public JsonElement serialize(E src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
|
||||
@@ -86,8 +86,9 @@ class TracingImpl extends ChannelOwner implements Tracing {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void group(String name, GroupOptions options) {
|
||||
public AutoCloseable group(String name, GroupOptions options) {
|
||||
groupImpl(name, options);
|
||||
return new DisposableStub(this::groupEnd);
|
||||
}
|
||||
|
||||
private void groupImpl(String name, GroupOptions options) {
|
||||
|
||||
@@ -16,37 +16,32 @@
|
||||
|
||||
package com.microsoft.playwright.impl;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.microsoft.playwright.PlaywrightException;
|
||||
import com.microsoft.playwright.Video;
|
||||
|
||||
import static com.microsoft.playwright.impl.Serialization.gson;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
class VideoImpl implements Video {
|
||||
private final PageImpl page;
|
||||
private final WaitableResult<ArtifactImpl> waitableArtifact = new WaitableResult<>();
|
||||
private ArtifactImpl artifact;
|
||||
|
||||
VideoImpl(PageImpl page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
void setArtifact(ArtifactImpl artifact) {
|
||||
waitableArtifact.complete(artifact);
|
||||
}
|
||||
|
||||
private ArtifactImpl waitForArtifact() {
|
||||
Waitable<ArtifactImpl> waitable = new WaitableRace<>(asList(waitableArtifact, (Waitable<ArtifactImpl>) page.waitableClosedOrCrashed));
|
||||
return page.runUntil(() -> {}, waitable);
|
||||
VideoImpl(PageImpl page, ArtifactImpl artifact) {
|
||||
this.page = page;
|
||||
this.artifact = artifact;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
try {
|
||||
waitForArtifact().delete();
|
||||
} catch (PlaywrightException e) {
|
||||
}
|
||||
if (artifact != null)
|
||||
artifact.delete();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -54,22 +49,32 @@ class VideoImpl implements Video {
|
||||
if (page.connection.isRemote) {
|
||||
throw new PlaywrightException("Path is not available when using browserType.connect(). Use saveAs() to save a local copy.");
|
||||
}
|
||||
try {
|
||||
return Paths.get(waitForArtifact().initializer.get("absolutePath").getAsString());
|
||||
} catch (PlaywrightException e) {
|
||||
throw new PlaywrightException("Page did not produce any video frames", e);
|
||||
if (artifact == null)
|
||||
throw new PlaywrightException("Video recording has not been started.");
|
||||
return Paths.get(artifact.initializer.get("absolutePath").getAsString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AutoCloseable start(StartOptions options) {
|
||||
JsonObject params = new JsonObject();
|
||||
if (options != null) {
|
||||
params = gson().toJsonTree(options).getAsJsonObject();
|
||||
}
|
||||
JsonObject result = page.sendMessage("videoStart", params, ChannelOwner.NO_TIMEOUT).getAsJsonObject();
|
||||
String artifactGuid = result.getAsJsonObject("artifact").get("guid").getAsString();
|
||||
artifact = page.connection.getExistingObject(artifactGuid);
|
||||
return new DisposableStub(this::stop);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
page.sendMessage("videoStop", new JsonObject(), ChannelOwner.NO_TIMEOUT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveAs(Path path) {
|
||||
if (!page.isClosed()) {
|
||||
throw new PlaywrightException("Page is not yet closed. Close the page prior to calling saveAs");
|
||||
}
|
||||
try {
|
||||
waitForArtifact().saveAs(path);
|
||||
} catch (PlaywrightException e) {
|
||||
throw new PlaywrightException("Page did not produce any video frames", e);
|
||||
}
|
||||
if (artifact == null)
|
||||
throw new PlaywrightException("Video recording has not been started.");
|
||||
artifact.saveAs(path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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 Annotate {
|
||||
/**
|
||||
* How long each annotation is displayed in milliseconds. Defaults to {@code 500}.
|
||||
*/
|
||||
public Integer delay;
|
||||
|
||||
/**
|
||||
* How long each annotation is displayed in milliseconds. Defaults to {@code 500}.
|
||||
*/
|
||||
public Annotate setDelay(int delay) {
|
||||
this.delay = delay;
|
||||
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 AriaSnapshotMode {
|
||||
AI,
|
||||
DEFAULT
|
||||
}
|
||||
@@ -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 ConsoleMessagesFilter {
|
||||
ALL,
|
||||
SINCE_NAVIGATION
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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 PausedDetails {
|
||||
public Location location;
|
||||
public String title;
|
||||
|
||||
}
|
||||
@@ -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.options;
|
||||
|
||||
public class Size {
|
||||
/**
|
||||
* Video frame width.
|
||||
*/
|
||||
public int width;
|
||||
/**
|
||||
* Video frame height.
|
||||
*/
|
||||
public int height;
|
||||
|
||||
public Size(int width, int height) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
}
|
||||
@@ -155,6 +155,26 @@ public class TestBrowserContextCDPSession extends TestBase {
|
||||
assertEquals(2, events.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldEmitEventForEachCDPEvent() {
|
||||
CDPSession client = page.context().newCDPSession(page);
|
||||
client.send("Network.enable");
|
||||
List<JsonObject> events = new ArrayList<>();
|
||||
client.on("event", events::add);
|
||||
page.navigate(server.EMPTY_PAGE);
|
||||
assertTrue(events.size() > 0);
|
||||
JsonObject requestEvent = null;
|
||||
for (JsonObject e : events) {
|
||||
if ("Network.requestWillBeSent".equals(e.get("method").getAsString())) {
|
||||
requestEvent = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertNotNull(requestEvent);
|
||||
assertEquals(server.EMPTY_PAGE,
|
||||
requestEvent.getAsJsonObject("params").getAsJsonObject("request").get("url").getAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRemoveEventListeners() {
|
||||
CDPSession cdpSession = page.context().newCDPSession(page);
|
||||
|
||||
@@ -31,6 +31,7 @@ import static com.microsoft.playwright.Utils.assertJsonEquals;
|
||||
import static com.microsoft.playwright.Utils.mapOf;
|
||||
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class TestBrowserContextStorageState extends TestBase {
|
||||
|
||||
@@ -276,4 +277,12 @@ public class TestBrowserContextStorageState extends TestBase {
|
||||
assertEquals("{\"cookies\":[],\"origins\":[]}", context.storageState(
|
||||
new BrowserContext.StorageStateOptions().setIndexedDB(false)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void setStorageStateShouldHandleMissingFile(@TempDir Path tempDir) {
|
||||
Path file = tempDir.resolve("does-not-exist.json");
|
||||
PlaywrightException e = org.junit.jupiter.api.Assertions.assertThrows(
|
||||
PlaywrightException.class, () -> context.setStorageState(file));
|
||||
assertTrue(e.getMessage().contains("Failed to read storage state from file"), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,9 +355,8 @@ public class TestClick extends TestBase {
|
||||
page.evalOnSelector("button", "button => button.style.borderWidth = '8px'");
|
||||
page.click("button", new Page.ClickOptions().setPosition(20, 10));
|
||||
assertEquals(page.evaluate("result"), "Clicked");
|
||||
// Safari reports border-relative offsetX/offsetY.
|
||||
assertEquals(isWebKit() ? 20 + 8 : 20, page.evaluate("offsetX"));
|
||||
assertEquals(isWebKit() ? 10 + 8 : 10, page.evaluate("offsetY"));
|
||||
assertEquals(20, page.evaluate("offsetX"));
|
||||
assertEquals(10, page.evaluate("offsetY"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -367,9 +366,8 @@ public class TestClick extends TestBase {
|
||||
page.evalOnSelector("button", "button => button.style.fontSize = '12px'");
|
||||
page.click("button", new Page.ClickOptions().setPosition(20, 10));
|
||||
assertEquals("Clicked", page.evaluate("result"));
|
||||
// Safari reports border-relative offsetX/offsetY.
|
||||
assertEquals(isWebKit() ? 12 * 2 + 20 : 20, page.evaluate("offsetX"));
|
||||
assertEquals(isWebKit() ? 12 * 2 + 10 : 10, page.evaluate("offsetY"));
|
||||
assertEquals(20, page.evaluate("offsetX"));
|
||||
assertEquals(10, page.evaluate("offsetY"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -379,9 +377,8 @@ public class TestClick extends TestBase {
|
||||
page.evalOnSelector("button", "button => button.style.height = button.style.width = '2000px'");
|
||||
page.click("button", new Page.ClickOptions().setPosition(1900, 1910));
|
||||
assertEquals("Clicked", page.evaluate("() => window['result']"));
|
||||
// Safari reports border-relative offsetX/offsetY.
|
||||
assertEquals(isWebKit() ? 1900 + 8 : 1900, page.evaluate("offsetX"));
|
||||
assertEquals(isWebKit() ? 1910 + 8 : 1910, page.evaluate("offsetY"));
|
||||
assertEquals(1900, page.evaluate("offsetX"));
|
||||
assertEquals(1910, page.evaluate("offsetY"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -400,9 +397,8 @@ public class TestClick extends TestBase {
|
||||
"}");
|
||||
page.click("button", new Page.ClickOptions().setPosition(1900, 1910));
|
||||
assertEquals("Clicked", page.evaluate("() => window['result']"));
|
||||
// Safari reports border-relative offsetX/offsetY.
|
||||
assertEquals(isWebKit() ? 1900 + 8 : 1900, page.evaluate("offsetX"));
|
||||
assertEquals(isWebKit() ? 1910 + 8 : 1910, page.evaluate("offsetY"));
|
||||
assertEquals(1900, page.evaluate("offsetX"));
|
||||
assertEquals(1910, page.evaluate("offsetY"));
|
||||
}
|
||||
|
||||
private static void expectCloseTo(double expected, double actual) {
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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.PausedDetails;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class TestDebugger extends TestBase {
|
||||
@Test
|
||||
void shouldReturnEmptyPausedDetailsInitially() {
|
||||
Debugger dbg = context.debugger();
|
||||
assertEquals(Collections.emptyList(), dbg.pausedDetails());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPauseAtPauseCall() {
|
||||
page.setContent("<div>click me</div>");
|
||||
Debugger dbg = context.debugger();
|
||||
assertEquals(Collections.emptyList(), dbg.pausedDetails());
|
||||
|
||||
dbg.pause();
|
||||
|
||||
boolean[] paused = {false};
|
||||
dbg.onPausedStateChanged(() -> {
|
||||
if (!paused[0]) {
|
||||
paused[0] = true;
|
||||
List<PausedDetails> details = dbg.pausedDetails();
|
||||
assertEquals(1, details.size());
|
||||
assertTrue(details.get(0).title.contains("Pause"), "title: " + details.get(0).title);
|
||||
dbg.resume();
|
||||
}
|
||||
});
|
||||
|
||||
page.pause(); // blocks until dbg.resume() is called from event handler
|
||||
assertEquals(Collections.emptyList(), dbg.pausedDetails());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPauseAtNextAndResume() {
|
||||
page.setContent("<div>click me</div>");
|
||||
Debugger dbg = context.debugger();
|
||||
assertEquals(Collections.emptyList(), dbg.pausedDetails());
|
||||
|
||||
dbg.pause();
|
||||
|
||||
boolean[] paused = {false};
|
||||
dbg.onPausedStateChanged(() -> {
|
||||
if (!paused[0]) {
|
||||
paused[0] = true;
|
||||
List<PausedDetails> details = dbg.pausedDetails();
|
||||
assertEquals(1, details.size());
|
||||
assertTrue(details.get(0).title.contains("Click"), "title: " + details.get(0).title);
|
||||
dbg.resume();
|
||||
}
|
||||
});
|
||||
|
||||
page.click("div"); // blocks until dbg.resume() is called
|
||||
assertEquals(Collections.emptyList(), dbg.pausedDetails());
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,7 @@ public class TestDefaultBrowserContext2 extends TestBase {
|
||||
@TempDir Path tempDir;
|
||||
|
||||
@AfterEach
|
||||
private void closePersistentContext() {
|
||||
void closePersistentContext() {
|
||||
if (persistentContext != null) {
|
||||
persistentContext.close();
|
||||
persistentContext = null;
|
||||
|
||||
@@ -136,4 +136,209 @@ public class TestPageAriaSnapshot {
|
||||
" - /url: /auth?r=/");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSnapshotIntegration(Page page) {
|
||||
page.setContent(
|
||||
"<h1>Microsoft</h1>" +
|
||||
"<div>Open source projects and samples from Microsoft</div>" +
|
||||
"<ul>" +
|
||||
"<li><details><summary>Verified</summary><div><div>" +
|
||||
"<p>We've verified that the organization <strong>microsoft</strong> controls the domain:</p>" +
|
||||
"<ul><li class=\"mb-1\"><strong>opensource.microsoft.com</strong></li></ul>" +
|
||||
"<div><a href=\"about: blank\">Learn more about verified organizations</a></div>" +
|
||||
"</div></div></details></li>" +
|
||||
"<li><a href=\"about:blank\"><summary title=\"Label: GitHub Sponsor\">Sponsor</summary></a></li>" +
|
||||
"</ul>");
|
||||
checkAndMatchSnapshot(page.locator("body"),
|
||||
"- heading \"Microsoft\" [level=1]\n" +
|
||||
"- text: Open source projects and samples from Microsoft\n" +
|
||||
"- list:\n" +
|
||||
" - listitem:\n" +
|
||||
" - group: Verified\n" +
|
||||
" - listitem:\n" +
|
||||
" - link \"Sponsor\":\n" +
|
||||
" - /url: about:blank");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSupportMultilineText(Page page) {
|
||||
page.setContent("<p>\n Line 1\n Line 2\n Line 3\n </p>");
|
||||
checkAndMatchSnapshot(page.locator("body"), "- paragraph: Line 1 Line 2 Line 3");
|
||||
assertThat(page.locator("body")).matchesAriaSnapshot(
|
||||
" - paragraph: |\n" +
|
||||
" Line 1\n" +
|
||||
" Line 2\n" +
|
||||
" Line 3");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldConcatenateSpanText(Page page) {
|
||||
page.setContent("<span>One</span> <span>Two</span> <span>Three</span>");
|
||||
checkAndMatchSnapshot(page.locator("body"), "- text: One Two Three");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldConcatenateSpanText2(Page page) {
|
||||
page.setContent("<span>One </span><span>Two </span><span>Three</span>");
|
||||
checkAndMatchSnapshot(page.locator("body"), "- text: One Two Three");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldConcatenateDivTextWithSpaces(Page page) {
|
||||
page.setContent("<div>One</div><div>Two</div><div>Three</div>");
|
||||
checkAndMatchSnapshot(page.locator("body"), "- text: One Two Three");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldIncludePseudoInText(Page page) {
|
||||
page.setContent(
|
||||
"<style>span:before { content: 'world'; } div:after { content: 'bye'; }</style>" +
|
||||
"<a href=\"about:blank\"><span>hello</span><div>hello</div></a>");
|
||||
checkAndMatchSnapshot(page.locator("body"),
|
||||
"- link \"worldhello hellobye\":\n" +
|
||||
" - /url: about:blank");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotIncludeHiddenPseudoInText(Page page) {
|
||||
page.setContent(
|
||||
"<style>span:before { content: 'world'; display: none; } div:after { content: 'bye'; visibility: hidden; }</style>" +
|
||||
"<a href=\"about:blank\"><span>hello</span><div>hello</div></a>");
|
||||
checkAndMatchSnapshot(page.locator("body"),
|
||||
"- link \"hello hello\":\n" +
|
||||
" - /url: about:blank");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldIncludeNewLineForBlockPseudo(Page page) {
|
||||
page.setContent(
|
||||
"<style>span:before { content: 'world'; display: block; } div:after { content: 'bye'; display: block; }</style>" +
|
||||
"<a href=\"about:blank\"><span>hello</span><div>hello</div></a>");
|
||||
checkAndMatchSnapshot(page.locator("body"),
|
||||
"- link \"world hello hello bye\":\n" +
|
||||
" - /url: about:blank");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldWorkWithSlots(Page page) {
|
||||
// Text "foo" is assigned to the slot, should not be used twice.
|
||||
page.setContent(
|
||||
"<button><div>foo</div></button>" +
|
||||
"<script>(() => {" +
|
||||
" const container = document.querySelector('div');" +
|
||||
" const shadow = container.attachShadow({ mode: 'open' });" +
|
||||
" const slot = document.createElement('slot');" +
|
||||
" shadow.appendChild(slot);" +
|
||||
"})()</script>");
|
||||
checkAndMatchSnapshot(page.locator("body"), "- button \"foo\"");
|
||||
|
||||
// Text "foo" is assigned to the slot, should be used instead of slot content.
|
||||
page.setContent(
|
||||
"<div>foo</div>" +
|
||||
"<script>(() => {" +
|
||||
" const container = document.querySelector('div');" +
|
||||
" const shadow = container.attachShadow({ mode: 'open' });" +
|
||||
" const button = document.createElement('button');" +
|
||||
" shadow.appendChild(button);" +
|
||||
" const slot = document.createElement('slot');" +
|
||||
" button.appendChild(slot);" +
|
||||
" const span = document.createElement('span');" +
|
||||
" span.textContent = 'pre';" +
|
||||
" slot.appendChild(span);" +
|
||||
"})()</script>");
|
||||
checkAndMatchSnapshot(page.locator("body"), "- button \"foo\"");
|
||||
|
||||
// Nothing is assigned to the slot, should use slot content.
|
||||
page.setContent(
|
||||
"<div></div>" +
|
||||
"<script>(() => {" +
|
||||
" const container = document.querySelector('div');" +
|
||||
" const shadow = container.attachShadow({ mode: 'open' });" +
|
||||
" const button = document.createElement('button');" +
|
||||
" shadow.appendChild(button);" +
|
||||
" const slot = document.createElement('slot');" +
|
||||
" button.appendChild(slot);" +
|
||||
" const span = document.createElement('span');" +
|
||||
" span.textContent = 'pre';" +
|
||||
" slot.appendChild(span);" +
|
||||
"})()</script>");
|
||||
checkAndMatchSnapshot(page.locator("body"), "- button \"pre\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSnapshotInnerText(Page page) {
|
||||
page.setContent(
|
||||
"<div role=\"listitem\"><div><div><span title=\"a.test.ts\">a.test.ts</span></div>" +
|
||||
"<div><button title=\"Run\"></button><button title=\"Show source\"></button><button title=\"Watch\"></button></div></div></div>" +
|
||||
"<div role=\"listitem\"><div><div><span title=\"snapshot\">snapshot</span></div>" +
|
||||
"<div class=\"ui-mode-list-item-time\">30ms</div>" +
|
||||
"<div><button title=\"Run\"></button><button title=\"Show source\"></button><button title=\"Watch\"></button></div></div></div>");
|
||||
checkAndMatchSnapshot(page.locator("body"),
|
||||
" - listitem:\n" +
|
||||
" - text: a.test.ts\n" +
|
||||
" - button \"Run\"\n" +
|
||||
" - button \"Show source\"\n" +
|
||||
" - button \"Watch\"\n" +
|
||||
" - listitem:\n" +
|
||||
" - text: snapshot 30ms\n" +
|
||||
" - button \"Run\"\n" +
|
||||
" - button \"Show source\"\n" +
|
||||
" - button \"Watch\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
void checkAriaHiddenText(Page page) {
|
||||
page.setContent("<p><span>hello</span><span aria-hidden=\"true\">world</span></p>");
|
||||
checkAndMatchSnapshot(page.locator("body"), "- paragraph: hello");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldIgnorePresentationAndNoneRoles(Page page) {
|
||||
page.setContent("<ul><li role=\"presentation\">hello</li><li role=\"none\">world</li></ul>");
|
||||
checkAndMatchSnapshot(page.locator("body"), "- list: hello world");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotUseOnAsCheckboxValue(Page page) {
|
||||
page.setContent("<input type=\"checkbox\"><input type=\"radio\">");
|
||||
checkAndMatchSnapshot(page.locator("body"), "- checkbox\n- radio");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotReportTextareaTextContent(Page page) {
|
||||
page.setContent("<textarea>Before</textarea>");
|
||||
checkAndMatchSnapshot(page.locator("body"), "- textbox: Before");
|
||||
page.evaluate("document.querySelector('textarea').value = 'After'");
|
||||
checkAndMatchSnapshot(page.locator("body"), "- textbox: After");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotShowVisibleChildrenOfHiddenElements(Page page) {
|
||||
page.setContent(
|
||||
"<div style=\"visibility: hidden;\">" +
|
||||
"<div style=\"visibility: visible;\"><button>Button</button></div>" +
|
||||
"</div>");
|
||||
assertEquals("", page.locator("body").ariaSnapshot());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotShowUnhiddenChildrenOfAriaHiddenElements(Page page) {
|
||||
page.setContent(
|
||||
"<div aria-hidden=\"true\">" +
|
||||
"<div aria-hidden=\"false\"><button>Button</button></div>" +
|
||||
"</div>");
|
||||
assertEquals("", page.locator("body").ariaSnapshot());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSnapshotPlaceholderWhenDifferentFromName(Page page) {
|
||||
page.setContent("<input placeholder=\"Placeholder\">");
|
||||
assertThat(page.locator("body")).matchesAriaSnapshot("- textbox \"Placeholder\"");
|
||||
|
||||
page.setContent("<input placeholder=\"Placeholder\" aria-label=\"Label\">");
|
||||
assertThat(page.locator("body")).matchesAriaSnapshot(
|
||||
"- textbox \"Label\":\n" +
|
||||
" - /placeholder: Placeholder");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
package com.microsoft.playwright;
|
||||
|
||||
import com.microsoft.playwright.junit.FixtureTest;
|
||||
import com.microsoft.playwright.junit.UsePlaywright;
|
||||
import com.microsoft.playwright.options.AriaSnapshotMode;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
@FixtureTest
|
||||
@UsePlaywright
|
||||
public class TestPageAriaSnapshotAI {
|
||||
private static String aiSnapshot(Page page) {
|
||||
return page.ariaSnapshot(new Page.AriaSnapshotOptions().setMode(AriaSnapshotMode.AI));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldGenerateRefs(Page page) {
|
||||
page.setContent("<button>One</button><button>Two</button><button>Three</button>");
|
||||
|
||||
String snapshot1 = aiSnapshot(page);
|
||||
assertTrue(snapshot1.contains("button \"One\" [ref=e2]"), snapshot1);
|
||||
assertTrue(snapshot1.contains("button \"Two\" [ref=e3]"), snapshot1);
|
||||
assertTrue(snapshot1.contains("button \"Three\" [ref=e4]"), snapshot1);
|
||||
assertThat(page.locator("aria-ref=e2")).hasText("One");
|
||||
assertThat(page.locator("aria-ref=e3")).hasText("Two");
|
||||
assertThat(page.locator("aria-ref=e4")).hasText("Three");
|
||||
|
||||
page.locator("aria-ref=e3").evaluate("e => e.textContent = 'Not Two'");
|
||||
|
||||
String snapshot2 = aiSnapshot(page);
|
||||
assertTrue(snapshot2.contains("button \"One\" [ref=e2]"), snapshot2);
|
||||
assertTrue(snapshot2.contains("button \"Not Two\" [ref=e5]"), snapshot2);
|
||||
assertTrue(snapshot2.contains("button \"Three\" [ref=e4]"), snapshot2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldListIframes(Page page) {
|
||||
page.setContent(
|
||||
"<h1>Hello</h1>" +
|
||||
"<iframe name=\"foo\" src=\"data:text/html,<h1>World</h1>\">");
|
||||
|
||||
String snapshot = aiSnapshot(page);
|
||||
assertTrue(snapshot.contains("- iframe"), snapshot);
|
||||
|
||||
String frameSnapshot = page.frameLocator("iframe").locator("body").ariaSnapshot();
|
||||
assertEquals("- heading \"World\" [level=1]", frameSnapshot);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSnapshotLocatorInsideIframe(Page page) {
|
||||
page.setContent(
|
||||
"<h1>Main Page</h1>" +
|
||||
"<iframe srcdoc=\"<ul><li>Item 1</li><li>Item 2</li></ul>\"></iframe>");
|
||||
|
||||
Locator list = page.frames().get(1).locator("ul");
|
||||
String snapshot = list.ariaSnapshot(new Locator.AriaSnapshotOptions().setMode(AriaSnapshotMode.AI));
|
||||
assertTrue(snapshot.contains("list [ref=f1e1]"), snapshot);
|
||||
assertTrue(snapshot.contains("listitem [ref=f1e2]: Item 1"), snapshot);
|
||||
assertTrue(snapshot.contains("listitem [ref=f1e3]: Item 2"), snapshot);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCollapseGenericNodes(Page page) {
|
||||
page.setContent("<div><div><div><button>Button</button></div></div></div>");
|
||||
String snapshot = aiSnapshot(page);
|
||||
assertTrue(snapshot.contains("button \"Button\" [ref=e5]"), snapshot);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldIncludeCursorPointerHint(Page page) {
|
||||
page.setContent("<button style=\"cursor: pointer\">Button</button>");
|
||||
String snapshot = aiSnapshot(page);
|
||||
assertTrue(snapshot.contains("button \"Button\" [ref=e2] [cursor=pointer]"), snapshot);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotNestCursorPointerHints(Page page) {
|
||||
page.setContent(
|
||||
"<a style=\"cursor: pointer\" href=\"about:blank\">" +
|
||||
"Link with a button <button style=\"cursor: pointer\">Button</button>" +
|
||||
"</a>");
|
||||
String snapshot = aiSnapshot(page);
|
||||
assertTrue(snapshot.contains("link \"Link with a button Button\" [ref=e2] [cursor=pointer]"), snapshot);
|
||||
// The button inside a cursor-pointer link should not get a redundant [cursor=pointer]
|
||||
assertTrue(snapshot.contains("button \"Button\" [ref=e3]"), snapshot);
|
||||
assertFalse(snapshot.contains("button \"Button\" [ref=e3] [cursor=pointer]"), snapshot);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldShowVisibleChildrenOfHiddenElements(Page page) {
|
||||
page.setContent(
|
||||
"<div style=\"visibility: hidden\">" +
|
||||
" <div style=\"visibility: visible\"><button>Visible</button></div>" +
|
||||
" <div style=\"visibility: hidden\"><button style=\"visibility: visible\">Visible</button></div>" +
|
||||
" <div>" +
|
||||
" <div style=\"visibility: visible\"><button style=\"visibility: hidden\">Hidden</button></div>" +
|
||||
" <button>Hidden</button>" +
|
||||
" </div>" +
|
||||
"</div>");
|
||||
String snapshot = aiSnapshot(page);
|
||||
assertEquals(
|
||||
"- generic [active] [ref=e1]:\n" +
|
||||
" - button \"Visible\" [ref=e3]\n" +
|
||||
" - button \"Visible\" [ref=e4]",
|
||||
snapshot);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldIncludeActiveElementInformation(Page page) {
|
||||
page.setContent(
|
||||
"<button id=\"btn1\">Button 1</button>" +
|
||||
"<button id=\"btn2\" autofocus>Button 2</button>" +
|
||||
"<div>Not focusable</div>");
|
||||
page.waitForFunction("document.activeElement?.id === 'btn2'");
|
||||
|
||||
String snapshot = aiSnapshot(page);
|
||||
assertTrue(snapshot.contains("button \"Button 2\" [active] [ref=e3]"), snapshot);
|
||||
assertFalse(snapshot.contains("button \"Button 1\" [active]"), snapshot);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUpdateActiveElementOnFocus(Page page) {
|
||||
page.setContent(
|
||||
"<input id=\"input1\" placeholder=\"First input\">" +
|
||||
"<input id=\"input2\" placeholder=\"Second input\">");
|
||||
|
||||
String initialSnapshot = aiSnapshot(page);
|
||||
assertTrue(initialSnapshot.contains("textbox \"First input\" [ref=e2]"), initialSnapshot);
|
||||
assertTrue(initialSnapshot.contains("textbox \"Second input\" [ref=e3]"), initialSnapshot);
|
||||
assertFalse(initialSnapshot.contains("textbox \"First input\" [active]"), initialSnapshot);
|
||||
assertFalse(initialSnapshot.contains("textbox \"Second input\" [active]"), initialSnapshot);
|
||||
|
||||
page.locator("#input2").focus();
|
||||
|
||||
String afterFocusSnapshot = aiSnapshot(page);
|
||||
assertTrue(afterFocusSnapshot.contains("textbox \"Second input\" [active] [ref=e3]"), afterFocusSnapshot);
|
||||
assertFalse(afterFocusSnapshot.contains("textbox \"First input\" [active]"), afterFocusSnapshot);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCollapseInlineGenericNodes(Page page) {
|
||||
page.setContent(
|
||||
"<ul>" +
|
||||
"<li><b>3</b> <abbr>bds</abbr></li>" +
|
||||
"<li><b>2</b> <abbr>ba</abbr></li>" +
|
||||
"<li><b>1,200</b> <abbr>sqft</abbr></li>" +
|
||||
"</ul>");
|
||||
String snapshot = aiSnapshot(page);
|
||||
assertTrue(snapshot.contains("listitem [ref=e3]: 3 bds"), snapshot);
|
||||
assertTrue(snapshot.contains("listitem [ref=e4]: 2 ba"), snapshot);
|
||||
assertTrue(snapshot.contains("listitem [ref=e5]: 1,200 sqft"), snapshot);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotRemoveGenericNodesWithTitle(Page page) {
|
||||
page.setContent("<div title=\"Element title\">Element content</div>");
|
||||
String snapshot = aiSnapshot(page);
|
||||
assertTrue(snapshot.contains("generic \"Element title\" [ref=e2]"), snapshot);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldLimitDepth(Page page) {
|
||||
page.setContent(
|
||||
"<ul>" +
|
||||
"<li>item1</li>" +
|
||||
"<a href=\"about:blank\" style=\"cursor:pointer\">link</a>" +
|
||||
"<li><ul id=\"target\"><li>item2</li><li><ul><li>item3</li></ul></li></ul></li>" +
|
||||
"</ul>");
|
||||
|
||||
String snapshot1 = page.ariaSnapshot(new Page.AriaSnapshotOptions().setMode(AriaSnapshotMode.AI).setDepth(1));
|
||||
assertTrue(snapshot1.contains("listitem [ref=e3]: item1"), snapshot1);
|
||||
assertFalse(snapshot1.contains("item2"), snapshot1);
|
||||
assertFalse(snapshot1.contains("item3"), snapshot1);
|
||||
|
||||
String snapshot2 = page.ariaSnapshot(new Page.AriaSnapshotOptions().setMode(AriaSnapshotMode.AI).setDepth(3));
|
||||
assertTrue(snapshot2.contains("item1"), snapshot2);
|
||||
assertTrue(snapshot2.contains("item2"), snapshot2);
|
||||
assertFalse(snapshot2.contains("item3"), snapshot2);
|
||||
|
||||
String snapshot3 = page.ariaSnapshot(new Page.AriaSnapshotOptions().setMode(AriaSnapshotMode.AI).setDepth(100));
|
||||
assertTrue(snapshot3.contains("item1"), snapshot3);
|
||||
assertTrue(snapshot3.contains("item2"), snapshot3);
|
||||
assertTrue(snapshot3.contains("item3"), snapshot3);
|
||||
|
||||
String snapshot4 = page.locator("#target").ariaSnapshot(new Locator.AriaSnapshotOptions().setMode(AriaSnapshotMode.AI).setDepth(1));
|
||||
assertTrue(snapshot4.contains("listitem [ref=e7]: item2"), snapshot4);
|
||||
assertFalse(snapshot4.contains("item3"), snapshot4);
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.microsoft.playwright;
|
||||
|
||||
import com.microsoft.playwright.options.ConsoleMessagesFilter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledIf;
|
||||
|
||||
@@ -26,8 +27,7 @@ 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;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class TestPageEventConsole extends TestBase {
|
||||
@Test
|
||||
@@ -149,4 +149,60 @@ public class TestPageEventConsole extends TestBase {
|
||||
assertEquals(page, message.page());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHaveTimestamp() {
|
||||
double before = (double) System.currentTimeMillis() - 1;
|
||||
ConsoleMessage message = page.waitForConsoleMessage(
|
||||
() -> page.evaluate("() => console.log('timestamp test')"));
|
||||
double after = (double) System.currentTimeMillis() + 1;
|
||||
assertTrue(message.timestamp() >= before,
|
||||
"timestamp " + message.timestamp() + " should be >= " + before);
|
||||
assertTrue(message.timestamp() <= after,
|
||||
"timestamp " + message.timestamp() + " should be <= " + after);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHaveIncreasingTimestamps() {
|
||||
List<ConsoleMessage> messages = new ArrayList<>();
|
||||
page.onConsoleMessage(messages::add);
|
||||
page.evaluate("() => { console.log('first'); console.log('second'); console.log('third'); }");
|
||||
assertEquals(3, messages.size());
|
||||
for (int i = 1; i < messages.size(); i++)
|
||||
assertTrue(messages.get(i).timestamp() >= messages.get(i - 1).timestamp());
|
||||
}
|
||||
|
||||
@Test
|
||||
void clearConsoleMessagesShouldWork() {
|
||||
page.evaluate("() => { console.log('message1'); console.log('message2'); }");
|
||||
List<ConsoleMessage> messages = page.consoleMessages();
|
||||
assertTrue(messages.stream().anyMatch(m -> "message1".equals(m.text())));
|
||||
assertTrue(messages.stream().anyMatch(m -> "message2".equals(m.text())));
|
||||
|
||||
page.clearConsoleMessages();
|
||||
messages = page.consoleMessages();
|
||||
assertEquals(0, messages.size());
|
||||
|
||||
page.waitForConsoleMessage(() -> page.evaluate("() => console.log('message3')"));
|
||||
messages = page.consoleMessages();
|
||||
assertEquals(1, messages.size());
|
||||
assertEquals("message3", messages.get(0).text());
|
||||
}
|
||||
|
||||
@Test
|
||||
void consoleMessagesSinceNavigationFilterShouldWork() {
|
||||
page.evaluate("() => console.log('before navigation')");
|
||||
page.navigate(server.EMPTY_PAGE);
|
||||
page.evaluate("() => console.log('after navigation')");
|
||||
|
||||
List<ConsoleMessage> all = page.consoleMessages(
|
||||
new Page.ConsoleMessagesOptions().setFilter(ConsoleMessagesFilter.ALL));
|
||||
assertTrue(all.stream().anyMatch(m -> "before navigation".equals(m.text())));
|
||||
assertTrue(all.stream().anyMatch(m -> "after navigation".equals(m.text())));
|
||||
|
||||
// sinceNavigation is the default
|
||||
List<ConsoleMessage> sinceNav = page.consoleMessages();
|
||||
assertFalse(sinceNav.stream().anyMatch(m -> "before navigation".equals(m.text())));
|
||||
assertTrue(sinceNav.stream().anyMatch(m -> "after navigation".equals(m.text())));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ package com.microsoft.playwright;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
@@ -44,4 +43,28 @@ public class TestPageEventPageError extends TestBase {
|
||||
assertTrue(error.startsWith("Error: error" + (201 + i)), error);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void clearPageErrorsShouldWork() {
|
||||
page.navigate(server.EMPTY_PAGE);
|
||||
page.evaluate("async () => {\n" +
|
||||
" window.setTimeout(() => { throw new Error('error1'); }, 0);\n" +
|
||||
" await new Promise(f => window.setTimeout(f, 100));\n" +
|
||||
"}");
|
||||
|
||||
List<String> errors = page.pageErrors();
|
||||
assertTrue(errors.stream().anyMatch(e -> e.contains("error1")));
|
||||
|
||||
page.clearPageErrors();
|
||||
errors = page.pageErrors();
|
||||
assertEquals(0, errors.size());
|
||||
|
||||
page.evaluate("async () => {\n" +
|
||||
" window.setTimeout(() => { throw new Error('error2'); }, 0);\n" +
|
||||
" await new Promise(f => window.setTimeout(f, 100));\n" +
|
||||
"}");
|
||||
errors = page.pageErrors();
|
||||
assertEquals(1, errors.size());
|
||||
assertTrue(errors.get(0).contains("error2"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.microsoft.playwright;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.Assumptions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -107,6 +108,8 @@ public class TestPopup extends TestBase {
|
||||
|
||||
@Test
|
||||
void shouldInheritTouchSupportFromBrowserContext() {
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=2014330
|
||||
Assumptions.assumeFalse(isFirefox() && Integer.parseInt(browser.version().split("\\.")[0]) >= 148);
|
||||
BrowserContext context = browser.newContext(new Browser.NewContextOptions()
|
||||
.setViewportSize(400, 500)
|
||||
.setHasTouch(true));
|
||||
|
||||
@@ -58,32 +58,6 @@ public class TestScreencast extends TestBase {
|
||||
assertTrue(Files.exists(saveAsPath));
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveAsShouldThrowWhenNoVideoFrames(@TempDir Path videosDir) {
|
||||
try (BrowserContext context = browser.newContext(
|
||||
new Browser.NewContextOptions()
|
||||
.setRecordVideoDir(videosDir)
|
||||
.setRecordVideoSize(320, 240)
|
||||
.setViewportSize(320, 240))) {
|
||||
|
||||
Page page = context.newPage();
|
||||
Page popup = context.waitForPage(() -> {
|
||||
page.evaluate("() => {\n" +
|
||||
" const win = window.open('about:blank');\n" +
|
||||
" win.close();\n" +
|
||||
"}");
|
||||
});
|
||||
page.close();
|
||||
|
||||
Path saveAsPath = videosDir.resolve("my-video.webm");
|
||||
if (!popup.isClosed()) {
|
||||
popup.waitForClose(() -> {});
|
||||
}
|
||||
PlaywrightException e = assertThrows(PlaywrightException.class, () -> popup.video().saveAs(saveAsPath));
|
||||
assertTrue(e.getMessage().contains("Page did not produce any video frames"), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldDeleteVideo(@TempDir Path videosDir) {
|
||||
try (BrowserContext context = browser.newContext(
|
||||
@@ -123,16 +97,4 @@ public class TestScreencast extends TestBase {
|
||||
assertTrue(Files.size(files.get(0)) > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldErrorIfPageNotClosedBeforeSaveAs(@TempDir Path tmpDir) {
|
||||
try (Page page = browser.newPage(new Browser.NewPageOptions().setRecordVideoDir(tmpDir))) {
|
||||
page.navigate(server.PREFIX + "/grid.html");
|
||||
Path outPath = tmpDir.resolve("some-video.webm");
|
||||
Video video = page.video();
|
||||
PlaywrightException exception = assertThrows(PlaywrightException.class, () -> video.saveAs(outPath));
|
||||
assertTrue(
|
||||
exception.getMessage().contains("Page is not yet closed. Close the page prior to calling saveAs"),
|
||||
exception.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.microsoft.playwright;
|
||||
|
||||
import com.microsoft.playwright.options.Size;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
@@ -23,7 +24,7 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static com.microsoft.playwright.Utils.relativePathOrSkipTest;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class TestVideo extends TestBase {
|
||||
@Test
|
||||
@@ -37,4 +38,50 @@ public class TestVideo extends TestBase {
|
||||
assertTrue(videoPath.isAbsolute(), "videosPath = " + videoPath);
|
||||
assertTrue(Files.exists(videoPath), "videosPath = " + videoPath);
|
||||
}
|
||||
|
||||
@Test
|
||||
void videoStartShouldFailWhenRecordVideoIsSet(@TempDir Path tmpDir) {
|
||||
BrowserContext ctx = browser.newContext(new Browser.NewContextOptions()
|
||||
.setRecordVideoSize(320, 240).setRecordVideoDir(tmpDir));
|
||||
Page pg = ctx.newPage();
|
||||
try {
|
||||
PlaywrightException e = assertThrows(PlaywrightException.class,
|
||||
() -> pg.video().start());
|
||||
assertTrue(e.getMessage().contains("Video is already being recorded"), e.getMessage());
|
||||
// stop should still work
|
||||
pg.video().stop();
|
||||
} finally {
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void videoStopShouldFailWhenNoRecordingIsInProgress() {
|
||||
BrowserContext ctx = browser.newContext();
|
||||
Page pg = ctx.newPage();
|
||||
try {
|
||||
PlaywrightException e = assertThrows(PlaywrightException.class,
|
||||
() -> pg.video().stop());
|
||||
assertTrue(e.getMessage().contains("Video is not being recorded"), e.getMessage());
|
||||
} finally {
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void videoStartAndStopShouldProduceVideoFile(@TempDir Path tmpDir) throws Exception {
|
||||
BrowserContext ctx = browser.newContext(new Browser.NewContextOptions()
|
||||
.setViewportSize(800, 800));
|
||||
Page pg = ctx.newPage();
|
||||
try {
|
||||
Size size = new Size(800, 800);
|
||||
pg.video().start(new Video.StartOptions().setSize(size));
|
||||
pg.video().stop();
|
||||
Path videoPath = pg.video().path();
|
||||
assertNotNull(videoPath);
|
||||
assertTrue(Files.exists(videoPath), "video file should exist: " + videoPath);
|
||||
} finally {
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
1.58.0
|
||||
1.59.0-alpha-1774287265000
|
||||
|
||||
+11
-3
@@ -6,15 +6,23 @@ set +x
|
||||
trap "cd $(pwd -P)" EXIT
|
||||
cd "$(dirname $0)"
|
||||
|
||||
if [ "$#" -ne 1 ]; then
|
||||
if [ "$#" -gt 1 ]; then
|
||||
echo ""
|
||||
echo "Usage: scripts/roll_driver.sh [new version]"
|
||||
echo "Usage: scripts/roll_driver.sh [next|beta|<version>]"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
NEW_VERSION=$1
|
||||
ARG=${1:-next}
|
||||
if [[ "$ARG" == "next" ]]; then
|
||||
NEW_VERSION=$(npm view playwright@next version)
|
||||
elif [[ "$ARG" == "beta" ]]; then
|
||||
NEW_VERSION=$(npm view playwright@beta version)
|
||||
else
|
||||
NEW_VERSION=$ARG
|
||||
fi
|
||||
CURRENT_VERSION=$(head -1 ./DRIVER_VERSION)
|
||||
echo "Rolling driver from $CURRENT_VERSION to $NEW_VERSION"
|
||||
|
||||
if [[ "$CURRENT_VERSION" == "$NEW_VERSION" ]]; then
|
||||
echo "Current version is up to date. Skipping driver download.";
|
||||
|
||||
@@ -500,6 +500,9 @@ class TypeRef extends Element {
|
||||
if ("Buffer".equals(name)) {
|
||||
return "byte[]";
|
||||
}
|
||||
if ("Disposable".equals(name)) {
|
||||
return "AutoCloseable";
|
||||
}
|
||||
if ("URL".equals(name)) {
|
||||
return "String";
|
||||
}
|
||||
@@ -639,7 +642,7 @@ class Event extends Element {
|
||||
writeJavadoc(output, offset, comment());
|
||||
String name = toTitle(jsonName);
|
||||
String paramType = type.toJava();
|
||||
String listenerType = "Consumer<" + paramType + ">";
|
||||
String listenerType = "void".equals(paramType) ? "Runnable" : "Consumer<" + paramType + ">";
|
||||
output.add(offset + "void on" + name + "(" + listenerType + " handler);");
|
||||
writeJavadoc(output, offset, "Removes handler that was previously added with {@link #on" + name + " on" + name + "(handler)}.");
|
||||
output.add(offset + "void off" + name + "(" + listenerType + " handler);");
|
||||
@@ -986,7 +989,7 @@ class Interface extends TypeDefinition {
|
||||
if (methods.stream().anyMatch(m -> "create".equals(m.jsonName))) {
|
||||
output.add("import com.microsoft.playwright.impl." + jsonName + "Impl;");
|
||||
}
|
||||
if (asList("Page", "Request", "Response", "APIRequestContext", "APIRequest", "APIResponse", "FileChooser", "Frame", "FrameLocator", "ElementHandle", "Locator", "Browser", "BrowserContext", "BrowserType", "Mouse", "Keyboard", "Tracing").contains(jsonName)) {
|
||||
if (asList("Page", "Request", "Response", "APIRequestContext", "APIRequest", "APIResponse", "FileChooser", "Frame", "FrameLocator", "ElementHandle", "Locator", "Browser", "BrowserContext", "BrowserType", "Mouse", "Keyboard", "Tracing", "Video", "Debugger").contains(jsonName)) {
|
||||
output.add("import com.microsoft.playwright.options.*;");
|
||||
}
|
||||
if ("Download".equals(jsonName)) {
|
||||
@@ -998,7 +1001,7 @@ class Interface extends TypeDefinition {
|
||||
if ("Clock".equals(jsonName)) {
|
||||
output.add("import java.util.Date;");
|
||||
}
|
||||
if (asList("Page", "Frame", "ElementHandle", "Locator", "LocatorAssertions", "APIRequest", "Browser", "BrowserContext", "BrowserType", "Route", "Request", "Response", "JSHandle", "ConsoleMessage", "APIResponse", "Playwright").contains(jsonName)) {
|
||||
if (asList("Page", "Frame", "ElementHandle", "Locator", "LocatorAssertions", "APIRequest", "Browser", "BrowserContext", "BrowserType", "Route", "Request", "Response", "JSHandle", "ConsoleMessage", "APIResponse", "Playwright", "Debugger").contains(jsonName)) {
|
||||
output.add("import java.util.*;");
|
||||
}
|
||||
if (asList("WebSocketRoute").contains(jsonName)) {
|
||||
|
||||
Reference in New Issue
Block a user