Files
fermata/tests/core_project.rs
T
g4borg fd2482e3e6 fix(fermata): .botignore no longer stops project-root walk-up
Only .git, botignore.toml, and .botignore.toml define project boundaries.
A bare .botignore is a policy file, not a root marker.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-08 23:30:30 +02:00

103 lines
3.0 KiB
Rust

use dirigent_fermata::core::project::find_project_root;
use std::fs;
use tempfile::TempDir;
#[test]
fn finds_botignore_toml_first() {
let tmp = TempDir::new().unwrap();
let root = tmp.path();
fs::create_dir_all(root.join("sub/deep")).unwrap();
fs::write(root.join("botignore.toml"), "").unwrap();
fs::write(root.join(".botignore.toml"), "").unwrap();
fs::create_dir_all(root.join(".git")).unwrap();
let target = root.join("sub/deep/file.rs");
fs::write(&target, "").unwrap();
let found = find_project_root(&target).unwrap();
assert_eq!(found, root);
}
#[test]
fn finds_dot_botignore_toml() {
let tmp = TempDir::new().unwrap();
let root = tmp.path();
fs::create_dir_all(root.join("sub")).unwrap();
fs::write(root.join(".botignore.toml"), "").unwrap();
let target = root.join("sub/file.rs");
fs::write(&target, "").unwrap();
let found = find_project_root(&target).unwrap();
assert_eq!(found, root);
}
#[test]
fn botignore_alone_does_not_stop_walk() {
// A bare .botignore is a policy file, not a project boundary.
// The walk should continue past it to find a real root marker.
let tmp = TempDir::new().unwrap();
let root = tmp.path();
fs::create_dir_all(root.join("a/b")).unwrap();
fs::create_dir_all(root.join(".git")).unwrap();
fs::write(root.join("a/.botignore"), "*.secret").unwrap();
let target = root.join("a/b/file.rs");
fs::write(&target, "").unwrap();
// Should find root (with .git), NOT root/a (with .botignore)
let found = find_project_root(&target).unwrap();
assert_eq!(found, root);
}
#[test]
fn botignore_only_returns_none() {
// If only .botignore exists with no real root marker, no project root is found.
let tmp = TempDir::new().unwrap();
let root = tmp.path();
fs::create_dir_all(root.join("sub")).unwrap();
fs::write(root.join(".botignore"), "").unwrap();
let target = root.join("sub/file.rs");
fs::write(&target, "").unwrap();
// .botignore alone should NOT define a project root
assert!(find_project_root(&target).is_none());
}
#[test]
fn falls_back_to_git() {
let tmp = TempDir::new().unwrap();
let root = tmp.path();
fs::create_dir_all(root.join("sub")).unwrap();
fs::create_dir_all(root.join(".git")).unwrap();
let target = root.join("sub/file.rs");
fs::write(&target, "").unwrap();
let found = find_project_root(&target).unwrap();
assert_eq!(found, root);
}
#[test]
fn returns_none_when_no_marker() {
let tmp = TempDir::new().unwrap();
let target = tmp.path().join("file.rs");
std::fs::write(&target, "").unwrap();
assert!(find_project_root(&target).is_none());
}
#[test]
fn walks_up_from_file_path_not_cwd() {
let tmp = TempDir::new().unwrap();
let root = tmp.path();
fs::create_dir_all(root.join("a/b/c")).unwrap();
fs::write(root.join("a/botignore.toml"), "").unwrap();
let target = root.join("a/b/c/file.rs");
fs::write(&target, "").unwrap();
let found = find_project_root(&target).unwrap();
assert_eq!(found, root.join("a"));
}