use super::*;
use crate::fs_watcher::tests::workspace;
use std::fs;
use tempfile::tempdir;
#[test]
fn coalesce_drops_rename_source_with_trailing_modify() {
use notify::event::{CreateKind, DataChange};
let (_dir, root) = workspace();
fs::create_dir_all(root.join("steps/abc/001")).unwrap();
let tmp = root.join("steps/abc/001/request.json.tmp");
let final_path = root.join("steps/abc/001/request.json");
fs::write(&final_path, b"{}").unwrap(); let name = EventKind::Modify(ModifyKind::Name(RenameMode::Any));
let modify = EventKind::Modify(ModifyKind::Data(DataChange::Content));
let raw = vec![
(tmp.clone(), EventKind::Create(CreateKind::File)),
(tmp.clone(), name),
(tmp.clone(), modify),
(final_path.clone(), EventKind::Create(CreateKind::File)),
];
let changes = coalesce(&root, RootKind::Workspace, raw);
assert_eq!(changes.len(), 1);
assert_eq!(changes[0].path, final_path);
assert_eq!(changes[0].kind, ChangeKind::Touched);
}
#[test]
fn coalesce_surfaces_genuine_deletion_with_non_remove_last_event() {
use notify::event::{CreateKind, DataChange, RemoveKind};
let (_dir, root) = workspace();
fs::create_dir_all(root.join("agents/aa-bb/summary")).unwrap();
let gone = root.join("agents/aa-bb/summary/001.md");
let modify = EventKind::Modify(ModifyKind::Data(DataChange::Content));
let raw = vec![
(gone.clone(), EventKind::Create(CreateKind::File)),
(gone.clone(), EventKind::Remove(RemoveKind::File)),
(gone.clone(), modify),
];
let changes = coalesce(&root, RootKind::Workspace, raw);
assert_eq!(changes.len(), 1);
assert_eq!(changes[0].path, gone);
assert_eq!(changes[0].kind, ChangeKind::Removed);
}
#[test]
fn ingest_splits_name_both_into_from_and_to() {
let mut raw = Vec::new();
ingest(
Event {
kind: EventKind::Modify(ModifyKind::Name(RenameMode::Both)),
paths: vec![PathBuf::from("/a"), PathBuf::from("/b")],
attrs: notify::event::EventAttributes::default(),
},
&mut raw,
);
assert_eq!(raw.len(), 2);
assert!(matches!(
raw[0].1,
EventKind::Modify(ModifyKind::Name(RenameMode::From))
));
assert!(matches!(
raw[1].1,
EventKind::Modify(ModifyKind::Name(RenameMode::To))
));
}
#[test]
fn coalesce_drops_prior_events_when_rename_from_arrives() {
let repo = Path::new("/r");
let p = PathBuf::from("/r/steps/abc/001/request.json");
let raw = vec![
(
p.clone(),
EventKind::Create(notify::event::CreateKind::File),
),
(
p.clone(),
EventKind::Modify(ModifyKind::Name(RenameMode::From)),
),
];
assert!(coalesce(repo, RootKind::Workspace, raw).is_empty());
}
#[test]
fn classify_over_existence_and_rename() {
let root = tempdir().unwrap();
let present = root.path().join("x");
fs::write(&present, b"").unwrap();
assert_eq!(classify(false, &present), Some(ChangeKind::Touched));
assert_eq!(classify(true, &present), Some(ChangeKind::Touched));
let absent = Path::new("/no/such/path");
assert_eq!(classify(true, absent), None);
assert_eq!(classify(false, absent), Some(ChangeKind::Removed));
}