use tempfile::TempDir;
use claude_version_core::config_catalog;
use claude_version_core::config_resolve::{ resolve, Layer };
use crate::subprocess_helpers::{ assert_exit, run_clm_with_env };
#[ test ]
fn ac004_float_inference()
{
let dir = TempDir::new().unwrap();
let out = run_clm_with_env(
&[ ".settings.set", "key::pi", "value::3.14" ],
&[ ( "HOME", dir.path().to_str().unwrap() ) ],
);
assert_exit( &out, 0 );
let content = std::fs::read_to_string(
dir.path().join( ".claude/settings.json" )
).unwrap();
assert!( content.contains( "\"pi\": 3.14" ), "3.14 must be stored as bare float: {content}" );
assert!( !content.contains( "\"pi\": \"3.14\"" ), "3.14 must NOT be quoted: {content}" );
}
#[ test ]
fn ac005_nan_stores_string()
{
let dir = TempDir::new().unwrap();
let out = run_clm_with_env(
&[ ".settings.set", "key::bad", "value::nan" ],
&[ ( "HOME", dir.path().to_str().unwrap() ) ],
);
assert_exit( &out, 0 );
let content = std::fs::read_to_string(
dir.path().join( ".claude/settings.json" )
).unwrap();
assert!( content.contains( "\"bad\": \"nan\"" ), "nan must be stored as quoted string: {content}" );
}
#[ test ]
fn ac01_002_env_overrides_user()
{
let home_dir = TempDir::new().unwrap();
let cwd = TempDir::new().unwrap();
crate::subprocess_helpers::write_settings( home_dir.path(), &[ ( "model", "claude-sonnet-4-6" ) ] );
std::env::set_var( "CLAUDE_MODEL", "claude-opus-4-6" );
let r = resolve( "model", home_dir.path(), cwd.path(), config_catalog::catalog() );
assert_eq!( r.source, Layer::Env, "env must beat user config: got {:?}", r.source );
assert_eq!( r.value, Some( "claude-opus-4-6".to_string() ), "wrong value: {:?}", r.value );
}
#[ test ]
fn ac02_002_user_config_wins_without_env()
{
let home_dir = TempDir::new().unwrap();
let cwd = TempDir::new().unwrap();
crate::subprocess_helpers::write_settings( home_dir.path(), &[ ( "model", "claude-haiku-4-5-20251001" ) ] );
std::env::remove_var( "CLAUDE_MODEL" );
let r = resolve( "model", home_dir.path(), cwd.path(), config_catalog::catalog() );
assert_eq!( r.source, Layer::User, "user config must win when env absent: got {:?}", r.source );
assert_eq!( r.value, Some( "claude-haiku-4-5-20251001".to_string() ), "wrong value: {:?}", r.value );
}
#[ test ]
fn ac03_002_project_config_key()
{
let home_dir = TempDir::new().unwrap();
let cwd = TempDir::new().unwrap();
crate::subprocess_helpers::write_settings( cwd.path(), &[ ( "model", "claude-opus-4-6" ) ] );
std::env::remove_var( "CLAUDE_MODEL" );
let r = resolve( "model", home_dir.path(), cwd.path(), config_catalog::catalog() );
assert_eq!( r.source, Layer::Project, "project config must supply value: got {:?}", r.source );
assert_eq!( r.value, Some( "claude-opus-4-6".to_string() ), "wrong value: {:?}", r.value );
}
#[ test ]
fn ac04_002_catalog_default_returned()
{
let home_dir = TempDir::new().unwrap();
let cwd = TempDir::new().unwrap();
std::env::remove_var( "CLAUDE_MODEL" );
let r = resolve( "model", home_dir.path(), cwd.path(), config_catalog::catalog() );
assert_eq!( r.source, Layer::Default, "catalog default must be returned: got {:?}", r.source );
assert_eq!( r.value, Some( "claude-sonnet-4-6".to_string() ), "wrong default value: {:?}", r.value );
}
#[ test ]
fn ac05_002_all_layers_absent()
{
let home_dir = TempDir::new().unwrap();
let cwd = TempDir::new().unwrap();
let r = resolve( "myArbitraryKey", home_dir.path(), cwd.path(), config_catalog::catalog() );
assert_eq!( r.source, Layer::Absent, "absent key must return Absent: got {:?}", r.source );
assert_eq!( r.value, None, "absent key must return None value: {:?}", r.value );
}
#[ test ]
fn ac06_002_project_overrides_user()
{
let home_dir = TempDir::new().unwrap();
let cwd = TempDir::new().unwrap();
crate::subprocess_helpers::write_settings( cwd.path(), &[ ( "theme", "dark" ) ] );
crate::subprocess_helpers::write_settings( home_dir.path(), &[ ( "theme", "light" ) ] );
let r = resolve( "theme", home_dir.path(), cwd.path(), config_catalog::catalog() );
assert_eq!( r.source, Layer::Project, "project must beat user for same key: got {:?}", r.source );
assert_eq!( r.value, Some( "dark".to_string() ), "wrong value: {:?}", r.value );
}
#[ test ]
fn ac07_002_home_unset_skips_user_config()
{
let home_dir = TempDir::new().unwrap();
let cwd = TempDir::new().unwrap();
std::env::remove_var( "CLAUDE_MODEL" );
let r = resolve( "theme", home_dir.path(), cwd.path(), config_catalog::catalog() );
assert_eq!( r.source, Layer::Default, "absent user config must fall through to Default: got {:?}", r.source );
assert_eq!( r.value, Some( "system".to_string() ), "catalog default for 'theme' must be \"system\": {:?}", r.value );
}
#[ test ]
fn ac08_002_ancestor_project_config_found()
{
let parent = TempDir::new().unwrap();
let home_dir = TempDir::new().unwrap();
crate::subprocess_helpers::write_settings( parent.path(), &[ ( "preferredVersionSpec", "beta" ) ] );
let child = parent.path().join( "subdir" );
std::fs::create_dir_all( &child ).unwrap();
std::env::remove_var( "CLAUDE_MODEL" );
let r = resolve( "preferredVersionSpec", home_dir.path(), &child, config_catalog::catalog() );
assert_eq!( r.source, Layer::Project, "ancestor project config must supply value: got {:?}", r.source );
assert_eq!( r.value, Some( "beta".to_string() ), "ancestor config value must be returned: {:?}", r.value );
}