tests/testthat/test-pkgdown.R

test_that("_pkgdown.yml reference section covers all non-internal topics", {
  skip_if_not_installed("yaml")

  # Find package root: try test_path() first, then fall back to getwd()-relative paths.
  # _pkgdown.yml is excluded from the R CMD CHECK tarball via .Rbuildignore, so the
  # test skips gracefully when running inside R CMD CHECK.
  pkg_root <- local({
    candidates <- c(
      tryCatch(normalizePath(test_path("..", "..")), error = function(e) ""),
      normalizePath(file.path(getwd(), "..", ".."), mustWork = FALSE),
      normalizePath(file.path(getwd(), ".."), mustWork = FALSE),
      normalizePath(getwd(), mustWork = FALSE)
    )
    found <- candidates[file.exists(file.path(candidates, "_pkgdown.yml"))]
    if (length(found) > 0) found[1] else NULL
  })
  skip_if(is.null(pkg_root), "_pkgdown.yml not found (skipping outside source tree)")

  pkgdown_file <- file.path(pkg_root, "_pkgdown.yml")

  # Find man directory
  man_dir <- file.path(pkg_root, "man")
  skip_if(!dir.exists(man_dir), "man directory not found")

  has_keyword_pattern <- '^has_keyword\\("(.+)"\\)$'

  # Parse each .Rd file to get topic name and keywords
  rd_files <- list.files(man_dir, pattern = "\\.Rd$", full.names = TRUE)

  rd_info <- lapply(rd_files, function(rd_file) {
    content <- readLines(rd_file, warn = FALSE)
    name_lines <- grep("^\\\\name\\{", content, value = TRUE)
    if (length(name_lines) == 0L) return(NULL)
    name <- sub("\\\\name\\{(.+)\\}", "\\1", name_lines[1])
    keywords <- gsub("\\\\keyword\\{(.+)\\}", "\\1",
                     grep("^\\\\keyword\\{", content, value = TRUE))
    list(name = name, keywords = keywords)
  })
  rd_info <- Filter(Negate(is.null), rd_info)

  # Keep only non-internal public topics
  public_topics <- Filter(function(x) !("internal" %in% x$keywords), rd_info)
  public_topic_names <- vapply(public_topics, `[[`, character(1), "name")

  # Parse _pkgdown.yml reference section
  pkgdown_config <- yaml::read_yaml(pkgdown_file)

  # Build the set of topics covered by the reference section
  covered_topics <- character(0)
  for (section in pkgdown_config$reference) {
    for (item in section$contents) {
      if (!is.character(item)) next
      if (grepl(has_keyword_pattern, item)) {
        # Expand has_keyword("xxx") to all topics carrying that keyword
        keyword <- sub(has_keyword_pattern, "\\1", item)
        matching_names <- vapply(
          Filter(function(x) keyword %in% x$keywords, public_topics),
          `[[`, character(1), "name"
        )
        covered_topics <- c(covered_topics, matching_names)
      } else {
        covered_topics <- c(covered_topics, item)
      }
    }
  }

  missing_topics <- setdiff(public_topic_names, covered_topics)

  expect_equal(
    missing_topics, character(0),
    info = paste(
      "Topics missing from _pkgdown.yml reference section:",
      paste(missing_topics, collapse = ", ")
    )
  )
})

Try the bmm package in your browser

Any scripts or data that you put into this service are public.

bmm documentation built on March 30, 2026, 5:08 p.m.