From f14bf058b7b7ba27fc9af0b07e69a35b36b5761e Mon Sep 17 00:00:00 2001 From: xscriptor Date: Fri, 6 Nov 2026 22:53:41 +0100 Subject: [PATCH 1/5] test(cli): isolate config edit from ambient editor variables --- tests/cli.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/cli.rs b/tests/cli.rs index 2d73339..cfcf6f4 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -728,13 +728,21 @@ fn config_edit_runs_an_editor_and_validates() { let output = Command::new(env!("CARGO_BIN_EXE_xfetch")) .args([&config_arg, "config", "edit"]) + .env("VISUAL", &editor) .env("EDITOR", &editor) .env("XDG_CONFIG_HOME", dir.join("config")) .env("XDG_CACHE_HOME", dir.join("cache")) + .env("XDG_STATE_HOME", dir.join("state")) .env("HOME", dir.join("home")) .output() .unwrap(); - assert!(output.status.success()); + assert!( + output.status.success(), + "config edit failed: status={:?}\nstdout={}\nstderr={}", + output.status, + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr) + ); assert!( fs::read_to_string(&path) .unwrap() From de9aa2535647f08e6523b81d58ede3e8bfc36eee Mon Sep 17 00:00:00 2001 From: xscriptor Date: Fri, 6 Nov 2026 23:01:04 +0100 Subject: [PATCH 2/5] test(cli): make CLI tests portable across Linux and Windows --- tests/cli.rs | 59 +++++++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/tests/cli.rs b/tests/cli.rs index cfcf6f4..dc354ba 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -321,24 +321,22 @@ fn backup_and_restore_config_roulette() { ) .unwrap(); let routes = config_dir.join("routes.json"); - fs::write( - &routes, - format!( - "[{{\"_name\":\"a\",\"path\":\"{}\"}},{{\"_name\":\"b\",\"path\":\"{}\"}}]", - route_a.display(), - route_b.display() - ), - ) - .unwrap(); + let routes_json = serde_json::json!([ + {"_name": "a", "path": route_a.display().to_string()}, + {"_name": "b", "path": route_b.display().to_string()}, + ]); + fs::write(&routes, serde_json::to_string(&routes_json).unwrap()).unwrap(); let path = config_dir.join("config.jsonc"); - fs::write( - &path, - format!( - "{{\"config_providers\":[{{\"extension\":\"config-roulette\",\"args\":{{\"routes\":\"{}\",\"strategy\":\"daily\"}}}}]}}", - routes.display() - ), - ) - .unwrap(); + let config_json = serde_json::json!({ + "config_providers": [{ + "extension": "config-roulette", + "args": { + "routes": routes.display().to_string(), + "strategy": "daily" + } + }] + }); + fs::write(&path, serde_json::to_string(&config_json).unwrap()).unwrap(); let config_arg = format!("--config={}", path.display()); let backup_file = dir.join("roulette.json"); let backup = command( @@ -445,8 +443,9 @@ fn json_addon_rollback_and_remove() { let dir = temp_dir("addon-json"); let plugins = dir.join("config").join("xfetch").join("plugins"); fs::create_dir_all(&plugins).unwrap(); - let artifact = plugins.join("xfetch-plugin-test"); - let backup = plugins.join("xfetch-plugin-test.bak"); + let ext = if cfg!(windows) { ".exe" } else { "" }; + let artifact = plugins.join(format!("xfetch-plugin-test{ext}")); + let backup = plugins.join(format!("xfetch-plugin-test{ext}.bak")); fs::write(&artifact, b"new").unwrap(); fs::write(&backup, b"old").unwrap(); @@ -533,11 +532,10 @@ fn backup_compress_and_root_remap() { fs::create_dir_all(original.join("themes")).unwrap(); let config = original.join("config.jsonc"); let theme = original.join("themes").join("nord.jsonc"); - fs::write( - &config, - format!("{{\n \"theme\": \"{}\"\n}}\n", theme.display()), - ) - .unwrap(); + let config_json = serde_json::json!({ + "theme": theme.display().to_string() + }); + fs::write(&config, serde_json::to_string(&config_json).unwrap()).unwrap(); fs::write(&theme, "{ \"layout\": \"compact\" }\n").unwrap(); let config_arg = format!("--config={}", config.display()); let backup_dir = dir.join("backups"); @@ -624,8 +622,13 @@ fn schema_and_update_rollback() { let bin_dir = dir.join("bin"); fs::create_dir_all(&bin_dir).unwrap(); - fs::write(bin_dir.join("xfetch"), b"new").unwrap(); - fs::write(bin_dir.join("xfetch.bak"), b"old").unwrap(); + let binary = if cfg!(windows) { + "xfetch.exe" + } else { + "xfetch" + }; + fs::write(bin_dir.join(binary), b"new").unwrap(); + fs::write(bin_dir.join(format!("{binary}.bak")), b"old").unwrap(); let rollback = command( &dir, &[ @@ -639,7 +642,7 @@ fn schema_and_update_rollback() { assert!(rollback.status.success()); let value = stdout_json(&rollback); assert_eq!(value["status"], "rolled-back"); - assert_eq!(fs::read(bin_dir.join("xfetch")).unwrap(), b"old"); + assert_eq!(fs::read(bin_dir.join(binary)).unwrap(), b"old"); } #[cfg(unix)] @@ -721,7 +724,7 @@ fn config_edit_runs_an_editor_and_validates() { let editor = dir.join("editor.sh"); fs::write( &editor, - "#!/bin/sh\nprintf '{ \\\"layout\\\": \\\"minimal\\\" }\\n' > \"$1\"\n", + "#!/bin/sh\ncat > \"$1\" <<'EOF'\n{ \"layout\": \"minimal\" }\nEOF\n", ) .unwrap(); fs::set_permissions(&editor, fs::Permissions::from_mode(0o755)).unwrap(); From 214a0fefeec3e19688d01ebec14843cf95c059d8 Mon Sep 17 00:00:00 2001 From: xscriptor Date: Fri, 6 Nov 2026 23:08:29 +0100 Subject: [PATCH 3/5] test(help): normalize the Windows binary name in snapshots --- tests/help_snapshots.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/help_snapshots.rs b/tests/help_snapshots.rs index 295e44e..871fd6b 100644 --- a/tests/help_snapshots.rs +++ b/tests/help_snapshots.rs @@ -13,7 +13,9 @@ fn run(args: &[&str]) -> String { args, String::from_utf8_lossy(&output.stderr) ); - String::from_utf8(output.stdout).expect("utf-8 output") + String::from_utf8(output.stdout) + .expect("utf-8 output") + .replace("xfetch.exe", "xfetch") } fn snapshot(name: &str, actual: &str) { From 98f599164c80345f670e20cdbf481943596020ca Mon Sep 17 00:00:00 2001 From: xscriptor Date: Fri, 6 Nov 2026 23:17:05 +0100 Subject: [PATCH 4/5] ci(windows): install clippy in the test job --- .github/workflows/rust-tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/rust-tests.yml b/.github/workflows/rust-tests.yml index 5e856a2..f2e67e5 100644 --- a/.github/workflows/rust-tests.yml +++ b/.github/workflows/rust-tests.yml @@ -32,6 +32,8 @@ jobs: - name: Install stable Rust toolchain uses: dtolnay/rust-toolchain@18f0487477426dce244608110aa2660c2893deb7 # stable + with: + components: clippy - name: Run updater tests on Windows run: 'cargo test --locked --no-default-features --features update --bin xfetch update::' From 9cdb6d821a519b53ff31fa6a5597cc957076091b Mon Sep 17 00:00:00 2001 From: xscriptor Date: Fri, 6 Nov 2026 23:26:35 +0100 Subject: [PATCH 5/5] fix(doctor): gate Linux-only code and drop unused Windows helper --- src/cli/doctor/platform/mod.rs | 8 ++------ src/cli/doctor/platform/windows.rs | 7 ------- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/cli/doctor/platform/mod.rs b/src/cli/doctor/platform/mod.rs index 1dd6346..a48d386 100644 --- a/src/cli/doctor/platform/mod.rs +++ b/src/cli/doctor/platform/mod.rs @@ -23,14 +23,10 @@ pub fn collect() -> PlatformInfo { } } +#[cfg(target_os = "linux")] pub fn command_exists(command: &str) -> bool { std::env::var_os("PATH") - .map(|paths| { - std::env::split_paths(&paths).any(|dir| { - let candidate = dir.join(command); - candidate.is_file() || cfg!(windows) && dir.join(format!("{command}.exe")).is_file() - }) - }) + .map(|paths| std::env::split_paths(&paths).any(|dir| dir.join(command).is_file())) .unwrap_or(false) } diff --git a/src/cli/doctor/platform/windows.rs b/src/cli/doctor/platform/windows.rs index 4391500..d79bd34 100644 --- a/src/cli/doctor/platform/windows.rs +++ b/src/cli/doctor/platform/windows.rs @@ -15,10 +15,3 @@ pub fn collect() -> Vec { } details } - -fn detail(name: &str, value: impl Into) -> Detail { - Detail { - name: name.to_string(), - value: value.into(), - } -}