use super::*;
#[test]
fn scratch_section_defaults_and_parses() {
let bare: Config = toml::from_str("").unwrap();
assert!(bare.scratch.is_none());
let cfg: Config = toml::from_str("[scratch]\ndir = \"/tmp/newt-scratch\"\n").unwrap();
assert_eq!(
cfg.scratch.and_then(|s| s.dir).as_deref(),
Some("/tmp/newt-scratch")
);
}
#[test]
fn allow_bang_escape_defaults_to_true_and_round_trips() {
let cfg: TuiConfig = toml::from_str("").unwrap();
assert!(cfg.allow_bang_escape);
let cfg: TuiConfig = toml::from_str("allow_bang_escape = false").unwrap();
assert!(!cfg.allow_bang_escape);
}
#[test]
fn shell_commands_default_on_mutations_default_off_and_round_trip() {
let cfg: TuiConfig = toml::from_str("").unwrap();
assert!(cfg.allow_shell_commands);
assert!(!cfg.allow_shell_mutations);
let cfg: TuiConfig =
toml::from_str("allow_shell_commands = false\nallow_shell_mutations = true").unwrap();
assert!(!cfg.allow_shell_commands);
assert!(cfg.allow_shell_mutations);
}
#[test]
fn conversations_config_defaults_to_count_cap() {
let cfg = Config::default();
let conversations = cfg.conversations.unwrap_or_default();
assert_eq!(conversations.max_per_workspace, 100);
assert!(!conversations.resume);
}
#[test]
fn conversations_config_roundtrips_through_toml() {
let cfg: Config = toml::from_str(
r#"
[conversations]
max_per_workspace = 25
"#,
)
.unwrap();
let conversations = cfg.conversations.unwrap_or_default();
assert_eq!(conversations.max_per_workspace, 25);
assert!(!conversations.resume);
}
#[test]
fn conversations_resume_opt_in_parses() {
let cfg: Config = toml::from_str(
r#"
[conversations]
resume = true
"#,
)
.unwrap();
assert!(cfg.conversations.unwrap_or_default().resume);
}
#[test]
fn agents_config_default_enabled() {
let cfg = AgentsConfig::default();
assert!(cfg.enabled);
assert_eq!(cfg.path, None);
assert!(Config::default().agents.enabled);
}
#[test]
fn agents_config_roundtrips_with_path() {
let cfg: Config = toml::from_str(
r#"
[agents]
path = "docs/instructions"
"#,
)
.unwrap();
assert!(cfg.agents.enabled);
assert_eq!(cfg.agents.path.as_deref(), Some("docs/instructions"));
let text = toml::to_string(&cfg).unwrap();
assert!(text.contains("docs/instructions"));
}
#[test]
fn agents_config_can_be_disabled() {
let cfg: Config = toml::from_str(
r#"
[agents]
enabled = false
"#,
)
.unwrap();
assert!(!cfg.agents.enabled);
assert_eq!(cfg.agents.path, None);
}
#[test]
fn default_max_tool_rounds_is_40() {
assert_eq!(default_max_tool_rounds(), 40);
assert_eq!(TuiConfig::default().max_tool_rounds, 40);
assert_eq!(default_workflow_grace_rounds(), 5);
assert_eq!(TuiConfig::default().workflow_grace_rounds, 5);
}
#[test]
fn tui_max_tool_rounds_defaults_when_field_absent() {
let toml = r#"
[tui]
"#;
let cfg: Config = toml::from_str(toml).unwrap();
assert_eq!(cfg.tui.unwrap().max_tool_rounds, 40);
}
#[test]
fn tui_max_tool_rounds_can_be_overridden() {
let toml = r#"
[tui]
max_tool_rounds = 7
"#;
let cfg: Config = toml::from_str(toml).unwrap();
assert_eq!(cfg.tui.unwrap().max_tool_rounds, 7);
}
#[test]
fn tui_narration_nudge_cap_defaults_to_one_and_can_be_raised() {
assert_eq!(default_narration_nudge_cap(), 1);
assert_eq!(TuiConfig::default().narration_nudge_cap, 1);
let cfg: Config = toml::from_str("[tui]\n").unwrap();
assert_eq!(cfg.tui.unwrap().narration_nudge_cap, 1);
let cfg: Config = toml::from_str("[tui]\nnarration_nudge_cap = 3\n").unwrap();
assert_eq!(cfg.tui.unwrap().narration_nudge_cap, 3);
}
#[test]
fn tui_narration_intent_line_defaults_off_and_can_be_enabled() {
assert!(!default_narration_intent_line());
assert!(!TuiConfig::default().narration_intent_line);
let cfg: Config = toml::from_str("[tui]\n").unwrap();
assert!(!cfg.tui.unwrap().narration_intent_line);
let cfg: Config = toml::from_str("[tui]\nnarration_intent_line = true\n").unwrap();
assert!(cfg.tui.unwrap().narration_intent_line);
}
#[test]
fn model_tuning_narration_nudge_cap_override_parses() {
let cfg: Config = toml::from_str(
r#"
[[model_tuning]]
model = "ornith:35b"
narration_nudge_cap = 3
output_allowance = 6000
"#,
)
.unwrap();
let tune = cfg.find_model_tuning("ornith:35b").unwrap();
assert_eq!(tune.narration_nudge_cap, Some(3));
assert_eq!(tune.output_allowance, Some(6_000));
let cfg: Config = toml::from_str(
r#"
[[model_tuning]]
model = "other:7b"
max_tool_rounds = 9
"#,
)
.unwrap();
assert_eq!(
cfg.find_model_tuning("other:7b")
.unwrap()
.narration_nudge_cap,
None
);
}
#[test]
fn tui_workflow_grace_rounds_can_be_overridden_or_disabled() {
let cfg: Config = toml::from_str(
r#"
[tui]
workflow_grace_rounds = 9
"#,
)
.unwrap();
assert_eq!(cfg.tui.unwrap().workflow_grace_rounds, 9);
let disabled: Config = toml::from_str(
r#"
[tui]
workflow_grace_rounds = 0
"#,
)
.unwrap();
assert_eq!(disabled.tui.unwrap().workflow_grace_rounds, 0);
}
#[test]
fn model_tuning_parses_from_toml() {
let toml = r#"
[[model_tuning]]
model = "nemotron3:33b"
num_ctx = 24576
mid_loop_trim_threshold = 12
max_tool_rounds = 20
workflow_grace_rounds = 8
[[model_tuning]]
model = "qwen3-coder:30b"
num_ctx = 65536
"#;
let cfg: Config = toml::from_str(toml).unwrap();
assert_eq!(cfg.model_tuning.len(), 2);
let nemo = cfg.find_model_tuning("nemotron3:33b").unwrap();
assert_eq!(nemo.num_ctx, Some(24576));
assert_eq!(nemo.mid_loop_trim_threshold, Some(12));
assert_eq!(nemo.max_tool_rounds, Some(20));
assert_eq!(nemo.workflow_grace_rounds, Some(8));
let qwen = cfg.find_model_tuning("qwen3-coder:30b").unwrap();
assert_eq!(qwen.num_ctx, Some(65536));
assert_eq!(qwen.mid_loop_trim_threshold, None);
assert_eq!(qwen.workflow_grace_rounds, None);
}
#[test]
fn model_tuning_find_returns_none_for_unknown_model() {
let cfg = Config::default();
assert!(cfg.find_model_tuning("nonexistent:7b").is_none());
}
#[test]
fn model_tuning_partial_fields_are_optional() {
let toml = r#"
[[model_tuning]]
model = "llama3.1:8b"
"#;
let cfg: Config = toml::from_str(toml).unwrap();
let entry = cfg.find_model_tuning("llama3.1:8b").unwrap();
assert_eq!(entry.num_ctx, None);
assert_eq!(entry.mid_loop_trim_threshold, None);
assert_eq!(entry.max_tool_rounds, None);
assert_eq!(entry.workflow_grace_rounds, None);
}