Nothing
# =============================================================================
# Test Coverage for shapes-registry.R (Extended)
# =============================================================================
# Additional comprehensive tests for shape registration and drawing functions
# Targets functions in shapes-registry.R, shapes-basic.R, and shapes-special.R
# =============================================================================
# Test: register_builtin_shapes comprehensive coverage
# =============================================================================
skip_on_cran()
test_that("register_builtin_shapes initializes all expected shapes", {
# Force re-registration to ensure function is called
register_builtin_shapes()
shapes <- list_shapes()
# Check all basic shapes
basic_shapes <- c("circle", "square", "triangle", "diamond", "pentagon", "hexagon")
for (shape in basic_shapes) {
expect_true(shape %in% shapes, info = paste("Missing basic shape:", shape))
}
# Check all special shapes
special_shapes <- c("ellipse", "heart", "star", "pie", "donut",
"polygon_donut", "donut_pie", "double_donut_pie", "cross", "plus")
for (shape in special_shapes) {
expect_true(shape %in% shapes, info = paste("Missing special shape:", shape))
}
# Check AI-themed shapes
ai_shapes <- c("neural", "chip", "robot", "brain", "network",
"database", "cloud", "gear")
for (shape in ai_shapes) {
expect_true(shape %in% shapes, info = paste("Missing AI shape:", shape))
}
# Check rectangle and none
expect_true("rectangle" %in% shapes)
expect_true("none" %in% shapes)
})
# =============================================================================
# Test: draw_circle edge cases
# =============================================================================
test_that("draw_circle handles zero alpha", {
skip_if_not_installed("grid")
grob <- draw_circle(0.5, 0.5, 0.1, "blue", "black", 1, alpha = 0)
expect_s3_class(grob, "grob")
expect_s3_class(grob, "circle")
})
test_that("draw_circle handles negative coordinates", {
skip_if_not_installed("grid")
grob <- draw_circle(-0.5, -0.5, 0.1, "blue", "black", 1)
expect_s3_class(grob, "grob")
})
test_that("draw_circle handles very large size", {
skip_if_not_installed("grid")
grob <- draw_circle(0.5, 0.5, 2.0, "red", "black", 1)
expect_s3_class(grob, "grob")
})
test_that("draw_circle handles transparent colors", {
skip_if_not_installed("grid")
grob <- draw_circle(0.5, 0.5, 0.1, "transparent", "transparent", 1)
expect_s3_class(grob, "grob")
})
# =============================================================================
# Test: draw_square edge cases
# =============================================================================
test_that("draw_square handles zero size", {
skip_if_not_installed("grid")
grob <- draw_square(0.5, 0.5, 0, "red", "black", 1)
expect_s3_class(grob, "grob")
})
test_that("draw_square handles large border width", {
skip_if_not_installed("grid")
grob <- draw_square(0.5, 0.5, 0.1, "blue", "black", 10)
expect_s3_class(grob, "grob")
})
# =============================================================================
# Test: draw_triangle edge cases
# =============================================================================
test_that("draw_triangle creates proper polygon with correct vertex count", {
skip_if_not_installed("grid")
grob <- draw_triangle(0.5, 0.5, 0.15, "green", "black", 1.5)
expect_s3_class(grob, "polygon")
# Should have 3 vertices
expect_equal(length(grob$x), 3)
})
# =============================================================================
# Test: draw_diamond edge cases
# =============================================================================
test_that("draw_diamond creates proper polygon with correct vertex count", {
skip_if_not_installed("grid")
grob <- draw_diamond(0.5, 0.5, 0.1, "purple", "gray", 2)
expect_s3_class(grob, "polygon")
# Should have 4 vertices
expect_equal(length(grob$x), 4)
})
# =============================================================================
# Test: draw_pentagon edge cases
# =============================================================================
test_that("draw_pentagon creates proper polygon with 5 vertices", {
skip_if_not_installed("grid")
grob <- draw_pentagon(0.5, 0.5, 0.1, "orange", "black", 1)
expect_s3_class(grob, "polygon")
# Should have 5 vertices
expect_equal(length(grob$x), 5)
})
# =============================================================================
# Test: draw_hexagon edge cases
# =============================================================================
test_that("draw_hexagon creates proper polygon with 6 vertices", {
skip_if_not_installed("grid")
grob <- draw_hexagon(0.5, 0.5, 0.1, "cyan", "black", 1)
expect_s3_class(grob, "polygon")
# Should have 6 vertices
expect_equal(length(grob$x), 6)
})
# =============================================================================
# Test: draw_ellipse additional cases
# =============================================================================
test_that("draw_ellipse handles extreme aspect ratios", {
skip_if_not_installed("grid")
# Very flat ellipse
grob <- draw_ellipse(0.5, 0.5, 0.1, "blue", "black", 1, aspect = 0.1)
expect_s3_class(grob, "polygon")
# Tall ellipse
grob <- draw_ellipse(0.5, 0.5, 0.1, "blue", "black", 1, aspect = 1.0)
expect_s3_class(grob, "polygon")
})
test_that("draw_ellipse generates sufficient points for smooth curve", {
skip_if_not_installed("grid")
grob <- draw_ellipse(0.5, 0.5, 0.1, "blue", "black", 1)
# Should have 50 points for smooth rendering
expect_equal(length(grob$x), 50)
})
# =============================================================================
# Test: draw_heart additional cases
# =============================================================================
test_that("draw_heart generates proper polygon", {
skip_if_not_installed("grid")
grob <- draw_heart(0.5, 0.5, 0.15, "red", "darkred", 1.5)
expect_s3_class(grob, "polygon")
# Should have 100 points for smooth curve
expect_equal(length(grob$x), 100)
})
# =============================================================================
# Test: draw_star additional cases
# =============================================================================
test_that("draw_star handles different point configurations", {
skip_if_not_installed("grid")
# 3-point star
grob <- draw_star(0.5, 0.5, 0.1, "gold", "black", 1, n_points = 3)
expect_s3_class(grob, "polygon")
expect_equal(length(grob$x), 6) # 3 outer + 3 inner
# 7-point star
grob <- draw_star(0.5, 0.5, 0.1, "gold", "black", 1, n_points = 7)
expect_s3_class(grob, "polygon")
expect_equal(length(grob$x), 14) # 7 outer + 7 inner
# 10-point star
grob <- draw_star(0.5, 0.5, 0.1, "gold", "black", 1, n_points = 10)
expect_s3_class(grob, "polygon")
expect_equal(length(grob$x), 20)
})
test_that("draw_star handles extreme inner_ratio values", {
skip_if_not_installed("grid")
# Very small inner ratio (thin star)
grob <- draw_star(0.5, 0.5, 0.1, "gold", "black", 1, inner_ratio = 0.1)
expect_s3_class(grob, "polygon")
# Large inner ratio (fat star)
grob <- draw_star(0.5, 0.5, 0.1, "gold", "black", 1, inner_ratio = 0.9)
expect_s3_class(grob, "polygon")
})
# =============================================================================
# Test: draw_pie additional cases
# =============================================================================
test_that("draw_pie handles empty values vector", {
skip_if_not_installed("grid")
grob <- draw_pie(0.5, 0.5, 0.1, "blue", "black", 1, values = c())
expect_s3_class(grob, "grob")
})
test_that("draw_pie handles very small proportions", {
skip_if_not_installed("grid")
grob <- draw_pie(0.5, 0.5, 0.1, "blue", "black", 1,
values = c(1, 1000)) # 0.1% vs 99.9%
expect_s3_class(grob, "gList")
})
test_that("draw_pie handles zero border segment width", {
skip_if_not_installed("grid")
grob <- draw_pie(0.5, 0.5, 0.1, "blue", "black", 1,
values = c(50, 50),
pie_border_width = 0)
expect_s3_class(grob, "gList")
})
test_that("draw_pie handles many segments", {
skip_if_not_installed("grid")
grob <- draw_pie(0.5, 0.5, 0.1, "blue", "black", 1,
values = rep(10, 10)) # 10 equal segments
expect_s3_class(grob, "gList")
})
# =============================================================================
# Test: draw_donut additional cases
# =============================================================================
test_that("draw_donut handles extreme inner_ratio values", {
skip_if_not_installed("grid")
# Thin ring
grob <- draw_donut(0.5, 0.5, 0.1, "blue", "black", 1,
values = 0.5, inner_ratio = 0.9)
expect_s3_class(grob, "gList")
# Thick ring
grob <- draw_donut(0.5, 0.5, 0.1, "blue", "black", 1,
values = 0.5, inner_ratio = 0.1)
expect_s3_class(grob, "gList")
})
test_that("draw_donut handles value slightly over 1", {
skip_if_not_installed("grid")
# Should clamp to 1
grob <- draw_donut(0.5, 0.5, 0.1, "blue", "black", 1, values = 1.5)
expect_s3_class(grob, "gList")
})
test_that("draw_donut handles negative value", {
skip_if_not_installed("grid")
# Should clamp to 0
grob <- draw_donut(0.5, 0.5, 0.1, "blue", "black", 1, values = -0.5)
expect_s3_class(grob, "gList")
})
test_that("draw_donut handles all fontface options", {
skip_if_not_installed("grid")
fontfaces <- c("plain", "bold", "italic", "bold.italic")
for (ff in fontfaces) {
grob <- draw_donut(0.5, 0.5, 0.1, "blue", "black", 1,
values = 0.5, show_value = TRUE, value_fontface = ff)
expect_s3_class(grob, "gList")
}
})
test_that("draw_donut handles custom value_fontfamily", {
skip_if_not_installed("grid")
grob <- draw_donut(0.5, 0.5, 0.1, "blue", "black", 1,
values = 0.5, show_value = TRUE,
value_fontfamily = "serif")
expect_s3_class(grob, "gList")
})
test_that("draw_donut handles multiple values with custom colors", {
skip_if_not_installed("grid")
grob <- draw_donut(0.5, 0.5, 0.1, "blue", "black", 1,
values = c(25, 35, 40),
colors = c("red", "green", "blue"))
expect_s3_class(grob, "gList")
})
# =============================================================================
# Test: draw_polygon_donut additional cases
# =============================================================================
test_that("draw_polygon_donut handles NULL values", {
skip_if_not_installed("grid")
grob <- draw_polygon_donut(0.5, 0.5, 0.1, "blue", "black", 1, values = NULL)
expect_s3_class(grob, "gList")
})
test_that("draw_polygon_donut handles empty values", {
skip_if_not_installed("grid")
grob <- draw_polygon_donut(0.5, 0.5, 0.1, "blue", "black", 1, values = c())
expect_s3_class(grob, "gList")
})
test_that("draw_polygon_donut handles multi-segment with custom colors", {
skip_if_not_installed("grid")
grob <- draw_polygon_donut(0.5, 0.5, 0.1, "blue", "black", 1,
values = c(30, 40, 30),
colors = c("red", "green", "blue"))
expect_s3_class(grob, "gList")
})
test_that("draw_polygon_donut handles custom value formatting", {
skip_if_not_installed("grid")
custom_format <- function(x) paste0(round(x * 100), "%")
grob <- draw_polygon_donut(0.5, 0.5, 0.1, "blue", "black", 1,
values = 0.75,
show_value = TRUE,
value_format = custom_format)
expect_s3_class(grob, "gList")
})
test_that("draw_polygon_donut handles all fontface types", {
skip_if_not_installed("grid")
fontfaces <- c("plain", "bold", "italic", "bold.italic")
for (ff in fontfaces) {
grob <- draw_polygon_donut(0.5, 0.5, 0.1, "blue", "black", 1,
values = 0.5, show_value = TRUE,
value_fontface = ff)
expect_s3_class(grob, "gList")
}
})
test_that("draw_polygon_donut handles edge case where prop is 0", {
skip_if_not_installed("grid")
grob <- draw_polygon_donut(0.5, 0.5, 0.1, "blue", "black", 1, values = 0)
expect_s3_class(grob, "gList")
})
# =============================================================================
# Test: draw_donut_pie additional cases
# =============================================================================
test_that("draw_donut_pie handles NULL donut_value", {
skip_if_not_installed("grid")
grob <- draw_donut_pie(0.5, 0.5, 0.1, "blue", "black", 1,
donut_value = NULL)
expect_s3_class(grob, "gList")
})
test_that("draw_donut_pie handles NULL pie_values", {
skip_if_not_installed("grid")
grob <- draw_donut_pie(0.5, 0.5, 0.1, "blue", "black", 1,
donut_value = 0.75,
pie_values = NULL)
expect_s3_class(grob, "gList")
})
test_that("draw_donut_pie handles empty pie_values", {
skip_if_not_installed("grid")
grob <- draw_donut_pie(0.5, 0.5, 0.1, "blue", "black", 1,
donut_value = 0.5,
pie_values = c())
expect_s3_class(grob, "gList")
})
test_that("draw_donut_pie handles different border widths", {
skip_if_not_installed("grid")
grob <- draw_donut_pie(0.5, 0.5, 0.1, "blue", "black", 2,
donut_value = 0.6,
pie_values = c(40, 60),
pie_border_width = 0.5,
donut_border_width = 3)
expect_s3_class(grob, "gList")
})
test_that("draw_donut_pie handles pie_colors recycling", {
skip_if_not_installed("grid")
grob <- draw_donut_pie(0.5, 0.5, 0.1, "blue", "black", 1,
pie_values = c(30, 30, 40),
pie_colors = c("red", "green")) # Only 2 colors for 3 values
expect_s3_class(grob, "gList")
})
# =============================================================================
# Test: draw_double_donut_pie additional cases
# =============================================================================
test_that("draw_double_donut_pie handles all NULL values", {
skip_if_not_installed("grid")
grob <- draw_double_donut_pie(0.5, 0.5, 0.1, "blue", "black", 1,
donut_values = NULL,
donut2_values = NULL,
pie_values = NULL)
expect_s3_class(grob, "gList")
})
test_that("draw_double_donut_pie handles multi-segment donuts", {
skip_if_not_installed("grid")
grob <- draw_double_donut_pie(0.5, 0.5, 0.1, "blue", "black", 1,
donut_values = c(30, 40, 30),
donut_colors = c("red", "green", "blue"),
donut2_values = c(50, 50),
donut2_colors = c("orange", "purple"),
pie_values = c(25, 25, 50),
pie_colors = c("cyan", "magenta", "yellow"))
expect_s3_class(grob, "gList")
})
test_that("draw_double_donut_pie handles progress-style donuts", {
skip_if_not_installed("grid")
grob <- draw_double_donut_pie(0.5, 0.5, 0.1, "blue", "black", 1,
donut_values = 0.8,
donut_colors = "steelblue",
donut2_values = 0.6,
donut2_colors = "coral")
expect_s3_class(grob, "gList")
})
test_that("draw_double_donut_pie handles custom border widths", {
skip_if_not_installed("grid")
grob <- draw_double_donut_pie(0.5, 0.5, 0.1, "blue", "black", 2,
donut_values = 0.5,
donut2_values = 0.7,
pie_values = c(50, 50),
pie_border_width = 0.5,
donut_border_width = 3)
expect_s3_class(grob, "gList")
})
# =============================================================================
# Test: AI-themed shapes additional cases
# =============================================================================
test_that("draw_neural handles different connection counts", {
skip_if_not_installed("grid")
# Few connections
grob <- draw_neural(0.5, 0.5, 0.1, "lightblue", "navy", 1, n_connections = 3)
expect_s3_class(grob, "gList")
# Many connections
grob <- draw_neural(0.5, 0.5, 0.1, "lightblue", "navy", 1, n_connections = 12)
expect_s3_class(grob, "gList")
})
test_that("draw_chip handles different pins_per_side values", {
skip_if_not_installed("grid")
# Few pins
grob <- draw_chip(0.5, 0.5, 0.1, "gray", "black", 1, pins_per_side = 2)
expect_s3_class(grob, "gList")
# Many pins
grob <- draw_chip(0.5, 0.5, 0.1, "gray", "black", 1, pins_per_side = 8)
expect_s3_class(grob, "gList")
})
test_that("draw_gear handles different tooth counts", {
skip_if_not_installed("grid")
# Few teeth
grob <- draw_gear(0.5, 0.5, 0.1, "gray", "black", 1, n_teeth = 4)
expect_s3_class(grob, "gList")
# Many teeth
grob <- draw_gear(0.5, 0.5, 0.1, "gray", "black", 1, n_teeth = 16)
expect_s3_class(grob, "gList")
})
# =============================================================================
# Test: draw_cross additional cases
# =============================================================================
test_that("draw_cross handles different thickness values", {
skip_if_not_installed("grid")
# Thin cross
grob <- draw_cross(0.5, 0.5, 0.1, "gray", "black", 1, thickness = 0.1)
expect_s3_class(grob, "gList")
# Thick cross
grob <- draw_cross(0.5, 0.5, 0.1, "gray", "black", 1, thickness = 0.8)
expect_s3_class(grob, "gList")
})
# =============================================================================
# Test: rectangle shape edge cases
# =============================================================================
test_that("rectangle shape handles different aspect ratios", {
skip_if_not_installed("grid")
rect_fn <- get_shape("rectangle")
# Wide rectangle
grob <- rect_fn(0.5, 0.5, 0.1, "blue", "black", 1, aspect = 3.0)
expect_s3_class(grob, "rect")
# Square-ish (aspect = 1)
grob <- rect_fn(0.5, 0.5, 0.1, "blue", "black", 1, aspect = 1.0)
expect_s3_class(grob, "rect")
})
# =============================================================================
# Test: none shape edge cases
# =============================================================================
test_that("none shape returns nullGrob regardless of parameters", {
skip_if_not_installed("grid")
none_fn <- get_shape("none")
# Various parameters should all return null grob
grob1 <- none_fn(0.5, 0.5, 0.1, "red", "black", 1)
grob2 <- none_fn(0.1, 0.9, 0.5, "blue", "white", 10)
grob3 <- none_fn(0, 0, 0, NA, NA, 0)
expect_s3_class(grob1, "null")
expect_s3_class(grob2, "null")
expect_s3_class(grob3, "null")
})
# =============================================================================
# Test: Shape function signature compatibility
# =============================================================================
test_that("all registered shapes accept standard parameters", {
skip_if_not_installed("grid")
shapes_to_test <- c("circle", "square", "triangle", "diamond",
"pentagon", "hexagon", "ellipse", "heart", "star",
"cross", "rectangle", "none")
for (shape_name in shapes_to_test) {
fn <- get_shape(shape_name)
expect_true(is.function(fn), info = paste("Shape not a function:", shape_name))
# All shapes should accept these standard parameters
result <- tryCatch(
fn(0.5, 0.5, 0.1, "blue", "black", 1, alpha = 0.8),
error = function(e) NULL
)
expect_true(!is.null(result) || inherits(result, "grob") || inherits(result, "gList"),
info = paste("Shape failed standard call:", shape_name))
}
})
test_that("all complex shapes accept extra parameters via ...", {
skip_if_not_installed("grid")
complex_shapes <- c("pie", "donut", "neural", "chip", "gear")
for (shape_name in complex_shapes) {
fn <- get_shape(shape_name)
expect_true(is.function(fn), info = paste("Shape not a function:", shape_name))
# Should handle extra parameters without error
result <- tryCatch(
fn(0.5, 0.5, 0.1, "blue", "black", 1, alpha = 0.8, extra_param = "ignored"),
error = function(e) NULL
)
expect_false(is.null(result), info = paste("Shape failed with extra params:", shape_name))
}
})
# =============================================================================
# Test: Custom shape registration and retrieval
# =============================================================================
test_that("register_shape allows registering lambdas", {
skip_if_not_installed("grid")
# Register anonymous function
register_shape("test_lambda_shape", function(x, y, size, fill, border_color, border_width, ...) {
grid::circleGrob(
x = grid::unit(x, "npc"),
y = grid::unit(y, "npc"),
r = grid::unit(size * 0.5, "npc"),
gp = grid::gpar(fill = fill, col = border_color, lwd = border_width)
)
})
fn <- get_shape("test_lambda_shape")
expect_true(is.function(fn))
grob <- fn(0.5, 0.5, 0.1, "green", "darkgreen", 2)
expect_s3_class(grob, "grob")
})
test_that("register_shape allows shape with complex return value", {
skip_if_not_installed("grid")
register_shape("test_complex_shape", function(x, y, size, fill, border_color, border_width, ...) {
grobs <- list()
grobs[[1]] <- grid::circleGrob(
x = grid::unit(x, "npc"),
y = grid::unit(y, "npc"),
r = grid::unit(size, "npc"),
gp = grid::gpar(fill = fill, col = border_color, lwd = border_width)
)
grobs[[2]] <- grid::circleGrob(
x = grid::unit(x, "npc"),
y = grid::unit(y, "npc"),
r = grid::unit(size * 0.5, "npc"),
gp = grid::gpar(fill = "white", col = border_color, lwd = border_width)
)
do.call(grid::gList, grobs)
})
fn <- get_shape("test_complex_shape")
grob <- fn(0.5, 0.5, 0.1, "blue", "black", 1)
expect_s3_class(grob, "gList")
})
# =============================================================================
# Test: Shape registry state
# =============================================================================
test_that("list_shapes returns current state of registry", {
skip_if_not_installed("grid")
initial_shapes <- list_shapes()
# Register a new shape
register_shape("test_temp_shape", function(x, y, size, fill, border_color, border_width, ...) {
grid::nullGrob()
})
new_shapes <- list_shapes()
expect_true("test_temp_shape" %in% new_shapes)
expect_equal(length(new_shapes), length(initial_shapes) + 1)
})
test_that("get_shape returns NULL for non-existent shapes", {
fn <- get_shape("definitely_not_a_registered_shape_12345")
expect_null(fn)
})
# =============================================================================
# Test: Grob property verification
# =============================================================================
test_that("basic shape grobs have correct graphical parameters", {
skip_if_not_installed("grid")
grob <- draw_circle(0.5, 0.5, 0.1, "blue", "red", 2)
# Check that gp exists and has expected values
expect_true(!is.null(grob$gp))
expect_equal(grob$gp$lwd, 2)
})
test_that("shapes handle hex color codes", {
skip_if_not_installed("grid")
grob <- draw_square(0.5, 0.5, 0.1, "#FF5500", "#003355", 1)
expect_s3_class(grob, "grob")
grob <- draw_triangle(0.5, 0.5, 0.1, "#AABBCC", "#112233", 1.5)
expect_s3_class(grob, "polygon")
})
test_that("shapes handle RGB color specifications", {
skip_if_not_installed("grid")
rgb_color <- grDevices::rgb(0.5, 0.2, 0.8)
grob <- draw_diamond(0.5, 0.5, 0.1, rgb_color, "black", 1)
expect_s3_class(grob, "polygon")
})
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.