test_that("add_modal creates modal content in collection", {
# Create a viz collection with a modal
viz <- create_viz(mtcars, name = "test") %>%
add_text("[Click me](#test-modal){.modal-link}") %>%
add_modal(
modal_id = "test-modal",
title = "Test Title",
modal_content = "Test content"
)
# Check that needs_modals flag is set
expect_true(viz$needs_modals)
# Check that content blocks were added
expect_true(length(viz$items) > 0)
})
test_that("add_modal works with viz_collection", {
viz <- create_viz(mtcars, name = "test") %>%
add_modal(
modal_id = "viz-modal",
title = "Viz Modal",
modal_content = "Content"
)
expect_s3_class(viz, "content_collection")
expect_true(viz$needs_modals)
})
test_that("add_modal with data.frame converts to table", {
viz <- create_viz(mtcars, name = "test") %>%
add_modal(
modal_id = "data-modal",
title = "Data",
modal_content = head(mtcars, 5)
)
# Should have created content with HTML table
expect_true(viz$needs_modals)
expect_true(length(viz$items) > 0)
})
test_that("add_modal with image includes image tag", {
viz <- create_viz(mtcars, name = "test") %>%
add_modal(
modal_id = "img-modal",
title = "Image Modal",
image = "test.png",
modal_content = "Description"
)
expect_true(viz$needs_modals)
})
test_that("add_modal escapes quotes in content", {
viz <- create_viz(mtcars, name = "test") %>%
add_modal(
modal_id = "quote-modal",
title = "Test",
modal_content = "Content with 'single quotes' and more"
)
expect_true(viz$needs_modals)
})
test_that("multiple modals can be added to same collection", {
viz <- create_viz(mtcars, name = "test") %>%
add_modal(
modal_id = "modal-1",
title = "First",
modal_content = "Content 1"
) %>%
add_modal(
modal_id = "modal-2",
title = "Second",
modal_content = "Content 2"
)
expect_true(viz$needs_modals)
# Should have multiple content blocks
expect_true(length(viz$items) >= 2)
})
test_that("modal content is properly formatted", {
# Test the internal helper function
html_table <- dashboardr:::.df_to_html_table(head(mtcars, 3))
expect_true(grepl("
", html_table))
expect_true(grepl("", html_table))
expect_true(grepl("mpg", html_table))
expect_true(grepl("cyl", html_table))
})
test_that("modal with only title works", {
viz <- create_viz(mtcars, name = "test") %>%
add_modal(
modal_id = "title-only",
title = "Just a Title"
)
expect_true(viz$needs_modals)
})
test_that("modal with HTML content works", {
viz <- create_viz(mtcars, name = "test") %>%
add_modal(
modal_id = "html-modal",
title = "HTML",
modal_content = "Bold text
"
)
expect_true(viz$needs_modals)
})
test_that("page generation includes modal assets when needed", {
# Create a page with modal
viz <- create_viz(mtcars, name = "test") %>%
add_text("[Link](#modal){.modal-link}") %>%
add_modal(
modal_id = "modal",
title = "Test",
modal_content = "Content"
)
page <- list(
title = "Test Page",
file_name = "test",
visualizations = list(viz),
needs_modals = viz$needs_modals
)
# Check that needs_modals flag is preserved
expect_true(page$needs_modals)
})
test_that("modal_content function creates proper HTML structure", {
content <- modal_content(
modal_id = "test",
title = "Title",
text = "Text content"
)
expect_s3_class(content, "shiny.tag")
expect_equal(content$attribs$id, "test")
expect_equal(content$attribs$class, "modal-content")
expect_equal(content$attribs$style, "display:none;")
})
test_that("modal_link creates proper anchor tag", {
link <- modal_link("Click me", "my-modal")
expect_s3_class(link, "shiny.tag")
expect_equal(link$name, "a")
expect_equal(link$attribs$href, "#my-modal")
})
test_that("enable_modals returns necessary assets", {
result <- enable_modals()
expect_s3_class(result, "shiny.tag.list")
expect_length(result, 2) # CSS and JS
})
# =============================================================================
# Tests for add_modal with page_object (fixes regression from Feb 2026)
# =============================================================================
test_that("add_modal works with page_object", {
# Create a page and add a modal
page <- create_page("Test", data = mtcars, type = "bar") %>%
add_text("[Click here](#info){.modal-link}") %>%
add_modal(
modal_id = "info",
title = "Information",
modal_content = "This is some info."
)
# Check that we get a page_object back
expect_s3_class(page, "page_object")
# Check that needs_modals flag is set on the page
expect_true(page$needs_modals)
# Check that the modal block was added to page$.items
modal_items <- Filter(function(x) x$type == "modal", page$.items)
expect_length(modal_items, 1)
expect_equal(modal_items[[1]]$modal_id, "info")
})
test_that("add_modal.page_object creates modal block with correct structure", {
page <- create_page("Test", data = mtcars) %>%
add_modal(
modal_id = "test-modal",
title = "Test Title",
modal_content = "Test content here"
)
# Find the modal item
modal_item <- Filter(function(x) x$type == "modal", page$.items)[[1]]
# Check structure
expect_equal(modal_item$type, "modal")
expect_equal(modal_item$modal_id, "test-modal")
expect_true(grepl("Test Title
", modal_item$html_content))
expect_true(grepl("Test content here", modal_item$html_content))
})
test_that("multiple modals can be added to page_object", {
page <- create_page("Test", data = mtcars) %>%
add_modal(modal_id = "modal-1", title = "First", modal_content = "Content 1") %>%
add_modal(modal_id = "modal-2", title = "Second", modal_content = "Content 2") %>%
add_modal(modal_id = "modal-3", title = "Third", modal_content = "Content 3")
# Check needs_modals is set
expect_true(page$needs_modals)
# Check all three modals were added
modal_items <- Filter(function(x) x$type == "modal", page$.items)
expect_length(modal_items, 3)
# Check modal IDs
modal_ids <- sapply(modal_items, function(x) x$modal_id)
expect_setequal(modal_ids, c("modal-1", "modal-2", "modal-3"))
})
test_that("add_modal.page_object with image includes image tag", {
page <- create_page("Test", data = mtcars) %>%
add_modal(
modal_id = "img-modal",
title = "With Image",
image = "chart.png",
image_width = "80%",
modal_content = "Description"
)
modal_item <- Filter(function(x) x$type == "modal", page$.items)[[1]]
# Check image is in HTML content
expect_true(grepl('
%
add_text("[Link](#modal){.modal-link}") %>%
add_viz(x_var = "cyl", title = "Test") %>%
add_modal(modal_id = "modal", title = "Info", modal_content = "Content")
# Convert to content using internal function
content <- dashboardr:::.page_to_content(page)
# Check that needs_modals propagated
expect_true(content$needs_modals)
})
test_that("page_object modals generate correct QMD output", {
skip_on_cran()
# Create a temporary directory for the test
test_dir <- tempfile("modal_test_")
dir.create(test_dir)
on.exit(unlink(test_dir, recursive = TRUE))
# Create page with modal
page <- create_page("Results", data = mtcars, type = "bar") %>%
add_text("[View details](#details){.modal-link}") %>%
add_viz(x_var = "cyl", title = "Cylinders") %>%
add_modal(
modal_id = "details",
title = "Details",
modal_content = "More information here."
)
# Generate dashboard (without rendering)
dashboard <- create_dashboard(title = "Test", output_dir = test_dir) %>%
add_page(page) %>%
generate_dashboard(render = FALSE, quiet = TRUE)
# Read generated QMD
qmd_file <- file.path(test_dir, "results.qmd")
expect_true(file.exists(qmd_file))
qmd_content <- readLines(qmd_file)
qmd_text <- paste(qmd_content, collapse = "\n")
# Check that enable_modals() is included
expect_true(grepl("enable_modals\\(\\)", qmd_text))
# Check that modal_content() is included with correct ID
expect_true(grepl("modal_content\\(", qmd_text))
expect_true(grepl("modal_id = 'details'", qmd_text))
# Check that the title and content are in the generated code
expect_true(grepl("Details
", qmd_text))
expect_true(grepl("More information here", qmd_text))
})
test_that("page_object with text and modals mixed preserves order", {
page <- create_page("Test", data = mtcars) %>%
add_text("First text") %>%
add_modal(modal_id = "m1", title = "Modal 1", modal_content = "C1") %>%
add_text("Second text") %>%
add_modal(modal_id = "m2", title = "Modal 2", modal_content = "C2")
# Check item order
expect_equal(page$.items[[1]]$type, "text")
expect_equal(page$.items[[2]]$type, "modal")
expect_equal(page$.items[[3]]$type, "text")
expect_equal(page$.items[[4]]$type, "modal")
# Check modal IDs in order
expect_equal(page$.items[[2]]$modal_id, "m1")
expect_equal(page$.items[[4]]$modal_id, "m2")
})