Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 80fa0c6e98 | |||
| 3d9dc8429c | |||
| 4762ad9768 | |||
| 0fb77bbc81 | |||
| c4b27febd4 | |||
| a478acf6b2 | |||
| da36841809 | |||
| 8dfb745da9 | |||
| e81b874bbb |
@@ -11,9 +11,9 @@ Playwright is a Java library to automate [Chromium](https://www.chromium.org/Hom
|
||||
|
||||
| | Linux | macOS | Windows |
|
||||
| :--- | :---: | :---: | :---: |
|
||||
| Chromium <!-- GEN:chromium-version -->110.0.5481.38<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| Chromium <!-- GEN:chromium-version -->111.0.5563.19<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| WebKit <!-- GEN:webkit-version -->16.4<!-- GEN:stop --> | ✅ | ✅ | ✅ |
|
||||
| Firefox <!-- GEN:firefox-version -->108.0.2<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| Firefox <!-- GEN:firefox-version -->109.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
|
||||
Headless execution is supported for all the browsers on all platforms. Check out [system requirements](https://playwright.dev/java/docs/next/intro/#system-requirements) for details.
|
||||
|
||||
|
||||
+1
-20
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.microsoft.playwright</groupId>
|
||||
<artifactId>parent-pom</artifactId>
|
||||
<version>1.30.0-SNAPSHOT</version>
|
||||
<version>1.31.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>driver-bundle</artifactId>
|
||||
@@ -16,25 +16,6 @@
|
||||
It is intended to be used on the systems where Playwright driver is not preinstalled.
|
||||
</description>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludeResources>true</excludeResources>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.microsoft.playwright</groupId>
|
||||
|
||||
+1
-17
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.microsoft.playwright</groupId>
|
||||
<artifactId>parent-pom</artifactId>
|
||||
<version>1.30.0-SNAPSHOT</version>
|
||||
<version>1.31.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>driver</artifactId>
|
||||
@@ -15,22 +15,6 @@
|
||||
This module provides API for discovery and launching of Playwright driver.
|
||||
</description>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>org.example</groupId>
|
||||
<artifactId>examples</artifactId>
|
||||
<version>1.30.0-SNAPSHOT</version>
|
||||
<version>1.31.0</version>
|
||||
<name>Playwright Client Examples</name>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
@@ -15,7 +15,7 @@
|
||||
<dependency>
|
||||
<groupId>com.microsoft.playwright</groupId>
|
||||
<artifactId>playwright</artifactId>
|
||||
<version>1.22.0</version>
|
||||
<version>1.30.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
|
||||
+2
-14
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.microsoft.playwright</groupId>
|
||||
<artifactId>parent-pom</artifactId>
|
||||
<version>1.30.0-SNAPSHOT</version>
|
||||
<version>1.31.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>playwright</artifactId>
|
||||
@@ -21,26 +21,14 @@
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<configuration>
|
||||
<configuration combine.self="append">
|
||||
<subpackages>com.microsoft.playwright</subpackages>
|
||||
<excludePackageNames>com.microsoft.playwright.impl</excludePackageNames>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
|
||||
@@ -227,8 +227,11 @@ public interface Browser extends AutoCloseable {
|
||||
*/
|
||||
public String userAgent;
|
||||
/**
|
||||
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. {@code null} disables the default
|
||||
* viewport.
|
||||
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. Use {@code null} to disable the consistent
|
||||
* viewport emulation.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> The {@code null} value opts out from the default presets, makes viewport depend on the host window size defined by the
|
||||
* operating system. It makes the execution of the tests non-deterministic.
|
||||
*/
|
||||
public Optional<ViewportSize> viewportSize;
|
||||
|
||||
@@ -536,15 +539,21 @@ public interface Browser extends AutoCloseable {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. {@code null} disables the default
|
||||
* viewport.
|
||||
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. Use {@code null} to disable the consistent
|
||||
* viewport emulation.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> The {@code null} value opts out from the default presets, makes viewport depend on the host window size defined by the
|
||||
* operating system. It makes the execution of the tests non-deterministic.
|
||||
*/
|
||||
public NewContextOptions setViewportSize(int width, int height) {
|
||||
return setViewportSize(new ViewportSize(width, height));
|
||||
}
|
||||
/**
|
||||
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. {@code null} disables the default
|
||||
* viewport.
|
||||
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. Use {@code null} to disable the consistent
|
||||
* viewport emulation.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> The {@code null} value opts out from the default presets, makes viewport depend on the host window size defined by the
|
||||
* operating system. It makes the execution of the tests non-deterministic.
|
||||
*/
|
||||
public NewContextOptions setViewportSize(ViewportSize viewportSize) {
|
||||
this.viewportSize = Optional.ofNullable(viewportSize);
|
||||
@@ -722,8 +731,11 @@ public interface Browser extends AutoCloseable {
|
||||
*/
|
||||
public String userAgent;
|
||||
/**
|
||||
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. {@code null} disables the default
|
||||
* viewport.
|
||||
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. Use {@code null} to disable the consistent
|
||||
* viewport emulation.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> The {@code null} value opts out from the default presets, makes viewport depend on the host window size defined by the
|
||||
* operating system. It makes the execution of the tests non-deterministic.
|
||||
*/
|
||||
public Optional<ViewportSize> viewportSize;
|
||||
|
||||
@@ -1031,15 +1043,21 @@ public interface Browser extends AutoCloseable {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. {@code null} disables the default
|
||||
* viewport.
|
||||
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. Use {@code null} to disable the consistent
|
||||
* viewport emulation.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> The {@code null} value opts out from the default presets, makes viewport depend on the host window size defined by the
|
||||
* operating system. It makes the execution of the tests non-deterministic.
|
||||
*/
|
||||
public NewPageOptions setViewportSize(int width, int height) {
|
||||
return setViewportSize(new ViewportSize(width, height));
|
||||
}
|
||||
/**
|
||||
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. {@code null} disables the default
|
||||
* viewport.
|
||||
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. Use {@code null} to disable the consistent
|
||||
* viewport emulation.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> The {@code null} value opts out from the default presets, makes viewport depend on the host window size defined by the
|
||||
* operating system. It makes the execution of the tests non-deterministic.
|
||||
*/
|
||||
public NewPageOptions setViewportSize(ViewportSize viewportSize) {
|
||||
this.viewportSize = Optional.ofNullable(viewportSize);
|
||||
|
||||
@@ -601,8 +601,11 @@ public interface BrowserType {
|
||||
*/
|
||||
public String userAgent;
|
||||
/**
|
||||
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. {@code null} disables the default
|
||||
* viewport.
|
||||
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. Use {@code null} to disable the consistent
|
||||
* viewport emulation.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> The {@code null} value opts out from the default presets, makes viewport depend on the host window size defined by the
|
||||
* operating system. It makes the execution of the tests non-deterministic.
|
||||
*/
|
||||
public Optional<ViewportSize> viewportSize;
|
||||
|
||||
@@ -1021,15 +1024,21 @@ public interface BrowserType {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. {@code null} disables the default
|
||||
* viewport.
|
||||
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. Use {@code null} to disable the consistent
|
||||
* viewport emulation.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> The {@code null} value opts out from the default presets, makes viewport depend on the host window size defined by the
|
||||
* operating system. It makes the execution of the tests non-deterministic.
|
||||
*/
|
||||
public LaunchPersistentContextOptions setViewportSize(int width, int height) {
|
||||
return setViewportSize(new ViewportSize(width, height));
|
||||
}
|
||||
/**
|
||||
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. {@code null} disables the default
|
||||
* viewport.
|
||||
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. Use {@code null} to disable the consistent
|
||||
* viewport emulation.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> The {@code null} value opts out from the default presets, makes viewport depend on the host window size defined by the
|
||||
* operating system. It makes the execution of the tests non-deterministic.
|
||||
*/
|
||||
public LaunchPersistentContextOptions setViewportSize(ViewportSize viewportSize) {
|
||||
this.viewportSize = Optional.ofNullable(viewportSize);
|
||||
|
||||
@@ -2283,7 +2283,7 @@ public interface Locator {
|
||||
*/
|
||||
void dblclick(DblclickOptions options);
|
||||
/**
|
||||
* Programmaticaly dispatch an event on the matching element.
|
||||
* Programmatically dispatch an event on the matching element.
|
||||
*
|
||||
* <p> **Usage**
|
||||
* <pre>{@code
|
||||
@@ -2328,7 +2328,7 @@ public interface Locator {
|
||||
dispatchEvent(type, eventInit, null);
|
||||
}
|
||||
/**
|
||||
* Programmaticaly dispatch an event on the matching element.
|
||||
* Programmatically dispatch an event on the matching element.
|
||||
*
|
||||
* <p> **Usage**
|
||||
* <pre>{@code
|
||||
@@ -2372,7 +2372,7 @@ public interface Locator {
|
||||
dispatchEvent(type, null);
|
||||
}
|
||||
/**
|
||||
* Programmaticaly dispatch an event on the matching element.
|
||||
* Programmatically dispatch an event on the matching element.
|
||||
*
|
||||
* <p> **Usage**
|
||||
* <pre>{@code
|
||||
@@ -3717,7 +3717,7 @@ public interface Locator {
|
||||
*/
|
||||
Page page();
|
||||
/**
|
||||
* Focuses the mathing element and presses a combintation of the keys.
|
||||
* Focuses the matching element and presses a combination of the keys.
|
||||
*
|
||||
* <p> **Usage**
|
||||
* <pre>{@code
|
||||
@@ -3756,7 +3756,7 @@ public interface Locator {
|
||||
press(key, null);
|
||||
}
|
||||
/**
|
||||
* Focuses the mathing element and presses a combintation of the keys.
|
||||
* Focuses the matching element and presses a combination of the keys.
|
||||
*
|
||||
* <p> **Usage**
|
||||
* <pre>{@code
|
||||
|
||||
@@ -5441,6 +5441,45 @@ public interface Page extends AutoCloseable {
|
||||
* @since v1.8
|
||||
*/
|
||||
Mouse mouse();
|
||||
/**
|
||||
* Adds one-off {@code Dialog} handler. The handler will be removed immediately after next {@code Dialog} is created.
|
||||
* <pre>{@code
|
||||
* page.onceDialog(dialog -> {
|
||||
* dialog.accept("foo");
|
||||
* });
|
||||
*
|
||||
* // prints 'foo'
|
||||
* System.out.println(page.evaluate("prompt('Enter string:')"));
|
||||
*
|
||||
* // prints 'null' as the dialog will be auto-dismissed because there are no handlers.
|
||||
* System.out.println(page.evaluate("prompt('Enter string:')"));
|
||||
* }</pre>
|
||||
*
|
||||
* <p> This code above is equivalent to:
|
||||
* <pre>{@code
|
||||
* Consumer<Dialog> handler = new Consumer<Dialog>() {
|
||||
* @Override
|
||||
* public void accept(Dialog dialog) {
|
||||
* dialog.accept("foo");
|
||||
* page.offDialog(this);
|
||||
* }
|
||||
* };
|
||||
* page.onDialog(handler);
|
||||
*
|
||||
* // prints 'foo'
|
||||
* System.out.println(page.evaluate("prompt('Enter string:')"));
|
||||
*
|
||||
* // prints 'null' as the dialog will be auto-dismissed because there are no handlers.
|
||||
* System.out.println(page.evaluate("prompt('Enter string:')"));
|
||||
* }</pre>
|
||||
*
|
||||
* @param handler Receives the {@code Dialog} object, it **must** either {@link Dialog#accept Dialog.accept()} or {@link Dialog#dismiss
|
||||
* Dialog.dismiss()} the dialog - otherwise the page will <a
|
||||
* href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#never_blocking">freeze</a> waiting for the
|
||||
* dialog, and actions like click will never finish.
|
||||
* @since v1.10
|
||||
*/
|
||||
void onceDialog(Consumer<Dialog> handler);
|
||||
/**
|
||||
* Returns the opener for popup pages and {@code null} for others. If the opener has been closed already the returns {@code
|
||||
* null}.
|
||||
@@ -6727,7 +6766,7 @@ public interface Page extends AutoCloseable {
|
||||
* <p> When all steps combined have not finished during the specified {@code timeout}, this method throws a {@code
|
||||
* TimeoutError}. Passing zero timeout disables this.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> {@link Page#tap Page.tap()} requires that the {@code hasTouch} option of the browser context be set to true.
|
||||
* <p> <strong>NOTE:</strong> {@link Page#tap Page.tap()} the method will throw if {@code hasTouch} option of the browser context is false.
|
||||
*
|
||||
* @param selector A selector to search for an element. If there are multiple elements satisfying the selector, the first will be used.
|
||||
* @since v1.8
|
||||
@@ -6749,7 +6788,7 @@ public interface Page extends AutoCloseable {
|
||||
* <p> When all steps combined have not finished during the specified {@code timeout}, this method throws a {@code
|
||||
* TimeoutError}. Passing zero timeout disables this.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> {@link Page#tap Page.tap()} requires that the {@code hasTouch} option of the browser context be set to true.
|
||||
* <p> <strong>NOTE:</strong> {@link Page#tap Page.tap()} the method will throw if {@code hasTouch} option of the browser context is false.
|
||||
*
|
||||
* @param selector A selector to search for an element. If there are multiple elements satisfying the selector, the first will be used.
|
||||
* @since v1.8
|
||||
@@ -7838,44 +7877,5 @@ public interface Page extends AutoCloseable {
|
||||
* @since v1.8
|
||||
*/
|
||||
List<Worker> workers();
|
||||
/**
|
||||
* Adds one-off {@code Dialog} handler. The handler will be removed immediately after next {@code Dialog} is created.
|
||||
* <pre>{@code
|
||||
* page.onceDialog(dialog -> {
|
||||
* dialog.accept("foo");
|
||||
* });
|
||||
*
|
||||
* // prints 'foo'
|
||||
* System.out.println(page.evaluate("prompt('Enter string:')"));
|
||||
*
|
||||
* // prints 'null' as the dialog will be auto-dismissed because there are no handlers.
|
||||
* System.out.println(page.evaluate("prompt('Enter string:')"));
|
||||
* }</pre>
|
||||
*
|
||||
* <p> This code above is equivalent to:
|
||||
* <pre>{@code
|
||||
* Consumer<Dialog> handler = new Consumer<Dialog>() {
|
||||
* @Override
|
||||
* public void accept(Dialog dialog) {
|
||||
* dialog.accept("foo");
|
||||
* page.offDialog(this);
|
||||
* }
|
||||
* };
|
||||
* page.onDialog(handler);
|
||||
*
|
||||
* // prints 'foo'
|
||||
* System.out.println(page.evaluate("prompt('Enter string:')"));
|
||||
*
|
||||
* // prints 'null' as the dialog will be auto-dismissed because there are no handlers.
|
||||
* System.out.println(page.evaluate("prompt('Enter string:')"));
|
||||
* }</pre>
|
||||
*
|
||||
* @param handler Receives the {@code Dialog} object, it **must** either {@link Dialog#accept Dialog.accept()} or {@link Dialog#dismiss
|
||||
* Dialog.dismiss()} the dialog - otherwise the page will <a
|
||||
* href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#never_blocking">freeze</a> waiting for the
|
||||
* dialog, and actions like click will never finish.
|
||||
* @since v1.10
|
||||
*/
|
||||
void onceDialog(Consumer<Dialog> handler);
|
||||
}
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ public interface Playwright extends AutoCloseable {
|
||||
* Launches new Playwright driver process and connects to it. {@link Playwright#close Playwright.close()} should be called
|
||||
* when the instance is no longer needed.
|
||||
* <pre>{@code
|
||||
* Playwright playwright = Playwright.create()) {
|
||||
* Playwright playwright = Playwright.create();
|
||||
* Browser browser = playwright.webkit().launch();
|
||||
* Page page = browser.newPage();
|
||||
* page.navigate("https://www.w3.org/");
|
||||
|
||||
@@ -141,6 +141,11 @@ public interface Route {
|
||||
* If set changes the request HTTP headers. Header values will be converted to a string.
|
||||
*/
|
||||
public Map<String, String> headers;
|
||||
/**
|
||||
* Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is
|
||||
* exceeded. Defaults to {@code 20}. Pass {@code 0} to not follow redirects.
|
||||
*/
|
||||
public Integer maxRedirects;
|
||||
/**
|
||||
* If set changes the request method (e.g. GET or POST).
|
||||
*/
|
||||
@@ -161,6 +166,14 @@ public interface Route {
|
||||
this.headers = headers;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is
|
||||
* exceeded. Defaults to {@code 20}. Pass {@code 0} to not follow redirects.
|
||||
*/
|
||||
public FetchOptions setMaxRedirects(int maxRedirects) {
|
||||
this.maxRedirects = maxRedirects;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* If set changes the request method (e.g. GET or POST).
|
||||
*/
|
||||
@@ -321,6 +334,13 @@ public interface Route {
|
||||
* });
|
||||
* }</pre>
|
||||
*
|
||||
* <p> **Details**
|
||||
*
|
||||
* <p> Note that any overrides such as {@code url} or {@code headers} only apply to the request being routed. If this request
|
||||
* results in a redirect, overrides will not be applied to the new redirected request. If you want to propagate a header
|
||||
* through redirects, use the combination of {@link Route#fetch Route.fetch()} and {@link Route#fulfill Route.fulfill()}
|
||||
* instead.
|
||||
*
|
||||
* @since v1.8
|
||||
*/
|
||||
default void resume() {
|
||||
@@ -340,6 +360,13 @@ public interface Route {
|
||||
* });
|
||||
* }</pre>
|
||||
*
|
||||
* <p> **Details**
|
||||
*
|
||||
* <p> Note that any overrides such as {@code url} or {@code headers} only apply to the request being routed. If this request
|
||||
* results in a redirect, overrides will not be applied to the new redirected request. If you want to propagate a header
|
||||
* through redirects, use the combination of {@link Route#fetch Route.fetch()} and {@link Route#fulfill Route.fulfill()}
|
||||
* instead.
|
||||
*
|
||||
* @since v1.8
|
||||
*/
|
||||
void resume(ResumeOptions options);
|
||||
@@ -488,6 +515,12 @@ public interface Route {
|
||||
* });
|
||||
* }</pre>
|
||||
*
|
||||
* <p> **Details**
|
||||
*
|
||||
* <p> Note that {@code headers} option will apply to the fetched request as well as any redirects initiated by it. If you want
|
||||
* to only apply {@code headers} to the original request, but not to redirects, look into {@link Route#resume
|
||||
* Route.resume()} instead.
|
||||
*
|
||||
* @since v1.29
|
||||
*/
|
||||
default APIResponse fetch() {
|
||||
@@ -510,6 +543,12 @@ public interface Route {
|
||||
* });
|
||||
* }</pre>
|
||||
*
|
||||
* <p> **Details**
|
||||
*
|
||||
* <p> Note that {@code headers} option will apply to the fetched request as well as any redirects initiated by it. If you want
|
||||
* to only apply {@code headers} to the original request, but not to redirects, look into {@link Route#resume
|
||||
* Route.resume()} instead.
|
||||
*
|
||||
* @since v1.29
|
||||
*/
|
||||
APIResponse fetch(FetchOptions options);
|
||||
|
||||
@@ -42,7 +42,9 @@ public interface Selectors {
|
||||
}
|
||||
}
|
||||
/**
|
||||
* **Usage**
|
||||
* Selectors must be registered before creating the page.
|
||||
*
|
||||
* <p> **Usage**
|
||||
*
|
||||
* <p> An example of registering selector engine that queries elements based on a tag name:
|
||||
* <pre>{@code
|
||||
@@ -64,8 +66,8 @@ public interface Selectors {
|
||||
* page.setContent("<div><button>Click me</button></div>");
|
||||
* // Use the selector prefixed with its name.
|
||||
* Locator button = page.locator("tag=button");
|
||||
* // Combine it with other selector engines.
|
||||
* page.locator("tag=div >> text=\"Click me\"").click();
|
||||
* // Combine it with built-in locators.
|
||||
* page.locator("tag=div").getByText("Click me").click();
|
||||
* // Can use it in any methods supporting selectors.
|
||||
* int buttonCount = (int) page.locator("tag=button").count();
|
||||
* browser.close();
|
||||
@@ -80,7 +82,9 @@ public interface Selectors {
|
||||
register(name, script, null);
|
||||
}
|
||||
/**
|
||||
* **Usage**
|
||||
* Selectors must be registered before creating the page.
|
||||
*
|
||||
* <p> **Usage**
|
||||
*
|
||||
* <p> An example of registering selector engine that queries elements based on a tag name:
|
||||
* <pre>{@code
|
||||
@@ -102,8 +106,8 @@ public interface Selectors {
|
||||
* page.setContent("<div><button>Click me</button></div>");
|
||||
* // Use the selector prefixed with its name.
|
||||
* Locator button = page.locator("tag=button");
|
||||
* // Combine it with other selector engines.
|
||||
* page.locator("tag=div >> text=\"Click me\"").click();
|
||||
* // Combine it with built-in locators.
|
||||
* page.locator("tag=div").getByText("Click me").click();
|
||||
* // Can use it in any methods supporting selectors.
|
||||
* int buttonCount = (int) page.locator("tag=button").count();
|
||||
* browser.close();
|
||||
@@ -116,7 +120,9 @@ public interface Selectors {
|
||||
*/
|
||||
void register(String name, String script, RegisterOptions options);
|
||||
/**
|
||||
* **Usage**
|
||||
* Selectors must be registered before creating the page.
|
||||
*
|
||||
* <p> **Usage**
|
||||
*
|
||||
* <p> An example of registering selector engine that queries elements based on a tag name:
|
||||
* <pre>{@code
|
||||
@@ -138,8 +144,8 @@ public interface Selectors {
|
||||
* page.setContent("<div><button>Click me</button></div>");
|
||||
* // Use the selector prefixed with its name.
|
||||
* Locator button = page.locator("tag=button");
|
||||
* // Combine it with other selector engines.
|
||||
* page.locator("tag=div >> text=\"Click me\"").click();
|
||||
* // Combine it with built-in locators.
|
||||
* page.locator("tag=div").getByText("Click me").click();
|
||||
* // Can use it in any methods supporting selectors.
|
||||
* int buttonCount = (int) page.locator("tag=button").count();
|
||||
* browser.close();
|
||||
@@ -154,7 +160,9 @@ public interface Selectors {
|
||||
register(name, script, null);
|
||||
}
|
||||
/**
|
||||
* **Usage**
|
||||
* Selectors must be registered before creating the page.
|
||||
*
|
||||
* <p> **Usage**
|
||||
*
|
||||
* <p> An example of registering selector engine that queries elements based on a tag name:
|
||||
* <pre>{@code
|
||||
@@ -176,8 +184,8 @@ public interface Selectors {
|
||||
* page.setContent("<div><button>Click me</button></div>");
|
||||
* // Use the selector prefixed with its name.
|
||||
* Locator button = page.locator("tag=button");
|
||||
* // Combine it with other selector engines.
|
||||
* page.locator("tag=div >> text=\"Click me\"").click();
|
||||
* // Combine it with built-in locators.
|
||||
* page.locator("tag=div").getByText("Click me").click();
|
||||
* // Can use it in any methods supporting selectors.
|
||||
* int buttonCount = (int) page.locator("tag=button").count();
|
||||
* browser.close();
|
||||
|
||||
@@ -25,6 +25,8 @@ public interface Touchscreen {
|
||||
/**
|
||||
* Dispatches a {@code touchstart} and {@code touchend} event with a single touch at the position ({@code x},{@code y}).
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> {@link Page#tap Page.tap()} the method will throw if {@code hasTouch} option of the browser context is false.
|
||||
*
|
||||
* @since v1.8
|
||||
*/
|
||||
void tap(double x, double y);
|
||||
|
||||
+1
-2
@@ -19,8 +19,7 @@ package com.microsoft.playwright.assertions;
|
||||
|
||||
/**
|
||||
* The {@code APIResponseAssertions} class provides assertion methods that can be used to make assertions about the {@code
|
||||
* APIResponse} in the tests. A new instance of {@code APIResponseAssertions} is created by calling {@link
|
||||
* PlaywrightAssertions#assertThat PlaywrightAssertions.assertThat()}:
|
||||
* APIResponse} in the tests.
|
||||
* <pre>{@code
|
||||
* ...
|
||||
* import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
|
||||
|
||||
+66
-2
@@ -20,8 +20,7 @@ import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* The {@code LocatorAssertions} class provides assertion methods that can be used to make assertions about the {@code
|
||||
* Locator} state in the tests. A new instance of {@code LocatorAssertions} is created by calling {@link
|
||||
* PlaywrightAssertions#assertThat PlaywrightAssertions.assertThat()}:
|
||||
* Locator} state in the tests.
|
||||
* <pre>{@code
|
||||
* ...
|
||||
* import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
|
||||
@@ -151,6 +150,33 @@ public interface LocatorAssertions {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
class IsInViewportOptions {
|
||||
/**
|
||||
* The minimal ratio of the element to intersect viewport. If equals to {@code 0}, then element should intersect viewport
|
||||
* at any positive ratio. Defaults to {@code 0}.
|
||||
*/
|
||||
public Double ratio;
|
||||
/**
|
||||
* Time to retry the assertion for.
|
||||
*/
|
||||
public Double timeout;
|
||||
|
||||
/**
|
||||
* The minimal ratio of the element to intersect viewport. If equals to {@code 0}, then element should intersect viewport
|
||||
* at any positive ratio. Defaults to {@code 0}.
|
||||
*/
|
||||
public IsInViewportOptions setRatio(double ratio) {
|
||||
this.ratio = ratio;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Time to retry the assertion for.
|
||||
*/
|
||||
public IsInViewportOptions setTimeout(double timeout) {
|
||||
this.timeout = timeout;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
class IsVisibleOptions {
|
||||
/**
|
||||
* Time to retry the assertion for.
|
||||
@@ -548,6 +574,44 @@ public interface LocatorAssertions {
|
||||
* @since v1.20
|
||||
*/
|
||||
void isHidden(IsHiddenOptions options);
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element that intersects viewport, according to the <a
|
||||
* href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API">intersection observer API</a>.
|
||||
*
|
||||
* <p> **Usage**
|
||||
* <pre>{@code
|
||||
* Locator locator = page.getByRole(AriaRole.BUTTON);
|
||||
* // Make sure at least some part of element intersects viewport.
|
||||
* assertThat(locator).isInViewport();
|
||||
* // Make sure element is fully outside of viewport.
|
||||
* assertThat(locator).not().isInViewport();
|
||||
* // Make sure that at least half of the element intersects viewport.
|
||||
* assertThat(locator).isInViewport(new LocatorAssertions.IsInViewportOptions().setRatio(0.5));
|
||||
* }</pre>
|
||||
*
|
||||
* @since v1.31
|
||||
*/
|
||||
default void isInViewport() {
|
||||
isInViewport(null);
|
||||
}
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element that intersects viewport, according to the <a
|
||||
* href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API">intersection observer API</a>.
|
||||
*
|
||||
* <p> **Usage**
|
||||
* <pre>{@code
|
||||
* Locator locator = page.getByRole(AriaRole.BUTTON);
|
||||
* // Make sure at least some part of element intersects viewport.
|
||||
* assertThat(locator).isInViewport();
|
||||
* // Make sure element is fully outside of viewport.
|
||||
* assertThat(locator).not().isInViewport();
|
||||
* // Make sure that at least half of the element intersects viewport.
|
||||
* assertThat(locator).isInViewport(new LocatorAssertions.IsInViewportOptions().setRatio(0.5));
|
||||
* }</pre>
|
||||
*
|
||||
* @since v1.31
|
||||
*/
|
||||
void isInViewport(IsInViewportOptions options);
|
||||
/**
|
||||
* Ensures that {@code Locator} points to an <a href="https://playwright.dev/java/docs/actionability#attached">attached</a>
|
||||
* and <a href="https://playwright.dev/java/docs/actionability#visible">visible</a> DOM node.
|
||||
|
||||
@@ -20,8 +20,7 @@ import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* The {@code PageAssertions} class provides assertion methods that can be used to make assertions about the {@code Page}
|
||||
* state in the tests. A new instance of {@code PageAssertions} is created by calling {@link
|
||||
* PlaywrightAssertions#assertThat PlaywrightAssertions.assertThat()}:
|
||||
* state in the tests.
|
||||
* <pre>{@code
|
||||
* ...
|
||||
* import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
|
||||
|
||||
@@ -399,11 +399,7 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
|
||||
private void route(UrlMatcher matcher, Consumer<Route> handler, RouteOptions options) {
|
||||
withLogging("BrowserContext.route", () -> {
|
||||
routes.add(matcher, handler, options == null ? null : options.times);
|
||||
if (routes.size() == 1) {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty("enabled", true);
|
||||
sendMessage("setNetworkInterceptionEnabled", params);
|
||||
}
|
||||
updateInterceptionPatterns();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -525,22 +521,18 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
|
||||
private void unroute(UrlMatcher matcher, Consumer<Route> handler) {
|
||||
withLogging("BrowserContext.unroute", () -> {
|
||||
routes.remove(matcher, handler);
|
||||
maybeDisableNetworkInterception();
|
||||
updateInterceptionPatterns();
|
||||
});
|
||||
}
|
||||
|
||||
private void maybeDisableNetworkInterception() {
|
||||
if (routes.size() == 0) {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty("enabled", false);
|
||||
sendMessage("setNetworkInterceptionEnabled", params);
|
||||
}
|
||||
private void updateInterceptionPatterns() {
|
||||
sendMessage("setNetworkInterceptionPatterns", routes.interceptionPatterns());
|
||||
}
|
||||
|
||||
void handleRoute(RouteImpl route) {
|
||||
Router.HandleResult handled = routes.handle(route);
|
||||
if (handled != Router.HandleResult.NoMatchingHandler) {
|
||||
maybeDisableNetworkInterception();
|
||||
updateInterceptionPatterns();
|
||||
}
|
||||
if (handled == Router.HandleResult.NoMatchingHandler || handled == Router.HandleResult.Fallback) {
|
||||
route.resume();
|
||||
|
||||
@@ -148,7 +148,7 @@ public class LocatorAssertionsImpl extends AssertionsBase implements LocatorAsse
|
||||
options = new HasCountOptions();
|
||||
}
|
||||
FrameExpectOptions commonOptions = convertType(options, FrameExpectOptions.class);
|
||||
commonOptions.expectedNumber = count;
|
||||
commonOptions.expectedNumber = (double) count;
|
||||
List<ExpectedTextValue> expectedText = null;
|
||||
expectImpl("to.have.count", expectedText, count, "Locator expected to have count", commonOptions);
|
||||
}
|
||||
@@ -326,6 +326,15 @@ public class LocatorAssertionsImpl extends AssertionsBase implements LocatorAsse
|
||||
expectTrue("to.be.hidden", "Locator expected to be hidden", convertType(options, FrameExpectOptions.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void isInViewport(IsInViewportOptions options) {
|
||||
FrameExpectOptions expectOptions = convertType(options, FrameExpectOptions.class);
|
||||
if (options != null && options.ratio != null) {
|
||||
expectOptions.expectedNumber = options.ratio;
|
||||
}
|
||||
expectTrue("to.be.in.viewport", "Locator expected to be in viewport", expectOptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void isVisible(IsVisibleOptions options) {
|
||||
FrameExpectOptions frameOptions = convertType(options, FrameExpectOptions.class);
|
||||
|
||||
@@ -118,7 +118,7 @@ public class LocatorUtils {
|
||||
// cssEscape(value).replace(/\\ /g, ' ')
|
||||
// However, our attribute selectors do not conform to CSS parsing spec,
|
||||
// so we escape them differently.
|
||||
return '"' + value.replaceAll("\"", "\\\\\"") + '"' + (exact ? "" : "i");
|
||||
return '"' + value.replaceAll("\\\\", "\\\\\\\\").replaceAll("\"", "\\\\\"") + '"' + (exact ? "" : "i");
|
||||
}
|
||||
|
||||
private static String toJsRegExp(Pattern pattern) {
|
||||
|
||||
@@ -189,7 +189,7 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
RouteImpl route = connection.getExistingObject(params.getAsJsonObject("route").get("guid").getAsString());
|
||||
Router.HandleResult handled = routes.handle(route);
|
||||
if (handled != Router.HandleResult.NoMatchingHandler) {
|
||||
maybeDisableNetworkInterception();
|
||||
updateInterceptionPatterns();
|
||||
}
|
||||
if (handled == Router.HandleResult.NoMatchingHandler || handled == Router.HandleResult.Fallback) {
|
||||
browserContext.handleRoute(route);
|
||||
@@ -949,8 +949,8 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
|
||||
@Override
|
||||
public void pause() {
|
||||
withLogging("BrowserContext.pause", () -> {
|
||||
new WaitableRace<>(asList(context().pause(), (Waitable<JsonElement>) waitableClosedOrCrashed)).get();
|
||||
withLogging("Page.pause", () -> {
|
||||
runUntil(() -> {}, new WaitableRace<>(asList(context().pause(), (Waitable<JsonElement>) waitableClosedOrCrashed)));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1037,11 +1037,7 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
private void route(UrlMatcher matcher, Consumer<Route> handler, RouteOptions options) {
|
||||
withLogging("Page.route", () -> {
|
||||
routes.add(matcher, handler, options == null ? null : options.times);
|
||||
if (routes.size() == 1) {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty("enabled", true);
|
||||
sendMessage("setNetworkInterceptionEnabled", params);
|
||||
}
|
||||
updateInterceptionPatterns();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1256,16 +1252,12 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
private void unroute(UrlMatcher matcher, Consumer<Route> handler) {
|
||||
withLogging("Page.unroute", () -> {
|
||||
routes.remove(matcher, handler);
|
||||
maybeDisableNetworkInterception();
|
||||
updateInterceptionPatterns();
|
||||
});
|
||||
}
|
||||
|
||||
private void maybeDisableNetworkInterception() {
|
||||
if (routes.size() == 0) {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty("enabled", false);
|
||||
sendMessage("setNetworkInterceptionEnabled", params);
|
||||
}
|
||||
private void updateInterceptionPatterns() {
|
||||
sendMessage("setNetworkInterceptionPatterns", routes.interceptionPatterns());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -94,7 +94,7 @@ class ExpectedTextValue {
|
||||
class FrameExpectOptions {
|
||||
Object expressionArg;
|
||||
List<ExpectedTextValue> expectedText;
|
||||
Integer expectedNumber;
|
||||
Double expectedNumber;
|
||||
SerializedArgument expectedValue;
|
||||
Boolean useInnerText;
|
||||
boolean isNot;
|
||||
|
||||
@@ -16,14 +16,19 @@
|
||||
|
||||
package com.microsoft.playwright.impl;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.microsoft.playwright.Route;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.microsoft.playwright.impl.Utils.toJsRegexFlags;
|
||||
|
||||
class Router {
|
||||
private List<RouteInfo> routes = new ArrayList<>();
|
||||
|
||||
@@ -92,4 +97,29 @@ class Router {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
JsonObject interceptionPatterns() {
|
||||
JsonArray jsonPatterns = new JsonArray();
|
||||
for (RouteInfo route : routes) {
|
||||
JsonObject jsonPattern = new JsonObject();
|
||||
Object urlFilter = route.matcher.rawSource;
|
||||
if (urlFilter instanceof String) {
|
||||
jsonPattern.addProperty("glob", (String) urlFilter);
|
||||
} else if (urlFilter instanceof Pattern) {
|
||||
Pattern pattern = (Pattern) urlFilter;
|
||||
jsonPattern.addProperty("regexSource", pattern.pattern());
|
||||
jsonPattern.addProperty("regexFlags", toJsRegexFlags(pattern));
|
||||
} else {
|
||||
// Match all requests.
|
||||
jsonPattern.addProperty("glob", "**/*");
|
||||
jsonPatterns = new JsonArray();
|
||||
jsonPatterns.add(jsonPattern);
|
||||
break;
|
||||
}
|
||||
jsonPatterns.add(jsonPattern);
|
||||
}
|
||||
JsonObject result = new JsonObject();
|
||||
result.add("patterns", jsonPatterns);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ import java.util.regex.Pattern;
|
||||
import static com.microsoft.playwright.impl.Utils.globToRegex;
|
||||
|
||||
class UrlMatcher {
|
||||
private final Object rawSource;
|
||||
final Object rawSource;
|
||||
private final Predicate<String> predicate;
|
||||
|
||||
private static Predicate<String> toPredicate(Pattern pattern) {
|
||||
|
||||
@@ -110,7 +110,8 @@ public interface RequestOptions {
|
||||
*/
|
||||
RequestOptions setForm(FormData form);
|
||||
/**
|
||||
* Sets an HTTP header to the request.
|
||||
* Sets an HTTP header to the request. This header will apply to the fetched request as well as any redirects initiated by
|
||||
* it.
|
||||
*
|
||||
* @param name Header name.
|
||||
* @param value Header value.
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.microsoft.playwright;
|
||||
|
||||
import com.microsoft.playwright.assertions.LocatorAssertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.opentest4j.AssertionFailedError;
|
||||
|
||||
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
// Copied from expect-misc.spec.ts > toBeInViewport
|
||||
public class TestAssertThatIsInViewport extends TestBase {
|
||||
@Test
|
||||
void shouldWork() {
|
||||
page.setContent("<div id=big style=\"height: 10000px;\"></div>\n" +
|
||||
" <div id=small>foo</div>");
|
||||
assertThat(page.locator("#big")).isInViewport();
|
||||
assertThat(page.locator("#small")).not().isInViewport();
|
||||
page.locator("#small").scrollIntoViewIfNeeded();
|
||||
assertThat(page.locator("#small")).isInViewport();
|
||||
assertThat(page.locator("#small")).isInViewport(new LocatorAssertions.IsInViewportOptions().setRatio(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRespectRatioOption() {
|
||||
page.setContent("<style>body, div, html { padding: 0; margin: 0; }</style>\n" +
|
||||
" <div id=big style=\"height: 400vh;\"></div>");
|
||||
assertThat(page.locator("div")).isInViewport();
|
||||
assertThat(page.locator("div")).isInViewport(new LocatorAssertions.IsInViewportOptions().setRatio(0.1));
|
||||
assertThat(page.locator("div")).isInViewport(new LocatorAssertions.IsInViewportOptions().setRatio(0.2));
|
||||
|
||||
assertThat(page.locator("div")).isInViewport(new LocatorAssertions.IsInViewportOptions().setRatio(0.24));
|
||||
// In this test, element's ratio is 0.25.
|
||||
assertThat(page.locator("div")).isInViewport(new LocatorAssertions.IsInViewportOptions().setRatio(0.25));
|
||||
assertThat(page.locator("div")).not().isInViewport(new LocatorAssertions.IsInViewportOptions().setRatio(0.26));
|
||||
|
||||
assertThat(page.locator("div")).not().isInViewport(new LocatorAssertions.IsInViewportOptions().setRatio(0.3));
|
||||
assertThat(page.locator("div")).not().isInViewport(new LocatorAssertions.IsInViewportOptions().setRatio(0.7));
|
||||
assertThat(page.locator("div")).not().isInViewport(new LocatorAssertions.IsInViewportOptions().setRatio(0.8));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHaveGoodStack() {
|
||||
AssertionFailedError error = assertThrows(AssertionFailedError.class, () -> assertThat(page.locator("body")).not().isInViewport(new LocatorAssertions.IsInViewportOptions().setTimeout(100)));
|
||||
assertNotNull(error);
|
||||
assertTrue(error.getMessage().contains("Locator expected not to be in viewport"), error.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReportIntersectionEvenIfFullyCoveredByOtherElement() {
|
||||
page.setContent("<h1>hello</h1>\n" +
|
||||
" <div style=\"position: relative; height: 10000px; top: -5000px;></div>");
|
||||
assertThat(page.locator("h1")).isInViewport();
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.microsoft.playwright;
|
||||
|
||||
import com.microsoft.playwright.options.AriaRole;
|
||||
import com.microsoft.playwright.options.WaitUntilState;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledIf;
|
||||
import org.junit.jupiter.api.condition.EnabledIf;
|
||||
|
||||
@@ -92,4 +92,17 @@ public class TestPageInterception extends TestBase {
|
||||
page.navigate(server.PREFIX + "/empty.html");
|
||||
assertEquals("{ \"foo\": \"bar\" }", new String(request.get().postBody));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotFollowRedirectsWhenMaxRedirectsIsSetTo0InRouteFetch() {
|
||||
server.setRedirect("/foo", "/empty.html");
|
||||
page.route("**/*", route -> {
|
||||
APIResponse response = route.fetch(new Route.FetchOptions().setMaxRedirects(0));
|
||||
assertEquals("/empty.html", response.headers().get("location"));
|
||||
assertEquals(302, response.status());
|
||||
route.fulfill(new Route.FulfillOptions().setBody("hello"));
|
||||
});
|
||||
page.navigate(server.PREFIX + "/foo");
|
||||
assertTrue(page.content().contains("hello"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,11 +19,12 @@ package com.microsoft.playwright;
|
||||
import com.microsoft.playwright.options.HttpHeader;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class TestPageNetworkResponse extends TestBase {
|
||||
@Test
|
||||
@@ -45,4 +46,51 @@ public class TestPageNetworkResponse extends TestBase {
|
||||
assertEquals(asList("a=b", "c=d"), response.headerValues("set-cookie"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRejectResponseFinishedIfPageCloses() {
|
||||
page.navigate(server.EMPTY_PAGE);
|
||||
server.setRoute("/get", exchange -> {
|
||||
// In Firefox, |fetch| will be hanging until it receives |Content-Type| header
|
||||
// from server.
|
||||
exchange.getResponseHeaders().add("Content-Type", "text/plain; charset=utf-8");
|
||||
exchange.sendResponseHeaders(200, 0);
|
||||
OutputStreamWriter writer = new OutputStreamWriter(exchange.getResponseBody());
|
||||
writer.write("hello ");
|
||||
});
|
||||
|
||||
// send request and wait for server response
|
||||
Response pageResponse = page.waitForResponse("**/get", () -> {
|
||||
page.evaluate("() => fetch('./get', { method: 'GET' })");
|
||||
});
|
||||
// In 1s send a request which will trigger a request event while pageResponse.finished() is still
|
||||
// on the callstack.
|
||||
page.onRequest(request -> page.close());
|
||||
page.evaluate("() => setTimeout(() => fetch('./empty.html', { method: 'GET' }), 1000)");
|
||||
PlaywrightException e = assertThrows(PlaywrightException.class, () -> pageResponse.finished());
|
||||
assertTrue(e.getMessage().contains("closed"), e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRejectResponseFinishedIfContextCloses() {
|
||||
page.navigate(server.EMPTY_PAGE);
|
||||
server.setRoute("/get", exchange -> {
|
||||
// In Firefox, |fetch| will be hanging until it receives |Content-Type| header
|
||||
// from server.
|
||||
exchange.getResponseHeaders().add("Content-Type", "text/plain; charset=utf-8");
|
||||
exchange.sendResponseHeaders(200, 0);
|
||||
OutputStreamWriter writer = new OutputStreamWriter(exchange.getResponseBody());
|
||||
writer.write("hello ");
|
||||
});
|
||||
|
||||
// send request and wait for server response
|
||||
Response pageResponse = page.waitForResponse("**/get", () -> {
|
||||
page.evaluate("() => fetch('./get', { method: 'GET' })");
|
||||
});
|
||||
// In 1s send a request which will trigger a request event while pageResponse.finished() is still
|
||||
// on the callstack.
|
||||
page.onRequest(request -> context.close());
|
||||
page.evaluate("() => setTimeout(() => fetch('./empty.html', { method: 'GET' }), 1000)");
|
||||
PlaywrightException e = assertThrows(PlaywrightException.class, () -> pageResponse.finished());
|
||||
assertTrue(e.getMessage().contains("closed"), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ public class TestPageRequestContinue extends TestBase {
|
||||
done[0] = true;
|
||||
});
|
||||
PlaywrightException e = assertThrows(PlaywrightException.class, () -> page.navigate(server.EMPTY_PAGE));
|
||||
assertTrue(e.getMessage().contains("Navigation failed because page was closed") ||
|
||||
assertTrue(e.getMessage().contains("Target page, context or browser has been closed") ||
|
||||
e.getMessage().contains("frame was detached"), e.getMessage());
|
||||
assertTrue(done[0]);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.microsoft.playwright;
|
||||
|
||||
import com.microsoft.playwright.assertions.LocatorAssertions;
|
||||
import com.microsoft.playwright.options.AriaRole;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -147,6 +148,11 @@ public class TestSelectorsGetBy extends TestBase {
|
||||
assertThat(page.getByPlaceholder("hello my\nworld")).hasAttribute("id", "control");
|
||||
assertThat(page.getByAltText("hello my\nworld")).hasAttribute("id", "control");
|
||||
assertThat(page.getByTitle("hello my\nworld")).hasAttribute("id", "control");
|
||||
|
||||
page.setContent("<div id=target title='my title'>Text here</div>");
|
||||
assertThat(page.getByTitle("my title", new Page.GetByTitleOptions().setExact(true))).hasCount(1, new LocatorAssertions.HasCountOptions().setTimeout(500));
|
||||
assertThat(page.getByTitle("my t\\itle", new Page.GetByTitleOptions().setExact(true))).hasCount(0, new LocatorAssertions.HasCountOptions().setTimeout(500));
|
||||
assertThat(page.getByTitle("my t\\\\itle", new Page.GetByTitleOptions().setExact(true))).hasCount(0, new LocatorAssertions.HasCountOptions().setTimeout(500));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -178,6 +184,16 @@ public class TestSelectorsGetBy extends TestBase {
|
||||
assertEquals(
|
||||
asList("<a href=\"https://playwright.dev\">he llo 56</a>"),
|
||||
page.getByRole(AriaRole.LINK, new Page.GetByRoleOptions().setName(" he \n llo 56 ").setExact(true)).evaluateAll("els => els.map(e => e.outerHTML)"));
|
||||
|
||||
assertEquals(
|
||||
asList("<button>Click me</button>"),
|
||||
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Click me").setExact(true)).evaluateAll("els => els.map(e => e.outerHTML)"));
|
||||
assertEquals(
|
||||
asList(),
|
||||
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Click \\me").setExact(true)).evaluateAll("els => els.map(e => e.outerHTML)"));
|
||||
assertEquals(
|
||||
asList(),
|
||||
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Click \\\\me").setExact(true)).evaluateAll("els => els.map(e => e.outerHTML)"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>com.microsoft.playwright</groupId>
|
||||
<artifactId>parent-pom</artifactId>
|
||||
<version>1.30.0-SNAPSHOT</version>
|
||||
<version>1.31.0</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>Playwright Parent Project</name>
|
||||
<description>Java library to automate Chromium, Firefox and WebKit with a single API.
|
||||
@@ -42,7 +42,8 @@
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<compiler.version>1.8</compiler.version>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<gson.version>2.8.9</gson.version>
|
||||
<junit.version>5.7.0</junit.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
@@ -90,26 +91,35 @@
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-clean-plugin</artifactId>
|
||||
<version>3.2.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<configuration>
|
||||
<source>${compiler.version}</source>
|
||||
<target>${compiler.version}</target>
|
||||
</configuration>
|
||||
<version>3.10.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-install-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
@@ -119,14 +129,6 @@
|
||||
<additionalOptions>--allow-script-in-comments</additionalOptions>
|
||||
<failOnError>false</failOnError>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadocs</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
@@ -156,7 +158,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.2.0</version>
|
||||
<version>3.3.0</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
@@ -167,6 +169,30 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>jar-no-fork</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
1.30.0-beta-1674276599000
|
||||
1.31.1
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>com.microsoft.playwright</groupId>
|
||||
<artifactId>api-generator</artifactId>
|
||||
<version>1.30.0-SNAPSHOT</version>
|
||||
<version>1.31.0</version>
|
||||
<name>Playwright - API Generator</name>
|
||||
<description>
|
||||
This is an internal module used to generate Java API from the upstream Playwright
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.microsoft.playwright</groupId>
|
||||
<artifactId>test-cli-fatjar</artifactId>
|
||||
<version>1.30.0-SNAPSHOT</version>
|
||||
<version>1.31.0</version>
|
||||
<name>Test Playwright Command Line FatJar</name>
|
||||
<properties>
|
||||
<compiler.version>1.8</compiler.version>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.microsoft.playwright</groupId>
|
||||
<artifactId>test-cli-version</artifactId>
|
||||
<version>1.30.0-SNAPSHOT</version>
|
||||
<version>1.31.0</version>
|
||||
<name>Test Playwright Command Line Version</name>
|
||||
<properties>
|
||||
<compiler.version>1.8</compiler.version>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.microsoft.playwright</groupId>
|
||||
<artifactId>test-local-installation</artifactId>
|
||||
<version>1.30.0-SNAPSHOT</version>
|
||||
<version>1.31.0</version>
|
||||
<name>Test local installation</name>
|
||||
<description>Runs Playwright test suite (copied from playwright module) against locally cached Playwright</description>
|
||||
<properties>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
</parent>
|
||||
<groupId>com.microsoft.playwright</groupId>
|
||||
<artifactId>test-spring-boot-starter</artifactId>
|
||||
<version>1.30.0-SNAPSHOT</version>
|
||||
<version>1.31.0</version>
|
||||
<name>Test Playwright With Spring Boot</name>
|
||||
<properties>
|
||||
<spring.version>2.4.3</spring.version>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>com.microsoft.playwright</groupId>
|
||||
<artifactId>update-version</artifactId>
|
||||
<version>1.30.0-SNAPSHOT</version>
|
||||
<version>1.31.0</version>
|
||||
<name>Playwright - Update Version in Documentation</name>
|
||||
<description>
|
||||
This is an internal module used to update versions in the documentation based on
|
||||
|
||||
Reference in New Issue
Block a user