From 91a53cf0e8c9e063cd34ee60df96539fc95877af Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Tue, 8 Jul 2025 11:23:45 +0200 Subject: [PATCH 01/11] 1.54.0-alpha-2025-06-20 --- examples/pom.xml | 2 +- .../com/microsoft/playwright/BrowserContext.java | 5 ++++- .../main/java/com/microsoft/playwright/Mouse.java | 5 +++++ .../microsoft/playwright/impl/AssertionsBase.java | 13 ++++++------- .../com/microsoft/playwright/impl/FrameImpl.java | 12 ++++++++++++ .../playwright/impl/LocatorAssertionsImpl.java | 10 +++++++++- .../microsoft/playwright/impl/LocatorImpl.java | 12 ++---------- .../playwright/impl/PageAssertionsImpl.java | 8 +++++++- .../com/microsoft/playwright/impl/Protocol.java | 3 +-- .../com/microsoft/playwright/options/Cookie.java | 15 +++++++++++++++ .../playwright/TestPageInterception.java | 6 ++++++ scripts/DRIVER_VERSION | 2 +- 12 files changed, 69 insertions(+), 24 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index 85e64f832..7474e88fa 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -10,7 +10,7 @@ Playwright Client Examples UTF-8 - 1.53.0 + 1.54.0 diff --git a/playwright/src/main/java/com/microsoft/playwright/BrowserContext.java b/playwright/src/main/java/com/microsoft/playwright/BrowserContext.java index 97b46508b..695a38a6f 100644 --- a/playwright/src/main/java/com/microsoft/playwright/BrowserContext.java +++ b/playwright/src/main/java/com/microsoft/playwright/BrowserContext.java @@ -596,7 +596,8 @@ public WaitForPageOptions setTimeout(double timeout) { */ List 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 @@ default void exposeBinding(String name, BindingCallback callback) { *
  • {@code "notifications"}
  • *
  • {@code "payment-handler"}
  • *
  • {@code "storage-access"}
  • + *
  • {@code "local-fonts"}
  • * * @since v1.8 */ @@ -903,6 +905,7 @@ default void grantPermissions(List permissions) { *
  • {@code "notifications"}
  • *
  • {@code "payment-handler"}
  • *
  • {@code "storage-access"}
  • + *
  • {@code "local-fonts"}
  • * * @since v1.8 */ diff --git a/playwright/src/main/java/com/microsoft/playwright/Mouse.java b/playwright/src/main/java/com/microsoft/playwright/Mouse.java index 83c6d7c7f..dbb9fb781 100644 --- a/playwright/src/main/java/com/microsoft/playwright/Mouse.java +++ b/playwright/src/main/java/com/microsoft/playwright/Mouse.java @@ -21,6 +21,11 @@ /** * The Mouse class operates in main-frame CSS pixels relative to the top-left corner of the viewport. * + *

    NOTE: If you want to debug where the mouse moved, you can use the Trace viewer or Playwright Inspector. A red dot showing the location of the + * mouse will be shown for every mouse action. + * *

    Every {@code page} object has its own Mouse, accessible with {@link com.microsoft.playwright.Page#mouse Page.mouse()}. *

    {@code
      * // Using ‘page.mouse’ to trace a 100x100 square.
    diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/AssertionsBase.java b/playwright/src/main/java/com/microsoft/playwright/impl/AssertionsBase.java
    index 92ad7ef3c..c97796032 100644
    --- a/playwright/src/main/java/com/microsoft/playwright/impl/AssertionsBase.java
    +++ b/playwright/src/main/java/com/microsoft/playwright/impl/AssertionsBase.java
    @@ -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 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 @@ void expectImpl(String expression, FrameExpectOptions expectOptions, Object expe
         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 @@ void expectImpl(String expression, FrameExpectOptions expectOptions, Object expe
         }
       }
     
    -  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);
         }
    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 5f1a0a53d..28fa27adc 100644
    --- a/playwright/src/main/java/com/microsoft/playwright/impl/FrameImpl.java
    +++ b/playwright/src/main/java/com/microsoft/playwright/impl/FrameImpl.java
    @@ -1085,4 +1085,16 @@ protected double navigationTimeout(Double timeout) {
         }
         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;
    +  }
     }
    diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/LocatorAssertionsImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/LocatorAssertionsImpl.java
    index 616366b06..088910c98 100644
    --- a/playwright/src/main/java/com/microsoft/playwright/impl/LocatorAssertionsImpl.java
    +++ b/playwright/src/main/java/com/microsoft/playwright/impl/LocatorAssertionsImpl.java
    @@ -30,12 +30,20 @@
     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);
       }
     
     
    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 f27a3d43f..7c182ad3c 100644
    --- a/playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java
    +++ b/playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java
    @@ -645,7 +645,8 @@ public int hashCode() {
       }
     
       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 @@ JsonObject toProtocol() {
         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;
    -  }
     }
    diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/PageAssertionsImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/PageAssertionsImpl.java
    index e4c113834..9a114f249 100644
    --- a/playwright/src/main/java/com/microsoft/playwright/impl/PageAssertionsImpl.java
    +++ b/playwright/src/main/java/com/microsoft/playwright/impl/PageAssertionsImpl.java
    @@ -32,10 +32,16 @@ public PageAssertionsImpl(Page page) {
       }
     
       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();
    diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/Protocol.java b/playwright/src/main/java/com/microsoft/playwright/impl/Protocol.java
    index 2caef1409..c1a1768b1 100644
    --- a/playwright/src/main/java/com/microsoft/playwright/impl/Protocol.java
    +++ b/playwright/src/main/java/com/microsoft/playwright/impl/Protocol.java
    @@ -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 expectedText;
    +  String selector;
       Double expectedNumber;
       SerializedArgument expectedValue;
       Boolean useInnerText;
    diff --git a/playwright/src/main/java/com/microsoft/playwright/options/Cookie.java b/playwright/src/main/java/com/microsoft/playwright/options/Cookie.java
    index ae3881329..ee7888536 100644
    --- a/playwright/src/main/java/com/microsoft/playwright/options/Cookie.java
    +++ b/playwright/src/main/java/com/microsoft/playwright/options/Cookie.java
    @@ -48,6 +48,12 @@ public class Cookie {
        * Optional.
        */
       public SameSiteAttribute sameSite;
    +  /**
    +   * For partitioned third-party cookies (aka CHIPS), the
    +   * partition key. Optional.
    +   */
    +  public String partitionKey;
     
       public Cookie(String name, String value) {
         this.name = name;
    @@ -103,4 +109,13 @@ public Cookie setSameSite(SameSiteAttribute sameSite) {
         this.sameSite = sameSite;
         return this;
       }
    +  /**
    +   * For partitioned third-party cookies (aka CHIPS), the
    +   * partition key. Optional.
    +   */
    +  public Cookie setPartitionKey(String partitionKey) {
    +    this.partitionKey = partitionKey;
    +    return this;
    +  }
     }
    \ No newline at end of file
    diff --git a/playwright/src/test/java/com/microsoft/playwright/TestPageInterception.java b/playwright/src/test/java/com/microsoft/playwright/TestPageInterception.java
    index a6462ff22..22004944f 100644
    --- a/playwright/src/test/java/com/microsoft/playwright/TestPageInterception.java
    +++ b/playwright/src/test/java/com/microsoft/playwright/TestPageInterception.java
    @@ -198,6 +198,12 @@ void shouldWorkWithGlob() {
         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/"));
    +
    +    assertTrue(urlMatches("http://playwright.dev/", "about:blank", "about:blank"));
    +    assertFalse(urlMatches("http://playwright.dev/", "about:blank", "http://playwright.dev/"));
    +    assertTrue(urlMatches(null, "about:blank", "about:blank"));
    +    assertTrue(urlMatches(null, "about:blank", "about:*"));
    +    assertFalse(urlMatches(null, "notabout:blank", "about:*"));
       }
     
       Pattern globToRegex(String glob) {
    diff --git a/scripts/DRIVER_VERSION b/scripts/DRIVER_VERSION
    index 9adccc2f2..108ad323a 100644
    --- a/scripts/DRIVER_VERSION
    +++ b/scripts/DRIVER_VERSION
    @@ -1 +1 @@
    -1.53.1
    +1.54.0-alpha-2025-06-20
    
    From dbd6070466c0bf7d16faac5204749c81aaf8c8aa Mon Sep 17 00:00:00 2001
    From: Simon Knott 
    Date: Tue, 8 Jul 2025 11:36:25 +0200
    Subject: [PATCH 02/11] fix tests
    
    ---
     .../com/microsoft/playwright/TestBrowserContextFetch.java     | 4 ++--
     .../test/java/com/microsoft/playwright/TestGlobalFetch.java   | 2 +-
     .../com/microsoft/playwright/TestPageAddLocatorHandler.java   | 2 ++
     .../java/com/microsoft/playwright/TestPageInterception.java   | 2 +-
     4 files changed, 6 insertions(+), 4 deletions(-)
    
    diff --git a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextFetch.java b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextFetch.java
    index f8592f82e..d7352c748 100644
    --- a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextFetch.java
    +++ b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextFetch.java
    @@ -436,7 +436,7 @@ void shouldSupportTimeoutOption() {
         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 @@ void shouldRespectTimeoutAfterRedirects() {
     
         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
    diff --git a/playwright/src/test/java/com/microsoft/playwright/TestGlobalFetch.java b/playwright/src/test/java/com/microsoft/playwright/TestGlobalFetch.java
    index f11e39f22..ce9e21f48 100644
    --- a/playwright/src/test/java/com/microsoft/playwright/TestGlobalFetch.java
    +++ b/playwright/src/test/java/com/microsoft/playwright/TestGlobalFetch.java
    @@ -189,7 +189,7 @@ void shouldSupportGlobalTimeoutOption() {
         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());
       }
     
     
    diff --git a/playwright/src/test/java/com/microsoft/playwright/TestPageAddLocatorHandler.java b/playwright/src/test/java/com/microsoft/playwright/TestPageAddLocatorHandler.java
    index 49a615f4f..1d4e358e3 100644
    --- a/playwright/src/test/java/com/microsoft/playwright/TestPageAddLocatorHandler.java
    +++ b/playwright/src/test/java/com/microsoft/playwright/TestPageAddLocatorHandler.java
    @@ -19,6 +19,7 @@
     import com.microsoft.playwright.options.AriaRole;
     import com.microsoft.playwright.options.WaitForSelectorState;
     import org.junit.jupiter.api.Test;
    +import org.junit.jupiter.api.Disabled;
     
     import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
     import static org.junit.jupiter.api.Assertions.*;
    @@ -254,6 +255,7 @@ public void shouldWaitForHiddenByDefault() {
       }
     
       @Test
    +  @Disabled("need to debug why this is failing")
       public void shouldWaitForHiddenByDefault2() {
         Page page = browser.newPage();
         page.navigate(server.PREFIX + "/input/handle-locator.html");
    diff --git a/playwright/src/test/java/com/microsoft/playwright/TestPageInterception.java b/playwright/src/test/java/com/microsoft/playwright/TestPageInterception.java
    index 22004944f..aed0786b5 100644
    --- a/playwright/src/test/java/com/microsoft/playwright/TestPageInterception.java
    +++ b/playwright/src/test/java/com/microsoft/playwright/TestPageInterception.java
    @@ -99,7 +99,7 @@ void shouldSupportTimeoutOptionInRouteFetch() {
         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)));
    
    From 14c66f90f03ffd4a7126220589ae7cb180cca1be Mon Sep 17 00:00:00 2001
    From: Simon Knott 
    Date: Tue, 8 Jul 2025 12:09:22 +0200
    Subject: [PATCH 03/11] 1.54.0-alpha-2025-07-08
    
    ---
     .../microsoft/playwright/ConsoleMessage.java  |  3 +-
     .../playwright/impl/BrowserContextImpl.java   |  2 +-
     .../playwright/impl/ConsoleMessageImpl.java   |  5 ++-
     .../microsoft/playwright/impl/FrameImpl.java  |  3 +-
     .../playwright/impl/SelectorsImpl.java        |  4 ++
     .../playwright/impl/WebSocketRouteImpl.java   |  6 ++-
     .../options/ConsoleMessageType.java           | 38 +++++++++++++++++
     .../playwright/TestPageAriaSnapshot.java      | 25 +++++++++++
     .../playwright/TestPageInterception.java      | 13 +++---
     .../playwright/TestSelectorsRegister.java     | 42 +++++++++++++------
     scripts/DRIVER_VERSION                        |  2 +-
     .../playwright/tools/ApiGenerator.java        |  2 +-
     12 files changed, 119 insertions(+), 26 deletions(-)
     create mode 100644 playwright/src/main/java/com/microsoft/playwright/options/ConsoleMessageType.java
    
    diff --git a/playwright/src/main/java/com/microsoft/playwright/ConsoleMessage.java b/playwright/src/main/java/com/microsoft/playwright/ConsoleMessage.java
    index 663092f3c..3cfa6c2e0 100644
    --- a/playwright/src/main/java/com/microsoft/playwright/ConsoleMessage.java
    +++ b/playwright/src/main/java/com/microsoft/playwright/ConsoleMessage.java
    @@ -16,6 +16,7 @@
     
     package com.microsoft.playwright;
     
    +import com.microsoft.playwright.options.*;
     import java.util.*;
     
     /**
    @@ -77,6 +78,6 @@ public interface ConsoleMessage {
        *
        * @since v1.8
        */
    -  String type();
    +  ConsoleMessageType type();
     }
     
    diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/BrowserContextImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/BrowserContextImpl.java
    index b1f21d880..55a1aec42 100644
    --- a/playwright/src/main/java/com/microsoft/playwright/impl/BrowserContextImpl.java
    +++ b/playwright/src/main/java/com/microsoft/playwright/impl/BrowserContextImpl.java
    @@ -506,7 +506,7 @@ private void routeWebSocketImpl(UrlMatcher matcher, Consumer han
     
       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;
    diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/ConsoleMessageImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/ConsoleMessageImpl.java
    index e5aa1af1f..8bea66863 100644
    --- a/playwright/src/main/java/com/microsoft/playwright/impl/ConsoleMessageImpl.java
    +++ b/playwright/src/main/java/com/microsoft/playwright/impl/ConsoleMessageImpl.java
    @@ -21,6 +21,7 @@
     import com.microsoft.playwright.ConsoleMessage;
     import com.microsoft.playwright.JSHandle;
     import com.microsoft.playwright.Page;
    +import com.microsoft.playwright.options.ConsoleMessageType;
     
     import java.util.ArrayList;
     import java.util.List;
    @@ -43,8 +44,8 @@ public ConsoleMessageImpl(Connection connection, JsonObject initializer) {
         this.initializer = initializer;
       }
     
    -  public String type() {
    -    return initializer.get("type").getAsString();
    +  public ConsoleMessageType type() {
    +    return Utils.convertType(initializer.get("type").getAsString(), ConsoleMessageType.class);
       }
     
       public String text() {
    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 28fa27adc..ac04719ab 100644
    --- a/playwright/src/main/java/com/microsoft/playwright/impl/FrameImpl.java
    +++ b/playwright/src/main/java/com/microsoft/playwright/impl/FrameImpl.java
    @@ -993,7 +993,8 @@ ElementHandle waitForSelectorImpl(String selector, WaitForSelectorOptions option
       @Override
       public void waitForTimeout(double timeout) {
         JsonObject params = new JsonObject();
    -    sendMessage("waitForTimeout", params, timeout);
    +    params.addProperty("waitTimeout", timeout);
    +    sendMessage("waitForTimeout", params, NO_TIMEOUT);
       }
     
       @Override
    diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/SelectorsImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/SelectorsImpl.java
    index 62f5779be..878542ef1 100644
    --- a/playwright/src/main/java/com/microsoft/playwright/impl/SelectorsImpl.java
    +++ b/playwright/src/main/java/com/microsoft/playwright/impl/SelectorsImpl.java
    @@ -68,6 +68,10 @@ public void register(String name, Path path, RegisterOptions options) {
       }
     
       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);
    diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/WebSocketRouteImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/WebSocketRouteImpl.java
    index 53479fcf2..ab9ed40a0 100644
    --- a/playwright/src/main/java/com/microsoft/playwright/impl/WebSocketRouteImpl.java
    +++ b/playwright/src/main/java/com/microsoft/playwright/impl/WebSocketRouteImpl.java
    @@ -128,7 +128,11 @@ void afterHandle() {
           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
    diff --git a/playwright/src/main/java/com/microsoft/playwright/options/ConsoleMessageType.java b/playwright/src/main/java/com/microsoft/playwright/options/ConsoleMessageType.java
    new file mode 100644
    index 000000000..01a3d0b70
    --- /dev/null
    +++ b/playwright/src/main/java/com/microsoft/playwright/options/ConsoleMessageType.java
    @@ -0,0 +1,38 @@
    +/*
    + * 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.options;
    +
    +public enum ConsoleMessageType {
    +  LOG,
    +  DEBUG,
    +  INFO,
    +  ERROR,
    +  WARNING,
    +  DIR,
    +  DIRXML,
    +  TABLE,
    +  TRACE,
    +  CLEAR,
    +  STARTGROUP,
    +  STARTGROUPCOLLAPSED,
    +  ENDGROUP,
    +  ASSERT,
    +  PROFILE,
    +  PROFILEEND,
    +  COUNT,
    +  TIMEEND
    +}
    \ No newline at end of file
    diff --git a/playwright/src/test/java/com/microsoft/playwright/TestPageAriaSnapshot.java b/playwright/src/test/java/com/microsoft/playwright/TestPageAriaSnapshot.java
    index 527e0d7b7..7dd9c8dfa 100644
    --- a/playwright/src/test/java/com/microsoft/playwright/TestPageAriaSnapshot.java
    +++ b/playwright/src/test/java/com/microsoft/playwright/TestPageAriaSnapshot.java
    @@ -3,6 +3,7 @@
     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 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 @@ void shouldMatchUrl(Page page) {
           "- link:\n" +
           "  - /url: /.*example.com/");
       }
    +
    +  @Test
    +  void shouldHandleTopLevelDeepEqual(Page page) {
    +    // https://github.com/microsoft/playwright/issues/36456
    +    page.setContent("" +
    +      "
      \n" + + "
    • \n" + + "
        \n" + + "
      • 1.1
      • \n" + + "
      • 1.2
      • \n" + + "
      \n" + + "
    • \n" + + "
    "); + + assertThrows(AssertionFailedError.class, () -> { + assertThat(page.locator("body")).matchesAriaSnapshot("" + + "- /children: deep-equal\n" + + "- list:\n" + + " - listitem:\n" + + " - listitem: \"1.1\"\n" + + " - listitem: \"1.2\""); + }); + } } diff --git a/playwright/src/test/java/com/microsoft/playwright/TestPageInterception.java b/playwright/src/test/java/com/microsoft/playwright/TestPageInterception.java index aed0786b5..907d37bbc 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestPageInterception.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestPageInterception.java @@ -199,11 +199,14 @@ void shouldWorkWithGlob() { assertTrue(urlMatches("http://first.host/", "http://second.host/foo", "**/foo")); assertTrue(urlMatches("http://playwright.dev/", "http://localhost/", "*//localhost/")); - assertTrue(urlMatches("http://playwright.dev/", "about:blank", "about:blank")); - assertFalse(urlMatches("http://playwright.dev/", "about:blank", "http://playwright.dev/")); - assertTrue(urlMatches(null, "about:blank", "about:blank")); - assertTrue(urlMatches(null, "about:blank", "about:*")); - assertFalse(urlMatches(null, "notabout:blank", "about:*")); + 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) { diff --git a/playwright/src/test/java/com/microsoft/playwright/TestSelectorsRegister.java b/playwright/src/test/java/com/microsoft/playwright/TestSelectorsRegister.java index 4d50891ce..e4fbd78d5 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestSelectorsRegister.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestSelectorsRegister.java @@ -23,25 +23,26 @@ 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("
    "); @@ -134,4 +135,19 @@ void shouldHandleErrors() { }); assertTrue(e.getMessage().contains("\"css\" is a predefined selector engine")); } + + @Test + void shouldThrowAlreadyRegisteredErrorWhenRegistering() { + // https://github.com/microsoft/playwright/issues/36467 + browser.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")); + } } diff --git a/scripts/DRIVER_VERSION b/scripts/DRIVER_VERSION index 108ad323a..645e1f615 100644 --- a/scripts/DRIVER_VERSION +++ b/scripts/DRIVER_VERSION @@ -1 +1 @@ -1.54.0-alpha-2025-06-20 +1.54.0-alpha-2025-07-08 diff --git a/tools/api-generator/src/main/java/com/microsoft/playwright/tools/ApiGenerator.java b/tools/api-generator/src/main/java/com/microsoft/playwright/tools/ApiGenerator.java index fc088237d..2d931c6ef 100644 --- a/tools/api-generator/src/main/java/com/microsoft/playwright/tools/ApiGenerator.java +++ b/tools/api-generator/src/main/java/com/microsoft/playwright/tools/ApiGenerator.java @@ -986,7 +986,7 @@ void writeTo(List output, String offset) { if (methods.stream().anyMatch(m -> "create".equals(m.jsonName))) { output.add("import com.microsoft.playwright.impl." + jsonName + "Impl;"); } - if (asList("Page", "Request", "Response", "APIRequestContext", "APIRequest", "APIResponse", "FileChooser", "Frame", "FrameLocator", "ElementHandle", "Locator", "Browser", "BrowserContext", "BrowserType", "Mouse", "Keyboard", "Tracing").contains(jsonName)) { + if (asList("Page", "Request", "Response", "APIRequestContext", "APIRequest", "APIResponse", "FileChooser", "Frame", "FrameLocator", "ElementHandle", "Locator", "Browser", "BrowserContext", "BrowserType", "Mouse", "Keyboard", "Tracing", "ConsoleMessage").contains(jsonName)) { output.add("import com.microsoft.playwright.options.*;"); } if ("Download".equals(jsonName)) { From ae4a620dd3d9ece8f047f6fd7547f3a752997453 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Tue, 8 Jul 2025 12:37:03 +0200 Subject: [PATCH 04/11] fix tests --- .../playwright/impl/ConsoleMessageImpl.java | 27 ++++++++++++++++--- .../playwright/TestBrowserContextEvents.java | 4 ++- .../playwright/TestPageEventConsole.java | 20 +++++++++----- .../playwright/TestSelectorsRegister.java | 4 ++- 4 files changed, 43 insertions(+), 12 deletions(-) diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/ConsoleMessageImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/ConsoleMessageImpl.java index 8bea66863..465dcc093 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/ConsoleMessageImpl.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/ConsoleMessageImpl.java @@ -20,14 +20,12 @@ import com.google.gson.JsonObject; import com.microsoft.playwright.ConsoleMessage; import com.microsoft.playwright.JSHandle; -import com.microsoft.playwright.Page; +import com.microsoft.playwright.PlaywrightException; import com.microsoft.playwright.options.ConsoleMessageType; 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; @@ -45,7 +43,28 @@ public ConsoleMessageImpl(Connection connection, JsonObject initializer) { } public ConsoleMessageType type() { - return Utils.convertType(initializer.get("type").getAsString(), ConsoleMessageType.class); + String value = initializer.get("type").getAsString(); + switch (value) { + case "log": return ConsoleMessageType.LOG; + case "debug": return ConsoleMessageType.DEBUG; + case "info": return ConsoleMessageType.INFO; + case "error": return ConsoleMessageType.ERROR; + case "warning": return ConsoleMessageType.WARNING; + case "dir": return ConsoleMessageType.DIR; + case "dirxml": return ConsoleMessageType.DIRXML; + case "table": return ConsoleMessageType.TABLE; + case "trace": return ConsoleMessageType.TRACE; + case "clear": return ConsoleMessageType.CLEAR; + case "startGroup": return ConsoleMessageType.STARTGROUP; + case "startGroupCollapsed": return ConsoleMessageType.STARTGROUPCOLLAPSED; + case "endGroup": return ConsoleMessageType.ENDGROUP; + case "assert": return ConsoleMessageType.ASSERT; + case "profile": return ConsoleMessageType.PROFILE; + case "profileEnd": return ConsoleMessageType.PROFILEEND; + case "count": return ConsoleMessageType.COUNT; + case "timeEnd": return ConsoleMessageType.TIMEEND; + default: throw new PlaywrightException("Unexpected console message type: " + value); + } } public String text() { diff --git a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextEvents.java b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextEvents.java index a1c95b87f..77518b86e 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextEvents.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextEvents.java @@ -19,6 +19,8 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledIf; +import com.microsoft.playwright.options.ConsoleMessageType; + import java.io.OutputStreamWriter; import java.io.Writer; @@ -53,7 +55,7 @@ void consoleEventShouldWorkInPopup() { void consoleEventShouldWorkInPopup2() { Page[] popup = { null }; ConsoleMessage message = context.waitForConsoleMessage( - new BrowserContext.WaitForConsoleMessageOptions().setPredicate(msg -> "log".equals(msg.type())), + new BrowserContext.WaitForConsoleMessageOptions().setPredicate(msg -> msg.type() == ConsoleMessageType.LOG), () -> { popup[0] = context.waitForPage(() -> { page.evaluate("async () => {\n" + diff --git a/playwright/src/test/java/com/microsoft/playwright/TestPageEventConsole.java b/playwright/src/test/java/com/microsoft/playwright/TestPageEventConsole.java index feeb8bfd0..75c4eda43 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestPageEventConsole.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestPageEventConsole.java @@ -19,6 +19,8 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledIf; +import com.microsoft.playwright.options.ConsoleMessageType; + import java.util.ArrayList; import java.util.List; @@ -40,7 +42,7 @@ void shouldWork() { } else { assertEquals("hello 5 {foo: bar}", message.text()); } - assertEquals("log", message.type()); + assertEquals(ConsoleMessageType.LOG, message.type()); assertEquals("hello", message.args().get(0).jsonValue()); assertEquals(5, message.args().get(1).jsonValue()); assertEquals(mapOf("foo", "bar"), message.args().get(2).jsonValue()); @@ -70,7 +72,13 @@ void shouldWorkForDifferentConsoleAPICalls() { " console.error('calling console.error');\n" + " console.log(Promise.resolve('should not wait until resolved!'));\n" + " }"); - assertEquals(asList("timeEnd", "trace", "dir", "warning", "error", "log"), + assertEquals(asList( + ConsoleMessageType.TIMEEND, + ConsoleMessageType.TRACE, + ConsoleMessageType.DIR, + ConsoleMessageType.WARNING, + ConsoleMessageType.ERROR, + ConsoleMessageType.LOG), messages.stream().map(msg -> msg.type()).collect(toList())); assertTrue(messages.get(0).text().contains("calling console.time")); @@ -104,7 +112,7 @@ void shouldTriggerCorrectLog() { page.evaluate("async url => fetch(url).catch(e => {})", server.EMPTY_PAGE); }); assertTrue(message.text().contains("Access-Control-Allow-Origin")); - assertEquals("error", message.type()); + assertEquals(ConsoleMessageType.ERROR, message.type()); } @Test @@ -113,7 +121,7 @@ void shouldHaveLocationForConsoleAPICalls() { ConsoleMessage message = page.waitForConsoleMessage( new Page.WaitForConsoleMessageOptions().setPredicate(m -> "yellow".equals(m.text())), () -> page.navigate(server.PREFIX + "/consolelog.html")); - assertEquals("log", message.type()); + assertEquals(ConsoleMessageType.LOG, message.type()); // Engines have different column notion. assertTrue(message.location().startsWith(server.PREFIX + "/consolelog.html:7:"), message.location()); } @@ -122,12 +130,12 @@ void shouldHaveLocationForConsoleAPICalls() { void shouldSupportPredicate() { page.navigate(server.EMPTY_PAGE); ConsoleMessage message = page.waitForConsoleMessage( - new Page.WaitForConsoleMessageOptions().setPredicate(m -> "info".equals(m.type())), + new Page.WaitForConsoleMessageOptions().setPredicate(m -> m.type() == ConsoleMessageType.INFO), () -> { page.evaluate("console.log(1)"); page.evaluate("console.info(2)"); }); assertEquals("2", message.text()); - assertEquals("info", message.type()); + assertEquals(ConsoleMessageType.INFO, message.type()); } } diff --git a/playwright/src/test/java/com/microsoft/playwright/TestSelectorsRegister.java b/playwright/src/test/java/com/microsoft/playwright/TestSelectorsRegister.java index e4fbd78d5..1c6cbcc0c 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestSelectorsRegister.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestSelectorsRegister.java @@ -139,7 +139,9 @@ void shouldHandleErrors() { @Test void shouldThrowAlreadyRegisteredErrorWhenRegistering() { // https://github.com/microsoft/playwright/issues/36467 - browser.close(); + + // 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); From c2727df1c194e5a6d7f7157f07e824eb2e8aec0c Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Tue, 8 Jul 2025 13:26:45 +0200 Subject: [PATCH 05/11] fix chromium tracing test --- .../microsoft/playwright/TestChromiumTracing.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/playwright/src/test/java/com/microsoft/playwright/TestChromiumTracing.java b/playwright/src/test/java/com/microsoft/playwright/TestChromiumTracing.java index 034d464c4..a3e8bc100 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestChromiumTracing.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestChromiumTracing.java @@ -64,11 +64,19 @@ void shouldRunWithCustomCategoriesIfProvided(@TempDir Path tempDir) throws IOExc browser.startTracing(page, new Browser.StartTracingOptions() .setPath(outputTraceFile) .setCategories(asList("disabled-by-default-v8.cpu_profiler.hires"))); + 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").getAsString().contains("disabled-by-default-v8.cpu_profiler.hires"); + 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-v8.cpu_profiler.hires"); + }); + assertTrue(hasTraceConfig || hasTraceEvents); } } } From 8f6c099b303cf71c96abaee44dbba5baa29a1f00 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Tue, 8 Jul 2025 13:33:23 +0200 Subject: [PATCH 06/11] fix one more test --- .../com/microsoft/playwright/TestPageAddLocatorHandler.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/playwright/src/test/java/com/microsoft/playwright/TestPageAddLocatorHandler.java b/playwright/src/test/java/com/microsoft/playwright/TestPageAddLocatorHandler.java index 1d4e358e3..5b5cab3e2 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestPageAddLocatorHandler.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestPageAddLocatorHandler.java @@ -19,7 +19,6 @@ import com.microsoft.playwright.options.AriaRole; import com.microsoft.playwright.options.WaitForSelectorState; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.Disabled; import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; import static org.junit.jupiter.api.Assertions.*; @@ -255,7 +254,6 @@ public void shouldWaitForHiddenByDefault() { } @Test - @Disabled("need to debug why this is failing") public void shouldWaitForHiddenByDefault2() { Page page = browser.newPage(); page.navigate(server.PREFIX + "/input/handle-locator.html"); @@ -273,7 +271,7 @@ public void shouldWaitForHiddenByDefault2() { 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()); } From 90b37db0a83ac7103acedf1b3dd02a9a8c7c69ed Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Tue, 8 Jul 2025 13:39:16 +0200 Subject: [PATCH 07/11] readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7ba2b89e0..c59818785 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@ Playwright is a Java library to automate [Chromium](https://www.chromium.org/Hom | | Linux | macOS | Windows | | :--- | :---: | :---: | :---: | -| Chromium 138.0.7204.23 | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| Chromium 139.0.7258.5 | :white_check_mark: | :white_check_mark: | :white_check_mark: | | WebKit 18.5 | ✅ | ✅ | ✅ | -| Firefox 139.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| Firefox 140.0.2 | :white_check_mark: | :white_check_mark: | :white_check_mark: | ## Documentation From 1a6bb17221240c62921db5636565c789f38893bb Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Tue, 8 Jul 2025 13:55:22 +0200 Subject: [PATCH 08/11] fix another test --- .../com/microsoft/playwright/TestChromiumTracing.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/playwright/src/test/java/com/microsoft/playwright/TestChromiumTracing.java b/playwright/src/test/java/com/microsoft/playwright/TestChromiumTracing.java index a3e8bc100..93d1a220c 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestChromiumTracing.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestChromiumTracing.java @@ -63,18 +63,20 @@ void shouldRunWithCustomCategoriesIfProvided(@TempDir Path tempDir) throws IOExc 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); // NOTE: trace-config is deprecated as per http://crrev.com/c/6628182 - boolean hasTraceConfig = traceJson.getAsJsonObject("metadata").get("trace-config").getAsString().contains("disabled-by-default-v8.cpu_profiler.hires"); + 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-v8.cpu_profiler.hires"); + eventObj.get("cat").getAsString().equals("disabled-by-default-cc.debug"); }); assertTrue(hasTraceConfig || hasTraceEvents); } From 8e6783d5dcea6818c87b7d46759f963d94972622 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Tue, 8 Jul 2025 14:24:54 +0200 Subject: [PATCH 09/11] revert console message type change --- .../microsoft/playwright/ConsoleMessage.java | 3 +- .../playwright/impl/ConsoleMessageImpl.java | 27 +------------ .../options/ConsoleMessageType.java | 38 ------------------- .../playwright/TestBrowserContextEvents.java | 4 +- .../playwright/TestPageEventConsole.java | 20 +++------- .../playwright/tools/ApiGenerator.java | 10 ++++- 6 files changed, 19 insertions(+), 83 deletions(-) delete mode 100644 playwright/src/main/java/com/microsoft/playwright/options/ConsoleMessageType.java diff --git a/playwright/src/main/java/com/microsoft/playwright/ConsoleMessage.java b/playwright/src/main/java/com/microsoft/playwright/ConsoleMessage.java index 3cfa6c2e0..663092f3c 100644 --- a/playwright/src/main/java/com/microsoft/playwright/ConsoleMessage.java +++ b/playwright/src/main/java/com/microsoft/playwright/ConsoleMessage.java @@ -16,7 +16,6 @@ package com.microsoft.playwright; -import com.microsoft.playwright.options.*; import java.util.*; /** @@ -78,6 +77,6 @@ public interface ConsoleMessage { * * @since v1.8 */ - ConsoleMessageType type(); + String type(); } diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/ConsoleMessageImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/ConsoleMessageImpl.java index 465dcc093..f199c26f8 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/ConsoleMessageImpl.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/ConsoleMessageImpl.java @@ -20,8 +20,6 @@ import com.google.gson.JsonObject; import com.microsoft.playwright.ConsoleMessage; import com.microsoft.playwright.JSHandle; -import com.microsoft.playwright.PlaywrightException; -import com.microsoft.playwright.options.ConsoleMessageType; import java.util.ArrayList; import java.util.List; @@ -42,29 +40,8 @@ public ConsoleMessageImpl(Connection connection, JsonObject initializer) { this.initializer = initializer; } - public ConsoleMessageType type() { - String value = initializer.get("type").getAsString(); - switch (value) { - case "log": return ConsoleMessageType.LOG; - case "debug": return ConsoleMessageType.DEBUG; - case "info": return ConsoleMessageType.INFO; - case "error": return ConsoleMessageType.ERROR; - case "warning": return ConsoleMessageType.WARNING; - case "dir": return ConsoleMessageType.DIR; - case "dirxml": return ConsoleMessageType.DIRXML; - case "table": return ConsoleMessageType.TABLE; - case "trace": return ConsoleMessageType.TRACE; - case "clear": return ConsoleMessageType.CLEAR; - case "startGroup": return ConsoleMessageType.STARTGROUP; - case "startGroupCollapsed": return ConsoleMessageType.STARTGROUPCOLLAPSED; - case "endGroup": return ConsoleMessageType.ENDGROUP; - case "assert": return ConsoleMessageType.ASSERT; - case "profile": return ConsoleMessageType.PROFILE; - case "profileEnd": return ConsoleMessageType.PROFILEEND; - case "count": return ConsoleMessageType.COUNT; - case "timeEnd": return ConsoleMessageType.TIMEEND; - default: throw new PlaywrightException("Unexpected console message type: " + value); - } + public String type() { + return initializer.get("type").getAsString(); } public String text() { diff --git a/playwright/src/main/java/com/microsoft/playwright/options/ConsoleMessageType.java b/playwright/src/main/java/com/microsoft/playwright/options/ConsoleMessageType.java deleted file mode 100644 index 01a3d0b70..000000000 --- a/playwright/src/main/java/com/microsoft/playwright/options/ConsoleMessageType.java +++ /dev/null @@ -1,38 +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.options; - -public enum ConsoleMessageType { - LOG, - DEBUG, - INFO, - ERROR, - WARNING, - DIR, - DIRXML, - TABLE, - TRACE, - CLEAR, - STARTGROUP, - STARTGROUPCOLLAPSED, - ENDGROUP, - ASSERT, - PROFILE, - PROFILEEND, - COUNT, - TIMEEND -} \ No newline at end of file diff --git a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextEvents.java b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextEvents.java index 77518b86e..a1c95b87f 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextEvents.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextEvents.java @@ -19,8 +19,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledIf; -import com.microsoft.playwright.options.ConsoleMessageType; - import java.io.OutputStreamWriter; import java.io.Writer; @@ -55,7 +53,7 @@ void consoleEventShouldWorkInPopup() { void consoleEventShouldWorkInPopup2() { Page[] popup = { null }; ConsoleMessage message = context.waitForConsoleMessage( - new BrowserContext.WaitForConsoleMessageOptions().setPredicate(msg -> msg.type() == ConsoleMessageType.LOG), + new BrowserContext.WaitForConsoleMessageOptions().setPredicate(msg -> "log".equals(msg.type())), () -> { popup[0] = context.waitForPage(() -> { page.evaluate("async () => {\n" + diff --git a/playwright/src/test/java/com/microsoft/playwright/TestPageEventConsole.java b/playwright/src/test/java/com/microsoft/playwright/TestPageEventConsole.java index 75c4eda43..feeb8bfd0 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestPageEventConsole.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestPageEventConsole.java @@ -19,8 +19,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledIf; -import com.microsoft.playwright.options.ConsoleMessageType; - import java.util.ArrayList; import java.util.List; @@ -42,7 +40,7 @@ void shouldWork() { } else { assertEquals("hello 5 {foo: bar}", message.text()); } - assertEquals(ConsoleMessageType.LOG, message.type()); + assertEquals("log", message.type()); assertEquals("hello", message.args().get(0).jsonValue()); assertEquals(5, message.args().get(1).jsonValue()); assertEquals(mapOf("foo", "bar"), message.args().get(2).jsonValue()); @@ -72,13 +70,7 @@ void shouldWorkForDifferentConsoleAPICalls() { " console.error('calling console.error');\n" + " console.log(Promise.resolve('should not wait until resolved!'));\n" + " }"); - assertEquals(asList( - ConsoleMessageType.TIMEEND, - ConsoleMessageType.TRACE, - ConsoleMessageType.DIR, - ConsoleMessageType.WARNING, - ConsoleMessageType.ERROR, - ConsoleMessageType.LOG), + assertEquals(asList("timeEnd", "trace", "dir", "warning", "error", "log"), messages.stream().map(msg -> msg.type()).collect(toList())); assertTrue(messages.get(0).text().contains("calling console.time")); @@ -112,7 +104,7 @@ void shouldTriggerCorrectLog() { page.evaluate("async url => fetch(url).catch(e => {})", server.EMPTY_PAGE); }); assertTrue(message.text().contains("Access-Control-Allow-Origin")); - assertEquals(ConsoleMessageType.ERROR, message.type()); + assertEquals("error", message.type()); } @Test @@ -121,7 +113,7 @@ void shouldHaveLocationForConsoleAPICalls() { ConsoleMessage message = page.waitForConsoleMessage( new Page.WaitForConsoleMessageOptions().setPredicate(m -> "yellow".equals(m.text())), () -> page.navigate(server.PREFIX + "/consolelog.html")); - assertEquals(ConsoleMessageType.LOG, message.type()); + assertEquals("log", message.type()); // Engines have different column notion. assertTrue(message.location().startsWith(server.PREFIX + "/consolelog.html:7:"), message.location()); } @@ -130,12 +122,12 @@ void shouldHaveLocationForConsoleAPICalls() { void shouldSupportPredicate() { page.navigate(server.EMPTY_PAGE); ConsoleMessage message = page.waitForConsoleMessage( - new Page.WaitForConsoleMessageOptions().setPredicate(m -> m.type() == ConsoleMessageType.INFO), + new Page.WaitForConsoleMessageOptions().setPredicate(m -> "info".equals(m.type())), () -> { page.evaluate("console.log(1)"); page.evaluate("console.info(2)"); }); assertEquals("2", message.text()); - assertEquals(ConsoleMessageType.INFO, message.type()); + assertEquals("info", message.type()); } } diff --git a/tools/api-generator/src/main/java/com/microsoft/playwright/tools/ApiGenerator.java b/tools/api-generator/src/main/java/com/microsoft/playwright/tools/ApiGenerator.java index 2d931c6ef..bb8a1750b 100644 --- a/tools/api-generator/src/main/java/com/microsoft/playwright/tools/ApiGenerator.java +++ b/tools/api-generator/src/main/java/com/microsoft/playwright/tools/ApiGenerator.java @@ -596,6 +596,9 @@ void createEnum(JsonObject jsonObject) { if (newEnum.jsonName == null) { throw new RuntimeException("Enum without name: " + jsonObject); } + if ("ConsoleMessageType".equals(newEnum.jsonName)) { + return; + } Map enumMap = topLevelTypes(); TypeDefinition existing = enumMap.putIfAbsent(newEnum.jsonName, newEnum); if (existing != null && (!(existing instanceof Enum) || !((Enum) existing).hasSameValues(newEnum))) { @@ -722,6 +725,11 @@ void writeTo(List output, String offset) { output.add(""); return; } + if ("ConsoleMessage.type".equals(jsonPath)) { + writeJavadoc(params, output, offset); + output.add(offset + "String type();"); + return; + } int numOverloads = 1; for (int i = 0; i < params.size(); i++) { if (params.get(i).type.isTypeUnion()) { @@ -986,7 +994,7 @@ void writeTo(List output, String offset) { if (methods.stream().anyMatch(m -> "create".equals(m.jsonName))) { output.add("import com.microsoft.playwright.impl." + jsonName + "Impl;"); } - if (asList("Page", "Request", "Response", "APIRequestContext", "APIRequest", "APIResponse", "FileChooser", "Frame", "FrameLocator", "ElementHandle", "Locator", "Browser", "BrowserContext", "BrowserType", "Mouse", "Keyboard", "Tracing", "ConsoleMessage").contains(jsonName)) { + if (asList("Page", "Request", "Response", "APIRequestContext", "APIRequest", "APIResponse", "FileChooser", "Frame", "FrameLocator", "ElementHandle", "Locator", "Browser", "BrowserContext", "BrowserType", "Mouse", "Keyboard", "Tracing").contains(jsonName)) { output.add("import com.microsoft.playwright.options.*;"); } if ("Download".equals(jsonName)) { From 4443d27313cf16fd3a17d611674b1d8f244c41da Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Wed, 9 Jul 2025 09:28:46 +0200 Subject: [PATCH 10/11] type change --- scripts/DRIVER_VERSION | 2 +- .../java/com/microsoft/playwright/tools/ApiGenerator.java | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/scripts/DRIVER_VERSION b/scripts/DRIVER_VERSION index 645e1f615..8ba9de6a3 100644 --- a/scripts/DRIVER_VERSION +++ b/scripts/DRIVER_VERSION @@ -1 +1 @@ -1.54.0-alpha-2025-07-08 +1.54.0-alpha-2025-07-09 diff --git a/tools/api-generator/src/main/java/com/microsoft/playwright/tools/ApiGenerator.java b/tools/api-generator/src/main/java/com/microsoft/playwright/tools/ApiGenerator.java index bb8a1750b..fc088237d 100644 --- a/tools/api-generator/src/main/java/com/microsoft/playwright/tools/ApiGenerator.java +++ b/tools/api-generator/src/main/java/com/microsoft/playwright/tools/ApiGenerator.java @@ -596,9 +596,6 @@ void createEnum(JsonObject jsonObject) { if (newEnum.jsonName == null) { throw new RuntimeException("Enum without name: " + jsonObject); } - if ("ConsoleMessageType".equals(newEnum.jsonName)) { - return; - } Map enumMap = topLevelTypes(); TypeDefinition existing = enumMap.putIfAbsent(newEnum.jsonName, newEnum); if (existing != null && (!(existing instanceof Enum) || !((Enum) existing).hasSameValues(newEnum))) { @@ -725,11 +722,6 @@ void writeTo(List output, String offset) { output.add(""); return; } - if ("ConsoleMessage.type".equals(jsonPath)) { - writeJavadoc(params, output, offset); - output.add(offset + "String type();"); - return; - } int numOverloads = 1; for (int i = 0; i < params.size(); i++) { if (params.get(i).type.isTypeUnion()) { From afa61e8791cf991f15bfbb80b74134ec39ca3d37 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Wed, 9 Jul 2025 09:51:56 +0200 Subject: [PATCH 11/11] fix flaky test --- .../playwright/TestBrowserContextStorageState.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextStorageState.java b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextStorageState.java index 4d62fec4f..a398aaba0 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextStorageState.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextStorageState.java @@ -174,10 +174,19 @@ void shouldSerialiseStorageStateWithLoneSurrogates() { @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" +