use crate::utils::providers::{
KNOWN_PROVIDERS, config_section, find_provider_meta, normalize_provider_name,
};
#[test]
fn known_provider_anthropic_section() {
let meta = find_provider_meta("anthropic").expect("anthropic must exist");
assert_eq!(meta.config_section, "providers.anthropic");
assert_eq!(meta.id, "anthropic");
assert!(meta.needs_api_key);
}
#[test]
fn known_provider_openai_section() {
let meta = find_provider_meta("openai").expect("openai must exist");
assert_eq!(meta.config_section, "providers.openai");
}
#[test]
fn known_provider_github_section() {
let meta = find_provider_meta("github").expect("github must exist");
assert_eq!(meta.config_section, "providers.github");
}
#[test]
fn known_provider_gemini_section() {
let meta = find_provider_meta("gemini").expect("gemini must exist");
assert_eq!(meta.config_section, "providers.gemini");
}
#[test]
fn known_provider_openrouter_section() {
let meta = find_provider_meta("openrouter").expect("openrouter must exist");
assert_eq!(meta.config_section, "providers.openrouter");
}
#[test]
fn known_provider_minimax_section() {
let meta = find_provider_meta("minimax").expect("minimax must exist");
assert_eq!(meta.config_section, "providers.minimax");
}
#[test]
fn known_provider_zhipu_section() {
let meta = find_provider_meta("zhipu").expect("zhipu must exist");
assert_eq!(meta.config_section, "providers.zhipu");
}
#[test]
fn known_provider_claude_cli_section() {
let meta = find_provider_meta("claude_cli").expect("claude_cli must exist");
assert_eq!(meta.config_section, "providers.claude_cli");
assert!(!meta.needs_api_key);
}
#[test]
fn known_provider_opencode_cli_section() {
let meta = find_provider_meta("opencode_cli").expect("opencode_cli must exist");
assert_eq!(meta.config_section, "providers.opencode_cli");
assert!(!meta.needs_api_key);
}
#[test]
fn known_provider_codex_cli_section() {
let meta = find_provider_meta("codex_cli").expect("codex_cli must exist");
assert_eq!(meta.config_section, "providers.codex_cli");
assert!(!meta.needs_api_key);
}
#[test]
fn known_provider_codex_oauth_section() {
let meta = find_provider_meta("codex").expect("codex must exist");
assert_eq!(meta.config_section, "providers.codex");
assert!(!meta.needs_api_key);
}
#[test]
fn known_provider_opencode_section() {
let meta = find_provider_meta("opencode").expect("opencode must exist");
assert_eq!(meta.config_section, "providers.opencode");
assert!(meta.needs_api_key);
}
#[test]
fn known_provider_qwen_section() {
let meta = find_provider_meta("qwen").expect("qwen must exist");
assert_eq!(meta.config_section, "providers.qwen");
}
#[test]
fn known_provider_ollama_section() {
let meta = find_provider_meta("ollama").expect("ollama must exist");
assert_eq!(meta.config_section, "providers.ollama");
}
#[test]
fn config_section_builtin_returns_correct() {
assert_eq!(
config_section("anthropic"),
Some("providers.anthropic".to_string())
);
assert_eq!(
config_section("openai"),
Some("providers.openai".to_string())
);
assert_eq!(
config_section("ollama"),
Some("providers.ollama".to_string())
);
assert_eq!(
config_section("opencode"),
Some("providers.opencode".to_string())
);
}
#[test]
fn config_section_custom_returns_correct() {
assert_eq!(
config_section("custom:dialagram"),
Some("providers.custom.dialagram".to_string())
);
assert_eq!(
config_section("custom:opencode-qwen"),
Some("providers.custom.opencode-qwen".to_string())
);
assert_eq!(
config_section("custom(opencode-kimi)"),
Some("providers.custom.opencode-kimi".to_string())
);
}
#[test]
fn config_section_unknown_returns_none() {
assert_eq!(config_section("nonexistent"), None);
}
#[test]
fn normalize_builtin_returns_canonical_id() {
assert_eq!(normalize_provider_name("Anthropic"), "anthropic");
assert_eq!(normalize_provider_name("claude_cli"), "claude-cli");
assert_eq!(normalize_provider_name("opencode_cli"), "opencode-cli");
assert_eq!(normalize_provider_name("codex_cli"), "codex-cli");
assert_eq!(normalize_provider_name("codex_oauth"), "codex");
assert_eq!(normalize_provider_name("Codex CLI"), "codex-cli");
assert_eq!(normalize_provider_name("Codex"), "codex");
assert_eq!(normalize_provider_name("Ollama"), "ollama");
}
#[test]
fn normalize_custom_preserves_prefix() {
assert_eq!(
normalize_provider_name("custom:dialagram"),
"custom:dialagram"
);
assert_eq!(
normalize_provider_name("Custom(dialagram)"),
"custom:dialagram"
);
}
#[test]
fn all_known_providers_have_unique_ids() {
let ids: Vec<&str> = KNOWN_PROVIDERS.iter().map(|p| p.id).collect();
let mut seen = std::collections::HashSet::new();
for id in &ids {
assert!(seen.insert(*id), "Duplicate provider id: {}", id);
}
}
#[test]
fn all_known_providers_have_unique_sections() {
let sections: Vec<&str> = KNOWN_PROVIDERS.iter().map(|p| p.config_section).collect();
let mut seen = std::collections::HashSet::new();
for s in §ions {
assert!(seen.insert(*s), "Duplicate config section: {}", s);
}
}
#[test]
fn all_known_providers_have_non_empty_display_names() {
for p in KNOWN_PROVIDERS {
assert!(
!p.display_name.is_empty(),
"Provider {} has empty display_name",
p.id
);
}
}
#[test]
fn known_provider_count_matches_expected() {
assert_eq!(KNOWN_PROVIDERS.len(), 15);
}
#[test]
fn tui_providers_all_have_matching_known_provider() {
use crate::tui::onboarding::PROVIDERS;
for p in PROVIDERS {
if p.id.is_empty() {
continue;
}
let meta = find_provider_meta(p.id);
assert!(
meta.is_some(),
"TUI provider '{}' (id='{}') has no matching KNOWN_PROVIDER entry",
p.name,
p.id
);
let meta = meta.unwrap();
assert_eq!(
meta.config_section,
format!("providers.{}", p.id.replace('-', "_")),
"TUI provider '{}' section mismatch",
p.id
);
}
}
#[test]
fn tui_custom_provider_is_last() {
use crate::tui::onboarding::PROVIDERS;
let last = PROVIDERS.last().expect("PROVIDERS must not be empty");
assert!(
last.id.is_empty(),
"Last PROVIDERS entry must be Custom (empty id), got '{}'",
last.id
);
assert!(
last.name.contains("Custom"),
"Last PROVIDERS entry must be named Custom, got '{}'",
last.name
);
}
#[test]
fn is_first_time_uses_provider_registry_not_hardcoded_list() {
let source = include_str!("../tui/onboarding/fetch.rs");
assert!(
source.contains("active_provider_and_model"),
"is_first_time() must use active_provider_and_model (provider_registry), \
not a hardcoded provider list that drifts every time a provider is added"
);
}
const SAVE_SRC: &str = include_str!("../tui/onboarding/config.rs");
#[test]
fn save_provider_section_routing_covers_all_providers() {
let required_ids = [
"anthropic",
"openai",
"github",
"gemini",
"openrouter",
"minimax",
"zhipu",
"claude-cli",
"opencode-cli",
"codex-cli",
"codex",
"opencode",
"qwen",
"ollama",
];
for id in &required_ids {
let meta = find_provider_meta(id).unwrap_or_else(|| {
panic!("provider '{id}' is missing from the KNOWN_PROVIDERS registry")
});
assert!(
meta.config_section.starts_with("providers."),
"provider '{id}' resolves to a malformed section '{}'",
meta.config_section
);
}
assert!(
SAVE_SRC.contains("find_provider_meta(id)"),
"apply_config must resolve the provider section via \
find_provider_meta(id).config_section, not a hardcoded match"
);
}
#[test]
fn save_provider_disables_all_known_sections() {
let required_sections = [
"providers.anthropic",
"providers.openai",
"providers.github",
"providers.gemini",
"providers.openrouter",
"providers.minimax",
"providers.zhipu",
"providers.claude_cli",
"providers.opencode_cli",
"providers.codex_cli",
"providers.codex",
"providers.opencode",
"providers.qwen",
"providers.ollama",
];
for section in &required_sections {
assert!(
KNOWN_PROVIDERS.iter().any(|p| p.config_section == *section),
"section '{section}' is missing from the KNOWN_PROVIDERS registry, so the \
registry-driven disable-all sweep would skip it"
);
}
assert!(
SAVE_SRC.contains("all_config_sections"),
"apply_config's disable-all loop must iterate all_config_sections \
(registry-driven), not a hardcoded section list"
);
}