-
Notifications
You must be signed in to change notification settings - Fork 55
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
Take screenshot of element #260
Comments
I want to generate screenshots of input elements, and generally of layouts. (This isn't for testing rather than generating screenshots for a book so I don't need to iteratively figure out the width and height) |
Have you tried webshot with CSS selectors? https://github.com/wch/webshot#usage (see also https://github.com/rstudio/webshot2) |
How would I point webshot to a shiny app and then tell it to do stuff? I'd rather not reimplement all the shinytest features that I need. |
You could do it in a similar way to this: callr::r_bg(function() {
shiny::runExample("01_hello", port = 8001)
})
webshot::webshot("http://localhost:8001", selector = ".shiny-input-container") |
I think it would be better to bake directly into shinytest. It doesn't seem like it would be that hard to implement. |
Here's my (failed) attempt: https://github.com/jcheng5/shiny-book/blob/master/common.R |
@jcheng5 that's mostly my code!! |
Oh 🤣 I swear I did something similar! (And that it didn't quite work) |
From the |
@wch could you please give me some hint as to how to take a screenshot of an element given a WebDriver? |
Here's what I've come up with: library(shiny)
testApp <- function(ui, server = NULL) {
if (is.null(server)) {
server <- function(input, output, session) {}
}
app_dir <- tempfile()
dir.create(app_dir)
saveRDS(ui, file.path(app_dir, "ui.rds"))
saveRDS(server, file.path(app_dir, "server.rds"))
app <- rlang::expr({
library(shiny)
ui <- readRDS("ui.rds")
server <- readRDS("server.rds")
shinyApp(ui, server)
})
cat(rlang::expr_text(app), file = file.path(app_dir, "app.R"))
shinytest::ShinyDriver$new(app_dir)
}
ui <- fluidPage(
div(class = "foo", "Hello!"),
"Some other text"
)
sd <- testApp(ui)
tmp <- tempfile(fileext = ".png")
sd$takeScreenshot(tmp)
# Find bounding rectangle of target div
wd <- sd$.__enclos_env__$private$web
obj <- wd$findElement(".foo")
rect <- obj$getRect()
# Clip to the bounding rectangle
img <- png::readPNG(tmp)
img <- img[seq(rect$y, rect$y + rect$height), seq(rect$x, rect$x + rect$width), 1:4]
png::writePNG(img, "out.png")
browseURL("out.png")
unlink(img) |
Thanks! |
Here's what I ended up with: show_raster <- function(x) {
withr::local_par(list(bg = "grey90"))
plot(as.raster(x))
}
app_wait <- function(app) {
app$waitFor("!$('html').first().hasClass('shiny-busy')")
}
screenshot_element <- function(app, id, parent = FALSE) {
path <- tempfile()
app$takeScreenshot(path)
png <- png::readPNG(path )
element <- app$findElement(paste0("#", id))
if (parent) {
element <- element$findElement(xpath = "..")
}
pos <- element$getRect()
pos$x2 <- pos$x + pos$width
pos$y2 <- pos$y + pos$height
png[pos$y:pos$y2, pos$x:pos$x2, ]
}
app <- shinytest::ShinyDriver$new("apps/shiny-test")
app$setInputs(x = 10)
app$waitFor("!$('html').first().hasClass('shiny-busy')")
snap <- screenshot_element(app, "x", parent = TRUE)
show_raster(snap)
path2 <- tempfile()
png::writePNG(snap, path2) |
Probably should be screenshot method for Widget class. |
I explored making this a method of the Widget class, but that would require passing the ShinyDriver object to the Widget, which would require changing it's exported interface. Includes refactoring of ShinyDriver tests to use single app. Fixes #260.
I explored making this a method of the Widget class, but that would require passing the ShinyDriver object to the Widget, which would require changing it's exported interface. Includes refactoring of ShinyDriver tests to use single app. Fixes #260
It would be very useful to be able to take a screenshot of an element, i.e. find the element, compute it's bounds, and then only screenshot that region.
The text was updated successfully, but these errors were encountered: