Skip to contents

rplaywright is an R package developed as part of my participation in the rOpenSci Champions Program. It is designed to seamlessly bridge with the NodeJS library, Playwright, enabling simplified web testing and automation for R users. This package aims to provide R users with a comprehensive toolkit for interacting with web browsers programmatically, allowing for tasks such as browser automation, web scraping, and end-to-end testing directly from within the R environment. rplaywright offers a user-friendly interface and robust functionality for handling complex web interactions, making it an invaluable tool for both beginners and experienced developers alike.

Installation

You can install the development version of rplaywright from GitHub with:

devtools::install_github("erikaris/rplaywright")
rplaywright::install_rplaywright(force = TRUE)

Browser

Launch new browser instance

chrome <- rplaywright::new_chromium()
firefox <- rplaywright::new_firefox()
webkit <- rplaywright::new_webkit()

Browser Context

BrowserContexts provide a way to operate multiple independent browser sessions.

context <- chrome$new_context()$then()

Page

Page provides methods to interact with a single tab in a Browser, or an extension background page in Chromium. One Browser instance might have multiple Page instances.

page <- context$new_page()$then()
add_init_script

Adds a script which would be evaluated in one of the following scenarios:

  • Whenever the page is navigated.
  • Whenever the child frame is attached or navigated. 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.

// examples/preload.js
Math.random = () => 42;
page$add_init_script(list(path=normalizePath("./examples/preload.js")))
page$goto("https://playwright.dev/")$then()
result_from_preload <- page$evaluate("() => Math.random()")$then()
add_locator_handler

When testing a web page, sometimes unexpected overlays like a “Sign up” dialog appear and block actions you want to automate, e.g. clicking a button. These overlays don’t always show up in the same way or at the same time, making them tricky to handle in automated tests.

This method lets you set up a special function, called a handler, that activates when it detects that overlay is visible. The handler’s job is to remove the overlay, allowing your test to continue as if the overlay wasn’t there.

Things to keep in mind:

  • When an overlay is shown predictably, we recommend explicitly waiting for it in your test and dismissing it as a part of your normal test flow, instead of using page.addLocatorHandler().
  • Playwright checks for the overlay every time before executing or retrying an action that requires an actionability check, or before performing an auto-waiting assertion check. When overlay is visible, Playwright calls the handler first, and then proceeds with the action/assertion. Note that the handler is only called when you perform an action/assertion - if the overlay becomes visible but you don’t perform any actions, the handler will not be triggered.
  • After executing the handler, Playwright will ensure that overlay that triggered the handler is not visible anymore. You can opt-out of this behavior with noWaitAfter.
  • The execution time of the handler counts towards the timeout of the action/assertion that executed the handler. If your handler takes too long, it might cause timeouts.
  • You can register multiple handlers. However, only a single handler will be running at a time. Make sure the actions within a handler don’t depend on another handler.
page$add_locator_handler()
page$goto("https://playwright.dev/")$then()
add_script_tag

Returns the main resource response. In case of multiple redirects, the navigation will resolve with the first non-redirect response.

page$goto("https://playwright.dev/")$then()
page$add_script_tag(list(path=normalizePath("./examples/preload.js")))$then()
page$add_script_tag(list(content="const greet = () => console.log('hello')"))$then()
add_style_tag

Adds a <link rel="stylesheet"> tag into the page with the desired url or a <style type="text/css"> tag with the content. Returns the added tag when the stylesheet’s onload fires or when the CSS content was injected into frame.

page$goto("https://playwright.dev/")$then()
page$add_style_tag(list(path=normalizePath("./examples/style.css")))$then()
page$add_style_tag(list(content=
  ".highlight_gXVj {
    color: red;
  }"))$then()
bring_to_front

Brings page to front (activates tab).

page2 <- context$new_page()$then()
page2$goto("https://demo.playwright.dev/todomvc/#/")$then()
page$bring_to_front()$then()
close

If runBeforeUnload is false, does not run any unload handlers and waits for the page to be closed. If runBeforeUnload is true the method will run unload handlers, but will not wait for the page to close.

By default, page.close() does not run beforeunload handlers.

page2$close()
content

Gets the full HTML contents of the page, including the doctype.

content <- page$content()$then()
context

Get the browser context that the page belongs to.

page_context <- page$context()
drag_and_drop

This method drags the source element to the target element. It will first move to the source element, perform a mousedown, then move to the target element and perform a mouseup.

page$drag_and_drop("#source", "#target")$then()
emulate_media

This method changes the CSS media type through the media argument, and/or the ‘prefers-colors-scheme’ media feature, using the colorScheme argument.

page$emulate_media(list(media="print"))$then()
page$evaluate("() => matchMedia('screen').matches")$then()
page$evaluate("() => matchMedia('print').matches")$then()
evaluate

Returns the value of the pageFunction invocation.

If the function passed to the page.evaluate() returns a Promise, then page.evaluate() would wait for the promise to resolve and return its value.

If the function passed to the page.evaluate() returns a non-Serializable value, then page.evaluate() resolves to undefined. Playwright also supports transferring some additional values that are not serializable by JSON: -0, NaN, Infinity, -Infinity.

page$emulate_media(list(media="print"))$then()
page$evaluate("() => matchMedia('screen').matches")$then()
page$evaluate("() => matchMedia('print').matches")$then()
page$evaluate(
  "([x, y]) => {
    return Promise.resolve(x * y);
  }",
  c(7, 8)
)$then()
page$evaluate(
  "({ x, y }) => {
    return Promise.resolve(x * y);
  }",
  list(x=7, y=10)
)$then()
evaluate_handle

Returns the value of the pageFunction invocation as a JSHandle.

The only difference between page.evaluate() and page.evaluateHandle() is that page.evaluateHandle() returns JSHandle.

If the function passed to the page.evaluateHandle() returns a Promise, then page.evaluateHandle() would wait for the promise to resolve and return its value.

page$evaluate_handle()
expose_binding

The method adds a function called name on the window object of every frame in this page. When called, the function executes callback and returns a Promise which resolves to the return value of callback. If the callback returns a Promise, it will be awaited.

The first argument of the callback function contains information about the caller: { browserContext: BrowserContext, page: Page, frame: Frame }.

page$expose_binding("pageURL", "({ page }) => page.url()")
page$set_content("
  <script>
      async function onClick() {
        document.querySelector('div').textContent = await window.pageURL();
      }
  </script>
  <button onclick='onClick()'>Click me</button>
  <div></div>"
)$then()
page$get_by_role("button")$click("button")$then()
expose_function

The method adds a function called name on the window object of every frame in the page. When called, the function executes callback and returns a Promise which resolves to the return value of callback.

If the callback returns a Promise, it will be awaited.

page$expose_function("base64", "(text) => btoa(text)")
page$set_content("
  <script>
      async function onClick() {
        document.querySelector('div').textContent = await base64('PLAYWRIGHT');
      }
  </script>
  <button onclick='onClick()'>Click me</button>
  <div></div>"
)$then()
page$get_by_role("button")$click("button")$then()
frame

Returns frame matching the specified criteria. Either name or url must be specified.

page$goto("https://playwright.dev/")$then()
frame <- page$frame("main")
frame_locator

When working with iframes, you can create a frame locator that will enter the iframe and allow selecting elements in that iframe.

page$set_content(
  "<iframe id='myframe'>
    <button>Button</button>
  </iframe>"
)
myframe <- page$frame_locator("#myframe")
frames

An array of all frames attached to the page.

page$set_content(
  "<iframe id='myframe'>
    <button>Button</button>
  </iframe>"
)
frames <- page$frames()
get_by_alt_text

Allows locating elements by their alt text.

page_2 <- context$new_page()$then()
page_2$set_content("<img alt='Playwright logo'>")
page_2$get_by_alt_text("link")$click(list(timeout=100))$then()
get_by_label

Allows locating input elements by the text of the associated

page_2 <- context$new_page()$then()
page_2$set_content('<input aria-label="Username"></input>
  <label for="password-input">Password:</label>
  <input id="password-input"></input>')
page_2$get_by_label("Username")$fill("John", list(timeout=100))$then()
get_by_placeholder

Allows locating input elements by the placeholder text.

page_2 <- context$new_page()$then()
page_2$set_content('<input type="email" placeholder="name@example.com"></input>')
page_2$get_by_placeholder("name@example.com")$fill("playwright@microsoft.com", list(timeout=100))$then()
get_by_role

Allows locating elements by their ARIA role, ARIA attributes and accessible name.

page_2 <- context$new_page()$then()
page_2$set_content('<h3>Sign up</h3>
  <label>
    <input type="checkbox"></input> Subscribe
  </label>
  <br/>
  <button>Submit</button>')
page_2$get_by_role("checkbox", list(name="Subscribe"))$check(list(timeout=100))$then()
get_by_test_id

Locate element by the test id.

page_2 <- context$new_page()$then()
page_2$set_content('<button data-testid="directions">Itinéraire</button>')
page_2$get_by_test_id("directions")$click(list(timeout=100))$then()
get_by_text

Allows locating elements that contain given text.

See also locator.filter() that allows to match by another criteria, like an accessible role, and then filter by the text content.

page_2 <- context$new_page()$then()
page_2$set_content('<div>Hello <span>world</span></div>
  <div>Hello</div>')
page_2$get_by_text("Hello", list(exact=FALSE))$click(list(timeout=100))$then()
get_by_title

Allows locating elements by their title attribute.

page_2 <- context$new_page()$then()
page_2$set_content("<span title='Issues count'>25 issues</span>")
get_by_title <- page_2$get_by_title("Issues count")$text_content()$then()
go_back

Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of the last redirect. If cannot go back, returns null.

Navigate to the previous page in history.

page$goto("https://playwright.dev/docs/api/class-page#page-get-by-title")
page$goto("https://playwright.dev/docs/api/class-page#page-go-back")
page$go_back()$then()
go_forward

Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of the last redirect. If cannot go forward, returns null.

Navigate to the next page in history.

page$goto("https://playwright.dev/docs/api/class-page#page-get-by-title")
page$goto("https://playwright.dev/docs/api/class-page#page-go-back")
page$go_back()$then()
page$go_forward()$then()
goto

Returns the main resource response. In case of multiple redirects, the navigation will resolve with the first non-redirect response.

resp <- page$goto("https://playwright.dev/")$then()
resp$status()
is_closed

Indicates that the page has been closed.

page2 <- context$new_page()$then()
page2$goto("https://playwright.dev/")$then()
page2$close()$then()
is_closed <- page2$is_closed()
locator

The method finds an element matching the specified selector in the locator’s subtree. It also accepts filter options, similar to locator.filter() method.

page_2 <- context$new_page()$then()
page_2$set_content('<button data-testid="directions">Itinéraire</button>')
locator_inner_text <- page_2$locator('[data-testid="directions"]')$inner_text(list(timeout=100))$then()
main_frame

The page’s main frame. Page is guaranteed to have a main frame which persists during navigations.

page2 <- context$new_page()$then()
page2$goto("https://playwright.dev/")$then()
main_frame <- page2$main_frame()
opener

Returns the opener for popup pages and null for others. If the opener has been closed already the returns null.

page2 <- context$new_page()$then()
page2$goto("https://playwright.dev/")$then()
opener <- page2$opener()$then()
pause

Pauses script execution. Playwright will stop executing the script and wait for the user to either press ‘Resume’ button in the page overlay or to call playwright.resume() in the DevTools console.

User can inspect selectors or perform manual steps while paused. Resume will continue running the original script from the place it was paused.

page2 <- context$new_page()$then()
page2$goto("https://playwright.dev/")$then()
page2$pause()$then()
pdf

Returns the PDF buffer.

page2 <- context$new_page()$then()
page2$goto("https://playwright.dev/")$then()
page2$emulate_media(list(media="screen"))$then()
pdf <- page2$pdf()$then()
reload

This method reloads the current page, in the same way as if the user had triggered a browser refresh. Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of the last redirect.

page2 <- context$new_page()$then()
page2$goto("https://playwright.dev/")$then()
page2$reload()$then()$status()
remove_locator_handler

Removes all locator handlers added by page.addLocatorHandler() for a specific locator.

page$remove_locator_handler()
page$goto("https://playwright.dev/")$then()
route

Routing provides the capability to modify network requests that are made by a page.

Once routing is enabled, every request matching the url pattern will stall unless it’s continued, fulfilled or aborted.

page$route("**/*.{png,jpg,jpeg}", "route => route.abort()")$then()
page$goto("https://playwright.dev/")$then()
route_from_h_a_r

If specified the network requests that are made in the page will be served from the HAR file. Read more about Replaying from HAR.

Playwright will not serve requests intercepted by Service Worker from the HAR file. See this issue. We recommend disabling Service Workers when using request interception by setting Browser.newContext.serviceWorkers to ‘block’.

page$route_from_h_a_r("/path/to/har")
page$goto("https://playwright.dev/")$then()
screenshot

Returns the buffer with the captured screenshot.

page$goto("https://playwright.dev/")$then()
page_screenshot <- page$screenshot()$then()
set_content

This method internally calls document.write(), inheriting all its specific characteristics and behaviors.

page$set_content('<button data-testid="directions">Itinéraire</button>')$then()
set_default_navigation_timeout

This setting will change the default maximum navigation time for the following methods and related shortcuts:

page.goBack() page.goForward() page.goto() page.reload() page.setContent() page.waitForNavigation() page.waitForURL()

page$set_default_navigation_timeout(100)
set_default_timeout

This setting will change the default maximum time for all the methods accepting timeout option.

page$set_default_timeout(100)
set_extra_h_t_t_p_headers

The extra HTTP headers will be sent with every request the page initiates.

page$set_extra_h_t_t_p_headers(list("setCookies", "token=token"))$then()
page$set_content('<button data-testid="directions">Itinéraire</button>')$then()
set_viewport_size

In the case of multiple pages in a single browser, each page can have its own viewport size. However, browser.newContext() allows to set viewport size (and more) for all pages in the context at once.

page.setViewportSize() will resize the page. A lot of websites don’t expect phones to change size, so you should set the viewport size before navigating to the page. page.setViewportSize() will also reset screen size, use browser.newContext() with screen and viewport parameters if you need better control of these properties.

page$set_viewport_size(list(width=800, height=600))$then()
page$goto("https://playwright.dev/")$then()
title

Returns the page’s title.

page$goto("https://playwright.dev/")$then()
title <- page$title()$then()
unroute

Removes a route created with page.route(). When handler is not specified, removes all routes for the url.

page$unroute("**/*.{png,jpg,jpeg}", "route => route.abort()")$then()
page$goto("https://playwright.dev/")$then()
unroute_all

Removes all routes created with page.route() and page.routeFromHAR().

page$unroute_all()$then()
page$goto("https://playwright.dev/")$then()
url
page$goto("https://playwright.dev/")$then()
url <- page$url()
video

Video object associated with this page.

page$goto("https://playwright.dev/")$then()
video <- page$video()
viewport_size
page$goto("https://playwright.dev/")$then()
viewport_size <- page$viewport_size()
wait_for_event

Waits for event to fire and passes its value into the predicate function. Returns when the predicate returns truthy value. Will throw an error if the page is closed before the event is fired. Returns the event data value.

ev_promise <- page$wait_for_event("load")
page$goto("https://playwright.dev/")$then()
ev <- ev_promise$then()
wait_for_function

Returns when the pageFunction returns a truthy value. It resolves to a JSHandle of the truthy value.

fn_promise <- page$wait_for_function("() => window.innerWidth < 100")
page$set_viewport_size(list(width=50, height=50))$then()
js <- fn_promise$then()
wait_for_load_state

Returns when the required load state has been reached.

This resolves when the page reaches a required load state, load by default. The navigation must have been committed when this method is called. If current document has already reached the required state, resolves immediately.

ev_promise <- page$wait_for_load_state("load")
page$goto("https://playwright.dev/")$then()
ev <- ev_promise$then()
wait_for_request

Waits for the matching request and returns it. See waiting for event for more details about events.

req_promise <- page$wait_for_request("(req) => req.url().includes('playwright.dev')")
page$goto("https://playwright.dev/")$then()
req <- req_promise$then()
wait_for_response

Returns the matched response. See waiting for event for more details about events.

resp_promise <- page$wait_for_response("(resp) => resp.url().includes('playwright.dev')")
page$goto("https://playwright.dev/")$then()
resp <- resp_promise$then()
wait_for_u_r_l

Waits for the main frame to navigate to the given URL.

resp_promise <- page$wait_for_u_r_l("https://playwright.dev/")
page$goto("https://playwright.dev/")$then()
resp_promise$then()
workers

This method returns all of the dedicated WebWorkers associated with the page.

page$goto("https://playwright.dev/")$then()
workers <- page$workers()

Locator

Locators are the central piece of Playwright’s auto-waiting and retry-ability. In a nutshell, locators represent a way to find element(s) on the page at any moment.

all

When the locator points to a list of elements, this returns an array of locators, pointing to their respective elements.

all_links <- page$get_by_role("link")$all()$then()
all_inner_texts

Returns an array of node.innerText values for all matching nodes.

all_inner_texts <- page$get_by_role("link")$all_inner_texts()$then()
all_text_contents

Returns an array of node.textContent values for all matching nodes.

all_text_contents <- page$get_by_role("link")$all_text_contents()$then()
and

Creates a locator that matches both this locator and the argument locator.

and_unimplemented <- page$get_by_role("link")$and()
blur

Calls blur on the element.

page$get_by_role("link", list(name="Get started"))$blur()$then()
bounding_box

This method returns the bounding box of the element matching the locator, or null if the element is not visible. The bounding box is calculated relative to the main frame viewport - which is usually the same as the browser window.

bounding_box <- page$get_by_role("link", list(name="Get started"))$bounding_box()$then()
check

Ensure that checkbox or radio element is checked.

page$get_by_role("checkbox")$check(list(timeout=100))$then()
clear

Clear the input field.

page$get_by_role("textbox")$clear(list(timeout=100))$then()
click

Click an element.

page$get_by_role("link", list(name="Get started"))$click(list(timeout=100))$then()
content_frame

Returns a FrameLocator object pointing to the same iframe as this locator.

Useful when you have a Locator object obtained somewhere, and later on would like to interact with the content inside the frame.

For a reverse operation, use frameLocator.owner().

content_frame_unimplemented <- page$get_by_role("link")$content_frame()
count

Returns the number of elements matching the locator.

count <- page$get_by_role("link")$count()$then()
dblclick

Double-click an element.

page$get_by_role("link", list(name="Get started"))$dblclick(list(timeout=100))$then()
dispatch_event

Programmatically dispatch an event on the matching element.

page$get_by_role("link", list(name="Get started"))$dispatch_event('click', NULL, list(timeout=100))$then()
drag_to

Drag the source element towards the target element and drop it.

drag_to_unimplemented <- page$get_by_role("link")$drag_to()
evaluate

Execute JavaScript code in the page, taking the matching element as an argument.

evaluate_unimplemented <- page$get_by_role("link")$evaluate()
evaluate_all

Execute JavaScript code in the page, taking all matching elements as an argument.

evaluate_all_unimplemented <- page$get_by_role("link")$evaluate_all()
evaluate_handle

Execute JavaScript code in the page, taking the matching element as an argument, and return a JSHandle with the result.

evaluate_handle_unimplemented <- page$get_by_role("link")$evaluate_handle()
fill

Set a value to the input field.

page$get_by_role("textbox")$fill("example value", list(timeout=100))$then()
filter

This method narrows existing locator according to the options, for example filters by text. It can be chained to filter multiple times.

filter_unimplemented <- page$get_by_role("link")$filter()
first

Returns locator to the first matching element.

first <- page$get_by_role("link")$first()
focus

Calls focus on the matching element.

page$get_by_role("link")$first()$focus()$then()
frame_locator

When working with iframes, you can create a frame locator that will enter the iframe and allow locating elements in that iframe:

frame_locator_unimplemented <- page$get_by_role("link")$frame_locator()
get_attribute

Returns the matching element’s attribute value.

attribute <- page$get_by_role("link")$first()$get_attribute("title")$then()
get_by_alt_text

Allows locating elements by their alt text.

page_2 <- context$new_page()$then()
page_2$set_content("<img alt='Playwright logo'>")
page_2$get_by_alt_text("link")$click(list(timeout=100))$then()
get_by_label

Allows locating input elements by the text of the associated

page_2 <- context$new_page()$then()
page_2$set_content('<input aria-label="Username"></input>
  <label for="password-input">Password:</label>
  <input id="password-input"></input>')
page_2$get_by_label("Username")$fill("John", list(timeout=100))$then()
get_by_placeholder

Allows locating input elements by the placeholder text.

page_2 <- context$new_page()$then()
page_2$set_content('<input type="email" placeholder="name@example.com"></input>')
page_2$get_by_placeholder("name@example.com")$fill("playwright@microsoft.com", list(timeout=100))$then()
get_by_role

Allows locating elements by their ARIA role, ARIA attributes and accessible name.

page_2 <- context$new_page()$then()
page_2$set_content('<h3>Sign up</h3>
  <label>
    <input type="checkbox"></input> Subscribe
  </label>
  <br/>
  <button>Submit</button>')
page_2$get_by_role("checkbox", list(name="Subscribe"))$check(list(timeout=100))$then()
get_by_test_id

Locate element by the test id.

page_2 <- context$new_page()$then()
page_2$set_content('<button data-testid="directions">Itinéraire</button>')
page_2$get_by_test_id("directions")$click(list(timeout=100))$then()
get_by_text

Allows locating elements that contain given text.

See also locator.filter() that allows to match by another criteria, like an accessible role, and then filter by the text content.

page_2 <- context$new_page()$then()
page_2$set_content('<div>Hello <span>world</span></div>
  <div>Hello</div>')
page_2$get_by_text("Hello", list(exact=FALSE))$click(list(timeout=100))$then()
get_by_title

Allows locating elements by their title attribute.

page_2 <- context$new_page()$then()
page_2$set_content("<span title='Issues count'>25 issues</span>")
get_by_title <- page_2$get_by_title("Issues count")$text_content()$then()
highlight

Highlight the corresponding element(s) on the screen. Useful for debugging, don’t commit the code that uses locator.highlight().

page_2 <- context$new_page()$then()
page_2$set_content("<span title='Issues count'>25 issues</span>")
page_2$get_by_title("Issues count")$highlight()$then()
hover

Hover over the matching element.

page$get_by_role("link", list(name="Get started"))$hover(list(timeout=100))$then()
inner_h_t_m_l

Returns the element.innerHTML.

inner_html = page$get_by_role("link", list(name="Get started"))$inner_h_t_m_l(list(timeout=100))$then()
inner_text

Returns the element.innerText.

inner_text = page$get_by_role("link", list(name="Get started"))$inner_text(list(timeout=100))$then()
input_value

Returns the value for the matching <input> or <textarea> or <select> element.

page_2 <- context$new_page()$then()
page_2$set_content('<input type="text" value="Test"></input>')
input_value <- page_2$get_by_role("text")$first()$input_value(list(timeout=100))$then()
is_checked

Returns whether the element is checked. Throws if the element is not a checkbox or radio input.

page_2 <- context$new_page()$then()
page_2$set_content('<input type="checkbox"></input>')
is_checked <- page_2$get_by_role("checkbox")$is_checked(list(timeout=100))$then()
is_disabled

Returns whether the element is disabled, the opposite of enabled.

page_2 <- context$new_page()$then()
page_2$set_content('<button data-testid="directions">Itinéraire</button>')
is_disabled <- page_2$get_by_test_id("directions")$is_disabled(list(timeout=100))$then()
is_editable

Returns whether the element is editable.

page_2 <- context$new_page()$then()
page_2$set_content('<input type="checkbox"></input>')
is_editable <- page_2$get_by_role("checkbox")$is_editable(list(timeout=100))$then()
is_enabled

Returns whether the element is enabled.

page_2 <- context$new_page()$then()
page_2$set_content('<button data-testid="directions">Itinéraire</button>')
is_enabled <- page_2$get_by_test_id("directions")$is_enabled(list(timeout=100))$then()
is_hidden

Returns whether the element is hidden, the opposite of visible.

page_2 <- context$new_page()$then()
page_2$set_content('<button data-testid="directions">Itinéraire</button>')
is_hidden <- page_2$get_by_test_id("directions")$is_hidden(list(timeout=100))$then()
is_visible

Returns whether the element is visible.

page_2 <- context$new_page()$then()
page_2$set_content('<button data-testid="directions">Itinéraire</button>')
is_visible <- page_2$get_by_test_id("directions")$is_visible(list(timeout=100))$then()
last

Returns locator to the last matching element.

last <- page$get_by_role("link")$last()
locator

The method finds an element matching the specified selector in the locator’s subtree. It also accepts filter options, similar to locator.filter() method.

page_2 <- context$new_page()$then()
page_2$set_content('<button data-testid="directions">Itinéraire</button>')
locator_inner_text <- page_2$locator('[data-testid="directions"]')$inner_text(list(timeout=100))$then()
nth

Returns locator to the n-th matching element. It’s zero based, nth(0) selects the first element.

nth_inner_text <- page$get_by_role("link")$nth(2)$inner_text(list(timeout=100))$then()
or

Creates a locator that matches either of the two locators.

or_unimplemented <- page$get_by_role("link")$or()
page

A page this locator belongs to.

locator_page <- page$get_by_role("link")$page()
press

Focuses the matching element and presses a combination of the keys.

page_2 <- context$new_page()$then()
page_2$set_content('<input type="text" value="Test"></input>')
page_2$locator("input")$press("Backspace", list(timeout=100))$then()
press_sequentially

Focuses the element, and then sends a keydown, keypress/input, and keyup event for each character in the text.

To press a special key, like Control or ArrowDown, use locator.press().

page_2 <- context$new_page()$then()
page_2$set_content('<input type="text"></input>')
page_2$locator("input")$press_sequentially("World", list(delay=100))$then()
screenshot

Take a screenshot of the element matching the locator.

locator_screenshot <- page$get_by_role("link")$first()$screenshot()$then()
scroll_into_view_if_needed

This method waits for actionability checks, then tries to scroll element into view, unless it is completely visible as defined by IntersectionObserver’s ratio.

See scrolling for alternative ways to scroll.

page$get_by_role("link")$last()$scroll_into_view_if_needed(list(delay=100))$then()
select_option

Selects option or options in <select>.

page_2 <- context$new_page()$then()
page_2$set_content('<select multiple>
    <option value="red">Red</div>
    <option value="green">Green</div>
    <option value="blue">Blue</div>
  </select>')
select_option <- page_2$locator("select")$select_option("blue", list(delay=100))$then()
select_text

This method waits for actionability checks, then focuses the element and selects all its text content.

If the element is inside the

page_2 <- context$new_page()$then()
page_2$set_content('<label>This is a label</label>')
page_2$locator("label")$select_text("label", list(delay=100))$then()
set_checked

Set the state of a checkbox or a radio element.

page_2 <- context$new_page()$then()
page_2$set_content('<h3>Sign up</h3>
  <label>
    <input type="checkbox"></input> Subscribe
  </label>
  <br/>
  <button>Submit</button>')
page_2$get_by_role("checkbox", list(name="Subscribe"))$set_checked(TRUE, list(timeout=100))$then()
tap

Perform a tap gesture on the element matching the locator.

page$get_by_role("link", list(name="Get started"))$tap()
text_content

Returns the node.textContent.

page_2 <- context$new_page()$then()
page_2$set_content('<label>This is a label</label>')
text_content = page_2$locator("label")$text_content(list(delay=100))$then()
uncheck

Ensure that checkbox or radio element is unchecked.

page_2 <- context$new_page()$then()
page_2$set_content('<h3>Sign up</h3>
  <label>
    <input type="checkbox" checked="checked"></input> Subscribe
  </label>
  <br/>
  <button>Submit</button>')
page_2$get_by_role("checkbox", list(name="Subscribe"))$uncheck(TRUE, list(timeout=100))$then()
wait_for

Returns when element specified by locator satisfies the state option.

If target element already satisfies the condition, the method returns immediately. Otherwise, waits for up to timeout milliseconds until the condition is met.

page_2 <- context$new_page()$then()
page_2$set_content('<label>This is a label</label>')
page_2$locator("label")$wait_for(list(state="visible", timeout=100))$then()

Request

Whenever the page sends a request for a network resource the following sequence of events are emitted by Page:

  • page.on(‘request’) emitted when the request is issued by the page.
  • page.on(‘response’) emitted when/if the response status and headers are received for the request.
  • page.on(‘requestfinished’) emitted when the response body is downloaded and the request is complete.

If request fails at some point, then instead of ‘requestfinished’ event (and possibly instead of ‘response’ event), the page.on(‘requestfailed’) event is emitted.

req_promise <- page$wait_for_event('requestfinished');
page$goto("https://hp-api.onrender.com/api/characters")$then()
req <- req_promise$then()
all_headers

An object with all the request HTTP headers associated with this request. The header names are lower-cased.

req_all_headers <- req$all_headers()$then()
failure

The method returns null unless this request has failed, as reported by requestfailed event.

req_failure <- req$failure()
frame

Returns the Frame that initiated this request.

req_frame <- req$frame()
req_frame$url()
header_value

Returns the value of the header matching the name. The name is case-insensitive.

req_headers_accept <- req$header_value("accept")$then()
headers

An object with the request HTTP headers. The header names are lower-cased. Note that this method does not return security-related headers, including cookie-related ones. You can use request.allHeaders() for complete list of headers that include cookie information.

req_headers <- req$headers()
headers_array

An array with all the request HTTP headers associated with this request. Unlike request.allHeaders(), header names are NOT lower-cased. Headers with multiple entries, such as Set-Cookie, appear in the array multiple times.

req_headers_array <- req$headers_array()
is_navigation_request

Whether this request is driving frame’s navigation.

Some navigation requests are issued before the corresponding frame is created, and therefore do not have request.frame() available.

req_is_navigation_request <- req$is_navigation_request()
method

Request’s method (GET, POST, etc.)

req_method <- req$method()
post_data

Request’s post body, if any.

req_post_data <- req$post_data()
post_data_buffer

Request’s post body in a binary form, if any.

req_post_data_buffer <- req$post_data_buffer()
post_data_j_s_o_n

Returns parsed request’s body for form-urlencoded and JSON as a fallback if any.

When the response is application/x-www-form-urlencoded then a key/value object of the values will be returned. Otherwise it will be parsed as JSON.

req_post_data_j_s_o_n <- req$post_data_j_s_o_n()
redirected_from

Request that was redirected by the server to this one, if any.

When the server responds with a redirect, Playwright creates a new Request object. The two requests are connected by redirectedFrom() and redirectedTo() methods. When multiple server redirects has happened, it is possible to construct the whole redirect chain by repeatedly calling redirectedFrom().

req_redirected_from <- req$redirected_from()
redirected_to

New request issued by the browser if the server responded with redirect.

req_redirected_to <- req$redirected_to()
resource_type

Contains the request’s resource type as it was perceived by the rendering engine. ResourceType will be one of the following: document, stylesheet, image, media, font, script, texttrack, xhr, fetch, eventsource, websocket, manifest, other.

req_resource_type <- req$resource_type()
response

Returns the matching Response object, or null if the response was not received due to error.

req_response <- req$response()$then()
req_response$ok()
service_worker

The Service Worker that is performing the request.

req_service_worker <- req$service_worker()
sizes

Returns resource size information for given request.

req_sizes <- req$sizes()$then()
timing

Returns resource timing information for given request. Most of the timing values become available upon the response, responseEnd becomes available when request finishes. Find more information at Resource Timing API.

req_timing <- req$timing()
url

URL of the request.

req_url <- req$url()

Response

Response class represents responses which are received by page.

page <- context$new_page()$then()
resp <- page$goto("https://hp-api.onrender.com/api/characters")$then()
all_headers

An object with all the response HTTP headers associated with this response.

all_headers <- resp$all_headers()$then()
body

Returns the base64 encoded response body.

body <- resp$body()$then()
finished

Waits for this response to finish, returns always null.

finished <- resp$finished()$then()
frame

Returns the Frame that initiated this response.

frame <- resp$frame()
from_service_worker

Indicates whether this Response was fulfilled by a Service Worker’s Fetch Handler (i.e. via FetchEvent.respondWith).

from_service_worker <- resp$from_service_worker()
header_value

Returns the value of the header matching the name. The name is case-insensitive. If multiple headers have the same name (except set-cookie), they are returned as a list separated by , . For set-cookie, the separator is used. If no headers are found, null is returned.

header_value <- resp$header_value()
header_values

Returns all values of the headers matching the name, for example set-cookie. The name is case-insensitive.

header_values <- resp$header_values()
headers

An object with the response HTTP headers. The header names are lower-cased. Note that this method does not return security-related headers, including cookie-related ones. You can use response.allHeaders() for complete list of headers that include cookie information.

headers <- resp$headers()
headers_array

An array with all the request HTTP headers associated with this response. Unlike response.allHeaders(), header names are NOT lower-cased. Headers with multiple entries, such as Set-Cookie, appear in the array multiple times.

headers_array <- resp$headers_array()$then()
json

Returns the JSON representation of response body. This method will throw if the response body is not parsable via JSON.parse.

json <- resp$json()$then()
ok

Contains a boolean stating whether the response was successful (status in the range 200-299) or not.

ok <- resp$ok()
request

Returns the matching Request object.

request <- resp$request()
security_details

Returns SSL and other security information.

security_details <- resp$security_details()$then()
server_addr

Returns the IP address and port of the server.

server_addr <- resp$server_addr()$then()
status

Contains the status code of the response (e.g., 200 for a success).

status <- resp$status()
status_text

Contains the status text of the response (e.g. usually an “OK” for a success).

status_text <- resp$status_text()
text

Returns the text representation of response body.

text <- resp$text()$then()
url

Contains the URL of the response.

url <- resp$url()

Frame

At every point of time, page exposes its current frame tree via the page.mainFrame() and frame.childFrames() methods.

Frame object’s lifecycle is controlled by three events, dispatched on the page object:

  • page.on(‘frameattached’) - fired when the frame gets attached to the page. A Frame can be attached to the page only once.

  • page.on(‘framenavigated’) - fired when the frame commits navigation to a different URL.

  • page.on(‘framedetached’) - fired when the frame gets detached from the page. A Frame can be detached from the page only once.

add_script_tag

Returns the added tag when the script’s onload fires or when the script content was injected into frame.

Adds a <script> tag into the page with the desired url or content.

page$goto("https://ui.vision/demo/webtest/frames/")$then()
main_frame <- page$main_frame()
child_frames <- main_frame$child_frames()

child_frame <- child_frames[[1]]
child_frame$add_script_tag(list(content="document.querySelector('[name=mytext1]').value = 'value from add_script_tag'"))$then()
add_style_tag

Returns the added tag when the stylesheet’s onload fires or when the CSS content was injected into frame.

Adds a <link rel="stylesheet"> tag into the page with the desired url or a <style type="text/css"> tag with the content.

page$goto("https://ui.vision/demo/webtest/frames/")$then()
main_frame <- page$main_frame()
child_frames <- main_frame$child_frames()

child_frame <- child_frames[[1]]
child_frame$add_style_tag(list(content="body { background-color: red }"))$then()
child_frames
page$goto("https://ui.vision/demo/webtest/frames/")$then()
main_frame <- page$main_frame()
child_frames <- main_frame$child_frames()

child_frame_content <- child_frames[[1]]$content()$then()
content

Gets the full HTML contents of the frame, including the doctype.

page$goto("https://ui.vision/demo/webtest/frames/")$then()
main_frame <- page$main_frame()
child_frames <- main_frame$child_frames()

child_frame_content <- child_frames[[1]]$content()$then()
drag_and_drop
page$drag_and_drop("#source", "#target")$then()
evaluate

Returns the return value of pageFunction.

If the function passed to the frame.evaluate() returns a Promise, then 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 undefined. Playwright also supports transferring some additional values that are not serializable by JSON: -0, NaN, Infinity, -Infinity.

page$goto("https://ui.vision/demo/webtest/frames/")$then()
main_frame <- page$main_frame()
child_frames <- main_frame$child_frames()

evaluate_result <- child_frames[[1]]$evaluate("([a, b]) => a * b", c(5, 7))$then()
evaluate_handle

Returns the return value of pageFunction as a JSHandle.

The only difference between frame.evaluate() and frame.evaluateHandle() is that frame.evaluateHandle() returns JSHandle.

If the function, passed to the frame.evaluateHandle(), returns a Promise, then frame.evaluateHandle() would wait for the promise to resolve and return its value.

page$goto("https://ui.vision/demo/webtest/frames/")$then()
main_frame <- page$main_frame()
child_frames <- main_frame$child_frames()

child_frames[[1]]$evaluate_handle()$then()
frame_element

Returns the frame or iframe element handle which corresponds to this frame.

This is an inverse of elementHandle.contentFrame(). Note that returned handle actually belongs to the parent frame.

This method throws an error if the frame has been detached before frameElement() returns.

page$goto("https://ui.vision/demo/webtest/frames/")$then()
main_frame <- page$main_frame()
child_frames <- main_frame$child_frames()

frame_element <- child_frames[[1]]$frame_element()
frame_locator

When working with iframes, you can create a frame locator that will enter the iframe and allow selecting elements in that iframe.

page$goto("https://ui.vision/demo/webtest/frames/")$then()
frame3 <- page$main_frame()$frame_locator("[url=https://ui.vision/demo/webtest/frames/frame_3.html]")
frame3$get_by_text("Berikutnya")$click()$then()
get_by_alt_text

Allows locating elements by their alt text.

page$goto("https://ui.vision/demo/webtest/frames/")$then()
frame3 <- page$main_frame()$frame_locator("[url=https://ui.vision/demo/webtest/frames/frame_3.html]")
frame3$get_by_alt_text("Berikutnya")$click()$then()
get_by_label

Allows locating input elements by the text of the associated

page$goto("https://ui.vision/demo/webtest/frames/")$then()
frame3 <- page$main_frame()$frame_locator("[url=https://ui.vision/demo/webtest/frames/frame_3.html]")
frame3$get_by_label("Berikutnya")$click()$then()
get_by_placeholder

Allows locating input elements by the placeholder text.

page$goto("https://ui.vision/demo/webtest/frames/")$then()
frame3 <- page$main_frame()$frame_locator("[url=https://ui.vision/demo/webtest/frames/frame_3.html]")
frame3$get_by_placeholder("Berikutnya")$click()$then()
get_by_role

Allows locating elements by their ARIA role, ARIA attributes and accessible name.

page$goto("https://ui.vision/demo/webtest/frames/")$then()
frame3 <- page$main_frame()$frame_locator("[url=https://ui.vision/demo/webtest/frames/frame_3.html]")
frame3$get_by_role("Berikutnya")$click()$then()
get_by_test_id

Locate element by the test id.

page$goto("https://ui.vision/demo/webtest/frames/")$then()
frame3 <- page$main_frame()$frame_locator("[url=https://ui.vision/demo/webtest/frames/frame_3.html]")
frame3$get_by_test_id("Berikutnya")$click()$then()
get_by_text

Allows locating elements that contain given text.

See also locator.filter() that allows to match by another criteria, like an accessible role, and then filter by the text content.

page$goto("https://ui.vision/demo/webtest/frames/")$then()
frame3 <- page$main_frame()$frame_locator("[url=https://ui.vision/demo/webtest/frames/frame_3.html]")
frame3$get_by_text("Berikutnya")$click()$then()
get_by_title

Allows locating elements by their title attribute.

page$goto("https://ui.vision/demo/webtest/frames/")$then()
frame3 <- page$main_frame()$frame_locator("[url=https://ui.vision/demo/webtest/frames/frame_3.html]")
frame3$get_by_title("Berikutnya")$click()$then()
goto

Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of the last redirect.

The method will throw an error if:

  • there’s an SSL error (e.g. in case of self-signed certificates).
  • target URL is invalid.
  • the timeout is exceeded during navigation.
  • the remote server does not respond or is unreachable.
  • the main resource failed to load.
  • The method will not throw an error when any valid HTTP status code is returned by the remote server, including 404 “Not Found” and 500 “Internal Server Error”. The status code for such responses can be retrieved by calling response.status().
page$goto("https://ui.vision/demo/webtest/frames/")$then()
child_frames <- page$main_frame()$child_frames()
child_frames[[3]]$goto("https://ui.vision/demo/webtest/frames/")
is_detached

Returns true if the frame has been detached, or false otherwise.

page$goto("https://ui.vision/demo/webtest/frames/")$then()
child_frames <- page$main_frame()$child_frames()
child_frames[[3]]$is_detached()
is_enabled

Returns whether the element is enabled.

page$goto("https://ui.vision/demo/webtest/frames/")$then()
child_frames <- page$main_frame()$child_frames()
child_frames[[3]]$is_enabled("[name=mytext3]", list(timeout=200))$then()
locator

The method returns an element locator that can be used to perform actions on this page / frame. Locator is resolved to the element immediately before performing an action, so a series of actions on the same locator can in fact be performed on different DOM elements. That would happen if the DOM structure between those actions has changed.

page$goto("https://ui.vision/demo/webtest/frames/")$then()
child_frames <- page$main_frame()$child_frames()
child_frames[[3]]$locator("[name=mytext3]")$focus()$then()
name

Returns frame’s name attribute as specified in the tag.

If the name is empty, returns the id attribute instead.

page$goto("https://ui.vision/demo/webtest/frames/")$then()
child_frames <- page$main_frame()$child_frames()
child_frames[[3]]$name()
page

Returns the page containing this frame.

page$goto("https://ui.vision/demo/webtest/frames/")$then()
child_frames <- page$main_frame()$child_frames()
frame_page_content <- child_frames[[3]]$page()$content()$then()
parent_frame

Parent frame, if any. Detached frames and main frames return null.

page$goto("https://ui.vision/demo/webtest/frames/")$then()
child_frames <- page$main_frame()$child_frames()
frame_parent_frame <- child_frames[[3]]$parent_frame()
set_content

This method internally calls document.write(), inheriting all its specific characteristics and behaviors.

page$goto("https://ui.vision/demo/webtest/frames/")$then()
child_frames <- page$main_frame()$child_frames()
child_frames[[3]]$set_content("content from set_content")
title

Returns the page title.

page$goto("https://ui.vision/demo/webtest/frames/")$then()
child_frames <- page$main_frame()$child_frames()
frame_title <- child_frames[[3]]$title()$then()
url

Returns frame’s url.

page$goto("https://ui.vision/demo/webtest/frames/")$then()
child_frames <- page$main_frame()$child_frames()
frame_url <- child_frames[[3]]$url()
wait_for_function

Returns when the pageFunction returns a truthy value, returns that value.

page$goto("https://ui.vision/demo/webtest/frames/")$then()
child_frames <- page$main_frame()$child_frames()
frame_3 <- child_frames[[3]]

fn_promise <- frame_3$wait_for_function("() => window.innerWidth < 100")
page$set_viewport_size(list(width=50, height=50))$then()
js <- fn_promise$then()
wait_for_load_state

Waits for the required load state to be reached.

This returns when the frame reaches a required load state, load by default. The navigation must have been committed when this method is called. If current document has already reached the required state, resolves immediately.

page$goto("https://ui.vision/demo/webtest/frames/")$then()
child_frames <- page$main_frame()$child_frames()
frame_3 <- child_frames[[3]]

ev_promise <- frame_3$wait_for_load_state("load")
frame_3$goto("https://playwright.dev/")$then()
ev <- ev_promise$then()
wait_for_u_r_l

Waits for the frame to navigate to the given URL.

page$goto("https://ui.vision/demo/webtest/frames/")$then()
child_frames <- page$main_frame()$child_frames()
frame_3 <- child_frames[[3]]

resp_promise <- frame_3$wait_for_u_r_l("https://playwright.dev/")
frame_3$goto("https://playwright.dev/")$then()
resp_promise$then()

Full Usage Example

devtools::load_all()
roxygen2::roxygenise()

rplaywright::install_rplaywright(force = TRUE)

chrome <- rplaywright::new_chromium()
firefox <- rplaywright::new_firefox()
webkit <- rplaywright::new_webkit()

context <- chrome$new_context()$then()
page <- context$new_page()$then()
resp <- page$goto("https://playwright.dev/")$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-all}
all_links <- page$get_by_role("link")$all()$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-all-inner-texts}
all_inner_texts <- page$get_by_role("link")$all_inner_texts()$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-all-text-contents}
all_text_contents <- page$get_by_role("link")$all_text_contents()$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-and}
and_unimplemented <- page$get_by_role("link")$and()

# @link{https://playwright.dev/docs/api/class-locator#locator-blur}
page$get_by_role("link", list(name="Get started"))$blur()$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-bounding-box}
bounding_box <- page$get_by_role("link", list(name="Get started"))$bounding_box()$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-check}
page$get_by_role("checkbox")$check(list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-clear}
page$get_by_role("textbox")$clear(list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-click}
page$get_by_role("link", list(name="Get started"))$click(list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-content-frame}
content_frame_unimplemented <- page$get_by_role("link")$content_frame()

# @link{https://playwright.dev/docs/api/class-locator#locator-count}
count <- page$get_by_role("link")$count()$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-dblclick}
page$get_by_role("link", list(name="Get started"))$dblclick(list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-dispatch-event}
page$get_by_role("link", list(name="Get started"))$dispatch_event('click', NULL, list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-drag-to}
drag_to_unimplemented <- page$get_by_role("link")$drag_to()

# @link{https://playwright.dev/docs/api/class-locator#locator-evaluate}
evaluate_unimplemented <- page$get_by_role("link")$evaluate()

# @link{https://playwright.dev/docs/api/class-locator#locator-evaluate-all}
evaluate_all_unimplemented <- page$get_by_role("link")$evaluate_all()

# @link{https://playwright.dev/docs/api/class-locator#locator-evaluate-handle}
evaluate_handle_unimplemented <- page$get_by_role("link")$evaluate_handle()

# @link{https://playwright.dev/docs/api/class-locator#locator-fill}
page$get_by_role("textbox")$fill("example value", list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-filter}
filter_unimplemented <- page$get_by_role("link")$filter()

# @link{https://playwright.dev/docs/api/class-locator#locator-first}
first <- page$get_by_role("link")$first()

# @link{https://playwright.dev/docs/api/class-locator#locator-focus}
page$get_by_role("link")$first()$focus()$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-frame-locator}
frame_locator_unimplemented <- page$get_by_role("link")$frame_locator()

# @link{https://playwright.dev/docs/api/class-locator#locator-get-attribute}
attribute <- page$get_by_role("link")$first()$get_attribute("title")$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-get-by-alt-text}
page_2 <- context$new_page()$then()
page_2$set_content("<img alt='Playwright logo'>")
page_2$get_by_alt_text("link")$click(list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-get-by-label}
page_2 <- context$new_page()$then()
page_2$set_content('<input aria-label="Username"></input>
  <label for="password-input">Password:</label>
  <input id="password-input"></input>')
page_2$get_by_label("Username")$fill("John", list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-get-by-placeholder}
page_2 <- context$new_page()$then()
page_2$set_content('<input type="email" placeholder="name@example.com"></input>')
page_2$get_by_placeholder("name@example.com")$fill("playwright@microsoft.com", list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-get-by-role}
page_2 <- context$new_page()$then()
page_2$set_content('<h3>Sign up</h3>
  <label>
    <input type="checkbox"></input> Subscribe
  </label>
  <br/>
  <button>Submit</button>')
page_2$get_by_role("checkbox", list(name="Subscribe"))$check(list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-get-by-test-id}
page_2 <- context$new_page()$then()
page_2$set_content('<button data-testid="directions">Itinéraire</button>')
page_2$get_by_test_id("directions")$click(list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-get-by-text}
page_2 <- context$new_page()$then()
page_2$set_content('<div>Hello <span>world</span></div>
  <div>Hello</div>')
page_2$get_by_text("Hello", list(exact=FALSE))$click(list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-get-by-title}
page_2 <- context$new_page()$then()
page_2$set_content("<span title='Issues count'>25 issues</span>")
get_by_title <- page_2$get_by_title("Issues count")$text_content()$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-highlight}
page_2 <- context$new_page()$then()
page_2$set_content("<span title='Issues count'>25 issues</span>")
page_2$get_by_title("Issues count")$highlight()$then()

#
page$goto("https://playwright.dev/")$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-hover}
page$get_by_role("link", list(name="Get started"))$hover(list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-inner-html}
inner_html = page$get_by_role("link", list(name="Get started"))$inner_h_t_m_l(list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-inner-text}
inner_text = page$get_by_role("link", list(name="Get started"))$inner_text(list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-input-value}
page_2 <- context$new_page()$then()
page_2$set_content('<input type="text" value="Test"></input>')
input_value <- page_2$get_by_role("text")$first()$input_value(list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-is-checked}
page_2 <- context$new_page()$then()
page_2$set_content('<input type="checkbox"></input>')
is_checked <- page_2$get_by_role("checkbox")$is_checked(list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-is-disabled}
page_2 <- context$new_page()$then()
page_2$set_content('<button data-testid="directions">Itinéraire</button>')
is_disabled <- page_2$get_by_test_id("directions")$is_disabled(list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-is-editable}
page_2 <- context$new_page()$then()
page_2$set_content('<input type="checkbox"></input>')
is_editable <- page_2$get_by_role("checkbox")$is_editable(list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-is-enabled}
page_2 <- context$new_page()$then()
page_2$set_content('<button data-testid="directions">Itinéraire</button>')
is_enabled <- page_2$get_by_test_id("directions")$is_enabled(list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-is-hidden}
page_2 <- context$new_page()$then()
page_2$set_content('<button data-testid="directions">Itinéraire</button>')
is_hidden <- page_2$get_by_test_id("directions")$is_hidden(list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-is-visible}
page_2 <- context$new_page()$then()
page_2$set_content('<button data-testid="directions">Itinéraire</button>')
is_visible <- page_2$get_by_test_id("directions")$is_visible(list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-last}
last <- page$get_by_role("link")$last()

# @link{https://playwright.dev/docs/api/class-locator#locator-locator}
page_2 <- context$new_page()$then()
page_2$set_content('<button data-testid="directions">Itinéraire</button>')
locator_inner_text <- page_2$locator('[data-testid="directions"]')$inner_text(list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-nth}
nth_inner_text <- page$get_by_role("link")$nth(2)$inner_text(list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-or}
or_unimplemented <- page$get_by_role("link")$or()

# @link{https://playwright.dev/docs/api/class-locator#locator-page}
locator_page <- page$get_by_role("link")$page()

# @link{https://playwright.dev/docs/api/class-locator#locator-press}
page_2 <- context$new_page()$then()
page_2$set_content('<input type="text" value="Test"></input>')
page_2$locator("input")$press("Backspace", list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-press-sequentially}
page_2 <- context$new_page()$then()
page_2$set_content('<input type="text"></input>')
page_2$locator("input")$press_sequentially("World", list(delay=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-screenshot}
locator_screenshot <- page$get_by_role("link")$first()$screenshot()$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-screenshot}
page$get_by_role("link")$last()$scroll_into_view_if_needed(list(delay=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-select-option}
page_2 <- context$new_page()$then()
page_2$set_content('<select multiple>
    <option value="red">Red</option>
    <option value="green">Green</option>
    <option value="blue">Blue</option>
  </select>')
select_option <- page_2$locator("select")$select_option("blue", list(delay=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-select-text}
page_2 <- context$new_page()$then()
page_2$set_content('<label>This is a label</label>')
page_2$locator("label")$select_text("label", list(delay=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-set-checked}
page_2 <- context$new_page()$then()
page_2$set_content('<h3>Sign up</h3>
  <label>
    <input type="checkbox"></input> Subscribe
  </label>
  <br/>
  <button>Submit</button>')
page_2$get_by_role("checkbox", list(name="Subscribe"))$set_checked(TRUE, list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-tap}
page$get_by_role("link", list(name="Get started"))$tap()

# @link{https://playwright.dev/docs/api/class-locator#locator-text-content}
page_2 <- context$new_page()$then()
page_2$set_content('<label>This is a label</label>')
text_content = page_2$locator("label")$text_content(list(delay=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-uncheck}
page_2 <- context$new_page()$then()
page_2$set_content('<h3>Sign up</h3>
  <label>
    <input type="checkbox" checked="checked"></input> Subscribe
  </label>
  <br/>
  <button>Submit</button>')
page_2$get_by_role("checkbox", list(name="Subscribe"))$uncheck(TRUE, list(timeout=100))$then()

# @link{https://playwright.dev/docs/api/class-locator#locator-wait-for}
page_2 <- context$new_page()$then()
page_2$set_content('<label>This is a label</label>')
page_2$locator("label")$wait_for(list(state="visible", timeout=100))$then()

chrome$close()$then()

rplaywright::stop_server()

Use Case Example for Twitter Crawling

chrome <- rplaywright::new_chromium()

context <- chrome$new_context(list(
  screen = list(width = 1240, height = 1080),
  storage_state = list(
    cookies = list(
      list(
        name = "auth_token",
        value = "auth_token_from_cookies", # Use auth_token from cookies
        domain = ".x.com",
        path = "/",
        expires = -1,
        http_only = T,
        secure = T,
        same_site = "Strict"
      )
    ),
    origins = list()
  )
))$then()

page <- context$new_page()$then()
resp <- page$goto("https://x.com/search-advanced")$then()

aresp <- page$wait_for_response(
  "resp => (resp.url().includes('SearchTimeline') || resp.url().includes('TweetDetail')) && resp.status() === 200", 
  list(timeout=15000000)
)

page$get_by_label("All of these words")$fill("playwright")$then()
page$get_by_role("button", list(name="Search"))$click()$then()

resp <- aresp$then()

result <- list()
count <- 1

all_headers = resp$all_headers()$then()
body = resp$body()$then()
finished = resp$finished()$then()
headers = resp$headers()
headers_array = resp$headers_array()$then()
json = resp$json()$then()
ok = resp$ok()
security_details = resp$security_details()$then()
server_addr = resp$server_addr()$then()
status = resp$status()
status_text = resp$status_text()
text = resp$text()$then()
url = resp$url()
frame = resp$frame()
from_service_worker = resp$from_service_worker()
header_value = resp$header_value()
header_values = resp$header_values()
request = resp$request()

result[[count]] <- json
count <- count + 1

while (T) {
  print(paste0("Iteration ", count))
  
  page$evaluate("
    () => window.scrollTo({
      behavior: 'smooth',
      top: 0,
    })
  ")$then()
  
  page$evaluate("
     async () => await new Promise((r, j) => setTimeout(() => r(), 2000))
  ")$then()
  
  page$evaluate("
    () => window.scrollTo({
      behavior: 'smooth',
      top: document.body.scrollHeight,
    })
  ")$then()
  
  resp <- aresp$then()
  if (is.null(resp)) next;
  
  json = resp$json()$then()
  
  result[[count]] <- json
  count <- count + 1
  
  if (count > 3) break;
}

chrome$close()$then()
rplaywright::stop_server()