-
-
Notifications
You must be signed in to change notification settings - Fork 50
improve covr tests #1646
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
improve covr tests #1646
Changes from all commits
133d6f7
9d9480b
0e628aa
5c559e2
71a458e
f62099e
8053af7
99381fb
d638012
cde50df
e306059
0df407d
54f20ce
06897df
c008a08
ff8d146
db4bbd6
2b9ccdb
a6c74f8
57da7ec
2c8aab8
084482e
0dd71fb
3e55ac8
176d8aa
408e990
b160fa3
74a2709
89faa70
6031170
21afa04
88fe006
35781ac
d5f0305
9e674a7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| R/module_teal_with_splash.R | ||
| R/tdata.R | ||
| R/landing_popup_module.R | ||
| R/show_rcode_modal.R | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -189,128 +189,17 @@ need_bookmarking <- function(modules) { | |
| #' @keywords internal | ||
| #' | ||
| restoreValue <- function(value, default) { # nolint: object_name. | ||
| checkmate::assert_character("value") | ||
| checkmate::assert_character(value) | ||
| session_default <- shiny::getDefaultReactiveDomain() | ||
| session_parent <- .subset2(session_default, "parent") | ||
| session <- if (is.null(session_parent)) session_default else session_parent | ||
|
|
||
| if (isTRUE(session$restoreContext$active) && exists(value, session$restoreContext$values, inherits = FALSE)) { | ||
| session$restoreContext$values[[value]] | ||
| } else { | ||
| default | ||
| } | ||
| } | ||
|
|
||
| #' Compare bookmarks. | ||
| #' | ||
| #' Test if two bookmarks store identical state. | ||
| #' | ||
| #' `input` environments are compared one variable at a time and if not identical, | ||
| #' values in both bookmarks are reported. States of `datatable`s are stripped | ||
| #' of the `time` element before comparing because the time stamp is always different. | ||
| #' The contents themselves are not printed as they are large and the contents are not informative. | ||
| #' Elements present in one bookmark and absent in the other are also reported. | ||
| #' Differences are printed as messages. | ||
| #' | ||
| #' `values` environments are compared with `all.equal`. | ||
| #' | ||
| #' @section How to use: | ||
| #' Open an application, change relevant inputs (typically, all of them), and create a bookmark. | ||
| #' Then open that bookmark and immediately create a bookmark of that. | ||
| #' If restoring bookmarks occurred properly, the two bookmarks should store the same state. | ||
| #' | ||
| #' | ||
| #' @param book1,book2 bookmark directories stored in `shiny_bookmarks/`; | ||
| #' default to the two most recently modified directories | ||
| #' | ||
| #' @return | ||
| #' Invisible `NULL` if bookmarks are identical or if there are no bookmarks to test. | ||
| #' `FALSE` if inconsistencies are detected. | ||
| #' | ||
| #' @keywords internal | ||
| #' | ||
| bookmarks_identical <- function(book1, book2) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| if (!dir.exists("shiny_bookmarks")) { | ||
| message("no bookmark directory") | ||
| return(invisible(NULL)) | ||
| } | ||
|
|
||
| ans <- TRUE | ||
|
|
||
| if (missing(book1) && missing(book2)) { | ||
| dirs <- list.dirs("shiny_bookmarks", recursive = FALSE) | ||
| bookmarks_sorted <- basename(rev(dirs[order(file.mtime(dirs))])) | ||
| if (length(bookmarks_sorted) < 2L) { | ||
| message("no bookmarks to compare") | ||
| return(invisible(NULL)) | ||
| } | ||
| book1 <- bookmarks_sorted[2L] | ||
| book2 <- bookmarks_sorted[1L] | ||
| } else { | ||
| if (!dir.exists(file.path("shiny_bookmarks", book1))) stop(book1, " not found") | ||
| if (!dir.exists(file.path("shiny_bookmarks", book2))) stop(book2, " not found") | ||
| } | ||
|
|
||
| book1_input <- readRDS(file.path("shiny_bookmarks", book1, "input.rds")) | ||
| book2_input <- readRDS(file.path("shiny_bookmarks", book2, "input.rds")) | ||
|
|
||
| elements_common <- intersect(names(book1_input), names(book2_input)) | ||
| dt_states <- grepl("_state$", elements_common) | ||
| if (any(dt_states)) { | ||
| for (el in elements_common[dt_states]) { | ||
| book1_input[[el]][["time"]] <- NULL | ||
| book2_input[[el]][["time"]] <- NULL | ||
| } | ||
| } | ||
|
|
||
| identicals <- mapply(identical, book1_input[elements_common], book2_input[elements_common]) | ||
| non_identicals <- names(identicals[!identicals]) | ||
| compares <- sprintf("$ %s:\t%s --- %s", non_identicals, book1_input[non_identicals], book2_input[non_identicals]) | ||
| if (length(compares) != 0L) { | ||
| message("common elements not identical: \n", paste(compares, collapse = "\n")) | ||
| ans <- FALSE | ||
| } | ||
|
|
||
| elements_boook1 <- setdiff(names(book1_input), names(book2_input)) | ||
| if (length(elements_boook1) != 0L) { | ||
| dt_states <- grepl("_state$", elements_boook1) | ||
| if (any(dt_states)) { | ||
| for (el in elements_boook1[dt_states]) { | ||
| if (is.list(book1_input[[el]])) book1_input[[el]] <- "--- data table state ---" | ||
| } | ||
| } | ||
| excess1 <- sprintf("$ %s:\t%s", elements_boook1, book1_input[elements_boook1]) | ||
| message("elements only in book1: \n", paste(excess1, collapse = "\n")) | ||
| ans <- FALSE | ||
| } | ||
|
|
||
| elements_boook2 <- setdiff(names(book2_input), names(book1_input)) | ||
| if (length(elements_boook2) != 0L) { | ||
| dt_states <- grepl("_state$", elements_boook1) | ||
| if (any(dt_states)) { | ||
| for (el in elements_boook1[dt_states]) { | ||
| if (is.list(book2_input[[el]])) book2_input[[el]] <- "--- data table state ---" | ||
| } | ||
| } | ||
| excess2 <- sprintf("$ %s:\t%s", elements_boook2, book2_input[elements_boook2]) | ||
| message("elements only in book2: \n", paste(excess2, collapse = "\n")) | ||
| ans <- FALSE | ||
| } | ||
|
|
||
| book1_values <- readRDS(file.path("shiny_bookmarks", book1, "values.rds")) | ||
| book2_values <- readRDS(file.path("shiny_bookmarks", book2, "values.rds")) | ||
|
|
||
| if (!isTRUE(all.equal(book1_values, book2_values))) { | ||
| message("different values detected") | ||
| message("choices for numeric filters MAY be different, see RangeFilterState$set_choices") | ||
| ans <- FALSE | ||
| } | ||
|
|
||
| if (ans) message("perfect!") | ||
| invisible(NULL) | ||
| } | ||
|
|
||
|
|
||
| # Replacement for [base::rapply] which doesn't handle NULL values - skips the evaluation | ||
| # of the function and returns NULL for given element. | ||
| rapply2 <- function(x, f) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -286,32 +286,6 @@ methods::setOldClass("reactivevalues") | |
| invisible(.self) | ||
| }) | ||
| }, | ||
| slices_deactivate_all = function(module_label) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed as this method (in private class) is never used in whole NEST project. Please |
||
| shiny::isolate({ | ||
| new_slices <- .self$all_slices() | ||
| old_mapping <- attr(new_slices, "mapping") | ||
|
|
||
| new_mapping <- if (.self$is_module_specific()) { | ||
| new_module_mapping <- setNames(nm = module_label, list(character(0))) | ||
| modifyList(old_mapping, new_module_mapping) | ||
| } else if (missing(module_label)) { | ||
| lapply( | ||
| attr(.self$all_slices(), "mapping"), | ||
| function(x) character(0) | ||
| ) | ||
| } else { | ||
| old_mapping[[module_label]] <- character(0) | ||
| old_mapping | ||
| } | ||
|
|
||
| if (!identical(new_mapping, old_mapping)) { | ||
| logger::log_debug(".slicesGlobal@slices_deactivate_all: deactivating all slices.") | ||
| attr(new_slices, "mapping") <- new_mapping | ||
| .self$all_slices(new_slices) | ||
| } | ||
| invisible(.self) | ||
| }) | ||
| }, | ||
| slices_active = function(mapping_elem) { | ||
| shiny::isolate({ | ||
| if (.self$is_module_specific()) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,140 +21,24 @@ | |
| #' (except error 1). | ||
| #' | ||
| #' @inheritParams module_teal | ||
| #' @param data_module (`teal_data_module`) | ||
| #' @param modules (`teal_modules` or `teal_module`) For `datanames` validation purpose | ||
| #' @param validate_shiny_silent_error (`logical`) If `TRUE`, then `shiny.silent.error` is validated and | ||
| #' @param is_transform_failed (`reactiveValues`) contains `logical` flags named after each transformator. | ||
| #' Help to determine if any previous transformator failed, so that following transformators can be disabled | ||
| #' and display a generic failure message. | ||
| #' | ||
| #' @return `reactive` `teal_data` | ||
| #' | ||
| #' @rdname module_teal_data | ||
| #' @name module_teal_data | ||
| #' @rdname module_validate_error | ||
| #' @name module_validate_error | ||
| #' @keywords internal | ||
| NULL | ||
|
|
||
| #' @rdname module_teal_data | ||
| #' @aliases ui_teal_data | ||
| #' @note | ||
| #' `ui_teal_data_module` was renamed from `ui_teal_data`. | ||
| ui_teal_data_module <- function(id, data_module = function(id) NULL) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed as they are never used:
|
||
| checkmate::assert_string(id) | ||
| checkmate::assert_function(data_module, args = "id") | ||
| ns <- NS(id) | ||
|
|
||
| shiny::tagList( | ||
| tags$div(id = ns("wrapper"), data_module(id = ns("data"))), | ||
| ui_validate_reactive_teal_data(ns("validate")) | ||
| ) | ||
| } | ||
|
|
||
| #' @rdname module_teal_data | ||
| #' @aliases srv_teal_data | ||
| #' @note | ||
| #' `srv_teal_data_module` was renamed from `srv_teal_data`. | ||
| srv_teal_data_module <- function(id, | ||
| data_module = function(id) NULL, | ||
| modules = NULL, | ||
| validate_shiny_silent_error = TRUE, | ||
| is_transform_failed = reactiveValues()) { | ||
| checkmate::assert_string(id) | ||
| checkmate::assert_function(data_module, args = "id") | ||
| checkmate::assert_multi_class(modules, c("teal_modules", "teal_module"), null.ok = TRUE) | ||
| checkmate::assert_class(is_transform_failed, "reactivevalues") | ||
|
|
||
| moduleServer(id, function(input, output, session) { | ||
| logger::log_debug("srv_teal_data_module initializing.") | ||
| is_transform_failed[[id]] <- FALSE | ||
| module_out <- data_module(id = "data") | ||
| try_module_out <- reactive(tryCatch(module_out(), error = function(e) e)) | ||
| observeEvent(try_module_out(), { | ||
| if (!inherits(try_module_out(), "teal_data")) { | ||
| is_transform_failed[[id]] <- TRUE | ||
| } else { | ||
| is_transform_failed[[id]] <- FALSE | ||
| } | ||
| }) | ||
|
|
||
| is_previous_failed <- reactive({ | ||
| idx_this <- which(names(is_transform_failed) == id) | ||
| is_transform_failed_list <- reactiveValuesToList(is_transform_failed) | ||
| idx_failures <- which(unlist(is_transform_failed_list)) | ||
| any(idx_failures < idx_this) | ||
| }) | ||
|
|
||
| observeEvent(is_previous_failed(), { | ||
| if (is_previous_failed()) { | ||
| shinyjs::disable("wrapper") | ||
| } else { | ||
| shinyjs::enable("wrapper") | ||
| } | ||
| }) | ||
|
|
||
| srv_validate_reactive_teal_data( | ||
| "validate", | ||
| data = try_module_out, | ||
| modules = modules, | ||
| validate_shiny_silent_error = validate_shiny_silent_error, | ||
| hide_validation_error = is_previous_failed | ||
| ) | ||
| }) | ||
| } | ||
|
|
||
| #' @rdname module_teal_data | ||
| ui_validate_reactive_teal_data <- function(id) { | ||
| ns <- NS(id) | ||
| tags$div( | ||
| div( | ||
| id = ns("validate_messages"), | ||
| class = "teal_validated", | ||
| ui_validate_error(ns("silent_error")), | ||
| ui_check_class_teal_data(ns("class_teal_data")), | ||
| ui_check_module_datanames(ns("shiny_warnings")) | ||
| ), | ||
| div( | ||
| class = "teal_validated", | ||
| uiOutput(ns("previous_failed")) | ||
| ) | ||
| ) | ||
| } | ||
|
|
||
| #' @rdname module_teal_data | ||
| srv_validate_reactive_teal_data <- function(id, # nolint: object_length | ||
| data, | ||
| modules = NULL, | ||
| validate_shiny_silent_error = FALSE, | ||
| hide_validation_error = reactive(FALSE)) { | ||
| checkmate::assert_string(id) | ||
| checkmate::assert_multi_class(modules, c("teal_modules", "teal_module"), null.ok = TRUE) | ||
| checkmate::assert_flag(validate_shiny_silent_error) | ||
|
|
||
| moduleServer(id, function(input, output, session) { | ||
| # there is an empty reactive cycle on `init` and `data` has `shiny.silent.error` class | ||
| srv_validate_error("silent_error", data, validate_shiny_silent_error) | ||
| srv_check_class_teal_data("class_teal_data", data) | ||
| srv_check_module_datanames("shiny_warnings", data, modules) | ||
| output$previous_failed <- renderUI({ | ||
| if (hide_validation_error()) { | ||
| shinyjs::hide("validate_messages") | ||
| tags$div("One of previous transformators failed. Please check its inputs.", class = "teal-output-warning") | ||
| } else { | ||
| shinyjs::show("validate_messages") | ||
| NULL | ||
| } | ||
| }) | ||
|
|
||
| .trigger_on_success(data) | ||
| }) | ||
| } | ||
|
|
||
| #' @rdname module_validate_error | ||
| #' @keywords internal | ||
| ui_validate_error <- function(id) { | ||
| ns <- NS(id) | ||
| uiOutput(ns("message")) | ||
| } | ||
|
|
||
| #' @rdname module_validate_error | ||
| #' @keywords internal | ||
| srv_validate_error <- function(id, data, validate_shiny_silent_error) { | ||
| checkmate::assert_string(id) | ||
|
|
@@ -193,13 +77,14 @@ srv_validate_error <- function(id, data, validate_shiny_silent_error) { | |
| }) | ||
| } | ||
|
|
||
|
|
||
| #' @rdname module_validate_error | ||
| #' @keywords internal | ||
| ui_check_class_teal_data <- function(id) { | ||
| ns <- NS(id) | ||
| uiOutput(ns("message")) | ||
| } | ||
|
|
||
| #' @rdname module_validate_error | ||
| #' @keywords internal | ||
| srv_check_class_teal_data <- function(id, data) { | ||
| checkmate::assert_string(id) | ||
|
|
@@ -215,12 +100,14 @@ srv_check_class_teal_data <- function(id, data) { | |
| }) | ||
| } | ||
|
|
||
| #' @rdname module_validate_error | ||
| #' @keywords internal | ||
| ui_check_module_datanames <- function(id) { | ||
| ns <- NS(id) | ||
| uiOutput(NS(id, "message")) | ||
| } | ||
|
|
||
| #' @rdname module_validate_error | ||
| #' @keywords internal | ||
| srv_check_module_datanames <- function(id, data, modules) { | ||
| checkmate::assert_string(id) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those files have functions deprecated in 0.16.0. We discussed with gogonzo, that those files could be deleted and functions could be removed as we had a MAJOR release to 1.0.0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice finding. Should we do that here? Or you want a different PR for this code to be removed on 1.1.0 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@llrs-roche unsure yet. Maybe we can discuss today during the standup
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, because to reach 80% of coverage is not a hard requirement, I would not ignore the files. I think for the matter of the 80% coverage issue, the task is done, even if the CI report does not have >80% of coverage if we do not ignore the files. We can prove in a screenshot or comment that by ignoring those files we reach 80% of coverage.
Then, on a separate issue and PR, we remove the deprecated functions as it was already announced to users. The same actions are applicable to other packages, like teal.widgets, where deprecated functions alter the count of coverage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand. Lets talk during the standup. And my vote would be to remove those files from the codebase.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with Marcin. They are not used or needed, so let's remove the dead code. But let's talk now about this