diff --git a/R/dt_stub_df.R b/R/dt_stub_df.R index faac62b19..5f8023e86 100644 --- a/R/dt_stub_df.R +++ b/R/dt_stub_df.R @@ -145,7 +145,12 @@ dt_stub_df_init <- function( # dplyr::recode is superseded, and is slower now. # TODO consider using vctrs::vec_case_match when available r-lib/vctrs#1622 - row_group_ids <- dplyr::recode(row_group_labels, !!!unique_row_group_ids) + # Handle empty dataframe case where unique_row_group_ids is empty + if (length(unique_row_group_ids) == 0) { + row_group_ids <- row_group_labels + } else { + row_group_ids <- dplyr::recode(row_group_labels, !!!unique_row_group_ids) + } } else { row_group_ids <- row_group_labels diff --git a/tests/testthat/test-gt_object.R b/tests/testthat/test-gt_object.R index b333314d0..a6892e62b 100644 --- a/tests/testthat/test-gt_object.R +++ b/tests/testthat/test-gt_object.R @@ -992,3 +992,34 @@ test_that("Formatting functions operate with a 'last-one-wins' approach", { ) ) }) + +test_that("Empty dataframes with process_md = TRUE work correctly (issue #2081)", { + + # Test case 1: Empty dataframe with groupname_col and process_md = TRUE + # Should not throw "No replacements provided" error + expect_no_error( + mtcars[0, ] |> gt(groupname_col = "cyl", process_md = TRUE) + ) + + # Test case 2: Empty grouped dataframe with process_md = TRUE + # Should not throw "No replacements provided" error + expect_no_error( + mtcars[0, ] |> dplyr::group_by(cyl) |> gt(process_md = TRUE) + ) + + # Test case 3: Empty dataframe with rowname_col and process_md = TRUE + # Should continue to work as before + expect_no_error( + mtcars[0, ] |> gt(rowname_col = "cyl", process_md = TRUE) + ) + + # Test case 4: Regression test - non-empty dataframes should still work + expect_no_error( + mtcars[1:5, ] |> gt(groupname_col = "cyl", process_md = TRUE) + ) + + # Test case 5: Verify empty table is created with correct structure + empty_gt <- mtcars[0, ] |> gt(groupname_col = "cyl", process_md = TRUE) + expect_s3_class(empty_gt, "gt_tbl") + expect_equal(nrow(dt_data_get(empty_gt)), 0) +})