test_that("edit extension server (blocks)", {
testServer(
blk_ext_srv,
{
expect_null(update())
session$setInputs(
registry_select = "dataset_block",
block_id = "a",
confirm_add = 1
)
res <- update()$blocks
expect_s3_class(res$add, "blocks")
expect_length(res$add, 1L)
expect_null(res$rm)
expect_null(session$returned)
},
args = list(
board = board_args(),
update = reactiveVal()
)
)
testServer(
blk_ext_srv,
{
expect_null(update())
session$setInputs(block_select = "a", confirm_rm = 1)
session$flushReact()
res <- update()$blocks
expect_type(res$rm, "character")
expect_length(res$rm, 1L)
expect_null(res$add)
expect_null(session$returned)
},
args = list(
board = board_args(
blocks = c(
a = new_dataset_block("iris"),
b = new_subset_block()
),
links = links(from = "a", to = "b")
),
update = reactiveVal()
)
)
testServer(
blk_ext_srv,
{
expect_null(update())
session$setInputs(confirm_add = 1)
session$setInputs(block_id = "", confirm_add = 2)
session$setInputs(block_id = "a", confirm_add = 3)
session$setInputs(block_id = "c", registry_select = "abc",
confirm_add = 4)
session$setInputs(cancel_add = 1)
session$setInputs(confirm_rm = 1)
session$setInputs(block_select = "x", confirm_rm = 2)
session$setInputs(cancel_rm = 1)
res <- update()$blocks
expect_null(res$add)
expect_null(res$rm)
expect_null(session$returned)
},
args = list(
board = board_args(
blocks = c(
a = new_dataset_block("iris"),
b = new_subset_block()
),
links = links(from = "a", to = "b")
),
update = reactiveVal()
)
)
})
test_that("edit extension server (links)", {
testServer(
blk_ext_srv,
{
expect_null(session$returned)
expect_null(update())
expect_identical(upd$add, links())
expect_identical(upd$rm, character())
expect_null(upd$edit)
expect_null(update())
session$setInputs(add_link = 1)
expect_s3_class(upd$add, "links")
expect_length(upd$add, 1L)
lnk <- names(upd$add)
expect_identical(upd$add, as_links(set_names(list(new_link()), lnk)))
session$setInputs(add_link = 2)
expect_identical(upd$add, as_links(set_names(list(new_link()), lnk)))
upd$edit <- list(row = names(upd$add), col = "from", val = "a")
session$flushReact()
expect_identical(upd$add, as_links(set_names(list(new_link("a")), lnk)))
upd$edit <- list(row = names(upd$add), col = "to", val = "b")
session$flushReact()
expect_identical(
upd$add,
as_links(set_names(list(new_link("a", "b")), lnk))
)
upd$edit <- list(row = names(upd$add), col = "input", val = "data")
session$flushReact()
expect_identical(
upd$add,
as_links(set_names(list(new_link("a", "b", "data")), lnk))
)
session$setInputs(apply_changes = 1)
expect_identical(
update()$links,
list(
add = as_links(set_names(list(new_link("a", "b", "data")), lnk)),
rm = NULL
)
)
expect_identical(upd$add, links())
expect_identical(upd$rm, character())
expect_null(session$returned)
},
args = list(
board = board_args(
blocks = c(
a = new_dataset_block("iris"),
b = new_subset_block()
)
),
update = reactiveVal()
)
)
testServer(
blk_ext_srv,
{
expect_null(upd$edit)
expect_length(upd$add, 0L)
session$flushReact()
expect_length(upd$obs, 1L)
expect_named(upd$obs, "ac")
expect_type(upd$obs, "list")
expect_length(upd$obs[["ac"]], 3L)
expect_named(upd$obs[["ac"]], c("from", "to", "input"))
expect_type(upd$obs[["ac"]], "list")
for (i in c("from", "to", "input")) {
expect_type(upd$obs[["ac"]][[i]], "list")
for (x in upd$obs[["ac"]][[i]]) {
expect_s3_class(x, "Observer")
}
}
session$setInputs(ac_input = "data")
expect_null(upd$edit)
expect_length(upd$add, 0L)
session$setInputs(ac_to = "d")
expect_identical(upd$edit, list(row = "ac", col = "to", val = "d"))
expect_length(upd$add, 1L)
session$setInputs(ac_from = "b")
expect_identical(upd$edit, list(row = "ac", col = "from", val = "b"))
expect_length(upd$add, 1L)
},
args = list(
board = board_args(
blocks = c(
a = new_dataset_block("iris"),
b = new_dataset_block("mtcars"),
c = new_subset_block(),
d = new_subset_block()
),
links = links(ac = new_link(from = "a", to = "c"))
),
update = reactiveVal()
)
)
testServer(
blk_ext_srv,
{
expect_null(session$returned)
expect_null(update())
expect_s3_class(upd$curr, "links")
expect_length(upd$curr, 1L)
expect_named(upd$curr, "aa")
expect_identical(upd$rm, character())
session$setInputs(links_dt_rows_selected = 1, rm_link = 1)
expect_identical(upd$rm, "aa")
session$setInputs(apply_changes = 1)
expect_identical(
update()$links,
list(add = NULL, rm = "aa")
)
expect_identical(upd$add, links())
expect_identical(upd$rm, character())
expect_identical(upd$curr, links())
expect_null(session$returned)
},
args = list(
board = board_args(
blocks = c(
a = new_dataset_block("iris"),
b = new_subset_block()
),
links = links(aa = new_link(from = "a", to = "b"))
),
update = reactiveVal()
)
)
})
test_that("edit extension server (stacks)", {
testServer(
blk_ext_srv,
{
expect_null(update())
expect_identical(stk$add, stacks())
expect_identical(stk$rm, character())
expect_identical(stk$mod, stacks())
expect_null(stk$edit)
session$setInputs(new_stack_id = "s1", add_stack = 1)
expect_s3_class(stk$add, "stacks")
expect_named(stk$add, "s1")
expect_true(is_dock_stack(stk$add[["s1"]]))
stk$edit <- list(row = "s1", col = "name", val = "My Stack")
session$flushReact()
stk$edit <- list(row = "s1", col = "color", val = "#123456")
session$flushReact()
stk$edit <- list(row = "s1", col = "blocks", val = "a")
session$flushReact()
staged <- stk$add[["s1"]]
expect_identical(stack_name(staged), "My Stack")
expect_identical(stack_color(staged), "#123456")
expect_identical(stack_blocks(staged), "a")
session$setInputs(apply_changes = 1)
res <- update()$stacks
expect_s3_class(res$add, "stacks")
expect_named(res$add, "s1")
expect_null(res$rm)
expect_null(res$mod)
expect_identical(stk$add, stacks())
expect_null(session$returned)
},
args = list(
board = board_args(
blocks = c(
a = new_dataset_block("iris"),
b = new_subset_block()
)
),
update = reactiveVal()
)
)
testServer(
blk_ext_srv,
{
session$flushReact()
expect_length(stk$obs, 1L)
expect_named(stk$obs, "s1")
expect_named(stk$obs[["s1"]], c("name", "color", "blocks"))
for (x in stk$obs[["s1"]]) {
expect_s3_class(x, "Observer")
}
session$setInputs(s1_name = "Renamed")
expect_identical(
stk$edit,
list(row = "s1", col = "name", val = "Renamed")
)
expect_true("s1" %in% names(stk$mod))
session$setInputs(s1_color = "#00ff00")
expect_identical(
stk$edit,
list(row = "s1", col = "color", val = "#00ff00")
)
session$setInputs(s1_blocks = c("a", "b"))
expect_identical(stk$edit$col, "blocks")
expect_setequal(stk$edit$val, c("a", "b"))
session$setInputs(apply_changes = 1)
res <- update()$stacks
expect_null(res$add)
expect_null(res$rm)
expect_named(res$mod, "s1")
payload <- res$mod[["s1"]]
expect_false(is_stack(payload))
expect_named(payload, c("name", "blocks", "color"))
expect_identical(payload$name, "Renamed")
expect_identical(payload$color, "#00ff00")
expect_setequal(payload$blocks, c("a", "b"))
},
args = list(
board = board_args(
blocks = c(
a = new_dataset_block("iris"),
b = new_subset_block()
),
stacks = stacks(s1 = new_dock_stack(blocks = "a", name = "One"))
),
update = reactiveVal()
)
)
testServer(
blk_ext_srv,
{
session$flushReact()
expect_identical(stk$rm, character())
session$setInputs(stacks_dt_rows_selected = 1, rm_stack = 1)
expect_identical(stk$rm, "s1")
session$setInputs(apply_changes = 1)
res <- update()$stacks
expect_null(res$add)
expect_null(res$mod)
expect_identical(res$rm, "s1")
expect_identical(stk$rm, character())
expect_identical(stk$curr, stacks())
expect_null(session$returned)
},
args = list(
board = board_args(
blocks = c(
a = new_dataset_block("iris"),
b = new_subset_block()
),
stacks = stacks(s1 = new_dock_stack(blocks = "a", name = "One"))
),
update = reactiveVal()
)
)
})
test_that("edit extension applies links and stacks together", {
testServer(
blk_ext_srv,
{
session$flushReact()
upd$add <- as_links(set_names(list(new_link("a", "b", "data")), "lnk"))
stk$edit <- list(row = "s1", col = "name", val = "Renamed")
session$flushReact()
expect_length(upd$add, 1L)
expect_true("s1" %in% names(stk$mod))
session$setInputs(apply_changes = 1)
res <- update()
expect_named(res, c("links", "stacks"))
expect_s3_class(res$links$add, "links")
expect_named(res$stacks$mod, "s1")
expect_identical(upd$add, links())
expect_identical(stk$mod, stacks())
},
args = list(
board = board_args(
blocks = c(
a = new_dataset_block("iris"),
b = new_subset_block()
),
stacks = stacks(s1 = new_dock_stack(blocks = "a", name = "One"))
),
update = reactiveVal()
)
)
})
test_that("merge_staged_links overlays staged edits on refreshed links", {
applied <- links(
l1 = new_link(from = "a", to = "c", input = "1"),
l2 = new_link(from = "b", to = "c", input = "2")
)
expect_identical(
merge_staged_links(applied, links(), character()),
applied
)
added <- links(x = new_link(from = "", to = "", input = ""))
expect_identical(
merge_staged_links(applied, added, character()),
c(applied, added)
)
edited <- links(l1 = new_link(from = "a", to = "c", input = "9"))
in_place <- applied
in_place["l1"] <- edited
expect_identical(merge_staged_links(applied, edited, "l1"), in_place)
expect_named(merge_staged_links(applied, links(), "l2"), "l1")
expect_named(
merge_staged_links(applied["l1"], added, character()),
c("l1", "x")
)
})
test_that("merge_staged_stacks overlays staged edits on refreshed stacks", {
applied <- stacks(
k1 = new_dock_stack(name = "One", color = "#111111"),
k2 = new_dock_stack(name = "Two", color = "#222222")
)
expect_identical(
merge_staged_stacks(applied, stacks(), character(), stacks()),
applied
)
added <- stacks(z = new_dock_stack(name = "Zed", color = "#333333"))
expect_identical(
merge_staged_stacks(applied, added, character(), stacks()),
c(applied, added)
)
modded <- stacks(k1 = new_dock_stack(name = "Renamed", color = "#999999"))
in_place <- applied
in_place[["k1"]] <- modded[["k1"]]
expect_identical(
merge_staged_stacks(applied, stacks(), character(), modded),
in_place
)
expect_named(
merge_staged_stacks(applied, added, "k2", stacks()),
c("k1", "z")
)
})
test_that("edit extension keeps staged link edits when the board re-emits", {
testServer(
blk_ext_srv,
{
session$flushReact()
session$setInputs(add_link = 1)
session$flushReact()
row <- names(upd$add)
expect_length(upd$curr, 1L)
expect_identical(names(upd$curr), row)
board$board <- new_dock_board(
blocks = c(
a = new_dataset_block("iris"),
b = new_dataset_block("mtcars"),
c = new_rbind_block()
)
)
session$flushReact()
expect_length(upd$curr, 1L)
expect_identical(names(upd$curr), row)
expect_identical(upd$add, upd$curr[row])
upd$edit <- list(row = row, col = "from", val = "a")
session$flushReact()
upd$edit <- list(row = row, col = "to", val = "c")
session$flushReact()
upd$edit <- list(row = row, col = "input", val = "1")
session$flushReact()
session$setInputs(add_link = 2)
session$flushReact()
row2 <- setdiff(names(upd$curr), row)
upd$edit <- list(row = row2, col = "from", val = "b")
session$flushReact()
upd$edit <- list(row = row2, col = "to", val = "c")
session$flushReact()
upd$edit <- list(row = row2, col = "input", val = "2")
session$flushReact()
session$setInputs(apply_changes = 1)
res <- update()$links
expect_s3_class(res$add, "links")
expect_length(res$add, 2L)
},
args = list(
board = board_args(
blocks = c(
a = new_dataset_block("iris"),
b = new_dataset_block("mtcars"),
c = new_rbind_block()
)
),
update = reactiveVal()
)
)
})
test_that("edit extension redraws links only when the id set changes", {
redraws <- 0L
local_mocked_bindings(
replaceData = function(...) redraws <<- redraws + 1L,
.package = "DT"
)
testServer(
blk_ext_srv,
{
session$flushReact()
expect_identical(names(upd$curr), "aa")
expect_setequal(names(upd$obs), "aa")
base <- redraws
upd$curr <- links(aa = new_link(from = "a", to = ""))
session$flushReact()
expect_identical(names(upd$curr), "aa")
expect_identical(redraws, base)
expect_setequal(names(upd$obs), "aa")
upd$curr <- links(
aa = new_link(from = "a", to = ""),
bb = new_link(from = "b", to = "")
)
session$flushReact()
expect_gt(redraws, base)
expect_setequal(names(upd$obs), c("aa", "bb"))
},
args = list(
board = board_args(
blocks = c(
a = new_dataset_block("iris"),
b = new_subset_block()
),
links = links(aa = new_link(from = "a", to = "b"))
),
update = reactiveVal()
)
)
})
test_that("edit extension keeps staged stack edits when the board re-emits", {
testServer(
blk_ext_srv,
{
session$flushReact()
session$setInputs(new_stack_id = "s1", add_stack = 1)
session$flushReact()
stk$edit <- list(row = "s1", col = "blocks", val = "a")
session$flushReact()
expect_named(stk$add, "s1")
expect_true("s1" %in% names(stk$curr))
board$board <- new_dock_board(
blocks = c(
a = new_dataset_block("iris"),
b = new_subset_block()
)
)
session$flushReact()
expect_true("s1" %in% names(stk$curr))
expect_named(stk$add, "s1")
expect_identical(stk$curr[["s1"]], stk$add[["s1"]])
session$setInputs(apply_changes = 1)
res <- update()$stacks
expect_named(res$add, "s1")
},
args = list(
board = board_args(
blocks = c(
a = new_dataset_block("iris"),
b = new_subset_block()
)
),
update = reactiveVal()
)
)
})
test_that("edit extension ignores no-op board re-emits", {
link_syncs <- 0L
stack_syncs <- 0L
real_merge_links <- merge_staged_links
real_merge_stacks <- merge_staged_stacks
local_mocked_bindings(
merge_staged_links = function(...) {
link_syncs <<- link_syncs + 1L
real_merge_links(...)
},
merge_staged_stacks = function(...) {
stack_syncs <<- stack_syncs + 1L
real_merge_stacks(...)
}
)
testServer(
blk_ext_srv,
{
session$flushReact()
expect_gt(link_syncs, 0L)
expect_gt(stack_syncs, 0L)
link_base <- link_syncs
stack_base <- stack_syncs
board$board <- new_dock_board(
blocks = c(
a = new_dataset_block("iris"),
b = new_subset_block()
),
links = links(aa = new_link(from = "a", to = "b")),
stacks = stacks(s1 = new_dock_stack(blocks = "a", name = "One"))
)
session$flushReact()
expect_identical(link_syncs, link_base)
expect_identical(stack_syncs, stack_base)
},
args = list(
board = board_args(
blocks = c(
a = new_dataset_block("iris"),
b = new_subset_block()
),
links = links(aa = new_link(from = "a", to = "b")),
stacks = stacks(s1 = new_dock_stack(blocks = "a", name = "One"))
),
update = reactiveVal()
)
)
})
test_that("dummy edit extension ui test", {
ui <- blk_ext_ui(
"test",
new_dock_board(blocks = c(a = new_dataset_block()))
)
expect_s3_class(ui, "shiny.tag")
expect_identical(htmltools::tagGetAttribute(ui, "class"), "blockr-ext-edit")
})
test_that("variadic link inputs offer no positional-integer options", {
board <- new_dock_board(
blocks = c(
a = new_dataset_block("BOD"),
b = new_dataset_block("BOD"),
c = new_rbind_block()
),
links = links(ac = new_link("a", "c"), bc = new_link("b", "c"))
)
dt <- dt_board_link(board_links(board), NS("x"), board)
expect_false(grepl("