1
0
mirror of synced 2026-07-07 09:00:02 +00:00

fix: generate waitFor* methods from upstream docs (#260)

This commit is contained in:
Yury Semikhatsky
2021-02-04 22:29:55 -08:00
committed by GitHub
parent 2c9fa04a43
commit 90940b23f3
23 changed files with 519 additions and 465 deletions
@@ -48,7 +48,6 @@ public interface Browser extends AutoCloseable {
void onDisconnected(Consumer<Browser> handler);
void offDisconnected(Consumer<Browser> handler);
class NewContextOptions {
public class Proxy {
/**
@@ -61,17 +61,6 @@ public interface BrowserContext extends AutoCloseable {
void onPage(Consumer<Page> handler);
void offPage(Consumer<Page> handler);
class WaitForPageOptions {
public Double timeout;
public WaitForPageOptions withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
Page waitForPage(Runnable code, WaitForPageOptions options);
default Page waitForPage(Runnable code) { return waitForPage(code, null); }
class AddCookie {
public String name;
public String value;
@@ -214,6 +203,26 @@ public interface BrowserContext extends AutoCloseable {
return this;
}
}
class WaitForPageOptions {
/**
* Receives the {@code Page} object and resolves to truthy value when the waiting should resolve.
*/
public Predicate<Page> predicate;
/**
* Maximum time to wait for in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
* value can be changed by using the [{@code method: BrowserContext.setDefaultTimeout}].
*/
public Double timeout;
public WaitForPageOptions withPredicate(Predicate<Page> predicate) {
this.predicate = predicate;
return this;
}
public WaitForPageOptions withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
/**
* 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}].
@@ -412,5 +421,16 @@ public interface BrowserContext extends AutoCloseable {
* @param handler Optional handler function used to register a routing with [{@code method: BrowserContext.route}].
*/
void unroute(Predicate<String> url, Consumer<Route> handler);
default Page waitForPage(Runnable callback) {
return waitForPage(null, callback);
}
/**
* Performs action and waits for a new {@code Page} to be created in the context. If predicate is provided, it passes {@code Page}
* value into the {@code predicate} function and waits for {@code predicate(event)} to return a truthy value. Will throw an error if
* the context closes before new {@code Page} is created.
*
* @param callback Callback that performs the action triggering the event.
*/
Page waitForPage(WaitForPageOptions options, Runnable callback);
}
@@ -1482,7 +1482,7 @@ public interface Frame {
* - {@code 'networkidle'} - wait until there are no network connections for at least {@code 500} ms.
*/
void waitForLoadState(LoadState state, WaitForLoadStateOptions options);
default Response waitForNavigation(Runnable code) { return waitForNavigation(code, null); }
default Response waitForNavigation(Runnable callback) { return waitForNavigation(null, callback); }
/**
* Waits for the frame navigation and returns the main resource response. In case of multiple redirects, the navigation
* will resolve with the response of the last redirect. In case of navigation to a different anchor or navigation due to
@@ -1494,7 +1494,7 @@ public interface Frame {
* <p> <strong>NOTE:</strong> Usage of the [History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API) to change the URL is
* considered a navigation.
*/
Response waitForNavigation(Runnable code, WaitForNavigationOptions options);
Response waitForNavigation(WaitForNavigationOptions options, Runnable callback);
default ElementHandle waitForSelector(String selector) {
return waitForSelector(selector, null);
}
@@ -132,137 +132,6 @@ public interface Page extends AutoCloseable {
void onWorker(Consumer<Worker> handler);
void offWorker(Consumer<Worker> handler);
class WaitForCloseOptions {
public Double timeout;
public WaitForCloseOptions withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
Page waitForClose(Runnable code, WaitForCloseOptions options);
default Page waitForClose(Runnable code) { return waitForClose(code, null); }
class WaitForConsoleOptions {
public Double timeout;
public WaitForConsoleOptions withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
ConsoleMessage waitForConsole(Runnable code, WaitForConsoleOptions options);
default ConsoleMessage waitForConsole(Runnable code) { return waitForConsole(code, null); }
class WaitForDownloadOptions {
public Double timeout;
public WaitForDownloadOptions withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
Download waitForDownload(Runnable code, WaitForDownloadOptions options);
default Download waitForDownload(Runnable code) { return waitForDownload(code, null); }
class WaitForFileChooserOptions {
public Double timeout;
public WaitForFileChooserOptions withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
FileChooser waitForFileChooser(Runnable code, WaitForFileChooserOptions options);
default FileChooser waitForFileChooser(Runnable code) { return waitForFileChooser(code, null); }
class WaitForFrameAttachedOptions {
public Double timeout;
public WaitForFrameAttachedOptions withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
Frame waitForFrameAttached(Runnable code, WaitForFrameAttachedOptions options);
default Frame waitForFrameAttached(Runnable code) { return waitForFrameAttached(code, null); }
class WaitForFrameDetachedOptions {
public Double timeout;
public WaitForFrameDetachedOptions withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
Frame waitForFrameDetached(Runnable code, WaitForFrameDetachedOptions options);
default Frame waitForFrameDetached(Runnable code) { return waitForFrameDetached(code, null); }
class WaitForFrameNavigatedOptions {
public Double timeout;
public WaitForFrameNavigatedOptions withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
Frame waitForFrameNavigated(Runnable code, WaitForFrameNavigatedOptions options);
default Frame waitForFrameNavigated(Runnable code) { return waitForFrameNavigated(code, null); }
class WaitForPageErrorOptions {
public Double timeout;
public WaitForPageErrorOptions withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
Error waitForPageError(Runnable code, WaitForPageErrorOptions options);
default Error waitForPageError(Runnable code) { return waitForPageError(code, null); }
class WaitForPopupOptions {
public Double timeout;
public WaitForPopupOptions withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
Page waitForPopup(Runnable code, WaitForPopupOptions options);
default Page waitForPopup(Runnable code) { return waitForPopup(code, null); }
class WaitForRequestFailedOptions {
public Double timeout;
public WaitForRequestFailedOptions withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
Request waitForRequestFailed(Runnable code, WaitForRequestFailedOptions options);
default Request waitForRequestFailed(Runnable code) { return waitForRequestFailed(code, null); }
class WaitForRequestFinishedOptions {
public Double timeout;
public WaitForRequestFinishedOptions withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
Request waitForRequestFinished(Runnable code, WaitForRequestFinishedOptions options);
default Request waitForRequestFinished(Runnable code) { return waitForRequestFinished(code, null); }
class WaitForWebSocketOptions {
public Double timeout;
public WaitForWebSocketOptions withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
WebSocket waitForWebSocket(Runnable code, WaitForWebSocketOptions options);
default WebSocket waitForWebSocket(Runnable code) { return waitForWebSocket(code, null); }
class WaitForWorkerOptions {
public Double timeout;
public WaitForWorkerOptions withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
Worker waitForWorker(Runnable code, WaitForWorkerOptions options);
default Worker waitForWorker(Runnable code) { return waitForWorker(code, null); }
class AddScriptTagOptions {
/**
* Raw JavaScript content to be injected into frame.
@@ -1350,6 +1219,78 @@ public interface Page extends AutoCloseable {
return this;
}
}
class WaitForCloseOptions {
/**
* Maximum time to wait for in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
* value can be changed by using the [{@code method: BrowserContext.setDefaultTimeout}].
*/
public Double timeout;
public WaitForCloseOptions withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
class WaitForConsoleMessageOptions {
/**
* Receives the {@code ConsoleMessage} object and resolves to truthy value when the waiting should resolve.
*/
public Predicate<ConsoleMessage> predicate;
/**
* Maximum time to wait for in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
* value can be changed by using the [{@code method: BrowserContext.setDefaultTimeout}].
*/
public Double timeout;
public WaitForConsoleMessageOptions withPredicate(Predicate<ConsoleMessage> predicate) {
this.predicate = predicate;
return this;
}
public WaitForConsoleMessageOptions withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
class WaitForDownloadOptions {
/**
* Receives the {@code Download} object and resolves to truthy value when the waiting should resolve.
*/
public Predicate<Download> predicate;
/**
* Maximum time to wait for in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
* value can be changed by using the [{@code method: BrowserContext.setDefaultTimeout}].
*/
public Double timeout;
public WaitForDownloadOptions withPredicate(Predicate<Download> predicate) {
this.predicate = predicate;
return this;
}
public WaitForDownloadOptions withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
class WaitForFileChooserOptions {
/**
* Receives the {@code FileChooser} object and resolves to truthy value when the waiting should resolve.
*/
public Predicate<FileChooser> predicate;
/**
* Maximum time to wait for in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
* value can be changed by using the [{@code method: BrowserContext.setDefaultTimeout}].
*/
public Double timeout;
public WaitForFileChooserOptions withPredicate(Predicate<FileChooser> predicate) {
this.predicate = predicate;
return this;
}
public WaitForFileChooserOptions withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
class WaitForFunctionOptions {
/**
* If {@code polling} is {@code 'raf'}, then {@code expression} is constantly executed in {@code requestAnimationFrame} callback. If {@code polling} is a
@@ -1432,6 +1373,26 @@ public interface Page extends AutoCloseable {
return this;
}
}
class WaitForPopupOptions {
/**
* Receives the {@code Page} object and resolves to truthy value when the waiting should resolve.
*/
public Predicate<Page> predicate;
/**
* Maximum time to wait for in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
* value can be changed by using the [{@code method: BrowserContext.setDefaultTimeout}].
*/
public Double timeout;
public WaitForPopupOptions withPredicate(Predicate<Page> predicate) {
this.predicate = predicate;
return this;
}
public WaitForPopupOptions withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
class WaitForRequestOptions {
/**
* Maximum wait time in milliseconds, defaults to 30 seconds, pass {@code 0} to disable the timeout. The default value can be
@@ -1483,6 +1444,46 @@ public interface Page extends AutoCloseable {
return this;
}
}
class WaitForWebSocketOptions {
/**
* Receives the {@code WebSocket} object and resolves to truthy value when the waiting should resolve.
*/
public Predicate<WebSocket> predicate;
/**
* Maximum time to wait for in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
* value can be changed by using the [{@code method: BrowserContext.setDefaultTimeout}].
*/
public Double timeout;
public WaitForWebSocketOptions withPredicate(Predicate<WebSocket> predicate) {
this.predicate = predicate;
return this;
}
public WaitForWebSocketOptions withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
class WaitForWorkerOptions {
/**
* Receives the {@code Worker} object and resolves to truthy value when the waiting should resolve.
*/
public Predicate<Worker> predicate;
/**
* Maximum time to wait for in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
* value can be changed by using the [{@code method: BrowserContext.setDefaultTimeout}].
*/
public Double timeout;
public WaitForWorkerOptions withPredicate(Predicate<Worker> predicate) {
this.predicate = predicate;
return this;
}
public WaitForWorkerOptions withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
Accessibility accessibility();
/**
* Adds a script which would be evaluated in one of the following scenarios:
@@ -2348,6 +2349,48 @@ public interface Page extends AutoCloseable {
*/
Video video();
Viewport viewportSize();
default Page waitForClose(Runnable callback) {
return waitForClose(null, callback);
}
/**
* Performs action and waits for the Page to close.
*
* @param callback Callback that performs the action triggering the event.
*/
Page waitForClose(WaitForCloseOptions options, Runnable callback);
default ConsoleMessage waitForConsoleMessage(Runnable callback) {
return waitForConsoleMessage(null, callback);
}
/**
* Performs action and waits for a [ConoleMessage] to be logged by in the page. If predicate is provided, it passes
* {@code ConsoleMessage} value into the {@code predicate} function and waits for {@code predicate(message)} to return a truthy value. Will
* throw an error if the page is closed before the console event is fired.
*
* @param callback Callback that performs the action triggering the event.
*/
ConsoleMessage waitForConsoleMessage(WaitForConsoleMessageOptions options, Runnable callback);
default Download waitForDownload(Runnable callback) {
return waitForDownload(null, callback);
}
/**
* Performs action and waits for a new {@code Download}. If predicate is provided, it passes {@code Download} value into the
* {@code predicate} function and waits for {@code predicate(download)} to return a truthy value. Will throw an error if the page is
* closed before the download event is fired.
*
* @param callback Callback that performs the action triggering the event.
*/
Download waitForDownload(WaitForDownloadOptions options, Runnable callback);
default FileChooser waitForFileChooser(Runnable callback) {
return waitForFileChooser(null, callback);
}
/**
* Performs action and waits for a new {@code FileChooser} to be created. If predicate is provided, it passes {@code FileChooser} value
* into the {@code predicate} function and waits for {@code predicate(fileChooser)} to return a truthy value. Will throw an error if
* the page is closed before the file chooser is opened.
*
* @param callback Callback that performs the action triggering the event.
*/
FileChooser waitForFileChooser(WaitForFileChooserOptions options, Runnable callback);
default JSHandle waitForFunction(String expression, Object arg) {
return waitForFunction(expression, arg, null);
}
@@ -2389,7 +2432,7 @@ public interface Page extends AutoCloseable {
* - {@code 'networkidle'} - wait until there are no network connections for at least {@code 500} ms.
*/
void waitForLoadState(Frame.LoadState state, WaitForLoadStateOptions options);
default Response waitForNavigation(Runnable code) { return waitForNavigation(code, null); }
default Response waitForNavigation(Runnable callback) { return waitForNavigation(null, callback); }
/**
* Waits for the main frame navigation and returns the main resource response. In case of multiple redirects, the
* navigation will resolve with the response of the last redirect. In case of navigation to a different anchor or
@@ -2404,21 +2447,46 @@ public interface Page extends AutoCloseable {
*
* <p> Shortcut for main frame's [{@code method: Frame.waitForNavigation}].
*/
Response waitForNavigation(Runnable code, WaitForNavigationOptions options);
default Request waitForRequest(Runnable code) { return waitForRequest(code, (Predicate<Request>) null, null); }
default Request waitForRequest(Runnable code, String urlGlob) { return waitForRequest(code, urlGlob, null); }
default Request waitForRequest(Runnable code, Pattern urlPattern) { return waitForRequest(code, urlPattern, null); }
default Request waitForRequest(Runnable code, Predicate<Request> predicate) { return waitForRequest(code, predicate, null); }
Request waitForRequest(Runnable code, String urlGlob, WaitForRequestOptions options);
Request waitForRequest(Runnable code, Pattern urlPattern, WaitForRequestOptions options);
Request waitForRequest(Runnable code, Predicate<Request> predicate, WaitForRequestOptions options);
default Response waitForResponse(Runnable code) { return waitForResponse(code, (Predicate<Response>) null, null); }
default Response waitForResponse(Runnable code, String urlGlob) { return waitForResponse(code, urlGlob, null); }
default Response waitForResponse(Runnable code, Pattern urlPattern) { return waitForResponse(code, urlPattern, null); }
default Response waitForResponse(Runnable code, Predicate<Response> predicate) { return waitForResponse(code, predicate, null); }
Response waitForResponse(Runnable code, String urlGlob, WaitForResponseOptions options);
Response waitForResponse(Runnable code, Pattern urlPattern, WaitForResponseOptions options);
Response waitForResponse(Runnable code, Predicate<Response> predicate, WaitForResponseOptions options);
Response waitForNavigation(WaitForNavigationOptions options, Runnable callback);
default Page waitForPopup(Runnable callback) {
return waitForPopup(null, callback);
}
/**
* Performs action and waits for a popup {@code Page}. If predicate is provided, it passes [Popup] value into the {@code predicate}
* function and waits for {@code predicate(page)} to return a truthy value. Will throw an error if the page is closed before the
* popup event is fired.
*
* @param callback Callback that performs the action triggering the event.
*/
Page waitForPopup(WaitForPopupOptions options, Runnable callback);
default Request waitForRequest(Runnable callback) { return waitForRequest((Predicate<Request>) null, null, callback); }
default Request waitForRequest(String urlGlob, Runnable callback) { return waitForRequest(urlGlob, null, callback); }
default Request waitForRequest(Pattern urlPattern, Runnable callback) { return waitForRequest(urlPattern, null, callback); }
default Request waitForRequest(Predicate<Request> predicate, Runnable callback) { return waitForRequest(predicate, null, callback); }
Request waitForRequest(String urlGlob, WaitForRequestOptions options, Runnable callback);
Request waitForRequest(Pattern urlPattern, WaitForRequestOptions options, Runnable callback);
/**
* Waits for the matching request and returns it.
*
*
* @param urlOrPredicate Request URL string, regex or predicate receiving {@code Request} object.
* @param callback Callback that performs the action triggering the event.
*/
Request waitForRequest(Predicate<Request> predicate, WaitForRequestOptions options, Runnable callback);
default Response waitForResponse(Runnable callback) { return waitForResponse((Predicate<Response>) null, null, callback); }
default Response waitForResponse(String urlGlob, Runnable callback) { return waitForResponse(urlGlob, null, callback); }
default Response waitForResponse(Pattern urlPattern, Runnable callback) { return waitForResponse(urlPattern, null, callback); }
default Response waitForResponse(Predicate<Response> predicate, Runnable callback) { return waitForResponse(predicate, null, callback); }
Response waitForResponse(String urlGlob, WaitForResponseOptions options, Runnable callback);
Response waitForResponse(Pattern urlPattern, WaitForResponseOptions options, Runnable callback);
/**
* Returns the matched response.
*
*
* @param urlOrPredicate Request URL string, regex or predicate receiving {@code Response} object.
* @param callback Callback that performs the action triggering the event.
*/
Response waitForResponse(Predicate<Response> predicate, WaitForResponseOptions option, Runnable callbacks);
default ElementHandle waitForSelector(String selector) {
return waitForSelector(selector, null);
}
@@ -2447,6 +2515,28 @@ public interface Page extends AutoCloseable {
* @param timeout A timeout to wait for
*/
void waitForTimeout(double timeout);
default WebSocket waitForWebSocket(Runnable callback) {
return waitForWebSocket(null, callback);
}
/**
* Performs action and waits for a new {@code WebSocket}. If predicate is provided, it passes {@code WebSocket} value into the
* {@code predicate} function and waits for {@code predicate(webSocket)} to return a truthy value. Will throw an error if the page is
* closed before the WebSocket event is fired.
*
* @param callback Callback that performs the action triggering the event.
*/
WebSocket waitForWebSocket(WaitForWebSocketOptions options, Runnable callback);
default Worker waitForWorker(Runnable callback) {
return waitForWorker(null, callback);
}
/**
* Performs action and waits for a new {@code Worker}. If predicate is provided, it passes {@code Worker} value into the {@code predicate}
* function and waits for {@code predicate(worker)} to return a truthy value. Will throw an error if the page is closed before
* the worker event is fired.
*
* @param callback Callback that performs the action triggering the event.
*/
Worker waitForWorker(WaitForWorkerOptions options, Runnable callback);
/**
* This method returns all of the dedicated [WebWorkers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API)
* associated with the page.
@@ -24,55 +24,59 @@ import java.util.function.Predicate;
* The {@code WebSocket} class represents websocket connections in the page.
*/
public interface WebSocket {
interface FrameData {
byte[] body();
String text();
}
void onClose(Consumer<WebSocket> handler);
void offClose(Consumer<WebSocket> handler);
void onFrameReceived(Consumer<FrameData> handler);
void offFrameReceived(Consumer<FrameData> handler);
void onFrameReceived(Consumer<WebSocketFrame> handler);
void offFrameReceived(Consumer<WebSocketFrame> handler);
void onFrameSent(Consumer<FrameData> handler);
void offFrameSent(Consumer<FrameData> handler);
void onFrameSent(Consumer<WebSocketFrame> handler);
void offFrameSent(Consumer<WebSocketFrame> handler);
void onSocketError(Consumer<String> handler);
void offSocketError(Consumer<String> handler);
class WaitForFrameReceivedOptions {
/**
* Receives the {@code WebSocketFrame} object and resolves to truthy value when the waiting should resolve.
*/
public Predicate<WebSocketFrame> predicate;
/**
* Maximum time to wait for in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
* value can be changed by using the [{@code method: BrowserContext.setDefaultTimeout}].
*/
public Double timeout;
public WaitForFrameReceivedOptions withPredicate(Predicate<WebSocketFrame> predicate) {
this.predicate = predicate;
return this;
}
public WaitForFrameReceivedOptions withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
FrameData waitForFrameReceived(Runnable code, WaitForFrameReceivedOptions options);
default FrameData waitForFrameReceived(Runnable code) { return waitForFrameReceived(code, null); }
class WaitForFrameSentOptions {
/**
* Receives the {@code WebSocketFrame} object and resolves to truthy value when the waiting should resolve.
*/
public Predicate<WebSocketFrame> predicate;
/**
* Maximum time to wait for in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
* value can be changed by using the [{@code method: BrowserContext.setDefaultTimeout}].
*/
public Double timeout;
public WaitForFrameSentOptions withPredicate(Predicate<WebSocketFrame> predicate) {
this.predicate = predicate;
return this;
}
public WaitForFrameSentOptions withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
FrameData waitForFrameSent(Runnable code, WaitForFrameSentOptions options);
default FrameData waitForFrameSent(Runnable code) { return waitForFrameSent(code, null); }
class WaitForSocketErrorOptions {
public Double timeout;
public WaitForSocketErrorOptions withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
String waitForSocketError(Runnable code, WaitForSocketErrorOptions options);
default String waitForSocketError(Runnable code) { return waitForSocketError(code, null); }
/**
* Indicates that the web socket has been closed.
*/
@@ -81,5 +85,27 @@ public interface WebSocket {
* Contains the URL of the WebSocket.
*/
String url();
default WebSocketFrame waitForFrameReceived(Runnable callback) {
return waitForFrameReceived(null, callback);
}
/**
* Performs action and waits for a frame to be sent. If predicate is provided, it passes {@code WebSocketFrame} value into the
* {@code predicate} function and waits for {@code predicate(webSocketFrame)} to return a truthy value. Will throw an error if the
* WebSocket or Page is closed before the frame is received.
*
* @param callback Callback that performs the action triggering the event.
*/
WebSocketFrame waitForFrameReceived(WaitForFrameReceivedOptions options, Runnable callback);
default WebSocketFrame waitForFrameSent(Runnable callback) {
return waitForFrameSent(null, callback);
}
/**
* Performs action and waits for a frame to be sent. If predicate is provided, it passes {@code WebSocketFrame} value into the
* {@code predicate} function and waits for {@code predicate(webSocketFrame)} to return a truthy value. Will throw an error if the
* WebSocket or Page is closed before the frame is sent.
*
* @param callback Callback that performs the action triggering the event.
*/
WebSocketFrame waitForFrameSent(WaitForFrameSentOptions options, Runnable callback);
}
@@ -0,0 +1,35 @@
/*
* 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;
import java.util.*;
/**
* The {@code WebSocketFrame} class represents frames sent over {@code WebSocket} connections in the page. Frame payload is returned by
* either [{@code method: WebSocketFrame.text}] or [{@code method: WebSocketFrame.binary}] method depending on the its type.
*/
public interface WebSocketFrame {
/**
* Returns binary payload.
*/
byte[] binary();
/**
* Returns text payload.
*/
String text();
}
@@ -29,17 +29,18 @@ public interface Worker {
void onClose(Consumer<Worker> handler);
void offClose(Consumer<Worker> handler);
class WaitForCloseOptions {
/**
* Maximum time to wait for in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
* value can be changed by using the [{@code method: BrowserContext.setDefaultTimeout}].
*/
public Double timeout;
public WaitForCloseOptions withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
Worker waitForClose(Runnable code, WaitForCloseOptions options);
default Worker waitForClose(Runnable code) { return waitForClose(code, null); }
default Object evaluate(String expression) {
return evaluate(expression, null);
}
@@ -76,5 +77,14 @@ public interface Worker {
*/
JSHandle evaluateHandle(String expression, Object arg);
String url();
default Worker waitForClose(Runnable callback) {
return waitForClose(null, callback);
}
/**
* Performs action and waits for the Worker to close.
*
* @param callback Callback that performs the action triggering the event.
*/
Worker waitForClose(WaitForCloseOptions options, Runnable callback);
}
@@ -86,7 +86,7 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
}
@Override
public Page waitForPage(Runnable code, WaitForPageOptions options) {
public Page waitForPage(WaitForPageOptions options, Runnable code) {
if (options == null) {
options = new WaitForPageOptions();
}
@@ -819,7 +819,7 @@ public class FrameImpl extends ChannelOwner implements Frame {
}
@Override
public Response waitForNavigation(Runnable code, WaitForNavigationOptions options) {
public Response waitForNavigation(WaitForNavigationOptions options, Runnable code) {
return withLogging("Frame.waitForNavigation", () -> waitForNavigationImpl(code, options));
}
@@ -429,7 +429,7 @@ public class PageImpl extends ChannelOwner implements Page {
}
@Override
public Page waitForClose(Runnable code, WaitForCloseOptions options) {
public Page waitForClose(WaitForCloseOptions options, Runnable code) {
if (options == null) {
options = new WaitForCloseOptions();
}
@@ -437,9 +437,9 @@ public class PageImpl extends ChannelOwner implements Page {
}
@Override
public ConsoleMessage waitForConsole(Runnable code, WaitForConsoleOptions options) {
public ConsoleMessage waitForConsoleMessage(WaitForConsoleMessageOptions options, Runnable code) {
if (options == null) {
options = new WaitForConsoleOptions();
options = new WaitForConsoleMessageOptions();
}
return waitForEventWithTimeout(EventType.CONSOLE, code, options.timeout);
}
@@ -453,7 +453,7 @@ public class PageImpl extends ChannelOwner implements Page {
}
@Override
public Download waitForDownload(Runnable code, WaitForDownloadOptions options) {
public Download waitForDownload(WaitForDownloadOptions options, Runnable code) {
if (options == null) {
options = new WaitForDownloadOptions();
}
@@ -461,7 +461,7 @@ public class PageImpl extends ChannelOwner implements Page {
}
@Override
public FileChooser waitForFileChooser(Runnable code, WaitForFileChooserOptions options) {
public FileChooser waitForFileChooser(WaitForFileChooserOptions options, Runnable code) {
// TODO: enable/disable file chooser interception
if (options == null) {
options = new WaitForFileChooserOptions();
@@ -470,39 +470,7 @@ public class PageImpl extends ChannelOwner implements Page {
}
@Override
public Frame waitForFrameAttached(Runnable code, WaitForFrameAttachedOptions options) {
if (options == null) {
options = new WaitForFrameAttachedOptions();
}
return waitForEventWithTimeout(EventType.FRAMEATTACHED, code, options.timeout);
}
@Override
public Frame waitForFrameDetached(Runnable code, WaitForFrameDetachedOptions options) {
if (options == null) {
options = new WaitForFrameDetachedOptions();
}
return waitForEventWithTimeout(EventType.FRAMEDETACHED, code, options.timeout);
}
@Override
public Frame waitForFrameNavigated(Runnable code, WaitForFrameNavigatedOptions options) {
if (options == null) {
options = new WaitForFrameNavigatedOptions();
}
return waitForEventWithTimeout(EventType.FRAMENAVIGATED, code, options.timeout);
}
@Override
public Error waitForPageError(Runnable code, WaitForPageErrorOptions options) {
if (options == null) {
options = new WaitForPageErrorOptions();
}
return waitForEventWithTimeout(EventType.PAGEERROR, code, options.timeout);
}
@Override
public Page waitForPopup(Runnable code, WaitForPopupOptions options) {
public Page waitForPopup(WaitForPopupOptions options, Runnable code) {
if (options == null) {
options = new WaitForPopupOptions();
}
@@ -510,23 +478,7 @@ public class PageImpl extends ChannelOwner implements Page {
}
@Override
public Request waitForRequestFailed(Runnable code, WaitForRequestFailedOptions options) {
if (options == null) {
options = new WaitForRequestFailedOptions();
}
return waitForEventWithTimeout(EventType.REQUESTFAILED, code, options.timeout);
}
@Override
public Request waitForRequestFinished(Runnable code, WaitForRequestFinishedOptions options) {
if (options == null) {
options = new WaitForRequestFinishedOptions();
}
return waitForEventWithTimeout(EventType.REQUESTFINISHED, code, options.timeout);
}
@Override
public WebSocket waitForWebSocket(Runnable code, WaitForWebSocketOptions options) {
public WebSocket waitForWebSocket(WaitForWebSocketOptions options, Runnable code) {
if (options == null) {
options = new WaitForWebSocketOptions();
}
@@ -534,7 +486,7 @@ public class PageImpl extends ChannelOwner implements Page {
}
@Override
public Worker waitForWorker(Runnable code, WaitForWorkerOptions options) {
public Worker waitForWorker(WaitForWorkerOptions options, Runnable code) {
if (options == null) {
options = new WaitForWorkerOptions();
}
@@ -1171,7 +1123,7 @@ public class PageImpl extends ChannelOwner implements Page {
}
@Override
public Response waitForNavigation(Runnable code, WaitForNavigationOptions options) {
public Response waitForNavigation(WaitForNavigationOptions options, Runnable code) {
return withLogging("Page.waitForNavigation", () -> waitForNavigationImpl(code, options));
}
@@ -1258,25 +1210,25 @@ public class PageImpl extends ChannelOwner implements Page {
}
@Override
public Request waitForRequest(Runnable code, String urlGlob, WaitForRequestOptions options) {
return waitForRequest(code, toRequestPredicate(new UrlMatcher(urlGlob)), options);
public Request waitForRequest(String urlGlob, WaitForRequestOptions options, Runnable code) {
return waitForRequest(toRequestPredicate(new UrlMatcher(urlGlob)), options, code);
}
@Override
public Request waitForRequest(Runnable code, Pattern urlPattern, WaitForRequestOptions options) {
return waitForRequest(code, toRequestPredicate(new UrlMatcher(urlPattern)), options);
public Request waitForRequest(Pattern urlPattern, WaitForRequestOptions options, Runnable code) {
return waitForRequest(toRequestPredicate(new UrlMatcher(urlPattern)), options, code);
}
@Override
public Request waitForRequest(Runnable code, Predicate<Request> predicate, WaitForRequestOptions options) {
return withLogging("Page.waitForRequest", () -> waitForRequestImpl(code, predicate, options));
public Request waitForRequest(Predicate<Request> predicate, WaitForRequestOptions options, Runnable code) {
return withLogging("Page.waitForRequest", () -> waitForRequestImpl(predicate, options, code));
}
private static Predicate<Request> toRequestPredicate(UrlMatcher matcher) {
return request -> matcher.test(request.url());
}
private Request waitForRequestImpl(Runnable code, Predicate<Request> predicate, WaitForRequestOptions options) {
private Request waitForRequestImpl(Predicate<Request> predicate, WaitForRequestOptions options, Runnable code) {
if (options == null) {
options = new WaitForRequestOptions();
}
@@ -1289,25 +1241,25 @@ public class PageImpl extends ChannelOwner implements Page {
}
@Override
public Response waitForResponse(Runnable code, String urlGlob, WaitForResponseOptions options) {
return waitForResponse(code, toResponsePredicate(new UrlMatcher(urlGlob)), options);
public Response waitForResponse(String urlGlob, WaitForResponseOptions options, Runnable code) {
return waitForResponse(toResponsePredicate(new UrlMatcher(urlGlob)), options, code);
}
@Override
public Response waitForResponse(Runnable code, Pattern urlPattern, WaitForResponseOptions options) {
return waitForResponse(code, toResponsePredicate(new UrlMatcher(urlPattern)), options);
public Response waitForResponse(Pattern urlPattern, WaitForResponseOptions options, Runnable code) {
return waitForResponse(toResponsePredicate(new UrlMatcher(urlPattern)), options, code);
}
@Override
public Response waitForResponse(Runnable code, Predicate<Response> predicate, WaitForResponseOptions options) {
return withLogging("Page.waitForResponse", () -> waitForResponseImpl(code, predicate, options));
public Response waitForResponse(Predicate<Response> predicate, WaitForResponseOptions options, Runnable code) {
return withLogging("Page.waitForResponse", () -> waitForResponseImpl(predicate, options, code));
}
private static Predicate<Response> toResponsePredicate(UrlMatcher matcher) {
return response -> matcher.test(response.url());
}
private Response waitForResponseImpl(Runnable code, Predicate<Response> predicate, WaitForResponseOptions options) {
private Response waitForResponseImpl(Predicate<Response> predicate, WaitForResponseOptions options, Runnable code) {
if (options == null) {
options = new WaitForResponseOptions();
}
@@ -54,22 +54,22 @@ class WebSocketImpl extends ChannelOwner implements WebSocket {
}
@Override
public void onFrameReceived(Consumer<FrameData> handler) {
public void onFrameReceived(Consumer<WebSocketFrame> handler) {
listeners.add(EventType.FRAMERECEIVED, handler);
}
@Override
public void offFrameReceived(Consumer<FrameData> handler) {
public void offFrameReceived(Consumer<WebSocketFrame> handler) {
listeners.remove(EventType.FRAMERECEIVED, handler);
}
@Override
public void onFrameSent(Consumer<FrameData> handler) {
public void onFrameSent(Consumer<WebSocketFrame> handler) {
listeners.add(EventType.FRAMESENT, handler);
}
@Override
public void offFrameSent(Consumer<FrameData> handler) {
public void offFrameSent(Consumer<WebSocketFrame> handler) {
listeners.remove(EventType.FRAMESENT, handler);
}
@@ -84,7 +84,7 @@ class WebSocketImpl extends ChannelOwner implements WebSocket {
}
@Override
public FrameData waitForFrameReceived(Runnable code, WaitForFrameReceivedOptions options) {
public WebSocketFrame waitForFrameReceived(WaitForFrameReceivedOptions options, Runnable code) {
if (options == null) {
options = new WaitForFrameReceivedOptions();
}
@@ -92,21 +92,13 @@ class WebSocketImpl extends ChannelOwner implements WebSocket {
}
@Override
public FrameData waitForFrameSent(Runnable code, WaitForFrameSentOptions options) {
public WebSocketFrame waitForFrameSent(WaitForFrameSentOptions options, Runnable code) {
if (options == null) {
options = new WaitForFrameSentOptions();
}
return waitForEventWithTimeout(EventType.FRAMESENT, code, options.timeout);
}
@Override
public String waitForSocketError(Runnable code, WaitForSocketErrorOptions options) {
if (options == null) {
options = new WaitForSocketErrorOptions();
}
return waitForEventWithTimeout(EventType.SOCKETERROR, code, options.timeout);
}
@Override
public boolean isClosed() {
return isClosed;
@@ -149,10 +141,10 @@ class WebSocketImpl extends ChannelOwner implements WebSocket {
return runUntil(code, new WaitableRace<>(waitables));
}
private static class FrameDataImpl implements FrameData {
private static class WebSocketFrameImpl implements WebSocketFrame {
private final byte[] bytes;
FrameDataImpl(String payload, boolean isBase64) {
WebSocketFrameImpl(String payload, boolean isBase64) {
if (isBase64) {
bytes = Base64.getDecoder().decode(payload);
} else {
@@ -161,7 +153,7 @@ class WebSocketImpl extends ChannelOwner implements WebSocket {
}
@Override
public byte[] body() {
public byte[] binary() {
return bytes;
}
@@ -175,15 +167,15 @@ class WebSocketImpl extends ChannelOwner implements WebSocket {
void handleEvent(String event, JsonObject parameters) {
switch (event) {
case "frameSent": {
FrameDataImpl frameData = new FrameDataImpl(
WebSocketFrameImpl WebSocketFrame = new WebSocketFrameImpl(
parameters.get("data").getAsString(), parameters.get("opcode").getAsInt() == 2);
listeners.notify(EventType.FRAMESENT, frameData);
listeners.notify(EventType.FRAMESENT, WebSocketFrame);
break;
}
case "frameReceived": {
FrameDataImpl frameData = new FrameDataImpl(
WebSocketFrameImpl WebSocketFrame = new WebSocketFrameImpl(
parameters.get("data").getAsString(), parameters.get("opcode").getAsInt() == 2);
listeners.notify(EventType.FRAMERECEIVED, frameData);
listeners.notify(EventType.FRAMERECEIVED, WebSocketFrame);
break;
}
case "socketError": {
@@ -59,7 +59,7 @@ class WorkerImpl extends ChannelOwner implements Worker {
}
@Override
public Worker waitForClose(Runnable code, WaitForCloseOptions options) {
public Worker waitForClose(WaitForCloseOptions options, Runnable code) {
if (options == null) {
options = new WaitForCloseOptions();
}
@@ -118,24 +118,24 @@ public class TestGeolocation extends TestBase {
" }, err => {});\n" +
"}");
{
ConsoleMessage message = page.waitForConsole(() -> context.setGeolocation(new Geolocation(0, 10)));
ConsoleMessage message = page.waitForConsoleMessage(() -> context.setGeolocation(new Geolocation(0, 10)));
// Location change events come several times so we loop until expected one is received.
while (!message.text().contains("lat=0 lng=10")) {
message = page.waitForConsole(() -> {});
message = page.waitForConsoleMessage(() -> {});
}
assertTrue(message.text().contains("lat=0 lng=10"), message.text());
}
{
ConsoleMessage message = page.waitForConsole(() -> context.setGeolocation(new Geolocation(20, 30)));
ConsoleMessage message = page.waitForConsoleMessage(() -> context.setGeolocation(new Geolocation(20, 30)));
while (!message.text().contains("lat=20 lng=30")) {
message = page.waitForConsole(() -> {});
message = page.waitForConsoleMessage(() -> {});
}
assertTrue(message.text().contains("lat=20 lng=30"), message.text());
}
{
ConsoleMessage message = page.waitForConsole(() -> context.setGeolocation(new Geolocation(40, 50)));
ConsoleMessage message = page.waitForConsoleMessage(() -> context.setGeolocation(new Geolocation(40, 50)));
while (!message.text().contains("lat=40 lng=50")) {
message = page.waitForConsole(() -> {});
message = page.waitForConsoleMessage(() -> {});
}
assertTrue(message.text().contains("lat=40 lng=50"), message.text());
}
@@ -109,7 +109,7 @@ public class TestPageBasic extends TestBase {
try {
newPage.waitForResponse(() -> {
try {
newPage.waitForRequest(() -> newPage.close(), server.EMPTY_PAGE);
newPage.waitForRequest(server.EMPTY_PAGE, () -> newPage.close());
fail("waitForRequest() should throw");
} catch (PlaywrightException e) {
assertTrue(e.getMessage().contains("Page closed"));
@@ -184,12 +184,12 @@ public class TestPageExposeFunction extends TestBase {
}, new Page.ExposeBindingOptions().withHandle(true));
page.navigate(server.EMPTY_PAGE);
page.waitForNavigation(() -> {
page.waitForNavigation(new Page.WaitForNavigationOptions().withWaitUntil(LOAD), () -> {
page.evaluate("async url => {\n" +
" window['logme']({ foo: 42 });\n" +
" window.location.href = url;\n" +
"}", server.PREFIX + "/one-style.html");
}, new Page.WaitForNavigationOptions().withWaitUntil(LOAD));
});
}
@Test
@@ -126,7 +126,7 @@ public class TestPageSetInputFiles extends TestBase {
@Test
void shouldRespectTimeout() {
try {
page.waitForFileChooser(() -> {}, new Page.WaitForFileChooserOptions().withTimeout(1));
page.waitForFileChooser(new Page.WaitForFileChooserOptions().withTimeout(1), () -> {});
fail("did not throw");
} catch (PlaywrightException e) {
assertTrue(e.getMessage().contains("Timeout 1ms exceeded"));
@@ -148,7 +148,7 @@ public class TestPageSetInputFiles extends TestBase {
void shouldPrioritizeExactTimeoutOverDefaultTimeout() {
page.setDefaultTimeout(0);
try {
page.waitForFileChooser(() -> {}, new Page.WaitForFileChooserOptions().withTimeout(1));
page.waitForFileChooser(new Page.WaitForFileChooserOptions().withTimeout(1), () -> {});
fail("did not throw");
} catch (PlaywrightException e) {
assertTrue(e.getMessage().contains("Timeout 1ms exceeded"));
@@ -157,13 +157,13 @@ public class TestPageSetInputFiles extends TestBase {
@Test
void shouldWorkWithNoTimeout() {
FileChooser fileChooser = page.waitForFileChooser(() -> {
FileChooser fileChooser = page.waitForFileChooser(new Page.WaitForFileChooserOptions().withTimeout(0), () -> {
page.evaluate("() => setTimeout(() => {\n" +
" const el = document.createElement('input');\n" +
" el.type = 'file';\n" +
" el.click();\n" +
"}, 50)");
}, new Page.WaitForFileChooserOptions().withTimeout(0));
});
assertNotNull(fileChooser);
}
@@ -41,8 +41,8 @@ public class TestPageWaitForNavigation extends TestBase {
void shouldRespectTimeout() {
try {
page.waitForNavigation(
() -> page.navigate(server.EMPTY_PAGE),
new Page.WaitForNavigationOptions().withUrl("**/frame.html").withTimeout(5000));
new Page.WaitForNavigationOptions().withUrl("**/frame.html").withTimeout(5000),
() -> page.navigate(server.EMPTY_PAGE));
fail("did not throw");
} catch (PlaywrightException e) {
assertTrue(e.getMessage().contains("Timeout 5000ms exceeded"));
@@ -150,26 +150,26 @@ public class TestPageWaitForNavigation extends TestBase {
page.navigate(server.EMPTY_PAGE);
Response response1 = page.waitForNavigation(
() -> page.navigate(server.PREFIX + "/one-style.html"),
new Page.WaitForNavigationOptions().withUrl("**/one-style.html"));
new Page.WaitForNavigationOptions().withUrl("**/one-style.html"),
() -> page.navigate(server.PREFIX + "/one-style.html"));
assertNotNull(response1);
assertEquals(server.PREFIX + "/one-style.html", response1.url());
Response response2 = page.waitForNavigation(
() -> page.navigate(server.PREFIX + "/frame.html"),
new Page.WaitForNavigationOptions().withUrl(Pattern.compile("frame.html$")));
new Page.WaitForNavigationOptions().withUrl(Pattern.compile("frame.html$")),
() -> page.navigate(server.PREFIX + "/frame.html"));
assertNotNull(response2);
assertEquals(server.PREFIX + "/frame.html", response2.url());
Response response3 = page.waitForNavigation(
() -> page.navigate(server.PREFIX + "/frame.html?foo=bar"),
new Page.WaitForNavigationOptions().withUrl(url -> {
try {
return new URL(url).getQuery().contains("foo=bar");
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}));
}),
() -> page.navigate(server.PREFIX + "/frame.html?foo=bar"));
assertNotNull(response3);
assertEquals(server.PREFIX + "/frame.html?foo=bar", response3.url());
}
@@ -177,7 +177,7 @@ public class TestPageWaitForNavigation extends TestBase {
@Test
void shouldWorkWithUrlMatchForSameDocumentNavigations() {
page.navigate(server.EMPTY_PAGE);
Response response = page.waitForNavigation(() -> {
Response response = page.waitForNavigation(new Page.WaitForNavigationOptions().withUrl("**/third.html"), () -> {
page.evaluate("() => {\n" +
" history.pushState({}, '', '/first.html');\n" +
"}");
@@ -187,7 +187,7 @@ public class TestPageWaitForNavigation extends TestBase {
page.evaluate("() => {\n" +
" history.pushState({}, '', '/third.html');\n" +
"}");
}, new Page.WaitForNavigationOptions().withUrl("**/third.html"));
});
assertNull(response);
}
@@ -196,8 +196,8 @@ public class TestPageWaitForNavigation extends TestBase {
page.navigate(server.EMPTY_PAGE);
String url = server.CROSS_PROCESS_PREFIX + "/empty.html";
Response response = page.waitForNavigation(
() -> page.navigate(url),
new Page.WaitForNavigationOptions().withWaitUntil(Frame.LoadState.DOMCONTENTLOADED));
new Page.WaitForNavigationOptions().withWaitUntil(Frame.LoadState.DOMCONTENTLOADED),
() -> page.navigate(url));
assertEquals(url, response.url());
assertEquals(url, page.url());
assertEquals(url, page.evaluate("document.location.href"));
@@ -27,33 +27,33 @@ public class TestPageWaitForRequest extends TestBase {
@Test
void shouldWork() {
page.navigate(server.EMPTY_PAGE);
Request request = page.waitForRequest(() -> {
Request request = page.waitForRequest(server.PREFIX + "/digits/2.png", () -> {
page.evaluate("() => {\n" +
" fetch('/digits/1.png');\n" +
" fetch('/digits/2.png');\n" +
" fetch('/digits/3.png');\n" +
"}");
}, server.PREFIX + "/digits/2.png");
});
assertEquals(server.PREFIX + "/digits/2.png", request.url());
}
@Test
void shouldWorkWithPredicate() {
page.navigate(server.EMPTY_PAGE);
Request request = page.waitForRequest(() -> {
Request request = page.waitForRequest(r -> r.url().equals(server.PREFIX + "/digits/2.png"), () -> {
page.evaluate("() => {\n" +
" fetch('/digits/1.png');\n" +
" fetch('/digits/2.png');\n" +
" fetch('/digits/3.png');\n" +
"}");
}, r -> r.url().equals(server.PREFIX + "/digits/2.png"));
});
assertEquals(server.PREFIX + "/digits/2.png", request.url());
}
@Test
void shouldRespectTimeout() {
try {
page.waitForRequest(() -> {}, url -> false, new Page.WaitForRequestOptions().withTimeout(1));
page.waitForRequest(url -> false, new Page.WaitForRequestOptions().withTimeout(1), () -> {});
fail("did not throw");
} catch (PlaywrightException e) {
assertTrue(e.getMessage().contains("Timeout"), e.getMessage());
@@ -64,7 +64,7 @@ public class TestPageWaitForRequest extends TestBase {
void shouldRespectDefaultTimeout() {
page.setDefaultTimeout(1);
try {
page.waitForRequest(() -> {}, request -> false);
page.waitForRequest(request -> false, () -> {});
fail("did not throw");
} catch (PlaywrightException e) {
assertTrue(e.getMessage().contains("Timeout"), e.getMessage());
@@ -74,26 +74,26 @@ public class TestPageWaitForRequest extends TestBase {
@Test
void shouldWorkWithNoTimeout() {
page.navigate(server.EMPTY_PAGE);
Request request = page.waitForRequest(() -> {
Request request = page.waitForRequest(
server.PREFIX + "/digits/2.png",
new Page.WaitForRequestOptions().withTimeout(0),() -> {
page.evaluate("() => setTimeout(() => {\n" +
" fetch('/digits/1.png');\n" +
" fetch('/digits/2.png');\n" +
" fetch('/digits/3.png');\n" +
"}, 50)");
},
server.PREFIX + "/digits/2.png",
new Page.WaitForRequestOptions().withTimeout(0));
});
assertEquals(server.PREFIX + "/digits/2.png", request.url());
}
@Test
void shouldWorkWithUrlMatch() {
page.navigate(server.EMPTY_PAGE);
Request request = page.waitForRequest(() -> {
Request request = page.waitForRequest(Pattern.compile(".*digits/\\d\\.png"), () -> {
page.evaluate("() => {\n" +
" fetch('/digits/1.png');\n" +
"}");
}, Pattern.compile(".*digits/\\d\\.png"));
});
assertEquals(server.PREFIX + "/digits/1.png", request.url());
}
@@ -24,39 +24,39 @@ public class TestPageWaitForResponse extends TestBase {
@Test
void shouldWork() {
page.navigate(server.EMPTY_PAGE);
Response response = page.waitForResponse(() -> {
Response response = page.waitForResponse(server.PREFIX + "/digits/2.png", () -> {
page.evaluate("() => {\n" +
" fetch('/digits/1.png');\n" +
" fetch('/digits/2.png');\n" +
" fetch('/digits/3.png');\n" +
"}");
}, server.PREFIX + "/digits/2.png");
});
assertEquals(server.PREFIX + "/digits/2.png", response.url());
}
@Test
void shouldRespectTimeout() {
page.navigate(server.EMPTY_PAGE);
Response response = page.waitForResponse(() -> {
Response response = page.waitForResponse(r -> r.url().equals(server.PREFIX + "/digits/2.png"), () -> {
page.evaluate("() => {\n" +
" fetch('/digits/1.png');\n" +
" fetch('/digits/2.png');\n" +
" fetch('/digits/3.png');\n" +
"}");
}, r -> r.url().equals(server.PREFIX + "/digits/2.png"));
});
assertEquals(server.PREFIX + "/digits/2.png", response.url());
}
@Test
void shouldWorkWithPredicate() {
page.navigate(server.EMPTY_PAGE);
Response response = page.waitForResponse(() -> {
Response response = page.waitForResponse(r -> r.url().equals(server.PREFIX + "/digits/2.png"), () -> {
page.evaluate("() => {\n" +
" fetch('/digits/1.png');\n" +
" fetch('/digits/2.png');\n" +
" fetch('/digits/3.png');\n" +
"}");
}, r -> r.url().equals(server.PREFIX + "/digits/2.png"));
});
assertEquals(server.PREFIX + "/digits/2.png", response.url());
}
@@ -64,7 +64,7 @@ public class TestPageWaitForResponse extends TestBase {
void shouldRespectDefaultTimeout() {
page.setDefaultTimeout(1);
try {
page.waitForResponse(() -> {}, response -> false);
page.waitForResponse(response -> false, () -> {});
fail("did not throw");
} catch (PlaywrightException e) {
assertTrue(e.getMessage().contains("Timeout"), e.getMessage());
@@ -74,16 +74,17 @@ public class TestPageWaitForResponse extends TestBase {
@Test
void shouldWorkWithNoTimeout() {
page.navigate(server.EMPTY_PAGE);
Response response = page.waitForResponse(() -> {
Response response = page.waitForResponse(
server.PREFIX + "/digits/2.png",
new Page.WaitForResponseOptions().withTimeout(0),
() -> {
page.evaluate("() => setTimeout(() => {\n" +
" fetch('/digits/1.png');\n" +
" fetch('/digits/2.png');\n" +
" fetch('/digits/3.png');\n" +
"}, 50)");
},
server.PREFIX + "/digits/2.png",
new Page.WaitForResponseOptions().withTimeout(0));
});
assertEquals(server.PREFIX + "/digits/2.png", response.url());
}
}
@@ -144,7 +144,7 @@ public class TestWebSocket extends TestBase {
@Test
void shouldEmitBinaryFrameEvents() {
boolean[] socketClosed = {false};
List<com.microsoft.playwright.WebSocket.FrameData> sent = new ArrayList<>();
List<WebSocketFrame> sent = new ArrayList<>();
page.onWebSocket(ws -> {
ws.onClose(ws1 -> socketClosed[0] = true);
ws.onFrameSent(frameData -> sent.add(frameData));
@@ -163,7 +163,7 @@ public class TestWebSocket extends TestBase {
waitForCondition(socketClosed);
assertEquals("text", sent.get(0).text());
for (int i = 0; i < 5; ++i) {
assertEquals(i, sent.get(1).body()[i]);
assertEquals(i, sent.get(1).binary()[i]);
}
}
@@ -58,14 +58,14 @@ public class TestWorkers extends TestBase {
@Test
void shouldReportConsoleLogs() {
ConsoleMessage message = page.waitForConsole(() -> page.evaluate(
ConsoleMessage message = page.waitForConsoleMessage(() -> page.evaluate(
"() => new Worker(URL.createObjectURL(new Blob(['console.log(1)'], {type: 'application/javascript'})))"));
assertEquals("1", message.text());
}
@Test
void shouldHaveJSHandlesForConsoleLogs() {
ConsoleMessage log = page.waitForConsole(() -> page.evaluate(
ConsoleMessage log = page.waitForConsoleMessage(() -> page.evaluate(
"() => new Worker(URL.createObjectURL(new Blob(['console.log(1,2,3,this)'], {type: 'application/javascript'})))"));
assertEquals("1 2 3 JSHandle@object", log.text());
assertEquals(4, log.args().size());
@@ -133,9 +133,9 @@ public class TestWorkers extends TestBase {
});
assertNotNull(frame[0]);
String url = server.PREFIX + "/one-style.css";
Request request = page.waitForRequest(() -> {
Request request = page.waitForRequest(url, () -> {
worker.evaluate("url => fetch(url).then(response => response.text()).then(console.log)", url);
}, url);
});
assertEquals(url, request.url());
assertEquals(frame[0], request.frame());
}
@@ -145,12 +145,12 @@ public class TestWorkers extends TestBase {
Worker worker = page.waitForWorker(() -> page.navigate(server.PREFIX + "/worker/worker.html"));
String url = server.PREFIX + "/one-style.css";
Request[] request = {null};
Response response = page.waitForResponse(() -> {
request[0] = page.waitForRequest(() -> {
Response response = page.waitForResponse(url, () -> {
request[0] = page.waitForRequest(url, () -> {
worker.evaluate("url => fetch(url).then(response => response.text()).then(console.log)", url);
}, url);
});
assertEquals(url, request[0].url());
}, url);
});
assertEquals(request[0], response.request());
assertTrue(response.ok());
}
@@ -161,14 +161,14 @@ public class TestWorkers extends TestBase {
page.navigate(server.EMPTY_PAGE);
String url = server.PREFIX + "/one-style.css";
Request[] request = {null};
Response response = page.waitForResponse(() -> {
request[0] = page.waitForRequest(() -> {
Response response = page.waitForResponse(url, () -> {
request[0] = page.waitForRequest(url, () -> {
page.evaluate("url => new Worker(URL.createObjectURL(new Blob([`\n" +
" fetch('${url}').then(response => response.text()).then(console.log);\n" +
"`], {type: 'application/javascript'})))", url);
}, url);
});
assertEquals(url, request[0].url());
}, url);
});
assertEquals(request[0], response.request());
assertTrue(response.ok());
}
+1 -1
View File
@@ -1 +1 @@
1.9.0-next-1612463649000
1.9.0-next-1612502114000
@@ -313,7 +313,14 @@ class TypeRef extends Element {
return convertTemplateParams(jsonType);
}
if ("function".equals(name)) {
throw new RuntimeException("Missing mapping for " + jsonType);
if (jsonType.getAsJsonArray("args").size() == 1) {
String paramType = convertBuiltinType(jsonType.getAsJsonArray("args").get(0).getAsJsonObject());
if (jsonType.has("returnType")
&& "bool".equals(jsonType.getAsJsonObject("returnType").get("name").getAsString())) {
return "Predicate<" + paramType + ">";
}
throw new RuntimeException("Missing mapping for " + jsonType);
}
}
return name;
}
@@ -382,33 +389,6 @@ abstract class TypeDefinition extends Element {
}
class Event extends Element {
private static Set<String> waitForEvents = new HashSet<>();
static {
waitForEvents.add("BrowserContext.page");
waitForEvents.add("Page.close");
waitForEvents.add("Page.console");
waitForEvents.add("Page.download");
waitForEvents.add("Page.fileChooser");
waitForEvents.add("Page.frameAttached");
waitForEvents.add("Page.frameDetached");
waitForEvents.add("Page.frameNavigated");
waitForEvents.add("Page.pageError");
waitForEvents.add("Page.popup");
waitForEvents.add("Page.request");
waitForEvents.add("Page.requestFailed");
waitForEvents.add("Page.requestFinished");
waitForEvents.add("Page.response");
waitForEvents.add("Page.webSocket");
waitForEvents.add("Page.worker");
waitForEvents.add("WebSocket.frameReceived");
waitForEvents.add("WebSocket.frameSent");
waitForEvents.add("WebSocket.socketError");
waitForEvents.add("Worker.close");
}
private final TypeRef type;
Event(Element parent, JsonObject jsonElement) {
@@ -418,48 +398,21 @@ class Event extends Element {
void writeListenerMethods(List<String> output, String offset) {
String name = toTitle(jsonName);
String listenerType = "Consumer<" + type.toJava() + ">";
String paramType = type.toJava();
// TODO: fix upstream
if ("FrameData".equals(paramType)) {
paramType = "WebSocketFrame";
}
String listenerType = "Consumer<" + paramType + ">";
output.add(offset + "void on" + name + "(" + listenerType + " handler);");
output.add(offset + "void off" + name + "(" + listenerType + " handler);");
}
void writeWaitForEventIfNeeded(List<String> output, String offset) {
if (!waitForEvents.contains(jsonPath)) {
return;
}
String name = toTitle(jsonName);
String methodName = "waitFor" + name;
// Skip events for which there is waitFor* method in the upstream API, that method will generate the code.
if (Method.waitForMethods.contains(parent.jsonPath + "." + methodName)) {
return;
}
output.add("");
String optionsClass = toTitle(methodName) + "Options";
output.add(offset + "class " + optionsClass + " {");
output.add(offset + " public Double timeout;");
output.add(offset + " public " + optionsClass + " withTimeout(double timeout) {");
output.add(offset + " this.timeout = timeout;");
output.add(offset + " return this;");
output.add(offset + " }");
output.add(offset + "}");
String paramType = jsonPath.equals("Page.close") ? "Page" : type.toJava();
output.add(offset + paramType + " " + methodName + "(Runnable code, " + optionsClass + " options);");
output.add(offset + "default " + paramType + " " + methodName + "(Runnable code) { return " + methodName + "(code, null); }");
}
}
class Method extends Element {
final TypeRef returnType;
final List<Param> params = new ArrayList<>();
static Set<String> waitForMethods = new HashSet<>();
static {
waitForMethods.add("Page.waitForNavigation");
waitForMethods.add("Page.waitForRequest");
waitForMethods.add("Page.waitForResponse");
waitForMethods.add("Frame.waitForNavigation");
}
private static Map<String, String[]> customSignature = new HashMap<>();
static {
customSignature.put("Page.setViewportSize", new String[]{"void setViewportSize(int width, int height);"});
@@ -540,27 +493,27 @@ class Method extends Element {
customSignature.put("Frame.setInputFiles", setInputFilesWithSelector);
customSignature.put("Page.waitForRequest", new String[] {
"default Request waitForRequest(Runnable code) { return waitForRequest(code, (Predicate<Request>) null, null); }",
"default Request waitForRequest(Runnable code, String urlGlob) { return waitForRequest(code, urlGlob, null); }",
"default Request waitForRequest(Runnable code, Pattern urlPattern) { return waitForRequest(code, urlPattern, null); }",
"default Request waitForRequest(Runnable code, Predicate<Request> predicate) { return waitForRequest(code, predicate, null); }",
"Request waitForRequest(Runnable code, String urlGlob, WaitForRequestOptions options);",
"Request waitForRequest(Runnable code, Pattern urlPattern, WaitForRequestOptions options);",
"Request waitForRequest(Runnable code, Predicate<Request> predicate, WaitForRequestOptions options);"
"default Request waitForRequest(Runnable callback) { return waitForRequest((Predicate<Request>) null, null, callback); }",
"default Request waitForRequest(String urlGlob, Runnable callback) { return waitForRequest(urlGlob, null, callback); }",
"default Request waitForRequest(Pattern urlPattern, Runnable callback) { return waitForRequest(urlPattern, null, callback); }",
"default Request waitForRequest(Predicate<Request> predicate, Runnable callback) { return waitForRequest(predicate, null, callback); }",
"Request waitForRequest(String urlGlob, WaitForRequestOptions options, Runnable callback);",
"Request waitForRequest(Pattern urlPattern, WaitForRequestOptions options, Runnable callback);",
"Request waitForRequest(Predicate<Request> predicate, WaitForRequestOptions options, Runnable callback);"
});
customSignature.put("Page.waitForResponse", new String[] {
"default Response waitForResponse(Runnable code) { return waitForResponse(code, (Predicate<Response>) null, null); }",
"default Response waitForResponse(Runnable code, String urlGlob) { return waitForResponse(code, urlGlob, null); }",
"default Response waitForResponse(Runnable code, Pattern urlPattern) { return waitForResponse(code, urlPattern, null); }",
"default Response waitForResponse(Runnable code, Predicate<Response> predicate) { return waitForResponse(code, predicate, null); }",
"Response waitForResponse(Runnable code, String urlGlob, WaitForResponseOptions options);",
"Response waitForResponse(Runnable code, Pattern urlPattern, WaitForResponseOptions options);",
"Response waitForResponse(Runnable code, Predicate<Response> predicate, WaitForResponseOptions options);"
"default Response waitForResponse(Runnable callback) { return waitForResponse((Predicate<Response>) null, null, callback); }",
"default Response waitForResponse(String urlGlob, Runnable callback) { return waitForResponse(urlGlob, null, callback); }",
"default Response waitForResponse(Pattern urlPattern, Runnable callback) { return waitForResponse(urlPattern, null, callback); }",
"default Response waitForResponse(Predicate<Response> predicate, Runnable callback) { return waitForResponse(predicate, null, callback); }",
"Response waitForResponse(String urlGlob, WaitForResponseOptions options, Runnable callback);",
"Response waitForResponse(Pattern urlPattern, WaitForResponseOptions options, Runnable callback);",
"Response waitForResponse(Predicate<Response> predicate, WaitForResponseOptions option, Runnable callbacks);"
});
String[] waitForNavigation = {
"default Response waitForNavigation(Runnable code) { return waitForNavigation(code, null); }",
"Response waitForNavigation(Runnable code, WaitForNavigationOptions options);"
"default Response waitForNavigation(Runnable callback) { return waitForNavigation(null, callback); }",
"Response waitForNavigation(WaitForNavigationOptions options, Runnable callback);"
};
customSignature.put("Frame.waitForNavigation", waitForNavigation);
customSignature.put("Page.waitForNavigation", waitForNavigation);
@@ -621,11 +574,6 @@ class Method extends Element {
});
}
private static Set<String> skipJavadoc = new HashSet<>(asList(
"Page.waitForRequest",
"Page.waitForResponse"
));
Method(TypeDefinition parent, JsonObject jsonElement) {
super(parent, jsonElement);
if (customSignature.containsKey(jsonPath) && customSignature.get(jsonPath).length == 0) {
@@ -665,7 +613,7 @@ class Method extends Element {
for (int i = params.size() - 1; i >= 0; i--) {
Param p = params.get(i);
if (!p.isOptional()) {
break;
continue;
}
writeDefaultOverloadedMethod(i, output, offset);
}
@@ -673,32 +621,28 @@ class Method extends Element {
output.add(offset + toJava());
}
private void writeDefaultOverloadedMethod(int paramCount, List<String> output, String offset) {
StringBuilder paramList = new StringBuilder();
StringBuilder argList = new StringBuilder();
for (int i = 0; i < paramCount; i++) {
private void writeDefaultOverloadedMethod(int firstNullOptional, List<String> output, String offset) {
List<String> paramList = new ArrayList<>();
List<String> argList = new ArrayList<>();
for (int i = 0; i < params.size(); i++) {
Param p = params.get(i);
if (paramList.length() > 0) {
paramList.append(", ");
argList.append(", ");
if (i == firstNullOptional) {
argList.add("int".equals(params.get(firstNullOptional).type.toJava()) ? "0" : "null");
continue;
}
paramList.append(p.toJava());
argList.append(p.jsonName);
if (p.isOptional() && i > firstNullOptional) {
continue;
}
paramList.add(p.toJava());
argList.add(p.jsonName);
}
if (argList.length() > 0) {
argList.append(", ");
}
argList.append("int".equals(params.get(paramCount).type.toJava()) ? "0" : "null");
String returns = returnType.toJava().equals("void") ? "" : "return ";
output.add(offset + "default " + returnType.toJava() + " " + jsonName + "(" + paramList + ") {");
output.add(offset + " " + returns + jsonName + "(" + argList + ");");
output.add(offset + "default " + returnType.toJava() + " " + jsonName + "(" + String.join(", ", paramList) + ") {");
output.add(offset + " " + returns + jsonName + "(" + String.join(", ", argList) + ");");
output.add(offset + "}");
}
private void writeJavadoc(List<String> output, String offset) {
if (skipJavadoc.contains(jsonPath)) {
return;
}
List<String> sections = new ArrayList<>();
sections.add(formattedComment());
boolean hasBlankLine = false;
@@ -708,9 +652,6 @@ class Method extends Element {
if (comment.isEmpty()) {
continue;
}
if (skipJavadoc.contains(p.jsonPath)) {
continue;
}
if (!hasBlankLine) {
sections.add("");
hasBlankLine = true;
@@ -995,10 +936,6 @@ class Interface extends TypeDefinition {
e.writeListenerMethods(output, offset);
}
output.add("");
for (Event e : events) {
e.writeWaitForEventIfNeeded(output, offset);
}
output.add("");
}
private void writeSharedTypes(List<String> output, String offset) {
@@ -1144,14 +1081,6 @@ class Interface extends TypeDefinition {
output.add("");
break;
}
case "WebSocket": {
output.add(offset + "interface FrameData {");
output.add(offset + " byte[] body();");
output.add(offset + " String text();");
output.add(offset + "}");
output.add("");
break;
}
}
}
}