From c848aae75b447b945a60686cd43c015274c2c289 Mon Sep 17 00:00:00 2001 From: Nicolas Casajus <10423581+ahasverus@users.noreply.github.com> Date: Sun, 24 May 2026 21:46:21 +0200 Subject: [PATCH] feat: implement, document and test fp_retrieve_article_doi() - fix #26 --- NAMESPACE | 1 + R/checks.R | 45 +++++ R/fp_retrieve_article_doi.R | 102 ++++++++++ R/utils.R | 12 ++ _pkgdown.yaml | 1 + man/fp_retrieve_article_doi.Rd | 54 ++++++ ...p_compute_citation_ratio_not_in_dafnee.yml | 36 ++-- .../fp_compute_citation_ratio_not_in_oa.yml | 16 +- .../_vcr/fp_compute_citation_ratio_works.yml | 96 ++++----- .../_vcr/fp_get_article_fairness_fp_acad.yml | 66 +++---- .../fp_get_article_fairness_fp_non_acad.yml | 183 +++++++++--------- .../fp_get_article_fairness_not_in_dafnee.yml | 44 ++--- .../fp_get_article_fairness_not_in_oa.yml | 18 +- .../_vcr/fp_get_article_fairness_np.yml | 72 +++---- .../_vcr/fp_retrieve_article_doi_error.yml | 39 ++++ .../fp_retrieve_article_doi_manymatches.yml | 152 +++++++++++++++ ...p_retrieve_article_doi_manymatches_w_n.yml | 125 ++++++++++++ .../_vcr/fp_retrieve_article_doi_nomatch.yml | 39 ++++ .../_vcr/fp_retrieve_article_doi_onematch.yml | 102 ++++++++++ tests/testthat/setup.R | 3 + tests/testthat/test-check_arg_n.R | 67 +++++++ tests/testthat/test-fp_retrieve_article_doi.R | 104 ++++++++++ tests/testthat/test-fp_shorten_string.R | 9 + 23 files changed, 1120 insertions(+), 266 deletions(-) create mode 100644 R/fp_retrieve_article_doi.R create mode 100644 man/fp_retrieve_article_doi.Rd create mode 100644 tests/testthat/_vcr/fp_retrieve_article_doi_error.yml create mode 100644 tests/testthat/_vcr/fp_retrieve_article_doi_manymatches.yml create mode 100644 tests/testthat/_vcr/fp_retrieve_article_doi_manymatches_w_n.yml create mode 100644 tests/testthat/_vcr/fp_retrieve_article_doi_nomatch.yml create mode 100644 tests/testthat/_vcr/fp_retrieve_article_doi_onematch.yml create mode 100644 tests/testthat/test-check_arg_n.R create mode 100644 tests/testthat/test-fp_retrieve_article_doi.R create mode 100644 tests/testthat/test-fp_shorten_string.R diff --git a/NAMESPACE b/NAMESPACE index dec8901..c69277a 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -6,3 +6,4 @@ export(fp_extract_doi) export(fp_get_article_fairness) export(fp_get_journal_fairness) export(fp_list_dafnee_journals) +export(fp_retrieve_article_doi) diff --git a/R/checks.R b/R/checks.R index be728ad..9e34adc 100644 --- a/R/checks.R +++ b/R/checks.R @@ -71,3 +71,48 @@ check_arg_string <- function(x) { invisible(NULL) } + + +#' @noRd +check_arg_n <- function(n) { + if (is.null(n)) { + stop("Argument 'n' is required", call. = FALSE) + } + + if (!is.numeric(n)) { + stop( + "Argument 'n' must be an integer", + call. = FALSE + ) + } + + if (length(n) != 1) { + stop( + "Argument 'n' must be of length 1", + call. = FALSE + ) + } + + if (!is.finite(n)) { + stop( + "Argument 'n' must be finite", + call. = FALSE + ) + } + + if (n %% 1 != 0) { + stop( + "Argument 'n' must be an integer", + call. = FALSE + ) + } + + if (n < 1 || n > 200) { + stop( + "Argument 'n' must be a positive integer between 1 and 200", + call. = FALSE + ) + } + + invisible(NULL) +} diff --git a/R/fp_retrieve_article_doi.R b/R/fp_retrieve_article_doi.R new file mode 100644 index 0000000..95bae2f --- /dev/null +++ b/R/fp_retrieve_article_doi.R @@ -0,0 +1,102 @@ +#' Retrieve the DOI of an article from OpenAlex +#' +#' @description +#' This function queries the OpenAlex bibliographic database +#' () to retrieve the DOI of an article based on its +#' title. +#' +#' @param title a `character` of length 1. The title of the article. +#' +#' @param n an `integer` of length 1. The number of results to return (between +#' 1 and 200). Default is `5`. +#' +#' @return A `data.frame` with the following columns: +#' - `display_name`, the publication titles matching the query +#' - `publication_year`, the year of publication +#' - `source_display_name`, the name of the journal +#' - `doi`, the DOI of the publications +#' +#' @export +#' +#' @examples +#' \dontrun{ +#' # Be polite and send your email to OpenAlex API ---- +#' options(openalexR.mailto = 'anonymous@mail.com') +#' +#' # Search for an full title ---- +#' fp_retrieve_article_doi( +#' "Citation self-awareness for a fairer academic publishing landscape" +#' ) +#' #> display_name publication_year +#' #> 1 Citation self-awareness for a fairer academic... 2026 +#' #> source_display_name doi +#' #> 1 BioScience 10.1093/biosci/biag028 +#' +#' # Search for a partial title ---- +#' fp_retrieve_article_doi( +#' "Citation fairer academic landscape" +#' ) +#' #> display_name publication_year +#' #> 1 Strategic citations for a fairer academic... 2025 +#' #> 2 Citation self-awareness for a fairer academic... 2026 +#' #> source_display_name doi +#' #> 1 bioRxiv (Cold Spring Harbor Laboratory) 10.1101/2025.08.06.668908 +#' #> 2 BioScience 10.1093/biosci/biag028 +#' } + +fp_retrieve_article_doi <- function(title, n = 5) { + fp_check_mailto() + + check_arg_string(title) + check_arg_n(n) + + meta <- tryCatch( + suppressMessages( + openalexR::oa_fetch( + entity = "works", + title.search = title, + per_page = n, + paging = "page", + pages = 1, + options = list( + sort = "relevance_score:desc", + select = c( + "doi", + "display_name", + "publication_year", + "primary_location" + ) + ) + ) + ), + error = function(e) { + stop( + "Failed to retrieve data from OpenAlex", + call. = FALSE + ) + } + ) + + meta <- as.data.frame(meta) + + if (nrow(meta) > 0) { + meta <- meta[, c( + "display_name", + "publication_year", + "source_display_name", + "doi" + )] + + meta$doi <- fp_clean_doi(meta$doi) + meta$display_name <- fp_shorten_string(meta$display_name) + } else { + meta <- data.frame( + display_name = character(), + publication_year = integer(), + source_display_name = character(), + doi = character() + ) + } + + meta +} diff --git a/R/utils.R b/R/utils.R index 024d566..ec2c439 100644 --- a/R/utils.R +++ b/R/utils.R @@ -43,3 +43,15 @@ fp_extract_doi_from_string <- function(x) { unlist(matches, use.names = FALSE) } + + +#' @noRd +fp_shorten_string <- function(x, width = 50) { + is_short <- nchar(x) <= width + + shortened <- substr(x, 1, width - 3) + shortened <- sub("\\s+\\S*$", "", shortened) + shortened <- paste0(shortened, "...") + + ifelse(is_short, x, shortened) +} diff --git a/_pkgdown.yaml b/_pkgdown.yaml index 6554f38..3f50929 100644 --- a/_pkgdown.yaml +++ b/_pkgdown.yaml @@ -17,6 +17,7 @@ reference: desc: | Functions to retrieve, extract and clean DOI. contents: + - fp_retrieve_article_doi - fp_extract_doi - fp_clean_doi diff --git a/man/fp_retrieve_article_doi.Rd b/man/fp_retrieve_article_doi.Rd new file mode 100644 index 0000000..9f9522e --- /dev/null +++ b/man/fp_retrieve_article_doi.Rd @@ -0,0 +1,54 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/fp_retrieve_article_doi.R +\name{fp_retrieve_article_doi} +\alias{fp_retrieve_article_doi} +\title{Retrieve the DOI of an article from OpenAlex} +\usage{ +fp_retrieve_article_doi(title, n = 5) +} +\arguments{ +\item{title}{a \code{character} of length 1. The title of the article.} + +\item{n}{an \code{integer} of length 1. The number of results to return (between +1 and 200). Default is \code{5}.} +} +\value{ +A \code{data.frame} with the following columns: +\itemize{ +\item \code{display_name}, the publication titles matching the query +\item \code{publication_year}, the year of publication +\item \code{source_display_name}, the name of the journal +\item \code{doi}, the DOI of the publications +} +} +\description{ +This function queries the OpenAlex bibliographic database +(\url{https://openalex.org}) to retrieve the DOI of an article based on its +title. +} +\examples{ +\dontrun{ +# Be polite and send your email to OpenAlex API ---- +options(openalexR.mailto = 'anonymous@mail.com') + +# Search for an full title ---- +fp_retrieve_article_doi( + "Citation self-awareness for a fairer academic publishing landscape" +) +#> display_name publication_year +#> 1 Citation self-awareness for a fairer academic... 2026 +#> source_display_name doi +#> 1 BioScience 10.1093/biosci/biag028 + +# Search for a partial title ---- +fp_retrieve_article_doi( + "Citation fairer academic landscape" +) +#> display_name publication_year +#> 1 Strategic citations for a fairer academic... 2025 +#> 2 Citation self-awareness for a fairer academic... 2026 +#> source_display_name doi +#> 1 bioRxiv (Cold Spring Harbor Laboratory) 10.1101/2025.08.06.668908 +#> 2 BioScience 10.1093/biosci/biag028 +} +} diff --git a/tests/testthat/_vcr/fp_compute_citation_ratio_not_in_dafnee.yml b/tests/testthat/_vcr/fp_compute_citation_ratio_not_in_dafnee.yml index 87a6891..d7f560b 100644 --- a/tests/testthat/_vcr/fp_compute_citation_ratio_not_in_dafnee.yml +++ b/tests/testthat/_vcr/fp_compute_citation_ratio_not_in_dafnee.yml @@ -5,9 +5,9 @@ http_interactions: response: status: 200 headers: - date: Sun, 24 May 2026 08:50:23 GMT + date: Sun, 24 May 2026 19:44:31 GMT content-type: application/json - cf-ray: a00b0d6dfc2ca26a-MRS + cf-ray: a00ecba14d9a6cf5-MRS cf-cache-status: DYNAMIC access-control-allow-origin: '*' server: cloudflare @@ -16,24 +16,24 @@ http_interactions: Content-Type access-control-allow-methods: GET, HEAD, POST, OPTIONS nel: '{"report_to":"heroku-nel","response_headers":["Via"],"max_age":3600,"success_fraction":0.01,"failure_fraction":0.1}' - report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=IzketT9t%2BpEqDndNscV7Fwj14yBEmOozplfe0%2BJRBvQ%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779612623"}],"max_age":3600}' - reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=IzketT9t%2BpEqDndNscV7Fwj14yBEmOozplfe0%2BJRBvQ%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779612623" + report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=jMexQeBJFdOk8EJmpNUYorqL47IS%2BUTibGl0ghaLMZA%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779651870"}],"max_age":3600}' + reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=jMexQeBJFdOk8EJmpNUYorqL47IS%2BUTibGl0ghaLMZA%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779651870" x-ratelimit-cost-usd: '0.0001' x-ratelimit-credits-used: '1' x-ratelimit-limit: '10000' x-ratelimit-limit-usd: '1' x-ratelimit-onetime-remaining: '0' x-ratelimit-prepaid-remaining-usd: '0' - x-ratelimit-remaining: '9937' - x-ratelimit-remaining-usd: '0.9937' - x-ratelimit-reset: '54577' + x-ratelimit-remaining: '9544' + x-ratelimit-remaining-usd: '0.9544' + x-ratelimit-reset: '15329' access-control-expose-headers: Cache-Control, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Onetime-Remaining, X-RateLimit-Credits-Used, X-RateLimit-Credits-Required, X-RateLimit-Reset, X-RateLimit-Limit-USD, X-RateLimit-Remaining-USD, X-RateLimit-Prepaid-Remaining-USD, X-RateLimit-Cost-USD, X-RateLimit-Cost-Required-USD, Retry-After content-encoding: br body: - string: '{"meta": {"count": 1, "db_response_time_ms": 23, "page": 1, "per_page": + string: '{"meta": {"count": 1, "db_response_time_ms": 21, "page": 1, "per_page": 1, "groups_count": null, "cost_usd": 0.0001}, "results": [{"id": "https://openalex.org/W4393830903", "doi": "https://doi.org/10.5281/zenodo.7390791", "title": "The FORCIS database: A global census of planktonic Foraminifera from ocean waters", "display_name": @@ -483,16 +483,16 @@ http_interactions: [352], "number.": [353]}, "counts_by_year": [{"year": 2024, "cited_by_count": 1}, {"year": 2023, "cited_by_count": 1}], "updated_date": "2026-05-07T13:39:58.223016", "created_date": "2025-10-10T00:00:00"}], "group_by": []}' - recorded_at: 2026-05-24 08:50:23 + recorded_at: 2026-05-24 19:44:31 - request: method: GET uri: https://api.openalex.org/works?filter=doi%3A10.5281%2Fzenodo.7390791&per-page=200&mailto=anonymous%40mail.com&cursor=%2A response: status: 200 headers: - date: Sun, 24 May 2026 08:50:24 GMT + date: Sun, 24 May 2026 19:44:31 GMT content-type: application/json - cf-ray: a00b0d713a13a26a-MRS + cf-ray: a00ecba3ff296cf5-MRS cf-cache-status: DYNAMIC access-control-allow-origin: '*' server: cloudflare @@ -501,24 +501,24 @@ http_interactions: Content-Type access-control-allow-methods: GET, HEAD, POST, OPTIONS nel: '{"report_to":"heroku-nel","response_headers":["Via"],"max_age":3600,"success_fraction":0.01,"failure_fraction":0.1}' - report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=IzketT9t%2BpEqDndNscV7Fwj14yBEmOozplfe0%2BJRBvQ%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779612623"}],"max_age":3600}' - reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=IzketT9t%2BpEqDndNscV7Fwj14yBEmOozplfe0%2BJRBvQ%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779612623" + report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=SnJQChtc3RS4p87ujD7GF2OIJ7UoA7qy%2BDLCK%2BwnmFk%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779651871"}],"max_age":3600}' + reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=SnJQChtc3RS4p87ujD7GF2OIJ7UoA7qy%2BDLCK%2BwnmFk%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779651871" x-ratelimit-cost-usd: '0.0001' x-ratelimit-credits-used: '1' x-ratelimit-limit: '10000' x-ratelimit-limit-usd: '1' x-ratelimit-onetime-remaining: '0' x-ratelimit-prepaid-remaining-usd: '0' - x-ratelimit-remaining: '9936' - x-ratelimit-remaining-usd: '0.9936' - x-ratelimit-reset: '54576' + x-ratelimit-remaining: '9543' + x-ratelimit-remaining-usd: '0.9543' + x-ratelimit-reset: '15329' access-control-expose-headers: Cache-Control, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Onetime-Remaining, X-RateLimit-Credits-Used, X-RateLimit-Credits-Required, X-RateLimit-Reset, X-RateLimit-Limit-USD, X-RateLimit-Remaining-USD, X-RateLimit-Prepaid-Remaining-USD, X-RateLimit-Cost-USD, X-RateLimit-Cost-Required-USD, Retry-After content-encoding: br body: - string: '{"meta": {"count": 1, "db_response_time_ms": 29, "page": null, "per_page": + string: '{"meta": {"count": 1, "db_response_time_ms": 38, "page": null, "per_page": 200, "next_cursor": null, "groups_count": null, "cost_usd": 0.0001}, "results": [{"id": "https://openalex.org/W4393830903", "doi": "https://doi.org/10.5281/zenodo.7390791", "title": "The FORCIS database: A global census of planktonic Foraminifera @@ -968,5 +968,5 @@ http_interactions: [352], "number.": [353]}, "counts_by_year": [{"year": 2024, "cited_by_count": 1}, {"year": 2023, "cited_by_count": 1}], "updated_date": "2026-05-07T13:39:58.223016", "created_date": "2025-10-10T00:00:00"}], "group_by": []}' - recorded_at: 2026-05-24 08:50:24 + recorded_at: 2026-05-24 19:44:31 recorded_with: VCR-vcr/2.1.0 diff --git a/tests/testthat/_vcr/fp_compute_citation_ratio_not_in_oa.yml b/tests/testthat/_vcr/fp_compute_citation_ratio_not_in_oa.yml index 220d80e..e735266 100644 --- a/tests/testthat/_vcr/fp_compute_citation_ratio_not_in_oa.yml +++ b/tests/testthat/_vcr/fp_compute_citation_ratio_not_in_oa.yml @@ -5,9 +5,9 @@ http_interactions: response: status: 200 headers: - date: Sun, 24 May 2026 08:50:22 GMT + date: Sun, 24 May 2026 19:44:30 GMT content-type: application/json - cf-ray: a00b0d698b55a26a-MRS + cf-ray: a00ecb9ecc166cf5-MRS cf-cache-status: DYNAMIC access-control-allow-origin: '*' server: cloudflare @@ -16,17 +16,17 @@ http_interactions: Content-Type access-control-allow-methods: GET, HEAD, POST, OPTIONS nel: '{"report_to":"heroku-nel","response_headers":["Via"],"max_age":3600,"success_fraction":0.01,"failure_fraction":0.1}' - report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=NilQfiuH0FfLgvtkUaWDbbKYYcZoe8H57cNzEmYwwnU%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779612622"}],"max_age":3600}' - reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=NilQfiuH0FfLgvtkUaWDbbKYYcZoe8H57cNzEmYwwnU%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779612622" + report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=jMexQeBJFdOk8EJmpNUYorqL47IS%2BUTibGl0ghaLMZA%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779651870"}],"max_age":3600}' + reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=jMexQeBJFdOk8EJmpNUYorqL47IS%2BUTibGl0ghaLMZA%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779651870" x-ratelimit-cost-usd: '0.0001' x-ratelimit-credits-used: '1' x-ratelimit-limit: '10000' x-ratelimit-limit-usd: '1' x-ratelimit-onetime-remaining: '0' x-ratelimit-prepaid-remaining-usd: '0' - x-ratelimit-remaining: '9938' - x-ratelimit-remaining-usd: '0.9938' - x-ratelimit-reset: '54578' + x-ratelimit-remaining: '9545' + x-ratelimit-remaining-usd: '0.9545' + x-ratelimit-reset: '15330' access-control-expose-headers: Cache-Control, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Onetime-Remaining, X-RateLimit-Credits-Used, X-RateLimit-Credits-Required, X-RateLimit-Reset, X-RateLimit-Limit-USD, X-RateLimit-Remaining-USD, X-RateLimit-Prepaid-Remaining-USD, @@ -35,5 +35,5 @@ http_interactions: body: string: '{"meta": {"count": 0, "db_response_time_ms": 7, "page": 1, "per_page": 1, "groups_count": null, "cost_usd": 0.0001}, "results": [], "group_by": []}' - recorded_at: 2026-05-24 08:50:22 + recorded_at: 2026-05-24 19:44:30 recorded_with: VCR-vcr/2.1.0 diff --git a/tests/testthat/_vcr/fp_compute_citation_ratio_works.yml b/tests/testthat/_vcr/fp_compute_citation_ratio_works.yml index d04b899..f13cacd 100644 --- a/tests/testthat/_vcr/fp_compute_citation_ratio_works.yml +++ b/tests/testthat/_vcr/fp_compute_citation_ratio_works.yml @@ -5,9 +5,9 @@ http_interactions: response: status: 200 headers: - date: Sun, 24 May 2026 08:50:24 GMT + date: Sun, 24 May 2026 19:44:32 GMT content-type: application/json - cf-ray: a00b0d764c0ca26a-MRS + cf-ray: a00ecba739236cf5-MRS cf-cache-status: DYNAMIC access-control-allow-origin: '*' server: cloudflare @@ -16,24 +16,24 @@ http_interactions: Content-Type access-control-allow-methods: GET, HEAD, POST, OPTIONS nel: '{"report_to":"heroku-nel","response_headers":["Via"],"max_age":3600,"success_fraction":0.01,"failure_fraction":0.1}' - report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=CG6tpDI8MvwN8e7AciFYXoZqAjnqempTX4VvrehiQCg%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779612624"}],"max_age":3600}' - reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=CG6tpDI8MvwN8e7AciFYXoZqAjnqempTX4VvrehiQCg%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779612624" + report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=SnJQChtc3RS4p87ujD7GF2OIJ7UoA7qy%2BDLCK%2BwnmFk%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779651871"}],"max_age":3600}' + reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=SnJQChtc3RS4p87ujD7GF2OIJ7UoA7qy%2BDLCK%2BwnmFk%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779651871" x-ratelimit-cost-usd: '0.0001' x-ratelimit-credits-used: '1' x-ratelimit-limit: '10000' x-ratelimit-limit-usd: '1' x-ratelimit-onetime-remaining: '0' x-ratelimit-prepaid-remaining-usd: '0' - x-ratelimit-remaining: '9935' - x-ratelimit-remaining-usd: '0.9935' - x-ratelimit-reset: '54576' + x-ratelimit-remaining: '9542' + x-ratelimit-remaining-usd: '0.9542' + x-ratelimit-reset: '15328' access-control-expose-headers: Cache-Control, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Onetime-Remaining, X-RateLimit-Credits-Used, X-RateLimit-Credits-Required, X-RateLimit-Reset, X-RateLimit-Limit-USD, X-RateLimit-Remaining-USD, X-RateLimit-Prepaid-Remaining-USD, X-RateLimit-Cost-USD, X-RateLimit-Cost-Required-USD, Retry-After content-encoding: br body: - string: '{"meta": {"count": 4, "db_response_time_ms": 46, "page": 1, "per_page": + string: '{"meta": {"count": 4, "db_response_time_ms": 22, "page": 1, "per_page": 1, "groups_count": null, "cost_usd": 0.0001}, "results": [{"id": "https://openalex.org/W2162348455", "doi": "https://doi.org/10.1038/35002501", "title": "Biodiversity hotspots for conservation priorities", "display_name": "Biodiversity hotspots for conservation @@ -106,7 +106,7 @@ http_interactions: 5, "corresponding_author_ids": ["https://openalex.org/A5109070857"], "corresponding_institution_ids": ["https://openalex.org/I40120149"], "apc_list": {"value": 9750, "currency": "EUR", "value_usd": 11690}, "apc_paid": null, "fwci": 506.2763, "has_fulltext": - false, "cited_by_count": 31038, "citation_normalized_percentile": {"value": + false, "cited_by_count": 31040, "citation_normalized_percentile": {"value": 1.0, "is_in_top_1_percent": true, "is_in_top_10_percent": true}, "cited_by_percentile_year": {"min": 99, "max": 100}, "biblio": {"volume": "403", "issue": "6772", "first_page": "853", "last_page": "858"}, "is_retracted": false, "is_paratext": false, "is_xpac": @@ -270,8 +270,8 @@ http_interactions: "awards": [], "funders": [{"id": "https://openalex.org/F4320306142", "display_name": "John D. and Catherine T. MacArthur Foundation", "ror": "https://ror.org/00dxczh48"}, {"id": "https://openalex.org/F4320323161", "display_name": "WWF International", - "ror": "https://ror.org/00ppaw753"}], "has_content": {"grobid_xml": false, - "pdf": false}, "content_urls": null, "referenced_works_count": 230, "referenced_works": + "ror": "https://ror.org/00ppaw753"}], "has_content": {"pdf": false, "grobid_xml": + false}, "content_urls": null, "referenced_works_count": 230, "referenced_works": ["https://openalex.org/W22843948", "https://openalex.org/W32719449", "https://openalex.org/W38423605", "https://openalex.org/W46166763", "https://openalex.org/W89943346", "https://openalex.org/W117453349", "https://openalex.org/W146764914", "https://openalex.org/W197913869", "https://openalex.org/W213495198", @@ -353,25 +353,25 @@ http_interactions: "https://openalex.org/W1888713647", "https://openalex.org/W4384207523", "https://openalex.org/W2107551382", "https://openalex.org/W2157912707", "https://openalex.org/W4212786172", "https://openalex.org/W2148001066", "https://openalex.org/W2162348455"], "abstract_inverted_index": null, "counts_by_year": - [{"year": 2026, "cited_by_count": 588}, {"year": 2025, "cited_by_count": 1796}, + [{"year": 2026, "cited_by_count": 589}, {"year": 2025, "cited_by_count": 1796}, {"year": 2024, "cited_by_count": 1794}, {"year": 2023, "cited_by_count": 1973}, - {"year": 2022, "cited_by_count": 2005}, {"year": 2021, "cited_by_count": 2184}, + {"year": 2022, "cited_by_count": 2005}, {"year": 2021, "cited_by_count": 2185}, {"year": 2020, "cited_by_count": 2048}, {"year": 2019, "cited_by_count": 1752}, {"year": 2018, "cited_by_count": 1602}, {"year": 2017, "cited_by_count": 1533}, {"year": 2016, "cited_by_count": 1558}, {"year": 2015, "cited_by_count": 1417}, {"year": 2014, "cited_by_count": 1465}, {"year": 2013, "cited_by_count": 1424}, - {"year": 2012, "cited_by_count": 1216}], "updated_date": "2026-05-23T08:51:43.019350", + {"year": 2012, "cited_by_count": 1216}], "updated_date": "2026-05-24T08:33:08.758527", "created_date": "2025-10-10T00:00:00"}], "group_by": []}' - recorded_at: 2026-05-24 08:50:24 + recorded_at: 2026-05-24 19:44:32 - request: method: GET uri: https://api.openalex.org/works?filter=doi%3A10.1126%2Fscience.162.3859.1243%7C10.1038%2F35002501%7C10.1111%2Fj.1461-0248.2005.00792.x%7C10.xxxx%2Fxxxx%7C10.21105%2Fjoss.09217&per-page=200&mailto=anonymous%40mail.com&cursor=%2A response: status: 200 headers: - date: Sun, 24 May 2026 08:50:25 GMT + date: Sun, 24 May 2026 19:44:32 GMT content-type: application/json - cf-ray: a00b0d7b0d0ea26a-MRS + cf-ray: a00ecba9dacc6cf5-MRS cf-cache-status: DYNAMIC access-control-allow-origin: '*' server: cloudflare @@ -380,24 +380,24 @@ http_interactions: Content-Type access-control-allow-methods: GET, HEAD, POST, OPTIONS nel: '{"report_to":"heroku-nel","response_headers":["Via"],"max_age":3600,"success_fraction":0.01,"failure_fraction":0.1}' - report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=4xwnYpyT73p4PS1C7h9VbrlukNcFhlY6Yto2cYF4hXM%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779612625"}],"max_age":3600}' - reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=4xwnYpyT73p4PS1C7h9VbrlukNcFhlY6Yto2cYF4hXM%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779612625" + report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=h2BEBQA8fRs1D%2FxIZl3v4FO%2BIoSGR7g5ufYWSW5A7UA%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779651872"}],"max_age":3600}' + reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=h2BEBQA8fRs1D%2FxIZl3v4FO%2BIoSGR7g5ufYWSW5A7UA%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779651872" x-ratelimit-cost-usd: '0.0001' x-ratelimit-credits-used: '1' x-ratelimit-limit: '10000' x-ratelimit-limit-usd: '1' x-ratelimit-onetime-remaining: '0' x-ratelimit-prepaid-remaining-usd: '0' - x-ratelimit-remaining: '9934' - x-ratelimit-remaining-usd: '0.9934' - x-ratelimit-reset: '54575' + x-ratelimit-remaining: '9541' + x-ratelimit-remaining-usd: '0.9541' + x-ratelimit-reset: '15328' access-control-expose-headers: Cache-Control, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Onetime-Remaining, X-RateLimit-Credits-Used, X-RateLimit-Credits-Required, X-RateLimit-Reset, X-RateLimit-Limit-USD, X-RateLimit-Remaining-USD, X-RateLimit-Prepaid-Remaining-USD, X-RateLimit-Cost-USD, X-RateLimit-Cost-Required-USD, Retry-After content-encoding: br body: - string: '{"meta": {"count": 4, "db_response_time_ms": 41, "page": null, "per_page": + string: '{"meta": {"count": 4, "db_response_time_ms": 14, "page": null, "per_page": 200, "next_cursor": null, "groups_count": null, "cost_usd": 0.0001}, "results": [{"id": "https://openalex.org/W2162348455", "doi": "https://doi.org/10.1038/35002501", "title": "Biodiversity hotspots for conservation priorities", "display_name": @@ -470,7 +470,7 @@ http_interactions: 5, "corresponding_author_ids": ["https://openalex.org/A5109070857"], "corresponding_institution_ids": ["https://openalex.org/I40120149"], "apc_list": {"value": 9750, "currency": "EUR", "value_usd": 11690}, "apc_paid": null, "fwci": 506.2763, "has_fulltext": - false, "cited_by_count": 31038, "citation_normalized_percentile": {"value": + false, "cited_by_count": 31040, "citation_normalized_percentile": {"value": 1.0, "is_in_top_1_percent": true, "is_in_top_10_percent": true}, "cited_by_percentile_year": {"min": 99, "max": 100}, "biblio": {"volume": "403", "issue": "6772", "first_page": "853", "last_page": "858"}, "is_retracted": false, "is_paratext": false, "is_xpac": @@ -629,13 +629,13 @@ http_interactions: "host_organization_lineage": [], "host_organization_lineage_names": [], "type": "repository"}, "license": null, "license_id": null, "version": "submittedVersion", "is_accepted": false, "is_published": false, "raw_source_name": null, "raw_type": - "JournalArticle"}, "sustainable_development_goals": [{"id": "https://metadata.un.org/sdg/15", - "display_name": "Life in Land", "score": 0.5600000023841858}], "awards": [], - "funders": [{"id": "https://openalex.org/F4320306142", "display_name": "John - D. and Catherine T. MacArthur Foundation", "ror": "https://ror.org/00dxczh48"}, + "JournalArticle"}, "sustainable_development_goals": [{"display_name": "Life + in Land", "score": 0.5600000023841858, "id": "https://metadata.un.org/sdg/15"}], + "awards": [], "funders": [{"id": "https://openalex.org/F4320306142", "display_name": + "John D. and Catherine T. MacArthur Foundation", "ror": "https://ror.org/00dxczh48"}, {"id": "https://openalex.org/F4320323161", "display_name": "WWF International", - "ror": "https://ror.org/00ppaw753"}], "has_content": {"pdf": false, "grobid_xml": - false}, "content_urls": null, "referenced_works_count": 230, "referenced_works": + "ror": "https://ror.org/00ppaw753"}], "has_content": {"grobid_xml": false, + "pdf": false}, "content_urls": null, "referenced_works_count": 230, "referenced_works": ["https://openalex.org/W22843948", "https://openalex.org/W32719449", "https://openalex.org/W38423605", "https://openalex.org/W46166763", "https://openalex.org/W89943346", "https://openalex.org/W117453349", "https://openalex.org/W146764914", "https://openalex.org/W197913869", "https://openalex.org/W213495198", @@ -717,14 +717,14 @@ http_interactions: "https://openalex.org/W1888713647", "https://openalex.org/W4384207523", "https://openalex.org/W2107551382", "https://openalex.org/W2157912707", "https://openalex.org/W4212786172", "https://openalex.org/W2148001066", "https://openalex.org/W2162348455"], "abstract_inverted_index": null, "counts_by_year": - [{"year": 2026, "cited_by_count": 588}, {"year": 2025, "cited_by_count": 1796}, + [{"year": 2026, "cited_by_count": 589}, {"year": 2025, "cited_by_count": 1796}, {"year": 2024, "cited_by_count": 1794}, {"year": 2023, "cited_by_count": 1973}, - {"year": 2022, "cited_by_count": 2005}, {"year": 2021, "cited_by_count": 2184}, + {"year": 2022, "cited_by_count": 2005}, {"year": 2021, "cited_by_count": 2185}, {"year": 2020, "cited_by_count": 2048}, {"year": 2019, "cited_by_count": 1752}, {"year": 2018, "cited_by_count": 1602}, {"year": 2017, "cited_by_count": 1533}, {"year": 2016, "cited_by_count": 1558}, {"year": 2015, "cited_by_count": 1417}, {"year": 2014, "cited_by_count": 1465}, {"year": 2013, "cited_by_count": 1424}, - {"year": 2012, "cited_by_count": 1216}], "updated_date": "2026-05-23T08:51:43.019350", + {"year": 2012, "cited_by_count": 1216}], "updated_date": "2026-05-24T08:33:08.758527", "created_date": "2025-10-10T00:00:00"}, {"id": "https://openalex.org/W2226396244", "doi": "https://doi.org/10.1126/science.162.3859.1243", "title": "The Tragedy of the Commons", "display_name": "The Tragedy of the Commons", "publication_year": @@ -761,8 +761,8 @@ http_interactions: ["https://openalex.org/I1311206647"]}]}], "institutions": [], "countries_distinct_count": 1, "institutions_distinct_count": 1, "corresponding_author_ids": ["https://openalex.org/A5111448232"], "corresponding_institution_ids": ["https://openalex.org/I1311206647"], "apc_list": - null, "apc_paid": null, "fwci": 276.052, "has_fulltext": false, "cited_by_count": - 22830, "citation_normalized_percentile": {"value": 1.0, "is_in_top_1_percent": + null, "apc_paid": null, "fwci": 276.0638, "has_fulltext": false, "cited_by_count": + 22834, "citation_normalized_percentile": {"value": 1.0, "is_in_top_1_percent": true, "is_in_top_10_percent": true}, "cited_by_percentile_year": {"min": 99, "max": 100}, "biblio": {"volume": "162", "issue": "3859", "first_page": "1243", "last_page": "1248"}, "is_retracted": false, "is_paratext": false, "is_xpac": @@ -850,9 +850,9 @@ http_interactions: "host_organization_lineage_names": [], "type": "repository"}, "license": null, "license_id": null, "version": "publishedVersion", "is_accepted": true, "is_published": true, "raw_source_name": "Science (New York, N.Y.)", "raw_type": null}], "best_oa_location": - null, "sustainable_development_goals": [{"id": "https://metadata.un.org/sdg/16", - "display_name": "Peace, Justice and strong institutions", "score": 0.4300000071525574}], - "awards": [], "funders": [], "has_content": {"pdf": false, "grobid_xml": false}, + null, "sustainable_development_goals": [{"display_name": "Peace, Justice and + strong institutions", "score": 0.4300000071525574, "id": "https://metadata.un.org/sdg/16"}], + "awards": [], "funders": [], "has_content": {"grobid_xml": false, "pdf": false}, "content_urls": null, "referenced_works_count": 16, "referenced_works": ["https://openalex.org/W645218623", "https://openalex.org/W1520891760", "https://openalex.org/W1546755579", "https://openalex.org/W1967161129", "https://openalex.org/W2027636702", "https://openalex.org/W2029363644", "https://openalex.org/W2054383667", @@ -866,14 +866,14 @@ http_interactions: {"The": [0], "population": [1], "problem": [2], "has": [3], "no": [4], "technical": [5], "solution;": [6], "it": [7], "requires": [8], "a": [9], "fundamental": [10], "extension": [11], "in": [12], "morality.": [13]}, "counts_by_year": - [{"year": 2026, "cited_by_count": 306}, {"year": 2025, "cited_by_count": 830}, + [{"year": 2026, "cited_by_count": 307}, {"year": 2025, "cited_by_count": 831}, {"year": 2024, "cited_by_count": 914}, {"year": 2023, "cited_by_count": 860}, {"year": 2022, "cited_by_count": 898}, {"year": 2021, "cited_by_count": 1169}, {"year": 2020, "cited_by_count": 1230}, {"year": 2019, "cited_by_count": 1132}, - {"year": 2018, "cited_by_count": 1048}, {"year": 2017, "cited_by_count": 969}, + {"year": 2018, "cited_by_count": 1049}, {"year": 2017, "cited_by_count": 969}, {"year": 2016, "cited_by_count": 956}, {"year": 2015, "cited_by_count": 909}, - {"year": 2014, "cited_by_count": 1013}, {"year": 2013, "cited_by_count": 921}, - {"year": 2012, "cited_by_count": 889}], "updated_date": "2026-05-23T08:51:43.019350", + {"year": 2014, "cited_by_count": 1014}, {"year": 2013, "cited_by_count": 921}, + {"year": 2012, "cited_by_count": 889}], "updated_date": "2026-05-24T08:33:08.758527", "created_date": "2016-06-24T00:00:00"}, {"id": "https://openalex.org/W2123337039", "doi": "https://doi.org/10.1111/j.1461-0248.2005.00792.x", "title": "Predicting species distribution: offering more than simple habitat models", "display_name": @@ -1078,9 +1078,9 @@ http_interactions: [], "host_organization_lineage_names": [], "type": "repository"}, "license": null, "license_id": null, "version": "submittedVersion", "is_accepted": false, "is_published": false, "raw_source_name": null, "raw_type": "JournalArticle"}, - "sustainable_development_goals": [{"id": "https://metadata.un.org/sdg/13", - "display_name": "Climate action", "score": 0.4399999976158142}], "awards": - [], "funders": [], "has_content": {"pdf": false, "grobid_xml": false}, "content_urls": + "sustainable_development_goals": [{"display_name": "Climate action", "score": + 0.4399999976158142, "id": "https://metadata.un.org/sdg/13"}], "awards": [], + "funders": [], "has_content": {"grobid_xml": false, "pdf": false}, "content_urls": null, "referenced_works_count": 125, "referenced_works": ["https://openalex.org/W221484134", "https://openalex.org/W228375214", "https://openalex.org/W276691513", "https://openalex.org/W1503026800", "https://openalex.org/W1519918296", "https://openalex.org/W1535048244", "https://openalex.org/W1552647955", @@ -1432,12 +1432,12 @@ http_interactions: f\u00fcr Chemie", "ror": "https://ror.org/02f5b7n18"}, {"id": "https://openalex.org/F4320335598", "display_name": "Agencia Estatal de Investigaci\u00f3n", "ror": null}, {"id": "https://openalex.org/F4320338223", "display_name": "Direcci\u00f3 General - de Recerca, Generalitat de Catalunya", "ror": null}], "has_content": {"pdf": - true, "grobid_xml": false}, "content_urls": {"pdf": "https://content.openalex.org/works/W4415113473.pdf"}, + de Recerca, Generalitat de Catalunya", "ror": null}], "has_content": {"grobid_xml": + false, "pdf": true}, "content_urls": {"pdf": "https://content.openalex.org/works/W4415113473.pdf"}, "referenced_works_count": 3, "referenced_works": ["https://openalex.org/W4229082123", "https://openalex.org/W4379259280", "https://openalex.org/W4404305647"], "related_works": [], "abstract_inverted_index": {"International": [0], "audience": [1]}, "counts_by_year": [], "updated_date": "2026-05-07T13:39:58.223016", "created_date": "2025-10-14T00:00:00"}], "group_by": []}' - recorded_at: 2026-05-24 08:50:25 + recorded_at: 2026-05-24 19:44:32 recorded_with: VCR-vcr/2.1.0 diff --git a/tests/testthat/_vcr/fp_get_article_fairness_fp_acad.yml b/tests/testthat/_vcr/fp_get_article_fairness_fp_acad.yml index 50050a5..0f474aa 100644 --- a/tests/testthat/_vcr/fp_get_article_fairness_fp_acad.yml +++ b/tests/testthat/_vcr/fp_get_article_fairness_fp_acad.yml @@ -5,9 +5,9 @@ http_interactions: response: status: 200 headers: - date: Sun, 24 May 2026 08:50:27 GMT + date: Sun, 24 May 2026 19:44:35 GMT content-type: application/json - cf-ray: a00b0d8a3a02a26a-MRS + cf-ray: a00ecbb9bca66cf5-MRS cf-cache-status: DYNAMIC access-control-allow-origin: '*' server: cloudflare @@ -16,24 +16,24 @@ http_interactions: Content-Type access-control-allow-methods: GET, HEAD, POST, OPTIONS nel: '{"report_to":"heroku-nel","response_headers":["Via"],"max_age":3600,"success_fraction":0.01,"failure_fraction":0.1}' - report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=NQ6dlv6030jIxYibePSHS5K3luCQWjiKCIGcV78lCe8%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779612627"}],"max_age":3600}' - reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=NQ6dlv6030jIxYibePSHS5K3luCQWjiKCIGcV78lCe8%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779612627" + report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=j4g6Ox3SRV8RC4BPrKC6MpmkLVz93NCIRlGA2AbjfSE%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779651874"}],"max_age":3600}' + reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=j4g6Ox3SRV8RC4BPrKC6MpmkLVz93NCIRlGA2AbjfSE%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779651874" x-ratelimit-cost-usd: '0.0001' x-ratelimit-credits-used: '1' x-ratelimit-limit: '10000' x-ratelimit-limit-usd: '1' x-ratelimit-onetime-remaining: '0' x-ratelimit-prepaid-remaining-usd: '0' - x-ratelimit-remaining: '9929' - x-ratelimit-remaining-usd: '0.9929' - x-ratelimit-reset: '54573' + x-ratelimit-remaining: '9536' + x-ratelimit-remaining-usd: '0.9536' + x-ratelimit-reset: '15326' access-control-expose-headers: Cache-Control, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Onetime-Remaining, X-RateLimit-Credits-Used, X-RateLimit-Credits-Required, X-RateLimit-Reset, X-RateLimit-Limit-USD, X-RateLimit-Remaining-USD, X-RateLimit-Prepaid-Remaining-USD, X-RateLimit-Cost-USD, X-RateLimit-Cost-Required-USD, Retry-After content-encoding: br body: - string: '{"meta": {"count": 1, "db_response_time_ms": 40, "page": 1, "per_page": + string: '{"meta": {"count": 1, "db_response_time_ms": 23, "page": 1, "per_page": 1, "groups_count": null, "cost_usd": 0.0001}, "results": [{"id": "https://openalex.org/W2162348455", "doi": "https://doi.org/10.1038/35002501", "title": "Biodiversity hotspots for conservation priorities", "display_name": "Biodiversity hotspots for conservation @@ -106,7 +106,7 @@ http_interactions: 5, "corresponding_author_ids": ["https://openalex.org/A5109070857"], "corresponding_institution_ids": ["https://openalex.org/I40120149"], "apc_list": {"value": 9750, "currency": "EUR", "value_usd": 11690}, "apc_paid": null, "fwci": 506.2763, "has_fulltext": - false, "cited_by_count": 31038, "citation_normalized_percentile": {"value": + false, "cited_by_count": 31040, "citation_normalized_percentile": {"value": 1.0, "is_in_top_1_percent": true, "is_in_top_10_percent": true}, "cited_by_percentile_year": {"min": 99, "max": 100}, "biblio": {"volume": "403", "issue": "6772", "first_page": "853", "last_page": "858"}, "is_retracted": false, "is_paratext": false, "is_xpac": @@ -266,7 +266,7 @@ http_interactions: "repository"}, "license": null, "license_id": null, "version": "submittedVersion", "is_accepted": false, "is_published": false, "raw_source_name": null, "raw_type": "JournalArticle"}, "sustainable_development_goals": [{"display_name": "Life - in Land", "id": "https://metadata.un.org/sdg/15", "score": 0.5600000023841858}], + in Land", "score": 0.5600000023841858, "id": "https://metadata.un.org/sdg/15"}], "awards": [], "funders": [{"id": "https://openalex.org/F4320306142", "display_name": "John D. and Catherine T. MacArthur Foundation", "ror": "https://ror.org/00dxczh48"}, {"id": "https://openalex.org/F4320323161", "display_name": "WWF International", @@ -353,25 +353,25 @@ http_interactions: "https://openalex.org/W1888713647", "https://openalex.org/W4384207523", "https://openalex.org/W2107551382", "https://openalex.org/W2157912707", "https://openalex.org/W4212786172", "https://openalex.org/W2148001066", "https://openalex.org/W2162348455"], "abstract_inverted_index": null, "counts_by_year": - [{"year": 2026, "cited_by_count": 588}, {"year": 2025, "cited_by_count": 1796}, + [{"year": 2026, "cited_by_count": 589}, {"year": 2025, "cited_by_count": 1796}, {"year": 2024, "cited_by_count": 1794}, {"year": 2023, "cited_by_count": 1973}, - {"year": 2022, "cited_by_count": 2005}, {"year": 2021, "cited_by_count": 2184}, + {"year": 2022, "cited_by_count": 2005}, {"year": 2021, "cited_by_count": 2185}, {"year": 2020, "cited_by_count": 2048}, {"year": 2019, "cited_by_count": 1752}, {"year": 2018, "cited_by_count": 1602}, {"year": 2017, "cited_by_count": 1533}, {"year": 2016, "cited_by_count": 1558}, {"year": 2015, "cited_by_count": 1417}, {"year": 2014, "cited_by_count": 1465}, {"year": 2013, "cited_by_count": 1424}, - {"year": 2012, "cited_by_count": 1216}], "updated_date": "2026-05-23T08:51:43.019350", + {"year": 2012, "cited_by_count": 1216}], "updated_date": "2026-05-24T08:33:08.758527", "created_date": "2025-10-10T00:00:00"}], "group_by": []}' - recorded_at: 2026-05-24 08:50:27 + recorded_at: 2026-05-24 19:44:35 - request: method: GET uri: https://api.openalex.org/works?filter=doi%3A10.1038%2F35002501&per-page=200&mailto=anonymous%40mail.com&cursor=%2A response: status: 200 headers: - date: Sun, 24 May 2026 08:50:28 GMT + date: Sun, 24 May 2026 19:44:35 GMT content-type: application/json - cf-ray: a00b0d8d5883a26a-MRS + cf-ray: a00ecbbc7e886cf5-MRS cf-cache-status: DYNAMIC access-control-allow-origin: '*' server: cloudflare @@ -380,24 +380,24 @@ http_interactions: Content-Type access-control-allow-methods: GET, HEAD, POST, OPTIONS nel: '{"report_to":"heroku-nel","response_headers":["Via"],"max_age":3600,"success_fraction":0.01,"failure_fraction":0.1}' - report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=AqjQ3Npl8xUc8e%2F0%2BUb3szCrc9%2BfZgLjuB0u9%2F5DftU%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779612628"}],"max_age":3600}' - reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=AqjQ3Npl8xUc8e%2F0%2BUb3szCrc9%2BfZgLjuB0u9%2F5DftU%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779612628" + report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=R%2FbP9o%2FXDn5uibAxKiU%2FAiN88vQf%2FrQBO6ItBwzpbJc%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779651875"}],"max_age":3600}' + reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=R%2FbP9o%2FXDn5uibAxKiU%2FAiN88vQf%2FrQBO6ItBwzpbJc%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779651875" x-ratelimit-cost-usd: '0.0001' x-ratelimit-credits-used: '1' x-ratelimit-limit: '10000' x-ratelimit-limit-usd: '1' x-ratelimit-onetime-remaining: '0' x-ratelimit-prepaid-remaining-usd: '0' - x-ratelimit-remaining: '9928' - x-ratelimit-remaining-usd: '0.9928' - x-ratelimit-reset: '54572' + x-ratelimit-remaining: '9535' + x-ratelimit-remaining-usd: '0.9535' + x-ratelimit-reset: '15325' access-control-expose-headers: Cache-Control, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Onetime-Remaining, X-RateLimit-Credits-Used, X-RateLimit-Credits-Required, X-RateLimit-Reset, X-RateLimit-Limit-USD, X-RateLimit-Remaining-USD, X-RateLimit-Prepaid-Remaining-USD, X-RateLimit-Cost-USD, X-RateLimit-Cost-Required-USD, Retry-After content-encoding: br body: - string: '{"meta": {"count": 1, "db_response_time_ms": 24, "page": null, "per_page": + string: '{"meta": {"count": 1, "db_response_time_ms": 19, "page": null, "per_page": 200, "next_cursor": null, "groups_count": null, "cost_usd": 0.0001}, "results": [{"id": "https://openalex.org/W2162348455", "doi": "https://doi.org/10.1038/35002501", "title": "Biodiversity hotspots for conservation priorities", "display_name": @@ -470,7 +470,7 @@ http_interactions: 5, "corresponding_author_ids": ["https://openalex.org/A5109070857"], "corresponding_institution_ids": ["https://openalex.org/I40120149"], "apc_list": {"value": 9750, "currency": "EUR", "value_usd": 11690}, "apc_paid": null, "fwci": 506.2763, "has_fulltext": - false, "cited_by_count": 31038, "citation_normalized_percentile": {"value": + false, "cited_by_count": 31040, "citation_normalized_percentile": {"value": 1.0, "is_in_top_1_percent": true, "is_in_top_10_percent": true}, "cited_by_percentile_year": {"min": 99, "max": 100}, "biblio": {"volume": "403", "issue": "6772", "first_page": "853", "last_page": "858"}, "is_retracted": false, "is_paratext": false, "is_xpac": @@ -629,13 +629,13 @@ http_interactions: "host_organization_lineage": [], "host_organization_lineage_names": [], "type": "repository"}, "license": null, "license_id": null, "version": "submittedVersion", "is_accepted": false, "is_published": false, "raw_source_name": null, "raw_type": - "JournalArticle"}, "sustainable_development_goals": [{"id": "https://metadata.un.org/sdg/15", - "display_name": "Life in Land", "score": 0.5600000023841858}], "awards": [], - "funders": [{"id": "https://openalex.org/F4320306142", "display_name": "John - D. and Catherine T. MacArthur Foundation", "ror": "https://ror.org/00dxczh48"}, + "JournalArticle"}, "sustainable_development_goals": [{"display_name": "Life + in Land", "id": "https://metadata.un.org/sdg/15", "score": 0.5600000023841858}], + "awards": [], "funders": [{"id": "https://openalex.org/F4320306142", "display_name": + "John D. and Catherine T. MacArthur Foundation", "ror": "https://ror.org/00dxczh48"}, {"id": "https://openalex.org/F4320323161", "display_name": "WWF International", - "ror": "https://ror.org/00ppaw753"}], "has_content": {"pdf": false, "grobid_xml": - false}, "content_urls": null, "referenced_works_count": 230, "referenced_works": + "ror": "https://ror.org/00ppaw753"}], "has_content": {"grobid_xml": false, + "pdf": false}, "content_urls": null, "referenced_works_count": 230, "referenced_works": ["https://openalex.org/W22843948", "https://openalex.org/W32719449", "https://openalex.org/W38423605", "https://openalex.org/W46166763", "https://openalex.org/W89943346", "https://openalex.org/W117453349", "https://openalex.org/W146764914", "https://openalex.org/W197913869", "https://openalex.org/W213495198", @@ -717,14 +717,14 @@ http_interactions: "https://openalex.org/W1888713647", "https://openalex.org/W4384207523", "https://openalex.org/W2107551382", "https://openalex.org/W2157912707", "https://openalex.org/W4212786172", "https://openalex.org/W2148001066", "https://openalex.org/W2162348455"], "abstract_inverted_index": null, "counts_by_year": - [{"year": 2026, "cited_by_count": 588}, {"year": 2025, "cited_by_count": 1796}, + [{"year": 2026, "cited_by_count": 589}, {"year": 2025, "cited_by_count": 1796}, {"year": 2024, "cited_by_count": 1794}, {"year": 2023, "cited_by_count": 1973}, - {"year": 2022, "cited_by_count": 2005}, {"year": 2021, "cited_by_count": 2184}, + {"year": 2022, "cited_by_count": 2005}, {"year": 2021, "cited_by_count": 2185}, {"year": 2020, "cited_by_count": 2048}, {"year": 2019, "cited_by_count": 1752}, {"year": 2018, "cited_by_count": 1602}, {"year": 2017, "cited_by_count": 1533}, {"year": 2016, "cited_by_count": 1558}, {"year": 2015, "cited_by_count": 1417}, {"year": 2014, "cited_by_count": 1465}, {"year": 2013, "cited_by_count": 1424}, - {"year": 2012, "cited_by_count": 1216}], "updated_date": "2026-05-23T08:51:43.019350", + {"year": 2012, "cited_by_count": 1216}], "updated_date": "2026-05-24T08:33:08.758527", "created_date": "2025-10-10T00:00:00"}], "group_by": []}' - recorded_at: 2026-05-24 08:50:28 + recorded_at: 2026-05-24 19:44:35 recorded_with: VCR-vcr/2.1.0 diff --git a/tests/testthat/_vcr/fp_get_article_fairness_fp_non_acad.yml b/tests/testthat/_vcr/fp_get_article_fairness_fp_non_acad.yml index 9a9bea6..fc97c2d 100644 --- a/tests/testthat/_vcr/fp_get_article_fairness_fp_non_acad.yml +++ b/tests/testthat/_vcr/fp_get_article_fairness_fp_non_acad.yml @@ -5,9 +5,9 @@ http_interactions: response: status: 200 headers: - date: Sun, 24 May 2026 08:50:26 GMT + date: Sun, 24 May 2026 19:44:34 GMT content-type: application/json - cf-ray: a00b0d851f98a26a-MRS + cf-ray: a00ecbb3f9116cf5-MRS cf-cache-status: DYNAMIC access-control-allow-origin: '*' server: cloudflare @@ -16,24 +16,24 @@ http_interactions: Content-Type access-control-allow-methods: GET, HEAD, POST, OPTIONS nel: '{"report_to":"heroku-nel","response_headers":["Via"],"max_age":3600,"success_fraction":0.01,"failure_fraction":0.1}' - report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=%2F6eoHQdfK%2FFe7FVSs%2BpVa6bQ7sfS%2F4WVnO3ax%2FvmDOQ%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779612626"}],"max_age":3600}' - reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=%2F6eoHQdfK%2FFe7FVSs%2BpVa6bQ7sfS%2F4WVnO3ax%2FvmDOQ%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779612626" + report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=6wFPruFOncvjVxvLqtPcSq5Wh5IvQGvu9KXhv%2FMhBcM%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779651873"}],"max_age":3600}' + reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=6wFPruFOncvjVxvLqtPcSq5Wh5IvQGvu9KXhv%2FMhBcM%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779651873" x-ratelimit-cost-usd: '0.0001' x-ratelimit-credits-used: '1' x-ratelimit-limit: '10000' x-ratelimit-limit-usd: '1' x-ratelimit-onetime-remaining: '0' x-ratelimit-prepaid-remaining-usd: '0' - x-ratelimit-remaining: '9931' - x-ratelimit-remaining-usd: '0.9931' - x-ratelimit-reset: '54574' + x-ratelimit-remaining: '9538' + x-ratelimit-remaining-usd: '0.9538' + x-ratelimit-reset: '15326' access-control-expose-headers: Cache-Control, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Onetime-Remaining, X-RateLimit-Credits-Used, X-RateLimit-Credits-Required, X-RateLimit-Reset, X-RateLimit-Limit-USD, X-RateLimit-Remaining-USD, X-RateLimit-Prepaid-Remaining-USD, X-RateLimit-Cost-USD, X-RateLimit-Cost-Required-USD, Retry-After content-encoding: br body: - string: '{"meta": {"count": 1, "db_response_time_ms": 14, "page": 1, "per_page": + string: '{"meta": {"count": 1, "db_response_time_ms": 43, "page": 1, "per_page": 1, "groups_count": null, "cost_usd": 0.0001}, "results": [{"id": "https://openalex.org/W2123337039", "doi": "https://doi.org/10.1111/j.1461-0248.2005.00792.x", "title": "Predicting species distribution: offering more than simple habitat models", "display_name": @@ -320,16 +320,16 @@ http_interactions: {"year": 2014, "cited_by_count": 337}, {"year": 2013, "cited_by_count": 341}, {"year": 2012, "cited_by_count": 378}], "updated_date": "2026-05-23T08:51:43.019350", "created_date": "2025-10-10T00:00:00"}], "group_by": []}' - recorded_at: 2026-05-24 08:50:26 + recorded_at: 2026-05-24 19:44:34 - request: method: GET uri: https://api.openalex.org/works?filter=doi%3A10.1111%2Fj.1461-0248.2005.00792.x&per-page=200&mailto=anonymous%40mail.com&cursor=%2A response: status: 200 headers: - date: Sun, 24 May 2026 08:50:27 GMT + date: Sun, 24 May 2026 19:44:34 GMT content-type: application/json - cf-ray: a00b0d879c7ba26a-MRS + cf-ray: a00ecbb6da996cf5-MRS cf-cache-status: DYNAMIC access-control-allow-origin: '*' server: cloudflare @@ -338,24 +338,24 @@ http_interactions: Content-Type access-control-allow-methods: GET, HEAD, POST, OPTIONS nel: '{"report_to":"heroku-nel","response_headers":["Via"],"max_age":3600,"success_fraction":0.01,"failure_fraction":0.1}' - report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=NQ6dlv6030jIxYibePSHS5K3luCQWjiKCIGcV78lCe8%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779612627"}],"max_age":3600}' - reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=NQ6dlv6030jIxYibePSHS5K3luCQWjiKCIGcV78lCe8%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779612627" + report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=j4g6Ox3SRV8RC4BPrKC6MpmkLVz93NCIRlGA2AbjfSE%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779651874"}],"max_age":3600}' + reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=j4g6Ox3SRV8RC4BPrKC6MpmkLVz93NCIRlGA2AbjfSE%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779651874" x-ratelimit-cost-usd: '0.0001' x-ratelimit-credits-used: '1' x-ratelimit-limit: '10000' x-ratelimit-limit-usd: '1' x-ratelimit-onetime-remaining: '0' x-ratelimit-prepaid-remaining-usd: '0' - x-ratelimit-remaining: '9930' - x-ratelimit-remaining-usd: '0.993' - x-ratelimit-reset: '54573' + x-ratelimit-remaining: '9537' + x-ratelimit-remaining-usd: '0.9537' + x-ratelimit-reset: '15326' access-control-expose-headers: Cache-Control, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Onetime-Remaining, X-RateLimit-Credits-Used, X-RateLimit-Credits-Required, X-RateLimit-Reset, X-RateLimit-Limit-USD, X-RateLimit-Remaining-USD, X-RateLimit-Prepaid-Remaining-USD, X-RateLimit-Cost-USD, X-RateLimit-Cost-Required-USD, Retry-After content-encoding: br body: - string: '{"meta": {"count": 1, "db_response_time_ms": 15, "page": null, "per_page": + string: '{"meta": {"count": 1, "db_response_time_ms": 18, "page": null, "per_page": 200, "next_cursor": null, "groups_count": null, "cost_usd": 0.0001}, "results": [{"id": "https://openalex.org/W2123337039", "doi": "https://doi.org/10.1111/j.1461-0248.2005.00792.x", "title": "Predicting species distribution: offering more than simple habitat @@ -560,80 +560,79 @@ http_interactions: [], "host_organization_lineage_names": [], "type": "repository"}, "license": null, "license_id": null, "version": "submittedVersion", "is_accepted": false, "is_published": false, "raw_source_name": null, "raw_type": "JournalArticle"}, - "sustainable_development_goals": [{"id": "https://metadata.un.org/sdg/13", - "display_name": "Climate action", "score": 0.4399999976158142}], "awards": - [], "funders": [], "has_content": {"grobid_xml": false, "pdf": false}, "content_urls": - null, "referenced_works_count": 125, "referenced_works": ["https://openalex.org/W221484134", - "https://openalex.org/W228375214", "https://openalex.org/W276691513", "https://openalex.org/W1503026800", - "https://openalex.org/W1519918296", "https://openalex.org/W1535048244", "https://openalex.org/W1552647955", - "https://openalex.org/W1575985957", "https://openalex.org/W1596529738", "https://openalex.org/W1838542636", - "https://openalex.org/W1844182505", "https://openalex.org/W1963600966", "https://openalex.org/W1964191306", - "https://openalex.org/W1964837462", "https://openalex.org/W1972082227", "https://openalex.org/W1985448383", - "https://openalex.org/W1986568873", "https://openalex.org/W1994031665", "https://openalex.org/W1994217680", - "https://openalex.org/W1994442418", "https://openalex.org/W1996364967", "https://openalex.org/W1998951281", - "https://openalex.org/W1999659160", "https://openalex.org/W2006970177", "https://openalex.org/W2015340512", - "https://openalex.org/W2016070884", "https://openalex.org/W2019055691", "https://openalex.org/W2022909546", - "https://openalex.org/W2023966367", "https://openalex.org/W2024046085", "https://openalex.org/W2024780423", - "https://openalex.org/W2031217053", "https://openalex.org/W2031901125", "https://openalex.org/W2032138416", - "https://openalex.org/W2037105750", "https://openalex.org/W2045997296", "https://openalex.org/W2048429184", - "https://openalex.org/W2049424645", "https://openalex.org/W2052489905", "https://openalex.org/W2055764609", - "https://openalex.org/W2058597570", "https://openalex.org/W2059210846", "https://openalex.org/W2060298585", - "https://openalex.org/W2078204193", "https://openalex.org/W2080441793", "https://openalex.org/W2080978149", - "https://openalex.org/W2081964130", "https://openalex.org/W2085073796", "https://openalex.org/W2085449681", - "https://openalex.org/W2088626174", "https://openalex.org/W2089454337", "https://openalex.org/W2095240644", - "https://openalex.org/W2096152168", "https://openalex.org/W2097672723", "https://openalex.org/W2099197539", - "https://openalex.org/W2099320848", "https://openalex.org/W2102881574", "https://openalex.org/W2106718643", - "https://openalex.org/W2108683999", "https://openalex.org/W2110022170", "https://openalex.org/W2111954076", - "https://openalex.org/W2114630657", "https://openalex.org/W2115414100", "https://openalex.org/W2118436877", - "https://openalex.org/W2119830727", "https://openalex.org/W2120160157", "https://openalex.org/W2123379596", - "https://openalex.org/W2123498764", "https://openalex.org/W2124286013", "https://openalex.org/W2124516299", - "https://openalex.org/W2125118617", "https://openalex.org/W2125340357", "https://openalex.org/W2129913788", - "https://openalex.org/W2130354003", "https://openalex.org/W2130695471", "https://openalex.org/W2132885452", - "https://openalex.org/W2136017883", "https://openalex.org/W2138788795", "https://openalex.org/W2139416101", - "https://openalex.org/W2139857790", "https://openalex.org/W2140534668", "https://openalex.org/W2144377259", - "https://openalex.org/W2146081698", "https://openalex.org/W2147531279", "https://openalex.org/W2149507322", - "https://openalex.org/W2150171421", "https://openalex.org/W2154107014", "https://openalex.org/W2155475871", - "https://openalex.org/W2156319159", "https://openalex.org/W2156476474", "https://openalex.org/W2157701121", - "https://openalex.org/W2160613335", "https://openalex.org/W2162883397", "https://openalex.org/W2163816695", - "https://openalex.org/W2164351958", "https://openalex.org/W2167237900", "https://openalex.org/W2167518054", - "https://openalex.org/W2168939113", "https://openalex.org/W2170505236", "https://openalex.org/W2170597372", - "https://openalex.org/W2171173166", "https://openalex.org/W2172838612", "https://openalex.org/W2188094503", - "https://openalex.org/W2247170044", "https://openalex.org/W2470118347", "https://openalex.org/W2474908076", - "https://openalex.org/W2507100972", "https://openalex.org/W2796407663", "https://openalex.org/W2997943624", - "https://openalex.org/W3150326654", "https://openalex.org/W3170870831", "https://openalex.org/W4231374061", - "https://openalex.org/W4233991124", "https://openalex.org/W4243871771", "https://openalex.org/W4249657560", - "https://openalex.org/W4301427652", "https://openalex.org/W6635459477", "https://openalex.org/W6648520290", - "https://openalex.org/W6671827719", "https://openalex.org/W6679410509", "https://openalex.org/W6679892459", - "https://openalex.org/W6681526416", "https://openalex.org/W6681784784", "https://openalex.org/W6682194299", - "https://openalex.org/W6812609589"], "related_works": ["https://openalex.org/W1585007175", - "https://openalex.org/W2382521049", "https://openalex.org/W2144385241", "https://openalex.org/W4300101996", - "https://openalex.org/W2165950148", "https://openalex.org/W4253593777", "https://openalex.org/W2951497643", - "https://openalex.org/W1524579078", "https://openalex.org/W1996083730", "https://openalex.org/W2095269989"], - "abstract_inverted_index": {"In": [0], "the": [1, 42, 64, 79, 90, 95], "last": - [2], "two": [3], "decades,": [4], "interest": [5], "in": [6, 20, 46, 60, 78], - "species": [7, 111], "distribution": [8], "models": [9], "(SDMs)": [10], "of": - [11, 31, 44, 57, 83, 92, 97, 134], "plants": [12], "and": [13, 49, 67, 71, - 75, 81, 101, 117], "animals": [14], "has": [15], "grown": [16], "dramatically.": - [17], "Recent": [18], "advances": [19, 59], "SDMs": [21, 45, 93, 121, 135], - "allow": [22], "us": [23], "to": [24, 89], "potentially": [25], "forecast": - [26], "anthropogenic": [27], "effects": [28], "on": [29], "patterns": [30], - "biodiversity": [32], "at": [33, 122], "different": [34], "spatial": [35, - 124], "scales.": [36, 125], "However,": [37], "some": [38], "limitations": - [39, 74], "still": [40], "preclude": [41], "use": [43, 91], "many": [47], - "theoretical": [48], "practical": [50], "applications.": [51], "Here,": [52], - "we": [53], "provide": [54], "an": [55], "overview": [56], "recent": [58], - "this": [61], "field,": [62], "discuss": [63], "ecological": [65, 137], "principles": - [66], "assumptions": [68], "underpinning": [69], "SDMs,": [70], "highlight": - [72], "critical": [73], "decisions": [76], "inherent": [77], "construction": - [80], "evaluation": [82], "SDMs.": [84], "Particular": [85], "emphasis": [86], - "is": [87], "given": [88], "for": [94, 109], "assessment": [96], "climate": - [98], "change": [99], "impacts": [100], "conservation": [102], "management": - [103], "issues.": [104], "We": [105], "suggest": [106], "new": [107], "avenues": - [108], "incorporating": [110], "migration,": [112], "population": [113], "dynamics,": - [114], "biotic": [115], "interactions": [116], "community": [118], "ecology": - [119], "into": [120], "multiple": [123], "Addressing": [126], "all": [127], - "these": [128], "issues": [129], "requires": [130], "a": [131], "better": - [132], "integration": [133], "with": [136], "theory.": [138]}, "counts_by_year": + "sustainable_development_goals": [{"score": 0.4399999976158142, "id": "https://metadata.un.org/sdg/13", + "display_name": "Climate action"}], "awards": [], "funders": [], "has_content": + {"pdf": false, "grobid_xml": false}, "content_urls": null, "referenced_works_count": + 125, "referenced_works": ["https://openalex.org/W221484134", "https://openalex.org/W228375214", + "https://openalex.org/W276691513", "https://openalex.org/W1503026800", "https://openalex.org/W1519918296", + "https://openalex.org/W1535048244", "https://openalex.org/W1552647955", "https://openalex.org/W1575985957", + "https://openalex.org/W1596529738", "https://openalex.org/W1838542636", "https://openalex.org/W1844182505", + "https://openalex.org/W1963600966", "https://openalex.org/W1964191306", "https://openalex.org/W1964837462", + "https://openalex.org/W1972082227", "https://openalex.org/W1985448383", "https://openalex.org/W1986568873", + "https://openalex.org/W1994031665", "https://openalex.org/W1994217680", "https://openalex.org/W1994442418", + "https://openalex.org/W1996364967", "https://openalex.org/W1998951281", "https://openalex.org/W1999659160", + "https://openalex.org/W2006970177", "https://openalex.org/W2015340512", "https://openalex.org/W2016070884", + "https://openalex.org/W2019055691", "https://openalex.org/W2022909546", "https://openalex.org/W2023966367", + "https://openalex.org/W2024046085", "https://openalex.org/W2024780423", "https://openalex.org/W2031217053", + "https://openalex.org/W2031901125", "https://openalex.org/W2032138416", "https://openalex.org/W2037105750", + "https://openalex.org/W2045997296", "https://openalex.org/W2048429184", "https://openalex.org/W2049424645", + "https://openalex.org/W2052489905", "https://openalex.org/W2055764609", "https://openalex.org/W2058597570", + "https://openalex.org/W2059210846", "https://openalex.org/W2060298585", "https://openalex.org/W2078204193", + "https://openalex.org/W2080441793", "https://openalex.org/W2080978149", "https://openalex.org/W2081964130", + "https://openalex.org/W2085073796", "https://openalex.org/W2085449681", "https://openalex.org/W2088626174", + "https://openalex.org/W2089454337", "https://openalex.org/W2095240644", "https://openalex.org/W2096152168", + "https://openalex.org/W2097672723", "https://openalex.org/W2099197539", "https://openalex.org/W2099320848", + "https://openalex.org/W2102881574", "https://openalex.org/W2106718643", "https://openalex.org/W2108683999", + "https://openalex.org/W2110022170", "https://openalex.org/W2111954076", "https://openalex.org/W2114630657", + "https://openalex.org/W2115414100", "https://openalex.org/W2118436877", "https://openalex.org/W2119830727", + "https://openalex.org/W2120160157", "https://openalex.org/W2123379596", "https://openalex.org/W2123498764", + "https://openalex.org/W2124286013", "https://openalex.org/W2124516299", "https://openalex.org/W2125118617", + "https://openalex.org/W2125340357", "https://openalex.org/W2129913788", "https://openalex.org/W2130354003", + "https://openalex.org/W2130695471", "https://openalex.org/W2132885452", "https://openalex.org/W2136017883", + "https://openalex.org/W2138788795", "https://openalex.org/W2139416101", "https://openalex.org/W2139857790", + "https://openalex.org/W2140534668", "https://openalex.org/W2144377259", "https://openalex.org/W2146081698", + "https://openalex.org/W2147531279", "https://openalex.org/W2149507322", "https://openalex.org/W2150171421", + "https://openalex.org/W2154107014", "https://openalex.org/W2155475871", "https://openalex.org/W2156319159", + "https://openalex.org/W2156476474", "https://openalex.org/W2157701121", "https://openalex.org/W2160613335", + "https://openalex.org/W2162883397", "https://openalex.org/W2163816695", "https://openalex.org/W2164351958", + "https://openalex.org/W2167237900", "https://openalex.org/W2167518054", "https://openalex.org/W2168939113", + "https://openalex.org/W2170505236", "https://openalex.org/W2170597372", "https://openalex.org/W2171173166", + "https://openalex.org/W2172838612", "https://openalex.org/W2188094503", "https://openalex.org/W2247170044", + "https://openalex.org/W2470118347", "https://openalex.org/W2474908076", "https://openalex.org/W2507100972", + "https://openalex.org/W2796407663", "https://openalex.org/W2997943624", "https://openalex.org/W3150326654", + "https://openalex.org/W3170870831", "https://openalex.org/W4231374061", "https://openalex.org/W4233991124", + "https://openalex.org/W4243871771", "https://openalex.org/W4249657560", "https://openalex.org/W4301427652", + "https://openalex.org/W6635459477", "https://openalex.org/W6648520290", "https://openalex.org/W6671827719", + "https://openalex.org/W6679410509", "https://openalex.org/W6679892459", "https://openalex.org/W6681526416", + "https://openalex.org/W6681784784", "https://openalex.org/W6682194299", "https://openalex.org/W6812609589"], + "related_works": ["https://openalex.org/W1585007175", "https://openalex.org/W2382521049", + "https://openalex.org/W2144385241", "https://openalex.org/W4300101996", "https://openalex.org/W2165950148", + "https://openalex.org/W4253593777", "https://openalex.org/W2951497643", "https://openalex.org/W1524579078", + "https://openalex.org/W1996083730", "https://openalex.org/W2095269989"], "abstract_inverted_index": + {"In": [0], "the": [1, 42, 64, 79, 90, 95], "last": [2], "two": [3], "decades,": + [4], "interest": [5], "in": [6, 20, 46, 60, 78], "species": [7, 111], "distribution": + [8], "models": [9], "(SDMs)": [10], "of": [11, 31, 44, 57, 83, 92, 97, 134], + "plants": [12], "and": [13, 49, 67, 71, 75, 81, 101, 117], "animals": [14], + "has": [15], "grown": [16], "dramatically.": [17], "Recent": [18], "advances": + [19, 59], "SDMs": [21, 45, 93, 121, 135], "allow": [22], "us": [23], "to": + [24, 89], "potentially": [25], "forecast": [26], "anthropogenic": [27], "effects": + [28], "on": [29], "patterns": [30], "biodiversity": [32], "at": [33, 122], + "different": [34], "spatial": [35, 124], "scales.": [36, 125], "However,": + [37], "some": [38], "limitations": [39, 74], "still": [40], "preclude": [41], + "use": [43, 91], "many": [47], "theoretical": [48], "practical": [50], "applications.": + [51], "Here,": [52], "we": [53], "provide": [54], "an": [55], "overview": + [56], "recent": [58], "this": [61], "field,": [62], "discuss": [63], "ecological": + [65, 137], "principles": [66], "assumptions": [68], "underpinning": [69], + "SDMs,": [70], "highlight": [72], "critical": [73], "decisions": [76], "inherent": + [77], "construction": [80], "evaluation": [82], "SDMs.": [84], "Particular": + [85], "emphasis": [86], "is": [87], "given": [88], "for": [94, 109], "assessment": + [96], "climate": [98], "change": [99], "impacts": [100], "conservation": [102], + "management": [103], "issues.": [104], "We": [105], "suggest": [106], "new": + [107], "avenues": [108], "incorporating": [110], "migration,": [112], "population": + [113], "dynamics,": [114], "biotic": [115], "interactions": [116], "community": + [118], "ecology": [119], "into": [120], "multiple": [123], "Addressing": [126], + "all": [127], "these": [128], "issues": [129], "requires": [130], "a": [131], + "better": [132], "integration": [133], "with": [136], "theory.": [138]}, "counts_by_year": [{"year": 2026, "cited_by_count": 119}, {"year": 2025, "cited_by_count": 390}, {"year": 2024, "cited_by_count": 348}, {"year": 2023, "cited_by_count": 345}, {"year": 2022, "cited_by_count": 373}, {"year": 2021, "cited_by_count": 378}, @@ -643,5 +642,5 @@ http_interactions: {"year": 2014, "cited_by_count": 337}, {"year": 2013, "cited_by_count": 341}, {"year": 2012, "cited_by_count": 378}], "updated_date": "2026-05-23T08:51:43.019350", "created_date": "2025-10-10T00:00:00"}], "group_by": []}' - recorded_at: 2026-05-24 08:50:27 + recorded_at: 2026-05-24 19:44:34 recorded_with: VCR-vcr/2.1.0 diff --git a/tests/testthat/_vcr/fp_get_article_fairness_not_in_dafnee.yml b/tests/testthat/_vcr/fp_get_article_fairness_not_in_dafnee.yml index 1577134..3dc1924 100644 --- a/tests/testthat/_vcr/fp_get_article_fairness_not_in_dafnee.yml +++ b/tests/testthat/_vcr/fp_get_article_fairness_not_in_dafnee.yml @@ -5,9 +5,9 @@ http_interactions: response: status: 200 headers: - date: Sun, 24 May 2026 08:50:29 GMT + date: Sun, 24 May 2026 19:44:36 GMT content-type: application/json - cf-ray: a00b0d927af7a26a-MRS + cf-ray: a00ecbc1ea216cf5-MRS cf-cache-status: DYNAMIC access-control-allow-origin: '*' server: cloudflare @@ -16,24 +16,24 @@ http_interactions: Content-Type access-control-allow-methods: GET, HEAD, POST, OPTIONS nel: '{"report_to":"heroku-nel","response_headers":["Via"],"max_age":3600,"success_fraction":0.01,"failure_fraction":0.1}' - report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=AqjQ3Npl8xUc8e%2F0%2BUb3szCrc9%2BfZgLjuB0u9%2F5DftU%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779612628"}],"max_age":3600}' - reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=AqjQ3Npl8xUc8e%2F0%2BUb3szCrc9%2BfZgLjuB0u9%2F5DftU%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779612628" + report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=Gdcm5uNZwtQ1Gm2Y1pzfItkR7A6y0G8MUhaq0k33jp4%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779651876"}],"max_age":3600}' + reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=Gdcm5uNZwtQ1Gm2Y1pzfItkR7A6y0G8MUhaq0k33jp4%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779651876" x-ratelimit-cost-usd: '0.0001' x-ratelimit-credits-used: '1' x-ratelimit-limit: '10000' x-ratelimit-limit-usd: '1' x-ratelimit-onetime-remaining: '0' x-ratelimit-prepaid-remaining-usd: '0' - x-ratelimit-remaining: '9926' - x-ratelimit-remaining-usd: '0.9926' - x-ratelimit-reset: '54571' + x-ratelimit-remaining: '9533' + x-ratelimit-remaining-usd: '0.9533' + x-ratelimit-reset: '15324' access-control-expose-headers: Cache-Control, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Onetime-Remaining, X-RateLimit-Credits-Used, X-RateLimit-Credits-Required, X-RateLimit-Reset, X-RateLimit-Limit-USD, X-RateLimit-Remaining-USD, X-RateLimit-Prepaid-Remaining-USD, X-RateLimit-Cost-USD, X-RateLimit-Cost-Required-USD, Retry-After content-encoding: br body: - string: '{"meta": {"count": 1, "db_response_time_ms": 18, "page": 1, "per_page": + string: '{"meta": {"count": 1, "db_response_time_ms": 16, "page": 1, "per_page": 1, "groups_count": null, "cost_usd": 0.0001}, "results": [{"id": "https://openalex.org/W4415113473", "doi": "https://doi.org/10.21105/joss.09217", "title": "forcis: An R package for accessing, handling and analysing the FORCIS database", "display_name": @@ -306,23 +306,23 @@ http_interactions: f\u00fcr Chemie", "ror": "https://ror.org/02f5b7n18"}, {"id": "https://openalex.org/F4320335598", "display_name": "Agencia Estatal de Investigaci\u00f3n", "ror": null}, {"id": "https://openalex.org/F4320338223", "display_name": "Direcci\u00f3 General - de Recerca, Generalitat de Catalunya", "ror": null}], "has_content": {"pdf": - true, "grobid_xml": false}, "content_urls": {"pdf": "https://content.openalex.org/works/W4415113473.pdf"}, + de Recerca, Generalitat de Catalunya", "ror": null}], "has_content": {"grobid_xml": + false, "pdf": true}, "content_urls": {"pdf": "https://content.openalex.org/works/W4415113473.pdf"}, "referenced_works_count": 3, "referenced_works": ["https://openalex.org/W4229082123", "https://openalex.org/W4379259280", "https://openalex.org/W4404305647"], "related_works": [], "abstract_inverted_index": {"International": [0], "audience": [1]}, "counts_by_year": [], "updated_date": "2026-05-07T13:39:58.223016", "created_date": "2025-10-14T00:00:00"}], "group_by": []}' - recorded_at: 2026-05-24 08:50:29 + recorded_at: 2026-05-24 19:44:36 - request: method: GET uri: https://api.openalex.org/works?filter=doi%3A10.21105%2Fjoss.09217&per-page=200&mailto=anonymous%40mail.com&cursor=%2A response: status: 200 headers: - date: Sun, 24 May 2026 08:50:29 GMT + date: Sun, 24 May 2026 19:44:36 GMT content-type: application/json - cf-ray: a00b0d95c954a26a-MRS + cf-ray: a00ecbc47bfa6cf5-MRS cf-cache-status: DYNAMIC access-control-allow-origin: '*' server: cloudflare @@ -331,24 +331,24 @@ http_interactions: Content-Type access-control-allow-methods: GET, HEAD, POST, OPTIONS nel: '{"report_to":"heroku-nel","response_headers":["Via"],"max_age":3600,"success_fraction":0.01,"failure_fraction":0.1}' - report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=agYEIFpNtkI4p9mUB%2FiNXqizjiGRMfm0VGrlL%2F%2FN7lE%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779612629"}],"max_age":3600}' - reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=agYEIFpNtkI4p9mUB%2FiNXqizjiGRMfm0VGrlL%2F%2FN7lE%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779612629" + report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=Gdcm5uNZwtQ1Gm2Y1pzfItkR7A6y0G8MUhaq0k33jp4%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779651876"}],"max_age":3600}' + reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=Gdcm5uNZwtQ1Gm2Y1pzfItkR7A6y0G8MUhaq0k33jp4%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779651876" x-ratelimit-cost-usd: '0.0001' x-ratelimit-credits-used: '1' x-ratelimit-limit: '10000' x-ratelimit-limit-usd: '1' x-ratelimit-onetime-remaining: '0' x-ratelimit-prepaid-remaining-usd: '0' - x-ratelimit-remaining: '9925' - x-ratelimit-remaining-usd: '0.9925' - x-ratelimit-reset: '54571' + x-ratelimit-remaining: '9532' + x-ratelimit-remaining-usd: '0.9532' + x-ratelimit-reset: '15324' access-control-expose-headers: Cache-Control, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Onetime-Remaining, X-RateLimit-Credits-Used, X-RateLimit-Credits-Required, X-RateLimit-Reset, X-RateLimit-Limit-USD, X-RateLimit-Remaining-USD, X-RateLimit-Prepaid-Remaining-USD, X-RateLimit-Cost-USD, X-RateLimit-Cost-Required-USD, Retry-After content-encoding: br body: - string: '{"meta": {"count": 1, "db_response_time_ms": 24, "page": null, "per_page": + string: '{"meta": {"count": 1, "db_response_time_ms": 17, "page": null, "per_page": 200, "next_cursor": null, "groups_count": null, "cost_usd": 0.0001}, "results": [{"id": "https://openalex.org/W4415113473", "doi": "https://doi.org/10.21105/joss.09217", "title": "forcis: An R package for accessing, handling and analysing the FORCIS @@ -621,12 +621,12 @@ http_interactions: f\u00fcr Chemie", "ror": "https://ror.org/02f5b7n18"}, {"id": "https://openalex.org/F4320335598", "display_name": "Agencia Estatal de Investigaci\u00f3n", "ror": null}, {"id": "https://openalex.org/F4320338223", "display_name": "Direcci\u00f3 General - de Recerca, Generalitat de Catalunya", "ror": null}], "has_content": {"pdf": - true, "grobid_xml": false}, "content_urls": {"pdf": "https://content.openalex.org/works/W4415113473.pdf"}, + de Recerca, Generalitat de Catalunya", "ror": null}], "has_content": {"grobid_xml": + false, "pdf": true}, "content_urls": {"pdf": "https://content.openalex.org/works/W4415113473.pdf"}, "referenced_works_count": 3, "referenced_works": ["https://openalex.org/W4229082123", "https://openalex.org/W4379259280", "https://openalex.org/W4404305647"], "related_works": [], "abstract_inverted_index": {"International": [0], "audience": [1]}, "counts_by_year": [], "updated_date": "2026-05-07T13:39:58.223016", "created_date": "2025-10-14T00:00:00"}], "group_by": []}' - recorded_at: 2026-05-24 08:50:29 + recorded_at: 2026-05-24 19:44:36 recorded_with: VCR-vcr/2.1.0 diff --git a/tests/testthat/_vcr/fp_get_article_fairness_not_in_oa.yml b/tests/testthat/_vcr/fp_get_article_fairness_not_in_oa.yml index 6163173..862e3ff 100644 --- a/tests/testthat/_vcr/fp_get_article_fairness_not_in_oa.yml +++ b/tests/testthat/_vcr/fp_get_article_fairness_not_in_oa.yml @@ -5,9 +5,9 @@ http_interactions: response: status: 200 headers: - date: Sun, 24 May 2026 08:50:28 GMT + date: Sun, 24 May 2026 19:44:35 GMT content-type: application/json - cf-ray: a00b0d901d97a26a-MRS + cf-ray: a00ecbbf788c6cf5-MRS cf-cache-status: DYNAMIC access-control-allow-origin: '*' server: cloudflare @@ -16,24 +16,24 @@ http_interactions: Content-Type access-control-allow-methods: GET, HEAD, POST, OPTIONS nel: '{"report_to":"heroku-nel","response_headers":["Via"],"max_age":3600,"success_fraction":0.01,"failure_fraction":0.1}' - report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=AqjQ3Npl8xUc8e%2F0%2BUb3szCrc9%2BfZgLjuB0u9%2F5DftU%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779612628"}],"max_age":3600}' - reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=AqjQ3Npl8xUc8e%2F0%2BUb3szCrc9%2BfZgLjuB0u9%2F5DftU%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779612628" + report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=R%2FbP9o%2FXDn5uibAxKiU%2FAiN88vQf%2FrQBO6ItBwzpbJc%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779651875"}],"max_age":3600}' + reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=R%2FbP9o%2FXDn5uibAxKiU%2FAiN88vQf%2FrQBO6ItBwzpbJc%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779651875" x-ratelimit-cost-usd: '0.0001' x-ratelimit-credits-used: '1' x-ratelimit-limit: '10000' x-ratelimit-limit-usd: '1' x-ratelimit-onetime-remaining: '0' x-ratelimit-prepaid-remaining-usd: '0' - x-ratelimit-remaining: '9927' - x-ratelimit-remaining-usd: '0.9927' - x-ratelimit-reset: '54572' + x-ratelimit-remaining: '9534' + x-ratelimit-remaining-usd: '0.9534' + x-ratelimit-reset: '15325' access-control-expose-headers: Cache-Control, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Onetime-Remaining, X-RateLimit-Credits-Used, X-RateLimit-Credits-Required, X-RateLimit-Reset, X-RateLimit-Limit-USD, X-RateLimit-Remaining-USD, X-RateLimit-Prepaid-Remaining-USD, X-RateLimit-Cost-USD, X-RateLimit-Cost-Required-USD, Retry-After content-encoding: br body: - string: '{"meta": {"count": 0, "db_response_time_ms": 8, "page": 1, "per_page": + string: '{"meta": {"count": 0, "db_response_time_ms": 6, "page": 1, "per_page": 1, "groups_count": null, "cost_usd": 0.0001}, "results": [], "group_by": []}' - recorded_at: 2026-05-24 08:50:28 + recorded_at: 2026-05-24 19:44:35 recorded_with: VCR-vcr/2.1.0 diff --git a/tests/testthat/_vcr/fp_get_article_fairness_np.yml b/tests/testthat/_vcr/fp_get_article_fairness_np.yml index 882102c..05f996b 100644 --- a/tests/testthat/_vcr/fp_get_article_fairness_np.yml +++ b/tests/testthat/_vcr/fp_get_article_fairness_np.yml @@ -5,9 +5,9 @@ http_interactions: response: status: 200 headers: - date: Sun, 24 May 2026 08:50:26 GMT + date: Sun, 24 May 2026 19:44:33 GMT content-type: application/json - cf-ray: a00b0d7fee16a26a-MRS + cf-ray: a00ecbaecdd56cf5-MRS cf-cache-status: DYNAMIC access-control-allow-origin: '*' server: cloudflare @@ -16,24 +16,24 @@ http_interactions: Content-Type access-control-allow-methods: GET, HEAD, POST, OPTIONS nel: '{"report_to":"heroku-nel","response_headers":["Via"],"max_age":3600,"success_fraction":0.01,"failure_fraction":0.1}' - report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=4xwnYpyT73p4PS1C7h9VbrlukNcFhlY6Yto2cYF4hXM%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779612625"}],"max_age":3600}' - reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=4xwnYpyT73p4PS1C7h9VbrlukNcFhlY6Yto2cYF4hXM%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779612625" + report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=6wFPruFOncvjVxvLqtPcSq5Wh5IvQGvu9KXhv%2FMhBcM%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779651873"}],"max_age":3600}' + reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=6wFPruFOncvjVxvLqtPcSq5Wh5IvQGvu9KXhv%2FMhBcM%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779651873" x-ratelimit-cost-usd: '0.0001' x-ratelimit-credits-used: '1' x-ratelimit-limit: '10000' x-ratelimit-limit-usd: '1' x-ratelimit-onetime-remaining: '0' x-ratelimit-prepaid-remaining-usd: '0' - x-ratelimit-remaining: '9933' - x-ratelimit-remaining-usd: '0.9933' - x-ratelimit-reset: '54574' + x-ratelimit-remaining: '9540' + x-ratelimit-remaining-usd: '0.954' + x-ratelimit-reset: '15327' access-control-expose-headers: Cache-Control, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Onetime-Remaining, X-RateLimit-Credits-Used, X-RateLimit-Credits-Required, X-RateLimit-Reset, X-RateLimit-Limit-USD, X-RateLimit-Remaining-USD, X-RateLimit-Prepaid-Remaining-USD, X-RateLimit-Cost-USD, X-RateLimit-Cost-Required-USD, Retry-After content-encoding: br body: - string: '{"meta": {"count": 1, "db_response_time_ms": 15, "page": 1, "per_page": + string: '{"meta": {"count": 1, "db_response_time_ms": 20, "page": 1, "per_page": 1, "groups_count": null, "cost_usd": 0.0001}, "results": [{"id": "https://openalex.org/W2226396244", "doi": "https://doi.org/10.1126/science.162.3859.1243", "title": "The Tragedy of the Commons", "display_name": "The Tragedy of the Commons", "publication_year": @@ -70,8 +70,8 @@ http_interactions: ["https://openalex.org/I1311206647"]}]}], "institutions": [], "countries_distinct_count": 1, "institutions_distinct_count": 1, "corresponding_author_ids": ["https://openalex.org/A5111448232"], "corresponding_institution_ids": ["https://openalex.org/I1311206647"], "apc_list": - null, "apc_paid": null, "fwci": 276.052, "has_fulltext": false, "cited_by_count": - 22830, "citation_normalized_percentile": {"value": 1.0, "is_in_top_1_percent": + null, "apc_paid": null, "fwci": 276.0638, "has_fulltext": false, "cited_by_count": + 22834, "citation_normalized_percentile": {"value": 1.0, "is_in_top_1_percent": true, "is_in_top_10_percent": true}, "cited_by_percentile_year": {"min": 99, "max": 100}, "biblio": {"volume": "162", "issue": "3859", "first_page": "1243", "last_page": "1248"}, "is_retracted": false, "is_paratext": false, "is_xpac": @@ -159,9 +159,9 @@ http_interactions: "host_organization_lineage_names": [], "type": "repository"}, "license": null, "license_id": null, "version": "publishedVersion", "is_accepted": true, "is_published": true, "raw_source_name": "Science (New York, N.Y.)", "raw_type": null}], "best_oa_location": - null, "sustainable_development_goals": [{"id": "https://metadata.un.org/sdg/16", - "display_name": "Peace, Justice and strong institutions", "score": 0.4300000071525574}], - "awards": [], "funders": [], "has_content": {"pdf": false, "grobid_xml": false}, + null, "sustainable_development_goals": [{"display_name": "Peace, Justice and + strong institutions", "id": "https://metadata.un.org/sdg/16", "score": 0.4300000071525574}], + "awards": [], "funders": [], "has_content": {"grobid_xml": false, "pdf": false}, "content_urls": null, "referenced_works_count": 16, "referenced_works": ["https://openalex.org/W645218623", "https://openalex.org/W1520891760", "https://openalex.org/W1546755579", "https://openalex.org/W1967161129", "https://openalex.org/W2027636702", "https://openalex.org/W2029363644", "https://openalex.org/W2054383667", @@ -175,25 +175,25 @@ http_interactions: {"The": [0], "population": [1], "problem": [2], "has": [3], "no": [4], "technical": [5], "solution;": [6], "it": [7], "requires": [8], "a": [9], "fundamental": [10], "extension": [11], "in": [12], "morality.": [13]}, "counts_by_year": - [{"year": 2026, "cited_by_count": 306}, {"year": 2025, "cited_by_count": 830}, + [{"year": 2026, "cited_by_count": 307}, {"year": 2025, "cited_by_count": 831}, {"year": 2024, "cited_by_count": 914}, {"year": 2023, "cited_by_count": 860}, {"year": 2022, "cited_by_count": 898}, {"year": 2021, "cited_by_count": 1169}, {"year": 2020, "cited_by_count": 1230}, {"year": 2019, "cited_by_count": 1132}, - {"year": 2018, "cited_by_count": 1048}, {"year": 2017, "cited_by_count": 969}, + {"year": 2018, "cited_by_count": 1049}, {"year": 2017, "cited_by_count": 969}, {"year": 2016, "cited_by_count": 956}, {"year": 2015, "cited_by_count": 909}, - {"year": 2014, "cited_by_count": 1013}, {"year": 2013, "cited_by_count": 921}, - {"year": 2012, "cited_by_count": 889}], "updated_date": "2026-05-23T08:51:43.019350", + {"year": 2014, "cited_by_count": 1014}, {"year": 2013, "cited_by_count": 921}, + {"year": 2012, "cited_by_count": 889}], "updated_date": "2026-05-24T08:33:08.758527", "created_date": "2016-06-24T00:00:00"}], "group_by": []}' - recorded_at: 2026-05-24 08:50:26 + recorded_at: 2026-05-24 19:44:33 - request: method: GET uri: https://api.openalex.org/works?filter=doi%3A10.1126%2Fscience.162.3859.1243&per-page=200&mailto=anonymous%40mail.com&cursor=%2A response: status: 200 headers: - date: Sun, 24 May 2026 08:50:26 GMT + date: Sun, 24 May 2026 19:44:33 GMT content-type: application/json - cf-ray: a00b0d827b08a26a-MRS + cf-ray: a00ecbb14fa86cf5-MRS cf-cache-status: DYNAMIC access-control-allow-origin: '*' server: cloudflare @@ -202,24 +202,24 @@ http_interactions: Content-Type access-control-allow-methods: GET, HEAD, POST, OPTIONS nel: '{"report_to":"heroku-nel","response_headers":["Via"],"max_age":3600,"success_fraction":0.01,"failure_fraction":0.1}' - report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=%2F6eoHQdfK%2FFe7FVSs%2BpVa6bQ7sfS%2F4WVnO3ax%2FvmDOQ%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779612626"}],"max_age":3600}' - reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=%2F6eoHQdfK%2FFe7FVSs%2BpVa6bQ7sfS%2F4WVnO3ax%2FvmDOQ%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779612626" + report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=6wFPruFOncvjVxvLqtPcSq5Wh5IvQGvu9KXhv%2FMhBcM%3D\u0026sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add\u0026ts=1779651873"}],"max_age":3600}' + reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=6wFPruFOncvjVxvLqtPcSq5Wh5IvQGvu9KXhv%2FMhBcM%3D&sid=c46efe9b-d3d2-4a0c-8c76-bfafa16c5add&ts=1779651873" x-ratelimit-cost-usd: '0.0001' x-ratelimit-credits-used: '1' x-ratelimit-limit: '10000' x-ratelimit-limit-usd: '1' x-ratelimit-onetime-remaining: '0' x-ratelimit-prepaid-remaining-usd: '0' - x-ratelimit-remaining: '9932' - x-ratelimit-remaining-usd: '0.9932' - x-ratelimit-reset: '54574' + x-ratelimit-remaining: '9539' + x-ratelimit-remaining-usd: '0.9539' + x-ratelimit-reset: '15327' access-control-expose-headers: Cache-Control, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Onetime-Remaining, X-RateLimit-Credits-Used, X-RateLimit-Credits-Required, X-RateLimit-Reset, X-RateLimit-Limit-USD, X-RateLimit-Remaining-USD, X-RateLimit-Prepaid-Remaining-USD, X-RateLimit-Cost-USD, X-RateLimit-Cost-Required-USD, Retry-After content-encoding: br body: - string: '{"meta": {"count": 1, "db_response_time_ms": 14, "page": null, "per_page": + string: '{"meta": {"count": 1, "db_response_time_ms": 17, "page": null, "per_page": 200, "next_cursor": null, "groups_count": null, "cost_usd": 0.0001}, "results": [{"id": "https://openalex.org/W2226396244", "doi": "https://doi.org/10.1126/science.162.3859.1243", "title": "The Tragedy of the Commons", "display_name": "The Tragedy of the @@ -256,8 +256,8 @@ http_interactions: ["https://openalex.org/I1311206647"]}]}], "institutions": [], "countries_distinct_count": 1, "institutions_distinct_count": 1, "corresponding_author_ids": ["https://openalex.org/A5111448232"], "corresponding_institution_ids": ["https://openalex.org/I1311206647"], "apc_list": - null, "apc_paid": null, "fwci": 276.052, "has_fulltext": false, "cited_by_count": - 22830, "citation_normalized_percentile": {"value": 1.0, "is_in_top_1_percent": + null, "apc_paid": null, "fwci": 276.0638, "has_fulltext": false, "cited_by_count": + 22834, "citation_normalized_percentile": {"value": 1.0, "is_in_top_1_percent": true, "is_in_top_10_percent": true}, "cited_by_percentile_year": {"min": 99, "max": 100}, "biblio": {"volume": "162", "issue": "3859", "first_page": "1243", "last_page": "1248"}, "is_retracted": false, "is_paratext": false, "is_xpac": @@ -345,9 +345,9 @@ http_interactions: "host_organization_lineage_names": [], "type": "repository"}, "license": null, "license_id": null, "version": "publishedVersion", "is_accepted": true, "is_published": true, "raw_source_name": "Science (New York, N.Y.)", "raw_type": null}], "best_oa_location": - null, "sustainable_development_goals": [{"score": 0.4300000071525574, "display_name": - "Peace, Justice and strong institutions", "id": "https://metadata.un.org/sdg/16"}], - "awards": [], "funders": [], "has_content": {"grobid_xml": false, "pdf": false}, + null, "sustainable_development_goals": [{"display_name": "Peace, Justice and + strong institutions", "id": "https://metadata.un.org/sdg/16", "score": 0.4300000071525574}], + "awards": [], "funders": [], "has_content": {"pdf": false, "grobid_xml": false}, "content_urls": null, "referenced_works_count": 16, "referenced_works": ["https://openalex.org/W645218623", "https://openalex.org/W1520891760", "https://openalex.org/W1546755579", "https://openalex.org/W1967161129", "https://openalex.org/W2027636702", "https://openalex.org/W2029363644", "https://openalex.org/W2054383667", @@ -361,14 +361,14 @@ http_interactions: {"The": [0], "population": [1], "problem": [2], "has": [3], "no": [4], "technical": [5], "solution;": [6], "it": [7], "requires": [8], "a": [9], "fundamental": [10], "extension": [11], "in": [12], "morality.": [13]}, "counts_by_year": - [{"year": 2026, "cited_by_count": 306}, {"year": 2025, "cited_by_count": 830}, + [{"year": 2026, "cited_by_count": 307}, {"year": 2025, "cited_by_count": 831}, {"year": 2024, "cited_by_count": 914}, {"year": 2023, "cited_by_count": 860}, {"year": 2022, "cited_by_count": 898}, {"year": 2021, "cited_by_count": 1169}, {"year": 2020, "cited_by_count": 1230}, {"year": 2019, "cited_by_count": 1132}, - {"year": 2018, "cited_by_count": 1048}, {"year": 2017, "cited_by_count": 969}, + {"year": 2018, "cited_by_count": 1049}, {"year": 2017, "cited_by_count": 969}, {"year": 2016, "cited_by_count": 956}, {"year": 2015, "cited_by_count": 909}, - {"year": 2014, "cited_by_count": 1013}, {"year": 2013, "cited_by_count": 921}, - {"year": 2012, "cited_by_count": 889}], "updated_date": "2026-05-23T08:51:43.019350", + {"year": 2014, "cited_by_count": 1014}, {"year": 2013, "cited_by_count": 921}, + {"year": 2012, "cited_by_count": 889}], "updated_date": "2026-05-24T08:33:08.758527", "created_date": "2016-06-24T00:00:00"}], "group_by": []}' - recorded_at: 2026-05-24 08:50:26 + recorded_at: 2026-05-24 19:44:33 recorded_with: VCR-vcr/2.1.0 diff --git a/tests/testthat/_vcr/fp_retrieve_article_doi_error.yml b/tests/testthat/_vcr/fp_retrieve_article_doi_error.yml new file mode 100644 index 0000000..d38dd1b --- /dev/null +++ b/tests/testthat/_vcr/fp_retrieve_article_doi_error.yml @@ -0,0 +1,39 @@ +http_interactions: +- request: + method: GET + uri: https://api.openalex.org/works?filter=title.search%3A&sort=relevance_score%3Adesc&select=doi%2Cdisplay_name%2Cpublication_year%2Cprimary_location&per-page=1&mailto=anonymous%40mail.com + response: + status: 400 + headers: + date: Sun, 24 May 2026 19:44:37 GMT + content-type: application/json + content-length: '180' + cf-ray: a00ecbc96f476cf5-MRS + cf-cache-status: DYNAMIC + access-control-allow-origin: '*' + server: cloudflare + via: 1.1 heroku-router + access-control-allow-headers: Accept, Accept-Language, Accept-Encoding, Authorization, + Content-Type + access-control-allow-methods: GET, HEAD, POST, OPTIONS + nel: '{"report_to":"heroku-nel","response_headers":["Via"],"max_age":3600,"success_fraction":0.01,"failure_fraction":0.1}' + report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=MN8byXCtw78O3Da%2BEZul6WEgvNNG9mtDvuE0boi%2B9QE%3D\u0026sid=e11707d5-02a7-43ef-b45e-2cf4d2036f7d\u0026ts=1779651877"}],"max_age":3600}' + reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=MN8byXCtw78O3Da%2BEZul6WEgvNNG9mtDvuE0boi%2B9QE%3D&sid=e11707d5-02a7-43ef-b45e-2cf4d2036f7d&ts=1779651877" + x-ratelimit-cost-usd: '0.001' + x-ratelimit-credits-used: '10' + x-ratelimit-limit: '10000' + x-ratelimit-limit-usd: '1' + x-ratelimit-onetime-remaining: '0' + x-ratelimit-prepaid-remaining-usd: '0' + x-ratelimit-remaining: '9522' + x-ratelimit-remaining-usd: '0.9522' + x-ratelimit-reset: '15323' + access-control-expose-headers: Cache-Control, X-RateLimit-Limit, X-RateLimit-Remaining, + X-RateLimit-Onetime-Remaining, X-RateLimit-Credits-Used, X-RateLimit-Credits-Required, + X-RateLimit-Reset, X-RateLimit-Limit-USD, X-RateLimit-Remaining-USD, X-RateLimit-Prepaid-Remaining-USD, + X-RateLimit-Cost-USD, X-RateLimit-Cost-Required-USD, Retry-After + body: + string: | + {"error":"Invalid query parameters error.","message":"Invalid filter value for 'title.search': value cannot be empty or ''. Use a valid value like filter=title.search:your_value"} + recorded_at: 2026-05-24 19:44:37 +recorded_with: VCR-vcr/2.1.0 diff --git a/tests/testthat/_vcr/fp_retrieve_article_doi_manymatches.yml b/tests/testthat/_vcr/fp_retrieve_article_doi_manymatches.yml new file mode 100644 index 0000000..cf27ea6 --- /dev/null +++ b/tests/testthat/_vcr/fp_retrieve_article_doi_manymatches.yml @@ -0,0 +1,152 @@ +http_interactions: +- request: + method: GET + uri: https://api.openalex.org/works?filter=title.search%3ACitation+landscape&sort=relevance_score%3Adesc&select=doi%2Cdisplay_name%2Cpublication_year%2Cprimary_location&per-page=1&mailto=anonymous%40mail.com + response: + status: 200 + headers: + date: Sun, 24 May 2026 19:44:38 GMT + content-type: application/json + cf-ray: a00ecbd14c6e6cf5-MRS + cf-cache-status: DYNAMIC + access-control-allow-origin: '*' + server: cloudflare + via: 1.1 heroku-router + access-control-allow-headers: Accept, Accept-Language, Accept-Encoding, Authorization, + Content-Type + access-control-allow-methods: GET, HEAD, POST, OPTIONS + nel: '{"report_to":"heroku-nel","response_headers":["Via"],"max_age":3600,"success_fraction":0.01,"failure_fraction":0.1}' + report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=eNzWtXxqByEfeyLe%2FVP0OOvTjVV0VksyrQUC16UHTc8%3D\u0026sid=e11707d5-02a7-43ef-b45e-2cf4d2036f7d\u0026ts=1779651878"}],"max_age":3600}' + reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=eNzWtXxqByEfeyLe%2FVP0OOvTjVV0VksyrQUC16UHTc8%3D&sid=e11707d5-02a7-43ef-b45e-2cf4d2036f7d&ts=1779651878" + x-ratelimit-cost-usd: '0.001' + x-ratelimit-credits-used: '10' + x-ratelimit-limit: '10000' + x-ratelimit-limit-usd: '1' + x-ratelimit-onetime-remaining: '0' + x-ratelimit-prepaid-remaining-usd: '0' + x-ratelimit-remaining: '9492' + x-ratelimit-remaining-usd: '0.9492' + x-ratelimit-reset: '15322' + access-control-expose-headers: Cache-Control, X-RateLimit-Limit, X-RateLimit-Remaining, + X-RateLimit-Onetime-Remaining, X-RateLimit-Credits-Used, X-RateLimit-Credits-Required, + X-RateLimit-Reset, X-RateLimit-Limit-USD, X-RateLimit-Remaining-USD, X-RateLimit-Prepaid-Remaining-USD, + X-RateLimit-Cost-USD, X-RateLimit-Cost-Required-USD, Retry-After + content-encoding: br + body: + string: '{"meta": {"count": 114, "db_response_time_ms": 8, "page": 1, "per_page": + 1, "groups_count": null, "cost_usd": 0.001}, "results": [{"doi": "https://doi.org/10.1016/j.datak.2008.05.004", + "display_name": "The thematic and citation landscape of Data and Knowledge + Engineering (1985\u20132007)", "publication_year": 2008, "primary_location": + {"id": "doi:10.1016/j.datak.2008.05.004", "is_oa": false, "landing_page_url": + "https://doi.org/10.1016/j.datak.2008.05.004", "pdf_url": null, "source": + {"id": "https://openalex.org/S136993123", "display_name": "Data & Knowledge + Engineering", "issn_l": "0169-023X", "issn": ["0169-023X", "1872-6933"], "is_oa": + false, "is_in_doaj": false, "is_core": true, "host_organization": "https://openalex.org/P4310320990", + "host_organization_name": "Elsevier BV", "host_organization_lineage": ["https://openalex.org/P4310320990"], + "host_organization_lineage_names": ["Elsevier BV"], "type": "journal"}, "license": + null, "license_id": null, "version": "publishedVersion", "is_accepted": true, + "is_published": true, "raw_source_name": "Data & Knowledge Engineering", + "raw_type": "journal-article"}}], "group_by": []}' + recorded_at: 2026-05-24 19:44:38 +- request: + method: GET + uri: https://api.openalex.org/works?filter=title.search%3ACitation+landscape&sort=relevance_score%3Adesc&select=doi%2Cdisplay_name%2Cpublication_year%2Cprimary_location&per-page=5&mailto=anonymous%40mail.com&page=1 + response: + status: 200 + headers: + date: Sun, 24 May 2026 19:44:39 GMT + content-type: application/json + cf-ray: a00ecbd3de116cf5-MRS + cf-cache-status: DYNAMIC + access-control-allow-origin: '*' + server: cloudflare + via: 1.1 heroku-router + access-control-allow-headers: Accept, Accept-Language, Accept-Encoding, Authorization, + Content-Type + access-control-allow-methods: GET, HEAD, POST, OPTIONS + nel: '{"report_to":"heroku-nel","response_headers":["Via"],"max_age":3600,"success_fraction":0.01,"failure_fraction":0.1}' + report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=dJGHcswUJhd7Ur9ZkJGTZc7V9faC2u8QbEUnQEQ4cP0%3D\u0026sid=e11707d5-02a7-43ef-b45e-2cf4d2036f7d\u0026ts=1779651879"}],"max_age":3600}' + reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=dJGHcswUJhd7Ur9ZkJGTZc7V9faC2u8QbEUnQEQ4cP0%3D&sid=e11707d5-02a7-43ef-b45e-2cf4d2036f7d&ts=1779651879" + x-ratelimit-cost-usd: '0.001' + x-ratelimit-credits-used: '10' + x-ratelimit-limit: '10000' + x-ratelimit-limit-usd: '1' + x-ratelimit-onetime-remaining: '0' + x-ratelimit-prepaid-remaining-usd: '0' + x-ratelimit-remaining: '9482' + x-ratelimit-remaining-usd: '0.9482' + x-ratelimit-reset: '15321' + access-control-expose-headers: Cache-Control, X-RateLimit-Limit, X-RateLimit-Remaining, + X-RateLimit-Onetime-Remaining, X-RateLimit-Credits-Used, X-RateLimit-Credits-Required, + X-RateLimit-Reset, X-RateLimit-Limit-USD, X-RateLimit-Remaining-USD, X-RateLimit-Prepaid-Remaining-USD, + X-RateLimit-Cost-USD, X-RateLimit-Cost-Required-USD, Retry-After + content-encoding: br + body: + string: '{"meta": {"count": 114, "db_response_time_ms": 8, "page": 1, "per_page": + 5, "groups_count": null, "cost_usd": 0.001}, "results": [{"doi": "https://doi.org/10.1016/j.datak.2008.05.004", + "display_name": "The thematic and citation landscape of Data and Knowledge + Engineering (1985\u20132007)", "publication_year": 2008, "primary_location": + {"id": "doi:10.1016/j.datak.2008.05.004", "is_oa": false, "landing_page_url": + "https://doi.org/10.1016/j.datak.2008.05.004", "pdf_url": null, "source": + {"id": "https://openalex.org/S136993123", "display_name": "Data & Knowledge + Engineering", "issn_l": "0169-023X", "issn": ["0169-023X", "1872-6933"], "is_oa": + false, "is_in_doaj": false, "is_core": true, "host_organization": "https://openalex.org/P4310320990", + "host_organization_name": "Elsevier BV", "host_organization_lineage": ["https://openalex.org/P4310320990"], + "host_organization_lineage_names": ["Elsevier BV"], "type": "journal"}, "license": + null, "license_id": null, "version": "publishedVersion", "is_accepted": true, + "is_published": true, "raw_source_name": "Data & Knowledge Engineering", + "raw_type": "journal-article"}}, {"doi": "https://doi.org/10.1109/tfuzz.2017.2672732", + "display_name": "The Structure and Citation Landscape of IEEE Transactions + on Fuzzy Systems (1994\u20132015)", "publication_year": 2017, "primary_location": + {"id": "doi:10.1109/tfuzz.2017.2672732", "is_oa": false, "landing_page_url": + "https://doi.org/10.1109/tfuzz.2017.2672732", "pdf_url": null, "source": {"id": + "https://openalex.org/S134177497", "display_name": "IEEE Transactions on Fuzzy + Systems", "issn_l": "1063-6706", "issn": ["1063-6706", "1941-0034"], "is_oa": + false, "is_in_doaj": false, "is_core": true, "host_organization": "https://openalex.org/P4310319808", + "host_organization_name": "Institute of Electrical and Electronics Engineers", + "host_organization_lineage": ["https://openalex.org/P4310319808"], "host_organization_lineage_names": + ["Institute of Electrical and Electronics Engineers"], "type": "journal"}, + "license": null, "license_id": null, "version": "publishedVersion", "is_accepted": + true, "is_published": true, "raw_source_name": "IEEE Transactions on Fuzzy + Systems", "raw_type": "journal-article"}}, {"doi": "https://doi.org/10.1016/j.jbusres.2016.11.009", + "display_name": "Mapping the luxury research landscape: A bibliometric citation + analysis", "publication_year": 2016, "primary_location": {"id": "doi:10.1016/j.jbusres.2016.11.009", + "is_oa": false, "landing_page_url": "https://doi.org/10.1016/j.jbusres.2016.11.009", + "pdf_url": null, "source": {"id": "https://openalex.org/S93284759", "display_name": + "Journal of Business Research", "issn_l": "0148-2963", "issn": ["0148-2963", + "1873-7978"], "is_oa": false, "is_in_doaj": false, "is_core": true, "host_organization": + "https://openalex.org/P4310320990", "host_organization_name": "Elsevier BV", + "host_organization_lineage": ["https://openalex.org/P4310320990"], "host_organization_lineage_names": + ["Elsevier BV"], "type": "journal"}, "license": null, "license_id": null, + "version": "publishedVersion", "is_accepted": true, "is_published": true, + "raw_source_name": "Journal of Business Research", "raw_type": "journal-article"}}, + {"doi": "https://doi.org/10.1007/s11625-007-0027-8", "display_name": "Creating + an academic landscape of sustainability science: an analysis of the citation + network", "publication_year": 2007, "primary_location": {"id": "doi:10.1007/s11625-007-0027-8", + "is_oa": true, "landing_page_url": "https://doi.org/10.1007/s11625-007-0027-8", + "pdf_url": "https://link.springer.com/content/pdf/10.1007/s11625-007-0027-8.pdf", + "source": {"id": "https://openalex.org/S135086837", "display_name": "Sustainability + Science", "issn_l": "1862-4057", "issn": ["1862-4057", "1862-4065"], "is_oa": + false, "is_in_doaj": false, "is_core": true, "host_organization": "https://openalex.org/P4310319900", + "host_organization_name": "Springer Science+Business Media", "host_organization_lineage": + ["https://openalex.org/P4310319900", "https://openalex.org/P4310319965"], + "host_organization_lineage_names": ["Springer Science+Business Media", "Springer + Nature"], "type": "journal"}, "license": "cc-by-nc", "license_id": "https://openalex.org/licenses/cc-by-nc", + "version": "publishedVersion", "is_accepted": true, "is_published": true, + "raw_source_name": "Sustainability Science", "raw_type": "journal-article"}}, + {"doi": "https://doi.org/10.1007/s11135-023-01626-7", "display_name": "Twenty + years of Wikipedia in scholarly publications: a bibliometric network analysis + of the thematic and citation landscape", "publication_year": 2023, "primary_location": + {"id": "doi:10.1007/s11135-023-01626-7", "is_oa": false, "landing_page_url": + "https://doi.org/10.1007/s11135-023-01626-7", "pdf_url": null, "source": {"id": + "https://openalex.org/S102399824", "display_name": "Quality & Quantity", "issn_l": + "0033-5177", "issn": ["0033-5177", "1573-7845"], "is_oa": false, "is_in_doaj": + false, "is_core": true, "host_organization": "https://openalex.org/P4310319900", + "host_organization_name": "Springer Science+Business Media", "host_organization_lineage": + ["https://openalex.org/P4310319900", "https://openalex.org/P4310319965"], + "host_organization_lineage_names": ["Springer Science+Business Media", "Springer + Nature"], "type": "journal"}, "license": null, "license_id": null, "version": + "publishedVersion", "is_accepted": true, "is_published": true, "raw_source_name": + "Quality & Quantity", "raw_type": "journal-article"}}], "group_by": []}' + recorded_at: 2026-05-24 19:44:39 +recorded_with: VCR-vcr/2.1.0 diff --git a/tests/testthat/_vcr/fp_retrieve_article_doi_manymatches_w_n.yml b/tests/testthat/_vcr/fp_retrieve_article_doi_manymatches_w_n.yml new file mode 100644 index 0000000..e88b020 --- /dev/null +++ b/tests/testthat/_vcr/fp_retrieve_article_doi_manymatches_w_n.yml @@ -0,0 +1,125 @@ +http_interactions: +- request: + method: GET + uri: https://api.openalex.org/works?filter=title.search%3ACitation+landscape&sort=relevance_score%3Adesc&select=doi%2Cdisplay_name%2Cpublication_year%2Cprimary_location&per-page=1&mailto=anonymous%40mail.com + response: + status: 200 + headers: + date: Sun, 24 May 2026 19:44:39 GMT + content-type: application/json + cf-ray: a00ecbd67fa26cf5-MRS + cf-cache-status: DYNAMIC + access-control-allow-origin: '*' + server: cloudflare + via: 1.1 heroku-router + access-control-allow-headers: Accept, Accept-Language, Accept-Encoding, Authorization, + Content-Type + access-control-allow-methods: GET, HEAD, POST, OPTIONS + nel: '{"report_to":"heroku-nel","response_headers":["Via"],"max_age":3600,"success_fraction":0.01,"failure_fraction":0.1}' + report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=dJGHcswUJhd7Ur9ZkJGTZc7V9faC2u8QbEUnQEQ4cP0%3D\u0026sid=e11707d5-02a7-43ef-b45e-2cf4d2036f7d\u0026ts=1779651879"}],"max_age":3600}' + reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=dJGHcswUJhd7Ur9ZkJGTZc7V9faC2u8QbEUnQEQ4cP0%3D&sid=e11707d5-02a7-43ef-b45e-2cf4d2036f7d&ts=1779651879" + x-ratelimit-cost-usd: '0.001' + x-ratelimit-credits-used: '10' + x-ratelimit-limit: '10000' + x-ratelimit-limit-usd: '1' + x-ratelimit-onetime-remaining: '0' + x-ratelimit-prepaid-remaining-usd: '0' + x-ratelimit-remaining: '9472' + x-ratelimit-remaining-usd: '0.9472' + x-ratelimit-reset: '15321' + access-control-expose-headers: Cache-Control, X-RateLimit-Limit, X-RateLimit-Remaining, + X-RateLimit-Onetime-Remaining, X-RateLimit-Credits-Used, X-RateLimit-Credits-Required, + X-RateLimit-Reset, X-RateLimit-Limit-USD, X-RateLimit-Remaining-USD, X-RateLimit-Prepaid-Remaining-USD, + X-RateLimit-Cost-USD, X-RateLimit-Cost-Required-USD, Retry-After + content-encoding: br + body: + string: '{"meta": {"count": 114, "db_response_time_ms": 7, "page": 1, "per_page": + 1, "groups_count": null, "cost_usd": 0.001}, "results": [{"doi": "https://doi.org/10.1016/j.datak.2008.05.004", + "display_name": "The thematic and citation landscape of Data and Knowledge + Engineering (1985\u20132007)", "publication_year": 2008, "primary_location": + {"id": "doi:10.1016/j.datak.2008.05.004", "is_oa": false, "landing_page_url": + "https://doi.org/10.1016/j.datak.2008.05.004", "pdf_url": null, "source": + {"id": "https://openalex.org/S136993123", "display_name": "Data & Knowledge + Engineering", "issn_l": "0169-023X", "issn": ["0169-023X", "1872-6933"], "is_oa": + false, "is_in_doaj": false, "is_core": true, "host_organization": "https://openalex.org/P4310320990", + "host_organization_name": "Elsevier BV", "host_organization_lineage": ["https://openalex.org/P4310320990"], + "host_organization_lineage_names": ["Elsevier BV"], "type": "journal"}, "license": + null, "license_id": null, "version": "publishedVersion", "is_accepted": true, + "is_published": true, "raw_source_name": "Data & Knowledge Engineering", + "raw_type": "journal-article"}}], "group_by": []}' + recorded_at: 2026-05-24 19:44:39 +- request: + method: GET + uri: https://api.openalex.org/works?filter=title.search%3ACitation+landscape&sort=relevance_score%3Adesc&select=doi%2Cdisplay_name%2Cpublication_year%2Cprimary_location&per-page=3&mailto=anonymous%40mail.com&page=1 + response: + status: 200 + headers: + date: Sun, 24 May 2026 19:44:39 GMT + content-type: application/json + cf-ray: a00ecbd8f95d6cf5-MRS + cf-cache-status: DYNAMIC + access-control-allow-origin: '*' + server: cloudflare + via: 1.1 heroku-router + access-control-allow-headers: Accept, Accept-Language, Accept-Encoding, Authorization, + Content-Type + access-control-allow-methods: GET, HEAD, POST, OPTIONS + nel: '{"report_to":"heroku-nel","response_headers":["Via"],"max_age":3600,"success_fraction":0.01,"failure_fraction":0.1}' + report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=dJGHcswUJhd7Ur9ZkJGTZc7V9faC2u8QbEUnQEQ4cP0%3D\u0026sid=e11707d5-02a7-43ef-b45e-2cf4d2036f7d\u0026ts=1779651879"}],"max_age":3600}' + reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=dJGHcswUJhd7Ur9ZkJGTZc7V9faC2u8QbEUnQEQ4cP0%3D&sid=e11707d5-02a7-43ef-b45e-2cf4d2036f7d&ts=1779651879" + x-ratelimit-cost-usd: '0.001' + x-ratelimit-credits-used: '10' + x-ratelimit-limit: '10000' + x-ratelimit-limit-usd: '1' + x-ratelimit-onetime-remaining: '0' + x-ratelimit-prepaid-remaining-usd: '0' + x-ratelimit-remaining: '9462' + x-ratelimit-remaining-usd: '0.9462' + x-ratelimit-reset: '15321' + access-control-expose-headers: Cache-Control, X-RateLimit-Limit, X-RateLimit-Remaining, + X-RateLimit-Onetime-Remaining, X-RateLimit-Credits-Used, X-RateLimit-Credits-Required, + X-RateLimit-Reset, X-RateLimit-Limit-USD, X-RateLimit-Remaining-USD, X-RateLimit-Prepaid-Remaining-USD, + X-RateLimit-Cost-USD, X-RateLimit-Cost-Required-USD, Retry-After + content-encoding: br + body: + string: '{"meta": {"count": 114, "db_response_time_ms": 18, "page": 1, "per_page": + 3, "groups_count": null, "cost_usd": 0.001}, "results": [{"doi": "https://doi.org/10.1016/j.datak.2008.05.004", + "display_name": "The thematic and citation landscape of Data and Knowledge + Engineering (1985\u20132007)", "publication_year": 2008, "primary_location": + {"id": "doi:10.1016/j.datak.2008.05.004", "is_oa": false, "landing_page_url": + "https://doi.org/10.1016/j.datak.2008.05.004", "pdf_url": null, "source": + {"id": "https://openalex.org/S136993123", "display_name": "Data & Knowledge + Engineering", "issn_l": "0169-023X", "issn": ["0169-023X", "1872-6933"], "is_oa": + false, "is_in_doaj": false, "is_core": true, "host_organization": "https://openalex.org/P4310320990", + "host_organization_name": "Elsevier BV", "host_organization_lineage": ["https://openalex.org/P4310320990"], + "host_organization_lineage_names": ["Elsevier BV"], "type": "journal"}, "license": + null, "license_id": null, "version": "publishedVersion", "is_accepted": true, + "is_published": true, "raw_source_name": "Data & Knowledge Engineering", + "raw_type": "journal-article"}}, {"doi": "https://doi.org/10.1109/tfuzz.2017.2672732", + "display_name": "The Structure and Citation Landscape of IEEE Transactions + on Fuzzy Systems (1994\u20132015)", "publication_year": 2017, "primary_location": + {"id": "doi:10.1109/tfuzz.2017.2672732", "is_oa": false, "landing_page_url": + "https://doi.org/10.1109/tfuzz.2017.2672732", "pdf_url": null, "source": {"id": + "https://openalex.org/S134177497", "display_name": "IEEE Transactions on Fuzzy + Systems", "issn_l": "1063-6706", "issn": ["1063-6706", "1941-0034"], "is_oa": + false, "is_in_doaj": false, "is_core": true, "host_organization": "https://openalex.org/P4310319808", + "host_organization_name": "Institute of Electrical and Electronics Engineers", + "host_organization_lineage": ["https://openalex.org/P4310319808"], "host_organization_lineage_names": + ["Institute of Electrical and Electronics Engineers"], "type": "journal"}, + "license": null, "license_id": null, "version": "publishedVersion", "is_accepted": + true, "is_published": true, "raw_source_name": "IEEE Transactions on Fuzzy + Systems", "raw_type": "journal-article"}}, {"doi": "https://doi.org/10.1016/j.jbusres.2016.11.009", + "display_name": "Mapping the luxury research landscape: A bibliometric citation + analysis", "publication_year": 2016, "primary_location": {"id": "doi:10.1016/j.jbusres.2016.11.009", + "is_oa": false, "landing_page_url": "https://doi.org/10.1016/j.jbusres.2016.11.009", + "pdf_url": null, "source": {"id": "https://openalex.org/S93284759", "display_name": + "Journal of Business Research", "issn_l": "0148-2963", "issn": ["0148-2963", + "1873-7978"], "is_oa": false, "is_in_doaj": false, "is_core": true, "host_organization": + "https://openalex.org/P4310320990", "host_organization_name": "Elsevier BV", + "host_organization_lineage": ["https://openalex.org/P4310320990"], "host_organization_lineage_names": + ["Elsevier BV"], "type": "journal"}, "license": null, "license_id": null, + "version": "publishedVersion", "is_accepted": true, "is_published": true, + "raw_source_name": "Journal of Business Research", "raw_type": "journal-article"}}], + "group_by": []}' + recorded_at: 2026-05-24 19:44:40 +recorded_with: VCR-vcr/2.1.0 diff --git a/tests/testthat/_vcr/fp_retrieve_article_doi_nomatch.yml b/tests/testthat/_vcr/fp_retrieve_article_doi_nomatch.yml new file mode 100644 index 0000000..8883cd0 --- /dev/null +++ b/tests/testthat/_vcr/fp_retrieve_article_doi_nomatch.yml @@ -0,0 +1,39 @@ +http_interactions: +- request: + method: GET + uri: https://api.openalex.org/works?filter=title.search%3Akjdhfgvlzjegvz&sort=relevance_score%3Adesc&select=doi%2Cdisplay_name%2Cpublication_year%2Cprimary_location&per-page=1&mailto=anonymous%40mail.com + response: + status: 200 + headers: + date: Sun, 24 May 2026 19:44:40 GMT + content-type: application/json + cf-ray: a00ecbdb9b116cf5-MRS + cf-cache-status: DYNAMIC + access-control-allow-origin: '*' + server: cloudflare + via: 1.1 heroku-router + access-control-allow-headers: Accept, Accept-Language, Accept-Encoding, Authorization, + Content-Type + access-control-allow-methods: GET, HEAD, POST, OPTIONS + nel: '{"report_to":"heroku-nel","response_headers":["Via"],"max_age":3600,"success_fraction":0.01,"failure_fraction":0.1}' + report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=3jbLfa2gbmn8HZ1Lp4HCgP1G5iTImntjh2KPUBzBLQQ%3D\u0026sid=e11707d5-02a7-43ef-b45e-2cf4d2036f7d\u0026ts=1779651880"}],"max_age":3600}' + reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=3jbLfa2gbmn8HZ1Lp4HCgP1G5iTImntjh2KPUBzBLQQ%3D&sid=e11707d5-02a7-43ef-b45e-2cf4d2036f7d&ts=1779651880" + x-ratelimit-cost-usd: '0.001' + x-ratelimit-credits-used: '10' + x-ratelimit-limit: '10000' + x-ratelimit-limit-usd: '1' + x-ratelimit-onetime-remaining: '0' + x-ratelimit-prepaid-remaining-usd: '0' + x-ratelimit-remaining: '9452' + x-ratelimit-remaining-usd: '0.9452' + x-ratelimit-reset: '15320' + access-control-expose-headers: Cache-Control, X-RateLimit-Limit, X-RateLimit-Remaining, + X-RateLimit-Onetime-Remaining, X-RateLimit-Credits-Used, X-RateLimit-Credits-Required, + X-RateLimit-Reset, X-RateLimit-Limit-USD, X-RateLimit-Remaining-USD, X-RateLimit-Prepaid-Remaining-USD, + X-RateLimit-Cost-USD, X-RateLimit-Cost-Required-USD, Retry-After + content-encoding: br + body: + string: '{"meta": {"count": 0, "db_response_time_ms": 3, "page": 1, "per_page": + 1, "groups_count": null, "cost_usd": 0.001}, "results": [], "group_by": []}' + recorded_at: 2026-05-24 19:44:40 +recorded_with: VCR-vcr/2.1.0 diff --git a/tests/testthat/_vcr/fp_retrieve_article_doi_onematch.yml b/tests/testthat/_vcr/fp_retrieve_article_doi_onematch.yml new file mode 100644 index 0000000..b00c77c --- /dev/null +++ b/tests/testthat/_vcr/fp_retrieve_article_doi_onematch.yml @@ -0,0 +1,102 @@ +http_interactions: +- request: + method: GET + uri: https://api.openalex.org/works?filter=title.search%3ACitation+self-awareness+for+a+fairer+academic+publishing+landscape&sort=relevance_score%3Adesc&select=doi%2Cdisplay_name%2Cpublication_year%2Cprimary_location&per-page=1&mailto=anonymous%40mail.com + response: + status: 200 + headers: + date: Sun, 24 May 2026 19:44:37 GMT + content-type: application/json + cf-ray: a00ecbcc38ed6cf5-MRS + cf-cache-status: DYNAMIC + access-control-allow-origin: '*' + server: cloudflare + via: 1.1 heroku-router + access-control-allow-headers: Accept, Accept-Language, Accept-Encoding, Authorization, + Content-Type + access-control-allow-methods: GET, HEAD, POST, OPTIONS + nel: '{"report_to":"heroku-nel","response_headers":["Via"],"max_age":3600,"success_fraction":0.01,"failure_fraction":0.1}' + report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=MN8byXCtw78O3Da%2BEZul6WEgvNNG9mtDvuE0boi%2B9QE%3D\u0026sid=e11707d5-02a7-43ef-b45e-2cf4d2036f7d\u0026ts=1779651877"}],"max_age":3600}' + reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=MN8byXCtw78O3Da%2BEZul6WEgvNNG9mtDvuE0boi%2B9QE%3D&sid=e11707d5-02a7-43ef-b45e-2cf4d2036f7d&ts=1779651877" + x-ratelimit-cost-usd: '0.001' + x-ratelimit-credits-used: '10' + x-ratelimit-limit: '10000' + x-ratelimit-limit-usd: '1' + x-ratelimit-onetime-remaining: '0' + x-ratelimit-prepaid-remaining-usd: '0' + x-ratelimit-remaining: '9512' + x-ratelimit-remaining-usd: '0.9512' + x-ratelimit-reset: '15323' + access-control-expose-headers: Cache-Control, X-RateLimit-Limit, X-RateLimit-Remaining, + X-RateLimit-Onetime-Remaining, X-RateLimit-Credits-Used, X-RateLimit-Credits-Required, + X-RateLimit-Reset, X-RateLimit-Limit-USD, X-RateLimit-Remaining-USD, X-RateLimit-Prepaid-Remaining-USD, + X-RateLimit-Cost-USD, X-RateLimit-Cost-Required-USD, Retry-After + content-encoding: br + body: + string: '{"meta": {"count": 1, "db_response_time_ms": 17, "page": 1, "per_page": + 1, "groups_count": null, "cost_usd": 0.001}, "results": [{"doi": "https://doi.org/10.1093/biosci/biag028", + "display_name": "Citation self-awareness for a fairer academic publishing + landscape", "publication_year": 2026, "primary_location": {"id": "doi:10.1093/biosci/biag028", + "is_oa": true, "landing_page_url": "https://doi.org/10.1093/biosci/biag028", + "pdf_url": null, "source": {"id": "https://openalex.org/S121830084", "display_name": + "BioScience", "issn_l": "0006-3568", "issn": ["0006-3568", "1525-3244"], "is_oa": + false, "is_in_doaj": false, "is_core": true, "host_organization": "https://openalex.org/P4310311648", + "host_organization_name": "Oxford University Press", "host_organization_lineage": + ["https://openalex.org/P4310311648", "https://openalex.org/P4310311647"], + "host_organization_lineage_names": ["Oxford University Press", "University + of Oxford"], "type": "journal"}, "license": "cc-by", "license_id": "https://openalex.org/licenses/cc-by", + "version": "publishedVersion", "is_accepted": true, "is_published": true, + "raw_source_name": "BioScience", "raw_type": "journal-article"}}], "group_by": + []}' + recorded_at: 2026-05-24 19:44:38 +- request: + method: GET + uri: https://api.openalex.org/works?filter=title.search%3ACitation+self-awareness+for+a+fairer+academic+publishing+landscape&sort=relevance_score%3Adesc&select=doi%2Cdisplay_name%2Cpublication_year%2Cprimary_location&per-page=5&mailto=anonymous%40mail.com&page=1 + response: + status: 200 + headers: + date: Sun, 24 May 2026 19:44:38 GMT + content-type: application/json + cf-ray: a00ecbceaa906cf5-MRS + cf-cache-status: DYNAMIC + access-control-allow-origin: '*' + server: cloudflare + via: 1.1 heroku-router + access-control-allow-headers: Accept, Accept-Language, Accept-Encoding, Authorization, + Content-Type + access-control-allow-methods: GET, HEAD, POST, OPTIONS + nel: '{"report_to":"heroku-nel","response_headers":["Via"],"max_age":3600,"success_fraction":0.01,"failure_fraction":0.1}' + report-to: '{"group":"heroku-nel","endpoints":[{"url":"https://nel.heroku.com/reports?s=eNzWtXxqByEfeyLe%2FVP0OOvTjVV0VksyrQUC16UHTc8%3D\u0026sid=e11707d5-02a7-43ef-b45e-2cf4d2036f7d\u0026ts=1779651878"}],"max_age":3600}' + reporting-endpoints: heroku-nel="https://nel.heroku.com/reports?s=eNzWtXxqByEfeyLe%2FVP0OOvTjVV0VksyrQUC16UHTc8%3D&sid=e11707d5-02a7-43ef-b45e-2cf4d2036f7d&ts=1779651878" + x-ratelimit-cost-usd: '0.001' + x-ratelimit-credits-used: '10' + x-ratelimit-limit: '10000' + x-ratelimit-limit-usd: '1' + x-ratelimit-onetime-remaining: '0' + x-ratelimit-prepaid-remaining-usd: '0' + x-ratelimit-remaining: '9502' + x-ratelimit-remaining-usd: '0.9502' + x-ratelimit-reset: '15322' + access-control-expose-headers: Cache-Control, X-RateLimit-Limit, X-RateLimit-Remaining, + X-RateLimit-Onetime-Remaining, X-RateLimit-Credits-Used, X-RateLimit-Credits-Required, + X-RateLimit-Reset, X-RateLimit-Limit-USD, X-RateLimit-Remaining-USD, X-RateLimit-Prepaid-Remaining-USD, + X-RateLimit-Cost-USD, X-RateLimit-Cost-Required-USD, Retry-After + content-encoding: br + body: + string: '{"meta": {"count": 1, "db_response_time_ms": 14, "page": 1, "per_page": + 5, "groups_count": null, "cost_usd": 0.001}, "results": [{"doi": "https://doi.org/10.1093/biosci/biag028", + "display_name": "Citation self-awareness for a fairer academic publishing + landscape", "publication_year": 2026, "primary_location": {"id": "doi:10.1093/biosci/biag028", + "is_oa": true, "landing_page_url": "https://doi.org/10.1093/biosci/biag028", + "pdf_url": null, "source": {"id": "https://openalex.org/S121830084", "display_name": + "BioScience", "issn_l": "0006-3568", "issn": ["0006-3568", "1525-3244"], "is_oa": + false, "is_in_doaj": false, "is_core": true, "host_organization": "https://openalex.org/P4310311648", + "host_organization_name": "Oxford University Press", "host_organization_lineage": + ["https://openalex.org/P4310311648", "https://openalex.org/P4310311647"], + "host_organization_lineage_names": ["Oxford University Press", "University + of Oxford"], "type": "journal"}, "license": "cc-by", "license_id": "https://openalex.org/licenses/cc-by", + "version": "publishedVersion", "is_accepted": true, "is_published": true, + "raw_source_name": "BioScience", "raw_type": "journal-article"}}], "group_by": + []}' + recorded_at: 2026-05-24 19:44:38 +recorded_with: VCR-vcr/2.1.0 diff --git a/tests/testthat/setup.R b/tests/testthat/setup.R index 0c459bc..5a4fd09 100644 --- a/tests/testthat/setup.R +++ b/tests/testthat/setup.R @@ -62,3 +62,6 @@ texte <- c( "Receveur A (2024) David vs Goliath... https://doi.org/10.1111/ele.14395", "Smith J (9999) This is a fake article." ) + +article_title <- + "Citation self-awareness for a fairer academic publishing landscape" diff --git a/tests/testthat/test-check_arg_n.R b/tests/testthat/test-check_arg_n.R new file mode 100644 index 0000000..8ce593b --- /dev/null +++ b/tests/testthat/test-check_arg_n.R @@ -0,0 +1,67 @@ +## check_arg_n() ---- + +test_that("check_arg_n() errors", { + expect_error( + check_arg_n(NULL), + "Argument 'n' is required", + fixed = TRUE + ) + + expect_error( + check_arg_n("12"), + "Argument 'n' must be an integer", + fixed = TRUE + ) + + expect_error( + check_arg_n(rep(12, 2)), + "Argument 'n' must be of length 1", + fixed = TRUE + ) + + expect_error( + check_arg_n(Inf), + "Argument 'n' must be finite", + fixed = TRUE + ) + + expect_error( + check_arg_n(-Inf), + "Argument 'n' must be finite", + fixed = TRUE + ) + + expect_error( + check_arg_n(NA_integer_), + "Argument 'n' must be finite", + fixed = TRUE + ) + + expect_error( + check_arg_n(12.4), + "Argument 'n' must be an integer", + fixed = TRUE + ) + + expect_error( + check_arg_n(-12.4), + "Argument 'n' must be an integer", + fixed = TRUE + ) + + expect_error( + check_arg_n(0), + "Argument 'n' must be a positive integer between 1 and 200", + fixed = TRUE + ) + + expect_error( + check_arg_n(201), + "Argument 'n' must be a positive integer between 1 and 200", + fixed = TRUE + ) +}) + +test_that("check_arg_n() works", { + expect_silent(check_arg_n(10)) +}) diff --git a/tests/testthat/test-fp_retrieve_article_doi.R b/tests/testthat/test-fp_retrieve_article_doi.R new file mode 100644 index 0000000..a30ec63 --- /dev/null +++ b/tests/testthat/test-fp_retrieve_article_doi.R @@ -0,0 +1,104 @@ +## fp_retrieve_article_doi() ---- + +test_that("fp_retrieve_article_doi() errors - No API query", { + expect_error( + fp_retrieve_article_doi(article_title), + paste0( + "Be polite with OpenAlex API and run: ", + "`options(openalexR.mailto = 'your_email')`" + ), + fixed = TRUE + ) + + withr::local_options( + list("openalexR.mailto" = NULL) + ) + + expect_error( + fp_retrieve_article_doi(article_title), + paste0( + "Be polite with OpenAlex API and run: ", + "`options(openalexR.mailto = 'your_email')`" + ), + fixed = TRUE + ) +}) + + +test_that("fp_retrieve_article_doi() errors - API query", { + withr::local_options( + list("openalexR.mailto" = "anonymous@mail.com") + ) + + vcr::use_cassette("fp_retrieve_article_doi_error", { + expect_error( + fp_retrieve_article_doi(""), + "Failed to retrieve data from OpenAlex", + fixed = TRUE + ) + }) +}) + + +test_that("fp_retrieve_article_doi() works - API query", { + withr::local_options( + list("openalexR.mailto" = "anonymous@mail.com") + ) + + vcr::use_cassette("fp_retrieve_article_doi_onematch", { + res <- fp_retrieve_article_doi(article_title) + }) + + expect_true(inherits(res, "data.frame")) + expect_equal(nrow(res), 1L) + expect_equal(ncol(res), 4L) + + expect_equal( + res[1, "display_name"], + "Citation self-awareness for a fairer academic..." + ) + + expect_equal( + res[1, "publication_year"], + 2026 + ) + + expect_equal( + res[1, "source_display_name"], + "BioScience" + ) + + expect_equal( + res[1, "doi"], + "10.1093/biosci/biag028" + ) + + vcr::use_cassette("fp_retrieve_article_doi_manymatches", { + res <- fp_retrieve_article_doi("Citation landscape") + }) + + expect_true(inherits(res, "data.frame")) + expect_equal(nrow(res), 5L) + expect_equal(ncol(res), 4L) + + vcr::use_cassette("fp_retrieve_article_doi_manymatches_w_n", { + res <- fp_retrieve_article_doi("Citation landscape", n = 3) + }) + + expect_true(inherits(res, "data.frame")) + expect_equal(nrow(res), 3L) + expect_equal(ncol(res), 4L) + + vcr::use_cassette("fp_retrieve_article_doi_nomatch", { + res <- suppressWarnings(fp_retrieve_article_doi("kjdhfgvlzjegvz")) + }) + + expect_true(inherits(res, "data.frame")) + expect_equal(nrow(res), 0L) + expect_equal(ncol(res), 4L) + + expect_true("display_name" %in% colnames(res)) + expect_true("publication_year" %in% colnames(res)) + expect_true("source_display_name" %in% colnames(res)) + expect_true("doi" %in% colnames(res)) +}) diff --git a/tests/testthat/test-fp_shorten_string.R b/tests/testthat/test-fp_shorten_string.R new file mode 100644 index 0000000..5e46ea4 --- /dev/null +++ b/tests/testthat/test-fp_shorten_string.R @@ -0,0 +1,9 @@ +## fp_shorten_string() ---- + +test_that("fp_shorten_string() works", { + expect_silent(res <- fp_shorten_string(article_title, 100)) + expect_equal(res, article_title) + + expect_silent(res <- fp_shorten_string(article_title, 30)) + expect_equal(res, "Citation self-awareness...") +})