use std::fs;
use webpage_quality_analyzer::test_fixtures::*;
#[tokio::test]
async fn test_level1_api_simple_analyze() {
let result = webpage_quality_analyzer::analyze(
"https://example.com/test-page",
Some(COMPREHENSIVE_HTML),
)
.await;
assert!(
result.is_ok(),
"Level 1 API should work with comprehensive HTML"
);
let report = result.unwrap();
assert!(
report.score >= 0.0 && report.score <= 100.0,
"Score should be between 0-100"
);
assert_eq!(report.url, "https://example.com/test-page");
assert_eq!(report.metadata.title, "Test Page");
assert!(
report.metadata.meta_description.is_some(),
"Should extract meta description"
);
}
#[tokio::test]
async fn test_level2_api_with_profiles() {
let profiles = ["content_article", "news", "product", "portfolio"];
for profile in &profiles {
let result = webpage_quality_analyzer::analyze_with_profile(
"https://example.com/test-page",
Some(COMPREHENSIVE_HTML),
profile,
)
.await;
assert!(
result.is_ok(),
"Level 2 API should work with profile: {} - Error: {:?}",
profile,
result.as_ref().err()
);
let report = result.unwrap();
assert!(report.score >= 0.0 && report.score <= 100.0);
println!(
"Profile {}: Score = {:.1}, Verdict = {}",
profile, report.score, report.verdict
);
}
}
#[tokio::test]
async fn test_level2_api_invalid_profile() {
let result = webpage_quality_analyzer::analyze_with_profile(
"https://example.com/test-page",
Some(COMPREHENSIVE_HTML),
"nonexistent_profile",
)
.await;
assert!(result.is_err(), "Should fail with invalid profile");
}
#[tokio::test]
async fn test_level3_api_config_file() {
let config_content = r#"
active_profile: "test_profile"
presets:
test_profile:
metadata:
name: "Test Profile"
description: "Test configuration profile"
target_content_types: ["article", "blog"]
version: "1.0.0"
author: "test"
created_at: "2025-01-01T00:00:00Z"
tags: ["test"]
category_weights:
content: 0.5
structure: 0.3
seo: 0.2
technical: 0.0
media: 0.0
links: 0.0
accessibility: 0.0
mobile: 0.0
authority: 0.0
language: 0.0
forms: 0.0
structureddata: 0.0
branding: 0.0
userexperience: 0.0
business: 0.0
internationalization: 0.0
performance: 0.0
security: 0.0
analytics: 0.0
errorhandling: 0.0
metric_overrides: {}
content_expectations:
min_word_count: 50
min_paragraph_count: 2
min_heading_count: 1
expected_heading_structure: []
min_main_text_ratio: 0.1
min_image_alt_coverage: 0.7
required_meta_tags: []
recommended_meta_tags: []
quality_bands:
excellent: 85.0
good: 65.0
fair: 45.0
poor: 25.0
penalties:
severe_penalties: {}
moderate_penalties: {}
light_penalties: {}
bonuses:
excellence_bonuses: {}
achievement_bonuses: {}
synergy_bonuses: {}
output:
verbosity: "normal"
include_metadata: true
include_processed_document: false
include_debug: false
include_raw_metrics: false
timestamp_format: "ISO8601"
float_precision: 2
"#;
let config_path = "test_config.yaml";
fs::write(config_path, config_content).expect("Should write config file");
let result = webpage_quality_analyzer::from_config_file(config_path);
if let Err(ref e) = result {
println!("Config file loading error: {:?}", e);
}
assert!(result.is_ok(), "Level 3 API should load config file");
let analyzer = result.unwrap();
let analysis_result = analyzer
.run("https://example.com/test-page", Some(COMPREHENSIVE_HTML))
.await;
if let Err(ref e) = analysis_result {
println!("Analysis error: {:?}", e);
}
assert!(
analysis_result.is_ok(),
"Analysis should succeed with custom config"
);
let report = analysis_result.unwrap();
assert!(report.score >= 0.0 && report.score <= 100.0);
let _ = fs::remove_file(config_path);
}
#[test]
fn test_level3_api_nonexistent_config() {
let result = webpage_quality_analyzer::from_config_file("nonexistent_config.yaml");
assert!(result.is_err(), "Should fail with nonexistent config file");
}
#[tokio::test]
async fn test_error_handling_malformed_html() {
let malformed_html = MALFORMED_HTML;
let result =
webpage_quality_analyzer::analyze("https://example.com/malformed", Some(malformed_html))
.await;
assert!(result.is_ok(), "Should handle malformed HTML gracefully");
let report = result.unwrap();
assert!(report.score >= 0.0 && report.score <= 100.0);
}
#[tokio::test]
async fn test_minimal_html() {
let minimal_html = MINIMAL_HTML;
let result =
webpage_quality_analyzer::analyze("https://example.com/minimal", Some(minimal_html)).await;
assert!(result.is_ok(), "Should handle minimal HTML");
let report = result.unwrap();
assert!(report.score >= 0.0 && report.score <= 100.0);
assert!(report.score < 80.0, "Minimal HTML should have lower score");
}
#[tokio::test]
async fn test_empty_html() {
let result = webpage_quality_analyzer::analyze("https://example.com/empty", Some("")).await;
assert!(result.is_ok(), "Should handle empty HTML");
let report = result.unwrap();
assert!(report.score >= 0.0 && report.score <= 100.0);
assert!(report.score < 50.0, "Empty HTML should have very low score");
}
#[tokio::test]
async fn test_profile_comparison() {
let profiles = ["content_article", "news", "product", "portfolio"];
let mut results = Vec::new();
for profile in &profiles {
let result = webpage_quality_analyzer::analyze_with_profile(
"https://example.com/comparison",
Some(COMPREHENSIVE_HTML),
profile,
)
.await;
assert!(
result.is_ok(),
"Profile {} should work - Error: {:?}",
profile,
result.as_ref().err()
);
results.push((profile, result.unwrap()));
}
for (profile, report) in &results {
assert!(report.score >= 0.0 && report.score <= 100.0);
println!("Profile {}: Score = {:.1}", profile, report.score);
}
let scores: Vec<f32> = results.iter().map(|(_, report)| report.score).collect();
assert!(scores.len() == 4, "Should have 4 profile results");
}