4.0 KiB · text History aca7335
//! Switching palette has to move the icon's colours with it.

use icon_studio::app::Studio;
use icon_studio::palette;

fn index_of(name: &str) -> usize {
    palette::THEMES
        .iter()
        .position(|t| t.name == name)
        .unwrap_or_else(|| panic!("no theme named {name}"))
}

#[test]
fn changing_theme_changes_the_colours() {
    let mut s = Studio::new();
    let before = (s.spec().fg_color.rgb, s.spec().bg_a.rgb, s.spec().bg_b.rgb);
    assert_eq!(s.theme_name(), "Casabeza");

    s.set_theme(index_of("forest"));
    assert_eq!(s.theme_name(), "forest");

    let after = (s.spec().fg_color.rgb, s.spec().bg_a.rgb, s.spec().bg_b.rgb);
    assert_ne!(before, after, "colours should follow the palette");
}

#[test]
fn roles_are_preserved_across_a_theme_change() {
    let mut s = Studio::new();
    let roles = (
        s.spec().fg_color.role,
        s.spec().bg_a.role,
        s.spec().bg_b.role,
    );

    s.set_theme(index_of("sky"));

    assert_eq!(
        (
            s.spec().fg_color.role,
            s.spec().bg_a.role,
            s.spec().bg_b.role
        ),
        roles,
        "a role defined by both palettes should carry across"
    );
}

#[test]
fn colours_match_the_theme_that_is_selected() {
    let mut s = Studio::new();
    for theme in palette::THEMES.iter() {
        s.set_theme(index_of(theme.name));
        for c in [s.spec().fg_color, s.spec().bg_a, s.spec().bg_b] {
            if let Some(defined) = theme.get(c.role) {
                assert_eq!(
                    c.rgb, defined.rgb,
                    "{}: {} should be the palette's value",
                    theme.name, c.role
                );
            }
        }
    }
}

#[test]
fn a_role_the_new_palette_lacks_still_moves() {
    // `info` exists in the dms themes but not in Casabeza. Switching to
    // Casabeza must not leave a colour from the palette we just left.
    let mut s = Studio::new();
    s.set_theme(index_of("sky"));
    let sky = palette::THEMES[index_of("sky")];
    let Some(info) = sky.get("info") else {
        return; // nothing to test if the palette drops the role
    };

    s.set_theme_color_for_test(info);
    assert_eq!(s.spec().bg_a.rgb, info.rgb);

    s.set_theme(index_of("Casabeza"));
    let casabeza = palette::THEMES[index_of("Casabeza")];
    assert!(casabeza.get("info").is_none(), "precondition");
    assert_ne!(
        s.spec().bg_a.rgb,
        info.rgb,
        "should fall back into the new palette, not keep the old colour"
    );
    assert_eq!(
        s.spec().bg_a.rgb,
        casabeza.get("primary").unwrap().rgb,
        "should fall back to the slot's default role"
    );
}

#[test]
fn switching_theme_is_idempotent() {
    let mut s = Studio::new();
    s.set_theme(index_of("clays"));
    let once = (s.spec().fg_color.rgb, s.spec().bg_a.rgb, s.spec().bg_b.rgb);
    s.set_theme(index_of("clays"));
    assert_eq!(
        once,
        (s.spec().fg_color.rgb, s.spec().bg_a.rgb, s.spec().bg_b.rgb)
    );
}

#[test]
fn blueprint_is_available_and_distinct() {
    let bp = palette::THEMES[index_of("blueprint")];
    assert!(!bp.light, "blueprint is a dark scheme");
    // The blues that make it a blueprint, from the waxx stylesheet.
    assert_eq!(bp.get("base-100").unwrap().rgb, [0x00, 0x26, 0x61]);
    assert_eq!(bp.get("primary").unwrap().rgb, [0x0E, 0x9D, 0xFF]);

    let mut s = Studio::new();
    s.set_theme(index_of("blueprint"));
    assert_eq!(
        s.spec().bg_a.rgb,
        [0x0E, 0x9D, 0xFF],
        "primary should apply"
    );
}

#[test]
fn every_theme_defines_the_roles_the_defaults_use() {
    // set_theme falls back when a role is missing; these three should never
    // need the fallback, or the default configuration renders differently
    // depending on which palette you happen to be on.
    for theme in palette::THEMES.iter() {
        for role in ["primary", "accent", "base-200"] {
            assert!(
                theme.get(role).is_some(),
                "{} is missing {role}",
                theme.name
            );
        }
    }
}