//! Saved workspaces: `workspace.save`, `workspace.list`, `workspace.load`, `workspace.delete`. mod common; use common::{temp_config, temp_vault}; use notescraft_engine::{Registry, Session, register_core}; use serde_json::json; #[test] fn a_layout_is_saved_listed_loaded_replaced_and_deleted() { let vault = temp_vault("workspaces"); let config = temp_config("workspaces"); let mut registry = Registry::new(); register_core(&mut registry).expect("register"); let mut session = Session::open(vault.path()).expect("open"); session.use_settings_dir(config.path()); let layout = json!({"tabs": ["a.md", "b.md"], "active": 1}); registry.run("workspace.save", &mut session, &json!({"name": "Writing", "layout": layout})).expect("save"); registry.run("workspace.save", &mut session, &json!({"name": "Review", "layout": {"tabs": []}})).expect("save"); assert_eq!(registry.run("workspace.list", &mut session, &json!({})).expect("list")["workspaces"], json!(["Review", "Writing"])); assert_eq!(registry.run("workspace.load", &mut session, &json!({"name": "Writing"})).expect("load")["layout"], layout); registry.run("workspace.save", &mut session, &json!({"name": "Writing", "layout": {"tabs": ["c.md"]}})).expect("replace"); assert_eq!(registry.run("workspace.load", &mut session, &json!({"name": "Writing"})).expect("load")["layout"]["tabs"], json!(["c.md"])); registry.run("workspace.delete", &mut session, &json!({"name": "Review"})).expect("delete"); assert_eq!(registry.run("workspace.list", &mut session, &json!({})).expect("list")["workspaces"], json!(["Writing"])); assert!(registry.run("workspace.load", &mut session, &json!({"name": "Review"})).is_err()); assert!(registry.run("workspace.delete", &mut session, &json!({"name": "Review"})).is_err()); } #[test] fn hostile_names_and_oversized_layouts_are_refused() { let vault = temp_vault("workspaces-bad"); let config = temp_config("workspaces-bad"); let mut registry = Registry::new(); register_core(&mut registry).expect("register"); let mut session = Session::open(vault.path()).expect("open"); session.use_settings_dir(config.path()); for name in ["", " pad", ".hidden", "../up", "a/b", "a\\b", "x:y", &"n".repeat(65), "tab\tname"] { assert!(registry.run("workspace.save", &mut session, &json!({"name": name, "layout": {}})).is_err(), "{name:?}"); assert!(registry.run("workspace.load", &mut session, &json!({"name": name})).is_err(), "{name:?}"); } let big = json!({"x": "y".repeat(300_000)}); assert!(registry.run("workspace.save", &mut session, &json!({"name": "big", "layout": big})).is_err()); assert_eq!(registry.run("workspace.list", &mut session, &json!({})).expect("list")["workspaces"], json!([])); } #[test] fn saving_a_note_keeps_a_local_snapshot_a_command_lists_and_reads() { let vault = temp_vault("snapshots"); let config = temp_config("snapshots"); std::fs::write(vault.path().join("n.md"), "first\n").expect("seed"); let mut registry = Registry::new(); register_core(&mut registry).expect("register"); let mut session = Session::open(vault.path()).expect("open"); session.use_settings_dir(config.path()); session.open_buffer("n.md").expect("buffer"); session.buffer_mut("n.md").expect("buffer").edit(0..5, "second").expect("edit"); session.save_buffer("n.md").expect("save"); session.buffer_mut("n.md").expect("buffer").edit(0..6, "third").expect("edit"); session.save_buffer("n.md").expect("save again at once"); let listed = registry.run("history.list", &mut session, &json!({"path": "n.md"})).expect("list"); let versions = listed["versions"].as_array().expect("array"); assert_eq!(versions.len(), 1, "the second save came inside the gap"); let id = versions[0]["id"].as_u64().expect("id"); let read = registry.run("history.read", &mut session, &json!({"path": "n.md", "id": id})).expect("read"); assert_eq!(read["text"], "second\n"); assert!(registry.run("history.read", &mut session, &json!({"path": "n.md", "id": 1})).is_err()); assert_eq!(registry.run("history.list", &mut session, &json!({"path": "other.md"})).expect("list")["versions"], json!([])); }