mirror of
https://github.com/rstudio/shiny.git
synced 2026-01-11 16:08:19 -05:00
Compare commits
7 Commits
reactive_c
...
moduleServ
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a036aa4607 | ||
|
|
2c2ca4b58e | ||
|
|
c2c0a0d836 | ||
|
|
ed93d42a6e | ||
|
|
6fa332aa77 | ||
|
|
14b572e115 | ||
|
|
946435f25d |
@@ -173,6 +173,6 @@ Collate:
|
||||
'test-module.R'
|
||||
'test.R'
|
||||
'update-input.R'
|
||||
RoxygenNote: 7.1.0
|
||||
RoxygenNote: 7.0.2
|
||||
Encoding: UTF-8
|
||||
Roxygen: list(markdown = TRUE)
|
||||
|
||||
8
NEWS.md
8
NEWS.md
@@ -19,8 +19,6 @@ shiny 1.4.0.9001
|
||||
|
||||
* `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))
|
||||
@@ -30,12 +28,6 @@ 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
|
||||
===========
|
||||
|
||||
|
||||
@@ -69,6 +69,19 @@ extract <- function(promise) {
|
||||
stop("Single-bracket indexing of mockclientdata is not allowed.")
|
||||
}
|
||||
|
||||
#' @noRd
|
||||
patchModuleFunction <- function(module) {
|
||||
body(module) <- rlang::expr({
|
||||
withr::with_options(base::list(`shiny.allowoutputreads` = TRUE), {
|
||||
session$setEnv(base::environment())
|
||||
session$setReturned({
|
||||
!!!body(module)
|
||||
})
|
||||
})
|
||||
})
|
||||
module
|
||||
}
|
||||
|
||||
#' Mock Shiny Session
|
||||
#'
|
||||
#' @description
|
||||
@@ -100,7 +113,8 @@ MockShinySession <- R6Class(
|
||||
userData = NULL,
|
||||
#' @field progressStack A stack of progress objects
|
||||
progressStack = 'Stack',
|
||||
|
||||
#' @field TRUE when a moduleServer()-based module is under test
|
||||
isModuleServer = FALSE,
|
||||
#' @description Create a new MockShinySession
|
||||
initialize = function() {
|
||||
private$.input <- ReactiveValues$new(dedupe = FALSE, label = "input")
|
||||
@@ -380,16 +394,38 @@ MockShinySession <- R6Class(
|
||||
flushReact = function(){
|
||||
private$flush()
|
||||
},
|
||||
setEnv = function(env) {
|
||||
self$env <- env
|
||||
},
|
||||
setReturned = function(value) {
|
||||
private$returnedVal <- value
|
||||
private$flush()
|
||||
value
|
||||
},
|
||||
#' @description Create and return a namespace-specific session proxy.
|
||||
#' @param namespace Character vector indicating a namespace.
|
||||
makeScope = function(namespace) {
|
||||
ns <- NS(namespace)
|
||||
createSessionProxy(
|
||||
proxy <- createSessionProxy(
|
||||
self,
|
||||
input = .createReactiveValues(private$.input, readonly = TRUE, ns = ns),
|
||||
output = structure(.createOutputWriter(self, ns = ns), class = "shinyoutput"),
|
||||
makeScope = function(namespace) self$makeScope(ns(namespace))
|
||||
makeScope = function(namespace) self$makeScope(ns(namespace)),
|
||||
env = NULL,
|
||||
returned = NULL,
|
||||
setEnv = function(env) assign("env", env, envir = proxy),
|
||||
setReturned = function(value) {
|
||||
assign("returned", value, envir = proxy)
|
||||
private$flush()
|
||||
value
|
||||
},
|
||||
setInputs = function(...) {
|
||||
args <- list(...)
|
||||
names(args) <- ns(names(args))
|
||||
do.call(self$setInputs, args)
|
||||
}
|
||||
)
|
||||
proxy
|
||||
}
|
||||
),
|
||||
private = list(
|
||||
|
||||
32
R/modules.R
32
R/modules.R
@@ -91,9 +91,7 @@ createSessionProxy <- function(parentSession, ...) {
|
||||
#' counterServer("counter1")
|
||||
#' counterServer("counter2")
|
||||
#' }
|
||||
#' if (interactive()) {
|
||||
#' shinyApp(ui, server)
|
||||
#' }
|
||||
#' shinyApp(ui, server)
|
||||
#'
|
||||
#'
|
||||
#'
|
||||
@@ -119,21 +117,37 @@ createSessionProxy <- function(parentSession, ...) {
|
||||
#' server <- function(input, output, session) {
|
||||
#' counterServer2("counter", "The current count is: ")
|
||||
#' }
|
||||
#' if (interactive()) {
|
||||
#' shinyApp(ui, server)
|
||||
#' }
|
||||
#' shinyApp(ui, server)
|
||||
#'
|
||||
#' @export
|
||||
moduleServer <- function(id, module, session = getDefaultReactiveDomain()) {
|
||||
callModule(module, id, session = session)
|
||||
if (inherits(sessionFor(session), "MockShinySession")) {
|
||||
module <- patchModuleFunction(module)
|
||||
isolate(callModule(module, id, session = session))
|
||||
} else {
|
||||
callModule(module, id, session = session)
|
||||
}
|
||||
}
|
||||
|
||||
#' @noRd
|
||||
sessionFor <- function(session) {
|
||||
if (inherits(session, c("MockShinySession", "ShinySession")))
|
||||
return(session)
|
||||
|
||||
if (!inherits(session, "session_proxy"))
|
||||
stop("session must be a ShinySession, MockShinySession, or session_proxy object.")
|
||||
|
||||
while (inherits(session, "session_proxy"))
|
||||
session <- session$parent
|
||||
|
||||
session
|
||||
}
|
||||
|
||||
#' @rdname moduleServer
|
||||
#' @export
|
||||
callModule <- function(module, id, ..., session = getDefaultReactiveDomain()) {
|
||||
if (!inherits(session, c("ShinySession", "session_proxy", "MockShinySession"))) {
|
||||
stop("session must be a ShinySession or session_proxy object.")
|
||||
if (!inherits(session, c("ShinySession", "MockShinySession", "session_proxy"))) {
|
||||
stop("session must be a ShinySession, MockShinySession, 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", "function"),
|
||||
class = c("reactiveVal", "reactive"),
|
||||
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", "function"))
|
||||
structure(o$getValue, observable = o, class = c("reactiveExpr", "reactive"))
|
||||
}
|
||||
|
||||
# Given the srcref to a reactive expression, attempts to figure out what the
|
||||
|
||||
@@ -889,14 +889,6 @@ 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) {
|
||||
@@ -912,11 +904,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(getUnitType(u) == "null")
|
||||
isTRUE(attr(u, "unit", exact = TRUE) == "null")
|
||||
})
|
||||
} else {
|
||||
# For later versions of ggplot2
|
||||
getUnitType(x) == "null"
|
||||
attr(x, "unit", exact = TRUE) == "null"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -956,11 +948,7 @@ find_panel_ranges <- function(g, res) {
|
||||
|
||||
# The plotting panels all are 'null' units.
|
||||
null_sizes <- rep(NA_real_, length(rel_sizes))
|
||||
# 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])
|
||||
}
|
||||
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.
|
||||
|
||||
@@ -64,38 +64,27 @@ testModule <- function(module, expr, ...) {
|
||||
)
|
||||
}
|
||||
|
||||
#' @noRd
|
||||
#' @importFrom withr with_options
|
||||
.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 <- base::environment()
|
||||
!!!body(module)
|
||||
})
|
||||
isOldModule <- function(func) {
|
||||
stopifnot(is.function(func))
|
||||
required <- c("input", "output", "session")
|
||||
declared <- names(formals(func))
|
||||
setequal(required, intersect(required, declared))
|
||||
}
|
||||
|
||||
#' @noRd
|
||||
.testModule <- function(module, quosure, dots, env) {
|
||||
session <- MockShinySession$new()
|
||||
on.exit(if (!session$isClosed()) session$close())
|
||||
args <- append(dots, list(input = session$input, output = session$output, session = session))
|
||||
|
||||
isolate(
|
||||
withReactiveDomain(
|
||||
session,
|
||||
withr::with_options(list(`shiny.allowoutputreads`=TRUE), {
|
||||
# Assigning to `$returned` causes a flush to happen automatically.
|
||||
session$returned <- do.call(module, args)
|
||||
})
|
||||
)
|
||||
)
|
||||
if (isOldModule(module)) {
|
||||
module <- patchModuleFunction(module)
|
||||
args <- append(dots, list(input = session$input, output = session$output, session = session))
|
||||
} else {
|
||||
args <- dots
|
||||
}
|
||||
|
||||
isolate(withReactiveDomain(session, do.call(module, args)))
|
||||
|
||||
# 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,
|
||||
|
||||
@@ -88,7 +88,6 @@ 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}{
|
||||
@@ -105,7 +104,6 @@ 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}{
|
||||
@@ -115,7 +113,6 @@ 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}{
|
||||
@@ -125,7 +122,6 @@ 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}{
|
||||
@@ -144,7 +140,6 @@ 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}{
|
||||
@@ -163,7 +158,6 @@ 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}{
|
||||
@@ -180,7 +174,6 @@ 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}{
|
||||
@@ -190,7 +183,6 @@ 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}{
|
||||
@@ -200,7 +192,6 @@ 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}{
|
||||
@@ -210,7 +201,6 @@ 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.
|
||||
@@ -228,7 +218,6 @@ 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}{
|
||||
@@ -249,7 +238,6 @@ 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.
|
||||
@@ -276,7 +264,6 @@ 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}{
|
||||
@@ -295,7 +282,6 @@ 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}{
|
||||
@@ -312,7 +298,6 @@ 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}{
|
||||
@@ -322,7 +307,6 @@ 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}{
|
||||
@@ -343,7 +327,6 @@ 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}{
|
||||
@@ -360,7 +343,6 @@ 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}{
|
||||
@@ -381,7 +363,6 @@ 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}{
|
||||
@@ -398,7 +379,6 @@ 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}{
|
||||
@@ -408,7 +388,6 @@ 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}{
|
||||
@@ -425,7 +404,6 @@ 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}{
|
||||
@@ -444,7 +422,6 @@ 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}{
|
||||
@@ -463,7 +440,6 @@ 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}{
|
||||
@@ -482,7 +458,6 @@ 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}{
|
||||
@@ -499,7 +474,6 @@ 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}{
|
||||
@@ -509,7 +483,6 @@ 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}{
|
||||
@@ -526,7 +499,6 @@ 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}{
|
||||
@@ -543,7 +515,6 @@ 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}{
|
||||
@@ -553,7 +524,6 @@ 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}{
|
||||
@@ -570,7 +540,6 @@ 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}{
|
||||
@@ -587,7 +556,6 @@ 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}{
|
||||
@@ -597,7 +565,6 @@ 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}{
|
||||
@@ -625,7 +592,6 @@ 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}{
|
||||
@@ -642,7 +608,6 @@ 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}{
|
||||
@@ -652,7 +617,6 @@ 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}{
|
||||
@@ -669,7 +633,6 @@ Create and return a namespace-specific session proxy.
|
||||
}
|
||||
\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,9 +5,7 @@
|
||||
\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,7 +74,6 @@ 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}{
|
||||
@@ -108,7 +107,6 @@ 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.
|
||||
@@ -136,7 +134,6 @@ 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
|
||||
@@ -164,7 +161,6 @@ 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}{
|
||||
@@ -174,7 +170,6 @@ 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}{
|
||||
@@ -184,7 +179,6 @@ 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}{
|
||||
@@ -194,7 +188,6 @@ 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.
|
||||
@@ -205,7 +198,6 @@ 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,9 +67,7 @@ server <- function(input, output, session) {
|
||||
counterServer("counter1")
|
||||
counterServer("counter2")
|
||||
}
|
||||
if (interactive()) {
|
||||
shinyApp(ui, server)
|
||||
}
|
||||
shinyApp(ui, server)
|
||||
|
||||
|
||||
|
||||
@@ -95,9 +93,7 @@ ui <- fluidPage(
|
||||
server <- function(input, output, session) {
|
||||
counterServer2("counter", "The current count is: ")
|
||||
}
|
||||
if (interactive()) {
|
||||
shinyApp(ui, server)
|
||||
}
|
||||
shinyApp(ui, server)
|
||||
|
||||
}
|
||||
\seealso{
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
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()
|
||||
@@ -1103,10 +1097,6 @@ 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)
|
||||
|
||||
|
||||
23
tests/testthat/test-test-moduleServer.R
Normal file
23
tests/testthat/test-test-moduleServer.R
Normal file
@@ -0,0 +1,23 @@
|
||||
context("testModule-moduleServer")
|
||||
|
||||
test_that("New-style modules work", {
|
||||
counterServer <- local({
|
||||
function(id) {
|
||||
moduleServer(id, function(input, output, session) {
|
||||
count <- reactiveVal(0)
|
||||
observeEvent(input$button, {
|
||||
count(count() + 1)
|
||||
})
|
||||
output$out <- renderText({
|
||||
count()
|
||||
})
|
||||
count
|
||||
})
|
||||
}
|
||||
})
|
||||
testModule(counterServer, {
|
||||
input$setInputs(button = 0)
|
||||
input$setInputs(button = 1)
|
||||
expect_equal(count(), 1)
|
||||
}, id = "foob")
|
||||
})
|
||||
Reference in New Issue
Block a user