Skip to content

Commit 389c96f

Browse files
authored
Merge branch '503-introduce-shinytest2@main' into session-info@503-introduce-shinytest2@main
2 parents f5ade8e + 66dd0b9 commit 389c96f

18 files changed

+193
-352
lines changed

.github/workflows/check.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,9 @@ on:
1010
- ready_for_review
1111
branches:
1212
- main
13-
- 503-introduce-shinytest2@main
1413
push:
1514
branches:
1615
- main
17-
- 503-introduce-shinytest2@main
1816
workflow_dispatch:
1917

2018
jobs:

DESCRIPTION

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
Type: Package
22
Package: teal
33
Title: Exploratory Web Apps for Analyzing Clinical Trials Data
4-
Version: 0.15.2.9003
5-
Date: 2024-03-12
4+
Version: 0.15.2.9004
5+
Date: 2024-03-18
66
Authors@R: c(
77
person("Dawid", "Kaledkowski", , "dawid.kaledkowski@roche.com", role = c("aut", "cre"),
88
comment = c(ORCID = "0000-0001-9533-457X")),

NEWS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# teal 0.15.2.9003
1+
# teal 0.15.2.9004
22

33
# teal 0.15.2
44

R/TealAppDriver.R

Lines changed: 44 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@
22

33
#' Drive a `teal` application
44
#'
5-
#' This class inherits the `shinytest2::AppDriver` class and has additional
6-
#' helper functions to help in driving a `teal` application for performing interactions
7-
#' on a `teal` application for implementing `shinytest2` tests.
5+
#' Extension of the `shinytest2::AppDriver` class with methods for
6+
#' driving a teal application for performing interactions for `shinytest2` tests.
87
#'
98
#' @keywords internal
109
#'
11-
TealAppDriver <- R6::R6Class( # nolint
10+
TealAppDriver <- R6::R6Class( # nolint: object_name.
1211
"TealAppDriver",
1312
inherit = shinytest2::AppDriver,
1413
# public methods ----
@@ -103,6 +102,7 @@ TealAppDriver <- R6::R6Class( # nolint
103102
#'
104103
#' @return The `TealAppDriver` object invisibly.
105104
navigate_teal_tab = function(tabs) {
105+
checkmate::check_character(tabs, min.len = 1)
106106
for (tab in tabs) {
107107
root <- "root"
108108
self$set_input(
@@ -137,53 +137,24 @@ TealAppDriver <- R6::R6Class( # nolint
137137
private$ns$module
138138
},
139139
#' @description
140-
#' Get the active shiny name space for interacting with the filter panel.
140+
#' Get the active shiny name space bound with a custom `element` name.
141141
#'
142-
#' @return (`string`) The active shiny name space of the component.
143-
active_filters_ns = function() {
144-
if (identical(private$ns$filter_panel, character(0))) {
145-
private$set_active_ns()
146-
}
147-
private$ns$filter_panel
142+
#' @param element `character(1)` custom element name.
143+
#'
144+
#' @return (`string`) The active shiny name space of the component bound with the input `element`.
145+
active_module_element = function(element) {
146+
checkmate::assert_string(element)
147+
sprintf("#%s-%s", self$active_module_ns(), element)
148148
},
149149
#' @description
150150
#' Get the active shiny name space for interacting with the filter panel.
151151
#'
152152
#' @return (`string`) The active shiny name space of the component.
153-
filter_manager_ns = function() {
154-
if (identical(private$ns$filter_manager, character(0))) {
153+
active_filters_ns = function() {
154+
if (identical(private$ns$filter_panel, character(0))) {
155155
private$set_active_ns()
156156
}
157-
private$ns$filter_manager
158-
},
159-
#' @description
160-
#' Advance utility to help in creating namespace and CSS selectors for Shiny UI.
161-
#' It is similar with [shiny::NS()] by returning a function that can be used
162-
#' to create a namespace for the shiny UI.
163-
#'
164-
#' This namespace can be enriched with a prefix and suffix to create a CSS selector.
165-
#'
166-
#' @param namespace (`character(1)`) The base id to be used for the namespace.
167-
#' @param ... (`character`) The additional ids to be appended to `namespace`.
168-
#'
169-
#' @return A function similar to [shiny::NS()] that is used to create a `character`
170-
#' namespace for the shiny UI.
171-
#'
172-
helper_NS = function(namespace, ...) { # nolint: object_name.
173-
dots <- rlang::list2(...)
174-
checkmate::assert_list(dots, types = "character")
175-
base_id <- namespace
176-
if (length(dots) > 0) base_id <- paste(c(namespace, dots), collapse = shiny::ns.sep)
177-
178-
function(..., .css_prefix = "", .css_suffix = "") {
179-
dots <- rlang::list2(...)
180-
checkmate::assert_list(dots, types = "character")
181-
base_string <- sprintf("%s%s%s", .css_prefix, base_id, .css_suffix)
182-
if (length(dots) == 0) {
183-
return(base_string)
184-
}
185-
(shiny::NS(base_string))(paste(dots, collapse = shiny::ns.sep))
186-
}
157+
private$ns$filter_panel
187158
},
188159
#' @description
189160
#' Get the input from the module in the `teal` app.
@@ -193,6 +164,7 @@ TealAppDriver <- R6::R6Class( # nolint
193164
#'
194165
#' @return The value of the shiny input.
195166
get_active_module_input = function(input_id) {
167+
checkmate::check_string(input_id)
196168
self$get_value(input = sprintf("%s-%s", self$active_module_ns(), input_id))
197169
},
198170
#' @description
@@ -203,6 +175,7 @@ TealAppDriver <- R6::R6Class( # nolint
203175
#'
204176
#' @return The value of the shiny output.
205177
get_active_module_output = function(output_id) {
178+
checkmate::check_string(output_id)
206179
self$get_value(output = sprintf("%s-%s", self$active_module_ns(), output_id))
207180
},
208181
#' @description
@@ -214,6 +187,8 @@ TealAppDriver <- R6::R6Class( # nolint
214187
#'
215188
#' @return The `TealAppDriver` object invisibly.
216189
set_module_input = function(input_id, value) {
190+
checkmate::check_string(input_id)
191+
checkmate::check_string(value)
217192
self$set_input(
218193
sprintf("%s-%s", self$active_module_ns(), input_id),
219194
value
@@ -223,24 +198,14 @@ TealAppDriver <- R6::R6Class( # nolint
223198
#' @description
224199
#' Get the active datasets that can be accessed via the filter panel of the current active teal module.
225200
get_active_filter_vars = function() {
226-
displayed_datasets_index <- vapply(
227-
self$get_html(
228-
sprintf(
229-
"#%s-active-filter_active_vars_contents > span",
230-
self$active_filters_ns()
231-
)
232-
),
233-
function(x) {
234-
style <- x %>%
235-
rvest::read_html() %>%
236-
rvest::html_element("span") %>%
237-
rvest::html_attr("style")
238-
style <- ifelse(is.na(style), "", style)
239-
style != "display: none;"
240-
},
241-
logical(1),
242-
USE.NAMES = FALSE
243-
)
201+
displayed_datasets_index <- self$get_js(
202+
sprintf(
203+
"Array.from(
204+
document.querySelectorAll(\"#%s-active-filter_active_vars_contents > span\")
205+
).map((el) => window.getComputedStyle(el).display != \"none\");",
206+
self$active_filters_ns()
207+
)
208+
) |> unlist()
244209

245210
available_datasets <- self$get_text(
246211
sprintf(
@@ -256,6 +221,7 @@ TealAppDriver <- R6::R6Class( # nolint
256221
#' @param dataset_name (character) The name of the dataset to get the filter variables from.
257222
#' If `NULL`, the filter variables for all the datasets will be returned in a list.
258223
get_active_data_filters = function(dataset_name = NULL) {
224+
checkmate::check_string(dataset_name, null.ok = TRUE)
259225
datasets <- self$get_active_filter_vars()
260226
checkmate::assert_subset(dataset_name, datasets)
261227
active_filters <- lapply(
@@ -286,6 +252,9 @@ TealAppDriver <- R6::R6Class( # nolint
286252
#'
287253
#' @return The value of the active filter selection.
288254
get_active_filter_selection = function(dataset_name, var_name, is_numeric = FALSE) {
255+
checkmate::check_string(dataset_name)
256+
checkmate::check_string(var_name)
257+
checkmate::check_flag(is_numeric)
289258
selection_suffix <- ifelse(is_numeric, "selection_manual", "selection")
290259
self$get_value(
291260
input = sprintf(
@@ -306,6 +275,8 @@ TealAppDriver <- R6::R6Class( # nolint
306275
#'
307276
#' @return The `TealAppDriver` object invisibly.
308277
add_filter_var = function(dataset_name, var_name) {
278+
checkmate::check_string(dataset_name)
279+
checkmate::check_string(var_name)
309280
self$set_input(
310281
sprintf(
311282
"%s-add-%s-filter-var_to_add",
@@ -326,6 +297,8 @@ TealAppDriver <- R6::R6Class( # nolint
326297
#'
327298
#' @return The `TealAppDriver` object invisibly.
328299
remove_filter_var = function(dataset_name = NULL, var_name = NULL) {
300+
checkmate::check_string(dataset_name, null.ok = TRUE)
301+
checkmate::check_string(var_name, null.ok = TRUE)
329302
if (is.null(dataset_name)) {
330303
remove_selector <- sprintf(
331304
"#%s-active-remove_all_filters",
@@ -361,6 +334,11 @@ TealAppDriver <- R6::R6Class( # nolint
361334
#'
362335
#' @return The `TealAppDriver` object invisibly.
363336
set_active_filter_selection = function(dataset_name, var_name, input, is_numeric = FALSE) {
337+
checkmate::check_string(dataset_name)
338+
checkmate::check_string(var_name)
339+
checkmate::check_string(input)
340+
checkmate::check_flag(is_numeric)
341+
364342
selection_suffix <- ifelse(is_numeric, "selection_manual", "selection")
365343
self$set_input(
366344
sprintf(
@@ -376,16 +354,11 @@ TealAppDriver <- R6::R6Class( # nolint
376354
invisible(self)
377355
},
378356
#' @description
379-
#' Click on the filter manager show button.
357+
#' Wrapper around `get_url()` method that opens the app in the browser.
380358
#'
381-
#' @return The `TealAppDriver` object invisibly.
382-
open_filter_manager = function() {
383-
active_ns <- self$filter_manager_ns()
384-
ns <- self$helper_NS(active_ns)
385-
386-
self$click(ns("show"))
387-
self$wait_for_idle(500)
388-
invisible(self)
359+
#' @return Nothing. Opens the underlying teal app in the browser.
360+
open_url = function() {
361+
browseURL(self$get_url())
389362
}
390363
),
391364
# private members ----
@@ -396,8 +369,7 @@ TealAppDriver <- R6::R6Class( # nolint
396369
filter = teal_slices(),
397370
ns = list(
398371
module = character(0),
399-
filter_panel = character(0),
400-
filter_manager = character(0)
372+
filter_panel = character(0)
401373
),
402374
idle_timeout = 20000, # 20 seconds
403375
load_timeout = 100000, # 100 seconds
@@ -431,13 +403,6 @@ TealAppDriver <- R6::R6Class( # nolint
431403
} else {
432404
private$ns[[component]] <- sprintf("%s-module_%s", active_ns, component)
433405
}
434-
435-
component <- "filter_manager"
436-
if (!is.null(self$get_html(sprintf("#teal-main_ui-%s-show", component)))) {
437-
private$ns[[component]] <- sprintf("teal-main_ui-%s", component)
438-
} else {
439-
private$ns[[component]] <- sprintf("%s-module_%s", active_ns, component)
440-
}
441406
}
442407
)
443408
)

R/init.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@
3131
#' The header of the app.
3232
#' @param footer (`shiny.tag` or `character(1)`)
3333
#' The footer of the app.
34-
#' @param id (`character`)
35-
#' Optional string specifying the `shiny` module id in cases it is used as a `shiny` module
34+
#' @param id (`character`) optional
35+
#' string specifying the `shiny` module id in cases it is used as a `shiny` module
3636
#' rather than a standalone `shiny` app. This is a legacy feature.
3737
#'
3838
#' @return Named list with server and UI functions.

R/modules.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ is_arg_used <- function(modules, arg) {
395395
#' Nesting it increases overall depth by 1.
396396
#'
397397
#' @inheritParams init
398-
#' @param depth optional, integer determining current depth level
398+
#' @param depth optional integer determining current depth level
399399
#'
400400
#' @return Depth level for given module.
401401
#' @keywords internal

R/show_rcode_modal.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
#' Title of the modal, displayed in the first comment of the `R` code.
99
#' @param rcode (`character`)
1010
#' vector with `R` code to show inside the modal.
11-
#' @param session (`ShinySession` optional)
12-
#' `shiny` session object, if missing then [shiny::getDefaultReactiveDomain()] is used.
11+
#' @param session (`ShinySession`) optional
12+
#' `shiny` session object, defaults to [shiny::getDefaultReactiveDomain()].
1313
#'
1414
#' @references [shiny::showModal()]
1515
#' @export

R/teal_slices.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#'
1010
#' @inheritParams teal.slice::teal_slices
1111
#'
12-
#' @param module_specific optional (`logical(1)`)
12+
#' @param module_specific (`logical(1)`) optional,
1313
#' - `FALSE` (default) when one filter panel applied to all modules.
1414
#' All filters will be shared by all modules.
1515
#' - `TRUE` when filter panel module-specific.

R/utils.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ teal_data_to_filtered_data <- function(x, datanames = teal_data_datanames(x)) {
8080
#'
8181
#' @param title (`character(1)`) title of the card (unless overwritten by label)
8282
#' @param label (`character(1)`) label provided by the user when adding the card
83-
#' @param description (`character(1)`) optional additional description
83+
#' @param description (`character(1)`) optional, additional description
8484
#' @param with_filter (`logical(1)`) flag indicating to add filter state
8585
#' @param filter_panel_api (`FilterPanelAPI`) object with API that allows the generation
8686
#' of the filter state in the report

0 commit comments

Comments
 (0)