diff --git a/docs/src/assertions.md b/docs/src/assertions.md
index b41806b350..5d04de2492 100644
--- a/docs/src/assertions.md
+++ b/docs/src/assertions.md
@@ -8,7 +8,6 @@ text content of an element. These APIs can be used in your test assertions.
-
## Text content
```js
@@ -16,6 +15,11 @@ const content = await page.textContent('nav:first-child');
expect(content).toBe('home');
```
+```java
+String content = page.textContent("nav:first-child");
+assertEquals("home", content);
+```
+
```python async
content = await page.text_content("nav:first-child")
assert content == "home"
@@ -37,6 +41,11 @@ const text = await page.innerText('.selected');
expect(text).toBe('value');
```
+```java
+String text = page.innerText(".selected");
+assertEquals("value", text);
+```
+
```python async
text = await page.inner_text(".selected")
assert text == "value"
@@ -58,6 +67,11 @@ const alt = await page.getAttribute('input', 'alt');
expect(alt).toBe('Text');
```
+```java
+String alt = page.getAttribute("input", "alt");
+assertEquals("Text", alt);
+```
+
```python async
checked = await page.get_attribute("input", "alt")
assert alt == "Text"
@@ -75,6 +89,11 @@ const checked = await page.isChecked('input');
expect(checked).toBeTruthy();
```
+```java
+boolean checked = page.isChecked("input");
+assertTrue(checked);
+```
+
```python async
checked = await page.is_checked("input")
assert checked
@@ -96,6 +115,11 @@ const content = await page.$eval('nav:first-child', e => e.textContent);
expect(content).toBe('home');
```
+```java
+Object content = page.evalOnSelector("nav:first-child", "e => e.textContent");
+assertEquals("home", content);
+```
+
```python async
content = await page.eval_on_selector("nav:first-child", "e => e.textContent")
assert content == "home"
@@ -117,6 +141,11 @@ const html = await page.innerHTML('div.result');
expect(html).toBe('
Result
');
```
+```java
+String html = page.innerHTML("div.result");
+assertEquals("Result
", html);
+```
+
```python async
html = await page.inner_html("div.result")
assert html == "Result
"
@@ -138,6 +167,11 @@ const visible = await page.isVisible('input');
expect(visible).toBeTruthy();
```
+```java
+boolean visible = page.isVisible("input");
+assertTrue(visible);
+```
+
```python async
visible = await page.is_visible("input")
assert visible
@@ -156,7 +190,12 @@ assert visible
```js
const enabled = await page.isEnabled('input');
-expect(visible).toBeTruthy();
+expect(enabled).toBeTruthy();
+```
+
+```java
+boolean enabled = page.isEnabled("input");
+assertTrue(enabled);
```
```python async
@@ -198,6 +237,25 @@ const length = await page.$$eval('li.selected', (items) => items.length);
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
# Assert local storage value
user_id = page.evaluate("() => window.localStorage.getItem('user_id')")
@@ -245,4 +303,4 @@ assert length == 3
- [`method: Frame.evalOnSelectorAll`]
- [`method: ElementHandle.evalOnSelector`]
- [`method: ElementHandle.evalOnSelectorAll`]
-- [EvaluationArgument]
+- [EvaluationArgument]
\ No newline at end of file
diff --git a/docs/src/auth.md b/docs/src/auth.md
index 95b689ecef..cb1156440a 100644
--- a/docs/src/auth.md
+++ b/docs/src/auth.md
@@ -36,6 +36,17 @@ await page.click('text=Submit');
// 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
page = await context.new_page()
await page.goto('https://github.com/login')
@@ -88,6 +99,16 @@ const storageState = JSON.parse(process.env.STORAGE);
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
import json
import os
@@ -150,6 +171,23 @@ await context.addInitScript(storage => {
}, 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
import os
# Get session storage and store as env variable
@@ -199,8 +237,6 @@ manual intervention. Persistent authentication can be used to partially automate
MFA scenarios.
### 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
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
```
+```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
import asyncio
from playwright.async_api import async_playwright
@@ -246,4 +298,4 @@ with sync_playwright() as p:
### API reference
- [BrowserContext]
-- [`method: BrowserType.launchPersistentContext`]
+- [`method: BrowserType.launchPersistentContext`]
\ No newline at end of file
diff --git a/docs/src/ci.md b/docs/src/ci.md
index 34cbd738c0..65076bdcd2 100644
--- a/docs/src/ci.md
+++ b/docs/src/ci.md
@@ -83,6 +83,11 @@ Suggested configuration
});
```
+ ```java
+ Browser browser = playwright.chromium().launch(new BrowserType.LaunchOptions()
+ .withArgs(Arrays.asList("--disable-dev-shm-usage")));
+ ```
+
```python async
browser = await playwright.chromium.launch(
args=['--disable-dev-shm-usage']
@@ -233,6 +238,19 @@ const { chromium } = require('playwright');
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
browser = await playwright.chromium.launch(chromiumSandbox=False)
```
@@ -319,6 +337,20 @@ const { chromium } = require('playwright');
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
import asyncio
from playwright.async_api import async_playwright
diff --git a/docs/src/cli.md b/docs/src/cli.md
index 2da5c5f529..9b8fce65d8 100644
--- a/docs/src/cli.md
+++ b/docs/src/cli.md
@@ -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
import asyncio
from playwright.async_api import async_playwright
diff --git a/docs/src/core-concepts.md b/docs/src/core-concepts.md
index cd0eaff7ca..a30fddd35b 100644
--- a/docs/src/core-concepts.md
+++ b/docs/src/core-concepts.md
@@ -29,6 +29,20 @@ const browser = await chromium.launch({ headless: false });
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
import asyncio
from playwright.async_api import async_playwright
@@ -69,6 +83,11 @@ const browser = await chromium.launch();
const context = await browser.newContext();
```
+```java
+Browser browser = chromium.launch();
+BrowserContext context = browser.newContext();
+```
+
```python async
browser = await playwright.chromium.launch()
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
import asyncio
from playwright.async_api import async_playwright
@@ -161,6 +203,24 @@ console.log(page.url());
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
page = await context.new_page()
@@ -219,6 +279,21 @@ const frame = await frameElementHandle.contentFrame();
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
# Get frame using the frame's name attribute
frame = page.frame('frame-login')
@@ -274,6 +349,11 @@ Some examples below:
await page.click('data-test-id=foo');
```
+```java
+// Using data-test-id= selector engine
+page.click("data-test-id=foo");
+```
+
```python async
# Using data-test-id= selector engine
await page.click('data-test-id=foo')
@@ -290,6 +370,12 @@ await page.click('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
# CSS and XPath selector engines are automatically detected
await page.click('div')
@@ -307,6 +393,11 @@ page.click('//html/body/div')
await page.click('text=Hello w');
```
+```java
+// Find node by text substring
+page.click("text=Hello w");
+```
+
```python async
# Find node by text substring
await page.click('text=Hello w')
@@ -323,6 +414,12 @@ await page.click('css=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
# Explicit CSS and XPath notation
await page.click('css=div')
@@ -340,6 +437,11 @@ page.click('xpath=//html/body/div')
await page.click('css:light=div');
```
+```java
+// Only search light DOM, outside WebComponent shadow DOM:
+page.click("css:light=div");
+```
+
```python async
# Only search light DOM, outside WebComponent shadow DOM:
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');
```
+```java
+// Click an element with text "Sign Up" inside of a #free-month-promo.
+page.click("#free-month-promo >> text=Sign Up");
+```
+
```python async
# Click an element with text 'Sign Up' inside of a #free-month-promo.
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);
```
+```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
# 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')
@@ -401,6 +513,11 @@ and [actionable](./actionability.md). For example, click will:
await page.fill('#search', 'query');
```
+```java
+// Playwright waits for #search element to be in the DOM
+page.fill("#search", "query");
+```
+
```python async
# Playwright waits for #search element to be in the DOM
await page.fill('#search', 'query')
@@ -417,6 +534,12 @@ page.fill('#search', 'query')
await page.click('#search');
```
+```java
+// Playwright waits for element to stop animating
+// and accept clicks.
+page.click("#search");
+```
+
```python async
# Playwright waits for element to stop animating
# and accept clicks.
@@ -438,6 +561,14 @@ await page.waitForSelector('#search', { state: 'attached' });
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
# Wait for #search to appear in the DOM.
await page.wait_for_selector('#search', state='attached')
@@ -461,6 +592,15 @@ await page.waitForSelector('#details', { state: 'hidden' });
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
# Wait for #details to become hidden, for example with `display:none`.
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);
```
+```java
+String href = (String) page.evaluate("document.location.href");
+```
+
```python async
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
status = await page.evaluate("""async () => {
response = await fetch(location.href)
@@ -573,6 +724,57 @@ await page.evaluate(
{ 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 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 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 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 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
# A primitive value.
await page.evaluate('num => num', 42)
@@ -668,6 +870,16 @@ const result = await page.evaluate(data => {
}, data);
```
+```java
+Map 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
data = { 'text': 'some data', 'value': 1 }
# Pass |data| as a parameter.
@@ -694,6 +906,16 @@ const result = await page.evaluate(() => {
});
```
+```java
+Map 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
data = { 'text': 'some data', 'value': 1 }
result = await page.evaluate("""() => {
diff --git a/docs/src/debug.md b/docs/src/debug.md
index 4623cfcf3f..aa15a2d1d6 100644
--- a/docs/src/debug.md
+++ b/docs/src/debug.md
@@ -26,6 +26,12 @@ to slow down execution and follow along while debugging.
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
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 });
```
+```java
+chromium.launch(new BrowserType.LaunchOptions().withDevtools(true));
+```
+
```python async
await chromium.launch(devtools=True)
@@ -98,6 +108,15 @@ $ set PWDEBUG=1
$ npm run test
```
+```sh java
+# Linux/macOS
+$ PWDEBUG=1 mvn test
+
+# Windows
+$ set PWDEBUG=1
+$ mvn test
+```
+
```sh python
# Linux/macOS
$ PWDEBUG=1 pytest -s
@@ -152,6 +171,15 @@ $ set DEBUG=pw:api
$ npm run test
```
+```sh java
+# Linux/macOS
+$ DEBUG=pw:api mvn test
+
+# Windows
+$ set DEBUG=pw:api
+$ mvn test
+```
+
```sh python
# Linux/macOS
$ DEBUG=pw:api pytest -s
diff --git a/docs/src/dialogs.md b/docs/src/dialogs.md
index f85924aecd..624edf0f56 100644
--- a/docs/src/dialogs.md
+++ b/docs/src/dialogs.md
@@ -16,6 +16,11 @@ page.on('dialog', dialog => dialog.accept());
await page.click('button');
```
+```java
+page.onDialog(dialog -> dialog.accept());
+page.click("button");
+```
+
```python async
page.on("dialog", lambda dialog: dialog.accept())
await page.click("button")
@@ -41,6 +46,11 @@ page.on('dialog', dialog => console.log(dialog.message()));
await page.click('button'); // Will hang here
```
+```java
+page.onDialog(dialog -> System.out.println(dialog.message()));
+page.click("button"); // Will hang here
+```
+
```python async
page.on("dialog", lambda dialog: print(dialog.message))
await page.click("button") # Will hang here
@@ -75,6 +85,14 @@ page.on('dialog', async dialog => {
await page.close({runBeforeUnload: true});
```
+```java
+page.onDialog(dialog -> {
+ assertEquals("beforeunload", dialog.type());
+ dialog.dismiss();
+});
+page.close(new Page.CloseOptions().withRunBeforeUnload(true));
+```
+
```python async
async def handle_dialog(dialog):
assert dialog.type == 'beforeunload'
diff --git a/docs/src/downloads.md b/docs/src/downloads.md
index d187b9ef63..c1eaa68a6b 100644
--- a/docs/src/downloads.md
+++ b/docs/src/downloads.md
@@ -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));
```
+```java
+page.onDownload(download -> System.out.println(download.path()));
+```
+
```python async
async def handle_download(download):
print(await download.path())
diff --git a/docs/src/emulation.md b/docs/src/emulation.md
index b51143c8c3..6ef3a6b76f 100644
--- a/docs/src/emulation.md
+++ b/docs/src/emulation.md
@@ -81,6 +81,11 @@ const context = await browser.newContext({
});
```
+```java
+BrowserContext context = browser.newContext(new Browser.NewContextOptions()
+ .withUserAgent("My user agent"));
+```
+
```python async
context = await browser.new_context(
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
# Create context with given viewport
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
# Emulate locale and time
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
context = await browser.new_context(
permissions=['notifications'],
@@ -214,6 +245,10 @@ Grant all pages in the existing context access to current location:
await context.grantPermissions(['geolocation']);
```
+```java
+context.grantPermissions(Arrays.asList("geolocation"));
+```
+
```python async
await context.grant_permissions(['geolocation'])
```
@@ -228,6 +263,11 @@ Grant notifications access from a specific domain:
await context.grantPermissions(['notifications'], {origin: 'https://skype.com'} );
```
+```java
+context.grantPermissions(Arrays.asList("notifications"),
+ new BrowserContext.GrantPermissionsOptions().withOrigin("https://skype.com"));
+```
+
```python async
await context.grant_permissions(['notifications'], origin='https://skype.com')
```
@@ -242,6 +282,10 @@ Revoke all permissions:
await context.clearPermissions();
```
+```java
+context.clearPermissions();
+```
+
```python async
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
context = await browser.new_context(
geolocation={"longitude": 48.858455, "latitude": 2.294474},
@@ -288,6 +338,10 @@ Change the location later:
await context.setGeolocation({ longitude: 29.979097, latitude: 31.134256 });
```
+```java
+context.setGeolocation(new Geolocation(29.979097, 31.134256));
+```
+
```python async
await context.set_geolocation({"longitude": 29.979097, "latitude": 31.134256})
```
@@ -326,6 +380,22 @@ await page.emulateMedia({ colorScheme: 'dark' });
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
# Create context with dark mode
context = await browser.new_context(
diff --git a/docs/src/extensibility.md b/docs/src/extensibility.md
index 1963d17ed6..21510b50d3 100644
--- a/docs/src/extensibility.md
+++ b/docs/src/extensibility.md
@@ -51,6 +51,33 @@ await page.click('tag=div >> span >> "Click me"');
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
tag_selector = """
// Must evaluate to a selector engine instance.
diff --git a/docs/src/handles.md b/docs/src/handles.md
index 20532f2b2f..c937e4ad86 100644
--- a/docs/src/handles.md
+++ b/docs/src/handles.md
@@ -28,6 +28,11 @@ const jsHandle = await page.evaluateHandle('window');
// Use jsHandle for evaluations.
```
+```java
+JSHandle jsHandle = page.evaluateHandle("window");
+// Use jsHandle for evaluations.
+```
+
```python async
js_handle = await page.evaluate_handle('window')
# Use jsHandle for evaluations.
@@ -43,6 +48,11 @@ const ulElementHandle = await page.waitForSelector('ul');
// Use ulElementHandle for actions and evaluation.
```
+```java
+ElementHandle ulElementHandle = page.waitForSelector("ul");
+// Use ulElementHandle for actions and evaluation.
+```
+
```python async
ul_element_handle = await page.wait_for_selector('ul')
# Use ul_element_handle for actions and evaluation.
@@ -76,6 +86,20 @@ const classNames = await elementHandle.getAttribute('class');
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
# Get the element handle
element_handle = page.wait_for_selector('#box')
@@ -129,6 +153,26 @@ await page.evaluate(arg => arg.myArray.push(arg.newElement), {
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 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
# Create new array in page.
my_array_handle = await page.evaluate_handle("""() => {
diff --git a/docs/src/input.md b/docs/src/input.md
index 3780df181c..a6a5c73e86 100644
--- a/docs/src/input.md
+++ b/docs/src/input.md
@@ -26,6 +26,23 @@ await page.fill('#local', '2020-03-02T05:15');
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
# Text input
await page.fill('#name', 'Peter')
@@ -86,6 +103,20 @@ await page.uncheck('#subscribe-label');
await page.check('text=XL');
```
+```java
+// Check the checkbox
+page.check("#agree");
+
+// Assert the checked state
+assertTrue(page.isChecked("#agree"));
+
+// Uncheck by input