Skip to content

Commit b03eccd

Browse files
authored
Add assortment of unit tests to Dash for R (#179)
* 🚨 add layout unit test * 🚨 restore API unit tests * 🚨 add wildcards unit tests * 🚨 add components unit tests
1 parent 0085036 commit b03eccd

File tree

4 files changed

+161
-0
lines changed

4 files changed

+161
-0
lines changed

tests/testthat/test-components.R

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
context("components")
2+
3+
test_that("Components work recursively (components can be children of components)", {
4+
5+
# div inside a div
6+
x <- dashHtmlComponents::htmlDiv(id = "one", htmlDiv(id = "two"))
7+
expect_true(dash:::is.component(x))
8+
expect_true(dash:::is.component(x[[1]]$children))
9+
10+
# slider inside a div
11+
x <- htmlDiv(
12+
dashCoreComponents::dccSlider(
13+
id = "h",
14+
min = 1,
15+
max = 100,
16+
value = 48
17+
)
18+
)
19+
20+
expect_true(dash:::is.component(x))
21+
expect_true(dash:::is.component(x[[1]]$children))
22+
slider <- x$props
23+
expect_true(slider$children$props[["id"]] == "h")
24+
expect_true(slider$children$props[["min"]] == 1)
25+
expect_true(slider$children$props[["max"]] == 100)
26+
expect_true(slider$children$props[["value"]] == 48)
27+
})
28+
29+
test_that("Component constructors behave as intended", {
30+
31+
# components have three main keys
32+
# (1) props: or the main properties, which are recursive (component)
33+
# (2) type: or the 'name' of the component
34+
# (3) namespace: is this a core/html component?
35+
36+
expect_component_names <- function(component) {
37+
diff <- dash:::setdiffsym(names(component), c("props", "type", "namespace", "propNames", "package"))
38+
expect_length(diff, 0)
39+
}
40+
41+
expect_component_names(dashHtmlComponents::htmlA())
42+
expect_component_names(dashCoreComponents::dccDropdown())
43+
44+
expect_equal(
45+
htmlH2("A header")$props$children[[1]], "A header"
46+
)
47+
48+
# test akin to this one https://github.com/plotly/dash-renderer/blob/851d717b/tests/test_render.py#L25-L38
49+
vals <- list("Basic string", 3.14, NULL, htmlDiv("Just a test"))
50+
prop_vals <- htmlH2(vals)$props
51+
expect_identical(prop_vals$children[[1]], vals[[1]])
52+
53+
# TODO: test the rendered DOM!
54+
55+
})
56+
57+
58+
test_that("Giving nonsense arguments to components yields error", {
59+
expect_error(
60+
htmlA(nonsense = "string", gibberish = "string"),
61+
"The following props are not valid in this component: 'nonsense, gibberish'",
62+
fixed = TRUE
63+
)
64+
})
65+
66+
# test_that("Can identify whether a component contains a component of a given type", {
67+
# g <- dashCoreComponents::dccGraph()
68+
# s <- dashCoreComponents::dccSlider()
69+
# expect_true(dash:::component_contains_type(g, "dashCoreComponents", "Graph"))
70+
# expect_false(dash:::component_contains_type(g, "dash", "Graph"))
71+
# expect_false(dash:::component_contains_type(s, "dashCoreComponents", "Graph"))
72+
# expect_true(dash:::component_contains_type(htmlDiv(children=list(s, htmlDiv(g))), "dashCoreComponents", "Graph"))
73+
# })
74+
75+
test_that("wildcard attributes work with children", {
76+
s1 <- htmlSpan("hmm", className = "value-output", `data-icon` = "fa-pencil")
77+
s2 <- htmlSpan(children = list("hmm"), className = "value-output", `data-icon` = "fa-pencil")
78+
79+
expect_equal(s1$props$children, "hmm")
80+
expect_equal(s1$props$`data-icon`, "fa-pencil")
81+
expect_equal(s2$props$children, list("hmm"))
82+
expect_equal(s2$props$`data-icon`, "fa-pencil")
83+
})
84+
85+
# test_that("Can translate arbitrary HTML string", {
86+
# skip_if_not_installed("dashDangerouslySetInnerHtml")
87+
#
88+
# html <- "<div> 1 </div>"
89+
# expect_is(
90+
# dashDangerouslySetInnerHtml::DangerouslySetInnerHTML(HTML(html)),
91+
# "dash_component"
92+
# )
93+
# })

tests/testthat/test-dash.R

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
context("dash-api")
2+
3+
test_that("Can access fiery server within a dash app", {
4+
5+
d <- Dash$new()
6+
expect_is(d, c("Dash", "R6"))
7+
expect_is(d$server, c("Fiery", "R6"))
8+
9+
})
10+
11+
test_that("Can set/get layout", {
12+
13+
d <- Dash$new()
14+
div <- htmlDiv("A div", id = "An id")
15+
16+
# rendered layout has a container div
17+
d$layout(div)
18+
l <- d$layout_get()
19+
expect_true(dash:::is.layout(l))
20+
expect_identical(l$props$children[[1]], div)
21+
22+
# dynamic layouts
23+
d$layout(function() { div })
24+
l2 <- d$layout_get()
25+
expect_identical(l, l2)
26+
expect_is(d$layout_get(render = FALSE), "function")
27+
28+
})

tests/testthat/test-layout.R

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
context("layout")
2+
3+
test_that("layout IDs must be unique", {
4+
5+
app <- Dash$new()
6+
7+
expect_error(
8+
app$layout(htmlA(id = "a"), htmlA(id = "a")),
9+
"layout ids must be unique -- the following id was duplicated: 'a'"
10+
)
11+
12+
})

tests/testthat/test-wildcards.R

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
context("wildcards")
2+
3+
test_that("HTML `data-*` & `aria-* ` wildcards work", {
4+
x <- htmlDiv(`data-foo` = 1)
5+
expect_equal(x$props$`data-foo`, 1)
6+
expect_true("data-foo" %in% x$propNames)
7+
8+
x <- htmlDiv(`aria-bar` = "b")
9+
expect_equal(x$props$`aria-bar`, "b")
10+
expect_true("aria-bar" %in% x$propNames)
11+
12+
x <- htmlDiv(`data-foo` = NA, `aria-bar` = 1:10)
13+
expect_equal(x$props$`data-foo`, NA)
14+
expect_equal(x$props$`aria-bar`, 1:10)
15+
expect_true("data-foo" %in% x$propNames)
16+
expect_true("aria-bar" %in% x$propNames)
17+
})
18+
19+
20+
test_that("HTML `data-*` & `aria-* ` wildcards are passed along to layout appropriately ", {
21+
app <- Dash$new()
22+
app$layout(htmlDiv(id = "foo", `data-foo` = 1))
23+
x <- app$layout_get()
24+
expect_equal(x$props$children[[1]]$props$`data-foo`, 1)
25+
})
26+
27+
# TODO: test NULL values aren't rendered on the HTML div
28+
# https://github.com/plotly/dash/pull/237/files#r179251041

0 commit comments

Comments
 (0)