diff --git a/DESCRIPTION b/DESCRIPTION index f4e95dd..0d91438 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -18,6 +18,7 @@ BugReports: https://github.com/jonthegeek/rapid/issues Imports: cli, glue, + jsonlite, purrr, rlang (>= 1.1.0), S7 (>= 0.1.1), @@ -60,6 +61,7 @@ Collate: 'components-security_scheme-oauth2-token_flow.R' 'components-security_scheme-oauth2.R' 'rapid-package.R' + 'urls.R' 'utils.R' 'validate_in.R' 'validate_lengths.R' diff --git a/R/as.R b/R/as.R index 64cdc41..b03ac98 100644 --- a/R/as.R +++ b/R/as.R @@ -23,7 +23,9 @@ as_api_object <- S7::new_generic( alternate_names = NULL, arg = caller_arg(x), call = caller_env()) { - if (missing(x)) return(target_class()) + if (missing(x)) { + return(target_class()) + } force(arg) rlang::check_dots_empty(call = call) if (S7::S7_inherits(x, target_class)) { diff --git a/R/urls.R b/R/urls.R new file mode 100644 index 0000000..c029e62 --- /dev/null +++ b/R/urls.R @@ -0,0 +1,12 @@ +.url_to_string <- function(x) { + summary(x)$description +} + +.url_fetch <- function(x) { + rlang::try_fetch( + jsonlite::fromJSON(url(x), simplifyDataFrame = FALSE), + error = function(e) { + yaml::read_yaml(url(x)) + } + ) +} diff --git a/R/zz-rapid.R b/R/zz-rapid.R index dc9482e..de50533 100644 --- a/R/zz-rapid.R +++ b/R/zz-rapid.R @@ -107,7 +107,8 @@ S7::method(length, rapid) <- function(x) { #' @inheritParams rlang::args_error_context #' @param x The object to coerce. Must be empty or have names "info" and/or #' "servers", or names that can be coerced to those names via -#' [snakecase::to_snake_case()]. Extra names are ignored. +#' [snakecase::to_snake_case()]. Extra names are ignored. [url()] objects are +#' read with [jsonlite::fromJSON()] or [yaml::read_yaml()] before conversion. #' #' @return A `rapid` object as returned by [rapid()]. #' @export @@ -120,10 +121,10 @@ S7::method(as_rapid, S7::new_S3_class("url")) <- function(x, ..., arg = caller_arg(x), call = caller_env()) { - url <- summary(x)$description - x <- yaml::read_yaml(x) + url_string <- .url_to_string(x) + x <- .url_fetch(url_string) if (!length(x$info$`x-origin`)) { - x$info$`x-origin` <- list(url = url) + x$info$`x-origin` <- list(url = url_string) } as_rapid(x, ..., arg = arg, call = call) } diff --git a/man/as_rapid.Rd b/man/as_rapid.Rd index 289722d..cfa4712 100644 --- a/man/as_rapid.Rd +++ b/man/as_rapid.Rd @@ -9,7 +9,8 @@ as_rapid(x, ...) \arguments{ \item{x}{The object to coerce. Must be empty or have names "info" and/or "servers", or names that can be coerced to those names via -\code{\link[snakecase:caseconverter]{snakecase::to_snake_case()}}. Extra names are ignored.} +\code{\link[snakecase:caseconverter]{snakecase::to_snake_case()}}. Extra names are ignored. \code{\link[=url]{url()}} objects are +read with \code{\link[jsonlite:fromJSON]{jsonlite::fromJSON()}} or \code{\link[yaml:read_yaml]{yaml::read_yaml()}} before conversion.} \item{...}{These dots are for future extensions and must be empty.} } diff --git a/tests/testthat/_snaps/zz-rapid.md b/tests/testthat/_snaps/zz-rapid.md index 12984b5..a427f3b 100644 --- a/tests/testthat/_snaps/zz-rapid.md +++ b/tests/testthat/_snaps/zz-rapid.md @@ -117,11 +117,76 @@ ! `list(list("https://example.com", "A cool server."))` must have names "info", "servers", "components", or "security". * Any other names are ignored. -# as_rapid() works for urls +# as_rapid() works for yaml urls Code - suppressWarnings(as_rapid(url( - "https://api.apis.guru/v2/specs/amazonaws.com/AWSMigrationHub/2017-05-31/openapi.yaml"))) + test_result + Output + + @ info : + .. @ title : chr "AWS Migration Hub" + .. @ version : chr "2017-05-31" + .. @ contact : + .. .. @ name : chr "Mike Ralphson" + .. .. @ email: chr "mike.ralphson@gmail.com" + .. .. @ url : chr "https://github.com/mermade/aws2openapi" + .. @ description : chr "

The AWS Migration Hub API methods help to obtain server and application migration status and integrate your "| __truncated__ + .. @ license : + .. .. @ name : chr "Apache 2.0 License" + .. .. @ identifier: chr(0) + .. .. @ url : chr "http://www.apache.org/licenses/" + .. @ summary : chr(0) + .. @ terms_of_service: chr "https://aws.amazon.com/service-terms/" + .. @ origin : + .. .. @ url : chr "https://raw.githubusercontent.com/aws/aws-sdk-js/master/apis/AWSMigrationHub-2017-05-31.normal.json" + .. .. @ format : chr(0) + .. .. @ version: chr(0) + @ servers : + .. @ url : chr [1:4] "http://mgh.{region}.amazonaws.com" ... + .. @ description: chr [1:4] "The AWS Migration Hub multi-region endpoint" ... + .. @ variables : List of 4 + .. .. $ : + .. .. ..@ name : chr "region" + .. .. ..@ default : chr "us-east-1" + .. .. ..@ enum :List of 1 + .. .. .. .. $ : chr [1:23] "us-east-1" "us-east-2" "us-west-1" "us-west-2" ... + .. .. ..@ description: chr "The AWS region" + .. .. $ : + .. .. ..@ name : chr "region" + .. .. ..@ default : chr "us-east-1" + .. .. ..@ enum :List of 1 + .. .. .. .. $ : chr [1:23] "us-east-1" "us-east-2" "us-west-1" "us-west-2" ... + .. .. ..@ description: chr "The AWS region" + .. .. $ : + .. .. ..@ name : chr "region" + .. .. ..@ default : chr "cn-north-1" + .. .. ..@ enum :List of 1 + .. .. .. .. $ : chr [1:2] "cn-north-1" "cn-northwest-1" + .. .. ..@ description: chr "The AWS region" + .. .. $ : + .. .. ..@ name : chr "region" + .. .. ..@ default : chr "cn-north-1" + .. .. ..@ enum :List of 1 + .. .. .. .. $ : chr [1:2] "cn-north-1" "cn-northwest-1" + .. .. ..@ description: chr "The AWS region" + @ components: + .. @ security_schemes: + .. .. @ name : chr "hmac" + .. .. @ details : List of 1 + .. .. .. $ : + .. .. .. ..@ parameter_name: chr "Authorization" + .. .. .. ..@ location : chr "header" + .. .. @ description: chr "Amazon Signature authorization v4" + @ security : + .. @ name : chr "hmac" + .. @ required_scopes :List of 1 + .. .. $ : chr(0) + .. @ rapid_class_requirement: chr "security_scheme" + +# as_rapid() works for json urls + + Code + test_result Output @ info : @@ -187,7 +252,6 @@ # as_rapid() stores origin info for urls Code - test_result <- suppressWarnings(as_rapid(url(test_url))) test_result Output @@ -229,7 +293,7 @@ # as_rapid() works for empty optional fields Code - suppressWarnings(as_rapid(x)) + test_result Output @ info : diff --git a/tests/testthat/test-zz-rapid.R b/tests/testthat/test-zz-rapid.R index 643edda..8742513 100644 --- a/tests/testthat/test-zz-rapid.R +++ b/tests/testthat/test-zz-rapid.R @@ -213,65 +213,76 @@ test_that("as_rapid() works for lists", { ) }) -test_that("as_rapid() works for urls", { +test_that("as_rapid() works for yaml urls", { skip_if_not(Sys.getenv("RAPID_TEST_DL") == "true") - - expect_warning( + yaml_url <- "https://api.apis.guru/v2/specs/amazonaws.com/AWSMigrationHub/2017-05-31/openapi.yaml" + expect_warning(expect_warning( expect_warning( expect_warning( expect_warning( expect_warning( - expect_warning( - as_rapid( - url( - "https://api.apis.guru/v2/specs/amazonaws.com/AWSMigrationHub/2017-05-31/openapi.yaml" - ) - ), - "x_has_equivalent_paths", - class = "rapid_warning_extra_names" - ), - "x_release", + { + test_result <- as_rapid(url(yaml_url)) + }, + "x_has_equivalent_paths", class = "rapid_warning_extra_names" ), - "x_twitter", + "x_release", class = "rapid_warning_extra_names" ), - "parameters", + "x_twitter", class = "rapid_warning_extra_names" ), - "x_amazon_apigateway_authtype", + "parameters", class = "rapid_warning_extra_names" ), - "x_apisguru_driver", + "x_amazon_apigateway_authtype", class = "rapid_warning_extra_names" - ) + ), "x_apisguru_driver", class = "rapid_warning_extra_names") + expect_snapshot(test_result) +}) - expect_snapshot( - suppressWarnings(as_rapid( - url( - "https://api.apis.guru/v2/specs/amazonaws.com/AWSMigrationHub/2017-05-31/openapi.yaml" - ) - )) - ) +test_that("as_rapid() works for json urls", { + skip_if_not(Sys.getenv("RAPID_TEST_DL") == "true") + + json_url <- "https://api.apis.guru/v2/specs/amazonaws.com/AWSMigrationHub/2017-05-31/openapi.json" + expect_warning(expect_warning( + expect_warning( + expect_warning( + expect_warning( + expect_warning( + { + test_result <- as_rapid(url(json_url)) + }, + "x_has_equivalent_paths", + class = "rapid_warning_extra_names" + ), + "x_release", + class = "rapid_warning_extra_names" + ), + "x_twitter", + class = "rapid_warning_extra_names" + ), + "parameters", + class = "rapid_warning_extra_names" + ), + "x_amazon_apigateway_authtype", + class = "rapid_warning_extra_names" + ), "x_apisguru_driver", class = "rapid_warning_extra_names") + expect_snapshot(test_result) }) test_that("as_rapid() stores origin info for urls", { skip_if_not(Sys.getenv("RAPID_TEST_DL") == "true") - test_url <- "https://api.open.fec.gov/swagger/" - expect_warning( - as_rapid(url(test_url)), + { + test_result <- as_rapid(url(test_url)) + }, "swagger", class = "rapid_warning_extra_names" ) - - expect_snapshot({ - test_result <- suppressWarnings( - as_rapid(url(test_url)) - ) - test_result - }) + expect_snapshot(test_result) expect_identical(test_result@info@origin@url, test_url) }) @@ -288,7 +299,9 @@ test_that("as_rapid() works for empty optional fields", { expect_warning( expect_warning( expect_warning( - as_rapid(x), + { + test_result <- as_rapid(x) + }, "openapi", class = "rapid_warning_extra_names" ), @@ -302,7 +315,5 @@ test_that("as_rapid() works for empty optional fields", { class = "rapid_warning_extra_names" ) - expect_snapshot( - suppressWarnings(as_rapid(x)) - ) + expect_snapshot(test_result) })