Skip to content
Closed
Show file tree
Hide file tree
Changes from 13 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
72 changes: 51 additions & 21 deletions R/tm_outliers.R
Original file line number Diff line number Diff line change
Expand Up @@ -438,11 +438,33 @@ srv_outliers <- function(id, data, reporter, filter_panel_api, outlier_var,
}
})

anl_merged_input <- teal.transform::merge_expression_srv(
selector_list = reactive_select_input,
datasets = data,
merge_function = "dplyr::inner_join"
)
anl_merged_input <- reactive({
dataname_first <- names(data())[[1]]
join_keys <- teal.data::join_keys(data())[dataname_first, dataname_first]

if (length(join_keys) == 0) {
# No join keys - single dataset, no merging needed
# Return the same structure as merge_expression_srv but with simple assignment
list(
expr = substitute(ANL <- dataname, list(dataname = as.name(dataname_first))),
columns_source = list(
outlier_var = reactive_select_input()$outlier_var()$select,
categorical_var = if (!is.null(reactive_select_input()$categorical_var)) {
names(reactive_select_input()$categorical_var()$filter)
} else {
character(0)
}
)
)
} else {
# Join keys exist - use merge_expression_srv
teal.transform::merge_expression_srv(
selector_list = reactive_select_input,
datasets = data,
merge_function = "dplyr::inner_join"
)()
}
})

anl_merged_q <- reactive({
req(anl_merged_input())
Expand Down Expand Up @@ -616,25 +638,33 @@ srv_outliers <- function(id, data, reporter, filter_panel_api, outlier_var,
)

# ANL_OUTLIER_EXTENDED is the base table
qenv <- teal.code::eval_code(
qenv,
substitute(
expr = {
ANL_OUTLIER_EXTENDED <- dplyr::left_join(
ANL_OUTLIER,
dplyr::select(
dataname,
dplyr::setdiff(names(dataname), dplyr::setdiff(names(ANL_OUTLIER), join_keys))
),
by = join_keys
join_keys <- as.character(teal.data::join_keys(data())[dataname_first, dataname_first])

if (length(join_keys) == 0) {
# No join keys - single dataset, no join needed
qenv <- teal.code::eval_code(qenv, quote(ANL_OUTLIER_EXTENDED <- ANL_OUTLIER))
} else {
# Join keys exist - perform left join
qenv <- teal.code::eval_code(
qenv,
substitute(
expr = {
ANL_OUTLIER_EXTENDED <- dplyr::left_join(
ANL_OUTLIER,
dplyr::select(
dataname,
dplyr::setdiff(names(dataname), dplyr::setdiff(names(ANL_OUTLIER), join_keys))
),
by = join_keys
)
},
env = list(
dataname = as.name(dataname_first),
join_keys = join_keys
)
},
env = list(
dataname = as.name(dataname_first),
join_keys = as.character(teal.data::join_keys(data())[dataname_first, dataname_first])
)
)
)
}

qenv <- if (length(categorical_var) > 0) {
qenv <- teal.code::eval_code(
Expand Down
66 changes: 66 additions & 0 deletions tests/testthat/test-shinytest2-tm_outliers.R
Original file line number Diff line number Diff line change
Expand Up @@ -319,3 +319,69 @@ testthat::test_that("e2e - tm_outliers: Outlier table is displayed with proper c

app_driver$stop()
})

testthat::test_that("e2e - tm_outliers: works without join keys", {
# Test for issue where tm_outliers fails if data has no joining keys
# This test reproduces the exact scenario described in the issue
testthat::skip("chromium")
skip_if_too_deep(5)

# Create data without join keys (as per issue description)
data <- teal.data::teal_data()
data <- within(data, {
CO2 <- CO2 # nolint: object_name
})
# Note: No join_keys defined here, which should NOT cause the issue after fix

vars <- teal.transform::choices_selected(
teal.transform::variable_choices(
data[["CO2"]],
c("Plant", "Type", "Treatment")
)
)

# This should NOT fail after the fix
app_driver <- init_teal_app_driver(
data = data,
modules = tm_outliers(
outlier_var = list(
teal.transform::data_extract_spec(
dataname = "CO2",
select = teal.transform::select_spec(
label = "Select variable:",
choices = teal.transform::variable_choices(data[["CO2"]], c("conc", "uptake")),
selected = "uptake",
multiple = FALSE,
fixed = FALSE
)
)
),
categorical_var = list(
teal.transform::data_extract_spec(
dataname = "CO2",
filter = teal.transform::filter_spec(
vars = vars,
choices = teal.transform::value_choices(data[["CO2"]], vars$selected),
selected = teal.transform::value_choices(data[["CO2"]], vars$selected),
multiple = TRUE
)
)
),
ggplot2_args = list(
teal.widgets::ggplot2_args(
labs = list(subtitle = "Plot generated by Outliers Module")
)
)
)
)

app_driver$expect_no_shiny_error()

# Verify the module loads correctly
testthat::expect_equal(
app_driver$get_text("#teal-teal_modules-active_tab .active"),
"Outliers Module"
)

app_driver$stop()
})
Loading