diff --git a/DESCRIPTION b/DESCRIPTION
index 963846e3b..317519e26 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -32,7 +32,8 @@ Imports:
magrittr,
mime,
lifecycle (>= 0.2.0),
- ellipsis (>= 0.3.0)
+ ellipsis (>= 0.3.0),
+ rlang
LazyData: TRUE
ByteCompile: TRUE
Suggests:
@@ -46,7 +47,8 @@ Suggests:
yaml,
feather,
future,
- rstudioapi
+ rstudioapi,
+ mockery (>= 0.4.2)
RoxygenNote: 7.1.1
Collate:
'async.R'
diff --git a/NAMESPACE b/NAMESPACE
index fac11426b..fa6fd8477 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -104,6 +104,8 @@ importFrom(jsonlite,parse_json)
importFrom(jsonlite,toJSON)
importFrom(lifecycle,deprecated)
importFrom(magrittr,"%>%")
+importFrom(rlang,"%||%")
+importFrom(rlang,missing_arg)
importFrom(stats,runif)
importFrom(stats,setNames)
importFrom(utils,file.edit)
diff --git a/NEWS.md b/NEWS.md
index 98bd59e1c..cdb077463 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -23,6 +23,12 @@ plumber 1.0.0.9999 Development version
* OpenAPI Specification can be set using a file path. (@meztez #696)
+* Un-deprecated `Plumber$run(debug=, swaggerCallback=)` and added the parameters for `Plumber$run(docs=, quiet=)` and `pr_run(debug=, docs=, swaggerCallback=, quiet=)`. Now, all four parameters will not produce lingering effects on the `Plumber` router. (@jcheng5 #765)
+ * Setting `quiet = TRUE` will suppress routine startup messages.
+ * Setting `debug = TRUE`, will display information when an error occurs. See `pr_set_debug()`.
+ * Setting `docs` will update the visual documentation. See `pr_set_docs()`.
+ * Set `swaggerCallback` to a function which will be called with a url to the documentation, or `NULL` to do nothing. See `pr_set_docs_callback()`.
+
* To update a `PlumberEndpoint` path after initialization, call the new `PlumberEndpoint$setPath(path)`. This will update internal path matching meta data. (Active bindings were not used to avoid breaking changes.) (@blairj09 #770)
### Bug fixes
diff --git a/R/plumber.R b/R/plumber.R
index 056a07512..fe9aab86c 100644
--- a/R/plumber.R
+++ b/R/plumber.R
@@ -1,5 +1,6 @@
#' @import R6
#' @import stringi
+#' @importFrom rlang %||%
NULL
# used to identify annotation flags.
@@ -86,7 +87,6 @@ Plumber <- R6Class(
}
# Initialize
- private$maxSize <- getOption('plumber.maxRequestSize', 0) #0 Unlimited
self$setSerializer(serializer_json())
# Default parsers to maintain legacy features
self$setParsers(c("json", "form", "text", "octet", "multi"))
@@ -94,8 +94,8 @@ Plumber <- R6Class(
self$set404Handler(default404Handler)
self$setDocs(TRUE)
private$docs_info$has_not_been_set <- TRUE # set to know if `$setDocs()` has been called before `$run()`
- self$setDocsCallback(getOption('plumber.docs.callback', getOption('plumber.swagger.url')))
- self$setDebug(interactive())
+ private$docs_callback <- rlang::missing_arg()
+ private$debug <- NULL
self$setApiSpec(NULL)
# Add in the initial filters
@@ -143,55 +143,111 @@ Plumber <- R6Class(
#' Mac OS X, port numbers smaller than 1025 require root privileges.
#'
#' This value does not need to be explicitly assigned. To explicitly set it, see [options_plumber()].
- #' @param debug Deprecated. See `$setDebug()`
- #' @param swagger Deprecated. See `$setDocs(docs)` or `$setApiSpec()`
- #' @param swaggerCallback Deprecated. See `$setDocsCallback()`
+ #' @param debug If `TRUE`, it will provide more insight into your API errors. Using this value will only last for the duration of the run. If a `$setDebug()` has not been called, `debug` will default to `interactive()` at `$run()` time. See `$setDebug()` for more details.
+ #' @param swagger Deprecated. Please use `docs` instead. See `$setDocs(docs)` or `$setApiSpec()` for more customization.
+ #' @param swaggerCallback An optional single-argument function that is
+ #' called back with the URL to an OpenAPI user interface when one becomes
+ #' ready. If missing, defaults to information previously set with `$setDocsCallback()`.
+ #' This value will only be used while running the router.
+ #' @param docs Visual documentation value to use while running the API.
+ #' This value will only be used while running the router.
+ #' If missing, defaults to information previously set with `setDocs()`.
+ #' For more customization, see `$setDocs()` or [pr_set_docs()] for examples.
+ #' @param quiet If `TRUE`, don't print routine startup messages.
+ #' @param ... Should be empty.
#' @importFrom lifecycle deprecated
+ #' @importFrom rlang missing_arg
run = function(
host = '127.0.0.1',
port = getOption('plumber.port', NULL),
swagger = deprecated(),
- debug = deprecated(),
- swaggerCallback = deprecated()
+ debug = missing_arg(),
+ swaggerCallback = missing_arg(),
+ ...,
+ # any new args should go below `...`
+ docs = missing_arg(),
+ quiet = FALSE
) {
if (isTRUE(private$disable_run)) {
stop("Plumber router `$run()` method should not be called while `plumb()`ing a file")
}
+ ellipsis::check_dots_empty()
+
# Legacy support for RStudio pro products.
# Checks must be kept for >= 2 yrs after plumber v1.0.0 release date
- if (lifecycle::is_present(debug)) {
- lifecycle::deprecate_warn("1.0.0", "run(debug = )", "setDebug(debug = )")
- self$setDebug(debug)
- }
if (lifecycle::is_present(swagger)) {
- if (is.function(swagger)) {
- # between v0.4.6 and v1.0.0
- lifecycle::deprecate_warn("1.0.0", "run(swagger = )", "setApiSpec(api = )")
- self$setApiSpec(swagger)
- # spec is now enabled by default. Do not alter
+ if (!rlang::is_missing(docs)) {
+ lifecycle::deprecate_warn("1.0.0", "Plumber$run(swagger = )", "Plumber$run(docs = )", details = "`docs` will take preference (ignoring `swagger`)")
+ # (`docs` is resolved after `swagger` checks)
} else {
- if (isTRUE(private$docs_info$has_not_been_set)) {
- # <= v0.4.6
- lifecycle::deprecate_warn("1.0.0", "run(swagger = )", "setDocs(docs = )")
- self$setDocs(swagger)
+ if (is.function(swagger)) {
+ # between v0.4.6 and v1.0.0
+ lifecycle::deprecate_warn("1.0.0", "Plumber$run(swagger = )", "Plumber$setApiSpec(api = )")
+ # set the new api function and force turn on the docs
+ old_api_spec_handler <- private$api_spec_handler
+ self$setApiSpec(swagger)
+ on.exit({
+ private$api_spec_handler <- old_api_spec_handler
+ }, add = TRUE)
+ docs <- TRUE
} else {
- # $setDocs() has been called (other than during initialization).
- # Believe that it is the correct behavior
- # Warn about updating the run method
- lifecycle::deprecate_warn("1.0.0", "run(swagger = )", details = "The Plumber docs have already been set. Ignoring `swagger` parameter.")
+ if (isTRUE(private$docs_info$has_not_been_set)) {
+ # <= v0.4.6
+ lifecycle::deprecate_warn("1.0.0", "Plumber$run(swagger = )", "Plumber$run(docs = )")
+ docs <- swagger
+ } else {
+ # $setDocs() has been called (other than during initialization).
+ # `docs` is not provided
+ # Believe that prior `$setDocs()` behavior is the correct behavior
+ # Warn about updating the run method
+ lifecycle::deprecate_warn("1.0.0", "Plumber$run(swagger = )", "Plumber$run(docs = )", details = "The Plumber docs have already been set. Ignoring `swagger` parameter.")
+ }
}
}
}
- if (lifecycle::is_present(swaggerCallback)) {
- lifecycle::deprecate_warn("1.0.0", "run(swaggerCallback = )", "setDocsCallback(callback = )")
- self$setDocsCallback(swaggerCallback)
- }
port <- findPort(port)
- message("Running plumber API at ", urlHost(host = host, port = port, changeHostLocation = FALSE))
+ # Delay setting max size option. It could be set in `plumber.R`, which is after initialization
+ private$maxSize <- getOption('plumber.maxRequestSize', 0) #0 Unlimited
+
+ # Delay the setting of swaggerCallback as long as possible.
+ # An option could be set in `plumber.R`, which is after initialization
+ # Order: Run method parameter, internally set value, option, fallback option, NULL
+ swaggerCallback <-
+ rlang::maybe_missing(swaggerCallback,
+ rlang::maybe_missing(private$docs_callback,
+ getOption('plumber.docs.callback', getOption('plumber.swagger.url', NULL))
+ )
+ )
+
+ # Delay the setting of debug as long as possible.
+ # The router could be made in an interactive setting and used in background process.
+ # Do not determine if interactive until run time
+ prev_debug <- private$debug
+ on.exit({
+ private$debug <- prev_debug
+ }, add = TRUE)
+ # Fix the debug value while running.
+ self$setDebug(
+ # Order: Run method param, internally set value, is interactive()
+ # `$getDebug()` is dynamic given `setDebug()` has never been called.
+ rlang::maybe_missing(debug, self$getDebug())
+ )
+
+ docs_info <-
+ if (!rlang::is_missing(docs)) {
+ # Manually provided. Need to upgrade the parameter
+ upgrade_docs_parameter(docs)
+ } else {
+ private$docs_info
+ }
+
+ if (!isTRUE(quiet)) {
+ message("Running plumber API at ", urlHost(host = host, port = port, changeHostLocation = FALSE))
+ }
# Set and restore the wd to make it appear that the proc is running local to the file's definition.
if (!is.null(private$filename)) {
@@ -199,15 +255,16 @@ Plumber <- R6Class(
on.exit({setwd(old_wd)}, add = TRUE)
}
- if (isTRUE(private$docs_info$enabled)) {
+ if (isTRUE(docs_info$enabled)) {
mount_docs(
pr = self,
host = host,
port = port,
- docs_info = private$docs_info,
- callback = private$docs_callback
+ docs_info = docs_info,
+ callback = swaggerCallback,
+ quiet = quiet
)
- on.exit(unmount_docs(self, private$docs_info), add = TRUE)
+ on.exit(unmount_docs(self, docs_info), add = TRUE)
}
on.exit(private$runHooks("exit"), add = TRUE)
@@ -879,23 +936,7 @@ Plumber <- R6Class(
docs = getOption("plumber.docs", TRUE),
...
) {
- stopifnot(length(docs) == 1)
- stopifnot(is.logical(docs) || is.character(docs))
- if (isTRUE(docs)) {
- docs <- "swagger"
- }
- if (is.character(docs) && is_docs_available(docs)) {
- enabled <- TRUE
- } else {
- enabled <- FALSE
- docs <- "__not_enabled__"
- }
- private$docs_info <- list(
- enabled = enabled,
- docs = docs,
- args = list(...),
- has_not_been_set = FALSE
- )
+ private$docs_info <- upgrade_docs_parameter(docs, ...)
},
#' @description Set a callback to notify where the API's visual documentation is located.
#'
@@ -918,7 +959,7 @@ Plumber <- R6Class(
}
private$docs_callback <- callback
},
- #' @description Set debug value to include error messages
+ #' @description Set debug value to include error messages.
#'
#' See also: `$getDebug()` and [pr_set_debug()]
#' @param debug `TRUE` provides more insight into your API errors.
@@ -926,11 +967,11 @@ Plumber <- R6Class(
stopifnot(length(debug) == 1)
private$debug <- isTRUE(debug)
},
- #' @description Retrieve the `debug` value.
+ #' @description Retrieve the `debug` value. If it has never been set, the result of `interactive()` will be used.
#'
#' See also: `$getDebug()` and [pr_set_debug()]
getDebug = function() {
- private$debug
+ private$debug %||% default_debug()
},
#' @description Add a filter to plumber router
#'
@@ -1176,7 +1217,7 @@ Plumber <- R6Class(
errorHandler = NULL,
notFoundHandler = NULL,
- maxSize = NULL, # Max request size in bytes
+ maxSize = 0, # Max request size in bytes. (0 is a no-op)
api_spec_handler = NULL,
docs_info = NULL,
@@ -1271,9 +1312,32 @@ Plumber <- R6Class(
+upgrade_docs_parameter <- function(docs, ...) {
+ stopifnot(length(docs) == 1)
+ stopifnot(is.logical(docs) || is.character(docs))
+ if (isTRUE(docs)) {
+ docs <- "swagger"
+ }
+ if (is.character(docs) && is_docs_available(docs)) {
+ enabled <- TRUE
+ } else {
+ enabled <- FALSE
+ docs <- "__not_enabled__"
+ }
+
+ list(
+ enabled = enabled,
+ docs = docs,
+ args = list(...),
+ has_not_been_set = FALSE
+ )
+}
+default_debug <- function() {
+ interactive()
+}
urlHost <- function(scheme = "http", host, port, path = "", changeHostLocation = FALSE) {
diff --git a/R/pr.R b/R/pr.R
index ec2c4219e..6843bfb8a 100644
--- a/R/pr.R
+++ b/R/pr.R
@@ -475,6 +475,19 @@ pr_filter <- function(pr,
#' @param port A number or integer that indicates the server port that should
#' be listened on. Note that on most Unix-like systems including Linux and
#' Mac OS X, port numbers smaller than 1025 require root privileges.
+#' @param ... Should be empty.
+#' @param debug If `TRUE`, it will provide more insight into your API errors.
+#' Using this value will only last for the duration of the run.
+#' If [pr_set_debug()] has not been called, `debug` will default to `interactive()` at [pr_run()] time
+#' @param docs Visual documentation value to use while running the API.
+#' This value will only be used while running the router.
+#' If missing, defaults to information previously set with [pr_set_docs()].
+#' For more customization, see [pr_set_docs()] for examples.
+#' @param swaggerCallback An optional single-argument function that is called
+#' back with the URL to an OpenAPI user interface when one becomes ready. If
+#' missing, defaults to information set with [pr_set_docs_callback()].
+#' This value will only be used while running the router.
+#' @param quiet If `TRUE`, don't print routine startup messages.
#'
#' @examples
#' \dontrun{
@@ -482,17 +495,34 @@ pr_filter <- function(pr,
#' pr_run()
#'
#' pr() %>%
-#' pr_run(port = 5762)
+#' pr_run(
+#' # manually set port
+#' port = 5762,
+#' # turn off visual documentation
+#' docs = FALSE,
+#' # do not display startup messages
+#' quiet = TRUE
+#' )
#' }
#'
#' @export
pr_run <- function(pr,
host = '127.0.0.1',
- port = getOption('plumber.port', NULL)
+ port = getOption('plumber.port', NULL),
+ ...,
+ debug = missing_arg(),
+ docs = missing_arg(),
+ swaggerCallback = missing_arg(),
+ quiet = FALSE
) {
validate_pr(pr)
+ ellipsis::check_dots_empty()
pr$run(host = host,
- port = port)
+ port = port,
+ debug = debug,
+ docs = docs,
+ swaggerCallback = swaggerCallback,
+ quiet = quiet)
}
diff --git a/R/ui.R b/R/ui.R
index ffe5f1e32..b4c779d6b 100644
--- a/R/ui.R
+++ b/R/ui.R
@@ -2,7 +2,7 @@
# Mount OpenAPI and Docs
#' @noRd
-mount_docs <- function(pr, host, port, docs_info, callback) {
+mount_docs <- function(pr, host, port, docs_info, callback, quiet = FALSE) {
# return early if not enabled
if (!isTRUE(docs_info$enabled)) {
@@ -26,14 +26,18 @@ mount_docs <- function(pr, host, port, docs_info, callback) {
# Mount Docs
if (length(registered_docs()) == 0) {
- message("No visual documentation options registered. See help(register_docs).")
+ if (!isTRUE(quiet)) {
+ message("No visual documentation options registered. See help(register_docs).")
+ }
return()
}
if (is_docs_available(docs_info$docs)) {
docs_mount <- .globals$docs[[docs_info$docs]]$mount
docs_url <- do.call(docs_mount, c(list(pr, api_url), docs_info$args))
- message("Running ", docs_info$docs, " Docs at ", docs_url, sep = "")
+ if (!isTRUE(quiet)) {
+ message("Running ", docs_info$docs, " Docs at ", docs_url, sep = "")
+ }
} else {
return()
}
diff --git a/man/Plumber.Rd b/man/Plumber.Rd
index 11736bc4e..f1a1bf705 100644
--- a/man/Plumber.Rd
+++ b/man/Plumber.Rd
@@ -219,8 +219,11 @@ See also: \code{\link[=pr_run]{pr_run()}}
host = "127.0.0.1",
port = getOption("plumber.port", NULL),
swagger = deprecated(),
- debug = deprecated(),
- swaggerCallback = deprecated()
+ debug = missing_arg(),
+ swaggerCallback = missing_arg(),
+ ...,
+ docs = missing_arg(),
+ quiet = FALSE
)}\if{html}{\out{}}
}
@@ -237,11 +240,23 @@ Mac OS X, port numbers smaller than 1025 require root privileges.
This value does not need to be explicitly assigned. To explicitly set it, see \code{\link[=options_plumber]{options_plumber()}}.}
-\item{\code{swagger}}{Deprecated. See \verb{$setDocs(docs)} or \verb{$setApiSpec()}}
+\item{\code{swagger}}{Deprecated. Please use \code{docs} instead. See \verb{$setDocs(docs)} or \verb{$setApiSpec()} for more customization.}
-\item{\code{debug}}{Deprecated. See \verb{$setDebug()}}
+\item{\code{debug}}{If \code{TRUE}, it will provide more insight into your API errors. Using this value will only last for the duration of the run. If a \verb{$setDebug()} has not been called, \code{debug} will default to \code{interactive()} at \verb{$run()} time. See \verb{$setDebug()} for more details.}
-\item{\code{swaggerCallback}}{Deprecated. See \verb{$setDocsCallback()}}
+\item{\code{swaggerCallback}}{An optional single-argument function that is
+called back with the URL to an OpenAPI user interface when one becomes
+ready. If missing, defaults to information previously set with \verb{$setDocsCallback()}.
+This value will only be used while running the router.}
+
+\item{\code{...}}{Should be empty.}
+
+\item{\code{docs}}{Visual documentation value to use while running the API.
+This value will only be used while running the router.
+If missing, defaults to information previously set with \code{setDocs()}.
+For more customization, see \verb{$setDocs()} or \code{\link[=pr_set_docs]{pr_set_docs()}} for examples.}
+
+\item{\code{quiet}}{If \code{TRUE}, don't print routine startup messages.}
}
\if{html}{\out{}}
}
@@ -765,7 +780,7 @@ See also: \code{\link[=pr_set_docs_callback]{pr_set_docs_callback()}}
\if{html}{\out{}}
\if{latex}{\out{\hypertarget{method-setDebug}{}}}
\subsection{Method \code{setDebug()}}{
-Set debug value to include error messages
+Set debug value to include error messages.
See also: \verb{$getDebug()} and \code{\link[=pr_set_debug]{pr_set_debug()}}
\subsection{Usage}{
@@ -784,7 +799,7 @@ See also: \verb{$getDebug()} and \code{\link[=pr_set_debug]{pr_set_debug()}}
\if{html}{\out{}}
\if{latex}{\out{\hypertarget{method-getDebug}{}}}
\subsection{Method \code{getDebug()}}{
-Retrieve the \code{debug} value.
+Retrieve the \code{debug} value. If it has never been set, the result of \code{interactive()} will be used.
See also: \verb{$getDebug()} and \code{\link[=pr_set_debug]{pr_set_debug()}}
\subsection{Usage}{
diff --git a/man/pr_run.Rd b/man/pr_run.Rd
index fdd279eec..e674b7ed4 100644
--- a/man/pr_run.Rd
+++ b/man/pr_run.Rd
@@ -4,7 +4,16 @@
\alias{pr_run}
\title{Start a server using \code{plumber} object}
\usage{
-pr_run(pr, host = "127.0.0.1", port = getOption("plumber.port", NULL))
+pr_run(
+ pr,
+ host = "127.0.0.1",
+ port = getOption("plumber.port", NULL),
+ ...,
+ debug = missing_arg(),
+ docs = missing_arg(),
+ swaggerCallback = missing_arg(),
+ quiet = FALSE
+)
}
\arguments{
\item{pr}{A Plumber API. Note: The supplied Plumber API object will also be updated in place as well as returned by the function.}
@@ -16,6 +25,24 @@ all IPv4 addresses and "::/0" represents all IPv6 addresses.}
\item{port}{A number or integer that indicates the server port that should
be listened on. Note that on most Unix-like systems including Linux and
Mac OS X, port numbers smaller than 1025 require root privileges.}
+
+\item{...}{Should be empty.}
+
+\item{debug}{If \code{TRUE}, it will provide more insight into your API errors.
+Using this value will only last for the duration of the run.
+If \code{\link[=pr_set_debug]{pr_set_debug()}} has not been called, \code{debug} will default to \code{interactive()} at \code{\link[=pr_run]{pr_run()}} time}
+
+\item{docs}{Visual documentation value to use while running the API.
+This value will only be used while running the router.
+If missing, defaults to information previously set with \code{\link[=pr_set_docs]{pr_set_docs()}}.
+For more customization, see \code{\link[=pr_set_docs]{pr_set_docs()}} for examples.}
+
+\item{swaggerCallback}{An optional single-argument function that is called
+back with the URL to an OpenAPI user interface when one becomes ready. If
+missing, defaults to information set with \code{\link[=pr_set_docs_callback]{pr_set_docs_callback()}}.
+This value will only be used while running the router.}
+
+\item{quiet}{If \code{TRUE}, don't print routine startup messages.}
}
\description{
\code{port} does not need to be explicitly assigned.
@@ -26,7 +53,14 @@ pr() \%>\%
pr_run()
pr() \%>\%
- pr_run(port = 5762)
+ pr_run(
+ # manually set port
+ port = 5762,
+ # turn off visual documentation
+ docs = FALSE,
+ # do not display startup messages
+ quiet = TRUE
+ )
}
}
diff --git a/tests/testthat/test-options.R b/tests/testthat/test-options.R
index e9ca6f00c..8fa6e53af 100644
--- a/tests/testthat/test-options.R
+++ b/tests/testthat/test-options.R
@@ -52,22 +52,31 @@ test_that("all options used are `options_plumber()` parameters", {
test_that("Legacy swagger redirect can be disabled", {
- with_options(list(), {
- options_plumber(legacyRedirects = TRUE)
- redirects <- swagger_redirects()
- expect_gt(length(redirects), 0)
+ with_options(
+ list(
+ plumber.legacyRedirets = getOption("plumber.legacyRedirects")
+ ), {
+ options_plumber(legacyRedirects = TRUE)
+ redirects <- swagger_redirects()
+ expect_gt(length(redirects), 0)
- options_plumber(legacyRedirects = FALSE)
- redirects <- swagger_redirects()
- expect_equal(length(redirects), 0)
- })
+ options_plumber(legacyRedirects = FALSE)
+ redirects <- swagger_redirects()
+ expect_equal(length(redirects), 0)
+ }
+ )
})
test_that("docs.callback sync plumber.swagger.url", {
- with_options(list(), {
- options("plumber.swagger.url" = function(api_url) {cat(api_url)})
- opt <- options_plumber(docs.callback = NULL)
- expect_null(getOption("plumber.swagger.url"))
- expect_null(opt$plumber.docs.callback)
- })
+ with_options(
+ list(
+ plumber.swagger.url = getOption("plumber.swagger.url"),
+ plumber.docs.callback = getOption("plumber.docs.callback")
+ ), {
+ options("plumber.swagger.url" = function(api_url) {cat(api_url)})
+ opt <- options_plumber(docs.callback = NULL)
+ expect_null(getOption("plumber.swagger.url"))
+ expect_null(opt$plumber.docs.callback)
+ }
+ )
})
diff --git a/tests/testthat/test-plumber-run.R b/tests/testthat/test-plumber-run.R
new file mode 100644
index 000000000..ffdf829bf
--- /dev/null
+++ b/tests/testthat/test-plumber-run.R
@@ -0,0 +1,136 @@
+
+with_interrupt <- function(expr) {
+ # Causes pr_run() to immediately exit
+ later::later(httpuv::interrupt)
+ force(expr)
+}
+
+test_that("quiet=TRUE suppresses startup messages", {
+ with_interrupt({
+ expect_message(pr() %>% pr_run(quiet = TRUE), NA)
+ })
+ with_interrupt({
+ expect_message(pr()$run(quiet = TRUE), NA)
+ })
+})
+
+test_that("`docs` does not not permanetly set pr information", {
+ doc_name <- "swagger"
+ root <- pr() %>% pr_set_docs(doc_name)
+ # no docs. do not find printed message
+ with_interrupt({
+ expect_failure(
+ expect_message({
+ root %>% pr_run(docs = FALSE)
+ }, doc_name)
+ )
+ })
+ # no docs. do not find printed message
+ with_interrupt({
+ expect_failure(
+ expect_message({
+ root$run(docs = FALSE)
+ }, doc_name)
+ )
+ })
+ # docs enabled by default. Find printed message
+ with_interrupt({
+ expect_message({
+ root %>% pr_run(quiet = FALSE)
+ }, doc_name)
+ })
+})
+
+test_that("`swaggerCallback` does not not permanetly set pr information", {
+ skip_if_not_installed("mockery", "0.4.2")
+
+ m <- mockery::mock(TRUE, cycle = TRUE)
+ m() # call once so that `length(m)` > 0 as `length(m)` represents the number of calls to `m`
+ root <- pr() %>% pr_set_docs_callback(m)
+ # m not used
+ with_interrupt({
+ mockery::expect_called(m, 1)
+ root %>% pr_run(swaggerCallback = NULL)
+ mockery::expect_called(m, 1)
+ })
+ # m not used
+ with_interrupt({
+ mockery::expect_called(m, 1)
+ root$run(swaggerCallback = NULL)
+ mockery::expect_called(m, 1)
+ })
+ # m is used
+ with_interrupt({
+ mockery::expect_called(m, 1)
+ root %>% pr_run(quiet = FALSE)
+ mockery::expect_called(m, 2)
+ })
+})
+
+test_that("`swaggerCallback` can be set by option after the pr is created", {
+ skip_if_not_installed("mockery", "0.4.2")
+
+ m <- mockery::mock(TRUE)
+
+ # must initialize before options are set for this test
+ root <- pr()
+
+ with_options(
+ list(
+ plumber.swagger.url = getOption("plumber.swagger.url"),
+ plumber.docs.callback = getOption("plumber.docs.callback")
+ ),
+ {
+ # set option after init
+ options_plumber(docs.callback = m)
+ with_interrupt({
+ mockery::expect_called(m, 0)
+ pr_run(root)
+ })
+ }
+ )
+ # m is used
+ mockery::expect_called(m, 1)
+
+})
+
+
+### Test does not work as expected with R6 objects.
+test_that("`debug` is not set until runtime", {
+ skip_if_not_installed("mockery", "0.4.2")
+
+ m <- mockery::mock(TRUE, cycle = TRUE)
+ # https://github.com/r-lib/testthat/issues/734#issuecomment-377367516
+ # > It should work if you fully qualify the function name (include the pkgname)
+ with_mock("plumber:::default_debug" = m, {
+ root <- pr()
+ root$getDebug()
+ mockery::expect_called(m, 1)
+
+ with_interrupt({
+ root %>% pr_run(quiet = TRUE)
+ })
+ # increase by 1
+ mockery::expect_called(m, 2)
+
+ # listen to set value
+ with_interrupt({
+ root %>%
+ pr_set_debug(TRUE) %>%
+ pr_run(quiet = TRUE)
+ })
+ # not updated. stay at 2
+ mockery::expect_called(m, 2)
+
+ # listen to run value
+ with_interrupt({
+ root %>%
+ pr_run(debug = FALSE, quiet = TRUE)
+ })
+ # not updated. stay at 2
+ mockery::expect_called(m, 2)
+
+ # TODO test that run(debug=) has preference over pr_set_debug()
+ })
+
+})