mirror of
https://github.com/rstudio/shiny.git
synced 2026-01-10 23:48:01 -05:00
Compare commits
37 Commits
wch-module
...
reactive_c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
550b679e61 | ||
|
|
8ada448c51 | ||
|
|
106ad74d2b | ||
|
|
0a6260259a | ||
|
|
78f9132eb3 | ||
|
|
15476ac32e | ||
|
|
17fb5b9eae | ||
|
|
fd27a0dfa2 | ||
|
|
5ffe69ec6c | ||
|
|
f5723b2a4d | ||
|
|
01491cc696 | ||
|
|
568a3f28cf | ||
|
|
02219df480 | ||
|
|
212b33a0ce | ||
|
|
6b7a121161 | ||
|
|
c89da718b1 | ||
|
|
eef3ae8387 | ||
|
|
0975a61725 | ||
|
|
0c53d54347 | ||
|
|
cbbb04cf69 | ||
|
|
120baf0a6e | ||
|
|
685dc7cc3a | ||
|
|
2fbb2ac77b | ||
|
|
2832db7aba | ||
|
|
18f2471d7c | ||
|
|
ea28f5a61b | ||
|
|
fe9cc6038e | ||
|
|
5ed335c499 | ||
|
|
fd04b97496 | ||
|
|
4c9d281b59 | ||
|
|
2ee06a7cbf | ||
|
|
cf2ba90b1d | ||
|
|
c69f34d1e2 | ||
|
|
ccfcc5d8b4 | ||
|
|
210c248264 | ||
|
|
e3258657d0 | ||
|
|
dbc518bf53 |
@@ -5,6 +5,7 @@ matrix:
|
||||
r: release
|
||||
r_packages:
|
||||
- devtools
|
||||
- rprojroot
|
||||
script: ./tools/checkDocsCurrent.sh
|
||||
- name: "Javascript check"
|
||||
language: node_js
|
||||
@@ -25,7 +26,3 @@ notifications:
|
||||
email:
|
||||
on_success: change
|
||||
on_failure: change
|
||||
slack:
|
||||
on_success: change
|
||||
secure: QoM0+hliVC4l2HYv126AkljG/uFvgwayW9IpuB5QNqjSukM122MhMDL7ZuMB9a2vWP24juzOTXiNIymgEspfnvvAMnZwYRBNWkuot2m8HIR2B9UjQLiztFnN1EAT+P+thz8Qax9TV2SOfXb2S2ZOeZmRTVkJctxkL8heAZadIC4=
|
||||
on_pull_requests: false
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Package: shiny
|
||||
Type: Package
|
||||
Title: Web Application Framework for R
|
||||
Version: 1.4.0.9001
|
||||
Version: 1.4.0.9002
|
||||
Authors@R: c(
|
||||
person("Winston", "Chang", role = c("aut", "cre"), email = "winston@rstudio.com"),
|
||||
person("Joe", "Cheng", role = "aut", email = "joe@rstudio.com"),
|
||||
@@ -173,6 +173,6 @@ Collate:
|
||||
'test-module.R'
|
||||
'test.R'
|
||||
'update-input.R'
|
||||
RoxygenNote: 7.0.2
|
||||
RoxygenNote: 7.1.0
|
||||
Encoding: UTF-8
|
||||
Roxygen: list(markdown = TRUE)
|
||||
|
||||
10
NEWS.md
10
NEWS.md
@@ -17,6 +17,10 @@ shiny 1.4.0.9001
|
||||
|
||||
* Added a label to observer that auto-reloads `R/` directory to avoid confusion when using `reactlog`. ([#58](https://github.com/rstudio/reactlog/issues/58))
|
||||
|
||||
* `getDefaultReactiveDomain()` can now be called inside a `session$onSessionEnded` callback and will return the calling `session` information. ([#2757](https://github.com/rstudio/shiny/pull/2757))
|
||||
|
||||
* Added a `'function'` class to `reactive()` and `reactiveVal()` objects. ([#2793](https://github.com/rstudio/shiny/pull/2793))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
* Fixed [#2606](https://github.com/rstudio/shiny/issues/2606): `debounce()` would not work properly if the code in the reactive expression threw an error on the first run. ([#2652](https://github.com/rstudio/shiny/pull/2652))
|
||||
@@ -26,6 +30,12 @@ shiny 1.4.0.9001
|
||||
### Documentation Updates
|
||||
|
||||
|
||||
shiny 1.4.0.1
|
||||
===========
|
||||
|
||||
Minor patch release to account for changes to the grid package that will be upcoming in the R 4.0 release ([#2776](https://github.com/rstudio/shiny/pull/2776)).
|
||||
|
||||
|
||||
shiny 1.4.0
|
||||
===========
|
||||
|
||||
|
||||
@@ -80,7 +80,6 @@ extract <- function(promise) {
|
||||
MockShinySession <- R6Class(
|
||||
'MockShinySession',
|
||||
portable = FALSE,
|
||||
class = FALSE,
|
||||
public = list(
|
||||
#' @field env The environment associated with the session.
|
||||
env = NULL,
|
||||
@@ -381,6 +380,8 @@ MockShinySession <- R6Class(
|
||||
flushReact = function(){
|
||||
private$flush()
|
||||
},
|
||||
#' @description Create and return a namespace-specific session proxy.
|
||||
#' @param namespace Character vector indicating a namespace.
|
||||
makeScope = function(namespace) {
|
||||
ns <- NS(namespace)
|
||||
createSessionProxy(
|
||||
|
||||
10
R/modules.R
10
R/modules.R
@@ -91,7 +91,9 @@ createSessionProxy <- function(parentSession, ...) {
|
||||
#' counterServer("counter1")
|
||||
#' counterServer("counter2")
|
||||
#' }
|
||||
#' shinyApp(ui, server)
|
||||
#' if (interactive()) {
|
||||
#' shinyApp(ui, server)
|
||||
#' }
|
||||
#'
|
||||
#'
|
||||
#'
|
||||
@@ -117,7 +119,9 @@ createSessionProxy <- function(parentSession, ...) {
|
||||
#' server <- function(input, output, session) {
|
||||
#' counterServer2("counter", "The current count is: ")
|
||||
#' }
|
||||
#' shinyApp(ui, server)
|
||||
#' if (interactive()) {
|
||||
#' shinyApp(ui, server)
|
||||
#' }
|
||||
#'
|
||||
#' @export
|
||||
moduleServer <- function(id, module, session = getDefaultReactiveDomain()) {
|
||||
@@ -128,7 +132,7 @@ moduleServer <- function(id, module, session = getDefaultReactiveDomain()) {
|
||||
#' @rdname moduleServer
|
||||
#' @export
|
||||
callModule <- function(module, id, ..., session = getDefaultReactiveDomain()) {
|
||||
if (!inherits(session, "ShinySession") && !inherits(session, "session_proxy")) {
|
||||
if (!inherits(session, c("ShinySession", "session_proxy", "MockShinySession"))) {
|
||||
stop("session must be a ShinySession or session_proxy object.")
|
||||
}
|
||||
childScope <- session$makeScope(id)
|
||||
|
||||
@@ -222,7 +222,7 @@ reactiveVal <- function(value = NULL, label = NULL) {
|
||||
rv$set(x)
|
||||
}
|
||||
},
|
||||
class = c("reactiveVal", "reactive"),
|
||||
class = c("reactiveVal", "reactive", "function"),
|
||||
label = label,
|
||||
.impl = rv
|
||||
)
|
||||
@@ -969,7 +969,7 @@ reactive <- function(x, env = parent.frame(), quoted = FALSE, label = NULL,
|
||||
if (length(srcref) >= 2) attr(label, "srcref") <- srcref[[2]]
|
||||
attr(label, "srcfile") <- srcFileOfRef(srcref[[1]])
|
||||
o <- Observable$new(fun, label, domain, ..stacktraceon = ..stacktraceon)
|
||||
structure(o$getValue, observable = o, class = c("reactiveExpr", "reactive"))
|
||||
structure(o$getValue, observable = o, class = c("reactiveExpr", "reactive", "function"))
|
||||
}
|
||||
|
||||
# Given the srcref to a reactive expression, attempts to figure out what the
|
||||
|
||||
@@ -889,6 +889,14 @@ find_panel_info_non_api <- function(b, ggplot_format) {
|
||||
})
|
||||
}
|
||||
|
||||
# Use public API for getting the unit's type (grid::unitType(), added in R 4.0)
|
||||
# https://github.com/wch/r-source/blob/f9b8a42/src/library/grid/R/unit.R#L179
|
||||
getUnitType <- function(u) {
|
||||
tryCatch(
|
||||
get("unitType", envir = asNamespace("grid"))(u),
|
||||
error = function(e) attr(u, "unit", exact = TRUE)
|
||||
)
|
||||
}
|
||||
|
||||
# Given a gtable object, return the x and y ranges (in pixel dimensions)
|
||||
find_panel_ranges <- function(g, res) {
|
||||
@@ -904,11 +912,11 @@ find_panel_ranges <- function(g, res) {
|
||||
if (inherits(x, "unit.list")) {
|
||||
# For ggplot2 <= 1.0.1
|
||||
vapply(x, FUN.VALUE = logical(1), function(u) {
|
||||
isTRUE(attr(u, "unit", exact = TRUE) == "null")
|
||||
isTRUE(getUnitType(u) == "null")
|
||||
})
|
||||
} else {
|
||||
# For later versions of ggplot2
|
||||
attr(x, "unit", exact = TRUE) == "null"
|
||||
getUnitType(x) == "null"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -948,7 +956,11 @@ find_panel_ranges <- function(g, res) {
|
||||
|
||||
# The plotting panels all are 'null' units.
|
||||
null_sizes <- rep(NA_real_, length(rel_sizes))
|
||||
null_sizes[null_idx] <- as.numeric(rel_sizes[null_idx])
|
||||
# Workaround for `[.unit` forbidding zero-length subsets
|
||||
# https://github.com/wch/r-source/blob/f9b8a42/src/library/grid/R/unit.R#L448-L450
|
||||
if (length(null_idx)) {
|
||||
null_sizes[null_idx] <- as.numeric(rel_sizes[null_idx])
|
||||
}
|
||||
|
||||
# Total size allocated for panels is the total image size minus absolute
|
||||
# (non-panel) elements.
|
||||
|
||||
@@ -962,7 +962,9 @@ ShinySession <- R6Class(
|
||||
output$suspend()
|
||||
}
|
||||
# ..stacktraceon matches with the top-level ..stacktraceoff..
|
||||
private$closedCallbacks$invoke(onError = printError, ..stacktraceon = TRUE)
|
||||
withReactiveDomain(self, {
|
||||
private$closedCallbacks$invoke(onError = printError, ..stacktraceon = TRUE)
|
||||
})
|
||||
},
|
||||
isClosed = function() {
|
||||
return(self$closed)
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#' @param ... Additional arguments to pass to the module function. These
|
||||
#' arguments are processed with [rlang::list2()] and so are
|
||||
#' _[dynamic][rlang::dyn-dots]_.
|
||||
#' @return The result of evaluating `expr`.
|
||||
#' @include mock-session.R
|
||||
#' @rdname testModule
|
||||
#' @examples
|
||||
@@ -55,53 +56,58 @@
|
||||
#' }, !!multiplier_arg_name := 2, !!!more_args)
|
||||
#' @export
|
||||
testModule <- function(module, expr, ...) {
|
||||
expr <- substitute(expr)
|
||||
.testModule(module, expr, ...)
|
||||
.testModule(
|
||||
module,
|
||||
quosure = rlang::enquo(expr),
|
||||
dots = rlang::list2(...),
|
||||
env = rlang::caller_env()
|
||||
)
|
||||
}
|
||||
|
||||
#' @noRd
|
||||
#' @importFrom withr with_options
|
||||
.testModule <- function(module, expr, ...) {
|
||||
# Capture the environment from the module
|
||||
# Inserts `session$env <- environment()` at the top of the function
|
||||
.testModule <- function(module, quosure, dots, env) {
|
||||
# Modify the module function locally by inserting `session$env <-
|
||||
# environment()` at the beginning of its body. The dynamic environment of the
|
||||
# module function is saved so that it may be referenced after the module
|
||||
# function has returned. The saved dynamic environment is the basis for the
|
||||
# `data` argument of tidy_eval() when used below to evaluate `quosure`, the
|
||||
# test code expression.
|
||||
body(module) <- rlang::expr({
|
||||
session$env <- environment()
|
||||
session$env <- base::environment()
|
||||
!!!body(module)
|
||||
})
|
||||
|
||||
# Create a mock session
|
||||
session <- MockShinySession$new()
|
||||
on.exit(if (!session$isClosed()) session$close())
|
||||
args <- append(dots, list(input = session$input, output = session$output, session = session))
|
||||
|
||||
# Parse the additional arguments
|
||||
args <- rlang::list2(..., input = session$input, output = session$output, session = session)
|
||||
|
||||
# Initialize the module
|
||||
isolate(
|
||||
withReactiveDomain(
|
||||
session,
|
||||
withr::with_options(list(`shiny.allowoutputreads`=TRUE), {
|
||||
# Remember that invoking this module implicitly assigns to `session$env`
|
||||
# Also, assigning to `$returned` will cause a flush to happen automatically.
|
||||
# Assigning to `$returned` causes a flush to happen automatically.
|
||||
session$returned <- do.call(module, args)
|
||||
})
|
||||
)
|
||||
)
|
||||
|
||||
# Run the test expression in a reactive context and in the module's environment.
|
||||
# We don't need to flush before entering the loop because the first expr that we execute is `{`.
|
||||
# So we'll already flush before we get to the good stuff.
|
||||
# Evaluate `quosure` in a reactive context, and in the provided `env`, but
|
||||
# with `env` masked by a shallow view of `session$env`, the environment that
|
||||
# was saved when the module function was invoked. flush is not needed before
|
||||
# entering the loop because the first expr executed is `{`.
|
||||
isolate({
|
||||
withReactiveDomain(
|
||||
session,
|
||||
withr::with_options(list(`shiny.allowoutputreads`=TRUE), {
|
||||
eval(expr, new.env(parent=session$env))
|
||||
rlang::eval_tidy(
|
||||
quosure,
|
||||
data = rlang::as_data_mask(as.list(session$env)),
|
||||
env = env
|
||||
)
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
if (!session$isClosed()){
|
||||
session$close()
|
||||
}
|
||||
}
|
||||
|
||||
#' Test an app's server-side logic
|
||||
@@ -130,8 +136,14 @@ testServer <- function(expr, appDir=NULL) {
|
||||
formals(server) <- fn_formals
|
||||
}
|
||||
|
||||
# Now test the server as we would a module
|
||||
.testModule(server, expr=substitute(expr))
|
||||
# Test the server function almost as if it were a module. `dots` is empty
|
||||
# because server functions never take additional arguments.
|
||||
.testModule(
|
||||
server,
|
||||
quosure = rlang::enquo(expr),
|
||||
dots = list(),
|
||||
env = rlang::caller_env()
|
||||
)
|
||||
}
|
||||
|
||||
findApp <- function(startDir="."){
|
||||
|
||||
@@ -207,7 +207,7 @@ reference:
|
||||
desc: Functions for modularizing Shiny apps
|
||||
contents:
|
||||
- NS
|
||||
- callModule
|
||||
- moduleServer
|
||||
- title: Embedding
|
||||
desc: Functions that are intended for third-party packages that embed Shiny applications.
|
||||
contents:
|
||||
|
||||
@@ -12,7 +12,7 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
|
||||
|
||||
var exports = window.Shiny = window.Shiny || {};
|
||||
|
||||
exports.version = "1.4.0.9001"; // Version number inserted by Grunt
|
||||
exports.version = "1.4.0.9002"; // Version number inserted by Grunt
|
||||
|
||||
var origPushState = window.history.pushState;
|
||||
window.history.pushState = function () {
|
||||
|
||||
4
inst/www/shared/shiny.min.js
vendored
4
inst/www/shared/shiny.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -2,13 +2,18 @@
|
||||
\alias{HTML}
|
||||
\title{Mark Characters as HTML}
|
||||
\usage{
|
||||
HTML(text, ...)
|
||||
HTML(text, ..., .noWS = NULL)
|
||||
}
|
||||
\arguments{
|
||||
\item{text}{The text value to mark with HTML}
|
||||
|
||||
\item{...}{Any additional values to be converted to character and
|
||||
concatenated together}
|
||||
|
||||
\item{.noWS}{Character vector used to omit some of the whitespace that would
|
||||
normally be written around this HTML. Valid options include \code{before},
|
||||
\code{after}, and \code{outside} (equivalent to \code{before} and
|
||||
\code{end}).}
|
||||
}
|
||||
\value{
|
||||
The same value, but marked as HTML.
|
||||
|
||||
@@ -88,6 +88,7 @@ s$setInputs(x=1, y=2)
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-reactlog"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-reactlog}{}}}
|
||||
\subsection{Method \code{reactlog()}}{
|
||||
No-op
|
||||
\subsection{Usage}{
|
||||
@@ -104,6 +105,7 @@ No-op
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-incrementBusyCount"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-incrementBusyCount}{}}}
|
||||
\subsection{Method \code{incrementBusyCount()}}{
|
||||
No-op
|
||||
\subsection{Usage}{
|
||||
@@ -113,6 +115,7 @@ No-op
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-new"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-new}{}}}
|
||||
\subsection{Method \code{new()}}{
|
||||
Create a new MockShinySession
|
||||
\subsection{Usage}{
|
||||
@@ -122,6 +125,7 @@ Create a new MockShinySession
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-onFlush"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-onFlush}{}}}
|
||||
\subsection{Method \code{onFlush()}}{
|
||||
Define a callback to be invoked before a reactive flush
|
||||
\subsection{Usage}{
|
||||
@@ -140,6 +144,7 @@ Define a callback to be invoked before a reactive flush
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-onFlushed"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-onFlushed}{}}}
|
||||
\subsection{Method \code{onFlushed()}}{
|
||||
Define a callback to be invoked after a reactive flush
|
||||
\subsection{Usage}{
|
||||
@@ -158,6 +163,7 @@ Define a callback to be invoked after a reactive flush
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-onEnded"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-onEnded}{}}}
|
||||
\subsection{Method \code{onEnded()}}{
|
||||
Define a callback to be invoked when the session ends
|
||||
\subsection{Usage}{
|
||||
@@ -174,6 +180,7 @@ Define a callback to be invoked when the session ends
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-isEnded"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-isEnded}{}}}
|
||||
\subsection{Method \code{isEnded()}}{
|
||||
Returns \code{FALSE} if the session has not yet been closed
|
||||
\subsection{Usage}{
|
||||
@@ -183,6 +190,7 @@ Returns \code{FALSE} if the session has not yet been closed
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-isClosed"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-isClosed}{}}}
|
||||
\subsection{Method \code{isClosed()}}{
|
||||
Returns \code{FALSE} if the session has not yet been closed
|
||||
\subsection{Usage}{
|
||||
@@ -192,6 +200,7 @@ Returns \code{FALSE} if the session has not yet been closed
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-close"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-close}{}}}
|
||||
\subsection{Method \code{close()}}{
|
||||
Closes the session
|
||||
\subsection{Usage}{
|
||||
@@ -201,6 +210,7 @@ Closes the session
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-cycleStartAction"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-cycleStartAction}{}}}
|
||||
\subsection{Method \code{cycleStartAction()}}{
|
||||
Unsophisticated mock implementation that merely invokes
|
||||
the given callback immediately.
|
||||
@@ -218,6 +228,7 @@ the given callback immediately.
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-fileUrl"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-fileUrl}{}}}
|
||||
\subsection{Method \code{fileUrl()}}{
|
||||
Base64-encode the given file. Needed for image rendering.
|
||||
\subsection{Usage}{
|
||||
@@ -238,6 +249,7 @@ Base64-encode the given file. Needed for image rendering.
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-setInputs"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-setInputs}{}}}
|
||||
\subsection{Method \code{setInputs()}}{
|
||||
Sets reactive values associated with the \code{session$inputs} object
|
||||
and flushes the reactives.
|
||||
@@ -264,6 +276,7 @@ s$setInputs(x=1, y=2)
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-.scheduleTask"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-.scheduleTask}{}}}
|
||||
\subsection{Method \code{.scheduleTask()}}{
|
||||
An internal method which shouldn't be used by others.
|
||||
\subsection{Usage}{
|
||||
@@ -282,6 +295,7 @@ An internal method which shouldn't be used by others.
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-elapse"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-elapse}{}}}
|
||||
\subsection{Method \code{elapse()}}{
|
||||
Simulate the passing of time by the given number of milliseconds.
|
||||
\subsection{Usage}{
|
||||
@@ -298,6 +312,7 @@ Simulate the passing of time by the given number of milliseconds.
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-.now"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-.now}{}}}
|
||||
\subsection{Method \code{.now()}}{
|
||||
An internal method which shouldn't be used by others.
|
||||
\subsection{Usage}{
|
||||
@@ -307,6 +322,7 @@ An internal method which shouldn't be used by others.
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-defineOutput"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-defineOutput}{}}}
|
||||
\subsection{Method \code{defineOutput()}}{
|
||||
An internal method which shouldn't be used by others.
|
||||
\subsection{Usage}{
|
||||
@@ -327,6 +343,7 @@ An internal method which shouldn't be used by others.
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-getOutput"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-getOutput}{}}}
|
||||
\subsection{Method \code{getOutput()}}{
|
||||
An internal method which shouldn't be used by others.
|
||||
\subsection{Usage}{
|
||||
@@ -343,6 +360,7 @@ An internal method which shouldn't be used by others.
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-registerDataObj"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-registerDataObj}{}}}
|
||||
\subsection{Method \code{registerDataObj()}}{
|
||||
No-op
|
||||
\subsection{Usage}{
|
||||
@@ -363,6 +381,7 @@ No-op
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-allowReconnect"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-allowReconnect}{}}}
|
||||
\subsection{Method \code{allowReconnect()}}{
|
||||
No-op
|
||||
\subsection{Usage}{
|
||||
@@ -379,6 +398,7 @@ No-op
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-reload"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-reload}{}}}
|
||||
\subsection{Method \code{reload()}}{
|
||||
No-op
|
||||
\subsection{Usage}{
|
||||
@@ -388,6 +408,7 @@ No-op
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-resetBrush"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-resetBrush}{}}}
|
||||
\subsection{Method \code{resetBrush()}}{
|
||||
No-op
|
||||
\subsection{Usage}{
|
||||
@@ -404,6 +425,7 @@ No-op
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-sendCustomMessage"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-sendCustomMessage}{}}}
|
||||
\subsection{Method \code{sendCustomMessage()}}{
|
||||
No-op
|
||||
\subsection{Usage}{
|
||||
@@ -422,6 +444,7 @@ No-op
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-sendBinaryMessage"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-sendBinaryMessage}{}}}
|
||||
\subsection{Method \code{sendBinaryMessage()}}{
|
||||
No-op
|
||||
\subsection{Usage}{
|
||||
@@ -440,6 +463,7 @@ No-op
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-sendInputMessage"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-sendInputMessage}{}}}
|
||||
\subsection{Method \code{sendInputMessage()}}{
|
||||
No-op
|
||||
\subsection{Usage}{
|
||||
@@ -458,6 +482,7 @@ No-op
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-setBookmarkExclude"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-setBookmarkExclude}{}}}
|
||||
\subsection{Method \code{setBookmarkExclude()}}{
|
||||
No-op
|
||||
\subsection{Usage}{
|
||||
@@ -474,6 +499,7 @@ No-op
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-getBookmarkExclude"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-getBookmarkExclude}{}}}
|
||||
\subsection{Method \code{getBookmarkExclude()}}{
|
||||
No-op
|
||||
\subsection{Usage}{
|
||||
@@ -483,6 +509,7 @@ No-op
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-onBookmark"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-onBookmark}{}}}
|
||||
\subsection{Method \code{onBookmark()}}{
|
||||
No-op
|
||||
\subsection{Usage}{
|
||||
@@ -499,6 +526,7 @@ No-op
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-onBookmarked"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-onBookmarked}{}}}
|
||||
\subsection{Method \code{onBookmarked()}}{
|
||||
No-op
|
||||
\subsection{Usage}{
|
||||
@@ -515,6 +543,7 @@ No-op
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-doBookmark"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-doBookmark}{}}}
|
||||
\subsection{Method \code{doBookmark()}}{
|
||||
No-op
|
||||
\subsection{Usage}{
|
||||
@@ -524,6 +553,7 @@ No-op
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-onRestore"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-onRestore}{}}}
|
||||
\subsection{Method \code{onRestore()}}{
|
||||
No-op
|
||||
\subsection{Usage}{
|
||||
@@ -540,6 +570,7 @@ No-op
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-onRestored"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-onRestored}{}}}
|
||||
\subsection{Method \code{onRestored()}}{
|
||||
No-op
|
||||
\subsection{Usage}{
|
||||
@@ -556,6 +587,7 @@ No-op
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-exportTestValues"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-exportTestValues}{}}}
|
||||
\subsection{Method \code{exportTestValues()}}{
|
||||
No-op
|
||||
\subsection{Usage}{
|
||||
@@ -565,6 +597,7 @@ No-op
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-getTestSnapshotUrl"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-getTestSnapshotUrl}{}}}
|
||||
\subsection{Method \code{getTestSnapshotUrl()}}{
|
||||
No-op
|
||||
\subsection{Usage}{
|
||||
@@ -592,6 +625,7 @@ No-op
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-ns"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-ns}{}}}
|
||||
\subsection{Method \code{ns()}}{
|
||||
Returns the given id prefixed by \verb{mock-session-}.
|
||||
\subsection{Usage}{
|
||||
@@ -608,6 +642,7 @@ Returns the given id prefixed by \verb{mock-session-}.
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-flushReact"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-flushReact}{}}}
|
||||
\subsection{Method \code{flushReact()}}{
|
||||
Trigger a reactive flush right now.
|
||||
\subsection{Usage}{
|
||||
@@ -617,14 +652,24 @@ Trigger a reactive flush right now.
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-makeScope"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-makeScope}{}}}
|
||||
\subsection{Method \code{makeScope()}}{
|
||||
Create and return a namespace-specific session proxy.
|
||||
\subsection{Usage}{
|
||||
\if{html}{\out{<div class="r">}}\preformatted{MockShinySession$makeScope(namespace)}\if{html}{\out{</div>}}
|
||||
}
|
||||
|
||||
\subsection{Arguments}{
|
||||
\if{html}{\out{<div class="arguments">}}
|
||||
\describe{
|
||||
\item{\code{namespace}}{Character vector indicating a namespace.}
|
||||
}
|
||||
\if{html}{\out{</div>}}
|
||||
}
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-clone"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-clone}{}}}
|
||||
\subsection{Method \code{clone()}}{
|
||||
The objects of this class are cloneable with this method.
|
||||
\subsection{Usage}{
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
\alias{NS}
|
||||
\alias{ns.sep}
|
||||
\title{Namespaced IDs for inputs/outputs}
|
||||
\format{An object of class \code{character} of length 1.}
|
||||
\format{
|
||||
An object of class \code{character} of length 1.
|
||||
}
|
||||
\usage{
|
||||
NS(namespace, id = NULL)
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ shinyApp(ui, server)
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-new"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-new}{}}}
|
||||
\subsection{Method \code{new()}}{
|
||||
Creates a new progress panel (but does not display it).
|
||||
\subsection{Usage}{
|
||||
@@ -107,6 +108,7 @@ is for backward-compatibility).}
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-set"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-set}{}}}
|
||||
\subsection{Method \code{set()}}{
|
||||
Updates the progress panel. When called the first time, the
|
||||
progress panel is displayed.
|
||||
@@ -134,6 +136,7 @@ relative to \code{message}.}
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-inc"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-inc}{}}}
|
||||
\subsection{Method \code{inc()}}{
|
||||
Like \code{set}, this updates the progress panel. The difference
|
||||
is that \code{inc} increases the progress bar by \code{amount}, instead of
|
||||
@@ -161,6 +164,7 @@ relative to \code{message}.}
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-getMin"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-getMin}{}}}
|
||||
\subsection{Method \code{getMin()}}{
|
||||
Returns the minimum value.
|
||||
\subsection{Usage}{
|
||||
@@ -170,6 +174,7 @@ Returns the minimum value.
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-getMax"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-getMax}{}}}
|
||||
\subsection{Method \code{getMax()}}{
|
||||
Returns the maximum value.
|
||||
\subsection{Usage}{
|
||||
@@ -179,6 +184,7 @@ Returns the maximum value.
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-getValue"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-getValue}{}}}
|
||||
\subsection{Method \code{getValue()}}{
|
||||
Returns the current value.
|
||||
\subsection{Usage}{
|
||||
@@ -188,6 +194,7 @@ Returns the current value.
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-close"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-close}{}}}
|
||||
\subsection{Method \code{close()}}{
|
||||
Removes the progress panel. Future calls to \code{set} and
|
||||
\code{close} will be ignored.
|
||||
@@ -198,6 +205,7 @@ Removes the progress panel. Future calls to \code{set} and
|
||||
}
|
||||
\if{html}{\out{<hr>}}
|
||||
\if{html}{\out{<a id="method-clone"></a>}}
|
||||
\if{latex}{\out{\hypertarget{method-clone}{}}}
|
||||
\subsection{Method \code{clone()}}{
|
||||
The objects of this class are cloneable with this method.
|
||||
\subsection{Usage}{
|
||||
|
||||
@@ -67,7 +67,9 @@ server <- function(input, output, session) {
|
||||
counterServer("counter1")
|
||||
counterServer("counter2")
|
||||
}
|
||||
shinyApp(ui, server)
|
||||
if (interactive()) {
|
||||
shinyApp(ui, server)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -93,7 +95,9 @@ ui <- fluidPage(
|
||||
server <- function(input, output, session) {
|
||||
counterServer2("counter", "The current count is: ")
|
||||
}
|
||||
shinyApp(ui, server)
|
||||
if (interactive()) {
|
||||
shinyApp(ui, server)
|
||||
}
|
||||
|
||||
}
|
||||
\seealso{
|
||||
|
||||
@@ -25,6 +25,9 @@ arguments are processed with \code{\link[rlang:list2]{rlang::list2()}} and so ar
|
||||
will work up the directory hierarchy --- starting with the current directory ---
|
||||
looking for a directory that contains an \code{app.R} or \code{server.R} file.}
|
||||
}
|
||||
\value{
|
||||
The result of evaluating \code{expr}.
|
||||
}
|
||||
\description{
|
||||
Offer a way to test the reactive interactions in Shiny --- either in Shiny
|
||||
modules or in the server portion of a Shiny application. For more
|
||||
|
||||
@@ -29,6 +29,7 @@ If the number has a suffix, it must be valid: \code{px},
|
||||
\code{vmax}.
|
||||
If the number has no suffix, the suffix \code{"px"} is appended.
|
||||
|
||||
|
||||
Any other value will cause an error to be thrown.
|
||||
}
|
||||
\examples{
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
context("reactivity")
|
||||
|
||||
test_that("reactive and reactiveVal are functions", {
|
||||
expect_s3_class(reactive({1}), "function")
|
||||
expect_s3_class(reactiveVal(1), "function")
|
||||
})
|
||||
|
||||
|
||||
|
||||
test_that("ReactiveVal", {
|
||||
val <- reactiveVal()
|
||||
@@ -1097,6 +1103,10 @@ test_that("event handling helpers take correct dependencies", {
|
||||
})
|
||||
|
||||
run_debounce_throttle <- function(do_priming) {
|
||||
# Some of the CRAN test machines are heavily loaded and so the timing for
|
||||
# these tests isn't reliable. https://github.com/rstudio/shiny/pull/2789
|
||||
skip_on_cran()
|
||||
|
||||
# The changing of rv$a will be the (chatty) source of reactivity.
|
||||
rv <- reactiveValues(a = 0)
|
||||
|
||||
|
||||
@@ -525,6 +525,33 @@ test_that("testModule works with nested modules", {
|
||||
})
|
||||
})
|
||||
|
||||
test_that("testModule calls can be nested", {
|
||||
outerModule <- function(input, output, session) {
|
||||
doubled <- reactive({ input$x * 2 })
|
||||
innerModule <- function(input, output, session) {
|
||||
quadrupled <- reactive({ doubled() * 2 })
|
||||
}
|
||||
}
|
||||
|
||||
testModule(outerModule, {
|
||||
session$setInputs(x = 1)
|
||||
expect_equal(doubled(), 2)
|
||||
testModule(innerModule, {
|
||||
expect_equal(quadrupled(), 4)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
test_that("testModule returns a meaningful result", {
|
||||
result <- testModule(function(input, output, session) {
|
||||
reactive({ input$x * 2 })
|
||||
}, {
|
||||
session$setInputs(x = 2)
|
||||
session$returned()
|
||||
})
|
||||
expect_equal(result, 4)
|
||||
})
|
||||
|
||||
test_that("assigning an output in a module function with a non-function errors", {
|
||||
module <- function(input, output, session) {
|
||||
output$someVar <- 123
|
||||
@@ -556,10 +583,43 @@ test_that("testServer works", {
|
||||
test_that("testServer works when referencing external globals", {
|
||||
# If global is defined at the top of app.R outside of the server function.
|
||||
testServer({
|
||||
expect_equal(global, 123)
|
||||
expect_equal(get("global", session$env), 123)
|
||||
}, appDir=test_path("..", "test-modules", "06_tabsets"))
|
||||
})
|
||||
|
||||
test_that("testModule allows lexical environment access through session$env", {
|
||||
m <- local({
|
||||
a_var <- 123
|
||||
function(input, output, session) {
|
||||
b_var <- 321
|
||||
}
|
||||
})
|
||||
expect_false(exists("a_var", inherits = FALSE))
|
||||
testModule(m, {
|
||||
expect_equal(b_var, 321)
|
||||
expect_equal(get("a_var", session$env), 123)
|
||||
})
|
||||
})
|
||||
|
||||
test_that("Module shadowing can be mitigated with unquote", {
|
||||
i <- 0
|
||||
inc <- function() i <<- i+1
|
||||
|
||||
m <- local({
|
||||
function(input, output, session) {
|
||||
inc <- function() stop("I should never be called")
|
||||
}
|
||||
})
|
||||
|
||||
testModule(m, {
|
||||
expect_is(inc, "function")
|
||||
expect_false(identical(inc, !!inc))
|
||||
!!inc()
|
||||
})
|
||||
|
||||
expect_equal(i, 1)
|
||||
})
|
||||
|
||||
test_that("testModule handles invalidateLater", {
|
||||
module <- function(input, output, session) {
|
||||
rv <- reactiveValues(x = 0)
|
||||
|
||||
@@ -72,11 +72,11 @@ test_that("mockableTimer works", {
|
||||
})
|
||||
|
||||
test_that("getDomainTimeMs works", {
|
||||
start <- Sys.time()
|
||||
start <- as.numeric(Sys.time()) * 1000
|
||||
t1 <- getDomainTimeMs(NULL)
|
||||
t2 <- getDomainTimeMs(list())
|
||||
t3 <- getDomainTimeMs(list(.now = function(){456}))
|
||||
end <- Sys.time()
|
||||
end <- as.numeric(Sys.time()) * 1000
|
||||
|
||||
expect_gte(t1, start)
|
||||
expect_gte(t2, start)
|
||||
|
||||
@@ -14,3 +14,17 @@ then
|
||||
else
|
||||
echo "No difference detected; Roxygen docs are current."
|
||||
fi
|
||||
|
||||
|
||||
# Update htmltools docs
|
||||
Rscript './tools/updateHtmltoolsMan.R'
|
||||
|
||||
if [ -n "$(git status --porcelain)" ]
|
||||
then
|
||||
git status --porcelain
|
||||
>&2 echo "Please generate the htmltools documentation and commit the updates."
|
||||
>&2 echo "The above files changed when we generated the htmltools documentation. This most often occurs when the documentation re-exported by shiny does not match the htmltools documentation."
|
||||
exit 1
|
||||
else
|
||||
echo "No difference detected; re-exported htmltools docs are current."
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user