diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/APIResponseImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/APIResponseImpl.java index ee8d6724..e80fd3d3 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/APIResponseImpl.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/APIResponseImpl.java @@ -34,7 +34,7 @@ import static com.microsoft.playwright.impl.Utils.isSafeCloseError; import static java.util.Arrays.asList; class APIResponseImpl implements APIResponse { - private final APIRequestContextImpl context; + final APIRequestContextImpl context; private final JsonObject initializer; private final RawHeaders headers; diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/FrameImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/FrameImpl.java index 229dacbc..53cf09c6 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/FrameImpl.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/FrameImpl.java @@ -586,7 +586,7 @@ public class FrameImpl extends ChannelOwner implements Frame { } @Override - public Page page() { + public PageImpl page() { return page; } diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/RouteImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/RouteImpl.java index a3b3ae2b..665aeb03 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/RouteImpl.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/RouteImpl.java @@ -18,7 +18,6 @@ package com.microsoft.playwright.impl; import com.google.gson.JsonObject; import com.microsoft.playwright.PlaywrightException; -import com.microsoft.playwright.Request; import com.microsoft.playwright.Route; import java.io.IOException; @@ -102,9 +101,6 @@ public class RouteImpl extends ChannelOwner implements Route { if (headersOption == null) { headersOption = options.response.headers(); } - if (options.body == null && options.path == null) { - fetchResponseUid = ((APIResponseImpl) options.response).fetchUid(); - } } if (status == null) { status = 200; @@ -114,10 +110,10 @@ public class RouteImpl extends ChannelOwner implements Route { int length = 0; if (options.path != null) { try { - byte[] buffer = Files.readAllBytes(options.path); - body = Base64.getEncoder().encodeToString(buffer); - isBase64 = true; - length = buffer.length; + byte[] buffer = Files.readAllBytes(options.path); + body = Base64.getEncoder().encodeToString(buffer); + isBase64 = true; + length = buffer.length; } catch (IOException e) { throw new PlaywrightException("Failed to read from file: " + options.path, e); } @@ -129,8 +125,19 @@ public class RouteImpl extends ChannelOwner implements Route { body = Base64.getEncoder().encodeToString(options.bodyBytes); isBase64 = true; length = options.bodyBytes.length; + } else if (options.response != null) { + APIResponseImpl response = (APIResponseImpl) options.response; + if (response.context.connection == connection) { + fetchResponseUid = response.fetchUid(); + } else { + byte[] bodyBytes = response.body(); + body = Base64.getEncoder().encodeToString(bodyBytes); + isBase64 = true; + length = bodyBytes.length; + } } + Map headers = new LinkedHashMap<>(); if (headersOption != null) { for (Map.Entry h : headersOption.entrySet()) { @@ -157,7 +164,7 @@ public class RouteImpl extends ChannelOwner implements Route { } @Override - public Request request() { + public RequestImpl request() { return connection.getExistingObject(initializer.getAsJsonObject("request").get("guid").getAsString()); } diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/Waitable.java b/playwright/src/main/java/com/microsoft/playwright/impl/Waitable.java index d722f0b5..88746c29 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/Waitable.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/Waitable.java @@ -22,7 +22,4 @@ interface Waitable { boolean isDone(); T get(); void dispose(); - default Waitable apply(Function transform) { - return new WaitableAdapter(this, transform); - } } diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/WaitableAdapter.java b/playwright/src/main/java/com/microsoft/playwright/impl/WaitableAdapter.java deleted file mode 100644 index 64879113..00000000 --- a/playwright/src/main/java/com/microsoft/playwright/impl/WaitableAdapter.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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.impl; - -import java.util.function.Function; - -class WaitableAdapter implements Waitable { - private final Waitable waitable; - private final Function transformation; - - WaitableAdapter(Waitable waitable, Function transformation) { - this.waitable = waitable; - this.transformation = transformation; - } - @Override - public boolean isDone() { - return waitable.isDone(); - } - - @Override - public T get() { - return transformation.apply(waitable.get()); - } - - @Override - public void dispose() { - waitable.dispose(); - } -} diff --git a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextRoute.java b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextRoute.java index e214f3ab..fb300806 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextRoute.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextRoute.java @@ -16,10 +16,13 @@ package com.microsoft.playwright; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; import java.util.function.Consumer; import static java.util.Arrays.asList; @@ -134,4 +137,70 @@ public class TestBrowserContextRoute extends TestBase { page.navigate(server.EMPTY_PAGE); assertEquals(2, intercepted[0]); } + + @Test + void shouldOverwritePostBodyWithEmptyString() throws ExecutionException, InterruptedException { + context.route("**/empty.html", route -> { + route.resume(new Route.ResumeOptions().setPostData("")); + }); + + Future req = server.futureRequest("/empty.html"); + page.setContent(""); + + byte[] body = req.get().postBody; + assertEquals(0, body.length); + } + + @Test + void shouldNotSwallowExceptionsInRoute() throws ExecutionException, InterruptedException { + context.route("**/empty.html", route -> { + throw new RuntimeException("My Exception"); + }); + + try { + page.navigate(server.EMPTY_PAGE); + fail("did not throw"); + } catch (RuntimeException e) { + assertTrue(e.getMessage().contains("My Exception"), e.getMessage()); + } + } + + @Test + @Disabled("Conflicts with https://github.com/microsoft/playwright-java/pull/680") + void shouldNotSwallowExceptionsInFulfill() throws ExecutionException, InterruptedException { + APIRequestContext request = playwright.request().newContext(); + APIResponse response = request.get(server.EMPTY_PAGE); + response.dispose(); + page.route("**/*", route -> { + // Fulfilling with dsiposed response will lead to a server-side exception. + route.fulfill(new Route.FulfillOptions().setResponse(response)); + }); + try { + page.navigate(server.EMPTY_PAGE); + fail("did not throw"); + } catch (RuntimeException e) { + assertTrue(e.getMessage().contains("Fetch response has been disposed"), e.getMessage()); + } + } + + @Test + @Disabled("Conflicts with https://github.com/microsoft/playwright-java/pull/680") + void shouldNotSwallowExceptionsInResume() throws ExecutionException, InterruptedException { + page.route("**/*", route -> { + route.resume(new Route.ResumeOptions().setUrl("file:///tmp")); + }); + try { + page.navigate(server.EMPTY_PAGE); + fail("did not throw"); + } catch (RuntimeException e) { + assertTrue(e.getMessage().contains("New URL must have same protocol as overridden URL"), e.getMessage()); + } + } } diff --git a/playwright/src/test/java/com/microsoft/playwright/TestBrowserTypeConnect.java b/playwright/src/test/java/com/microsoft/playwright/TestBrowserTypeConnect.java index 9206841d..9b929374 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestBrowserTypeConnect.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestBrowserTypeConnect.java @@ -507,4 +507,15 @@ public class TestBrowserTypeConnect extends TestBase { assertEquals(new String(thisFile, UTF_8), new String(sources.values().iterator().next(), UTF_8)); } + @Test + void shouldFulfillWithGlobalFetchResult() { + page.route("**/*", route -> { + APIRequestContext request = playwright.request().newContext(); + APIResponse response = request.get(server.PREFIX + "/simple.json"); + route.fulfill(new Route.FulfillOptions().setResponse(response)); + }); + Response response = page.navigate(server.EMPTY_PAGE); + assertEquals(200, response.status()); + assertEquals("{\"foo\": \"bar\"}\n", response.text()); + } }