mirror of
https://github.com/rstudio/shiny.git
synced 2026-01-11 16:08:19 -05:00
Compare commits
3 Commits
tab-docs
...
slider-che
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03b03f1173 | ||
|
|
28dc3ecd5b | ||
|
|
c3e6fdc550 |
@@ -342,13 +342,20 @@ collapseSizes <- function(padding) {
|
||||
#' Create a page with a top level navigation bar
|
||||
#'
|
||||
#' Create a page that contains a top level navigation bar that can be used to
|
||||
#' toggle a set of [tabPanel()] elements. `navbarMenu()` can be used to create
|
||||
#' an embedded menu within the navbar that in turns includes additional
|
||||
#' `tabPanels`.
|
||||
#' toggle a set of [tabPanel()] elements.
|
||||
#'
|
||||
#' @inheritParams navlistPanel
|
||||
#' @inheritParams bootstrapPage
|
||||
#' @param title The title to display in the navbar
|
||||
#' @param ... [tabPanel()] elements to include in the page. The
|
||||
#' `navbarMenu` function also accepts strings, which will be used as menu
|
||||
#' section headers. If the string is a set of dashes like `"----"` a
|
||||
#' horizontal separator will be displayed in the menu.
|
||||
#' @param id If provided, you can use `input$`*`id`* in your
|
||||
#' server logic to determine which of the current tabs is active. The value
|
||||
#' will correspond to the `value` argument that is passed to
|
||||
#' [tabPanel()].
|
||||
#' @param selected The `value` (or, if none was supplied, the `title`)
|
||||
#' of the tab that should be selected by default. If `NULL`, the first
|
||||
#' tab will be selected.
|
||||
#' @param position Determines whether the navbar should be displayed at the top
|
||||
#' of the page with normal scrolling behavior (`"static-top"`), pinned at
|
||||
#' the top (`"fixed-top"`), or pinned at the bottom
|
||||
@@ -366,13 +373,26 @@ collapseSizes <- function(padding) {
|
||||
#' elements into a menu when the width of the browser is less than 940 pixels
|
||||
#' (useful for viewing on smaller touchscreen device)
|
||||
#' @param collapsable Deprecated; use `collapsible` instead.
|
||||
#' @param fluid `TRUE` to use a fluid layout. `FALSE` to use a fixed
|
||||
#' layout.
|
||||
#' @param responsive This option is deprecated; it is no longer optional with
|
||||
#' Bootstrap 3.
|
||||
#' @param windowTitle The title that should be displayed by the browser window.
|
||||
#' Useful if `title` is not a string.
|
||||
#' @inheritParams bootstrapPage
|
||||
#' @param icon Optional icon to appear on a `navbarMenu` tab.
|
||||
#'
|
||||
#' @seealso [updateNavbarPage()], [insertTab()], [showTab()]
|
||||
#' @return A UI defintion that can be passed to the [shinyUI] function.
|
||||
#'
|
||||
#' @details The `navbarMenu` function can be used to create an embedded
|
||||
#' menu within the navbar that in turns includes additional tabPanels (see
|
||||
#' example below).
|
||||
#'
|
||||
#' @seealso [tabPanel()], [tabsetPanel()],
|
||||
#' [updateNavbarPage()], [insertTab()],
|
||||
#' [showTab()]
|
||||
#'
|
||||
#' @family layout functions
|
||||
#' @family tab layouts
|
||||
#'
|
||||
#' @examples
|
||||
#' navbarPage("App Title",
|
||||
@@ -603,10 +623,6 @@ helpText <- function(...) {
|
||||
|
||||
#' Create a tab panel
|
||||
#'
|
||||
#' `tabPanel()` creates a tab panel that can be included within a
|
||||
#' [tabsetPanel()], [navListPanel()], or [navbarPage()]. `tabPanelBody()`
|
||||
#' drops the `title`, making it most suitable for use within
|
||||
#' `tabsetPanel(type = "hidden")`.
|
||||
#'
|
||||
#' @param title Display title for tab
|
||||
#' @param ... UI elements to include within the tab
|
||||
@@ -615,8 +631,9 @@ helpText <- function(...) {
|
||||
#' `id`, then the title will be used.
|
||||
#' @param icon Optional icon to appear on the tab. This attribute is only
|
||||
#' valid when using a `tabPanel` within a [navbarPage()].
|
||||
#' @return A tab that can be passed to [tabsetPanel()]
|
||||
#'
|
||||
#' @family tab layouts
|
||||
#' @seealso [tabsetPanel()]
|
||||
#'
|
||||
#' @examples
|
||||
#' # Show a tabset that includes a plot, summary, and
|
||||
@@ -629,6 +646,7 @@ helpText <- function(...) {
|
||||
#' )
|
||||
#' )
|
||||
#' @export
|
||||
#' @describeIn tabPanel Create a tab panel that can be included within a [tabsetPanel()] or a [navbarPage()].
|
||||
tabPanel <- function(title, ..., value = title, icon = NULL) {
|
||||
div(
|
||||
class = "tab-pane",
|
||||
@@ -639,7 +657,8 @@ tabPanel <- function(title, ..., value = title, icon = NULL) {
|
||||
)
|
||||
}
|
||||
#' @export
|
||||
#' @rdname tabPanel
|
||||
#' @describeIn tabPanel Create a tab panel that drops the title argument.
|
||||
#' This function should be used within `tabsetPanel(type = "hidden")`. See [tabsetPanel()] for example usage.
|
||||
tabPanelBody <- function(value, ..., icon = NULL) {
|
||||
if (
|
||||
!is.character(value) ||
|
||||
@@ -674,8 +693,10 @@ tabPanelBody <- function(value, ..., icon = NULL) {
|
||||
#' }
|
||||
#' @param position This argument is deprecated; it has been discontinued in
|
||||
#' Bootstrap 3.
|
||||
#' @seealso [updateTabsetPanel()], [insertTab()], [showTab()]
|
||||
#' @family tab layouts
|
||||
#' @return A tabset that can be passed to [mainPanel()]
|
||||
#'
|
||||
#' @seealso [tabPanel()], [updateTabsetPanel()],
|
||||
#' [insertTab()], [showTab()]
|
||||
#'
|
||||
#' @examples
|
||||
#' # Show a tabset that includes a plot, summary, and
|
||||
@@ -751,20 +772,29 @@ tabsetPanel <- function(...,
|
||||
#' Create a navigation list panel that provides a list of links on the left
|
||||
#' which navigate to a set of tabPanels displayed to the right.
|
||||
#'
|
||||
#' @inheritParams tabsetPanel
|
||||
#' @param ... [tabPanel()] elements to include in the navbar.
|
||||
#' Plain strings will be converted to headers.
|
||||
#' @param ... [tabPanel()] elements to include in the navlist
|
||||
#' @param id If provided, you can use `input$`*`id`* in your
|
||||
#' server logic to determine which of the current navlist items is active. The
|
||||
#' value will correspond to the `value` argument that is passed to
|
||||
#' [tabPanel()].
|
||||
#' @param selected The `value` (or, if none was supplied, the `title`)
|
||||
#' of the navigation item that should be selected by default. If `NULL`,
|
||||
#' the first navigation will be selected.
|
||||
#' @param well `TRUE` to place a well (gray rounded rectangle) around the
|
||||
#' navigation list.
|
||||
#' @param fluid `TRUE` to use fluid layout; `FALSE` to use fixed
|
||||
#' layout.
|
||||
#' @param widths Column widths of the navigation list and tabset content areas
|
||||
#' @param widths Column withs of the navigation list and tabset content areas
|
||||
#' respectively.
|
||||
#'
|
||||
#' @details
|
||||
#' @details You can include headers within the `navlistPanel` by including
|
||||
#' plain text elements in the list. Versions of Shiny before 0.11 supported
|
||||
#' separators with "------", but as of 0.11, separators were no longer
|
||||
#' supported. This is because version 0.11 switched to Bootstrap 3, which
|
||||
#' doesn't support separators.
|
||||
#'
|
||||
#' @seealso [updateTabsetPanel()], [insertTab()], [showTab()]
|
||||
#' @family tab layouts
|
||||
#' @seealso [tabPanel()], [updateNavlistPanel()],
|
||||
#' [insertTab()], [showTab()]
|
||||
#'
|
||||
#' @examples
|
||||
#' fluidPage(
|
||||
|
||||
@@ -79,9 +79,12 @@ sliderInput <- function(inputId, label, min, max, value, step = NULL,
|
||||
round = FALSE, ticks = TRUE, animate = FALSE,
|
||||
width = NULL, sep = ",", pre = NULL, post = NULL,
|
||||
timeFormat = NULL, timezone = NULL, dragRange = TRUE) {
|
||||
validate_slider_value(min, max, value, "sliderInput")
|
||||
|
||||
dataType <- getSliderType(min, max, value)
|
||||
# Force required arguments for maximally informative errors
|
||||
inputId; label; min; max; value
|
||||
|
||||
validate_slider_value(min, max, value, "sliderInput")
|
||||
dataType <- slider_type(value)
|
||||
|
||||
if (is.null(timeFormat)) {
|
||||
timeFormat <- switch(dataType, date = "%F", datetime = "%F %T", number = NULL)
|
||||
@@ -288,37 +291,45 @@ findStepSize <- function(min, max, step) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Throw a warning if ever `value` is not in the [`min`, `max`] range
|
||||
validate_slider_value <- function(min, max, value, fun) {
|
||||
if (length(min) != 1 || is_na(min) ||
|
||||
length(max) != 1 || is_na(max) ||
|
||||
length(value) < 1 || length(value) > 2 || any(is.na(value)))
|
||||
{
|
||||
stop(call. = FALSE,
|
||||
sprintf("In %s(): `min`, `max`, and `value` cannot be NULL, NA, or empty.", fun)
|
||||
if (!is_slider_type(min) || length(min) != 1 || is_na(min)) {
|
||||
rlang::abort("sliderInput(min) must be a single number, Date, or POSIXct")
|
||||
}
|
||||
if (!is_slider_type(min) || length(max) != 1 || is_na(max)) {
|
||||
rlang::abort("sliderInput(value) must be a single number, Date, or POSIXct")
|
||||
}
|
||||
if (!is_slider_type(value) || !length(value) %in% c(1, 2) || any(is_na(value))) {
|
||||
rlang::abort(
|
||||
"sliderInput(value) must be a single or pair of numbers, Dates, or POSIXcts"
|
||||
)
|
||||
}
|
||||
|
||||
if (min(value) < min) {
|
||||
warning(call. = FALSE,
|
||||
sprintf(
|
||||
"In %s(): `value` should be greater than or equal to `min` (value = %s, min = %s).",
|
||||
fun, paste(value, collapse = ", "), min
|
||||
)
|
||||
)
|
||||
if (!identical(class(min), class(value)) || !identical(class(max), class(value))) {
|
||||
rlang::abort(c(
|
||||
"Type mismatch for `min`, `max`, and `value`.",
|
||||
i = "All values must have same type: either numeric, Date, or POSIXt."
|
||||
))
|
||||
}
|
||||
|
||||
if (max(value) > max) {
|
||||
warning(
|
||||
noBreaks. = TRUE, call. = FALSE,
|
||||
sprintf(
|
||||
"In %s(): `value` should be less than or equal to `max` (value = %s, max = %s).",
|
||||
fun, paste(value, collapse = ", "), max
|
||||
)
|
||||
)
|
||||
if (min(value) < min || max(value) > max) {
|
||||
rlang::abort("`value` does not lie within [min, max]")
|
||||
}
|
||||
}
|
||||
|
||||
is_slider_type <- function(x) {
|
||||
is.numeric(x) || inherits(x, "Date") || inherits(x, "POSIXct")
|
||||
}
|
||||
slider_type <- function(x) {
|
||||
if (is.numeric(x)) {
|
||||
"number"
|
||||
} else if (inherits(x, "Date")) {
|
||||
"date"
|
||||
} else if (inherits(x, "POSIXct")) {
|
||||
"datetime"
|
||||
}
|
||||
}
|
||||
|
||||
#' @rdname sliderInput
|
||||
#'
|
||||
|
||||
17
R/utils.R
17
R/utils.R
@@ -1751,23 +1751,6 @@ createVarPromiseDomain <- function(env, name, value) {
|
||||
)
|
||||
}
|
||||
|
||||
getSliderType <- function(min, max, value) {
|
||||
vals <- dropNulls(list(value, min, max))
|
||||
if (length(vals) == 0) return("")
|
||||
type <- unique(lapply(vals, function(x) {
|
||||
if (inherits(x, "Date")) "date"
|
||||
else if (inherits(x, "POSIXt")) "datetime"
|
||||
else "number"
|
||||
}))
|
||||
if (length(type) > 1) {
|
||||
rlang::abort(c(
|
||||
"Type mismatch for `min`, `max`, and `value`.",
|
||||
"All values must either be numeric, Date, or POSIXt."
|
||||
))
|
||||
}
|
||||
type[[1]]
|
||||
}
|
||||
|
||||
# Reads the `shiny.sharedSecret` global option, and returns a function that can
|
||||
# be used to test header values for a match.
|
||||
loadSharedSecret <- function() {
|
||||
|
||||
@@ -28,8 +28,10 @@ navbarMenu(title, ..., menuName = title, icon = NULL)
|
||||
\arguments{
|
||||
\item{title}{The title to display in the navbar}
|
||||
|
||||
\item{...}{\code{\link[=tabPanel]{tabPanel()}} elements to include in the navbar.
|
||||
Plain strings will be converted to headers.}
|
||||
\item{...}{\code{\link[=tabPanel]{tabPanel()}} elements to include in the page. The
|
||||
\code{navbarMenu} function also accepts strings, which will be used as menu
|
||||
section headers. If the string is a set of dashes like \code{"----"} a
|
||||
horizontal separator will be displayed in the menu.}
|
||||
|
||||
\item{id}{If provided, you can use \verb{input$}\emph{\code{id}} in your
|
||||
server logic to determine which of the current tabs is active. The value
|
||||
@@ -63,7 +65,7 @@ elements into a menu when the width of the browser is less than 940 pixels
|
||||
|
||||
\item{collapsable}{Deprecated; use \code{collapsible} instead.}
|
||||
|
||||
\item{fluid}{\code{TRUE} to use fluid layout; \code{FALSE} to use fixed
|
||||
\item{fluid}{\code{TRUE} to use a fluid layout. \code{FALSE} to use a fixed
|
||||
layout.}
|
||||
|
||||
\item{responsive}{This option is deprecated; it is no longer optional with
|
||||
@@ -91,11 +93,17 @@ is needed if you want to insert/remove or show/hide an entire
|
||||
|
||||
\item{icon}{Optional icon to appear on a \code{navbarMenu} tab.}
|
||||
}
|
||||
\value{
|
||||
A UI defintion that can be passed to the \link{shinyUI} function.
|
||||
}
|
||||
\description{
|
||||
Create a page that contains a top level navigation bar that can be used to
|
||||
toggle a set of \code{\link[=tabPanel]{tabPanel()}} elements. \code{navbarMenu()} can be used to create
|
||||
an embedded menu within the navbar that in turns includes additional
|
||||
\code{tabPanels}.
|
||||
toggle a set of \code{\link[=tabPanel]{tabPanel()}} elements.
|
||||
}
|
||||
\details{
|
||||
The \code{navbarMenu} function can be used to create an embedded
|
||||
menu within the navbar that in turns includes additional tabPanels (see
|
||||
example below).
|
||||
}
|
||||
\examples{
|
||||
navbarPage("App Title",
|
||||
@@ -115,7 +123,9 @@ navbarPage("App Title",
|
||||
)
|
||||
}
|
||||
\seealso{
|
||||
\code{\link[=updateNavbarPage]{updateNavbarPage()}}, \code{\link[=insertTab]{insertTab()}}, \code{\link[=showTab]{showTab()}}
|
||||
\code{\link[=tabPanel]{tabPanel()}}, \code{\link[=tabsetPanel]{tabsetPanel()}},
|
||||
\code{\link[=updateNavbarPage]{updateNavbarPage()}}, \code{\link[=insertTab]{insertTab()}},
|
||||
\code{\link[=showTab]{showTab()}}
|
||||
|
||||
Other layout functions:
|
||||
\code{\link{fillPage}()},
|
||||
@@ -125,11 +135,5 @@ Other layout functions:
|
||||
\code{\link{sidebarLayout}()},
|
||||
\code{\link{splitLayout}()},
|
||||
\code{\link{verticalLayout}()}
|
||||
|
||||
Other tab layouts:
|
||||
\code{\link{navlistPanel}()},
|
||||
\code{\link{tabPanel}()},
|
||||
\code{\link{tabsetPanel}()}
|
||||
}
|
||||
\concept{layout functions}
|
||||
\concept{tab layouts}
|
||||
|
||||
@@ -14,17 +14,16 @@ navlistPanel(
|
||||
)
|
||||
}
|
||||
\arguments{
|
||||
\item{...}{\code{\link[=tabPanel]{tabPanel()}} elements to include in the navbar.
|
||||
Plain strings will be converted to headers.}
|
||||
\item{...}{\code{\link[=tabPanel]{tabPanel()}} elements to include in the navlist}
|
||||
|
||||
\item{id}{If provided, you can use \verb{input$}\emph{\code{id}} in your
|
||||
server logic to determine which of the current tabs is active. The value
|
||||
will correspond to the \code{value} argument that is passed to
|
||||
server logic to determine which of the current navlist items is active. The
|
||||
value will correspond to the \code{value} argument that is passed to
|
||||
\code{\link[=tabPanel]{tabPanel()}}.}
|
||||
|
||||
\item{selected}{The \code{value} (or, if none was supplied, the \code{title})
|
||||
of the tab that should be selected by default. If \code{NULL}, the first
|
||||
tab will be selected.}
|
||||
of the navigation item that should be selected by default. If \code{NULL},
|
||||
the first navigation will be selected.}
|
||||
|
||||
\item{well}{\code{TRUE} to place a well (gray rounded rectangle) around the
|
||||
navigation list.}
|
||||
@@ -32,7 +31,7 @@ navigation list.}
|
||||
\item{fluid}{\code{TRUE} to use fluid layout; \code{FALSE} to use fixed
|
||||
layout.}
|
||||
|
||||
\item{widths}{Column widths of the navigation list and tabset content areas
|
||||
\item{widths}{Column withs of the navigation list and tabset content areas
|
||||
respectively.}
|
||||
}
|
||||
\description{
|
||||
@@ -40,7 +39,11 @@ Create a navigation list panel that provides a list of links on the left
|
||||
which navigate to a set of tabPanels displayed to the right.
|
||||
}
|
||||
\details{
|
||||
|
||||
You can include headers within the \code{navlistPanel} by including
|
||||
plain text elements in the list. Versions of Shiny before 0.11 supported
|
||||
separators with "------", but as of 0.11, separators were no longer
|
||||
supported. This is because version 0.11 switched to Bootstrap 3, which
|
||||
doesn't support separators.
|
||||
}
|
||||
\examples{
|
||||
fluidPage(
|
||||
@@ -56,11 +59,6 @@ fluidPage(
|
||||
)
|
||||
}
|
||||
\seealso{
|
||||
\code{\link[=updateTabsetPanel]{updateTabsetPanel()}}, \code{\link[=insertTab]{insertTab()}}, \code{\link[=showTab]{showTab()}}
|
||||
|
||||
Other tab layouts:
|
||||
\code{\link{navbarPage}()},
|
||||
\code{\link{tabPanel}()},
|
||||
\code{\link{tabsetPanel}()}
|
||||
\code{\link[=tabPanel]{tabPanel()}}, \code{\link[=updateNavlistPanel]{updateNavlistPanel()}},
|
||||
\code{\link[=insertTab]{insertTab()}}, \code{\link[=showTab]{showTab()}}
|
||||
}
|
||||
\concept{tab layouts}
|
||||
|
||||
@@ -21,12 +21,20 @@ that this tab is selected. If omitted and \code{tabsetPanel} has an
|
||||
\item{icon}{Optional icon to appear on the tab. This attribute is only
|
||||
valid when using a \code{tabPanel} within a \code{\link[=navbarPage]{navbarPage()}}.}
|
||||
}
|
||||
\description{
|
||||
\code{tabPanel()} creates a tab panel that can be included within a
|
||||
\code{\link[=tabsetPanel]{tabsetPanel()}}, \code{\link[=navListPanel]{navListPanel()}}, or \code{\link[=navbarPage]{navbarPage()}}. \code{tabPanelBody()}
|
||||
drops the \code{title}, making it most suitable for use within
|
||||
\code{tabsetPanel(type = "hidden")}.
|
||||
\value{
|
||||
A tab that can be passed to \code{\link[=tabsetPanel]{tabsetPanel()}}
|
||||
}
|
||||
\description{
|
||||
Create a tab panel
|
||||
}
|
||||
\section{Functions}{
|
||||
\itemize{
|
||||
\item \code{tabPanel}: Create a tab panel that can be included within a \code{\link[=tabsetPanel]{tabsetPanel()}} or a \code{\link[=navbarPage]{navbarPage()}}.
|
||||
|
||||
\item \code{tabPanelBody}: Create a tab panel that drops the title argument.
|
||||
This function should be used within \code{tabsetPanel(type = "hidden")}. See \code{\link[=tabsetPanel]{tabsetPanel()}} for example usage.
|
||||
}}
|
||||
|
||||
\examples{
|
||||
# Show a tabset that includes a plot, summary, and
|
||||
# table view of the generated distribution
|
||||
@@ -39,9 +47,5 @@ mainPanel(
|
||||
)
|
||||
}
|
||||
\seealso{
|
||||
Other tab layouts:
|
||||
\code{\link{navbarPage}()},
|
||||
\code{\link{navlistPanel}()},
|
||||
\code{\link{tabsetPanel}()}
|
||||
\code{\link[=tabsetPanel]{tabsetPanel()}}
|
||||
}
|
||||
\concept{tab layouts}
|
||||
|
||||
@@ -35,6 +35,9 @@ active tab via other input controls. (See example below)}
|
||||
\item{position}{This argument is deprecated; it has been discontinued in
|
||||
Bootstrap 3.}
|
||||
}
|
||||
\value{
|
||||
A tabset that can be passed to \code{\link[=mainPanel]{mainPanel()}}
|
||||
}
|
||||
\description{
|
||||
Create a tabset that contains \code{\link[=tabPanel]{tabPanel()}} elements. Tabsets are
|
||||
useful for dividing output into multiple independently viewable sections.
|
||||
@@ -80,11 +83,6 @@ if (interactive()) {
|
||||
}
|
||||
}
|
||||
\seealso{
|
||||
\code{\link[=updateTabsetPanel]{updateTabsetPanel()}}, \code{\link[=insertTab]{insertTab()}}, \code{\link[=showTab]{showTab()}}
|
||||
|
||||
Other tab layouts:
|
||||
\code{\link{navbarPage}()},
|
||||
\code{\link{navlistPanel}()},
|
||||
\code{\link{tabPanel}()}
|
||||
\code{\link[=tabPanel]{tabPanel()}}, \code{\link[=updateTabsetPanel]{updateTabsetPanel()}},
|
||||
\code{\link[=insertTab]{insertTab()}}, \code{\link[=showTab]{showTab()}}
|
||||
}
|
||||
\concept{tab layouts}
|
||||
|
||||
28
tests/testthat/_snaps/input-slider.md
Normal file
28
tests/testthat/_snaps/input-slider.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# sliderInput gives informative errors for bad inputs
|
||||
|
||||
Code
|
||||
sliderInput("x", "x")
|
||||
Error <simpleError>
|
||||
argument "min" is missing, with no default
|
||||
Code
|
||||
sliderInput("x", "x", min = NULL, max = 3, value = 2)
|
||||
Error <rlang_error>
|
||||
sliderInput(min) must be a single number, Date, or POSIXct
|
||||
Code
|
||||
sliderInput("x", "x", min = 1, max = NULL, value = 2)
|
||||
Error <rlang_error>
|
||||
sliderInput(value) must be a single number, Date, or POSIXct
|
||||
Code
|
||||
sliderInput("x", "x", min = 1, max = 3, value = NULL)
|
||||
Error <rlang_error>
|
||||
sliderInput(value) must be a single or pair of numbers, Dates, or POSIXcts
|
||||
Code
|
||||
sliderInput("x", "x", min = Sys.Date(), max = Sys.Date(), value = 1)
|
||||
Error <rlang_error>
|
||||
Type mismatch for `min`, `max`, and `value`.
|
||||
i All values must have same type: either numeric, Date, or POSIXt.
|
||||
Code
|
||||
sliderInput("x", "x", min = 1, max = 3, value = 0)
|
||||
Error <rlang_error>
|
||||
`value` does not lie within [min, max]
|
||||
|
||||
@@ -4,99 +4,23 @@ test_that("sliderInput steps don't have rounding errors", {
|
||||
expect_identical(findStepSize(-5.5, 4, NULL), 0.1)
|
||||
})
|
||||
|
||||
test_that("sliderInput can use numbers, dates, or POSIXct", {
|
||||
n <- 1
|
||||
d <- Sys.Date()
|
||||
dt <- Sys.time()
|
||||
|
||||
|
||||
test_that("sliderInput validation", {
|
||||
# Number
|
||||
x <- 10
|
||||
expect_silent(sliderInput('s', 's', x-1, x+1, x))
|
||||
expect_silent(sliderInput('s', 's', x-1, x+1, x-1))
|
||||
expect_silent(sliderInput('s', 's', x-1, x+1, c(x-1, x+1)))
|
||||
|
||||
expect_warning(sliderInput('s', 's', x-1, x+1, x+2))
|
||||
expect_warning(sliderInput('s', 's', x-1, x+1, x-2))
|
||||
expect_warning(sliderInput('s', 's', x-1, x+1, c(x-2, x)))
|
||||
expect_warning(sliderInput('s', 's', x-1, x+1, c(x, x+2)))
|
||||
|
||||
expect_error(sliderInput('s', 's', x-1, x+1))
|
||||
expect_error(sliderInput('s', 's', x-1, x+1, NULL))
|
||||
expect_error(sliderInput('s', 's', x-1, NULL, x))
|
||||
expect_error(sliderInput('s', 's', NULL, x+1, x))
|
||||
expect_error(sliderInput('s', 's', NULL, NULL, x))
|
||||
expect_error(sliderInput('s', 's', x-1, x+1, NA_real_))
|
||||
expect_error(sliderInput('s', 's', x-1, x+1, c(x, NA_real_)))
|
||||
|
||||
# Date
|
||||
x <- Sys.Date()
|
||||
expect_silent(sliderInput('s', 's', x-1, x+1, x))
|
||||
expect_silent(sliderInput('s', 's', x-1, x+1, x-1))
|
||||
expect_silent(sliderInput('s', 's', x-1, x+1, c(x-1, x+1)))
|
||||
|
||||
expect_warning(sliderInput('s', 's', x-1, x+1, x+2))
|
||||
expect_warning(sliderInput('s', 's', x-1, x+1, x-2))
|
||||
expect_warning(sliderInput('s', 's', x-1, x+1, c(x-2, x)))
|
||||
expect_warning(sliderInput('s', 's', x-1, x+1, c(x, x+2)))
|
||||
|
||||
expect_error(sliderInput('s', 's', x-1, x+1))
|
||||
expect_error(sliderInput('s', 's', x-1, x+1, NULL))
|
||||
expect_error(sliderInput('s', 's', x-1, NULL, x))
|
||||
expect_error(sliderInput('s', 's', NULL, x+1, x))
|
||||
expect_error(sliderInput('s', 's', NULL, NULL, x))
|
||||
expect_error(sliderInput('s', 's', x-1, x+1, as.Date(NA)))
|
||||
|
||||
# POSIXct
|
||||
x <- Sys.time()
|
||||
expect_silent(sliderInput('s', 's', x-1, x+1, x))
|
||||
expect_silent(sliderInput('s', 's', x-1, x+1, x-1))
|
||||
expect_silent(sliderInput('s', 's', x-1, x+1, c(x-1, x+1)))
|
||||
|
||||
expect_warning(sliderInput('s', 's', x-1, x+1, x+2))
|
||||
expect_warning(sliderInput('s', 's', x-1, x+1, x-2))
|
||||
expect_warning(sliderInput('s', 's', x-1, x+1, c(x-2, x)))
|
||||
expect_warning(sliderInput('s', 's', x-1, x+1, c(x, x+2)))
|
||||
|
||||
expect_error(sliderInput('s', 's', x-1, x+1))
|
||||
expect_error(sliderInput('s', 's', x-1, x+1, NULL))
|
||||
expect_error(sliderInput('s', 's', x-1, NULL, x))
|
||||
expect_error(sliderInput('s', 's', NULL, x+1, x))
|
||||
expect_error(sliderInput('s', 's', NULL, NULL, x))
|
||||
|
||||
# POSIXLt
|
||||
x <- as.POSIXlt(Sys.time())
|
||||
expect_silent(sliderInput('s', 's', x-1, x+1, x))
|
||||
expect_silent(sliderInput('s', 's', x-1, x+1, x-1))
|
||||
|
||||
expect_warning(sliderInput('s', 's', x-1, x+1, x+2))
|
||||
expect_warning(sliderInput('s', 's', x-1, x+1, x-2))
|
||||
|
||||
if (getRversion() >= "4.0") {
|
||||
expect_silent(sliderInput('s', 's', x-1, x+1, c(x-1, x+1)))
|
||||
expect_warning(sliderInput('s', 's', x-1, x+1, c(x-2, x)))
|
||||
expect_warning(sliderInput('s', 's', x-1, x+1, c(x, x+2)))
|
||||
} else {
|
||||
skip("c() doesn't work sensibly on POSIXlt objects with this version of R")
|
||||
}
|
||||
|
||||
|
||||
expect_error(sliderInput('s', 's', x-1, x+1))
|
||||
expect_error(sliderInput('s', 's', x-1, x+1, NULL))
|
||||
expect_error(sliderInput('s', 's', x-1, NULL, x))
|
||||
expect_error(sliderInput('s', 's', NULL, x+1, x))
|
||||
expect_error(sliderInput('s', 's', NULL, NULL, x))
|
||||
|
||||
|
||||
# Size
|
||||
x <- 10
|
||||
## length 0
|
||||
expect_error(sliderInput('s', 's', x-1, x+1, numeric(0)))
|
||||
expect_error(sliderInput('s', 's', x-1, numeric(0), x))
|
||||
expect_error(sliderInput('s', 's', numeric(0), x+1, x))
|
||||
## length 1
|
||||
expect_silent(sliderInput('s', 's', x-1, x+1, x))
|
||||
## length 2
|
||||
expect_silent(sliderInput('s', 's', x-1, x+1, c(x, x)))
|
||||
## length 3+
|
||||
expect_error(sliderInput('s', 's', x-1, x+1, c(x, x, x)))
|
||||
expect_error(sliderInput('s', 's', x-1, c(x, x, x), x))
|
||||
expect_error(sliderInput('s', 's', c(x, x, x), x+1, x))
|
||||
expect_error(sliderInput("x", "x", n - 1, n + 1, n), NA)
|
||||
expect_error(sliderInput("x", "x", d - 1, d + 1, d), NA)
|
||||
expect_error(sliderInput("x", "x", dt - 1, dt + 1, dt), NA)
|
||||
})
|
||||
|
||||
test_that("sliderInput gives informative errors for bad inputs", {
|
||||
expect_snapshot(error = TRUE, {
|
||||
sliderInput("x", "x")
|
||||
sliderInput("x", "x", min = NULL, max = 3, value = 2)
|
||||
sliderInput("x", "x", min = 1, max = NULL, value = 2)
|
||||
sliderInput("x", "x", min = 1, max = 3, value = NULL)
|
||||
sliderInput("x", "x", min = Sys.Date(), max = Sys.Date(), value = 1)
|
||||
sliderInput("x", "x", min = 1, max = 3, value = 0)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user