chore: roll 1.54.0-alpha-2025-07-09 (#1817)
This commit is contained in:
@@ -10,9 +10,9 @@ Playwright is a Java library to automate [Chromium](https://www.chromium.org/Hom
|
||||
|
||||
| | Linux | macOS | Windows |
|
||||
| :--- | :---: | :---: | :---: |
|
||||
| Chromium <!-- GEN:chromium-version -->138.0.7204.23<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| Chromium <!-- GEN:chromium-version -->139.0.7258.5<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| WebKit <!-- GEN:webkit-version -->18.5<!-- GEN:stop --> | ✅ | ✅ | ✅ |
|
||||
| Firefox <!-- GEN:firefox-version -->139.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| Firefox <!-- GEN:firefox-version -->140.0.2<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
<name>Playwright Client Examples</name>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<playwright.version>1.53.0</playwright.version>
|
||||
<playwright.version>1.54.0</playwright.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
||||
@@ -596,7 +596,8 @@ public interface BrowserContext extends AutoCloseable {
|
||||
*/
|
||||
List<Page> backgroundPages();
|
||||
/**
|
||||
* Returns the browser instance of the context. If it was launched as a persistent context null gets returned.
|
||||
* Gets the browser instance that owns the context. Returns {@code null} if the context is created outside of normal
|
||||
* browser, e.g. Android or Electron.
|
||||
*
|
||||
* @since v1.8
|
||||
*/
|
||||
@@ -871,6 +872,7 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* <li> {@code "notifications"}</li>
|
||||
* <li> {@code "payment-handler"}</li>
|
||||
* <li> {@code "storage-access"}</li>
|
||||
* <li> {@code "local-fonts"}</li>
|
||||
* </ul>
|
||||
* @since v1.8
|
||||
*/
|
||||
@@ -903,6 +905,7 @@ public interface BrowserContext extends AutoCloseable {
|
||||
* <li> {@code "notifications"}</li>
|
||||
* <li> {@code "payment-handler"}</li>
|
||||
* <li> {@code "storage-access"}</li>
|
||||
* <li> {@code "local-fonts"}</li>
|
||||
* </ul>
|
||||
* @since v1.8
|
||||
*/
|
||||
|
||||
@@ -21,6 +21,11 @@ import com.microsoft.playwright.options.*;
|
||||
/**
|
||||
* The Mouse class operates in main-frame CSS pixels relative to the top-left corner of the viewport.
|
||||
*
|
||||
* <p> <strong>NOTE:</strong> If you want to debug where the mouse moved, you can use the <a
|
||||
* href="https://playwright.dev/java/docs/trace-viewer-intro">Trace viewer</a> or <a
|
||||
* href="https://playwright.dev/java/docs/running-tests">Playwright Inspector</a>. A red dot showing the location of the
|
||||
* mouse will be shown for every mouse action.
|
||||
*
|
||||
* <p> Every {@code page} object has its own Mouse, accessible with {@link com.microsoft.playwright.Page#mouse Page.mouse()}.
|
||||
* <pre>{@code
|
||||
* // Using ‘page.mouse’ to trace a 100x100 square.
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.microsoft.playwright.impl;
|
||||
|
||||
import com.microsoft.playwright.PlaywrightException;
|
||||
import org.opentest4j.AssertionFailedError;
|
||||
import org.opentest4j.ValueWrapper;
|
||||
|
||||
@@ -29,12 +28,10 @@ import java.util.stream.Collectors;
|
||||
import static com.microsoft.playwright.impl.Utils.toJsRegexFlags;
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
class AssertionsBase {
|
||||
final LocatorImpl actualLocator;
|
||||
abstract class AssertionsBase {
|
||||
final boolean isNot;
|
||||
|
||||
AssertionsBase(LocatorImpl actual, boolean isNot) {
|
||||
this.actualLocator = actual;
|
||||
AssertionsBase(boolean isNot) {
|
||||
this.isNot = isNot;
|
||||
}
|
||||
|
||||
@@ -58,7 +55,7 @@ class AssertionsBase {
|
||||
if (isNot) {
|
||||
message = message.replace("expected to", "expected not to");
|
||||
}
|
||||
FrameExpectResult result = actualLocator.expect(expression, expectOptions, title);
|
||||
FrameExpectResult result = doExpect(expression, expectOptions, title);
|
||||
if (result.matches == isNot) {
|
||||
Object actual = result.received == null ? null : Serialization.deserialize(result.received);
|
||||
String log = (result.log == null) ? "" : String.join("\n", result.log);
|
||||
@@ -75,7 +72,9 @@ class AssertionsBase {
|
||||
}
|
||||
}
|
||||
|
||||
private static ValueWrapper formatValue(Object value) {
|
||||
abstract FrameExpectResult doExpect(String expression, FrameExpectOptions expectOptions, String title);
|
||||
|
||||
protected static ValueWrapper formatValue(Object value) {
|
||||
if (value == null || !value.getClass().isArray()) {
|
||||
return ValueWrapper.create(value);
|
||||
}
|
||||
|
||||
@@ -506,7 +506,7 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
|
||||
|
||||
void recordIntoHar(PageImpl page, Path har, RouteFromHAROptions options, HarContentPolicy contentPolicy) {
|
||||
if (contentPolicy == null) {
|
||||
contentPolicy = Utils.convertType(options.updateContent, HarContentPolicy.class);;
|
||||
contentPolicy = Utils.convertType(options.updateContent, HarContentPolicy.class);
|
||||
}
|
||||
if (contentPolicy == null) {
|
||||
contentPolicy = HarContentPolicy.ATTACH;
|
||||
|
||||
@@ -20,13 +20,10 @@ import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.microsoft.playwright.ConsoleMessage;
|
||||
import com.microsoft.playwright.JSHandle;
|
||||
import com.microsoft.playwright.Page;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.microsoft.playwright.impl.Serialization.gson;
|
||||
|
||||
public class ConsoleMessageImpl implements ConsoleMessage {
|
||||
private final Connection connection;
|
||||
private PageImpl page;
|
||||
|
||||
@@ -993,7 +993,8 @@ public class FrameImpl extends ChannelOwner implements Frame {
|
||||
@Override
|
||||
public void waitForTimeout(double timeout) {
|
||||
JsonObject params = new JsonObject();
|
||||
sendMessage("waitForTimeout", params, timeout);
|
||||
params.addProperty("waitTimeout", timeout);
|
||||
sendMessage("waitForTimeout", params, NO_TIMEOUT);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1085,4 +1086,16 @@ public class FrameImpl extends ChannelOwner implements Frame {
|
||||
}
|
||||
return new TimeoutSettings().navigationTimeout(timeout);
|
||||
}
|
||||
|
||||
FrameExpectResult expect(String expression, FrameExpectOptions options, String title) {
|
||||
return withTitle(title, () -> expect(expression, options));
|
||||
}
|
||||
|
||||
FrameExpectResult expect(String expression, FrameExpectOptions options) {
|
||||
JsonObject params = gson().toJsonTree(options).getAsJsonObject();
|
||||
params.addProperty("expression", expression);
|
||||
JsonElement json = sendMessage("expect", params, options.timeout);
|
||||
FrameExpectResult result = gson().fromJson(json, FrameExpectResult.class);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,12 +30,20 @@ import static com.microsoft.playwright.impl.Serialization.serializeArgument;
|
||||
import static com.microsoft.playwright.impl.Utils.convertType;
|
||||
|
||||
public class LocatorAssertionsImpl extends AssertionsBase implements LocatorAssertions {
|
||||
LocatorImpl actualLocator;
|
||||
|
||||
public LocatorAssertionsImpl(Locator locator) {
|
||||
this(locator, false);
|
||||
}
|
||||
|
||||
private LocatorAssertionsImpl(Locator locator, boolean isNot) {
|
||||
super((LocatorImpl) locator, isNot);
|
||||
super(isNot);
|
||||
this.actualLocator = (LocatorImpl) locator;
|
||||
}
|
||||
|
||||
@Override
|
||||
FrameExpectResult doExpect(String expression, FrameExpectOptions expectOptions, String title) {
|
||||
return actualLocator.expect(expression, expectOptions, title);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -645,7 +645,8 @@ class LocatorImpl implements Locator {
|
||||
}
|
||||
|
||||
FrameExpectResult expect(String expression, FrameExpectOptions options, String title) {
|
||||
return frame.withTitle(title, () -> expectImpl(expression, options));
|
||||
options.selector = selector;
|
||||
return frame.expect(expression, options, title);
|
||||
}
|
||||
|
||||
JsonObject toProtocol() {
|
||||
@@ -654,13 +655,4 @@ class LocatorImpl implements Locator {
|
||||
result.addProperty("selector", selector);
|
||||
return result;
|
||||
}
|
||||
|
||||
private FrameExpectResult expectImpl(String expression, FrameExpectOptions options) {
|
||||
JsonObject params = gson().toJsonTree(options).getAsJsonObject();
|
||||
params.addProperty("selector", selector);
|
||||
params.addProperty("expression", expression);
|
||||
JsonElement json = frame.sendMessage("expect", params, options.timeout);
|
||||
FrameExpectResult result = gson().fromJson(json, FrameExpectResult.class);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,10 +32,16 @@ public class PageAssertionsImpl extends AssertionsBase implements PageAssertions
|
||||
}
|
||||
|
||||
private PageAssertionsImpl(Page page, boolean isNot) {
|
||||
super((LocatorImpl) page.locator(":root"), isNot);
|
||||
super(isNot);
|
||||
this.actualPage = (PageImpl) page;
|
||||
}
|
||||
|
||||
@Override
|
||||
FrameExpectResult doExpect(String expression, FrameExpectOptions expectOptions, String title) {
|
||||
FrameImpl frame = (FrameImpl) actualPage.mainFrame();
|
||||
return frame.expect(expression, expectOptions, title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hasTitle(String title, HasTitleOptions options) {
|
||||
ExpectedTextValue expected = new ExpectedTextValue();
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// This file is generated by generate_java_rpc.js, do not edit manually.
|
||||
|
||||
package com.microsoft.playwright.impl;
|
||||
|
||||
import java.util.List;
|
||||
@@ -105,6 +103,7 @@ class ExpectedTextValue {
|
||||
class FrameExpectOptions {
|
||||
Object expressionArg;
|
||||
List<ExpectedTextValue> expectedText;
|
||||
String selector;
|
||||
Double expectedNumber;
|
||||
SerializedArgument expectedValue;
|
||||
Boolean useInnerText;
|
||||
|
||||
@@ -68,6 +68,10 @@ public class SelectorsImpl extends LoggingSupport implements Selectors {
|
||||
}
|
||||
|
||||
private void registerImpl(String name, String script, RegisterOptions options) {
|
||||
if (selectorEngines.stream().anyMatch(engine -> name.equals(engine.get("name").getAsString()))) {
|
||||
throw new PlaywrightException("selectors.register: \"" + name + "\" selector engine has been already registered");
|
||||
}
|
||||
|
||||
JsonObject engine = new JsonObject();
|
||||
engine.addProperty("name", name);
|
||||
engine.addProperty("source", script);
|
||||
|
||||
@@ -128,7 +128,11 @@ class WebSocketRouteImpl extends ChannelOwner implements WebSocketRoute {
|
||||
return;
|
||||
}
|
||||
// Ensure that websocket is "open" and can send messages without an actual server connection.
|
||||
sendMessageAsync("ensureOpened");
|
||||
try {
|
||||
sendMessageAsync("ensureOpened");
|
||||
} catch (PlaywrightException e) {
|
||||
// If this happens after the page has been closed, ignore the error.
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -48,6 +48,12 @@ public class Cookie {
|
||||
* Optional.
|
||||
*/
|
||||
public SameSiteAttribute sameSite;
|
||||
/**
|
||||
* For partitioned third-party cookies (aka <a
|
||||
* href="https://developer.mozilla.org/en-US/docs/Web/Privacy/Guides/Privacy_sandbox/Partitioned_cookies">CHIPS</a>), the
|
||||
* partition key. Optional.
|
||||
*/
|
||||
public String partitionKey;
|
||||
|
||||
public Cookie(String name, String value) {
|
||||
this.name = name;
|
||||
@@ -103,4 +109,13 @@ public class Cookie {
|
||||
this.sameSite = sameSite;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* For partitioned third-party cookies (aka <a
|
||||
* href="https://developer.mozilla.org/en-US/docs/Web/Privacy/Guides/Privacy_sandbox/Partitioned_cookies">CHIPS</a>), the
|
||||
* partition key. Optional.
|
||||
*/
|
||||
public Cookie setPartitionKey(String partitionKey) {
|
||||
this.partitionKey = partitionKey;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -436,7 +436,7 @@ public class TestBrowserContextFetch extends TestBase {
|
||||
PlaywrightException e = assertThrows(PlaywrightException.class, () -> {
|
||||
context.request().get(server.PREFIX + "/slow", RequestOptions.create().setTimeout(100));
|
||||
});
|
||||
assertTrue(e.getMessage().contains("Request timed out after 100ms"), e.getMessage());
|
||||
assertTrue(e.getMessage().contains("Timeout 100ms exceeded"), e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -468,7 +468,7 @@ public class TestBrowserContextFetch extends TestBase {
|
||||
|
||||
context.setDefaultTimeout(100);
|
||||
PlaywrightException e = assertThrows(PlaywrightException.class, () -> context.request().get(server.PREFIX + "/redirect"));
|
||||
assertTrue(e.getMessage().contains("Request timed out after 100ms"), e.getMessage());
|
||||
assertTrue(e.getMessage().contains("Timeout 100ms exceeded"), e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -174,10 +174,19 @@ public class TestBrowserContextStorageState extends TestBase {
|
||||
@Test
|
||||
void shouldSupportIndexedDB() {
|
||||
page.navigate(server.PREFIX + "/to-do-notifications/index.html");
|
||||
|
||||
assertThat(page.locator("#notifications")).matchesAriaSnapshot(
|
||||
" - list:\n" +
|
||||
" - listitem: Database initialised."
|
||||
);
|
||||
page.locator("label:has-text('Task title')").fill("Pet the cat");
|
||||
page.locator("label:has-text('Hours')").fill("1");
|
||||
page.locator("label:has-text('Mins')").fill("1");
|
||||
page.locator("text=Add Task").click();
|
||||
assertThat(page.locator("#notifications")).matchesAriaSnapshot(
|
||||
" - list:\n" +
|
||||
" - listitem: \"Transaction completed: database modification finished.\""
|
||||
);
|
||||
|
||||
String storageState = page.context().storageState(new BrowserContext.StorageStateOptions().setIndexedDB(true));
|
||||
assertJsonEquals("{\"cookies\":[],\"origins\":[\n" +
|
||||
|
||||
@@ -63,12 +63,22 @@ public class TestChromiumTracing extends TestBase {
|
||||
Path outputTraceFile = tempDir.resolve("trace.json");
|
||||
browser.startTracing(page, new Browser.StartTracingOptions()
|
||||
.setPath(outputTraceFile)
|
||||
.setCategories(asList("disabled-by-default-v8.cpu_profiler.hires")));
|
||||
.setCategories(asList("disabled-by-default-cc.debug")));
|
||||
page.evaluate("() => 1 + 1");
|
||||
browser.stopTracing();
|
||||
try (FileReader fileReader = new FileReader(outputTraceFile.toFile())) {
|
||||
JsonObject traceJson = new Gson().fromJson(fileReader, JsonObject.class);
|
||||
assertTrue(traceJson.getAsJsonObject("metadata").get("trace-config")
|
||||
.getAsString().contains("disabled-by-default-v8.cpu_profiler.hires"));
|
||||
// NOTE: trace-config is deprecated as per http://crrev.com/c/6628182
|
||||
boolean hasTraceConfig =
|
||||
traceJson.getAsJsonObject("metadata").get("trace-config") != null
|
||||
&& traceJson.getAsJsonObject("metadata").get("trace-config").getAsString().contains("disabled-by-default-cc.debug");
|
||||
boolean hasTraceEvents = traceJson.getAsJsonArray("traceEvents").asList().stream()
|
||||
.anyMatch(event -> {
|
||||
JsonObject eventObj = (JsonObject) event;
|
||||
return eventObj.has("cat") &&
|
||||
eventObj.get("cat").getAsString().equals("disabled-by-default-cc.debug");
|
||||
});
|
||||
assertTrue(hasTraceConfig || hasTraceEvents);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ public class TestGlobalFetch extends TestBase {
|
||||
APIRequestContext request = playwright.request().newContext(new APIRequest.NewContextOptions().setTimeout(100));
|
||||
server.setRoute("/empty.html", exchange -> {});
|
||||
PlaywrightException e = assertThrows(PlaywrightException.class, () -> request.get(server.EMPTY_PAGE));
|
||||
assertTrue(e.getMessage().contains("Request timed out after 100ms"), e.getMessage());
|
||||
assertTrue(e.getMessage().contains("Timeout 100ms exceeded"), e.getMessage());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -271,7 +271,7 @@ public class TestPageAddLocatorHandler extends TestBase {
|
||||
|
||||
PlaywrightException e = assertThrows(PlaywrightException.class, () -> page.locator("#target").click(new Locator.ClickOptions().setTimeout(3_000)));
|
||||
assertEquals(0, (int) page.evaluate("window.clicked"));
|
||||
assertThat(page.locator("#interstitial")).isVisible();
|
||||
assertTrue(page.locator("#interstitial").isVisible());
|
||||
assertEquals(1, called[0]);
|
||||
assertTrue(e.getMessage().contains("locator handler has finished, waiting for getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName(\"close\")) to be hidden"), e.getMessage());
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.microsoft.playwright;
|
||||
import com.microsoft.playwright.junit.FixtureTest;
|
||||
import com.microsoft.playwright.junit.UsePlaywright;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.opentest4j.AssertionFailedError;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -12,6 +13,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
@FixtureTest
|
||||
@UsePlaywright
|
||||
@@ -102,4 +104,27 @@ public class TestPageAriaSnapshot {
|
||||
"- link:\n" +
|
||||
" - /url: /.*example.com/");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHandleTopLevelDeepEqual(Page page) {
|
||||
// https://github.com/microsoft/playwright/issues/36456
|
||||
page.setContent("" +
|
||||
"<ul>\n" +
|
||||
" <li>\n" +
|
||||
" <ul>\n" +
|
||||
" <li>1.1</li>\n" +
|
||||
" <li>1.2</li>\n" +
|
||||
" </ul>\n" +
|
||||
" </li>\n" +
|
||||
"</ul>");
|
||||
|
||||
assertThrows(AssertionFailedError.class, () -> {
|
||||
assertThat(page.locator("body")).matchesAriaSnapshot("" +
|
||||
"- /children: deep-equal\n" +
|
||||
"- list:\n" +
|
||||
" - listitem:\n" +
|
||||
" - listitem: \"1.1\"\n" +
|
||||
" - listitem: \"1.2\"");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ public class TestPageInterception extends TestBase {
|
||||
page.route("**/*", route -> {
|
||||
PlaywrightException error = assertThrows(PlaywrightException.class,
|
||||
() -> route.fetch(new Route.FetchOptions().setTimeout(1000)));
|
||||
assertTrue(error.getMessage().contains("Request timed out after 1000ms"), error.getMessage());
|
||||
assertTrue(error.getMessage().contains("Timeout 1000ms exceeded"), error.getMessage());
|
||||
});
|
||||
PlaywrightException error = assertThrows(PlaywrightException.class,
|
||||
() -> page.navigate(server.PREFIX + "/slow", new Page.NavigateOptions().setTimeout(2000)));
|
||||
@@ -198,6 +198,15 @@ public class TestPageInterception extends TestBase {
|
||||
assertTrue(urlMatches("http://playwright.dev/foo", "http://playwright.dev/foo?bar", "\\\\?bar"));
|
||||
assertTrue(urlMatches("http://first.host/", "http://second.host/foo", "**/foo"));
|
||||
assertTrue(urlMatches("http://playwright.dev/", "http://localhost/", "*//localhost/"));
|
||||
|
||||
String[] customPrefixes = {"about", "data", "chrome", "edge", "file"};
|
||||
for (String prefix : customPrefixes) {
|
||||
assertTrue(urlMatches("http://playwright.dev/", prefix + ":blank", prefix + ":blank"));
|
||||
assertFalse(urlMatches("http://playwright.dev/", prefix + ":blank", "http://playwright.dev/"));
|
||||
assertTrue(urlMatches(null, prefix + ":blank", prefix + ":blank"));
|
||||
assertTrue(urlMatches(null, prefix + ":blank", prefix + ":*"));
|
||||
assertFalse(urlMatches(null, "not" + prefix + ":blank", prefix + ":*"));
|
||||
}
|
||||
}
|
||||
|
||||
Pattern globToRegex(String glob) {
|
||||
|
||||
@@ -23,25 +23,26 @@ import java.nio.file.Paths;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class TestSelectorsRegister extends TestBase {
|
||||
private static final String TAG_SELECTOR_SCRIPT = "{\n" +
|
||||
" create(root, target) {\n" +
|
||||
" return target.nodeName;\n" +
|
||||
" },\n" +
|
||||
" query(root, selector) {\n" +
|
||||
" return root.querySelector(selector);\n" +
|
||||
" },\n" +
|
||||
" queryAll(root, selector) {\n" +
|
||||
" return Array.from(root.querySelectorAll(selector));\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
|
||||
@Test
|
||||
void shouldWork() {
|
||||
String selectorScript = "{\n" +
|
||||
" create(root, target) {\n" +
|
||||
" return target.nodeName;\n" +
|
||||
" },\n" +
|
||||
" query(root, selector) {\n" +
|
||||
" return root.querySelector(selector);\n" +
|
||||
" },\n" +
|
||||
" queryAll(root, selector) {\n" +
|
||||
" return Array.from(root.querySelectorAll(selector));\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
// Register one engine before creating context.
|
||||
playwright.selectors().register("tag", selectorScript);
|
||||
playwright.selectors().register("tag", TAG_SELECTOR_SCRIPT);
|
||||
|
||||
BrowserContext context = browser.newContext();
|
||||
// Register another engine after creating context.
|
||||
playwright.selectors().register("tag2", selectorScript);
|
||||
playwright.selectors().register("tag2", TAG_SELECTOR_SCRIPT);
|
||||
|
||||
Page page = context.newPage();
|
||||
page.setContent("<div><span></span></div><div></div>");
|
||||
@@ -134,4 +135,21 @@ public class TestSelectorsRegister extends TestBase {
|
||||
});
|
||||
assertTrue(e.getMessage().contains("\"css\" is a predefined selector engine"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldThrowAlreadyRegisteredErrorWhenRegistering() {
|
||||
// https://github.com/microsoft/playwright/issues/36467
|
||||
|
||||
// this test is about the exception *before* there's a context created
|
||||
context.close();
|
||||
|
||||
// Register the selector engine first
|
||||
playwright.selectors().register("alreadyRegistered", TAG_SELECTOR_SCRIPT);
|
||||
|
||||
// Attempt to register the same selector engine again should throw an error
|
||||
PlaywrightException e = assertThrows(PlaywrightException.class, () -> {
|
||||
playwright.selectors().register("alreadyRegistered", TAG_SELECTOR_SCRIPT);
|
||||
});
|
||||
assertTrue(e.getMessage().contains("\"alreadyRegistered\" selector engine has been already registered"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
1.53.1
|
||||
1.54.0-alpha-2025-07-09
|
||||
|
||||
Reference in New Issue
Block a user