Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
2dae122
Commit code before gutting
schloerke Sep 24, 2024
7c70eb6
commit code before computer breaks
schloerke Dec 11, 2024
918664e
Merge branch 'main' into pkg_test_env
schloerke Feb 10, 2025
5167a2d
Merge branch 'main' into pkg_test_env
schloerke Feb 10, 2025
bf57461
Add pkgload as new dep
schloerke Feb 10, 2025
1fcf20a
Update test files
schloerke Feb 10, 2025
e89fdd2
Commit changes before chopping code
schloerke Feb 10, 2025
bbca165
Merge branch 'pkg_test_env' of https://github.com/rstudio/shinytest2 …
schloerke Feb 10, 2025
0d6bf0a
Do not enable the local package's namespace when testing
schloerke Feb 10, 2025
767f7ef
Remove old setup code
schloerke Feb 10, 2025
eb95f71
Be explicit on return value
schloerke Feb 10, 2025
67d8fd8
Update comment for `load_package`
schloerke Feb 10, 2025
b50d8d0
Clean up loading code to only load exported source fns
schloerke Feb 10, 2025
13e5a58
Move variant folders for more robust testing
schloerke Feb 10, 2025
6c7fa51
Update to latest snaps
schloerke Feb 10, 2025
1a5fee0
Update local variable name used for testing
schloerke Feb 11, 2025
db958d3
Do not attach local package. Only add it to the search path for local…
schloerke Feb 11, 2025
a1a8045
Update snaps
schloerke Feb 11, 2025
58c7b59
lint
schloerke Feb 11, 2025
4feb531
Fix sanity check for testing (now that we're trying to compile the pa…
schloerke Feb 11, 2025
eea9330
Add vanilla golem app to test
schloerke Feb 11, 2025
1c8879d
temp. please vet files
schloerke Mar 25, 2025
6d60117
Merge branch 'main' into pkg_test_env
schloerke Apr 9, 2025
2309781
Merge branch 'main' into pkg_test_env
schloerke Nov 14, 2025
e9d1419
Commit before gutting code
schloerke Nov 17, 2025
cc32a65
Remove rhino renv lib
schloerke Nov 17, 2025
33b5882
Screenshot updates
schloerke Nov 17, 2025
146fd37
`usethis::use_tidy_description()` (GitHub Actions)
schloerke Nov 17, 2025
a179bf3
Updates
schloerke Nov 18, 2025
c6d79a3
Better app function support
schloerke Nov 18, 2025
2c80b30
Test a rhino, golem, and local pkg
schloerke Nov 18, 2025
61b0b13
`usethis::use_tidy_description()` (GitHub Actions)
schloerke Nov 18, 2025
f9d9d94
Delete 001.json
schloerke Nov 18, 2025
8bbd2b4
Merge branch 'pkg_test_env' of https://github.com/rstudio/shinytest2 …
schloerke Nov 18, 2025
1a94d3f
Only disable R folder sourcing when pkg dir is the same as the app dir
schloerke Nov 18, 2025
70266ac
Double check golem support
schloerke Nov 18, 2025
329f71b
Scoping
schloerke Nov 18, 2025
410dad3
Function can return an app object
schloerke Nov 18, 2025
84fddff
docs and news entry
schloerke Nov 18, 2025
b3dacc2
Get rid of cran notes / warnings
schloerke Nov 18, 2025
3c4a090
lints
schloerke Nov 18, 2025
dba6cc8
Do not do test on windows or CRAN
schloerke Nov 18, 2025
1e88c22
typo
schloerke Nov 18, 2025
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
1 change: 1 addition & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ _\.new\.png$

^tests/testthat/migrate-apps$
^tests/testthat/apps$
^tests/testthat/pkgs$
^CRAN-SUBMISSION$
^_dev$
6 changes: 4 additions & 2 deletions .github/workflows/test-actions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@ jobs:

- uses: r-lib/actions/setup-r-dependencies@v2
with:
extra-packages:
"local::."
needs: |
shinytest2-testing
extra-packages: |
local::.

# ## Suggested usage
# - name: Test app
Expand Down
5 changes: 4 additions & 1 deletion .lintr
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@ exclusions: list(
"inst/gha/audit-app.R" = list(
"object_usage_linter" = 81
),
"R/cpp11.R"
"R/cpp11.R",
"tests/testthat/pkgs/golem/R/run_app.R",
"vignettes/use-package.Rmd",
"tests/testthat/pkgs/"
)
7 changes: 6 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,22 @@ Imports:
jsonlite,
lifecycle,
pingr,
pkgload,
R6 (>= 2.4.0),
rlang (>= 1.0.0),
rmarkdown,
shiny,
withr
Suggests:
box,
deSolve,
diffobj,
ggplot2,
golem,
knitr,
plotly,
png,
rhino,
rstudioapi,
shinytest (>= 1.5.1),
shinyvalidate (>= 0.1.2),
Expand All @@ -55,9 +59,10 @@ Suggests:
vdiffr (>= 1.0.0)
LinkingTo:
cpp11
VignetteBuilder:
VignetteBuilder:
knitr
Config/Needs/check: rstudio/shiny, bslib
Config/Needs/shinytest2-testing: decor
Config/Needs/website: pkgdown, tidyverse/tidytemplate
Config/testthat/edition: 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,5 +1,9 @@
# shinytest2 (development version)

* Added support for local package development for the background Shiny App process in `AppDriver$new(app_dir=)`. In the background test R process, any `library(<pkg>)` or `require(<pkg>)` call will automatically execute `pkgload::load_all()` to load the local R package's source code. Installing the package before testing is no longer required! (#402).

* Added support for function execution for `AppDriver$new(app_dir=)`. You must run the App or document yourself. Similar to `{mirai}`, all packages must be `library()`'d or `require()`'d again as the function is being ran in the background R process (#402).

* Fixed internal bug where `{testthat}` v3.3.0 changed expectation behavior for screenshot snapshots within `App$expect_values()` (#418).

# shinytest2 0.4.1
Expand Down
99 changes: 78 additions & 21 deletions R/app-driver-dir.R
Original file line number Diff line number Diff line change
@@ -1,10 +1,47 @@

app_set_dir <- function(
self, private,
self,
private,
app_dir
) {
ckm8_assert_app_driver(self, private)

if (is.function(app_dir)) {
# package_path <- tryCatch(pkgload::pkg_path(), error = function(e) NULL)
package_name <- tryCatch(pkgload::pkg_name(), error = function(e) NULL)

if (
!is.null(package_name) &&
rlang::env_label(environment(app_dir)) ==
rlang::env_label(pkgload::pkg_ns())
) {
# If the function is from the local package, ensure the package is loaded
# Make a new function that first loads the package, then runs the original function
message(
"Upgrading `app_dir` function to load dev package: ",
package_name
)

app_fn <- app_dir
app_dir <- function() {}
rlang::fn_body(app_dir) <- rlang::expr({
# Run app with dev package loaded
# `library()` shimmed in app driver start
library(!!package_name, character.only = TRUE)

.pkg_ns <- rlang::ns_env(!!package_name)
.dev_pkg_run_app <- !!app_fn
environment(.dev_pkg_run_app) <- .pkg_ns

.dev_pkg_run_app()
})
rlang::fn_env(app_dir) <- globalenv()
}

# Set app function
private$dir <- app_dir
return()
}

app_dir <- app_dir_value(app_dir)

if (!fs::dir_exists(app_dir)) {
Expand All @@ -16,7 +53,8 @@ app_set_dir <- function(
paste0("\"", cur_dir, "\"")
}
app_abort(
self, private,
self,
private,
c(
"`app_dir` must be an existing directory",
"i" = paste0("Received: ", cur_dir)
Expand All @@ -25,25 +63,33 @@ app_set_dir <- function(
}

shiny_app_and_rmd_abort <- function() {
app_abort(self, private, c(
"`app_dir` must be a directory containing:",
"",
"*" = "an `./app.R` Shiny application",
"",
" " = "or",
"",
"*" = "a Shiny R Markdown file",
"*" = "a `./server.R` Shiny server",
"",
"i" = "If a Shiny R Markdown document is found, it will be the prefered document.",
"i" = "`./app.R` is not compatible with Shiny R Markdown files."
))
app_abort(
self,
private,
c(
"`app_dir` must be a directory containing:",
"",
"*" = "an `./app.R` Shiny application",
"",
" " = "or",
"",
"*" = "a Shiny R Markdown file",
"*" = "a `./server.R` Shiny server",
"",
"i" = "If a Shiny R Markdown document is found, it will be the prefered document.",
"i" = "`./app.R` is not compatible with Shiny R Markdown files."
)
)
}
shiny_app_and_server_abort <- function() {
app_abort(self, private, c(
"`app_dir` contains both `app.R` and `server.R`. Unintented behavior may occur.",
"!" = "Please either use `app.R` or `server.R`, but not both."
))
app_abort(
self,
private,
c(
"`app_dir` contains both `app.R` and `server.R`. Unintented behavior may occur.",
"!" = "Please either use `app.R` or `server.R`, but not both."
)
)
}

if (!fs::dir_exists(app_dir)) {
Expand Down Expand Up @@ -74,6 +120,10 @@ app_set_dir <- function(

app_get_dir <- function(self, private) {
ckm8_assert_app_driver(self, private)
if (is.function(private$dir)) {
return(private$dir)
}

as.character(private$dir)
}

Expand All @@ -82,6 +132,9 @@ app_dir_has_rmd <- function(self, private, app_dir = missing_arg()) {
ckm8_assert_app_driver(self, private)
app_dir <- self$get_dir()
}
if (is.function(app_dir)) {
return(FALSE)
}
length(app_dir_rmd(app_dir = app_dir)) >= 1
}
app_dir_rmd <- function(self, private, app_dir = rlang::missing_arg()) {
Expand All @@ -90,7 +143,11 @@ app_dir_rmd <- function(self, private, app_dir = rlang::missing_arg()) {
app_dir <- self$get_dir()
}
# Similar to https://github.com/rstudio/rmarkdown/issues/2236
docs <- fs::dir_ls(app_dir, regexp = "^[^_].*\\.[Rrq][Mm][Dd]$", type = "file")
docs <- fs::dir_ls(
app_dir,
regexp = "^[^_].*\\.[Rrq][Mm][Dd]$",
type = "file"
)

if (length(docs) >= 1) {
docs <- Filter(docs, f = function(doc_path) {
Expand Down
40 changes: 28 additions & 12 deletions R/app-driver-expect-values.R
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,32 @@ app_get_single_ioe <- function(
)
}

if (input_is_provided) ckm8_assert_single_string(input) else if (
output_is_provided
)
ckm8_assert_single_string(output) else if (export_is_provided)
ckm8_assert_single_string(export) else
if (input_is_provided) {
ckm8_assert_single_string(input)
} else if (output_is_provided) {
ckm8_assert_single_string(output)
} else if (export_is_provided) {
ckm8_assert_single_string(export)
} else {
app_abort(self, private, "Missing ioe type", .internal = TRUE)
}

type <-
if (input_is_provided) "input" else if (output_is_provided)
"output" else if (export_is_provided) "export"
if (input_is_provided) {
"input"
} else if (output_is_provided) {
"output"
} else if (export_is_provided) {
"export"
}
name <-
if (input_is_provided) input else if (output_is_provided) output else if (
export_is_provided
)
if (input_is_provided) {
input
} else if (output_is_provided) {
output
} else if (export_is_provided) {
export
}

list(
input = input,
Expand Down Expand Up @@ -307,8 +318,13 @@ app_get_shiny_test_url <- function(
}

q_string <- function(group, value) {
if (isTRUE(value)) paste0(group, "=1") else if (is.character(value))
paste0(group, "=", paste(value, collapse = ",")) else ""
if (isTRUE(value)) {
paste0(group, "=1")
} else if (is.character(value)) {
paste0(group, "=", paste(value, collapse = ","))
} else {
""
}
}
paste(
private$shiny_test_url,
Expand Down
16 changes: 14 additions & 2 deletions R/app-driver-initialize.R
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,18 @@ app_initialize_ <- function(
} else {
"!DEBUG starting shiny app from path"
self$log_message("Starting Shiny app")
app_set_dir(self, private, app_dir)
if (is.function(app_dir)) {
if (length(shiny_args) != 0) {
app_abort(
self,
private,
"When `app_dir=` is a function, `shiny_args=` must be empty"
)
}
app_set_dir(self, private, app_dir)
} else {
app_set_dir(self, private, app_dir)
}

app_start_shiny(
self,
Expand Down Expand Up @@ -173,8 +184,9 @@ app_initialize_ <- function(
self$get_chromote_session(),
"Shiny.shinyapp.config.workerId"
)$result$value
if (identical(private$shiny_worker_id, ""))
if (identical(private$shiny_worker_id, "")) {
private$shiny_worker_id <- NA_character_
}

private$shiny_test_url <- chromote_eval(
self$get_chromote_session(),
Expand Down
Loading
Loading