Skip to content

Commit 16cc466

Browse files
authored
feat: roll driver, headerValue(s), wheel (#609)
1 parent 9588132 commit 16cc466

File tree

17 files changed

+384
-32
lines changed

17 files changed

+384
-32
lines changed

README.md

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

1212
| | Linux | macOS | Windows |
1313
| :--- | :---: | :---: | :---: |
14-
| Chromium <!-- GEN:chromium-version -->95.0.4630.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
14+
| Chromium <!-- GEN:chromium-version -->96.0.4641.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
1515
| WebKit <!-- GEN:webkit-version -->15.0<!-- GEN:stop --> ||||
16-
| Firefox <!-- GEN:firefox-version -->91.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
16+
| Firefox <!-- GEN:firefox-version -->92.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
1717

1818
Headless execution is supported for all the browsers on all platforms. Check out [system requirements](https://playwright.dev/java/docs/next/intro/#system-requirements) for details.
1919

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,5 +212,15 @@ default void up() {
212212
* Dispatches a {@code mouseup} event.
213213
*/
214214
void up(UpOptions options);
215+
/**
216+
* Dispatches a {@code wheel} event.
217+
*
218+
* <p> <strong>NOTE:</strong> Wheel events may cause scrolling if they are not handled, and this method does not wait for the scrolling to finish
219+
* before returning.
220+
*
221+
* @param deltaX Pixels to scroll horizontally.
222+
* @param deltaY Pixels to scroll vertically.
223+
*/
224+
void wheel(double deltaX, double deltaY);
215225
}
216226

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,16 @@ public interface Request {
6464
Map<String, String> headers();
6565
/**
6666
* An array with all the request HTTP headers associated with this request. Unlike {@link Request#allHeaders
67-
* Request.allHeaders()}, header names are not lower-cased. Headers with multiple entries, such as {@code Set-Cookie}, appear in
67+
* Request.allHeaders()}, header names are NOT lower-cased. Headers with multiple entries, such as {@code Set-Cookie}, appear in
6868
* the array multiple times.
6969
*/
7070
List<HttpHeader> headersArray();
71+
/**
72+
* Returns the value of the header matching the name. The name is case insensitive.
73+
*
74+
* @param name Name of the header.
75+
*/
76+
String headerValue(String name);
7177
/**
7278
* Whether this request is driving frame's navigation.
7379
*/

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public interface Response {
3232
*/
3333
byte[] body();
3434
/**
35-
* Waits for this response to finish, returns failure error if request failed.
35+
* Waits for this response to finish, returns always {@code null}.
3636
*/
3737
String finished();
3838
/**
@@ -46,10 +46,24 @@ public interface Response {
4646
Map<String, String> headers();
4747
/**
4848
* An array with all the request HTTP headers associated with this response. Unlike {@link Response#allHeaders
49-
* Response.allHeaders()}, header names are not lower-cased. Headers with multiple entries, such as {@code Set-Cookie}, appear in
49+
* Response.allHeaders()}, header names are NOT lower-cased. Headers with multiple entries, such as {@code Set-Cookie}, appear in
5050
* the array multiple times.
5151
*/
5252
List<HttpHeader> headersArray();
53+
/**
54+
* Returns the value of the header matching the name. The name is case insensitive. If multiple headers have the same name
55+
* (except {@code set-cookie}), they are returned as a list separated by {@code , }. For {@code set-cookie}, the {@code \n} separator is used. If
56+
* no headers are found, {@code null} is returned.
57+
*
58+
* @param name Name of the header.
59+
*/
60+
String headerValue(String name);
61+
/**
62+
* Returns all values of the headers matching the name, for example {@code set-cookie}. The name is case insensitive.
63+
*
64+
* @param name Name of the header.
65+
*/
66+
List<String> headerValues(String name);
5367
/**
5468
* Contains a boolean stating whether the response was successful (status in the range 200-299) or not.
5569
*/

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,10 @@ private ChannelOwner createRemoteObject(String parentGuid, JsonObject params) {
305305
case "ElementHandle":
306306
result = new ElementHandleImpl(parent, type, guid, initializer);
307307
break;
308+
case "FetchRequest":
309+
// Create fake object as this API is experimental an only exposed in Node.js.
310+
result = new ChannelOwner(parent, type, guid, initializer);
311+
break;
308312
case "Frame":
309313
result = new FrameImpl(parent, type, guid, initializer);
310314
break;

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,16 @@ public void up(UpOptions options) {
9393
page.withLogging("Mouse.up", () -> upImpl(options));
9494
}
9595

96+
@Override
97+
public void wheel(double deltaX, double deltaY) {
98+
page.withLogging("Mouse.wheel", () -> {
99+
JsonObject params = new JsonObject();
100+
params.addProperty("deltaX", deltaX);
101+
params.addProperty("deltaY", deltaY);
102+
page.sendMessage("mouseWheel", params);
103+
});
104+
}
105+
96106
private void upImpl(UpOptions options) {
97107
if (options == null) {
98108
options = new UpOptions();

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,14 @@ protected void handleEvent(String event, JsonObject params) {
125125
if (listeners.hasListeners(EventType.DIALOG)) {
126126
listeners.notify(EventType.DIALOG, dialog);
127127
} else {
128-
dialog.dismiss();
128+
if ("beforeunload".equals(dialog.type())) {
129+
try {
130+
dialog.accept();
131+
} catch (PlaywrightException e) {
132+
}
133+
} else {
134+
dialog.dismiss();
135+
}
129136
}
130137
} else if ("worker".equals(event)) {
131138
String guid = params.getAsJsonObject("worker").get("guid").getAsString();
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright (c) Microsoft Corporation.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.microsoft.playwright.impl;
18+
19+
import com.microsoft.playwright.options.HttpHeader;
20+
21+
import java.util.ArrayList;
22+
import java.util.LinkedHashMap;
23+
import java.util.List;
24+
import java.util.Map;
25+
26+
class RawHeaders {
27+
private final List<HttpHeader> headersArray;
28+
private final Map<String, List<String>> headersMap = new LinkedHashMap<>();
29+
30+
RawHeaders(List<HttpHeader> headers) {
31+
headersArray = headers;
32+
for (HttpHeader h: headers) {
33+
String name = h.name.toLowerCase();
34+
List<String> values = headersMap.get(name);
35+
if (values == null) {
36+
values = new ArrayList<>();
37+
headersMap.put(name, values);
38+
}
39+
values.add(h.value);
40+
}
41+
}
42+
43+
String get(String name) {
44+
List<String> values = getAll(name);
45+
if (values == null) {
46+
return null;
47+
}
48+
return String.join("set-cookie".equals(name.toLowerCase()) ? "\n" : ", ", values);
49+
}
50+
51+
List<String> getAll(String name) {
52+
return headersMap.get(name.toLowerCase());
53+
}
54+
55+
Map<String, String> headers() {
56+
Map<String, String> result = new LinkedHashMap<>();
57+
for (String name: headersMap.keySet()) {
58+
result.put(name, get(name));
59+
}
60+
return result;
61+
}
62+
63+
List<HttpHeader> headersArray() {
64+
return headersArray;
65+
}
66+
67+
}

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

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ public class RequestImpl extends ChannelOwner implements Request {
3737
private final byte[] postData;
3838
private RequestImpl redirectedFrom;
3939
private RequestImpl redirectedTo;
40-
private final List<HttpHeader> headers;
41-
private List<HttpHeader> rawHeaders;
40+
private final RawHeaders headers;
41+
private RawHeaders rawHeaders;
4242
String failure;
4343
Timing timing;
4444
boolean didFailOrFinish;
@@ -50,7 +50,7 @@ public class RequestImpl extends ChannelOwner implements Request {
5050
redirectedFrom = connection.getExistingObject(initializer.getAsJsonObject("redirectedFrom").get("guid").getAsString());
5151
redirectedFrom.redirectedTo = this;
5252
}
53-
headers = asList(gson().fromJson(initializer.getAsJsonArray("headers"), HttpHeader[].class));
53+
headers = new RawHeaders(asList(gson().fromJson(initializer.getAsJsonArray("headers"), HttpHeader[].class)));
5454
if (initializer.has("postData")) {
5555
postData = Base64.getDecoder().decode(initializer.get("postData").getAsString());
5656
} else {
@@ -60,7 +60,7 @@ public class RequestImpl extends ChannelOwner implements Request {
6060

6161
@Override
6262
public Map<String, String> allHeaders() {
63-
return withLogging("Request.allHeaders", () -> toHeadersMap(getRawHeaders()));
63+
return withLogging("Request.allHeaders", () -> getRawHeaders().headers());
6464
}
6565

6666
@Override
@@ -75,12 +75,17 @@ public FrameImpl frame() {
7575

7676
@Override
7777
public Map<String, String> headers() {
78-
return toHeadersMap(headers);
78+
return headers.headers();
7979
}
8080

8181
@Override
8282
public List<HttpHeader> headersArray() {
83-
return withLogging("Request.headersArray", () -> getRawHeaders());
83+
return withLogging("Request.headersArray", () -> getRawHeaders().headersArray());
84+
}
85+
86+
@Override
87+
public String headerValue(String name) {
88+
return withLogging("Request.headerValue", () -> getRawHeaders().get(name));
8489
}
8590

8691
@Override
@@ -158,7 +163,7 @@ Request finalRequest() {
158163
return redirectedTo != null ? redirectedTo.finalRequest() : this;
159164
}
160165

161-
private List<HttpHeader> getRawHeaders() {
166+
private RawHeaders getRawHeaders() {
162167
if (rawHeaders != null) {
163168
return rawHeaders;
164169
}
@@ -173,7 +178,7 @@ private List<HttpHeader> getRawHeaders() {
173178
});
174179

175180
// The field may have been initialized in a nested call but it is ok.
176-
rawHeaders = asList(gson().fromJson(rawHeadersJson, HttpHeader[].class));
181+
rawHeaders = new RawHeaders(asList(gson().fromJson(rawHeadersJson, HttpHeader[].class)));
177182
return rawHeaders;
178183
}
179184
}

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

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
package com.microsoft.playwright.impl;
1818

19-
import com.google.gson.JsonElement;
2019
import com.google.gson.JsonObject;
2120
import com.microsoft.playwright.Frame;
2221
import com.microsoft.playwright.Response;
@@ -26,32 +25,29 @@
2625
import com.microsoft.playwright.options.Timing;
2726

2827
import java.nio.charset.StandardCharsets;
29-
import java.util.*;
28+
import java.util.ArrayList;
29+
import java.util.Base64;
30+
import java.util.List;
31+
import java.util.Map;
3032

3133
import static com.microsoft.playwright.impl.Serialization.gson;
32-
import static com.microsoft.playwright.impl.Utils.toHeadersMap;
3334
import static java.util.Arrays.asList;
3435

3536
public class ResponseImpl extends ChannelOwner implements Response {
36-
private final Map<String, String> headers = new HashMap<>();
37-
private List<HttpHeader> rawHeaders;
37+
private final RawHeaders headers;
38+
private RawHeaders rawHeaders;
3839
private final RequestImpl request;
3940

4041
ResponseImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
4142
super(parent, type, guid, initializer);
42-
43-
for (JsonElement e : initializer.getAsJsonArray("headers")) {
44-
JsonObject item = e.getAsJsonObject();
45-
headers.put(item.get("name").getAsString().toLowerCase(), item.get("value").getAsString());
46-
}
47-
43+
headers = new RawHeaders(asList(gson().fromJson(initializer.getAsJsonArray("headers"), HttpHeader[].class)));
4844
request = connection.getExistingObject(initializer.getAsJsonObject("request").get("guid").getAsString());
4945
request.timing = gson().fromJson(initializer.get("timing"), Timing.class);
5046
}
5147

5248
@Override
5349
public Map<String, String> allHeaders() {
54-
return withLogging("Response.allHeaders", () -> toHeadersMap(getRawHeaders()));
50+
return withLogging("Response.allHeaders", () -> getRawHeaders().headers());
5551
}
5652

5753
@Override
@@ -89,12 +85,22 @@ public Frame frame() {
8985

9086
@Override
9187
public Map<String, String> headers() {
92-
return headers;
88+
return headers.headers();
9389
}
9490

9591
@Override
9692
public List<HttpHeader> headersArray() {
97-
return withLogging("Response.headersArray", () -> getRawHeaders());
93+
return withLogging("Response.headersArray", () -> getRawHeaders().headersArray());
94+
}
95+
96+
@Override
97+
public String headerValue(String name) {
98+
return getRawHeaders().get(name);
99+
}
100+
101+
@Override
102+
public List<String> headerValues(String name) {
103+
return getRawHeaders().getAll(name);
98104
}
99105

100106
@Override
@@ -149,10 +155,10 @@ public String url() {
149155
return initializer.get("url").getAsString();
150156
}
151157

152-
private List<HttpHeader> getRawHeaders() {
158+
private RawHeaders getRawHeaders() {
153159
if (rawHeaders == null) {
154160
JsonObject json = sendMessage("rawResponseHeaders").getAsJsonObject();
155-
rawHeaders = asList(gson().fromJson(json.getAsJsonArray("headers"), HttpHeader[].class));
161+
rawHeaders = new RawHeaders(asList(gson().fromJson(json.getAsJsonArray("headers"), HttpHeader[].class)));
156162
}
157163
return rawHeaders;
158164
}

0 commit comments

Comments
 (0)