diff --git a/docs/src/api/class-accessibility.md b/docs/src/api/class-accessibility.md index 1550cb3820..a5680c8406 100644 --- a/docs/src/api/class-accessibility.md +++ b/docs/src/api/class-accessibility.md @@ -47,9 +47,8 @@ Captures the current state of the accessibility tree. The returned object repres page. :::note -The Chromium accessibility tree contains nodes that go unused on most platforms and by most screen readers. -Playwright will discard them as well for an easier to process tree, unless [`option: interestingOnly`] is set to -`false`. +The Chromium accessibility tree contains nodes that go unused on most platforms and by most screen readers. Playwright +will discard them as well for an easier to process tree, unless [`option: interestingOnly`] is set to `false`. ::: An example of dumping the entire accessibility tree: @@ -59,6 +58,16 @@ const snapshot = await page.accessibility.snapshot(); console.log(snapshot); ``` +```python async +snapshot = await page.accessibility.snapshot() +print(snapshot) +``` + +```python sync +snapshot = page.accessibility.snapshot() +print(snapshot) +``` + An example of logging the focused node's name: ```js @@ -77,6 +86,36 @@ function findFocusedNode(node) { } ``` +```python async +def find_focused_node(node): + if (node.get("focused")) + return node + for child in (node.get("children") or []): + found_node = find_focused_node(child) + return found_node + return null + +snapshot = await page.accessibility.snapshot() +node = find_focused_node(snapshot) +if node: + print(node["name"]) +``` + +```python sync +def find_focused_node(node): + if (node.get("focused")) + return node + for child in (node.get("children") or []): + found_node = find_focused_node(child) + return found_node + return null + +snapshot = page.accessibility.snapshot() +node = find_focused_node(snapshot) +if node: + print(node["name"]) +``` + ### option: Accessibility.snapshot.interestingOnly - `interestingOnly` <[boolean]> diff --git a/docs/src/api/class-browser.md b/docs/src/api/class-browser.md index faa503bb10..ba6ea0148b 100644 --- a/docs/src/api/class-browser.md +++ b/docs/src/api/class-browser.md @@ -14,6 +14,37 @@ const { firefox } = require('playwright'); // Or 'chromium' or 'webkit'. })(); ``` +```python async +import asyncio +from playwright.async_api import async_playwright + +async def run(playwright): + firefox = playwright.firefox + browser = await firefox.launch() + page = await browser.new_page() + await page.goto("https://example.com") + await browser.close() + +async def main(): + async with async_playwright() as playwright: + await run(playwright) +asyncio.run(main()) +``` + +```python sync +from playwright.sync_api import sync_playwright + +def run(playwright): + firefox = playwright.firefox + browser = firefox.launch() + page = browser.new_page() + page.goto("https://example.com") + browser.close() + +with sync_playwright() as playwright: + run(playwright) +``` + ## event: Browser.disconnected Emitted when Browser gets disconnected from the browser application. This might happen because of one of the following: @@ -25,8 +56,8 @@ Emitted when Browser gets disconnected from the browser application. This might In case this browser is obtained using [`method: BrowserType.launch`], closes the browser and all of its pages (if any were opened). -In case this browser is connected to, clears all created contexts belonging to this -browser and disconnects from the browser server. +In case this browser is connected to, clears all created contexts belonging to this browser and disconnects from the +browser server. The [Browser] object itself is considered to be disposed and cannot be used anymore. @@ -43,6 +74,20 @@ const context = await browser.newContext(); console.log(browser.contexts().length); // prints `1` ``` +```python async +browser = await pw.webkit.launch() +print(len(browser.contexts())) # prints `0` +context = await browser.new_context() +print(len(browser.contexts())) # prints `1` +``` + +```python sync +browser = pw.webkit.launch() +print(len(browser.contexts())) # prints `0` +context = browser.new_context() +print(len(browser.contexts())) # prints `1` +``` + ## method: Browser.isConnected - returns: <[boolean]> @@ -64,6 +109,24 @@ Creates a new browser context. It won't share cookies/cache with other browser c })(); ``` +```python async + browser = await playwright.firefox.launch() # or "chromium" or "webkit". + # create a new incognito browser context. + context = await browser.new_context() + # create a new page in a pristine context. + page = await context.new_page() + await page.goto("https://example.com") +``` + +```python sync + browser = playwright.firefox.launch() # or "chromium" or "webkit". + # create a new incognito browser context. + context = browser.new_context() + # create a new page in a pristine context. + page = context.new_page() + page.goto("https://example.com") +``` + ### option: Browser.newContext.-inline- = %%-shared-context-params-list-%% ### option: Browser.newContext.proxy = %%-context-option-proxy-%% @@ -76,8 +139,8 @@ Creates a new browser context. It won't share cookies/cache with other browser c Creates a new page in a new browser context. Closing this page will close the context as well. This is a convenience API that should only be used for the single-page scenarios and short snippets. Production code and -testing frameworks should explicitly create [`method: Browser.newContext`] followed by the [`method: -BrowserContext.newPage`] to control their exact life times. +testing frameworks should explicitly create [`method: Browser.newContext`] followed by the +[`method: BrowserContext.newPage`] to control their exact life times. ### option: Browser.newPage.-inline- = %%-shared-context-params-list-%% diff --git a/docs/src/api/class-browsercontext.md b/docs/src/api/class-browsercontext.md index 7663713ca8..9b4e5f3466 100644 --- a/docs/src/api/class-browsercontext.md +++ b/docs/src/api/class-browsercontext.md @@ -19,6 +19,26 @@ await page.goto('https://example.com'); await context.close(); ``` +```python async +# create a new incognito browser context +context = await browser.new_context() +# create a new page inside context. +page = await context.new_page() +await page.goto("https://example.com") +# dispose context once it"s no longer needed. +await context.close() +``` + +```python sync +# create a new incognito browser context +context = browser.new_context() +# create a new page inside context. +page = context.new_page() +page.goto("https://example.com") +# dispose context once it"s no longer needed. +context.close() +``` + ## event: BrowserContext.close Emitted when Browser context gets closed. This might happen because of one of the following: @@ -44,9 +64,23 @@ const [page] = await Promise.all([ console.log(await page.evaluate('location.href')); ``` +```python async +async with context.expect_page() as page_info: + await page.click("a[target=_blank]"), +page = await page_info.value +print(await page.evaluate("location.href")) +``` + +```python sync +with context.expect_page() as page_info: + page.click("a[target=_blank]"), +page = page_info.value +print(page.evaluate("location.href")) +``` + :::note -Use [`method: Page.waitForLoadState`] to wait until the page gets to a particular state (you should not -need it in most cases). +Use [`method: Page.waitForLoadState`] to wait until the page gets to a particular state (you should not need it in most +cases). ::: ## async method: BrowserContext.addCookies @@ -58,6 +92,14 @@ obtained via [`method: BrowserContext.cookies`]. await browserContext.addCookies([cookieObject1, cookieObject2]); ``` +```python async +await browser_context.add_cookies([cookie_object1, cookie_object2]) +``` + +```python sync +browser_context.add_cookies([cookie_object1, cookie_object2]) +``` + ### param: BrowserContext.addCookies.cookies - `cookies` <[Array]<[Object]>> - `name` <[string]> @@ -74,7 +116,8 @@ await browserContext.addCookies([cookieObject1, cookieObject2]); Adds a script which would be evaluated in one of the following scenarios: * Whenever a page is created in the browser context or is navigated. -* Whenever a child frame is attached or navigated in any page in the browser context. In this case, the script is evaluated in the context of the newly attached frame. +* Whenever a child frame is attached or navigated in any page in the browser context. In this case, the script is + evaluated in the context of the newly attached frame. The script is evaluated after the document was created but before any of its scripts were run. This is useful to amend the JavaScript environment, e.g. to seed `Math.random`. @@ -93,6 +136,16 @@ await browserContext.addInitScript({ }); ``` +```python async +# in your playwright script, assuming the preload.js file is in same directory. +await browser_context.add_init_script(path="preload.js") +``` + +```python sync +# in your playwright script, assuming the preload.js file is in same directory. +browser_context.add_init_script(path="preload.js") +``` + :::note The order of evaluation of multiple scripts installed via [`method: BrowserContext.addInitScript`] and [`method: Page.addInitScript`] is not defined. @@ -101,7 +154,8 @@ The order of evaluation of multiple scripts installed via [`method: BrowserConte ### param: BrowserContext.addInitScript.script * langs: js - `script` <[function]|[string]|[Object]> - - `path` <[path]> Path to the JavaScript file. If `path` is a relative path, then it is resolved relative to the current working directory. Optional. + - `path` <[path]> Path to the JavaScript file. If `path` is a relative path, then it is resolved relative to the + current working directory. Optional. - `content` <[string]> Raw script content. Optional. Script to be evaluated in all pages in the browser context. @@ -132,6 +186,20 @@ await context.grantPermissions(['clipboard-read']); context.clearPermissions(); ``` +```python async +context = await browser.new_context() +await context.grant_permissions(["clipboard-read"]) +# do stuff .. +context.clear_permissions() +``` + +```python sync +context = browser.new_context() +context.grant_permissions(["clipboard-read"]) +# do stuff .. +context.clear_permissions() +``` + ## async method: BrowserContext.close Closes the browser context. All the pages that belong to the browser context will be closed. @@ -162,11 +230,11 @@ Optional list of URLs. ## async method: BrowserContext.exposeBinding The method adds a function called [`param: name`] on the `window` object of every frame in every page in the context. -When called, the function executes [`param: callback`] and returns a [Promise] which resolves to the return -value of [`param: callback`]. If the [`param: callback`] returns a [Promise], it will be awaited. +When called, the function executes [`param: callback`] and returns a [Promise] which resolves to the return value of +[`param: callback`]. If the [`param: callback`] returns a [Promise], it will be awaited. -The first argument of the [`param: callback`] function contains information about the caller: `{ -browserContext: BrowserContext, page: Page, frame: Frame }`. +The first argument of the [`param: callback`] function contains information about the caller: `{ browserContext: +BrowserContext, page: Page, frame: Frame }`. See [`method: Page.exposeBinding`] for page-only version. @@ -193,6 +261,57 @@ const { webkit } = require('playwright'); // Or 'chromium' or 'firefox'. })(); ``` +```python async +import asyncio +from playwright.async_api import async_playwright + +async def run(playwright): + webkit = playwright.webkit + browser = await webkit.launch(headless=false) + context = await browser.new_context() + await context.expose_binding("pageURL", lambda source: source["page"].url) + page = await context.new_page() + await page.set_content(""" + + +
+ """) + await page.click("button") + +async def main(): + async with async_playwright() as playwright: + await run(playwright) +asyncio.run(main()) +``` + +```python sync +from playwright.sync_api import sync_playwright + +def run(playwright): + webkit = playwright.webkit + browser = webkit.launch(headless=false) + context = browser.new_context() + context.expose_binding("pageURL", lambda source: source["page"].url) + page = context.new_page() + page.set_content(""" + + +
+ """) + page.click("button") + +with sync_playwright() as playwright: + run(playwright) +``` + An example of passing an element handle: ```js @@ -208,6 +327,34 @@ await page.setContent(` `); ``` +```python async +async def print(source, element): + print(await element.text_content()) + +await context.expose_binding("clicked", print, handle=true) +await page.set_content(""" + +
Click me
+
Or click me
+""") +``` + +```python sync +def print(source, element): + print(element.text_content()) + +context.expose_binding("clicked", print, handle=true) +page.set_content(""" + +
Click me
+
Or click me
+""") +``` + ### param: BrowserContext.exposeBinding.name - `name` <[string]> @@ -227,8 +374,8 @@ supported. When passing by value, multiple arguments are supported. ## async method: BrowserContext.exposeFunction The method adds a function called [`param: name`] on the `window` object of every frame in every page in the context. -When called, the function executes [`param: callback`] and returns a [Promise] which resolves to the return -value of [`param: callback`]. +When called, the function executes [`param: callback`] and returns a [Promise] which resolves to the return value of +[`param: callback`]. If the [`param: callback`] returns a [Promise], it will be awaited. @@ -258,6 +405,72 @@ const crypto = require('crypto'); })(); ``` +```python async +import asyncio +import hashlib +from playwright.async_api import async_playwright + +async def sha1(text): + m = hashlib.sha1() + m.update(bytes(text, "utf8")) + return m.hexdigest() + + +async def run(playwright): + webkit = playwright.webkit + browser = await webkit.launch(headless=False) + context = await browser.new_context() + await context.expose_function("sha1", sha1) + page = await context.new_page() + await page.set_content(""" + + +
+ """) + await page.click("button") + +async def main(): + async with async_playwright() as playwright: + await run(playwright) +asyncio.run(main()) +``` + +```python sync +import hashlib +from playwright.sync_api import sync_playwright + +def sha1(text): + m = hashlib.sha1() + m.update(bytes(text, "utf8")) + return m.hexdigest() + + +def run(playwright): + webkit = playwright.webkit + browser = webkit.launch(headless=False) + context = browser.new_context() + context.expose_function("sha1", sha1) + page = context.new_page() + page.expose_function("sha1", sha1) + page.set_content(""" + + +
+ """) + page.click("button") + +with sync_playwright() as playwright: + run(playwright) +``` + ### param: BrowserContext.exposeFunction.name - `name` <[string]> @@ -277,22 +490,22 @@ specified. - `permissions` <[Array]<[string]>> A permission or an array of permissions to grant. Permissions can be one of the following values: - * `'geolocation'` - * `'midi'` - * `'midi-sysex'` (system-exclusive midi) - * `'notifications'` - * `'push'` - * `'camera'` - * `'microphone'` - * `'background-sync'` - * `'ambient-light-sensor'` - * `'accelerometer'` - * `'gyroscope'` - * `'magnetometer'` - * `'accessibility-events'` - * `'clipboard-read'` - * `'clipboard-write'` - * `'payment-handler'` +* `'geolocation'` +* `'midi'` +* `'midi-sysex'` (system-exclusive midi) +* `'notifications'` +* `'push'` +* `'camera'` +* `'microphone'` +* `'background-sync'` +* `'ambient-light-sensor'` +* `'accelerometer'` +* `'gyroscope'` +* `'magnetometer'` +* `'accessibility-events'` +* `'clipboard-read'` +* `'clipboard-write'` +* `'payment-handler'` ### option: BrowserContext.grantPermissions.origin - `origin` <[string]> @@ -325,6 +538,22 @@ await page.goto('https://example.com'); await browser.close(); ``` +```python async +context = await browser.new_context() +page = await context.new_page() +await context.route("**/*.{png,jpg,jpeg}", lambda route: route.abort()) +await page.goto("https://example.com") +await browser.close() +``` + +```python sync +context = browser.new_context() +page = context.new_page() +context.route("**/*.{png,jpg,jpeg}", lambda route: route.abort()) +page.goto("https://example.com") +browser.close() +``` + or the same snippet using a regex pattern instead: ```js @@ -335,6 +564,23 @@ await page.goto('https://example.com'); await browser.close(); ``` +```python async +context = await browser.new_context() +page = await context.new_page() +await context.route(r"(\.png$)|(\.jpg$)", lambda page = await context.new_page() +await page.goto("https://example.com") +await browser.close() +``` + +```python sync +context = browser.new_context() +page = context.new_page() +context.route(r"(\.png$)|(\.jpg$)", lambda page = await context.new_page() +page = context.new_page() +page.goto("https://example.com") +browser.close() +``` + Page routes (set up with [`method: Page.route`]) take precedence over browser context routes when request matches both handlers. @@ -377,8 +623,8 @@ Maximum navigation time in milliseconds This setting will change the default maximum time for all the methods accepting [`param: timeout`] option. :::note -[`method: Page.setDefaultNavigationTimeout`], [`method: Page.setDefaultTimeout`] and [`method: -BrowserContext.setDefaultNavigationTimeout`] take priority over [`method: BrowserContext.setDefaultTimeout`]. +[`method: Page.setDefaultNavigationTimeout`], [`method: Page.setDefaultTimeout`] and +[`method: BrowserContext.setDefaultNavigationTimeout`] take priority over [`method: BrowserContext.setDefaultTimeout`]. ::: ### param: BrowserContext.setDefaultTimeout.timeout @@ -409,9 +655,17 @@ Sets the context's geolocation. Passing `null` or `undefined` emulates position await browserContext.setGeolocation({latitude: 59.95, longitude: 30.31667}); ``` +```python async +await browser_context.set_geolocation({"latitude": 59.95, "longitude": 30.31667}) +``` + +```python sync +browser_context.set_geolocation({"latitude": 59.95, "longitude": 30.31667}) +``` + :::note -Consider using [`method: BrowserContext.grantPermissions`] to grant permissions for the browser context -pages to read its geolocation. +Consider using [`method: BrowserContext.grantPermissions`] to grant permissions for the browser context pages to read +its geolocation. ::: ### param: BrowserContext.setGeolocation.geolocation @@ -423,8 +677,7 @@ pages to read its geolocation. ## async method: BrowserContext.setHTTPCredentials * langs: js -**DEPRECATED** Browsers may cache credentials after successful authentication. -Create a new browser context instead. +**DEPRECATED** Browsers may cache credentials after successful authentication. Create a new browser context instead. ### param: BrowserContext.setHTTPCredentials.httpCredentials - `httpCredentials` <[null]|[Object]> @@ -472,8 +725,8 @@ routes for the [`param: url`]. ### param: BrowserContext.unroute.url - `url` <[string]|[RegExp]|[function]\([URL]\):[boolean]> -A glob pattern, regex pattern or predicate receiving [URL] used to register a routing with [`method: -BrowserContext.route`]. +A glob pattern, regex pattern or predicate receiving [URL] used to register a routing with +[`method: BrowserContext.route`]. ### param: BrowserContext.unroute.handler - `handler` <[function]\([Route], [Request]\)> @@ -491,6 +744,16 @@ const context = await browser.newContext(); await context.grantPermissions(['geolocation']); ``` +```python async +context = await browser.new_context() +await context.grant_permissions(["geolocation"]) +``` + +```python sync +context = browser.new_context() +context.grant_permissions(["geolocation"]) +``` + ### param: BrowserContext.waitForEvent.event - `event` <[string]> @@ -500,6 +763,7 @@ Event name, same one would pass into `browserContext.on(event)`. * langs: js - `optionsOrPredicate` <[function]|[Object]> - `predicate` <[function]> receives the event data and resolves to truthy value when the waiting should resolve. - - `timeout` <[float]> maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can be changed by using the [`method: BrowserContext.setDefaultTimeout`]. + - `timeout` <[float]> maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to + disable timeout. The default value can be changed by using the [`method: BrowserContext.setDefaultTimeout`]. -Either a predicate that receives an event or an options object. Optional. +Either a predicate that receives an event or an options object. Optional. \ No newline at end of file diff --git a/docs/src/api/class-browsertype.md b/docs/src/api/class-browsertype.md index 92b7a188e5..49dcd1d25f 100644 --- a/docs/src/api/class-browsertype.md +++ b/docs/src/api/class-browsertype.md @@ -15,6 +15,39 @@ const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'. })(); ``` +```python async +import asyncio +from playwright.async_api import async_playwright + +async def run(playwright): + chromium = playwright.chromium + browser = await chromium.launch() + page = await browser.new_page() + await page.goto("https://example.com") + # other actions... + await browser.close() + +async def main(): + async with async_playwright() as playwright: + await run(playwright) +asyncio.run(main()) +``` + +```python sync +from playwright.sync_api import sync_playwright + +def run(playwright): + chromium = playwright.chromium + browser = chromium.launch() + page = browser.new_page() + page.goto("https://example.com") + # other actions... + browser.close() + +with sync_playwright() as playwright: + run(playwright) +``` + ## async method: BrowserType.connect * langs: js - returns: <[Browser]> @@ -24,9 +57,11 @@ This methods attaches Playwright to an existing browser instance. ### param: BrowserType.connect.params - `params` <[Object]> - `wsEndpoint` <[string]> A browser websocket endpoint to connect to. - - `slowMo` <[float]> Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going on. Defaults to 0. + - `slowMo` <[float]> Slows down Playwright operations by the specified amount of milliseconds. Useful so that you + can see what is going on. Defaults to 0. - `logger` <[Logger]> Logger sink for Playwright logging. Optional. - - `timeout` <[float]> Maximum time in milliseconds to wait for the connection to be established. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. + - `timeout` <[float]> Maximum time in milliseconds to wait for the connection to be established. Defaults to + `30000` (30 seconds). Pass `0` to disable timeout. ## method: BrowserType.executablePath - returns: <[string]> @@ -46,20 +81,32 @@ const browser = await chromium.launch({ // Or 'firefox' or 'webkit'. }); ``` +```python async +browser = await playwright.chromium.launch( # or "firefox" or "webkit". + ignore_default_args=["--mute-audio"] +) +``` + +```python sync +browser = playwright.chromium.launch( # or "firefox" or "webkit". + ignore_default_args=["--mute-audio"] +) +``` + > **Chromium-only** Playwright can also be used to control the Chrome browser, but it works best with the version of Chromium it is bundled with. There is no guarantee it will work with any other version. Use [`option: executablePath`] option with extreme caution. > -> If Google Chrome (rather than Chromium) is preferred, a [Chrome -Canary](https://www.google.com/chrome/browser/canary.html) or [Dev -Channel](https://www.chromium.org/getting-involved/dev-channel) build is suggested. +> If Google Chrome (rather than Chromium) is preferred, a +[Chrome Canary](https://www.google.com/chrome/browser/canary.html) or +[Dev Channel](https://www.chromium.org/getting-involved/dev-channel) build is suggested. > > In [`method: BrowserType.launch`] above, any mention of Chromium also applies to Chrome. > > See [`this article`](https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/) for -a description of the differences between Chromium and Chrome. [`This -article`](https://chromium.googlesource.com/chromium/src/+/lkgr/docs/chromium_browser_vs_google_chrome.md) describes -some differences for Linux users. +a description of the differences between Chromium and Chrome. +[`This article`](https://chromium.googlesource.com/chromium/src/+/lkgr/docs/chromium_browser_vs_google_chrome.md) +describes some differences for Linux users. ### option: BrowserType.launch.headless - `headless` <[boolean]> @@ -90,8 +137,11 @@ array is given, then filters out the given default arguments. Dangerous option; ### option: BrowserType.launch.proxy - `proxy` <[Object]> - - `server` <[string]> Proxy to be used for all requests. HTTP and SOCKS proxies are supported, for example `http://myproxy.com:3128` or `socks5://myproxy.com:3128`. Short form `myproxy.com:3128` is considered an HTTP proxy. - - `bypass` <[string]> Optional coma-separated domains to bypass proxy, for example `".com, chromium.org, .domain.com"`. + - `server` <[string]> Proxy to be used for all requests. HTTP and SOCKS proxies are supported, for example + `http://myproxy.com:3128` or `socks5://myproxy.com:3128`. Short form `myproxy.com:3128` is considered an HTTP + proxy. + - `bypass` <[string]> Optional coma-separated domains to bypass proxy, for example `".com, chromium.org, + .domain.com"`. - `username` <[string]> Optional username to use if HTTP proxy requires authentication. - `password` <[string]> Optional password to use if HTTP proxy requires authentication. @@ -149,8 +199,8 @@ Specify environment variables that will be visible to the browser. Defaults to ` ### option: BrowserType.launch.devtools - `devtools` <[boolean]> -**Chromium-only** Whether to auto-open a Developer Tools panel for each tab. If this option is `true`, the [`option: -headless`] option will be set `false`. +**Chromium-only** Whether to auto-open a Developer Tools panel for each tab. If this option is `true`, the +[`option: headless`] option will be set `false`. ### option: BrowserType.launch.slowMo - `slowMo` <[float]> @@ -201,8 +251,11 @@ arguments. Dangerous option; use with care. Defaults to `false`. ### option: BrowserType.launchPersistentContext.proxy - `proxy` <[Object]> - - `server` <[string]> Proxy to be used for all requests. HTTP and SOCKS proxies are supported, for example `http://myproxy.com:3128` or `socks5://myproxy.com:3128`. Short form `myproxy.com:3128` is considered an HTTP proxy. - - `bypass` <[string]> Optional coma-separated domains to bypass proxy, for example `".com, chromium.org, .domain.com"`. + - `server` <[string]> Proxy to be used for all requests. HTTP and SOCKS proxies are supported, for example + `http://myproxy.com:3128` or `socks5://myproxy.com:3128`. Short form `myproxy.com:3128` is considered an HTTP + proxy. + - `bypass` <[string]> Optional coma-separated domains to bypass proxy, for example `".com, chromium.org, + .domain.com"`. - `username` <[string]> Optional username to use if HTTP proxy requires authentication. - `password` <[string]> Optional password to use if HTTP proxy requires authentication. @@ -248,8 +301,8 @@ Specify environment variables that will be visible to the browser. Defaults to ` ### option: BrowserType.launchPersistentContext.devtools - `devtools` <[boolean]> -**Chromium-only** Whether to auto-open a Developer Tools panel for each tab. If this option is `true`, the [`option: -headless`] option will be set `false`. +**Chromium-only** Whether to auto-open a Developer Tools panel for each tab. If this option is `true`, the +[`option: headless`] option will be set `false`. ### option: BrowserType.launchPersistentContext.slowMo - `slowMo` <[float]> @@ -315,8 +368,11 @@ arguments. Dangerous option; use with care. Defaults to `false`. ### option: BrowserType.launchServer.proxy - `proxy` <[Object]> - - `server` <[string]> Proxy to be used for all requests. HTTP and SOCKS proxies are supported, for example `http://myproxy.com:3128` or `socks5://myproxy.com:3128`. Short form `myproxy.com:3128` is considered an HTTP proxy. - - `bypass` <[string]> Optional coma-separated domains to bypass proxy, for example `".com, chromium.org, .domain.com"`. + - `server` <[string]> Proxy to be used for all requests. HTTP and SOCKS proxies are supported, for example + `http://myproxy.com:3128` or `socks5://myproxy.com:3128`. Short form `myproxy.com:3128` is considered an HTTP + proxy. + - `bypass` <[string]> Optional coma-separated domains to bypass proxy, for example `".com, chromium.org, + .domain.com"`. - `username` <[string]> Optional username to use if HTTP proxy requires authentication. - `password` <[string]> Optional password to use if HTTP proxy requires authentication. @@ -374,8 +430,8 @@ Specify environment variables that will be visible to the browser. Defaults to ` ### option: BrowserType.launchServer.devtools - `devtools` <[boolean]> -**Chromium-only** Whether to auto-open a Developer Tools panel for each tab. If this option is `true`, the [`option: -headless`] option will be set `false`. +**Chromium-only** Whether to auto-open a Developer Tools panel for each tab. If this option is `true`, the +[`option: headless`] option will be set `false`. ## method: BrowserType.name - returns: <[string]> diff --git a/docs/src/api/class-cdpsession.md b/docs/src/api/class-cdpsession.md index f83913398d..658c4f4b07 100644 --- a/docs/src/api/class-cdpsession.md +++ b/docs/src/api/class-cdpsession.md @@ -6,8 +6,10 @@ The `CDPSession` instances are used to talk raw Chrome Devtools Protocol: * protocol events can be subscribed to with `session.on` method. Useful links: -* Documentation on DevTools Protocol can be found here: [DevTools Protocol Viewer](https://chromedevtools.github.io/devtools-protocol/). -* Getting Started with DevTools Protocol: https://github.com/aslushnikov/getting-started-with-cdp/blob/master/README.md +* Documentation on DevTools Protocol can be found here: + [DevTools Protocol Viewer](https://chromedevtools.github.io/devtools-protocol/). +* Getting Started with DevTools Protocol: + https://github.com/aslushnikov/getting-started-with-cdp/blob/master/README.md ```js const client = await page.context().newCDPSession(page); @@ -20,6 +22,28 @@ await client.send('Animation.setPlaybackRate', { }); ``` +```python async +client = await page.context().new_cdp_session(page) +await client.send("animation.enable") +client.on("animation.animation_created", lambda: print("animation created!")) +response = await client.send("animation.get_playback_rate") +print("playback rate is " + response["playback_rate"]) +await client.send("animation.set_playback_rate", { + playback_rate: response["playback_rate"] / 2 +}) +``` + +```python sync +client = page.context().new_cdp_session(page) +client.send("animation.enable") +client.on("animation.animation_created", lambda: print("animation created!")) +response = client.send("animation.get_playback_rate") +print("playback rate is " + response["playback_rate"]) +client.send("animation.set_playback_rate", { + playback_rate: response["playback_rate"] / 2 +}) +``` + ## async method: CDPSession.detach Detaches the CDPSession from the target. Once detached, the CDPSession object won't emit any events and can't be used to diff --git a/docs/src/api/class-chromiumbrowsercontext.md b/docs/src/api/class-chromiumbrowsercontext.md index 6ef33016bc..0f803dc63c 100644 --- a/docs/src/api/class-chromiumbrowsercontext.md +++ b/docs/src/api/class-chromiumbrowsercontext.md @@ -7,6 +7,16 @@ Chromium-specific features including background pages, service worker support, e const backgroundPage = await context.waitForEvent('backgroundpage'); ``` +```python async +# FIXME +background_page = await context.wait_for_event("backgroundpage") +``` + +```python sync +# FIXME +background_page = context.wait_for_event("backgroundpage") +``` + ## event: ChromiumBrowserContext.backgroundpage - type: <[Page]> diff --git a/docs/src/api/class-dialog.md b/docs/src/api/class-dialog.md index f7015a8b95..a2995b70ac 100644 --- a/docs/src/api/class-dialog.md +++ b/docs/src/api/class-dialog.md @@ -1,3 +1,4 @@ + # class: Dialog [Dialog] objects are dispatched by page via the [`event: Page.dialog`] event. @@ -19,6 +20,48 @@ const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'. })(); ``` +```python async +import asyncio +from playwright.async_api import async_playwright + +async def handle_dialog(dialog): + print(dialog.message) + await dialog.dismiss() + +async def run(playwright): + chromium = playwright.chromium + browser = await chromium.launch() + page = await browser.new_page() + page.on("dialog", handle_dialog) + page.evaluate("alert('1')") + await browser.close() + +async def main(): + async with async_playwright() as playwright: + await run(playwright) +asyncio.run(main()) +``` + +```python sync +# FIXME +from playwright.sync_api import sync_playwright + +def handle_dialog(dialog): + print(dialog.message) + await dialog.dismiss() + +def run(playwright): + chromium = playwright.chromium + browser = chromium.launch() + page = browser.new_page() + page.on("dialog", handle_dialog) + page.evaluate("alert('1')") + browser.close() + +with sync_playwright() as playwright: + run(playwright) +``` + ## async method: Dialog.accept Returns when the dialog has been accepted. diff --git a/docs/src/api/class-download.md b/docs/src/api/class-download.md index 758c8476f4..984f769ff3 100644 --- a/docs/src/api/class-download.md +++ b/docs/src/api/class-download.md @@ -14,14 +14,28 @@ const [ download ] = await Promise.all([ ]); // wait for download to complete const path = await download.path(); -... +``` + +```python async +async with page.expect_download() as download_info: + await page.click("a") +download = await download_info.value +# waits for download to complete +path = await download.path() +``` + +```python sync +with page.expect_download() as download_info: + page.click("a") +download = download_info.value +# wait for download to complete +path = download.path() ``` :::note Browser context **must** be created with the [`option: acceptDownloads`] set to `true` when user needs access to the -downloaded content. If [`option: acceptDownloads`] is not set, download events are -emitted, but the actual download is not performed and user has no access to the -downloaded files. +downloaded content. If [`option: acceptDownloads`] is not set, download events are emitted, but the actual download is +not performed and user has no access to the downloaded files. ::: ## async method: Download.createReadStream diff --git a/docs/src/api/class-elementhandle.md b/docs/src/api/class-elementhandle.md index 456746e358..b09555ea5c 100644 --- a/docs/src/api/class-elementhandle.md +++ b/docs/src/api/class-elementhandle.md @@ -16,8 +16,43 @@ const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'. })(); ``` -ElementHandle prevents DOM element from garbage collection unless the handle is disposed with [`method: -JSHandle.dispose`]. ElementHandles are auto-disposed when their origin frame gets navigated. +```python async +import asyncio +from playwright.async_api import async_playwright + +async def run(playwright): + chromium = playwright.chromium + browser = await chromium.launch() + page = await browser.new_page() + await page.goto("https://example.com") + href_element = await page.query_selector("a") + await href_element.click() + # ... + +async def main(): + async with async_playwright() as playwright: + await run(playwright) +asyncio.run(main()) +``` + +```python sync +from playwright.sync_api import sync_playwright + +def run(playwright): + chromium = playwright.chromium + browser = chromium.launch() + page = browser.new_page() + page.goto("https://example.com") + href_element = page.query_selector("a") + href_element.click() + # ... + +with sync_playwright() as playwright: + run(playwright) +``` + +ElementHandle prevents DOM element from garbage collection unless the handle is disposed with +[`method: JSHandle.dispose`]. ElementHandles are auto-disposed when their origin frame gets navigated. ElementHandle instances can be used as an argument in [`method: Page.$eval`] and [`method: Page.evaluate`] methods. @@ -26,8 +61,9 @@ ElementHandle instances can be used as an argument in [`method: Page.$eval`] and - alias-python: query_selector - returns: <[null]|[ElementHandle]> -The method finds an element matching the specified selector in the `ElementHandle`'s subtree. See [Working with -selectors](./selectors.md#working-with-selectors) for more details. If no elements match the selector, returns `null`. +The method finds an element matching the specified selector in the `ElementHandle`'s subtree. See +[Working with selectors](./selectors.md#working-with-selectors) for more details. If no elements match the selector, +returns `null`. ### param: ElementHandle.$.selector = %%-query-selector-%% @@ -36,8 +72,9 @@ selectors](./selectors.md#working-with-selectors) for more details. If no elemen - alias-python: query_selector_all - returns: <[Array]<[ElementHandle]>> -The method finds all elements matching the specified selector in the `ElementHandle`s subtree. See [Working with -selectors](./selectors.md#working-with-selectors) for more details. If no elements match the selector, returns empty array. +The method finds all elements matching the specified selector in the `ElementHandle`s subtree. See +[Working with selectors](./selectors.md#working-with-selectors) for more details. If no elements match the selector, +returns empty array. ### param: ElementHandle.$$.selector = %%-query-selector-%% @@ -49,11 +86,11 @@ selectors](./selectors.md#working-with-selectors) for more details. If no elemen Returns the return value of [`param: pageFunction`] The method finds an element matching the specified selector in the `ElementHandle`s subtree and passes it as a first -argument to [`param: pageFunction`]. See [Working with selectors](./selectors.md#working-with-selectors) for more details. If no -elements match the selector, the method throws an error. +argument to [`param: pageFunction`]. See [Working with selectors](./selectors.md#working-with-selectors) for more +details. If no elements match the selector, the method throws an error. -If [`param: pageFunction`] returns a [Promise], then `frame.$eval` would wait for the promise to resolve and return -its value. +If [`param: pageFunction`] returns a [Promise], then `frame.$eval` would wait for the promise to resolve and return its +value. Examples: @@ -63,6 +100,18 @@ expect(await tweetHandle.$eval('.like', node => node.innerText)).toBe('100'); expect(await tweetHandle.$eval('.retweets', node => node.innerText)).toBe('10'); ``` +```python async +tweet_handle = await page.query_selector(".tweet") +assert await tweet_handle.eval_on_selector(".like", "node => node.innerText") == "100" +assert await tweet_handle.eval_on_selector(".retweets", "node => node.innerText") = "10" +``` + +```python sync +tweet_handle = page.query_selector(".tweet") +assert tweet_handle.eval_on_selector(".like", "node => node.innerText") == "100" +assert tweet_handle.eval_on_selector(".retweets", "node => node.innerText") = "10" +``` + ### param: ElementHandle.$eval.selector = %%-query-selector-%% ### param: ElementHandle.$eval.pageFunction @@ -84,11 +133,11 @@ Optional argument to pass to [`param: pageFunction`] Returns the return value of [`param: pageFunction`] The method finds all elements matching the specified selector in the `ElementHandle`'s subtree and passes an array of -matched elements as a first argument to [`param: pageFunction`]. See [Working with selectors](./selectors.md#working-with-selectors) -for more details. +matched elements as a first argument to [`param: pageFunction`]. See +[Working with selectors](./selectors.md#working-with-selectors) for more details. -If [`param: pageFunction`] returns a [Promise], then `frame.$$eval` would wait for the promise to resolve and return -its value. +If [`param: pageFunction`] returns a [Promise], then `frame.$$eval` would wait for the promise to resolve and return its +value. Examples: @@ -104,6 +153,17 @@ const feedHandle = await page.$('.feed'); expect(await feedHandle.$$eval('.tweet', nodes => nodes.map(n => n.innerText))).toEqual(['Hello!', 'Hi!']); ``` +```python async +# FIXME +feed_handle = await page.query_selector(".feed") +assert await feed_handle.eval_on_selector_all(".tweet", "nodes => nodes.map(n => n.innerText)") == ["hello!", "hi!"] +``` + +```python sync +feed_handle = page.query_selector(".feed") +assert feed_handle.eval_on_selector_all(".tweet", "nodes => nodes.map(n => n.innerText)") == ["hello!", "hi!"] +``` + ### param: ElementHandle.$$eval.selector = %%-query-selector-%% ### param: ElementHandle.$$eval.pageFunction @@ -142,10 +202,21 @@ const box = await elementHandle.boundingBox(); await page.mouse.click(box.x + box.width / 2, box.y + box.height / 2); ``` +```python async +box = await element_handle.bounding_box() +await page.mouse.click(box["x"] + box["width"] / 2, box["y"] + box["height"] / 2) +``` + +```python sync +box = element_handle.bounding_box() +page.mouse.click(box["x"] + box["width"] / 2, box["y"] + box["height"] / 2) +``` + ## async method: ElementHandle.check This method checks the element by performing the following steps: -1. Ensure that element is a checkbox or a radio input. If not, this method rejects. If the element is already checked, this method returns immediately. +1. Ensure that element is a checkbox or a radio input. If not, this method rejects. If the element is already + checked, this method returns immediately. 1. Wait for [actionability](./actionability.md) checks on the element, unless [`option: force`] option is set. 1. Scroll the element into view if needed. 1. Use [`property: Page.mouse`] to click in the center of the element. @@ -203,7 +274,8 @@ This method double clicks the element by performing the following steps: 1. Wait for [actionability](./actionability.md) checks on the element, unless [`option: force`] option is set. 1. Scroll the element into view if needed. 1. Use [`property: Page.mouse`] to double click in the center of the element, or the specified [`option: position`]. -1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set. Note that if the first click of the `dblclick()` triggers a navigation event, this method will reject. +1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set. Note that + if the first click of the `dblclick()` triggers a navigation event, this method will reject. If the element is detached from the DOM at any moment during the action, this method rejects. @@ -238,8 +310,17 @@ is dispatched. This is equivalend to calling await elementHandle.dispatchEvent('click'); ``` -Under the hood, it creates an instance of an event based on the given [`param: type`], initializes it with [`param: -eventInit`] properties and dispatches it on the element. Events are `composed`, `cancelable` and bubble by default. +```python async +await element_handle.dispatch_event("click") +``` + +```python sync +element_handle.dispatch_event("click") +``` + +Under the hood, it creates an instance of an event based on the given [`param: type`], initializes it with +[`param: eventInit`] properties and dispatches it on the element. Events are `composed`, `cancelable` and bubble by +default. Since [`param: eventInit`] is event-specific, please refer to the events documentation for the lists of initial properties: @@ -259,6 +340,18 @@ const dataTransfer = await page.evaluateHandle(() => new DataTransfer()); await elementHandle.dispatchEvent('dragstart', { dataTransfer }); ``` +```python async +# note you can only create data_transfer in chromium and firefox +data_transfer = await page.evaluate_handle("new DataTransfer()") +await element_handle.dispatch_event("#source", "dragstart", {"dataTransfer": data_transfer}) +``` + +```python sync +# note you can only create data_transfer in chromium and firefox +data_transfer = page.evaluate_handle("new DataTransfer()") +element_handle.dispatch_event("#source", "dragstart", {"dataTransfer": data_transfer}) +``` + ### param: ElementHandle.dispatchEvent.type - `type` <[string]> @@ -454,20 +547,49 @@ element, the method throws an error. ```js // single selection matching the value -handle.selectOption('blue'); +handle.selectOption('select#colors', 'blue'); -// single selection matching both the value and the label -handle.selectOption({ label: 'Blue' }); +// single selection matching the label +handle.selectOption('select#colors', { label: 'Blue' }); // multiple selection -handle.selectOption('red', 'green', 'blue'); +handle.selectOption('select#colors', ['red', 'green', 'blue']); +``` -// multiple selection for blue, red and second option -handle.selectOption({ value: 'blue' }, { index: 2 }, 'red'); +```python async +# single selection matching the value +await handle.select_option("select#colors", "blue") +# single selection matching the label +await handle.select_option("select#colors", label="blue") +# multiple selection +await handle.select_option("select#colors", value=["red", "green", "blue"]) +``` + +```python sync +# single selection matching the value +handle.select_option("select#colors", "blue") +# single selection matching both the label +handle.select_option("select#colors", label="blue") +# multiple selection +handle.select_option("select#colors", value=["red", "green", "blue"]) +``` + +```python sync +# FIXME +# single selection matching the value +handle.select_option("blue") +# single selection matching both the value and the label +handle.select_option(label="blue") +# multiple selection +handle.select_option("red", "green", "blue") +# multiple selection for blue, red and second option +handle.select_option(value="blue", { index: 2 }, "red") ``` ### param: ElementHandle.selectOption.values = %%-select-options-values-%% + ### option: ElementHandle.selectOption.noWaitAfter = %%-input-no-wait-after-%% + ### option: ElementHandle.selectOption.timeout = %%-input-timeout-%% ## async method: ElementHandle.selectText @@ -479,8 +601,8 @@ content. ## async method: ElementHandle.setInputFiles -This method expects `elementHandle` to point to an [input -element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input). +This method expects `elementHandle` to point to an +[input element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input). Sets the value of the file input to these file paths or files. If some of the `filePaths` are relative paths, then they are resolved relative to the the current working directory. For empty array, clears the selected files. @@ -534,6 +656,16 @@ await elementHandle.type('Hello'); // Types instantly await elementHandle.type('World', {delay: 100}); // Types slower, like a user ``` +```python async +await element_handle.type("hello") # types instantly +await element_handle.type("world", delay=100) # types slower, like a user +``` + +```python sync +element_handle.type("hello") # types instantly +element_handle.type("world", delay=100) # types slower, like a user +``` + An example of typing into a text field and then submitting the form: ```js @@ -542,6 +674,18 @@ await elementHandle.type('some text'); await elementHandle.press('Enter'); ``` +```python async +element_handle = await page.query_selector("input") +await element_handle.type("some text") +await element_handle.press("Enter") +``` + +```python sync +element_handle = page.query_selector("input") +element_handle.type("some text") +element_handle.press("Enter") +``` + ### param: ElementHandle.type.text - `text` <[string]> @@ -559,7 +703,8 @@ Time to wait between key presses in milliseconds. Defaults to 0. ## async method: ElementHandle.uncheck This method checks the element by performing the following steps: -1. Ensure that element is a checkbox or a radio input. If not, this method rejects. If the element is already unchecked, this method returns immediately. +1. Ensure that element is a checkbox or a radio input. If not, this method rejects. If the element is already + unchecked, this method returns immediately. 1. Wait for [actionability](./actionability.md) checks on the element, unless [`option: force`] option is set. 1. Scroll the element into view if needed. 1. Use [`property: Page.mouse`] to click in the center of the element. @@ -581,11 +726,13 @@ When all steps combined have not finished during the specified [`option: timeout Returns when the element satisfies the [`param: state`]. -Depending on the [`param: state`] parameter, this method waits for one of the [actionability](./actionability.md) -checks to pass. This method throws when the element is detached while waiting, unless waiting for the `"hidden"` state. +Depending on the [`param: state`] parameter, this method waits for one of the [actionability](./actionability.md) checks +to pass. This method throws when the element is detached while waiting, unless waiting for the `"hidden"` state. * `"visible"` Wait until the element is [visible](./actionability.md#visible). -* `"hidden"` Wait until the element is [not visible](./actionability.md#visible) or [not attached](./actionability.md#attached). Note that waiting for hidden does not throw when the element detaches. -* `"stable"` Wait until the element is both [visible](./actionability.md#visible) and [stable](./actionability.md#stable). +* `"hidden"` Wait until the element is [not visible](./actionability.md#visible) or + [not attached](./actionability.md#attached). Note that waiting for hidden does not throw when the element detaches. +* `"stable"` Wait until the element is both [visible](./actionability.md#visible) and + [stable](./actionability.md#stable). * `"enabled"` Wait until the element is [enabled](./actionability.md#enabled). * `"disabled"` Wait until the element is [not enabled](./actionability.md#enabled). * `"editable"` Wait until the element is [editable](./actionability.md#editable). @@ -602,13 +749,13 @@ A state to wait for, see below for more details. ## async method: ElementHandle.waitForSelector - returns: <[null]|[ElementHandle]> -Returns element specified by selector when it satisfies [`option: state`] option. Returns `null` if waiting for `hidden` or -`detached`. +Returns element specified by selector when it satisfies [`option: state`] option. Returns `null` if waiting for `hidden` +or `detached`. Wait for the [`param: selector`] relative to the element handle to satisfy [`option: state`] option (either -appear/disappear from dom, or become visible/hidden). If at the moment of calling the method [`param: selector`] -already satisfies the condition, the method will return immediately. If the selector doesn't satisfy the condition for -the [`option: timeout`] milliseconds, the function will throw. +appear/disappear from dom, or become visible/hidden). If at the moment of calling the method [`param: selector`] already +satisfies the condition, the method will return immediately. If the selector doesn't satisfy the condition for the +[`option: timeout`] milliseconds, the function will throw. ```js await page.setContent(`
`); @@ -617,6 +764,20 @@ const div = await page.$('div'); const span = await div.waitForSelector('span', { state: 'attached' }); ``` +```python async +await page.set_content("
") +div = await page.query_selector("div") +# waiting for the "span" selector relative to the div. +span = await div.wait_for_selector("span", state="attached") +``` + +```python sync +page.set_content("
") +div = page.query_selector("div") +# waiting for the "span" selector relative to the div. +span = div.wait_for_selector("span", state="attached") +``` + :::note This method does not work across navigations, use [`method: Page.waitForSelector`] instead. ::: diff --git a/docs/src/api/class-filechooser.md b/docs/src/api/class-filechooser.md index 4d3bab7347..ccfc8a2b99 100644 --- a/docs/src/api/class-filechooser.md +++ b/docs/src/api/class-filechooser.md @@ -8,6 +8,14 @@ page.on('filechooser', async (fileChooser) => { }); ``` +```python async +page.on("filechooser", lambda file_chooser: file_chooser.set_files("/tmp/myfile.pdf")) +``` + +```python sync +page.on("filechooser", lambda file_chooser: file_chooser.set_files("/tmp/myfile.pdf")) +``` + ## method: FileChooser.element - returns: <[ElementHandle]> diff --git a/docs/src/api/class-frame.md b/docs/src/api/class-frame.md index 0211edfb49..d17894d48b 100644 --- a/docs/src/api/class-frame.md +++ b/docs/src/api/class-frame.md @@ -1,12 +1,14 @@ # class: Frame -At every point of time, page exposes its current frame tree via the [`method: Page.mainFrame`] and [`method: -Frame.childFrames`] methods. +At every point of time, page exposes its current frame tree via the [`method: Page.mainFrame`] and +[`method: Frame.childFrames`] methods. [Frame] object's lifecycle is controlled by three events, dispatched on the page object: -* [`event: Page.frameattached`] - fired when the frame gets attached to the page. A Frame can be attached to the page only once. +* [`event: Page.frameattached`] - fired when the frame gets attached to the page. A Frame can be attached to the page + only once. * [`event: Page.framenavigated`] - fired when the frame commits navigation to a different URL. -* [`event: Page.framedetached`] - fired when the frame gets detached from the page. A Frame can be detached from the page only once. +* [`event: Page.framedetached`] - fired when the frame gets detached from the page. A Frame can be detached from the + page only once. An example of dumping frame tree: @@ -29,12 +31,47 @@ const { firefox } = require('playwright'); // Or 'chromium' or 'webkit'. })(); ``` -An example of getting text from an iframe element: +```python async +import asyncio +from playwright.async_api import async_playwright -```js -const frame = page.frames().find(frame => frame.name() === 'myframe'); -const text = await frame.$eval('.selector', element => element.textContent); -console.log(text); +async def run(playwright): + firefox = playwright.firefox + browser = await firefox.launch() + page = await browser.new_page() + await page.goto("https://www.theverge.com") + dump_frame_tree(page.main_frame, "") + await browser.close() + +def dump_frame_tree(frame, indent): + print(indent + frame.name + '@' + frame.url) + for child in frame.child_frames: + dump_frame_tree(child, indent + " ") + +async def main(): + async with async_playwright() as playwright: + await run(playwright) +asyncio.run(main()) +``` + +```python sync +from playwright.sync_api import sync_playwright + +def run(playwright): + firefox = playwright.firefox + browser = firefox.launch() + page = browser.new_page() + page.goto("https://www.theverge.com") + dump_frame_tree(page.main_frame, "") + browser.close() + +def dump_frame_tree(frame, indent): + print(indent + frame.name + '@' + frame.url) + for child in frame.child_frames: + dump_frame_tree(child, indent + " ") + +with sync_playwright() as playwright: + run(playwright) ``` ## async method: Frame.$ @@ -44,8 +81,9 @@ console.log(text); Returns the ElementHandle pointing to the frame element. -The method finds an element matching the specified selector within the frame. See [Working with -selectors](./selectors.md#working-with-selectors) for more details. If no elements match the selector, returns `null`. +The method finds an element matching the specified selector within the frame. See +[Working with selectors](./selectors.md#working-with-selectors) for more details. If no elements match the selector, +returns `null`. ### param: Frame.$.selector = %%-query-selector-%% @@ -56,8 +94,9 @@ selectors](./selectors.md#working-with-selectors) for more details. If no elemen Returns the ElementHandles pointing to the frame elements. -The method finds all elements matching the specified selector within the frame. See [Working with -selectors](./selectors.md#working-with-selectors) for more details. If no elements match the selector, returns empty array. +The method finds all elements matching the specified selector within the frame. See +[Working with selectors](./selectors.md#working-with-selectors) for more details. If no elements match the selector, +returns empty array. ### param: Frame.$$.selector = %%-query-selector-%% @@ -69,11 +108,11 @@ selectors](./selectors.md#working-with-selectors) for more details. If no elemen Returns the return value of [`param: pageFunction`] The method finds an element matching the specified selector within the frame and passes it as a first argument to -[`param: pageFunction`]. See [Working with selectors](./selectors.md#working-with-selectors) for more details. If no elements match -the selector, the method throws an error. +[`param: pageFunction`]. See [Working with selectors](./selectors.md#working-with-selectors) for more details. If no +elements match the selector, the method throws an error. -If [`param: pageFunction`] returns a [Promise], then `frame.$eval` would wait for the promise to resolve and return -its value. +If [`param: pageFunction`] returns a [Promise], then `frame.$eval` would wait for the promise to resolve and return its +value. Examples: @@ -83,6 +122,18 @@ const preloadHref = await frame.$eval('link[rel=preload]', el => el.href); const html = await frame.$eval('.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") +html = await frame.eval_on_selector(".main-container", "(e, suffix) => e.outerHTML + suffix", "hello") +``` + +```python sync +search_value = frame.eval_on_selector("#search", "el => el.value") +preload_href = frame.eval_on_selector("link[rel=preload]", "el => el.href") +html = frame.eval_on_selector(".main-container", "(e, suffix) => e.outerHTML + suffix", "hello") +``` + ### param: Frame.$eval.selector = %%-query-selector-%% ### param: Frame.$eval.pageFunction @@ -104,11 +155,11 @@ Optional argument to pass to [`param: pageFunction`] Returns the return value of [`param: pageFunction`] The method finds all elements matching the specified selector within the frame and passes an array of matched elements -as a first argument to [`param: pageFunction`]. See [Working with selectors](./selectors.md#working-with-selectors) for more -details. +as a first argument to [`param: pageFunction`]. See [Working with selectors](./selectors.md#working-with-selectors) for +more details. -If [`param: pageFunction`] returns a [Promise], then `frame.$$eval` would wait for the promise to resolve and return -its value. +If [`param: pageFunction`] returns a [Promise], then `frame.$$eval` would wait for the promise to resolve and return its +value. Examples: @@ -116,6 +167,14 @@ Examples: const divsCounts = await frame.$$eval('div', (divs, min) => divs.length >= min, 10); ``` +```python async +divs_counts = await frame.eval_on_selector_all("div", "(divs, min) => divs.length >= min", 10) +``` + +```python sync +divs_counts = frame.eval_on_selector_all("div", "(divs, min) => divs.length >= min", 10) +``` + ### param: Frame.$$eval.selector = %%-query-selector-%% ### param: Frame.$$eval.pageFunction @@ -144,7 +203,8 @@ URL of a script to be added. ### option: Frame.addScriptTag.path - `path` <[path]> -Path to the JavaScript file to be injected into frame. If `path` is a relative path, then it is resolved relative to the current working directory. +Path to the JavaScript file to be injected into frame. If `path` is a relative path, then it is resolved relative to the +current working directory. ### option: Frame.addScriptTag.content - `content` <[string]> @@ -154,7 +214,8 @@ Raw JavaScript content to be injected into frame. ### option: Frame.addScriptTag.type - `type` <[string]> -Script type. Use 'module' in order to load a Javascript ES6 module. See [script](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script) for more details. +Script type. Use 'module' in order to load a Javascript ES6 module. See +[script](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script) for more details. ## async method: Frame.addStyleTag - returns: <[ElementHandle]> @@ -172,7 +233,8 @@ URL of the `` tag. ### option: Frame.addStyleTag.path - `path` <[path]> -Path to the CSS file to be injected into frame. If `path` is a relative path, then it is resolved relative to the current working directory. +Path to the CSS file to be injected into frame. If `path` is a relative path, then it is resolved relative to the +current working directory. ### option: Frame.addStyleTag.content - `content` <[string]> @@ -182,9 +244,12 @@ Raw CSS content to be injected into frame. ## async method: Frame.check This method checks an element matching [`param: selector`] by performing the following steps: -1. Find an element match matching [`param: selector`]. If there is none, wait until a matching element is attached to the DOM. -1. Ensure that matched element is a checkbox or a radio input. If not, this method rejects. If the element is already checked, this method returns immediately. -1. Wait for [actionability](./actionability.md) checks on the matched element, unless [`option: force`] option is set. If the element is detached during the checks, the whole action is retried. +1. Find an element match matching [`param: selector`]. If there is none, wait until a matching element is attached to + the DOM. +1. Ensure that matched element is a checkbox or a radio input. If not, this method rejects. If the element is already + checked, this method returns immediately. +1. Wait for [actionability](./actionability.md) checks on the matched element, unless [`option: force`] option is + set. If the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use [`property: Page.mouse`] to click in the center of the element. 1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set. @@ -207,8 +272,10 @@ When all steps combined have not finished during the specified [`option: timeout ## async method: Frame.click This method clicks an element matching [`param: selector`] by performing the following steps: -1. Find an element match matching [`param: selector`]. If there is none, wait until a matching element is attached to the DOM. -1. Wait for [actionability](./actionability.md) checks on the matched element, unless [`option: force`] option is set. If the element is detached during the checks, the whole action is retried. +1. Find an element match matching [`param: selector`]. If there is none, wait until a matching element is attached to + the DOM. +1. Wait for [actionability](./actionability.md) checks on the matched element, unless [`option: force`] option is + set. If the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use [`property: Page.mouse`] to click in the center of the element, or the specified [`option: position`]. 1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set. @@ -242,11 +309,14 @@ Gets the full HTML contents of the frame, including the doctype. ## async method: Frame.dblclick This method double clicks an element matching [`param: selector`] by performing the following steps: -1. Find an element match matching [`param: selector`]. If there is none, wait until a matching element is attached to the DOM. -1. Wait for [actionability](./actionability.md) checks on the matched element, unless [`option: force`] option is set. If the element is detached during the checks, the whole action is retried. +1. Find an element match matching [`param: selector`]. If there is none, wait until a matching element is attached to + the DOM. +1. Wait for [actionability](./actionability.md) checks on the matched element, unless [`option: force`] option is + set. If the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use [`property: Page.mouse`] to double click in the center of the element, or the specified [`option: position`]. -1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set. Note that if the first click of the `dblclick()` triggers a navigation event, this method will reject. +1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set. Note that + if the first click of the `dblclick()` triggers a navigation event, this method will reject. When all steps combined have not finished during the specified [`option: timeout`], this method rejects with a [TimeoutError]. Passing zero timeout disables this. @@ -281,8 +351,17 @@ is dispatched. This is equivalend to calling await frame.dispatchEvent('button#submit', 'click'); ``` -Under the hood, it creates an instance of an event based on the given [`param: type`], initializes it with [`param: -eventInit`] properties and dispatches it on the element. Events are `composed`, `cancelable` and bubble by default. +```python async +await frame.dispatch_event("button#submit", "click") +``` + +```python sync +frame.dispatch_event("button#submit", "click") +``` + +Under the hood, it creates an instance of an event based on the given [`param: type`], initializes it with +[`param: eventInit`] properties and dispatches it on the element. Events are `composed`, `cancelable` and bubble by +default. Since [`param: eventInit`] is event-specific, please refer to the events documentation for the lists of initial properties: @@ -302,6 +381,19 @@ const dataTransfer = await frame.evaluateHandle(() => new DataTransfer()); await frame.dispatchEvent('#source', 'dragstart', { dataTransfer }); ``` +```python async +# note you can only create data_transfer in chromium and firefox +data_transfer = await frame.evaluate_handle("new DataTransfer()") +await frame.dispatch_event("#source", "dragstart", { "dataTransfer": data_transfer }) +``` + +```python sync +# note you can only create data_transfer in chromium and firefox +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 @@ -321,10 +413,10 @@ Optional event-specific initialization properties. Returns the return value of [`param: pageFunction`] -If the function passed to the `frame.evaluate` returns a [Promise], then `frame.evaluate` would wait for the promise to +If the function passed to the [`method: Frame.evaluate`] returns a [Promise], then [`method: Frame.evaluate`] would wait for the promise to resolve and return its value. -If the function passed to the `frame.evaluate` returns a non-[Serializable] value, then `frame.evaluate` returns +If the function passed to the [`method: Frame.evaluate`] returns a non-[Serializable] value, then[ method: `Frame.evaluate`] returns `undefined`. DevTools Protocol also supports transferring some additional values that are not serializable by `JSON`: `-0`, `NaN`, `Infinity`, `-Infinity`, and bigint literals. @@ -335,13 +427,37 @@ const result = await frame.evaluate(([x, y]) => { console.log(result); // prints "56" ``` +```python async +result = await frame.evaluate("([x, y]) => Promise.resolve(x * y)", [7, 8]) +print(result) # prints "56" +``` + +```python sync +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" ``` -[ElementHandle] instances can be passed as an argument to the `frame.evaluate`: +```python async +print(await frame.evaluate("1 + 2")) # prints "3" +x = 10 +print(await frame.evaluate(f"1 + {x}")) # prints "11" +``` + +```python sync +print(frame.evaluate("1 + 2")) # prints "3" +x = 10 +print(frame.evaluate(f"1 + {x}")) # prints "11" +``` + + +[ElementHandle] instances can be passed as an argument to the [`method: Frame.evaluate`]: ```js const bodyHandle = await frame.$('body'); @@ -349,6 +465,18 @@ const html = await frame.evaluate(([body, suffix]) => body.innerHTML + suffix, [ await bodyHandle.dispose(); ``` +```python async +body_handle = await frame.query_selector("body") +html = await frame.evaluate("([body, suffix]) => body.innerHTML + suffix", [body_handle, "hello"]) +await body_handle.dispose() +``` + +```python sync +body_handle = frame.query_selector("body") +html = frame.evaluate("([body, suffix]) => body.innerHTML + suffix", [body_handle, "hello"]) +body_handle.dispose() +``` + ### param: Frame.evaluate.pageFunction * langs: js - `pageFunction` <[function]|[string]> @@ -365,10 +493,10 @@ Optional argument to pass to [`param: pageFunction`] Returns the return value of [`param: pageFunction`] as in-page object (JSHandle). -The only difference between `frame.evaluate` and `frame.evaluateHandle` is that `frame.evaluateHandle` returns in-page +The only difference between [`method: Frame.evaluate`] and [`method: Frame.evaluateHandle`] is that[ method: Fframe.evaluateHandle`] returns in-page object (JSHandle). -If the function, passed to the `frame.evaluateHandle`, returns a [Promise], then `frame.evaluateHandle` would wait for +If the function, passed to the [`method: Frame.evaluateHandle`], returns a [Promise], then[ method: Fframe.evaluateHandle`] would wait for the promise to resolve and return its value. ```js @@ -376,13 +504,32 @@ const aWindowHandle = await frame.evaluateHandle(() => Promise.resolve(window)); aWindowHandle; // Handle for the window object. ``` +```python async +# FIXME +a_window_handle = await frame.evaluate_handle("Promise.resolve(window)") +a_window_handle # handle for the window object. +``` + +```python sync +a_window_handle = frame.evaluate_handle("Promise.resolve(window)") +a_window_handle # handle for the window object. +``` + A string can also be passed in instead of a function. ```js const aHandle = await frame.evaluateHandle('document'); // Handle for the 'document'. ``` -[JSHandle] instances can be passed as an argument to the `frame.evaluateHandle`: +```python async +a_handle = await page.evaluate_handle("document") # handle for the "document" +``` + +```python sync +a_handle = page.evaluate_handle("document") # handle for the "document" +``` + +[JSHandle] instances can be passed as an argument to the [`method: Frame.evaluateHandle`]: ```js const aHandle = await frame.evaluateHandle(() => document.body); @@ -391,6 +538,20 @@ console.log(await resultHandle.jsonValue()); await resultHandle.dispose(); ``` +```python async +a_handle = await page.evaluate_handle("document.body") +result_handle = await page.evaluate_handle("body => body.innerHTML", a_handle) +print(await result_handle.json_value()) +await result_handle.dispose() +``` + +```python sync +a_handle = page.evaluate_handle("document.body") +result_handle = page.evaluate_handle("body => body.innerHTML", a_handle) +print(result_handle.json_value()) +result_handle.dispose() +``` + ### param: Frame.evaluateHandle.pageFunction * langs: js - `pageFunction` <[function]|[string]> @@ -424,8 +585,8 @@ Value to fill for the ``, `