diff --git a/.github/workflows/render-rmarkdown-and-bump-version.yaml b/.github/workflows/render-rmarkdown-and-bump-version.yaml index 9fe4a725..01215e91 100644 --- a/.github/workflows/render-rmarkdown-and-bump-version.yaml +++ b/.github/workflows/render-rmarkdown-and-bump-version.yaml @@ -37,12 +37,6 @@ jobs: needs: check # Render READEME.md using rmarkdown - - name: Maybe bump dev version - if: github.ref == 'refs/heads/dev' - run: Rscript -e 'desc::desc_bump_version("patch")' - - name: Maybe bump master version - if: github.ref == 'refs/heads/master' - run: Rscript -e 'desc::desc_bump_version("minor")' - name: render README run: Rscript -e 'rmarkdown::render("README.Rmd", output_format = "md_document")' - name: Commit Results diff --git a/DESCRIPTION b/DESCRIPTION index f68fe93f..07787f20 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: golem Title: A Framework for Robust Shiny Applications -Version: 0.5.3 +Version: 0.5.0 Authors@R: c( person("Colin", "Fay", , "contact@colinfay.me", role = c("cre", "aut"), comment = c(ORCID = "0000-0001-7343-1846")), diff --git a/NEWS.md b/NEWS.md index 4c0e4053..23f3995d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,4 @@ -> Notes: the # between parenthesis referes to the related issue on GitHub, and the @ refers to an external contributor solving this issue. +> Notes: the # between parenthesis refers to the related issue on GitHub, and the @ refers to an external contributor solving this issue. # 0.5.0 diff --git a/R/bootstrap_rlang.R b/R/bootstrap_rlang.R new file mode 100644 index 00000000..52c662a3 --- /dev/null +++ b/R/bootstrap_rlang.R @@ -0,0 +1,4 @@ +# For mocking purposes +rlang_is_interactive <- rlang::is_interactive + +rlang_is_installed <- rlang::is_installed \ No newline at end of file diff --git a/R/config.R b/R/config.R index 1230ab27..08419402 100644 --- a/R/config.R +++ b/R/config.R @@ -220,13 +220,12 @@ get_current_config <- function(path = getwd()) { } if (!fs_file_exists(path_conf)) { - if (rlang::is_interactive()) { + if (rlang_is_interactive()) { ask <- ask_golem_creation_upon_config(path_conf) # Return early if the user doesn't allow if (!ask) { return(NULL) } - fs_file_copy( path = golem_sys("shinyexample/inst/golem-config.yml"), new_path = fs_path( @@ -247,7 +246,7 @@ get_current_config <- function(path = getwd()) { "R/app_config.R" ), "shinyexample", - golem::pkg_name() + golem::pkg_name(path = path) ) # TODO This should also create the dev folder } else { @@ -265,6 +264,8 @@ get_current_config <- function(path = getwd()) { ) } + + ask_golem_creation_upon_config <- function(pth) { msg <- paste0( "The %s file doesn't exist.", @@ -273,6 +274,7 @@ ask_golem_creation_upon_config <- function(pth) { ) yesno(sprintf(msg, basename(pth))) } + # This function changes the name of the # package in app_config when you need to # set the {golem} name diff --git a/R/install_dev_deps.R b/R/install_dev_deps.R index 23f624e4..aced76df 100644 --- a/R/install_dev_deps.R +++ b/R/install_dev_deps.R @@ -103,7 +103,7 @@ dev_deps <- unique( check_dev_deps_are_installed <- function() { are_installed <- sapply( dev_deps, - FUN = rlang::is_installed + FUN = rlang_is_installed ) if (!all(are_installed)) { message( diff --git a/R/test_helpers.R b/R/test_helpers.R index 14baa080..a4f98d01 100644 --- a/R/test_helpers.R +++ b/R/test_helpers.R @@ -39,6 +39,9 @@ expect_shinytaglist <- function(object) { invisible(act$val) } + +testthat_expect_snapshot <- testthat::expect_snapshot + #' @export #' @rdname testhelpers #' @param ui output of an UI function @@ -62,7 +65,7 @@ expect_html_equal <- function( ) } - testthat::expect_snapshot( + testthat_expect_snapshot( x = ui, ... ) @@ -86,7 +89,7 @@ expect_running <- function( testthat::skip_on_cran() # Ok for now we'll get back to this - testthat::skip_if_not(interactive()) + testthat::skip_if_not(rlang_is_interactive()) # Oh boy using testthat and processx is a mess # @@ -170,7 +173,7 @@ expect_running <- function( if (go_for_pkgload) { # Using pkgload because we can - shinyproc <- processx::process$new( + shinyproc <- processx_process( command = r_, c( "-e", @@ -179,7 +182,7 @@ expect_running <- function( ) } else { # Using the temps libPaths because we can - shinyproc <- processx::process$new( + shinyproc <- processx_process( echo_cmd = TRUE, command = r_, c( @@ -195,3 +198,6 @@ expect_running <- function( testthat::expect_true(shinyproc$is_alive()) shinyproc$kill() } + + +processx_process <- processx::process$new \ No newline at end of file diff --git a/R/use_recommended.R b/R/use_recommended.R index 1bead534..e82770ec 100644 --- a/R/use_recommended.R +++ b/R/use_recommended.R @@ -69,7 +69,8 @@ use_recommended_tests <- function( fs_file_copy( golem_sys( "utils", - "test-golem-recommended.R") + "test-golem-recommended.R" + ) , fs_path(pkg, "tests", "testthat"), overwrite = TRUE diff --git a/R/utils.R b/R/utils.R index 09c6e04a..b6cbe18a 100644 --- a/R/utils.R +++ b/R/utils.R @@ -11,11 +11,6 @@ golem_sys <- function( ) } -# For testing purpose -rlang_is_interactive <- function() { - rlang::is_interactive() -} - create_if_needed <- function( path, type = c("file", "directory"), diff --git a/tests/testthat/_snaps/after_creation_msg.md b/tests/testthat/_snaps/after_creation_msg.md index f246c6c2..640b786c 100644 --- a/tests/testthat/_snaps/after_creation_msg.md +++ b/tests/testthat/_snaps/after_creation_msg.md @@ -17,9 +17,21 @@ body = tagList() # add here other template arguments ) + Code + testthat::with_mocked_bindings(fs_path_abs = paste, { + after_creation_message_any_file("mypkg", "inst/app/www", "myhtml") + }) + Output + + File downloaded at inst/app/www/myhtml Code file_created_dance("inst/app/www", after_creation_message_sass, "mypkg", "inst/app/www", "mysass", open_file = FALSE, open_or_go_to = FALSE) Output v File created at inst/app/www + Code + file_already_there_dance("inst/app/www", open_file = FALSE) + Output + v File already exists. + * Go to inst/app/www diff --git a/tests/testthat/_snaps/config.md b/tests/testthat/_snaps/config.md new file mode 100644 index 00000000..2113afb1 --- /dev/null +++ b/tests/testthat/_snaps/config.md @@ -0,0 +1,7 @@ +# ask_golem_creation_upon_config works + + Code + ask_golem_creation_upon_config("/home/golem") + Output + [1] "The golem file doesn't exist.\nIt's possible that you might not be in a {golem} based project.\nDo you want to create the {golem} files?" + diff --git a/tests/testthat/test-add_files.R b/tests/testthat/test-add_files.R index 4906cf5e..c84ba2fe 100644 --- a/tests/testthat/test-add_files.R +++ b/tests/testthat/test-add_files.R @@ -1,104 +1,215 @@ -test_that("add_file works", { - run_quietly_in_a_dummy_golem({ - add_js_file( - "add_js_file", - open = FALSE +test_already_there_dance <- function( + fun, + filename, + template +) { + testthat::with_mocked_bindings( + file_already_there_dance = function(...) { + return(TRUE) + }, + { + expect_true( + fun( + filename, + open = FALSE + ) + ) + } + ) +} + +test_add_file <- function( + fun, + file_with_extension, + template = function(path, code = "oh no") { + write(code, file = path, append = TRUE) + }, + with_template = TRUE, + output_suffix = "" +) { + file_sans_extension <- tools::file_path_sans_ext( + file_with_extension + ) + expect_error(fun()) + fun( + file_sans_extension, + open = FALSE + ) + expect_exists( + file.path( + "inst/app/www", + sprintf( + "%s%s", + output_suffix, + file_with_extension + ) + ) + ) + test_already_there_dance( + fun, + file_sans_extension + ) + if (with_template) { + fun( + sprintf( + "tpl_%s", + file_sans_extension + ), + open = FALSE, + template = template ) expect_exists( file.path( "inst/app/www", - "add_js_file.js" + sprintf( + "tpl_%s", + file_with_extension + ) ) ) - add_js_handler( - "add_js_handler", - open = FALSE + all_lines <- paste0( + readLines( + file.path( + "inst/app/www", + sprintf( + "tpl_%s", + file_with_extension + ) + ) + ), + collapse = " " ) - expect_exists( - file.path( - "inst/app/www", - "add_js_handler.js" + expect_true( + grepl( + "oh no", + all_lines ) ) + } +} - add_js_input_binding( - "add_js_input_binding", - open = FALSE +test_that("add_file works", { + run_quietly_in_a_dummy_golem({ + test_add_file( + add_js_file, + "add_js_file.js" ) - expect_exists( - file.path( - "inst/app/www", - "input-add_js_input_binding.js" - ) + test_add_file( + add_js_handler, + "add_js_handler.js" ) - add_js_output_binding( - "add_js_output_binding", - open = FALSE + test_add_file( + add_js_input_binding, + "add_js_input_binding.js", + with_template = FALSE, + output_suffix = "input-" ) - expect_exists( - file.path( - "inst/app/www", - "output-add_js_output_binding.js" - ) + test_add_file( + add_js_output_binding, + "add_js_output_binding.js", + with_template = FALSE, + output_suffix = "output-" ) - add_css_file( - "add_css_file", - open = FALSE + + test_add_file( + add_css_file, + "add_css_file.css" ) - expect_exists( - file.path( - "inst/app/www", - "add_css_file.css" - ) + + test_add_file( + add_sass_file, + "add_sass_file.sass" ) - add_sass_file( - "add_sass_file", + test_add_file( + add_empty_file, + "add_empty_file" + ) + + add_html_template( open = FALSE ) expect_exists( file.path( "inst/app/www", - "add_sass_file.sass" + "template.html" ) ) + test_already_there_dance( + add_html_template, + "template.html" + ) - add_empty_file( - "add_empty_file", + add_partial_html_template( open = FALSE ) expect_exists( file.path( "inst/app/www", - "add_empty_file" + "partial_template.html" ) ) + test_already_there_dance( + add_partial_html_template, + "partial_template.html" + ) - add_html_template( - open = FALSE - ) - - expect_exists( - file.path( - "inst/app/www", - "template.html" - ) - ) - - add_partial_html_template( - open = FALSE - ) - - expect_exists( - file.path( - "inst/app/www", - "partial_template.html" - ) - ) + for ( + file in c( + "warn_add_js_file.js", + "warn_add_css_file.css", + "warn_add_sass_file.sass", + "warn_template.html" + ) + ) { + expect_warning( + add_empty_file( + file, + open = FALSE + ) + ) + } + res <- expect_warning( + add_ui_server_files( + pkg = "." + ) + ) + expect_exists( + "inst/app/ui.R" + ) + expect_exists( + "inst/app/server.R" + ) + res <- expect_warning( + add_ui_server_files( + pkg = "." + ) + ) }) }) + +test_that( + "add_empty_file throws a warning if using an extension that is already handled by another function", + { + run_quietly_in_a_dummy_golem({ + for (file in c( + "add_js_file.js", + "add_css_file.css", + "add_sass_file.sass", + "template.html" + )) { + expect_warning( + add_empty_file( + file, + open = FALSE + ) + ) + } + }) + } +) \ No newline at end of file diff --git a/tests/testthat/test-after_creation_msg.R b/tests/testthat/test-after_creation_msg.R index 22c94ca8..b243f3e5 100644 --- a/tests/testthat/test-after_creation_msg.R +++ b/tests/testthat/test-after_creation_msg.R @@ -25,6 +25,16 @@ test_that("after_creation_msg works", { "inst/app/www", "myhtml" ) + testthat::with_mocked_bindings( + fs_path_abs = paste, + { + after_creation_message_any_file( + "mypkg", + "inst/app/www", + "myhtml" + ) + } + ) file_created_dance( "inst/app/www", after_creation_message_sass, @@ -34,5 +44,9 @@ test_that("after_creation_msg works", { open_file = FALSE, open_or_go_to = FALSE ) + file_already_there_dance( + "inst/app/www", + open_file = FALSE + ) }) }) diff --git a/tests/testthat/test-config.R b/tests/testthat/test-config.R index 04463534..e5974d34 100644 --- a/tests/testthat/test-config.R +++ b/tests/testthat/test-config.R @@ -23,5 +23,103 @@ test_that("config finding works", { expect_exists( config ) + + unlink( + "R/app_config.R", + force = TRUE + ) + unlink( + "inst/golem-config.yml", + force = TRUE + ) + testthat::with_mocked_bindings( + guess_where_config = function(...) { + return(NULL) + }, + rlang_is_interactive = function(...) { + return(FALSE) + }, + { + expect_error( + get_current_config() + ) + expect_false( + file.exists("R/app_config.R") + ) + expect_false( + file.exists("inst/golem-config.yml") + ) + } + ) + testthat::with_mocked_bindings( + guess_where_config = function(...) { + return(NULL) + }, + fs_file_exists = function(...) { + return(FALSE) + }, + rlang_is_interactive = function(...) { + return(TRUE) + }, + ask_golem_creation_upon_config = function(...) { + return(TRUE) + }, + { + config <- get_current_config() + expect_exists( + config + ) + } + ) + }) + + + testthat::with_mocked_bindings( + fs_file_exists = function(...) { + return(FALSE) + }, + rlang_is_interactive = function(...) { + return(TRUE) + }, + ask_golem_creation_upon_config = function(...) { + return(FALSE) + }, + { + config <- get_current_config() + + expect_null( + config + ) + } + ) +}) + +test_that("ask_golem_creation_upon_config works",{ + testthat::with_mocked_bindings( + yesno = paste,{ + expect_snapshot( + ask_golem_creation_upon_config( + "/home/golem" + ) + ) + } + ) +}) + +test_that("change_app_config_name works", { + run_quietly_in_a_dummy_golem({ + change_app_config_name( + "new_name", + "." + ) + expect_true( + grepl( + "new_name", + paste( + readLines("R/app_config.R"), + collapse = " " + ) + ) + ) }) -}) \ No newline at end of file +}) diff --git a/tests/testthat/test-desc.R b/tests/testthat/test-desc.R index 0e9e7982..11effd7e 100644 --- a/tests/testthat/test-desc.R +++ b/tests/testthat/test-desc.R @@ -75,5 +75,61 @@ test_that("desc works", { } ) }) - + run_quietly_in_a_dummy_golem({ + testthat::with_mocked_bindings( + usethis_proj_set = function(pkg) { + return(TRUE) + }, + { + expect_warning( + fill_desc( + pkg_name = "fakename", + pkg_title = "newtitle", + pkg_description = "Newdescription.", + author_first_name = list( + "Coucou" + ), + repo_url = "http://repo_url.com", + pkg_version = "0.0.0.9010" + ) + ) + } + ) + }) + run_quietly_in_a_dummy_golem({ + testthat::with_mocked_bindings( + usethis_proj_set = function(pkg) { + return(TRUE) + }, + { + expect_warning( + fill_desc( + pkg_name = "fakename", + pkg_title = "newtitle", + pkg_description = "Newdescription.", + author_first_name = list( + "Coucou" + ), + author_last_name = list( + "Coucou" + ), + author_email = list( + "coucou@coucou.com" + ), + author_orcid = NULL, + repo_url = "http://repo_url.com", + pkg_version = "0.0.0.9010" + ) + ) + expect_equal( + as.character( + desc::desc_get_authors( + "DESCRIPTION" + ) + ), + "Coucou Coucou " + ) + } + ) + }) }) diff --git a/tests/testthat/test-install_dev_deps.R b/tests/testthat/test-install_dev_deps.R index 34c4c6d0..51b23453 100644 --- a/tests/testthat/test-install_dev_deps.R +++ b/tests/testthat/test-install_dev_deps.R @@ -33,3 +33,17 @@ test_that("install_dev_deps works", { } }) }) + +test_that("check_dev_deps_are_installed works", { + withr::with_temp_libpaths({ + testthat::with_mocked_bindings( + rlang_is_installed = function(...){ + return(FALSE) + },{ + expect_message( + check_dev_deps_are_installed() + ) + } + ) + }) +}) \ No newline at end of file diff --git a/tests/testthat/test-modules_fn.R b/tests/testthat/test-modules_fn.R index 960a5654..229f912e 100644 --- a/tests/testthat/test-modules_fn.R +++ b/tests/testthat/test-modules_fn.R @@ -56,6 +56,43 @@ test_that("use_module_test", { }) }) +test_that( + "module_template works", + { + module_template( + "mod1", + path <- tempfile(), + export = TRUE, + open = FALSE + ) + on.exit({ + unlink( + path, + recursive = TRUE, + force = TRUE + ) + }) + mod_read <- paste( + readLines( + path + ), + collapse = " " + ) + expect_true( + grepl( + "mod_mod1", + mod_read + ) + ) + expect_true( + grepl( + "@export", + mod_read + ) + ) + } +) + test_that("mod_remove work", { expect_equal( diff --git a/tests/testthat/test-test_helpers.R b/tests/testthat/test-test_helpers.R index 7028fdfc..8e8544d6 100644 --- a/tests/testthat/test-test_helpers.R +++ b/tests/testthat/test-test_helpers.R @@ -23,3 +23,60 @@ test_that("test expect_shinytaglist", { expect_shinytaglist("test") ) }) + +test_that("test expect_shinytag", { + testthat::with_mocked_bindings( + testthat_expect_snapshot = function(...) { + return(TRUE) + }, + { + expect_message( + expect_html_equal( + shiny::tagList(), + html = "test" + ) + ) + expect_true( + expect_html_equal( + shiny::tagList() + ) + ) + } + ) +}) + +test_that( + "expect_running",{ + testthat::with_mocked_bindings( + rlang_is_interactive = function() { + return(TRUE) + }, + processx_process = function(...) { + list( + is_alive = function() { + return(TRUE) + }, + kill = function() { + return(TRUE) + } + ) + }, + { + expect_true( + expect_running( + sleep = 0 + ) + ) + } + ) + } +) + +test_that( + "processx_process is correct", { + expect_equal( + processx_process("R"), + processx::process$new("R") + ) + } +) diff --git a/tests/testthat/test-use_recommended.R b/tests/testthat/test-use_recommended.R index 64367dda..522f1994 100644 --- a/tests/testthat/test-use_recommended.R +++ b/tests/testthat/test-use_recommended.R @@ -46,5 +46,52 @@ test_that( } ) }) + # Testing adding testthat if not there + run_quietly_in_a_dummy_golem({ + testthat::with_mocked_bindings( + usethis_use_testthat = function() { + dir.create("tests") + dir.create("tests/testthat") + file.create( + "tests/testthat.R" + ) + }, + { + unlink("tests", TRUE, TRUE) + use_recommended_tests( + pkg = ".", + spellcheck = FALSE + ) + + expect_exists( + file.path( + "tests", + "testthat", + "test-golem-recommended.R" + ) + ) + } + ) + }) + # Testing adding testthat if processx + # is not available + run_quietly_in_a_dummy_golem({ + testthat::with_mocked_bindings( + usethis_use_testthat = function() { + dir.create("tests") + dir.create("tests/testthat") + file.create( + "tests/testthat.R" + ) + }, + { + + use_recommended_tests( + pkg = ".", + spellcheck = FALSE + ) + } + ) + }) } )