gpui-phosphor 0.1.0

An unofficial GPUI component and asset source for Phosphor Icons
Documentation
use std::borrow::Cow;

use gpui::{AssetSource, SharedString};
use gpui_phosphor::{IconName, PhosphorAssets, Weight};

#[test]
fn generated_icon_names_produce_namespaced_paths() {
    assert!(!IconName::ALL.is_empty());
    assert_eq!(IconName::Heart.as_str(), "heart");
    assert_eq!(IconName::Heart.to_string(), "heart");
    if let Some(weight) = Weight::ALL.into_iter().find(|weight| weight.is_enabled()) {
        let path = IconName::Heart
            .path(weight)
            .expect("an enabled weight should produce a path");
        assert_eq!(path.to_string(), format!("phosphor/{weight}/heart.svg"));
    } else {
        assert!(IconName::Heart.path(Weight::Regular).is_err());
    }
    assert_eq!(IconName::from_name("heart"), Some(IconName::Heart));
    assert_eq!(IconName::from_name("not-an-icon"), None);
}

#[test]
fn every_enabled_weight_loads_from_embedded_assets() {
    let source = PhosphorAssets;
    for weight in Weight::ALL {
        if !weight.is_enabled() {
            continue;
        }
        let path = IconName::Heart
            .path(weight)
            .expect("enabled weights should produce paths");
        let bytes = source
            .load(path.as_ref())
            .expect("heart should not fail to load")
            .expect("heart should be embedded");
        let svg = std::str::from_utf8(&bytes).expect("Phosphor SVG should be UTF-8");
        assert!(svg.starts_with("<svg"));
    }

    #[cfg(feature = "regular")]
    {
        let path = IconName::Heart.path(Weight::Regular).unwrap();
        let paths = source
            .list("phosphor/regular")
            .expect("regular assets should list");
        assert_eq!(paths.len(), IconName::ALL.len());
        assert!(paths.iter().any(|asset| asset == &path));
    }
}

#[test]
fn feature_flags_match_the_compiled_configuration() {
    assert_eq!(Weight::Regular.is_enabled(), cfg!(feature = "regular"));
    assert_eq!(Weight::Thin.is_enabled(), cfg!(feature = "thin"));
    assert_eq!(Weight::Light.is_enabled(), cfg!(feature = "light"));
    assert_eq!(Weight::Bold.is_enabled(), cfg!(feature = "bold"));
    assert_eq!(Weight::Fill.is_enabled(), cfg!(feature = "fill"));
    assert_eq!(Weight::Duotone.is_enabled(), cfg!(feature = "duotone"));
}

#[test]
fn disabled_weight_has_actionable_error() {
    for weight in Weight::ALL {
        if !weight.is_enabled() {
            let error = IconName::Heart
                .path(weight)
                .expect_err("disabled weights should not resolve");
            assert!(error.to_string().contains(weight.as_str()));
        }
    }
}

#[test]
fn asset_source_reports_disabled_weight_errors() {
    let source = PhosphorAssets;
    for weight in Weight::ALL {
        if weight.is_enabled() {
            continue;
        }
        let path = format!("phosphor/{weight}/heart.svg");
        let error = source
            .load(&path)
            .expect_err("disabled assets should report their missing feature");
        assert!(error.to_string().contains(weight.as_str()));
    }
}

struct ExistingAssets;

impl AssetSource for ExistingAssets {
    fn load(&self, path: &str) -> gpui::Result<Option<Cow<'static, [u8]>>> {
        if path == "custom/example.svg" {
            Ok(Some(Cow::Borrowed(b"<svg />")))
        } else {
            Ok(None)
        }
    }

    fn list(&self, _path: &str) -> gpui::Result<Vec<SharedString>> {
        Ok(vec!["custom/example.svg".into()])
    }
}

#[test]
fn composable_source_delegates_non_phosphor_assets() {
    let source = PhosphorAssets::with_fallback(ExistingAssets);
    let custom = source
        .load("custom/example.svg")
        .expect("fallback load should succeed")
        .expect("fallback asset should be present");
    assert_eq!(&*custom, b"<svg />");

    let paths = source.list("custom").expect("fallback list should succeed");
    assert_eq!(paths, vec![SharedString::from("custom/example.svg")]);
}