mod support;
use std::fs;
use std::path::Path;
use loopflow::engine::{load_config, load_config_or_default, LaunchTarget};
use support::with_clean_home;
use tempfile::TempDir;
fn write_config(dir: &Path, content: &str) {
let lf_dir = dir.join(".lf");
fs::create_dir_all(&lf_dir).unwrap();
fs::write(lf_dir.join("config.yaml"), content).unwrap();
}
#[test]
fn load_config_or_default_handles_missing_file() {
let temp = TempDir::new().unwrap();
let config = with_clean_home(|| load_config_or_default(Some(temp.path())));
assert!(config.agent.is_none());
}
#[test]
fn load_config_or_default_handles_empty_file() {
let temp = TempDir::new().unwrap();
write_config(temp.path(), "");
let config = with_clean_home(|| load_config_or_default(Some(temp.path())));
assert!(config.agent.is_none());
}
#[test]
fn load_config_or_default_handles_whitespace_only() {
let temp = TempDir::new().unwrap();
write_config(temp.path(), " \n\n ");
let config = with_clean_home(|| load_config_or_default(Some(temp.path())));
assert!(config.agent.is_none());
}
#[test]
fn load_config_parses_basic_yaml() {
let temp = TempDir::new().unwrap();
write_config(
temp.path(),
r#"
agent: claude:sonnet
yolo: true
"#,
);
let config = with_clean_home(|| load_config(Some(temp.path())))
.expect("config should load")
.expect("config should exist");
assert_eq!(config.agent.as_deref(), Some("claude:sonnet"));
assert!(config.yolo);
}
#[test]
fn load_config_or_default_returns_defaults() {
let temp = TempDir::new().unwrap();
let config = with_clean_home(|| load_config_or_default(Some(temp.path())));
assert!(config.agent.is_none());
assert!(!config.yolo);
assert!(!config.chrome);
}
#[test]
fn config_model_with_variant() {
let temp = TempDir::new().unwrap();
write_config(temp.path(), "agent: gemini:2.5-pro");
let config = with_clean_home(|| load_config(Some(temp.path())))
.unwrap()
.unwrap();
assert_eq!(config.agent.as_deref(), Some("gemini:2.5-pro"));
}
#[test]
fn config_model_without_variant() {
let temp = TempDir::new().unwrap();
write_config(temp.path(), "agent: codex");
let config = with_clean_home(|| load_config(Some(temp.path())))
.unwrap()
.unwrap();
assert_eq!(config.agent.as_deref(), Some("codex"));
}
#[test]
fn config_feature_flags() {
let temp = TempDir::new().unwrap();
write_config(
temp.path(),
r#"
yolo: true
chrome: true
pr: true
"#,
);
let config = with_clean_home(|| load_config(Some(temp.path())))
.unwrap()
.unwrap();
assert!(config.yolo);
assert!(config.chrome);
assert!(config.pr);
}
#[test]
fn config_context_as_list() {
let temp = TempDir::new().unwrap();
write_config(
temp.path(),
r#"
context:
- src/
- lib/
"#,
);
let config = with_clean_home(|| load_config(Some(temp.path())))
.unwrap()
.unwrap();
assert_eq!(config.context, vec!["src/", "lib/"]);
}
#[test]
fn config_exclude_as_list() {
let temp = TempDir::new().unwrap();
write_config(
temp.path(),
r#"
exclude:
- "*.log"
- node_modules/
"#,
);
let config = with_clean_home(|| load_config(Some(temp.path())))
.unwrap()
.unwrap();
assert_eq!(config.exclude, vec!["*.log", "node_modules/"]);
}
#[test]
fn config_direction_as_list() {
let temp = TempDir::new().unwrap();
write_config(
temp.path(),
r#"
direction:
- concise
- security
"#,
);
let config = with_clean_home(|| load_config(Some(temp.path())))
.unwrap()
.unwrap();
assert_eq!(
config.direction,
Some(vec!["concise".to_string(), "security".to_string()])
);
}
#[test]
fn config_direction_single_item_list() {
let temp = TempDir::new().unwrap();
write_config(
temp.path(),
r#"
direction:
- architect
"#,
);
let config = with_clean_home(|| load_config(Some(temp.path())))
.unwrap()
.unwrap();
assert_eq!(config.direction, Some(vec!["architect".to_string()]));
}
#[test]
fn config_session_launch_tui() {
let temp = TempDir::new().unwrap();
write_config(
temp.path(),
r#"
session:
launch: tui
"#,
);
let config = with_clean_home(|| load_config(Some(temp.path())))
.unwrap()
.unwrap();
assert_eq!(config.session.launch, LaunchTarget::Tui);
}
#[test]
fn config_session_launch_ide() {
let temp = TempDir::new().unwrap();
write_config(
temp.path(),
r#"
session:
launch: ide
"#,
);
let config = with_clean_home(|| load_config(Some(temp.path())))
.unwrap()
.unwrap();
assert_eq!(config.session.launch, LaunchTarget::Ide);
}
#[test]
fn config_summaries() {
let temp = TempDir::new().unwrap();
write_config(
temp.path(),
r#"
summaries:
- path: src/
tokens: 500
- path: lib/
tokens: 300
"#,
);
let config = with_clean_home(|| load_config(Some(temp.path())))
.unwrap()
.unwrap();
assert_eq!(config.summaries.len(), 2);
}
#[test]
fn config_land_strategy() {
let temp = TempDir::new().unwrap();
write_config(temp.path(), "land: local");
let config = with_clean_home(|| load_config(Some(temp.path())))
.unwrap()
.unwrap();
assert_eq!(config.land, "local");
}
#[test]
fn config_land_defaults_to_gh() {
let temp = TempDir::new().unwrap();
write_config(temp.path(), "yolo: false");
let config = with_clean_home(|| load_config(Some(temp.path())))
.unwrap()
.unwrap();
assert_eq!(config.land, "gh");
}
#[test]
fn config_autoprune_bool() {
let temp = TempDir::new().unwrap();
write_config(temp.path(), "autoprune: true");
let config = with_clean_home(|| load_config(Some(temp.path())))
.unwrap()
.unwrap();
assert!(config.autoprune.enabled);
}
#[test]
fn config_autoprune_object() {
let temp = TempDir::new().unwrap();
write_config(
temp.path(),
r#"
autoprune:
enabled: true
poll_interval_seconds: 120
"#,
);
let config = with_clean_home(|| load_config(Some(temp.path())))
.unwrap()
.unwrap();
assert!(config.autoprune.enabled);
assert_eq!(config.autoprune.poll_interval_seconds, 120);
}