1300a4e223
核心功能: - ✅ Categories/Series双视图管理(category_view.rs + import_markdown.rs) - ✅ FUSE Multi-Volume支持(tree_type参数) - ✅ SSH/SFTP/SCP/rsync协议完整实现(4042行) - ✅ NFS/SMB Module Phase 1-3完成 - ✅ Archive Module Phase 1-4完成(2916行) - ✅ Download Center API完整实现 - ✅ S3兼容API实现(560行) Git配置修正: - ✅ 删除错误origin(gitea.momentry.ddns.net) - ✅ 删除m5max128(指向机器名) - ✅ 设置origin = m5max128gitea.momentry.ddns.net/admin/markbase - ✅ 设置m4minigitea = m4minigitea.momentry.ddns.net/warren/markbase 数据清理: - ✅ 删除38个临时SQLite(保留accusys.sqlite、demo.sqlite) - ✅ 删除.bak、test_*.bin、调试脚本等临时文件 - ✅ 删除临时目录(build/、download files/、raid_test/等) - ✅ 更新.gitignore排除临时文件 架构优化: - 52个文件修改,2434行新增,4739行删除 - Workspace成员整合(16个crate) - 数据库状态:accusys.sqlite保留(主demo测试) 远程同步: - ✅ 准备推送到m5max128gitea(远程Gitea) - ✅ 准备推送到m4minigitea(本地Gitea)
248 lines
7.6 KiB
Rust
248 lines
7.6 KiB
Rust
// API測試 - 使用整合測試方式
|
|
// 因handler函數未公開,使用FileTree直接測試API邏輯
|
|
|
|
use markbase::filetree::node::NodeType;
|
|
use markbase::filetree::{mode, FileTree};
|
|
use rusqlite::Connection;
|
|
use uuid::Uuid;
|
|
|
|
fn temp_db() -> (Connection, String) {
|
|
let user_id = format!("test_api_{}", Uuid::new_v4());
|
|
let conn = FileTree::init_user_db(&user_id).unwrap();
|
|
(conn, user_id)
|
|
}
|
|
|
|
#[test]
|
|
fn test_api_logic_create_folder() {
|
|
let (conn, user_id) = temp_db();
|
|
let mut tree = FileTree::load(&conn, &user_id, "untitled folder").unwrap();
|
|
|
|
let folder = FileTree::new_folder("API_Test_Folder", None);
|
|
tree.insert_node(&conn, &folder).unwrap();
|
|
|
|
let loaded = FileTree::load(&conn, &user_id, "untitled folder").unwrap();
|
|
assert_eq!(loaded.nodes.len(), 1);
|
|
}
|
|
|
|
#[test]
|
|
fn test_api_logic_create_file() {
|
|
let (conn, user_id) = temp_db();
|
|
let mut tree = FileTree::load(&conn, &user_id, "untitled folder").unwrap();
|
|
|
|
let (file_node, register_sql) = FileTree::new_file_node(
|
|
"test_api.mp4",
|
|
"api_test_uuid",
|
|
None,
|
|
"test_api.mp4",
|
|
Some(1024),
|
|
Some("video/mp4"),
|
|
None,
|
|
None,
|
|
);
|
|
|
|
if let Some(sql) = register_sql {
|
|
conn.execute_batch(&sql).unwrap();
|
|
}
|
|
|
|
tree.insert_node(&conn, &file_node).unwrap();
|
|
|
|
let loaded = FileTree::load(&conn, &user_id, "untitled folder").unwrap();
|
|
assert_eq!(loaded.nodes.len(), 1);
|
|
assert_eq!(loaded.nodes[0].node_type, NodeType::File);
|
|
}
|
|
|
|
#[test]
|
|
fn test_api_logic_get_tree_with_mode() {
|
|
let (conn, user_id) = temp_db();
|
|
let mut tree = FileTree::load(&conn, &user_id, "untitled folder").unwrap();
|
|
|
|
let folder = FileTree::new_folder("Root", None);
|
|
tree.insert_node(&conn, &folder).unwrap();
|
|
|
|
//測試不同顯示模式
|
|
let tree_mode = mode::get_mode("tree").unwrap();
|
|
let tree_rendered = tree_mode.render(&tree);
|
|
assert!(tree_rendered["nodes"].is_array());
|
|
|
|
let list_mode = mode::get_mode("list").unwrap();
|
|
let list_rendered = list_mode.render(&tree);
|
|
assert!(list_rendered["nodes"].is_array());
|
|
|
|
let grid_sm_mode = mode::get_mode("grid_sm").unwrap();
|
|
let grid_sm_rendered = grid_sm_mode.render(&tree);
|
|
assert!(grid_sm_rendered["nodes"].is_array());
|
|
}
|
|
|
|
#[test]
|
|
fn test_api_logic_update_node() {
|
|
let (conn, user_id) = temp_db();
|
|
let mut tree = FileTree::load(&conn, &user_id, "untitled folder").unwrap();
|
|
|
|
let mut folder = FileTree::new_folder("Original", None);
|
|
tree.insert_node(&conn, &folder).unwrap();
|
|
|
|
folder.label = "Updated_via_API".to_string();
|
|
folder.icon = Some("🎬".to_string());
|
|
tree.update_node(&conn, &folder.node_id, &folder).unwrap();
|
|
|
|
let loaded = FileTree::load(&conn, &user_id, "untitled folder").unwrap();
|
|
assert_eq!(loaded.nodes[0].label, "Updated_via_API");
|
|
assert_eq!(loaded.nodes[0].icon, Some("🎬".to_string()));
|
|
}
|
|
|
|
#[test]
|
|
fn test_api_logic_delete_node() {
|
|
let (conn, user_id) = temp_db();
|
|
let mut tree = FileTree::load(&conn, &user_id, "untitled folder").unwrap();
|
|
|
|
let folder = FileTree::new_folder("ToDelete", None);
|
|
let node_id = folder.node_id.clone();
|
|
tree.insert_node(&conn, &folder).unwrap();
|
|
|
|
assert_eq!(tree.nodes.len(), 1);
|
|
|
|
tree.delete_node(&conn, &node_id).unwrap();
|
|
|
|
let loaded = FileTree::load(&conn, &user_id, "untitled folder").unwrap();
|
|
assert_eq!(loaded.nodes.len(), 0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_api_logic_delete_all_nodes() {
|
|
let (conn, user_id) = temp_db();
|
|
let mut tree = FileTree::load(&conn, &user_id, "untitled folder").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, "untitled folder").unwrap();
|
|
assert_eq!(loaded.nodes.len(), 5);
|
|
|
|
//模擬delete_all_nodes API邏輯
|
|
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, "untitled folder").unwrap();
|
|
assert_eq!(after_delete.nodes.len(), 0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_api_logic_move_node() {
|
|
let (conn, user_id) = temp_db();
|
|
let mut tree = FileTree::load(&conn, &user_id, "untitled folder").unwrap();
|
|
|
|
let parent = FileTree::new_folder("Parent", None);
|
|
let child = FileTree::new_folder("Child", Some(parent.node_id.clone()));
|
|
|
|
tree.insert_node(&conn, &parent).unwrap();
|
|
tree.insert_node(&conn, &child).unwrap();
|
|
|
|
//移動到根目錄
|
|
tree.move_node(&conn, &child.node_id, None).unwrap();
|
|
|
|
let loaded = FileTree::load(&conn, &user_id, "untitled folder").unwrap();
|
|
let moved_node = loaded
|
|
.nodes
|
|
.iter()
|
|
.find(|n| n.node_id == child.node_id)
|
|
.unwrap();
|
|
assert!(moved_node.parent_id.is_none());
|
|
}
|
|
|
|
#[test]
|
|
fn test_api_logic_update_alias() {
|
|
let (conn, user_id) = temp_db();
|
|
let mut tree = FileTree::load(&conn, &user_id, "untitled folder").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();
|
|
|
|
let loaded = FileTree::load(&conn, &user_id, "untitled folder").unwrap();
|
|
assert_eq!(
|
|
loaded.nodes[0].aliases.get("zh_tw").map(|s| s.as_str()),
|
|
Some("影片")
|
|
);
|
|
assert_eq!(
|
|
loaded.nodes[0].aliases.get("en_us").map(|s| s.as_str()),
|
|
Some("Videos")
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_api_logic_nested_structure() {
|
|
let (conn, user_id) = temp_db();
|
|
let mut tree = FileTree::load(&conn, &user_id, "untitled folder").unwrap();
|
|
|
|
let root = FileTree::new_folder("Root", None);
|
|
let level1 = FileTree::new_folder("Level1", Some(root.node_id.clone()));
|
|
let level2 = FileTree::new_folder("Level2", Some(level1.node_id.clone()));
|
|
|
|
tree.insert_node(&conn, &root).unwrap();
|
|
tree.insert_node(&conn, &level1).unwrap();
|
|
tree.insert_node(&conn, &level2).unwrap();
|
|
|
|
let loaded = FileTree::load(&conn, &user_id, "untitled folder").unwrap();
|
|
assert_eq!(loaded.nodes.len(), 3);
|
|
}
|
|
|
|
#[test]
|
|
fn test_api_logic_get_modes() {
|
|
let modes = mode::list_modes();
|
|
|
|
assert_eq!(modes.len(), 4);
|
|
|
|
let names: Vec<&str> = modes.iter().map(|m| m.name()).collect();
|
|
assert!(names.contains(&"tree"));
|
|
assert!(names.contains(&"list"));
|
|
assert!(names.contains(&"grid_sm"));
|
|
assert!(names.contains(&"grid_lg"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_api_logic_file_info() {
|
|
let (conn, _user_id) = temp_db();
|
|
|
|
let file_uuid = "test_file_uuid_123";
|
|
FileTree::add_location(&conn, file_uuid, "/path/to/file.mp4", Some("origin")).unwrap();
|
|
|
|
let location: String = conn
|
|
.query_row(
|
|
"SELECT location FROM file_locations WHERE file_uuid = ?1",
|
|
[file_uuid],
|
|
|row| row.get(0),
|
|
)
|
|
.unwrap();
|
|
|
|
assert_eq!(location, "/path/to/file.mp4");
|
|
}
|
|
|
|
#[test]
|
|
fn test_api_logic_restore_scenario() {
|
|
//模擬restore_tree API邏輯
|
|
let (conn, user_id) = temp_db();
|
|
let mut tree = FileTree::load(&conn, &user_id, "untitled folder").unwrap();
|
|
|
|
//建立基本結構
|
|
let home = FileTree::new_folder("Home", None);
|
|
let movies = FileTree::new_folder("Movies", Some(home.node_id.clone()));
|
|
|
|
tree.insert_node(&conn, &home).unwrap();
|
|
tree.insert_node(&conn, &movies).unwrap();
|
|
|
|
let loaded = FileTree::load(&conn, &user_id, "untitled folder").unwrap();
|
|
assert!(loaded.nodes.iter().any(|n| n.label == "Home"));
|
|
assert!(loaded.nodes.iter().any(|n| n.label == "Movies"));
|
|
}
|