docs: use getBy... in documentation (#17795)

This commit is contained in:
Dmitry Gozman 2022-10-03 17:02:46 -07:00 committed by GitHub
parent f14f69624f
commit b07690f408
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
37 changed files with 580 additions and 624 deletions

View file

@ -74,7 +74,7 @@ For example, you can use [`AxeBuilder.include()`](https://github.com/dequelabs/a
test('navigation menu flyout should not have automatically detectable accessibility violations', async ({ page }) => {
await page.goto('https://your-site.com/');
await page.locator('button[aria-label="Navigation Menu"]').click();
await page.getByRole('button', { name: 'Navigation Menu' }).click();
// It is important to waitFor() the page to be in the desired
// state *before* running analyze(). Otherwise, axe might not

View file

@ -435,7 +435,7 @@ const { webkit } = require('playwright'); // Or 'chromium' or 'firefox'.
<button onclick="onClick()">Click me</button>
<div></div>
`);
await page.locator('button').click();
await page.getByRole('button').click();
})();
```
@ -457,7 +457,7 @@ public class Example {
"</script>\n" +
"<button onclick=\"onClick()\">Click me</button>\n" +
"<div></div>");
page.locator("button").click();
page.getByRole("button").click();
}
}
}
@ -482,7 +482,7 @@ async def run(playwright):
<button onclick="onClick()">Click me</button>
<div></div>
""")
await page.locator("button").click()
await page.get_by_role("button").click()
async def main():
async with async_playwright() as playwright:
@ -508,7 +508,7 @@ def run(playwright):
<button onclick="onClick()">Click me</button>
<div></div>
""")
page.locator("button").click()
page.get_by_role("button").click()
with sync_playwright() as playwright:
run(playwright)
@ -530,7 +530,7 @@ await page.SetContentAsync("<script>\n" +
"</script>\n" +
"<button onclick=\"onClick()\">Click me</button>\n" +
"<div></div>");
await page.Locator("button").ClickAsync();
await page.GetByRole("button").ClickAsync();
```
An example of passing an element handle:
@ -660,7 +660,7 @@ const crypto = require('crypto');
<button onclick="onClick()">Click me</button>
<div></div>
`);
await page.locator('button').click();
await page.getByRole('button').click();
})();
```
@ -696,7 +696,7 @@ public class Example {
"</script>\n" +
"<button onclick=\"onClick()\">Click me</button>\n" +
"<div></div>\n");
page.locator("button").click();
page.getByRole("button").click();
}
}
}
@ -728,7 +728,7 @@ async def run(playwright):
<button onclick="onClick()">Click me</button>
<div></div>
""")
await page.locator("button").click()
await page.get_by_role("button").click()
async def main():
async with async_playwright() as playwright:
@ -761,7 +761,7 @@ def run(playwright):
<button onclick="onClick()">Click me</button>
<div></div>
""")
page.locator("button").click()
page.get_by_role("button").click()
with sync_playwright() as playwright:
run(playwright)
@ -796,7 +796,7 @@ class BrowserContextExamples
"<button onclick=\"onClick()\">Click me</button>\n" +
"<div></div>");
await page.Locator("button").ClickAsync();
await page.GetByRole("button").ClickAsync();
Console.WriteLine(await page.TextContentAsync("div"));
}
}
@ -1300,30 +1300,30 @@ value. Will throw an error if the context closes before the event is fired. Retu
```js
const [page, _] = await Promise.all([
context.waitForEvent('page'),
page.locator('button').click()
page.getByRole('button').click()
]);
```
```java
Page newPage = context.waitForPage(() -> page.locator("button").click());
Page newPage = context.waitForPage(() -> page.getByRole("button").click());
```
```python async
async with context.expect_event("page") as event_info:
await page.locator("button").click()
await page.get_by_role("button").click()
page = await event_info.value
```
```python sync
with context.expect_event("page") as event_info:
page.locator("button").click()
page.get_by_role("button").click()
page = event_info.value
```
```csharp
var page = await context.RunAndWaitForPageAsync(async () =>
{
await page.Locator("button").ClickAsync();
await page.GetByRole("button").ClickAsync();
});
```

View file

@ -15,23 +15,16 @@ const [ download ] = await Promise.all([
// It is important to call waitForEvent before click to set up waiting.
page.waitForEvent('download'),
// Triggers the download.
page.locator('text=Download file').click(),
page.getByText('Download file').click(),
]);
// wait for download to complete
const path = await download.path();
```
```java
// wait for download to start
Download download = page.waitForDownload(() -> page.locator("a").click());
// wait for download to complete
Path path = download.path();
```
```java
// wait for download to start
Download download = page.waitForDownload(() -> {
page.locator("a").click();
page.getByText("Download file").click();
});
// wait for download to complete
Path path = download.path();
@ -39,7 +32,7 @@ Path path = download.path();
```python async
async with page.expect_download() as download_info:
await page.locator("a").click()
await page.get_by_text("Download file").click()
download = await download_info.value
# waits for download to complete
path = await download.path()
@ -47,7 +40,7 @@ path = await download.path()
```python sync
with page.expect_download() as download_info:
page.locator("a").click()
page.get_by_text("Download file").click()
download = download_info.value
# wait for download to complete
path = download.path()
@ -56,7 +49,7 @@ path = download.path()
```csharp
var download = await page.RunAndWaitForDownloadAsync(async () =>
{
await page.Locator("#downloadButton").ClickAsync();
await page.GetByText("Download file").ClickAsync();
});
Console.WriteLine(await download.PathAsync());
```

View file

@ -76,32 +76,32 @@ await handle.ClickAsync();
With the locator, every time the `element` is used, up-to-date DOM element is located in the page using the selector. So in the snippet below, underlying DOM element is going to be located twice.
```js
const locator = page.locator('text=Submit');
const locator = page.getByText('Submit');
// ...
await locator.hover();
await locator.click();
```
```java
Locator locator = page.locator("text=Submit");
Locator locator = page.getByText("Submit");
locator.hover();
locator.click();
```
```python async
locator = page.locator("text=Submit")
locator = page.get_by_text("Submit")
await locator.hover()
await locator.click()
```
```python sync
locator = page.locator("text=Submit")
locator = page.get_by_text("Submit")
locator.hover()
locator.click()
```
```csharp
var locator = page.Locator("text=Submit");
var locator = page.GetByText("Submit");
await locator.HoverAsync();
await locator.ClickAsync();
```

View file

@ -10,26 +10,26 @@ const [fileChooser] = await Promise.all([
// It is important to call waitForEvent before click to set up waiting.
page.waitForEvent('filechooser'),
// Opens the file chooser.
page.locator('text=Upload').click(),
page.getByText('Upload').click(),
]);
await fileChooser.setFiles('myfile.pdf');
```
```java
FileChooser fileChooser = page.waitForFileChooser(() -> page.locator("upload").click());
FileChooser fileChooser = page.waitForFileChooser(() -> page.getByText("Upload").click());
fileChooser.setFiles(Paths.get("myfile.pdf"));
```
```python async
async with page.expect_file_chooser() as fc_info:
await page.locator("upload").click()
await page.get_by_text("Upload").click()
file_chooser = await fc_info.value
await file_chooser.set_files("myfile.pdf")
```
```python sync
with page.expect_file_chooser() as fc_info:
page.locator("upload").click()
page.get_by_text("Upload").click()
file_chooser = fc_info.value
file_chooser.set_files("myfile.pdf")
```
@ -37,7 +37,7 @@ file_chooser.set_files("myfile.pdf")
```csharp
var fileChooser = await page.RunAndWaitForFileChooserAsync(async () =>
{
await page.Locator("upload").ClickAsync();
await page.GetByText("Upload").ClickAsync();
});
await fileChooser.SetFilesAsync("temp.txt");
```

View file

@ -859,27 +859,27 @@ in that iframe. Following snippet locates element with text "Submit" in the ifra
like `<iframe id="my-frame">`:
```js
const locator = frame.frameLocator('#my-iframe').locator('text=Submit');
const locator = frame.frameLocator('#my-iframe').getByText('Submit');
await locator.click();
```
```java
Locator locator = frame.frameLocator("#my-iframe").locator("text=Submit");
Locator locator = frame.frameLocator("#my-iframe").getByText("Submit");
locator.click();
```
```python async
locator = frame.frame_locator("#my-iframe").locator("text=Submit")
locator = frame.frame_locator("#my-iframe").get_by_text("Submit")
await locator.click()
```
```python sync
locator = frame.frame_locator("#my-iframe").locator("text=Submit")
locator = frame.frame_locator("#my-iframe").get_by_text("Submit")
locator.click()
```
```csharp
var locator = frame.FrameLocator("#my-iframe").Locator("text=Submit");
var locator = frame.FrameLocator("#my-iframe").GetByText("Submit");
await locator.ClickAsync();
```

View file

@ -4,7 +4,7 @@
FrameLocator represents a view to the `iframe` on the page. It captures the logic sufficient to retrieve the `iframe` and locate elements in that iframe. FrameLocator can be created with either [`method: Page.frameLocator`] or [`method: Locator.frameLocator`] method.
```js
const locator = page.frameLocator('#my-frame').locator('text=Submit');
const locator = page.frameLocator('#my-frame').getByText('Submit');
await locator.click();
```
@ -34,42 +34,42 @@ Frame locators are strict. This means that all operations on frame locators will
```js
// Throws if there are several frames in DOM:
await page.frameLocator('.result-frame').locator('button').click();
await page.frameLocator('.result-frame').getByRole('button').click();
// Works because we explicitly tell locator to pick the first frame:
await page.frameLocator('.result-frame').first().locator('button').click();
await page.frameLocator('.result-frame').first().getByRole('button').click();
```
```python async
# Throws if there are several frames in DOM:
await page.frame_locator('.result-frame').locator('button').click()
await page.frame_locator('.result-frame').get_by_role('button').click()
# Works because we explicitly tell locator to pick the first frame:
await page.frame_locator('.result-frame').first.locator('button').click()
await page.frame_locator('.result-frame').first.get_by_role('button').click()
```
```python sync
# Throws if there are several frames in DOM:
page.frame_locator('.result-frame').locator('button').click()
page.frame_locator('.result-frame').get_by_role('button').click()
# Works because we explicitly tell locator to pick the first frame:
page.frame_locator('.result-frame').first.locator('button').click()
page.frame_locator('.result-frame').first.get_by_role('button').click()
```
```java
// Throws if there are several frames in DOM:
page.frame_locator(".result-frame").locator("button").click();
page.frame_locator(".result-frame").getByRole("button").click();
// Works because we explicitly tell locator to pick the first frame:
page.frame_locator(".result-frame").first().locator("button").click();
page.frame_locator(".result-frame").first().getByRole("button").click();
```
```csharp
// Throws if there are several frames in DOM:
await page.FrameLocator(".result-frame").Locator("button").ClickAsync();
await page.FrameLocator(".result-frame").GetByRole("button").ClickAsync();
// Works because we explicitly tell locator to pick the first frame:
await page.FrameLocator(".result-frame").First.Locator("button").ClickAsync();
await page.FrameLocator(".result-frame").First.getByRole("button").ClickAsync();
```
**Converting Locator to FrameLocator**

View file

@ -524,7 +524,7 @@ const rowLocator = page.locator('tr');
// ...
await rowLocator
.filter({ hasText: 'text in column 1' })
.filter({ has: page.locator('button', { hasText: 'column 2 button' }) })
.filter({ has: page.getByRole('button', { name: 'column 2 button' }) })
.screenshot();
```
```java
@ -533,7 +533,7 @@ Locator rowLocator = page.locator("tr");
rowLocator
.filter(new Locator.FilterOptions().setHasText("text in column 1"))
.filter(new Locator.FilterOptions().setHas(
page.locator("button", new Page.LocatorOptions().setHasText("column 2 button"))
page.getByRole("button", new Page.GetByRoleOptions().setName("column 2 button"))
))
.screenshot();
```
@ -542,7 +542,7 @@ row_locator = page.locator("tr")
# ...
await row_locator
.filter(has_text="text in column 1")
.filter(has=page.locator("tr", has_text="column 2 button"))
.filter(has=page.get_by_role("button", name="column 2 button"))
.screenshot()
```
```python sync
@ -550,7 +550,7 @@ row_locator = page.locator("tr")
# ...
row_locator
.filter(has_text="text in column 1")
.filter(has=page.locator("tr", has_text="column 2 button"))
.filter(has=page.get_by_role("button", name="column 2 button"))
.screenshot()
```
```csharp
@ -559,7 +559,7 @@ var rowLocator = page.Locator("tr");
await rowLocator
.Filter(new LocatorFilterOptions { HasText = "text in column 1" })
.Filter(new LocatorFilterOptions {
Has = page.Locator("tr", new PageLocatorOptions { HasText = "column 2 button" } )
Has = page.GetByRole("button", new() { Name = "column 2 button" } )
})
.ScreenshotAsync();
```
@ -590,27 +590,27 @@ When working with iframes, you can create a frame locator that will enter the if
in that iframe:
```js
const locator = page.frameLocator('iframe').locator('text=Submit');
const locator = page.frameLocator('iframe').getByText('Submit');
await locator.click();
```
```java
Locator locator = page.frameLocator("iframe").locator("text=Submit");
Locator locator = page.frameLocator("iframe").getByText("Submit");
locator.click();
```
```python async
locator = page.frame_locator("iframe").locator("text=Submit")
locator = page.frame_locator("iframe").get_by_text("Submit")
await locator.click()
```
```python sync
locator = page.frame_locator("iframe").locator("text=Submit")
locator = page.frame_locator("iframe").get_by_text("Submit")
locator.click()
```
```csharp
var locator = page.FrameLocator("iframe").Locator("text=Submit");
var locator = page.FrameLocator("iframe").GetByText("Submit");
await locator.ClickAsync();
```
@ -1128,32 +1128,32 @@ await element.TypeAsync("World", new() { Delay = 100 }); // Types slower, like a
An example of typing into a text field and then submitting the form:
```js
const element = page.locator('input');
await element.type('some text');
const element = page.getByLabelText('Password');
await element.type('my password');
await element.press('Enter');
```
```java
Locator element = page.locator("input");
element.type("some text");
Locator element = page.getByLabelText("Password");
element.type("my password");
element.press("Enter");
```
```python async
element = page.locator("input")
await element.type("some text")
element = page.get_by_label_text("Password")
await element.type("my password")
await element.press("Enter")
```
```python sync
element = page.locator("input")
element.type("some text")
element = page.get_by_label_text("Password")
element.type("my password")
element.press("Enter")
```
```csharp
var element = page.Locator("input");
await element.TypeAsync("some text");
var element = page.GetByLabelText("Password");
await element.TypeAsync("my password");
await element.PressAsync("Enter");
```

View file

@ -8,7 +8,7 @@ import { test, expect } from '@playwright/test';
test('status becomes submitted', async ({ page }) => {
// ...
await page.locator('#submit-button').click();
await page.getByRole('button').click();
await expect(page.locator('.status')).toHaveText('Submitted');
});
```
@ -22,7 +22,7 @@ public class TestLocator {
@Test
void statusBecomesSubmitted() {
...
page.locator("#submit-button").click();
page.getByRole("button").click();
assertThat(page.locator(".status")).hasText("Submitted");
}
}
@ -33,7 +33,7 @@ from playwright.async_api import Page, expect
async def test_status_becomes_submitted(page: Page) -> None:
# ..
await page.locator("#submit-button").click()
await page.get_by_role("button").click()
await expect(page.locator(".status")).to_have_text("Submitted")
```
@ -42,7 +42,7 @@ from playwright.sync_api import Page, expect
def test_status_becomes_submitted(page: Page) -> None:
# ..
page.locator("#submit-button").click()
page.get_by_role("button").click()
expect(page.locator(".status")).to_have_text("Submitted")
```
@ -61,7 +61,7 @@ public class ExampleTests : PageTest
public async Task StatusBecomesSubmitted()
{
// ..
await Page.Locator("#submit-button").ClickAsync();
await Page.GetByRole("button").ClickAsync();
await Expect(Page.Locator(".status")).ToHaveTextAsync("Submitted");
}
}
@ -404,30 +404,30 @@ Expected options currently selected.
Ensures the [Locator] points to a checked input.
```js
const locator = page.locator('.subscribe');
const locator = page.getByLabelText('Subscribe to newsletter');
await expect(locator).toBeChecked();
```
```java
assertThat(page.locator(".subscribe")).isChecked();
assertThat(page.getByLabelText("Subscribe to newsletter")).isChecked();
```
```python async
from playwright.async_api import expect
locator = page.locator(".subscribe")
locator = page.get_by_label_text("Subscribe to newsletter")
await expect(locator).to_be_checked()
```
```python sync
from playwright.sync_api import expect
locator = page.locator(".subscribe")
locator = page.get_by_label_text("Subscribe to newsletter")
expect(locator).to_be_checked()
```
```csharp
var locator = Page.Locator(".subscribe");
var locator = Page.GetByLabelText("Subscribe to newsletter");
await Expect(locator).ToBeCheckedAsync();
```
@ -494,30 +494,30 @@ await Expect(locator).ToBeDisabledAsync();
Ensures the [Locator] points to an editable element.
```js
const locator = page.locator('input');
const locator = page.getByRole('textbox');
await expect(locator).toBeEditable();
```
```java
assertThat(page.locator("input")).isEditable();
assertThat(page.getByRole("textbox")).isEditable();
```
```python async
from playwright.async_api import expect
locator = page.locator(".input")
locator = page.get_by_role("textbox")
await expect(locator).to_be_editable()
```
```python sync
from playwright.sync_api import expect
locator = page.locator(".input")
locator = page.get_by_role("textbox")
expect(locator).to_be_editable()
```
```csharp
var locator = Page.Locator("input");
var locator = Page.GetByRole("textbox");
await Expect(locator).ToBeEditableAsync();
```
@ -623,30 +623,30 @@ await Expect(locator).toBeEnabledAsync();
Ensures the [Locator] points to a focused DOM node.
```js
const locator = page.locator('input');
const locator = page.getByRole('textbox');
await expect(locator).toBeFocused();
```
```java
assertThat(page.locator("input")).isFocused();
assertThat(page.getByRole("textbox")).isFocused();
```
```python async
from playwright.async_api import expect
locator = page.locator('input')
locator = page.get_by_role("textbox")
await expect(locator).to_be_focused()
```
```python sync
from playwright.sync_api import expect
locator = page.locator('input')
locator = page.get_by_role("textbox")
expect(locator).to_be_focused()
```
```csharp
var locator = Page.Locator("input");
var locator = Page.GetByRole("textbox");
await Expect(locator).ToBeFocusedAsync();
```
@ -1105,30 +1105,30 @@ Expected count.
Ensures the [Locator] resolves to an element with the given computed CSS style.
```js
const locator = page.locator('button');
const locator = page.getByRole('button');
await expect(locator).toHaveCSS('display', 'flex');
```
```java
assertThat(page.locator("button")).hasCSS("display", "flex");
assertThat(page.getByRole("button")).hasCSS("display", "flex");
```
```python async
from playwright.async_api import expect
locator = page.locator("button")
locator = page.get_by_role("button")
await expect(locator).to_have_css("display", "flex")
```
```python sync
from playwright.sync_api import expect
locator = page.locator("button")
locator = page.get_by_role("button")
expect(locator).to_have_css("display", "flex")
```
```csharp
var locator = Page.Locator("button");
var locator = Page.GetByRole("button");
await Expect(locator).ToHaveCSSAsync("display", "flex");
```
@ -1157,30 +1157,30 @@ CSS property value.
Ensures the [Locator] points to an element with the given DOM Node ID.
```js
const locator = page.locator('input');
const locator = page.getByRole('textbox');
await expect(locator).toHaveId('lastname');
```
```java
assertThat(page.locator("input")).hasId("lastname");
assertThat(page.getByRole("textbox")).hasId("lastname");
```
```python async
from playwright.async_api import expect
locator = page.locator("input")
locator = page.get_by_role("textbox")
await expect(locator).to_have_id("lastname")
```
```python sync
from playwright.sync_api import expect
locator = page.locator("input")
locator = page.get_by_role("textbox")
expect(locator).to_have_id("lastname")
```
```csharp
var locator = Page.Locator("input");
var locator = Page.GetByRole("textbox");
await Expect(locator).ToHaveIdAsync("lastname");
```
@ -1258,7 +1258,7 @@ This function will wait until two consecutive locator screenshots
yield the same result, and then compare the last screenshot with the expectation.
```js
const locator = page.locator('button');
const locator = page.getByRole('button');
await expect(locator).toHaveScreenshot('image.png');
```
@ -1296,7 +1296,7 @@ This function will wait until two consecutive locator screenshots
yield the same result, and then compare the last screenshot with the expectation.
```js
const locator = page.locator('button');
const locator = page.getByRole('button');
await expect(locator).toHaveScreenshot();
```

View file

@ -2128,27 +2128,27 @@ in that iframe. Following snippet locates element with text "Submit" in the ifra
like `<iframe id="my-frame">`:
```js
const locator = page.frameLocator('#my-iframe').locator('text=Submit');
const locator = page.frameLocator('#my-iframe').getByText('Submit');
await locator.click();
```
```java
Locator locator = page.frameLocator("#my-iframe").locator("text=Submit");
Locator locator = page.frameLocator("#my-iframe").getByText("Submit");
locator.click();
```
```python async
locator = page.frame_locator("#my-iframe").locator("text=Submit")
locator = page.frame_locator("#my-iframe").get_by_text("Submit")
await locator.click()
```
```python sync
locator = page.frame_locator("#my-iframe").locator("text=Submit")
locator = page.frame_locator("#my-iframe").get_by_text("Submit")
locator.click()
```
```csharp
var locator = page.FrameLocator("#my-iframe").Locator("text=Submit");
var locator = page.FrameLocator("#my-iframe").GetByText("Submit");
await locator.ClickAsync();
```
@ -3672,19 +3672,19 @@ const [frame, _] = await Promise.all([
// It is important to call waitForEvent before click to set up waiting.
page.waitForEvent('framenavigated'),
// Triggers the navigation.
page.locator('button').click(),
page.getByRole('button').click(),
]);
```
```python async
async with page.expect_event("framenavigated") as event_info:
await page.click("button")
await page.get_by_role("button")
frame = await event_info.value
```
```python sync
with page.expect_event("framenavigated") as event_info:
page.click("button")
page.get_by_role("button")
frame = event_info.value
```
@ -3865,27 +3865,27 @@ This resolves when the page reaches a required load state, `load` by default. Th
when this method is called. If current document has already reached the required state, resolves immediately.
```js
await page.click('button'); // Click triggers navigation.
await page.getByRole('button').click(); // Click triggers navigation.
await page.waitForLoadState(); // The promise resolves after 'load' event.
```
```java
page.click("button"); // Click triggers navigation.
page.getByRole("button").click(); // Click triggers navigation.
page.waitForLoadState(); // The promise resolves after "load" event.
```
```python async
await page.click("button") # click triggers navigation.
await page.get_by_role("button").click() # click triggers navigation.
await page.wait_for_load_state() # the promise resolves after "load" event.
```
```python sync
page.click("button") # click triggers navigation.
page.get_by_role("button").click() # click triggers navigation.
page.wait_for_load_state() # the promise resolves after "load" event.
```
```csharp
await page.ClickAsync("button"); // Click triggers navigation.
await page.GetByRole("button").ClickAsync(); // Click triggers navigation.
await page.WaitForLoadStateAsync(); // The promise resolves after 'load' event.
```
@ -3894,7 +3894,7 @@ const [popup] = await Promise.all([
// It is important to call waitForEvent before click to set up waiting.
page.waitForEvent('popup'),
// Click triggers a popup.
page.locator('button').click(),
page.getByRole('button').click(),
])
await popup.waitForLoadState('domcontentloaded'); // The promise resolves after 'domcontentloaded' event.
console.log(await popup.title()); // Popup is ready to use.
@ -3902,7 +3902,7 @@ console.log(await popup.title()); // Popup is ready to use.
```java
Page popup = page.waitForPopup(() -> {
page.click("button"); // Click triggers a popup.
page.getByRole("button").click(); // Click triggers a popup.
});
popup.waitForLoadState(LoadState.DOMCONTENTLOADED);
System.out.println(popup.title()); // Popup is ready to use.
@ -3910,7 +3910,7 @@ System.out.println(popup.title()); // Popup is ready to use.
```python async
async with page.expect_popup() as page_info:
await page.click("button") # click triggers a popup.
await page.get_by_role("button").click() # click triggers a popup.
popup = await page_info.value
# Following resolves after "domcontentloaded" event.
await popup.wait_for_load_state("domcontentloaded")
@ -3919,7 +3919,7 @@ print(await popup.title()) # popup is ready to use.
```python sync
with page.expect_popup() as page_info:
page.click("button") # click triggers a popup.
page.get_by_role("button").click() # click triggers a popup.
popup = page_info.value
# Following resolves after "domcontentloaded" event.
popup.wait_for_load_state("domcontentloaded")
@ -3929,7 +3929,7 @@ print(popup.title()) # popup is ready to use.
```csharp
var popup = await page.RunAndWaitForPopupAsync(async () =>
{
await page.ClickAsync("button"); // click triggers the popup/
await page.GetByRole("button").ClickAsync(); // click triggers the popup/
});
await popup.WaitForLoadStateAsync(LoadState.DOMContentLoaded);
Console.WriteLine(await popup.TitleAsync()); // popup is ready to use.

View file

@ -8,7 +8,7 @@ import { test, expect } from '@playwright/test';
test('navigates to login', async ({ page }) => {
// ...
await page.locator('#login').click();
await page.getByText('Sign in').click();
await expect(page).toHaveURL(/.*\/login/);
});
```
@ -22,7 +22,7 @@ public class TestPage {
@Test
void navigatesToLoginPage() {
...
page.locator("#login").click();
page.getByText("Sign in").click();
assertThat(page).hasURL(Pattern.compile(".*/login"));
}
}
@ -34,7 +34,7 @@ from playwright.async_api import Page, expect
async def test_navigates_to_login_page(page: Page) -> None:
# ..
await page.locator("#login").click()
await page.get_by_text("Sign in").click()
await expect(page).to_have_url(re.compile(r".*/login"))
```
@ -44,7 +44,7 @@ from playwright.sync_api import Page, expect
def test_navigates_to_login_page(page: Page) -> None:
# ..
page.locator("#login").click()
page.get_by_text("Sign in").click()
expect(page).to_have_url(re.compile(r".*/login"))
```
@ -63,7 +63,7 @@ public class ExampleTests : PageTest
public async Task NavigatetoLoginPage()
{
// ..
await Page.Locator("#login").ClickAsync();
await Page.GetByText("Sing in").ClickAsync();
await Expect(Page.Locator("div#foobar")).ToHaveURL(new Regex(".*/login"));
}
}

View file

@ -167,7 +167,7 @@ const page = await context.newPage();
await page.goto('https://playwright.dev');
await context.tracing.startChunk();
await page.locator('text=Get Started').click();
await page.getByText('Get Started').click();
// Everything between startChunk and stopChunk will be recorded in the trace.
await context.tracing.stopChunk({ path: 'trace1.zip' });
@ -185,7 +185,7 @@ Page page = context.newPage();
page.navigate("https://playwright.dev");
context.tracing().startChunk();
page.locator("text=Get Started").click();
page.getByText("Get Started").click();
// Everything between startChunk and stopChunk will be recorded in the trace.
context.tracing().stopChunk(new Tracing.StopChunkOptions()
.setPath(Paths.get("trace1.zip")));
@ -203,7 +203,7 @@ page = await context.new_page()
await page.goto("https://playwright.dev")
await context.tracing.start_chunk()
await page.locator("text=Get Started").click()
await page.get_by_text("Get Started").click()
# Everything between start_chunk and stop_chunk will be recorded in the trace.
await context.tracing.stop_chunk(path = "trace1.zip")
@ -219,7 +219,7 @@ page = context.new_page()
page.goto("https://playwright.dev")
context.tracing.start_chunk()
page.locator("text=Get Started").click()
page.get_by_text("Get Started").click()
# Everything between start_chunk and stop_chunk will be recorded in the trace.
context.tracing.stop_chunk(path = "trace1.zip")
@ -241,7 +241,7 @@ var page = context.NewPageAsync();
await page.GotoAsync("https://playwright.dev");
await context.Tracing.StartChunkAsync();
await page.ClickAsync("text=Get Started");
await page.GetByText("Get Started").ClickAsync();
// Everything between StartChunkAsync and StopChunkAsync will be recorded in the trace.
await context.Tracing.StopChunkAsync(new()
{

View file

@ -22,10 +22,10 @@ import { test } from '@playwright/test';
test.beforeEach(async ({ page }) => {
// Runs before each test and signs in each page.
await page.goto('https://github.com/login');
await page.locator('text=Login').click();
await page.locator('input[name="login"]').fill('username');
await page.locator('input[name="password"]').fill('password');
await page.locator('text=Submit').click();
await page.getByText('Login').click();
await page.getByLabelText('User Name').fill('username');
await page.getByLabelText('Password').fill('password');
await page.getByText('Submit').click();
});
test('first', async ({ page }) => {
@ -43,10 +43,10 @@ const { test } = require('@playwright/test');
test.beforeEach(async ({ page }) => {
// Runs before each test and signs in each page.
await page.goto('https://github.com/login');
await page.locator('text=Login').click();
await page.locator('input[name="login"]').fill('username');
await page.locator('input[name="password"]').fill('password');
await page.locator('text=Submit').click();
await page.getByText('Login').click();
await page.getByLabelText('User name').fill('username');
await page.getByLabelText('Password').fill('password');
await page.getByText('Submit').click();
});
test('first', async ({ page }) => {
@ -63,10 +63,10 @@ const page = await context.newPage();
await page.goto('https://github.com/login');
// Interact with login form
await page.locator('text=Login').click();
await page.locator('input[name="login"]').fill(USERNAME);
await page.locator('input[name="password"]').fill(PASSWORD);
await page.locator('text=Submit').click();
await page.getByText('Login').click();
await page.getByLabelText('User Name').fill(USERNAME);
await page.getByLabelText('Password').fill(PASSWORD);
await page.getByText('Submit').click();
// Continue with the test
```
@ -74,9 +74,9 @@ await page.locator('text=Submit').click();
Page page = context.newPage();
page.navigate("https://github.com/login");
// Interact with login form
page.locator("text=Login").click();
page.locator("input[name='login']").fill(USERNAME);
page.locator("input[name='password']").fill(PASSWORD);
page.getByText("Login").click();
page.getByLabelText("User Name").fill(USERNAME);
page.getByLabelText("Password").fill(PASSWORD);
page.locator("text=Submit").click();
// Continue with the test
```
@ -86,10 +86,10 @@ page = await context.new_page()
await page.goto('https://github.com/login')
# Interact with login form
await page.locator('text=Login').click()
await page.locator('input[name="login"]').fill(USERNAME)
await page.locator('input[name="password"]').fill(PASSWORD)
await page.locator('text=Submit').click()
await page.get_by_text("Login").click()
await page.get_by_label_text("User Name").fill(USERNAME)
await page.get_by_label_text("Password").fill(PASSWORD)
await page.get_by_text('Submit').click()
# Continue with the test
```
@ -98,10 +98,10 @@ page = context.new_page()
page.goto('https://github.com/login')
# Interact with login form
page.locator('text=Login').click()
page.locator('input[name="login"]').fill(USERNAME)
page.locator('input[name="password"]').fill(PASSWORD)
page.locator('text=Submit').click()
page.get_by_text("Login").click()
page.get_by_label_text("User Name").fill(USERNAME)
page.get_by_label_text("Password").fill(PASSWORD)
page.get_by_text('Submit').click()
# Continue with the test
```
@ -109,10 +109,10 @@ page.locator('text=Submit').click()
var page = await context.NewPageAsync();
await page.GotoAsync("https://github.com/login");
// Interact with login form
await page.Locator("text=Login").ClickAsync();
await page.Locator("input[name='login']").FillAsync(USERNAME);
await page.Locator("input[name='password']").FillAsync(PASSWORD);
await page.Locator("text=Submit").ClickAsync();
await page.GetByText("Login").ClickAsync();
await page.GetByLabelText("User Name").FillAsync(USERNAME);
await page.GetByLabelText("Password").FillAsync(PASSWORD);
await page.GetByText("Submit").ClickAsync();
// Continue with the test
```
@ -189,9 +189,9 @@ module.exports = async config => {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://github.com/login');
await page.locator('input[name="login"]').fill('user');
await page.locator('input[name="password"]').fill('password');
await page.locator('text=Sign in').click();
await page.getByLabelText('User Name').fill('user');
await page.getByLabelText('Password').fill('password');
await page.getByText('Sign in').click();
// Save signed-in state to 'storageState.json'.
await page.context().storageState({ path: 'storageState.json' });
await browser.close();
@ -206,9 +206,9 @@ async function globalSetup(config: FullConfig) {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://github.com/login');
await page.locator('input[name="login"]').fill('user');
await page.locator('input[name="password"]').fill('password');
await page.locator('text=Sign in').click();
await page.getByLabelText('User Name').fill('user');
await page.getByLabelText('Password').fill('password');
await page.getByText('Sign in').click();
// Save signed-in state to 'storageState.json'.
await page.context().storageState({ path: 'storageState.json' });
await browser.close();
@ -339,9 +339,9 @@ exports.test = base.extend({
// Make sure we are not using any other storage state.
const page = await browser.newPage({ storageState: undefined });
await page.goto('https://github.com/login');
await page.locator('input[name="login"]').fill(users[testInfo.workerIndex].username);
await page.locator('input[name="password"]').fill(users[testInfo.workerIndex].password);
await page.locator('text=Sign in').click();
await page.getByLabelText('User Name').fill(users[testInfo.workerIndex].username);
await page.getByLabelText('Password').fill(users[testInfo.workerIndex].password);
await page.getByText('Sign in').click();
await page.context().storageState({ path: fileName });
await page.close();
}
@ -378,9 +378,9 @@ export const test = baseTest.extend({
const page = await browser.newPage({ storageState: undefined });
await page.goto('https://github.com/login');
// Create a unique username for each worker.
await page.locator('input[name="login"]').fill(users[testInfo.workerIndex].username);
await page.locator('input[name="password"]').fill(users[testInfo.workerIndex].password);
await page.locator('text=Sign in').click();
await page.getByLabelText('User Name').fill(users[testInfo.workerIndex].username);
await page.getByLabelText('Password').fill(users[testInfo.workerIndex].password);
await page.getByText('Sign in').click();
await page.context().storageState({ path: fileName });
await page.close();
}
@ -675,9 +675,9 @@ test.beforeAll(async ({ browser }) => {
// Create page yourself and sign in.
page = await browser.newPage();
await page.goto('https://github.com/login');
await page.locator('input[name="user"]').fill('user');
await page.locator('input[name="password"]').fill('password');
await page.locator('text=Sign in').click();
await page.getByLabelText('User Name').fill('user');
await page.getByLabelText('Password').fill('password');
await page.getByText('Sign in').click();
});
test.afterAll(async () => {
@ -706,9 +706,9 @@ test.beforeAll(async ({ browser }) => {
// Create page once and sign in.
page = await browser.newPage();
await page.goto('https://github.com/login');
await page.locator('input[name="user"]').fill('user');
await page.locator('input[name="password"]').fill('password');
await page.locator('text=Sign in').click();
await page.getByLabelText('User Name').fill('user');
await page.getByLabelText('Password').fill('password');
await page.getByText('Sign in').click();
});
test.afterAll(async () => {
@ -909,7 +909,7 @@ class Program
The following code snippet retrieves state from an authenticated context and creates a new context with that state.
```js
```js
// Save storage state into the file.
await context.storageState({ path: 'state.json' });

View file

@ -11,27 +11,27 @@ By default, dialogs are auto-dismissed by Playwright, so you don't have to handl
```js
page.on('dialog', dialog => dialog.accept());
await page.locator('button').click();
await page.getByRole('button').click();
```
```java
page.onDialog(dialog -> dialog.accept());
page.locator("button").click();
page.getByRole("button").click();
```
```python async
page.on("dialog", lambda dialog: dialog.accept())
await page.locator("button".click())
await page.get_by_role("button".click())
```
```python sync
page.on("dialog", lambda dialog: dialog.accept())
page.locator("button").click()
page.get_by_role("button").click()
```
```csharp
page.Dialog += (_, dialog) => dialog.AcceptAsync();
await page.Locator("button").ClickAsync();
await page.GetByRole("button").ClickAsync();
```
:::note
@ -46,27 +46,27 @@ WRONG!
```js
page.on('dialog', dialog => console.log(dialog.message()));
await page.locator('button').click(); // Will hang here
await page.getByRole('button').click(); // Will hang here
```
```java
page.onDialog(dialog -> System.out.println(dialog.message()));
page.locator("button").click(); // Will hang here
page.getByRole("button").click(); // Will hang here
```
```python async
page.on("dialog", lambda dialog: print(dialog.message))
await page.locator("button").click() # Will hang here
await page.get_by_role("button").click() # Will hang here
```
```python sync
page.on("dialog", lambda dialog: print(dialog.message))
page.locator("button").click() # Will hang here
page.get_by_role("button").click() # Will hang here
```
```csharp
page.Dialog += (_, dialog) => Console.WriteLine(dialog.Message);
await page.Locator("button").ClickAsync(); // Will hang here
await page.GetByRole("button").ClickAsync(); // Will hang here
```
:::note

View file

@ -11,32 +11,32 @@ inside the frame.
```js
// Locate element inside frame
const username = await page.frameLocator('.frame-class').locator('#username-input');
const username = await page.frameLocator('.frame-class').getByLabelText('User Name');
await username.fill('John');
```
```java
// Locate element inside frame
Locator username = page.frameLocator(".frame-class").locator("#username-input");
Locator username = page.frameLocator(".frame-class").getByLabelText("User Name");
username.fill("John");
```
```python async
# Locate element inside frame
username = await page.frame_locator('.frame-class').locator('#username-input')
username = await page.frame_locator('.frame-class').get_by_label_text('User Name')
await username.fill('John')
```
```python sync
# Locate element inside frame
# Get frame using any other selector
username = page.frame_locator('.frame-class').locator('#username-input')
username = page.frame_locator('.frame-class').get_by_label_text('User Name')
username.fill('John')
```
```csharp
// Locate element inside frame
var username = await page.FrameLocator(".frame-class").Locator("#username-input");
var username = await page.FrameLocator(".frame-class").GetByLabelText("User Name");
await username.FillAsync("John");
```

View file

@ -7,165 +7,135 @@ Playwright can interact with HTML Input elements such as text inputs, checkboxes
## Text input
Using [`method: Locator.fill`] is the easiest way to fill out the form fields. It focuses the element and triggers an `input` event with the entered text. It works for `<input>`, `<textarea>`, `[contenteditable]` and `<label>` associated with an input or textarea.
Using [`method: Locator.fill`] is the easiest way to fill out the form fields. It focuses the element and triggers an `input` event with the entered text. It works for `<input>`, `<textarea>` and `[contenteditable]` elements.
```js
// Text input
await page.locator('#name').fill('Peter');
await page.getByRole('textbox').fill('Peter');
// Date input
await page.locator('#date').fill('2020-02-02');
await page.getByLabelText('Birth date').fill('2020-02-02');
// Time input
await page.locator('#time').fill('13:15');
await page.getByLabelText('Appointment time').fill('13:15');
// Local datetime input
await page.locator('#local').fill('2020-03-02T05:15');
// Input through label
await page.locator('text=First Name').fill('Peter');
await page.getByLabelText('Local time').fill('2020-03-02T05:15');
```
```java
// Text input
page.locator("#name").fill("Peter");
page.getByRole("textbox").fill("Peter");
// Date input
page.locator("#date").fill("2020-02-02");
page.getByLabelText("Birth date").fill("2020-02-02");
// Time input
page.locator("#time").fill("13-15");
page.getByLabelText("Appointment time").fill("13-15");
// Local datetime input
page.locator("#local").fill("2020-03-02T05:15");
// Input through label
page.locator("text=First Name").fill("Peter");
page.getByLabelText("Local time").fill("2020-03-02T05:15");
```
```python async
# Text input
await page.locator('#name').fill('Peter')
await page.get_by_role("textbox").fill("Peter")
# Date input
await page.locator('#date').fill('2020-02-02')
await page.get_by_label_text("Birth date").fill("2020-02-02")
# Time input
await page.locator('#time').fill('13:15')
await page.get_by_label_text("Appointment time").fill("13:15")
# Local datetime input
await page.locator('#local').fill('2020-03-02T05:15')
# Input through label
await page.locator('text=First Name').fill('Peter')
await page.get_by_label_text("Local time").fill("2020-03-02T05:15")
```
```python sync
# Text input
page.locator('#name').fill('Peter')
page.get_by_role("textbox").fill("Peter")
# Date input
page.locator('#date').fill('2020-02-02')
page.get_by_label_text("Birth date").fill("2020-02-02")
# Time input
page.locator('#time').fill('13:15')
page.get_by_label_text("Appointment time").fill("13:15")
# Local datetime input
page.locator('#local').fill('2020-03-02T05:15')
# Input through label
page.locator('text=First Name').fill('Peter')
page.get_by_label_text("Local time").fill("2020-03-02T05:15")
```
```csharp
// Text input
await page.Locator("#name").FillAsync("Peter");
await page.GetByRole("textbox").FillAsync("Peter");
// Date input
await page.Locator("#date").FillAsync("2020-02-02");
await page.GetByLabelText("Birth date").FillAsync("2020-02-02");
// Time input
await page.Locator("#time").FillAsync("13-15");
await page.GetByLabelText("Appointment time").FillAsync("13-15");
// Local datetime input
await page.Locator("#local").FillAsync("2020-03-02T05:15");
// Input through label
await page.Locator("text=First Name").FillAsync("Peter");
await page.GetByLabelText("Local time").FillAsync("2020-03-02T05:15");
```
## Checkboxes and radio buttons
Using [`method: Locator.setChecked`] is the easiest way to check and uncheck a checkbox or a radio button. This method can be used with `input[type=checkbox]`, `input[type=radio]`, `[role=checkbox]` or `label` associated with checkbox or radio button.
Using [`method: Locator.setChecked`] is the easiest way to check and uncheck a checkbox or a radio button. This method can be used with `input[type=checkbox]`, `input[type=radio]` and `[role=checkbox]` elements.
```js
// Check the checkbox
await page.locator('#agree').check();
await page.getByLabelText('I agree to the terms above').check();
// Assert the checked state
expect(await page.locator('#agree').isChecked()).toBeTruthy()
// Uncheck by input <label>.
await page.locator('#subscribe-label').uncheck();
expect(await page.getByLabelText('Subscribe to newsletter').isChecked()).toBeTruthy()
// Select the radio button
await page.locator('text=XL').check();
await page.getByLabelText('XL').check();
```
```java
// Check the checkbox
page.locator("#agree").check();
page.getByLabelText("I agree to the terms above").check();
// Assert the checked state
assertTrue(page.locator("#agree").isChecked());
// Uncheck by input <label>.
page.locator("#subscribe-label").uncheck();
assertTrue(page.getByLabelText("Subscribe to newsletter").isChecked());
// Select the radio button
page.locator("text=XL").check();
page.getByLabelText("XL").check();
```
```python async
# Check the checkbox
await page.locator('#agree').check()
await page.get_by_label_text('I agree to the terms above').check()
# Assert the checked state
assert await page.locator('#agree').is_checked() is True
# Uncheck by input <label>.
await page.locator('#subscribe-label').uncheck()
assert await page.get_by_label_text('Subscribe to newsletter').is_checked() is True
# Select the radio button
await page.locator('text=XL').check()
await page.get_by_label_text('XL').check()
```
```python sync
# Check the checkbox
page.locator('#agree').check()
page.get_by_label_text('I agree to the terms above').check()
# Assert the checked state
assert page.locator('#agree').is_checked() is True
# Uncheck by input <label>.
page.locator('#subscribe-label').uncheck()
assert page.get_by_label_text('Subscribe to newsletter').is_checked() is True
# Select the radio button
page.locator('text=XL').check()
page.get_by_label_text('XL').check()
```
```csharp
// Check the checkbox
await page.Locator("#agree").CheckAsync();
await page.GetByLabelText("I agree to the terms above").CheckAsync();
// Assert the checked state
Assert.True(await page.Locator("#agree").IsCheckedAsync());
// Uncheck by input <label>.
await page.Locator("#subscribe-label").UncheckAsync();
Assert.True(await page.GetByLabelText("Subscribe to newsletter").IsCheckedAsync());
// Select the radio button
await page.Locator("text=XL").CheckAsync();
await page.GetByLabelText("XL").CheckAsync();
```
## Select options
@ -175,57 +145,57 @@ You can specify option `value`, or `label` to select. Multiple options can be se
```js
// Single selection matching the value
await page.locator('select#colors').selectOption('blue');
await page.getByLabelText('Choose a color').selectOption('blue');
// Single selection matching the label
await page.locator('select#colors').selectOption({ label: 'Blue' });
await page.getByLabelText('Choose a color').selectOption({ label: 'Blue' });
// Multiple selected items
await page.locator('select#colors').selectOption(['red', 'green', 'blue']);
await page.getByLabelText('Choose multiple colors').selectOption(['red', 'green', 'blue']);
```
```java
// Single selection matching the value
page.locator("select#colors").selectOption("blue");
page.getByLabelText("Choose a color").selectOption("blue");
// Single selection matching the label
page.locator("select#colors").selectOption(new SelectOption().setLabel("Blue"));
page.getByLabelText("Choose a color").selectOption(new SelectOption().setLabel("Blue"));
// Multiple selected items
page.locator("select#colors").selectOption(new String[] {"red", "green", "blue"});
page.getByLabelText("Choose multiple colors").selectOption(new String[] {"red", "green", "blue"});
```
```python async
# Single selection matching the value
await page.locator('select#colors').select_option('blue')
await page.get_by_label_text('Choose a color').select_option('blue')
# Single selection matching the label
await page.locator('select#colors').select_option(label='Blue')
await page.get_by_label_text('Choose a color').select_option(label='Blue')
# Multiple selected items
await page.locator('select#colors').select_option(['red', 'green', 'blue'])
await page.get_by_label_text('Choose multiple colors').select_option(['red', 'green', 'blue'])
```
```python sync
# Single selection matching the value
page.locator('select#colors').select_option('blue')
page.get_by_label_text('Choose a color').select_option('blue')
# Single selection matching the label
page.locator('select#colors').select_option(label='Blue')
page.get_by_label_text('Choose a color').select_option(label='Blue')
# Multiple selected items
page.locator('select#colors').select_option(['red', 'green', 'blue'])
page.get_by_label_text('Choose multiple colors').select_option(['red', 'green', 'blue'])
```
```csharp
// Single selection matching the value
await page.Locator("select#colors").SelectOptionAsync("blue");
await page.GetByLabelText("Choose a color").SelectOptionAsync("blue");
// Single selection matching the label
await page.Locator("select#colors").SelectOptionAsync(new SelectOptionValue { Label = "blue" }));
await page.GetByLabelText("Choose a color").SelectOptionAsync(new SelectOptionValue { Label = "blue" }));
// Multiple selected items
await page.Locator("select#colors").SelectOptionAsync(new[] { "blue", "green", "red" });
await page.GetByLabelText("Choose multiple colors").SelectOptionAsync(new[] { "blue", "green", "red" });
```
## Mouse click
@ -234,102 +204,102 @@ Performs a simple human click.
```js
// Generic click
await page.locator('button#submit').click();
await page.getByRole('button').click();
// Double click
await page.locator('#item').dblclick();
await page.getByText('Item').dblclick();
// Right click
await page.locator('#item').click({ button: 'right' });
await page.getByText('Item').click({ button: 'right' });
// Shift + click
await page.locator('#item').click({ modifiers: ['Shift'] });
await page.getByText('Item').click({ modifiers: ['Shift'] });
// Hover over element
await page.locator('#item').hover();
await page.getByText('Item').hover();
// Click the top left corner
await page.locator('#item').click({ position: { x: 0, y: 0} });
await page.getByText('Item').click({ position: { x: 0, y: 0} });
```
```java
// Generic click
page.locator("button#submit").click();
page.getByRole("button").click();
// Double click
page.locator("#item").dblclick();
page.getByText("Item").dblclick();
// Right click
page.locator("#item").click(new Locator.ClickOptions().setButton(MouseButton.RIGHT));
page.getByText("Item").click(new Locator.ClickOptions().setButton(MouseButton.RIGHT));
// Shift + click
page.locator("#item").click(new Locator.ClickOptions().setModifiers(Arrays.asList(KeyboardModifier.SHIFT)));
page.getByText("Item").click(new Locator.ClickOptions().setModifiers(Arrays.asList(KeyboardModifier.SHIFT)));
// Hover over element
page.locator("#item").hover();
page.getByText("Item").hover();
// Click the top left corner
page.locator("#item").click(new Locator.ClickOptions().setPosition(0, 0));
page.getByText("Item").click(new Locator.ClickOptions().setPosition(0, 0));
```
```python async
# Generic click
await page.locator('button#submit').click()
await page.get_by_role("button").click()
# Double click
await page.locator('#item').dblclick()
await page.get_by_text("Item").dblclick()
# Right click
await page.locator('#item').click(button='right')
await page.get_by_text("Item").click(button="right")
# Shift + click
await page.locator('#item').click(modifiers=['Shift'])
await page.get_by_text("Item").click(modifiers=["Shift"])
# Hover over element
await page.locator('#item').hover()
await page.get_by_text("Item").hover()
# Click the top left corner
await page.locator('#item').click(position={ 'x': 0, 'y': 0})
await page.get_by_text("Item").click(position={ "x": 0, "y": 0})
```
```python sync
# Generic click
page.locator('button#submit').click()
page.get_by_role("button").click()
# Double click
page.locator('#item').dblclick()
page.get_by_text("Item").dblclick()
# Right click
page.locator('#item').click(button='right')
page.get_by_text("Item").click(button="right")
# Shift + click
page.locator('#item').click(modifiers=['Shift'])
page.get_by_text("Item").click(modifiers=["Shift"])
# Hover over element
page.locator('#item').hover()
page.get_by_text("Item").hover()
# Click the top left corner
page.locator('#item').click(position={ 'x': 0, 'y': 0})
page.get_by_text("Item").click(position={ "x": 0, "y": 0})
```
```csharp
// Generic click
await page.Locator("button#submit").ClickAsync();
await page.GetByRole("button").ClickAsync();
// Double click
await page.Locator("#item").DblClickAsync();
await page.GetByText("Item").DblClickAsync();
// Right click
await page.Locator("#item").ClickAsync(new() { Button = MouseButton.Right });
await page.GetByText("Item").ClickAsync(new() { Button = MouseButton.Right });
// Shift + click
await page.Locator("#item").ClickAsync(new() { Modifiers = new[] { KeyboardModifier.Shift } });
await page.GetByText("Item").ClickAsync(new() { Modifiers = new[] { KeyboardModifier.Shift } });
// Hover over element
await page.Locator("#item").HoverAsync();
await page.GetByText("Item").HoverAsync();
// Click the top left corner
await page.Locator("#item").ClickAsync(new() { position = new Position { X = 0, Y = 0 } });
await page.GetByText("Item").ClickAsync(new() { position = new Position { X = 0, Y = 0 } });
```
Under the hood, this and other pointer-related methods:
@ -346,23 +316,23 @@ Under the hood, this and other pointer-related methods:
Sometimes, apps use non-trivial logic where hovering the element overlays it with another element that intercepts the click. This behavior is indistinguishable from a bug where element gets covered and the click is dispatched elsewhere. If you know this is taking place, you can bypass the [actionability](./actionability.md) checks and force the click:
```js
await page.locator('button#submit').click({ force: true });
await page.getByRole('button').click({ force: true });
```
```java
page.locator("button#submit").click(new Locator.ClickOptions().setForce(true));
page.getByRole("button").click(new Locator.ClickOptions().setForce(true));
```
```python async
await page.locator('button#submit').click(force=True)
await page.get_by_role("button").click(force=True)
```
```python sync
page.locator('button#submit').click(force=True)
page.get_by_role("button").click(force=True)
```
```csharp
await page.Locator("button#submit").ClickAsync(new() { Force = true });
await page.GetByRole("button").ClickAsync(new() { Force = true });
```
#### Programmatic click
@ -370,23 +340,23 @@ await page.Locator("button#submit").ClickAsync(new() { Force = true });
If you are not interested in testing your app under the real conditions and want to simulate the click by any means possible, you can trigger the [`HTMLElement.click()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click) behavior via simply dispatching a click event on the element with [`method: Locator.dispatchEvent`]:
```js
await page.locator('button#submit').dispatchEvent('click');
await page.getByRole('button').dispatchEvent('click');
```
```java
page.locator("button#submit").dispatchEvent("click");
page.getByRole("button").dispatchEvent("click");
```
```python async
await page.locator('button#submit').dispatch_event('click')
await page.get_by_role("button").dispatch_event('click')
```
```python sync
page.locator('button#submit').dispatch_event('click')
page.get_by_role("button").dispatch_event('click')
```
```csharp
await page.Locator("button#submit").DispatchEventAsync("click");
await page.GetByRole("button").DispatchEventAsync("click");
```
## Type characters
@ -428,57 +398,57 @@ Most of the time, [`method: Page.fill`] will just work. You only need to type ch
```js
// Hit Enter
await page.locator('#submit').press('Enter');
await page.getByText('Submit').press('Enter');
// Dispatch Control+Right
await page.locator('#name').press('Control+ArrowRight');
await page.getByRole('textbox').press('Control+ArrowRight');
// Press $ sign on keyboard
await page.locator('#value').press('$');
await page.getByRole('textbox').press('$');
```
```java
// Hit Enter
page.locator("#submit").press("Enter");
page.getByText("Submit").press("Enter");
// Dispatch Control+Right
page.locator("#name").press("Control+ArrowRight");
page.getByRole("textbox").press("Control+ArrowRight");
// Press $ sign on keyboard
page.locator("#value").press("$");
page.getByRole("textbox").press("$");
```
```python async
# Hit Enter
await page.locator('#submit').press('Enter')
await page.get_by_text("Submit").press("Enter")
# Dispatch Control+Right
await page.locator('#name').press('Control+ArrowRight')
await page.get_by_role("textbox").press("Control+ArrowRight")
# Press $ sign on keyboard
await page.locator('#value').press('$')
await page.get_by_role("textbox").press("$")
```
```python sync
# Hit Enter
page.locator('#submit').press('Enter')
page.get_by_text("Submit").press("Enter")
# Dispatch Control+Right
page.locator('#name').press('Control+ArrowRight')
page.get_by_role("textbox").press("Control+ArrowRight")
# Press $ sign on keyboard
page.locator('#value').press('$')
page.get_by_role("textbox").press("$")
```
```csharp
// Hit Enter
await page.Locator("#submit").PressAsync("Enter");
await page.GetByText("Submit").PressAsync("Enter");
// Dispatch Control+Right
await page.Locator("#name").PressAsync("Control+ArrowRight");
await page.GetByRole("textbox").PressAsync("Control+ArrowRight");
// Press $ sign on keyboard
await page.Locator("#value").PressAsync("$");
await page.GetByRole("textbox").PressAsync("$");
```
The [`method: Locator.press`] method focuses the selected element and produces a single keystroke. It accepts the logical key names that are emitted in the [keyboardEvent.key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) property of the keyboard events:
@ -546,16 +516,16 @@ You can select input files for upload using the [`method: Locator.setInputFiles`
```js
// Select one file
await page.locator('input#upload').setInputFiles('myfile.pdf');
await page.getByLabelText('Upload file').setInputFiles('myfile.pdf');
// Select multiple files
await page.locator('input#upload').setInputFiles(['file1.txt', 'file2.txt']);
await page.getByLabelText('Upload files').setInputFiles(['file1.txt', 'file2.txt']);
// Remove all the selected files
await page.locator('input#upload').setInputFiles([]);
await page.getByLabelText('Upload file').setInputFiles([]);
// Upload buffer from memory
await page.locator('input#upload').setInputFiles({
await page.getByLabelText('Upload file').setInputFiles({
name: 'file.txt',
mimeType: 'text/plain',
buffer: Buffer.from('this is test')
@ -564,31 +534,31 @@ await page.locator('input#upload').setInputFiles({
```java
// Select one file
page.locator("input#upload").setInputFiles(Paths.get("myfile.pdf"));
page.getByLabelText("Upload file").setInputFiles(Paths.get("myfile.pdf"));
// Select multiple files
page.locator("input#upload").setInputFiles(new Path[] {Paths.get("file1.txt"), Paths.get("file2.txt")});
page.getByLabelText("Upload files").setInputFiles(new Path[] {Paths.get("file1.txt"), Paths.get("file2.txt")});
// Remove all the selected files
page.locator("input#upload").setInputFiles(new Path[0]);
page.getByLabelText("Upload file").setInputFiles(new Path[0]);
// Upload buffer from memory
page.locator("input#upload").setInputFiles(new FilePayload(
page.getByLabelText("Upload file").setInputFiles(new FilePayload(
"file.txt", "text/plain", "this is test".getBytes(StandardCharsets.UTF_8)));
```
```python async
# Select one file
await page.locator('input#upload').set_input_files('myfile.pdf')
await page.get_by_label_text("Upload file").set_input_files('myfile.pdf')
# Select multiple files
await page.locator('input#upload').set_input_files(['file1.txt', 'file2.txt'])
await page.get_by_label_text("Upload files").set_input_files(['file1.txt', 'file2.txt'])
# Remove all the selected files
await page.locator('input#upload').set_input_files([])
await page.get_by_label_text("Upload file").set_input_files([])
# Upload buffer from memory
await page.locator("input#upload").set_input_files(
await page.get_by_label_text("Upload file").set_input_files(
files=[
{"name": "test.txt", "mimeType": "text/plain", "buffer": b"this is a test"}
],
@ -597,16 +567,16 @@ await page.locator("input#upload").set_input_files(
```python sync
# Select one file
page.locator('input#upload').set_input_files('myfile.pdf')
page.get_by_label_text("Upload file").set_input_files('myfile.pdf')
# Select multiple files
page.locator('input#upload').set_input_files(['file1.txt', 'file2.txt'])
page.get_by_label_text("Upload files").set_input_files(['file1.txt', 'file2.txt'])
# Remove all the selected files
page.locator('input#upload').set_input_files([])
page.get_by_label_text("Upload file").set_input_files([])
# Upload buffer from memory
page.locator("input#upload").set_input_files(
page.get_by_label_text("Upload file").set_input_files(
files=[
{"name": "test.txt", "mimeType": "text/plain", "buffer": b"this is a test"}
],
@ -615,16 +585,16 @@ page.locator("input#upload").set_input_files(
```csharp
// Select one file
await page.Locator("input#upload").SetInputFilesAsync("myfile.pdf");
await page.GetByLabelText("Upload file").SetInputFilesAsync("myfile.pdf");
// Select multiple files
await page.Locator("input#upload").SetInputFilesAsync(new[] { "file1.txt", "file12.txt" });
await page.GetByLabelText("Upload files").SetInputFilesAsync(new[] { "file1.txt", "file12.txt" });
// Remove all the selected files
await page.Locator("input#upload").SetInputFilesAsync(new[] {});
await page.GetByLabelText("Upload file").SetInputFilesAsync(new[] {});
// Upload buffer from memory
await page.Locator("input#upload").SetInputFilesAsync(new FilePayload
await page.GetByLabelText("Upload file").SetInputFilesAsync(new FilePayload
{
Name = "file.txt",
MimeType = "text/plain",
@ -680,23 +650,23 @@ await fileChooser.SetFilesAsync("myfile.pdf");
For the dynamic pages that handle focus events, you can focus the given element with [`method: Locator.focus`].
```js
await page.locator('input#name').focus();
await page.getByLabelText('Password').focus();
```
```java
page.locator("input#name").focus();
page.getByLabelText("Password").focus();
```
```python async
await page.locator('input#name').focus()
await page.get_by_label_text('password').focus()
```
```python sync
page.locator('input#name').focus()
page.get_by_label_text('password').focus()
```
```csharp
await page.Locator("input#name").FocusAsync();
await page.GetByLabelText("Password").FocusAsync();
```
## Drag and Drop

View file

@ -7,27 +7,27 @@ title: "Locators"
a way to find element(s) on the page at any moment. Locator can be created with the [`method: Page.locator`] method.
```js
const locator = page.locator('text=Submit');
const locator = page.getByText('Submit');
await locator.click();
```
```java
Locator locator = page.locator("text=Submit");
Locator locator = page.getByText("Submit");
locator.click();
```
```python async
locator = page.locator("text=Submit")
locator = page.get_by_text("Submit")
await locator.click()
```
```python sync
locator = page.locator("text=Submit")
locator = page.get_by_text("Submit")
locator.click()
```
```csharp
var locator = page.Locator("text=Submit");
var locator = page.GetByText("Submit");
await locator.ClickAsync();
```
@ -37,32 +37,32 @@ DOM changes in between the calls due to re-render, the new element corresponding
locator will be used.
```js
const locator = page.locator('text=Submit');
const locator = page.getByText('Submit');
// ...
await locator.hover();
await locator.click();
```
```java
Locator locator = page.locator("text=Submit");
Locator locator = page.getByText("Submit");
locator.hover();
locator.click();
```
```python async
locator = page.locator("text=Submit")
locator = page.get_by_text("Submit")
await locator.hover()
await locator.click()
```
```python sync
locator = page.locator("text=Submit")
locator = page.get_by_text("Submit")
locator.hover()
locator.click()
```
```csharp
var locator = page.Locator("text=Submit");
var locator = page.GetByText("Submit");
await locator.HoverAsync();
await locator.ClickAsync();
```
@ -75,57 +75,57 @@ given selector.
```js
// Throws if there are several buttons in DOM:
await page.locator('button').click();
await page.getByRole('button').click();
// Works because we explicitly tell locator to pick the first element:
await page.locator('button').first().click(); // ⚠️ using first disables strictness
await page.getByRole('button').first().click(); // ⚠️ using first disables strictness
// Works because count knows what to do with multiple matches:
await page.locator('button').count();
await page.getByRole('button').count();
```
```python async
# Throws if there are several buttons in DOM:
await page.locator('button').click()
await page.get_by_role("button").click()
# Works because we explicitly tell locator to pick the first element:
await page.locator('button').first.click() # ⚠️ using first disables strictness
await page.get_by_role("button").first.click() # ⚠️ using first disables strictness
# Works because count knows what to do with multiple matches:
await page.locator('button').count()
await page.get_by_role("button").count()
```
```python sync
# Throws if there are several buttons in DOM:
page.locator('button').click()
page.get_by_role("button").click()
# Works because we explicitly tell locator to pick the first element:
page.locator('button').first.click() # ⚠️ using first disables strictness
page.get_by_role("button").first.click() # ⚠️ using first disables strictness
# Works because count knows what to do with multiple matches:
page.locator('button').count()
page.get_by_role("button").count()
```
```java
// Throws if there are several buttons in DOM:
page.locator("button").click();
page.getByRole("button").click();
// Works because we explicitly tell locator to pick the first element:
page.locator("button").first().click(); // ⚠️ using first disables strictness
page.getByRole("button").first().click(); // ⚠️ using first disables strictness
// Works because count knows what to do with multiple matches:
page.locator("button").count();
page.getByRole("button").count();
```
```csharp
// Throws if there are several buttons in DOM:
await page.Locator("button").ClickAsync();
await page.GetByRole("button").ClickAsync();
// Works because we explicitly tell locator to pick the first element:
await page.Locator("button").First.ClickAsync(); // ⚠️ using First disables strictness
await page.GetByRole("button").First.ClickAsync(); // ⚠️ using First disables strictness
// Works because Count knows what to do with multiple matches:
await page.Locator("button").CountAsync();
await page.GetByRole("button").CountAsync();
```
:::caution
@ -142,19 +142,19 @@ Use [`method: Page.locator`] method to create a locator. This method takes a sel
The easiest way to find an element is to look for the text it contains.
```js
await page.locator('text=Log in').click();
await page.getByText('Log in').click();
```
```java
page.locator("text=Log in").click();
page.getByText("Log in").click();
```
```python async
await page.locator("text=Log in").click()
await page.get_by_text("Log in").click()
```
```python sync
page.locator("text=Log in").click()
page.get_by_text("Log in").click()
```
```csharp
await page.Locator("text=Log in").ClickAsync();
await page.GetByText("Log in").ClickAsync();
```
You can also [filter by text](#filter-by-text) when locating in some other way, for example find a particular item in the list.
@ -182,33 +182,33 @@ await page.Locator("data-test-id=product-item", new() { HasText = "Playwright Bo
The `role` selector reflects how users and assistive technology percieve the page, for example whether some element is a button or a checkbox. When locating by role, you should usually pass the accessible name as well, so that locator pinpoints the exact element.
```js
await page.locator('role=button[name=/submit/i]').click();
await page.getByRole('button', { name: /submit/i }).click();
await page.locator('role=checkbox[checked][name="Check me"]').check();
await page.getByRole('checkbox', { checked: true, name: "Check me" }).check();
```
```python async
await page.locator('role=button[name=/submit/i]').click()
await page.get_by_role("button", name=re.compile("(?i)submit")).click()
await page.locator('role=checkbox[checked][name="Check me"]').check()
await page.get_by_role("checkbox", checked=True, name="Check me"]).check()
```
```python sync
page.locator('role=button[name=/submit/i]').click()
page.get_by_role("button", name=re.compile("(?i)submit")).click()
page.locator('role=checkbox[checked][name="Check me"]').check()
page.get_by_role("checkbox", checked=True, name="Check me"]).check()
```
```java
page.locator("role=button[name=/submit/i]").click();
page.getByRole("button", new Page.GetByRoleOptions().setName(Pattern.compile("(?i)submit"))).click();
page.locator("role=checkbox[checked][name=\"Check me\"]").check();
page.getByRole("checkbox", new Page.GetByRoleOptions().setChecked(true).setName("Check me"))).check();
```
```csharp
await page.Locator("role=button[name=/submit/i]").ClickAsync();
await page.GetByRole("button", new() { Name = new Regex("(?i)submit") }).ClickAsync();
await page.Locator("role=checkbox[checked][name=\"Check me\"]").CheckAsync();
await page.GetByRole("checkbox", new() { Checked = true, Name = "Check me" }).CheckAsync();
```
[Learn more about the `role` selector](./selectors.md#role-selector).
@ -262,23 +262,23 @@ You can target the label with something like `text=Password` and perform the fol
For example, to fill the input by targeting the label:
```js
await page.locator('text=Password').fill('secret');
await page.getByText('Password').fill('secret');
```
```java
page.locator("text=Password").fill("secret");
page.getByText("Password").fill("secret");
```
```python async
await page.locator('text=Password').fill('secret')
await page.get_by_text('Password').fill('secret')
```
```python sync
page.locator('text=Password').fill('secret')
page.get_by_text('Password').fill('secret')
```
```csharp
await page.Locator("text=Password").FillAsync("secret");
await page.GetByText("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.
@ -305,31 +305,31 @@ For example, we can first find a product card that contains text "Product 2", an
```js
const product = page.locator('data-test-id=product-card', { hasText: 'Product 2' });
await product.locator('text=Buy').click();
await product.getByText('Buy').click();
```
```python async
product = page.locator("data-test-id=product-card", has_text="Product 2")
await product.locator("text=Buy").click()
await product.getByText("Buy").click()
```
```python sync
product = page.locator("data-test-id=product-card", has_text="Product 2")
product.locator("text=Buy").click()
product.get_by_text("Buy").click()
```
```java
Locator product = page.locator("data-test-id=product-card", new Page.LocatorOptions().setHasText("Product 2"));
product.locator("text=Buy").click();
product.get_by_text("Buy").click();
```
```csharp
var product = page.Locator("data-test-id=product-card", new() { HasText = "Product 2" });
await product.Locator("text=Buy").clickAsync();
await product.GetByText("Buy").clickAsync();
```
### Locate by CSS or XPath selector
@ -531,19 +531,19 @@ You can locate in the same way as if the shadow root was not present at all.
- Click `<span>Details</span>`
```js
await page.locator('text=Details').click();
await page.getByText('Details').click();
```
```java
page.locator("text=Details").click();
page.getByText("Details").click();
```
```python async
await page.locator("text=Details").click()
await page.get_by_text("Details").click()
```
```python sync
page.locator("text=Details").click()
page.get_by_text("Details").click()
```
```csharp
await page.Locator("text=Details").ClickAsync();
await page.GetByText("Details").ClickAsync();
```
- Click `<x-badge>`
@ -742,32 +742,32 @@ await handle.ClickAsync();
With the locator, every time the locator is used, up-to-date DOM element is located in the page using the selector. So in the snippet below, underlying DOM element is going to be located twice.
```js
const locator = page.locator('text=Submit');
const locator = page.getByText('Submit');
// ...
await locator.hover();
await locator.click();
```
```java
Locator locator = page.locator("text=Submit");
Locator locator = page.getByText("Submit");
locator.hover();
locator.click();
```
```python async
locator = page.locator("text=Submit")
locator = page.get_by_text("Submit")
await locator.hover()
await locator.click()
```
```python sync
locator = page.locator("text=Submit")
locator = page.get_by_text("Submit")
locator.hover()
locator.click()
```
```csharp
var locator = page.Locator("text=Submit");
var locator = page.GetByText("Submit");
await locator.HoverAsync();
await locator.ClickAsync();
```

View file

@ -97,56 +97,56 @@ Alternatively, page interactions like [`method: Page.click`] auto-wait for eleme
```js
// Navigate and wait for element
await page.goto('https://example.com');
await page.locator('text=Example Domain').waitFor();
await page.getByText('Example Domain').waitFor();
// Navigate and click element
// Click will auto-wait for the element
await page.goto('https://example.com');
await page.locator('text=Example Domain').click();
await page.getByText('Example Domain').click();
```
```java
// Navigate and wait for element
page.navigate("https://example.com");
page.locator("text=Example Domain").waitFor();
page.getByText("Example Domain").waitFor();
// Navigate and click element
// Click will auto-wait for the element
page.navigate("https://example.com");
page.locator("text=Example Domain").click();
page.getByText("Example Domain").click();
```
```python async
# Navigate and wait for element
await page.goto("https://example.com")
await page.locator("text=example domain").wait_for()
await page.get_by_text("example domain").wait_for()
# Navigate and click element
# Click will auto-wait for the element
await page.goto("https://example.com")
await page.locator("text=example domain").click()
await page.get_by_text("example domain").click()
```
```python sync
# Navigate and wait for element
page.goto("https://example.com")
page.locator("text=example domain").wait_for()
page.get_by_text("example domain").wait_for()
# Navigate and click element
# Click will auto-wait for the element
page.goto("https://example.com")
page.locator("text=example domain").click()
page.get_by_text("example domain").click()
```
```csharp
// Navigate and wait for element
await page.GotoAsync("https://example.com");
await page.Locator("text=Example Domain").WaitForAsync();
await page.GetByText("Example Domain").WaitForAsync();
// Navigate and click element
// Click will auto-wait for the element
await page.GotoAsync("https://example.com");
await page.Locator("text=Example Domain").ClickAsync();
await page.GetByText("Example Domain").ClickAsync();
```
## Scenarios initiated by page interaction
@ -159,42 +159,42 @@ By default, [`method: Locator.click`] will wait for the navigation step to compl
```js
// Click will auto-wait for navigation to complete
await page.locator('text=Login').click();
await page.getByText('Login').click();
// Fill will auto-wait for element on navigated page
await page.locator('#username').fill('John Doe');
await page.getByLabelText('User Name').fill('John Doe');
```
```java
// Click will auto-wait for navigation to complete
page.locator("text=Login").click();
page.getByText("Login").click();
// Fill will auto-wait for element on navigated page
page.locator("#username").fill("John Doe");
page.getByLabelText("User Name").fill("John Doe");
```
```python async
# Click will auto-wait for navigation to complete
await page.locator("text=Login").click()
await page.get_by_text("Login").click()
# Fill will auto-wait for element on navigated page
await page.locator("#username").fill("John Doe")
await page.get_by_label_text("User Name").fill("John Doe")
```
```python sync
# Click will auto-wait for navigation to complete
page.locator("text=Login").click()
page.get_by_text("Login").click()
# Fill will auto-wait for element on navigated page
page.locator("#username").fill("John Doe")
page.get_by_label_text("User Name").fill("John Doe")
```
```csharp
// Click will auto-wait for navigation to complete
await page.Locator("text=Login").ClickAsync();
await page.GetByText("Login").ClickAsync();
// Fill will auto-wait for element on navigated page
await page.Locator("#username").FillAsync("John Doe");
await page.GetByLabelText("User Name").FillAsync("John Doe");
```
### Custom wait
@ -202,7 +202,7 @@ await page.Locator("#username").FillAsync("John Doe");
`locator.click` can be combined with [`method: Page.waitForLoadState`] to wait for a loading event.
```js
await page.locator('button').click(); // Click triggers navigation
await page.getByRole('button').click(); // Click triggers navigation
await page.waitForLoadState('networkidle'); // This resolves after 'networkidle'
```
@ -233,62 +233,62 @@ Alternatively, page interactions like [`method: Locator.click`] auto-wait for el
```js
// Click will auto-wait for the element and trigger navigation
await page.locator('text=Login').click();
await page.getByText('Login').click();
// Wait for the element
await page.locator('#username').waitFor();
await page.getByLabelText('User Name').waitFor();
// Click triggers navigation
await page.locator('text=Login').click();
await page.getByText('Login').click();
// Fill will auto-wait for element
await page.locator('#username').fill('John Doe');
await page.getByLabelText('User Name').fill('John Doe');
```
```java
// Click will auto-wait for the element and trigger navigation
page.locator("text=Login").click();
page.getByText("Login").click();
// Wait for the element
page.locator("#username").waitFor();
page.getByLabelText("User Name").waitFor();
// Click triggers navigation
page.locator("text=Login").click();
page.getByText("Login").click();
// Fill will auto-wait for element
page.locator("#username").fill("John Doe");
page.getByLabelText("User Name").fill("John Doe");
```
```python async
# Click will auto-wait for the element and trigger navigation
await page.locator("text=Login").click()
await page.get_by_text("Login").click()
# Wait for the element
await page.locator("#username").wait_for()
await page.get_by_label_text("User Name").wait_for()
# Click triggers navigation
await page.locator("text=Login").click()
await page.get_by_text("Login").click()
# Fill will auto-wait for element
await page.locator("#username").fill("John Doe")
await page.get_by_label_text("User Name").fill("John Doe")
```
```python sync
# Click triggers navigation
page.locator("text=Login").click()
page.get_by_text("Login").click()
# Click will auto-wait for the element
page.locator("#username").wait_for()
page.get_by_label_text("User Name").wait_for()
# Click triggers navigation
page.locator("text=Login").click()
page.get_by_text("Login").click()
# Fill will auto-wait for element
page.locator("#username").fill("John Doe")
page.get_by_label_text("User Name").fill("John Doe")
```
```csharp
// Click will auto-wait for the element and trigger navigation
await page.Locator("text=Login").ClickAsync();
await page.GetByText("Login").ClickAsync();
// Wait for the element
await page.Locator("#username").WaitForAsync();
await page.GetByLabelText("User Name").WaitForAsync();
// Click triggers navigation
await page.Locator("text=Login").ClickAsync();
await page.GetByText("Login").ClickAsync();
// Fill will auto-wait for element
await page.Locator("#username").FillAsync("John Doe");
await page.GetByLabelText("User Name").FillAsync("John Doe");
```
### Asynchronous navigation
@ -358,7 +358,7 @@ await Promise.all([
// It is important to call waitForNavigation before click to set up waiting.
page.waitForNavigation({ url: '**/login' }),
// Triggers a navigation with a script redirect.
page.locator('text=Click me').click(),
page.getByText('Click me').click(),
]);
```
@ -366,7 +366,7 @@ await Promise.all([
// Running action in the callback of waitForNavigation prevents a race
// condition between clicking and waiting for a navigation.
page.waitForNavigation(new Page.WaitForNavigationOptions().setUrl("**/login"), () -> {
page.locator("a").click(); // Triggers a navigation with a script redirect
page.getByText("Click me").click(); // Triggers a navigation with a script redirect
});
```
@ -375,7 +375,7 @@ page.waitForNavigation(new Page.WaitForNavigationOptions().setUrl("**/login"), (
# between clicking and waiting for a navigation.
async with page.expect_navigation(url="**/login"):
# Triggers a navigation with a script redirect
await page.locator("a").click()
await page.get_by_text("Click me").click()
```
```python sync
@ -383,7 +383,7 @@ async with page.expect_navigation(url="**/login"):
# between clicking and waiting for a navigation.
with page.expect_navigation(url="**/login"):
# Triggers a navigation with a script redirect
page.locator("a").click()
page.get_by_text("Click me").click()
```
```csharp
@ -392,7 +392,7 @@ with page.expect_navigation(url="**/login"):
await page.RunAndWaitForNavigationAsync(async () =>
{
// Triggers a navigation with a script redirect.
await page.Locator("a").ClickAsync();
await page.GetByText("Click me").ClickAsync();
}, new()
{
UrlString = "**/login"

View file

@ -251,35 +251,35 @@ Or wait for a network response after the button click with [`method: Page.waitFo
// Use a glob URL pattern
const [response] = await Promise.all([
page.waitForResponse('**/api/fetch_data'),
page.locator('button#update').click(),
page.getByText('Update').click(),
]);
```
```java
// Use a glob URL pattern
Response response = page.waitForResponse("**/api/fetch_data", () -> {
page.locator("button#update").click();
page.getByText("Update").click();
});
```
```python async
# Use a glob url pattern
async with page.expect_response("**/api/fetch_data") as response_info:
await page.locator("button#update").click()
await page.get_by_text("Update").click()
response = await response_info.value
```
```python sync
# Use a glob url pattern
with page.expect_response("**/api/fetch_data") as response_info:
page.locator("button#update").click()
page.get_by_text("Update").click()
response = response_info.value
```
```csharp
// Use a glob URL pattern
var waitForResponseTask = page.WaitForResponseAsync("**/api/fetch_data");
await page.Locator("button#update").ClickAsync();
await page.GetByText("Update").ClickAsync();
var response = await waitForResponseTask;
```
@ -291,61 +291,61 @@ Wait for [Response]s with [`method: Page.waitForResponse`]
// Use a RegExp
const [response] = await Promise.all([
page.waitForResponse(/\.jpeg$/),
page.locator('button#update').click(),
page.getByText('Update').click(),
]);
// Use a predicate taking a Response object
const [response] = await Promise.all([
page.waitForResponse(response => response.url().includes(token)),
page.locator('button#update').click(),
page.getByText('Update').click(),
]);
```
```java
// Use a RegExp
Response response = page.waitForResponse(Pattern.compile("\\.jpeg$"), () -> {
page.locator("button#update").click();
page.getByText("Update").click();
});
// Use a predicate taking a Response object
Response response = page.waitForResponse(r -> r.url().contains(token), () -> {
page.locator("button#update").click();
page.getByText("Update").click();
});
```
```python async
# Use a regular expression
async with page.expect_response(re.compile(r"\.jpeg$")) as response_info:
await page.locator("button#update").click()
await page.get_by_text("Update").click()
response = await response_info.value
# Use a predicate taking a response object
async with page.expect_response(lambda response: token in response.url) as response_info:
await page.locator("button#update").click()
await page.get_by_text("Update").click()
response = await response_info.value
```
```python sync
# Use a regular expression
with page.expect_response(re.compile(r"\.jpeg$")) as response_info:
page.locator("button#update").click()
page.get_by_text("Update").click()
response = response_info.value
# Use a predicate taking a response object
with page.expect_response(lambda response: token in response.url) as response_info:
page.locator("button#update").click()
page.get_by_text("Update").click()
response = response_info.value
```
```csharp
// Use a regular expression
var waitForResponseTask = page.WaitForResponseAsync(new Regex("\\.jpeg$"));
await page.Locator("button#update").ClickAsync();
await page.GetByText("Update").ClickAsync();
var response = await waitForResponseTask;
// Use a predicate taking a Response object
var waitForResponseTask = page.WaitForResponseAsync(r => r.Url.Contains(token));
await page.Locator("button#update").ClickAsync();
await page.GetByText("Update").ClickAsync();
var response = await waitForResponseTask;
```
## Handle requests

View file

@ -71,7 +71,7 @@ test.describe('angularjs homepage todo list', function() {
});
// You wrote your first test, cross it off the list
await todoList.nth(2).locator('input').click();
await todoList.nth(2).getByRole('textbox').click();
var completedAmount = page.locator('.done-true');
await expect(completedAmount).toHaveCount(2);
});

View file

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

View file

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

View file

@ -302,10 +302,10 @@ test.afterAll(async ({ }) => {
test('last created issue should be on the server', async ({ page, request }) => {
await page.goto(`https://github.com/${USER}/${REPO}/issues`);
await page.locator('text=New Issue').click();
await page.locator('[aria-label="Title"]').fill('Bug report 1');
await page.locator('[aria-label="Comment body"]').fill('Bug description');
await page.locator('text=Submit new issue').click();
await page.getByText('New Issue').click();
await page.getByRole('textbox', { name: 'Title' }).fill('Bug report 1');
await page.getByRole('textbox', { name: 'Comment body' }).fill('Bug description');
await page.getByText('Submit new issue').click();
const issueId = page.url().substr(page.url().lastIndexOf('/'));
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 }) => {
await page.goto(`https://github.com/${USER}/${REPO}/issues`);
await page.locator('text=New Issue').click();
await page.locator('[aria-label="Title"]').fill('Bug report 1');
await page.locator('[aria-label="Comment body"]').fill('Bug description');
await page.locator('text=Submit new issue').click();
await page.getByText('New Issue').click();
await page.getByRole('textbox', { name: 'Title' }).fill('Bug report 1');
await page.getByRole('textbox', { name: 'Comment body' }).fill('Bug description');
await page.getByText('Submit new issue').click();
const issueId = page.url().substr(page.url().lastIndexOf('/'));
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 }) => {
await page.goto('/signin');
await page.locator('#username').fill('User');
await page.locator('#password').fill('pwd');
await page.locator('text=Sign in').click();
await page.getByLabelText('User Name').fill('user');
await page.getByLabelText('Password').fill('password');
await page.getByText('Sign in').click();
// ...
});
```
@ -89,9 +89,9 @@ import { test, expect } from '@playwright/test';
test('basic test', async ({ page }) => {
await page.goto('/signin');
await page.locator('#username').fill('User');
await page.locator('#password').fill('pwd');
await page.locator('text=Sign in').click();
await page.getByLabelText('User Name').fill('user');
await page.getByLabelText('Password').fill('password');
await page.getByText('Sign in').click();
// ...
});
```

View file

@ -63,7 +63,7 @@ expect(test.info().errors).toHaveLength(0);
You can specify a custom error message as a second argument to the `expect` function, for example:
```js
await expect(page.locator('text=Name'), 'should be logged in').toBeVisible();
await expect(page.getByText('Name'), 'should be logged in').toBeVisible();
```
The error would look like this:
@ -78,7 +78,7 @@ The error would look like this:
2 |
3 | test('example test', async({ page }) => {
> 4 | await expect(page.locator('text=Name'), 'should be logged in').toBeVisible();
> 4 | await expect(page.getByText('Name'), 'should be logged in').toBeVisible();
| ^
5 | });
6 |

View file

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

View file

@ -334,9 +334,9 @@ exports.test = base.test.extend({
// Create the account with Playwright.
const page = await browser.newPage();
await page.goto('/signup');
await page.locator('#username').fill(username);
await page.locator('#password').fill(password);
await page.locator('text=Sign up').click();
await page.getByLabelText('User Name').fill(username);
await page.getByLabelText('Password').fill(password);
await page.getByText('Sign up').click();
// Make sure everything is ok.
await expect(page.locator('#result')).toHaveText('Success');
// Do not forget to cleanup.
@ -350,9 +350,9 @@ exports.test = base.test.extend({
// Sign in with our account.
const { username, password } = account;
await page.goto('/signin');
await page.locator('#username').fill(username);
await page.locator('#password').fill(password);
await page.locator('text=Sign in').click();
await page.getByLabelText('User Name').fill(username);
await page.getByLabelText('Password').fill(password);
await page.getByText('Sign in').click();
await expect(page.locator('#userinfo')).toHaveText(username);
// Use signed-in page in the test.
@ -381,9 +381,9 @@ export const test = base.extend<{}, { account: Account }>({
// Create the account with Playwright.
const page = await browser.newPage();
await page.goto('/signup');
await page.locator('#username').fill(username);
await page.locator('#password').fill(password);
await page.locator('text=Sign up').click();
await page.getByLabelText('User Name').fill(username);
await page.getByLabelText('Password').fill(password);
await page.getByText('Sign up').click();
// Make sure everything is ok.
await expect(page.locator('#result')).toHaveText('Success');
// Do not forget to cleanup.
@ -397,9 +397,9 @@ export const test = base.extend<{}, { account: Account }>({
// Sign in with our account.
const { username, password } = account;
await page.goto('/signin');
await page.locator('#username').fill(username);
await page.locator('#password').fill(password);
await page.locator('text=Sign in').click();
await page.getByLabelText('User Name').fill(username);
await page.getByLabelText('Password').fill(password);
await page.getByText('Sign in').click();
await expect(page.locator('#userinfo')).toHaveText(username);
// Use signed-in page in the test.

View file

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

View file

@ -143,8 +143,8 @@ exports.test = base.test.extend({
page: async ({ page, person }, use) => {
await page.goto('/chat');
// We use "person" parameter as a "name" for the chat room.
await page.locator('#name').fill(person);
await page.locator('text=Enter chat room').click();
await page.getByLabelText('User Name').fill(person);
await page.getByText('Enter chat room').click();
// Each test will get a "page" that already has the person name.
await use(page);
},
@ -168,8 +168,8 @@ export const test = base.test.extend<TestOptions>({
page: async ({ page, person }, use) => {
await page.goto('/chat');
// We use "person" parameter as a "name" for the chat room.
await page.locator('#name').fill(person);
await page.locator('text=Enter chat room').click();
await page.getByLabelText('User Name').fill(person);
await page.getByText('Enter chat room').click();
// Each test will get a "page" that already has the person name.
await use(page);
},
@ -190,8 +190,8 @@ For example, consider the following test file that needs a username and a passwo
// example.spec.js
test(`example test`, async ({ page }) => {
// ...
await page.locator('#username').fill(process.env.USERNAME);
await page.locator('#password').fill(process.env.PASSWORD);
await page.getByLabelText('User Name').fill(process.env.USERNAME);
await page.getByLabelText('Password').fill(process.env.PASSWORD);
});
```
@ -199,8 +199,8 @@ test(`example test`, async ({ page }) => {
// example.spec.ts
test(`example test`, async ({ page }) => {
// ...
await page.locator('#username').fill(process.env.USERNAME);
await page.locator('#password').fill(process.env.PASSWORD);
await page.getByLabelText('User Name').fill(process.env.USERNAME);
await page.getByLabelText('Password').fill(process.env.PASSWORD);
});
```

View file

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

View file

@ -185,7 +185,7 @@ API reference: [`property: TestConfig.expect`].
const { test, expect } = require('@playwright/test');
test('basic test', async ({ page }) => {
await expect(page.locator('button')).toHaveText('Sign in', { timeout: 10000 });
await expect(page.getByRole('button')).toHaveText('Sign in', { timeout: 10000 });
});
```
@ -193,7 +193,7 @@ test('basic test', async ({ page }) => {
import { test, expect } from '@playwright/test';
test('basic test', async ({ page }) => {
await expect(page.locator('button')).toHaveText('Sign in', { timeout: 10000 });
await expect(page.getByRole('button')).toHaveText('Sign in', { timeout: 10000 });
});
```
@ -251,7 +251,7 @@ const { test, expect } = require('@playwright/test');
test('basic test', async ({ page }) => {
await page.goto('https://playwright.dev', { timeout: 30000 });
await page.locator('text=Get Started').click({ timeout: 10000 });
await page.getByText('Get Started').click({ timeout: 10000 });
});
```
@ -260,7 +260,7 @@ import { test, expect } from '@playwright/test';
test('basic test', async ({ page }) => {
await page.goto('https://playwright.dev', { timeout: 30000 });
await page.locator('text=Get Started').click({ timeout: 10000 });
await page.getByText('Get Started').click({ timeout: 10000 });
});
```

View file

@ -25,8 +25,8 @@ import { test, expect } from '@playwright/test';
import { username, password } from './helper';
test('example', async ({ page }) => {
await page.locator('#username').fill(username);
await page.locator('#password').fill(password);
await page.getByLabelText('User Name').fill(username);
await page.getByLabelText('Password').fill(password);
});
```
@ -62,8 +62,8 @@ import { test, expect } from '@playwright/test';
import { username, password } from './helper.ts';
test('example', async ({ page }) => {
await page.locator('#username').fill(username);
await page.locator('#password').fill(password);
await page.getByLabelText('User Name').fill(username);
await page.getByLabelText('Password').fill(password);
});
```
@ -96,8 +96,8 @@ import { test, expect } from '@playwright/test';
import { username, password } from '@myhelper/credentials';
test('example', async ({ page }) => {
await page.locator('#username').fill(username);
await page.locator('#password').fill(password);
await page.getByLabelText('User Name').fill(username);
await page.getByLabelText('Password').fill(password);
});
```

View file

@ -27,7 +27,7 @@ If you use DOM Testing Library in the browser (for example, you bundle end-to-en
| `expect(screen.getByLabelText('Password')).toHaveValue('secret')` | `await expect(component.getByLabelText('Password')).toHaveValue('secret')` |
| `screen.findByText('...')` | `component.getByText('...')` |
| `screen.getByTestId('...')` | `component.getByTestId('...')` |
| `screen.queryByPlaceholderText('...')` | `component.locator('[placeholder="..."]')` |
| `screen.queryByPlaceholderText('...')` | `component.getByPlaceholderText('...')` |
| `screen.getByRole('button', { pressed: true })` | `component.getByRole('button', { pressed: true })`|
## Example
@ -64,12 +64,12 @@ test('should sign in', async ({ page, mount }) => { // 2
const component = await mount(<SignInPage />); // 3
// Perform actions.
await component.locator('text=Username').fill('John'); // 4
await component.locator('text=Password').fill('secret');
await component.locator('text=Sign in').click();
await component.getByText('Username').fill('John'); // 4
await component.getByText('Password').fill('secret');
await component.getByText('Sign in').click();
// Verify signed in state by waiting until "Welcome" message appears.
await expect(component.locator('text=Welcome, John')).toBeVisible(); // 5
await expect(component.getByText('Welcome, John')).toBeVisible(); // 5
});
```
@ -83,14 +83,7 @@ Migration highlights (see inline comments in the Playwright Test code snippet):
## Migrating queries
All queries like `getBy...`, `findBy...`, `queryBy...` and their multi-element counterparts are replaced with `page.locator('...')`. Locators always auto-wait and retry when needed, so you don't have to worry about choosing the right method. When you want to do a [list operation](./locators#lists), e.g. assert a list of texts, Playwright automatically performs multi-element operations.
1. `getByRole`: use [role selector](./selectors#role-selector) `component.locator('role=button[name="Sign up"]')`.
1. `getByText`: use `component.locator('text=some value')` and other variations of the [text selector](./selectors#text-selector).
1. `getByTestId`: use [test id selectors](./selectors#id-data-testid-data-test-id-data-test-selectors), for example `component.locator('data-testid=some value')`.
1. `getByPlaceholderText`: use css alternative `component.locator('[placeholder="some value"]')`.
1. `getByAltText`: use css alternative `component.locator('[alt="some value"]')` or [role selector](./selectors#role-selector) `component.locator('role=img[name="some value"]')`.
1. `getByTitle`: use css alternative `component.locator('[title="some value"]')`
All queries like `getBy...`, `findBy...`, `queryBy...` and their multi-element counterparts are replaced with `component.getBy...` locators. Locators always auto-wait and retry when needed, so you don't have to worry about choosing the right method. When you want to do a [list operation](./locators#lists), e.g. assert a list of texts, Playwright automatically performs multi-element operations.
## Replacing `waitFor`
@ -104,8 +97,8 @@ await waitFor(() => {
await waitForElementToBeRemoved(() => queryByText('the mummy'))
// Playwright
await expect(page.locator('text=the lion king')).toBeVisible()
await expect(page.locator('text=the mummy')).toBeHidden()
await expect(page.getByText('the lion king')).toBeVisible()
await expect(page.getByText('the mummy')).toBeHidden()
```
When you cannot find a suitable assertion, use [`expect.poll`](./test-assertions#polling) instead.
@ -128,7 +121,7 @@ const helloMessage = within(messages).getByText('hello')
// Playwright
const messages = component.locator('id=messages')
const helloMessage = messages.locator('text=hello')
const helloMessage = messages.getByText('hello')
```
## Playwright Test Super Powers

View file

@ -120,7 +120,7 @@ import { test, expect } from './webView2Test';
test('test WebView2', async ({ page }) => {
await page.goto('https://playwright.dev');
const getStarted = page.locator('text=Get Started');
const getStarted = page.getByText('Get Started');
await expect(getStarted).toBeVisible();
});
```
@ -242,7 +242,7 @@ public class TestExample {
@Test
public void shouldClickButton() {
page.navigate("https://playwright.dev");
Locator gettingStarted = page.locator("text=Get started");
Locator gettingStarted = page.getByText("Get started");
assertThat(gettingStarted).isVisible();
}
}
@ -338,7 +338,7 @@ from playwright.sync_api import Page, expect
def test_webview2(page: Page):
page.goto("https://playwright.dev")
get_started = page.locator("text=Get Started")
get_started = page.get_by_text("Get Started")
expect(get_started).to_be_visible()
```
@ -420,7 +420,7 @@ public class Tests : WebView2Test
public async Task HomepageHasPlaywrightInTitleAndGetStartedLinkLinkingtoTheIntroPage()
{
await Page.GotoAsync("https://playwright.dev");
var getStarted = Page.Locator("text=Get Started");
var getStarted = Page.GetByText("Get Started");
await Expect(getStarted).ToBeVisibleAsync();
}
}

View file

@ -28,14 +28,14 @@ test('homepage has Playwright in title and get started link linking to the intro
await expect(page).toHaveTitle(/Playwright/);
// create a locator
const getStarted = page.locator('text=Get Started');
const getStarted = page.getByText('Get Started');
// Expect an attribute "to be strictly equal" to the value.
await expect(getStarted).toHaveAttribute('href', '/docs/intro');
// Click the get started link.
await getStarted.click();
// Expects the URL to contain intro.
await expect(page).toHaveURL(/.*intro/);
});
@ -51,7 +51,7 @@ test('homepage has Playwright in title and get started link linking to the intro
await expect(page).toHaveTitle(/Playwright/);
// create a locator
const getStarted = page.locator('text=Get Started');
const getStarted = page.getByText('Get Started');
// Expect an attribute "to be strictly equal" to the value.
await expect(getStarted).toHaveAttribute('href', '/docs/intro');
@ -82,7 +82,7 @@ await expect(page).toHaveTitle(/Playwright/);
[Locators](./locators.md) are the central piece of Playwright's auto-waiting and retry-ability. Locators represent a way to find element(s) on the page at any moment and are used to perform actions on elements such as `.click` `.fill` etc. Custom locators can be created with the [`method: Page.locator`] method.
```js
const getStarted = page.locator('text=Get Started');
const getStarted = page.getByText('Get Started');
await expect(getStarted).toHaveAttribute('href', '/docs/installation');
await getStarted.click();
@ -92,7 +92,7 @@ await getStarted.click();
```js
await expect(page.locator('text=Installation')).toBeVisible();
await expect(page.getByText('Installation')).toBeVisible();
```

View file

@ -2421,7 +2421,7 @@ export interface Page {
* id="my-frame">`:
*
* ```js
* const locator = page.frameLocator('#my-iframe').locator('text=Submit');
* const locator = page.frameLocator('#my-iframe').getByText('Submit');
* await locator.click();
* ```
*
@ -4152,7 +4152,7 @@ export interface Page {
* when this method is called. If current document has already reached the required state, resolves immediately.
*
* ```js
* await page.click('button'); // Click triggers navigation.
* await page.getByRole('button').click(); // Click triggers navigation.
* await page.waitForLoadState(); // The promise resolves after 'load' event.
* ```
*
@ -4161,7 +4161,7 @@ export interface Page {
* // It is important to call waitForEvent before click to set up waiting.
* page.waitForEvent('popup'),
* // Click triggers a popup.
* page.locator('button').click(),
* page.getByRole('button').click(),
* ])
* await popup.waitForLoadState('domcontentloaded'); // The promise resolves after 'domcontentloaded' event.
* console.log(await popup.title()); // Popup is ready to use.
@ -5512,7 +5512,7 @@ export interface Frame {
* id="my-frame">`:
*
* ```js
* const locator = frame.frameLocator('#my-iframe').locator('text=Submit');
* const locator = frame.frameLocator('#my-iframe').getByText('Submit');
* await locator.click();
* ```
*
@ -6724,7 +6724,7 @@ export interface BrowserContext {
* <button onclick="onClick()">Click me</button>
* <div></div>
* `);
* await page.locator('button').click();
* await page.getByRole('button').click();
* })();
* ```
*
@ -6778,7 +6778,7 @@ export interface BrowserContext {
* <button onclick="onClick()">Click me</button>
* <div></div>
* `);
* await page.locator('button').click();
* await page.getByRole('button').click();
* })();
* ```
*
@ -7350,7 +7350,7 @@ export interface BrowserContext {
* <button onclick="onClick()">Click me</button>
* <div></div>
* `);
* await page.locator('button').click();
* await page.getByRole('button').click();
* })();
* ```
*
@ -8030,7 +8030,7 @@ export interface JSHandle<T = any> {
* in the snippet below, underlying DOM element is going to be located twice.
*
* ```js
* const locator = page.locator('text=Submit');
* const locator = page.getByText('Submit');
* // ...
* await locator.hover();
* await locator.click();
@ -9906,7 +9906,7 @@ export interface Locator {
* // ...
* await rowLocator
* .filter({ hasText: 'text in column 1' })
* .filter({ has: page.locator('button', { hasText: 'column 2 button' }) })
* .filter({ has: page.getByRole('button', { name: 'column 2 button' }) })
* .screenshot();
* ```
*
@ -9953,7 +9953,7 @@ export interface Locator {
* that iframe:
*
* ```js
* const locator = page.frameLocator('iframe').locator('text=Submit');
* const locator = page.frameLocator('iframe').getByText('Submit');
* await locator.click();
* ```
*
@ -10746,8 +10746,8 @@ export interface Locator {
* An example of typing into a text field and then submitting the form:
*
* ```js
* const element = page.locator('input');
* await element.type('some text');
* const element = page.getByLabelText('Password');
* await element.type('my password');
* await element.press('Enter');
* ```
*
@ -14805,7 +14805,7 @@ export interface Dialog {
* // It is important to call waitForEvent before click to set up waiting.
* page.waitForEvent('download'),
* // Triggers the download.
* page.locator('text=Download file').click(),
* page.getByText('Download file').click(),
* ]);
* // wait for download to complete
* const path = await download.path();
@ -15108,7 +15108,7 @@ export interface Electron {
* // It is important to call waitForEvent before click to set up waiting.
* page.waitForEvent('filechooser'),
* // Opens the file chooser.
* page.locator('text=Upload').click(),
* page.getByText('Upload').click(),
* ]);
* await fileChooser.setFiles('myfile.pdf');
* ```
@ -15191,7 +15191,7 @@ export interface FileChooser {
* [locator.frameLocator(selector)](https://playwright.dev/docs/api/class-locator#locator-frame-locator) method.
*
* ```js
* const locator = page.frameLocator('#my-frame').locator('text=Submit');
* const locator = page.frameLocator('#my-frame').getByText('Submit');
* await locator.click();
* ```
*
@ -15202,10 +15202,10 @@ export interface FileChooser {
*
* ```js
* // Throws if there are several frames in DOM:
* await page.frameLocator('.result-frame').locator('button').click();
* await page.frameLocator('.result-frame').getByRole('button').click();
*
* // Works because we explicitly tell locator to pick the first frame:
* await page.frameLocator('.result-frame').first().locator('button').click();
* await page.frameLocator('.result-frame').first().getByRole('button').click();
* ```
*
* **Converting Locator to FrameLocator**
@ -16572,7 +16572,7 @@ export interface Tracing {
* await page.goto('https://playwright.dev');
*
* await context.tracing.startChunk();
* await page.locator('text=Get Started').click();
* await page.getByText('Get Started').click();
* // Everything between startChunk and stopChunk will be recorded in the trace.
* await context.tracing.stopChunk({ path: 'trace1.zip' });
*

View file

@ -3078,9 +3078,9 @@ export interface PlaywrightTestArgs {
*
* test('basic test', async ({ page }) => {
* await page.goto('/signin');
* await page.locator('#username').fill('User');
* await page.locator('#password').fill('pwd');
* await page.locator('text=Sign in').click();
* await page.getByLabelText('User Name').fill('user');
* await page.getByLabelText('Password').fill('password');
* await page.getByText('Sign in').click();
* // ...
* });
* ```
@ -3255,7 +3255,7 @@ interface APIResponseAssertions {
*
* test('status becomes submitted', async ({ page }) => {
* // ...
* await page.locator('#submit-button').click();
* await page.getByRole('button').click();
* await expect(page.locator('.status')).toHaveText('Submitted');
* });
* ```
@ -3277,7 +3277,7 @@ interface LocatorAssertions {
* Ensures the [Locator] points to a checked input.
*
* ```js
* const locator = page.locator('.subscribe');
* const locator = page.getByLabelText('Subscribe to newsletter');
* await expect(locator).toBeChecked();
* ```
*
@ -3316,7 +3316,7 @@ interface LocatorAssertions {
* Ensures the [Locator] points to an editable element.
*
* ```js
* const locator = page.locator('input');
* const locator = page.getByRole('textbox');
* await expect(locator).toBeEditable();
* ```
*
@ -3371,7 +3371,7 @@ interface LocatorAssertions {
* Ensures the [Locator] points to a focused DOM node.
*
* ```js
* const locator = page.locator('input');
* const locator = page.getByRole('textbox');
* await expect(locator).toBeFocused();
* ```
*
@ -3557,7 +3557,7 @@ interface LocatorAssertions {
* Ensures the [Locator] resolves to an element with the given computed CSS style.
*
* ```js
* const locator = page.locator('button');
* const locator = page.getByRole('button');
* await expect(locator).toHaveCSS('display', 'flex');
* ```
*
@ -3576,7 +3576,7 @@ interface LocatorAssertions {
* Ensures the [Locator] points to an element with the given DOM Node ID.
*
* ```js
* const locator = page.locator('input');
* const locator = page.getByRole('textbox');
* await expect(locator).toHaveId('lastname');
* ```
*
@ -3615,7 +3615,7 @@ interface LocatorAssertions {
* screenshot with the expectation.
*
* ```js
* const locator = page.locator('button');
* const locator = page.getByRole('button');
* await expect(locator).toHaveScreenshot('image.png');
* ```
*
@ -3690,7 +3690,7 @@ interface LocatorAssertions {
* screenshot with the expectation.
*
* ```js
* const locator = page.locator('button');
* const locator = page.getByRole('button');
* await expect(locator).toHaveScreenshot();
* ```
*
@ -3880,7 +3880,7 @@ interface LocatorAssertions {
*
* test('navigates to login', async ({ page }) => {
* // ...
* await page.locator('#login').click();
* await page.getByText('Sign in').click();
* await expect(page).toHaveURL(/.*\/login/);
* });
* ```