Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 38 additions & 5 deletions R/tm_missing_data.R
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,9 @@ ui_missing_data <- function(id, by_subject_plot = FALSE) {
),
tabPanel(
"By Variable Levels",
teal.widgets::plot_with_settings_ui(id = ns("by_variable_plot"))
teal.widgets::plot_with_settings_ui(id = ns("by_variable_plot")),
tags$br(),
DT::dataTableOutput(ns("levels_table"))
)
)
if (isTRUE(by_subject_plot)) {
Expand Down Expand Up @@ -468,7 +470,12 @@ srv_missing_data <- function(id,
iv_summary_table$add_rule("count_type", shinyvalidate::sv_required("Please select type of counts"))
iv_summary_table$add_rule(
"group_by_vals",
shinyvalidate::sv_required("Please select both group-by variable and values")
~ if (!is.null(.) && length(.) == 0) {
"Please select both group-by variable and values"
} else if (is.null(.)) {
# Input doesn't exist yet, skip validation
NULL
}
)
iv_summary_table$add_rule(
"group_by_var",
Expand Down Expand Up @@ -645,10 +652,11 @@ srv_missing_data <- function(id,
})

output$group_by_vals_ui <- renderUI({
req(isolate(prev_group_by_var()), input$group_by_var, data_r())
req(input$group_by_var, data_r())

choices <- teal.transform::value_choices(data_r(), input$group_by_var, input$group_by_var)
prev_choices <- req(isolate(input$group_by_vals))
prev_choices <- isolate(input$group_by_vals)
prev_group_var <- isolate(prev_group_by_var())

# determine selected value based on filtered data
# display those previously selected values that are still available
Expand All @@ -657,7 +665,7 @@ srv_missing_data <- function(id,
} else if (
!is.null(prev_choices) &&
!any(prev_choices %in% choices) &&
isolate(prev_group_by_var()) == input$group_by_var
prev_group_var == input$group_by_var && prev_group_var != ""
) {
# if not any previously selected value is available and the grouping variable is the same,
# then display NULL
Expand Down Expand Up @@ -1249,6 +1257,12 @@ srv_missing_data <- function(id,
)
}

# Store summary_data in qenv for table display
tile <- teal.code::eval_code(
tile,
quote(levels_table_data <- summary_data)
)

tile
})

Expand Down Expand Up @@ -1426,6 +1440,14 @@ srv_missing_data <- function(id,
req(decorated_by_variable_plot_q())[["by_variable_plot"]]
})

levels_table_r <- reactive({
req(
input$summary_type == "By Variable Levels",
decorated_by_variable_plot_q()
)
decorated_by_variable_plot_q()[["levels_table_data"]]
})

by_subject_plot_r <- reactive({
req(decorated_by_subject_plot_q()[["by_subject_plot"]])
})
Expand Down Expand Up @@ -1470,6 +1492,17 @@ srv_missing_data <- function(id,
decorated_by_subject_plot_dims_q <- # nolint: object_length_linter.
set_chunk_dims(pws4, decorated_by_subject_plot_q)

output$levels_table <- DT::renderDT({
req(levels_table_r())
DT::datatable(
levels_table_r(),
options = list(
scrollX = TRUE,
pageLength = 25
)
)
})

decorated_final_q <- reactive({
sum_type <- req(input$summary_type)
if (sum_type == "Summary") {
Expand Down
27 changes: 24 additions & 3 deletions tests/testthat/test-shinytest2-tm_file_viewer.R
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,14 @@ test_that("e2e - tm_file_viewer: Shows selected image file", {
skip_if_too_deep(5)
app_driver <- app_driver_tm_file_viewer()

app_driver$click(selector = "[id= '4_anchor']")
# Find and click the png file anchor by text content
tree_selector <- app_driver$namespaces(TRUE)$module("tree")
tree_html <- app_driver$get_html_rvest(selector = tree_selector)
anchors <- rvest::html_nodes(tree_html, "a")
anchor_texts <- rvest::html_text(anchors)
png_idx <- which(anchor_texts == "png")
png_id <- rvest::html_attr(anchors[png_idx], "id")
app_driver$click(selector = paste0("[id='", png_id, "']"))
testthat::expect_true(app_driver$is_visible(app_driver$namespaces(TRUE)$module("output img")))

img_src <- app_driver$get_html_rvest(app_driver$namespaces(TRUE)$module("output")) %>%
Expand All @@ -60,7 +67,14 @@ test_that("e2e - tm_file_viewer: Shows selected text file", {
skip_if_too_deep(5)
app_driver <- app_driver_tm_file_viewer()

app_driver$click(selector = "[id= '5_anchor']")
# Find and click the txt file anchor by text content
tree_selector <- app_driver$namespaces(TRUE)$module("tree")
tree_html <- app_driver$get_html_rvest(selector = tree_selector)
anchors <- rvest::html_nodes(tree_html, "a")
anchor_texts <- rvest::html_text(anchors)
txt_idx <- which(anchor_texts == "txt")
txt_id <- rvest::html_attr(anchors[txt_idx], "id")
app_driver$click(selector = paste0("[id='", txt_id, "']"))
testthat::expect_true(app_driver$is_visible(app_driver$namespaces(TRUE)$module("output pre")))

pre_text <- app_driver$get_html_rvest(app_driver$namespaces(TRUE)$module("output")) %>%
Expand All @@ -82,7 +96,14 @@ test_that("e2e - tm_file_viewer: Shows selected url", {
skip_if_too_deep(5)
app_driver <- app_driver_tm_file_viewer()

app_driver$click(selector = "[id= '6_anchor']")
# Find and click the url anchor by text content
tree_selector <- app_driver$namespaces(TRUE)$module("tree")
tree_html <- app_driver$get_html_rvest(selector = tree_selector)
anchors <- rvest::html_nodes(tree_html, "a")
anchor_texts <- rvest::html_text(anchors)
url_idx <- which(anchor_texts == "url")
url_id <- rvest::html_attr(anchors[url_idx], "id")
app_driver$click(selector = paste0("[id='", url_id, "']"))
testthat::expect_true(app_driver$is_visible(app_driver$namespaces(TRUE)$module("output img")))

testthat::expect_equal(
Expand Down
67 changes: 59 additions & 8 deletions tests/testthat/test-shinytest2-tm_missing_data.R
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ test_that("e2e - tm_missing_data: Default settings and visibility of the summary

app_driver$click(selector = app_driver$namespaces(TRUE)$module("iris-any_na"))
app_driver$expect_no_validation_error()
app_driver$wait_for_idle()

testthat::expect_true(
app_driver$is_visible(
Expand All @@ -91,22 +92,33 @@ test_that("e2e - tm_missing_data: Check default settings and visibility of the c

app_driver$set_active_module_input("iris-summary_type", "Combinations")
app_driver$expect_no_validation_error()
app_driver$wait_for_idle()

testthat::expect_true(
app_driver$is_visible(
app_driver$namespaces(TRUE)$module("iris-combination_plot-plot_out_main .shiny-plot-output")
)
)

# combination encoding
app_driver$wait_for_idle()

testthat::expect_true(
app_driver$is_visible(
app_driver$namespaces(TRUE)$module("iris-cutoff .shiny-input-container")
)
)

testthat::expect_equal(app_driver$get_active_module_input("iris-combination_cutoff"), 1L)
app_driver$wait_for_idle()
# Wait for input to be available
cutoff_value <- app_driver$get_active_module_input("iris-combination_cutoff")
testthat::expect_true(!is.null(cutoff_value))
testthat::expect_true(is.numeric(cutoff_value))
# The default value is calculated based on data, so we just check it's a valid number >= 1
testthat::expect_true(cutoff_value >= 1L)

app_driver$set_active_module_input("iris-combination_cutoff", 10L)
app_driver$wait_for_idle()
testthat::expect_equal(app_driver$get_active_module_input("iris-combination_cutoff"), 10L)
app_driver$expect_no_validation_error()

Expand Down Expand Up @@ -148,15 +160,54 @@ test_that("e2e - tm_missing_data: Validate 'By Variable Levels' table values", {
app_driver <- app_driver_tm_missing_data()

app_driver$set_active_module_input("iris-summary_type", "By Variable Levels")
levels_table <- app_driver$namespaces(TRUE)$module("iris-levels_table") %>%
app_driver$get_html_rvest() %>%
rvest::html_table(fill = TRUE) %>%
.[[1]]
app_driver$wait_for_idle()

testthat::expect_setequal(
levels_table$Variable,
c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width")
# Wait for table to be visible and rendered
testthat::expect_true(
app_driver$is_visible(app_driver$namespaces(TRUE)$module("iris-levels_table"))
)
app_driver$wait_for_idle()

levels_table_html <- app_driver$namespaces(TRUE)$module("iris-levels_table") %>%
app_driver$get_html_rvest()

# DT tables typically have multiple tables in HTML - try both first and second
tables <- rvest::html_table(levels_table_html, fill = TRUE)

# Find the table with Variable column
levels_table <- NULL
for (i in seq_along(tables)) {
if ("Variable" %in% names(tables[[i]])) {
levels_table <- tables[[i]]
break
}
}

# If not found in html_table, try extracting from DT structure directly
if (is.null(levels_table)) {
# DT tables render with specific structure - try to get from tbody
table_rows <- levels_table_html %>%
rvest::html_nodes("tbody tr")

if (length(table_rows) > 0) {
# Extract first column (Variable) from each row
variable_cells <- levels_table_html %>%
rvest::html_nodes("tbody tr td:first-child") %>%
rvest::html_text(trim = TRUE)

testthat::expect_setequal(
variable_cells,
c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width")
)
} else {
testthat::skip("Table not yet rendered or empty")
}
} else {
testthat::expect_setequal(
levels_table$Variable,
c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width")
)
}

app_driver$stop()
})
Loading