Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .claude/skills/playwright-roll/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
name: playwright-roll
description: Roll Playwright Java to a new version
---

Help the user roll to a new version of Playwright.
ROLLING.md contains general instructions and scripts.

Start with updating the version and generating the API to see the state of things.
Afterwards, work through the list of changes that need to be backported.
You can find a list of pull requests that might need to be taking into account in the issue titled "Backport changes".
Work through them one-by-one and check off the items that you have handled.
Not all of them will be relevant, some might have partially been reverted, etc. - so feel free to check with the upstream release branch.

Rolling includes:
- updating client implementation to match changes in the upstream JS implementation (see ../playwright/packages/playwright-core/src/client)
- adding a couple of new tests to verify new/changed functionality

## Tips & Tricks
- Project checkouts are in the parent directory (`../`).
- When updating checkboxes, store the issue content into /tmp and edit it there, then update the issue based on the file
- use the "gh" cli to interact with GitHub
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ Playwright is a Java library to automate [Chromium](https://www.chromium.org/Hom

| | Linux | macOS | Windows |
| :--- | :---: | :---: | :---: |
| Chromium <!-- GEN:chromium-version -->143.0.7499.4<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Chromium <!-- GEN:chromium-version -->145.0.7632.6<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| WebKit <!-- GEN:webkit-version -->26.0<!-- GEN:stop --> | ✅ | ✅ | ✅ |
| Firefox <!-- GEN:firefox-version -->144.0.2<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Firefox <!-- GEN:firefox-version -->146.0.1<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |

## Documentation

Expand Down
2 changes: 1 addition & 1 deletion examples/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<name>Playwright Client Examples</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<playwright.version>1.57.0</playwright.version>
<playwright.version>1.58.0</playwright.version>
</properties>
<dependencies>
<dependency>
Expand Down
47 changes: 17 additions & 30 deletions playwright/src/main/java/com/microsoft/playwright/BrowserType.java
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,11 @@ class ConnectOverCDPOptions {
* Additional HTTP headers to be sent with connect request. Optional.
*/
public Map<String, String> headers;
/**
* Tells Playwright that it runs on the same host as the CDP server. It will enable certain optimizations that rely upon
* the file system being the same between Playwright and the Browser.
*/
public Boolean isLocal;
/**
* Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going on.
* Defaults to 0.
Expand All @@ -146,6 +151,14 @@ public ConnectOverCDPOptions setHeaders(Map<String, String> headers) {
this.headers = headers;
return this;
}
/**
* Tells Playwright that it runs on the same host as the CDP server. It will enable certain optimizations that rely upon
* the file system being the same between Playwright and the Browser.
*/
public ConnectOverCDPOptions setIsLocal(boolean isLocal) {
this.isLocal = isLocal;
return this;
}
/**
* Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going on.
* Defaults to 0.
Expand Down Expand Up @@ -186,10 +199,6 @@ class LaunchOptions {
* Enable Chromium sandboxing. Defaults to {@code false}.
*/
public Boolean chromiumSandbox;
/**
* @deprecated Use <a href="https://playwright.dev/java/docs/debug">debugging tools</a> instead.
*/
public Boolean devtools;
/**
* If specified, accepted downloads are downloaded into this directory. Otherwise, temporary directory is created and is
* deleted when browser is closed. In either case, the downloads are deleted when the browser context they were created in
Expand Down Expand Up @@ -229,8 +238,7 @@ class LaunchOptions {
/**
* Whether to run browser in headless mode. More details for <a
* href="https://developers.google.com/web/updates/2017/04/headless-chrome">Chromium</a> and <a
* href="https://hacks.mozilla.org/2017/12/using-headless-mode-in-firefox/">Firefox</a>. Defaults to {@code true} unless
* the {@code devtools} option is {@code true}.
* href="https://hacks.mozilla.org/2017/12/using-headless-mode-in-firefox/">Firefox</a>. Defaults to {@code true}.
*/
public Boolean headless;
/**
Expand Down Expand Up @@ -307,13 +315,6 @@ public LaunchOptions setChromiumSandbox(boolean chromiumSandbox) {
this.chromiumSandbox = chromiumSandbox;
return this;
}
/**
* @deprecated Use <a href="https://playwright.dev/java/docs/debug">debugging tools</a> instead.
*/
public LaunchOptions setDevtools(boolean devtools) {
this.devtools = devtools;
return this;
}
/**
* If specified, accepted downloads are downloaded into this directory. Otherwise, temporary directory is created and is
* deleted when browser is closed. In either case, the downloads are deleted when the browser context they were created in
Expand Down Expand Up @@ -374,8 +375,7 @@ public LaunchOptions setHandleSIGTERM(boolean handleSIGTERM) {
/**
* Whether to run browser in headless mode. More details for <a
* href="https://developers.google.com/web/updates/2017/04/headless-chrome">Chromium</a> and <a
* href="https://hacks.mozilla.org/2017/12/using-headless-mode-in-firefox/">Firefox</a>. Defaults to {@code true} unless
* the {@code devtools} option is {@code true}.
* href="https://hacks.mozilla.org/2017/12/using-headless-mode-in-firefox/">Firefox</a>. Defaults to {@code true}.
*/
public LaunchOptions setHeadless(boolean headless) {
this.headless = headless;
Expand Down Expand Up @@ -518,10 +518,6 @@ class LaunchPersistentContextOptions {
* href="https://playwright.dev/java/docs/emulation#devices">emulating devices with device scale factor</a>.
*/
public Double deviceScaleFactor;
/**
* @deprecated Use <a href="https://playwright.dev/java/docs/debug">debugging tools</a> instead.
*/
public Boolean devtools;
/**
* If specified, accepted downloads are downloaded into this directory. Otherwise, temporary directory is created and is
* deleted when browser is closed. In either case, the downloads are deleted when the browser context they were created in
Expand Down Expand Up @@ -577,8 +573,7 @@ class LaunchPersistentContextOptions {
/**
* Whether to run browser in headless mode. More details for <a
* href="https://developers.google.com/web/updates/2017/04/headless-chrome">Chromium</a> and <a
* href="https://hacks.mozilla.org/2017/12/using-headless-mode-in-firefox/">Firefox</a>. Defaults to {@code true} unless
* the {@code devtools} option is {@code true}.
* href="https://hacks.mozilla.org/2017/12/using-headless-mode-in-firefox/">Firefox</a>. Defaults to {@code true}.
*/
public Boolean headless;
/**
Expand Down Expand Up @@ -856,13 +851,6 @@ public LaunchPersistentContextOptions setDeviceScaleFactor(double deviceScaleFac
this.deviceScaleFactor = deviceScaleFactor;
return this;
}
/**
* @deprecated Use <a href="https://playwright.dev/java/docs/debug">debugging tools</a> instead.
*/
public LaunchPersistentContextOptions setDevtools(boolean devtools) {
this.devtools = devtools;
return this;
}
/**
* If specified, accepted downloads are downloaded into this directory. Otherwise, temporary directory is created and is
* deleted when browser is closed. In either case, the downloads are deleted when the browser context they were created in
Expand Down Expand Up @@ -954,8 +942,7 @@ public LaunchPersistentContextOptions setHasTouch(boolean hasTouch) {
/**
* Whether to run browser in headless mode. More details for <a
* href="https://developers.google.com/web/updates/2017/04/headless-chrome">Chromium</a> and <a
* href="https://hacks.mozilla.org/2017/12/using-headless-mode-in-firefox/">Firefox</a>. Defaults to {@code true} unless
* the {@code devtools} option is {@code true}.
* href="https://hacks.mozilla.org/2017/12/using-headless-mode-in-firefox/">Firefox</a>. Defaults to {@code true}.
*/
public LaunchPersistentContextOptions setHeadless(boolean headless) {
this.headless = headless;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2661,8 +2661,7 @@ default void dblclick() {
Locator describe(String description);
/**
* Returns locator description previously set with {@link com.microsoft.playwright.Locator#describe Locator.describe()}.
* Returns {@code null} if no custom description has been set. Prefer {@code Locator.toString()} for a human-readable
* representation, as it uses the description when available.
* Returns {@code null} if no custom description has been set.
*
* <p> <strong>Usage</strong>
* <pre>{@code
Expand Down
14 changes: 8 additions & 6 deletions playwright/src/main/java/com/microsoft/playwright/Route.java
Original file line number Diff line number Diff line change
Expand Up @@ -370,9 +370,10 @@ default void abort() {
* matching handlers won't be invoked. Use {@link com.microsoft.playwright.Route#fallback Route.fallback()} If you want
* next matching handler in the chain to be invoked.
*
* <p> <strong>NOTE:</strong> The {@code Cookie} header cannot be overridden using this method. If a value is provided, it will be ignored, and the
* cookie will be loaded from the browser's cookie store. To set custom cookies, use {@link
* com.microsoft.playwright.BrowserContext#addCookies BrowserContext.addCookies()}.
* <p> <strong>NOTE:</strong> Some request headers are **forbidden** and cannot be overridden (for example, {@code Cookie}, {@code Host}, {@code
* Content-Length} and others, see <a
* href="https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_request_header">this MDN page</a> for full list). If
* an override is provided for a forbidden header, it will be ignored and the original request header will be used.To set custom cookies, use {@link com.microsoft.playwright.BrowserContext#addCookies BrowserContext.addCookies()}.
*
* @since v1.8
*/
Expand Down Expand Up @@ -402,9 +403,10 @@ default void resume() {
* matching handlers won't be invoked. Use {@link com.microsoft.playwright.Route#fallback Route.fallback()} If you want
* next matching handler in the chain to be invoked.
*
* <p> <strong>NOTE:</strong> The {@code Cookie} header cannot be overridden using this method. If a value is provided, it will be ignored, and the
* cookie will be loaded from the browser's cookie store. To set custom cookies, use {@link
* com.microsoft.playwright.BrowserContext#addCookies BrowserContext.addCookies()}.
* <p> <strong>NOTE:</strong> Some request headers are **forbidden** and cannot be overridden (for example, {@code Cookie}, {@code Host}, {@code
* Content-Length} and others, see <a
* href="https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_request_header">this MDN page</a> for full list). If
* an override is provided for a forbidden header, it will be ignored and the original request header will be used.To set custom cookies, use {@link com.microsoft.playwright.BrowserContext#addCookies BrowserContext.addCookies()}.
*
* @since v1.8
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -989,7 +989,7 @@ default void containsClass(List<String> expected) {
* <p> Let's see how we can use the assertion:
* <pre>{@code
* // ✓ Contains the right items in the right order
* assertThat(page.locator("ul > li")).containsText(new String[] {"Text 1", "Text 3", "Text 4"});
* assertThat(page.locator("ul > li")).containsText(new String[] {"Text 1", "Text 3"});
*
* // ✖ Wrong order
* assertThat(page.locator("ul > li")).containsText(new String[] {"Text 3", "Text 2"});
Expand Down Expand Up @@ -1034,7 +1034,7 @@ default void containsText(String expected) {
* <p> Let's see how we can use the assertion:
* <pre>{@code
* // ✓ Contains the right items in the right order
* assertThat(page.locator("ul > li")).containsText(new String[] {"Text 1", "Text 3", "Text 4"});
* assertThat(page.locator("ul > li")).containsText(new String[] {"Text 1", "Text 3"});
*
* // ✖ Wrong order
* assertThat(page.locator("ul > li")).containsText(new String[] {"Text 3", "Text 2"});
Expand Down Expand Up @@ -1077,7 +1077,7 @@ default void containsText(String expected) {
* <p> Let's see how we can use the assertion:
* <pre>{@code
* // ✓ Contains the right items in the right order
* assertThat(page.locator("ul > li")).containsText(new String[] {"Text 1", "Text 3", "Text 4"});
* assertThat(page.locator("ul > li")).containsText(new String[] {"Text 1", "Text 3"});
*
* // ✖ Wrong order
* assertThat(page.locator("ul > li")).containsText(new String[] {"Text 3", "Text 2"});
Expand Down Expand Up @@ -1122,7 +1122,7 @@ default void containsText(Pattern expected) {
* <p> Let's see how we can use the assertion:
* <pre>{@code
* // ✓ Contains the right items in the right order
* assertThat(page.locator("ul > li")).containsText(new String[] {"Text 1", "Text 3", "Text 4"});
* assertThat(page.locator("ul > li")).containsText(new String[] {"Text 1", "Text 3"});
*
* // ✖ Wrong order
* assertThat(page.locator("ul > li")).containsText(new String[] {"Text 3", "Text 2"});
Expand Down Expand Up @@ -1165,7 +1165,7 @@ default void containsText(Pattern expected) {
* <p> Let's see how we can use the assertion:
* <pre>{@code
* // ✓ Contains the right items in the right order
* assertThat(page.locator("ul > li")).containsText(new String[] {"Text 1", "Text 3", "Text 4"});
* assertThat(page.locator("ul > li")).containsText(new String[] {"Text 1", "Text 3"});
*
* // ✖ Wrong order
* assertThat(page.locator("ul > li")).containsText(new String[] {"Text 3", "Text 2"});
Expand Down Expand Up @@ -1210,7 +1210,7 @@ default void containsText(String[] expected) {
* <p> Let's see how we can use the assertion:
* <pre>{@code
* // ✓ Contains the right items in the right order
* assertThat(page.locator("ul > li")).containsText(new String[] {"Text 1", "Text 3", "Text 4"});
* assertThat(page.locator("ul > li")).containsText(new String[] {"Text 1", "Text 3"});
*
* // ✖ Wrong order
* assertThat(page.locator("ul > li")).containsText(new String[] {"Text 3", "Text 2"});
Expand Down Expand Up @@ -1253,7 +1253,7 @@ default void containsText(String[] expected) {
* <p> Let's see how we can use the assertion:
* <pre>{@code
* // ✓ Contains the right items in the right order
* assertThat(page.locator("ul > li")).containsText(new String[] {"Text 1", "Text 3", "Text 4"});
* assertThat(page.locator("ul > li")).containsText(new String[] {"Text 1", "Text 3"});
*
* // ✖ Wrong order
* assertThat(page.locator("ul > li")).containsText(new String[] {"Text 3", "Text 2"});
Expand Down Expand Up @@ -1298,7 +1298,7 @@ default void containsText(Pattern[] expected) {
* <p> Let's see how we can use the assertion:
* <pre>{@code
* // ✓ Contains the right items in the right order
* assertThat(page.locator("ul > li")).containsText(new String[] {"Text 1", "Text 3", "Text 4"});
* assertThat(page.locator("ul > li")).containsText(new String[] {"Text 1", "Text 3"});
*
* // ✖ Wrong order
* assertThat(page.locator("ul > li")).containsText(new String[] {"Text 3", "Text 2"});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,8 @@ void saveAsShouldThrowWhenNoVideoFrames(@TempDir Path videosDir) {
if (!popup.isClosed()) {
popup.waitForClose(() -> {});
}
// WebKit pauses renderer before win.close() and actually writes something.
if (isWebKit()) {
popup.video().saveAs(saveAsPath);
assertTrue(Files.exists(saveAsPath));
} else {
PlaywrightException e = assertThrows(PlaywrightException.class, () -> popup.video().saveAs(saveAsPath));
assertTrue(e.getMessage().contains("Page did not produce any video frames"), e.getMessage());
}
PlaywrightException e = assertThrows(PlaywrightException.class, () -> popup.video().saveAs(saveAsPath));
assertTrue(e.getMessage().contains("Page did not produce any video frames"), e.getMessage());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,9 @@ void shouldFormatNumberUsingContextLocale() {
page.navigate(server.EMPTY_PAGE);
Worker worker = page.waitForWorker(() -> page.evaluate(
"() => new Worker(URL.createObjectURL(new Blob(['console.log(1)'], {type: 'application/javascript'})))"));
assertEquals("10\u00A0000,2", worker.evaluate("() => (10000.20).toLocaleString()"));
// https://github.com/microsoft/playwright/issues/38919
String expected = isFirefox() ? "10,000.2" : "10\u00A0000,2";
assertEquals(expected, worker.evaluate("() => (10000.20).toLocaleString()"));
context.close();
}

Expand Down
20 changes: 4 additions & 16 deletions playwright/src/test/java/com/microsoft/playwright/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,24 +37,12 @@
import static org.junit.jupiter.api.Assertions.assertEquals;

public class Utils {
private static final AtomicInteger nextUnusedPort = new AtomicInteger(9000);

private static boolean available(int port) {
try (ServerSocket ignored = new ServerSocket(port)) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this didn't work for me locally 🤷 i always got "address already in use"

return true;
} catch (IOException ignored) {
return false;
}
}

public static int nextFreePort() {
for (int i = 0; i < 100; i++) {
int port = nextUnusedPort.getAndIncrement();
if (available(port)) {
return port;
}
try (ServerSocket socket = new ServerSocket(0)) {
return socket.getLocalPort();
} catch (IOException e) {
throw new RuntimeException("Cannot find free port", e);
}
throw new RuntimeException("Cannot find free port: " + nextUnusedPort.get());
}

static void assertJsonEquals(Object expected, Object actual) {
Expand Down
2 changes: 1 addition & 1 deletion scripts/DRIVER_VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.57.0-beta-1764692940000
1.58.0
Loading