test_that("enrichment fetches missing abstracts and preserves metadata", {
calls <- character()
callback <- function(url, headers, params, timeout) {
calls <<- c(calls, url)
expect_equal(timeout, 7)
list(message = list(abstract = "Crossref result"))
}
original <- Article(
title = "Scopus title", authors = c("Ada", "Grace"),
publication_date = "2025-01-01", doi = "10.1000/paper"
)
articles <- list(first = original, second = Article(
title = "Already complete", doi = "10.1000/different", abstract = "Keep me"
))
enriched <- enrich_articles_with_crossref(
articles, requester = callback, timeout = 7
)
expect_identical(names(enriched), names(articles))
expect_equal(enriched$first$abstract, "Crossref result")
expect_equal(enriched$first$title, "Scopus title")
expect_identical(enriched$first$authors, c("Ada", "Grace"))
expect_equal(enriched$second$abstract, "Keep me")
expect_null(original$abstract)
expect_length(calls, 1L)
})
test_that("duplicate DOIs use one request and missing responses are cached", {
calls <- 0L
callback <- function(url, headers, params, timeout) {
calls <<- calls + 1L
list(message = list())
}
articles <- list(
Article(doi = " 10.1000/Duplicate "),
Article(doi = "10.1000/duplicate"),
Article(doi = "10.1000/duplicate", abstract = " ")
)
enriched <- enrich_articles_with_crossref(articles, requester = callback)
expect_equal(calls, 1L)
expect_null(enriched[[1L]]$abstract)
expect_equal(enriched[[3L]]$abstract, " ")
})
test_that("overwrite never destroys text when Crossref has no abstract", {
callback <- function(url, headers, params, timeout) list(message = list())
article <- Article(doi = "10.1000/example", abstract = "Scopus original")
enriched <- enrich_articles_with_crossref(
list(article), overwrite = TRUE, requester = callback
)
expect_identical(enriched[[1L]]$abstract, "Scopus original")
})
test_that("overwrite can explicitly replace existing text", {
callback <- function(url, headers, params, timeout) {
list(message = list(abstract = "Crossref replacement"))
}
article <- Article(doi = "10.1000/example", abstract = "Scopus original")
expect_equal(enrich_articles_with_crossref(
list(article), overwrite = TRUE, requester = callback
)[[1L]]$abstract, "Crossref replacement")
})
test_that("missing and blank DOIs never generate requests", {
callback <- function(url, headers, params, timeout) {
fail("Unexpected network call")
}
articles <- list(Article(), Article(doi = " "))
expect_identical(
enrich_articles_with_crossref(articles, requester = callback), articles
)
expect_identical(
enrich_articles_with_crossref(list(), requester = callback), list()
)
})
test_that("error policies stop warn or skip with original metadata intact", {
callback <- function(url, headers, params, timeout) stop("offline")
article <- Article(title = "Unchanged", doi = "10.1000/failure")
expect_error(enrich_articles_with_crossref(
list(article), requester = callback
), "Failed to retrieve")
expect_warning(
warning_result <- enrich_articles_with_crossref(
list(article), on_error = "warn", requester = callback
),
"Crossref lookup failed"
)
expect_identical(warning_result[[1L]], article)
expect_silent(
skip_result <- enrich_articles_with_crossref(
list(article), on_error = "skip", requester = callback
)
)
expect_identical(skip_result[[1L]], article)
})
test_that("input validation does not depend on a network connection", {
callback <- function(url, headers, params, timeout) list(message = list())
expect_error(enrich_articles_with_crossref(list(list()), requester = callback),
"Article")
expect_error(enrich_articles_with_crossref("invalid", requester = callback),
"list")
expect_error(enrich_articles_with_crossref(list(), overwrite = NA,
requester = callback), "overwrite")
expect_error(enrich_articles_with_crossref(list(), timeout = 0,
requester = callback), "timeout")
expect_error(enrich_articles_with_crossref(list(), requester = "not callable"),
"requester")
expect_error(enrich_articles_with_crossref(list(), on_error = "unknown",
requester = callback), "arg")
})