chore: prepare non-api docs for non-js variants (#4969)
This commit is contained in:
parent
4dbbb47583
commit
7a8214cd95
|
|
@ -124,13 +124,13 @@ Performs action and waits for given `event` to fire. If predicate is provided, i
|
|||
event's value into the `predicate` function and waits for `predicate(event)` to return a truthy value.
|
||||
Will throw an error if the page is closed before the `event` is fired.
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
async with page.expect_event(event_name) as event_info:
|
||||
await page.click("button")
|
||||
value = await event_info.value
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
with page.expect_event(event_name) as event_info:
|
||||
page.click("button")
|
||||
value = event_info.value
|
||||
|
|
@ -148,13 +148,13 @@ Performs action and waits for given `event` to fire. If predicate is provided, i
|
|||
event's value into the `predicate` function and waits for `predicate(event)` to return a truthy value.
|
||||
Will throw an error if browser context is closed before the `event` is fired.
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
async with context.expect_event(event_name) as event_info:
|
||||
await context.click("button")
|
||||
value = await event_info.value
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
with context.expect_event(event_name) as event_info:
|
||||
context.click("button")
|
||||
value = event_info.value
|
||||
|
|
@ -172,13 +172,13 @@ Performs action and waits for given `event` to fire. If predicate is provided, i
|
|||
event's value into the `predicate` function and waits for `predicate(event)` to return a truthy value.
|
||||
Will throw an error if the socket is closed before the `event` is fired.
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
async with ws.expect_event(event_name) as event_info:
|
||||
await ws.click("button")
|
||||
value = await event_info.value
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
with ws.expect_event(event_name) as event_info:
|
||||
ws.click("button")
|
||||
value = event_info.value
|
||||
|
|
@ -195,13 +195,13 @@ value = event_info.value
|
|||
Performs action and waits for the required load state. It resolves when the page reaches a required load state, `load` by default. The navigation must have been committed when this method is called. If current document has
|
||||
already reached the required state, resolves immediately.
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
async with page.expect_load_state():
|
||||
await page.click('button') # Click triggers navigation.
|
||||
# Context manager waits for 'load' event.
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
with page.expect_load_state():
|
||||
page.click('button') # Click triggers navigation.
|
||||
# Context manager waits for 'load' event.
|
||||
|
|
@ -219,13 +219,13 @@ Shortcut for main frame's [`method: Frame.expectLoadState`].
|
|||
Performs action and waits for the required load state. It resolves when the page reaches a required load state, `load` by default. The navigation must have been committed when this method is called. If current document has
|
||||
already reached the required state, resolves immediately.
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
async with frame.expect_load_state():
|
||||
await frame.click('button') # Click triggers navigation.
|
||||
# Context manager waits for 'load' event.
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
with frame.expect_load_state():
|
||||
frame.click('button') # Click triggers navigation.
|
||||
# Context manager waits for 'load' event.
|
||||
|
|
@ -238,7 +238,7 @@ with frame.expect_load_state():
|
|||
* langs: python
|
||||
- returns: <[EventContextManager]>
|
||||
|
||||
Performs action and wait for the next navigation. In case of multiple redirects, the navigation will resolve with
|
||||
Performs action and waits for the next navigation. In case of multiple redirects, the navigation will resolve with
|
||||
the response of the last redirect. In case of navigation to a different anchor or navigation due to History API
|
||||
usage, the navigation will resolve with `null`.
|
||||
|
||||
|
|
@ -246,13 +246,13 @@ This resolves when the page navigates to a new URL or reloads. It is useful for
|
|||
indirectly cause the page to navigate. e.g. The click target has an `onclick` handler that triggers navigation
|
||||
from a `setTimeout`. Consider this example:
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
async with page.expect_navigation():
|
||||
await page.click("a.delayed-navigation") # Clicking the link will indirectly cause a navigation
|
||||
# Context manager waited for the navigation to happen.
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
with page.expect_navigation():
|
||||
page.click("a.delayed-navigation") # Clicking the link will indirectly cause a navigation
|
||||
# Context manager waited for the navigation to happen.
|
||||
|
|
@ -271,7 +271,7 @@ Shortcut for main frame's [`method: Frame.expectNavigation`].
|
|||
* langs: python
|
||||
- returns: <[EventContextManager]>
|
||||
|
||||
Performs action and wait for the next navigation. In case of multiple redirects, the navigation will resolve with
|
||||
Performs action and waits for the next navigation. In case of multiple redirects, the navigation will resolve with
|
||||
the response of the last redirect. In case of navigation to a different anchor or navigation due to History API
|
||||
usage, the navigation will resolve with `null`.
|
||||
|
||||
|
|
@ -279,13 +279,13 @@ This resolves when the page navigates to a new URL or reloads. It is useful for
|
|||
indirectly cause the page to navigate. e.g. The click target has an `onclick` handler that triggers navigation
|
||||
from a `setTimeout`. Consider this example:
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
async with frame.expect_navigation():
|
||||
await frame.click("a.delayed-navigation") # Clicking the link will indirectly cause a navigation
|
||||
# Context manager waited for the navigation to happen.
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
with frame.expect_navigation():
|
||||
frame.click("a.delayed-navigation") # Clicking the link will indirectly cause a navigation
|
||||
# Context manager waited for the navigation to happen.
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ const checked = await page.getAttribute('input', 'checked');
|
|||
assert(checked);
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# Assert text content
|
||||
content = await page.text_content('nav:first-child')
|
||||
assert content == 'home'
|
||||
|
|
@ -53,7 +53,7 @@ checked = await page.get_attribute('input', 'checked')
|
|||
assert checked
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# Assert text content
|
||||
content = page.text_content('nav:first-child')
|
||||
assert content == 'home'
|
||||
|
|
@ -106,7 +106,7 @@ const classNames = await elementHandle.getAttribute('class');
|
|||
assert(classNames.includes('highlighted'));
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# Get the element handle
|
||||
element_handle = page.wait_for_selector('#box')
|
||||
|
||||
|
|
@ -119,7 +119,7 @@ class_names = await element_handle.get_attribute('class')
|
|||
assert 'highlighted' in class_names
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# Get the element handle
|
||||
element_handle = page.wait_for_selector('#box')
|
||||
|
||||
|
|
@ -171,7 +171,7 @@ const length = await page.$$eval('li.selected', (items) => items.length);
|
|||
assert(length === 3);
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# Assert local storage value
|
||||
user_id = page.evaluate("() => window.localStorage.getItem('user_id')")
|
||||
assert user_id
|
||||
|
|
@ -190,7 +190,7 @@ length = await page.eval_on_selector_all('li.selected', '(items) => items.length
|
|||
assert length == 3
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# Assert local storage value
|
||||
user_id = page.evaluate("() => window.localStorage.getItem('user_id')")
|
||||
assert user_id
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ await page.click('text=Submit');
|
|||
// Verify app is logged in
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
page = await context.new_page()
|
||||
await page.goto('https://github.com/login')
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ await page.click('text=Submit')
|
|||
# Verify app is logged in
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
page = context.new_page()
|
||||
page.goto('https://github.com/login')
|
||||
|
||||
|
|
@ -88,7 +88,7 @@ const storageState = JSON.parse(process.env.STORAGE);
|
|||
const context = await browser.newContext({ storageState });
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
import json
|
||||
import os
|
||||
# Save storage state and store as an env variable
|
||||
|
|
@ -100,7 +100,7 @@ storage_state = json.loads(os.environ["STORAGE"])
|
|||
context = await browser.new_context(storage_state=storage_state)
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
import json
|
||||
import os
|
||||
# Save storage state and store as an env variable
|
||||
|
|
@ -134,7 +134,7 @@ await context.addInitScript(storage => {
|
|||
}, sessionStorage);
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
import os
|
||||
# Get session storage and store as env variable
|
||||
session_storage = await page.evaluate("() => JSON.stringify(sessionStorage)")
|
||||
|
|
@ -152,7 +152,7 @@ await context.add_init_script(storage => {
|
|||
}, session_storage)
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
import os
|
||||
# Get session storage and store as env variable
|
||||
session_storage = page.evaluate("() => JSON.stringify(sessionStorage)")
|
||||
|
|
@ -217,7 +217,7 @@ const context = await chromium.launchPersistentContext(userDataDir, { headless:
|
|||
// Execute login steps manually in the browser window
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
import asyncio
|
||||
from playwright import async_playwright
|
||||
|
||||
|
|
@ -230,7 +230,7 @@ async def main():
|
|||
asyncio.get_event_loop().run_until_complete(main())
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
from playwright import sync_playwright
|
||||
|
||||
with sync_playwright() as p:
|
||||
|
|
|
|||
|
|
@ -50,13 +50,13 @@ Suggested configuration
|
|||
});
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
browser = await playwright.chromium.launch(
|
||||
args=['--disable-dev-shm-usage']
|
||||
)
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
browser = playwright.chromium.launch({
|
||||
args=['--disable-dev-shm-usage']
|
||||
})
|
||||
|
|
@ -203,11 +203,11 @@ const { chromium } = require('playwright');
|
|||
const browser = await chromium.launch({ chromiumSandbox: false });
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
browser = await playwright.chromium.launch(chromiumSandbox=False)
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
browser = playwright.chromium.launch(chromiumSandbox=False)
|
||||
```
|
||||
|
||||
|
|
@ -287,7 +287,7 @@ const { chromium } = require('playwright');
|
|||
const browser = await chromium.launch({ headless: false });
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
import asyncio
|
||||
from playwright import async_playwright
|
||||
|
||||
|
|
@ -299,7 +299,7 @@ async def main():
|
|||
asyncio.get_event_loop().run_until_complete(main())
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
from playwright import sync_playwright
|
||||
|
||||
with sync_playwright() as p:
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ const browser = await chromium.launch({ headless: false });
|
|||
await browser.close();
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
import asyncio
|
||||
from playwright import async_playwright
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ async def main():
|
|||
asyncio.get_event_loop().run_until_complete(main())
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
from playwright import sync_playwright
|
||||
|
||||
with sync_playwright() as p:
|
||||
|
|
@ -69,12 +69,12 @@ const browser = await chromium.launch();
|
|||
const context = await browser.newContext();
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
browser = await playwright.chromium.launch()
|
||||
context = await browser.new_context()
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
browser = playwright.chromium.launch()
|
||||
context = browser.new_context()
|
||||
```
|
||||
|
|
@ -95,7 +95,7 @@ const context = await browser.newContext({
|
|||
});
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
import asyncio
|
||||
from playwright import async_playwright
|
||||
|
||||
|
|
@ -116,7 +116,7 @@ async def main():
|
|||
asyncio.get_event_loop().run_until_complete(main())
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
from playwright import sync_playwright
|
||||
|
||||
with sync_playwright() as p:
|
||||
|
|
@ -161,7 +161,7 @@ console.log(page.url());
|
|||
window.location.href = 'https://example.com';
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
page = await context.new_page()
|
||||
|
||||
# Navigate explicitly, similar to entering a URL in the browser.
|
||||
|
|
@ -178,7 +178,7 @@ print(page.url)
|
|||
# window.location.href = 'https://example.com'
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
page = context.new_page()
|
||||
|
||||
# Navigate explicitly, similar to entering a URL in the browser.
|
||||
|
|
@ -219,7 +219,7 @@ const frame = await frameElementHandle.contentFrame();
|
|||
await frame.fill('#username-input', 'John');
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# Get frame using the frame's name attribute
|
||||
frame = page.frame('frame-login')
|
||||
|
||||
|
|
@ -234,7 +234,7 @@ frame = await frame_element_handle.content_frame()
|
|||
await frame.fill('#username-input', 'John')
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# Get frame using the frame's name attribute
|
||||
frame = page.frame('frame-login')
|
||||
|
||||
|
|
@ -274,12 +274,12 @@ Some examples below:
|
|||
await page.click('data-test-id=foo');
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# Using data-test-id= selector engine
|
||||
await page.click('data-test-id=foo')
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# Using data-test-id= selector engine
|
||||
page.click('data-test-id=foo')
|
||||
```
|
||||
|
|
@ -290,13 +290,13 @@ await page.click('div');
|
|||
await page.click('//html/body/div');
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# CSS and XPath selector engines are automatically detected
|
||||
await page.click('div')
|
||||
await page.click('//html/body/div')
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# CSS and XPath selector engines are automatically detected
|
||||
page.click('div')
|
||||
page.click('//html/body/div')
|
||||
|
|
@ -307,12 +307,12 @@ page.click('//html/body/div')
|
|||
await page.click('text=Hello w');
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# Find node by text substring
|
||||
await page.click('text=Hello w')
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# Find node by text substring
|
||||
page.click('text=Hello w')
|
||||
```
|
||||
|
|
@ -323,13 +323,13 @@ await page.click('css=div');
|
|||
await page.click('xpath=//html/body/div');
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# Explicit CSS and XPath notation
|
||||
await page.click('css=div')
|
||||
await page.click('xpath=//html/body/div')
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# Explicit CSS and XPath notation
|
||||
page.click('css=div')
|
||||
page.click('xpath=//html/body/div')
|
||||
|
|
@ -340,12 +340,12 @@ page.click('xpath=//html/body/div')
|
|||
await page.click('css:light=div');
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# Only search light DOM, outside WebComponent shadow DOM:
|
||||
await page.click('css:light=div')
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# Only search light DOM, outside WebComponent shadow DOM:
|
||||
page.click('css:light=div')
|
||||
```
|
||||
|
|
@ -357,12 +357,12 @@ Selectors using the same or different engines can be combined using the `>>` sep
|
|||
await page.click('#free-month-promo >> text=Sign Up');
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# Click an element with text 'Sign Up' inside of a #free-month-promo.
|
||||
await page.click('#free-month-promo >> text=Sign Up')
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# Click an element with text 'Sign Up' inside of a #free-month-promo.
|
||||
page.click('#free-month-promo >> text=Sign Up')
|
||||
```
|
||||
|
|
@ -372,12 +372,12 @@ page.click('#free-month-promo >> text=Sign Up')
|
|||
const sectionText = await page.$eval('*css=section >> text=Selectors', e => e.textContent);
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# Capture textContent of a section that contains an element with text 'Selectors'.
|
||||
section_text = await page.eval_on_selector('*css=section >> text=Selectors', 'e => e.textContent')
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# Capture textContent of a section that contains an element with text 'Selectors'.
|
||||
section_text = page.eval_on_selector('*css=section >> text=Selectors', 'e => e.textContent')
|
||||
```
|
||||
|
|
@ -401,12 +401,12 @@ and [actionable](./actionability.md). For example, click will:
|
|||
await page.fill('#search', 'query');
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# Playwright waits for #search element to be in the DOM
|
||||
await page.fill('#search', 'query')
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# Playwright waits for #search element to be in the DOM
|
||||
page.fill('#search', 'query')
|
||||
```
|
||||
|
|
@ -417,13 +417,13 @@ page.fill('#search', 'query')
|
|||
await page.click('#search');
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# Playwright waits for element to stop animating
|
||||
# and accept clicks.
|
||||
await page.click('#search')
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# Playwright waits for element to stop animating
|
||||
# and accept clicks.
|
||||
page.click('#search')
|
||||
|
|
@ -438,14 +438,14 @@ await page.waitForSelector('#search', { state: 'attached' });
|
|||
await page.waitForSelector('#promo');
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# Wait for #search to appear in the DOM.
|
||||
await page.wait_for_selector('#search', state='attached')
|
||||
# Wait for #promo to become visible, for example with `visibility:visible`.
|
||||
await page.wait_for_selector('#promo')
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# Wait for #search to appear in the DOM.
|
||||
page.wait_for_selector('#search', state='attached')
|
||||
# Wait for #promo to become visible, for example with `visibility:visible`.
|
||||
|
|
@ -461,14 +461,14 @@ await page.waitForSelector('#details', { state: 'hidden' });
|
|||
await page.waitForSelector('#promo', { state: 'detached' });
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# Wait for #details to become hidden, for example with `display:none`.
|
||||
await page.wait_for_selector('#details', state='hidden')
|
||||
# Wait for #promo to be removed from the DOM.
|
||||
await page.wait_for_selector('#promo', state='detached')
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# Wait for #details to become hidden, for example with `display:none`.
|
||||
page.wait_for_selector('#details', state='hidden')
|
||||
# Wait for #promo to be removed from the DOM.
|
||||
|
|
@ -495,11 +495,11 @@ of the web page and bring results back to the Node.js environment. Browser globa
|
|||
const href = await page.evaluate(() => document.location.href);
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
href = await page.evaluate('() => document.location.href')
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
href = page.evaluate('() => document.location.href')
|
||||
```
|
||||
|
||||
|
|
@ -512,14 +512,14 @@ const status = await page.evaluate(async () => {
|
|||
});
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
status = await page.evaluate("""async () => {
|
||||
response = await fetch(location.href)
|
||||
return response.status
|
||||
}""")
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
status = page.evaluate("""async () => {
|
||||
response = fetch(location.href)
|
||||
return response.status
|
||||
|
|
@ -573,7 +573,7 @@ await page.evaluate(
|
|||
{ button1, list: [button2], foo: null });
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# A primitive value.
|
||||
await page.evaluate('num => num', 42)
|
||||
|
||||
|
|
@ -616,7 +616,7 @@ await page.evaluate("""
|
|||
{ 'button1': button1, 'list': [button2], 'foo': None })
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# A primitive value.
|
||||
page.evaluate('num => num', 42)
|
||||
|
||||
|
|
@ -668,7 +668,7 @@ const result = await page.evaluate(data => {
|
|||
}, data);
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
data = { 'text': 'some data', 'value': 1 }
|
||||
# Pass |data| as a parameter.
|
||||
result = await page.evaluate("""data => {
|
||||
|
|
@ -676,7 +676,7 @@ result = await page.evaluate("""data => {
|
|||
}""", data)
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
data = { 'text': 'some data', 'value': 1 }
|
||||
# Pass |data| as a parameter.
|
||||
result = page.evaluate("""data => {
|
||||
|
|
@ -694,7 +694,7 @@ const result = await page.evaluate(() => {
|
|||
});
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
data = { 'text': 'some data', 'value': 1 }
|
||||
result = await page.evaluate("""() => {
|
||||
# There is no |data| in the web page.
|
||||
|
|
@ -702,7 +702,7 @@ result = await page.evaluate("""() => {
|
|||
}""")
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
data = { 'text': 'some data', 'value': 1 }
|
||||
result = page.evaluate("""() => {
|
||||
# There is no |data| in the web page.
|
||||
|
|
@ -744,13 +744,13 @@ const ulElementHandle = await page.$('ul');
|
|||
await ulElementHandle.evaluate(ulElement => getComputedStyle(ulElement).getPropertyValue('display'));
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# The first parameter of the elementHandle.evaluate callback is the element handle points to.
|
||||
ul_element_handle = await page.query_selector('ul')
|
||||
await ul_element_handle.evaluate("ulElement => getComputedStyle(ulElement).getPropertyValue('display')")
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# The first parameter of the elementHandle.evaluate callback is the element handle points to.
|
||||
ul_element_handle = page.query_selector('ul')
|
||||
ul_element_handle.evaluate("ulElement => getComputedStyle(ulElement).getPropertyValue('display')")
|
||||
|
|
@ -764,12 +764,12 @@ const ulElementHandle = await page.$('ul');
|
|||
await page.evaluate(uiElement => getComputedStyle(uiElement).getPropertyValue('display'), uiElement);
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
ul_element_handle = await page.query_selector('ul')
|
||||
await page.evaluate("uiElement => getComputedStyle(uiElement).getPropertyValue('display')", uiElement)
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
ul_element_handle = page.query_selector('ul')
|
||||
page.evaluate("uiElement => getComputedStyle(uiElement).getPropertyValue('display')", uiElement)
|
||||
```
|
||||
|
|
@ -803,7 +803,7 @@ const newLength = await page.evaluate(() => window.myArray.length);
|
|||
await myArrayHandle.dispose();
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# Create a new array in the page, write a reference to it in
|
||||
# window.myArray and get a handle to it.
|
||||
my_array_handle = await page.evaluate_handle("""() => {
|
||||
|
|
@ -830,7 +830,7 @@ new_length = await page.evaluate("() => window.myArray.length")
|
|||
await my_array_handle.dispose()
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# Create a new array in the page, write a reference to it in
|
||||
# window.myArray and get a handle to it.
|
||||
my_array_handle = page.evaluate_handle("""() => {
|
||||
|
|
|
|||
|
|
@ -19,17 +19,17 @@ to slow down execution and follow along while debugging.
|
|||
await chromium.launch({ headless: false, slowMo: 100 }); // or firefox, webkit
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
await chromium.launch(headless=False, slow_mo=100) # or firefox, webkit
|
||||
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
chromium.launch(headless=False, slow_mo=100) # or firefox, webkit
|
||||
|
||||
```
|
||||
|
||||
## Visual Studio Code debugger
|
||||
## Visual Studio Code debugger (Node.JS)
|
||||
|
||||
The VS Code debugger can be used to pause and resume execution of Playwright
|
||||
scripts with breakpoints. The debugger can be configured in two ways.
|
||||
|
|
@ -40,18 +40,13 @@ Setup [`launch.json` configuration](https://code.visualstudio.com/docs/nodejs/no
|
|||
for your Node.js project. Once configured launch the scripts with F5 and use
|
||||
breakpoints.
|
||||
|
||||
### Use the new JavaScript debugger
|
||||
### Use the new JavaScript debugging terminal
|
||||
|
||||
VS Code 1.46+ introduces the new JavaScript debugger behind a feature flag. The
|
||||
new debugger does not require a `launch.json` configuration. To use this:
|
||||
|
||||
1. Enable the preview debugger
|
||||
* Open JSON settings and add `"debug.javascript.usePreview": true`
|
||||
* Open settings UI and enable the `Debug › JavaScript: Use Preview` setting
|
||||
VS Code 1.46+ introduced the new JavaScript debugger that does not require a `launch.json`
|
||||
configuration. To use it:
|
||||
|
||||
1. Set a breakpoint in VS Code
|
||||
* Use the `debugger` keyword or set a breakpoint in the VS Code UI
|
||||
|
||||
1. Run your Node.js script from the terminal
|
||||
|
||||
## Browser Developer Tools
|
||||
|
|
@ -76,12 +71,12 @@ In Chromium, you can also open developer tools through a launch option.
|
|||
await chromium.launch({ devtools: true });
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
await chromium.launch(devtools=True)
|
||||
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
chromium.launch(devtools=True)
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ id: docker
|
|||
title: "Docker"
|
||||
---
|
||||
|
||||
[Dockerfile.bionic](https://github.com/microsoft/playwright/blob/master/utils/docker/Dockerfile.bionic) and [Dockerfile.focal](https://github.com/microsoft/playwright/blob/master/utils/docker/Dockerfile.focal) can be used to run Playwright scripts in Docker environments. These images includes all the dependencies needed to run browsers in a Docker container, including browsers.
|
||||
[Dockerfile.bionic](https://github.com/microsoft/playwright/blob/master/utils/docker/Dockerfile.bionic) and [Dockerfile.focal](https://github.com/microsoft/playwright/blob/master/utils/docker/Dockerfile.focal) can be used to run Playwright scripts in Docker environments. These images includes all the dependencies needed to run browsers in a Docker container, and also include the browsers themselves.
|
||||
|
||||
<!-- TOC -->
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ const context = await browser.newContext({
|
|||
});
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
import asyncio
|
||||
from playwright import async_playwright
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ async def main():
|
|||
asyncio.get_event_loop().run_until_complete(main())
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
from playwright import sync_playwright
|
||||
|
||||
with sync_playwright() as p:
|
||||
|
|
@ -74,13 +74,13 @@ const context = await browser.newContext({
|
|||
});
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
context = await browser.new_context(
|
||||
user_agent='My user agent'
|
||||
)
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
context = browser.new_context(
|
||||
user_agent='My user agent'
|
||||
)
|
||||
|
|
@ -112,7 +112,7 @@ const context = await browser.newContext({
|
|||
});
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# Create context with given viewport
|
||||
context = await browser.new_context(
|
||||
viewport={ 'width': 1280, 'height': 1024 }
|
||||
|
|
@ -128,7 +128,7 @@ context = await browser.new_context(
|
|||
)
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# Create context with given viewport
|
||||
context = browser.new_context(
|
||||
viewport={ 'width': 1280, 'height': 1024 }
|
||||
|
|
@ -161,7 +161,7 @@ const context = await browser.newContext({
|
|||
});
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# Emulate locale and time
|
||||
context = await browser.new_context(
|
||||
locale='de-DE',
|
||||
|
|
@ -169,7 +169,7 @@ context = await browser.new_context(
|
|||
)
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# Emulate locale and time
|
||||
context = browser.new_context(
|
||||
locale='de-DE',
|
||||
|
|
@ -193,13 +193,13 @@ const context = await browser.newContext({
|
|||
});
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
context = await browser.new_context(
|
||||
permissions=['notifications'],
|
||||
)
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
context = browser.new_context(
|
||||
permissions=['notifications'],
|
||||
)
|
||||
|
|
@ -211,11 +211,11 @@ Grant all pages in the existing context access to current location:
|
|||
await context.grantPermissions(['geolocation']);
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
await context.grant_permissions(['geolocation'])
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
context.grant_permissions(['geolocation'])
|
||||
```
|
||||
|
||||
|
|
@ -225,11 +225,11 @@ Grant notifications access from a specific domain:
|
|||
await context.grantPermissions(['notifications'], {origin: 'https://skype.com'} );
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
await context.grant_permissions(['notifications'], origin='https://skype.com')
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
context.grant_permissions(['notifications'], origin='https://skype.com')
|
||||
```
|
||||
|
||||
|
|
@ -239,11 +239,11 @@ Revoke all permissions:
|
|||
await context.clearPermissions();
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
await context.clear_permissions()
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
context.clear_permissions()
|
||||
```
|
||||
|
||||
|
|
@ -265,14 +265,14 @@ const context = await browser.newContext({
|
|||
});
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
context = await browser.new_context(
|
||||
geolocation={"longitude": 48.858455, "latitude": 2.294474},
|
||||
permissions=["geolocation"]
|
||||
)
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
context = browser.new_context(
|
||||
geolocation={"longitude": 48.858455, "latitude": 2.294474},
|
||||
permissions=["geolocation"]
|
||||
|
|
@ -285,11 +285,11 @@ Change the location later:
|
|||
await context.setGeolocation({ longitude: 29.979097, latitude: 31.134256 });
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
await context.set_geolocation({"longitude": 29.979097, "latitude": 31.134256})
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
context.set_geolocation({"longitude": 29.979097, "latitude": 31.134256})
|
||||
```
|
||||
|
||||
|
|
@ -325,7 +325,7 @@ await page.emulateMedia({ colorScheme: 'dark' });
|
|||
await page.emulateMedia({ media: 'print' });
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# Create context with dark mode
|
||||
context = await browser.new_context(
|
||||
color_scheme='dark' # or 'light'
|
||||
|
|
@ -343,7 +343,7 @@ await page.emulate_media(color_scheme='dark')
|
|||
await page.emulate_media(media='print')
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# Create context with dark mode
|
||||
context = browser.new_context(
|
||||
color_scheme='dark' # or 'light'
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ await page.fill('#local', '2020-03-02T05:15');
|
|||
await page.fill('text=First Name', 'Peter');
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# Text input
|
||||
await page.fill('#name', 'Peter')
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ await page.fill('#local', '2020-03-02T05:15')
|
|||
await page.fill('text=First Name', 'Peter')
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# Text input
|
||||
page.fill('#name', 'Peter')
|
||||
|
||||
|
|
@ -83,7 +83,7 @@ await page.uncheck('#subscribe-label');
|
|||
await page.check('text=XL');
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# Check the checkbox
|
||||
await page.check('#agree')
|
||||
|
||||
|
|
@ -94,7 +94,7 @@ await page.uncheck('#subscribe-label')
|
|||
await page.check('text=XL')
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# Check the checkbox
|
||||
page.check('#agree')
|
||||
|
||||
|
|
@ -136,7 +136,7 @@ const option = await page.$('#best-option');
|
|||
await page.selectOption('select#colors', option);
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# Single selection matching the value
|
||||
await page.select_option('select#colors', 'blue')
|
||||
|
||||
|
|
@ -151,7 +151,7 @@ option = await page.query_selector('#best-option')
|
|||
await page.select_option('select#colors', option)
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# Single selection matching the value
|
||||
page.select_option('select#colors', 'blue')
|
||||
|
||||
|
|
@ -198,7 +198,7 @@ await page.hover('#item');
|
|||
await page.click('#item', { position: { x: 0, y: 0} });
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# Generic click
|
||||
await page.click('button#submit')
|
||||
|
||||
|
|
@ -218,7 +218,7 @@ await page.hover('#item')
|
|||
await page.click('#item', position={ 'x': 0, 'y': 0})
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# Generic click
|
||||
page.click('button#submit')
|
||||
|
||||
|
|
@ -255,11 +255,11 @@ Sometimes, apps use non-trivial logic where hovering the element overlays it wit
|
|||
await page.click('button#submit', { force: true });
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
await page.click('button#submit', force=True)
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
page.click('button#submit', force=True)
|
||||
```
|
||||
|
||||
|
|
@ -271,11 +271,11 @@ If you are not interested in testing your app under the real conditions and want
|
|||
await page.dispatchEvent('button#submit', 'click');
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
await page.dispatch_event('button#submit', 'click')
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
page.dispatch_event('button#submit', 'click')
|
||||
```
|
||||
|
||||
|
|
@ -305,12 +305,12 @@ Type into the field character by character, as if it was a user with a real keyb
|
|||
await page.type('#area', 'Hello World!');
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# Type character by character
|
||||
await page.type('#area', 'Hello World!')
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# Type character by character
|
||||
page.type('#area', 'Hello World!')
|
||||
```
|
||||
|
|
@ -341,7 +341,7 @@ await page.press('#name', 'Control+ArrowRight');
|
|||
await page.press('#value', '$');
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# Hit Enter
|
||||
await page.press('#submit', 'Enter')
|
||||
|
||||
|
|
@ -352,7 +352,7 @@ await page.press('#name', 'Control+ArrowRight')
|
|||
await page.press('#value', '$')
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# Hit Enter
|
||||
page.press('#submit', 'Enter')
|
||||
|
||||
|
|
@ -386,7 +386,7 @@ await page.press('#name', 'Shift+A');
|
|||
await page.press('#name', 'Shift+ArrowLeft');
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
# <input id=name>
|
||||
await page.press('#name', 'Shift+A')
|
||||
|
||||
|
|
@ -394,7 +394,7 @@ await page.press('#name', 'Shift+A')
|
|||
await page.press('#name', 'Shift+ArrowLeft')
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
# <input id=name>
|
||||
page.press('#name', 'Shift+A')
|
||||
|
||||
|
|
@ -436,7 +436,7 @@ await page.setInputFiles('input#upload', {
|
|||
});
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
from playwright.async_api import FilePayload
|
||||
# Select one file
|
||||
await page.set_input_files('input#upload', 'myfile.pdf')
|
||||
|
|
@ -454,7 +454,7 @@ await page.set_input_files(
|
|||
)
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
from playwright.sync_api import FilePayload
|
||||
# Select one file
|
||||
page.set_input_files('input#upload', 'myfile.pdf')
|
||||
|
|
@ -494,11 +494,11 @@ For the dynamic pages that handle focus events, you can focus the given element.
|
|||
await page.focus('input#name');
|
||||
```
|
||||
|
||||
```python-async
|
||||
```python async
|
||||
await page.focus('input#name')
|
||||
```
|
||||
|
||||
```python-sync
|
||||
```python sync
|
||||
page.focus('input#name')
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
id: installation
|
||||
title: "Advanced installation"
|
||||
title: "Installation"
|
||||
---
|
||||
|
||||
<!-- TOC -->
|
||||
|
|
|
|||
86
docs/src/intro-python.md
Normal file
86
docs/src/intro-python.md
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
---
|
||||
id: intro-python
|
||||
title: "Getting Started"
|
||||
---
|
||||
|
||||
<!-- TOC -->
|
||||
|
||||
## Installation
|
||||
|
||||
Use pip to install Playwright in your Python project. See [system requirements](#system-requirements).
|
||||
|
||||
```sh
|
||||
pip install playwright
|
||||
python -m playwright install
|
||||
```
|
||||
|
||||
These commands download the Playwright package and install browser binaries for Chromium, Firefox and WebKit. To modify this behavior see [installation parameters](./installation.md).
|
||||
|
||||
## Usage
|
||||
|
||||
Once installed, you can `import` Playwright in a Python script, and launch any of the 3 browsers (`chromium`, `firefox` and `webkit`).
|
||||
|
||||
```python
|
||||
from playwright import sync_playwright
|
||||
|
||||
with sync_playwright() as p:
|
||||
browser = p.chromium.launch()
|
||||
page = browser.new_page()
|
||||
# interact with UI elements, assert values
|
||||
browser.close()
|
||||
```
|
||||
|
||||
Playwright supports two variations of the API: synchronous are asynchronous. If your modern project uses
|
||||
[asyncio](https://docs.python.org/3/library/asyncio.html), you should use async API:
|
||||
|
||||
```python
|
||||
from playwright import async_playwright
|
||||
|
||||
with async_playwright() as p:
|
||||
browser = await p.chromium.launch()
|
||||
page = await browser.new_page()
|
||||
# interact with UI elements, assert values
|
||||
await browser.close()
|
||||
```
|
||||
|
||||
## First script
|
||||
|
||||
In our first script, we will navigate to `whatsmyuseragent.org` and take a screenshot in WebKit.
|
||||
|
||||
```python
|
||||
from playwright import sync_playwright
|
||||
|
||||
with sync_playwright() as p:
|
||||
browser = p.webkit.launch()
|
||||
page = await browser.new_page()
|
||||
page.goto("http://whatsmyuseragent.org/")
|
||||
page.screenshot(path="example.png")
|
||||
browser.close()
|
||||
```
|
||||
|
||||
By default, Playwright runs the browsers in headless mode. To see the browser UI, pass the `headless=False` flag while launching the browser. You can also use `slowMo` to slow down execution. Learn more in the debugging tools [section](./debug.md).
|
||||
|
||||
```python
|
||||
firefox.launch(headless=False, slowMo=50)
|
||||
```
|
||||
|
||||
## Record scripts
|
||||
|
||||
Command Line Interface [CLI](./cli.md) can be used to record user interactions and generate Python code.
|
||||
|
||||
```sh
|
||||
python -m playwright codegen wikipedia.org
|
||||
```
|
||||
|
||||
## System requirements
|
||||
|
||||
Playwright requires Python version 3.7 or above. The browser binaries for Chromium,
|
||||
Firefox and WebKit work across the 3 platforms (Windows, macOS, Linux):
|
||||
|
||||
* **Windows**: Works with Windows and Windows Subsystem for Linux (WSL).
|
||||
* **macOS**: Requires 10.14 or above.
|
||||
* **Linux**: Depending on your Linux distribution, you might need to install additional
|
||||
dependencies to run the browsers.
|
||||
* Firefox requires Ubuntu 18.04+
|
||||
* For Ubuntu 18.04, the additional dependencies are defined in [our Docker image](https://github.com/microsoft/playwright/blob/master/utils/docker/Dockerfile.bionic),
|
||||
which is based on Ubuntu.
|
||||
|
|
@ -54,7 +54,7 @@ const { webkit } = require('playwright');
|
|||
})();
|
||||
```
|
||||
|
||||
By default, Playwright runs the browsers in headless mode. To see the browser UI, pass the `headless: false` flag while launching the browser. You can also use `slowMo` to slow down execution.
|
||||
By default, Playwright runs the browsers in headless mode. To see the browser UI, pass the `headless: false` flag while launching the browser. You can also use `slowMo` to slow down execution. Learn more in the debugging tools [section](./debug.md).
|
||||
|
||||
```js
|
||||
firefox.launch({ headless: false, slowMo: 50 });
|
||||
|
|
@ -62,7 +62,7 @@ firefox.launch({ headless: false, slowMo: 50 });
|
|||
|
||||
## Record scripts
|
||||
|
||||
[Playwright CLI](./cli.md) can be used to record user interactions and generate JavaScript code.
|
||||
Command Line Interface [CLI](./cli.md) can be used to record user interactions and generate JavaScript code.
|
||||
|
||||
```sh
|
||||
npx playwright codegen wikipedia.org
|
||||
|
|
|
|||
210
docs/src/test-runners-python.md
Normal file
210
docs/src/test-runners-python.md
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
---
|
||||
id: test-runners-python
|
||||
title: "Test Runners"
|
||||
---
|
||||
|
||||
You can use our [Pytest integration](https://github.com/microsoft/playwright-pytest) to write end-to-end tests
|
||||
in Python.
|
||||
|
||||
<!-- TOC -->
|
||||
|
||||
## Usage
|
||||
|
||||
```sh
|
||||
pip install pytest-playwright
|
||||
```
|
||||
|
||||
Use the `page` fixture to write a basic test. See [more examples](#examples).
|
||||
|
||||
```py
|
||||
def test_example_is_working(page):
|
||||
page.goto("https://example.com")
|
||||
assert page.innerText('h1') == 'Example Domain'
|
||||
page.click("text=More information")
|
||||
```
|
||||
|
||||
To run your tests, use pytest CLI.
|
||||
|
||||
```sh
|
||||
# Run tests (Chromium and headless by default)
|
||||
pytest
|
||||
|
||||
# Run tests in headful mode
|
||||
pytest --headful
|
||||
|
||||
# Run tests in a different browser (chromium, firefox, webkit)
|
||||
pytest --browser firefox
|
||||
|
||||
# Run tests in multiple browsers
|
||||
pytest --browser chromium --browser webkit
|
||||
```
|
||||
|
||||
If you want to add the CLI arguments automatically without specifying them, you can use the [pytest.ini](https://docs.pytest.org/en/stable/reference.html#ini-options-ref) file:
|
||||
|
||||
```ini
|
||||
# content of pytest.ini
|
||||
[pytest]
|
||||
# Run firefox with UI
|
||||
addopts = --headful --browser firefox
|
||||
|
||||
```
|
||||
|
||||
## Fixtures
|
||||
|
||||
This plugin configures Playwright-specific [fixtures for pytest](https://docs.pytest.org/en/latest/fixture.html). To use these fixtures, use the fixture name as an argument to the test function.
|
||||
|
||||
```py
|
||||
def test_my_app_is_working(fixture_name):
|
||||
# Test using fixture_name
|
||||
# ...
|
||||
```
|
||||
|
||||
**Function scope**: These fixtures are created when requested in a test function and destroyed when the test ends.
|
||||
|
||||
- `context`: New [browser context](https://playwright.dev/#path=docs%2Fcore-concepts.md&q=browser-contexts) for a test.
|
||||
- `page`: New [browser page](https://playwright.dev/#path=docs%2Fcore-concepts.md&q=pages-and-frames) for a test.
|
||||
|
||||
**Session scope**: These fixtures are created when requested in a test function and destroyed when all tests end.
|
||||
|
||||
- `browser`: Browser instance launched by Playwright.
|
||||
- `browser_name`: Browser name as string.
|
||||
- `is_chromium`, `is_webkit`, `is_firefox`: Booleans for the respective browser types.
|
||||
|
||||
**Customizing fixture options**: For `browser` and `context` fixtures, use the the following fixtures to define custom launch options.
|
||||
|
||||
- `browser_type_launch_args`: Override launch arguments for [`browserType.launch()`](https://playwright.dev/#path=docs%2Fapi.md&q=browsertypelaunchoptions). It should return a Dict.
|
||||
- `browser_context_args`: Override the options for [`browser.newContext()`](https://playwright.dev/#path=docs%2Fapi.md&q=browsernewcontextoptions). It should return a Dict.
|
||||
|
||||
## Examples
|
||||
|
||||
### Configure Mypy typings for auto-completion
|
||||
|
||||
```py
|
||||
from playwright.sync_api import Page
|
||||
|
||||
def test_visit_admin_dashboard(page: Page):
|
||||
page.goto("/admin")
|
||||
# ...
|
||||
```
|
||||
|
||||
### Skip test by browser
|
||||
|
||||
```py
|
||||
import pytest
|
||||
|
||||
@pytest.mark.skip_browser("firefox")
|
||||
def test_visit_example(page):
|
||||
page.goto("https://example.com")
|
||||
# ...
|
||||
```
|
||||
|
||||
### Run on a specific browser
|
||||
|
||||
```py
|
||||
import pytest
|
||||
|
||||
@pytest.mark.only_browser("chromium")
|
||||
def test_visit_example(page):
|
||||
page.goto("https://example.com")
|
||||
# ...
|
||||
```
|
||||
|
||||
### Configure base-url
|
||||
|
||||
Start Pytest with the `base-url` argument.
|
||||
|
||||
```sh
|
||||
pytest --base-url http://localhost:8080
|
||||
```
|
||||
|
||||
```py
|
||||
def test_visit_example(page):
|
||||
page.goto("/admin")
|
||||
# -> Will result in http://localhost:8080/admin
|
||||
```
|
||||
|
||||
### Ignore HTTPS errors
|
||||
|
||||
conftest.py
|
||||
|
||||
```py
|
||||
import pytest
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def browser_context_args(browser_context_args):
|
||||
return {
|
||||
**browser_context_args,
|
||||
"ignoreHTTPSErrors": True
|
||||
}
|
||||
```
|
||||
|
||||
### Use custom viewport size
|
||||
|
||||
conftest.py
|
||||
|
||||
```py
|
||||
import pytest
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def browser_context_args(browser_context_args):
|
||||
return {
|
||||
**browser_context_args,
|
||||
"viewport": {
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Device emulation
|
||||
|
||||
conftest.py
|
||||
|
||||
```py
|
||||
import pytest
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def browser_context_args(browser_context_args, playwright):
|
||||
iphone_11 = playwright.devices['iPhone 11 Pro']
|
||||
return {
|
||||
**browser_context_args,
|
||||
**iphone_11,
|
||||
}
|
||||
```
|
||||
|
||||
## Debugging
|
||||
|
||||
### Use with pdb
|
||||
|
||||
Use the `breakpoint()` statement in your test code to pause execution and get a [pdb](https://docs.python.org/3/library/pdb.html) REPL.
|
||||
|
||||
```py
|
||||
def test_bing_is_working(page):
|
||||
page.goto("https://bing.com")
|
||||
breakpoint()
|
||||
# ...
|
||||
```
|
||||
|
||||
### Screenshot on test failure
|
||||
|
||||
You can capture screenshots for failed tests with a [pytest runtest hook](https://docs.pytest.org/en/6.1.0/reference.html?highlight=pytest_runtest_makereport#test-running-runtest-hooks). Add this to your `conftest.py` file.
|
||||
|
||||
Note that this snippet uses `slugify` to convert test names to file paths, which can be installed with `pip install python-slugify`.
|
||||
|
||||
```py
|
||||
# In conftest.py
|
||||
from slugify import slugify
|
||||
from pathlib import Path
|
||||
|
||||
def pytest_runtest_makereport(item, call) -> None:
|
||||
if call.when == "call":
|
||||
if call.excinfo is not None and "page" in item.funcargs:
|
||||
page = item.funcargs["page"]
|
||||
screenshot_dir = Path(".playwright-screenshots")
|
||||
screenshot_dir.mkdir(exist_ok=True)
|
||||
page.screenshot(path=str(screenshot_dir / f"{slugify(item.nodeid)}.png"))
|
||||
```
|
||||
|
||||
## Deploy to CI
|
||||
|
||||
Use the [Playwright GitHub Action](https://github.com/microsoft/playwright-github-action) or [guides for other CI providers](https://playwright.dev/#path=docs%2Fci.md&q=) to deploy your tests to CI/CD
|
||||
|
|
@ -41,7 +41,8 @@ Playwright enables fast, reliable and capable automation across all modern brows
|
|||
|
||||
* **Debugging tools**. Playwright works with the [editor debugger and browser developer tools](./debug.md) to pause execution and inspect the web page.
|
||||
|
||||
* **Language bindings**. Playwright is also available in [Python](https://github.com/microsoft/playwright-python) and [C#](https://github.com/microsoft/playwright-sharp). Learn about [supported languages](./languages.md).
|
||||
* **Language bindings**. Playwright is available for [Node.js](https://github.com/microsoft/playwright) [Python](https://github.com/microsoft/playwright-python), [C#](https://github.com/microsoft/playwright-sharp) and
|
||||
[Java](https://github.com/microsoft/playwright-java). Learn more about [supported languages](./languages.md).
|
||||
|
||||
* **Deploy tests to CI**. First-party [Docker image](./docker.md) and [GitHub Actions](https://github.com/microsoft/playwright-github-action) to deploy tests to [your preferred CI/CD provider](./ci.md).
|
||||
|
||||
|
|
|
|||
|
|
@ -342,7 +342,7 @@ function generateToc(nodes) {
|
|||
if (node.type === 'h1' || node.type === 'h2') {
|
||||
let link = node.text.toLowerCase();
|
||||
link = link.replace(/[ ]+/g, '-');
|
||||
link = link.replace(/[^\w-]/g, '');
|
||||
link = link.replace(/[^\w-_]/g, '');
|
||||
result.push(`${' '.repeat(depth * 2)}- [${node.text}](#${link})`);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue