Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add chromote as headless browser for testing #126

Merged
merged 96 commits into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from 94 commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
1e7c8a9
changed browser name to chromote
siddhesh195 May 5, 2024
361265a
Update helper-HTML.R
siddhesh195 May 27, 2024
635e7a1
Update helper-HTML.R
siddhesh195 May 29, 2024
bbb45af
Update helper-HTML.R
siddhesh195 May 30, 2024
41b36cf
Update helper-HTML.R
siddhesh195 May 31, 2024
58afca2
Update helper-HTML.R
siddhesh195 Jun 1, 2024
03f362d
Update helper-HTML.R
siddhesh195 Jun 1, 2024
c06c837
Update helper-HTML.R
siddhesh195 Jun 2, 2024
b17b9b3
Update helper-functions.R
siddhesh195 Jun 3, 2024
54447b1
Update test-renderer1-global-variables.R
siddhesh195 Jun 5, 2024
86bbdeb
Update test-renderer1-global-variables.R
siddhesh195 Jun 5, 2024
9f9c919
Update test-renderer1-facet-lines.R
siddhesh195 Jun 5, 2024
42f35ff
Update test-renderer1-axis-angle-rotate.R
siddhesh195 Jun 5, 2024
96752b4
Update test-renderer1-axis-angle-rotate.R
siddhesh195 Jun 5, 2024
5aa6df4
Update test-renderer1-url-fragment.R
siddhesh195 Jun 6, 2024
03c3069
Update test-renderer1-global-variables.R
siddhesh195 Jun 6, 2024
0fe937d
Update test-renderer1-facet-lines.R
siddhesh195 Jun 6, 2024
1cb23ad
Update test-renderer1-axis-angle-rotate.R
siddhesh195 Jun 6, 2024
c1e77cb
Update helper-functions.R
siddhesh195 Jun 6, 2024
7833553
Update test-renderer1-axis-angle-rotate.R
siddhesh195 Jun 6, 2024
67fccdf
Update test-renderer1-url-fragment.R
siddhesh195 Jun 6, 2024
0250d7f
Update version and NEWS.md
siddhesh195 Jun 6, 2024
01a2c2a
Update z_pages.R
siddhesh195 Jun 12, 2024
7ebb270
Update z_pages.R
siddhesh195 Jun 12, 2024
73a0856
Revert accidental commit
siddhesh195 Jun 12, 2024
e90f655
Update test to such that it can be run on chromote
siddhesh195 Jun 13, 2024
9ef4993
Switch to chromote for Github actions
siddhesh195 Jun 13, 2024
d2b5de7
Migrate renderer1-knit-print to chromote
siddhesh195 Jun 14, 2024
2aa1922
Update test-renderer1-knit-print.R
siddhesh195 Jun 15, 2024
d45f3d9
Update test-renderer1-knit-print.R
siddhesh195 Jun 15, 2024
979fb9d
edits that work on TDH ubuntu laptop with chrome
tdhock Jun 25, 2024
083b611
kept only chromote APIs
siddhesh195 Jun 26, 2024
4433592
kept only chromote APIs
siddhesh195 Jun 26, 2024
cc85e09
kept only chromote APIs
siddhesh195 Jun 26, 2024
041fd2a
modified delay for chromote
siddhesh195 Jun 26, 2024
35cdf6f
kept only chromote APIs
siddhesh195 Jun 26, 2024
819963d
removed everything not required for chromote
siddhesh195 Jun 26, 2024
752a5bf
kept only chromote's way of using clickID and clickHTML
siddhesh195 Jun 26, 2024
a6f495e
Merge branch 'chromote-testing' of https://github.com/animint/animint…
siddhesh195 Jun 27, 2024
2507635
removed all code expect for chromote
siddhesh195 Jun 27, 2024
996ac70
added browserName as first argument again
siddhesh195 Jun 27, 2024
5ccb456
removed requirement for browser name in tests_init()
siddhesh195 Jun 27, 2024
843c164
removed code not related to chromote
siddhesh195 Jun 27, 2024
31ba2a3
removed browsername argument
siddhesh195 Jun 27, 2024
ec0b8a9
restored accidentally deleted code
siddhesh195 Jun 28, 2024
6c9ab03
partial work of requested changes
siddhesh195 Jul 7, 2024
c2d7bc5
Refactor the test and undo deletion of tests
siddhesh195 Jul 7, 2024
1c62fa6
removed unnecessary lines in helper-HTML and changed system sleep to …
siddhesh195 Jul 10, 2024
bbadd20
added explanation to why offset was added in tick box and title box
siddhesh195 Jul 10, 2024
4022f0b
refactored code to make clear difference between if and else blocks
siddhesh195 Jul 10, 2024
11c0fc3
Fix setting plot duration in wirerect test
siddhesh195 Jul 10, 2024
54d605b
Refactor widerect and knit-print
siddhesh195 Jul 10, 2024
9377292
delete extra-packages
tdhock Jul 11, 2024
9f9129b
getBounds -> getClassBound
tdhock Jul 11, 2024
9644cd2
removed print
siddhesh195 Jul 11, 2024
8357e45
removed white line
siddhesh195 Jul 11, 2024
42ce09d
expect_true changed to expect_gt
siddhesh195 Jul 11, 2024
2b39a33
undo whitespaces
siddhesh195 Jul 13, 2024
6d79c0b
made a helper function for Runtime$evaluate
siddhesh195 Jul 13, 2024
0ae07c6
modified helper function
siddhesh195 Jul 14, 2024
c5762eb
reverted changes
siddhesh195 Jul 15, 2024
273dc5f
added extra-packages back
siddhesh195 Jul 18, 2024
76800a4
removed extra packages
siddhesh195 Jul 18, 2024
1830ace
helper function, empty space
siddhesh195 Jul 19, 2024
56a5007
added sleep
siddhesh195 Jul 19, 2024
1f613b7
added dispatch_event=TRUE
siddhesh195 Jul 20, 2024
30f8e49
added space after comma and blank line
siddhesh195 Jul 31, 2024
1e5c897
return by value always,
siddhesh195 Jul 31, 2024
460567e
corrected runtime_evaluate to return by value
siddhesh195 Aug 2, 2024
c639517
added space, returning in helper function directly without saving in …
siddhesh195 Aug 2, 2024
e00b556
added for loop
siddhesh195 Aug 2, 2024
61ced10
made variable names more informative
siddhesh195 Aug 4, 2024
73604ab
added sleep to try solving perpetual run on github actions
siddhesh195 Aug 4, 2024
7d119a4
added sleep to try solving perpetual run on github actions
siddhesh195 Aug 4, 2024
607d94e
removed sleep in helper function because widerect test failed
siddhesh195 Aug 4, 2024
93478c6
changed names in list
siddhesh195 Aug 5, 2024
a0e51ea
reverted names in the list
siddhesh195 Aug 5, 2024
e6c837c
changing names inside list
siddhesh195 Aug 5, 2024
97202cf
changing names inside list
siddhesh195 Aug 5, 2024
9aa2419
reverted values in list
siddhesh195 Aug 5, 2024
4174041
eliminated intermediate variables
siddhesh195 Aug 5, 2024
52c88b0
simplify runtime_evaluate_helper
tdhock Aug 7, 2024
5a3ca36
removed empty line
siddhesh195 Aug 7, 2024
e411c4f
Merge branch 'chromote-testing' of https://github.com/animint/animint…
siddhesh195 Aug 7, 2024
7cbc05a
removed sprintf and port argument
siddhesh195 Aug 7, 2024
2479b4e
removed port argument's use
siddhesh195 Aug 7, 2024
9c37ee0
corrected port type from %s to %d
siddhesh195 Aug 7, 2024
576b1ce
removed return by value
siddhesh195 Aug 7, 2024
2258245
refactor sendKey, fix style
tdhock Aug 11, 2024
41d1c10
changed keyCode to key2code[[key]]
siddhesh195 Aug 12, 2024
49e923a
rm types
tdhock Aug 12, 2024
2b15fba
commented for key-codes
siddhesh195 Aug 12, 2024
2a63348
modified comment for key codes
siddhesh195 Aug 12, 2024
053dde9
link chromote docs and mozilla key event page
tdhock Aug 14, 2024
0c044e7
Increase chromote initialization timeout
siddhesh195 Aug 27, 2024
45ecfb8
change tab to space
tdhock Aug 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@ jobs:
- run: /usr/bin/sudo DEBIAN_FRONTEND=noninteractive apt install texlive texlive-fonts-extra -y
- uses: r-lib/actions/setup-r@v2
- uses: r-lib/actions/setup-r-dependencies@v2
with:
extra-packages: digest, RJSONIO, gtable, plyr, reshape2, scales, knitr



- name: install package
run: R CMD INSTALL .

Expand Down
5 changes: 3 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: animint2
Title: Animated Interactive Grammar of Graphics
Version: 2024.3.12
Version: 2024.6.6
URL: https://animint.github.io/animint2/
BugReports: https://github.com/animint/animint2/issues
Authors@R: c(
Expand Down Expand Up @@ -100,7 +100,8 @@ Suggests:
nlme,
rpart,
svglite,
ggplot2
ggplot2,
chromote
Remotes: ropensci/RSelenium@v1.7.4
License: GPL-3
Encoding: UTF-8
Expand Down
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Changes in version 2024.6.6 (PR#126)

- Add chromote as headless browser for testing and remove phantomjs/firefox support

# Changes in version 2024.3.12 (PR#119)

- Add validation checks for duplicate args passed geom and aes
Expand Down
8 changes: 1 addition & 7 deletions tests/testthat.R
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,7 @@ if(filter == ""){
filter <- NULL
}
message(gh.action)
if(FALSE){
tests_init("chrome")
}else if(interactive() | (gh.action == "ENABLED")) {
tests_init("firefox")
} else {
tests_init()
}
tests_init()

tests_run(filter=filter)
tests_exit()
221 changes: 105 additions & 116 deletions tests/testthat/helper-HTML.R
Original file line number Diff line number Diff line change
@@ -1,116 +1,105 @@
#' Apply `animint2dir` to a list ggplots and extract the (rendered) page source via RSelenium
#'
#' @param plotList A named list of ggplot2 objects
animint2HTML <- function(plotList) {
unlink("animint-htmltest", recursive=TRUE)
res <- animint2dir(plotList, out.dir = "animint-htmltest",
open.browser = FALSE)
remDr$refresh()
Sys.sleep(1)
res$html <- getHTML()
## [ERROR - 2019-06-05T18:30:55.358Z] Session [e7c4e500-871e-11e9-a9b5-8dab1f486f7e] - page.onError - msg: TypeError: 'undefined' is not an object (evaluating 's_info.type')
## [ERROR - 2019-06-05T18:30:55.360Z] Session [e7c4e500-871e-11e9-a9b5-8dab1f486f7e] - page.onError - stack:
## (anonymous function) (http://localhost:4848/animint-htmltest/animint.js:2535)
## print(sapply(res$selectors, "[[", "type"))
res
}
getHTML <- function(){
XML::htmlParse(remDr$getPageSource(), asText = TRUE)
}
#' Initiate external processes necessary for running tests.
#'
#' Initiates a local file server and remote driver.
#'
#' @param browserName Name of the browser to use for testing.
#' See ?RSelenium::remoteDriver for details.
#' @param dir character string with the path to animint's source code. Defaults to current directory
#' @param port port portnumber used for local file server
#' @param ... list of additional options passed onto RSelenium::remoteDriver
#' @return invisible(TRUE)
#' @export
#' @seealso \link{tests_run}
#'
tests_init <- function(browserName = "phantomjs", dir = ".", port = 4848, ...) {
# try to exit out of previously initated processes
ex <- tests_exit()
# start a non-blocking local file server under path/to/animint/tests/testhat
testPath <- find_test_path(dir)
run_servr(port = port, directory = testPath)
# animint tests are performed in path/to/testthat/animint-htmltest/
# note this path has to match the out.dir argument in animint2THML...
testDir <- file.path(testPath, "animint-htmltest")
# if the htmltest directory exists, wipe clean, then create an empty folder
unlink(testDir, recursive = TRUE)
# start-up remote driver
remotePort <- 4444L
OS <- Sys.info()[['sysname']]
if(OS == "Linux") {
animint_server <- "localhost"
}
if(OS == "Windows" || OS == "Darwin") {
animint_server <- "host.docker.internal"
}
if(browserName == "chrome"){
chrome.session <- chromote::ChromoteSession$new()
chrome.session$view()
chrome.session$refresh <- function()chrome.session$Page$reload()
chrome.session$navigate <- function(u){
chrome.session$Page$navigate(u)
}
chrome.session$getPageSource <- function(){
doc <- chrome.session$DOM$getDocument()
chrome.session$DOM$getOuterHTML(doc$root$nodeId)$outerHTML
}
remDr <<- chrome.session
}else{
if (browserName == "phantomjs") {
message("Starting phantomjs binary. To shut it down, run: \n pJS$stop()")
pJS <<- wdman::phantomjs(
port = remotePort,
phantomver = "latest"
)
## Give time for phantomjs binary to start
animint_server <- "localhost"
Sys.sleep(8)
} else if(browserName=="firefox"){
## If using firefox, you'll need to run selenium-firefox docker image in order to make it work correctly.
## We're using docker to avoid version incompatibility issues.
message("You need to run selenium docker image(selenium/standalone-firefox:2.53.0) as specified in docs(https://github.com/tdhock/animint2/wiki/Testing). \nNote: Ignore if already running.")
}else stop("unrecognized browser name")
remDr <<- RSelenium::remoteDriver(
port = remotePort,
browser = browserName,
)
## wait for the remote driver to start-up
Sys.sleep(6)
remDr$open(silent = TRUE)
## some tests don't run reliably with phantomjs (see tests-widerect.R)
Sys.setenv("ANIMINT_BROWSER" = browserName)
## wait a maximum of 30 seconds when searchinsg for elements.
remDr$setTimeout(type = "implicit", milliseconds = 30000)
## wait a maximum of 30 seconds for a particular type of operation to execute
remDr$setTimeout(type = "page load", milliseconds = 30000)
## if we navigate to localhost:%s/htmltest directly, some browsers will
## redirect to www.htmltest.com. A 'safer' approach is to navigate, then click.
}
remDr$navigate(sprintf("http://%s:%s/animint-htmltest/", animint_server, port))
## Why not just navigate to the right URL to begin with?
## e <- remDr$findElement("xpath", "//a[@href='animint-htmltest/']")
## e$clickElement()
invisible(TRUE)
}
## get both horizontal and vertical grid lines
get_grid_lines <- function(html, p_name, grid_class){
path.i <-
'//svg[@id="plot_%s"]//g[@class="grid_%s"]//g[@class="%s"]//line'
path.hor <- sprintf(path.i, p_name, grid_class, "y")
path.vert <- sprintf(path.i, p_name, grid_class, "x")
nodes_h <- getNodeSet(html, path.hor)
nodes_v <- getNodeSet(html, path.vert)
# take x1, x2, y1, y2 values only
attr_h <- sapply(nodes_h, xmlAttrs)[1:4, ]
attr_v <- sapply(nodes_v, xmlAttrs)[1:4, ]
attr_h <- apply(attr_h, 2, as.numeric)
attr_v <- apply(attr_v, 2, as.numeric)
return(list(hor=attr_h, vert=attr_v))
}
#' Apply `animint2dir` to a list ggplots and extract the (rendered) page source via RSelenium
#'
#' @param plotList A named list of ggplot2 objects
animint2HTML <- function(plotList) {
unlink("animint-htmltest", recursive=TRUE)
res <- animint2dir(plotList, out.dir = "animint-htmltest",
open.browser = FALSE)
remDr$refresh()
Sys.sleep(2)
res$html <- getHTML()
## [ERROR - 2019-06-05T18:30:55.358Z] Session [e7c4e500-871e-11e9-a9b5-8dab1f486f7e] - page.onError - msg: TypeError: 'undefined' is not an object (evaluating 's_info.type')
## [ERROR - 2019-06-05T18:30:55.360Z] Session [e7c4e500-871e-11e9-a9b5-8dab1f486f7e] - page.onError - stack:
## (anonymous function) (http://localhost:4848/animint-htmltest/animint.js:2535)
## print(sapply(res$selectors, "[[", "type"))
res
}
getHTML <- function(){
XML::htmlParse(remDr$getPageSource(), asText = TRUE)
}
#' Initiate external processes necessary for running tests.
#'
#' Initiates a local file server and remote driver.
#'
#' @param browserName Name of the browser to use for testing.
#' See ?RSelenium::remoteDriver for details.
#' @param dir character string with the path to animint's source code. Defaults to current directory
#' @param port port portnumber used for local file server
#' @param ... list of additional options passed onto RSelenium::remoteDriver
#' @return invisible(TRUE)
#' @export
#' @seealso \link{tests_run}
#'
tests_init <- function(dir = ".", ...) {
# try to exit out of previously initated processes
ex <- tests_exit()
# start a non-blocking local file server under path/to/animint/tests/testhat
testPath <- find_test_path(dir)
run_servr(port = 4848, directory = testPath)
# animint tests are performed in path/to/testthat/animint-htmltest/
# note this path has to match the out.dir argument in animint2THML...
testDir <- file.path(testPath, "animint-htmltest")
# if the htmltest directory exists, wipe clean, then create an empty folder
unlink(testDir, recursive = TRUE)
chrome.session <- chromote::ChromoteSession$new()
chrome.session$view()
chrome.session$refresh <- function(){
## from https://github.com/rstudio/chromote?tab=readme-ov-file#loading-a-page-reliably
prom <- chrome.session$Page$loadEventFired(wait_ = FALSE) # Get the promise for the loadEventFired
chrome.session$Page$reload()
# Block until p resolves
chrome.session$wait_for(prom)
}
chrome.session$navigate <- function(u){
chrome.session$Page$navigate(u)
}
chrome.session$getPageSource <- function(){
doc <- chrome.session$DOM$getDocument()
chrome.session$DOM$getOuterHTML(doc$root$nodeId)$outerHTML
}
remDr <<- chrome.session
remDr$navigate("http://localhost:4848/animint-htmltest/")
invisible(TRUE)
}
## get both horizontal and vertical grid lines
get_grid_lines <- function(html, p_name, grid_class){
path.i <-
'//svg[@id="plot_%s"]//g[@class="grid_%s"]//g[@class="%s"]//line'
path.hor <- sprintf(path.i, p_name, grid_class, "y")
path.vert <- sprintf(path.i, p_name, grid_class, "x")
nodes_h <- getNodeSet(html, path.hor)
nodes_v <- getNodeSet(html, path.vert)
# take x1, x2, y1, y2 values only
attr_h <- sapply(nodes_h, xmlAttrs)[1:4, ]
attr_v <- sapply(nodes_v, xmlAttrs)[1:4, ]
attr_h <- apply(attr_h, 2, as.numeric)
attr_v <- apply(attr_v, 2, as.numeric)
return(list(hor=attr_h, vert=attr_v))
}
### The hex codes come from
### https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values
key2hex_code <- c(
Backspace="08",
tdhock marked this conversation as resolved.
Show resolved Hide resolved
Enter="0D",
ArrowDown="28")
### https://chromedevtools.github.io/devtools-protocol/tot/Input/ says
### that dispatchKeyEvent() requires DOM key codes (in decimal) for
### the windowsVirtualKeyCode and nativeVirtualKeyCode arguments.
key2dec_code <- structure(
strtoi(key2hex_code,base=16),
names=names(key2hex_code))
# Function to send a key event
sendKey <- function(key) {
stopifnot(is.character(key))
for (type in c("keyDown", "keyUp")) {
remDr$Input$dispatchKeyEvent(type = type, key = key, code = key, windowsVirtualKeyCode = key2dec_code[[key]], nativeVirtualKeyCode = key2dec_code[[key]])
}
}

getClassBound <- function(geom.class, position){
script.txt <- sprintf(
'document.getElementsByClassName("%s")[0].getBoundingClientRect().%s',
geom.class, position)
Sys.sleep(2)
runtime_evaluate(script=script.txt)
}
Loading
Loading