test_that("dummy board ui test", {
ui <- board_ui(
"test",
new_dock_board(blocks = c(a = new_dataset_block()))
)
expect_s3_class(ui, "shiny.tag.list")
# 8 base elements + the two pre-rendered block-browser sidebars
# (add_block_sidebar, append_block_sidebar).
expect_length(ui, 10L)
})
# Settings sidebar is mounted with pre-rendered content + a JS-trigger gear
# button (PR #2 amendment: static-content sidebar). The chain that used to
# live server-side (settings_observer → show_sidebar → settings_body) is
# replaced by markup, so the assertions move to the rendered tag tree.
test_that("settings sidebar mount is pre-rendered with the options accordion", {
ui <- board_ui(
"test",
new_dock_board(blocks = c(a = new_dataset_block()))
)
html <- as.character(ui)
# The settings sidebar exists with the namespaced DOM id and overlay
# mode. The id is `NS("test", "settings_sidebar")` so two boards on
# the same page don't collide.
expect_match(html, 'id="test-settings_sidebar"', fixed = TRUE)
expect_match(html, 'data-mode="overlay"', fixed = TRUE)
# Its body slot carries the rendered options accordion. We probe by
# looking for the inputId of the default `board_name` option, which is
# always present (contributed by blockr.core for any board).
expect_match(html, 'id="test-board_name"', fixed = TRUE)
# And the panel's title slot is populated at UI-build time.
expect_match(
html,
'
',
fixed = TRUE
)
})
test_that("gear button targets the settings sidebar via data-attribute", {
ui <- board_ui(
"test",
new_dock_board(blocks = c(a = new_dataset_block()))
)
html <- as.character(ui)
# The gear opens the settings sidebar purely client-side; no Shiny input
# is wired, so no `id="test-settings_btn"` should appear.
expect_match(
html,
'data-blockr-sidebar-target="test-settings_sidebar"',
fixed = TRUE
)
expect_false(grepl('id="test-settings_btn"', html, fixed = TRUE))
})
test_that("caller-supplied `options` flows into the rendered settings body", {
# Simulate `serve(board, options = custom_options(...))`: replace the
# default `board_options` with a single synthetic option carrying a
# unique id we can grep for.
marker_id <- "marker_opt_for_test"
custom <- blockr.core::as_board_options(
list(
blockr.core::new_board_option(
id = marker_id,
default = "hi",
ui = function(id) {
shiny::textInput(NS(id, marker_id), label = "Marker")
},
category = "custom",
# `ctor` defaults to `sys.parent()`, which tries to resolve the
# package of the calling closure. In a test scope that closure has
# no namespace, so pass an explicit `pkg::fn` identifier instead.
ctor = "blockr.core::new_board_option"
)
)
)
ui <- board_ui(
"test",
new_dock_board(blocks = c(a = new_dataset_block())),
options = custom
)
html <- as.character(ui)
# The custom option appears.
expect_match(html, sprintf('id="test-%s"', marker_id), fixed = TRUE)
# The default options that would have been recomputed are NOT
# present — the override fully replaces the set.
expect_false(grepl('id="test-board_name"', html, fixed = TRUE))
})
test_that("locked mode renders a navbar lock indicator", {
brd <- new_dock_board(blocks = c(a = new_dataset_block()))
unlocked_html <- withr::with_options(
list(blockr.dock_is_locked = NULL),
as.character(board_ui("test", brd))
)
expect_false(grepl("blockr-lock-indicator", unlocked_html, fixed = TRUE))
locked_html <- withr::with_options(
list(blockr.dock_is_locked = TRUE),
as.character(board_ui("test", brd))
)
expect_match(locked_html, "blockr-lock-indicator", fixed = TRUE)
expect_match(locked_html, 'role="status"', fixed = TRUE)
expect_match(locked_html, "blockr-lock-indicator-label", fixed = TRUE)
# Visible label, not just the aria-label / tooltip.
expect_match(locked_html, ">Read-only<", fixed = TRUE)
})