Skip to content

Commit 7af5405

Browse files
authored
feat: roll driver, implement locator.waitFor (#639)
1 parent 50ba2da commit 7af5405

File tree

9 files changed

+125
-11
lines changed

9 files changed

+125
-11
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Playwright is a Java library to automate [Chromium](https://www.chromium.org/Hom
1111

1212
| | Linux | macOS | Windows |
1313
| :--- | :---: | :---: | :---: |
14-
| Chromium <!-- GEN:chromium-version -->96.0.4655.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
14+
| Chromium <!-- GEN:chromium-version -->96.0.4660.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
1515
| WebKit <!-- GEN:webkit-version -->15.0<!-- GEN:stop --> ||||
1616
| Firefox <!-- GEN:firefox-version -->92.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
1717

playwright/src/main/java/com/microsoft/playwright/BrowserType.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,7 +1079,8 @@ default Browser launch() {
10791079
* @param userDataDir Path to a User Data Directory, which stores browser session data like cookies and local storage. More details for <a
10801080
* href="https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md#introduction">Chromium</a> and <a
10811081
* href="https://developer.mozilla.org/en-US/docs/Mozilla/Command_Line_Options#User_Profile">Firefox</a>. Note that
1082-
* Chromium's user data directory is the **parent** directory of the "Profile Path" seen at {@code chrome://version}.
1082+
* Chromium's user data directory is the **parent** directory of the "Profile Path" seen at {@code chrome://version}. Pass an
1083+
* empty string to use a temporary directory instead.
10831084
*/
10841085
default BrowserContext launchPersistentContext(Path userDataDir) {
10851086
return launchPersistentContext(userDataDir, null);
@@ -1093,7 +1094,8 @@ default BrowserContext launchPersistentContext(Path userDataDir) {
10931094
* @param userDataDir Path to a User Data Directory, which stores browser session data like cookies and local storage. More details for <a
10941095
* href="https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md#introduction">Chromium</a> and <a
10951096
* href="https://developer.mozilla.org/en-US/docs/Mozilla/Command_Line_Options#User_Profile">Firefox</a>. Note that
1096-
* Chromium's user data directory is the **parent** directory of the "Profile Path" seen at {@code chrome://version}.
1097+
* Chromium's user data directory is the **parent** directory of the "Profile Path" seen at {@code chrome://version}. Pass an
1098+
* empty string to use a temporary directory instead.
10971099
*/
10981100
BrowserContext launchPersistentContext(Path userDataDir, LaunchPersistentContextOptions options);
10991101
/**

playwright/src/main/java/com/microsoft/playwright/Locator.java

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1355,6 +1355,51 @@ public UncheckOptions setTrial(boolean trial) {
13551355
return this;
13561356
}
13571357
}
1358+
class WaitForOptions {
1359+
/**
1360+
* Defaults to {@code "visible"}. Can be either:
1361+
* <ul>
1362+
* <li> {@code "attached"} - wait for element to be present in DOM.</li>
1363+
* <li> {@code "detached"} - wait for element to not be present in DOM.</li>
1364+
* <li> {@code "visible"} - wait for element to have non-empty bounding box and no {@code visibility:hidden}. Note that element without any
1365+
* content or with {@code display:none} has an empty bounding box and is not considered visible.</li>
1366+
* <li> {@code "hidden"} - wait for element to be either detached from DOM, or have an empty bounding box or {@code visibility:hidden}. This
1367+
* is opposite to the {@code "visible"} option.</li>
1368+
* </ul>
1369+
*/
1370+
public WaitForSelectorState state;
1371+
/**
1372+
* Maximum time in milliseconds, defaults to 30 seconds, pass {@code 0} to disable timeout. The default value can be changed by
1373+
* using the {@link BrowserContext#setDefaultTimeout BrowserContext.setDefaultTimeout()} or {@link Page#setDefaultTimeout
1374+
* Page.setDefaultTimeout()} methods.
1375+
*/
1376+
public Double timeout;
1377+
1378+
/**
1379+
* Defaults to {@code "visible"}. Can be either:
1380+
* <ul>
1381+
* <li> {@code "attached"} - wait for element to be present in DOM.</li>
1382+
* <li> {@code "detached"} - wait for element to not be present in DOM.</li>
1383+
* <li> {@code "visible"} - wait for element to have non-empty bounding box and no {@code visibility:hidden}. Note that element without any
1384+
* content or with {@code display:none} has an empty bounding box and is not considered visible.</li>
1385+
* <li> {@code "hidden"} - wait for element to be either detached from DOM, or have an empty bounding box or {@code visibility:hidden}. This
1386+
* is opposite to the {@code "visible"} option.</li>
1387+
* </ul>
1388+
*/
1389+
public WaitForOptions setState(WaitForSelectorState state) {
1390+
this.state = state;
1391+
return this;
1392+
}
1393+
/**
1394+
* Maximum time in milliseconds, defaults to 30 seconds, pass {@code 0} to disable timeout. The default value can be changed by
1395+
* using the {@link BrowserContext#setDefaultTimeout BrowserContext.setDefaultTimeout()} or {@link Page#setDefaultTimeout
1396+
* Page.setDefaultTimeout()} methods.
1397+
*/
1398+
public WaitForOptions setTimeout(double timeout) {
1399+
this.timeout = timeout;
1400+
return this;
1401+
}
1402+
}
13581403
/**
13591404
* Returns an array of {@code node.innerText} values for all matching nodes.
13601405
*/
@@ -2667,5 +2712,29 @@ default void uncheck() {
26672712
* zero timeout disables this.
26682713
*/
26692714
void uncheck(UncheckOptions options);
2715+
/**
2716+
* Returns when element specified by locator satisfies the {@code state} option.
2717+
*
2718+
* <p> If target element already satisfies the condition, the method returns immediately. Otherwise, waits for up to {@code timeout}
2719+
* milliseconds until the condition is met.
2720+
* <pre>{@code
2721+
* Locator orderSent = page.locator("#order-sent");
2722+
* orderSent.waitFor();
2723+
* }</pre>
2724+
*/
2725+
default void waitFor() {
2726+
waitFor(null);
2727+
}
2728+
/**
2729+
* Returns when element specified by locator satisfies the {@code state} option.
2730+
*
2731+
* <p> If target element already satisfies the condition, the method returns immediately. Otherwise, waits for up to {@code timeout}
2732+
* milliseconds until the condition is met.
2733+
* <pre>{@code
2734+
* Locator orderSent = page.locator("#order-sent");
2735+
* orderSent.waitFor();
2736+
* }</pre>
2737+
*/
2738+
void waitFor(WaitForOptions options);
26702739
}
26712740

playwright/src/main/java/com/microsoft/playwright/impl/FrameImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -948,11 +948,16 @@ public ElementHandle waitForSelector(String selector, WaitForSelectorOptions opt
948948
}
949949

950950
ElementHandle waitForSelectorImpl(String selector, WaitForSelectorOptions options) {
951+
return waitForSelectorImpl(selector, options, false);
952+
}
953+
954+
ElementHandle waitForSelectorImpl(String selector, WaitForSelectorOptions options, boolean omitReturnValue) {
951955
if (options == null) {
952956
options = new WaitForSelectorOptions();
953957
}
954958
JsonObject params = gson().toJsonTree(options).getAsJsonObject();
955959
params.addProperty("selector", selector);
960+
params.addProperty("omitReturnValue", omitReturnValue);
956961
JsonElement json = sendMessage("waitForSelector", params);
957962
JsonObject element = json.getAsJsonObject().getAsJsonObject("element");
958963
if (element == null) {

playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,18 @@ public void uncheck(UncheckOptions options) {
399399
frame.uncheck(selector, convertViaJson(options, Frame.UncheckOptions.class).setStrict(true));
400400
}
401401

402+
@Override
403+
public void waitFor(WaitForOptions options) {
404+
if (options == null) {
405+
options = new WaitForOptions();
406+
}
407+
waitForImpl(options);
408+
}
409+
410+
private void waitForImpl(WaitForOptions options) {
411+
frame.withLogging("Locator.waitFor", () -> frame.waitForSelectorImpl(selector, convertViaJson(options, Frame.WaitForSelectorOptions.class).setStrict(true), true));
412+
}
413+
402414
@Override
403415
public String toString() {
404416
return "Locator@" + selector;

playwright/src/main/java/com/microsoft/playwright/impl/RequestImpl.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -167,13 +167,8 @@ private RawHeaders getRawHeaders() {
167167
if (rawHeaders != null) {
168168
return rawHeaders;
169169
}
170-
ResponseImpl response = response();
171-
// there is no response, so should we return the headers we have now?
172-
if (response == null) {
173-
return headers;
174-
}
175-
JsonArray rawHeadersJson = response.withLogging("Request.allHeaders", () -> {
176-
JsonObject result = response.sendMessage("rawRequestHeaders").getAsJsonObject();
170+
JsonArray rawHeadersJson = withLogging("Request.allHeaders", () -> {
171+
JsonObject result = sendMessage("rawRequestHeaders").getAsJsonObject();
177172
return result.getAsJsonArray("headers");
178173
});
179174

playwright/src/test/java/com/microsoft/playwright/TestLocatorMisc.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616

1717
package com.microsoft.playwright;
1818

19+
import com.microsoft.playwright.options.WaitForSelectorState;
1920
import org.junit.jupiter.api.Test;
2021

2122
import static org.junit.jupiter.api.Assertions.assertEquals;
23+
import static org.junit.jupiter.api.Assertions.assertTrue;
2224

2325
public class TestLocatorMisc extends TestBase{
2426
@Test
@@ -30,4 +32,21 @@ void shouldCheckTheBoxUsingSetChecked() {
3032
input.setChecked(false);
3133
assertEquals(false, page.evaluate("checkbox.checked"));
3234
}
35+
36+
@Test
37+
void shouldWaitFor() {
38+
page.setContent("<div></div>");
39+
Locator locator = page.locator("span");
40+
page.evalOnSelector("div", "div => setTimeout(() => div.innerHTML = '<span>target</span>', 500)");
41+
locator.waitFor();
42+
assertTrue(locator.textContent().contains("target"));
43+
}
44+
45+
@Test
46+
void shouldWaitForHidden() {
47+
page.setContent("<div><span>target</span></div>");
48+
Locator locator = page.locator("span");
49+
page.evalOnSelector("div", "div => setTimeout(() => div.innerHTML = '', 500)");
50+
locator.waitFor(new Locator.WaitForOptions().setState(WaitForSelectorState.HIDDEN));
51+
}
3352
}

playwright/src/test/java/com/microsoft/playwright/TestNetworkRequest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,18 @@ void shouldWorkForARedirect() {
7373
assertEquals(server.PREFIX + "/empty.html", requests.get(1).url());
7474
}
7575

76+
@Test
77+
void shouldWorkAllHeadersInsideRoute() {
78+
List<Request> requests = new ArrayList<>();
79+
page.route("**", route -> {
80+
assertTrue(route.request().allHeaders().get("accept").length() > 5);
81+
requests.add(route.request());
82+
route.resume();
83+
});
84+
page.navigate(server.PREFIX + "/empty.html");
85+
assertEquals(1, requests.size());
86+
}
87+
7688
// https://github.com/microsoft/playwright/issues/3993
7789
@Test
7890
void shouldNotWorkForARedirectAndInterception() {

scripts/CLI_VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.16.0-next-1632766475000
1+
1.16.0-next-1633463468000

0 commit comments

Comments
 (0)