diff --git a/DESCRIPTION b/DESCRIPTION index e9a56aa..c82ddbf 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -33,7 +33,8 @@ Suggests: rmarkdown, testthat, covr, - vcr (>= 0.6.0) + vcr (>= 0.6.0), + withr RoxygenNote: 7.3.1 X-schema.org-applicationCategory: Data Access X-schema.org-keywords: birds, birding, ebird, database, data, biology, observations, sightings, ornithology diff --git a/R/ebirdtaxonomy.R b/R/ebirdtaxonomy.R index a7f44c5..d505f08 100644 --- a/R/ebirdtaxonomy.R +++ b/R/ebirdtaxonomy.R @@ -17,6 +17,8 @@ #' See \url{https://docs.oracle.com/javase/6/docs/api/java/util/Locale.html} and #' \url{https://support.ebird.org/en/support/solutions/articles/48000804865-bird-names-in-ebird} #' (defaults to en_US). +#' @param species Character vector of eBird taxonomy species code(s). Limits query +#' results to only these taxa. Default is NULL, which does not limit taxa. #' @param key eBird API key. You can obtain one from https://ebird.org/api/keygen. #' We strongly recommend storing it in your \code{.Renviron} file as an #' environment variable called \code{EBIRD_KEY} to avoid having to constantly @@ -46,14 +48,18 @@ #' Sebastian Pardo \email{sebpardo@@gmail.com} #' @references \url{http://ebird.org/} -ebirdtaxonomy <- function(cat=NULL, locale=NULL, key = NULL, ...){ +ebirdtaxonomy <- function(cat=NULL, locale=NULL, species = NULL, key = NULL, ...){ cats <- c("domestic", "form", "hybrid", "intergrade", "issf", "slash", "species", "spuh") if (!all(vapply(cat, function(x) x %in% cats, FUN.VALUE = logical(1)))) { stop("You have supplied an invalid species category") } cat <- if(!is.null(cat)) cat <- paste0(cat, collapse = ",") - args <- list(fmt='json', cat=cat, locale=locale) + if (!is.null(species) && (length(species) == 0 || any(is.na(species)))){ + stop('Invalid species code(s)') + } + species <- if(!is.null(species)) species <- paste0(species, collapse = ",") + args <- list(fmt='json', cat=cat, locale=locale, species=species) # Allow not using a key for just this function, it's the only endpoint # that allows it diff --git a/man/ebirdtaxonomy.Rd b/man/ebirdtaxonomy.Rd index 5b4ac31..e613fd8 100644 --- a/man/ebirdtaxonomy.Rd +++ b/man/ebirdtaxonomy.Rd @@ -4,7 +4,7 @@ \alias{ebirdtaxonomy} \title{eBird Taxonomy} \usage{ -ebirdtaxonomy(cat = NULL, locale = NULL, key = NULL, ...) +ebirdtaxonomy(cat = NULL, locale = NULL, species = NULL, key = NULL, ...) } \arguments{ \item{cat}{Species category. String or character vector with one of more of: @@ -18,6 +18,9 @@ See \url{https://docs.oracle.com/javase/6/docs/api/java/util/Locale.html} and \url{https://support.ebird.org/en/support/solutions/articles/48000804865-bird-names-in-ebird} (defaults to en_US).} +\item{species}{Character vector of eBird taxonomy species code(s). Limits query +results to only these taxa. Default is NULL, which does not limit taxa.} + \item{key}{eBird API key. You can obtain one from https://ebird.org/api/keygen. We strongly recommend storing it in your \code{.Renviron} file as an environment variable called \code{EBIRD_KEY} to avoid having to constantly diff --git a/tests/fixtures/ebirdtaxonomy.yml b/tests/fixtures/ebirdtaxonomy.yml new file mode 100644 index 0000000..c98d894 --- /dev/null +++ b/tests/fixtures/ebirdtaxonomy.yml @@ -0,0 +1,120 @@ +http_interactions: +- request: + method: get + uri: https://ebird.org/ws2.0/ref/taxonomy/ebird?fmt=json&cat=domestic&species=btbwar%2Cmallar2%2Cgragoo1 + body: + encoding: '' + string: '' + headers: + Accept: application/json, text/xml, application/xml, */* + X-eBirdApiToken: <<>> + response: + status: + status_code: 200 + category: Success + reason: OK + message: 'Success: (200) OK' + headers: + cache-control: no-cache, no-store, max-age=0, must-revalidate + content-encoding: gzip + content-length: '297' + content-type: application/json;charset=utf-8 + date: Sat, 09 Mar 2024 04:35:17 GMT + expires: '0' + pragma: no-cache + server: Apache + strict-transport-security: max-age=31536000 ; includeSubDomains + vary: + - Accept-Encoding + - Accept-Encoding,Origin,Access-Control-Request-Method,Access-Control-Request-Headers + x-content-type-options: nosniff + x-frame-options: DENY + x-xss-protection: 1; mode=block + body: + encoding: '' + file: no + string: '[{"sciName":"Anser anser (Domestic type)","comName":"Graylag Goose + (Domestic type)","speciesCode":"gragoo1","category":"domestic","taxonOrder":266.0,"bandingCodes":[],"comNameCodes":["GRGO"],"sciNameCodes":["ANAN"],"order":"Anseriformes","familyCode":"anatid1","familyComName":"Ducks, + Geese, and Waterfowl","familySciName":"Anatidae","reportAs":"gragoo"},{"sciName":"Anas + platyrhynchos (Domestic type)","comName":"Mallard (Domestic type)","speciesCode":"mallar2","category":"domestic","taxonOrder":518.0,"bandingCodes":[],"comNameCodes":["MALL"],"sciNameCodes":["ANPL"],"order":"Anseriformes","familyCode":"anatid1","familyComName":"Ducks, + Geese, and Waterfowl","familySciName":"Anatidae","reportAs":"mallar3"}]' + recorded_at: 2024-03-09 04:38:56 GMT + recorded_with: vcr/1.2.2, webmockr/0.9.0 +- request: + method: get + uri: https://ebird.org/ws2.0/ref/taxonomy/ebird?fmt=json&cat=spuh%2Cslash&species=passer1%2Cbird1%2Camewoo%2Cy00335 + body: + encoding: '' + string: '' + headers: + Accept: application/json, text/xml, application/xml, */* + X-eBirdApiToken: <<>> + response: + status: + status_code: 200 + category: Success + reason: OK + message: 'Success: (200) OK' + headers: + cache-control: no-cache, no-store, max-age=0, must-revalidate + content-encoding: gzip + content-length: '312' + content-type: application/json;charset=utf-8 + date: Sat, 09 Mar 2024 04:35:17 GMT + expires: '0' + pragma: no-cache + server: Apache + strict-transport-security: max-age=31536000 ; includeSubDomains + vary: + - Accept-Encoding + - Accept-Encoding,Origin,Access-Control-Request-Method,Access-Control-Request-Headers + x-content-type-options: nosniff + x-frame-options: DENY + x-xss-protection: 1; mode=block + body: + encoding: '' + file: no + string: '[{"sciName":"Passerina amoena/cyanea","comName":"Lazuli/Indigo Bunting","speciesCode":"y00335","category":"slash","taxonOrder":34063.0,"bandingCodes":[],"comNameCodes":["LAZB","INBU","LABU"],"sciNameCodes":["PAAM","PACY"],"order":"Passeriformes","familyCode":"cardin1","familyComName":"Cardinals + and Allies","familySciName":"Cardinalidae"},{"sciName":"Passeriformes sp.","comName":"passerine + sp.","speciesCode":"passer1","category":"spuh","taxonOrder":35292.0,"bandingCodes":[],"comNameCodes":[],"sciNameCodes":[],"order":"Passeriformes"},{"sciName":"Aves + sp.","comName":"bird sp.","speciesCode":"bird1","category":"spuh","taxonOrder":35293.0,"bandingCodes":["UNBI"],"comNameCodes":[],"sciNameCodes":[]}]' + recorded_at: 2024-03-09 04:38:56 GMT + recorded_with: vcr/1.2.2, webmockr/0.9.0 +- request: + method: get + uri: https://ebird.org/ws2.0/ref/taxonomy/ebird?fmt=json&species=rewbla + body: + encoding: '' + string: '' + headers: + Accept: application/json, text/xml, application/xml, */* + X-eBirdApiToken: '' + response: + status: + status_code: 200 + category: Success + reason: OK + message: 'Success: (200) OK' + headers: + cache-control: no-cache, no-store, max-age=0, must-revalidate + content-encoding: gzip + content-length: '218' + content-type: application/json;charset=utf-8 + date: Sat, 09 Mar 2024 04:35:18 GMT + expires: '0' + pragma: no-cache + server: Apache + strict-transport-security: max-age=31536000 ; includeSubDomains + vary: + - Accept-Encoding + - Accept-Encoding,Origin,Access-Control-Request-Method,Access-Control-Request-Headers + x-content-type-options: nosniff + x-frame-options: DENY + x-xss-protection: 1; mode=block + body: + encoding: '' + file: no + string: '[{"sciName":"Agelaius phoeniceus","comName":"Red-winged Blackbird","speciesCode":"rewbla","category":"species","taxonOrder":33251.0,"bandingCodes":["RWBL"],"comNameCodes":[],"sciNameCodes":["AGPH"],"order":"Passeriformes","familyCode":"icteri1","familyComName":"Troupials + and Allies","familySciName":"Icteridae"}]' + recorded_at: 2024-03-09 04:38:56 GMT + recorded_with: vcr/1.2.2, webmockr/0.9.0 diff --git a/tests/testthat/test-ebirdtaxonomy.R b/tests/testthat/test-ebirdtaxonomy.R index 6877538..0e167b4 100644 --- a/tests/testthat/test-ebirdtaxonomy.R +++ b/tests/testthat/test-ebirdtaxonomy.R @@ -1,38 +1,38 @@ -context("ebirdtaxonomy") +vcr::use_cassette("ebirdtaxonomy", { + test_that("ebirdtaxonomy works correctly", { + out <- ebirdtaxonomy("domestic", species = c('btbwar', 'mallar2', 'gragoo1')) + expect_true(inherits(out, "data.frame")) + expect_true(inherits(out, "tbl_df")) + expect_equal(nrow(out), 2) -test_that("ebirdtaxonomy works correctly", { - skip_on_cran() - skip_on_ci() - - out <- ebirdtaxonomy("domestic") - out2 <- ebirdtaxonomy(cat=c("spuh", "slash")) - - expect_is(out, "data.frame") - expect_is(out, "tbl_df") - expect_is(out2, "data.frame") - expect_is(out2, "tbl_df") - - expect_is(out$comName, "character") - expect_is(out$taxonOrder, "numeric") -}) - -test_that("ebirdtaxonomy fails correctly", { - skip_on_cran() - skip_on_ci() - - mssg <- "You have supplied an invalid species category" - expect_error(ebirdtaxonomy("asf"), mssg) - expect_error(ebirdtaxonomy(2), mssg) - - expect_error(ebirdtaxonomy("spuh", config=timeout(0.02))) -}) + out2 <- ebirdtaxonomy(cat=c("spuh", "slash"), + species = c('passer1', 'bird1', 'amewoo', 'y00335')) + expect_equal(nrow(out2), 3) + expect_true(inherits(out2, "data.frame")) + expect_true(inherits(out2, "tbl_df")) + expect_true(inherits(out2$comName, "character")) + expect_true(inherits(out2$taxonOrder, "numeric")) + }) -test_that_without_key("ebirdtaxonomy works without an API key", { - skip_on_cran() - skip_on_ci() + test_that("ebirdtaxonomy fails correctly", { + mssg <- "You have supplied an invalid species category" + expect_error(ebirdtaxonomy("asf"), mssg) + expect_error(ebirdtaxonomy(2), mssg) + isc <- 'Invalid species code' + expect_error(ebirdtaxonomy(species = character(0)), isc) + expect_error(ebirdtaxonomy(species = NA_character_), isc) + }) - tax <- ebirdtaxonomy() - expect_is(tax, "data.frame") - expect_gte(ncol(tax), 12L) + test_that("ebirdtaxonomy works without an API key", { + withr::with_envvar( + c('EBIRD_KEY' = NA), + { + expect_equal(Sys.getenv('EBIRD_KEY'), "") + rwbl <- ebirdtaxonomy(species = 'rewbla') + expect_true(inherits(rwbl, "data.frame")) + expect_gte(ncol(rwbl), 12L) + expect_true(nrow(rwbl) == 1) + } + ) + }) }) -