tests/testthat/test-wflow_publish.R

context("wflow_publish")

# Setup ------------------------------------------------------------------------

library("git2r")

# Setup workflowr project for testing
site_dir <- tempfile("test-wflow_publish-")
suppressMessages(wflow_start(site_dir, change_wd = FALSE))
# Delete workflowr project on exit
on.exit(unlink(site_dir, recursive = TRUE, force = TRUE))
site_dir <- workflowr:::absolute(site_dir)
s <- wflow_status(project = site_dir)
r <- repository(s$root)

rmd <- file.path(s$analysis, c("about.Rmd", "index.Rmd", "license.Rmd"))
html <- workflowr:::to_html(rmd, outdir = s$docs)

rmd_to_fail <- file.path(s$analysis, "error.Rmd")
file.copy(from = "files/test-wflow_build/error.Rmd",
          to = rmd_to_fail)

# Test wflow_publish -----------------------------------------------------------

test_that("wflow_publish works in a simple case", {
  expect_message(o <- wflow_publish(rmd, view = FALSE, project = site_dir),
                 rmd[1])
  expect_true(all(file.exists(html)))
  s <- wflow_status(project = site_dir)
  expect_true(all(s$status[rmd, "published"]))
})

# Create decoy file that should not be built since it is unpublished
rmd_decoy <- file.path(s$analysis, "decoy.Rmd")
file.create(rmd_decoy)
html_decoy <- workflowr:::to_html(rmd_decoy, outdir = s$docs)

test_that("wflow_publish can `republish`", {
  mtime_pre <- file.mtime(html)
  Sys.sleep(2)
  # Change the theme
  config <- file.path(s$analysis, "_site.yml")
  config_lines <- readLines(config)
  config_lines <- stringr::str_replace(config_lines,
                                       "    theme: cosmo",
                                       "    theme: readable")
  writeLines(config_lines, con = config)
  # Republish with new theme
  expect_message(o <- wflow_publish(config, republish = TRUE, view = FALSE,
                                    project = site_dir),
                 rmd[1])
  mtime_post <- file.mtime(html)
  expect_true(all(mtime_post > mtime_pre))
  expect_true(config == o$step1$commit_files)
  expect_true(all(html %in% o$step3$commit_files))
  expect_false(file.exists(html_decoy))
  expect_false(html_decoy %in% o$step3$commit_files)
})

# Commit decoy file. Should not be affected by `update = TRUE` b/c it has not
# been published.
wflow_commit(rmd_decoy, "Commit decoy Rmd", project = site_dir)

test_that("wflow_publish can `update`", {
  # Edit and manually commit a published Rmd file, then use `update` to publish.
  cat("edit", file = rmd[1], append = TRUE)
  wflow_commit(rmd[1], "Draft edit", project = site_dir)
  # Update
  expect_message(o <- wflow_publish(update = TRUE, view = FALSE, project = site_dir),
                 rmd[1])
  expect_true(is.null(o$step1))
  expect_true(html[1] == o$step3$commit_files)
  expect_false(file.exists(html_decoy))
  expect_false(html_decoy %in% o$step3$commit_files)
})

test_that("wflow_publish can be used to commit non-Rmd files instead of wflow_commit", {
  f_test <- file.path(s$root, "test.txt")
  file.create(f_test)
  expect_silent(o <- wflow_publish(f_test, view = FALSE, project = site_dir))
  expect_true(f_test == o$step1$commit_files)
  expect_true(is.null(o$step2))
  expect_true(is.null(o$step3))
})

test_that("wflow_publish automatically removes unused figure files", {
  # Publish a file that has 2 plots from 2 unnamed chunks
  file_w_figs <- file.path(s$analysis, "fig.Rmd")
  file.copy("files/test-wflow_build/figure-v01.Rmd", file_w_figs)
  publish_v01 <- wflow_publish(file_w_figs, view = FALSE, project = site_dir)
  figs_analysis_v01 <- file.path(s$analysis, "figure", basename(file_w_figs),
                                 c("unnamed-chunk-1-1.png", "unnamed-chunk-2-1.png"))
  expect_true(all(file.exists(figs_analysis_v01)))
  figs_docs_v01 <- file.path(s$docs, "figure", basename(file_w_figs),
                             c("unnamed-chunk-1-1.png", "unnamed-chunk-2-1.png"))
  expect_true(all(file.exists(figs_docs_v01)))
  expect_true(all(figs_docs_v01 %in% publish_v01$step3$commit_files))
  # Update the file such that the previous 2 chunks are now named, plus add a
  # 3rd plot chunk
  file.copy("files/test-wflow_build/figure-v02.Rmd", file_w_figs, overwrite = TRUE)
  publish_v02 <- wflow_publish(file_w_figs, view = FALSE, project = site_dir)
  expect_false(all(file.exists(figs_analysis_v01)))
  expect_false(all(file.exists(figs_docs_v01)))
  figs_analysis_v02 <- file.path(s$analysis, "figure", basename(file_w_figs),
                                 c("named1-1.png", "named2-1.png", "named3-1.png"))
  expect_true(all(file.exists(figs_analysis_v02)))
  figs_docs_v02 <- file.path(s$docs, "figure", basename(file_w_figs),
                             c("named1-1.png", "named2-1.png", "named3-1.png"))
  expect_true(all(file.exists(figs_docs_v02)))
  expect_true(all(figs_docs_v02 %in% publish_v02$step3$commit_files))
  # The v01 files should also be listed in the commit_files b/c they are removed
  # in this commit
  expect_true(all(figs_docs_v01 %in% publish_v02$step3$commit_files))
  # The Git status should have no staged or unstaged changes, which would occur
  # if the files were deleted but not committed
  current_status <- status(r)
  expect_false(length(current_status$staged) > 0)
  expect_false(length(current_status$unstaged) > 0)
  # Cleanup
  file.remove(file_w_figs)
  unlink(file.path(s$analysis, "figure", basename(file_w_figs)),
         recursive = TRUE, force = TRUE)
  unlink(file.path(s$docs, "figure", basename(file_w_figs)),
         recursive = TRUE, force = TRUE)
})

# This tests the edge case where a file had one or more figures but then gets
# reduced to zero. While Git is able to "add" a non-existent directory to stage
# deleted files, git2r chokes if the non-existent directory is a relative path.
# git2r requires the non-existent directory to either be an absolute path or a
# relative path from the root of the Git repo.
test_that("wflow_publish removes unused figure files even if directory no longer exists", {
  # Publish a file that has 2 plots from 2 unnamed chunks
  file_w_figs <- file.path(s$analysis, "fig.Rmd")
  file.copy("files/test-wflow_build/figure-v01.Rmd", file_w_figs)
  publish_v01 <- wflow_publish(file_w_figs, view = FALSE, project = site_dir)
  figs_analysis_v01 <- file.path(s$analysis, "figure", basename(file_w_figs),
                                 c("unnamed-chunk-1-1.png", "unnamed-chunk-2-1.png"))
  expect_true(all(file.exists(figs_analysis_v01)))
  figs_docs_v01 <- file.path(s$docs, "figure", basename(file_w_figs),
                             c("unnamed-chunk-1-1.png", "unnamed-chunk-2-1.png"))
  expect_true(all(file.exists(figs_docs_v01)))
  expect_true(all(figs_docs_v01 %in% publish_v01$step3$commit_files))
  # Update the file to have no plots
  file.copy("files/test-wflow_build/seed.Rmd", file_w_figs, overwrite = TRUE)
  publish_v02 <- wflow_publish(file_w_figs, view = FALSE, project = site_dir)
  expect_false(all(file.exists(figs_analysis_v01)))
  expect_false(all(file.exists(figs_docs_v01)))
  # The old figure files should also be listed in the commit_files b/c they are
  # removed in this commit
  expect_true(all(figs_docs_v01 %in% publish_v02$step3$commit_files))
  # The Git status should have no staged or unstaged changes, which would occur
  # if the files were deleted but not committed
  current_status <- status(r)
  expect_false(length(current_status$staged) > 0)
  expect_false(length(current_status$unstaged) > 0)
  # Cleanup
  file.remove(file_w_figs)
})

# Test error handling ----------------------------------------------------------

test_that("wflow_publish resets Git repo to previous commit if build fails", {
  commit_pre <- commits(r, n = 1)[[1]]
  expect_error(utils::capture.output(
    wflow_publish(rmd_to_fail, view = FALSE, project = site_dir)),
               "There was an error")
  commit_post <- commits(r, n = 1)[[1]]
  expect_identical(commit_post, commit_pre)
})

test_that("wflow_publish restores previous docs/ if build fails", {
  md5sum_pre <- tools::md5sum(rmd)
  mtime_pre <- file.mtime(rmd)
  Sys.sleep(2)
  expect_error(utils::capture.output(
    wflow_publish(c(rmd, rmd_to_fail), view = FALSE, project = site_dir)),
    "There was an error")
  md5sum_post <- tools::md5sum(rmd)
  mtime_post <- file.mtime(rmd)
  expect_identical(md5sum_post, md5sum_pre)
  expect_identical(mtime_post, mtime_pre)
})
jdblischak/workflowrBeta documentation built on May 17, 2019, 7:28 p.m.