use std::collections::HashMap;
use terraphim_config::{ConfigBuilder, Haystack, Role, ServiceType};
use terraphim_middleware::indexer::search_haystacks;
use terraphim_types::{RelevanceFunction, SearchQuery};
#[tokio::test]
async fn test_perplexity_config_parsing() {
println!("๐งช Testing Perplexity Configuration");
println!("=====================================");
let mut extra_params = HashMap::new();
extra_params.insert("api_key".to_string(), "test_key_12345".to_string());
extra_params.insert("model".to_string(), "sonar-large-online".to_string());
extra_params.insert("max_tokens".to_string(), "1500".to_string());
extra_params.insert("temperature".to_string(), "0.1".to_string());
extra_params.insert("cache_ttl_hours".to_string(), "2".to_string());
extra_params.insert(
"search_domains".to_string(),
"arxiv.org,github.com".to_string(),
);
extra_params.insert("search_recency".to_string(), "week".to_string());
let haystack = Haystack {
location: "https://api.perplexity.ai".to_string(),
service: ServiceType::Perplexity,
read_only: true,
atomic_server_secret: None,
extra_parameters: extra_params,
fetch_content: false,
};
println!("โ
Haystack configuration created successfully");
assert_eq!(haystack.service, ServiceType::Perplexity);
assert_eq!(haystack.location, "https://api.perplexity.ai");
assert!(haystack.read_only);
assert_eq!(
haystack.extra_parameters.get("api_key"),
Some(&"test_key_12345".to_string())
);
assert_eq!(
haystack.extra_parameters.get("model"),
Some(&"sonar-large-online".to_string())
);
println!("โ
Extra parameters parsed correctly");
println!("โ
Perplexity configuration test passed");
}
#[tokio::test]
async fn test_perplexity_service_type_integration() {
println!("๐งช Testing ServiceType::Perplexity Integration");
println!("===============================================");
let service_type = ServiceType::Perplexity;
match service_type {
ServiceType::Perplexity => {
println!("โ
ServiceType::Perplexity is properly defined");
}
_ => {
panic!("ServiceType::Perplexity should match Perplexity variant");
}
}
let mut extra_params = HashMap::new();
extra_params.insert("api_key".to_string(), "sk-test123".to_string());
extra_params.insert("model".to_string(), "sonar-medium-online".to_string());
let haystack = Haystack {
location: "https://api.perplexity.ai".to_string(),
service: ServiceType::Perplexity,
read_only: true,
atomic_server_secret: None,
extra_parameters: extra_params,
fetch_content: false,
};
assert_eq!(haystack.service, ServiceType::Perplexity);
assert_eq!(haystack.location, "https://api.perplexity.ai");
assert!(haystack.read_only);
println!("โ
Haystack configuration with Perplexity service works correctly");
let role = Role {
shortname: Some("perplexity-test".to_string()),
name: "Perplexity Test".into(),
relevance_function: RelevanceFunction::TitleScorer,
terraphim_it: false,
theme: "superhero".to_string(),
kg: None,
haystacks: vec![haystack],
llm_enabled: false,
llm_api_key: None,
llm_model: None,
llm_auto_summarize: false,
llm_chat_enabled: false,
llm_chat_system_prompt: None,
llm_chat_model: None,
llm_context_window: None,
llm_router_enabled: false,
llm_router_config: None,
extra: ahash::AHashMap::new(),
};
assert_eq!(role.haystacks.len(), 1);
assert_eq!(role.haystacks[0].service, ServiceType::Perplexity);
println!("โ
Role with Perplexity haystack created successfully");
println!("โ
ServiceType::Perplexity integration is complete");
}
#[tokio::test]
async fn test_perplexity_document_format() {
println!("๐งช Testing Perplexity Document Format");
println!("=====================================");
let test_cases = vec![
("Basic config", "sonar-medium-online", None, None),
("Large model", "sonar-large-online", Some("2000"), None),
(
"With domains",
"sonar-small-online",
None,
Some("github.com,arxiv.org"),
),
];
for (name, model, max_tokens, domains) in test_cases {
println!("Testing case: {}", name);
let mut extra_params = HashMap::new();
extra_params.insert("api_key".to_string(), "test_key".to_string());
extra_params.insert("model".to_string(), model.to_string());
if let Some(tokens) = max_tokens {
extra_params.insert("max_tokens".to_string(), tokens.to_string());
}
if let Some(domain_list) = domains {
extra_params.insert("search_domains".to_string(), domain_list.to_string());
}
let haystack = Haystack {
location: "https://api.perplexity.ai".to_string(),
service: ServiceType::Perplexity,
read_only: true,
atomic_server_secret: None,
extra_parameters: extra_params,
fetch_content: false,
};
assert_eq!(haystack.service, ServiceType::Perplexity);
assert!(!haystack.extra_parameters.is_empty());
println!(" โ
{} configuration valid", name);
}
println!("โ
All Perplexity document format tests passed");
}
#[tokio::test]
async fn test_perplexity_missing_api_key() {
println!("๐งช Testing Perplexity Error Handling");
println!("====================================");
let haystack = Haystack {
location: "https://api.perplexity.ai".to_string(),
service: ServiceType::Perplexity,
read_only: true,
atomic_server_secret: None,
extra_parameters: HashMap::new(), fetch_content: false,
};
let role = Role {
shortname: Some("perplexity-test".to_string()),
name: "Perplexity Test".into(),
relevance_function: RelevanceFunction::TitleScorer,
terraphim_it: false,
theme: "superhero".to_string(),
kg: None,
haystacks: vec![haystack],
llm_enabled: false,
llm_api_key: None,
llm_model: None,
llm_auto_summarize: false,
llm_chat_enabled: false,
llm_chat_system_prompt: None,
llm_chat_model: None,
llm_context_window: None,
llm_router_enabled: false,
llm_router_config: None,
extra: ahash::AHashMap::new(),
};
let mut config = ConfigBuilder::new()
.add_role("Perplexity Test", role)
.default_role("Perplexity Test")
.unwrap()
.build()
.unwrap();
let config_state = terraphim_config::ConfigState::new(&mut config)
.await
.expect("config state");
let query = SearchQuery {
search_term: "test query".into(),
search_terms: None,
operator: None,
skip: Some(0),
limit: Some(10),
role: Some("Perplexity Test".into()),
layer: Default::default(),
include_pinned: false,
};
let result = search_haystacks(config_state, query).await;
match result {
Ok(index) => {
println!(
"โ
Graceful degradation: returned {} documents",
index.len()
);
}
Err(e) => {
println!("โ
Error handled: {:?}", e);
}
}
println!("โ
Perplexity error handling test completed");
}
#[tokio::test]
#[ignore]
async fn perplexity_live_api_test() {
dotenvy::dotenv().ok();
let api_key = match std::env::var("PERPLEXITY_API_KEY") {
Ok(key) if !key.trim().is_empty() => key,
_ => {
eprintln!("PERPLEXITY_API_KEY not set; skipping live Perplexity API test");
eprintln!("Set your API key and run: cargo test perplexity_live_api_test -- --ignored");
return;
}
};
println!("๐งช Testing Live Perplexity API");
println!("==============================");
println!(
"Using API key: {}...",
&api_key[..std::cmp::min(8, api_key.len())]
);
let mut extra_params = HashMap::new();
extra_params.insert("api_key".to_string(), api_key);
extra_params.insert("model".to_string(), "sonar-small-online".to_string());
extra_params.insert("max_tokens".to_string(), "500".to_string());
extra_params.insert("temperature".to_string(), "0.1".to_string());
let role = Role {
shortname: Some("perplexity-live".to_string()),
name: "Perplexity Live Test".into(),
relevance_function: RelevanceFunction::TitleScorer,
terraphim_it: false,
theme: "superhero".to_string(),
kg: None,
haystacks: vec![Haystack {
location: "https://api.perplexity.ai".to_string(),
service: ServiceType::Perplexity,
read_only: true,
atomic_server_secret: None,
extra_parameters: extra_params,
fetch_content: false,
}],
llm_enabled: false,
llm_api_key: None,
llm_model: None,
llm_auto_summarize: false,
llm_chat_enabled: false,
llm_chat_system_prompt: None,
llm_chat_model: None,
llm_context_window: None,
llm_router_enabled: false,
llm_router_config: None,
extra: ahash::AHashMap::new(),
};
let mut config = ConfigBuilder::new()
.add_role("Perplexity Live Test", role)
.default_role("Perplexity Live Test")
.unwrap()
.build()
.unwrap();
let config_state = terraphim_config::ConfigState::new(&mut config)
.await
.expect("config state");
let query = SearchQuery {
search_term: "What is Rust programming language?".into(),
search_terms: None,
operator: None,
skip: Some(0),
limit: Some(5),
role: Some("Perplexity Live Test".into()),
layer: Default::default(),
include_pinned: false,
};
println!("Sending query: {}", query.search_term.as_str());
let start_time = std::time::Instant::now();
let result = search_haystacks(config_state, query).await;
let elapsed = start_time.elapsed();
match result {
Ok(index) => {
println!("โ
Live API test successful!");
println!(" Response time: {}ms", elapsed.as_millis());
println!(" Documents returned: {}", index.len());
for (i, (id, doc)) in index.iter().enumerate().take(3) {
println!(" Document {}: {}", i + 1, doc.title);
println!(" ID: {}", id);
println!(" URL: {}", doc.url);
if let Some(description) = &doc.description {
println!(" Description: {}", description);
}
if !doc.body.is_empty() {
let preview = if doc.body.len() > 100 {
format!("{}...", &doc.body[..100])
} else {
doc.body.clone()
};
println!(" Content preview: {}", preview);
}
println!();
}
if !index.is_empty() {
println!("โ
Perplexity API integration working correctly!");
} else {
println!("โ ๏ธ No documents returned - check API key and model");
}
}
Err(e) => {
println!("โ Live API test failed: {:?}", e);
panic!("Live API test should succeed with valid API key");
}
}
}