//! Provider selection and provenance behavior through the `smith` CLI //! (`SMH-SPEC-SPEC0001`, Providers). //! CLI tests assert on outcomes. use assert_cmd::Command; use predicates::prelude::PredicateBooleanExt; fn smith(name: &str) -> Command { let mut command = Command::cargo_bin("smith").unwrap(); command .env( "XDG_DATA_HOME", std::env::temp_dir().join(format!("smith-sel-test-{name}-{}", std::process::id())), ) .env_remove("SMITH_PROVIDER") .env_remove("SMITH_MODEL") .env_remove("SMITH_BASE_URL") .env_remove("ANTHROPIC_API_KEY") .env_remove("OPENAI_API_KEY") .env_remove("GEMINI_API_KEY"); command } #[test] fn eval_without_provider_fails_naming_the_selection_surfaces() { smith("noprovider") .args(["eval", "hi"]) .assert() .failure() .stderr(predicates::str::contains( "no provider selected (tried --provider/SMITH_PROVIDER)", )); } #[test] fn eval_missing_credential_names_store_and_env_without_leaking_secrets() { let assert = smith("nocreds") .args([ "eval", "--provider", "anthropic", "--model", "claude-sonnet-4-5", "hi", ]) .env("ANTHROPIC_API_KEY", "") .assert() .failure(); assert .stderr(predicates::str::contains( "no credential for anthropic (tried store, env ANTHROPIC_API_KEY)", )) .stderr(predicates::str::contains("sk-").not()); } #[test] fn command_line_overrides_environment_and_reports_provenance() { smith("provenance") .args([ "eval", "--provider", "anthropic", "--model", "claude-sonnet-4-5", "hi", ]) .env("SMITH_PROVIDER", "google") .env("SMITH_MODEL", "gemini-3-pro") .env_remove("ANTHROPIC_API_KEY") .assert() .failure() .stderr(predicates::str::contains( "provider=anthropic(cli) model=claude-sonnet-4-5(cli)", )) .stderr(predicates::str::contains("provider=google").not()); } #[test] fn environment_selection_reports_env_provenance() { smith("envprov") .args(["eval", "hi"]) .env("SMITH_PROVIDER", "google") .env("SMITH_MODEL", "gemini-3-pro") .assert() .failure() .stderr(predicates::str::contains( "provider=google(env) model=gemini-3-pro(env)", )); } #[test] fn mock_eval_still_runs_without_selection() { smith("mock") .args(["eval", "--mock", "hi"]) .assert() .success() .stdout("mock provider: no model configured\n"); }