use std::fs;
use std::path::Path;
use std::process::Command;
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
}
fn icons(dir: &Path, args: &[&str]) -> std::process::Output {
Command::new(env!("CARGO_BIN_EXE_icons"))
.args(args)
.current_dir(dir)
.output()
.expect("failed to run the icons binary")
}
#[test]
fn check_exits_zero_and_prints_ok_for_a_valid_manifest() {
let dir = tempdir().unwrap();
write(dir.path(), "docker.svg", "<svg/>");
write(dir.path(), "icons.gui.toml", "[docker]\nfile = \"docker.svg\"\n");
let output = icons(dir.path(), &["check"]);
assert!(output.status.success(), "{output:?}");
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(stdout.contains("OK"), "{stdout}");
assert!(stdout.contains('1'), "should mention the one icon found: {stdout}");
}
#[test]
fn check_exits_nonzero_and_prints_a_diagnostic_for_an_invalid_manifest() {
let dir = tempdir().unwrap();
write(dir.path(), "icons.gui.toml", "[docker]\nfile = \"docker.svg\"\nfile1 = \"docker.svg\"\n");
let output = icons(dir.path(), &["check"]);
assert!(!output.status.success());
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(stderr.contains("unexpected field"), "{stderr}");
assert!(stderr.contains("file1"), "{stderr}");
assert!(stderr.contains("1 error"), "{stderr}");
}
#[test]
fn check_exits_nonzero_for_a_missing_manifest_file() {
let dir = tempdir().unwrap();
let output = icons(dir.path(), &["check", "--manifest", "does-not-exist.gui.toml"]);
assert!(!output.status.success());
}
mod check_semantic_validation {
use super::*;
#[test]
fn check_catches_a_file_source_pointing_at_a_nonexistent_asset() {
let dir = tempdir().unwrap();
write(dir.path(), "icons.gui.toml", "[docker]\nfile = \"does-not-exist.svg\"\n");
let output = icons(dir.path(), &["check"]);
assert!(!output.status.success());
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(stderr.contains("does-not-exist.svg"), "{stderr}");
assert!(stderr.contains("1 error"), "{stderr}");
}
#[test]
fn check_notes_but_does_not_fail_on_an_uncached_iconify_id() {
let dir = tempdir().unwrap();
write(dir.path(), "icons.gui.toml", "[docker]\niconify = \"mdi:home\"\n");
let output = icons(dir.path(), &["check"]);
assert!(output.status.success(), "{output:?}");
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(stderr.contains("isn't cached locally"), "{stderr}");
assert!(stderr.contains("1 note"), "{stderr}");
}
#[test]
fn check_does_not_catch_a_variant_name_on_an_unrelated_file_entry() {
let dir = tempdir().unwrap();
write(dir.path(), "settings-nonsense.svg", "<svg/>");
write(
dir.path(),
"icons.gui.toml",
"[providers.fluent.override]\nvariants = [\"regular\", \"filled\"]\n\n\
[settings]\nvariants.nonsense = { file = \"settings-nonsense.svg\" }\n",
);
let output = icons(dir.path(), &["check"]);
assert!(output.status.success(), "known gap: {output:?}");
}
#[test]
fn check_catches_a_variant_not_in_the_auto_build_providers_schema() {
let dir = tempdir().unwrap();
write(
dir.path(),
"icons.gui.toml",
"[defaults]\nprovider = \"fluent\"\n\n\
[providers.fluent.override]\nvariants = [\"regular\", \"filled\"]\n\n\
[settings]\nvariants.nonsense = {}\n",
);
let output = icons(dir.path(), &["check"]);
assert!(!output.status.success());
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(stderr.contains("nonsense"), "{stderr}");
assert!(stderr.contains("fluent"), "{stderr}");
}
#[test]
fn check_catches_a_malformed_glyph_spec() {
let dir = tempdir().unwrap();
write(dir.path(), "icons.gui.toml", "[settings]\nglyph = \"no-colon-here\"\n");
let output = icons(dir.path(), &["check"]);
assert!(!output.status.success());
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(stderr.contains("invalid glyph spec"), "{stderr}");
}
#[test]
fn check_does_not_catch_an_unknown_iconify_provider_prefix_on_an_explicit_id() {
let dir = tempdir().unwrap();
write(dir.path(), "icons.gui.toml", "[docker]\niconify = \"totally-fake-provider:some-icon\"\n");
let output = icons(dir.path(), &["check"]);
assert!(output.status.success(), "known gap: {output:?}");
}
#[test]
fn check_catches_an_unknown_provider_used_to_auto_build_an_iconify_id() {
let dir = tempdir().unwrap();
write(
dir.path(),
"icons.gui.toml",
"[defaults]\nprovider = \"totally-fake-provider\"\n\n[docker]\ndynamic = true\n",
);
let output = icons(dir.path(), &["check"]);
assert!(!output.status.success());
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(stderr.contains("totally-fake-provider"), "{stderr}");
}
#[test]
fn check_catches_a_duplicate_key_across_a_link_include() {
let dir = tempdir().unwrap();
write(dir.path(), "a.svg", "<svg/>");
write(dir.path(), "b.svg", "<svg/>");
write(dir.path(), "nav.gui.toml", "[settings]\nfile = \"a.svg\"\n");
write(
dir.path(),
"icons.gui.toml",
"[link]\nincludes = [\"nav.gui.toml\"]\n\n[settings]\nfile = \"b.svg\"\n",
);
let output = icons(dir.path(), &["check"]);
assert!(!output.status.success());
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(stderr.contains("duplicate icon key"), "{stderr}");
assert!(stderr.contains("settings"), "{stderr}");
}
}
#[test]
fn add_writes_a_new_entry_and_prints_the_key() {
let dir = tempdir().unwrap();
write(dir.path(), "logo.svg", "<svg/>");
let output = icons(dir.path(), &["add", "logo.svg", "--name", "my-logo"]);
assert!(output.status.success(), "{output:?}");
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(stdout.contains("my-logo"), "{stdout}");
let (manifest, errors) = guicons_core::load_icon_manifest(&dir.path().join("icons.gui.toml"));
assert!(errors.is_empty(), "{errors:?}");
assert!(manifest.entry_for_key("my-logo").is_some());
}
#[test]
fn add_without_force_fails_on_a_duplicate_key() {
let dir = tempdir().unwrap();
write(dir.path(), "logo.svg", "<svg/>");
write(dir.path(), "icons.gui.toml", "[my-logo]\nfile = \"logo.svg\"\n");
let output = icons(dir.path(), &["add", "logo.svg", "--name", "my-logo"]);
assert!(!output.status.success());
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(stderr.contains("--force"), "{stderr}");
}