mirror of
https://github.com/rstudio/shiny.git
synced 2026-01-12 08:27:56 -05:00
Compare commits
7 Commits
testserver
...
jeff-skele
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
337f4c9c40 | ||
|
|
e86c0c4be4 | ||
|
|
44a485b07a | ||
|
|
9138adf8a1 | ||
|
|
e588fc5a4a | ||
|
|
19965c9eb7 | ||
|
|
98e390bc1b |
151
R/app_template.R
151
R/app_template.R
@@ -1,8 +1,6 @@
|
||||
#' Generate a Shiny application from a template
|
||||
#'
|
||||
#' This function populates a directory with files for a Shiny application. They
|
||||
#' are based off of the "12_counter" example which can be run with
|
||||
#' `runExample()`.
|
||||
#' This function populates a directory with files for a Shiny application.
|
||||
#'
|
||||
#' In an interactive R session, this function will, by default, prompt the user
|
||||
#' which components to add to the application.
|
||||
@@ -11,48 +9,49 @@
|
||||
#'
|
||||
#' ```
|
||||
#' appdir/
|
||||
#' ├── app.R
|
||||
#' ├── R
|
||||
#' │ ├── my-module.R
|
||||
#' │ └── utils.R
|
||||
#' └── tests
|
||||
#' ├── server.R
|
||||
#' ├── server
|
||||
#' │ ├── test-mymodule.R
|
||||
#' │ └── test-server.R
|
||||
#' ├── shinytest.R
|
||||
#' ├── shinytest
|
||||
#' │ └── mytest.R
|
||||
#' ├── testthat.R
|
||||
#' └── testthat
|
||||
#' ├── helper-load.R
|
||||
#' └── test-utils.R
|
||||
#' |- app.R
|
||||
#' |- R
|
||||
#' | |- my-module.R
|
||||
#' | |-- sort.R
|
||||
#' `-- tests
|
||||
#' |- server.R
|
||||
#' |- server
|
||||
#' | |- test-mymodule.R
|
||||
#' | `- test-server.R
|
||||
#' |- shinytest.R
|
||||
#' |- shinytest
|
||||
#' | `- mytest.R
|
||||
#' |- testthat.R
|
||||
#' `-- testthat
|
||||
#' |- helper-load.R
|
||||
#' `- test-sort.R
|
||||
#' ```
|
||||
#'
|
||||
#' Some notes about these files:
|
||||
#' * app.R is the main application file.
|
||||
#' * All files in the R/ subdirectory are automatically sourced when the
|
||||
#' * `app.R` is the main application file.
|
||||
#' * All files in the `R/` subdirectory are automatically sourced when the
|
||||
#' application is run.
|
||||
#' * The R/my-module.R file is automatically sourced when the application
|
||||
#' is run. This file contains code for a [Shiny module](moduleServer()) which
|
||||
#' * `R/sort.R` and `R/my-module.R` are automatically sourced when
|
||||
#' the application is run. The first contains a function `lexical_sort()`,
|
||||
#' and the second contains code for a [Shiny module](moduleServer()) which
|
||||
#' is used in the application.
|
||||
#' * The tests/ directory contains various tests for the application. You may
|
||||
#' * `tests/` contains various tests for the application. You may
|
||||
#' choose to use or remove any of them. They can be executed by the
|
||||
#' [runTests()] function.
|
||||
#' * tests/server.R is a test runner for test files in
|
||||
#' tests/server/.
|
||||
#' * tests/server/test-mymodule.R is a test for the module.
|
||||
#' * tests/shinytest.R is a test runner for test files in the
|
||||
#' tests/shinytest/ directory.
|
||||
#' * tests/shinytest/mytest.R is a test that uses the
|
||||
#' * `tests/server.R` is a test runner for test files in
|
||||
#' `tests/server/`.
|
||||
#' * `tests/server/test-mymodule.R` is a test for the module.
|
||||
#' * `tests/shinytest.R` is a test runner for test files in the
|
||||
#' `tests/shinytest/` directory.
|
||||
#' * `tests/shinytest/mytest.R` is a test that uses the
|
||||
#' [shinytest](https://rstudio.github.io/shinytest/) package to do
|
||||
#' snapshot-based testing.
|
||||
#' * tests/testthat.R is a test runner for test files in the
|
||||
#' tests/testthat/ directory.
|
||||
#' * tests/testthat/helper-load.R is a helper script that is automatically
|
||||
#' loaded before running test-counter.R. (This is performed by the testthat
|
||||
#' * `tests/testthat.R` is a test runner for test files in the
|
||||
#' `tests/testthat/` directory.
|
||||
#' * `tests/testthat/helper-load.R` is a helper script that is automatically
|
||||
#' loaded before running `test-mymodule.`R. (This is performed by the testthat
|
||||
#' package.)
|
||||
#' * tests/testthat/test-utils.R is a set of tests that use the
|
||||
#' * `tests/testthat/test-sort.R` is a set of tests that use the
|
||||
#' [testthat](https://testthat.r-lib.org/) package for testing.
|
||||
#'
|
||||
#' @param path Path to create new shiny application template.
|
||||
@@ -67,16 +66,20 @@
|
||||
#' @export
|
||||
shinyAppTemplate <- function(path = NULL, examples = "default")
|
||||
{
|
||||
if (is.null(path)) {
|
||||
stop("Please provide a `path`.")
|
||||
}
|
||||
|
||||
choices <- c(
|
||||
app = "app.R : Main application file",
|
||||
rdir = "R/utils.R : Helper file with R code",
|
||||
rdir = "R/sort.R : Helper file with R code",
|
||||
module = "R/my-module.R : Example module",
|
||||
shinytest = "tests/shinytest/ : Tests using shinytest package",
|
||||
testthat = "tests/testthat/ : Tests using testthat",
|
||||
server = "tests/server/ : Tests of server and module code"
|
||||
)
|
||||
|
||||
if (length(examples) == 1 && examples == "default") {
|
||||
if (identical(examples, "default")) {
|
||||
if (interactive()) {
|
||||
examples <- "ask"
|
||||
} else {
|
||||
@@ -104,6 +107,8 @@ shinyAppTemplate <- function(path = NULL, examples = "default")
|
||||
examples <- names(response)
|
||||
}
|
||||
|
||||
examples <- unique(examples)
|
||||
|
||||
if ("all" %in% examples) {
|
||||
examples <- names(choices)
|
||||
}
|
||||
@@ -122,53 +127,20 @@ shinyAppTemplate <- function(path = NULL, examples = "default")
|
||||
|
||||
# Helper to resolve paths relative to our example
|
||||
example_path <- function(path) {
|
||||
system.file("examples", "12_counter", path, package = "shiny")
|
||||
}
|
||||
|
||||
# Helper to remove rdir code from a file
|
||||
remove_rdir_code <- function(filename) {
|
||||
txt <- readLines(filename)
|
||||
txt <- txt[!grepl("# lexical_sort from R/utils.R", txt)]
|
||||
txt <- sub("Lexically sorted sequence", "Sorted sequence", txt, fixed = TRUE)
|
||||
txt <- sub("lexical_sort", "sort", txt, fixed = TRUE)
|
||||
# Write with \n line endings on all platforms
|
||||
con <- file(filename, open="wb")
|
||||
writeLines(txt, con)
|
||||
close(con)
|
||||
}
|
||||
|
||||
# Helper to remove module code from a file
|
||||
remove_module_code <- function(filename) {
|
||||
txt <- readLines(filename)
|
||||
start_lines <- grep("^ +# =+ Modules =+$", txt)
|
||||
stop_lines <- grep("^ +# =+$", txt)
|
||||
if (length(start_lines) != length(stop_lines)) {
|
||||
stop("Start and end markers are unbalanced.")
|
||||
}
|
||||
if (length(start_lines) == 0) {
|
||||
return()
|
||||
}
|
||||
drop_lines <- unlist(lapply(seq_along(start_lines), function(i) {
|
||||
seq(start_lines[i], stop_lines[i])
|
||||
}))
|
||||
# Write with \n line endings on all platforms
|
||||
con <- file(filename, open="wb")
|
||||
writeLines(txt[-drop_lines], con)
|
||||
close(con)
|
||||
system.file("app_template", path, package = "shiny")
|
||||
}
|
||||
|
||||
# Copy the files for a tests/ subdirectory
|
||||
copy_test_dir <- function(name, with_rdir, with_module) {
|
||||
tests_dir <- file.path(path, "tests")
|
||||
if (!dirExists(tests_dir)) {
|
||||
dir.create(tests_dir, recursive = TRUE)
|
||||
}
|
||||
dir.create(tests_dir, showWarnings = FALSE, recursive = TRUE)
|
||||
|
||||
files <- dir(example_path("tests"), recursive = TRUE)
|
||||
# Note: This is not the same as using dir(pattern = "^shinytest"), since
|
||||
# that will not match files inside of shinytest/.
|
||||
files <- files[grepl(paste0("^", name), files)]
|
||||
|
||||
# Filter out files related to R/utils.R, if applicable.
|
||||
# Filter out files related to R/sort.R, if applicable.
|
||||
if (!with_rdir) {
|
||||
files <- files[!grepl("utils", files)]
|
||||
}
|
||||
@@ -181,7 +153,7 @@ shinyAppTemplate <- function(path = NULL, examples = "default")
|
||||
# Create any subdirectories if needed
|
||||
dirs <- setdiff(unique(dirname(files)), ".")
|
||||
for (dir in dirs) {
|
||||
dir.create(file.path(tests_dir, dir), recursive = TRUE)
|
||||
dir.create(file.path(tests_dir, dir), showWarnings = FALSE, recursive = TRUE)
|
||||
}
|
||||
|
||||
file.copy(
|
||||
@@ -216,30 +188,29 @@ shinyAppTemplate <- function(path = NULL, examples = "default")
|
||||
app_file <- file.path(path, "app.R")
|
||||
if ("app" %in% examples) {
|
||||
if (file.exists(app_file)) {
|
||||
message(app_file, " already exists")
|
||||
}
|
||||
file.copy(example_path("app.R"), path)
|
||||
message("Not writing ", app_file, "because file already exists.")
|
||||
|
||||
if (!"rdir" %in% examples) {
|
||||
remove_rdir_code(app_file)
|
||||
}
|
||||
if (!"module" %in% examples) {
|
||||
remove_module_code(app_file)
|
||||
} else {
|
||||
writeChar(
|
||||
as.character(htmlTemplate(
|
||||
example_path("app.R"),
|
||||
rdir = "rdir" %in% examples,
|
||||
module = "module" %in% examples
|
||||
)),
|
||||
con = app_file,
|
||||
eos = NULL
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
# R/ dir with utils and/or module
|
||||
r_dir <- file.path(path, "R")
|
||||
if ("rdir" %in% examples) {
|
||||
if (!dirExists(r_dir)) {
|
||||
dir.create(r_dir, recursive = TRUE)
|
||||
}
|
||||
file.copy(example_path("R/utils.R"), r_dir, recursive = TRUE)
|
||||
dir.create(r_dir, showWarnings = FALSE, recursive = TRUE)
|
||||
file.copy(example_path("R/sort.R"), r_dir, recursive = TRUE)
|
||||
}
|
||||
if ("module" %in% examples) {
|
||||
if (!dirExists(r_dir)) {
|
||||
dir.create(r_dir, recursive = TRUE)
|
||||
}
|
||||
dir.create(r_dir, showWarnings = FALSE, recursive = TRUE)
|
||||
file.copy(example_path("R/my-module.R"), r_dir, recursive = TRUE)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
mymoduleUI <- function(id, label = "Counter") {
|
||||
# Al uses of Shiny input/output IDs in the UI must be namespaced,
|
||||
# as in ns("x").
|
||||
ns <- NS(id)
|
||||
tagList(
|
||||
actionButton(ns("button"), label = label),
|
||||
@@ -7,6 +9,8 @@ mymoduleUI <- function(id, label = "Counter") {
|
||||
}
|
||||
|
||||
mymoduleServer <- function(id) {
|
||||
# moduleServer() wraps a function to create the server component of a
|
||||
# module.
|
||||
moduleServer(
|
||||
id,
|
||||
function(input, output, session) {
|
||||
@@ -1,26 +1,48 @@
|
||||
ui <- fluidPage(
|
||||
# ======== Modules ========
|
||||
{{
|
||||
# These blocks of code are processed with htmlTemplate()
|
||||
if (isTRUE(module)) {
|
||||
' # ======== Modules ========
|
||||
# mymoduleUI is defined in R/my-module.R
|
||||
mymoduleUI("mymodule1", "Click counter #1"),
|
||||
mymoduleUI("mymodule2", "Click counter #2"),
|
||||
# =========================
|
||||
'
|
||||
}
|
||||
}}
|
||||
wellPanel(
|
||||
sliderInput("size", "Data size", min = 5, max = 20, value = 10),
|
||||
div("Lexically sorted sequence:"),
|
||||
{{
|
||||
if (isTRUE(rdir)) {
|
||||
' div("Lexically sorted sequence:"),'
|
||||
} else {
|
||||
' div("Sorted sequence:"),'
|
||||
}
|
||||
}}
|
||||
verbatimTextOutput("sequence")
|
||||
)
|
||||
)
|
||||
|
||||
server <- function(input, output, session) {
|
||||
# ======== Modules ========
|
||||
{{
|
||||
if (isTRUE(module)) {
|
||||
' # ======== Modules ========
|
||||
# mymoduleServer is defined in R/my-module.R
|
||||
mymoduleServer("mymodule1")
|
||||
mymoduleServer("mymodule2")
|
||||
# =========================
|
||||
|
||||
'
|
||||
}
|
||||
}}
|
||||
data <- reactive({
|
||||
# lexical_sort from R/utils.R
|
||||
lexical_sort(seq_len(input$size))
|
||||
{{
|
||||
if (isTRUE(rdir)) {
|
||||
' # lexical_sort from R/sort.R
|
||||
lexical_sort(seq_len(input$size))'
|
||||
} else {
|
||||
' sort(seq_len(input$size))'
|
||||
}
|
||||
}}
|
||||
})
|
||||
output$sequence <- renderText({
|
||||
paste(data(), collapse = " ")
|
||||
@@ -1,6 +1,7 @@
|
||||
# Use testthat just for expectations
|
||||
library(testthat)
|
||||
|
||||
# See ?testServer for more information
|
||||
testServer(mymoduleServer, {
|
||||
# Set initial value of a button
|
||||
session$setInputs(button = 0)
|
||||
@@ -4,29 +4,34 @@
|
||||
\alias{markdown}
|
||||
\title{Insert inline Markdown}
|
||||
\usage{
|
||||
markdown(mds, extensions = TRUE, ...)
|
||||
markdown(mds, extensions = TRUE, .noWS = NULL, ...)
|
||||
}
|
||||
\arguments{
|
||||
\item{mds}{A character vector of Markdown source to convert to HTML. If the
|
||||
vector has more than one element, resulting HTML is concatenated.}
|
||||
vector has more than one element, a single-element character vector of
|
||||
concatenated HTML is returned.}
|
||||
|
||||
\item{extensions}{Enable Github syntax extensions, defaults to \code{TRUE}.}
|
||||
\item{extensions}{Enable Github syntax extensions; defaults to \code{TRUE}.}
|
||||
|
||||
\item{.noWS}{Character vector used to omit some of the whitespace that would
|
||||
normally be written around generated HTML. Valid options include \code{before},
|
||||
\code{after}, and \code{outside} (equivalent to \code{before} and \code{end}).}
|
||||
|
||||
\item{...}{Additional arguments to pass to \code{\link[commonmark:markdown_html]{commonmark::markdown_html()}}.
|
||||
These arguments are \emph{\link[rlang:dyn-dots]{dynamic}}.}
|
||||
}
|
||||
\value{
|
||||
an \code{html}-classed character vector of rendered HTML
|
||||
a character vector marked as HTML.
|
||||
}
|
||||
\description{
|
||||
This function accepts a character vector of
|
||||
\href{https://en.wikipedia.org/wiki/Markdown}{Markdown}-syntax text and renders
|
||||
it to HTML that may be included in a UI.
|
||||
This function accepts
|
||||
\href{https://en.wikipedia.org/wiki/Markdown}{Markdown}-syntax text and returns
|
||||
HTML that may be included in Shiny UIs.
|
||||
}
|
||||
\details{
|
||||
Prior to interpretation as Markdown, leading whitespace is trimmed from text
|
||||
with \code{\link[glue:trim]{glue::trim()}}. This makes it possible to insert Markdown and for it to
|
||||
be processed correctly even when the call to \code{markdown()} is indented.
|
||||
Leading whitespace is trimmed from Markdown text with \code{\link[glue:trim]{glue::trim()}}.
|
||||
Whitespace trimming ensures Markdown is processed correctly even when the
|
||||
call to \code{markdown()} is indented within surrounding R code.
|
||||
|
||||
By default, \link[commonmark:extensions]{Github extensions} are enabled, but this
|
||||
can be disabled by passing \code{extensions = FALSE}.
|
||||
|
||||
@@ -52,6 +52,6 @@ below to see their documentation.
|
||||
\describe{
|
||||
\item{fastmap}{\code{\link[fastmap]{is.key_missing}}, \code{\link[fastmap]{key_missing}}}
|
||||
|
||||
\item{htmltools}{\code{\link[htmltools]{a}}, \code{\link[htmltools]{br}}, \code{\link[htmltools]{code}}, \code{\link[htmltools]{div}}, \code{\link[htmltools]{em}}, \code{\link[htmltools]{h1}}, \code{\link[htmltools]{h2}}, \code{\link[htmltools]{h3}}, \code{\link[htmltools]{h4}}, \code{\link[htmltools]{h5}}, \code{\link[htmltools]{h6}}, \code{\link[htmltools]{hr}}, \code{\link[htmltools]{HTML}}, \code{\link[htmltools]{htmlTemplate}}, \code{\link[htmltools]{img}}, \code{\link[htmltools]{includeCSS}}, \code{\link[htmltools]{includeHTML}}, \code{\link[htmltools]{includeMarkdown}}, \code{\link[htmltools]{includeScript}}, \code{\link[htmltools]{includeText}}, \code{\link[htmltools]{is.singleton}}, \code{\link[htmltools]{p}}, \code{\link[htmltools]{pre}}, \code{\link[htmltools]{singleton}}, \code{\link[htmltools]{span}}, \code{\link[htmltools]{strong}}, \code{\link[htmltools]{suppressDependencies}}, \code{\link[htmltools]{tag}}, \code{\link[htmltools]{tagAppendAttributes}}, \code{\link[htmltools]{tagAppendChild}}, \code{\link[htmltools]{tagAppendChildren}}, \code{\link[htmltools]{tagGetAttribute}}, \code{\link[htmltools]{tagHasAttribute}}, \code{\link[htmltools]{tagList}}, \code{\link[htmltools]{tags}}, \code{\link[htmltools]{tagSetChildren}}, \code{\link[htmltools]{validateCssUnit}}, \code{\link[htmltools]{withTags}}}
|
||||
\item{htmltools}{\code{\link[htmltools]{HTML}}, \code{\link[htmltools]{a}}, \code{\link[htmltools]{br}}, \code{\link[htmltools]{code}}, \code{\link[htmltools]{div}}, \code{\link[htmltools]{em}}, \code{\link[htmltools]{h1}}, \code{\link[htmltools]{h2}}, \code{\link[htmltools]{h3}}, \code{\link[htmltools]{h4}}, \code{\link[htmltools]{h5}}, \code{\link[htmltools]{h6}}, \code{\link[htmltools]{hr}}, \code{\link[htmltools]{htmlTemplate}}, \code{\link[htmltools]{img}}, \code{\link[htmltools]{includeCSS}}, \code{\link[htmltools]{includeHTML}}, \code{\link[htmltools]{includeMarkdown}}, \code{\link[htmltools]{includeScript}}, \code{\link[htmltools]{includeText}}, \code{\link[htmltools]{is.singleton}}, \code{\link[htmltools]{p}}, \code{\link[htmltools]{pre}}, \code{\link[htmltools]{singleton}}, \code{\link[htmltools]{span}}, \code{\link[htmltools]{strong}}, \code{\link[htmltools]{suppressDependencies}}, \code{\link[htmltools]{tag}}, \code{\link[htmltools]{tagAppendAttributes}}, \code{\link[htmltools]{tagAppendChild}}, \code{\link[htmltools]{tagAppendChildren}}, \code{\link[htmltools]{tagGetAttribute}}, \code{\link[htmltools]{tagHasAttribute}}, \code{\link[htmltools]{tagList}}, \code{\link[htmltools]{tagSetChildren}}, \code{\link[htmltools]{tags}}, \code{\link[htmltools]{validateCssUnit}}, \code{\link[htmltools]{withTags}}}
|
||||
}}
|
||||
|
||||
|
||||
@@ -18,58 +18,57 @@ directory. With "all", all template items will be added to the app
|
||||
directory.}
|
||||
}
|
||||
\description{
|
||||
This function populates a directory with files for a Shiny application. They
|
||||
are based off of the "12_counter" example which can be run with
|
||||
\code{runExample()}.
|
||||
This function populates a directory with files for a Shiny application.
|
||||
}
|
||||
\details{
|
||||
In an interactive R session, this function will, by default, prompt the user
|
||||
which components to add to the application.
|
||||
|
||||
The full example application includes the following files and directories:\preformatted{appdir/
|
||||
├── app.R
|
||||
├── R
|
||||
│ ├── my-module.R
|
||||
│ └── utils.R
|
||||
└── tests
|
||||
├── server.R
|
||||
├── server
|
||||
│ ├── test-mymodule.R
|
||||
│ └── test-server.R
|
||||
├── shinytest.R
|
||||
├── shinytest
|
||||
│ └── mytest.R
|
||||
├── testthat.R
|
||||
└── testthat
|
||||
├── helper-load.R
|
||||
└── test-utils.R
|
||||
|- app.R
|
||||
|- R
|
||||
| |- my-module.R
|
||||
| |-- sort.R
|
||||
`-- tests
|
||||
|- server.R
|
||||
|- server
|
||||
| |- test-mymodule.R
|
||||
| `- test-server.R
|
||||
|- shinytest.R
|
||||
|- shinytest
|
||||
| `- mytest.R
|
||||
|- testthat.R
|
||||
`-- testthat
|
||||
|- helper-load.R
|
||||
`- test-sort.R
|
||||
}
|
||||
|
||||
Some notes about these files:
|
||||
\itemize{
|
||||
\item app.R is the main application file.
|
||||
\item All files in the R/ subdirectory are automatically sourced when the
|
||||
\item \code{app.R} is the main application file.
|
||||
\item All files in the \verb{R/} subdirectory are automatically sourced when the
|
||||
application is run.
|
||||
\item The R/my-module.R file is automatically sourced when the application
|
||||
is run. This file contains code for a \href{moduleServer()}{Shiny module} which
|
||||
\item \code{R/sort.R} and \code{R/my-module.R} are automatically sourced when
|
||||
the application is run. The first contains a function \code{lexical_sort()},
|
||||
and the second contains code for a \href{moduleServer()}{Shiny module} which
|
||||
is used in the application.
|
||||
\item The tests/ directory contains various tests for the application. You may
|
||||
\item \verb{tests/} contains various tests for the application. You may
|
||||
choose to use or remove any of them. They can be executed by the
|
||||
\code{\link[=runTests]{runTests()}} function.
|
||||
\item tests/server.R is a test runner for test files in
|
||||
tests/server/.
|
||||
\item tests/server/test-mymodule.R is a test for the module.
|
||||
\item tests/shinytest.R is a test runner for test files in the
|
||||
tests/shinytest/ directory.
|
||||
\item tests/shinytest/mytest.R is a test that uses the
|
||||
\item \code{tests/server.R} is a test runner for test files in
|
||||
\verb{tests/server/}.
|
||||
\item \code{tests/server/test-mymodule.R} is a test for the module.
|
||||
\item \code{tests/shinytest.R} is a test runner for test files in the
|
||||
\verb{tests/shinytest/} directory.
|
||||
\item \code{tests/shinytest/mytest.R} is a test that uses the
|
||||
\href{https://rstudio.github.io/shinytest/}{shinytest} package to do
|
||||
snapshot-based testing.
|
||||
\item tests/testthat.R is a test runner for test files in the
|
||||
tests/testthat/ directory.
|
||||
\item tests/testthat/helper-load.R is a helper script that is automatically
|
||||
loaded before running test-counter.R. (This is performed by the testthat
|
||||
\item \code{tests/testthat.R} is a test runner for test files in the
|
||||
\verb{tests/testthat/} directory.
|
||||
\item \code{tests/testthat/helper-load.R} is a helper script that is automatically
|
||||
loaded before running \code{test-mymodule.}R. (This is performed by the testthat
|
||||
package.)
|
||||
\item tests/testthat/test-utils.R is a set of tests that use the
|
||||
\item \code{tests/testthat/test-sort.R} is a set of tests that use the
|
||||
\href{https://testthat.r-lib.org/}{testthat} package for testing.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,6 +168,7 @@ reference:
|
||||
- title: Utility functions
|
||||
desc: Miscellaneous utilities that may be useful to advanced users or when extending Shiny.
|
||||
contents:
|
||||
- shinyAppTemplate
|
||||
- req
|
||||
- validate
|
||||
- session
|
||||
|
||||
Reference in New Issue
Block a user