Skip to content

Commit 6af010b

Browse files
committed
test: Add integration tests for complete provider configuration flow
1 parent ac5f9d1 commit 6af010b

File tree

1 file changed

+247
-0
lines changed

1 file changed

+247
-0
lines changed
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
///! Integration test for Issue #34 - Complete Provider Configuration Integration
2+
///!
3+
///! Tests the complete end-to-end flow:
4+
///! 1. App starts in WaitingForConfig state
5+
///! 2. Settings modal shows provider configuration
6+
///! 3. Async validation works
7+
///! 4. State transitions correctly
8+
///! 5. UI components integrate properly
9+
use agentic::{
10+
events::{AppEvent, AppState},
11+
settings::{AsyncValidationResult, ProviderType, Settings, ValidationEvent, ValidationStatus},
12+
theme::{Theme, ThemeVariant},
13+
ui::app::App,
14+
};
15+
use std::time::Duration;
16+
17+
#[tokio::main]
18+
async fn main() -> Result<(), Box<dyn std::error::Error>> {
19+
println!("🧪 Integration Test: Complete Provider Configuration");
20+
println!("==================================================");
21+
22+
// Test 1: App starts in correct state
23+
test_initial_app_state().await?;
24+
25+
// Test 2: Settings integration
26+
test_settings_integration().await?;
27+
28+
// Test 3: Provider validation result handling
29+
test_provider_validation_handling().await?;
30+
31+
// Test 4: State transitions
32+
test_state_transitions().await?;
33+
34+
// Test 5: Provider configuration components
35+
test_provider_configuration_components().await?;
36+
37+
println!("\n✅ All integration tests passed!");
38+
println!("🎯 Issue #34 Provider Configuration Integration: COMPLETE");
39+
40+
Ok(())
41+
}
42+
43+
async fn test_initial_app_state() -> Result<(), Box<dyn std::error::Error>> {
44+
println!("\n📋 Test 1: Initial App State");
45+
println!("-----------------------------");
46+
47+
let theme = Theme::new(ThemeVariant::EverforestDark);
48+
let app = App::new(theme);
49+
50+
// App should start in WaitingForConfig since no providers are configured
51+
assert_eq!(app.state(), &AppState::WaitingForConfig);
52+
println!("✅ App correctly starts in WaitingForConfig state");
53+
54+
// Provider readiness should be false
55+
assert!(!app.settings().has_valid_provider());
56+
println!("✅ Provider readiness check works correctly");
57+
58+
// Available providers should be empty
59+
assert!(app.settings().get_available_providers().is_empty());
60+
println!("✅ Available providers list is correctly empty");
61+
62+
Ok(())
63+
}
64+
65+
async fn test_settings_integration() -> Result<(), Box<dyn std::error::Error>> {
66+
println!("\n⚙️ Test 2: Settings Integration");
67+
println!("-------------------------------------");
68+
69+
let theme = Theme::new(ThemeVariant::EverforestDark);
70+
let mut app = App::new(theme);
71+
72+
// Test opening settings
73+
app.enter_settings();
74+
assert_eq!(app.state(), &AppState::Settings);
75+
println!("✅ Settings modal opens correctly");
76+
77+
// Check that provider sections exist
78+
let provider_sections = app.settings().get_provider_sections();
79+
assert!(!provider_sections.is_empty());
80+
println!("✅ Provider sections are available in settings");
81+
82+
// Check that both LOCAL and OPENROUTER sections exist
83+
let section_names: Vec<&str> = provider_sections.iter().map(|s| s.title.as_str()).collect();
84+
assert!(section_names.contains(&"LOCAL Provider"));
85+
assert!(section_names.contains(&"OPENROUTER Provider"));
86+
println!("✅ Both LOCAL and OPENROUTER provider sections exist");
87+
88+
// Test closing settings
89+
app.exit_settings();
90+
assert_eq!(app.state(), &AppState::WaitingForConfig);
91+
println!("✅ Settings modal closes correctly, returns to WaitingForConfig");
92+
93+
Ok(())
94+
}
95+
96+
async fn test_provider_validation_handling() -> Result<(), Box<dyn std::error::Error>> {
97+
println!("\n🔄 Test 3: Provider Validation Result Handling");
98+
println!("---------------------------------------------");
99+
100+
let mut settings = Settings::new();
101+
102+
// Check initial state
103+
assert_eq!(
104+
settings.local_provider.validation_status,
105+
ValidationStatus::Unchecked
106+
);
107+
assert_eq!(
108+
settings.openrouter_provider.validation_status,
109+
ValidationStatus::Unchecked
110+
);
111+
println!("✅ Initial provider status is Unchecked");
112+
113+
// Test validation event handling
114+
let validation_event = ValidationEvent::ValidationComplete {
115+
provider: ProviderType::Local,
116+
result: AsyncValidationResult {
117+
status: ValidationStatus::Valid,
118+
message: Some("Connection successful".to_string()),
119+
response_time: Some(Duration::from_millis(250)),
120+
},
121+
};
122+
123+
settings.handle_validation_event(validation_event);
124+
assert_eq!(
125+
settings.local_provider.validation_status,
126+
ValidationStatus::Valid
127+
);
128+
println!("✅ Validation event correctly updates provider status");
129+
130+
// Test provider readiness after validation
131+
assert!(settings.has_valid_provider());
132+
println!("✅ Provider readiness correctly reflects valid provider");
133+
134+
let available = settings.get_available_providers();
135+
assert!(available.contains(&ProviderType::Local));
136+
assert!(!available.contains(&ProviderType::OpenRouter));
137+
println!("✅ Available providers list correctly reflects valid providers");
138+
139+
Ok(())
140+
}
141+
142+
async fn test_state_transitions() -> Result<(), Box<dyn std::error::Error>> {
143+
println!("\n🔄 Test 4: State Transitions");
144+
println!("-----------------------------");
145+
146+
let theme = Theme::new(ThemeVariant::EverforestDark);
147+
let mut app = App::new(theme);
148+
149+
// Initial state should be WaitingForConfig
150+
assert_eq!(app.state(), &AppState::WaitingForConfig);
151+
println!("✅ Initial state: WaitingForConfig");
152+
153+
// Simulate a provider becoming valid
154+
let validation_event = ValidationEvent::ValidationComplete {
155+
provider: ProviderType::Local,
156+
result: AsyncValidationResult {
157+
status: ValidationStatus::Valid,
158+
message: Some("Connection successful".to_string()),
159+
response_time: Some(Duration::from_millis(150)),
160+
},
161+
};
162+
163+
app.update_provider_status(validation_event);
164+
// State should transition to Main
165+
assert_eq!(app.state(), &AppState::Main);
166+
println!("✅ State correctly transitions to Main when provider becomes valid");
167+
168+
// Simulate provider becoming invalid
169+
let invalid_event = ValidationEvent::ValidationComplete {
170+
provider: ProviderType::Local,
171+
result: AsyncValidationResult {
172+
status: ValidationStatus::Invalid,
173+
message: Some("Connection failed".to_string()),
174+
response_time: Some(Duration::from_millis(5000)),
175+
},
176+
};
177+
178+
app.update_provider_status(invalid_event);
179+
// State should transition back to WaitingForConfig
180+
assert_eq!(app.state(), &AppState::WaitingForConfig);
181+
println!(
182+
"✅ State correctly transitions back to WaitingForConfig when provider becomes invalid"
183+
);
184+
185+
Ok(())
186+
}
187+
188+
async fn test_provider_configuration_components() -> Result<(), Box<dyn std::error::Error>> {
189+
println!("\n🎯 Test 5: Provider Configuration Components");
190+
println!("--------------------------------------------");
191+
192+
let settings = Settings::new();
193+
194+
// Test provider status summary
195+
let status_summary = settings.get_provider_status_summary();
196+
assert_eq!(status_summary.len(), 2); // LOCAL and OPENROUTER
197+
println!("✅ Provider status summary includes both providers");
198+
199+
// Check initial status icons in provider sections
200+
let provider_sections = settings.get_provider_sections();
201+
for section in &provider_sections {
202+
assert_eq!(section.status_icon, "⚪"); // Unchecked
203+
}
204+
println!("✅ Initial status icons show unchecked state (⚪)");
205+
206+
// Test field structure for LOCAL provider
207+
let local_section = provider_sections
208+
.iter()
209+
.find(|s| s.title == "LOCAL Provider")
210+
.expect("LOCAL Provider section should exist");
211+
212+
assert!(!local_section.fields.is_empty());
213+
let _endpoint_field = local_section
214+
.fields
215+
.iter()
216+
.find(|f| f.label.contains("Endpoint"))
217+
.expect("Endpoint field should exist");
218+
219+
println!("✅ LOCAL provider has endpoint configuration field");
220+
221+
// Test field structure for OPENROUTER provider
222+
let openrouter_section = provider_sections
223+
.iter()
224+
.find(|s| s.title == "OPENROUTER Provider")
225+
.expect("OPENROUTER Provider section should exist");
226+
227+
assert!(!openrouter_section.fields.is_empty());
228+
let _api_key_field = openrouter_section
229+
.fields
230+
.iter()
231+
.find(|f| f.label.contains("API Key"))
232+
.expect("API Key field should exist");
233+
234+
println!("✅ OPENROUTER provider has API key configuration field");
235+
236+
// Test API key masking functionality
237+
let test_key = "sk-or-v1-1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef00e";
238+
let masked = agentic::settings::mask_api_key(test_key);
239+
assert!(masked.starts_with("sk-or-v1-"));
240+
assert!(masked.ends_with("00e"));
241+
assert!(masked.contains("***"));
242+
println!("✅ API key masking works correctly");
243+
244+
println!("\n🎉 All provider configuration components verified!");
245+
246+
Ok(())
247+
}

0 commit comments

Comments
 (0)