mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
docs: code snippet alignments (#23959)
This commit is contained in:
parent
c2127595b8
commit
fef029e98e
@ -202,16 +202,18 @@ try {
|
||||
|
||||
```python async
|
||||
try:
|
||||
await page.wait_for_selector(".foo")
|
||||
await page.wait_for_selector(".foo")
|
||||
except TimeoutError as e:
|
||||
# do something if this is a timeout.
|
||||
pass
|
||||
# do something if this is a timeout.
|
||||
```
|
||||
|
||||
```python sync
|
||||
try:
|
||||
page.wait_for_selector(".foo")
|
||||
page.wait_for_selector(".foo")
|
||||
except TimeoutError as e:
|
||||
# do something if this is a timeout.
|
||||
pass
|
||||
# do something if this is a timeout.
|
||||
```
|
||||
|
||||
## property: Playwright.firefox
|
||||
@ -277,15 +279,15 @@ process inherits environment variables of the Playwright process.
|
||||
Terminates this instance of Playwright in case it was created bypassing the Python context manager. This is useful in REPL applications.
|
||||
|
||||
```py
|
||||
>>> from playwright.sync_api import sync_playwright
|
||||
from playwright.sync_api import sync_playwright
|
||||
|
||||
>>> playwright = sync_playwright().start()
|
||||
playwright = sync_playwright().start()
|
||||
|
||||
>>> browser = playwright.chromium.launch()
|
||||
>>> page = browser.new_page()
|
||||
>>> page.goto("https://playwright.dev/")
|
||||
>>> page.screenshot(path="example.png")
|
||||
>>> browser.close()
|
||||
browser = playwright.chromium.launch()
|
||||
page = browser.new_page()
|
||||
page.goto("https://playwright.dev/")
|
||||
page.screenshot(path="example.png")
|
||||
browser.close()
|
||||
|
||||
>>> playwright.stop()
|
||||
playwright.stop()
|
||||
```
|
||||
|
@ -1667,7 +1667,7 @@ The value might include some "tokens" that will be replaced with actual values d
|
||||
|
||||
Consider the following file structure:
|
||||
|
||||
```
|
||||
```txt
|
||||
playwright.config.ts
|
||||
tests/
|
||||
└── page/
|
||||
|
@ -16,8 +16,7 @@ Using a canary release in production might seem risky, but in practice, it's not
|
||||
A canary release passes all automated tests and is used to test e.g. the HTML report, Trace Viewer, or Playwright Inspector with end-to-end tests.
|
||||
|
||||
:::
|
||||
|
||||
```
|
||||
```txt
|
||||
npm install -D @playwright/test@next
|
||||
```
|
||||
|
||||
@ -33,7 +32,7 @@ You can see on [npm](https://www.npmjs.com/package/@playwright/test?activeTab=ve
|
||||
|
||||
## Using a Canary Release
|
||||
|
||||
```
|
||||
```txt
|
||||
npm install -D @playwright/test@next
|
||||
```
|
||||
|
||||
|
@ -15,7 +15,7 @@ const { chromium } = require('playwright');
|
||||
(async () => {
|
||||
const pathToExtension = require('path').join(__dirname, 'my-extension');
|
||||
const userDataDir = '/tmp/test-user-data-dir';
|
||||
const browserContext = await chromium.launchPersistentContext(userDataDir,{
|
||||
const browserContext = await chromium.launchPersistentContext(userDataDir, {
|
||||
headless: false,
|
||||
args: [
|
||||
`--disable-extensions-except=${pathToExtension}`,
|
||||
|
@ -138,13 +138,13 @@ Browser builds for Firefox and WebKit are built for the [glibc](https://en.wikip
|
||||
|
||||
Use [`//utils/docker/build.sh`](https://github.com/microsoft/playwright/blob/main/utils/docker/build.sh) to build the image.
|
||||
|
||||
```
|
||||
```txt
|
||||
./utils/docker/build.sh jammy playwright:localbuild-jammy
|
||||
```
|
||||
|
||||
The image will be tagged as `playwright:localbuild-jammy` and could be run as:
|
||||
|
||||
```
|
||||
```txt
|
||||
docker run --rm -it playwright:localbuild /bin/bash
|
||||
```
|
||||
|
||||
|
@ -453,7 +453,7 @@ await page.GetByRole(AriaRole.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:
|
||||
|
||||
```
|
||||
```txt
|
||||
Backquote, Minus, Equal, Backslash, Backspace, Tab, Delete, Escape,
|
||||
ArrowDown, End, Enter, Home, Insert, PageDown, PageUp, ArrowRight,
|
||||
ArrowUp, F1 - F12, Digit0 - Digit9, KeyA - KeyZ, etc.
|
||||
|
@ -92,16 +92,16 @@ python
|
||||
and then launch Playwright within it for quick experimentation:
|
||||
|
||||
```py
|
||||
>>> from playwright.sync_api import sync_playwright
|
||||
>>> playwright = sync_playwright().start()
|
||||
from playwright.sync_api import sync_playwright
|
||||
playwright = sync_playwright().start()
|
||||
# Use playwright.chromium, playwright.firefox or playwright.webkit
|
||||
# Pass headless=False to launch() to see the browser UI
|
||||
>>> browser = playwright.chromium.launch()
|
||||
>>> page = browser.new_page()
|
||||
>>> page.goto("https://playwright.dev/")
|
||||
>>> page.screenshot(path="example.png")
|
||||
>>> browser.close()
|
||||
>>> playwright.stop()
|
||||
browser = playwright.chromium.launch()
|
||||
page = browser.new_page()
|
||||
page.goto("https://playwright.dev/")
|
||||
page.screenshot(path="example.png")
|
||||
browser.close()
|
||||
playwright.stop()
|
||||
```
|
||||
|
||||
Async REPL such as `asyncio` REPL:
|
||||
@ -111,14 +111,14 @@ python -m asyncio
|
||||
```
|
||||
|
||||
```py
|
||||
>>> from playwright.async_api import async_playwright
|
||||
>>> playwright = await async_playwright().start()
|
||||
>>> browser = await playwright.chromium.launch()
|
||||
>>> page = await browser.new_page()
|
||||
>>> await page.goto("https://playwright.dev/")
|
||||
>>> await page.screenshot(path="example.png")
|
||||
>>> await browser.close()
|
||||
>>> await playwright.stop()
|
||||
from playwright.async_api import async_playwright
|
||||
playwright = await async_playwright().start()
|
||||
browser = await playwright.chromium.launch()
|
||||
page = await browser.new_page()
|
||||
await page.goto("https://playwright.dev/")
|
||||
await page.screenshot(path="example.png")
|
||||
await browser.close()
|
||||
await playwright.stop()
|
||||
```
|
||||
|
||||
## Pyinstaller
|
||||
|
@ -15,13 +15,13 @@ The following code will intercept all the calls to `*/**/api/v1/fruits` and will
|
||||
```js
|
||||
test("mocks a fruit and doesn't call api", async ({ page }) => {
|
||||
// Mock the api call before navigating
|
||||
await page.route('*/**/api/v1/fruits', async (route) => {
|
||||
await page.route('*/**/api/v1/fruits', async route => {
|
||||
const json = [{ name: 'Strawberry', id: 21 }];
|
||||
await route.fulfill({ json });
|
||||
});
|
||||
// Go to the page
|
||||
await page.goto('https://demo.playwright.dev/api-mocking');
|
||||
|
||||
|
||||
// Assert that the Strawberry fruit is visible
|
||||
await expect(page.getByText('Strawberry')).toBeVisible();
|
||||
});
|
||||
@ -115,7 +115,7 @@ In the example below we intercept the call to the fruit API and add a new fruit
|
||||
```js
|
||||
test('gets the json from api and adds a new fruit', async ({ page }) => {
|
||||
// Get the response and add to it
|
||||
await page.route('*/**/api/v1/fruits', async (route) => {
|
||||
await page.route('*/**/api/v1/fruits', async route => {
|
||||
const response = await route.fetch();
|
||||
const json = await response.json();
|
||||
json.push({ name: 'Playwright', id: 100 });
|
||||
@ -188,7 +188,7 @@ await page.RouteAsync("*/**/api/v1/fruits", async (route) => {
|
||||
await page.GotoAsync("https://demo.playwright.dev/api-mocking");
|
||||
|
||||
// Assert that the Strawberry fruit is visible
|
||||
await Expect(page.GetByTextAsync("Playwright", new() { Exact: true })).ToBeVisibleAsync();
|
||||
await Expect(page.GetByTextAsync("Playwright", new () { Exact = true })).ToBeVisibleAsync();
|
||||
```
|
||||
|
||||
```java
|
||||
@ -265,11 +265,9 @@ def records_or_updates_the_har_file(page: Page):
|
||||
|
||||
```csharp
|
||||
// Get the response from the HAR file
|
||||
await page.RouteFromHARAsync("./hars/fruit.har", new (){
|
||||
{
|
||||
Url = "*/**/api/v1/fruits",
|
||||
Update = true,
|
||||
}
|
||||
await page.RouteFromHARAsync("./hars/fruit.har", new () {
|
||||
Url = "*/**/api/v1/fruits",
|
||||
Update = true,
|
||||
});
|
||||
|
||||
// Go to the page
|
||||
@ -289,7 +287,7 @@ page.goto("https://demo.playwright.dev/api-mocking");
|
||||
|
||||
### Modifying a HAR file
|
||||
|
||||
Once you have recorded a HAR file you can modify it by opening the hashed .txt file inside your 'hars' folder and editing the JSON. This file should be committed to your source control. Anytime you run this test with `update: true` it will update your HAR file with the request from the API.
|
||||
Once you have recorded a HAR file you can modify it by opening the hashed .txt file inside your 'hars' folder and editing the JSON. This file should be committed to your source control. Anytime you run this test with `update: true` it will update your HAR file with the request from the API.
|
||||
|
||||
```json
|
||||
[
|
||||
|
@ -894,9 +894,11 @@ We recommend [chaining locators](./locators.md#chaining-locators) instead.
|
||||
Selectors defined as `engine=body` or in short-form can be combined with the `>>` token, e.g. `selector1 >> selector2 >> selectors3`. When selectors are chained, the next one is queried relative to the previous one's result.
|
||||
|
||||
For example,
|
||||
```
|
||||
|
||||
```txt
|
||||
css=article >> css=.bar > .baz >> css=span[attr=value]
|
||||
```
|
||||
|
||||
is equivalent to
|
||||
|
||||
```js browser
|
||||
|
@ -305,7 +305,7 @@ All the same methods are also available on [Locator], [FrameLocator] and [Frame]
|
||||
|
||||
- [`method: LocatorAssertions.toHaveAttribute`] with an empty value does not match missing attribute anymore. For example, the following snippet will succeed when `button` **does not** have a `disabled` attribute.
|
||||
|
||||
```js
|
||||
```java
|
||||
assertThat(page.getByRole(AriaRole.BUTTON)).hasAttribute("disabled", "");
|
||||
```
|
||||
|
||||
@ -340,7 +340,7 @@ This version was also tested against the following stable channels:
|
||||
A bunch of Playwright APIs already support the `setWaitUntil(WaitUntilState.DOMCONTENTLOADED)` option.
|
||||
For example:
|
||||
|
||||
```js
|
||||
```java
|
||||
page.navigate("https://playwright.dev", new Page.NavigateOptions().setWaitUntil(WaitUntilState.DOMCONTENTLOADED));
|
||||
```
|
||||
|
||||
|
@ -691,11 +691,11 @@ This version was also tested against the following stable channels:
|
||||
|
||||
```ts
|
||||
test('should work', async ({ page }) => {
|
||||
const pageTitle = await test.step('get title', async () => {
|
||||
await page.goto('https://playwright.dev');
|
||||
return await page.title();
|
||||
});
|
||||
console.log(pageTitle);
|
||||
const pageTitle = await test.step('get title', async () => {
|
||||
await page.goto('https://playwright.dev');
|
||||
return await page.title();
|
||||
});
|
||||
console.log(pageTitle);
|
||||
});
|
||||
```
|
||||
|
||||
@ -930,7 +930,7 @@ Read more about [component testing with Playwright](./test-components).
|
||||
use: {
|
||||
serviceWorkers: 'block',
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
* Using `.zip` path for `recordHar` context option automatically zips the resulting HAR:
|
||||
```ts
|
||||
|
@ -300,7 +300,7 @@ All the same methods are also available on [Locator], [FrameLocator] and [Frame]
|
||||
|
||||
- [`method: LocatorAssertions.toHaveAttribute`] with an empty value does not match missing attribute anymore. For example, the following snippet will succeed when `button` **does not** have a `disabled` attribute.
|
||||
|
||||
```js
|
||||
```python
|
||||
expect(page.get_by_role("button")).to_have_attribute("disabled", "")
|
||||
```
|
||||
|
||||
|
@ -33,30 +33,6 @@ await page.goto('/example-with-a-service-worker.html');
|
||||
const serviceworker = await serviceWorkerPromise;
|
||||
```
|
||||
|
||||
```python async
|
||||
async with context.expect_event("serviceworker") as event_info:
|
||||
await page.goto('/example-with-a-service-worker.html')
|
||||
serviceworker = await event_info.value
|
||||
```
|
||||
|
||||
```python sync
|
||||
with context.expect_event("serviceworker") as event_info:
|
||||
page.goto('/example-with-a-service-worker.html')
|
||||
serviceworker = event_info.value
|
||||
```
|
||||
|
||||
```csharp
|
||||
var waitForServiceWorkerTask = page.WaitForServiceWorkerAsync();
|
||||
await page.GotoAsync('/example-with-a-service-worker.html');
|
||||
var serviceworker = await waitForServiceWorkerTask;
|
||||
```
|
||||
|
||||
```java
|
||||
Worker serviceWorker = page.waitForRequest(() -> {
|
||||
page.navigate('/example-with-a-service-worker.html');
|
||||
});
|
||||
```
|
||||
|
||||
[`event: BrowserContext.serviceWorker`] is fired ***before*** the Service Worker's main script has been evaluated, so ***before*** calling service[`method: Worker.evaluate`] you should wait on its activation.
|
||||
|
||||
There are more idiomatic methods of waiting for a Service Worker to be activated, but the following is an implementation agnostic method:
|
||||
@ -70,44 +46,6 @@ await page.evaluate(async () => {
|
||||
});
|
||||
```
|
||||
|
||||
```python async
|
||||
await page.evaluate("""async () => {
|
||||
const registration = await window.navigator.serviceWorker.getRegistration();
|
||||
if (registration.active?.state === 'activated')
|
||||
return;
|
||||
await new Promise(res => window.navigator.serviceWorker.addEventListener('controllerchange', res));
|
||||
}""")
|
||||
```
|
||||
|
||||
```python sync
|
||||
page.evaluate("""async () => {
|
||||
const registration = await window.navigator.serviceWorker.getRegistration();
|
||||
if (registration.active?.state === 'activated')
|
||||
return;
|
||||
await new Promise(res => window.navigator.serviceWorker.addEventListener('controllerchange', res));
|
||||
}""")
|
||||
```
|
||||
|
||||
```csharp
|
||||
await page.EvaluateAsync(@"async () => {
|
||||
const registration = await window.navigator.serviceWorker.getRegistration();
|
||||
if (registration.active?.state === 'activated')
|
||||
return;
|
||||
await new Promise(res => window.navigator.serviceWorker.addEventListener('controllerchange', res));
|
||||
}");
|
||||
```
|
||||
|
||||
```java
|
||||
page.evaluate(
|
||||
"async () => {"
|
||||
" const registration = await window.navigator.serviceWorker.getRegistration();" +
|
||||
" if (registration.active?.state === 'activated')" +
|
||||
" return;" +
|
||||
" await new Promise(res => window.navigator.serviceWorker.addEventListener('controllerchange', res));" +
|
||||
"}"
|
||||
)
|
||||
```
|
||||
|
||||
### Network Events and Routing
|
||||
|
||||
Any network request made by the **Service Worker** will have:
|
||||
@ -248,34 +186,6 @@ await page.evaluate(() => fetch('/tracker.js'));
|
||||
await page.evaluate(() => fetch('/fallthrough.txt'));
|
||||
```
|
||||
|
||||
```python async
|
||||
await page.evaluate("fetch('/addressbook.json')")
|
||||
await page.evaluate("fetch('/foo')")
|
||||
await page.evaluate("fetch('/tracker.js')")
|
||||
await page.evaluate("fetch('/fallthrough.txt')")
|
||||
```
|
||||
|
||||
```python sync
|
||||
page.evaluate("fetch('/addressbook.json')")
|
||||
page.evaluate("fetch('/foo')")
|
||||
page.evaluate("fetch('/tracker.js')")
|
||||
page.evaluate("fetch('/fallthrough.txt')")
|
||||
```
|
||||
|
||||
```csharp
|
||||
await page.EvaluateAsync("fetch('/addressbook.json')");
|
||||
await page.EvaluateAsync("fetch('/foo')");
|
||||
await page.EvaluateAsync("fetch('/tracker.js')");
|
||||
await page.EvaluateAsync("fetch('/fallthrough.txt')");
|
||||
```
|
||||
|
||||
```java
|
||||
page.evaluate("fetch('/addressbook.json')")
|
||||
page.evaluate("fetch('/foo')")
|
||||
page.evaluate("fetch('/tracker.js')")
|
||||
page.evaluate("fetch('/fallthrough.txt')")
|
||||
```
|
||||
|
||||
The following Request/Response events would be emitted:
|
||||
|
||||
| Event | Owner | URL | Routed | [`method: Response.fromServiceWorker`] |
|
||||
@ -313,56 +223,6 @@ await context.route('**', async route => {
|
||||
});
|
||||
```
|
||||
|
||||
```python async
|
||||
async def handle(route: Route):
|
||||
if route.request.service_worker:
|
||||
# NB: calling route.request.frame here would THROW
|
||||
await route.fulfill(content_type='text/plain', status=200, body='from sw');
|
||||
else:
|
||||
await route.continue_()
|
||||
await context.route('**', handle)
|
||||
```
|
||||
|
||||
```python sync
|
||||
def handle(route: Route):
|
||||
if route.request.service_worker:
|
||||
# NB: calling route.request.frame here would THROW
|
||||
route.fulfill(content_type='text/plain', status=200, body='from sw');
|
||||
else:
|
||||
route.continue_()
|
||||
context.route('**', handle)
|
||||
```
|
||||
|
||||
```csharp
|
||||
await context.RouteAsync("**", async route => {
|
||||
if (route.request().serviceWorker() != null) {
|
||||
// NB: calling route.request.frame here would THROW
|
||||
await route.FulfillAsync(new ()
|
||||
{
|
||||
ContentType = "text/plain",
|
||||
Status = 200,
|
||||
Body = "from sw"
|
||||
});
|
||||
} else {
|
||||
await route.Continue()Async();
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
```java
|
||||
browserContext.route("**", route -> {
|
||||
if (route.request()) {
|
||||
// calling route.request().frame() here would THROW
|
||||
route.fulfill(new Route.FulfillOptions()
|
||||
.setStatus(200)
|
||||
.setContentType("text/plain")
|
||||
.setBody("from sw"));
|
||||
} else {
|
||||
route.resume();
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Known Limitations
|
||||
|
||||
Requests for updated Service Worker main script code currently cannot be routed (https://github.com/microsoft/playwright/issues/14711).
|
||||
|
@ -498,7 +498,7 @@ await mount(app);
|
||||
|
||||
results in
|
||||
|
||||
```
|
||||
```txt
|
||||
undefined: TypeError: Cannot read properties of undefined (reading 'map')
|
||||
```
|
||||
|
||||
|
@ -40,6 +40,7 @@ This plugin configures Playwright-specific [fixtures for pytest](https://docs.py
|
||||
|
||||
```py
|
||||
def test_my_app_is_working(fixture_name):
|
||||
pass
|
||||
# Test using fixture_name
|
||||
# ...
|
||||
```
|
||||
|
@ -15,7 +15,8 @@ test('example test', async ({ page }) => {
|
||||
```
|
||||
|
||||
When you run above for the first time, test runner will say:
|
||||
```
|
||||
|
||||
```txt
|
||||
Error: A snapshot doesn't exist at example.spec.ts-snapshots/example-test-1-chromium-darwin.png, writing actual.
|
||||
```
|
||||
|
||||
|
@ -16,7 +16,7 @@ Playwright Test enforces a timeout for each test, 30 seconds by default. Time sp
|
||||
|
||||
Timed out test produces the following error:
|
||||
|
||||
```
|
||||
```txt
|
||||
example.spec.ts:3:1 › basic test ===========================
|
||||
|
||||
Timeout of 30000ms exceeded.
|
||||
@ -86,7 +86,7 @@ API reference: [`method: TestInfo.setTimeout`].
|
||||
|
||||
Web-first assertions like `expect(locator).toHaveText()` have a separate timeout, 5 seconds by default. Assertion timeout is unrelated to the test timeout. It produces the following error:
|
||||
|
||||
```
|
||||
```txt
|
||||
example.spec.ts:3:1 › basic test ===========================
|
||||
|
||||
Error: expect(received).toHaveText(expected)
|
||||
@ -114,7 +114,7 @@ export default defineConfig({
|
||||
|
||||
Playwright Test supports a timeout for the whole test run. This prevents excess resource usage when everything went wrong. There is no default global timeout, but you can set a reasonable one in the config, for example one hour. Global timeout produces the following error:
|
||||
|
||||
```
|
||||
```txt
|
||||
Running 1000 tests using 10 workers
|
||||
|
||||
514 skipped
|
||||
|
@ -11,7 +11,7 @@ Playwright will pick up `tsconfig.json` for each source file it loads. Note that
|
||||
|
||||
We recommend setting up a separate `tsconfig.json` in the tests directory so that you can change some preferences specifically for the tests. Here is an example directory structure.
|
||||
|
||||
```
|
||||
```txt
|
||||
src/
|
||||
source.ts
|
||||
|
||||
|
4
packages/playwright-test/types/test.d.ts
vendored
4
packages/playwright-test/types/test.d.ts
vendored
@ -1151,7 +1151,7 @@ interface TestConfig {
|
||||
*
|
||||
* Consider the following file structure:
|
||||
*
|
||||
* ```
|
||||
* ```txt
|
||||
* playwright.config.ts
|
||||
* tests/
|
||||
* └── page/
|
||||
@ -6324,7 +6324,7 @@ interface TestProject {
|
||||
*
|
||||
* Consider the following file structure:
|
||||
*
|
||||
* ```
|
||||
* ```txt
|
||||
* playwright.config.ts
|
||||
* tests/
|
||||
* └── page/
|
||||
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//@ts-check
|
||||
// @ts-check
|
||||
const path = require('path');
|
||||
const toKebabCase = require('lodash/kebabCase')
|
||||
const devices = require('../../packages/playwright-core/lib/server/deviceDescriptors');
|
||||
@ -360,7 +360,7 @@ class TypesGenerator {
|
||||
flavor = match[3];
|
||||
line = line.replace(/tab=js-\w+/, '').replace(/```\w+/, '```ts');
|
||||
}
|
||||
skipExample = !["html", "yml", "bash", "js"].includes(lang) || flavor !== 'ts';
|
||||
skipExample = !["html", "yml", "bash", "js", "txt"].includes(lang) || flavor !== 'ts';
|
||||
} else if (skipExample && line.trim().startsWith('```')) {
|
||||
skipExample = false;
|
||||
continue;
|
||||
|
Loading…
x
Reference in New Issue
Block a user