Title: | Test Shiny Apps |
Version: | 1.6.1 |
Description: | Please see the 'shinytest' to 'shinytest2' migration guide at https://rstudio.github.io/shinytest2/articles/z-migration.html. |
License: | MIT + file LICENSE |
URL: | https://github.com/rstudio/shinytest |
BugReports: | https://github.com/rstudio/shinytest/issues |
Imports: | assertthat, callr (≥ 2.0.3), crayon, debugme, digest, htmlwidgets, httpuv, httr, jsonlite, parsedate, pingr, R6, rematch, rlang, rstudioapi (≥ 0.8.0.9002), shiny (≥ 1.3.2), testthat (≥ 1.0.0), utils, webdriver (≥ 1.0.6), withr |
Suggests: | flexdashboard, globals, rmarkdown |
Encoding: | UTF-8 |
RoxygenNote: | 7.3.1 |
SystemRequirements: | PhantomJS (http://phantomjs.org/) |
NeedsCompilation: | no |
Packaged: | 2024-05-30 18:58:12 UTC; winston |
Author: | Winston Chang [aut, cre], Gábor Csárdi [aut], Hadley Wickham [aut], Posit Software, PBC [cph, fnd], Ascent Digital Services [cph, ccp] |
Maintainer: | Winston Chang <winston@posit.co> |
Repository: | CRAN |
Date/Publication: | 2024-05-30 19:10:02 UTC |
shinytest: Test Shiny Apps
Description
Please see the shinytest to shinytest2 migration guide at https://rstudio.github.io/shinytest2/articles/z-migration.html
Author(s)
Maintainer: Winston Chang winston@posit.co
Authors:
Gábor Csárdi gabor@posit.co
Hadley Wickham hadley@posit.co
Other contributors:
Posit Software, PBC [copyright holder, funder]
Ascent Digital Services [copyright holder, conceptor]
See Also
Useful links:
Remote control a Shiny app running in a headless browser
Description
This class starts a Shiny app in a new R session, along with a phantom.js
headless browser that can be used to simulate user actions. This provides
a full simulation of a Shiny app so that you can test user interactions
with a live app.
Methods
Public methods
Method new()
Usage
ShinyDriver$new( path = ".", loadTimeout = NULL, checkNames = TRUE, debug = c("none", "all", shinytest::ShinyDriver$debugLogTypes), phantomTimeout = 5000, seed = NULL, cleanLogs = TRUE, shinyOptions = list(), renderArgs = NULL, options = list() )
Arguments
path
Path to a directory containing a Shiny app, i.e. a single
app.R
file or aserver.R
-ui.R
pair.loadTimeout
How long to wait for the app to load, in ms. This includes the time to start R. Defaults to 5s when running locally and 10s when running on CI.
checkNames
Check if widget names are unique?
debug
Start the app in debugging mode? In debugging mode debug messages are printed to the console.
phantomTimeout
How long to wait when connecting to phantomJS process, in ms
seed
An optional random seed to use before starting the application. For apps that use R's random number generator, this can make their behavior repeatable.
cleanLogs
Whether to remove the stdout and stderr logs when the Shiny process object is garbage collected.
shinyOptions
A list of options to pass to
shiny::runApp()
.renderArgs
Passed to
rmarkdown::run()
for interactive.Rmd
s.options
A list of
base::options()
to set in the driver's child process.
Method finalize()
Stop app and clean up logs.
Usage
ShinyDriver$finalize()
Method stop()
Stop the app, the terminate external R process that runs the app and the phantomjs instance.
Usage
ShinyDriver$stop()
Method getValue()
Finds a widget and queries its value. See the getValue()
method of
Widget for more details.
Usage
ShinyDriver$getValue(name, iotype = c("auto", "input", "output"))
Arguments
name
Name of a shiny widget.
iotype
Type of the Shiny widget. Usually shinytest finds the widgets by their name, so this is only needed if you use the same name for an input and output widget.
Method setValue()
Finds a widget and sets its value. It's a shortcut for findElement()
plus setValue()
; see the Widget documentation for more details.
Usage
ShinyDriver$setValue(name, value, iotype = c("auto", "input", "output"))
Arguments
name
Name of a shiny widget.
value
New value.
iotype
Type of the Shiny widget. Usually shinytest finds the widgets by their name, so this is only needed if you use the same name for an input and output widget.
Returns
Self, invisibly.
Method click()
Find a widget and click it. It's a shortcut for findElement()
plus click()
; see the Widget documentation for more details.
Usage
ShinyDriver$click(name, iotype = c("auto", "input", "output"))
Arguments
name
Name of a shiny widget.
iotype
Type of the Shiny widget. Usually shinytest finds the widgets by their name, so this is only needed if you use the same name for an input and output widget.
Method getAllValues()
Returns a named list of all inputs, outputs, and export values.
Usage
ShinyDriver$getAllValues(input = TRUE, output = TRUE, export = TRUE)
Arguments
input, output, export
Either
TRUE
to return all input/output/exported values, or a character vector of specific controls.
Method sendKeys()
Sends the specified keys to specific HTML element. Shortcut for
findWidget()
plus sendKeys()
.
Usage
ShinyDriver$sendKeys(name, keys)
Arguments
name
Name of a shiny widget.
keys
Keys to send to the widget or the app. See webdriver::key for how to specific special keys.
Returns
Self, invisibly.
Method setWindowSize()
Sets size of the browser window.
Usage
ShinyDriver$setWindowSize(width, height)
Arguments
width, height
Height and width of browser, in pixels.
Returns
Self, invisibly.
Method getWindowSize()
Get current size of the browser window, as list of integer scalars
named width
and height
.
Usage
ShinyDriver$getWindowSize()
Method getDebugLog()
Query one or more of the debug logs.
Usage
ShinyDriver$getDebugLog(type = c("all", ShinyDriver$debugLogTypes))
Arguments
type
Log type:
"all"
,"shiny_console"
,"browser"
, or"shinytest"
.
Method enableDebugLogMessages()
Enable/disable debugging messages
Usage
ShinyDriver$enableDebugLogMessages(enable = TRUE)
Arguments
enable
New value.
Method logEvent()
Add event to log.
Usage
ShinyDriver$logEvent(event, ...)
Arguments
event
Event name
...
Addition data to store for event
Method getEventLog()
Retrieve event log.
Usage
ShinyDriver$getEventLog()
Method getUrl()
Get current url
Usage
ShinyDriver$getUrl()
Method getTitle()
Get page title
Usage
ShinyDriver$getTitle()
Method getSource()
Get complete source of current page.
Usage
ShinyDriver$getSource()
Method goBack()
Return to previous page
Usage
ShinyDriver$goBack()
Returns
Self, invisibly.
Method refresh()
Refresh the browser
Usage
ShinyDriver$refresh()
Returns
Self, invisibly.
Method takeScreenshot()
Takes a screenshot of the current page and writes it to a PNG file or shows on current graphics device.
Usage
ShinyDriver$takeScreenshot(file = NULL, id = NULL, parent = FALSE)
Arguments
file
File name to save the screenshot to. If
NULL
, then it will be shown on the R graphics device.id
If not-
NULL
, will take a screenshot of element with this id.parent
If
TRUE
, will take screenshot of parent ofid
; this is useful if you also want to capture the label attached to a Shiny control.
Returns
Self, invisibly.
Method findElement()
Find an HTML element on the page, using a CSS selector, XPath expression,
or link text (for <a>
tags). If multiple elements are matched, only
the first is returned.
Usage
ShinyDriver$findElement( css = NULL, linkText = NULL, partialLinkText = NULL, xpath = NULL )
Arguments
css
CSS selector to find an HTML element.
linkText
Find
<a>
HTML elements based on exactinnerText
partialLinkText
Find
<a>
HTML elements based on partialinnerText
xpath
Find HTML elements using XPath expressions.
Returns
Method findElements()
Find all elements matching CSS selection, xpath, or link text.
Usage
ShinyDriver$findElements( css = NULL, linkText = NULL, partialLinkText = NULL, xpath = NULL )
Arguments
css
CSS selector to find an HTML element.
linkText
Find
<a>
HTML elements based on exactinnerText
partialLinkText
Find
<a>
HTML elements based on partialinnerText
xpath
Find HTML elements using XPath expressions.
Returns
A list of webdriver::Elements.
Method waitFor()
Waits until a JavaScript expr
ession evaluates to true
or the
timeout
is exceeded.
Usage
ShinyDriver$waitFor(expr, checkInterval = 100, timeout = 3000)
Arguments
expr
A string containing JavaScript code. Will wait until the condition returns
true
.checkInterval
How often to check for the condition, in ms.
timeout
Amount of time to wait before giving up (milliseconds).
Returns
TRUE
if expression evaluates to true
without error, before
timeout. Otherwise returns NA
.
Method waitForShiny()
Waits until Shiny is not busy, i.e. the reactive graph has finished
updating. This is useful, for example, if you've resized the window with
setWindowSize()
and want to make sure all plot redrawing is complete
before take a screenshot.
Usage
ShinyDriver$waitForShiny()
Returns
TRUE
if done before before timeout; NA
otherwise.
Method waitForValue()
Waits until the input
or output
with name name
is not one of
ignore
d values, or the timeout is reached.
This function can be useful in helping determine if an application has initialized or finished processing a complex reactive situation.
Usage
ShinyDriver$waitForValue( name, ignore = list(NULL, ""), iotype = c("input", "output", "export"), timeout = 10000, checkInterval = 400 )
Arguments
name
Name of a shiny widget.
ignore
List of possible values to ignore when checking for updates.
iotype
Type of the Shiny widget. Usually shinytest finds the widgets by their name, so this is only needed if you use the same name for an input and output widget.
timeout
Amount of time to wait before giving up (milliseconds).
checkInterval
How often to check for the condition, in ms.
Method listWidgets()
Lists the names of all input and output widgets
Usage
ShinyDriver$listWidgets()
Returns
A list of two character vectors, named input
and output
.
Method checkUniqueWidgetNames()
Check if Shiny widget names are unique.
Usage
ShinyDriver$checkUniqueWidgetNames()
Method executeScript()
Execute JS code
Usage
ShinyDriver$executeScript(script, ...)
Arguments
script
JS to execute.
...
Additional arguments to script.
Returns
Self, invisibly.
Method executeScriptAsync()
Execute JS code asynchronously.
Usage
ShinyDriver$executeScriptAsync(script, ...)
Arguments
script
JS to execute.
...
Additional arguments to script.
Returns
Self, invisibly.
Method findWidget()
Finds the a Shiny input or output control.
Usage
ShinyDriver$findWidget(name, iotype = c("auto", "input", "output"))
Arguments
name
Name of a shiny widget.
iotype
Type of the Shiny widget. Usually shinytest finds the widgets by their name, so this is only needed if you use the same name for an input and output widget.
Returns
A Widget.
Method expectUpdate()
It performs one or more update operations via the browser, thens
waits for the specified output(s) to update. The test succeeds if
all specified output widgets are updated before the timeout
.
For updates that involve a lot of computation, increase the timeout.
Usage
ShinyDriver$expectUpdate( output, ..., timeout = 3000, iotype = c("auto", "input", "output") )
Arguments
output
Name of output control to check.
...
Name-value pairs used to update inputs.
timeout
Amount of time to wait before giving up (milliseconds).
iotype
Type of the Shiny widget. Usually shinytest finds the widgets by their name, so this is only needed if you use the same name for an input and output widget.
Method setInputs()
Sets input values.
Usage
ShinyDriver$setInputs( ..., wait_ = TRUE, values_ = TRUE, timeout_ = 3000, allowInputNoBinding_ = FALSE, priority_ = c("input", "event") )
Arguments
...
Name-value pairs,
name1 = value1, name2 = value2
etc. Enput with namename1
will be assigned valuevalue1
.wait_
Wait until all reactive updates have completed?
values_
If
TRUE
, will return final updated values of inputs.timeout_
Amount of time to wait before giving up (milliseconds).
allowInputNoBinding_
When setting the value of an input, allow it to set the value of an input even if that input does not have an input binding.
priority_
Sets the event priority. For expert use only: see https://shiny.rstudio.com/articles/communicating-with-js.html#values-vs-events for details.
Returns
Returns updated values, invisibly.
Method uploadFile()
Uploads a file to a file input.
Usage
ShinyDriver$uploadFile(..., wait_ = TRUE, values_ = TRUE, timeout_ = 3000)
Arguments
...
Name-path pairs, e.g.
name1 = path1
. The file located atpath1
will be uploaded to file input with namename1
.wait_
Wait until all reactive updates have completed?
values_
If
TRUE
, will return final updated values of download control.timeout_
Amount of time to wait before giving up (milliseconds).
Method snapshotInit()
Download a snapshot. Generally, you should not call this function
yourself; it will be generated by recordTest()
as needed.
Usage
ShinyDriver$snapshotInit(path, screenshot = TRUE)
Arguments
path
Directory to save snapshots.
screenshot
Take screenshots for each snapshot?
Method snapshot()
Take a snapshot. Generally, you should not call this function
yourself; it will be generated by recordTest()
as needed.
Usage
ShinyDriver$snapshot(items = NULL, filename = NULL, screenshot = NULL)
Arguments
items
Elements to include in snapshot
filename
Filename to use. It is recommended to use a
.json
file extension.screenshot
Take a screenshot? Overrides value set by
$snapshotInit()
Method snapshotCompare()
Deprecated
Usage
ShinyDriver$snapshotCompare(...)
Arguments
...
Ignored
Method snapshotDownload()
Snapshot a file download action. Generally, you should not call this
function yourself; it will be generated by recordTest()
as needed.
Usage
ShinyDriver$snapshotDownload(id, filename = NULL)
Arguments
id
Output id of
shiny::downloadButton()
/shiny::downloadLink()
filename
File name to save file to. The default,
NULL
, generates an ascending sequence of names:001.download
,002.download
, etc.
Method getAppDir()
Directory where app is located
Usage
ShinyDriver$getAppDir()
Method getAppFilename()
App file name, i.e. app.R
or server.R
. NULL
for Rmds.
Usage
ShinyDriver$getAppFilename()
Method getTestsDir()
Directory where tests are located
Usage
ShinyDriver$getTestsDir()
Method getRelativePathToApp()
Relative path to app from current directory.
Usage
ShinyDriver$getRelativePathToApp()
Method getSnapshotDir()
Directory where snapshots are located.
Usage
ShinyDriver$getSnapshotDir()
Method isRmd()
Is this app an Shiny Rmd document?
Usage
ShinyDriver$isRmd()
Method clone()
The objects of this class are cloneable with this method.
Usage
ShinyDriver$clone(deep = FALSE)
Arguments
deep
Whether to make a deep clone.
A Shiny Widget
Description
A Widget
object represents a Shiny input or output control, and provides
methods for finer grained interaction.
Methods
Public methods
Method new()
Create new Widget
Usage
Widget$new(name, element, type, iotype = c("input", "output"))
Arguments
name
Name of a Shiny widget.
element
type
Widget type
iotype
Input/output type.
Method getName()
Control id (i.e. inputId
or outputId
that control
was created with).
Usage
Widget$getName()
Method getElement()
Underlying webdriver::Element()
object.
Usage
Widget$getElement()
Method getHtml()
retrieve the underlying HTML for a widget
Usage
Widget$getHtml()
Method getType()
Widget type, e.g. textInput
, selectInput
.
Usage
Widget$getType()
Method getIoType()
Is this an input or output control?
Usage
Widget$getIoType()
Method isInput()
Is this an input control?
Usage
Widget$isInput()
Method isOutput()
Is this an output control?
Usage
Widget$isOutput()
Method getValue()
Get current value of control.
Usage
Widget$getValue()
Method setValue()
Set value of control.
Usage
Widget$setValue(value)
Arguments
value
Value to set for the widget.
Method click()
scrolls the element into view, then clicks the in-view centre point of it.
Usage
Widget$click()
Returns
self, invisibly.
Method sendKeys()
Send specified key presses to control.
Usage
Widget$sendKeys(keys)
Arguments
keys
Keys to send to the widget or the app. See webdriver::key for how to specific special keys.
Method listTabs()
Lists the tab names of a shiny::tabsetPanel()
.
It fails for other types of widgets.
Usage
Widget$listTabs()
Method uploadFile()
Upload a file to a shiny::fileInput()
.
It fails for other types of widgets.
Usage
Widget$uploadFile(filename)
Arguments
filename
Path to file to upload
Method clone()
The objects of this class are cloneable with this method.
Usage
Widget$clone(deep = FALSE)
Arguments
deep
Whether to make a deep clone.
Checks for/installs dependencies
Description
dependenciesInstalled()
that all the required system dependency,
PhantomJS, is installed, and installDependencies()
installs it if needed.
For more information about where PhantomJS will be installed
see webdriver::install_phantomjs()
.
Usage
dependenciesInstalled()
installDependencies()
Value
TRUE
when all dependencies are fulfilled; otherwise, FALSE
.
Creat an htmlwidget that shows differences between files or directories
Description
This function can be used for viewing differences between current test results and the expected results
Usage
diffviewer_widget(old, new, width = NULL, height = NULL, pattern = NULL)
Arguments
old , new |
Names of the old and new directories to compare. Alternatively, they can be a character vectors of specific files to compare. |
width |
Width of the htmlwidget. |
height |
Height of the htmlwidget |
pattern |
A filter to apply to the old and new directories. |
testthat
expectation for a Shiny update
Description
testthat
expectation for a Shiny update
Usage
expectUpdate(
app,
output,
...,
timeout = 3000,
iotype = c("auto", "input", "output")
)
Arguments
app |
A |
output |
Character vector, the name(s) of the output widgets that are required to update for the test to succeed. |
... |
Named arguments specifying updates for Shiny input widgets. |
timeout |
Timeout for the update to happen, in milliseconds. |
iotype |
Type of the widget(s) to change. These are normally input widgets. |
Examples
## Not run:
## https://github.com/rstudio/shiny-examples/tree/main/050-kmeans-example
app <- ShinyDriver$new("050-kmeans-example")
expectUpdate(app, xcol = "Sepal.Width", output = "plot1")
expectUpdate(app, ycol = "Petal.Width", output = "plot1")
expectUpdate(app, clusters = 4, output = "plot1")
## End(Not run)
Expectation: testApp()
passes snapshot tests
Description
This returns an testthat expectation object.
Usage
expect_pass(object, info = NULL)
Arguments
object |
The results returned by |
info |
Extra information to be included in the message (useful when writing tests in loops). |
Examples
## Not run:
expect_pass(testApp("path/to/app/"))
## End(Not run)
Migrate legacy shinytest files to new test directory structure
Description
This function migrates the old-style directory structure used by shinytest (versions 1.3.1 and below) to new test directory structure used in shinytest 1.4.0 and above.
Usage
migrateShinytestDir(appdir, dryrun = FALSE)
Arguments
appdir |
A directory containing a Shiny application. |
dryrun |
If |
Details
Before shinytest 1.4.0, the shinytest scripts and results were put in a
subdirectory of the application named tests/
. As of shinytest 1.4.0,
the tests are put in tests/shinytest/
, so that it works with the
runTests()
function shiny package (added in shiny 1.5.0).
With shinytest 1.3.1 and below, the tests/ subdirectory of the application was used specifically for shinytest, and could not be used for other types of tests. So the directory structure would look like this:
appdir/ `- tests `- mytest.R
In Shiny 1.5.0, the shiny::runTests()
function was added, and it will run
test scripts tests/ subdirectory of the application. This makes it possible
to use other testing systems in addition to shinytest. shinytest 1.4.0
is designed to work with this new directory structure. The directory
structure looks something like this:
appdir/ |- R |- tests |- shinytest.R |- shinytest | `- mytest.R |- testthat.R `- testthat `- test-script.R
This allows for tests using the shinytest package as well as other
testing tools, such as the shiny::testServer()
function, which can be used
for testing module and server logic, and for unit tests of functions in an R/
subdirectory.
In shinytest 1.4.0 and above, it defaults to creating the new directory structure.
Get the name of the OS
Description
Returns the name of the current OS. This can be useful for the suffix
when
running testApp()
.
Usage
osName()
Launch test event recorder for a Shiny app
Description
Launch test event recorder for a Shiny app
Usage
recordTest(
app = ".",
save_dir = NULL,
load_mode = FALSE,
seed = NULL,
loadTimeout = 10000,
debug = "shiny_console",
shinyOptions = list()
)
Arguments
app |
A |
save_dir |
A directory to save stuff. |
load_mode |
A boolean that determines whether or not the resulting test script should be appropriate for load testing. |
seed |
A random seed to set before running the app. This seed will also be used in the test script. |
loadTimeout |
Maximum time to wait for the Shiny application to load, in milliseconds. If a value is provided, it will be saved in the test script. |
debug |
start the underlying |
shinyOptions |
A list of options to pass to |
Register an input processor for the test recorder
Description
registerInputProcessor()
registers an input processor which will be used by
the test recorder. The input processor function should take one parameter,
value
, and return a string of R code which returns the desired value.
getInputProcessors()
returns a named list of all registered input processor
functions.
Usage
registerInputProcessor(inputType, processor)
getInputProcessors()
Arguments
inputType |
The name of an input type, for example,
|
processor |
An input processor function. |
Compare current and expected snapshots
Description
This compares current and expected snapshots for a test set, and prints any differences to the console.
Usage
snapshotCompare(
appDir,
testnames = NULL,
autoremove = TRUE,
images = TRUE,
quiet = FALSE,
interactive = is_interactive(),
suffix = NULL
)
snapshotUpdate(appDir = ".", testnames = NULL, quiet = FALSE, suffix = NULL)
Arguments
appDir |
Directory that holds the tests for an application. This is the parent directory for the expected and current snapshot directories. |
testnames |
Name or names of a test. If NULL, compare all test results. |
autoremove |
If the current results match the expected results, should the current results be removed automatically? Defaults to TRUE. |
images |
Should screenshots and PNG images be compared? It can be useful
to set this to |
quiet |
Should output be suppressed? This is useful for automated testing. |
interactive |
If there are any differences between current results and expected results, provide an interactive graphical viewer that shows the changes and allows the user to accept or reject the changes. |
suffix |
An optional suffix for the expected results directory. For
example, if the suffix is |
See Also
Run tests for a Shiny application
Description
Run tests for a Shiny application
Usage
testApp(
appDir = ".",
testnames = NULL,
quiet = FALSE,
compareImages = TRUE,
interactive = is_interactive(),
suffix = NULL
)
Arguments
appDir |
Path to directory containing a Shiny app (e.g. |
testnames |
Test script(s) to run. The .R extension of the filename is
optional. For example, |
quiet |
Should output be suppressed? This is useful for automated testing. |
compareImages |
Should screenshots be compared? It can be useful to set
this to |
interactive |
If there are any differences between current results and expected results, provide an interactive graphical viewer that shows the changes and allows the user to accept or reject the changes. |
suffix |
An optional suffix for the expected results directory. For
example, if the suffix is |
See Also
snapshotCompare()
and snapshotUpdate()
if
you want to compare or update snapshots after testing. In most cases, the
user is prompted to do these tasks interactively, but there are also times
where it is useful to call these functions from the console.
Get textual diff of test results
Description
Get textual diff of test results
Usage
textTestDiff(appDir = ".", testnames = NULL, images = TRUE, suffix = NULL)
Arguments
appDir |
Directory of the Shiny application that was tested. |
testnames |
A character vector of names of tests to compare. If NULL, compare all test results for which there are differences. |
images |
Compare screenshot images. |
suffix |
An optional suffix for the expected results directory. For
example, if the suffix is |
See Also
viewTestDiff()
for interactive diff viewer.
View differences in test results
Description
View differences in test results
Usage
viewTestDiff(
appDir = ".",
testnames = NULL,
interactive = is_interactive(),
images = TRUE,
suffix = NULL
)
Arguments
appDir |
Directory of the Shiny application that was tested. |
testnames |
A character vector of names of tests to compare. If NULL, compare all test results for which there are differences. |
interactive |
If TRUE, use the interactive diff viewer, which runs in a
Shiny app. If FALSE, print a textual diff, generated by
|
images |
Compare screenshot images (only used when |
suffix |
An optional suffix for the expected results directory. For
example, if the suffix is |
Value
A character vector the same length as testnames
, with
"accept"
or "reject"
for each test.
See Also
textTestDiff()
to get a text diff as a string.
Interactive viewer widget for changes in test results
Description
Interactive viewer widget for changes in test results
Usage
viewTestDiffWidget(appDir = ".", testname = NULL, suffix = NULL)
Arguments
appDir |
Directory of the Shiny application that was tested. |
testname |
Name of test to compare. |
suffix |
An optional suffix for the expected results directory. For
example, if the suffix is |