feat: 工作目录支持页面内目录浏览器

This commit is contained in:
2026-10-24 23:20:20 +08:00
parent dd7612bc74
commit e555610037
15 changed files with 1154 additions and 16 deletions
+84
View File
@@ -1,3 +1,5 @@
use std::fs;
use axum::{
body::Body,
http::{Request, StatusCode},
@@ -71,4 +73,86 @@ async fn openapi_endpoint_describes_health_api() {
assert_eq!(json["info"]["title"], "TaskPilot API");
assert!(json["paths"]["/api/v1/health"]["get"].is_object());
assert!(json["paths"]["/api/v1/system/directories"]["get"].is_object());
}
fn encode_query_path(path: &std::path::Path) -> String {
path.to_string_lossy()
.replace('%', "%25")
.replace(':', "%3A")
.replace('\\', "%5C")
}
async fn get_json(app: &axum::Router, uri: &str) -> (StatusCode, Value) {
let response = app
.clone()
.oneshot(
Request::builder()
.uri(uri)
.body(Body::empty())
.expect("request should build"),
)
.await
.expect("router should respond");
let status = response.status();
let body = response
.into_body()
.collect()
.await
.expect("response body should be readable")
.to_bytes();
(status, serde_json::from_slice(&body).unwrap_or(Value::Null))
}
#[tokio::test]
async fn directory_listing_endpoint_returns_subdirectories() {
let (app, temp_dir) = test_app().await;
let project = temp_dir.path().join("project");
fs::create_dir_all(project.join("nested")).expect("nested directory should be created");
fs::write(project.join("file.txt"), "x").expect("file should be written");
let uri = format!(
"/api/v1/system/directories?path={}",
encode_query_path(&project)
);
let (status, body) = get_json(&app, &uri).await;
assert_eq!(status, StatusCode::OK);
assert_eq!(body["path"], project.to_string_lossy().into_owned());
let entries = body["entries"]
.as_array()
.expect("entries should be an array");
assert_eq!(entries.len(), 1);
assert_eq!(entries[0]["name"], "nested");
assert_eq!(
entries[0]["path"],
project.join("nested").to_string_lossy().into_owned()
);
}
#[tokio::test]
async fn directory_listing_endpoint_rejects_relative_paths() {
let (app, _temp_dir) = test_app().await;
let (status, body) = get_json(&app, "/api/v1/system/directories?path=relative").await;
assert_eq!(status, StatusCode::BAD_REQUEST);
assert_eq!(body["code"], "DIRECTORY_PATH_INVALID");
}
#[tokio::test]
async fn directory_listing_endpoint_returns_drives_without_path() {
let (app, _temp_dir) = test_app().await;
let (status, body) = get_json(&app, "/api/v1/system/directories").await;
assert_eq!(status, StatusCode::OK);
assert!(body["path"].is_null());
assert!(
!body["entries"]
.as_array()
.expect("entries should be an array")
.is_empty()
);
}