tests/testthat/test-bundlePackageRenv.R

# snapshotRenvDependencies() ----------------------------------------------

test_that("non-R apps don't have packages", {
  skip_on_cran()
  app_dir <- local_temp_app(list(index.html = ""))
  out <- snapshotRenvDependencies(app_dir)
  expect_equal(out, data.frame())
})

test_that("manifest has correct data types", {
  skip_on_cran()
  withr::local_options(renv.verbose = TRUE)
  app <- local_temp_app(list("index.Rmd" = ""))
  deps <- snapshotRenvDependencies(app)
  expect_type(deps$description, "list")
  expect_type(deps$description[[1]], "list")
})

test_that("recommended packages are snapshotted", {
  skip_on_cran()
  skip_if_not_installed("MASS")

  withr::local_options(renv.verbose = TRUE)
  app <- local_temp_app(list(
    "index.Rmd" = c(
      "```{r}",
      "library(MASS)",
      "```"
    )
  ))
  deps <- snapshotRenvDependencies(app)
  expect_true("MASS" %in% deps$Package)
})

test_that("extra packages are snapshotted", {
  skip_on_cran()
  skip_if_not_installed("foreign")

  withr::local_options(renv.verbose = TRUE)
  app <- local_temp_app(list("index.Rmd" = ""))
  deps <- snapshotRenvDependencies(app, extraPackages = c("foreign"))
  expect_true("foreign" %in% deps$Package)
})

test_that("works with BioC packages", {
  skip_on_cran()
  skip_on_ci()
  skip_if_not_installed("BiocManager")
  skip_if_not_installed("Biobase")

  app <- local_temp_app(list(
    "index.R" = c(
      "library(Biobase)"
    )
  ))
  biocRepos <- BiocManager::repositories()
  withr::local_options(repos = biocRepos)
  expect_no_condition(
    {
      deps <- snapshotRenvDependencies(app)
    },
    class = "rsconnect_biocRepos"
  )
  Biobase <- deps[deps$Package == "Biobase", ]
  expect_equal(Biobase$Source, "Bioconductor")
  expect_equal(Biobase$Repository, biocRepos[["BioCsoft"]])

  withr::local_options(
    repos = c(
      CRAN = "https://cran.rstudio.com"
    )
  )
  expect_condition(
    deps <- snapshotRenvDependencies(app),
    class = "rsconnect_biocRepos"
  )

  Biobase <- deps[deps$Package == "Biobase", ]
  expect_equal(Biobase$Source, "Bioconductor")
  expect_equal(Biobase$Repository, biocRepos(".")[[1]])
})

# https://github.com/rstudio/rsconnect/issues/968
test_that("large directories are analyzed", {
  skip_on_cran()
  skip_if_not_installed("foreign")

  app_dir <- local_temp_app(list("foo.R" = "library(foreign)"))
  data_dir <- file.path(app_dir, "data")
  dir.create(data_dir)
  for (each in seq_len(1001)) {
    writeLines(character(0), file.path(data_dir, paste0(each, ".txt")))
  }
  expect_snapshot(
    deps <- snapshotRenvDependencies(app_dir)
  )
  expect_contains(deps$Package, "foreign")
})

test_that("errors when renv::snapshot fails", {
  local_mocked_bindings(
    dependencies = function(...) data.frame(Package = "fakepkg"),
    snapshot = function(...) stop("can't snapshot this package"),
    .package = "renv"
  )

  app_dir <- local_temp_app(list("foo.R" = "library(foreign)"))
  expect_snapshot(
    snapshotRenvDependencies(app_dir),
    error = TRUE
  )
})

# parseRenvDependencies ---------------------------------------------------

test_that("gets DESCRIPTION from renv & system libraries", {
  skip_if_not_installed("foreign")
  skip_if_not_installed("MASS")

  withr::local_options(renv.verbose = FALSE)

  app_dir <- local_temp_app(list("foo.R" = "library(foreign); library(MASS)"))
  renv::snapshot(app_dir, prompt = FALSE)

  deps <- parseRenvDependencies(file.path(app_dir, "renv.lock"), app_dir)
  expect_setequal(deps$Package, c("foreign", "MASS", "renv"))

  expect_type(deps$description, "list")
  expect_type(deps$description[[which(deps$Package == "foreign")]], "list")
  expect_type(deps$description[[which(deps$Package == "MASS")]], "list")
})


test_that("errors if library and project are inconsistent", {
  withr::local_options(renv.verbose = FALSE)

  app_dir <- local_temp_app(list("foo.R" = "library(withr)"))
  renv::snapshot(app_dir, prompt = FALSE)
  renv::record("withr@0.1.1", project = app_dir)

  expect_snapshot(
    parseRenvDependencies(file.path(app_dir, "renv.lock"), app_dir),
    error = TRUE
  )
})

test_that("dependencyResolution = 'library' bypasses lockfile and uses local library", {
  skip_on_cran()

  withr::local_options(renv.verbose = FALSE)

  app_dir <- local_temp_app(list("foo.R" = "library(withr)"))
  renv::snapshot(app_dir, prompt = FALSE)
  renv::record("withr@0.1.1", project = app_dir)

  # Without dependencyResolution = "library", this would error with "out of sync"
  deps <- computePackageDependencies(
    app_dir,
    quiet = TRUE,
    dependencyResolution = "library"
  )
  expect_true("withr" %in% deps$Package)
  withr_dep <- deps[deps$Package == "withr", ]
  expect_true(withr_dep$Version != "0.1.1")
})

# standardizeRenvPackage -----------------------------------------

test_that("SCM get names translated", {
  bitbucket <- list(Package = "pkg", Source = "Bitbucket")
  gitlab <- list(Package = "pkg", Source = "GitLab")
  github <- list(Package = "pkg", Source = "GitHub")

  expect_equal(
    standardizeRenvPackage(bitbucket),
    list(Package = "pkg", Source = "bitbucket")
  )
  expect_equal(
    standardizeRenvPackage(gitlab),
    list(Package = "pkg", Source = "gitlab")
  )
  expect_equal(
    standardizeRenvPackage(github),
    list(Package = "pkg", Source = "github")
  )
})

test_that("BioC gets normalized repo", {
  Bioconductor <- list(Package = "pkg", Source = "Bioconductor")

  packages <- data.frame(
    Package = "pkg",
    Repository = "https://b.com/src/contrib",
    stringsAsFactors = FALSE
  )

  expect_equal(
    standardizeRenvPackage(Bioconductor, packages),
    list(Package = "pkg", Source = "Bioconductor", Repository = "https://b.com")
  )
})

test_that("BioC prefers biocPackages over availablePackages (#1314)", {
  bioc_pkg <- list(Package = "S4Vectors", Source = "Bioconductor")

  avail <- data.frame(
    Package = "S4Vectors",
    Repository = "https://cran.rstudio.com/src/contrib/Transit",
    stringsAsFactors = FALSE
  )

  bioc <- data.frame(
    Package = "S4Vectors",
    Repository = "https://bioconductor.org/packages/3.22/bioc/src/contrib",
    stringsAsFactors = FALSE
  )

  result <- standardizeRenvPackage(bioc_pkg, avail, biocPackages = bioc)
  expect_equal(result$Repository, "https://bioconductor.org/packages/3.22/bioc")
})

test_that("has special handling for CRAN packages", {
  packages <- as.matrix(data.frame(
    Package = "pkg",
    Version = "1.0.0",
    Repository = "https://cran.com/src/contrib",
    stringsAsFactors = FALSE
  ))
  repos <- c(CRAN = "https://cran.com")

  spec <- function(version, source = "Repository", repo = "CRAN") {
    list(Package = "pkg", Version = version, Source = source, Repository = repo)
  }

  expect_equal(
    standardizeRenvPackage(spec("1.0.0"), packages, repos),
    spec("1.0.0", "CRAN", "https://cran.com")
  )

  expect_equal(
    standardizeRenvPackage(spec("1.0.0.9000"), packages, repos),
    spec("1.0.0.9000", NA_character_, NA_character_)
  )
})

test_that("packages installed from other repos get correctly named", {
  pkg <- list(
    Package = "pkg",
    Source = "Repository",
    Repository = "https://test2.com"
  )
  packages <- as.matrix(data.frame(
    Package = "pkg",
    Version = "1.0.0",
    Repository = "https://test2.com/src/contrib",
    stringsAsFactors = FALSE
  ))
  repos <- c(TEST1 = "https://test1.com", TEST2 = "https://test2.com")

  expect_equal(
    standardizeRenvPackage(pkg, packages, repos = repos),
    list(Package = "pkg", Source = "TEST2", Repository = "https://test2.com")
  )
})

test_that("packages available in multiple repos use the one from renv.lock", {
  # When a package is available in multiple repositories,
  # standardizeRenvPackage should respect the Repository field from renv.lock
  # rather than just using the first match from availablePackages

  # Simulate availablePackages with both packages available from both repos
  # Note: available.packages() returns first match with "duplicates" filter
  packages <- rbind(
    c(
      Package = "pkg1",
      Version = "1.0.0",
      Repository = "https://cran.com/src/contrib"
    ),
    c(
      Package = "pkg2",
      Version = "2.0.0",
      Repository = "https://cran.com/src/contrib"
    ),
    c(
      Package = "pkg1",
      Version = "1.0.0",
      Repository = "https://og-cran.com/src/contrib"
    ),
    c(
      Package = "pkg2",
      Version = "2.0.0",
      Repository = "https://og-cran.com/src/contrib"
    )
  )

  repos <- c(CRAN = "https://cran.com", OG_CRAN = "https://og-cran.com")

  # pkg1 should come from OG_CRAN (as specified in renv.lock)
  pkg1 <- list(
    Package = "pkg1",
    Version = "1.0.0",
    Source = "Repository",
    Repository = "OG_CRAN"
  )

  # pkg2 should come from CRAN (as specified in renv.lock)
  pkg2 <- list(
    Package = "pkg2",
    Version = "2.0.0",
    Source = "Repository",
    Repository = "CRAN"
  )

  expect_equal(
    standardizeRenvPackage(pkg1, packages, repos = repos),
    list(
      Package = "pkg1",
      Version = "1.0.0",
      Source = "OG_CRAN",
      Repository = "https://og-cran.com"
    )
  )

  expect_equal(
    standardizeRenvPackage(pkg2, packages, repos = repos),
    list(
      Package = "pkg2",
      Version = "2.0.0",
      Source = "CRAN",
      Repository = "https://cran.com"
    )
  )
})

test_that("unknown source packages get NA source + repository", {
  source <- list(Package = "pkg", Source = "unknown", Repository = "useless")
  expect_equal(
    standardizeRenvPackage(source),
    list(Package = "pkg", Source = NA_character_, Repository = NA_character_)
  )
})

test_that("Local packages resolve from a configured repo when available", {
  pkg <- list(Package = "pkg", Version = "1.0.0", Source = "Local")

  packages <- as.matrix(data.frame(
    Package = "pkg",
    Version = "1.0.0",
    Repository = "https://cran.com/src/contrib",
    stringsAsFactors = FALSE
  ))
  repos <- c(CRAN = "https://cran.com")

  expect_equal(
    standardizeRenvPackage(pkg, packages, repos = repos),
    list(
      Package = "pkg",
      Version = "1.0.0",
      Source = "CRAN",
      Repository = "https://cran.com"
    )
  )
})

test_that("Local packages get NA source + repository when not in any repo", {
  pkg <- list(Package = "pkg", Version = "1.0.0", Source = "Local")

  packages <- as.matrix(data.frame(
    Package = "otherpkg",
    Version = "1.0.0",
    Repository = "https://cran.com/src/contrib",
    stringsAsFactors = FALSE
  ))
  repos <- c(CRAN = "https://cran.com")

  expect_equal(
    standardizeRenvPackage(pkg, packages, repos = repos),
    list(
      Package = "pkg",
      Version = "1.0.0",
      Source = NA_character_,
      Repository = NA_character_
    )
  )
})

Try the rsconnect package in your browser

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

rsconnect documentation built on June 9, 2026, 1:09 a.m.