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

add app$waitForValue #304

Merged
merged 22 commits into from
Feb 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
9c42a4f
add
schloerke Feb 3, 2020
683e85e
code review feedback
schloerke Feb 4, 2020
c10983f
Add news item for PR 302
schloerke Feb 4, 2020
a061d0d
Bump version and add RStudio as cph and fnd
schloerke Feb 4, 2020
201fc98
Simplify RStudio author name to work better with pkgdown
schloerke Feb 4, 2020
771e4e8
Update NEWS.md
schloerke Feb 4, 2020
c059db9
Have badges be displayed on right sidebar in pkgdown
schloerke Feb 4, 2020
573622e
Add example information for `app$waitForValue` in vigs/in-depth and v…
schloerke Feb 4, 2020
012cc5e
Update news to work cleaner with pkgdown. Fix bad markdown links
schloerke Feb 4, 2020
017430f
compile pkgdown
schloerke Feb 4, 2020
64296b7
Fix many bugs in app$waitForValue.
schloerke Feb 4, 2020
45cd486
add Mango Solutions as cph and ccp
schloerke Feb 5, 2020
a86e12e
code feedback. 30s -> 10s. invalidValues -> ignore. always use ignore…
schloerke Feb 6, 2020
8d7edee
Merge branch 'master' into wait_for_value
schloerke Feb 6, 2020
4861b03
Be allowed to call `app$getValue('PLOT')` on a plotOutput object
schloerke Feb 7, 2020
17fed4c
fix the debug message
schloerke Feb 7, 2020
429ebc6
Update the article on `app$waitForValue`
schloerke Feb 7, 2020
b9ed9fb
Add the documentation app as a test
schloerke Feb 7, 2020
f8d9e1f
add the community badge for shinytest
schloerke Feb 7, 2020
6d5a515
adjust wording to point to new subsection
schloerke Feb 7, 2020
8636f2c
Remove bad plotOutput implementation and use `app$getAllValues` insid…
schloerke Feb 7, 2020
639a033
Remove warning
schloerke Feb 7, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
Package: shinytest
Title: Test Shiny Apps
Version: 1.3.1.9001
Version: 1.3.1.9002
Authors@R: c(
person("Winston", "Chang", role = c("aut", "cre"), email = "[email protected]"),
person("Gábor", "Csárdi", role = "aut", email = "[email protected]")
person("Gábor", "Csárdi", role = "aut", email = "[email protected]"),
person("RStudio", role = c("cph", "fnd")),
person("Mango Solutions", role = c("cph", "ccp"))
)
Description: For automated testing of Shiny applications, using a headless
browser, driven through 'WebDriver'.
Expand Down
12 changes: 7 additions & 5 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
1.3.1.9001
shinytest (development version)
==========

* Recommend that tests be placed in `tests/shinytests/` instead of directly in the tests directory. Users with their tests in the `tests/` directory will now see a message about this change. Storing shinytests directly in `tests/` will be deprecated in the future.

* Added new `suffix` option, which allows adding a suffix to an expected results directory. This makes it possible to store multiple sets of results, which can be useful, for example, if you run tests on multiple platforms. ((#295)[https://github.com/rstudio/shinytest/pull/295])
* Added new `suffix` option, which allows adding a suffix to an expected results directory. This makes it possible to store multiple sets of results, which can be useful, for example, if you run tests on multiple platforms. ([#295](https://github.com/rstudio/shinytest/pull/295))

* Previously, on Windows, the reported resolution of screenshots depended on the actual screen resolution. For example, on one Windows machine, it might report a screenshot to be 96 ppi, while on another machine, it might report it to be 240 ppi, even though the image data is exactly the same from the two machines. This caused problems when expected results were generated on one machine and the tests were run on another machine. Now, the screenshots are modified so that they always report 72 ppi resolution, which is the same as on Mac and Linux. ((#297)[https://github.com/rstudio/shinytest/pull/297])
* Previously, on Windows, the reported resolution of screenshots depended on the actual screen resolution. For example, on one Windows machine, it might report a screenshot to be 96 ppi, while on another machine, it might report it to be 240 ppi, even though the image data is exactly the same from the two machines. This caused problems when expected results were generated on one machine and the tests were run on another machine. Now, the screenshots are modified so that they always report 72 ppi resolution, which is the same as on Mac and Linux. ([#297](https://github.com/rstudio/shinytest/pull/297))

1.3.1
* Added new `ShinyDriver` method `app$waitForValue()` which will wait until the current application's `input` (or `output`) value is not one of the supplied invalid values. ([#304](https://github.com/rstudio/shinytest/pull/304))

shinytest 1.3.1
=======

## New features
Expand All @@ -26,7 +28,7 @@

* `ShinyDriver` now passes the current `RNGkind()` to the background R process that serves up the app being tested. This allows for better control over randomness across mutliple versions of R with different `RNGkind()` defaults (e.g., 3.5 and 3.6)

1.3.0
shinytest 1.3.0
=====

* First public release
1 change: 1 addition & 0 deletions R/app-get-all-values.R
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Note: This queries the server
sd_getAllValues <- function(self, private, input, output, export) {
"!DEBUG sd_getAllValues"
url <- private$getTestSnapshotUrl(input, output, export, format = "rds")
Expand Down
64 changes: 64 additions & 0 deletions R/shiny-driver.R
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#'
#' app$waitFor(expr, checkInterval = 100, timeout = 3000)
#'
#' app$waitForValue(name, ignore = list(NULL, ""), iotype = "input", timeout = 10000, checkInterval = 400)
#'
#' app$listWidgets()
#'
#' app$checkUniqueWidgetNames()
Expand Down Expand Up @@ -84,6 +86,9 @@
#' evaluates to the condition to wait for.}
#' \item{checkInterval}{How often to check for the condition, in
#' milliseconds.}
#' \item{ignore}{List of possible values that are to not be
#' considered valid. \code{app$waitForValue} will continue to poll until
#' it finds a value not contained in \code{ignore}.}
#' \item{timeout}{Timeout for the condition, in milliseconds.}
#' \item{output}{Character vector, the name(s) of the Shiny output
#' widgets that should be updated.}
Expand Down Expand Up @@ -169,6 +174,13 @@
#' to \code{true}, or a timeout happens. It returns \code{TRUE} is the
#' expression evaluated to \code{true}, possible after some waiting.
#'
#' \code{app$waitForValue()} waits until the current application's
#' \code{input} (or \code{output}) value is not one of the supplied invalid
#' values. The function returns the value found if the time limit has not
#' been reached (default is 10 seconds). This function can be useful in
#' helping determine if an application has initialized or finished
#' processing a complex reactive situation.
#'
#' \code{app$listWidgets()} lists the names of all input and output
#' widgets. It returns a list of two character vectors, named \code{input}
#' and \code{output}.
Expand Down Expand Up @@ -220,12 +232,14 @@ ShinyDriver <- R6Class(
stop = function()
sd_stop(self, private),

# Note: This queries the **browser**
getValue = function(name, iotype = c("auto", "input", "output"))
sd_getValue(self, private, name, match.arg(iotype)),

setValue = function(name, value, iotype = c("auto", "input", "output"))
sd_setValue(self, private, name, value, match.arg(iotype)),

# Note: This queries the server
getAllValues = function(input = TRUE, output = TRUE, export = TRUE)
sd_getAllValues(self, private, input, output, export),

Expand Down Expand Up @@ -287,6 +301,9 @@ ShinyDriver <- R6Class(
waitFor = function(expr, checkInterval = 100, timeout = 3000)
sd_waitFor(self, private, expr, checkInterval, timeout),

waitForValue = function(name, ignore = list(NULL, ""), iotype = c("input", "output", "export"), timeout = 10000, checkInterval = 400) {
sd_waitForValue(self, private, name = name, ignore = ignore, iotype = match.arg(iotype), timeout = timeout, checkInterval = checkInterval)
},

listWidgets = function()
sd_listWidgets(self, private),
Expand Down Expand Up @@ -408,6 +425,7 @@ ShinyDriver$debugLogTypes <- c(
"shinytest"
)

# Note: This queries the **browser**
sd_getValue <- function(self, private, name, iotype) {
"!DEBUG sd_getValue `name` (`iotype`)"
self$findWidget(name, iotype)$getValue()
Expand Down Expand Up @@ -470,6 +488,52 @@ sd_waitFor <- function(self, private, expr, checkInterval, timeout) {
private$web$waitFor(expr, checkInterval, timeout)
}

sd_waitForValue <- function(self, private, name, ignore = list(NULL, ""), iotype = "input", timeout = 10000, checkInterval = 400) {
"!DEBUG sd_waitForValue"

timeoutSec <- as.numeric(timeout) / 1000
if (!is.numeric(timeoutSec) || is.na(timeoutSec) || is.nan(timeoutSec)) {
stop("timeout must be numeric")
}
checkInterval <- as.numeric(checkInterval)
if (!is.numeric(checkInterval) || is.na(checkInterval) || is.nan(checkInterval)) {
stop("checkInterval must be numeric")
}

now <- function() {
as.numeric(Sys.time())
}

endTime <- now() + timeoutSec

while (TRUE) {
value <- try({
args <- list()
args[[iotype]] <- name
do.call(self$getAllValues, args)[[iotype]][[name]]
}, silent = TRUE)

# if no error when trying ot retrieve the value..
if (!inherits(value, "try-error")) {
# check against all invalid values
isInvalid <- vapply(ignore, identical, logical(1), x = value)
# if no matches, then it's a success!
if (!any(isInvalid)) {
return(value)
}
}

# if too much time has elapsed... throw
if (now() > endTime) {
stop("timeout reached when waiting for value: ", name)
}

# wait a little bit for shiny to do some work
Sys.sleep(checkInterval / 1000)
}

}

sd_listWidgets <- function(self, private) {
"!DEBUG sd_listWidgets"
res <- private$web$executeScript("return shinytest.listWidgets();")
Expand Down
1 change: 1 addition & 0 deletions R/widget-get-value.R
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ widget_getValueFuncs <- list(
textOutput = function(self, private) {
private$element$getText()
}

)

widget_getValuePostprocess <- list(
Expand Down
13 changes: 13 additions & 0 deletions README.Rmd
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
---
title: README
output:
md_document:
variant: gfm
pandoc_args: "--wrap=preserve"
# compile using `rmarkdown::render("README.Rmd")`
---

```{r, setup, echo = FALSE, message = FALSE}
knitr::opts_chunk$set(
Expand All @@ -12,10 +20,15 @@ knitr::opts_chunk$set(

> Test Shiny Apps

<!-- badges: start -->
[![Linux Build Status](https://travis-ci.org/rstudio/shinytest.svg?branch=master)](https://travis-ci.org/rstudio/shinytest)
[![Windows Build status](https://ci.appveyor.com/api/projects/status/github/rstudio/shinytest?svg=true)](https://ci.appveyor.com/project/rstudio/shinytest)
[![](http://www.r-pkg.org/badges/version/shinytest)](http://www.r-pkg.org/pkg/shinytest)
[![CRAN RStudio mirror downloads](http://cranlogs.r-pkg.org/badges/shinytest)](http://www.r-pkg.org/pkg/shinytest)
<!-- badges: end -->

[![RStudio community](https://img.shields.io/badge/community-shinytest-blue?style=social&logo=rstudio&logoColor=75AADB)](https://community.rstudio.com/tags/c/shiny/8/shinytest)


## Installation

Expand Down
15 changes: 7 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,28 @@



# shinytest

> Test Shiny Apps

<!-- badges: start -->

[![Linux Build Status](https://travis-ci.org/rstudio/shinytest.svg?branch=master)](https://travis-ci.org/rstudio/shinytest)
[![Windows Build status](https://ci.appveyor.com/api/projects/status/github/rstudio/shinytest?svg=true)](https://ci.appveyor.com/project/rstudio/shinytest)
[![](http://www.r-pkg.org/badges/version/shinytest)](http://www.r-pkg.org/pkg/shinytest)
[![CRAN RStudio mirror downloads](http://cranlogs.r-pkg.org/badges/shinytest)](http://www.r-pkg.org/pkg/shinytest)
<!-- badges: end -->

[![RStudio community](https://img.shields.io/badge/community-shinytest-blue?style=social&logo=rstudio&logoColor=75AADB)](https://community.rstudio.com/tags/c/shiny/8/shinytest)

## Installation

To install the current release version:


```r
``` r
install.packages("shinytest")
```


To install the development version:


```r
``` r
devtools::install_github("rstudio/shinytest")
```

Expand Down
Loading