From 536f5e82d1555e3b53141a81c66fee2ebdf0b379 Mon Sep 17 00:00:00 2001 From: Playwright Service <89237858+playwrightmachine@users.noreply.github.com> Date: Fri, 4 Oct 2024 03:18:14 -0700 Subject: [PATCH] feat(roll): roll to ToT Playwright (04-10-24) (#1545) --- java/docs/accessibility-testing.mdx | 96 ++++++++++--------- java/docs/api-testing.mdx | 54 ++++++----- java/docs/api/class-apiresponseassertions.mdx | 8 +- java/docs/api/class-browser.mdx | 22 ++--- java/docs/api/class-browsercontext.mdx | 5 +- java/docs/api/class-consolemessage.mdx | 4 +- java/docs/api/class-formdata.mdx | 6 +- java/docs/api/class-frame.mdx | 10 +- java/docs/api/class-framelocator.mdx | 10 +- java/docs/api/class-keyboard.mdx | 2 +- java/docs/api/class-locator.mdx | 12 +-- java/docs/api/class-locatorassertions.mdx | 8 +- java/docs/api/class-page.mdx | 51 +++++----- java/docs/api/class-pageassertions.mdx | 6 +- java/docs/api/class-playwrightassertions.mdx | 5 +- java/docs/emulation.mdx | 4 +- java/docs/locators.mdx | 12 +-- java/docs/mock.mdx | 13 +-- java/docs/network.mdx | 6 +- java/docs/pom.mdx | 2 +- java/docs/release-notes.mdx | 16 ++-- java/docs/screenshots.mdx | 2 +- java/docs/test-runners.mdx | 4 +- 23 files changed, 184 insertions(+), 174 deletions(-) diff --git a/java/docs/accessibility-testing.mdx b/java/docs/accessibility-testing.mdx index 3d8cc9a233..08e9c49bef 100644 --- a/java/docs/accessibility-testing.mdx +++ b/java/docs/accessibility-testing.mdx @@ -73,22 +73,24 @@ For example, you can use [`AxeBuilder.include()`](https://github.com/dequelabs/a `AxeBuilder.analyze()` will scan the page *in its current state* when you call it. To scan parts of a page that are revealed based on UI interactions, use [Locators](./locators.mdx) to interact with the page before invoking `analyze()`: ```java -@Test -void navigationMenuFlyoutShouldNotHaveAutomaticallyDetectableAccessibilityViolations() throws Exception { - page.navigate("https://your-site.com/"); +public class HomepageTests { + @Test + void navigationMenuFlyoutShouldNotHaveAutomaticallyDetectableAccessibilityViolations() throws Exception { + page.navigate("https://your-site.com/"); - page.locator("button[aria-label=\"Navigation Menu\"]").click(); + page.locator("button[aria-label=\"Navigation Menu\"]").click(); - // It is important to waitFor() the page to be in the desired - // state *before* running analyze(). Otherwise, axe might not - // find all the elements your test expects it to scan. - page.locator("#navigation-menu-flyout").waitFor(); + // It is important to waitFor() the page to be in the desired + // state *before* running analyze(). Otherwise, axe might not + // find all the elements your test expects it to scan. + page.locator("#navigation-menu-flyout").waitFor(); - AxeResults accessibilityScanResults = new AxeBuilder(page) - .include(Arrays.asList("#navigation-menu-flyout")) - .analyze(); + AxeResults accessibilityScanResults = new AxeBuilder(page) + .include(Arrays.asList("#navigation-menu-flyout")) + .analyze(); - assertEquals(Collections.emptyList(), accessibilityScanResults.getViolations()); + assertEquals(Collections.emptyList(), accessibilityScanResults.getViolations()); + } } ``` @@ -160,38 +162,40 @@ This approach avoids the downsides of using `AxeBuilder.exclude()` at the cost o Here is an example of using fingerprints based on only rule IDs and "target" selectors pointing to each violation: ```java -@Test -shouldOnlyHaveAccessibilityViolationsMatchingKnownFingerprints() throws Exception { - page.navigate("https://your-site.com/"); +public class HomepageTests { + @Test + shouldOnlyHaveAccessibilityViolationsMatchingKnownFingerprints() throws Exception { + page.navigate("https://your-site.com/"); - AxeResults accessibilityScanResults = new AxeBuilder(page).analyze(); + AxeResults accessibilityScanResults = new AxeBuilder(page).analyze(); - List violationFingerprints = fingerprintsFromScanResults(accessibilityScanResults); + List violationFingerprints = fingerprintsFromScanResults(accessibilityScanResults); - assertEquals(Arrays.asList( - new ViolationFingerprint("aria-roles", "[span[role=\"invalid\"]]"), - new ViolationFingerprint("color-contrast", "[li:nth-child(2) > span]"), - new ViolationFingerprint("label", "[input]") - ), violationFingerprints); -} + assertEquals(Arrays.asList( + new ViolationFingerprint("aria-roles", "[span[role=\"invalid\"]]"), + new ViolationFingerprint("color-contrast", "[li:nth-child(2) > span]"), + new ViolationFingerprint("label", "[input]") + ), violationFingerprints); + } -// You can make your "fingerprint" as specific as you like. This one considers a violation to be -// "the same" if it corresponds the same Axe rule on the same element. -// -// Using a record type makes it easy to compare fingerprints with assertEquals -public record ViolationFingerprint(String ruleId, String target) { } - -public List fingerprintsFromScanResults(AxeResults results) { - return results.getViolations().stream() - // Each violation refers to one rule and multiple "nodes" which violate it - .flatMap(violation -> violation.getNodes().stream() - .map(node -> new ViolationFingerprint( - violation.getId(), - // Each node contains a "target", which is a CSS selector that uniquely identifies it - // If the page involves iframes or shadow DOMs, it may be a chain of CSS selectors - node.getTarget().toString() - ))) - .collect(Collectors.toList()); + // You can make your "fingerprint" as specific as you like. This one considers a violation to be + // "the same" if it corresponds the same Axe rule on the same element. + // + // Using a record type makes it easy to compare fingerprints with assertEquals + public record ViolationFingerprint(String ruleId, String target) { } + + public List fingerprintsFromScanResults(AxeResults results) { + return results.getViolations().stream() + // Each violation refers to one rule and multiple "nodes" which violate it + .flatMap(violation -> violation.getNodes().stream() + .map(node -> new ViolationFingerprint( + violation.getId(), + // Each node contains a "target", which is a CSS selector that uniquely identifies it + // If the page involves iframes or shadow DOMs, it may be a chain of CSS selectors + node.getTarget().toString() + ))) + .collect(Collectors.toList()); + } } ``` @@ -210,11 +214,11 @@ This example fixture creates an `AxeBuilder` object which is pre-configured with ```java class AxeTestFixtures extends TestFixtures { - AxeBuilder makeAxeBuilder() { - return new AxeBuilder(page) - .withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa']) - .exclude('#commonly-reused-element-with-known-issue'); - } + AxeBuilder makeAxeBuilder() { + return new AxeBuilder(page) + .withTags(new String[]{"wcag2a", "wcag2aa", "wcag21a", "wcag21aa"}) + .exclude("#commonly-reused-element-with-known-issue"); + } } ``` @@ -231,7 +235,7 @@ public class HomepageTests extends AxeTestFixtures { AxeResults accessibilityScanResults = makeAxeBuilder() // Automatically uses the shared AxeBuilder configuration, // but supports additional test-specific configuration too - .include('#specific-element-under-test') + .include("#specific-element-under-test") .analyze(); assertEquals(Collections.emptyList(), accessibilityScanResults.getViolations()); diff --git a/java/docs/api-testing.mdx b/java/docs/api-testing.mdx index f0adcbd1d3..700fc7f0dc 100644 --- a/java/docs/api-testing.mdx +++ b/java/docs/api-testing.mdx @@ -196,6 +196,7 @@ public class TestGitHubAPI { These tests assume that repository exists. You probably want to create a new one before running tests and delete it afterwards. Use `@BeforeAll` and `@AfterAll` hooks for that. ```java +public class TestGitHubAPI { // ... void createTestRepository() { @@ -225,6 +226,7 @@ These tests assume that repository exists. You probably want to create a new one disposeAPIRequestContext(); closePlaywright(); } +} ``` ### Complete test example @@ -382,18 +384,20 @@ See experimental [JUnit integration](./junit.mdx) to automatically initialize Pl The following test creates a new issue via API and then navigates to the list of all issues in the project to check that it appears at the top of the list. The check is performed using [LocatorAssertions]. ```java -@Test -void lastCreatedIssueShouldBeFirstInTheList() { - Map data = new HashMap<>(); - data.put("title", "[Feature] request 1"); - data.put("body", "Feature description"); - APIResponse newIssue = request.post("/repos/" + USER + "/" + REPO + "/issues", - RequestOptions.create().setData(data)); - assertTrue(newIssue.ok()); - - page.navigate("https://github.com/" + USER + "/" + REPO + "/issues"); - Locator firstIssue = page.locator("a[data-hovercard-type='issue']").first(); - assertThat(firstIssue).hasText("[Feature] request 1"); +public class TestGitHubAPI { + @Test + void lastCreatedIssueShouldBeFirstInTheList() { + Map data = new HashMap<>(); + data.put("title", "[Feature] request 1"); + data.put("body", "Feature description"); + APIResponse newIssue = request.post("/repos/" + USER + "/" + REPO + "/issues", + RequestOptions.create().setData(data)); + assertTrue(newIssue.ok()); + + page.navigate("https://github.com/" + USER + "/" + REPO + "/issues"); + Locator firstIssue = page.locator("a[data-hovercard-type='issue']").first(); + assertThat(firstIssue).hasText("[Feature] request 1"); + } } ``` @@ -402,18 +406,20 @@ void lastCreatedIssueShouldBeFirstInTheList() { The following test creates a new issue via user interface in the browser and then checks via API if it was created: ```java -@Test -void lastCreatedIssueShouldBeOnTheServer() { - page.navigate("https://github.com/" + USER + "/" + REPO + "/issues"); - page.locator("text=New Issue").click(); - page.locator("[aria-label='Title']").fill("Bug report 1"); - page.locator("[aria-label='Comment body']").fill("Bug description"); - page.locator("text=Submit new issue").click(); - String issueId = page.url().substring(page.url().lastIndexOf('/')); - - APIResponse newIssue = request.get("https://github.com/" + USER + "/" + REPO + "/issues/" + issueId); - assertThat(newIssue).isOK(); - assertTrue(newIssue.text().contains("Bug report 1")); +public class TestGitHubAPI { + @Test + void lastCreatedIssueShouldBeOnTheServer() { + page.navigate("https://github.com/" + USER + "/" + REPO + "/issues"); + page.locator("text=New Issue").click(); + page.locator("[aria-label='Title']").fill("Bug report 1"); + page.locator("[aria-label='Comment body']").fill("Bug description"); + page.locator("text=Submit new issue").click(); + String issueId = page.url().substring(page.url().lastIndexOf('/')); + + APIResponse newIssue = request.get("https://github.com/" + USER + "/" + REPO + "/issues/" + issueId); + assertThat(newIssue).isOK(); + assertTrue(newIssue.text().contains("Bug report 1")); + } } ``` diff --git a/java/docs/api/class-apiresponseassertions.mdx b/java/docs/api/class-apiresponseassertions.mdx index ed7a92943e..64d80b3b79 100644 --- a/java/docs/api/class-apiresponseassertions.mdx +++ b/java/docs/api/class-apiresponseassertions.mdx @@ -10,15 +10,15 @@ import HTMLCard from '@site/src/components/HTMLCard'; The [APIResponseAssertions] class provides assertion methods that can be used to make assertions about the [APIResponse] in the tests. ```java -... +// ... import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; public class TestPage { - ... + // ... @Test void navigatesToLoginPage() { - ... - APIResponse response = page.request().get('https://playwright.dev'); + // ... + APIResponse response = page.request().get("https://playwright.dev"); assertThat(response).isOK(); } } diff --git a/java/docs/api/class-browser.mdx b/java/docs/api/class-browser.mdx index 203dbe43e5..151de5bcbf 100644 --- a/java/docs/api/class-browser.mdx +++ b/java/docs/api/class-browser.mdx @@ -13,15 +13,15 @@ A Browser is created via [BrowserType.launch()](/api/class-browsertype.mdx#brows import com.microsoft.playwright.*; public class Example { - public static void main(String[] args) { - try (Playwright playwright = Playwright.create()) { - BrowserType firefox = playwright.firefox() - Browser browser = firefox.launch(); - Page page = browser.newPage(); - page.navigate('https://example.com'); - browser.close(); - } - } + public static void main(String[] args) { + try (Playwright playwright = Playwright.create()) { + BrowserType firefox = playwright.firefox(); + Browser browser = firefox.launch(); + Page page = browser.newPage(); + page.navigate("https://example.com"); + browser.close(); + } + } } ``` @@ -158,7 +158,7 @@ Browser browser = playwright.firefox().launch(); // Or 'chromium' or 'webkit'. BrowserContext context = browser.newContext(); // Create a new page in a pristine context. Page page = context.newPage(); -page.navigate('https://example.com'); +page.navigate("https://example.com"); // Graceful close up everything context.close(); @@ -598,7 +598,7 @@ You can use [Browser.startTracing()](/api/class-browser.mdx#browser-start-tracin ```java browser.startTracing(page, new Browser.StartTracingOptions() .setPath(Paths.get("trace.json"))); -page.goto('https://www.google.com'); +page.navigate("https://www.google.com"); browser.stopTracing(); ``` diff --git a/java/docs/api/class-browsercontext.mdx b/java/docs/api/class-browsercontext.mdx index 380ab44ff9..80ba72c3bc 100644 --- a/java/docs/api/class-browsercontext.mdx +++ b/java/docs/api/class-browsercontext.mdx @@ -302,7 +302,7 @@ import com.microsoft.playwright.*; public class Example { public static void main(String[] args) { try (Playwright playwright = Playwright.create()) { - BrowserType webkit = playwright.webkit() + BrowserType webkit = playwright.webkit(); Browser browser = webkit.launch(new BrowserType.LaunchOptions().setHeadless(false)); BrowserContext context = browser.newContext(); context.exposeBinding("pageURL", (source, args) -> source.page().url()); @@ -367,8 +367,9 @@ import java.util.Base64; public class Example { public static void main(String[] args) { try (Playwright playwright = Playwright.create()) { - BrowserType webkit = playwright.webkit() + BrowserType webkit = playwright.webkit(); Browser browser = webkit.launch(new BrowserType.LaunchOptions().setHeadless(false)); + BrowserContext context = browser.newContext(); context.exposeFunction("sha256", args -> { String text = (String) args[0]; MessageDigest crypto; diff --git a/java/docs/api/class-consolemessage.mdx b/java/docs/api/class-consolemessage.mdx index 2414d50e3f..980e220211 100644 --- a/java/docs/api/class-consolemessage.mdx +++ b/java/docs/api/class-consolemessage.mdx @@ -26,8 +26,8 @@ ConsoleMessage msg = page.waitForConsoleMessage(() -> { }); // Deconstruct console.log arguments -msg.args().get(0).jsonValue() // hello -msg.args().get(1).jsonValue() // 42 +msg.args().get(0).jsonValue(); // hello +msg.args().get(1).jsonValue(); // 42 ``` diff --git a/java/docs/api/class-formdata.mdx b/java/docs/api/class-formdata.mdx index 8aa66d7740..7878876ecd 100644 --- a/java/docs/api/class-formdata.mdx +++ b/java/docs/api/class-formdata.mdx @@ -11,7 +11,7 @@ The [FormData] is used create form data that is sent via [APIRequestContext]. ```java import com.microsoft.playwright.options.FormData; -... +// ... FormData form = FormData.create() .set("firstName", "John") .set("lastName", "Doe") @@ -34,7 +34,7 @@ The difference between [FormData.set()](/api/class-formdata.mdx#form-data-set) a ```java import com.microsoft.playwright.options.FormData; -... +// ... FormData form = FormData.create() // Only name and value are set. .append("firstName", "John") @@ -98,7 +98,7 @@ Sets a field on the form. File values can be passed either as `Path` or as `File ```java import com.microsoft.playwright.options.FormData; -... +// ... FormData form = FormData.create() // Only name and value are set. .set("firstName", "John") diff --git a/java/docs/api/class-frame.mdx b/java/docs/api/class-frame.mdx index e0bc829ad6..6287605a7f 100644 --- a/java/docs/api/class-frame.mdx +++ b/java/docs/api/class-frame.mdx @@ -600,19 +600,19 @@ You can locate by text substring, exact string, or a regular expression: ```java // Matches -page.getByText("world") +page.getByText("world"); // Matches first
-page.getByText("Hello world") +page.getByText("Hello world"); // Matches second
-page.getByText("Hello", new Page.GetByTextOptions().setExact(true)) +page.getByText("Hello", new Page.GetByTextOptions().setExact(true)); // Matches both
s -page.getByText(Pattern.compile("Hello")) +page.getByText(Pattern.compile("Hello")); // Matches second
-page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE)) +page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE)); ``` **Arguments** diff --git a/java/docs/api/class-framelocator.mdx b/java/docs/api/class-framelocator.mdx index c1b5203f99..c108618a21 100644 --- a/java/docs/api/class-framelocator.mdx +++ b/java/docs/api/class-framelocator.mdx @@ -318,19 +318,19 @@ You can locate by text substring, exact string, or a regular expression: ```java // Matches -page.getByText("world") +page.getByText("world"); // Matches first
-page.getByText("Hello world") +page.getByText("Hello world"); // Matches second
-page.getByText("Hello", new Page.GetByTextOptions().setExact(true)) +page.getByText("Hello", new Page.GetByTextOptions().setExact(true)); // Matches both
s -page.getByText(Pattern.compile("Hello")) +page.getByText(Pattern.compile("Hello")); // Matches second
-page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE)) +page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE)); ``` **Arguments** diff --git a/java/docs/api/class-keyboard.mdx b/java/docs/api/class-keyboard.mdx index b84c92d8da..e413cd3769 100644 --- a/java/docs/api/class-keyboard.mdx +++ b/java/docs/api/class-keyboard.mdx @@ -140,7 +140,7 @@ Shortcuts such as `key: "Control+o"`, `key: "Control++` or `key: "Control+Shift+ Page page = browser.newPage(); page.navigate("https://keycode.info"); page.keyboard().press("A"); -page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get("A.png")); +page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get("A.png"))); page.keyboard().press("ArrowLeft"); page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get("ArrowLeft.png"))); page.keyboard().press("Shift+O"); diff --git a/java/docs/api/class-locator.mdx b/java/docs/api/class-locator.mdx index 10186d1a02..4630b1e65d 100644 --- a/java/docs/api/class-locator.mdx +++ b/java/docs/api/class-locator.mdx @@ -34,7 +34,7 @@ When the list of elements is stable, but loaded dynamically, wait for the full l **Usage** ```java -for (Locator li : page.getByRole('listitem').all()) +for (Locator li : page.getByRole("listitem").all()) li.click(); ``` @@ -1154,19 +1154,19 @@ You can locate by text substring, exact string, or a regular expression: ```java // Matches -page.getByText("world") +page.getByText("world"); // Matches first
-page.getByText("Hello world") +page.getByText("Hello world"); // Matches second
-page.getByText("Hello", new Page.GetByTextOptions().setExact(true)) +page.getByText("Hello", new Page.GetByTextOptions().setExact(true)); // Matches both
s -page.getByText(Pattern.compile("Hello")) +page.getByText(Pattern.compile("Hello")); // Matches second
-page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE)) +page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE)); ``` **Arguments** diff --git a/java/docs/api/class-locatorassertions.mdx b/java/docs/api/class-locatorassertions.mdx index d6fb0a671a..2aa554cb89 100644 --- a/java/docs/api/class-locatorassertions.mdx +++ b/java/docs/api/class-locatorassertions.mdx @@ -10,14 +10,14 @@ import HTMLCard from '@site/src/components/HTMLCard'; The [LocatorAssertions] class provides assertion methods that can be used to make assertions about the [Locator] state in the tests. ```java -... +// ... import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; public class TestLocator { - ... + // ... @Test void statusBecomesSubmitted() { - ... + // ... page.getByRole(AriaRole.BUTTON).click(); assertThat(page.locator(".status")).hasText("Submitted"); } @@ -478,7 +478,7 @@ For example, given the following element: ``` ```java -page.locator("id=favorite-colors").selectOption(["R", "G"]); +page.locator("id=favorite-colors").selectOption(new String[]{"R", "G"}); assertThat(page.locator("id=favorite-colors")).hasValues(new Pattern[] { Pattern.compile("R"), Pattern.compile("G") }); ``` diff --git a/java/docs/api/class-page.mdx b/java/docs/api/class-page.mdx index f863e2934e..04277d95c9 100644 --- a/java/docs/api/class-page.mdx +++ b/java/docs/api/class-page.mdx @@ -121,12 +121,12 @@ An example that closes a "Sign up to the newsletter" dialog when it appears: ```java // Setup the handler. -page.addLocatorHandler(page.getByText("Sign up to the newsletter"), () => { +page.addLocatorHandler(page.getByText("Sign up to the newsletter"), () -> { page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("No thanks")).click(); }); // Write the test as usual. -page.goto("https://example.com"); +page.navigate("https://example.com"); page.getByRole("button", Page.GetByRoleOptions().setName("Start here")).click(); ``` @@ -134,12 +134,12 @@ An example that skips the "Confirm your security details" page when it is shown: ```java // Setup the handler. -page.addLocatorHandler(page.getByText("Confirm your security details")), () => { +page.addLocatorHandler(page.getByText("Confirm your security details"), () -> { page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Remind me later")).click(); }); // Write the test as usual. -page.goto("https://example.com"); +page.navigate("https://example.com"); page.getByRole("button", Page.GetByRoleOptions().setName("Start here")).click(); ``` @@ -147,19 +147,19 @@ An example with a custom callback on every actionability check. It uses a ` { +page.addLocatorHandler(page.locator("body"), () -> { page.evaluate("window.removeObstructionsForTestIfNeeded()"); -}, new Page.AddLocatorHandlerOptions.setNoWaitAfter(true)); +}, new Page.AddLocatorHandlerOptions().setNoWaitAfter(true)); // Write the test as usual. -page.goto("https://example.com"); +page.navigate("https://example.com"); page.getByRole("button", Page.GetByRoleOptions().setName("Start here")).click(); ``` Handler takes the original locator as an argument. You can also automatically remove the handler after a number of invocations by setting [setTimes](/api/class-page.mdx#page-add-locator-handler-option-times): ```java -page.addLocatorHandler(page.getByLabel("Close"), locator => { +page.addLocatorHandler(page.getByLabel("Close"), locator -> { locator.click(); }, new Page.AddLocatorHandlerOptions().setTimes(1)); ``` @@ -341,9 +341,9 @@ This method drags the source element to the target element. It will first move t **Usage** ```java -page.dragAndDrop("#source", '#target'); +page.dragAndDrop("#source", "#target"); // or specify exact positions relative to the top-left corners of the elements: -page.dragAndDrop("#source", '#target', new Page.DragAndDropOptions() +page.dragAndDrop("#source", "#target", new Page.DragAndDropOptions() .setSourcePosition(34, 7).setTargetPosition(10, 20)); ``` @@ -573,7 +573,7 @@ public class Example { public static void main(String[] args) { try (Playwright playwright = Playwright.create()) { BrowserType webkit = playwright.webkit(); - Browser browser = webkit.launch({ headless: false }); + Browser browser = webkit.launch(new BrowserType.LaunchOptions().setHeadless(false)); BrowserContext context = browser.newContext(); Page page = context.newPage(); page.exposeBinding("pageURL", (source, args) -> source.page().url()); @@ -643,26 +643,27 @@ public class Example { public static void main(String[] args) { try (Playwright playwright = Playwright.create()) { BrowserType webkit = playwright.webkit(); - Browser browser = webkit.launch({ headless: false }); + Browser browser = webkit.launch(new BrowserType.LaunchOptions().setHeadless(false)); Page page = browser.newPage(); page.exposeFunction("sha256", args -> { - String text = (String) args[0]; - MessageDigest crypto; try { - crypto = MessageDigest.getInstance("SHA-256"); + String text = (String) args[0]; + MessageDigest crypto = MessageDigest.getInstance("SHA-256"); + byte[] token = crypto.digest(text.getBytes(StandardCharsets.UTF_8)); + return Base64.getEncoder().encodeToString(token); } catch (NoSuchAlgorithmException e) { return null; } - byte[] token = crypto.digest(text.getBytes(StandardCharsets.UTF_8)); - return Base64.getEncoder().encodeToString(token); }); - page.setContent("\n" + "\n" + - "
\n"); + "
" + ); page.click("button"); } } @@ -695,7 +696,7 @@ Frame frame = page.frame("frame-name"); ``` ```java -Frame frame = page.frameByUrl(Pattern.compile(".*domain.*"); +Frame frame = page.frameByUrl(Pattern.compile(".*domain.*")); ``` **Arguments** @@ -1029,19 +1030,19 @@ You can locate by text substring, exact string, or a regular expression: ```java // Matches -page.getByText("world") +page.getByText("world"); // Matches first
-page.getByText("Hello world") +page.getByText("Hello world"); // Matches second
-page.getByText("Hello", new Page.GetByTextOptions().setExact(true)) +page.getByText("Hello", new Page.GetByTextOptions().setExact(true)); // Matches both
s -page.getByText(Pattern.compile("Hello")) +page.getByText(Pattern.compile("Hello")); // Matches second
-page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE)) +page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE)); ``` **Arguments** diff --git a/java/docs/api/class-pageassertions.mdx b/java/docs/api/class-pageassertions.mdx index 5a9b42c891..905d8f56cf 100644 --- a/java/docs/api/class-pageassertions.mdx +++ b/java/docs/api/class-pageassertions.mdx @@ -10,14 +10,14 @@ import HTMLCard from '@site/src/components/HTMLCard'; The [PageAssertions] class provides assertion methods that can be used to make assertions about the [Page] state in the tests. ```java -... +// ... import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; public class TestPage { - ... + // ... @Test void navigatesToLoginPage() { - ... + // ... page.getByText("Sign in").click(); assertThat(page).hasURL(Pattern.compile(".*/login")); } diff --git a/java/docs/api/class-playwrightassertions.mdx b/java/docs/api/class-playwrightassertions.mdx index 030b17f88e..cb77cf0281 100644 --- a/java/docs/api/class-playwrightassertions.mdx +++ b/java/docs/api/class-playwrightassertions.mdx @@ -12,14 +12,13 @@ Playwright gives you Web-First Assertions with convenience methods for creating Consider the following example: ```java -... import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; public class TestExample { - ... + // ... @Test void statusBecomesSubmitted() { - ... + // ... page.locator("#submit-button").click(); assertThat(page.locator(".status")).hasText("Submitted"); } diff --git a/java/docs/emulation.mdx b/java/docs/emulation.mdx index 9bfa5a90fe..5cf00fe7c6 100644 --- a/java/docs/emulation.mdx +++ b/java/docs/emulation.mdx @@ -33,7 +33,7 @@ page.setViewportSize(1600, 1200); // Emulate high-DPI BrowserContext context = browser.newContext(new Browser.NewContextOptions() .setViewportSize(2560, 1440) - .setDeviceScaleFactor(2); + .setDeviceScaleFactor(2)); ``` ## isMobile @@ -63,7 +63,7 @@ Allow app to show system notifications. ```java BrowserContext context = browser.newContext(new Browser.NewContextOptions() - .setPermissions(Arrays.asList("notifications")); + .setPermissions(Arrays.asList("notifications"))); ``` Allow notifications for a specific domain. diff --git a/java/docs/locators.mdx b/java/docs/locators.mdx index 74779969b2..cb87460f7c 100644 --- a/java/docs/locators.mdx +++ b/java/docs/locators.mdx @@ -63,7 +63,7 @@ Every time a locator is used for an action, an up-to-date DOM element is located ```java Locator locator = page.getByRole(AriaRole.BUTTON, - new Page.GetByRoleOptions().setName("Sign in")) + new Page.GetByRoleOptions().setName("Sign in")); locator.hover(); locator.click(); @@ -524,7 +524,7 @@ page.getByRole(AriaRole.LISTITEM) .setName("Product 2")))) .getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Add to cart")) - .click() + .click(); ``` We can also assert the product card to make sure there is only one: @@ -534,7 +534,7 @@ assertThat(page .getByRole(AriaRole.LISTITEM) .filter(new Locator.FilterOptions() .setHas(page.GetByRole(AriaRole.HEADING, - new Page.GetByRoleOptions().setName("Product 2")))) + new Page.GetByRoleOptions().setName("Product 2"))))) .hasCount(1); ``` @@ -547,7 +547,7 @@ assertThat(page .filter(new Locator.FilterOptions() .setHas(page.GetByRole(AriaRole.LIST) .GetByRole(AriaRole.HEADING, - new Page.GetByRoleOptions().setName("Product 2")))) + new Page.GetByRoleOptions().setName("Product 2"))))) .hasCount(1); ``` @@ -558,7 +558,7 @@ We can also filter by **not having** a matching element inside. ```java assertThat(page .getByRole(AriaRole.LISTITEM) - .filter(new Locator.FilterOptions().setHasNot(page.getByText("Product 2"))) + .filter(new Locator.FilterOptions().setHasNot(page.getByText("Product 2")))) .hasCount(1); ``` @@ -676,7 +676,7 @@ For example, consider the following DOM structure: Use the count assertion to ensure that the list has 3 items. ```java -assertThat(page.getByRole(AriaRole.LISTITEM).hasCount(3); +assertThat(page.getByRole(AriaRole.LISTITEM)).hasCount(3); ``` ### Assert all text in a list diff --git a/java/docs/mock.mdx b/java/docs/mock.mdx index 49e03926e9..5821f4a0ba 100644 --- a/java/docs/mock.mdx +++ b/java/docs/mock.mdx @@ -47,15 +47,15 @@ In the example below we intercept the call to the fruit API and add a new fruit page.route("*/**/api/v1/fruits", route -> { Response response = route.fetch(); byte[] json = response.body(); - parsed = new Gson().fromJson(json, JsonObject.class) + JsonObject parsed = new Gson().fromJson(new String(json), JsonObject.class); parsed.add(new JsonObject().add("name", "Loquat").add("id", 100)); // Fulfill using the original response, while patching the response body // with the given JSON object. - route.fulfill(new Route.FulfillOptions().setResponse(response).setBody(json.toString())); + route.fulfill(new Route.FulfillOptions().setResponse(response).setBody(parsed.toString())); }); // Go to the page -page.goto("https://demo.playwright.dev/api-mocking"); +page.navigate("https://demo.playwright.dev/api-mocking"); // Assert that the Loquat fruit is visible assertThat(page.getByText("Loquat", new Page.GetByTextOptions().setExact(true))).isVisible(); @@ -88,7 +88,7 @@ page.routeFromHAR(Path.of("./hars/fruit.har"), new RouteFromHAROptions() ); // Go to the page -page.goto("https://demo.playwright.dev/api-mocking"); +page.navigate("https://demo.playwright.dev/api-mocking"); // Assert that the fruit is visible assertThat(page.getByText("Strawberry")).isVisible(); @@ -122,10 +122,11 @@ page.routeFromHAR(Path.of("./hars/fruit.har"), new RouteFromHAROptions() ); // Go to the page -page.goto("https://demo.playwright.dev/api-mocking"); +page.navigate("https://demo.playwright.dev/api-mocking"); // Assert that the Playwright fruit is visible -assertThat(page.getByText("Playwright", new Page.GetByTextOptions().setExact(true))).isVisible(); +assertThat(page.getByText("Playwright", new Page.GetByTextOptions() + .setExact(true))).isVisible(); ``` In the trace of our test we can see that the route was fulfilled from the HAR file and the API was not called. ![trace showing the HAR file being used](https://github.com/microsoft/playwright/assets/13063165/1bd7ab66-ea4f-43c2-a4e5-ca17d4837ff1) diff --git a/java/docs/network.mdx b/java/docs/network.mdx index 6e2c2e4f01..65c0e0ee09 100644 --- a/java/docs/network.mdx +++ b/java/docs/network.mdx @@ -39,8 +39,8 @@ Here is an example of a global proxy: ```java Browser browser = chromium.launch(new BrowserType.LaunchOptions() .setProxy(new Proxy("http://myproxy.com:3128") - .setUsername('usr') - .setPassword('pwd'))); + .setUsername("usr") + .setPassword("pwd"))); ``` Its also possible to specify it per context: @@ -164,7 +164,7 @@ page.route("**/title.html", route -> { String body = response.text(); body = body.replace("", "<title>My prefix:"); Map<String, String> headers = response.headers(); - headers.put("content-type": "text/html"); + headers.put("content-type", "text/html"); route.fulfill(new Route.FulfillOptions() // Pass all fields from the response. .setResponse(response) diff --git a/java/docs/pom.mdx b/java/docs/pom.mdx index 243fba6c3a..a4fc343431 100644 --- a/java/docs/pom.mdx +++ b/java/docs/pom.mdx @@ -48,7 +48,7 @@ Page objects can then be used inside a test. ```java import models.SearchPage; import com.microsoft.playwright.*; -... +// ... // In the test Page page = browser.newPage(); diff --git a/java/docs/release-notes.mdx b/java/docs/release-notes.mdx index 21cf2d495e..d17cd6b0c7 100644 --- a/java/docs/release-notes.mdx +++ b/java/docs/release-notes.mdx @@ -356,7 +356,7 @@ New method [Page.addLocatorHandler()](/api/class-page.mdx#page-add-locator-handl // Setup the handler. page.addLocatorHandler( page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Hej! You are in control of your cookies.")), - () - > { + () -> { page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Accept all")).click(); }); // Write the test as usual. @@ -1062,14 +1062,12 @@ Playwright for Java 1.18 introduces [Web-First Assertions](./test-assertions). Consider the following example: ```java -... import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; public class TestExample { - ... @Test void statusBecomesSubmitted() { - ... + // ... page.locator("#submit-button").click(); assertThat(page.locator(".status")).hasText("Submitted"); } @@ -1316,19 +1314,19 @@ button.click("button >> visible=true"); Traces are recorded using the new [BrowserContext.tracing()](/api/class-browsercontext.mdx#browser-context-tracing) API: ```java -Browser browser = chromium.launch(); +Browser browser = playwright.chromium().launch(); BrowserContext context = browser.newContext(); // Start tracing before creating / navigating a page. -context.tracing.start(new Tracing.StartOptions() +context.tracing().start(new Tracing.StartOptions() .setScreenshots(true) - .setSnapshots(true); + .setSnapshots(true)); Page page = context.newPage(); -page.goto("https://playwright.dev"); +page.navigate("https://playwright.dev"); // Stop tracing and export it into a zip archive. -context.tracing.stop(new Tracing.StopOptions() +context.tracing().stop(new Tracing.StopOptions() .setPath(Paths.get("trace.zip"))); ``` diff --git a/java/docs/screenshots.mdx b/java/docs/screenshots.mdx index 2c4b33a176..f1c93e1de6 100644 --- a/java/docs/screenshots.mdx +++ b/java/docs/screenshots.mdx @@ -12,7 +12,7 @@ Here is a quick way to capture a screenshot and save it into a file: ```java page.screenshot(new Page.ScreenshotOptions() - .setPath(Paths.get("screenshot.png"))) + .setPath(Paths.get("screenshot.png"))); ``` [Screenshots API](./api/class-page#page-screenshot) accepts many parameters for image format, clip area, quality, etc. Make sure to check them out. diff --git a/java/docs/test-runners.mdx b/java/docs/test-runners.mdx index 3071ea774a..1b27d72488 100644 --- a/java/docs/test-runners.mdx +++ b/java/docs/test-runners.mdx @@ -187,7 +187,7 @@ You can use a Gradle build configuration script, written in Groovy or Kotlin. <TabItem value="gradle"> -```java +```groovy plugins { application id 'java' @@ -220,7 +220,7 @@ test { <TabItem value="gradle-kotlin"> -```java +```groovy plugins { application id("java")