# ============================================================================= # Comprehensive tests for universal preview() function # ============================================================================= # ----------------------------------------------------------------------------- # Helper functions # ----------------------------------------------------------------------------- #' Verify HTML structure is valid verify_html_structure <- function(html_path) { expect_true(file.exists(html_path)) html <- paste(readLines(html_path, warn = FALSE), collapse = "\n") # Basic HTML structure expect_true(grepl("% add_page("Home", text = "# Welcome to the Dashboard", is_landing_page = TRUE) html_path <- preview(dashboard, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) html <- verify_html_structure(html_path) expect_true(grepl("Welcome", html)) expect_true(grepl("Dashboard", html)) unlink(temp_dir, recursive = TRUE) }) test_that("preview works for dashboard_project with specific page", { temp_dir <- tempfile() dashboard <- create_dashboard(temp_dir, "Multi Page") %>% add_page("Home", text = "# Home Page", is_landing_page = TRUE) %>% add_page("About", text = "# About Page") html_path <- preview(dashboard, page = "About", open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) html <- paste(readLines(html_path, warn = FALSE), collapse = "\n") expect_true(grepl("About", html)) unlink(temp_dir, recursive = TRUE) }) test_that("preview errors for non-existent page", { temp_dir <- tempfile() dashboard <- create_dashboard(temp_dir, "Test") %>% add_page("Home", text = "# Home", is_landing_page = TRUE) expect_error( preview(dashboard, page = "NonExistent", open = FALSE), "not found" ) unlink(temp_dir, recursive = TRUE) }) test_that("preview errors for empty dashboard", { temp_dir <- tempfile() dashboard <- create_dashboard(temp_dir, "Empty") expect_error( preview(dashboard, open = FALSE), "no pages" ) unlink(temp_dir, recursive = TRUE) }) # ----------------------------------------------------------------------------- # 2. Object Type Tests - page_object # ----------------------------------------------------------------------------- test_that("preview works for page_object with text", { page <- create_page("Test Page") %>% add_text("# Hello World", "This is a paragraph.") html_path <- preview(page, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) html <- paste(readLines(html_path, warn = FALSE), collapse = "\n") expect_true(grepl("Hello World", html)) }) test_that("preview works for page_object with visualizations", { page <- create_page("Analysis", data = mtcars) %>% add_viz(type = "histogram", x_var = "mpg", title = "MPG Distribution") html_path <- preview(page, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) html <- paste(readLines(html_path, warn = FALSE), collapse = "\n") expect_true(grepl("MPG Distribution", html)) }) # ----------------------------------------------------------------------------- # 3. Object Type Tests - content_block (standalone) # ----------------------------------------------------------------------------- test_that("preview works for standalone text content_block", { text_block <- add_text("# Standalone Text Block") html_path <- preview(text_block, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) html <- paste(readLines(html_path, warn = FALSE), collapse = "\n") expect_true(grepl("Standalone Text Block", html)) }) # ----------------------------------------------------------------------------- # 4. Content Block Type Tests - All Types # ----------------------------------------------------------------------------- test_that("preview renders text blocks", { content <- create_content() %>% add_text("# Header\n\nParagraph text here") html_path <- preview(content, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) expect_html_contains(html_path, c("Header", "Paragraph")) }) test_that("preview renders callout blocks", { content <- create_content() %>% add_callout("This is a tip!", type = "tip", title = "Pro Tip") html_path <- preview(content, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) expect_html_contains(html_path, c("This is a tip", "Pro Tip", "callout")) }) test_that("preview renders image blocks", { content <- create_content() %>% add_image("https://via.placeholder.com/150", alt = "Placeholder", caption = "Test image") html_path <- preview(content, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) expect_html_contains(html_path, c("img", "placeholder.com")) }) test_that("preview renders divider blocks", { content <- create_content() %>% add_text("Before") %>% add_divider() %>% add_text("After") html_path <- preview(content, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) expect_html_contains(html_path, c("Before", "After", "hr|divider")) }) test_that("preview renders code blocks", { content <- create_content() %>% add_code("x <- 1 + 2\nprint(x)", language = "r") html_path <- preview(content, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) # Note: < is HTML-escaped to < expect_html_contains(html_path, c("<- 1", "pre", "code", "language-r")) }) test_that("preview renders spacer blocks", { content <- create_content() %>% add_text("Before") %>% add_spacer(height = "3rem") %>% add_text("After") html_path <- preview(content, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) expect_html_contains(html_path, c("Before", "After")) }) test_that("preview renders card blocks", { content <- create_content() %>% add_card(text = "Card body content", title = "Card Title", footer = "Card footer") html_path <- preview(content, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) expect_html_contains(html_path, c("Card Title", "Card body", "card")) }) test_that("preview renders accordion blocks", { content <- create_content() %>% add_accordion("Click to expand", "Hidden content here") html_path <- preview(content, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) expect_html_contains(html_path, c("Click to expand", "accordion")) }) test_that("preview renders iframe blocks", { content <- create_content() %>% add_iframe("https://example.com", height = "400px") html_path <- preview(content, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) expect_html_contains(html_path, c("iframe", "example.com")) }) test_that("preview renders video blocks", { content <- create_content() %>% add_video("https://example.com/video.mp4", caption = "Test video") html_path <- preview(content, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) expect_html_contains(html_path, c("video", "video.mp4")) }) test_that("preview renders html blocks", { content <- create_content() %>% add_html("
Custom HTML content
") html_path <- preview(content, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) expect_html_contains(html_path, c("custom-class", "Custom HTML content")) }) test_that("preview renders quote blocks", { content <- create_content() %>% add_quote("To be or not to be", attribution = "Shakespeare") html_path <- preview(content, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) expect_html_contains(html_path, c("To be or not to be", "Shakespeare", "blockquote")) }) test_that("preview renders badge blocks", { content <- create_content() %>% add_badge("New", color = "success") html_path <- preview(content, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) expect_html_contains(html_path, c("New", "badge")) }) test_that("preview renders metric blocks", { content <- create_content() %>% add_metric("Total Sales", "$1,234,567") html_path <- preview(content, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) expect_html_contains(html_path, c("Total Sales", "1,234,567", "metric")) }) # ----------------------------------------------------------------------------- # 5. Mixed Content Tests # ----------------------------------------------------------------------------- test_that("preview handles mixed content and visualizations", { content <- create_content(data = mtcars) %>% add_text("# Before Chart") %>% add_viz(type = "histogram", x_var = "mpg", title = "Histogram") %>% add_text("# After Chart") html_path <- preview(content, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) html <- paste(readLines(html_path, warn = FALSE), collapse = "\n") expect_true(grepl("Before Chart", html)) expect_true(grepl("After Chart", html)) expect_true(grepl("Histogram", html)) }) test_that("preview handles multiple visualization types", { content <- create_content(data = mtcars) %>% add_viz(type = "histogram", x_var = "mpg", title = "Histogram") %>% add_viz(type = "bar", x_var = "cyl", title = "Bar Chart") html_path <- preview(content, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) html <- paste(readLines(html_path, warn = FALSE), collapse = "\n") expect_true(grepl("Histogram", html)) expect_true(grepl("Bar Chart", html)) }) # ----------------------------------------------------------------------------- # 6. Styling Tests # ----------------------------------------------------------------------------- test_that("preview applies custom fonts from dashboard", { temp_dir <- tempfile() dashboard <- create_dashboard(temp_dir, "Styled", mainfont = "Roboto") %>% add_page("Home", text = "# Styled Page", is_landing_page = TRUE) html_path <- preview(dashboard, open = FALSE, quarto = FALSE) html <- paste(readLines(html_path, warn = FALSE), collapse = "\n") expect_true(grepl("Roboto", html)) unlink(temp_dir, recursive = TRUE) }) test_that("preview applies navbar colors from dashboard", { temp_dir <- tempfile() dashboard <- create_dashboard(temp_dir, "Colored", navbar_bg_color = "#FF5733" ) %>% add_page("Home", text = "# Colored", is_landing_page = TRUE) html_path <- preview(dashboard, open = FALSE, quarto = FALSE) html <- paste(readLines(html_path, warn = FALSE), collapse = "\n") # Preview uses unified simple styling (gray-bordered container) # Navbar colors are only applied in final generated dashboard, not previews # Check for the consistent preview container instead expect_true(grepl("border: 2px solid #e1e4e8", html)) expect_true(grepl("Preview:", html)) unlink(temp_dir, recursive = TRUE) }) # ----------------------------------------------------------------------------- # 7. Interactive Elements Tests # ----------------------------------------------------------------------------- test_that("preview includes input filter assets", { # add_input requires filter_var and options parameters content <- create_content() %>% add_input( input_id = "test_filter", label = "Select Option:", type = "select_single", filter_var = "cyl", options = c("Option A", "Option B", "Option C") ) html_path <- preview(content, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) html <- paste(readLines(html_path, warn = FALSE), collapse = "\n") # Should include input-related content expect_true(grepl("test_filter|select|option", html, ignore.case = TRUE)) }) test_that("preview includes modal assets", { content <- create_content() %>% add_modal(modal_id = "info-modal", title = "Information", modal_content = "Modal body text") html_path <- preview(content, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) html <- paste(readLines(html_path, warn = FALSE), collapse = "\n") # Should include modal structure or at least some content expect_true(grepl("modal|Information", html, ignore.case = TRUE)) }) # ----------------------------------------------------------------------------- # 8. Tabgroup Tests # ----------------------------------------------------------------------------- test_that("preview with tabgroups works in direct mode", { content <- create_content(data = mtcars) %>% add_viz(type = "histogram", x_var = "mpg", tabgroup = "Tab1") %>% add_viz(type = "histogram", x_var = "hp", tabgroup = "Tab2") # May or may not warn depending on interactive mode, but should work html_path <- suppressWarnings( preview(content, open = FALSE, quarto = FALSE) ) expect_true(file.exists(html_path)) }) # ----------------------------------------------------------------------------- # 9. Quarto Mode Tests (skip if Quarto not available) # ----------------------------------------------------------------------------- test_that("preview quarto mode works for content collection", { skip_if(Sys.which("quarto") == "", "Quarto not available") skip_on_ci() # Quarto rendering can be flaky in CI environments content <- create_content(data = mtcars) %>% add_viz(type = "histogram", x_var = "mpg", title = "Quarto Test") # Use tryCatch to handle rendering failures gracefully result <- tryCatch({ html_path <- preview(content, open = FALSE, quarto = TRUE) list(success = TRUE, path = html_path) }, error = function(e) { list(success = FALSE, error = e$message) }) skip_if(!result$success, paste("Preview rendering failed:", result$error)) expect_true(file.exists(result$path)) html <- paste(readLines(result$path, warn = FALSE), collapse = "\n") expect_true(grepl("Quarto Test", html)) }) test_that("preview quarto mode works for dashboard_project", { skip_if(Sys.which("quarto") == "", "Quarto not available") skip_on_ci() # Quarto rendering can be flaky in CI environments temp_dir <- tempfile() on.exit(unlink(temp_dir, recursive = TRUE), add = TRUE) dashboard <- create_dashboard(temp_dir, "Quarto Dashboard") %>% add_page("Home", text = "# Quarto Mode Test", is_landing_page = TRUE) # Use tryCatch to handle rendering failures gracefully result <- tryCatch({ html_path <- preview(dashboard, open = FALSE, quarto = TRUE) list(success = TRUE, path = html_path) }, error = function(e) { list(success = FALSE, error = e$message) }) skip_if(!result$success, paste("Preview rendering failed:", result$error)) expect_true(file.exists(result$path)) html <- paste(readLines(result$path, warn = FALSE), collapse = "\n") expect_true(grepl("Quarto Mode Test", html)) }) test_that("preview quarto mode applies dashboard theme", { skip_if(Sys.which("quarto") == "", "Quarto not available") skip_on_ci() # Quarto rendering can be flaky in CI environments temp_dir <- tempfile() on.exit(unlink(temp_dir, recursive = TRUE), add = TRUE) dashboard <- create_dashboard(temp_dir, "Themed", theme = "darkly") %>% add_page("Home", text = "# Dark Theme", is_landing_page = TRUE) # Use tryCatch to handle rendering failures gracefully result <- tryCatch({ html_path <- preview(dashboard, open = FALSE, quarto = TRUE, theme = "darkly") list(success = TRUE, path = html_path) }, error = function(e) { list(success = FALSE, error = e$message) }) skip_if(!result$success, paste("Preview rendering failed:", result$error)) expect_true(file.exists(result$path)) }) # ----------------------------------------------------------------------------- # 10. Path Parameter Tests # ----------------------------------------------------------------------------- test_that("preview saves to specified file path", { temp_file <- tempfile(fileext = ".html") on.exit(unlink(temp_file), add = TRUE) content <- create_content(data = mtcars) %>% add_viz(type = "histogram", x_var = "mpg") result_path <- preview(content, path = temp_file, open = FALSE, quarto = FALSE) expect_equal(normalizePath(result_path), normalizePath(temp_file)) expect_true(file.exists(temp_file)) }) test_that("preview saves to specified directory", { temp_dir <- tempfile() dir.create(temp_dir) on.exit(unlink(temp_dir, recursive = TRUE), add = TRUE) content <- create_content(data = mtcars) %>% add_viz(type = "histogram", x_var = "mpg") result_path <- preview(content, path = temp_dir, open = FALSE, quarto = FALSE) expect_true(file.exists(result_path)) expect_match(result_path, "preview\\.html$") }) # ----------------------------------------------------------------------------- # 11. Edge Cases # ----------------------------------------------------------------------------- test_that("preview handles page without data (text only)", { page <- create_page("Text Only") %>% add_text("# Just Text", "No visualizations here") # Should work without data since no visualizations html_path <- preview(page, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) expect_html_contains(html_path, c("Just Text")) }) test_that("preview handles empty collection gracefully", { content <- create_content(data = mtcars) expect_error( preview(content, open = FALSE), "empty" ) }) test_that("preview handles collection with only content blocks", { content <- create_content() %>% add_text("# Title") %>% add_callout("Note", type = "note") %>% add_divider() html_path <- preview(content, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) expect_html_contains(html_path, c("Title", "Note")) }) # ----------------------------------------------------------------------------- # 12. Table Tests # ----------------------------------------------------------------------------- test_that("preview renders basic table blocks", { content <- create_content() %>% add_table(head(mtcars), caption = "Cars data") html_path <- preview(content, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) html <- paste(readLines(html_path, warn = FALSE), collapse = "\n") # Should have table structure expect_true(grepl("table|% add_gt(gt_table) html_path <- suppressWarnings(preview(content, open = FALSE, quarto = FALSE)) expect_true(file.exists(html_path)) }) test_that("preview renders reactable tables if available", { skip_if_not_installed("reactable") content <- create_content() %>% add_reactable(head(mtcars, 5)) html_path <- preview(content, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) }) test_that("preview renders DT tables if available", { skip_if_not_installed("DT") content <- create_content() %>% add_DT(head(mtcars, 5)) html_path <- preview(content, open = FALSE, quarto = FALSE) expect_true(file.exists(html_path)) }) } # end covr CI skip