From ee7d60fceeee077ae209ac9241763ac82b431038 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Wed, 13 Jul 2022 11:50:18 +0200 Subject: [PATCH] docs: migrate page actions to locator actions 2/n (#15603) --- docs/src/api-testing-csharp.md | 2 +- docs/src/api/class-browsercontext.md | 40 ++++---- docs/src/api/class-download.md | 10 +- docs/src/api/class-filechooser.md | 8 +- docs/src/api/class-locatorassertions.md | 10 +- docs/src/api/class-page.md | 4 +- docs/src/api/class-pageassertions.md | 10 +- docs/src/api/class-playwrightassertions.md | 9 +- docs/src/api/class-selectors.md | 10 +- docs/src/api/class-timeouterror.md | 8 +- docs/src/api/class-tracing.md | 22 ++--- docs/src/auth.md | 6 +- docs/src/ci.md | 2 +- docs/src/debug.md | 4 +- docs/src/emulation.md | 18 ++-- docs/src/extensibility.md | 8 +- docs/src/getting-started-cli-js.md | 4 +- docs/src/getting-started-vscode-js.md | 4 +- docs/src/intro-csharp.md | 22 +++-- docs/src/intro-js.md | 8 +- docs/src/navigations.md | 106 ++++++++++----------- docs/src/network.md | 40 ++++---- docs/src/pages.md | 18 ++-- docs/src/pom.md | 8 +- docs/src/release-notes-csharp.md | 18 ++-- docs/src/release-notes-java.md | 10 +- docs/src/release-notes-js.md | 8 +- docs/src/release-notes-python.md | 16 ++-- docs/src/screenshots.md | 27 +++++- docs/src/selectors.md | 16 ++-- docs/src/test-advanced-js.md | 24 ++--- docs/src/test-annotations-js.md | 4 +- docs/src/test-api-testing-js.md | 16 ++-- docs/src/test-api/class-fixtures.md | 12 +-- docs/src/test-auth-js.md | 52 +++++----- docs/src/test-parallel-js.md | 4 +- docs/src/test-parameterize-js.md | 4 +- docs/src/test-retries-js.md | 4 +- docs/src/test-runners-java.md | 20 ++-- docs/src/test-runners-python.md | 4 +- docs/src/trace-viewer.md | 4 +- docs/src/videos.md | 4 +- packages/playwright-core/types/types.d.ts | 20 ++-- packages/playwright-test/types/test.d.ts | 10 +- 44 files changed, 344 insertions(+), 314 deletions(-) diff --git a/docs/src/api-testing-csharp.md b/docs/src/api-testing-csharp.md index 52fa1f3e83..9f74845af4 100644 --- a/docs/src/api-testing-csharp.md +++ b/docs/src/api-testing-csharp.md @@ -63,7 +63,7 @@ namespace Playwright.TestingHarnessTest.NUnit // Assuming personal access token available in the environment. headers.Add("Authorization", "token " + API_TOKEN); - Request = await this.Playwright.APIRequest.NewContextAsync(new () { + Request = await this.Playwright.APIRequest.NewContextAsync(new() { // All requests we send go to this API endpoint. BaseURL = "https://api.github.com", ExtraHTTPHeaders = headers, diff --git a/docs/src/api/class-browsercontext.md b/docs/src/api/class-browsercontext.md index fdab58e763..b7da9f113f 100644 --- a/docs/src/api/class-browsercontext.md +++ b/docs/src/api/class-browsercontext.md @@ -109,28 +109,28 @@ done and its response has started loading in the popup. ```js const [newPage] = await Promise.all([ context.waitForEvent('page'), - page.click('a[target=_blank]'), + page.locator('a[target=_blank]').click(), ]); console.log(await newPage.evaluate('location.href')); ``` ```java Page newPage = context.waitForPage(() -> { - page.click("a[target=_blank]"); + page.locator("a[target=_blank]").click(); }); System.out.println(newPage.evaluate("location.href")); ``` ```python async async with context.expect_page() as page_info: - await page.click("a[target=_blank]"), + await page.locator("a[target=_blank]").click(), page = await page_info.value print(await page.evaluate("location.href")) ``` ```python sync with context.expect_page() as page_info: - page.click("a[target=_blank]"), + page.locator("a[target=_blank]").click(), page = page_info.value print(page.evaluate("location.href")) ``` @@ -138,7 +138,7 @@ print(page.evaluate("location.href")) ```csharp var popup = await context.RunAndWaitForPageAsync(async => { - await page.ClickAsync("a"); + await page.Locator("a").ClickAsync(); }); Console.WriteLine(await popup.EvaluateAsync("location.href")); ``` @@ -435,7 +435,7 @@ const { webkit } = require('playwright'); // Or 'chromium' or 'firefox'.
`); - await page.click('button'); + await page.locator('button').click(); })(); ``` @@ -457,7 +457,7 @@ public class Example { "\n" + "\n" + "
"); - page.click("button"); + page.locator("button").click(); } } } @@ -482,7 +482,7 @@ async def run(playwright):
""") - await page.click("button") + await page.locator("button").click() async def main(): async with async_playwright() as playwright: @@ -508,7 +508,7 @@ def run(playwright):
""") - page.click("button") + page.locator("button").click() with sync_playwright() as playwright: run(playwright) @@ -530,7 +530,7 @@ await page.SetContentAsync("\n" + "\n" + "
"); -await page.ClickAsync("button"); +await page.Locator("button").ClickAsync(); ``` An example of passing an element handle: @@ -660,7 +660,7 @@ const crypto = require('crypto');
`); - await page.click('button'); + await page.locator('button').click(); })(); ``` @@ -696,7 +696,7 @@ public class Example { "\n" + "\n" + "
\n"); - page.click("button"); + page.locator("button").click(); } } } @@ -728,7 +728,7 @@ async def run(playwright):
""") - await page.click("button") + await page.locator("button").click() async def main(): async with async_playwright() as playwright: @@ -761,7 +761,7 @@ def run(playwright):
""") - page.click("button") + page.locator("button").click() with sync_playwright() as playwright: run(playwright) @@ -796,7 +796,7 @@ class BrowserContextExamples "\n" + "
"); - await page.ClickAsync("button"); + await page.Locator("button").ClickAsync(); Console.WriteLine(await page.TextContentAsync("div")); } } @@ -1300,30 +1300,30 @@ value. Will throw an error if the context closes before the event is fired. Retu ```js const [page, _] = await Promise.all([ context.waitForEvent('page'), - page.click('button') + page.locator('button').click() ]); ``` ```java -Page newPage = context.waitForPage(() -> page.click("button")); +Page newPage = context.waitForPage(() -> page.locator("button").click()); ``` ```python async async with context.expect_event("page") as event_info: - await page.click("button") + await page.locator("button").click() page = await event_info.value ``` ```python sync with context.expect_event("page") as event_info: - page.click("button") + page.locator("button").click() page = event_info.value ``` ```csharp var page = await context.RunAndWaitForPageAsync(async () => { - await page.ClickAsync("button"); + await page.Locator("button").ClickAsync(); }); ``` diff --git a/docs/src/api/class-download.md b/docs/src/api/class-download.md index 281ddd278f..7e1f949056 100644 --- a/docs/src/api/class-download.md +++ b/docs/src/api/class-download.md @@ -23,7 +23,7 @@ const path = await download.path(); ```java // wait for download to start -Download download = page.waitForDownload(() -> page.click("a")); +Download download = page.waitForDownload(() -> page.locator("a").click()); // wait for download to complete Path path = download.path(); ``` @@ -31,7 +31,7 @@ Path path = download.path(); ```java // wait for download to start Download download = page.waitForDownload(() -> { - page.click("a"); + page.locator("a").click(); }); // wait for download to complete Path path = download.path(); @@ -39,7 +39,7 @@ Path path = download.path(); ```python async async with page.expect_download() as download_info: - await page.click("a") + await page.locator("a").click() download = await download_info.value # waits for download to complete path = await download.path() @@ -47,7 +47,7 @@ path = await download.path() ```python sync with page.expect_download() as download_info: - page.click("a") + page.locator("a").click() download = download_info.value # wait for download to complete path = download.path() @@ -56,7 +56,7 @@ path = download.path() ```csharp var download = await page.RunAndWaitForDownloadAsync(async () => { - await page.ClickAsync("#downloadButton"); + await page.Locator("#downloadButton").ClickAsync(); }); Console.WriteLine(await download.PathAsync()); ``` diff --git a/docs/src/api/class-filechooser.md b/docs/src/api/class-filechooser.md index 42a3319497..b2c4cea6ff 100644 --- a/docs/src/api/class-filechooser.md +++ b/docs/src/api/class-filechooser.md @@ -16,20 +16,20 @@ await fileChooser.setFiles('myfile.pdf'); ``` ```java -FileChooser fileChooser = page.waitForFileChooser(() -> page.click("upload")); +FileChooser fileChooser = page.waitForFileChooser(() -> page.locator("upload").click()); fileChooser.setFiles(Paths.get("myfile.pdf")); ``` ```python async async with page.expect_file_chooser() as fc_info: - await page.click("upload") + await page.locator("upload").click() file_chooser = await fc_info.value await file_chooser.set_files("myfile.pdf") ``` ```python sync with page.expect_file_chooser() as fc_info: - page.click("upload") + page.locator("upload").click() file_chooser = fc_info.value file_chooser.set_files("myfile.pdf") ``` @@ -37,7 +37,7 @@ file_chooser.set_files("myfile.pdf") ```csharp var fileChooser = await page.RunAndWaitForFileChooserAsync(async () => { - await page.ClickAsync("upload"); + await page.Locator("upload").ClickAsync(); }); await fileChooser.SetFilesAsync("temp.txt"); ``` diff --git a/docs/src/api/class-locatorassertions.md b/docs/src/api/class-locatorassertions.md index 47a723c0ff..ecc532d5c0 100644 --- a/docs/src/api/class-locatorassertions.md +++ b/docs/src/api/class-locatorassertions.md @@ -8,7 +8,7 @@ import { test, expect } from '@playwright/test'; test('status becomes submitted', async ({ page }) => { // ... - await page.click('#submit-button'); + await page.locator('#submit-button').click(); await expect(page.locator('.status')).toHaveText('Submitted'); }); ``` @@ -22,7 +22,7 @@ public class TestLocator { @Test void statusBecomesSubmitted() { ... - page.click("#submit-button"); + page.locator("#submit-button").click(); assertThat(page.locator(".status")).hasText("Submitted"); } } @@ -33,7 +33,7 @@ from playwright.async_api import Page, expect async def test_status_becomes_submitted(page: Page) -> None: # .. - await page.click("#submit-button") + await page.locator("#submit-button").click() await expect(page.locator(".status")).to_have_text("Submitted") ``` @@ -42,7 +42,7 @@ from playwright.sync_api import Page, expect def test_status_becomes_submitted(page: Page) -> None: # .. - page.click("#submit-button") + page.locator("#submit-button").click() expect(page.locator(".status")).to_have_text("Submitted") ``` @@ -60,7 +60,7 @@ public class ExampleTests : PageTest public async Task StatusBecomesSubmitted() { // .. - await Page.ClickAsync("#submit-button"); + await Page.Locator("#submit-button").ClickAsync(); await Expect(Page.Locator(".status")).ToHaveTextAsync("Submitted"); } } diff --git a/docs/src/api/class-page.md b/docs/src/api/class-page.md index ccd9044d91..91b9e0d912 100644 --- a/docs/src/api/class-page.md +++ b/docs/src/api/class-page.md @@ -1654,7 +1654,7 @@ class PageExamples public static async Task Main() { using var playwright = await Playwright.CreateAsync(); - await using var browser = await playwright.Webkit.LaunchAsync(new BrowserTypeLaunchOptions + await using var browser = await playwright.Webkit.LaunchAsync(new() { Headless: false }); @@ -1916,7 +1916,7 @@ class PageExamples public static async Task Main() { using var playwright = await Playwright.CreateAsync(); - await using var browser = await playwright.Webkit.LaunchAsync(new BrowserTypeLaunchOptions + await using var browser = await playwright.Webkit.LaunchAsync(new() { Headless: false }); diff --git a/docs/src/api/class-pageassertions.md b/docs/src/api/class-pageassertions.md index 31ec94971e..68d02b23ed 100644 --- a/docs/src/api/class-pageassertions.md +++ b/docs/src/api/class-pageassertions.md @@ -8,7 +8,7 @@ import { test, expect } from '@playwright/test'; test('navigates to login', async ({ page }) => { // ... - await page.click('#login'); + await page.locator('#login').click(); await expect(page).toHaveURL(/.*\/login/); }); ``` @@ -22,7 +22,7 @@ public class TestPage { @Test void navigatesToLoginPage() { ... - page.click("#login"); + page.locator("#login").click(); assertThat(page).hasURL(Pattern.compile(".*/login")); } } @@ -34,7 +34,7 @@ from playwright.async_api import Page, expect async def test_navigates_to_login_page(page: Page) -> None: # .. - await page.click("#login") + await page.locator("#login").click() await expect(page).to_have_url(re.compile(r".*/login")) ``` @@ -44,7 +44,7 @@ from playwright.sync_api import Page, expect def test_navigates_to_login_page(page: Page) -> None: # .. - page.click("#login") + page.locator("#login").click() expect(page).to_have_url(re.compile(r".*/login")) ``` @@ -62,7 +62,7 @@ public class ExampleTests : PageTest public async Task NavigatetoLoginPage() { // .. - await Page.ClickAsync("#login"); + await Page.Locator("#login").ClickAsync(); await Expect(Page.Locator("div#foobar")).ToHaveURL(new Regex(".*/login")); } } diff --git a/docs/src/api/class-playwrightassertions.md b/docs/src/api/class-playwrightassertions.md index d0d3db99ed..7412ff5b87 100644 --- a/docs/src/api/class-playwrightassertions.md +++ b/docs/src/api/class-playwrightassertions.md @@ -10,7 +10,7 @@ import { test, expect } from '@playwright/test'; test('status becomes submitted', async ({ page }) => { // ... - await page.click('#submit-button') + await page.locator('#submit-button').click() await expect(page.locator('.status')).toHaveText('Submitted'); }); ``` @@ -20,7 +20,7 @@ from playwright.async_api import Page, expect async def test_status_becomes_submitted(page: Page) -> None: # .. - await page.click("#submit-button") + await page.locator("#submit-button").click() await expect(page.locator(".status")).to_have_text("Submitted") ``` @@ -29,7 +29,7 @@ from playwright.sync_api import Page, expect def test_status_becomes_submitted(page: Page) -> None: # .. - page.click("#submit-button") + page.locator("#submit-button").click() expect(page.locator(".status")).to_have_text("Submitted") ``` @@ -42,7 +42,7 @@ public class TestExample { @Test void statusBecomesSubmitted() { ... - page.click("#submit-button"); + page.locator("#submit-button").click(); assertThat(page.locator(".status")).hasText("Submitted"); } } @@ -60,6 +60,7 @@ public class ExampleTests : PageTest [Test] public async Task StatusBecomesSubmitted() { + await Page.Locator("#submit-button").ClickAsync(); await Expect(Page.Locator(".status")).ToHaveTextAsync("Submitted"); } } diff --git a/docs/src/api/class-selectors.md b/docs/src/api/class-selectors.md index f2cb5a690b..51241b070d 100644 --- a/docs/src/api/class-selectors.md +++ b/docs/src/api/class-selectors.md @@ -36,7 +36,7 @@ const { selectors, firefox } = require('playwright'); // Or 'chromium' or 'webk // Use the selector prefixed with its name. const button = page.locator('tag=button'); // Combine it with other selector engines. - await page.click('tag=div >> text="Click me"'); + await page.locator('tag=div >> text="Click me"').click(); // Can use it in any methods supporting selectors. const buttonCount = await page.locator('tag=button').count(); @@ -64,7 +64,7 @@ page.setContent("
"); // Use the selector prefixed with its name. Locator button = page.locator("tag=button"); // Combine it with other selector engines. -page.click("tag=div >> text=\"Click me\""); +page.locator("tag=div >> text=\"Click me\"").click(); // Can use it in any methods supporting selectors. int buttonCount = (int) page.locator("tag=button").count(); browser.close(); @@ -96,7 +96,7 @@ async def run(playwright): # Use the selector prefixed with its name. button = await page.query_selector('tag=button') # Combine it with other selector engines. - await page.click('tag=div >> text="Click me"') + await page.locator('tag=div >> text="Click me"').click() # Can use it in any methods supporting selectors. button_count = await page.locator('tag=button').count() print(button_count) @@ -134,7 +134,7 @@ def run(playwright): # Use the selector prefixed with its name. button = page.locator('tag=button') # Combine it with other selector engines. - page.click('tag=div >> text="Click me"') + page.locator('tag=div >> text="Click me"').click() # Can use it in any methods supporting selectors. button_count = page.locator('tag=button').count() print(button_count) @@ -164,7 +164,7 @@ await page.SetContentAsync("
"); // Use the selector prefixed with its name. var button = page.Locator("tag=button"); // Combine it with other selector engines. -await page.ClickAsync("tag=div >> text=\"Click me\""); +await page.Locator("tag=div >> text=\"Click me\"").ClickAsync(); // Can use it in any methods supporting selectors. int buttonCount = await page.Locator("tag=button").CountAsync(); ``` diff --git a/docs/src/api/class-timeouterror.md b/docs/src/api/class-timeouterror.md index 970aa4dbbb..8fcfd3634b 100644 --- a/docs/src/api/class-timeouterror.md +++ b/docs/src/api/class-timeouterror.md @@ -13,7 +13,7 @@ const playwright = require('playwright'); const context = await browser.newContext(); const page = await context.newPage(); try { - await page.click("text=Foo", { + await page.locator("text=Foo").click({ timeout: 100, }) } catch (error) { @@ -32,7 +32,7 @@ async def run(playwright): browser = await playwright.chromium.launch() page = await browser.new_page() try: - await page.click("text=Example", timeout=100) + await page.locator("text=Example").click(timeout=100) except PlaywrightTimeoutError: print("Timeout!") await browser.close() @@ -51,7 +51,7 @@ with sync_playwright() as p: browser = p.chromium.launch() page = browser.new_page() try: - page.click("text=Example", timeout=100) + page.locator("text=Example").click(timeout=100) except PlaywrightTimeoutError: print("Timeout!") browser.close() @@ -69,7 +69,7 @@ public class TimeoutErrorExample { BrowserContext context = browser.newContext(); Page page = context.newPage(); try { - page.click("text=Example", new Page.ClickOptions().setTimeout(100)); + page.locator("text=Example").click(new Locator.ClickOptions().setTimeout(100)); } catch (TimeoutError e) { System.out.println("Timeout!"); } diff --git a/docs/src/api/class-tracing.md b/docs/src/api/class-tracing.md index e235f6d494..ce4391e9aa 100644 --- a/docs/src/api/class-tracing.md +++ b/docs/src/api/class-tracing.md @@ -47,14 +47,14 @@ context.tracing.stop(path = "trace.zip") ```csharp await using var browser = playwright.Chromium.LaunchAsync(); await using var context = await browser.NewContextAsync(); -await context.Tracing.StartAsync(new TracingStartOptions +await context.Tracing.StartAsync(new() { Screenshots: true, Snapshots: true }); var page = context.NewPageAsync(); await page.GotoAsync("https://playwright.dev"); -await context.Tracing.StopAsync(new TracingStopOptions +await context.Tracing.StopAsync(new() { Path: "trace.zip" }); @@ -99,14 +99,14 @@ context.tracing.stop(path = "trace.zip") ```csharp await using var browser = playwright.Chromium.LaunchAsync(); await using var context = await browser.NewContextAsync(); -await context.Tracing.StartAsync(new TracingStartOptions +await context.Tracing.StartAsync(new() { Screenshots: true, Snapshots: true }); var page = context.NewPageAsync(); await page.GotoAsync("https://playwright.dev"); -await context.Tracing.StopAsync(new TracingStopOptions +await context.Tracing.StopAsync(new() { Path: "trace.zip" }); @@ -167,7 +167,7 @@ const page = await context.newPage(); await page.goto('https://playwright.dev'); await context.tracing.startChunk(); -await page.click('text=Get Started'); +await page.locator('text=Get Started').click(); // Everything between startChunk and stopChunk will be recorded in the trace. await context.tracing.stopChunk({ path: 'trace1.zip' }); @@ -185,7 +185,7 @@ Page page = context.newPage(); page.navigate("https://playwright.dev"); context.tracing().startChunk(); -page.click("text=Get Started"); +page.locator("text=Get Started").click(); // Everything between startChunk and stopChunk will be recorded in the trace. context.tracing().stopChunk(new Tracing.StopChunkOptions() .setPath(Paths.get("trace1.zip"))); @@ -203,7 +203,7 @@ page = await context.new_page() await page.goto("https://playwright.dev") await context.tracing.start_chunk() -await page.click("text=Get Started") +await page.locator("text=Get Started").click() # Everything between start_chunk and stop_chunk will be recorded in the trace. await context.tracing.stop_chunk(path = "trace1.zip") @@ -219,7 +219,7 @@ page = context.new_page() page.goto("https://playwright.dev") context.tracing.start_chunk() -page.click("text=Get Started") +page.locator("text=Get Started").click() # Everything between start_chunk and stop_chunk will be recorded in the trace. context.tracing.stop_chunk(path = "trace1.zip") @@ -232,7 +232,7 @@ context.tracing.stop_chunk(path = "trace2.zip") ```csharp await using var browser = playwright.Chromium.LaunchAsync(); await using var context = await browser.NewContextAsync(); -await context.Tracing.StartAsync(new TracingStartOptions +await context.Tracing.StartAsync(new() { Screenshots: true, Snapshots: true @@ -243,7 +243,7 @@ await page.GotoAsync("https://playwright.dev"); await context.Tracing.StartChunkAsync(); await page.ClickAsync("text=Get Started"); // Everything between StartChunkAsync and StopChunkAsync will be recorded in the trace. -await context.Tracing.StopChunkAsync(new TracingStopChunkOptions +await context.Tracing.StopChunkAsync(new() { Path: "trace1.zip" }); @@ -251,7 +251,7 @@ await context.Tracing.StopChunkAsync(new TracingStopChunkOptions await context.Tracing.StartChunkAsync(); await page.GotoAsync("http://example.com"); // Save a second trace file with different actions. -await context.Tracing.StopChunkAsync(new TracingStopChunkOptions +await context.Tracing.StopChunkAsync(new() { Path: "trace2.zip" }); diff --git a/docs/src/auth.md b/docs/src/auth.md index c454fce971..661aa9f06e 100644 --- a/docs/src/auth.md +++ b/docs/src/auth.md @@ -135,13 +135,13 @@ context = browser.new_context(storage_state="state.json") ```csharp // Save storage state into the file. -await context.StorageStateAsync(new BrowserContextStorageStateOptions +await context.StorageStateAsync(new() { Path = "state.json" }); // Create a new context with the saved storage state. -var context = await browser.NewContextAsync(new BrowserNewContextOptions +var context = await browser.NewContextAsync(new() { StorageStatePath = "state.json" }); @@ -332,7 +332,7 @@ class Program { using var playwright = await Playwright.CreateAsync(); var chromium = playwright.Chromium; - var context = chromium.LaunchPersistentContextAsync(@"C:\path\to\directory\", new BrowserTypeLaunchPersistentContextOptions + var context = chromium.LaunchPersistentContextAsync(@"C:\path\to\directory\", new() { Headless = false }); diff --git a/docs/src/ci.md b/docs/src/ci.md index fd6f8d391f..c6dc811c6b 100644 --- a/docs/src/ci.md +++ b/docs/src/ci.md @@ -470,7 +470,7 @@ with sync_playwright() as p: using Microsoft.Playwright; using var playwright = await Playwright.CreateAsync(); -await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions +await playwright.Chromium.LaunchAsync(new() { Headless = false }); diff --git a/docs/src/debug.md b/docs/src/debug.md index 62680d11ad..3a1744a0cb 100644 --- a/docs/src/debug.md +++ b/docs/src/debug.md @@ -50,7 +50,7 @@ chromium.launch(headless=False, slow_mo=100) # or firefox, webkit ```csharp // Chromium, Firefox, or Webkit -await using var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions +await using var browser = await playwright.Chromium.LaunchAsync(new() { Headless = false, SlowMo = 100 @@ -89,7 +89,7 @@ chromium.launch(devtools=True) ``` ```csharp -await using var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions +await using var browser = await playwright.Chromium.LaunchAsync(new() { Devtools: true }); diff --git a/docs/src/emulation.md b/docs/src/emulation.md index 7615ed5a1e..c6f948c221 100644 --- a/docs/src/emulation.md +++ b/docs/src/emulation.md @@ -72,7 +72,7 @@ class Program public static async Task Main() { using var playwright = await Playwright.CreateAsync(); - await using var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions + await using var browser = await playwright.Chromium.LaunchAsync(new() { Headless: False }); @@ -193,7 +193,7 @@ context = browser.new_context( ```csharp // Create context with given viewport -await using var context = await browser.NewContextAsync(new BrowserNewContextOptions +await using var context = await browser.NewContextAsync(new() { ViewportSize = new ViewportSize() { Width = 1280, Height = 1024 } }); @@ -202,7 +202,7 @@ await using var context = await browser.NewContextAsync(new BrowserNewContextOpt await page.SetViewportSizeAsync(1600, 1200); // Emulate high-DPI -await using var context = await browser.NewContextAsync(new BrowserNewContextOptions +await using var context = await browser.NewContextAsync(new() { ViewportSize = new ViewportSize() { Width = 2560, Height = 1440 }, DeviceScaleFactor = 2 @@ -249,7 +249,7 @@ context = browser.new_context( ``` ```csharp -await using var context = await browser.NewContextAsync(new BrowserNewContextOptions +await using var context = await browser.NewContextAsync(new() { Locale = "de-DE", TimezoneId = "Europe/Berlin" @@ -394,7 +394,7 @@ context = browser.new_context( ``` ```csharp -await using var context = await browser.NewContextAsync(new BrowserNewContextOptions +await using var context = await browser.NewContextAsync(new() { Permissions = new[] { "geolocation" }, Geolocation = new Geolocation() { Longitude = 48.858455f, Latitude = 2.294474f } @@ -507,25 +507,25 @@ page.emulate_media(media='print') ```csharp // Create context with dark mode -await using var context = await browser.NewContextAsync(new BrowserNewContextOptions +await using var context = await browser.NewContextAsync(new() { ColorScheme = ColorScheme.Dark }); // Create page with dark mode -var page = await browser.NewPageAsync(new BrowserNewPageOptions +var page = await browser.NewPageAsync(new() { ColorScheme = ColorScheme.Dark }); // Change color scheme for the page -await page.EmulateMediaAsync(new PageEmulateMediaOptions +await page.EmulateMediaAsync(new() { ColorScheme = ColorScheme.Dark }); // Change media for page -await page.EmulateMediaAsync(new PageEmulateMediaOptions +await page.EmulateMediaAsync(new() { Media = Media.Print }); diff --git a/docs/src/extensibility.md b/docs/src/extensibility.md index 50c991d4e7..2910c3f4d4 100644 --- a/docs/src/extensibility.md +++ b/docs/src/extensibility.md @@ -46,7 +46,7 @@ const button = page.locator('tag=button'); await button.click(); // We can combine it with other selector engines using `>>` combinator. -await page.click('tag=div >> span >> "Click me"'); +await page.locator('tag=div >> span >> "Click me"').click(); // We can use it in any methods supporting selectors. const buttonCount = await page.locator('tag=button').count(); @@ -74,7 +74,7 @@ Locator button = page.locator("tag=button"); button.click(); // We can combine it with other selector engines using ">>" combinator. -page.click("tag=div >> span >> \"Click me\""); +page.locator("tag=div >> span >> \"Click me\"").click(); // We can use it in any methods supporting selectors. int buttonCount = (int) page.locator("tag=button").count(); @@ -103,7 +103,7 @@ button = page.locator("tag=button") await button.click() # we can combine it with other selector engines using `>>` combinator. -await page.click("tag=div >> span >> "click me"") +await page.locator("tag=div >> span >> \"click me\"").click() # we can use it in any methods supporting selectors. button_count = await page.locator("tag=button").count() @@ -132,7 +132,7 @@ button = page.locator("tag=button") button.click() # we can combine it with other selector engines using `>>` combinator. -page.click("tag=div >> span >> "click me"") +page.locator("tag=div >> span >> \"click me\"").click() # we can use it in any methods supporting selectors. button_count = page.locator("tag=button").count() diff --git a/docs/src/getting-started-cli-js.md b/docs/src/getting-started-cli-js.md index d5d55526fb..40a6196190 100644 --- a/docs/src/getting-started-cli-js.md +++ b/docs/src/getting-started-cli-js.md @@ -75,7 +75,7 @@ test("my test", async ({ page }) => { "/docs/intro" ); - await page.click("text=Get Started"); + await page.locator("text=Get Started").click(); // Expect some text to be visible on the page. await expect(page.locator("text=Introduction").first()).toBeVisible(); }); @@ -97,7 +97,7 @@ test("my test", async ({ page }) => { "/docs/intro" ); - await page.click("text=Get Started"); + await page.locator("text=Get Started").click(); // Expect some text to be visible on the page. await expect(page.locator("text=Introduction").first()).toBeVisible(); }); diff --git a/docs/src/getting-started-vscode-js.md b/docs/src/getting-started-vscode-js.md index 172a052b66..19b0528fe9 100644 --- a/docs/src/getting-started-vscode-js.md +++ b/docs/src/getting-started-vscode-js.md @@ -61,7 +61,7 @@ test("my test", async ({ page }) => { "/docs/intro" ); - await page.click("text=Get Started"); + await page.locator("text=Get Started").click(); // Expect some text to be visible on the page. await expect(page.locator("text=Introduction").first()).toBeVisible(); }); @@ -83,7 +83,7 @@ test("my test", async ({ page }) => { "/docs/intro" ); - await page.click("text=Get Started"); + await page.locator("text=Get Started").click(); // Expect some text to be visible on the page. await expect(page.locator("text=Introduction").first()).toBeVisible(); }); diff --git a/docs/src/intro-csharp.md b/docs/src/intro-csharp.md index 5ef9172ec2..e80fdcd407 100644 --- a/docs/src/intro-csharp.md +++ b/docs/src/intro-csharp.md @@ -47,7 +47,7 @@ dotnet run By default, Playwright runs the browsers in headless mode. To see the browser UI, pass the `Headless = false` flag while launching the browser. You can also use [`option: slowMo`] to slow down execution. Learn more in the debugging tools [section](./debug.md). ```csharp -await playwright.Firefox.LaunchAsync(new BrowserTypeLaunchOptions +await playwright.Firefox.LaunchAsync(new() { Headless = false, SlowMo = 50, @@ -87,17 +87,25 @@ namespace PlaywrightTests; public class Tests : PageTest { [Test] - public async Task ShouldAdd() + async public Task ShouldHaveTheCorrectSlogan() { - int result = await Page.EvaluateAsync("() => 7 + 3"); - Assert.AreEqual(10, result); + await Page.GotoAsync("https://playwright.dev"); + await Expect(Page.Locator("text=enables reliable end-to-end testing for modern web apps")).ToBeVisibleAsync(); } [Test] - public async Task ShouldMultiply() + public async Task ShouldHaveTheCorrectTitle() { - int result = await Page.EvaluateAsync("() => 7 * 3"); - Assert.AreEqual(21, result); + await Page.GotoAsync("https://playwright.dev"); + var title = Page.Locator(".navbar__inner .navbar__title"); + await Expect(title).ToHaveTextAsync("Playwright"); + } + + [Test] + public async Task ShouldAdd() + { + var result = await Page.EvaluateAsync("() => 7 + 3"); + Assert.AreEqual(10, result); } } ``` diff --git a/docs/src/intro-js.md b/docs/src/intro-js.md index ed9895f7c2..43b656d0aa 100644 --- a/docs/src/intro-js.md +++ b/docs/src/intro-js.md @@ -208,9 +208,9 @@ test('my test', async ({ page }) => { await expect(page).toHaveTitle(/Playwright/); // Expect an attribute "to be strictly equal" to the value. - await expect(page.locator('text=Get Started').first()).toHaveAttribute('href', '/docs/intro'); + await expect(page.locator('text=Get Started')).toHaveAttribute('href', '/docs/intro'); - await page.click('text=Get Started'); + await page.locator('text=Get Started').click(); // Expect some text to be visible on the page. await expect(page.locator('text=Introduction').first()).toBeVisible(); }); @@ -227,9 +227,9 @@ test('my test', async ({ page }) => { await expect(page).toHaveTitle(/Playwright/); // Expect an attribute "to be strictly equal" to the value. - await expect(page.locator('text=Get Started').first()).toHaveAttribute('href', '/docs/intro'); + await expect(page.locator('text=Get Started')).toHaveAttribute('href', '/docs/intro'); - await page.click('text=Get Started'); + await page.locator('text=Get Started').click(); // Expect some text to be visible on the page. await expect(page.locator('text=Introduction').first()).toBeVisible(); }); diff --git a/docs/src/navigations.md b/docs/src/navigations.md index dbd42cef31..3c0e90ea30 100644 --- a/docs/src/navigations.md +++ b/docs/src/navigations.md @@ -106,7 +106,7 @@ await page.locator('text=Example Domain').waitFor(); // Navigate and click element // Click will auto-wait for the element await page.goto('https://example.com'); -await page.click('text=Example Domain'); +await page.locator('text=Example Domain').click(); ``` ```java @@ -117,7 +117,7 @@ page.locator("text=Example Domain").waitFor(); // Navigate and click element // Click will auto-wait for the element page.navigate("https://example.com"); -page.click("text=Example Domain"); +page.locator("text=Example Domain").click(); ``` ```python async @@ -128,7 +128,7 @@ await page.locator("text=example domain").wait_for() # Navigate and click element # Click will auto-wait for the element await page.goto("https://example.com") -await page.click("text=example domain") +await page.locator("text=example domain").click() ``` ```python sync @@ -139,7 +139,7 @@ page.locator("text=example domain").wait_for() # Navigate and click element # Click will auto-wait for the element page.goto("https://example.com") -page.click("text=example domain") +page.locator("text=example domain").click() ``` ```csharp @@ -150,7 +150,7 @@ await page.Locator("text=Example Domain").WaitForAsync(); // Navigate and click element // Click will auto-wait for the element await page.GotoAsync("https://example.com"); -await page.ClickAsync("text=Example Domain"); +await page.Locator("text=Example Domain").ClickAsync(); ``` ### API reference @@ -161,145 +161,145 @@ await page.ClickAsync("text=Example Domain"); ## Scenarios initiated by page interaction -In the scenarios below, [`method: Page.click`] initiates a navigation and then waits for the navigation to complete. +In the scenarios below, [`method: Locator.click`] initiates a navigation and then waits for the navigation to complete. ### Auto-wait -By default, [`method: Page.click`] will wait for the navigation step to complete. This can be combined with a page interaction on +By default, [`method: Locator.click`] will wait for the navigation step to complete. This can be combined with a page interaction on the navigated page which would auto-wait for an element. ```js // Click will auto-wait for navigation to complete -await page.click('text=Login'); +await page.locator('text=Login').click(); // Fill will auto-wait for element on navigated page -await page.fill('#username', 'John Doe'); +await page.locator('#username').fill('John Doe'); ``` ```java // Click will auto-wait for navigation to complete -page.click("text=Login"); +page.locator("text=Login").click(); // Fill will auto-wait for element on navigated page -page.fill("#username", "John Doe"); +page.locator("#username").fill("John Doe"); ``` ```python async # Click will auto-wait for navigation to complete -await page.click("text=Login") +await page.locator("text=Login").click() # Fill will auto-wait for element on navigated page -await page.fill("#username", "John Doe") +await page.locator("#username").fill("John Doe") ``` ```python sync # Click will auto-wait for navigation to complete -page.click("text=Login") +page.locator("text=Login").click() # Fill will auto-wait for element on navigated page -page.fill("#username", "John Doe") +page.locator("#username").fill("John Doe") ``` ```csharp // Click will auto-wait for navigation to complete -await page.ClickAsync("text=Login"); +await page.Locator("text=Login").ClickAsync(); // Fill will auto-wait for element on navigated page -await page.FillAsync("#username", "John Doe"); +await page.Locator("#username").FillAsync("John Doe"); ``` ### Custom wait -`page.click` can be combined with [`method: Page.waitForLoadState`] to wait for a loading event. +`locator.click` can be combined with [`method: Page.waitForLoadState`] to wait for a loading event. ```js -await page.click('button'); // Click triggers navigation +await page.locator('button').click(); // Click triggers navigation await page.waitForLoadState('networkidle'); // This resolves after 'networkidle' ``` ```java -page.click("button"); // Click triggers navigation +page.locator("button").click(); // Click triggers navigation page.waitForLoadState(LoadState.NETWORKIDLE); // This resolves after "networkidle" ``` ```python async -await page.click("button"); # Click triggers navigation +await page.locator("button").click(); # Click triggers navigation await page.wait_for_load_state("networkidle"); # This waits for the "networkidle" ``` ```python sync -page.click("button"); # Click triggers navigation +page.locator("button").click(); # Click triggers navigation page.wait_for_load_state("networkidle"); # This waits for the "networkidle" ``` ```csharp -await page.ClickAsync("button"); // Click triggers navigation +await page.Locator("button").ClickAsync(); // Click triggers navigation await page.WaitForLoadStateAsync(LoadState.NetworkIdle); // This resolves after "networkidle" ``` ### Wait for element In lazy-loaded pages, it can be useful to wait until an element is visible with [`method: Locator.waitFor`]. -Alternatively, page interactions like [`method: Page.click`] auto-wait for elements. +Alternatively, page interactions like [`method: Locator.click`] auto-wait for elements. ```js // Click will auto-wait for the element and trigger navigation -await page.click('text=Login'); +await page.locator('text=Login').click(); // Wait for the element await page.locator('#username').waitFor(); // Click triggers navigation -await page.click('text=Login'); +await page.locator('text=Login').click(); // Fill will auto-wait for element -await page.fill('#username', 'John Doe'); +await page.locator('#username').fill('John Doe'); ``` ```java // Click will auto-wait for the element and trigger navigation -page.click("text=Login"); +page.locator("text=Login").click(); // Wait for the element page.locator("#username").waitFor(); // Click triggers navigation -page.click("text=Login"); +page.locator("text=Login").click(); // Fill will auto-wait for element -page.fill("#username", "John Doe"); +page.locator("#username").fill("John Doe"); ``` ```python async # Click will auto-wait for the element and trigger navigation -await page.click("text=Login") +await page.locator("text=Login").click() # Wait for the element await page.locator("#username").wait_for() # Click triggers navigation -await page.click("text=Login") +await page.locator("text=Login").click() # Fill will auto-wait for element -await page.fill("#username", "John Doe") +await page.locator("#username").fill("John Doe") ``` ```python sync # Click triggers navigation -page.click("text=Login") +page.locator("text=Login").click() # Click will auto-wait for the element page.locator("#username").wait_for() # Click triggers navigation -page.click("text=Login") +page.locator("text=Login").click() # Fill will auto-wait for element -page.fill("#username", "John Doe") +page.locator("#username").fill("John Doe") ``` ```csharp // Click will auto-wait for the element and trigger navigation -await page.ClickAsync("text=Login"); +await page.Locator("text=Login").ClickAsync(); // Wait for the element await page.Locator("#username").WaitForAsync(); // Click triggers navigation -await page.ClickAsync("text=Login"); +await page.Locator("text=Login").ClickAsync(); // Fill will auto-wait for element -await page.FillAsync("#username", "John Doe"); +await page.Locator("#username").FillAsync("John Doe"); ``` ### Asynchronous navigation @@ -325,7 +325,7 @@ await Promise.all([ // Using waitForNavigation with a callback prevents a race condition // between clicking and waiting for a navigation. page.waitForNavigation(() -> { // Waits for the next navigation - page.click("div.delayed-navigation"); // Triggers a navigation after a timeout + page.locator("div.delayed-navigation").click(); // Triggers a navigation after a timeout }); ``` @@ -334,7 +334,7 @@ page.waitForNavigation(() -> { // Waits for the next navigation # prevents a race condition between clicking and waiting for a navigation. async with page.expect_navigation(): # Triggers a navigation after a timeout - await page.click("div.delayed-navigation") + await page.locator("div.delayed-navigation").click() ``` ```python sync @@ -342,7 +342,7 @@ async with page.expect_navigation(): # prevents a race condition between clicking and waiting for a navigation. with page.expect_navigation(): # Triggers a navigation after a timeout - page.click("a") + page.locator("a").click() ``` ```csharp @@ -351,7 +351,7 @@ with page.expect_navigation(): await page.RunAndWaitForNavigationAsync(async () => { // Triggers a navigation after a timeout - await page.ClickAsync("div.delayed-navigation"); + await page.Locator("div.delayed-navigation").ClickAsync(); }); ``` @@ -377,7 +377,7 @@ await Promise.all([ // Running action in the callback of waitForNavigation prevents a race // condition between clicking and waiting for a navigation. page.waitForNavigation(new Page.WaitForNavigationOptions().setUrl("**/login"), () -> { - page.click("a"); // Triggers a navigation with a script redirect + page.locator("a").click(); // Triggers a navigation with a script redirect }); ``` @@ -386,7 +386,7 @@ page.waitForNavigation(new Page.WaitForNavigationOptions().setUrl("**/login"), ( # between clicking and waiting for a navigation. async with page.expect_navigation(url="**/login"): # Triggers a navigation with a script redirect - await page.click("a") + await page.locator("a").click() ``` ```python sync @@ -394,7 +394,7 @@ async with page.expect_navigation(url="**/login"): # between clicking and waiting for a navigation. with page.expect_navigation(url="**/login"): # Triggers a navigation with a script redirect - page.click("a") + page.locator("a").click() ``` ```csharp @@ -403,8 +403,8 @@ with page.expect_navigation(url="**/login"): await page.RunAndWaitForNavigationAsync(async () => { // Triggers a navigation with a script redirect. - await page.ClickAsync("a"); -}, new PageWaitForNavigationOptions + await page.Locator("a").ClickAsync(); +}, new() { UrlString = "**/login" }); @@ -429,21 +429,21 @@ await popup.waitForLoadState('load'); ```java Page popup = page.waitForPopup(() -> { - page.click("a[target='_blank']"); // Opens popup + page.locator("a[target='_blank']").click(); // Opens popup }); popup.waitForLoadState(LoadState.LOAD); ``` ```python async async with page.expect_popup() as popup_info: - await page.click('a[target="_blank"]') # Opens popup + await page.locator('a[target="_blank"]').click() # Opens popup popup = await popup_info.value await popup.wait_for_load_state("load") ``` ```python sync with page.expect_popup() as popup_info: - page.click('a[target="_blank"]') # Opens popup + page.locator('a[target="_blank"]').click() # Opens popup popup = popup_info.value popup.wait_for_load_state("load") ``` @@ -451,13 +451,13 @@ popup.wait_for_load_state("load") ```csharp var popup = await page.RunAndWaitForPopupAsync(async () => { - await page.ClickAsync("a[target='_blank']"); // Opens popup + await page.Locator("a[target='_blank']").ClickAsync(); // Opens popup }); popup.WaitForLoadStateAsync(LoadState.Load); ``` ### API reference -- [`method: Page.click`] +- [`method: Locator.click`] - [`method: Page.waitForLoadState`] - [`method: Page.waitForNavigation`] - [`method: Page.waitForFunction`] diff --git a/docs/src/network.md b/docs/src/network.md index 9faabbbb95..a4b2866d38 100644 --- a/docs/src/network.md +++ b/docs/src/network.md @@ -48,7 +48,7 @@ page.goto("https://example.com") ``` ```csharp -using var context = await Browser.NewContextAsync(new BrowserNewContextOptions +using var context = await Browser.NewContextAsync(new() { HttpCredentials = new HttpCredentials { @@ -113,7 +113,7 @@ var proxy = new Proxy Username = "user", Password = "pwd" }; -await using var browser = await BrowserType.LaunchAsync(new BrowserTypeLaunchOptions +await using var browser = await BrowserType.LaunchAsync(new() { Proxy = proxy }); @@ -153,12 +153,12 @@ context = browser.new_context(proxy={"server": "http://myproxy.com:3128"}) ```csharp var proxy = new Proxy { Server = "per-context" }; -await using var browser = await BrowserType.LaunchAsync(new BrowserTypeLaunchOptions +await using var browser = await BrowserType.LaunchAsync(new() { // Browser proxy option is required for Chromium on Windows. Proxy = proxy }); -using var context = await Browser.NewContextAsync(new BrowserNewContextOptions +using var context = await Browser.NewContextAsync(new() { Proxy = new Proxy { Server = "http://myproxy.com:3128" }) }); @@ -259,35 +259,35 @@ Or wait for a network response after the button click: // Use a glob URL pattern const [response] = await Promise.all([ page.waitForResponse('**/api/fetch_data'), - page.click('button#update'), + page.locator('button#update').click(), ]); ``` ```java // Use a glob URL pattern Response response = page.waitForResponse("**/api/fetch_data", () -> { - page.click("button#update"); + page.locator("button#update").click(); }); ``` ```python async # Use a glob url pattern async with page.expect_response("**/api/fetch_data") as response_info: - await page.click("button#update") + await page.locator("button#update").click() response = await response_info.value ``` ```python sync # Use a glob url pattern with page.expect_response("**/api/fetch_data") as response_info: - page.click("button#update") + page.locator("button#update").click() response = response_info.value ``` ```csharp // Use a glob URL pattern var waitForResponseTask = page.WaitForResponseAsync("**/api/fetch_data"); -await page.ClickAsync("button#update"); +await page.Locator("button#update").ClickAsync(); var response = await waitForResponseTask; ``` @@ -297,61 +297,61 @@ var response = await waitForResponseTask; // Use a RegExp const [response] = await Promise.all([ page.waitForResponse(/\.jpeg$/), - page.click('button#update'), + page.locator('button#update').click(), ]); // Use a predicate taking a Response object const [response] = await Promise.all([ page.waitForResponse(response => response.url().includes(token)), - page.click('button#update'), + page.locator('button#update').click(), ]); ``` ```java // Use a RegExp Response response = page.waitForResponse(Pattern.compile("\\.jpeg$"), () -> { - page.click("button#update"); + page.locator("button#update").click(); }); // Use a predicate taking a Response object Response response = page.waitForResponse(r -> r.url().contains(token), () -> { - page.click("button#update"); + page.locator("button#update").click(); }); ``` ```python async # Use a regular expression async with page.expect_response(re.compile(r"\.jpeg$")) as response_info: - await page.click("button#update") + await page.locator("button#update").click() response = await response_info.value # Use a predicate taking a response object async with page.expect_response(lambda response: token in response.url) as response_info: - await page.click("button#update") + await page.locator("button#update").click() response = await response_info.value ``` ```python sync # Use a regular expression with page.expect_response(re.compile(r"\.jpeg$")) as response_info: - page.click("button#update") + page.locator("button#update").click() response = response_info.value # Use a predicate taking a response object with page.expect_response(lambda response: token in response.url) as response_info: - page.click("button#update") + page.locator("button#update").click() response = response_info.value ``` ```csharp // Use a regular expression var waitForResponseTask = page.WaitForResponseAsync(new Regex("\\.jpeg$")); -await page.ClickAsync("button#update"); +await page.Locator("button#update").ClickAsync(); var response = await waitForResponseTask; // Use a predicate taking a Response object var waitForResponseTask = page.WaitForResponseAsync(r => r.Url.Contains(token)); -await page.ClickAsync("button#update"); +await page.Locator("button#update").ClickAsync(); var response = await waitForResponseTask; ``` @@ -767,7 +767,7 @@ context.close() ``` ```csharp -var context = await browser.NewContextAsync(new () { +var context = await browser.NewContextAsync(new() { RecordHarPath = "example.har", RecordHarUrlFilter = "**/api/**", }); diff --git a/docs/src/pages.md b/docs/src/pages.md index 414ea409c0..2dde6ca0c7 100644 --- a/docs/src/pages.md +++ b/docs/src/pages.md @@ -144,7 +144,7 @@ handle new pages opened by `target="_blank"` links. // Get page after a specific action (e.g. clicking a link) const [newPage] = await Promise.all([ context.waitForEvent('page'), - page.click('a[target="_blank"]') // Opens a new tab + page.locator('a[target="_blank"]').click() // Opens a new tab ]) await newPage.waitForLoadState(); console.log(await newPage.title()); @@ -153,7 +153,7 @@ console.log(await newPage.title()); ```java // Get page after a specific action (e.g. clicking a link) Page newPage = context.waitForPage(() -> { - page.click("a[target='_blank']"); // Opens a new tab + page.locator("a[target='_blank']").click(); // Opens a new tab }); newPage.waitForLoadState(); System.out.println(newPage.title()); @@ -162,7 +162,7 @@ System.out.println(newPage.title()); ```python async # Get page after a specific action (e.g. clicking a link) async with context.expect_page() as new_page_info: - await page.click('a[target="_blank"]') # Opens a new tab + await page.locator('a[target="_blank"]').click() # Opens a new tab new_page = await new_page_info.value await new_page.wait_for_load_state() @@ -172,7 +172,7 @@ print(await new_page.title()) ```python sync # Get page after a specific action (e.g. clicking a link) with context.expect_page() as new_page_info: - page.click('a[target="_blank"]') # Opens a new tab + page.locator('a[target="_blank"]').click() # Opens a new tab new_page = new_page_info.value new_page.wait_for_load_state() @@ -183,7 +183,7 @@ print(new_page.title()) // Get page after a specific action (e.g. clicking a link) var newPage = await context.RunAndWaitForPageAsync(async () => { - await page.ClickAsync("a[target='_blank']"); + await page.Locator("a[target='_blank']").ClickAsync(); }); await newPage.WaitForLoadStateAsync(); Console.WriteLine(await newPage.TitleAsync()); @@ -256,7 +256,7 @@ console.log(await popup.title()); ```java // Get popup after a specific action (e.g., click) Page popup = page.waitForPopup(() -> { - page.click("#open"); + page.locator("#open").click(); }); popup.waitForLoadState(); System.out.println(popup.title()); @@ -265,7 +265,7 @@ System.out.println(popup.title()); ```python async # Get popup after a specific action (e.g., click) async with page.expect_popup() as popup_info: - await page.click("#open") + await page.locator("#open").click() popup = await popup_info.value await popup.wait_for_load_state() @@ -275,7 +275,7 @@ print(await popup.title()) ```python sync # Get popup after a specific action (e.g., click) with page.expect_popup() as popup_info: - page.click("#open") + page.locator("#open").click() popup = popup_info.value popup.wait_for_load_state() @@ -286,7 +286,7 @@ print(popup.title()) // Get popup after a specific action (e.g., click) var newPage = await page.RunAndWaitForPopupAsync(async () => { - await page.ClickAsync("#open"); + await page.Locator("#open").ClickAsync(); }); await newPage.WaitForLoadStateAsync(); Console.WriteLine(await newPage.TitleAsync()); diff --git a/docs/src/pom.md b/docs/src/pom.md index 984cd8172d..beca39bd37 100644 --- a/docs/src/pom.md +++ b/docs/src/pom.md @@ -116,12 +116,12 @@ public class SearchPage _searchTermInput = page.Locator("[aria-label='Enter your search term']"); } - public async Task Goto() + public async Task GotoAsync() { await _page.GotoAsync("https://bing.com"); } - public async Task Search(string text) + public async Task SearchAsync(string text) { await _searchTermInput.FillAsync(text); await _searchTermInput.PressAsync("Enter"); @@ -181,8 +181,8 @@ using BigEcommerceApp.Tests.Models; // in the test var page = new SearchPage(await browser.NewPageAsync()); -await page.Goto(); -await page.Search("search query"); +await page.GotoAsync(); +await page.SearchAsync("search query"); ``` ### API reference diff --git a/docs/src/release-notes-csharp.md b/docs/src/release-notes-csharp.md index 5d28afaf0f..37a2fe94c4 100644 --- a/docs/src/release-notes-csharp.md +++ b/docs/src/release-notes-csharp.md @@ -44,7 +44,7 @@ pwsh bin\Debug\netX\playwright.ps1 open --save-har=example.har --save-har-glob=" Alternatively, you can record HAR programmatically: ```csharp -var context = await browser.NewContextAsync(new () +var context = await browser.NewContextAsync(new() { RecordHarPath = harPath, RecordHarUrlFilterString = "**/api/**", @@ -78,7 +78,7 @@ await page.RouteAsync("**/*", async route => { var headers = route.Request.Headers; headers.Remove("X-Secret"); - await route.ContinueAsync(new () { Headers = headers }); + await route.ContinueAsync(new() { Headers = headers }); }); // Abort all images. @@ -131,7 +131,7 @@ Note that the new methods [`method: Page.routeFromHAR`] and [`method: BrowserCon ```csharp // Click a button with accessible name "log in" - await page.ClickAsync("role=button[name='log in']") + await page.Locator("role=button[name='log in']").ClickAsync(); ``` Read more in [our documentation](./selectors#role-selector). @@ -153,7 +153,7 @@ Note that the new methods [`method: Page.routeFromHAR`] and [`method: BrowserCon ```csharp // Click a button with accessible name "log in" - await page.ClickAsync("role=button[name='log in']") + await page.Locator("role=button[name='log in']").ClickAsync(); ``` Read more in [our documentation](./selectors#role-selector). @@ -238,7 +238,7 @@ This version was also tested against the following stable channels: - Locator now supports a `has` option that makes sure it contains another locator inside: ```csharp - await Page.Locator("article", new () { Has = Page.Locator(".highlight") }).ClickAsync(); + await Page.Locator("article", new() { Has = Page.Locator(".highlight") }).ClickAsync(); ``` Read more in [locator documentation](./api/class-locator#locator-locator-option-has) @@ -266,7 +266,7 @@ This version was also tested against the following stable channels: - [`method: Locator.dragTo`] - Each locator can now be optionally filtered by the text it contains: ```csharp - await Page.Locator("li", new () { HasTextString = "My Item" }) + await Page.Locator("li", new() { HasTextString = "My Item" }) .Locator("button").click(); ``` Read more in [locator documentation](./api/class-locator#locator-locator-option-has-text) @@ -426,7 +426,7 @@ Set `setStrict(true)` in your action calls to opt in. ```csharp // This will throw if you have more than one button! -await page.ClickAsync("button", new Page.ClickOptions().setStrict(true)); +await page.Locator("button", new() { Strict = true }); ``` #### 📍 New [**Locators API**](./api/class-locator) @@ -449,8 +449,8 @@ Learn more in the [documentation](./api/class-locator). React and Vue selectors allow selecting elements by its component name and/or property values. The syntax is very similar to [attribute selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors) and supports all attribute selector operators. ```csharp -await page.ClickAsync("_react=SubmitButton[enabled=true]"); -await page.ClickAsync("_vue=submit-button[enabled=true]"); +await page.Locator("_react=SubmitButton[enabled=true]").ClickAsync(); +await page.Locator("_vue=submit-button[enabled=true]").ClickAsync(); ``` Learn more in the [react selectors documentation](./selectors#react-selectors) and the [vue selectors documentation](./selectors#vue-selectors). diff --git a/docs/src/release-notes-java.md b/docs/src/release-notes-java.md index cf54bfb14e..74a3ef1fa1 100644 --- a/docs/src/release-notes-java.md +++ b/docs/src/release-notes-java.md @@ -100,7 +100,7 @@ Note that the new methods [`method: Page.routeFromHAR`] and [`method: BrowserCon ```java // Click a button with accessible name "log in" - page.click("role=button[name='log in']") + page.locator("role=button[name='log in']").click(); ``` Read more in [our documentation](./selectors#role-selector). @@ -126,7 +126,7 @@ Note that the new methods [`method: Page.routeFromHAR`] and [`method: BrowserCon ```java // Click a button with accessible name "log in" - page.click("role=button[name='log in']") + page.locator("role=button[name='log in']").click(); ``` Read more in [our documentation](./selectors#role-selector). @@ -237,7 +237,7 @@ public class TestExample { @Test void statusBecomesSubmitted() { ... - page.click("#submit-button"); + page.locator("#submit-button").click(); assertThat(page.locator(".status")).hasText("Submitted"); } } @@ -441,8 +441,8 @@ Learn more in the [documentation](./api/class-locator). React and Vue selectors allow selecting elements by its component name and/or property values. The syntax is very similar to [attribute selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors) and supports all attribute selector operators. ```java -page.click("_react=SubmitButton[enabled=true]"); -page.click("_vue=submit-button[enabled=true]"); +page.locator("_react=SubmitButton[enabled=true]").click(); +page.locator("_vue=submit-button[enabled=true]").click(); ``` Learn more in the [react selectors documentation](./selectors#react-selectors) and the [vue selectors documentation](./selectors#vue-selectors). diff --git a/docs/src/release-notes-js.md b/docs/src/release-notes-js.md index 7f83c04f5a..e9216b909d 100644 --- a/docs/src/release-notes-js.md +++ b/docs/src/release-notes-js.md @@ -165,7 +165,7 @@ WebServer is now considered "ready" if request to the specified port has any of ```js // Click a button with accessible name "log in" - await page.click('role=button[name="log in"]') + await page.locator('role=button[name="log in"]').click() ``` Read more in [our documentation](./selectors#role-selector). @@ -207,7 +207,7 @@ WebServer is now considered "ready" if request to the specified port has any of ```js // Click a button with accessible name "log in" - await page.click('role=button[name="log in"]') + await page.locator('role=button[name="log in"]').click() ``` Read more in [our documentation](./selectors#role-selector). @@ -807,8 +807,8 @@ Learn more in the [documentation](./api/class-locator). React and Vue selectors allow selecting elements by its component name and/or property values. The syntax is very similar to [attribute selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors) and supports all attribute selector operators. ```js -await page.click('_react=SubmitButton[enabled=true]'); -await page.click('_vue=submit-button[enabled=true]'); +await page.locator('_react=SubmitButton[enabled=true]').click(); +await page.locator('_vue=submit-button[enabled=true]').click(); ``` Learn more in the [react selectors documentation](./selectors#react-selectors) and the [vue selectors documentation](./selectors#vue-selectors). diff --git a/docs/src/release-notes-python.md b/docs/src/release-notes-python.md index b5a406cb63..051159f2e6 100644 --- a/docs/src/release-notes-python.md +++ b/docs/src/release-notes-python.md @@ -144,7 +144,7 @@ Note that the new methods [`method: Page.routeFromHAR`] and [`method: BrowserCon ```py # Click a button with accessible name "log in" - page.click("role=button[name='log in']") + page.locator("role=button[name='log in']").click() ``` Read more in [our documentation](./selectors#role-selector). @@ -172,12 +172,12 @@ Note that the new methods [`method: Page.routeFromHAR`] and [`method: BrowserCon ```python async # Click a button with accessible name "log in" - await page.click("role=button[name='log in']") + await page.locator("role=button[name='log in']").click() ``` ```python sync # Click a button with accessible name "log in" - page.click("role=button[name='log in']") + page.locator("role=button[name='log in']").click() ``` Read more in [our documentation](./selectors#role-selector). @@ -297,7 +297,7 @@ from playwright.async_api import Page, expect async def test_status_becomes_submitted(page: Page) -> None: # .. - await page.click("#submit-button") + await page.locator("#submit-button").click() await expect(page.locator(".status")).to_have_text("Submitted") ``` @@ -306,7 +306,7 @@ from playwright.sync_api import Page, expect def test_status_becomes_submitted(page: Page) -> None: # .. - page.click("#submit-button") + page.locator("#submit-button").click() expect(page.locator(".status")).to_have_text("Submitted") ``` @@ -490,7 +490,7 @@ Pass `strict=true` into your action calls to opt in. ```py # This will throw if you have more than one button! -page.click("button", strict=true) +page.click("button", strict=True) ``` #### 📍 New [**Locators API**](./api/class-locator) @@ -513,8 +513,8 @@ Learn more in the [documentation](./api/class-locator). React and Vue selectors allow selecting elements by its component name and/or property values. The syntax is very similar to [attribute selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors) and supports all attribute selector operators. ```py -page.click("_react=SubmitButton[enabled=true]"); -page.click("_vue=submit-button[enabled=true]"); +page.locator("_react=SubmitButton[enabled=true]").click() +page.locator("_vue=submit-button[enabled=true]").click() ``` Learn more in the [react selectors documentation](./selectors#react-selectors) and the [vue selectors documentation](./selectors#vue-selectors). diff --git a/docs/src/screenshots.md b/docs/src/screenshots.md index e7efe050ac..b9a9296405 100644 --- a/docs/src/screenshots.md +++ b/docs/src/screenshots.md @@ -17,6 +17,18 @@ await page.screenshot(path="screenshot.png") page.screenshot(path="screenshot.png") ``` +```java +page.screenshot(new Page.ScreenshotOptions() + .setPath(Paths.get("screenshot.png"))) +``` + +```csharp +await Page.ScreenshotAsync(new() +{ + Path = "screenshot.png", +}); +``` + Screenshots API accepts many parameters for image format, clip area, quality, etc. Make sure to check them out. @@ -44,6 +56,14 @@ await page.screenshot(path="screenshot.png", full_page=True) page.screenshot(path="screenshot.png", full_page=True) ``` +```csharp +await Page.ScreenshotAsync(new() +{ + Path = "screenshot.png", + FullPage = true, +}); +``` + ## Capture into buffer Rather than writing into a file, you can get a buffer with the image and post-process it or pass it to a third party pixel diff facility. @@ -61,16 +81,17 @@ System.out.println(Base64.getEncoder().encode(buffer)); ```python async # Capture into Image screenshot_bytes = await page.screenshot() -image = Image.open(io.BytesIO(screenshot_bytes)) +print(base64.b64encode(screenshot_bytes).decode()) ``` ```python sync screenshot_bytes = page.screenshot() -image = Image.open(io.BytesIO(screenshot_bytes)) +print(base64.b64encode(screenshot_bytes).decode()) ``` ```csharp var bytes = await page.ScreenshotAsync(); +Console.WriteLine(Convert.ToBase64String(bytes)); ``` @@ -95,5 +116,5 @@ page.locator(".header").screenshot(path="screenshot.png") ``` ```csharp -await page.Locator(".header").ScreenshotAsync(new LocatorScreenshotOptions { Path = "screenshot.png" }); +await page.Locator(".header").ScreenshotAsync(new() { Path = "screenshot.png" }); ``` diff --git a/docs/src/selectors.md b/docs/src/selectors.md index 5b8795a8c4..8440cb16ab 100644 --- a/docs/src/selectors.md +++ b/docs/src/selectors.md @@ -491,7 +491,7 @@ Locators support an option to only select elements that have some text somewhere page.locator("button", has_text="Click me").click() ``` ```csharp - await page.Locator("button", new PageLocatorOptions { HasText = "Click me" }).ClickAsync(); + await page.Locator("button", new() { HasText = "Click me" }).ClickAsync(); ``` You can also pass a regular expression. @@ -513,7 +513,7 @@ Locators support an option to only select elements that have a descendant matchi page.locator("article", has=page.locator("button.subscribe")) ``` ```csharp - page.Locator("article", new PageLocatorOptions { Has = page.Locator("button.subscribe") }) + page.Locator("article", new() { Has = page.Locator("button.subscribe") }) ``` Note that inner locator is matched starting from the outer one, not from the document root. @@ -572,7 +572,7 @@ You can add filtering to any locator by passing `:scope` selector to [`method: L ```csharp var locator = page.Locator(".row"); // ... later on ... - await locator.Locator(":scope", new LocatorLocatorOptions { HasText = "Hello" }).ClickAsync(); + await locator.Locator(":scope", new() { HasText = "Hello" }).ClickAsync(); ``` ## Selecting elements matching one of the conditions @@ -795,27 +795,27 @@ For example, consider the following DOM structure: `