feat: support extra headers in connect and connectOverCDP (#414)

This commit is contained in:
Yury Semikhatsky 2021-04-26 14:30:55 -07:00 committed by GitHub
parent 8ee5b8b436
commit c30e105e36
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 543 additions and 91 deletions

View File

@ -488,6 +488,17 @@ public interface BrowserContext extends AutoCloseable {
* browser.close();
* }</pre>
*
* <p> It is possible to examine the request to decide the route action. For example, mocking all requests that contain some
* post data, and leaving all other requests as is:
* <pre>{@code
* context.route("/api/**", route -> {
* if (route.request().postData().contains("my-string"))
* route.fulfill(new Route.FulfillOptions().setBody("mocked-data"));
* else
* route.resume();
* });
* }</pre>
*
* <p> Page routes (set up with {@link Page#route Page.route()}) take precedence over browser context routes when request
* matches both handlers.
*
@ -521,6 +532,17 @@ public interface BrowserContext extends AutoCloseable {
* browser.close();
* }</pre>
*
* <p> It is possible to examine the request to decide the route action. For example, mocking all requests that contain some
* post data, and leaving all other requests as is:
* <pre>{@code
* context.route("/api/**", route -> {
* if (route.request().postData().contains("my-string"))
* route.fulfill(new Route.FulfillOptions().setBody("mocked-data"));
* else
* route.resume();
* });
* }</pre>
*
* <p> Page routes (set up with {@link Page#route Page.route()}) take precedence over browser context routes when request
* matches both handlers.
*
@ -554,6 +576,17 @@ public interface BrowserContext extends AutoCloseable {
* browser.close();
* }</pre>
*
* <p> It is possible to examine the request to decide the route action. For example, mocking all requests that contain some
* post data, and leaving all other requests as is:
* <pre>{@code
* context.route("/api/**", route -> {
* if (route.request().postData().contains("my-string"))
* route.fulfill(new Route.FulfillOptions().setBody("mocked-data"));
* else
* route.resume();
* });
* }</pre>
*
* <p> Page routes (set up with {@link Page#route Page.route()}) take precedence over browser context routes when request
* matches both handlers.
*

View File

@ -42,6 +42,10 @@ import java.util.*;
*/
public interface BrowserType {
class ConnectOptions {
/**
* Additional HTTP headers to be sent with web socket connect request. Optional.
*/
public Map<String, String> headers;
/**
* Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going on.
* Defaults to 0.
@ -53,6 +57,10 @@ public interface BrowserType {
*/
public Double timeout;
public ConnectOptions setHeaders(Map<String, String> headers) {
this.headers = headers;
return this;
}
public ConnectOptions setSlowMo(double slowMo) {
this.slowMo = slowMo;
return this;
@ -63,6 +71,10 @@ public interface BrowserType {
}
}
class ConnectOverCDPOptions {
/**
* Additional HTTP headers to be sent with connect request. Optional.
*/
public Map<String, String> headers;
/**
* Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going on.
* Defaults to 0.
@ -74,6 +86,10 @@ public interface BrowserType {
*/
public Double timeout;
public ConnectOverCDPOptions setHeaders(Map<String, String> headers) {
this.headers = headers;
return this;
}
public ConnectOverCDPOptions setSlowMo(double slowMo) {
this.slowMo = slowMo;
return this;
@ -253,7 +269,8 @@ public interface BrowserType {
*/
public Boolean bypassCSP;
/**
* Browser distribution channel.
* Browser distribution channel. Read more about using <a
* href="https://playwright.dev/java/docs/browsers/#google-chrome--microsoft-edge">Google Chrome and Microsoft Edge</a>.
*/
public BrowserChannel channel;
/**

View File

@ -71,6 +71,12 @@ public interface ElementHandle extends JSHandle {
* Page.setDefaultTimeout()} methods.
*/
public Double timeout;
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public Boolean trial;
public CheckOptions setForce(boolean force) {
this.force = force;
@ -91,6 +97,10 @@ public interface ElementHandle extends JSHandle {
this.timeout = timeout;
return this;
}
public CheckOptions setTrial(boolean trial) {
this.trial = trial;
return this;
}
}
class ClickOptions {
/**
@ -132,6 +142,12 @@ public interface ElementHandle extends JSHandle {
* Page.setDefaultTimeout()} methods.
*/
public Double timeout;
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public Boolean trial;
public ClickOptions setButton(MouseButton button) {
this.button = button;
@ -168,6 +184,10 @@ public interface ElementHandle extends JSHandle {
this.timeout = timeout;
return this;
}
public ClickOptions setTrial(boolean trial) {
this.trial = trial;
return this;
}
}
class DblclickOptions {
/**
@ -205,6 +225,12 @@ public interface ElementHandle extends JSHandle {
* Page.setDefaultTimeout()} methods.
*/
public Double timeout;
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public Boolean trial;
public DblclickOptions setButton(MouseButton button) {
this.button = button;
@ -237,6 +263,10 @@ public interface ElementHandle extends JSHandle {
this.timeout = timeout;
return this;
}
public DblclickOptions setTrial(boolean trial) {
this.trial = trial;
return this;
}
}
class FillOptions {
/**
@ -283,6 +313,12 @@ public interface ElementHandle extends JSHandle {
* Page.setDefaultTimeout()} methods.
*/
public Double timeout;
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public Boolean trial;
public HoverOptions setForce(boolean force) {
this.force = force;
@ -303,6 +339,10 @@ public interface ElementHandle extends JSHandle {
this.timeout = timeout;
return this;
}
public HoverOptions setTrial(boolean trial) {
this.trial = trial;
return this;
}
}
class PressOptions {
/**
@ -483,6 +523,12 @@ public interface ElementHandle extends JSHandle {
* Page.setDefaultTimeout()} methods.
*/
public Double timeout;
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public Boolean trial;
public TapOptions setForce(boolean force) {
this.force = force;
@ -507,6 +553,10 @@ public interface ElementHandle extends JSHandle {
this.timeout = timeout;
return this;
}
public TapOptions setTrial(boolean trial) {
this.trial = trial;
return this;
}
}
class TypeOptions {
/**
@ -562,6 +612,12 @@ public interface ElementHandle extends JSHandle {
* Page.setDefaultTimeout()} methods.
*/
public Double timeout;
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public Boolean trial;
public UncheckOptions setForce(boolean force) {
this.force = force;
@ -582,6 +638,10 @@ public interface ElementHandle extends JSHandle {
this.timeout = timeout;
return this;
}
public UncheckOptions setTrial(boolean trial) {
this.trial = trial;
return this;
}
}
class WaitForElementStateOptions {
/**

View File

@ -148,6 +148,12 @@ public interface Frame {
* Page.setDefaultTimeout()} methods.
*/
public Double timeout;
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public Boolean trial;
public CheckOptions setForce(boolean force) {
this.force = force;
@ -168,6 +174,10 @@ public interface Frame {
this.timeout = timeout;
return this;
}
public CheckOptions setTrial(boolean trial) {
this.trial = trial;
return this;
}
}
class ClickOptions {
/**
@ -209,6 +219,12 @@ public interface Frame {
* Page.setDefaultTimeout()} methods.
*/
public Double timeout;
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public Boolean trial;
public ClickOptions setButton(MouseButton button) {
this.button = button;
@ -245,6 +261,10 @@ public interface Frame {
this.timeout = timeout;
return this;
}
public ClickOptions setTrial(boolean trial) {
this.trial = trial;
return this;
}
}
class DblclickOptions {
/**
@ -282,6 +302,12 @@ public interface Frame {
* Page.setDefaultTimeout()} methods.
*/
public Double timeout;
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public Boolean trial;
public DblclickOptions setButton(MouseButton button) {
this.button = button;
@ -314,6 +340,10 @@ public interface Frame {
this.timeout = timeout;
return this;
}
public DblclickOptions setTrial(boolean trial) {
this.trial = trial;
return this;
}
}
class DispatchEventOptions {
/**
@ -435,6 +465,12 @@ public interface Frame {
* Page.setDefaultTimeout()} methods.
*/
public Double timeout;
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public Boolean trial;
public HoverOptions setForce(boolean force) {
this.force = force;
@ -455,6 +491,10 @@ public interface Frame {
this.timeout = timeout;
return this;
}
public HoverOptions setTrial(boolean trial) {
this.trial = trial;
return this;
}
}
class InnerHTMLOptions {
/**
@ -692,6 +732,12 @@ public interface Frame {
* Page.setDefaultTimeout()} methods.
*/
public Double timeout;
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public Boolean trial;
public TapOptions setForce(boolean force) {
this.force = force;
@ -716,6 +762,10 @@ public interface Frame {
this.timeout = timeout;
return this;
}
public TapOptions setTrial(boolean trial) {
this.trial = trial;
return this;
}
}
class TextContentOptions {
/**
@ -784,6 +834,12 @@ public interface Frame {
* Page.setDefaultTimeout()} methods.
*/
public Double timeout;
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public Boolean trial;
public UncheckOptions setForce(boolean force) {
this.force = force;
@ -804,6 +860,10 @@ public interface Frame {
this.timeout = timeout;
return this;
}
public UncheckOptions setTrial(boolean trial) {
this.trial = trial;
return this;
}
}
class WaitForFunctionOptions {
/**

View File

@ -393,6 +393,12 @@ public interface Page extends AutoCloseable {
* Page.setDefaultTimeout()} methods.
*/
public Double timeout;
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public Boolean trial;
public CheckOptions setForce(boolean force) {
this.force = force;
@ -413,6 +419,10 @@ public interface Page extends AutoCloseable {
this.timeout = timeout;
return this;
}
public CheckOptions setTrial(boolean trial) {
this.trial = trial;
return this;
}
}
class ClickOptions {
/**
@ -454,6 +464,12 @@ public interface Page extends AutoCloseable {
* Page.setDefaultTimeout()} methods.
*/
public Double timeout;
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public Boolean trial;
public ClickOptions setButton(MouseButton button) {
this.button = button;
@ -490,6 +506,10 @@ public interface Page extends AutoCloseable {
this.timeout = timeout;
return this;
}
public ClickOptions setTrial(boolean trial) {
this.trial = trial;
return this;
}
}
class CloseOptions {
/**
@ -539,6 +559,12 @@ public interface Page extends AutoCloseable {
* Page.setDefaultTimeout()} methods.
*/
public Double timeout;
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public Boolean trial;
public DblclickOptions setButton(MouseButton button) {
this.button = button;
@ -571,6 +597,10 @@ public interface Page extends AutoCloseable {
this.timeout = timeout;
return this;
}
public DblclickOptions setTrial(boolean trial) {
this.trial = trial;
return this;
}
}
class DispatchEventOptions {
/**
@ -779,6 +809,12 @@ public interface Page extends AutoCloseable {
* Page.setDefaultTimeout()} methods.
*/
public Double timeout;
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public Boolean trial;
public HoverOptions setForce(boolean force) {
this.force = force;
@ -799,6 +835,10 @@ public interface Page extends AutoCloseable {
this.timeout = timeout;
return this;
}
public HoverOptions setTrial(boolean trial) {
this.trial = trial;
return this;
}
}
class InnerHTMLOptions {
/**
@ -1248,6 +1288,12 @@ public interface Page extends AutoCloseable {
* Page.setDefaultTimeout()} methods.
*/
public Double timeout;
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public Boolean trial;
public TapOptions setForce(boolean force) {
this.force = force;
@ -1272,6 +1318,10 @@ public interface Page extends AutoCloseable {
this.timeout = timeout;
return this;
}
public TapOptions setTrial(boolean trial) {
this.trial = trial;
return this;
}
}
class TextContentOptions {
/**
@ -1340,6 +1390,12 @@ public interface Page extends AutoCloseable {
* Page.setDefaultTimeout()} methods.
*/
public Double timeout;
/**
* When set, this method only performs the <a href="https://playwright.dev/java/docs/actionability/">actionability</a>
* checks and skips the action. Defaults to {@code false}. Useful to wait until the element is ready for the action without
* performing it.
*/
public Boolean trial;
public UncheckOptions setForce(boolean force) {
this.force = force;
@ -1360,6 +1416,10 @@ public interface Page extends AutoCloseable {
this.timeout = timeout;
return this;
}
public UncheckOptions setTrial(boolean trial) {
this.trial = trial;
return this;
}
}
class WaitForCloseOptions {
/**
@ -3127,6 +3187,17 @@ public interface Page extends AutoCloseable {
* browser.close();
* }</pre>
*
* <p> It is possible to examine the request to decide the route action. For example, mocking all requests that contain some
* post data, and leaving all other requests as is:
* <pre>{@code
* page.route("/api/**", route -> {
* if (route.request().postData().contains("my-string"))
* route.fulfill(new Route.FulfillOptions().setBody("mocked-data"));
* else
* route.resume();
* });
* }</pre>
*
* <p> Page routes take precedence over browser context routes (set up with {@link BrowserContext#route
* BrowserContext.route()}) when request matches both handlers.
*
@ -3161,6 +3232,17 @@ public interface Page extends AutoCloseable {
* browser.close();
* }</pre>
*
* <p> It is possible to examine the request to decide the route action. For example, mocking all requests that contain some
* post data, and leaving all other requests as is:
* <pre>{@code
* page.route("/api/**", route -> {
* if (route.request().postData().contains("my-string"))
* route.fulfill(new Route.FulfillOptions().setBody("mocked-data"));
* else
* route.resume();
* });
* }</pre>
*
* <p> Page routes take precedence over browser context routes (set up with {@link BrowserContext#route
* BrowserContext.route()}) when request matches both handlers.
*
@ -3195,6 +3277,17 @@ public interface Page extends AutoCloseable {
* browser.close();
* }</pre>
*
* <p> It is possible to examine the request to decide the route action. For example, mocking all requests that contain some
* post data, and leaving all other requests as is:
* <pre>{@code
* page.route("/api/**", route -> {
* if (route.request().postData().contains("my-string"))
* route.fulfill(new Route.FulfillOptions().setBody("mocked-data"));
* else
* route.resume();
* });
* }</pre>
*
* <p> Page routes take precedence over browser context routes (set up with {@link BrowserContext#route
* BrowserContext.route()}) when request matches both handlers.
*
@ -4224,12 +4317,20 @@ public interface Page extends AutoCloseable {
*/
Page waitForPopup(WaitForPopupOptions options, Runnable callback);
/**
* Waits for the matching request and returns it.
* Waits for the matching request and returns it. See <a
* href="https://playwright.dev/java/docs/events/#waiting-for-event">waiting for event</a> for more details about events.
* <pre>{@code
* Request firstRequest = page.waitForRequest("http://example.com/resource");
* Object finalRequest = page.waitForRequest(
* request -> "http://example.com".equals(request.url()) && "GET".equals(request.method()), () -> {});
* return firstRequest.url();
* // Waits for the next response with the specified url
* Request request = page.waitForRequest("https://example.com/resource", () -> {
* // Triggers the request
* page.click("button.triggers-request");
* });
*
* // Waits for the next request matching some conditions
* Request request = page.waitForRequest(request -> "https://example.com".equals(request.url()) && "GET".equals(request.method()), () -> {
* // Triggers the request
* page.click("button.triggers-request");
* });
* }</pre>
*
* @param urlOrPredicate Request URL string, regex or predicate receiving {@code Request} object.
@ -4239,12 +4340,20 @@ public interface Page extends AutoCloseable {
return waitForRequest(urlOrPredicate, null, callback);
}
/**
* Waits for the matching request and returns it.
* Waits for the matching request and returns it. See <a
* href="https://playwright.dev/java/docs/events/#waiting-for-event">waiting for event</a> for more details about events.
* <pre>{@code
* Request firstRequest = page.waitForRequest("http://example.com/resource");
* Object finalRequest = page.waitForRequest(
* request -> "http://example.com".equals(request.url()) && "GET".equals(request.method()), () -> {});
* return firstRequest.url();
* // Waits for the next response with the specified url
* Request request = page.waitForRequest("https://example.com/resource", () -> {
* // Triggers the request
* page.click("button.triggers-request");
* });
*
* // Waits for the next request matching some conditions
* Request request = page.waitForRequest(request -> "https://example.com".equals(request.url()) && "GET".equals(request.method()), () -> {
* // Triggers the request
* page.click("button.triggers-request");
* });
* }</pre>
*
* @param urlOrPredicate Request URL string, regex or predicate receiving {@code Request} object.
@ -4252,12 +4361,20 @@ public interface Page extends AutoCloseable {
*/
Request waitForRequest(String urlOrPredicate, WaitForRequestOptions options, Runnable callback);
/**
* Waits for the matching request and returns it.
* Waits for the matching request and returns it. See <a
* href="https://playwright.dev/java/docs/events/#waiting-for-event">waiting for event</a> for more details about events.
* <pre>{@code
* Request firstRequest = page.waitForRequest("http://example.com/resource");
* Object finalRequest = page.waitForRequest(
* request -> "http://example.com".equals(request.url()) && "GET".equals(request.method()), () -> {});
* return firstRequest.url();
* // Waits for the next response with the specified url
* Request request = page.waitForRequest("https://example.com/resource", () -> {
* // Triggers the request
* page.click("button.triggers-request");
* });
*
* // Waits for the next request matching some conditions
* Request request = page.waitForRequest(request -> "https://example.com".equals(request.url()) && "GET".equals(request.method()), () -> {
* // Triggers the request
* page.click("button.triggers-request");
* });
* }</pre>
*
* @param urlOrPredicate Request URL string, regex or predicate receiving {@code Request} object.
@ -4267,12 +4384,20 @@ public interface Page extends AutoCloseable {
return waitForRequest(urlOrPredicate, null, callback);
}
/**
* Waits for the matching request and returns it.
* Waits for the matching request and returns it. See <a
* href="https://playwright.dev/java/docs/events/#waiting-for-event">waiting for event</a> for more details about events.
* <pre>{@code
* Request firstRequest = page.waitForRequest("http://example.com/resource");
* Object finalRequest = page.waitForRequest(
* request -> "http://example.com".equals(request.url()) && "GET".equals(request.method()), () -> {});
* return firstRequest.url();
* // Waits for the next response with the specified url
* Request request = page.waitForRequest("https://example.com/resource", () -> {
* // Triggers the request
* page.click("button.triggers-request");
* });
*
* // Waits for the next request matching some conditions
* Request request = page.waitForRequest(request -> "https://example.com".equals(request.url()) && "GET".equals(request.method()), () -> {
* // Triggers the request
* page.click("button.triggers-request");
* });
* }</pre>
*
* @param urlOrPredicate Request URL string, regex or predicate receiving {@code Request} object.
@ -4280,12 +4405,20 @@ public interface Page extends AutoCloseable {
*/
Request waitForRequest(Pattern urlOrPredicate, WaitForRequestOptions options, Runnable callback);
/**
* Waits for the matching request and returns it.
* Waits for the matching request and returns it. See <a
* href="https://playwright.dev/java/docs/events/#waiting-for-event">waiting for event</a> for more details about events.
* <pre>{@code
* Request firstRequest = page.waitForRequest("http://example.com/resource");
* Object finalRequest = page.waitForRequest(
* request -> "http://example.com".equals(request.url()) && "GET".equals(request.method()), () -> {});
* return firstRequest.url();
* // Waits for the next response with the specified url
* Request request = page.waitForRequest("https://example.com/resource", () -> {
* // Triggers the request
* page.click("button.triggers-request");
* });
*
* // Waits for the next request matching some conditions
* Request request = page.waitForRequest(request -> "https://example.com".equals(request.url()) && "GET".equals(request.method()), () -> {
* // Triggers the request
* page.click("button.triggers-request");
* });
* }</pre>
*
* @param urlOrPredicate Request URL string, regex or predicate receiving {@code Request} object.
@ -4295,12 +4428,20 @@ public interface Page extends AutoCloseable {
return waitForRequest(urlOrPredicate, null, callback);
}
/**
* Waits for the matching request and returns it.
* Waits for the matching request and returns it. See <a
* href="https://playwright.dev/java/docs/events/#waiting-for-event">waiting for event</a> for more details about events.
* <pre>{@code
* Request firstRequest = page.waitForRequest("http://example.com/resource");
* Object finalRequest = page.waitForRequest(
* request -> "http://example.com".equals(request.url()) && "GET".equals(request.method()), () -> {});
* return firstRequest.url();
* // Waits for the next response with the specified url
* Request request = page.waitForRequest("https://example.com/resource", () -> {
* // Triggers the request
* page.click("button.triggers-request");
* });
*
* // Waits for the next request matching some conditions
* Request request = page.waitForRequest(request -> "https://example.com".equals(request.url()) && "GET".equals(request.method()), () -> {
* // Triggers the request
* page.click("button.triggers-request");
* });
* }</pre>
*
* @param urlOrPredicate Request URL string, regex or predicate receiving {@code Request} object.
@ -4308,11 +4449,20 @@ public interface Page extends AutoCloseable {
*/
Request waitForRequest(Predicate<Request> urlOrPredicate, WaitForRequestOptions options, Runnable callback);
/**
* Returns the matched response.
* Returns the matched response. See <a href="https://playwright.dev/java/docs/events/#waiting-for-event">waiting for
* event</a> for more details about events.
* <pre>{@code
* Response firstResponse = page.waitForResponse("https://example.com/resource", () -> {});
* Response finalResponse = page.waitForResponse(response -> "https://example.com".equals(response.url()) && response.status() == 200, () -> {});
* return finalResponse.ok();
* // Waits for the next response with the specified url
* Response response = page.waitForResponse("https://example.com/resource", () -> {
* // Triggers the response
* page.click("button.triggers-response");
* });
*
* // Waits for the next response matching some conditions
* Response response = page.waitForResponse(response -> "https://example.com".equals(response.url()) && response.status() == 200, () -> {
* // Triggers the response
* page.click("button.triggers-response");
* });
* }</pre>
*
* @param urlOrPredicate Request URL string, regex or predicate receiving {@code Response} object.
@ -4322,11 +4472,20 @@ public interface Page extends AutoCloseable {
return waitForResponse(urlOrPredicate, null, callback);
}
/**
* Returns the matched response.
* Returns the matched response. See <a href="https://playwright.dev/java/docs/events/#waiting-for-event">waiting for
* event</a> for more details about events.
* <pre>{@code
* Response firstResponse = page.waitForResponse("https://example.com/resource", () -> {});
* Response finalResponse = page.waitForResponse(response -> "https://example.com".equals(response.url()) && response.status() == 200, () -> {});
* return finalResponse.ok();
* // Waits for the next response with the specified url
* Response response = page.waitForResponse("https://example.com/resource", () -> {
* // Triggers the response
* page.click("button.triggers-response");
* });
*
* // Waits for the next response matching some conditions
* Response response = page.waitForResponse(response -> "https://example.com".equals(response.url()) && response.status() == 200, () -> {
* // Triggers the response
* page.click("button.triggers-response");
* });
* }</pre>
*
* @param urlOrPredicate Request URL string, regex or predicate receiving {@code Response} object.
@ -4334,11 +4493,20 @@ public interface Page extends AutoCloseable {
*/
Response waitForResponse(String urlOrPredicate, WaitForResponseOptions options, Runnable callback);
/**
* Returns the matched response.
* Returns the matched response. See <a href="https://playwright.dev/java/docs/events/#waiting-for-event">waiting for
* event</a> for more details about events.
* <pre>{@code
* Response firstResponse = page.waitForResponse("https://example.com/resource", () -> {});
* Response finalResponse = page.waitForResponse(response -> "https://example.com".equals(response.url()) && response.status() == 200, () -> {});
* return finalResponse.ok();
* // Waits for the next response with the specified url
* Response response = page.waitForResponse("https://example.com/resource", () -> {
* // Triggers the response
* page.click("button.triggers-response");
* });
*
* // Waits for the next response matching some conditions
* Response response = page.waitForResponse(response -> "https://example.com".equals(response.url()) && response.status() == 200, () -> {
* // Triggers the response
* page.click("button.triggers-response");
* });
* }</pre>
*
* @param urlOrPredicate Request URL string, regex or predicate receiving {@code Response} object.
@ -4348,11 +4516,20 @@ public interface Page extends AutoCloseable {
return waitForResponse(urlOrPredicate, null, callback);
}
/**
* Returns the matched response.
* Returns the matched response. See <a href="https://playwright.dev/java/docs/events/#waiting-for-event">waiting for
* event</a> for more details about events.
* <pre>{@code
* Response firstResponse = page.waitForResponse("https://example.com/resource", () -> {});
* Response finalResponse = page.waitForResponse(response -> "https://example.com".equals(response.url()) && response.status() == 200, () -> {});
* return finalResponse.ok();
* // Waits for the next response with the specified url
* Response response = page.waitForResponse("https://example.com/resource", () -> {
* // Triggers the response
* page.click("button.triggers-response");
* });
*
* // Waits for the next response matching some conditions
* Response response = page.waitForResponse(response -> "https://example.com".equals(response.url()) && response.status() == 200, () -> {
* // Triggers the response
* page.click("button.triggers-response");
* });
* }</pre>
*
* @param urlOrPredicate Request URL string, regex or predicate receiving {@code Response} object.
@ -4360,11 +4537,20 @@ public interface Page extends AutoCloseable {
*/
Response waitForResponse(Pattern urlOrPredicate, WaitForResponseOptions options, Runnable callback);
/**
* Returns the matched response.
* Returns the matched response. See <a href="https://playwright.dev/java/docs/events/#waiting-for-event">waiting for
* event</a> for more details about events.
* <pre>{@code
* Response firstResponse = page.waitForResponse("https://example.com/resource", () -> {});
* Response finalResponse = page.waitForResponse(response -> "https://example.com".equals(response.url()) && response.status() == 200, () -> {});
* return finalResponse.ok();
* // Waits for the next response with the specified url
* Response response = page.waitForResponse("https://example.com/resource", () -> {
* // Triggers the response
* page.click("button.triggers-response");
* });
*
* // Waits for the next response matching some conditions
* Response response = page.waitForResponse(response -> "https://example.com".equals(response.url()) && response.status() == 200, () -> {
* // Triggers the response
* page.click("button.triggers-response");
* });
* }</pre>
*
* @param urlOrPredicate Request URL string, regex or predicate receiving {@code Response} object.
@ -4374,11 +4560,20 @@ public interface Page extends AutoCloseable {
return waitForResponse(urlOrPredicate, null, callback);
}
/**
* Returns the matched response.
* Returns the matched response. See <a href="https://playwright.dev/java/docs/events/#waiting-for-event">waiting for
* event</a> for more details about events.
* <pre>{@code
* Response firstResponse = page.waitForResponse("https://example.com/resource", () -> {});
* Response finalResponse = page.waitForResponse(response -> "https://example.com".equals(response.url()) && response.status() == 200, () -> {});
* return finalResponse.ok();
* // Waits for the next response with the specified url
* Response response = page.waitForResponse("https://example.com/resource", () -> {
* // Triggers the response
* page.click("button.triggers-response");
* });
*
* // Waits for the next response matching some conditions
* Response response = page.waitForResponse(response -> "https://example.com".equals(response.url()) && response.status() == 200, () -> {
* // Triggers the response
* page.click("button.triggers-response");
* });
* }</pre>
*
* @param urlOrPredicate Request URL string, regex or predicate receiving {@code Response} object.

View File

@ -27,6 +27,8 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.time.Duration;
import java.util.Collections;
import java.util.Map;
import java.util.function.Consumer;
import static com.microsoft.playwright.impl.Serialization.gson;
@ -58,10 +60,16 @@ class BrowserTypeImpl extends ChannelOwner implements BrowserType {
private Browser connectImpl(String wsEndpoint, ConnectOptions options) {
try {
Duration timeout = Duration.ofDays(1);
if (options != null && options.timeout != null) {
timeout = Duration.ofMillis(Math.round(options.timeout));
Map<String, String> headers = Collections.emptyMap();
if (options != null) {
if (options.timeout != null) {
timeout = Duration.ofMillis(Math.round(options.timeout));
}
if (options.headers != null) {
headers = options.headers;
}
}
WebSocketTransport transport = new WebSocketTransport(new URI(wsEndpoint), timeout);
WebSocketTransport transport = new WebSocketTransport(new URI(wsEndpoint), headers, timeout);
Connection connection = new Connection(transport);
PlaywrightImpl playwright = (PlaywrightImpl) connection.waitForObjectWithKnownName("Playwright");
if (!playwright.initializer.has("preLaunchedBrowser")) {

View File

@ -23,6 +23,7 @@ import org.java_websocket.handshake.ServerHandshake;
import java.io.IOException;
import java.net.URI;
import java.time.Duration;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
@ -62,8 +63,11 @@ class WebSocketTransport implements Transport {
}
}
WebSocketTransport(URI uri, Duration timeout) {
WebSocketTransport(URI uri, Map<String, String> headers, Duration timeout) {
clientConnection = new ClientConnection(uri);
for (Map.Entry<String, String> entry : headers.entrySet()) {
clientConnection.addHeader(entry.getKey(), entry.getValue());
}
try {
if (!clientConnection.connectBlocking(timeout.toMillis(), TimeUnit.MILLISECONDS)) {
throw new PlaywrightException("Failed to connect", lastError);

View File

@ -18,14 +18,17 @@ package com.microsoft.playwright;
import com.microsoft.playwright.impl.Driver;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.nio.file.Path;
import static com.microsoft.playwright.Utils.mapOf;
import static org.junit.jupiter.api.Assertions.*;
public class TestBrowserTypeConnect extends TestBase {
@ -133,6 +136,20 @@ public class TestBrowserTypeConnect extends TestBase {
browser2.close();
}
@Test
void shouldSendExtraHeadersWithConnectRequest() throws Exception {
try (WebSocketServerImpl webSocketServer = WebSocketServerImpl.create()) {
try {
browserType.connect("ws://localhost:" + webSocketServer.getPort() + "/ws",
new BrowserType.ConnectOptions().setHeaders(mapOf("User-Agent", "Playwright", "foo", "bar")));
} catch (Exception e) {
}
assertNotNull(webSocketServer.lastClientHandshake);
assertEquals("Playwright", webSocketServer.lastClientHandshake.getFieldValue("User-Agent"));
assertEquals("bar", webSocketServer.lastClientHandshake.getFieldValue("foo"));
}
}
@Test
void disconnectedEventShouldBeEmittedWhenBrowserIsClosedOrServerIsClosed() throws InterruptedException {
// Launch another server to not affect other tests.

View File

@ -29,8 +29,10 @@ import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import static com.microsoft.playwright.Utils.mapOf;
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@EnabledIf(value="com.microsoft.playwright.TestBase#isChromium", disabledReason="Chromium-specific API")
public class TestChromium extends TestBase {
@ -104,4 +106,18 @@ public class TestChromium extends TestBase {
cdpBrowser2.close();
}
}
@Test
void shouldSendExtraHeadersWithConnectRequest() throws Exception {
try (WebSocketServerImpl webSocketServer = WebSocketServerImpl.create()) {
try {
browserType.connectOverCDP("ws://localhost:" + webSocketServer.getPort() + "/ws",
new BrowserType.ConnectOverCDPOptions().setHeaders(mapOf("User-Agent", "Playwright", "foo", "bar")));
} catch (Exception e) {
}
assertNotNull(webSocketServer.lastClientHandshake);
assertEquals("Playwright", webSocketServer.lastClientHandshake.getFieldValue("User-Agent"));
assertEquals("bar", webSocketServer.lastClientHandshake.getFieldValue("foo"));
}
}
}

View File

@ -213,7 +213,7 @@ public class TestDownload extends TestBase {
download.saveAs(userPath);
fail("did not throw");
} catch (PlaywrightException e) {
assertTrue(e.getMessage().contains("File already deleted. Save before deleting."), e.getMessage());
assertTrue(e.getMessage().contains("Target page, context or browser has been closed"), e.getMessage());
}
page.close();
}

View File

@ -16,9 +16,6 @@
package com.microsoft.playwright;
import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@ -35,35 +32,10 @@ import static org.junit.jupiter.api.Assertions.*;
public class TestWebSocket extends TestBase {
private static WebSocketServerImpl webSocketServer;
private static int WS_SERVER_PORT = 8910;
private static class WebSocketServerImpl extends WebSocketServer {
WebSocketServerImpl(InetSocketAddress address) {
super(address, 1);
}
@Override
public void onOpen(org.java_websocket.WebSocket webSocket, ClientHandshake clientHandshake) {
webSocket.send("incoming");
}
@Override
public void onClose(org.java_websocket.WebSocket webSocket, int i, String s, boolean b) { }
@Override
public void onMessage(org.java_websocket.WebSocket webSocket, String s) { }
@Override
public void onError(WebSocket webSocket, Exception e) { }
@Override
public void onStart() { }
}
@BeforeAll
static void startWebSockerServer() {
webSocketServer = new WebSocketServerImpl(new InetSocketAddress("localhost", WS_SERVER_PORT));
new Thread(webSocketServer).start();
static void startWebSockerServer() throws InterruptedException {
webSocketServer = WebSocketServerImpl.create();
}
@AfterAll

View File

@ -0,0 +1,70 @@
/*
* 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 org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;
import java.net.InetSocketAddress;
import java.util.concurrent.Semaphore;
class WebSocketServerImpl extends WebSocketServer implements AutoCloseable {
volatile ClientHandshake lastClientHandshake;
private final Semaphore startSemaphore = new Semaphore(0);
static final int WS_SERVER_PORT = 8910;
static WebSocketServerImpl create() throws InterruptedException {
WebSocketServerImpl result = new WebSocketServerImpl(new InetSocketAddress("localhost", WebSocketServerImpl.WS_SERVER_PORT));
result.start();
result.startSemaphore.acquire();
return result;
}
private WebSocketServerImpl(InetSocketAddress address) {
super(address, 1);
}
@Override
public void close() throws Exception {
this.stop();
}
@Override
public void onOpen(org.java_websocket.WebSocket webSocket, ClientHandshake clientHandshake) {
lastClientHandshake = clientHandshake;
webSocket.send("incoming");
}
@Override
public void onClose(org.java_websocket.WebSocket webSocket, int i, String s, boolean b) {
}
@Override
public void onMessage(org.java_websocket.WebSocket webSocket, String s) {
}
@Override
public void onError(WebSocket webSocket, Exception e) {
}
@Override
public void onStart() {
startSemaphore.release();
}
}

View File

@ -1 +1 @@
1.11.0-next-1618951606000
1.11.0-next-1619459952000