From 259505a1660a696c397b6981903b199513efbd98 Mon Sep 17 00:00:00 2001 From: Gauarv Chaudhary Date: Sun, 21 Dec 2025 21:24:28 +0530 Subject: [PATCH 1/3] test: add failing tests for facet error messages Issue #168 - facet_wrap(. ~ var) gives unhelpful error when var is missing. Added tests that will pass once we improve error messages in animint2dir(). Tests cover facet_wrap and facet_grid with missing variables. These tests are animint2-specific . --- .../test-renderer-facet-error-messages.R | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 tests/testthat/test-renderer-facet-error-messages.R diff --git a/tests/testthat/test-renderer-facet-error-messages.R b/tests/testthat/test-renderer-facet-error-messages.R new file mode 100644 index 000000000..4add970e7 --- /dev/null +++ b/tests/testthat/test-renderer-facet-error-messages.R @@ -0,0 +1,32 @@ +acontext("Facet error messages") +test_that("facet_wrap formula with missing variable gives clear error", { + viz <- list( + scatter = ggplot() + + facet_wrap(. ~ NonExistentColumn) + + geom_point(aes(Sepal.Length, Petal.Length), data = iris) + ) + expect_error( + animint2dir(viz, out.dir = tempfile(), open.browser = FALSE), + "NonExistentColumn" + ) +}) +test_that("facet_grid formula with missing variable gives clear error", { + viz <- list( + scatter = ggplot() + + facet_grid(. ~ MissingVar) + + geom_point(aes(Sepal.Length, Petal.Length), data = iris) + ) + expect_error( + animint2dir(viz, out.dir = tempfile(), open.browser = FALSE), + "MissingVar" + ) +}) +test_that("facet_wrap string notation works", { + viz <- list( + scatter = ggplot() + + facet_wrap("Species") + + geom_point(aes(Sepal.Length, Petal.Length), data = iris) + ) + info <- animint2dir(viz, out.dir = tempfile(), open.browser = FALSE) + expect_true(file.exists(file.path(info$out.dir, "index.html"))) +}) From 24721558434248fdbdd2e8f112d1cdcd648e7254 Mon Sep 17 00:00:00 2001 From: Gauarv Chaudhary Date: Mon, 22 Dec 2025 09:30:27 +0530 Subject: [PATCH 2/3] fix: improve error message for missing facet variables When facet_wrap or facet_grid uses formula notation with a variable that does not exist in the data, the error now shows: - Which variable is missing - What columns are available - Suggests using string notation instead Fixes #168 --- R/z_animint.R | 3 +++ R/z_animintHelpers.R | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/R/z_animint.R b/R/z_animint.R index 3beb7dd7c..0f6c371ef 100644 --- a/R/z_animint.R +++ b/R/z_animint.R @@ -21,6 +21,9 @@ parsePlot <- function(meta, plot, plot.name){ } } + ## Validate facet variables before ggplot_build (Issue #168) + checkFacetVariables(plot) + built <- ggplot_build(plot) plot.info <- list() diff --git a/R/z_animintHelpers.R b/R/z_animintHelpers.R index f36864547..a0844e246 100644 --- a/R/z_animintHelpers.R +++ b/R/z_animintHelpers.R @@ -1066,3 +1066,40 @@ selectSSandCS <- function(aesthetics_list){ ## TODO: how to handle showSelected$ignored in prev animint code?? return(aes.list) } + +checkFacetVariables <- function(plot){ + facet <- plot$facet + if(is.null(facet)) return(invisible()) + facet_class <- class(facet)[1] + facet_vars <- character(0) + if(facet_class == "wrap" && length(facet$facets) > 0){ + facet_vars <- names(facet$facets) + facet_vars <- facet_vars[facet_vars != "."] + }else if(facet_class == "grid"){ + row_vars <- names(facet$rows) + col_vars <- names(facet$cols) + facet_vars <- c(row_vars, col_vars) + facet_vars <- facet_vars[facet_vars != "."] + } + if(length(facet_vars) == 0) return(invisible()) + all_data_vars <- character(0) + for(layer in plot$layers){ + if(length(layer$data) > 0){ + all_data_vars <- c(all_data_vars, names(layer$data)) + } + } + if(length(plot$data) > 0){ + all_data_vars <- c(all_data_vars, names(plot$data)) + } + all_data_vars <- unique(all_data_vars) + missing_vars <- setdiff(facet_vars, all_data_vars) + if(length(missing_vars) > 0){ + stop(sprintf( + "Facet variable%s not found in data: %s\nAvailable columns: %s\nUse string notation like facet_wrap(\"var\") instead of formula notation facet_wrap(. ~ var)", + if(length(missing_vars) > 1) "s" else "", + paste(missing_vars, collapse = ", "), + paste(all_data_vars, collapse = ", ") + )) + } + invisible() +} From d8b4cb1ccc7969f784145d39d26dc1746553d367 Mon Sep 17 00:00:00 2001 From: Gaurav Chaudhary Date: Thu, 12 Mar 2026 16:12:59 +0530 Subject: [PATCH 3/3] fix: clear error message for missing facet variables (#168) --- R/facet-layout.r | 11 ++++++ R/z_animint.R | 3 -- R/z_animintHelpers.R | 37 +------------------ .../test-renderer-facet-error-messages.R | 6 ++- 4 files changed, 16 insertions(+), 41 deletions(-) diff --git a/R/facet-layout.r b/R/facet-layout.r index ef312b4a1..1f38aaf5e 100644 --- a/R/facet-layout.r +++ b/R/facet-layout.r @@ -95,6 +95,17 @@ layout_base <- function(data, vars = NULL, drop = TRUE) { # variables that appear in the data has_all <- unlist(plyr::llply(values, length)) == length(vars) if (!any(has_all)) { + vars_to_check <- vars[vars != "."] + all_data_vars <- unique(unlist(lapply(data, names))) + missing_vars <- setdiff(vars_to_check, all_data_vars) + if(length(missing_vars) > 0){ + stop(sprintf( + "Facet variable%s not found in data: %s\nAvailable columns: %s\nUse string notation like facet_wrap(\"var\") instead of formula notation facet_wrap(. ~ var)", + if(length(missing_vars) > 1) "s" else "", + paste(missing_vars, collapse = ", "), + paste(all_data_vars, collapse = ", ") + )) + } stop("At least one layer must contain all variables used for facetting") } diff --git a/R/z_animint.R b/R/z_animint.R index b2b13ff1d..c50bfee02 100644 --- a/R/z_animint.R +++ b/R/z_animint.R @@ -21,9 +21,6 @@ parsePlot <- function(meta, plot, plot.name){ } } - ## Validate facet variables before ggplot_build (Issue #168) - checkFacetVariables(plot) - built <- ggplot_build(plot) plot.info <- list() diff --git a/R/z_animintHelpers.R b/R/z_animintHelpers.R index e6dd634d4..39d39f291 100644 --- a/R/z_animintHelpers.R +++ b/R/z_animintHelpers.R @@ -1083,39 +1083,4 @@ selectSSandCS <- function(aesthetics_list){ return(aes.list) } -checkFacetVariables <- function(plot){ - facet <- plot$facet - if(is.null(facet)) return(invisible()) - facet_class <- class(facet)[1] - facet_vars <- character(0) - if(facet_class == "wrap" && length(facet$facets) > 0){ - facet_vars <- names(facet$facets) - facet_vars <- facet_vars[facet_vars != "."] - }else if(facet_class == "grid"){ - row_vars <- names(facet$rows) - col_vars <- names(facet$cols) - facet_vars <- c(row_vars, col_vars) - facet_vars <- facet_vars[facet_vars != "."] - } - if(length(facet_vars) == 0) return(invisible()) - all_data_vars <- character(0) - for(layer in plot$layers){ - if(length(layer$data) > 0){ - all_data_vars <- c(all_data_vars, names(layer$data)) - } - } - if(length(plot$data) > 0){ - all_data_vars <- c(all_data_vars, names(plot$data)) - } - all_data_vars <- unique(all_data_vars) - missing_vars <- setdiff(facet_vars, all_data_vars) - if(length(missing_vars) > 0){ - stop(sprintf( - "Facet variable%s not found in data: %s\nAvailable columns: %s\nUse string notation like facet_wrap(\"var\") instead of formula notation facet_wrap(. ~ var)", - if(length(missing_vars) > 1) "s" else "", - paste(missing_vars, collapse = ", "), - paste(all_data_vars, collapse = ", ") - )) - } - invisible() -} + diff --git a/tests/testthat/test-renderer-facet-error-messages.R b/tests/testthat/test-renderer-facet-error-messages.R index 4add970e7..79be2d002 100644 --- a/tests/testthat/test-renderer-facet-error-messages.R +++ b/tests/testthat/test-renderer-facet-error-messages.R @@ -7,7 +7,8 @@ test_that("facet_wrap formula with missing variable gives clear error", { ) expect_error( animint2dir(viz, out.dir = tempfile(), open.browser = FALSE), - "NonExistentColumn" + "Facet variable not found in data: NonExistentColumn\nAvailable columns: Sepal.Length, Sepal.Width, Petal.Length, Petal.Width, Species\nUse string notation like facet_wrap(\"var\") instead of formula notation facet_wrap(. ~ var)", + fixed = TRUE ) }) test_that("facet_grid formula with missing variable gives clear error", { @@ -18,7 +19,8 @@ test_that("facet_grid formula with missing variable gives clear error", { ) expect_error( animint2dir(viz, out.dir = tempfile(), open.browser = FALSE), - "MissingVar" + "Facet variable not found in data: MissingVar\nAvailable columns: Sepal.Length, Sepal.Width, Petal.Length, Petal.Width, Species\nUse string notation like facet_wrap(\"var\") instead of formula notation facet_wrap(. ~ var)", + fixed = TRUE ) }) test_that("facet_wrap string notation works", {