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)
0 commit comments