use super::*;
use crate::config_edit::brazen::NOT_REQUIRED;
fn row(name: &str, auth: &str, credential: &str) -> ProviderRow {
ProviderRow {
name: name.to_owned(),
protocol: String::new(),
auth: auth.to_owned(),
credential: credential.to_owned(),
effort: false,
priority: false,
tools: Some(true),
device: String::new(),
}
}
fn role(role: &str, provider: &str) -> RoleModel {
RoleModel {
role: role.to_owned(),
provider: provider.to_owned(),
model: "m".to_owned(),
effort: None,
priority: false,
}
}
#[test]
fn a_lineage_that_declares_no_worker_falls_back_to_the_wall() {
let keyless = [
row("ollama", "none", NOT_REQUIRED),
row("acme", "api_key", "missing"),
];
assert_eq!(verdict(&keyless, &[]), Some(Unready::Wall));
assert_eq!(verdict(&[row("acme", "api_key", "stored")], &[]), None);
assert_eq!(
verdict(
&[row(
"acme",
"api_key",
"a-spelling-this-build-never-heard-of"
)],
&[]
),
None,
"every spelling but missing and not-required is a credential"
);
}
#[test]
fn a_credentialed_row_the_roles_do_not_name_readies_nothing() {
let rows = [
row("sideline", "bearer", "ambient"),
row("anthropic", "api_key", "missing"),
];
let roles = [role("worker", "anthropic")];
assert_eq!(
verdict(&rows, &roles),
Some(Unready::Uncredentialed {
row: rows[1].clone(),
})
);
let signed = [rows[0].clone(), row("anthropic", "api_key", "stored")];
assert_eq!(verdict(&signed, &roles), None);
}
#[test]
fn a_role_naming_a_keyless_row_readies_the_wall() {
let rows = [row("ollama", "none", NOT_REQUIRED)];
assert_eq!(verdict(&rows, &[role("worker", "ollama")]), None);
assert_eq!(verdict(&rows, &[]), Some(Unready::Wall));
}
#[test]
fn only_the_worker_gates_the_fire() {
let rows = [row("acme", "api_key", "stored")];
assert_eq!(
verdict(
&rows,
&[
role("worker", "acme"),
role("compactor", "gone"),
role("reviewer", "also-gone"),
]
),
None
);
assert_eq!(
verdict(&rows, &[role("compactor", "acme"), role("worker", "gone")]),
Some(Unready::Undeclared {
provider: "gone".to_owned(),
})
);
}
#[test]
fn each_refusal_names_its_own_act() {
let rows = [
row("openai-chatgpt", "oauth2", "missing"),
row("anthropic", "api_key", "missing"),
];
let keyed = refusal::say(
&Unready::Uncredentialed {
row: rows[1].clone(),
},
&rows,
);
assert!(keyed.starts_with("sign in first"), "{keyed}");
assert!(
keyed.contains("`worker` resolves provider `anthropic`"),
"{keyed}"
);
assert!(keyed.ends_with("/config brazen"), "{keyed}");
let oauth = refusal::say(
&Unready::Uncredentialed {
row: rows[0].clone(),
},
&rows,
);
assert!(oauth.ends_with("/login openai-chatgpt"), "{oauth}");
let absent = refusal::say(
&Unready::Undeclared {
provider: "claude-session-direct".to_owned(),
},
&rows,
);
assert!(!absent.contains("/login"), "{absent}");
assert!(absent.contains("declares no such row"), "{absent}");
assert!(absent.contains("/config brazen"), "{absent}");
assert!(
absent.contains("/model worker <provider> <model-id>"),
"{absent}"
);
assert!(
absent.ends_with("(rows here: openai-chatgpt, anthropic)"),
"{absent}"
);
let wall = refusal::say(&Unready::Wall, &rows);
assert!(wall.starts_with("sign in first"), "{wall}");
assert!(
wall.ends_with(
"sign in with /login: openai-chatgpt; \
write a key with /config brazen: anthropic"
),
"{wall}"
);
}
#[test]
fn the_wall_offers_each_row_the_act_that_would_ready_it() {
let mut rows = vec![
row("openai-chatgpt", "oauth2", "missing"),
row("anthropic", "api_key", "missing"),
row("google", "api_key", "missing"),
row("ollama", "none", NOT_REQUIRED),
row("claude-code", "none", NOT_REQUIRED),
];
rows[4].tools = Some(false);
rows[4].protocol = "claude_code".to_owned();
let said = refusal::say(&Unready::Wall, &rows);
assert!(
said.ends_with(
"sign in with /login: openai-chatgpt; \
write a key with /config brazen: anthropic, google; \
name in a role with /model <role> <provider> <model-id>: ollama; \
can serve no role: claude-code"
),
"{said}"
);
let one = refusal::say(&Unready::Wall, &rows[3..4]);
assert!(
one.ends_with("name in a role with /model <role> <provider> <model-id>: ollama"),
"{one}"
);
}