Add cacheAsInfo() to read back what produced a cache file

A cacheAs file records the parameters of the call, the KorAP instance,
the index revision that instance's corpus had at the time and the version
of RKorAPClient that wrote it - which is what makes such a file worth
keeping next to a document, and until now there was no documented way of
getting at it. cacheAsInfo() returns the record, or NULL for a file
written before 1.4.0, which holds none.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Change-Id: If39a8e331a008529fda06d91862e1c498534d78a
diff --git a/tests/testthat/test-cache-as.R b/tests/testthat/test-cache-as.R
index 2a15b75..0b56a9a 100644
--- a/tests/testthat/test-cache-as.R
+++ b/tests/testthat/test-cache-as.R
@@ -4,6 +4,38 @@
   expect_equal(RKorAPClient:::cacheAsFileName("analysis.RDS"), "analysis.RDS")
 })
 
+test_that("cacheAsInfo says what produced a file", {
+  skip_if_offline()
+  kco <- KorAPConnection(accessToken = NULL, verbose = FALSE)
+  file <- tempfile(fileext = ".rds")
+  on.exit(unlink(file), add = TRUE)
+
+  frequencyQuery(kco, "Ameisenplage", cacheAs = file)
+  info <- cacheAsInfo(file)
+
+  expect_equal(info$packageVersion, as.character(utils::packageVersion("RKorAPClient")))
+  expect_equal(info$apiUrl, kco@apiUrl)
+  expect_equal(info$indexRevision, kco@indexRevision)
+  expect_equal(info$parameters$query, "Ameisenplage")
+  # given without its extension, the .rds file is found
+  expect_equal(cacheAsInfo(sub("\\.rds$", "", file)), info)
+})
+
+test_that("cacheAsInfo has nothing to report for a file from before 1.4.0", {
+  file <- tempfile(fileext = ".rds")
+  on.exit(unlink(file), add = TRUE)
+  saveRDS(tibble::tibble(x = 1), file)
+
+  expect_null(cacheAsInfo(file))
+})
+
+test_that("cacheAsInfo refuses a file that is not there", {
+  expect_error(
+    cacheAsInfo(file.path(tempdir(), "no-such-cache.rds")),
+    "does not exist"
+  )
+})
+
 test_that("a cache file is written and read back, without contacting the server", {
   skip_if_offline()
   kco <- KorAPConnection(accessToken = NULL, verbose = FALSE)