use std::fs;
use std::process::Command;
use track::db::Database;
use track::services::{TaskService, TodoService, WorktreeService};
fn init_jj_repo(path: &str) {
Command::new("jj")
.args(["git", "init", path])
.output()
.unwrap();
}
fn describe_change(path: &str, message: &str) {
Command::new("jj")
.args(["-R", path, "describe", "-m", message])
.output()
.unwrap();
}
fn new_change(path: &str) {
Command::new("jj")
.args(["-R", path, "new"])
.output()
.unwrap();
}
#[test]
fn test_complete_worktree_for_todo_full_workflow() {
let db = Database::new_in_memory().unwrap();
let task_service = TaskService::new(&db);
let todo_service = TodoService::new(&db);
let worktree_service = WorktreeService::new(&db);
let task = task_service
.create_task("Task", None, Some("WT-100"), None)
.unwrap();
let todo = todo_service.add_todo(task.id, "Todo WT", true).unwrap();
let temp_dir = tempfile::tempdir().unwrap();
let repo_path = temp_dir.path().to_str().unwrap();
init_jj_repo(repo_path);
fs::write(temp_dir.path().join("README.md"), "init").unwrap();
describe_change(repo_path, "init");
new_change(repo_path);
let base_wt = worktree_service
.add_worktree(task.id, repo_path, None, Some("WT-100"), None, true)
.unwrap();
let todo_wt = worktree_service
.add_worktree(
task.id,
repo_path,
None,
Some("WT-100"),
Some(todo.id),
false,
)
.unwrap();
fs::write(
std::path::Path::new(&todo_wt.path).join("feature.txt"),
"new feature",
)
.unwrap();
describe_change(&todo_wt.path, "add feature");
new_change(&todo_wt.path);
let branch_name = worktree_service
.complete_worktree_for_todo(todo.id)
.unwrap();
assert!(branch_name.is_some());
assert_eq!(branch_name.unwrap(), todo_wt.branch);
let worktrees = worktree_service.list_worktrees(task.id).unwrap();
assert_eq!(worktrees.len(), 1); assert!(worktrees[0].is_base);
assert!(std::path::Path::new(&base_wt.path)
.join("feature.txt")
.exists());
}
#[test]
fn test_complete_worktree_with_uncommitted_changes() {
let db = Database::new_in_memory().unwrap();
let task_service = TaskService::new(&db);
let todo_service = TodoService::new(&db);
let worktree_service = WorktreeService::new(&db);
let task = task_service
.create_task("Task", None, Some("WT-101"), None)
.unwrap();
let todo = todo_service.add_todo(task.id, "Todo WT", true).unwrap();
let temp_dir = tempfile::tempdir().unwrap();
let repo_path = temp_dir.path().to_str().unwrap();
init_jj_repo(repo_path);
fs::write(temp_dir.path().join("README.md"), "init").unwrap();
describe_change(repo_path, "init");
new_change(repo_path);
worktree_service
.add_worktree(task.id, repo_path, None, Some("WT-101"), None, true)
.unwrap();
let todo_wt = worktree_service
.add_worktree(
task.id,
repo_path,
None,
Some("WT-101"),
Some(todo.id),
false,
)
.unwrap();
fs::write(
std::path::Path::new(&todo_wt.path).join("dirty.txt"),
"uncommitted",
)
.unwrap();
let result = worktree_service.complete_worktree_for_todo(todo.id);
assert!(result.is_err());
let worktrees = worktree_service.list_worktrees(task.id).unwrap();
assert_eq!(worktrees.len(), 2);
}
#[test]
fn test_complete_worktree_no_worktree() {
let db = Database::new_in_memory().unwrap();
let task_service = TaskService::new(&db);
let todo_service = TodoService::new(&db);
let worktree_service = WorktreeService::new(&db);
let task = task_service.create_task("Task", None, None, None).unwrap();
let todo = todo_service.add_todo(task.id, "Todo No WT", false).unwrap();
let result = worktree_service
.complete_worktree_for_todo(todo.id)
.unwrap();
assert!(result.is_none());
}
#[test]
fn test_remove_git_worktree_actually_removes() {
let db = Database::new_in_memory().unwrap();
let task_service = TaskService::new(&db);
let worktree_service = WorktreeService::new(&db);
let task = task_service
.create_task("Task", None, Some("RM-100"), None)
.unwrap();
let temp_dir = tempfile::tempdir().unwrap();
let repo_path = temp_dir.path().to_str().unwrap();
init_jj_repo(repo_path);
fs::write(temp_dir.path().join("README.md"), "init").unwrap();
describe_change(repo_path, "init");
new_change(repo_path);
let wt = worktree_service
.add_worktree(task.id, repo_path, None, Some("RM-100"), None, true)
.unwrap();
assert!(std::path::Path::new(&wt.path).exists());
worktree_service.remove_worktree(wt.id, false).unwrap();
assert!(!std::path::Path::new(&wt.path).exists());
}