docs: migrate page actions to locator actions 2/n (#15603)

This commit is contained in:
Max Schmitt 2022-07-13 11:50:18 +02:00 committed by GitHub
parent 3436e64b75
commit ee7d60fcee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
44 changed files with 344 additions and 314 deletions

View file

@ -63,7 +63,7 @@ namespace Playwright.TestingHarnessTest.NUnit
// Assuming personal access token available in the environment. // Assuming personal access token available in the environment.
headers.Add("Authorization", "token " + API_TOKEN); 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. // All requests we send go to this API endpoint.
BaseURL = "https://api.github.com", BaseURL = "https://api.github.com",
ExtraHTTPHeaders = headers, ExtraHTTPHeaders = headers,

View file

@ -109,28 +109,28 @@ done and its response has started loading in the popup.
```js ```js
const [newPage] = await Promise.all([ const [newPage] = await Promise.all([
context.waitForEvent('page'), context.waitForEvent('page'),
page.click('a[target=_blank]'), page.locator('a[target=_blank]').click(),
]); ]);
console.log(await newPage.evaluate('location.href')); console.log(await newPage.evaluate('location.href'));
``` ```
```java ```java
Page newPage = context.waitForPage(() -> { Page newPage = context.waitForPage(() -> {
page.click("a[target=_blank]"); page.locator("a[target=_blank]").click();
}); });
System.out.println(newPage.evaluate("location.href")); System.out.println(newPage.evaluate("location.href"));
``` ```
```python async ```python async
async with context.expect_page() as page_info: 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 page = await page_info.value
print(await page.evaluate("location.href")) print(await page.evaluate("location.href"))
``` ```
```python sync ```python sync
with context.expect_page() as page_info: with context.expect_page() as page_info:
page.click("a[target=_blank]"), page.locator("a[target=_blank]").click(),
page = page_info.value page = page_info.value
print(page.evaluate("location.href")) print(page.evaluate("location.href"))
``` ```
@ -138,7 +138,7 @@ print(page.evaluate("location.href"))
```csharp ```csharp
var popup = await context.RunAndWaitForPageAsync(async => var popup = await context.RunAndWaitForPageAsync(async =>
{ {
await page.ClickAsync("a"); await page.Locator("a").ClickAsync();
}); });
Console.WriteLine(await popup.EvaluateAsync<string>("location.href")); Console.WriteLine(await popup.EvaluateAsync<string>("location.href"));
``` ```
@ -435,7 +435,7 @@ const { webkit } = require('playwright'); // Or 'chromium' or 'firefox'.
<button onclick="onClick()">Click me</button> <button onclick="onClick()">Click me</button>
<div></div> <div></div>
`); `);
await page.click('button'); await page.locator('button').click();
})(); })();
``` ```
@ -457,7 +457,7 @@ public class Example {
"</script>\n" + "</script>\n" +
"<button onclick=\"onClick()\">Click me</button>\n" + "<button onclick=\"onClick()\">Click me</button>\n" +
"<div></div>"); "<div></div>");
page.click("button"); page.locator("button").click();
} }
} }
} }
@ -482,7 +482,7 @@ async def run(playwright):
<button onclick="onClick()">Click me</button> <button onclick="onClick()">Click me</button>
<div></div> <div></div>
""") """)
await page.click("button") await page.locator("button").click()
async def main(): async def main():
async with async_playwright() as playwright: async with async_playwright() as playwright:
@ -508,7 +508,7 @@ def run(playwright):
<button onclick="onClick()">Click me</button> <button onclick="onClick()">Click me</button>
<div></div> <div></div>
""") """)
page.click("button") page.locator("button").click()
with sync_playwright() as playwright: with sync_playwright() as playwright:
run(playwright) run(playwright)
@ -530,7 +530,7 @@ await page.SetContentAsync("<script>\n" +
"</script>\n" + "</script>\n" +
"<button onclick=\"onClick()\">Click me</button>\n" + "<button onclick=\"onClick()\">Click me</button>\n" +
"<div></div>"); "<div></div>");
await page.ClickAsync("button"); await page.Locator("button").ClickAsync();
``` ```
An example of passing an element handle: An example of passing an element handle:
@ -660,7 +660,7 @@ const crypto = require('crypto');
<button onclick="onClick()">Click me</button> <button onclick="onClick()">Click me</button>
<div></div> <div></div>
`); `);
await page.click('button'); await page.locator('button').click();
})(); })();
``` ```
@ -696,7 +696,7 @@ public class Example {
"</script>\n" + "</script>\n" +
"<button onclick=\"onClick()\">Click me</button>\n" + "<button onclick=\"onClick()\">Click me</button>\n" +
"<div></div>\n"); "<div></div>\n");
page.click("button"); page.locator("button").click();
} }
} }
} }
@ -728,7 +728,7 @@ async def run(playwright):
<button onclick="onClick()">Click me</button> <button onclick="onClick()">Click me</button>
<div></div> <div></div>
""") """)
await page.click("button") await page.locator("button").click()
async def main(): async def main():
async with async_playwright() as playwright: async with async_playwright() as playwright:
@ -761,7 +761,7 @@ def run(playwright):
<button onclick="onClick()">Click me</button> <button onclick="onClick()">Click me</button>
<div></div> <div></div>
""") """)
page.click("button") page.locator("button").click()
with sync_playwright() as playwright: with sync_playwright() as playwright:
run(playwright) run(playwright)
@ -796,7 +796,7 @@ class BrowserContextExamples
"<button onclick=\"onClick()\">Click me</button>\n" + "<button onclick=\"onClick()\">Click me</button>\n" +
"<div></div>"); "<div></div>");
await page.ClickAsync("button"); await page.Locator("button").ClickAsync();
Console.WriteLine(await page.TextContentAsync("div")); 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 ```js
const [page, _] = await Promise.all([ const [page, _] = await Promise.all([
context.waitForEvent('page'), context.waitForEvent('page'),
page.click('button') page.locator('button').click()
]); ]);
``` ```
```java ```java
Page newPage = context.waitForPage(() -> page.click("button")); Page newPage = context.waitForPage(() -> page.locator("button").click());
``` ```
```python async ```python async
async with context.expect_event("page") as event_info: async with context.expect_event("page") as event_info:
await page.click("button") await page.locator("button").click()
page = await event_info.value page = await event_info.value
``` ```
```python sync ```python sync
with context.expect_event("page") as event_info: with context.expect_event("page") as event_info:
page.click("button") page.locator("button").click()
page = event_info.value page = event_info.value
``` ```
```csharp ```csharp
var page = await context.RunAndWaitForPageAsync(async () => var page = await context.RunAndWaitForPageAsync(async () =>
{ {
await page.ClickAsync("button"); await page.Locator("button").ClickAsync();
}); });
``` ```

View file

@ -23,7 +23,7 @@ const path = await download.path();
```java ```java
// wait for download to start // 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 // wait for download to complete
Path path = download.path(); Path path = download.path();
``` ```
@ -31,7 +31,7 @@ Path path = download.path();
```java ```java
// wait for download to start // wait for download to start
Download download = page.waitForDownload(() -> { Download download = page.waitForDownload(() -> {
page.click("a"); page.locator("a").click();
}); });
// wait for download to complete // wait for download to complete
Path path = download.path(); Path path = download.path();
@ -39,7 +39,7 @@ Path path = download.path();
```python async ```python async
async with page.expect_download() as download_info: async with page.expect_download() as download_info:
await page.click("a") await page.locator("a").click()
download = await download_info.value download = await download_info.value
# waits for download to complete # waits for download to complete
path = await download.path() path = await download.path()
@ -47,7 +47,7 @@ path = await download.path()
```python sync ```python sync
with page.expect_download() as download_info: with page.expect_download() as download_info:
page.click("a") page.locator("a").click()
download = download_info.value download = download_info.value
# wait for download to complete # wait for download to complete
path = download.path() path = download.path()
@ -56,7 +56,7 @@ path = download.path()
```csharp ```csharp
var download = await page.RunAndWaitForDownloadAsync(async () => var download = await page.RunAndWaitForDownloadAsync(async () =>
{ {
await page.ClickAsync("#downloadButton"); await page.Locator("#downloadButton").ClickAsync();
}); });
Console.WriteLine(await download.PathAsync()); Console.WriteLine(await download.PathAsync());
``` ```

View file

@ -16,20 +16,20 @@ await fileChooser.setFiles('myfile.pdf');
``` ```
```java ```java
FileChooser fileChooser = page.waitForFileChooser(() -> page.click("upload")); FileChooser fileChooser = page.waitForFileChooser(() -> page.locator("upload").click());
fileChooser.setFiles(Paths.get("myfile.pdf")); fileChooser.setFiles(Paths.get("myfile.pdf"));
``` ```
```python async ```python async
async with page.expect_file_chooser() as fc_info: async with page.expect_file_chooser() as fc_info:
await page.click("upload") await page.locator("upload").click()
file_chooser = await fc_info.value file_chooser = await fc_info.value
await file_chooser.set_files("myfile.pdf") await file_chooser.set_files("myfile.pdf")
``` ```
```python sync ```python sync
with page.expect_file_chooser() as fc_info: with page.expect_file_chooser() as fc_info:
page.click("upload") page.locator("upload").click()
file_chooser = fc_info.value file_chooser = fc_info.value
file_chooser.set_files("myfile.pdf") file_chooser.set_files("myfile.pdf")
``` ```
@ -37,7 +37,7 @@ file_chooser.set_files("myfile.pdf")
```csharp ```csharp
var fileChooser = await page.RunAndWaitForFileChooserAsync(async () => var fileChooser = await page.RunAndWaitForFileChooserAsync(async () =>
{ {
await page.ClickAsync("upload"); await page.Locator("upload").ClickAsync();
}); });
await fileChooser.SetFilesAsync("temp.txt"); await fileChooser.SetFilesAsync("temp.txt");
``` ```

View file

@ -8,7 +8,7 @@ import { test, expect } from '@playwright/test';
test('status becomes submitted', async ({ page }) => { test('status becomes submitted', async ({ page }) => {
// ... // ...
await page.click('#submit-button'); await page.locator('#submit-button').click();
await expect(page.locator('.status')).toHaveText('Submitted'); await expect(page.locator('.status')).toHaveText('Submitted');
}); });
``` ```
@ -22,7 +22,7 @@ public class TestLocator {
@Test @Test
void statusBecomesSubmitted() { void statusBecomesSubmitted() {
... ...
page.click("#submit-button"); page.locator("#submit-button").click();
assertThat(page.locator(".status")).hasText("Submitted"); 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: 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") 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: 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") expect(page.locator(".status")).to_have_text("Submitted")
``` ```
@ -60,7 +60,7 @@ public class ExampleTests : PageTest
public async Task StatusBecomesSubmitted() public async Task StatusBecomesSubmitted()
{ {
// .. // ..
await Page.ClickAsync("#submit-button"); await Page.Locator("#submit-button").ClickAsync();
await Expect(Page.Locator(".status")).ToHaveTextAsync("Submitted"); await Expect(Page.Locator(".status")).ToHaveTextAsync("Submitted");
} }
} }

View file

@ -1654,7 +1654,7 @@ class PageExamples
public static async Task Main() public static async Task Main()
{ {
using var playwright = await Playwright.CreateAsync(); 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 Headless: false
}); });
@ -1916,7 +1916,7 @@ class PageExamples
public static async Task Main() public static async Task Main()
{ {
using var playwright = await Playwright.CreateAsync(); 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 Headless: false
}); });

View file

@ -8,7 +8,7 @@ import { test, expect } from '@playwright/test';
test('navigates to login', async ({ page }) => { test('navigates to login', async ({ page }) => {
// ... // ...
await page.click('#login'); await page.locator('#login').click();
await expect(page).toHaveURL(/.*\/login/); await expect(page).toHaveURL(/.*\/login/);
}); });
``` ```
@ -22,7 +22,7 @@ public class TestPage {
@Test @Test
void navigatesToLoginPage() { void navigatesToLoginPage() {
... ...
page.click("#login"); page.locator("#login").click();
assertThat(page).hasURL(Pattern.compile(".*/login")); 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: 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")) 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: 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")) expect(page).to_have_url(re.compile(r".*/login"))
``` ```
@ -62,7 +62,7 @@ public class ExampleTests : PageTest
public async Task NavigatetoLoginPage() public async Task NavigatetoLoginPage()
{ {
// .. // ..
await Page.ClickAsync("#login"); await Page.Locator("#login").ClickAsync();
await Expect(Page.Locator("div#foobar")).ToHaveURL(new Regex(".*/login")); await Expect(Page.Locator("div#foobar")).ToHaveURL(new Regex(".*/login"));
} }
} }

View file

@ -10,7 +10,7 @@ import { test, expect } from '@playwright/test';
test('status becomes submitted', async ({ page }) => { test('status becomes submitted', async ({ page }) => {
// ... // ...
await page.click('#submit-button') await page.locator('#submit-button').click()
await expect(page.locator('.status')).toHaveText('Submitted'); 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: 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") 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: 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") expect(page.locator(".status")).to_have_text("Submitted")
``` ```
@ -42,7 +42,7 @@ public class TestExample {
@Test @Test
void statusBecomesSubmitted() { void statusBecomesSubmitted() {
... ...
page.click("#submit-button"); page.locator("#submit-button").click();
assertThat(page.locator(".status")).hasText("Submitted"); assertThat(page.locator(".status")).hasText("Submitted");
} }
} }
@ -60,6 +60,7 @@ public class ExampleTests : PageTest
[Test] [Test]
public async Task StatusBecomesSubmitted() public async Task StatusBecomesSubmitted()
{ {
await Page.Locator("#submit-button").ClickAsync();
await Expect(Page.Locator(".status")).ToHaveTextAsync("Submitted"); await Expect(Page.Locator(".status")).ToHaveTextAsync("Submitted");
} }
} }

View file

@ -36,7 +36,7 @@ const { selectors, firefox } = require('playwright'); // Or 'chromium' or 'webk
// Use the selector prefixed with its name. // Use the selector prefixed with its name.
const button = page.locator('tag=button'); const button = page.locator('tag=button');
// Combine it with other selector engines. // 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. // Can use it in any methods supporting selectors.
const buttonCount = await page.locator('tag=button').count(); const buttonCount = await page.locator('tag=button').count();
@ -64,7 +64,7 @@ page.setContent("<div><button>Click me</button></div>");
// Use the selector prefixed with its name. // Use the selector prefixed with its name.
Locator button = page.locator("tag=button"); Locator button = page.locator("tag=button");
// Combine it with other selector engines. // 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. // Can use it in any methods supporting selectors.
int buttonCount = (int) page.locator("tag=button").count(); int buttonCount = (int) page.locator("tag=button").count();
browser.close(); browser.close();
@ -96,7 +96,7 @@ async def run(playwright):
# Use the selector prefixed with its name. # Use the selector prefixed with its name.
button = await page.query_selector('tag=button') button = await page.query_selector('tag=button')
# Combine it with other selector engines. # 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. # Can use it in any methods supporting selectors.
button_count = await page.locator('tag=button').count() button_count = await page.locator('tag=button').count()
print(button_count) print(button_count)
@ -134,7 +134,7 @@ def run(playwright):
# Use the selector prefixed with its name. # Use the selector prefixed with its name.
button = page.locator('tag=button') button = page.locator('tag=button')
# Combine it with other selector engines. # 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. # Can use it in any methods supporting selectors.
button_count = page.locator('tag=button').count() button_count = page.locator('tag=button').count()
print(button_count) print(button_count)
@ -164,7 +164,7 @@ await page.SetContentAsync("<div><button>Click me</button></div>");
// Use the selector prefixed with its name. // Use the selector prefixed with its name.
var button = page.Locator("tag=button"); var button = page.Locator("tag=button");
// Combine it with other selector engines. // 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. // Can use it in any methods supporting selectors.
int buttonCount = await page.Locator("tag=button").CountAsync(); int buttonCount = await page.Locator("tag=button").CountAsync();
``` ```

View file

@ -13,7 +13,7 @@ const playwright = require('playwright');
const context = await browser.newContext(); const context = await browser.newContext();
const page = await context.newPage(); const page = await context.newPage();
try { try {
await page.click("text=Foo", { await page.locator("text=Foo").click({
timeout: 100, timeout: 100,
}) })
} catch (error) { } catch (error) {
@ -32,7 +32,7 @@ async def run(playwright):
browser = await playwright.chromium.launch() browser = await playwright.chromium.launch()
page = await browser.new_page() page = await browser.new_page()
try: try:
await page.click("text=Example", timeout=100) await page.locator("text=Example").click(timeout=100)
except PlaywrightTimeoutError: except PlaywrightTimeoutError:
print("Timeout!") print("Timeout!")
await browser.close() await browser.close()
@ -51,7 +51,7 @@ with sync_playwright() as p:
browser = p.chromium.launch() browser = p.chromium.launch()
page = browser.new_page() page = browser.new_page()
try: try:
page.click("text=Example", timeout=100) page.locator("text=Example").click(timeout=100)
except PlaywrightTimeoutError: except PlaywrightTimeoutError:
print("Timeout!") print("Timeout!")
browser.close() browser.close()
@ -69,7 +69,7 @@ public class TimeoutErrorExample {
BrowserContext context = browser.newContext(); BrowserContext context = browser.newContext();
Page page = context.newPage(); Page page = context.newPage();
try { try {
page.click("text=Example", new Page.ClickOptions().setTimeout(100)); page.locator("text=Example").click(new Locator.ClickOptions().setTimeout(100));
} catch (TimeoutError e) { } catch (TimeoutError e) {
System.out.println("Timeout!"); System.out.println("Timeout!");
} }

View file

@ -47,14 +47,14 @@ context.tracing.stop(path = "trace.zip")
```csharp ```csharp
await using var browser = playwright.Chromium.LaunchAsync(); await using var browser = playwright.Chromium.LaunchAsync();
await using var context = await browser.NewContextAsync(); await using var context = await browser.NewContextAsync();
await context.Tracing.StartAsync(new TracingStartOptions await context.Tracing.StartAsync(new()
{ {
Screenshots: true, Screenshots: true,
Snapshots: true Snapshots: true
}); });
var page = context.NewPageAsync(); var page = context.NewPageAsync();
await page.GotoAsync("https://playwright.dev"); await page.GotoAsync("https://playwright.dev");
await context.Tracing.StopAsync(new TracingStopOptions await context.Tracing.StopAsync(new()
{ {
Path: "trace.zip" Path: "trace.zip"
}); });
@ -99,14 +99,14 @@ context.tracing.stop(path = "trace.zip")
```csharp ```csharp
await using var browser = playwright.Chromium.LaunchAsync(); await using var browser = playwright.Chromium.LaunchAsync();
await using var context = await browser.NewContextAsync(); await using var context = await browser.NewContextAsync();
await context.Tracing.StartAsync(new TracingStartOptions await context.Tracing.StartAsync(new()
{ {
Screenshots: true, Screenshots: true,
Snapshots: true Snapshots: true
}); });
var page = context.NewPageAsync(); var page = context.NewPageAsync();
await page.GotoAsync("https://playwright.dev"); await page.GotoAsync("https://playwright.dev");
await context.Tracing.StopAsync(new TracingStopOptions await context.Tracing.StopAsync(new()
{ {
Path: "trace.zip" Path: "trace.zip"
}); });
@ -167,7 +167,7 @@ const page = await context.newPage();
await page.goto('https://playwright.dev'); await page.goto('https://playwright.dev');
await context.tracing.startChunk(); 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. // Everything between startChunk and stopChunk will be recorded in the trace.
await context.tracing.stopChunk({ path: 'trace1.zip' }); await context.tracing.stopChunk({ path: 'trace1.zip' });
@ -185,7 +185,7 @@ Page page = context.newPage();
page.navigate("https://playwright.dev"); page.navigate("https://playwright.dev");
context.tracing().startChunk(); 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. // Everything between startChunk and stopChunk will be recorded in the trace.
context.tracing().stopChunk(new Tracing.StopChunkOptions() context.tracing().stopChunk(new Tracing.StopChunkOptions()
.setPath(Paths.get("trace1.zip"))); .setPath(Paths.get("trace1.zip")));
@ -203,7 +203,7 @@ page = await context.new_page()
await page.goto("https://playwright.dev") await page.goto("https://playwright.dev")
await context.tracing.start_chunk() 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. # Everything between start_chunk and stop_chunk will be recorded in the trace.
await context.tracing.stop_chunk(path = "trace1.zip") await context.tracing.stop_chunk(path = "trace1.zip")
@ -219,7 +219,7 @@ page = context.new_page()
page.goto("https://playwright.dev") page.goto("https://playwright.dev")
context.tracing.start_chunk() 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. # Everything between start_chunk and stop_chunk will be recorded in the trace.
context.tracing.stop_chunk(path = "trace1.zip") context.tracing.stop_chunk(path = "trace1.zip")
@ -232,7 +232,7 @@ context.tracing.stop_chunk(path = "trace2.zip")
```csharp ```csharp
await using var browser = playwright.Chromium.LaunchAsync(); await using var browser = playwright.Chromium.LaunchAsync();
await using var context = await browser.NewContextAsync(); await using var context = await browser.NewContextAsync();
await context.Tracing.StartAsync(new TracingStartOptions await context.Tracing.StartAsync(new()
{ {
Screenshots: true, Screenshots: true,
Snapshots: true Snapshots: true
@ -243,7 +243,7 @@ await page.GotoAsync("https://playwright.dev");
await context.Tracing.StartChunkAsync(); await context.Tracing.StartChunkAsync();
await page.ClickAsync("text=Get Started"); await page.ClickAsync("text=Get Started");
// Everything between StartChunkAsync and StopChunkAsync will be recorded in the trace. // 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" Path: "trace1.zip"
}); });
@ -251,7 +251,7 @@ await context.Tracing.StopChunkAsync(new TracingStopChunkOptions
await context.Tracing.StartChunkAsync(); await context.Tracing.StartChunkAsync();
await page.GotoAsync("http://example.com"); await page.GotoAsync("http://example.com");
// Save a second trace file with different actions. // Save a second trace file with different actions.
await context.Tracing.StopChunkAsync(new TracingStopChunkOptions await context.Tracing.StopChunkAsync(new()
{ {
Path: "trace2.zip" Path: "trace2.zip"
}); });

View file

@ -135,13 +135,13 @@ context = browser.new_context(storage_state="state.json")
```csharp ```csharp
// Save storage state into the file. // Save storage state into the file.
await context.StorageStateAsync(new BrowserContextStorageStateOptions await context.StorageStateAsync(new()
{ {
Path = "state.json" Path = "state.json"
}); });
// Create a new context with the saved storage state. // 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" StorageStatePath = "state.json"
}); });
@ -332,7 +332,7 @@ class Program
{ {
using var playwright = await Playwright.CreateAsync(); using var playwright = await Playwright.CreateAsync();
var chromium = playwright.Chromium; 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 Headless = false
}); });

View file

@ -470,7 +470,7 @@ with sync_playwright() as p:
using Microsoft.Playwright; using Microsoft.Playwright;
using var playwright = await Playwright.CreateAsync(); using var playwright = await Playwright.CreateAsync();
await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions await playwright.Chromium.LaunchAsync(new()
{ {
Headless = false Headless = false
}); });

View file

@ -50,7 +50,7 @@ chromium.launch(headless=False, slow_mo=100) # or firefox, webkit
```csharp ```csharp
// Chromium, Firefox, or Webkit // 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, Headless = false,
SlowMo = 100 SlowMo = 100
@ -89,7 +89,7 @@ chromium.launch(devtools=True)
``` ```
```csharp ```csharp
await using var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions await using var browser = await playwright.Chromium.LaunchAsync(new()
{ {
Devtools: true Devtools: true
}); });

View file

@ -72,7 +72,7 @@ class Program
public static async Task Main() public static async Task Main()
{ {
using var playwright = await Playwright.CreateAsync(); 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 Headless: False
}); });
@ -193,7 +193,7 @@ context = browser.new_context(
```csharp ```csharp
// Create context with given viewport // 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 } 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); await page.SetViewportSizeAsync(1600, 1200);
// Emulate high-DPI // 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 }, ViewportSize = new ViewportSize() { Width = 2560, Height = 1440 },
DeviceScaleFactor = 2 DeviceScaleFactor = 2
@ -249,7 +249,7 @@ context = browser.new_context(
``` ```
```csharp ```csharp
await using var context = await browser.NewContextAsync(new BrowserNewContextOptions await using var context = await browser.NewContextAsync(new()
{ {
Locale = "de-DE", Locale = "de-DE",
TimezoneId = "Europe/Berlin" TimezoneId = "Europe/Berlin"
@ -394,7 +394,7 @@ context = browser.new_context(
``` ```
```csharp ```csharp
await using var context = await browser.NewContextAsync(new BrowserNewContextOptions await using var context = await browser.NewContextAsync(new()
{ {
Permissions = new[] { "geolocation" }, Permissions = new[] { "geolocation" },
Geolocation = new Geolocation() { Longitude = 48.858455f, Latitude = 2.294474f } Geolocation = new Geolocation() { Longitude = 48.858455f, Latitude = 2.294474f }
@ -507,25 +507,25 @@ page.emulate_media(media='print')
```csharp ```csharp
// Create context with dark mode // 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 ColorScheme = ColorScheme.Dark
}); });
// Create page with dark mode // Create page with dark mode
var page = await browser.NewPageAsync(new BrowserNewPageOptions var page = await browser.NewPageAsync(new()
{ {
ColorScheme = ColorScheme.Dark ColorScheme = ColorScheme.Dark
}); });
// Change color scheme for the page // Change color scheme for the page
await page.EmulateMediaAsync(new PageEmulateMediaOptions await page.EmulateMediaAsync(new()
{ {
ColorScheme = ColorScheme.Dark ColorScheme = ColorScheme.Dark
}); });
// Change media for page // Change media for page
await page.EmulateMediaAsync(new PageEmulateMediaOptions await page.EmulateMediaAsync(new()
{ {
Media = Media.Print Media = Media.Print
}); });

View file

@ -46,7 +46,7 @@ const button = page.locator('tag=button');
await button.click(); await button.click();
// We can combine it with other selector engines using `>>` combinator. // 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. // We can use it in any methods supporting selectors.
const buttonCount = await page.locator('tag=button').count(); const buttonCount = await page.locator('tag=button').count();
@ -74,7 +74,7 @@ Locator button = page.locator("tag=button");
button.click(); button.click();
// We can combine it with other selector engines using ">>" combinator. // 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. // We can use it in any methods supporting selectors.
int buttonCount = (int) page.locator("tag=button").count(); int buttonCount = (int) page.locator("tag=button").count();
@ -103,7 +103,7 @@ button = page.locator("tag=button")
await button.click() await button.click()
# we can combine it with other selector engines using `>>` combinator. # 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. # we can use it in any methods supporting selectors.
button_count = await page.locator("tag=button").count() button_count = await page.locator("tag=button").count()
@ -132,7 +132,7 @@ button = page.locator("tag=button")
button.click() button.click()
# we can combine it with other selector engines using `>>` combinator. # 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. # we can use it in any methods supporting selectors.
button_count = page.locator("tag=button").count() button_count = page.locator("tag=button").count()

View file

@ -75,7 +75,7 @@ test("my test", async ({ page }) => {
"/docs/intro" "/docs/intro"
); );
await page.click("text=Get Started"); await page.locator("text=Get Started").click();
// Expect some text to be visible on the page. // Expect some text to be visible on the page.
await expect(page.locator("text=Introduction").first()).toBeVisible(); await expect(page.locator("text=Introduction").first()).toBeVisible();
}); });
@ -97,7 +97,7 @@ test("my test", async ({ page }) => {
"/docs/intro" "/docs/intro"
); );
await page.click("text=Get Started"); await page.locator("text=Get Started").click();
// Expect some text to be visible on the page. // Expect some text to be visible on the page.
await expect(page.locator("text=Introduction").first()).toBeVisible(); await expect(page.locator("text=Introduction").first()).toBeVisible();
}); });

View file

@ -61,7 +61,7 @@ test("my test", async ({ page }) => {
"/docs/intro" "/docs/intro"
); );
await page.click("text=Get Started"); await page.locator("text=Get Started").click();
// Expect some text to be visible on the page. // Expect some text to be visible on the page.
await expect(page.locator("text=Introduction").first()).toBeVisible(); await expect(page.locator("text=Introduction").first()).toBeVisible();
}); });
@ -83,7 +83,7 @@ test("my test", async ({ page }) => {
"/docs/intro" "/docs/intro"
); );
await page.click("text=Get Started"); await page.locator("text=Get Started").click();
// Expect some text to be visible on the page. // Expect some text to be visible on the page.
await expect(page.locator("text=Introduction").first()).toBeVisible(); await expect(page.locator("text=Introduction").first()).toBeVisible();
}); });

View file

@ -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). 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 ```csharp
await playwright.Firefox.LaunchAsync(new BrowserTypeLaunchOptions await playwright.Firefox.LaunchAsync(new()
{ {
Headless = false, Headless = false,
SlowMo = 50, SlowMo = 50,
@ -87,17 +87,25 @@ namespace PlaywrightTests;
public class Tests : PageTest public class Tests : PageTest
{ {
[Test] [Test]
public async Task ShouldAdd() async public Task ShouldHaveTheCorrectSlogan()
{ {
int result = await Page.EvaluateAsync<int>("() => 7 + 3"); await Page.GotoAsync("https://playwright.dev");
Assert.AreEqual(10, result); await Expect(Page.Locator("text=enables reliable end-to-end testing for modern web apps")).ToBeVisibleAsync();
} }
[Test] [Test]
public async Task ShouldMultiply() public async Task ShouldHaveTheCorrectTitle()
{ {
int result = await Page.EvaluateAsync<int>("() => 7 * 3"); await Page.GotoAsync("https://playwright.dev");
Assert.AreEqual(21, result); var title = Page.Locator(".navbar__inner .navbar__title");
await Expect(title).ToHaveTextAsync("Playwright");
}
[Test]
public async Task ShouldAdd()
{
var result = await Page.EvaluateAsync<int>("() => 7 + 3");
Assert.AreEqual(10, result);
} }
} }
``` ```

View file

@ -208,9 +208,9 @@ test('my test', async ({ page }) => {
await expect(page).toHaveTitle(/Playwright/); await expect(page).toHaveTitle(/Playwright/);
// Expect an attribute "to be strictly equal" to the value. // 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. // Expect some text to be visible on the page.
await expect(page.locator('text=Introduction').first()).toBeVisible(); await expect(page.locator('text=Introduction').first()).toBeVisible();
}); });
@ -227,9 +227,9 @@ test('my test', async ({ page }) => {
await expect(page).toHaveTitle(/Playwright/); await expect(page).toHaveTitle(/Playwright/);
// Expect an attribute "to be strictly equal" to the value. // 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. // Expect some text to be visible on the page.
await expect(page.locator('text=Introduction').first()).toBeVisible(); await expect(page.locator('text=Introduction').first()).toBeVisible();
}); });

View file

@ -106,7 +106,7 @@ await page.locator('text=Example Domain').waitFor();
// Navigate and click element // Navigate and click element
// Click will auto-wait for the element // Click will auto-wait for the element
await page.goto('https://example.com'); await page.goto('https://example.com');
await page.click('text=Example Domain'); await page.locator('text=Example Domain').click();
``` ```
```java ```java
@ -117,7 +117,7 @@ page.locator("text=Example Domain").waitFor();
// Navigate and click element // Navigate and click element
// Click will auto-wait for the element // Click will auto-wait for the element
page.navigate("https://example.com"); page.navigate("https://example.com");
page.click("text=Example Domain"); page.locator("text=Example Domain").click();
``` ```
```python async ```python async
@ -128,7 +128,7 @@ await page.locator("text=example domain").wait_for()
# Navigate and click element # Navigate and click element
# Click will auto-wait for the element # Click will auto-wait for the element
await page.goto("https://example.com") await page.goto("https://example.com")
await page.click("text=example domain") await page.locator("text=example domain").click()
``` ```
```python sync ```python sync
@ -139,7 +139,7 @@ page.locator("text=example domain").wait_for()
# Navigate and click element # Navigate and click element
# Click will auto-wait for the element # Click will auto-wait for the element
page.goto("https://example.com") page.goto("https://example.com")
page.click("text=example domain") page.locator("text=example domain").click()
``` ```
```csharp ```csharp
@ -150,7 +150,7 @@ await page.Locator("text=Example Domain").WaitForAsync();
// Navigate and click element // Navigate and click element
// Click will auto-wait for the element // Click will auto-wait for the element
await page.GotoAsync("https://example.com"); await page.GotoAsync("https://example.com");
await page.ClickAsync("text=Example Domain"); await page.Locator("text=Example Domain").ClickAsync();
``` ```
### API reference ### API reference
@ -161,145 +161,145 @@ await page.ClickAsync("text=Example Domain");
## Scenarios initiated by page interaction ## 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 ### 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. the navigated page which would auto-wait for an element.
```js ```js
// Click will auto-wait for navigation to complete // 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 // Fill will auto-wait for element on navigated page
await page.fill('#username', 'John Doe'); await page.locator('#username').fill('John Doe');
``` ```
```java ```java
// Click will auto-wait for navigation to complete // 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 // Fill will auto-wait for element on navigated page
page.fill("#username", "John Doe"); page.locator("#username").fill("John Doe");
``` ```
```python async ```python async
# Click will auto-wait for navigation to complete # 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 # Fill will auto-wait for element on navigated page
await page.fill("#username", "John Doe") await page.locator("#username").fill("John Doe")
``` ```
```python sync ```python sync
# Click will auto-wait for navigation to complete # 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 # Fill will auto-wait for element on navigated page
page.fill("#username", "John Doe") page.locator("#username").fill("John Doe")
``` ```
```csharp ```csharp
// Click will auto-wait for navigation to complete // 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 // Fill will auto-wait for element on navigated page
await page.FillAsync("#username", "John Doe"); await page.Locator("#username").FillAsync("John Doe");
``` ```
### Custom wait ### 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 ```js
await page.click('button'); // Click triggers navigation await page.locator('button').click(); // Click triggers navigation
await page.waitForLoadState('networkidle'); // This resolves after 'networkidle' await page.waitForLoadState('networkidle'); // This resolves after 'networkidle'
``` ```
```java ```java
page.click("button"); // Click triggers navigation page.locator("button").click(); // Click triggers navigation
page.waitForLoadState(LoadState.NETWORKIDLE); // This resolves after "networkidle" page.waitForLoadState(LoadState.NETWORKIDLE); // This resolves after "networkidle"
``` ```
```python async ```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" await page.wait_for_load_state("networkidle"); # This waits for the "networkidle"
``` ```
```python sync ```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" page.wait_for_load_state("networkidle"); # This waits for the "networkidle"
``` ```
```csharp ```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" await page.WaitForLoadStateAsync(LoadState.NetworkIdle); // This resolves after "networkidle"
``` ```
### Wait for element ### Wait for element
In lazy-loaded pages, it can be useful to wait until an element is visible with [`method: Locator.waitFor`]. 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 ```js
// Click will auto-wait for the element and trigger navigation // 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 // Wait for the element
await page.locator('#username').waitFor(); await page.locator('#username').waitFor();
// Click triggers navigation // Click triggers navigation
await page.click('text=Login'); await page.locator('text=Login').click();
// Fill will auto-wait for element // Fill will auto-wait for element
await page.fill('#username', 'John Doe'); await page.locator('#username').fill('John Doe');
``` ```
```java ```java
// Click will auto-wait for the element and trigger navigation // Click will auto-wait for the element and trigger navigation
page.click("text=Login"); page.locator("text=Login").click();
// Wait for the element // Wait for the element
page.locator("#username").waitFor(); page.locator("#username").waitFor();
// Click triggers navigation // Click triggers navigation
page.click("text=Login"); page.locator("text=Login").click();
// Fill will auto-wait for element // Fill will auto-wait for element
page.fill("#username", "John Doe"); page.locator("#username").fill("John Doe");
``` ```
```python async ```python async
# Click will auto-wait for the element and trigger navigation # 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 # Wait for the element
await page.locator("#username").wait_for() await page.locator("#username").wait_for()
# Click triggers navigation # Click triggers navigation
await page.click("text=Login") await page.locator("text=Login").click()
# Fill will auto-wait for element # Fill will auto-wait for element
await page.fill("#username", "John Doe") await page.locator("#username").fill("John Doe")
``` ```
```python sync ```python sync
# Click triggers navigation # Click triggers navigation
page.click("text=Login") page.locator("text=Login").click()
# Click will auto-wait for the element # Click will auto-wait for the element
page.locator("#username").wait_for() page.locator("#username").wait_for()
# Click triggers navigation # Click triggers navigation
page.click("text=Login") page.locator("text=Login").click()
# Fill will auto-wait for element # Fill will auto-wait for element
page.fill("#username", "John Doe") page.locator("#username").fill("John Doe")
``` ```
```csharp ```csharp
// Click will auto-wait for the element and trigger navigation // 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 // Wait for the element
await page.Locator("#username").WaitForAsync(); await page.Locator("#username").WaitForAsync();
// Click triggers navigation // Click triggers navigation
await page.ClickAsync("text=Login"); await page.Locator("text=Login").ClickAsync();
// Fill will auto-wait for element // Fill will auto-wait for element
await page.FillAsync("#username", "John Doe"); await page.Locator("#username").FillAsync("John Doe");
``` ```
### Asynchronous navigation ### Asynchronous navigation
@ -325,7 +325,7 @@ await Promise.all([
// Using waitForNavigation with a callback prevents a race condition // Using waitForNavigation with a callback prevents a race condition
// between clicking and waiting for a navigation. // between clicking and waiting for a navigation.
page.waitForNavigation(() -> { // Waits for the next 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. # prevents a race condition between clicking and waiting for a navigation.
async with page.expect_navigation(): async with page.expect_navigation():
# Triggers a navigation after a timeout # Triggers a navigation after a timeout
await page.click("div.delayed-navigation") await page.locator("div.delayed-navigation").click()
``` ```
```python sync ```python sync
@ -342,7 +342,7 @@ async with page.expect_navigation():
# prevents a race condition between clicking and waiting for a navigation. # prevents a race condition between clicking and waiting for a navigation.
with page.expect_navigation(): with page.expect_navigation():
# Triggers a navigation after a timeout # Triggers a navigation after a timeout
page.click("a") page.locator("a").click()
``` ```
```csharp ```csharp
@ -351,7 +351,7 @@ with page.expect_navigation():
await page.RunAndWaitForNavigationAsync(async () => await page.RunAndWaitForNavigationAsync(async () =>
{ {
// Triggers a navigation after a timeout // 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 // Running action in the callback of waitForNavigation prevents a race
// condition between clicking and waiting for a navigation. // condition between clicking and waiting for a navigation.
page.waitForNavigation(new Page.WaitForNavigationOptions().setUrl("**/login"), () -> { 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. # between clicking and waiting for a navigation.
async with page.expect_navigation(url="**/login"): async with page.expect_navigation(url="**/login"):
# Triggers a navigation with a script redirect # Triggers a navigation with a script redirect
await page.click("a") await page.locator("a").click()
``` ```
```python sync ```python sync
@ -394,7 +394,7 @@ async with page.expect_navigation(url="**/login"):
# between clicking and waiting for a navigation. # between clicking and waiting for a navigation.
with page.expect_navigation(url="**/login"): with page.expect_navigation(url="**/login"):
# Triggers a navigation with a script redirect # Triggers a navigation with a script redirect
page.click("a") page.locator("a").click()
``` ```
```csharp ```csharp
@ -403,8 +403,8 @@ with page.expect_navigation(url="**/login"):
await page.RunAndWaitForNavigationAsync(async () => await page.RunAndWaitForNavigationAsync(async () =>
{ {
// Triggers a navigation with a script redirect. // Triggers a navigation with a script redirect.
await page.ClickAsync("a"); await page.Locator("a").ClickAsync();
}, new PageWaitForNavigationOptions }, new()
{ {
UrlString = "**/login" UrlString = "**/login"
}); });
@ -429,21 +429,21 @@ await popup.waitForLoadState('load');
```java ```java
Page popup = page.waitForPopup(() -> { Page popup = page.waitForPopup(() -> {
page.click("a[target='_blank']"); // Opens popup page.locator("a[target='_blank']").click(); // Opens popup
}); });
popup.waitForLoadState(LoadState.LOAD); popup.waitForLoadState(LoadState.LOAD);
``` ```
```python async ```python async
async with page.expect_popup() as popup_info: 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 popup = await popup_info.value
await popup.wait_for_load_state("load") await popup.wait_for_load_state("load")
``` ```
```python sync ```python sync
with page.expect_popup() as popup_info: 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 = popup_info.value
popup.wait_for_load_state("load") popup.wait_for_load_state("load")
``` ```
@ -451,13 +451,13 @@ popup.wait_for_load_state("load")
```csharp ```csharp
var popup = await page.RunAndWaitForPopupAsync(async () => 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); popup.WaitForLoadStateAsync(LoadState.Load);
``` ```
### API reference ### API reference
- [`method: Page.click`] - [`method: Locator.click`]
- [`method: Page.waitForLoadState`] - [`method: Page.waitForLoadState`]
- [`method: Page.waitForNavigation`] - [`method: Page.waitForNavigation`]
- [`method: Page.waitForFunction`] - [`method: Page.waitForFunction`]

View file

@ -48,7 +48,7 @@ page.goto("https://example.com")
``` ```
```csharp ```csharp
using var context = await Browser.NewContextAsync(new BrowserNewContextOptions using var context = await Browser.NewContextAsync(new()
{ {
HttpCredentials = new HttpCredentials HttpCredentials = new HttpCredentials
{ {
@ -113,7 +113,7 @@ var proxy = new Proxy
Username = "user", Username = "user",
Password = "pwd" Password = "pwd"
}; };
await using var browser = await BrowserType.LaunchAsync(new BrowserTypeLaunchOptions await using var browser = await BrowserType.LaunchAsync(new()
{ {
Proxy = proxy Proxy = proxy
}); });
@ -153,12 +153,12 @@ context = browser.new_context(proxy={"server": "http://myproxy.com:3128"})
```csharp ```csharp
var proxy = new Proxy { Server = "per-context" }; 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. // Browser proxy option is required for Chromium on Windows.
Proxy = proxy 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" }) 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 // Use a glob URL pattern
const [response] = await Promise.all([ const [response] = await Promise.all([
page.waitForResponse('**/api/fetch_data'), page.waitForResponse('**/api/fetch_data'),
page.click('button#update'), page.locator('button#update').click(),
]); ]);
``` ```
```java ```java
// Use a glob URL pattern // Use a glob URL pattern
Response response = page.waitForResponse("**/api/fetch_data", () -> { Response response = page.waitForResponse("**/api/fetch_data", () -> {
page.click("button#update"); page.locator("button#update").click();
}); });
``` ```
```python async ```python async
# Use a glob url pattern # Use a glob url pattern
async with page.expect_response("**/api/fetch_data") as response_info: 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 response = await response_info.value
``` ```
```python sync ```python sync
# Use a glob url pattern # Use a glob url pattern
with page.expect_response("**/api/fetch_data") as response_info: with page.expect_response("**/api/fetch_data") as response_info:
page.click("button#update") page.locator("button#update").click()
response = response_info.value response = response_info.value
``` ```
```csharp ```csharp
// Use a glob URL pattern // Use a glob URL pattern
var waitForResponseTask = page.WaitForResponseAsync("**/api/fetch_data"); var waitForResponseTask = page.WaitForResponseAsync("**/api/fetch_data");
await page.ClickAsync("button#update"); await page.Locator("button#update").ClickAsync();
var response = await waitForResponseTask; var response = await waitForResponseTask;
``` ```
@ -297,61 +297,61 @@ var response = await waitForResponseTask;
// Use a RegExp // Use a RegExp
const [response] = await Promise.all([ const [response] = await Promise.all([
page.waitForResponse(/\.jpeg$/), page.waitForResponse(/\.jpeg$/),
page.click('button#update'), page.locator('button#update').click(),
]); ]);
// Use a predicate taking a Response object // Use a predicate taking a Response object
const [response] = await Promise.all([ const [response] = await Promise.all([
page.waitForResponse(response => response.url().includes(token)), page.waitForResponse(response => response.url().includes(token)),
page.click('button#update'), page.locator('button#update').click(),
]); ]);
``` ```
```java ```java
// Use a RegExp // Use a RegExp
Response response = page.waitForResponse(Pattern.compile("\\.jpeg$"), () -> { Response response = page.waitForResponse(Pattern.compile("\\.jpeg$"), () -> {
page.click("button#update"); page.locator("button#update").click();
}); });
// Use a predicate taking a Response object // Use a predicate taking a Response object
Response response = page.waitForResponse(r -> r.url().contains(token), () -> { Response response = page.waitForResponse(r -> r.url().contains(token), () -> {
page.click("button#update"); page.locator("button#update").click();
}); });
``` ```
```python async ```python async
# Use a regular expression # Use a regular expression
async with page.expect_response(re.compile(r"\.jpeg$")) as response_info: 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 response = await response_info.value
# Use a predicate taking a response object # Use a predicate taking a response object
async with page.expect_response(lambda response: token in response.url) as response_info: 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 response = await response_info.value
``` ```
```python sync ```python sync
# Use a regular expression # Use a regular expression
with page.expect_response(re.compile(r"\.jpeg$")) as response_info: with page.expect_response(re.compile(r"\.jpeg$")) as response_info:
page.click("button#update") page.locator("button#update").click()
response = response_info.value response = response_info.value
# Use a predicate taking a response object # Use a predicate taking a response object
with page.expect_response(lambda response: token in response.url) as response_info: 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 response = response_info.value
``` ```
```csharp ```csharp
// Use a regular expression // Use a regular expression
var waitForResponseTask = page.WaitForResponseAsync(new Regex("\\.jpeg$")); var waitForResponseTask = page.WaitForResponseAsync(new Regex("\\.jpeg$"));
await page.ClickAsync("button#update"); await page.Locator("button#update").ClickAsync();
var response = await waitForResponseTask; var response = await waitForResponseTask;
// Use a predicate taking a Response object // Use a predicate taking a Response object
var waitForResponseTask = page.WaitForResponseAsync(r => r.Url.Contains(token)); var waitForResponseTask = page.WaitForResponseAsync(r => r.Url.Contains(token));
await page.ClickAsync("button#update"); await page.Locator("button#update").ClickAsync();
var response = await waitForResponseTask; var response = await waitForResponseTask;
``` ```
@ -767,7 +767,7 @@ context.close()
``` ```
```csharp ```csharp
var context = await browser.NewContextAsync(new () { var context = await browser.NewContextAsync(new() {
RecordHarPath = "example.har", RecordHarPath = "example.har",
RecordHarUrlFilter = "**/api/**", RecordHarUrlFilter = "**/api/**",
}); });

View file

@ -144,7 +144,7 @@ handle new pages opened by `target="_blank"` links.
// Get page after a specific action (e.g. clicking a link) // Get page after a specific action (e.g. clicking a link)
const [newPage] = await Promise.all([ const [newPage] = await Promise.all([
context.waitForEvent('page'), 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(); await newPage.waitForLoadState();
console.log(await newPage.title()); console.log(await newPage.title());
@ -153,7 +153,7 @@ console.log(await newPage.title());
```java ```java
// Get page after a specific action (e.g. clicking a link) // Get page after a specific action (e.g. clicking a link)
Page newPage = context.waitForPage(() -> { 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(); newPage.waitForLoadState();
System.out.println(newPage.title()); System.out.println(newPage.title());
@ -162,7 +162,7 @@ System.out.println(newPage.title());
```python async ```python async
# Get page after a specific action (e.g. clicking a link) # Get page after a specific action (e.g. clicking a link)
async with context.expect_page() as new_page_info: 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 new_page = await new_page_info.value
await new_page.wait_for_load_state() await new_page.wait_for_load_state()
@ -172,7 +172,7 @@ print(await new_page.title())
```python sync ```python sync
# Get page after a specific action (e.g. clicking a link) # Get page after a specific action (e.g. clicking a link)
with context.expect_page() as new_page_info: 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 = new_page_info.value
new_page.wait_for_load_state() 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) // Get page after a specific action (e.g. clicking a link)
var newPage = await context.RunAndWaitForPageAsync(async () => var newPage = await context.RunAndWaitForPageAsync(async () =>
{ {
await page.ClickAsync("a[target='_blank']"); await page.Locator("a[target='_blank']").ClickAsync();
}); });
await newPage.WaitForLoadStateAsync(); await newPage.WaitForLoadStateAsync();
Console.WriteLine(await newPage.TitleAsync()); Console.WriteLine(await newPage.TitleAsync());
@ -256,7 +256,7 @@ console.log(await popup.title());
```java ```java
// Get popup after a specific action (e.g., click) // Get popup after a specific action (e.g., click)
Page popup = page.waitForPopup(() -> { Page popup = page.waitForPopup(() -> {
page.click("#open"); page.locator("#open").click();
}); });
popup.waitForLoadState(); popup.waitForLoadState();
System.out.println(popup.title()); System.out.println(popup.title());
@ -265,7 +265,7 @@ System.out.println(popup.title());
```python async ```python async
# Get popup after a specific action (e.g., click) # Get popup after a specific action (e.g., click)
async with page.expect_popup() as popup_info: async with page.expect_popup() as popup_info:
await page.click("#open") await page.locator("#open").click()
popup = await popup_info.value popup = await popup_info.value
await popup.wait_for_load_state() await popup.wait_for_load_state()
@ -275,7 +275,7 @@ print(await popup.title())
```python sync ```python sync
# Get popup after a specific action (e.g., click) # Get popup after a specific action (e.g., click)
with page.expect_popup() as popup_info: with page.expect_popup() as popup_info:
page.click("#open") page.locator("#open").click()
popup = popup_info.value popup = popup_info.value
popup.wait_for_load_state() popup.wait_for_load_state()
@ -286,7 +286,7 @@ print(popup.title())
// Get popup after a specific action (e.g., click) // Get popup after a specific action (e.g., click)
var newPage = await page.RunAndWaitForPopupAsync(async () => var newPage = await page.RunAndWaitForPopupAsync(async () =>
{ {
await page.ClickAsync("#open"); await page.Locator("#open").ClickAsync();
}); });
await newPage.WaitForLoadStateAsync(); await newPage.WaitForLoadStateAsync();
Console.WriteLine(await newPage.TitleAsync()); Console.WriteLine(await newPage.TitleAsync());

View file

@ -116,12 +116,12 @@ public class SearchPage
_searchTermInput = page.Locator("[aria-label='Enter your search term']"); _searchTermInput = page.Locator("[aria-label='Enter your search term']");
} }
public async Task Goto() public async Task GotoAsync()
{ {
await _page.GotoAsync("https://bing.com"); await _page.GotoAsync("https://bing.com");
} }
public async Task Search(string text) public async Task SearchAsync(string text)
{ {
await _searchTermInput.FillAsync(text); await _searchTermInput.FillAsync(text);
await _searchTermInput.PressAsync("Enter"); await _searchTermInput.PressAsync("Enter");
@ -181,8 +181,8 @@ using BigEcommerceApp.Tests.Models;
// in the test // in the test
var page = new SearchPage(await browser.NewPageAsync()); var page = new SearchPage(await browser.NewPageAsync());
await page.Goto(); await page.GotoAsync();
await page.Search("search query"); await page.SearchAsync("search query");
``` ```
### API reference ### API reference

View file

@ -44,7 +44,7 @@ pwsh bin\Debug\netX\playwright.ps1 open --save-har=example.har --save-har-glob="
Alternatively, you can record HAR programmatically: Alternatively, you can record HAR programmatically:
```csharp ```csharp
var context = await browser.NewContextAsync(new () var context = await browser.NewContextAsync(new()
{ {
RecordHarPath = harPath, RecordHarPath = harPath,
RecordHarUrlFilterString = "**/api/**", RecordHarUrlFilterString = "**/api/**",
@ -78,7 +78,7 @@ await page.RouteAsync("**/*", async route =>
{ {
var headers = route.Request.Headers; var headers = route.Request.Headers;
headers.Remove("X-Secret"); headers.Remove("X-Secret");
await route.ContinueAsync(new () { Headers = headers }); await route.ContinueAsync(new() { Headers = headers });
}); });
// Abort all images. // Abort all images.
@ -131,7 +131,7 @@ Note that the new methods [`method: Page.routeFromHAR`] and [`method: BrowserCon
```csharp ```csharp
// Click a button with accessible name "log in" // 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). Read more in [our documentation](./selectors#role-selector).
@ -153,7 +153,7 @@ Note that the new methods [`method: Page.routeFromHAR`] and [`method: BrowserCon
```csharp ```csharp
// Click a button with accessible name "log in" // 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). 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: - Locator now supports a `has` option that makes sure it contains another locator inside:
```csharp ```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) 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`] - [`method: Locator.dragTo`]
- Each locator can now be optionally filtered by the text it contains: - Each locator can now be optionally filtered by the text it contains:
```csharp ```csharp
await Page.Locator("li", new () { HasTextString = "My Item" }) await Page.Locator("li", new() { HasTextString = "My Item" })
.Locator("button").click(); .Locator("button").click();
``` ```
Read more in [locator documentation](./api/class-locator#locator-locator-option-has-text) 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 ```csharp
// This will throw if you have more than one button! // 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) #### 📍 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. 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 ```csharp
await page.ClickAsync("_react=SubmitButton[enabled=true]"); await page.Locator("_react=SubmitButton[enabled=true]").ClickAsync();
await page.ClickAsync("_vue=submit-button[enabled=true]"); 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). Learn more in the [react selectors documentation](./selectors#react-selectors) and the [vue selectors documentation](./selectors#vue-selectors).

View file

@ -100,7 +100,7 @@ Note that the new methods [`method: Page.routeFromHAR`] and [`method: BrowserCon
```java ```java
// Click a button with accessible name "log in" // 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). Read more in [our documentation](./selectors#role-selector).
@ -126,7 +126,7 @@ Note that the new methods [`method: Page.routeFromHAR`] and [`method: BrowserCon
```java ```java
// Click a button with accessible name "log in" // 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). Read more in [our documentation](./selectors#role-selector).
@ -237,7 +237,7 @@ public class TestExample {
@Test @Test
void statusBecomesSubmitted() { void statusBecomesSubmitted() {
... ...
page.click("#submit-button"); page.locator("#submit-button").click();
assertThat(page.locator(".status")).hasText("Submitted"); 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. 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 ```java
page.click("_react=SubmitButton[enabled=true]"); page.locator("_react=SubmitButton[enabled=true]").click();
page.click("_vue=submit-button[enabled=true]"); 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). Learn more in the [react selectors documentation](./selectors#react-selectors) and the [vue selectors documentation](./selectors#vue-selectors).

View file

@ -165,7 +165,7 @@ WebServer is now considered "ready" if request to the specified port has any of
```js ```js
// Click a button with accessible name "log in" // 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). 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 ```js
// Click a button with accessible name "log in" // 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). 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. 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 ```js
await page.click('_react=SubmitButton[enabled=true]'); await page.locator('_react=SubmitButton[enabled=true]').click();
await page.click('_vue=submit-button[enabled=true]'); 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). Learn more in the [react selectors documentation](./selectors#react-selectors) and the [vue selectors documentation](./selectors#vue-selectors).

View file

@ -144,7 +144,7 @@ Note that the new methods [`method: Page.routeFromHAR`] and [`method: BrowserCon
```py ```py
# Click a button with accessible name "log in" # 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). 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 ```python async
# Click a button with accessible name "log in" # 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 ```python sync
# Click a button with accessible name "log in" # 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). 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: 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") 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: 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") expect(page.locator(".status")).to_have_text("Submitted")
``` ```
@ -490,7 +490,7 @@ Pass `strict=true` into your action calls to opt in.
```py ```py
# This will throw if you have more than one button! # 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) #### 📍 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. 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 ```py
page.click("_react=SubmitButton[enabled=true]"); page.locator("_react=SubmitButton[enabled=true]").click()
page.click("_vue=submit-button[enabled=true]"); 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). Learn more in the [react selectors documentation](./selectors#react-selectors) and the [vue selectors documentation](./selectors#vue-selectors).

View file

@ -17,6 +17,18 @@ await page.screenshot(path="screenshot.png")
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. Screenshots API accepts many parameters for image format, clip area, quality, etc. Make sure to check them out.
<!-- TOC --> <!-- TOC -->
@ -44,6 +56,14 @@ await page.screenshot(path="screenshot.png", full_page=True)
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 ## 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. 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 ```python async
# Capture into Image # Capture into Image
screenshot_bytes = await page.screenshot() screenshot_bytes = await page.screenshot()
image = Image.open(io.BytesIO(screenshot_bytes)) print(base64.b64encode(screenshot_bytes).decode())
``` ```
```python sync ```python sync
screenshot_bytes = page.screenshot() screenshot_bytes = page.screenshot()
image = Image.open(io.BytesIO(screenshot_bytes)) print(base64.b64encode(screenshot_bytes).decode())
``` ```
```csharp ```csharp
var bytes = await page.ScreenshotAsync(); var bytes = await page.ScreenshotAsync();
Console.WriteLine(Convert.ToBase64String(bytes));
``` ```
@ -95,5 +116,5 @@ page.locator(".header").screenshot(path="screenshot.png")
``` ```
```csharp ```csharp
await page.Locator(".header").ScreenshotAsync(new LocatorScreenshotOptions { Path = "screenshot.png" }); await page.Locator(".header").ScreenshotAsync(new() { Path = "screenshot.png" });
``` ```

View file

@ -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() page.locator("button", has_text="Click me").click()
``` ```
```csharp ```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. 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")) page.locator("article", has=page.locator("button.subscribe"))
``` ```
```csharp ```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. 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 ```csharp
var locator = page.Locator(".row"); var locator = page.Locator(".row");
// ... later on ... // ... 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 ## Selecting elements matching one of the conditions
@ -795,27 +795,27 @@ For example, consider the following DOM structure: `<label for="password">Passwo
```js ```js
// Fill the input by targeting the label. // Fill the input by targeting the label.
await page.fill('text=Password', 'secret'); await page.locator('text=Password').fill('secret');
``` ```
```java ```java
// Fill the input by targeting the label. // Fill the input by targeting the label.
page.fill("text=Password", "secret"); page.locator("text=Password").fill("secret");
``` ```
```python async ```python async
# Fill the input by targeting the label. # Fill the input by targeting the label.
await page.fill('text=Password', 'secret') await page.locator('text=Password').fill('secret')
``` ```
```python sync ```python sync
# Fill the input by targeting the label. # Fill the input by targeting the label.
page.fill('text=Password', 'secret') page.locator('text=Password').fill('secret')
``` ```
```csharp ```csharp
// Fill the input by targeting the label. // Fill the input by targeting the label.
await page.FillAsync("text=Password", "secret"); await page.Locator("text=Password").FillAsync("secret");
``` ```
However, other methods will target the label itself, for example `textContent` will return the text content of the label, not the input field. However, other methods will target the label itself, for example `textContent` will return the text content of the label, not the input field.

View file

@ -226,9 +226,9 @@ module.exports = async config => {
const browser = await chromium.launch(); const browser = await chromium.launch();
const page = await browser.newPage(); const page = await browser.newPage();
await page.goto(baseURL); await page.goto(baseURL);
await page.fill('input[name="user"]', 'user'); await page.locator('input[name="user"]').fill('user');
await page.fill('input[name="password"]', 'password'); await page.locator('input[name="password"]').fill('password');
await page.click('text=Sign in'); await page.locator('text=Sign in').click();
await page.context().storageState({ path: storageState }); await page.context().storageState({ path: storageState });
await browser.close(); await browser.close();
}; };
@ -243,9 +243,9 @@ async function globalSetup(config: FullConfig) {
const browser = await chromium.launch(); const browser = await chromium.launch();
const page = await browser.newPage(); const page = await browser.newPage();
await page.goto(baseURL!); await page.goto(baseURL!);
await page.fill('input[name="user"]', 'user'); await page.locator('input[name="user"]').fill('user');
await page.fill('input[name="password"]', 'password'); await page.locator('input[name="password"]').fill('password');
await page.click('text=Sign in'); await page.locator('text=Sign in').click();
await page.context().storageState({ path: storageState as string }); await page.context().storageState({ path: storageState as string });
await browser.close(); await browser.close();
} }
@ -375,9 +375,9 @@ module.exports = async config => {
try { try {
await context.tracing.start({ screenshots: true, snapshots: true }); await context.tracing.start({ screenshots: true, snapshots: true });
await page.goto(baseURL); await page.goto(baseURL);
await page.fill('input[name="user"]', 'user'); await page.locator('input[name="user"]').fill('user');
await page.fill('input[name="password"]', 'password'); await page.locator('input[name="password"]').fill('password');
await page.click('text=Sign in'); await page.locator('text=Sign in').click();
await context.storageState({ path: storageState }); await context.storageState({ path: storageState });
await context.tracing.stop({ await context.tracing.stop({
path: './test-results/setup-trace.zip', path: './test-results/setup-trace.zip',
@ -405,9 +405,9 @@ async function globalSetup(config: FullConfig) {
try { try {
await context.tracing.start({ screenshots: true, snapshots: true }); await context.tracing.start({ screenshots: true, snapshots: true });
await page.goto(baseURL!); await page.goto(baseURL!);
await page.fill('input[name="user"]', 'user'); await page.locator('input[name="user"]').fill('user');
await page.fill('input[name="password"]', 'password'); await page.locator('input[name="password"]').fill('password');
await page.click('text=Sign in'); await page.locator('text=Sign in').click();
await context.storageState({ path: storageState as string }); await context.storageState({ path: storageState as string });
await context.tracing.stop({ await context.tracing.stop({
path: './test-results/setup-trace.zip', path: './test-results/setup-trace.zip',

View file

@ -193,7 +193,7 @@ test.beforeEach(async ({ page, isMobile }) => {
}); });
test('user profile', async ({ page }) => { test('user profile', async ({ page }) => {
await page.click('text=My Profile'); await page.locator('text=My Profile').click();
// ... // ...
}); });
``` ```
@ -208,7 +208,7 @@ test.beforeEach(async ({ page, isMobile }) => {
}); });
test('user profile', async ({ page }) => { test('user profile', async ({ page }) => {
await page.click('text=My Profile'); await page.locator('text=My Profile').click();
// ... // ...
}); });
``` ```

View file

@ -302,10 +302,10 @@ test.afterAll(async ({ }) => {
test('last created issue should be on the server', async ({ page, request }) => { test('last created issue should be on the server', async ({ page, request }) => {
await page.goto(`https://github.com/${USER}/${REPO}/issues`); await page.goto(`https://github.com/${USER}/${REPO}/issues`);
await page.click('text=New Issue'); await page.locator('text=New Issue').click();
await page.fill('[aria-label="Title"]', 'Bug report 1'); await page.locator('[aria-label="Title"]').fill('Bug report 1');
await page.fill('[aria-label="Comment body"]', 'Bug description'); await page.locator('[aria-label="Comment body"]').fill('Bug description');
await page.click('text=Submit new issue'); await page.locator('text=Submit new issue').click();
const issueId = page.url().substr(page.url().lastIndexOf('/')); const issueId = page.url().substr(page.url().lastIndexOf('/'));
const newIssue = await request.get(`https://api.github.com/repos/${USER}/${REPO}/issues/${issueId}`); const newIssue = await request.get(`https://api.github.com/repos/${USER}/${REPO}/issues/${issueId}`);
@ -347,10 +347,10 @@ test.afterAll(async ({ }) => {
test('last created issue should be on the server', async ({ page, request }) => { test('last created issue should be on the server', async ({ page, request }) => {
await page.goto(`https://github.com/${USER}/${REPO}/issues`); await page.goto(`https://github.com/${USER}/${REPO}/issues`);
await page.click('text=New Issue'); await page.locator('text=New Issue').click();
await page.fill('[aria-label="Title"]', 'Bug report 1'); await page.locator('[aria-label="Title"]').fill('Bug report 1');
await page.fill('[aria-label="Comment body"]', 'Bug description'); await page.locator('[aria-label="Comment body"]').fill('Bug description');
await page.click('text=Submit new issue'); await page.locator('text=Submit new issue').click();
const issueId = page.url().substr(page.url().lastIndexOf('/')); const issueId = page.url().substr(page.url().lastIndexOf('/'));
const newIssue = await request.get(`https://api.github.com/repos/${USER}/${REPO}/issues/${issueId}`); const newIssue = await request.get(`https://api.github.com/repos/${USER}/${REPO}/issues/${issueId}`);

View file

@ -77,9 +77,9 @@ const { test, expect } = require('@playwright/test');
test('basic test', async ({ page }) => { test('basic test', async ({ page }) => {
await page.goto('/signin'); await page.goto('/signin');
await page.fill('#username', 'User'); await page.locator('#username').fill('User');
await page.fill('#password', 'pwd'); await page.locator('#password').fill('pwd');
await page.click('text=Sign in'); await page.locator('text=Sign in').click();
// ... // ...
}); });
``` ```
@ -89,9 +89,9 @@ import { test, expect } from '@playwright/test';
test('basic test', async ({ page }) => { test('basic test', async ({ page }) => {
await page.goto('/signin'); await page.goto('/signin');
await page.fill('#username', 'User'); await page.locator('#username').fill('User');
await page.fill('#password', 'pwd'); await page.locator('#password').fill('pwd');
await page.click('text=Sign in'); await page.locator('text=Sign in').click();
// ... // ...
}); });
``` ```

View file

@ -23,10 +23,10 @@ import { test } from '@playwright/test';
test.beforeEach(async ({ page }) => { test.beforeEach(async ({ page }) => {
// Runs before each test and signs in each page. // Runs before each test and signs in each page.
await page.goto('https://github.com/login'); await page.goto('https://github.com/login');
await page.click('text=Login'); await page.locator('text=Login').click();
await page.fill('input[name="login"]', 'username'); await page.locator('input[name="login"]').fill('username');
await page.fill('input[name="password"]', 'password'); await page.locator('input[name="password"]').fill('password');
await page.click('text=Submit'); await page.locator('text=Submit').click();
}); });
test('first', async ({ page }) => { test('first', async ({ page }) => {
@ -44,10 +44,10 @@ const { test } = require('@playwright/test');
test.beforeEach(async ({ page }) => { test.beforeEach(async ({ page }) => {
// Runs before each test and signs in each page. // Runs before each test and signs in each page.
await page.goto('https://github.com/login'); await page.goto('https://github.com/login');
await page.click('text=Login'); await page.locator('text=Login').click();
await page.fill('input[name="login"]', 'username'); await page.locator('input[name="login"]').fill('username');
await page.fill('input[name="password"]', 'password'); await page.locator('input[name="password"]').fill('password');
await page.click('text=Submit'); await page.locator('text=Submit').click();
}); });
test('first', async ({ page }) => { test('first', async ({ page }) => {
@ -77,9 +77,9 @@ module.exports = async config => {
const browser = await chromium.launch(); const browser = await chromium.launch();
const page = await browser.newPage(); const page = await browser.newPage();
await page.goto('https://github.com/login'); await page.goto('https://github.com/login');
await page.fill('input[name="login"]', 'user'); await page.locator('input[name="login"]').fill('user');
await page.fill('input[name="password"]', 'password'); await page.locator('input[name="password"]').fill('password');
await page.click('text=Sign in'); await page.locator('text=Sign in').click();
// Save signed-in state to 'storageState.json'. // Save signed-in state to 'storageState.json'.
await page.context().storageState({ path: 'storageState.json' }); await page.context().storageState({ path: 'storageState.json' });
await browser.close(); await browser.close();
@ -94,9 +94,9 @@ async function globalSetup(config: FullConfig) {
const browser = await chromium.launch(); const browser = await chromium.launch();
const page = await browser.newPage(); const page = await browser.newPage();
await page.goto('https://github.com/login'); await page.goto('https://github.com/login');
await page.fill('input[name="login"]', 'user'); await page.locator('input[name="login"]').fill('user');
await page.fill('input[name="password"]', 'password'); await page.locator('input[name="password"]').fill('password');
await page.click('text=Sign in'); await page.locator('text=Sign in').click();
// Save signed-in state to 'storageState.json'. // Save signed-in state to 'storageState.json'.
await page.context().storageState({ path: 'storageState.json' }); await page.context().storageState({ path: 'storageState.json' });
await browser.close(); await browser.close();
@ -226,9 +226,9 @@ exports.test = base.extend({
// Make sure we are not using any other storage state. // Make sure we are not using any other storage state.
const page = await browser.newPage({ storageState: undefined }); const page = await browser.newPage({ storageState: undefined });
await page.goto('https://github.com/login'); await page.goto('https://github.com/login');
await page.fill('input[name="login"]', users[testInfo.workerIndex].username); await page.locator('input[name="login"]').fill(users[testInfo.workerIndex].username);
await page.fill('input[name="password"]', users[testInfo.workerIndex].password); await page.locator('input[name="password"]').fill(users[testInfo.workerIndex].password);
await page.click('text=Sign in'); await page.locator('text=Sign in').click();
await page.context().storageState({ path: fileName }); await page.context().storageState({ path: fileName });
await page.close(); await page.close();
} }
@ -265,9 +265,9 @@ export const test = baseTest.extend({
const page = await browser.newPage({ storageState: undefined }); const page = await browser.newPage({ storageState: undefined });
await page.goto('https://github.com/login'); await page.goto('https://github.com/login');
// Create a unique username for each worker. // Create a unique username for each worker.
await page.fill('input[name="login"]', users[testInfo.workerIndex].username); await page.locator('input[name="login"]').fill(users[testInfo.workerIndex].username);
await page.fill('input[name="password"]', users[testInfo.workerIndex].password); await page.locator('input[name="password"]').fill(users[testInfo.workerIndex].password);
await page.click('text=Sign in'); await page.locator('text=Sign in').click();
await page.context().storageState({ path: fileName }); await page.context().storageState({ path: fileName });
await page.close(); await page.close();
} }
@ -558,9 +558,9 @@ test.beforeAll(async ({ browser }) => {
// Create page yourself and sign in. // Create page yourself and sign in.
page = await browser.newPage(); page = await browser.newPage();
await page.goto('https://github.com/login'); await page.goto('https://github.com/login');
await page.fill('input[name="user"]', 'user'); await page.locator('input[name="user"]').fill('user');
await page.fill('input[name="password"]', 'password'); await page.locator('input[name="password"]').fill('password');
await page.click('text=Sign in'); await page.locator('text=Sign in').click();
}); });
test.afterAll(async () => { test.afterAll(async () => {
@ -589,9 +589,9 @@ test.beforeAll(async ({ browser }) => {
// Create page once and sign in. // Create page once and sign in.
page = await browser.newPage(); page = await browser.newPage();
await page.goto('https://github.com/login'); await page.goto('https://github.com/login');
await page.fill('input[name="user"]', 'user'); await page.locator('input[name="user"]').fill('user');
await page.fill('input[name="password"]', 'password'); await page.locator('input[name="password"]').fill('password');
await page.click('text=Sign in'); await page.locator('text=Sign in').click();
}); });
test.afterAll(async () => { test.afterAll(async () => {

View file

@ -144,7 +144,7 @@ test('runs first', async () => {
}); });
test('runs second', async () => { test('runs second', async () => {
await page.click('text=Get Started'); await page.locator('text=Get Started').click();
}); });
``` ```
@ -171,7 +171,7 @@ test('runs first', async () => {
}); });
test('runs second', async () => { test('runs second', async () => {
await page.click('text=Get Started'); await page.locator('text=Get Started').click();
}); });
``` ```

View file

@ -146,7 +146,7 @@ exports.test = base.test.extend({
await page.goto('/chat'); await page.goto('/chat');
// We use "person" parameter as a "name" for the chat room. // We use "person" parameter as a "name" for the chat room.
await page.locator('#name').fill(person); await page.locator('#name').fill(person);
await page.click('text=Enter chat room'); await page.locator('text=Enter chat room').click();
// Each test will get a "page" that already has the person name. // Each test will get a "page" that already has the person name.
await use(page); await use(page);
}, },
@ -171,7 +171,7 @@ export const test = base.test.extend<TestOptions>({
await page.goto('/chat'); await page.goto('/chat');
// We use "person" parameter as a "name" for the chat room. // We use "person" parameter as a "name" for the chat room.
await page.locator('#name').fill(person); await page.locator('#name').fill(person);
await page.click('text=Enter chat room'); await page.locator('text=Enter chat room').click();
// Each test will get a "page" that already has the person name. // Each test will get a "page" that already has the person name.
await use(page); await use(page);
}, },

View file

@ -213,7 +213,7 @@ test('runs first', async () => {
}); });
test('runs second', async () => { test('runs second', async () => {
await page.click('text=Get Started'); await page.locator('text=Get Started').click();
}); });
``` ```
@ -239,6 +239,6 @@ test('runs first', async () => {
}); });
test('runs second', async () => { test('runs second', async () => {
await page.click('text=Get Started'); await page.locator('text=Get Started').click();
}); });
``` ```

View file

@ -63,23 +63,23 @@ public class TestExample {
@Test @Test
void shouldClickButton() { void shouldClickButton() {
page.navigate("data:text/html,<script>var result;</script><button onclick='result=\"Clicked\"'>Go</button>"); page.navigate("data:text/html,<script>var result;</script><button onclick='result=\"Clicked\"'>Go</button>");
page.click("button"); page.locator("button").click();
assertEquals("Clicked", page.evaluate("result")); assertEquals("Clicked", page.evaluate("result"));
} }
@Test @Test
void shouldCheckTheBox() { void shouldCheckTheBox() {
page.setContent("<input id='checkbox' type='checkbox'></input>"); page.setContent("<input id='checkbox' type='checkbox'></input>");
page.check("input"); page.locator("input").check();
assertTrue((Boolean) page.evaluate("() => window['checkbox'].checked")); assertTrue((Boolean) page.evaluate("() => window['checkbox'].checked"));
} }
@Test @Test
void shouldSearchWiki() { void shouldSearchWiki() {
page.navigate("https://www.wikipedia.org/"); page.navigate("https://www.wikipedia.org/");
page.click("input[name=\"search\"]"); page.locator("input[name=\"search\"]").click();
page.fill("input[name=\"search\"]", "playwright"); page.locator("input[name=\"search\"]").fill("playwright");
page.press("input[name=\"search\"]", "Enter"); page.locator("input[name=\"search\"]").press("Enter");
assertEquals("https://en.wikipedia.org/wiki/Playwright", page.url()); assertEquals("https://en.wikipedia.org/wiki/Playwright", page.url());
} }
} }
@ -137,23 +137,23 @@ class Test1 extends TestFixtures {
@Test @Test
void shouldClickButton() { void shouldClickButton() {
page.navigate("data:text/html,<script>var result;</script><button onclick='result=\"Clicked\"'>Go</button>"); page.navigate("data:text/html,<script>var result;</script><button onclick='result=\"Clicked\"'>Go</button>");
page.click("button"); page.locator("button").click();
assertEquals("Clicked", page.evaluate("result")); assertEquals("Clicked", page.evaluate("result"));
} }
@Test @Test
void shouldCheckTheBox() { void shouldCheckTheBox() {
page.setContent("<input id='checkbox' type='checkbox'></input>"); page.setContent("<input id='checkbox' type='checkbox'></input>");
page.check("input"); page.locator("input").check();
assertTrue((Boolean) page.evaluate("() => window['checkbox'].checked")); assertTrue((Boolean) page.evaluate("() => window['checkbox'].checked"));
} }
@Test @Test
void shouldSearchWiki() { void shouldSearchWiki() {
page.navigate("https://www.wikipedia.org/"); page.navigate("https://www.wikipedia.org/");
page.click("input[name=\"search\"]"); page.locator("input[name=\"search\"]").click();
page.fill("input[name=\"search\"]", "playwright"); page.locator("input[name=\"search\"]").fill("playwright");
page.press("input[name=\"search\"]", "Enter"); page.locator("input[name=\"search\"]").press("Enter");
assertEquals("https://en.wikipedia.org/wiki/Playwright", page.url()); assertEquals("https://en.wikipedia.org/wiki/Playwright", page.url());
} }
} }

View file

@ -20,7 +20,7 @@ Use the `page` fixture to write a basic test. See [more examples](#examples).
def test_example_is_working(page): def test_example_is_working(page):
page.goto("https://example.com") page.goto("https://example.com")
assert page.inner_text('h1') == 'Example Domain' assert page.inner_text('h1') == 'Example Domain'
page.click("text=More information") page.locator("text=More information").click()
``` ```
To run your tests, use pytest CLI. To run your tests, use pytest CLI.
@ -255,7 +255,7 @@ class MyTest(unittest.TestCase):
def test_foobar(self): def test_foobar(self):
self.page.goto("https://microsoft.com") self.page.goto("https://microsoft.com")
self.page.click("#foobar") self.page.locator("#foobar").click()
assert self.page.evaluate("1 + 1") == 2 assert self.page.evaluate("1 + 1") == 2
``` ```

View file

@ -117,7 +117,7 @@ await using var browser = playwright.Chromium.LaunchAsync();
await using var context = await browser.NewContextAsync(); await using var context = await browser.NewContextAsync();
// Start tracing before creating / navigating a page. // Start tracing before creating / navigating a page.
await context.Tracing.StartAsync(new TracingStartOptions await context.Tracing.StartAsync(new()
{ {
Screenshots = true, Screenshots = true,
Snapshots = true, Snapshots = true,
@ -128,7 +128,7 @@ var page = context.NewPageAsync();
await page.GotoAsync("https://playwright.dev"); await page.GotoAsync("https://playwright.dev");
// Stop tracing and export it into a zip archive. // Stop tracing and export it into a zip archive.
await context.Tracing.StopAsync(new TracingStopOptions await context.Tracing.StopAsync(new()
{ {
Path = "trace.zip" Path = "trace.zip"
}); });

View file

@ -33,7 +33,7 @@ context.close()
``` ```
```csharp ```csharp
var context = await browser.NewContextAsync(new BrowserNewContextOptions var context = await browser.NewContextAsync(new()
{ {
RecordVideoDir = "videos/" RecordVideoDir = "videos/"
}); });
@ -73,7 +73,7 @@ context = browser.new_context(
``` ```
```csharp ```csharp
var context = await browser.NewContextAsync(new BrowserNewContextOptions var context = await browser.NewContextAsync(new()
{ {
RecordVideoDir = "videos/", RecordVideoDir = "videos/",
RecordVideoSize = new RecordVideoSize() { Width = 640, Height = 480 } RecordVideoSize = new RecordVideoSize() { Width = 640, Height = 480 }

View file

@ -6377,7 +6377,7 @@ export interface BrowserContext {
* <button onclick="onClick()">Click me</button> * <button onclick="onClick()">Click me</button>
* <div></div> * <div></div>
* `); * `);
* await page.click('button'); * await page.locator('button').click();
* })(); * })();
* ``` * ```
* *
@ -6431,7 +6431,7 @@ export interface BrowserContext {
* <button onclick="onClick()">Click me</button> * <button onclick="onClick()">Click me</button>
* <div></div> * <div></div>
* `); * `);
* await page.click('button'); * await page.locator('button').click();
* })(); * })();
* ``` * ```
* *
@ -6487,7 +6487,7 @@ export interface BrowserContext {
* ```js * ```js
* const [newPage] = await Promise.all([ * const [newPage] = await Promise.all([
* context.waitForEvent('page'), * context.waitForEvent('page'),
* page.click('a[target=_blank]'), * page.locator('a[target=_blank]').click(),
* ]); * ]);
* console.log(await newPage.evaluate('location.href')); * console.log(await newPage.evaluate('location.href'));
* ``` * ```
@ -6614,7 +6614,7 @@ export interface BrowserContext {
* ```js * ```js
* const [newPage] = await Promise.all([ * const [newPage] = await Promise.all([
* context.waitForEvent('page'), * context.waitForEvent('page'),
* page.click('a[target=_blank]'), * page.locator('a[target=_blank]').click(),
* ]); * ]);
* console.log(await newPage.evaluate('location.href')); * console.log(await newPage.evaluate('location.href'));
* ``` * ```
@ -6781,7 +6781,7 @@ export interface BrowserContext {
* ```js * ```js
* const [newPage] = await Promise.all([ * const [newPage] = await Promise.all([
* context.waitForEvent('page'), * context.waitForEvent('page'),
* page.click('a[target=_blank]'), * page.locator('a[target=_blank]').click(),
* ]); * ]);
* console.log(await newPage.evaluate('location.href')); * console.log(await newPage.evaluate('location.href'));
* ``` * ```
@ -7003,7 +7003,7 @@ export interface BrowserContext {
* <button onclick="onClick()">Click me</button> * <button onclick="onClick()">Click me</button>
* <div></div> * <div></div>
* `); * `);
* await page.click('button'); * await page.locator('button').click();
* })(); * })();
* ``` * ```
* *
@ -7336,7 +7336,7 @@ export interface BrowserContext {
* ```js * ```js
* const [newPage] = await Promise.all([ * const [newPage] = await Promise.all([
* context.waitForEvent('page'), * context.waitForEvent('page'),
* page.click('a[target=_blank]'), * page.locator('a[target=_blank]').click(),
* ]); * ]);
* console.log(await newPage.evaluate('location.href')); * console.log(await newPage.evaluate('location.href'));
* ``` * ```
@ -11066,7 +11066,7 @@ export namespace errors {
* const context = await browser.newContext(); * const context = await browser.newContext();
* const page = await context.newPage(); * const page = await context.newPage();
* try { * try {
* await page.click("text=Foo", { * await page.locator("text=Foo").click({
* timeout: 100, * timeout: 100,
* }) * })
* } catch (error) { * } catch (error) {
@ -15510,7 +15510,7 @@ export interface Selectors {
* // Use the selector prefixed with its name. * // Use the selector prefixed with its name.
* const button = page.locator('tag=button'); * const button = page.locator('tag=button');
* // Combine it with other selector engines. * // 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. * // Can use it in any methods supporting selectors.
* const buttonCount = await page.locator('tag=button').count(); * const buttonCount = await page.locator('tag=button').count();
* *
@ -15627,7 +15627,7 @@ export interface Tracing {
* await page.goto('https://playwright.dev'); * await page.goto('https://playwright.dev');
* *
* await context.tracing.startChunk(); * 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. * // Everything between startChunk and stopChunk will be recorded in the trace.
* await context.tracing.stopChunk({ path: 'trace1.zip' }); * await context.tracing.stopChunk({ path: 'trace1.zip' });
* *

View file

@ -2991,9 +2991,9 @@ export interface PlaywrightTestArgs {
* *
* test('basic test', async ({ page }) => { * test('basic test', async ({ page }) => {
* await page.goto('/signin'); * await page.goto('/signin');
* await page.fill('#username', 'User'); * await page.locator('#username').fill('User');
* await page.fill('#password', 'pwd'); * await page.locator('#password').fill('pwd');
* await page.click('text=Sign in'); * await page.locator('text=Sign in').click();
* // ... * // ...
* }); * });
* ``` * ```
@ -3168,7 +3168,7 @@ interface APIResponseAssertions {
* *
* test('status becomes submitted', async ({ page }) => { * test('status becomes submitted', async ({ page }) => {
* // ... * // ...
* await page.click('#submit-button'); * await page.locator('#submit-button').click();
* await expect(page.locator('.status')).toHaveText('Submitted'); * await expect(page.locator('.status')).toHaveText('Submitted');
* }); * });
* ``` * ```
@ -3777,7 +3777,7 @@ interface LocatorAssertions {
* *
* test('navigates to login', async ({ page }) => { * test('navigates to login', async ({ page }) => {
* // ... * // ...
* await page.click('#login'); * await page.locator('#login').click();
* await expect(page).toHaveURL(/.*\/login/); * await expect(page).toHaveURL(/.*\/login/);
* }); * });
* ``` * ```