diff --git a/playwright/src/main/java/com/microsoft/playwright/BrowserContext.java b/playwright/src/main/java/com/microsoft/playwright/BrowserContext.java index 7fc534f3..17d1e208 100644 --- a/playwright/src/main/java/com/microsoft/playwright/BrowserContext.java +++ b/playwright/src/main/java/com/microsoft/playwright/BrowserContext.java @@ -130,7 +130,7 @@ public interface BrowserContext { /** * Unix time in seconds. Optional. */ - public Long expires; + public Double expires; /** * Optional. */ @@ -164,7 +164,7 @@ public interface BrowserContext { this.path = path; return this; } - public AddCookie withExpires(Long expires) { + public AddCookie withExpires(double expires) { this.expires = expires; return this; } @@ -189,7 +189,7 @@ public interface BrowserContext { /** * Unix time in seconds. */ - private long expires; + private double expires; private boolean httpOnly; private boolean secure; private SameSite sameSite; @@ -206,7 +206,7 @@ public interface BrowserContext { public String path() { return this.path; } - public long expires() { + public double expires() { return this.expires; } public boolean httpOnly() { diff --git a/playwright/src/main/java/com/microsoft/playwright/Keyboard.java b/playwright/src/main/java/com/microsoft/playwright/Keyboard.java index 52a38511..3ddae906 100644 --- a/playwright/src/main/java/com/microsoft/playwright/Keyboard.java +++ b/playwright/src/main/java/com/microsoft/playwright/Keyboard.java @@ -30,6 +30,28 @@ import java.util.*; public interface Keyboard { enum Modifier { ALT, CONTROL, META, SHIFT } + class PressOptions { + /** + * Time to wait between {@code keydown} and {@code keyup} in milliseconds. Defaults to 0. + */ + public Double delay; + + public PressOptions withDelay(double delay) { + this.delay = delay; + return this; + } + } + class TypeOptions { + /** + * Time to wait between key presses in milliseconds. Defaults to 0. + */ + public Double delay; + + public TypeOptions withDelay(double delay) { + this.delay = delay; + return this; + } + } /** * Dispatches a {@code keydown} event. * @@ -68,7 +90,7 @@ public interface Keyboard { */ void insertText(String text); default void press(String key) { - press(key, 0); + press(key, null); } /** * {@code key} can specify the intended [keyboardEvent.key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) @@ -92,9 +114,9 @@ public interface Keyboard { * * @param key Name of the key to press or a character to generate, such as {@code ArrowLeft} or {@code a}. */ - void press(String key, int delay); + void press(String key, PressOptions delay); default void type(String text) { - type(text, 0); + type(text, null); } /** * Sends a {@code keydown}, {@code keypress}/{@code input}, and {@code keyup} event for each character in the text. @@ -105,7 +127,7 @@ public interface Keyboard { * * @param text A text to type into a focused element. */ - void type(String text, int delay); + void type(String text, TypeOptions delay); /** * Dispatches a {@code keyup} event. * diff --git a/playwright/src/main/java/com/microsoft/playwright/Route.java b/playwright/src/main/java/com/microsoft/playwright/Route.java index e9218d27..473f76f5 100644 --- a/playwright/src/main/java/com/microsoft/playwright/Route.java +++ b/playwright/src/main/java/com/microsoft/playwright/Route.java @@ -86,7 +86,7 @@ public interface Route { /** * Response status code, defaults to {@code 200}. */ - public int status; + public Integer status; public FulfillOptions withBody(byte[] body) { this.bodyBytes = body; diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/KeyboardImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/KeyboardImpl.java index 804d9a79..5a5dc132 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/KeyboardImpl.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/KeyboardImpl.java @@ -19,6 +19,8 @@ package com.microsoft.playwright.impl; import com.google.gson.JsonObject; import com.microsoft.playwright.Keyboard; +import static com.microsoft.playwright.impl.Serialization.gson; + class KeyboardImpl extends LoggingSupport implements Keyboard { private final ChannelOwner page; @@ -45,27 +47,31 @@ class KeyboardImpl extends LoggingSupport implements Keyboard { } @Override - public void press(String key, int delay) { - withLogging("Keyboard.press", () -> { - JsonObject params = new JsonObject(); - params.addProperty("key", key); - if (delay != 0) { - params.addProperty("delay", delay); - } - page.sendMessage("keyboardPress", params); - }); + public void press(String key, PressOptions options) { + withLogging("Keyboard.press", () -> pressImpl(key, options)); } - @Override - public void type(String text, int delay) { - withLogging("Keyboard.type", () -> { - JsonObject params = new JsonObject(); - params.addProperty("text", text); - if (delay != 0) { - params.addProperty("delay", delay); - } - page.sendMessage("keyboardType", params); - }); + private void pressImpl(String key, PressOptions options) { + if (options == null) { + options = new PressOptions(); + } + JsonObject params = gson().toJsonTree(options).getAsJsonObject(); + params.addProperty("key", key); + page.sendMessage("keyboardPress", params); + } + + @Override + public void type(String text, TypeOptions options) { + withLogging("Keyboard.type", () -> typeImpl(text, options)); + } + + private void typeImpl(String text, TypeOptions options) { + if (options == null) { + options = new TypeOptions(); + } + JsonObject params = gson().toJsonTree(options).getAsJsonObject(); + params.addProperty("text", text); + page.sendMessage("keyboardType", params); } @Override diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/RouteImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/RouteImpl.java index e508f9c4..4bfacdd3 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/RouteImpl.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/RouteImpl.java @@ -79,7 +79,7 @@ public class RouteImpl extends ChannelOwner implements Route { options = new FulfillOptions(); } - int status = options.status == 0 ? 200 : options.status; + int status = options.status == null ? 200 : options.status; String body = ""; boolean isBase64 = false; int length = 0; diff --git a/tools/api-generator/src/main/java/com/microsoft/playwright/tools/ApiGenerator.java b/tools/api-generator/src/main/java/com/microsoft/playwright/tools/ApiGenerator.java index a9ba4c6c..113595f0 100644 --- a/tools/api-generator/src/main/java/com/microsoft/playwright/tools/ApiGenerator.java +++ b/tools/api-generator/src/main/java/com/microsoft/playwright/tools/ApiGenerator.java @@ -238,14 +238,25 @@ class TypeRef extends Element { return "Boolean"; } } - if (jsonName.replace("null|", "").contains("|")) { - throw new RuntimeException("Missing mapping for type union: " + jsonPath + ": " + jsonName); + return convertBuiltinType(stripNullable()); + } + + private JsonObject stripNullable() { + JsonObject jsonType = jsonElement.getAsJsonObject(); + if (!"union".equals(jsonType.get("name").getAsString())) { + return jsonType; } -// System.out.println(jsonPath + " : " + jsonName); -// if (jsonName.equals("Promise")) { -// System.out.println(jsonElement); -// } - return convertBuiltinType(jsonElement.getAsJsonObject()); + JsonArray values = jsonType.getAsJsonArray("union"); + if (values.size() != 2) { + throw new RuntimeException("Unexpected union without custom mapping " + jsonPath + ": " + jsonType); + } + for (JsonElement item : values) { + JsonObject o = item.getAsJsonObject(); + if (!"null".equals(o.get("name").getAsString())) { + return o; + } + } + throw new RuntimeException("Unexpected union " + jsonPath + ": " + jsonType); } private static String convertBuiltinType(JsonObject jsonType) { @@ -265,6 +276,15 @@ class TypeRef extends Element { if ("path".equals(name)) { return "Path"; } + if ("EvaluationArgument".equals(name)) { + return "Object"; + } + if ("Serializable".equals(name)) { + return "Object"; + } + if ("Buffer".equals(name)) { + return "byte[]"; + } if ("Array".equals(name)) { return "List<" + convertTemplateParams(jsonType) + ">"; } diff --git a/tools/api-generator/src/main/java/com/microsoft/playwright/tools/Types.java b/tools/api-generator/src/main/java/com/microsoft/playwright/tools/Types.java index f2089d53..58c49a69 100644 --- a/tools/api-generator/src/main/java/com/microsoft/playwright/tools/Types.java +++ b/tools/api-generator/src/main/java/com/microsoft/playwright/tools/Types.java @@ -69,7 +69,7 @@ class Types { add("Page.reload.options.waitUntil", "\"domcontentloaded\"|\"load\"|\"networkidle\"", "Frame.LoadState", new Empty()); add("Page.screenshot.options.type", "\"jpeg\"|\"png\"", "Type"); add("Page.setContent.options.waitUntil", "\"domcontentloaded\"|\"load\"|\"networkidle\"", "Frame.LoadState", new Empty()); - add("Page.waitForFunction.options.polling", "\"raf\"|float", "double", new PollingOption()); + add("Page.waitForFunction.options.polling", "\"raf\"|float", "double", new Empty()); add("Page.waitForNavigation.options.waitUntil", "\"domcontentloaded\"|\"load\"|\"networkidle\"", "Frame.LoadState", new Empty()); add("Page.waitForSelector.options.state", "\"attached\"|\"detached\"|\"hidden\"|\"visible\"", "State"); add("Frame.click.options.button", "\"left\"|\"middle\"|\"right\"", "Mouse.Button", new Empty()); @@ -80,7 +80,7 @@ class Types { add("Frame.goto.options.waitUntil", "\"domcontentloaded\"|\"load\"|\"networkidle\"", "LoadState", new Empty()); add("Frame.hover.options.modifiers", "Array<\"Alt\"|\"Control\"|\"Meta\"|\"Shift\">", "Set", new Empty()); add("Frame.setContent.options.waitUntil", "\"domcontentloaded\"|\"load\"|\"networkidle\"", "LoadState", new Empty()); - add("Frame.waitForFunction.options.polling", "\"raf\"|float", "double", new PollingOption()); + add("Frame.waitForFunction.options.polling", "\"raf\"|float", "double", new Empty()); add("Frame.waitForNavigation.options.waitUntil", "\"domcontentloaded\"|\"load\"|\"networkidle\"", "LoadState", new Empty()); add("Frame.waitForSelector.options.state", "\"attached\"|\"detached\"|\"hidden\"|\"visible\"", "State"); add("ElementHandle.click.options.button", "\"left\"|\"middle\"|\"right\"", "Mouse.Button", new Empty()); @@ -97,32 +97,6 @@ class Types { add("Mouse.up.options.button", "\"left\"|\"middle\"|\"right\"", "Button", new Empty()); add("BrowserType.launchPersistentContext.options.colorScheme", "\"dark\"|\"light\"|\"no-preference\"", "ColorScheme", new Empty()); - // File - add("Page.addScriptTag.options.path", "path", "Path"); - add("Page.addStyleTag.options.path", "path", "Path"); - add("Page.pdf.options.path", "path", "Path"); - add("Page.screenshot.options.path", "path", "Path"); - add("Frame.addScriptTag.options.path", "path", "Path"); - add("Frame.addStyleTag.options.path", "path", "Path"); - add("ElementHandle.screenshot.options.path", "path", "Path"); - add("Route.fulfill.options.path", "path", "Path"); - add("Route.fulfill.options.status", "int", "int"); - add("Browser.newContext.options.recordHar.path", "path", "Path"); - add("Browser.newContext.options.recordVideo.dir", "path", "Path"); - add("Browser.newPage.options.recordHar.path", "path", "Path"); - add("Browser.newPage.options.recordVideo.dir", "path", "Path"); - add("BrowserType.launchPersistentContext.options.recordHar.path", "path", "Path"); - add("BrowserType.launchPersistentContext.options.recordVideo.dir", "path", "Path"); - add("BrowserType.launchPersistentContext.userDataDir", "path", "Path"); - add("BrowserType.launchPersistentContext.options.executablePath", "path", "Path"); - add("BrowserType.launchServer.options.executablePath", "path", "Path"); - add("BrowserType.launchPersistentContext.options.downloadsPath", "path", "Path"); - add("BrowserType.launch.options.executablePath", "path", "Path"); - add("BrowserType.launch.options.downloadsPath", "path", "Path"); - add("BrowserContext.storageState.options.path", "path", "Path"); - add("ChromiumBrowser.startTracing.options.path", "path", "Path"); - add("Video.path", "path", "Path"); - // Route add("BrowserContext.route.handler", "function(Route, Request)", "Consumer"); add("BrowserContext.unroute.handler", "function(Route, Request)", "Consumer"); @@ -147,30 +121,6 @@ class Types { add("BrowserType.launchPersistentContext.options.httpCredentials", "Object", "BrowserContext.HTTPCredentials", new Empty()); add("BrowserContext.setHTTPCredentials.httpCredentials", "Object|null", "do nothing", new Empty()); - // EvaluationArgument - add("Page.$eval.arg", "EvaluationArgument", "Object"); - add("Page.$$eval.arg", "EvaluationArgument", "Object"); - add("Page.dispatchEvent.eventInit", "EvaluationArgument", "Object"); - add("Page.evaluate.arg", "EvaluationArgument", "Object"); - add("Page.evaluateHandle.arg", "EvaluationArgument", "Object"); - add("Page.waitForFunction.arg", "EvaluationArgument", "Object"); - add("Frame.$eval.arg", "EvaluationArgument", "Object"); - add("Frame.$$eval.arg", "EvaluationArgument", "Object"); - add("Frame.dispatchEvent.eventInit", "EvaluationArgument", "Object"); - add("Frame.evaluate.arg", "EvaluationArgument", "Object"); - add("Frame.evaluateHandle.arg", "EvaluationArgument", "Object"); - add("Frame.waitForFunction.arg", "EvaluationArgument", "Object"); - add("ElementHandle.$eval.arg", "EvaluationArgument", "Object"); - add("ElementHandle.$$eval.arg", "EvaluationArgument", "Object"); - add("ElementHandle.dispatchEvent.eventInit", "EvaluationArgument", "Object"); - add("ElementHandle.evaluate.arg", "EvaluationArgument", "Object"); - add("ElementHandle.evaluateHandle.arg", "EvaluationArgument", "Object"); - add("JSHandle.evaluate.arg", "EvaluationArgument", "Object"); - add("JSHandle.evaluateHandle.arg", "EvaluationArgument", "Object"); - add("Worker.evaluate.arg", "EvaluationArgument", "Object"); - add("Worker.evaluateHandle.arg", "EvaluationArgument", "Object"); - - // js functions are always passed as text in java. add("Page.$eval.pageFunction", "function(Element)", "String"); add("Page.$$eval.pageFunction", "function(Array)", "String"); @@ -209,22 +159,6 @@ class Types { add("WebSocket.framereceived", "Object", "FrameData", new Empty()); add("WebSocket.framesent", "Object", "FrameData", new Empty()); - add("Page.waitForRequest", "Request", "Deferred"); - add("Page.waitForResponse", "Response", "Deferred"); - add("Page.waitForNavigation", "Response|null", "Deferred"); - add("Frame.waitForNavigation", "Response|null", "Deferred"); - add("Page.waitForSelector", "ElementHandle|null", "ElementHandle", new Empty()); - add("Frame.waitForSelector", "ElementHandle|null", "ElementHandle", new Empty()); - add("ElementHandle.waitForSelector", "ElementHandle|null", "ElementHandle", new Empty()); - - add("Frame.waitForLoadState", "void", "void", new Empty()); - add("Page.waitForLoadState", "void", "void", new Empty()); - add("Frame.waitForTimeout", "void", "void", new Empty()); - add("Page.waitForTimeout", "void", "void", new Empty()); - add("Frame.waitForFunction", "JSHandle", "JSHandle", new Empty()); - add("Page.waitForFunction", "JSHandle", "JSHandle", new Empty()); - add("ElementHandle.waitForElementState", "void", "void", new Empty()); - // Custom options add("Page.pdf.options.margin.top", "float|string", "String"); add("Page.pdf.options.margin.right", "float|string", "String"); @@ -250,16 +184,11 @@ class Types { // The method has custom signatures add("BrowserContext.cookies", "Array", "Cookie"); add("BrowserContext.cookies.sameSite", "\"Lax\"|\"None\"|\"Strict\"", "SameSite", new Empty()); - add("BrowserContext.cookies.expires", "float", "long"); add("BrowserContext.addCookies.cookies", "Array", "AddCookie"); add("BrowserContext.addCookies.cookies.sameSite", "\"Lax\"|\"None\"|\"Strict\"", "SameSite", new Empty()); - add("BrowserContext.addCookies.cookies.expires", "float", "Long", new Empty()); add("BrowserContext.route.url", "RegExp|function(URL):boolean|string", "String"); add("BrowserContext.unroute.url", "RegExp|function(URL):boolean|string", "String"); add("BrowserContext.storageState", "Object", "StorageState", new Empty()); - add("BrowserContext.waitForEvent.event", "string", "EventType", new Empty()); - add("BrowserContext.waitForEvent.optionsOrPredicate", "Function|Object", "String"); - add("BrowserContext.waitForEvent", "Promise", "Deferred>", new Empty()); add("Page.waitForNavigation.options.url", "RegExp|function(URL):boolean|string", "Custom"); add("Page.waitForNavigation.options", "Object", "WaitForNavigationOptions"); add("Page.waitForRequest.options", "Object", "WaitForRequestOptions"); @@ -269,9 +198,6 @@ class Types { add("Page.selectOption.values", "Array|Array|Array|ElementHandle|Object|null|string", "String"); add("Page.setInputFiles.files", "Array|Array|Object|path", "String"); add("Page.unroute.url", "RegExp|function(URL):boolean|string", "String"); - add("Page.waitForEvent.event", "string", "EventType", new Empty()); - add("Page.waitForEvent.optionsOrPredicate", "Function|Object", "WaitForEventOptions"); - add("Page.waitForEvent", "Promise", "Deferred>", new Empty()); add("Page.waitForRequest.urlOrPredicate", "RegExp|function(Request):boolean|string", "String"); add("Page.waitForResponse.urlOrPredicate", "RegExp|function(Response):boolean|string", "String"); add("Frame.waitForNavigation.options.url", "RegExp|function(URL):boolean|string", "Custom"); @@ -293,73 +219,18 @@ class Types { add("BrowserType.launchServer.options.env", "Object", "Map", new Empty()); add("Logger.log.message", "string|Error", "String"); - add("Browser.newContext.options.geolocation.latitude", "number", "double"); - add("Browser.newContext.options.geolocation.longitude", "number", "double"); - add("Browser.newContext.options.geolocation.accuracy", "number", "double"); - add("Browser.newPage.options.geolocation.latitude", "number", "double"); - add("Browser.newPage.options.geolocation.longitude", "number", "double"); - add("Browser.newPage.options.geolocation.accuracy", "number", "double"); - add("BrowserType.launchPersistentContext.options.geolocation.latitude", "number", "double"); - add("BrowserType.launchPersistentContext.options.geolocation.longitude", "number", "double"); - add("BrowserType.launchPersistentContext.options.geolocation.accuracy", "number", "double"); - add("BrowserContext.setGeolocation.geolocation", "Object|null", "Geolocation", new Empty()); add("Browser.newContext.options.geolocation", "Object", "Geolocation", new Empty()); add("Browser.newContext.options.storageState", "Object|path", "BrowserContext.StorageState", new Empty()); add("Browser.newPage.options.storageState", "Object|path", "BrowserContext.StorageState", new Empty()); add("Browser.newPage.options.geolocation", "Object", "Geolocation", new Empty()); add("BrowserType.launchPersistentContext.options.geolocation", "Object", "Geolocation", new Empty()); - add("Download.saveAs.path", "path", "Path", new Empty()); - add("Download.path", "null|path", "Path", new Empty()); add("Download.createReadStream", "Readable|null", "InputStream", new Empty()); - // Single field options - add("Keyboard.type.options", "Object", "int", new Empty()); - add("Keyboard.press.options", "Object", "int", new Empty()); - // node.js types add("BrowserServer.process", "ChildProcess", "Object"); - add("Page.pdf", "Buffer", "byte[]", new Empty()); - add("Page.screenshot", "Buffer", "byte[]", new Empty()); - add("ElementHandle.screenshot", "Buffer", "byte[]", new Empty()); - add("Request.postDataBuffer", "Buffer|null", "byte[]", new Empty()); - add("Response.body", "Buffer", "byte[]", new Empty()); add("Response.finished", "Error|null", "String"); - add("ChromiumBrowser.stopTracing", "Buffer", "byte[]", new Empty()); - add("WebSocket.framereceived.payload", "Buffer|string", "byte[]", new Empty()); - add("WebSocket.framesent.payload", "Buffer|string", "byte[]", new Empty()); - - add("BrowserContext.browser", "Browser|null", "Browser"); - add("BrowserContext.cookies.urls", "Array|string", "Custom", new Empty()); - add("Page.$", "ElementHandle|null", "ElementHandle"); - add("Page.frame", "Frame|null", "Frame"); - add("Page.frame.frameSelector", "Object|string", "Custom", new Empty()); - add("Page.getAttribute", "null|string", "String", new Empty()); - add("Page.goBack", "Response|null", "Response", new Empty()); - add("Page.goForward", "Response|null", "Response", new Empty()); - add("Page.goto", "Response|null", "Response", new Empty()); - add("Page.opener", "Page|null", "Page", new Empty()); - add("Page.reload", "Response|null", "Response", new Empty()); - add("Page.textContent", "null|string", "String", new Empty()); - add("Page.video", "Video|null", "Video", new Empty()); - add("Frame.$", "ElementHandle|null", "ElementHandle", new Empty()); - add("Frame.getAttribute", "null|string", "String", new Empty()); - add("Frame.goto", "Response|null", "Response", new Empty()); - add("Frame.parentFrame", "Frame|null", "Frame", new Empty()); - add("Frame.textContent", "null|string", "String", new Empty()); - add("ElementHandle.$", "ElementHandle|null", "ElementHandle", new Empty()); - add("ElementHandle.contentFrame", "Frame|null", "Frame", new Empty()); - add("ElementHandle.getAttribute", "null|string", "String", new Empty()); - add("ElementHandle.ownerFrame", "Frame|null", "Frame", new Empty()); - add("ElementHandle.textContent", "null|string", "String", new Empty()); - add("JSHandle.asElement", "ElementHandle|null", "ElementHandle", new Empty()); - add("Download.failure", "null|string", "String", new Empty()); -// add("Request.failure", "Object|null", "Object", new Empty()); - add("Request.postData", "null|string", "String", new Empty()); - add("Request.redirectedFrom", "Request|null", "Request", new Empty()); - add("Request.redirectedTo", "Request|null", "Request", new Empty()); - add("Request.response", "Response|null", "Response", new Empty()); // TODO: fix upstream types! add("Request.headers", "Object", "Map", new Empty()); @@ -372,26 +243,6 @@ class Types { add("Route.continue.options.headers", "Object", "Map", new Empty()); add("Route.fulfill.options.headers", "Object", "Map", new Empty()); add("Playwright.devices", "Object", "Map", new Empty()); - - // JSON type - add("BrowserContext.addInitScript.arg", "Serializable", "Object"); - add("Page.$eval", "Serializable", "Object"); - add("Page.$$eval", "Serializable", "Object"); - add("Page.addInitScript.arg", "Serializable", "Object"); - add("Page.evaluate", "Serializable", "Object"); - add("Frame.$eval", "Serializable", "Object"); - add("Frame.$$eval", "Serializable", "Object"); - add("Frame.evaluate", "Serializable", "Object"); - add("ElementHandle.$eval", "Serializable", "Object"); - add("ElementHandle.$$eval", "Serializable", "Object"); - add("ElementHandle.evaluate", "Serializable", "Object"); - add("ElementHandle.jsonValue", "Serializable", "Object"); - add("JSHandle.evaluate", "Serializable", "Object"); - add("JSHandle.jsonValue", "Serializable", "Object"); - add("Response.json", "Serializable", "Object"); - add("Worker.evaluate", "Serializable", "Object"); - - add("CDPSession.send.params", "Object", "Object", new Empty()); } Mapping findForPath(String jsonPath) { @@ -409,12 +260,6 @@ class Types { jsonPathToMapping.put(jsonPath, new Mapping(fromType, toType, factory)); } - private static class PollingOption implements CustomMapping { - @Override - public void defineTypesIn(TypeDefinition scope) { - } - } - private static class Empty implements CustomMapping { @Override public void defineTypesIn(TypeDefinition scope) {