diff --git a/NAMESPACE b/NAMESPACE index 209b1855..70ee196e 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -29,10 +29,6 @@ S3method(resolve,delayed_variable_choices) S3method(resolve,list) S3method(resolve_delayed,FilteredData) S3method(resolve_delayed,list) -S3method(value_choices,character) -S3method(value_choices,data.frame) -S3method(variable_choices,character) -S3method(variable_choices,data.frame) export("%>%") export(add_no_selected_choices) export(all_choices) @@ -63,6 +59,7 @@ export(merge_datasets) export(merge_expression_module) export(merge_expression_srv) export(no_selected_as_NULL) +export(nth_choice) export(resolve_delayed) export(select_spec) export(select_spec.default) diff --git a/NEWS.md b/NEWS.md index 0893897f..081738a8 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,10 @@ # teal.transform 0.6.0.9000 +### Enhancements + +* Introduced defaults to all `data_extract_spec()` components to simplify the user experience. It is now possible to just call `data_extract_spec()` which will provide necessary information for `data_extract_srv()` and `data_extract_multiple_srv()` to initialize inputs for all provided datasets. +* Introduced utility function `nth_choice(n)`. + # teal.transform 0.6.0 ### Enhancements diff --git a/R/choices_labeled.R b/R/choices_labeled.R index 0b307cd6..8684aa94 100644 --- a/R/choices_labeled.R +++ b/R/choices_labeled.R @@ -131,7 +131,8 @@ choices_labeled <- function(choices, labels, subset = NULL, types = NULL) { #' #' @param data (`data.frame` or `character`) #' If `data.frame`, then data to extract labels from. -#' If `character`, then name of the dataset to extract data from once available. +#' If `character`, then name of the dataset to extract data from once available. Keyword `"all"` +#' (default) indicates that `data` will be inherited from the `data_extract_spec` `dataname`. #' @param subset (`character` or `function`) #' If `character`, then a vector of column names. #' If `function`, then this function is used to determine the possible columns (e.g. all factor columns). @@ -161,7 +162,10 @@ choices_labeled <- function(choices, labels, subset = NULL, types = NULL) { #' key = default_cdisc_join_keys["ADRS", "ADRS"] #' ) #' -#' # delayed version +#' # delayed version with unknown dataset +#' variable_choices() +#' +#' # delayed ADRS #' variable_choices("ADRS", subset = c("USUBJID", "STUDYID")) #' #' # functional subset (with delayed data) - return only factor variables @@ -171,35 +175,48 @@ choices_labeled <- function(choices, labels, subset = NULL, types = NULL) { #' }) #' @export #' -variable_choices <- function(data, subset = NULL, fill = FALSE, key = NULL) { +variable_choices <- function(data = "all", subset = function(data) names(data), fill = FALSE, key = NULL) { checkmate::assert( checkmate::check_character(subset, null.ok = TRUE, any.missing = FALSE), - checkmate::check_function(subset) + checkmate::check_function(subset, args = "data") ) checkmate::assert_flag(fill) checkmate::assert_character(key, null.ok = TRUE, any.missing = FALSE) - - UseMethod("variable_choices") + if (is.character(data)) { + variable_choices_delayed(data = data, subset = subset, fill = fill, key = key) + } else { + variable_choices_data_frame(data = data, subset = subset, fill = fill, key = key) + } } -#' @rdname variable_choices -#' @export -variable_choices.character <- function(data, subset = NULL, fill = FALSE, key = NULL) { +#' @keywords internal +variable_choices_delayed <- function(data, subset = function(data) names(data), fill = FALSE, key = NULL) { + checkmate::assert_string(data) structure(list(data = data, subset = subset, key = key), class = c("delayed_variable_choices", "delayed_data", "choices_labeled") ) } -#' @rdname variable_choices -#' @export -variable_choices.data.frame <- function(data, subset = NULL, fill = TRUE, key = NULL) { +#' @keywords internal +variable_choices_data_frame <- function(data, subset = function(data) names(data), fill = TRUE, key = NULL) { + checkmate::assert_data_frame(data, min.cols = 1) checkmate::assert( checkmate::check_character(subset, null.ok = TRUE), checkmate::check_function(subset, null.ok = TRUE) ) if (is.function(subset)) { - subset <- resolve_delayed_expr(subset, ds = data, is_value_choices = FALSE) + subset <- subset(data) + if ( + !checkmate::test_character(subset, any.missing = FALSE) || + length(subset) > ncol(data) || + anyDuplicated(subset) + ) { + stop( + "variable_choices(subset) function in must return a character vector with unique", + "names from the available columns of the dataset" + ) + } } checkmate::assert_subset(subset, c("", names(data)), empty.ok = TRUE) @@ -283,8 +300,8 @@ variable_choices.data.frame <- function(data, subset = NULL, fill = TRUE, key = #' }) #' @export #' -value_choices <- function(data, - var_choices, +value_choices <- function(data = "all", + var_choices = variable_choices(data = data), var_label = NULL, subset = NULL, sep = " - ") { @@ -298,16 +315,21 @@ value_choices <- function(data, checkmate::check_function(subset) ) checkmate::assert_string(sep) - UseMethod("value_choices") + + if (is.character(data)) { + value_choices_delayed(data = data, var_choices = var_choices, var_label = var_label, subset = subset, sep = sep) + } else { + value_choices_data_frame(data = data, var_choices = var_choices, var_label = var_label, subset = subset, sep = sep) + } } -#' @rdname value_choices -#' @export -value_choices.character <- function(data, - var_choices, - var_label = NULL, - subset = NULL, - sep = " - ") { +#' @keywords internal +value_choices_delayed <- function(data, + var_choices, + var_label = NULL, + subset = NULL, + sep = " - ") { + checkmate::assert_string(data, null.ok = TRUE) structure( list( data = data, @@ -320,13 +342,13 @@ value_choices.character <- function(data, ) } -#' @rdname value_choices -#' @export -value_choices.data.frame <- function(data, +#' @keywords internal +value_choices_data_frame <- function(data, var_choices, var_label = NULL, subset = NULL, sep = " - ") { + checkmate::assert_data_frame(data, min.cols = 1) checkmate::assert_subset(var_choices, names(data)) checkmate::assert_subset(var_label, names(data), empty.ok = TRUE) @@ -369,7 +391,13 @@ value_choices.data.frame <- function(data, df <- unique(data.frame(choices, labels, stringsAsFactors = FALSE)) # unique combo of choices x labels if (is.function(subset)) { - subset <- resolve_delayed_expr(subset, ds = data, is_value_choices = TRUE) + subset <- subset(data) + if (!checkmate::test_atomic(subset) || anyDuplicated(subset)) { + stop( + "value_choices(subset) function must return a vector with unique values from the ", + "respective columns of the dataset." + ) + } } res <- choices_labeled( choices = df$choices, diff --git a/R/choices_selected.R b/R/choices_selected.R index a12a5d3c..1cf0f5bd 100644 --- a/R/choices_selected.R +++ b/R/choices_selected.R @@ -131,7 +131,7 @@ no_select_keyword <- "-- no selection --" #' @export #' choices_selected <- function(choices, - selected = if (inherits(choices, "delayed_data")) NULL else choices[1], + selected = first_choice(), keep_order = FALSE, fixed = FALSE) { checkmate::assert( @@ -141,6 +141,8 @@ choices_selected <- function(choices, checkmate::assert( checkmate::check_atomic(selected), checkmate::check_multi_class(selected, c("delayed_data", "delayed_choices")) + # todo: only delayed_choices should be possible for delayed, otherwise it might cause different + # delayed output for choices and selected (for example two independent variable_choices) ) checkmate::assert_flag(keep_order) checkmate::assert_flag(fixed) diff --git a/R/data_extract_datanames.R b/R/data_extract_datanames.R index 7437cb3b..ebb43efe 100644 --- a/R/data_extract_datanames.R +++ b/R/data_extract_datanames.R @@ -53,15 +53,22 @@ get_extract_datanames <- function(data_extracts) { all(vapply(data_extracts, function(x) checkmate::test_list(x, types = "data_extract_spec"), logical(1))) ) - datanames <- lapply(data_extracts, function(x) { - if (inherits(x, "data_extract_spec")) { - x[["dataname"]] - } else if (checkmate::test_list(x, types = "data_extract_spec")) { - lapply(x, `[[`, "dataname") - } - }) + datanames <- unlist( + lapply(data_extracts, function(x) { + if (inherits(x, "data_extract_spec")) { + x[["dataname"]] + } else if (checkmate::test_list(x, types = "data_extract_spec")) { + lapply(x, `[[`, "dataname") + } + }), + use.names = FALSE + ) - unique(unlist(datanames)) + if (any(datanames == "all")) { + "all" + } else { + unique(datanames) + } } #' Verify uniform dataset source across data extract specification @@ -82,5 +89,5 @@ get_extract_datanames <- function(data_extracts) { is_single_dataset <- function(...) { data_extract_spec <- list(...) dataset_names <- get_extract_datanames(data_extract_spec) - length(dataset_names) == 1 + length(dataset_names) == 1L && dataset_names != "all" } diff --git a/R/data_extract_module.R b/R/data_extract_module.R index f541de50..fb85cb3d 100644 --- a/R/data_extract_module.R +++ b/R/data_extract_module.R @@ -124,74 +124,14 @@ cond_data_extract_single_ui <- function(ns, single_data_extract_spec) { data_extract_ui <- function(id, label, data_extract_spec, is_single_dataset = FALSE) { ns <- NS(id) - if (inherits(data_extract_spec, "data_extract_spec")) { - data_extract_spec <- list(data_extract_spec) - } - check_data_extract_spec(data_extract_spec) - - if (is.null(data_extract_spec)) { - return(helpText(sprintf("Data extraction with label '%s' is NULL. Please contact the app author.", label))) - } - stopifnot( - `more than one dataset in data_extract_spec but is_single_dataset parameter is set to TRUE` = - !is_single_dataset || length(data_extract_spec) == 1 - ) - - dataset_names <- vapply( - data_extract_spec, - function(x) x$dataname, - character(1), - USE.NAMES = FALSE - ) - - stopifnot(`list contains data_extract_spec objects with the same dataset` = all(!duplicated(dataset_names))) - - dataset_input <- if (is_single_dataset) { - NULL - } else { - if (length(dataset_names) == 1) { - if ((is.null(data_extract_spec[[1]]$filter)) && - ( - !is.null(data_extract_spec[[1]]$select$fixed) && - data_extract_spec[[1]]$select$fixed == TRUE - )) { - NULL - } else { - helpText("Dataset:", tags$code(dataset_names)) - } - } else { - teal.widgets::optionalSelectInput( - inputId = ns("dataset"), - label = "Dataset", - choices = dataset_names, - selected = dataset_names[1], - multiple = FALSE - ) - } - } tagList( - include_css_files(pattern = "data_extract"), - tags$div( - class = "data-extract", - tags$label(label), - dataset_input, - if (length(dataset_names) == 1) { - data_extract_single_ui( - id = ns(id_for_dataset(dataset_names)), - single_data_extract_spec = data_extract_spec[[1]] - ) - } else { - do.call( - div, - unname(lapply( - data_extract_spec, - function(x) { - cond_data_extract_single_ui(ns, x) - } - )) - ) - } - ) + # Pass arguments to server function. + div( + checkboxInput(ns("is_single_dataset"), label = NULL, value = is_single_dataset), + textInput(ns("data_extract_label"), label = NULL, value = label), + style = "display: none;" + ), + uiOutput(ns("data_extract_ui_container")) ) } @@ -410,7 +350,7 @@ data_extract_srv.FilteredData <- function(id, datasets, data_extract_spec, ...) id, function(input, output, session) { logger::log_debug( - "data_extract_srv.FilteredData initialized with datasets: { paste(datasets$datanames(), collapse = ', ') }." + "data_extract_srv.FilteredData initialized with datasets: { toString(datasets$datanames()) }." ) data_list <- sapply(X = datasets$datanames(), simplify = FALSE, FUN = function(x) { @@ -451,7 +391,7 @@ data_extract_srv.FilteredData <- function(id, datasets, data_extract_spec, ...) data_extract_srv.list <- function(id, datasets, data_extract_spec, - join_keys = NULL, + join_keys = teal.data::join_keys(), select_validation_rule = NULL, filter_validation_rule = NULL, dataset_validation_rule = if ( @@ -472,16 +412,11 @@ data_extract_srv.list <- function(id, moduleServer( id, function(input, output, session) { - logger::log_debug( - "data_extract_srv.list initialized with datasets: { paste(names(datasets), collapse = ', ') }." - ) + logger::log_debug("data_extract_srv.list initialized with datasets: { toString(names(datasets)) }.") - # get keys out of join_keys - if (length(join_keys)) { - keys <- sapply(names(datasets), simplify = FALSE, function(x) join_keys[x, x]) - } else { - keys <- sapply(names(datasets), simplify = FALSE, function(x) character(0)) - } + data_extract_spec <- shiny::isolate( + resolve_delayed(x = data_extract_spec, datasets = datasets, join_keys = join_keys) + ) # convert to list of reactives datasets <- sapply(X = datasets, simplify = FALSE, FUN = function(x) { @@ -502,6 +437,11 @@ data_extract_srv.list <- function(id, return(reactive(NULL)) } check_data_extract_spec(data_extract_spec = data_extract_spec) + datanames <- vapply(data_extract_spec, function(x) x$dataname, character(1), USE.NAMES = FALSE) + if (anyDuplicated(datanames)) { + stop("list contains data_extract_spec objects with the same dataset") + } + names(data_extract_spec) <- datanames # so the lapply/sapply results are named # Each dataset needs its own shinyvalidate to make sure only the # currently visible d-e-s's validation is used @@ -512,7 +452,6 @@ data_extract_srv.list <- function(id, } iv_dataset }) - names(iv) <- lapply(data_extract_spec, `[[`, "dataname") # also need a final iv for the case where no dataset is selected iv[["blank_dataset_case"]] <- shinyvalidate::InputValidator$new() @@ -536,7 +475,6 @@ data_extract_srv.list <- function(id, filter_validation_rule = filter_validation_rule ) }) - names(filter_and_select) <- sapply(data_extract_spec, function(x) x$dataname) dataname <- reactive({ # For fixed data sets, ignore input_value @@ -557,11 +495,78 @@ data_extract_srv.list <- function(id, list( dataname = dataname(), internal_id = gsub("^.*-(.+)$", "\\1", session$ns(NULL)), # parent module id - keys = keys[[dataname()]] + keys = as.character(join_keys[dataname(), dataname()]) # to convert NULL to character(0) ) ) } }) + + + output$data_extract_ui_container <- renderUI({ + ns <- session$ns + + logger::log_debug("initializing data_extract_ui w/ datasets: { toString(names(datasets)) }.") + + if (is.null(data_extract_spec)) { + return(helpText( + sprintf("Data extraction with label '%s' is NULL. Please contact the app author.", input$label) + )) + } + + stopifnot( + `more than one dataset in data_extract_spec but is_single_dataset parameter is set to TRUE` = + isFALSE(input$is_single_dataset) || length(data_extract_spec) == 1 + ) + + dataset_input <- + if (isTRUE(input$is_single_dataset)) { + NULL + } else { + if (length(data_extract_spec) == 1) { + if ((is.null(data_extract_spec[[1]]$filter)) && + ( + !is.null(data_extract_spec[[1]]$select$fixed) && + data_extract_spec[[1]]$select$fixed == TRUE + )) { + NULL + } else { + helpText("Dataset:", tags$code(names(data_extract_spec))) + } + } else { + teal.widgets::optionalSelectInput( + inputId = ns("dataset"), + label = "Dataset", + choices = names(data_extract_spec), + selected = names(data_extract_spec)[1], + multiple = FALSE + ) + } + } + tagList( + include_css_files(pattern = "data_extract"), + tags$div( + class = "data-extract", + tags$label(input$data_extract_label), + dataset_input, + if (length(data_extract_spec) == 1) { + data_extract_single_ui( + id = ns(id_for_dataset(names(data_extract_spec))), + single_data_extract_spec = data_extract_spec[[1]] + ) + } else { + do.call( + div, + unname(lapply( + data_extract_spec, + function(x) { + cond_data_extract_single_ui(ns, x) + } + )) + ) + } + ) + ) + }) filter_and_select_reactive } ) @@ -697,14 +702,14 @@ data_extract_multiple_srv.reactive <- function(data_extract, datasets, ...) { data_extract_multiple_srv.FilteredData <- function(data_extract, datasets, ...) { checkmate::assert_class(datasets, classes = "FilteredData") logger::log_debug( - "data_extract_multiple_srv.filteredData initialized with dataset: { paste(datasets$datanames(), collapse = ', ') }." + "data_extract_multiple_srv.FilteredData initialized w/ datasets: { toString(datasets$datanames()) }." ) data_list <- sapply(X = datasets$datanames(), simplify = FALSE, FUN = function(x) { reactive(datasets$get_data(dataname = x, filtered = TRUE)) }) - join_keys <- datasets$get_join_keys() + data_extract_multiple_srv(data_extract = data_extract, datasets = data_list, join_keys = join_keys) } @@ -732,7 +737,7 @@ data_extract_multiple_srv.FilteredData <- function(data_extract, datasets, ...) #' data_extract_multiple_srv.list <- function(data_extract, datasets, - join_keys = NULL, + join_keys = teal.data::join_keys(), select_validation_rule = NULL, filter_validation_rule = NULL, dataset_validation_rule = if ( @@ -758,38 +763,35 @@ data_extract_multiple_srv.list <- function(data_extract, checkmate::check_multi_class(dataset_validation_rule, classes = c("function", "formula"), null.ok = TRUE), checkmate::check_list(dataset_validation_rule, types = c("function", "formula", "NULL"), null.ok = TRUE) ) - - logger::log_debug( - "data_extract_multiple_srv.list initialized with dataset: { paste(names(datasets), collapse = ', ') }." - ) - - data_extract <- Filter(Negate(is.null), data_extract) - - if (is.function(select_validation_rule)) { - select_validation_rule <- sapply( - names(data_extract), - simplify = FALSE, - USE.NAMES = TRUE, - function(x) select_validation_rule - ) - } - - if (is.function(dataset_validation_rule)) { - dataset_validation_rule <- sapply( - names(data_extract), - simplify = FALSE, - USE.NAMES = TRUE, - function(x) dataset_validation_rule - ) - } + logger::log_debug("data_extract_multiple_srv.list initialized with dataset: { toString(names(datasets)) }.") reactive({ + data_extract <- Filter(Negate(is.null), data_extract) + data_extract <- resolve_delayed(x = data_extract, datasets = datasets, join_keys = join_keys) + + if (is.function(select_validation_rule)) { + select_validation_rule <- sapply( + names(data_extract), + simplify = FALSE, + USE.NAMES = TRUE, + function(x) select_validation_rule + ) + } + + if (is.function(dataset_validation_rule)) { + dataset_validation_rule <- sapply( + names(data_extract), + simplify = FALSE, + USE.NAMES = TRUE, + function(x) dataset_validation_rule + ) + } sapply( X = names(data_extract), simplify = FALSE, USE.NAMES = TRUE, function(x) { - data_extract_srv( + data_extract_srv( # todo: Come on! Module shouldn't be called in a reactive. id = x, data_extract_spec = data_extract[[x]], datasets = datasets, diff --git a/R/data_extract_single_module.R b/R/data_extract_single_module.R index d105c885..a946594e 100644 --- a/R/data_extract_single_module.R +++ b/R/data_extract_single_module.R @@ -78,20 +78,17 @@ data_extract_single_srv <- function(id, datasets, single_data_extract_spec) { function(input, output, session) { logger::log_debug("data_extract_single_srv initialized with dataset: { single_data_extract_spec$dataname }.") - # ui could be initialized with a delayed select spec so the choices and selected are NULL - # here delayed are resolved isolate({ - resolved <- resolve_delayed(single_data_extract_spec, datasets) teal.widgets::updateOptionalSelectInput( session = session, inputId = "select", - choices = resolved$select$choices, - selected = resolved$select$selected + choices = single_data_extract_spec$select$choices, + selected = single_data_extract_spec$select$selected ) }) - for (idx in seq_along(resolved$filter)) { - x <- resolved$filter[[idx]] + for (idx in seq_along(single_data_extract_spec$filter)) { + x <- single_data_extract_spec$filter[[idx]] if (inherits(x, "filter_spec")) { data_extract_filter_srv( id = paste0("filter", idx), diff --git a/R/data_extract_spec.R b/R/data_extract_spec.R index 517f2861..0cb8e3b9 100644 --- a/R/data_extract_spec.R +++ b/R/data_extract_spec.R @@ -15,7 +15,8 @@ #' `teal.transform` uses this object to construct a UI element in a module. #' #' @param dataname (`character`) -#' The name of the dataset to be extracted. +#' The name of the dataset to be extracted. Keyword `"all"` suggest that this `data_extract_spec` +#' is universal for all datasets used in `teal` application. #' @param select (`NULL` or `select_spec`-S3 class or `delayed_select_spec`) #' Columns to be selected from the input dataset mentioned in `dataname`. #' The setup can be created using [select_spec] function. @@ -83,7 +84,10 @@ #' ) #' @export #' -data_extract_spec <- function(dataname, select = NULL, filter = NULL, reshape = FALSE) { +data_extract_spec <- function(dataname = "all", + select = select_spec(selected = all_choices()), # todo: remove this default + filter = filter_spec(), # todo: default filter should be NULL + reshape = FALSE) { checkmate::assert_string(dataname) stopifnot( is.null(select) || @@ -96,22 +100,11 @@ data_extract_spec <- function(dataname, select = NULL, filter = NULL, reshape = ) checkmate::assert_flag(reshape) - if (is.null(select) && is.null(filter)) { - select <- select_spec( - choices = variable_choices(dataname), - multiple = TRUE - ) - filter <- filter_spec( - vars = choices_selected(variable_choices(dataname)), - selected = all_choices() - ) - } - if (inherits(filter, "filter_spec")) filter <- list(filter) - for (idx in seq_along(filter)) filter[[idx]]$dataname <- dataname + for (idx in seq_along(filter)) filter[[idx]]$dataname <- dataname # todo: find where it is used - if ( + ans <- if ( inherits(select, "delayed_select_spec") || any(vapply(filter, inherits, logical(1), "delayed_filter_spec")) ) { @@ -125,4 +118,5 @@ data_extract_spec <- function(dataname, select = NULL, filter = NULL, reshape = class = "data_extract_spec" ) } + ans } diff --git a/R/delayed_choices.R b/R/delayed_choices.R index 0ade84bf..c3de135b 100644 --- a/R/delayed_choices.R +++ b/R/delayed_choices.R @@ -6,7 +6,7 @@ #' Special S3 structures that delay selection of possible choices in a #' `filter_spec`, `select_spec` or `choices_selected` object. #' -#' @param n positive (`integer`-like) number of first/last items to subset to +#' @param n positive (`integer`-like) number of first/last/nth item(s) to subset to. #' #' @return #' Object of class `delayed_data, delayed_choices`, which is a function @@ -51,21 +51,34 @@ all_choices <- function() { class(ans) <- c("multiple_choices", class(ans)) ans } +#' @export +#' @rdname delayed_choices +nth_choice <- function(n) { + .delayed_choices(selected_fun = function(x) { + new_n <- min(length(x), n) + if (new_n > 0) { + x[new_n] + } else { + NULL + } + }) +} + #' @export #' @rdname delayed_choices first_choice <- function() { - .delayed_choices(function(x) utils::head(x, 1L)) + .delayed_choices(selected_fun = function(x) utils::head(x, 1L)) } #' @export #' @rdname delayed_choices last_choice <- function() { - .delayed_choices(function(x) utils::tail(x, 1L)) + .delayed_choices(selected_fun = function(x) utils::tail(x, 1L)) } #' @export #' @rdname delayed_choices first_choices <- function(n) { checkmate::assert_count(n, positive = TRUE) - ans <- .delayed_choices(function(x) utils::head(x, n)) + ans <- .delayed_choices(selected_fun = function(x) utils::head(x, n)) class(ans) <- c("multiple_choices", class(ans)) ans } @@ -73,14 +86,14 @@ first_choices <- function(n) { #' @rdname delayed_choices last_choices <- function(n) { checkmate::assert_count(n, positive = TRUE) - ans <- .delayed_choices(function(x) utils::tail(x, n)) + ans <- .delayed_choices(selected_fun = function(x) utils::tail(x, n)) class(ans) <- c("multiple_choices", class(ans)) ans } #' @keywords internal #' @noRd -.delayed_choices <- function(fun) { +.delayed_choices <- function(selected_fun) { structure( function(x) { if (inherits(x, "delayed_choices")) { @@ -88,14 +101,14 @@ last_choices <- function(n) { } else if (length(x) == 0L) { x } else if (is.atomic(x)) { - fun(x) + selected_fun(x) } else if (inherits(x, "delayed_data")) { if (is.null(x$subset)) { return(x) } - original_fun <- x$subset + choices_fun <- x$subset x$subset <- function(data) { - fun(original_fun(data)) + selected_fun(choices_fun(data)) } x } diff --git a/R/filter_spec.R b/R/filter_spec.R index c45e88f4..f47066f9 100644 --- a/R/filter_spec.R +++ b/R/filter_spec.R @@ -107,9 +107,9 @@ #' ) #' @export #' -filter_spec <- function(vars, +filter_spec <- function(vars = choices_selected(choices = variable_choices()), choices = NULL, - selected = `if`(inherits(choices, "delayed_data"), NULL, choices[1]), + selected = first_choice(), multiple = length(selected) > 1 || inherits(selected, "multiple_choices"), label = "Filter by", sep = attr(choices, "sep"), diff --git a/R/get_merge_call.R b/R/get_merge_call.R index 04b1a92c..57627358 100644 --- a/R/get_merge_call.R +++ b/R/get_merge_call.R @@ -386,16 +386,14 @@ get_anl_relabel_call <- function(columns_source, datasets, anl_name = "ANL") { column_labels <- labels[intersect(colnames(data_used()), column_names)] # NULL for no labels at all, character(0) for no labels for a given columns - return( - if (rlang::is_empty(column_labels)) { - column_labels - } else { - stats::setNames( - column_labels, - selector[names(column_labels)] - ) - } - ) + if (rlang::is_empty(column_labels)) { + column_labels + } else { + stats::setNames( + column_labels, + selector[names(column_labels)] + ) + } } ) ) diff --git a/R/resolve.R b/R/resolve.R index c5682b54..f89240aa 100644 --- a/R/resolve.R +++ b/R/resolve.R @@ -7,60 +7,49 @@ #' #' @param x (`delayed_data`) object to resolve. #' @param datasets (named `list` of `data.frame`) to use in evaluation. -#' @param keys (named `list` of `character`) to be used as the keys for each dataset. -#' The names of this list must be exactly the same as for datasets. +#' @param join_keys (`join_keys`) used to resolve `key` in [variable_choices()]. #' #' @return Resolved object. #' #' @keywords internal #' -resolve <- function(x, datasets, keys = NULL) { - checkmate::assert_list(datasets, types = "reactive", min.len = 1, names = "named") - checkmate::assert_list(keys, "character", names = "named", null.ok = TRUE) - checkmate::assert( - .var.name = "keys", - checkmate::check_names(names(keys), subset.of = names(datasets)), - checkmate::check_null(keys) - ) - +resolve <- function(x, datasets, join_keys = teal.data::join_keys()) { + checkmate::assert_list(datasets, min.len = 1, names = "named") + checkmate::assert_class(join_keys, "join_keys") UseMethod("resolve") } #' @describeIn resolve Call [variable_choices()] on the delayed `variable_choices` object. #' @export -resolve.delayed_variable_choices <- function(x, datasets, keys) { +resolve.delayed_variable_choices <- function(x, datasets, join_keys = teal.data::join_keys()) { + checkmate::assert_list(datasets, len = 1, names = "named") + x$data <- datasets[[1]] if (is.null(x$key)) { - x$key <- `if`(is.null(keys), character(), keys[[x$data]]) - } - x$data <- datasets[[x$data]]() - if (inherits(x$subset, "function")) { - x$subset <- resolve_delayed_expr(x$subset, ds = x$data, is_value_choices = FALSE) + dataname <- names(datasets) + x$key <- as.character(join_keys[dataname, dataname]) } - do.call("variable_choices", x) } #' @describeIn resolve Call [value_choices()] on the delayed `value_choices` object. #' @export -resolve.delayed_value_choices <- function(x, datasets, keys) { - x$data <- datasets[[x$data]]() +resolve.delayed_value_choices <- function(x, datasets, join_keys = teal.data::join_keys()) { + checkmate::assert_list(datasets, len = 1, names = "named") + x$data <- datasets[[1]] if (inherits(x$var_choices, "delayed_variable_choices")) { - x$var_choices <- resolve(x$var_choices, datasets, keys) - } - if (is.function(x$subset)) { - x$subset <- resolve_delayed_expr(x$subset, ds = x$data, is_value_choices = TRUE) + x$var_choices <- resolve(x$var_choices, datasets, join_keys = join_keys) } - do.call("value_choices", x) } #' @describeIn resolve Call [select_spec()] on the delayed `choices_selected` object. #' @export -resolve.delayed_choices_selected <- function(x, datasets, keys) { +resolve.delayed_choices_selected <- function(x, datasets, join_keys = teal.data::join_keys()) { + checkmate::assert_list(datasets, len = 1, names = "named") if (inherits(x$selected, "delayed_data")) { - x$selected <- resolve(x$selected, datasets = datasets, keys) + x$selected <- resolve(x$selected, datasets = datasets, join_keys = join_keys) } - x$choices <- resolve(x$choices, datasets = datasets, keys) + x$choices <- resolve(x$choices, datasets = datasets, join_keys = join_keys) if (!all(x$selected %in% x$choices)) { warning(paste( @@ -76,29 +65,30 @@ resolve.delayed_choices_selected <- function(x, datasets, keys) { #' @describeIn resolve Call [select_spec()] on the delayed specification. #' @export -resolve.delayed_select_spec <- function(x, datasets, keys) { - x$choices <- resolve(x$choices, datasets = datasets, keys) +resolve.delayed_select_spec <- function(x, datasets, join_keys = teal.data::join_keys()) { + checkmate::assert_list(datasets, len = 1, names = "named") + x$choices <- resolve(x$choices, datasets = datasets, join_keys = join_keys) if (inherits(x$selected, "delayed_data")) { - x$selected <- resolve(x$selected, datasets = datasets, keys) + x$selected <- resolve(x$selected, datasets = datasets, join_keys = join_keys) } - do.call("select_spec", x) } #' @describeIn resolve Call [filter_spec()] on the delayed specification. #' @export -resolve.delayed_filter_spec <- function(x, datasets, keys) { +resolve.delayed_filter_spec <- function(x, datasets, join_keys = teal.data::join_keys()) { + checkmate::assert_list(datasets, len = 1, names = "named") if (inherits(x$vars_choices, "delayed_data")) { - x$vars_choices <- resolve(x$vars_choices, datasets = datasets, keys) + x$vars_choices <- resolve(x$vars_choices, datasets = datasets, join_keys = join_keys) } if (inherits(x$vars_selected, "delayed_data")) { - x$vars_selected <- resolve(x$vars_selected, datasets = datasets, keys) + x$vars_selected <- resolve(x$vars_selected, datasets = datasets, join_keys = join_keys) } if (inherits(x$choices, "delayed_data")) { - x$choices <- resolve(x$choices, datasets = datasets, keys) + x$choices <- resolve(x$choices, datasets = datasets, join_keys = join_keys) } if (inherits(x$selected, "delayed_data")) { - x$selected <- resolve(x$selected, datasets = datasets, keys) + x$selected <- resolve(x$selected, datasets = datasets, join_keys = join_keys) } do.call("filter_spec_internal", x[intersect(names(x), methods::formalArgs(filter_spec_internal))]) @@ -106,16 +96,17 @@ resolve.delayed_filter_spec <- function(x, datasets, keys) { #' @describeIn resolve Call [data_extract_spec()] on the delayed specification. #' @export -resolve.delayed_data_extract_spec <- function(x, datasets, keys) { +resolve.delayed_data_extract_spec <- function(x, datasets, join_keys = teal.data::join_keys()) { + dataset <- datasets[x$dataname] x$select <- `if`( inherits(x$select, "delayed_data"), - resolve(x$select, datasets = datasets, keys), + resolve(x$select, datasets = dataset, join_keys = join_keys), x$select ) if (any(vapply(x$filter, inherits, logical(1L), "delayed_data"))) { idx <- vapply(x$filter, inherits, logical(1), "delayed_data") - x$filter[idx] <- lapply(x$filter[idx], resolve, datasets = datasets, keys = keys) + x$filter[idx] <- lapply(x$filter[idx], resolve, datasets = dataset, join_keys = join_keys) } do.call("data_extract_spec", x) @@ -124,57 +115,26 @@ resolve.delayed_data_extract_spec <- function(x, datasets, keys) { #' @describeIn resolve Iterates over elements of the list and recursively calls #' `resolve`. #' @export -resolve.list <- function(x, datasets, keys) { +resolve.list <- function(x, datasets, join_keys = teal.data::join_keys()) { + new_x <- if (checkmate::test_list(x, "data_extract_spec", min.len = 1) && identical(x[[1]]$dataname, "all")) { + lapply(seq_along(datasets), function(i) { + xx <- x[[1]] + xx$dataname <- names(datasets)[i] + xx + }) + } else { + x + } # If specified explicitly, return it unchanged. Otherwise if delayed, resolve. - lapply(x, resolve, datasets = datasets, keys = keys) + lapply(new_x, resolve, datasets = datasets, join_keys = join_keys) } #' @describeIn resolve Default method that does nothing and returns `x` itself. #' @export -resolve.default <- function(x, datasets, keys) { +resolve.default <- function(x, datasets, join_keys = teal.data::join_keys()) { x } -#' Resolve expression after delayed data are loaded -#' -#' -#' @param x (`function`) Function that is applied on dataset. -#' It must take only a single argument "data" and return character vector with columns / values. -#' @param ds (`data.frame`) Dataset. -#' @param is_value_choices (`logical`) Determines which check of the returned value will be applied. -#' -#' @return `character` vector - result of calling function `x` on dataset `ds`. -#' -#' @keywords internal -#' -resolve_delayed_expr <- function(x, ds, is_value_choices) { - checkmate::assert_function(x, args = "data", nargs = 1) - - # evaluate function - res <- do.call(x, list(data = ds)) - - # check returned value - if (is_value_choices) { - if (!checkmate::test_atomic(res) || anyDuplicated(res)) { - stop(paste( - "The following function must return a vector with unique values", - "from the respective columns of the dataset.\n\n", - deparse1(bquote(.(x)), collapse = "\n") - )) - } - } else { - if (!checkmate::test_character(res, any.missing = FALSE) || length(res) > ncol(ds) || anyDuplicated(res)) { - stop(paste( - "The following function must return a character vector with unique", - "names from the available columns of the dataset:\n\n", - deparse1(bquote(.(x)), collapse = "\n") - )) - } - } - - res -} - #' @export #' @keywords internal #' diff --git a/R/resolve_delayed.R b/R/resolve_delayed.R index 007ac2d0..a2db9b12 100644 --- a/R/resolve_delayed.R +++ b/R/resolve_delayed.R @@ -4,8 +4,7 @@ #' #' @param x (`delayed_data`, `list`) to resolve. #' @param datasets (`FilteredData` or named `list`) to use as a reference to resolve `x`. -#' @param keys (named `list`) with primary keys for each dataset from `datasets`. `names(keys)` -#' should match `names(datasets)`. +#' @param join_keys (`join_keys`) used to resolve `key` in [variable_choices()]. #' #' @return Resolved object. #' @@ -66,34 +65,28 @@ #' }) #' @export #' -resolve_delayed <- function(x, datasets, keys) { +resolve_delayed <- function(x, datasets, join_keys = teal.data::join_keys()) { + checkmate::assert_class(join_keys, "join_keys") UseMethod("resolve_delayed", datasets) } -#' @describeIn resolve_delayed Default values for `keys` parameters is extracted from `datasets`. +#' @describeIn resolve_delayed Default values for `join_keys` parameters is extracted from `datasets`. #' @export resolve_delayed.FilteredData <- function(x, datasets, - keys = sapply(datasets$datanames(), datasets$get_keys, simplify = FALSE)) { + join_keys = datasets$get_join_keys()) { datasets_list <- sapply(X = datasets$datanames(), simplify = FALSE, FUN = function(x) { - reactive(datasets$get_data(dataname = x, filtered = TRUE)) + datasets$get_data(dataname = x, filtered = TRUE) }) - resolve(x, datasets_list, keys) + resolve(x, datasets_list, join_keys) } #' @describeIn resolve_delayed Generic method when `datasets` argument is a named list. #' @export -resolve_delayed.list <- function(x, datasets, keys = NULL) { +resolve_delayed.list <- function(x, datasets, join_keys = teal.data::join_keys()) { checkmate::assert_list(datasets, types = c("reactive", "data.frame"), min.len = 1, names = "named") - checkmate::assert_list(keys, "character", names = "named", null.ok = TRUE) - checkmate::assert( - .var.name = "keys", - checkmate::check_names(names(keys), subset.of = names(datasets)), - checkmate::check_null(keys) - ) - # convert to list of reactives datasets_list <- sapply(X = datasets, simplify = FALSE, FUN = function(x) { - if (is.reactive(x)) x else reactive(x) + if (is.reactive(x)) x() else x }) - resolve(x, datasets_list, keys) + resolve(x, datasets = datasets_list, join_keys = join_keys) } diff --git a/R/select_spec.R b/R/select_spec.R index e2cdcce4..2a5be405 100644 --- a/R/select_spec.R +++ b/R/select_spec.R @@ -83,8 +83,8 @@ #' select_spec(choices = variable_choices("ADSL"), selected = all_choices()) #' @export #' -select_spec <- function(choices, - selected = `if`(inherits(choices, "delayed_data"), NULL, choices[1]), +select_spec <- function(choices = variable_choices(), + selected = first_choice(), multiple = length(selected) > 1 || inherits(selected, "multiple_choices"), fixed = FALSE, always_selected = NULL, @@ -141,6 +141,7 @@ select_spec.delayed_data <- function(choices, # nolint: object_name_linter. ) } + #' @rdname select_spec #' @export #' diff --git a/_pkgdown.yml b/_pkgdown.yml index 1fb8c182..687a724b 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -30,7 +30,10 @@ reference: - add_no_selected_choices - all_choices - first_choice + - first_choices - last_choice + - last_choices + - delayed_datanames - check_no_multiple_selection - choices_labeled - choices_selected diff --git a/man/choices_selected.Rd b/man/choices_selected.Rd index 5e2ec3eb..d1a2cc54 100644 --- a/man/choices_selected.Rd +++ b/man/choices_selected.Rd @@ -7,7 +7,7 @@ \usage{ choices_selected( choices, - selected = if (inherits(choices, "delayed_data")) NULL else choices[1], + selected = first_choice(), keep_order = FALSE, fixed = FALSE ) diff --git a/man/data_extract_multiple_srv.Rd b/man/data_extract_multiple_srv.Rd index bf77550a..daf863db 100644 --- a/man/data_extract_multiple_srv.Rd +++ b/man/data_extract_multiple_srv.Rd @@ -16,7 +16,7 @@ data_extract_multiple_srv(data_extract, datasets, ...) \method{data_extract_multiple_srv}{list}( data_extract, datasets, - join_keys = NULL, + join_keys = teal.data::join_keys(), select_validation_rule = NULL, filter_validation_rule = NULL, dataset_validation_rule = if (is.null(select_validation_rule) && diff --git a/man/data_extract_spec.Rd b/man/data_extract_spec.Rd index 867c82b1..7c1a2966 100644 --- a/man/data_extract_spec.Rd +++ b/man/data_extract_spec.Rd @@ -4,11 +4,17 @@ \alias{data_extract_spec} \title{Data extract input for \code{teal} modules} \usage{ -data_extract_spec(dataname, select = NULL, filter = NULL, reshape = FALSE) +data_extract_spec( + dataname = "all", + select = select_spec(selected = all_choices()), + filter = filter_spec(), + reshape = FALSE +) } \arguments{ \item{dataname}{(\code{character}) -The name of the dataset to be extracted.} +The name of the dataset to be extracted. Keyword \code{"all"} suggest that this \code{data_extract_spec} +is universal for all datasets used in \code{teal} application.} \item{select}{(\code{NULL} or \code{select_spec}-S3 class or \code{delayed_select_spec}) Columns to be selected from the input dataset mentioned in \code{dataname}. diff --git a/man/data_extract_srv.Rd b/man/data_extract_srv.Rd index f5a5c969..ab2c27a5 100644 --- a/man/data_extract_srv.Rd +++ b/man/data_extract_srv.Rd @@ -14,7 +14,7 @@ data_extract_srv(id, datasets, data_extract_spec, ...) id, datasets, data_extract_spec, - join_keys = NULL, + join_keys = teal.data::join_keys(), select_validation_rule = NULL, filter_validation_rule = NULL, dataset_validation_rule = if (is.null(select_validation_rule) && diff --git a/man/delayed_choices.Rd b/man/delayed_choices.Rd index e7d50e76..02f0ecd4 100644 --- a/man/delayed_choices.Rd +++ b/man/delayed_choices.Rd @@ -3,6 +3,7 @@ \name{delayed_choices} \alias{delayed_choices} \alias{all_choices} +\alias{nth_choice} \alias{first_choice} \alias{last_choice} \alias{first_choices} @@ -11,6 +12,8 @@ \usage{ all_choices() +nth_choice(n) + first_choice() last_choice() @@ -20,7 +23,7 @@ first_choices(n) last_choices(n) } \arguments{ -\item{n}{positive (\code{integer}-like) number of first/last items to subset to} +\item{n}{positive (\code{integer}-like) number of first/last/nth item(s) to subset to.} } \value{ Object of class \verb{delayed_data, delayed_choices}, which is a function diff --git a/man/filter_spec.Rd b/man/filter_spec.Rd index 21304662..73637c76 100644 --- a/man/filter_spec.Rd +++ b/man/filter_spec.Rd @@ -5,9 +5,9 @@ \title{Data extract filter specification} \usage{ filter_spec( - vars, + vars = choices_selected(choices = variable_choices()), choices = NULL, - selected = if (inherits(choices, "delayed_data")) NULL else choices[1], + selected = first_choice(), multiple = length(selected) > 1 || inherits(selected, "multiple_choices"), label = "Filter by", sep = attr(choices, "sep"), diff --git a/man/resolve.Rd b/man/resolve.Rd index 104962f1..a9b32f70 100644 --- a/man/resolve.Rd +++ b/man/resolve.Rd @@ -12,31 +12,30 @@ \alias{resolve.default} \title{Resolve delayed inputs by evaluating the code within the provided datasets} \usage{ -resolve(x, datasets, keys = NULL) +resolve(x, datasets, join_keys = teal.data::join_keys()) -\method{resolve}{delayed_variable_choices}(x, datasets, keys) +\method{resolve}{delayed_variable_choices}(x, datasets, join_keys = teal.data::join_keys()) -\method{resolve}{delayed_value_choices}(x, datasets, keys) +\method{resolve}{delayed_value_choices}(x, datasets, join_keys = teal.data::join_keys()) -\method{resolve}{delayed_choices_selected}(x, datasets, keys) +\method{resolve}{delayed_choices_selected}(x, datasets, join_keys = teal.data::join_keys()) -\method{resolve}{delayed_select_spec}(x, datasets, keys) +\method{resolve}{delayed_select_spec}(x, datasets, join_keys = teal.data::join_keys()) -\method{resolve}{delayed_filter_spec}(x, datasets, keys) +\method{resolve}{delayed_filter_spec}(x, datasets, join_keys = teal.data::join_keys()) -\method{resolve}{delayed_data_extract_spec}(x, datasets, keys) +\method{resolve}{delayed_data_extract_spec}(x, datasets, join_keys = teal.data::join_keys()) -\method{resolve}{list}(x, datasets, keys) +\method{resolve}{list}(x, datasets, join_keys = teal.data::join_keys()) -\method{resolve}{default}(x, datasets, keys) +\method{resolve}{default}(x, datasets, join_keys = teal.data::join_keys()) } \arguments{ \item{x}{(\code{delayed_data}) object to resolve.} \item{datasets}{(named \code{list} of \code{data.frame}) to use in evaluation.} -\item{keys}{(named \code{list} of \code{character}) to be used as the keys for each dataset. -The names of this list must be exactly the same as for datasets.} +\item{join_keys}{(\code{join_keys}) used to resolve \code{key} in \code{\link[=variable_choices]{variable_choices()}}.} } \value{ Resolved object. diff --git a/man/resolve_delayed.Rd b/man/resolve_delayed.Rd index 41996186..f669cefc 100644 --- a/man/resolve_delayed.Rd +++ b/man/resolve_delayed.Rd @@ -6,23 +6,18 @@ \alias{resolve_delayed.list} \title{Resolve delayed inputs by evaluating the code within the provided datasets} \usage{ -resolve_delayed(x, datasets, keys) +resolve_delayed(x, datasets, join_keys = teal.data::join_keys()) -\method{resolve_delayed}{FilteredData}( - x, - datasets, - keys = sapply(datasets$datanames(), datasets$get_keys, simplify = FALSE) -) +\method{resolve_delayed}{FilteredData}(x, datasets, join_keys = datasets$get_join_keys()) -\method{resolve_delayed}{list}(x, datasets, keys = NULL) +\method{resolve_delayed}{list}(x, datasets, join_keys = teal.data::join_keys()) } \arguments{ \item{x}{(\code{delayed_data}, \code{list}) to resolve.} \item{datasets}{(\code{FilteredData} or named \code{list}) to use as a reference to resolve \code{x}.} -\item{keys}{(named \code{list}) with primary keys for each dataset from \code{datasets}. \code{names(keys)} -should match \code{names(datasets)}.} +\item{join_keys}{(\code{join_keys}) used to resolve \code{key} in \code{\link[=variable_choices]{variable_choices()}}.} } \value{ Resolved object. @@ -32,7 +27,7 @@ Resolved object. } \section{Methods (by class)}{ \itemize{ -\item \code{resolve_delayed(FilteredData)}: Default values for \code{keys} parameters is extracted from \code{datasets}. +\item \code{resolve_delayed(FilteredData)}: Default values for \code{join_keys} parameters is extracted from \code{datasets}. \item \code{resolve_delayed(list)}: Generic method when \code{datasets} argument is a named list. diff --git a/man/resolve_delayed_expr.Rd b/man/resolve_delayed_expr.Rd deleted file mode 100644 index ff384c69..00000000 --- a/man/resolve_delayed_expr.Rd +++ /dev/null @@ -1,23 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/resolve.R -\name{resolve_delayed_expr} -\alias{resolve_delayed_expr} -\title{Resolve expression after delayed data are loaded} -\usage{ -resolve_delayed_expr(x, ds, is_value_choices) -} -\arguments{ -\item{x}{(\code{function}) Function that is applied on dataset. -It must take only a single argument "data" and return character vector with columns / values.} - -\item{ds}{(\code{data.frame}) Dataset.} - -\item{is_value_choices}{(\code{logical}) Determines which check of the returned value will be applied.} -} -\value{ -\code{character} vector - result of calling function \code{x} on dataset \code{ds}. -} -\description{ -Resolve expression after delayed data are loaded -} -\keyword{internal} diff --git a/man/select_spec.Rd b/man/select_spec.Rd index 9a9cfec4..348b7325 100644 --- a/man/select_spec.Rd +++ b/man/select_spec.Rd @@ -7,8 +7,8 @@ \title{Column selection input specification} \usage{ select_spec( - choices, - selected = if (inherits(choices, "delayed_data")) NULL else choices[1], + choices = variable_choices(), + selected = first_choice(), multiple = length(selected) > 1 || inherits(selected, "multiple_choices"), fixed = FALSE, always_selected = NULL, diff --git a/man/value_choices.Rd b/man/value_choices.Rd index f6dd40d0..70734217 100644 --- a/man/value_choices.Rd +++ b/man/value_choices.Rd @@ -2,15 +2,15 @@ % Please edit documentation in R/choices_labeled.R \name{value_choices} \alias{value_choices} -\alias{value_choices.character} -\alias{value_choices.data.frame} \title{Value labeling and filtering based on variable relationship} \usage{ -value_choices(data, var_choices, var_label = NULL, subset = NULL, sep = " - ") - -\method{value_choices}{character}(data, var_choices, var_label = NULL, subset = NULL, sep = " - ") - -\method{value_choices}{data.frame}(data, var_choices, var_label = NULL, subset = NULL, sep = " - ") +value_choices( + data = "all", + var_choices = variable_choices(data = data), + var_label = NULL, + subset = NULL, + sep = " - " +) } \arguments{ \item{data}{(\code{data.frame}, \code{character}) diff --git a/man/variable_choices.Rd b/man/variable_choices.Rd index 40a9f76b..0b3978ab 100644 --- a/man/variable_choices.Rd +++ b/man/variable_choices.Rd @@ -2,20 +2,20 @@ % Please edit documentation in R/choices_labeled.R \name{variable_choices} \alias{variable_choices} -\alias{variable_choices.character} -\alias{variable_choices.data.frame} \title{Variable label extraction and custom selection from data} \usage{ -variable_choices(data, subset = NULL, fill = FALSE, key = NULL) - -\method{variable_choices}{character}(data, subset = NULL, fill = FALSE, key = NULL) - -\method{variable_choices}{data.frame}(data, subset = NULL, fill = TRUE, key = NULL) +variable_choices( + data = "all", + subset = function(data) names(data), + fill = FALSE, + key = NULL +) } \arguments{ \item{data}{(\code{data.frame} or \code{character}) If \code{data.frame}, then data to extract labels from. -If \code{character}, then name of the dataset to extract data from once available.} +If \code{character}, then name of the dataset to extract data from once available. Keyword \code{"all"} +(default) indicates that \code{data} will be inherited from the \code{data_extract_spec} \code{dataname}.} \item{subset}{(\code{character} or \code{function}) If \code{character}, then a vector of column names. @@ -54,7 +54,10 @@ variable_choices( key = default_cdisc_join_keys["ADRS", "ADRS"] ) -# delayed version +# delayed version with unknown dataset +variable_choices() + +# delayed ADRS variable_choices("ADRS", subset = c("USUBJID", "STUDYID")) # functional subset (with delayed data) - return only factor variables diff --git a/tests/testthat/test-check_selector.R b/tests/testthat/test-check_selector.R deleted file mode 100644 index 2aa7a97d..00000000 --- a/tests/testthat/test-check_selector.R +++ /dev/null @@ -1,5 +0,0 @@ -testthat::test_that("check_selector_dataname", { - testthat::expect_silent(check_selector_dataname("test")) - testthat::expect_error(check_selector_dataname(c())) - testthat::expect_error(check_selector_dataname(c("test", "test2"))) -}) diff --git a/tests/testthat/test-choices_selected.R b/tests/testthat/test-choices_selected.R index 4cf40b41..f8e23db6 100644 --- a/tests/testthat/test-choices_selected.R +++ b/tests/testthat/test-choices_selected.R @@ -1,74 +1,44 @@ -adsl <- as.data.frame(as.list(setNames(nm = c("STUDYID", "USUBJID")))) -adtte <- as.data.frame(as.list(setNames(nm = c("STUDYID", "USUBJID", "PARAMCD")))) - -vc_hard <- variable_choices("ADSL", subset = c("STUDYID", "USUBJID")) -vc_hard_exp <- structure( - list(data = "ADSL", subset = c("STUDYID", "USUBJID"), key = NULL), - class = c("delayed_variable_choices", "delayed_data", "choices_labeled") -) - -vc_hard_short <- variable_choices("ADSL", subset = "STUDYID") -vc_hard_short_exp <- structure( - list(data = "ADSL", subset = "STUDYID", key = NULL), - class = c("delayed_variable_choices", "delayed_data", "choices_labeled") -) - -vc_fun <- variable_choices("ADSL", subset = function(data) colnames(data)[1:2]) -vc_fun_exp <- structure( - list(data = "ADSL", subset = function(data) colnames(data)[1:2], key = NULL), - class = c("delayed_variable_choices", "delayed_data", "choices_labeled") -) +testthat::test_that("choices_selected requires choices to be specified", { + testthat::expect_error(choices_selected(), "\"choices\" is missing") +}) -vc_fun_short <- variable_choices("ADSL", subset = function(data) colnames(data)[1]) -vc_fun_short_exp <- structure( - list(data = "ADSL", subset = function(data) colnames(data)[1], key = NULL), - class = c("delayed_variable_choices", "delayed_data", "choices_labeled") -) +testthat::test_that("choices_selected accepts choices as atomics", { + testthat::expect_no_error(choices_selected(choices = c("a", "b"))) + testthat::expect_no_error(choices_selected(choices = c(1, 2))) + testthat::expect_no_error(choices_selected(choices = NULL)) + testthat::expect_error(choices_selected(choices = list(1, 2))) +}) -testthat::test_that("delayed version of choices_selected", { - # hard-coded choices and selected - obj <- choices_selected(vc_hard, selected = vc_hard_short) - testthat::expect_equal( - obj, - structure( - list(choices = vc_hard_exp, selected = vc_hard_short_exp, keep_order = FALSE, fixed = FALSE), - class = c("delayed_choices_selected", "delayed_data", "choices_selected") - ) +testthat::test_that("choices_selected returns list of class choices_selected", { + testthat::expect_identical( + choices_selected(choices = c("a", "b")), + structure(list(choices = c("a", "b"), selected = "a", fixed = FALSE), class = "choices_selected") ) +}) - data_list <- list(ADSL = reactive(adsl), ADTTE = reactive(adtte)) - key_list <- list(ADSL = c("STUDYID", "USUBJID"), ADTTE = c("STUDYID", "USUBJID", "PARAMCD")) +testthat::test_that("choices_selected accepts choices as delayed_data", { + testthat::expect_no_error(choices_selected(choices = variable_choices(data = "iris"))) + testthat::expect_no_error(choices_selected(choices = value_choices(data = "iris", var_choices = "Species"))) +}) - res_obj <- isolate(resolve(obj, datasets = data_list, keys = key_list)) - exp_obj <- choices_selected( - variable_choices(adsl, subset = c("STUDYID", "USUBJID"), key = c("STUDYID", "USUBJID")), - selected = variable_choices(adsl, subset = c("STUDYID"), key = c("STUDYID", "USUBJID")) +testthat::test_that("choices_selected returns delayed_choices_selected when choices are delayed_data", { + testthat::expect_s3_class( + choices_selected(choices = variable_choices(data = "iris")), + c("delayed_choices_selected", "delayed_data") ) - testthat::expect_equal(res_obj, exp_obj, check.attributes = TRUE) +}) - # functional choices and selected - obj <- choices_selected(vc_fun, selected = vc_fun_short) - testthat::expect_equal( - obj, - structure( - list(choices = vc_fun_exp, selected = vc_fun_short_exp, keep_order = FALSE, fixed = FALSE), - class = c("delayed_choices_selected", "delayed_data", "choices_selected") - ) +testthat::test_that("choices_selected by default sets selected as first choice", { + testthat::expect_identical( + choices_selected(choices = c(1, 2)), + choices_selected(choices = c(1, 2), selected = 1) ) - - res_obj <- isolate(resolve(obj, datasets = data_list, keys = key_list)) - testthat::expect_equal(res_obj, exp_obj) }) testthat::test_that("choices_selected throws error when selected is not found in choices", { - testthat::expect_error(choices_selected(choices = c("a"), selected = "b"), "Must be a subset of \\{'a'\\}") testthat::expect_error( - choices_selected(choices = c("a"), selected = c("a", "b")), - "Must be a subset of \\{'a'\\}" - ) - testthat::expect_error( - choices_selected(choices = c("a"), selected = c("c", "b")), - "Must be a subset of \\{'a'\\}" + choices_selected(choices = c("a", "b"), selected = c("c", "d")), + "Must be a subset of \\{'a','b'\\}" ) }) @@ -162,38 +132,3 @@ testthat::test_that("choices_selected remove duplicates", { ), class = "choices_selected") ) }) - -testthat::test_that("delayed version of choices_selected - resolve_delayed", { - data_list <- list(ADSL = reactive(adsl), ADTTE = reactive(adtte)) - key_list <- list(ADSL = c("STUDYID", "USUBJID"), ADTTE = c("STUDYID", "USUBJID", "PARAMCD")) - - # hard-coded choices and selected - obj <- choices_selected(vc_hard, selected = vc_hard_short) - testthat::expect_equal( - obj, - structure( - list(choices = vc_hard_exp, selected = vc_hard_short_exp, keep_order = FALSE, fixed = FALSE), - class = c("delayed_choices_selected", "delayed_data", "choices_selected") - ) - ) - - res_obj <- isolate(resolve_delayed(obj, datasets = data_list, keys = key_list)) - exp_obj <- choices_selected( - variable_choices(adsl, subset = c("STUDYID", "USUBJID"), key = c("STUDYID", "USUBJID")), - selected = variable_choices(adsl, subset = c("STUDYID"), key = c("STUDYID", "USUBJID")) - ) - testthat::expect_equal(res_obj, exp_obj, check.attributes = TRUE) - - # functional choices and selected - obj <- choices_selected(vc_fun, selected = vc_fun_short) - testthat::expect_equal( - obj, - structure( - list(choices = vc_fun_exp, selected = vc_fun_short_exp, keep_order = FALSE, fixed = FALSE), - class = c("delayed_choices_selected", "delayed_data", "choices_selected") - ) - ) - - res_obj <- isolate(resolve_delayed(obj, datasets = data_list, keys = key_list)) - testthat::expect_equal(res_obj, exp_obj) -}) diff --git a/tests/testthat/test-data_extract_multiple_srv.R b/tests/testthat/test-data_extract_multiple_srv.R index dfe9b4a2..0b902ec2 100644 --- a/tests/testthat/test-data_extract_multiple_srv.R +++ b/tests/testthat/test-data_extract_multiple_srv.R @@ -2,7 +2,7 @@ ADSL <- teal.data::rADSL ADLB <- teal.data::rADLB ADTTE <- teal.data::rADTTE -data_list <- list(ADSL = reactive(ADSL), ADTTE = reactive(ADTTE), ADLB = reactive(ADLB)) +data_list <- list(ADSL = reactive(ADSL), ADTTE = reactive(ADTTE), ADLB = reactive(ADLB), iris = reactive(iris)) join_keys <- teal.data::default_cdisc_join_keys[c("ADSL", "ADTTE", "ADLB")] testthat::test_that("data_extract_multiple_srv accepts a named list of `data_extract_spec`", { @@ -10,7 +10,7 @@ testthat::test_that("data_extract_multiple_srv accepts a named list of `data_ext domain = shiny::MockShinySession$new(), expr = testthat::expect_no_error( data_extract_multiple_srv( - data_extract = list(test = data_extract_spec(dataname = "iris")), + data_extract = list(test = data_extract_spec(dataname = "ADSL")), datasets = data_list, join_keys = teal.data::join_keys() ) @@ -53,12 +53,11 @@ testthat::test_that("data_extract_multiple_srv returns an empty list if passed a }) testthat::test_that("data_extract_multiple_srv prunes `NULL` from the passed list", { - data_list <- list(iris = reactive(iris)) shiny::withReactiveDomain( domain = shiny::MockShinySession$new(), expr = testthat::expect_equal( length(data_extract_multiple_srv( - list(test = data_extract_spec(dataname = "iris"), test2 = NULL), + list(test = data_extract_spec(dataname = "ADSL"), test2 = NULL), datasets = data_list )), 1 diff --git a/tests/testthat/test-data_extract_spec.R b/tests/testthat/test-data_extract_spec.R index 04ae26a8..873891dd 100644 --- a/tests/testthat/test-data_extract_spec.R +++ b/tests/testthat/test-data_extract_spec.R @@ -1,503 +1,75 @@ -ADSL <- teal.data::rADSL -ADTTE <- teal.data::rADTTE -data_list <- list(ADSL = reactive(ADSL), ADTTE = reactive(ADTTE)) -key_list <- list(ADSL = c("STUDYID", "USUBJID"), ADTTE = c("STUDYID", "USUBJID", "PARAMCD")) - -vc_hard <- variable_choices("ADSL", subset = c("STUDYID", "USUBJID")) -vc_hard_exp <- structure( - list(data = "ADSL", subset = c("STUDYID", "USUBJID"), key = NULL), - class = c("delayed_variable_choices", "delayed_data", "choices_labeled") -) - -vc_hard_short <- variable_choices("ADSL", subset = "STUDYID") -vc_hard_short_exp <- structure( - list(data = "ADSL", subset = "STUDYID", key = NULL), - class = c("delayed_variable_choices", "delayed_data", "choices_labeled") -) - -vc_fun <- variable_choices("ADSL", subset = function(data) colnames(data)[1:2]) -vc_fun_exp <- structure( - list(data = "ADSL", subset = function(data) colnames(data)[1:2], key = NULL), - class = c("delayed_variable_choices", "delayed_data", "choices_labeled") -) - -vc_fun_short <- variable_choices("ADSL", subset = function(data) colnames(data)[1]) -vc_fun_short_exp <- structure( - list(data = "ADSL", subset = function(data) colnames(data)[1], key = NULL), - class = c("delayed_variable_choices", "delayed_data", "choices_labeled") -) - -testthat::test_that("data_extract_spec throws when select is not select_spec or NULL", { - testthat::expect_error(data_extract_spec("toyDataset", select = c("A", "B"))) +testthat::test_that("data_extract_spec accepts string in dataname argument", { + testthat::expect_no_error(data_extract_spec(dataname = "a")) + testthat::expect_no_error(data_extract_spec(dataname = "all")) + testthat::expect_error(data_extract_spec(dataname = NULL)) + testthat::expect_error(data_extract_spec(dataname = character(0))) + testthat::expect_error(data_extract_spec(dataname = 1)) }) -testthat::test_that("data_extract_spec works with valid input", { - # the dataset does not exist, so we just check if the combinations are accepted - # we add 1 to the var names to avoid confusion with their respective functions - - select_spec1 <- select_spec( - label = "Select variable:", - choices = c("SEX", "RACE"), - selected = "SEX", - multiple = FALSE, - ordered = FALSE, - fixed = FALSE - ) - data_extract_spec1 <- testthat::expect_silent(data_extract_spec( - "toyDataset", - select = select_spec1 - )) - testthat::expect_identical(data_extract_spec1$select, select_spec1) - testthat::expect_identical(class(data_extract_spec1), "data_extract_spec") - - testthat::expect_identical( - testthat::expect_silent(data_extract_spec( - "toyDataset", - select = select_spec1 - )), - testthat::expect_silent(data_extract_spec( - "toyDataset", - select = select_spec1, - filter = NULL - )) - ) - - # with filter - select_spec1 <- select_spec( - label = "Select variable:", - choices = c("AVAL", "CNSR"), - selected = "AVAL", - multiple = FALSE, - ordered = FALSE, - fixed = FALSE - ) - filter_spec1 <- filter_spec( - label = "Select parameter:", - vars = "PARAMCD", - choices = c("OS", "PFS"), - selected = "PFS", - multiple = FALSE - ) - filter_spec1$dataname <- "ADTTE" - - filter_spec2 <- filter_spec( - label = "Select parameter:", - vars = "AVISIT", - choices = c("BASELINE", "SCREENIG"), - selected = "BASELINE", - multiple = FALSE - ) - filter_spec2$dataname <- "ADTTE" - - data_extract_spec1 <- testthat::expect_silent(data_extract_spec( - dataname = "ADTTE", - select = select_spec1, - filter = filter_spec1 - )) - testthat::expect_identical(data_extract_spec1$select, select_spec1) - - testthat::expect_identical(data_extract_spec1$filter, list(filter_spec1)) - - data_extract_spec2 <- testthat::expect_silent(data_extract_spec( - dataname = "ADTTE", - select = select_spec1, - filter = list(filter_spec1, filter_spec2) - )) - - testthat::expect_identical(data_extract_spec2$select, select_spec1) - testthat::expect_identical(data_extract_spec2$filter, list(filter_spec1, filter_spec2)) - - # with reshape (only makes sense when filter is there) - filter_spec1 <- filter_spec( - label = "Select parameter:", - vars = "PARAMCD", - choices = c("OS", "PFS", "OS2"), - selected = c("OS", "PFS"), - multiple = TRUE - ) - filter_spec1$dataname <- "ADTTE" - data_extract_spec1 <- testthat::expect_silent(data_extract_spec( - dataname = "ADTTE", - select = select_spec1, - filter = filter_spec1, - reshape = TRUE - )) - testthat::expect_identical(data_extract_spec1$select, select_spec1) - testthat::expect_identical(data_extract_spec1$filter, list(filter_spec1)) - testthat::expect_identical(data_extract_spec1$reshape, TRUE) +testthat::test_that("data_extract_spec accepts select_spec or NULL in select argument", { + testthat::expect_no_error(data_extract_spec(select = select_spec())) + testthat::expect_no_error(data_extract_spec(select = NULL)) + testthat::expect_error(data_extract_spec(select = list())) }) -testthat::test_that("delayed data_extract_spec works", { - set.seed(1) - ADSL <- data.frame( - USUBJID = letters[1:10], - SEX = sample(c("F", "M", "U"), 10, replace = TRUE), - BMRKR1 = rnorm(10), - BMRKR2 = sample(c("L", "M", "H"), 10, replace = TRUE), - stringsAsFactors = FALSE - ) - attr(ADSL, "keys") <- c("STUDYID", "USUBJID") - - filter_normal <- filter_spec( - vars = variable_choices(ADSL, "SEX"), - sep = "-", - choices = value_choices(ADSL, "SEX", "SEX"), - selected = "F", - multiple = FALSE - ) - - filter_delayed <- filter_spec( - vars = variable_choices("ADSL", "SEX"), - sep = "-", - choices = value_choices("ADSL", "SEX", "SEX"), - selected = "F", - multiple = FALSE - ) - - select_normal <- select_spec( - choices = variable_choices(ADSL, c("BMRKR1", "BMRKR2")), - selected = "BMRKR1", - multiple = FALSE, - fixed = FALSE, - ordered = FALSE - ) - - select_delayed <- select_spec( - choices = variable_choices("ADSL", c("BMRKR1", "BMRKR2")), - selected = "BMRKR1", - multiple = FALSE, - fixed = FALSE, - ordered = FALSE - ) - - expected_spec <- data_extract_spec( - dataname = "ADSL", - select = select_normal, - filter = filter_normal - ) - - # obtained via delayed approach - delayed_spec <- data_extract_spec( - dataname = "ADSL", - select = select_delayed, - filter = filter_delayed - ) - - mix1 <- data_extract_spec( - dataname = "ADSL", - select = select_delayed, - filter = filter_normal - ) - - mix2 <- data_extract_spec( - dataname = "ADSL", - select = select_normal, - filter = filter_delayed - ) - - mix3 <- data_extract_spec( - dataname = "ADSL", - select = select_delayed, - filter = list(filter_delayed, filter_normal) - ) - - testthat::expect_equal(class(delayed_spec), c("delayed_data_extract_spec", "delayed_data", "data_extract_spec")) - testthat::expect_equal(class(mix1), c("delayed_data_extract_spec", "delayed_data", "data_extract_spec")) - testthat::expect_equal(class(mix2), c("delayed_data_extract_spec", "delayed_data", "data_extract_spec")) - testthat::expect_equal(class(mix3), c("delayed_data_extract_spec", "delayed_data", "data_extract_spec")) - - testthat::expect_equal(names(expected_spec), names(delayed_spec)) - testthat::expect_equal(names(expected_spec), names(mix1)) - testthat::expect_equal(names(expected_spec), names(mix2)) - testthat::expect_equal(names(expected_spec), names(mix3)) - - data_list <- list(ADSL = reactive(ADSL)) - key_list <- list(ADSL = c("STUDYID", "USUBJID")) - - isolate({ - testthat::expect_identical(expected_spec, resolve(delayed_spec, data_list, key_list)) - testthat::expect_identical(expected_spec, resolve(mix1, data_list, key_list)) - testthat::expect_identical(expected_spec, resolve(mix2, data_list, key_list)) - - mix3_res <- resolve(mix3, data_list, key_list) - }) - testthat::expect_identical(expected_spec$filter[[1]], mix3_res$filter[[1]]) - testthat::expect_identical(expected_spec$filter[[1]], mix3_res$filter[[2]]) - mix3_res$filter <- NULL - expected_spec$filter <- NULL - testthat::expect_identical(expected_spec, mix3_res) +testthat::test_that("data_extract_spec accepts list of filter_spec, filter_spec or NULL in filter argument", { + testthat::expect_no_error(data_extract_spec(filter = list(filter_spec(), filter_spec()))) + testthat::expect_no_error(data_extract_spec(filter = filter_spec())) + testthat::expect_no_error(data_extract_spec(filter = NULL)) + testthat::expect_error(data_extract_spec(filter = list(a = 1))) }) -testthat::test_that("delayed version of data_extract_spec", { - # hard-coded subset - obj <- data_extract_spec( - "ADSL", - select = select_spec(vc_hard, selected = vc_hard_short, multiple = FALSE), - filter = filter_spec( - vars = variable_choices("ADSL", subset = "ARMCD"), - choices = value_choices("ADSL", var_choices = "ARMCD", var_label = "ARM", subset = c("ARM A", "ARM B")), - selected = value_choices("ADSL", var_choices = "ARMCD", var_label = "ARM", subset = "ARM A"), - multiple = FALSE - ) - ) +testthat::test_that("data_extract_spec accepts a flag in reshape argument", { + testthat::expect_no_error(data_extract_spec(reshape = TRUE)) + testthat::expect_error(data_extract_spec(reshape = c("A", "B"))) +}) - res_obj <- isolate(resolve(obj, datasets = data_list, keys = key_list)) - exp_obj <- data_extract_spec( - "ADSL", - select = select_spec(variable_choices(ADSL, c("STUDYID", "USUBJID"), key = c("STUDYID", "USUBJID")), - selected = variable_choices(ADSL, "STUDYID", key = c("STUDYID", "USUBJID")) - ), - filter = filter_spec( - vars = variable_choices(ADSL, subset = "ARMCD", key = c("STUDYID", "USUBJID")), - choices = value_choices(ADSL, var_choices = "ARMCD", var_label = "ARM", subset = c("ARM A", "ARM B")), - selected = value_choices(ADSL, var_choices = "ARMCD", var_label = "ARM", subset = "ARM A"), - multiple = FALSE +testthat::test_that("data_extract_spec has defaults", { + testthat::expect_equal( + data_extract_spec(), + data_extract_spec( + dataname = "all", + select = select_spec(selected = all_choices()), + filter = filter_spec(), + reshape = FALSE ) ) +}) - testthat::expect_equal(res_obj$select, exp_obj$select) - testthat::expect_equal(res_obj$filter[[1]]$choices, exp_obj$filter[[1]]$choices) - testthat::expect_equal(res_obj$filter[[1]]$selected, exp_obj$filter[[1]]$selected) - - # functional subset - obj <- data_extract_spec( - "ADSL", - select = select_spec(vc_fun, selected = vc_fun_short, multiple = FALSE), - filter = filter_spec( - vars = variable_choices("ADSL", subset = "ARMCD"), - choices = value_choices( - "ADSL", - var_choices = "ARMCD", - var_label = "ARM", - subset = function(data) c("ARM A", "ARM B") - ), - selected = value_choices( - "ADSL", - var_choices = "ARMCD", - var_label = "ARM", - subset = function(data) "ARM A" +testthat::test_that("data_extract_spec returns data_extract_spec when filter and select are eager", { + ss <- select_spec(choices = letters) + fs <- filter_spec(vars = "col1", choices = letters) + fs$dataname <- "dataset" + testthat::expect_identical( + data_extract_spec(dataname = "dataset", select = ss, filter = fs), + structure( + list( + dataname = "dataset", + select = ss, + filter = list(fs), + reshape = FALSE ), - multiple = FALSE - ) - ) - - res_obj <- isolate(resolve(obj, datasets = data_list, keys = key_list)) - exp_obj <- data_extract_spec( - "ADSL", - select = select_spec(variable_choices(ADSL, c("STUDYID", "USUBJID"), key = c("STUDYID", "USUBJID")), - selected = variable_choices(ADSL, "STUDYID", key = c("STUDYID", "USUBJID")) - ), - filter = filter_spec( - vars = variable_choices(ADSL, subset = "ARMCD", key = c("STUDYID", "USUBJID")), - choices = value_choices(ADSL, var_choices = "ARMCD", var_label = "ARM", subset = c("ARM A", "ARM B")), - selected = value_choices(ADSL, var_choices = "ARMCD", var_label = "ARM", subset = "ARM A"), - multiple = FALSE + class = "data_extract_spec" ) ) - - testthat::expect_equal(res_obj$select, exp_obj$select) - testthat::expect_equal(res_obj$filter[[1]]$choices, exp_obj$filter[[1]]$choices) - testthat::expect_equal(res_obj$filter[[1]]$selected, exp_obj$filter[[1]]$selected) }) -testthat::test_that("data_extract_spec allows both select and filter parameters to be NULL", { - testthat::expect_no_error(des <- data_extract_spec("ADSL")) +testthat::test_that("data_extract_spec fails when dataname is 'all' and select/filter are eager", { + testthat::skip("todo") + testthat::expect_error(data_extract_spec(select = select_spec(choices = letters))) + testthat::expect_error(data_extract_spec(filter = select_spec(vars = "col1", choices = letters))) }) -testthat::test_that("data_extract_spec returns filter_spec with multiple set to TRUE", { - des <- data_extract_spec("ADSL") - testthat::expect_equal(class(des$filter[[1]]), c("delayed_filter_spec", "filter_spec", "delayed_data")) - testthat::expect_equal(length(des$filter), 1) - testthat::expect_true(des$filter[[1]]$multiple) +testthat::test_that("data_extract_spec warns when dataname is 'all' and `data != all` in any variable/value_choices", { + testthat::skip("todo") + testthat::expect_warning(data_extract_spec(select = select_spec(choices = variable_choices(data = "iris")))) + testthat::expect_warning(data_extract_spec(select = filter_spec(choices = value_choices(data = "iris")))) }) -testthat::test_that("data_extract_spec returns select_spec with multiple set to TRUE", { - des <- data_extract_spec("ADSL") - testthat::expect_identical( - names(des$select), - names(formals(select_spec)) - ) - testthat::expect_equal(class(des$select$choices), c("delayed_variable_choices", "delayed_data", "choices_labeled")) - testthat::expect_true(des$select$multiple) - testthat::expect_null(des$select$selected) - testthat::expect_null(des$select$always_selected) - testthat::expect_false(des$select$fixed) - testthat::expect_equal(des$select$label, "Select") -}) - -# with resolve_delayed -testthat::test_that("delayed data_extract_spec works - resolve_delayed", { - set.seed(1) - ADSL <- data.frame( - USUBJID = letters[1:10], - SEX = sample(c("F", "M", "U"), 10, replace = TRUE), - BMRKR1 = rnorm(10), - BMRKR2 = sample(c("L", "M", "H"), 10, replace = TRUE), - stringsAsFactors = FALSE - ) - attr(ADSL, "keys") <- c("STUDYID", "USUBJID") - - filter_normal <- filter_spec( - vars = variable_choices(ADSL, "SEX"), - sep = "-", - choices = value_choices(ADSL, "SEX", "SEX"), - selected = "F", - multiple = FALSE - ) - - filter_delayed <- filter_spec( - vars = variable_choices("ADSL", "SEX"), - sep = "-", - choices = value_choices("ADSL", "SEX", "SEX"), - selected = "F", - multiple = FALSE - ) - - select_normal <- select_spec( - choices = variable_choices(ADSL, c("BMRKR1", "BMRKR2")), - selected = "BMRKR1", - multiple = FALSE, - fixed = FALSE, - ordered = FALSE - ) - - select_delayed <- select_spec( - choices = variable_choices("ADSL", c("BMRKR1", "BMRKR2")), - selected = "BMRKR1", - multiple = FALSE, - fixed = FALSE, - ordered = FALSE - ) - - expected_spec <- data_extract_spec( - dataname = "ADSL", - select = select_normal, - filter = filter_normal - ) - - # obtained via delayed approach - delayed_spec <- data_extract_spec( - dataname = "ADSL", - select = select_delayed, - filter = filter_delayed - ) - - mix1 <- data_extract_spec( - dataname = "ADSL", - select = select_delayed, - filter = filter_normal - ) - - mix2 <- data_extract_spec( - dataname = "ADSL", - select = select_normal, - filter = filter_delayed - ) - - mix3 <- data_extract_spec( - dataname = "ADSL", - select = select_delayed, - filter = list(filter_delayed, filter_normal) - ) - - testthat::expect_equal(class(delayed_spec), c("delayed_data_extract_spec", "delayed_data", "data_extract_spec")) - testthat::expect_equal(class(mix1), c("delayed_data_extract_spec", "delayed_data", "data_extract_spec")) - testthat::expect_equal(class(mix2), c("delayed_data_extract_spec", "delayed_data", "data_extract_spec")) - testthat::expect_equal(class(mix3), c("delayed_data_extract_spec", "delayed_data", "data_extract_spec")) - - testthat::expect_equal(names(expected_spec), names(delayed_spec)) - testthat::expect_equal(names(expected_spec), names(mix1)) - testthat::expect_equal(names(expected_spec), names(mix2)) - testthat::expect_equal(names(expected_spec), names(mix3)) - - - isolate({ - data_list <- list(ADSL = reactive(ADSL)) - testthat::expect_identical(expected_spec, resolve_delayed(delayed_spec, data_list)) - testthat::expect_identical(expected_spec, resolve_delayed(mix1, data_list)) - testthat::expect_identical(expected_spec, resolve_delayed(mix2, data_list)) - - mix3_res <- resolve_delayed(mix3, data_list) - }) - - testthat::expect_identical(expected_spec$filter[[1]], mix3_res$filter[[1]]) - testthat::expect_identical(expected_spec$filter[[1]], mix3_res$filter[[2]]) - mix3_res$filter <- NULL - expected_spec$filter <- NULL - testthat::expect_identical(expected_spec, mix3_res) +testthat::test_that("resolve.data_extract_spec multiplies when dataname is 'all'", { + # todo: make sure that data in variable/value_choices is different or force rewrite (as it is now) }) -testthat::test_that("delayed version of data_extract_spec - resolve_delayed", { - data_list <- list(ADSL = reactive(ADSL)) - keys_list <- list(ADSL = c("STUDYID", "USUBJID")) - # hard-coded subset - obj <- data_extract_spec( - "ADSL", - select = select_spec(vc_hard, selected = vc_hard_short, multiple = FALSE), - filter = filter_spec( - vars = variable_choices("ADSL", subset = "ARMCD"), - choices = value_choices("ADSL", var_choices = "ARMCD", var_label = "ARM", subset = c("ARM A", "ARM B")), - selected = value_choices("ADSL", var_choices = "ARMCD", var_label = "ARM", subset = "ARM A"), - multiple = FALSE - ) - ) - - res_obj <- isolate(resolve_delayed(obj, datasets = data_list, keys = keys_list)) - exp_obj <- data_extract_spec( - "ADSL", - select = select_spec(variable_choices(ADSL, c("STUDYID", "USUBJID"), key = c("STUDYID", "USUBJID")), - selected = variable_choices(ADSL, "STUDYID", key = c("STUDYID", "USUBJID")) - ), - filter = filter_spec( - vars = variable_choices(ADSL, subset = "ARMCD", key = c("STUDYID", "USUBJID")), - choices = value_choices(ADSL, var_choices = "ARMCD", var_label = "ARM", subset = c("ARM A", "ARM B")), - selected = value_choices(ADSL, var_choices = "ARMCD", var_label = "ARM", subset = "ARM A"), - multiple = FALSE - ) - ) - - testthat::expect_equal(res_obj$select, exp_obj$select) - testthat::expect_equal(res_obj$filter[[1]]$choices, exp_obj$filter[[1]]$choices) - testthat::expect_equal(res_obj$filter[[1]]$selected, exp_obj$filter[[1]]$selected) - - - # functional subset - obj <- data_extract_spec( - "ADSL", - select = select_spec(vc_fun, selected = vc_fun_short, multiple = FALSE), - filter = filter_spec( - vars = variable_choices("ADSL", subset = "ARMCD"), - choices = value_choices( - "ADSL", - var_choices = "ARMCD", - var_label = "ARM", - subset = function(data) c("ARM A", "ARM B") - ), - selected = value_choices( - "ADSL", - var_choices = "ARMCD", - var_label = "ARM", - subset = function(data) "ARM A" - ), - multiple = FALSE - ) - ) - - res_obj <- isolate(resolve_delayed(obj, datasets = data_list, keys = keys_list)) - exp_obj <- data_extract_spec( - "ADSL", - select = select_spec(variable_choices(ADSL, c("STUDYID", "USUBJID"), key = c("STUDYID", "USUBJID")), - selected = variable_choices(ADSL, "STUDYID", key = c("STUDYID", "USUBJID")) - ), - filter = filter_spec( - vars = variable_choices(ADSL, subset = "ARMCD", key = c("STUDYID", "USUBJID")), - choices = value_choices(ADSL, var_choices = "ARMCD", var_label = "ARM", subset = c("ARM A", "ARM B")), - selected = value_choices(ADSL, var_choices = "ARMCD", var_label = "ARM", subset = "ARM A"), - multiple = FALSE - ) - ) - - testthat::expect_equal(res_obj$select, exp_obj$select) - testthat::expect_equal(res_obj$filter[[1]]$choices, exp_obj$filter[[1]]$choices) - testthat::expect_equal(res_obj$filter[[1]]$selected, exp_obj$filter[[1]]$selected) +testthat::test_that("data_extract_spec returns delayed_data_extract_spec when delayed_data in the arguments", { + testthat::expect_s3_class(data_extract_spec(select = select_spec()), "delayed_data_extract_spec") }) diff --git a/tests/testthat/test-data_extract_srv.R b/tests/testthat/test-data_extract_srv.R index 0f908971..ee0d10d8 100644 --- a/tests/testthat/test-data_extract_srv.R +++ b/tests/testthat/test-data_extract_srv.R @@ -333,7 +333,6 @@ testthat::test_that("data_extract_srv with a list of multiple data_extract_spec" ) }) - testthat::test_that("select validation", { adsl_extract <- data_extract_spec( dataname = "ADSL", @@ -382,22 +381,11 @@ testthat::test_that("select validation", { }) testthat::test_that("validation only runs on currently selected dataset's data extract spec", { - iris_extract <- data_extract_spec( - dataname = "IRIS", - select = select_spec( - label = "Select variable:", - choices = variable_choices(iris, colnames(iris)), - selected = "Sepal.Length", - multiple = TRUE, - fixed = FALSE - ) - ) - server <- function(input, output, session) { adsl_reactive_input <- data_extract_srv( id = "adsl_var", datasets = data_list, - data_extract_spec = list(iris_extract, iris_extract), + data_extract_spec = list(adsl_extract, adlb_extract), join_keys = join_keys, select_validation_rule = shinyvalidate::sv_required("Please select a variable.") ) @@ -421,8 +409,8 @@ testthat::test_that("validation only runs on currently selected dataset's data e shiny::testServer(server, { session$setInputs("adsl_var-dataset_ADSL_singleextract-select" = "") testthat::expect_match(output$out1, "Please fix errors in your selection") - session$setInputs("adsl_var-dataset" = "IRIS") - session$setInputs("adsl_var-dataset_IRIS_singleextract-select" = "Species") + session$setInputs("adsl_var-dataset" = "ADSL") + session$setInputs("adsl_var-dataset_ADSL_singleextract-select" = "Species") testthat::expect_true(iv_r()$is_valid()) }) }) diff --git a/tests/testthat/test-delayed_data_extract.R b/tests/testthat/test-delayed_data_extract.R deleted file mode 100644 index 53afd032..00000000 --- a/tests/testthat/test-delayed_data_extract.R +++ /dev/null @@ -1,162 +0,0 @@ -# Contains integration tests between delayed data loading objects and -# the objects responsible for loading, pulling and filtering the data -ADSL <- teal.data::rADSL -ADTTE <- teal.data::rADTTE -ADAE <- teal.data::rADAE -ADRS <- teal.data::rADRS - -data_list <- list(ADSL = reactive(ADSL), ADTTE = reactive(ADTTE), ADAE = reactive(ADAE), ADRS = reactive(ADRS)) -join_keys <- teal.data::default_cdisc_join_keys[c("ADSL", "ADTTE", "ADAE", "ADRS")] -primary_keys_list <- lapply(join_keys, function(x) x[[1]]) - -vc_hard <- variable_choices("ADSL", subset = c("STUDYID", "USUBJID")) -vc_hard_exp <- structure( - list(data = "ADSL", subset = c("STUDYID", "USUBJID"), key = NULL), - class = c("delayed_variable_choices", "delayed_data", "choices_labeled") -) - -vc_hard_short <- variable_choices("ADSL", subset = "STUDYID") -vc_hard_short_exp <- structure( - list(data = "ADSL", subset = "STUDYID", key = NULL), - class = c("delayed_variable_choices", "delayed_data", "choices_labeled") -) - -vc_fun <- variable_choices("ADSL", subset = function(data) colnames(data)[1:2]) -vc_fun_exp <- structure( - list(data = "ADSL", subset = function(data) colnames(data)[1:2], key = NULL), - class = c("delayed_variable_choices", "delayed_data", "choices_labeled") -) - -vc_fun_short <- variable_choices("ADSL", subset = function(data) colnames(data)[1]) -vc_fun_short_exp <- structure( - list(data = "ADSL", subset = function(data) colnames(data)[1], key = NULL), - class = c("delayed_variable_choices", "delayed_data", "choices_labeled") -) - -# Delayed data extract - single data connector with two scda dataset connectors ---- -get_continuous <- function(data) { - # example function to show selections from delayed data - names(Filter(is.numeric, data)) -} - -testthat::test_that("Delayed data extract - single data connector with two scda dataset connectors", { - x <- data_extract_spec( - dataname = "ADSL", - select = select_spec( - choices = variable_choices("ADSL", subset = get_continuous) - ) - ) - y <- data_extract_spec( - dataname = "ADAE", - select = select_spec( - choices = variable_choices("ADAE", subset = get_continuous), - selected = c("AGE: Age" = "AGE") - ) - ) - - x_expected <- data_extract_spec( - dataname = "ADSL", - select = select_spec( - choices = variable_choices(ADSL, subset = get_continuous, key = c("STUDYID", "USUBJID")), - selected = NULL - ) - ) - y_expected <- data_extract_spec( - dataname = "ADAE", - select = select_spec( - choices = variable_choices( - ADAE, - subset = get_continuous, key = c("STUDYID", "USUBJID", "ASTDTM", "AETERM", "AESEQ") - ) - ) - ) - data_list <- list(ADSL = reactive(ADSL), ADAE = reactive(ADAE)) - primary_keys_list <- list( - ADSL = c("STUDYID", "USUBJID"), - ADAE = c("STUDYID", "USUBJID", "ASTDTM", "AETERM", "AESEQ") - ) - x_result <- isolate(resolve(x, datasets = data_list, keys = primary_keys_list)) - y_result <- isolate(resolve(y, datasets = data_list, keys = primary_keys_list)) - testthat::expect_identical(x_result, x_expected) - testthat::expect_identical(y_result, y_expected) -}) - -# Delayed choices selected - single data connector with two scda dataset connectors ---- - -testthat::test_that("Delayed choices selected - single data connector with two scda dataset connectors", { - data_list <- list(ADSL = reactive(ADSL), ADAE = reactive(ADAE)) - primary_keys_list <- list( - ADSL = c("STUDYID", "USUBJID"), - ADAE = c("STUDYID", "USUBJID", "ASTDTM", "AETERM", "AESEQ") - ) - choices <- variable_choices("ADSL") - choices_result <- isolate(resolve(choices, datasets = data_list, keys = primary_keys_list)) - - choices_expected <- variable_choices(ADSL, key = c("STUDYID", "USUBJID")) - testthat::expect_identical(choices_result, choices_expected) -}) - -# Delayed data extract - filtered ---- - -testthat::test_that("Delayed data extract - filtered", { - data_list <- list(ADSL = reactive(ADSL), ADRS = reactive(ADRS)) - primary_keys_list <- list( - ADSL = c("STUDYID", "USUBJID"), - ADRS = c("STUDYID", "USUBJID", "PARAMCD", "AVISIT") - ) - - x <- data_extract_spec( - dataname = "ADSL", - select = select_spec( - choices = variable_choices("ADSL", subset = get_continuous) - ), - filter = filter_spec( - label = "Select endpoints:", - vars = "ARMCD", - choices = value_choices("ADSL", - var_choices = "ARMCD", - var_label = "ARM", - subset = function(data) levels(data$ARMCD)[1:2] - ), - selected = "ARM A", - multiple = TRUE - ) - ) - y <- data_extract_spec( - dataname = "ADRS", - select = select_spec( - choices = variable_choices("ADRS", subset = get_continuous), - selected = c("AGE: Age" = "AGE") - ) - ) - - x_expected <- data_extract_spec( - dataname = "ADSL", - select = select_spec( - choices = variable_choices(ADSL, subset = get_continuous), - selected = NULL - ), - filter = filter_spec( - label = "Select endpoints:", - vars = "ARMCD", - choices = value_choices(ADSL, - var_choices = "ARMCD", - var_label = "ARM", - subset = function(data) levels(data$ARMCD)[1:2] - ), - selected = "ARM A", - multiple = TRUE - ) - ) - y_expected <- data_extract_spec( - dataname = "ADRS", - select = select_spec( - choices = variable_choices(ADRS, subset = get_continuous) - ) - ) - - x_result <- isolate(resolve(x, datasets = data_list, primary_keys_list)) - y_result <- isolate(resolve(y, datasets = data_list, primary_keys_list)) - testthat::expect_identical(x_result, x_expected) - testthat::expect_identical(y_result, y_expected) -}) diff --git a/tests/testthat/test-filter_spec.R b/tests/testthat/test-filter_spec.R index 11640f28..9bcbfd28 100644 --- a/tests/testthat/test-filter_spec.R +++ b/tests/testthat/test-filter_spec.R @@ -1,9 +1,3 @@ -ADSL <- teal.data::rADSL -ADTTE <- teal.data::rADTTE -data_list <- list(ADSL = reactive(ADSL), ADTTE = reactive(ADTTE), ADLB = reactive(ADLB)) -join_keys <- teal.data::default_cdisc_join_keys[c("ADSL", "ADTTE", "ADLB")] -primary_keys_list <- lapply(join_keys, function(x) x[[1]]) - choices <- c("val1", "val2", "val3") choices_d <- c("val1", "val1", "val2", "val3") choices_f <- as.factor(choices) @@ -152,17 +146,12 @@ testthat::test_that("Dropping keys attribute", { }) testthat::test_that("delayed filter_spec", { + adsl_keys <- teal.data::default_cdisc_join_keys["ADSL"] set.seed(1) - ADSL <- data.frame( - USUBJID = letters[1:10], - SEX = sample(c("F", "M", "U"), 10, replace = TRUE), - stringsAsFactors = FALSE - ) - expected_spec <- filter_spec( - vars = variable_choices(ADSL, "SEX"), + vars = variable_choices(teal.data::rADSL, "SEX"), sep = "-", - choices = value_choices(ADSL, "SEX", "SEX"), + choices = value_choices(teal.data::rADSL, "SEX", "SEX"), selected = "F", multiple = FALSE ) @@ -178,14 +167,15 @@ testthat::test_that("delayed filter_spec", { testthat::expect_equal(names(expected_spec), names(delayed)) - data_list <- list(ADSL = reactive(ADSL)) - key_list <- list(ADSL = c("STUDYID", "USUBJID")) + adsl_keys <- teal.data::default_cdisc_join_keys["ASDL"] - result_spec <- isolate(resolve(delayed, data_list, key_list)) - testthat::expect_identical(expected_spec, isolate(resolve(delayed, data_list, key_list))) + result_spec <- resolve(delayed, datasets = list(ADSL = teal.data::rADSL), join_keys = adsl_keys) + testthat::expect_identical( + expected_spec, + resolve(delayed, datasets = list(ADSL = teal.data::rADSL), join_keys = adsl_keys) + ) }) - testthat::test_that("filter_spec with choices_selected where all selected in choices does not throw an error", { valid_cs <- choices_selected( choices = stats::setNames(LETTERS[1:5], paste("Letter", LETTERS[1:5])), @@ -194,7 +184,6 @@ testthat::test_that("filter_spec with choices_selected where all selected in cho testthat::expect_no_error(filter_spec(vars = valid_cs)) }) - testthat::test_that("filter_spec_internal", { testthat::expect_silent( filter_spec_internal( @@ -220,9 +209,7 @@ testthat::test_that("filter_spec_internal", { testthat::test_that("filter_spec_internal contains dataname", { ADSL <- teal.data::rADSL - x_filter <- filter_spec_internal( - vars_choices = variable_choices(ADSL) - ) + x_filter <- filter_spec_internal(vars_choices = variable_choices(ADSL)) testthat::expect_null(x_filter$dataname) @@ -235,15 +222,10 @@ testthat::test_that("filter_spec_internal contains dataname", { }) testthat::test_that("delayed filter_spec works", { + adsl_keys <- teal.data::default_cdisc_join_keys["ADSL"] set.seed(1) - ADSL <- data.frame( - USUBJID = letters[1:10], - SEX = sample(c("F", "M", "U"), 10, replace = TRUE), - stringsAsFactors = FALSE - ) - expected_spec <- filter_spec_internal( - vars_choices = variable_choices(ADSL), + vars_choices = variable_choices(teal.data::rADSL, key = c("STUDYID", "USUBJID")), vars_selected = "SEX" ) @@ -255,43 +237,17 @@ testthat::test_that("delayed filter_spec works", { testthat::expect_equal( class(delayed), - c( - "delayed_filter_spec", - "filter_spec", - "delayed_data" - ) + c("delayed_filter_spec", "filter_spec", "delayed_data") ) testthat::expect_equal(names(expected_spec), names(delayed)) - delayed$dataname <- "ADSL" - expected_spec$dataname <- "ADSL" + adsl_keys <- teal.data::default_cdisc_join_keys["ADSL"] - data_list <- list(ADSL = reactive(ADSL)) - key_list <- list(ADSL = character(0)) - - testthat::expect_identical( + testthat::expect_equal( expected_spec, - isolate(resolve(delayed, data_list, key_list)) - ) - - expected_spec <- data_extract_spec( - dataname = "ADSL", - filter = filter_spec_internal( - vars_choices = variable_choices(ADSL), - vars_selected = "SEX" - ) - ) - - delayed <- data_extract_spec( - dataname = "ADSL", - filter = filter_spec_internal( - vars_choices = variable_choices("ADSL"), - vars_selected = "SEX" - ) + resolve(delayed, list(ADSL = teal.data::rADSL), join_keys = adsl_keys) ) - - testthat::expect_identical(expected_spec, isolate(resolve(delayed, data_list, key_list))) }) vc_hard <- variable_choices("ADSL", subset = c("STUDYID", "USUBJID")) @@ -319,6 +275,7 @@ vc_fun_short_exp <- structure( ) testthat::test_that("delayed version of filter_spec", { + adsl_keys <- teal.data::default_cdisc_join_keys["ADSL"] # hard-coded vars & choices & selected obj <- filter_spec( vars = variable_choices("ADSL", subset = "ARMCD"), @@ -346,19 +303,15 @@ testthat::test_that("delayed version of filter_spec", { dataname = NULL, initialized = FALSE ), - class = c( - "delayed_filter_spec", - "filter_spec", - "delayed_data" - ) + class = c("delayed_filter_spec", "filter_spec", "delayed_data") ) ) - res_obj <- isolate(resolve(obj, datasets = data_list, keys = primary_keys_list)) + res_obj <- resolve(obj, datasets = list(ADSL = teal.data::rADSL), join_keys = adsl_keys) exp_obj <- filter_spec( - vars = variable_choices(ADSL, subset = "ARMCD"), - choices = value_choices(ADSL, var_choices = "ARMCD", var_label = "ARM", subset = c("ARM A", "ARM B")), - selected = value_choices(ADSL, var_choices = "ARMCD", var_label = "ARM", subset = "ARM A"), + vars = variable_choices(teal.data::rADSL, subset = "ARMCD"), + choices = value_choices(teal.data::rADSL, var_choices = "ARMCD", var_label = "ARM", subset = c("ARM A", "ARM B")), + selected = value_choices(teal.data::rADSL, var_choices = "ARMCD", var_label = "ARM", subset = "ARM A"), multiple = FALSE ) @@ -426,7 +379,7 @@ testthat::test_that("delayed version of filter_spec", { ) ) - res_obj <- isolate(resolve(obj, datasets = data_list, keys = primary_keys_list)) + res_obj <- resolve(obj, datasets = list(ADSL = teal.data::rADSL), join_keys = adsl_keys) # comparison not implemented, must be done individually testthat::expect_equal(res_obj$choices, exp_obj$choices) @@ -463,9 +416,9 @@ testthat::test_that("delayed_choices passed to selected select desired choices", # With resolve_delayed testthat::test_that("delayed filter_spec - resolve_delayed", { expected_spec <- filter_spec( - vars = variable_choices(ADSL, "SEX"), + vars = variable_choices(teal.data::rADSL, "SEX"), sep = "-", - choices = value_choices(ADSL, "SEX", "SEX"), + choices = value_choices(teal.data::rADSL, "SEX", "SEX"), selected = "F", multiple = FALSE ) @@ -479,8 +432,9 @@ testthat::test_that("delayed filter_spec - resolve_delayed", { multiple = FALSE ) + adsl_keys <- teal.data::default_cdisc_join_keys["ADSL"] testthat::expect_equal(names(expected_spec), names(delayed)) - result_spec <- isolate(resolve_delayed(delayed, datasets = data_list, keys = primary_keys_list)) + result_spec <- resolve_delayed(delayed, datasets = list(ADSL = teal.data::rADSL), join_keys = adsl_keys) testthat::expect_identical(expected_spec, result_spec) }) @@ -497,8 +451,9 @@ testthat::test_that( ) testthat::test_that("delayed filter_spec works - resolve_delayed", { + adsl_keys <- teal.data::default_cdisc_join_keys["ADSL"] expected_spec <- filter_spec_internal( - vars_choices = variable_choices(ADSL), + vars_choices = variable_choices(teal.data::rADSL, key = c("STUDYID", "USUBJID")), vars_selected = "SEX" ) @@ -508,29 +463,8 @@ testthat::test_that("delayed filter_spec works - resolve_delayed", { vars_selected = "SEX" ) - resolved <- isolate(resolve_delayed(delayed, datasets = data_list)) + resolved <- resolve_delayed(delayed, datasets = list(ADSL = teal.data::rADSL), join_keys = adsl_keys) testthat::expect_identical(expected_spec, resolved) - - expected_spec <- data_extract_spec( - dataname = "ADSL", - filter = filter_spec_internal( - vars_choices = variable_choices(ADSL), - vars_selected = "SEX" - ) - ) - - delayed <- data_extract_spec( - dataname = "ADSL", - filter = filter_spec_internal( - vars_choices = variable_choices("ADSL"), - vars_selected = "SEX" - ) - ) - - testthat::expect_identical( - expected_spec, - isolate(resolve_delayed(delayed, datasets = data_list)) - ) }) testthat::test_that("delayed version of filter_spec - resolve_delayed", { @@ -569,11 +503,15 @@ testthat::test_that("delayed version of filter_spec - resolve_delayed", { ) ) - res_obj <- isolate(resolve_delayed(obj, datasets = data_list, keys = primary_keys_list)) + res_obj <- resolve_delayed( + obj, + datasets = list(ADSL = teal.data::rADSL), + join_keys = teal.data::default_cdisc_join_keys + ) exp_obj <- filter_spec( - vars = variable_choices(ADSL, subset = "ARMCD"), - choices = value_choices(ADSL, var_choices = "ARMCD", var_label = "ARM", subset = c("ARM A", "ARM B")), - selected = value_choices(ADSL, var_choices = "ARMCD", var_label = "ARM", subset = "ARM A"), + vars = variable_choices(teal.data::rADSL, subset = "ARMCD"), + choices = value_choices(teal.data::rADSL, var_choices = "ARMCD", var_label = "ARM", subset = c("ARM A", "ARM B")), + selected = value_choices(teal.data::rADSL, var_choices = "ARMCD", var_label = "ARM", subset = "ARM A"), multiple = FALSE ) @@ -641,7 +579,11 @@ testthat::test_that("delayed version of filter_spec - resolve_delayed", { ) ) - res_obj <- isolate(resolve_delayed(obj, datasets = data_list, keys = primary_keys_list)) + res_obj <- resolve_delayed( + obj, + datasets = list(ADSL = teal.data::rADSL), + join_keys = teal.data::default_cdisc_join_keys + ) # comparison not implemented, must be done individually testthat::expect_equal(res_obj$choices, exp_obj$choices) diff --git a/tests/testthat/test-resolve.R b/tests/testthat/test-resolve.R index 8acd3b8f..4cc304b1 100644 --- a/tests/testthat/test-resolve.R +++ b/tests/testthat/test-resolve.R @@ -1,130 +1,3 @@ -ADSL <- teal.data::rADSL -ADTTE <- teal.data::rADTTE +testthat::test_that("resolve replaces data in delayed_variable_choices by dataname from ancestor data_extract_spec", { -arm_ref_comp <- list( - ARMCD = list( - ref = value_choices(ADTTE, var_choices = "ARMCD", var_label = "ARM", subset = "ARM A"), - comp = value_choices(ADTTE, var_choices = "ARMCD", var_label = "ARM", subset = c("ARM B", "ARM C")) - ), - ARM = list( - ref = variable_choices(ADSL, subset = "ARM"), comp = variable_choices(ADSL, subset = "ARMCD") - ), - ARM2 = list(ref = "A: Drug X", comp = c("B: Placebo", "C: Combination")) -) -arm_ref_comp_ddl <- list( - ARMCD = list( - ref = value_choices("ADTTE", var_choices = "ARMCD", var_label = "ARM", subset = "ARM A"), - comp = value_choices("ADTTE", var_choices = "ARMCD", var_label = "ARM", subset = c("ARM B", "ARM C")) - ), - ARM = list( - ref = variable_choices("ADSL", subset = "ARM"), comp = variable_choices("ADSL", subset = "ARMCD") - ), - ARM2 = list(ref = "A: Drug X", comp = c("B: Placebo", "C: Combination")) -) - -testthat::test_that("resolve_delayed_expr works correctly", { - # function assumptions check - # 1) single argument called "data" - testthat::expect_error( - resolve_delayed_expr(function() {}, ds = ADSL, is_value_choices = FALSE), - regexp = "Assertion on 'x' failed: Must have formal arguments: data.", - fixed = TRUE - ) - testthat::expect_error( - resolve_delayed_expr(function(a) {}, ds = ADSL, is_value_choices = FALSE), - regexp = "Assertion on 'x' failed: Must have formal arguments: data.", - fixed = TRUE - ) - testthat::expect_error( - resolve_delayed_expr(function(data, a) {}, ds = ADSL, is_value_choices = FALSE), - regexp = "Assertion on 'x' failed: Must have exactly 1 formal arg", - fixed = TRUE - ) - - # function assumptions check - # 2a) returning character unique vector of length <= ncol(ds) - testthat::expect_error( - resolve_delayed_expr(function(data) 1, ds = ADSL, is_value_choices = FALSE), - regexp = "must return a character vector with unique names from the available columns of the dataset" - ) - testthat::expect_error( - resolve_delayed_expr(function(data) c("a", "a"), ds = ADSL, is_value_choices = FALSE), - regexp = "must return a character vector with unique names from the available columns of the dataset" - ) - testthat::expect_error( - resolve_delayed_expr(function(data) c("a", "b"), ds = ADSL[1], is_value_choices = FALSE), - regexp = "must return a character vector with unique names from the available columns of the dataset" - ) - - # function assumptions check - # 2b) returning unique vector - testthat::expect_error( - resolve_delayed_expr(function(data) c(1, 1), ds = ADSL, is_value_choices = TRUE), - regexp = "must return a vector with unique values from the respective columns of the dataset" - ) - - # function return value check - testthat::expect_equal( - resolve_delayed_expr(function(data) c("a", "b"), ds = ADSL, is_value_choices = FALSE), - c("a", "b") - ) - testthat::expect_equal(resolve_delayed_expr(function(data) 1:2, ds = ADSL, is_value_choices = TRUE), 1:2) -}) - -testthat::test_that("resolve.list works correctly", { - data_list <- list(ADSL = reactive(ADSL), ADTTE = reactive(ADTTE)) - key_list <- list(ADSL = c("STUDYID", "USUBJID"), ADTTE = c("STUDYID", "USUBJID", "PARAMCD")) - - ddl_resolved <- isolate(resolve(arm_ref_comp_ddl, data_list, key_list)) - testthat::expect_identical(arm_ref_comp, ddl_resolved) -}) - -testthat::test_that("resolve throws error with non-reactive data.frames or unnamed list as input to datasets", { - data_list <- list(ADSL = ADSL, ADTTE = ADTTE) - key_list <- list(ADSL = c("STUDYID", "USUBJID"), ADTTE = c("STUDYID", "USUBJID", "PARAMCD")) - - testthat::expect_error( - isolate(resolve(arm_ref_comp_ddl, data_list, key_list)), - "Assertion on 'datasets' failed: May only contain the following types: {reactive}", - fixed = TRUE - ) - - data_list2 <- list(reactive(ADSL), reactive(ADTTE)) - testthat::expect_error( - isolate(resolve(arm_ref_comp_ddl, data_list2, key_list)), - "Assertion on 'datasets' failed: Must have names." - ) -}) - -testthat::test_that("resolve throws error with unnamed list or wrong names as input to keys", { - data_list <- list(ADSL = reactive(ADSL), ADTTE = reactive(ADTTE)) - key_list <- list(c("STUDYID", "USUBJID"), c("STUDYID", "USUBJID", "PARAMCD")) - - testthat::expect_error( - isolate(resolve(arm_ref_comp_ddl, data_list, key_list)), - "Assertion on 'keys' failed: Must have names." - ) - - key_list <- list(AA = c("STUDYID", "USUBJID"), ADTTE = c("STUDYID", "USUBJID", "PARAMCD")) - - testthat::expect_error( - isolate(resolve(arm_ref_comp_ddl, data_list, key_list)), - "Names must be a subset of", - fixed = TRUE - ) -}) - -testthat::test_that("resolve throws error with missing arguments", { - data_list <- list(ADSL = reactive(ADSL), ADTTE = reactive(ADTTE)) - key_list <- list(ADSL = c("STUDYID", "USUBJID"), ADTTE = c("STUDYID", "USUBJID", "PARAMCD")) - - testthat::expect_error( - isolate(resolve(arm_ref_comp_ddl, data_list)), - "argument \"keys\" is missing, with no default" - ) - - testthat::expect_error( - isolate(resolve(arm_ref_comp_ddl, keys = key_list)), - "argument \"datasets\" is missing, with no default" - ) }) diff --git a/tests/testthat/test-resolve_delayed.R b/tests/testthat/test-resolve_delayed.R index b1789eee..61699f76 100644 --- a/tests/testthat/test-resolve_delayed.R +++ b/tests/testthat/test-resolve_delayed.R @@ -4,158 +4,3 @@ adtte <- teal.data::rADTTE data_list <- list(ADSL = reactive(adsl), ADTTE = reactive(adtte)) join_keys <- teal.data::default_cdisc_join_keys[c("ADSL", "ADTTE")] primary_keys_list <- lapply(join_keys, function(keys) keys[[1]]) - -testthat::test_that("resolve_delayed_expr works correctly", { - # function assumptions check - # 1) single argument called "data" - testthat::expect_error( - resolve_delayed_expr(function() {}, ds = adsl, is_value_choices = FALSE), - regexp = "Assertion on 'x' failed: Must have formal arguments: data.", - fixed = TRUE - ) - testthat::expect_error( - resolve_delayed_expr(function(a) {}, ds = adsl, is_value_choices = FALSE), - regexp = "Assertion on 'x' failed: Must have formal arguments: data.", - fixed = TRUE - ) - testthat::expect_error( - resolve_delayed_expr(function(data, a) {}, ds = adsl, is_value_choices = FALSE), - regexp = "Assertion on 'x' failed: Must have exactly 1 formal arg", - fixed = TRUE - ) - - # function assumptions check - # 2a) returning character unique vector of length <= ncol(ds) - testthat::expect_error( - resolve_delayed_expr(function(data) 1, ds = adsl, is_value_choices = FALSE), - regexp = "must return a character vector with unique names from the available columns of the dataset" - ) - testthat::expect_error( - resolve_delayed_expr(function(data) c("a", "a"), ds = adsl, is_value_choices = FALSE), - regexp = "must return a character vector with unique names from the available columns of the dataset" - ) - testthat::expect_error( - resolve_delayed_expr(function(data) c("a", "b"), ds = adsl[1], is_value_choices = FALSE), - regexp = "must return a character vector with unique names from the available columns of the dataset" - ) - - # function assumptions check - # 2b) returning unique vector - testthat::expect_error( - resolve_delayed_expr(function(data) c(1, 1), ds = adsl, is_value_choices = TRUE), - regexp = "must return a vector with unique values from the respective columns of the dataset" - ) - - # function return value check - testthat::expect_equal( - resolve_delayed_expr(function(data) c("a", "b"), ds = adsl, is_value_choices = FALSE), - c("a", "b") - ) - testthat::expect_equal(resolve_delayed_expr(function(data) 1:2, ds = adsl, is_value_choices = TRUE), 1:2) -}) - -testthat::test_that("resolve_delayed.FilteredData works correctly", { - arm_ref_comp <- list( - ARMCD = list( - ref = value_choices(adtte, var_choices = "ARMCD", var_label = "ARM", subset = "ARM A"), - comp = value_choices(adtte, var_choices = "ARMCD", var_label = "ARM", subset = c("ARM B", "ARM C")) - ), - ARM = list( - ref = variable_choices(adsl, subset = "ARM"), comp = variable_choices(adsl, subset = "ARMCD") - ), - ARM2 = list(ref = "A: Drug X", comp = c("B: Placebo", "C: Combination")) - ) - arm_ref_comp_ddl <- list( - ARMCD = list( - ref = value_choices("ADTTE", var_choices = "ARMCD", var_label = "ARM", subset = "ARM A"), - comp = value_choices("ADTTE", var_choices = "ARMCD", var_label = "ARM", subset = c("ARM B", "ARM C")) - ), - ARM = list( - ref = variable_choices("ADSL", subset = "ARM"), comp = variable_choices("ADSL", subset = "ARMCD") - ), - ARM2 = list(ref = "A: Drug X", comp = c("B: Placebo", "C: Combination")) - ) - ddl_resolved <- isolate(resolve_delayed(arm_ref_comp_ddl, datasets = data_list, keys = primary_keys_list)) - testthat::expect_identical(arm_ref_comp, ddl_resolved) -}) - - -testthat::test_that("resolve_delayed.list works correctly with reactive objects", { - arm_ref_comp <- list( - ARMCD = list( - ref = value_choices(adtte, var_choices = "ARMCD", var_label = "ARM", subset = "ARM A"), - comp = value_choices(adtte, var_choices = "ARMCD", var_label = "ARM", subset = c("ARM B", "ARM C")) - ), - ARM = list( - ref = variable_choices(adsl, subset = "ARM"), comp = variable_choices(adsl, subset = "ARMCD") - ), - ARM2 = list(ref = "A: Drug X", comp = c("B: Placebo", "C: Combination")) - ) - arm_ref_comp_ddl <- list( - ARMCD = list( - ref = value_choices("ADTTE", var_choices = "ARMCD", var_label = "ARM", subset = "ARM A"), - comp = value_choices("ADTTE", var_choices = "ARMCD", var_label = "ARM", subset = c("ARM B", "ARM C")) - ), - ARM = list( - ref = variable_choices("ADSL", subset = "ARM"), comp = variable_choices("ADSL", subset = "ARMCD") - ), - ARM2 = list(ref = "A: Drug X", comp = c("B: Placebo", "C: Combination")) - ) - ddl_resolved <- isolate( - resolve_delayed( - arm_ref_comp_ddl, - data_list, - keys = primary_keys_list - ) - ) - testthat::expect_identical(arm_ref_comp, ddl_resolved) -}) - -testthat::test_that("resolve_delayed.list works correctly with non-reactive objects", { - data <- list(ADSL = adsl, ADTTE = reactive(adtte)) - arm_ref_comp <- list( - ARMCD = list( - ref = value_choices(adtte, var_choices = "ARMCD", var_label = "ARM", subset = "ARM A"), - comp = value_choices(adtte, var_choices = "ARMCD", var_label = "ARM", subset = c("ARM B", "ARM C")) - ), - ARM = list( - ref = variable_choices(adsl, subset = "ARM"), comp = variable_choices(adsl, subset = "ARMCD") - ), - ARM2 = list(ref = "A: Drug X", comp = c("B: Placebo", "C: Combination")) - ) - arm_ref_comp_ddl <- list( - ARMCD = list( - ref = value_choices("ADTTE", var_choices = "ARMCD", var_label = "ARM", subset = "ARM A"), - comp = value_choices("ADTTE", var_choices = "ARMCD", var_label = "ARM", subset = c("ARM B", "ARM C")) - ), - ARM = list( - ref = variable_choices("ADSL", subset = "ARM"), comp = variable_choices("ADSL", subset = "ARMCD") - ), - ARM2 = list(ref = "A: Drug X", comp = c("B: Placebo", "C: Combination")) - ) - ddl_resolved <- isolate( - resolve_delayed( - arm_ref_comp_ddl, - data, - keys = list(ADSL = c("STUDYID", "USUBJID"), ADTTE = c("STUDYID", "USUBJID", "PARAMCD")) - ) - ) - testthat::expect_identical(arm_ref_comp, ddl_resolved) -}) - - -testthat::test_that("resolving delayed choices removes selected not in choices and give a log output", { - c_s <- choices_selected( - choices = variable_choices("IRIS", c("Sepal.Length", "Sepal.Width")), - selected = variable_choices("IRIS", c("Petal.Length", "Sepal.Width")) - ) - - testthat::expect_warning( - output <- shiny::isolate({ - resolved_cs <- resolve_delayed(c_s, datasets = list(IRIS = reactive(iris))) - }), - "Removing Petal.Length from 'selected' as not in 'choices' when resolving delayed choices_selected" - ) - - testthat::expect_equal(resolved_cs$selected, stats::setNames("Sepal.Width", "Sepal.Width: Sepal.Width")) -}) diff --git a/tests/testthat/test-select_spec.R b/tests/testthat/test-select_spec.R index 0ad8f2d8..b22161e4 100644 --- a/tests/testthat/test-select_spec.R +++ b/tests/testthat/test-select_spec.R @@ -1,8 +1,3 @@ -adsl <- teal.data::rADSL -adtte <- teal.data::rADTTE -data_list <- list(ADSL = reactive(adsl), ADTTE = reactive(adtte)) -primary_keys_list <- list(ADSL = c("STUDYID", "USUBJID"), ADTTE = c("STUDYID", "USUBJID", "PARAMCD")) - testthat::test_that("Proper argument types", { choices <- c("c1", "c2", "c3") selected <- c("c1", "c2") @@ -34,6 +29,7 @@ testthat::test_that("Single choice", { testthat::expect_silent( c2 <- select_spec( choices = c("AVAL", "BMRKR1", "AGE"), + selected = first_choice(), fixed = FALSE, label = "Column" ) @@ -49,7 +45,7 @@ testthat::test_that("Single choice", { testthat::expect_false(c2$fixed) # minimal example - testthat::expect_silent(c3 <- select_spec(choices = c("AVAL", "BMRKR1", "AGE"))) + testthat::expect_silent(c3 <- select_spec(choices = c("AVAL", "BMRKR1", "AGE"), selected = first_choice())) testthat::expect_identical(class(c3), "select_spec") testthat::expect_identical(c3$choices, setNames(c("AVAL", "BMRKR1", "AGE"), c("AVAL", "BMRKR1", "AGE"))) testthat::expect_identical(c3$selected, setNames("AVAL", "AVAL")) @@ -85,10 +81,9 @@ testthat::test_that("Multiple choices", { }) testthat::test_that("resolve select_spec works", { - attr(adsl, "keys") <- c("STUDYID", "USUBJID") - + adsl_keys <- teal.data::default_cdisc_join_keys["ADSL"] expected_spec <- select_spec( - choices = variable_choices(adsl, c("BMRKR1", "BMRKR2")), + choices = variable_choices(teal.data::rADSL, c("BMRKR1", "BMRKR2"), key = c("STUDYID", "USUBJID")), selected = "BMRKR1", multiple = FALSE, fixed = FALSE @@ -107,7 +102,7 @@ testthat::test_that("resolve select_spec works", { testthat::expect_identical( expected_spec, - isolate(resolve(delayed_spec, datasets = data_list, keys = primary_keys_list)) + resolve(delayed_spec, datasets = list(ADSL = teal.data::rADSL), join_keys = adsl_keys) ) }) @@ -136,6 +131,7 @@ vc_fun_short_exp <- structure( ) testthat::test_that("delayed version of select_spec", { + adsl_keys <- teal.data::default_cdisc_join_keys["ADSL"] # hard-coded choices & selected obj <- select_spec(vc_hard, selected = vc_hard_short, multiple = FALSE) testthat::expect_equal( @@ -154,10 +150,10 @@ testthat::test_that("delayed version of select_spec", { ) ) - res_obj <- isolate(resolve(obj, datasets = data_list, keys = primary_keys_list)) + res_obj <- resolve(obj, datasets = list(ADSL = teal.data::rADSL), join_keys = adsl_keys) exp_obj <- select_spec( - variable_choices(adsl, subset = c("STUDYID", "USUBJID"), key = c("STUDYID", "USUBJID")), - selected = variable_choices(adsl, "STUDYID", key = c("STUDYID", "USUBJID")) + variable_choices(teal.data::rADSL, subset = c("STUDYID", "USUBJID"), key = c("STUDYID", "USUBJID")), + selected = variable_choices(teal.data::rADSL, "STUDYID", key = c("STUDYID", "USUBJID")) ) testthat::expect_equal(res_obj, exp_obj) @@ -179,7 +175,7 @@ testthat::test_that("delayed version of select_spec", { ) ) - res_obj <- isolate(resolve(obj, datasets = data_list, keys = primary_keys_list)) + res_obj <- resolve(obj, datasets = list(ADSL = teal.data::rADSL), join_keys = adsl_keys) testthat::expect_equal(res_obj, exp_obj) }) @@ -212,7 +208,7 @@ testthat::test_that("multiple is set to TRUE if all_choices() is passed to selec }) testthat::test_that("default values", { - test <- select_spec("a") + test <- select_spec(choices = c("a", "b")) testthat::expect_identical(test$selected, c(a = "a")) testthat::expect_false(test$multiple) testthat::expect_false(test$fixed) @@ -223,10 +219,9 @@ testthat::test_that("default values", { # With resolve_delayed testthat::test_that("resolve_delayed select_spec works - resolve_delayed", { - attr(adsl, "keys") <- c("STUDYID", "USUBJID") - + adsl_keys <- teal.data::default_cdisc_join_keys["ADSL"] expected_spec <- select_spec( - choices = variable_choices(adsl, c("BMRKR1", "BMRKR2")), + choices = variable_choices(teal.data::rADSL, c("BMRKR1", "BMRKR2"), key = c("STUDYID", "USUBJID")), selected = "BMRKR1", multiple = FALSE, fixed = FALSE @@ -245,12 +240,13 @@ testthat::test_that("resolve_delayed select_spec works - resolve_delayed", { testthat::expect_identical( expected_spec, - isolate(resolve_delayed(delayed_spec, datasets = data_list, keys = primary_keys_list)) + resolve_delayed(delayed_spec, datasets = list(ADSL = teal.data::rADSL), join_keys = adsl_keys) ) }) testthat::test_that("delayed version of select_spec - resolve_delayed", { + adsl_keys <- teal.data::default_cdisc_join_keys["ADSL"] # hard-coded choices & selected obj <- select_spec(vc_hard, selected = vc_hard_short, multiple = FALSE) testthat::expect_equal( @@ -269,10 +265,10 @@ testthat::test_that("delayed version of select_spec - resolve_delayed", { ) ) - res_obj <- isolate(resolve_delayed(obj, datasets = data_list, keys = primary_keys_list)) + res_obj <- resolve_delayed(obj, datasets = list(ADSL = teal.data::rADSL), join_keys = adsl_keys) exp_obj <- select_spec( - variable_choices(adsl, subset = c("STUDYID", "USUBJID"), key = c("STUDYID", "USUBJID")), - selected = variable_choices(adsl, "STUDYID", key = c("STUDYID", "USUBJID")) + variable_choices(teal.data::rADSL, subset = c("STUDYID", "USUBJID"), key = c("STUDYID", "USUBJID")), + selected = variable_choices(teal.data::rADSL, "STUDYID", key = c("STUDYID", "USUBJID")) ) testthat::expect_equal(res_obj, exp_obj) @@ -295,6 +291,6 @@ testthat::test_that("delayed version of select_spec - resolve_delayed", { ) - res_obj <- isolate(resolve_delayed(obj, datasets = data_list, keys = primary_keys_list)) + res_obj <- resolve_delayed(obj, datasets = list(ADSL = teal.data::rADSL), join_keys = adsl_keys) testthat::expect_equal(res_obj, exp_obj) }) diff --git a/tests/testthat/test-value_choices.R b/tests/testthat/test-value_choices.R index c16266bc..3eb565f6 100644 --- a/tests/testthat/test-value_choices.R +++ b/tests/testthat/test-value_choices.R @@ -1,8 +1,3 @@ -ADSL <- teal.data::rADSL -ADTTE <- teal.data::rADTTE -data_list <- list(ADSL = reactive(ADSL), ADTTE = reactive(ADTTE)) -primary_keys_list <- list(ADSL = c("STUDYID", "USUBJID"), ADTTE = c("STUDYID", "USUBJID", "PARAMCD")) - testthat::test_that("Will output warnings when value_choices applied on datasets with missing values and / or labels", { data <- data.frame( A = c(1, 2, 3), @@ -43,10 +38,10 @@ testthat::test_that("delayed version of value_choices", { ) ) - res_obj <- isolate(resolve(obj, datasets = data_list, keys = primary_keys_list)) + res_obj <- resolve(obj, datasets = list(ADSL = teal.data::rADSL), join_keys = teal.data::default_cdisc_join_keys) testthat::expect_equal( res_obj, - value_choices(ADSL, var_choices = "ARMCD", var_label = "ARM", subset = c("ARM A", "ARM B")) + value_choices(teal.data::rADSL, var_choices = "ARMCD", var_label = "ARM", subset = c("ARM A", "ARM B")) ) # functional subset @@ -74,10 +69,10 @@ testthat::test_that("delayed version of value_choices", { ) ) - res_obj <- isolate(resolve(obj, datasets = data_list, keys = primary_keys_list)) + res_obj <- resolve(obj, datasets = list(ADSL = teal.data::rADSL), join_keys = teal.data::default_cdisc_join_keys) testthat::expect_equal( res_obj, - value_choices(ADSL, + value_choices(teal.data::rADSL, var_choices = "ARMCD", var_label = "ARM", subset = function(data) { levels(data$ARMCD)[1:2] @@ -114,10 +109,10 @@ testthat::test_that("delayed version of value_choices", { ) ) - res_obj <- isolate(resolve(obj, datasets = data_list, keys = primary_keys_list)) + res_obj <- resolve(obj, datasets = list(ADSL = teal.data::rADSL), join_keys = teal.data::default_cdisc_join_keys) testthat::expect_equal( res_obj, - value_choices(ADSL, + value_choices(teal.data::rADSL, var_choices = c("ARMCD", "BMRKR2"), var_label = c("ARM", "BMRKR2"), subset = combine_armcd_bmrkr2 ) @@ -145,10 +140,13 @@ testthat::test_that("delayed version of value_choices - resolve_delayed", { ) ) - res_obj <- isolate(resolve_delayed(obj, datasets = data_list, keys = primary_keys_list)) + res_obj <- resolve_delayed( + obj, + datasets = list(ADSL = teal.data::rADSL), join_keys = teal.data::default_cdisc_join_keys + ) testthat::expect_equal( res_obj, - value_choices(ADSL, var_choices = "ARMCD", var_label = "ARM", subset = c("ARM A", "ARM B")) + value_choices(teal.data::rADSL, var_choices = "ARMCD", var_label = "ARM", subset = c("ARM A", "ARM B")) ) @@ -177,10 +175,13 @@ testthat::test_that("delayed version of value_choices - resolve_delayed", { ) ) - res_obj <- isolate(resolve_delayed(obj, datasets = data_list, keys = primary_keys_list)) + res_obj <- resolve_delayed( + obj, + datasets = list(ADSL = teal.data::rADSL), join_keys = teal.data::default_cdisc_join_keys + ) testthat::expect_equal( res_obj, - value_choices(ADSL, + value_choices(teal.data::rADSL, var_choices = "ARMCD", var_label = "ARM", subset = function(data) { levels(data$ARMCD)[1:2] @@ -218,10 +219,13 @@ testthat::test_that("delayed version of value_choices - resolve_delayed", { ) ) - res_obj <- isolate(resolve_delayed(obj, datasets = data_list, keys = primary_keys_list)) + res_obj <- resolve_delayed( + obj, + datasets = list(ADSL = teal.data::rADSL), join_keys = teal.data::default_cdisc_join_keys + ) testthat::expect_equal( res_obj, - value_choices(ADSL, + value_choices(teal.data::rADSL, var_choices = c("ARMCD", "BMRKR2"), var_label = c("ARM", "BMRKR2"), subset = combine_armcd_bmrkr2 ) diff --git a/tests/testthat/test-variable_choices.R b/tests/testthat/test-variable_choices.R index f1dddb33..0a77500d 100644 --- a/tests/testthat/test-variable_choices.R +++ b/tests/testthat/test-variable_choices.R @@ -1,129 +1,58 @@ -ADSL <- teal.data::rADSL -ADTTE <- teal.data::rADTTE -data_list <- list(ADSL = reactive(ADSL), ADTTE = reactive(ADTTE)) -primary_keys_list <- list(ADSL = c("STUDYID", "USUBJID"), ADTTE = c("STUDYID", "USUBJID", "PARAMCD")) - -test_that("Can create variable_choices with datasets with no or missing labels", { - example_data <- data.frame(USUBJID = 1:2, STUDYID = 1:1) - - # no labels given - choice_1 <- variable_choices(example_data, fill = TRUE) - testthat::expect_equal(names(choice_1), c("USUBJID: USUBJID", "STUDYID: STUDYID")) - - # one missing label - missing_one_label_data <- example_data - teal.data::col_labels(missing_one_label_data) <- c(as.character(NA), "Label") - choice_2 <- variable_choices(missing_one_label_data, fill = FALSE) - testthat::expect_equal(names(choice_2), c("USUBJID: Label Missing", "STUDYID: Label")) - - # all missing label - missing_two_label_data <- example_data - teal.data::col_labels(missing_two_label_data) <- c(as.character(NA), as.character(NA)) - choice_2 <- variable_choices(missing_two_label_data, fill = FALSE) - testthat::expect_equal(names(choice_2), c("USUBJID: Label Missing", "STUDYID: Label Missing")) +testthat::test_that("variable_choices returns variable_choices", { + testthat::expect_s3_class(variable_choices(), "choices_labeled") }) -test_that("delayed version of variable_choices", { - # hard-coded subset - obj <- variable_choices("ADSL", subset = c("SEX", "ARMCD", "COUNTRY")) - testthat::expect_equal( - obj, - structure( - list(data = "ADSL", subset = c("SEX", "ARMCD", "COUNTRY"), key = NULL), - class = c("delayed_variable_choices", "delayed_data", "choices_labeled") - ) - ) - - data_list <- list(ADSL = reactive(ADSL), ADTTE = reactive(ADTTE)) - key_list <- list(ADSL = c("STUDYID", "USUBJID"), ADTTE = c("STUDYID", "USUBJID", "PARAMCD")) - - res_obj <- isolate(resolve(obj, datasets = data_list, keys = key_list)) - testthat::expect_equal( - res_obj, - variable_choices(ADSL, subset = c("SEX", "ARMCD", "COUNTRY")) - ) - - # functional subset - obj <- variable_choices("ADSL", subset = function(data) colnames(data)[1:2]) - testthat::expect_equal( - obj, - structure( - list(data = "ADSL", subset = function(data) colnames(data)[1:2], key = NULL), - class = c("delayed_variable_choices", "delayed_data", "choices_labeled") - ) - ) - - res_obj <- isolate(resolve(obj, datasets = data_list, keys = key_list)) - testthat::expect_equal( - res_obj, - variable_choices(ADSL, subset = colnames(ADSL)[1:2], key = c("STUDYID", "USUBJID")) - ) - - # non-null key value - obj <- variable_choices("ADSL", key = c("USUBJID", "STUDYID")) - testthat::expect_equal( - obj, - structure( - list(data = "ADSL", subset = NULL, key = c("USUBJID", "STUDYID")), - class = c("delayed_variable_choices", "delayed_data", "choices_labeled") - ) - ) +testthat::test_that("variable_choices accepts data to be string or data.frame with cols", { + testthat::expect_no_error(variable_choices(data = "all")) + testthat::expect_no_error(variable_choices(data = mtcars)) + testthat::expect_error(variable_choices(data = NULL)) + testthat::expect_error(variable_choices(data = data.frame())) + testthat::expect_error(variable_choices(data = c("a", "b"))) +}) - res_obj <- isolate(resolve(obj, datasets = data_list, keys = key_list)) - testthat::expect_equal( - res_obj, - variable_choices(ADSL, key = c("USUBJID", "STUDYID")) - ) +testthat::test_that("variable_choices accepts subset to be character or a function. Both checked against colnames", { + testthat::expect_no_error(variable_choices(iris, c("Species", "Sepal.Length"))) + testthat::expect_no_error(variable_choices(iris, subset = function(data) colnames(data))) + testthat::expect_error(variable_choices(iris, c("Species", "idontexist")), "Must be a subset of") }) +testthat::test_that("variable_choices accepts subset to be character or a function when data is NULL", { + testthat::expect_no_error(variable_choices(subset = c("Species", "Sepal.Length"))) + testthat::expect_no_error(variable_choices(subset = function(data) colnames(data))) + testthat::expect_no_error(variable_choices(subset = c("Species", "idontexist"))) + testthat::expect_no_error(variable_choices(subset = function(data) c("Species", "idontexist"))) +}) -test_that("delayed version of variable_choices - resolve_delayed", { - # hard-coded subset - obj <- variable_choices("ADSL", subset = c("SEX", "ARMCD", "COUNTRY")) - testthat::expect_equal( - obj, - structure( - list(data = "ADSL", subset = c("SEX", "ARMCD", "COUNTRY"), key = NULL), - class = c("delayed_variable_choices", "delayed_data", "choices_labeled") - ) - ) +testthat::test_that("variable_choices has defaults for all arguments", { + testthat::expect_no_error(variable_choices()) +}) - res_obj <- isolate(resolve_delayed(obj, datasets = data_list, keys = primary_keys_list)) - testthat::expect_equal( - res_obj, - variable_choices(ADSL, subset = c("SEX", "ARMCD", "COUNTRY")) +testthat::test_that("variable_choices subset function is evaluated when data is eager", { + testthat::expect_identical( + variable_choices(iris, subset = function(data) names(data)), + variable_choices(iris, subset = colnames(iris)) ) + testthat::expect_error(variable_choices(iris, subset = function(data) c("idontexist")), "Must be a subset of") +}) - - # functional subset - obj <- variable_choices("ADSL", subset = function(data) colnames(data)[1:2]) - testthat::expect_equal( - obj, - structure( - list(data = "ADSL", subset = function(data) colnames(data)[1:2], key = NULL), - class = c("delayed_variable_choices", "delayed_data", "choices_labeled") - ) +testthat::test_that("resolved delayed_variable_choices is identical to variable_choices specified with data", { + testthat::expect_identical( + resolve(variable_choices(), datasets = list(iris = iris)), + variable_choices(iris, subset = function(data) names(data)) ) - - res_obj <- isolate(resolve_delayed(obj, datasets = data_list, keys = primary_keys_list)) - testthat::expect_equal( - res_obj, - variable_choices(ADSL, subset = colnames(ADSL)[1:2], key = c("STUDYID", "USUBJID")) + testthat::expect_identical( + resolve(variable_choices(subset = c("Species", "Sepal.Length")), datasets = list(iris = iris)), + variable_choices(iris, subset = c("Species", "Sepal.Length")) ) +}) - # non-null key value - obj <- variable_choices("ADSL", key = c("USUBJID", "STUDYID")) - testthat::expect_equal( - obj, - structure( - list(data = "ADSL", subset = NULL, key = c("USUBJID", "STUDYID")), - class = c("delayed_variable_choices", "delayed_data", "choices_labeled") - ) +testthat::test_that("resolving delayed_variable_choices throws the error when subset isn't a colname", { + testthat::expect_error( + resolve(variable_choices(subset = function(data) "idontexist"), datasets = list(iris = iris)), + "Must be a subset of" ) - - res_obj <- isolate(resolve_delayed(obj, datasets = data_list, keys = primary_keys_list)) - testthat::expect_equal( - res_obj, - variable_choices(ADSL, key = c("USUBJID", "STUDYID")) + testthat::expect_error( + resolve(variable_choices(subset = "idontexist"), datasets = list(iris = iris)), + "Must be a subset of" ) })