mod common;
use std::time::Duration;
use tokio::time::timeout;
use outrig::config::Config;
use outrig_cli::init::run_with;
use common::{StubHfTreeFetcher, scripted_prompt};
const TEST_TIMEOUT: Duration = Duration::from_secs(10);
const ALL_DEFAULTS: &[u8] = b"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
#[tokio::test]
async fn fresh_state_writes_global_repo_and_container() {
let tmp = tempfile::tempdir().unwrap();
let cwd = tmp.path().join("repo");
std::fs::create_dir_all(&cwd).unwrap();
let global = tmp.path().join("global.toml");
let (mut prompt, _stderr_r) = scripted_prompt(ALL_DEFAULTS).await;
let mut hf = StubHfTreeFetcher::with_files(Vec::<&str>::new());
timeout(
TEST_TIMEOUT,
run_with(false, Some(&global), &cwd, &mut prompt, &mut hf),
)
.await
.expect("init must not hang")
.expect("init must succeed");
assert!(global.is_file(), "global config not written");
let global_text = std::fs::read_to_string(&global).unwrap();
Config::load_from_str(&global_text)
.unwrap()
.validate(None)
.unwrap();
let repo_cfg_path = cwd.join(".agents/outrig/config.toml");
assert!(repo_cfg_path.is_file(), "repo config not written");
let dockerfile = cwd.join(".agents/outrig/images/repo-standard/Dockerfile");
assert!(dockerfile.is_file(), "container Dockerfile not written");
let merged = Config::load(&cwd, Some(&global)).expect("merged config must load");
assert_eq!(merged.default_image.as_deref(), Some("repo-standard"));
assert_eq!(merged.default_agent.as_deref(), Some("coder"));
assert_eq!(merged.default_model.as_deref(), Some("fast"));
let repo_text = std::fs::read_to_string(&repo_cfg_path).unwrap();
assert!(repo_text.contains("[agents.coder]"), "{repo_text}");
assert!(repo_text.contains("[workspace]"), "{repo_text}");
assert!(repo_text.contains("[images.repo-standard]"), "{repo_text}");
}
#[tokio::test]
async fn idempotent_rerun_leaves_files_untouched() {
let tmp = tempfile::tempdir().unwrap();
let cwd = tmp.path().join("repo");
std::fs::create_dir_all(&cwd).unwrap();
let global = tmp.path().join("global.toml");
let (mut prompt, _stderr_r) = scripted_prompt(ALL_DEFAULTS).await;
let mut hf = StubHfTreeFetcher::with_files(Vec::<&str>::new());
timeout(
TEST_TIMEOUT,
run_with(false, Some(&global), &cwd, &mut prompt, &mut hf),
)
.await
.expect("seed init must not hang")
.expect("seed init must succeed");
let global_before = std::fs::read_to_string(&global).unwrap();
let repo_cfg_path = cwd.join(".agents/outrig/config.toml");
let repo_before = std::fs::read_to_string(&repo_cfg_path).unwrap();
let dockerfile_path = cwd.join(".agents/outrig/images/repo-standard/Dockerfile");
let dockerfile_before = std::fs::read_to_string(&dockerfile_path).unwrap();
let (mut prompt, _stderr_r) = scripted_prompt(b"n\n").await;
let mut hf = StubHfTreeFetcher::with_files(Vec::<&str>::new());
timeout(
TEST_TIMEOUT,
run_with(false, Some(&global), &cwd, &mut prompt, &mut hf),
)
.await
.expect("re-run must not hang")
.expect("re-run must succeed");
assert_eq!(
std::fs::read_to_string(&global).unwrap(),
global_before,
"global config rewritten"
);
assert_eq!(
std::fs::read_to_string(&repo_cfg_path).unwrap(),
repo_before,
"repo config rewritten"
);
assert_eq!(
std::fs::read_to_string(&dockerfile_path).unwrap(),
dockerfile_before,
"Dockerfile rewritten"
);
}
#[tokio::test]
async fn skips_global_phase_when_global_exists() {
let tmp = tempfile::tempdir().unwrap();
let cwd = tmp.path().join("repo");
std::fs::create_dir_all(&cwd).unwrap();
let global = tmp.path().join("global.toml");
let pre_global = "default-model = \"fast\"\n\
\n\
[providers.openai]\n\
style = \"openai\"\n\
base-url = \"https://api.openai.com/v1\"\n\
api-key = \"${OPENAI_API_KEY}\"\n\
\n\
[models.fast]\n\
provider = \"openai\"\n\
identifier = \"gpt-4o-mini\"\n";
std::fs::write(&global, pre_global).unwrap();
let script = b"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
let (mut prompt, _stderr_r) = scripted_prompt(script).await;
let mut hf = StubHfTreeFetcher::with_files(Vec::<&str>::new());
timeout(
TEST_TIMEOUT,
run_with(false, Some(&global), &cwd, &mut prompt, &mut hf),
)
.await
.expect("init must not hang")
.expect("init must succeed");
assert_eq!(
std::fs::read_to_string(&global).unwrap(),
pre_global,
"existing global was rewritten",
);
assert!(cwd.join(".agents/outrig/config.toml").is_file());
assert!(
cwd.join(".agents/outrig/images/repo-standard/Dockerfile")
.is_file()
);
let _merged: Config = Config::load(&cwd, Some(&global)).expect("merged config must load");
}