1
0
mirror of synced 2026-08-05 23:16:54 +00:00

feat: roll driver to Apr 12, implement new APIs (#1264)

This commit is contained in:
Yury Semikhatsky
2023-04-12 13:38:04 -07:00
committed by GitHub
parent 804c577070
commit 45591df430
19 changed files with 536 additions and 68 deletions
+1 -1
View File
@@ -11,7 +11,7 @@ Playwright is a Java library to automate [Chromium](https://www.chromium.org/Hom
| | Linux | macOS | Windows |
| :--- | :---: | :---: | :---: |
| Chromium <!-- GEN:chromium-version -->112.0.5615.29<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Chromium <!-- GEN:chromium-version -->113.0.5672.24<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| WebKit <!-- GEN:webkit-version -->16.4<!-- GEN:stop --> | ✅ | ✅ | ✅ |
| Firefox <!-- GEN:firefox-version -->111.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
@@ -46,7 +46,8 @@ public interface APIRequest {
*/
public Map<String, String> extraHTTPHeaders;
/**
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>.
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>. If
* no origin is specified, the username and password are sent to any servers upon unauthorized responses.
*/
public HttpCredentials httpCredentials;
/**
@@ -106,13 +107,15 @@ public interface APIRequest {
return this;
}
/**
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>.
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>. If
* no origin is specified, the username and password are sent to any servers upon unauthorized responses.
*/
public NewContextOptions setHttpCredentials(String username, String password) {
return setHttpCredentials(new HttpCredentials(username, password));
}
/**
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>.
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>. If
* no origin is specified, the username and password are sent to any servers upon unauthorized responses.
*/
public NewContextOptions setHttpCredentials(HttpCredentials httpCredentials) {
this.httpCredentials = httpCredentials;
@@ -107,7 +107,8 @@ public interface Browser extends AutoCloseable {
*/
public Boolean hasTouch;
/**
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>.
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>. If
* no origin is specified, the username and password are sent to any servers upon unauthorized responses.
*/
public HttpCredentials httpCredentials;
/**
@@ -315,13 +316,15 @@ public interface Browser extends AutoCloseable {
return this;
}
/**
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>.
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>. If
* no origin is specified, the username and password are sent to any servers upon unauthorized responses.
*/
public NewContextOptions setHttpCredentials(String username, String password) {
return setHttpCredentials(new HttpCredentials(username, password));
}
/**
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>.
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>. If
* no origin is specified, the username and password are sent to any servers upon unauthorized responses.
*/
public NewContextOptions setHttpCredentials(HttpCredentials httpCredentials) {
this.httpCredentials = httpCredentials;
@@ -611,7 +614,8 @@ public interface Browser extends AutoCloseable {
*/
public Boolean hasTouch;
/**
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>.
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>. If
* no origin is specified, the username and password are sent to any servers upon unauthorized responses.
*/
public HttpCredentials httpCredentials;
/**
@@ -819,13 +823,15 @@ public interface Browser extends AutoCloseable {
return this;
}
/**
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>.
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>. If
* no origin is specified, the username and password are sent to any servers upon unauthorized responses.
*/
public NewPageOptions setHttpCredentials(String username, String password) {
return setHttpCredentials(new HttpCredentials(username, password));
}
/**
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>.
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>. If
* no origin is specified, the username and password are sent to any servers upon unauthorized responses.
*/
public NewPageOptions setHttpCredentials(HttpCredentials httpCredentials) {
this.httpCredentials = httpCredentials;
@@ -473,7 +473,8 @@ public interface BrowserType {
*/
public Boolean headless;
/**
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>.
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>. If
* no origin is specified, the username and password are sent to any servers upon unauthorized responses.
*/
public HttpCredentials httpCredentials;
/**
@@ -787,13 +788,15 @@ public interface BrowserType {
return this;
}
/**
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>.
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>. If
* no origin is specified, the username and password are sent to any servers upon unauthorized responses.
*/
public LaunchPersistentContextOptions setHttpCredentials(String username, String password) {
return setHttpCredentials(new HttpCredentials(username, password));
}
/**
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>.
* Credentials for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">HTTP authentication</a>. If
* no origin is specified, the username and password are sent to any servers upon unauthorized responses.
*/
public LaunchPersistentContextOptions setHttpCredentials(HttpCredentials httpCredentials) {
this.httpCredentials = httpCredentials;
@@ -1046,8 +1046,8 @@ public interface Frame {
* <ul>
* <li> {@code "domcontentloaded"} - consider operation to be finished when the {@code DOMContentLoaded} event is fired.</li>
* <li> {@code "load"} - consider operation to be finished when the {@code load} event is fired.</li>
* <li> {@code "networkidle"} - consider operation to be finished when there are no network connections for at least {@code 500}
* ms.</li>
* <li> {@code "networkidle"} - **DISCOURAGED** consider operation to be finished when there are no network connections for at
* least {@code 500} ms. Don't use this method for testing, rely on web assertions to assess readiness instead.</li>
* <li> {@code "commit"} - consider operation to be finished when network response is received and the document started loading.</li>
* </ul>
*/
@@ -1076,8 +1076,8 @@ public interface Frame {
* <ul>
* <li> {@code "domcontentloaded"} - consider operation to be finished when the {@code DOMContentLoaded} event is fired.</li>
* <li> {@code "load"} - consider operation to be finished when the {@code load} event is fired.</li>
* <li> {@code "networkidle"} - consider operation to be finished when there are no network connections for at least {@code 500}
* ms.</li>
* <li> {@code "networkidle"} - **DISCOURAGED** consider operation to be finished when there are no network connections for at
* least {@code 500} ms. Don't use this method for testing, rely on web assertions to assess readiness instead.</li>
* <li> {@code "commit"} - consider operation to be finished when network response is received and the document started loading.</li>
* </ul>
*/
@@ -1476,6 +1476,19 @@ public interface Frame {
* <p> Note that outer and inner locators must belong to the same frame. Inner locator must not contain {@code FrameLocator}s.
*/
public Locator has;
/**
* Matches elements that do not contain an element that matches an inner locator. Inner locator is queried against the
* outer one. For example, {@code article} that does not have {@code div} matches {@code
* <article><span>Playwright</span></article>}.
*
* <p> Note that outer and inner locators must belong to the same frame. Inner locator must not contain {@code FrameLocator}s.
*/
public Locator hasNot;
/**
* Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element. When
* passed a [string], matching is case-insensitive and searches for a substring.
*/
public Object hasNotText;
/**
* Matches elements containing specified text somewhere inside, possibly in a child or a descendant element. When passed a
* [string], matching is case-insensitive and searches for a substring. For example, {@code "Playwright"} matches {@code
@@ -1493,6 +1506,33 @@ public interface Frame {
this.has = has;
return this;
}
/**
* Matches elements that do not contain an element that matches an inner locator. Inner locator is queried against the
* outer one. For example, {@code article} that does not have {@code div} matches {@code
* <article><span>Playwright</span></article>}.
*
* <p> Note that outer and inner locators must belong to the same frame. Inner locator must not contain {@code FrameLocator}s.
*/
public LocatorOptions setHasNot(Locator hasNot) {
this.hasNot = hasNot;
return this;
}
/**
* Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element. When
* passed a [string], matching is case-insensitive and searches for a substring.
*/
public LocatorOptions setHasNotText(String hasNotText) {
this.hasNotText = hasNotText;
return this;
}
/**
* Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element. When
* passed a [string], matching is case-insensitive and searches for a substring.
*/
public LocatorOptions setHasNotText(Pattern hasNotText) {
this.hasNotText = hasNotText;
return this;
}
/**
* Matches elements containing specified text somewhere inside, possibly in a child or a descendant element. When passed a
* [string], matching is case-insensitive and searches for a substring. For example, {@code "Playwright"} matches {@code
@@ -1751,8 +1791,8 @@ public interface Frame {
* <ul>
* <li> {@code "domcontentloaded"} - consider operation to be finished when the {@code DOMContentLoaded} event is fired.</li>
* <li> {@code "load"} - consider operation to be finished when the {@code load} event is fired.</li>
* <li> {@code "networkidle"} - consider operation to be finished when there are no network connections for at least {@code 500}
* ms.</li>
* <li> {@code "networkidle"} - **DISCOURAGED** consider operation to be finished when there are no network connections for at
* least {@code 500} ms. Don't use this method for testing, rely on web assertions to assess readiness instead.</li>
* <li> {@code "commit"} - consider operation to be finished when network response is received and the document started loading.</li>
* </ul>
*/
@@ -1773,8 +1813,8 @@ public interface Frame {
* <ul>
* <li> {@code "domcontentloaded"} - consider operation to be finished when the {@code DOMContentLoaded} event is fired.</li>
* <li> {@code "load"} - consider operation to be finished when the {@code load} event is fired.</li>
* <li> {@code "networkidle"} - consider operation to be finished when there are no network connections for at least {@code 500}
* ms.</li>
* <li> {@code "networkidle"} - **DISCOURAGED** consider operation to be finished when there are no network connections for at
* least {@code 500} ms. Don't use this method for testing, rely on web assertions to assess readiness instead.</li>
* <li> {@code "commit"} - consider operation to be finished when network response is received and the document started loading.</li>
* </ul>
*/
@@ -2188,8 +2228,8 @@ public interface Frame {
* <ul>
* <li> {@code "domcontentloaded"} - consider operation to be finished when the {@code DOMContentLoaded} event is fired.</li>
* <li> {@code "load"} - consider operation to be finished when the {@code load} event is fired.</li>
* <li> {@code "networkidle"} - consider operation to be finished when there are no network connections for at least {@code 500}
* ms.</li>
* <li> {@code "networkidle"} - **DISCOURAGED** consider operation to be finished when there are no network connections for at
* least {@code 500} ms. Don't use this method for testing, rely on web assertions to assess readiness instead.</li>
* <li> {@code "commit"} - consider operation to be finished when network response is received and the document started loading.</li>
* </ul>
*/
@@ -2237,8 +2277,8 @@ public interface Frame {
* <ul>
* <li> {@code "domcontentloaded"} - consider operation to be finished when the {@code DOMContentLoaded} event is fired.</li>
* <li> {@code "load"} - consider operation to be finished when the {@code load} event is fired.</li>
* <li> {@code "networkidle"} - consider operation to be finished when there are no network connections for at least {@code 500}
* ms.</li>
* <li> {@code "networkidle"} - **DISCOURAGED** consider operation to be finished when there are no network connections for at
* least {@code 500} ms. Don't use this method for testing, rely on web assertions to assess readiness instead.</li>
* <li> {@code "commit"} - consider operation to be finished when network response is received and the document started loading.</li>
* </ul>
*/
@@ -2318,8 +2358,8 @@ public interface Frame {
* <ul>
* <li> {@code "domcontentloaded"} - consider operation to be finished when the {@code DOMContentLoaded} event is fired.</li>
* <li> {@code "load"} - consider operation to be finished when the {@code load} event is fired.</li>
* <li> {@code "networkidle"} - consider operation to be finished when there are no network connections for at least {@code 500}
* ms.</li>
* <li> {@code "networkidle"} - **DISCOURAGED** consider operation to be finished when there are no network connections for at
* least {@code 500} ms. Don't use this method for testing, rely on web assertions to assess readiness instead.</li>
* <li> {@code "commit"} - consider operation to be finished when network response is received and the document started loading.</li>
* </ul>
*/
@@ -2340,8 +2380,8 @@ public interface Frame {
* <ul>
* <li> {@code "domcontentloaded"} - consider operation to be finished when the {@code DOMContentLoaded} event is fired.</li>
* <li> {@code "load"} - consider operation to be finished when the {@code load} event is fired.</li>
* <li> {@code "networkidle"} - consider operation to be finished when there are no network connections for at least {@code 500}
* ms.</li>
* <li> {@code "networkidle"} - **DISCOURAGED** consider operation to be finished when there are no network connections for at
* least {@code 500} ms. Don't use this method for testing, rely on web assertions to assess readiness instead.</li>
* <li> {@code "commit"} - consider operation to be finished when network response is received and the document started loading.</li>
* </ul>
*/
@@ -4849,7 +4889,8 @@ public interface Frame {
* <ul>
* <li> {@code "load"} - wait for the {@code load} event to be fired.</li>
* <li> {@code "domcontentloaded"} - wait for the {@code DOMContentLoaded} event to be fired.</li>
* <li> {@code "networkidle"} - wait until there are no network connections for at least {@code 500} ms.</li>
* <li> {@code "networkidle"} - **DISCOURAGED** wait until there are no network connections for at least {@code 500} ms. Don't
* use this method for testing, rely on web assertions to assess readiness instead.</li>
* </ul>
* @since v1.8
*/
@@ -4890,7 +4931,8 @@ public interface Frame {
* <ul>
* <li> {@code "load"} - wait for the {@code load} event to be fired.</li>
* <li> {@code "domcontentloaded"} - wait for the {@code DOMContentLoaded} event to be fired.</li>
* <li> {@code "networkidle"} - wait until there are no network connections for at least {@code 500} ms.</li>
* <li> {@code "networkidle"} - **DISCOURAGED** wait until there are no network connections for at least {@code 500} ms. Don't
* use this method for testing, rely on web assertions to assess readiness instead.</li>
* </ul>
* @since v1.8
*/
@@ -291,6 +291,19 @@ public interface FrameLocator {
* <p> Note that outer and inner locators must belong to the same frame. Inner locator must not contain {@code FrameLocator}s.
*/
public Locator has;
/**
* Matches elements that do not contain an element that matches an inner locator. Inner locator is queried against the
* outer one. For example, {@code article} that does not have {@code div} matches {@code
* <article><span>Playwright</span></article>}.
*
* <p> Note that outer and inner locators must belong to the same frame. Inner locator must not contain {@code FrameLocator}s.
*/
public Locator hasNot;
/**
* Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element. When
* passed a [string], matching is case-insensitive and searches for a substring.
*/
public Object hasNotText;
/**
* Matches elements containing specified text somewhere inside, possibly in a child or a descendant element. When passed a
* [string], matching is case-insensitive and searches for a substring. For example, {@code "Playwright"} matches {@code
@@ -308,6 +321,33 @@ public interface FrameLocator {
this.has = has;
return this;
}
/**
* Matches elements that do not contain an element that matches an inner locator. Inner locator is queried against the
* outer one. For example, {@code article} that does not have {@code div} matches {@code
* <article><span>Playwright</span></article>}.
*
* <p> Note that outer and inner locators must belong to the same frame. Inner locator must not contain {@code FrameLocator}s.
*/
public LocatorOptions setHasNot(Locator hasNot) {
this.hasNot = hasNot;
return this;
}
/**
* Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element. When
* passed a [string], matching is case-insensitive and searches for a substring.
*/
public LocatorOptions setHasNotText(String hasNotText) {
this.hasNotText = hasNotText;
return this;
}
/**
* Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element. When
* passed a [string], matching is case-insensitive and searches for a substring.
*/
public LocatorOptions setHasNotText(Pattern hasNotText) {
this.hasNotText = hasNotText;
return this;
}
/**
* Matches elements containing specified text somewhere inside, possibly in a child or a descendant element. When passed a
* [string], matching is case-insensitive and searches for a substring. For example, {@code "Playwright"} matches {@code
@@ -135,7 +135,7 @@ public interface JSHandle {
*
* <p> **Usage**
* <pre>{@code
* JSHandle handle = page.evaluateHandle("() => ({window, document}"););
* JSHandle handle = page.evaluateHandle("() => ({window, document})");
* Map<String, JSHandle> properties = handle.getProperties();
* JSHandle windowHandle = properties.get("window");
* JSHandle documentHandle = properties.get("document");
@@ -662,6 +662,19 @@ public interface Locator {
* <p> Note that outer and inner locators must belong to the same frame. Inner locator must not contain {@code FrameLocator}s.
*/
public Locator has;
/**
* Matches elements that do not contain an element that matches an inner locator. Inner locator is queried against the
* outer one. For example, {@code article} that does not have {@code div} matches {@code
* <article><span>Playwright</span></article>}.
*
* <p> Note that outer and inner locators must belong to the same frame. Inner locator must not contain {@code FrameLocator}s.
*/
public Locator hasNot;
/**
* Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element. When
* passed a [string], matching is case-insensitive and searches for a substring.
*/
public Object hasNotText;
/**
* Matches elements containing specified text somewhere inside, possibly in a child or a descendant element. When passed a
* [string], matching is case-insensitive and searches for a substring. For example, {@code "Playwright"} matches {@code
@@ -679,6 +692,33 @@ public interface Locator {
this.has = has;
return this;
}
/**
* Matches elements that do not contain an element that matches an inner locator. Inner locator is queried against the
* outer one. For example, {@code article} that does not have {@code div} matches {@code
* <article><span>Playwright</span></article>}.
*
* <p> Note that outer and inner locators must belong to the same frame. Inner locator must not contain {@code FrameLocator}s.
*/
public FilterOptions setHasNot(Locator hasNot) {
this.hasNot = hasNot;
return this;
}
/**
* Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element. When
* passed a [string], matching is case-insensitive and searches for a substring.
*/
public FilterOptions setHasNotText(String hasNotText) {
this.hasNotText = hasNotText;
return this;
}
/**
* Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element. When
* passed a [string], matching is case-insensitive and searches for a substring.
*/
public FilterOptions setHasNotText(Pattern hasNotText) {
this.hasNotText = hasNotText;
return this;
}
/**
* Matches elements containing specified text somewhere inside, possibly in a child or a descendant element. When passed a
* [string], matching is case-insensitive and searches for a substring. For example, {@code "Playwright"} matches {@code
@@ -1228,6 +1268,19 @@ public interface Locator {
* <p> Note that outer and inner locators must belong to the same frame. Inner locator must not contain {@code FrameLocator}s.
*/
public Locator has;
/**
* Matches elements that do not contain an element that matches an inner locator. Inner locator is queried against the
* outer one. For example, {@code article} that does not have {@code div} matches {@code
* <article><span>Playwright</span></article>}.
*
* <p> Note that outer and inner locators must belong to the same frame. Inner locator must not contain {@code FrameLocator}s.
*/
public Locator hasNot;
/**
* Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element. When
* passed a [string], matching is case-insensitive and searches for a substring.
*/
public Object hasNotText;
/**
* Matches elements containing specified text somewhere inside, possibly in a child or a descendant element. When passed a
* [string], matching is case-insensitive and searches for a substring. For example, {@code "Playwright"} matches {@code
@@ -1245,6 +1298,33 @@ public interface Locator {
this.has = has;
return this;
}
/**
* Matches elements that do not contain an element that matches an inner locator. Inner locator is queried against the
* outer one. For example, {@code article} that does not have {@code div} matches {@code
* <article><span>Playwright</span></article>}.
*
* <p> Note that outer and inner locators must belong to the same frame. Inner locator must not contain {@code FrameLocator}s.
*/
public LocatorOptions setHasNot(Locator hasNot) {
this.hasNot = hasNot;
return this;
}
/**
* Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element. When
* passed a [string], matching is case-insensitive and searches for a substring.
*/
public LocatorOptions setHasNotText(String hasNotText) {
this.hasNotText = hasNotText;
return this;
}
/**
* Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element. When
* passed a [string], matching is case-insensitive and searches for a substring.
*/
public LocatorOptions setHasNotText(Pattern hasNotText) {
this.hasNotText = hasNotText;
return this;
}
/**
* Matches elements containing specified text somewhere inside, possibly in a child or a descendant element. When passed a
* [string], matching is case-insensitive and searches for a substring. For example, {@code "Playwright"} matches {@code
@@ -3744,6 +3824,26 @@ public interface Locator {
* @since v1.14
*/
Locator nth(int index);
/**
* Creates a locator that matches either of the two locators.
*
* <p> **Usage**
*
* <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.
* <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();
* if (dialog.isVisible())
* page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Dismiss")).click();
* newEmail.click();
* }</pre>
*
* @param locator Alternative locator to match.
* @since v1.33
*/
Locator or(Locator locator);
/**
* A page this locator belongs to.
*
@@ -1391,8 +1391,8 @@ public interface Page extends AutoCloseable {
* <ul>
* <li> {@code "domcontentloaded"} - consider operation to be finished when the {@code DOMContentLoaded} event is fired.</li>
* <li> {@code "load"} - consider operation to be finished when the {@code load} event is fired.</li>
* <li> {@code "networkidle"} - consider operation to be finished when there are no network connections for at least {@code 500}
* ms.</li>
* <li> {@code "networkidle"} - **DISCOURAGED** consider operation to be finished when there are no network connections for at
* least {@code 500} ms. Don't use this method for testing, rely on web assertions to assess readiness instead.</li>
* <li> {@code "commit"} - consider operation to be finished when network response is received and the document started loading.</li>
* </ul>
*/
@@ -1413,8 +1413,8 @@ public interface Page extends AutoCloseable {
* <ul>
* <li> {@code "domcontentloaded"} - consider operation to be finished when the {@code DOMContentLoaded} event is fired.</li>
* <li> {@code "load"} - consider operation to be finished when the {@code load} event is fired.</li>
* <li> {@code "networkidle"} - consider operation to be finished when there are no network connections for at least {@code 500}
* ms.</li>
* <li> {@code "networkidle"} - **DISCOURAGED** consider operation to be finished when there are no network connections for at
* least {@code 500} ms. Don't use this method for testing, rely on web assertions to assess readiness instead.</li>
* <li> {@code "commit"} - consider operation to be finished when network response is received and the document started loading.</li>
* </ul>
*/
@@ -1436,8 +1436,8 @@ public interface Page extends AutoCloseable {
* <ul>
* <li> {@code "domcontentloaded"} - consider operation to be finished when the {@code DOMContentLoaded} event is fired.</li>
* <li> {@code "load"} - consider operation to be finished when the {@code load} event is fired.</li>
* <li> {@code "networkidle"} - consider operation to be finished when there are no network connections for at least {@code 500}
* ms.</li>
* <li> {@code "networkidle"} - **DISCOURAGED** consider operation to be finished when there are no network connections for at
* least {@code 500} ms. Don't use this method for testing, rely on web assertions to assess readiness instead.</li>
* <li> {@code "commit"} - consider operation to be finished when network response is received and the document started loading.</li>
* </ul>
*/
@@ -1458,8 +1458,8 @@ public interface Page extends AutoCloseable {
* <ul>
* <li> {@code "domcontentloaded"} - consider operation to be finished when the {@code DOMContentLoaded} event is fired.</li>
* <li> {@code "load"} - consider operation to be finished when the {@code load} event is fired.</li>
* <li> {@code "networkidle"} - consider operation to be finished when there are no network connections for at least {@code 500}
* ms.</li>
* <li> {@code "networkidle"} - **DISCOURAGED** consider operation to be finished when there are no network connections for at
* least {@code 500} ms. Don't use this method for testing, rely on web assertions to assess readiness instead.</li>
* <li> {@code "commit"} - consider operation to be finished when network response is received and the document started loading.</li>
* </ul>
*/
@@ -1486,8 +1486,8 @@ public interface Page extends AutoCloseable {
* <ul>
* <li> {@code "domcontentloaded"} - consider operation to be finished when the {@code DOMContentLoaded} event is fired.</li>
* <li> {@code "load"} - consider operation to be finished when the {@code load} event is fired.</li>
* <li> {@code "networkidle"} - consider operation to be finished when there are no network connections for at least {@code 500}
* ms.</li>
* <li> {@code "networkidle"} - **DISCOURAGED** consider operation to be finished when there are no network connections for at
* least {@code 500} ms. Don't use this method for testing, rely on web assertions to assess readiness instead.</li>
* <li> {@code "commit"} - consider operation to be finished when network response is received and the document started loading.</li>
* </ul>
*/
@@ -1516,8 +1516,8 @@ public interface Page extends AutoCloseable {
* <ul>
* <li> {@code "domcontentloaded"} - consider operation to be finished when the {@code DOMContentLoaded} event is fired.</li>
* <li> {@code "load"} - consider operation to be finished when the {@code load} event is fired.</li>
* <li> {@code "networkidle"} - consider operation to be finished when there are no network connections for at least {@code 500}
* ms.</li>
* <li> {@code "networkidle"} - **DISCOURAGED** consider operation to be finished when there are no network connections for at
* least {@code 500} ms. Don't use this method for testing, rely on web assertions to assess readiness instead.</li>
* <li> {@code "commit"} - consider operation to be finished when network response is received and the document started loading.</li>
* </ul>
*/
@@ -1916,6 +1916,19 @@ public interface Page extends AutoCloseable {
* <p> Note that outer and inner locators must belong to the same frame. Inner locator must not contain {@code FrameLocator}s.
*/
public Locator has;
/**
* Matches elements that do not contain an element that matches an inner locator. Inner locator is queried against the
* outer one. For example, {@code article} that does not have {@code div} matches {@code
* <article><span>Playwright</span></article>}.
*
* <p> Note that outer and inner locators must belong to the same frame. Inner locator must not contain {@code FrameLocator}s.
*/
public Locator hasNot;
/**
* Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element. When
* passed a [string], matching is case-insensitive and searches for a substring.
*/
public Object hasNotText;
/**
* Matches elements containing specified text somewhere inside, possibly in a child or a descendant element. When passed a
* [string], matching is case-insensitive and searches for a substring. For example, {@code "Playwright"} matches {@code
@@ -1933,6 +1946,33 @@ public interface Page extends AutoCloseable {
this.has = has;
return this;
}
/**
* Matches elements that do not contain an element that matches an inner locator. Inner locator is queried against the
* outer one. For example, {@code article} that does not have {@code div} matches {@code
* <article><span>Playwright</span></article>}.
*
* <p> Note that outer and inner locators must belong to the same frame. Inner locator must not contain {@code FrameLocator}s.
*/
public LocatorOptions setHasNot(Locator hasNot) {
this.hasNot = hasNot;
return this;
}
/**
* Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element. When
* passed a [string], matching is case-insensitive and searches for a substring.
*/
public LocatorOptions setHasNotText(String hasNotText) {
this.hasNotText = hasNotText;
return this;
}
/**
* Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element. When
* passed a [string], matching is case-insensitive and searches for a substring.
*/
public LocatorOptions setHasNotText(Pattern hasNotText) {
this.hasNotText = hasNotText;
return this;
}
/**
* Matches elements containing specified text somewhere inside, possibly in a child or a descendant element. When passed a
* [string], matching is case-insensitive and searches for a substring. For example, {@code "Playwright"} matches {@code
@@ -2204,8 +2244,8 @@ public interface Page extends AutoCloseable {
* <ul>
* <li> {@code "domcontentloaded"} - consider operation to be finished when the {@code DOMContentLoaded} event is fired.</li>
* <li> {@code "load"} - consider operation to be finished when the {@code load} event is fired.</li>
* <li> {@code "networkidle"} - consider operation to be finished when there are no network connections for at least {@code 500}
* ms.</li>
* <li> {@code "networkidle"} - **DISCOURAGED** consider operation to be finished when there are no network connections for at
* least {@code 500} ms. Don't use this method for testing, rely on web assertions to assess readiness instead.</li>
* <li> {@code "commit"} - consider operation to be finished when network response is received and the document started loading.</li>
* </ul>
*/
@@ -2226,8 +2266,8 @@ public interface Page extends AutoCloseable {
* <ul>
* <li> {@code "domcontentloaded"} - consider operation to be finished when the {@code DOMContentLoaded} event is fired.</li>
* <li> {@code "load"} - consider operation to be finished when the {@code load} event is fired.</li>
* <li> {@code "networkidle"} - consider operation to be finished when there are no network connections for at least {@code 500}
* ms.</li>
* <li> {@code "networkidle"} - **DISCOURAGED** consider operation to be finished when there are no network connections for at
* least {@code 500} ms. Don't use this method for testing, rely on web assertions to assess readiness instead.</li>
* <li> {@code "commit"} - consider operation to be finished when network response is received and the document started loading.</li>
* </ul>
*/
@@ -2670,8 +2710,8 @@ public interface Page extends AutoCloseable {
* <ul>
* <li> {@code "domcontentloaded"} - consider operation to be finished when the {@code DOMContentLoaded} event is fired.</li>
* <li> {@code "load"} - consider operation to be finished when the {@code load} event is fired.</li>
* <li> {@code "networkidle"} - consider operation to be finished when there are no network connections for at least {@code 500}
* ms.</li>
* <li> {@code "networkidle"} - **DISCOURAGED** consider operation to be finished when there are no network connections for at
* least {@code 500} ms. Don't use this method for testing, rely on web assertions to assess readiness instead.</li>
* <li> {@code "commit"} - consider operation to be finished when network response is received and the document started loading.</li>
* </ul>
*/
@@ -2692,8 +2732,8 @@ public interface Page extends AutoCloseable {
* <ul>
* <li> {@code "domcontentloaded"} - consider operation to be finished when the {@code DOMContentLoaded} event is fired.</li>
* <li> {@code "load"} - consider operation to be finished when the {@code load} event is fired.</li>
* <li> {@code "networkidle"} - consider operation to be finished when there are no network connections for at least {@code 500}
* ms.</li>
* <li> {@code "networkidle"} - **DISCOURAGED** consider operation to be finished when there are no network connections for at
* least {@code 500} ms. Don't use this method for testing, rely on web assertions to assess readiness instead.</li>
* <li> {@code "commit"} - consider operation to be finished when network response is received and the document started loading.</li>
* </ul>
*/
@@ -3204,8 +3244,8 @@ public interface Page extends AutoCloseable {
* <ul>
* <li> {@code "domcontentloaded"} - consider operation to be finished when the {@code DOMContentLoaded} event is fired.</li>
* <li> {@code "load"} - consider operation to be finished when the {@code load} event is fired.</li>
* <li> {@code "networkidle"} - consider operation to be finished when there are no network connections for at least {@code 500}
* ms.</li>
* <li> {@code "networkidle"} - **DISCOURAGED** consider operation to be finished when there are no network connections for at
* least {@code 500} ms. Don't use this method for testing, rely on web assertions to assess readiness instead.</li>
* <li> {@code "commit"} - consider operation to be finished when network response is received and the document started loading.</li>
* </ul>
*/
@@ -3253,8 +3293,8 @@ public interface Page extends AutoCloseable {
* <ul>
* <li> {@code "domcontentloaded"} - consider operation to be finished when the {@code DOMContentLoaded} event is fired.</li>
* <li> {@code "load"} - consider operation to be finished when the {@code load} event is fired.</li>
* <li> {@code "networkidle"} - consider operation to be finished when there are no network connections for at least {@code 500}
* ms.</li>
* <li> {@code "networkidle"} - **DISCOURAGED** consider operation to be finished when there are no network connections for at
* least {@code 500} ms. Don't use this method for testing, rely on web assertions to assess readiness instead.</li>
* <li> {@code "commit"} - consider operation to be finished when network response is received and the document started loading.</li>
* </ul>
*/
@@ -3440,8 +3480,8 @@ public interface Page extends AutoCloseable {
* <ul>
* <li> {@code "domcontentloaded"} - consider operation to be finished when the {@code DOMContentLoaded} event is fired.</li>
* <li> {@code "load"} - consider operation to be finished when the {@code load} event is fired.</li>
* <li> {@code "networkidle"} - consider operation to be finished when there are no network connections for at least {@code 500}
* ms.</li>
* <li> {@code "networkidle"} - **DISCOURAGED** consider operation to be finished when there are no network connections for at
* least {@code 500} ms. Don't use this method for testing, rely on web assertions to assess readiness instead.</li>
* <li> {@code "commit"} - consider operation to be finished when network response is received and the document started loading.</li>
* </ul>
*/
@@ -3462,8 +3502,8 @@ public interface Page extends AutoCloseable {
* <ul>
* <li> {@code "domcontentloaded"} - consider operation to be finished when the {@code DOMContentLoaded} event is fired.</li>
* <li> {@code "load"} - consider operation to be finished when the {@code load} event is fired.</li>
* <li> {@code "networkidle"} - consider operation to be finished when there are no network connections for at least {@code 500}
* ms.</li>
* <li> {@code "networkidle"} - **DISCOURAGED** consider operation to be finished when there are no network connections for at
* least {@code 500} ms. Don't use this method for testing, rely on web assertions to assess readiness instead.</li>
* <li> {@code "commit"} - consider operation to be finished when network response is received and the document started loading.</li>
* </ul>
*/
@@ -7251,7 +7291,8 @@ public interface Page extends AutoCloseable {
* <ul>
* <li> {@code "load"} - wait for the {@code load} event to be fired.</li>
* <li> {@code "domcontentloaded"} - wait for the {@code DOMContentLoaded} event to be fired.</li>
* <li> {@code "networkidle"} - wait until there are no network connections for at least {@code 500} ms.</li>
* <li> {@code "networkidle"} - **DISCOURAGED** wait until there are no network connections for at least {@code 500} ms. Don't
* use this method for testing, rely on web assertions to assess readiness instead.</li>
* </ul>
* @since v1.8
*/
@@ -7308,7 +7349,8 @@ public interface Page extends AutoCloseable {
* <ul>
* <li> {@code "load"} - wait for the {@code load} event to be fired.</li>
* <li> {@code "domcontentloaded"} - wait for the {@code DOMContentLoaded} event to be fired.</li>
* <li> {@code "networkidle"} - wait until there are no network connections for at least {@code 500} ms.</li>
* <li> {@code "networkidle"} - **DISCOURAGED** wait until there are no network connections for at least {@code 500} ms. Don't
* use this method for testing, rely on web assertions to assess readiness instead.</li>
* </ul>
* @since v1.8
*/
@@ -37,6 +37,25 @@ import java.util.regex.Pattern;
* }</pre>
*/
public interface LocatorAssertions {
class IsAttachedOptions {
public Boolean attached;
/**
* Time to retry the assertion for.
*/
public Double timeout;
public IsAttachedOptions setAttached(boolean attached) {
this.attached = attached;
return this;
}
/**
* Time to retry the assertion for.
*/
public IsAttachedOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
class IsCheckedOptions {
public Boolean checked;
/**
@@ -394,6 +413,32 @@ public interface LocatorAssertions {
* @since v1.20
*/
LocatorAssertions not();
/**
* Ensures that {@code Locator} points to an <a href="https://playwright.dev/java/docs/actionability#attached">attached</a>
* DOM node.
*
* <p> **Usage**
* <pre>{@code
* assertThat(page.getByText("Hidden text")).isAttached();
* }</pre>
*
* @since v1.33
*/
default void isAttached() {
isAttached(null);
}
/**
* Ensures that {@code Locator} points to an <a href="https://playwright.dev/java/docs/actionability#attached">attached</a>
* DOM node.
*
* <p> **Usage**
* <pre>{@code
* assertThat(page.getByText("Hidden text")).isAttached();
* }</pre>
*
* @since v1.33
*/
void isAttached(IsAttachedOptions options);
/**
* Ensures the {@code Locator} points to a checked input.
*
@@ -618,7 +663,7 @@ public interface LocatorAssertions {
*
* <p> **Usage**
* <pre>{@code
* assertThat(page.locator(".my-element")).isVisible();
* assertThat(page.getByText("Welcome")).isVisible();
* }</pre>
*
* @since v1.20
@@ -632,7 +677,7 @@ public interface LocatorAssertions {
*
* <p> **Usage**
* <pre>{@code
* assertThat(page.locator(".my-element")).isVisible();
* assertThat(page.getByText("Welcome")).isVisible();
* }</pre>
*
* @since v1.20
@@ -357,6 +357,14 @@ public class LocatorAssertionsImpl extends AssertionsBase implements LocatorAsse
return new LocatorAssertionsImpl(actualLocator, !isNot);
}
@Override
public void isAttached(IsAttachedOptions options) {
FrameExpectOptions frameOptions = convertType(options, FrameExpectOptions.class);
boolean attached = options == null || options.attached == null || options.attached == true;
String message = "Locator expected to be " + (attached ? "attached" : "detached");
expectTrue(attached ? "to.be.attached" : "to.be.detached", message, frameOptions);
}
private static Boolean shouldIgnoreCase(Object options) {
if (options == null) {
return null;
@@ -29,12 +29,21 @@ class LocatorImpl implements Locator {
if (options.hasText != null) {
selector += " >> internal:has-text=" + escapeForTextSelector(options.hasText, false);
}
if (options.hasNotText != null) {
selector += " >> internal:has-not-text=" + escapeForTextSelector(options.hasNotText, false);
}
if (options.has != null) {
LocatorImpl locator = (LocatorImpl) options.has;
if (locator.frame != frame)
throw new Error("Inner 'has' locator must belong to the same frame.");
selector += " >> internal:has=" + gson().toJson(locator.selector);
}
if (options.hasNot != null) {
LocatorImpl locator = (LocatorImpl) options.hasNot;
if (locator.frame != frame)
throw new Error("Inner 'hasNot' locator must belong to the same frame.");
selector += " >> internal:has-not=" + gson().toJson(locator.selector);
}
}
this.selector = selector;
}
@@ -398,6 +407,14 @@ class LocatorImpl implements Locator {
return new LocatorImpl(frame, selector + " >> nth=" + index, null);
}
@Override
public Locator or(Locator locator) {
LocatorImpl other = (LocatorImpl) locator;
if (other.frame != frame)
throw new Error("Locators must belong to the same frame.");
return new LocatorImpl(frame, selector + " >> internal:or=" + gson().toJson(other.selector), null);
}
@Override
public Page page() {
return frame.page();
@@ -47,6 +47,7 @@ public class RouteImpl extends ChannelOwner implements Route {
withLogging("Route.abort", () -> {
JsonObject params = new JsonObject();
params.addProperty("errorCode", errorCode);
params.addProperty("requestUrl", request.initializer.get("url").getAsString());
sendMessageAsync("abort", params);
});
}
@@ -95,7 +96,7 @@ public class RouteImpl extends ChannelOwner implements Route {
String url = (fetchOptions == null || fetchOptions.url == null) ? request().url() : fetchOptions.url;
return apiRequest.fetch(url, options);
}
private void applyOverrides(FallbackOptions options) {
if (options == null) {
return;
@@ -127,6 +128,7 @@ public class RouteImpl extends ChannelOwner implements Route {
params.addProperty("postData", base64);
}
}
params.addProperty("requestUrl", request.initializer.get("url").getAsString());
sendMessageAsync("continue", params);
}
@@ -221,6 +223,7 @@ public class RouteImpl extends ChannelOwner implements Route {
if (fetchResponseUid != null) {
params.addProperty("fetchResponseUid", fetchResponseUid);
}
params.addProperty("requestUrl", request.initializer.get("url").getAsString());
sendMessageAsync("fulfill", params);
}
@@ -19,9 +19,20 @@ package com.microsoft.playwright.options;
public class HttpCredentials {
public String username;
public String password;
/**
* Restrain sending http credentials on specific origin (scheme://host:port).
*/
public String origin;
public HttpCredentials(String username, String password) {
this.username = username;
this.password = password;
}
/**
* Restrain sending http credentials on specific origin (scheme://host:port).
*/
public HttpCredentials setOrigin(String origin) {
this.origin = origin;
return this;
}
}
@@ -52,8 +52,8 @@ public class Timing {
*/
public double requestStart;
/**
* Time immediately after the browser starts requesting the resource from the server, cache, or local resource. The value
* is given in milliseconds relative to {@code startTime}, -1 if not available.
* Time immediately after the browser receives the first byte of the response from the server, cache, or local resource.
* The value is given in milliseconds relative to {@code startTime}, -1 if not available.
*/
public double responseStart;
/**
@@ -0,0 +1,102 @@
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.*;
public class TestLocatorAssertions2 extends TestBase {
@Test
void isAttachedDefault() {
page.setContent("<input></input>");
Locator locator = page.locator("input");
assertThat(locator).isAttached();
}
@Test
void isAttachedWithHiddenElement() {
page.setContent("<button style='display:none'>hello</button>");
Locator locator = page.locator("button");
assertThat(locator).isAttached();
}
@Test
void isAttachedWithNot() {
page.setContent("<button>hello</button>");
Locator locator = page.locator("input");
assertThat(locator).not().isAttached();
}
@Test
void isAttachedWithAttachedTrue() {
page.setContent("<button>hello</button>");
Locator locator = page.locator("button");
assertThat(locator).isAttached(new LocatorAssertions.IsAttachedOptions().setAttached(true));
}
@Test
void isAttachedWithAttachedFalse() {
page.setContent("<button>hello</button>");
Locator locator = page.locator("input");
assertThat(locator).isAttached(new LocatorAssertions.IsAttachedOptions().setAttached(false));
}
@Test
void isAttachedWithNotAndAttachedFalse() {
page.setContent("<button>hello</button>");
Locator locator = page.locator("button");
assertThat(locator).not().isAttached(new LocatorAssertions.IsAttachedOptions().setAttached(false));
}
@Test
void isAttachedEventually() {
page.setContent("<div></div>");
Locator locator = page.locator("span");
page.evalOnSelector("div", "div => setTimeout(() => {\n" +
" div.innerHTML = '<span>Hello</span>'\n" +
" }, 100)");
assertThat(locator).isAttached();
}
@Test
void isAttachedEventuallyWithNot() {
page.setContent("<div><span>Hello</span></div>");
Locator locator = page.locator("span");
page.evalOnSelector("div", "div => setTimeout(() => {\n" +
" div.textContent = '';\n" +
" }, 0)");
assertThat(locator).not().isAttached();
}
@Test
void isAttachedFail() {
page.setContent("<button>Hello</button>");
Locator locator = page.locator("input");
AssertionFailedError error = assertThrows(AssertionFailedError.class,
() -> assertThat(locator).isAttached(new LocatorAssertions.IsAttachedOptions().setTimeout(1000)));
assertFalse(error.getMessage().contains("locator resolved to"), error.getMessage());
}
@Test
void isAttachedFailWithNot() {
page.setContent("<input></input>");
Locator locator = page.locator("input");
AssertionFailedError error = assertThrows(AssertionFailedError.class,
() -> assertThat(locator).not().isAttached(new LocatorAssertions.IsAttachedOptions().setTimeout(1000)));
assertTrue(error.getMessage().contains("locator resolved to <input/>"), error.getMessage());
}
@Test
void isAttachedWithImpossibleTimeout() {
page.setContent("<div id=node>Text content</div>");
assertThat(page.locator("#node")).isAttached(new LocatorAssertions.IsAttachedOptions().setTimeout(1));
}
@Test
void isAttachedWithImpossibleTimeoutNot() {
page.setContent("<div id=node>Text content</div>");
assertThat(page.locator("no-such-thing")).not().isAttached(new LocatorAssertions.IsAttachedOptions().setTimeout(1));
}
}
@@ -172,5 +172,26 @@ public class TestPageLocatorQuery extends TestBase {
assertThat(page.locator("div").filter(new Locator.FilterOptions()
.setHas(page.locator("span"))
.setHasText("world"))).hasCount(1);
assertThat(page.locator("div").filter(new Locator.FilterOptions()
.setHasNot(page.locator("span", new Page.LocatorOptions().setHasText("world"))))).hasCount(1);
assertThat(page.locator("div").filter(new Locator.FilterOptions()
.setHasNot(page.locator("section")))).hasCount(2);
assertThat(page.locator("div").filter(new Locator.FilterOptions()
.setHasNot(page.locator("span")))).hasCount(0);
assertThat(page.locator("div").filter(new Locator.FilterOptions().setHasNotText("hello"))).hasCount(1);
assertThat(page.locator("div").filter(new Locator.FilterOptions().setHasNotText("foo"))).hasCount(2);
}
@Test
void shouldSupportLocatorOr() {
page.setContent("<div>hello</div><span>world</span>");
assertThat(page.locator("div").or(page.locator("span"))).hasCount(2);
assertThat(page.locator("div").or(page.locator("span"))).hasText(new String[]{"hello", "world"});
assertThat(page.locator("span").or(page.locator("article")).or(page.locator("div"))).hasText(new String[]{"hello", "world"});
assertThat(page.locator("article").or(page.locator("someting"))).hasCount(0);
assertThat(page.locator("article").or(page.locator("div"))).hasText("hello");
assertThat(page.locator("article").or(page.locator("span"))).hasText("world");
assertThat(page.locator("div").or(page.locator("article"))).hasText("hello");
assertThat(page.locator("span").or(page.locator("article"))).hasText("world");
}
}
@@ -2,6 +2,7 @@ package com.microsoft.playwright;
import org.junit.jupiter.api.Test;
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.*;
public class TestSelectorsMisc extends TestBase {
@@ -194,4 +195,28 @@ public class TestSelectorsMisc extends TestBase {
e = assertThrows(PlaywrightException.class, () -> page.querySelector("div >> left-of='span',3,4"));
assertTrue(e.getMessage().contains("Malformed selector: left-of='span',3,4"));
}
@Test
void shouldWorkWithInternalHasNot() {
page.setContent("<section><span></span><div></div></section><section><br></section>");
assertEquals(1, page.evalOnSelectorAll("section >> internal:has-not=\"span\"", "els => els.length"));
assertEquals(0, page.evalOnSelectorAll("section >> internal:has-not=\"span, div, br\"", "els => els.length"));
assertEquals(1, page.evalOnSelectorAll("section >> internal:has-not=\"br\"", "els => els.length"));
assertEquals(1, page.evalOnSelectorAll("section >> internal:has-not=\"span, div\"", "els => els.length"));
assertEquals(2, page.evalOnSelectorAll("section >> internal:has-not=\"article\"", "els => els.length"));
}
@Test
void shouldWorkWithInternalOr() {
page.setContent("<div>hello</div>\n" +
" <span>world</span>");
assertEquals(asList("hello", "world"), page.evalOnSelectorAll("div >> internal:or=\"span\"", "els => els.map(e => e.textContent)"));
assertEquals(asList("hello", "world"), page.evalOnSelectorAll("span >> internal:or=\"div\"", "els => els.map(e => e.textContent)"));
assertEquals(0, page.evalOnSelectorAll("article >> internal:or=\"something\"", "els => els.length"));
assertEquals("hello", page.locator("article >> internal:or=\"div\"").textContent());
assertEquals("world", page.locator("article >> internal:or=\"span\"").textContent());
assertEquals("hello", page.locator("div >> internal:or=\"article\"").textContent());
assertEquals("world", page.locator("span >> internal:or=\"article\"").textContent());
}
}
+1 -1
View File
@@ -1 +1 @@
1.32.1
1.33.0-alpha-apr-12-2023