#![allow(deprecated)]
use tempfile::TempDir;
use tree_type::tree_type;
tree_type! {
RequiredParentTest {
#[required]
projects/ as ProjectsDir {
[project: String]/ as ProjectDir {
#[required]
tasks/ as TasksDir {
#[required]
active/,
#[required]
backlog/ {
p1/ {},
p2/ {}
},
#[required]
completed/
},
#[optional]
implementation/ {}
}
}
}
}
#[test]
fn test_required_parent_created_during_setup() {
let temp_dir = TempDir::new().unwrap();
let root = RequiredParentTest::new(temp_dir.path()).unwrap();
let result = root.sync();
assert!(result.is_ok(), "Sync should succeed: {:?}", result);
assert!(
root.projects().as_path().exists(),
"projects/ should be created"
);
let project_dir = root.projects().as_path().join("test-project");
assert!(
!project_dir.exists(),
"Dynamic project dir should not be created without default"
);
}
#[test]
fn test_required_parent_validated() {
let temp_dir = TempDir::new().unwrap();
let root = RequiredParentTest::new(temp_dir.path()).unwrap();
let report = root.validate();
assert!(
!report.errors.is_empty(),
"Validation should fail without setup"
);
let has_projects_error = report.errors.iter().any(|e| {
e.path == root.projects().as_path() && e.message.contains("Required path does not exist")
});
assert!(
has_projects_error,
"Should have error for missing projects/ directory"
);
}
#[test]
fn test_required_nested_parent_validated() {
let temp_dir = TempDir::new().unwrap();
let root = RequiredParentTest::new(temp_dir.path()).unwrap();
std::fs::create_dir_all(root.projects().as_path()).unwrap();
let project_path = root.projects().as_path().join("test-project");
std::fs::create_dir_all(&project_path).unwrap();
let report = root.validate();
assert!(
!report.errors.is_empty(),
"Validation should fail without tasks/ directory"
);
let tasks_path = project_path.join("tasks");
let has_tasks_error = report
.errors
.iter()
.any(|e| e.path == tasks_path && e.message.contains("Required path does not exist"));
assert!(
has_tasks_error,
"Should have error for missing tasks/ directory: {:?}",
report.errors
);
}
#[test]
fn test_optional_parent_not_required() {
let temp_dir = TempDir::new().unwrap();
let root = RequiredParentTest::new(temp_dir.path()).unwrap();
std::fs::create_dir_all(root.projects().as_path()).unwrap();
let project_path = root.projects().as_path().join("test-project");
std::fs::create_dir_all(&project_path).unwrap();
std::fs::create_dir_all(project_path.join("tasks")).unwrap();
std::fs::create_dir_all(project_path.join("tasks/active")).unwrap();
std::fs::create_dir_all(project_path.join("tasks/backlog")).unwrap();
std::fs::create_dir_all(project_path.join("tasks/completed")).unwrap();
let report = root.validate();
assert!(
report.errors.is_empty(),
"Validation should pass without optional implementation/: {:?}",
report.errors
);
}
#[test]
fn test_required_parent_with_children_setup() {
let temp_dir = TempDir::new().unwrap();
let root = RequiredParentTest::new(temp_dir.path()).unwrap();
root.sync().unwrap();
assert!(
root.projects().as_path().exists(),
"projects/ should exist after setup"
);
let project_path = root.projects().as_path().join("test-project");
std::fs::create_dir_all(&project_path).unwrap();
let project = root.projects().project("test-project");
project.tasks().sync().unwrap();
assert!(project.tasks().as_path().exists(), "tasks/ should exist");
assert!(
project.tasks().active().as_path().exists(),
"tasks/active/ should exist"
);
assert!(
project.tasks().backlog().as_path().exists(),
"tasks/backlog/ should exist"
);
assert!(
project.tasks().completed().as_path().exists(),
"tasks/completed/ should exist"
);
assert!(
!project.implementation().as_path().exists(),
"implementation/ should not be created (optional)"
);
}