#[cfg(test)]
mod tests {
use crate::tui::onboarding::fetch_provider_models;
fn load_gemini_key() -> Option<String> {
let config = crate::config::Config::load().ok()?;
config.providers.gemini?.api_key
}
#[tokio::test]
async fn test_gemini_api_direct() {
let key = match load_gemini_key() {
Some(k) => k,
None => {
eprintln!("SKIP: no Gemini API key in config");
return;
}
};
let url = "https://generativelanguage.googleapis.com/v1beta/models";
let resp = match reqwest::Client::new()
.get(url)
.header("x-goog-api-key", &key)
.send()
.await
{
Ok(r) => r,
Err(e) => {
eprintln!("SKIP: Gemini API unreachable: {e}");
return;
}
};
let status = resp.status();
let body = resp.text().await.unwrap_or_default();
eprintln!("Status: {}", status);
eprintln!("Body (first 500 chars): {}", &body[..body.len().min(500)]);
if status == reqwest::StatusCode::FORBIDDEN || status == reqwest::StatusCode::UNAUTHORIZED {
eprintln!(
"SKIP: Gemini API key rejected ({}), likely IP restriction",
status
);
return;
}
assert!(
status.is_success(),
"Gemini API returned {}: {}",
status,
&body[..body.len().min(200)]
);
#[derive(serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct GeminiModel {
name: String,
#[serde(default)]
supported_generation_methods: Vec<String>,
}
#[derive(serde::Deserialize)]
struct GeminiModelsResponse {
models: Vec<GeminiModel>,
}
let parsed: GeminiModelsResponse = serde_json::from_str(&body).unwrap();
let generate_content_models: Vec<&str> = parsed
.models
.iter()
.filter(|m| {
m.supported_generation_methods
.iter()
.any(|g| g == "generateContent")
})
.map(|m| m.name.as_str())
.collect();
eprintln!("Total models: {}", parsed.models.len());
eprintln!("generateContent models: {}", generate_content_models.len());
for m in &generate_content_models[..generate_content_models.len().min(5)] {
eprintln!(" {}", m);
}
assert!(
!generate_content_models.is_empty(),
"No models with generateContent found"
);
}
#[tokio::test]
async fn test_gemini_fetch_provider_models() {
let key = match load_gemini_key() {
Some(k) => k,
None => {
eprintln!("SKIP: no Gemini API key in config");
return;
}
};
eprintln!("Calling fetch_provider_models(3, key, None)...");
let models = fetch_provider_models(3, Some(&key), None, None, None).await;
eprintln!("Returned {} models", models.len());
for m in models.iter().take(10) {
eprintln!(" {}", m);
}
if models.is_empty() {
eprintln!(
"SKIP: fetch_provider_models returned empty — likely IP restriction or API issue"
);
return;
}
}
#[tokio::test]
async fn test_gemini_fetch_no_key() {
let models = fetch_provider_models(3, None, None, None, None).await;
assert!(models.is_empty(), "Should return empty with no key");
}
}