Files
spotifast/tests/omarchy.rs

114 lines
4.0 KiB
Rust

//! The optional desktop hook must copy palettes without changing preferences
//! or launching an app. All paths and commands here belong to the test.
#![cfg(target_os = "linux")]
use std::{os::unix::fs::PermissionsExt, path::PathBuf, process::Command};
struct Scratch(PathBuf);
impl Drop for Scratch {
fn drop(&mut self) {
let _ = std::fs::remove_dir_all(&self.0);
}
}
#[test]
fn omarchy_hook_replaces_only_its_palette_and_tolerates_a_stopped_app() {
let scratch =
Scratch(std::env::temp_dir().join(format!("spotifast omarchy {}", rand::random::<u64>())));
let source = scratch.0.join("current theme");
let config = scratch.0.join("config");
let target = config.join("spotifast/themes");
let bin = scratch.0.join("bin");
let log = scratch.0.join("commands");
for dir in [&source, &target, &bin] {
std::fs::create_dir_all(dir).unwrap();
}
// Nix provides tools through PATH without /bin or /usr/bin. Keep that
// environment and use its actual interpreter for the generated fixture.
let search_path = std::env::var_os("PATH").expect("test tools on PATH");
let shell = std::env::split_paths(&search_path)
.map(|directory| directory.join("bash"))
.find(|path| path.is_file())
.expect("bash for the Omarchy hook");
let command_path = std::env::join_paths(
std::iter::once(bin.clone()).chain(std::env::split_paths(&search_path)),
)
.unwrap();
std::fs::write(
bin.join("spotifast"),
format!(
"#!{}\nprintf '%s\\n' \"$*\" >> \"$SPOTIFAST_HOOK_TEST_LOG\"\nexit 1\n",
shell.display()
),
)
.unwrap();
std::fs::set_permissions(
bin.join("spotifast"),
std::fs::Permissions::from_mode(0o755),
)
.unwrap();
let run = || {
let output = Command::new(&shell)
.arg(concat!(
env!("CARGO_MANIFEST_DIR"),
"/contrib/omarchy/spotifast-theme"
))
.env("PATH", &command_path)
.env("XDG_CONFIG_HOME", &config)
.env("SPOTIFAST_OMARCHY_THEME_DIR", &source)
.env_remove("SPOTIFAST_THEMES_DIR")
.env("SPOTIFAST_HOOK_TEST_LOG", &log)
.output()
.unwrap();
assert!(
output.status.success(),
"{}",
String::from_utf8_lossy(&output.stderr)
);
};
run();
assert!(!log.exists(), "a missing palette cannot request a reload");
let outside = scratch.0.join("unrelated.json");
std::fs::write(&outside, "preserve me").unwrap();
std::os::unix::fs::symlink(&outside, target.join("omarchy.json")).unwrap();
std::fs::write(config.join("spotifast/settings.json"), "unchanged settings").unwrap();
for text in [r#"{"base":"dark"}"#, r#"{"base":"light"}"#] {
std::fs::write(source.join("spotifast.json"), text).unwrap();
run();
assert_eq!(
std::fs::read_to_string(target.join("omarchy.json")).unwrap(),
text
);
let metadata = std::fs::symlink_metadata(target.join("omarchy.json")).unwrap();
assert!(metadata.is_file());
assert_eq!(metadata.permissions().mode() & 0o777, 0o644);
}
assert_eq!(std::fs::read_to_string(&outside).unwrap(), "preserve me");
assert_eq!(
std::fs::read_to_string(config.join("spotifast/settings.json")).unwrap(),
"unchanged settings"
);
assert_eq!(
std::fs::read_to_string(&log).unwrap(),
"reload-themes\nreload-themes\n"
);
assert_eq!(
std::fs::read_dir(&target).unwrap().count(),
1,
"no temporary file remains"
);
std::fs::remove_file(source.join("spotifast.json")).unwrap();
std::os::unix::fs::symlink(&outside, source.join("spotifast.json")).unwrap();
run();
assert_eq!(
std::fs::read_to_string(&log).unwrap(),
"reload-themes\nreload-themes\n"
);
assert_eq!(
std::fs::read_to_string(target.join("omarchy.json")).unwrap(),
r#"{"base":"light"}"#
);
}