From c0428f880f3933abc7102c24d0449cc84665555a Mon Sep 17 00:00:00 2001 From: "Paul W. Egeler, M.S., GStat" Date: Mon, 24 Jun 2019 13:48:18 -0400 Subject: [PATCH 1/4] moved metadata names into a sysdata file --- R/.Rbuildignore | 1 + R/R/REDCap_split.r | 9 +-------- R/R/sysdata.rda | Bin 0 -> 295 bytes R/data-raw/metadata_names.R | 10 ++++++++++ 4 files changed, 12 insertions(+), 8 deletions(-) create mode 100644 R/R/sysdata.rda create mode 100644 R/data-raw/metadata_names.R diff --git a/R/.Rbuildignore b/R/.Rbuildignore index e148253..7f78a9d 100644 --- a/R/.Rbuildignore +++ b/R/.Rbuildignore @@ -2,3 +2,4 @@ ^\.Rproj\.user$ ^\.travis\.yml$ ^appveyor\.yml$ +^data-raw$ diff --git a/R/R/REDCap_split.r b/R/R/REDCap_split.r index 4e45901..14f499d 100644 --- a/R/R/REDCap_split.r +++ b/R/R/REDCap_split.r @@ -87,14 +87,7 @@ REDCap_split <- function(records, metadata) { } # Standardize variable names for metadata - names(metadata) <- c( - "field_name", "form_name", "section_header", "field_type", - "field_label", "select_choices_or_calculations", "field_note", - "text_validation_type_or_show_slider_number", "text_validation_min", - "text_validation_max", "identifier", "branching_logic", "required_field", - "custom_alignment", "question_number", "matrix_group_name", "matrix_ranking", - "field_annotation" - ) + names(metadata) <- metadata_names # Make sure that no metadata columns are factors metadata <- rapply(metadata, as.character, classes = "factor", how = "replace") diff --git a/R/R/sysdata.rda b/R/R/sysdata.rda new file mode 100644 index 0000000000000000000000000000000000000000..0299f29acc10d71483fb818db38ea7f631055462 GIT binary patch literal 295 zcmV+?0oeXRT4*^jL0KkKS;$9c0{{SB|A78E_yGVA5C8-K5J120|KI=tFaY?g4H2Sh zZ&dI|20$7B15l4pXaE2J0iZD{>Zk1$9!*aW(i&vbO+8Q57>y4A9TBww&Itx{-{(C# zxR<*>I61;c!Ey~Db0DD!G$W72+>uTcBr*}%z`*O7dP@KR literal 0 HcmV?d00001 diff --git a/R/data-raw/metadata_names.R b/R/data-raw/metadata_names.R new file mode 100644 index 0000000..30d8c8c --- /dev/null +++ b/R/data-raw/metadata_names.R @@ -0,0 +1,10 @@ +metadata_names <- c( + "field_name", "form_name", "section_header", "field_type", + "field_label", "select_choices_or_calculations", "field_note", + "text_validation_type_or_show_slider_number", "text_validation_min", + "text_validation_max", "identifier", "branching_logic", "required_field", + "custom_alignment", "question_number", "matrix_group_name", "matrix_ranking", + "field_annotation" +) + +usethis::use_data(metadata_names, overwrite = TRUE, internal = TRUE) From 76420b527cc3008f3513ee228ad609c605334052 Mon Sep 17 00:00:00 2001 From: "Paul W. Egeler, M.S., GStat" Date: Mon, 1 Jul 2019 16:54:29 -0400 Subject: [PATCH 2/4] Closes #9. User can specify primary table label Incremented to v0.1.0 --- R/DESCRIPTION | 5 +- R/NEWS.md | 10 ++++ R/R/REDCap_split.r | 109 ++++++++++-------------------------------- R/R/utils.r | 76 +++++++++++++++++++++++++++++ R/man/REDCap_split.Rd | 5 +- 5 files changed, 118 insertions(+), 87 deletions(-) create mode 100644 R/NEWS.md create mode 100644 R/R/utils.r diff --git a/R/DESCRIPTION b/R/DESCRIPTION index 5372597..0a493f5 100644 --- a/R/DESCRIPTION +++ b/R/DESCRIPTION @@ -1,6 +1,6 @@ Package: REDCapRITS Title: REDCap Repeating Instrument Table Splitter -Version: 0.0.0 +Version: 0.1.0 Authors@R: c( person("Paul", "Egeler", email = "paul.egeler@spectrumhealth.org", role = c("aut", "cre")), person("Spectrum Health, Grand Rapids, MI", role = "cph")) @@ -18,9 +18,10 @@ Suggests: License: GPL-3 Encoding: UTF-8 LazyData: true -RoxygenNote: 6.0.1 +RoxygenNote: 6.1.1 URL: https://github.com/SpectrumHealthResearch/REDCapRITS BugReports: https://github.com/SpectrumHealthResearch/REDCapRITS/issues Collate: + 'utils.r' 'process_user_input.r' 'REDCap_split.r' diff --git a/R/NEWS.md b/R/NEWS.md new file mode 100644 index 0000000..4f5c340 --- /dev/null +++ b/R/NEWS.md @@ -0,0 +1,10 @@ +# REDCapRITS 0.1.0 (Release date: 2019-07-01) + + * [feature] User can now specify the name of the 'primary' table, which previously was left blank. (#9) + * [bug] Keeps REDCap-generated fields in non-repeating data.frame that are not present in metadata file. (#7) + * [enhancement] Unit tests created. (#6) + * [bug] Checkbox data now supported. (#1) + +# REDCapRITS 0.0.0 (Release date: 2018-06-03) + + * Initial Release diff --git a/R/R/REDCap_split.r b/R/R/REDCap_split.r index 14f499d..7e9236c 100644 --- a/R/R/REDCap_split.r +++ b/R/R/REDCap_split.r @@ -10,6 +10,8 @@ #' @param metadata Project metadata (the data dictionary). May be a #' \code{data.frame}, \code{response}, or \code{character} vector containing #' JSON from an API call. +#' @param primary_table_label Name of the label given to the list element for +#' the primary output table (as described in *README.md*). #' @author Paul W. Egeler, M.S., GStat #' @examples #' \dontrun{ @@ -66,9 +68,12 @@ #' } #' @return A list of \code{"data.frame"}s: one base table and zero or more #' tables for each repeating instrument. -#' @include process_user_input.r +#' @include process_user_input.r utils.r #' @export -REDCap_split <- function(records, metadata) { +REDCap_split <- function(records, + metadata, + primary_table_label = "" +) { # Process user input records <- process_user_input(records) @@ -78,12 +83,8 @@ REDCap_split <- function(records, metadata) { vars_in_data <- names(records) # Check to see if there were any repeating instruments - if (!any(vars_in_data == "redcap_repeat_instrument")) { - - message("There are no repeating instruments in this data.") - - return(list(records)) - + if (!"redcap_repeat_instrument" %in% vars_in_data) { + stop("There are no repeating instruments in this dataset.") } # Standardize variable names for metadata @@ -93,80 +94,7 @@ REDCap_split <- function(records, metadata) { metadata <- rapply(metadata, as.character, classes = "factor", how = "replace") # Find the fields and associated form - fields <- metadata[ - !metadata$field_type %in% c("descriptive", "checkbox"), - c("field_name", "form_name") - ] - - # Process instrument status fields - form_names <- unique(metadata$form_name) - form_complete_fields <- data.frame( - field_name = paste0(form_names, "_complete"), - form_name = form_names, - stringsAsFactors = FALSE - ) - - fields <- rbind(fields, form_complete_fields) - - # Process checkbox fields - if (any(metadata$field_type == "checkbox")) { - - checkbox_basenames <- metadata[ - metadata$field_type == "checkbox", - c("field_name", "form_name") - ] - - checkbox_fields <- - do.call( - "rbind", - apply( - checkbox_basenames, - 1, - function(x, y) - data.frame( - field_name = y[grepl(paste0("^", x[1], "___((?!\\.factor).)+$"), y, perl = TRUE)], - form_name = x[2], - stringsAsFactors = FALSE, - row.names = NULL - ), - y = vars_in_data - ) - ) - - fields <- rbind(fields, checkbox_fields) - - } - - # Process ".*\\.factor" fields supplied by REDCap's export data R script - if (any(grepl("\\.factor$", vars_in_data))) { - - factor_fields <- - do.call( - "rbind", - apply( - fields, - 1, - function(x, y) { - field_indices <- grepl(paste0("^", x[1], "\\.factor$"), y) - if (any(field_indices)) - data.frame( - field_name = y[field_indices], - form_name = x[2], - stringsAsFactors = FALSE, - row.names = NULL - ) - }, - y = vars_in_data - ) - ) - - fields <- rbind(fields, factor_fields) - - } - - # Identify the subtables in the data - subtables <- unique(records$redcap_repeat_instrument) - subtables <- subtables[subtables != ""] + fields <- match_fields_to_form(metadata, vars_in_data) # Variables to be present in each output table universal_fields <- c( @@ -187,13 +115,26 @@ REDCap_split <- function(records, metadata) { ) + # Identify the subtables in the data + subtables <- unique(records$redcap_repeat_instrument) + subtables <- subtables[subtables != ""] + # Split the table based on instrument out <- split.data.frame(records, records$redcap_repeat_instrument) + if (primary_table_label %in% subtables) { + warning( + "The label given to the primary table is already used by a repeating instrument.\n", + "The primary table label will be left blank." + ) + } else if (primary_table_label > "") { + names(out)[[which(names(out) == "")]] <- primary_table_label + } + # Delete the variables that are not relevant for (i in names(out)) { - if (i == "") { + if (i == primary_table_label) { out_fields <- which( vars_in_data %in% c( @@ -201,7 +142,7 @@ REDCap_split <- function(records, metadata) { fields[!fields[,2] %in% subtables, 1] ) ) - out[[which(names(out) == "")]] <- out[[which(names(out) == "")]][out_fields] + out[[which(names(out) == primary_table_label)]] <- out[[which(names(out) == primary_table_label)]][out_fields] } else { diff --git a/R/R/utils.r b/R/R/utils.r new file mode 100644 index 0000000..9115671 --- /dev/null +++ b/R/R/utils.r @@ -0,0 +1,76 @@ +match_fields_to_form <- function(metadata, vars_in_data) { + + fields <- metadata[ + !metadata$field_type %in% c("descriptive", "checkbox"), + c("field_name", "form_name") + ] + + # Process instrument status fields + form_names <- unique(metadata$form_name) + form_complete_fields <- data.frame( + field_name = paste0(form_names, "_complete"), + form_name = form_names, + stringsAsFactors = FALSE + ) + + fields <- rbind(fields, form_complete_fields) + + # Process checkbox fields + if (any(metadata$field_type == "checkbox")) { + + checkbox_basenames <- metadata[ + metadata$field_type == "checkbox", + c("field_name", "form_name") + ] + + checkbox_fields <- + do.call( + "rbind", + apply( + checkbox_basenames, + 1, + function(x, y) + data.frame( + field_name = y[grepl(paste0("^", x[1], "___((?!\\.factor).)+$"), y, perl = TRUE)], + form_name = x[2], + stringsAsFactors = FALSE, + row.names = NULL + ), + y = vars_in_data + ) + ) + + fields <- rbind(fields, checkbox_fields) + + } + + # Process ".*\\.factor" fields supplied by REDCap's export data R script + if (any(grepl("\\.factor$", vars_in_data))) { + + factor_fields <- + do.call( + "rbind", + apply( + fields, + 1, + function(x, y) { + field_indices <- grepl(paste0("^", x[1], "\\.factor$"), y) + if (any(field_indices)) + data.frame( + field_name = y[field_indices], + form_name = x[2], + stringsAsFactors = FALSE, + row.names = NULL + ) + }, + y = vars_in_data + ) + ) + + fields <- rbind(fields, factor_fields) + + } + + fields + + } diff --git a/R/man/REDCap_split.Rd b/R/man/REDCap_split.Rd index 8bd4793..9fdf018 100644 --- a/R/man/REDCap_split.Rd +++ b/R/man/REDCap_split.Rd @@ -4,7 +4,7 @@ \alias{REDCap_split} \title{Split REDCap repeating instruments table into multiple tables} \usage{ -REDCap_split(records, metadata) +REDCap_split(records, metadata, primary_table_label = "") } \arguments{ \item{records}{Exported project records. May be a \code{data.frame}, @@ -14,6 +14,9 @@ call.} \item{metadata}{Project metadata (the data dictionary). May be a \code{data.frame}, \code{response}, or \code{character} vector containing JSON from an API call.} + +\item{primary_table_label}{Name of the label given to the list element for +the primary output table (as described in *README.md*).} } \value{ A list of \code{"data.frame"}s: one base table and zero or more From e7be5c18088b8eacea2a1f90ba978549e0622390 Mon Sep 17 00:00:00 2001 From: "Paul W. Egeler, M.S., GStat" Date: Mon, 8 Jul 2019 12:19:33 -0400 Subject: [PATCH 3/4] Fixed bug introduced in previous commit, added test to check for bug Also started working on issue #10 --- R/R/REDCap_split.r | 112 ++++++++++++--------- R/man/REDCap_split.Rd | 21 +++- R/tests/testthat/test-primary-table-name.R | 38 +++++++ 3 files changed, 116 insertions(+), 55 deletions(-) create mode 100644 R/tests/testthat/test-primary-table-name.R diff --git a/R/R/REDCap_split.r b/R/R/REDCap_split.r index 7e9236c..d12db72 100644 --- a/R/R/REDCap_split.r +++ b/R/R/REDCap_split.r @@ -10,8 +10,11 @@ #' @param metadata Project metadata (the data dictionary). May be a #' \code{data.frame}, \code{response}, or \code{character} vector containing #' JSON from an API call. -#' @param primary_table_label Name of the label given to the list element for -#' the primary output table (as described in *README.md*). +#' @param primary_table_name Name given to the list element for the primary +#' output table (as described in \emph{README.md}). Ignored if +#' \code{forms = 'all'}. +#' @param forms Indicate whether to create separate tables for repeating +#' instruments only or for all forms. #' @author Paul W. Egeler, M.S., GStat #' @examples #' \dontrun{ @@ -66,13 +69,20 @@ #' # Split the tables #' REDCapRITS::REDCap_split(data, metadata) #' } -#' @return A list of \code{"data.frame"}s: one base table and zero or more -#' tables for each repeating instrument. +#' @return A list of \code{"data.frame"}s. The number of tables will differ +#' depending on the \code{forms} option selected. +#' \itemize{ +#' \item \code{'repeating'}: one base table and one or more +#' tables for each repeating instrument. +#' \item \code{'all'}: a data.frame for each instrument, regardless of +#' whether it is a repeating instrument or not. +#' } #' @include process_user_input.r utils.r #' @export REDCap_split <- function(records, metadata, - primary_table_label = "" + primary_table_name = "", + forms = c("repeating", "all") ) { # Process user input @@ -82,8 +92,11 @@ REDCap_split <- function(records, # Get the variable names in the dataset vars_in_data <- names(records) + # Match arg for forms + forms <- match.arg(forms) + # Check to see if there were any repeating instruments - if (!"redcap_repeat_instrument" %in% vars_in_data) { + if (forms == "repeating" && !"redcap_repeat_instrument" %in% vars_in_data) { stop("There are no repeating instruments in this dataset.") } @@ -107,56 +120,55 @@ REDCap_split <- function(records, ) ) - # Variables to be at the beginning of each repeating instrument - repeat_instrument_fields <- grep( - "^redcap_repeat.*", - vars_in_data, - value = TRUE - ) - - - # Identify the subtables in the data - subtables <- unique(records$redcap_repeat_instrument) - subtables <- subtables[subtables != ""] - - # Split the table based on instrument - out <- split.data.frame(records, records$redcap_repeat_instrument) - - if (primary_table_label %in% subtables) { - warning( - "The label given to the primary table is already used by a repeating instrument.\n", - "The primary table label will be left blank." + if ("redcap_repeat_instrument" %in% vars_in_data) { + # Variables to be at the beginning of each repeating instrument + repeat_instrument_fields <- grep( + "^redcap_repeat.*", + vars_in_data, + value = TRUE ) - } else if (primary_table_label > "") { - names(out)[[which(names(out) == "")]] <- primary_table_label - } - # Delete the variables that are not relevant - for (i in names(out)) { + # Identify the subtables in the data + subtables <- unique(records$redcap_repeat_instrument) + subtables <- subtables[subtables != ""] - if (i == primary_table_label) { - - out_fields <- which( - vars_in_data %in% c( - universal_fields, - fields[!fields[,2] %in% subtables, 1] - ) - ) - out[[which(names(out) == primary_table_label)]] <- out[[which(names(out) == primary_table_label)]][out_fields] - - } else { - - out_fields <- which( - vars_in_data %in% c( - universal_fields, - repeat_instrument_fields, - fields[fields[,2] == i, 1] - ) - ) - out[[i]] <- out[[i]][out_fields] + # Split the table based on instrument + out <- split.data.frame(records, records$redcap_repeat_instrument) + if (forms == "repeating" && primary_table_name %in% subtables) { + warning("The label given to the primary table is already used by a repeating instrument. The primary table label will be left blank.") + primary_table_name <- "" + } else if (primary_table_name > "") { + names(out)[[which(names(out) == "")]] <- primary_table_name } + # Delete the variables that are not relevant + for (i in names(out)) { + + if (i == primary_table_name) { + + out_fields <- which( + vars_in_data %in% c( + universal_fields, + fields[!fields[,2] %in% subtables, 1] + ) + ) + out[[which(names(out) == primary_table_name)]] <- out[[which(names(out) == primary_table_name)]][out_fields] + + } else { + + out_fields <- which( + vars_in_data %in% c( + universal_fields, + repeat_instrument_fields, + fields[fields[,2] == i, 1] + ) + ) + out[[i]] <- out[[i]][out_fields] + + } + + } } out diff --git a/R/man/REDCap_split.Rd b/R/man/REDCap_split.Rd index 9fdf018..c5a99b0 100644 --- a/R/man/REDCap_split.Rd +++ b/R/man/REDCap_split.Rd @@ -4,7 +4,8 @@ \alias{REDCap_split} \title{Split REDCap repeating instruments table into multiple tables} \usage{ -REDCap_split(records, metadata, primary_table_label = "") +REDCap_split(records, metadata, primary_table_name = "", + forms = c("repeating", "all")) } \arguments{ \item{records}{Exported project records. May be a \code{data.frame}, @@ -15,12 +16,22 @@ call.} \code{data.frame}, \code{response}, or \code{character} vector containing JSON from an API call.} -\item{primary_table_label}{Name of the label given to the list element for -the primary output table (as described in *README.md*).} +\item{primary_table_name}{Name given to the list element for the primary +output table (as described in \emph{README.md}). Ignored if +\code{forms = 'all'}.} + +\item{forms}{Indicate whether to create separate tables for repeating +instruments only or for all forms.} } \value{ -A list of \code{"data.frame"}s: one base table and zero or more - tables for each repeating instrument. +A list of \code{"data.frame"}s. The number of tables will differ + depending on the \code{forms} option selected. + \itemize{ + \item \code{'repeating'}: one base table and one or more + tables for each repeating instrument. + \item \code{'all'}: a data.frame for each instrument, regardless of + whether it is a repeating instrument or not. + } } \description{ This will take output from a REDCap export and split it into a base table diff --git a/R/tests/testthat/test-primary-table-name.R b/R/tests/testthat/test-primary-table-name.R new file mode 100644 index 0000000..0c3a31b --- /dev/null +++ b/R/tests/testthat/test-primary-table-name.R @@ -0,0 +1,38 @@ +context("Primary table name processing") + + +# Global variables ------------------------------------------------------- +metadata <- jsonlite::fromJSON( + get_data_location( + "ExampleProject_metadata.json" + ) +) + +records <- jsonlite::fromJSON( + get_data_location( + "ExampleProject_records.json" + ) +) + +ref_hash <- "2c8b6531597182af1248f92124161e0c" + +# Tests ------------------------------------------------------------------- +test_that("Will not use a repeating instrument name for primary table", { + + redcap_output_json1 <- expect_warning( + REDCap_split(records, metadata, "sale"), + "primary table" + ) + + expect_known_hash(redcap_output_json1, ref_hash) + +}) + +test_that("Names are set correctly and output is identical", { + redcap_output_json2 <- REDCap_split(records, metadata, "main") + + + expect_identical(names(redcap_output_json2), c("main", "sale")) + expect_known_hash(setNames(redcap_output_json2, c("", "sale")), ref_hash) + +}) From d15c2d35adc6ccd22c2b371c8fadfae83c77bb4e Mon Sep 17 00:00:00 2001 From: "Paul W. Egeler, M.S., GStat" Date: Mon, 8 Jul 2019 18:01:48 -0400 Subject: [PATCH 4/4] Increment to v 0.2.0 and closes #10 Form timestamp fields also captured now. --- R/DESCRIPTION | 2 +- R/NEWS.md | 5 +++ R/R/REDCap_split.r | 23 +++++++++- R/R/utils.r | 30 +++++++++++++ R/tests/testthat/test-forms-arg.R | 63 ++++++++++++++++++++++++++++ R/tests/testthat/test-longitudinal.R | 2 +- 6 files changed, 121 insertions(+), 4 deletions(-) create mode 100644 R/tests/testthat/test-forms-arg.R diff --git a/R/DESCRIPTION b/R/DESCRIPTION index 0a493f5..3163f9a 100644 --- a/R/DESCRIPTION +++ b/R/DESCRIPTION @@ -1,6 +1,6 @@ Package: REDCapRITS Title: REDCap Repeating Instrument Table Splitter -Version: 0.1.0 +Version: 0.2.0 Authors@R: c( person("Paul", "Egeler", email = "paul.egeler@spectrumhealth.org", role = c("aut", "cre")), person("Spectrum Health, Grand Rapids, MI", role = "cph")) diff --git a/R/NEWS.md b/R/NEWS.md index 4f5c340..e79fe06 100644 --- a/R/NEWS.md +++ b/R/NEWS.md @@ -1,3 +1,8 @@ +# REDCapRITS 0.2.0 (Release date: 2019-??-??) + + * [feature] User can now separate each form into its own data.frame, regardless if it is a repeating instrument or not. (#10) + * [bug] Handles auto-generated form timestamp fields. + # REDCapRITS 0.1.0 (Release date: 2019-07-01) * [feature] User can now specify the name of the 'primary' table, which previously was left blank. (#9) diff --git a/R/R/REDCap_split.r b/R/R/REDCap_split.r index d12db72..d28a26a 100644 --- a/R/R/REDCap_split.r +++ b/R/R/REDCap_split.r @@ -134,12 +134,13 @@ REDCap_split <- function(records, # Split the table based on instrument out <- split.data.frame(records, records$redcap_repeat_instrument) + primary_table_index <- which(names(out) == "") if (forms == "repeating" && primary_table_name %in% subtables) { warning("The label given to the primary table is already used by a repeating instrument. The primary table label will be left blank.") primary_table_name <- "" } else if (primary_table_name > "") { - names(out)[[which(names(out) == "")]] <- primary_table_name + names(out)[[primary_table_index]] <- primary_table_name } # Delete the variables that are not relevant @@ -153,7 +154,7 @@ REDCap_split <- function(records, fields[!fields[,2] %in% subtables, 1] ) ) - out[[which(names(out) == primary_table_name)]] <- out[[which(names(out) == primary_table_name)]][out_fields] + out[[primary_table_index]] <- out[[primary_table_index]][out_fields] } else { @@ -169,6 +170,24 @@ REDCap_split <- function(records, } } + + if (forms == "all") { + + out <- c( + split_non_repeating_forms( + out[[primary_table_index]], + universal_fields, + fields[!fields[,2] %in% subtables,] + ), + out[-primary_table_index] + ) + + } + + } else { + + out <- split_non_repeating_forms(records, universal_fields, fields) + } out diff --git a/R/R/utils.r b/R/R/utils.r index 9115671..87d1509 100644 --- a/R/R/utils.r +++ b/R/R/utils.r @@ -15,6 +15,20 @@ match_fields_to_form <- function(metadata, vars_in_data) { fields <- rbind(fields, form_complete_fields) + # Process survey timestamps + timestamps <- intersect(vars_in_data, paste0(form_names, "_timestamp")) + if (length(timestamps)) { + + timestamp_fields <- data.frame( + field_name = timestamps, + form_name = sub("_timestamp$", "", timestamps), + stringsAsFactors = FALSE + ) + + fields <- rbind(fields, timestamp_fields) + + } + # Process checkbox fields if (any(metadata$field_type == "checkbox")) { @@ -74,3 +88,19 @@ match_fields_to_form <- function(metadata, vars_in_data) { fields } + + +split_non_repeating_forms <- function(table, universal_fields, fields) { + + forms <- unique(fields[[2]]) + + x <- lapply( + forms, + function (x) { + table[names(table) %in% union(universal_fields, fields[fields[,2] == x,1])] + }) + + structure(x, names = forms) + +} + diff --git a/R/tests/testthat/test-forms-arg.R b/R/tests/testthat/test-forms-arg.R new file mode 100644 index 0000000..74c3507 --- /dev/null +++ b/R/tests/testthat/test-forms-arg.R @@ -0,0 +1,63 @@ +context("Using the `forms = 'all'` argument") + +# Global variables -------------------------------------------------------- + +# Cars +metadata <- jsonlite::fromJSON( + get_data_location( + "ExampleProject_metadata.json" + ) +) + +records <- jsonlite::fromJSON( + get_data_location( + "ExampleProject_records.json" + ) +) + +redcap_output_json <- REDCap_split(records, metadata, forms = "all") + +# Longitudinal +file_paths <- sapply( + c( + records = "WARRIORtestForSoftwa_DATA_2018-06-21_1431.csv", + metadata = "WARRIORtestForSoftwareUpgrades_DataDictionary_2018-06-21.csv" + ), get_data_location +) + +redcap <- lapply(file_paths, read.csv, stringsAsFactors = FALSE) +redcap[["metadata"]] <- with(redcap, metadata[metadata[,1] > "",]) +redcap_output_long <- with(redcap, REDCap_split(records, metadata, forms = "all")) +redcap_long_names <- names(redcap[[1]]) + +# Tests ------------------------------------------------------------------- + +test_that("Each form is an element in the list", { + + expect_length(redcap_output_json, 3L) + expect_identical(names(redcap_output_json), c("motor_trend_cars", "grouping", "sale")) + +}) + +test_that("All variables land somewhere", { + + expect_true(setequal(names(records), Reduce("union", sapply(redcap_output_json, names)))) + +}) + + +test_that("Primary table name is ignored", { + expect_identical( + REDCap_split(records, metadata, "HELLO", "all"), + redcap_output_json + ) +}) + +test_that("Supports longitudinal data", { + + # setdiff(redcap_long_names, Reduce("union", sapply(redcap_output_long, names))) + ## [1] "informed_consent_and_addendum_timestamp" + + expect_true(setequal(redcap_long_names, Reduce("union", sapply(redcap_output_long, names)))) + +}) diff --git a/R/tests/testthat/test-longitudinal.R b/R/tests/testthat/test-longitudinal.R index c64cc14..3b955c3 100644 --- a/R/tests/testthat/test-longitudinal.R +++ b/R/tests/testthat/test-longitudinal.R @@ -13,5 +13,5 @@ test_that("CSV export matches reference", { redcap_output <- with(redcap, REDCap_split(records, metadata)) - expect_known_hash(redcap_output, "dff3a52955") + expect_known_hash(redcap_output, "0934bcb292") })