Skip to content

Commit 616a157

Browse files
committed
Add additional tests to increase coverage
1 parent 9556985 commit 616a157

2 files changed

Lines changed: 170 additions & 31 deletions

File tree

R/spec_builder.R

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -556,15 +556,15 @@ spec_type_to_var_spec <- function(
556556
if (!"dataset" %in% names(out)) {
557557
dups <- out |>
558558
distinct() |>
559-
count(variable) |>
559+
dplyr::count(variable) |>
560560
filter(n > 1) |>
561561
pull(variable)
562562

563563
if (length(dups) > 0) {
564564
cli_abort(c(
565-
col_red("The following variables are repeated with different metadata for different datasets:"),
566-
"i" = ansi_collapse(dups),
567-
"i" = "Please add 'dataset' = [Name of dataset column] to your named cols vector to correct this."
565+
"x" = "The following variables are repeated with different metadata for different datasets: {dups}",
566+
"i" = "Please add {.val dataset} = \"<name of dataset column>\" to your named cols vector to correct this.",
567+
"i" = "E.g. \"dataset\" = \"[D|d]ataset\""
568568
))
569569
}
570570
} else {
@@ -769,8 +769,8 @@ spec_type_to_value_spec <- function(
769769
out <- bind_rows(out, var_out)
770770
}
771771

772-
if (where_sep_sheet && "where" %in% names(out)) {
773-
where_df <- create_tbl(doc, where_cols, context = spec_type_to_value_spec) |>
772+
if (where_sep_sheet && any(!is.na(out$where))) {
773+
where_df <- create_tbl(doc, where_cols, context = "spec_type_to_value_spec") |>
774774
tidyr::unite("where_new", starts_with("where"), sep = " ", na.rm = TRUE, remove = FALSE) |>
775775
select(id, where_new)
776776

@@ -1574,11 +1574,11 @@ build_from_sheet <- function(sheet_data, cols, context, sheet_name = NULL) {
15741574

15751575
if (length(nm_test) > 0) {
15761576
test_exact <- cols[names(nm_test)] |>
1577-
paste0("^", ., "$") |>
1577+
(\(x) paste0("^", x, "$"))() |>
15781578
map_int(~ sum(str_detect(sheet_names, .))) |>
15791579
keep(~ . != 1)
15801580
if (length(test_exact) == 0) {
1581-
cols[names(nm_test)] <- cols[names(nm_test)] |> paste0("^", ., "$")
1581+
cols[names(nm_test)] <- cols[names(nm_test)] |> (\(x) paste0("^", x, "$"))()
15821582
} else {
15831583
errors <- NULL
15841584
for (i in seq_along(nm_test)) {

tests/testthat/test-reader.R

Lines changed: 162 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -649,37 +649,176 @@ test_that("define_to_metacore(quiet) deprecation message is output when supplied
649649
)
650650
})
651651

652-
test_that("Informative error when where_sep_sheet=TRUE but WhereClause sheet missing", {
653-
# This should trigger the helpful error message about where_sep_sheet
654-
expect_error(
655-
spec_to_metacore(
656-
"spec_no_val.xlsx", # Use relative path like the existing test
657-
where_sep_sheet = TRUE, # This is the default, but being explicit
658-
verbose = "silent"
659-
),
660-
regexp = "where.*where_sep_sheet",
661-
ignore.case = TRUE
662-
)
663-
664-
# Verify the error message contains helpful context
665-
err <- tryCatch(
652+
test_that("spec_to_metacore warns when where_sep_sheet=TRUE but no WHERE IDs exist in the spec", {
653+
# spec_no_val.xlsx has no WHERE clause references (all-NA where column)
654+
expect_warning(
666655
spec_to_metacore(
667656
"spec_no_val.xlsx",
668657
where_sep_sheet = TRUE,
669-
verbose = "silent"
658+
verbose = "warn"
670659
),
671-
error = function(e) conditionMessage(e)
660+
regexp = "where column needed"
661+
)
662+
})
663+
664+
test_that("spec_type_to_value_spec warns when where_sep_sheet=TRUE but all where values are NA", {
665+
val_sheet <- tibble::tibble(
666+
Dataset = "ADSL",
667+
Variable = "AGE",
668+
Origin = "Derived",
669+
Type = "Num",
670+
Predecessor = NA_character_
671+
)
672+
doc <- list(ValueSpec = val_sheet)
673+
cols <- c(
674+
dataset = "^Dataset$",
675+
variable = "^Variable$",
676+
origin = "^Origin$",
677+
type = "^Type$",
678+
predecessor = "^Predecessor$"
679+
)
680+
681+
expect_warning(
682+
spec_type_to_value_spec(doc, cols = cols, where_sep_sheet = TRUE, var_sheet = NULL),
683+
regexp = "where column needed"
672684
)
685+
})
673686

674-
# Check that the error message mentions:
675-
# 1. That columns couldn't be matched
676-
expect_match(err, "Unable to identify a sheet|Could not find matching columns", ignore.case = TRUE)
687+
test_that("spec_type_to_value_spec replaces where IDs with text from the separate where sheet", {
688+
val_sheet <- tibble::tibble(
689+
Dataset = "ADSL",
690+
Variable = "AGE",
691+
Origin = "Derived",
692+
Type = "Num",
693+
Predecessor = NA_character_,
694+
Where = "W01"
695+
)
696+
where_sheet <- tibble::tibble(
697+
ID = "W01",
698+
Variable = "AGEGR",
699+
Comparator = "GE",
700+
Value = "18"
701+
)
702+
doc <- list(ValueSpec = val_sheet, WhereSheet = where_sheet)
703+
cols <- c(
704+
dataset = "^Dataset$",
705+
variable = "^Variable$",
706+
origin = "^Origin$",
707+
type = "^Type$",
708+
predecessor = "^Predecessor$",
709+
where = "^Where$"
710+
)
677711

678-
# 2. Provides the helpful tip about where_sep_sheet
679-
expect_match(err, "where_sep_sheet", ignore.case = TRUE)
712+
result <- spec_type_to_value_spec(doc, cols = cols, where_sep_sheet = TRUE, var_sheet = NULL)
680713

681-
# 3. Shows which sheet was closest
682-
expect_match(err, "Sheet|Closest", ignore.case = TRUE)
714+
expect_equal(result$where, "AGEGR GE 18")
715+
})
716+
717+
test_that("spec_type_to_value_spec auto-generates derivation_id from origin when not in cols", {
718+
val_sheet <- tibble::tibble(
719+
Dataset = c("ADSL", "ADSL"),
720+
Variable = c("AGE", "VISIT"),
721+
Origin = c("Assigned", "Derived"),
722+
Type = c("Num", "Char"),
723+
Predecessor = c(NA_character_, NA_character_)
724+
)
725+
doc <- list(ValueSpec = val_sheet)
726+
# No derivation_id in cols — auto-generated at lines 786-795
727+
cols <- c(
728+
dataset = "^Dataset$",
729+
variable = "^Variable$",
730+
origin = "^Origin$",
731+
type = "^Type$",
732+
predecessor = "^Predecessor$"
733+
)
734+
735+
result <- spec_type_to_value_spec(doc, cols = cols, where_sep_sheet = FALSE, var_sheet = NULL)
736+
737+
# origin "Assigned" → dataset.variable
738+
expect_equal(result$derivation_id[result$variable == "AGE"], "ADSL.AGE")
739+
# other origin → pred.dataset.variable
740+
expect_equal(result$derivation_id[result$variable == "VISIT"], "pred.ADSL.VISIT")
741+
})
742+
743+
test_that("spec_type_to_var_spec errors when duplicate variables have different metadata without dataset col", {
744+
vars_sheet <- tibble::tibble(
745+
Variable = c("VISIT", "VISIT"),
746+
Length = c("20", "40"), # different lengths → same variable, different metadata
747+
Label = c("Visit", "Visit"),
748+
Type = c("Char", "Char"),
749+
Format = c(NA_character_, NA_character_)
750+
)
751+
doc <- list(Variables = vars_sheet)
752+
cols <- c(
753+
variable = "^Variable$",
754+
length = "^Length$",
755+
label = "^Label$",
756+
type = "^Type$",
757+
format = "^Format$"
758+
)
759+
760+
expect_error(
761+
spec_type_to_var_spec(doc, cols = cols),
762+
regexp = "repeated with different metadata"
763+
)
764+
expect_error(
765+
spec_type_to_var_spec(doc, cols = cols),
766+
regexp = "VISIT"
767+
)
768+
})
769+
770+
test_that("spec_type_to_var_spec passes when duplicate variables have identical metadata without dataset col", {
771+
vars_sheet <- tibble::tibble(
772+
Variable = c("VISIT", "VISIT"),
773+
Length = c("20", "20"), # identical rows — distinct() collapses to one
774+
Label = c("Visit", "Visit"),
775+
Type = c("Char", "Char"),
776+
Format = c(NA_character_, NA_character_)
777+
)
778+
doc <- list(Variables = vars_sheet)
779+
cols <- c(
780+
variable = "^Variable$",
781+
length = "^Length$",
782+
label = "^Label$",
783+
type = "^Type$",
784+
format = "^Format$"
785+
)
786+
787+
result <- spec_type_to_var_spec(doc, cols = cols)
788+
789+
expect_equal(nrow(result), 1L)
790+
expect_equal(result$variable, "VISIT")
791+
})
792+
793+
test_that("build_from_sheet resolves ambiguous regex via exact anchoring", {
794+
# "label" partially matches both "label" and "label_extra"; ^label$ matches only "label"
795+
sheet_data <- tibble::tibble(label = 1:3, label_extra = 4:6, other = 7:9)
796+
cols <- c(lbl = "label", oth = "other")
797+
798+
result <- metacore:::build_from_sheet(sheet_data, cols, context = "test_table", sheet_name = "TestSheet")
799+
800+
expect_equal(result$lbl, 1:3)
801+
expect_equal(result$oth, 7:9)
802+
})
803+
804+
test_that("build_from_sheet errors when exact anchoring still leaves ambiguity", {
805+
# "label" matches "label_1" and "label_2"; ^label$ matches neither
806+
sheet_data <- tibble::tibble(label_1 = 1:3, label_2 = 4:6)
807+
cols <- c(lbl = "label")
808+
809+
expect_error(
810+
metacore:::build_from_sheet(sheet_data, cols, context = "test_table", sheet_name = "MySheet"),
811+
regexp = "Unable to rename"
812+
)
813+
expect_error(
814+
metacore:::build_from_sheet(sheet_data, cols, context = "test_table", sheet_name = "MySheet"),
815+
regexp = "Please check your regular expression for `test_table`"
816+
)
817+
# NULL context uses the generic hint
818+
expect_error(
819+
metacore:::build_from_sheet(sheet_data, cols, context = NULL, sheet_name = "MySheet"),
820+
regexp = "Please check your regular expressions"
821+
)
683822
})
684823

685824
test_that("spec_to_metacore provides detailed information for failed regular expressions", {

0 commit comments

Comments
 (0)