Files
civilyticsR/tests/testthat/test_theme.R
T
jared 7371069379
R-CMD-check / R CMD check (push) Successful in 2m39s
feat: rebrand logos with wordmark/mark variants and pipe-friendly API
- Replace old civilytics_logo.png/white.png/jpg/pdf with new rebrand
  assets: civilytics-wordmark.png, civilytics-wordmark-reverse.png,
  civilytics-mark.png, civilytics-mark-reverse.png (all transparent bg)
- make_logo_grob() now accepts type = c("wordmark", "mark") alongside
  variant = c("light", "dark") for 4 combinations
- New civilytics_logo() pipe-friendly convenience function:
    ggplot(df, aes(x, y)) + geom_point() + theme_civilytics() |>
      civilytics_logo()
  R's |> has lower precedence than +, so the full ggplot chain pipes
  through without parentheses
- Remove old icon/favicon assets no longer used
- Wrap showtext-dependent examples in \dontrun{} to prevent R CMD check
  failures in headless PostScript environments
2026-05-17 22:42:40 -06:00

203 lines
6.6 KiB
R

library(ggplot2)
# --- civilytics_colors -------------------------------------------------------
test_that("civilytics_colors is a named character vector of hex codes", {
expect_type(civilytics_colors, "character")
expect_named(civilytics_colors)
expect_true(all(grepl("^#[0-9A-Fa-f]{6}$", civilytics_colors)))
})
test_that("civilytics_colors contains expected brand keys", {
expected <- c("paper", "ink", "accent", "navy", "navy_dark",
"accent_dark", "paper_2", "rule")
expect_true(all(expected %in% names(civilytics_colors)))
})
test_that("civilytics_colors values match brand specification", {
expect_equal(unname(civilytics_colors["paper"]), "#FAF7F2")
expect_equal(unname(civilytics_colors["ink"]), "#0E1A2B")
expect_equal(unname(civilytics_colors["accent"]), "#C25311")
expect_equal(unname(civilytics_colors["navy_dark"]), "#1A2E4A")
expect_equal(unname(civilytics_colors["accent_dark"]),"#E07840")
})
# --- civilytics_pal ----------------------------------------------------------
test_that("civilytics_pal returns character vector of hex codes", {
result <- civilytics_pal()
expect_type(result, "character")
expect_true(all(grepl("^#[0-9A-Fa-f]{6}$", result)))
})
test_that("civilytics_pal respects n argument", {
expect_length(civilytics_pal("main", n = 3), 3)
expect_length(civilytics_pal("sequential", n = 5), 5)
})
test_that("civilytics_pal interpolates when n exceeds palette size", {
result <- civilytics_pal("main", n = 10)
expect_length(result, 10)
expect_true(all(grepl("^#[0-9A-Fa-f]{6}$", result)))
})
test_that("civilytics_pal errors on unknown palette name", {
expect_error(civilytics_pal("nope"), "'nope' is not a valid Civilytics palette")
})
test_that("civilytics_pal supports all three named palettes", {
expect_no_error(civilytics_pal("main"))
expect_no_error(civilytics_pal("sequential"))
expect_no_error(civilytics_pal("diverging"))
})
# --- scale_color/fill_civilytics ---------------------------------------------
test_that("scale_color_civilytics returns a Scale object (discrete)", {
sc <- scale_color_civilytics()
expect_s3_class(sc, "Scale")
})
test_that("scale_color_civilytics returns a Scale object (continuous)", {
sc <- scale_color_civilytics("sequential", discrete = FALSE)
expect_s3_class(sc, "Scale")
})
test_that("scale_fill_civilytics returns a Scale object (discrete)", {
sc <- scale_fill_civilytics()
expect_s3_class(sc, "Scale")
})
test_that("scale_fill_civilytics returns a Scale object (continuous)", {
sc <- scale_fill_civilytics("sequential", discrete = FALSE)
expect_s3_class(sc, "Scale")
})
test_that("scale_color_civilytics works in a ggplot", {
p <- ggplot(mpg, aes(displ, hwy, colour = class)) +
geom_point() +
scale_color_civilytics()
expect_no_error(ggplot_build(p))
})
test_that("scale_fill_civilytics works in a ggplot", {
p <- ggplot(mpg, aes(class, fill = class)) +
geom_bar() +
scale_fill_civilytics()
expect_no_error(ggplot_build(p))
})
# --- theme_civilytics --------------------------------------------------------
test_that("theme_civilytics returns a complete ggplot2 theme", {
th <- theme_civilytics()
expect_s3_class(th, "theme")
expect_true(attr(th, "complete"))
})
test_that("theme_civilytics applies to a ggplot without error", {
p <- ggplot(mpg, aes(displ, hwy)) +
geom_point() +
theme_civilytics()
expect_no_error(ggplot_build(p))
})
test_that("theme_civilytics uses brand ink color for text", {
th <- theme_civilytics()
expect_equal(th$text$colour, unname(civilytics_colors["ink"]))
})
test_that("theme_civilytics uses brand paper color for plot background", {
th <- theme_civilytics()
expect_equal(th$plot.background$fill, unname(civilytics_colors["paper"]))
})
test_that("theme_civilytics uses paper_2 for strip background by default", {
th <- theme_civilytics()
expect_equal(th$strip.background$fill, unname(civilytics_colors["paper_2"]))
})
test_that("theme_civilytics strip_color parameter is respected", {
th <- theme_civilytics(strip_color = "#FF0000")
expect_equal(th$strip.background$fill, "#FF0000")
})
test_that("theme_civilytics font_size parameter scales text elements", {
th_big <- theme_civilytics(font_size = 20)
th_sml <- theme_civilytics(font_size = 10)
expect_gt(th_big$text$size, th_sml$text$size)
})
# --- theme_civilytics_dark ---------------------------------------------------
test_that("theme_civilytics_dark returns a complete ggplot2 theme", {
th <- theme_civilytics_dark()
expect_s3_class(th, "theme")
expect_true(attr(th, "complete"))
})
test_that("theme_civilytics_dark applies to a ggplot without error", {
p <- ggplot(mpg, aes(displ, hwy)) +
geom_point() +
theme_civilytics_dark()
expect_no_error(ggplot_build(p))
})
test_that("theme_civilytics_dark uses paper color as ink (light text on dark bg)", {
th <- theme_civilytics_dark()
expect_equal(th$text$colour, unname(civilytics_colors["paper"]))
})
test_that("theme_civilytics_dark uses navy_dark as background", {
th <- theme_civilytics_dark()
expect_equal(th$plot.background$fill, unname(civilytics_colors["navy_dark"]))
})
test_that("theme_civilytics_dark uses navy for strip background", {
th <- theme_civilytics_dark()
expect_equal(th$strip.background$fill, unname(civilytics_colors["navy"]))
})
# --- make_logo_grob ----------------------------------------------------------
test_that("make_logo_grob returns a gg object for all type/variant combos", {
for (type in c("wordmark", "mark")) {
for (variant in c("light", "dark")) {
logo <- make_logo_grob(type = type, variant = variant)
expect_s3_class(logo, "gg")
}
}
})
test_that("make_logo_grob defaults to wordmark light", {
expect_no_error(make_logo_grob())
})
test_that("make_logo_grob errors on invalid type", {
expect_error(make_logo_grob(type = "banner"))
})
test_that("make_logo_grob errors on invalid variant", {
expect_error(make_logo_grob(variant = "purple"))
})
# --- civilytics_logo (pipe-friendly) -----------------------------------------
test_that("civilytics_logo returns a grob", {
p <- ggplot(mpg, aes(displ, hwy)) + geom_point() + theme_civilytics()
result <- suppressWarnings(civilytics_logo(p))
expect_s3_class(result, "grob")
})
test_that("civilytics_logo works with pipe operator", {
p <- ggplot(mpg, aes(displ, hwy)) + geom_point() + theme_civilytics()
result <- suppressWarnings(p |> civilytics_logo())
expect_s3_class(result, "grob")
})
test_that("civilytics_logo accepts type and variant params", {
p <- ggplot(mpg, aes(displ, hwy)) + geom_point() + theme_civilytics_dark()
result <- suppressWarnings(civilytics_logo(p, type = "mark", variant = "dark"))
expect_s3_class(result, "grob")
})