chore: prepare non-api docs for non-js variants (#4969)

This commit is contained in:
Pavel Feldman 2021-01-11 09:34:49 -08:00 committed by GitHub
parent 4dbbb47583
commit 7a8214cd95
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 439 additions and 147 deletions

View file

@ -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. 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. 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: async with page.expect_event(event_name) as event_info:
await page.click("button") await page.click("button")
value = await event_info.value value = await event_info.value
``` ```
```python-sync ```python sync
with page.expect_event(event_name) as event_info: with page.expect_event(event_name) as event_info:
page.click("button") page.click("button")
value = event_info.value 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. 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. 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: async with context.expect_event(event_name) as event_info:
await context.click("button") await context.click("button")
value = await event_info.value value = await event_info.value
``` ```
```python-sync ```python sync
with context.expect_event(event_name) as event_info: with context.expect_event(event_name) as event_info:
context.click("button") context.click("button")
value = event_info.value 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. 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. 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: async with ws.expect_event(event_name) as event_info:
await ws.click("button") await ws.click("button")
value = await event_info.value value = await event_info.value
``` ```
```python-sync ```python sync
with ws.expect_event(event_name) as event_info: with ws.expect_event(event_name) as event_info:
ws.click("button") ws.click("button")
value = event_info.value 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 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. already reached the required state, resolves immediately.
```python-async ```python async
async with page.expect_load_state(): async with page.expect_load_state():
await page.click('button') # Click triggers navigation. await page.click('button') # Click triggers navigation.
# Context manager waits for 'load' event. # Context manager waits for 'load' event.
``` ```
```python-sync ```python sync
with page.expect_load_state(): with page.expect_load_state():
page.click('button') # Click triggers navigation. page.click('button') # Click triggers navigation.
# Context manager waits for 'load' event. # 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 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. already reached the required state, resolves immediately.
```python-async ```python async
async with frame.expect_load_state(): async with frame.expect_load_state():
await frame.click('button') # Click triggers navigation. await frame.click('button') # Click triggers navigation.
# Context manager waits for 'load' event. # Context manager waits for 'load' event.
``` ```
```python-sync ```python sync
with frame.expect_load_state(): with frame.expect_load_state():
frame.click('button') # Click triggers navigation. frame.click('button') # Click triggers navigation.
# Context manager waits for 'load' event. # Context manager waits for 'load' event.
@ -238,7 +238,7 @@ with frame.expect_load_state():
* langs: python * langs: python
- returns: <[EventContextManager]> - 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 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`. 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 indirectly cause the page to navigate. e.g. The click target has an `onclick` handler that triggers navigation
from a `setTimeout`. Consider this example: from a `setTimeout`. Consider this example:
```python-async ```python async
async with page.expect_navigation(): async with page.expect_navigation():
await page.click("a.delayed-navigation") # Clicking the link will indirectly cause a navigation await page.click("a.delayed-navigation") # Clicking the link will indirectly cause a navigation
# Context manager waited for the navigation to happen. # Context manager waited for the navigation to happen.
``` ```
```python-sync ```python sync
with page.expect_navigation(): with page.expect_navigation():
page.click("a.delayed-navigation") # Clicking the link will indirectly cause a navigation page.click("a.delayed-navigation") # Clicking the link will indirectly cause a navigation
# Context manager waited for the navigation to happen. # Context manager waited for the navigation to happen.
@ -271,7 +271,7 @@ Shortcut for main frame's [`method: Frame.expectNavigation`].
* langs: python * langs: python
- returns: <[EventContextManager]> - 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 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`. 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 indirectly cause the page to navigate. e.g. The click target has an `onclick` handler that triggers navigation
from a `setTimeout`. Consider this example: from a `setTimeout`. Consider this example:
```python-async ```python async
async with frame.expect_navigation(): async with frame.expect_navigation():
await frame.click("a.delayed-navigation") # Clicking the link will indirectly cause a navigation await frame.click("a.delayed-navigation") # Clicking the link will indirectly cause a navigation
# Context manager waited for the navigation to happen. # Context manager waited for the navigation to happen.
``` ```
```python-sync ```python sync
with frame.expect_navigation(): with frame.expect_navigation():
frame.click("a.delayed-navigation") # Clicking the link will indirectly cause a navigation frame.click("a.delayed-navigation") # Clicking the link will indirectly cause a navigation
# Context manager waited for the navigation to happen. # Context manager waited for the navigation to happen.

View file

@ -35,7 +35,7 @@ const checked = await page.getAttribute('input', 'checked');
assert(checked); assert(checked);
``` ```
```python-async ```python async
# Assert text content # Assert text content
content = await page.text_content('nav:first-child') content = await page.text_content('nav:first-child')
assert content == 'home' assert content == 'home'
@ -53,7 +53,7 @@ checked = await page.get_attribute('input', 'checked')
assert checked assert checked
``` ```
```python-sync ```python sync
# Assert text content # Assert text content
content = page.text_content('nav:first-child') content = page.text_content('nav:first-child')
assert content == 'home' assert content == 'home'
@ -106,7 +106,7 @@ const classNames = await elementHandle.getAttribute('class');
assert(classNames.includes('highlighted')); assert(classNames.includes('highlighted'));
``` ```
```python-async ```python async
# Get the element handle # Get the element handle
element_handle = page.wait_for_selector('#box') element_handle = page.wait_for_selector('#box')
@ -119,7 +119,7 @@ class_names = await element_handle.get_attribute('class')
assert 'highlighted' in class_names assert 'highlighted' in class_names
``` ```
```python-sync ```python sync
# Get the element handle # Get the element handle
element_handle = page.wait_for_selector('#box') element_handle = page.wait_for_selector('#box')
@ -171,7 +171,7 @@ const length = await page.$$eval('li.selected', (items) => items.length);
assert(length === 3); assert(length === 3);
``` ```
```python-async ```python async
# Assert local storage value # Assert local storage value
user_id = page.evaluate("() => window.localStorage.getItem('user_id')") user_id = page.evaluate("() => window.localStorage.getItem('user_id')")
assert user_id assert user_id
@ -190,7 +190,7 @@ length = await page.eval_on_selector_all('li.selected', '(items) => items.length
assert length == 3 assert length == 3
``` ```
```python-sync ```python sync
# Assert local storage value # Assert local storage value
user_id = page.evaluate("() => window.localStorage.getItem('user_id')") user_id = page.evaluate("() => window.localStorage.getItem('user_id')")
assert user_id assert user_id

View file

@ -36,7 +36,7 @@ await page.click('text=Submit');
// Verify app is logged in // Verify app is logged in
``` ```
```python-async ```python async
page = await context.new_page() page = await context.new_page()
await page.goto('https://github.com/login') await page.goto('https://github.com/login')
@ -48,7 +48,7 @@ await page.click('text=Submit')
# Verify app is logged in # Verify app is logged in
``` ```
```python-sync ```python sync
page = context.new_page() page = context.new_page()
page.goto('https://github.com/login') page.goto('https://github.com/login')
@ -88,7 +88,7 @@ const storageState = JSON.parse(process.env.STORAGE);
const context = await browser.newContext({ storageState }); const context = await browser.newContext({ storageState });
``` ```
```python-async ```python async
import json import json
import os import os
# Save storage state and store as an env variable # 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) context = await browser.new_context(storage_state=storage_state)
``` ```
```python-sync ```python sync
import json import json
import os import os
# Save storage state and store as an env variable # Save storage state and store as an env variable
@ -134,7 +134,7 @@ await context.addInitScript(storage => {
}, sessionStorage); }, sessionStorage);
``` ```
```python-async ```python async
import os import os
# Get session storage and store as env variable # Get session storage and store as env variable
session_storage = await page.evaluate("() => JSON.stringify(sessionStorage)") session_storage = await page.evaluate("() => JSON.stringify(sessionStorage)")
@ -152,7 +152,7 @@ await context.add_init_script(storage => {
}, session_storage) }, session_storage)
``` ```
```python-sync ```python sync
import os import os
# Get session storage and store as env variable # Get session storage and store as env variable
session_storage = page.evaluate("() => JSON.stringify(sessionStorage)") 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 // Execute login steps manually in the browser window
``` ```
```python-async ```python async
import asyncio import asyncio
from playwright import async_playwright from playwright import async_playwright
@ -230,7 +230,7 @@ async def main():
asyncio.get_event_loop().run_until_complete(main()) asyncio.get_event_loop().run_until_complete(main())
``` ```
```python-sync ```python sync
from playwright import sync_playwright from playwright import sync_playwright
with sync_playwright() as p: with sync_playwright() as p:

View file

@ -50,13 +50,13 @@ Suggested configuration
}); });
``` ```
```python-async ```python async
browser = await playwright.chromium.launch( browser = await playwright.chromium.launch(
args=['--disable-dev-shm-usage'] args=['--disable-dev-shm-usage']
) )
``` ```
```python-sync ```python sync
browser = playwright.chromium.launch({ browser = playwright.chromium.launch({
args=['--disable-dev-shm-usage'] args=['--disable-dev-shm-usage']
}) })
@ -203,11 +203,11 @@ const { chromium } = require('playwright');
const browser = await chromium.launch({ chromiumSandbox: false }); const browser = await chromium.launch({ chromiumSandbox: false });
``` ```
```python-async ```python async
browser = await playwright.chromium.launch(chromiumSandbox=False) browser = await playwright.chromium.launch(chromiumSandbox=False)
``` ```
```python-sync ```python sync
browser = playwright.chromium.launch(chromiumSandbox=False) browser = playwright.chromium.launch(chromiumSandbox=False)
``` ```
@ -287,7 +287,7 @@ const { chromium } = require('playwright');
const browser = await chromium.launch({ headless: false }); const browser = await chromium.launch({ headless: false });
``` ```
```python-async ```python async
import asyncio import asyncio
from playwright import async_playwright from playwright import async_playwright
@ -299,7 +299,7 @@ async def main():
asyncio.get_event_loop().run_until_complete(main()) asyncio.get_event_loop().run_until_complete(main())
``` ```
```python-sync ```python sync
from playwright import sync_playwright from playwright import sync_playwright
with sync_playwright() as p: with sync_playwright() as p:

View file

@ -29,7 +29,7 @@ const browser = await chromium.launch({ headless: false });
await browser.close(); await browser.close();
``` ```
```python-async ```python async
import asyncio import asyncio
from playwright import async_playwright from playwright import async_playwright
@ -41,7 +41,7 @@ async def main():
asyncio.get_event_loop().run_until_complete(main()) asyncio.get_event_loop().run_until_complete(main())
``` ```
```python-sync ```python sync
from playwright import sync_playwright from playwright import sync_playwright
with sync_playwright() as p: with sync_playwright() as p:
@ -69,12 +69,12 @@ const browser = await chromium.launch();
const context = await browser.newContext(); const context = await browser.newContext();
``` ```
```python-async ```python async
browser = await playwright.chromium.launch() browser = await playwright.chromium.launch()
context = await browser.new_context() context = await browser.new_context()
``` ```
```python-sync ```python sync
browser = playwright.chromium.launch() browser = playwright.chromium.launch()
context = browser.new_context() context = browser.new_context()
``` ```
@ -95,7 +95,7 @@ const context = await browser.newContext({
}); });
``` ```
```python-async ```python async
import asyncio import asyncio
from playwright import async_playwright from playwright import async_playwright
@ -116,7 +116,7 @@ async def main():
asyncio.get_event_loop().run_until_complete(main()) asyncio.get_event_loop().run_until_complete(main())
``` ```
```python-sync ```python sync
from playwright import sync_playwright from playwright import sync_playwright
with sync_playwright() as p: with sync_playwright() as p:
@ -161,7 +161,7 @@ console.log(page.url());
window.location.href = 'https://example.com'; window.location.href = 'https://example.com';
``` ```
```python-async ```python async
page = await context.new_page() page = await context.new_page()
# Navigate explicitly, similar to entering a URL in the browser. # Navigate explicitly, similar to entering a URL in the browser.
@ -178,7 +178,7 @@ print(page.url)
# window.location.href = 'https://example.com' # window.location.href = 'https://example.com'
``` ```
```python-sync ```python sync
page = context.new_page() page = context.new_page()
# Navigate explicitly, similar to entering a URL in the browser. # 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'); await frame.fill('#username-input', 'John');
``` ```
```python-async ```python async
# Get frame using the frame's name attribute # Get frame using the frame's name attribute
frame = page.frame('frame-login') frame = page.frame('frame-login')
@ -234,7 +234,7 @@ frame = await frame_element_handle.content_frame()
await frame.fill('#username-input', 'John') await frame.fill('#username-input', 'John')
``` ```
```python-sync ```python sync
# Get frame using the frame's name attribute # Get frame using the frame's name attribute
frame = page.frame('frame-login') frame = page.frame('frame-login')
@ -274,12 +274,12 @@ Some examples below:
await page.click('data-test-id=foo'); await page.click('data-test-id=foo');
``` ```
```python-async ```python async
# Using data-test-id= selector engine # Using data-test-id= selector engine
await page.click('data-test-id=foo') await page.click('data-test-id=foo')
``` ```
```python-sync ```python sync
# Using data-test-id= selector engine # Using data-test-id= selector engine
page.click('data-test-id=foo') page.click('data-test-id=foo')
``` ```
@ -290,13 +290,13 @@ await page.click('div');
await page.click('//html/body/div'); await page.click('//html/body/div');
``` ```
```python-async ```python async
# CSS and XPath selector engines are automatically detected # CSS and XPath selector engines are automatically detected
await page.click('div') await page.click('div')
await page.click('//html/body/div') await page.click('//html/body/div')
``` ```
```python-sync ```python sync
# CSS and XPath selector engines are automatically detected # CSS and XPath selector engines are automatically detected
page.click('div') page.click('div')
page.click('//html/body/div') page.click('//html/body/div')
@ -307,12 +307,12 @@ page.click('//html/body/div')
await page.click('text=Hello w'); await page.click('text=Hello w');
``` ```
```python-async ```python async
# Find node by text substring # Find node by text substring
await page.click('text=Hello w') await page.click('text=Hello w')
``` ```
```python-sync ```python sync
# Find node by text substring # Find node by text substring
page.click('text=Hello w') page.click('text=Hello w')
``` ```
@ -323,13 +323,13 @@ await page.click('css=div');
await page.click('xpath=//html/body/div'); await page.click('xpath=//html/body/div');
``` ```
```python-async ```python async
# Explicit CSS and XPath notation # Explicit CSS and XPath notation
await page.click('css=div') await page.click('css=div')
await page.click('xpath=//html/body/div') await page.click('xpath=//html/body/div')
``` ```
```python-sync ```python sync
# Explicit CSS and XPath notation # Explicit CSS and XPath notation
page.click('css=div') page.click('css=div')
page.click('xpath=//html/body/div') page.click('xpath=//html/body/div')
@ -340,12 +340,12 @@ page.click('xpath=//html/body/div')
await page.click('css:light=div'); await page.click('css:light=div');
``` ```
```python-async ```python async
# Only search light DOM, outside WebComponent shadow DOM: # Only search light DOM, outside WebComponent shadow DOM:
await page.click('css:light=div') await page.click('css:light=div')
``` ```
```python-sync ```python sync
# Only search light DOM, outside WebComponent shadow DOM: # Only search light DOM, outside WebComponent shadow DOM:
page.click('css:light=div') 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'); 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. # Click an element with text 'Sign Up' inside of a #free-month-promo.
await page.click('#free-month-promo >> text=Sign Up') 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. # Click an element with text 'Sign Up' inside of a #free-month-promo.
page.click('#free-month-promo >> text=Sign Up') 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); 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'. # 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') 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'. # 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') 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'); await page.fill('#search', 'query');
``` ```
```python-async ```python async
# Playwright waits for #search element to be in the DOM # Playwright waits for #search element to be in the DOM
await page.fill('#search', 'query') await page.fill('#search', 'query')
``` ```
```python-sync ```python sync
# Playwright waits for #search element to be in the DOM # Playwright waits for #search element to be in the DOM
page.fill('#search', 'query') page.fill('#search', 'query')
``` ```
@ -417,13 +417,13 @@ page.fill('#search', 'query')
await page.click('#search'); await page.click('#search');
``` ```
```python-async ```python async
# Playwright waits for element to stop animating # Playwright waits for element to stop animating
# and accept clicks. # and accept clicks.
await page.click('#search') await page.click('#search')
``` ```
```python-sync ```python sync
# Playwright waits for element to stop animating # Playwright waits for element to stop animating
# and accept clicks. # and accept clicks.
page.click('#search') page.click('#search')
@ -438,14 +438,14 @@ await page.waitForSelector('#search', { state: 'attached' });
await page.waitForSelector('#promo'); await page.waitForSelector('#promo');
``` ```
```python-async ```python async
# Wait for #search to appear in the DOM. # Wait for #search to appear in the DOM.
await page.wait_for_selector('#search', state='attached') await page.wait_for_selector('#search', state='attached')
# Wait for #promo to become visible, for example with `visibility:visible`. # Wait for #promo to become visible, for example with `visibility:visible`.
await page.wait_for_selector('#promo') await page.wait_for_selector('#promo')
``` ```
```python-sync ```python sync
# Wait for #search to appear in the DOM. # Wait for #search to appear in the DOM.
page.wait_for_selector('#search', state='attached') page.wait_for_selector('#search', state='attached')
# Wait for #promo to become visible, for example with `visibility:visible`. # 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' }); await page.waitForSelector('#promo', { state: 'detached' });
``` ```
```python-async ```python async
# Wait for #details to become hidden, for example with `display:none`. # Wait for #details to become hidden, for example with `display:none`.
await page.wait_for_selector('#details', state='hidden') await page.wait_for_selector('#details', state='hidden')
# Wait for #promo to be removed from the DOM. # Wait for #promo to be removed from the DOM.
await page.wait_for_selector('#promo', state='detached') await page.wait_for_selector('#promo', state='detached')
``` ```
```python-sync ```python sync
# Wait for #details to become hidden, for example with `display:none`. # Wait for #details to become hidden, for example with `display:none`.
page.wait_for_selector('#details', state='hidden') page.wait_for_selector('#details', state='hidden')
# Wait for #promo to be removed from the DOM. # 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); const href = await page.evaluate(() => document.location.href);
``` ```
```python-async ```python async
href = await page.evaluate('() => document.location.href') href = await page.evaluate('() => document.location.href')
``` ```
```python-sync ```python sync
href = page.evaluate('() => document.location.href') 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 () => { status = await page.evaluate("""async () => {
response = await fetch(location.href) response = await fetch(location.href)
return response.status return response.status
}""") }""")
``` ```
```python-sync ```python sync
status = page.evaluate("""async () => { status = page.evaluate("""async () => {
response = fetch(location.href) response = fetch(location.href)
return response.status return response.status
@ -573,7 +573,7 @@ await page.evaluate(
{ button1, list: [button2], foo: null }); { button1, list: [button2], foo: null });
``` ```
```python-async ```python async
# A primitive value. # A primitive value.
await page.evaluate('num => num', 42) await page.evaluate('num => num', 42)
@ -616,7 +616,7 @@ await page.evaluate("""
{ 'button1': button1, 'list': [button2], 'foo': None }) { 'button1': button1, 'list': [button2], 'foo': None })
``` ```
```python-sync ```python sync
# A primitive value. # A primitive value.
page.evaluate('num => num', 42) page.evaluate('num => num', 42)
@ -668,7 +668,7 @@ const result = await page.evaluate(data => {
}, data); }, data);
``` ```
```python-async ```python async
data = { 'text': 'some data', 'value': 1 } data = { 'text': 'some data', 'value': 1 }
# Pass |data| as a parameter. # Pass |data| as a parameter.
result = await page.evaluate("""data => { result = await page.evaluate("""data => {
@ -676,7 +676,7 @@ result = await page.evaluate("""data => {
}""", data) }""", data)
``` ```
```python-sync ```python sync
data = { 'text': 'some data', 'value': 1 } data = { 'text': 'some data', 'value': 1 }
# Pass |data| as a parameter. # Pass |data| as a parameter.
result = page.evaluate("""data => { result = page.evaluate("""data => {
@ -694,7 +694,7 @@ const result = await page.evaluate(() => {
}); });
``` ```
```python-async ```python async
data = { 'text': 'some data', 'value': 1 } data = { 'text': 'some data', 'value': 1 }
result = await page.evaluate("""() => { result = await page.evaluate("""() => {
# There is no |data| in the web page. # 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 } data = { 'text': 'some data', 'value': 1 }
result = page.evaluate("""() => { result = page.evaluate("""() => {
# There is no |data| in the web page. # 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')); 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. # The first parameter of the elementHandle.evaluate callback is the element handle points to.
ul_element_handle = await page.query_selector('ul') ul_element_handle = await page.query_selector('ul')
await ul_element_handle.evaluate("ulElement => getComputedStyle(ulElement).getPropertyValue('display')") 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. # The first parameter of the elementHandle.evaluate callback is the element handle points to.
ul_element_handle = page.query_selector('ul') ul_element_handle = page.query_selector('ul')
ul_element_handle.evaluate("ulElement => getComputedStyle(ulElement).getPropertyValue('display')") 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); await page.evaluate(uiElement => getComputedStyle(uiElement).getPropertyValue('display'), uiElement);
``` ```
```python-async ```python async
ul_element_handle = await page.query_selector('ul') ul_element_handle = await page.query_selector('ul')
await page.evaluate("uiElement => getComputedStyle(uiElement).getPropertyValue('display')", uiElement) await page.evaluate("uiElement => getComputedStyle(uiElement).getPropertyValue('display')", uiElement)
``` ```
```python-sync ```python sync
ul_element_handle = page.query_selector('ul') ul_element_handle = page.query_selector('ul')
page.evaluate("uiElement => getComputedStyle(uiElement).getPropertyValue('display')", uiElement) page.evaluate("uiElement => getComputedStyle(uiElement).getPropertyValue('display')", uiElement)
``` ```
@ -803,7 +803,7 @@ const newLength = await page.evaluate(() => window.myArray.length);
await myArrayHandle.dispose(); await myArrayHandle.dispose();
``` ```
```python-async ```python async
# Create a new array in the page, write a reference to it in # Create a new array in the page, write a reference to it in
# window.myArray and get a handle to it. # window.myArray and get a handle to it.
my_array_handle = await page.evaluate_handle("""() => { my_array_handle = await page.evaluate_handle("""() => {
@ -830,7 +830,7 @@ new_length = await page.evaluate("() => window.myArray.length")
await my_array_handle.dispose() await my_array_handle.dispose()
``` ```
```python-sync ```python sync
# Create a new array in the page, write a reference to it in # Create a new array in the page, write a reference to it in
# window.myArray and get a handle to it. # window.myArray and get a handle to it.
my_array_handle = page.evaluate_handle("""() => { my_array_handle = page.evaluate_handle("""() => {

View file

@ -19,17 +19,17 @@ to slow down execution and follow along while debugging.
await chromium.launch({ headless: false, slowMo: 100 }); // or firefox, webkit 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 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 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 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. 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 for your Node.js project. Once configured launch the scripts with F5 and use
breakpoints. 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 VS Code 1.46+ introduced the new JavaScript debugger that does not require a `launch.json`
new debugger does not require a `launch.json` configuration. To use this: configuration. To use it:
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
1. Set a breakpoint in VS Code 1. Set a breakpoint in VS Code
* Use the `debugger` keyword or set a breakpoint in the VS Code UI * Use the `debugger` keyword or set a breakpoint in the VS Code UI
1. Run your Node.js script from the terminal 1. Run your Node.js script from the terminal
## Browser Developer Tools ## Browser Developer Tools
@ -76,12 +71,12 @@ In Chromium, you can also open developer tools through a launch option.
await chromium.launch({ devtools: true }); await chromium.launch({ devtools: true });
``` ```
```python-async ```python async
await chromium.launch(devtools=True) await chromium.launch(devtools=True)
``` ```
```python-sync ```python sync
chromium.launch(devtools=True) chromium.launch(devtools=True)
``` ```

View file

@ -3,7 +3,7 @@ id: docker
title: "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 --> <!-- TOC -->

View file

@ -29,7 +29,7 @@ const context = await browser.newContext({
}); });
``` ```
```python-async ```python async
import asyncio import asyncio
from playwright import async_playwright from playwright import async_playwright
@ -44,7 +44,7 @@ async def main():
asyncio.get_event_loop().run_until_complete(main()) asyncio.get_event_loop().run_until_complete(main())
``` ```
```python-sync ```python sync
from playwright import sync_playwright from playwright import sync_playwright
with sync_playwright() as p: with sync_playwright() as p:
@ -74,13 +74,13 @@ const context = await browser.newContext({
}); });
``` ```
```python-async ```python async
context = await browser.new_context( context = await browser.new_context(
user_agent='My user agent' user_agent='My user agent'
) )
``` ```
```python-sync ```python sync
context = browser.new_context( context = browser.new_context(
user_agent='My user agent' user_agent='My user agent'
) )
@ -112,7 +112,7 @@ const context = await browser.newContext({
}); });
``` ```
```python-async ```python async
# Create context with given viewport # Create context with given viewport
context = await browser.new_context( context = await browser.new_context(
viewport={ 'width': 1280, 'height': 1024 } viewport={ 'width': 1280, 'height': 1024 }
@ -128,7 +128,7 @@ context = await browser.new_context(
) )
``` ```
```python-sync ```python sync
# Create context with given viewport # Create context with given viewport
context = browser.new_context( context = browser.new_context(
viewport={ 'width': 1280, 'height': 1024 } viewport={ 'width': 1280, 'height': 1024 }
@ -161,7 +161,7 @@ const context = await browser.newContext({
}); });
``` ```
```python-async ```python async
# Emulate locale and time # Emulate locale and time
context = await browser.new_context( context = await browser.new_context(
locale='de-DE', locale='de-DE',
@ -169,7 +169,7 @@ context = await browser.new_context(
) )
``` ```
```python-sync ```python sync
# Emulate locale and time # Emulate locale and time
context = browser.new_context( context = browser.new_context(
locale='de-DE', locale='de-DE',
@ -193,13 +193,13 @@ const context = await browser.newContext({
}); });
``` ```
```python-async ```python async
context = await browser.new_context( context = await browser.new_context(
permissions=['notifications'], permissions=['notifications'],
) )
``` ```
```python-sync ```python sync
context = browser.new_context( context = browser.new_context(
permissions=['notifications'], permissions=['notifications'],
) )
@ -211,11 +211,11 @@ Grant all pages in the existing context access to current location:
await context.grantPermissions(['geolocation']); await context.grantPermissions(['geolocation']);
``` ```
```python-async ```python async
await context.grant_permissions(['geolocation']) await context.grant_permissions(['geolocation'])
``` ```
```python-sync ```python sync
context.grant_permissions(['geolocation']) context.grant_permissions(['geolocation'])
``` ```
@ -225,11 +225,11 @@ Grant notifications access from a specific domain:
await context.grantPermissions(['notifications'], {origin: 'https://skype.com'} ); await context.grantPermissions(['notifications'], {origin: 'https://skype.com'} );
``` ```
```python-async ```python async
await context.grant_permissions(['notifications'], origin='https://skype.com') await context.grant_permissions(['notifications'], origin='https://skype.com')
``` ```
```python-sync ```python sync
context.grant_permissions(['notifications'], origin='https://skype.com') context.grant_permissions(['notifications'], origin='https://skype.com')
``` ```
@ -239,11 +239,11 @@ Revoke all permissions:
await context.clearPermissions(); await context.clearPermissions();
``` ```
```python-async ```python async
await context.clear_permissions() await context.clear_permissions()
``` ```
```python-sync ```python sync
context.clear_permissions() context.clear_permissions()
``` ```
@ -265,14 +265,14 @@ const context = await browser.newContext({
}); });
``` ```
```python-async ```python async
context = await browser.new_context( context = await browser.new_context(
geolocation={"longitude": 48.858455, "latitude": 2.294474}, geolocation={"longitude": 48.858455, "latitude": 2.294474},
permissions=["geolocation"] permissions=["geolocation"]
) )
``` ```
```python-sync ```python sync
context = browser.new_context( context = browser.new_context(
geolocation={"longitude": 48.858455, "latitude": 2.294474}, geolocation={"longitude": 48.858455, "latitude": 2.294474},
permissions=["geolocation"] permissions=["geolocation"]
@ -285,11 +285,11 @@ Change the location later:
await context.setGeolocation({ longitude: 29.979097, latitude: 31.134256 }); await context.setGeolocation({ longitude: 29.979097, latitude: 31.134256 });
``` ```
```python-async ```python async
await context.set_geolocation({"longitude": 29.979097, "latitude": 31.134256}) await context.set_geolocation({"longitude": 29.979097, "latitude": 31.134256})
``` ```
```python-sync ```python sync
context.set_geolocation({"longitude": 29.979097, "latitude": 31.134256}) context.set_geolocation({"longitude": 29.979097, "latitude": 31.134256})
``` ```
@ -325,7 +325,7 @@ await page.emulateMedia({ colorScheme: 'dark' });
await page.emulateMedia({ media: 'print' }); await page.emulateMedia({ media: 'print' });
``` ```
```python-async ```python async
# Create context with dark mode # Create context with dark mode
context = await browser.new_context( context = await browser.new_context(
color_scheme='dark' # or 'light' color_scheme='dark' # or 'light'
@ -343,7 +343,7 @@ await page.emulate_media(color_scheme='dark')
await page.emulate_media(media='print') await page.emulate_media(media='print')
``` ```
```python-sync ```python sync
# Create context with dark mode # Create context with dark mode
context = browser.new_context( context = browser.new_context(
color_scheme='dark' # or 'light' color_scheme='dark' # or 'light'

View file

@ -26,7 +26,7 @@ await page.fill('#local', '2020-03-02T05:15');
await page.fill('text=First Name', 'Peter'); await page.fill('text=First Name', 'Peter');
``` ```
```python-async ```python async
# Text input # Text input
await page.fill('#name', 'Peter') await page.fill('#name', 'Peter')
@ -43,7 +43,7 @@ await page.fill('#local', '2020-03-02T05:15')
await page.fill('text=First Name', 'Peter') await page.fill('text=First Name', 'Peter')
``` ```
```python-sync ```python sync
# Text input # Text input
page.fill('#name', 'Peter') page.fill('#name', 'Peter')
@ -83,7 +83,7 @@ await page.uncheck('#subscribe-label');
await page.check('text=XL'); await page.check('text=XL');
``` ```
```python-async ```python async
# Check the checkbox # Check the checkbox
await page.check('#agree') await page.check('#agree')
@ -94,7 +94,7 @@ await page.uncheck('#subscribe-label')
await page.check('text=XL') await page.check('text=XL')
``` ```
```python-sync ```python sync
# Check the checkbox # Check the checkbox
page.check('#agree') page.check('#agree')
@ -136,7 +136,7 @@ const option = await page.$('#best-option');
await page.selectOption('select#colors', option); await page.selectOption('select#colors', option);
``` ```
```python-async ```python async
# Single selection matching the value # Single selection matching the value
await page.select_option('select#colors', 'blue') 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) await page.select_option('select#colors', option)
``` ```
```python-sync ```python sync
# Single selection matching the value # Single selection matching the value
page.select_option('select#colors', 'blue') page.select_option('select#colors', 'blue')
@ -198,7 +198,7 @@ await page.hover('#item');
await page.click('#item', { position: { x: 0, y: 0} }); await page.click('#item', { position: { x: 0, y: 0} });
``` ```
```python-async ```python async
# Generic click # Generic click
await page.click('button#submit') await page.click('button#submit')
@ -218,7 +218,7 @@ await page.hover('#item')
await page.click('#item', position={ 'x': 0, 'y': 0}) await page.click('#item', position={ 'x': 0, 'y': 0})
``` ```
```python-sync ```python sync
# Generic click # Generic click
page.click('button#submit') 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 }); await page.click('button#submit', { force: true });
``` ```
```python-async ```python async
await page.click('button#submit', force=True) await page.click('button#submit', force=True)
``` ```
```python-sync ```python sync
page.click('button#submit', force=True) 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'); await page.dispatchEvent('button#submit', 'click');
``` ```
```python-async ```python async
await page.dispatch_event('button#submit', 'click') await page.dispatch_event('button#submit', 'click')
``` ```
```python-sync ```python sync
page.dispatch_event('button#submit', 'click') 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!'); await page.type('#area', 'Hello World!');
``` ```
```python-async ```python async
# Type character by character # Type character by character
await page.type('#area', 'Hello World!') await page.type('#area', 'Hello World!')
``` ```
```python-sync ```python sync
# Type character by character # Type character by character
page.type('#area', 'Hello World!') page.type('#area', 'Hello World!')
``` ```
@ -341,7 +341,7 @@ await page.press('#name', 'Control+ArrowRight');
await page.press('#value', '$'); await page.press('#value', '$');
``` ```
```python-async ```python async
# Hit Enter # Hit Enter
await page.press('#submit', 'Enter') await page.press('#submit', 'Enter')
@ -352,7 +352,7 @@ await page.press('#name', 'Control+ArrowRight')
await page.press('#value', '$') await page.press('#value', '$')
``` ```
```python-sync ```python sync
# Hit Enter # Hit Enter
page.press('#submit', 'Enter') page.press('#submit', 'Enter')
@ -386,7 +386,7 @@ await page.press('#name', 'Shift+A');
await page.press('#name', 'Shift+ArrowLeft'); await page.press('#name', 'Shift+ArrowLeft');
``` ```
```python-async ```python async
# <input id=name> # <input id=name>
await page.press('#name', 'Shift+A') await page.press('#name', 'Shift+A')
@ -394,7 +394,7 @@ await page.press('#name', 'Shift+A')
await page.press('#name', 'Shift+ArrowLeft') await page.press('#name', 'Shift+ArrowLeft')
``` ```
```python-sync ```python sync
# <input id=name> # <input id=name>
page.press('#name', 'Shift+A') page.press('#name', 'Shift+A')
@ -436,7 +436,7 @@ await page.setInputFiles('input#upload', {
}); });
``` ```
```python-async ```python async
from playwright.async_api import FilePayload from playwright.async_api import FilePayload
# Select one file # Select one file
await page.set_input_files('input#upload', 'myfile.pdf') 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 from playwright.sync_api import FilePayload
# Select one file # Select one file
page.set_input_files('input#upload', 'myfile.pdf') 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'); await page.focus('input#name');
``` ```
```python-async ```python async
await page.focus('input#name') await page.focus('input#name')
``` ```
```python-sync ```python sync
page.focus('input#name') page.focus('input#name')
``` ```

View file

@ -1,6 +1,6 @@
--- ---
id: installation id: installation
title: "Advanced installation" title: "Installation"
--- ---
<!-- TOC --> <!-- TOC -->

86
docs/src/intro-python.md Normal file
View 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.

View file

@ -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 ```js
firefox.launch({ headless: false, slowMo: 50 }); firefox.launch({ headless: false, slowMo: 50 });
@ -62,7 +62,7 @@ firefox.launch({ headless: false, slowMo: 50 });
## Record scripts ## 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 ```sh
npx playwright codegen wikipedia.org npx playwright codegen wikipedia.org

View 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

View file

@ -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. * **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). * **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).

View file

@ -342,7 +342,7 @@ function generateToc(nodes) {
if (node.type === 'h1' || node.type === 'h2') { if (node.type === 'h1' || node.type === 'h2') {
let link = node.text.toLowerCase(); let link = node.text.toLowerCase();
link = link.replace(/[ ]+/g, '-'); link = link.replace(/[ ]+/g, '-');
link = link.replace(/[^\w-]/g, ''); link = link.replace(/[^\w-_]/g, '');
result.push(`${' '.repeat(depth * 2)}- [${node.text}](#${link})`); result.push(`${' '.repeat(depth * 2)}- [${node.text}](#${link})`);
} }
}); });