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

Inputs component(s) in set_input can't be provided as variables #338

Open
gladkia opened this issue Jun 8, 2023 · 3 comments
Open

Inputs component(s) in set_input can't be provided as variables #338

gladkia opened this issue Jun 8, 2023 · 3 comments

Comments

@gladkia
Copy link
Contributor

gladkia commented Jun 8, 2023

Summary

It seems that in the current version of set_inputs one has to hard-code the input components.

App and evaluation

Please find a simple app with example uses of set_input below:

library(shinytest2) 

two_radio_buttons_app <- shinyApp(ui <- fluidPage(
  radioButtons("rd1", "rd1", letters[1:5]),
  radioButtons("rd2", "rd2", LETTERS[1:5]),
  textOutput("rd_out")
  
),
server <- function(input, output, session) {
  output$rd_out <-
    renderText(sprintf("info: rd1:%s rd2:%s", input$rd1, input$rd2))
  
})

app <- shinytest2::AppDriver$new(two_radio_buttons_app, name = "two_radio_buttons_app")
on.exit({
  print(app$get_logs())
  app$stop()
  rm(app)
})

test_that("evaluate `set_input`", {
  print("### providing input component as hard-coded data")
  print(app$get_value(input = "rd1"))
  app$set_inputs(rd1 = "b")
  print(app$get_value(input = "rd1"))
  app$set_inputs(rd1 = "e")
  print(app$get_value(input = "rd1"))
  
  print(app$get_value(input = "rd2"))
  app$set_inputs(rd2 = "C")
  print(app$get_value(input = "rd2"))
  app$set_inputs(rd2 = "D")
  print(app$get_value(input = "rd2"))
  
  print("### providing input component as variables")
  rd1_v1 <- "b"
  rd1_id <- "rd1"
  rd1_v2 <- "c"
  print(app$get_value(input = "rd1"))
  
  # value can be provided as variable
  app$set_inputs("rd1" = rd1_v1)
  print(app$get_value(input = "rd1"))
  
  # input component can be provided as variable (solution #1)
  app$set_inputs(`as.name(rd1_id)` = rd1_v2)
  print(app$get_value(input = "rd1"))
  
  # input component can be provided as variable (solution #2)
  rv <- structure(rd1_v2, names = rd1_id)
  app$set_inputs(rv)
  print(app$get_value(input = "rd1"))
})

Output from testthat

And here is the output of testthat::test_file("code_above.R")

[ FAIL 0 | WARN 0 | SKIP 0 | PASS 0 ][1] 
"### providing input component as hard-coded data"
[1] "a"
[1] "b"
[1] "e"
[1] "A"
[1] "C"
[1] "D"
[1] "### providing input component as variables"
[1] "e"
[1] "b"
[1] "b"
[ FAIL 1 | WARN 0 | SKIP 0 | PASS 0 ]{shinytest2} R  info   20:17:48.02 Start AppDriver initialization
(...)
{chromote}   JS info   20:17:54.55 shinytest2; Unable to find input binding for element with id as.name(rd1_id)
{shinytest2} R  info   20:17:54.55 Error received while setting inputs: Unable to find input binding for element with id as.name(rd1_id)
{shinytest2} R  info   20:17:54.66 Getting all values
{shinytest2} R  info   20:17:55.08 Setting inputs: ''
{shiny}      R  stderr ----------- Loading required package: shiny
{shiny}      R  stderr ----------- Running application in test mode.
{shiny}      R  stderr ----------- 
{shiny}      R  stderr ----------- Listening on http://127.0.0.1:5059

── Error (shinytest2.R:52): evaluate `set_input` ───────────────────────────────
Error in `app_queue_inputs(self, private, input_values)`: Assertion on 'rlang::is_named(inputs)' failed: Must be TRUE.
Backtrace:
 1. app$set_inputs(rv)
      at shinytest2.R:52:2
 2. shinytest2:::app_set_inputs(...)
      at shinytest2/R/app-driver.R:433:6
 3. shinytest2:::app_queue_inputs(self, private, input_values)
      at shinytest2/R/app-driver-set-inputs.R:43:2
 4. checkmate::assert_true(rlang::is_named(inputs))
      at shinytest2/R/app-driver-set-inputs.R:72:2
 5. checkmate::makeAssertion(x, res, .var.name, add)
 6. checkmate:::mstop(...)

[ FAIL 1 | WARN 0 | SKIP 0 | PASS 0 ]
@gadenbuie
Copy link
Member

Hi @gladkia, thanks for posting this issue and for following up with a PR!

As you may have noticed while looking at the source code, $set_inputs() uses rlang::list2(...) to process the input values. This function supports !!!, the splicing operator, so you can construct a list outside of set_inputs() and use it to set the input values.

all_to_value_b <- list(rd1 = "b", rd2 = "B")
app$set_inputs(!!!all_to_value_b)

@gladkia
Copy link
Contributor Author

gladkia commented Jun 13, 2023

Hi @gadenbuie,

Thanks for the quick answer. Awesome. Now I see how powerful the solution with rlang::list2(...) is :)!

It would be great to add some info to the vignette and maybe sth in the tests to let the users know that such a great and simple solution is possible :). I mean sth similar to the updated version of the PR.

@gadenbuie
Copy link
Member

Thanks @gladkia, I agree it would be helpful to mention this in the documentation and think your updated PR is a good start! Barret will likely review your PR when we pick up work in shinytest2 again (please don't be alarmed if it takes a little while for us to get to it).

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

2 participants