daattali / shinyjs

💡 Easily improve the user experience of your Shiny apps in seconds
https://deanattali.com/shinyjs
Other
734 stars 119 forks source link

support testing within shiny apps #257

Closed bhogan-mitre closed 1 year ago

bhogan-mitre commented 1 year ago

Is it possible to test that show/hide, enable/disable, etc. are working properly from within a shiny app?

Suppose I am running the test app at https://github.com/daattali/shinyjs/blob/master/README.md?plain=1#L296-L312 and I want to verify that the toggle is working as expected.

I modified the app to dynamically render the text form, so that I can examine it as an output variable.

library(shiny)
library(shinyjs)

ui <- fluidPage(
  useShinyjs(),  # Include shinyjs

  actionButton("button", "Click me"),
  uiOutput("textForm")
)

server <- function(input, output, session) {
  output$textForm <- renderUI({
    textInput("text", "Text")
  })

  observeEvent(input$button, {
    toggle("text")  # toggle is a shinyjs function
  })
}

shinyApp(ui, server)

Then I am trying test it as follows:

testServer(expr = {

  test_that("input form is set", {
    session$setInputs(text = "abc")
    expect_equal(input$text, "abc")
  })  

  test_that("button hides text input", {
    session$setInputs(button = 1)
    expect_match(
      output$textForm$html,
      "display: none"
    )
  })
})

However the style (or class in the case of enable/disable) doesn't seem to be applied at the level that shiny::testServer() can see.

Screen Shot 2022-10-26 at 8 49 41 AM

Is it possible to test in this way? Or is it outside the view of R if it's happening at the JS-level? Thanks in advance for any insight on this.

daattali commented 1 year ago

I don't know enough about how testServer() works so I can't say for sure, but I imagine it does not use a real browser and has no way of ever working with javascript code. Perhaps it's a question you can ask on the {shiny} github issues -- whether or not it's possible to test something that happens in the browser. I know it's meant to test reactivity and server events, not client events, and the name also suggests the same, so I highly doubt it can test javascript.

With {shinytest2} you should be able to test things in the browser. Specifically, look at AppDriver$expect_js(), that should be helpful

bhogan-mitre commented 1 year ago

Got it. Thanks for your reply! It does sounds like a better candidate for testing with {shinytest2} and its headless browser.

daattali commented 1 year ago

FYI I'm currently working on a large shiny app that makes use of a lot of shinyjs functionality, and I do use shinytest2 for testing usage of shinyjs::toggle and shinyjs::disable. I use functions such as this one for testing:

is_shiny_enabled <- function(driver, id) {
  driver$get_js(glue::glue("$('#{ id }').is(':enabled')"))
}