docs: code snippet alignments (#23959)

This commit is contained in:
Max Schmitt 2023-06-29 18:26:19 +02:00 committed by GitHub
parent c2127595b8
commit fef029e98e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 69 additions and 206 deletions

View File

@ -202,16 +202,18 @@ try {
```python async ```python async
try: try:
await page.wait_for_selector(".foo") await page.wait_for_selector(".foo")
except TimeoutError as e: except TimeoutError as e:
# do something if this is a timeout. pass
# do something if this is a timeout.
``` ```
```python sync ```python sync
try: try:
page.wait_for_selector(".foo") page.wait_for_selector(".foo")
except TimeoutError as e: except TimeoutError as e:
# do something if this is a timeout. pass
# do something if this is a timeout.
``` ```
## property: Playwright.firefox ## 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. Terminates this instance of Playwright in case it was created bypassing the Python context manager. This is useful in REPL applications.
```py ```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() browser = playwright.chromium.launch()
>>> page = browser.new_page() page = browser.new_page()
>>> page.goto("https://playwright.dev/") page.goto("https://playwright.dev/")
>>> page.screenshot(path="example.png") page.screenshot(path="example.png")
>>> browser.close() browser.close()
>>> playwright.stop() playwright.stop()
``` ```

View File

@ -1667,7 +1667,7 @@ The value might include some "tokens" that will be replaced with actual values d
Consider the following file structure: Consider the following file structure:
``` ```txt
playwright.config.ts playwright.config.ts
tests/ tests/
└── page/ └── page/

View File

@ -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. 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 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 ## Using a Canary Release
``` ```txt
npm install -D @playwright/test@next npm install -D @playwright/test@next
``` ```

View File

@ -15,7 +15,7 @@ const { chromium } = require('playwright');
(async () => { (async () => {
const pathToExtension = require('path').join(__dirname, 'my-extension'); const pathToExtension = require('path').join(__dirname, 'my-extension');
const userDataDir = '/tmp/test-user-data-dir'; const userDataDir = '/tmp/test-user-data-dir';
const browserContext = await chromium.launchPersistentContext(userDataDir,{ const browserContext = await chromium.launchPersistentContext(userDataDir, {
headless: false, headless: false,
args: [ args: [
`--disable-extensions-except=${pathToExtension}`, `--disable-extensions-except=${pathToExtension}`,

View File

@ -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. 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 ./utils/docker/build.sh jammy playwright:localbuild-jammy
``` ```
The image will be tagged as `playwright:localbuild-jammy` and could be run as: The image will be tagged as `playwright:localbuild-jammy` and could be run as:
``` ```txt
docker run --rm -it playwright:localbuild /bin/bash docker run --rm -it playwright:localbuild /bin/bash
``` ```

View File

@ -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: 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, Backquote, Minus, Equal, Backslash, Backspace, Tab, Delete, Escape,
ArrowDown, End, Enter, Home, Insert, PageDown, PageUp, ArrowRight, ArrowDown, End, Enter, Home, Insert, PageDown, PageUp, ArrowRight,
ArrowUp, F1 - F12, Digit0 - Digit9, KeyA - KeyZ, etc. ArrowUp, F1 - F12, Digit0 - Digit9, KeyA - KeyZ, etc.

View File

@ -92,16 +92,16 @@ python
and then launch Playwright within it for quick experimentation: and then launch Playwright within it for quick experimentation:
```py ```py
>>> from playwright.sync_api import sync_playwright from playwright.sync_api import sync_playwright
>>> playwright = sync_playwright().start() playwright = sync_playwright().start()
# Use playwright.chromium, playwright.firefox or playwright.webkit # Use playwright.chromium, playwright.firefox or playwright.webkit
# Pass headless=False to launch() to see the browser UI # Pass headless=False to launch() to see the browser UI
>>> browser = playwright.chromium.launch() browser = playwright.chromium.launch()
>>> page = browser.new_page() page = browser.new_page()
>>> page.goto("https://playwright.dev/") page.goto("https://playwright.dev/")
>>> page.screenshot(path="example.png") page.screenshot(path="example.png")
>>> browser.close() browser.close()
>>> playwright.stop() playwright.stop()
``` ```
Async REPL such as `asyncio` REPL: Async REPL such as `asyncio` REPL:
@ -111,14 +111,14 @@ python -m asyncio
``` ```
```py ```py
>>> from playwright.async_api import async_playwright from playwright.async_api import async_playwright
>>> playwright = await async_playwright().start() playwright = await async_playwright().start()
>>> browser = await playwright.chromium.launch() browser = await playwright.chromium.launch()
>>> page = await browser.new_page() page = await browser.new_page()
>>> await page.goto("https://playwright.dev/") await page.goto("https://playwright.dev/")
>>> await page.screenshot(path="example.png") await page.screenshot(path="example.png")
>>> await browser.close() await browser.close()
>>> await playwright.stop() await playwright.stop()
``` ```
## Pyinstaller ## Pyinstaller

View File

@ -15,13 +15,13 @@ The following code will intercept all the calls to `*/**/api/v1/fruits` and will
```js ```js
test("mocks a fruit and doesn't call api", async ({ page }) => { test("mocks a fruit and doesn't call api", async ({ page }) => {
// Mock the api call before navigating // 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 }]; const json = [{ name: 'Strawberry', id: 21 }];
await route.fulfill({ json }); await route.fulfill({ json });
}); });
// Go to the page // Go to the page
await page.goto('https://demo.playwright.dev/api-mocking'); await page.goto('https://demo.playwright.dev/api-mocking');
// Assert that the Strawberry fruit is visible // Assert that the Strawberry fruit is visible
await expect(page.getByText('Strawberry')).toBeVisible(); 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 ```js
test('gets the json from api and adds a new fruit', async ({ page }) => { test('gets the json from api and adds a new fruit', async ({ page }) => {
// Get the response and add to it // 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 response = await route.fetch();
const json = await response.json(); const json = await response.json();
json.push({ name: 'Playwright', id: 100 }); 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"); await page.GotoAsync("https://demo.playwright.dev/api-mocking");
// Assert that the Strawberry fruit is visible // 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 ```java
@ -265,11 +265,9 @@ def records_or_updates_the_har_file(page: Page):
```csharp ```csharp
// Get the response from the HAR file // Get the response from the HAR file
await page.RouteFromHARAsync("./hars/fruit.har", new (){ await page.RouteFromHARAsync("./hars/fruit.har", new () {
{ Url = "*/**/api/v1/fruits",
Url = "*/**/api/v1/fruits", Update = true,
Update = true,
}
}); });
// Go to the page // Go to the page
@ -289,7 +287,7 @@ page.goto("https://demo.playwright.dev/api-mocking");
### Modifying a HAR file ### 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 ```json
[ [

View File

@ -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. 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, For example,
```
```txt
css=article >> css=.bar > .baz >> css=span[attr=value] css=article >> css=.bar > .baz >> css=span[attr=value]
``` ```
is equivalent to is equivalent to
```js browser ```js browser

View File

@ -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. - [`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", ""); 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. A bunch of Playwright APIs already support the `setWaitUntil(WaitUntilState.DOMCONTENTLOADED)` option.
For example: For example:
```js ```java
page.navigate("https://playwright.dev", new Page.NavigateOptions().setWaitUntil(WaitUntilState.DOMCONTENTLOADED)); page.navigate("https://playwright.dev", new Page.NavigateOptions().setWaitUntil(WaitUntilState.DOMCONTENTLOADED));
``` ```

View File

@ -691,11 +691,11 @@ This version was also tested against the following stable channels:
```ts ```ts
test('should work', async ({ page }) => { test('should work', async ({ page }) => {
const pageTitle = await test.step('get title', async () => { const pageTitle = await test.step('get title', async () => {
await page.goto('https://playwright.dev'); await page.goto('https://playwright.dev');
return await page.title(); return await page.title();
}); });
console.log(pageTitle); console.log(pageTitle);
}); });
``` ```
@ -930,7 +930,7 @@ Read more about [component testing with Playwright](./test-components).
use: { use: {
serviceWorkers: 'block', serviceWorkers: 'block',
} }
} };
``` ```
* Using `.zip` path for `recordHar` context option automatically zips the resulting HAR: * Using `.zip` path for `recordHar` context option automatically zips the resulting HAR:
```ts ```ts

View File

@ -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. - [`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", "") expect(page.get_by_role("button")).to_have_attribute("disabled", "")
``` ```

View File

@ -33,30 +33,6 @@ await page.goto('/example-with-a-service-worker.html');
const serviceworker = await serviceWorkerPromise; 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. [`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: 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 ### Network Events and Routing
Any network request made by the **Service Worker** will have: 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')); 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: The following Request/Response events would be emitted:
| Event | Owner | URL | Routed | [`method: Response.fromServiceWorker`] | | 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 ## Known Limitations
Requests for updated Service Worker main script code currently cannot be routed (https://github.com/microsoft/playwright/issues/14711). Requests for updated Service Worker main script code currently cannot be routed (https://github.com/microsoft/playwright/issues/14711).

View File

@ -498,7 +498,7 @@ await mount(app);
results in results in
``` ```txt
undefined: TypeError: Cannot read properties of undefined (reading 'map') undefined: TypeError: Cannot read properties of undefined (reading 'map')
``` ```

View File

@ -40,6 +40,7 @@ This plugin configures Playwright-specific [fixtures for pytest](https://docs.py
```py ```py
def test_my_app_is_working(fixture_name): def test_my_app_is_working(fixture_name):
pass
# Test using fixture_name # Test using fixture_name
# ... # ...
``` ```

View File

@ -15,7 +15,8 @@ test('example test', async ({ page }) => {
``` ```
When you run above for the first time, test runner will say: 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. Error: A snapshot doesn't exist at example.spec.ts-snapshots/example-test-1-chromium-darwin.png, writing actual.
``` ```

View File

@ -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: Timed out test produces the following error:
``` ```txt
example.spec.ts:3:1 basic test =========================== example.spec.ts:3:1 basic test ===========================
Timeout of 30000ms exceeded. 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: 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 =========================== example.spec.ts:3:1 basic test ===========================
Error: expect(received).toHaveText(expected) 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: 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 Running 1000 tests using 10 workers
514 skipped 514 skipped

View File

@ -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. 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/ src/
source.ts source.ts

View File

@ -1151,7 +1151,7 @@ interface TestConfig {
* *
* Consider the following file structure: * Consider the following file structure:
* *
* ``` * ```txt
* playwright.config.ts * playwright.config.ts
* tests/ * tests/
* page/ * page/
@ -6324,7 +6324,7 @@ interface TestProject {
* *
* Consider the following file structure: * Consider the following file structure:
* *
* ``` * ```txt
* playwright.config.ts * playwright.config.ts
* tests/ * tests/
* page/ * page/

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
//@ts-check // @ts-check
const path = require('path'); const path = require('path');
const toKebabCase = require('lodash/kebabCase') const toKebabCase = require('lodash/kebabCase')
const devices = require('../../packages/playwright-core/lib/server/deviceDescriptors'); const devices = require('../../packages/playwright-core/lib/server/deviceDescriptors');
@ -360,7 +360,7 @@ class TypesGenerator {
flavor = match[3]; flavor = match[3];
line = line.replace(/tab=js-\w+/, '').replace(/```\w+/, '```ts'); 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('```')) { } else if (skipExample && line.trim().startsWith('```')) {
skipExample = false; skipExample = false;
continue; continue;