test_that("Standard mode returns an htmlwidget with correct data", { sd <- crosstalk::SharedData$new(mtcars) res <- kpiwidget(sd, kpi = "mean", column = "mpg", decimals = 1, prefix = "", suffix = " mpg" ) # Check that the returned object is an htmlwidget expect_s3_class(res, "htmlwidget") # Check that the data sent to JS equals the 'mpg' column from mtcars expect_equal(res$x$data, mtcars[["mpg"]]) # Check settings: kpi should be "mean" and no comparison mode expect_equal(res$x$settings$kpi, "mean") expect_null(res$x$settings$comparison) }) test_that("Comparison mode (share) returns an htmlwidget with proper filters", { sd <- crosstalk::SharedData$new(mtcars) res <- kpiwidget(sd, kpi = "sum", comparison = "share", column = "mpg", group1 = ~ cyl == 4 ) expect_s3_class(res, "htmlwidget") expect_equal(res$x$settings$comparison, "share") expect_equal(res$x$settings$kpi, "sum") # group1_filter should be a logical vector of length equal to number of rows expect_true(is.logical(res$x$group1_filter)) expect_equal(length(res$x$group1_filter), nrow(mtcars)) # In share mode, if group2 is not provided, group2_filter should be all TRUE. expect_equal(res$x$group2_filter, rep(TRUE, nrow(mtcars))) }) test_that("Comparison mode (ratio) returns an htmlwidget with proper filters", { sd <- crosstalk::SharedData$new(mtcars) res <- kpiwidget(sd, kpi = "sum", comparison = "ratio", column = "mpg", group1 = ~ cyl == 4 ) expect_s3_class(res, "htmlwidget") expect_equal(res$x$settings$comparison, "ratio") expect_equal(res$x$settings$kpi, "sum") # Check that group1_filter and group2_filter are logical and have correct length expect_true(is.logical(res$x$group1_filter)) expect_true(is.logical(res$x$group2_filter)) expect_equal(length(res$x$group1_filter), nrow(mtcars)) expect_equal(length(res$x$group2_filter), nrow(mtcars)) # In ratio mode, default group2_filter should be the complement of group1_filter. expect_equal(res$x$group2_filter, !res$x$group1_filter) }) test_that("Non-SharedData input returns NULL with warning", { expect_warning( res <- kpiwidget(mtcars, kpi = "mean", column = "mpg", decimals = 1, prefix = "", suffix = " mpg" ), "kpiWidget can be used only with a Crosstalk SharedData object!" ) expect_null(res) }) test_that("Nonexistent column returns NULL with warning", { sd <- crosstalk::SharedData$new(mtcars) expect_warning( res <- kpiwidget(sd, kpi = "mean", column = "nonexistent", decimals = 1, prefix = "", suffix = " mpg" ), "No 'nonexistent' column in data." ) expect_null(res) }) test_that("Nonexistent column returns NULL with warning in comparison mode", { sd <- crosstalk::SharedData$new(mtcars) expect_warning( res <- kpiwidget(sd, kpi = "mean", column = "nonexistent", decimals = 1, comparison = "share", group1 = ~ cyl == 4 ), "No 'nonexistent' column in data." ) expect_null(res) }) test_that("Missing group1 in comparison mode returns NULL with warning", { sd <- crosstalk::SharedData$new(mtcars) expect_warning( res <- kpiwidget(sd, kpi = "sum", comparison = "share", column = "mpg"), "group1 filter must be provided in comparison mode." ) expect_null(res) }) test_that("Selection filter works correctly", { sd <- crosstalk::SharedData$new(mtcars) res <- kpiwidget(sd, kpi = "mean", column = "mpg", selection = ~ mpg > 20, decimals = 1 ) expect_s3_class(res, "htmlwidget") # Manually filter mtcars by mpg > 20. filtered <- mtcars[mtcars$mpg > 20, , drop = FALSE] expect_equal(res$x$data, filtered[["mpg"]]) }) test_that("Missing column returns NULL with warning", { sd <- crosstalk::SharedData$new(mtcars) expect_warning( res <- kpiwidget(sd, kpi = "sum"), "Column must be provided for standard KPI calculation." ) expect_null(res) }) test_that("Selection must be one-sided formula", { sd <- crosstalk::SharedData$new(mtcars) expect_warning( res <- kpiwidget(sd, kpi = "sum", column = "mpg", selection = mpg ~ mpg > 20), "Unexpected two-sided formula in selection: mpg ~ mpg > 20" ) expect_null(res) }) test_that("group1 wrong format", { sd <- crosstalk::SharedData$new(mtcars) expect_warning( res <- kpiwidget(sd, kpi = "sum", column = "mpg", comparison = "ratio", group1 = "~ cyl > 4" ), "group1 must be a one-sided formula. Remove single/double quotes if you used them." ) expect_null(res) }) test_that("group1 must be one-sided formula", { sd <- crosstalk::SharedData$new(mtcars) expect_warning( res <- kpiwidget(sd, kpi = "sum", column = "mpg", comparison = "ratio", group1 = cyl ~ cyl > 4 ), "Unexpected two-sided formula in group2: cyl ~ cyl > 4" ) expect_null(res) }) test_that("group2 wrong format", { sd <- crosstalk::SharedData$new(mtcars) expect_warning( res <- kpiwidget(sd, kpi = "sum", column = "mpg", comparison = "ratio", group1 = ~ cyl > 4, group2 = "~ cyl == 4" ), "group2 must be a one-sided formula or remain blank. Remove single/double quotes if you used them." ) expect_null(res) }) test_that("group2 must be one-sided formula", { sd <- crosstalk::SharedData$new(mtcars) expect_warning( res <- kpiwidget(sd, kpi = "sum", column = "mpg", comparison = "ratio", group1 = ~ cyl > 4, group2 = cyl ~ cyl == 4 ), "Unexpected two-sided formula in group2: cyl ~ cyl == 4" ) expect_null(res) }) test_that("Comparison mode (ratio), group2 is one-sided formula, returns an htmlwidget with proper filters", { sd <- crosstalk::SharedData$new(mtcars) res <- kpiwidget(sd, kpi = "sum", column = "mpg", comparison = "ratio", group1 = ~ cyl > 4, group2 = ~ cyl == 4 ) expect_s3_class(res, "htmlwidget") expect_equal(res$x$settings$comparison, "ratio") expect_equal(res$x$settings$kpi, "sum") # Check that group1_filter and group2_filter are logical and have correct length expect_true(is.logical(res$x$group1_filter)) expect_true(is.logical(res$x$group2_filter)) expect_equal(length(res$x$group1_filter), nrow(mtcars)) expect_equal(length(res$x$group2_filter), nrow(mtcars)) }) test_that("Comparison mode (ratio) without specified column will return count by default (each row has value == 1). No error is thrown", { sd <- crosstalk::SharedData$new(mtcars) res <- kpiwidget(sd, kpi = "sum", comparison = "ratio", group1 = ~ cyl > 4, group2 = ~ cyl == 4 ) expect_s3_class(res, "htmlwidget") expect_equal(res$x$settings$comparison, "ratio") expect_equal(res$x$settings$kpi, "sum") # Check that group1_filter and group2_filter are logical and have correct length expect_true(is.logical(res$x$group1_filter)) expect_true(is.logical(res$x$group2_filter)) expect_equal(length(res$x$group1_filter), nrow(mtcars)) expect_equal(length(res$x$group2_filter), nrow(mtcars)) })