use clap::Parser;
use super::*;
#[test]
fn parses_new_provider_auth_modes() {
for auth in rho_providers::auth_profiles() {
let cli = Cli::try_parse_from(["rho", "--auth", auth]).unwrap();
assert_eq!(cli.auth.as_deref(), Some(*auth));
}
}
#[test]
fn parses_custom_provider_api_key_auth() {
let cli = Cli::try_parse_from(["rho", "--auth", "vllm-api-key"]).unwrap();
assert_eq!(cli.auth.as_deref(), Some("vllm-api-key"));
}
#[test]
fn rejects_unknown_auth_profiles() {
let error = Cli::try_parse_from(["rho", "--auth", "not-a-real-auth"]).unwrap_err();
assert!(error
.to_string()
.contains("invalid value 'not-a-real-auth'"));
assert!(error.to_string().contains("ollama-cloud-api-key"));
}
#[test]
fn saved_session_flags_conflict() {
for args in [
vec!["rho", "--no-save", "--resume"],
vec!["rho", "--resume", "--no-save"],
vec!["rho", "--no-save", "--resume", "abc123"],
vec!["rho", "--resume", "abc123", "--no-save"],
vec!["rho", "--no-save", "-R"],
vec!["rho", "-R", "--no-save"],
vec!["rho", "--no-save", "-R", "abc123"],
vec!["rho", "-R", "abc123", "--no-save"],
vec!["rho", "--no-save", "--continue"],
vec!["rho", "-c", "--no-save"],
vec!["rho", "-c", "-R"],
vec!["rho", "-R", "abc123", "--continue"],
] {
let error = Cli::try_parse_from(&args).unwrap_err();
assert_eq!(
error.kind(),
clap::error::ErrorKind::ArgumentConflict,
"{args:?}"
);
}
}
#[test]
fn parses_credential_store_commands() {
use rho_providers::credentials::CredentialStoreBackend;
let probe = Cli::try_parse_from(["rho", "credential-store", "probe", "os"]).unwrap();
assert!(matches!(
probe.command,
Some(Command::CredentialStore {
command: CredentialStoreCommand::Probe { backend }
}) if backend == CredentialStoreBackend::Os
));
let probe_default = Cli::try_parse_from(["rho", "credential-store", "probe"]).unwrap();
assert!(matches!(
probe_default.command,
Some(Command::CredentialStore {
command: CredentialStoreCommand::Probe { backend }
}) if backend == CredentialStoreBackend::Os
));
let probe_auto = Cli::try_parse_from(["rho", "credential-store", "probe", "auto"]).unwrap();
assert!(matches!(
probe_auto.command,
Some(Command::CredentialStore {
command: CredentialStoreCommand::Probe { backend }
}) if backend == CredentialStoreBackend::Os
));
let set = Cli::try_parse_from(["rho", "credential-store", "set", "file"]).unwrap();
assert!(matches!(
set.command,
Some(Command::CredentialStore {
command: CredentialStoreCommand::Set { backend }
}) if backend == CredentialStoreBackend::File
));
let status = Cli::try_parse_from(["rho", "credential-store", "status"]).unwrap();
assert!(matches!(
status.command,
Some(Command::CredentialStore {
command: CredentialStoreCommand::Status
})
));
}
#[test]
fn parses_structured_output_and_execution_bounds() {
let cli = Cli::try_parse_from([
"rho",
"run",
"--output",
"jsonl",
"--max-steps",
"12",
"--timeout",
"20m",
"ship it",
])
.unwrap();
assert!(matches!(
cli.command,
Some(Command::Run {
output: OutputFormat::Jsonl,
max_steps: Some(max_steps),
timeout: Some(timeout),
..
}) if max_steps.get() == 12 && timeout == std::time::Duration::from_secs(1_200)
));
}
#[test]
fn rejects_zero_steps_and_invalid_durations() {
for arguments in [
["rho", "run", "--max-steps", "0"],
["rho", "run", "--timeout", "soon"],
] {
assert!(Cli::try_parse_from(arguments).is_err());
}
}
#[test]
fn parses_all_workflow_commands_and_output_modes() {
let list = Cli::try_parse_from([
"rho", "workflow", "list", "--runs", "--limit", "3", "--json",
])
.unwrap();
assert!(matches!(
list.command,
Some(Command::Workflow {
command: WorkflowCommand::List {
plans: false,
runs: true,
limit: Some(limit),
json: true,
}
}) if limit.get() == 3
));
let validate = Cli::try_parse_from([
"rho",
"workflow",
"validate",
"review.star",
"--input",
"target=\"src\"",
])
.unwrap();
assert!(matches!(
validate.command,
Some(Command::Workflow {
command: WorkflowCommand::Validate { file, input }
}) if file.as_path() == std::path::Path::new("review.star") && input == ["target=\"src\""]
));
let plan = Cli::try_parse_from(["rho", "workflow", "plan", "review.star", "--output", "json"])
.unwrap();
assert!(matches!(
plan.command,
Some(Command::Workflow {
command: WorkflowCommand::Plan {
output: WorkflowDocumentFormat::Json,
..
}
})
));
let run = Cli::try_parse_from([
"rho",
"workflow",
"run",
"plan-prefix",
"--yes",
"--output",
"jsonl",
])
.unwrap();
assert!(matches!(
run.command,
Some(Command::Workflow {
command: WorkflowCommand::Run {
plan_id,
yes: true,
output: Some(WorkflowRunFormat::Jsonl)
}
}) if plan_id == "plan-prefix"
));
let status = Cli::try_parse_from([
"rho",
"workflow",
"status",
"run-prefix",
"--output",
"json",
])
.unwrap();
assert!(matches!(
status.command,
Some(Command::Workflow {
command: WorkflowCommand::Status {
output: WorkflowDocumentFormat::Json,
..
}
})
));
let cancel = Cli::try_parse_from(["rho", "workflow", "cancel", "run-prefix"]).unwrap();
assert!(matches!(
cancel.command,
Some(Command::Workflow {
command: WorkflowCommand::Cancel { run_id }
}) if run_id == "run-prefix"
));
let resume = Cli::try_parse_from([
"rho",
"workflow",
"resume",
"run-prefix",
"--yes",
"--output",
"text",
])
.unwrap();
assert!(matches!(
resume.command,
Some(Command::Workflow {
command: WorkflowCommand::Resume {
yes: true,
output: Some(WorkflowRunFormat::Text),
..
}
})
));
}
#[test]
fn workflow_commands_reject_wrong_output_modes() {
assert!(Cli::try_parse_from([
"rho",
"workflow",
"plan",
"review.star",
"--output",
"jsonl"
])
.is_err());
assert!(
Cli::try_parse_from(["rho", "workflow", "run", "plan-id", "--output", "json"]).is_err()
);
}
#[test]
fn parses_hidden_workflow_planner_worker_command() {
let cli = Cli::try_parse_from(["rho", WORKFLOW_PLANNER_WORKER_COMMAND]).unwrap();
assert!(matches!(cli.command, Some(Command::WorkflowPlannerWorker)));
assert!(Cli::try_parse_from(["rho", "workflow", "validate", "worker.star"]).is_ok());
}