use super::super::*;
use super::{Catalog, Quirked, Scripted, deps, deps_with_env_set, number_of};
async fn run_zai(store: &AuthStore, key_answer: &str) -> (Plan, Scripted) {
let provider = number_of("zai");
let answers = vec![
provider.as_str(),
"", key_answer, "", "", "", "", ];
let mut console = Scripted::new(&answers);
let plan = run(
&mut console,
deps(store, &Catalog::Unavailable, &Quirked::Unavailable),
)
.await
.expect("the wizard completes");
assert!(console.is_drained(), "unused answers: the flow differed");
(plan, console)
}
#[tokio::test]
async fn a_pasted_key_is_queued_for_the_store_and_kept_out_of_the_config() {
let (plan, _) = run_zai(&AuthStore::new(), "sk-pasted").await;
assert_eq!(
plan.new_keys,
vec![(
"https://api.z.ai/api/coding/paas/v4".to_string(),
"sk-pasted".to_string()
)]
);
assert!(
plan.choices[0].key_in_store(),
"so no api_key line is rendered: an explicit one would override the key just saved"
);
}
#[tokio::test]
async fn the_key_prompt_is_a_secret_prompt() {
let (_, console) = run_zai(&AuthStore::new(), "sk-pasted").await;
assert_eq!(
console.secrets_asked.len(),
1,
"expected exactly one secret prompt, got {:?}",
console.secrets_asked
);
assert!(
console.secrets_asked[0].contains("Paste your API key"),
"got {:?}",
console.secrets_asked
);
}
#[tokio::test]
async fn an_empty_paste_falls_back_to_the_environment_variable() {
let (plan, console) = run_zai(&AuthStore::new(), "").await;
assert!(plan.new_keys.is_empty(), "nothing to store");
assert!(
!plan.choices[0].key_in_store(),
"so `api_key = \"${{ZAI_API_KEY}}\"` is written instead"
);
assert!(
console.transcript().contains("ZAI_API_KEY"),
"and the variable is named: {}",
console.transcript()
);
}
#[tokio::test]
async fn whitespace_only_is_treated_as_an_empty_paste() {
let (plan, _) = run_zai(&AuthStore::new(), " ").await;
assert!(plan.new_keys.is_empty());
assert!(!plan.choices[0].key_in_store());
}
#[tokio::test]
async fn a_key_already_in_the_store_is_reused_without_asking() {
let mut store = AuthStore::new();
store
.set("https://api.z.ai/api/coding/paas/v4", "sk-existing")
.expect("set");
let provider = number_of("zai");
let mut console = Scripted::new(&[provider.as_str(), "", "", "", "", ""]);
let plan = run(
&mut console,
deps(&store, &Catalog::Unavailable, &Quirked::Unavailable),
)
.await
.expect("the wizard completes");
assert!(console.is_drained(), "no paste prompt was answered");
assert!(
console.secrets_asked.is_empty(),
"nothing should have been asked as a secret: {:?}",
console.secrets_asked
);
assert!(plan.choices[0].key_in_store());
assert!(plan.new_keys.is_empty());
assert!(console.transcript().contains("already stored"));
}
#[tokio::test]
async fn a_stored_key_is_found_regardless_of_a_trailing_slash() {
let mut store = AuthStore::new();
store
.set("https://api.z.ai/api/coding/paas/v4/", "sk-existing")
.expect("set");
let provider = number_of("zai");
let mut console = Scripted::new(&[provider.as_str(), "", "", "", "", ""]);
let plan = run(
&mut console,
deps(&store, &Catalog::Unavailable, &Quirked::Unavailable),
)
.await
.expect("the wizard completes");
assert!(console.secrets_asked.is_empty());
assert!(plan.choices[0].key_in_store());
}
#[tokio::test]
async fn a_key_pasted_earlier_in_the_same_run_is_not_asked_for_twice() {
let zai = number_of("zai");
let mut console = Scripted::new(&[
zai.as_str(),
"", "sk-pasted", "", "y", zai.as_str(),
"", "glm-5.2", "", "",
"",
]);
let plan = run(
&mut console,
deps(
&AuthStore::new(),
&Catalog::Unavailable,
&Quirked::Unavailable,
),
)
.await
.expect("the wizard completes");
assert!(
console.is_drained(),
"the second provider asked for a key again"
);
assert_eq!(console.secrets_asked.len(), 1, "asked once, not twice");
assert_eq!(plan.new_keys.len(), 1, "and queued once");
assert!(
plan.choices[1].key_in_store(),
"the second entry uses it too"
);
}
#[tokio::test]
async fn a_provider_needing_no_key_is_never_asked_for_one() {
let mut console = Scripted::new(&["1", "", "", "", "", ""]);
let plan = run(
&mut console,
deps(
&AuthStore::new(),
&Catalog::Unavailable,
&Quirked::Unavailable,
),
)
.await
.expect("the wizard completes");
assert_eq!(plan.choices[0].preset.key, "local");
assert!(
console.secrets_asked.is_empty(),
"a local server has no key to paste"
);
assert!(!plan.choices[0].key_in_store());
}
#[tokio::test]
async fn the_place_to_get_a_key_is_shown_when_the_preset_knows_it() {
let (_, console) = run_zai(&AuthStore::new(), "").await;
let url = presets::preset("zai")
.expect("preset")
.key_url()
.expect("url");
assert!(
console.transcript().contains(url),
"the wizard should say where to get a key: {}",
console.transcript()
);
}
#[tokio::test]
async fn every_preset_that_needs_a_key_knows_where_to_get_one() {
for preset in presets::PRESETS {
if preset.api_key_env().is_some() && preset.endpoint().is_some() {
assert!(
preset.key_url().is_some(),
"preset `{}` needs a key but names no source",
preset.key
);
}
}
}
#[tokio::test]
async fn an_already_exported_variable_is_reported_at_the_prompt() {
let provider = number_of("zai");
let mut console = Scripted::new(&[provider.as_str(), "", "", "", "", "", ""]);
run(
&mut console,
deps_with_env_set(
&AuthStore::new(),
&Catalog::Unavailable,
&Quirked::Unavailable,
),
)
.await
.expect("the wizard completes");
assert!(
console.transcript().contains("already set in this shell"),
"got {}",
console.transcript()
);
}
#[tokio::test]
async fn an_unset_variable_is_not_claimed_to_be_set() {
let (_, console) = run_zai(&AuthStore::new(), "").await;
assert!(
!console.transcript().contains("already set in this shell"),
"got {}",
console.transcript()
);
}