diff --git a/README.md b/README.md index 6fda0136..59ac691e 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ Playwright is a Java library to automate [Chromium](https://www.chromium.org/Hom | | Linux | macOS | Windows | | :--- | :---: | :---: | :---: | -| Chromium 101.0.4915.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| Chromium 101.0.4929.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | | WebKit 15.4 | ✅ | ✅ | ✅ | -| Firefox 96.0.1 | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| Firefox 97.0.1 | :white_check_mark: | :white_check_mark: | :white_check_mark: | Headless execution is supported for all the browsers on all platforms. Check out [system requirements](https://playwright.dev/java/docs/next/intro/#system-requirements) for details. diff --git a/playwright/src/main/java/com/microsoft/playwright/ElementHandle.java b/playwright/src/main/java/com/microsoft/playwright/ElementHandle.java index de4bcf67..9ba924d9 100644 --- a/playwright/src/main/java/com/microsoft/playwright/ElementHandle.java +++ b/playwright/src/main/java/com/microsoft/playwright/ElementHandle.java @@ -570,10 +570,14 @@ public interface ElementHandle extends JSHandle { } class ScreenshotOptions { /** - * When true, stops CSS animations, CSS transitions and Web Animations. Animations get different treatment depending on - * their duration: + * When set to {@code "disabled"}, stops CSS animations, CSS transitions and Web Animations. Animations get different treatment + * depending on their duration: + * */ - public Boolean disableAnimations; + public ScreenshotAnimations animations; /** * Specify locators that should be masked when the screenshot is taken. Masked elements will be overlayed with a pink box * {@code #FF00FF} that completely covers its bounding box. @@ -606,11 +610,15 @@ public interface ElementHandle extends JSHandle { public ScreenshotType type; /** - * When true, stops CSS animations, CSS transitions and Web Animations. Animations get different treatment depending on - * their duration: + * When set to {@code "disabled"}, stops CSS animations, CSS transitions and Web Animations. Animations get different treatment + * depending on their duration: + * */ - public ScreenshotOptions setDisableAnimations(boolean disableAnimations) { - this.disableAnimations = disableAnimations; + public ScreenshotOptions setAnimations(ScreenshotAnimations animations) { + this.animations = animations; return this; } /** diff --git a/playwright/src/main/java/com/microsoft/playwright/Locator.java b/playwright/src/main/java/com/microsoft/playwright/Locator.java index 1dce57fb..ed45d4f8 100644 --- a/playwright/src/main/java/com/microsoft/playwright/Locator.java +++ b/playwright/src/main/java/com/microsoft/playwright/Locator.java @@ -950,10 +950,14 @@ public interface Locator { } class ScreenshotOptions { /** - * When true, stops CSS animations, CSS transitions and Web Animations. Animations get different treatment depending on - * their duration: + * When set to {@code "disabled"}, stops CSS animations, CSS transitions and Web Animations. Animations get different treatment + * depending on their duration: + * */ - public Boolean disableAnimations; + public ScreenshotAnimations animations; /** * Specify locators that should be masked when the screenshot is taken. Masked elements will be overlayed with a pink box * {@code #FF00FF} that completely covers its bounding box. @@ -986,11 +990,15 @@ public interface Locator { public ScreenshotType type; /** - * When true, stops CSS animations, CSS transitions and Web Animations. Animations get different treatment depending on - * their duration: + * When set to {@code "disabled"}, stops CSS animations, CSS transitions and Web Animations. Animations get different treatment + * depending on their duration: + * */ - public ScreenshotOptions setDisableAnimations(boolean disableAnimations) { - this.disableAnimations = disableAnimations; + public ScreenshotOptions setAnimations(ScreenshotAnimations animations) { + this.animations = animations; return this; } /** diff --git a/playwright/src/main/java/com/microsoft/playwright/Page.java b/playwright/src/main/java/com/microsoft/playwright/Page.java index 0a8b5654..0e8590ee 100644 --- a/playwright/src/main/java/com/microsoft/playwright/Page.java +++ b/playwright/src/main/java/com/microsoft/playwright/Page.java @@ -1976,15 +1976,19 @@ public interface Page extends AutoCloseable { } } class ScreenshotOptions { + /** + * When set to {@code "disabled"}, stops CSS animations, CSS transitions and Web Animations. Animations get different treatment + * depending on their duration: + * + */ + public ScreenshotAnimations animations; /** * An object which specifies clipping of the resulting image. Should have the following fields: */ public Clip clip; - /** - * When true, stops CSS animations, CSS transitions and Web Animations. Animations get different treatment depending on - * their duration: - */ - public Boolean disableAnimations; /** * When true, takes a screenshot of the full scrollable page, instead of the currently visible viewport. Defaults to * {@code false}. @@ -2021,6 +2025,18 @@ public interface Page extends AutoCloseable { */ public ScreenshotType type; + /** + * When set to {@code "disabled"}, stops CSS animations, CSS transitions and Web Animations. Animations get different treatment + * depending on their duration: + * + */ + public ScreenshotOptions setAnimations(ScreenshotAnimations animations) { + this.animations = animations; + return this; + } /** * An object which specifies clipping of the resulting image. Should have the following fields: */ @@ -2034,14 +2050,6 @@ public interface Page extends AutoCloseable { this.clip = clip; return this; } - /** - * When true, stops CSS animations, CSS transitions and Web Animations. Animations get different treatment depending on - * their duration: - */ - public ScreenshotOptions setDisableAnimations(boolean disableAnimations) { - this.disableAnimations = disableAnimations; - return this; - } /** * When true, takes a screenshot of the full scrollable page, instead of the currently visible viewport. Defaults to * {@code false}. diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java b/playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java index 7fb59a7e..ba0b3329 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java @@ -40,6 +40,7 @@ class Serialization { .registerTypeAdapter(Media.class, new ToLowerCaseSerializer()) .registerTypeAdapter(ForcedColors.class, new ToLowerCaseSerializer()) .registerTypeAdapter(ReducedMotion.class, new ToLowerCaseAndDashSerializer()) + .registerTypeAdapter(ScreenshotAnimations.class, new ToLowerCaseSerializer()) .registerTypeAdapter(ScreenshotType.class, new ToLowerCaseSerializer()) .registerTypeAdapter(MouseButton.class, new ToLowerCaseSerializer()) .registerTypeAdapter(LoadState.class, new ToLowerCaseSerializer()) diff --git a/playwright/src/main/java/com/microsoft/playwright/options/ScreenshotAnimations.java b/playwright/src/main/java/com/microsoft/playwright/options/ScreenshotAnimations.java new file mode 100644 index 00000000..b1a73138 --- /dev/null +++ b/playwright/src/main/java/com/microsoft/playwright/options/ScreenshotAnimations.java @@ -0,0 +1,21 @@ +/* + * 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 ScreenshotAnimations { + DISABLED +} \ No newline at end of file diff --git a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextAddCookies.java b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextAddCookies.java index 1703eae1..06d51a03 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextAddCookies.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextAddCookies.java @@ -346,7 +346,21 @@ public class TestBrowserContextAddCookies extends TestBase { "}", server.CROSS_PROCESS_PREFIX + "/grid.html"); page.frames().get(1).evaluate("document.cookie = 'username=John Doe'"); page.waitForTimeout(2000); + boolean allowsThirdParty = isFirefox(); List cookies = context.cookies(server.CROSS_PROCESS_PREFIX + "/grid.html"); - assertEquals(0, cookies.size()); + if (allowsThirdParty) { + assertJsonEquals("[{\n" + + " 'domain': '127.0.0.1',\n" + + " 'expires': -1,\n" + + " 'httpOnly': false,\n" + + " 'name': 'username',\n" + + " 'path': '/',\n" + + " 'sameSite': 'NONE',\n" + + " 'secure': false,\n" + + " 'value': 'John Doe'\n" + + "}]", cookies); + } else { + assertEquals(0, cookies.size()); + } } } diff --git a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextCookies.java b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextCookies.java index 1d191fcd..fb405932 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextCookies.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextCookies.java @@ -50,7 +50,7 @@ public class TestBrowserContextCookies extends TestBase { " expires: -1,\n" + " httpOnly: false,\n" + " secure: false,\n" + - " sameSite: '" + (isChromium() || isFirefox() ? "LAX" : "NONE") +"'\n" + + " sameSite: '" + (isChromium() ? "LAX" : "NONE") +"'\n" + " }]", cookies); } @@ -74,7 +74,7 @@ public class TestBrowserContextCookies extends TestBase { assertEquals(timestamp, cookie.expires); assertEquals(false, cookie.httpOnly); assertEquals(false, cookie.secure); - if (isChromium() || isFirefox()) { + if (isChromium()) { assertEquals(SameSiteAttribute.LAX, cookie.sameSite); } else { assertEquals(SameSiteAttribute.NONE, cookie.sameSite); @@ -146,7 +146,7 @@ public class TestBrowserContextCookies extends TestBase { " expires: -1,\n" + " httpOnly: false,\n" + " secure: false,\n" + - " sameSite: '" + (isChromium() || isFirefox() ? "LAX" : "NONE") +"'\n" + + " sameSite: '" + (isChromium() ? "LAX" : "NONE") +"'\n" + " },\n" + " {\n" + " name: 'username',\n" + @@ -156,7 +156,7 @@ public class TestBrowserContextCookies extends TestBase { " expires: -1,\n" + " httpOnly: false,\n" + " secure: false,\n" + - " sameSite: '" + (isChromium() || isFirefox() ? "LAX" : "NONE") +"'\n" + + " sameSite: '" + (isChromium() ? "LAX" : "NONE") +"'\n" + " }\n" + "]", cookies); } diff --git a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextNetworkEvents.java b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextNetworkEvents.java index bc9b4e39..29c08bfe 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextNetworkEvents.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextNetworkEvents.java @@ -16,6 +16,7 @@ package com.microsoft.playwright; +import com.sun.net.httpserver.Filter; import org.junit.jupiter.api.Test; import java.util.ArrayList; @@ -33,10 +34,19 @@ public class TestBrowserContextNetworkEvents extends TestBase { page.setContent("yo"); Page page1 = context.waitForPage(() -> page.click("a")); page1.waitForLoadState(); - assertEquals(asList( - server.EMPTY_PAGE, - server.PREFIX + "/one-style.html", - server.PREFIX + "/one-style.css"), requests); + // In firefox one-style.css is requested multiple times. + if (isFirefox()) { + assertEquals(asList( + server.EMPTY_PAGE, + server.PREFIX + "/one-style.html", + server.PREFIX + "/one-style.css", + server.PREFIX + "/one-style.css"), requests); + } else { + assertEquals(asList( + server.EMPTY_PAGE, + server.PREFIX + "/one-style.html", + server.PREFIX + "/one-style.css"), requests); + } } @Test @@ -47,10 +57,19 @@ public class TestBrowserContextNetworkEvents extends TestBase { page.setContent("yo"); Page page1 = context.waitForPage(() -> page.click("a")); page1.waitForLoadState(); - assertEquals(asList( - server.EMPTY_PAGE, - server.PREFIX + "/one-style.html", - server.PREFIX + "/one-style.css"), responses); + // In firefox one-style.css is requested multiple times. + if (isFirefox()) { + assertEquals(asList( + server.EMPTY_PAGE, + server.PREFIX + "/one-style.html", + server.PREFIX + "/one-style.css", + server.PREFIX + "/one-style.css"), responses); + } else { + assertEquals(asList( + server.EMPTY_PAGE, + server.PREFIX + "/one-style.html", + server.PREFIX + "/one-style.css"), responses); + } } @Test @@ -59,7 +78,12 @@ public class TestBrowserContextNetworkEvents extends TestBase { List failedRequests = new ArrayList<>(); context.onRequestFailed(request -> failedRequests.add(request)); page.navigate(server.PREFIX + "/one-style.html"); - assertEquals(1, failedRequests.size()); + // In firefox one-style.css is requested multiple times. + if (isFirefox()) { + assertTrue(failedRequests.size() > 0); + } else { + assertEquals(1, failedRequests.size()); + } assertTrue(failedRequests.get(0).url().contains("one-style.css")); assertNull(failedRequests.get(0).response()); assertEquals("stylesheet", failedRequests.get(0).resourceType()); diff --git a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextRoute.java b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextRoute.java index fb300806..5fb7b6e6 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextRoute.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextRoute.java @@ -140,8 +140,10 @@ public class TestBrowserContextRoute extends TestBase { @Test void shouldOverwritePostBodyWithEmptyString() throws ExecutionException, InterruptedException { + boolean[] routeHandled = {false}; context.route("**/empty.html", route -> { route.resume(new Route.ResumeOptions().setPostData("")); + routeHandled[0] = true; }); Future req = server.futureRequest("/empty.html"); @@ -153,7 +155,9 @@ public class TestBrowserContextRoute extends TestBase { " });\n" + " })()\n" + " "); - + while (!routeHandled[0]) { + page.waitForTimeout(100); + } byte[] body = req.get().postBody; assertEquals(0, body.length); } diff --git a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextStorageState.java b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextStorageState.java index 81269481..3ad573c0 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextStorageState.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextStorageState.java @@ -109,7 +109,7 @@ public class TestBrowserContextStorageState extends TestBase { " 'expires':-1,\n" + " 'httpOnly':false,\n" + " 'secure':false,\n" + - " 'sameSite':'" + (isChromium() || isFirefox() ? "Lax" : "None") + "'\n" + + " 'sameSite':'" + (isChromium() ? "Lax" : "None") + "'\n" + " }],\n" + " 'origins':[\n" + " {\n" + diff --git a/playwright/src/test/java/com/microsoft/playwright/TestElementHandlePress.java b/playwright/src/test/java/com/microsoft/playwright/TestElementHandlePress.java index 905beb34..cfd70427 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestElementHandlePress.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestElementHandlePress.java @@ -48,6 +48,6 @@ public class TestElementHandlePress extends TestBase { void shouldWorkWithNumberInput() { page.setContent(""); page.press("input", "1"); - assertEquals("12", page.evalOnSelector("input", "input => input.value")); + assertEquals(isWebKit() ? "1" : "12", page.evalOnSelector("input", "input => input.value")); } } diff --git a/playwright/src/test/java/com/microsoft/playwright/TestElementHandleType.java b/playwright/src/test/java/com/microsoft/playwright/TestElementHandleType.java index 092a1f2c..1d65fbf4 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestElementHandleType.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestElementHandleType.java @@ -48,6 +48,6 @@ public class TestElementHandleType extends TestBase { void shouldWorkWithNumberInput() { page.setContent(""); page.type("input", "13"); - assertEquals("132", page.evalOnSelector("input", "input => input.value")); + assertEquals(isWebKit() ? "13" : "132", page.evalOnSelector("input", "input => input.value")); } } diff --git a/playwright/src/test/java/com/microsoft/playwright/TestPageEventNetwork.java b/playwright/src/test/java/com/microsoft/playwright/TestPageEventNetwork.java index 6834ff65..d1e592a9 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestPageEventNetwork.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestPageEventNetwork.java @@ -57,7 +57,12 @@ public class TestPageEventNetwork extends TestBase { List failedRequests = new ArrayList<>(); page.onRequestFailed(request -> failedRequests.add(request)); page.navigate(server.PREFIX + "/one-style.html"); - assertEquals(1, failedRequests.size()); + // In firefox one-style.css is requested multiple times. + if (isFirefox()) { + assertTrue(failedRequests.size() > 0); + } else { + assertEquals(1, failedRequests.size()); + } assertTrue(failedRequests.get(0).url().contains("one-style.css")); assertNull(failedRequests.get(0).response()); assertEquals("stylesheet", failedRequests.get(0).resourceType()); diff --git a/playwright/src/test/java/com/microsoft/playwright/TestPageRoute.java b/playwright/src/test/java/com/microsoft/playwright/TestPageRoute.java index efbf1016..0452532e 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestPageRoute.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestPageRoute.java @@ -347,7 +347,12 @@ public class TestPageRoute extends TestBase { assertEquals(200, response.status()); assertTrue(response.url().contains("one-style.html")); - assertEquals(2, intercepted.size()); + // In firefox one-style.css is requested multiple times. + if (isFirefox()) { + assertTrue(intercepted.size() > 1); + } else { + assertEquals(2, intercepted.size()); + } assertEquals("document", intercepted.get(0).resourceType()); assertTrue(intercepted.get(0).url().contains("one-style.html")); @@ -460,7 +465,12 @@ public class TestPageRoute extends TestBase { }); Response response = page.navigate("data:text/html,"); assertNull(response); - assertEquals(1, requests.size()); + // In firefox linked resource is requested multiple times. + if (isFirefox()) { + assertTrue(requests.size() > 0); + } else { + assertEquals(1, requests.size()); + } assertEquals(400, (requests.get(0).response()).status()); } diff --git a/playwright/src/test/java/com/microsoft/playwright/TestPageScreenshot.java b/playwright/src/test/java/com/microsoft/playwright/TestPageScreenshot.java index 3aec00cd..daadc93d 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestPageScreenshot.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestPageScreenshot.java @@ -17,6 +17,7 @@ package com.microsoft.playwright; import com.microsoft.playwright.options.Clip; +import com.microsoft.playwright.options.ScreenshotAnimations; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.opentest4j.AssertionFailedError; @@ -27,6 +28,7 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.nio.file.Paths; +import static com.microsoft.playwright.options.ScreenshotAnimations.DISABLED; import static java.util.Arrays.asList; import static org.junit.jupiter.api.Assertions.*; @@ -67,10 +69,10 @@ public class TestPageScreenshot extends TestBase { void shouldNotCaptureInfiniteCssAnimation() { page.navigate(server.PREFIX + "/rotate-z.html"); Locator div = page.locator("div"); - byte[] screenshot = div.screenshot(new Locator.ScreenshotOptions().setDisableAnimations(true)); + byte[] screenshot = div.screenshot(new Locator.ScreenshotOptions().setAnimations(DISABLED)); for (int i = 0; i < 10; ++i) { rafraf(page); - byte[] newScreenshot = div.screenshot(new Locator.ScreenshotOptions().setDisableAnimations(true)); + byte[] newScreenshot = div.screenshot(new Locator.ScreenshotOptions().setAnimations(DISABLED)); assertArrayEquals(screenshot, newScreenshot); } } @@ -79,10 +81,10 @@ public class TestPageScreenshot extends TestBase { void shouldNotCapturePseudoElementCssAnimation() { page.navigate(server.PREFIX + "/rotate-pseudo.html"); Locator div = page.locator("div"); - byte[] screenshot = div.screenshot(new Locator.ScreenshotOptions().setDisableAnimations(true)); + byte[] screenshot = div.screenshot(new Locator.ScreenshotOptions().setAnimations(DISABLED)); for (int i = 0; i < 10; ++i) { rafraf(page); - byte[] newScreenshot = div.screenshot(new Locator.ScreenshotOptions().setDisableAnimations(true)); + byte[] newScreenshot = div.screenshot(new Locator.ScreenshotOptions().setAnimations(DISABLED)); assertArrayEquals(screenshot, newScreenshot); } } @@ -90,10 +92,10 @@ public class TestPageScreenshot extends TestBase { @Test void shouldNotCaptureCssAnimationsInShadowDOM() { page.navigate(server.PREFIX + "/rotate-z-shadow-dom.html"); - byte[] screenshot = page.screenshot(new Page.ScreenshotOptions().setDisableAnimations(true)); + byte[] screenshot = page.screenshot(new Page.ScreenshotOptions().setAnimations(DISABLED)); for (int i = 0; i < 10; ++i) { rafraf(page); - byte[] newScreenshot = page.screenshot(new Page.ScreenshotOptions().setDisableAnimations(true)); + byte[] newScreenshot = page.screenshot(new Page.ScreenshotOptions().setAnimations(DISABLED)); assertArrayEquals(screenshot, newScreenshot); } } @@ -101,7 +103,7 @@ public class TestPageScreenshot extends TestBase { @Test void shouldResumeInfiniteAnimations() { page.navigate(server.PREFIX + "/rotate-z.html"); - page.screenshot(new Page.ScreenshotOptions().setDisableAnimations(true)); + page.screenshot(new Page.ScreenshotOptions().setAnimations(DISABLED)); byte[] buffer1 = page.screenshot(); rafraf(page); byte[] buffer2 = page.screenshot(); @@ -117,10 +119,10 @@ public class TestPageScreenshot extends TestBase { void shouldNotCaptureInfiniteWebAnimations() { page.navigate(server.PREFIX + "/web-animation.html"); Locator div = page.locator("div"); - byte[] screenshot = div.screenshot(new Locator.ScreenshotOptions().setDisableAnimations(true)); + byte[] screenshot = div.screenshot(new Locator.ScreenshotOptions().setAnimations(DISABLED)); for (int i = 0; i < 10; ++i) { rafraf(page); - byte[] newScreenshot = div.screenshot(new Locator.ScreenshotOptions().setDisableAnimations(true)); + byte[] newScreenshot = div.screenshot(new Locator.ScreenshotOptions().setAnimations(DISABLED)); assertArrayEquals(screenshot, newScreenshot); } // Should resume infinite web animation. diff --git a/scripts/CLI_VERSION b/scripts/CLI_VERSION index 8333e579..2e12fedf 100644 --- a/scripts/CLI_VERSION +++ b/scripts/CLI_VERSION @@ -1 +1 @@ -1.20.0-alpha-mar-4-2022 +1.20.0-beta-1646855573000