Shinytest2 json comparisons fail because of renderUI div IDs

101 views Asked by At

I am using R Shiny's shinytest2 package to automate testing my app. The app and tests work. However, the tests keep failing shinytest2's comparisons because of renderUI()'s auto-generated ids, e.g. out63cdc91c431ff1ea. I thought setting the driver's seed would suffice, as it worked when I used shinytest, but it doesn't.

Here's a pared-down version of my test script:

library(shinytest2)
test_that("{shinytest2} recording: test-good", {
    print("Running test-good")
    app <- AppDriver$new(
        variant = platform_variant(), 
        name = "test-good", 
        seed = 1234,
        load_timeout = 1e+05)

app$set_inputs(sidebarmenuid = "tabClientCount")
app$wait_for_idle(500) #wait until whole application is idle for 500ms
app$expect_values()
})

And here's some of the console failure:

Failure (test-good.R:20:1): {shinytest2} recording: test-good
Snapshot of `file` to 'good/test-good-001.json' has changed

So in good/test-good-001.json the ID is out63cdc91c431ff1ea and in good/test-good-001.new.json the ID is outcdc91c431ff1ea2a. And if I run it again, the IDs change again. I thought the random seed would work, but it's not. How can I stop these renderUI-auto-generated IDs from flagging failures, e.g. via an option to ignore these sorts of IDs, or via setting the ids myself. Also, I have many tests, so the solution needs to be scalable.

In case the renderUI code is helpful:

headerGeneric <- function(tabTitle, extraHTML = NULL) {
  renderUI({
    if(valid_file() == 1) {
      list(h2(tabTitle),
           h4(strong("Date Range of Current File: "),
            paste(
             format(Project0$start_date, "%m-%d-%Y"),
             "to",
             format(Project0$end_date, "%m-%d-%Y")
           )),
           extraHTML
      )
    } else {
      h4("This is blank until your data has been validated.")
    }
  })
}

output$headerClientCounts <- headerGeneric("Client Counts Report", 
    renderUI({   
      organization <- Project0 %>%
        filter(ProjectName == input$currentProviderList) %>%
        pull(OrganizationName)

      h4(organization, "|", input$currentProviderList)
    })
  )

UPDATE: The source of the problem was the nested-nature of the renderUI() code. This must be because each renderUI() call is essentially creating a new reactive context, and so it generates a new ID. shinytest2's seed must only apply to the outer-most renderUI(). But I'm not sure how best to avoid this. I created the headerGeneric() function, because we reuse the main part of it over and over on each tab of our app. Is there a way to pass in a hard-coded ID to renderUI()?

1

There are 1 answers

0
Alex Silverman On

The source of the problem was the nested-nature of the renderUI code. It looks like I should be attaching all renderUI()s to outputs (whose names become the IDs), but, if I don't, Shiny is "smart" enough to generate a random ID for me. I do think this was not a problem with shinytest, but once I associated the inner renderUI() with an output, that fixed the problem.