Expected `DownBallotR:::.onAttach("", "DownBallotR")` to throw a message.

# Tests for Python-interaction code using testthat::local_mocked_bindings().
# No real Python virtualenv is required — reticulate calls are replaced with
test_that(".db_norm_path: NULL / NA / empty return NA_character_", {
test_that(".db_norm_path: valid path returns normalized string", {
test_that("db_ensure_virtualenv: skips creation when env already exists", {
test_that("db_ensure_virtualenv: creates env when missing", {
test_that("db_ensure_virtualenv: errors clearly when creation fails", {
virtualenv_create = function(...) stop("no python found"),
test_that("db_use_virtualenv: succeeds when reticulate accepts the env", {
test_that("db_use_virtualenv: errors clearly when activation fails", {
use_virtualenv = function(...) stop("env not found"),
test_that("db_missing_python_packages: returns only unavailable packages", {
py_module_available = function(pkg) pkg %in% c("pandas", "requests"),
test_that("db_missing_python_packages: returns character(0) when all present", {
test_that("db_install_python_packages: skips when package list is empty", {
# Should return without calling virtualenv_install at all
test_that("db_install_python_packages: calls virtualenv_install and messages", {
test_that("db_install_python_packages: errors clearly when install fails", {
virtualenv_install = function(...) stop("pip failed"),
"Failed while installing Python packages"
test_that("db_verify_python_imports: passes when all imports succeed", {
test_that("db_verify_python_imports: errors clearly when import fails", {
test_that("db_playwright_chromium_is_installed: returns FALSE when playwright missing", {
test_that("db_playwright_chromium_is_installed: returns TRUE when chromium found", {
# py$__le_chromium_ok would be NULL in mock context -> isTRUE(NULL) = FALSE
# so we just confirm it returns a logical without erroring
test_that("db_install_playwright_chromium: succeeds when py_run_string works", {
test_that("db_install_playwright_chromium: errors clearly when chromium install fails", {
py_run_string = function(...) stop("download failed"),
"Playwright is installed, but Chromium failed"
test_that("downballot_use_python: errors when virtualenv does not exist", {
test_that("downballot_use_python: returns TRUE when already init to correct interpreter", {
py_config          = function(...) list(python = "/fake/venv/bin/python"),
test_that("downballot_use_python: errors when init to wrong interpreter", {
py_config          = function(...) list(python = "/other/python"),
"already initialized to a different Python"
test_that("downballot_use_python: activates env when not yet initialized", {
test_that("downballot_use_python: errors clearly when use_virtualenv fails", {
use_virtualenv    = function(...) stop("cannot activate"),
# ── downballot_install_python: nothing to do path ─────────────────────────────
test_that("downballot_install_python: messages and returns early when env is ready", {
py_available         = function(initialize = TRUE) FALSE,
# db_playwright_chromium_is_installed also calls py_module_available -> TRUE
# but then py_run_string -> not mocked, so chromium check will be FALSE
# That means plan$chromium_missing = TRUE and it won't take the early-exit path.
# So just confirm it doesn't error on the install path.
# With all packages present and chromium "ok" (py_run_string returns without error,
# but py$__le_chromium_ok won't be set -> FALSE), expect it attempts chromium install
suppressMessages(downballot_install_python(install_chromium = FALSE, quiet = TRUE))
# ── downballot_python_status: uncovered advice branches ───────────────────────
test_that("db_python_status_advice: recommends install when env missing", {
test_that("db_python_status_advice: recommends use_python when env exists but not init", {
test_that("db_python_status_advice: warns about wrong interpreter", {
expect_true(any(grepl("wrong Python|different Python|wrong interpreter", advice, ignore.case = TRUE)))
test_that("db_python_status_advice: recommends reinstall when packages missing", {
expect_true(any(grepl("reinstall", advice, ignore.case = TRUE)))
test_that("db_python_status_advice: reports ready when all ok", {
expect_true(any(grepl("ready", advice, ignore.case = TRUE)))
test_that("print.downballot_python_status: prints all key fields", {
advice                    = c("Python environment is ready for use.")
expect_true(any(grepl("downballot", out, ignore.case = TRUE)))
test_that("print.downballot_python_status: shows missing packages", {
advice                    = c("Fix issues with:", "  downballot_install_python(reinstall = TRUE)")
test_that("print.downballot_python_status: shows wrong interpreter warning", {
advice                    = c("reticulate is initialized to a different Python than this virtualenv.")
expect_true(any(grepl("not checked", out, ignore.case = TRUE)))
test_that(".onAttach: shows setup message when virtualenv missing", {