use pixstrip_core::preset::Preset; use pixstrip_core::storage::*; fn with_temp_config_dir(f: impl FnOnce(&std::path::Path)) { let dir = tempfile::tempdir().unwrap(); f(dir.path()); } // --- Preset file I/O --- #[test] fn save_and_load_preset() { with_temp_config_dir(|base| { let store = PresetStore::with_base_dir(base); let preset = Preset::builtin_blog_photos(); store.save(&preset).unwrap(); let loaded = store.load("Blog Photos").unwrap(); assert_eq!(loaded.name, preset.name); assert_eq!(loaded.is_custom, preset.is_custom); }); } #[test] fn save_preset_creates_directory() { with_temp_config_dir(|base| { let presets_dir = base.join("presets"); assert!(!presets_dir.exists()); let store = PresetStore::with_base_dir(base); let preset = Preset::builtin_blog_photos(); store.save(&preset).unwrap(); assert!(presets_dir.exists()); }); } #[test] fn list_saved_presets() { with_temp_config_dir(|base| { let store = PresetStore::with_base_dir(base); store.save(&Preset::builtin_blog_photos()).unwrap(); store.save(&Preset::builtin_privacy_clean()).unwrap(); let list = store.list().unwrap(); assert_eq!(list.len(), 2); let names: Vec<&str> = list.iter().map(|p| p.name.as_str()).collect(); assert!(names.contains(&"Blog Photos")); assert!(names.contains(&"Privacy Clean")); }); } #[test] fn delete_preset() { with_temp_config_dir(|base| { let store = PresetStore::with_base_dir(base); store.save(&Preset::builtin_blog_photos()).unwrap(); assert!(store.delete("Blog Photos").is_ok()); assert!(store.load("Blog Photos").is_err()); }); } #[test] fn load_nonexistent_preset_returns_error() { with_temp_config_dir(|base| { let store = PresetStore::with_base_dir(base); assert!(store.load("Nonexistent").is_err()); }); } #[test] fn preset_filename_sanitization() { with_temp_config_dir(|base| { let store = PresetStore::with_base_dir(base); let mut preset = Preset::builtin_blog_photos(); preset.name = "My Preset / With Chars!".into(); preset.is_custom = true; store.save(&preset).unwrap(); let loaded = store.load("My Preset / With Chars!").unwrap(); assert_eq!(loaded.name, preset.name); }); } // --- Preset import/export --- #[test] fn export_and_import_preset() { with_temp_config_dir(|base| { let store = PresetStore::with_base_dir(base); let preset = Preset::builtin_blog_photos(); let export_path = base.join("exported.pixstrip-preset"); store.export_to_file(&preset, &export_path).unwrap(); assert!(export_path.exists()); let imported = store.import_from_file(&export_path).unwrap(); assert_eq!(imported.name, preset.name); assert!(imported.is_custom); }); } #[test] fn import_preset_marks_as_custom() { with_temp_config_dir(|base| { let store = PresetStore::with_base_dir(base); let preset = Preset::builtin_blog_photos(); let export_path = base.join("test.pixstrip-preset"); store.export_to_file(&preset, &export_path).unwrap(); let imported = store.import_from_file(&export_path).unwrap(); assert!(imported.is_custom); }); } // --- Config persistence --- #[test] fn save_and_load_config() { with_temp_config_dir(|base| { let config_store = ConfigStore::with_base_dir(base); let config = pixstrip_core::config::AppConfig { output_subfolder: "output_images".into(), auto_open_output: true, ..Default::default() }; config_store.save(&config).unwrap(); let loaded = config_store.load().unwrap(); assert_eq!(loaded.output_subfolder, "output_images"); assert!(loaded.auto_open_output); }); } #[test] fn load_missing_config_returns_default() { with_temp_config_dir(|base| { let config_store = ConfigStore::with_base_dir(base); let config = config_store.load().unwrap(); let default = pixstrip_core::config::AppConfig::default(); assert_eq!(config.output_subfolder, default.output_subfolder); }); } // --- Session memory --- #[test] fn save_and_load_session() { with_temp_config_dir(|base| { let session_store = SessionStore::with_base_dir(base); let session = SessionState { last_input_dir: Some("/home/user/photos".into()), last_output_dir: Some("/home/user/processed".into()), last_preset_name: Some("Blog Photos".into()), current_step: 3, window_width: Some(1024), window_height: Some(768), window_maximized: false, ..Default::default() }; session_store.save(&session).unwrap(); let loaded = session_store.load().unwrap(); assert_eq!(loaded.last_input_dir.as_deref(), Some("/home/user/photos")); assert_eq!(loaded.current_step, 3); }); } #[test] fn load_missing_session_returns_default() { with_temp_config_dir(|base| { let session_store = SessionStore::with_base_dir(base); let session = session_store.load().unwrap(); assert_eq!(session.current_step, 0); assert!(session.last_input_dir.is_none()); }); } // --- Processing history --- #[test] fn add_and_list_history_entries() { with_temp_config_dir(|base| { let history = HistoryStore::with_base_dir(base); let entry = HistoryEntry { timestamp: "2026-03-06T12:00:00Z".into(), input_dir: "/home/user/photos".into(), output_dir: "/home/user/processed".into(), preset_name: Some("Blog Photos".into()), total: 10, succeeded: 9, failed: 1, total_input_bytes: 50_000_000, total_output_bytes: 10_000_000, elapsed_ms: 5000, output_files: vec![ "/home/user/processed/photo1.jpg".into(), "/home/user/processed/photo2.jpg".into(), ], }; history.add(entry.clone()).unwrap(); let entries = history.list().unwrap(); assert_eq!(entries.len(), 1); assert_eq!(entries[0].total, 10); assert_eq!(entries[0].succeeded, 9); }); } #[test] fn history_appends_entries() { with_temp_config_dir(|base| { let history = HistoryStore::with_base_dir(base); for i in 0..3 { history .add(HistoryEntry { timestamp: format!("2026-03-06T12:0{}:00Z", i), input_dir: "/input".into(), output_dir: "/output".into(), preset_name: None, total: i + 1, succeeded: i + 1, failed: 0, total_input_bytes: 1000, total_output_bytes: 500, elapsed_ms: 100, output_files: vec![], }) .unwrap(); } let entries = history.list().unwrap(); assert_eq!(entries.len(), 3); }); } #[test] fn clear_history() { with_temp_config_dir(|base| { let history = HistoryStore::with_base_dir(base); history .add(HistoryEntry { timestamp: "2026-03-06T12:00:00Z".into(), input_dir: "/input".into(), output_dir: "/output".into(), preset_name: None, total: 1, succeeded: 1, failed: 0, total_input_bytes: 1000, total_output_bytes: 500, elapsed_ms: 100, output_files: vec![], }) .unwrap(); history.clear().unwrap(); let entries = history.list().unwrap(); assert!(entries.is_empty()); }); } #[test] fn empty_history_returns_empty_list() { with_temp_config_dir(|base| { let history = HistoryStore::with_base_dir(base); let entries = history.list().unwrap(); assert!(entries.is_empty()); }); }