");
+ElementHandle div = page.querySelector("div");
+// Waiting for the "span" selector relative to the div.
+ElementHandle span = div.waitForSelector("span", new ElementHandle.WaitForSelectorOptions()
+ .withState(WaitForSelectorState.ATTACHED));
+```
+
```python async
await page.set_content("
")
div = await page.query_selector("div")
diff --git a/docs/src/api/class-filechooser.md b/docs/src/api/class-filechooser.md
index e560a1a87a..2389db652f 100644
--- a/docs/src/api/class-filechooser.md
+++ b/docs/src/api/class-filechooser.md
@@ -10,6 +10,11 @@ const [fileChooser] = await Promise.all([
await fileChooser.setFiles('myfile.pdf');
```
+```java
+FileChooser fileChooser = page.waitForFileChooser(() -> page.click("upload"));
+fileChooser.setFiles(Paths.get("myfile.pdf"));
+```
+
```python async
async with page.expect_file_chooser() as fc_info:
await page.click("upload")
diff --git a/docs/src/api/class-frame.md b/docs/src/api/class-frame.md
index 8a0174cdea..2ff682af1e 100644
--- a/docs/src/api/class-frame.md
+++ b/docs/src/api/class-frame.md
@@ -31,6 +31,29 @@ const { firefox } = require('playwright'); // Or 'chromium' or 'webkit'.
})();
```
+```java
+import com.microsoft.playwright.*;
+
+public class Example {
+ public static void main(String[] args) {
+ try (Playwright playwright = Playwright.create()) {
+ BrowserType firefox = playwright.firefox();
+ Browser browser = firefox.launch();
+ Page page = browser.newPage();
+ page.navigate("https://www.google.com/chrome/browser/canary.html");
+ dumpFrameTree(page.mainFrame(), "");
+ browser.close();
+ }
+ }
+ static void dumpFrameTree(Frame frame, String indent) {
+ System.out.println(indent + frame.url());
+ for (Frame child : frame.childFrames()) {
+ dumpFrameTree(child, indent + " ");
+ }
+ }
+}
+```
+
```python async
import asyncio
from playwright.async_api import async_playwright
@@ -237,6 +260,10 @@ is dispatched. This is equivalend to calling
await frame.dispatchEvent('button#submit', 'click');
```
+```java
+frame.dispatchEvent("button#submit", "click");
+```
+
```python async
await frame.dispatch_event("button#submit", "click")
```
@@ -267,6 +294,14 @@ const dataTransfer = await frame.evaluateHandle(() => new DataTransfer());
await frame.dispatchEvent('#source', 'dragstart', { dataTransfer });
```
+```java
+// Note you can only create DataTransfer in Chromium and Firefox
+JSHandle dataTransfer = frame.evaluateHandle("() => new DataTransfer()");
+Map arg = new HashMap<>();
+arg.put("dataTransfer", dataTransfer);
+frame.dispatchEvent("#source", "dragstart", arg);
+```
+
```python async
# note you can only create data_transfer in chromium and firefox
data_transfer = await frame.evaluate_handle("new DataTransfer()")
@@ -279,7 +314,6 @@ data_transfer = frame.evaluate_handle("new DataTransfer()")
frame.dispatch_event("#source", "dragstart", { "dataTransfer": data_transfer })
```
-
### param: Frame.dispatchEvent.selector = %%-input-selector-%%
### param: Frame.dispatchEvent.type
@@ -317,6 +351,12 @@ const preloadHref = await frame.$eval('link[rel=preload]', el => el.href);
const html = await frame.$eval('.main-container', (e, suffix) => e.outerHTML + suffix, 'hello');
```
+```java
+String searchValue = (String) frame.evalOnSelector("#search", "el => el.value");
+String preloadHref = (String) frame.evalOnSelector("link[rel=preload]", "el => el.href");
+String html = (String) frame.evalOnSelector(".main-container", "(e, suffix) => e.outerHTML + suffix", "hello");
+```
+
```python async
search_value = await frame.eval_on_selector("#search", "el => el.value")
preload_href = await frame.eval_on_selector("link[rel=preload]", "el => el.href")
@@ -359,6 +399,10 @@ Examples:
const divsCounts = await frame.$$eval('div', (divs, min) => divs.length >= min, 10);
```
+```java
+boolean divsCounts = (boolean) page.evalOnSelectorAll("div", "(divs, min) => divs.length >= min", 10);
+```
+
```python async
divs_counts = await frame.eval_on_selector_all("div", "(divs, min) => divs.length >= min", 10)
```
@@ -395,6 +439,13 @@ const result = await frame.evaluate(([x, y]) => {
console.log(result); // prints "56"
```
+```java
+Object result = frame.evaluate("([x, y]) => {\n" +
+ " return Promise.resolve(x * y);\n" +
+ "}", Arrays.asList(7, 8));
+System.out.println(result); // prints "56"
+```
+
```python async
result = await frame.evaluate("([x, y]) => Promise.resolve(x * y)", [7, 8])
print(result) # prints "56"
@@ -405,13 +456,16 @@ result = frame.evaluate("([x, y]) => Promise.resolve(x * y)", [7, 8])
print(result) # prints "56"
```
-
A string can also be passed in instead of a function.
```js
console.log(await frame.evaluate('1 + 2')); // prints "3"
```
+```java
+System.out.println(frame.evaluate("1 + 2")); // prints "3"
+```
+
```python async
print(await frame.evaluate("1 + 2")) # prints "3"
x = 10
@@ -424,7 +478,6 @@ x = 10
print(frame.evaluate(f"1 + {x}")) # prints "11"
```
-
[ElementHandle] instances can be passed as an argument to the [`method: Frame.evaluate`]:
```js
@@ -433,6 +486,12 @@ const html = await frame.evaluate(([body, suffix]) => body.innerHTML + suffix, [
await bodyHandle.dispose();
```
+```java
+ElementHandle bodyHandle = frame.querySelector("body");
+String html = (String) frame.evaluate("([body, suffix]) => body.innerHTML + suffix", Arrays.asList(bodyHandle, "hello"));
+bodyHandle.dispose();
+```
+
```python async
body_handle = await frame.query_selector("body")
html = await frame.evaluate("([body, suffix]) => body.innerHTML + suffix", [body_handle, "hello"])
@@ -468,6 +527,11 @@ const aWindowHandle = await frame.evaluateHandle(() => Promise.resolve(window));
aWindowHandle; // Handle for the window object.
```
+```java
+// Handle for the window object.
+JSHandle aWindowHandle = frame.evaluateHandle("() => Promise.resolve(window)");
+```
+
```python async
a_window_handle = await frame.evaluate_handle("Promise.resolve(window)")
a_window_handle # handle for the window object.
@@ -484,6 +548,10 @@ A string can also be passed in instead of a function.
const aHandle = await frame.evaluateHandle('document'); // Handle for the 'document'.
```
+```java
+JSHandle aHandle = frame.evaluateHandle("document"); // Handle for the "document".
+```
+
```python async
a_handle = await page.evaluate_handle("document") # handle for the "document"
```
@@ -501,6 +569,13 @@ console.log(await resultHandle.jsonValue());
await resultHandle.dispose();
```
+```java
+JSHandle aHandle = frame.evaluateHandle("() => document.body");
+JSHandle resultHandle = frame.evaluateHandle("([body, suffix]) => body.innerHTML + suffix", Arrays.asList(aHandle, "hello"));
+System.out.println(resultHandle.jsonValue());
+resultHandle.dispose();
+```
+
```python async
a_handle = await page.evaluate_handle("document.body")
result_handle = await page.evaluate_handle("body => body.innerHTML", a_handle)
@@ -567,6 +642,12 @@ const contentFrame = await frameElement.contentFrame();
console.log(frame === contentFrame); // -> true
```
+```java
+ElementHandle frameElement = frame.frameElement();
+Frame contentFrame = frameElement.contentFrame();
+System.out.println(frame == contentFrame); // -> true
+```
+
```python async
frame_element = await frame.frame_element()
content_frame = await frame_element.content_frame()
@@ -844,6 +925,15 @@ frame.selectOption('select#colors', { label: 'Blue' });
frame.selectOption('select#colors', 'red', 'green', 'blue');
```
+```java
+// single selection matching the value
+frame.selectOption("select#colors", "blue");
+// single selection matching both the value and the label
+frame.selectOption("select#colors", new SelectOption().withLabel("Blue"));
+// multiple selection
+frame.selectOption("select#colors", new String[] {"red", "green", "blue"});
+```
+
```python async
# single selection matching the value
await frame.select_option("select#colors", "blue")
@@ -953,6 +1043,13 @@ await frame.type('#mytextarea', 'Hello'); // Types instantly
await frame.type('#mytextarea', 'World', {delay: 100}); // Types slower, like a user
```
+```java
+// Types instantly
+frame.type("#mytextarea", "Hello");
+// Types slower, like a user
+frame.type("#mytextarea", "World", new Frame.TypeOptions().withDelay(100));
+```
+
```python async
await frame.type("#mytextarea", "hello") # types instantly
await frame.type("#mytextarea", "world", delay=100) # types slower, like a user
@@ -1029,6 +1126,23 @@ const { firefox } = require('playwright'); // Or 'chromium' or 'webkit'.
})();
```
+```java
+import com.microsoft.playwright.*;
+
+public class Example {
+ public static void main(String[] args) {
+ try (Playwright playwright = Playwright.create()) {
+ BrowserType firefox = playwright.firefox();
+ Browser browser = firefox.launch();
+ Page page = browser.newPage();
+ page.setViewportSize(50, 50);
+ page.mainFrame().waitForFunction("window.innerWidth < 100");
+ browser.close();
+ }
+ }
+}
+```
+
```python async
import asyncio
from playwright.async_api import async_playwright
@@ -1069,6 +1183,11 @@ const selector = '.foo';
await frame.waitForFunction(selector => !!document.querySelector(selector), selector);
```
+```java
+String selector = ".foo";
+frame.waitForFunction("selector => !!document.querySelector(selector)", selector);
+```
+
```python async
selector = ".foo"
await frame.wait_for_function("selector => !!document.querySelector(selector)", selector)
@@ -1104,6 +1223,11 @@ await frame.click('button'); // Click triggers navigation.
await frame.waitForLoadState(); // Waits for 'load' state by default.
```
+```java
+frame.click("button"); // Click triggers navigation.
+frame.waitForLoadState(); // Waits for "load" state by default.
+```
+
```python async
await frame.click("button") # click triggers navigation.
await frame.wait_for_load_state() # the promise resolves after "load" event.
@@ -1137,6 +1261,14 @@ const [response] = await Promise.all([
]);
```
+```java
+// The method returns after navigation has finished
+Response response = frame.waitForNavigation(() -> {
+ // Clicking the link will indirectly cause a navigation
+ frame.click("a.delayed-navigation");
+});
+```
+
```python async
async with frame.expect_navigation():
await frame.click("a.delayed-navigation") # clicking the link will indirectly cause a navigation
@@ -1188,6 +1320,26 @@ const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'.
})();
```
+```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();
+ for (String currentURL : Arrays.asList("https://google.com", "https://bbc.com")) {
+ page.navigate(currentURL);
+ ElementHandle element = page.mainFrame().waitForSelector("img");
+ System.out.println("Loaded image: " + element.getAttribute("src"));
+ }
+ browser.close();
+ }
+ }
+}
+```
+
```python async
import asyncio
from playwright.async_api import async_playwright
diff --git a/docs/src/api/class-jshandle.md b/docs/src/api/class-jshandle.md
index 62fb54224f..e9d078770e 100644
--- a/docs/src/api/class-jshandle.md
+++ b/docs/src/api/class-jshandle.md
@@ -8,6 +8,11 @@ const windowHandle = await page.evaluateHandle(() => window);
// ...
```
+```java
+JSHandle windowHandle = page.evaluateHandle("() => window");
+// ...
+```
+
```python async
window_handle = await page.evaluate_handle("window")
# ...
@@ -51,6 +56,11 @@ const tweetHandle = await page.$('.tweet .retweets');
expect(await tweetHandle.evaluate(node => node.innerText)).toBe('10 retweets');
```
+```java
+ElementHandle tweetHandle = page.querySelector(".tweet .retweets");
+assertEquals("10 retweets", tweetHandle.evaluate("node => node.innerText"));
+```
+
```python async
tweet_handle = await page.query_selector(".tweet .retweets")
assert await tweet_handle.evaluate("node => node.innerText") == "10 retweets"
@@ -102,6 +112,14 @@ const documentHandle = properties.get('document');
await handle.dispose();
```
+```java
+JSHandle handle = page.evaluateHandle("() => ({window, document}"););
+Map properties = handle.getProperties();
+JSHandle windowHandle = properties.get("window");
+JSHandle documentHandle = properties.get("document");
+handle.dispose();
+```
+
```python async
handle = await page.evaluate_handle("{window, document}")
properties = await handle.get_properties()
diff --git a/docs/src/api/class-keyboard.md b/docs/src/api/class-keyboard.md
index 4431c1e14b..889eab1732 100644
--- a/docs/src/api/class-keyboard.md
+++ b/docs/src/api/class-keyboard.md
@@ -21,6 +21,17 @@ await page.keyboard.press('Backspace');
// Result text will end up saying 'Hello!'
```
+```java
+page.keyboard().type("Hello World!");
+page.keyboard().press("ArrowLeft");
+page.keyboard().down("Shift");
+for (int i = 0; i < " World".length(); i++)
+ page.keyboard().press("ArrowLeft");
+page.keyboard().up("Shift");
+page.keyboard().press("Backspace");
+// Result text will end up saying "Hello!"
+```
+
```python async
await page.keyboard.type("Hello World!")
await page.keyboard.press("ArrowLeft")
@@ -51,6 +62,12 @@ await page.keyboard.press('Shift+KeyA');
await page.keyboard.press('Shift+A');
```
+```java
+page.keyboard().press("Shift+KeyA");
+// or
+page.keyboard().press("Shift+A");
+```
+
```python async
await page.keyboard.press("Shift+KeyA")
# or
@@ -72,6 +89,13 @@ await page.keyboard.press('Control+A');
await page.keyboard.press('Meta+A');
```
+```java
+// on Windows and Linux
+page.keyboard().press("Control+A");
+// on macOS
+page.keyboard().press("Meta+A");
+```
+
```python async
# on windows and linux
await page.keyboard.press("Control+A")
@@ -129,6 +153,10 @@ Dispatches only `input` event, does not emit the `keydown`, `keyup` or `keypress
page.keyboard.insertText('嗨');
```
+```java
+page.keyboard().insertText("嗨");
+```
+
```python async
await page.keyboard.insert_text("嗨")
```
@@ -178,6 +206,18 @@ await page.screenshot({ path: 'O.png' });
await browser.close();
```
+```java
+Page page = browser.newPage();
+page.navigate("https://keycode.info");
+page.keyboard().press("A");
+page.screenshot(new Page.ScreenshotOptions().withPath(Paths.get("A.png"));
+page.keyboard().press("ArrowLeft");
+page.screenshot(new Page.ScreenshotOptions().withPath(Paths.get("ArrowLeft.png")));
+page.keyboard().press("Shift+O");
+page.screenshot(new Page.ScreenshotOptions().withPath(Paths.get("O.png")));
+browser.close();
+```
+
```python async
page = await browser.new_page()
await page.goto("https://keycode.info")
@@ -225,6 +265,13 @@ await page.keyboard.type('Hello'); // Types instantly
await page.keyboard.type('World', {delay: 100}); // Types slower, like a user
```
+```java
+// Types instantly
+page.keyboard().type("Hello");
+// Types slower, like a user
+page.keyboard().type("World", new Keyboard.TypeOptions().withDelay(100));
+```
+
```python async
await page.keyboard.type("Hello") # types instantly
await page.keyboard.type("World", delay=100) # types slower, like a user
diff --git a/docs/src/api/class-mouse.md b/docs/src/api/class-mouse.md
index d58ce793e3..a6f01ea53b 100644
--- a/docs/src/api/class-mouse.md
+++ b/docs/src/api/class-mouse.md
@@ -15,6 +15,17 @@ await page.mouse.move(0, 0);
await page.mouse.up();
```
+```java
+// Using ‘page.mouse’ to trace a 100x100 square.
+page.mouse().move(0, 0);
+page.mouse().down();
+page.mouse().move(0, 100);
+page.mouse().move(100, 100);
+page.mouse().move(100, 0);
+page.mouse().move(0, 0);
+page.mouse().up();
+```
+
```python async
# using ‘page.mouse’ to trace a 100x100 square.
await page.mouse.move(0, 0)
diff --git a/docs/src/api/class-page.md b/docs/src/api/class-page.md
index 284e438347..e553fc94dc 100644
--- a/docs/src/api/class-page.md
+++ b/docs/src/api/class-page.md
@@ -20,6 +20,24 @@ const { webkit } = require('playwright'); // Or 'chromium' or 'firefox'.
})();
```
+```java
+import com.microsoft.playwright.*;
+
+public class Example {
+ public static void main(String[] args) {
+ try (Playwright playwright = Playwright.create()) {
+ BrowserType webkit = playwright.webkit();
+ Browser browser = webkit.launch();
+ BrowserContext context = browser.newContext();
+ Page page = context.newPage();
+ page.navigate("https://example.com");
+ page.screenshot(new Page.ScreenshotOptions().withPath(Paths.get("screenshot.png")));
+ browser.close();
+ }
+ }
+}
+```
+
```python async
import asyncio
from playwright.async_api import async_playwright
@@ -65,6 +83,10 @@ This example logs a message for a single page `load` event:
page.once('load', () => console.log('Page loaded!'));
```
+```java
+page.onLoad(p -> System.out.println("Page loaded!"));
+```
+
```py
page.once("load", lambda: print("page loaded!"))
```
@@ -80,6 +102,15 @@ page.on('request', logRequest);
page.removeListener('request', logRequest);
```
+```java
+Consumer logRequest = interceptedRequest -> {
+ System.out.println("A request was made: " + interceptedRequest.url());
+};
+page.onRequest(logRequest);
+// Sometime later...
+page.offRequest(logRequest);
+```
+
```py
def log_request(intercepted_request):
print("a request was made:", intercepted_request.url)
@@ -111,6 +142,14 @@ page.on('console', msg => {
page.evaluate(() => console.log('hello', 5, {foo: 'bar'}));
```
+```java
+page.onConsole(msg -> {
+ for (int i = 0; i < msg.args().size(); ++i)
+ System.out.println(i + ": " + msg.args().get(i).jsonValue());
+});
+page.evaluate("() => console.log('hello', 5, {foo: 'bar'})");
+```
+
```python async
async def print_args(msg):
for arg in msg.args:
@@ -148,6 +187,17 @@ try {
}
```
+```java
+try {
+ // Crash might happen during a click.
+ page.click("button");
+ // Or while waiting for an event.
+ page.waitForPopup(() -> {});
+} catch (PlaywrightException e) {
+ // When the page crashes, exception message contains "crash".
+}
+```
+
```python async
try:
# crash might happen during a click.
@@ -207,6 +257,12 @@ page.on('filechooser', async (fileChooser) => {
});
```
+```java
+page.onFileChooser(fileChooser -> {
+ fileChooser.setFiles(Paths.get("/tmp/myfile.pdf"));
+});
+```
+
```py
page.on("filechooser", lambda file_chooser: file_chooser.set_files("/tmp/myfile.pdf"))
```
@@ -258,6 +314,13 @@ const [popup] = await Promise.all([
console.log(await popup.evaluate('location.href'));
```
+```java
+Page popup = page.waitForPopup(() -> {
+ page.evaluate("() => window.open('https://example.com')");
+});
+System.out.println(popup.evaluate("location.href"));
+```
+
```python async
async with page.expect_event("popup") as page_info:
page.evaluate("window.open('https://example.com')")
@@ -341,6 +404,11 @@ Math.random = () => 42;
await page.addInitScript({ path: './preload.js' });
```
+```java
+// In your playwright script, assuming the preload.js file is in same directory
+page.addInitScript(Paths.get("./preload.js"));
+```
+
```python async
# in your playwright script, assuming the preload.js file is in same directory
await page.add_init_script(path="./preload.js")
@@ -578,6 +646,10 @@ is dispatched. This is equivalend to calling
await page.dispatchEvent('button#submit', 'click');
```
+```java
+page.dispatchEvent("button#submit", "click");
+```
+
```python async
await page.dispatch_event("button#submit", "click")
```
@@ -608,6 +680,14 @@ const dataTransfer = await page.evaluateHandle(() => new DataTransfer());
await page.dispatchEvent('#source', 'dragstart', { dataTransfer });
```
+```java
+// Note you can only create DataTransfer in Chromium and Firefox
+JSHandle dataTransfer = page.evaluateHandle("() => new DataTransfer()");
+Map arg = new HashMap<>();
+arg.put("dataTransfer", dataTransfer);
+page.dispatchEvent("#source", "dragstart", arg);
+```
+
```python async
# note you can only create data_transfer in chromium and firefox
data_transfer = await page.evaluate_handle("new DataTransfer()")
@@ -655,6 +735,25 @@ await page.evaluate(() => matchMedia('print').matches);
// → false
```
+```java
+page.evaluate("() => matchMedia('screen').matches");
+// → true
+page.evaluate("() => matchMedia('print').matches");
+// → false
+
+page.emulateMedia(new Page.EmulateMediaOptions().withMedia(Media.PRINT));
+page.evaluate("() => matchMedia('screen').matches");
+// → false
+page.evaluate("() => matchMedia('print').matches");
+// → true
+
+page.emulateMedia(new Page.EmulateMediaOptions());
+page.evaluate("() => matchMedia('screen').matches");
+// → true
+page.evaluate("() => matchMedia('print').matches");
+// → false
+```
+
```python async
await page.evaluate("matchMedia('screen').matches")
# → True
@@ -703,6 +802,16 @@ await page.evaluate(() => matchMedia('(prefers-color-scheme: no-preference)').ma
// → false
```
+```java
+page.emulateMedia(new Page.EmulateMediaOptions().withColorScheme(ColorScheme.DARK));
+page.evaluate("() => matchMedia('(prefers-color-scheme: dark)').matches");
+// → true
+page.evaluate("() => matchMedia('(prefers-color-scheme: light)').matches");
+// → false
+page.evaluate("() => matchMedia('(prefers-color-scheme: no-preference)').matches");
+// → false
+```
+
```python async
await page.emulate_media(color_scheme="dark")
await page.evaluate("matchMedia('(prefers-color-scheme: dark)').matches")
@@ -755,6 +864,12 @@ const preloadHref = await page.$eval('link[rel=preload]', el => el.href);
const html = await page.$eval('.main-container', (e, suffix) => e.outerHTML + suffix, 'hello');
```
+```java
+String searchValue = (String) page.evalOnSelector("#search", "el => el.value");
+String preloadHref = (String) page.evalOnSelector("link[rel=preload]", "el => el.href");
+String html = (String) page.evalOnSelector(".main-container", "(e, suffix) => e.outerHTML + suffix", "hello");
+```
+
```python async
search_value = await page.eval_on_selector("#search", "el => el.value")
preload_href = await page.eval_on_selector("link[rel=preload]", "el => el.href")
@@ -796,6 +911,10 @@ Examples:
const divCounts = await page.$$eval('div', (divs, min) => divs.length >= min, 10);
```
+```java
+boolean divCounts = (boolean) page.evalOnSelectorAll("div", "(divs, min) => divs.length >= min", 10);
+```
+
```python async
div_counts = await page.eval_on_selector_all("div", "(divs, min) => divs.length >= min", 10)
```
@@ -834,6 +953,13 @@ const result = await page.evaluate(([x, y]) => {
console.log(result); // prints "56"
```
+```java
+Object result = page.evaluate("([x, y]) => {\n" +
+ " return Promise.resolve(x * y);\n" +
+ "}", Arrays.asList(7, 8));
+System.out.println(result); // prints "56"
+```
+
```python async
result = await page.evaluate("([x, y]) => Promise.resolve(x * y)", [7, 8])
print(result) # prints "56"
@@ -852,6 +978,10 @@ const x = 10;
console.log(await page.evaluate(`1 + ${x}`)); // prints "11"
```
+```java
+System.out.println(page.evaluate("1 + 2")); // prints "3"
+```
+
```python async
print(await page.evaluate("1 + 2")) # prints "3"
x = 10
@@ -872,6 +1002,12 @@ const html = await page.evaluate(([body, suffix]) => body.innerHTML + suffix, [b
await bodyHandle.dispose();
```
+```java
+ElementHandle bodyHandle = page.querySelector("body");
+String html = (String) page.evaluate("([body, suffix]) => body.innerHTML + suffix", Arrays.asList(bodyHandle, "hello"));
+bodyHandle.dispose();
+```
+
```python async
body_handle = await page.query_selector("body")
html = await page.evaluate("([body, suffix]) => body.innerHTML + suffix", [body_handle, "hello"])
@@ -908,6 +1044,11 @@ const aWindowHandle = await page.evaluateHandle(() => Promise.resolve(window));
aWindowHandle; // Handle for the window object.
```
+```java
+// Handle for the window object.
+JSHandle aWindowHandle = page.evaluateHandle("() => Promise.resolve(window)");
+```
+
```python async
a_window_handle = await page.evaluate_handle("Promise.resolve(window)")
a_window_handle # handle for the window object.
@@ -924,6 +1065,10 @@ A string can also be passed in instead of a function:
const aHandle = await page.evaluateHandle('document'); // Handle for the 'document'
```
+```java
+JSHandle aHandle = page.evaluateHandle("document"); // Handle for the "document".
+```
+
```python async
a_handle = await page.evaluate_handle("document") # handle for the "document"
```
@@ -941,6 +1086,13 @@ console.log(await resultHandle.jsonValue());
await resultHandle.dispose();
```
+```java
+JSHandle aHandle = page.evaluateHandle("() => document.body");
+JSHandle resultHandle = page.evaluateHandle("([body, suffix]) => body.innerHTML + suffix", Arrays.asList(aHandle, "hello"));
+System.out.println(resultHandle.jsonValue());
+resultHandle.dispose();
+```
+
```python async
a_handle = await page.evaluate_handle("document.body")
result_handle = await page.evaluate_handle("body => body.innerHTML", a_handle)
@@ -1000,6 +1152,30 @@ const { webkit } = require('playwright'); // Or 'chromium' or 'firefox'.
})();
```
+```java
+import com.microsoft.playwright.*;
+
+public class Example {
+ public static void main(String[] args) {
+ try (Playwright playwright = Playwright.create()) {
+ BrowserType webkit = playwright.webkit();
+ Browser browser = webkit.launch({ headless: false });
+ BrowserContext context = browser.newContext();
+ Page page = context.newPage();
+ page.exposeBinding("pageURL", (source, args) -> source.page().url());
+ page.setContent("\n" +
+ "\n" +
+ "");
+ page.click("button");
+ }
+ }
+}
+```
+
```python async
import asyncio
from playwright.async_api import async_playwright
@@ -1066,6 +1242,20 @@ await page.setContent(`
`);
```
+```java
+page.exposeBinding("clicked", (source, args) -> {
+ ElementHandle element = (ElementHandle) args[0];
+ System.out.println(element.textContent());
+ return null;
+}, new Page.ExposeBindingOptions().withHandle(true));
+page.setContent("" +
+ "\n" +
+ "
Click me
\n" +
+ "
Or click me
\n");
+```
+
```python async
async def print(source, element):
print(await element.text_content())
@@ -1146,6 +1336,44 @@ const crypto = require('crypto');
})();
```
+```java
+import com.microsoft.playwright.*;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Base64;
+
+public class Example {
+ public static void main(String[] args) {
+ try (Playwright playwright = Playwright.create()) {
+ BrowserType webkit = playwright.webkit();
+ Browser browser = webkit.launch({ headless: false });
+ Page page = browser.newPage();
+ page.exposeFunction("sha1", args -> {
+ String text = (String) args[0];
+ MessageDigest crypto;
+ try {
+ crypto = MessageDigest.getInstance("SHA-1");
+ } catch (NoSuchAlgorithmException e) {
+ return null;
+ }
+ byte[] token = crypto.digest(text.getBytes(StandardCharsets.UTF_8));
+ return Base64.getEncoder().encodeToString(token);
+ });
+ page.setContent("\n" +
+ "\n" +
+ "\n");
+ page.click("button");
+ }
+ }
+}
+```
+
```python async
import asyncio
import hashlib
@@ -1261,6 +1489,10 @@ Returns frame matching the specified criteria. Either `name` or `url` must be sp
const frame = page.frame('frame-name');
```
+```java
+Frame frame = page.frame("frame-name");
+```
+
```py
frame = page.frame(name="frame-name")
```
@@ -1269,6 +1501,10 @@ frame = page.frame(name="frame-name")
const frame = page.frame({ url: /.*domain.*/ });
```
+```java
+Frame frame = page.frameByUrl(Pattern.compile(".*domain.*");
+```
+
```py
frame = page.frame(url=r".*domain.*")
```
@@ -1545,6 +1781,12 @@ await page.emulateMedia({media: 'screen'});
await page.pdf({path: 'page.pdf'});
```
+```java
+// Generates a PDF with "screen" media type.
+page.emulateMedia(new Page.EmulateMediaOptions().withMedia(Media.SCREEN));
+page.pdf(new Page.PdfOptions().withPath(Paths.get("page.pdf")));
+```
+
```python async
# generates a pdf with "screen" media type.
await page.emulate_media(media="screen")
@@ -1726,6 +1968,17 @@ await page.screenshot({ path: 'O.png' });
await browser.close();
```
+```java
+Page page = browser.newPage();
+page.navigate("https://keycode.info");
+page.press("body", "A");
+page.screenshot(new Page.ScreenshotOptions().withPath(Paths.get("A.png")));
+page.press("body", "ArrowLeft");
+page.screenshot(new Page.ScreenshotOptions().withPath(Paths.get("ArrowLeft.png" )));
+page.press("body", "Shift+O");
+page.screenshot(new Page.ScreenshotOptions().withPath(Paths.get("O.png" )));
+```
+
```python async
page = await browser.new_page()
await page.goto("https://keycode.info")
@@ -1821,6 +2074,13 @@ await page.goto('https://example.com');
await browser.close();
```
+```java
+Page page = browser.newPage();
+page.route("**/*.{png,jpg,jpeg}", route -> route.abort());
+page.navigate("https://example.com");
+browser.close();
+```
+
```python async
page = await browser.new_page()
await page.route("**/*.{png,jpg,jpeg}", lambda route: route.abort())
@@ -1844,6 +2104,13 @@ await page.goto('https://example.com');
await browser.close();
```
+```java
+Page page = browser.newPage();
+page.route(Pattern.compile("(\\.png$)|(\\.jpg$)"),route -> route.abort());
+page.navigate("https://example.com");
+browser.close();
+```
+
```python async
page = await browser.new_page()
await page.route(re.compile(r"(\.png$)|(\.jpg$)"), lambda route: route.abort())
@@ -1950,6 +2217,15 @@ page.selectOption('select#colors', ['red', 'green', 'blue']);
```
+```java
+// single selection matching the value
+page.selectOption("select#colors", "blue");
+// single selection matching both the value and the label
+page.selectOption("select#colors", new SelectOption().withLabel("Blue"));
+// multiple selection
+page.selectOption("select#colors", new String[] {"red", "green", "blue"});
+```
+
```python async
# single selection matching the value
await page.select_option("select#colors", "blue")
@@ -2068,6 +2344,12 @@ await page.setViewportSize({
await page.goto('https://example.com');
```
+```java
+Page page = browser.newPage();
+page.setViewportSize(640, 480);
+page.navigate("https://example.com");
+```
+
```python async
page = await browser.new_page()
await page.set_viewport_size({"width": 640, "height": 480})
@@ -2146,6 +2428,13 @@ await page.type('#mytextarea', 'Hello'); // Types instantly
await page.type('#mytextarea', 'World', {delay: 100}); // Types slower, like a user
```
+```java
+// Types instantly
+page.type("#mytextarea", "Hello");
+// Types slower, like a user
+page.type("#mytextarea", "World", new Page.TypeOptions().withDelay(100));
+```
+
```python async
await page.type("#mytextarea", "hello") # types instantly
await page.type("#mytextarea", "world", delay=100) # types slower, like a user
@@ -2352,6 +2641,23 @@ const { webkit } = require('playwright'); // Or 'chromium' or 'firefox'.
})();
```
+```java
+import com.microsoft.playwright.*;
+
+public class Example {
+ public static void main(String[] args) {
+ try (Playwright playwright = Playwright.create()) {
+ BrowserType webkit = playwright.webkit();
+ Browser browser = webkit.launch();
+ Page page = browser.newPage();
+ page.setViewportSize(50, 50);
+ page.waitForFunction("() => window.innerWidth < 100");
+ browser.close();
+ }
+ }
+}
+```
+
```python async
import asyncio
from playwright.async_api import async_playwright
@@ -2392,6 +2698,11 @@ const selector = '.foo';
await page.waitForFunction(selector => !!document.querySelector(selector), selector);
```
+```java
+String selector = ".foo";
+page.waitForFunction("selector => !!document.querySelector(selector)", selector);
+```
+
```python async
selector = ".foo"
await page.wait_for_function("selector => !!document.querySelector(selector)", selector)
@@ -2429,6 +2740,11 @@ await page.click('button'); // Click triggers navigation.
await page.waitForLoadState(); // The promise resolves after 'load' event.
```
+```java
+page.click("button"); // Click triggers navigation.
+page.waitForLoadState(); // The promise resolves after "load" event.
+```
+
```python async
await page.click("button") # click triggers navigation.
await page.wait_for_load_state() # the promise resolves after "load" event.
@@ -2448,6 +2764,14 @@ await popup.waitForLoadState('domcontentloaded'); // The promise resolves after
console.log(await popup.title()); // Popup is ready to use.
```
+```java
+Page popup = page.waitForPopup(() -> {
+ page.click("button"); // Click triggers a popup.
+});
+popup.waitForLoadState(LoadState.DOMCONTENTLOADED);
+System.out.println(popup.title()); // Popup is ready to use.
+```
+
```python async
async with page.expect_popup() as page_info:
await page.click("button") # click triggers a popup.
@@ -2492,6 +2816,13 @@ const [response] = await Promise.all([
]);
```
+```java
+// The method returns after navigation has finished
+Response response = page.waitForNavigation(() -> {
+ page.click("a.delayed-navigation"); // Clicking the link will indirectly cause a navigation
+});
+```
+
```python async
async with page.expect_navigation():
await page.click("a.delayed-navigation") # clicking the link will indirectly cause a navigation
@@ -2546,6 +2877,13 @@ const finalRequest = await page.waitForRequest(request => request.url() === 'htt
return firstRequest.url();
```
+```java
+Request firstRequest = page.waitForRequest("http://example.com/resource");
+Object finalRequest = page.waitForRequest(
+ request -> "http://example.com".equals(request.url()) && "GET".equals(request.method()), () -> {});
+return firstRequest.url();
+```
+
```python async
async with page.expect_request("http://example.com/resource") as first:
await page.click('button')
@@ -2594,6 +2932,12 @@ const finalResponse = await page.waitForResponse(response => response.url() ===
return finalResponse.ok();
```
+```java
+Response firstResponse = page.waitForResponse("https://example.com/resource", () -> {});
+Response finalResponse = page.waitForResponse(response -> "https://example.com".equals(response.url()) && response.status() == 200, () -> {});
+return finalResponse.ok();
+```
+
```python async
first_response = await page.wait_for_response("https://example.com/resource")
final_response = await page.wait_for_response(lambda response: response.url == "https://example.com" and response.status === 200)
@@ -2645,6 +2989,26 @@ const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'.
})();
```
+```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();
+ for (String currentURL : Arrays.asList("https://google.com", "https://bbc.com")) {
+ page.navigate(currentURL);
+ ElementHandle element = page.waitForSelector("img");
+ System.out.println("Loaded image: " + element.getAttribute("src"));
+ }
+ browser.close();
+ }
+ }
+}
+```
+
```python async
import asyncio
from playwright.async_api import async_playwright
@@ -2700,6 +3064,11 @@ flaky. Use signals such as network events, selectors becoming visible and others
await page.waitForTimeout(1000);
```
+```java
+// wait for 1 second
+page.waitForTimeout(1000);
+```
+
```python async
# wait for 1 second
await page.wait_for_timeout(1000)
diff --git a/docs/src/api/class-playwright.md b/docs/src/api/class-playwright.md
index 51a28fb7fd..8ccf739686 100644
--- a/docs/src/api/class-playwright.md
+++ b/docs/src/api/class-playwright.md
@@ -15,6 +15,23 @@ const { chromium, firefox, webkit } = 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.navigate("http://example.com");
+ // other actions...
+ browser.close();
+ }
+ }
+}
+```
+
```python async
import asyncio
from playwright.async_api import async_playwright
diff --git a/docs/src/api/class-request.md b/docs/src/api/class-request.md
index 264dd44518..f9ed5b3fec 100644
--- a/docs/src/api/class-request.md
+++ b/docs/src/api/class-request.md
@@ -29,6 +29,12 @@ page.on('requestfailed', request => {
});
```
+```java
+page.onRequestFailed(request -> {
+ System.out.println(request.url() + " " + request.failure());
+});
+```
+
```py
page.on("requestfailed", lambda request: print(request.url + " " + request.failure))
```
@@ -88,6 +94,11 @@ const response = await page.goto('http://example.com');
console.log(response.request().redirectedFrom().url()); // 'http://example.com'
```
+```java
+Response response = page.navigate("http://example.com");
+System.out.println(response.request().redirectedFrom().url()); // "http://example.com"
+```
+
```python async
response = await page.goto("http://example.com")
print(response.request.redirected_from.url) # "http://example.com"
@@ -105,6 +116,11 @@ const response = await page.goto('https://google.com');
console.log(response.request().redirectedFrom()); // null
```
+```java
+Response response = page.navigate("https://google.com");
+System.out.println(response.request().redirectedFrom()); // null
+```
+
```python async
response = await page.goto("https://google.com")
print(response.request.redirected_from) # None
@@ -126,6 +142,10 @@ This method is the opposite of [`method: Request.redirectedFrom`]:
console.log(request.redirectedFrom().redirectedTo() === request); // true
```
+```java
+System.out.println(request.redirectedFrom().redirectedTo() == request); // true
+```
+
```py
assert request.redirected_from.redirected_to == request
```
@@ -175,6 +195,14 @@ const [request] = await Promise.all([
console.log(request.timing());
```
+```java
+page.onRequestFinished(request -> {
+ Timing timing = request.timing();
+ System.out.println(timing.responseEnd - timing.startTime);
+});
+page.navigate("http://example.com");
+```
+
```python async
async with page.expect_event("requestfinished") as request_info:
await page.goto("http://example.com")
diff --git a/docs/src/api/class-route.md b/docs/src/api/class-route.md
index 745d8876d6..82bd997fd3 100644
--- a/docs/src/api/class-route.md
+++ b/docs/src/api/class-route.md
@@ -48,6 +48,16 @@ await page.route('**/*', (route, request) => {
});
```
+```java
+page.route("**/*", route -> {
+ // Override headers
+ Map headers = new HashMap<>(route.request().headers());
+ headers.put("foo", "bar"); // set "foo" header
+ headers.remove("origin"); // remove "origin" header
+ route.resume(new Route.ResumeOptions().withHeaders(headers));
+});
+```
+
```python async
async def handle(route, request):
# override headers
@@ -110,6 +120,15 @@ await page.route('**/*', route => {
});
```
+```java
+page.route("**/*", route -> {
+ route.fulfill(new Route.FulfillOptions()
+ .withStatus(404)
+ .withContentType("text/plain")
+ .withBody("Not Found!"));
+});
+```
+
```python async
await page.route("**/*", lambda route: route.fulfill(
status=404,
@@ -130,6 +149,11 @@ An example of serving static file:
await page.route('**/xhr_endpoint', route => route.fulfill({ path: 'mock_data.json' }));
```
+```java
+page.route("**/xhr_endpoint", route -> route.fulfill(
+ new Route.FulfillOptions().withPath(Paths.get("mock_data.json")));
+```
+
```python async
await page.route("**/xhr_endpoint", lambda route: route.fulfill(path="mock_data.json"))
```
diff --git a/docs/src/api/class-selectors.md b/docs/src/api/class-selectors.md
index e62cd53a84..659e86db77 100644
--- a/docs/src/api/class-selectors.md
+++ b/docs/src/api/class-selectors.md
@@ -1,7 +1,7 @@
# class: Selectors
-Selectors can be used to install custom selector engines. See
-[Working with selectors](./selectors.md) for more information.
+Selectors can be used to install custom selector engines. See [Working with selectors](./selectors.md) for more
+information.
## async method: Selectors.register
@@ -42,6 +42,32 @@ const { selectors, firefox } = require('playwright'); // Or 'chromium' or 'webk
})();
```
+```java
+// 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" +
+ " // 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);
+Browser browser = playwright.firefox().launch();
+Page page = browser.newPage();
+page.setContent("");
+// Use the selector prefixed with its name.
+ElementHandle button = page.querySelector("tag=button");
+// Combine it with other selector engines.
+page.click("tag=div >> text=\"Click me\"");
+// Can use it in any methods supporting selectors.
+int buttonCount = (int) page.evalOnSelectorAll("tag=button", "buttons => buttons.length");
+browser.close();
+```
+
```python async
# FIXME: add snippet
```
@@ -76,4 +102,4 @@ Script that evaluates to a selector engine instance.
Whether to run this selector engine in isolated JavaScript environment. This environment has access to the same DOM, but
not any JavaScript objects from the frame's scripts. Defaults to `false`. Note that running as a content script is not
-guaranteed when this engine is used together with other registered engines.
+guaranteed when this engine is used together with other registered engines.
\ No newline at end of file
diff --git a/docs/src/api/class-video.md b/docs/src/api/class-video.md
index 89465ae85d..275e3b1c01 100644
--- a/docs/src/api/class-video.md
+++ b/docs/src/api/class-video.md
@@ -6,6 +6,10 @@ When browser context is created with the `videosPath` option, each page has a vi
console.log(await page.video().path());
```
+```java
+System.out.println(page.video().path());
+```
+
```python async
print(await page.video.path())
```
@@ -18,4 +22,4 @@ print(page.video.path())
- returns: <[path]>
Returns the file system path this video will be recorded to. The video is guaranteed to be written to the filesystem
-upon closing the browser context.
+upon closing the browser context.
\ No newline at end of file
diff --git a/docs/src/api/class-worker.md b/docs/src/api/class-worker.md
index 4c2997aa14..04bf4fbb86 100644
--- a/docs/src/api/class-worker.md
+++ b/docs/src/api/class-worker.md
@@ -15,6 +15,16 @@ for (const worker of page.workers())
console.log(' ' + worker.url());
```
+```java
+page.onWorker(worker -> {
+ System.out.println("Worker created: " + worker.url());
+ worker.onClose(worker1 -> System.out.println("Worker destroyed: " + worker1.url()));
+});
+System.out.println("Current workers:");
+for (Worker worker : page.workers())
+ System.out.println(" " + worker.url());
+```
+
```py
def handle_worker(worker):
print("worker created: " + worker.url)
diff --git a/types/types.d.ts b/types/types.d.ts
index 90a2612d5c..4b2df6a3c8 100644
--- a/types/types.d.ts
+++ b/types/types.d.ts
@@ -4576,11 +4576,11 @@ export interface BrowserContext {
* done and its response has started loading in the popup.
*
* ```js
- * const [page] = await Promise.all([
+ * const [newPage] = await Promise.all([
* context.waitForEvent('page'),
* page.click('a[target=_blank]'),
* ]);
- * console.log(await page.evaluate('location.href'));
+ * console.log(await newPage.evaluate('location.href'));
* ```
*
* > NOTE: Use
@@ -4607,11 +4607,11 @@ export interface BrowserContext {
* done and its response has started loading in the popup.
*
* ```js
- * const [page] = await Promise.all([
+ * const [newPage] = await Promise.all([
* context.waitForEvent('page'),
* page.click('a[target=_blank]'),
* ]);
- * console.log(await page.evaluate('location.href'));
+ * console.log(await newPage.evaluate('location.href'));
* ```
*
* > NOTE: Use
@@ -4638,11 +4638,11 @@ export interface BrowserContext {
* done and its response has started loading in the popup.
*
* ```js
- * const [page] = await Promise.all([
+ * const [newPage] = await Promise.all([
* context.waitForEvent('page'),
* page.click('a[target=_blank]'),
* ]);
- * console.log(await page.evaluate('location.href'));
+ * console.log(await newPage.evaluate('location.href'));
* ```
*
* > NOTE: Use
@@ -4669,11 +4669,11 @@ export interface BrowserContext {
* done and its response has started loading in the popup.
*
* ```js
- * const [page] = await Promise.all([
+ * const [newPage] = await Promise.all([
* context.waitForEvent('page'),
* page.click('a[target=_blank]'),
* ]);
- * console.log(await page.evaluate('location.href'));
+ * console.log(await newPage.evaluate('location.href'));
* ```
*
* > NOTE: Use
@@ -4700,11 +4700,11 @@ export interface BrowserContext {
* done and its response has started loading in the popup.
*
* ```js
- * const [page] = await Promise.all([
+ * const [newPage] = await Promise.all([
* context.waitForEvent('page'),
* page.click('a[target=_blank]'),
* ]);
- * console.log(await page.evaluate('location.href'));
+ * console.log(await newPage.evaluate('location.href'));
* ```
*
* > NOTE: Use
@@ -5113,11 +5113,11 @@ export interface BrowserContext {
* done and its response has started loading in the popup.
*
* ```js
- * const [page] = await Promise.all([
+ * const [newPage] = await Promise.all([
* context.waitForEvent('page'),
* page.click('a[target=_blank]'),
* ]);
- * console.log(await page.evaluate('location.href'));
+ * console.log(await newPage.evaluate('location.href'));
* ```
*
* > NOTE: Use
@@ -8627,11 +8627,11 @@ export interface ChromiumBrowserContext extends BrowserContext {
* done and its response has started loading in the popup.
*
* ```js
- * const [page] = await Promise.all([
+ * const [newPage] = await Promise.all([
* context.waitForEvent('page'),
* page.click('a[target=_blank]'),
* ]);
- * console.log(await page.evaluate('location.href'));
+ * console.log(await newPage.evaluate('location.href'));
* ```
*
* > NOTE: Use
@@ -8670,11 +8670,11 @@ export interface ChromiumBrowserContext extends BrowserContext {
* done and its response has started loading in the popup.
*
* ```js
- * const [page] = await Promise.all([
+ * const [newPage] = await Promise.all([
* context.waitForEvent('page'),
* page.click('a[target=_blank]'),
* ]);
- * console.log(await page.evaluate('location.href'));
+ * console.log(await newPage.evaluate('location.href'));
* ```
*
* > NOTE: Use
@@ -8713,11 +8713,11 @@ export interface ChromiumBrowserContext extends BrowserContext {
* done and its response has started loading in the popup.
*
* ```js
- * const [page] = await Promise.all([
+ * const [newPage] = await Promise.all([
* context.waitForEvent('page'),
* page.click('a[target=_blank]'),
* ]);
- * console.log(await page.evaluate('location.href'));
+ * console.log(await newPage.evaluate('location.href'));
* ```
*
* > NOTE: Use
@@ -8756,11 +8756,11 @@ export interface ChromiumBrowserContext extends BrowserContext {
* done and its response has started loading in the popup.
*
* ```js
- * const [page] = await Promise.all([
+ * const [newPage] = await Promise.all([
* context.waitForEvent('page'),
* page.click('a[target=_blank]'),
* ]);
- * console.log(await page.evaluate('location.href'));
+ * console.log(await newPage.evaluate('location.href'));
* ```
*
* > NOTE: Use
@@ -8799,11 +8799,11 @@ export interface ChromiumBrowserContext extends BrowserContext {
* done and its response has started loading in the popup.
*
* ```js
- * const [page] = await Promise.all([
+ * const [newPage] = await Promise.all([
* context.waitForEvent('page'),
* page.click('a[target=_blank]'),
* ]);
- * console.log(await page.evaluate('location.href'));
+ * console.log(await newPage.evaluate('location.href'));
* ```
*
* > NOTE: Use
@@ -8858,11 +8858,11 @@ export interface ChromiumBrowserContext extends BrowserContext {
* done and its response has started loading in the popup.
*
* ```js
- * const [page] = await Promise.all([
+ * const [newPage] = await Promise.all([
* context.waitForEvent('page'),
* page.click('a[target=_blank]'),
* ]);
- * console.log(await page.evaluate('location.href'));
+ * console.log(await newPage.evaluate('location.href'));
* ```
*
* > NOTE: Use
@@ -9052,9 +9052,9 @@ export interface ConsoleMessage {
* page.on('dialog', async dialog => {
* console.log(dialog.message());
* await dialog.dismiss();
- * await browser.close();
* });
- * page.evaluate(() => alert('1'));
+ * await page.evaluate(() => alert('1'));
+ * await browser.close();
* })();
* ```
*
diff --git a/utils/doclint/generateJavaSnippets.js b/utils/doclint/generateJavaSnippets.js
new file mode 100644
index 0000000000..386fbab776
--- /dev/null
+++ b/utils/doclint/generateJavaSnippets.js
@@ -0,0 +1,154 @@
+// @ts-check
+
+const fs = require("fs");
+const md = require("../markdown");
+
+
+/**
+ * @param {string[]} input
+ */
+function transformValue(input) {
+ const out = [];
+ const suffix = [];
+ for (let line of input) {
+ let match = line.match(/const { (\w+) } = require\('playwright'\);/);
+ if (match) {
+ out.push('import com.microsoft.playwright.*;');
+ out.push('');
+ out.push('public class Example {');
+ out.push(' public static void main(String[] args) {');
+ out.push(' try (Playwright playwright = Playwright.create()) {');
+ out.push(` BrowserType ${match[1]} = playwright.${match[1]}();`);
+ suffix.push(' }');
+ suffix.push(' }');
+ suffix.push('}');
+ continue;
+ }
+ if (line.trim() === '(async () => {' || line.trim() === '})();')
+ continue;
+ if (!line)
+ continue;
+ if (line.trim() === '}')
+ continue;
+
+ // Remove await/Promise.all
+ line = line.replace(/const \[(.+)\] = await Promise.all\(\[/g, '$1 =');
+ line = line.replace(/Promise\.all\(\[/g, '');
+ line = line.replace(/await /g, '');
+
+ // Rename some methods
+ line = line.replace(/\.goto\(/g, '.navigate(');
+ line = line.replace(/\.continue\(/g, '.resume(');
+ line = line.replace(/\.\$eval\(/g, '.evalOnSelector(');
+ line = line.replace(/\.\$\$eval\(/g, '.evalOnSelectorAll(');
+ line = line.replace(/\.\$\(/g, '.querySelector(');
+ line = line.replace(/\.\$\$\(/g, '.querySelectorAll(');
+
+ line = line.replace(/console.log/g, 'System.out.println');
+
+ line = line.replace(/page.evaluate\((\(\) => [^\)]+)\)/g, 'page.evaluate("$1")');
+
+ // Convert properties to methods
+ line = line.replace(/\.keyboard\./g, '.keyboard().');
+ line = line.replace(/\.mouse\./g, '.mouse().');
+ line = line.replace(/\.coverage\./g, '.coverage().');
+ line = line.replace(/\.accessibility\./g, '.accessibility().');
+ line = line.replace(/\.chromium\./g, '.chromium().');
+ line = line.replace(/\.webkit\./g, '.webkit().');
+ line = line.replace(/\.firefox\./g, '.firefox().');
+ line = line.replace(/\.length/g, '.size()');
+
+ // JUnit asserts
+ line = line.replace(/expect\((.+)\).toBeTruthy\(\);/g, 'assertNotNull($1);');
+ line = line.replace(/expect\(error.message\)\.toContain\((.+)\);/g, 'assertTrue(e.getMessage().contains($1));');
+ line = line.replace(/expect\((.+)\)\.toContain\((.+)\);/g, 'assertTrue($1.contains($2));');
+ line = line.replace(/expect\((.+)\)\.toBe\(null\);/g, 'assertNull($1);');
+ line = line.replace(/expect\((.+)\)\.not.toBe\(null\);/g, 'assertNotNull($1);');
+ line = line.replace(/expect\((.+)\)\.toBe\(true\);/g, 'assertTrue($1);');
+ line = line.replace(/expect\((.+)\)\.toBe\((.+)\);/g, 'assertEquals($2, $1);');
+ line = line.replace(/expect\((.+)\)\.toEqual\(\[(.+)\]\);/g, 'assertEquals(Arrays.asList($2), $1);');
+ line = line.replace(/expect\((.+)\)\.toEqual\((.+)\);/g, 'assertEquals($2, $1);');
+
+ line = line.replace(/\[('[^']+')\]/g, '.get("$1")');
+ line = line.replace(/.push\(/g, '.add(');
+
+ // Define common types
+ line = line.replace(/const browser = /g, 'Browser browser = ');
+ line = line.replace(/const context = /g, 'BrowserContext context = ');
+ line = line.replace(/const page = /g, 'Page page = ');
+ line = line.replace(/const newPage = /g, 'Page newPage = ');
+ line = line.replace(/const button/g, 'ElementHandle button');
+ line = line.replace(/const result = /g, 'Object result = ');
+ line = line.replace(/const response = /g, 'Response response = ');
+ line = line.replace(/const request = /g, 'Request request = ');
+ line = line.replace(/const requests = \[\];/g, 'List requests = new ArrayList<>();');
+ line = line.replace(/const snapshot = page.accessibility/g, 'String snapshot = page.accessibility');
+ line = line.replace(/snapshot\.children\./g, 'snapshot.children().');
+ line = line.replace(/const (.+) = \[\];/g, 'List<> $1 = new ArrayList<>();');
+ line = line.replace(/const (\w+ = .+evalOnSelector)/g, 'Object $1');
+ line = line.replace(/const (\w+ = .+querySelector)/g, 'ElementHandle $1');
+ line = line.replace(/const (.+= page.waitForNavigation)/g, 'Response $1');
+ line = line.replace(/const messages = \[\]/g, 'List messages = new ArrayList<>()');
+ line = line.replace(/const frame = /g, 'Frame frame = ');
+ line = line.replace(/const elementHandle = (.+)/g, 'JSHandle jsHandle = $1\n ElementHandle elementHandle = jsHandle.asElement();\n');
+ line = line.replace(/const (\w+ = \w+\.boundingBox)/g, 'BoundingBox $1');
+ line = line.replace(/setViewportSize\({ width: (\d+), height: (\d+) }\)/g, 'setViewportSize($1, $2)');
+ line = line.replace(/\.on\('([^']+)'/g, (match, p1, offset, string) => `.on${toTitleCase(p1)}(`);
+ line = line.replace(/\.waitForEvent\('([^']+)'/g, (match, p1, offset, string) => `page.waitFor${toTitleCase(p1)}(() -> {})`);
+
+ line = line.replace(/[`']/g, '"');
+
+ out.push(line)
+ }
+ return [...out, ...suffix].join("\n");
+}
+
+/**
+ * @param {string} name
+ */
+function toTitleCase(name) {
+ return name[0].toUpperCase() + name.substring(1);
+}
+
+/**
+ * @param {md.MarkdownNode} node
+ */
+function generateComment(node) {
+ const commentNode = md.clone(node)
+ commentNode.codeLang = 'java';
+ commentNode.lines = ['// FIXME', ...transformValue(node.lines).split("\n")];
+ return commentNode;
+}
+
+/**
+ *
+ * @param {md.MarkdownNode[]} spec
+ */
+function multiplyComment(spec) {
+ const children = []
+ for (const node of (spec || [])) {
+ if (node.codeLang === "js")
+ children.push(node, generateComment(node));
+ else
+ children.push(node);
+ }
+ return children;
+}
+
+for (const name of fs.readdirSync("docs/src/api")) {
+ if (!name.endsWith(".md"))
+ continue;
+ if (name.includes('android'))
+ continue;
+ const inputFile = `docs/src/api/${name}`;
+ const fileline = fs.readFileSync(inputFile).toString();
+ const nodes = md.parse(fileline);
+
+ md.visitAll(nodes, node => {
+ if (node.children)
+ node.children = multiplyComment(node.children);
+ });
+
+ const out = md.render(nodes, 120);
+ fs.writeFileSync(inputFile, out);
+}
diff --git a/utils/markdown.js b/utils/markdown.js
index 5085c25cbb..91e68899a2 100644
--- a/utils/markdown.js
+++ b/utils/markdown.js
@@ -227,7 +227,7 @@ function render(nodes, maxColumns) {
*/
function innerRenderMdNode(indent, node, lastNode, result, maxColumns) {
const newLine = () => {
- if (result[result.length - 1] !== '')
+ if (result.length && result[result.length - 1] !== '')
result.push('');
};