feat: 工作目录支持页面内目录浏览器
This commit is contained in:
@@ -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()
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user