docs: add java snippets to the examples in guides (#5638)

This commit is contained in:
Yury Semikhatsky 2021-03-01 09:18:44 -08:00 committed by GitHub
parent aeb2b2f605
commit 6c9e806672
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 1209 additions and 24 deletions

View File

@ -8,7 +8,6 @@ text content of an element. These APIs can be used in your test assertions.
<!-- TOC --> <!-- TOC -->
## Text content ## Text content
```js ```js
@ -16,6 +15,11 @@ const content = await page.textContent('nav:first-child');
expect(content).toBe('home'); expect(content).toBe('home');
``` ```
```java
String content = page.textContent("nav:first-child");
assertEquals("home", content);
```
```python async ```python async
content = await page.text_content("nav:first-child") content = await page.text_content("nav:first-child")
assert content == "home" assert content == "home"
@ -37,6 +41,11 @@ const text = await page.innerText('.selected');
expect(text).toBe('value'); expect(text).toBe('value');
``` ```
```java
String text = page.innerText(".selected");
assertEquals("value", text);
```
```python async ```python async
text = await page.inner_text(".selected") text = await page.inner_text(".selected")
assert text == "value" assert text == "value"
@ -58,6 +67,11 @@ const alt = await page.getAttribute('input', 'alt');
expect(alt).toBe('Text'); expect(alt).toBe('Text');
``` ```
```java
String alt = page.getAttribute("input", "alt");
assertEquals("Text", alt);
```
```python async ```python async
checked = await page.get_attribute("input", "alt") checked = await page.get_attribute("input", "alt")
assert alt == "Text" assert alt == "Text"
@ -75,6 +89,11 @@ const checked = await page.isChecked('input');
expect(checked).toBeTruthy(); expect(checked).toBeTruthy();
``` ```
```java
boolean checked = page.isChecked("input");
assertTrue(checked);
```
```python async ```python async
checked = await page.is_checked("input") checked = await page.is_checked("input")
assert checked assert checked
@ -96,6 +115,11 @@ const content = await page.$eval('nav:first-child', e => e.textContent);
expect(content).toBe('home'); expect(content).toBe('home');
``` ```
```java
Object content = page.evalOnSelector("nav:first-child", "e => e.textContent");
assertEquals("home", content);
```
```python async ```python async
content = await page.eval_on_selector("nav:first-child", "e => e.textContent") content = await page.eval_on_selector("nav:first-child", "e => e.textContent")
assert content == "home" assert content == "home"
@ -117,6 +141,11 @@ const html = await page.innerHTML('div.result');
expect(html).toBe('<p>Result</p>'); expect(html).toBe('<p>Result</p>');
``` ```
```java
String html = page.innerHTML("div.result");
assertEquals("<p>Result</p>", html);
```
```python async ```python async
html = await page.inner_html("div.result") html = await page.inner_html("div.result")
assert html == "<p>Result</p>" assert html == "<p>Result</p>"
@ -138,6 +167,11 @@ const visible = await page.isVisible('input');
expect(visible).toBeTruthy(); expect(visible).toBeTruthy();
``` ```
```java
boolean visible = page.isVisible("input");
assertTrue(visible);
```
```python async ```python async
visible = await page.is_visible("input") visible = await page.is_visible("input")
assert visible assert visible
@ -156,7 +190,12 @@ assert visible
```js ```js
const enabled = await page.isEnabled('input'); const enabled = await page.isEnabled('input');
expect(visible).toBeTruthy(); expect(enabled).toBeTruthy();
```
```java
boolean enabled = page.isEnabled("input");
assertTrue(enabled);
``` ```
```python async ```python async
@ -198,6 +237,25 @@ const length = await page.$$eval('li.selected', (items) => items.length);
expect(length === 3).toBeTruthy(); expect(length === 3).toBeTruthy();
``` ```
```java
// Assert local storage value
Object userId = page.evaluate("() => window.localStorage.getItem('userId')");
assertNotNull(userId);
// Assert value for input element
page.waitForSelector("#search");
Object value = page.evalOnSelector("#search", "el => el.value");
assertEquals("query", value);
// Assert computed style
Object fontSize = page.evalOnSelector("div", "el => window.getComputedStyle(el).fontSize");
assertEquals("16px", fontSize);
// Assert list length
Object length = page.evalOnSelectorAll("li.selected", "items => items.length");
assertEquals(3, length);
```
```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')")
@ -245,4 +303,4 @@ assert length == 3
- [`method: Frame.evalOnSelectorAll`] - [`method: Frame.evalOnSelectorAll`]
- [`method: ElementHandle.evalOnSelector`] - [`method: ElementHandle.evalOnSelector`]
- [`method: ElementHandle.evalOnSelectorAll`] - [`method: ElementHandle.evalOnSelectorAll`]
- [EvaluationArgument] - [EvaluationArgument]

View File

@ -36,6 +36,17 @@ await page.click('text=Submit');
// Verify app is logged in // Verify app is logged in
``` ```
```java
Page page = context.newPage();
page.navigate("https://github.com/login");
// Interact with login form
page.click("text=Login");
page.fill("input[name='login']", USERNAME);
page.fill("input[name='password']", PASSWORD);
page.click("text=Submit");
// 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')
@ -88,6 +99,16 @@ const storageState = JSON.parse(process.env.STORAGE);
const context = await browser.newContext({ storageState }); const context = await browser.newContext({ storageState });
``` ```
```java
// Save storage state and store as an env variable
String storage = context.storageState();
System.getenv().put("STORAGE", storage);
// Create a new context with the saved storage state
BrowserContext context = browser.newContext(
new Browser.NewContextOptions().withStorageState(storage));
```
```python async ```python async
import json import json
import os import os
@ -150,6 +171,23 @@ await context.addInitScript(storage => {
}, sessionStorage); }, sessionStorage);
``` ```
```java
// Get session storage and store as env variable
String sessionStorage = (String) page.evaluate("() => JSON.stringify(sessionStorage");
System.getenv().put("SESSION_STORAGE", sessionStorage);
// Set session storage in a new context
String sessionStorage = System.getenv("SESSION_STORAGE");
context.addInitScript("(storage => {\n" +
" if (window.location.hostname === 'example.com') {\n" +
" const entries = JSON.parse(storage);\n" +
" Object.keys(entries).forEach(key => {\n" +
" window.sessionStorage.setItem(key, entries[key]);\n" +
" });\n" +
" }\n" +
"})(" + 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
@ -199,8 +237,6 @@ manual intervention. Persistent authentication can be used to partially automate
MFA scenarios. MFA scenarios.
### Persistent authentication ### Persistent authentication
Web browsers use a directory on disk to store user history, cookies, IndexedDB
and other local state. This disk location is called the [User data directory](https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md).
Note that persistent authentication is not suited for CI environments since it Note that persistent authentication is not suited for CI environments since it
relies on a disk location. User data directories are specific to browser types relies on a disk location. User data directories are specific to browser types
@ -216,6 +252,22 @@ const context = await chromium.launchPersistentContext(userDataDir, { headless:
// Execute login steps manually in the browser window // Execute login steps manually in the browser window
``` ```
```java
import com.microsoft.playwright.*;
public class Example {
public static void main(String[] args) {
try (Playwright playwright = Playwright.create()) {
BrowserType chromium = playwright.chromium();
Path userDataDir = Paths.get("/path/to/directory");
BrowserContext context = chromium.launchPersistentContext(userDataDir,
new BrowserType.LaunchPersistentContextOptions().withHeadless(false));
// Execute login steps manually in the browser window
}
}
}
```
```python async ```python async
import asyncio import asyncio
from playwright.async_api import async_playwright from playwright.async_api import async_playwright
@ -246,4 +298,4 @@ with sync_playwright() as p:
### API reference ### API reference
- [BrowserContext] - [BrowserContext]
- [`method: BrowserType.launchPersistentContext`] - [`method: BrowserType.launchPersistentContext`]

View File

@ -83,6 +83,11 @@ Suggested configuration
}); });
``` ```
```java
Browser browser = playwright.chromium().launch(new BrowserType.LaunchOptions()
.withArgs(Arrays.asList("--disable-dev-shm-usage")));
```
```python async ```python async
browser = await playwright.chromium.launch( browser = await playwright.chromium.launch(
args=['--disable-dev-shm-usage'] args=['--disable-dev-shm-usage']
@ -233,6 +238,19 @@ const { chromium } = require('playwright');
const browser = await chromium.launch({ chromiumSandbox: false }); const browser = await chromium.launch({ chromiumSandbox: false });
``` ```
```java
import com.microsoft.playwright.*;
public class Example {
public static void main(String[] args) {
try (Playwright playwright = Playwright.create()) {
BrowserType chromium = playwright.chromium();
Browser browser = chromium.launch(new BrowserType.LaunchOptions().withChromiumSandbox(false));
}
}
}
```
```python async ```python async
browser = await playwright.chromium.launch(chromiumSandbox=False) browser = await playwright.chromium.launch(chromiumSandbox=False)
``` ```
@ -319,6 +337,20 @@ const { chromium } = require('playwright');
const browser = await chromium.launch({ headless: false }); const browser = await chromium.launch({ headless: false });
``` ```
```java
// Works across chromium, firefox and webkit
import com.microsoft.playwright.*;
public class Example {
public static void main(String[] args) {
try (Playwright playwright = Playwright.create()) {
BrowserType chromium = playwright.chromium();
Browser browser = chromium.launch(new BrowserType.LaunchOptions().withHeadless(false));
}
}
}
```
```python async ```python async
import asyncio import asyncio
from playwright.async_api import async_playwright from playwright.async_api import async_playwright

View File

@ -91,6 +91,27 @@ const { chromium } = require('playwright');
})(); })();
``` ```
```java
// FIXME
import com.microsoft.playwright.*;
public class Example {
public static void main(String[] args) {
try (Playwright playwright = Playwright.create()) {
BrowserType chromium = playwright.chromium();
// Make sure to run headed.
Browser browser = chromium.launch(new BrowserType.LaunchOptions().withHeadless(false));
// Setup context however you like.
BrowserContext context = browser.newContext(/* pass any options */);
context.route("**/*", route -> route.resume());
// Pause the page, and start recording manually.
Page page = context.newPage();
page.pause();
}
}
}
```
```python async ```python async
import asyncio import asyncio
from playwright.async_api import async_playwright from playwright.async_api import async_playwright

View File

@ -29,6 +29,20 @@ const browser = await chromium.launch({ headless: false });
await browser.close(); await browser.close();
``` ```
```java
import com.microsoft.playwright.*;
public class Example {
public static void main(String[] args) {
try (Playwright playwright = Playwright.create()) {
BrowserType chromium = playwright.chromium();
Browser browser = chromium.launch(new BrowserType.LaunchOptions().withHeadless(false));
browser.close();
}
}
}
```
```python async ```python async
import asyncio import asyncio
from playwright.async_api import async_playwright from playwright.async_api import async_playwright
@ -69,6 +83,11 @@ const browser = await chromium.launch();
const context = await browser.newContext(); const context = await browser.newContext();
``` ```
```java
Browser browser = chromium.launch();
BrowserContext context = 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()
@ -95,6 +114,29 @@ const context = await browser.newContext({
}); });
``` ```
```java
// FIXME
import com.microsoft.playwright.*;
public class Example {
public static void main(String[] args) {
try (Playwright playwright = Playwright.create()) {
BrowserType devices = playwright.devices();
BrowserContext context = browser.newContext(new Browser.NewContextOptions()
.withUserAgent("Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Mobile/15E148 Safari/604.1")
.withViewportSize(375, 812)
.withDeviceScaleFactor(3)
.withIsMobile(true)
.withHasTouch(true)
.withPermissions(Arrays.asList("geolocation"))
.withGeolocation(52.52, 13.39)
.withColorScheme(ColorScheme.DARK)
.withLocale("de-DE"));
}
}
}
```
```python async ```python async
import asyncio import asyncio
from playwright.async_api import async_playwright from playwright.async_api import async_playwright
@ -161,6 +203,24 @@ console.log(page.url());
window.location.href = 'https://example.com'; window.location.href = 'https://example.com';
``` ```
```java
// Create a page.
Page page = context.newPage();
// Navigate explicitly, similar to entering a URL in the browser.
page.navigate("http://example.com");
// Fill an input.
page.fill("#search", "query");
// Navigate implicitly by clicking a link.
page.click("#submit");
// Expect a new url.
System.out.println(page.url());
// Page can navigate from the script - this will be picked up by Playwright.
// window.location.href = "https://example.com";
```
```python async ```python async
page = await context.new_page() page = await context.new_page()
@ -219,6 +279,21 @@ const frame = await frameElementHandle.contentFrame();
await frame.fill('#username-input', 'John'); await frame.fill('#username-input', 'John');
``` ```
```java
// Get frame using the frame"s name attribute
Frame frame = page.frame("frame-login");
// Get frame using frame"s URL
Frame frame = page.frameByUrl(Pattern.compile(".*domain.*"));
// Get frame using any other selector
ElementHandle frameElementHandle = page.querySelector(".frame-class");
Frame frame = frameElementHandle.contentFrame();
// Interact with the frame
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')
@ -274,6 +349,11 @@ Some examples below:
await page.click('data-test-id=foo'); await page.click('data-test-id=foo');
``` ```
```java
// Using data-test-id= selector engine
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')
@ -290,6 +370,12 @@ await page.click('div');
await page.click('//html/body/div'); await page.click('//html/body/div');
``` ```
```java
// CSS and XPath selector engines are automatically detected
page.click("div");
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')
@ -307,6 +393,11 @@ page.click('//html/body/div')
await page.click('text=Hello w'); await page.click('text=Hello w');
``` ```
```java
// Find node by text substring
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')
@ -323,6 +414,12 @@ await page.click('css=div');
await page.click('xpath=//html/body/div'); await page.click('xpath=//html/body/div');
``` ```
```java
// Explicit CSS and XPath notation
page.click("css=div");
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')
@ -340,6 +437,11 @@ page.click('xpath=//html/body/div')
await page.click('css:light=div'); await page.click('css:light=div');
``` ```
```java
// Only search light DOM, outside WebComponent shadow DOM:
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')
@ -357,6 +459,11 @@ 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');
``` ```
```java
// Click an element with text "Sign Up" inside of a #free-month-promo.
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')
@ -372,6 +479,11 @@ 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);
``` ```
```java
// Capture textContent of a section that contains an element with text "Selectors".
String sectionText = (String) page.evalOnSelector("*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')
@ -401,6 +513,11 @@ and [actionable](./actionability.md). For example, click will:
await page.fill('#search', 'query'); await page.fill('#search', 'query');
``` ```
```java
// Playwright waits for #search element to be in the DOM
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')
@ -417,6 +534,12 @@ page.fill('#search', 'query')
await page.click('#search'); await page.click('#search');
``` ```
```java
// Playwright waits for element to stop animating
// and accept clicks.
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.
@ -438,6 +561,14 @@ await page.waitForSelector('#search', { state: 'attached' });
await page.waitForSelector('#promo'); await page.waitForSelector('#promo');
``` ```
```java
// Wait for #search to appear in the DOM.
page.waitForSelector("#search", new Page.WaitForSelectorOptions()
.withState(WaitForSelectorState.ATTACHED));
// Wait for #promo to become visible, for example with "visibility:visible".
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')
@ -461,6 +592,15 @@ await page.waitForSelector('#details', { state: 'hidden' });
await page.waitForSelector('#promo', { state: 'detached' }); await page.waitForSelector('#promo', { state: 'detached' });
``` ```
```java
// Wait for #details to become hidden, for example with "display:none".
page.waitForSelector("#details", new Page.WaitForSelectorOptions()
.withState(WaitForSelectorState.HIDDEN));
// Wait for #promo to be removed from the DOM.
page.waitForSelector("#promo", new Page.WaitForSelectorOptions()
.withState(WaitForSelectorState.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')
@ -495,6 +635,10 @@ of the web page and bring results back to the Playwright environment. Browser gl
const href = await page.evaluate(() => document.location.href); const href = await page.evaluate(() => document.location.href);
``` ```
```java
String href = (String) page.evaluate("document.location.href");
```
```python async ```python async
href = await page.evaluate('() => document.location.href') href = await page.evaluate('() => document.location.href')
``` ```
@ -512,6 +656,13 @@ const status = await page.evaluate(async () => {
}); });
``` ```
```java
int status = (int) page.evaluate("async () => {\n" +
" const response = await fetch(location.href);\n" +
" return response.status;\n" +
"}");
```
```python async ```python async
status = await page.evaluate("""async () => { status = await page.evaluate("""async () => {
response = await fetch(location.href) response = await fetch(location.href)
@ -573,6 +724,57 @@ await page.evaluate(
{ button1, list: [button2], foo: null }); { button1, list: [button2], foo: null });
``` ```
```java
// A primitive value.
page.evaluate("num => num", 42);
// An array.
page.evaluate("array => array.length", Arrays.asList(1, 2, 3));
// An object.
Map<String, Object> obj = new HashMap<>();
obj.put("foo", "bar");
page.evaluate("object => object.foo", obj);
// A single handle.
ElementHandle button = page.querySelector("button");
page.evaluate("button => button.textContent", button);
// Alternative notation using elementHandle.evaluate.
button.evaluate("(button, from) => button.textContent.substring(from)", 5);
// Object with multiple handles.
ElementHandle button1 = page.querySelector(".button1");
ElementHandle button2 = page.querySelector(".button2");
Map<String, ElementHandle> arg = new HashMap<>();
arg.put("button1", button1);
arg.put("button2", button2);
page.evaluate("o => o.button1.textContent + o.button2.textContent", arg);
// Object destructuring works. Note that property names must match
// between the destructured object and the argument.
// Also note the required parenthesis.
Map<String, ElementHandle> arg = new HashMap<>();
arg.put("button1", button1);
arg.put("button2", button2);
page.evaluate("({ button1, button2 }) => button1.textContent + button2.textContent", arg);
// Array works as well. Arbitrary names can be used for destructuring.
// Note the required parenthesis.
page.evaluate(
"([b1, b2]) => b1.textContent + b2.textContent",
Arrays.asList(button1, button2));
// Any non-cyclic mix of serializables and handles works.
Map<String, Object> arg = new HashMap<>();
arg.put("button1", button1);
arg.put("list", Arrays.asList(button2));
arg.put("foo", 0);
page.evaluate(
"x => x.button1.textContent + x.list[0].textContent + String(x.foo)",
arg);
```
```python async ```python async
# A primitive value. # A primitive value.
await page.evaluate('num => num', 42) await page.evaluate('num => num', 42)
@ -668,6 +870,16 @@ const result = await page.evaluate(data => {
}, data); }, data);
``` ```
```java
Map<String, Object> data = new HashMap<>();
data.put("text", "some data");
data.put("value", 1);
// Pass |data| as a parameter.
Object result = page.evaluate("data => {\n" +
" window.myApp.use(data);\n" +
"}", 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.
@ -694,6 +906,16 @@ const result = await page.evaluate(() => {
}); });
``` ```
```java
Map<String, Object> data = new HashMap<>();
data.put("text", "some data");
data.put("value", 1);
Object result = page.evaluate("() => {\n" +
" // There is no |data| in the web page.\n" +
" window.myApp.use(data);\n" +
"}");
```
```python async ```python async
data = { 'text': 'some data', 'value': 1 } data = { 'text': 'some data', 'value': 1 }
result = await page.evaluate("""() => { result = await page.evaluate("""() => {

View File

@ -26,6 +26,12 @@ 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
``` ```
```java
chromium.launch(new BrowserType.LaunchOptions() // or firefox, webkit
.withHeadless(false)
.withSlowMo(100));
```
```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
@ -75,6 +81,10 @@ In Chromium, you can also open developer tools through a launch option.
await chromium.launch({ devtools: true }); await chromium.launch({ devtools: true });
``` ```
```java
chromium.launch(new BrowserType.LaunchOptions().withDevtools(true));
```
```python async ```python async
await chromium.launch(devtools=True) await chromium.launch(devtools=True)
@ -98,6 +108,15 @@ $ set PWDEBUG=1
$ npm run test $ npm run test
``` ```
```sh java
# Linux/macOS
$ PWDEBUG=1 mvn test
# Windows
$ set PWDEBUG=1
$ mvn test
```
```sh python ```sh python
# Linux/macOS # Linux/macOS
$ PWDEBUG=1 pytest -s $ PWDEBUG=1 pytest -s
@ -152,6 +171,15 @@ $ set DEBUG=pw:api
$ npm run test $ npm run test
``` ```
```sh java
# Linux/macOS
$ DEBUG=pw:api mvn test
# Windows
$ set DEBUG=pw:api
$ mvn test
```
```sh python ```sh python
# Linux/macOS # Linux/macOS
$ DEBUG=pw:api pytest -s $ DEBUG=pw:api pytest -s

View File

@ -16,6 +16,11 @@ page.on('dialog', dialog => dialog.accept());
await page.click('button'); await page.click('button');
``` ```
```java
page.onDialog(dialog -> dialog.accept());
page.click("button");
```
```python async ```python async
page.on("dialog", lambda dialog: dialog.accept()) page.on("dialog", lambda dialog: dialog.accept())
await page.click("button") await page.click("button")
@ -41,6 +46,11 @@ page.on('dialog', dialog => console.log(dialog.message()));
await page.click('button'); // Will hang here await page.click('button'); // Will hang here
``` ```
```java
page.onDialog(dialog -> System.out.println(dialog.message()));
page.click("button"); // Will hang here
```
```python async ```python async
page.on("dialog", lambda dialog: print(dialog.message)) page.on("dialog", lambda dialog: print(dialog.message))
await page.click("button") # Will hang here await page.click("button") # Will hang here
@ -75,6 +85,14 @@ page.on('dialog', async dialog => {
await page.close({runBeforeUnload: true}); await page.close({runBeforeUnload: true});
``` ```
```java
page.onDialog(dialog -> {
assertEquals("beforeunload", dialog.type());
dialog.dismiss();
});
page.close(new Page.CloseOptions().withRunBeforeUnload(true));
```
```python async ```python async
async def handle_dialog(dialog): async def handle_dialog(dialog):
assert dialog.type == 'beforeunload' assert dialog.type == 'beforeunload'

View File

@ -58,6 +58,10 @@ If you have no idea what initiates the download, you can still handle the event:
page.on('download', download => download.path().then(console.log)); page.on('download', download => download.path().then(console.log));
``` ```
```java
page.onDownload(download -> System.out.println(download.path()));
```
```python async ```python async
async def handle_download(download): async def handle_download(download):
print(await download.path()) print(await download.path())

View File

@ -81,6 +81,11 @@ const context = await browser.newContext({
}); });
``` ```
```java
BrowserContext context = browser.newContext(new Browser.NewContextOptions()
.withUserAgent("My user agent"));
```
```python async ```python async
context = await browser.new_context( context = await browser.new_context(
user_agent='My user agent' user_agent='My user agent'
@ -118,6 +123,20 @@ const context = await browser.newContext({
}); });
``` ```
```java
// Create context with given viewport
BrowserContext context = browser.newContext(new Browser.NewContextOptions()
.withViewportSize(1280, 1024));
// Resize viewport for individual page
page.setViewportSize(1600, 1200);
// Emulate high-DPI
BrowserContext context = browser.newContext(new Browser.NewContextOptions()
.withViewportSize(2560, 1440)
.withDeviceScaleFactor(2);
```
```python async ```python async
# Create context with given viewport # Create context with given viewport
context = await browser.new_context( context = await browser.new_context(
@ -165,6 +184,13 @@ const context = await browser.newContext({
}); });
``` ```
```java
// Emulate locale and time
BrowserContext context = browser.newContext(new Browser.NewContextOptions()
.withLocale("de-DE")
.withTimezoneId("Europe/Berlin"));
```
```python async ```python async
# Emulate locale and time # Emulate locale and time
context = await browser.new_context( context = await browser.new_context(
@ -196,6 +222,11 @@ const context = await browser.newContext({
}); });
``` ```
```java
BrowserContext context = browser.newContext(new Browser.NewContextOptions()
.withPermissions(Arrays.asList("notifications"));
```
```python async ```python async
context = await browser.new_context( context = await browser.new_context(
permissions=['notifications'], permissions=['notifications'],
@ -214,6 +245,10 @@ Grant all pages in the existing context access to current location:
await context.grantPermissions(['geolocation']); await context.grantPermissions(['geolocation']);
``` ```
```java
context.grantPermissions(Arrays.asList("geolocation"));
```
```python async ```python async
await context.grant_permissions(['geolocation']) await context.grant_permissions(['geolocation'])
``` ```
@ -228,6 +263,11 @@ Grant notifications access from a specific domain:
await context.grantPermissions(['notifications'], {origin: 'https://skype.com'} ); await context.grantPermissions(['notifications'], {origin: 'https://skype.com'} );
``` ```
```java
context.grantPermissions(Arrays.asList("notifications"),
new BrowserContext.GrantPermissionsOptions().withOrigin("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')
``` ```
@ -242,6 +282,10 @@ Revoke all permissions:
await context.clearPermissions(); await context.clearPermissions();
``` ```
```java
context.clearPermissions();
```
```python async ```python async
await context.clear_permissions() await context.clear_permissions()
``` ```
@ -268,6 +312,12 @@ const context = await browser.newContext({
}); });
``` ```
```java
BrowserContext context = browser.newContext(new Browser.NewContextOptions()
.withGeolocation(48.858455, 2.294474)
.withPermissions(Arrays.asList("geolocation")));
```
```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},
@ -288,6 +338,10 @@ Change the location later:
await context.setGeolocation({ longitude: 29.979097, latitude: 31.134256 }); await context.setGeolocation({ longitude: 29.979097, latitude: 31.134256 });
``` ```
```java
context.setGeolocation(new Geolocation(29.979097, 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})
``` ```
@ -326,6 +380,22 @@ await page.emulateMedia({ colorScheme: 'dark' });
await page.emulateMedia({ media: 'print' }); await page.emulateMedia({ media: 'print' });
``` ```
```java
// Create context with dark mode
BrowserContext context = browser.newContext(new Browser.NewContextOptions()
.withColorScheme(ColorScheme.DARK)); // or "light"
// Create page with dark mode
Page page = browser.newPage(new Browser.NewPageOptions()
.withColorScheme(ColorScheme.DARK)); // or "light"
// Change color scheme for the page
page.emulateMedia(new Page.EmulateMediaOptions().withColorScheme(ColorScheme.DARK));
// Change media for page
page.emulateMedia(new Page.EmulateMediaOptions().withMedia(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(

View File

@ -51,6 +51,33 @@ await page.click('tag=div >> span >> "Click me"');
const buttonCount = await page.$$eval('tag=button', buttons => buttons.length); const buttonCount = await page.$$eval('tag=button', buttons => buttons.length);
``` ```
```java
// Must be a script that evaluates to a selector engine instance.
String createTagNameEngine = "{\n" +
" // Returns the first element matching given selector in the root's subtree.\n" +
" query(root, selector) {\n" +
" return root.querySelector(selector);\n" +
" },\n" +
"\n" +
" // Returns all elements matching given selector in the root's subtree.\n" +
" queryAll(root, selector) {\n" +
" return Array.from(root.querySelectorAll(selector));\n" +
" }\n" +
"}";
// Register the engine. Selectors will be prefixed with "tag=".
playwright.selectors().register("tag", createTagNameEngine);
// Now we can use "tag=" selectors.
ElementHandle button = page.querySelector("tag=button");
// We can combine it with other selector engines using ">>" combinator.
page.click("tag=div >> span >> \"Click me\"");
// We can use it in any methods supporting selectors.
int buttonCount = (int) page.evalOnSelectorAll("tag=button", "buttons => buttons.length");
```
```python async ```python async
tag_selector = """ tag_selector = """
// Must evaluate to a selector engine instance. // Must evaluate to a selector engine instance.

View File

@ -28,6 +28,11 @@ const jsHandle = await page.evaluateHandle('window');
// Use jsHandle for evaluations. // Use jsHandle for evaluations.
``` ```
```java
JSHandle jsHandle = page.evaluateHandle("window");
// Use jsHandle for evaluations.
```
```python async ```python async
js_handle = await page.evaluate_handle('window') js_handle = await page.evaluate_handle('window')
# Use jsHandle for evaluations. # Use jsHandle for evaluations.
@ -43,6 +48,11 @@ const ulElementHandle = await page.waitForSelector('ul');
// Use ulElementHandle for actions and evaluation. // Use ulElementHandle for actions and evaluation.
``` ```
```java
ElementHandle ulElementHandle = page.waitForSelector("ul");
// Use ulElementHandle for actions and evaluation.
```
```python async ```python async
ul_element_handle = await page.wait_for_selector('ul') ul_element_handle = await page.wait_for_selector('ul')
# Use ul_element_handle for actions and evaluation. # Use ul_element_handle for actions and evaluation.
@ -76,6 +86,20 @@ const classNames = await elementHandle.getAttribute('class');
expect(classNames.includes('highlighted')).toBeTruthy(); expect(classNames.includes('highlighted')).toBeTruthy();
``` ```
```java
// Get the element handle
JSHandle jsHandle = page.waitForSelector("#box");
ElementHandle elementHandle = jsHandle.asElement();
// Assert bounding box for the element
BoundingBox boundingBox = elementHandle.boundingBox();
assertEquals(100, boundingBox.width);
// Assert attribute for the element
String classNames = elementHandle.getAttribute("class");
assertTrue(classNames.contains("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')
@ -129,6 +153,26 @@ await page.evaluate(arg => arg.myArray.push(arg.newElement), {
await myArrayHandle.dispose(); await myArrayHandle.dispose();
``` ```
```java
// Create new array in page.
JSHandle myArrayHandle = page.evaluateHandle("() => {\n" +
" window.myArray = [1];\n" +
" return myArray;\n" +
"}");
// Get the length of the array.
int length = (int) page.evaluate("a => a.length", myArrayHandle);
// Add one more element to the array using the handle
Map<String, Object> arg = new HashMap<>();
arg.put("myArray", myArrayHandle);
arg.put("newElement", 2);
page.evaluate("arg => arg.myArray.add(arg.newElement)", arg);
// Release the object when it"s no longer needed.
myArrayHandle.dispose();
```
```python async ```python async
# Create new array in page. # Create new array in page.
my_array_handle = await page.evaluate_handle("""() => { my_array_handle = await page.evaluate_handle("""() => {

View File

@ -26,6 +26,23 @@ await page.fill('#local', '2020-03-02T05:15');
await page.fill('text=First Name', 'Peter'); await page.fill('text=First Name', 'Peter');
``` ```
```java
// Text input
page.fill("#name", "Peter");
// Date input
page.fill("#date", "2020-02-02");
// Time input
page.fill("#time", "13-15");
// Local datetime input
page.fill("#local", "2020-03-02T05:15");
// Input through label
page.fill("text=First Name", "Peter");
```
```python async ```python async
# Text input # Text input
await page.fill('#name', 'Peter') await page.fill('#name', 'Peter')
@ -86,6 +103,20 @@ await page.uncheck('#subscribe-label');
await page.check('text=XL'); await page.check('text=XL');
``` ```
```java
// Check the checkbox
page.check("#agree");
// Assert the checked state
assertTrue(page.isChecked("#agree"));
// Uncheck by input <label>.
page.uncheck("#subscribe-label");
// Select the radio button
page.check("text=XL");
```
```python async ```python async
# Check the checkbox # Check the checkbox
await page.check('#agree') await page.check('#agree')
@ -145,6 +176,21 @@ const option = await page.$('#best-option');
await page.selectOption('select#colors', option); await page.selectOption('select#colors', option);
``` ```
```java
// Single selection matching the value
page.selectOption("select#colors", "blue");
// Single selection matching the label
page.selectOption("select#colors", new SelectOption().withLabel("Blue"));
// Multiple selected items
page.selectOption("select#colors", new String[] {"red", "green", "blue"});
// Select the option via element handle
ElementHandle option = page.querySelector("#best-option");
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')
@ -207,6 +253,26 @@ await page.hover('#item');
await page.click('#item', { position: { x: 0, y: 0} }); await page.click('#item', { position: { x: 0, y: 0} });
``` ```
```java
// Generic click
page.click("button#submit");
// Double click
page.dblclick("#item");
// Right click
page.click("#item", new Page.ClickOptions().withButton(MouseButton.RIGHT));
// Shift + click
page.click("#item", new Page.ClickOptions().withModifiers(Arrays.asList(KeyboardModifier.SHIFT)));
// Hover over element
page.hover("#item");
// Click the top left corner
page.click("#item", new Page.ClickOptions().withPosition(0, 0));
```
```python async ```python async
# Generic click # Generic click
await page.click('button#submit') await page.click('button#submit')
@ -264,6 +330,10 @@ 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 });
``` ```
```java
page.click("button#submit", new Page.ClickOptions().withForce(true));
```
```python async ```python async
await page.click('button#submit', force=True) await page.click('button#submit', force=True)
``` ```
@ -280,6 +350,10 @@ 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');
``` ```
```java
page.dispatchEvent("button#submit", "click");
```
```python async ```python async
await page.dispatch_event('button#submit', 'click') await page.dispatch_event('button#submit', 'click')
``` ```
@ -314,6 +388,11 @@ 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!');
``` ```
```java
// Type character by character
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!')
@ -352,6 +431,17 @@ await page.press('#name', 'Control+ArrowRight');
await page.press('#value', '$'); await page.press('#value', '$');
``` ```
```java
// Hit Enter
page.press("#submit", "Enter");
// Dispatch Control+Right
page.press("#name", "Control+ArrowRight");
// Press $ sign on keyboard
page.press("#value", "$");
```
```python async ```python async
# Hit Enter # Hit Enter
await page.press('#submit', 'Enter') await page.press('#submit', 'Enter')
@ -397,6 +487,14 @@ await page.press('#name', 'Shift+A');
await page.press('#name', 'Shift+ArrowLeft'); await page.press('#name', 'Shift+ArrowLeft');
``` ```
```java
// <input id=name>
page.press("#name", "Shift+A");
// <input id=name>
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')
@ -449,6 +547,21 @@ await page.setInputFiles('input#upload', {
}); });
``` ```
```java
// Select one file
page.setInputFiles("input#upload", Paths.get("myfile.pdf"));
// Select multiple files
page.setInputFiles("input#upload", new Path[] {Paths.get("file1.txt"), Paths.get("file2.txt")});
// Remove all the selected files
page.setInputFiles("input#upload", new Path[0]);
// Upload buffer from memory
page.setInputFiles("input#upload", new FilePayload(
"file.txt", "text/plain", "this is test".getBytes(StandardCharsets.UTF_8)));
```
```python async ```python async
# Select one file # Select one file
await page.set_input_files('input#upload', 'myfile.pdf') await page.set_input_files('input#upload', 'myfile.pdf')
@ -498,6 +611,13 @@ const [fileChooser] = await Promise.all([
await fileChooser.setFiles('myfile.pdf'); await fileChooser.setFiles('myfile.pdf');
``` ```
```java
FileChooser fileChooser = page.waitForFileChooser(() -> {
page.click("upload");
});
fileChooser.setFiles(Paths.get("myfile.pdf"));
```
```python async ```python async
async with page.expect_file_chooser() as fc_info: async with page.expect_file_chooser() as fc_info:
await page.click("upload") await page.click("upload")
@ -528,6 +648,10 @@ For the dynamic pages that handle focus events, you can focus the given element.
await page.focus('input#name'); await page.focus('input#name');
``` ```
```java
page.focus("input#name");
```
```python async ```python async
await page.focus('input#name') await page.focus('input#name')
``` ```

View File

@ -44,6 +44,11 @@ configures Playwright for debugging and opens the inspector.
await page.pause(); await page.pause();
``` ```
```java
// Pause on the following line.
page.pause();
```
```python async ```python async
# Pause on the following line. # Pause on the following line.
await page.pause() await page.pause()

View File

@ -28,6 +28,27 @@ await userContext.addCookies(userCookies);
await adminContext.addCookies(adminCookies); await adminContext.addCookies(adminCookies);
``` ```
```java
// FIXME
import com.microsoft.playwright.*;
public class Example {
public static void main(String[] args) {
try (Playwright playwright = Playwright.create()) {
BrowserType chromium = playwright.chromium();
// Create a Chromium browser instance
Browser browser = chromium.launch();
// Create two isolated browser contexts
BrowserContext userContext = browser.newContext();
BrowserContext adminContext = browser.newContext();
// Load user and admin cookies
userContext.addCookies(userCookies);
adminContext.addCookies(adminCookies);
}
}
}
```
```python async ```python async
import asyncio import asyncio
from playwright.async_api import async_playwright from playwright.async_api import async_playwright
@ -92,6 +113,15 @@ const pageTwo = await context.newPage();
const allPages = context.pages(); const allPages = context.pages();
``` ```
```java
// Create two pages
Page pageOne = context.newPage();
Page pageTwo = context.newPage();
// Get pages of a brower context
List<Page> allPages = context.pages();
```
```python async ```python async
# create two pages # create two pages
page_one = await context.new_page() page_one = await context.new_page()
@ -130,6 +160,15 @@ await newPage.waitForLoadState();
console.log(await newPage.title()); console.log(await newPage.title());
``` ```
```java
// Get page after a specific action (e.g. clicking a link)
Page newPage = context.waitForPage(() -> {
page.click("a[target='_blank']"); // Opens a new tab
});
newPage.waitForLoadState();
System.out.println(newPage.title());
```
```python async ```python async
# Get page after a specific action (e.g. clicking a link) # Get page after a specific action (e.g. clicking a link)
async with context.expect_page() as new_page_info: async with context.expect_page() as new_page_info:
@ -160,6 +199,14 @@ context.on('page', async page => {
}) })
``` ```
```java
// Get all new pages (including popups) in the context
context.onPage(page -> {
page.waitForLoadState();
System.out.println(page.title());
});
```
```python async ```python async
# Get all new pages (including popups) in the context # Get all new pages (including popups) in the context
async def handle_page(page): async def handle_page(page):
@ -197,6 +244,15 @@ await popup.waitForLoadState();
console.log(await popup.title()); console.log(await popup.title());
``` ```
```java
// Get popup after a specific action (e.g., click)
Page popup = page.waitForPopup(() -> {
page.click("#open");
});
popup.waitForLoadState();
System.out.println(popup.title());
```
```python async ```python async
# Get popup after a specific action (e.g., click) # Get popup after a specific action (e.g., click)
async with page.expect_popup() as popup_info: async with page.expect_popup() as popup_info:
@ -227,6 +283,14 @@ page.on('popup', async popup => {
}) })
``` ```
```java
// Get all popups when they open
page.onPopup(popup -> {
popup.waitForLoadState();
System.out.println(popup.title());
});
```
```python async ```python async
# Get all popups when they open # Get all popups when they open
async def handle_popup(popup): async def handle_popup(popup):

View File

@ -41,6 +41,11 @@ Navigating to a URL auto-waits for the page to fire the `load` event. If the pag
await page.goto('https://example.com'); await page.goto('https://example.com');
``` ```
```java
// Navigate the page
page.navigate("https://example.com");
```
```python async ```python async
# Navigate the page # Navigate the page
await page.goto("https://example.com") await page.goto("https://example.com")
@ -60,6 +65,12 @@ Override the default behavior to wait until a specific event, like `networkidle`
await page.goto('https://example.com', { waitUntil: 'networkidle' }); await page.goto('https://example.com', { waitUntil: 'networkidle' });
``` ```
```java
// Navigate and wait until network is idle
page.navigate("https://example.com", new Page.NavigateOptions()
.withWaitUntil(WaitUntilState.NETWORKIDLE));
```
```python async ```python async
# Navigate and wait until network is idle # Navigate and wait until network is idle
await page.goto("https://example.com", wait_until="networkidle") await page.goto("https://example.com", wait_until="networkidle")
@ -86,6 +97,17 @@ await page.goto('https://example.com');
await page.click('text=Example Domain'); await page.click('text=Example Domain');
``` ```
```java
// Navigate and wait for element
page.navigate("https://example.com");
page.waitForSelector("text=Example Domain");
// Navigate and click element
// Click will auto-wait for the element
page.navigate("https://example.com");
page.click("text=Example Domain");
```
```python async ```python async
# Navigate and wait for element # Navigate and wait for element
await page.goto("https://example.com") await page.goto("https://example.com")
@ -126,10 +148,19 @@ the navigated page which would auto-wait for an element.
```js ```js
// Click will auto-wait for navigation to complete // Click will auto-wait for navigation to complete
await page.click('text=Login'); await page.click('text=Login');
// Fill will auto-wait for element on navigated page // Fill will auto-wait for element on navigated page
await page.fill('#username', 'John Doe'); await page.fill('#username', 'John Doe');
``` ```
```java
// Click will auto-wait for navigation to complete
page.click("text=Login");
// Fill will auto-wait for element on navigated page
page.fill("#username", "John Doe");
```
```python async ```python async
# Click will auto-wait for navigation to complete # Click will auto-wait for navigation to complete
await page.click("text=Login") await page.click("text=Login")
@ -155,6 +186,11 @@ await page.click('button'); // Click triggers navigation
await page.waitForLoadState('networkidle'); // This resolves after 'networkidle' await page.waitForLoadState('networkidle'); // This resolves after 'networkidle'
``` ```
```java
page.click("button"); // Click triggers navigation
page.waitForLoadState(LoadState.NETWORKIDLE); // This resolves after "networkidle"
```
```python async ```python async
await page.click("button"); # Click triggers navigation await page.click("button"); # Click triggers navigation
await page.wait_for_load_state("networkidle"); # This waits for the "networkidle" await page.wait_for_load_state("networkidle"); # This waits for the "networkidle"
@ -171,10 +207,10 @@ In lazy-loaded pages, it can be useful to wait until an element is visible with
Alternatively, page interactions like [`method: Page.click`] auto-wait for elements. Alternatively, page interactions like [`method: Page.click`] auto-wait for elements.
```js ```js
// Click triggers navigation // Click will auto-wait for the element and trigger navigation
await page.click('text=Login'); await page.click('text=Login');
// Click will auto-wait for the element // Wait for the element
await page.waitForSelector('#username', 'John Doe'); await page.waitForSelector('#username');
// Click triggers navigation // Click triggers navigation
await page.click('text=Login'); await page.click('text=Login');
@ -182,11 +218,23 @@ await page.click('text=Login');
await page.fill('#username', 'John Doe'); await page.fill('#username', 'John Doe');
``` ```
```java
// Click will auto-wait for the element and trigger navigation
page.click("text=Login");
// Wait for the element
page.waitForSelector("#username");
// Click triggers navigation
page.click("text=Login");
// Fill will auto-wait for element
page.fill("#username", "John Doe");
```
```python async ```python async
# Click triggers navigation # Click will auto-wait for the element and trigger navigation
await page.click("text=Login") await page.click("text=Login")
# Click will auto-wait for the element # Wait for the element
await page.wait_for_selector("#username", "John Doe") await page.wait_for_selector("#username")
# Click triggers navigation # Click triggers navigation
await page.click("text=Login") await page.click("text=Login")
@ -222,6 +270,14 @@ await Promise.all([
]); ]);
``` ```
```java
// Using waitForNavigation with a callback prevents a race condition
// between clicking and waiting for a navigation.
page.waitForNavigation(() -> { // Waits for the next navigation
page.click("a"); // Triggers a navigation after a timeout
});
```
```python async ```python async
# Waits for the next navigation. Using Python context manager # Waits for the next navigation. Using Python context manager
# prevents a race condition between clicking and waiting for a navigation. # prevents a race condition between clicking and waiting for a navigation.
@ -254,6 +310,14 @@ await Promise.all([
]); ]);
``` ```
```java
// Running action in the callback of waitForNavigation prevents a race
// condition between clicking and waiting for a navigation.
page.waitForNavigation(new Page.WaitForNavigationOptions().withUrl("**/login"), () -> {
page.click("a"); // Triggers a navigation with a script redirect
});
```
```python async ```python async
# Using Python context manager prevents a race condition # Using Python context manager prevents a race condition
# between clicking and waiting for a navigation. # between clicking and waiting for a navigation.
@ -283,6 +347,13 @@ const [ popup ] = await Promise.all([
await popup.waitForLoadState('load'); await popup.waitForLoadState('load');
``` ```
```java
Page popup = page.waitForPopup(() -> {
page.click("a[target='_blank']"); // Opens popup
});
popup.waitForLoadState(LoadState.LOAD);
```
```python async ```python async
async with page.expect_popup() as popup_info: async with page.expect_popup() as popup_info:
await page.click('a[target="_blank"]') # Opens popup await page.click('a[target="_blank"]') # Opens popup
@ -316,6 +387,13 @@ await page.waitForFunction(() => window.amILoadedYet());
await page.screenshot(); await page.screenshot();
``` ```
```java
page.navigate("http://example.com");
page.waitForFunction("() => window.amILoadedYet()");
// Ready to take a screenshot, according to the page itself.
page.screenshot();
```
```python async ```python async
await page.goto("http://example.com") await page.goto("http://example.com")
await page.wait_for_function("() => window.amILoadedYet()") await page.wait_for_function("() => window.amILoadedYet()")

View File

@ -24,6 +24,13 @@ const page = await context.newPage();
await page.goto('https://example.com'); await page.goto('https://example.com');
``` ```
```java
BrowserContext context = browser.newContext(new Browser.NewContextOptions()
.withHttpCredentials("bill", "pa55w0rd"));
Page page = context.newPage();
page.navigate("https://example.com");
```
```python async ```python async
context = await browser.new_context( context = await browser.new_context(
http_credentials={"username": "bill", "password": "pa55w0rd"} http_credentials={"username": "bill", "password": "pa55w0rd"}
@ -65,6 +72,24 @@ const { chromium, webkit, firefox } = require('playwright');
})(); })();
``` ```
```java
import com.microsoft.playwright.*;
public class Example {
public static void main(String[] args) {
try (Playwright playwright = Playwright.create()) {
BrowserType chromium = playwright.chromium();
Browser browser = chromium.launch();
Page page = browser.newPage();
page.onRequest(request -> System.out.println(">> " + request.method() + " " + request.url()));
page.onResponse(response -> System.out.println("<<" + response.status() + " " + response.url()));
page.navigate("https://example.com");
browser.close();
}
}
}
```
```python async ```python async
import asyncio import asyncio
from playwright.async_api import async_playwright from playwright.async_api import async_playwright
@ -112,6 +137,13 @@ const [response] = await Promise.all([
]); ]);
``` ```
```java
// Use a glob URL pattern
Response response = page.waitForResponse("**/api/fetch_data", () -> {
page.click("button#update");
});
```
```python async ```python async
# Use a glob url pattern # Use a glob url pattern
async with page.expect_response("**/api/fetch_data") as response_info: async with page.expect_response("**/api/fetch_data") as response_info:
@ -142,6 +174,18 @@ const [response] = await Promise.all([
]); ]);
``` ```
```java
// Use a RegExp
Response response = page.waitForResponse(Pattern.compile("\\.jpeg$"), () -> {
page.click("button#update");
});
// Use a predicate taking a Response object
Response response = page.waitForResponse(r -> r.url().contains(token), () -> {
page.click("button#update");
});
```
```python async ```python async
# Use a regular expression # Use a regular expression
async with page.expect_response(re.compile(r"\.jpeg$")) as response_info: async with page.expect_response(re.compile(r"\.jpeg$")) as response_info:
@ -186,6 +230,13 @@ await page.route('**/api/fetch_data', route => route.fulfill({
await page.goto('https://example.com'); await page.goto('https://example.com');
``` ```
```java
page.route("**/api/fetch_data", route -> route.fulfill(new Route.FulfillOptions()
.withStatus(200)
.withBody(testData)));
page.navigate("https://example.com");
```
```python async ```python async
await page.route( await page.route(
"**/api/fetch_data", "**/api/fetch_data",
@ -215,6 +266,13 @@ await browserContext.route('**/api/login', route => route.fulfill({
await page.goto('https://example.com'); await page.goto('https://example.com');
``` ```
```java
browserContext.route("**/api/login", route -> route.fulfill(new Route.FulfillOptions()
.withStatus(200)
.withBody("accept")));
page.navigate("https://example.com");
```
```python async ```python async
# Set up route on the entire browser context. # Set up route on the entire browser context.
# It will apply to popup windows and opened links. # It will apply to popup windows and opened links.
@ -256,6 +314,18 @@ await page.route('**/*', route => {
await page.route('**/*', route => route.continue({method: 'POST'})); await page.route('**/*', route => route.continue({method: 'POST'}));
``` ```
```java
// Delete header
page.route("**/*", route -> {
Map<String, String> headers = new HashMap<>(route.request().headers());
headers.remove("X-Secret");
route.resume(new Route.ResumeOptions().withHeaders(headers));
});
// Continue requests as POST.
page.route("**/*", route -> route.resume(new Route.ResumeOptions().withMethod("POST")));
```
```python async ```python async
# Delete header # Delete header
async def handle_route(route): async def handle_route(route):
@ -294,6 +364,18 @@ await page.route('**/*', route => {
}); });
``` ```
```java
page.route("**/*.{png,jpg,jpeg}", route -> route.abort());
// Abort based on the request type
page.route("**/*", route -> {
if ("image".equals(route.request().resourceType()))
route.abort();
else
route.resume();
});
```
```python async ```python async
await page.route("**/*.{png,jpg,jpeg}", lambda route: route.abort()) await page.route("**/*.{png,jpg,jpeg}", lambda route: route.abort())

View File

@ -39,6 +39,30 @@ class SearchPage {
module.exports = { SearchPage }; module.exports = { SearchPage };
``` ```
```java
// models/SearchPage.java
package models;
import com.microsoft.playwright;
public class SearchPage {
private final Page page;
public SearchPage(Page page) {
this.page = page;
}
public void navigate() {
page.navigate("https://bing.com");
}
public void search(String text) {
page.fill("[aria-label='Enter your search term']", text);
page.press("[aria-label='Enter your search term']", "Enter");
}
}
```
```python async ```python async
# models/search.py # models/search.py
class SearchPage: class SearchPage:
@ -80,6 +104,18 @@ await searchPage.navigate();
await searchPage.search('search query'); await searchPage.search('search query');
``` ```
```java
import models.SearchPage;
import com.microsoft.playwright.*;
...
// In the test
Page page = browser.newPage();
SearchPage searchPage = new SearchPage(page);
searchPage.navigate();
searchPage.search("search query");
```
```python async ```python async
# test_search.py # test_search.py
from models.search import SearchPage from models.search import SearchPage

View File

@ -30,6 +30,12 @@ tall screen and the page could fit it entirely.
await page.screenshot({ path: 'screenshot.png', fullPage: true }); await page.screenshot({ path: 'screenshot.png', fullPage: true });
``` ```
```java
page.screenshot(new Page.ScreenshotOptions()
.withPath(Paths.get("screenshot.png"))
.withFullPage(true));
```
```python async ```python async
await page.screenshot(path="screenshot.png", full_page=True) await page.screenshot(path="screenshot.png", full_page=True)
``` ```
@ -47,6 +53,11 @@ const buffer = await page.screenshot();
console.log(buffer.toString('base64')); console.log(buffer.toString('base64'));
``` ```
```java
byte[] buffer = page.screenshot();
System.out.println(Base64.getEncoder().encode(buffer));
```
```python async ```python async
# Capture into Image # Capture into Image
screenshot_bytes = await page.screenshot() screenshot_bytes = await page.screenshot()
@ -67,6 +78,11 @@ const elementHandle = await page.$('.header');
await elementHandle.screenshot({ path: 'screenshot.png' }); await elementHandle.screenshot({ path: 'screenshot.png' });
``` ```
```java
ElementHandle elementHandle = page.querySelector(".header");
elementHandle.screenshot(new ElementHandle.ScreenshotOptions().withPath(Paths.get("screenshot.png")));
```
```python async ```python async
element_handle = await page.query_selector(".header") element_handle = await page.query_selector(".header")
await element_handle.screenshot(path="screenshot.png") await element_handle.screenshot(path="screenshot.png")

View File

@ -15,6 +15,9 @@ methods accept [`param: selector`] as their first argument.
```js ```js
await page.click('text=Log in'); await page.click('text=Log in');
``` ```
```java
page.click("text=Log in");
```
```python async ```python async
await page.click("text=Log in") await page.click("text=Log in")
``` ```
@ -27,6 +30,10 @@ methods accept [`param: selector`] as their first argument.
await page.click('button'); await page.click('button');
await page.click('#nav-bar .contact-us-item'); await page.click('#nav-bar .contact-us-item');
``` ```
```java
page.click("button");
page.click("#nav-bar .contact-us-item");
```
```python async ```python async
await page.click("button") await page.click("button")
await page.click("#nav-bar .contact-us-item") await page.click("#nav-bar .contact-us-item")
@ -41,6 +48,10 @@ methods accept [`param: selector`] as their first argument.
await page.click('[data-test=login-button]'); await page.click('[data-test=login-button]');
await page.click('[aria-label="Sign in"]'); await page.click('[aria-label="Sign in"]');
``` ```
```java
page.click("[data-test=login-button]");
page.click("[aria-label='Sign in']");
```
```python async ```python async
await page.click("[data-test=login-button]") await page.click("[data-test=login-button]")
await page.click("[aria-label='Sign in']") await page.click("[aria-label='Sign in']")
@ -55,6 +66,10 @@ methods accept [`param: selector`] as their first argument.
await page.click('article:has-text("Playwright")'); await page.click('article:has-text("Playwright")');
await page.click('#nav-bar :text("Contact us")'); await page.click('#nav-bar :text("Contact us")');
``` ```
```java
page.click("article:has-text(\"Playwright\")");
page.click("#nav-bar :text(\"Contact us\")");
```
```python async ```python async
await page.click("article:has-text('Playwright')") await page.click("article:has-text('Playwright')")
await page.click("#nav-bar :text('Contact us')") await page.click("#nav-bar :text('Contact us')")
@ -68,6 +83,9 @@ methods accept [`param: selector`] as their first argument.
```js ```js
await page.click('.item-description:has(.item-promo-banner)'); await page.click('.item-description:has(.item-promo-banner)');
``` ```
```java
page.click(".item-description:has(.item-promo-banner)");
```
```python async ```python async
await page.click(".item-description:has(.item-promo-banner)") await page.click(".item-description:has(.item-promo-banner)")
``` ```
@ -79,6 +97,9 @@ methods accept [`param: selector`] as their first argument.
```js ```js
await page.click('input:right-of(:text("Username"))'); await page.click('input:right-of(:text("Username"))');
``` ```
```java
page.click("input:right-of(:text(\"Username\"))");
```
```python async ```python async
await page.click("input:right-of(:text('Username'))") await page.click("input:right-of(:text('Username'))")
``` ```
@ -90,6 +111,9 @@ methods accept [`param: selector`] as their first argument.
```js ```js
await page.click('.login-button:visible'); await page.click('.login-button:visible');
``` ```
```java
page.click(".login-button:visible");
```
```python async ```python async
await page.click(".login-button:visible") await page.click(".login-button:visible")
``` ```
@ -101,6 +125,9 @@ methods accept [`param: selector`] as their first argument.
```js ```js
await page.click(':nth-match(:text("Buy"), 3)'); await page.click(':nth-match(:text("Buy"), 3)');
``` ```
```java
page.click(":nth-match(:text('Buy'), 3)");
```
```python async ```python async
await page.click(":nth-match(:text('Buy'), 3)" await page.click(":nth-match(:text('Buy'), 3)"
``` ```
@ -112,6 +139,9 @@ methods accept [`param: selector`] as their first argument.
```js ```js
await page.click('xpath=//button'); await page.click('xpath=//button');
``` ```
```java
page.click("xpath=//button");
```
```python async ```python async
await page.click("xpath=//button") await page.click("xpath=//button")
``` ```
@ -127,6 +157,9 @@ Text selector locates elements that contain passed text.
```js ```js
await page.click('text=Log in'); await page.click('text=Log in');
``` ```
```java
page.click("text=Log in");
```
```python async ```python async
await page.click("text=Log in") await page.click("text=Log in")
``` ```
@ -141,6 +174,9 @@ Text selector has a few variations:
```js ```js
await page.click('text=Log in'); await page.click('text=Log in');
``` ```
```java
page.click("text=Log in");
```
```python async ```python async
await page.click("text=Log in") await page.click("text=Log in")
``` ```
@ -155,6 +191,9 @@ Text selector has a few variations:
```js ```js
await page.click('text="Log in"'); await page.click('text="Log in"');
``` ```
```java
page.click("text='Log in'");
```
```python async ```python async
await page.click("text='Log in'") await page.click("text='Log in'")
``` ```
@ -167,6 +206,9 @@ Text selector has a few variations:
```js ```js
await page.click('"Log in"'); await page.click('"Log in"');
``` ```
```java
page.click("'Log in'");
```
```python async ```python async
await page.click("'Log in'") await page.click("'Log in'")
``` ```
@ -179,6 +221,9 @@ Text selector has a few variations:
```js ```js
await page.click('text=/Log\\s*in/i'); await page.click('text=/Log\\s*in/i');
``` ```
```java
page.click("text=/Log\\s*in/i");
```
```python async ```python async
await page.click("text=/Log\s*in/i") await page.click("text=/Log\s*in/i")
``` ```
@ -195,6 +240,14 @@ Text selector has a few variations:
// Correct, only matches the <article> element // Correct, only matches the <article> element
await page.click('article:has-text("Playwright")'); await page.click('article:has-text("Playwright")');
``` ```
```java
// Wrong, will match many elements including <body>
page.click(":has-text(\"Playwright\")");
// Correct, only matches the <article> element
page.click("article:has-text(\"Playwright\")");
```
```python async ```python async
# Wrong, will match many elements including <body> # Wrong, will match many elements including <body>
await page.click(':has-text("Playwright")') await page.click(':has-text("Playwright")')
@ -213,6 +266,9 @@ Text selector has a few variations:
```js ```js
await page.click('#nav-bar :text("Home")'); await page.click('#nav-bar :text("Home")');
``` ```
```java
page.click("#nav-bar :text('Home')");
```
```python async ```python async
await page.click("#nav-bar :text('Home')") await page.click("#nav-bar :text('Home')")
``` ```
@ -242,6 +298,10 @@ Playwright augments standard CSS selectors in two ways:
await page.click('button'); await page.click('button');
``` ```
```java
page.click("button");
```
```python async ```python async
await page.click("button") await page.click("button")
``` ```
@ -275,6 +335,10 @@ Consider a page with two buttons, first invisible and second visible.
await page.click('button'); await page.click('button');
``` ```
```java
page.click("button");
```
```python async ```python async
await page.click("button") await page.click("button")
``` ```
@ -288,6 +352,9 @@ Consider a page with two buttons, first invisible and second visible.
```js ```js
await page.click('button:visible'); await page.click('button:visible');
``` ```
```java
page.click("button:visible");
```
```python async ```python async
await page.click("button:visible") await page.click("button:visible")
``` ```
@ -310,6 +377,10 @@ Following snippet returns text content of an `<article>` element that has a `<di
await page.textContent('article:has(div.promo)'); await page.textContent('article:has(div.promo)');
``` ```
```java
page.textContent("article:has(div.promo)");
```
```python async ```python async
await page.textContent("article:has(div.promo)") await page.textContent("article:has(div.promo)")
``` ```
@ -330,6 +401,11 @@ selectors in a more compact form.
await page.click(':is(button:has-text("Log in"), button:has-text("Sign in"))'); await page.click(':is(button:has-text("Log in"), button:has-text("Sign in"))');
``` ```
```java
// Clicks a <button> that has either a "Log in" or "Sign in" text.
page.click(":is(button:has-text(\"Log in\"), button:has-text(\"Sign in\"))");
```
```python async ```python async
# Clicks a <button> that has either a "Log in" or "Sign in" text. # Clicks a <button> that has either a "Log in" or "Sign in" text.
await page.click(':is(button:has-text("Log in"), button:has-text("Sign in"))') await page.click(':is(button:has-text("Log in"), button:has-text("Sign in"))')
@ -357,6 +433,10 @@ If you'd like to opt-out of this behavior, you can use `:light` CSS extension or
await page.click(':light(.article > .header)'); await page.click(':light(.article > .header)');
``` ```
```java
page.click(":light(.article > .header)");
```
```python async ```python async
await page.click(":light(.article > .header)") await page.click(":light(.article > .header)")
``` ```
@ -419,6 +499,14 @@ await page.fill('input:right-of(:text("Username"))', 'value');
await page.click('button:near(.promo-card)'); await page.click('button:near(.promo-card)');
``` ```
```java
// Fill an input to the right of "Username".
page.fill("input:right-of(:text(\"Username\"))", "value");
// Click a button near the promo card.
page.click("button:near(.promo-card)");
```
```python async ```python async
# Fill an input to the right of "Username". # Fill an input to the right of "Username".
await page.fill('input:right-of(:text("Username"))', 'value') await page.fill('input:right-of(:text("Username"))', 'value')
@ -465,6 +553,14 @@ await page.fill('id=username', 'value');
await page.click('data-test-id=submit'); await page.click('data-test-id=submit');
``` ```
```java
// Fill an input with the id "username"
page.fill("id=username", "value");
// Click an element with data-test-id "submit"
page.click("data-test-id=submit");
```
```python async ```python async
# Fill an input with the id "username" # Fill an input with the id "username"
await page.fill('id=username', 'value') await page.fill('id=username', 'value')
@ -503,6 +599,11 @@ In this case, `:nth-match(:text("Buy"), 3)` will select the third button from th
await page.click(':nth-match(:text("Buy"), 3)'); await page.click(':nth-match(:text("Buy"), 3)');
``` ```
```java
// Click the third "Buy" button
page.click(":nth-match(:text('Buy'), 3)");
```
```python async ```python async
# Click the third "Buy" button # Click the third "Buy" button
await page.click(":nth-match(:text('Buy'), 3)" await page.click(":nth-match(:text('Buy'), 3)"
@ -520,6 +621,11 @@ page.click(":nth-match(:text('Buy'), 3)"
await page.waitForSelector(':nth-match(:text("Buy"), 3)'); await page.waitForSelector(':nth-match(:text("Buy"), 3)');
``` ```
```java
// Wait until all three buttons are visible
page.waitForSelector(":nth-match(:text('Buy'), 3)");
```
```python async ```python async
# Wait until all three buttons are visible # Wait until all three buttons are visible
await page.wait_for_selector(":nth-match(:text('Buy'), 3)") await page.wait_for_selector(":nth-match(:text('Buy'), 3)")
@ -578,8 +684,8 @@ await page.click('text="Login"');
await page.click('"Login"'); // short-form await page.click('"Login"'); // short-form
// queries "Search GitHub" placeholder attribute // queries "Search GitHub" placeholder attribute
await page.fill('css=[placeholder="Search GitHub"]'); await page.fill('css=[placeholder="Search GitHub"]', 'query');
await page.fill('[placeholder="Search GitHub"]'); // short-form await page.fill('[placeholder="Search GitHub"]', 'query'); // short-form
// queries "Close" accessibility label // queries "Close" accessibility label
await page.click('css=[aria-label="Close"]'); await page.click('css=[aria-label="Close"]');
@ -589,14 +695,31 @@ await page.click('[aria-label="Close"]'); // short-form
await page.click('css=nav >> text=Login'); await page.click('css=nav >> text=Login');
``` ```
```java
// queries "Login" text selector
page.click("text=\"Login\"");
page.click("\"Login\""); // short-form
// queries "Search GitHub" placeholder attribute
page.fill("css=[placeholder='Search GitHub']", "query");
page.fill("[placeholder='Search GitHub']", "query"); // short-form
// queries "Close" accessibility label
page.click("css=[aria-label='Close']");
page.click("[aria-label='Close']"); // short-form
// combine role and text queries
page.click("css=nav >> text=Login");
```
```python async ```python async
# queries "Login" text selector # queries "Login" text selector
await page.click('text="Login"') await page.click('text="Login"')
await page.click('"Login"') # short-form await page.click('"Login"') # short-form
# queries "Search GitHub" placeholder attribute # queries "Search GitHub" placeholder attribute
await page.fill('css=[placeholder="Search GitHub"]') await page.fill('css=[placeholder="Search GitHub"]', 'query')
await page.fill('[placeholder="Search GitHub"]') # short-form await page.fill('[placeholder="Search GitHub"]', 'query') # short-form
# queries "Close" accessibility label # queries "Close" accessibility label
await page.click('css=[aria-label="Close"]') await page.click('css=[aria-label="Close"]')
@ -640,6 +763,15 @@ await page.click('[data-test-id=directions]'); // short-form
await page.click('data-test-id=directions'); await page.click('data-test-id=directions');
``` ```
```java
// queries data-test-id attribute with css
page.click("css=[data-test-id=directions]");
page.click("[data-test-id=directions]"); // short-form
// queries data-test-id with id
page.click("data-test-id=directions");
```
```python async ```python async
# queries data-test-id attribute with css # queries data-test-id attribute with css
await page.click('css=[data-test-id=directions]') await page.click('css=[data-test-id=directions]')
@ -669,6 +801,12 @@ await page.click('#tsf > div:nth-child(2) > div.A8SBwf > div.RNNXgb > div > div.
await page.click('//*[@id="tsf"]/div[2]/div[1]/div[1]/div/div[2]/input'); await page.click('//*[@id="tsf"]/div[2]/div[1]/div[1]/div/div[2]/input');
``` ```
```java
// avoid long css or xpath chains
page.click("#tsf > div:nth-child(2) > div.A8SBwf > div.RNNXgb > div > div.a4bIc > input");
page.click("//*[@id='tsf']/div[2]/div[1]/div[1]/div/div[2]/input");
```
```python async ```python async
# avoid long css or xpath chains # avoid long css or xpath chains
await page.click('#tsf > div:nth-child(2) > div.A8SBwf > div.RNNXgb > div > div.a4bIc > input') await page.click('#tsf > div:nth-child(2) > div.A8SBwf > div.RNNXgb > div > div.a4bIc > input')

View File

@ -33,6 +33,27 @@ await msg.args[0].jsonValue() // hello
await msg.args[1].jsonValue() // 42 await msg.args[1].jsonValue() // 42
``` ```
```java
// Listen for all System.out.printlns
page.onConsole(msg -> System.out.println(msg.text()));
// Listen for all console events and handle errors
page.onConsole(msg -> {
if ("error".equals(msg.type()))
System.out.println("Error text: " + msg.text());
});
// Get the next System.out.println
ConsoleMessage msg = page.waitForConsoleMessage(() -> {
// Issue console.log inside the page
page.evaluate("console.log('hello', 42, { foo: 'bar' });");
});
// Deconstruct console.log arguments
msg.args().get(0).jsonValue() // hello
msg.args().get(1).jsonValue() // 42
```
```python async ```python async
# Listen for all console logs # Listen for all console logs
page.on("console", msg => print(msg.text)) page.on("console", msg => print(msg.text))
@ -90,6 +111,16 @@ page.on('pageerror', exception => {
await page.goto('data:text/html,<script>throw new Error("Test")</script>'); await page.goto('data:text/html,<script>throw new Error("Test")</script>');
``` ```
```java
// Log all uncaught errors to the terminal
page.onPageError(exception -> {
System.out.println("Uncaught exception: " + exception);
});
// Navigate to a page with an exception.
page.navigate("data:text/html,<script>throw new Error('Test')</script>");
```
```python async ```python async
# Log all uncaught errors to the terminal # Log all uncaught errors to the terminal
page.on("pageerror", lambda exc: print(f"uncaught exception: {exc}")) page.on("pageerror", lambda exc: print(f"uncaught exception: {exc}"))
@ -122,6 +153,12 @@ page.on('requestfailed', request => {
}); });
``` ```
```java
page.onRequestFailed(request -> {
System.out.println(request.url() + " " + request.failure());
});
```
```python ```python
page.on("requestfailed", lambda request: print(request.url + " " + request.failure.error_text)) page.on("requestfailed", lambda request: print(request.url + " " + request.failure.error_text))
``` ```
@ -134,6 +171,12 @@ page.on('dialog', dialog => {
}); });
``` ```
```java
page.onDialog(dialog -> {
dialog.accept();
});
```
```python ```python
page.on("dialog", lambda dialog: dialog.accept()) page.on("dialog", lambda dialog: dialog.accept())
``` ```
@ -147,6 +190,12 @@ const [popup] = await Promise.all([
]); ]);
``` ```
```java
Page popup = page.waitForPopup(() -> {
page.click("#open");
});
```
```python async ```python async
async with page.expect_popup() as popup_info: async with page.expect_popup() as popup_info:
await page.click("#open") await page.click("#open")

View File

@ -19,15 +19,32 @@ const page = await browser.newPage({ recordVideo: { dir: 'videos/' } });
// Make sure to await close, so that videos are saved. // Make sure to await close, so that videos are saved.
await page.close(); await page.close();
// [Optional] Specify video size; defaults to viewport size // [Optional] Specify video size; defaults to viewport size scaled down to fit 800x800
const context = await browser.newContext({ const context = await browser.newContext({
recordVideo: { recordVideo: {
dir: 'videos/', dir: 'videos/',
size: { width: 800, height: 600 }, size: { width: 1024, height: 768 },
} }
}); });
``` ```
```java
// With browser.newContext()
context = browser.newContext(new Browser.NewContextOptions().withRecordVideoDir(Paths.get("videos/")));
// Make sure to close, so that videos are saved.
context.close();
// With browser.newPage()
Page page = browser.newPage(new Browser.NewPageOptions().withRecordVideoDir(Paths.get("videos/")));
// Make sure to close, so that videos are saved.
page.close();
// [Optional] Specify video size; defaults to viewport size scaled down to fit 800x800
BrowserContext context = browser.newContext(new Browser.NewContextOptions()
.withRecordVideoDir(Paths.get("videos/"))
.withRecordVideoSize(1024, 768));
```
```python async ```python async
# With browser.new_context() # With browser.new_context()
context = await browser.new_context(record_video_dir="videos/") context = await browser.new_context(record_video_dir="videos/")
@ -39,10 +56,10 @@ page = await browser.new_page(record_video_dir="videos/")
# Make sure to await close, so that videos are saved. # Make sure to await close, so that videos are saved.
await page.close() await page.close()
# [Optional] specify video size; defaults to viewport size # [Optional] specify video size; defaults to viewport size scaled down to fit 800x800
context = await browser.new_context( context = await browser.new_context(
record_video_dir="videos/", record_video_dir="videos/",
record_video_size={"width": 800, "height": 600} record_video_size={"width": 1024, "height": 768}
) )
``` ```
@ -57,10 +74,10 @@ page = browser.new_page(record_video_dir="videos/")
# Make sure to close, so that videos are saved. # Make sure to close, so that videos are saved.
page.close() page.close()
# [Optional] specify video size; defaults to viewport size # [Optional] specify video size; defaults to viewport size scaled down to fit 800x800
context = browser.new_context( context = browser.new_context(
record_video_dir="videos/", record_video_dir="videos/",
record_video_size={"width": 800, "height": 600} record_video_size={"width": 1024, "height": 768}
) )
``` ```

View File

@ -135,12 +135,12 @@ function multiplyComment(spec) {
return children; return children;
} }
for (const name of fs.readdirSync("docs/src/api")) { for (const name of fs.readdirSync("docs/src")) {
if (!name.endsWith(".md")) if (!name.endsWith(".md"))
continue; continue;
if (name.includes('android')) if (name.includes('android'))
continue; continue;
const inputFile = `docs/src/api/${name}`; const inputFile = `docs/src/${name}`;
const fileline = fs.readFileSync(inputFile).toString(); const fileline = fs.readFileSync(inputFile).toString();
const nodes = md.parse(fileline); const nodes = md.parse(fileline);