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

Capture reactives from a Shiny app in a general way #340

Open
parmsam-pfizer opened this issue Jun 15, 2023 · 0 comments
Open

Capture reactives from a Shiny app in a general way #340

parmsam-pfizer opened this issue Jun 15, 2023 · 0 comments

Comments

@parmsam-pfizer
Copy link

Love the package. Currently inputs and outputs can be automatically exported. Creating issue to see if there is a way to generally export all reactives without explicitly declaring them in shiny::exportTestValues(). This could be a future feature. Here is a reproducible example in this direction:

library(shiny)
library(shinytest2)
shiny_app <- shinyApp(
  fluidPage(
    h1("Pythagorean theorem"),
    numericInput("A", "A", 3),
    numericInput("B", "B", 4),
    verbatimTextOutput("C"),
  ),
  function(input, output) {
    a_squared <- reactive({ req(input$A); input$A * input$A })
    b_squared <- reactive({ req(input$B); input$B * input$B })
    c_squared <- reactive({ a_squared() + b_squared() })
    c_value <- reactive({ sqrt(c_squared()) })
    
    output$C <- renderText({ c_value() })
    

    observe({
      # alternatively, automatically generate list of reactives for export
      # use function to auto gen reactive list
      getReactives4Export <- function(n = 3) {
        # note that function is expected to run within a reactive context
        # get parent environment
        curr_env <- rlang::env_parent(n = n)
        reactive_objs <-
          unlist(lapply(curr_env, shiny::is.reactive))
        export <- names(reactive_objs[reactive_objs == T])

        # omit the get_inputs reactive which is used for loading purposes
        # can also omit other reactives as needed here
        export <- export[export != "get_inputs"]
        # wrangle export vector into list with reactive formatting
        export_names <- export
        export <- as.list(export)
        # print TRUE or FALSE to the developers console depending on if
        # reactives were captured
        if (length(export) > 0) {
          print("export success")
          export <- paste0(export, "()")
        } else{
          print("export fail")
          export
        }
        names(export) <- export_names
        # parse list reactives to get objects
        eval_parse_reactive <-
          function(reactive_str) {
            eval(parse(text = reactive_str))
          }
        export_vals <- lapply(export, eval_parse_reactive)
        # another idea would be also saving reactive expressions
        ## interesting idea I first saw in shinyobjects (https://rjake.github.io/shinyobjects/)
        ## this export_expr line of code gets those expressions into a list
        export_expr <- lapply(names(export), eval_parse_reactive)
        return(export_vals)
      }
      all_reactives <- getReactives4Export()
      exportTestValues(
        all_reactives = all_reactives
      )
    })
    
})

app <- AppDriver$new(shiny_app)

init_vals <- app$get_values()
str(init_vals)
#> List of 3
#>  $ input :List of 2
#>   ..$ A: int 3
#>   ..$ B: int 4
#>  $ output:List of 1
#>   ..$ C: chr "5"
#>  $ export:List of 1
#>   ..$ all_reactives:List of 4
#>   .. ..$ c_value  : num 5
#>   .. ..$ c_squared: int 25
#>   .. ..$ b_squared: int 16
#>   .. ..$ a_squared: int 9

Created on 2023-06-15 by the reprex package (v2.0.1)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant