Compare commits

..

7 Commits

Author SHA1 Message Date
Alan Dipert
a036aa4607 still broken, progress on new modules and proxied mocksession 2020-03-07 00:10:07 +00:00
Alan Dipert
2c2ca4b58e simplifications 2020-03-06 23:40:27 +00:00
Alan Dipert
c2c0a0d836 A little churn 2020-03-06 00:35:35 +00:00
Alan Dipert
ed93d42a6e Simplify differentiation strategy 2020-03-05 21:24:38 +00:00
Alan Dipert
6fa332aa77 Add changes and a failing test 2020-03-05 19:46:35 +00:00
Alan Dipert
14b572e115 Passing existing tests 2020-03-05 19:25:33 +00:00
Alan Dipert
946435f25d Add class to ShinyMockSession and fix tests 2020-03-05 18:11:42 +00:00
13 changed files with 110 additions and 129 deletions

View File

@@ -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)

View File

@@ -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
===========

View File

@@ -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(

View File

@@ -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)

View File

@@ -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

View File

@@ -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.

View File

@@ -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,

View File

@@ -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}{

View File

@@ -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)

View File

@@ -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}{

View File

@@ -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{

View File

@@ -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)

View 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")
})