Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ea48985e21 |
@@ -19,6 +19,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: microsoft/playwright-github-action@v1
|
||||
- name: Set up JDK 1.8
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
@@ -29,8 +30,6 @@ jobs:
|
||||
run: scripts/download_driver.sh
|
||||
- name: Build & Install
|
||||
run: mvn -B install -D skipTests --no-transfer-progress
|
||||
- name: Install browsers
|
||||
run: mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="install --with-deps" -f playwright/pom.xml --no-transfer-progress
|
||||
- name: Run tests
|
||||
run: mvn test --no-transfer-progress --fail-at-end -D org.slf4j.simpleLogger.showDateTime=true -D org.slf4j.simpleLogger.dateTimeFormat=HH:mm:ss
|
||||
env:
|
||||
@@ -64,6 +63,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: microsoft/playwright-github-action@v1
|
||||
- name: Install Media Pack
|
||||
if: matrix.os == 'windows-latest'
|
||||
shell: powershell
|
||||
@@ -78,8 +78,6 @@ jobs:
|
||||
run: scripts/download_driver.sh
|
||||
- name: Build & Install
|
||||
run: mvn -B install -D skipTests --no-transfer-progress
|
||||
- name: Install browsers
|
||||
run: mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="install --with-deps" -f playwright/pom.xml --no-transfer-progress
|
||||
- name: Install MS Edge
|
||||
if: matrix.browser-channel == 'msedge' && matrix.os == 'macos-latest'
|
||||
shell: bash
|
||||
@@ -99,6 +97,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: microsoft/playwright-github-action@v1
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
@@ -109,8 +108,6 @@ jobs:
|
||||
run: scripts/download_driver.sh
|
||||
- name: Build & Install
|
||||
run: mvn -B install -D skipTests --no-transfer-progress
|
||||
- name: Install browsers
|
||||
run: mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="install --with-deps" -f playwright/pom.xml --no-transfer-progress
|
||||
- name: Run tests
|
||||
run: mvn test --no-transfer-progress --fail-at-end
|
||||
env:
|
||||
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
flavor: [jammy, noble]
|
||||
flavor: [focal, jammy, noble]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build Docker image
|
||||
|
||||
@@ -9,7 +9,7 @@ on:
|
||||
jobs:
|
||||
trigger:
|
||||
name: "trigger"
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- run: |
|
||||
curl -X POST \
|
||||
|
||||
@@ -20,14 +20,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: microsoft/playwright-github-action@v1
|
||||
- name: Download drivers
|
||||
run: scripts/download_driver.sh
|
||||
- name: Regenerate APIs
|
||||
run: scripts/generate_api.sh
|
||||
- name: Build & Install
|
||||
run: mvn -B install -D skipTests --no-transfer-progress
|
||||
- name: Install browsers
|
||||
run: mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="install --with-deps" -f playwright/pom.xml --no-transfer-progress
|
||||
- name: Update browser versions in README
|
||||
run: scripts/update_readme.sh
|
||||
- name: Verify API is up to date
|
||||
|
||||
@@ -10,9 +10,9 @@ Playwright is a Java library to automate [Chromium](https://www.chromium.org/Hom
|
||||
|
||||
| | Linux | macOS | Windows |
|
||||
| :--- | :---: | :---: | :---: |
|
||||
| Chromium <!-- GEN:chromium-version -->133.0.6943.16<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| WebKit <!-- GEN:webkit-version -->18.2<!-- GEN:stop --> | ✅ | ✅ | ✅ |
|
||||
| Firefox <!-- GEN:firefox-version -->134.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| Chromium <!-- GEN:chromium-version -->130.0.6723.31<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| WebKit <!-- GEN:webkit-version -->18.0<!-- GEN:stop --> | ✅ | ✅ | ✅ |
|
||||
| Firefox <!-- GEN:firefox-version -->131.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/intro#system-requirements) for details.
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.microsoft.playwright</groupId>
|
||||
<artifactId>parent-pom</artifactId>
|
||||
<version>1.50.0</version>
|
||||
<version>1.48.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.50.0</version>
|
||||
<version>1.48.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>driver</artifactId>
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>org.example</groupId>
|
||||
<artifactId>examples</artifactId>
|
||||
<version>1.50.0</version>
|
||||
<version>1.48.0</version>
|
||||
<name>Playwright Client Examples</name>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.microsoft.playwright</groupId>
|
||||
<artifactId>parent-pom</artifactId>
|
||||
<version>1.50.0</version>
|
||||
<version>1.48.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>playwright</artifactId>
|
||||
|
||||
@@ -29,15 +29,15 @@ import java.util.regex.Pattern;
|
||||
* import com.microsoft.playwright.*;
|
||||
*
|
||||
* public class Example {
|
||||
* public static void main(String[] args) {
|
||||
* try (Playwright playwright = Playwright.create()) {
|
||||
* BrowserType firefox = playwright.firefox();
|
||||
* Browser browser = firefox.launch();
|
||||
* Page page = browser.newPage();
|
||||
* page.navigate("https://example.com");
|
||||
* browser.close();
|
||||
* }
|
||||
* }
|
||||
* public static void main(String[] args) {
|
||||
* try (Playwright playwright = Playwright.create()) {
|
||||
* BrowserType firefox = playwright.firefox()
|
||||
* Browser browser = firefox.launch();
|
||||
* Page page = browser.newPage();
|
||||
* page.navigate('https://example.com');
|
||||
* browser.close();
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }</pre>
|
||||
*/
|
||||
@@ -111,11 +111,9 @@ public interface Browser extends AutoCloseable {
|
||||
*/
|
||||
public List<ClientCertificate> clientCertificates;
|
||||
/**
|
||||
* Emulates <a
|
||||
* href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme">prefers-colors-scheme</a> media
|
||||
* feature, supported values are {@code "light"} and {@code "dark"}. See {@link com.microsoft.playwright.Page#emulateMedia
|
||||
* Page.emulateMedia()} for more details. Passing {@code null} resets emulation to system defaults. Defaults to {@code
|
||||
* "light"}.
|
||||
* Emulates {@code "prefers-colors-scheme"} media feature, supported values are {@code "light"}, {@code "dark"}, {@code
|
||||
* "no-preference"}. See {@link com.microsoft.playwright.Page#emulateMedia Page.emulateMedia()} for more details. Passing
|
||||
* {@code null} resets emulation to system defaults. Defaults to {@code "light"}.
|
||||
*/
|
||||
public Optional<ColorScheme> colorScheme;
|
||||
/**
|
||||
@@ -325,11 +323,9 @@ public interface Browser extends AutoCloseable {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Emulates <a
|
||||
* href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme">prefers-colors-scheme</a> media
|
||||
* feature, supported values are {@code "light"} and {@code "dark"}. See {@link com.microsoft.playwright.Page#emulateMedia
|
||||
* Page.emulateMedia()} for more details. Passing {@code null} resets emulation to system defaults. Defaults to {@code
|
||||
* "light"}.
|
||||
* Emulates {@code "prefers-colors-scheme"} media feature, supported values are {@code "light"}, {@code "dark"}, {@code
|
||||
* "no-preference"}. See {@link com.microsoft.playwright.Page#emulateMedia Page.emulateMedia()} for more details. Passing
|
||||
* {@code null} resets emulation to system defaults. Defaults to {@code "light"}.
|
||||
*/
|
||||
public NewContextOptions setColorScheme(ColorScheme colorScheme) {
|
||||
this.colorScheme = Optional.ofNullable(colorScheme);
|
||||
@@ -664,11 +660,9 @@ public interface Browser extends AutoCloseable {
|
||||
*/
|
||||
public List<ClientCertificate> clientCertificates;
|
||||
/**
|
||||
* Emulates <a
|
||||
* href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme">prefers-colors-scheme</a> media
|
||||
* feature, supported values are {@code "light"} and {@code "dark"}. See {@link com.microsoft.playwright.Page#emulateMedia
|
||||
* Page.emulateMedia()} for more details. Passing {@code null} resets emulation to system defaults. Defaults to {@code
|
||||
* "light"}.
|
||||
* Emulates {@code "prefers-colors-scheme"} media feature, supported values are {@code "light"}, {@code "dark"}, {@code
|
||||
* "no-preference"}. See {@link com.microsoft.playwright.Page#emulateMedia Page.emulateMedia()} for more details. Passing
|
||||
* {@code null} resets emulation to system defaults. Defaults to {@code "light"}.
|
||||
*/
|
||||
public Optional<ColorScheme> colorScheme;
|
||||
/**
|
||||
@@ -878,11 +872,9 @@ public interface Browser extends AutoCloseable {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Emulates <a
|
||||
* href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme">prefers-colors-scheme</a> media
|
||||
* feature, supported values are {@code "light"} and {@code "dark"}. See {@link com.microsoft.playwright.Page#emulateMedia
|
||||
* Page.emulateMedia()} for more details. Passing {@code null} resets emulation to system defaults. Defaults to {@code
|
||||
* "light"}.
|
||||
* Emulates {@code "prefers-colors-scheme"} media feature, supported values are {@code "light"}, {@code "dark"}, {@code
|
||||
* "no-preference"}. See {@link com.microsoft.playwright.Page#emulateMedia Page.emulateMedia()} for more details. Passing
|
||||
* {@code null} resets emulation to system defaults. Defaults to {@code "light"}.
|
||||
*/
|
||||
public NewPageOptions setColorScheme(ColorScheme colorScheme) {
|
||||
this.colorScheme = Optional.ofNullable(colorScheme);
|
||||
@@ -1225,10 +1217,10 @@ public interface Browser extends AutoCloseable {
|
||||
* <p> In case this browser is connected to, clears all created contexts belonging to this browser and disconnects from the
|
||||
* browser server.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> This is similar to force-quitting the browser. To close pages gracefully and ensure you receive page close events, call
|
||||
* {@link com.microsoft.playwright.BrowserContext#close BrowserContext.close()} on any {@code BrowserContext} instances you
|
||||
* explicitly created earlier using {@link com.microsoft.playwright.Browser#newContext Browser.newContext()} **before**
|
||||
* calling {@link com.microsoft.playwright.Browser#close Browser.close()}.
|
||||
* <p> <strong>NOTE:</strong> This is similar to force quitting the browser. Therefore, you should call {@link
|
||||
* com.microsoft.playwright.BrowserContext#close BrowserContext.close()} on any {@code BrowserContext}'s you explicitly
|
||||
* created earlier with {@link com.microsoft.playwright.Browser#newContext Browser.newContext()} **before** calling {@link
|
||||
* com.microsoft.playwright.Browser#close Browser.close()}.
|
||||
*
|
||||
* <p> The {@code Browser} object itself is considered to be disposed and cannot be used anymore.
|
||||
*
|
||||
@@ -1244,10 +1236,10 @@ public interface Browser extends AutoCloseable {
|
||||
* <p> In case this browser is connected to, clears all created contexts belonging to this browser and disconnects from the
|
||||
* browser server.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> This is similar to force-quitting the browser. To close pages gracefully and ensure you receive page close events, call
|
||||
* {@link com.microsoft.playwright.BrowserContext#close BrowserContext.close()} on any {@code BrowserContext} instances you
|
||||
* explicitly created earlier using {@link com.microsoft.playwright.Browser#newContext Browser.newContext()} **before**
|
||||
* calling {@link com.microsoft.playwright.Browser#close Browser.close()}.
|
||||
* <p> <strong>NOTE:</strong> This is similar to force quitting the browser. Therefore, you should call {@link
|
||||
* com.microsoft.playwright.BrowserContext#close BrowserContext.close()} on any {@code BrowserContext}'s you explicitly
|
||||
* created earlier with {@link com.microsoft.playwright.Browser#newContext Browser.newContext()} **before** calling {@link
|
||||
* com.microsoft.playwright.Browser#close Browser.close()}.
|
||||
*
|
||||
* <p> The {@code Browser} object itself is considered to be disposed and cannot be used anymore.
|
||||
*
|
||||
@@ -1297,7 +1289,7 @@ public interface Browser extends AutoCloseable {
|
||||
* BrowserContext context = browser.newContext();
|
||||
* // Create a new page in a pristine context.
|
||||
* Page page = context.newPage();
|
||||
* page.navigate("https://example.com");
|
||||
* page.navigate('https://example.com');
|
||||
*
|
||||
* // Graceful close up everything
|
||||
* context.close();
|
||||
@@ -1324,7 +1316,7 @@ public interface Browser extends AutoCloseable {
|
||||
* BrowserContext context = browser.newContext();
|
||||
* // Create a new page in a pristine context.
|
||||
* Page page = context.newPage();
|
||||
* page.navigate("https://example.com");
|
||||
* page.navigate('https://example.com');
|
||||
*
|
||||
* // Graceful close up everything
|
||||
* context.close();
|
||||
@@ -1372,7 +1364,7 @@ public interface Browser extends AutoCloseable {
|
||||
* <pre>{@code
|
||||
* browser.startTracing(page, new Browser.StartTracingOptions()
|
||||
* .setPath(Paths.get("trace.json")));
|
||||
* page.navigate("https://www.google.com");
|
||||
* page.goto('https://www.google.com');
|
||||
* browser.stopTracing();
|
||||
* }</pre>
|
||||
*
|
||||
@@ -1396,7 +1388,7 @@ public interface Browser extends AutoCloseable {
|
||||
* <pre>{@code
|
||||
* browser.startTracing(page, new Browser.StartTracingOptions()
|
||||
* .setPath(Paths.get("trace.json")));
|
||||
* page.navigate("https://www.google.com");
|
||||
* page.goto('https://www.google.com');
|
||||
* browser.stopTracing();
|
||||
* }</pre>
|
||||
*
|
||||
@@ -1419,7 +1411,7 @@ public interface Browser extends AutoCloseable {
|
||||
* <pre>{@code
|
||||
* browser.startTracing(page, new Browser.StartTracingOptions()
|
||||
* .setPath(Paths.get("trace.json")));
|
||||
* page.navigate("https://www.google.com");
|
||||
* page.goto('https://www.google.com');
|
||||
* browser.stopTracing();
|
||||
* }</pre>
|
||||
*
|
||||
|
||||
@@ -701,7 +701,7 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* public class Example {
|
||||
* public static void main(String[] args) {
|
||||
* try (Playwright playwright = Playwright.create()) {
|
||||
* BrowserType webkit = playwright.webkit();
|
||||
* BrowserType webkit = playwright.webkit()
|
||||
* Browser browser = webkit.launch(new BrowserType.LaunchOptions().setHeadless(false));
|
||||
* BrowserContext context = browser.newContext();
|
||||
* context.exposeBinding("pageURL", (source, args) -> source.page().url());
|
||||
@@ -748,7 +748,7 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* public class Example {
|
||||
* public static void main(String[] args) {
|
||||
* try (Playwright playwright = Playwright.create()) {
|
||||
* BrowserType webkit = playwright.webkit();
|
||||
* BrowserType webkit = playwright.webkit()
|
||||
* Browser browser = webkit.launch(new BrowserType.LaunchOptions().setHeadless(false));
|
||||
* BrowserContext context = browser.newContext();
|
||||
* context.exposeBinding("pageURL", (source, args) -> source.page().url());
|
||||
@@ -797,9 +797,8 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* public class Example {
|
||||
* public static void main(String[] args) {
|
||||
* try (Playwright playwright = Playwright.create()) {
|
||||
* BrowserType webkit = playwright.webkit();
|
||||
* BrowserType webkit = playwright.webkit()
|
||||
* Browser browser = webkit.launch(new BrowserType.LaunchOptions().setHeadless(false));
|
||||
* BrowserContext context = browser.newContext();
|
||||
* context.exposeFunction("sha256", args -> {
|
||||
* String text = (String) args[0];
|
||||
* MessageDigest crypto;
|
||||
@@ -834,14 +833,10 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* Grants specified permissions to the browser context. Only grants corresponding permissions to the given origin if
|
||||
* specified.
|
||||
*
|
||||
* @param permissions A list of permissions to grant.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> Supported permissions differ between browsers, and even between different versions of the same browser. Any permission
|
||||
* may stop working after an update.
|
||||
*
|
||||
* <p> Here are some permissions that may be supported by some browsers:
|
||||
* @param permissions A permission or an array of permissions to grant. Permissions can be one of the following values:
|
||||
* <ul>
|
||||
* <li> {@code "accelerometer"}</li>
|
||||
* <li> {@code "accessibility-events"}</li>
|
||||
* <li> {@code "ambient-light-sensor"}</li>
|
||||
* <li> {@code "background-sync"}</li>
|
||||
* <li> {@code "camera"}</li>
|
||||
@@ -866,14 +861,10 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* Grants specified permissions to the browser context. Only grants corresponding permissions to the given origin if
|
||||
* specified.
|
||||
*
|
||||
* @param permissions A list of permissions to grant.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> Supported permissions differ between browsers, and even between different versions of the same browser. Any permission
|
||||
* may stop working after an update.
|
||||
*
|
||||
* <p> Here are some permissions that may be supported by some browsers:
|
||||
* @param permissions A permission or an array of permissions to grant. Permissions can be one of the following values:
|
||||
* <ul>
|
||||
* <li> {@code "accelerometer"}</li>
|
||||
* <li> {@code "accessibility-events"}</li>
|
||||
* <li> {@code "ambient-light-sensor"}</li>
|
||||
* <li> {@code "background-sync"}</li>
|
||||
* <li> {@code "camera"}</li>
|
||||
@@ -1396,7 +1387,7 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* com.microsoft.playwright.BrowserContext#setDefaultNavigationTimeout BrowserContext.setDefaultNavigationTimeout()} take
|
||||
* priority over {@link com.microsoft.playwright.BrowserContext#setDefaultTimeout BrowserContext.setDefaultTimeout()}.
|
||||
*
|
||||
* @param timeout Maximum time in milliseconds. Pass {@code 0} to disable timeout.
|
||||
* @param timeout Maximum time in milliseconds
|
||||
* @since v1.8
|
||||
*/
|
||||
void setDefaultTimeout(double timeout);
|
||||
|
||||
@@ -172,14 +172,9 @@ public interface BrowserType {
|
||||
*/
|
||||
public List<String> args;
|
||||
/**
|
||||
* Browser distribution channel.
|
||||
*
|
||||
* <p> Use "chromium" to <a href="https://playwright.dev/java/docs/browsers#chromium-new-headless-mode">opt in to new headless
|
||||
* mode</a>.
|
||||
*
|
||||
* <p> Use "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", or "msedge-canary" to
|
||||
* use branded <a href="https://playwright.dev/java/docs/browsers#google-chrome--microsoft-edge">Google Chrome and
|
||||
* Microsoft Edge</a>.
|
||||
* Browser distribution channel. Supported values are "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge",
|
||||
* "msedge-beta", "msedge-dev", "msedge-canary". Read more about using <a
|
||||
* href="https://playwright.dev/java/docs/browsers#google-chrome--microsoft-edge">Google Chrome and Microsoft Edge</a>.
|
||||
*/
|
||||
public Object channel;
|
||||
/**
|
||||
@@ -270,28 +265,18 @@ public interface BrowserType {
|
||||
}
|
||||
@Deprecated
|
||||
/**
|
||||
* Browser distribution channel.
|
||||
*
|
||||
* <p> Use "chromium" to <a href="https://playwright.dev/java/docs/browsers#chromium-new-headless-mode">opt in to new headless
|
||||
* mode</a>.
|
||||
*
|
||||
* <p> Use "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", or "msedge-canary" to
|
||||
* use branded <a href="https://playwright.dev/java/docs/browsers#google-chrome--microsoft-edge">Google Chrome and
|
||||
* Microsoft Edge</a>.
|
||||
* Browser distribution channel. Supported values are "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge",
|
||||
* "msedge-beta", "msedge-dev", "msedge-canary". Read more about using <a
|
||||
* href="https://playwright.dev/java/docs/browsers#google-chrome--microsoft-edge">Google Chrome and Microsoft Edge</a>.
|
||||
*/
|
||||
public LaunchOptions setChannel(BrowserChannel channel) {
|
||||
this.channel = channel;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Browser distribution channel.
|
||||
*
|
||||
* <p> Use "chromium" to <a href="https://playwright.dev/java/docs/browsers#chromium-new-headless-mode">opt in to new headless
|
||||
* mode</a>.
|
||||
*
|
||||
* <p> Use "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", or "msedge-canary" to
|
||||
* use branded <a href="https://playwright.dev/java/docs/browsers#google-chrome--microsoft-edge">Google Chrome and
|
||||
* Microsoft Edge</a>.
|
||||
* Browser distribution channel. Supported values are "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge",
|
||||
* "msedge-beta", "msedge-dev", "msedge-canary". Read more about using <a
|
||||
* href="https://playwright.dev/java/docs/browsers#google-chrome--microsoft-edge">Google Chrome and Microsoft Edge</a>.
|
||||
*/
|
||||
public LaunchOptions setChannel(String channel) {
|
||||
this.channel = channel;
|
||||
@@ -461,14 +446,9 @@ public interface BrowserType {
|
||||
*/
|
||||
public Boolean bypassCSP;
|
||||
/**
|
||||
* Browser distribution channel.
|
||||
*
|
||||
* <p> Use "chromium" to <a href="https://playwright.dev/java/docs/browsers#chromium-new-headless-mode">opt in to new headless
|
||||
* mode</a>.
|
||||
*
|
||||
* <p> Use "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", or "msedge-canary" to
|
||||
* use branded <a href="https://playwright.dev/java/docs/browsers#google-chrome--microsoft-edge">Google Chrome and
|
||||
* Microsoft Edge</a>.
|
||||
* Browser distribution channel. Supported values are "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge",
|
||||
* "msedge-beta", "msedge-dev", "msedge-canary". Read more about using <a
|
||||
* href="https://playwright.dev/java/docs/browsers#google-chrome--microsoft-edge">Google Chrome and Microsoft Edge</a>.
|
||||
*/
|
||||
public Object channel;
|
||||
/**
|
||||
@@ -490,11 +470,9 @@ public interface BrowserType {
|
||||
*/
|
||||
public List<ClientCertificate> clientCertificates;
|
||||
/**
|
||||
* Emulates <a
|
||||
* href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme">prefers-colors-scheme</a> media
|
||||
* feature, supported values are {@code "light"} and {@code "dark"}. See {@link com.microsoft.playwright.Page#emulateMedia
|
||||
* Page.emulateMedia()} for more details. Passing {@code null} resets emulation to system defaults. Defaults to {@code
|
||||
* "light"}.
|
||||
* Emulates {@code "prefers-colors-scheme"} media feature, supported values are {@code "light"}, {@code "dark"}, {@code
|
||||
* "no-preference"}. See {@link com.microsoft.playwright.Page#emulateMedia Page.emulateMedia()} for more details. Passing
|
||||
* {@code null} resets emulation to system defaults. Defaults to {@code "light"}.
|
||||
*/
|
||||
public Optional<ColorScheme> colorScheme;
|
||||
/**
|
||||
@@ -754,28 +732,18 @@ public interface BrowserType {
|
||||
}
|
||||
@Deprecated
|
||||
/**
|
||||
* Browser distribution channel.
|
||||
*
|
||||
* <p> Use "chromium" to <a href="https://playwright.dev/java/docs/browsers#chromium-new-headless-mode">opt in to new headless
|
||||
* mode</a>.
|
||||
*
|
||||
* <p> Use "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", or "msedge-canary" to
|
||||
* use branded <a href="https://playwright.dev/java/docs/browsers#google-chrome--microsoft-edge">Google Chrome and
|
||||
* Microsoft Edge</a>.
|
||||
* Browser distribution channel. Supported values are "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge",
|
||||
* "msedge-beta", "msedge-dev", "msedge-canary". Read more about using <a
|
||||
* href="https://playwright.dev/java/docs/browsers#google-chrome--microsoft-edge">Google Chrome and Microsoft Edge</a>.
|
||||
*/
|
||||
public LaunchPersistentContextOptions setChannel(BrowserChannel channel) {
|
||||
this.channel = channel;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Browser distribution channel.
|
||||
*
|
||||
* <p> Use "chromium" to <a href="https://playwright.dev/java/docs/browsers#chromium-new-headless-mode">opt in to new headless
|
||||
* mode</a>.
|
||||
*
|
||||
* <p> Use "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", or "msedge-canary" to
|
||||
* use branded <a href="https://playwright.dev/java/docs/browsers#google-chrome--microsoft-edge">Google Chrome and
|
||||
* Microsoft Edge</a>.
|
||||
* Browser distribution channel. Supported values are "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge",
|
||||
* "msedge-beta", "msedge-dev", "msedge-canary". Read more about using <a
|
||||
* href="https://playwright.dev/java/docs/browsers#google-chrome--microsoft-edge">Google Chrome and Microsoft Edge</a>.
|
||||
*/
|
||||
public LaunchPersistentContextOptions setChannel(String channel) {
|
||||
this.channel = channel;
|
||||
@@ -806,11 +774,9 @@ public interface BrowserType {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Emulates <a
|
||||
* href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme">prefers-colors-scheme</a> media
|
||||
* feature, supported values are {@code "light"} and {@code "dark"}. See {@link com.microsoft.playwright.Page#emulateMedia
|
||||
* Page.emulateMedia()} for more details. Passing {@code null} resets emulation to system defaults. Defaults to {@code
|
||||
* "light"}.
|
||||
* Emulates {@code "prefers-colors-scheme"} media feature, supported values are {@code "light"}, {@code "dark"}, {@code
|
||||
* "no-preference"}. See {@link com.microsoft.playwright.Page#emulateMedia Page.emulateMedia()} for more details. Passing
|
||||
* {@code null} resets emulation to system defaults. Defaults to {@code "light"}.
|
||||
*/
|
||||
public LaunchPersistentContextOptions setColorScheme(ColorScheme colorScheme) {
|
||||
this.colorScheme = Optional.ofNullable(colorScheme);
|
||||
|
||||
@@ -174,19 +174,6 @@ public interface Clock {
|
||||
* page.clock().pauseAt("2020-02-02");
|
||||
* }</pre>
|
||||
*
|
||||
* <p> For best results, install the clock before navigating the page and set it to a time slightly before the intended test
|
||||
* time. This ensures that all timers run normally during page loading, preventing the page from getting stuck. Once the
|
||||
* page has fully loaded, you can safely use {@link com.microsoft.playwright.Clock#pauseAt Clock.pauseAt()} to pause the
|
||||
* clock.
|
||||
* <pre>{@code
|
||||
* // Initialize clock with some time before the test time and let the page load
|
||||
* // naturally. `Date.now` will progress as the timers fire.
|
||||
* SimpleDateFormat format = new SimpleDateFormat("yyy-MM-dd'T'HH:mm:ss");
|
||||
* page.clock().install(new Clock.InstallOptions().setTime(format.parse("2024-12-10T08:00:00")));
|
||||
* page.navigate("http://localhost:3333");
|
||||
* page.clock().pauseAt(format.parse("2024-12-10T10:00:00"));
|
||||
* }</pre>
|
||||
*
|
||||
* @param time Time to pause at.
|
||||
* @since v1.45
|
||||
*/
|
||||
@@ -207,19 +194,6 @@ public interface Clock {
|
||||
* page.clock().pauseAt("2020-02-02");
|
||||
* }</pre>
|
||||
*
|
||||
* <p> For best results, install the clock before navigating the page and set it to a time slightly before the intended test
|
||||
* time. This ensures that all timers run normally during page loading, preventing the page from getting stuck. Once the
|
||||
* page has fully loaded, you can safely use {@link com.microsoft.playwright.Clock#pauseAt Clock.pauseAt()} to pause the
|
||||
* clock.
|
||||
* <pre>{@code
|
||||
* // Initialize clock with some time before the test time and let the page load
|
||||
* // naturally. `Date.now` will progress as the timers fire.
|
||||
* SimpleDateFormat format = new SimpleDateFormat("yyy-MM-dd'T'HH:mm:ss");
|
||||
* page.clock().install(new Clock.InstallOptions().setTime(format.parse("2024-12-10T08:00:00")));
|
||||
* page.navigate("http://localhost:3333");
|
||||
* page.clock().pauseAt(format.parse("2024-12-10T10:00:00"));
|
||||
* }</pre>
|
||||
*
|
||||
* @param time Time to pause at.
|
||||
* @since v1.45
|
||||
*/
|
||||
@@ -240,19 +214,6 @@ public interface Clock {
|
||||
* page.clock().pauseAt("2020-02-02");
|
||||
* }</pre>
|
||||
*
|
||||
* <p> For best results, install the clock before navigating the page and set it to a time slightly before the intended test
|
||||
* time. This ensures that all timers run normally during page loading, preventing the page from getting stuck. Once the
|
||||
* page has fully loaded, you can safely use {@link com.microsoft.playwright.Clock#pauseAt Clock.pauseAt()} to pause the
|
||||
* clock.
|
||||
* <pre>{@code
|
||||
* // Initialize clock with some time before the test time and let the page load
|
||||
* // naturally. `Date.now` will progress as the timers fire.
|
||||
* SimpleDateFormat format = new SimpleDateFormat("yyy-MM-dd'T'HH:mm:ss");
|
||||
* page.clock().install(new Clock.InstallOptions().setTime(format.parse("2024-12-10T08:00:00")));
|
||||
* page.navigate("http://localhost:3333");
|
||||
* page.clock().pauseAt(format.parse("2024-12-10T10:00:00"));
|
||||
* }</pre>
|
||||
*
|
||||
* @param time Time to pause at.
|
||||
* @since v1.45
|
||||
*/
|
||||
@@ -266,10 +227,6 @@ public interface Clock {
|
||||
/**
|
||||
* Makes {@code Date.now} and {@code new Date()} return fixed fake time at all times, keeps all the timers running.
|
||||
*
|
||||
* <p> Use this method for simple scenarios where you only need to test with a predefined time. For more advanced scenarios,
|
||||
* use {@link com.microsoft.playwright.Clock#install Clock.install()} instead. Read docs on <a
|
||||
* href="https://playwright.dev/java/docs/clock">clock emulation</a> to learn more.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* page.clock().setFixedTime(new Date());
|
||||
@@ -284,10 +241,6 @@ public interface Clock {
|
||||
/**
|
||||
* Makes {@code Date.now} and {@code new Date()} return fixed fake time at all times, keeps all the timers running.
|
||||
*
|
||||
* <p> Use this method for simple scenarios where you only need to test with a predefined time. For more advanced scenarios,
|
||||
* use {@link com.microsoft.playwright.Clock#install Clock.install()} instead. Read docs on <a
|
||||
* href="https://playwright.dev/java/docs/clock">clock emulation</a> to learn more.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* page.clock().setFixedTime(new Date());
|
||||
@@ -302,10 +255,6 @@ public interface Clock {
|
||||
/**
|
||||
* Makes {@code Date.now} and {@code new Date()} return fixed fake time at all times, keeps all the timers running.
|
||||
*
|
||||
* <p> Use this method for simple scenarios where you only need to test with a predefined time. For more advanced scenarios,
|
||||
* use {@link com.microsoft.playwright.Clock#install Clock.install()} instead. Read docs on <a
|
||||
* href="https://playwright.dev/java/docs/clock">clock emulation</a> to learn more.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* page.clock().setFixedTime(new Date());
|
||||
@@ -318,8 +267,7 @@ public interface Clock {
|
||||
*/
|
||||
void setFixedTime(Date time);
|
||||
/**
|
||||
* Sets system time, but does not trigger any timers. Use this to test how the web page reacts to a time shift, for example
|
||||
* switching from summer to winter time, or changing time zones.
|
||||
* Sets current system time but does not trigger any timers.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
@@ -333,8 +281,7 @@ public interface Clock {
|
||||
*/
|
||||
void setSystemTime(long time);
|
||||
/**
|
||||
* Sets system time, but does not trigger any timers. Use this to test how the web page reacts to a time shift, for example
|
||||
* switching from summer to winter time, or changing time zones.
|
||||
* Sets current system time but does not trigger any timers.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
@@ -348,8 +295,7 @@ public interface Clock {
|
||||
*/
|
||||
void setSystemTime(String time);
|
||||
/**
|
||||
* Sets system time, but does not trigger any timers. Use this to test how the web page reacts to a time shift, for example
|
||||
* switching from summer to winter time, or changing time zones.
|
||||
* Sets current system time but does not trigger any timers.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
|
||||
@@ -39,8 +39,8 @@ import java.util.*;
|
||||
* });
|
||||
*
|
||||
* // Deconstruct console.log arguments
|
||||
* msg.args().get(0).jsonValue(); // hello
|
||||
* msg.args().get(1).jsonValue(); // 42
|
||||
* msg.args().get(0).jsonValue() // hello
|
||||
* msg.args().get(1).jsonValue() // 42
|
||||
* }</pre>
|
||||
*/
|
||||
public interface ConsoleMessage {
|
||||
|
||||
@@ -3499,19 +3499,19 @@ public interface Frame {
|
||||
* <p> You can locate by text substring, exact string, or a regular expression:
|
||||
* <pre>{@code
|
||||
* // Matches <span>
|
||||
* page.getByText("world");
|
||||
* page.getByText("world")
|
||||
*
|
||||
* // Matches first <div>
|
||||
* page.getByText("Hello world");
|
||||
* page.getByText("Hello world")
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true));
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
|
||||
*
|
||||
* // Matches both <div>s
|
||||
* page.getByText(Pattern.compile("Hello"));
|
||||
* page.getByText(Pattern.compile("Hello"))
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE));
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
|
||||
* }</pre>
|
||||
*
|
||||
* <p> <strong>Details</strong>
|
||||
@@ -3541,19 +3541,19 @@ public interface Frame {
|
||||
* <p> You can locate by text substring, exact string, or a regular expression:
|
||||
* <pre>{@code
|
||||
* // Matches <span>
|
||||
* page.getByText("world");
|
||||
* page.getByText("world")
|
||||
*
|
||||
* // Matches first <div>
|
||||
* page.getByText("Hello world");
|
||||
* page.getByText("Hello world")
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true));
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
|
||||
*
|
||||
* // Matches both <div>s
|
||||
* page.getByText(Pattern.compile("Hello"));
|
||||
* page.getByText(Pattern.compile("Hello"))
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE));
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
|
||||
* }</pre>
|
||||
*
|
||||
* <p> <strong>Details</strong>
|
||||
@@ -3581,19 +3581,19 @@ public interface Frame {
|
||||
* <p> You can locate by text substring, exact string, or a regular expression:
|
||||
* <pre>{@code
|
||||
* // Matches <span>
|
||||
* page.getByText("world");
|
||||
* page.getByText("world")
|
||||
*
|
||||
* // Matches first <div>
|
||||
* page.getByText("Hello world");
|
||||
* page.getByText("Hello world")
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true));
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
|
||||
*
|
||||
* // Matches both <div>s
|
||||
* page.getByText(Pattern.compile("Hello"));
|
||||
* page.getByText(Pattern.compile("Hello"))
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE));
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
|
||||
* }</pre>
|
||||
*
|
||||
* <p> <strong>Details</strong>
|
||||
@@ -3623,19 +3623,19 @@ public interface Frame {
|
||||
* <p> You can locate by text substring, exact string, or a regular expression:
|
||||
* <pre>{@code
|
||||
* // Matches <span>
|
||||
* page.getByText("world");
|
||||
* page.getByText("world")
|
||||
*
|
||||
* // Matches first <div>
|
||||
* page.getByText("Hello world");
|
||||
* page.getByText("Hello world")
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true));
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
|
||||
*
|
||||
* // Matches both <div>s
|
||||
* page.getByText(Pattern.compile("Hello"));
|
||||
* page.getByText(Pattern.compile("Hello"))
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE));
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
|
||||
* }</pre>
|
||||
*
|
||||
* <p> <strong>Details</strong>
|
||||
|
||||
@@ -734,19 +734,19 @@ public interface FrameLocator {
|
||||
* <p> You can locate by text substring, exact string, or a regular expression:
|
||||
* <pre>{@code
|
||||
* // Matches <span>
|
||||
* page.getByText("world");
|
||||
* page.getByText("world")
|
||||
*
|
||||
* // Matches first <div>
|
||||
* page.getByText("Hello world");
|
||||
* page.getByText("Hello world")
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true));
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
|
||||
*
|
||||
* // Matches both <div>s
|
||||
* page.getByText(Pattern.compile("Hello"));
|
||||
* page.getByText(Pattern.compile("Hello"))
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE));
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
|
||||
* }</pre>
|
||||
*
|
||||
* <p> <strong>Details</strong>
|
||||
@@ -776,19 +776,19 @@ public interface FrameLocator {
|
||||
* <p> You can locate by text substring, exact string, or a regular expression:
|
||||
* <pre>{@code
|
||||
* // Matches <span>
|
||||
* page.getByText("world");
|
||||
* page.getByText("world")
|
||||
*
|
||||
* // Matches first <div>
|
||||
* page.getByText("Hello world");
|
||||
* page.getByText("Hello world")
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true));
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
|
||||
*
|
||||
* // Matches both <div>s
|
||||
* page.getByText(Pattern.compile("Hello"));
|
||||
* page.getByText(Pattern.compile("Hello"))
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE));
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
|
||||
* }</pre>
|
||||
*
|
||||
* <p> <strong>Details</strong>
|
||||
@@ -816,19 +816,19 @@ public interface FrameLocator {
|
||||
* <p> You can locate by text substring, exact string, or a regular expression:
|
||||
* <pre>{@code
|
||||
* // Matches <span>
|
||||
* page.getByText("world");
|
||||
* page.getByText("world")
|
||||
*
|
||||
* // Matches first <div>
|
||||
* page.getByText("Hello world");
|
||||
* page.getByText("Hello world")
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true));
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
|
||||
*
|
||||
* // Matches both <div>s
|
||||
* page.getByText(Pattern.compile("Hello"));
|
||||
* page.getByText(Pattern.compile("Hello"))
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE));
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
|
||||
* }</pre>
|
||||
*
|
||||
* <p> <strong>Details</strong>
|
||||
@@ -858,19 +858,19 @@ public interface FrameLocator {
|
||||
* <p> You can locate by text substring, exact string, or a regular expression:
|
||||
* <pre>{@code
|
||||
* // Matches <span>
|
||||
* page.getByText("world");
|
||||
* page.getByText("world")
|
||||
*
|
||||
* // Matches first <div>
|
||||
* page.getByText("Hello world");
|
||||
* page.getByText("Hello world")
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true));
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
|
||||
*
|
||||
* // Matches both <div>s
|
||||
* page.getByText(Pattern.compile("Hello"));
|
||||
* page.getByText(Pattern.compile("Hello"))
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE));
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
|
||||
* }</pre>
|
||||
*
|
||||
* <p> <strong>Details</strong>
|
||||
|
||||
@@ -48,7 +48,10 @@ import com.microsoft.playwright.options.*;
|
||||
*
|
||||
* <p> An example to trigger select-all with the keyboard
|
||||
* <pre>{@code
|
||||
* page.keyboard().press("ControlOrMeta+A");
|
||||
* // on Windows and Linux
|
||||
* page.keyboard().press("Control+A");
|
||||
* // on macOS
|
||||
* page.keyboard().press("Meta+A");
|
||||
* }</pre>
|
||||
*/
|
||||
public interface Keyboard {
|
||||
@@ -161,7 +164,7 @@ public interface Keyboard {
|
||||
* Page page = browser.newPage();
|
||||
* page.navigate("https://keycode.info");
|
||||
* page.keyboard().press("A");
|
||||
* page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get("A.png")));
|
||||
* page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get("A.png"));
|
||||
* page.keyboard().press("ArrowLeft");
|
||||
* page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get("ArrowLeft.png")));
|
||||
* page.keyboard().press("Shift+O");
|
||||
@@ -208,7 +211,7 @@ public interface Keyboard {
|
||||
* Page page = browser.newPage();
|
||||
* page.navigate("https://keycode.info");
|
||||
* page.keyboard().press("A");
|
||||
* page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get("A.png")));
|
||||
* page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get("A.png"));
|
||||
* page.keyboard().press("ArrowLeft");
|
||||
* page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get("ArrowLeft.png")));
|
||||
* page.keyboard().press("Shift+O");
|
||||
|
||||
@@ -29,26 +29,6 @@ import java.util.regex.Pattern;
|
||||
* <p> <a href="https://playwright.dev/java/docs/locators">Learn more about locators</a>.
|
||||
*/
|
||||
public interface Locator {
|
||||
class AriaSnapshotOptions {
|
||||
/**
|
||||
* Maximum time in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
|
||||
* value can be changed by using the {@link com.microsoft.playwright.BrowserContext#setDefaultTimeout
|
||||
* BrowserContext.setDefaultTimeout()} or {@link com.microsoft.playwright.Page#setDefaultTimeout Page.setDefaultTimeout()}
|
||||
* methods.
|
||||
*/
|
||||
public Double timeout;
|
||||
|
||||
/**
|
||||
* Maximum time in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
|
||||
* value can be changed by using the {@link com.microsoft.playwright.BrowserContext#setDefaultTimeout
|
||||
* BrowserContext.setDefaultTimeout()} or {@link com.microsoft.playwright.Page#setDefaultTimeout Page.setDefaultTimeout()}
|
||||
* methods.
|
||||
*/
|
||||
public AriaSnapshotOptions setTimeout(double timeout) {
|
||||
this.timeout = timeout;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
class BlurOptions {
|
||||
/**
|
||||
* Maximum time in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
|
||||
@@ -2171,7 +2151,7 @@ public interface Locator {
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* for (Locator li : page.getByRole("listitem").all())
|
||||
* for (Locator li : page.getByRole('listitem').all())
|
||||
* li.click();
|
||||
* }</pre>
|
||||
*
|
||||
@@ -2222,66 +2202,6 @@ public interface Locator {
|
||||
* @since v1.34
|
||||
*/
|
||||
Locator and(Locator locator);
|
||||
/**
|
||||
* Captures the aria snapshot of the given element. Read more about <a
|
||||
* href="https://playwright.dev/java/docs/aria-snapshots">aria snapshots</a> and {@link
|
||||
* com.microsoft.playwright.assertions.LocatorAssertions#matchesAriaSnapshot LocatorAssertions.matchesAriaSnapshot()} for
|
||||
* the corresponding assertion.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* page.getByRole(AriaRole.LINK).ariaSnapshot();
|
||||
* }</pre>
|
||||
*
|
||||
* <p> <strong>Details</strong>
|
||||
*
|
||||
* <p> This method captures the aria snapshot of the given element. The snapshot is a string that represents the state of the
|
||||
* element and its children. The snapshot can be used to assert the state of the element in the test, or to compare it to
|
||||
* state in the future.
|
||||
*
|
||||
* <p> The ARIA snapshot is represented using <a href="https://yaml.org/spec/1.2.2/">YAML</a> markup language:
|
||||
* <ul>
|
||||
* <li> The keys of the objects are the roles and optional accessible names of the elements.</li>
|
||||
* <li> The values are either text content or an array of child elements.</li>
|
||||
* <li> Generic static text can be represented with the {@code text} key.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p> Below is the HTML markup and the respective ARIA snapshot:
|
||||
*
|
||||
* @since v1.49
|
||||
*/
|
||||
default String ariaSnapshot() {
|
||||
return ariaSnapshot(null);
|
||||
}
|
||||
/**
|
||||
* Captures the aria snapshot of the given element. Read more about <a
|
||||
* href="https://playwright.dev/java/docs/aria-snapshots">aria snapshots</a> and {@link
|
||||
* com.microsoft.playwright.assertions.LocatorAssertions#matchesAriaSnapshot LocatorAssertions.matchesAriaSnapshot()} for
|
||||
* the corresponding assertion.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* page.getByRole(AriaRole.LINK).ariaSnapshot();
|
||||
* }</pre>
|
||||
*
|
||||
* <p> <strong>Details</strong>
|
||||
*
|
||||
* <p> This method captures the aria snapshot of the given element. The snapshot is a string that represents the state of the
|
||||
* element and its children. The snapshot can be used to assert the state of the element in the test, or to compare it to
|
||||
* state in the future.
|
||||
*
|
||||
* <p> The ARIA snapshot is represented using <a href="https://yaml.org/spec/1.2.2/">YAML</a> markup language:
|
||||
* <ul>
|
||||
* <li> The keys of the objects are the roles and optional accessible names of the elements.</li>
|
||||
* <li> The values are either text content or an array of child elements.</li>
|
||||
* <li> Generic static text can be represented with the {@code text} key.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p> Below is the HTML markup and the respective ARIA snapshot:
|
||||
*
|
||||
* @since v1.49
|
||||
*/
|
||||
String ariaSnapshot(AriaSnapshotOptions options);
|
||||
/**
|
||||
* Calls <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/blur">blur</a> on the element.
|
||||
*
|
||||
@@ -2630,6 +2550,7 @@ public interface Locator {
|
||||
*
|
||||
* <p> You can also specify {@code JSHandle} as the property value if you want live objects to be passed into the event:
|
||||
* <pre>{@code
|
||||
* // Note you can only create DataTransfer in Chromium and Firefox
|
||||
* JSHandle dataTransfer = page.evaluateHandle("() => new DataTransfer()");
|
||||
* Map<String, Object> arg = new HashMap<>();
|
||||
* arg.put("dataTransfer", dataTransfer);
|
||||
@@ -2678,6 +2599,7 @@ public interface Locator {
|
||||
*
|
||||
* <p> You can also specify {@code JSHandle} as the property value if you want live objects to be passed into the event:
|
||||
* <pre>{@code
|
||||
* // Note you can only create DataTransfer in Chromium and Firefox
|
||||
* JSHandle dataTransfer = page.evaluateHandle("() => new DataTransfer()");
|
||||
* Map<String, Object> arg = new HashMap<>();
|
||||
* arg.put("dataTransfer", dataTransfer);
|
||||
@@ -2725,6 +2647,7 @@ public interface Locator {
|
||||
*
|
||||
* <p> You can also specify {@code JSHandle} as the property value if you want live objects to be passed into the event:
|
||||
* <pre>{@code
|
||||
* // Note you can only create DataTransfer in Chromium and Firefox
|
||||
* JSHandle dataTransfer = page.evaluateHandle("() => new DataTransfer()");
|
||||
* Map<String, Object> arg = new HashMap<>();
|
||||
* arg.put("dataTransfer", dataTransfer);
|
||||
@@ -3532,19 +3455,19 @@ public interface Locator {
|
||||
* <p> You can locate by text substring, exact string, or a regular expression:
|
||||
* <pre>{@code
|
||||
* // Matches <span>
|
||||
* page.getByText("world");
|
||||
* page.getByText("world")
|
||||
*
|
||||
* // Matches first <div>
|
||||
* page.getByText("Hello world");
|
||||
* page.getByText("Hello world")
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true));
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
|
||||
*
|
||||
* // Matches both <div>s
|
||||
* page.getByText(Pattern.compile("Hello"));
|
||||
* page.getByText(Pattern.compile("Hello"))
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE));
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
|
||||
* }</pre>
|
||||
*
|
||||
* <p> <strong>Details</strong>
|
||||
@@ -3574,19 +3497,19 @@ public interface Locator {
|
||||
* <p> You can locate by text substring, exact string, or a regular expression:
|
||||
* <pre>{@code
|
||||
* // Matches <span>
|
||||
* page.getByText("world");
|
||||
* page.getByText("world")
|
||||
*
|
||||
* // Matches first <div>
|
||||
* page.getByText("Hello world");
|
||||
* page.getByText("Hello world")
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true));
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
|
||||
*
|
||||
* // Matches both <div>s
|
||||
* page.getByText(Pattern.compile("Hello"));
|
||||
* page.getByText(Pattern.compile("Hello"))
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE));
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
|
||||
* }</pre>
|
||||
*
|
||||
* <p> <strong>Details</strong>
|
||||
@@ -3614,19 +3537,19 @@ public interface Locator {
|
||||
* <p> You can locate by text substring, exact string, or a regular expression:
|
||||
* <pre>{@code
|
||||
* // Matches <span>
|
||||
* page.getByText("world");
|
||||
* page.getByText("world")
|
||||
*
|
||||
* // Matches first <div>
|
||||
* page.getByText("Hello world");
|
||||
* page.getByText("Hello world")
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true));
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
|
||||
*
|
||||
* // Matches both <div>s
|
||||
* page.getByText(Pattern.compile("Hello"));
|
||||
* page.getByText(Pattern.compile("Hello"))
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE));
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
|
||||
* }</pre>
|
||||
*
|
||||
* <p> <strong>Details</strong>
|
||||
@@ -3656,19 +3579,19 @@ public interface Locator {
|
||||
* <p> You can locate by text substring, exact string, or a regular expression:
|
||||
* <pre>{@code
|
||||
* // Matches <span>
|
||||
* page.getByText("world");
|
||||
* page.getByText("world")
|
||||
*
|
||||
* // Matches first <div>
|
||||
* page.getByText("Hello world");
|
||||
* page.getByText("Hello world")
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true));
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
|
||||
*
|
||||
* // Matches both <div>s
|
||||
* page.getByText(Pattern.compile("Hello"));
|
||||
* page.getByText(Pattern.compile("Hello"))
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE));
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
|
||||
* }</pre>
|
||||
*
|
||||
* <p> <strong>Details</strong>
|
||||
@@ -3965,9 +3888,7 @@ public interface Locator {
|
||||
*/
|
||||
boolean isDisabled(IsDisabledOptions options);
|
||||
/**
|
||||
* Returns whether the element is <a href="https://playwright.dev/java/docs/actionability#editable">editable</a>. If the
|
||||
* target element is not an {@code <input>}, {@code <textarea>}, {@code <select>}, {@code [contenteditable]} and does not
|
||||
* have a role allowing {@code [aria-readonly]}, this method throws an error.
|
||||
* Returns whether the element is <a href="https://playwright.dev/java/docs/actionability#editable">editable</a>.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> If you need to assert that an element is editable, prefer {@link
|
||||
* com.microsoft.playwright.assertions.LocatorAssertions#isEditable LocatorAssertions.isEditable()} to avoid flakiness. See
|
||||
@@ -3984,9 +3905,7 @@ public interface Locator {
|
||||
return isEditable(null);
|
||||
}
|
||||
/**
|
||||
* Returns whether the element is <a href="https://playwright.dev/java/docs/actionability#editable">editable</a>. If the
|
||||
* target element is not an {@code <input>}, {@code <textarea>}, {@code <select>}, {@code [contenteditable]} and does not
|
||||
* have a role allowing {@code [aria-readonly]}, this method throws an error.
|
||||
* Returns whether the element is <a href="https://playwright.dev/java/docs/actionability#editable">editable</a>.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> If you need to assert that an element is editable, prefer {@link
|
||||
* com.microsoft.playwright.assertions.LocatorAssertions#isEditable LocatorAssertions.isEditable()} to avoid flakiness. See
|
||||
@@ -4167,21 +4086,17 @@ public interface Locator {
|
||||
/**
|
||||
* Creates a locator matching all elements that match one or both of the two locators.
|
||||
*
|
||||
* <p> Note that when both locators match something, the resulting locator will have multiple matches, potentially causing a <a
|
||||
* href="https://playwright.dev/java/docs/locators#strictness">locator strictness</a> violation.
|
||||
* <p> Note that when both locators match something, the resulting locator will have multiple matches and violate <a
|
||||
* href="https://playwright.dev/java/docs/locators#strictness">locator strictness</a> guidelines.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
*
|
||||
* <p> Consider a scenario where you'd like to click on a "New email" button, but sometimes a security settings dialog shows up
|
||||
* instead. In this case, you can wait for either a "New email" button, or a dialog and act accordingly.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> If both "New email" button and security dialog appear on screen, the "or" locator will match both of them, possibly
|
||||
* throwing the <a href="https://playwright.dev/java/docs/locators#strictness">"strict mode violation" error</a>. In this
|
||||
* case, you can use {@link com.microsoft.playwright.Locator#first Locator.first()} to only match one of them.
|
||||
* <pre>{@code
|
||||
* Locator newEmail = page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("New"));
|
||||
* Locator dialog = page.getByText("Confirm security settings");
|
||||
* assertThat(newEmail.or(dialog).first()).isVisible();
|
||||
* assertThat(newEmail.or(dialog)).isVisible();
|
||||
* if (dialog.isVisible())
|
||||
* page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Dismiss")).click();
|
||||
* newEmail.click();
|
||||
|
||||
@@ -959,10 +959,8 @@ public interface Page extends AutoCloseable {
|
||||
}
|
||||
class EmulateMediaOptions {
|
||||
/**
|
||||
* Emulates <a
|
||||
* href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme">prefers-colors-scheme</a> media
|
||||
* feature, supported values are {@code "light"} and {@code "dark"}. Passing {@code null} disables color scheme emulation.
|
||||
* {@code "no-preference"} is deprecated.
|
||||
* Emulates {@code "prefers-colors-scheme"} media feature, supported values are {@code "light"}, {@code "dark"}, {@code
|
||||
* "no-preference"}. Passing {@code null} disables color scheme emulation.
|
||||
*/
|
||||
public Optional<ColorScheme> colorScheme;
|
||||
/**
|
||||
@@ -982,10 +980,8 @@ public interface Page extends AutoCloseable {
|
||||
public Optional<ReducedMotion> reducedMotion;
|
||||
|
||||
/**
|
||||
* Emulates <a
|
||||
* href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme">prefers-colors-scheme</a> media
|
||||
* feature, supported values are {@code "light"} and {@code "dark"}. Passing {@code null} disables color scheme emulation.
|
||||
* {@code "no-preference"} is deprecated.
|
||||
* Emulates {@code "prefers-colors-scheme"} media feature, supported values are {@code "light"}, {@code "dark"}, {@code
|
||||
* "no-preference"}. Passing {@code null} disables color scheme emulation.
|
||||
*/
|
||||
public EmulateMediaOptions setColorScheme(ColorScheme colorScheme) {
|
||||
this.colorScheme = Optional.ofNullable(colorScheme);
|
||||
@@ -4155,9 +4151,9 @@ public interface Page extends AutoCloseable {
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* page.dragAndDrop("#source", "#target");
|
||||
* page.dragAndDrop("#source", '#target');
|
||||
* // or specify exact positions relative to the top-left corners of the elements:
|
||||
* page.dragAndDrop("#source", "#target", new Page.DragAndDropOptions()
|
||||
* page.dragAndDrop("#source", '#target', new Page.DragAndDropOptions()
|
||||
* .setSourcePosition(34, 7).setTargetPosition(10, 20));
|
||||
* }</pre>
|
||||
*
|
||||
@@ -4176,9 +4172,9 @@ public interface Page extends AutoCloseable {
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* page.dragAndDrop("#source", "#target");
|
||||
* page.dragAndDrop("#source", '#target');
|
||||
* // or specify exact positions relative to the top-left corners of the elements:
|
||||
* page.dragAndDrop("#source", "#target", new Page.DragAndDropOptions()
|
||||
* page.dragAndDrop("#source", '#target', new Page.DragAndDropOptions()
|
||||
* .setSourcePosition(34, 7).setTargetPosition(10, 20));
|
||||
* }</pre>
|
||||
*
|
||||
@@ -4218,6 +4214,8 @@ public interface Page extends AutoCloseable {
|
||||
* // → true
|
||||
* page.evaluate("() => matchMedia('(prefers-color-scheme: light)').matches");
|
||||
* // → false
|
||||
* page.evaluate("() => matchMedia('(prefers-color-scheme: no-preference)').matches");
|
||||
* // → false
|
||||
* }</pre>
|
||||
*
|
||||
* @since v1.8
|
||||
@@ -4254,6 +4252,8 @@ public interface Page extends AutoCloseable {
|
||||
* // → true
|
||||
* page.evaluate("() => matchMedia('(prefers-color-scheme: light)').matches");
|
||||
* // → false
|
||||
* page.evaluate("() => matchMedia('(prefers-color-scheme: no-preference)').matches");
|
||||
* // → false
|
||||
* }</pre>
|
||||
*
|
||||
* @since v1.8
|
||||
@@ -4560,7 +4560,7 @@ public interface Page extends AutoCloseable {
|
||||
* public static void main(String[] args) {
|
||||
* try (Playwright playwright = Playwright.create()) {
|
||||
* BrowserType webkit = playwright.webkit();
|
||||
* Browser browser = webkit.launch(new BrowserType.LaunchOptions().setHeadless(false));
|
||||
* Browser browser = webkit.launch({ headless: false });
|
||||
* BrowserContext context = browser.newContext();
|
||||
* Page page = context.newPage();
|
||||
* page.exposeBinding("pageURL", (source, args) -> source.page().url());
|
||||
@@ -4610,7 +4610,7 @@ public interface Page extends AutoCloseable {
|
||||
* public static void main(String[] args) {
|
||||
* try (Playwright playwright = Playwright.create()) {
|
||||
* BrowserType webkit = playwright.webkit();
|
||||
* Browser browser = webkit.launch(new BrowserType.LaunchOptions().setHeadless(false));
|
||||
* Browser browser = webkit.launch({ headless: false });
|
||||
* BrowserContext context = browser.newContext();
|
||||
* Page page = context.newPage();
|
||||
* page.exposeBinding("pageURL", (source, args) -> source.page().url());
|
||||
@@ -4662,27 +4662,26 @@ public interface Page extends AutoCloseable {
|
||||
* public static void main(String[] args) {
|
||||
* try (Playwright playwright = Playwright.create()) {
|
||||
* BrowserType webkit = playwright.webkit();
|
||||
* Browser browser = webkit.launch(new BrowserType.LaunchOptions().setHeadless(false));
|
||||
* Browser browser = webkit.launch({ headless: false });
|
||||
* Page page = browser.newPage();
|
||||
* page.exposeFunction("sha256", args -> {
|
||||
* String text = (String) args[0];
|
||||
* MessageDigest crypto;
|
||||
* try {
|
||||
* String text = (String) args[0];
|
||||
* MessageDigest crypto = MessageDigest.getInstance("SHA-256");
|
||||
* byte[] token = crypto.digest(text.getBytes(StandardCharsets.UTF_8));
|
||||
* return Base64.getEncoder().encodeToString(token);
|
||||
* crypto = MessageDigest.getInstance("SHA-256");
|
||||
* } catch (NoSuchAlgorithmException e) {
|
||||
* return null;
|
||||
* }
|
||||
* byte[] token = crypto.digest(text.getBytes(StandardCharsets.UTF_8));
|
||||
* return Base64.getEncoder().encodeToString(token);
|
||||
* });
|
||||
* page.setContent(
|
||||
* "<script>\n" +
|
||||
* page.setContent("<script>\n" +
|
||||
* " async function onClick() {\n" +
|
||||
* " document.querySelector('div').textContent = await window.sha256('PLAYWRIGHT');\n" +
|
||||
* " }\n" +
|
||||
* "</script>\n" +
|
||||
* "<button onclick=\"onClick()\">Click me</button>\n" +
|
||||
* "<div></div>"
|
||||
* );
|
||||
* "<div></div>\n");
|
||||
* page.click("button");
|
||||
* }
|
||||
* }
|
||||
@@ -4758,7 +4757,7 @@ public interface Page extends AutoCloseable {
|
||||
* Frame frame = page.frame("frame-name");
|
||||
* }</pre>
|
||||
* <pre>{@code
|
||||
* Frame frame = page.frameByUrl(Pattern.compile(".*domain.*"));
|
||||
* Frame frame = page.frameByUrl(Pattern.compile(".*domain.*");
|
||||
* }</pre>
|
||||
*
|
||||
* @param name Frame name specified in the {@code iframe}'s {@code name} attribute.
|
||||
@@ -5164,19 +5163,19 @@ public interface Page extends AutoCloseable {
|
||||
* <p> You can locate by text substring, exact string, or a regular expression:
|
||||
* <pre>{@code
|
||||
* // Matches <span>
|
||||
* page.getByText("world");
|
||||
* page.getByText("world")
|
||||
*
|
||||
* // Matches first <div>
|
||||
* page.getByText("Hello world");
|
||||
* page.getByText("Hello world")
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true));
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
|
||||
*
|
||||
* // Matches both <div>s
|
||||
* page.getByText(Pattern.compile("Hello"));
|
||||
* page.getByText(Pattern.compile("Hello"))
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE));
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
|
||||
* }</pre>
|
||||
*
|
||||
* <p> <strong>Details</strong>
|
||||
@@ -5206,19 +5205,19 @@ public interface Page extends AutoCloseable {
|
||||
* <p> You can locate by text substring, exact string, or a regular expression:
|
||||
* <pre>{@code
|
||||
* // Matches <span>
|
||||
* page.getByText("world");
|
||||
* page.getByText("world")
|
||||
*
|
||||
* // Matches first <div>
|
||||
* page.getByText("Hello world");
|
||||
* page.getByText("Hello world")
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true));
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
|
||||
*
|
||||
* // Matches both <div>s
|
||||
* page.getByText(Pattern.compile("Hello"));
|
||||
* page.getByText(Pattern.compile("Hello"))
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE));
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
|
||||
* }</pre>
|
||||
*
|
||||
* <p> <strong>Details</strong>
|
||||
@@ -5246,19 +5245,19 @@ public interface Page extends AutoCloseable {
|
||||
* <p> You can locate by text substring, exact string, or a regular expression:
|
||||
* <pre>{@code
|
||||
* // Matches <span>
|
||||
* page.getByText("world");
|
||||
* page.getByText("world")
|
||||
*
|
||||
* // Matches first <div>
|
||||
* page.getByText("Hello world");
|
||||
* page.getByText("Hello world")
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true));
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
|
||||
*
|
||||
* // Matches both <div>s
|
||||
* page.getByText(Pattern.compile("Hello"));
|
||||
* page.getByText(Pattern.compile("Hello"))
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE));
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
|
||||
* }</pre>
|
||||
*
|
||||
* <p> <strong>Details</strong>
|
||||
@@ -5288,19 +5287,19 @@ public interface Page extends AutoCloseable {
|
||||
* <p> You can locate by text substring, exact string, or a regular expression:
|
||||
* <pre>{@code
|
||||
* // Matches <span>
|
||||
* page.getByText("world");
|
||||
* page.getByText("world")
|
||||
*
|
||||
* // Matches first <div>
|
||||
* page.getByText("Hello world");
|
||||
* page.getByText("Hello world")
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true));
|
||||
* page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
|
||||
*
|
||||
* // Matches both <div>s
|
||||
* page.getByText(Pattern.compile("Hello"));
|
||||
* page.getByText(Pattern.compile("Hello"))
|
||||
*
|
||||
* // Matches second <div>
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE));
|
||||
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
|
||||
* }</pre>
|
||||
*
|
||||
* <p> <strong>Details</strong>
|
||||
@@ -5809,6 +5808,8 @@ public interface Page extends AutoCloseable {
|
||||
/**
|
||||
* Returns the PDF buffer.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> Generating a pdf is currently only supported in Chromium headless.
|
||||
*
|
||||
* <p> {@code page.pdf()} generates a pdf of the page with {@code print} css media. To generate a pdf with {@code screen}
|
||||
* media, call {@link com.microsoft.playwright.Page#emulateMedia Page.emulateMedia()} before calling {@code page.pdf()}:
|
||||
*
|
||||
@@ -5867,6 +5868,8 @@ public interface Page extends AutoCloseable {
|
||||
/**
|
||||
* Returns the PDF buffer.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> Generating a pdf is currently only supported in Chromium headless.
|
||||
*
|
||||
* <p> {@code page.pdf()} generates a pdf of the page with {@code print} css media. To generate a pdf with {@code screen}
|
||||
* media, call {@link com.microsoft.playwright.Page#emulateMedia Page.emulateMedia()} before calling {@code page.pdf()}:
|
||||
*
|
||||
@@ -6077,24 +6080,24 @@ public interface Page extends AutoCloseable {
|
||||
* <p> An example that closes a "Sign up to the newsletter" dialog when it appears:
|
||||
* <pre>{@code
|
||||
* // Setup the handler.
|
||||
* page.addLocatorHandler(page.getByText("Sign up to the newsletter"), () -> {
|
||||
* page.addLocatorHandler(page.getByText("Sign up to the newsletter"), () => {
|
||||
* page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("No thanks")).click();
|
||||
* });
|
||||
*
|
||||
* // Write the test as usual.
|
||||
* page.navigate("https://example.com");
|
||||
* page.goto("https://example.com");
|
||||
* page.getByRole("button", Page.GetByRoleOptions().setName("Start here")).click();
|
||||
* }</pre>
|
||||
*
|
||||
* <p> An example that skips the "Confirm your security details" page when it is shown:
|
||||
* <pre>{@code
|
||||
* // Setup the handler.
|
||||
* page.addLocatorHandler(page.getByText("Confirm your security details"), () -> {
|
||||
* page.addLocatorHandler(page.getByText("Confirm your security details")), () => {
|
||||
* page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Remind me later")).click();
|
||||
* });
|
||||
*
|
||||
* // Write the test as usual.
|
||||
* page.navigate("https://example.com");
|
||||
* page.goto("https://example.com");
|
||||
* page.getByRole("button", Page.GetByRoleOptions().setName("Start here")).click();
|
||||
* }</pre>
|
||||
*
|
||||
@@ -6103,19 +6106,19 @@ public interface Page extends AutoCloseable {
|
||||
* handler does not hide the {@code <body>} element.
|
||||
* <pre>{@code
|
||||
* // Setup the handler.
|
||||
* page.addLocatorHandler(page.locator("body"), () -> {
|
||||
* page.addLocatorHandler(page.locator("body")), () => {
|
||||
* page.evaluate("window.removeObstructionsForTestIfNeeded()");
|
||||
* }, new Page.AddLocatorHandlerOptions().setNoWaitAfter(true));
|
||||
* }, new Page.AddLocatorHandlerOptions.setNoWaitAfter(true));
|
||||
*
|
||||
* // Write the test as usual.
|
||||
* page.navigate("https://example.com");
|
||||
* page.goto("https://example.com");
|
||||
* page.getByRole("button", Page.GetByRoleOptions().setName("Start here")).click();
|
||||
* }</pre>
|
||||
*
|
||||
* <p> Handler takes the original locator as an argument. You can also automatically remove the handler after a number of
|
||||
* invocations by setting {@code times}:
|
||||
* <pre>{@code
|
||||
* page.addLocatorHandler(page.getByLabel("Close"), locator -> {
|
||||
* page.addLocatorHandler(page.getByLabel("Close"), locator => {
|
||||
* locator.click();
|
||||
* }, new Page.AddLocatorHandlerOptions().setTimes(1));
|
||||
* }</pre>
|
||||
@@ -6169,24 +6172,24 @@ public interface Page extends AutoCloseable {
|
||||
* <p> An example that closes a "Sign up to the newsletter" dialog when it appears:
|
||||
* <pre>{@code
|
||||
* // Setup the handler.
|
||||
* page.addLocatorHandler(page.getByText("Sign up to the newsletter"), () -> {
|
||||
* page.addLocatorHandler(page.getByText("Sign up to the newsletter"), () => {
|
||||
* page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("No thanks")).click();
|
||||
* });
|
||||
*
|
||||
* // Write the test as usual.
|
||||
* page.navigate("https://example.com");
|
||||
* page.goto("https://example.com");
|
||||
* page.getByRole("button", Page.GetByRoleOptions().setName("Start here")).click();
|
||||
* }</pre>
|
||||
*
|
||||
* <p> An example that skips the "Confirm your security details" page when it is shown:
|
||||
* <pre>{@code
|
||||
* // Setup the handler.
|
||||
* page.addLocatorHandler(page.getByText("Confirm your security details"), () -> {
|
||||
* page.addLocatorHandler(page.getByText("Confirm your security details")), () => {
|
||||
* page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Remind me later")).click();
|
||||
* });
|
||||
*
|
||||
* // Write the test as usual.
|
||||
* page.navigate("https://example.com");
|
||||
* page.goto("https://example.com");
|
||||
* page.getByRole("button", Page.GetByRoleOptions().setName("Start here")).click();
|
||||
* }</pre>
|
||||
*
|
||||
@@ -6195,19 +6198,19 @@ public interface Page extends AutoCloseable {
|
||||
* handler does not hide the {@code <body>} element.
|
||||
* <pre>{@code
|
||||
* // Setup the handler.
|
||||
* page.addLocatorHandler(page.locator("body"), () -> {
|
||||
* page.addLocatorHandler(page.locator("body")), () => {
|
||||
* page.evaluate("window.removeObstructionsForTestIfNeeded()");
|
||||
* }, new Page.AddLocatorHandlerOptions().setNoWaitAfter(true));
|
||||
* }, new Page.AddLocatorHandlerOptions.setNoWaitAfter(true));
|
||||
*
|
||||
* // Write the test as usual.
|
||||
* page.navigate("https://example.com");
|
||||
* page.goto("https://example.com");
|
||||
* page.getByRole("button", Page.GetByRoleOptions().setName("Start here")).click();
|
||||
* }</pre>
|
||||
*
|
||||
* <p> Handler takes the original locator as an argument. You can also automatically remove the handler after a number of
|
||||
* invocations by setting {@code times}:
|
||||
* <pre>{@code
|
||||
* page.addLocatorHandler(page.getByLabel("Close"), locator -> {
|
||||
* page.addLocatorHandler(page.getByLabel("Close"), locator => {
|
||||
* locator.click();
|
||||
* }, new Page.AddLocatorHandlerOptions().setTimes(1));
|
||||
* }</pre>
|
||||
@@ -6638,8 +6641,8 @@ public interface Page extends AutoCloseable {
|
||||
* examples.
|
||||
* <pre>{@code
|
||||
* page.routeWebSocket("/ws", ws -> {
|
||||
* ws.onMessage(frame -> {
|
||||
* if ("request".equals(frame.text()))
|
||||
* ws.onMessage(message -> {
|
||||
* if ("request".equals(message))
|
||||
* ws.send("response");
|
||||
* });
|
||||
* });
|
||||
@@ -6663,8 +6666,8 @@ public interface Page extends AutoCloseable {
|
||||
* examples.
|
||||
* <pre>{@code
|
||||
* page.routeWebSocket("/ws", ws -> {
|
||||
* ws.onMessage(frame -> {
|
||||
* if ("request".equals(frame.text()))
|
||||
* ws.onMessage(message -> {
|
||||
* if ("request".equals(message))
|
||||
* ws.send("response");
|
||||
* });
|
||||
* });
|
||||
@@ -6688,8 +6691,8 @@ public interface Page extends AutoCloseable {
|
||||
* examples.
|
||||
* <pre>{@code
|
||||
* page.routeWebSocket("/ws", ws -> {
|
||||
* ws.onMessage(frame -> {
|
||||
* if ("request".equals(frame.text()))
|
||||
* ws.onMessage(message -> {
|
||||
* if ("request".equals(message))
|
||||
* ws.send("response");
|
||||
* });
|
||||
* });
|
||||
@@ -7190,7 +7193,7 @@ public interface Page extends AutoCloseable {
|
||||
* <p> <strong>NOTE:</strong> {@link com.microsoft.playwright.Page#setDefaultNavigationTimeout Page.setDefaultNavigationTimeout()} takes priority over
|
||||
* {@link com.microsoft.playwright.Page#setDefaultTimeout Page.setDefaultTimeout()}.
|
||||
*
|
||||
* @param timeout Maximum time in milliseconds. Pass {@code 0} to disable timeout.
|
||||
* @param timeout Maximum time in milliseconds
|
||||
* @since v1.8
|
||||
*/
|
||||
void setDefaultTimeout(double timeout);
|
||||
|
||||
@@ -363,8 +363,10 @@ public interface Route {
|
||||
*
|
||||
* <p> <strong>Details</strong>
|
||||
*
|
||||
* <p> The {@code headers} option applies to both the routed request and any redirects it initiates. However, {@code url},
|
||||
* {@code method}, and {@code postData} only apply to the original request and are not carried over to redirected requests.
|
||||
* <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 com.microsoft.playwright.Route#fetch Route.fetch()} and {@link
|
||||
* com.microsoft.playwright.Route#fulfill Route.fulfill()} instead.
|
||||
*
|
||||
* <p> {@link com.microsoft.playwright.Route#resume Route.resume()} will immediately send the request to the network, other
|
||||
* matching handlers won't be invoked. Use {@link com.microsoft.playwright.Route#fallback Route.fallback()} If you want
|
||||
@@ -391,8 +393,10 @@ public interface Route {
|
||||
*
|
||||
* <p> <strong>Details</strong>
|
||||
*
|
||||
* <p> The {@code headers} option applies to both the routed request and any redirects it initiates. However, {@code url},
|
||||
* {@code method}, and {@code postData} only apply to the original request and are not carried over to redirected requests.
|
||||
* <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 com.microsoft.playwright.Route#fetch Route.fetch()} and {@link
|
||||
* com.microsoft.playwright.Route#fulfill Route.fulfill()} instead.
|
||||
*
|
||||
* <p> {@link com.microsoft.playwright.Route#resume Route.resume()} will immediately send the request to the network, other
|
||||
* matching handlers won't be invoked. Use {@link com.microsoft.playwright.Route#fallback Route.fallback()} If you want
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.microsoft.playwright;
|
||||
|
||||
import com.microsoft.playwright.options.*;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
@@ -144,29 +143,6 @@ public interface Tracing {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
class GroupOptions {
|
||||
/**
|
||||
* Specifies a custom location for the group to be shown in the trace viewer. Defaults to the location of the {@link
|
||||
* com.microsoft.playwright.Tracing#group Tracing.group()} call.
|
||||
*/
|
||||
public Location location;
|
||||
|
||||
/**
|
||||
* Specifies a custom location for the group to be shown in the trace viewer. Defaults to the location of the {@link
|
||||
* com.microsoft.playwright.Tracing#group Tracing.group()} call.
|
||||
*/
|
||||
public GroupOptions setLocation(String file) {
|
||||
return setLocation(new Location(file));
|
||||
}
|
||||
/**
|
||||
* Specifies a custom location for the group to be shown in the trace viewer. Defaults to the location of the {@link
|
||||
* com.microsoft.playwright.Tracing#group Tracing.group()} call.
|
||||
*/
|
||||
public GroupOptions setLocation(Location location) {
|
||||
this.location = location;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
class StopOptions {
|
||||
/**
|
||||
* Export trace into the file with the given path.
|
||||
@@ -295,56 +271,6 @@ public interface Tracing {
|
||||
* @since v1.15
|
||||
*/
|
||||
void startChunk(StartChunkOptions options);
|
||||
/**
|
||||
* <strong>NOTE:</strong> Use {@code test.step} instead when available.
|
||||
*
|
||||
* <p> Creates a new group within the trace, assigning any subsequent API calls to this group, until {@link
|
||||
* com.microsoft.playwright.Tracing#groupEnd Tracing.groupEnd()} is called. Groups can be nested and will be visible in the
|
||||
* trace viewer.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* // All actions between group and groupEnd
|
||||
* // will be shown in the trace viewer as a group.
|
||||
* page.context().tracing().group("Open Playwright.dev > API");
|
||||
* page.navigate("https://playwright.dev/");
|
||||
* page.getByRole(AriaRole.LINK, new Page.GetByRoleOptions().setName("API")).click();
|
||||
* page.context().tracing().groupEnd();
|
||||
* }</pre>
|
||||
*
|
||||
* @param name Group name shown in the trace viewer.
|
||||
* @since v1.49
|
||||
*/
|
||||
default void group(String name) {
|
||||
group(name, null);
|
||||
}
|
||||
/**
|
||||
* <strong>NOTE:</strong> Use {@code test.step} instead when available.
|
||||
*
|
||||
* <p> Creates a new group within the trace, assigning any subsequent API calls to this group, until {@link
|
||||
* com.microsoft.playwright.Tracing#groupEnd Tracing.groupEnd()} is called. Groups can be nested and will be visible in the
|
||||
* trace viewer.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* // All actions between group and groupEnd
|
||||
* // will be shown in the trace viewer as a group.
|
||||
* page.context().tracing().group("Open Playwright.dev > API");
|
||||
* page.navigate("https://playwright.dev/");
|
||||
* page.getByRole(AriaRole.LINK, new Page.GetByRoleOptions().setName("API")).click();
|
||||
* page.context().tracing().groupEnd();
|
||||
* }</pre>
|
||||
*
|
||||
* @param name Group name shown in the trace viewer.
|
||||
* @since v1.49
|
||||
*/
|
||||
void group(String name, GroupOptions options);
|
||||
/**
|
||||
* Closes the last group created by {@link com.microsoft.playwright.Tracing#group Tracing.group()}.
|
||||
*
|
||||
* @since v1.49
|
||||
*/
|
||||
void groupEnd();
|
||||
/**
|
||||
* Stop tracing.
|
||||
*
|
||||
|
||||
@@ -31,8 +31,8 @@ import java.util.function.Consumer;
|
||||
* WebSocket. Here is an example that responds to a {@code "request"} with a {@code "response"}.
|
||||
* <pre>{@code
|
||||
* page.routeWebSocket("wss://example.com/ws", ws -> {
|
||||
* ws.onMessage(frame -> {
|
||||
* if ("request".equals(frame.text()))
|
||||
* ws.onMessage(message -> {
|
||||
* if ("request".equals(message))
|
||||
* ws.send("response");
|
||||
* });
|
||||
* });
|
||||
@@ -45,8 +45,8 @@ import java.util.function.Consumer;
|
||||
* <p> Here is another example that handles JSON messages:
|
||||
* <pre>{@code
|
||||
* page.routeWebSocket("wss://example.com/ws", ws -> {
|
||||
* ws.onMessage(frame -> {
|
||||
* JsonObject json = new JsonParser().parse(frame.text()).getAsJsonObject();
|
||||
* ws.onMessage(message -> {
|
||||
* JsonObject json = new JsonParser().parse(message).getAsJsonObject();
|
||||
* if ("question".equals(json.get("request").getAsString())) {
|
||||
* Map<String, String> result = new HashMap();
|
||||
* result.put("response", "answer");
|
||||
@@ -67,11 +67,11 @@ import java.util.function.Consumer;
|
||||
* <pre>{@code
|
||||
* page.routeWebSocket("/ws", ws -> {
|
||||
* WebSocketRoute server = ws.connectToServer();
|
||||
* ws.onMessage(frame -> {
|
||||
* if ("request".equals(frame.text()))
|
||||
* ws.onMessage(message -> {
|
||||
* if ("request".equals(message))
|
||||
* server.send("request2");
|
||||
* else
|
||||
* server.send(frame.text());
|
||||
* server.send(message);
|
||||
* });
|
||||
* });
|
||||
* }</pre>
|
||||
@@ -92,13 +92,13 @@ import java.util.function.Consumer;
|
||||
* <pre>{@code
|
||||
* page.routeWebSocket("/ws", ws -> {
|
||||
* WebSocketRoute server = ws.connectToServer();
|
||||
* ws.onMessage(frame -> {
|
||||
* if (!"blocked-from-the-page".equals(frame.text()))
|
||||
* server.send(frame.text());
|
||||
* ws.onMessage(message -> {
|
||||
* if (!"blocked-from-the-page".equals(message))
|
||||
* server.send(message);
|
||||
* });
|
||||
* server.onMessage(frame -> {
|
||||
* if (!"blocked-from-the-server".equals(frame.text()))
|
||||
* ws.send(frame.text());
|
||||
* server.onMessage(message -> {
|
||||
* if (!"blocked-from-the-server".equals(message))
|
||||
* ws.send(message);
|
||||
* });
|
||||
* });
|
||||
* }</pre>
|
||||
|
||||
+4
-4
@@ -21,15 +21,15 @@ 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.
|
||||
* <pre>{@code
|
||||
* // ...
|
||||
* ...
|
||||
* import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
|
||||
*
|
||||
* public class TestPage {
|
||||
* // ...
|
||||
* ...
|
||||
* @Test
|
||||
* void navigatesToLoginPage() {
|
||||
* // ...
|
||||
* APIResponse response = page.request().get("https://playwright.dev");
|
||||
* ...
|
||||
* APIResponse response = page.request().get('https://playwright.dev');
|
||||
* assertThat(response).isOK();
|
||||
* }
|
||||
* }
|
||||
|
||||
+47
-219
@@ -23,14 +23,14 @@ import com.microsoft.playwright.options.AriaRole;
|
||||
* The {@code LocatorAssertions} class provides assertion methods that can be used to make assertions about the {@code
|
||||
* Locator} state in the tests.
|
||||
* <pre>{@code
|
||||
* // ...
|
||||
* ...
|
||||
* import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
|
||||
*
|
||||
* public class TestLocator {
|
||||
* // ...
|
||||
* ...
|
||||
* @Test
|
||||
* void statusBecomesSubmitted() {
|
||||
* // ...
|
||||
* ...
|
||||
* page.getByRole(AriaRole.BUTTON).click();
|
||||
* assertThat(page.locator(".status")).hasText("Submitted");
|
||||
* }
|
||||
@@ -58,37 +58,16 @@ public interface LocatorAssertions {
|
||||
}
|
||||
}
|
||||
class IsCheckedOptions {
|
||||
/**
|
||||
* Provides state to assert for. Asserts for input to be checked by default. This option can't be used when {@code
|
||||
* indeterminate} is set to true.
|
||||
*/
|
||||
public Boolean checked;
|
||||
/**
|
||||
* Asserts that the element is in the indeterminate (mixed) state. Only supported for checkboxes and radio buttons. This
|
||||
* option can't be true when {@code checked} is provided.
|
||||
*/
|
||||
public Boolean indeterminate;
|
||||
/**
|
||||
* Time to retry the assertion for in milliseconds. Defaults to {@code 5000}.
|
||||
*/
|
||||
public Double timeout;
|
||||
|
||||
/**
|
||||
* Provides state to assert for. Asserts for input to be checked by default. This option can't be used when {@code
|
||||
* indeterminate} is set to true.
|
||||
*/
|
||||
public IsCheckedOptions setChecked(boolean checked) {
|
||||
this.checked = checked;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Asserts that the element is in the indeterminate (mixed) state. Only supported for checkboxes and radio buttons. This
|
||||
* option can't be true when {@code checked} is provided.
|
||||
*/
|
||||
public IsCheckedOptions setIndeterminate(boolean indeterminate) {
|
||||
this.indeterminate = indeterminate;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Time to retry the assertion for in milliseconds. Defaults to {@code 5000}.
|
||||
*/
|
||||
@@ -302,33 +281,6 @@ public interface LocatorAssertions {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
class HasAccessibleErrorMessageOptions {
|
||||
/**
|
||||
* Whether to perform case-insensitive match. {@code ignoreCase} option takes precedence over the corresponding regular
|
||||
* expression flag if specified.
|
||||
*/
|
||||
public Boolean ignoreCase;
|
||||
/**
|
||||
* Time to retry the assertion for in milliseconds. Defaults to {@code 5000}.
|
||||
*/
|
||||
public Double timeout;
|
||||
|
||||
/**
|
||||
* Whether to perform case-insensitive match. {@code ignoreCase} option takes precedence over the corresponding regular
|
||||
* expression flag if specified.
|
||||
*/
|
||||
public HasAccessibleErrorMessageOptions setIgnoreCase(boolean ignoreCase) {
|
||||
this.ignoreCase = ignoreCase;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Time to retry the assertion for in milliseconds. Defaults to {@code 5000}.
|
||||
*/
|
||||
public HasAccessibleErrorMessageOptions setTimeout(double timeout) {
|
||||
this.timeout = timeout;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
class HasAccessibleNameOptions {
|
||||
/**
|
||||
* Whether to perform case-insensitive match. {@code ignoreCase} option takes precedence over the corresponding regular
|
||||
@@ -533,20 +485,6 @@ public interface LocatorAssertions {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
class MatchesAriaSnapshotOptions {
|
||||
/**
|
||||
* Time to retry the assertion for in milliseconds. Defaults to {@code 5000}.
|
||||
*/
|
||||
public Double timeout;
|
||||
|
||||
/**
|
||||
* Time to retry the assertion for in milliseconds. Defaults to {@code 5000}.
|
||||
*/
|
||||
public MatchesAriaSnapshotOptions setTimeout(double timeout) {
|
||||
this.timeout = timeout;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Makes the assertion check for the opposite condition. For example, this code tests that the Locator doesn't contain text
|
||||
* {@code "error"}:
|
||||
@@ -1267,66 +1205,6 @@ public interface LocatorAssertions {
|
||||
* @since v1.44
|
||||
*/
|
||||
void hasAccessibleDescription(Pattern description, HasAccessibleDescriptionOptions options);
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element with a given <a
|
||||
* href="https://w3c.github.io/aria/#aria-errormessage">aria errormessage</a>.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* Locator locator = page.getByTestId("username-input");
|
||||
* assertThat(locator).hasAccessibleErrorMessage("Username is required.");
|
||||
* }</pre>
|
||||
*
|
||||
* @param errorMessage Expected accessible error message.
|
||||
* @since v1.50
|
||||
*/
|
||||
default void hasAccessibleErrorMessage(String errorMessage) {
|
||||
hasAccessibleErrorMessage(errorMessage, null);
|
||||
}
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element with a given <a
|
||||
* href="https://w3c.github.io/aria/#aria-errormessage">aria errormessage</a>.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* Locator locator = page.getByTestId("username-input");
|
||||
* assertThat(locator).hasAccessibleErrorMessage("Username is required.");
|
||||
* }</pre>
|
||||
*
|
||||
* @param errorMessage Expected accessible error message.
|
||||
* @since v1.50
|
||||
*/
|
||||
void hasAccessibleErrorMessage(String errorMessage, HasAccessibleErrorMessageOptions options);
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element with a given <a
|
||||
* href="https://w3c.github.io/aria/#aria-errormessage">aria errormessage</a>.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* Locator locator = page.getByTestId("username-input");
|
||||
* assertThat(locator).hasAccessibleErrorMessage("Username is required.");
|
||||
* }</pre>
|
||||
*
|
||||
* @param errorMessage Expected accessible error message.
|
||||
* @since v1.50
|
||||
*/
|
||||
default void hasAccessibleErrorMessage(Pattern errorMessage) {
|
||||
hasAccessibleErrorMessage(errorMessage, null);
|
||||
}
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element with a given <a
|
||||
* href="https://w3c.github.io/aria/#aria-errormessage">aria errormessage</a>.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* Locator locator = page.getByTestId("username-input");
|
||||
* assertThat(locator).hasAccessibleErrorMessage("Username is required.");
|
||||
* }</pre>
|
||||
*
|
||||
* @param errorMessage Expected accessible error message.
|
||||
* @since v1.50
|
||||
*/
|
||||
void hasAccessibleErrorMessage(Pattern errorMessage, HasAccessibleErrorMessageOptions options);
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element with a given <a
|
||||
* href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
|
||||
@@ -1444,18 +1322,16 @@ public interface LocatorAssertions {
|
||||
*/
|
||||
void hasAttribute(String name, Pattern value, HasAttributeOptions options);
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. When a string is provided, it must fully match
|
||||
* the element's {@code class} attribute. To match individual classes or perform partial matches, use a regular expression:
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. This needs to be a full match or using a
|
||||
* relaxed regular expression.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("(^|\\s)selected(\\s|$)"));
|
||||
* assertThat(page.locator("#component")).hasClass("middle selected row");
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("selected"));
|
||||
* assertThat(page.locator("#component")).hasClass("selected row");
|
||||
* }</pre>
|
||||
*
|
||||
* <p> When an array is passed, the method asserts that the list of elements located matches the corresponding list of expected
|
||||
* class values. Each element's class attribute is matched against the corresponding string or regular expression in the
|
||||
* array:
|
||||
* <p> Note that if array is passed as an expected value, entire lists of elements can be asserted:
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("list > .component")).hasClass(new String[] {"component", "component selected", "component"});
|
||||
* }</pre>
|
||||
@@ -1467,18 +1343,16 @@ public interface LocatorAssertions {
|
||||
hasClass(expected, null);
|
||||
}
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. When a string is provided, it must fully match
|
||||
* the element's {@code class} attribute. To match individual classes or perform partial matches, use a regular expression:
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. This needs to be a full match or using a
|
||||
* relaxed regular expression.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("(^|\\s)selected(\\s|$)"));
|
||||
* assertThat(page.locator("#component")).hasClass("middle selected row");
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("selected"));
|
||||
* assertThat(page.locator("#component")).hasClass("selected row");
|
||||
* }</pre>
|
||||
*
|
||||
* <p> When an array is passed, the method asserts that the list of elements located matches the corresponding list of expected
|
||||
* class values. Each element's class attribute is matched against the corresponding string or regular expression in the
|
||||
* array:
|
||||
* <p> Note that if array is passed as an expected value, entire lists of elements can be asserted:
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("list > .component")).hasClass(new String[] {"component", "component selected", "component"});
|
||||
* }</pre>
|
||||
@@ -1488,18 +1362,16 @@ public interface LocatorAssertions {
|
||||
*/
|
||||
void hasClass(String expected, HasClassOptions options);
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. When a string is provided, it must fully match
|
||||
* the element's {@code class} attribute. To match individual classes or perform partial matches, use a regular expression:
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. This needs to be a full match or using a
|
||||
* relaxed regular expression.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("(^|\\s)selected(\\s|$)"));
|
||||
* assertThat(page.locator("#component")).hasClass("middle selected row");
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("selected"));
|
||||
* assertThat(page.locator("#component")).hasClass("selected row");
|
||||
* }</pre>
|
||||
*
|
||||
* <p> When an array is passed, the method asserts that the list of elements located matches the corresponding list of expected
|
||||
* class values. Each element's class attribute is matched against the corresponding string or regular expression in the
|
||||
* array:
|
||||
* <p> Note that if array is passed as an expected value, entire lists of elements can be asserted:
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("list > .component")).hasClass(new String[] {"component", "component selected", "component"});
|
||||
* }</pre>
|
||||
@@ -1511,18 +1383,16 @@ public interface LocatorAssertions {
|
||||
hasClass(expected, null);
|
||||
}
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. When a string is provided, it must fully match
|
||||
* the element's {@code class} attribute. To match individual classes or perform partial matches, use a regular expression:
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. This needs to be a full match or using a
|
||||
* relaxed regular expression.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("(^|\\s)selected(\\s|$)"));
|
||||
* assertThat(page.locator("#component")).hasClass("middle selected row");
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("selected"));
|
||||
* assertThat(page.locator("#component")).hasClass("selected row");
|
||||
* }</pre>
|
||||
*
|
||||
* <p> When an array is passed, the method asserts that the list of elements located matches the corresponding list of expected
|
||||
* class values. Each element's class attribute is matched against the corresponding string or regular expression in the
|
||||
* array:
|
||||
* <p> Note that if array is passed as an expected value, entire lists of elements can be asserted:
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("list > .component")).hasClass(new String[] {"component", "component selected", "component"});
|
||||
* }</pre>
|
||||
@@ -1532,18 +1402,16 @@ public interface LocatorAssertions {
|
||||
*/
|
||||
void hasClass(Pattern expected, HasClassOptions options);
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. When a string is provided, it must fully match
|
||||
* the element's {@code class} attribute. To match individual classes or perform partial matches, use a regular expression:
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. This needs to be a full match or using a
|
||||
* relaxed regular expression.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("(^|\\s)selected(\\s|$)"));
|
||||
* assertThat(page.locator("#component")).hasClass("middle selected row");
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("selected"));
|
||||
* assertThat(page.locator("#component")).hasClass("selected row");
|
||||
* }</pre>
|
||||
*
|
||||
* <p> When an array is passed, the method asserts that the list of elements located matches the corresponding list of expected
|
||||
* class values. Each element's class attribute is matched against the corresponding string or regular expression in the
|
||||
* array:
|
||||
* <p> Note that if array is passed as an expected value, entire lists of elements can be asserted:
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("list > .component")).hasClass(new String[] {"component", "component selected", "component"});
|
||||
* }</pre>
|
||||
@@ -1555,18 +1423,16 @@ public interface LocatorAssertions {
|
||||
hasClass(expected, null);
|
||||
}
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. When a string is provided, it must fully match
|
||||
* the element's {@code class} attribute. To match individual classes or perform partial matches, use a regular expression:
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. This needs to be a full match or using a
|
||||
* relaxed regular expression.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("(^|\\s)selected(\\s|$)"));
|
||||
* assertThat(page.locator("#component")).hasClass("middle selected row");
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("selected"));
|
||||
* assertThat(page.locator("#component")).hasClass("selected row");
|
||||
* }</pre>
|
||||
*
|
||||
* <p> When an array is passed, the method asserts that the list of elements located matches the corresponding list of expected
|
||||
* class values. Each element's class attribute is matched against the corresponding string or regular expression in the
|
||||
* array:
|
||||
* <p> Note that if array is passed as an expected value, entire lists of elements can be asserted:
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("list > .component")).hasClass(new String[] {"component", "component selected", "component"});
|
||||
* }</pre>
|
||||
@@ -1576,18 +1442,16 @@ public interface LocatorAssertions {
|
||||
*/
|
||||
void hasClass(String[] expected, HasClassOptions options);
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. When a string is provided, it must fully match
|
||||
* the element's {@code class} attribute. To match individual classes or perform partial matches, use a regular expression:
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. This needs to be a full match or using a
|
||||
* relaxed regular expression.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("(^|\\s)selected(\\s|$)"));
|
||||
* assertThat(page.locator("#component")).hasClass("middle selected row");
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("selected"));
|
||||
* assertThat(page.locator("#component")).hasClass("selected row");
|
||||
* }</pre>
|
||||
*
|
||||
* <p> When an array is passed, the method asserts that the list of elements located matches the corresponding list of expected
|
||||
* class values. Each element's class attribute is matched against the corresponding string or regular expression in the
|
||||
* array:
|
||||
* <p> Note that if array is passed as an expected value, entire lists of elements can be asserted:
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("list > .component")).hasClass(new String[] {"component", "component selected", "component"});
|
||||
* }</pre>
|
||||
@@ -1599,18 +1463,16 @@ public interface LocatorAssertions {
|
||||
hasClass(expected, null);
|
||||
}
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. When a string is provided, it must fully match
|
||||
* the element's {@code class} attribute. To match individual classes or perform partial matches, use a regular expression:
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. This needs to be a full match or using a
|
||||
* relaxed regular expression.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("(^|\\s)selected(\\s|$)"));
|
||||
* assertThat(page.locator("#component")).hasClass("middle selected row");
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("selected"));
|
||||
* assertThat(page.locator("#component")).hasClass("selected row");
|
||||
* }</pre>
|
||||
*
|
||||
* <p> When an array is passed, the method asserts that the list of elements located matches the corresponding list of expected
|
||||
* class values. Each element's class attribute is matched against the corresponding string or regular expression in the
|
||||
* array:
|
||||
* <p> Note that if array is passed as an expected value, entire lists of elements can be asserted:
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("list > .component")).hasClass(new String[] {"component", "component selected", "component"});
|
||||
* }</pre>
|
||||
@@ -2235,7 +2097,7 @@ public interface LocatorAssertions {
|
||||
*
|
||||
* <p> For example, given the following element:
|
||||
* <pre>{@code
|
||||
* page.locator("id=favorite-colors").selectOption(new String[]{"R", "G"});
|
||||
* page.locator("id=favorite-colors").selectOption(["R", "G"]);
|
||||
* assertThat(page.locator("id=favorite-colors")).hasValues(new Pattern[] { Pattern.compile("R"), Pattern.compile("G") });
|
||||
* }</pre>
|
||||
*
|
||||
@@ -2253,7 +2115,7 @@ public interface LocatorAssertions {
|
||||
*
|
||||
* <p> For example, given the following element:
|
||||
* <pre>{@code
|
||||
* page.locator("id=favorite-colors").selectOption(new String[]{"R", "G"});
|
||||
* page.locator("id=favorite-colors").selectOption(["R", "G"]);
|
||||
* assertThat(page.locator("id=favorite-colors")).hasValues(new Pattern[] { Pattern.compile("R"), Pattern.compile("G") });
|
||||
* }</pre>
|
||||
*
|
||||
@@ -2269,7 +2131,7 @@ public interface LocatorAssertions {
|
||||
*
|
||||
* <p> For example, given the following element:
|
||||
* <pre>{@code
|
||||
* page.locator("id=favorite-colors").selectOption(new String[]{"R", "G"});
|
||||
* page.locator("id=favorite-colors").selectOption(["R", "G"]);
|
||||
* assertThat(page.locator("id=favorite-colors")).hasValues(new Pattern[] { Pattern.compile("R"), Pattern.compile("G") });
|
||||
* }</pre>
|
||||
*
|
||||
@@ -2287,7 +2149,7 @@ public interface LocatorAssertions {
|
||||
*
|
||||
* <p> For example, given the following element:
|
||||
* <pre>{@code
|
||||
* page.locator("id=favorite-colors").selectOption(new String[]{"R", "G"});
|
||||
* page.locator("id=favorite-colors").selectOption(["R", "G"]);
|
||||
* assertThat(page.locator("id=favorite-colors")).hasValues(new Pattern[] { Pattern.compile("R"), Pattern.compile("G") });
|
||||
* }</pre>
|
||||
*
|
||||
@@ -2295,39 +2157,5 @@ public interface LocatorAssertions {
|
||||
* @since v1.23
|
||||
*/
|
||||
void hasValues(Pattern[] values, HasValuesOptions options);
|
||||
/**
|
||||
* Asserts that the target element matches the given <a
|
||||
* href="https://playwright.dev/java/docs/aria-snapshots">accessibility snapshot</a>.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* page.navigate("https://demo.playwright.dev/todomvc/");
|
||||
* assertThat(page.locator("body")).matchesAriaSnapshot("""
|
||||
* - heading "todos"
|
||||
* - textbox "What needs to be done?"
|
||||
* """);
|
||||
* }</pre>
|
||||
*
|
||||
* @since v1.49
|
||||
*/
|
||||
default void matchesAriaSnapshot(String expected) {
|
||||
matchesAriaSnapshot(expected, null);
|
||||
}
|
||||
/**
|
||||
* Asserts that the target element matches the given <a
|
||||
* href="https://playwright.dev/java/docs/aria-snapshots">accessibility snapshot</a>.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* page.navigate("https://demo.playwright.dev/todomvc/");
|
||||
* assertThat(page.locator("body")).matchesAriaSnapshot("""
|
||||
* - heading "todos"
|
||||
* - textbox "What needs to be done?"
|
||||
* """);
|
||||
* }</pre>
|
||||
*
|
||||
* @since v1.49
|
||||
*/
|
||||
void matchesAriaSnapshot(String expected, MatchesAriaSnapshotOptions options);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,14 +22,14 @@ 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.
|
||||
* <pre>{@code
|
||||
* // ...
|
||||
* ...
|
||||
* import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
|
||||
*
|
||||
* public class TestPage {
|
||||
* // ...
|
||||
* ...
|
||||
* @Test
|
||||
* void navigatesToLoginPage() {
|
||||
* // ...
|
||||
* ...
|
||||
* page.getByText("Sign in").click();
|
||||
* assertThat(page).hasURL(Pattern.compile(".*\/login"));
|
||||
* }
|
||||
|
||||
+3
-2
@@ -30,13 +30,14 @@ import com.microsoft.playwright.impl.PageAssertionsImpl;
|
||||
*
|
||||
* <p> Consider the following example:
|
||||
* <pre>{@code
|
||||
* ...
|
||||
* import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
|
||||
*
|
||||
* public class TestExample {
|
||||
* // ...
|
||||
* ...
|
||||
* @Test
|
||||
* void statusBecomesSubmitted() {
|
||||
* // ...
|
||||
* ...
|
||||
* page.locator("#submit-button").click();
|
||||
* assertThat(page.locator(".status")).hasText("Submitted");
|
||||
* }
|
||||
|
||||
@@ -47,6 +47,7 @@ class AssertionsBase {
|
||||
options = new FrameExpectOptions();
|
||||
}
|
||||
options.expectedText = expectedText;
|
||||
options.isNot = isNot;
|
||||
expectImpl(expression, options, expected, message);
|
||||
}
|
||||
|
||||
@@ -54,14 +55,13 @@ class AssertionsBase {
|
||||
if (expectOptions.timeout == null) {
|
||||
expectOptions.timeout = AssertionsTimeout.defaultTimeout;
|
||||
}
|
||||
expectOptions.isNot = isNot;
|
||||
if (isNot) {
|
||||
if (expectOptions.isNot) {
|
||||
message = message.replace("expected to", "expected not to");
|
||||
}
|
||||
FrameExpectResult result = actualLocator.expect(expression, expectOptions);
|
||||
if (result.matches == isNot) {
|
||||
Object actual = result.received == null ? null : Serialization.deserialize(result.received);
|
||||
String log = (result.log == null) ? "" : String.join("\n", result.log);
|
||||
String log = String.join("\n", result.log);
|
||||
if (!log.isEmpty()) {
|
||||
log = "\nCall log:\n" + log;
|
||||
}
|
||||
|
||||
@@ -12,24 +12,18 @@ class ClockImpl implements Clock {
|
||||
this.browserContext = browserContext;
|
||||
}
|
||||
|
||||
private void sendMessageWithLogging(String method, JsonObject params) {
|
||||
String capitalizedMethod = method.substring(0, 1).toUpperCase() + method.substring(1);
|
||||
browserContext.withLogging("Clock." + method,
|
||||
() -> browserContext.sendMessage("clock" + capitalizedMethod, params));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fastForward(long ticks) {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty("ticksNumber", ticks);
|
||||
sendMessageWithLogging("fastForward", params);
|
||||
browserContext.sendMessage("clockFastForward", params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fastForward(String ticks) {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty("ticksString", ticks);
|
||||
sendMessageWithLogging("fastForward", params);
|
||||
browserContext.sendMessage("clockFastForward", params);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -38,89 +32,89 @@ class ClockImpl implements Clock {
|
||||
if (options != null) {
|
||||
parseTime(options.time, params);
|
||||
}
|
||||
sendMessageWithLogging("install", params);
|
||||
browserContext.sendMessage("clockInstall", params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runFor(long ticks) {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty("ticksNumber", ticks);
|
||||
sendMessageWithLogging("runFor", params);
|
||||
browserContext.sendMessage("clockRunFor", params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runFor(String ticks) {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty("ticksString", ticks);
|
||||
sendMessageWithLogging("runFor", params);
|
||||
browserContext.sendMessage("clockRunFor", params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pauseAt(long time) {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty("timeNumber", time);
|
||||
sendMessageWithLogging("pauseAt", params);
|
||||
browserContext.sendMessage("clockPauseAt", params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pauseAt(String time) {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty("timeString", time);
|
||||
sendMessageWithLogging("pauseAt", params);
|
||||
browserContext.sendMessage("clockPauseAt", params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pauseAt(Date time) {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty("timeNumber", time.getTime());
|
||||
sendMessageWithLogging("pauseAt", params);
|
||||
browserContext.sendMessage("clockPauseAt", params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resume() {
|
||||
sendMessageWithLogging("resume", new JsonObject());
|
||||
browserContext.sendMessage("clockResume");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFixedTime(long time) {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty("timeNumber", time);
|
||||
sendMessageWithLogging("setFixedTime", params);
|
||||
browserContext.sendMessage("clockSetFixedTime", params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFixedTime(String time) {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty("timeString", time);
|
||||
sendMessageWithLogging("setFixedTime", params);
|
||||
browserContext.sendMessage("clockSetFixedTime", params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFixedTime(Date time) {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty("timeNumber", time.getTime());
|
||||
sendMessageWithLogging("setFixedTime", params);
|
||||
browserContext.sendMessage("clockSetFixedTime", params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSystemTime(long time) {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty("timeNumber", time);
|
||||
sendMessageWithLogging("setSystemTime", params);
|
||||
browserContext.sendMessage("clockSetSystemTime", params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSystemTime(String time) {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty("timeString", time);
|
||||
sendMessageWithLogging("setSystemTime", params);
|
||||
browserContext.sendMessage("clockSetSystemTime", params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSystemTime(Date time) {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty("timeNumber", time.getTime());
|
||||
sendMessageWithLogging("setSystemTime", params);
|
||||
browserContext.sendMessage("clockSetSystemTime", params);
|
||||
}
|
||||
|
||||
private static void parseTime(Object time, JsonObject params) {
|
||||
|
||||
@@ -22,9 +22,7 @@ import com.microsoft.playwright.options.AriaRole;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.microsoft.playwright.impl.Serialization.serializeArgument;
|
||||
@@ -90,7 +88,6 @@ public class LocatorAssertionsImpl extends AssertionsBase implements LocatorAsse
|
||||
ExpectedTextValue expected = new ExpectedTextValue();
|
||||
expected.string = description;
|
||||
expected.ignoreCase = shouldIgnoreCase(options);
|
||||
expected.normalizeWhiteSpace = true;
|
||||
expectImpl("to.have.accessible.description", expected, description, "Locator expected to have accessible description", convertType(options, FrameExpectOptions.class));
|
||||
}
|
||||
|
||||
@@ -98,33 +95,14 @@ public class LocatorAssertionsImpl extends AssertionsBase implements LocatorAsse
|
||||
public void hasAccessibleDescription(Pattern pattern, HasAccessibleDescriptionOptions options) {
|
||||
ExpectedTextValue expected = expectedRegex(pattern);
|
||||
expected.ignoreCase = shouldIgnoreCase(options);
|
||||
expected.normalizeWhiteSpace = true;
|
||||
expectImpl("to.have.accessible.description", expected, pattern, "Locator expected to have accessible description", convertType(options, FrameExpectOptions.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hasAccessibleErrorMessage(String errorMessage, HasAccessibleErrorMessageOptions options) {
|
||||
ExpectedTextValue expected = new ExpectedTextValue();
|
||||
expected.string = errorMessage;
|
||||
expected.ignoreCase = shouldIgnoreCase(options);
|
||||
expected.normalizeWhiteSpace = true;
|
||||
expectImpl("to.have.accessible.error.message", expected, errorMessage, "Locator expected to have accessible error message", convertType(options, FrameExpectOptions.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hasAccessibleErrorMessage(Pattern pattern, HasAccessibleErrorMessageOptions options) {
|
||||
ExpectedTextValue expected = expectedRegex(pattern);
|
||||
expected.ignoreCase = shouldIgnoreCase(options);
|
||||
expected.normalizeWhiteSpace = true;
|
||||
expectImpl("to.have.accessible.error.message", expected, pattern, "Locator expected to have accessible error message", convertType(options, FrameExpectOptions.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hasAccessibleName(String name, HasAccessibleNameOptions options) {
|
||||
ExpectedTextValue expected = new ExpectedTextValue();
|
||||
expected.string = name;
|
||||
expected.ignoreCase = shouldIgnoreCase(options);
|
||||
expected.normalizeWhiteSpace = true;
|
||||
expectImpl("to.have.accessible.name", expected, name, "Locator expected to have accessible name", convertType(options, FrameExpectOptions.class));
|
||||
}
|
||||
|
||||
@@ -132,7 +110,6 @@ public class LocatorAssertionsImpl extends AssertionsBase implements LocatorAsse
|
||||
public void hasAccessibleName(Pattern pattern, HasAccessibleNameOptions options) {
|
||||
ExpectedTextValue expected = expectedRegex(pattern);
|
||||
expected.ignoreCase = shouldIgnoreCase(options);
|
||||
expected.normalizeWhiteSpace = true;
|
||||
expectImpl("to.have.accessible.name", expected, pattern, "Locator expected to have accessible name", convertType(options, FrameExpectOptions.class));
|
||||
}
|
||||
|
||||
@@ -349,42 +326,12 @@ public class LocatorAssertionsImpl extends AssertionsBase implements LocatorAsse
|
||||
expectImpl("to.have.values", list, patterns, "Locator expected to have values matching regex", convertType(options, FrameExpectOptions.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void matchesAriaSnapshot(String expected, MatchesAriaSnapshotOptions snapshotOptions) {
|
||||
if (snapshotOptions == null) {
|
||||
snapshotOptions = new MatchesAriaSnapshotOptions();
|
||||
}
|
||||
FrameExpectOptions options = convertType(snapshotOptions, FrameExpectOptions.class);
|
||||
options.expectedValue = serializeArgument(expected);
|
||||
expectImpl("to.match.aria", options, expected,"Locator expected to match Aria snapshot");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void isChecked(IsCheckedOptions options) {
|
||||
if (options == null) {
|
||||
options = new IsCheckedOptions();
|
||||
}
|
||||
|
||||
Map<String, Boolean> expectedValue = new HashMap<>();
|
||||
if (options.indeterminate != null) {
|
||||
expectedValue.put("indeterminate", options.indeterminate);
|
||||
}
|
||||
if (options.checked != null) {
|
||||
expectedValue.put("checked", options.checked);
|
||||
}
|
||||
|
||||
String expected;
|
||||
if (options.indeterminate != null && options.indeterminate) {
|
||||
expected = "indeterminate";
|
||||
} else {
|
||||
boolean unchecked = options.checked != null && !options.checked;
|
||||
expected = unchecked ? "unchecked" : "checked";
|
||||
}
|
||||
|
||||
String message = "Locator expected to be";
|
||||
FrameExpectOptions expectOptions = convertType(options, FrameExpectOptions.class);
|
||||
expectOptions.expectedValue = serializeArgument(expectedValue);
|
||||
expectImpl("to.be.checked", expectOptions, expected, message);
|
||||
boolean unchecked = options != null && options.checked != null && !options.checked;
|
||||
String expression = unchecked ? "to.be.unchecked" : "to.be.checked";
|
||||
String message = "Locator expected to be " + (unchecked ? "un" : "") + "checked";
|
||||
expectTrue(expression, message, convertType(options, FrameExpectOptions.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -119,21 +119,6 @@ class LocatorImpl implements Locator {
|
||||
return new LocatorImpl(frame, selector + " >> internal:and=" + gson().toJson(other.selector), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String ariaSnapshot(AriaSnapshotOptions options) {
|
||||
return frame.withLogging("Locator.ariaSnapshot", () -> ariaSnapshotImpl(options));
|
||||
}
|
||||
|
||||
private String ariaSnapshotImpl(AriaSnapshotOptions options) {
|
||||
if (options == null) {
|
||||
options = new AriaSnapshotOptions();
|
||||
}
|
||||
JsonObject params = gson().toJsonTree(options).getAsJsonObject();
|
||||
params.addProperty("selector", selector);
|
||||
JsonObject result = frame.sendMessage("ariaSnapshot", params).getAsJsonObject();
|
||||
return result.get("snapshot").getAsString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void blur(BlurOptions options) {
|
||||
frame.withLogging("Locator.blur", () -> blurImpl(options));
|
||||
@@ -665,6 +650,9 @@ class LocatorImpl implements Locator {
|
||||
}
|
||||
|
||||
private FrameExpectResult expectImpl(String expression, FrameExpectOptions options) {
|
||||
if (options == null) {
|
||||
options = new FrameExpectOptions();
|
||||
}
|
||||
JsonObject params = gson().toJsonTree(options).getAsJsonObject();
|
||||
params.addProperty("selector", selector);
|
||||
params.addProperty("expression", expression);
|
||||
|
||||
@@ -53,7 +53,6 @@ public class RequestImpl extends ChannelOwner implements Request {
|
||||
|
||||
RequestImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
markAsInternalType();
|
||||
|
||||
if (initializer.has("redirectedFrom")) {
|
||||
redirectedFrom = connection.getExistingObject(initializer.getAsJsonObject("redirectedFrom").get("guid").getAsString());
|
||||
|
||||
@@ -40,7 +40,6 @@ public class ResponseImpl extends ChannelOwner implements Response {
|
||||
|
||||
ResponseImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
markAsInternalType();
|
||||
headers = new RawHeaders(asList(gson().fromJson(initializer.getAsJsonArray("headers"), HttpHeader[].class)));
|
||||
request = connection.getExistingObject(initializer.getAsJsonObject("request").get("guid").getAsString());
|
||||
request.timing = gson().fromJson(initializer.get("timing"), Timing.class);
|
||||
|
||||
@@ -86,25 +86,6 @@ class TracingImpl extends ChannelOwner implements Tracing {
|
||||
tracingStartChunk(options.name, options.title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void group(String name, GroupOptions options) {
|
||||
withLogging("Tracing.group", () -> groupImpl(name, options));
|
||||
}
|
||||
|
||||
private void groupImpl(String name, GroupOptions options) {
|
||||
if (options == null) {
|
||||
options = new GroupOptions();
|
||||
}
|
||||
JsonObject params = gson().toJsonTree(options).getAsJsonObject();
|
||||
params.addProperty("name", name);
|
||||
sendMessage("tracingGroup", params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void groupEnd() {
|
||||
withLogging("Tracing.groupEnd", () -> sendMessage("tracingGroupEnd"));
|
||||
}
|
||||
|
||||
private void tracingStartChunk(String name, String title) {
|
||||
JsonObject params = new JsonObject();
|
||||
if (name != null) {
|
||||
|
||||
@@ -16,12 +16,13 @@
|
||||
|
||||
package com.microsoft.playwright.impl;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.microsoft.playwright.PlaywrightException;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -29,14 +30,20 @@ import static com.microsoft.playwright.impl.Utils.globToRegex;
|
||||
import static com.microsoft.playwright.impl.Utils.toJsRegexFlags;
|
||||
|
||||
class UrlMatcher {
|
||||
private final String baseURL;
|
||||
public final String glob;
|
||||
public final Pattern pattern;
|
||||
public final Predicate<String> predicate;
|
||||
final Object rawSource;
|
||||
private final Predicate<String> predicate;
|
||||
|
||||
private static Predicate<String> toPredicate(Pattern pattern) {
|
||||
return s -> pattern.matcher(s).find();
|
||||
}
|
||||
|
||||
static UrlMatcher any() {
|
||||
return new UrlMatcher((Object) null, null);
|
||||
}
|
||||
|
||||
static UrlMatcher forOneOf(URL baseUrl, Object object) {
|
||||
if (object == null) {
|
||||
return new UrlMatcher(null, null, null, null);
|
||||
return UrlMatcher.any();
|
||||
}
|
||||
if (object instanceof String) {
|
||||
return new UrlMatcher(baseUrl, (String) object);
|
||||
@@ -51,77 +58,34 @@ class UrlMatcher {
|
||||
}
|
||||
|
||||
static String resolveUrl(URL baseUrl, String spec) {
|
||||
return resolveUrl(baseUrl.toString(), spec);
|
||||
}
|
||||
|
||||
private static String resolveUrl(String baseUrl, String spec) {
|
||||
if (baseUrl == null) {
|
||||
return spec;
|
||||
}
|
||||
try {
|
||||
// Join using URI instead of URL since URL doesn't handle ws(s) protocols.
|
||||
return new URI(baseUrl).resolve(spec).toString();
|
||||
} catch (URISyntaxException e) {
|
||||
return new URL(baseUrl, spec).toString();
|
||||
} catch (MalformedURLException e) {
|
||||
return spec;
|
||||
}
|
||||
}
|
||||
|
||||
private static String normaliseUrl(String spec) {
|
||||
try {
|
||||
// Align with the Node.js URL parser which automatically adds a slash to the path if it is empty.
|
||||
URI url = new URI(spec);
|
||||
if (url.getScheme() != null &&
|
||||
Arrays.asList("http", "https", "ws", "wss").contains(url.getScheme()) &&
|
||||
url.getPath().isEmpty()) {
|
||||
return new URI(url.getScheme(), url.getAuthority(), "/", url.getQuery(), url.getFragment()).toString();
|
||||
}
|
||||
return url.toString();
|
||||
} catch (URISyntaxException e) {
|
||||
return spec;
|
||||
}
|
||||
}
|
||||
|
||||
UrlMatcher(URL baseURL, String glob) {
|
||||
this(baseURL, glob, null, null);
|
||||
UrlMatcher(URL base, String url) {
|
||||
this(url, toPredicate(Pattern.compile(globToRegex(resolveUrl(base, url)))).or(s -> url == null || url.equals(s)));
|
||||
}
|
||||
|
||||
UrlMatcher(Pattern pattern) {
|
||||
this(null, null, pattern, null);
|
||||
this(pattern, toPredicate(pattern));
|
||||
}
|
||||
|
||||
UrlMatcher(Predicate<String> predicate) {
|
||||
this(null, null, null, predicate);
|
||||
this(predicate, predicate);
|
||||
}
|
||||
|
||||
private UrlMatcher(URL baseURL, String glob, Pattern pattern, Predicate<String> predicate) {
|
||||
this.baseURL = baseURL != null ? baseURL.toString() : null;
|
||||
this.glob = glob;
|
||||
this.pattern = pattern;
|
||||
private UrlMatcher(Object rawSource, Predicate<String> predicate) {
|
||||
this.rawSource = rawSource;
|
||||
this.predicate = predicate;
|
||||
}
|
||||
|
||||
boolean test(String value) {
|
||||
return testImpl(baseURL, pattern, predicate, glob, value);
|
||||
}
|
||||
|
||||
private static boolean testImpl(String baseURL, Pattern pattern, Predicate<String> predicate, String glob, String value) {
|
||||
if (pattern != null) {
|
||||
return pattern.matcher(value).find();
|
||||
}
|
||||
if (predicate != null) {
|
||||
return predicate.test(value);
|
||||
}
|
||||
if (glob != null) {
|
||||
if (!glob.startsWith("*")) {
|
||||
// Allow http(s) baseURL to match ws(s) urls.
|
||||
if (baseURL != null && Pattern.compile("^https?://").matcher(baseURL).find() && Pattern.compile("^wss?://").matcher(value).find()) {
|
||||
baseURL = baseURL.replaceFirst("^http", "ws");
|
||||
}
|
||||
glob = normaliseUrl(resolveUrl(baseURL, glob));
|
||||
}
|
||||
return Pattern.compile(globToRegex(glob)).matcher(value).find();
|
||||
}
|
||||
return true;
|
||||
return predicate == null || predicate.test(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -129,38 +93,25 @@ class UrlMatcher {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
UrlMatcher that = (UrlMatcher) o;
|
||||
if (pattern != null) {
|
||||
return that.pattern != null && pattern.pattern().equals(that.pattern.pattern()) && pattern.flags() == that.pattern.flags();
|
||||
if (rawSource instanceof Pattern && that.rawSource instanceof Pattern) {
|
||||
Pattern a = (Pattern) rawSource;
|
||||
Pattern b = (Pattern) that.rawSource;
|
||||
return a.pattern().equals(b.pattern()) && a.flags() == b.flags();
|
||||
}
|
||||
if (predicate != null) {
|
||||
return predicate.equals(that.predicate);
|
||||
}
|
||||
if (glob != null) {
|
||||
return glob.equals(that.glob);
|
||||
}
|
||||
return that.pattern == null && that.predicate == null && that.glob == null;
|
||||
return Objects.equals(rawSource, that.rawSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if (pattern != null) {
|
||||
return pattern.hashCode();
|
||||
}
|
||||
if (predicate != null) {
|
||||
return predicate.hashCode();
|
||||
}
|
||||
if (glob != null) {
|
||||
return glob.hashCode();
|
||||
}
|
||||
return 0;
|
||||
return Objects.hash(rawSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (pattern != null)
|
||||
return String.format("<regex pattern=\"%s\" flags=\"%s\">", pattern.pattern(), toJsRegexFlags(pattern));
|
||||
if (this.predicate != null)
|
||||
return "<predicate>";
|
||||
return String.format("<glob pattern=\"%s\">", glob);
|
||||
if (rawSource == null)
|
||||
return "<any>";
|
||||
if (rawSource instanceof Predicate)
|
||||
return "matching predicate";
|
||||
return rawSource.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -462,11 +462,13 @@ public class Utils {
|
||||
JsonArray jsonPatterns = new JsonArray();
|
||||
for (UrlMatcher matcher: matchers) {
|
||||
JsonObject jsonPattern = new JsonObject();
|
||||
if (matcher.glob != null) {
|
||||
jsonPattern.addProperty("glob", matcher.glob);
|
||||
} else if (matcher.pattern != null) {
|
||||
jsonPattern.addProperty("regexSource", matcher.pattern.pattern());
|
||||
jsonPattern.addProperty("regexFlags", toJsRegexFlags(matcher.pattern));
|
||||
Object urlFilter = 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", "**/*");
|
||||
|
||||
@@ -20,7 +20,6 @@ import java.util.Collection;
|
||||
|
||||
class WaitableRace<T> implements Waitable<T> {
|
||||
private final Collection<Waitable<T>> waitables;
|
||||
private Waitable<T> firstReady;
|
||||
|
||||
WaitableRace(Collection<Waitable<T>> waitables) {
|
||||
this.waitables = waitables;
|
||||
@@ -28,12 +27,8 @@ class WaitableRace<T> implements Waitable<T> {
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
if (firstReady != null) {
|
||||
return true;
|
||||
}
|
||||
for (Waitable<T> w : waitables) {
|
||||
for (Waitable w : waitables) {
|
||||
if (w.isDone()) {
|
||||
firstReady = w;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -42,11 +37,14 @@ class WaitableRace<T> implements Waitable<T> {
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
try {
|
||||
return firstReady.get();
|
||||
} finally {
|
||||
dispose();
|
||||
assert isDone();
|
||||
dispose();
|
||||
for (Waitable<T> w : waitables) {
|
||||
if (w.isDone()) {
|
||||
return w.get();
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("At least one element must be ready");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -69,7 +69,6 @@ class WebSocketRouteImpl extends ChannelOwner implements WebSocketRoute {
|
||||
|
||||
WebSocketRouteImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
markAsInternalType();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -23,7 +23,7 @@ import java.nio.file.Path;
|
||||
* The {@code FormData} is used create form data that is sent via {@code APIRequestContext}.
|
||||
* <pre>{@code
|
||||
* import com.microsoft.playwright.options.FormData;
|
||||
* // ...
|
||||
* ...
|
||||
* FormData form = FormData.create()
|
||||
* .set("firstName", "John")
|
||||
* .set("lastName", "Doe")
|
||||
@@ -43,7 +43,7 @@ public interface FormData {
|
||||
* existing set of values.
|
||||
* <pre>{@code
|
||||
* import com.microsoft.playwright.options.FormData;
|
||||
* // ...
|
||||
* ...
|
||||
* FormData form = FormData.create()
|
||||
* // Only name and value are set.
|
||||
* .append("firstName", "John")
|
||||
@@ -70,7 +70,7 @@ public interface FormData {
|
||||
* existing set of values.
|
||||
* <pre>{@code
|
||||
* import com.microsoft.playwright.options.FormData;
|
||||
* // ...
|
||||
* ...
|
||||
* FormData form = FormData.create()
|
||||
* // Only name and value are set.
|
||||
* .append("firstName", "John")
|
||||
@@ -97,7 +97,7 @@ public interface FormData {
|
||||
* existing set of values.
|
||||
* <pre>{@code
|
||||
* import com.microsoft.playwright.options.FormData;
|
||||
* // ...
|
||||
* ...
|
||||
* FormData form = FormData.create()
|
||||
* // Only name and value are set.
|
||||
* .append("firstName", "John")
|
||||
@@ -124,7 +124,7 @@ public interface FormData {
|
||||
* existing set of values.
|
||||
* <pre>{@code
|
||||
* import com.microsoft.playwright.options.FormData;
|
||||
* // ...
|
||||
* ...
|
||||
* FormData form = FormData.create()
|
||||
* // Only name and value are set.
|
||||
* .append("firstName", "John")
|
||||
@@ -151,7 +151,7 @@ public interface FormData {
|
||||
* existing set of values.
|
||||
* <pre>{@code
|
||||
* import com.microsoft.playwright.options.FormData;
|
||||
* // ...
|
||||
* ...
|
||||
* FormData form = FormData.create()
|
||||
* // Only name and value are set.
|
||||
* .append("firstName", "John")
|
||||
@@ -179,7 +179,7 @@ public interface FormData {
|
||||
* Sets a field on the form. File values can be passed either as {@code Path} or as {@code FilePayload}.
|
||||
* <pre>{@code
|
||||
* import com.microsoft.playwright.options.FormData;
|
||||
* // ...
|
||||
* ...
|
||||
* FormData form = FormData.create()
|
||||
* // Only name and value are set.
|
||||
* .set("firstName", "John")
|
||||
@@ -200,7 +200,7 @@ public interface FormData {
|
||||
* Sets a field on the form. File values can be passed either as {@code Path} or as {@code FilePayload}.
|
||||
* <pre>{@code
|
||||
* import com.microsoft.playwright.options.FormData;
|
||||
* // ...
|
||||
* ...
|
||||
* FormData form = FormData.create()
|
||||
* // Only name and value are set.
|
||||
* .set("firstName", "John")
|
||||
@@ -221,7 +221,7 @@ public interface FormData {
|
||||
* Sets a field on the form. File values can be passed either as {@code Path} or as {@code FilePayload}.
|
||||
* <pre>{@code
|
||||
* import com.microsoft.playwright.options.FormData;
|
||||
* // ...
|
||||
* ...
|
||||
* FormData form = FormData.create()
|
||||
* // Only name and value are set.
|
||||
* .set("firstName", "John")
|
||||
@@ -242,7 +242,7 @@ public interface FormData {
|
||||
* Sets a field on the form. File values can be passed either as {@code Path} or as {@code FilePayload}.
|
||||
* <pre>{@code
|
||||
* import com.microsoft.playwright.options.FormData;
|
||||
* // ...
|
||||
* ...
|
||||
* FormData form = FormData.create()
|
||||
* // Only name and value are set.
|
||||
* .set("firstName", "John")
|
||||
@@ -263,7 +263,7 @@ public interface FormData {
|
||||
* Sets a field on the form. File values can be passed either as {@code Path} or as {@code FilePayload}.
|
||||
* <pre>{@code
|
||||
* import com.microsoft.playwright.options.FormData;
|
||||
* // ...
|
||||
* ...
|
||||
* FormData form = FormData.create()
|
||||
* // Only name and value are set.
|
||||
* .set("firstName", "John")
|
||||
|
||||
@@ -1,35 +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.options;
|
||||
|
||||
public class Location {
|
||||
public String file;
|
||||
public Integer line;
|
||||
public Integer column;
|
||||
|
||||
public Location(String file) {
|
||||
this.file = file;
|
||||
}
|
||||
public Location setLine(int line) {
|
||||
this.line = line;
|
||||
return this;
|
||||
}
|
||||
public Location setColumn(int column) {
|
||||
this.column = column;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -299,13 +299,6 @@ public class TestBrowserContextBasic {
|
||||
assertTrue(e.getMessage().contains("Target page, context or browser has been closed"), e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void waitForConditionThatMayChangeToFalse(BrowserContext context) {
|
||||
int[] var = {0};
|
||||
context.waitForCondition(() -> ++var[0] == 1);
|
||||
assertEquals(1, var[0], "The predicate should be called only once.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPropagateCloseReasonToPendingActions(Browser browser) {
|
||||
BrowserContext context = browser.newContext();
|
||||
|
||||
+7
-25
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.microsoft.playwright;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -50,12 +49,7 @@ public class TestBrowserContextCDPSession extends TestBase {
|
||||
cdpSession.send("Network.enable");
|
||||
|
||||
List<JsonElement> events = new ArrayList<>();
|
||||
cdpSession.on("Network.requestWillBeSent", (JsonObject jsonObject) -> {
|
||||
// Only register main request, ignore favicon requests.
|
||||
if ("Document".equals(jsonObject.get("type").getAsString())) {
|
||||
events.add(jsonObject);
|
||||
}
|
||||
});
|
||||
cdpSession.on("Network.requestWillBeSent", events::add);
|
||||
page.navigate(server.EMPTY_PAGE);
|
||||
|
||||
assertEquals(1, events.size());
|
||||
@@ -132,7 +126,7 @@ public class TestBrowserContextCDPSession extends TestBase {
|
||||
page.close();
|
||||
|
||||
PlaywrightException exception = assertThrows(PlaywrightException.class, session::detach);
|
||||
assertTrue(exception.getMessage().contains("Target page, context or browser has been closed"), exception.getMessage());
|
||||
assertTrue(exception.getMessage().contains("Target page, context or browser has been closed"));
|
||||
context.close();
|
||||
}
|
||||
|
||||
@@ -142,14 +136,8 @@ public class TestBrowserContextCDPSession extends TestBase {
|
||||
cdpSession.send("Network.enable");
|
||||
|
||||
List<JsonObject> events = new ArrayList<>();
|
||||
Consumer<JsonObject> listener1 = (JsonObject jsonObject) -> {
|
||||
// Only register main request, ignore favicon requests.
|
||||
if ("Document".equals(jsonObject.get("type").getAsString())) {
|
||||
events.add(jsonObject);
|
||||
}
|
||||
};
|
||||
cdpSession.on("Network.requestWillBeSent", listener1);
|
||||
cdpSession.on("Network.requestWillBeSent", listener1);
|
||||
cdpSession.on("Network.requestWillBeSent", events::add);
|
||||
cdpSession.on("Network.requestWillBeSent", events::add);
|
||||
|
||||
page.navigate(server.EMPTY_PAGE);
|
||||
assertEquals(2, events.size());
|
||||
@@ -161,15 +149,9 @@ public class TestBrowserContextCDPSession extends TestBase {
|
||||
cdpSession.send("Network.enable");
|
||||
|
||||
List<JsonObject> events = new ArrayList<>();
|
||||
Consumer<JsonObject> listener1 = (JsonObject jsonObject) -> {
|
||||
// Only register main request, ignore favicon requests.
|
||||
if ("Document".equals(jsonObject.get("type").getAsString())) {
|
||||
events.add(jsonObject);
|
||||
}
|
||||
};
|
||||
Consumer<JsonObject> listener2 = listener1::accept;
|
||||
Consumer<JsonObject> listener1 = events::add;
|
||||
cdpSession.on("Network.requestWillBeSent", listener1);
|
||||
cdpSession.on("Network.requestWillBeSent", listener2);
|
||||
cdpSession.on("Network.requestWillBeSent", events::add);
|
||||
|
||||
page.navigate(server.EMPTY_PAGE);
|
||||
assertEquals(2, events.size());
|
||||
@@ -178,6 +160,6 @@ public class TestBrowserContextCDPSession extends TestBase {
|
||||
events.clear();
|
||||
|
||||
page.navigate(server.EMPTY_PAGE);
|
||||
assertEquals(1, events.size(), new Gson().toJson(events));
|
||||
assertEquals(1, events.size());
|
||||
}
|
||||
}
|
||||
|
||||
+3
-8
@@ -25,15 +25,13 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class TestBrowserContextCredentials extends TestBase {
|
||||
|
||||
static boolean isChromiumHeadedLike() {
|
||||
// --headless=new, the default in all Chromium channels, is like headless.
|
||||
return isChromium() && (isHeadful() || getBrowserChannelFromEnv() != null);
|
||||
static boolean isChromiumHeadful() {
|
||||
return isChromium() && isHeadful();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledIf(value="isChromiumHeadedLike", disabledReason="fail")
|
||||
@DisabledIf(value="isChromiumHeadful", disabledReason="fail")
|
||||
void shouldFailWithoutCredentials() {
|
||||
System.out.println("channel2 " + getBrowserChannelFromEnv());
|
||||
server.setAuth("/empty.html", "user", "pass");
|
||||
Response response = page.navigate(server.EMPTY_PAGE);
|
||||
assertEquals(401, response.status());
|
||||
@@ -105,7 +103,6 @@ public class TestBrowserContextCredentials extends TestBase {
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledIf(value="isChromiumHeadedLike", disabledReason="fail")
|
||||
void shouldFailWithCorrectCredentialsAndWrongOriginScheme() {
|
||||
server.setAuth("/empty.html", "user", "pass");
|
||||
final HttpCredentials httpCredentials = new HttpCredentials("user", "pass");
|
||||
@@ -118,7 +115,6 @@ public class TestBrowserContextCredentials extends TestBase {
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledIf(value="isChromiumHeadedLike", disabledReason="fail")
|
||||
void shouldFailWithCorrectCredentialsAndWrongOriginHostname() {
|
||||
server.setAuth("/empty.html", "user", "pass");
|
||||
final HttpCredentials httpCredentials = new HttpCredentials("user", "pass");
|
||||
@@ -131,7 +127,6 @@ public class TestBrowserContextCredentials extends TestBase {
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledIf(value="isChromiumHeadedLike", disabledReason="fail")
|
||||
void shouldFailWithCorrectCredentialsAndWrongOriginPort() {
|
||||
server.setAuth("/empty.html", "user", "pass");
|
||||
final HttpCredentials httpCredentials = new HttpCredentials("user", "pass");
|
||||
|
||||
@@ -18,9 +18,9 @@ package com.microsoft.playwright;
|
||||
|
||||
import com.microsoft.playwright.assertions.LocatorAssertions;
|
||||
import com.microsoft.playwright.assertions.PlaywrightAssertions;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.opentest4j.AssertionFailedError;
|
||||
import org.opentest4j.ValueWrapper;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -657,9 +657,9 @@ public class TestLocatorAssertions extends TestBase {
|
||||
AssertionFailedError e = assertThrows(AssertionFailedError.class, () -> {
|
||||
assertThat(locator).isChecked(new LocatorAssertions.IsCheckedOptions().setTimeout(1000));
|
||||
});
|
||||
assertEquals("checked", e.getExpected().getStringRepresentation());
|
||||
assertEquals("unchecked", e.getActual().getStringRepresentation());
|
||||
assertTrue(e.getMessage().contains("Locator expected to be: checked"), e.getMessage());
|
||||
assertNull(e.getExpected());
|
||||
assertNull(e.getActual());
|
||||
assertTrue(e.getMessage().contains("Locator expected to be checked"), e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -669,10 +669,9 @@ public class TestLocatorAssertions extends TestBase {
|
||||
AssertionFailedError e = assertThrows(AssertionFailedError.class, () -> {
|
||||
assertThat(locator).not().isChecked(new LocatorAssertions.IsCheckedOptions().setTimeout(1000));
|
||||
});
|
||||
|
||||
assertEquals("checked", e.getExpected().getStringRepresentation());
|
||||
assertEquals("checked", e.getActual().getStringRepresentation());
|
||||
assertTrue(e.getMessage().contains("Locator expected not to be: checked"), e.getMessage());
|
||||
assertNull(e.getExpected());
|
||||
assertNull(e.getActual());
|
||||
assertTrue(e.getMessage().contains("Locator expected not to be checked"), e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -688,7 +687,7 @@ public class TestLocatorAssertions extends TestBase {
|
||||
Locator locator = page.locator("input");
|
||||
AssertionFailedError error = assertThrows(AssertionFailedError.class,
|
||||
() -> assertThat(locator).isChecked(new LocatorAssertions.IsCheckedOptions().setChecked(false).setTimeout(1000)));
|
||||
assertTrue(error.getMessage().contains("Locator expected to be: unchecked"), error.getMessage());
|
||||
assertTrue(error.getMessage().contains("Locator expected to be unchecked"), error.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -790,14 +789,6 @@ public class TestLocatorAssertions extends TestBase {
|
||||
assertThat(locator).not().isEditable(new LocatorAssertions.IsEditableOptions().setEditable(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isEditableThrowsOnNonInputElement() {
|
||||
page.setContent("<button>");
|
||||
Locator locator = page.locator("button");
|
||||
PlaywrightException e = assertThrows(PlaywrightException.class, () -> assertThat(locator).isEditable());
|
||||
assertTrue(e.getMessage().contains("Element is not an <input>, <textarea>, <select> or [contenteditable] and does not have a role allowing [aria-readonly]"), e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void isEmptyPass() {
|
||||
page.setContent("<input></input>");
|
||||
|
||||
@@ -73,9 +73,9 @@ public class TestLocatorAssertions2 extends TestBase {
|
||||
void isAttachedEventually() {
|
||||
page.setContent("<div></div>");
|
||||
Locator locator = page.locator("span");
|
||||
page.evalOnSelector("div", "div => setTimeout(() => {\n" +
|
||||
" div.innerHTML = '<span>Hello</span>'\n" +
|
||||
" }, 100)");
|
||||
page.evalOnSelector("div", "div => setTimeout(() => {\n" +
|
||||
" div.innerHTML = '<span>Hello</span>'\n" +
|
||||
" }, 100)");
|
||||
assertThat(locator).isAttached();
|
||||
}
|
||||
|
||||
@@ -83,9 +83,9 @@ public class TestLocatorAssertions2 extends TestBase {
|
||||
void isAttachedEventuallyWithNot() {
|
||||
page.setContent("<div><span>Hello</span></div>");
|
||||
Locator locator = page.locator("span");
|
||||
page.evalOnSelector("div", "div => setTimeout(() => {\n" +
|
||||
" div.textContent = '';\n" +
|
||||
" }, 0)");
|
||||
page.evalOnSelector("div", "div => setTimeout(() => {\n" +
|
||||
" div.textContent = '';\n" +
|
||||
" }, 0)");
|
||||
assertThat(locator).not().isAttached();
|
||||
}
|
||||
|
||||
@@ -129,9 +129,6 @@ public class TestLocatorAssertions2 extends TestBase {
|
||||
assertThat(page.locator("div")).hasAccessibleName(Pattern.compile("ell\\w"));
|
||||
assertThat(page.locator("div")).not().hasAccessibleName(Pattern.compile("hello"));
|
||||
assertThat(page.locator("div")).hasAccessibleName(Pattern.compile("hello"), new LocatorAssertions.HasAccessibleNameOptions().setIgnoreCase(true));
|
||||
|
||||
page.setContent("<button>foo bar\nbaz</button>");
|
||||
assertThat(page.locator("button")).hasAccessibleName("foo bar baz");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -144,10 +141,6 @@ public class TestLocatorAssertions2 extends TestBase {
|
||||
assertThat(page.locator("div")).hasAccessibleDescription(Pattern.compile("ell\\w"));
|
||||
assertThat(page.locator("div")).not().hasAccessibleDescription(Pattern.compile("hello"));
|
||||
assertThat(page.locator("div")).hasAccessibleDescription(Pattern.compile("hello"), new LocatorAssertions.HasAccessibleDescriptionOptions().setIgnoreCase(true));
|
||||
|
||||
page.setContent("<div role=\"button\" aria-describedby=\"desc\"></div>\n" +
|
||||
" <span id=\"desc\">foo bar\nbaz</span>");
|
||||
assertThat(page.locator("div")).hasAccessibleDescription("foo bar baz");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -157,67 +150,4 @@ public class TestLocatorAssertions2 extends TestBase {
|
||||
assertThat(page.locator("div")).hasRole(AriaRole.BUTTON);
|
||||
assertThat(page.locator("div")).not().hasRole(AriaRole.CHECKBOX);
|
||||
}
|
||||
|
||||
@Test
|
||||
void toHaveAccessibleErrorMessage() {
|
||||
page.setContent("<form>" +
|
||||
"<input role=\"textbox\" aria-invalid=\"true\" aria-errormessage=\"error-message\" />" +
|
||||
"<div id=\"error-message\">Hello</div>" +
|
||||
"<div id=\"irrelevant-error\">This should not be considered.</div>" +
|
||||
"</form>");
|
||||
|
||||
Locator locator = page.locator("input[role=\"textbox\"]");
|
||||
assertThat(locator).hasAccessibleErrorMessage("Hello");
|
||||
assertThat(locator).not().hasAccessibleErrorMessage("hello");
|
||||
assertThat(locator).hasAccessibleErrorMessage("hello", new LocatorAssertions.HasAccessibleErrorMessageOptions().setIgnoreCase(true));
|
||||
assertThat(locator).hasAccessibleErrorMessage(Pattern.compile("ell\\w"));
|
||||
assertThat(locator).not().hasAccessibleErrorMessage(Pattern.compile("hello"));
|
||||
assertThat(locator).hasAccessibleErrorMessage(Pattern.compile("hello"), new LocatorAssertions.HasAccessibleErrorMessageOptions().setIgnoreCase(true));
|
||||
assertThat(locator).not().hasAccessibleErrorMessage("This should not be considered.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void toHaveAccessibleErrorMessageShouldHandleMultipleAriaErrorMessageReferences() {
|
||||
page.setContent("<form>\n" +
|
||||
" <input role=\"textbox\" aria-invalid=\"true\" aria-errormessage=\"error1 error2\" />\n" +
|
||||
" <div id=\"error1\">First error message.</div>\n" +
|
||||
" <div id=\"error2\">Second error message.</div>\n" +
|
||||
" <div id=\"irrelevant-error\">This should not be considered.</div>\n" +
|
||||
"</form>");
|
||||
|
||||
Locator locator = page.locator("input[role=\"textbox\"]");
|
||||
|
||||
assertThat(locator).hasAccessibleErrorMessage("First error message. Second error message.");
|
||||
assertThat(locator).hasAccessibleErrorMessage(Pattern.compile("first error message.", Pattern.CASE_INSENSITIVE));
|
||||
assertThat(locator).hasAccessibleErrorMessage(Pattern.compile("second error message.", Pattern.CASE_INSENSITIVE));
|
||||
assertThat(locator).not().hasAccessibleErrorMessage(Pattern.compile("This should not be considered.", Pattern.CASE_INSENSITIVE));
|
||||
}
|
||||
|
||||
@Test
|
||||
void toBeEditableWithIndeterminateTrue() {
|
||||
page.setContent("<input type=checkbox></input>");
|
||||
page.locator("input").evaluate("e => e.indeterminate = true");
|
||||
Locator locator = page.locator("input");
|
||||
assertThat(locator).isChecked(new LocatorAssertions.IsCheckedOptions().setIndeterminate(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
void toBeEditableWithIndeterminateTrueAndChecked() {
|
||||
page.setContent("<input type=checkbox></input>");
|
||||
page.locator("input").evaluate("e => e.indeterminate = true");
|
||||
Locator locator = page.locator("input");
|
||||
PlaywrightException e = assertThrows(PlaywrightException.class, () ->
|
||||
assertThat(locator).isChecked(new LocatorAssertions.IsCheckedOptions().setIndeterminate(true).setChecked(false)));
|
||||
assertTrue(e.getMessage().contains("Can't assert indeterminate and checked at the same time"), e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void toBeEditableFailWithIndeterminateTrue() {
|
||||
page.setContent("<input type=checkbox></input>");
|
||||
Locator locator = page.locator("input");
|
||||
AssertionFailedError e = assertThrows(AssertionFailedError.class, () ->
|
||||
assertThat(locator).isChecked(new LocatorAssertions.IsCheckedOptions().setIndeterminate(true).setTimeout(1000)));
|
||||
// TODO: should be "assertThat().isChecked() with timeout 1000ms"
|
||||
assertTrue(e.getMessage().contains("Locator.expect with timeout 1000ms"), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
package com.microsoft.playwright;
|
||||
|
||||
import com.microsoft.playwright.junit.FixtureTest;
|
||||
import com.microsoft.playwright.junit.UsePlaywright;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
@FixtureTest
|
||||
@UsePlaywright
|
||||
public class TestPageAriaSnapshot {
|
||||
public static String unshift(String snapshot) {
|
||||
List<String> lines = Arrays.asList(snapshot.split("\n"));
|
||||
int whitespacePrefixLength = 100;
|
||||
Pattern pattern = Pattern.compile("^(\\s*).*");
|
||||
for (String line : lines) {
|
||||
if (line.trim().isEmpty())
|
||||
continue;
|
||||
Matcher matcher = pattern.matcher(line);
|
||||
if (!matcher.matches()) {
|
||||
continue;
|
||||
}
|
||||
String match = matcher.group(1);
|
||||
if (match.length() < whitespacePrefixLength) {
|
||||
whitespacePrefixLength = match.length();
|
||||
}
|
||||
}
|
||||
final int prefixLength = whitespacePrefixLength;
|
||||
return lines.stream()
|
||||
.filter(line -> !line.trim().isEmpty())
|
||||
.map(line -> line.substring(prefixLength))
|
||||
.collect(Collectors.joining("\n"));
|
||||
}
|
||||
|
||||
private static void checkAndMatchSnapshot(Locator locator, String snapshot) {
|
||||
assertEquals(unshift(snapshot), locator.ariaSnapshot());
|
||||
assertThat(locator).matchesAriaSnapshot(snapshot);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSnapshot(Page page) {
|
||||
page.setContent("<h1>title</h1>");
|
||||
checkAndMatchSnapshot(page.locator("body"), "- heading \"title\" [level=1]");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSnapshotList(Page page) {
|
||||
page.setContent("<h1>title</h1><h1>title 2</h1>");
|
||||
checkAndMatchSnapshot(page.locator("body"), "" +
|
||||
" - heading \"title\" [level=1]\n" +
|
||||
" - heading \"title 2\" [level=1]");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSnapshotListWithAccessibleName(Page page) {
|
||||
page.setContent("<ul aria-label=\"my list\"><li>one</li><li>two</li></ul>");
|
||||
checkAndMatchSnapshot(page.locator("body"), "- list \"my list\":\n - listitem: one\n - listitem: two");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSnapshotComplex(Page page) {
|
||||
page.setContent("<ul><li><a href='about:blank'>link</a></li></ul>");
|
||||
checkAndMatchSnapshot(page.locator("body"), "- list:\n - listitem:\n - link \"link\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldAllowTextNodes(Page page) {
|
||||
page.setContent("<h1>Microsoft</h1><div>Open source projects and samples from Microsoft</div>");
|
||||
checkAndMatchSnapshot(page.locator("body"), "" +
|
||||
" - heading \"Microsoft\" [level=1]\n" +
|
||||
" - text: Open source projects and samples from Microsoft");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSnapshotDetailsVisibility(Page page) {
|
||||
page.setContent("<details><summary>Summary</summary><div>Details</div></details>");
|
||||
checkAndMatchSnapshot(page.locator("body"), "- group: Summary");
|
||||
}
|
||||
}
|
||||
@@ -290,9 +290,8 @@ public class TestPageClock {
|
||||
Page popup = page.waitForPopup(() -> {
|
||||
page.evaluate("url => window.open(url)", server.PREFIX + "/popup.html");
|
||||
});
|
||||
popup.waitForURL(server.PREFIX + "/popup.html");
|
||||
Double popupTime = (Double) popup.evaluate("time");
|
||||
assertTrue(popupTime >= 2000, "popupTime = " + popupTime);
|
||||
assertTrue(popupTime >= 2000);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -311,7 +310,6 @@ public class TestPageClock {
|
||||
Page popup = page.waitForPopup(() -> {
|
||||
page.evaluate("url => window.open(url)", server.PREFIX + "/popup.html");
|
||||
});
|
||||
popup.waitForURL(server.PREFIX + "/popup.html");
|
||||
Object popupTime = popup.evaluate("time");
|
||||
assertEquals(1000, popupTime);
|
||||
}
|
||||
|
||||
@@ -97,18 +97,6 @@ public class TestPageRoute extends TestBase {
|
||||
assertEquals(asList(1), intercepted);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUnrouteNonExistentPatternHandler() {
|
||||
List<Integer> intercepted = new ArrayList<>();
|
||||
page.route(Pattern.compile("empty.html"), route -> {
|
||||
intercepted.add(1);
|
||||
route.fallback();
|
||||
});
|
||||
page.unroute("**/*");
|
||||
page.navigate(server.EMPTY_PAGE);
|
||||
assertEquals(asList( 1), intercepted);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSupportQuestionMarkInGlobPattern() {
|
||||
server.setRoute("/index", exchange -> {
|
||||
|
||||
@@ -471,10 +471,10 @@ public class TestPageSetInputFiles extends TestBase {
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUploadAFolderAndThrowForMultipleDirectories(@TempDir Path tmpDir) throws IOException {
|
||||
void shouldUploadAFolderAndThrowForMultipleDirectories() throws IOException {
|
||||
page.navigate(server.PREFIX + "/input/folderupload.html");
|
||||
Locator input = page.locator("input[name=\"file1\"]");
|
||||
Path dir = tmpDir.resolve("file-upload-test");
|
||||
Path dir = Paths.get("file-upload-test"); // Adjust path as necessary
|
||||
Files.createDirectories(dir.resolve("folder1"));
|
||||
writeFile(dir.resolve("folder1").resolve("file1.txt"), "file1 content");
|
||||
Files.createDirectories(dir.resolve("folder2"));
|
||||
@@ -485,11 +485,11 @@ public class TestPageSetInputFiles extends TestBase {
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldThrowIfADirectoryAndFilesArePassed(@TempDir Path tmpDir) throws IOException {
|
||||
void shouldThrowIfADirectoryAndFilesArePassed() throws IOException {
|
||||
// Skipping conditions based on environment not directly translatable to Java; needs custom implementation
|
||||
page.navigate(server.PREFIX + "/input/folderupload.html");
|
||||
Locator input = page.locator("input[name=\"file1\"]");
|
||||
Path dir = tmpDir.resolve("file-upload-test");
|
||||
Path dir = Paths.get("file-upload-test"); // Adjust path as necessary
|
||||
Files.createDirectories(dir.resolve("folder1"));
|
||||
writeFile(dir.resolve("folder1").resolve("file1.txt"), "file1 content");
|
||||
PlaywrightException e = assertThrows(PlaywrightException.class,
|
||||
@@ -498,10 +498,10 @@ public class TestPageSetInputFiles extends TestBase {
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldThrowWhenUploadingAFolderInANormalFileUploadInput(@TempDir Path tmpDir) throws IOException {
|
||||
void shouldThrowWhenUploadingAFolderInANormalFileUploadInput() throws IOException {
|
||||
page.navigate(server.PREFIX + "/input/fileupload.html");
|
||||
Locator input = page.locator("input[name=\"file1\"]");
|
||||
Path dir = tmpDir.resolve("file-upload-test");
|
||||
Path dir = Paths.get("file-upload-test"); // Adjust path as necessary
|
||||
Files.createDirectories(dir);
|
||||
writeFile(dir.resolve("file1.txt"), "file1 content");
|
||||
PlaywrightException e = assertThrows(PlaywrightException.class,
|
||||
|
||||
@@ -30,6 +30,7 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
public class TestPdf extends TestBase {
|
||||
@Test
|
||||
@EnabledIf(value="com.microsoft.playwright.TestBase#isChromium", disabledReason="skip")
|
||||
@DisabledIf(value="com.microsoft.playwright.TestBase#isHeadful", disabledReason="skip")
|
||||
void shouldBeAbleToSaveFile(@TempDir Path tempDir) throws IOException {
|
||||
Path path = tempDir.resolve("output.pdf");
|
||||
page.pdf(new Page.PdfOptions().setPath(path));
|
||||
@@ -39,6 +40,7 @@ public class TestPdf extends TestBase {
|
||||
|
||||
@Test
|
||||
@EnabledIf(value="com.microsoft.playwright.TestBase#isChromium", disabledReason="skip")
|
||||
@DisabledIf(value="com.microsoft.playwright.TestBase#isHeadful", disabledReason="skip")
|
||||
void shouldSupportFractionalScaleValue(@TempDir Path tempDir) throws IOException {
|
||||
Path path = tempDir.resolve("output.pdf");
|
||||
page.pdf(new Page.PdfOptions().setPath(path).setScale(0.5));
|
||||
@@ -49,6 +51,7 @@ public class TestPdf extends TestBase {
|
||||
|
||||
@Test
|
||||
@EnabledIf(value="com.microsoft.playwright.TestBase#isChromium", disabledReason="Printing to pdf is currently only supported in headless chromium.")
|
||||
@DisabledIf(value="com.microsoft.playwright.TestBase#isHeadful", disabledReason="Printing to pdf is currently only supported in headless chromium.")
|
||||
void shouldBeAbleToGenerateOutline(@TempDir Path tempDir) throws IOException {
|
||||
page.navigate(server.PREFIX + "/headings.html");
|
||||
Path outputFileNoOutline = tempDir.resolve("outputNoOutline.pdf");
|
||||
|
||||
@@ -9,8 +9,6 @@ import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -319,76 +317,4 @@ public class TestRouteWebSocket {
|
||||
"close code=3008 reason=oops"),
|
||||
page.evaluate("window.log"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldWorkWithBaseURL(Browser browser) throws Exception {
|
||||
BrowserContext context = browser.newContext(new Browser.NewContextOptions().setBaseURL("http://localhost:" + webSocketServer.getPort()));
|
||||
Page newPage = context.newPage();
|
||||
|
||||
newPage.routeWebSocket("/ws", ws -> {
|
||||
ws.onMessage(message -> {
|
||||
if (message.text() != null) {
|
||||
ws.send(message.text());
|
||||
} else {
|
||||
ws.send(message.binary());
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
setupWS(newPage, webSocketServer.getPort(), "blob");
|
||||
|
||||
newPage.evaluate("async () => {\n" +
|
||||
" await window.wsOpened;\n" +
|
||||
" window.ws.send('echo');\n" +
|
||||
" }");
|
||||
|
||||
newPage.waitForCondition(() -> {
|
||||
Boolean result = (Boolean) newPage.evaluate("() => window.log.length >= 2");
|
||||
return result;
|
||||
});
|
||||
|
||||
assertEquals(
|
||||
asList("open", "message: data=echo origin=ws://localhost:" + webSocketServer.getPort() + " lastEventId="),
|
||||
newPage.evaluate("window.log"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldWorkWithNoTrailingSlash(Page page) throws Exception {
|
||||
List<String> log = new ArrayList<>();
|
||||
|
||||
// No trailing slash in the route pattern
|
||||
page.routeWebSocket("ws://localhost:" + webSocketServer.getPort(), ws -> {
|
||||
ws.onMessage(message -> {
|
||||
log.add(message.text());
|
||||
ws.send("response");
|
||||
});
|
||||
});
|
||||
|
||||
page.navigate("about:blank");
|
||||
page.evaluate("({ port }) => {\n" +
|
||||
" window.log = [];\n" +
|
||||
" // No trailing slash in WebSocket URL\n" +
|
||||
" window.ws = new WebSocket('ws://localhost:' + port);\n" +
|
||||
" window.ws.addEventListener('message', event => window.log.push(event.data));\n" +
|
||||
"}", mapOf("port", webSocketServer.getPort()));
|
||||
|
||||
// Wait for WebSocket to be ready (readyState === 1)
|
||||
page.waitForCondition(() -> {
|
||||
Integer result = (Integer) page.evaluate("() => window.ws.readyState");
|
||||
return result == 1;
|
||||
});
|
||||
|
||||
page.evaluate("() => window.ws.send('query')");
|
||||
|
||||
// Wait and verify server received message
|
||||
page.waitForCondition(() -> log.size() >= 1);
|
||||
assertEquals(asList("query"), log);
|
||||
|
||||
// Wait and verify client received response
|
||||
page.waitForCondition(() -> {
|
||||
Boolean result = (Boolean) page.evaluate("() => window.log.length >= 1");
|
||||
return result;
|
||||
});
|
||||
assertEquals(asList("response"), page.evaluate("window.log"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,12 +16,6 @@
|
||||
|
||||
package com.microsoft.playwright;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.microsoft.playwright.options.AriaRole;
|
||||
import com.microsoft.playwright.options.Location;
|
||||
import com.microsoft.playwright.options.MouseButton;
|
||||
|
||||
import org.junit.jupiter.api.Assumptions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -32,14 +26,12 @@ import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class TestTracing extends TestBase {
|
||||
@Override
|
||||
@@ -162,151 +154,4 @@ public class TestTracing extends TestBase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void canCallTracingGroupGroupEndAtAnyTimeAndAutoClose(@TempDir Path tempDir) throws Exception {
|
||||
context.tracing().group("ignored");
|
||||
context.tracing().groupEnd();
|
||||
context.tracing().group("ignored2");
|
||||
|
||||
context.tracing().start(new Tracing.StartOptions());
|
||||
context.tracing().group("actual");
|
||||
page.navigate(server.EMPTY_PAGE);
|
||||
Path traceFile1 = tempDir.resolve("trace1.zip");
|
||||
context.tracing().stopChunk(new Tracing.StopChunkOptions().setPath(traceFile1));
|
||||
|
||||
context.tracing().group("ignored3");
|
||||
context.tracing().groupEnd();
|
||||
context.tracing().groupEnd();
|
||||
context.tracing().groupEnd();
|
||||
|
||||
List<TraceEvent> events = parseTraceEvents(traceFile1);
|
||||
List<TraceEvent> groups = events.stream().filter(e -> "tracingGroup".equals(e.method)).collect(Collectors.toList());
|
||||
assertEquals(1, groups.size());
|
||||
assertEquals("actual", groups.get(0).apiName);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void traceGroupGroupEnd(@TempDir Path tempDir) throws Exception {
|
||||
context.tracing().start(new Tracing.StartOptions());
|
||||
context.tracing().group("outer group");
|
||||
page.navigate("data:text/html,<!DOCTYPE html><body><div>Hello world</div></body>");
|
||||
context.tracing().group("inner group 1", new Tracing.GroupOptions().setLocation(new Location("foo.java").setLine(17).setColumn(1)));
|
||||
page.locator("body").click();
|
||||
context.tracing().groupEnd();
|
||||
context.tracing().group("inner group 2");
|
||||
assertTrue(page.locator("text=Hello").isVisible());
|
||||
context.tracing().groupEnd();
|
||||
context.tracing().groupEnd();
|
||||
|
||||
Path traceFile1 = tempDir.resolve("trace1.zip");
|
||||
context.tracing().stop(new Tracing.StopOptions().setPath(traceFile1));
|
||||
|
||||
List<TraceEvent> events = parseTraceEvents(traceFile1);
|
||||
List<String> calls = events.stream().filter(e -> e.apiName != null).map(e -> e.apiName).collect(Collectors.toList());
|
||||
assertEquals(asList("outer group", "Page.navigate", "inner group 1", "Frame.click", "inner group 2", "Page.isVisible"), calls);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldTraceVariousAPIs(@TempDir Path tempDir) throws Exception {
|
||||
context.tracing().start(new Tracing.StartOptions());
|
||||
|
||||
page.clock().install();
|
||||
|
||||
page.setContent("<input type='text' />");
|
||||
page.locator("input").click(new Locator.ClickOptions().setButton(MouseButton.RIGHT));
|
||||
page.getByRole(AriaRole.TEXTBOX).click();
|
||||
page.keyboard().type("Hello world this is a very long string what happens when it overflows?");
|
||||
page.keyboard().press("Control+c");
|
||||
page.keyboard().down("Shift");
|
||||
page.keyboard().insertText("Hello world");
|
||||
page.keyboard().up("Shift");
|
||||
page.mouse().move(0, 0);
|
||||
page.mouse().down();
|
||||
page.mouse().move(100, 200);
|
||||
page.mouse().wheel(5, 7);
|
||||
page.mouse().up();
|
||||
page.clock().fastForward(1000);
|
||||
page.clock().fastForward("30:00");
|
||||
page.clock().pauseAt("2050-02-02");
|
||||
page.clock().runFor(10);
|
||||
page.clock().setFixedTime("2050-02-02");
|
||||
page.clock().setSystemTime("2050-02-02");
|
||||
|
||||
page.clock().resume();
|
||||
|
||||
page.locator("input").click(new Locator.ClickOptions().setButton(MouseButton.RIGHT));
|
||||
|
||||
Path traceFile1 = tempDir.resolve("trace1.zip");
|
||||
context.tracing().stop(new Tracing.StopOptions().setPath(traceFile1));
|
||||
|
||||
List<TraceEvent> events = parseTraceEvents(traceFile1);
|
||||
List<String> calls = events.stream().filter(e -> e.apiName != null).map(e -> e.apiName)
|
||||
.collect(Collectors.toList());
|
||||
assertEquals(asList(
|
||||
"Clock.install",
|
||||
"Page.setContent",
|
||||
"Frame.click",
|
||||
"Frame.click",
|
||||
"Keyboard.type",
|
||||
"Keyboard.press",
|
||||
"Keyboard.down",
|
||||
"Keyboard.insertText",
|
||||
"Keyboard.up",
|
||||
"Mouse.move",
|
||||
"Mouse.down",
|
||||
"Mouse.move",
|
||||
"Mouse.wheel",
|
||||
"Mouse.up",
|
||||
"Clock.fastForward",
|
||||
"Clock.fastForward",
|
||||
"Clock.pauseAt",
|
||||
"Clock.runFor",
|
||||
"Clock.setFixedTime",
|
||||
"Clock.setSystemTime",
|
||||
"Clock.resume",
|
||||
"Frame.click"),
|
||||
calls);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotRecordNetworkActions(@TempDir Path tempDir) throws IOException {
|
||||
context.tracing().start(new Tracing.StartOptions());
|
||||
|
||||
page.onRequest(request -> {
|
||||
request.allHeaders();
|
||||
});
|
||||
page.onResponse(response -> {
|
||||
response.text();
|
||||
});
|
||||
page.navigate(server.EMPTY_PAGE);
|
||||
|
||||
Path traceFile1 = tempDir.resolve("trace1.zip");
|
||||
context.tracing().stop(new Tracing.StopOptions().setPath(traceFile1));
|
||||
|
||||
List<TraceEvent> events = parseTraceEvents(traceFile1);
|
||||
List<String> calls = events.stream().filter(e -> e.apiName != null).map(e -> e.apiName)
|
||||
.collect(Collectors.toList());
|
||||
assertEquals(asList("Page.navigate"), calls);
|
||||
}
|
||||
|
||||
private static class TraceEvent {
|
||||
String type;
|
||||
String name;
|
||||
String apiName;
|
||||
String method;
|
||||
Double startTime;
|
||||
Double endTime;
|
||||
String callId;
|
||||
}
|
||||
|
||||
private static List<TraceEvent> parseTraceEvents(Path traceFile) throws IOException {
|
||||
Map<String, byte[]> files = Utils.parseZip(traceFile);
|
||||
Map<String, byte[]> traces = files.entrySet().stream().filter(e -> e.getKey().endsWith(".trace")).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
assertNotNull(traces.get("trace.trace"));
|
||||
return Arrays.stream(new String(traces.get("trace.trace"), UTF_8)
|
||||
.split("\n"))
|
||||
.map(s -> new Gson().fromJson(s, TraceEvent.class))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>com.microsoft.playwright</groupId>
|
||||
<artifactId>parent-pom</artifactId>
|
||||
<version>1.50.0</version>
|
||||
<version>1.48.0</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>Playwright Parent Project</name>
|
||||
<description>Java library to automate Chromium, Firefox and WebKit with a single API.
|
||||
@@ -44,10 +44,10 @@
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<maven.compiler.parameters>true</maven.compiler.parameters>
|
||||
<gson.version>2.12.1</gson.version>
|
||||
<junit.version>5.11.4</junit.version>
|
||||
<gson.version>2.11.0</gson.version>
|
||||
<junit.version>5.11.1</junit.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<websocket.version>1.6.0</websocket.version>
|
||||
<websocket.version>1.5.7</websocket.version>
|
||||
<opentest4j.version>1.3.0</opentest4j.version>
|
||||
</properties>
|
||||
|
||||
@@ -136,7 +136,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.11.2</version>
|
||||
<version>3.10.1</version>
|
||||
<configuration>
|
||||
<additionalOptions>--allow-script-in-comments</additionalOptions>
|
||||
<failOnError>false</failOnError>
|
||||
@@ -147,7 +147,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.5.2</version>
|
||||
<version>3.5.0</version>
|
||||
<configuration>
|
||||
<properties>
|
||||
<configurationParameters>
|
||||
|
||||
@@ -1 +1 @@
|
||||
1.50.1-beta-1738592302000
|
||||
1.48.1
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>com.microsoft.playwright</groupId>
|
||||
<artifactId>api-generator</artifactId>
|
||||
<version>1.50.0</version>
|
||||
<version>1.48.0</version>
|
||||
<name>Playwright - API Generator</name>
|
||||
<description>
|
||||
This is an internal module used to generate Java API from the upstream Playwright
|
||||
|
||||
@@ -986,7 +986,7 @@ class Interface extends TypeDefinition {
|
||||
if (methods.stream().anyMatch(m -> "create".equals(m.jsonName))) {
|
||||
output.add("import com.microsoft.playwright.impl." + jsonName + "Impl;");
|
||||
}
|
||||
if (asList("Page", "Request", "Response", "APIRequestContext", "APIRequest", "APIResponse", "FileChooser", "Frame", "FrameLocator", "ElementHandle", "Locator", "Browser", "BrowserContext", "BrowserType", "Mouse", "Keyboard", "Tracing").contains(jsonName)) {
|
||||
if (asList("Page", "Request", "Response", "APIRequestContext", "APIRequest", "APIResponse", "FileChooser", "Frame", "FrameLocator", "ElementHandle", "Locator", "Browser", "BrowserContext", "BrowserType", "Mouse", "Keyboard").contains(jsonName)) {
|
||||
output.add("import com.microsoft.playwright.options.*;");
|
||||
}
|
||||
if ("Download".equals(jsonName)) {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.microsoft.playwright</groupId>
|
||||
<artifactId>test-cli-fatjar</artifactId>
|
||||
<version>1.50.0</version>
|
||||
<version>1.48.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.50.0</version>
|
||||
<version>1.48.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.50.0</version>
|
||||
<version>1.48.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.50.0</version>
|
||||
<version>1.48.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.50.0</version>
|
||||
<version>1.48.0</version>
|
||||
<name>Playwright - Update Version in Documentation</name>
|
||||
<description>
|
||||
This is an internal module used to update versions in the documentation based on
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
FROM ubuntu:focal
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ARG TZ=America/Los_Angeles
|
||||
ARG DOCKER_IMAGE_NAME_TEMPLATE="mcr.microsoft.com/playwright/java:v%version%-focal"
|
||||
|
||||
# === INSTALL JDK and Maven ===
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends openjdk-21-jdk \
|
||||
# Install utilities required for downloading browsers
|
||||
wget \
|
||||
# Install utilities required for downloading driver
|
||||
unzip \
|
||||
# For the MSEdge install script
|
||||
gpg && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
# Create the pwuser
|
||||
adduser pwuser
|
||||
|
||||
# Ubuntu 22.04 and earlier come with Maven 3.6.3 which fails with
|
||||
# Java 21, so we install latest Maven from Apache instead.
|
||||
RUN VERSION=3.9.6 && \
|
||||
wget -O - https://archive.apache.org/dist/maven/maven-3/$VERSION/binaries/apache-maven-$VERSION-bin.tar.gz | tar zxfv - -C /opt/ && \
|
||||
ln -s /opt/apache-maven-$VERSION/bin/mvn /usr/local/bin/
|
||||
|
||||
ARG PW_TARGET_ARCH
|
||||
ENV JAVA_HOME=/usr/lib/jvm/java-21-openjdk-${PW_TARGET_ARCH}
|
||||
|
||||
# === BAKE BROWSERS INTO IMAGE ===
|
||||
|
||||
# Browsers will remain downloaded in `/ms-playwright`.
|
||||
# Note: make sure to set 777 to the registry so that any user can access
|
||||
# registry.
|
||||
|
||||
ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright
|
||||
|
||||
RUN mkdir /ms-playwright && \
|
||||
mkdir /tmp/pw-java
|
||||
|
||||
COPY . /tmp/pw-java
|
||||
|
||||
RUN cd /tmp/pw-java && \
|
||||
./scripts/download_driver.sh && \
|
||||
mvn install -D skipTests --no-transfer-progress && \
|
||||
DEBIAN_FRONTEND=noninteractive mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI \
|
||||
-D exec.args="install-deps" -f playwright/pom.xml --no-transfer-progress && \
|
||||
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI \
|
||||
-D exec.args="install" -f playwright/pom.xml --no-transfer-progress && \
|
||||
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI \
|
||||
-D exec.args="mark-docker-image '${DOCKER_IMAGE_NAME_TEMPLATE}'" -f playwright/pom.xml --no-transfer-progress && \
|
||||
rm -rf /tmp/pw-java && \
|
||||
chmod -R 777 $PLAYWRIGHT_BROWSERS_PATH
|
||||
@@ -3,12 +3,12 @@ set -e
|
||||
set +x
|
||||
|
||||
if [[ ($1 == '--help') || ($1 == '-h') || ($1 == '') || ($2 == '') ]]; then
|
||||
echo "usage: $(basename $0) {--arm64,--amd64} {jammy,noble} playwright:localbuild-noble"
|
||||
echo "usage: $(basename $0) {--arm64,--amd64} {focal,jammy} playwright:localbuild-focal"
|
||||
echo
|
||||
echo "Build Playwright docker image and tag it as 'playwright:localbuild-noble'."
|
||||
echo "Build Playwright docker image and tag it as 'playwright:localbuild-focal'."
|
||||
echo "Once image is built, you can run it with"
|
||||
echo ""
|
||||
echo " docker run --rm -it playwright:localbuild-noble /bin/bash"
|
||||
echo " docker run --rm -it playwright:localbuild-focal /bin/bash"
|
||||
echo ""
|
||||
echo "NOTE: this requires on Playwright PIP dependencies to be installed"
|
||||
echo ""
|
||||
|
||||
@@ -27,6 +27,11 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Ubuntu 20.04
|
||||
FOCAL_TAGS=(
|
||||
"v${PW_VERSION}-focal"
|
||||
)
|
||||
|
||||
# Ubuntu 22.04
|
||||
JAMMY_TAGS=(
|
||||
"v${PW_VERSION}-jammy"
|
||||
@@ -70,12 +75,14 @@ install_oras_if_needed() {
|
||||
publish_docker_images_with_arch_suffix() {
|
||||
local FLAVOR="$1"
|
||||
local TAGS=()
|
||||
if [[ "$FLAVOR" == "jammy" ]]; then
|
||||
if [[ "$FLAVOR" == "focal" ]]; then
|
||||
TAGS=("${FOCAL_TAGS[@]}")
|
||||
elif [[ "$FLAVOR" == "jammy" ]]; then
|
||||
TAGS=("${JAMMY_TAGS[@]}")
|
||||
elif [[ "$FLAVOR" == "noble" ]]; then
|
||||
TAGS=("${NOBLE_TAGS[@]}")
|
||||
else
|
||||
echo "ERROR: unknown flavor - $FLAVOR. Must be either 'jammy', or 'noble'"
|
||||
echo "ERROR: unknown flavor - $FLAVOR. Must be either 'focal', 'jammy', or 'noble'"
|
||||
exit 1
|
||||
fi
|
||||
local ARCH="$2"
|
||||
@@ -96,12 +103,14 @@ publish_docker_images_with_arch_suffix() {
|
||||
publish_docker_manifest () {
|
||||
local FLAVOR="$1"
|
||||
local TAGS=()
|
||||
if [[ "$FLAVOR" == "jammy" ]]; then
|
||||
if [[ "$FLAVOR" == "focal" ]]; then
|
||||
TAGS=("${FOCAL_TAGS[@]}")
|
||||
elif [[ "$FLAVOR" == "jammy" ]]; then
|
||||
TAGS=("${JAMMY_TAGS[@]}")
|
||||
elif [[ "$FLAVOR" == "noble" ]]; then
|
||||
TAGS=("${NOBLE_TAGS[@]}")
|
||||
else
|
||||
echo "ERROR: unknown flavor - $FLAVOR. Must be either 'jammy', 'noble'"
|
||||
echo "ERROR: unknown flavor - $FLAVOR. Must be either 'focal', 'jammy', 'noble'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -120,6 +129,10 @@ publish_docker_manifest () {
|
||||
done
|
||||
}
|
||||
|
||||
publish_docker_images_with_arch_suffix focal amd64
|
||||
publish_docker_images_with_arch_suffix focal arm64
|
||||
publish_docker_manifest focal amd64 arm64
|
||||
|
||||
publish_docker_images_with_arch_suffix jammy amd64
|
||||
publish_docker_images_with_arch_suffix jammy arm64
|
||||
publish_docker_manifest jammy amd64 arm64
|
||||
|
||||
Reference in New Issue
Block a user