diff --git a/DESCRIPTION b/DESCRIPTION index ba40188f..b45753a7 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -32,6 +32,7 @@ Imports: fs, glue, httr, + mime, jsonlite, lifecycle, magrittr, diff --git a/NAMESPACE b/NAMESPACE index 954fa503..ac608d63 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -58,6 +58,7 @@ export(dashboard_url_chr) export(delete_bundle) export(delete_image) export(delete_tag) +export(delete_thumbnail) export(delete_vanity_url) export(deploy) export(deploy_current) @@ -84,6 +85,7 @@ export(get_oauth_credentials) export(get_procs) export(get_tag_data) export(get_tags) +export(get_thumbnail) export(get_timezones) export(get_usage_shiny) export(get_usage_static) @@ -97,6 +99,7 @@ export(get_variant_schedule) export(get_variants) export(groups_create_remote) export(has_image) +export(has_thumbnail) export(page_cursor) export(page_offset) export(poll_task) @@ -127,6 +130,7 @@ export(set_schedule_semimonth) export(set_schedule_week) export(set_schedule_weekday) export(set_schedule_year) +export(set_thumbnail) export(set_vanity_url) export(swap_vanity_url) export(tbl_connect) diff --git a/NEWS.md b/NEWS.md index bafcac2d..9ff89bba 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,21 @@ +# Unreleased + +## New features + +- New functions `set_thumbnail()`, `get_thumbnail()`, `delete_thumbnail()` and + `has_thumbnail()` let you interact with content thumbnails, replacing older + `*_image()` functions. + +## Lifecycle changes + +### Newly deprecated + +- `set_image_path()`, `set_image_url()`, and `set_image_webshot()` have been + deprecated and will be removed in a future update. They have been replaced by + `set_thumbnail()`, which works both with local file paths and remote URLs to + images. Likewise, `has_image()` and `delete_image()` have been deprecated in + favor of `has_thumbnail()` and `delete_thumbnail()`. + # connectapi 0.3.0 ## Breaking changes diff --git a/R/connect.R b/R/connect.R index 2321960c..937c94db 100644 --- a/R/connect.R +++ b/R/connect.R @@ -107,7 +107,13 @@ Connect <- R6::R6Class( #' @description Build a URL relative to the API root #' @param ... path segments api_url = function(...) { - paste(self$server, "__api__", ..., sep = "/") + self$server_url("__api__", ...) + }, + + #' @description Build a URL relative to the server root + #' @param ... path segments + server_url = function(...) { + paste(self$server, ..., sep = "/") }, #' @description General wrapper around `httr` verbs diff --git a/R/deploy.R b/R/deploy.R index 219dd905..b8f460e2 100644 --- a/R/deploy.R +++ b/R/deploy.R @@ -399,172 +399,6 @@ deploy_current <- function(content) { return(ContentTask$new(connect = content$get_connect(), content = content, task = res)) } - -#' Get the Content Image -#' -#' \lifecycle{experimental} -#' `get_image` saves the content image to the given path (default: temp file). -#' `delete_image` removes the image (optionally saving to the given path) -#' `has_image` returns whether the content has an image -#' -#' @param content A content object -#' @param path optional. The path to the image on disk -#' -#' @rdname get_image -#' @family content functions -#' @export -get_image <- function(content, path = NULL) { - warn_experimental("get_image") - validate_R6_class(content, "Content") - guid <- content$get_content()$guid - - con <- content$get_connect() - - res <- con$GET( - unversioned_url("applications", guid, "image"), - parser = NULL - ) - - if (httr::status_code(res) == 204) { - return(NA) - } - - # guess file extension - if (is.null(path)) { - ct <- httr::headers(res)$`content-type` - if (grepl("^image/", ct)) { - # just strip off 'image/' - ext <- substr(ct, 7, nchar(ct)) - path <- fs::file_temp(pattern = "content_image_", ext = ext) - } else { - # try png - warning(glue::glue("Could not infer file extension from content type: {ct}. Using '.png'")) - path <- fs::file_temp(pattern = "content_image_", ext = ".png") - } - } - - writeBin(httr::content(res, as = "raw"), path) - - return(fs::as_fs_path(path)) -} - -#' @rdname get_image -#' @export -delete_image <- function(content, path = NULL) { - warn_experimental("delete_image") - validate_R6_class(content, "Content") - guid <- content$get_content()$guid - - con <- content$get_connect() - - if (!is.null(path)) { - scoped_experimental_silence() - get_image(content, path) - } - - res <- con$DELETE(unversioned_url("applications", guid, "image")) - - return(content) -} - -#' @rdname get_image -#' @export -has_image <- function(content) { - warn_experimental("has_image") - validate_R6_class(content, "Content") - guid <- content$get_content()$guid - - con <- content$get_connect() - - res <- con$GET(unversioned_url("applications", guid, "image"), parser = NULL) - - httr::status_code(res) != 204 -} - -#' Set the Content Image -#' -#' \lifecycle{experimental} -#' -#' Set the Content Image using a variety of methods. -#' -#' NOTE: `set_image_webshot()` requires [webshot2::webshot()], but currently -#' skips and warns for any content that requires authentication until the -#' `webshot2` package supports authentication. -#' -#' @param content A content object -#' @param path The path to an image on disk -#' @param url The url for an image -#' @param ... Additional arguments passed on to [webshot2::webshot()] -#' -#' @rdname set_image -#' @family content functions -#' @export -set_image_path <- function(content, path) { - warn_experimental("set_image_path") - validate_R6_class(content, "Content") - guid <- content$get_content()$guid - - con <- content$get_connect() - - res <- con$POST( - path = unversioned_url("applications", guid, "image"), - body = httr::upload_file(path) - ) - - # return the input (in case it inherits more than just Content) - content -} - -#' @rdname set_image -#' @export -set_image_url <- function(content, url) { - warn_experimental("set_image_url") - validate_R6_class(content, "Content") - parsed_url <- httr::parse_url(url) - imgfile <- fs::file_temp(pattern = "image", ext = fs::path_ext(parsed_url[["path"]])) - httr::GET(url, httr::write_disk(imgfile)) - - set_image_path(content = content, path = imgfile) -} - -#' @rdname set_image -#' @export -set_image_webshot <- function(content, ...) { - warn_experimental("set_image_webshot") - validate_R6_class(content, "Content") - imgfile <- fs::file_temp(pattern = "webshot", ext = ".png") - - rlang::check_installed("webshot2", "to take screenshots of applications") - content_details <- content$get_content_remote() - - # check if it is possible to take the webshot - if (content_details$access_type != "all") { - warning(glue::glue( - "WARNING: unable to take webshot for content ", - "'{content_details$guid}' because authentication is not possible yet. ", - "Set access_type='all' to proceed." - )) - return(content) - } - - # default args - args <- rlang::list2(...) - - if (!"cliprect" %in% names(args)) { - args["cliprect"] <- "viewport" - } - - - rlang::inject(webshot2::webshot( - url = content_details$content_url, - file = imgfile, - !!!args - )) - - set_image_path(content = content, path = imgfile) -} - - #' Set the Vanity URL #' #' Sets the Vanity URL for a piece of content. diff --git a/R/thumbnail.R b/R/thumbnail.R new file mode 100644 index 00000000..2888ae47 --- /dev/null +++ b/R/thumbnail.R @@ -0,0 +1,340 @@ +#' Get content item thumbnail +#' +#' Download the thumbnail for a content item on Connect to a file on your +#' computer. +#' +#' @param content A content item. +#' @param path Optional. A path to a file used to write the thumbnail image. If +#' no path is provided, a temporary file with the correct file extension is +#' created. +#' +#' @returns The path to the downloaded image file, if `content` has a thumbnail; otherwise `NA`. +#' +#' @examples +#' \dontrun{ +#' client <- connect() +#' item <- content_item(client, "8f37d6e0-3395-4a2c-aa6a-d7f2fe1babd0") +#' thumbnail <- get_thumbnail(item) +#' } +#' +#' @family thumbnail functions +#' @family content functions +#' @export +get_thumbnail <- function(content, path = NULL) { + validate_R6_class(content, "Content") + guid <- content$content$guid + con <- content$connect + + # Connect 2024.09.0 introduced public endpoints for content thumbnails. We + # prefer those, falling back to the unversioned endpoints if unavailable. + # The "content/{guid}/__thumbnail__" URL is not under "__api__". + res <- con$GET( + url = con$server_url("content", guid, "__thumbnail__"), + parser = NULL + ) + if (httr::status_code(res) == 404) { + res <- con$GET( + unversioned_url("applications", guid, "image"), + parser = NULL + ) + } + con$raise_error(res) + + if (httr::status_code(res) == 204) { + return(NA_character_) + } + + # Guess file extension + if (is.null(path)) { + path <- tempfile(pattern = glue::glue("content_image_{content$content$guid}_")) + } + ct <- httr::headers(res)$`content-type` + if (ct %in% mime::mimemap) { + exts <- names(mime::mimemap[mime::mimemap == ct]) + # Append the correct extension to the path if it does not match any of the + # MIME type's valid file extensions. + if (!any(sapply(exts, function(x) endsWith(path, x)))) { + path <- paste(path, exts[1], sep = ".") + } + } else { + warning(glue::glue("Could not infer file extension from content type: {ct}.")) + } + + writeBin(httr::content(res, as = "raw"), path) + + return(path) +} + + +#' Delete content item thumbnail +#' +#' Delete the thumbnail from a content item on Connect. +#' +#' @param content A content item. +#' +#' @returns The content item (invisibly). +#' +#' @examples +#' \dontrun{ +#' client <- connect() +#' item <- content_item(client, "8f37d6e0-3395-4a2c-aa6a-d7f2fe1babd0") +#' thumbnail <- get_thumbnail(item) +#' } +#' +#' @family thumbnail functions +#' @family content functions +#' @export +delete_thumbnail <- function(content) { + validate_R6_class(content, "Content") + guid <- content$content$guid + con <- content$connect + + # Connect 2024.09.0 introduced public endpoints for content thumbnails. We + # prefer those, falling back to the unversioned endpoints if unavailable. + res <- con$DELETE( + v1_url("content", guid, "thumbnail"), + parser = NULL + ) + # API error code 17 indicates that the request was successful but the thumbnail does not exist. + # In this case, we don't need to make another request. + # https://docs.posit.co/connect/api/#overview--api-error-codes + if (httr::status_code(res) == 404 && !("code" %in% names(httr::content(res)) && isTRUE(httr::content(res)$code == 17))) { + res <- con$DELETE( + unversioned_url("applications", guid, "image"), + parser = NULL + ) + } + + # API error code 17 indicates that the request was successful but the thumbnail does not exist. + # We do not want to throw an error in this case. + # https://docs.posit.co/connect/api/#overview--api-error-codes + if (httr::status_code(res) == 404 && !("code" %in% names(httr::content(res)) && isTRUE(httr::content(res)$code == 17))) { + con$raise_error(res) + } + + invisible(content) +} + +#' Check content item thumbnail +#' +#' Check whether a content item has a thumbnail. +#' +#' @param content A content item. +#' +#' @returns `TRUE` if the content item has a thumbnail, otherwise `FALSE`. +#' Throws an error if you do not have permission to view the thumbnail. +#' @examples +#' \dontrun{ +#' client <- connect() +#' item <- content_item(client, "8f37d6e0-3395-4a2c-aa6a-d7f2fe1babd0") +#' has_thumbnail(item) +#' } +#' +#' @family thumbnail functions +#' @family content functions +#' @export +has_thumbnail <- function(content) { + validate_R6_class(content, "Content") + guid <- content$content$guid + con <- content$connect + + # Connect 2024.09.0 introduced public endpoints for content thumbnails. We + # prefer those, falling back to the unversioned endpoints if unavailable. + # The "content/{guid}/__thumbnail__" URL is not under "__api__". + res <- con$GET( + url = con$server_url("content", guid, "__thumbnail__"), + parser = NULL + ) + if (httr::status_code(res) == 404) { + res <- con$GET( + unversioned_url("applications", guid, "image"), + parser = NULL + ) + } + con$raise_error(res) + httr::status_code(res) != 204 +} + +#' Set content item thumbnail +#' +#' Set the thumbnail for a content item. +#' +#' @param content A content item. +#' @param path Either a path to a local file or a URL to an image available over +#' HTTP/HTTPS. If `path` is an HTTP or HTTPS URL, the image will first +#' be downloaded. +#' +#' @returns The content item (invisibly). +#' +#' @examples +#' \dontrun{ +#' client <- connect() +#' item <- content_item(client, "8f37d6e0-3395-4a2c-aa6a-d7f2fe1babd0") +#' set_thumbnail(item, "resources/image.png") +#' } +#' +#' @family thumbnail functions +#' @family content functions +#' @export +set_thumbnail <- function(content, path) { + validate_R6_class(content, "Content") + + valid_path <- NULL + if (file.exists(path)) { + valid_path <- path + } else { + parsed <- httr::parse_url(path) + if (!is.null(parsed$scheme) && parsed$scheme %in% c("http", "https")) { + valid_path <- tempfile(pattern = "image", fileext = paste0(".", tools::file_ext(parsed[["path"]]))) + res <- httr::GET(path, httr::write_disk(valid_path)) + on.exit(unlink(valid_path)) + if (httr::http_error(res)) { + stop(glue::glue("Could not download image from {path}: {httr::http_status(res)$message}")) + } + } + } + if (is.null(valid_path)) { + stop(glue::glue("Could not locate image at path: {path}")) + } + + guid <- content$content$guid + con <- content$connect + + # Connect 2024.09.0 introduced public endpoints for content thumbnails. We + # prefer those, falling back to the unversioned endpoints if unavailable. + res <- con$PUT( + path = v1_url("content", guid, "thumbnail"), + body = httr::upload_file(valid_path), + parser = NULL + ) + if (httr::status_code(res) == 404) { + res <- con$POST( + path = unversioned_url("applications", guid, "image"), + body = httr::upload_file(valid_path), + parser = NULL + ) + } + con$raise_error(res) + + # return the input (in case it inherits more than just Content) + invisible(content) +} + + +#' Get the Content Image +#' +#' @description +#' +#' \lifecycle{deprecated} +#' +#' Please use [`get_thumbnail`], +#' [`delete_thumbnail`], and [`has_thumbnail`] instead. +#' +#' `get_image` saves the content image to the given path (default: temp file). +#' `delete_image` removes the image (optionally saving to the given path) +#' `has_image` returns whether the content has an image +#' +#' @param content A content object +#' @param path optional. The path to the image on disk +#' +#' @rdname get_image +#' @family content functions +#' @export +get_image <- function(content, path = NULL) { + lifecycle::deprecate_warn("0.3.1", "get_image()", "get_thumbnail()") + + get_thumbnail(content, path) +} + +#' @rdname get_image +#' @export +delete_image <- function(content, path = NULL) { + lifecycle::deprecate_warn("0.3.1", "delete_image()", "delete_thumbnail()") + + if (!is.null(path)) { + get_thumbnail(content, path) + } + + delete_thumbnail(content) +} + +#' @rdname get_image +#' @export +has_image <- function(content) { + lifecycle::deprecate_warn("0.3.1", "has_image()", "has_thumbnail()") + has_thumbnail(content) +} + + +#' Set the Content Image +#' +#' @description +#' +#' \lifecycle{deprecated} +#' +#' Please use [`set_thumbnail`] instead. +#' +#' Set the Content Image using a variety of methods. +#' +#' @details NOTE: `set_image_webshot()` requires [webshot2::webshot()], but currently +#' skips and warns for any content that requires authentication until the +#' `webshot2` package supports authentication. +#' +#' @param content A content object +#' @param path The path to an image on disk +#' @param url The url for an image +#' @param ... Additional arguments passed on to [webshot2::webshot()] +#' +#' @rdname set_image +#' @family content functions +#' @export +set_image_path <- function(content, path) { + lifecycle::deprecate_warn("0.3.1", "set_image_path()", "set_thumbnail()") + set_thumbnail(content, path) +} + + +#' @rdname set_image +#' @export +set_image_url <- function(content, url) { + lifecycle::deprecate_warn("0.3.1", "set_image_url()", "set_thumbnail()") + set_thumbnail(content, url) +} + + +#' @rdname set_image +#' @export +set_image_webshot <- function(content, ...) { + lifecycle::deprecate_warn("0.3.1", "set_image_webshot()", "set_thumbnail()") + validate_R6_class(content, "Content") + imgfile <- fs::file_temp(pattern = "webshot", ext = ".png") + + rlang::check_installed("webshot2", "to take screenshots of applications") + content_details <- content$get_content_remote() + + # check if it is possible to take the webshot + if (content_details$access_type != "all") { + warning(glue::glue( + "WARNING: unable to take webshot for content ", + "'{content_details$guid}' because authentication is not possible yet. ", + "Set access_type='all' to proceed." + )) + return(content) + } + + # default args + args <- rlang::list2(...) + + if (!"cliprect" %in% names(args)) { + args["cliprect"] <- "viewport" + } + + + rlang::inject(webshot2::webshot( + url = content_details$content_url, + file = imgfile, + !!!args + )) + + set_thumbnail(content = content, path = imgfile) +} diff --git a/README.Rmd b/README.Rmd index bf1eaf7c..9bff44ce 100644 --- a/README.Rmd +++ b/README.Rmd @@ -111,15 +111,15 @@ content <- client %>% # set an image for content content %>% - set_image_path("./my/local/image.png") + set_thumbnail("./my/local/image.png") content %>% - set_image_url("http://url.example.com/image.png") + set_thumbnail("http://url.example.com/image.png") # set image and a vanity URL content %>% - set_image_path("./my/local/image.png") %>% + set_thumbnail("./my/local/image.png") %>% set_vanity_url("/my-awesome-app") # change access_type to "anyone" diff --git a/README.md b/README.md index ac74dd0f..528c703e 100644 --- a/README.md +++ b/README.md @@ -107,15 +107,15 @@ content <- client %>% # set an image for content content %>% - set_image_path("./my/local/image.png") + set_thumbnail("./my/local/image.png") content %>% - set_image_url("http://url.example.com/image.png") + set_thumbnail("http://url.example.com/image.png") # set image and a vanity URL content %>% - set_image_path("./my/local/image.png") %>% + set_thumbnail("./my/local/image.png") %>% set_vanity_url("/my-awesome-app") # change access_type to "anyone" diff --git a/_pkgdown.yml b/_pkgdown.yml index cb452c7e..987ddb10 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -33,6 +33,7 @@ reference: contents: - matches("content") - matches("variant") + - matches("thumbnail") - matches("image") - matches("vanity") - matches("schedule") diff --git a/connectapi.Rproj b/connectapi.Rproj index 270314b8..00d640a9 100644 --- a/connectapi.Rproj +++ b/connectapi.Rproj @@ -1,4 +1,5 @@ Version: 1.0 +ProjectId: ddae6158-feaf-4be6-8303-465640e6e5f8 RestoreWorkspace: Default SaveWorkspace: Default diff --git a/man/PositConnect.Rd b/man/PositConnect.Rd index bb7d5d63..1a45f15e 100644 --- a/man/PositConnect.Rd +++ b/man/PositConnect.Rd @@ -66,6 +66,7 @@ Other R6 classes: \item \href{#method-Connect-raise_error}{\code{Connect$raise_error()}} \item \href{#method-Connect-add_auth}{\code{Connect$add_auth()}} \item \href{#method-Connect-api_url}{\code{Connect$api_url()}} +\item \href{#method-Connect-server_url}{\code{Connect$server_url()}} \item \href{#method-Connect-request}{\code{Connect$request()}} \item \href{#method-Connect-GET}{\code{Connect$GET()}} \item \href{#method-Connect-PUT}{\code{Connect$PUT()}} @@ -219,6 +220,23 @@ Build a URL relative to the API root \if{html}{\out{
}}\preformatted{Connect$api_url(...)}\if{html}{\out{
}} } +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{...}}{path segments} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-Connect-server_url}{}}} +\subsection{Method \code{server_url()}}{ +Build a URL relative to the server root +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{Connect$server_url(...)}\if{html}{\out{
}} +} + \subsection{Arguments}{ \if{html}{\out{
}} \describe{ diff --git a/man/content_delete.Rd b/man/content_delete.Rd index 8431be54..6bf767e5 100644 --- a/man/content_delete.Rd +++ b/man/content_delete.Rd @@ -26,17 +26,21 @@ Other content functions: \code{\link{create_random_name}()}, \code{\link{dashboard_url}()}, \code{\link{dashboard_url_chr}()}, +\code{\link{delete_thumbnail}()}, \code{\link{delete_vanity_url}()}, \code{\link{deploy_repo}()}, \code{\link{get_bundles}()}, \code{\link{get_environment}()}, \code{\link{get_image}()}, \code{\link{get_jobs}()}, +\code{\link{get_thumbnail}()}, \code{\link{get_vanity_url}()}, \code{\link{git}}, +\code{\link{has_thumbnail}()}, \code{\link{permissions}}, \code{\link{set_image_path}()}, \code{\link{set_run_as}()}, +\code{\link{set_thumbnail}()}, \code{\link{set_vanity_url}()}, \code{\link{swap_vanity_url}()}, \code{\link{verify_content_name}()} diff --git a/man/content_item.Rd b/man/content_item.Rd index 41dcd50f..a0d90fcc 100644 --- a/man/content_item.Rd +++ b/man/content_item.Rd @@ -32,17 +32,21 @@ Other content functions: \code{\link{create_random_name}()}, \code{\link{dashboard_url}()}, \code{\link{dashboard_url_chr}()}, +\code{\link{delete_thumbnail}()}, \code{\link{delete_vanity_url}()}, \code{\link{deploy_repo}()}, \code{\link{get_bundles}()}, \code{\link{get_environment}()}, \code{\link{get_image}()}, \code{\link{get_jobs}()}, +\code{\link{get_thumbnail}()}, \code{\link{get_vanity_url}()}, \code{\link{git}}, +\code{\link{has_thumbnail}()}, \code{\link{permissions}}, \code{\link{set_image_path}()}, \code{\link{set_run_as}()}, +\code{\link{set_thumbnail}()}, \code{\link{set_vanity_url}()}, \code{\link{swap_vanity_url}()}, \code{\link{verify_content_name}()} diff --git a/man/content_title.Rd b/man/content_title.Rd index 3b4d2cbd..7b6b83f4 100644 --- a/man/content_title.Rd +++ b/man/content_title.Rd @@ -28,17 +28,21 @@ Other content functions: \code{\link{create_random_name}()}, \code{\link{dashboard_url}()}, \code{\link{dashboard_url_chr}()}, +\code{\link{delete_thumbnail}()}, \code{\link{delete_vanity_url}()}, \code{\link{deploy_repo}()}, \code{\link{get_bundles}()}, \code{\link{get_environment}()}, \code{\link{get_image}()}, \code{\link{get_jobs}()}, +\code{\link{get_thumbnail}()}, \code{\link{get_vanity_url}()}, \code{\link{git}}, +\code{\link{has_thumbnail}()}, \code{\link{permissions}}, \code{\link{set_image_path}()}, \code{\link{set_run_as}()}, +\code{\link{set_thumbnail}()}, \code{\link{set_vanity_url}()}, \code{\link{swap_vanity_url}()}, \code{\link{verify_content_name}()} diff --git a/man/content_update.Rd b/man/content_update.Rd index 8611a525..a0e27136 100644 --- a/man/content_update.Rd +++ b/man/content_update.Rd @@ -48,17 +48,21 @@ Other content functions: \code{\link{create_random_name}()}, \code{\link{dashboard_url}()}, \code{\link{dashboard_url_chr}()}, +\code{\link{delete_thumbnail}()}, \code{\link{delete_vanity_url}()}, \code{\link{deploy_repo}()}, \code{\link{get_bundles}()}, \code{\link{get_environment}()}, \code{\link{get_image}()}, \code{\link{get_jobs}()}, +\code{\link{get_thumbnail}()}, \code{\link{get_vanity_url}()}, \code{\link{git}}, +\code{\link{has_thumbnail}()}, \code{\link{permissions}}, \code{\link{set_image_path}()}, \code{\link{set_run_as}()}, +\code{\link{set_thumbnail}()}, \code{\link{set_vanity_url}()}, \code{\link{swap_vanity_url}()}, \code{\link{verify_content_name}()} diff --git a/man/create_random_name.Rd b/man/create_random_name.Rd index 8572693b..e00dc799 100644 --- a/man/create_random_name.Rd +++ b/man/create_random_name.Rd @@ -25,17 +25,21 @@ Other content functions: \code{\link{content_update}()}, \code{\link{dashboard_url}()}, \code{\link{dashboard_url_chr}()}, +\code{\link{delete_thumbnail}()}, \code{\link{delete_vanity_url}()}, \code{\link{deploy_repo}()}, \code{\link{get_bundles}()}, \code{\link{get_environment}()}, \code{\link{get_image}()}, \code{\link{get_jobs}()}, +\code{\link{get_thumbnail}()}, \code{\link{get_vanity_url}()}, \code{\link{git}}, +\code{\link{has_thumbnail}()}, \code{\link{permissions}}, \code{\link{set_image_path}()}, \code{\link{set_run_as}()}, +\code{\link{set_thumbnail}()}, \code{\link{set_vanity_url}()}, \code{\link{swap_vanity_url}()}, \code{\link{verify_content_name}()} diff --git a/man/dashboard_url.Rd b/man/dashboard_url.Rd index e7e4125d..e3dc08a8 100644 --- a/man/dashboard_url.Rd +++ b/man/dashboard_url.Rd @@ -25,17 +25,21 @@ Other content functions: \code{\link{content_update}()}, \code{\link{create_random_name}()}, \code{\link{dashboard_url_chr}()}, +\code{\link{delete_thumbnail}()}, \code{\link{delete_vanity_url}()}, \code{\link{deploy_repo}()}, \code{\link{get_bundles}()}, \code{\link{get_environment}()}, \code{\link{get_image}()}, \code{\link{get_jobs}()}, +\code{\link{get_thumbnail}()}, \code{\link{get_vanity_url}()}, \code{\link{git}}, +\code{\link{has_thumbnail}()}, \code{\link{permissions}}, \code{\link{set_image_path}()}, \code{\link{set_run_as}()}, +\code{\link{set_thumbnail}()}, \code{\link{set_vanity_url}()}, \code{\link{swap_vanity_url}()}, \code{\link{verify_content_name}()} diff --git a/man/dashboard_url_chr.Rd b/man/dashboard_url_chr.Rd index 350f125d..166a160c 100644 --- a/man/dashboard_url_chr.Rd +++ b/man/dashboard_url_chr.Rd @@ -28,17 +28,21 @@ Other content functions: \code{\link{content_update}()}, \code{\link{create_random_name}()}, \code{\link{dashboard_url}()}, +\code{\link{delete_thumbnail}()}, \code{\link{delete_vanity_url}()}, \code{\link{deploy_repo}()}, \code{\link{get_bundles}()}, \code{\link{get_environment}()}, \code{\link{get_image}()}, \code{\link{get_jobs}()}, +\code{\link{get_thumbnail}()}, \code{\link{get_vanity_url}()}, \code{\link{git}}, +\code{\link{has_thumbnail}()}, \code{\link{permissions}}, \code{\link{set_image_path}()}, \code{\link{set_run_as}()}, +\code{\link{set_thumbnail}()}, \code{\link{set_vanity_url}()}, \code{\link{swap_vanity_url}()}, \code{\link{verify_content_name}()} diff --git a/man/delete_thumbnail.Rd b/man/delete_thumbnail.Rd new file mode 100644 index 00000000..4cfbd83f --- /dev/null +++ b/man/delete_thumbnail.Rd @@ -0,0 +1,59 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/thumbnail.R +\name{delete_thumbnail} +\alias{delete_thumbnail} +\title{Delete content item thumbnail} +\usage{ +delete_thumbnail(content) +} +\arguments{ +\item{content}{A content item.} +} +\value{ +The content item (invisibly). +} +\description{ +Delete the thumbnail from a content item on Connect. +} +\examples{ +\dontrun{ +client <- connect() +item <- content_item(client, "8f37d6e0-3395-4a2c-aa6a-d7f2fe1babd0") +thumbnail <- get_thumbnail(item) +} + +} +\seealso{ +Other thumbnail functions: +\code{\link{get_thumbnail}()}, +\code{\link{has_thumbnail}()}, +\code{\link{set_thumbnail}()} + +Other content functions: +\code{\link{content_delete}()}, +\code{\link{content_item}()}, +\code{\link{content_title}()}, +\code{\link{content_update}()}, +\code{\link{create_random_name}()}, +\code{\link{dashboard_url}()}, +\code{\link{dashboard_url_chr}()}, +\code{\link{delete_vanity_url}()}, +\code{\link{deploy_repo}()}, +\code{\link{get_bundles}()}, +\code{\link{get_environment}()}, +\code{\link{get_image}()}, +\code{\link{get_jobs}()}, +\code{\link{get_thumbnail}()}, +\code{\link{get_vanity_url}()}, +\code{\link{git}}, +\code{\link{has_thumbnail}()}, +\code{\link{permissions}}, +\code{\link{set_image_path}()}, +\code{\link{set_run_as}()}, +\code{\link{set_thumbnail}()}, +\code{\link{set_vanity_url}()}, +\code{\link{swap_vanity_url}()}, +\code{\link{verify_content_name}()} +} +\concept{content functions} +\concept{thumbnail functions} diff --git a/man/delete_vanity_url.Rd b/man/delete_vanity_url.Rd index b0347f1e..64dc15b3 100644 --- a/man/delete_vanity_url.Rd +++ b/man/delete_vanity_url.Rd @@ -21,16 +21,20 @@ Other content functions: \code{\link{create_random_name}()}, \code{\link{dashboard_url}()}, \code{\link{dashboard_url_chr}()}, +\code{\link{delete_thumbnail}()}, \code{\link{deploy_repo}()}, \code{\link{get_bundles}()}, \code{\link{get_environment}()}, \code{\link{get_image}()}, \code{\link{get_jobs}()}, +\code{\link{get_thumbnail}()}, \code{\link{get_vanity_url}()}, \code{\link{git}}, +\code{\link{has_thumbnail}()}, \code{\link{permissions}}, \code{\link{set_image_path}()}, \code{\link{set_run_as}()}, +\code{\link{set_thumbnail}()}, \code{\link{set_vanity_url}()}, \code{\link{swap_vanity_url}()}, \code{\link{verify_content_name}()} diff --git a/man/deploy_repo.Rd b/man/deploy_repo.Rd index e6718de5..be84c855 100644 --- a/man/deploy_repo.Rd +++ b/man/deploy_repo.Rd @@ -63,16 +63,20 @@ Other content functions: \code{\link{create_random_name}()}, \code{\link{dashboard_url}()}, \code{\link{dashboard_url_chr}()}, +\code{\link{delete_thumbnail}()}, \code{\link{delete_vanity_url}()}, \code{\link{get_bundles}()}, \code{\link{get_environment}()}, \code{\link{get_image}()}, \code{\link{get_jobs}()}, +\code{\link{get_thumbnail}()}, \code{\link{get_vanity_url}()}, \code{\link{git}}, +\code{\link{has_thumbnail}()}, \code{\link{permissions}}, \code{\link{set_image_path}()}, \code{\link{set_run_as}()}, +\code{\link{set_thumbnail}()}, \code{\link{set_vanity_url}()}, \code{\link{swap_vanity_url}()}, \code{\link{verify_content_name}()} diff --git a/man/environment.Rd b/man/environment.Rd index 0b74d1d8..944b2455 100644 --- a/man/environment.Rd +++ b/man/environment.Rd @@ -46,16 +46,20 @@ Other content functions: \code{\link{create_random_name}()}, \code{\link{dashboard_url}()}, \code{\link{dashboard_url_chr}()}, +\code{\link{delete_thumbnail}()}, \code{\link{delete_vanity_url}()}, \code{\link{deploy_repo}()}, \code{\link{get_bundles}()}, \code{\link{get_image}()}, \code{\link{get_jobs}()}, +\code{\link{get_thumbnail}()}, \code{\link{get_vanity_url}()}, \code{\link{git}}, +\code{\link{has_thumbnail}()}, \code{\link{permissions}}, \code{\link{set_image_path}()}, \code{\link{set_run_as}()}, +\code{\link{set_thumbnail}()}, \code{\link{set_vanity_url}()}, \code{\link{swap_vanity_url}()}, \code{\link{verify_content_name}()} diff --git a/man/get_bundles.Rd b/man/get_bundles.Rd index 8a1ea282..e59af114 100644 --- a/man/get_bundles.Rd +++ b/man/get_bundles.Rd @@ -26,16 +26,20 @@ Other content functions: \code{\link{create_random_name}()}, \code{\link{dashboard_url}()}, \code{\link{dashboard_url_chr}()}, +\code{\link{delete_thumbnail}()}, \code{\link{delete_vanity_url}()}, \code{\link{deploy_repo}()}, \code{\link{get_environment}()}, \code{\link{get_image}()}, \code{\link{get_jobs}()}, +\code{\link{get_thumbnail}()}, \code{\link{get_vanity_url}()}, \code{\link{git}}, +\code{\link{has_thumbnail}()}, \code{\link{permissions}}, \code{\link{set_image_path}()}, \code{\link{set_run_as}()}, +\code{\link{set_thumbnail}()}, \code{\link{set_vanity_url}()}, \code{\link{swap_vanity_url}()}, \code{\link{verify_content_name}()} @@ -48,16 +52,20 @@ Other content functions: \code{\link{create_random_name}()}, \code{\link{dashboard_url}()}, \code{\link{dashboard_url_chr}()}, +\code{\link{delete_thumbnail}()}, \code{\link{delete_vanity_url}()}, \code{\link{deploy_repo}()}, \code{\link{get_environment}()}, \code{\link{get_image}()}, \code{\link{get_jobs}()}, +\code{\link{get_thumbnail}()}, \code{\link{get_vanity_url}()}, \code{\link{git}}, +\code{\link{has_thumbnail}()}, \code{\link{permissions}}, \code{\link{set_image_path}()}, \code{\link{set_run_as}()}, +\code{\link{set_thumbnail}()}, \code{\link{set_vanity_url}()}, \code{\link{swap_vanity_url}()}, \code{\link{verify_content_name}()} diff --git a/man/get_image.Rd b/man/get_image.Rd index 75001ebd..d3039e45 100644 --- a/man/get_image.Rd +++ b/man/get_image.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/deploy.R +% Please edit documentation in R/thumbnail.R \name{get_image} \alias{get_image} \alias{delete_image} @@ -18,7 +18,11 @@ has_image(content) \item{path}{optional. The path to the image on disk} } \description{ -\lifecycle{experimental} +\lifecycle{deprecated} + +Please use \code{\link{get_thumbnail}}, +\code{\link{delete_thumbnail}}, and \code{\link{has_thumbnail}} instead. + \code{get_image} saves the content image to the given path (default: temp file). \code{delete_image} removes the image (optionally saving to the given path) \code{has_image} returns whether the content has an image @@ -32,16 +36,20 @@ Other content functions: \code{\link{create_random_name}()}, \code{\link{dashboard_url}()}, \code{\link{dashboard_url_chr}()}, +\code{\link{delete_thumbnail}()}, \code{\link{delete_vanity_url}()}, \code{\link{deploy_repo}()}, \code{\link{get_bundles}()}, \code{\link{get_environment}()}, \code{\link{get_jobs}()}, +\code{\link{get_thumbnail}()}, \code{\link{get_vanity_url}()}, \code{\link{git}}, +\code{\link{has_thumbnail}()}, \code{\link{permissions}}, \code{\link{set_image_path}()}, \code{\link{set_run_as}()}, +\code{\link{set_thumbnail}()}, \code{\link{set_vanity_url}()}, \code{\link{swap_vanity_url}()}, \code{\link{verify_content_name}()} diff --git a/man/get_thumbnail.Rd b/man/get_thumbnail.Rd new file mode 100644 index 00000000..80ec48e3 --- /dev/null +++ b/man/get_thumbnail.Rd @@ -0,0 +1,64 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/thumbnail.R +\name{get_thumbnail} +\alias{get_thumbnail} +\title{Get content item thumbnail} +\usage{ +get_thumbnail(content, path = NULL) +} +\arguments{ +\item{content}{A content item.} + +\item{path}{Optional. A path to a file used to write the thumbnail image. If +no path is provided, a temporary file with the correct file extension is +created.} +} +\value{ +The path to the downloaded image file, if \code{content} has a thumbnail; otherwise \code{NA}. +} +\description{ +Download the thumbnail for a content item on Connect to a file on your +computer. +} +\examples{ +\dontrun{ +client <- connect() +item <- content_item(client, "8f37d6e0-3395-4a2c-aa6a-d7f2fe1babd0") +thumbnail <- get_thumbnail(item) +} + +} +\seealso{ +Other thumbnail functions: +\code{\link{delete_thumbnail}()}, +\code{\link{has_thumbnail}()}, +\code{\link{set_thumbnail}()} + +Other content functions: +\code{\link{content_delete}()}, +\code{\link{content_item}()}, +\code{\link{content_title}()}, +\code{\link{content_update}()}, +\code{\link{create_random_name}()}, +\code{\link{dashboard_url}()}, +\code{\link{dashboard_url_chr}()}, +\code{\link{delete_thumbnail}()}, +\code{\link{delete_vanity_url}()}, +\code{\link{deploy_repo}()}, +\code{\link{get_bundles}()}, +\code{\link{get_environment}()}, +\code{\link{get_image}()}, +\code{\link{get_jobs}()}, +\code{\link{get_vanity_url}()}, +\code{\link{git}}, +\code{\link{has_thumbnail}()}, +\code{\link{permissions}}, +\code{\link{set_image_path}()}, +\code{\link{set_run_as}()}, +\code{\link{set_thumbnail}()}, +\code{\link{set_vanity_url}()}, +\code{\link{swap_vanity_url}()}, +\code{\link{verify_content_name}()} +} +\concept{content functions} +\concept{thumbnail functions} diff --git a/man/get_vanity_url.Rd b/man/get_vanity_url.Rd index 3c601e04..b90dcbf9 100644 --- a/man/get_vanity_url.Rd +++ b/man/get_vanity_url.Rd @@ -24,16 +24,20 @@ Other content functions: \code{\link{create_random_name}()}, \code{\link{dashboard_url}()}, \code{\link{dashboard_url_chr}()}, +\code{\link{delete_thumbnail}()}, \code{\link{delete_vanity_url}()}, \code{\link{deploy_repo}()}, \code{\link{get_bundles}()}, \code{\link{get_environment}()}, \code{\link{get_image}()}, \code{\link{get_jobs}()}, +\code{\link{get_thumbnail}()}, \code{\link{git}}, +\code{\link{has_thumbnail}()}, \code{\link{permissions}}, \code{\link{set_image_path}()}, \code{\link{set_run_as}()}, +\code{\link{set_thumbnail}()}, \code{\link{set_vanity_url}()}, \code{\link{swap_vanity_url}()}, \code{\link{verify_content_name}()} diff --git a/man/git.Rd b/man/git.Rd index 08ab0c44..fd4f3ef9 100644 --- a/man/git.Rd +++ b/man/git.Rd @@ -47,16 +47,20 @@ Other content functions: \code{\link{create_random_name}()}, \code{\link{dashboard_url}()}, \code{\link{dashboard_url_chr}()}, +\code{\link{delete_thumbnail}()}, \code{\link{delete_vanity_url}()}, \code{\link{deploy_repo}()}, \code{\link{get_bundles}()}, \code{\link{get_environment}()}, \code{\link{get_image}()}, \code{\link{get_jobs}()}, +\code{\link{get_thumbnail}()}, \code{\link{get_vanity_url}()}, +\code{\link{has_thumbnail}()}, \code{\link{permissions}}, \code{\link{set_image_path}()}, \code{\link{set_run_as}()}, +\code{\link{set_thumbnail}()}, \code{\link{set_vanity_url}()}, \code{\link{swap_vanity_url}()}, \code{\link{verify_content_name}()} diff --git a/man/has_thumbnail.Rd b/man/has_thumbnail.Rd new file mode 100644 index 00000000..69656905 --- /dev/null +++ b/man/has_thumbnail.Rd @@ -0,0 +1,60 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/thumbnail.R +\name{has_thumbnail} +\alias{has_thumbnail} +\title{Check content item thumbnail} +\usage{ +has_thumbnail(content) +} +\arguments{ +\item{content}{A content item.} +} +\value{ +\code{TRUE} if the content item has a thumbnail, otherwise \code{FALSE}. +Throws an error if you do not have permission to view the thumbnail. +} +\description{ +Check whether a content item has a thumbnail. +} +\examples{ +\dontrun{ +client <- connect() +item <- content_item(client, "8f37d6e0-3395-4a2c-aa6a-d7f2fe1babd0") +has_thumbnail(item) +} + +} +\seealso{ +Other thumbnail functions: +\code{\link{delete_thumbnail}()}, +\code{\link{get_thumbnail}()}, +\code{\link{set_thumbnail}()} + +Other content functions: +\code{\link{content_delete}()}, +\code{\link{content_item}()}, +\code{\link{content_title}()}, +\code{\link{content_update}()}, +\code{\link{create_random_name}()}, +\code{\link{dashboard_url}()}, +\code{\link{dashboard_url_chr}()}, +\code{\link{delete_thumbnail}()}, +\code{\link{delete_vanity_url}()}, +\code{\link{deploy_repo}()}, +\code{\link{get_bundles}()}, +\code{\link{get_environment}()}, +\code{\link{get_image}()}, +\code{\link{get_jobs}()}, +\code{\link{get_thumbnail}()}, +\code{\link{get_vanity_url}()}, +\code{\link{git}}, +\code{\link{permissions}}, +\code{\link{set_image_path}()}, +\code{\link{set_run_as}()}, +\code{\link{set_thumbnail}()}, +\code{\link{set_vanity_url}()}, +\code{\link{swap_vanity_url}()}, +\code{\link{verify_content_name}()} +} +\concept{content functions} +\concept{thumbnail functions} diff --git a/man/jobs.Rd b/man/jobs.Rd index 4de6bfd5..4ebb580b 100644 --- a/man/jobs.Rd +++ b/man/jobs.Rd @@ -27,16 +27,20 @@ Other content functions: \code{\link{create_random_name}()}, \code{\link{dashboard_url}()}, \code{\link{dashboard_url_chr}()}, +\code{\link{delete_thumbnail}()}, \code{\link{delete_vanity_url}()}, \code{\link{deploy_repo}()}, \code{\link{get_bundles}()}, \code{\link{get_environment}()}, \code{\link{get_image}()}, +\code{\link{get_thumbnail}()}, \code{\link{get_vanity_url}()}, \code{\link{git}}, +\code{\link{has_thumbnail}()}, \code{\link{permissions}}, \code{\link{set_image_path}()}, \code{\link{set_run_as}()}, +\code{\link{set_thumbnail}()}, \code{\link{set_vanity_url}()}, \code{\link{swap_vanity_url}()}, \code{\link{verify_content_name}()} diff --git a/man/permissions.Rd b/man/permissions.Rd index 7c40964a..05835eda 100644 --- a/man/permissions.Rd +++ b/man/permissions.Rd @@ -71,16 +71,20 @@ Other content functions: \code{\link{create_random_name}()}, \code{\link{dashboard_url}()}, \code{\link{dashboard_url_chr}()}, +\code{\link{delete_thumbnail}()}, \code{\link{delete_vanity_url}()}, \code{\link{deploy_repo}()}, \code{\link{get_bundles}()}, \code{\link{get_environment}()}, \code{\link{get_image}()}, \code{\link{get_jobs}()}, +\code{\link{get_thumbnail}()}, \code{\link{get_vanity_url}()}, \code{\link{git}}, +\code{\link{has_thumbnail}()}, \code{\link{set_image_path}()}, \code{\link{set_run_as}()}, +\code{\link{set_thumbnail}()}, \code{\link{set_vanity_url}()}, \code{\link{swap_vanity_url}()}, \code{\link{verify_content_name}()} diff --git a/man/set_image.Rd b/man/set_image.Rd index fa72993f..e0150f21 100644 --- a/man/set_image.Rd +++ b/man/set_image.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/deploy.R +% Please edit documentation in R/thumbnail.R \name{set_image_path} \alias{set_image_path} \alias{set_image_url} @@ -22,11 +22,13 @@ set_image_webshot(content, ...) \item{...}{Additional arguments passed on to \code{\link[webshot2:webshot]{webshot2::webshot()}}} } \description{ -\lifecycle{experimental} +\lifecycle{deprecated} + +Please use \code{\link{set_thumbnail}} instead. + +Set the Content Image using a variety of methods. } \details{ -Set the Content Image using a variety of methods. - NOTE: \code{set_image_webshot()} requires \code{\link[webshot2:webshot]{webshot2::webshot()}}, but currently skips and warns for any content that requires authentication until the \code{webshot2} package supports authentication. @@ -40,16 +42,20 @@ Other content functions: \code{\link{create_random_name}()}, \code{\link{dashboard_url}()}, \code{\link{dashboard_url_chr}()}, +\code{\link{delete_thumbnail}()}, \code{\link{delete_vanity_url}()}, \code{\link{deploy_repo}()}, \code{\link{get_bundles}()}, \code{\link{get_environment}()}, \code{\link{get_image}()}, \code{\link{get_jobs}()}, +\code{\link{get_thumbnail}()}, \code{\link{get_vanity_url}()}, \code{\link{git}}, +\code{\link{has_thumbnail}()}, \code{\link{permissions}}, \code{\link{set_run_as}()}, +\code{\link{set_thumbnail}()}, \code{\link{set_vanity_url}()}, \code{\link{swap_vanity_url}()}, \code{\link{verify_content_name}()} diff --git a/man/set_run_as.Rd b/man/set_run_as.Rd index 060c584e..772594a1 100644 --- a/man/set_run_as.Rd +++ b/man/set_run_as.Rd @@ -44,16 +44,20 @@ Other content functions: \code{\link{create_random_name}()}, \code{\link{dashboard_url}()}, \code{\link{dashboard_url_chr}()}, +\code{\link{delete_thumbnail}()}, \code{\link{delete_vanity_url}()}, \code{\link{deploy_repo}()}, \code{\link{get_bundles}()}, \code{\link{get_environment}()}, \code{\link{get_image}()}, \code{\link{get_jobs}()}, +\code{\link{get_thumbnail}()}, \code{\link{get_vanity_url}()}, \code{\link{git}}, +\code{\link{has_thumbnail}()}, \code{\link{permissions}}, \code{\link{set_image_path}()}, +\code{\link{set_thumbnail}()}, \code{\link{set_vanity_url}()}, \code{\link{swap_vanity_url}()}, \code{\link{verify_content_name}()} diff --git a/man/set_thumbnail.Rd b/man/set_thumbnail.Rd new file mode 100644 index 00000000..0d3caf60 --- /dev/null +++ b/man/set_thumbnail.Rd @@ -0,0 +1,63 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/thumbnail.R +\name{set_thumbnail} +\alias{set_thumbnail} +\title{Set content item thumbnail} +\usage{ +set_thumbnail(content, path) +} +\arguments{ +\item{content}{A content item.} + +\item{path}{Either a path to a local file or a URL to an image available over +HTTP/HTTPS. If \code{path} is an HTTP or HTTPS URL, the image will first +be downloaded.} +} +\value{ +The content item (invisibly). +} +\description{ +Set the thumbnail for a content item. +} +\examples{ +\dontrun{ +client <- connect() +item <- content_item(client, "8f37d6e0-3395-4a2c-aa6a-d7f2fe1babd0") +set_thumbnail(item, "resources/image.png") +} + +} +\seealso{ +Other thumbnail functions: +\code{\link{delete_thumbnail}()}, +\code{\link{get_thumbnail}()}, +\code{\link{has_thumbnail}()} + +Other content functions: +\code{\link{content_delete}()}, +\code{\link{content_item}()}, +\code{\link{content_title}()}, +\code{\link{content_update}()}, +\code{\link{create_random_name}()}, +\code{\link{dashboard_url}()}, +\code{\link{dashboard_url_chr}()}, +\code{\link{delete_thumbnail}()}, +\code{\link{delete_vanity_url}()}, +\code{\link{deploy_repo}()}, +\code{\link{get_bundles}()}, +\code{\link{get_environment}()}, +\code{\link{get_image}()}, +\code{\link{get_jobs}()}, +\code{\link{get_thumbnail}()}, +\code{\link{get_vanity_url}()}, +\code{\link{git}}, +\code{\link{has_thumbnail}()}, +\code{\link{permissions}}, +\code{\link{set_image_path}()}, +\code{\link{set_run_as}()}, +\code{\link{set_vanity_url}()}, +\code{\link{swap_vanity_url}()}, +\code{\link{verify_content_name}()} +} +\concept{content functions} +\concept{thumbnail functions} diff --git a/man/set_vanity_url.Rd b/man/set_vanity_url.Rd index 41d95427..85428805 100644 --- a/man/set_vanity_url.Rd +++ b/man/set_vanity_url.Rd @@ -37,17 +37,21 @@ Other content functions: \code{\link{create_random_name}()}, \code{\link{dashboard_url}()}, \code{\link{dashboard_url_chr}()}, +\code{\link{delete_thumbnail}()}, \code{\link{delete_vanity_url}()}, \code{\link{deploy_repo}()}, \code{\link{get_bundles}()}, \code{\link{get_environment}()}, \code{\link{get_image}()}, \code{\link{get_jobs}()}, +\code{\link{get_thumbnail}()}, \code{\link{get_vanity_url}()}, \code{\link{git}}, +\code{\link{has_thumbnail}()}, \code{\link{permissions}}, \code{\link{set_image_path}()}, \code{\link{set_run_as}()}, +\code{\link{set_thumbnail}()}, \code{\link{swap_vanity_url}()}, \code{\link{verify_content_name}()} } diff --git a/man/swap_vanity_url.Rd b/man/swap_vanity_url.Rd index 69126ae0..36de9bf0 100644 --- a/man/swap_vanity_url.Rd +++ b/man/swap_vanity_url.Rd @@ -23,17 +23,21 @@ Other content functions: \code{\link{create_random_name}()}, \code{\link{dashboard_url}()}, \code{\link{dashboard_url_chr}()}, +\code{\link{delete_thumbnail}()}, \code{\link{delete_vanity_url}()}, \code{\link{deploy_repo}()}, \code{\link{get_bundles}()}, \code{\link{get_environment}()}, \code{\link{get_image}()}, \code{\link{get_jobs}()}, +\code{\link{get_thumbnail}()}, \code{\link{get_vanity_url}()}, \code{\link{git}}, +\code{\link{has_thumbnail}()}, \code{\link{permissions}}, \code{\link{set_image_path}()}, \code{\link{set_run_as}()}, +\code{\link{set_thumbnail}()}, \code{\link{set_vanity_url}()}, \code{\link{verify_content_name}()} } diff --git a/man/verify_content_name.Rd b/man/verify_content_name.Rd index 7219bee7..03abe180 100644 --- a/man/verify_content_name.Rd +++ b/man/verify_content_name.Rd @@ -29,17 +29,21 @@ Other content functions: \code{\link{create_random_name}()}, \code{\link{dashboard_url}()}, \code{\link{dashboard_url_chr}()}, +\code{\link{delete_thumbnail}()}, \code{\link{delete_vanity_url}()}, \code{\link{deploy_repo}()}, \code{\link{get_bundles}()}, \code{\link{get_environment}()}, \code{\link{get_image}()}, \code{\link{get_jobs}()}, +\code{\link{get_thumbnail}()}, \code{\link{get_vanity_url}()}, \code{\link{git}}, +\code{\link{has_thumbnail}()}, \code{\link{permissions}}, \code{\link{set_image_path}()}, \code{\link{set_run_as}()}, +\code{\link{set_thumbnail}()}, \code{\link{set_vanity_url}()}, \code{\link{swap_vanity_url}()} } diff --git a/tests/integrated/test-deploy.R b/tests/integrated/test-deploy.R index 029c6ea8..459fe3b7 100644 --- a/tests/integrated/test-deploy.R +++ b/tests/integrated/test-deploy.R @@ -247,6 +247,10 @@ test_that("get_image returns NA if no image", { test_that("set_image_url works", { scoped_experimental_silence() + # This test fails with the 1.8.8.2 image. The failure is to do with + # downloading the favicon, used in the test as the remote image. + skip_if_connect_older_than(cont1_content$connect, "2021.09.0") + res <- set_image_url(cont1_content, glue::glue("{cont1_content$get_connect()$server}/connect/__favicon__")) expect_true(validate_R6_class(res, "Content")) @@ -444,3 +448,86 @@ test_that("deployment timestamps respect timezone", { # (really protecting against being off by hours b/c of timezone differences) expect_lt(Sys.time() - all_usage$time, lubridate::make_difftime(60, "seconds")) }) + +# thumbnail --------------------------------------------------- + +test_that("set_thumbnail works with local images", { + scoped_experimental_silence() + img_path <- rprojroot::find_package_root_file("tests/testthat/examples/logo.png") + + res <- set_thumbnail(cont1_content, img_path) + + expect_true(validate_R6_class(res, "Content")) +}) + +test_that("get_thumbnail works", { + scoped_experimental_silence() + img_path <- rprojroot::find_package_root_file("tests/testthat/examples/logo.png") + + tmp_img <- fs::file_temp(pattern = "img", ext = ".png") + get_thumbnail(cont1_content, tmp_img) + + expect_identical( + readBin(img_path, "raw"), + readBin(tmp_img, "raw") + ) + + # works again (i.e. does not append data) + get_thumbnail(cont1_content, tmp_img) + expect_identical( + readBin(img_path, "raw"), + readBin(tmp_img, "raw") + ) + + # works with no path + auto_path <- get_thumbnail(cont1_content) + expect_identical( + readBin(img_path, "raw"), + readBin(auto_path, "raw") + ) + expect_identical(fs::path_ext(auto_path), "png") +}) + +test_that("has_thumbnail works with an image", { + scoped_experimental_silence() + + expect_true(has_thumbnail(cont1_content)) +}) + +test_that("delete_thumbnail works", { + scoped_experimental_silence() + + expect_true(validate_R6_class(delete_thumbnail(cont1_content), "Content")) + expect_false(has_thumbnail(cont1_content)) + + # works again - i.e. if no image available + expect_true(validate_R6_class(delete_thumbnail(cont1_content), "Content")) +}) + +test_that("has_thumbnail works with no image", { + scoped_experimental_silence() + + expect_false(has_thumbnail(cont1_content)) +}) + +test_that("get_thumbnail returns NA if no image", { + scoped_experimental_silence() + + tmp_img <- fs::file_temp(pattern = "img", ext = ".png") + response <- get_thumbnail(cont1_content, tmp_img) + + expect_false(identical(tmp_img, response)) + expect_true(is.na(response)) +}) + +test_that("set_thumbnail works with remote paths", { + scoped_experimental_silence() + + # This test fails with the 1.8.8.2 image. The failure is to do with + # downloading the favicon, used in the test as the remote image. + skip_if_connect_older_than(cont1_content$connect, "2021.09.0") + + res <- set_thumbnail(cont1_content, glue::glue("{cont1_content$get_connect()$server}/connect/__favicon__")) + + expect_true(validate_R6_class(res, "Content")) +}) diff --git a/tests/testthat/2024.08.0/__api__/applications/01234567/image-DELETE.204 b/tests/testthat/2024.08.0/__api__/applications/01234567/image-DELETE.204 new file mode 100644 index 00000000..e69de29b diff --git a/tests/testthat/2024.08.0/__api__/applications/01234567/image-POST.204 b/tests/testthat/2024.08.0/__api__/applications/01234567/image-POST.204 new file mode 100644 index 00000000..e69de29b diff --git a/tests/testthat/2024.08.0/__api__/applications/01234567/image.R b/tests/testthat/2024.08.0/__api__/applications/01234567/image.R new file mode 100644 index 00000000..c6ddab3c --- /dev/null +++ b/tests/testthat/2024.08.0/__api__/applications/01234567/image.R @@ -0,0 +1,12 @@ +structure( + list( + url = "__api__/applications/01234567/image", status_code = 200L, + headers = structure(list( + `content-type` = "image/jpeg" + )), content = as.raw(c( + 0x4e, + 0x41 + )) + ), + class = "response" +) diff --git a/tests/testthat/2024.08.0/__api__/applications/12345678/image.204 b/tests/testthat/2024.08.0/__api__/applications/12345678/image.204 new file mode 100644 index 00000000..e69de29b diff --git a/tests/testthat/2024.08.0/__api__/applications/23456789/image-DELETE.R b/tests/testthat/2024.08.0/__api__/applications/23456789/image-DELETE.R new file mode 100644 index 00000000..ce1c8150 --- /dev/null +++ b/tests/testthat/2024.08.0/__api__/applications/23456789/image-DELETE.R @@ -0,0 +1,8 @@ +structure( + list( + url = "__api__/applications/23456789/image", + status_code = 404L, + content = list(code = 4, error = "The requested object does not exist.", payload = NULL) + ), + class = "response" +) diff --git a/tests/testthat/2024.08.0/__api__/applications/23456789/image-POST.R b/tests/testthat/2024.08.0/__api__/applications/23456789/image-POST.R new file mode 100644 index 00000000..ce28cff8 --- /dev/null +++ b/tests/testthat/2024.08.0/__api__/applications/23456789/image-POST.R @@ -0,0 +1,5 @@ +structure( + list(url = "__api__/applications/23456789/image", status_code = 404L), + content = charToRaw("404 page not found"), + class = "response" +) diff --git a/tests/testthat/2024.08.0/__api__/applications/23456789/image.R b/tests/testthat/2024.08.0/__api__/applications/23456789/image.R new file mode 100644 index 00000000..ce28cff8 --- /dev/null +++ b/tests/testthat/2024.08.0/__api__/applications/23456789/image.R @@ -0,0 +1,5 @@ +structure( + list(url = "__api__/applications/23456789/image", status_code = 404L), + content = charToRaw("404 page not found"), + class = "response" +) diff --git a/tests/testthat/2024.08.0/__api__/applications/34567890/image-DELETE.R b/tests/testthat/2024.08.0/__api__/applications/34567890/image-DELETE.R new file mode 100644 index 00000000..704664a8 --- /dev/null +++ b/tests/testthat/2024.08.0/__api__/applications/34567890/image-DELETE.R @@ -0,0 +1,8 @@ +structure( + list( + url = "__api__/v1/applications/34567890/thumbnail", + status_code = 404L, + content = list(code = 17, error = "The requested item could not be removed because it does not exist.", payload = NULL) + ), + class = "response" +) diff --git a/tests/testthat/__api__/applications/951bf3ad/variants.json b/tests/testthat/2024.08.0/__api__/applications/951bf3ad/variants.json similarity index 100% rename from tests/testthat/__api__/applications/951bf3ad/variants.json rename to tests/testthat/2024.08.0/__api__/applications/951bf3ad/variants.json diff --git a/tests/testthat/__api__/applications/f2f37341/variants.json b/tests/testthat/2024.08.0/__api__/applications/f2f37341/variants.json similarity index 100% rename from tests/testthat/__api__/applications/f2f37341/variants.json rename to tests/testthat/2024.08.0/__api__/applications/f2f37341/variants.json diff --git a/tests/testthat/__api__/server_settings.json b/tests/testthat/2024.08.0/__api__/server_settings.json similarity index 100% rename from tests/testthat/__api__/server_settings.json rename to tests/testthat/2024.08.0/__api__/server_settings.json diff --git a/tests/testthat/__api__/v1/content-064d19.json b/tests/testthat/2024.08.0/__api__/v1/content-064d19.json similarity index 100% rename from tests/testthat/__api__/v1/content-064d19.json rename to tests/testthat/2024.08.0/__api__/v1/content-064d19.json diff --git a/tests/testthat/2024.08.0/__api__/v1/content/01234567.json b/tests/testthat/2024.08.0/__api__/v1/content/01234567.json new file mode 100644 index 00000000..607b9fb3 --- /dev/null +++ b/tests/testthat/2024.08.0/__api__/v1/content/01234567.json @@ -0,0 +1,47 @@ +{ + "guid": "01234567", + "name": "shinyapp-2024-08-22", + "title": "shinyapp-2024-08-22", + "description": "", + "access_type": "acl", + "locked": false, + "locked_message": "", + "connection_timeout": null, + "read_timeout": null, + "init_timeout": null, + "idle_timeout": null, + "max_processes": null, + "min_processes": null, + "max_conns_per_process": null, + "load_factor": null, + "memory_request": null, + "memory_limit": null, + "cpu_request": null, + "cpu_limit": null, + "amd_gpu_limit": null, + "nvidia_gpu_limit": null, + "service_account_name": null, + "default_image_name": null, + "created_time": "2024-08-22T15:44:48Z", + "last_deployed_time": "2024-08-22T15:44:49Z", + "bundle_id": "142621", + "app_mode": "shiny", + "content_category": "", + "parameterized": false, + "cluster_name": "Local", + "image_name": null, + "r_version": "4.4.0", + "py_version": null, + "quarto_version": null, + "r_environment_management": true, + "default_r_environment_management": null, + "py_environment_management": null, + "default_py_environment_management": null, + "run_as": null, + "run_as_current_user": false, + "owner_guid": "fe07bf64", + "content_url": "https://connect.example/content/01234567/", + "dashboard_url": "https://connect.example/connect/#/apps/01234567", + "app_role": "owner", + "id": "56746" +} diff --git a/tests/testthat/2024.08.0/__api__/v1/content/01234567/thumbnail-DELETE.R b/tests/testthat/2024.08.0/__api__/v1/content/01234567/thumbnail-DELETE.R new file mode 100644 index 00000000..30df65ed --- /dev/null +++ b/tests/testthat/2024.08.0/__api__/v1/content/01234567/thumbnail-DELETE.R @@ -0,0 +1,7 @@ +structure( + list( + url = "__api__/v1/applications/01234567/thumbnail", + status_code = 404L, content = charToRaw("404 page not found") + ), + class = "response" +) diff --git a/tests/testthat/2024.08.0/__api__/v1/content/01234567/thumbnail-PUT.R b/tests/testthat/2024.08.0/__api__/v1/content/01234567/thumbnail-PUT.R new file mode 100644 index 00000000..a19fb69b --- /dev/null +++ b/tests/testthat/2024.08.0/__api__/v1/content/01234567/thumbnail-PUT.R @@ -0,0 +1,7 @@ +structure( + list( + url = "__api__/v1/content/01234567/thumbnail", + status_code = 404L, content = charToRaw("404 page not found") + ), + class = "response" +) diff --git a/tests/testthat/2024.08.0/__api__/v1/content/12345678.json b/tests/testthat/2024.08.0/__api__/v1/content/12345678.json new file mode 100644 index 00000000..1cc306fd --- /dev/null +++ b/tests/testthat/2024.08.0/__api__/v1/content/12345678.json @@ -0,0 +1,47 @@ +{ + "guid": "12345678", + "name": "fake-app-2000", + "title": "fake-app-2000", + "description": "", + "access_type": "acl", + "locked": false, + "locked_message": "", + "connection_timeout": null, + "read_timeout": null, + "init_timeout": null, + "idle_timeout": null, + "max_processes": null, + "min_processes": null, + "max_conns_per_process": null, + "load_factor": null, + "memory_request": null, + "memory_limit": null, + "cpu_request": null, + "cpu_limit": null, + "amd_gpu_limit": null, + "nvidia_gpu_limit": null, + "service_account_name": null, + "default_image_name": null, + "created_time": "2024-08-22T15:44:48Z", + "last_deployed_time": "2024-08-22T15:44:49Z", + "bundle_id": "142621", + "app_mode": "shiny", + "content_category": "", + "parameterized": false, + "cluster_name": "Local", + "image_name": null, + "r_version": "4.4.0", + "py_version": null, + "quarto_version": null, + "r_environment_management": true, + "default_r_environment_management": null, + "py_environment_management": null, + "default_py_environment_management": null, + "run_as": null, + "run_as_current_user": false, + "owner_guid": "fe07bf64", + "content_url": "https://connect.example/content/12345678/", + "dashboard_url": "https://connect.example/connect/#/apps/12345678", + "app_role": "owner", + "id": "56746" +} diff --git a/tests/testthat/2024.08.0/__api__/v1/content/23456789.json b/tests/testthat/2024.08.0/__api__/v1/content/23456789.json new file mode 100644 index 00000000..7a1fcb8d --- /dev/null +++ b/tests/testthat/2024.08.0/__api__/v1/content/23456789.json @@ -0,0 +1,47 @@ +{ + "guid": "23456789", + "name": "fake-app-3000", + "title": "fake-app-3000", + "description": "", + "access_type": "acl", + "locked": false, + "locked_message": "", + "connection_timeout": null, + "read_timeout": null, + "init_timeout": null, + "idle_timeout": null, + "max_processes": null, + "min_processes": null, + "max_conns_per_process": null, + "load_factor": null, + "memory_request": null, + "memory_limit": null, + "cpu_request": null, + "cpu_limit": null, + "amd_gpu_limit": null, + "nvidia_gpu_limit": null, + "service_account_name": null, + "default_image_name": null, + "created_time": "2024-08-22T15:44:48Z", + "last_deployed_time": "2024-08-22T15:44:49Z", + "bundle_id": "142621", + "app_mode": "shiny", + "content_category": "", + "parameterized": false, + "cluster_name": "Local", + "image_name": null, + "r_version": "4.4.0", + "py_version": null, + "quarto_version": null, + "r_environment_management": true, + "default_r_environment_management": null, + "py_environment_management": null, + "default_py_environment_management": null, + "run_as": null, + "run_as_current_user": false, + "owner_guid": "fe07bf64", + "content_url": "https://connect.example/content/23456789/", + "dashboard_url": "https://connect.example/connect/#/apps/23456789", + "app_role": "owner", + "id": "56746" +} diff --git a/tests/testthat/2024.08.0/__api__/v1/content/23456789/thumbnail-DELETE.R b/tests/testthat/2024.08.0/__api__/v1/content/23456789/thumbnail-DELETE.R new file mode 100644 index 00000000..740b5c58 --- /dev/null +++ b/tests/testthat/2024.08.0/__api__/v1/content/23456789/thumbnail-DELETE.R @@ -0,0 +1,7 @@ +structure( + list( + url = "__api__/v1/applications/23456789/thumbnail", + status_code = 404L + ), + class = "response" +) diff --git a/tests/testthat/2024.08.0/__api__/v1/content/23456789/thumbnail-PUT.R b/tests/testthat/2024.08.0/__api__/v1/content/23456789/thumbnail-PUT.R new file mode 100644 index 00000000..a19fb69b --- /dev/null +++ b/tests/testthat/2024.08.0/__api__/v1/content/23456789/thumbnail-PUT.R @@ -0,0 +1,7 @@ +structure( + list( + url = "__api__/v1/content/01234567/thumbnail", + status_code = 404L, content = charToRaw("404 page not found") + ), + class = "response" +) diff --git a/tests/testthat/2024.08.0/__api__/v1/content/34567890.json b/tests/testthat/2024.08.0/__api__/v1/content/34567890.json new file mode 100644 index 00000000..0c3ff7d8 --- /dev/null +++ b/tests/testthat/2024.08.0/__api__/v1/content/34567890.json @@ -0,0 +1,47 @@ +{ + "guid": "34567890", + "name": "fake-app-3000", + "title": "fake-app-3000", + "description": "", + "access_type": "acl", + "locked": false, + "locked_message": "", + "connection_timeout": null, + "read_timeout": null, + "init_timeout": null, + "idle_timeout": null, + "max_processes": null, + "min_processes": null, + "max_conns_per_process": null, + "load_factor": null, + "memory_request": null, + "memory_limit": null, + "cpu_request": null, + "cpu_limit": null, + "amd_gpu_limit": null, + "nvidia_gpu_limit": null, + "service_account_name": null, + "default_image_name": null, + "created_time": "2024-08-22T15:44:48Z", + "last_deployed_time": "2024-08-22T15:44:49Z", + "bundle_id": "142621", + "app_mode": "shiny", + "content_category": "", + "parameterized": false, + "cluster_name": "Local", + "image_name": null, + "r_version": "4.4.0", + "py_version": null, + "quarto_version": null, + "r_environment_management": true, + "default_r_environment_management": null, + "py_environment_management": null, + "default_py_environment_management": null, + "run_as": null, + "run_as_current_user": false, + "owner_guid": "fe07bf64", + "content_url": "https://connect.example/content/23456789/", + "dashboard_url": "https://connect.example/connect/#/apps/23456789", + "app_role": "owner", + "id": "56746" +} diff --git a/tests/testthat/2024.08.0/__api__/v1/content/34567890/thumbnail-DELETE.R b/tests/testthat/2024.08.0/__api__/v1/content/34567890/thumbnail-DELETE.R new file mode 100644 index 00000000..704664a8 --- /dev/null +++ b/tests/testthat/2024.08.0/__api__/v1/content/34567890/thumbnail-DELETE.R @@ -0,0 +1,8 @@ +structure( + list( + url = "__api__/v1/applications/34567890/thumbnail", + status_code = 404L, + content = list(code = 17, error = "The requested item could not be removed because it does not exist.", payload = NULL) + ), + class = "response" +) diff --git a/tests/testthat/__api__/v1/content/8f37d6e0.json b/tests/testthat/2024.08.0/__api__/v1/content/8f37d6e0.json similarity index 100% rename from tests/testthat/__api__/v1/content/8f37d6e0.json rename to tests/testthat/2024.08.0/__api__/v1/content/8f37d6e0.json diff --git a/tests/testthat/__api__/v1/content/8f37d6e0/environment-58ff34-PATCH.json b/tests/testthat/2024.08.0/__api__/v1/content/8f37d6e0/environment-58ff34-PATCH.json similarity index 100% rename from tests/testthat/__api__/v1/content/8f37d6e0/environment-58ff34-PATCH.json rename to tests/testthat/2024.08.0/__api__/v1/content/8f37d6e0/environment-58ff34-PATCH.json diff --git a/tests/testthat/__api__/v1/content/8f37d6e0/environment-af33b5-PATCH.json b/tests/testthat/2024.08.0/__api__/v1/content/8f37d6e0/environment-af33b5-PATCH.json similarity index 100% rename from tests/testthat/__api__/v1/content/8f37d6e0/environment-af33b5-PATCH.json rename to tests/testthat/2024.08.0/__api__/v1/content/8f37d6e0/environment-af33b5-PATCH.json diff --git a/tests/testthat/__api__/v1/content/951bf3ad.json b/tests/testthat/2024.08.0/__api__/v1/content/951bf3ad.json similarity index 100% rename from tests/testthat/__api__/v1/content/951bf3ad.json rename to tests/testthat/2024.08.0/__api__/v1/content/951bf3ad.json diff --git a/tests/testthat/__api__/v1/content/f2f37341.json b/tests/testthat/2024.08.0/__api__/v1/content/f2f37341.json similarity index 100% rename from tests/testthat/__api__/v1/content/f2f37341.json rename to tests/testthat/2024.08.0/__api__/v1/content/f2f37341.json diff --git a/tests/testthat/__api__/v1/content/f2f37341/permissions.json b/tests/testthat/2024.08.0/__api__/v1/content/f2f37341/permissions.json similarity index 100% rename from tests/testthat/__api__/v1/content/f2f37341/permissions.json rename to tests/testthat/2024.08.0/__api__/v1/content/f2f37341/permissions.json diff --git a/tests/testthat/__api__/v1/content/f2f37341/permissions/94.json b/tests/testthat/2024.08.0/__api__/v1/content/f2f37341/permissions/94.json similarity index 100% rename from tests/testthat/__api__/v1/content/f2f37341/permissions/94.json rename to tests/testthat/2024.08.0/__api__/v1/content/f2f37341/permissions/94.json diff --git a/tests/testthat/__api__/v1/oauth/integrations/credentials-fe6213-POST.json b/tests/testthat/2024.08.0/__api__/v1/oauth/integrations/credentials-fe6213-POST.json similarity index 100% rename from tests/testthat/__api__/v1/oauth/integrations/credentials-fe6213-POST.json rename to tests/testthat/2024.08.0/__api__/v1/oauth/integrations/credentials-fe6213-POST.json diff --git a/tests/testthat/__api__/v1/users-01eb50.json b/tests/testthat/2024.08.0/__api__/v1/users-01eb50.json similarity index 100% rename from tests/testthat/__api__/v1/users-01eb50.json rename to tests/testthat/2024.08.0/__api__/v1/users-01eb50.json diff --git a/tests/testthat/__api__/v1/users-a7d21f.json b/tests/testthat/2024.08.0/__api__/v1/users-a7d21f.json similarity index 100% rename from tests/testthat/__api__/v1/users-a7d21f.json rename to tests/testthat/2024.08.0/__api__/v1/users-a7d21f.json diff --git a/tests/testthat/__api__/v1/users-c6c26e.json b/tests/testthat/2024.08.0/__api__/v1/users-c6c26e.json similarity index 100% rename from tests/testthat/__api__/v1/users-c6c26e.json rename to tests/testthat/2024.08.0/__api__/v1/users-c6c26e.json diff --git a/tests/testthat/__api__/v1/users/20a79ce3.json b/tests/testthat/2024.08.0/__api__/v1/users/20a79ce3.json similarity index 100% rename from tests/testthat/__api__/v1/users/20a79ce3.json rename to tests/testthat/2024.08.0/__api__/v1/users/20a79ce3.json diff --git a/tests/testthat/__api__/v1/vanities.json b/tests/testthat/2024.08.0/__api__/v1/vanities.json similarity index 100% rename from tests/testthat/__api__/v1/vanities.json rename to tests/testthat/2024.08.0/__api__/v1/vanities.json diff --git a/tests/testthat/__api__/variants/6644/render-38c41e-POST.json b/tests/testthat/2024.08.0/__api__/variants/6644/render-38c41e-POST.json similarity index 100% rename from tests/testthat/__api__/variants/6644/render-38c41e-POST.json rename to tests/testthat/2024.08.0/__api__/variants/6644/render-38c41e-POST.json diff --git a/tests/testthat/__api__/variants/6666/render-38c41e-POST.json b/tests/testthat/2024.08.0/__api__/variants/6666/render-38c41e-POST.json similarity index 100% rename from tests/testthat/__api__/variants/6666/render-38c41e-POST.json rename to tests/testthat/2024.08.0/__api__/variants/6666/render-38c41e-POST.json diff --git a/tests/testthat/2024.08.0/__ping__.json b/tests/testthat/2024.08.0/__ping__.json new file mode 100644 index 00000000..0db3279e --- /dev/null +++ b/tests/testthat/2024.08.0/__ping__.json @@ -0,0 +1,3 @@ +{ + +} diff --git a/tests/testthat/2024.08.0/content/01234567/__thumbnail__.R b/tests/testthat/2024.08.0/content/01234567/__thumbnail__.R new file mode 100644 index 00000000..3b30d530 --- /dev/null +++ b/tests/testthat/2024.08.0/content/01234567/__thumbnail__.R @@ -0,0 +1,7 @@ +structure( + list( + url = "content/01234567/__thumbnail__", + status_code = 404L, content = charToRaw("404 page not found") + ), + class = "response" +) diff --git a/tests/testthat/2024.08.0/content/12345678/__thumbnail__.R b/tests/testthat/2024.08.0/content/12345678/__thumbnail__.R new file mode 100644 index 00000000..0d1504db --- /dev/null +++ b/tests/testthat/2024.08.0/content/12345678/__thumbnail__.R @@ -0,0 +1,5 @@ +structure( + list(url = "content/12345678/__thumbnail__", status_code = 404L), + content = charToRaw("404 page not found"), + class = "response" +) diff --git a/tests/testthat/2024.08.0/content/23456789/__thumbnail__.R b/tests/testthat/2024.08.0/content/23456789/__thumbnail__.R new file mode 100644 index 00000000..ca982d55 --- /dev/null +++ b/tests/testthat/2024.08.0/content/23456789/__thumbnail__.R @@ -0,0 +1,5 @@ +structure( + list(url = "content/23456789/__thumbnail__", status_code = 404L), + content = charToRaw("404 page not found"), + class = "response" +) diff --git a/tests/testthat/2024.08.0/content/34567890/__thumbnail__.R b/tests/testthat/2024.08.0/content/34567890/__thumbnail__.R new file mode 100644 index 00000000..ca982d55 --- /dev/null +++ b/tests/testthat/2024.08.0/content/34567890/__thumbnail__.R @@ -0,0 +1,5 @@ +structure( + list(url = "content/23456789/__thumbnail__", status_code = 404L), + content = charToRaw("404 page not found"), + class = "response" +) diff --git a/tests/testthat/2024.08.0/non-connect/missing-image/image.png.R b/tests/testthat/2024.08.0/non-connect/missing-image/image.png.R new file mode 100644 index 00000000..9700514d --- /dev/null +++ b/tests/testthat/2024.08.0/non-connect/missing-image/image.png.R @@ -0,0 +1,5 @@ +structure( + list(url = "missing-image/image.png", status_code = 404L), + content = charToRaw("404 page not found"), + class = "response" +) diff --git a/tests/testthat/2024.09.0/__api__/applications/23456789/image-DELETE.R b/tests/testthat/2024.09.0/__api__/applications/23456789/image-DELETE.R new file mode 100644 index 00000000..ce28cff8 --- /dev/null +++ b/tests/testthat/2024.09.0/__api__/applications/23456789/image-DELETE.R @@ -0,0 +1,5 @@ +structure( + list(url = "__api__/applications/23456789/image", status_code = 404L), + content = charToRaw("404 page not found"), + class = "response" +) diff --git a/tests/testthat/2024.09.0/__api__/applications/23456789/image-POST.R b/tests/testthat/2024.09.0/__api__/applications/23456789/image-POST.R new file mode 100644 index 00000000..ce28cff8 --- /dev/null +++ b/tests/testthat/2024.09.0/__api__/applications/23456789/image-POST.R @@ -0,0 +1,5 @@ +structure( + list(url = "__api__/applications/23456789/image", status_code = 404L), + content = charToRaw("404 page not found"), + class = "response" +) diff --git a/tests/testthat/2024.09.0/__api__/applications/23456789/image.R b/tests/testthat/2024.09.0/__api__/applications/23456789/image.R new file mode 100644 index 00000000..ce28cff8 --- /dev/null +++ b/tests/testthat/2024.09.0/__api__/applications/23456789/image.R @@ -0,0 +1,5 @@ +structure( + list(url = "__api__/applications/23456789/image", status_code = 404L), + content = charToRaw("404 page not found"), + class = "response" +) diff --git a/tests/testthat/2024.09.0/__api__/server_settings.json b/tests/testthat/2024.09.0/__api__/server_settings.json new file mode 100644 index 00000000..3c2342c8 --- /dev/null +++ b/tests/testthat/2024.09.0/__api__/server_settings.json @@ -0,0 +1,123 @@ +{ + "hostname": "dogfood01", + "version": "2024.09.0-dev+77-g9296f96ffb", + "build": "v2024.08.0-77-g9296f96ffb", + "about": "Posit Connect v2024.09.0-dev+77-g9296f96ffb", + "authentication": { + "handles_credentials": false, + "handles_login": true, + "challenge_response_enabled": false, + "external_user_data": true, + "external_user_search": true, + "external_user_id": true, + "groups_enabled": true, + "external_group_search": false, + "external_group_members": false, + "external_group_id": false, + "external_group_owner": false, + "unique_usernames": true, + "name_editable_by": "provider", + "email_editable_by": "provider", + "username_editable_by": "adminandself", + "role_editable_by": "adminandself", + "name": "OAuth2", + "notice": "NOTICE: Other users will be able to see your full name and email address in Posit Connect.", + "warning_delay": 10, + "API_key_auth": true + }, + "license": { + "ts": 1726138921155, + "status": "activated", + "expiration": 1759276800000, + "days-left": 384, + "has-key": true, + "has-trial": true, + "tier": "standard", + "sku-year": "2023", + "edition": "", + "cores": 0, + "connections": 0, + "type": "local", + "users": 0, + "user-activity-days": 365, + "users-grace": "true", + "shiny-users": 0, + "allow-apis": true, + "custom-branding": true, + "current-user-execution": true, + "anonymous-servers": true, + "unrestricted-servers": true, + "anonymous-branding": false, + "oauth-integrations": true, + "enable-launcher": false + }, + "license_expiration_ui_warning": true, + "end_of_support_ui_warning": true, + "deprecated_settings": false, + "deprecated_settings_ui_warning": true, + "viewers_can_request_privileges": true, + "mail_all": false, + "mail_configured": true, + "public_warning": "", + "logged_in_warning": "", + "logout_url": "__logout__", + "metrics_rrd_enabled": true, + "metrics_instrumentation": true, + "customized_landing": false, + "self_registration": false, + "prohibited_usernames": [ + "connect", + "apps", + "users", + "groups", + "setpassword", + "user-completion", + "confirm", + "recent", + "reports", + "plots", + "unpublished", + "settings", + "metrics", + "tokens", + "help", + "login", + "welcome", + "register", + "resetpassword", + "content" + ], + "username_validator": "default", + "viewers_can_only_see_themselves": false, + "http_warning": false, + "runtimes": [ + "R", + "Python", + "Quarto", + "TensorFlow" + ], + "default_content_list_view": "compact", + "maximum_app_image_size": 10000000, + "server_settings_toggler": true, + "git_enabled": true, + "git_available": true, + "dashboard_path": "/connect", + "system_display_name": "Posit Connect", + "hide_viewer_documentation": false, + "jump_start_enabled": true, + "permission_request": true, + "tableau_integration_enabled": true, + "self_test_enabled": true, + "execution_type": "native", + "enable_runtime_cache_management": true, + "default_image_selection_enabled": true, + "default_environment_management_selection": true, + "default_r_environment_management": true, + "default_py_environment_management": true, + "new_parameterization_enabled": false, + "use_window_location": false, + "locked_content_enabled": true, + "oauth_integrations_enabled": true, + "labs_enabled": false, + "whats_new_enabled": true +} diff --git a/tests/testthat/2024.09.0/__api__/v1/content/01234567.json b/tests/testthat/2024.09.0/__api__/v1/content/01234567.json new file mode 100644 index 00000000..607b9fb3 --- /dev/null +++ b/tests/testthat/2024.09.0/__api__/v1/content/01234567.json @@ -0,0 +1,47 @@ +{ + "guid": "01234567", + "name": "shinyapp-2024-08-22", + "title": "shinyapp-2024-08-22", + "description": "", + "access_type": "acl", + "locked": false, + "locked_message": "", + "connection_timeout": null, + "read_timeout": null, + "init_timeout": null, + "idle_timeout": null, + "max_processes": null, + "min_processes": null, + "max_conns_per_process": null, + "load_factor": null, + "memory_request": null, + "memory_limit": null, + "cpu_request": null, + "cpu_limit": null, + "amd_gpu_limit": null, + "nvidia_gpu_limit": null, + "service_account_name": null, + "default_image_name": null, + "created_time": "2024-08-22T15:44:48Z", + "last_deployed_time": "2024-08-22T15:44:49Z", + "bundle_id": "142621", + "app_mode": "shiny", + "content_category": "", + "parameterized": false, + "cluster_name": "Local", + "image_name": null, + "r_version": "4.4.0", + "py_version": null, + "quarto_version": null, + "r_environment_management": true, + "default_r_environment_management": null, + "py_environment_management": null, + "default_py_environment_management": null, + "run_as": null, + "run_as_current_user": false, + "owner_guid": "fe07bf64", + "content_url": "https://connect.example/content/01234567/", + "dashboard_url": "https://connect.example/connect/#/apps/01234567", + "app_role": "owner", + "id": "56746" +} diff --git a/tests/testthat/2024.09.0/__api__/v1/content/01234567/thumbnail-DELETE.204 b/tests/testthat/2024.09.0/__api__/v1/content/01234567/thumbnail-DELETE.204 new file mode 100644 index 00000000..e69de29b diff --git a/tests/testthat/2024.09.0/__api__/v1/content/01234567/thumbnail-PUT.204 b/tests/testthat/2024.09.0/__api__/v1/content/01234567/thumbnail-PUT.204 new file mode 100644 index 00000000..e69de29b diff --git a/tests/testthat/2024.09.0/__api__/v1/content/12345678.json b/tests/testthat/2024.09.0/__api__/v1/content/12345678.json new file mode 100644 index 00000000..1cc306fd --- /dev/null +++ b/tests/testthat/2024.09.0/__api__/v1/content/12345678.json @@ -0,0 +1,47 @@ +{ + "guid": "12345678", + "name": "fake-app-2000", + "title": "fake-app-2000", + "description": "", + "access_type": "acl", + "locked": false, + "locked_message": "", + "connection_timeout": null, + "read_timeout": null, + "init_timeout": null, + "idle_timeout": null, + "max_processes": null, + "min_processes": null, + "max_conns_per_process": null, + "load_factor": null, + "memory_request": null, + "memory_limit": null, + "cpu_request": null, + "cpu_limit": null, + "amd_gpu_limit": null, + "nvidia_gpu_limit": null, + "service_account_name": null, + "default_image_name": null, + "created_time": "2024-08-22T15:44:48Z", + "last_deployed_time": "2024-08-22T15:44:49Z", + "bundle_id": "142621", + "app_mode": "shiny", + "content_category": "", + "parameterized": false, + "cluster_name": "Local", + "image_name": null, + "r_version": "4.4.0", + "py_version": null, + "quarto_version": null, + "r_environment_management": true, + "default_r_environment_management": null, + "py_environment_management": null, + "default_py_environment_management": null, + "run_as": null, + "run_as_current_user": false, + "owner_guid": "fe07bf64", + "content_url": "https://connect.example/content/12345678/", + "dashboard_url": "https://connect.example/connect/#/apps/12345678", + "app_role": "owner", + "id": "56746" +} diff --git a/tests/testthat/2024.09.0/__api__/v1/content/23456789.json b/tests/testthat/2024.09.0/__api__/v1/content/23456789.json new file mode 100644 index 00000000..7a1fcb8d --- /dev/null +++ b/tests/testthat/2024.09.0/__api__/v1/content/23456789.json @@ -0,0 +1,47 @@ +{ + "guid": "23456789", + "name": "fake-app-3000", + "title": "fake-app-3000", + "description": "", + "access_type": "acl", + "locked": false, + "locked_message": "", + "connection_timeout": null, + "read_timeout": null, + "init_timeout": null, + "idle_timeout": null, + "max_processes": null, + "min_processes": null, + "max_conns_per_process": null, + "load_factor": null, + "memory_request": null, + "memory_limit": null, + "cpu_request": null, + "cpu_limit": null, + "amd_gpu_limit": null, + "nvidia_gpu_limit": null, + "service_account_name": null, + "default_image_name": null, + "created_time": "2024-08-22T15:44:48Z", + "last_deployed_time": "2024-08-22T15:44:49Z", + "bundle_id": "142621", + "app_mode": "shiny", + "content_category": "", + "parameterized": false, + "cluster_name": "Local", + "image_name": null, + "r_version": "4.4.0", + "py_version": null, + "quarto_version": null, + "r_environment_management": true, + "default_r_environment_management": null, + "py_environment_management": null, + "default_py_environment_management": null, + "run_as": null, + "run_as_current_user": false, + "owner_guid": "fe07bf64", + "content_url": "https://connect.example/content/23456789/", + "dashboard_url": "https://connect.example/connect/#/apps/23456789", + "app_role": "owner", + "id": "56746" +} diff --git a/tests/testthat/2024.09.0/__api__/v1/content/23456789/thumbnail-DELETE.R b/tests/testthat/2024.09.0/__api__/v1/content/23456789/thumbnail-DELETE.R new file mode 100644 index 00000000..ce1c8150 --- /dev/null +++ b/tests/testthat/2024.09.0/__api__/v1/content/23456789/thumbnail-DELETE.R @@ -0,0 +1,8 @@ +structure( + list( + url = "__api__/applications/23456789/image", + status_code = 404L, + content = list(code = 4, error = "The requested object does not exist.", payload = NULL) + ), + class = "response" +) diff --git a/tests/testthat/2024.09.0/__api__/v1/content/23456789/thumbnail-PUT.R b/tests/testthat/2024.09.0/__api__/v1/content/23456789/thumbnail-PUT.R new file mode 100644 index 00000000..085dfd37 --- /dev/null +++ b/tests/testthat/2024.09.0/__api__/v1/content/23456789/thumbnail-PUT.R @@ -0,0 +1,5 @@ +structure( + list(url = "__api__/v1/content/23456789/thumbnail", status_code = 404L), + content = charToRaw("404 page not found"), + class = "response" +) diff --git a/tests/testthat/2024.09.0/__api__/v1/content/34567890.json b/tests/testthat/2024.09.0/__api__/v1/content/34567890.json new file mode 100644 index 00000000..0c3ff7d8 --- /dev/null +++ b/tests/testthat/2024.09.0/__api__/v1/content/34567890.json @@ -0,0 +1,47 @@ +{ + "guid": "34567890", + "name": "fake-app-3000", + "title": "fake-app-3000", + "description": "", + "access_type": "acl", + "locked": false, + "locked_message": "", + "connection_timeout": null, + "read_timeout": null, + "init_timeout": null, + "idle_timeout": null, + "max_processes": null, + "min_processes": null, + "max_conns_per_process": null, + "load_factor": null, + "memory_request": null, + "memory_limit": null, + "cpu_request": null, + "cpu_limit": null, + "amd_gpu_limit": null, + "nvidia_gpu_limit": null, + "service_account_name": null, + "default_image_name": null, + "created_time": "2024-08-22T15:44:48Z", + "last_deployed_time": "2024-08-22T15:44:49Z", + "bundle_id": "142621", + "app_mode": "shiny", + "content_category": "", + "parameterized": false, + "cluster_name": "Local", + "image_name": null, + "r_version": "4.4.0", + "py_version": null, + "quarto_version": null, + "r_environment_management": true, + "default_r_environment_management": null, + "py_environment_management": null, + "default_py_environment_management": null, + "run_as": null, + "run_as_current_user": false, + "owner_guid": "fe07bf64", + "content_url": "https://connect.example/content/23456789/", + "dashboard_url": "https://connect.example/connect/#/apps/23456789", + "app_role": "owner", + "id": "56746" +} diff --git a/tests/testthat/2024.09.0/__api__/v1/content/34567890/thumbnail-DELETE.R b/tests/testthat/2024.09.0/__api__/v1/content/34567890/thumbnail-DELETE.R new file mode 100644 index 00000000..704664a8 --- /dev/null +++ b/tests/testthat/2024.09.0/__api__/v1/content/34567890/thumbnail-DELETE.R @@ -0,0 +1,8 @@ +structure( + list( + url = "__api__/v1/applications/34567890/thumbnail", + status_code = 404L, + content = list(code = 17, error = "The requested item could not be removed because it does not exist.", payload = NULL) + ), + class = "response" +) diff --git a/tests/testthat/2024.09.0/__ping__.json b/tests/testthat/2024.09.0/__ping__.json new file mode 100644 index 00000000..0db3279e --- /dev/null +++ b/tests/testthat/2024.09.0/__ping__.json @@ -0,0 +1,3 @@ +{ + +} diff --git a/tests/testthat/2024.09.0/content/01234567/__thumbnail__.R b/tests/testthat/2024.09.0/content/01234567/__thumbnail__.R new file mode 100644 index 00000000..9ffdfce8 --- /dev/null +++ b/tests/testthat/2024.09.0/content/01234567/__thumbnail__.R @@ -0,0 +1,9 @@ +structure(list( + url = "content/01234567/__thumbnail__", status_code = 200L, + headers = structure(list( + `content-type` = "image/jpeg" + )), content = as.raw(c( + 0x4e, + 0x41 + )) +), class = "response") diff --git a/tests/testthat/2024.09.0/content/12345678/__thumbnail__.204 b/tests/testthat/2024.09.0/content/12345678/__thumbnail__.204 new file mode 100644 index 00000000..e69de29b diff --git a/tests/testthat/2024.09.0/content/23456789/__thumbnail__.R b/tests/testthat/2024.09.0/content/23456789/__thumbnail__.R new file mode 100644 index 00000000..e4a31c50 --- /dev/null +++ b/tests/testthat/2024.09.0/content/23456789/__thumbnail__.R @@ -0,0 +1,6 @@ +structure( + list(url = "content/23456789/__thumbnail__", status_code = 404L), + content = charToRaw("404 page not found"), + class = "response" + ) + \ No newline at end of file diff --git a/tests/testthat/2024.09.0/non-connect/missing-image/image.png.R b/tests/testthat/2024.09.0/non-connect/missing-image/image.png.R new file mode 100644 index 00000000..9700514d --- /dev/null +++ b/tests/testthat/2024.09.0/non-connect/missing-image/image.png.R @@ -0,0 +1,5 @@ +structure( + list(url = "missing-image/image.png", status_code = 404L), + content = charToRaw("404 page not found"), + class = "response" +) diff --git a/tests/testthat/Rplots.pdf b/tests/testthat/Rplots.pdf new file mode 100644 index 00000000..fbadf3e5 Binary files /dev/null and b/tests/testthat/Rplots.pdf differ diff --git a/tests/testthat/resources/smol.jpg b/tests/testthat/resources/smol.jpg new file mode 100644 index 00000000..e905241b Binary files /dev/null and b/tests/testthat/resources/smol.jpg differ diff --git a/tests/testthat/setup.R b/tests/testthat/setup.R index 62f21da2..aae96e0f 100644 --- a/tests/testthat/setup.R +++ b/tests/testthat/setup.R @@ -31,3 +31,7 @@ set_redactor( ) } ) + +# Mocks are in directories by Connect version. 2024.08.0 contains all mocks +# created before 2024.09.0, and is the default mock path. +.mockPaths("2024.08.0") diff --git a/tests/testthat/test-content.R b/tests/testthat/test-content.R index 91a534ca..31f3c8bf 100644 --- a/tests/testthat/test-content.R +++ b/tests/testthat/test-content.R @@ -231,4 +231,3 @@ with_mock_api({ expect_identical(v$key, "WrEKKa77") }) }) - diff --git a/tests/testthat/test-thumbnail.R b/tests/testthat/test-thumbnail.R new file mode 100644 index 00000000..c026ea00 --- /dev/null +++ b/tests/testthat/test-thumbnail.R @@ -0,0 +1,125 @@ +mock_dirs <- c( + "unversioned" = "2024.08.0", + "v1" = "2024.09.0" +) + +# The mocked content items are as follows: +# - 01234567: +# - Returns 200 and a tiny jpeg when getting the thumbnail +# - Returns 204 (success) when setting and deleting +# - 12345678: Returns 204 when getting the thumbnail (no thumbnail) +# - 23456789: Returns 404 for all endpoints +# - non-connect/missing-image/image.R: a 404 response + +for (api_ver in names(mock_dirs)) { + mock_dir <- mock_dirs[[api_ver]] + with_mock_dir(mock_dir, { + with_mock_api({ + client <- connect(server = "https://connect.example", api_key = "fake") + test_that(glue::glue("get_thumbnail() gets the thumbnail ({api_ver} - {mock_dir})"), { + item <- content_item(client, "01234567") + + # User-specified path + user_path <- tempfile("thumbnail_", fileext = ".jpg") + received_path <- get_thumbnail(item, user_path) + received <- readBin(received_path, "raw", n = 8) + expected <- as.raw(c(0x4e, 0x41)) + expect_equal(user_path, received_path) + expect_equal(received, expected) + + # User-specified path (wrong extension) + user_path <- tempfile("thumbnail_", fileext = ".png") + received_path <- get_thumbnail(item, user_path) + received <- readBin(received_path, "raw", n = 8) + expected <- as.raw(c(0x4e, 0x41)) + expect_equal(paste0(user_path, ".jpeg"), received_path) + expect_equal(received, expected) + + # Automatic path + received_path <- get_thumbnail(item) + received <- readBin(received_path, "raw", n = 8) + expected <- as.raw(c(0x4e, 0x41)) + expect_equal(substring(received_path, nchar(received_path) - 4), ".jpeg") + expect_equal(received, expected) + }) + + test_that(glue::glue("get_thumbnail() returns NA_character_ for 204 status codes ({api_ver} - {mock_dir})"), { + item <- content_item(client, "12345678") + + # User-specified path + user_path <- tempfile("thumbnail_", fileext = ".jpg") + received_path <- get_thumbnail(item, user_path) + expect_equal(received_path, NA_character_) + + # Automatic path + received_path <- get_thumbnail(item) + expect_equal(received_path, NA_character_) + }) + + test_that(glue::glue("get_thumbnail() errors with 404 status codes ({api_ver} - {mock_dir})"), { + item <- content_item(client, "23456789") + expect_error(get_thumbnail(item), "request failed with Client error: \\(404\\) Not Found") + }) + + test_that(glue::glue("has_thumbnail() returns TRUE when the item has a thumbnail ({api_ver} - {mock_dir})"), { + item <- content_item(client, "01234567") + expect_true(has_thumbnail(item)) + }) + + test_that(glue::glue("has_thumbnail() returns FALSE when the status code is 204 ({api_ver} - {mock_dir})"), { + item <- content_item(client, "12345678") + expect_false(has_thumbnail(item)) + }) + + test_that(glue::glue("has_thumbnail() errors with 404 status codes ({api_ver} - {mock_dir})"), { + item <- content_item(client, "23456789") + expect_error(has_thumbnail(item), "request failed with Client error: \\(404\\) Not Found") + }) + + test_that(glue::glue("set_thumbnail() returns returns the content item when successful ({api_ver} - {mock_dir})"), { + item <- content_item(client, "01234567") + received <- set_thumbnail(item, "resources/smol.jpg") + expect_true(validate_R6_class(received, "Content")) + expect_identical(item, received) + }) + + test_that(glue::glue("set_thumbnail() raises an error when the endpoint returns a 404 ({api_ver} - {mock_dir})"), { + item <- content_item(client, "23456789") + expect_error(set_thumbnail(item, "resources/smol.jpg"), "request failed with Client error: \\(404\\) Not Found") + }) + + test_that(glue::glue("set_thumbnail() works with remote images ({api_ver} - {mock_dir})"), { + item <- content_item(client, "01234567") + expect_GET(set_thumbnail(item, "https://other.server/non-connect/working-image/not-an-image"), + "https://other.server/non-connect/working-image/not-an-image") + # We're only asserting that the remote image hits GET. Because we + # httr::write_disk() and then using what is written doesn't work + # (https://github.com/nealrichardson/httptest/issues/86) the rest of + # this function is tested elsewhere, so we have confidence that so long + # as getting and writing to disk works, we are good. + }) + + test_that(glue::glue("set_thumbnail() returns an error when the remote image cannot be found ({api_ver} - {mock_dir})"), { + item <- content_item(client, "01234567") + expect_error(set_thumbnail(item, "https://other.server/non-connect/missing-image/image.png"), + "Could not download image from https") + }) + + test_that(glue::glue("delete_thumbnail() returns the content item when delete works ({api_ver} - {mock_dir})"), { + item <- content_item(client, "01234567") + expect_identical(delete_thumbnail(item), item) + }) + + test_that(glue::glue("delete_thumbnail() throws an error for other 404 errors ({api_ver} - {mock_dir})"), { + item <- content_item(client, "23456789") + expect_error(delete_thumbnail(item), "request failed with Client error: \\(404\\) Not Found") + }) + + test_that(glue::glue("delete_thumbnail() returns the content for 404s indicating no thumbnail ({api_ver} - {mock_dir})"), { + item <- content_item(client, "34567890") + expect_identical(delete_thumbnail(item), item) + }) + }) + }) +} + diff --git a/vignettes/getting-started.Rmd b/vignettes/getting-started.Rmd index 8455400e..3810329a 100644 --- a/vignettes/getting-started.Rmd +++ b/vignettes/getting-started.Rmd @@ -82,7 +82,7 @@ while you wait for deployment to complete: ```r content_1 %>% - set_image_url("https://gph.is/29vyb0s") %>% + set_thumbnail("https://gph.is/29vyb0s") %>% set_vanity_url("/my_clever_content") # ensure the vanity URL is set as expected