diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 00000000..082b1943
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "makefile.configureOnOpen": false
+}
\ No newline at end of file
diff --git a/inst/examples/restore-workspace/app.R b/inst/examples/restore-workspace/app.R
index 66f19f51..ee30aa42 100644
--- a/inst/examples/restore-workspace/app.R
+++ b/inst/examples/restore-workspace/app.R
@@ -2,12 +2,14 @@ library(blockr)
set_workspace(
stack_1 = new_stack(
+ # Won't autoclick on submit
block_11 = new_dataset_block("anscombe"),
- block_12 = new_select_block(c("x1", "y1"))
+ block_12 = new_filter_block("x1", 10, ">")
),
+ # Submit autoclick
stack_2 = new_stack(
block_21 = new_dataset_block("anscombe"),
- block_22 = new_select_block(c("x2", "y2"))
+ block_22 = new_filter_block("x1", 10, ">", submit = TRUE)
)
)
diff --git a/tests/testthat/_snaps/block/block-app-001_.new.png b/tests/testthat/_snaps/block/block-app-001_.new.png
index 81d792b4..cda1709a 100644
Binary files a/tests/testthat/_snaps/block/block-app-001_.new.png and b/tests/testthat/_snaps/block/block-app-001_.new.png differ
diff --git a/tests/testthat/_snaps/block/block-app-003_.new.png b/tests/testthat/_snaps/block/block-app-003_.new.png
index febafb5a..b4d056ed 100644
Binary files a/tests/testthat/_snaps/block/block-app-003_.new.png and b/tests/testthat/_snaps/block/block-app-003_.new.png differ
diff --git a/tests/testthat/_snaps/block/block-app-004_.new.png b/tests/testthat/_snaps/block/block-app-004_.new.png
index c05f8aff..7cf37837 100644
Binary files a/tests/testthat/_snaps/block/block-app-004_.new.png and b/tests/testthat/_snaps/block/block-app-004_.new.png differ
diff --git a/tests/testthat/_snaps/block/block-autosubmit-app-001.json b/tests/testthat/_snaps/block/block-autosubmit-app-001.json
new file mode 100644
index 00000000..0d06a854
--- /dev/null
+++ b/tests/testthat/_snaps/block/block-autosubmit-app-001.json
@@ -0,0 +1,181 @@
+{
+ "input": {
+ "my_stack-block_2-submit": 0
+ },
+ "output": {
+ "my_stack-block_2-res": {
+ "x": {
+ "style": "bootstrap5",
+ "filter": "none",
+ "vertical": false,
+ "container": "
\n \n \n <\/th>\n | x1<\/th>\n | x2<\/th>\n | x3<\/th>\n | x4<\/th>\n | y1<\/th>\n | y2<\/th>\n | y3<\/th>\n | y4<\/th>\n <\/tr>\n <\/thead>\n<\/table>",
+ "options": {
+ "pageLength": 5,
+ "processing": false,
+ "columnDefs": [
+ {
+ "className": "dt-right",
+ "targets": [
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8
+ ]
+ },
+ {
+ "orderable": false,
+ "targets": 0
+ },
+ {
+ "name": " ",
+ "targets": 0
+ },
+ {
+ "name": "x1",
+ "targets": 1
+ },
+ {
+ "name": "x2",
+ "targets": 2
+ },
+ {
+ "name": "x3",
+ "targets": 3
+ },
+ {
+ "name": "x4",
+ "targets": 4
+ },
+ {
+ "name": "y1",
+ "targets": 5
+ },
+ {
+ "name": "y2",
+ "targets": 6
+ },
+ {
+ "name": "y3",
+ "targets": 7
+ },
+ {
+ "name": "y4",
+ "targets": 8
+ }
+ ],
+ "order": [
+
+ ],
+ "autoWidth": false,
+ "orderClasses": false,
+ "lengthMenu": [
+ 5,
+ 10,
+ 25,
+ 50,
+ 100
+ ],
+ "ajax": {
+ "type": "POST",
+ "data": "function(d) {\nd.search.caseInsensitive = true;\nd.search.smart = true;\nd.escape = true;\nvar encodeAmp = function(x) { x.value = x.value.replace(/&/g, \"%26\"); }\nencodeAmp(d.search);\n$.each(d.columns, function(i, v) {encodeAmp(v.search);});\n}"
+ },
+ "serverSide": true
+ },
+ "selection": {
+ "mode": "none",
+ "selected": null,
+ "target": "row",
+ "selectable": null
+ }
+ },
+ "evals": [
+ "options.ajax.data"
+ ],
+ "jsHooks": [
+
+ ],
+ "deps": [
+ {
+ "name": "jquery",
+ "version": "3.6.0",
+ "src": {
+ "href": "jquery-3.6.0"
+ },
+ "meta": null,
+ "script": "jquery-3.6.0.min.js",
+ "stylesheet": null,
+ "head": null,
+ "attachment": null,
+ "all_files": true
+ },
+ {
+ "name": "dt-core-bootstrap5",
+ "version": "1.13.6",
+ "src": {
+ "href": "dt-core-bootstrap5-1.13.6"
+ },
+ "meta": null,
+ "script": [
+ "js/jquery.dataTables.min.js",
+ "js/dataTables.bootstrap5.min.js"
+ ],
+ "stylesheet": "css/dataTables.bootstrap5.min.css",
+ "head": null,
+ "attachment": null,
+ "package": null,
+ "all_files": false
+ },
+ {
+ "name": "bootstrap",
+ "version": "5.3.1",
+ "src": {
+ "href": "bootstrap-5.3.1"
+ },
+ "meta": {
+ "viewport": "width=device-width, initial-scale=1, shrink-to-fit=no"
+ },
+ "script": "bootstrap.bundle.min.js",
+ "stylesheet": "bootstrap.min.css",
+ "head": null,
+ "attachment": null,
+ "package": null,
+ "all_files": true
+ },
+ {
+ "name": "bs3compat",
+ "version": "0.8.0",
+ "src": {
+ "href": "bs3compat-0.8.0"
+ },
+ "meta": null,
+ "script": [
+ "transition.js",
+ "tabs.js",
+ "bs3compat.js"
+ ],
+ "stylesheet": null,
+ "head": null,
+ "attachment": null,
+ "all_files": true
+ },
+ {
+ "name": "crosstalk",
+ "version": "1.2.1",
+ "src": {
+ "href": "crosstalk-1.2.1"
+ },
+ "meta": null,
+ "script": "js/crosstalk.min.js",
+ "stylesheet": "css/crosstalk.min.css",
+ "head": null,
+ "attachment": null,
+ "all_files": true
+ }
+ ]
+ }
+ }
+}
diff --git a/tests/testthat/_snaps/block/block-submit-app-001.json b/tests/testthat/_snaps/block/block-submit-app-001.json
new file mode 100644
index 00000000..2f7a4dfa
--- /dev/null
+++ b/tests/testthat/_snaps/block/block-submit-app-001.json
@@ -0,0 +1,12 @@
+{
+ "input": {
+ "my_stack-block_2-submit": 0
+ },
+ "output": {
+ "my_stack-block_2-res": [
+ "",
+ "NULL",
+ "c(\"shiny.silent.error\", \"validation\")"
+ ]
+ }
+}
diff --git a/tests/testthat/_snaps/block/block-submit-app-002.json b/tests/testthat/_snaps/block/block-submit-app-002.json
new file mode 100644
index 00000000..dcb7948a
--- /dev/null
+++ b/tests/testthat/_snaps/block/block-submit-app-002.json
@@ -0,0 +1,181 @@
+{
+ "input": {
+ "my_stack-block_2-submit": 1
+ },
+ "output": {
+ "my_stack-block_2-res": {
+ "x": {
+ "style": "bootstrap5",
+ "filter": "none",
+ "vertical": false,
+ "container": "\n \n \n <\/th>\n | x1<\/th>\n | x2<\/th>\n | x3<\/th>\n | x4<\/th>\n | y1<\/th>\n | y2<\/th>\n | y3<\/th>\n | y4<\/th>\n <\/tr>\n <\/thead>\n<\/table>",
+ "options": {
+ "pageLength": 5,
+ "processing": false,
+ "columnDefs": [
+ {
+ "className": "dt-right",
+ "targets": [
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8
+ ]
+ },
+ {
+ "orderable": false,
+ "targets": 0
+ },
+ {
+ "name": " ",
+ "targets": 0
+ },
+ {
+ "name": "x1",
+ "targets": 1
+ },
+ {
+ "name": "x2",
+ "targets": 2
+ },
+ {
+ "name": "x3",
+ "targets": 3
+ },
+ {
+ "name": "x4",
+ "targets": 4
+ },
+ {
+ "name": "y1",
+ "targets": 5
+ },
+ {
+ "name": "y2",
+ "targets": 6
+ },
+ {
+ "name": "y3",
+ "targets": 7
+ },
+ {
+ "name": "y4",
+ "targets": 8
+ }
+ ],
+ "order": [
+
+ ],
+ "autoWidth": false,
+ "orderClasses": false,
+ "lengthMenu": [
+ 5,
+ 10,
+ 25,
+ 50,
+ 100
+ ],
+ "ajax": {
+ "type": "POST",
+ "data": "function(d) {\nd.search.caseInsensitive = true;\nd.search.smart = true;\nd.escape = true;\nvar encodeAmp = function(x) { x.value = x.value.replace(/&/g, \"%26\"); }\nencodeAmp(d.search);\n$.each(d.columns, function(i, v) {encodeAmp(v.search);});\n}"
+ },
+ "serverSide": true
+ },
+ "selection": {
+ "mode": "none",
+ "selected": null,
+ "target": "row",
+ "selectable": null
+ }
+ },
+ "evals": [
+ "options.ajax.data"
+ ],
+ "jsHooks": [
+
+ ],
+ "deps": [
+ {
+ "name": "jquery",
+ "version": "3.6.0",
+ "src": {
+ "href": "jquery-3.6.0"
+ },
+ "meta": null,
+ "script": "jquery-3.6.0.min.js",
+ "stylesheet": null,
+ "head": null,
+ "attachment": null,
+ "all_files": true
+ },
+ {
+ "name": "dt-core-bootstrap5",
+ "version": "1.13.6",
+ "src": {
+ "href": "dt-core-bootstrap5-1.13.6"
+ },
+ "meta": null,
+ "script": [
+ "js/jquery.dataTables.min.js",
+ "js/dataTables.bootstrap5.min.js"
+ ],
+ "stylesheet": "css/dataTables.bootstrap5.min.css",
+ "head": null,
+ "attachment": null,
+ "package": null,
+ "all_files": false
+ },
+ {
+ "name": "bootstrap",
+ "version": "5.3.1",
+ "src": {
+ "href": "bootstrap-5.3.1"
+ },
+ "meta": {
+ "viewport": "width=device-width, initial-scale=1, shrink-to-fit=no"
+ },
+ "script": "bootstrap.bundle.min.js",
+ "stylesheet": "bootstrap.min.css",
+ "head": null,
+ "attachment": null,
+ "package": null,
+ "all_files": true
+ },
+ {
+ "name": "bs3compat",
+ "version": "0.8.0",
+ "src": {
+ "href": "bs3compat-0.8.0"
+ },
+ "meta": null,
+ "script": [
+ "transition.js",
+ "tabs.js",
+ "bs3compat.js"
+ ],
+ "stylesheet": null,
+ "head": null,
+ "attachment": null,
+ "all_files": true
+ },
+ {
+ "name": "crosstalk",
+ "version": "1.2.1",
+ "src": {
+ "href": "crosstalk-1.2.1"
+ },
+ "meta": null,
+ "script": "js/crosstalk.min.js",
+ "stylesheet": "css/crosstalk.min.css",
+ "head": null,
+ "attachment": null,
+ "all_files": true
+ }
+ ]
+ }
+ }
+}
diff --git a/tests/testthat/_snaps/workspace/restore-workspace-app-001_.new.png b/tests/testthat/_snaps/workspace/restore-workspace-app-001_.new.png
index d35bf4b7..ccb4007e 100644
Binary files a/tests/testthat/_snaps/workspace/restore-workspace-app-001_.new.png and b/tests/testthat/_snaps/workspace/restore-workspace-app-001_.new.png differ
diff --git a/tests/testthat/test-block.R b/tests/testthat/test-block.R
index 1ad9ffa0..d7a6e482 100644
--- a/tests/testthat/test-block.R
+++ b/tests/testthat/test-block.R
@@ -1,5 +1,4 @@
test_that("data blocks", {
-
dat1 <- datasets::iris
blk1 <- new_dataset_block()
@@ -38,7 +37,6 @@ test_that("data blocks", {
})
test_that("filter blocks", {
-
data <- datasets::iris
blk1 <- new_filter_block()
@@ -65,7 +63,6 @@ test_that("filter blocks", {
})
test_that("select blocks", {
-
data <- datasets::iris
blk1 <- new_select_block()
@@ -92,7 +89,6 @@ test_that("select blocks", {
})
test_that("arrange blocks", {
-
data <- datasets::iris
blk1 <- new_arrange_block()
@@ -117,7 +113,6 @@ test_that("arrange blocks", {
})
test_that("group_by blocks", {
-
data <- datasets::iris
blk1 <- new_group_by_block()
@@ -142,7 +137,6 @@ test_that("group_by blocks", {
})
test_that("join blocks", {
-
datx <- dplyr::band_members
daty <- dplyr::band_instruments
@@ -170,7 +164,6 @@ test_that("join blocks", {
})
test_that("head blocks", {
-
data <- datasets::iris
blk1 <- new_head_block()
@@ -197,7 +190,6 @@ test_that("head blocks", {
})
test_that("summarize block", {
-
data <- datasets::iris
blk1 <- new_summarize_block()
@@ -225,7 +217,6 @@ test_that("summarize block", {
test_that("upload block", {
-
blk1 <- new_upload_block()
expect_s3_class(blk1, "data_block")
@@ -252,7 +243,6 @@ test_that("upload block", {
})
test_that("filesbrowser block", {
-
blk1 <- new_filesbrowser_block()
expect_s3_class(blk1, "data_block")
@@ -279,7 +269,6 @@ test_that("filesbrowser block", {
})
test_that("csv parser block", {
-
data <- datasets::iris
path <- withr::local_tempfile()
@@ -298,7 +287,6 @@ test_that("csv parser block", {
})
test_that("json parser block", {
-
data <- datasets::iris
path <- withr::local_tempfile()
@@ -317,7 +305,6 @@ test_that("json parser block", {
})
test_that("rds parser block", {
-
data <- datasets::iris
path <- withr::local_tempfile()
@@ -336,7 +323,6 @@ test_that("rds parser block", {
})
test_that("xpt parser block", {
-
data <- datasets::iris
colnames(data) <- gsub("\\.", "_", colnames(data))
@@ -366,7 +352,6 @@ test_that("block title", {
})
test_that("blocks can be constructed with default args", {
-
for (block in available_blocks()) {
expect_s3_class(do.call(block, list()), "block")
}
@@ -391,13 +376,14 @@ test_that("submit works", {
})
test_that("blocks can be updated", {
-
block_test_server <- function(id, x, dat = NULL, ...) {
if (is.null(dat)) {
generate_server(x = x, id = id, ...)
} else {
- generate_server(x = x, in_dat = shiny::reactive(dat), id = id,
- is_prev_valid = shiny::reactive(TRUE), ...)
+ generate_server(
+ x = x, in_dat = shiny::reactive(dat), id = id,
+ is_prev_valid = shiny::reactive(TRUE), ...
+ )
}
}
@@ -588,3 +574,71 @@ test_that("block demo works", {
output = blocks_outputs
)
})
+
+test_that("submit e2e", {
+ skip_on_cran()
+ skip_on_covr()
+
+ stack <- new_stack(
+ block_1 = new_dataset_block("anscombe"),
+ block_2 = new_filter_block(columns = "x1", values = 10, filter_fun = ">")
+ )
+
+ blocks_app <- serve_stack(stack)
+
+ app <- AppDriver$new(
+ blocks_app,
+ name = "block-submit-app"
+ )
+
+ app$click(selector = ".stack-edit-toggle")
+
+ app$expect_values(
+ # Button should be 0
+ input = "my_stack-block_2-submit",
+ # res should not be computed
+ output = "my_stack-block_2-res",
+ screenshot_args = FALSE
+ )
+
+ # Submit
+ app$click(selector = "#my_stack-block_2-submit")
+
+ app$expect_values(
+ # Button should be 1
+ input = "my_stack-block_2-submit",
+ # res should be computed
+ output = "my_stack-block_2-res",
+ screenshot_args = FALSE
+ )
+
+ # Submit is disabled if block is invalid
+ app$set_inputs("my_stack-block_2-filter_func" = "")
+ submit_btn <- app$get_html(selector = "#my_stack-block_2-submit")
+ expect_true(grepl("disabled", submit_btn))
+
+ app$stop()
+
+ # Autoclick on submit
+ stack <- new_stack(
+ block_1 = new_dataset_block("anscombe"),
+ block_2 = new_filter_block(columns = "x1", values = 10, filter_fun = ">", submit = TRUE)
+ )
+
+ blocks_app <- serve_stack(stack)
+
+ app <- AppDriver$new(
+ blocks_app,
+ name = "block-autosubmit-app"
+ )
+
+ app$click(selector = ".stack-edit-toggle")
+
+ app$expect_values(
+ # Button should be 1
+ input = "my_stack-block_2-submit",
+ # res should be computed
+ output = "my_stack-block_2-res",
+ screenshot_args = FALSE
+ )
+})
| |