diff --git a/playwright/src/main/java/com/microsoft/playwright/BrowserContext.java b/playwright/src/main/java/com/microsoft/playwright/BrowserContext.java index d595cf53..8820f8ba 100644 --- a/playwright/src/main/java/com/microsoft/playwright/BrowserContext.java +++ b/playwright/src/main/java/com/microsoft/playwright/BrowserContext.java @@ -491,6 +491,8 @@ public interface BrowserContext extends AutoCloseable { *
Page routes (set up with {@link Page#route Page.route()}) take precedence over browser context routes when request * matches both handlers. * + *
To remove a route with its handler you can use {@link BrowserContext#unroute BrowserContext.unroute()}. + * *
NOTE: Enabling routing disables http cache. * * @param url A glob pattern, regex pattern or predicate receiving [URL] to match while routing. @@ -522,6 +524,8 @@ public interface BrowserContext extends AutoCloseable { *
Page routes (set up with {@link Page#route Page.route()}) take precedence over browser context routes when request * matches both handlers. * + *
To remove a route with its handler you can use {@link BrowserContext#unroute BrowserContext.unroute()}. + * *
NOTE: Enabling routing disables http cache. * * @param url A glob pattern, regex pattern or predicate receiving [URL] to match while routing. @@ -553,6 +557,8 @@ public interface BrowserContext extends AutoCloseable { *
Page routes (set up with {@link Page#route Page.route()}) take precedence over browser context routes when request * matches both handlers. * + *
To remove a route with its handler you can use {@link BrowserContext#unroute BrowserContext.unroute()}. + * *
NOTE: Enabling routing disables http cache. * * @param url A glob pattern, regex pattern or predicate receiving [URL] to match while routing. diff --git a/playwright/src/main/java/com/microsoft/playwright/Download.java b/playwright/src/main/java/com/microsoft/playwright/Download.java index 02f4385f..8d173a79 100644 --- a/playwright/src/main/java/com/microsoft/playwright/Download.java +++ b/playwright/src/main/java/com/microsoft/playwright/Download.java @@ -29,7 +29,7 @@ import java.util.*; *
Download event is emitted once the download starts. Download path becomes available once download completes: *
{@code
* // wait for download to start
- * Download download = page.waitForDownload(() -> page.click("a"));
+ * Download download = page.waitForDownload(() -> page.click("a"));
* // wait for download to complete
* Path path = download.path();
* }
@@ -61,7 +61,7 @@ public interface Download {
String failure();
/**
* Returns path to the downloaded file in case of successful download. The method will wait for the download to finish if
- * necessary.
+ * necessary. The method throws when connected remotely via {@link BrowserType#connect BrowserType.connect()}.
*/
Path path();
/**
diff --git a/playwright/src/main/java/com/microsoft/playwright/Frame.java b/playwright/src/main/java/com/microsoft/playwright/Frame.java
index 34a2f373..3f1a64a0 100644
--- a/playwright/src/main/java/com/microsoft/playwright/Frame.java
+++ b/playwright/src/main/java/com/microsoft/playwright/Frame.java
@@ -888,6 +888,33 @@ public interface Frame {
return this;
}
}
+ class WaitForURLOptions {
+ /**
+ * Maximum operation time in milliseconds, defaults to 30 seconds, pass {@code 0} to disable timeout. The default value can be
+ * changed by using the {@link BrowserContext#setDefaultNavigationTimeout BrowserContext.setDefaultNavigationTimeout()},
+ * {@link BrowserContext#setDefaultTimeout BrowserContext.setDefaultTimeout()}, {@link Page#setDefaultNavigationTimeout
+ * Page.setDefaultNavigationTimeout()} or {@link Page#setDefaultTimeout Page.setDefaultTimeout()} methods.
+ */
+ public Double timeout;
+ /**
+ * When to consider operation succeeded, defaults to {@code load}. Events can be either:
+ * {@code
+ * frame.click("a.delayed-navigation"); // Clicking the link will indirectly cause a navigation
+ * frame.waitForURL("**\/target.html");
+ * }
+ *
+ * @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation.
+ */
+ default void waitForURL(String url) {
+ waitForURL(url, null);
+ }
+ /**
+ * Waits for the frame to navigate to the given URL.
+ * {@code
+ * frame.click("a.delayed-navigation"); // Clicking the link will indirectly cause a navigation
+ * frame.waitForURL("**\/target.html");
+ * }
+ *
+ * @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation.
+ */
+ void waitForURL(String url, WaitForURLOptions options);
+ /**
+ * Waits for the frame to navigate to the given URL.
+ * {@code
+ * frame.click("a.delayed-navigation"); // Clicking the link will indirectly cause a navigation
+ * frame.waitForURL("**\/target.html");
+ * }
+ *
+ * @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation.
+ */
+ default void waitForURL(Pattern url) {
+ waitForURL(url, null);
+ }
+ /**
+ * Waits for the frame to navigate to the given URL.
+ * {@code
+ * frame.click("a.delayed-navigation"); // Clicking the link will indirectly cause a navigation
+ * frame.waitForURL("**\/target.html");
+ * }
+ *
+ * @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation.
+ */
+ void waitForURL(Pattern url, WaitForURLOptions options);
+ /**
+ * Waits for the frame to navigate to the given URL.
+ * {@code
+ * frame.click("a.delayed-navigation"); // Clicking the link will indirectly cause a navigation
+ * frame.waitForURL("**\/target.html");
+ * }
+ *
+ * @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation.
+ */
+ default void waitForURL(Predicate{@code
+ * frame.click("a.delayed-navigation"); // Clicking the link will indirectly cause a navigation
+ * frame.waitForURL("**\/target.html");
+ * }
+ *
+ * @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation.
+ */
+ void waitForURL(PredicatePage routes take precedence over browser context routes (set up with {@link BrowserContext#route * BrowserContext.route()}) when request matches both handlers. * + *
To remove a route with its handler you can use {@link Page#unroute Page.unroute()}. + * *
NOTE: Enabling routing disables http cache. * * @param url A glob pattern, regex pattern or predicate receiving [URL] to match while routing. @@ -3111,6 +3140,8 @@ public interface Page extends AutoCloseable { *
Page routes take precedence over browser context routes (set up with {@link BrowserContext#route * BrowserContext.route()}) when request matches both handlers. * + *
To remove a route with its handler you can use {@link Page#unroute Page.unroute()}. + * *
NOTE: Enabling routing disables http cache. * * @param url A glob pattern, regex pattern or predicate receiving [URL] to match while routing. @@ -3143,6 +3174,8 @@ public interface Page extends AutoCloseable { *
Page routes take precedence over browser context routes (set up with {@link BrowserContext#route * BrowserContext.route()}) when request matches both handlers. * + *
To remove a route with its handler you can use {@link Page#unroute Page.unroute()}. + * *
NOTE: Enabling routing disables http cache. * * @param url A glob pattern, regex pattern or predicate receiving [URL] to match while routing. @@ -3494,6 +3527,7 @@ public interface Page extends AutoCloseable { *
NOTE: {@link Page#setDefaultNavigationTimeout Page.setDefaultNavigationTimeout()} takes priority over {@link @@ -4410,6 +4444,84 @@ public interface Page extends AutoCloseable { * @param timeout A timeout to wait for */ void waitForTimeout(double timeout); + /** + * Waits for the main frame to navigate to the given URL. + *
{@code
+ * page.click("a.delayed-navigation"); // Clicking the link will indirectly cause a navigation
+ * page.waitForURL("**\/target.html");
+ * }
+ *
+ * Shortcut for main frame's {@link Frame#waitForURL Frame.waitForURL()}. + * + * @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. + */ + default void waitForURL(String url) { + waitForURL(url, null); + } + /** + * Waits for the main frame to navigate to the given URL. + *
{@code
+ * page.click("a.delayed-navigation"); // Clicking the link will indirectly cause a navigation
+ * page.waitForURL("**\/target.html");
+ * }
+ *
+ * Shortcut for main frame's {@link Frame#waitForURL Frame.waitForURL()}. + * + * @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. + */ + void waitForURL(String url, WaitForURLOptions options); + /** + * Waits for the main frame to navigate to the given URL. + *
{@code
+ * page.click("a.delayed-navigation"); // Clicking the link will indirectly cause a navigation
+ * page.waitForURL("**\/target.html");
+ * }
+ *
+ * Shortcut for main frame's {@link Frame#waitForURL Frame.waitForURL()}. + * + * @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. + */ + default void waitForURL(Pattern url) { + waitForURL(url, null); + } + /** + * Waits for the main frame to navigate to the given URL. + *
{@code
+ * page.click("a.delayed-navigation"); // Clicking the link will indirectly cause a navigation
+ * page.waitForURL("**\/target.html");
+ * }
+ *
+ * Shortcut for main frame's {@link Frame#waitForURL Frame.waitForURL()}. + * + * @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. + */ + void waitForURL(Pattern url, WaitForURLOptions options); + /** + * Waits for the main frame to navigate to the given URL. + *
{@code
+ * page.click("a.delayed-navigation"); // Clicking the link will indirectly cause a navigation
+ * page.waitForURL("**\/target.html");
+ * }
+ *
+ * Shortcut for main frame's {@link Frame#waitForURL Frame.waitForURL()}.
+ *
+ * @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation.
+ */
+ default void waitForURL(Predicate Shortcut for main frame's {@link Frame#waitForURL Frame.waitForURL()}.
+ *
+ * @param url A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation.
+ */
+ void waitForURL(Predicate{@code
+ * page.click("a.delayed-navigation"); // Clicking the link will indirectly cause a navigation
+ * page.waitForURL("**\/target.html");
+ * }
+ *
+ * {@code
* System.out.println(page.video().path());
* }
*/
public interface Video {
+ /**
+ * Deletes the video file. Will wait for the video to finish if necessary.
+ */
+ void delete();
/**
* Returns the file system path this video will be recorded to. The video is guaranteed to be written to the filesystem
- * upon closing the browser context.
+ * upon closing the browser context. This method throws when connected remotely via {@link BrowserType#connect
+ * BrowserType.connect()}.
*/
Path path();
+ /**
+ * Saves the video to a user-specified path. It is safe to call this method while the video is still in progress, or after
+ * the page has closed. This method waits until the page is closed and the video is fully saved.
+ *
+ * @param path Path where the video should be saved.
+ */
+ void saveAs(Path path);
}
diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/ArtifactImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/ArtifactImpl.java
new file mode 100644
index 00000000..2f5a0c5c
--- /dev/null
+++ b/playwright/src/main/java/com/microsoft/playwright/impl/ArtifactImpl.java
@@ -0,0 +1,75 @@
+/*
+ * 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 com.google.gson.JsonObject;
+import com.microsoft.playwright.PlaywrightException;
+
+import java.io.InputStream;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+
+import static com.microsoft.playwright.impl.Utils.writeToFile;
+
+class ArtifactImpl extends ChannelOwner {
+ boolean isRemote;
+ public ArtifactImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
+ super(parent, type, guid, initializer);
+ }
+
+ public InputStream createReadStream() {
+ JsonObject result = sendMessage("stream").getAsJsonObject();
+ if (!result.has("stream")) {
+ return null;
+ }
+ Stream stream = connection.getExistingObject(result.getAsJsonObject("stream").get("guid").getAsString());
+ return stream.stream();
+ }
+
+ public void delete() {
+ sendMessage("delete");
+ }
+
+ public String failure() {
+ JsonObject result = sendMessage("failure").getAsJsonObject();
+ if (result.has("error")) {
+ return result.get("error").getAsString();
+ }
+ return null;
+ }
+
+ public Path pathAfterFinished() {
+ if (isRemote) {
+ throw new PlaywrightException("Path is not available when using browserType.connect(). Use download.saveAs() to save a local copy.");
+ }
+ JsonObject json = sendMessage("pathAfterFinished").getAsJsonObject();
+ return FileSystems.getDefault().getPath(json.get("value").getAsString());
+ }
+
+ public void saveAs(Path path) {
+ if (isRemote) {
+ JsonObject jsonObject = sendMessage("saveAsStream").getAsJsonObject();
+ Stream stream = connection.getExistingObject(jsonObject.getAsJsonObject("stream").get("guid").getAsString());
+ writeToFile(stream.stream(), path);
+ return;
+ }
+
+ JsonObject params = new JsonObject();
+ params.addProperty("path", path.toString());
+ sendMessage("saveAs", params);
+ }
+}
diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/Connection.java b/playwright/src/main/java/com/microsoft/playwright/impl/Connection.java
index a1d1175b..105b1a14 100644
--- a/playwright/src/main/java/com/microsoft/playwright/impl/Connection.java
+++ b/playwright/src/main/java/com/microsoft/playwright/impl/Connection.java
@@ -255,6 +255,9 @@ public class Connection {
case "AndroidDevice":
// result = new AndroidDevice(parent, type, guid, initializer);
break;
+ case "Artifact":
+ result = new ArtifactImpl(parent, type, guid, initializer);
+ break;
case "BindingCall":
result = new BindingCall(parent, type, guid, initializer);
break;
@@ -273,9 +276,6 @@ public class Connection {
case "Dialog":
result = new DialogImpl(parent, type, guid, initializer);
break;
- case "Download":
- result = new DownloadImpl(parent, type, guid, initializer);
- break;
case "Electron":
// result = new Playwright(parent, type, guid, initializer);
break;
diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/DownloadImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/DownloadImpl.java
index abe524c8..e2bc1e31 100644
--- a/playwright/src/main/java/com/microsoft/playwright/impl/DownloadImpl.java
+++ b/playwright/src/main/java/com/microsoft/playwright/impl/DownloadImpl.java
@@ -16,27 +16,19 @@
package com.microsoft.playwright.impl;
-import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
-import com.microsoft.playwright.BrowserContext;
import com.microsoft.playwright.Download;
-import com.microsoft.playwright.PlaywrightException;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
import java.io.InputStream;
-import java.nio.file.FileSystems;
import java.nio.file.Path;
-import static com.microsoft.playwright.impl.Utils.writeToFile;
+class DownloadImpl extends LoggingSupport implements Download {
+ private final ArtifactImpl artifact;
+ private final JsonObject initializer;
-public class DownloadImpl extends ChannelOwner implements Download {
- private final BrowserImpl browser;
-
- public DownloadImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
- super(parent, type, guid, initializer);
- browser = ((BrowserContextImpl) parent).browser();
+ DownloadImpl(ArtifactImpl artifact, JsonObject initializer) {
+ this.artifact = artifact;
+ this.initializer = initializer;
}
@Override
@@ -51,58 +43,26 @@ public class DownloadImpl extends ChannelOwner implements Download {
@Override
public InputStream createReadStream() {
- return withLogging("Download.createReadStream", () -> {
- JsonObject result = sendMessage("stream").getAsJsonObject();
- if (!result.has("stream")) {
- return null;
- }
- Stream stream = connection.getExistingObject(result.getAsJsonObject("stream").get("guid").getAsString());
- return stream.stream();
- });
+ return withLogging("Download.createReadStream", () -> artifact.createReadStream());
}
@Override
public void delete() {
- withLogging("Download.delete", () -> {
- sendMessage("delete");
- });
+ withLogging("Download.delete", () -> artifact.delete());
}
@Override
public String failure() {
- return withLogging("Download.failure", () -> {
- JsonObject result = sendMessage("failure").getAsJsonObject();
- if (result.has("error")) {
- return result.get("error").getAsString();
- }
- return null;
- });
+ return withLogging("Download.failure", () -> artifact.failure());
}
@Override
public Path path() {
- return withLogging("Download.path", () -> {
- if (browser != null && browser.isRemote) {
- throw new PlaywrightException("Path is not available when using browserType.connect(). Use download.saveAs() to save a local copy.");
- }
- JsonObject json = sendMessage("path").getAsJsonObject();
- return FileSystems.getDefault().getPath(json.get("value").getAsString());
- });
+ return withLogging("Download.path", () -> artifact.pathAfterFinished());
}
@Override
public void saveAs(Path path) {
- withLogging("Download.saveAs", () -> {
- if (browser != null && browser.isRemote) {
- JsonObject jsonObject = sendMessage("saveAsStream").getAsJsonObject();
- Stream stream = connection.getExistingObject(jsonObject.getAsJsonObject("stream").get("guid").getAsString());
- writeToFile(stream.stream(), path);
- return;
- }
-
- JsonObject params = new JsonObject();
- params.addProperty("path", path.toString());
- sendMessage("saveAs", params);
- });
+ withLogging("Download.saveAs", () -> artifact.saveAs(path));
}
}
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 b153f16c..b3ee4a9a 100644
--- a/playwright/src/main/java/com/microsoft/playwright/impl/FrameImpl.java
+++ b/playwright/src/main/java/com/microsoft/playwright/impl/FrameImpl.java
@@ -28,6 +28,8 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.regex.Pattern;
import static com.microsoft.playwright.options.LoadState.*;
import static com.microsoft.playwright.impl.Serialization.*;
@@ -856,10 +858,14 @@ public class FrameImpl extends ChannelOwner implements Frame {
@Override
public Response waitForNavigation(WaitForNavigationOptions options, Runnable code) {
- return withLogging("Frame.waitForNavigation", () -> waitForNavigationImpl(code, options));
+ return withLogging("Frame.waitForNavigation", () -> waitForNavigationImpl(code, options, null));
}
Response waitForNavigationImpl(Runnable code, WaitForNavigationOptions options) {
+ return waitForNavigationImpl(code, options, null);
+ }
+
+ private Response waitForNavigationImpl(Runnable code, WaitForNavigationOptions options, UrlMatcher matcher) {
if (options == null) {
options = new WaitForNavigationOptions();
}
@@ -868,7 +874,9 @@ public class FrameImpl extends ChannelOwner implements Frame {
}
List