diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml
index 275487bf57..4da952ce20 100644
--- a/.github/workflows/R-CMD-check.yaml
+++ b/.github/workflows/R-CMD-check.yaml
@@ -29,8 +29,7 @@ jobs:
# vdiffr & shinytest only runs on mac r-release since the results aren't cross-platform
- {os: macOS-latest, r: 'release', visual_tests: true, node: "14.x", shinytest: true}
- {os: windows-latest, r: 'release'}
- - {os: windows-latest, r: '4.1'}
- - {os: windows-latest, r: '3.6'}
+ # - {os: windows-latest, r: 'oldrel-1'} # pak is having issues
- {os: ubuntu-latest, r: 'devel'}
- {os: ubuntu-latest, r: 'release'}
- {os: ubuntu-latest, r: 'oldrel-1'}
@@ -48,6 +47,8 @@ jobs:
steps:
- uses: actions/checkout@v2
+ with:
+ persist-credentials: false
- uses: r-lib/actions/setup-r@v2
id: install-r
@@ -62,26 +63,10 @@ jobs:
cache-version: 3
needs: check
- - name: Set up Python 3.8
- uses: actions/setup-python@v2
- with:
- python-version: 3.8
-
- name: Install kaleido
if: matrix.config.visual_tests == true
run: |
- sudo chown -R $UID $CONDA # https://github.com/nextstrain/conda/issues/5
- Rscript -e "reticulate::install_miniconda()"
- Rscript -e "reticulate::conda_install('r-reticulate', 'python-kaleido')"
- Rscript -e "reticulate::conda_install('r-reticulate', 'plotly', channel = 'plotly')"
- Rscript -e "reticulate::use_miniconda('r-reticulate')"
-
- - name: Install shinytest deps
- if: matrix.config.shinytest == true
- run: |
- Rscript -e 'shinytest::installDependencies()'
- R CMD install .
- shell: bash
+ Rscript -e 'library(reticulate); use_python(install_python()); py_install(c("kaleido", "plotly"))'
# Run test() before R CMD check since, for some reason, rcmdcheck::rcmdcheck() skips vdiffr tests
- name: Run Tests
@@ -98,7 +83,9 @@ jobs:
uses: actions/upload-artifact@master
with:
name: ${{ runner.os }}-r${{ matrix.config.r }}-results
- path: ./
+ path: |
+ ./
+ !./.git/
- name: Check package
uses: r-lib/actions/check-r-package@v2
diff --git a/DESCRIPTION b/DESCRIPTION
index 6f303dccd3..1471874803 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -42,7 +42,7 @@ Imports:
vctrs,
tibble,
lazyeval (>= 0.2.0),
- rlang (>= 0.4.10),
+ rlang (>= 1.0.0),
crosstalk,
purrr,
data.table,
@@ -57,7 +57,7 @@ Suggests:
testthat,
knitr,
shiny (>= 1.1.0),
- shinytest (>= 1.3.0),
+ shinytest2,
curl,
rmarkdown,
Cairo,
@@ -75,7 +75,8 @@ Suggests:
palmerpenguins,
rversions,
reticulate,
- rsvg
+ rsvg,
+ ggridges
LazyData: true
RoxygenNote: 7.3.1
Encoding: UTF-8
diff --git a/NAMESPACE b/NAMESPACE
index 9fe5f8e0d5..a181db4ad9 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -13,6 +13,7 @@ S3method(geom2trace,GeomErrorbarh)
S3method(geom2trace,GeomPath)
S3method(geom2trace,GeomPoint)
S3method(geom2trace,GeomPolygon)
+S3method(geom2trace,GeomRidgelineGradient)
S3method(geom2trace,GeomText)
S3method(geom2trace,GeomTile)
S3method(geom2trace,default)
@@ -49,6 +50,10 @@ S3method(to_basic,GeomContour)
S3method(to_basic,GeomCrossbar)
S3method(to_basic,GeomDensity)
S3method(to_basic,GeomDensity2d)
+S3method(to_basic,GeomDensityLine)
+S3method(to_basic,GeomDensityRidges)
+S3method(to_basic,GeomDensityRidges2)
+S3method(to_basic,GeomDensityRidgesGradient)
S3method(to_basic,GeomDotplot)
S3method(to_basic,GeomErrorbar)
S3method(to_basic,GeomErrorbarh)
@@ -65,6 +70,8 @@ S3method(to_basic,GeomRaster)
S3method(to_basic,GeomRasterAnn)
S3method(to_basic,GeomRect)
S3method(to_basic,GeomRibbon)
+S3method(to_basic,GeomRidgeline)
+S3method(to_basic,GeomRidgelineGradient)
S3method(to_basic,GeomRug)
S3method(to_basic,GeomSegment)
S3method(to_basic,GeomSf)
diff --git a/NEWS.md b/NEWS.md
index 7471198093..27e654f097 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,5 +1,17 @@
# plotly (development version)
+## New features
+
+* `ggplotly()` now supports the `{ggridges}` package. (#2314)
+
+## Improvements
+
+* `ggplotly()` now works better with the development version of ggplot2 (> v3.4.4). (#2315, #2368)
+
+## Bug fixes
+
+* Closed #2337: Creating a new `event_data()` handler no longer causes a spurious reactive update of existing `event_data()`s. (#2339)
+
# 4.10.4
## Improvements
diff --git a/R/export.R b/R/export.R
index 91f18d0bbf..866a1b60ba 100644
--- a/R/export.R
+++ b/R/export.R
@@ -1,6 +1,6 @@
#' Export a plotly graph to a static file
#'
-#' This function is in the process of being deprecated (use [orca] instead).
+#' This function is deprecated, use [save_image] instead.
#'
#' @details For SVG plots, a screenshot is taken via `webshot::webshot()`.
#' Since `phantomjs` (and hence `webshot`) does not support WebGL,
@@ -19,7 +19,7 @@
#' @author Carson Sievert
#'
export <- function(p = last_plot(), file = "plotly.png", selenium = NULL, ...) {
- .Deprecated("orca")
+ .Deprecated("save_image")
# infer the file type
fileType <- tolower(tools::file_ext(file))
diff --git a/R/ggplotly.R b/R/ggplotly.R
index 98bf487a96..e358bce17a 100644
--- a/R/ggplotly.R
+++ b/R/ggplotly.R
@@ -277,6 +277,11 @@ gg2list <- function(p, width = NULL, height = NULL,
# Compute aesthetics to produce data with generalised variable names
data <- by_layer(function(l, d) l$compute_aesthetics(d, plot))
+ if (exists("setup_plot_labels", envir = asNamespace("ggplot2"))) {
+ # Mirror ggplot2/#5879
+ plot$labels <- ggfun("setup_plot_labels")(plot, layers, data)
+ }
+
# add frame to group if it exists
data <- lapply(data, function(d) {
@@ -463,12 +468,8 @@ gg2list <- function(p, width = NULL, height = NULL,
assign(var, built_env[[var]], envir = envir)
}
- # initiate plotly.js layout with some plot-wide theming stuff
- theme <- ggfun("plot_theme")(plot)
- elements <- names(which(sapply(theme, inherits, "element")))
- for (i in elements) {
- theme[[i]] <- ggplot2::calc_element(i, theme)
- }
+ theme <- calculated_theme_elements(plot)
+
# Translate plot wide theme elements to plotly.js layout
pm <- unitConvert(theme$plot.margin, "pixels")
gglayout <- list(
@@ -1154,6 +1155,23 @@ gg2list <- function(p, width = NULL, height = NULL,
# Due to the non-standard use of assign() in g2list() (above)
utils::globalVariables(c("groupDomains", "layers", "prestats_data", "scales", "sets"))
+# Get the "complete" set of theme elements and their calculated values
+calculated_theme_elements <- function(plot) {
+ if (is.function(asNamespace("ggplot2")$complete_theme)) {
+ theme <- ggplot2::complete_theme(plot$theme)
+ elements <- names(theme)
+ } else {
+ theme <- ggfun("plot_theme")(plot)
+ elements <- names(which(sapply(theme, inherits, "element")))
+ }
+
+ for (i in elements) {
+ theme[[i]] <- ggplot2::calc_element(i, theme)
+ }
+
+ theme
+}
+
#-----------------------------------------------------------------------------
# ggplotly 'utility' functions
@@ -1384,7 +1402,8 @@ rect2shape <- function(rekt = ggplot2::element_rect()) {
linetype = lty2dash(rekt$linetype)
),
yref = "paper",
- xref = "paper"
+ xref = "paper",
+ layer = "below"
)
}
@@ -1408,6 +1427,7 @@ gdef2trace <- function(gdef, theme, gglayout) {
# N.B. ggplot2 >v3.4.2 (specifically #4879) renamed bar to decor and also
# started returning normalized values for the key field
decor <- gdef$decor %||% gdef$bar
+ decor$value <- decor$value %||% decor$max
rng <- range(decor$value)
decor$value <- scales::rescale(decor$value, from = rng)
if (!"decor" %in% names(gdef)) {
diff --git a/R/ggridges.R b/R/ggridges.R
new file mode 100644
index 0000000000..afe34b6978
--- /dev/null
+++ b/R/ggridges.R
@@ -0,0 +1,272 @@
+# Get data for ridge plots
+#
+# @param data dataframe, the data returned by `ggplot2::ggplot_build()`.
+# @param na.rm boolean, from params
+#
+# @return dataframe containing plotting data
+#
+get_ridge_data <- function(data, na.rm) {
+ if (isTRUE(na.rm)) {
+ data <- data[stats::complete.cases(data[c("x", "ymin", "ymax")]), ]
+ }
+
+ #if dataframe is empty there's nothing to draw
+ if (nrow(data) == 0) return(list())
+
+ # remove all points that fall below the minimum height
+ data$ymax[data$height < data$min_height] <- NA
+
+ # order data
+ data <- data[order(data$ymin, data$x), ]
+
+ # remove missing points
+ missing_pos <- !stats::complete.cases(data[c("x", "ymin", "ymax")])
+ ids <- cumsum(missing_pos) + 1
+ data$group <- paste0(data$group, "-", ids)
+ data[!missing_pos, ]
+}
+
+
+# Prepare plotting data for ggridges
+# @param closed boolean, should the polygon be closed at bottom (TRUE for
+# geom_density_ridges2, FALSE for geom_density_ridges)
+prepare_ridge_chart <- function(data, prestats_data, layout, params, p, closed = FALSE, ...) {
+ d <- get_ridge_data(data, params$na.rm)
+
+ # split data into separate groups
+ groups <- split(d, factor(d$group))
+
+ # sort list so lowest ymin values are in the front (opposite of ggridges)
+ o <- order(
+ unlist(
+ lapply(
+ groups,
+ function(data) data$ymin[1]
+ )
+ ),
+ decreasing = FALSE
+ )
+ groups <- groups[o]
+
+ # for each group create a density + vline + point as applicable
+ res <- lapply(
+ rev(groups),
+ function(x) {
+ draw_stuff <- split(x, x$datatype)
+
+ # first draw the basic density ridge part
+ stopifnot(!is.null(draw_stuff$ridgeline))
+
+ d2 <- d1 <- draw_stuff$ridgeline
+ if (!closed) d2$colour <- NA # no colour for density bottom line
+
+ d1$y <- d1$ymax
+ d1$alpha <- 1 # don't use fill alpha for line alpha
+
+ ridges <- list(
+ to_basic(prefix_class(d2, "GeomDensity")),
+ to_basic(prefix_class(d1, "GeomLine"))
+ )
+ # attach the crosstalk group/set
+ ridges[[1]] <- structure(ridges[[1]], set = attr(d2, 'set')) # Density
+ ridges[[2]] <- structure(ridges[[2]], set = attr(d1, 'set')) # Line
+
+ if ('vline' %in% names(draw_stuff)) {
+ draw_stuff$vline$xend <- draw_stuff$vline$x
+ draw_stuff$vline$yend <- draw_stuff$vline$ymax
+ draw_stuff$vline$y <- draw_stuff$vline$ymin
+ draw_stuff$vline$colour <- draw_stuff$vline$vline_colour
+ draw_stuff$vline$size <- draw_stuff$vline$vline_size
+
+ vlines <- to_basic(
+ prefix_class(draw_stuff$vline, 'GeomSegment'),
+ prestats_data, layout, params, p, ...
+ )
+ # attach the crosstalk group/set
+ vlines <- structure(vlines, set = attr(draw_stuff$vline, 'set'))
+ ridges <- c(ridges, list(vlines))
+ }
+
+ # points
+ if ('point' %in% names(draw_stuff)) {
+ draw_stuff$point$y <- draw_stuff$point$ymin
+
+ # use point aesthetics
+ draw_stuff$point$shape <- draw_stuff$point$point_shape
+ draw_stuff$point$fill <- draw_stuff$point$point_fill
+ draw_stuff$point$stroke <- draw_stuff$point$point_stroke
+ draw_stuff$point$alpha <- draw_stuff$point$point_alpha
+ draw_stuff$point$colour <- draw_stuff$point$point_colour
+ draw_stuff$point$size <- draw_stuff$point$point_size
+
+ points <- to_basic(
+ prefix_class(as.data.frame(draw_stuff$point), # remove ridge classes
+ 'GeomPoint'),
+ prestats_data, layout, params, p, ...
+ )
+ # attach the crosstalk group/set
+ points <- structure(points, set = attr(draw_stuff$point, 'set'))
+ ridges <- c(ridges, list(points))
+ }
+
+ ridges
+ }
+ )
+ res
+}
+
+
+#' @export
+to_basic.GeomDensityRidgesGradient <- function(data, prestats_data, layout, params, p, ...) {
+ res <- prepare_ridge_chart(data, prestats_data, layout, params, p, FALSE, ...)
+ # set list depth to 1
+ unlist(res, recursive = FALSE)
+}
+
+
+#' @export
+to_basic.GeomDensityRidges <- function(data, prestats_data, layout, params, p, ...) {
+ to_basic(
+ prefix_class(data, 'GeomDensityRidgesGradient'),
+ prestats_data, layout, params, p,
+ closed = FALSE,
+ ...
+ )
+}
+
+
+#' @export
+to_basic.GeomDensityRidges2 <- function(data, prestats_data, layout, params, p, ...) {
+ to_basic(
+ prefix_class(data, 'GeomDensityRidgesGradient'),
+ prestats_data, layout, params, p,
+ closed = TRUE,
+ ...
+ )
+}
+
+
+
+#' @export
+to_basic.GeomDensityLine <- function(data, prestats_data, layout, params, p, ...) {
+ to_basic(prefix_class(data, 'GeomDensity'))
+}
+
+
+
+#' @export
+to_basic.GeomRidgeline <- function(data, prestats_data, layout, params, p, ...) {
+ to_basic(
+ prefix_class(data, 'GeomDensityRidgesGradient'),
+ prestats_data, layout, params, p, ...
+ )
+}
+
+
+#' @export
+to_basic.GeomRidgelineGradient <- function(data, prestats_data, layout, params, p, ...) {
+ d <- get_ridge_data(data, params$na.rm)
+
+ # split data into separate groups
+ groups <- split(d, factor(d$group))
+
+ # sort list so lowest ymin values are in the front (opposite of ggridges)
+ o <- order(
+ unlist(
+ lapply(
+ groups,
+ function(data) data$ymin[1]
+ )
+ ),
+ decreasing = FALSE
+ )
+ groups <- groups[o]
+
+ # for each group create a density + vline + point as applicable
+ res <- lapply(
+ rev(groups),
+ function(x) {
+
+ draw_stuff <- split(x, x$datatype)
+
+ # first draw the basic density ridge part
+
+ stopifnot(!is.null(draw_stuff$ridgeline))
+ d2 <- d1 <- draw_stuff$ridgeline
+ d2$colour <- NA # no colour for density area
+ d2$fill_plotlyDomain <- NA
+
+ d1$y <- d1$ymax
+ d1$alpha <- 1 # don't use fill alpha for line alpha
+
+ # calculate all the positions where the fill type changes
+ fillchange <- c(FALSE, d2$fill[2:nrow(d2)] != d2$fill[1:nrow(d2)-1])
+
+ # and where the id changes
+ idchange <- c(TRUE, d2$group[2:nrow(d2)] != d2$group[1:nrow(d2)-1])
+
+ # make new ids from all changes in fill style or original id
+ d2$ids <- cumsum(fillchange | idchange)
+
+ # get fill color for all ids
+ fill <- d2$fill[fillchange | idchange]
+
+ # rows to be duplicated
+ dupl_rows <- which(fillchange & !idchange)
+ d2$y <- d2$ymax
+ if (length(dupl_rows) > 0) {
+ rows <- d2[dupl_rows, ]
+ rows$ids <- d2$ids[dupl_rows-1]
+ rows <- rows[rev(seq_len(nrow(rows))), , drop = FALSE]
+ # combine original and duplicated d2
+ d2 <- rbind(d2, rows)
+ }
+
+ # split by group to make polygons
+ d2 <- tibble::deframe(tidyr::nest(d2, .by = 'ids'))
+
+ ridges <- c(
+ d2,
+ list(
+ to_basic(prefix_class(d1, "GeomLine"))
+ )
+ )
+
+ ridges
+ }
+ )
+ # set list depth to 1
+ unlist(res, recursive = FALSE)
+}
+
+
+
+#' @export
+geom2trace.GeomRidgelineGradient <- function(data, params, p) {
+ # munching for polygon
+ positions <- data.frame(
+ x = c(data$x , rev(data$x)),
+ y = c(data$ymax, rev(data$ymin))
+ )
+
+ L <- list(
+ x = positions[["x"]],
+ y = positions[["y"]],
+ text = uniq(data[["hovertext"]]),
+ key = data[["key"]],
+ customdata = data[["customdata"]],
+ frame = data[["frame"]],
+ ids = positions[["ids"]],
+ type = "scatter",
+ mode = "lines",
+ line = list(
+ width = aes2plotly(data, params, linewidth_or_size(GeomPolygon)),
+ color = toRGB('black'),
+ dash = aes2plotly(data, params, "linetype")
+ ),
+ fill = "toself",
+ fillcolor = toRGB(unique(data$fill[1])),
+ hoveron = hover_on(data)
+ )
+ compact(L)
+}
diff --git a/R/kaleido.R b/R/kaleido.R
index 97aa75549b..2ed9cdb678 100644
--- a/R/kaleido.R
+++ b/R/kaleido.R
@@ -8,14 +8,15 @@
#' @section Installation:
#'
#' `kaleido()` requires [the kaleido python
-#' package](https://github.com/plotly/Kaleido/) to be usable via the \pkg{reticulate} package. Here is a recommended way to do the installation:
+#' package](https://github.com/plotly/Kaleido/) to be usable via the
+#' \pkg{reticulate} package. If you're starting from scratch, you install
+#' eveything you need with the following R code:
#'
#' ```
-#' install.packages('reticulate')
-#' reticulate::install_miniconda()
-#' reticulate::conda_install('r-reticulate', 'python-kaleido')
-#' reticulate::conda_install('r-reticulate', 'plotly', channel = 'plotly')
-#' reticulate::use_miniconda('r-reticulate')
+#' install.packages("reticulate")
+#' library(reticulate)
+#' use_python(install_python())
+#' py_install(c("kaleido", "plotly"))
#' ```
#'
#' @param ... not currently used.
@@ -65,16 +66,40 @@ save_image <- function(p, file, ..., width = NULL, height = NULL, scale = NULL)
#' @rdname save_image
#' @export
kaleido <- function(...) {
- if (!rlang::is_installed("reticulate")) {
- stop("`kaleido()` requires the reticulate package.")
- }
- if (!reticulate::py_available(initialize = TRUE)) {
- stop("`kaleido()` requires `reticulate::py_available()` to be `TRUE`. Do you need to install python?")
+ rlang::check_installed("reticulate")
+
+ call_env <- rlang::caller_env()
+
+ if (!reticulate::py_available()) {
+ rlang::abort(c("`{reticulate}` wasn't able to find a Python environment.",
+ i = "If you have an existing Python installation, use `reticulate::use_python()` to inform `{reticulate}` of it.",
+ i = "To have `{reticulate}` install Python for you, `reticulate::install_python()`."
+ ), call = call_env)
}
+ tryCatch(
+ reticulate::import("plotly"),
+ error = function(e) {
+ rlang::abort(c(
+ "The `plotly` Python package is required for static image exporting.",
+ i = "Please install it via `reticulate::py_install('plotly')`."
+ ), call = call_env)
+ }
+ )
+
+ kaleido <- tryCatch(
+ reticulate::import("kaleido"),
+ error = function(e) {
+ rlang::abort(c(
+ "The `kaleido` Python package is required for static image exporting.",
+ i = "Please install it via `reticulate::py_install('kaleido')`."
+ ), call = call_env)
+ }
+ )
+
py <- reticulate::py
scope_name <- paste0("scope_", new_id())
- py[[scope_name]] <- reticulate::import("kaleido")$scopes$plotly$PlotlyScope(
+ py[[scope_name]] <- kaleido$scopes$plotly$PlotlyScope(
plotlyjs = plotlyMainBundlePath()
)
diff --git a/R/layers2traces.R b/R/layers2traces.R
index 240087563f..df78b0c62e 100644
--- a/R/layers2traces.R
+++ b/R/layers2traces.R
@@ -766,7 +766,7 @@ geom2trace.GeomPoint <- function(data, params, p) {
hoveron = hover_on(data)
)
# fill is only relevant for pch %in% 21:25
- pch <- uniq(data$shape) %||% params$shape %||% GeomPoint$default_aes$shape
+ pch <- uniq(data$shape) %||% params$shape %||% GeomPoint$use_defaults(NULL)$shape
if (any(idx <- pch %in% 21:25) || any(idx <- !is.null(data[["fill_plotlyDomain"]]))) {
fill_value <- aes2plotly(data, params, "fill")
if (length(idx) == 1) {
@@ -866,6 +866,9 @@ geom2trace.GeomPolygon <- function(data, params, p) {
#' @export
geom2trace.GeomBoxplot <- function(data, params, p) {
+ # marker styling must inherit from GeomPoint$default_aes
+ # https://github.com/hadley/ggplot2/blob/ab42c2ca81458b0cf78e3ba47ed5db21f4d0fc30/NEWS#L73-L7
+ point_defaults <- GeomPoint$use_defaults(NULL)
compact(list(
x = data[["x"]],
y = data[["y"]],
@@ -879,16 +882,15 @@ geom2trace.GeomBoxplot <- function(data, params, p) {
aes2plotly(data, params, "fill"),
aes2plotly(data, params, "alpha")
),
- # marker styling must inherit from GeomPoint$default_aes
- # https://github.com/hadley/ggplot2/blob/ab42c2ca81458b0cf78e3ba47ed5db21f4d0fc30/NEWS#L73-L77
+ # markers/points
marker = list(
- opacity = GeomPoint$default_aes$alpha,
- outliercolor = toRGB(GeomPoint$default_aes$colour),
+ opacity = point_defaults$alpha,
+ outliercolor = toRGB(point_defaults$colour),
line = list(
- width = mm2pixels(GeomPoint$default_aes$stroke),
- color = toRGB(GeomPoint$default_aes$colour)
+ width = mm2pixels(point_defaults$stroke),
+ color = toRGB(point_defaults$colour)
),
- size = mm2pixels(GeomPoint$default_aes$size)
+ size = mm2pixels(point_defaults$size)
),
line = list(
color = aes2plotly(data, params, "colour"),
@@ -1096,21 +1098,26 @@ ribbon_dat <- function(dat) {
aes2plotly <- function(data, params, aes = "size") {
geom <- class(data)[1]
- # Hack to support this geom_sf hack
- # https://github.com/tidyverse/ggplot2/blob/505e4bfb/R/sf.R#L179-L187
- defaults <- if (inherits(data, "GeomSf")) {
- type <- if (any(grepl("[P-p]oint", class(data)))) "point" else if (any(grepl("[L-l]ine", class(data)))) "line" else ""
- ggfun("default_aesthetics")(type)
- } else {
- geom_obj <- ggfun(geom)
- # If the first class of `data` is a data.frame,
- # ggfun() returns a function because ggplot2 now
- # defines data.frame in it's namespace
- # https://github.com/ropensci/plotly/pull/1481
- if ("default_aes" %in% names(geom_obj)) geom_obj$default_aes else NULL
+ vals <- uniq(data[[aes]]) %||% params[[aes]]
+
+ if (is.null(vals)) {
+ # Hack to support this geom_sf hack
+ # https://github.com/tidyverse/ggplot2/blob/505e4bfb/R/sf.R#L179-L187
+ defaults <- if (inherits(data, "GeomSf") && exists("default_aesthetics", envir = asNamespace("ggplot2"))) {
+ type <- if (any(grepl("[P-p]oint", class(data)))) "point" else if (any(grepl("[L-l]ine", class(data)))) "line" else ""
+ ggfun("default_aesthetics")(type)
+ } else {
+ geom_obj <- ggfun(geom)
+ # If the first class of `data` is a data.frame,
+ # ggfun() returns a function because ggplot2 now
+ # defines data.frame in it's namespace
+ # https://github.com/ropensci/plotly/pull/1481
+ if ("default_aes" %in% names(geom_obj)) geom_obj$use_defaults(NULL) else NULL
+ }
+ vals <- defaults[[aes]]
}
+ vals <- vals %||% NA
- vals <- uniq(data[[aes]]) %||% params[[aes]] %||% defaults[[aes]] %||% NA
converter <- switch(
aes,
size = mm2pixels,
diff --git a/R/orca.R b/R/orca.R
index dfa7d9716a..1f9f988742 100644
--- a/R/orca.R
+++ b/R/orca.R
@@ -1,6 +1,6 @@
#' Static image exporting via orca
#'
-#' Superseded by [kaleido()].
+#' This function is deprecated, use [save_image()] instead.
#'
#' @param p a plotly object.
#' @param file output filename.
@@ -60,7 +60,7 @@ orca <- function(p, file = "plot.png", format = tools::file_ext(file),
parallel_limit = NULL, verbose = FALSE, debug = FALSE,
safe = FALSE, more_args = NULL, ...) {
- .Deprecated("kaleido")
+ .Deprecated("save_image")
orca_available()
diff --git a/R/shiny.R b/R/shiny.R
index 583b4492f8..a25b653aac 100644
--- a/R/shiny.R
+++ b/R/shiny.R
@@ -193,7 +193,7 @@ event_data <- function(
} else {
- eventHasStorage <- eventID %in% names(session$userData$plotlyInputStore)
+ eventHasStorage <- eventID %in% shiny::isolate(names(session$userData$plotlyInputStore))
if (!eventHasStorage) {
# store input value as a reactive value to leverage caching
diff --git a/README.md b/README.md
index a3ad4eecd2..7414a8d888 100644
--- a/README.md
+++ b/README.md
@@ -14,6 +14,12 @@ An R package for creating interactive web graphics via the open source
JavaScript graphing library
[plotly.js](https://github.com/plotly/plotly.js).
+
+
## Installation
Install from CRAN:
diff --git a/inst/examples/shiny/event_data/tests/shinytest/mytest-expected/001.png b/inst/examples/shiny/event_data/tests/shinytest/mytest-expected/001.png
deleted file mode 100644
index 755f0cb579..0000000000
Binary files a/inst/examples/shiny/event_data/tests/shinytest/mytest-expected/001.png and /dev/null differ
diff --git a/inst/examples/shiny/event_data/tests/shinytest/mytest-expected/002.png b/inst/examples/shiny/event_data/tests/shinytest/mytest-expected/002.png
deleted file mode 100644
index 4c6e328694..0000000000
Binary files a/inst/examples/shiny/event_data/tests/shinytest/mytest-expected/002.png and /dev/null differ
diff --git a/inst/examples/shiny/event_data/tests/shinytest/mytest-expected/003.png b/inst/examples/shiny/event_data/tests/shinytest/mytest-expected/003.png
deleted file mode 100644
index 838f3bc87c..0000000000
Binary files a/inst/examples/shiny/event_data/tests/shinytest/mytest-expected/003.png and /dev/null differ
diff --git a/inst/examples/shiny/event_data/tests/shinytest/mytest-expected/004.png b/inst/examples/shiny/event_data/tests/shinytest/mytest-expected/004.png
deleted file mode 100644
index 755f0cb579..0000000000
Binary files a/inst/examples/shiny/event_data/tests/shinytest/mytest-expected/004.png and /dev/null differ
diff --git a/inst/examples/shiny/event_data/tests/shinytest/mytest.R b/inst/examples/shiny/event_data/tests/shinytest/mytest.R
deleted file mode 100644
index 68c6a9b270..0000000000
--- a/inst/examples/shiny/event_data/tests/shinytest/mytest.R
+++ /dev/null
@@ -1,30 +0,0 @@
-library(shinytest)
-app <- ShinyDriver$new("../../", shinyOptions = list(display.mode = "normal"))
-app$snapshotInit("mytest")
-
-app$snapshot()
-app$setInputs(`plotly_hover-A` = "[{\"curveNumber\":0,\"pointNumber\":7,\"x\":24.4,\"y\":3.19,\"customdata\":\"Merc 240D\"}]", allowInputNoBinding_ = TRUE)
-app$setInputs(`plotly_click-A` = "[{\"curveNumber\":0,\"pointNumber\":7,\"x\":24.4,\"y\":3.19,\"customdata\":\"Merc 240D\"}]", allowInputNoBinding_ = TRUE)
-app$setInputs(`plotly_hover-A` = character(0), allowInputNoBinding_ = TRUE)
-Sys.sleep(1)
-app$snapshot()
-app$setInputs(`plotly_brushing-A` = "{\"x\":[25.726819184123485,25.98332414553473],\"y\":[1.3174499999999998,5.61955]}", allowInputNoBinding_ = TRUE)
-app$setInputs(`plotly_selecting-A` = "[]", allowInputNoBinding_ = TRUE)
-app$setInputs(`plotly_brushing-A` = "{\"x\":[24.64379823594267,25.98332414553473],\"y\":[3.2093373493975905,3.5073743975903615]}", allowInputNoBinding_ = TRUE)
-app$setInputs(`plotly_brushing-A` = "{\"x\":[24.045286659316428,25.98332414553473],\"y\":[3.040881626506024,3.5073743975903615]}", allowInputNoBinding_ = TRUE)
-app$setInputs(`plotly_selecting-A` = "[{\"curveNumber\":0,\"pointNumber\":7,\"x\":24.4,\"y\":3.19,\"customdata\":\"Merc 240D\"}]", allowInputNoBinding_ = TRUE)
-app$setInputs(`plotly_brushing-A` = "{\"x\":[23.95978500551268,25.98332414553473],\"y\":[3.0020072289156627,3.5073743975903615]}", allowInputNoBinding_ = TRUE)
-app$setInputs(`plotly_selected-A` = "[{\"curveNumber\":0,\"pointNumber\":7,\"x\":24.4,\"y\":3.19,\"customdata\":\"Merc 240D\"}]", allowInputNoBinding_ = TRUE)
-app$setInputs(`plotly_brushed-A` = "{\"x\":[23.95978500551268,25.98332414553473],\"y\":[3.0020072289156627,3.5073743975903615]}", allowInputNoBinding_ = TRUE)
-app$setInputs(`plotly_hover-A` = "[{\"curveNumber\":0,\"pointNumber\":7,\"x\":24.4,\"y\":3.19,\"customdata\":\"Merc 240D\"}]", allowInputNoBinding_ = TRUE)
-app$setInputs(`plotly_hover-A` = character(0), allowInputNoBinding_ = TRUE)
-app$snapshot()
-app$setInputs(`plotly_selected-A` = character(0), allowInputNoBinding_ = TRUE)
-app$setInputs(`plotly_brushed-A` = character(0), allowInputNoBinding_ = TRUE)
-#app$setInputs(`plotly_selected-A` = character(0), allowInputNoBinding_ = TRUE)
-app$setInputs(`plotly_selecting-A` = character(0), allowInputNoBinding_ = TRUE)
-#app$setInputs(`plotly_brushed-A` = character(0), allowInputNoBinding_ = TRUE)
-app$setInputs(`plotly_brushing-A` = character(0), allowInputNoBinding_ = TRUE)
-app$setInputs(`plotly_click-A` = character(0), allowInputNoBinding_ = TRUE)
-app$setInputs(`plotly_deselect-A` = "\"plot\"", allowInputNoBinding_ = TRUE)
-app$snapshot()
diff --git a/inst/examples/shiny/event_data/tests/testthat.R b/inst/examples/shiny/event_data/tests/testthat.R
new file mode 100644
index 0000000000..7d25b5b9e4
--- /dev/null
+++ b/inst/examples/shiny/event_data/tests/testthat.R
@@ -0,0 +1 @@
+shinytest2::test_app()
diff --git a/inst/examples/shiny/event_data/tests/shinytest/mytest-expected/001.json b/inst/examples/shiny/event_data/tests/testthat/_snaps/shinytest2/001.json
similarity index 97%
rename from inst/examples/shiny/event_data/tests/shinytest/mytest-expected/001.json
rename to inst/examples/shiny/event_data/tests/testthat/_snaps/shinytest2/001.json
index aafb5d9688..e4e32e11f5 100644
--- a/inst/examples/shiny/event_data/tests/shinytest/mytest-expected/001.json
+++ b/inst/examples/shiny/event_data/tests/testthat/_snaps/shinytest2/001.json
@@ -1,6 +1,21 @@
{
"input": {
- "plotType": "ggplotly"
+ ".clientValue-default-plotlyCrosstalkOpts": {
+ "on": "plotly_click",
+ "persistent": false,
+ "dynamic": false,
+ "selectize": false,
+ "opacityDim": 0.2,
+ "selected": {
+ "opacity": 1
+ },
+ "debounce": 0,
+ "color": [
+
+ ]
+ },
+ "plotType": "ggplotly",
+ "plotly_afterplot-A": "\"plot\""
},
"output": {
"brushed": "[1] \"Brush extents appear here (double-click to clear)\"",
diff --git a/inst/examples/shiny/event_data/tests/testthat/_snaps/shinytest2/001_.png b/inst/examples/shiny/event_data/tests/testthat/_snaps/shinytest2/001_.png
new file mode 100644
index 0000000000..f844a551f9
Binary files /dev/null and b/inst/examples/shiny/event_data/tests/testthat/_snaps/shinytest2/001_.png differ
diff --git a/inst/examples/shiny/event_data/tests/shinytest/mytest-expected/002.json b/inst/examples/shiny/event_data/tests/testthat/_snaps/shinytest2/002.json
similarity index 99%
rename from inst/examples/shiny/event_data/tests/shinytest/mytest-expected/002.json
rename to inst/examples/shiny/event_data/tests/testthat/_snaps/shinytest2/002.json
index b089eae1e3..15430c47e8 100644
--- a/inst/examples/shiny/event_data/tests/shinytest/mytest-expected/002.json
+++ b/inst/examples/shiny/event_data/tests/testthat/_snaps/shinytest2/002.json
@@ -14,11 +14,11 @@
]
},
+ "plotType": "ggplotly",
"plotly_afterplot-A": "\"plot\"",
"plotly_click-A": "[{\"curveNumber\":0,\"pointNumber\":7,\"x\":24.4,\"y\":3.19,\"customdata\":\"Merc 240D\"}]",
"plotly_hover-A": null,
- "plotly_relayout-A": "{\"width\":962,\"height\":400}",
- "plotType": "ggplotly"
+ "plotly_relayout-A": "{\"width\":962,\"height\":400}"
},
"output": {
"brushed": "[1] \"Brush extents appear here (double-click to clear)\"",
diff --git a/inst/examples/shiny/event_data/tests/testthat/_snaps/shinytest2/002_.png b/inst/examples/shiny/event_data/tests/testthat/_snaps/shinytest2/002_.png
new file mode 100644
index 0000000000..b96cc7b25e
Binary files /dev/null and b/inst/examples/shiny/event_data/tests/testthat/_snaps/shinytest2/002_.png differ
diff --git a/inst/examples/shiny/event_data/tests/shinytest/mytest-expected/003.json b/inst/examples/shiny/event_data/tests/testthat/_snaps/shinytest2/003.json
similarity index 99%
rename from inst/examples/shiny/event_data/tests/shinytest/mytest-expected/003.json
rename to inst/examples/shiny/event_data/tests/testthat/_snaps/shinytest2/003.json
index 264b18e0a8..91f5634177 100644
--- a/inst/examples/shiny/event_data/tests/shinytest/mytest-expected/003.json
+++ b/inst/examples/shiny/event_data/tests/testthat/_snaps/shinytest2/003.json
@@ -14,6 +14,7 @@
]
},
+ "plotType": "ggplotly",
"plotly_afterplot-A": "\"plot\"",
"plotly_brushed-A": "{\"x\":[23.95978500551268,25.98332414553473],\"y\":[3.0020072289156627,3.5073743975903615]}",
"plotly_brushing-A": "{\"x\":[23.95978500551268,25.98332414553473],\"y\":[3.0020072289156627,3.5073743975903615]}",
@@ -21,8 +22,7 @@
"plotly_hover-A": null,
"plotly_relayout-A": "{\"width\":962,\"height\":400}",
"plotly_selected-A": "[{\"curveNumber\":0,\"pointNumber\":7,\"x\":24.4,\"y\":3.19,\"customdata\":\"Merc 240D\"}]",
- "plotly_selecting-A": "[{\"curveNumber\":0,\"pointNumber\":7,\"x\":24.4,\"y\":3.19,\"customdata\":\"Merc 240D\"}]",
- "plotType": "ggplotly"
+ "plotly_selecting-A": "[{\"curveNumber\":0,\"pointNumber\":7,\"x\":24.4,\"y\":3.19,\"customdata\":\"Merc 240D\"}]"
},
"output": {
"brushed": "$x\n[1] 23.95979 25.98332\n\n$y\n[1] 3.002007 3.507374",
diff --git a/inst/examples/shiny/event_data/tests/testthat/_snaps/shinytest2/003_.png b/inst/examples/shiny/event_data/tests/testthat/_snaps/shinytest2/003_.png
new file mode 100644
index 0000000000..6c51c45735
Binary files /dev/null and b/inst/examples/shiny/event_data/tests/testthat/_snaps/shinytest2/003_.png differ
diff --git a/inst/examples/shiny/event_data/tests/shinytest/mytest-expected/004.json b/inst/examples/shiny/event_data/tests/testthat/_snaps/shinytest2/004.json
similarity index 99%
rename from inst/examples/shiny/event_data/tests/shinytest/mytest-expected/004.json
rename to inst/examples/shiny/event_data/tests/testthat/_snaps/shinytest2/004.json
index 5552f3edd5..a5fc81e2ee 100644
--- a/inst/examples/shiny/event_data/tests/shinytest/mytest-expected/004.json
+++ b/inst/examples/shiny/event_data/tests/testthat/_snaps/shinytest2/004.json
@@ -14,6 +14,7 @@
]
},
+ "plotType": "ggplotly",
"plotly_afterplot-A": "\"plot\"",
"plotly_brushed-A": null,
"plotly_brushing-A": null,
@@ -22,8 +23,7 @@
"plotly_hover-A": null,
"plotly_relayout-A": "{\"width\":962,\"height\":400}",
"plotly_selected-A": null,
- "plotly_selecting-A": null,
- "plotType": "ggplotly"
+ "plotly_selecting-A": null
},
"output": {
"brushed": "[1] \"Brush extents appear here (double-click to clear)\"",
diff --git a/inst/examples/shiny/event_data/tests/testthat/_snaps/shinytest2/004_.png b/inst/examples/shiny/event_data/tests/testthat/_snaps/shinytest2/004_.png
new file mode 100644
index 0000000000..e424b18f25
Binary files /dev/null and b/inst/examples/shiny/event_data/tests/testthat/_snaps/shinytest2/004_.png differ
diff --git a/inst/examples/shiny/event_data/tests/testthat/setup-shinytest2.R b/inst/examples/shiny/event_data/tests/testthat/setup-shinytest2.R
new file mode 100644
index 0000000000..be65b4f035
--- /dev/null
+++ b/inst/examples/shiny/event_data/tests/testthat/setup-shinytest2.R
@@ -0,0 +1,2 @@
+# Load application support files into testing environment
+shinytest2::load_app_env()
diff --git a/inst/examples/shiny/event_data/tests/testthat/test-shinytest2.R b/inst/examples/shiny/event_data/tests/testthat/test-shinytest2.R
new file mode 100644
index 0000000000..ead36064f6
--- /dev/null
+++ b/inst/examples/shiny/event_data/tests/testthat/test-shinytest2.R
@@ -0,0 +1,34 @@
+library(shinytest2)
+app <- AppDriver$new(
+ "../../", view = interactive(),
+ options = list(display.mode = "normal")
+)
+
+test_that("Plotly input values in Shiny", {
+ app$expect_values()
+ app$set_inputs(`plotly_hover-A` = "[{\"curveNumber\":0,\"pointNumber\":7,\"x\":24.4,\"y\":3.19,\"customdata\":\"Merc 240D\"}]", allow_no_input_binding_ = TRUE)
+ app$set_inputs(`plotly_click-A` = "[{\"curveNumber\":0,\"pointNumber\":7,\"x\":24.4,\"y\":3.19,\"customdata\":\"Merc 240D\"}]", allow_no_input_binding_ = TRUE)
+ app$set_inputs(`plotly_hover-A` = character(0), allow_no_input_binding_ = TRUE)
+ Sys.sleep(1)
+ app$expect_values()
+ app$set_inputs(`plotly_brushing-A` = "{\"x\":[25.726819184123485,25.98332414553473],\"y\":[1.3174499999999998,5.61955]}", allow_no_input_binding_ = TRUE)
+ app$set_inputs(`plotly_selecting-A` = "[]", allow_no_input_binding_ = TRUE)
+ app$set_inputs(`plotly_brushing-A` = "{\"x\":[24.64379823594267,25.98332414553473],\"y\":[3.2093373493975905,3.5073743975903615]}", allow_no_input_binding_ = TRUE)
+ app$set_inputs(`plotly_brushing-A` = "{\"x\":[24.045286659316428,25.98332414553473],\"y\":[3.040881626506024,3.5073743975903615]}", allow_no_input_binding_ = TRUE)
+ app$set_inputs(`plotly_selecting-A` = "[{\"curveNumber\":0,\"pointNumber\":7,\"x\":24.4,\"y\":3.19,\"customdata\":\"Merc 240D\"}]", allow_no_input_binding_ = TRUE)
+ app$set_inputs(`plotly_brushing-A` = "{\"x\":[23.95978500551268,25.98332414553473],\"y\":[3.0020072289156627,3.5073743975903615]}", allow_no_input_binding_ = TRUE)
+ app$set_inputs(`plotly_selected-A` = "[{\"curveNumber\":0,\"pointNumber\":7,\"x\":24.4,\"y\":3.19,\"customdata\":\"Merc 240D\"}]", allow_no_input_binding_ = TRUE)
+ app$set_inputs(`plotly_brushed-A` = "{\"x\":[23.95978500551268,25.98332414553473],\"y\":[3.0020072289156627,3.5073743975903615]}", allow_no_input_binding_ = TRUE)
+ app$set_inputs(`plotly_hover-A` = "[{\"curveNumber\":0,\"pointNumber\":7,\"x\":24.4,\"y\":3.19,\"customdata\":\"Merc 240D\"}]", allow_no_input_binding_ = TRUE)
+ app$set_inputs(`plotly_hover-A` = character(0), allow_no_input_binding_ = TRUE)
+ app$expect_values()
+ app$set_inputs(`plotly_selected-A` = character(0), allow_no_input_binding_ = TRUE)
+ app$set_inputs(`plotly_brushed-A` = character(0), allow_no_input_binding_ = TRUE)
+ #app$set_inputs(`plotly_selected-A` = character(0), allow_no_input_binding_ = TRUE)
+ app$set_inputs(`plotly_selecting-A` = character(0), allow_no_input_binding_ = TRUE)
+ #app$set_inputs(`plotly_brushed-A` = character(0), allow_no_input_binding_ = TRUE)
+ app$set_inputs(`plotly_brushing-A` = character(0), allow_no_input_binding_ = TRUE)
+ app$set_inputs(`plotly_click-A` = character(0), allow_no_input_binding_ = TRUE)
+ app$set_inputs(`plotly_deselect-A` = "\"plot\"", allow_no_input_binding_ = TRUE)
+ app$expect_values()
+})
diff --git a/man/export.Rd b/man/export.Rd
index b8fb536213..fa9cf5c8ee 100644
--- a/man/export.Rd
+++ b/man/export.Rd
@@ -21,7 +21,7 @@ jpeg/png/pdf arguments are passed along to \code{webshot::webshot()}.
Otherwise, they are ignored.}
}
\description{
-This function is in the process of being deprecated (use \link{orca} instead).
+This function is deprecated, use \link{save_image} instead.
}
\details{
For SVG plots, a screenshot is taken via \code{webshot::webshot()}.
diff --git a/man/orca.Rd b/man/orca.Rd
index dc91c1f64c..efd96093d2 100644
--- a/man/orca.Rd
+++ b/man/orca.Rd
@@ -80,7 +80,7 @@ for specifying display and/or electron options, such as \code{--enable-webgl} or
\item{quiet}{Suppress all logging info.}
}
\description{
-Superseded by \code{\link[=kaleido]{kaleido()}}.
+This function is deprecated, use \code{\link[=save_image]{save_image()}} instead.
}
\section{Methods}{
diff --git a/man/reexports.Rd b/man/reexports.Rd
index 6b74bd0ff6..ba9c115313 100644
--- a/man/reexports.Rd
+++ b/man/reexports.Rd
@@ -29,14 +29,61 @@
\alias{reexports}
\alias{\%>\%}
\title{Objects exported from other packages}
+\usage{
+mutate(.data, ...)
+
+mutate_(.data, ..., .dots = list())
+
+transmute(.data, ...)
+
+transmute_(.data, ..., .dots = list())
+
+select(.data, ...)
+
+select_(.data, ..., .dots = list())
+
+rename(.data, ...)
+
+rename_(.data, ..., .dots = list())
+
+group_by(.data, ..., .add = FALSE, .drop = group_by_drop_default(.data))
+
+group_by_(.data, ..., .dots = list(), add = FALSE)
+
+groups(x)
+
+ungroup(x, ...)
+
+summarise(.data, ..., .by = NULL, .groups = NULL)
+
+summarise_(.data, ..., .dots = list())
+
+do(.data, ...)
+
+do_(.data, ..., .dots = list())
+
+arrange(.data, ..., .by_group = FALSE)
+
+arrange_(.data, ..., .dots = list())
+
+distinct(.data, ..., .keep_all = FALSE)
+
+distinct_(.data, ..., .dots, .keep_all = FALSE)
+
+slice(.data, ..., .by = NULL, .preserve = FALSE)
+
+slice_(.data, ..., .dots = list())
+
+filter(.data, ..., .by = NULL, .preserve = FALSE)
+
+filter_(.data, ..., .dots = list())
+}
\keyword{internal}
\description{
These objects are imported from other packages. Follow the links
below to see their documentation.
\describe{
- \item{dplyr}{\code{\link[dplyr]{arrange}}, \code{\link[dplyr:se-deprecated]{arrange_}}, \code{\link[dplyr]{distinct}}, \code{\link[dplyr:se-deprecated]{distinct_}}, \code{\link[dplyr]{do}}, \code{\link[dplyr:se-deprecated]{do_}}, \code{\link[dplyr]{filter}}, \code{\link[dplyr:se-deprecated]{filter_}}, \code{\link[dplyr]{group_by}}, \code{\link[dplyr:se-deprecated]{group_by_}}, \code{\link[dplyr:group_data]{groups}}, \code{\link[dplyr]{mutate}}, \code{\link[dplyr:se-deprecated]{mutate_}}, \code{\link[dplyr]{rename}}, \code{\link[dplyr:se-deprecated]{rename_}}, \code{\link[dplyr]{select}}, \code{\link[dplyr:se-deprecated]{select_}}, \code{\link[dplyr]{slice}}, \code{\link[dplyr:se-deprecated]{slice_}}, \code{\link[dplyr]{summarise}}, \code{\link[dplyr:se-deprecated]{summarise_}}, \code{\link[dplyr]{transmute}}, \code{\link[dplyr:se-deprecated]{transmute_}}, \code{\link[dplyr:group_by]{ungroup}}}
-
\item{magrittr}{\code{\link[magrittr:pipe]{\%>\%}}}
}}
diff --git a/man/save_image.Rd b/man/save_image.Rd
index 0934d81f86..baebd94f09 100644
--- a/man/save_image.Rd
+++ b/man/save_image.Rd
@@ -45,13 +45,14 @@ method for converting R plots into static images. \code{save_image()} provides a
\section{Installation}{
-\code{kaleido()} requires \href{https://github.com/plotly/Kaleido/}{the kaleido python package} to be usable via the \pkg{reticulate} package. Here is a recommended way to do the installation:
+\code{kaleido()} requires \href{https://github.com/plotly/Kaleido/}{the kaleido python package} to be usable via the
+\pkg{reticulate} package. If you're starting from scratch, you install
+eveything you need with the following R code:
-\if{html}{\out{}}\preformatted{install.packages('reticulate')
-reticulate::install_miniconda()
-reticulate::conda_install('r-reticulate', 'python-kaleido')
-reticulate::conda_install('r-reticulate', 'plotly', channel = 'plotly')
-reticulate::use_miniconda('r-reticulate')
+\if{html}{\out{
}}\preformatted{install.packages("reticulate")
+library(reticulate)
+use_python(install_python())
+py_install(c("kaleido", "plotly"))
}\if{html}{\out{
}}
}
diff --git a/tests/testthat/_snaps/ggalluvial/stratum-alluvium-color.svg b/tests/testthat/_snaps/ggalluvial/stratum-alluvium-color.svg
index cb49c6e6e7..d201562295 100644
--- a/tests/testthat/_snaps/ggalluvial/stratum-alluvium-color.svg
+++ b/tests/testthat/_snaps/ggalluvial/stratum-alluvium-color.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggalluvial/stratum-alluvium.svg b/tests/testthat/_snaps/ggalluvial/stratum-alluvium.svg
index 12d6c570db..f80bf4a8b1 100644
--- a/tests/testthat/_snaps/ggalluvial/stratum-alluvium.svg
+++ b/tests/testthat/_snaps/ggalluvial/stratum-alluvium.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-col/col.svg b/tests/testthat/_snaps/ggplot-col/col.svg
index 604aa66370..515c34c421 100644
--- a/tests/testthat/_snaps/ggplot-col/col.svg
+++ b/tests/testthat/_snaps/ggplot-col/col.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-contour/raster-contour-binned.svg b/tests/testthat/_snaps/ggplot-contour/raster-contour-binned.svg
new file mode 100644
index 0000000000..91b992bdd9
--- /dev/null
+++ b/tests/testthat/_snaps/ggplot-contour/raster-contour-binned.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggplot-density/density-color.svg b/tests/testthat/_snaps/ggplot-density/density-color.svg
index 7024b64224..37b2aac673 100644
--- a/tests/testthat/_snaps/ggplot-density/density-color.svg
+++ b/tests/testthat/_snaps/ggplot-density/density-color.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-density/density-fill.svg b/tests/testthat/_snaps/ggplot-density/density-fill.svg
index 5cc84ba105..10048115c7 100644
--- a/tests/testthat/_snaps/ggplot-density/density-fill.svg
+++ b/tests/testthat/_snaps/ggplot-density/density-fill.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-density/density-histogram.svg b/tests/testthat/_snaps/ggplot-density/density-histogram.svg
index f35c2fd108..b04eb749f6 100644
--- a/tests/testthat/_snaps/ggplot-density/density-histogram.svg
+++ b/tests/testthat/_snaps/ggplot-density/density-histogram.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-density/density-simple.svg b/tests/testthat/_snaps/ggplot-density/density-simple.svg
index 6a05645c6c..caa094e4ad 100644
--- a/tests/testthat/_snaps/ggplot-density/density-simple.svg
+++ b/tests/testthat/_snaps/ggplot-density/density-simple.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-density/density-traces-order.svg b/tests/testthat/_snaps/ggplot-density/density-traces-order.svg
index e1befb3cd7..cffbfa414f 100644
--- a/tests/testthat/_snaps/ggplot-density/density-traces-order.svg
+++ b/tests/testthat/_snaps/ggplot-density/density-traces-order.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-facets/3-panels.svg b/tests/testthat/_snaps/ggplot-facets/3-panels.svg
index a634bfe4e2..00587badec 100644
--- a/tests/testthat/_snaps/ggplot-facets/3-panels.svg
+++ b/tests/testthat/_snaps/ggplot-facets/3-panels.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-facets/barley.svg b/tests/testthat/_snaps/ggplot-facets/barley.svg
index b1acebfdff..f302ea46d8 100644
--- a/tests/testthat/_snaps/ggplot-facets/barley.svg
+++ b/tests/testthat/_snaps/ggplot-facets/barley.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-facets/facet-wrap-free-mult.svg b/tests/testthat/_snaps/ggplot-facets/facet-wrap-free-mult.svg
index bcf00858fd..8c5362adbd 100644
--- a/tests/testthat/_snaps/ggplot-facets/facet-wrap-free-mult.svg
+++ b/tests/testthat/_snaps/ggplot-facets/facet-wrap-free-mult.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-facets/facet-wrap-free-x.svg b/tests/testthat/_snaps/ggplot-facets/facet-wrap-free-x.svg
index 09a466f4d0..141052b850 100644
--- a/tests/testthat/_snaps/ggplot-facets/facet-wrap-free-x.svg
+++ b/tests/testthat/_snaps/ggplot-facets/facet-wrap-free-x.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-facets/facet-wrap-free-y-2.svg b/tests/testthat/_snaps/ggplot-facets/facet-wrap-free-y-2.svg
index 314a630781..066d9187bd 100644
--- a/tests/testthat/_snaps/ggplot-facets/facet-wrap-free-y-2.svg
+++ b/tests/testthat/_snaps/ggplot-facets/facet-wrap-free-y-2.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-facets/facet-wrap-free-y.svg b/tests/testthat/_snaps/ggplot-facets/facet-wrap-free-y.svg
index c61edec570..0c2231fcd6 100644
--- a/tests/testthat/_snaps/ggplot-facets/facet-wrap-free-y.svg
+++ b/tests/testthat/_snaps/ggplot-facets/facet-wrap-free-y.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-facets/facet-wrap-free.svg b/tests/testthat/_snaps/ggplot-facets/facet-wrap-free.svg
index 5f6f8fc2c8..a7198e04b8 100644
--- a/tests/testthat/_snaps/ggplot-facets/facet-wrap-free.svg
+++ b/tests/testthat/_snaps/ggplot-facets/facet-wrap-free.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-heatmap/tile-no-fill.svg b/tests/testthat/_snaps/ggplot-heatmap/tile-no-fill.svg
index 59eac083ca..3ffb60481b 100644
--- a/tests/testthat/_snaps/ggplot-heatmap/tile-no-fill.svg
+++ b/tests/testthat/_snaps/ggplot-heatmap/tile-no-fill.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-histogram/histogram-counts.svg b/tests/testthat/_snaps/ggplot-histogram/histogram-counts.svg
index 23c50b6c1a..bcd437959d 100644
--- a/tests/testthat/_snaps/ggplot-histogram/histogram-counts.svg
+++ b/tests/testthat/_snaps/ggplot-histogram/histogram-counts.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-histogram/histogram-dates.svg b/tests/testthat/_snaps/ggplot-histogram/histogram-dates.svg
index b58fa571d8..a7ce21f158 100644
--- a/tests/testthat/_snaps/ggplot-histogram/histogram-dates.svg
+++ b/tests/testthat/_snaps/ggplot-histogram/histogram-dates.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-histogram/histogram-density.svg b/tests/testthat/_snaps/ggplot-histogram/histogram-density.svg
index 51ac85d8e5..c65ecdb426 100644
--- a/tests/testthat/_snaps/ggplot-histogram/histogram-density.svg
+++ b/tests/testthat/_snaps/ggplot-histogram/histogram-density.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-histogram/histogram-fill-factor-dodge.svg b/tests/testthat/_snaps/ggplot-histogram/histogram-fill-factor-dodge.svg
index ca74cd6861..e1d79a991a 100644
--- a/tests/testthat/_snaps/ggplot-histogram/histogram-fill-factor-dodge.svg
+++ b/tests/testthat/_snaps/ggplot-histogram/histogram-fill-factor-dodge.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-histogram/histogram-fill-factor-facets.svg b/tests/testthat/_snaps/ggplot-histogram/histogram-fill-factor-facets.svg
index d4082381ce..39ffb737cb 100644
--- a/tests/testthat/_snaps/ggplot-histogram/histogram-fill-factor-facets.svg
+++ b/tests/testthat/_snaps/ggplot-histogram/histogram-fill-factor-facets.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-histogram/histogram-fill-factor-identity.svg b/tests/testthat/_snaps/ggplot-histogram/histogram-fill-factor-identity.svg
index 19de855334..311ffb0339 100644
--- a/tests/testthat/_snaps/ggplot-histogram/histogram-fill-factor-identity.svg
+++ b/tests/testthat/_snaps/ggplot-histogram/histogram-fill-factor-identity.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-histogram/histogram-fill-factor.svg b/tests/testthat/_snaps/ggplot-histogram/histogram-fill-factor.svg
index b7dca71a96..f128d6a4e5 100644
--- a/tests/testthat/_snaps/ggplot-histogram/histogram-fill-factor.svg
+++ b/tests/testthat/_snaps/ggplot-histogram/histogram-fill-factor.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-histogram/histogram-fill.svg b/tests/testthat/_snaps/ggplot-histogram/histogram-fill.svg
index 9a6b65a8e9..2cf48289ae 100644
--- a/tests/testthat/_snaps/ggplot-histogram/histogram-fill.svg
+++ b/tests/testthat/_snaps/ggplot-histogram/histogram-fill.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-histogram/histogram-fixed-fill-color.svg b/tests/testthat/_snaps/ggplot-histogram/histogram-fixed-fill-color.svg
index 9f9f80adec..b82629240f 100644
--- a/tests/testthat/_snaps/ggplot-histogram/histogram-fixed-fill-color.svg
+++ b/tests/testthat/_snaps/ggplot-histogram/histogram-fixed-fill-color.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-histogram/histogram-vline.svg b/tests/testthat/_snaps/ggplot-histogram/histogram-vline.svg
index af63a897ee..5b4bdf614e 100644
--- a/tests/testthat/_snaps/ggplot-histogram/histogram-vline.svg
+++ b/tests/testthat/_snaps/ggplot-histogram/histogram-vline.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-legend/guide-aes-none.svg b/tests/testthat/_snaps/ggplot-legend/guide-aes-none.svg
index a20c3f2006..7085010541 100644
--- a/tests/testthat/_snaps/ggplot-legend/guide-aes-none.svg
+++ b/tests/testthat/_snaps/ggplot-legend/guide-aes-none.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-legend/legend-many-legend-items.svg b/tests/testthat/_snaps/ggplot-legend/legend-many-legend-items.svg
index 68d634ed8a..63fe204462 100644
--- a/tests/testthat/_snaps/ggplot-legend/legend-many-legend-items.svg
+++ b/tests/testthat/_snaps/ggplot-legend/legend-many-legend-items.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-map/map-facet.svg b/tests/testthat/_snaps/ggplot-map/map-facet.svg
index 010be0473b..490a40ad79 100644
--- a/tests/testthat/_snaps/ggplot-map/map-facet.svg
+++ b/tests/testthat/_snaps/ggplot-map/map-facet.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-point/all-shapes.svg b/tests/testthat/_snaps/ggplot-point/all-shapes.svg
index 5d4609088a..8e927f22f4 100644
--- a/tests/testthat/_snaps/ggplot-point/all-shapes.svg
+++ b/tests/testthat/_snaps/ggplot-point/all-shapes.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-ribbon/ribbon-alpha.svg b/tests/testthat/_snaps/ggplot-ribbon/ribbon-alpha.svg
index 4e4ee12974..35cf2b4e15 100644
--- a/tests/testthat/_snaps/ggplot-ribbon/ribbon-alpha.svg
+++ b/tests/testthat/_snaps/ggplot-ribbon/ribbon-alpha.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-ribbon/ribbon-colour.svg b/tests/testthat/_snaps/ggplot-ribbon/ribbon-colour.svg
index b5ee09d283..5d58892410 100644
--- a/tests/testthat/_snaps/ggplot-ribbon/ribbon-colour.svg
+++ b/tests/testthat/_snaps/ggplot-ribbon/ribbon-colour.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-ribbon/ribbon-group.svg b/tests/testthat/_snaps/ggplot-ribbon/ribbon-group.svg
index c1bd65537f..ca8c53ce13 100644
--- a/tests/testthat/_snaps/ggplot-ribbon/ribbon-group.svg
+++ b/tests/testthat/_snaps/ggplot-ribbon/ribbon-group.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-sf/sf-aspect.svg b/tests/testthat/_snaps/ggplot-sf/sf-aspect.svg
index 4102cc0b67..b4603aa673 100644
--- a/tests/testthat/_snaps/ggplot-sf/sf-aspect.svg
+++ b/tests/testthat/_snaps/ggplot-sf/sf-aspect.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-sf/sf-axis-ticks.svg b/tests/testthat/_snaps/ggplot-sf/sf-axis-ticks.svg
index b695954579..32baf6c533 100644
--- a/tests/testthat/_snaps/ggplot-sf/sf-axis-ticks.svg
+++ b/tests/testthat/_snaps/ggplot-sf/sf-axis-ticks.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-sf/sf-fill-text.svg b/tests/testthat/_snaps/ggplot-sf/sf-fill-text.svg
index 644ffacdb0..b3ed88da78 100644
--- a/tests/testthat/_snaps/ggplot-sf/sf-fill-text.svg
+++ b/tests/testthat/_snaps/ggplot-sf/sf-fill-text.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-sf/sf-geom-collection.svg b/tests/testthat/_snaps/ggplot-sf/sf-geom-collection.svg
index 65338ebc5d..b710b5adf5 100644
--- a/tests/testthat/_snaps/ggplot-sf/sf-geom-collection.svg
+++ b/tests/testthat/_snaps/ggplot-sf/sf-geom-collection.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-sf/sf-points.svg b/tests/testthat/_snaps/ggplot-sf/sf-points.svg
index e62d92ead3..6cf62007c5 100644
--- a/tests/testthat/_snaps/ggplot-sf/sf-points.svg
+++ b/tests/testthat/_snaps/ggplot-sf/sf-points.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-sf/sf-theme-map.svg b/tests/testthat/_snaps/ggplot-sf/sf-theme-map.svg
index defe049fe3..48b2fba4c2 100644
--- a/tests/testthat/_snaps/ggplot-sf/sf-theme-map.svg
+++ b/tests/testthat/_snaps/ggplot-sf/sf-theme-map.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-sf/sf.svg b/tests/testthat/_snaps/ggplot-sf/sf.svg
index 4102cc0b67..b4603aa673 100644
--- a/tests/testthat/_snaps/ggplot-sf/sf.svg
+++ b/tests/testthat/_snaps/ggplot-sf/sf.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-smooth/smooth-facet.svg b/tests/testthat/_snaps/ggplot-smooth/smooth-facet.svg
index 007e99bd59..42407153f1 100644
--- a/tests/testthat/_snaps/ggplot-smooth/smooth-facet.svg
+++ b/tests/testthat/_snaps/ggplot-smooth/smooth-facet.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-text/text-colour.svg b/tests/testthat/_snaps/ggplot-text/text-colour.svg
index 87e8ad8072..963ddf31fc 100644
--- a/tests/testthat/_snaps/ggplot-text/text-colour.svg
+++ b/tests/testthat/_snaps/ggplot-text/text-colour.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-theme/theme-panel-border-2.svg b/tests/testthat/_snaps/ggplot-theme/theme-panel-border-2.svg
index e3829aa2e9..468c3ffe77 100644
--- a/tests/testthat/_snaps/ggplot-theme/theme-panel-border-2.svg
+++ b/tests/testthat/_snaps/ggplot-theme/theme-panel-border-2.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-violin/violin-aes.svg b/tests/testthat/_snaps/ggplot-violin/violin-aes.svg
index c51fb9bdca..9e19480d10 100644
--- a/tests/testthat/_snaps/ggplot-violin/violin-aes.svg
+++ b/tests/testthat/_snaps/ggplot-violin/violin-aes.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggplot-violin/violin.svg b/tests/testthat/_snaps/ggplot-violin/violin.svg
index 1a8ec9197d..c79f57e606 100644
--- a/tests/testthat/_snaps/ggplot-violin/violin.svg
+++ b/tests/testthat/_snaps/ggplot-violin/violin.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/ggridges/basic-ridgeline.svg b/tests/testthat/_snaps/ggridges/basic-ridgeline.svg
new file mode 100644
index 0000000000..6470518639
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/basic-ridgeline.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggridges/cutting-tails.svg b/tests/testthat/_snaps/ggridges/cutting-tails.svg
new file mode 100644
index 0000000000..4c2e9ec36c
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/cutting-tails.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggridges/density-ridgeline.svg b/tests/testthat/_snaps/ggridges/density-ridgeline.svg
new file mode 100644
index 0000000000..7d5012aabf
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/density-ridgeline.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggridges/density-ridgeline2.svg b/tests/testthat/_snaps/ggridges/density-ridgeline2.svg
new file mode 100644
index 0000000000..7648b6d017
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/density-ridgeline2.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggridges/histogram-ridges.svg b/tests/testthat/_snaps/ggridges/histogram-ridges.svg
new file mode 100644
index 0000000000..6b73b75dc3
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/histogram-ridges.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggridges/jittering-points.svg b/tests/testthat/_snaps/ggridges/jittering-points.svg
new file mode 100644
index 0000000000..7579dbb5dd
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/jittering-points.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggridges/manual-densities-stat-identity.svg b/tests/testthat/_snaps/ggridges/manual-densities-stat-identity.svg
new file mode 100644
index 0000000000..287d171f60
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/manual-densities-stat-identity.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggridges/multiple-ridgelines.svg b/tests/testthat/_snaps/ggridges/multiple-ridgelines.svg
new file mode 100644
index 0000000000..8f81ceab01
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/multiple-ridgelines.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggridges/negative-height-cut.svg b/tests/testthat/_snaps/ggridges/negative-height-cut.svg
new file mode 100644
index 0000000000..ada40d8242
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/negative-height-cut.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggridges/negative-height-retained.svg b/tests/testthat/_snaps/ggridges/negative-height-retained.svg
new file mode 100644
index 0000000000..6619000ff9
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/negative-height-retained.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggridges/numeric-grouping.svg b/tests/testthat/_snaps/ggridges/numeric-grouping.svg
new file mode 100644
index 0000000000..c995d8607e
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/numeric-grouping.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggridges/overlapping-facet-touching.svg b/tests/testthat/_snaps/ggridges/overlapping-facet-touching.svg
new file mode 100644
index 0000000000..636bf14e81
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/overlapping-facet-touching.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggridges/overlapping-lot.svg b/tests/testthat/_snaps/ggridges/overlapping-lot.svg
new file mode 100644
index 0000000000..8474194f3f
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/overlapping-lot.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggridges/overlapping-none.svg b/tests/testthat/_snaps/ggridges/overlapping-none.svg
new file mode 100644
index 0000000000..3a19ed95bc
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/overlapping-none.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggridges/overlapping-touching.svg b/tests/testthat/_snaps/ggridges/overlapping-touching.svg
new file mode 100644
index 0000000000..465ae2f348
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/overlapping-touching.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggridges/quantile-colouring-tails-only.svg b/tests/testthat/_snaps/ggridges/quantile-colouring-tails-only.svg
new file mode 100644
index 0000000000..2f5ec62269
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/quantile-colouring-tails-only.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggridges/quantile-colouring.svg b/tests/testthat/_snaps/ggridges/quantile-colouring.svg
new file mode 100644
index 0000000000..98d3c65a6d
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/quantile-colouring.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggridges/quantile-cut-points.svg b/tests/testthat/_snaps/ggridges/quantile-cut-points.svg
new file mode 100644
index 0000000000..155980eae8
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/quantile-cut-points.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggridges/quantile-lines-1.svg b/tests/testthat/_snaps/ggridges/quantile-lines-1.svg
new file mode 100644
index 0000000000..a3eb51cf34
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/quantile-lines-1.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggridges/quantile-lines-multi.svg b/tests/testthat/_snaps/ggridges/quantile-lines-multi.svg
new file mode 100644
index 0000000000..b3c2996a82
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/quantile-lines-multi.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggridges/raincloud-effect.svg b/tests/testthat/_snaps/ggridges/raincloud-effect.svg
new file mode 100644
index 0000000000..f31c3c3b89
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/raincloud-effect.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggridges/raincloud-vertical-line-points.svg b/tests/testthat/_snaps/ggridges/raincloud-vertical-line-points.svg
new file mode 100644
index 0000000000..735b868783
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/raincloud-vertical-line-points.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggridges/stat-density.svg b/tests/testthat/_snaps/ggridges/stat-density.svg
new file mode 100644
index 0000000000..ae4c3f0f97
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/stat-density.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggridges/stat-identity.svg b/tests/testthat/_snaps/ggridges/stat-identity.svg
new file mode 100644
index 0000000000..bfd9b447e7
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/stat-identity.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggridges/styling-points.svg b/tests/testthat/_snaps/ggridges/styling-points.svg
new file mode 100644
index 0000000000..7f5ab6e9fe
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/styling-points.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggridges/styling-points2.svg b/tests/testthat/_snaps/ggridges/styling-points2.svg
new file mode 100644
index 0000000000..ed541a2a1e
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/styling-points2.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/ggridges/varying-fill-colours.svg b/tests/testthat/_snaps/ggridges/varying-fill-colours.svg
new file mode 100644
index 0000000000..697afa35d7
--- /dev/null
+++ b/tests/testthat/_snaps/ggridges/varying-fill-colours.svg
@@ -0,0 +1 @@
+
diff --git a/tests/testthat/_snaps/mean-error-bars/error-rect-alpha.svg b/tests/testthat/_snaps/mean-error-bars/error-rect-alpha.svg
index fbc57369a6..1ef4b2a3de 100644
--- a/tests/testthat/_snaps/mean-error-bars/error-rect-alpha.svg
+++ b/tests/testthat/_snaps/mean-error-bars/error-rect-alpha.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/plotly-subplot/ggally-ggcorr.svg b/tests/testthat/_snaps/plotly-subplot/ggally-ggcorr.svg
index c47cd60883..987f28fdbf 100644
--- a/tests/testthat/_snaps/plotly-subplot/ggally-ggcorr.svg
+++ b/tests/testthat/_snaps/plotly-subplot/ggally-ggcorr.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/plotly-subplot/plotly-subplot-ggmatrix.svg b/tests/testthat/_snaps/plotly-subplot/plotly-subplot-ggmatrix.svg
index af626f8fec..7c3e107830 100644
--- a/tests/testthat/_snaps/plotly-subplot/plotly-subplot-ggmatrix.svg
+++ b/tests/testthat/_snaps/plotly-subplot/plotly-subplot-ggmatrix.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/_snaps/plotly-subplot/plotly-subplot-width-height.svg b/tests/testthat/_snaps/plotly-subplot/plotly-subplot-width-height.svg
index 1aa3afa892..ac7a647b97 100644
--- a/tests/testthat/_snaps/plotly-subplot/plotly-subplot-width-height.svg
+++ b/tests/testthat/_snaps/plotly-subplot/plotly-subplot-width-height.svg
@@ -1 +1 @@
-
+
diff --git a/tests/testthat/test-ggplot-area.R b/tests/testthat/test-ggplot-area.R
index acb1b3db8f..5ab2d84b15 100644
--- a/tests/testthat/test-ggplot-area.R
+++ b/tests/testthat/test-ggplot-area.R
@@ -26,9 +26,10 @@ test_that("sanity check for geom_area", {
expect_identical(L$data[[1]]$type, "scatter")
expect_identical(L$data[[1]]$mode, "lines")
expect_identical(L$data[[1]]$fill, "toself")
+ area_defaults <- GeomArea$use_defaults(NULL)
expect_true(
L$data[[1]]$fillcolor ==
- toRGB(GeomArea$default_aes$fill, GeomArea$default_aes$alpha)
+ toRGB(area_defaults$fill, area_defaults$alpha)
)
})
@@ -40,7 +41,7 @@ test_that("transparency alpha in geom_area is converted", {
expect_true(L$data[[1]]$line$color == "transparent")
expect_true(
L$data[[1]]$fillcolor ==
- toRGB(GeomArea$default_aes$fill, 0.4)
+ toRGB(GeomArea$use_defaults(NULL)$fill, 0.4)
)
})
@@ -78,7 +79,8 @@ test_that("Can handle an 'empty' geom_area()", {
expect_length(l$data, 2)
- expect_false(l$data[[1]]$visible)
+ # TODO: add doppelganger test
+ # expect_false(l$data[[1]]$visible)
expect_true(l$data[[2]]$x == 1)
expect_true(l$data[[2]]$y == 1)
expect_true(l$data[[2]]$mode == "markers")
diff --git a/tests/testthat/test-ggplot-contour.R b/tests/testthat/test-ggplot-contour.R
index 5bd48e3cf4..741aeec6c2 100644
--- a/tests/testthat/test-ggplot-contour.R
+++ b/tests/testthat/test-ggplot-contour.R
@@ -12,4 +12,15 @@ test_that("geom_contour is translated to a path", {
expect_identical(L$data[[1]]$mode, "lines")
})
-
+test_that("raster/contour works with scale_fill_binned", {
+ xy_grid <- expand.grid(ps=seq(-1,3, length=100),
+ trs=seq(-1,3,length=100))
+ xy_grid$ptl <- xy_grid$ps^2 + xy_grid$trs^2
+
+ gg <- ggplot(xy_grid) +
+ geom_raster(aes(y=ps,x=trs,fill=ptl), interpolate = TRUE) +
+ geom_contour(aes(y=ps,x=trs,z=ptl), breaks = c(2,4,6,8,10), color='black') +
+ scale_fill_binned(low = 'red', high = 'green', breaks = c(2,4,6,8,10))
+
+ expect_doppelganger_built(gg, "raster-contour-binned")
+})
diff --git a/tests/testthat/test-ggplot-point.R b/tests/testthat/test-ggplot-point.R
index ad50cf10fd..4a090e7c05 100644
--- a/tests/testthat/test-ggplot-point.R
+++ b/tests/testthat/test-ggplot-point.R
@@ -29,7 +29,7 @@ test_that("marker color is non-transparent for open shapes", {
grepl("open$", info$data[[1]]$marker$symbol)
)
expect_true(
- info$data[[1]]$marker$color == toRGB(GeomPoint$default_aes$colour)
+ info$data[[1]]$marker$color == toRGB(GeomPoint$use_defaults(NULL)$colour)
)
})
diff --git a/tests/testthat/test-ggplot-quantile.R b/tests/testthat/test-ggplot-quantile.R
index 483980dac3..16b1e8b4fd 100644
--- a/tests/testthat/test-ggplot-quantile.R
+++ b/tests/testthat/test-ggplot-quantile.R
@@ -20,7 +20,7 @@ test_that("Basic geom_quantile() works", {
expect_equivalent(tr$type, "scatter")
expect_equivalent(tr$mode, "lines")
expect_equivalent(
- tr$line$color, toRGB(GeomQuantile$default_aes[["colour"]])
+ tr$line$color, toRGB(GeomQuantile$use_defaults(NULL)[["colour"]])
)
}
diff --git a/tests/testthat/test-ggridges.R b/tests/testthat/test-ggridges.R
new file mode 100644
index 0000000000..feca915ae6
--- /dev/null
+++ b/tests/testthat/test-ggridges.R
@@ -0,0 +1,313 @@
+skip_if_not_installed("ggridges")
+library(ggridges)
+
+test_that(
+ desc = "ggridges basic ridgelines",
+ code = {
+
+ # simple ridge plot
+ data <- data.frame(x = 1:5, y = rep(1, 5), height = c(0, 1, 3, 4, 2))
+ p <- ggplot(data, aes(x, y, height = height)) + geom_ridgeline()
+
+ p2 <- ggplotly(p)
+
+ expect_doppelganger(p2, 'basic_ridgeline')
+
+
+ # Negative height
+ data <- data.frame(x = 1:5, y = rep(1, 5), height = c(0, 1, -1, 3, 2))
+ plot_base <- ggplot(data, aes(x, y, height = height))
+
+ ## Negative height cut off
+ p <- plot_base + geom_ridgeline()
+
+ p2 <- ggplotly(p)
+ expect_doppelganger(p2, 'negative_height_cut')
+
+
+ ## Negative height allowed
+ p <- plot_base + geom_ridgeline(min_height = -2)
+
+ p2 <- ggplotly(p)
+ expect_doppelganger(p2, 'negative_height_retained')
+
+
+ # Multiple ridgelines at same time
+ d <- data.frame(
+ x = rep(1:5, 3),
+ y = c(rep(0, 5), rep(1, 5), rep(2, 5)),
+ height = c(0, 1, 3, 4, 0, 1, 2, 3, 5, 4, 0, 5, 4, 4, 1)
+ )
+
+ p <- ggplot(d, aes(x, y, height = height, group = y)) +
+ geom_ridgeline(fill = "lightblue")
+
+ p2 <- ggplotly(p)
+ expect_doppelganger(p2, 'multiple_ridgelines')
+
+ # stat = identity (works)
+ p <- ggplot(d, aes(x, y, height = height, group = y)) +
+ geom_density_ridges(stat = "identity", scale = 1)
+
+ p2 <- ggplotly(p)
+ expect_doppelganger(p2, 'stat_identity')
+ }
+)
+
+test_that(
+ desc = "ggridges density_ridgeline",
+ code = {
+
+ # Density ridgeline plots
+
+ p <- ggplot(iris, aes(x = Sepal.Length, y = Species)) +
+ geom_density_ridges()
+ p2 <- ggplotly(p)
+ expect_doppelganger(p2, 'density_ridgeline')
+
+ # geom_density_ridges2 (closed polygon)
+ p <- ggplot(iris, aes(x = Sepal.Length, y = Species)) + geom_density_ridges2()
+ p2 <- ggplotly(p)
+ expect_doppelganger(p2, 'density_ridgeline2')
+
+ # Grouping aesthetic
+ # modified dataset that represents species as a number
+ iris_num <- transform(iris, Species_num = as.numeric(Species))
+
+ p <- ggplot(iris_num,
+ aes(x = Sepal.Length,
+ y = Species_num,
+ group = Species_num)) +
+ geom_density_ridges()
+ p2 <- ggplotly(p)
+ expect_doppelganger(p2, 'numeric_grouping')
+
+ # Cutting trailing tails (works)
+ p <- ggplot(iris, aes(x = Sepal.Length, y = Species)) +
+ geom_density_ridges(rel_min_height = 0.01)
+ p2 <- ggplotly(p)
+ expect_doppelganger(p2, 'cutting_tails')
+
+ # Non-overlapping ridges (Works)
+ p <- ggplot(iris, aes(x = Sepal.Length, y = Species)) +
+ geom_density_ridges(scale = 0.9)
+ p2 <- ggplotly(p)
+ expect_doppelganger(p2, 'overlapping_none')
+
+
+ # Exactly touching (Works)
+ p <- ggplot(iris, aes(x = Sepal.Length, y = Species)) +
+ geom_density_ridges(scale = 1)
+ p2 <- ggplotly(p)
+ expect_doppelganger(p2, 'overlapping_touching')
+
+
+ # scale = 5, substantial overlap (Works)
+ p <- ggplot(iris, aes(x = Sepal.Length, y = Species)) +
+ geom_density_ridges(scale = 5)
+ p2 <- ggplotly(p)
+ expect_doppelganger(p2, 'overlapping_lot')
+
+
+ # Panel scaling (Works)
+ p <- ggplot(iris, aes(x = Sepal.Length, y = Species)) +
+ geom_density_ridges(scale = 1) + facet_wrap(~Species)
+ p2 <- ggplotly(p)
+ expect_doppelganger(p2, 'overlapping_facet_touching')
+
+ }
+)
+
+test_that(
+ desc = "ggridges fill colours",
+ code = {
+
+ # Varying fill colors along the x axis
+
+ # Example 1 (Works, but extra legend that is not shown in ggridges)
+ d <- data.frame(
+ x = rep(1:5, 3) + c(rep(0, 5), rep(0.3, 5), rep(0.6, 5)),
+ y = c(rep(0, 5), rep(1, 5), rep(3, 5)),
+ height = c(0, 1, 3, 4, 0, 1, 2, 3, 5, 4, 0, 5, 4, 4, 1))
+
+ p <- ggplot(d, aes(x, y, height = height, group = y, fill = factor(x+y))) +
+ geom_ridgeline_gradient() +
+ scale_fill_viridis_d(direction = -1, guide = "none")
+ p2 <- ggplotly(p)
+ expect_doppelganger(p2, 'varying_fill_colours')
+
+ # geom_density_ridges_gradient (Doesn't work)
+ # p <- ggplot(lincoln_weather, aes(x = `Mean Temperature [F]`, y = Month, fill = stat(x))) +
+ # geom_density_ridges_gradient(scale = 3, rel_min_height = 0.01) +
+ # scale_fill_viridis_c(name = "Temp. [F]", option = "C") +
+ # labs(title = 'Temperatures in Lincoln NE in 2016')
+ # ggplotly(p) # gets stuck
+
+ # Stats
+
+ ## Quantile lines and coloring by quantiles or probabilities (Works)
+
+ # quantile multiple lines
+ p <- ggplot(iris, aes(x = Sepal.Length, y = Species)) +
+ stat_density_ridges(quantile_lines = TRUE)
+ p2 <- ggplotly(p)
+ expect_doppelganger(p2, 'quantile_lines_multi')
+
+ # quantile single line
+ p <- ggplot(iris, aes(x = Sepal.Length, y = Species)) +
+ stat_density_ridges(quantile_lines = TRUE, quantiles = 2)
+ p2 <- ggplotly(p)
+ expect_doppelganger(p2, 'quantile_lines_1')
+
+ # quantile by cut points
+ p <- ggplot(iris, aes(x = Sepal.Length, y = Species)) +
+ stat_density_ridges(quantile_lines = TRUE,
+ quantiles = c(0.025, 0.975),
+ alpha = 0.7)
+ p2 <- ggplotly(p)
+ expect_doppelganger(p2, 'quantile_cut_points')
+
+
+ ## Colour by quantile
+ # warning since ggridges uses stat(quantile)
+ suppressWarnings(
+ p <- ggplot(iris, aes(x=Sepal.Length, y=Species, fill = factor(stat(quantile)))) +
+ stat_density_ridges(
+ geom = "density_ridges_gradient", calc_ecdf = TRUE,
+ quantiles = 4, quantile_lines = TRUE
+ ) +
+ scale_fill_viridis_d(name = "Quartiles")
+ )
+
+ suppressWarnings(
+ p2 <- ggplotly(p)
+ )
+ expect_doppelganger(p2, 'quantile_colouring')
+
+
+ # highglight tails of distributions (works)
+ p <- ggplot(iris, aes(x = Sepal.Length, y = Species, fill = factor(stat(quantile)))) +
+ stat_density_ridges(
+ geom = "density_ridges_gradient",
+ calc_ecdf = TRUE,
+ quantiles = c(0.025, 0.975)
+ ) +
+ scale_fill_manual(
+ name = "Probability", values = c("#FF0000A0", "#A0A0A0A0", "#0000FFA0"),
+ labels = c("(0, 0.025]", "(0.025, 0.975]", "(0.975, 1]")
+ )
+ p2 <- ggplotly(p)
+ expect_doppelganger(p2, 'quantile_colouring_tails_only')
+
+ # mapping prob onto colour (doesn't work)
+ # p <- ggplot(iris, aes(x = Sepal.Length, y = Species, fill = 0.5 - abs(0.5 - stat(ecdf)))) +
+ # stat_density_ridges(geom = "density_ridges_gradient", calc_ecdf = TRUE) +
+ # scale_fill_viridis_c(name = "Tail probability", direction = -1)
+ # ggplotly(p)
+
+
+ }
+)
+
+
+test_that(
+ desc = "ggridges points",
+ code = {
+
+ set.seed(123) # make jittering reproducible
+ # jittering points (works)
+ p <- ggplot(iris, aes(x = Sepal.Length, y = Species)) +
+ geom_density_ridges(jittered_points = TRUE)
+ p2 <- ggplotly(p)
+ expect_doppelganger(p2, 'jittering points')
+
+ # raincloud effect (works)
+ p <- ggplot(iris, aes(x = Sepal.Length, y = Species)) +
+ geom_density_ridges(
+ jittered_points = TRUE, position = "raincloud",
+ alpha = 0.7, scale = 0.9
+ )
+ p2 <- ggplotly(p)
+ expect_doppelganger(p2, 'raincloud_effect')
+
+ # rug effect (doesn't work, point shape not taken into account)
+ # p <- ggplot(iris, aes(x = Sepal.Length, y = Species)) +
+ # geom_density_ridges(
+ # jittered_points = TRUE,
+ # position = position_points_jitter(width = 0.05, height = 0),
+ # point_shape = '|', point_size = 3, point_alpha = 1, alpha = 0.7,
+ # )
+
+
+ # styling points
+ p <- ggplot(iris, aes(x = Sepal.Length, y = Species, fill = Species)) +
+ geom_density_ridges(
+ aes(point_color = Species, point_fill = Species, point_shape = Species),
+ alpha = .2, point_alpha = 1, jittered_points = TRUE
+ ) +
+ scale_point_color_hue(l = 40) +
+ scale_discrete_manual(aesthetics = "point_shape", values = c(21, 22, 23))
+ p2 <- ggplotly(p)
+ expect_doppelganger(p2, 'styling_points')
+
+ # styling points 2
+ p <- ggplot(iris, aes(x = Sepal.Length, y = Species, fill = Species)) +
+ geom_density_ridges(
+ aes(point_shape = Species, point_fill = Species, point_size = Petal.Length),
+ alpha = .2, point_alpha = 1, jittered_points = TRUE
+ ) +
+ scale_point_color_hue(l = 40) + scale_point_size_continuous(range = c(0.5, 4)) +
+ scale_discrete_manual(aesthetics = "point_shape", values = c(21, 22, 23))
+ p2 <- ggplotly(p)
+ expect_doppelganger(p2, 'styling_points2')
+
+
+ # aesthetics for vertical line (works) (might need to check line on top of points)
+ p <- ggplot(iris, aes(x = Sepal.Length, y = Species)) +
+ geom_density_ridges(
+ jittered_points = TRUE, quantile_lines = TRUE, scale = 0.9, alpha = 0.7,
+ vline_size = 1, vline_color = "red",
+ point_size = 0.4, point_alpha = 1,
+ position = position_raincloud(adjust_vlines = TRUE)
+ )
+ p2 <- ggplotly(p)
+ expect_doppelganger(p2, 'raincloud_vertical_line_points')
+
+ }
+)
+
+
+test_that(
+ desc = "ggridges alternate stats",
+ code = {
+
+ ## stat_density_ridges (works)
+ suppressWarnings({
+ p <- ggplot(iris, aes(x = Sepal.Length, y = Species, height = stat(density))) +
+ geom_density_ridges(stat = "density")
+
+ p2 <- ggplotly(p)
+ })
+ expect_doppelganger(p2, 'stat_density')
+
+
+ skip_if_not_installed("dplyr")
+ iris_densities <- iris %>%
+ dplyr::group_by(Species) %>%
+ dplyr::group_modify(~ ggplot2:::compute_density(.x$Sepal.Length, NULL)) %>%
+ dplyr::rename(Sepal.Length = x)
+
+ p <- ggplot(iris_densities, aes(x = Sepal.Length, y = Species, height = density)) +
+ geom_density_ridges(stat = "identity")
+ p2 <- ggplotly(p)
+ expect_doppelganger(p2, 'manual_densities_stat_identity')
+
+ ## histograms (works)
+ p <- ggplot(iris, aes(x = Sepal.Length, y = Species, height = stat(density))) +
+ geom_density_ridges(stat = "binline", bins = 20, scale = 0.95, draw_baseline = FALSE)
+ p2 <- ggplotly(p)
+ expect_doppelganger(p2, 'histogram_ridges')
+
+ }
+)
+
diff --git a/tests/testthat/test-plotly-shiny.R b/tests/testthat/test-plotly-shiny.R
index 513aa155fb..13369aef58 100644
--- a/tests/testthat/test-plotly-shiny.R
+++ b/tests/testthat/test-plotly-shiny.R
@@ -23,5 +23,5 @@ test_that("event_data shiny app works", {
skip_shinytest_tests()
appdir <- system.file(package = "plotly", "examples", "shiny", "event_data")
- shinytest::expect_pass(shinytest::testApp(appdir))
+ shiny::runTests(appdir)
})
diff --git a/tests/testthat/test-ticktext-linebreaks.R b/tests/testthat/test-ticktext-linebreaks.R
index 7aa2846a7f..09973e48c1 100644
--- a/tests/testthat/test-ticktext-linebreaks.R
+++ b/tests/testthat/test-ticktext-linebreaks.R
@@ -2,11 +2,7 @@
# Compute margin
comp_margin <- function(gg, axisTickText) {
plot <- ggfun("plot_clone")(gg)
- theme <- ggfun("plot_theme")(plot)
- elements <- names(which(sapply(theme, inherits, "element")))
- for (i in elements) {
- theme[[i]] <- ggplot2::calc_element(i, theme)
- }
+ theme <- calculated_theme_elements(plot)
pm <- unitConvert(theme$plot.margin, "pixels")
gglayout <- list(