use markbase::filetree::{node::NodeType, FileTree}; use rusqlite::Connection; use uuid::Uuid; fn temp_db() -> (Connection, String) { let user_id = format!("test_{}", Uuid::new_v4()); let conn = FileTree::init_user_db(&user_id).unwrap(); (conn, user_id) } #[test] fn test_api_create_folder_node() { let (conn, user_id) = temp_db(); let mut tree = FileTree::load(&conn, &user_id).unwrap(); let label = "TestFolder"; let node_type = NodeType::Folder; let folder = FileTree::new_folder(label, None); let node_id = folder.node_id.clone(); tree.insert_node(&conn, &folder).unwrap(); let loaded = FileTree::load(&conn, &user_id).unwrap(); let found = loaded.nodes.iter().find(|n| n.node_id == node_id); assert!(found.is_some()); let found_node = found.unwrap(); assert_eq!(found_node.label, label); assert_eq!(found_node.node_type, node_type); assert!(found_node.parent_id.is_none()); } #[test] fn test_api_create_file_node() { let (conn, user_id) = temp_db(); let mut tree = FileTree::load(&conn, &user_id).unwrap(); let parent = FileTree::new_folder("Parent", None); tree.insert_node(&conn, &parent).unwrap(); let (file_node, register_sql) = FileTree::new_file_node( "test.mp4", "abc123def456", Some("sha256hash"), "test.mp4", Some(1024000), Some("video/mp4"), None, Some(parent.node_id.clone()), ); if let Some(sql) = register_sql { conn.execute_batch(&sql).unwrap(); } let node_id = file_node.node_id.clone(); tree.insert_node(&conn, &file_node).unwrap(); let loaded = FileTree::load(&conn, &user_id).unwrap(); let found = loaded.nodes.iter().find(|n| n.node_id == node_id); assert!(found.is_some()); let found_node = found.unwrap(); assert_eq!(found_node.label, "test.mp4"); assert_eq!(found_node.node_type, NodeType::File); assert_eq!(found_node.parent_id, Some(parent.node_id.clone())); assert_eq!(found_node.file_size, Some(1024000)); } #[test] fn test_api_update_node() { let (conn, user_id) = temp_db(); let mut tree = FileTree::load(&conn, &user_id).unwrap(); let mut folder = FileTree::new_folder("Original", None); tree.insert_node(&conn, &folder).unwrap(); folder.label = "Updated".to_string(); folder.icon = Some("📁".to_string()); folder.color = Some("#ff0000".to_string()); tree.update_node(&conn, &folder.node_id, &folder).unwrap(); let loaded = FileTree::load(&conn, &user_id).unwrap(); let found = loaded.nodes.iter().find(|n| n.node_id == folder.node_id); assert!(found.is_some()); let found_node = found.unwrap(); assert_eq!(found_node.label, "Updated"); assert_eq!(found_node.icon, Some("📁".to_string())); assert_eq!(found_node.color, Some("#ff0000".to_string())); } #[test] fn test_api_delete_node() { let (conn, user_id) = temp_db(); let mut tree = FileTree::load(&conn, &user_id).unwrap(); let folder = FileTree::new_folder("ToDelete", None); let node_id = folder.node_id.clone(); tree.insert_node(&conn, &folder).unwrap(); tree.delete_node(&conn, &node_id).unwrap(); let loaded = FileTree::load(&conn, &user_id).unwrap(); let found = loaded.nodes.iter().find(|n| n.node_id == node_id); assert!(found.is_none(), "deleted node should not be found"); } #[test] fn test_api_move_node() { let (conn, user_id) = temp_db(); let mut tree = FileTree::load(&conn, &user_id).unwrap(); let root = FileTree::new_folder("Root", None); let child = FileTree::new_folder("Child", Some(root.node_id.clone())); tree.insert_node(&conn, &root).unwrap(); tree.insert_node(&conn, &child).unwrap(); tree.move_node(&conn, &child.node_id, None).unwrap(); let loaded = FileTree::load(&conn, &user_id).unwrap(); let moved = loaded.nodes.iter().find(|n| n.node_id == child.node_id); assert!(moved.is_some()); assert!( moved.unwrap().parent_id.is_none(), "moved node should have no parent" ); } #[test] fn test_api_update_alias() { let (conn, user_id) = temp_db(); let mut tree = FileTree::load(&conn, &user_id).unwrap(); let folder = FileTree::new_folder("Videos", None); tree.insert_node(&conn, &folder).unwrap(); tree.update_node_alias(&conn, &folder.node_id, "zh_tw", "影片") .unwrap(); tree.update_node_alias(&conn, &folder.node_id, "en_us", "Videos") .unwrap(); tree.update_node_alias(&conn, &folder.node_id, "ja_jp", "動画") .unwrap(); let loaded = FileTree::load(&conn, &user_id).unwrap(); let found = loaded.nodes.iter().find(|n| n.node_id == folder.node_id); assert!(found.is_some()); let found_node = found.unwrap(); assert_eq!( found_node.aliases.get("zh_tw").map(|s| s.as_str()), Some("影片") ); assert_eq!( found_node.aliases.get("en_us").map(|s| s.as_str()), Some("Videos") ); assert_eq!( found_node.aliases.get("ja_jp").map(|s| s.as_str()), Some("動画") ); } #[test] fn test_api_get_tree() { let (conn, user_id) = temp_db(); let mut tree = FileTree::load(&conn, &user_id).unwrap(); let root = FileTree::new_folder("Root", None); let child1 = FileTree::new_folder("Child1", Some(root.node_id.clone())); let child2 = FileTree::new_folder("Child2", Some(root.node_id.clone())); tree.insert_node(&conn, &root).unwrap(); tree.insert_node(&conn, &child1).unwrap(); tree.insert_node(&conn, &child2).unwrap(); let loaded = FileTree::load(&conn, &user_id).unwrap(); assert_eq!(loaded.nodes.len(), 3); assert_eq!(loaded.user_id, user_id); } #[test] fn test_api_build_tree_structure() { let (conn, user_id) = temp_db(); let mut tree = FileTree::load(&conn, &user_id).unwrap(); let root = FileTree::new_folder("Root", None); let child1 = FileTree::new_folder("Child1", Some(root.node_id.clone())); let child2 = FileTree::new_folder("Child2", Some(root.node_id.clone())); let grandchild = FileTree::new_folder("Grandchild", Some(child1.node_id.clone())); tree.insert_node(&conn, &root).unwrap(); tree.insert_node(&conn, &child1).unwrap(); tree.insert_node(&conn, &child2).unwrap(); tree.insert_node(&conn, &grandchild).unwrap(); let roots = tree.build_tree(); assert_eq!(roots.len(), 1); assert_eq!(roots[0].label, "Root"); } #[test] fn test_api_add_location() { let (_conn, user_id) = temp_db(); let conn = FileTree::open_user_db(&user_id).unwrap(); let file_uuid = "abc123def456"; let location = "/path/to/file.mp4"; FileTree::add_location(&conn, file_uuid, location, Some("origin")).unwrap(); let result: String = conn .query_row( "SELECT location FROM file_locations WHERE file_uuid = ?1", [file_uuid], |row| row.get(0), ) .unwrap(); assert_eq!(result, location); } #[test] fn test_api_delete_all_nodes() { let (conn, user_id) = temp_db(); let mut tree = FileTree::load(&conn, &user_id).unwrap(); for i in 1..=5 { let folder = FileTree::new_folder(&format!("Folder{}", i), None); tree.insert_node(&conn, &folder).unwrap(); } let loaded = FileTree::load(&conn, &user_id).unwrap(); assert_eq!(loaded.nodes.len(), 5); for node in &loaded.nodes { conn.execute( "DELETE FROM file_nodes WHERE node_id = ?1", rusqlite::params![node.node_id], ) .unwrap(); } let after_delete = FileTree::load(&conn, &user_id).unwrap(); assert_eq!(after_delete.nodes.len(), 0); }