From 858d4675f433e9c99d0c3c77f1347ee868120854 Mon Sep 17 00:00:00 2001 From: Gianfranco Spiteri Date: Sat, 16 Nov 2024 12:21:34 +0100 Subject: [PATCH] Add xpath argument to session$click() method --- DESCRIPTION | 2 +- R/live.R | 25 +++++++++++++++++++------ man/LiveHTML.Rd | 4 ++-- tests/testthat/test-live.R | 8 ++++++-- 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index d9680b1..ee5ddd7 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -42,4 +42,4 @@ Config/testthat/parallel: true Encoding: UTF-8 Language: en-US Roxygen: list(markdown = TRUE) -RoxygenNote: 7.3.1 +RoxygenNote: 7.3.2 diff --git a/R/live.R b/R/live.R index 6f7828e..ee65ddc 100644 --- a/R/live.R +++ b/R/live.R @@ -127,17 +127,19 @@ LiveHTML <- R6::R6Class( #' @description Simulate a click on an HTML element. - #' @param css CSS selector or xpath expression. + #' @param css,xpath CSS selector or xpath expression. #' @param n_clicks Number of clicks - click = function(css, n_clicks = 1) { + click = function(css, xpath, n_clicks = 1) { private$check_active() + check_exclusive(css, xpath) + check_number_whole(n_clicks, min = 1) # Implementation based on puppeteer as described in # https://medium.com/@aslushnikov/automating-clicks-in-chromium-a50e7f01d3fb # With code from https://github.com/puppeteer/puppeteer/blob/b53de4e0942e93c/packages/puppeteer-core/src/cdp/Input.ts#L431-L459 - node <- private$wait_for_selector(css) + node <- private$wait_for_selector(css, xpath) self$session$DOM$scrollIntoViewIfNeeded(node) # Quad = location of four corners (x1, y1, x2, y2, x3, y3, x4, y4) @@ -277,17 +279,28 @@ LiveHTML <- R6::R6Class( } }, - wait_for_selector = function(css, timeout = 5) { + wait_for_selector = function(css, xpath, timeout = 5) { + check_exclusive(css, xpath) + done <- now() + timeout while(now() < done) { - nodes <- private$find_nodes(css) + if (!missing(css)) { + nodes <- private$find_nodes(css = css) + } else { + nodes <- private$find_nodes(xpath = xpath) + } if (length(nodes) > 0) { return(nodes) } Sys.sleep(0.1) } - cli::cli_abort("Failed to find selector {.str {css}} in {timeout} seconds.") + + if(!missing(css)){ + cli::cli_abort("Failed to find selector {.str {css}} in {timeout} seconds.") + } else { + cli::cli_abort("Failed to find xpath {.str {xpath}} in {timeout} seconds.") + } }, find_nodes = function(css, xpath) { diff --git a/man/LiveHTML.Rd b/man/LiveHTML.Rd index a568e66..0198d51 100644 --- a/man/LiveHTML.Rd +++ b/man/LiveHTML.Rd @@ -122,13 +122,13 @@ Extract HTML elements from the current page. \subsection{Method \code{click()}}{ Simulate a click on an HTML element. \subsection{Usage}{ -\if{html}{\out{
}}\preformatted{LiveHTML$click(css, n_clicks = 1)}\if{html}{\out{
}} +\if{html}{\out{
}}\preformatted{LiveHTML$click(css, xpath, n_clicks = 1)}\if{html}{\out{
}} } \subsection{Arguments}{ \if{html}{\out{
}} \describe{ -\item{\code{css}}{CSS selector or xpath expression.} +\item{\code{css, xpath}}{CSS selector or xpath expression.} \item{\code{n_clicks}}{Number of clicks} } diff --git a/tests/testthat/test-live.R b/tests/testthat/test-live.R index e1d7fab..3cb1e8a 100644 --- a/tests/testthat/test-live.R +++ b/tests/testthat/test-live.R @@ -43,10 +43,14 @@ test_that("can click a button", { skip_if_no_chromote() sess <- read_html_live(html_test_path("click")) - sess$click("button") + sess$click(css = "button") expect_equal(html_text(html_element(sess, "p")), "clicked") - sess$click("button", 2) + sess <- read_html_live(html_test_path("click")) + sess$click(xpath = "//button") + expect_equal(html_text(html_element(sess, "p")), "clicked") + + sess$click(css = "button", n_clicks = 2) expect_equal(html_text(html_element(sess, "p")), "double clicked") })