# ============================================================================== # Tests for internal morph_utils.R helpers # ============================================================================== # These test internal functions that don't require magick/image files # ------------------------------------------------------------------------------ # .gif_delay_from_fps tests # ------------------------------------------------------------------------------ test_that(".gif_delay_from_fps calculates correct delay", { # 10 fps = 100/10 = 10 centiseconds per frame expect_equal(couplr:::.gif_delay_from_fps(10), 10L) # 25 fps = 100/25 = 4 centiseconds expect_equal(couplr:::.gif_delay_from_fps(25), 4L) # 1 fps = 100/1 = 100 centiseconds expect_equal(couplr:::.gif_delay_from_fps(1), 100L) }) test_that(".gif_delay_from_fps handles edge cases", { # fps < 1 defaults to 10 expect_equal(couplr:::.gif_delay_from_fps(0), 10L) # non-finite values default to 10 fps expect_equal(couplr:::.gif_delay_from_fps(NA), 10L) expect_equal(couplr:::.gif_delay_from_fps(Inf), 10L) }) # ------------------------------------------------------------------------------ # .to_planar_rgb and .from_planar_rgb tests # ------------------------------------------------------------------------------ test_that(".to_planar_rgb converts H x W x 3 array to planar", { # Create a 2x3x3 RGB array arr <- array(1:18, dim = c(2, 3, 3)) result <- couplr:::.to_planar_rgb(arr) expect_length(result, 18) expect_type(result, "double") }) test_that(".from_planar_rgb converts planar back to array", { H <- 2 W <- 3 planar <- as.numeric(1:(H * W * 3)) result <- couplr:::.from_planar_rgb(planar, H, W) expect_equal(dim(result), c(H, W, 3)) }) test_that(".from_planar_rgb errors on wrong length", { expect_error( couplr:::.from_planar_rgb(1:10, H = 2, W = 3), "wrong length" ) }) test_that("planar round-trip preserves data", { H <- 3 W <- 4 arr <- array(runif(H * W * 3) * 255, dim = c(H, W, 3)) planar <- couplr:::.to_planar_rgb(arr) recovered <- couplr:::.from_planar_rgb(planar, H, W) expect_equal(recovered, arr) }) # ------------------------------------------------------------------------------ # .clamp_rgb tests # ------------------------------------------------------------------------------ test_that(".clamp_rgb clamps values to 0-255", { x <- c(-10, 0, 128, 255, 300) result <- couplr:::.clamp_rgb(x) expect_equal(result, c(0L, 0L, 128L, 255L, 255L)) }) test_that(".clamp_rgb preserves array dimensions", { arr <- array(c(-10, 100, 200, 300), dim = c(2, 2)) result <- couplr:::.clamp_rgb(arr) expect_equal(dim(result), c(2, 2)) expect_equal(result[1, 1], 0L) expect_equal(result[2, 2], 255L) }) # ------------------------------------------------------------------------------ # .has_namespace tests # ------------------------------------------------------------------------------ test_that(".has_namespace returns TRUE for base packages", { expect_true(couplr:::.has_namespace("stats")) expect_true(couplr:::.has_namespace("base")) }) test_that(".has_namespace returns FALSE for nonexistent packages", { expect_false(couplr:::.has_namespace("nonexistent_pkg_xyz123")) }) # ------------------------------------------------------------------------------ # .call_or helper tests # ------------------------------------------------------------------------------ test_that(".call_or calls primary function when available", { # sum should exist result <- couplr:::.call_or("sum", "nonexistent", 1:5) expect_equal(result, 15) }) test_that(".call_or errors when neither function exists", { expect_error( couplr:::.call_or("nonexistent1", "nonexistent2", 1), "Neither" ) }) # ------------------------------------------------------------------------------ # .fill_unassigned_identity tests # ------------------------------------------------------------------------------ test_that(".fill_unassigned_identity fills negatives with index", { assign <- c(2L, -1L, 1L, -1L) result <- couplr:::.fill_unassigned_identity(assign) expect_equal(result, c(2L, 2L, 1L, 4L)) }) test_that(".fill_unassigned_identity keeps positive values", { assign <- c(5L, 4L, 3L, 2L, 1L) result <- couplr:::.fill_unassigned_identity(assign) expect_equal(result, assign) }) # ------------------------------------------------------------------------------ # .assemble_assignment tests # ------------------------------------------------------------------------------ test_that(".assemble_assignment creates assignment vector", { N <- 5 i_idx <- c(1L, 3L, 5L) j_idx <- c(2L, 4L, 1L) result <- couplr:::.assemble_assignment(N, i_idx, j_idx) expect_length(result, N) expect_equal(result[1], 2L) expect_equal(result[3], 4L) expect_equal(result[5], 1L) expect_equal(result[2], -1L) # unfilled }) test_that(".assemble_assignment handles empty input", { N <- 3 result <- couplr:::.assemble_assignment(N, integer(), integer()) expect_equal(result, rep(-1L, 3)) }) # ------------------------------------------------------------------------------ # %||% operator tests # ------------------------------------------------------------------------------ test_that("%||% returns left when not NULL", { expect_equal(5 %||% 10, 5) expect_equal("a" %||% "b", "a") }) test_that("%||% returns right when left is NULL", { expect_equal(NULL %||% 10, 10) expect_equal(NULL %||% "default", "default") }) # ------------------------------------------------------------------------------ # .palette_pairs_identity tests # ------------------------------------------------------------------------------ test_that(".palette_pairs_identity matches identical colors", { # Create mock info structure info <- list( colorsA_rgb = matrix(c(255, 0, 0, 0, 255, 0), nrow = 2, byrow = TRUE), colorsB_rgb = matrix(c(255, 0, 0, 0, 0, 255), nrow = 2, byrow = TRUE), countsA = c(10, 5), countsB = c(8, 3), groupsA = list(1:10, 11:15), groupsB = list(1:8, 9:11) ) result <- couplr:::.palette_pairs_identity(info) expect_s3_class(result, "data.frame") # Should match color (255,0,0) which is index 1 in both expect_true(1 %in% result$ia) }) test_that(".palette_pairs_identity returns empty when no matches", { info <- list( colorsA_rgb = matrix(c(255, 0, 0), nrow = 1), colorsB_rgb = matrix(c(0, 255, 0), nrow = 1), countsA = 10, countsB = 10, groupsA = list(1:10), groupsB = list(1:10) ) result <- couplr:::.palette_pairs_identity(info) expect_equal(nrow(result), 0) }) # ------------------------------------------------------------------------------ # .downscale_both tests (without C++) # ------------------------------------------------------------------------------ test_that(".downscale_both returns unchanged when steps is NULL", { H <- 10 W <- 10 A <- rep(128, H * W * 3) B <- rep(64, H * W * 3) result <- couplr:::.downscale_both(A, B, H, W, steps = NULL) expect_equal(result$Hs, H) expect_equal(result$Ws, W) expect_equal(result$A_s, A) expect_equal(result$B_s, B) }) test_that(".downscale_both returns unchanged when steps is 0", { H <- 10 W <- 10 A <- rep(128, H * W * 3) B <- rep(64, H * W * 3) result <- couplr:::.downscale_both(A, B, H, W, steps = 0) expect_equal(result$Hs, H) expect_equal(result$Ws, W) })