Files
pixstrip/pixstrip-core/tests/watcher_tests.rs
lashman b432cc7431 Fix 26 bugs, edge cases, and consistency issues from fifth audit pass
Critical: undo toast now trashes only batch output files (not entire dir),
JPEG scanline write errors propagated, selective metadata write result returned.

High: zero-dimension guards in ResizeConfig/fit_within, negative aspect ratio
rejection, FM integration toggle infinite recursion guard, saturating counter
arithmetic in executor.

Medium: PNG compression level passed to oxipng, pct mode updates job_config,
external file loading updates step indicator, CLI undo removes history entries,
watch config write failures reported, fast-copy path reads image dimensions for
rename templates, discovery excludes unprocessable formats (heic/svg/ico/jxl),
CLI warns on invalid algorithm/overwrite values, resolve_collision trailing dot
fix, generation guards on all preview threads to cancel stale results, default
DPI aligned to 0, watermark text width uses char count not byte length.

Low: binary path escaped in Nautilus extension, file dialog filter aligned with
discovery, reset_wizard clears preset_mode and output_dir.
2026-03-07 19:47:23 +02:00

116 lines
3.1 KiB
Rust

use pixstrip_core::watcher::*;
use std::sync::mpsc;
#[test]
fn watch_folder_serialization() {
let folder = WatchFolder {
path: "/home/user/photos".into(),
preset_name: "Blog Photos".into(),
recursive: true,
active: true,
};
let json = serde_json::to_string(&folder).unwrap();
let deserialized: WatchFolder = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized.preset_name, "Blog Photos");
assert!(deserialized.recursive);
}
#[test]
fn watcher_starts_and_stops() {
let dir = tempfile::tempdir().unwrap();
let folder = WatchFolder {
path: dir.path().to_path_buf(),
preset_name: "Test".into(),
recursive: false,
active: true,
};
let watcher = FolderWatcher::new();
let (tx, _rx) = mpsc::channel();
watcher.start(&folder, tx).unwrap();
assert!(watcher.is_running());
watcher.stop();
// Give the thread time to see the stop signal
std::thread::sleep(std::time::Duration::from_millis(600));
assert!(!watcher.is_running());
}
#[test]
fn watcher_detects_new_image() {
let dir = tempfile::tempdir().unwrap();
let folder = WatchFolder {
path: dir.path().to_path_buf(),
preset_name: "Test".into(),
recursive: false,
active: true,
};
let watcher = FolderWatcher::new();
let (tx, rx) = mpsc::channel();
watcher.start(&folder, tx).unwrap();
// Wait for watcher to be ready
std::thread::sleep(std::time::Duration::from_millis(500));
// Create an image file
let img_path = dir.path().join("new_photo.jpg");
std::fs::write(&img_path, b"fake jpeg data").unwrap();
// Wait and check for event
let event = rx.recv_timeout(std::time::Duration::from_secs(3));
watcher.stop();
match event {
Ok(WatchEvent::NewImage(path)) => {
assert_eq!(path, img_path);
}
Ok(WatchEvent::Error(e)) => panic!("Unexpected error: {}", e),
Err(_) => panic!("No event received within timeout"),
}
}
#[test]
fn watcher_ignores_non_image_files() {
let dir = tempfile::tempdir().unwrap();
let folder = WatchFolder {
path: dir.path().to_path_buf(),
preset_name: "Test".into(),
recursive: false,
active: true,
};
let watcher = FolderWatcher::new();
let (tx, rx) = mpsc::channel();
watcher.start(&folder, tx).unwrap();
std::thread::sleep(std::time::Duration::from_millis(500));
// Create a non-image file
std::fs::write(dir.path().join("readme.txt"), b"text file").unwrap();
// Should not receive any event
let result = rx.recv_timeout(std::time::Duration::from_secs(1));
watcher.stop();
assert!(result.is_err(), "Should not receive event for non-image file");
}
#[test]
fn watcher_rejects_nonexistent_path() {
let folder = WatchFolder {
path: "/nonexistent/path/to/watch".into(),
preset_name: "Test".into(),
recursive: false,
active: true,
};
let watcher = FolderWatcher::new();
let (tx, _rx) = mpsc::channel();
assert!(watcher.start(&folder, tx).is_err());
}