story-kit: merge 125_story_test_coverage_http_io_rs

This commit is contained in:
Dave
2026-02-24 00:03:47 +00:00
parent 45840ad6e2
commit 26e2164833

View File

@@ -128,3 +128,221 @@ impl IoApi {
Ok(Json(output)) Ok(Json(output))
} }
} }
#[cfg(test)]
mod tests {
use super::*;
use crate::http::context::AppContext;
use tempfile::TempDir;
fn make_api(dir: &TempDir) -> IoApi {
IoApi {
ctx: Arc::new(AppContext::new_test(dir.path().to_path_buf())),
}
}
// --- list_directory_absolute ---
#[tokio::test]
async fn list_directory_absolute_returns_entries_for_valid_path() {
let dir = TempDir::new().unwrap();
std::fs::create_dir(dir.path().join("subdir")).unwrap();
std::fs::write(dir.path().join("file.txt"), "content").unwrap();
let api = make_api(&dir);
let payload = Json(FilePathPayload {
path: dir.path().to_string_lossy().to_string(),
});
let result = api.list_directory_absolute(payload).await.unwrap();
let entries = &result.0;
assert!(entries.len() >= 2);
assert!(entries.iter().any(|e| e.name == "subdir" && e.kind == "dir"));
assert!(entries.iter().any(|e| e.name == "file.txt" && e.kind == "file"));
}
#[tokio::test]
async fn list_directory_absolute_returns_empty_for_empty_dir() {
let dir = TempDir::new().unwrap();
let empty = dir.path().join("empty");
std::fs::create_dir(&empty).unwrap();
let api = make_api(&dir);
let payload = Json(FilePathPayload {
path: empty.to_string_lossy().to_string(),
});
let result = api.list_directory_absolute(payload).await.unwrap();
assert!(result.0.is_empty());
}
#[tokio::test]
async fn list_directory_absolute_errors_on_nonexistent_path() {
let dir = TempDir::new().unwrap();
let api = make_api(&dir);
let payload = Json(FilePathPayload {
path: dir.path().join("nonexistent").to_string_lossy().to_string(),
});
let result = api.list_directory_absolute(payload).await;
assert!(result.is_err());
}
#[tokio::test]
async fn list_directory_absolute_errors_on_file_path() {
let dir = TempDir::new().unwrap();
let file = dir.path().join("not_a_dir.txt");
std::fs::write(&file, "content").unwrap();
let api = make_api(&dir);
let payload = Json(FilePathPayload {
path: file.to_string_lossy().to_string(),
});
let result = api.list_directory_absolute(payload).await;
assert!(result.is_err());
}
// --- create_directory_absolute ---
#[tokio::test]
async fn create_directory_absolute_creates_new_dir() {
let dir = TempDir::new().unwrap();
let new_dir = dir.path().join("new_dir");
let api = make_api(&dir);
let payload = Json(CreateDirectoryPayload {
path: new_dir.to_string_lossy().to_string(),
});
let result = api.create_directory_absolute(payload).await.unwrap();
assert!(result.0);
assert!(new_dir.is_dir());
}
#[tokio::test]
async fn create_directory_absolute_succeeds_for_existing_dir() {
let dir = TempDir::new().unwrap();
let existing = dir.path().join("existing");
std::fs::create_dir(&existing).unwrap();
let api = make_api(&dir);
let payload = Json(CreateDirectoryPayload {
path: existing.to_string_lossy().to_string(),
});
let result = api.create_directory_absolute(payload).await.unwrap();
assert!(result.0);
}
#[tokio::test]
async fn create_directory_absolute_creates_nested_dirs() {
let dir = TempDir::new().unwrap();
let nested = dir.path().join("a").join("b").join("c");
let api = make_api(&dir);
let payload = Json(CreateDirectoryPayload {
path: nested.to_string_lossy().to_string(),
});
let result = api.create_directory_absolute(payload).await.unwrap();
assert!(result.0);
assert!(nested.is_dir());
}
// --- get_home_directory ---
#[tokio::test]
async fn get_home_directory_returns_a_path() {
let dir = TempDir::new().unwrap();
let api = make_api(&dir);
let result = api.get_home_directory().await.unwrap();
let home = &result.0;
assert!(!home.is_empty());
assert!(std::path::Path::new(home).is_absolute());
}
// --- read_file (project-scoped) ---
#[tokio::test]
async fn read_file_returns_content() {
let dir = TempDir::new().unwrap();
std::fs::write(dir.path().join("hello.txt"), "hello world").unwrap();
let api = make_api(&dir);
let payload = Json(FilePathPayload {
path: "hello.txt".to_string(),
});
let result = api.read_file(payload).await.unwrap();
assert_eq!(result.0, "hello world");
}
#[tokio::test]
async fn read_file_errors_on_missing_file() {
let dir = TempDir::new().unwrap();
let api = make_api(&dir);
let payload = Json(FilePathPayload {
path: "nonexistent.txt".to_string(),
});
let result = api.read_file(payload).await;
assert!(result.is_err());
}
// --- write_file (project-scoped) ---
#[tokio::test]
async fn write_file_creates_file() {
let dir = TempDir::new().unwrap();
let api = make_api(&dir);
let payload = Json(WriteFilePayload {
path: "output.txt".to_string(),
content: "written content".to_string(),
});
let result = api.write_file(payload).await.unwrap();
assert!(result.0);
assert_eq!(
std::fs::read_to_string(dir.path().join("output.txt")).unwrap(),
"written content"
);
}
#[tokio::test]
async fn write_file_creates_parent_dirs() {
let dir = TempDir::new().unwrap();
let api = make_api(&dir);
let payload = Json(WriteFilePayload {
path: "sub/dir/file.txt".to_string(),
content: "nested".to_string(),
});
let result = api.write_file(payload).await.unwrap();
assert!(result.0);
assert_eq!(
std::fs::read_to_string(dir.path().join("sub/dir/file.txt")).unwrap(),
"nested"
);
}
// --- list_directory (project-scoped) ---
#[tokio::test]
async fn list_directory_returns_entries() {
let dir = TempDir::new().unwrap();
std::fs::create_dir(dir.path().join("adir")).unwrap();
std::fs::write(dir.path().join("bfile.txt"), "").unwrap();
let api = make_api(&dir);
let payload = Json(FilePathPayload {
path: ".".to_string(),
});
let result = api.list_directory(payload).await.unwrap();
let entries = &result.0;
assert!(entries.iter().any(|e| e.name == "adir" && e.kind == "dir"));
assert!(entries.iter().any(|e| e.name == "bfile.txt" && e.kind == "file"));
}
#[tokio::test]
async fn list_directory_errors_on_nonexistent() {
let dir = TempDir::new().unwrap();
let api = make_api(&dir);
let payload = Json(FilePathPayload {
path: "nonexistent_dir".to_string(),
});
let result = api.list_directory(payload).await;
assert!(result.is_err());
}
}