Add blessCacheAs() to vouch for a file an older version wrote

Files from the 1.3.0.9000 development cycle already hold correctly
computed scores - the corrections landed there, before the release was
cut - but they say nothing about what wrote them, so the check added for
1.4.0 recomputes them. That is right in general and wrong for exactly
the files whose owners know better, and a collocation analysis they would
have to sit through again runs for hours.

blessCacheAs() records that a file holds what this version would compute.
What actually produced it is left as it stands and the blessing noted
beside it, so cacheAsInfo() goes on saying where the numbers come from
rather than claiming a provenance the file does not have.

A file recording no parameters, as those written before 1.3.0.9000 do,
has nothing left to compare against a call once blessed, and is reused
for any call naming it. Blessing one says so.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Change-Id: I0c46322154441b11547da205b2aa0fb5cf98371d
diff --git a/tests/testthat/test-cache-as.R b/tests/testthat/test-cache-as.R
index 0b56a9a..7b4b034 100644
--- a/tests/testthat/test-cache-as.R
+++ b/tests/testthat/test-cache-as.R
@@ -4,6 +4,51 @@
   expect_equal(RKorAPClient:::cacheAsFileName("analysis.RDS"), "analysis.RDS")
 })
 
+offlineKco <- function() {
+  methods::new(
+    "KorAPConnection",
+    apiUrl = "https://example.invalid/",
+    KorAPUrl = "https://example.invalid/",
+    authorizationSupported = FALSE,
+    verbose = FALSE
+  )
+}
+
+test_that("blessCacheAs makes an old file usable again", {
+  kco <- offlineKco()
+  file <- tempfile(fileext = ".rds")
+  on.exit(unlink(file), add = TRUE)
+  legacy <- tibble::tibble(node = "Test", collocate = "c", logDice = 7)
+  saveRDS(legacy, file)
+
+  testthat::local_mocked_bindings(
+    collocatesQuery = function(...) stop("server must not be contacted"),
+    .package = "RKorAPClient"
+  )
+
+  expect_message(blessCacheAs(file), "records no parameters")
+  expect_silent(result <- collocationAnalysis(kco, "Test", cacheAs = file))
+  expect_equal(result, legacy)
+})
+
+test_that("blessing records itself without claiming a provenance", {
+  file <- tempfile(fileext = ".rds")
+  on.exit(unlink(file), add = TRUE)
+  saveRDS(tibble::tibble(x = 1), file)
+
+  suppressMessages(blessCacheAs(file))
+  info <- cacheAsInfo(file)
+
+  expect_equal(info$scoresConfirmedFor, RKorAPClient:::cacheAsScoreVersion)
+  expect_s3_class(info$blessedAt, "POSIXct")
+  # what actually wrote the file is unknown and stays unclaimed
+  expect_null(info$packageVersion)
+})
+
+test_that("blessCacheAs refuses a file that is not there", {
+  expect_error(blessCacheAs(file.path(tempdir(), "no-such-cache.rds")), "does not exist")
+})
+
 test_that("cacheAsInfo says what produced a file", {
   skip_if_offline()
   kco <- KorAPConnection(accessToken = NULL, verbose = FALSE)