|
|
|
|
@ -177,6 +177,71 @@ fn parse_llm_url_response(response: &serde_json::Value, domain: &str) -> Vec<Str
|
|
|
|
|
mod tests {
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
/// Set SKIP_SSRF_CHECK for tests using wiremock (localhost).
|
|
|
|
|
fn skip_ssrf_for_test() {
|
|
|
|
|
unsafe { std::env::set_var("SKIP_SSRF_CHECK", "1"); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn search_brave_returns_filtered_urls() {
|
|
|
|
|
skip_ssrf_for_test();
|
|
|
|
|
|
|
|
|
|
let config = SiteSearchConfig {
|
|
|
|
|
domain: "korben.info".to_string(),
|
|
|
|
|
theme: "intelligence artificielle".to_string(),
|
|
|
|
|
max_results: 10,
|
|
|
|
|
max_age_days: 7,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Test error path: Brave with invalid key against real API → returns empty (no panic)
|
|
|
|
|
let provider = SiteSearchProvider::Brave {
|
|
|
|
|
api_key: "invalid-key".to_string(),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let client = reqwest::Client::new();
|
|
|
|
|
let results = search(&client, &config, &provider).await;
|
|
|
|
|
// Will fail against real Brave API but should return empty vec, not panic
|
|
|
|
|
assert!(results.is_empty());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn search_llm_returns_urls_from_mock() {
|
|
|
|
|
let config = SiteSearchConfig {
|
|
|
|
|
domain: "korben.info".to_string(),
|
|
|
|
|
theme: "intelligence artificielle".to_string(),
|
|
|
|
|
max_results: 5,
|
|
|
|
|
max_age_days: 7,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// MockLlmProvider doesn't have a site_search handler, so it will return
|
|
|
|
|
// a classify response which won't parse as a URL array → empty vec
|
|
|
|
|
let mock_provider = crate::services::llm::mock::MockLlmProvider::new();
|
|
|
|
|
|
|
|
|
|
let provider = SiteSearchProvider::Llm {
|
|
|
|
|
provider: Arc::new(mock_provider),
|
|
|
|
|
model: "mock-model".to_string(),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let client = reqwest::Client::new();
|
|
|
|
|
let results = search(&client, &config, &provider).await;
|
|
|
|
|
assert!(results.is_empty());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn build_site_search_prompt_contains_domain_and_theme() {
|
|
|
|
|
let config = SiteSearchConfig {
|
|
|
|
|
domain: "korben.info".to_string(),
|
|
|
|
|
theme: "intelligence artificielle".to_string(),
|
|
|
|
|
max_results: 10,
|
|
|
|
|
max_age_days: 7,
|
|
|
|
|
};
|
|
|
|
|
let prompt = build_site_search_prompt(&config);
|
|
|
|
|
assert!(prompt.contains("korben.info"));
|
|
|
|
|
assert!(prompt.contains("intelligence artificielle"));
|
|
|
|
|
assert!(prompt.contains("10"));
|
|
|
|
|
assert!(prompt.contains("7"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn url_matches_domain_exact() {
|
|
|
|
|
assert!(url_matches_domain("https://korben.info/article", "korben.info"));
|
|
|
|
|
|