# Test for template manager functions
# Tests for TemplateManager class methods
# ============================================================================
# Setup helper - create temp templates directory
# ============================================================================
create_test_template_dir <- function() {
temp_dir <- file.path(tempdir(), paste0("templates_test_", Sys.getpid()))
dir.create(temp_dir, showWarnings = FALSE, recursive = TRUE)
# Create a simple test template
writeLines(
"
{{title}}{{content}}",
file.path(temp_dir, "test.html")
)
# Create landing page template
writeLines(
"{{session_info}}
{{app_cards}}
",
file.path(temp_dir, "landing_page.html")
)
# Create management page template
writeLines(
"Management Dashboard
",
file.path(temp_dir, "management_page.html")
)
# Create a CSS file for static file tests
styles_dir <- file.path(temp_dir, "styles")
dir.create(styles_dir, showWarnings = FALSE)
writeLines("body { margin: 0; }", file.path(styles_dir, "main.css"))
return(temp_dir)
}
cleanup_test_template_dir <- function(temp_dir) {
unlink(temp_dir, recursive = TRUE)
}
# ============================================================================
# TemplateManager Initialization Tests
# ============================================================================
test_that("TemplateManager initializes with defaults", {
tm <- TemplateManager$new()
expect_true(inherits(tm, "TemplateManager"))
expect_equal(tm$template_dir, "templates")
expect_equal(tm$base_url, "")
})
test_that("TemplateManager initializes with custom values", {
tm <- TemplateManager$new("/custom/path", "/my-base")
expect_equal(tm$template_dir, "/custom/path")
expect_equal(tm$base_url, "/my-base")
})
test_that("create_template_manager factory function works", {
temp_dir <- create_test_template_dir()
on.exit(cleanup_test_template_dir(temp_dir))
tm <- create_template_manager(temp_dir, "/api")
expect_true(inherits(tm, "TemplateManager"))
expect_equal(tm$template_dir, temp_dir)
expect_equal(tm$base_url, "/api")
})
# ============================================================================
# load_template() Tests
# ============================================================================
test_that("load_template loads existing template", {
temp_dir <- create_test_template_dir()
on.exit(cleanup_test_template_dir(temp_dir))
tm <- TemplateManager$new(temp_dir)
content <- tm$load_template("test")
expect_match(content, "")
expect_match(content, "\\{\\{title\\}\\}")
expect_match(content, "\\{\\{content\\}\\}")
})
test_that("load_template throws error for missing template", {
temp_dir <- create_test_template_dir()
on.exit(cleanup_test_template_dir(temp_dir))
tm <- TemplateManager$new(temp_dir)
expect_error(tm$load_template("nonexistent"), "Template not found")
})
test_that("load_template handles invalid directory", {
tm <- TemplateManager$new("/nonexistent/path")
expect_error(tm$load_template("test"), "Template not found")
})
# ============================================================================
# render_template() Tests
# ============================================================================
test_that("render_template substitutes variables", {
temp_dir <- create_test_template_dir()
on.exit(cleanup_test_template_dir(temp_dir))
tm <- TemplateManager$new(temp_dir)
result <- tm$render_template("test", list(
title = "My Page",
content = "Hello World"
))
expect_match(result, "My Page")
expect_match(result, "Hello World")
expect_no_match(result, "\\{\\{title\\}\\}")
expect_no_match(result, "\\{\\{content\\}\\}")
})
test_that("render_template adds base_url to variables", {
temp_dir <- create_test_template_dir()
on.exit(cleanup_test_template_dir(temp_dir))
# Create template that uses base_url
writeLines(
"",
file.path(temp_dir, "with_base_url.html")
)
tm <- TemplateManager$new(temp_dir, "/my-app")
result <- tm$render_template("with_base_url", list())
expect_match(result, "/my-app/styles.css")
})
test_that("render_template handles empty variables", {
temp_dir <- create_test_template_dir()
on.exit(cleanup_test_template_dir(temp_dir))
tm <- TemplateManager$new(temp_dir)
result <- tm$render_template("test", list())
# Unreplaced variables remain as-is
expect_match(result, "\\{\\{title\\}\\}")
expect_match(result, "\\{\\{content\\}\\}")
})
test_that("render_template handles numeric variables", {
temp_dir <- create_test_template_dir()
on.exit(cleanup_test_template_dir(temp_dir))
writeLines("Count: {{count}}", file.path(temp_dir, "numeric.html"))
tm <- TemplateManager$new(temp_dir)
result <- tm$render_template("numeric", list(count = 42))
expect_match(result, "Count: 42")
})
# ============================================================================
# generate_app_cards() Tests
# ============================================================================
test_that("generate_app_cards returns message for empty apps", {
temp_dir <- create_test_template_dir()
on.exit(cleanup_test_template_dir(temp_dir))
tm <- TemplateManager$new(temp_dir)
result <- tm$generate_app_cards(list())
expect_match(result, "No applications configured")
})
test_that("generate_app_cards generates HTML for apps", {
temp_dir <- create_test_template_dir()
on.exit(cleanup_test_template_dir(temp_dir))
tm <- TemplateManager$new(temp_dir)
apps <- list(
list(name = "app1", path = "/path1"),
list(name = "app2", path = "/path2")
)
result <- tm$generate_app_cards(apps)
expect_match(result, "app1")
expect_match(result, "app2")
expect_match(result, "app-card")
expect_match(result, "data-app=")
})
test_that("generate_app_cards sorts apps alphabetically", {
temp_dir <- create_test_template_dir()
on.exit(cleanup_test_template_dir(temp_dir))
tm <- TemplateManager$new(temp_dir)
apps <- list(
list(name = "zebra", path = "/z"),
list(name = "alpha", path = "/a"),
list(name = "beta", path = "/b")
)
result <- tm$generate_app_cards(apps)
# Alpha should appear before beta, beta before zebra
alpha_pos <- regexpr("alpha", result)
beta_pos <- regexpr("beta", result)
zebra_pos <- regexpr("zebra", result)
expect_lt(alpha_pos, beta_pos)
expect_lt(beta_pos, zebra_pos)
})
test_that("generate_app_cards escapes HTML in app names", {
temp_dir <- create_test_template_dir()
on.exit(cleanup_test_template_dir(temp_dir))
tm <- TemplateManager$new(temp_dir)
# Note: In practice, app names are validated, but we test the safety
apps <- list(
list(name = "safe-app", path = "/path")
)
result <- tm$generate_app_cards(apps)
# The result should be valid HTML
expect_match(result, "safe-app")
})
# ============================================================================
# generate_landing_page() Tests
# ============================================================================
test_that("generate_landing_page creates HTML with session info", {
temp_dir <- create_test_template_dir()
on.exit(cleanup_test_template_dir(temp_dir))
tm <- TemplateManager$new(temp_dir)
config <- ShinyServerConfig$new()
config$config <- list(
apps = list(
list(name = "testapp", path = "/test")
)
)
result <- tm$generate_landing_page(config)
expect_match(result, "")
expect_match(result, "testapp")
# Should contain R version info from sessionInfo()
# Matches both "R version X.Y.Z" (stable) and "R Under development" (unstable)
expect_match(result, "R (version|Under development)", ignore.case = TRUE)
})
test_that("generate_landing_page handles empty apps list", {
temp_dir <- create_test_template_dir()
on.exit(cleanup_test_template_dir(temp_dir))
tm <- TemplateManager$new(temp_dir)
config <- ShinyServerConfig$new()
config$config <- list(apps = list())
result <- tm$generate_landing_page(config)
expect_match(result, "No applications configured")
})
# ============================================================================
# generate_management_page() Tests
# ============================================================================
test_that("generate_management_page returns HTML", {
temp_dir <- create_test_template_dir()
on.exit(cleanup_test_template_dir(temp_dir))
tm <- TemplateManager$new(temp_dir)
result <- tm$generate_management_page()
expect_match(result, "")
expect_match(result, "Management Dashboard")
})
# ============================================================================
# create_error_page() Tests
# ============================================================================
test_that("create_error_page creates error HTML", {
tm <- TemplateManager$new("templates", "/base")
result <- tm$create_error_page(404, "Page not found")
expect_match(result, "Error 404")
expect_match(result, "Error 404")
expect_match(result, "Page not found")
expect_match(result, "/base/templates/styles/main.css")
})
test_that("create_error_page includes details when provided", {
tm <- TemplateManager$new("templates")
result <- tm$create_error_page(500, "Server error", "Check logs for details")
expect_match(result, "Server error")
expect_match(result, "Check logs for details")
})
test_that("create_error_page escapes HTML in message", {
tm <- TemplateManager$new("templates")
result <- tm$create_error_page(400, "")
# Script tags should be escaped
expect_no_match(result, "