use std::fs;
use std::path::Path;
use tempfile::tempdir;
fn write(dir: &Path, name: &str, content: &str) -> std::path::PathBuf {
let path = dir.join(name);
if let Some(parent) = path.parent() {
fs::create_dir_all(parent).unwrap();
}
fs::write(&path, content).unwrap();
path
}
#[test]
fn add_file_source_creates_a_fresh_manifest() {
let dir = tempdir().unwrap();
let manifest_path = dir.path().join("icons.gui.toml");
let keys = guicons_cli::add(&manifest_path, "./logo.svg", Some("uniproc-logo"), &[], None, false).unwrap();
assert_eq!(keys, vec!["uniproc-logo"]);
let (manifest, errors) = guicons_core::load_icon_manifest(&manifest_path);
assert!(errors.is_empty(), "{errors:?}");
let entry = manifest.entry_for_key("uniproc-logo").unwrap();
assert_eq!(entry.family(), "uniproc-logo");
}
#[test]
fn add_preserves_existing_content_and_formatting() {
let dir = tempdir().unwrap();
let manifest_path = write(
dir.path(),
"icons.gui.toml",
"# a comment worth keeping\n[defaults]\nroot = \"assets\"\n\n[docker]\nfile = \"docker.svg\"\n",
);
guicons_cli::add(&manifest_path, "./logo.svg", Some("logo"), &[], None, false).unwrap();
let content = fs::read_to_string(&manifest_path).unwrap();
assert!(content.contains("# a comment worth keeping"));
assert!(content.contains("root = \"assets\""));
assert!(content.contains("[docker]"));
let (manifest, errors) = guicons_core::load_icon_manifest(&manifest_path);
assert!(errors.is_empty(), "{errors:?}");
assert!(manifest.entry_for_key("docker").is_some());
assert!(manifest.entry_for_key("logo").is_some());
}
#[test]
fn add_iconify_without_flags_falls_back_to_flat_entry_without_a_schema() {
let dir = tempdir().unwrap();
let manifest_path = dir.path().join("icons.gui.toml");
let keys = guicons_cli::add(&manifest_path, "fluent:settings-24-regular", None, &[], None, false).unwrap();
assert_eq!(keys, vec!["settings-24-regular"]);
let (manifest, errors) = guicons_core::load_icon_manifest(&manifest_path);
assert!(errors.is_empty(), "{errors:?}");
let entry = manifest.entry_for_key("settings-24-regular").unwrap();
assert_eq!(
entry.source(),
&guicons_core::IconEntrySource::Iconify("fluent:settings-24-regular".to_string())
);
}
#[test]
fn add_iconify_without_flags_decomposes_using_provider_schema() {
let dir = tempdir().unwrap();
let manifest_path = write(
dir.path(),
"icons.gui.toml",
"[providers.fluent.override]\nvariants = [\"regular\", \"filled\"]\nsizes = [24]\n",
);
let keys = guicons_cli::add(&manifest_path, "fluent:settings-24-regular", None, &[], None, false).unwrap();
assert_eq!(keys, vec!["settings-24-regular"]);
let (manifest, errors) = guicons_core::load_icon_manifest(&manifest_path);
assert!(errors.is_empty(), "{errors:?}");
let entry = manifest.entry_for_key("settings-24-regular").unwrap();
assert_eq!(entry.family(), "settings");
assert_eq!(entry.variant(), Some("regular"));
assert_eq!(entry.size(), Some(24));
}
#[test]
fn add_with_variants_and_size_writes_a_sized_group() {
let dir = tempdir().unwrap();
let manifest_path = dir.path().join("icons.gui.toml");
let mut keys = guicons_cli::add(
&manifest_path,
"fluent:settings",
Some("settings"),
&["filled".to_string(), "regular".to_string()],
Some(24),
false,
)
.unwrap();
keys.sort();
assert_eq!(keys, vec!["settings-24-filled", "settings-24-regular"]);
let (manifest, errors) = guicons_core::load_icon_manifest(&manifest_path);
assert!(errors.is_empty(), "{errors:?}");
let filled = manifest.entry_for_key("settings-24-filled").unwrap();
assert_eq!(filled.family(), "settings");
assert_eq!(filled.size(), Some(24));
assert_eq!(filled.variant(), Some("filled"));
assert_eq!(
filled.source(),
&guicons_core::IconEntrySource::Iconify("fluent:settings-24-filled".to_string())
);
}
#[test]
fn add_rejects_duplicate_key_without_force() {
let dir = tempdir().unwrap();
let manifest_path = write(dir.path(), "icons.gui.toml", "[docker]\nfile = \"docker.svg\"\n");
let err = guicons_cli::add(&manifest_path, "./other.svg", Some("docker"), &[], None, false).unwrap_err();
assert!(matches!(err, guicons_cli::AddError::AlreadyExists(_)));
let content = fs::read_to_string(&manifest_path).unwrap();
assert!(content.contains("docker.svg"));
assert!(!content.contains("other.svg"));
}
#[test]
fn add_overwrites_duplicate_key_with_force() {
let dir = tempdir().unwrap();
let manifest_path = write(dir.path(), "icons.gui.toml", "[docker]\nfile = \"docker.svg\"\n");
guicons_cli::add(&manifest_path, "./other.svg", Some("docker"), &[], None, true).unwrap();
let (manifest, errors) = guicons_core::load_icon_manifest(&manifest_path);
assert!(errors.is_empty(), "{errors:?}");
let entry = manifest.entry_for_key("docker").unwrap();
match entry.source() {
guicons_core::IconEntrySource::File(path) => {
assert_eq!(path.file_name().unwrap(), "other.svg");
}
other => panic!("expected a file source, got {other:?}"),
}
}
#[test]
fn add_variants_without_name_is_an_error() {
let dir = tempdir().unwrap();
let manifest_path = dir.path().join("icons.gui.toml");
let err = guicons_cli::add(
&manifest_path,
"fluent:settings",
None,
&["filled".to_string()],
None,
false,
)
.unwrap_err();
assert!(matches!(err, guicons_cli::AddError::Plan(_)));
}