mirror of
https://github.com/microsoft/playwright-java.git
synced 2025-09-08 21:01:00 +00:00
feat: implement Page.waitForRequest/Response
This commit is contained in:
parent
9b5765e1f1
commit
3d75d2a836
@ -93,7 +93,7 @@ class TypeRef extends Element {
|
||||
}
|
||||
} else {
|
||||
if (!mapping.from.equals(jsonName)) {
|
||||
throw new RuntimeException("Unexpected source type for: " + parentPath);
|
||||
throw new RuntimeException("Unexpected source type for: " + parentPath +". Expected: " + mapping.from + "; found: " + jsonName);
|
||||
}
|
||||
customType = mapping.to;
|
||||
if (mapping.customMapping != null) {
|
||||
@ -511,6 +511,10 @@ class Interface extends TypeDefinition {
|
||||
for (Method m : methods) {
|
||||
m.writeTo(output, offset);
|
||||
}
|
||||
// TODO: fix api.json generator to avoid name clash between close() method and close event.
|
||||
if ("Page".equals(jsonName)) {
|
||||
output.add(offset + "Deferred<Void> waitForClose();");
|
||||
}
|
||||
output.add("}");
|
||||
output.add("\n");
|
||||
}
|
||||
|
@ -185,6 +185,10 @@ class Types {
|
||||
// Return structures
|
||||
add("ConsoleMessage.location", "Object", "Location");
|
||||
|
||||
add("Page.waitForRequest", "Promise<Request>", "Deferred<Request>");
|
||||
add("Page.waitForResponse", "Promise<Response>", "Deferred<Response>");
|
||||
add("Page.waitForNavigation", "Promise<null|Response>", "Deferred<Response>");
|
||||
|
||||
// Custom options
|
||||
add("Page.pdf.options.margin.top", "string|number", "String");
|
||||
add("Page.pdf.options.margin.right", "string|number", "String");
|
||||
|
@ -920,23 +920,24 @@ public interface Page {
|
||||
waitForLoadState(null);
|
||||
}
|
||||
void waitForLoadState(LoadState state, WaitForLoadStateOptions options);
|
||||
default Response waitForNavigation() {
|
||||
default Deferred<Response> waitForNavigation() {
|
||||
return waitForNavigation(null);
|
||||
}
|
||||
Response waitForNavigation(WaitForNavigationOptions options);
|
||||
default Request waitForRequest(String urlOrPredicate) {
|
||||
Deferred<Response> waitForNavigation(WaitForNavigationOptions options);
|
||||
default Deferred<Request> waitForRequest(String urlOrPredicate) {
|
||||
return waitForRequest(urlOrPredicate, null);
|
||||
}
|
||||
Request waitForRequest(String urlOrPredicate, WaitForRequestOptions options);
|
||||
default Response waitForResponse(String urlOrPredicate) {
|
||||
Deferred<Request> waitForRequest(String urlOrPredicate, WaitForRequestOptions options);
|
||||
default Deferred<Response> waitForResponse(String urlOrPredicate) {
|
||||
return waitForResponse(urlOrPredicate, null);
|
||||
}
|
||||
Response waitForResponse(String urlOrPredicate, WaitForResponseOptions options);
|
||||
Deferred<Response> waitForResponse(String urlOrPredicate, WaitForResponseOptions options);
|
||||
default ElementHandle waitForSelector(String selector) {
|
||||
return waitForSelector(selector, null);
|
||||
}
|
||||
ElementHandle waitForSelector(String selector, WaitForSelectorOptions options);
|
||||
void waitForTimeout(int timeout);
|
||||
List<Worker> workers();
|
||||
Deferred<Void> waitForClose();
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.regex.Pattern;
|
||||
@ -34,7 +35,7 @@ import static com.microsoft.playwright.impl.Utils.isFunctionBody;
|
||||
|
||||
class BrowserContextImpl extends ChannelOwner implements BrowserContext {
|
||||
private final BrowserImpl browser;
|
||||
private final List<PageImpl> pages = new ArrayList<>();
|
||||
final List<PageImpl> pages = new ArrayList<>();
|
||||
private List<RouteInfo> routes = new ArrayList<>();
|
||||
private boolean isClosedOrClosing;
|
||||
final Map<String, Page.Binding> bindings = new HashMap<String, Page.Binding>();
|
||||
@ -206,9 +207,9 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
|
||||
|
||||
@Override
|
||||
public Deferred<Page> waitForPage() {
|
||||
Supplier<JsonObject> pageSupplier = waitForProtocolEvent("page");
|
||||
CompletableFuture<JsonObject> pageFuture = futureForEvent("page");
|
||||
return () -> {
|
||||
JsonObject params = pageSupplier.get();
|
||||
JsonObject params = waitForCompletion(pageFuture);
|
||||
String guid = params.getAsJsonObject("page").get("guid").getAsString();
|
||||
return connection.getExistingObject(guid);
|
||||
};
|
||||
|
@ -66,11 +66,11 @@ class ChannelOwner {
|
||||
return connection.sendMessage(guid, method, params);
|
||||
}
|
||||
|
||||
protected void sendMessageNoWait(String method, JsonObject params) {
|
||||
void sendMessageNoWait(String method, JsonObject params) {
|
||||
connection.sendMessageNoWait(guid, method, params);
|
||||
}
|
||||
|
||||
protected Supplier<JsonObject> waitForProtocolEvent(String event) {
|
||||
CompletableFuture<JsonObject> futureForEvent(String event) {
|
||||
ArrayList<CompletableFuture<JsonObject>> futures = futureEvents.get(event);
|
||||
if (futures == null) {
|
||||
futures = new ArrayList<>();
|
||||
@ -78,23 +78,27 @@ class ChannelOwner {
|
||||
}
|
||||
CompletableFuture<JsonObject> result = new CompletableFuture<>();
|
||||
futures.add(result);
|
||||
return () -> {
|
||||
while (!result.isDone()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
<T> T waitForCompletion(CompletableFuture<T> future) {
|
||||
while (!future.isDone()) {
|
||||
connection.processOneMessage();
|
||||
}
|
||||
// TODO: ensure it's been removed from futureEvents
|
||||
try {
|
||||
return result.get();
|
||||
return future.get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
final void onEvent(String event, JsonObject parameters) {
|
||||
handleEvent(event, parameters);
|
||||
ArrayList<CompletableFuture<JsonObject>> futures = futureEvents.remove(event);
|
||||
if (futures == null)
|
||||
if (futures == null) {
|
||||
return;
|
||||
}
|
||||
for (CompletableFuture<JsonObject> f : futures) {
|
||||
f.complete(parameters);
|
||||
}
|
||||
|
@ -240,7 +240,11 @@ public class FrameImpl extends ChannelOwner implements Frame {
|
||||
params.addProperty("waitUntil", toProtocol(options.waitUntil));
|
||||
}
|
||||
JsonElement result = sendMessage("goto", params);
|
||||
return connection.getExistingObject(result.getAsJsonObject().getAsJsonObject("response").get("guid").getAsString());
|
||||
JsonObject jsonResponse = result.getAsJsonObject().getAsJsonObject("response");
|
||||
if (jsonResponse == null) {
|
||||
return null;
|
||||
}
|
||||
return connection.getExistingObject(jsonResponse.get("guid").getAsString());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -17,12 +17,13 @@
|
||||
package com.microsoft.playwright.impl;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.microsoft.playwright.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static com.microsoft.playwright.impl.Utils.convertViaJson;
|
||||
|
||||
@ -32,12 +33,16 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
private final FrameImpl mainFrame;
|
||||
private final KeyboardImpl keyboard;
|
||||
private final MouseImpl mouse;
|
||||
private Viewport viewport;
|
||||
// TODO: do not rely on the frame order in the tests
|
||||
private final Set<FrameImpl> frames = new LinkedHashSet<>();
|
||||
private final List<Listener<ConsoleMessage>> consoleListeners = new ArrayList<>();
|
||||
private final List<Listener<Dialog>> dialogListeners = new ArrayList<>();
|
||||
private final List<Listener<Page>> closeListeners = new ArrayList<>();
|
||||
private final List<WaitEventHelper> eventHelpers = new ArrayList<>();
|
||||
final Map<String, Binding> bindings = new HashMap<String, Binding>();
|
||||
BrowserContextImpl ownedContext;
|
||||
private boolean isClosed;
|
||||
|
||||
PageImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
@ -59,6 +64,14 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
consoleListeners.remove(listener);
|
||||
}
|
||||
|
||||
public void addCloseListener(Listener<Page> listener) {
|
||||
closeListeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeCloseListener(Listener<Page> listener) {
|
||||
closeListeners.remove(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDialogListener(Listener<Dialog> listener) {
|
||||
dialogListeners.add(listener);
|
||||
@ -71,21 +84,25 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
|
||||
@Override
|
||||
public Deferred<Page> waitForPopup() {
|
||||
Supplier<JsonObject> popupSupplier = waitForProtocolEvent("popup");
|
||||
CompletableFuture<JsonObject> popupFuture = futureForEvent("popup");
|
||||
return () -> {
|
||||
JsonObject params = popupSupplier.get();
|
||||
JsonObject params = waitForCompletion(popupFuture);
|
||||
String guid = params.getAsJsonObject("page").get("guid").getAsString();
|
||||
return connection.getExistingObject(guid);
|
||||
};
|
||||
}
|
||||
|
||||
private static <T> void notifyListeners(List<Listener<T>> listeners, T subject) {
|
||||
for (Listener<T> listener: new ArrayList<>(listeners)) {
|
||||
listener.handle(subject);
|
||||
}
|
||||
}
|
||||
|
||||
protected void handleEvent(String event, JsonObject params) {
|
||||
if ("dialog".equals(event)) {
|
||||
String guid = params.getAsJsonObject("dialog").get("guid").getAsString();
|
||||
DialogImpl dialog = connection.getExistingObject(guid);
|
||||
for (Listener<Dialog> listener: new ArrayList<>(dialogListeners)) {
|
||||
listener.handle(dialog);
|
||||
}
|
||||
notifyListeners(dialogListeners, dialog);
|
||||
// If no action taken dismiss dialog to not hang.
|
||||
if (!dialog.isHandled()) {
|
||||
dialog.dismiss();
|
||||
@ -93,9 +110,7 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
} else if ("console".equals(event)) {
|
||||
String guid = params.getAsJsonObject("message").get("guid").getAsString();
|
||||
ConsoleMessageImpl message = connection.getExistingObject(guid);
|
||||
for (Listener<ConsoleMessage> listener: new ArrayList<>(consoleListeners)) {
|
||||
listener.handle(message);
|
||||
}
|
||||
notifyListeners(consoleListeners, message);
|
||||
} else if ("frameAttached".equals(event)) {
|
||||
String guid = params.getAsJsonObject("frame").get("guid").getAsString();
|
||||
FrameImpl frame = connection.getExistingObject(guid);
|
||||
@ -104,7 +119,7 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
if (frame.parentFrame != null) {
|
||||
frame.parentFrame.childFrames.add(frame);
|
||||
}
|
||||
} else if ("'frameDetached'".equals(event)) {
|
||||
} else if ("frameDetached".equals(event)) {
|
||||
String guid = params.getAsJsonObject("frame").get("guid").getAsString();
|
||||
FrameImpl frame = connection.getExistingObject(guid);
|
||||
frames.remove(frame);
|
||||
@ -112,6 +127,13 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
if (frame.parentFrame != null) {
|
||||
frame.parentFrame.childFrames.remove(frame);
|
||||
}
|
||||
} else if ("close".equals(event)) {
|
||||
isClosed = true;
|
||||
browserContext.pages.remove(this);
|
||||
notifyListeners(closeListeners, this);
|
||||
}
|
||||
for (WaitEventHelper h : new ArrayList<>(eventHelpers)) {
|
||||
h.handleEvent(event, params);
|
||||
}
|
||||
}
|
||||
|
||||
@ -171,7 +193,7 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
|
||||
@Override
|
||||
public void check(String selector, CheckOptions options) {
|
||||
|
||||
mainFrame.check(selector, convertViaJson(options, Frame.CheckOptions.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -181,7 +203,7 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
|
||||
@Override
|
||||
public String content() {
|
||||
return null;
|
||||
return mainFrame.content();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -296,7 +318,7 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
|
||||
@Override
|
||||
public boolean isClosed() {
|
||||
return false;
|
||||
return isClosed;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -316,8 +338,12 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
|
||||
@Override
|
||||
public Page opener() {
|
||||
JsonObject result = sendMessage("opener", new JsonObject()).getAsJsonObject();
|
||||
if (!result.has("page")) {
|
||||
return null;
|
||||
}
|
||||
return connection.getExistingObject(result.getAsJsonObject("page").get("guid").getAsString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] pdf(PdfOptions options) {
|
||||
@ -376,17 +402,15 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
|
||||
@Override
|
||||
public void setViewportSize(int width, int height) {
|
||||
JsonObject size = new JsonObject();
|
||||
size.addProperty("width", width);
|
||||
size.addProperty("height", height);
|
||||
viewport = new Viewport(width, height);
|
||||
JsonObject params = new JsonObject();
|
||||
params.add("viewportSize", size);
|
||||
params.add("viewportSize", new Gson().toJsonTree(viewport));
|
||||
sendMessage("setViewportSize", params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String textContent(String selector, TextContentOptions options) {
|
||||
return null;
|
||||
return mainFrame.textContent(selector, convertViaJson(options, Frame.TextContentOptions.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -396,12 +420,12 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
|
||||
@Override
|
||||
public void type(String selector, String text, TypeOptions options) {
|
||||
|
||||
mainFrame.type(selector, text, convertViaJson(options, Frame.TypeOptions.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uncheck(String selector, UncheckOptions options) {
|
||||
|
||||
mainFrame.uncheck(selector, convertViaJson(options, Frame.UncheckOptions.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -411,19 +435,17 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
|
||||
@Override
|
||||
public String url() {
|
||||
return null;
|
||||
return mainFrame.url();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Viewport viewportSize() {
|
||||
return null;
|
||||
return viewport;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object waitForEvent(String event, String optionsOrPredicate) {
|
||||
// TODO: do we want to keep this method ?
|
||||
Supplier<JsonObject> popupSupplier = waitForProtocolEvent(event);
|
||||
popupSupplier.get();
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -438,18 +460,51 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response waitForNavigation(WaitForNavigationOptions options) {
|
||||
public Deferred<Response> waitForNavigation(WaitForNavigationOptions options) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Request waitForRequest(String urlOrPredicate, WaitForRequestOptions options) {
|
||||
return null;
|
||||
private class WaitEventHelper<R> implements Deferred<R> {
|
||||
private final CompletableFuture<R> result = new CompletableFuture<>();
|
||||
private final String event;
|
||||
private final String fieldName;
|
||||
|
||||
WaitEventHelper(String event, String fieldName) {
|
||||
this.event = event;
|
||||
this.fieldName = fieldName;
|
||||
eventHelpers.add(this);
|
||||
}
|
||||
|
||||
void handleEvent(String name, JsonObject params) {
|
||||
if (event.equals(name)) {
|
||||
if (fieldName != null && params.has(fieldName)) {
|
||||
result.complete(connection.getExistingObject(params.getAsJsonObject(fieldName).get("guid").getAsString()));
|
||||
} else {
|
||||
result.complete(null);
|
||||
}
|
||||
} else if ("close".equals(name)) {
|
||||
result.completeExceptionally(new RuntimeException("Page closed"));
|
||||
} else if ("crash".equals(name)) {
|
||||
result.completeExceptionally(new RuntimeException("Page crashed"));
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
eventHelpers.remove(this);
|
||||
}
|
||||
|
||||
public R get() {
|
||||
return waitForCompletion(result);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response waitForResponse(String urlOrPredicate, WaitForResponseOptions options) {
|
||||
return null;
|
||||
public Deferred<Request> waitForRequest(String urlOrPredicate, WaitForRequestOptions options) {
|
||||
return new WaitEventHelper<>("request", "request");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Deferred<Response> waitForResponse(String urlOrPredicate, WaitForResponseOptions options) {
|
||||
return new WaitEventHelper<>("response", "response");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -466,4 +521,9 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
public List<Worker> workers() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Deferred<Void> waitForClose() {
|
||||
return new WaitEventHelper<>("close", null);
|
||||
}
|
||||
}
|
||||
|
@ -101,6 +101,12 @@ public class Server implements HttpHandler {
|
||||
routes.put(path, handler);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
requestSubscribers.clear();
|
||||
auths.clear();
|
||||
routes.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(HttpExchange exchange) throws IOException {
|
||||
String path = exchange.getRequestURI().getPath();
|
||||
|
@ -62,6 +62,7 @@ public class TestClick {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
server.reset();
|
||||
context = browser.newContext();
|
||||
page = context.newPage();
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ public class TestDialog {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
server.reset();
|
||||
context = browser.newContext();
|
||||
page = context.newPage();
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ public class TestElementHandleClick {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
server.reset();
|
||||
context = browser.newContext();
|
||||
page = context.newPage();
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ public class TestFrameNavigate {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
server.reset();
|
||||
context = browser.newContext();
|
||||
page = context.newPage();
|
||||
}
|
||||
|
249
lib/src/test/java/com/microsoft/playwright/TestPageBasic.java
Normal file
249
lib/src/test/java/com/microsoft/playwright/TestPageBasic.java
Normal file
@ -0,0 +1,249 @@
|
||||
/**
|
||||
* 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.junit.jupiter.api.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static com.microsoft.playwright.Page.LoadState.DOMCONTENTLOADED;
|
||||
import static com.microsoft.playwright.Page.LoadState.LOAD;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class TestPageBasic {
|
||||
private static Server server;
|
||||
private static Browser browser;
|
||||
private static boolean isChromium;
|
||||
private static boolean isWebKit;
|
||||
private BrowserContext context;
|
||||
private Page page;
|
||||
|
||||
@BeforeAll
|
||||
static void launchBrowser() {
|
||||
Playwright playwright = Playwright.create();
|
||||
BrowserType.LaunchOptions options = new BrowserType.LaunchOptions();
|
||||
browser = playwright.chromium().launch(options);
|
||||
isChromium = true;
|
||||
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
static void startServer() throws IOException {
|
||||
server = new Server(8907);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void stopServer() throws IOException {
|
||||
browser.close();
|
||||
server.stop();
|
||||
server = null;
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
context = browser.newContext();
|
||||
page = context.newPage();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
context.close();
|
||||
context = null;
|
||||
page = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRejectAllPromisesWhenPageIsClosed() {
|
||||
Page newPage = context.newPage();
|
||||
newPage.close();
|
||||
try {
|
||||
newPage.evaluate("() => new Promise(r => {})");
|
||||
fail("evaluate should throw");
|
||||
} catch (RuntimeException e) {
|
||||
assertTrue(e.getMessage().contains("Protocol error"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotBeVisibleInContextPages() {
|
||||
Page newPage = context.newPage();
|
||||
assertTrue(context.pages().contains(newPage));
|
||||
newPage.close();
|
||||
assertFalse(context.pages().contains(newPage));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRunBeforeunloadIfAskedFor() {
|
||||
Page newPage = context.newPage();
|
||||
newPage.navigate(server.PREFIX + "/beforeunload.html");
|
||||
// We have to interact with a page so that "beforeunload" handlers
|
||||
// fire.
|
||||
newPage.click("body");
|
||||
boolean[] didShowDialog = {false};
|
||||
newPage.addDialogListener(dialog -> {
|
||||
didShowDialog[0] = true;
|
||||
assertEquals("beforeunload", dialog.type());
|
||||
assertEquals("", dialog.defaultValue());
|
||||
if (isChromium) {
|
||||
assertEquals("", dialog.message());
|
||||
} else if (isWebKit) {
|
||||
assertEquals("Leave?", dialog.message());
|
||||
} else {
|
||||
assertEquals("This page is asking you to confirm that you want to leave - data you have entered may not be saved.", dialog.message());
|
||||
}
|
||||
dialog.accept();
|
||||
});
|
||||
newPage.close(new Page.CloseOptions().withRunBeforeUnload(true));
|
||||
// TODO: uncomment once https://github.com/microsoft/playwright/pull/4070 is committed.
|
||||
// assertTrue(didShowDialog[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotRunBeforeunloadByDefault() {
|
||||
Page newPage = context.newPage();
|
||||
newPage.navigate(server.PREFIX + "/beforeunload.html");
|
||||
// We have to interact with a page so that "beforeunload" handlers
|
||||
// fire.
|
||||
newPage.click("body");
|
||||
boolean[] didShowDialog = {false};
|
||||
newPage.addDialogListener(dialog -> didShowDialog[0] = true);
|
||||
newPage.close();
|
||||
assertFalse(didShowDialog[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSetThePageCloseState() {
|
||||
Page newPage = context.newPage();
|
||||
assertEquals(false, newPage.isClosed());
|
||||
newPage.close();
|
||||
assertEquals(true, newPage.isClosed());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldTerminateNetworkWaiters() {
|
||||
Page newPage = context.newPage();
|
||||
Deferred<Request> request = newPage.waitForRequest(server.EMPTY_PAGE);
|
||||
Deferred<Response> response = newPage.waitForResponse(server.EMPTY_PAGE);
|
||||
newPage.close();
|
||||
try {
|
||||
request.get();
|
||||
fail("get() should throw");
|
||||
} catch (RuntimeException e) {
|
||||
assertTrue(e.getMessage().contains("Page closed"));
|
||||
assertFalse(e.getMessage().contains("Timeout"));
|
||||
}
|
||||
try {
|
||||
response.get();
|
||||
fail("get() should throw");
|
||||
} catch (RuntimeException e) {
|
||||
assertTrue(e.getMessage().contains("Page closed"));
|
||||
assertFalse(e.getMessage().contains("Timeout"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldBeCallableTwice() {
|
||||
Page newPage = context.newPage();
|
||||
newPage.close();
|
||||
newPage.close();
|
||||
newPage.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFireLoadWhenExpected() {
|
||||
page.navigate("about:blank");
|
||||
page.waitForLoadState(LOAD);
|
||||
}
|
||||
|
||||
// TODO: not supported in sync api
|
||||
void asyncStacksShouldWork() {
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldProvideAccessToTheOpenerPage() {
|
||||
Deferred<Page> popupEvent = page.waitForPopup();
|
||||
page.evaluate("() => window.open('about:blank')");
|
||||
Page opener = popupEvent.get().opener();
|
||||
assertEquals(page, opener);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnNullIfParentPageHasBeenClosed() {
|
||||
Deferred<Page> popupEvent = page.waitForPopup();
|
||||
page.evaluate("() => window.open('about:blank')");
|
||||
Page popup = popupEvent.get();
|
||||
page.close();
|
||||
Page opener = popup.opener();
|
||||
assertEquals(null, opener);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFireDomcontentloadedWhenExpected() {
|
||||
page.navigate("about:blank");
|
||||
page.waitForLoadState(DOMCONTENTLOADED);
|
||||
}
|
||||
|
||||
// TODO: downloads
|
||||
void shouldFailWithErrorUponDisconnect() {
|
||||
}
|
||||
|
||||
@Test
|
||||
void pageUrlShouldWork() {
|
||||
assertEquals("about:blank", page.url());
|
||||
page.navigate(server.EMPTY_PAGE);
|
||||
assertEquals(server.EMPTY_PAGE, page.url());
|
||||
}
|
||||
|
||||
@Test
|
||||
void pageUrlShouldIncludeHashes() {
|
||||
page.navigate(server.EMPTY_PAGE + "#hash");
|
||||
assertEquals(server.EMPTY_PAGE + "#hash", page.url());
|
||||
page.evaluate("() => {\n" +
|
||||
" window.location.hash = 'dynamic';\n" +
|
||||
"}");
|
||||
assertEquals(server.EMPTY_PAGE + "#dynamic", page.url());
|
||||
}
|
||||
|
||||
@Test
|
||||
void pageTitleShouldReturnThePageTitle() {
|
||||
page.navigate(server.PREFIX + "/title.html");
|
||||
assertEquals("Woof-Woof", page.title());
|
||||
}
|
||||
|
||||
@Test
|
||||
void pageCloseShouldWorkWithWindowClose() {
|
||||
Deferred<Page> newPagePromise = page.waitForPopup();
|
||||
page.evaluate("() => window['newPage'] = window.open('about:blank')");
|
||||
Page newPage = newPagePromise.get();
|
||||
Deferred<Void> closedPromise = newPage.waitForClose();
|
||||
page.evaluate("() => window['newPage'].close()");
|
||||
closedPromise.get();
|
||||
}
|
||||
|
||||
@Test
|
||||
void pageCloseShouldWorkWithPageClose() {
|
||||
Page newPage = context.newPage();
|
||||
Deferred<Void> closedPromise = newPage.waitForClose();
|
||||
newPage.close();
|
||||
closedPromise.get();
|
||||
}
|
||||
|
||||
@Test
|
||||
void pageContextShouldReturnTheCorrectInstance() {
|
||||
assertEquals(context, page.context());
|
||||
}
|
||||
}
|
@ -54,6 +54,7 @@ public class TestPopup {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
server.reset();
|
||||
context = browser.newContext();
|
||||
page = context.newPage();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user