test_that("store works", { # First write works expect_equal(store_tutorial_cache("myName", c("code", "here"), FALSE), TRUE) expect_equal(tutorial_cache_env$objects[["myName"]], c("code", "here")) # Second write without overwrite is a no-op expect_equal(store_tutorial_cache("myName", c("updated", "code"), FALSE), FALSE) expect_equal(tutorial_cache_env$objects[["myName"]], c("code", "here")) # Overwrite returns true expect_equal(store_tutorial_cache("myName", c("updated", "code"), TRUE), TRUE) expect_equal(tutorial_cache_env$objects[["myName"]], c("updated", "code")) # clear clears expect_warning(clear_exercise_cache_env(), "deprecated") expect_equal(length(get_tutorial_cache("exercise")), 0) }) test_that("get_tutorial_info() returns structured tutorial cache", { skip_if_not_pandoc("1.14") info <- get_tutorial_info(test_path("tutorials", "basic.Rmd")) withr::defer(clear_tutorial_cache()) # prepare_tutorial_cache() returns get_tutorial_info() expect_equal(info$tutorial_id, "test-basic") expect_equal(info$tutorial_version, "9.9.9") expect_s3_class(info$items, "data.frame") expect_named(info$items, c("order", "label", "type", "data")) all <- get_tutorial_cache() for (i in seq_along(info$items$data)) { item <- info$items$data[[i]] label <- info$items$label[[i]] if (inherits(item, "tutorial_exercise")) { # these items are added by app or by `get_tutorial_info()` item[["code"]] <- NULL } expect_equal(item, all[[label]]) } # tutorial cache lists items in order of appearance exercises <- c("two-plus-two", "add-function", "print-limit") questions <- c("quiz-1", "quiz-2") expect_equal(names(all), c(exercises, questions)) expect_equal(all[exercises], get_exercise_cache()) expect_equal(all$`two-plus-two`, get_exercise_cache("two-plus-two")) expect_true(all(vapply(all[exercises], inherits, logical(1), "tutorial_exercise"))) expect_equal(all[questions], get_question_cache()) expect_equal(all$`quiz-2`, get_question_cache("quiz-2")) expect_true(all(vapply(all[questions], inherits, logical(1), "tutorial_question"))) # exercises have the same `global_setup` expect_equal(all$`two-plus-two`$global_setup, all$`add-function`$global_setup) expect_equal(all$`two-plus-two`$global_setup, all$`print-limit`$global_setup) expect_equal(all$`add-function`$options$exercise.lines, 5) }) test_that("setup-global-exercise chunk is used for global_setup", { skip_if_not_pandoc("1.14") prepare_tutorial_cache_from_source(test_path("setup-chunks", "exercise-global-setup.Rmd")) withr::defer(clear_tutorial_cache()) all <- get_tutorial_cache() expect_equal(as.character(all$data1$global_setup), "global <- 0") # check that the correct chunk was used for the `global_setup` # NOTE: this may change if the knitr hooks are refactored expect_equal(attr(all$data1$global_setup, "chunk_opts")$label, "setup-global-exercise") ex <- mock_exercise(user_code = "global", label = "data1", check = I("global")) ex$chunks <- all$data1$chunks ex$global_setup <- all$data1$global_setup ex$setup <- all$data1$setup # global setup chunk is not evaluated unless explicitly requested res <- evaluate_exercise(ex, evaluate_global_setup = FALSE, envir = new.env()) expect_equal(res$error_message, "object 'global' not found") res <- evaluate_exercise(ex, evaluate_global_setup = TRUE, envir = new.env()) expect_equal(res$feedback$checker_args$last_value, 0) })