use crate::brain::Provider;
use crate::brain::provider::custom_openai_compatible::OpenAIProvider;
use crate::config::{Config, ProviderConfig, ProviderConfigs, resolve_provider_from_config};
use crate::tui::onboarding::{OnboardingWizard, PROVIDERS};
#[test]
fn github_models_is_at_index_2() {
assert_eq!(PROVIDERS[2].name, "GitHub Copilot");
}
#[test]
fn github_models_has_no_static_models() {
assert!(PROVIDERS[2].models.is_empty());
}
#[test]
fn github_copilot_key_label() {
assert_eq!(PROVIDERS[2].key_label, "OAuth");
}
#[test]
fn github_copilot_has_help_lines() {
assert!(!PROVIDERS[2].help_lines.is_empty());
let help = PROVIDERS[2].help_lines.join(" ");
assert!(help.contains("Copilot"));
}
#[test]
fn provider_order_after_github_insertion() {
assert_eq!(PROVIDERS[0].name, "Anthropic Claude");
assert_eq!(PROVIDERS[1].name, "OpenAI");
assert_eq!(PROVIDERS[2].name, "GitHub Copilot");
assert_eq!(PROVIDERS[3].name, "Google Gemini");
assert_eq!(PROVIDERS[4].name, "OpenRouter");
assert_eq!(PROVIDERS[5].name, "Minimax");
assert_eq!(PROVIDERS[6].name, "z.ai GLM");
assert_eq!(PROVIDERS[7].name, "Claude CLI");
assert_eq!(PROVIDERS[8].name, "OpenCode CLI");
assert_eq!(PROVIDERS[9].name, "OpenCode");
assert_eq!(PROVIDERS[10].name, "Qwen");
assert_eq!(PROVIDERS[11].name, "Ollama");
assert_eq!(PROVIDERS[12].name, "Custom OpenAI-Compatible");
}
#[test]
fn provider_configs_has_github_field() {
let configs = ProviderConfigs::default();
assert!(configs.github.is_none());
}
#[test]
fn provider_configs_github_round_trip() {
let configs = ProviderConfigs {
github: Some(ProviderConfig {
enabled: true,
default_model: Some("gpt-4o".to_string()),
..Default::default()
}),
..Default::default()
};
assert!(configs.github.as_ref().unwrap().enabled);
assert_eq!(
configs.github.as_ref().unwrap().default_model.as_deref(),
Some("gpt-4o")
);
}
#[test]
fn resolve_github_when_enabled() {
let mut config = Config::default();
config.providers.github = Some(ProviderConfig {
enabled: true,
default_model: Some("gpt-4o".to_string()),
..Default::default()
});
let (name, model) = resolve_provider_from_config(&config);
assert_eq!(name, "GitHub Copilot");
assert_eq!(model, "gpt-4o");
}
#[test]
fn resolve_github_default_model_when_none() {
let mut config = Config::default();
config.providers.github = Some(ProviderConfig {
enabled: true,
default_model: None,
..Default::default()
});
let (name, model) = resolve_provider_from_config(&config);
assert_eq!(name, "GitHub Copilot");
assert_eq!(model, "gpt-5-mini");
}
#[test]
fn resolve_skips_github_when_disabled() {
let mut config = Config::default();
config.providers.github = Some(ProviderConfig {
enabled: false,
..Default::default()
});
let (name, _) = resolve_provider_from_config(&config);
assert_ne!(name, "GitHub Copilot");
}
#[test]
fn resolve_skips_github_when_absent() {
let config = Config::default();
assert!(config.providers.github.is_none());
let (name, _) = resolve_provider_from_config(&config);
assert_ne!(name, "GitHub Copilot");
}
#[test]
fn extra_headers_builder_sets_headers() {
use crate::brain::provider::copilot::copilot_extra_headers;
let headers = copilot_extra_headers();
let provider = OpenAIProvider::with_base_url(
"copilot-managed".to_string(),
"https://api.githubcopilot.com/chat/completions".to_string(),
)
.with_extra_headers(headers);
assert!(!provider.extra_headers.is_empty());
assert!(
provider
.extra_headers
.iter()
.any(|(k, _)| k == "copilot-integration-id")
);
}
#[test]
fn extra_headers_default_empty() {
let provider = OpenAIProvider::with_base_url(
"test-key".to_string(),
"https://api.openai.com/v1/chat/completions".to_string(),
);
assert!(provider.extra_headers.is_empty());
}
#[test]
fn with_name_sets_provider_name() {
let provider = OpenAIProvider::with_base_url(
"copilot-managed".to_string(),
"https://api.githubcopilot.com/chat/completions".to_string(),
)
.with_name("GitHub Copilot");
assert_eq!(provider.name(), "GitHub Copilot");
}
#[test]
fn wizard_github_is_not_custom() {
let mut wizard = OnboardingWizard::new();
wizard.ps.selected_provider = 2;
assert!(!wizard.ps.is_custom());
}
#[test]
fn wizard_github_supports_model_fetch() {
let mut wizard = OnboardingWizard::new();
wizard.ps.selected_provider = 2;
assert!(wizard.ps.supports_model_fetch());
}
#[test]
fn wizard_current_provider_at_index_2_is_github() {
let mut wizard = OnboardingWizard::new();
wizard.ps.selected_provider = 2;
assert_eq!(wizard.ps.current_provider().name, "GitHub Copilot");
}
#[test]
fn wizard_model_filter_works_for_github() {
let mut wizard = OnboardingWizard::new();
wizard.ps.selected_provider = 2;
wizard.ps.models = vec![
"gpt-4o".to_string(),
"gpt-4o-mini".to_string(),
"Llama-3.3-70B-Instruct".to_string(),
];
wizard.ps.model_filter = "gpt".to_string();
let filtered = wizard.ps.filtered_model_names();
assert_eq!(filtered.len(), 2);
assert!(filtered.iter().all(|m| m.contains("gpt")));
}
#[test]
fn wizard_all_model_names_uses_fetched_first() {
let mut wizard = OnboardingWizard::new();
wizard.ps.selected_provider = 2;
wizard.ps.models = vec!["gpt-4o".to_string()];
let names = wizard.ps.all_model_names();
assert_eq!(names, vec!["gpt-4o"]);
}
#[test]
fn wizard_all_model_names_falls_back_to_config_models() {
let mut wizard = OnboardingWizard::new();
wizard.ps.selected_provider = 2;
wizard.ps.config_models = vec!["gpt-4o".to_string()];
let names = wizard.ps.all_model_names();
assert_eq!(names, vec!["gpt-4o"]);
}
#[test]
fn wizard_selected_model_name_in_bounds() {
let mut wizard = OnboardingWizard::new();
wizard.ps.selected_provider = 2;
wizard.ps.models = vec!["gpt-4o".to_string(), "gpt-4o-mini".to_string()];
wizard.ps.selected_model = 1;
assert_eq!(wizard.ps.selected_model_name(), "gpt-4o-mini");
}
#[test]
fn wizard_selected_model_name_out_of_bounds_fallback() {
let mut wizard = OnboardingWizard::new();
wizard.ps.selected_provider = 2;
wizard.ps.models = vec!["gpt-4o".to_string()];
wizard.ps.selected_model = 99;
assert_eq!(wizard.ps.selected_model_name(), "gpt-4o");
}
#[test]
fn github_provider_builder_full_chain() {
use crate::brain::provider::copilot::copilot_extra_headers;
let headers = copilot_extra_headers();
let provider = OpenAIProvider::with_base_url(
"copilot-managed".to_string(),
"https://api.githubcopilot.com/chat/completions".to_string(),
)
.with_name("GitHub Copilot")
.with_extra_headers(headers.clone());
assert_eq!(provider.name(), "GitHub Copilot");
assert!(!provider.extra_headers.is_empty());
let keys: Vec<&str> = provider
.extra_headers
.iter()
.map(|(k, _)| k.as_str())
.collect();
assert!(keys.contains(&"copilot-integration-id"));
}
#[test]
fn extra_headers_new_constructor_empty() {
let provider = OpenAIProvider::new("test-key".to_string());
assert!(provider.extra_headers.is_empty());
}
#[test]
fn github_config_section_is_providers_github() {
let sections = [
"providers.anthropic",
"providers.openai",
"providers.github",
"providers.gemini",
"providers.openrouter",
"providers.minimax",
];
assert_eq!(sections[2], "providers.github");
}
#[test]
fn github_writes_base_url() {
let github_index: usize = 2;
let writes_base_url = matches!(github_index, 2 | 4 | 5 | 6);
assert!(writes_base_url);
}
#[test]
fn github_writes_models_array() {
let github_index: usize = 2;
let writes_models = matches!(github_index, 2 | 5 | 6);
assert!(writes_models);
}
#[test]
fn resolve_anthropic_takes_priority_over_github() {
let mut config = Config::default();
config.providers.anthropic = Some(ProviderConfig {
enabled: true,
default_model: Some("claude-sonnet-4-20250514".to_string()),
..Default::default()
});
config.providers.github = Some(ProviderConfig {
enabled: true,
default_model: Some("gpt-4o".to_string()),
..Default::default()
});
let (name, _) = resolve_provider_from_config(&config);
assert_eq!(name, "Anthropic");
}
#[test]
fn resolve_github_chosen_when_only_github_enabled() {
let mut config = Config::default();
config.providers.anthropic = Some(ProviderConfig {
enabled: false,
..Default::default()
});
config.providers.openai = Some(ProviderConfig {
enabled: false,
..Default::default()
});
config.providers.github = Some(ProviderConfig {
enabled: true,
default_model: Some("Llama-3.3-70B-Instruct".to_string()),
..Default::default()
});
let (name, model) = resolve_provider_from_config(&config);
assert_eq!(name, "GitHub Copilot");
assert_eq!(model, "Llama-3.3-70B-Instruct");
}
#[test]
fn github_help_mentions_copilot_subscription() {
let help = PROVIDERS[2].help_lines.join(" ");
assert!(help.contains("Copilot"));
assert!(help.contains("subscription"));
}
#[test]
fn wizard_github_static_models_empty() {
assert!(PROVIDERS[2].models.is_empty());
}
#[test]
fn github_load_default_models_from_config_example() {
let models = crate::tui::provider_selector::load_default_models("github");
let _ = models;
}
#[test]
fn github_config_models_written_on_apply() {
let github_index: usize = 2;
let writes_models = matches!(github_index, 2 | 5 | 6);
assert!(writes_models);
}
#[test]
fn github_token_persist_path_index_matches() {
let github_index: usize = 2;
assert_eq!(github_index, 2);
}
#[test]
fn wizard_github_model_filter_empty_returns_all() {
let mut wizard = OnboardingWizard::new();
wizard.ps.selected_provider = 2;
wizard.ps.models = vec!["gpt-4o".to_string(), "Llama-3.3-70B-Instruct".to_string()];
wizard.ps.model_filter.clear();
assert_eq!(wizard.ps.filtered_model_names().len(), 2);
}
#[test]
fn wizard_github_model_filter_no_match() {
let mut wizard = OnboardingWizard::new();
wizard.ps.selected_provider = 2;
wizard.ps.models = vec!["gpt-4o".to_string()];
wizard.ps.model_filter = "nonexistent".to_string();
assert!(wizard.ps.filtered_model_names().is_empty());
}
#[test]
fn wizard_github_model_filter_case_insensitive() {
let mut wizard = OnboardingWizard::new();
wizard.ps.selected_provider = 2;
wizard.ps.models = vec!["GPT-4o".to_string(), "Llama-3.3-70B-Instruct".to_string()];
wizard.ps.model_filter = "gpt".to_string();
let filtered = wizard.ps.filtered_model_names();
assert_eq!(filtered.len(), 1);
assert_eq!(filtered[0], "GPT-4o");
}
#[test]
fn wizard_github_model_filter_by_provider_name() {
let mut wizard = OnboardingWizard::new();
wizard.ps.selected_provider = 2;
wizard.ps.models = vec![
"gpt-4o".to_string(),
"gpt-4o-mini".to_string(),
"Llama-3.3-70B-Instruct".to_string(),
"Mistral-Large".to_string(),
];
wizard.ps.model_filter = "llama".to_string();
let filtered = wizard.ps.filtered_model_names();
assert_eq!(filtered.len(), 1);
assert_eq!(filtered[0], "Llama-3.3-70B-Instruct");
}