Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 8 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
# shinytest2 (development version)

## Breaking changes

## New features

## Bug / Improvements

* Set the directory to the Shiny App directory before starting the background R process. This allows for local `.Rprofile` and `.Renviron` files to be found naturally. (#275)

* Fixed bug where `compare_screenshot_threshold()` did not safe guard against errors thrown by `screenshot_max_difference()`. (#276)

* Fixed bug where preview overflow did not have length of 1. (@cpsievert #291)

* Better support for saving global variables for a Shiny server function (#307)


# shinytest2 0.2.0

Expand Down
1 change: 1 addition & 0 deletions R/app-driver-start.R
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ app_start_shiny <- function(
"!DEBUG finding shiny port"
## Try to read out the port. Try 5 times/sec, until timeout.
max_i <- floor(load_timeout / 1000 * 5)
err_lines <- ""
for (i in seq_len(max_i)) {
err_lines <- readLines(p$get_error_file())

Expand Down
7 changes: 5 additions & 2 deletions R/save-app.R
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ app_data <- function(app) {
server <- app$serverFuncSource()
globals <- app_server_globals(server)

data <- globals$globals
data <- list(
globals = globals$globals
)
# data <- globals$globals
data$ui <- environment(app$httpHandler)$ui
# If the app is made from shinyAppDir with a wrapper around the handler...
# See https://github.com/rstudio/shiny/blob/fd7518018cbb2ec0b89960c922e34576d5dbc1e7/R/shinyapp.R#L407
Expand All @@ -39,7 +42,7 @@ app_server_globals <- function(server) {
# https://github.com/HenrikBengtsson/globals/issues/61#issuecomment-731777640
rlang::check_installed("globals", version = "0.14.0")

globals <- globals::globalsOf(server, envir = environment(server), recursive = FALSE)
globals <- globals::globalsOf(server, envir = environment(server), recursive = TRUE)
globals <- globals::cleanup(globals)

# remove globals found in packages
Expand Down
6 changes: 6 additions & 0 deletions inst/internal/app-template.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,10 @@ for (prefix in names(`_data`$resources)) {
shiny::addResourcePath(prefix, `_data`$resources[[prefix]])
}

# cat("attaching globals: ", paste0(names(`_data`$globals), collapse = ", "), "\n", sep = "")

# Assign to global environment so that everything is available to each other
# `list2env(x, envir=globalenv())` is equivalent to multiple calls to `assign(names(x)[[i]], x[[i]], envir = globalenv())`
list2env(`_data`$globals, envir = globalenv()) # nolint

shinyApp(`_data`$ui, `_data`$server)
35 changes: 35 additions & 0 deletions tests/testthat/scripts/issue_295.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
library(shiny)

my_mod_ui <- function(id) {
ns <- NS(id)
tagList(
textInput(ns("name"), "name", "test"),
textOutput(ns("greet"))
)
}

my_mod_server <- function(id) {
moduleServer(id, function(input, output, session) {
output$greet <- renderText(input$name)
})
}

make_app2 <- function(mod_ui, mod_server_gen) {
force(mod_server_gen)
shiny::shinyApp(
shiny::fluidPage(mod_ui),
function(input, output, session) mod_server_gen()
)
}

app <- make_app2(
my_mod_ui("test"),
function() {
my_mod_server("test")
}
)

driver <- shinytest2::AppDriver$new(app)

# Keep here to print to `stdout`
print(driver$get_logs())
49 changes: 49 additions & 0 deletions tests/testthat/scripts/issue_303.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Saving an app needs all globally defined objects
# See: https://github.com/rstudio/shinytest2/issues/303

# The code below has always worked within `{testthat}` testing
# However, it would break if run in the R console
# https://github.com/rstudio/shinytest2/issues/303#issuecomment-1377950984

# It does not work if run in a `callr::r{_bg}()` process as that is not executed the in their respective global environments
# The only way this error is found is if the code is executed in the global env
# Using `callr::rscript()` requires `{shinytest2}` to be installed
# Therefore, only test on CI as the package is not installed for CRAN testing

# driver$get_logs()
#> {shiny} R stderr ----------- Warning: Error in server: object 'foo' not found
#> {shiny} R stderr ----------- 60: server [dean.R#11]
#> {shiny} R stderr ----------- 14: <Anonymous>
#> {shiny} R stderr ----------- 12: <Anonymous>
#> {shiny} R stderr ----------- 11: <Anonymous>
#> {shiny} R stderr ----------- 10: do.call
#> {shiny} R stderr ----------- 9: saveRDS
#> {shiny} R stderr ----------- 8: withCallingHandlers
#> {shiny} R stderr ----------- 7: doTryCatch
#> {shiny} R stderr ----------- 6: tryCatchOne
#> {shiny} R stderr ----------- 5: tryCatchList
#> {shiny} R stderr ----------- 2: tryCatchList
#> {shiny} R stderr ----------- 1: tryCatch
#> {shiny} R stderr ----------- Error in server(...) : object 'foo' not found

foo <- 5
app <- local({

foo3 <- 19

shiny::shinyApp(
ui <- shiny::fluidPage(shiny::textOutput("foo")),
server = function(input, output, session) {
foo3
foo2 <- foo + 1
output$foo <- shiny::renderText({
foo2
})
}
)
})

driver <- shinytest2::AppDriver$new(app)

# Keep here to print to `stdout`
print(driver$get_logs())
27 changes: 27 additions & 0 deletions tests/testthat/scripts/pr_307.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
library(shiny)

mod_ui <- function(id) {
ns <- NS(id)
textOutput(ns("foo"))
}

mod_server <- function(id) {
moduleServer(
id,
function(input, output, session) {
output$foo <- renderText("bar")
}
)
}

app <- shinyApp(
mod_ui("test"),
function(input, output, session) {
mod_server("test")
}
)

driver <- shinytest2::AppDriver$new(app)

# Keep here to print to `stdout`
print(driver$get_logs())
44 changes: 44 additions & 0 deletions tests/testthat/test-save-app.R
Original file line number Diff line number Diff line change
@@ -1,5 +1,49 @@
require("shiny", quietly = TRUE, character.only = TRUE)

# App from: https://github.com/rstudio/shinytest2/issues/303#issuecomment-1377950984
test_that("Make sure global vars are set - issue303", {
# Only run on CI. CRAN requires package to be installed to run `callr::rscript()
skip_if(!on_ci(), "Only run on CI")

# Run the script in a global environment that does not polute this global environment
p <- callr::rscript("scripts/issue_303.R", show = FALSE)
expect_equal(
any(grepl("object 'foo' not found", p$stdout, fixed = TRUE)),
FALSE
)
expect_equal(
any(grepl("object 'foo3' not found", p$stdout, fixed = TRUE)),
FALSE
)
})

# App from: https://github.com/rstudio/shinytest2/pull/307#issuecomment-1381391531
test_that("Make sure global vars are set - pr307", {
# Only run on CI. CRAN requires package to be installed to run `callr::rscript()
skip_if(!on_ci(), "Only run on CI")

# Run the script in a global environment that does not polute this global environment
p <- callr::rscript("scripts/pr_307.R", show = FALSE)
expect_equal(
any(grepl("could not find function", p$stdout, fixed = TRUE)),
FALSE
)
})

# App from: https://github.com/rstudio/shinytest2/pull/307#issuecomment-1381391531
test_that("Make sure global vars are set - issue295", {
# Only run on CI. CRAN requires package to be installed to run `callr::rscript()
skip_if(!on_ci(), "Only run on CI")

# Run the script in a global environment that does not polute this global environment
p <- callr::rscript("scripts/issue_295.R", show = FALSE)
expect_equal(
any(grepl("could not find function", p$stdout, fixed = TRUE)),
FALSE
)
})


test_that("Saving an app has the right context", {
n <- 5
shiny_app <- shinyApp(
Expand Down