mirror of
https://github.com/microsoft/playwright-java.git
synced 2025-12-26 17:33:37 +00:00
feat: roll driver to 1.50 alpha (#1729)
This commit is contained in:
parent
eb8cf62d74
commit
015939b150
@ -10,9 +10,9 @@ Playwright is a Java library to automate [Chromium](https://www.chromium.org/Hom
|
||||
|
||||
| | Linux | macOS | Windows |
|
||||
| :--- | :---: | :---: | :---: |
|
||||
| Chromium <!-- GEN:chromium-version -->131.0.6778.33<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| Chromium <!-- GEN:chromium-version -->132.0.6834.57<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| WebKit <!-- GEN:webkit-version -->18.2<!-- GEN:stop --> | ✅ | ✅ | ✅ |
|
||||
| Firefox <!-- GEN:firefox-version -->132.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| Firefox <!-- GEN:firefox-version -->134.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
|
||||
Headless execution is supported for all the browsers on all platforms. Check out [system requirements](https://playwright.dev/java/docs/intro#system-requirements) for details.
|
||||
|
||||
|
||||
@ -1225,10 +1225,10 @@ public interface Browser extends AutoCloseable {
|
||||
* <p> In case this browser is connected to, clears all created contexts belonging to this browser and disconnects from the
|
||||
* browser server.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> This is similar to force quitting the browser. Therefore, you should call {@link
|
||||
* com.microsoft.playwright.BrowserContext#close BrowserContext.close()} on any {@code BrowserContext}'s you explicitly
|
||||
* created earlier with {@link com.microsoft.playwright.Browser#newContext Browser.newContext()} **before** calling {@link
|
||||
* com.microsoft.playwright.Browser#close Browser.close()}.
|
||||
* <p> <strong>NOTE:</strong> This is similar to force-quitting the browser. To close pages gracefully and ensure you receive page close events, call
|
||||
* {@link com.microsoft.playwright.BrowserContext#close BrowserContext.close()} on any {@code BrowserContext} instances you
|
||||
* explicitly created earlier using {@link com.microsoft.playwright.Browser#newContext Browser.newContext()} **before**
|
||||
* calling {@link com.microsoft.playwright.Browser#close Browser.close()}.
|
||||
*
|
||||
* <p> The {@code Browser} object itself is considered to be disposed and cannot be used anymore.
|
||||
*
|
||||
@ -1244,10 +1244,10 @@ public interface Browser extends AutoCloseable {
|
||||
* <p> In case this browser is connected to, clears all created contexts belonging to this browser and disconnects from the
|
||||
* browser server.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> This is similar to force quitting the browser. Therefore, you should call {@link
|
||||
* com.microsoft.playwright.BrowserContext#close BrowserContext.close()} on any {@code BrowserContext}'s you explicitly
|
||||
* created earlier with {@link com.microsoft.playwright.Browser#newContext Browser.newContext()} **before** calling {@link
|
||||
* com.microsoft.playwright.Browser#close Browser.close()}.
|
||||
* <p> <strong>NOTE:</strong> This is similar to force-quitting the browser. To close pages gracefully and ensure you receive page close events, call
|
||||
* {@link com.microsoft.playwright.BrowserContext#close BrowserContext.close()} on any {@code BrowserContext} instances you
|
||||
* explicitly created earlier using {@link com.microsoft.playwright.Browser#newContext Browser.newContext()} **before**
|
||||
* calling {@link com.microsoft.playwright.Browser#close Browser.close()}.
|
||||
*
|
||||
* <p> The {@code Browser} object itself is considered to be disposed and cannot be used anymore.
|
||||
*
|
||||
|
||||
@ -834,10 +834,14 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* Grants specified permissions to the browser context. Only grants corresponding permissions to the given origin if
|
||||
* specified.
|
||||
*
|
||||
* @param permissions A permission or an array of permissions to grant. Permissions can be one of the following values:
|
||||
* @param permissions A list of permissions to grant.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> Supported permissions differ between browsers, and even between different versions of the same browser. Any permission
|
||||
* may stop working after an update.
|
||||
*
|
||||
* <p> Here are some permissions that may be supported by some browsers:
|
||||
* <ul>
|
||||
* <li> {@code "accelerometer"}</li>
|
||||
* <li> {@code "accessibility-events"}</li>
|
||||
* <li> {@code "ambient-light-sensor"}</li>
|
||||
* <li> {@code "background-sync"}</li>
|
||||
* <li> {@code "camera"}</li>
|
||||
@ -862,10 +866,14 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* Grants specified permissions to the browser context. Only grants corresponding permissions to the given origin if
|
||||
* specified.
|
||||
*
|
||||
* @param permissions A permission or an array of permissions to grant. Permissions can be one of the following values:
|
||||
* @param permissions A list of permissions to grant.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> Supported permissions differ between browsers, and even between different versions of the same browser. Any permission
|
||||
* may stop working after an update.
|
||||
*
|
||||
* <p> Here are some permissions that may be supported by some browsers:
|
||||
* <ul>
|
||||
* <li> {@code "accelerometer"}</li>
|
||||
* <li> {@code "accessibility-events"}</li>
|
||||
* <li> {@code "ambient-light-sensor"}</li>
|
||||
* <li> {@code "background-sync"}</li>
|
||||
* <li> {@code "camera"}</li>
|
||||
@ -1388,7 +1396,7 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* com.microsoft.playwright.BrowserContext#setDefaultNavigationTimeout BrowserContext.setDefaultNavigationTimeout()} take
|
||||
* priority over {@link com.microsoft.playwright.BrowserContext#setDefaultTimeout BrowserContext.setDefaultTimeout()}.
|
||||
*
|
||||
* @param timeout Maximum time in milliseconds
|
||||
* @param timeout Maximum time in milliseconds. Pass {@code 0} to disable timeout.
|
||||
* @since v1.8
|
||||
*/
|
||||
void setDefaultTimeout(double timeout);
|
||||
|
||||
@ -172,9 +172,14 @@ public interface BrowserType {
|
||||
*/
|
||||
public List<String> args;
|
||||
/**
|
||||
* Browser distribution channel. Supported values are "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge",
|
||||
* "msedge-beta", "msedge-dev", "msedge-canary". Read more about using <a
|
||||
* href="https://playwright.dev/java/docs/browsers#google-chrome--microsoft-edge">Google Chrome and Microsoft Edge</a>.
|
||||
* Browser distribution channel.
|
||||
*
|
||||
* <p> Use "chromium" to <a href="https://playwright.dev/java/docs/browsers#chromium-new-headless-mode">opt in to new headless
|
||||
* mode</a>.
|
||||
*
|
||||
* <p> Use "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", or "msedge-canary" to
|
||||
* use branded <a href="https://playwright.dev/java/docs/browsers#google-chrome--microsoft-edge">Google Chrome and
|
||||
* Microsoft Edge</a>.
|
||||
*/
|
||||
public Object channel;
|
||||
/**
|
||||
@ -265,18 +270,28 @@ public interface BrowserType {
|
||||
}
|
||||
@Deprecated
|
||||
/**
|
||||
* Browser distribution channel. Supported values are "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge",
|
||||
* "msedge-beta", "msedge-dev", "msedge-canary". Read more about using <a
|
||||
* href="https://playwright.dev/java/docs/browsers#google-chrome--microsoft-edge">Google Chrome and Microsoft Edge</a>.
|
||||
* Browser distribution channel.
|
||||
*
|
||||
* <p> Use "chromium" to <a href="https://playwright.dev/java/docs/browsers#chromium-new-headless-mode">opt in to new headless
|
||||
* mode</a>.
|
||||
*
|
||||
* <p> Use "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", or "msedge-canary" to
|
||||
* use branded <a href="https://playwright.dev/java/docs/browsers#google-chrome--microsoft-edge">Google Chrome and
|
||||
* Microsoft Edge</a>.
|
||||
*/
|
||||
public LaunchOptions setChannel(BrowserChannel channel) {
|
||||
this.channel = channel;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Browser distribution channel. Supported values are "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge",
|
||||
* "msedge-beta", "msedge-dev", "msedge-canary". Read more about using <a
|
||||
* href="https://playwright.dev/java/docs/browsers#google-chrome--microsoft-edge">Google Chrome and Microsoft Edge</a>.
|
||||
* Browser distribution channel.
|
||||
*
|
||||
* <p> Use "chromium" to <a href="https://playwright.dev/java/docs/browsers#chromium-new-headless-mode">opt in to new headless
|
||||
* mode</a>.
|
||||
*
|
||||
* <p> Use "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", or "msedge-canary" to
|
||||
* use branded <a href="https://playwright.dev/java/docs/browsers#google-chrome--microsoft-edge">Google Chrome and
|
||||
* Microsoft Edge</a>.
|
||||
*/
|
||||
public LaunchOptions setChannel(String channel) {
|
||||
this.channel = channel;
|
||||
@ -446,9 +461,14 @@ public interface BrowserType {
|
||||
*/
|
||||
public Boolean bypassCSP;
|
||||
/**
|
||||
* Browser distribution channel. Supported values are "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge",
|
||||
* "msedge-beta", "msedge-dev", "msedge-canary". Read more about using <a
|
||||
* href="https://playwright.dev/java/docs/browsers#google-chrome--microsoft-edge">Google Chrome and Microsoft Edge</a>.
|
||||
* Browser distribution channel.
|
||||
*
|
||||
* <p> Use "chromium" to <a href="https://playwright.dev/java/docs/browsers#chromium-new-headless-mode">opt in to new headless
|
||||
* mode</a>.
|
||||
*
|
||||
* <p> Use "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", or "msedge-canary" to
|
||||
* use branded <a href="https://playwright.dev/java/docs/browsers#google-chrome--microsoft-edge">Google Chrome and
|
||||
* Microsoft Edge</a>.
|
||||
*/
|
||||
public Object channel;
|
||||
/**
|
||||
@ -734,18 +754,28 @@ public interface BrowserType {
|
||||
}
|
||||
@Deprecated
|
||||
/**
|
||||
* Browser distribution channel. Supported values are "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge",
|
||||
* "msedge-beta", "msedge-dev", "msedge-canary". Read more about using <a
|
||||
* href="https://playwright.dev/java/docs/browsers#google-chrome--microsoft-edge">Google Chrome and Microsoft Edge</a>.
|
||||
* Browser distribution channel.
|
||||
*
|
||||
* <p> Use "chromium" to <a href="https://playwright.dev/java/docs/browsers#chromium-new-headless-mode">opt in to new headless
|
||||
* mode</a>.
|
||||
*
|
||||
* <p> Use "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", or "msedge-canary" to
|
||||
* use branded <a href="https://playwright.dev/java/docs/browsers#google-chrome--microsoft-edge">Google Chrome and
|
||||
* Microsoft Edge</a>.
|
||||
*/
|
||||
public LaunchPersistentContextOptions setChannel(BrowserChannel channel) {
|
||||
this.channel = channel;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Browser distribution channel. Supported values are "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge",
|
||||
* "msedge-beta", "msedge-dev", "msedge-canary". Read more about using <a
|
||||
* href="https://playwright.dev/java/docs/browsers#google-chrome--microsoft-edge">Google Chrome and Microsoft Edge</a>.
|
||||
* Browser distribution channel.
|
||||
*
|
||||
* <p> Use "chromium" to <a href="https://playwright.dev/java/docs/browsers#chromium-new-headless-mode">opt in to new headless
|
||||
* mode</a>.
|
||||
*
|
||||
* <p> Use "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", or "msedge-canary" to
|
||||
* use branded <a href="https://playwright.dev/java/docs/browsers#google-chrome--microsoft-edge">Google Chrome and
|
||||
* Microsoft Edge</a>.
|
||||
*/
|
||||
public LaunchPersistentContextOptions setChannel(String channel) {
|
||||
this.channel = channel;
|
||||
|
||||
@ -174,6 +174,19 @@ public interface Clock {
|
||||
* page.clock().pauseAt("2020-02-02");
|
||||
* }</pre>
|
||||
*
|
||||
* <p> For best results, install the clock before navigating the page and set it to a time slightly before the intended test
|
||||
* time. This ensures that all timers run normally during page loading, preventing the page from getting stuck. Once the
|
||||
* page has fully loaded, you can safely use {@link com.microsoft.playwright.Clock#pauseAt Clock.pauseAt()} to pause the
|
||||
* clock.
|
||||
* <pre>{@code
|
||||
* // Initialize clock with some time before the test time and let the page load
|
||||
* // naturally. `Date.now` will progress as the timers fire.
|
||||
* SimpleDateFormat format = new SimpleDateFormat("yyy-MM-dd'T'HH:mm:ss");
|
||||
* page.clock().install(new Clock.InstallOptions().setTime(format.parse("2024-12-10T08:00:00")));
|
||||
* page.navigate("http://localhost:3333");
|
||||
* page.clock().pauseAt(format.parse("2024-12-10T10:00:00"));
|
||||
* }</pre>
|
||||
*
|
||||
* @param time Time to pause at.
|
||||
* @since v1.45
|
||||
*/
|
||||
@ -194,6 +207,19 @@ public interface Clock {
|
||||
* page.clock().pauseAt("2020-02-02");
|
||||
* }</pre>
|
||||
*
|
||||
* <p> For best results, install the clock before navigating the page and set it to a time slightly before the intended test
|
||||
* time. This ensures that all timers run normally during page loading, preventing the page from getting stuck. Once the
|
||||
* page has fully loaded, you can safely use {@link com.microsoft.playwright.Clock#pauseAt Clock.pauseAt()} to pause the
|
||||
* clock.
|
||||
* <pre>{@code
|
||||
* // Initialize clock with some time before the test time and let the page load
|
||||
* // naturally. `Date.now` will progress as the timers fire.
|
||||
* SimpleDateFormat format = new SimpleDateFormat("yyy-MM-dd'T'HH:mm:ss");
|
||||
* page.clock().install(new Clock.InstallOptions().setTime(format.parse("2024-12-10T08:00:00")));
|
||||
* page.navigate("http://localhost:3333");
|
||||
* page.clock().pauseAt(format.parse("2024-12-10T10:00:00"));
|
||||
* }</pre>
|
||||
*
|
||||
* @param time Time to pause at.
|
||||
* @since v1.45
|
||||
*/
|
||||
@ -214,6 +240,19 @@ public interface Clock {
|
||||
* page.clock().pauseAt("2020-02-02");
|
||||
* }</pre>
|
||||
*
|
||||
* <p> For best results, install the clock before navigating the page and set it to a time slightly before the intended test
|
||||
* time. This ensures that all timers run normally during page loading, preventing the page from getting stuck. Once the
|
||||
* page has fully loaded, you can safely use {@link com.microsoft.playwright.Clock#pauseAt Clock.pauseAt()} to pause the
|
||||
* clock.
|
||||
* <pre>{@code
|
||||
* // Initialize clock with some time before the test time and let the page load
|
||||
* // naturally. `Date.now` will progress as the timers fire.
|
||||
* SimpleDateFormat format = new SimpleDateFormat("yyy-MM-dd'T'HH:mm:ss");
|
||||
* page.clock().install(new Clock.InstallOptions().setTime(format.parse("2024-12-10T08:00:00")));
|
||||
* page.navigate("http://localhost:3333");
|
||||
* page.clock().pauseAt(format.parse("2024-12-10T10:00:00"));
|
||||
* }</pre>
|
||||
*
|
||||
* @param time Time to pause at.
|
||||
* @since v1.45
|
||||
*/
|
||||
|
||||
@ -2630,7 +2630,6 @@ public interface Locator {
|
||||
*
|
||||
* <p> You can also specify {@code JSHandle} as the property value if you want live objects to be passed into the event:
|
||||
* <pre>{@code
|
||||
* // Note you can only create DataTransfer in Chromium and Firefox
|
||||
* JSHandle dataTransfer = page.evaluateHandle("() => new DataTransfer()");
|
||||
* Map<String, Object> arg = new HashMap<>();
|
||||
* arg.put("dataTransfer", dataTransfer);
|
||||
@ -2679,7 +2678,6 @@ public interface Locator {
|
||||
*
|
||||
* <p> You can also specify {@code JSHandle} as the property value if you want live objects to be passed into the event:
|
||||
* <pre>{@code
|
||||
* // Note you can only create DataTransfer in Chromium and Firefox
|
||||
* JSHandle dataTransfer = page.evaluateHandle("() => new DataTransfer()");
|
||||
* Map<String, Object> arg = new HashMap<>();
|
||||
* arg.put("dataTransfer", dataTransfer);
|
||||
@ -2727,7 +2725,6 @@ public interface Locator {
|
||||
*
|
||||
* <p> You can also specify {@code JSHandle} as the property value if you want live objects to be passed into the event:
|
||||
* <pre>{@code
|
||||
* // Note you can only create DataTransfer in Chromium and Firefox
|
||||
* JSHandle dataTransfer = page.evaluateHandle("() => new DataTransfer()");
|
||||
* Map<String, Object> arg = new HashMap<>();
|
||||
* arg.put("dataTransfer", dataTransfer);
|
||||
@ -3968,7 +3965,9 @@ public interface Locator {
|
||||
*/
|
||||
boolean isDisabled(IsDisabledOptions options);
|
||||
/**
|
||||
* Returns whether the element is <a href="https://playwright.dev/java/docs/actionability#editable">editable</a>.
|
||||
* Returns whether the element is <a href="https://playwright.dev/java/docs/actionability#editable">editable</a>. If the
|
||||
* target element is not an {@code <input>}, {@code <textarea>}, {@code <select>}, {@code [contenteditable]} and does not
|
||||
* have a role allowing {@code [aria-readonly]}, this method throws an error.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> If you need to assert that an element is editable, prefer {@link
|
||||
* com.microsoft.playwright.assertions.LocatorAssertions#isEditable LocatorAssertions.isEditable()} to avoid flakiness. See
|
||||
@ -3985,7 +3984,9 @@ public interface Locator {
|
||||
return isEditable(null);
|
||||
}
|
||||
/**
|
||||
* Returns whether the element is <a href="https://playwright.dev/java/docs/actionability#editable">editable</a>.
|
||||
* Returns whether the element is <a href="https://playwright.dev/java/docs/actionability#editable">editable</a>. If the
|
||||
* target element is not an {@code <input>}, {@code <textarea>}, {@code <select>}, {@code [contenteditable]} and does not
|
||||
* have a role allowing {@code [aria-readonly]}, this method throws an error.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> If you need to assert that an element is editable, prefer {@link
|
||||
* com.microsoft.playwright.assertions.LocatorAssertions#isEditable LocatorAssertions.isEditable()} to avoid flakiness. See
|
||||
@ -4166,17 +4167,21 @@ public interface Locator {
|
||||
/**
|
||||
* Creates a locator matching all elements that match one or both of the two locators.
|
||||
*
|
||||
* <p> Note that when both locators match something, the resulting locator will have multiple matches and violate <a
|
||||
* href="https://playwright.dev/java/docs/locators#strictness">locator strictness</a> guidelines.
|
||||
* <p> Note that when both locators match something, the resulting locator will have multiple matches, potentially causing a <a
|
||||
* href="https://playwright.dev/java/docs/locators#strictness">locator strictness</a> violation.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
*
|
||||
* <p> Consider a scenario where you'd like to click on a "New email" button, but sometimes a security settings dialog shows up
|
||||
* instead. In this case, you can wait for either a "New email" button, or a dialog and act accordingly.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> If both "New email" button and security dialog appear on screen, the "or" locator will match both of them, possibly
|
||||
* throwing the <a href="https://playwright.dev/java/docs/locators#strictness">"strict mode violation" error</a>. In this
|
||||
* case, you can use {@link com.microsoft.playwright.Locator#first Locator.first()} to only match one of them.
|
||||
* <pre>{@code
|
||||
* Locator newEmail = page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("New"));
|
||||
* Locator dialog = page.getByText("Confirm security settings");
|
||||
* assertThat(newEmail.or(dialog)).isVisible();
|
||||
* assertThat(newEmail.or(dialog).first()).isVisible();
|
||||
* if (dialog.isVisible())
|
||||
* page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Dismiss")).click();
|
||||
* newEmail.click();
|
||||
|
||||
@ -5809,8 +5809,6 @@ public interface Page extends AutoCloseable {
|
||||
/**
|
||||
* Returns the PDF buffer.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> Generating a pdf is currently only supported in Chromium headless.
|
||||
*
|
||||
* <p> {@code page.pdf()} generates a pdf of the page with {@code print} css media. To generate a pdf with {@code screen}
|
||||
* media, call {@link com.microsoft.playwright.Page#emulateMedia Page.emulateMedia()} before calling {@code page.pdf()}:
|
||||
*
|
||||
@ -5869,8 +5867,6 @@ public interface Page extends AutoCloseable {
|
||||
/**
|
||||
* Returns the PDF buffer.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> Generating a pdf is currently only supported in Chromium headless.
|
||||
*
|
||||
* <p> {@code page.pdf()} generates a pdf of the page with {@code print} css media. To generate a pdf with {@code screen}
|
||||
* media, call {@link com.microsoft.playwright.Page#emulateMedia Page.emulateMedia()} before calling {@code page.pdf()}:
|
||||
*
|
||||
@ -7194,7 +7190,7 @@ public interface Page extends AutoCloseable {
|
||||
* <p> <strong>NOTE:</strong> {@link com.microsoft.playwright.Page#setDefaultNavigationTimeout Page.setDefaultNavigationTimeout()} takes priority over
|
||||
* {@link com.microsoft.playwright.Page#setDefaultTimeout Page.setDefaultTimeout()}.
|
||||
*
|
||||
* @param timeout Maximum time in milliseconds
|
||||
* @param timeout Maximum time in milliseconds. Pass {@code 0} to disable timeout.
|
||||
* @since v1.8
|
||||
*/
|
||||
void setDefaultTimeout(double timeout);
|
||||
|
||||
@ -306,10 +306,10 @@ public interface Tracing {
|
||||
* <pre>{@code
|
||||
* // All actions between group and groupEnd
|
||||
* // will be shown in the trace viewer as a group.
|
||||
* page.context().tracing.group("Open Playwright.dev > API");
|
||||
* page.context().tracing().group("Open Playwright.dev > API");
|
||||
* page.navigate("https://playwright.dev/");
|
||||
* page.getByRole(AriaRole.LINK, new Page.GetByRoleOptions().setName("API")).click();
|
||||
* page.context().tracing.groupEnd();
|
||||
* page.context().tracing().groupEnd();
|
||||
* }</pre>
|
||||
*
|
||||
* @param name Group name shown in the trace viewer.
|
||||
@ -329,10 +329,10 @@ public interface Tracing {
|
||||
* <pre>{@code
|
||||
* // All actions between group and groupEnd
|
||||
* // will be shown in the trace viewer as a group.
|
||||
* page.context().tracing.group("Open Playwright.dev > API");
|
||||
* page.context().tracing().group("Open Playwright.dev > API");
|
||||
* page.navigate("https://playwright.dev/");
|
||||
* page.getByRole(AriaRole.LINK, new Page.GetByRoleOptions().setName("API")).click();
|
||||
* page.context().tracing.groupEnd();
|
||||
* page.context().tracing().groupEnd();
|
||||
* }</pre>
|
||||
*
|
||||
* @param name Group name shown in the trace viewer.
|
||||
|
||||
@ -58,16 +58,37 @@ public interface LocatorAssertions {
|
||||
}
|
||||
}
|
||||
class IsCheckedOptions {
|
||||
/**
|
||||
* Provides state to assert for. Asserts for input to be checked by default. This option can't be used when {@code
|
||||
* indeterminate} is set to true.
|
||||
*/
|
||||
public Boolean checked;
|
||||
/**
|
||||
* Asserts that the element is in the indeterminate (mixed) state. Only supported for checkboxes and radio buttons. This
|
||||
* option can't be true when {@code checked} is provided.
|
||||
*/
|
||||
public Boolean indeterminate;
|
||||
/**
|
||||
* Time to retry the assertion for in milliseconds. Defaults to {@code 5000}.
|
||||
*/
|
||||
public Double timeout;
|
||||
|
||||
/**
|
||||
* Provides state to assert for. Asserts for input to be checked by default. This option can't be used when {@code
|
||||
* indeterminate} is set to true.
|
||||
*/
|
||||
public IsCheckedOptions setChecked(boolean checked) {
|
||||
this.checked = checked;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Asserts that the element is in the indeterminate (mixed) state. Only supported for checkboxes and radio buttons. This
|
||||
* option can't be true when {@code checked} is provided.
|
||||
*/
|
||||
public IsCheckedOptions setIndeterminate(boolean indeterminate) {
|
||||
this.indeterminate = indeterminate;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Time to retry the assertion for in milliseconds. Defaults to {@code 5000}.
|
||||
*/
|
||||
@ -281,6 +302,33 @@ public interface LocatorAssertions {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
class HasAccessibleErrorMessageOptions {
|
||||
/**
|
||||
* Whether to perform case-insensitive match. {@code ignoreCase} option takes precedence over the corresponding regular
|
||||
* expression flag if specified.
|
||||
*/
|
||||
public Boolean ignoreCase;
|
||||
/**
|
||||
* Time to retry the assertion for in milliseconds. Defaults to {@code 5000}.
|
||||
*/
|
||||
public Double timeout;
|
||||
|
||||
/**
|
||||
* Whether to perform case-insensitive match. {@code ignoreCase} option takes precedence over the corresponding regular
|
||||
* expression flag if specified.
|
||||
*/
|
||||
public HasAccessibleErrorMessageOptions setIgnoreCase(boolean ignoreCase) {
|
||||
this.ignoreCase = ignoreCase;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Time to retry the assertion for in milliseconds. Defaults to {@code 5000}.
|
||||
*/
|
||||
public HasAccessibleErrorMessageOptions setTimeout(double timeout) {
|
||||
this.timeout = timeout;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
class HasAccessibleNameOptions {
|
||||
/**
|
||||
* Whether to perform case-insensitive match. {@code ignoreCase} option takes precedence over the corresponding regular
|
||||
@ -1219,6 +1267,66 @@ public interface LocatorAssertions {
|
||||
* @since v1.44
|
||||
*/
|
||||
void hasAccessibleDescription(Pattern description, HasAccessibleDescriptionOptions options);
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element with a given <a
|
||||
* href="https://w3c.github.io/aria/#aria-errormessage">aria errormessage</a>.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* Locator locator = page.getByTestId("username-input");
|
||||
* assertThat(locator).hasAccessibleErrorMessage("Username is required.");
|
||||
* }</pre>
|
||||
*
|
||||
* @param errorMessage Expected accessible error message.
|
||||
* @since v1.50
|
||||
*/
|
||||
default void hasAccessibleErrorMessage(String errorMessage) {
|
||||
hasAccessibleErrorMessage(errorMessage, null);
|
||||
}
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element with a given <a
|
||||
* href="https://w3c.github.io/aria/#aria-errormessage">aria errormessage</a>.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* Locator locator = page.getByTestId("username-input");
|
||||
* assertThat(locator).hasAccessibleErrorMessage("Username is required.");
|
||||
* }</pre>
|
||||
*
|
||||
* @param errorMessage Expected accessible error message.
|
||||
* @since v1.50
|
||||
*/
|
||||
void hasAccessibleErrorMessage(String errorMessage, HasAccessibleErrorMessageOptions options);
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element with a given <a
|
||||
* href="https://w3c.github.io/aria/#aria-errormessage">aria errormessage</a>.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* Locator locator = page.getByTestId("username-input");
|
||||
* assertThat(locator).hasAccessibleErrorMessage("Username is required.");
|
||||
* }</pre>
|
||||
*
|
||||
* @param errorMessage Expected accessible error message.
|
||||
* @since v1.50
|
||||
*/
|
||||
default void hasAccessibleErrorMessage(Pattern errorMessage) {
|
||||
hasAccessibleErrorMessage(errorMessage, null);
|
||||
}
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element with a given <a
|
||||
* href="https://w3c.github.io/aria/#aria-errormessage">aria errormessage</a>.
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* Locator locator = page.getByTestId("username-input");
|
||||
* assertThat(locator).hasAccessibleErrorMessage("Username is required.");
|
||||
* }</pre>
|
||||
*
|
||||
* @param errorMessage Expected accessible error message.
|
||||
* @since v1.50
|
||||
*/
|
||||
void hasAccessibleErrorMessage(Pattern errorMessage, HasAccessibleErrorMessageOptions options);
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element with a given <a
|
||||
* href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
|
||||
@ -1336,16 +1444,18 @@ public interface LocatorAssertions {
|
||||
*/
|
||||
void hasAttribute(String name, Pattern value, HasAttributeOptions options);
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. This needs to be a full match or using a
|
||||
* relaxed regular expression.
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. When a string is provided, it must fully match
|
||||
* the element's {@code class} attribute. To match individual classes or perform partial matches, use a regular expression:
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("selected"));
|
||||
* assertThat(page.locator("#component")).hasClass("selected row");
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("(^|\\s)selected(\\s|$)"));
|
||||
* assertThat(page.locator("#component")).hasClass("middle selected row");
|
||||
* }</pre>
|
||||
*
|
||||
* <p> Note that if array is passed as an expected value, entire lists of elements can be asserted:
|
||||
* <p> When an array is passed, the method asserts that the list of elements located matches the corresponding list of expected
|
||||
* class values. Each element's class attribute is matched against the corresponding string or regular expression in the
|
||||
* array:
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("list > .component")).hasClass(new String[] {"component", "component selected", "component"});
|
||||
* }</pre>
|
||||
@ -1357,16 +1467,18 @@ public interface LocatorAssertions {
|
||||
hasClass(expected, null);
|
||||
}
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. This needs to be a full match or using a
|
||||
* relaxed regular expression.
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. When a string is provided, it must fully match
|
||||
* the element's {@code class} attribute. To match individual classes or perform partial matches, use a regular expression:
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("selected"));
|
||||
* assertThat(page.locator("#component")).hasClass("selected row");
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("(^|\\s)selected(\\s|$)"));
|
||||
* assertThat(page.locator("#component")).hasClass("middle selected row");
|
||||
* }</pre>
|
||||
*
|
||||
* <p> Note that if array is passed as an expected value, entire lists of elements can be asserted:
|
||||
* <p> When an array is passed, the method asserts that the list of elements located matches the corresponding list of expected
|
||||
* class values. Each element's class attribute is matched against the corresponding string or regular expression in the
|
||||
* array:
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("list > .component")).hasClass(new String[] {"component", "component selected", "component"});
|
||||
* }</pre>
|
||||
@ -1376,16 +1488,18 @@ public interface LocatorAssertions {
|
||||
*/
|
||||
void hasClass(String expected, HasClassOptions options);
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. This needs to be a full match or using a
|
||||
* relaxed regular expression.
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. When a string is provided, it must fully match
|
||||
* the element's {@code class} attribute. To match individual classes or perform partial matches, use a regular expression:
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("selected"));
|
||||
* assertThat(page.locator("#component")).hasClass("selected row");
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("(^|\\s)selected(\\s|$)"));
|
||||
* assertThat(page.locator("#component")).hasClass("middle selected row");
|
||||
* }</pre>
|
||||
*
|
||||
* <p> Note that if array is passed as an expected value, entire lists of elements can be asserted:
|
||||
* <p> When an array is passed, the method asserts that the list of elements located matches the corresponding list of expected
|
||||
* class values. Each element's class attribute is matched against the corresponding string or regular expression in the
|
||||
* array:
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("list > .component")).hasClass(new String[] {"component", "component selected", "component"});
|
||||
* }</pre>
|
||||
@ -1397,16 +1511,18 @@ public interface LocatorAssertions {
|
||||
hasClass(expected, null);
|
||||
}
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. This needs to be a full match or using a
|
||||
* relaxed regular expression.
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. When a string is provided, it must fully match
|
||||
* the element's {@code class} attribute. To match individual classes or perform partial matches, use a regular expression:
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("selected"));
|
||||
* assertThat(page.locator("#component")).hasClass("selected row");
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("(^|\\s)selected(\\s|$)"));
|
||||
* assertThat(page.locator("#component")).hasClass("middle selected row");
|
||||
* }</pre>
|
||||
*
|
||||
* <p> Note that if array is passed as an expected value, entire lists of elements can be asserted:
|
||||
* <p> When an array is passed, the method asserts that the list of elements located matches the corresponding list of expected
|
||||
* class values. Each element's class attribute is matched against the corresponding string or regular expression in the
|
||||
* array:
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("list > .component")).hasClass(new String[] {"component", "component selected", "component"});
|
||||
* }</pre>
|
||||
@ -1416,16 +1532,18 @@ public interface LocatorAssertions {
|
||||
*/
|
||||
void hasClass(Pattern expected, HasClassOptions options);
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. This needs to be a full match or using a
|
||||
* relaxed regular expression.
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. When a string is provided, it must fully match
|
||||
* the element's {@code class} attribute. To match individual classes or perform partial matches, use a regular expression:
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("selected"));
|
||||
* assertThat(page.locator("#component")).hasClass("selected row");
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("(^|\\s)selected(\\s|$)"));
|
||||
* assertThat(page.locator("#component")).hasClass("middle selected row");
|
||||
* }</pre>
|
||||
*
|
||||
* <p> Note that if array is passed as an expected value, entire lists of elements can be asserted:
|
||||
* <p> When an array is passed, the method asserts that the list of elements located matches the corresponding list of expected
|
||||
* class values. Each element's class attribute is matched against the corresponding string or regular expression in the
|
||||
* array:
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("list > .component")).hasClass(new String[] {"component", "component selected", "component"});
|
||||
* }</pre>
|
||||
@ -1437,16 +1555,18 @@ public interface LocatorAssertions {
|
||||
hasClass(expected, null);
|
||||
}
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. This needs to be a full match or using a
|
||||
* relaxed regular expression.
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. When a string is provided, it must fully match
|
||||
* the element's {@code class} attribute. To match individual classes or perform partial matches, use a regular expression:
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("selected"));
|
||||
* assertThat(page.locator("#component")).hasClass("selected row");
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("(^|\\s)selected(\\s|$)"));
|
||||
* assertThat(page.locator("#component")).hasClass("middle selected row");
|
||||
* }</pre>
|
||||
*
|
||||
* <p> Note that if array is passed as an expected value, entire lists of elements can be asserted:
|
||||
* <p> When an array is passed, the method asserts that the list of elements located matches the corresponding list of expected
|
||||
* class values. Each element's class attribute is matched against the corresponding string or regular expression in the
|
||||
* array:
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("list > .component")).hasClass(new String[] {"component", "component selected", "component"});
|
||||
* }</pre>
|
||||
@ -1456,16 +1576,18 @@ public interface LocatorAssertions {
|
||||
*/
|
||||
void hasClass(String[] expected, HasClassOptions options);
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. This needs to be a full match or using a
|
||||
* relaxed regular expression.
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. When a string is provided, it must fully match
|
||||
* the element's {@code class} attribute. To match individual classes or perform partial matches, use a regular expression:
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("selected"));
|
||||
* assertThat(page.locator("#component")).hasClass("selected row");
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("(^|\\s)selected(\\s|$)"));
|
||||
* assertThat(page.locator("#component")).hasClass("middle selected row");
|
||||
* }</pre>
|
||||
*
|
||||
* <p> Note that if array is passed as an expected value, entire lists of elements can be asserted:
|
||||
* <p> When an array is passed, the method asserts that the list of elements located matches the corresponding list of expected
|
||||
* class values. Each element's class attribute is matched against the corresponding string or regular expression in the
|
||||
* array:
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("list > .component")).hasClass(new String[] {"component", "component selected", "component"});
|
||||
* }</pre>
|
||||
@ -1477,16 +1599,18 @@ public interface LocatorAssertions {
|
||||
hasClass(expected, null);
|
||||
}
|
||||
/**
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. This needs to be a full match or using a
|
||||
* relaxed regular expression.
|
||||
* Ensures the {@code Locator} points to an element with given CSS classes. When a string is provided, it must fully match
|
||||
* the element's {@code class} attribute. To match individual classes or perform partial matches, use a regular expression:
|
||||
*
|
||||
* <p> <strong>Usage</strong>
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("selected"));
|
||||
* assertThat(page.locator("#component")).hasClass("selected row");
|
||||
* assertThat(page.locator("#component")).hasClass(Pattern.compile("(^|\\s)selected(\\s|$)"));
|
||||
* assertThat(page.locator("#component")).hasClass("middle selected row");
|
||||
* }</pre>
|
||||
*
|
||||
* <p> Note that if array is passed as an expected value, entire lists of elements can be asserted:
|
||||
* <p> When an array is passed, the method asserts that the list of elements located matches the corresponding list of expected
|
||||
* class values. Each element's class attribute is matched against the corresponding string or regular expression in the
|
||||
* array:
|
||||
* <pre>{@code
|
||||
* assertThat(page.locator("list > .component")).hasClass(new String[] {"component", "component selected", "component"});
|
||||
* }</pre>
|
||||
|
||||
@ -47,7 +47,6 @@ class AssertionsBase {
|
||||
options = new FrameExpectOptions();
|
||||
}
|
||||
options.expectedText = expectedText;
|
||||
options.isNot = isNot;
|
||||
expectImpl(expression, options, expected, message);
|
||||
}
|
||||
|
||||
@ -55,13 +54,14 @@ class AssertionsBase {
|
||||
if (expectOptions.timeout == null) {
|
||||
expectOptions.timeout = AssertionsTimeout.defaultTimeout;
|
||||
}
|
||||
if (expectOptions.isNot) {
|
||||
expectOptions.isNot = isNot;
|
||||
if (isNot) {
|
||||
message = message.replace("expected to", "expected not to");
|
||||
}
|
||||
FrameExpectResult result = actualLocator.expect(expression, expectOptions);
|
||||
if (result.matches == isNot) {
|
||||
Object actual = result.received == null ? null : Serialization.deserialize(result.received);
|
||||
String log = String.join("\n", result.log);
|
||||
String log = (result.log == null) ? "" : String.join("\n", result.log);
|
||||
if (!log.isEmpty()) {
|
||||
log = "\nCall log:\n" + log;
|
||||
}
|
||||
|
||||
@ -22,7 +22,9 @@ import com.microsoft.playwright.options.AriaRole;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.microsoft.playwright.impl.Serialization.serializeArgument;
|
||||
@ -88,6 +90,7 @@ public class LocatorAssertionsImpl extends AssertionsBase implements LocatorAsse
|
||||
ExpectedTextValue expected = new ExpectedTextValue();
|
||||
expected.string = description;
|
||||
expected.ignoreCase = shouldIgnoreCase(options);
|
||||
expected.normalizeWhiteSpace = true;
|
||||
expectImpl("to.have.accessible.description", expected, description, "Locator expected to have accessible description", convertType(options, FrameExpectOptions.class));
|
||||
}
|
||||
|
||||
@ -95,14 +98,33 @@ public class LocatorAssertionsImpl extends AssertionsBase implements LocatorAsse
|
||||
public void hasAccessibleDescription(Pattern pattern, HasAccessibleDescriptionOptions options) {
|
||||
ExpectedTextValue expected = expectedRegex(pattern);
|
||||
expected.ignoreCase = shouldIgnoreCase(options);
|
||||
expected.normalizeWhiteSpace = true;
|
||||
expectImpl("to.have.accessible.description", expected, pattern, "Locator expected to have accessible description", convertType(options, FrameExpectOptions.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hasAccessibleErrorMessage(String errorMessage, HasAccessibleErrorMessageOptions options) {
|
||||
ExpectedTextValue expected = new ExpectedTextValue();
|
||||
expected.string = errorMessage;
|
||||
expected.ignoreCase = shouldIgnoreCase(options);
|
||||
expected.normalizeWhiteSpace = true;
|
||||
expectImpl("to.have.accessible.error.message", expected, errorMessage, "Locator expected to have accessible error message", convertType(options, FrameExpectOptions.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hasAccessibleErrorMessage(Pattern pattern, HasAccessibleErrorMessageOptions options) {
|
||||
ExpectedTextValue expected = expectedRegex(pattern);
|
||||
expected.ignoreCase = shouldIgnoreCase(options);
|
||||
expected.normalizeWhiteSpace = true;
|
||||
expectImpl("to.have.accessible.error.message", expected, pattern, "Locator expected to have accessible error message", convertType(options, FrameExpectOptions.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hasAccessibleName(String name, HasAccessibleNameOptions options) {
|
||||
ExpectedTextValue expected = new ExpectedTextValue();
|
||||
expected.string = name;
|
||||
expected.ignoreCase = shouldIgnoreCase(options);
|
||||
expected.normalizeWhiteSpace = true;
|
||||
expectImpl("to.have.accessible.name", expected, name, "Locator expected to have accessible name", convertType(options, FrameExpectOptions.class));
|
||||
}
|
||||
|
||||
@ -110,6 +132,7 @@ public class LocatorAssertionsImpl extends AssertionsBase implements LocatorAsse
|
||||
public void hasAccessibleName(Pattern pattern, HasAccessibleNameOptions options) {
|
||||
ExpectedTextValue expected = expectedRegex(pattern);
|
||||
expected.ignoreCase = shouldIgnoreCase(options);
|
||||
expected.normalizeWhiteSpace = true;
|
||||
expectImpl("to.have.accessible.name", expected, pattern, "Locator expected to have accessible name", convertType(options, FrameExpectOptions.class));
|
||||
}
|
||||
|
||||
@ -338,10 +361,30 @@ public class LocatorAssertionsImpl extends AssertionsBase implements LocatorAsse
|
||||
|
||||
@Override
|
||||
public void isChecked(IsCheckedOptions options) {
|
||||
boolean unchecked = options != null && options.checked != null && !options.checked;
|
||||
String expression = unchecked ? "to.be.unchecked" : "to.be.checked";
|
||||
String message = "Locator expected to be " + (unchecked ? "un" : "") + "checked";
|
||||
expectTrue(expression, message, convertType(options, FrameExpectOptions.class));
|
||||
if (options == null) {
|
||||
options = new IsCheckedOptions();
|
||||
}
|
||||
|
||||
Map<String, Boolean> expectedValue = new HashMap<>();
|
||||
if (options.indeterminate != null) {
|
||||
expectedValue.put("indeterminate", options.indeterminate);
|
||||
}
|
||||
if (options.checked != null) {
|
||||
expectedValue.put("checked", options.checked);
|
||||
}
|
||||
|
||||
String expected;
|
||||
if (options.indeterminate != null && options.indeterminate) {
|
||||
expected = "indeterminate";
|
||||
} else {
|
||||
boolean unchecked = options.checked != null && !options.checked;
|
||||
expected = unchecked ? "unchecked" : "checked";
|
||||
}
|
||||
|
||||
String message = "Locator expected to be";
|
||||
FrameExpectOptions expectOptions = convertType(options, FrameExpectOptions.class);
|
||||
expectOptions.expectedValue = serializeArgument(expectedValue);
|
||||
expectImpl("to.be.checked", expectOptions, expected, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -53,6 +53,7 @@ public class RequestImpl extends ChannelOwner implements Request {
|
||||
|
||||
RequestImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
markAsInternalType();
|
||||
|
||||
if (initializer.has("redirectedFrom")) {
|
||||
redirectedFrom = connection.getExistingObject(initializer.getAsJsonObject("redirectedFrom").get("guid").getAsString());
|
||||
|
||||
@ -40,6 +40,7 @@ public class ResponseImpl extends ChannelOwner implements Response {
|
||||
|
||||
ResponseImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
markAsInternalType();
|
||||
headers = new RawHeaders(asList(gson().fromJson(initializer.getAsJsonArray("headers"), HttpHeader[].class)));
|
||||
request = connection.getExistingObject(initializer.getAsJsonObject("request").get("guid").getAsString());
|
||||
request.timing = gson().fromJson(initializer.get("timing"), Timing.class);
|
||||
|
||||
@ -18,9 +18,9 @@ package com.microsoft.playwright;
|
||||
|
||||
import com.microsoft.playwright.assertions.LocatorAssertions;
|
||||
import com.microsoft.playwright.assertions.PlaywrightAssertions;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.opentest4j.AssertionFailedError;
|
||||
import org.opentest4j.ValueWrapper;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@ -657,9 +657,9 @@ public class TestLocatorAssertions extends TestBase {
|
||||
AssertionFailedError e = assertThrows(AssertionFailedError.class, () -> {
|
||||
assertThat(locator).isChecked(new LocatorAssertions.IsCheckedOptions().setTimeout(1000));
|
||||
});
|
||||
assertNull(e.getExpected());
|
||||
assertNull(e.getActual());
|
||||
assertTrue(e.getMessage().contains("Locator expected to be checked"), e.getMessage());
|
||||
assertEquals("checked", e.getExpected().getStringRepresentation());
|
||||
assertEquals("unchecked", e.getActual().getStringRepresentation());
|
||||
assertTrue(e.getMessage().contains("Locator expected to be: checked"), e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -669,9 +669,10 @@ public class TestLocatorAssertions extends TestBase {
|
||||
AssertionFailedError e = assertThrows(AssertionFailedError.class, () -> {
|
||||
assertThat(locator).not().isChecked(new LocatorAssertions.IsCheckedOptions().setTimeout(1000));
|
||||
});
|
||||
assertNull(e.getExpected());
|
||||
assertNull(e.getActual());
|
||||
assertTrue(e.getMessage().contains("Locator expected not to be checked"), e.getMessage());
|
||||
|
||||
assertEquals("checked", e.getExpected().getStringRepresentation());
|
||||
assertEquals("checked", e.getActual().getStringRepresentation());
|
||||
assertTrue(e.getMessage().contains("Locator expected not to be: checked"), e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -687,7 +688,7 @@ public class TestLocatorAssertions extends TestBase {
|
||||
Locator locator = page.locator("input");
|
||||
AssertionFailedError error = assertThrows(AssertionFailedError.class,
|
||||
() -> assertThat(locator).isChecked(new LocatorAssertions.IsCheckedOptions().setChecked(false).setTimeout(1000)));
|
||||
assertTrue(error.getMessage().contains("Locator expected to be unchecked"), error.getMessage());
|
||||
assertTrue(error.getMessage().contains("Locator expected to be: unchecked"), error.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -789,6 +790,14 @@ public class TestLocatorAssertions extends TestBase {
|
||||
assertThat(locator).not().isEditable(new LocatorAssertions.IsEditableOptions().setEditable(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isEditableThrowsOnNonInputElement() {
|
||||
page.setContent("<button>");
|
||||
Locator locator = page.locator("button");
|
||||
PlaywrightException e = assertThrows(PlaywrightException.class, () -> assertThat(locator).isEditable());
|
||||
assertTrue(e.getMessage().contains("Element is not an <input>, <textarea>, <select> or [contenteditable] and does not have a role allowing [aria-readonly]"), e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void isEmptyPass() {
|
||||
page.setContent("<input></input>");
|
||||
|
||||
@ -73,9 +73,9 @@ public class TestLocatorAssertions2 extends TestBase {
|
||||
void isAttachedEventually() {
|
||||
page.setContent("<div></div>");
|
||||
Locator locator = page.locator("span");
|
||||
page.evalOnSelector("div", "div => setTimeout(() => {\n" +
|
||||
" div.innerHTML = '<span>Hello</span>'\n" +
|
||||
" }, 100)");
|
||||
page.evalOnSelector("div", "div => setTimeout(() => {\n" +
|
||||
" div.innerHTML = '<span>Hello</span>'\n" +
|
||||
" }, 100)");
|
||||
assertThat(locator).isAttached();
|
||||
}
|
||||
|
||||
@ -83,9 +83,9 @@ public class TestLocatorAssertions2 extends TestBase {
|
||||
void isAttachedEventuallyWithNot() {
|
||||
page.setContent("<div><span>Hello</span></div>");
|
||||
Locator locator = page.locator("span");
|
||||
page.evalOnSelector("div", "div => setTimeout(() => {\n" +
|
||||
" div.textContent = '';\n" +
|
||||
" }, 0)");
|
||||
page.evalOnSelector("div", "div => setTimeout(() => {\n" +
|
||||
" div.textContent = '';\n" +
|
||||
" }, 0)");
|
||||
assertThat(locator).not().isAttached();
|
||||
}
|
||||
|
||||
@ -129,6 +129,9 @@ public class TestLocatorAssertions2 extends TestBase {
|
||||
assertThat(page.locator("div")).hasAccessibleName(Pattern.compile("ell\\w"));
|
||||
assertThat(page.locator("div")).not().hasAccessibleName(Pattern.compile("hello"));
|
||||
assertThat(page.locator("div")).hasAccessibleName(Pattern.compile("hello"), new LocatorAssertions.HasAccessibleNameOptions().setIgnoreCase(true));
|
||||
|
||||
page.setContent("<button>foo bar\nbaz</button>");
|
||||
assertThat(page.locator("button")).hasAccessibleName("foo bar baz");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -141,6 +144,10 @@ public class TestLocatorAssertions2 extends TestBase {
|
||||
assertThat(page.locator("div")).hasAccessibleDescription(Pattern.compile("ell\\w"));
|
||||
assertThat(page.locator("div")).not().hasAccessibleDescription(Pattern.compile("hello"));
|
||||
assertThat(page.locator("div")).hasAccessibleDescription(Pattern.compile("hello"), new LocatorAssertions.HasAccessibleDescriptionOptions().setIgnoreCase(true));
|
||||
|
||||
page.setContent("<div role=\"button\" aria-describedby=\"desc\"></div>\n" +
|
||||
" <span id=\"desc\">foo bar\nbaz</span>");
|
||||
assertThat(page.locator("div")).hasAccessibleDescription("foo bar baz");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -150,4 +157,67 @@ public class TestLocatorAssertions2 extends TestBase {
|
||||
assertThat(page.locator("div")).hasRole(AriaRole.BUTTON);
|
||||
assertThat(page.locator("div")).not().hasRole(AriaRole.CHECKBOX);
|
||||
}
|
||||
|
||||
@Test
|
||||
void toHaveAccessibleErrorMessage() {
|
||||
page.setContent("<form>" +
|
||||
"<input role=\"textbox\" aria-invalid=\"true\" aria-errormessage=\"error-message\" />" +
|
||||
"<div id=\"error-message\">Hello</div>" +
|
||||
"<div id=\"irrelevant-error\">This should not be considered.</div>" +
|
||||
"</form>");
|
||||
|
||||
Locator locator = page.locator("input[role=\"textbox\"]");
|
||||
assertThat(locator).hasAccessibleErrorMessage("Hello");
|
||||
assertThat(locator).not().hasAccessibleErrorMessage("hello");
|
||||
assertThat(locator).hasAccessibleErrorMessage("hello", new LocatorAssertions.HasAccessibleErrorMessageOptions().setIgnoreCase(true));
|
||||
assertThat(locator).hasAccessibleErrorMessage(Pattern.compile("ell\\w"));
|
||||
assertThat(locator).not().hasAccessibleErrorMessage(Pattern.compile("hello"));
|
||||
assertThat(locator).hasAccessibleErrorMessage(Pattern.compile("hello"), new LocatorAssertions.HasAccessibleErrorMessageOptions().setIgnoreCase(true));
|
||||
assertThat(locator).not().hasAccessibleErrorMessage("This should not be considered.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void toHaveAccessibleErrorMessageShouldHandleMultipleAriaErrorMessageReferences() {
|
||||
page.setContent("<form>\n" +
|
||||
" <input role=\"textbox\" aria-invalid=\"true\" aria-errormessage=\"error1 error2\" />\n" +
|
||||
" <div id=\"error1\">First error message.</div>\n" +
|
||||
" <div id=\"error2\">Second error message.</div>\n" +
|
||||
" <div id=\"irrelevant-error\">This should not be considered.</div>\n" +
|
||||
"</form>");
|
||||
|
||||
Locator locator = page.locator("input[role=\"textbox\"]");
|
||||
|
||||
assertThat(locator).hasAccessibleErrorMessage("First error message. Second error message.");
|
||||
assertThat(locator).hasAccessibleErrorMessage(Pattern.compile("first error message.", Pattern.CASE_INSENSITIVE));
|
||||
assertThat(locator).hasAccessibleErrorMessage(Pattern.compile("second error message.", Pattern.CASE_INSENSITIVE));
|
||||
assertThat(locator).not().hasAccessibleErrorMessage(Pattern.compile("This should not be considered.", Pattern.CASE_INSENSITIVE));
|
||||
}
|
||||
|
||||
@Test
|
||||
void toBeEditableWithIndeterminateTrue() {
|
||||
page.setContent("<input type=checkbox></input>");
|
||||
page.locator("input").evaluate("e => e.indeterminate = true");
|
||||
Locator locator = page.locator("input");
|
||||
assertThat(locator).isChecked(new LocatorAssertions.IsCheckedOptions().setIndeterminate(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
void toBeEditableWithIndeterminateTrueAndChecked() {
|
||||
page.setContent("<input type=checkbox></input>");
|
||||
page.locator("input").evaluate("e => e.indeterminate = true");
|
||||
Locator locator = page.locator("input");
|
||||
PlaywrightException e = assertThrows(PlaywrightException.class, () ->
|
||||
assertThat(locator).isChecked(new LocatorAssertions.IsCheckedOptions().setIndeterminate(true).setChecked(false)));
|
||||
assertTrue(e.getMessage().contains("Can't assert indeterminate and checked at the same time"), e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void toBeEditableFailWithIndeterminateTrue() {
|
||||
page.setContent("<input type=checkbox></input>");
|
||||
Locator locator = page.locator("input");
|
||||
AssertionFailedError e = assertThrows(AssertionFailedError.class, () ->
|
||||
assertThat(locator).isChecked(new LocatorAssertions.IsCheckedOptions().setIndeterminate(true).setTimeout(1000)));
|
||||
// TODO: should be "assertThat().isChecked() with timeout 1000ms"
|
||||
assertTrue(e.getMessage().contains("Locator.expect with timeout 1000ms"), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,7 +30,6 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
public class TestPdf extends TestBase {
|
||||
@Test
|
||||
@EnabledIf(value="com.microsoft.playwright.TestBase#isChromium", disabledReason="skip")
|
||||
@DisabledIf(value="com.microsoft.playwright.TestBase#isHeadful", disabledReason="skip")
|
||||
void shouldBeAbleToSaveFile(@TempDir Path tempDir) throws IOException {
|
||||
Path path = tempDir.resolve("output.pdf");
|
||||
page.pdf(new Page.PdfOptions().setPath(path));
|
||||
@ -40,7 +39,6 @@ public class TestPdf extends TestBase {
|
||||
|
||||
@Test
|
||||
@EnabledIf(value="com.microsoft.playwright.TestBase#isChromium", disabledReason="skip")
|
||||
@DisabledIf(value="com.microsoft.playwright.TestBase#isHeadful", disabledReason="skip")
|
||||
void shouldSupportFractionalScaleValue(@TempDir Path tempDir) throws IOException {
|
||||
Path path = tempDir.resolve("output.pdf");
|
||||
page.pdf(new Page.PdfOptions().setPath(path).setScale(0.5));
|
||||
@ -51,7 +49,6 @@ public class TestPdf extends TestBase {
|
||||
|
||||
@Test
|
||||
@EnabledIf(value="com.microsoft.playwright.TestBase#isChromium", disabledReason="Printing to pdf is currently only supported in headless chromium.")
|
||||
@DisabledIf(value="com.microsoft.playwright.TestBase#isHeadful", disabledReason="Printing to pdf is currently only supported in headless chromium.")
|
||||
void shouldBeAbleToGenerateOutline(@TempDir Path tempDir) throws IOException {
|
||||
page.navigate(server.PREFIX + "/headings.html");
|
||||
Path outputFileNoOutline = tempDir.resolve("outputNoOutline.pdf");
|
||||
|
||||
@ -269,6 +269,27 @@ public class TestTracing extends TestBase {
|
||||
calls);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotRecordNetworkActions(@TempDir Path tempDir) throws IOException {
|
||||
context.tracing().start(new Tracing.StartOptions());
|
||||
|
||||
page.onRequest(request -> {
|
||||
request.allHeaders();
|
||||
});
|
||||
page.onResponse(response -> {
|
||||
response.text();
|
||||
});
|
||||
page.navigate(server.EMPTY_PAGE);
|
||||
|
||||
Path traceFile1 = tempDir.resolve("trace1.zip");
|
||||
context.tracing().stop(new Tracing.StopOptions().setPath(traceFile1));
|
||||
|
||||
List<TraceEvent> events = parseTraceEvents(traceFile1);
|
||||
List<String> calls = events.stream().filter(e -> e.apiName != null).map(e -> e.apiName)
|
||||
.collect(Collectors.toList());
|
||||
assertEquals(asList("Page.navigate"), calls);
|
||||
}
|
||||
|
||||
private static class TraceEvent {
|
||||
String type;
|
||||
String name;
|
||||
|
||||
@ -1 +1 @@
|
||||
1.49.0
|
||||
1.50.0-alpha-1737075373000
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user