Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ea16db9143 | |||
| 1a4dec86cd | |||
| c802c87e52 | |||
| ab81b542b8 | |||
| 07e7cb85c7 | |||
| 7af5405d38 | |||
| 50ba2dacbb | |||
| 61f5e4dfdd | |||
| 84344c9ff9 | |||
| c0fd575fac | |||
| 81724c7c94 | |||
| 3eb88931bf | |||
| 948dd1515a | |||
| dd57d5248d |
@@ -11,8 +11,8 @@ Playwright is a Java library to automate [Chromium](https://www.chromium.org/Hom
|
||||
|
||||
| | Linux | macOS | Windows |
|
||||
| :--- | :---: | :---: | :---: |
|
||||
| Chromium <!-- GEN:chromium-version -->96.0.4641.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| WebKit <!-- GEN:webkit-version -->15.0<!-- GEN:stop --> | ✅ | ✅ | ✅ |
|
||||
| Chromium <!-- GEN:chromium-version -->97.0.4666.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| WebKit <!-- GEN:webkit-version -->15.4<!-- GEN:stop --> | ✅ | ✅ | ✅ |
|
||||
| Firefox <!-- GEN:firefox-version -->92.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
|
||||
Headless execution is supported for all the browsers on all platforms. Check out [system requirements](https://playwright.dev/java/docs/next/intro/#system-requirements) for details.
|
||||
|
||||
@@ -5,3 +5,9 @@
|
||||
* set new driver version in `scripts/CLI_VERSION`
|
||||
* regenerate API: `./scripts/download_driver_for_all_platforms.sh -f && ./scripts/generate_api.sh && ./scripts/update_readme.sh`
|
||||
* commit & send PR with the roll
|
||||
|
||||
# Updating Version
|
||||
|
||||
```bash
|
||||
./scripts/set_maven_version.sh 1.15.0
|
||||
```
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.microsoft.playwright</groupId>
|
||||
<artifactId>parent-pom</artifactId>
|
||||
<version>1.15.0-SNAPSHOT</version>
|
||||
<version>1.16.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>driver-bundle</artifactId>
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.microsoft.playwright</groupId>
|
||||
<artifactId>parent-pom</artifactId>
|
||||
<version>1.15.0-SNAPSHOT</version>
|
||||
<version>1.16.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>driver</artifactId>
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>org.example</groupId>
|
||||
<artifactId>examples</artifactId>
|
||||
<version>1.15.0-SNAPSHOT</version>
|
||||
<version>1.16.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.11.1</version>
|
||||
<version>1.15.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.microsoft.playwright</groupId>
|
||||
<artifactId>parent-pom</artifactId>
|
||||
<version>1.15.0-SNAPSHOT</version>
|
||||
<version>1.16.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>playwright</artifactId>
|
||||
|
||||
@@ -86,7 +86,7 @@ public interface Browser extends AutoCloseable {
|
||||
*/
|
||||
public Double deviceScaleFactor;
|
||||
/**
|
||||
* An object containing additional HTTP headers to be sent with every request. All header values must be strings.
|
||||
* An object containing additional HTTP headers to be sent with every request.
|
||||
*/
|
||||
public Map<String, String> extraHTTPHeaders;
|
||||
/**
|
||||
@@ -107,7 +107,7 @@ public interface Browser extends AutoCloseable {
|
||||
*/
|
||||
public HttpCredentials httpCredentials;
|
||||
/**
|
||||
* Whether to ignore HTTPS errors during navigation. Defaults to {@code false}.
|
||||
* Whether to ignore HTTPS errors when sending network requests. Defaults to {@code false}.
|
||||
*/
|
||||
public Boolean ignoreHTTPSErrors;
|
||||
/**
|
||||
@@ -249,7 +249,7 @@ public interface Browser extends AutoCloseable {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* An object containing additional HTTP headers to be sent with every request. All header values must be strings.
|
||||
* An object containing additional HTTP headers to be sent with every request.
|
||||
*/
|
||||
public NewContextOptions setExtraHTTPHeaders(Map<String, String> extraHTTPHeaders) {
|
||||
this.extraHTTPHeaders = extraHTTPHeaders;
|
||||
@@ -294,7 +294,7 @@ public interface Browser extends AutoCloseable {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Whether to ignore HTTPS errors during navigation. Defaults to {@code false}.
|
||||
* Whether to ignore HTTPS errors when sending network requests. Defaults to {@code false}.
|
||||
*/
|
||||
public NewContextOptions setIgnoreHTTPSErrors(boolean ignoreHTTPSErrors) {
|
||||
this.ignoreHTTPSErrors = ignoreHTTPSErrors;
|
||||
@@ -510,7 +510,7 @@ public interface Browser extends AutoCloseable {
|
||||
*/
|
||||
public Double deviceScaleFactor;
|
||||
/**
|
||||
* An object containing additional HTTP headers to be sent with every request. All header values must be strings.
|
||||
* An object containing additional HTTP headers to be sent with every request.
|
||||
*/
|
||||
public Map<String, String> extraHTTPHeaders;
|
||||
/**
|
||||
@@ -531,7 +531,7 @@ public interface Browser extends AutoCloseable {
|
||||
*/
|
||||
public HttpCredentials httpCredentials;
|
||||
/**
|
||||
* Whether to ignore HTTPS errors during navigation. Defaults to {@code false}.
|
||||
* Whether to ignore HTTPS errors when sending network requests. Defaults to {@code false}.
|
||||
*/
|
||||
public Boolean ignoreHTTPSErrors;
|
||||
/**
|
||||
@@ -673,7 +673,7 @@ public interface Browser extends AutoCloseable {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* An object containing additional HTTP headers to be sent with every request. All header values must be strings.
|
||||
* An object containing additional HTTP headers to be sent with every request.
|
||||
*/
|
||||
public NewPageOptions setExtraHTTPHeaders(Map<String, String> extraHTTPHeaders) {
|
||||
this.extraHTTPHeaders = extraHTTPHeaders;
|
||||
@@ -718,7 +718,7 @@ public interface Browser extends AutoCloseable {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Whether to ignore HTTPS errors during navigation. Defaults to {@code false}.
|
||||
* Whether to ignore HTTPS errors when sending network requests. Defaults to {@code false}.
|
||||
*/
|
||||
public NewPageOptions setIgnoreHTTPSErrors(boolean ignoreHTTPSErrors) {
|
||||
this.ignoreHTTPSErrors = ignoreHTTPSErrors;
|
||||
|
||||
@@ -29,8 +29,8 @@ import java.util.regex.Pattern;
|
||||
* <p> If a page opens another page, e.g. with a {@code window.open} call, the popup will belong to the parent page's browser
|
||||
* context.
|
||||
*
|
||||
* <p> Playwright allows creation of "incognito" browser contexts with {@code browser.newContext()} method. "Incognito" browser
|
||||
* contexts don't write any browsing data to disk.
|
||||
* <p> Playwright allows creating "incognito" browser contexts with {@link Browser#newContext Browser.newContext()} method.
|
||||
* "Incognito" browser contexts don't write any browsing data to disk.
|
||||
* <pre>{@code
|
||||
* // Create a new incognito browser context
|
||||
* BrowserContext context = browser.newContext();
|
||||
|
||||
@@ -435,7 +435,7 @@ public interface BrowserType {
|
||||
*/
|
||||
public Path executablePath;
|
||||
/**
|
||||
* An object containing additional HTTP headers to be sent with every request. All header values must be strings.
|
||||
* An object containing additional HTTP headers to be sent with every request.
|
||||
*/
|
||||
public Map<String, String> extraHTTPHeaders;
|
||||
/**
|
||||
@@ -485,7 +485,7 @@ public interface BrowserType {
|
||||
*/
|
||||
public List<String> ignoreDefaultArgs;
|
||||
/**
|
||||
* Whether to ignore HTTPS errors during navigation. Defaults to {@code false}.
|
||||
* Whether to ignore HTTPS errors when sending network requests. Defaults to {@code false}.
|
||||
*/
|
||||
public Boolean ignoreHTTPSErrors;
|
||||
/**
|
||||
@@ -692,7 +692,7 @@ public interface BrowserType {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* An object containing additional HTTP headers to be sent with every request. All header values must be strings.
|
||||
* An object containing additional HTTP headers to be sent with every request.
|
||||
*/
|
||||
public LaunchPersistentContextOptions setExtraHTTPHeaders(Map<String, String> extraHTTPHeaders) {
|
||||
this.extraHTTPHeaders = extraHTTPHeaders;
|
||||
@@ -784,7 +784,7 @@ public interface BrowserType {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Whether to ignore HTTPS errors during navigation. Defaults to {@code false}.
|
||||
* Whether to ignore HTTPS errors when sending network requests. Defaults to {@code false}.
|
||||
*/
|
||||
public LaunchPersistentContextOptions setIgnoreHTTPSErrors(boolean ignoreHTTPSErrors) {
|
||||
this.ignoreHTTPSErrors = ignoreHTTPSErrors;
|
||||
@@ -1079,7 +1079,8 @@ public interface BrowserType {
|
||||
* @param userDataDir Path to a User Data Directory, which stores browser session data like cookies and local storage. More details for <a
|
||||
* href="https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md#introduction">Chromium</a> and <a
|
||||
* href="https://developer.mozilla.org/en-US/docs/Mozilla/Command_Line_Options#User_Profile">Firefox</a>. Note that
|
||||
* Chromium's user data directory is the **parent** directory of the "Profile Path" seen at {@code chrome://version}.
|
||||
* Chromium's user data directory is the **parent** directory of the "Profile Path" seen at {@code chrome://version}. Pass an
|
||||
* empty string to use a temporary directory instead.
|
||||
*/
|
||||
default BrowserContext launchPersistentContext(Path userDataDir) {
|
||||
return launchPersistentContext(userDataDir, null);
|
||||
@@ -1093,7 +1094,8 @@ public interface BrowserType {
|
||||
* @param userDataDir Path to a User Data Directory, which stores browser session data like cookies and local storage. More details for <a
|
||||
* href="https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md#introduction">Chromium</a> and <a
|
||||
* href="https://developer.mozilla.org/en-US/docs/Mozilla/Command_Line_Options#User_Profile">Firefox</a>. Note that
|
||||
* Chromium's user data directory is the **parent** directory of the "Profile Path" seen at {@code chrome://version}.
|
||||
* Chromium's user data directory is the **parent** directory of the "Profile Path" seen at {@code chrome://version}. Pass an
|
||||
* empty string to use a temporary directory instead.
|
||||
*/
|
||||
BrowserContext launchPersistentContext(Path userDataDir, LaunchPersistentContextOptions options);
|
||||
/**
|
||||
|
||||
@@ -1875,7 +1875,9 @@ public interface Frame {
|
||||
*/
|
||||
public Double timeout;
|
||||
/**
|
||||
* A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation.
|
||||
* 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 wilcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
public Object url;
|
||||
/**
|
||||
@@ -1899,21 +1901,27 @@ public interface Frame {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation.
|
||||
* 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 wilcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
public WaitForNavigationOptions setUrl(String url) {
|
||||
this.url = url;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation.
|
||||
* 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 wilcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
public WaitForNavigationOptions setUrl(Pattern url) {
|
||||
this.url = url;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation.
|
||||
* 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 wilcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
public WaitForNavigationOptions setUrl(Predicate<String> url) {
|
||||
this.url = url;
|
||||
@@ -3955,7 +3963,9 @@ 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.
|
||||
* @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 wilcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
default void waitForURL(String url) {
|
||||
waitForURL(url, null);
|
||||
@@ -3967,7 +3977,9 @@ 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.
|
||||
* @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 wilcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
void waitForURL(String url, WaitForURLOptions options);
|
||||
/**
|
||||
@@ -3977,7 +3989,9 @@ 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.
|
||||
* @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 wilcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
default void waitForURL(Pattern url) {
|
||||
waitForURL(url, null);
|
||||
@@ -3989,7 +4003,9 @@ 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.
|
||||
* @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 wilcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
void waitForURL(Pattern url, WaitForURLOptions options);
|
||||
/**
|
||||
@@ -3999,7 +4015,9 @@ 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.
|
||||
* @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 wilcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
default void waitForURL(Predicate<String> url) {
|
||||
waitForURL(url, null);
|
||||
@@ -4011,7 +4029,9 @@ 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.
|
||||
* @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 wilcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
void waitForURL(Predicate<String> url, WaitForURLOptions options);
|
||||
}
|
||||
|
||||
@@ -1355,6 +1355,51 @@ public interface Locator {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
class WaitForOptions {
|
||||
/**
|
||||
* Defaults to {@code "visible"}. Can be either:
|
||||
* <ul>
|
||||
* <li> {@code "attached"} - wait for element to be present in DOM.</li>
|
||||
* <li> {@code "detached"} - wait for element to not be present in DOM.</li>
|
||||
* <li> {@code "visible"} - wait for element to have non-empty bounding box and no {@code visibility:hidden}. Note that element without any
|
||||
* content or with {@code display:none} has an empty bounding box and is not considered visible.</li>
|
||||
* <li> {@code "hidden"} - wait for element to be either detached from DOM, or have an empty bounding box or {@code visibility:hidden}. This
|
||||
* is opposite to the {@code "visible"} option.</li>
|
||||
* </ul>
|
||||
*/
|
||||
public WaitForSelectorState state;
|
||||
/**
|
||||
* Maximum time in milliseconds, defaults to 30 seconds, pass {@code 0} to disable timeout. The default value can be changed by
|
||||
* using the {@link BrowserContext#setDefaultTimeout BrowserContext.setDefaultTimeout()} or {@link Page#setDefaultTimeout
|
||||
* Page.setDefaultTimeout()} methods.
|
||||
*/
|
||||
public Double timeout;
|
||||
|
||||
/**
|
||||
* Defaults to {@code "visible"}. Can be either:
|
||||
* <ul>
|
||||
* <li> {@code "attached"} - wait for element to be present in DOM.</li>
|
||||
* <li> {@code "detached"} - wait for element to not be present in DOM.</li>
|
||||
* <li> {@code "visible"} - wait for element to have non-empty bounding box and no {@code visibility:hidden}. Note that element without any
|
||||
* content or with {@code display:none} has an empty bounding box and is not considered visible.</li>
|
||||
* <li> {@code "hidden"} - wait for element to be either detached from DOM, or have an empty bounding box or {@code visibility:hidden}. This
|
||||
* is opposite to the {@code "visible"} option.</li>
|
||||
* </ul>
|
||||
*/
|
||||
public WaitForOptions setState(WaitForSelectorState state) {
|
||||
this.state = state;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Maximum time in milliseconds, defaults to 30 seconds, pass {@code 0} to disable timeout. The default value can be changed by
|
||||
* using the {@link BrowserContext#setDefaultTimeout BrowserContext.setDefaultTimeout()} or {@link Page#setDefaultTimeout
|
||||
* Page.setDefaultTimeout()} methods.
|
||||
*/
|
||||
public WaitForOptions setTimeout(double timeout) {
|
||||
this.timeout = timeout;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns an array of {@code node.innerText} values for all matching nodes.
|
||||
*/
|
||||
@@ -2667,5 +2712,29 @@ public interface Locator {
|
||||
* zero timeout disables this.
|
||||
*/
|
||||
void uncheck(UncheckOptions options);
|
||||
/**
|
||||
* Returns when element specified by locator satisfies the {@code state} option.
|
||||
*
|
||||
* <p> If target element already satisfies the condition, the method returns immediately. Otherwise, waits for up to {@code timeout}
|
||||
* milliseconds until the condition is met.
|
||||
* <pre>{@code
|
||||
* Locator orderSent = page.locator("#order-sent");
|
||||
* orderSent.waitFor();
|
||||
* }</pre>
|
||||
*/
|
||||
default void waitFor() {
|
||||
waitFor(null);
|
||||
}
|
||||
/**
|
||||
* Returns when element specified by locator satisfies the {@code state} option.
|
||||
*
|
||||
* <p> If target element already satisfies the condition, the method returns immediately. Otherwise, waits for up to {@code timeout}
|
||||
* milliseconds until the condition is met.
|
||||
* <pre>{@code
|
||||
* Locator orderSent = page.locator("#order-sent");
|
||||
* orderSent.waitFor();
|
||||
* }</pre>
|
||||
*/
|
||||
void waitFor(WaitForOptions options);
|
||||
}
|
||||
|
||||
|
||||
@@ -2712,7 +2712,9 @@ public interface Page extends AutoCloseable {
|
||||
*/
|
||||
public Double timeout;
|
||||
/**
|
||||
* A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation.
|
||||
* 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 wilcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
public Object url;
|
||||
/**
|
||||
@@ -2736,21 +2738,27 @@ public interface Page extends AutoCloseable {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation.
|
||||
* 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 wilcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
public WaitForNavigationOptions setUrl(String url) {
|
||||
this.url = url;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation.
|
||||
* 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 wilcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
public WaitForNavigationOptions setUrl(Pattern url) {
|
||||
this.url = url;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation.
|
||||
* 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 wilcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
public WaitForNavigationOptions setUrl(Predicate<String> url) {
|
||||
this.url = url;
|
||||
@@ -5454,7 +5462,9 @@ public interface Page extends AutoCloseable {
|
||||
* Browser#newContext Browser.newContext()} allows to set viewport size (and more) for all pages in the context at once.
|
||||
*
|
||||
* <p> {@code page.setViewportSize} will resize the page. A lot of websites don't expect phones to change size, so you should set the
|
||||
* viewport size before navigating to the page.
|
||||
* viewport size before navigating to the page. {@link Page#setViewportSize Page.setViewportSize()} will also reset
|
||||
* {@code screen} size, use {@link Browser#newContext Browser.newContext()} with {@code screen} and {@code viewport} parameters if you need
|
||||
* better control of these properties.
|
||||
* <pre>{@code
|
||||
* Page page = browser.newPage();
|
||||
* page.setViewportSize(640, 480);
|
||||
@@ -6394,7 +6404,9 @@ public interface Page extends AutoCloseable {
|
||||
*
|
||||
* <p> Shortcut for main frame's {@link Frame#waitForURL Frame.waitForURL()}.
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation.
|
||||
* @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 wilcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
default void waitForURL(String url) {
|
||||
waitForURL(url, null);
|
||||
@@ -6408,7 +6420,9 @@ public interface Page extends AutoCloseable {
|
||||
*
|
||||
* <p> Shortcut for main frame's {@link Frame#waitForURL Frame.waitForURL()}.
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation.
|
||||
* @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 wilcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
void waitForURL(String url, WaitForURLOptions options);
|
||||
/**
|
||||
@@ -6420,7 +6434,9 @@ public interface Page extends AutoCloseable {
|
||||
*
|
||||
* <p> Shortcut for main frame's {@link Frame#waitForURL Frame.waitForURL()}.
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation.
|
||||
* @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 wilcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
default void waitForURL(Pattern url) {
|
||||
waitForURL(url, null);
|
||||
@@ -6434,7 +6450,9 @@ public interface Page extends AutoCloseable {
|
||||
*
|
||||
* <p> Shortcut for main frame's {@link Frame#waitForURL Frame.waitForURL()}.
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation.
|
||||
* @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 wilcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
void waitForURL(Pattern url, WaitForURLOptions options);
|
||||
/**
|
||||
@@ -6446,7 +6464,9 @@ public interface Page extends AutoCloseable {
|
||||
*
|
||||
* <p> Shortcut for main frame's {@link Frame#waitForURL Frame.waitForURL()}.
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation.
|
||||
* @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 wilcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
default void waitForURL(Predicate<String> url) {
|
||||
waitForURL(url, null);
|
||||
@@ -6460,7 +6480,9 @@ public interface Page extends AutoCloseable {
|
||||
*
|
||||
* <p> Shortcut for main frame's {@link Frame#waitForURL Frame.waitForURL()}.
|
||||
*
|
||||
* @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation.
|
||||
* @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 wilcard characters, the method will wait for navigation to URL that is exactly equal to
|
||||
* the string.
|
||||
*/
|
||||
void waitForURL(Predicate<String> url, WaitForURLOptions options);
|
||||
/**
|
||||
|
||||
@@ -71,7 +71,6 @@ class BrowserImpl extends ChannelOwner implements Browser {
|
||||
} catch (IOException e) {
|
||||
throw new PlaywrightException("Failed to close browser connection", e);
|
||||
}
|
||||
notifyRemoteClosed();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.microsoft.playwright.impl;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.microsoft.playwright.Browser;
|
||||
@@ -23,12 +24,7 @@ import com.microsoft.playwright.BrowserType;
|
||||
import com.microsoft.playwright.PlaywrightException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Duration;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static com.microsoft.playwright.impl.Serialization.gson;
|
||||
@@ -58,51 +54,40 @@ class BrowserTypeImpl extends ChannelOwner implements BrowserType {
|
||||
}
|
||||
|
||||
private Browser connectImpl(String wsEndpoint, ConnectOptions options) {
|
||||
try {
|
||||
Duration timeout = Duration.ofDays(1);
|
||||
Map<String, String> headers = Collections.emptyMap();
|
||||
Duration slowMo = null;
|
||||
if (options != null) {
|
||||
if (options.timeout != null) {
|
||||
timeout = Duration.ofMillis(Math.round(options.timeout));
|
||||
}
|
||||
if (options.headers != null) {
|
||||
headers = options.headers;
|
||||
}
|
||||
if (options.slowMo != null) {
|
||||
slowMo = Duration.ofMillis(options.slowMo.intValue());
|
||||
}
|
||||
}
|
||||
WebSocketTransport transport = new WebSocketTransport(new URI(wsEndpoint), headers, timeout, slowMo);
|
||||
Connection connection = new Connection(transport);
|
||||
PlaywrightImpl playwright = connection.initializePlaywright();
|
||||
if (!playwright.initializer.has("preLaunchedBrowser")) {
|
||||
try {
|
||||
connection.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
throw new PlaywrightException("Malformed endpoint. Did you use launchServer method?");
|
||||
}
|
||||
playwright.initSharedSelectors(this.connection.getExistingObject("Playwright"));
|
||||
BrowserImpl browser = connection.getExistingObject(playwright.initializer.getAsJsonObject("preLaunchedBrowser").get("guid").getAsString());
|
||||
browser.isRemote = true;
|
||||
browser.isConnectedOverWebSocket = true;
|
||||
Consumer<WebSocketTransport> connectionCloseListener = t -> browser.notifyRemoteClosed();
|
||||
transport.onClose(connectionCloseListener);
|
||||
browser.onDisconnected(b -> {
|
||||
playwright.unregisterSelectors();
|
||||
transport.offClose(connectionCloseListener);
|
||||
try {
|
||||
connection.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
});
|
||||
return browser;
|
||||
} catch (URISyntaxException e) {
|
||||
throw new PlaywrightException("Failed to connect", e);
|
||||
if (options == null) {
|
||||
options = new ConnectOptions();
|
||||
}
|
||||
// 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);
|
||||
JsonObject json = sendMessage("connect", params).getAsJsonObject();
|
||||
JsonPipe pipe = connection.getExistingObject(json.getAsJsonObject("pipe").get("guid").getAsString());
|
||||
Connection connection = new Connection(pipe);
|
||||
PlaywrightImpl playwright = connection.initializePlaywright();
|
||||
if (!playwright.initializer.has("preLaunchedBrowser")) {
|
||||
try {
|
||||
connection.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
throw new PlaywrightException("Malformed endpoint. Did you use launchServer method?");
|
||||
}
|
||||
playwright.initSharedSelectors(this.connection.getExistingObject("Playwright"));
|
||||
BrowserImpl browser = connection.getExistingObject(playwright.initializer.getAsJsonObject("preLaunchedBrowser").get("guid").getAsString());
|
||||
browser.isRemote = true;
|
||||
browser.isConnectedOverWebSocket = true;
|
||||
Consumer<JsonPipe> connectionCloseListener = t -> browser.notifyRemoteClosed();
|
||||
pipe.onClose(connectionCloseListener);
|
||||
browser.onDisconnected(b -> {
|
||||
playwright.unregisterSelectors();
|
||||
pipe.offClose(connectionCloseListener);
|
||||
try {
|
||||
connection.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
});
|
||||
return browser;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -85,6 +85,9 @@ public class Connection {
|
||||
}
|
||||
|
||||
Connection(Transport transport) {
|
||||
if (isLogging) {
|
||||
transport = new TransportLogger(transport);
|
||||
}
|
||||
this.transport = transport;
|
||||
root = new Root(this);
|
||||
String srcRoot = System.getenv("PLAYWRIGHT_JAVA_SRC");
|
||||
@@ -172,11 +175,7 @@ public class Connection {
|
||||
metadata.addProperty("apiName", apiName);
|
||||
}
|
||||
message.add("metadata", metadata);
|
||||
String messageString = gson().toJson(message);
|
||||
if (isLogging) {
|
||||
logWithTimestamp("SEND ► " + messageString);
|
||||
}
|
||||
transport.send(messageString);
|
||||
transport.send(message);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -200,16 +199,13 @@ public class Connection {
|
||||
}
|
||||
|
||||
void processOneMessage() {
|
||||
String messageString = transport.poll(Duration.ofMillis(10));
|
||||
if (messageString == null) {
|
||||
JsonObject message = transport.poll(Duration.ofMillis(10));
|
||||
if (message == null) {
|
||||
return;
|
||||
}
|
||||
if (isLogging) {
|
||||
logWithTimestamp("◀ RECV " + messageString);
|
||||
}
|
||||
Gson gson = gson();
|
||||
Message message = gson.fromJson(messageString, Message.class);
|
||||
dispatch(message);
|
||||
Message messageObj = gson.fromJson(message, Message.class);
|
||||
dispatch(messageObj);
|
||||
}
|
||||
|
||||
private void dispatch(Message message) {
|
||||
@@ -315,6 +311,9 @@ public class Connection {
|
||||
case "JSHandle":
|
||||
result = new JSHandleImpl(parent, type, guid, initializer);
|
||||
break;
|
||||
case "JsonPipe":
|
||||
result = new JsonPipe(parent, type, guid, initializer);
|
||||
break;
|
||||
case "Page":
|
||||
result = new PageImpl(parent, type, guid, initializer);
|
||||
break;
|
||||
|
||||
@@ -948,11 +948,16 @@ public class FrameImpl extends ChannelOwner implements Frame {
|
||||
}
|
||||
|
||||
ElementHandle waitForSelectorImpl(String selector, WaitForSelectorOptions options) {
|
||||
return waitForSelectorImpl(selector, options, false);
|
||||
}
|
||||
|
||||
ElementHandle waitForSelectorImpl(String selector, WaitForSelectorOptions options, boolean omitReturnValue) {
|
||||
if (options == null) {
|
||||
options = new WaitForSelectorOptions();
|
||||
}
|
||||
JsonObject params = gson().toJsonTree(options).getAsJsonObject();
|
||||
params.addProperty("selector", selector);
|
||||
params.addProperty("omitReturnValue", omitReturnValue);
|
||||
JsonElement json = sendMessage("waitForSelector", params);
|
||||
JsonObject element = json.getAsJsonObject().getAsJsonObject("element");
|
||||
if (element == null) {
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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;
|
||||
import com.microsoft.playwright.PlaywrightException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static com.microsoft.playwright.impl.Serialization.gson;
|
||||
|
||||
class JsonPipe extends ChannelOwner implements Transport {
|
||||
private final Queue<JsonObject> incoming = new LinkedList<>();
|
||||
private ListenerCollection<EventType> listeners = new ListenerCollection<>();
|
||||
private enum EventType { CLOSE }
|
||||
private boolean isClosed;
|
||||
|
||||
JsonPipe(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(JsonObject message) {
|
||||
checkIfClosed();
|
||||
JsonObject params = new JsonObject();
|
||||
params.add("message", message);
|
||||
sendMessage("send", params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonObject poll(Duration timeout) {
|
||||
Instant start = Instant.now();
|
||||
return runUntil(() -> {}, new Waitable<JsonObject>() {
|
||||
JsonObject message;
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
if (!incoming.isEmpty()) {
|
||||
message = incoming.remove();
|
||||
return true;
|
||||
}
|
||||
checkIfClosed();
|
||||
if (Duration.between(start, Instant.now()).compareTo(timeout) > 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonObject get() {
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (!isClosed) {
|
||||
sendMessage("close");
|
||||
}
|
||||
}
|
||||
|
||||
void onClose(Consumer<JsonPipe> handler) {
|
||||
listeners.add(EventType.CLOSE, handler);
|
||||
}
|
||||
|
||||
void offClose(Consumer<JsonPipe> handler) {
|
||||
listeners.remove(EventType.CLOSE, handler);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void handleEvent(String event, JsonObject params) {
|
||||
if ("message".equals(event)) {
|
||||
incoming.add(params.get("message").getAsJsonObject());
|
||||
} else if ("closed".equals(event)) {
|
||||
isClosed = true;
|
||||
listeners.notify(EventType.CLOSE, this);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkIfClosed() {
|
||||
if (isClosed) {
|
||||
throw new PlaywrightException("Browser has been closed");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -399,6 +399,18 @@ class LocatorImpl implements Locator {
|
||||
frame.uncheck(selector, convertViaJson(options, Frame.UncheckOptions.class).setStrict(true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void waitFor(WaitForOptions options) {
|
||||
if (options == null) {
|
||||
options = new WaitForOptions();
|
||||
}
|
||||
waitForImpl(options);
|
||||
}
|
||||
|
||||
private void waitForImpl(WaitForOptions options) {
|
||||
frame.withLogging("Locator.waitFor", () -> frame.waitForSelectorImpl(selector, convertViaJson(options, Frame.WaitForSelectorOptions.class).setStrict(true), true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Locator@" + selector;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.microsoft.playwright.impl;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.microsoft.playwright.PlaywrightException;
|
||||
|
||||
import java.io.*;
|
||||
@@ -24,8 +25,10 @@ import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.microsoft.playwright.impl.Serialization.gson;
|
||||
|
||||
public class PipeTransport implements Transport {
|
||||
private final BlockingQueue<String> incoming = new ArrayBlockingQueue<>(1000);
|
||||
private final BlockingQueue<JsonObject> incoming = new ArrayBlockingQueue<>(1000);
|
||||
private final BlockingQueue<String> outgoing= new ArrayBlockingQueue<>(1000);
|
||||
|
||||
private final ReaderThread readerThread;
|
||||
@@ -42,24 +45,27 @@ public class PipeTransport implements Transport {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(String message) {
|
||||
public void send(JsonObject message) {
|
||||
if (isClosed) {
|
||||
throw new PlaywrightException("Playwright connection closed");
|
||||
}
|
||||
try {
|
||||
outgoing.put(message);
|
||||
// We could serialize the message on the IO thread but there is no guarantee
|
||||
// that the message object won't be modified on this thread after it's added
|
||||
// to the queue.
|
||||
outgoing.put(gson().toJson(message));
|
||||
} catch (InterruptedException e) {
|
||||
throw new PlaywrightException("Failed to send message", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String poll(Duration timeout) {
|
||||
public JsonObject poll(Duration timeout) {
|
||||
if (isClosed) {
|
||||
throw new PlaywrightException("Playwright connection closed");
|
||||
}
|
||||
try {
|
||||
String message = incoming.poll(timeout.toMillis(), TimeUnit.MILLISECONDS);
|
||||
JsonObject message = incoming.poll(timeout.toMillis(), TimeUnit.MILLISECONDS);
|
||||
if (message == null && readerThread.exception != null) {
|
||||
try {
|
||||
close();
|
||||
@@ -91,7 +97,7 @@ public class PipeTransport implements Transport {
|
||||
|
||||
class ReaderThread extends Thread {
|
||||
private final DataInputStream in;
|
||||
private final BlockingQueue<String> queue;
|
||||
private final BlockingQueue<JsonObject> queue;
|
||||
volatile boolean isClosing;
|
||||
volatile Exception exception;
|
||||
|
||||
@@ -107,7 +113,7 @@ class ReaderThread extends Thread {
|
||||
}
|
||||
}
|
||||
|
||||
ReaderThread(DataInputStream in, BlockingQueue<String> queue) {
|
||||
ReaderThread(DataInputStream in, BlockingQueue<JsonObject> queue) {
|
||||
this.in = in;
|
||||
this.queue = queue;
|
||||
}
|
||||
@@ -116,7 +122,8 @@ class ReaderThread extends Thread {
|
||||
public void run() {
|
||||
while (!isInterrupted()) {
|
||||
try {
|
||||
queue.put(readMessage());
|
||||
JsonObject message = gson().fromJson(readMessage(), JsonObject.class);
|
||||
queue.put(message);
|
||||
} catch (IOException e) {
|
||||
if (!isInterrupted() && !isClosing) {
|
||||
exception = e;
|
||||
|
||||
@@ -167,13 +167,8 @@ public class RequestImpl extends ChannelOwner implements Request {
|
||||
if (rawHeaders != null) {
|
||||
return rawHeaders;
|
||||
}
|
||||
ResponseImpl response = response();
|
||||
// there is no response, so should we return the headers we have now?
|
||||
if (response == null) {
|
||||
return headers;
|
||||
}
|
||||
JsonArray rawHeadersJson = response.withLogging("Request.allHeaders", () -> {
|
||||
JsonObject result = response.sendMessage("rawRequestHeaders").getAsJsonObject();
|
||||
JsonArray rawHeadersJson = withLogging("Request.allHeaders", () -> {
|
||||
JsonObject result = sendMessage("rawRequestHeaders").getAsJsonObject();
|
||||
return result.getAsJsonArray("headers");
|
||||
});
|
||||
|
||||
|
||||
@@ -50,6 +50,10 @@ class Router {
|
||||
handler.accept(route);
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean isDone() {
|
||||
return times != null && times <= 0;
|
||||
}
|
||||
}
|
||||
|
||||
void add(UrlMatcher matcher, Consumer<Route> handler, Integer times) {
|
||||
@@ -69,6 +73,9 @@ class Router {
|
||||
boolean handle(Route route) {
|
||||
for (RouteInfo info : routes) {
|
||||
if (info.handle(route)) {
|
||||
if (info.isDone()) {
|
||||
routes.remove(info);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,29 +33,26 @@ import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
class Serialization {
|
||||
private static Gson gson;
|
||||
private static Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(SameSiteAttribute.class, new SameSiteAdapter().nullSafe())
|
||||
.registerTypeAdapter(BrowserChannel.class, new ToLowerCaseAndDashSerializer<BrowserChannel>())
|
||||
.registerTypeAdapter(ColorScheme.class, new ToLowerCaseAndDashSerializer<ColorScheme>())
|
||||
.registerTypeAdapter(Media.class, new ToLowerCaseSerializer<Media>())
|
||||
.registerTypeAdapter(ForcedColors.class, new ToLowerCaseSerializer<ForcedColors>())
|
||||
.registerTypeAdapter(ReducedMotion.class, new ToLowerCaseAndDashSerializer<ReducedMotion>())
|
||||
.registerTypeAdapter(ScreenshotType.class, new ToLowerCaseSerializer<ScreenshotType>())
|
||||
.registerTypeAdapter(MouseButton.class, new ToLowerCaseSerializer<MouseButton>())
|
||||
.registerTypeAdapter(LoadState.class, new ToLowerCaseSerializer<LoadState>())
|
||||
.registerTypeAdapter(WaitUntilState.class, new ToLowerCaseSerializer<WaitUntilState>())
|
||||
.registerTypeAdapter(WaitForSelectorState.class, new ToLowerCaseSerializer<WaitForSelectorState>())
|
||||
.registerTypeAdapter((new TypeToken<List<KeyboardModifier>>(){}).getType(), new KeyboardModifiersSerializer())
|
||||
.registerTypeAdapter(Optional.class, new OptionalSerializer())
|
||||
.registerTypeHierarchyAdapter(JSHandleImpl.class, new HandleSerializer())
|
||||
.registerTypeAdapter((new TypeToken<Map<String, String>>(){}).getType(), new StringMapSerializer())
|
||||
.registerTypeAdapter((new TypeToken<Map<String, Object>>(){}).getType(), new FirefoxUserPrefsSerializer())
|
||||
.registerTypeHierarchyAdapter(Path.class, new PathSerializer()).create();;
|
||||
|
||||
static Gson gson() {
|
||||
if (gson == null) {
|
||||
gson = new GsonBuilder()
|
||||
.registerTypeAdapter(SameSiteAttribute.class, new SameSiteAdapter().nullSafe())
|
||||
.registerTypeAdapter(BrowserChannel.class, new ToLowerCaseAndDashSerializer<BrowserChannel>())
|
||||
.registerTypeAdapter(ColorScheme.class, new ToLowerCaseAndDashSerializer<ColorScheme>())
|
||||
.registerTypeAdapter(Media.class, new ToLowerCaseSerializer<Media>())
|
||||
.registerTypeAdapter(ForcedColors.class, new ToLowerCaseSerializer<ForcedColors>())
|
||||
.registerTypeAdapter(ReducedMotion.class, new ToLowerCaseAndDashSerializer<ReducedMotion>())
|
||||
.registerTypeAdapter(ScreenshotType.class, new ToLowerCaseSerializer<ScreenshotType>())
|
||||
.registerTypeAdapter(MouseButton.class, new ToLowerCaseSerializer<MouseButton>())
|
||||
.registerTypeAdapter(LoadState.class, new ToLowerCaseSerializer<LoadState>())
|
||||
.registerTypeAdapter(WaitUntilState.class, new ToLowerCaseSerializer<WaitUntilState>())
|
||||
.registerTypeAdapter(WaitForSelectorState.class, new ToLowerCaseSerializer<WaitForSelectorState>())
|
||||
.registerTypeAdapter((new TypeToken<List<KeyboardModifier>>(){}).getType(), new KeyboardModifiersSerializer())
|
||||
.registerTypeAdapter(Optional.class, new OptionalSerializer())
|
||||
.registerTypeHierarchyAdapter(JSHandleImpl.class, new HandleSerializer())
|
||||
.registerTypeAdapter((new TypeToken<Map<String, String>>(){}).getType(), new StringMapSerializer())
|
||||
.registerTypeAdapter((new TypeToken<Map<String, Object>>(){}).getType(), new FirefoxUserPrefsSerializer())
|
||||
.registerTypeHierarchyAdapter(Path.class, new PathSerializer()).create();
|
||||
}
|
||||
return gson;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,11 +16,13 @@
|
||||
|
||||
package com.microsoft.playwright.impl;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
|
||||
public interface Transport {
|
||||
void send(String message);
|
||||
String poll(Duration timeout);
|
||||
void send(JsonObject message);
|
||||
JsonObject poll(Duration timeout);
|
||||
void close() throws IOException;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.microsoft.playwright.impl;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
|
||||
import static com.microsoft.playwright.impl.LoggingSupport.logWithTimestamp;
|
||||
import static com.microsoft.playwright.impl.Serialization.gson;
|
||||
|
||||
class TransportLogger implements Transport {
|
||||
private final Transport transport;
|
||||
|
||||
TransportLogger(Transport transport) {
|
||||
this.transport = transport;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(JsonObject message) {
|
||||
String messageString = gson().toJson(message);
|
||||
logWithTimestamp("SEND ► " + messageString);
|
||||
transport.send(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonObject poll(Duration timeout) {
|
||||
JsonObject message = transport.poll(timeout);
|
||||
if (message != null) {
|
||||
String messageString = gson().toJson(message);
|
||||
logWithTimestamp("◀ RECV " + messageString);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
transport.close();
|
||||
}
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.microsoft.playwright.impl;
|
||||
|
||||
import com.microsoft.playwright.PlaywrightException;
|
||||
import org.java_websocket.client.WebSocketClient;
|
||||
import org.java_websocket.handshake.ServerHandshake;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.time.Duration;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
|
||||
class WebSocketTransport implements Transport {
|
||||
private final BlockingQueue<String> incoming = new LinkedBlockingQueue<>();
|
||||
private final ClientConnection clientConnection;
|
||||
private final Duration slowMo;
|
||||
private boolean isClosed;
|
||||
private volatile Exception lastError;
|
||||
ListenerCollection<EventType> listeners = new ListenerCollection<>();
|
||||
|
||||
private enum EventType { CLOSE }
|
||||
|
||||
private class ClientConnection extends WebSocketClient {
|
||||
ClientConnection(URI serverUri) {
|
||||
super(serverUri);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen(ServerHandshake handshakedata) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(String message) {
|
||||
incoming.add(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose(int code, String reason, boolean remote) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Exception ex) {
|
||||
lastError = ex;
|
||||
}
|
||||
}
|
||||
|
||||
WebSocketTransport(URI uri, Map<String, String> headers, Duration timeout, Duration slowMo) {
|
||||
clientConnection = new ClientConnection(uri);
|
||||
for (Map.Entry<String, String> entry : headers.entrySet()) {
|
||||
clientConnection.addHeader(entry.getKey(), entry.getValue());
|
||||
}
|
||||
try {
|
||||
if (!clientConnection.connectBlocking(timeout.toMillis(), TimeUnit.MILLISECONDS)) {
|
||||
throw new PlaywrightException("Failed to connect", lastError);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw new PlaywrightException("Failed to connect", e);
|
||||
}
|
||||
this.slowMo = slowMo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(String message) {
|
||||
checkIfClosed();
|
||||
clientConnection.send(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String poll(Duration timeout) {
|
||||
checkIfClosed();
|
||||
try {
|
||||
String message = incoming.poll(timeout.toMillis(), TimeUnit.MILLISECONDS);
|
||||
if (slowMo != null && message != null) {
|
||||
Thread.sleep(slowMo.toMillis());
|
||||
}
|
||||
return message;
|
||||
} catch (InterruptedException e) {
|
||||
throw new PlaywrightException("Failed to read message", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (isClosed) {
|
||||
return;
|
||||
}
|
||||
isClosed = true;
|
||||
clientConnection.close();
|
||||
}
|
||||
|
||||
void onClose(Consumer<WebSocketTransport> handler) {
|
||||
listeners.add(EventType.CLOSE, handler);
|
||||
}
|
||||
|
||||
void offClose(Consumer<WebSocketTransport> handler) {
|
||||
listeners.remove(EventType.CLOSE, handler);
|
||||
}
|
||||
|
||||
private void checkIfClosed() {
|
||||
if (isClosed) {
|
||||
throw new PlaywrightException("Playwright connection closed");
|
||||
}
|
||||
if (clientConnection.isClosed()) {
|
||||
isClosed = true;
|
||||
listeners.notify(EventType.CLOSE, this);
|
||||
throw new PlaywrightException("Playwright connection closed");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ public class Proxy {
|
||||
*/
|
||||
public String server;
|
||||
/**
|
||||
* Optional coma-separated domains to bypass proxy, for example {@code ".com, chromium.org, .domain.com"}.
|
||||
* Optional comma-separated domains to bypass proxy, for example {@code ".com, chromium.org, .domain.com"}.
|
||||
*/
|
||||
public String bypass;
|
||||
/**
|
||||
@@ -39,7 +39,7 @@ public class Proxy {
|
||||
this.server = server;
|
||||
}
|
||||
/**
|
||||
* Optional coma-separated domains to bypass proxy, for example {@code ".com, chromium.org, .domain.com"}.
|
||||
* Optional comma-separated domains to bypass proxy, for example {@code ".com, chromium.org, .domain.com"}.
|
||||
*/
|
||||
public Proxy setBypass(String bypass) {
|
||||
this.bypass = bypass;
|
||||
|
||||
@@ -201,23 +201,30 @@ public class Server implements HttpHandler {
|
||||
return;
|
||||
}
|
||||
exchange.getResponseHeaders().add("Content-Type", mimeType(file));
|
||||
OutputStream output = exchange.getResponseBody();
|
||||
ByteArrayOutputStream body = new ByteArrayOutputStream();
|
||||
OutputStream output = body;
|
||||
if (gzipRoutes.contains(path)) {
|
||||
exchange.getResponseHeaders().add("Content-Encoding", "gzip");
|
||||
}
|
||||
try (FileInputStream input = new FileInputStream(file)) {
|
||||
exchange.sendResponseHeaders(200, 0);
|
||||
if (gzipRoutes.contains(path)) {
|
||||
output = new GZIPOutputStream(output);
|
||||
}
|
||||
copy(input, output);
|
||||
output.close();
|
||||
} catch (IOException e) {
|
||||
try (Writer writer = new OutputStreamWriter(exchange.getResponseBody())) {
|
||||
body.reset();
|
||||
try (Writer writer = new OutputStreamWriter(output)) {
|
||||
writer.write("Exception: " + e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
output.close();
|
||||
long contentLength = body.size();
|
||||
// -1 means no body, 0 means chunked encoding.
|
||||
exchange.sendResponseHeaders(200, contentLength == 0 ? -1 : contentLength);
|
||||
if (contentLength > 0) {
|
||||
exchange.getResponseBody().write(body.toByteArray());
|
||||
}
|
||||
exchange.getResponseBody().close();
|
||||
}
|
||||
|
||||
private static String mimeType(File file) {
|
||||
|
||||
@@ -226,11 +226,21 @@ public class TestBrowserTypeConnect extends TestBase {
|
||||
BrowserServer server = launchBrowserServer(browserType);
|
||||
Browser remote = browserType.connect(server.wsEndpoint);
|
||||
Page page = remote.newPage();
|
||||
boolean[] disconnected = {false};
|
||||
remote.onDisconnected(b -> disconnected[0] = true);
|
||||
server.kill();
|
||||
while (!disconnected[0]) {
|
||||
try {
|
||||
page.waitForTimeout(10);
|
||||
} catch (PlaywrightException e) {
|
||||
assertTrue(e.getMessage().contains("Browser has been closed"));
|
||||
}
|
||||
}
|
||||
assertFalse(remote.isConnected());
|
||||
try {
|
||||
page.evaluate("1 + 1");
|
||||
} catch (PlaywrightException e) {
|
||||
assertTrue(e.getMessage().contains("Playwright connection closed"));
|
||||
assertTrue(e.getMessage().contains("Browser has been closed"), e.getMessage());
|
||||
}
|
||||
assertFalse(remote.isConnected());
|
||||
}
|
||||
@@ -248,7 +258,7 @@ public class TestBrowserTypeConnect extends TestBase {
|
||||
try {
|
||||
page.waitForTimeout(10);
|
||||
} catch (PlaywrightException e) {
|
||||
assertTrue(e.getMessage().contains("Playwright connection closed"));
|
||||
assertTrue(e.getMessage().contains("Browser has been closed"));
|
||||
}
|
||||
}
|
||||
assertFalse(browser.isConnected());
|
||||
@@ -256,7 +266,7 @@ public class TestBrowserTypeConnect extends TestBase {
|
||||
page.waitForNavigation(() -> {});
|
||||
fail("did not throw");
|
||||
} catch (PlaywrightException e) {
|
||||
assertTrue(e.getMessage().contains("Playwright connection closed"));
|
||||
assertTrue(e.getMessage().contains("Browser has been closed"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,7 +281,7 @@ public class TestBrowserTypeConnect extends TestBase {
|
||||
page.navigate(server.PREFIX + "/one-style.html", new Page.NavigateOptions().setTimeout(60000));
|
||||
fail("did not throw");
|
||||
} catch (PlaywrightException e) {
|
||||
assertTrue(e.getMessage().contains("Playwright connection closed"));
|
||||
assertTrue(e.getMessage().contains("Browser has been closed"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,14 +61,14 @@ public class TestElementHandleConvenience extends TestBase {
|
||||
page.inputValue("#inner");
|
||||
fail("did not throw");
|
||||
} catch (PlaywrightException e) {
|
||||
assertTrue(e.getMessage().contains("Node is not an HTMLInputElement or HTMLTextAreaElement"), e.getMessage());
|
||||
assertTrue(e.getMessage().contains("Node is not an <input>, <textarea> or <select> element"), e.getMessage());
|
||||
}
|
||||
ElementHandle handle2 = page.querySelector("#inner");
|
||||
try {
|
||||
handle2.inputValue();
|
||||
fail("did not throw");
|
||||
} catch (PlaywrightException e) {
|
||||
assertTrue(e.getMessage().contains("Node is not an HTMLInputElement or HTMLTextAreaElement"), e.getMessage());
|
||||
assertTrue(e.getMessage().contains("Node is not an <input>, <textarea> or <select> element"), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,14 +95,14 @@ public class TestElementHandleConvenience extends TestBase {
|
||||
page.innerText("svg");
|
||||
fail("did not throw");
|
||||
} catch (PlaywrightException e) {
|
||||
assertTrue(e.getMessage().contains("Not an HTMLElement"));
|
||||
assertTrue(e.getMessage().contains("Node is not an HTMLElement"), e.getMessage());
|
||||
}
|
||||
ElementHandle handle = page.querySelector("svg");
|
||||
try {
|
||||
handle.innerText();
|
||||
fail("did not throw");
|
||||
} catch (PlaywrightException e) {
|
||||
assertTrue(e.getMessage().contains("Not an HTMLElement"));
|
||||
assertTrue(e.getMessage().contains("Node is not an HTMLElement"), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,14 +65,14 @@ public class TestLocatorConvenience extends TestBase {
|
||||
page.inputValue("#inner");
|
||||
fail("did not throw");
|
||||
} catch (PlaywrightException e) {
|
||||
assertTrue(e.getMessage().contains("Node is not an HTMLInputElement or HTMLTextAreaElement or HTMLSelectElement"));
|
||||
assertTrue(e.getMessage().contains("Node is not an <input>, <textarea> or <select> element"), e.getMessage());
|
||||
}
|
||||
try {
|
||||
Locator locator2 = page.locator("#inner");
|
||||
locator2.inputValue();
|
||||
fail("did not throw");
|
||||
} catch (PlaywrightException e) {
|
||||
assertTrue(e.getMessage().contains("Node is not an HTMLInputElement or HTMLTextAreaElement or HTMLSelectElement"));
|
||||
assertTrue(e.getMessage().contains("Node is not an <input>, <textarea> or <select> element"), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,14 +99,14 @@ public class TestLocatorConvenience extends TestBase {
|
||||
page.innerText("svg");
|
||||
fail("did not throw");
|
||||
} catch (PlaywrightException e) {
|
||||
assertTrue(e.getMessage().contains("Not an HTMLElement"));
|
||||
assertTrue(e.getMessage().contains("Node is not an HTMLElement"), e.getMessage());
|
||||
}
|
||||
Locator locator = page.locator("svg");
|
||||
try {
|
||||
locator.innerText();
|
||||
fail("did not throw");
|
||||
} catch (PlaywrightException e) {
|
||||
assertTrue(e.getMessage().contains("Not an HTMLElement"));
|
||||
assertTrue(e.getMessage().contains("Node is not an HTMLElement"), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
|
||||
package com.microsoft.playwright;
|
||||
|
||||
import com.microsoft.playwright.options.WaitForSelectorState;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class TestLocatorMisc extends TestBase{
|
||||
@Test
|
||||
@@ -30,4 +32,21 @@ public class TestLocatorMisc extends TestBase{
|
||||
input.setChecked(false);
|
||||
assertEquals(false, page.evaluate("checkbox.checked"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldWaitFor() {
|
||||
page.setContent("<div></div>");
|
||||
Locator locator = page.locator("span");
|
||||
page.evalOnSelector("div", "div => setTimeout(() => div.innerHTML = '<span>target</span>', 500)");
|
||||
locator.waitFor();
|
||||
assertTrue(locator.textContent().contains("target"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldWaitForHidden() {
|
||||
page.setContent("<div><span>target</span></div>");
|
||||
Locator locator = page.locator("span");
|
||||
page.evalOnSelector("div", "div => setTimeout(() => div.innerHTML = '', 500)");
|
||||
locator.waitFor(new Locator.WaitForOptions().setState(WaitForSelectorState.HIDDEN));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,18 @@ public class TestNetworkRequest extends TestBase {
|
||||
assertEquals(server.PREFIX + "/empty.html", requests.get(1).url());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldWorkAllHeadersInsideRoute() {
|
||||
List<Request> requests = new ArrayList<>();
|
||||
page.route("**", route -> {
|
||||
assertTrue(route.request().allHeaders().get("accept").length() > 5);
|
||||
requests.add(route.request());
|
||||
route.resume();
|
||||
});
|
||||
page.navigate(server.PREFIX + "/empty.html");
|
||||
assertEquals(1, requests.size());
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/playwright/issues/3993
|
||||
@Test
|
||||
void shouldNotWorkForARedirectAndInterception() {
|
||||
|
||||
@@ -53,13 +53,12 @@ public class TestPageNetworkSizes extends TestBase {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled("responseBodySize == 16")
|
||||
void shouldSetBodySizeHeadersSizeAndTransferSize() throws ExecutionException, InterruptedException {
|
||||
server.setRoute("/get", exchange -> {
|
||||
// In Firefox, |fetch| will be hanging until it receives |Content-Type| header
|
||||
// from server.
|
||||
exchange.getResponseHeaders().add("Content-Type", "text/plain; charset=utf-8");
|
||||
exchange.sendResponseHeaders(200, 0);
|
||||
exchange.sendResponseHeaders(200, 6);
|
||||
try (OutputStreamWriter writer = new OutputStreamWriter(exchange.getResponseBody())) {
|
||||
writer.write("abc134");
|
||||
}
|
||||
@@ -71,20 +70,18 @@ public class TestPageNetworkSizes extends TestBase {
|
||||
request.get();
|
||||
Sizes sizes = response.request().sizes();
|
||||
assertEquals(6, sizes.responseBodySize);
|
||||
assertTrue(sizes.responseHeadersSize >= 100);
|
||||
assertTrue(sizes.responseHeadersSize > 10);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled("responseBodySize == 5")
|
||||
void shouldSetBodySizeTo0WhenThereWasNoResponseBody() {
|
||||
Response response = page.navigate(server.EMPTY_PAGE);
|
||||
Sizes sizes = response.request().sizes();
|
||||
assertEquals(0, sizes.responseBodySize);
|
||||
assertTrue(sizes.responseHeadersSize >= 100, "" + sizes.responseHeadersSize);
|
||||
assertTrue(sizes.responseHeadersSize > 10, "" + sizes.responseHeadersSize);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled("responseBodySize == 0")
|
||||
void shouldHaveTheCorrectResponseBodySize() throws IOException {
|
||||
Response response = page.navigate(server.PREFIX + "/simplezip.json");
|
||||
Sizes sizes = response.request().sizes();
|
||||
|
||||
@@ -141,7 +141,7 @@ public class TestPageSelectOption extends TestBase {
|
||||
page.selectOption("body", "");
|
||||
fail("did not throw");
|
||||
} catch (PlaywrightException e) {
|
||||
assertTrue(e.getMessage().contains("Element is not a <select> element."));
|
||||
assertTrue(e.getMessage().contains("Element is not a <select> element"), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>com.microsoft.playwright</groupId>
|
||||
<artifactId>parent-pom</artifactId>
|
||||
<version>1.15.0-SNAPSHOT</version>
|
||||
<version>1.16.0</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>Playwright Parent Project</name>
|
||||
<description>Java library to automate Chromium, Firefox and WebKit with a single API.
|
||||
@@ -76,6 +76,7 @@
|
||||
<groupId>org.java-websocket</groupId>
|
||||
<artifactId>Java-WebSocket</artifactId>
|
||||
<version>${websocket.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
1.15.0-1631797286000
|
||||
1.16.0-next-1634661437000
|
||||
|
||||
@@ -25,5 +25,5 @@ POM_FILES=(
|
||||
|
||||
for name in ${POM_FILES[*]};
|
||||
do
|
||||
mvn versions:set -D newVersion=$VERSION -f $name
|
||||
mvn versions:set -D generateBackupPoms=false -D newVersion=$VERSION -f $name
|
||||
done
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>com.microsoft.playwright</groupId>
|
||||
<artifactId>api-generator</artifactId>
|
||||
<version>1.15.0-SNAPSHOT</version>
|
||||
<version>1.16.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-local-installation</artifactId>
|
||||
<version>1.15.0-SNAPSHOT</version>
|
||||
<version>1.16.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.15.0-SNAPSHOT</version>
|
||||
<version>1.16.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.15.0-SNAPSHOT</version>
|
||||
<version>1.16.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