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

Compare commits

..

1 Commits

Author SHA1 Message Date
Yury Semikhatsky 96cc9e6e62 chore: set version to 1.29.0 (#1178) 2023-01-18 12:06:53 -08:00
44 changed files with 606 additions and 2260 deletions
+2 -2
View File
@@ -11,9 +11,9 @@ Playwright is a Java library to automate [Chromium](https://www.chromium.org/Hom
| | Linux | macOS | Windows |
| :--- | :---: | :---: | :---: |
| Chromium <!-- GEN:chromium-version -->111.0.5563.19<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Chromium <!-- GEN:chromium-version -->109.0.5414.46<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| WebKit <!-- GEN:webkit-version -->16.4<!-- GEN:stop --> | ✅ | ✅ | ✅ |
| Firefox <!-- GEN:firefox-version -->109.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Firefox <!-- GEN:firefox-version -->107.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
Headless execution is supported for all the browsers on all platforms. Check out [system requirements](https://playwright.dev/java/docs/next/intro/#system-requirements) for details.
+20 -1
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>com.microsoft.playwright</groupId>
<artifactId>parent-pom</artifactId>
<version>1.31.0</version>
<version>1.29.0</version>
</parent>
<artifactId>driver-bundle</artifactId>
@@ -16,6 +16,25 @@
It is intended to be used on the systems where Playwright driver is not preinstalled.
</description>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<configuration>
<excludeResources>true</excludeResources>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.microsoft.playwright</groupId>
+17 -1
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>com.microsoft.playwright</groupId>
<artifactId>parent-pom</artifactId>
<version>1.31.0</version>
<version>1.29.0</version>
</parent>
<artifactId>driver</artifactId>
@@ -15,6 +15,22 @@
This module provides API for discovery and launching of Playwright driver.
</description>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
+2 -2
View File
@@ -6,7 +6,7 @@
<groupId>org.example</groupId>
<artifactId>examples</artifactId>
<version>1.31.0</version>
<version>1.29.0</version>
<name>Playwright Client Examples</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -15,7 +15,7 @@
<dependency>
<groupId>com.microsoft.playwright</groupId>
<artifactId>playwright</artifactId>
<version>1.30.0</version>
<version>1.22.0</version>
</dependency>
</dependencies>
<build>
+14 -2
View File
@@ -7,7 +7,7 @@
<parent>
<groupId>com.microsoft.playwright</groupId>
<artifactId>parent-pom</artifactId>
<version>1.31.0</version>
<version>1.29.0</version>
</parent>
<artifactId>playwright</artifactId>
@@ -21,14 +21,26 @@
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration combine.self="append">
<configuration>
<subpackages>com.microsoft.playwright</subpackages>
<excludePackageNames>com.microsoft.playwright.impl</excludePackageNames>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
@@ -227,11 +227,8 @@ public interface Browser extends AutoCloseable {
*/
public String userAgent;
/**
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. Use {@code null} to disable the consistent
* viewport emulation.
*
* <p> <strong>NOTE:</strong> The {@code null} value opts out from the default presets, makes viewport depend on the host window size defined by the
* operating system. It makes the execution of the tests non-deterministic.
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. {@code null} disables the default
* viewport.
*/
public Optional<ViewportSize> viewportSize;
@@ -539,21 +536,15 @@ public interface Browser extends AutoCloseable {
return this;
}
/**
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. Use {@code null} to disable the consistent
* viewport emulation.
*
* <p> <strong>NOTE:</strong> The {@code null} value opts out from the default presets, makes viewport depend on the host window size defined by the
* operating system. It makes the execution of the tests non-deterministic.
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. {@code null} disables the default
* viewport.
*/
public NewContextOptions setViewportSize(int width, int height) {
return setViewportSize(new ViewportSize(width, height));
}
/**
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. Use {@code null} to disable the consistent
* viewport emulation.
*
* <p> <strong>NOTE:</strong> The {@code null} value opts out from the default presets, makes viewport depend on the host window size defined by the
* operating system. It makes the execution of the tests non-deterministic.
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. {@code null} disables the default
* viewport.
*/
public NewContextOptions setViewportSize(ViewportSize viewportSize) {
this.viewportSize = Optional.ofNullable(viewportSize);
@@ -731,11 +722,8 @@ public interface Browser extends AutoCloseable {
*/
public String userAgent;
/**
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. Use {@code null} to disable the consistent
* viewport emulation.
*
* <p> <strong>NOTE:</strong> The {@code null} value opts out from the default presets, makes viewport depend on the host window size defined by the
* operating system. It makes the execution of the tests non-deterministic.
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. {@code null} disables the default
* viewport.
*/
public Optional<ViewportSize> viewportSize;
@@ -1043,21 +1031,15 @@ public interface Browser extends AutoCloseable {
return this;
}
/**
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. Use {@code null} to disable the consistent
* viewport emulation.
*
* <p> <strong>NOTE:</strong> The {@code null} value opts out from the default presets, makes viewport depend on the host window size defined by the
* operating system. It makes the execution of the tests non-deterministic.
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. {@code null} disables the default
* viewport.
*/
public NewPageOptions setViewportSize(int width, int height) {
return setViewportSize(new ViewportSize(width, height));
}
/**
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. Use {@code null} to disable the consistent
* viewport emulation.
*
* <p> <strong>NOTE:</strong> The {@code null} value opts out from the default presets, makes viewport depend on the host window size defined by the
* operating system. It makes the execution of the tests non-deterministic.
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. {@code null} disables the default
* viewport.
*/
public NewPageOptions setViewportSize(ViewportSize viewportSize) {
this.viewportSize = Optional.ofNullable(viewportSize);
@@ -601,11 +601,8 @@ public interface BrowserType {
*/
public String userAgent;
/**
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. Use {@code null} to disable the consistent
* viewport emulation.
*
* <p> <strong>NOTE:</strong> The {@code null} value opts out from the default presets, makes viewport depend on the host window size defined by the
* operating system. It makes the execution of the tests non-deterministic.
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. {@code null} disables the default
* viewport.
*/
public Optional<ViewportSize> viewportSize;
@@ -1024,21 +1021,15 @@ public interface BrowserType {
return this;
}
/**
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. Use {@code null} to disable the consistent
* viewport emulation.
*
* <p> <strong>NOTE:</strong> The {@code null} value opts out from the default presets, makes viewport depend on the host window size defined by the
* operating system. It makes the execution of the tests non-deterministic.
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. {@code null} disables the default
* viewport.
*/
public LaunchPersistentContextOptions setViewportSize(int width, int height) {
return setViewportSize(new ViewportSize(width, height));
}
/**
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. Use {@code null} to disable the consistent
* viewport emulation.
*
* <p> <strong>NOTE:</strong> The {@code null} value opts out from the default presets, makes viewport depend on the host window size defined by the
* operating system. It makes the execution of the tests non-deterministic.
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. {@code null} disables the default
* viewport.
*/
public LaunchPersistentContextOptions setViewportSize(ViewportSize viewportSize) {
this.viewportSize = Optional.ofNullable(viewportSize);
@@ -22,16 +22,16 @@ import java.util.*;
* {@code ConsoleMessage} objects are dispatched by page via the {@link Page#onConsoleMessage Page.onConsoleMessage()}
* event. For each console messages logged in the page there will be corresponding event in the Playwright context.
* <pre>{@code
* // Listen for all console messages and print them to the standard output.
* // Listen for all System.out.printlns
* page.onConsoleMessage(msg -> System.out.println(msg.text()));
*
* // Listen for all console messages and print errors to the standard output.
* // Listen for all console events and handle errors
* page.onConsoleMessage(msg -> {
* if ("error".equals(msg.type()))
* System.out.println("Error text: " + msg.text());
* });
*
* // Get the next console message
* // Get the next System.out.println
* ConsoleMessage msg = page.waitForConsoleMessage(() -> {
* // Issue console.log inside the page
* page.evaluate("console.log('hello', 42, { foo: 'bar' });");
@@ -3043,14 +3043,7 @@ public interface Frame {
*/
String getAttribute(String selector, String name, GetAttributeOptions options);
/**
* Allows locating elements by their alt text.
*
* <p> **Usage**
*
* <p> For example, this method will find the image by alt text "Playwright logo":
* <pre>{@code
* page.getByAltText("Playwright logo").click();
* }</pre>
* Allows locating elements by their alt text. For example, this method will find the image by alt text "Castle":
*
* @param text Text to locate the element for.
* @since v1.27
@@ -3059,28 +3052,14 @@ public interface Frame {
return getByAltText(text, null);
}
/**
* Allows locating elements by their alt text.
*
* <p> **Usage**
*
* <p> For example, this method will find the image by alt text "Playwright logo":
* <pre>{@code
* page.getByAltText("Playwright logo").click();
* }</pre>
* Allows locating elements by their alt text. For example, this method will find the image by alt text "Castle":
*
* @param text Text to locate the element for.
* @since v1.27
*/
Locator getByAltText(String text, GetByAltTextOptions options);
/**
* Allows locating elements by their alt text.
*
* <p> **Usage**
*
* <p> For example, this method will find the image by alt text "Playwright logo":
* <pre>{@code
* page.getByAltText("Playwright logo").click();
* }</pre>
* Allows locating elements by their alt text. For example, this method will find the image by alt text "Castle":
*
* @param text Text to locate the element for.
* @since v1.27
@@ -3089,28 +3068,15 @@ public interface Frame {
return getByAltText(text, null);
}
/**
* Allows locating elements by their alt text.
*
* <p> **Usage**
*
* <p> For example, this method will find the image by alt text "Playwright logo":
* <pre>{@code
* page.getByAltText("Playwright logo").click();
* }</pre>
* Allows locating elements by their alt text. For example, this method will find the image by alt text "Castle":
*
* @param text Text to locate the element for.
* @since v1.27
*/
Locator getByAltText(Pattern text, GetByAltTextOptions options);
/**
* Allows locating input elements by the text of the associated label.
*
* <p> **Usage**
*
* <p> For example, this method will find the input by label text "Password" in the following DOM:
* <pre>{@code
* page.getByLabel("Password").fill("secret");
* }</pre>
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
* @since v1.27
@@ -3119,28 +3085,16 @@ public interface Frame {
return getByLabel(text, null);
}
/**
* Allows locating input elements by the text of the associated label.
*
* <p> **Usage**
*
* <p> For example, this method will find the input by label text "Password" in the following DOM:
* <pre>{@code
* page.getByLabel("Password").fill("secret");
* }</pre>
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
* @since v1.27
*/
Locator getByLabel(String text, GetByLabelOptions options);
/**
* Allows locating input elements by the text of the associated label.
*
* <p> **Usage**
*
* <p> For example, this method will find the input by label text "Password" in the following DOM:
* <pre>{@code
* page.getByLabel("Password").fill("secret");
* }</pre>
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
* @since v1.27
@@ -3149,30 +3103,16 @@ public interface Frame {
return getByLabel(text, null);
}
/**
* Allows locating input elements by the text of the associated label.
*
* <p> **Usage**
*
* <p> For example, this method will find the input by label text "Password" in the following DOM:
* <pre>{@code
* page.getByLabel("Password").fill("secret");
* }</pre>
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
* @since v1.27
*/
Locator getByLabel(Pattern text, GetByLabelOptions options);
/**
* Allows locating input elements by the placeholder text.
*
* <p> **Usage**
*
* <p> For example, consider the following DOM structure.
*
* <p> You can fill the input after locating it by the placeholder text:
* <pre>{@code
* page.getByPlaceholder("name@example.com").fill("playwright@microsoft.com");
* }</pre>
* Allows locating input elements by the placeholder text. For example, this method will find the input by placeholder
* "Country":
*
* @param text Text to locate the element for.
* @since v1.27
@@ -3181,32 +3121,16 @@ public interface Frame {
return getByPlaceholder(text, null);
}
/**
* Allows locating input elements by the placeholder text.
*
* <p> **Usage**
*
* <p> For example, consider the following DOM structure.
*
* <p> You can fill the input after locating it by the placeholder text:
* <pre>{@code
* page.getByPlaceholder("name@example.com").fill("playwright@microsoft.com");
* }</pre>
* Allows locating input elements by the placeholder text. For example, this method will find the input by placeholder
* "Country":
*
* @param text Text to locate the element for.
* @since v1.27
*/
Locator getByPlaceholder(String text, GetByPlaceholderOptions options);
/**
* Allows locating input elements by the placeholder text.
*
* <p> **Usage**
*
* <p> For example, consider the following DOM structure.
*
* <p> You can fill the input after locating it by the placeholder text:
* <pre>{@code
* page.getByPlaceholder("name@example.com").fill("playwright@microsoft.com");
* }</pre>
* Allows locating input elements by the placeholder text. For example, this method will find the input by placeholder
* "Country":
*
* @param text Text to locate the element for.
* @since v1.27
@@ -3215,16 +3139,8 @@ public interface Frame {
return getByPlaceholder(text, null);
}
/**
* Allows locating input elements by the placeholder text.
*
* <p> **Usage**
*
* <p> For example, consider the following DOM structure.
*
* <p> You can fill the input after locating it by the placeholder text:
* <pre>{@code
* page.getByPlaceholder("name@example.com").fill("playwright@microsoft.com");
* }</pre>
* Allows locating input elements by the placeholder text. For example, this method will find the input by placeholder
* "Country":
*
* @param text Text to locate the element for.
* @since v1.27
@@ -3233,39 +3149,14 @@ public interface Frame {
/**
* Allows locating elements by their <a href="https://www.w3.org/TR/wai-aria-1.2/#roles">ARIA role</a>, <a
* href="https://www.w3.org/TR/wai-aria-1.2/#aria-attributes">ARIA attributes</a> and <a
* href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
* href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>. Note that role selector **does not
* replace** accessibility audits and conformance tests, but rather gives early feedback about the ARIA guidelines.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure.
*
* <p> You can locate each element by it's implicit role:
* <pre>{@code
* assertThat(page
* .getByRole(AriaRole.HEADING,
* new Page.GetByRoleOptions().setName("Sign up")))
* .isVisible();
*
* page.getByRole(AriaRole.CHECKBOX,
* new Page.GetByRoleOptions().setName("Subscribe"))
* .check();
*
* page.getByRole(AriaRole.BUTTON,
* new Page.GetByRoleOptions().setName(
* Pattern.compile("submit", Pattern.CASE_INSENSITIVE)))
* .click();
* }</pre>
*
* <p> **Details**
*
* <p> Role selector **does not replace** accessibility audits and conformance tests, but rather gives early feedback about the
* ARIA guidelines.
*
* <p> Many html elements have an implicitly <a href="https://w3c.github.io/html-aam/#html-element-role-mappings">defined
* role</a> that is recognized by the role selector. You can find all the <a
* href="https://www.w3.org/TR/wai-aria-1.2/#role_definitions">supported roles here</a>. ARIA guidelines **do not
* recommend** duplicating implicit roles and attributes by setting {@code role} and/or {@code aria-*} attributes to
* default values.
* <p> Note that many html elements have an implicitly <a
* href="https://w3c.github.io/html-aam/#html-element-role-mappings">defined role</a> that is recognized by the role
* selector. You can find all the <a href="https://www.w3.org/TR/wai-aria-1.2/#role_definitions">supported roles here</a>.
* ARIA guidelines **do not recommend** duplicating implicit roles and attributes by setting {@code role} and/or {@code
* aria-*} attributes to default values.
*
* @param role Required aria role.
* @since v1.27
@@ -3276,95 +3167,37 @@ public interface Frame {
/**
* Allows locating elements by their <a href="https://www.w3.org/TR/wai-aria-1.2/#roles">ARIA role</a>, <a
* href="https://www.w3.org/TR/wai-aria-1.2/#aria-attributes">ARIA attributes</a> and <a
* href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
* href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>. Note that role selector **does not
* replace** accessibility audits and conformance tests, but rather gives early feedback about the ARIA guidelines.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure.
*
* <p> You can locate each element by it's implicit role:
* <pre>{@code
* assertThat(page
* .getByRole(AriaRole.HEADING,
* new Page.GetByRoleOptions().setName("Sign up")))
* .isVisible();
*
* page.getByRole(AriaRole.CHECKBOX,
* new Page.GetByRoleOptions().setName("Subscribe"))
* .check();
*
* page.getByRole(AriaRole.BUTTON,
* new Page.GetByRoleOptions().setName(
* Pattern.compile("submit", Pattern.CASE_INSENSITIVE)))
* .click();
* }</pre>
*
* <p> **Details**
*
* <p> Role selector **does not replace** accessibility audits and conformance tests, but rather gives early feedback about the
* ARIA guidelines.
*
* <p> Many html elements have an implicitly <a href="https://w3c.github.io/html-aam/#html-element-role-mappings">defined
* role</a> that is recognized by the role selector. You can find all the <a
* href="https://www.w3.org/TR/wai-aria-1.2/#role_definitions">supported roles here</a>. ARIA guidelines **do not
* recommend** duplicating implicit roles and attributes by setting {@code role} and/or {@code aria-*} attributes to
* default values.
* <p> Note that many html elements have an implicitly <a
* href="https://w3c.github.io/html-aam/#html-element-role-mappings">defined role</a> that is recognized by the role
* selector. You can find all the <a href="https://www.w3.org/TR/wai-aria-1.2/#role_definitions">supported roles here</a>.
* ARIA guidelines **do not recommend** duplicating implicit roles and attributes by setting {@code role} and/or {@code
* aria-*} attributes to default values.
*
* @param role Required aria role.
* @since v1.27
*/
Locator getByRole(AriaRole role, GetByRoleOptions options);
/**
* Locate element by the test id.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure.
*
* <p> You can locate the element by it's test id:
* <pre>{@code
* page.getByTestId("directions").click();
* }</pre>
*
* <p> **Details**
*
* <p> By default, the {@code data-testid} attribute is used as a test id. Use {@link Selectors#setTestIdAttribute
* Selectors.setTestIdAttribute()} to configure a different test id attribute if necessary.
* Locate element by the test id. By default, the {@code data-testid} attribute is used as a test id. Use {@link
* Selectors#setTestIdAttribute Selectors.setTestIdAttribute()} to configure a different test id attribute if necessary.
*
* @param testId Id to locate the element by.
* @since v1.27
*/
Locator getByTestId(String testId);
/**
* Locate element by the test id.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure.
*
* <p> You can locate the element by it's test id:
* <pre>{@code
* page.getByTestId("directions").click();
* }</pre>
*
* <p> **Details**
*
* <p> By default, the {@code data-testid} attribute is used as a test id. Use {@link Selectors#setTestIdAttribute
* Selectors.setTestIdAttribute()} to configure a different test id attribute if necessary.
* Locate element by the test id. By default, the {@code data-testid} attribute is used as a test id. Use {@link
* Selectors#setTestIdAttribute Selectors.setTestIdAttribute()} to configure a different test id attribute if necessary.
*
* @param testId Id to locate the element by.
* @since v1.27
*/
Locator getByTestId(Pattern testId);
/**
* Allows locating elements that contain given text.
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure:
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
@@ -3384,12 +3217,13 @@ public interface Frame {
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> **Details**
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text
* content. For example, locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
@@ -3399,14 +3233,7 @@ public interface Frame {
return getByText(text, null);
}
/**
* Allows locating elements that contain given text.
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure:
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
@@ -3426,12 +3253,13 @@ public interface Frame {
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> **Details**
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text
* content. For example, locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
@@ -3439,14 +3267,7 @@ public interface Frame {
*/
Locator getByText(String text, GetByTextOptions options);
/**
* Allows locating elements that contain given text.
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure:
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
@@ -3466,12 +3287,13 @@ public interface Frame {
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> **Details**
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text
* content. For example, locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
@@ -3481,14 +3303,7 @@ public interface Frame {
return getByText(text, null);
}
/**
* Allows locating elements that contain given text.
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure:
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
@@ -3508,12 +3323,13 @@ public interface Frame {
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> **Details**
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text
* content. For example, locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
@@ -3521,16 +3337,7 @@ public interface Frame {
*/
Locator getByText(Pattern text, GetByTextOptions options);
/**
* Allows locating elements by their title attribute.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure.
*
* <p> You can check the issues count after locating it by the title text:
* <pre>{@code
* assertThat(page.getByTitle("Issues count")).hasText("25 issues");
* }</pre>
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
* @since v1.27
@@ -3539,32 +3346,14 @@ public interface Frame {
return getByTitle(text, null);
}
/**
* Allows locating elements by their title attribute.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure.
*
* <p> You can check the issues count after locating it by the title text:
* <pre>{@code
* assertThat(page.getByTitle("Issues count")).hasText("25 issues");
* }</pre>
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
* @since v1.27
*/
Locator getByTitle(String text, GetByTitleOptions options);
/**
* Allows locating elements by their title attribute.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure.
*
* <p> You can check the issues count after locating it by the title text:
* <pre>{@code
* assertThat(page.getByTitle("Issues count")).hasText("25 issues");
* }</pre>
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
* @since v1.27
@@ -3573,16 +3362,7 @@ public interface Frame {
return getByTitle(text, null);
}
/**
* Allows locating elements by their title attribute.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure.
*
* <p> You can check the issues count after locating it by the title text:
* <pre>{@code
* assertThat(page.getByTitle("Issues count")).hasText("25 issues");
* }</pre>
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
* @since v1.27
@@ -342,14 +342,7 @@ public interface FrameLocator {
*/
FrameLocator frameLocator(String selector);
/**
* Allows locating elements by their alt text.
*
* <p> **Usage**
*
* <p> For example, this method will find the image by alt text "Playwright logo":
* <pre>{@code
* page.getByAltText("Playwright logo").click();
* }</pre>
* Allows locating elements by their alt text. For example, this method will find the image by alt text "Castle":
*
* @param text Text to locate the element for.
* @since v1.27
@@ -358,28 +351,14 @@ public interface FrameLocator {
return getByAltText(text, null);
}
/**
* Allows locating elements by their alt text.
*
* <p> **Usage**
*
* <p> For example, this method will find the image by alt text "Playwright logo":
* <pre>{@code
* page.getByAltText("Playwright logo").click();
* }</pre>
* Allows locating elements by their alt text. For example, this method will find the image by alt text "Castle":
*
* @param text Text to locate the element for.
* @since v1.27
*/
Locator getByAltText(String text, GetByAltTextOptions options);
/**
* Allows locating elements by their alt text.
*
* <p> **Usage**
*
* <p> For example, this method will find the image by alt text "Playwright logo":
* <pre>{@code
* page.getByAltText("Playwright logo").click();
* }</pre>
* Allows locating elements by their alt text. For example, this method will find the image by alt text "Castle":
*
* @param text Text to locate the element for.
* @since v1.27
@@ -388,28 +367,15 @@ public interface FrameLocator {
return getByAltText(text, null);
}
/**
* Allows locating elements by their alt text.
*
* <p> **Usage**
*
* <p> For example, this method will find the image by alt text "Playwright logo":
* <pre>{@code
* page.getByAltText("Playwright logo").click();
* }</pre>
* Allows locating elements by their alt text. For example, this method will find the image by alt text "Castle":
*
* @param text Text to locate the element for.
* @since v1.27
*/
Locator getByAltText(Pattern text, GetByAltTextOptions options);
/**
* Allows locating input elements by the text of the associated label.
*
* <p> **Usage**
*
* <p> For example, this method will find the input by label text "Password" in the following DOM:
* <pre>{@code
* page.getByLabel("Password").fill("secret");
* }</pre>
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
* @since v1.27
@@ -418,28 +384,16 @@ public interface FrameLocator {
return getByLabel(text, null);
}
/**
* Allows locating input elements by the text of the associated label.
*
* <p> **Usage**
*
* <p> For example, this method will find the input by label text "Password" in the following DOM:
* <pre>{@code
* page.getByLabel("Password").fill("secret");
* }</pre>
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
* @since v1.27
*/
Locator getByLabel(String text, GetByLabelOptions options);
/**
* Allows locating input elements by the text of the associated label.
*
* <p> **Usage**
*
* <p> For example, this method will find the input by label text "Password" in the following DOM:
* <pre>{@code
* page.getByLabel("Password").fill("secret");
* }</pre>
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
* @since v1.27
@@ -448,30 +402,16 @@ public interface FrameLocator {
return getByLabel(text, null);
}
/**
* Allows locating input elements by the text of the associated label.
*
* <p> **Usage**
*
* <p> For example, this method will find the input by label text "Password" in the following DOM:
* <pre>{@code
* page.getByLabel("Password").fill("secret");
* }</pre>
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
* @since v1.27
*/
Locator getByLabel(Pattern text, GetByLabelOptions options);
/**
* Allows locating input elements by the placeholder text.
*
* <p> **Usage**
*
* <p> For example, consider the following DOM structure.
*
* <p> You can fill the input after locating it by the placeholder text:
* <pre>{@code
* page.getByPlaceholder("name@example.com").fill("playwright@microsoft.com");
* }</pre>
* Allows locating input elements by the placeholder text. For example, this method will find the input by placeholder
* "Country":
*
* @param text Text to locate the element for.
* @since v1.27
@@ -480,32 +420,16 @@ public interface FrameLocator {
return getByPlaceholder(text, null);
}
/**
* Allows locating input elements by the placeholder text.
*
* <p> **Usage**
*
* <p> For example, consider the following DOM structure.
*
* <p> You can fill the input after locating it by the placeholder text:
* <pre>{@code
* page.getByPlaceholder("name@example.com").fill("playwright@microsoft.com");
* }</pre>
* Allows locating input elements by the placeholder text. For example, this method will find the input by placeholder
* "Country":
*
* @param text Text to locate the element for.
* @since v1.27
*/
Locator getByPlaceholder(String text, GetByPlaceholderOptions options);
/**
* Allows locating input elements by the placeholder text.
*
* <p> **Usage**
*
* <p> For example, consider the following DOM structure.
*
* <p> You can fill the input after locating it by the placeholder text:
* <pre>{@code
* page.getByPlaceholder("name@example.com").fill("playwright@microsoft.com");
* }</pre>
* Allows locating input elements by the placeholder text. For example, this method will find the input by placeholder
* "Country":
*
* @param text Text to locate the element for.
* @since v1.27
@@ -514,16 +438,8 @@ public interface FrameLocator {
return getByPlaceholder(text, null);
}
/**
* Allows locating input elements by the placeholder text.
*
* <p> **Usage**
*
* <p> For example, consider the following DOM structure.
*
* <p> You can fill the input after locating it by the placeholder text:
* <pre>{@code
* page.getByPlaceholder("name@example.com").fill("playwright@microsoft.com");
* }</pre>
* Allows locating input elements by the placeholder text. For example, this method will find the input by placeholder
* "Country":
*
* @param text Text to locate the element for.
* @since v1.27
@@ -532,39 +448,14 @@ public interface FrameLocator {
/**
* Allows locating elements by their <a href="https://www.w3.org/TR/wai-aria-1.2/#roles">ARIA role</a>, <a
* href="https://www.w3.org/TR/wai-aria-1.2/#aria-attributes">ARIA attributes</a> and <a
* href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
* href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>. Note that role selector **does not
* replace** accessibility audits and conformance tests, but rather gives early feedback about the ARIA guidelines.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure.
*
* <p> You can locate each element by it's implicit role:
* <pre>{@code
* assertThat(page
* .getByRole(AriaRole.HEADING,
* new Page.GetByRoleOptions().setName("Sign up")))
* .isVisible();
*
* page.getByRole(AriaRole.CHECKBOX,
* new Page.GetByRoleOptions().setName("Subscribe"))
* .check();
*
* page.getByRole(AriaRole.BUTTON,
* new Page.GetByRoleOptions().setName(
* Pattern.compile("submit", Pattern.CASE_INSENSITIVE)))
* .click();
* }</pre>
*
* <p> **Details**
*
* <p> Role selector **does not replace** accessibility audits and conformance tests, but rather gives early feedback about the
* ARIA guidelines.
*
* <p> Many html elements have an implicitly <a href="https://w3c.github.io/html-aam/#html-element-role-mappings">defined
* role</a> that is recognized by the role selector. You can find all the <a
* href="https://www.w3.org/TR/wai-aria-1.2/#role_definitions">supported roles here</a>. ARIA guidelines **do not
* recommend** duplicating implicit roles and attributes by setting {@code role} and/or {@code aria-*} attributes to
* default values.
* <p> Note that many html elements have an implicitly <a
* href="https://w3c.github.io/html-aam/#html-element-role-mappings">defined role</a> that is recognized by the role
* selector. You can find all the <a href="https://www.w3.org/TR/wai-aria-1.2/#role_definitions">supported roles here</a>.
* ARIA guidelines **do not recommend** duplicating implicit roles and attributes by setting {@code role} and/or {@code
* aria-*} attributes to default values.
*
* @param role Required aria role.
* @since v1.27
@@ -575,95 +466,37 @@ public interface FrameLocator {
/**
* Allows locating elements by their <a href="https://www.w3.org/TR/wai-aria-1.2/#roles">ARIA role</a>, <a
* href="https://www.w3.org/TR/wai-aria-1.2/#aria-attributes">ARIA attributes</a> and <a
* href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
* href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>. Note that role selector **does not
* replace** accessibility audits and conformance tests, but rather gives early feedback about the ARIA guidelines.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure.
*
* <p> You can locate each element by it's implicit role:
* <pre>{@code
* assertThat(page
* .getByRole(AriaRole.HEADING,
* new Page.GetByRoleOptions().setName("Sign up")))
* .isVisible();
*
* page.getByRole(AriaRole.CHECKBOX,
* new Page.GetByRoleOptions().setName("Subscribe"))
* .check();
*
* page.getByRole(AriaRole.BUTTON,
* new Page.GetByRoleOptions().setName(
* Pattern.compile("submit", Pattern.CASE_INSENSITIVE)))
* .click();
* }</pre>
*
* <p> **Details**
*
* <p> Role selector **does not replace** accessibility audits and conformance tests, but rather gives early feedback about the
* ARIA guidelines.
*
* <p> Many html elements have an implicitly <a href="https://w3c.github.io/html-aam/#html-element-role-mappings">defined
* role</a> that is recognized by the role selector. You can find all the <a
* href="https://www.w3.org/TR/wai-aria-1.2/#role_definitions">supported roles here</a>. ARIA guidelines **do not
* recommend** duplicating implicit roles and attributes by setting {@code role} and/or {@code aria-*} attributes to
* default values.
* <p> Note that many html elements have an implicitly <a
* href="https://w3c.github.io/html-aam/#html-element-role-mappings">defined role</a> that is recognized by the role
* selector. You can find all the <a href="https://www.w3.org/TR/wai-aria-1.2/#role_definitions">supported roles here</a>.
* ARIA guidelines **do not recommend** duplicating implicit roles and attributes by setting {@code role} and/or {@code
* aria-*} attributes to default values.
*
* @param role Required aria role.
* @since v1.27
*/
Locator getByRole(AriaRole role, GetByRoleOptions options);
/**
* Locate element by the test id.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure.
*
* <p> You can locate the element by it's test id:
* <pre>{@code
* page.getByTestId("directions").click();
* }</pre>
*
* <p> **Details**
*
* <p> By default, the {@code data-testid} attribute is used as a test id. Use {@link Selectors#setTestIdAttribute
* Selectors.setTestIdAttribute()} to configure a different test id attribute if necessary.
* Locate element by the test id. By default, the {@code data-testid} attribute is used as a test id. Use {@link
* Selectors#setTestIdAttribute Selectors.setTestIdAttribute()} to configure a different test id attribute if necessary.
*
* @param testId Id to locate the element by.
* @since v1.27
*/
Locator getByTestId(String testId);
/**
* Locate element by the test id.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure.
*
* <p> You can locate the element by it's test id:
* <pre>{@code
* page.getByTestId("directions").click();
* }</pre>
*
* <p> **Details**
*
* <p> By default, the {@code data-testid} attribute is used as a test id. Use {@link Selectors#setTestIdAttribute
* Selectors.setTestIdAttribute()} to configure a different test id attribute if necessary.
* Locate element by the test id. By default, the {@code data-testid} attribute is used as a test id. Use {@link
* Selectors#setTestIdAttribute Selectors.setTestIdAttribute()} to configure a different test id attribute if necessary.
*
* @param testId Id to locate the element by.
* @since v1.27
*/
Locator getByTestId(Pattern testId);
/**
* Allows locating elements that contain given text.
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure:
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
@@ -683,12 +516,13 @@ public interface FrameLocator {
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> **Details**
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text
* content. For example, locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
@@ -698,14 +532,7 @@ public interface FrameLocator {
return getByText(text, null);
}
/**
* Allows locating elements that contain given text.
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure:
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
@@ -725,12 +552,13 @@ public interface FrameLocator {
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> **Details**
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text
* content. For example, locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
@@ -738,14 +566,7 @@ public interface FrameLocator {
*/
Locator getByText(String text, GetByTextOptions options);
/**
* Allows locating elements that contain given text.
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure:
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
@@ -765,12 +586,13 @@ public interface FrameLocator {
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> **Details**
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text
* content. For example, locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
@@ -780,14 +602,7 @@ public interface FrameLocator {
return getByText(text, null);
}
/**
* Allows locating elements that contain given text.
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure:
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
@@ -807,12 +622,13 @@ public interface FrameLocator {
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> **Details**
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text
* content. For example, locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
@@ -820,16 +636,7 @@ public interface FrameLocator {
*/
Locator getByText(Pattern text, GetByTextOptions options);
/**
* Allows locating elements by their title attribute.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure.
*
* <p> You can check the issues count after locating it by the title text:
* <pre>{@code
* assertThat(page.getByTitle("Issues count")).hasText("25 issues");
* }</pre>
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
* @since v1.27
@@ -838,32 +645,14 @@ public interface FrameLocator {
return getByTitle(text, null);
}
/**
* Allows locating elements by their title attribute.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure.
*
* <p> You can check the issues count after locating it by the title text:
* <pre>{@code
* assertThat(page.getByTitle("Issues count")).hasText("25 issues");
* }</pre>
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
* @since v1.27
*/
Locator getByTitle(String text, GetByTitleOptions options);
/**
* Allows locating elements by their title attribute.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure.
*
* <p> You can check the issues count after locating it by the title text:
* <pre>{@code
* assertThat(page.getByTitle("Issues count")).hasText("25 issues");
* }</pre>
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
* @since v1.27
@@ -872,16 +661,7 @@ public interface FrameLocator {
return getByTitle(text, null);
}
/**
* Allows locating elements by their title attribute.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure.
*
* <p> You can check the issues count after locating it by the title text:
* <pre>{@code
* assertThat(page.getByTitle("Issues count")).hasText("25 issues");
* }</pre>
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
* @since v1.27
File diff suppressed because it is too large Load Diff
@@ -4550,14 +4550,7 @@ public interface Page extends AutoCloseable {
*/
String getAttribute(String selector, String name, GetAttributeOptions options);
/**
* Allows locating elements by their alt text.
*
* <p> **Usage**
*
* <p> For example, this method will find the image by alt text "Playwright logo":
* <pre>{@code
* page.getByAltText("Playwright logo").click();
* }</pre>
* Allows locating elements by their alt text. For example, this method will find the image by alt text "Castle":
*
* @param text Text to locate the element for.
* @since v1.27
@@ -4566,28 +4559,14 @@ public interface Page extends AutoCloseable {
return getByAltText(text, null);
}
/**
* Allows locating elements by their alt text.
*
* <p> **Usage**
*
* <p> For example, this method will find the image by alt text "Playwright logo":
* <pre>{@code
* page.getByAltText("Playwright logo").click();
* }</pre>
* Allows locating elements by their alt text. For example, this method will find the image by alt text "Castle":
*
* @param text Text to locate the element for.
* @since v1.27
*/
Locator getByAltText(String text, GetByAltTextOptions options);
/**
* Allows locating elements by their alt text.
*
* <p> **Usage**
*
* <p> For example, this method will find the image by alt text "Playwright logo":
* <pre>{@code
* page.getByAltText("Playwright logo").click();
* }</pre>
* Allows locating elements by their alt text. For example, this method will find the image by alt text "Castle":
*
* @param text Text to locate the element for.
* @since v1.27
@@ -4596,28 +4575,15 @@ public interface Page extends AutoCloseable {
return getByAltText(text, null);
}
/**
* Allows locating elements by their alt text.
*
* <p> **Usage**
*
* <p> For example, this method will find the image by alt text "Playwright logo":
* <pre>{@code
* page.getByAltText("Playwright logo").click();
* }</pre>
* Allows locating elements by their alt text. For example, this method will find the image by alt text "Castle":
*
* @param text Text to locate the element for.
* @since v1.27
*/
Locator getByAltText(Pattern text, GetByAltTextOptions options);
/**
* Allows locating input elements by the text of the associated label.
*
* <p> **Usage**
*
* <p> For example, this method will find the input by label text "Password" in the following DOM:
* <pre>{@code
* page.getByLabel("Password").fill("secret");
* }</pre>
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
* @since v1.27
@@ -4626,28 +4592,16 @@ public interface Page extends AutoCloseable {
return getByLabel(text, null);
}
/**
* Allows locating input elements by the text of the associated label.
*
* <p> **Usage**
*
* <p> For example, this method will find the input by label text "Password" in the following DOM:
* <pre>{@code
* page.getByLabel("Password").fill("secret");
* }</pre>
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
* @since v1.27
*/
Locator getByLabel(String text, GetByLabelOptions options);
/**
* Allows locating input elements by the text of the associated label.
*
* <p> **Usage**
*
* <p> For example, this method will find the input by label text "Password" in the following DOM:
* <pre>{@code
* page.getByLabel("Password").fill("secret");
* }</pre>
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
* @since v1.27
@@ -4656,30 +4610,16 @@ public interface Page extends AutoCloseable {
return getByLabel(text, null);
}
/**
* Allows locating input elements by the text of the associated label.
*
* <p> **Usage**
*
* <p> For example, this method will find the input by label text "Password" in the following DOM:
* <pre>{@code
* page.getByLabel("Password").fill("secret");
* }</pre>
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text "Password" in the following DOM:
*
* @param text Text to locate the element for.
* @since v1.27
*/
Locator getByLabel(Pattern text, GetByLabelOptions options);
/**
* Allows locating input elements by the placeholder text.
*
* <p> **Usage**
*
* <p> For example, consider the following DOM structure.
*
* <p> You can fill the input after locating it by the placeholder text:
* <pre>{@code
* page.getByPlaceholder("name@example.com").fill("playwright@microsoft.com");
* }</pre>
* Allows locating input elements by the placeholder text. For example, this method will find the input by placeholder
* "Country":
*
* @param text Text to locate the element for.
* @since v1.27
@@ -4688,32 +4628,16 @@ public interface Page extends AutoCloseable {
return getByPlaceholder(text, null);
}
/**
* Allows locating input elements by the placeholder text.
*
* <p> **Usage**
*
* <p> For example, consider the following DOM structure.
*
* <p> You can fill the input after locating it by the placeholder text:
* <pre>{@code
* page.getByPlaceholder("name@example.com").fill("playwright@microsoft.com");
* }</pre>
* Allows locating input elements by the placeholder text. For example, this method will find the input by placeholder
* "Country":
*
* @param text Text to locate the element for.
* @since v1.27
*/
Locator getByPlaceholder(String text, GetByPlaceholderOptions options);
/**
* Allows locating input elements by the placeholder text.
*
* <p> **Usage**
*
* <p> For example, consider the following DOM structure.
*
* <p> You can fill the input after locating it by the placeholder text:
* <pre>{@code
* page.getByPlaceholder("name@example.com").fill("playwright@microsoft.com");
* }</pre>
* Allows locating input elements by the placeholder text. For example, this method will find the input by placeholder
* "Country":
*
* @param text Text to locate the element for.
* @since v1.27
@@ -4722,16 +4646,8 @@ public interface Page extends AutoCloseable {
return getByPlaceholder(text, null);
}
/**
* Allows locating input elements by the placeholder text.
*
* <p> **Usage**
*
* <p> For example, consider the following DOM structure.
*
* <p> You can fill the input after locating it by the placeholder text:
* <pre>{@code
* page.getByPlaceholder("name@example.com").fill("playwright@microsoft.com");
* }</pre>
* Allows locating input elements by the placeholder text. For example, this method will find the input by placeholder
* "Country":
*
* @param text Text to locate the element for.
* @since v1.27
@@ -4740,39 +4656,14 @@ public interface Page extends AutoCloseable {
/**
* Allows locating elements by their <a href="https://www.w3.org/TR/wai-aria-1.2/#roles">ARIA role</a>, <a
* href="https://www.w3.org/TR/wai-aria-1.2/#aria-attributes">ARIA attributes</a> and <a
* href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
* href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>. Note that role selector **does not
* replace** accessibility audits and conformance tests, but rather gives early feedback about the ARIA guidelines.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure.
*
* <p> You can locate each element by it's implicit role:
* <pre>{@code
* assertThat(page
* .getByRole(AriaRole.HEADING,
* new Page.GetByRoleOptions().setName("Sign up")))
* .isVisible();
*
* page.getByRole(AriaRole.CHECKBOX,
* new Page.GetByRoleOptions().setName("Subscribe"))
* .check();
*
* page.getByRole(AriaRole.BUTTON,
* new Page.GetByRoleOptions().setName(
* Pattern.compile("submit", Pattern.CASE_INSENSITIVE)))
* .click();
* }</pre>
*
* <p> **Details**
*
* <p> Role selector **does not replace** accessibility audits and conformance tests, but rather gives early feedback about the
* ARIA guidelines.
*
* <p> Many html elements have an implicitly <a href="https://w3c.github.io/html-aam/#html-element-role-mappings">defined
* role</a> that is recognized by the role selector. You can find all the <a
* href="https://www.w3.org/TR/wai-aria-1.2/#role_definitions">supported roles here</a>. ARIA guidelines **do not
* recommend** duplicating implicit roles and attributes by setting {@code role} and/or {@code aria-*} attributes to
* default values.
* <p> Note that many html elements have an implicitly <a
* href="https://w3c.github.io/html-aam/#html-element-role-mappings">defined role</a> that is recognized by the role
* selector. You can find all the <a href="https://www.w3.org/TR/wai-aria-1.2/#role_definitions">supported roles here</a>.
* ARIA guidelines **do not recommend** duplicating implicit roles and attributes by setting {@code role} and/or {@code
* aria-*} attributes to default values.
*
* @param role Required aria role.
* @since v1.27
@@ -4783,95 +4674,37 @@ public interface Page extends AutoCloseable {
/**
* Allows locating elements by their <a href="https://www.w3.org/TR/wai-aria-1.2/#roles">ARIA role</a>, <a
* href="https://www.w3.org/TR/wai-aria-1.2/#aria-attributes">ARIA attributes</a> and <a
* href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
* href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>. Note that role selector **does not
* replace** accessibility audits and conformance tests, but rather gives early feedback about the ARIA guidelines.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure.
*
* <p> You can locate each element by it's implicit role:
* <pre>{@code
* assertThat(page
* .getByRole(AriaRole.HEADING,
* new Page.GetByRoleOptions().setName("Sign up")))
* .isVisible();
*
* page.getByRole(AriaRole.CHECKBOX,
* new Page.GetByRoleOptions().setName("Subscribe"))
* .check();
*
* page.getByRole(AriaRole.BUTTON,
* new Page.GetByRoleOptions().setName(
* Pattern.compile("submit", Pattern.CASE_INSENSITIVE)))
* .click();
* }</pre>
*
* <p> **Details**
*
* <p> Role selector **does not replace** accessibility audits and conformance tests, but rather gives early feedback about the
* ARIA guidelines.
*
* <p> Many html elements have an implicitly <a href="https://w3c.github.io/html-aam/#html-element-role-mappings">defined
* role</a> that is recognized by the role selector. You can find all the <a
* href="https://www.w3.org/TR/wai-aria-1.2/#role_definitions">supported roles here</a>. ARIA guidelines **do not
* recommend** duplicating implicit roles and attributes by setting {@code role} and/or {@code aria-*} attributes to
* default values.
* <p> Note that many html elements have an implicitly <a
* href="https://w3c.github.io/html-aam/#html-element-role-mappings">defined role</a> that is recognized by the role
* selector. You can find all the <a href="https://www.w3.org/TR/wai-aria-1.2/#role_definitions">supported roles here</a>.
* ARIA guidelines **do not recommend** duplicating implicit roles and attributes by setting {@code role} and/or {@code
* aria-*} attributes to default values.
*
* @param role Required aria role.
* @since v1.27
*/
Locator getByRole(AriaRole role, GetByRoleOptions options);
/**
* Locate element by the test id.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure.
*
* <p> You can locate the element by it's test id:
* <pre>{@code
* page.getByTestId("directions").click();
* }</pre>
*
* <p> **Details**
*
* <p> By default, the {@code data-testid} attribute is used as a test id. Use {@link Selectors#setTestIdAttribute
* Selectors.setTestIdAttribute()} to configure a different test id attribute if necessary.
* Locate element by the test id. By default, the {@code data-testid} attribute is used as a test id. Use {@link
* Selectors#setTestIdAttribute Selectors.setTestIdAttribute()} to configure a different test id attribute if necessary.
*
* @param testId Id to locate the element by.
* @since v1.27
*/
Locator getByTestId(String testId);
/**
* Locate element by the test id.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure.
*
* <p> You can locate the element by it's test id:
* <pre>{@code
* page.getByTestId("directions").click();
* }</pre>
*
* <p> **Details**
*
* <p> By default, the {@code data-testid} attribute is used as a test id. Use {@link Selectors#setTestIdAttribute
* Selectors.setTestIdAttribute()} to configure a different test id attribute if necessary.
* Locate element by the test id. By default, the {@code data-testid} attribute is used as a test id. Use {@link
* Selectors#setTestIdAttribute Selectors.setTestIdAttribute()} to configure a different test id attribute if necessary.
*
* @param testId Id to locate the element by.
* @since v1.27
*/
Locator getByTestId(Pattern testId);
/**
* Allows locating elements that contain given text.
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure:
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
@@ -4891,12 +4724,13 @@ public interface Page extends AutoCloseable {
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> **Details**
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text
* content. For example, locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
@@ -4906,14 +4740,7 @@ public interface Page extends AutoCloseable {
return getByText(text, null);
}
/**
* Allows locating elements that contain given text.
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure:
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
@@ -4933,12 +4760,13 @@ public interface Page extends AutoCloseable {
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> **Details**
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text
* content. For example, locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
@@ -4946,14 +4774,7 @@ public interface Page extends AutoCloseable {
*/
Locator getByText(String text, GetByTextOptions options);
/**
* Allows locating elements that contain given text.
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure:
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
@@ -4973,12 +4794,13 @@ public interface Page extends AutoCloseable {
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> **Details**
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text
* content. For example, locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
@@ -4988,14 +4810,7 @@ public interface Page extends AutoCloseable {
return getByText(text, null);
}
/**
* Allows locating elements that contain given text.
*
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure:
* Allows locating elements that contain given text. Consider the following DOM structure:
*
* <p> You can locate by text substring, exact string, or a regular expression:
* <pre>{@code
@@ -5015,12 +4830,13 @@ public interface Page extends AutoCloseable {
* page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
* }</pre>
*
* <p> **Details**
* <p> See also {@link Locator#filter Locator.filter()} that allows to match by another criteria, like an accessible role, and
* then filter by the text content.
*
* <p> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* <p> <strong>NOTE:</strong> Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one,
* turns line breaks into spaces and ignores leading and trailing whitespace.
*
* <p> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text
* <p> <strong>NOTE:</strong> Input elements of the type {@code button} and {@code submit} are matched by their {@code value} instead of the text
* content. For example, locating by text {@code "Log in"} matches {@code <input type=button value="Log in">}.
*
* @param text Text to locate the element for.
@@ -5028,16 +4844,7 @@ public interface Page extends AutoCloseable {
*/
Locator getByText(Pattern text, GetByTextOptions options);
/**
* Allows locating elements by their title attribute.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure.
*
* <p> You can check the issues count after locating it by the title text:
* <pre>{@code
* assertThat(page.getByTitle("Issues count")).hasText("25 issues");
* }</pre>
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
* @since v1.27
@@ -5046,32 +4853,14 @@ public interface Page extends AutoCloseable {
return getByTitle(text, null);
}
/**
* Allows locating elements by their title attribute.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure.
*
* <p> You can check the issues count after locating it by the title text:
* <pre>{@code
* assertThat(page.getByTitle("Issues count")).hasText("25 issues");
* }</pre>
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
* @since v1.27
*/
Locator getByTitle(String text, GetByTitleOptions options);
/**
* Allows locating elements by their title attribute.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure.
*
* <p> You can check the issues count after locating it by the title text:
* <pre>{@code
* assertThat(page.getByTitle("Issues count")).hasText("25 issues");
* }</pre>
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
* @since v1.27
@@ -5080,16 +4869,7 @@ public interface Page extends AutoCloseable {
return getByTitle(text, null);
}
/**
* Allows locating elements by their title attribute.
*
* <p> **Usage**
*
* <p> Consider the following DOM structure.
*
* <p> You can check the issues count after locating it by the title text:
* <pre>{@code
* assertThat(page.getByTitle("Issues count")).hasText("25 issues");
* }</pre>
* Allows locating elements by their title. For example, this method will find the button by its title "Place the order":
*
* @param text Text to locate the element for.
* @since v1.27
@@ -5441,45 +5221,6 @@ public interface Page extends AutoCloseable {
* @since v1.8
*/
Mouse mouse();
/**
* Adds one-off {@code Dialog} handler. The handler will be removed immediately after next {@code Dialog} is created.
* <pre>{@code
* page.onceDialog(dialog -> {
* dialog.accept("foo");
* });
*
* // prints 'foo'
* System.out.println(page.evaluate("prompt('Enter string:')"));
*
* // prints 'null' as the dialog will be auto-dismissed because there are no handlers.
* System.out.println(page.evaluate("prompt('Enter string:')"));
* }</pre>
*
* <p> This code above is equivalent to:
* <pre>{@code
* Consumer<Dialog> handler = new Consumer<Dialog>() {
* @Override
* public void accept(Dialog dialog) {
* dialog.accept("foo");
* page.offDialog(this);
* }
* };
* page.onDialog(handler);
*
* // prints 'foo'
* System.out.println(page.evaluate("prompt('Enter string:')"));
*
* // prints 'null' as the dialog will be auto-dismissed because there are no handlers.
* System.out.println(page.evaluate("prompt('Enter string:')"));
* }</pre>
*
* @param handler Receives the {@code Dialog} object, it **must** either {@link Dialog#accept Dialog.accept()} or {@link Dialog#dismiss
* Dialog.dismiss()} the dialog - otherwise the page will <a
* href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#never_blocking">freeze</a> waiting for the
* dialog, and actions like click will never finish.
* @since v1.10
*/
void onceDialog(Consumer<Dialog> handler);
/**
* Returns the opener for popup pages and {@code null} for others. If the opener has been closed already the returns {@code
* null}.
@@ -6766,7 +6507,7 @@ public interface Page extends AutoCloseable {
* <p> When all steps combined have not finished during the specified {@code timeout}, this method throws a {@code
* TimeoutError}. Passing zero timeout disables this.
*
* <p> <strong>NOTE:</strong> {@link Page#tap Page.tap()} the method will throw if {@code hasTouch} option of the browser context is false.
* <p> <strong>NOTE:</strong> {@link Page#tap Page.tap()} requires that the {@code hasTouch} option of the browser context be set to true.
*
* @param selector A selector to search for an element. If there are multiple elements satisfying the selector, the first will be used.
* @since v1.8
@@ -6788,7 +6529,7 @@ public interface Page extends AutoCloseable {
* <p> When all steps combined have not finished during the specified {@code timeout}, this method throws a {@code
* TimeoutError}. Passing zero timeout disables this.
*
* <p> <strong>NOTE:</strong> {@link Page#tap Page.tap()} the method will throw if {@code hasTouch} option of the browser context is false.
* <p> <strong>NOTE:</strong> {@link Page#tap Page.tap()} requires that the {@code hasTouch} option of the browser context be set to true.
*
* @param selector A selector to search for an element. If there are multiple elements satisfying the selector, the first will be used.
* @since v1.8
@@ -7257,7 +6998,25 @@ public interface Page extends AutoCloseable {
*/
void waitForLoadState(LoadState state, WaitForLoadStateOptions options);
/**
* @deprecated This method is inherently racy, please use {@link Page#waitForURL Page.waitForURL()} instead.
* Waits for the main frame navigation and returns the main resource response. In case of multiple redirects, the
* navigation will resolve with the response of the last redirect. In case of navigation to a different anchor or
* navigation due to History API usage, the navigation will resolve with {@code null}.
*
* <p> **Usage**
*
* <p> This resolves when the page navigates to a new URL or reloads. It is useful for when you run code which will indirectly
* cause the page to navigate. e.g. The click target has an {@code onclick} handler that triggers navigation from a {@code
* setTimeout}. Consider this example:
* <pre>{@code
* // The method returns after navigation has finished
* Response response = page.waitForNavigation(() -> {
* // This action triggers the navigation after a timeout.
* page.getByText("Navigate after timeout").click();
* });
* }</pre>
*
* <p> <strong>NOTE:</strong> Usage of the <a href="https://developer.mozilla.org/en-US/docs/Web/API/History_API">History API</a> to change the URL is
* considered a navigation.
*
* @param callback Callback that performs the action triggering the event.
* @since v1.8
@@ -7266,7 +7025,25 @@ public interface Page extends AutoCloseable {
return waitForNavigation(null, callback);
}
/**
* @deprecated This method is inherently racy, please use {@link Page#waitForURL Page.waitForURL()} instead.
* Waits for the main frame navigation and returns the main resource response. In case of multiple redirects, the
* navigation will resolve with the response of the last redirect. In case of navigation to a different anchor or
* navigation due to History API usage, the navigation will resolve with {@code null}.
*
* <p> **Usage**
*
* <p> This resolves when the page navigates to a new URL or reloads. It is useful for when you run code which will indirectly
* cause the page to navigate. e.g. The click target has an {@code onclick} handler that triggers navigation from a {@code
* setTimeout}. Consider this example:
* <pre>{@code
* // The method returns after navigation has finished
* Response response = page.waitForNavigation(() -> {
* // This action triggers the navigation after a timeout.
* page.getByText("Navigate after timeout").click();
* });
* }</pre>
*
* <p> <strong>NOTE:</strong> Usage of the <a href="https://developer.mozilla.org/en-US/docs/Web/API/History_API">History API</a> to change the URL is
* considered a navigation.
*
* @param callback Callback that performs the action triggering the event.
* @since v1.8
@@ -7877,5 +7654,44 @@ public interface Page extends AutoCloseable {
* @since v1.8
*/
List<Worker> workers();
/**
* Adds one-off {@code Dialog} handler. The handler will be removed immediately after next {@code Dialog} is created.
* <pre>{@code
* page.onceDialog(dialog -> {
* dialog.accept("foo");
* });
*
* // prints 'foo'
* System.out.println(page.evaluate("prompt('Enter string:')"));
*
* // prints 'null' as the dialog will be auto-dismissed because there are no handlers.
* System.out.println(page.evaluate("prompt('Enter string:')"));
* }</pre>
*
* <p> This code above is equivalent to:
* <pre>{@code
* Consumer<Dialog> handler = new Consumer<Dialog>() {
* @Override
* public void accept(Dialog dialog) {
* dialog.accept("foo");
* page.offDialog(this);
* }
* };
* page.onDialog(handler);
*
* // prints 'foo'
* System.out.println(page.evaluate("prompt('Enter string:')"));
*
* // prints 'null' as the dialog will be auto-dismissed because there are no handlers.
* System.out.println(page.evaluate("prompt('Enter string:')"));
* }</pre>
*
* @param handler Receives the {@code Dialog} object, it **must** either {@link Dialog#accept Dialog.accept()} or {@link Dialog#dismiss
* Dialog.dismiss()} the dialog - otherwise the page will <a
* href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#never_blocking">freeze</a> waiting for the
* dialog, and actions like click will never finish.
* @since v1.10
*/
void onceDialog(Consumer<Dialog> handler);
}
@@ -97,7 +97,7 @@ public interface Playwright extends AutoCloseable {
* Launches new Playwright driver process and connects to it. {@link Playwright#close Playwright.close()} should be called
* when the instance is no longer needed.
* <pre>{@code
* Playwright playwright = Playwright.create();
* Playwright playwright = Playwright.create()) {
* Browser browser = playwright.webkit().launch();
* Page page = browser.newPage();
* page.navigate("https://www.w3.org/");
@@ -141,11 +141,6 @@ public interface Route {
* If set changes the request HTTP headers. Header values will be converted to a string.
*/
public Map<String, String> headers;
/**
* Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is
* exceeded. Defaults to {@code 20}. Pass {@code 0} to not follow redirects.
*/
public Integer maxRedirects;
/**
* If set changes the request method (e.g. GET or POST).
*/
@@ -166,14 +161,6 @@ public interface Route {
this.headers = headers;
return this;
}
/**
* Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is
* exceeded. Defaults to {@code 20}. Pass {@code 0} to not follow redirects.
*/
public FetchOptions setMaxRedirects(int maxRedirects) {
this.maxRedirects = maxRedirects;
return this;
}
/**
* If set changes the request method (e.g. GET or POST).
*/
@@ -334,13 +321,6 @@ public interface Route {
* });
* }</pre>
*
* <p> **Details**
*
* <p> Note that any overrides such as {@code url} or {@code headers} only apply to the request being routed. If this request
* results in a redirect, overrides will not be applied to the new redirected request. If you want to propagate a header
* through redirects, use the combination of {@link Route#fetch Route.fetch()} and {@link Route#fulfill Route.fulfill()}
* instead.
*
* @since v1.8
*/
default void resume() {
@@ -360,13 +340,6 @@ public interface Route {
* });
* }</pre>
*
* <p> **Details**
*
* <p> Note that any overrides such as {@code url} or {@code headers} only apply to the request being routed. If this request
* results in a redirect, overrides will not be applied to the new redirected request. If you want to propagate a header
* through redirects, use the combination of {@link Route#fetch Route.fetch()} and {@link Route#fulfill Route.fulfill()}
* instead.
*
* @since v1.8
*/
void resume(ResumeOptions options);
@@ -515,12 +488,6 @@ public interface Route {
* });
* }</pre>
*
* <p> **Details**
*
* <p> Note that {@code headers} option will apply to the fetched request as well as any redirects initiated by it. If you want
* to only apply {@code headers} to the original request, but not to redirects, look into {@link Route#resume
* Route.resume()} instead.
*
* @since v1.29
*/
default APIResponse fetch() {
@@ -543,12 +510,6 @@ public interface Route {
* });
* }</pre>
*
* <p> **Details**
*
* <p> Note that {@code headers} option will apply to the fetched request as well as any redirects initiated by it. If you want
* to only apply {@code headers} to the original request, but not to redirects, look into {@link Route#resume
* Route.resume()} instead.
*
* @since v1.29
*/
APIResponse fetch(FetchOptions options);
@@ -42,9 +42,7 @@ public interface Selectors {
}
}
/**
* Selectors must be registered before creating the page.
*
* <p> **Usage**
* **Usage**
*
* <p> An example of registering selector engine that queries elements based on a tag name:
* <pre>{@code
@@ -66,8 +64,8 @@ public interface Selectors {
* page.setContent("<div><button>Click me</button></div>");
* // Use the selector prefixed with its name.
* Locator button = page.locator("tag=button");
* // Combine it with built-in locators.
* page.locator("tag=div").getByText("Click me").click();
* // Combine it with other selector engines.
* page.locator("tag=div >> text=\"Click me\"").click();
* // Can use it in any methods supporting selectors.
* int buttonCount = (int) page.locator("tag=button").count();
* browser.close();
@@ -82,9 +80,7 @@ public interface Selectors {
register(name, script, null);
}
/**
* Selectors must be registered before creating the page.
*
* <p> **Usage**
* **Usage**
*
* <p> An example of registering selector engine that queries elements based on a tag name:
* <pre>{@code
@@ -106,8 +102,8 @@ public interface Selectors {
* page.setContent("<div><button>Click me</button></div>");
* // Use the selector prefixed with its name.
* Locator button = page.locator("tag=button");
* // Combine it with built-in locators.
* page.locator("tag=div").getByText("Click me").click();
* // Combine it with other selector engines.
* page.locator("tag=div >> text=\"Click me\"").click();
* // Can use it in any methods supporting selectors.
* int buttonCount = (int) page.locator("tag=button").count();
* browser.close();
@@ -120,9 +116,7 @@ public interface Selectors {
*/
void register(String name, String script, RegisterOptions options);
/**
* Selectors must be registered before creating the page.
*
* <p> **Usage**
* **Usage**
*
* <p> An example of registering selector engine that queries elements based on a tag name:
* <pre>{@code
@@ -144,8 +138,8 @@ public interface Selectors {
* page.setContent("<div><button>Click me</button></div>");
* // Use the selector prefixed with its name.
* Locator button = page.locator("tag=button");
* // Combine it with built-in locators.
* page.locator("tag=div").getByText("Click me").click();
* // Combine it with other selector engines.
* page.locator("tag=div >> text=\"Click me\"").click();
* // Can use it in any methods supporting selectors.
* int buttonCount = (int) page.locator("tag=button").count();
* browser.close();
@@ -160,9 +154,7 @@ public interface Selectors {
register(name, script, null);
}
/**
* Selectors must be registered before creating the page.
*
* <p> **Usage**
* **Usage**
*
* <p> An example of registering selector engine that queries elements based on a tag name:
* <pre>{@code
@@ -184,8 +176,8 @@ public interface Selectors {
* page.setContent("<div><button>Click me</button></div>");
* // Use the selector prefixed with its name.
* Locator button = page.locator("tag=button");
* // Combine it with built-in locators.
* page.locator("tag=div").getByText("Click me").click();
* // Combine it with other selector engines.
* page.locator("tag=div >> text=\"Click me\"").click();
* // Can use it in any methods supporting selectors.
* int buttonCount = (int) page.locator("tag=button").count();
* browser.close();
@@ -25,8 +25,6 @@ public interface Touchscreen {
/**
* Dispatches a {@code touchstart} and {@code touchend} event with a single touch at the position ({@code x},{@code y}).
*
* <p> <strong>NOTE:</strong> {@link Page#tap Page.tap()} the method will throw if {@code hasTouch} option of the browser context is false.
*
* @since v1.8
*/
void tap(double x, double y);
@@ -19,7 +19,8 @@ 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.
* APIResponse} in the tests. A new instance of {@code APIResponseAssertions} is created by calling {@link
* PlaywrightAssertions#assertThat PlaywrightAssertions.assertThat()}:
* <pre>{@code
* ...
* import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
@@ -20,7 +20,8 @@ import java.util.regex.Pattern;
/**
* The {@code LocatorAssertions} class provides assertion methods that can be used to make assertions about the {@code
* Locator} state in the tests.
* Locator} state in the tests. A new instance of {@code LocatorAssertions} is created by calling {@link
* PlaywrightAssertions#assertThat PlaywrightAssertions.assertThat()}:
* <pre>{@code
* ...
* import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
@@ -150,33 +151,6 @@ public interface LocatorAssertions {
return this;
}
}
class IsInViewportOptions {
/**
* The minimal ratio of the element to intersect viewport. If equals to {@code 0}, then element should intersect viewport
* at any positive ratio. Defaults to {@code 0}.
*/
public Double ratio;
/**
* Time to retry the assertion for.
*/
public Double timeout;
/**
* The minimal ratio of the element to intersect viewport. If equals to {@code 0}, then element should intersect viewport
* at any positive ratio. Defaults to {@code 0}.
*/
public IsInViewportOptions setRatio(double ratio) {
this.ratio = ratio;
return this;
}
/**
* Time to retry the assertion for.
*/
public IsInViewportOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
class IsVisibleOptions {
/**
* Time to retry the assertion for.
@@ -574,44 +548,6 @@ public interface LocatorAssertions {
* @since v1.20
*/
void isHidden(IsHiddenOptions options);
/**
* Ensures the {@code Locator} points to an element that intersects viewport, according to the <a
* href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API">intersection observer API</a>.
*
* <p> **Usage**
* <pre>{@code
* Locator locator = page.getByRole(AriaRole.BUTTON);
* // Make sure at least some part of element intersects viewport.
* assertThat(locator).isInViewport();
* // Make sure element is fully outside of viewport.
* assertThat(locator).not().isInViewport();
* // Make sure that at least half of the element intersects viewport.
* assertThat(locator).isInViewport(new LocatorAssertions.IsInViewportOptions().setRatio(0.5));
* }</pre>
*
* @since v1.31
*/
default void isInViewport() {
isInViewport(null);
}
/**
* Ensures the {@code Locator} points to an element that intersects viewport, according to the <a
* href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API">intersection observer API</a>.
*
* <p> **Usage**
* <pre>{@code
* Locator locator = page.getByRole(AriaRole.BUTTON);
* // Make sure at least some part of element intersects viewport.
* assertThat(locator).isInViewport();
* // Make sure element is fully outside of viewport.
* assertThat(locator).not().isInViewport();
* // Make sure that at least half of the element intersects viewport.
* assertThat(locator).isInViewport(new LocatorAssertions.IsInViewportOptions().setRatio(0.5));
* }</pre>
*
* @since v1.31
*/
void isInViewport(IsInViewportOptions options);
/**
* Ensures that {@code Locator} points to an <a href="https://playwright.dev/java/docs/actionability#attached">attached</a>
* and <a href="https://playwright.dev/java/docs/actionability#visible">visible</a> DOM node.
@@ -20,7 +20,8 @@ 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.
* state in the tests. A new instance of {@code PageAssertions} is created by calling {@link
* PlaywrightAssertions#assertThat PlaywrightAssertions.assertThat()}:
* <pre>{@code
* ...
* import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
@@ -399,7 +399,11 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
private void route(UrlMatcher matcher, Consumer<Route> handler, RouteOptions options) {
withLogging("BrowserContext.route", () -> {
routes.add(matcher, handler, options == null ? null : options.times);
updateInterceptionPatterns();
if (routes.size() == 1) {
JsonObject params = new JsonObject();
params.addProperty("enabled", true);
sendMessage("setNetworkInterceptionEnabled", params);
}
});
}
@@ -521,26 +525,30 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
private void unroute(UrlMatcher matcher, Consumer<Route> handler) {
withLogging("BrowserContext.unroute", () -> {
routes.remove(matcher, handler);
updateInterceptionPatterns();
maybeDisableNetworkInterception();
});
}
private void updateInterceptionPatterns() {
sendMessage("setNetworkInterceptionPatterns", routes.interceptionPatterns());
private void maybeDisableNetworkInterception() {
if (routes.size() == 0) {
JsonObject params = new JsonObject();
params.addProperty("enabled", false);
sendMessage("setNetworkInterceptionEnabled", params);
}
}
void handleRoute(RouteImpl route) {
Router.HandleResult handled = routes.handle(route);
if (handled != Router.HandleResult.NoMatchingHandler) {
updateInterceptionPatterns();
maybeDisableNetworkInterception();
}
if (handled == Router.HandleResult.NoMatchingHandler || handled == Router.HandleResult.Fallback) {
route.resume();
}
}
WaitableResult<JsonElement> pause() {
return sendMessageAsync("pause", new JsonObject());
void pause() {
sendMessage("pause");
}
@Override
@@ -148,7 +148,7 @@ public class LocatorAssertionsImpl extends AssertionsBase implements LocatorAsse
options = new HasCountOptions();
}
FrameExpectOptions commonOptions = convertType(options, FrameExpectOptions.class);
commonOptions.expectedNumber = (double) count;
commonOptions.expectedNumber = count;
List<ExpectedTextValue> expectedText = null;
expectImpl("to.have.count", expectedText, count, "Locator expected to have count", commonOptions);
}
@@ -326,15 +326,6 @@ public class LocatorAssertionsImpl extends AssertionsBase implements LocatorAsse
expectTrue("to.be.hidden", "Locator expected to be hidden", convertType(options, FrameExpectOptions.class));
}
@Override
public void isInViewport(IsInViewportOptions options) {
FrameExpectOptions expectOptions = convertType(options, FrameExpectOptions.class);
if (options != null && options.ratio != null) {
expectOptions.expectedNumber = options.ratio;
}
expectTrue("to.be.in.viewport", "Locator expected to be in viewport", expectOptions);
}
@Override
public void isVisible(IsVisibleOptions options) {
FrameExpectOptions frameOptions = convertType(options, FrameExpectOptions.class);
@@ -118,7 +118,7 @@ public class LocatorUtils {
// cssEscape(value).replace(/\\ /g, ' ')
// However, our attribute selectors do not conform to CSS parsing spec,
// so we escape them differently.
return '"' + value.replaceAll("\\\\", "\\\\\\\\").replaceAll("\"", "\\\\\"") + '"' + (exact ? "" : "i");
return '"' + value.replaceAll("\"", "\\\\\"") + '"' + (exact ? "" : "i");
}
private static String toJsRegExp(Pattern pattern) {
@@ -17,7 +17,6 @@
package com.microsoft.playwright.impl;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.microsoft.playwright.*;
import com.microsoft.playwright.options.*;
@@ -189,7 +188,7 @@ public class PageImpl extends ChannelOwner implements Page {
RouteImpl route = connection.getExistingObject(params.getAsJsonObject("route").get("guid").getAsString());
Router.HandleResult handled = routes.handle(route);
if (handled != Router.HandleResult.NoMatchingHandler) {
updateInterceptionPatterns();
maybeDisableNetworkInterception();
}
if (handled == Router.HandleResult.NoMatchingHandler || handled == Router.HandleResult.Fallback) {
browserContext.handleRoute(route);
@@ -949,8 +948,8 @@ public class PageImpl extends ChannelOwner implements Page {
@Override
public void pause() {
withLogging("Page.pause", () -> {
runUntil(() -> {}, new WaitableRace<>(asList(context().pause(), (Waitable<JsonElement>) waitableClosedOrCrashed)));
withLogging("BrowserContext.pause", () -> {
context().pause();
});
}
@@ -1037,7 +1036,11 @@ public class PageImpl extends ChannelOwner implements Page {
private void route(UrlMatcher matcher, Consumer<Route> handler, RouteOptions options) {
withLogging("Page.route", () -> {
routes.add(matcher, handler, options == null ? null : options.times);
updateInterceptionPatterns();
if (routes.size() == 1) {
JsonObject params = new JsonObject();
params.addProperty("enabled", true);
sendMessage("setNetworkInterceptionEnabled", params);
}
});
}
@@ -1252,12 +1255,16 @@ public class PageImpl extends ChannelOwner implements Page {
private void unroute(UrlMatcher matcher, Consumer<Route> handler) {
withLogging("Page.unroute", () -> {
routes.remove(matcher, handler);
updateInterceptionPatterns();
maybeDisableNetworkInterception();
});
}
private void updateInterceptionPatterns() {
sendMessage("setNetworkInterceptionPatterns", routes.interceptionPatterns());
private void maybeDisableNetworkInterception() {
if (routes.size() == 0) {
JsonObject params = new JsonObject();
params.addProperty("enabled", false);
sendMessage("setNetworkInterceptionEnabled", params);
}
}
@Override
@@ -94,7 +94,7 @@ class ExpectedTextValue {
class FrameExpectOptions {
Object expressionArg;
List<ExpectedTextValue> expectedText;
Double expectedNumber;
Integer expectedNumber;
SerializedArgument expectedValue;
Boolean useInnerText;
boolean isNot;
@@ -16,19 +16,14 @@
package com.microsoft.playwright.impl;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.microsoft.playwright.Route;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static com.microsoft.playwright.impl.Utils.toJsRegexFlags;
class Router {
private List<RouteInfo> routes = new ArrayList<>();
@@ -97,29 +92,4 @@ class Router {
}
return result;
}
JsonObject interceptionPatterns() {
JsonArray jsonPatterns = new JsonArray();
for (RouteInfo route : routes) {
JsonObject jsonPattern = new JsonObject();
Object urlFilter = route.matcher.rawSource;
if (urlFilter instanceof String) {
jsonPattern.addProperty("glob", (String) urlFilter);
} else if (urlFilter instanceof Pattern) {
Pattern pattern = (Pattern) urlFilter;
jsonPattern.addProperty("regexSource", pattern.pattern());
jsonPattern.addProperty("regexFlags", toJsRegexFlags(pattern));
} else {
// Match all requests.
jsonPattern.addProperty("glob", "**/*");
jsonPatterns = new JsonArray();
jsonPatterns.add(jsonPattern);
break;
}
jsonPatterns.add(jsonPattern);
}
JsonObject result = new JsonObject();
result.add("patterns", jsonPatterns);
return result;
}
}
@@ -27,7 +27,7 @@ import java.util.regex.Pattern;
import static com.microsoft.playwright.impl.Utils.globToRegex;
class UrlMatcher {
final Object rawSource;
private final Object rawSource;
private final Predicate<String> predicate;
private static Predicate<String> toPredicate(Pattern pattern) {
@@ -110,8 +110,7 @@ public interface RequestOptions {
*/
RequestOptions setForm(FormData form);
/**
* Sets an HTTP header to the request. This header will apply to the fetched request as well as any redirects initiated by
* it.
* Sets an HTTP header to the request.
*
* @param name Header name.
* @param value Header value.
@@ -1,54 +0,0 @@
package com.microsoft.playwright;
import com.microsoft.playwright.assertions.LocatorAssertions;
import org.junit.jupiter.api.Test;
import org.opentest4j.AssertionFailedError;
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;
// Copied from expect-misc.spec.ts > toBeInViewport
public class TestAssertThatIsInViewport extends TestBase {
@Test
void shouldWork() {
page.setContent("<div id=big style=\"height: 10000px;\"></div>\n" +
" <div id=small>foo</div>");
assertThat(page.locator("#big")).isInViewport();
assertThat(page.locator("#small")).not().isInViewport();
page.locator("#small").scrollIntoViewIfNeeded();
assertThat(page.locator("#small")).isInViewport();
assertThat(page.locator("#small")).isInViewport(new LocatorAssertions.IsInViewportOptions().setRatio(1));
}
@Test
void shouldRespectRatioOption() {
page.setContent("<style>body, div, html { padding: 0; margin: 0; }</style>\n" +
" <div id=big style=\"height: 400vh;\"></div>");
assertThat(page.locator("div")).isInViewport();
assertThat(page.locator("div")).isInViewport(new LocatorAssertions.IsInViewportOptions().setRatio(0.1));
assertThat(page.locator("div")).isInViewport(new LocatorAssertions.IsInViewportOptions().setRatio(0.2));
assertThat(page.locator("div")).isInViewport(new LocatorAssertions.IsInViewportOptions().setRatio(0.24));
// In this test, element's ratio is 0.25.
assertThat(page.locator("div")).isInViewport(new LocatorAssertions.IsInViewportOptions().setRatio(0.25));
assertThat(page.locator("div")).not().isInViewport(new LocatorAssertions.IsInViewportOptions().setRatio(0.26));
assertThat(page.locator("div")).not().isInViewport(new LocatorAssertions.IsInViewportOptions().setRatio(0.3));
assertThat(page.locator("div")).not().isInViewport(new LocatorAssertions.IsInViewportOptions().setRatio(0.7));
assertThat(page.locator("div")).not().isInViewport(new LocatorAssertions.IsInViewportOptions().setRatio(0.8));
}
@Test
void shouldHaveGoodStack() {
AssertionFailedError error = assertThrows(AssertionFailedError.class, () -> assertThat(page.locator("body")).not().isInViewport(new LocatorAssertions.IsInViewportOptions().setTimeout(100)));
assertNotNull(error);
assertTrue(error.getMessage().contains("Locator expected not to be in viewport"), error.getMessage());
}
@Test
void shouldReportIntersectionEvenIfFullyCoveredByOtherElement() {
page.setContent("<h1>hello</h1>\n" +
" <div style=\"position: relative; height: 10000px; top: -5000px;></div>");
assertThat(page.locator("h1")).isInViewport();
}
}
@@ -17,7 +17,6 @@
package com.microsoft.playwright;
import com.microsoft.playwright.options.AriaRole;
import com.microsoft.playwright.options.WaitUntilState;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIf;
import org.junit.jupiter.api.condition.EnabledIf;
@@ -164,10 +164,10 @@ public class TestGlobalFetch extends TestBase {
@Test
void shouldSupportGlobalTimeoutOption() {
APIRequestContext request = playwright.request().newContext(new APIRequest.NewContextOptions().setTimeout(100));
APIRequestContext request = playwright.request().newContext(new APIRequest.NewContextOptions().setTimeout(1));
server.setRoute("/empty.html", exchange -> {});
PlaywrightException e = assertThrows(PlaywrightException.class, () -> request.get(server.EMPTY_PAGE));
assertTrue(e.getMessage().contains("Request timed out after 100ms"), e.getMessage());
assertTrue(e.getMessage().contains("Request timed out after 1ms"), e.getMessage());
}
@@ -193,7 +193,7 @@ public class TestLocatorAssertions extends TestBase {
assertThat(locator).not().hasText(new String[] {}, new LocatorAssertions.HasTextOptions().setTimeout(1000));
});
assertEquals("[]", e.getExpected().getStringRepresentation());
assertEquals("[]", e.getActual().getStringRepresentation());
assertEquals("null", e.getActual().getStringRepresentation());
assertTrue(e.getMessage().contains("Locator expected not to have text"), e.getMessage());
}
@@ -44,7 +44,7 @@ public class TestPageFill extends TestBase {
for (String type : new String[]{"button", "checkbox", "file", "image", "radio", "reset", "submit"}) {
page.evalOnSelector("input", "(input, type) => input.setAttribute('type', type)", type);
PlaywrightException e = assertThrows(PlaywrightException.class, () -> page.fill("input", ""));
assertTrue(e.getMessage().contains("Error: Input of type \"" + type + "\" cannot be filled"), "type = " + type + e.getMessage());
assertTrue(e.getMessage().contains("input of type \"" + type + "\" cannot be filled"), "type = " + type + e.getMessage());
}
}
@@ -92,17 +92,4 @@ public class TestPageInterception extends TestBase {
page.navigate(server.PREFIX + "/empty.html");
assertEquals("{ \"foo\": \"bar\" }", new String(request.get().postBody));
}
@Test
void shouldNotFollowRedirectsWhenMaxRedirectsIsSetTo0InRouteFetch() {
server.setRedirect("/foo", "/empty.html");
page.route("**/*", route -> {
APIResponse response = route.fetch(new Route.FetchOptions().setMaxRedirects(0));
assertEquals("/empty.html", response.headers().get("location"));
assertEquals(302, response.status());
route.fulfill(new Route.FulfillOptions().setBody("hello"));
});
page.navigate(server.PREFIX + "/foo");
assertTrue(page.content().contains("hello"));
}
}
@@ -19,12 +19,11 @@ package com.microsoft.playwright;
import com.microsoft.playwright.options.HttpHeader;
import org.junit.jupiter.api.Test;
import java.io.OutputStreamWriter;
import java.util.List;
import java.util.stream.Collectors;
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestPageNetworkResponse extends TestBase {
@Test
@@ -46,51 +45,4 @@ public class TestPageNetworkResponse extends TestBase {
assertEquals(asList("a=b", "c=d"), response.headerValues("set-cookie"));
}
@Test
void shouldRejectResponseFinishedIfPageCloses() {
page.navigate(server.EMPTY_PAGE);
server.setRoute("/get", exchange -> {
// In Firefox, |fetch| will be hanging until it receives |Content-Type| header
// from server.
exchange.getResponseHeaders().add("Content-Type", "text/plain; charset=utf-8");
exchange.sendResponseHeaders(200, 0);
OutputStreamWriter writer = new OutputStreamWriter(exchange.getResponseBody());
writer.write("hello ");
});
// send request and wait for server response
Response pageResponse = page.waitForResponse("**/get", () -> {
page.evaluate("() => fetch('./get', { method: 'GET' })");
});
// In 1s send a request which will trigger a request event while pageResponse.finished() is still
// on the callstack.
page.onRequest(request -> page.close());
page.evaluate("() => setTimeout(() => fetch('./empty.html', { method: 'GET' }), 1000)");
PlaywrightException e = assertThrows(PlaywrightException.class, () -> pageResponse.finished());
assertTrue(e.getMessage().contains("closed"), e.getMessage());
}
@Test
void shouldRejectResponseFinishedIfContextCloses() {
page.navigate(server.EMPTY_PAGE);
server.setRoute("/get", exchange -> {
// In Firefox, |fetch| will be hanging until it receives |Content-Type| header
// from server.
exchange.getResponseHeaders().add("Content-Type", "text/plain; charset=utf-8");
exchange.sendResponseHeaders(200, 0);
OutputStreamWriter writer = new OutputStreamWriter(exchange.getResponseBody());
writer.write("hello ");
});
// send request and wait for server response
Response pageResponse = page.waitForResponse("**/get", () -> {
page.evaluate("() => fetch('./get', { method: 'GET' })");
});
// In 1s send a request which will trigger a request event while pageResponse.finished() is still
// on the callstack.
page.onRequest(request -> context.close());
page.evaluate("() => setTimeout(() => fetch('./empty.html', { method: 'GET' }), 1000)");
PlaywrightException e = assertThrows(PlaywrightException.class, () -> pageResponse.finished());
assertTrue(e.getMessage().contains("closed"), e.getMessage());
}
}
@@ -73,7 +73,7 @@ public class TestPageRequestContinue extends TestBase {
done[0] = true;
});
PlaywrightException e = assertThrows(PlaywrightException.class, () -> page.navigate(server.EMPTY_PAGE));
assertTrue(e.getMessage().contains("Target page, context or browser has been closed") ||
assertTrue(e.getMessage().contains("Navigation failed because page was closed") ||
e.getMessage().contains("frame was detached"), e.getMessage());
assertTrue(done[0]);
}
@@ -1,6 +1,5 @@
package com.microsoft.playwright;
import com.microsoft.playwright.assertions.LocatorAssertions;
import com.microsoft.playwright.options.AriaRole;
import org.junit.jupiter.api.Test;
@@ -148,11 +147,6 @@ public class TestSelectorsGetBy extends TestBase {
assertThat(page.getByPlaceholder("hello my\nworld")).hasAttribute("id", "control");
assertThat(page.getByAltText("hello my\nworld")).hasAttribute("id", "control");
assertThat(page.getByTitle("hello my\nworld")).hasAttribute("id", "control");
page.setContent("<div id=target title='my title'>Text here</div>");
assertThat(page.getByTitle("my title", new Page.GetByTitleOptions().setExact(true))).hasCount(1, new LocatorAssertions.HasCountOptions().setTimeout(500));
assertThat(page.getByTitle("my t\\itle", new Page.GetByTitleOptions().setExact(true))).hasCount(0, new LocatorAssertions.HasCountOptions().setTimeout(500));
assertThat(page.getByTitle("my t\\\\itle", new Page.GetByTitleOptions().setExact(true))).hasCount(0, new LocatorAssertions.HasCountOptions().setTimeout(500));
}
@Test
@@ -184,16 +178,6 @@ public class TestSelectorsGetBy extends TestBase {
assertEquals(
asList("<a href=\"https://playwright.dev\">he llo 56</a>"),
page.getByRole(AriaRole.LINK, new Page.GetByRoleOptions().setName(" he \n llo 56 ").setExact(true)).evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(
asList("<button>Click me</button>"),
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Click me").setExact(true)).evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(
asList(),
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Click \\me").setExact(true)).evaluateAll("els => els.map(e => e.outerHTML)"));
assertEquals(
asList(),
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Click \\\\me").setExact(true)).evaluateAll("els => els.map(e => e.outerHTML)"));
}
@Test
+23 -49
View File
@@ -6,7 +6,7 @@
<groupId>com.microsoft.playwright</groupId>
<artifactId>parent-pom</artifactId>
<version>1.31.0</version>
<version>1.29.0</version>
<packaging>pom</packaging>
<name>Playwright Parent Project</name>
<description>Java library to automate Chromium, Firefox and WebKit with a single API.
@@ -42,8 +42,7 @@
</modules>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<compiler.version>1.8</compiler.version>
<gson.version>2.8.9</gson.version>
<junit.version>5.7.0</junit.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -91,35 +90,26 @@
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>3.2.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.1.0</version>
<version>3.1</version>
<configuration>
<source>${compiler.version}</source>
<target>${compiler.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -129,6 +119,14 @@
<additionalOptions>--allow-script-in-comments</additionalOptions>
<failOnError>false</failOnError>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -158,7 +156,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
@@ -169,30 +167,6 @@
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
+1 -1
View File
@@ -1 +1 @@
1.31.1
1.29.2
+1 -1
View File
@@ -6,7 +6,7 @@
<groupId>com.microsoft.playwright</groupId>
<artifactId>api-generator</artifactId>
<version>1.31.0</version>
<version>1.29.0</version>
<name>Playwright - API Generator</name>
<description>
This is an internal module used to generate Java API from the upstream Playwright
+1 -1
View File
@@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.microsoft.playwright</groupId>
<artifactId>test-cli-fatjar</artifactId>
<version>1.31.0</version>
<version>1.29.0</version>
<name>Test Playwright Command Line FatJar</name>
<properties>
<compiler.version>1.8</compiler.version>
+1 -1
View File
@@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.microsoft.playwright</groupId>
<artifactId>test-cli-version</artifactId>
<version>1.31.0</version>
<version>1.29.0</version>
<name>Test Playwright Command Line Version</name>
<properties>
<compiler.version>1.8</compiler.version>
+1 -1
View File
@@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.microsoft.playwright</groupId>
<artifactId>test-local-installation</artifactId>
<version>1.31.0</version>
<version>1.29.0</version>
<name>Test local installation</name>
<description>Runs Playwright test suite (copied from playwright module) against locally cached Playwright</description>
<properties>
+1 -1
View File
@@ -9,7 +9,7 @@
</parent>
<groupId>com.microsoft.playwright</groupId>
<artifactId>test-spring-boot-starter</artifactId>
<version>1.31.0</version>
<version>1.29.0</version>
<name>Test Playwright With Spring Boot</name>
<properties>
<spring.version>2.4.3</spring.version>
+1 -1
View File
@@ -6,7 +6,7 @@
<groupId>com.microsoft.playwright</groupId>
<artifactId>update-version</artifactId>
<version>1.31.0</version>
<version>1.29.0</version>
<name>Playwright - Update Version in Documentation</name>
<description>
This is an internal module used to update versions in the documentation based on