test(onboard): add regression coverage for quick setup model override

This commit is contained in:
Chummy 2026-02-20 16:13:20 +08:00
parent bbaf55eb3b
commit 70f12e5df9
3 changed files with 117 additions and 4 deletions

View file

@ -34,6 +34,7 @@ Last verified: **February 19, 2026**.
- `zeroclaw onboard --interactive` - `zeroclaw onboard --interactive`
- `zeroclaw onboard --channels-only` - `zeroclaw onboard --channels-only`
- `zeroclaw onboard --api-key <KEY> --provider <ID> --memory <sqlite|lucid|markdown|none>` - `zeroclaw onboard --api-key <KEY> --provider <ID> --memory <sqlite|lucid|markdown|none>`
- `zeroclaw onboard --api-key <KEY> --provider <ID> --model <MODEL_ID> --memory <sqlite|lucid|markdown|none>`
### `agent` ### `agent`

View file

@ -1352,10 +1352,61 @@ async fn handle_auth_command(auth_command: AuthCommands, config: &Config) -> Res
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use clap::CommandFactory; use clap::{CommandFactory, Parser};
#[test] #[test]
fn cli_definition_has_no_flag_conflicts() { fn cli_definition_has_no_flag_conflicts() {
Cli::command().debug_assert(); Cli::command().debug_assert();
} }
#[test]
fn onboard_help_includes_model_flag() {
let cmd = Cli::command();
let onboard = cmd
.get_subcommands()
.find(|subcommand| subcommand.get_name() == "onboard")
.expect("onboard subcommand must exist");
let has_model_flag = onboard
.get_arguments()
.any(|arg| arg.get_id().as_str() == "model" && arg.get_long() == Some("model"));
assert!(
has_model_flag,
"onboard help should include --model for quick setup overrides"
);
}
#[test]
fn onboard_cli_accepts_model_provider_and_api_key_in_quick_mode() {
let cli = Cli::try_parse_from([
"zeroclaw",
"onboard",
"--provider",
"openrouter",
"--model",
"custom-model-946",
"--api-key",
"sk-issue946",
])
.expect("quick onboard invocation should parse");
match cli.command {
Commands::Onboard {
interactive,
channels_only,
api_key,
provider,
model,
..
} => {
assert!(!interactive);
assert!(!channels_only);
assert_eq!(provider.as_deref(), Some("openrouter"));
assert_eq!(model.as_deref(), Some("custom-model-946"));
assert_eq!(api_key.as_deref(), Some("sk-issue946"));
}
other => panic!("expected onboard command, got {other:?}"),
}
}
} }

View file

@ -331,6 +331,28 @@ pub async fn run_quick_setup(
provider: Option<&str>, provider: Option<&str>,
model_override: Option<&str>, model_override: Option<&str>,
memory_backend: Option<&str>, memory_backend: Option<&str>,
) -> Result<Config> {
let home = directories::UserDirs::new()
.map(|u| u.home_dir().to_path_buf())
.context("Could not find home directory")?;
run_quick_setup_with_home(
credential_override,
provider,
model_override,
memory_backend,
&home,
)
.await
}
#[allow(clippy::too_many_lines)]
async fn run_quick_setup_with_home(
credential_override: Option<&str>,
provider: Option<&str>,
model_override: Option<&str>,
memory_backend: Option<&str>,
home: &Path,
) -> Result<Config> { ) -> Result<Config> {
println!("{}", style(BANNER).cyan().bold()); println!("{}", style(BANNER).cyan().bold());
println!( println!(
@ -341,9 +363,6 @@ pub async fn run_quick_setup(
); );
println!(); println!();
let home = directories::UserDirs::new()
.map(|u| u.home_dir().to_path_buf())
.context("Could not find home directory")?;
let zeroclaw_dir = home.join(".zeroclaw"); let zeroclaw_dir = home.join(".zeroclaw");
let workspace_dir = zeroclaw_dir.join("workspace"); let workspace_dir = zeroclaw_dir.join("workspace");
let config_path = zeroclaw_dir.join("config.toml"); let config_path = zeroclaw_dir.join("config.toml");
@ -4673,6 +4692,48 @@ mod tests {
assert!(ctx.communication_style.is_empty()); assert!(ctx.communication_style.is_empty());
} }
#[tokio::test]
async fn quick_setup_model_override_persists_to_config_toml() {
let tmp = TempDir::new().unwrap();
let config = run_quick_setup_with_home(
Some("sk-issue946"),
Some("openrouter"),
Some("custom-model-946"),
Some("sqlite"),
tmp.path(),
)
.await
.unwrap();
assert_eq!(config.default_provider.as_deref(), Some("openrouter"));
assert_eq!(config.default_model.as_deref(), Some("custom-model-946"));
assert_eq!(config.api_key.as_deref(), Some("sk-issue946"));
let config_raw = tokio::fs::read_to_string(config.config_path).await.unwrap();
assert!(config_raw.contains("default_provider = \"openrouter\""));
assert!(config_raw.contains("default_model = \"custom-model-946\""));
}
#[tokio::test]
async fn quick_setup_without_model_uses_provider_default_model() {
let tmp = TempDir::new().unwrap();
let config = run_quick_setup_with_home(
Some("sk-issue946"),
Some("anthropic"),
None,
Some("sqlite"),
tmp.path(),
)
.await
.unwrap();
let expected = default_model_for_provider("anthropic");
assert_eq!(config.default_provider.as_deref(), Some("anthropic"));
assert_eq!(config.default_model.as_deref(), Some(expected.as_str()));
}
// ── scaffold_workspace: basic file creation ───────────────── // ── scaffold_workspace: basic file creation ─────────────────
#[test] #[test]