diff --git a/DESCRIPTION b/DESCRIPTION index 0df4763..61ca0f4 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: mwanaApp Title: mwana GUI -Version: 0.1.0 +Version: 0.2.0 Authors@R: person(given = "Tomás", family = "Zaba", diff --git a/NEWS.md b/NEWS.md index 9959cda..5b7bcc2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,23 @@ +# mwanaApp 0.2.0 + +### New features ✨ + ++ Enabled estimation of age in months from the date of data collection and the +child’s date of birth, and added a corresponding note in the user guide. + +### General updates + ++ Revised the documentation for the app’s user‑interface and server modules. + +### Bug fixes + ++ Resolved an issue in which the app’s user interface failed to display the input + field for supplying survey weights in the weight‑for‑height- and combined‑prevalence + tabs. + ++ Resolved an issue where hyperlinks in the app were directing users to a +non‑existent page. + ## mwanaApp v0.1.0 -+ First release of a feature-complete app. \ No newline at end of file ++ First release of a feature-complete app. diff --git a/R/module-data-upload.R b/R/module-data-upload.R index f58a443..7399beb 100644 --- a/R/module-data-upload.R +++ b/R/module-data-upload.R @@ -5,9 +5,10 @@ #' #' #' @param id Module ID -#' +#' @rdname module-id +#' #' @keywords internal -#' +#' #' module_ui_upload <- function(id) { ## Namespace ID's ---- @@ -94,9 +95,10 @@ module_ui_upload <- function(id) { #' #' Module server for data upload #' +#' @rdname module-id #' -#' @param id Module ID -#' +#' @returns A reactive data object to be used in data wrangling tab. +#' #' @keywords internal #' #' diff --git a/R/module-data-wrangling.R b/R/module-data-wrangling.R index fe2e5db..dcf1294 100644 --- a/R/module-data-wrangling.R +++ b/R/module-data-wrangling.R @@ -6,8 +6,7 @@ #' #' Module UI for data wrangling #' -#' @param id Module ID -#' +#' @rdname module-id #' #' @keywords internal #' @@ -64,7 +63,7 @@ module_ui_wrangling <- function(id) { style = "font-size: 15px; font-weight: bold;" )), - #### A Placehoder for wrangled data and embed user feedback ---- + #### A Placeholder for wrangled data and embed user feedback ---- shinycssloaders::withSpinner( ui_element = DT::DTOutput(outputId = ns("wrangled")), type = 8, @@ -82,7 +81,7 @@ module_ui_wrangling <- function(id) { ) ), - #### Placeholder for donwload button ---- + #### Placeholder for download button ---- shiny::uiOutput(outputId = ns("download_wrangled_data")) ) ) @@ -98,7 +97,11 @@ module_ui_wrangling <- function(id) { #' Module server for data wrangling #' #' @param id Module ID -#' +#' +#' @param data An output and reactive data object from previous tab. +#' +#' @returns A reactive data object wrangled and ready to be used in plausibility +#' checks and prevalence analysis tabs. #' #' @keywords internal #' @@ -175,12 +178,32 @@ module_server_wrangling <- function(id, data) { w <- switch(EXPR = input$wrangle, "wfhz" = { shiny::req(input$sex, input$weight, input$height) - data() |> - dplyr::rename( + + ### Wrangle age dynamically ---- + df <- if (nzchar(input$dos)) { + dplyr::mutate( + .data = data(), + dos = as.Date(!!rlang::sym(input$dos), format = "%d/%m/%Y"), + dob = as.Date(!!rlang::sym(input$dob), format = "%d/%m/%Y"), + age = as.numeric(!!rlang::sym(input$age)), sex = !!rlang::sym(input$sex), weight = !!rlang::sym(input$weight), height = !!rlang::sym(input$height) ) |> + mwana::mw_wrangle_age(.data$dos, .data$dob, .data$age) + } else { + dplyr::mutate( + .data = data(), + dos = NULL, + dob = NULL, + sex = !!rlang::sym(input$sex), + weight = !!rlang::sym(input$weight), + height = !!rlang::sym(input$height) + ) + } + + ### Wrangle WFHZ data ---- + df |> mwana::mw_wrangle_wfhz( sex = .data$sex, .recode_sex = TRUE, @@ -188,18 +211,34 @@ module_server_wrangling <- function(id, data) { height = .data$height ) }, + "mfaz" = { shiny::req(input$age, input$sex, input$muac) - data() |> + ### Wrangle age dynamically ---- + df <- if (nzchar(input$dos)) { dplyr::mutate( - muac = mwana::recode_muac(x = !!rlang::sym(input$muac), .to = "cm") + .data = data(), + muac = mwana::recode_muac(!!rlang::sym(input$muac), "cm"), + dos = as.Date(!!rlang::sym(input$dos), format = "%d/%m/%Y"), + dob = as.Date(!!rlang::sym(input$dob), format = "%d/%m/%Y"), + age = as.numeric(!!rlang::sym(input$age)), + sex = !!rlang::sym(input$sex) ) |> - dplyr::rename( - age = !!rlang::sym(input$age), + mwana::mw_wrangle_age(.data$dos, .data$dob, .data$age) + } else { + dplyr::mutate( + .data = data(), + muac = mwana::recode_muac(!!rlang::sym(input$muac), "cm"), + dos = NULL, + dob = NULL, sex = !!rlang::sym(input$sex) ) |> - mwana::mw_wrangle_age(dos = NULL, dob = NULL, age = .data$age) |> + mwana::mw_wrangle_age(NULL, NULL, .data$age) + } + + ### Wrangle MUAC ---- + df |> mwana::mw_wrangle_muac( sex = .data$sex, .recode_sex = TRUE, @@ -232,23 +271,40 @@ module_server_wrangling <- function(id, data) { input$muac ) - data() |> + ### Wrangle age dynamically ---- + df <- if (nzchar(input$dos)) { dplyr::mutate( - muac = mwana::recode_muac(x = !!rlang::sym(input$muac), .to = "cm") + .data = data(), + muac = mwana::recode_muac(!!rlang::sym(input$muac), "cm"), + dos = as.Date(!!rlang::sym(input$dos), format = "%d/%m/%Y"), + dob = as.Date(!!rlang::sym(input$dob), format = "%d/%m/%Y"), + age = as.numeric(!!rlang::sym(input$age)), + sex = !!rlang::sym(input$sex), + weight = !!rlang::sym(input$weight), + height = !!rlang::sym(input$height) ) |> - dplyr::rename( - age = !!rlang::sym(input$age), + mwana::mw_wrangle_age(.data$dos, .data$dob, .data$age) + } else { + dplyr::mutate( + .data = data(), + muac = mwana::recode_muac(!!rlang::sym(input$muac), "cm"), + dos = NULL, + dob = NULL, sex = !!rlang::sym(input$sex), weight = !!rlang::sym(input$weight), height = !!rlang::sym(input$height) ) |> + mwana::mw_wrangle_age(NULL, NULL, .data$age) + } + + ### Wrangle WHZ and MUAC data ---- + df |> mwana::mw_wrangle_wfhz( sex = .data$sex, .recode_sex = TRUE, weight = .data$weight, height = .data$height ) |> - mwana::mw_wrangle_age(dos = NULL, dob = NULL, age = .data$age) |> mwana::mw_wrangle_muac( sex = .data$sex, .recode_sex = FALSE, diff --git a/R/module-helpers-data-wrangling.R b/R/module-helpers-data-wrangling.R index 84e7275..c4d0fb5 100644 --- a/R/module-helpers-data-wrangling.R +++ b/R/module-helpers-data-wrangling.R @@ -5,8 +5,17 @@ #' #' #' Display input variables dynamically, according to UI for screening -#' -#' +#' +#' @param vars An object holding the data variable names. This is used to display +#' all the variables in the input variable of the ui. +#' +#' @param method User-selected method for data wrangling. +#' +#' @param ns A placeholder for Shiny module namespace. +#' +#' @returns A set of input variables specific for the user-selected data-wrangling +#' method. +#' #' @keywords internal #' #' diff --git a/R/module-helpers-ipc-check.R b/R/module-helpers-ipc-check.R index cca67a0..eaf96c2 100644 --- a/R/module-helpers-ipc-check.R +++ b/R/module-helpers-ipc-check.R @@ -8,8 +8,18 @@ #' #' #' Display input variables dynamically, according to UI for screening +#' +#' @param vars An object holding the data variable names. This is used to display +#' all the variables in the input variable of the UI. +#' +#' @param source User-selected source of data. As in the underlying method +#' used to collect the data. Choices are survey, screening and sentinel. #' -#' +#' @param ns A placeholder for Shiny module namespace. +#' +#' @returns A set of input variables specific for the user-selected source of +#' data. +#' #' @keywords internal #' #' @@ -103,7 +113,14 @@ mod_ipccheck_display_input_variables <- function(vars, source, ns) { #' Invoke mwana's IPC Acute Malnutrition minimum sample size requirement checker #' from within the module server #' -#' +#' @param df,cluster,source,area1,area2 Input variables collected from the UI +#' and required to pass to mwana::mw_check_ipcamn_ssreq() function. +#' +#' @returns A summary tibble containing check results for: +#' + n_clusters - the total number of unique clusters or screening or site identifiers; +#' + n_obs - the corresponding total number of children in the dataset; and, +#' + meet_ipc - whether the IPC AMN requirements were met. +#' #' @keywords internal #' #' diff --git a/R/module-helpers-plausibility-check.R b/R/module-helpers-plausibility-check.R index 0ef444b..cfe9265 100644 --- a/R/module-helpers-plausibility-check.R +++ b/R/module-helpers-plausibility-check.R @@ -6,7 +6,8 @@ #' #' Display input variables dynamically, according to UI for screening #' -#' @keywords internal +#' @inheritParams mod_data_wrangling_display_input_variables +#' #' mod_plausibility_display_input_variables <- function(vars, method, ns) { ### Base inputs always shown @@ -132,16 +133,21 @@ mod_plausibility_display_input_variables <- function(vars, method, ns) { inputs_vars } + #' #' #' Invoke mwana's plausibility checkers dynamically from within module server, #' according to user specifications in the UI #' -#' +#' @param df,age,sex,muac,weight,height,flags,area1,area2,area3,.for Input +#' variables collected from the UI and required to pass to +#' mwana::mw_plausibility_check_wfhz(). +#' +#' @returns A single-row summary tibble with columns containing the plausibility +#' check results. +#' #' @keywords internal #' -#' -#' mod_plausibility_call_checker <- function( df, age = NULL, sex, muac = NULL, weight = NULL, height = NULL, flags, area1, area2, area3, .for = c("wfhz", "muac", "mfaz")) { diff --git a/R/module-helpers-prevalence.R b/R/module-helpers-prevalence.R index 1f2ed30..631e21e 100644 --- a/R/module-helpers-prevalence.R +++ b/R/module-helpers-prevalence.R @@ -5,6 +5,12 @@ #' #' #' Display input variables dynamically, according to UI for screening +#' +#' +#' @param vars,source,indicator_surv,has_age Input variables collected +#' from the UI and required to pass to `{mwana}` prevalence functions. +#' +#' @param ns A placeholder for Shiny module namespace. #' #' @keywords internal #' @@ -47,7 +53,20 @@ mod_prevalence_display_input_variables <- function( ) ), choices = c("", vars) - ) + ), + shiny::selectInput( + inputId = ns("wts"), + label = shiny::tagList( + htmltools::tags$span("Survey weights", + style = "font-size: 14px; font-weight: bold;" + ), + htmltools::tags$div( + style = "font-size: 0.85em; color: #6c7574;", + "Final survey weights for weighted analysis" + ) + ), + choices = c("", vars) + ) ) #### Conditional inputs depending on source of data ---- @@ -75,19 +94,6 @@ mod_prevalence_display_input_variables <- function( htmltools::tags$span("*", style = "color: red;") ), choices = c("", vars) - ), - shiny::selectInput( - inputId = ns("wts"), - label = shiny::tagList( - htmltools::tags$span("Survey weights", - style = "font-size: 14px; font-weight: bold;" - ), - htmltools::tags$div( - style = "font-size: 0.85em; color: #6c7574;", - "Final survey weights for weighted analysis" - ) - ), - choices = c("", vars) ) ) } @@ -154,6 +160,11 @@ mod_prevalence_display_input_variables <- function( #' #' Invoke mwana's prevalence functions from within module server according to #' user specifications in the UI +#' +#' @param df,wts,oedema,area1,area2,area3 Input variables collected from the UI +#' and required to pass to mwana::mw_estimate_prevalence_wfhz(). +#' +#' @returns A summary tibble for the descriptive statistics about wasting. #' #' @keywords internal #' @@ -180,12 +191,19 @@ mod_prevalence_call_wfhz_prev_estimator <- function( ) } + #' #' #' #' Invoke mwana's prevalence functions from within module server according to #' user specifications in the UI #' +#' @param df,age,muac,wts,oedema,area1,area2,area3 Input variables collected +#' from the UI and required to pass to mwana::mw_estimate_prevalence_muac(). +#' +#' @returns A summary tibble for the descriptive statistics about wasting based +#' on MUAC, with confidence intervals. +#' #' @keywords internal #' #' @@ -213,13 +231,14 @@ mod_prevalence_call_muac_prev_estimator <- function( ) } + #' #' #' #' Invoke mwana's prevalence functions from within module server according to #' user specifications in the UI #' -#' @keywords internal +#' @inheritParams mod_prevalence_call_wfhz_prev_estimator #' #' mod_prevalence_call_combined_prev_estimator <- function( @@ -250,11 +269,16 @@ mod_prevalence_call_combined_prev_estimator <- function( #' #' Invoke mwana's prevalence functions from within module server according to #' user specifications in the UI +#' +#' @param df,age,muac,oedema,area1,area2,area3 Input variables collected +#' from the UI and required to pass to mwana::mw_estimate_prevalence_screening(). +# +#' @returns A summary tibble for the descriptive statistics about wasting based +#' on MUAC, with no confidence intervals. #' #' @keywords internal #' #' -#' mod_prevalence_call_prev_estimator_screening <- function( df, age, muac, oedema = NULL, area1, area2, area3) { @@ -293,10 +317,14 @@ mod_prevalence_call_prev_estimator_screening <- function( #' Invoke mwana's prevalence functions from within module server according to #' user specifications in the UI #' +#' @param df,age_cat,muac,oedema,area1,area2,area3 Input variables collected +#' from the UI and required to pass to mwana::mw_estimate_prevalence_screening2() +#' +#' @returns A summary tibble for the descriptive statistics about wasting based +#' on MUAC, with no confidence intervals. #' #' @keywords internal #' -#' mod_prevalence_call_prev_estimator_screening2 <- function( df, age_cat, muac, oedema = NULL, area1, area2, area3) { @@ -329,6 +357,14 @@ mod_prevalence_call_prev_estimator_screening2 <- function( #' #' +#' Neat prevalence output from survey +#' +#' @param df data.frame containing the prevalence results. +#' @param .type A choice from which the prevalence is derived. +#' +#' @returns A tibble object of the same length and width as df, with column +#' names and values formatted for clarity and readability. +#' #' @keywords internal #' #' @@ -393,6 +429,13 @@ mod_prevalence_neat_output_survey <- function( #' +#' +#' Neat prevalence output from survey +#' +#' @param df data.frame containing the prevalence results. +#' +#' @returns A tibble object of the same length and width as df, with column +#' names and values formatted for clarity and readability. #' #' @keywords internal #' diff --git a/R/module-ipc-aman-check.R b/R/module-ipc-aman-check.R index c066086..47bf934 100644 --- a/R/module-ipc-aman-check.R +++ b/R/module-ipc-aman-check.R @@ -8,8 +8,6 @@ #' #' @keywords internal #' -#' -#' module_ui_ipccheck <- function(id) { ## Namespace ID ---- ns <- shiny::NS(id) @@ -79,7 +77,7 @@ module_ui_ipccheck <- function(id) { ) ), - #### Placeholder for donwload button ---- + #### Placeholder for download button ---- shiny::uiOutput(outputId = ns("download_ipccheck")) ) ) @@ -87,17 +85,13 @@ module_ui_ipccheck <- function(id) { } -## ---- Module: Sever ---------------------------------------------------------- +## ---- Module: Server ---------------------------------------------------------- #' #' #' Module server for IPC Acute Malnutrition sample size requirements check #' -#' @param id Module ID -#' -#' -#' @keywords internal -#' +#' @inheritParams module_server_wrangling #' #' module_server_ipccheck <- function(id, data) { @@ -204,7 +198,7 @@ module_server_ipccheck <- function(id, data) { pageLength = 20, scrollX = FALSE, scrollY = "800px", - columDefs = list(list(className = "dt-center", targets = "_all")) + columnDefs = list(list(className = "dt-center", targets = "_all")) ), caption = if (nrow(dataset$checked) > 20) { paste( diff --git a/R/module-plausibility-check.R b/R/module-plausibility-check.R index f095439..95578b8 100644 --- a/R/module-plausibility-check.R +++ b/R/module-plausibility-check.R @@ -6,7 +6,6 @@ #' #' @param id Module ID #' -#' #' @keywords internal #' #' @@ -59,7 +58,7 @@ module_ui_plausibility_check <- function(id) { style = "font-size: 15px; font-weight: bold;" )), - #### A Placehoder for wrangled data and embed user feedback ---- + #### A Placeholder for wrangled data and embed user feedback ---- shinycssloaders::withSpinner( ui_element = DT::DTOutput(outputId = ns("checked")), type = 8, @@ -77,7 +76,7 @@ module_ui_plausibility_check <- function(id) { ) ), - #### Placeholder for donwload button ---- + #### Placeholder for download button ---- shiny::uiOutput(outputId = ns("download_plausibility")) ) ) @@ -90,10 +89,8 @@ module_ui_plausibility_check <- function(id) { #' #' Module server for plausibility check #' -#' @param id Module ID -#' -#' -#' @keywords internal +#' +#' @inheritParams module_server_wrangling #' #' module_server_plausibility_check <- function(id, data) { diff --git a/R/module-prevalence.R b/R/module-prevalence.R index 5973813..6b066ff 100644 --- a/R/module-prevalence.R +++ b/R/module-prevalence.R @@ -9,7 +9,6 @@ #' @keywords internal #' #' -#' module_ui_prevalence <- function(id) { ## Namespace ID ---- ns <- shiny::NS(id) @@ -71,7 +70,7 @@ module_ui_prevalence <- function(id) { ) ), - #### A Placehoder for wrangled data and embed user feedback ---- + #### A Placeholder for wrangled data and embed user feedback ---- shinycssloaders::withSpinner( ui_element = DT::DTOutput(outputId = ns("results")), type = 8, @@ -89,7 +88,7 @@ module_ui_prevalence <- function(id) { ) ), - #### Placeholder for donwload button ---- + #### Placeholder for download button ---- shiny::uiOutput(outputId = ns("download_prevalence")) ) ) @@ -103,9 +102,7 @@ module_ui_prevalence <- function(id) { #' #' Module server for prevalence analysis #' -#' @param id Module ID -#' -#' @keywords internal +#' @inheritParams module_server_wrangling #' #' module_server_prevalence <- function(id, data) { diff --git a/README.md b/README.md index 074635d..118ca03 100644 --- a/README.md +++ b/README.md @@ -54,8 +54,8 @@ citation("mwanaApp") Tomás Zaba (2026). _mwanaApp: A seamless graphical interface to the mwana R package for data wrangling, plausibility checks, and - prevalence estimation_. R package version 0.1.0, - . + prevalence estimation_. R package version 0.2.0, + . A BibTeX entry for LaTeX users is @@ -63,6 +63,6 @@ citation("mwanaApp") title = {mwanaApp: A seamless graphical interface to the mwana R package for data wrangling, plausibility checks, and prevalence estimation}, author = {{Tomás Zaba}}, year = {2026}, - note = {R package version 0.1.0}, - url = {https://github.com/mphimo/mwanaApp.git}, + note = {R package version 0.2.0}, + url = {https://github.com/mphimo/mwanaApp}, } diff --git a/inst/CITATION b/inst/CITATION index 0cf8e7f..56e6169 100644 --- a/inst/CITATION +++ b/inst/CITATION @@ -4,6 +4,6 @@ bibentry( title = "mwanaApp: A seamless graphical interface to the mwana R package for data wrangling, plausibility checks, and prevalence estimation", author = person("Tomás Zaba"), year = 2026, - note = "R package version 0.1.0", - url = "https://github.com/mphimo/mwanaApp.git" + note = "R package version 0.2.0", + url = "https://github.com/mphimo/mwanaApp" ) diff --git a/man/mod_data_wrangling_display_input_variables.Rd b/man/mod_data_wrangling_display_input_variables.Rd index ddb1809..c9c7f62 100644 --- a/man/mod_data_wrangling_display_input_variables.Rd +++ b/man/mod_data_wrangling_display_input_variables.Rd @@ -6,6 +6,18 @@ \usage{ mod_data_wrangling_display_input_variables(vars, method, ns) } +\arguments{ +\item{vars}{An object holding the data variable names. This is used to display +all the variables in the input variable of the ui.} + +\item{method}{User-selected method for data wrangling.} + +\item{ns}{A placeholder for Shiny module namespace.} +} +\value{ +A set of input variables specific for the user-selected data-wrangling +method. +} \description{ Display input variables dynamically, according to UI for screening } diff --git a/man/mod_ipccheck_call_checker.Rd b/man/mod_ipccheck_call_checker.Rd index 329f09d..83a7f65 100644 --- a/man/mod_ipccheck_call_checker.Rd +++ b/man/mod_ipccheck_call_checker.Rd @@ -7,6 +7,18 @@ from within the module server} \usage{ mod_ipccheck_call_checker(df, cluster, source = character(), area1, area2) } +\arguments{ +\item{df, cluster, source, area1, area2}{Input variables collected from the UI +and required to pass to mwana::mw_check_ipcamn_ssreq() function.} +} +\value{ +A summary tibble containing check results for: +\itemize{ +\item n_clusters - the total number of unique clusters or screening or site identifiers; +\item n_obs - the corresponding total number of children in the dataset; and, +\item meet_ipc - whether the IPC AMN requirements were met. +} +} \description{ Invoke mwana's IPC Acute Malnutrition minimum sample size requirement checker from within the module server diff --git a/man/mod_ipccheck_display_input_variables.Rd b/man/mod_ipccheck_display_input_variables.Rd index 046c980..e1e3319 100644 --- a/man/mod_ipccheck_display_input_variables.Rd +++ b/man/mod_ipccheck_display_input_variables.Rd @@ -6,6 +6,19 @@ \usage{ mod_ipccheck_display_input_variables(vars, source, ns) } +\arguments{ +\item{vars}{An object holding the data variable names. This is used to display +all the variables in the input variable of the UI.} + +\item{source}{User-selected source of data. As in the underlying method +used to collect the data. Choices are survey, screening and sentinel.} + +\item{ns}{A placeholder for Shiny module namespace.} +} +\value{ +A set of input variables specific for the user-selected source of +data. +} \description{ Display input variables dynamically, according to UI for screening } diff --git a/man/mod_plausibility_call_checker.Rd b/man/mod_plausibility_call_checker.Rd index 3617ff3..2b5939e 100644 --- a/man/mod_plausibility_call_checker.Rd +++ b/man/mod_plausibility_call_checker.Rd @@ -19,6 +19,15 @@ mod_plausibility_call_checker( .for = c("wfhz", "muac", "mfaz") ) } +\arguments{ +\item{df, age, sex, muac, weight, height, flags, area1, area2, area3, .for}{Input +variables collected from the UI and required to pass to +mwana::mw_plausibility_check_wfhz().} +} +\value{ +A single-row summary tibble with columns containing the plausibility +check results. +} \description{ Invoke mwana's plausibility checkers dynamically from within module server, according to user specifications in the UI diff --git a/man/mod_plausibility_display_input_variables.Rd b/man/mod_plausibility_display_input_variables.Rd index 876edc5..6e1b9ca 100644 --- a/man/mod_plausibility_display_input_variables.Rd +++ b/man/mod_plausibility_display_input_variables.Rd @@ -6,7 +6,14 @@ \usage{ mod_plausibility_display_input_variables(vars, method, ns) } +\arguments{ +\item{vars}{An object holding the data variable names. This is used to display +all the variables in the input variable of the ui.} + +\item{method}{User-selected method for data wrangling.} + +\item{ns}{A placeholder for Shiny module namespace.} +} \description{ Display input variables dynamically, according to UI for screening } -\keyword{internal} diff --git a/man/mod_prevalence_call_combined_prev_estimator.Rd b/man/mod_prevalence_call_combined_prev_estimator.Rd index ee6420a..619a8bd 100644 --- a/man/mod_prevalence_call_combined_prev_estimator.Rd +++ b/man/mod_prevalence_call_combined_prev_estimator.Rd @@ -14,8 +14,11 @@ mod_prevalence_call_combined_prev_estimator( area3 ) } +\arguments{ +\item{df, wts, oedema, area1, area2, area3}{Input variables collected from the UI +and required to pass to mwana::mw_estimate_prevalence_wfhz().} +} \description{ Invoke mwana's prevalence functions from within module server according to user specifications in the UI } -\keyword{internal} diff --git a/man/mod_prevalence_call_muac_prev_estimator.Rd b/man/mod_prevalence_call_muac_prev_estimator.Rd index b1c4b56..cf18dcc 100644 --- a/man/mod_prevalence_call_muac_prev_estimator.Rd +++ b/man/mod_prevalence_call_muac_prev_estimator.Rd @@ -16,6 +16,14 @@ mod_prevalence_call_muac_prev_estimator( area3 ) } +\arguments{ +\item{df, age, muac, wts, oedema, area1, area2, area3}{Input variables collected +from the UI and required to pass to mwana::mw_estimate_prevalence_muac().} +} +\value{ +A summary tibble for the descriptive statistics about wasting based +on MUAC, with confidence intervals. +} \description{ Invoke mwana's prevalence functions from within module server according to user specifications in the UI diff --git a/man/mod_prevalence_call_prev_estimator_screening.Rd b/man/mod_prevalence_call_prev_estimator_screening.Rd index b6613c9..a29132b 100644 --- a/man/mod_prevalence_call_prev_estimator_screening.Rd +++ b/man/mod_prevalence_call_prev_estimator_screening.Rd @@ -15,6 +15,14 @@ mod_prevalence_call_prev_estimator_screening( area3 ) } +\arguments{ +\item{df, age, muac, oedema, area1, area2, area3}{Input variables collected +from the UI and required to pass to mwana::mw_estimate_prevalence_screening().} +} +\value{ +A summary tibble for the descriptive statistics about wasting based +on MUAC, with no confidence intervals. +} \description{ Invoke mwana's prevalence functions from within module server according to user specifications in the UI diff --git a/man/mod_prevalence_call_prev_estimator_screening2.Rd b/man/mod_prevalence_call_prev_estimator_screening2.Rd index 769d342..1c48446 100644 --- a/man/mod_prevalence_call_prev_estimator_screening2.Rd +++ b/man/mod_prevalence_call_prev_estimator_screening2.Rd @@ -15,6 +15,14 @@ mod_prevalence_call_prev_estimator_screening2( area3 ) } +\arguments{ +\item{df, age_cat, muac, oedema, area1, area2, area3}{Input variables collected +from the UI and required to pass to mwana::mw_estimate_prevalence_screening2()} +} +\value{ +A summary tibble for the descriptive statistics about wasting based +on MUAC, with no confidence intervals. +} \description{ Invoke mwana's prevalence functions from within module server according to user specifications in the UI diff --git a/man/mod_prevalence_call_wfhz_prev_estimator.Rd b/man/mod_prevalence_call_wfhz_prev_estimator.Rd index 26ca9df..2c8759d 100644 --- a/man/mod_prevalence_call_wfhz_prev_estimator.Rd +++ b/man/mod_prevalence_call_wfhz_prev_estimator.Rd @@ -14,6 +14,13 @@ mod_prevalence_call_wfhz_prev_estimator( area3 ) } +\arguments{ +\item{df, wts, oedema, area1, area2, area3}{Input variables collected from the UI +and required to pass to mwana::mw_estimate_prevalence_wfhz().} +} +\value{ +A summary tibble for the descriptive statistics about wasting. +} \description{ Invoke mwana's prevalence functions from within module server according to user specifications in the UI diff --git a/man/mod_prevalence_display_input_variables.Rd b/man/mod_prevalence_display_input_variables.Rd index 9875fcc..5ab673d 100644 --- a/man/mod_prevalence_display_input_variables.Rd +++ b/man/mod_prevalence_display_input_variables.Rd @@ -12,6 +12,12 @@ mod_prevalence_display_input_variables( ns ) } +\arguments{ +\item{vars, source, indicator_surv, has_age}{Input variables collected +from the UI and required to pass to \code{{mwana}} prevalence functions.} + +\item{ns}{A placeholder for Shiny module namespace.} +} \description{ Display input variables dynamically, according to UI for screening } diff --git a/man/mod_prevalence_neat_output_screening.Rd b/man/mod_prevalence_neat_output_screening.Rd new file mode 100644 index 0000000..853a188 --- /dev/null +++ b/man/mod_prevalence_neat_output_screening.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/module-helpers-prevalence.R +\name{mod_prevalence_neat_output_screening} +\alias{mod_prevalence_neat_output_screening} +\title{Neat prevalence output from survey} +\usage{ +mod_prevalence_neat_output_screening(df) +} +\arguments{ +\item{df}{data.frame containing the prevalence results.} +} +\value{ +A tibble object of the same length and width as df, with column +names and values formatted for clarity and readability. +} +\description{ +Neat prevalence output from survey +} +\keyword{internal} diff --git a/man/mod_prevalence_neat_output_survey.Rd b/man/mod_prevalence_neat_output_survey.Rd new file mode 100644 index 0000000..7e004ba --- /dev/null +++ b/man/mod_prevalence_neat_output_survey.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/module-helpers-prevalence.R +\name{mod_prevalence_neat_output_survey} +\alias{mod_prevalence_neat_output_survey} +\title{Neat prevalence output from survey} +\usage{ +mod_prevalence_neat_output_survey(df, .type = c("wfhz", "muac", "combined")) +} +\arguments{ +\item{df}{data.frame containing the prevalence results.} + +\item{.type}{A choice from which the prevalence is derived.} +} +\value{ +A tibble object of the same length and width as df, with column +names and values formatted for clarity and readability. +} +\description{ +Neat prevalence output from survey +} +\keyword{internal} diff --git a/man/module-id.Rd b/man/module-id.Rd new file mode 100644 index 0000000..9de5a4b --- /dev/null +++ b/man/module-id.Rd @@ -0,0 +1,28 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/module-data-upload.R, R/module-data-wrangling.R +\name{module_ui_upload} +\alias{module_ui_upload} +\alias{module_server_upload} +\alias{module_ui_wrangling} +\title{Module UI for data upload} +\usage{ +module_ui_upload(id) + +module_server_upload(id) + +module_ui_wrangling(id) +} +\arguments{ +\item{id}{Module ID} +} +\value{ +A reactive data object to be used in data wrangling tab. +} +\description{ +Module UI for data upload + +Module server for data upload + +Module UI for data wrangling +} +\keyword{internal} diff --git a/man/module_server_ipccheck.Rd b/man/module_server_ipccheck.Rd index 34ba2f2..845e09a 100644 --- a/man/module_server_ipccheck.Rd +++ b/man/module_server_ipccheck.Rd @@ -8,8 +8,9 @@ module_server_ipccheck(id, data) } \arguments{ \item{id}{Module ID} + +\item{data}{An output and reactive data object from previous tab.} } \description{ Module server for IPC Acute Malnutrition sample size requirements check } -\keyword{internal} diff --git a/man/module_server_plausibility_check.Rd b/man/module_server_plausibility_check.Rd index c6bf93c..769aa34 100644 --- a/man/module_server_plausibility_check.Rd +++ b/man/module_server_plausibility_check.Rd @@ -8,8 +8,9 @@ module_server_plausibility_check(id, data) } \arguments{ \item{id}{Module ID} + +\item{data}{An output and reactive data object from previous tab.} } \description{ Module server for plausibility check } -\keyword{internal} diff --git a/man/module_server_prevalence.Rd b/man/module_server_prevalence.Rd index 6129ff3..0737f08 100644 --- a/man/module_server_prevalence.Rd +++ b/man/module_server_prevalence.Rd @@ -8,8 +8,9 @@ module_server_prevalence(id, data) } \arguments{ \item{id}{Module ID} + +\item{data}{An output and reactive data object from previous tab.} } \description{ Module server for prevalence analysis } -\keyword{internal} diff --git a/man/module_server_upload.Rd b/man/module_server_upload.Rd deleted file mode 100644 index c8f4be2..0000000 --- a/man/module_server_upload.Rd +++ /dev/null @@ -1,15 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/module-data-upload.R -\name{module_server_upload} -\alias{module_server_upload} -\title{Module server for data upload} -\usage{ -module_server_upload(id) -} -\arguments{ -\item{id}{Module ID} -} -\description{ -Module server for data upload -} -\keyword{internal} diff --git a/man/module_server_wrangling.Rd b/man/module_server_wrangling.Rd index 5d5e840..11d433a 100644 --- a/man/module_server_wrangling.Rd +++ b/man/module_server_wrangling.Rd @@ -8,6 +8,12 @@ module_server_wrangling(id, data) } \arguments{ \item{id}{Module ID} + +\item{data}{An output and reactive data object from previous tab.} +} +\value{ +A reactive data object wrangled and ready to be used in plausibility +checks and prevalence analysis tabs. } \description{ Module server for data wrangling diff --git a/man/module_ui_upload.Rd b/man/module_ui_upload.Rd deleted file mode 100644 index 6883bf6..0000000 --- a/man/module_ui_upload.Rd +++ /dev/null @@ -1,15 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/module-data-upload.R -\name{module_ui_upload} -\alias{module_ui_upload} -\title{Module UI for data upload} -\usage{ -module_ui_upload(id) -} -\arguments{ -\item{id}{Module ID} -} -\description{ -Module UI for data upload -} -\keyword{internal} diff --git a/man/module_ui_wrangling.Rd b/man/module_ui_wrangling.Rd deleted file mode 100644 index 62acf81..0000000 --- a/man/module_ui_wrangling.Rd +++ /dev/null @@ -1,15 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/module-data-wrangling.R -\name{module_ui_wrangling} -\alias{module_ui_wrangling} -\title{Module UI for data wrangling} -\usage{ -module_ui_wrangling(id) -} -\arguments{ -\item{id}{Module ID} -} -\description{ -Module UI for data wrangling -} -\keyword{internal} diff --git a/tests/testthat/test-module-prevalence.R b/tests/testthat/test-module-prevalence.R index 36a05cf..a618553 100644 --- a/tests/testthat/test-module-prevalence.R +++ b/tests/testthat/test-module-prevalence.R @@ -6,15 +6,9 @@ ## ---- Survey data ------------------------------------------------------------ -### WFHZ Prevalence ---- - -#### Skip test on windows ---- -# if (identical(Sys.getenv("CI"), "true") && Sys.info()[["sysname"]] == "Windows") { -# skip("Skipping shinytest2 integration tests on Windows CI to reduce runtime") -# } - +### WFHZ weighted prevalence ---- testthat::test_that( - desc = "Module works well to estimate prevalence of AMN by WFHZ from survey", + desc = "Module works well to estimate weighted-WFHZ prevalence from survey", code = { ### Initialise mwana app ---- app <- shinytest2::AppDriver$new( @@ -35,6 +29,7 @@ testthat::test_that( file = testthat::test_path("fixtures", "anthro-01.csv"), check.names = FALSE ) + data["sex"] <- ifelse(data$sex == 1, "m", "f") tempfile <- tempfile(fileext = ".csv") write.csv(data, tempfile, row.names = FALSE) @@ -84,29 +79,112 @@ testthat::test_that( {return $(this).text();}).get();" ### Capture prevalence results of Nampula Province, Rural Strata ---- - glued_results <- app$get_js(js_values)[[1]] - weighted_pop <- stringr::str_extract(glued_results, "\\d{6}") + glued_results <- app$get_js(js_values)[[3]] + weighted_pop <- sub("1", "", stringr::str_extract(glued_results, "\\d{7}(?:)")) gam_prev <- stringr::str_extract(glued_results, "\\d\\.\\d") ### Test check ---- testthat::expect_equal(length(app$get_js(js_cols)[1:19]), 19) - testthat::expect_equal(as.numeric(weighted_pop), 243016) - testthat::expect_equal(as.numeric(gam_prev), 3.7) + testthat::expect_equal(as.numeric(weighted_pop), 292611) + testthat::expect_equal(as.numeric(gam_prev), 6.1) ### Stop the app ---- app$stop() } ) -### MUAC prevalence ---- -#### Skip test on windows ---- -# if (identical(Sys.getenv("CI"), "true") && Sys.info()[["sysname"]] == "Windows") { -# skip("Skipping shinytest2 integration tests on Windows CI to reduce runtime") -# } +### WFHZ unweighted prevalence ---- +testthat::test_that( + desc = "Module works well to estimate unweighted-WFHZ prevalence from survey", + code = { + ### Initialise mwana app ---- + app <- shinytest2::AppDriver$new( + app_dir = testthat::test_path("fixtures"), + timeout = 120000, + wait = TRUE + ) + + ### Wait the app to idle ---- + app$wait_for_idle(timeout = 40000) + + ### Click in the Data Upload tab ---- + app$click(selector = "a[data-value='Data Upload']") + app$wait_for_idle(timeout = 40000) + + #### Read data ---- + data <- read.csv( + file = testthat::test_path("fixtures", "anthro-01.csv"), + check.names = FALSE + ) + data["sex"] <- ifelse(data$sex == 1, "m", "f") + tempfile <- tempfile(fileext = ".csv") + write.csv(data, tempfile, row.names = FALSE) + + #### Upload onto the app ---- + app$upload_file(`upload_data-upload` = tempfile, wait_ = TRUE) + + ### Click on the data wrangling tab ---- + app$click(selector = "a[data-value='Data Wrangling']") + app$wait_for_idle(timeout = 40000) + + ## App defaults to WFHZ ---- + ### Input variables ---- + app$set_inputs(`wrangle_data-dos` = "", wait_ = FALSE) + app$set_inputs(`wrangle_data-dob` = "", wait_ = FALSE) + app$set_inputs(`wrangle_data-sex` = "sex", wait_ = FALSE) + app$set_inputs(`wrangle_data-weight` = "weight", wait_ = FALSE) + app$set_inputs(`wrangle_data-height` = "height", wait_ = FALSE) + + ### Click wrangle button and wait the app to idle ---- + app$click(input = "wrangle_data-apply_wrangle") + Sys.sleep(3) + + ### Click on the Prevalence tab and wait the app to idle ---- + app$click(selector = "a[data-value='Prevalence Analysis']") + app$wait_for_idle(timeout = 40000) + + ### Select source of data ---- + app$set_inputs(`prevalence-source` = "survey", wait_ = FALSE) + + ### Select the method ---- + app$set_inputs(`prevalence-amn_method_survey` = "wfhz", wait_ = FALSE) + app$set_inputs(`prevalence-area1` = "province", wait_ = FALSE) + app$set_inputs(`prevalence-area2` = "strata", wait_ = FALSE) ## Assume sex as grouping var + app$set_inputs(`prevalence-area3` = "sex", wait_ = FALSE) + app$set_inputs(`prevalence-wts` = "", wait_ = FALSE) + app$set_inputs(`prevalence-oedema` = "oedema", wait_ = FALSE) + + ### Click on Estime Prevalence button ---- + app$click(input = "prevalence-estimate") + app$wait_for_value(output = "prevalence-results", timeout = 40000) + + ### Capture JavaScript expressions to return results's cols and values ---- + js_cols <- "$('#prevalence-results thead th').map(function() + {return $(this).text();}).get();" + + js_values <- "$('#prevalence-results tbody tr').map(function() + {return $(this).text();}).get();" + + ### Capture prevalence results of Nampula Province, Rural Strata ---- + glued_results <- app$get_js(js_values)[[3]] + pop <- sub("1", "", stringr::str_extract(glued_results, "\\d{4}")) + gam_prev <- stringr::str_extract(glued_results, "\\d{1}\\.\\d") + + ### Test check ---- + testthat::expect_equal(length(app$get_js(js_cols)[1:19]), 19) + testthat::expect_equal(as.numeric(pop), 280) + testthat::expect_equal(as.numeric(gam_prev), 6.1) + ### Stop the app ---- + app$stop() + } +) + + +### MUAC weighted prevalence ---- testthat::test_that( - desc = "Module works well to estimate prevalence of AMN by MUAC from survey", + desc = "Module works well to estimate weighted-MUAC prevalence from survey", code = { ### Initialise mwana app ---- app <- shinytest2::AppDriver$new( @@ -127,6 +205,7 @@ testthat::test_that( file = testthat::test_path("fixtures", "anthro-01.csv"), check.names = FALSE ) + data["sex"] <- ifelse(data$sex == 1, "m", "f") tempfile <- tempfile(fileext = ".csv") write.csv(data, tempfile, row.names = FALSE) @@ -190,28 +269,125 @@ testthat::test_that( js_result <- app$get_js(js_values) } ### Capture prevalence results of Zambezia Province, Rural Strata ---- - prev <- stringr::str_extract_all(js_result[[3]][1], "\\d\\.\\d")[[1]] + prev <- stringr::str_extract_all(js_result[[3]], "\\d\\.\\d")[[1]] + weighted_pop <- sub("1", "", stringr::str_extract(js_result[[3]], "\\d{7}(?:)")) + + ### Test check ---- + testthat::expect_equal(length(app$get_js(js_cols)[1:19]), 19) + testthat::expect_equal(as.numeric(prev[2]), 7.7) # GAM + testthat::expect_equal(as.numeric(weighted_pop), 307395) + + ### Stop the app ---- + app$stop() + } +) + + +### MUAC unweighted prevalence ---- +testthat::test_that( + desc = "Module works well to estimate unweighted-MUAC prevalence from survey", + code = { + ### Initialise mwana app ---- + app <- shinytest2::AppDriver$new( + app_dir = testthat::test_path("fixtures"), + timeout = 120000, + wait = TRUE + ) + + ### Wait the app to idle ---- + app$wait_for_idle(timeout = 40000) + + ### Click in the Data Upload tab ---- + app$click(selector = "a[data-value='Data Upload']") + app$wait_for_idle(timeout = 40000) + + #### Read data ---- + data <- read.csv( + file = testthat::test_path("fixtures", "anthro-01.csv"), + check.names = FALSE + ) + data["sex"] <- ifelse(data$sex == 1, "m", "f") + tempfile <- tempfile(fileext = ".csv") + write.csv(data, tempfile, row.names = FALSE) + + #### Upload onto the app ---- + app$upload_file(`upload_data-upload` = tempfile, wait_ = TRUE) + + ### Click on the data wrangling tab ---- + app$click(selector = "a[data-value='Data Wrangling']") + app$wait_for_idle(timeout = 40000) + + ### Select data wrangling method and wait the app till idles ---- + app$set_inputs(`wrangle_data-wrangle` = "mfaz", wait_ = TRUE) + app$wait_for_idle(timeout = 40000) + + ### Input variables ---- + app$set_inputs(`wrangle_data-dos` = "", wait_ = FALSE) + app$set_inputs(`wrangle_data-dob` = "", wait_ = FALSE) + app$set_inputs(`wrangle_data-age` = "age", wait_ = FALSE) + app$set_inputs(`wrangle_data-sex` = "sex", wait_ = FALSE) + app$set_inputs(`wrangle_data-muac` = "muac", wait_ = FALSE) + + ### Click wrangle button and wait the app to idle ---- + app$click(input = "wrangle_data-apply_wrangle") + app$wait_for_idle(timeout = 40000) + + ### Click on the Prevalence tab and wait the app to idle ---- + app$click(selector = "a[data-value='Prevalence Analysis']") + app$wait_for_idle(timeout = 40000) + + ### Select source of data ---- + app$set_inputs(`prevalence-source` = "survey", wait_ = FALSE) + + ### Select the method ---- + app$set_inputs(`prevalence-amn_method_survey` = "muac", wait_ = TRUE) + app$set_inputs(`prevalence-area1` = "province", wait_ = FALSE) + app$set_inputs(`prevalence-area2` = "strata", wait_ = FALSE) ## Assume sex as grouping var + app$set_inputs(`prevalence-area3` = "sex", wait_ = FALSE) + app$set_inputs(`prevalence-muac` = "muac", wait_ = FALSE) + app$set_inputs(`prevalence-age` = "age", wait_ = FALSE) + app$set_inputs(`prevalence-wts` = "", wait_ = FALSE) + app$set_inputs(`prevalence-oedema` = "oedema", wait_ = FALSE) + + ### Click on Estime Prevalence button ---- + app$click(input = "prevalence-estimate") + app$wait_for_value(output = "prevalence-results", timeout = 40000) + + ### Capture JavaScript expressions to return results's cols and values ---- + js_cols <- "$('#prevalence-results thead th').map(function() + {return $(this).text();}).get();" + + js_values <- "$('#prevalence-results tbody tr').map(function() + {return $(this).text();}).get();" + + ### Get a JS expression ---- + js_result <- app$get_js(js_values) + + ### Wait/validate that we have at least 3 values + if (length(js_result) < 4) { + #### Add a small delay and retry + Sys.sleep(3) + js_result <- app$get_js(js_values) + } + ### Capture prevalence results of Zambezia Province, Rural Strata ---- + pop <- sub("1", "", stringr::str_extract(js_result[[3]], "\\d{4}")) + prev <- stringr::str_extract(js_result[[3]], "\\d{1}\\.\\d") ### Test check ---- testthat::expect_equal(length(app$get_js(js_cols)[1:19]), 19) - testthat::expect_equal(as.numeric(prev[2]), 5.3) # GAM - testthat::expect_equal(as.numeric(prev[6]), 1.3) # SAM - testthat::expect_equal(as.numeric(prev[10]), 4.0) # MAM + testthat::expect_equal(as.numeric(prev), 8.0) # GAM + testthat::expect_equal(as.numeric(pop), 300) ### Stop the app ---- app$stop() } ) -### Combined prevalence ---- -#### Skip test on windows ---- -# if (identical(Sys.getenv("CI"), "true") && Sys.info()[["sysname"]] == "Windows") { -# skip("Skipping shinytest2 integration tests on Windows CI to reduce runtime") -# } +### Combined weighted prevalence ---- testthat::test_that( - desc = "Module works well to estimate prevalence of combined AMN from survey", + desc = "Module works well to estimate weighted-combined prevalence from survey", code = { ### Initialise mwana app ---- app <- shinytest2::AppDriver$new( @@ -232,6 +408,7 @@ testthat::test_that( file = testthat::test_path("fixtures", "anthro-01.csv"), check.names = FALSE ) + data["sex"] <- ifelse(data$sex == 1, "m", "f") tempfile <- tempfile(fileext = ".csv") write.csv(data, tempfile, row.names = FALSE) @@ -286,13 +463,14 @@ testthat::test_that( {return $(this).text();}).get();" ### Capture prevalence results of Nampula Province, Urban Strata ---- - glued_results <- app$get_js(js_values)[[2]] - prev <- stringr::str_extract_all(glued_results, "\\d{2}\\.\\d")[[1]] # not all are prevs + glued_results <- app$get_js(js_values)[[3]] + prev <- stringr::str_extract_all(glued_results, "\\d{2}\\.\\d")[[1]] + weighted_pop <- sub("1", "", stringr::str_extract(glued_results, "\\d{7}(?:)")) ### Test check ---- testthat::expect_equal(length(app$get_js(js_cols)[1:19]), 19) - testthat::expect_equal(as.numeric(prev[1]), 10.1) # GAM - testthat::expect_equal(as.numeric(prev[2]), 13.3) # GAM's upper CI + testthat::expect_equal(as.numeric(prev[2]), 10.8) # GAM + testthat::expect_equal(as.numeric(weighted_pop), 288534) ### Stop the app ---- app$stop() @@ -300,16 +478,102 @@ testthat::test_that( ) -## ---- Screening data --------------------------------------------------------- +### Combined unweighted prevalence ---- +testthat::test_that( + desc = "Module works well to estimate unweighted-combined prevalence from survey", + code = { + ### Initialise mwana app ---- + app <- shinytest2::AppDriver$new( + app_dir = testthat::test_path("fixtures"), + timeout = 120000, + wait = TRUE + ) + ### Wait the app to idle ---- + app$wait_for_idle(timeout = 40000) -### When age is available ---- + ### Click in the Data Upload tab ---- + app$click(selector = "a[data-value='Data Upload']") + app$wait_for_idle(timeout = 40000) + + #### Read data ---- + data <- read.csv( + file = testthat::test_path("fixtures", "anthro-01.csv"), + check.names = FALSE + ) + data["sex"] <- ifelse(data$sex == 1, "m", "f") + tempfile <- tempfile(fileext = ".csv") + write.csv(data, tempfile, row.names = FALSE) -### Skip test on windows ---- -# if (identical(Sys.getenv("CI"), "true") && Sys.info()[["sysname"]] == "Windows") { -# skip("Skipping shinytest2 integration tests on Windows CI to reduce runtime") -# } + #### Upload onto the app ---- + app$upload_file(`upload_data-upload` = tempfile, wait_ = TRUE) + ### Click on the data wrangling tab ---- + app$click(selector = "a[data-value='Data Wrangling']") + app$wait_for_idle(timeout = 40000) + + ### Select data wrangling method and wait the app till idles ---- + app$set_inputs(`wrangle_data-wrangle` = "combined", wait_ = TRUE) + app$wait_for_idle(timeout = 40000) + + ### Input variables ---- + app$set_inputs(`wrangle_data-dos` = "", wait_ = FALSE) + app$set_inputs(`wrangle_data-dob` = "", wait_ = FALSE) + app$set_inputs(`wrangle_data-age` = "age", wait_ = FALSE) + app$set_inputs(`wrangle_data-sex` = "sex", wait_ = FALSE) + app$set_inputs(`wrangle_data-weight` = "weight", wait_ = FALSE) + app$set_inputs(`wrangle_data-height` = "height", wait_ = FALSE) + app$set_inputs(`wrangle_data-muac` = "muac", wait_ = FALSE) + + ### Click wrangle button and wait the app to idle ---- + app$click(input = "wrangle_data-apply_wrangle") + app$wait_for_idle(timeout = 40000) + + ### Click on the Prevalence tab and wait the app to idle ---- + app$click(selector = "a[data-value='Prevalence Analysis']") + app$wait_for_idle(timeout = 40000) + + ### Select source of data ---- + app$set_inputs(`prevalence-source` = "survey", wait_ = FALSE) + + ### Select the method ---- + app$set_inputs(`prevalence-amn_method_survey` = "combined", wait_ = TRUE) + app$set_inputs(`prevalence-area1` = "province", wait_ = FALSE) + app$set_inputs(`prevalence-area2` = "strata", wait_ = FALSE) ## Assume sex as grouping var + app$set_inputs(`prevalence-area3` = "sex", wait_ = FALSE) + app$set_inputs(`prevalence-wts` = "", wait_ = FALSE) + app$set_inputs(`prevalence-oedema` = "oedema", wait_ = FALSE) + + ### Click on Estime Prevalence button ---- + app$click(input = "prevalence-estimate") + app$wait_for_value(output = "prevalence-results", timeout = 40000) + + ### Capture JavaScript expressions to return results's cols and values ---- + js_cols <- "$('#prevalence-results thead th').map(function() + {return $(this).text();}).get();" + + js_values <- "$('#prevalence-results tbody tr').map(function() + {return $(this).text();}).get();" + + ### Capture prevalence results of Nampula Province, Urban Strata ---- + glued_results <- app$get_js(js_values)[[3]] + pop <- sub("1", "", stringr::str_extract(glued_results, "\\d{4}")) + prev <- stringr::str_extract(glued_results, "\\d{2}\\.\\d") + + ### Test check ---- + testthat::expect_equal(length(app$get_js(js_cols)[1:19]), 19) + testthat::expect_equal(as.numeric(prev), 10.5) # GAM + testthat::expect_equal(as.numeric(pop), 276) + + ### Stop the app ---- + app$stop() + } +) + +## ---- Screening data --------------------------------------------------------- + + +### When age is available ---- testthat::test_that( desc = "Module works well to estimate prevalence from screening", code = { @@ -415,12 +679,6 @@ testthat::test_that( ) ### When age is given in categories ---- - -#### Skip test on windows ---- -# if (identical(Sys.getenv("CI"), "true") && Sys.info()[["sysname"]] == "Windows") { -# skip("Skipping shinytest2 integration tests on Windows CI to reduce runtime") -# } - testthat::test_that( desc = "Prevalence tab works as expected when age is given in categories", code = { diff --git a/tests/testthat/test-module-wrangling.R b/tests/testthat/test-module-wrangling.R index f803c3d..ab3afe2 100644 --- a/tests/testthat/test-module-wrangling.R +++ b/tests/testthat/test-module-wrangling.R @@ -6,11 +6,6 @@ ## ---- Data Wrangling: WFHZ --------------------------------------------------- -### Skip test on windows ---- -# if (identical(Sys.getenv("CI"), "true") && Sys.info()[["sysname"]] == "Windows") { -# skip("Skipping shinytest2 integration tests on Windows CI to reduce runtime") -# } - testthat::test_that(desc = "Server data wrangling works as expected for WFHZ", { ## Initialise app ---- app <- shinytest2::AppDriver$new( @@ -70,13 +65,80 @@ testthat::test_that(desc = "Server data wrangling works as expected for WFHZ", { }) -## ---- Data Wrangling: MFAZ --------------------------------------------------- +### When user supplies dos and dob for age wrangling ---- + +testthat::test_that(desc = "Server data wrangling wrangles age correctly in WFHZ", { + ## Initialise app ---- + app <- shinytest2::AppDriver$new( + app_dir = testthat::test_path("fixtures"), + load_timeout = 120000, + wait = TRUE + ) + + ### Let the app load ---- + app$wait_for_idle(timeout = 40000) + + ### Click on the Data uploading navbar ---- + app$click(selector = "a[data-value='Data Upload']") + app$wait_for_idle(timeout = 40000) + + #### Create a toy dataset ---- + data <- data.frame( + dos = c("26/02/2026", "26/02/2026", "26/02/2026", "26/02/2026", "26/02/2026"), + dob = c("12/05/2024", "14/07/2025", "22/03/2024", "20/07/2024", "20/09/2021"), + age = c(NA, NA, NA, NA, 28), + sex = c("m", "f", "m", "f", "f"), + muac = c(121, 124, 132, 117, 100), + weight = c(12.3, 13.3, 14.5, 15.5, 10.0), + height = c(110.3, 117.2, 119.2, 80.6, 98.9) + ) + tempfile <- tempfile(fileext = ".csv") + write.csv(data, tempfile, row.names = FALSE) + #### Upload onto the app ---- + app$upload_file(`upload_data-upload` = tempfile, wait_ = TRUE) + + ### Click on the data wrangling tab ---- + app$click(selector = "a[data-value='Data Wrangling']") + app$wait_for_idle(timeout = 40000) -### Skip test on windows ---- -# if (identical(Sys.getenv("CI"), "true") && Sys.info()[["sysname"]] == "Windows") { -# skip("Skipping shinytest2 integration tests on Windows CI to reduce runtime") -# } + ### Select input variables ---- + app$set_inputs(`wrangle_data-wrangle` = "wfhz", wait_ = FALSE) + app$set_inputs(`wrangle_data-dos` = "dos", wait_ = FALSE) + app$set_inputs(`wrangle_data-dob` = "dob", wait_ = FALSE) + app$set_inputs(`wrangle_data-age` = "age", wait_ = FALSE) + app$set_inputs(`wrangle_data-sex` = "sex", wait_ = FALSE) + app$set_inputs(`wrangle_data-weight` = "weight", wait_ = FALSE) + app$set_inputs(`wrangle_data-height` = "height", wait_ = FALSE) + + ### Click wrangle button ---- + app$click(input = "wrangle_data-apply_wrangle") + app$wait_for_value(output = "wrangle_data-wrangled", timeout = 40000) + + ### Get wrangled values ---- + column_names <- app$get_js(" + $('#wrangle_data-wrangled thead th').map(function() { + return $(this).text(); + }).get(); + ") |> as.character() + + ### Capture JavaScript expressions to return results ---- + js_results <- app$get_js("$('#wrangle_data-wrangled tbody tr').map(function() + {return $(this).text();}).get();") + + age_mo <- stringr::str_extract(js_results[[1]], "\\d{2}\\.\\d{2}") + age_28 <- stringr::str_extract(js_results[[5]], stringr::fixed("28")) + + testthat::expect_true("age_days" %in% column_names) + testthat::expect_equal(as.numeric(age_mo), 21.51) + testthat::expect_equal(as.numeric(age_28), 28) + + #### Stop the app ---- + app$stop() +}) + + +## ---- Data Wrangling: MFAZ --------------------------------------------------- testthat::test_that(desc = "Server data wrangling works as expected for MFAZ", { @@ -111,8 +173,7 @@ testthat::test_that(desc = "Server data wrangling works as expected for MFAZ", { app$wait_for_idle(timeout = 40000) ### Set the wrangling method to MFAZ ---- - app$set_inputs(`wrangle_data-wrangle` = "mfaz", wait_ = FALSE) - Sys.sleep(3) + app$set_inputs(`wrangle_data-wrangle` = "mfaz", wait_ = TRUE) ### Select variables ---- app$set_inputs(`wrangle_data-dos` = "", wait_ = FALSE) app$set_inputs(`wrangle_data-dob` = "", wait_ = FALSE) @@ -141,13 +202,78 @@ testthat::test_that(desc = "Server data wrangling works as expected for MFAZ", { }) -## ---- Data Wrangling: MUAC --------------------------------------------------- +### When user supplies dos and dob for age wrangling ---- +testthat::test_that(desc = "Server data wrangling wrangles age correctly in MFAZ", { + ## Initialise app ---- + app <- shinytest2::AppDriver$new( + app_dir = testthat::test_path("fixtures"), + load_timeout = 120000, + wait = TRUE + ) + ### Let the app load ---- + app$wait_for_idle(timeout = 40000) + + ### Click on the Data uploading navbar ---- + app$click(selector = "a[data-value='Data Upload']") + app$wait_for_idle(timeout = 40000) + + #### Create a toy dataset ---- + data <- data.frame( + dos = c("26/02/2026", "26/02/2026", "26/02/2026", "26/02/2026", "26/02/2026"), + dob = c("12/05/2024", "14/07/2025", "22/03/2024", "20/07/2024", "20/09/2021"), + age = c(NA, NA, NA, NA, 28), + sex = c("m", "f", "m", "f", "f"), + muac = c(121, 124, 132, 117, 100) + ) + tempfile <- tempfile(fileext = ".csv") + write.csv(data, tempfile, row.names = FALSE) + + #### Upload onto the app ---- + app$upload_file(`upload_data-upload` = tempfile, wait_ = TRUE) + + ### Click on the data wrangling tab ---- + app$click(selector = "a[data-value='Data Wrangling']") + app$wait_for_idle(timeout = 40000) + + ### Set the wrangling method to MFAZ ---- + app$set_inputs(`wrangle_data-wrangle` = "mfaz", wait_ = TRUE) + ### Select variables ---- + app$set_inputs(`wrangle_data-dos` = "dos", wait_ = FALSE) + app$set_inputs(`wrangle_data-dob` = "dob", wait_ = FALSE) + app$set_inputs(`wrangle_data-age` = "age", wait_ = FALSE) + app$set_inputs(`wrangle_data-sex` = "sex", wait_ = FALSE) + app$set_inputs(`wrangle_data-muac` = "muac", wait_ = FALSE) + + ### Click wrangle button ---- + app$click(input = "wrangle_data-apply_wrangle", wait_ = TRUE, timeout_ = 15000) + app$wait_for_value(output = "wrangle_data-wrangled", timeout = 40000) + + ### Get wrangled values ---- + column_names <- app$get_js(" + $('#wrangle_data-wrangled thead th').map(function() { + return $(this).text(); + }).get(); + ") |> as.character() + + ### Capture JavaScript expressions to return results ---- + js_results <- app$get_js("$('#wrangle_data-wrangled tbody tr').map(function() + {return $(this).text();}).get();") + + age_mo <- stringr::str_extract(js_results[[1]], "\\d{2}\\.\\d{2}") + age_28 <- stringr::str_extract(js_results[[5]], stringr::fixed("28")) + + testthat::expect_true("age_days" %in% column_names) + testthat::expect_equal(as.numeric(age_mo), 21.51) + testthat::expect_equal(as.numeric(age_28), 28) + + #### Stop the app ---- + app$stop() +}) + + +## ---- Data Wrangling: MUAC --------------------------------------------------- -### Skip test on windows ---- -# if (identical(Sys.getenv("CI"), "true") && Sys.info()[["sysname"]] == "Windows") { -# skip("Skipping shinytest2 integration tests on Windows CI to reduce runtime") -# } ### When age is given in categories ---- testthat::test_that( @@ -216,11 +342,6 @@ testthat::test_that( ## ---- Data Wrangling: WFHZ and MFAZ ------------------------------------------ -### Skip test on windows ---- -# if (identical(Sys.getenv("CI"), "true") && Sys.info()[["sysname"]] == "Windows") { -# skip("Skipping shinytest2 integration tests on Windows CI to reduce runtime") -# } - testthat::test_that( desc = "Server data wrangling works as expected for combined wrangling", { @@ -255,7 +376,7 @@ testthat::test_that( app$wait_for_idle(timeout = 40000) ### Select input variables ---- - app$set_inputs(`wrangle_data-wrangle` = "combined", wait_ = FALSE) + app$set_inputs(`wrangle_data-wrangle` = "combined", wait_ = TRUE) app$set_inputs(`wrangle_data-dos` = "", wait_ = FALSE) app$set_inputs(`wrangle_data-dob` = "", wait_ = FALSE) app$set_inputs(`wrangle_data-age` = "age", wait_ = FALSE) @@ -269,10 +390,86 @@ testthat::test_that( app$wait_for_value(output = "wrangle_data-wrangled", timeout = 40000) app$wait_for_idle(timeout = 15000) - + testthat::expect_true(app$get_js("$('#wrangle_data-wrangled').length > 0")) #### Stop the app ---- app$stop() } ) + + +### When user supplies dos and dob for age wrangling ---- +testthat::test_that(desc = "Server data wrangling wrangles age correctly in +combined data wrangling", { + ## Initialise app ---- + app <- shinytest2::AppDriver$new( + app_dir = testthat::test_path("fixtures"), + load_timeout = 120000, + wait = TRUE + ) + + ### Let the app load ---- + app$wait_for_idle(timeout = 40000) + + ### Click on the Data uploading navbar ---- + app$click(selector = "a[data-value='Data Upload']") + app$wait_for_idle(timeout = 40000) + + #### Create a toy dataset ---- + data <- data.frame( + dos = c("26/02/2026", "26/02/2026", "26/02/2026", "26/02/2026", "26/02/2026"), + dob = c("12/05/2024", "14/07/2025", "22/03/2024", "20/07/2024", "20/09/2021"), + age = c(NA, NA, NA, NA, 28), + sex = c("m", "f", "m", "f", "f"), + muac = c(121, 124, 132, 117, 100), + weight = c(12.3, 13.3, 14.5, 15.5, 10.0), + height = c(110.3, 117.2, 119.2, 80.6, 98.9) + ) + tempfile <- tempfile(fileext = ".csv") + write.csv(data, tempfile, row.names = FALSE) + + #### Upload onto the app ---- + app$upload_file(`upload_data-upload` = tempfile, wait_ = TRUE) + + ### Click on the data wrangling tab ---- + app$click(selector = "a[data-value='Data Wrangling']") + app$wait_for_idle(timeout = 40000) + + ### Select input variables ---- + app$set_inputs(`wrangle_data-wrangle` = "combined", wait_ = TRUE) + app$set_inputs(`wrangle_data-dos` = "dos", wait_ = FALSE) + app$set_inputs(`wrangle_data-dob` = "dob", wait_ = FALSE) + app$set_inputs(`wrangle_data-age` = "age", wait_ = FALSE) + app$set_inputs(`wrangle_data-sex` = "sex", wait_ = FALSE) + app$set_inputs(`wrangle_data-weight` = "weight", wait_ = FALSE) + app$set_inputs(`wrangle_data-height` = "height", wait_ = FALSE) + app$set_inputs(`wrangle_data-muac` = "muac", wait_ = FALSE) + + ### Click wrangle button ---- + app$click(input = "wrangle_data-apply_wrangle") + app$wait_for_value(output = "wrangle_data-wrangled", timeout = 40000) + + app$wait_for_idle(timeout = 15000) + + ## Get wrangled values ---- + column_names <- app$get_js(" + $('#wrangle_data-wrangled thead th').map(function() { + return $(this).text(); + }).get(); + ") |> as.character() + + ### Capture JavaScript expressions to return results ---- + js_results <- app$get_js("$('#wrangle_data-wrangled tbody tr').map(function() + {return $(this).text();}).get();") + + age_mo <- stringr::str_extract(js_results[[1]], "\\d{2}\\.\\d{2}") + age_28 <- stringr::str_extract(js_results[[5]], stringr::fixed("28")) + + testthat::expect_true("age_days" %in% column_names) + testthat::expect_equal(as.numeric(age_mo), 21.51) + testthat::expect_equal(as.numeric(age_28), 28) + + #### Stop the app ---- + app$stop() +})