rstudio/shinytest2

No way to ignore a certain input or output when expecting values

Opened this issue · 5 comments

Suppose I have an app with many inputs. One of the packages I use also creates an ghost input just as a way to communicate with shiny, but it's not an input that I want to keep track of with expect_values() because it's a random number.

Currently, expect_values() can either capture ALL inputs, or a list of inputs. But it has no way of excluding a specific input.

As a concrete example, shinyAce::aceEditor() seems to create an input called contents_shinyAce_annotationTrigger that is a random number, so I don't want to include it in my expectations.

If you had a function, would you be ok if the execution of the black...

  1. serializing all possible values from Shiny server
  2. reading the JSON in {shinytest2}
  3. trimming the JSON
  4. and re-saving the JSON

The trimming step would be done with a Filter-like function. I believe the static black list would get unwieldy quickly.

Would this work? Then you can decide what is kept from within the function

The difficult part is that Shiny must receive a URL of information on which values to return. So only static values may be used. However, we can ask for everything and then trim the values in a post-processing step.

Trimming a json that shows all the values would be just fine

Hi,
I'd like to know whether "trimming a json" would help me in another simple use case as well. In my (first) shinytest2 attempts
expect_values() fails due to a timestamp in my app:

-     "projectName": "xyz project (created 2024-01-24_16.48.36.708312)",
+     "projectName": "xyz project (created 2024-01-24_16.49.41.955485)", 

Does trimming of e.g. testthat/_snaps/linux-4.3/shinytest2/app-002.json result in that I could either 1) ignore projectName values entirely, or 2) expect a match on a substring xyz project (created ?
I tried editing the json, and the diff shows (not unexpectedly)

+     "projectName": "xyz project (created 2024-01-24_16.49.41.955485)", 

So I guess that "trimming step would be done with a Filter-like function" needs to be done before the expect_values() in my tests.
Or maybe add expect_values(output_ignore = c("projectName")) ?
I would like to avoid littering my app with isTRUE(getOption("shiny.testmode"))

Yours,
Steffen

This is the workaround I currently use:

app <- AppDriver$new("myapp")

input_names <- names(app$get_values(input = TRUE)$input)
app$expect_values(input = vector_select(input_names, exclude = "random_input_that_always_changes"))

with vector_select being a simple regex selector function:

vector_select <- function(
    x,
    include = NULL,
    exclude = NULL
){
  if(is.null(x)) return(character(0))
  stopifnot(is.character(x))
  stopifnot(is.null(include) || is.character(include))
  stopifnot(is.null(exclude) || is.character(exclude))
  if(!is.null(include)){
    x <- x[grepl(paste(include, collapse = "|"), x)]
  }
  if(!is.null(exclude)){
    x <- x[!grepl(paste(exclude, collapse = "|"), x)]
  }
  x
}