fix: generate return and param types from api.json (#276)

This commit is contained in:
Yury Semikhatsky 2021-02-10 15:42:03 -08:00 committed by GitHub
parent 442a577506
commit ea34deeb2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 345 additions and 452 deletions

View File

@ -42,109 +42,6 @@ public interface BrowserContext extends AutoCloseable {
void onPage(Consumer<Page> handler);
void offPage(Consumer<Page> handler);
class AddCookie {
public String name;
public String value;
/**
* either url or domain / path are required. Optional.
*/
public String url;
/**
* either url or domain / path are required Optional.
*/
public String domain;
/**
* either url or domain / path are required Optional.
*/
public String path;
/**
* Unix time in seconds. Optional.
*/
public Double expires;
/**
* Optional.
*/
public Boolean httpOnly;
/**
* Optional.
*/
public Boolean secure;
/**
* Optional.
*/
public SameSiteAttribute sameSite;
public AddCookie(String name, String value) {
this.name = name;
this.value = value;
}
public AddCookie withUrl(String url) {
this.url = url;
return this;
}
public AddCookie withDomain(String domain) {
this.domain = domain;
return this;
}
public AddCookie withPath(String path) {
this.path = path;
return this;
}
public AddCookie withExpires(double expires) {
this.expires = expires;
return this;
}
public AddCookie withHttpOnly(boolean httpOnly) {
this.httpOnly = httpOnly;
return this;
}
public AddCookie withSecure(boolean secure) {
this.secure = secure;
return this;
}
public AddCookie withSameSite(SameSiteAttribute sameSite) {
this.sameSite = sameSite;
return this;
}
}
class Cookie {
private String name;
private String value;
private String domain;
private String path;
/**
* Unix time in seconds.
*/
private double expires;
private boolean httpOnly;
private boolean secure;
private SameSiteAttribute sameSite;
public String name() {
return this.name;
}
public String value() {
return this.value;
}
public String domain() {
return this.domain;
}
public String path() {
return this.path;
}
public double expires() {
return this.expires;
}
public boolean httpOnly() {
return this.httpOnly;
}
public boolean secure() {
return this.secure;
}
public SameSiteAttribute sameSite() {
return this.sameSite;
}
}
class ExposeBindingOptions {
/**
* Whether to pass the argument as a handle, instead of passing by value. When passing a handle, only one argument is
@ -204,7 +101,7 @@ public interface BrowserContext extends AutoCloseable {
* Adds cookies into this browser context. All pages within this context will have these cookies installed. Cookies can be
* obtained via [{@code method: BrowserContext.cookies}].
*/
void addCookies(List<AddCookie> cookies);
void addCookies(List<Cookie> cookies);
/**
* Adds a script which would be evaluated in one of the following scenarios:
* - Whenever a page is created in the browser context or is navigated.

View File

@ -22,32 +22,11 @@ import java.util.*;
* {@code ConsoleMessage} objects are dispatched by page via the [{@code event: Page.console}] event.
*/
public interface ConsoleMessage {
class Location {
/**
* URL of the resource.
*/
private String url;
/**
* 0-based line number in the resource.
*/
private int lineNumber;
/**
* 0-based column number in the resource.
*/
private int columnNumber;
public String url() {
return this.url;
}
public int lineNumber() {
return this.lineNumber;
}
public int columnNumber() {
return this.columnNumber;
}
}
List<JSHandle> args();
Location location();
/**
* URL of the resource followed by 0-based line and column numbers in the resource formatted as {@code URL:line:column}.
*/
String location();
String text();
/**
* One of the following values: {@code 'log'}, {@code 'debug'}, {@code 'info'}, {@code 'error'}, {@code 'warning'}, {@code 'dir'}, {@code 'dirxml'}, {@code 'table'},

View File

@ -33,13 +33,6 @@ import java.util.*;
* methods.
*/
public interface ElementHandle extends JSHandle {
class BoundingBox {
public double x;
public double y;
public double width;
public double height;
}
class SelectOption {
public String value;
public String label;

View File

@ -979,21 +979,6 @@ public interface Page extends AutoCloseable {
return this;
}
}
class SetViewportSizeViewportSize {
/**
* page width in pixels.
*/
public int width;
/**
* page height in pixels.
*/
public int height;
public SetViewportSizeViewportSize(int width, int height) {
this.width = width;
this.height = height;
}
}
class TapOptions {
/**
* Whether to bypass the [actionability](./actionability.md) checks. Defaults to {@code false}.

View File

@ -16,6 +16,7 @@
package com.microsoft.playwright;
import com.microsoft.playwright.options.*;
import java.util.*;
/**
@ -34,80 +35,6 @@ import java.util.*;
* request is issued to a redirected url.
*/
public interface Request {
class RequestTiming {
/**
* Request start time in milliseconds elapsed since January 1, 1970 00:00:00 UTC
*/
private double startTime;
/**
* Time immediately before the browser starts the domain name lookup for the resource. The value is given in milliseconds
* relative to {@code startTime}, -1 if not available.
*/
private double domainLookupStart;
/**
* Time immediately after the browser starts the domain name lookup for the resource. The value is given in milliseconds
* relative to {@code startTime}, -1 if not available.
*/
private double domainLookupEnd;
/**
* Time immediately before the user agent starts establishing the connection to the server to retrieve the resource. The
* value is given in milliseconds relative to {@code startTime}, -1 if not available.
*/
private double connectStart;
/**
* Time immediately before the browser starts the handshake process to secure the current connection. The value is given in
* milliseconds relative to {@code startTime}, -1 if not available.
*/
private double secureConnectionStart;
/**
* Time immediately before the user agent starts establishing the connection to the server to retrieve the resource. The
* value is given in milliseconds relative to {@code startTime}, -1 if not available.
*/
private double connectEnd;
/**
* Time immediately before 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.
*/
private 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.
*/
private double responseStart;
/**
* Time immediately after the browser receives the last byte of the resource or immediately before the transport connection
* is closed, whichever comes first. The value is given in milliseconds relative to {@code startTime}, -1 if not available.
*/
private double responseEnd;
public double startTime() {
return this.startTime;
}
public double domainLookupStart() {
return this.domainLookupStart;
}
public double domainLookupEnd() {
return this.domainLookupEnd;
}
public double connectStart() {
return this.connectStart;
}
public double secureConnectionStart() {
return this.secureConnectionStart;
}
public double connectEnd() {
return this.connectEnd;
}
public double requestStart() {
return this.requestStart;
}
public double responseStart() {
return this.responseStart;
}
public double responseEnd() {
return this.responseEnd;
}
}
/**
* The method returns {@code null} unless this request has failed, as reported by {@code requestfailed} event.
*
@ -171,7 +98,7 @@ public interface Request {
* {@code responseEnd} becomes available when request finishes. Find more information at
* [Resource Timing API](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming).
*/
RequestTiming timing();
Timing timing();
/**
* URL of the request.
*/

View File

@ -113,7 +113,7 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
}
@Override
public void addCookies(List<AddCookie> cookies) {
public void addCookies(List<Cookie> cookies) {
withLogging("BrowserContext.addCookies", () -> {
JsonObject params = new JsonObject();
params.add("cookies", gson().toJsonTree(cookies));

View File

@ -48,7 +48,11 @@ public class ConsoleMessageImpl extends ChannelOwner implements ConsoleMessage {
return result;
}
public Location location() {
return gson().fromJson(initializer.get("location"), Location.class);
@Override
public String location() {
JsonObject location = initializer.getAsJsonObject("location");
return location.get("url").getAsString() + ":" +
location.get("lineNumber").getAsNumber() + ":" +
location.get("columnNumber").getAsNumber();
}
}

View File

@ -20,18 +20,19 @@ import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.microsoft.playwright.ElementHandle;
import com.microsoft.playwright.options.ElementState;
import com.microsoft.playwright.FileChooser;
import com.microsoft.playwright.Frame;
import com.microsoft.playwright.options.BoundingBox;
import com.microsoft.playwright.options.ElementState;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import static com.microsoft.playwright.impl.Serialization.*;
import static com.microsoft.playwright.options.ScreenshotType.JPEG;
import static com.microsoft.playwright.options.ScreenshotType.PNG;
import static com.microsoft.playwright.impl.Serialization.*;
public class ElementHandleImpl extends JSHandleImpl implements ElementHandle {
ElementHandleImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {

View File

@ -21,6 +21,7 @@ import com.google.gson.JsonObject;
import com.microsoft.playwright.Frame;
import com.microsoft.playwright.Request;
import com.microsoft.playwright.Response;
import com.microsoft.playwright.options.Timing;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
@ -33,7 +34,7 @@ public class RequestImpl extends ChannelOwner implements Request {
private RequestImpl redirectedTo;
final Map<String, String> headers = new HashMap<>();
String failure;
RequestTiming timing;
Timing timing;
RequestImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
super(parent, type, guid, initializer);
@ -118,8 +119,8 @@ public class RequestImpl extends ChannelOwner implements Request {
}
@Override
public RequestTiming timing() {
return null;
public Timing timing() {
return timing;
}
@Override

View File

@ -21,6 +21,7 @@ import com.google.gson.JsonObject;
import com.microsoft.playwright.Frame;
import com.microsoft.playwright.Request;
import com.microsoft.playwright.Response;
import com.microsoft.playwright.options.Timing;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
@ -45,7 +46,7 @@ public class ResponseImpl extends ChannelOwner implements Response {
JsonObject item = e.getAsJsonObject();
request.headers.put(item.get("name").getAsString().toLowerCase(), item.get("value").getAsString());
}
request.timing = Serialization.gson().fromJson(initializer.get("timing"), Request.RequestTiming.class);
request.timing = Serialization.gson().fromJson(initializer.get("timing"), Timing.class);
}
@Override

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.microsoft.playwright.options;
public class BoundingBox {
/**
* the x coordinate of the element in pixels.
*/
public double x;
/**
* the y coordinate of the element in pixels.
*/
public double y;
/**
* the width of the element in pixels.
*/
public double width;
/**
* the height of the element in pixels.
*/
public double height;
}

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.microsoft.playwright.options;
public class Cookie {
public String name;
public String value;
/**
* either url or domain / path are required. Optional.
*/
public String url;
/**
* either url or domain / path are required Optional.
*/
public String domain;
/**
* either url or domain / path are required Optional.
*/
public String path;
/**
* Unix time in seconds. Optional.
*/
public Double expires;
/**
* Optional.
*/
public Boolean httpOnly;
/**
* Optional.
*/
public Boolean secure;
/**
* Optional.
*/
public SameSiteAttribute sameSite;
public Cookie(String name, String value) {
this.name = name;
this.value = value;
}
public Cookie withUrl(String url) {
this.url = url;
return this;
}
public Cookie withDomain(String domain) {
this.domain = domain;
return this;
}
public Cookie withPath(String path) {
this.path = path;
return this;
}
public Cookie withExpires(double expires) {
this.expires = expires;
return this;
}
public Cookie withHttpOnly(boolean httpOnly) {
this.httpOnly = httpOnly;
return this;
}
public Cookie withSecure(boolean secure) {
this.secure = secure;
return this;
}
public Cookie withSameSite(SameSiteAttribute sameSite) {
this.sameSite = sameSite;
return this;
}
}

View File

@ -17,33 +17,25 @@
package com.microsoft.playwright.options;
public class Geolocation {
/**
* Latitude between -90 and 90.
*/
public double latitude;
/**
* Longitude between -180 and 180.
*/
public double longitude;
/**
* Non-negative accuracy value. Defaults to {@code 0}.
*/
public Double accuracy;
public Geolocation() {
}
public Geolocation(double latitude, double longitude) {
this(latitude, longitude, null);
}
public Geolocation(double latitude, double longitude, Double accuracy) {
this.latitude = latitude;
this.longitude = longitude;
this.accuracy = accuracy;
}
public Geolocation withLatitude(double latitude) {
this.latitude = latitude;
return this;
}
public Geolocation withLongitude(double longitude) {
this.longitude = longitude;
return this;
}
public Geolocation withAccuracy(double accuracy) {
this.accuracy = accuracy;
return this;
}
}
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.microsoft.playwright.options;
public class Timing {
/**
* Request start time in milliseconds elapsed since January 1, 1970 00:00:00 UTC
*/
public double startTime;
/**
* Time immediately before the browser starts the domain name lookup for the resource. The value is given in milliseconds
* relative to {@code startTime}, -1 if not available.
*/
public double domainLookupStart;
/**
* Time immediately after the browser starts the domain name lookup for the resource. The value is given in milliseconds
* relative to {@code startTime}, -1 if not available.
*/
public double domainLookupEnd;
/**
* Time immediately before the user agent starts establishing the connection to the server to retrieve the resource. The
* value is given in milliseconds relative to {@code startTime}, -1 if not available.
*/
public double connectStart;
/**
* Time immediately before the browser starts the handshake process to secure the current connection. The value is given in
* milliseconds relative to {@code startTime}, -1 if not available.
*/
public double secureConnectionStart;
/**
* Time immediately before the user agent starts establishing the connection to the server to retrieve the resource. The
* value is given in milliseconds relative to {@code startTime}, -1 if not available.
*/
public double connectEnd;
/**
* Time immediately before 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.
*/
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.
*/
public double responseStart;
/**
* Time immediately after the browser receives the last byte of the resource or immediately before the transport connection
* is closed, whichever comes first. The value is given in milliseconds relative to {@code startTime}, -1 if not available.
*/
public double responseEnd;
}

View File

@ -17,6 +17,7 @@
package com.microsoft.playwright;
import com.google.gson.Gson;
import com.microsoft.playwright.options.Cookie;
import org.junit.jupiter.api.Test;
import java.time.Instant;
@ -35,7 +36,7 @@ public class TestBrowserContextAddCookies extends TestBase {
void shouldWork() {
page.navigate(server.EMPTY_PAGE);
context.addCookies(asList(
new BrowserContext.AddCookie("password", "123456").withUrl(server.EMPTY_PAGE)));
new Cookie("password", "123456").withUrl(server.EMPTY_PAGE)));
assertEquals("password=123456", page.evaluate("document.cookie"));
}
@ -49,13 +50,13 @@ public class TestBrowserContextAddCookies extends TestBase {
" return document.cookie;\n" +
"}");
assertEquals("username=John Doe", documentCookie);
List<BrowserContext.Cookie> cookies = context.cookies();
List<Cookie> cookies = context.cookies();
context.clearCookies();
assertEquals(emptyList(), context.cookies());
context.addCookies(asList(new BrowserContext.AddCookie(cookies.get(0).name(), cookies.get(0).value())
.withDomain(cookies.get(0).domain())
.withPath(cookies.get(0).path())
.withExpires(cookies.get(0).expires())
context.addCookies(asList(new Cookie(cookies.get(0).name, cookies.get(0).value)
.withDomain(cookies.get(0).domain)
.withPath(cookies.get(0).path)
.withExpires(cookies.get(0).expires)
));
assertJsonEquals(new Gson().toJson(cookies), context.cookies());
}
@ -64,7 +65,7 @@ public class TestBrowserContextAddCookies extends TestBase {
void shouldSendCookieHeader() throws ExecutionException, InterruptedException {
Future<Server.Request> request = server.futureRequest("/empty.html");
context.addCookies(asList(
new BrowserContext.AddCookie("cookie", "value").withUrl(server.EMPTY_PAGE)));
new Cookie("cookie", "value").withUrl(server.EMPTY_PAGE)));
Page page = context.newPage();
page.navigate(server.EMPTY_PAGE);
List<String> cookies = request.get().headers.get("cookie");
@ -75,17 +76,17 @@ public class TestBrowserContextAddCookies extends TestBase {
void shouldIsolateCookiesInBrowserContexts() {
BrowserContext anotherContext = browser.newContext();
context.addCookies(asList(
new BrowserContext.AddCookie("isolatecookie", "page1value").withUrl(server.EMPTY_PAGE)));
new Cookie("isolatecookie", "page1value").withUrl(server.EMPTY_PAGE)));
anotherContext.addCookies(asList(
new BrowserContext.AddCookie("isolatecookie", "page2value").withUrl(server.EMPTY_PAGE)));
List<BrowserContext.Cookie> cookies1 = context.cookies();
List<BrowserContext.Cookie> cookies2 = anotherContext.cookies();
new Cookie("isolatecookie", "page2value").withUrl(server.EMPTY_PAGE)));
List<Cookie> cookies1 = context.cookies();
List<Cookie> cookies2 = anotherContext.cookies();
assertEquals(1, cookies1.size());
assertEquals(1, cookies2.size());
assertEquals("isolatecookie", cookies1.get(0).name());
assertEquals("page1value", cookies1.get(0).value());
assertEquals("isolatecookie", cookies2.get(0).name());
assertEquals("page2value", cookies2.get(0).value());
assertEquals("isolatecookie", cookies1.get(0).name);
assertEquals("page1value", cookies1.get(0).value);
assertEquals("isolatecookie", cookies2.get(0).name);
assertEquals("page2value", cookies2.get(0).value);
anotherContext.close();
}
@ -103,15 +104,15 @@ public class TestBrowserContextAddCookies extends TestBase {
{
Page page = context.newPage();
page.navigate(server.EMPTY_PAGE);
List<BrowserContext.Cookie> cookies = context.cookies();
List<Cookie> cookies = context.cookies();
assertEquals(1, cookies.size());
assertEquals("value", cookies.get(0).value());
assertEquals("value", cookies.get(0).value);
}
{
BrowserContext context2 = browser.newContext();
Page page = context2.newPage();
page.navigate(server.EMPTY_PAGE);
List<BrowserContext.Cookie> cookies = context2.cookies();
List<Cookie> cookies = context2.cookies();
assertEquals(0, cookies.size());
context2.close();
}
@ -133,11 +134,11 @@ public class TestBrowserContextAddCookies extends TestBase {
Page page2 = context2.newPage();
page1.navigate(server.EMPTY_PAGE);
page2.navigate(server.EMPTY_PAGE);
List<BrowserContext.Cookie> cookies1 = context1.cookies();
List<BrowserContext.Cookie> cookies2 = context2.cookies();
List<Cookie> cookies1 = context1.cookies();
List<Cookie> cookies2 = context2.cookies();
assertEquals(1, cookies1.size());
assertEquals("persistent", cookies1.get(0).name());
assertEquals("persistent-value", cookies1.get(0).value());
assertEquals("persistent", cookies1.get(0).name);
assertEquals("persistent-value", cookies1.get(0).value);
assertEquals(0, cookies2.size());
context2.close();
}
@ -145,7 +146,7 @@ public class TestBrowserContextAddCookies extends TestBase {
@Test
void shouldIsolateSendCookieHeader() throws ExecutionException, InterruptedException {
context.addCookies(asList(
new BrowserContext.AddCookie("sendcookie", "value").withUrl(server.EMPTY_PAGE)));
new Cookie("sendcookie", "value").withUrl(server.EMPTY_PAGE)));
{
Page page = context.newPage();
Future<Server.Request> request = server.futureRequest("/empty.html");
@ -169,7 +170,7 @@ public class TestBrowserContextAddCookies extends TestBase {
// TODO: const browser1 = browserType.launch(browserOptions);
Browser browser1 = browserType.launch();
BrowserContext context1 = browser1.newContext();
context1.addCookies(asList(new BrowserContext.AddCookie("cookie-in-context-1", "value")
context1.addCookies(asList(new Cookie("cookie-in-context-1", "value")
.withUrl(server.EMPTY_PAGE)
.withExpires(Instant.now().getEpochSecond() + + 10000)));
browser1.close();
@ -177,7 +178,7 @@ public class TestBrowserContextAddCookies extends TestBase {
// const browser2 = browserType.launch(browserOptions);
Browser browser2 = browserType.launch();
BrowserContext context2 = browser2.newContext();
List<BrowserContext.Cookie> cookies = context2.cookies();
List<Cookie> cookies = context2.cookies();
assertEquals(0, cookies.size());
browser2.close();
}
@ -186,8 +187,8 @@ public class TestBrowserContextAddCookies extends TestBase {
void shouldSetMultipleCookies() {
page.navigate(server.EMPTY_PAGE);
context.addCookies(asList(
new BrowserContext.AddCookie("multiple-1", "123456").withUrl(server.EMPTY_PAGE),
new BrowserContext.AddCookie("multiple-2", "bar").withUrl(server.EMPTY_PAGE)
new Cookie("multiple-1", "123456").withUrl(server.EMPTY_PAGE),
new Cookie("multiple-2", "bar").withUrl(server.EMPTY_PAGE)
));
assertEquals(asList("multiple-1=123456", "multiple-2=bar"), page.evaluate("() => {\n" +
" const cookies = document.cookie.split(';');\n" +
@ -198,16 +199,16 @@ public class TestBrowserContextAddCookies extends TestBase {
@Test
void shouldHaveExpiresSetTo1ForSessionCookies() {
context.addCookies(asList(
new BrowserContext.AddCookie("expires", "123456").withUrl(server.EMPTY_PAGE)));
List<BrowserContext.Cookie> cookies = context.cookies();
assertEquals(-1, cookies.get(0).expires());
new Cookie("expires", "123456").withUrl(server.EMPTY_PAGE)));
List<Cookie> cookies = context.cookies();
assertEquals(-1, cookies.get(0).expires);
}
@Test
void shouldSetCookieWithReasonableDefaults() {
context.addCookies(asList(
new BrowserContext.AddCookie("defaults", "123456").withUrl(server.EMPTY_PAGE)));
List<BrowserContext.Cookie> cookies = context.cookies();
new Cookie("defaults", "123456").withUrl(server.EMPTY_PAGE)));
List<Cookie> cookies = context.cookies();
assertJsonEquals("[{\n" +
" name: 'defaults',\n" +
" value: '123456',\n" +
@ -223,10 +224,10 @@ public class TestBrowserContextAddCookies extends TestBase {
@Test
void shouldSetACookieWithAPath() {
page.navigate(server.PREFIX + "/grid.html");
context.addCookies(asList(new BrowserContext.AddCookie("gridcookie", "GRID")
context.addCookies(asList(new Cookie("gridcookie", "GRID")
.withDomain("localhost")
.withPath("/grid.html")));
List<BrowserContext.Cookie> cookies = context.cookies();
List<Cookie> cookies = context.cookies();
assertJsonEquals("[{\n" +
" name: 'gridcookie',\n" +
" value: 'GRID',\n" +
@ -248,8 +249,8 @@ public class TestBrowserContextAddCookies extends TestBase {
void shouldNotSetACookieWithBlankPageURL() {
try {
context.addCookies(asList(
new BrowserContext.AddCookie("example-cookie", "best").withUrl(server.EMPTY_PAGE),
new BrowserContext.AddCookie("example-cookie-blank", "best").withUrl("about:blank")
new Cookie("example-cookie", "best").withUrl(server.EMPTY_PAGE),
new Cookie("example-cookie-blank", "best").withUrl("about:blank")
));
fail("did not throw");
} catch (PlaywrightException e) {
@ -261,7 +262,7 @@ public class TestBrowserContextAddCookies extends TestBase {
void shouldNotSetACookieOnADataURLPage() {
try {
context.addCookies(asList(
new BrowserContext.AddCookie("example-cookie", "best").withUrl("data:,Hello%2C%20World!")
new Cookie("example-cookie", "best").withUrl("data:,Hello%2C%20World!")
));
fail("did not throw");
} catch (PlaywrightException e) {
@ -274,11 +275,11 @@ public class TestBrowserContextAddCookies extends TestBase {
page.navigate(server.EMPTY_PAGE);
String SECURE_URL = "https://example.com";
context.addCookies(asList(
new BrowserContext.AddCookie("foo", "bar").withUrl(SECURE_URL)
new Cookie("foo", "bar").withUrl(SECURE_URL)
));
List<BrowserContext.Cookie> cookies = context.cookies(SECURE_URL);
List<Cookie> cookies = context.cookies(SECURE_URL);
assertEquals(1, cookies.size());
assertTrue(cookies.get(0).secure());
assertTrue(cookies.get(0).secure);
}
@Test
@ -286,18 +287,18 @@ public class TestBrowserContextAddCookies extends TestBase {
page.navigate(server.EMPTY_PAGE);
String HTTP_URL = "http://example.com";
context.addCookies(asList(
new BrowserContext.AddCookie("foo", "bar").withUrl(HTTP_URL)
new Cookie("foo", "bar").withUrl(HTTP_URL)
));
List<BrowserContext.Cookie> cookies = context.cookies(HTTP_URL);
List<Cookie> cookies = context.cookies(HTTP_URL);
assertEquals(1, cookies.size());
assertFalse(cookies.get(0).secure());
assertFalse(cookies.get(0).secure);
}
@Test
void shouldSetACookieOnADifferentDomain() {
page.navigate(server.EMPTY_PAGE);
context.addCookies(asList(
new BrowserContext.AddCookie("example-cookie", "best").withUrl("https://www.example.com")
new Cookie("example-cookie", "best").withUrl("https://www.example.com")
));
assertEquals("", page.evaluate("document.cookie"));
assertJsonEquals("[{\n" +
@ -316,7 +317,7 @@ public class TestBrowserContextAddCookies extends TestBase {
void shouldSetCookiesForAFrame() {
page.navigate(server.EMPTY_PAGE);
context.addCookies(asList(
new BrowserContext.AddCookie("frame-cookie", "value").withUrl(server.PREFIX)
new Cookie("frame-cookie", "value").withUrl(server.PREFIX)
));
page.evaluate("src => {\n" +
" let fulfill;\n" +
@ -345,7 +346,7 @@ public class TestBrowserContextAddCookies extends TestBase {
page.frames().get(1).evaluate("document.cookie = 'username=John Doe'");
page.waitForTimeout(2000);
boolean allowsThirdParty = isChromium() || isFirefox();
List<BrowserContext.Cookie> cookies = context.cookies(server.CROSS_PROCESS_PREFIX + "/grid.html");
List<Cookie> cookies = context.cookies(server.CROSS_PROCESS_PREFIX + "/grid.html");
if (allowsThirdParty) {
assertJsonEquals("[{\n" +
" 'domain': '127.0.0.1',\n" +

View File

@ -16,6 +16,7 @@
package com.microsoft.playwright;
import com.microsoft.playwright.options.Cookie;
import org.junit.jupiter.api.Test;
import static java.util.Arrays.asList;
@ -27,7 +28,7 @@ public class TestBrowserContextClearCookies extends TestBase {
void shouldClearCookies() {
page.navigate(server.EMPTY_PAGE);
context.addCookies(asList(
new BrowserContext.AddCookie("cookie1", "1").withUrl(server.EMPTY_PAGE)));
new Cookie("cookie1", "1").withUrl(server.EMPTY_PAGE)));
assertEquals("cookie1=1", page.evaluate("document.cookie"));
context.clearCookies();
assertEquals(emptyList(), context.cookies());
@ -39,9 +40,9 @@ public class TestBrowserContextClearCookies extends TestBase {
void shouldIsolateCookiesWhenClearing() {
BrowserContext anotherContext = browser.newContext();
context.addCookies(asList(
new BrowserContext.AddCookie("page1cookie", "page1value").withUrl(server.EMPTY_PAGE)));
new Cookie("page1cookie", "page1value").withUrl(server.EMPTY_PAGE)));
anotherContext.addCookies(asList(
new BrowserContext.AddCookie("page2cookie", "page2value").withUrl(server.EMPTY_PAGE)));
new Cookie("page2cookie", "page2value").withUrl(server.EMPTY_PAGE)));
assertEquals(1, (context.cookies()).size());
assertEquals(1, (anotherContext.cookies()).size());

View File

@ -16,6 +16,7 @@
package com.microsoft.playwright;
import com.microsoft.playwright.options.Cookie;
import com.microsoft.playwright.options.SameSiteAttribute;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIf;
@ -38,7 +39,7 @@ public class TestBrowserContextCookies extends TestBase {
" return document.cookie;\n" +
"}");
assertEquals("username=John Doe", documentCookie);
List<BrowserContext.Cookie> cookies = context.cookies();
List<Cookie> cookies = context.cookies();
assertJsonEquals("[{\n" +
" name: 'username',\n" +
" value: 'John Doe',\n" +
@ -63,15 +64,15 @@ public class TestBrowserContextCookies extends TestBase {
" }");
assertEquals("username=John Doe", documentCookie);
int timestamp = (Integer) page.evaluate("+(new Date('1/1/2038'))/1000");
BrowserContext.Cookie cookie = context.cookies().get(0);
assertEquals("username", cookie.name());
assertEquals("John Doe", cookie.value());
assertEquals("localhost", cookie.domain());
assertEquals("/", cookie.path());
assertEquals(timestamp, cookie.expires());
assertEquals(false, cookie.httpOnly());
assertEquals(false, cookie.secure());
assertEquals(SameSiteAttribute.NONE, cookie.sameSite());
Cookie cookie = context.cookies().get(0);
assertEquals("username", cookie.name);
assertEquals("John Doe", cookie.value);
assertEquals("localhost", cookie.domain);
assertEquals("/", cookie.path);
assertEquals(timestamp, cookie.expires);
assertEquals(false, cookie.httpOnly);
assertEquals(false, cookie.secure);
assertEquals(SameSiteAttribute.NONE, cookie.sameSite);
}
@Test
@ -82,9 +83,9 @@ public class TestBrowserContextCookies extends TestBase {
exchange.getResponseBody().close();
});
page.navigate(server.EMPTY_PAGE);
List<BrowserContext.Cookie> cookies = context.cookies();
List<Cookie> cookies = context.cookies();
assertEquals(1, cookies.size());
assertTrue(cookies.get(0).httpOnly());
assertTrue(cookies.get(0).httpOnly);
}
static boolean isWebKitWindows() {
@ -100,9 +101,9 @@ public class TestBrowserContextCookies extends TestBase {
exchange.getResponseBody().close();
});
page.navigate(server.EMPTY_PAGE);
List<BrowserContext.Cookie> cookies = context.cookies();
List<Cookie> cookies = context.cookies();
assertEquals(1, cookies.size());
assertEquals(SameSiteAttribute.STRICT, cookies.get(0).sameSite());
assertEquals(SameSiteAttribute.STRICT, cookies.get(0).sameSite);
}
@Test
@ -114,9 +115,9 @@ public class TestBrowserContextCookies extends TestBase {
exchange.getResponseBody().close();
});
page.navigate(server.EMPTY_PAGE);
List<BrowserContext.Cookie> cookies = context.cookies();
List<Cookie> cookies = context.cookies();
assertEquals(1, cookies.size());
assertEquals(SameSiteAttribute.LAX, cookies.get(0).sameSite());
assertEquals(SameSiteAttribute.LAX, cookies.get(0).sameSite);
}
@Test
@ -127,8 +128,8 @@ public class TestBrowserContextCookies extends TestBase {
" document.cookie = 'password=1234';\n" +
" return document.cookie.split('; ').sort().join('; ');\n" +
"}");
List<BrowserContext.Cookie> cookies = context.cookies();
cookies.sort(Comparator.comparing(BrowserContext.Cookie::name));
List<Cookie> cookies = context.cookies();
cookies.sort(Comparator.comparing(c -> c.name));
assertEquals("password=1234; username=John Doe", documentCookie);
assertJsonEquals("[\n" +
" {\n" +
@ -157,11 +158,11 @@ public class TestBrowserContextCookies extends TestBase {
@Test
void shouldGetCookiesFromMultipleUrls() {
context.addCookies(asList(
new BrowserContext.AddCookie("doggo", "woofs").withUrl("https://foo.com"),
new BrowserContext.AddCookie("catto", "purrs").withUrl("https://bar.com"),
new BrowserContext.AddCookie("birdo", "tweets").withUrl("https://baz.com")));
List<BrowserContext.Cookie> cookies = context.cookies(asList("https://foo.com", "https://baz.com"));
cookies.sort(Comparator.comparing(BrowserContext.Cookie::name));
new Cookie("doggo", "woofs").withUrl("https://foo.com"),
new Cookie("catto", "purrs").withUrl("https://bar.com"),
new Cookie("birdo", "tweets").withUrl("https://baz.com")));
List<Cookie> cookies = context.cookies(asList("https://foo.com", "https://baz.com"));
cookies.sort(Comparator.comparing(c -> c.name));
assertJsonEquals("[{\n" +
" name: 'birdo',\n" +
" value: 'tweets',\n" +

View File

@ -16,6 +16,7 @@
package com.microsoft.playwright;
import com.microsoft.playwright.options.BoundingBox;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIf;
@ -35,7 +36,7 @@ public class TestElementHandleBoundingBox extends TestBase {
page.setViewportSize(500, 500);
page.navigate(server.PREFIX + "/grid.html");
ElementHandle elementHandle = page.querySelector(".box:nth-of-type(13)");
ElementHandle.BoundingBox box = elementHandle.boundingBox();
BoundingBox box = elementHandle.boundingBox();
assertEquals(100, box.x);
assertEquals(50, box.y);
assertEquals(50, box.width);
@ -49,7 +50,7 @@ public class TestElementHandleBoundingBox extends TestBase {
Frame nestedFrame = page.frameByName("dos");
assertNotNull(nestedFrame);
ElementHandle elementHandle = nestedFrame.querySelector("div");
ElementHandle.BoundingBox box = elementHandle.boundingBox();
BoundingBox box = elementHandle.boundingBox();
assertEquals(24, box.x);
assertEquals(224, box.y);
assertEquals(268, box.width);
@ -69,7 +70,7 @@ public class TestElementHandleBoundingBox extends TestBase {
page.setContent("<div style='width: 100px; height: 100px'>hello</div>");
ElementHandle elementHandle = page.querySelector("div");
page.evaluate("element => element.style.height = '200px'", elementHandle);
ElementHandle.BoundingBox box = elementHandle.boundingBox();
BoundingBox box = elementHandle.boundingBox();
assertEquals(box.x, 8);
assertEquals(box.y, 8);
assertEquals(box.width, 100);
@ -82,7 +83,7 @@ public class TestElementHandleBoundingBox extends TestBase {
"<rect id='theRect' x='30' y='50' width='200' height='300'></rect>\n" +
"</svg>");
ElementHandle element = page.querySelector("#therect");
ElementHandle.BoundingBox pwBoundingBox = element.boundingBox();
BoundingBox pwBoundingBox = element.boundingBox();
@SuppressWarnings("unchecked")
Map<String, Integer> webBoundingBox = (Map<String, Integer>) page.evaluate("e => {\n" +
" const rect = e.getBoundingClientRect();\n" +
@ -110,7 +111,7 @@ public class TestElementHandleBoundingBox extends TestBase {
" button.style.marginLeft = '17px';\n" +
" button.style.marginTop = '23px';\n" +
"}");
ElementHandle.BoundingBox box = button.boundingBox();
BoundingBox box = button.boundingBox();
assertEquals(17 * 100, round(box.x * 100));
assertEquals(23 * 100, round(box.y * 100));
assertEquals(200 * 100, round(box.width * 100));
@ -139,7 +140,7 @@ public class TestElementHandleBoundingBox extends TestBase {
"</style>\n" +
"<span><i>woof</i><b>doggo</b></span>");
ElementHandle handle = page.querySelector("span");
ElementHandle.BoundingBox pwBoundingBox = handle.boundingBox();
BoundingBox pwBoundingBox = handle.boundingBox();
@SuppressWarnings("unchecked")
Map<String, Object> webBoundingBox = (Map<String, Object>) handle.evaluate("e => {\n" +
" const rect = e.getBoundingClientRect();\n" +

View File

@ -111,7 +111,7 @@ public class TestGeolocation extends TestBase {
page.navigate(server.EMPTY_PAGE);
List<String> messages = new ArrayList<>();
page.onConsole(message -> messages.add(message.text()));
context.setGeolocation(new Geolocation());
context.setGeolocation(new Geolocation(0, 0));
page.evaluate("() => {\n" +
" navigator.geolocation.watchPosition(pos => {\n" +
" const coords = pos.coords;\n" +

View File

@ -16,6 +16,7 @@
package com.microsoft.playwright;
import com.microsoft.playwright.options.Cookie;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIf;
@ -148,7 +149,7 @@ public class TestPageRoute extends TestBase {
void shouldProperlyReturnNavigationResponseWhenURLHasCookies() {
// Setup cookie.
page.navigate(server.EMPTY_PAGE);
context.addCookies(asList(new BrowserContext.AddCookie("foo", "bar")
context.addCookies(asList(new Cookie("foo", "bar")
.withUrl(server.EMPTY_PAGE)));
// Setup request interception.
page.route("**/*", route -> route.resume());

View File

@ -1 +1 @@
1.9.0-next-1612986115000
1.9.0-next-1612996040000

View File

@ -24,7 +24,6 @@ import com.google.gson.JsonObject;
import java.io.*;
import java.nio.file.FileSystems;
import java.util.*;
import java.util.stream.Collectors;
import static java.util.Arrays.asList;
import static java.util.Collections.reverse;
@ -120,48 +119,6 @@ class TypeRef extends Element {
createCustomType();
}
enum GeneratedType { ENUM, CLASS, OTHER };
private static GeneratedType generatedTypeFor(JsonObject jsonType) {
if (jsonType.has("union")) {
if (!jsonType.get("name").getAsString().isEmpty()) {
return GeneratedType.ENUM;
}
for (JsonElement item : jsonType.getAsJsonArray("union")) {
String valueName = item.getAsJsonObject().get("name").getAsString();
if ("null".equals(valueName)) {
continue;
}
GeneratedType memberType = generatedTypeFor(item.getAsJsonObject());
if (memberType == GeneratedType.ENUM) {
// Nullable enum.
return GeneratedType.ENUM;
}
// If a value is not null and not a string it is a class name.
return GeneratedType.OTHER;
}
throw new RuntimeException("Unknown union type: " + jsonType);
}
switch (jsonType.get("name").getAsString()) {
case "Object": {
String expression = typeExpression(jsonType);
if ("Object<string, string>".equals(expression) || "Object<string, any>".equals(expression)) {
return GeneratedType.OTHER;
}
return GeneratedType.CLASS;
}
case "Array":
case "Promise": {
for (JsonElement item : jsonType.getAsJsonArray("templates")) {
return generatedTypeFor(item.getAsJsonObject());
}
return GeneratedType.OTHER;
}
default:
return GeneratedType.OTHER;
}
}
private static String typeExpression(JsonObject jsonType) {
String typeName = jsonType.get("name").getAsString();
if (jsonType.has("union")) {
@ -200,52 +157,26 @@ class TypeRef extends Element {
}
void createCustomType() {
GeneratedType generatedType = generatedTypeFor(stripNullable());
if (generatedType == GeneratedType.ENUM) {
createEnums(jsonElement.getAsJsonObject());
return;
}
// Use path to the corresponding method, param of field as the key.
String parentPath = parent.jsonPath;
Types.Mapping mapping = TypeDefinition.types.findForPath(parentPath);
if (mapping == null) {
if (generatedType != GeneratedType.CLASS) {
return;
}
if (parent instanceof Field) {
customType = toTitle(parent.jsonName);
} else {
customType = toTitle(parent.parent.jsonName) + toTitle(parent.jsonName);
}
} else {
if (mapping != null) {
String typeExpression = typeExpression(jsonElement.getAsJsonObject());
if (!mapping.from.equals(typeExpression)) {
throw new RuntimeException("Unexpected source type for: " + parentPath +". Expected: " + mapping.from + "; found: " + typeExpression);
}
customType = mapping.to;
if (mapping.customMapping != null) {
mapping.customMapping.defineTypesIn(typeScope());
return;
}
}
if (generatedType == GeneratedType.CLASS) {
if (parent instanceof Field ) {
typeScope().createTopLevelClass(customType, this, jsonElement.getAsJsonObject());
} else {
typeScope().createNestedClass(customType, this, jsonElement.getAsJsonObject());
isNestedClass = true;
}
return;
}
createClassesAndEnums(jsonElement.getAsJsonObject());
}
private void createEnums(JsonObject jsonObject) {
private void createClassesAndEnums(JsonObject jsonObject) {
if (jsonObject.has("union")) {
if (jsonObject.get("name").getAsString().isEmpty()) {
for (JsonElement item : jsonObject.getAsJsonArray("union")) {
if (item.isJsonObject()) {
createEnums(item.getAsJsonObject());
createClassesAndEnums(item.getAsJsonObject());
}
}
} else {
@ -256,9 +187,26 @@ class TypeRef extends Element {
if (jsonObject.has("templates")) {
for (JsonElement item : jsonObject.getAsJsonArray("templates")) {
if (item.isJsonObject()) {
createEnums(item.getAsJsonObject());
createClassesAndEnums(item.getAsJsonObject());
}
}
return;
}
if ("Object".equals(jsonObject.get("name").getAsString())) {
if (customType != null) {
throw new RuntimeException("Custom type has already been created: " + customType);
}
if (parent.jsonName.equals("cookies")) {
customType = "Cookie";
typeScope().createTopLevelClass(customType, this, jsonElement.getAsJsonObject());
} else if (parent instanceof Method || parent instanceof Field || (parent instanceof Param && !"options".equals(parent.jsonName))) {
customType = toTitle(parent.jsonName);
typeScope().createTopLevelClass(customType, this, jsonElement.getAsJsonObject());
} else {
customType = toTitle(parent.parent.jsonName) + toTitle(parent.jsonName);
typeScope().createNestedClass(customType, this, jsonElement.getAsJsonObject());
isNestedClass = true;
}
}
}
@ -269,18 +217,6 @@ class TypeRef extends Element {
if (jsonElement.isJsonNull()) {
return "void";
}
// Convert optional fields to boxed types.
if (!parent.jsonElement.getAsJsonObject().get("required").getAsBoolean()) {
if (jsonName.equals("int")) {
return "Integer";
}
if (jsonName.equals("float")) {
return "Double";
}
if (jsonName.equals("boolean")) {
return "Boolean";
}
}
return convertBuiltinType(stripNullable());
}
@ -525,7 +461,7 @@ class Method extends Element {
"List<Cookie> cookies(List<String> urls);",
});
customSignature.put("BrowserContext.addCookies", new String[]{
"void addCookies(List<AddCookie> cookies);"
"void addCookies(List<Cookie> cookies);"
});
customSignature.put("FileChooser.setFiles", new String[]{
"default void setFiles(Path file) { setFiles(file, null); }",
@ -771,7 +707,7 @@ class Field extends Element {
jsonElement.getAsJsonObject().get("required").getAsBoolean();
}
void writeTo(List<String> output, String offset, String access) {
void writeTo(List<String> output, String offset) {
writeJavadoc(output, offset, comment());
if (asList("Frame.waitForNavigation.options.url",
"Page.waitForNavigation.options.url").contains(jsonPath)) {
@ -789,7 +725,17 @@ class Field extends Element {
if (type.isNullable()) {
typeStr = "Optional<" + typeStr + ">";
}
output.add(offset + access + typeStr + " " + name + ";");
// Convert optional fields to boxed types.
if (!isRequired()) {
if (typeStr.equals("int")) {
typeStr = "Integer";
} else if (typeStr.equals("double")) {
typeStr = "Double";
} else if (typeStr.equals("boolean")) {
typeStr = "Boolean";
}
}
output.add(offset + "public " + typeStr + " " + name + ";");
}
void writeGetter(List<String> output, String offset) {
@ -949,7 +895,7 @@ class Interface extends TypeDefinition {
if ("Playwright".equals(jsonName)) {
output.add("import com.microsoft.playwright.impl.PlaywrightImpl;");
}
if (asList("Page", "Frame", "ElementHandle", "Browser", "BrowserContext", "BrowserType", "Mouse", "Keyboard").contains(jsonName)) {
if (asList("Page", "Request", "Frame", "ElementHandle", "Browser", "BrowserContext", "BrowserType", "Mouse", "Keyboard").contains(jsonName)) {
output.add("import com.microsoft.playwright.options.*;");
}
if (jsonName.equals("Route")) {
@ -1042,13 +988,6 @@ class Interface extends TypeDefinition {
break;
}
case "ElementHandle": {
output.add(offset + "class BoundingBox {");
output.add(offset + " public double x;");
output.add(offset + " public double y;");
output.add(offset + " public double width;");
output.add(offset + " public double height;");
output.add(offset + "}");
output.add("");
output.add(offset + "class SelectOption {");
output.add(offset + " public String value;");
output.add(offset + " public String label;");
@ -1131,22 +1070,17 @@ class NestedClass extends TypeDefinition {
if (asList("RecordHar", "RecordVideo").contains(name)) {
output.add("import java.nio.file.Path;");
}
String access = parent.typeScope() instanceof NestedClass ? "public " : "";
String access = (parent.typeScope() instanceof NestedClass) || topLevelClasses().containsKey(name) ? "public " : "";
output.add(offset + access + "class " + name + " {");
String bodyOffset = offset + " ";
super.writeTo(output, bodyOffset);
boolean isReturnType = parent.parent instanceof Method;
String fieldAccess = isReturnType ? "private " : "public ";
for (Field f : fields) {
f.writeTo(output, bodyOffset, fieldAccess);
f.writeTo(output, bodyOffset);
}
output.add("");
if (isReturnType) {
for (Field f : fields) {
f.writeGetter(output, bodyOffset);
}
} else {
if (!isReturnType) {
writeConstructor(output, bodyOffset);
writeBuilderMethods(output, bodyOffset);
if (asList("Browser.newContext.options",

View File

@ -57,18 +57,12 @@ class Types {
add("Page.addInitScript.script", "Object|function|string", "String");
add("Selectors.register.script", "Object|function|string", "String");
// Return structures
add("ConsoleMessage.location", "Object", "Location");
add("ElementHandle.boundingBox", "Object|null", "BoundingBox", new Empty());
// The method has custom signatures
add("BrowserContext.cookies", "Array<Object>", "Cookie");
add("BrowserContext.cookies.sameSite", "\"Lax\"|\"None\"|\"Strict\"", "SameSite", new Empty());
add("BrowserContext.addCookies.cookies", "Array<Object>", "AddCookie");
add("BrowserContext.addCookies.cookies.sameSite", "\"Lax\"|\"None\"|\"Strict\"", "SameSite", new Empty());
add("BrowserContext.route.url", "RegExp|function(URL):boolean|string", "String");
add("BrowserContext.unroute.url", "RegExp|function(URL):boolean|string", "String");
add("Page.waitForNavigation.options.url", "RegExp|function(URL):boolean|string", "Custom");
add("Page.frame.frameSelector", "Object|string", "Custom", new Empty());
add("Page.frame.options", "Object", "FrameOptions", new Empty());
add("Page.route.url", "RegExp|function(URL):boolean|string", "String");
add("Page.selectOption.values", "Array<ElementHandle>|Array<Object>|Array<string>|ElementHandle|Object|null|string", "String");
@ -84,11 +78,6 @@ class Types {
add("FileChooser.setFiles.files", "Array<Object>|Array<path>|Object|path", "String");
add("Route.resume.options.postData", "Buffer|string", "byte[]", new Empty());
add("BrowserContext.setGeolocation.geolocation", "Object|null", "Geolocation", new Empty());
add("Browser.newContext.options.geolocation", "Object", "Geolocation", new Empty());
add("Browser.newPage.options.geolocation", "Object", "Geolocation", new Empty());
add("BrowserType.launchPersistentContext.options.geolocation", "Object", "Geolocation", new Empty());
// TODO: fix upstream types!
add("Playwright.devices", "Object", "Map<String, DeviceDescriptor>", new Empty());
}