diff --git a/README.md b/README.md index 8df5008d..b24022c4 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Playwright is a Java library to automate [Chromium](https://www.chromium.org/Hom | | Linux | macOS | Windows | | :--- | :---: | :---: | :---: | -| Chromium 111.0.5563.19 | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| Chromium 111.0.5563.64 | :white_check_mark: | :white_check_mark: | :white_check_mark: | | WebKit 16.4 | ✅ | ✅ | ✅ | | Firefox 109.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | diff --git a/playwright/src/main/java/com/microsoft/playwright/BrowserContext.java b/playwright/src/main/java/com/microsoft/playwright/BrowserContext.java index 675b2236..2c544569 100644 --- a/playwright/src/main/java/com/microsoft/playwright/BrowserContext.java +++ b/playwright/src/main/java/com/microsoft/playwright/BrowserContext.java @@ -175,6 +175,18 @@ public interface BrowserContext extends AutoCloseable { } } class RouteFromHAROptions { + /** + * Optional setting to control resource content management. If {@code omit} is specified, content is not persisted. If + * {@code attach} is specified, resources are persisted as separate files or entries in the ZIP archive. If {@code embed} + * is specified, content is stored inline the HAR file + */ + public HarContentPolicy content; + /** + * When set to {@code minimal}, only record information necessary for routing from HAR. This omits sizes, timing, page, + * cookies, security and other types of HAR information that are not used when replaying from HAR. Defaults to {@code + * minimal}. + */ + public HarMode mode; /** *
**Usage** - * - *
This method waits for the frame to navigate to a new URL. It is useful for when you run code which will indirectly cause - * the frame to navigate. Consider this example: - *
{@code
- * // The method returns after navigation has finished
- * frame.waitForNavigation(() -> {
- * // Clicking the link will indirectly cause a navigation
- * frame.click("a.delayed-navigation");
- * });
- * }
- *
- * NOTE: Usage of the History API to change the URL is - * considered a navigation. + * @deprecated This method is inherently racy, please use {@link Frame#waitForURL Frame.waitForURL()} instead. * * @param callback Callback that performs the action triggering the event. * @since v1.8 @@ -4912,24 +4895,7 @@ public interface Frame { return waitForNavigation(null, callback); } /** - * Waits for the frame navigation and returns the main resource response. In case of multiple redirects, the navigation - * will resolve with the response of the last redirect. In case of navigation to a different anchor or navigation due to - * History API usage, the navigation will resolve with {@code null}. - * - *
**Usage** - * - *
This method waits for the frame to navigate to a new URL. It is useful for when you run code which will indirectly cause - * the frame to navigate. Consider this example: - *
{@code
- * // The method returns after navigation has finished
- * frame.waitForNavigation(() -> {
- * // Clicking the link will indirectly cause a navigation
- * frame.click("a.delayed-navigation");
- * });
- * }
- *
- * NOTE: Usage of the History API to change the URL is - * considered a navigation. + * @deprecated This method is inherently racy, please use {@link Frame#waitForURL Frame.waitForURL()} instead. * * @param callback Callback that performs the action triggering the event. * @since v1.8 diff --git a/playwright/src/main/java/com/microsoft/playwright/FrameLocator.java b/playwright/src/main/java/com/microsoft/playwright/FrameLocator.java index bb369f6a..32dfeba6 100644 --- a/playwright/src/main/java/com/microsoft/playwright/FrameLocator.java +++ b/playwright/src/main/java/com/microsoft/playwright/FrameLocator.java @@ -899,11 +899,11 @@ public interface FrameLocator { * *
Learn more about locators. * - * @param selector A selector to use when resolving DOM element. + * @param selectorOrLocator A selector or locator to use when resolving DOM element. * @since v1.17 */ - default Locator locator(String selector) { - return locator(selector, null); + default Locator locator(String selectorOrLocator) { + return locator(selectorOrLocator, null); } /** * The method finds an element matching the specified selector in the locator's subtree. It also accepts filter options, @@ -911,10 +911,32 @@ public interface FrameLocator { * *
Learn more about locators. * - * @param selector A selector to use when resolving DOM element. + * @param selectorOrLocator A selector or locator to use when resolving DOM element. * @since v1.17 */ - Locator locator(String selector, LocatorOptions options); + Locator locator(String selectorOrLocator, LocatorOptions options); + /** + * The method finds an element matching the specified selector in the locator's subtree. It also accepts filter options, + * similar to {@link Locator#filter Locator.filter()} method. + * + *
Learn more about locators. + * + * @param selectorOrLocator A selector or locator to use when resolving DOM element. + * @since v1.17 + */ + default Locator locator(Locator selectorOrLocator) { + return locator(selectorOrLocator, null); + } + /** + * The method finds an element matching the specified selector in the locator's subtree. It also accepts filter options, + * similar to {@link Locator#filter Locator.filter()} method. + * + *
Learn more about locators. + * + * @param selectorOrLocator A selector or locator to use when resolving DOM element. + * @since v1.17 + */ + Locator locator(Locator selectorOrLocator, LocatorOptions options); /** * Returns locator to the n-th matching frame. It's zero based, {@code nth(0)} selects the first frame. * diff --git a/playwright/src/main/java/com/microsoft/playwright/Locator.java b/playwright/src/main/java/com/microsoft/playwright/Locator.java index e2574530..c00babb8 100644 --- a/playwright/src/main/java/com/microsoft/playwright/Locator.java +++ b/playwright/src/main/java/com/microsoft/playwright/Locator.java @@ -2821,10 +2821,10 @@ public interface Locator { * locator.click(); * } * - * @param selector A selector to use when resolving DOM element. + * @param selectorOrLocator A selector to use when resolving DOM element. * @since v1.17 */ - FrameLocator frameLocator(String selector); + FrameLocator frameLocator(String selectorOrLocator); /** * Returns the matching element's attribute value. * @@ -3683,11 +3683,11 @@ public interface Locator { * *
Learn more about locators. * - * @param selector A selector to use when resolving DOM element. + * @param selectorOrLocator A selector or locator to use when resolving DOM element. * @since v1.14 */ - default Locator locator(String selector) { - return locator(selector, null); + default Locator locator(String selectorOrLocator) { + return locator(selectorOrLocator, null); } /** * The method finds an element matching the specified selector in the locator's subtree. It also accepts filter options, @@ -3695,10 +3695,32 @@ public interface Locator { * *
Learn more about locators. * - * @param selector A selector to use when resolving DOM element. + * @param selectorOrLocator A selector or locator to use when resolving DOM element. * @since v1.14 */ - Locator locator(String selector, LocatorOptions options); + Locator locator(String selectorOrLocator, LocatorOptions options); + /** + * The method finds an element matching the specified selector in the locator's subtree. It also accepts filter options, + * similar to {@link Locator#filter Locator.filter()} method. + * + *
Learn more about locators. + * + * @param selectorOrLocator A selector or locator to use when resolving DOM element. + * @since v1.14 + */ + default Locator locator(Locator selectorOrLocator) { + return locator(selectorOrLocator, null); + } + /** + * The method finds an element matching the specified selector in the locator's subtree. It also accepts filter options, + * similar to {@link Locator#filter Locator.filter()} method. + * + *
Learn more about locators. + * + * @param selectorOrLocator A selector or locator to use when resolving DOM element. + * @since v1.14 + */ + Locator locator(Locator selectorOrLocator, LocatorOptions options); /** * Returns locator to the n-th matching element. It's zero based, {@code nth(0)} selects the first element. * diff --git a/playwright/src/main/java/com/microsoft/playwright/Page.java b/playwright/src/main/java/com/microsoft/playwright/Page.java index 6d149101..528d3537 100644 --- a/playwright/src/main/java/com/microsoft/playwright/Page.java +++ b/playwright/src/main/java/com/microsoft/playwright/Page.java @@ -2250,6 +2250,8 @@ public interface Page extends AutoCloseable { } } class RouteFromHAROptions { + public HarContentPolicy content; + public HarMode mode; /** *
**Usage** *
{@code
- * Locator locator = page.locator("button.submit");
+ * Locator locator = page.getByRole(AriaRole.BUTTON);
* // Make sure at least some part of element intersects viewport.
* assertThat(locator).isInViewport();
* // Make sure element is fully outside of viewport.
@@ -600,7 +600,7 @@ public interface LocatorAssertions {
*
* **Usage**
*
{@code
- * Locator locator = page.locator("button.submit");
+ * Locator locator = page.getByRole(AriaRole.BUTTON);
* // Make sure at least some part of element intersects viewport.
* assertThat(locator).isInViewport();
* // Make sure element is fully outside of viewport.
diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/CallMetadata.java b/playwright/src/main/java/com/microsoft/playwright/impl/CallMetadata.java
new file mode 100644
index 00000000..baf39e59
--- /dev/null
+++ b/playwright/src/main/java/com/microsoft/playwright/impl/CallMetadata.java
@@ -0,0 +1,8 @@
+package com.microsoft.playwright.impl;
+
+import com.google.gson.JsonArray;
+
+class CallMetadata {
+ int id;
+ JsonArray stack;
+}
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 8314388f..3f48bf56 100644
--- a/playwright/src/main/java/com/microsoft/playwright/impl/Connection.java
+++ b/playwright/src/main/java/com/microsoft/playwright/impl/Connection.java
@@ -16,6 +16,7 @@
package com.microsoft.playwright.impl;
import com.google.gson.Gson;
+import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.microsoft.playwright.Playwright;
@@ -24,10 +25,10 @@ import com.microsoft.playwright.TimeoutError;
import java.io.IOException;
import java.time.Duration;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
import static com.microsoft.playwright.impl.Serialization.gson;
+import static java.lang.System.currentTimeMillis;
class Message {
int id;
@@ -67,6 +68,7 @@ public class Connection {
}
LocalUtils localUtils;
final Map env;
+ private Set> stackCollectors = Collections.newSetFromMap(new IdentityHashMap<>());
class Root extends ChannelOwner {
Root(Connection connection) {
@@ -101,8 +103,15 @@ public class Connection {
stackTraceCollector = StackTraceCollector.createFromEnv(env);
}
- boolean isCollectingStacks() {
- return stackTraceCollector != null;
+ void startCollectingCallMetadata(List collection) {
+ if (stackTraceCollector == null) {
+ throw new PlaywrightException("Source root directory must be specified via PLAYWRIGHT_JAVA_SRC environment variable when source collection is enabled");
+ }
+ stackCollectors.add(collection);
+ }
+
+ void stopCollectingCallMetadata(List collection) {
+ stackCollectors.remove(collection);
}
String setApiName(String name) {
@@ -133,6 +142,7 @@ public class Connection {
message.addProperty("method", method);
message.add("params", params);
JsonObject metadata = new JsonObject();
+ metadata.addProperty("wallTime", currentTimeMillis());
if (apiName == null) {
metadata.addProperty("internal", true);
} else {
@@ -140,7 +150,21 @@ public class Connection {
// All but first message in an API call are considered internal and will be hidden from the inspector.
apiName = null;
if (stackTraceCollector != null) {
- metadata.add("stack", stackTraceCollector.currentStackTrace());
+ JsonArray stack = stackTraceCollector.currentStackTrace();
+ CallMetadata callMetadata = new CallMetadata();
+ callMetadata.id = id;
+ callMetadata.stack = stack;
+ for (List collector : stackCollectors) {
+ collector.add(callMetadata);
+ }
+ if (!stack.isEmpty()) {
+ JsonObject location = new JsonObject();
+ JsonObject frame = stack.get(0).getAsJsonObject();
+ location.addProperty("file", frame.get("file").getAsString());
+ location.addProperty("line", frame.get("line").getAsInt());
+ location.addProperty("column", frame.get("column").getAsInt());
+ metadata.add("location", location);
+ }
}
}
message.add("metadata", metadata);
diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/FrameLocatorImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/FrameLocatorImpl.java
index 372e0a94..c28f8e13 100644
--- a/playwright/src/main/java/com/microsoft/playwright/impl/FrameLocatorImpl.java
+++ b/playwright/src/main/java/com/microsoft/playwright/impl/FrameLocatorImpl.java
@@ -18,6 +18,7 @@ package com.microsoft.playwright.impl;
import com.microsoft.playwright.FrameLocator;
import com.microsoft.playwright.Locator;
+import com.microsoft.playwright.PlaywrightException;
import com.microsoft.playwright.options.AriaRole;
import java.util.regex.Pattern;
@@ -119,6 +120,15 @@ class FrameLocatorImpl implements FrameLocator {
return new LocatorImpl(frame, frameSelector + " >> internal:control=enter-frame >> " + selector, convertType(options, Locator.LocatorOptions.class));
}
+ @Override
+ public Locator locator(Locator selectorOrLocator, LocatorOptions options) {
+ LocatorImpl other = (LocatorImpl) selectorOrLocator;
+ if (other.frame != frame) {
+ throw new PlaywrightException("Locators must belong to the same frame.");
+ }
+ return locator(other.selector, options);
+ }
+
@Override
public FrameLocator nth(int index) {
return new FrameLocatorImpl(frame, frameSelector + " >> nth=" + index);
diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/LocalUtils.java b/playwright/src/main/java/com/microsoft/playwright/impl/LocalUtils.java
index 09db1ad8..00e4be94 100644
--- a/playwright/src/main/java/com/microsoft/playwright/impl/LocalUtils.java
+++ b/playwright/src/main/java/com/microsoft/playwright/impl/LocalUtils.java
@@ -20,16 +20,22 @@ import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import java.nio.file.Path;
+import java.util.List;
+
+import static com.microsoft.playwright.impl.Serialization.gson;
class LocalUtils extends ChannelOwner {
LocalUtils(ChannelOwner parent, String type, String guid, JsonObject initializer) {
super(parent, type, guid, initializer);
}
- void zip(Path zipFile, JsonArray entries) {
+ void zip(Path zipFile, JsonArray entries, List metadata, boolean appendMode, boolean includeSources) {
JsonObject params = new JsonObject();
params.addProperty("zipFile", zipFile.toString());
params.add("entries", entries);
+ params.addProperty("mode", appendMode ? "append" : "write");
+ params.add("metadata", gson().toJsonTree(metadata));
+ params.addProperty("includeSources", includeSources);
sendMessage("zip", params);
}
}
diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java
index 2ae21a9f..210cd1e7 100644
--- a/playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java
+++ b/playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java
@@ -20,8 +20,8 @@ import static com.microsoft.playwright.impl.Utils.convertType;
import static com.microsoft.playwright.impl.Utils.toJsRegexFlags;
class LocatorImpl implements Locator {
- private final FrameImpl frame;
- private final String selector;
+ final FrameImpl frame;
+ final String selector;
public LocatorImpl(FrameImpl frame, String selector, LocatorOptions options) {
this.frame = frame;
@@ -384,6 +384,15 @@ class LocatorImpl implements Locator {
return new LocatorImpl(frame, this.selector + " >> " + selector, options);
}
+ @Override
+ public Locator locator(Locator selectorOrLocator, LocatorOptions options) {
+ LocatorImpl other = (LocatorImpl) selectorOrLocator;
+ if (other.frame != frame) {
+ throw new PlaywrightException("Locators must belong to the same frame.");
+ }
+ return locator(other.selector, options);
+ }
+
@Override
public Locator nth(int index) {
return new LocatorImpl(frame, selector + " >> nth=" + index, null);
diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/StackTraceCollector.java b/playwright/src/main/java/com/microsoft/playwright/impl/StackTraceCollector.java
index af6e26b4..861971c7 100644
--- a/playwright/src/main/java/com/microsoft/playwright/impl/StackTraceCollector.java
+++ b/playwright/src/main/java/com/microsoft/playwright/impl/StackTraceCollector.java
@@ -118,6 +118,7 @@ class StackTraceCollector {
JsonObject jsonFrame = new JsonObject();
jsonFrame.addProperty("file", sourceFile(frame));
jsonFrame.addProperty("line", frame.getLineNumber());
+ jsonFrame.addProperty("column", 0);
jsonFrame.addProperty("function", frame.getClassName() + "." + frame.getMethodName());
jsonStack.add(jsonFrame);
}
diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/TracingImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/TracingImpl.java
index f4fceb72..c2eacb06 100644
--- a/playwright/src/main/java/com/microsoft/playwright/impl/TracingImpl.java
+++ b/playwright/src/main/java/com/microsoft/playwright/impl/TracingImpl.java
@@ -22,26 +22,45 @@ import com.microsoft.playwright.PlaywrightException;
import com.microsoft.playwright.Tracing;
import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
import static com.microsoft.playwright.impl.Serialization.gson;
class TracingImpl extends ChannelOwner implements Tracing {
+ private boolean includeSources;
+ private List metadataCollector = new ArrayList<>();
+
TracingImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
super(parent, type, guid, initializer);
}
private void stopChunkImpl(Path path) {
+ connection.stopCollectingCallMetadata(metadataCollector);
+ List metadata = metadataCollector;
+ metadataCollector = new ArrayList<>();
+
JsonObject params = new JsonObject();
- String mode = "doNotSave";
- if (path != null) {
- if (connection.isRemote) {
- mode = "compressTrace";
- } else {
- mode = "compressTraceAndSources";
- }
+
+ // Not interested in artifacts.
+ if (path == null) {
+ params.addProperty("mode", "discard");
+ sendMessage("tracingStopChunk", params);
+ return;
}
- params.addProperty("mode", mode);
+
+ boolean isLocal = !connection.isRemote;
+ if (isLocal) {
+ params.addProperty("mode", "entries");
+ JsonObject json = sendMessage("tracingStopChunk", params).getAsJsonObject();
+ JsonArray entries = json.getAsJsonArray("entries");
+ connection.localUtils.zip(path, entries, metadata, false, includeSources);
+ return;
+ }
+
+ params.addProperty("mode", "archive");
JsonObject json = sendMessage("tracingStopChunk", params).getAsJsonObject();
+ // The artifact may be missing if the browser closed while stopping tracing.
if (!json.has("artifact")) {
return;
}
@@ -52,9 +71,9 @@ class TracingImpl extends ChannelOwner implements Tracing {
// Add local sources to the remote trace if necessary.
// In case of CDP connection since the connection is established by
// the driver it is safe to consider the artifact local.
- if (connection.isRemote && json.has("sourceEntries")) {
- JsonArray entries = json.getAsJsonArray("sourceEntries");
- connection.localUtils.zip(path, entries);
+ if (json.has("entries")) {
+ JsonArray entries = json.getAsJsonArray("entries");
+ connection.localUtils.zip(path, entries, metadata, true, includeSources);
}
}
@@ -74,6 +93,10 @@ class TracingImpl extends ChannelOwner implements Tracing {
if (options == null) {
options = new StartChunkOptions();
}
+ if (includeSources) {
+ metadataCollector = new ArrayList<>();
+ connection.startCollectingCallMetadata(metadataCollector);
+ }
JsonObject params = gson().toJsonTree(options).getAsJsonObject();
sendMessage("tracingStartChunk", params);
}
@@ -83,11 +106,10 @@ class TracingImpl extends ChannelOwner implements Tracing {
options = new StartOptions();
}
JsonObject params = gson().toJsonTree(options).getAsJsonObject();
- boolean includeSources = options.sources != null && options.sources;
+ includeSources = options.sources != null && options.sources;
if (includeSources) {
- if (!connection.isCollectingStacks()) {
- throw new PlaywrightException("Source root directory must be specified via PLAYWRIGHT_JAVA_SRC environment variable when source collection is enabled");
- }
+ metadataCollector = new ArrayList<>();
+ connection.startCollectingCallMetadata(metadataCollector);
params.addProperty("sources", true);
}
sendMessage("tracingStart", params);
diff --git a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextHar.java b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextHar.java
index e5e15ab8..ba906464 100644
--- a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextHar.java
+++ b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextHar.java
@@ -38,6 +38,7 @@ import static com.microsoft.playwright.Utils.copy;
import static com.microsoft.playwright.Utils.extractZip;
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
import static com.microsoft.playwright.options.HarContentPolicy.ATTACH;
+import static com.microsoft.playwright.options.HarContentPolicy.EMBED;
import static org.junit.jupiter.api.Assertions.*;
public class TestBrowserContextHar extends TestBase {
@@ -430,6 +431,24 @@ public class TestBrowserContextHar extends TestBase {
}
}
+ @Test
+ void shouldUpdateHarZipForPageWithDifferentOptions(@TempDir Path tmpDir) {
+ Path harPath = tmpDir.resolve("har.zip");
+ try (BrowserContext context1 = browser.newContext()) {
+ Page page1 = context1.newPage();
+ page1.routeFromHAR(harPath, new Page.RouteFromHAROptions().setUpdate(true).setContent(EMBED).setMode(HarMode.FULL));
+ page1.navigate(server.PREFIX + "/one-style.html");
+ }
+
+ try (BrowserContext context2 = browser.newContext()) {
+ Page page2 = context2.newPage();
+ page2.routeFromHAR(harPath, new Page.RouteFromHAROptions().setNotFound(HarNotFound.ABORT));
+ page2.navigate(server.PREFIX + "/one-style.html");
+ assertTrue(page2.content().contains("hello, world!"));
+ assertThat(page2.locator("body")).hasCSS("background-color", "rgb(255, 192, 203)");
+ }
+ }
+
@Test
void shouldUpdateExtractedHarZipForPage(@TempDir Path tmpDir) {
Path harPath = tmpDir.resolve("har.har");
diff --git a/playwright/src/test/java/com/microsoft/playwright/TestElementHandleSelectText.java b/playwright/src/test/java/com/microsoft/playwright/TestElementHandleSelectText.java
index 46e66d32..3b797669 100644
--- a/playwright/src/test/java/com/microsoft/playwright/TestElementHandleSelectText.java
+++ b/playwright/src/test/java/com/microsoft/playwright/TestElementHandleSelectText.java
@@ -12,7 +12,7 @@ public class TestElementHandleSelectText extends TestBase {
ElementHandle textarea = page.querySelector("textarea");
textarea.evaluate("textarea => textarea.value = 'some value'");
textarea.selectText();
- if (isFirefox()) {
+ if (isFirefox() || isWebKit()) {
assertEquals(0, textarea.evaluate("el => el.selectionStart"));
assertEquals(10, textarea.evaluate("el => el.selectionEnd"));
} else {
@@ -26,7 +26,7 @@ public class TestElementHandleSelectText extends TestBase {
ElementHandle input = page.querySelector("input");
input.evaluate("input => input.value = 'some value'");
input.selectText();
- if (isFirefox()) {
+ if (isFirefox() || isWebKit()) {
assertEquals(0, input.evaluate("el => el.selectionStart"));
assertEquals(10, input.evaluate("el => el.selectionEnd"));
} else {
diff --git a/playwright/src/test/java/com/microsoft/playwright/TestLocatorMisc.java b/playwright/src/test/java/com/microsoft/playwright/TestLocatorMisc.java
index 23d09f16..0bef19ef 100644
--- a/playwright/src/test/java/com/microsoft/playwright/TestLocatorMisc.java
+++ b/playwright/src/test/java/com/microsoft/playwright/TestLocatorMisc.java
@@ -102,4 +102,18 @@ public class TestLocatorMisc extends TestBase{
assertTrue(blurred[0]);
assertEquals(false, button.evaluate("button => document.activeElement === button"));
}
+ @Test
+ void LocatorLocatorAndFrameLocatorLocatorShouldAcceptLocator() {
+ page.setContent("\n" +
+ " \n");
+ Locator inputLocator = page.locator("input");
+ assertEquals("outer", inputLocator.inputValue());
+ assertEquals("outer", page.locator("div").locator(inputLocator).inputValue());
+ assertEquals("inner", page.frameLocator("iframe").locator(inputLocator).inputValue());
+ assertEquals("inner", page.frameLocator("iframe").locator("div").locator(inputLocator).inputValue());
+
+ Locator divLocator = page.locator("div");
+ assertEquals("outer", divLocator.locator("input").inputValue());
+ assertEquals("inner", page.frameLocator("iframe").locator(divLocator).locator("input").inputValue());
+ }
}
diff --git a/scripts/CLI_VERSION b/scripts/CLI_VERSION
index b78197a0..45edcbe2 100644
--- a/scripts/CLI_VERSION
+++ b/scripts/CLI_VERSION
@@ -1 +1 @@
-1.31.0-beta-1676596096000
+1.32.0-alpha-1678387519000