### Launch App and Recorder Source: https://rstudio.github.io/shinytest2/articles/use-application-audit.html Example of launching a Shiny app in the background and starting the recorder. Ensure the app path is correct. ```R target <- start_r_bg(shiny_bg, path = system.file("vig-apps/non-optimized-app/", package = "shinytest2")) # Listening on 127.0.0.1:3515 recorder <- start_r_bg(recorder_bg) # Listening on 127.0.0.1:8600 ``` -------------------------------- ### Example Usage of AppDriver$get_logs() Source: https://rstudio.github.io/shinytest2/reference/AppDriver.html Demonstrates how to initialize an AppDriver and then retrieve its logs. This example shows the typical output format and log sources. ```r app1 <- AppDriver$new(system.file("examples/01_hello", package = "shiny")) app1$get_logs() ``` -------------------------------- ### Example Screenshot File Paths Source: https://rstudio.github.io/shinytest2/reference/compare_screenshot_threshold.html Sets up example file paths for screenshot comparison using files from the 'shinytest2' package. ```r img_folder <- system.file("example/imgs/", package = "shinytest2") slider_old <- fs::path(img_folder, "slider-old.png") slider_new <- fs::path(img_folder, "slider-new.png") ``` -------------------------------- ### Example of recording a test Source: https://rstudio.github.io/shinytest2/reference/record_test.html A basic example showing how to invoke the recorder for a specific application path. ```R if (FALSE) { # \dontrun{ record_test("path/to/app") } # } ``` -------------------------------- ### Replace renv setup with r-dependencies setup Source: https://rstudio.github.io/shinytest2/articles/use-ci.html Modify your check-app.yaml to use setup-r-dependencies instead of setup-renv for package installation. ```yaml - uses: r-lib/actions/setup-r-dependencies@v2 ``` -------------------------------- ### Initialize AppDriver Instances Source: https://rstudio.github.io/shinytest2/reference/AppDriver.html Examples of creating AppDriver objects from the current directory or a specific path. ```R if (FALSE) { # \dontrun{ # Create an AppDriver from the Shiny app in the current directory app <- AppDriver() # Create an AppDriver object from a different Shiny app directory example_app <- system.file("examples/01_hello", package = "shiny") app <- AppDriver(example_app) # Expect consistent inital values app$expect_values() } # } ``` -------------------------------- ### Install shinytest2 from GitHub Source: https://rstudio.github.io/shinytest2 Install the development version of the shinytest2 package from GitHub using devtools. ```r # install.packages("devtools") devtools::install_github("rstudio/shinytest2") ``` -------------------------------- ### Initialize AppDriver and Log Messages Source: https://rstudio.github.io/shinytest2/reference/AppDriver.html Demonstrates creating an AppDriver instance from a package example and logging messages during test execution. ```R \dontrun{ app_path <- system.file("examples/01_hello", package = "shiny") app <- AppDriver$new(app_path) app$log_message("Setting bins to smaller value") app$set_inputs(bins = 10) app$get_logs() } ``` -------------------------------- ### Get a downloadable file with get_download Source: https://rstudio.github.io/shinytest2/reference/AppDriver.html Demonstrates how to trigger a file download and retrieve the local file path. ```R AppDriver$get_download(output, filename = NULL) ``` ```R \dontrun{ app_path <- system.file("examples/10_download", package = "shiny") app <- AppDriver$new(app_path) # Get rock.csv as a tempfile app$get_download("downloadData") #> [1] "/TEMP/PATH/rock.csv" # Get rock.csv as a "./myfile.csv" app$get_download("downloadData", filename = "./myfile.csv") #> [1] "./myfile.csv" } ``` -------------------------------- ### Install shinytest2 from CRAN Source: https://rstudio.github.io/shinytest2 Install the released version of the shinytest2 package from CRAN. ```r install.packages("shinytest2") ``` -------------------------------- ### Start Shiny Recorder Background Process Source: https://rstudio.github.io/shinytest2/articles/use-application-audit.html Defines a function to start the shinytest2 recording session in a background R process. Ensure the target app URL and port are correctly specified. ```R recorder_bg <- function(port) { shinyloadtest::record_session( target_app_url = sprintf("http://127.0.0.1:%s", port), host = "127.0.0.1", port = 8600, output_file = "recording.log", open_browser = FALSE ) } ``` -------------------------------- ### Execute test_app in various contexts Source: https://rstudio.github.io/shinytest2/reference/test_app.html Examples demonstrating how to run tests interactively, within testthat files, and inside package test suites. ```R ## Interactive usage # Test Shiny app in current working directory shinytest2::test_app() # Test Shiny app in another directory path_to_app <- "path/to/app" shinytest2::test_app(path_to_app) ## File: ./tests/testthat.R # Will find Shiny app in "../" shinytest2::test_app() ## File: ./tests/testthat/test-shinytest2.R # Test a shiny application within your own {testthat} code test_that("Testing a Shiny app in a package", { app <- shinytest2::AppDriver$new(path_to_app) # Perform tests with `app`... }) ``` -------------------------------- ### Start AppDriver with Recorder URL Source: https://rstudio.github.io/shinytest2/articles/use-application-audit.html Initializes the AppDriver to connect to the running recorder. Increase load_timeout to prevent 'Shiny app did not become stable' warnings. ```R # Start AppDriver with recorder url chrome <- shinytest2::AppDriver$new("http://127.0.0.1:8600", load_timeout = 15 * 1000) ``` -------------------------------- ### Test Shiny application support environment Source: https://rstudio.github.io/shinytest2/reference/app_support.html Examples demonstrating how to access app-specific helper functions and variables using local_app_support and with_app_support. ```R if (FALSE) { # \dontrun{ # Example 1: Basic usage with local_app_support() # File structure: # ./tests/testthat/apps/myapp/R/utils.R (contains: n <- 42) # ./tests/testthat/test-utils.R test_that("Can access support environment", { expect_false(exists("n")) shinytest2::local_app_support(test_path("apps/myapp")) expect_equal(n, 42) }) # After test completes, n is automatically removed # Example 2: Using with_app_support() for explicit scoping test_that("Can access support environment", { expect_false(exists("n")) shinytest2::with_app_support(test_path("apps/myapp"), { expect_equal(n, 42) }) expect_false(exists("n")) # n is no longer available }) # Example 3: Testing an app with its support files # File structure: # ./inst/myapps/app1/app.R # ./inst/myapps/app1/R/modules.R (contains: my_module_ui <- function() {...}) # ./tests/testthat/test-app1.R test_that("app1 loads with module support", { expect_false(exists("my_module_ui")) app_dir <- system.file("myapps/app1", package = "mypkg") local_app_support(app_dir) # Now we can access module functions from app1/R/ expect_true(exists("my_module_ui")) # And test the app app <- AppDriver$new(app_dir) app$expect_values() }) } # } ``` -------------------------------- ### Create AppDriver Instance Source: https://rstudio.github.io/shinytest2/reference/AppDriver.html Basic example of creating an AppDriver instance for a Shiny application located in the current directory. ```R \dontrun{ # Create an AppDriver from the Shiny app in the current directory app <- AppDriver() ``` -------------------------------- ### Initialize and unleash a basic horde Source: https://rstudio.github.io/shinytest2/articles/using-monkey-testing.html Create a default gremlins horde and start the monkey test. ```JavaScript const horde = gremlins.createHorde(); horde.unleash(); ``` -------------------------------- ### Start Background R Process Source: https://rstudio.github.io/shinytest2/articles/use-application-audit.html A utility function to start a background R process using callr::r_bg. It includes error handling and waits for the specified port to be available. ```R start_r_bg <- function(fun, path = NULL, port = 3515) { # remove NULL elements args <- Filter(Negate(is.null), list(path = path, port = port)) process <- callr::r_bg( func = fun, args = args, stderr= "", stdout = "" ) while (any(is.na(pingr::ping_port("127.0.0.1", 3515)))) { message("Waiting for Shiny app to start...") Sys.sleep(0.1) } attempt::stop_if_not( process$is_alive(), msg = "Unable to launch the subprocess" ) process } ``` -------------------------------- ### Initialize AppDriver for Testing Source: https://rstudio.github.io/shinytest2/reference/AppDriver.html Initializes an AppDriver instance for testing a Shiny application. Ensure these example lines are performed in a `./tests/testthat` test file for proper snapshot saving. ```r app_path <- system.file("examples/01_hello", package = "shiny") app <- AppDriver$new(app_path, variant = platform_variant()) ``` -------------------------------- ### AppDriver$new() Source: https://rstudio.github.io/shinytest2/reference/AppDriver.html Initializes a new AppDriver object to start a Shiny application in a new R session with a headless browser. ```APIDOC ## AppDriver$new() ### Description Initialize an AppDriver object to start a Shiny app in a new R session, along with a headless browser for simulating user actions. ### Method Constructor ### Parameters #### Request Body - **path** (string) - Optional - Path to the Shiny application directory. - **app** (object) - Optional - A Shiny application object. ### Request Example app <- AppDriver$new(shiny_app) ``` -------------------------------- ### Test sample app in inst/ directory Source: https://rstudio.github.io/shinytest2/articles/use-package.html Example of testing a Shiny application located in `inst/sample_app/` within an R package. It demonstrates initializing `AppDriver` with the application directory path and skipping CRAN builds. ```R # File: tests/testthat/test-sample_app.R library(shinytest2) test_that("sample_app works", { # Don't run these tests on the CRAN build servers skip_on_cran() appdir <- system.file(package = "exPackage", "sample_app") app <- AppDriver$new(appdir, name = "sample_app") app$expect_values() }) ``` -------------------------------- ### Initialize shinytest2 Source: https://rstudio.github.io/shinytest2/reference/use_shinytest2.html Initializes shinytest2 with various configurations for testing. This function sets up test runners, setup files, ignores debug screenshots, and adds shinytest2 to package dependencies. ```APIDOC ## POST /use_shinytest2 ### Description Initializes shinytest2 with various configurations for testing. This function sets up test runners, setup files, ignores debug screenshots, and adds shinytest2 to package dependencies. ### Method POST ### Endpoint /use_shinytest2 ### Parameters #### Query Parameters - **app_dir** (string) - Optional - The base directory for the Shiny application. - **runner** (boolean) - Optional - If TRUE, creates a shinytest2 test runner at `./tests/testthat.R`. - **setup** (boolean) - Optional - If TRUE, creates a setup file called `./tests/testthat/setup-shinytest2.R`. - **ignore** (boolean) - Optional - If TRUE, adds entries to `.Rbuildignore` and `.gitignore` to ignore new debug screenshots. - **package** (boolean) - Optional - If TRUE, adds shinytest2 to `Suggests` in the `DESCRIPTION` file. - **quiet** (boolean) - Optional - If TRUE, console output will be suppressed. - **overwrite** (boolean) - Optional - If TRUE, the test file or test runner will be overwritten. ### Request Example ```json { "app_dir": ".", "runner": true, "setup": true, "ignore": true, "package": true, "quiet": false, "overwrite": false } ``` ### Response #### Success Response (200) - **message** (string) - Confirmation message of successful setup. #### Response Example ```json { "message": "shinytest2 initialized successfully." } ``` ``` -------------------------------- ### Test Shiny Bookmarking with AppDriver Source: https://rstudio.github.io/shinytest2/articles/zzz-faq.html This R test demonstrates how to start a background Shiny app, capture its URL, and launch a new AppDriver instance with bookmarking query parameters to test bookmark functionality. ```R test_that("Bookmark works", { # Start local app in the background in test mode bg_app <- shinytest2::AppDriver$new("path/to/shiny/app") # Capture the background app's URL and add appropriate query parameters bookmark_url <- paste0(bg_app$get_url(), "?_inputs_&n=10") # Open the bookmark URL in a new AppDriver object app <- shinytest2::AppDriver$new(bookmark_url) # Run your tests on the bookmarked `app` app$expect_values() }) ``` -------------------------------- ### Get All Application Values Source: https://rstudio.github.io/shinytest2/articles/in-depth.html Retrieves all current input, output, and export values from the application without incrementing the expectation counter. The results can be inspected using str(). ```r vals <- app$get_values() str(vals) #> List of 3 #> $ input :List of 4 #> ..$ action :Classes 'integer', 'shinyActionButtonValue' int 0 #> ..$ checkbox : logi TRUE #> ..$ check_group: chr "1" #> ..$ text : chr "Enter text..." #> $ output:List of 12 #> ..$ action_out : chr "[1] 0\nattr(,"class") [1] "integer" #> "shinyActionButtonValue" #> ..$ checkbox_out : chr "[1] TRUE" #> ..$ check_group_out: chr "[1] \"1\"" #> ..$ text_out : chr "[1] \"Enter text...\"" #> $ export: Named list() ``` -------------------------------- ### AppDriver$get_window_size() and AppDriver$set_window_size() Source: https://rstudio.github.io/shinytest2/articles/z-migration.html Methods to get and set the browser window size. These replace ShinyDriver$getWindowSize() and ShinyDriver$setWindowSize(). ```APIDOC ## AppDriver$get_window_size() and AppDriver$set_window_size() ### Description Methods to get and set the browser window size. `get_window_size()` replaces `ShinyDriver$getWindowSize()`, and `set_window_size(width, height)` replaces `ShinyDriver$setWindowSize(width, height)`. ### Method `AppDriver$get_window_size()` `AppDriver$set_window_size(width, height)` ### Endpoint N/A (Methods within an object) ### Parameters #### `set_window_size` Parameters - **width** (numeric) - Required - The desired width of the window. - **height** (numeric) - Required - The desired height of the window. ### Request Example ```r # Get window size current_size <- app_driver$get_window_size() # Set window size app_driver$set_window_size(width = 1024, height = 768) ``` ### Response #### Success Response (200) for `get_window_size` - **width** (numeric) - The current width of the window. - **height** (numeric) - The current height of the window. #### Response Example for `get_window_size` ```json { "width": 1024, "height": 768 } ``` ``` -------------------------------- ### Basic DESCRIPTION file for Imports Source: https://rstudio.github.io/shinytest2/articles/use-ci.html List all R packages your application directly uses in the Imports field. Latest versions will be installed from CRAN. ```r Imports: shiny, shinytest2 ``` -------------------------------- ### Define a Simple Shiny App Source: https://rstudio.github.io/shinytest2/articles/shinytest2.html This is a basic Shiny application with a text input, an action button, and a text output. It serves as an example for recording tests. ```r library(shiny) ui <- fluidPage( textInput("name", "What is your name?"), actionButton("greet", "Greet"), textOutput("greeting") ) server <- function(input, output, session) { output$greeting <- renderText({ req(input$greet) paste0("Hello ", isolate(input$name), "!") }) } ``` ```r shinyApp(ui, server) ``` -------------------------------- ### GitHub Actions Workflow for Load Testing Source: https://rstudio.github.io/shinytest2/articles/use-application-audit.html A GitHub Actions YAML file to automate load testing. This workflow runs on push and pull requests, installs R and dependencies including shinycannon, executes the load test, and deploys the report to GitHub Pages. ```yaml on: push: branches: [main, master] pull_request: branches: [main, master] name: shiny-loadtest-ci jobs: shiny-loadtest-ci: runs-on: ${{ matrix.config.os }} permissions: contents: write name: ${{ matrix.config.os }} (${{ matrix.config.r }}) strategy: fail-fast: false matrix: config: - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} - {os: ubuntu-latest, r: 'release'} - {os: ubuntu-latest, r: 'oldrel-1'} env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} R_KEEP_PKG_SOURCE: yes steps: - uses: actions/checkout@v2 - uses: r-lib/actions/setup-r@v2 - uses: r-lib/actions/setup-r-dependencies@v2 with: cache-version: 2 extra-packages: | any::shinyloadtest any::lubridate any::DT any::callr any::shinytest2 any::deSolve any::attempt - name: Install shinycannon 💥 run: | sudo bash -c 'apt-get update; apt-get install -y default-jre-headless; apt-get clean; rm -rf /var/lib/apt/lists/*' wget https://github.com/rstudio/shinycannon/releases/download/v1.1.3/shinycannon_1.1.3-dd43f6b_amd64.deb sudo dpkg -i ./*.deb - name: Run load test 🏥 shell: Rscript {0} run: | source("R/audit-app.R") record_loadtest(path = "app.R"); - name: Deploy to GitHub pages 🚀 if: github.event_name != 'pull_request' uses: JamesIves/github-pages-deploy-action@4.1.4 with: clean: false branch: gh-pages folder: public ``` -------------------------------- ### Conditional Chromote Start Attempt Source: https://rstudio.github.io/shinytest2/news/index.html Tests are skipped if `chromote` cannot be started. On Windows CI environments, `chromote` receives an additional attempt to start. ```r chromote::start() ``` -------------------------------- ### Set up shinytest2 infrastructure Source: https://rstudio.github.io/shinytest2 Call use_shinytest2() to create an initial value test file and set up any other necessary infrastructure for shinytest2. ```r shinytest2::use_shinytest2() ``` -------------------------------- ### Interact with Inputs and Click Elements Source: https://rstudio.github.io/shinytest2/reference/AppDriver.html Demonstrates uploading a file, setting input values, and clicking buttons to update the application state. ```R if (FALSE) { # \dontrun{ app_path <- system.file("examples/07_widgets", package = "shiny") app <- AppDriver$new(app_path) tmpfile <- write.csv(cars, "cars.csv") app$upload_file(file1 = tmpfile) cat(app$get_text("#view")) app$set_inputs(dataset = "cars", obs = 6) app$click("update") cat(app$get_text("#view")) } # } ``` -------------------------------- ### Initialize AppDriver Source: https://rstudio.github.io/shinytest2/reference/AppDriver.html Constructor signature for creating a new AppDriver instance. ```R AppDriver$new( app_dir = testthat::test_path("../../"), ..., name = NULL, variant = missing_arg(), seed = NULL, load_timeout = missing_arg(), timeout = missing_arg(), wait = TRUE, screenshot_args = missing_arg(), expect_values_screenshot_args = TRUE, check_names = TRUE, view = missing_arg(), height = NULL, width = NULL, clean_logs = TRUE, shiny_args = list(), render_args = NULL, options = list() ) ``` -------------------------------- ### GET /logs Source: https://rstudio.github.io/shinytest2/reference/AppDriver.html Retrieve all debug logs recorded by the Shinytest2 AppDriver. ```APIDOC ## GET /logs ### Description Retrieve all of the debug logs that have been recorded by the AppDriver. ### Method GET ### Endpoint `/logs` ### Parameters This endpoint does not accept any parameters. ### Request Body This endpoint does not accept a request body. ### Response #### Success Response (200) Returns a data.frame with the following columns: - **workerid** (string) - The shiny worker ID found within the browser. - **timestamp** (POSIXct) - Timestamp of the log message. - **location** (string) - The source of the log message. Possible values include: `"shinytest2"`, `"shiny"`, `"chromote"`. - **level** (string) - The log level. Possible values depend on the location, e.g., `"log"`, `"error"`, `"info"`, `"debug"`, `"warn"`, `"stdout"`, `"stderr"`, `"websocket"`. #### Response Example ```json [ { "workerid": "worker_1", "timestamp": "2023-10-27T10:00:28.860Z", "location": "shinytest2", "level": "info" }, { "workerid": "worker_1", "timestamp": "2023-10-27T10:00:29.760Z", "location": "shiny", "level": "stderr" } ] ``` ``` -------------------------------- ### Get application variant Source: https://rstudio.github.io/shinytest2/reference/AppDriver.html Retrieves the variant identifier specified during the initialization of the AppDriver. ```R AppDriver$get_variant() ``` ```R \dontrun{ app_path <- system.file("examples/01_hello", package = "shiny") app <- AppDriver$new(app_path) app$get_variant() #> NULL app <- AppDriver$new(app_path, variant = platform_variant()) app$get_variant() #> [1] "mac-4.1" } ``` -------------------------------- ### Manage window size Source: https://rstudio.github.io/shinytest2/articles/z-migration.html Updates the methods for getting and setting the browser window dimensions. ```R ## {shinytest} old$getWindowSize() old$setWindowSize(width = 1024, height = 768) ## {shinytest2} new$get_window_size() new$set_window_size(width = 1024, height = 768) ``` -------------------------------- ### Configure GitHub Actions and Local Audit Files Source: https://rstudio.github.io/shinytest2/articles/use-application-audit.html Initializes the GitHub Actions workflow and copies the necessary audit script into the project directory. ```R usethis::use_github_action(url = "https://raw.githubusercontent.com/rstudio/shinytest2/main/inst/gha/app-audit.yaml") # Copy audit script dir.create("R", showWarnings = FALSE) file.copy(system.file("gha/audit-app.R", package = "shinytest2"), "R/audit-app.R") # Create your app.R file file.create("app.R") message("TODO: User - Copy in your app code to `app.R`!") # To test it locally source("R/audit-app.R") record_loadtest("app.R") # Test the audit with GitHub Actions usethis::use_description() usethis::use_git() usethis::use_github() usethis::use_github_pages() ``` -------------------------------- ### New test-sample_app.R implementation Source: https://rstudio.github.io/shinytest2/articles/use-package.html The updated test file using local_app_support to link application files into the test environment. ```r library(shinytest2) test_that("sample_app works", { appdir <- system.file(package = "exPackage", "sample_app") local_app_support(appdir) app <- AppDriver$new(appdir, name = "sample_app") app$expect_values() expect_equal(app$get_value("input$n"), helper_value) }) ``` -------------------------------- ### Get App Variant Source: https://rstudio.github.io/shinytest2/reference/AppDriver.html Retrieve the current platform variant or initialize the AppDriver with a specific variant. ```R if (FALSE) { # \dontrun{ app_path <- system.file("examples/01_hello", package = "shiny") app <- AppDriver$new(app_path) app$get_variant() #> NULL app <- AppDriver$new(app_path, variant = platform_variant()) app$get_variant() #> [1] "mac-4.1" } # } ``` -------------------------------- ### Get Chromote session Source: https://rstudio.github.io/shinytest2/reference/AppDriver.html Accesses the underlying chromote::ChromoteSession object for low-level browser control. ```R AppDriver$get_chromote_session() ``` ```R \dontrun{ app_path <- system.file("examples/01_hello", package = "shiny") app <- AppDriver$new(app_path) b <- app$get_chromote_session() b$Runtime$evaluate("1 + 1") #> $result #> $result$type #> [1] "number" #> #> $result$value #> [1] 2 #> #> $result$description #> [1] "2" } ``` -------------------------------- ### Retrieve values from Shiny app Source: https://rstudio.github.io/shinytest2/articles/z-migration.html Updates the method for getting input or output values from the application. ```R ## {shinytest} old$getValue("myinput") ## {shinytest2} new$get_value(input = "myinput") # Equivalent to new$get_values(input = "myinput")$input$myinput ``` -------------------------------- ### Initialize snapshots Source: https://rstudio.github.io/shinytest2/articles/z-migration.html Updates the initialization process for snapshot testing. ```R ## {shinytest} old$snapshotInit("mytest") ## {shinytest2} new <- AppDriver$new(name = "mytest", variant = NULL) # Suggested new <- AppDriver$new(name = "mytest", variant = platform_variant()) ``` -------------------------------- ### Get Window Size with AppDriver Source: https://rstudio.github.io/shinytest2/reference/AppDriver.html Retrieve the current dimensions of the browser window used by the AppDriver instance. ```R if (FALSE) { # \dontrun{ app_path <- system.file("examples/01_hello", package = "shiny") app <- AppDriver$new(app_path) app$get_window_size() #> $width #> [1] 992 #> #> $height #> [1] 1323 } # } ``` -------------------------------- ### Initialize shinytest2 configuration and tests Source: https://rstudio.github.io/shinytest2/reference/use_shinytest2.html Functions to set up the testing environment and create initial test files for a Shiny application. ```R use_shinytest2( app_dir = ".", runner = missing_arg(), setup = missing_arg(), ignore = missing_arg(), package = missing_arg(), ..., quiet = FALSE, overwrite = FALSE ) use_shinytest2_test( app_dir = ".", open = rlang::is_interactive(), quiet = FALSE, overwrite = FALSE ) ``` ```R # Set up shinytest2 testing configs if (FALSE) use_shinytest2() # \dontrun{} # Set up a shinytest2 test if (FALSE) use_shinytest2_test() # \dontrun{} ``` -------------------------------- ### Get application URL Source: https://rstudio.github.io/shinytest2/reference/AppDriver.html Retrieves the URL of the running Shiny application. This can be used to open the application in a browser. ```R app_path <- system.file("examples/01_hello", package = "shiny") app <- AppDriver$new(app_path) browseURL(app$get_url()) ``` -------------------------------- ### Setting Inputs and Clicks Source: https://rstudio.github.io/shinytest2/articles/in-depth.html Use `app$set_inputs()` to specify input names and their corresponding values, and `app$click()` to simulate button clicks. This is the primary method for interacting with the app during tests. ```R app$set_inputs(check_group = c("1", "2")) app$set_inputs(check_group = c("1", "2", "3")) app$click("action") ``` -------------------------------- ### Record all app values Source: https://rstudio.github.io/shinytest2/articles/in-depth.html Call `app$expect_values()` with no arguments to record all input, output, and export values. This creates a JSON file (e.g., `001.json`) and a debug screenshot (e.g., `001_.png`). ```r app$expect_values() ``` -------------------------------- ### GET /logs Source: https://rstudio.github.io/shinytest2/reference/AppDriver.html Retrieves the application logs as a data frame containing timestamps, locations, levels, and messages. ```APIDOC ## GET /logs ### Description Retrieves the full log history for the current AppDriver session. ### Method GET ### Response #### Success Response (200) - **workerid** (string) - The worker ID associated with the log entry - **timestamp** (datetime) - The time the log was recorded - **location** (string) - The source component of the log (e.g., shinytest2, chromote) - **level** (string) - The severity or type of log (e.g., info, websocket) - **message** (string) - The log content ``` -------------------------------- ### View App in Browser Source: https://rstudio.github.io/shinytest2/reference/AppDriver.html Opens the current application instance in a Chrome browser window. ```R if (FALSE) { # \dontrun{ # Open app in Chrome app$view() } # } ``` -------------------------------- ### Get browser window size Source: https://rstudio.github.io/shinytest2/reference/AppDriver.html Returns the current browser window dimensions as a list with width and height. ```R AppDriver$get_window_size() ``` ```R \dontrun{ app_path <- system.file("examples/01_hello", package = "shiny") app <- AppDriver$new(app_path) app$get_window_size() #> $width #> [1] 992 #> #> $height #> [1] 1323 } ``` -------------------------------- ### Previous test-sample_app.R implementation Source: https://rstudio.github.io/shinytest2/articles/use-package.html The legacy test file structure using AppDriver within the application directory. ```r library(shinytest2) test_that("sample_app works", { app <- AppDriver$new(name = "sample_app") app$expect_values() expect_equal(app$get_value("input$n"), helper_value) }) ``` -------------------------------- ### Initialize the AppDriver Source: https://rstudio.github.io/shinytest2/articles/using-monkey-testing.html Instantiate the AppDriver class to control the headless browser for testing. ```R headless_app <- AppDriver$new( app_dir = "", name = "monkey-test", shiny_args = list(port = 3515) ) ``` -------------------------------- ### Avoid unreliable sleep-based waiting Source: https://rstudio.github.io/shinytest2/articles/in-depth.html An example of a test pattern that relies on Sys.sleep, which is prone to failure on slower machines. ```R test_that("Sleeping can work to wait for an app to stabilize", { app <- AppDriver$new() # Check the box to display the slider and plot app$set_inputs('chkbx' = TRUE) # Hope that the plot appears within 7 seconds Sys.sleep(7) app$snapshot() app$set_inputs(bins = 40) # Hope the newer plot appears within 7 seconds Sys.sleep(7) app$expect_values() }) ``` -------------------------------- ### Define Image Paths Source: https://rstudio.github.io/shinytest2/reference/compare_screenshot_threshold.html Set file paths for bookmark images. ```R bookmark_old <- fs::path(img_folder, "bookmark-old.png") bookmark_new <- fs::path(img_folder, "bookmark-new.png") ``` -------------------------------- ### Setting Up Tests Source: https://rstudio.github.io/shinytest2/reference/index.html Functions for integrating shinytest2 with your Shiny application. ```APIDOC ## use_shinytest2() and use_shinytest2_test() ### Description Use shinytest2 with your Shiny application. ### Method N/A ### Endpoint N/A ``` -------------------------------- ### Get application directory Source: https://rstudio.github.io/shinytest2/reference/AppDriver.html Retrieves the file path to the directory where the Shiny application is located. This is useful for referencing application files. ```R app_path <- system.file("examples/01_hello", package = "shiny") app <- AppDriver$new(app_path) identical(app$get_dir(), app_path) #> [1] TRUE ``` -------------------------------- ### Get App Logs Source: https://rstudio.github.io/shinytest2/articles/use-application-audit.html Retrieves the logs from the Shiny application. This is helpful for debugging and verifying the application's behavior during testing. ```R app$get_logs() #> {shinytest2} R info 14:27:00.80 Start AppDriver initialization #> {shinytest2} R info 14:27:00.82 Creating new ChromoteSession #> {shinytest2} R info 14:27:02.20 Navigating to Shiny app #> {shinytest2} R info 14:27:02.57 Injecting shiny-tracer.js #> {chromote} JS info 14:27:02.61 shinytest2; jQuery not found #> {chromote} JS info 14:27:02.63 shinytest2; Loaded #> {shinytest2} R info 14:27:02.64 Waiting for Shiny to become ready #> {chromote} JS info 14:27:02.72 shinytest2; jQuery found #> {chromote} JS info 14:27:02.73 shinytest2; Waiting for shiny session to connect #> {chromote} JS info 14:27:03.12 shinytest2; Connected #> {shinytest2} R info 14:27:03.17 Waiting for Shiny to become idle for 200ms within 10000ms #> {chromote} JS info 14:27:03.18 shinytest2; Waiting for Shiny to be stable #> {chromote} JS info 14:27:03.27 shinytest2; shiny:busy #> {chromote} JS info 14:27:06.28 shinytest2; shiny:idle #> {chromote} JS info 14:27:06.30 shinytest2; shiny:value brussels #> {chromote} JS info 14:27:06.48 shinytest2; Shiny has been idle for 200ms #> {shinytest2} R info 14:27:06.48 Shiny app started #> {shinytest2} R info 14:30:17.79 Setting inputs: 'mu'', ''X'', ''Y' #> {chromote} JS info 14:30:17.81 shinytest2; inputQueue: adding mu #> {chromote} JS info 14:30:17.81 shinytest2; inputQueue: adding X #> {chromote} JS info 14:30:17.81 shinytest2; inputQueue: adding Y #> {chromote} JS info 14:30:17.82 shinytest2; inputQueue: flushing mu #> {chromote} JS info 14:30:17.83 shinytest2; inputQueue: flushing X #> {chromote} JS info 14:30:17.83 shinytest2; inputQueue: flushing Y #> {chromote} JS info 14:30:17.87 shinytest2; shiny:busy #> {chromote} JS info 14:30:20.42 shinytest2; shiny:idle #> {chromote} JS info 14:30:20.46 shinytest2; shiny:value brussels #> {shinytest2} R info 14:30:20.47 Finished setting inputs. Timedout: FALSE ``` -------------------------------- ### Define a Shiny application with dynamic UI Source: https://rstudio.github.io/shinytest2/articles/in-depth.html A sample app.R file demonstrating a checkbox that triggers dynamic UI generation and a plot that requires time to render. ```R library(shiny) ui <- fluidPage( checkboxInput("chkbx", "Display Graph?", FALSE), uiOutput("dynamic_output") ) server <- function(input, output) { output$dynamic_output <- renderUI({ if(!input$chkbx) { return(NULL) } tagList( sliderInput(inputId = "bins", label = "Number of bins:", min = 1, max = 50, value = 30), plotOutput(outputId = "dist_plot") ) }) # Will not execute until `input$bins` is available # `input$bins` is not available until `chkbx` is checked output$dist_plot <- renderPlot({ # artificially slow the plot Sys.sleep(5) x <- faithful$waiting bins <- seq(min(x), max(x), length.out = input$bins + 1) hist(x, breaks = bins, col = "#75AADB", border = "white", xlab = "Waiting time to next eruption (in mins)", main = "Histogram of waiting times") }) } shinyApp(ui = ui, server = server) ``` -------------------------------- ### Expect Identical Output Value Source: https://rstudio.github.io/shinytest2/articles/in-depth.html Compares a specific output value from the application to an expected string using expect_identical. This is an example of expectation-based testing. ```r vals <- app$get_values() expect_identical(vals$output$checkbox_out, "[1] TRUE") ``` -------------------------------- ### Snapshot all outputs and exports Source: https://rstudio.github.io/shinytest2/articles/in-depth.html Capture all output and export values by setting `output = TRUE` and `export = TRUE` in `app$expect_values()`. Input values will not be recorded. ```r app$expect_values(output = TRUE, export = TRUE) ``` -------------------------------- ### Example snapshot JSON Source: https://rstudio.github.io/shinytest2/articles/in-depth.html This JSON structure represents a snapshot of input, output, and exported values from a Shiny application, as generated by `app$expect_values()`. ```json { "input": { "x": 4, "y": 10, "z": 100 }, "output": { "result": "0.3636364" }, "export": { "xy": 40, "yz": 110 } } ``` -------------------------------- ### Set Window Size with AppDriver Source: https://rstudio.github.io/shinytest2/reference/AppDriver.html Configure the initial window size during initialization or update it manually using set_window_size. ```R if (FALSE) { # \dontrun{ app_path <- system.file("examples/01_hello", package = "shiny") # Set init window size app <- AppDriver$new(app_path, height = 1400, width = 1000) app$get_window_size() #> $width #> [1] 1000 #> #> $height #> [1] 1400 # Manually set the window size app$set_window_size(height = 1080, width = 1920) app$get_window_size() #> $width #> [1] 1920 #> #> $height #> [1] 1080 } # } ``` -------------------------------- ### New file structure Source: https://rstudio.github.io/shinytest2/articles/use-package.html The recommended directory layout where tests are moved to the package's top-level tests/testthat/ directory. ```text / ├── DESCRIPTION ├── NAMESPACE ├── R ├── inst │ └── sample_app │ ├── app.R │ ├── R │ └── helpers.R └── tests ├── testthat.R └── testthat ├── test-other-things.R └── test-sample_app.R ``` -------------------------------- ### Configure Chrome arguments Source: https://rstudio.github.io/shinytest2/articles/using-monkey-testing.html Set custom flags for the headless Chrome browser instance. ```R chromote::set_chrome_args( c( chromote::default_chrome_args(), # Custom flags: see https://peter.sh/experiments/chromium-command-line-switches/ ) ) ``` -------------------------------- ### Driver Initialization Migration Source: https://rstudio.github.io/shinytest2/articles/z-migration.html Replaces ShinyDriver$new with AppDriver$new. ```R ## {shinytest} old <- ShinyDriver$new(path_to_app, suffix = "macos-4.1") ## {shinytest2} new <- AppDriver$new(path_to_app, variant = "macos-4.1") ``` -------------------------------- ### Shinytest2 Equivalent for listWidgets Source: https://rstudio.github.io/shinytest2/articles/z-migration.html Replaces `ShinyDriver$listWidgets()` with `AppDriver$get_values()` and `lapply` to get the names of existing values, effectively listing widget names. ```R ## {shinytest} old$listWidgets() ## {shinytest2} lapply(new$get_values(), names) ``` -------------------------------- ### Launch a Shiny app in the background Source: https://rstudio.github.io/shinytest2/articles/use-application-audit.html This function uses the callr package to start a Shiny application in a background process, preventing the main R console from being blocked. ```R # Main shiny app shiny_bg <- function(path, port) { options(shiny.port = port) shiny::runApp(path) } ``` -------------------------------- ### Manage app support files with local_app_support Source: https://rstudio.github.io/shinytest2/articles/use-package.html Use local_app_support to attach an app's support environment during package testing. ```R test_that("app1 works with its helpers", { skip_on_cran() app_dir <- system.file("myapps/app1", package = "mypkg") # Load app1's support files (modules.R, etc.) local_app_support(app_dir) # Now helper functions from app1/R/ are available expect_true(exists("my_module_ui")) # Test the app app <- AppDriver$new(app_dir) app$expect_values() }) ``` -------------------------------- ### Shinytest2 Equivalent for sendKeys Source: https://rstudio.github.io/shinytest2/articles/z-migration.html Replaces `ShinyDriver$sendKeys()` with `AppDriver$run_js()` to trigger key events using jQuery. This example simulates pressing the Enter key. ```R ## {shinytest} old$sendKeys("myinput", webdriver::keys$enter) ## {shinytest2} new$run_js("$('#myinput').trigger({type: 'keypress', which: 13, keyCode: 13});") ``` -------------------------------- ### Define Interactions and Expectations Source: https://rstudio.github.io/shinytest2/articles/in-depth.html This section involves defining user interactions with the application and setting expectations using snapshots. It includes setting inputs and clicking elements. ```R app$set_inputs(check_group = c("1", "2")) app$set_inputs(check_group = c("1", "2", "3")) app$click("action") app$expect_values() app$click("action") app$expect_values() ``` -------------------------------- ### Wait for idle after window resize Source: https://rstudio.github.io/shinytest2/reference/AppDriver.html Shows how to wait for the application to become idle after resizing the browser window. It compares output values before and after the resize and wait. ```R pre_value <- app$get_value(output = "distPlot") app$set_window_size(height = 1080, width = 1920, wait = FALSE) middle_value <- app$get_value(output = "distPlot") app$wait_for_idle() post_value <- app$get_value(output = "distPlot") # No guarantee that these values are different identical(pre_value, middle_value) # Will not be equal identical(pre_value, post_value) ``` -------------------------------- ### Wait for JavaScript condition Source: https://rstudio.github.io/shinytest2/reference/AppDriver.html Waits for a specified JavaScript condition to evaluate to true within the browser. Includes an example of running a JS file and then waiting for a condition defined by it. ```R shiny_app <- shinyApp(h1("Empty App"), function(input, output) { }) app <- AppDriver$new(shiny_app) # Contrived example: # Wait until `Date.now()` returns a number that ends in a 5. (0 - 10 seconds) system.time( app$wait_for_js("Math.floor((Date.now() / 1000) % 10) == 5;") ) ## A second example where we run the contents of a JavaScript file ## and use the result to wait for a condition app$run_js(file = "complicated_file.js") app$wait_for_js("complicated_condition();") ``` -------------------------------- ### load_app_support Source: https://rstudio.github.io/shinytest2/reference/app_support.html Loads all support files into the current environment permanently. ```APIDOC ## load_app_support(app_dir, envir = rlang::caller_env()) ### Description Loads all support files into the current environment. No cleanup actions are ever performed. Best used in setup-shinytest2.R for non-package apps. ### Parameters #### Arguments - **app_dir** (string) - Required - The base directory for the Shiny application. - **envir** (environment) - Optional - The environment in which the App support should be made available. ``` -------------------------------- ### Generated Test Script with shinytest2 Source: https://rstudio.github.io/shinytest2/articles/shinytest2.html This is an example of a test script generated by shinytest2 after recording interactions. It includes setting inputs, clicking buttons, and taking value expectations. ```r # File: tests/testthat/test-shinytest2.R library(shinytest2) test_that("{shinytest2} recording: simple-app", { app <- AppDriver$new(name = "simple-app", height = 407, width = 348) app$set_inputs(name = "Barret") app$click("greet") app$expect_values() }) ``` -------------------------------- ### Get Screenshot of Specific Element and Display Source: https://rstudio.github.io/shinytest2/reference/AppDriver.html Captures a screenshot of a specific element and displays it in the graphics device. This allows for focused visual checks of particular app components. ```R # Update bins then display "disPlot" in graphics device app$set_inputs(bins = 10) app$get_screenshot(selector = "#distPlot") ``` -------------------------------- ### Load Shiny application support environment Source: https://rstudio.github.io/shinytest2/reference/load_app_env.html Use this function to load support files into the current environment for testing purposes. It is recommended to call this in tests/testthat/setup-shinytest2.R if access to support objects is required. ```R load_app_env( app_dir = "../../", renv = rlang::caller_env(), globalrenv = rlang::caller_env() ) ``` -------------------------------- ### View Headless Browser Source: https://rstudio.github.io/shinytest2/articles/in-depth.html Opens the application in a default Chrome browser for inspection. This is the recommended method for debugging during test execution. ```r app$view() ```