use webpage_quality_analyzer::{
analyze, analyze_with_profile,
models::models::{AnalyzeError, QualityBand},
};
const GOOD_HTML: &str = r#"<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Quality Web Page</title>
<meta name="description" content="A well-structured web page with good content and proper SEO.">
</head>
<body>
<h1>Main Heading</h1>
<p>This is a well-written article with multiple paragraphs and good structure.</p>
<h2>Section One</h2>
<p>Content continues here with meaningful text that provides value to readers.</p>
<h3>Subsection</h3>
<ul>
<li>First item</li>
<li>Second item</li>
</ul>
<p>More content with <a href="https://example.com">external links</a> and proper structure.</p>
</body>
</html>"#;
const MINIMAL_HTML: &str = r#"<!DOCTYPE html>
<html>
<head><title>Simple</title></head>
<body><h1>Hello</h1><p>Basic content.</p></body>
</html>"#;
#[tokio::test]
async fn test_basic_analysis() {
let report = analyze("https://example.com/test", Some(GOOD_HTML))
.await
.expect("Analysis failed");
assert_eq!(report.url, "https://example.com/test");
assert!(report.score >= 0.0 && report.score <= 100.0);
assert!(!report.version.is_empty());
assert!(matches!(
report.verdict,
QualityBand::VeryPoor
| QualityBand::Poor
| QualityBand::Fair
| QualityBand::Good
| QualityBand::Excellent
));
}
#[tokio::test]
async fn test_content_metrics() {
let report = analyze("https://example.com/test", Some(GOOD_HTML))
.await
.unwrap();
let html_metrics = &report.metrics.html_analysis;
assert!(html_metrics.content.word_count > 10);
assert!(html_metrics.structure.paragraph_count > 0);
assert!(html_metrics.structure.headings_count > 0);
assert!(html_metrics.seo.title_len > 0);
assert!(html_metrics.content.reading_time_minutes >= 0.0);
assert!(html_metrics.content.content_to_html_ratio > 0.0);
}
#[tokio::test]
async fn test_metadata_extraction() {
let report = analyze("https://example.com/test", Some(GOOD_HTML))
.await
.unwrap();
assert_eq!(report.metadata.title, "Quality Web Page");
assert!(report.metadata.meta_description.is_some());
assert!(report
.metadata
.meta_description
.as_ref()
.unwrap()
.contains("well-structured"));
}
#[tokio::test]
async fn test_html_metrics() {
let report = analyze("https://example.com/test", Some(GOOD_HTML))
.await
.unwrap();
let html_metrics = &report.metrics.html_analysis;
assert!(html_metrics.content.word_count > 10);
assert!(html_metrics.structure.paragraph_count > 0);
assert!(html_metrics.structure.headings_count > 0);
assert!(html_metrics.seo.title_len > 0);
assert!(html_metrics.content.reading_time_minutes >= 0.0);
assert!(html_metrics.content.content_to_html_ratio > 0.0);
}
#[tokio::test]
async fn test_minimal_content() {
let report = analyze("https://example.com/minimal", Some(MINIMAL_HTML))
.await
.unwrap();
assert!(report.score >= 0.0 && report.score <= 100.0);
assert_eq!(report.metadata.title, "Simple");
let html_metrics = &report.metrics.html_analysis;
assert!(html_metrics.content.word_count > 0);
assert!(html_metrics.structure.headings_count > 0);
}
#[tokio::test]
async fn test_different_profiles() {
let url = "https://example.com/test";
let report1 = analyze_with_profile(url, Some(GOOD_HTML), "content_article")
.await
.unwrap();
let report2 = analyze_with_profile(url, Some(GOOD_HTML), "news")
.await
.unwrap();
assert!(report1.score >= 0.0 && report1.score <= 100.0);
assert!(report2.score >= 0.0 && report2.score <= 100.0);
}
#[tokio::test]
async fn test_error_handling() {
let result = analyze("", Some(GOOD_HTML)).await;
assert!(result.is_err());
assert!(matches!(result.unwrap_err(), AnalyzeError::InvalidUrl(_)));
let result =
analyze_with_profile("https://example.com", Some(GOOD_HTML), "invalid_profile").await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_processed_document() {
let report = analyze("https://example.com/test", Some(GOOD_HTML))
.await
.unwrap();
assert!(!report.processed_document.headings.is_empty());
assert!(!report.processed_document.cleaned_text.is_empty());
if !report.processed_document.links.is_empty() {
assert!(report.processed_document.links[0].resolved_href.len() > 0);
assert!(report.processed_document.links[0].raw_href.len() > 0);
}
}
#[tokio::test]
async fn test_quality_bands() {
let good_report = analyze("https://example.com/good", Some(GOOD_HTML))
.await
.unwrap();
let minimal_report = analyze("https://example.com/minimal", Some(MINIMAL_HTML))
.await
.unwrap();
println!(
"Good HTML score: {}, verdict: {:?}",
good_report.score, good_report.verdict
);
println!(
"Minimal HTML score: {}, verdict: {:?}",
minimal_report.score, minimal_report.verdict
);
assert!(good_report.score >= 0.0 && good_report.score <= 100.0);
assert!(minimal_report.score >= 0.0 && minimal_report.score <= 100.0);
if good_report.score >= 90.0 {
assert!(matches!(good_report.verdict, QualityBand::Excellent));
} else if good_report.score >= 70.0 {
assert!(matches!(good_report.verdict, QualityBand::Good));
} else if good_report.score >= 50.0 {
assert!(matches!(good_report.verdict, QualityBand::Fair));
} else if good_report.score >= 30.0 {
assert!(matches!(good_report.verdict, QualityBand::Poor));
} else {
assert!(matches!(good_report.verdict, QualityBand::VeryPoor));
}
if minimal_report.score >= 90.0 {
assert!(matches!(minimal_report.verdict, QualityBand::Excellent));
} else if minimal_report.score >= 70.0 {
assert!(matches!(minimal_report.verdict, QualityBand::Good));
} else if minimal_report.score >= 50.0 {
assert!(matches!(minimal_report.verdict, QualityBand::Fair));
} else if minimal_report.score >= 30.0 {
assert!(matches!(minimal_report.verdict, QualityBand::Poor));
} else {
assert!(matches!(minimal_report.verdict, QualityBand::VeryPoor));
}
}