| 1 | use notebook::session::{Change, Notebook}; |
| 2 | use std::io::Write; |
| 3 | |
| 4 | /// One client watches a notebook while another changes it on disk; changes follow file |
| 5 | /// identity, and an unreachable notebook keeps the last catalog. |
| 6 | #[test] |
| 7 | fn external_structure_changes_are_reported_by_identity() { |
| 8 | let temporary = tempfile::tempdir().unwrap(); |
| 9 | let root = temporary.path().join("notebook"); |
| 10 | std::fs::create_dir(&root).unwrap(); |
| 11 | let first = onestore::create_section("First.one", "First page", "Author").unwrap(); |
| 12 | std::fs::File::create_new(root.join("First.one")) |
| 13 | .unwrap() |
| 14 | .write_all(&first) |
| 15 | .unwrap(); |
| 16 | let first_id = onestore::Store::parse(&first).unwrap().header.file_id; |
| 17 | std::fs::write( |
| 18 | root.join("Open Notebook.onetoc2"), |
| 19 | onestore::create_table_of_contents("Open Notebook.onetoc2", &[("First.one", first_id)]) |
| 20 | .unwrap(), |
| 21 | ) |
| 22 | .unwrap(); |
| 23 | let mut watcher = Notebook::open(&root, temporary.path().join("watcher")).unwrap(); |
| 24 | let mut other = Notebook::open(&root, temporary.path().join("other")).unwrap(); |
| 25 | assert_eq!(watcher.refresh().unwrap(), []); |
| 26 | |
| 27 | other |
| 28 | .create_section( |
| 29 | "", |
| 30 | "Second", |
| 31 | &onestore::PageCreation::new(None, Some(""), "Author").unwrap(), |
| 32 | ) |
| 33 | .unwrap(); |
| 34 | other.create_group("", "Group").unwrap(); |
| 35 | other |
| 36 | .create_section( |
| 37 | "Group", |
| 38 | "Inner", |
| 39 | &onestore::PageCreation::new(None, Some(""), "Author").unwrap(), |
| 40 | ) |
| 41 | .unwrap(); |
| 42 | assert_eq!( |
| 43 | watcher.refresh().unwrap(), |
| 44 | [ |
| 45 | Change::Added("Second.one".into()), |
| 46 | Change::Added("Group".into()), |
| 47 | Change::Added("Group/Inner.one".into()), |
| 48 | ] |
| 49 | ); |
| 50 | |
| 51 | other.rename("Second.one", "Renamed").unwrap(); |
| 52 | assert_eq!( |
| 53 | watcher.refresh().unwrap(), |
| 54 | [Change::Moved { |
| 55 | from: "Second.one".into(), |
| 56 | to: "Renamed.one".into() |
| 57 | }] |
| 58 | ); |
| 59 | |
| 60 | other.reorder("", &["Renamed.one", "First.one"]).unwrap(); |
| 61 | assert_eq!(watcher.refresh().unwrap(), [Change::Reordered("".into())]); |
| 62 | |
| 63 | other.delete("First.one").unwrap(); |
| 64 | assert_eq!( |
| 65 | watcher.refresh().unwrap(), |
| 66 | [ |
| 67 | Change::Moved { |
| 68 | from: "First.one".into(), |
| 69 | to: "OneNote_RecycleBin/First.one".into() |
| 70 | }, |
| 71 | Change::Added("OneNote_RecycleBin".into()), |
| 72 | ] |
| 73 | ); |
| 74 | std::fs::remove_dir_all(root.join("OneNote_RecycleBin")).unwrap(); |
| 75 | assert_eq!( |
| 76 | watcher.refresh().unwrap(), |
| 77 | [ |
| 78 | Change::Removed("OneNote_RecycleBin".into()), |
| 79 | Change::Removed("OneNote_RecycleBin/First.one".into()), |
| 80 | ] |
| 81 | ); |
| 82 | |
| 83 | let away = temporary.path().join("away"); |
| 84 | std::fs::rename(&root, &away).unwrap(); |
| 85 | assert!(watcher.refresh().is_err()); |
| 86 | assert_eq!(watcher.catalog().sections.len(), 1); |
| 87 | std::fs::rename(&away, &root).unwrap(); |
| 88 | assert_eq!(watcher.refresh().unwrap(), []); |
| 89 | assert_eq!(watcher.refresh().unwrap(), []); |
| 90 | } |