webpage_quality_analyzer 1.0.2

High-performance webpage quality analyzer with 115 comprehensive metrics - Rust library with WASM, C++, and Python bindings
Documentation
use webpage_quality_analyzer::{analyze, test_fixtures::*};

#[tokio::test]
async fn test_concurrent_analysis() {
    let html = MINIMAL_HTML.to_string();

    // Use join_all instead of tokio::spawn to avoid Send issues
    let futures: Vec<_> = (0..10)
        .map(|i| {
            let html = html.clone();
            let url = format!("https://example.com/concurrent-{}", i);
            async move { analyze(&url, Some(&html)).await }
        })
        .collect();

    let results = futures::future::join_all(futures).await;

    for result in results {
        assert!(result.is_ok());
        let report = result.unwrap();
        assert!(report.score >= 0.0 && report.score <= 100.0);
    }
}

#[tokio::test]
async fn test_analyzer_reuse() {
    let html1 = MINIMAL_HTML;
    let html2 = BASIC_HTML;

    // Test that the same analyzer can be used multiple times
    let report1 = analyze("https://example.com/first", Some(html1))
        .await
        .unwrap();
    let report2 = analyze("https://example.com/second", Some(html2))
        .await
        .unwrap();

    assert_eq!(report1.metadata.title, "Minimal");
    assert_eq!(report2.metadata.title, "Test Page");
    assert!(report1.score >= 0.0 && report1.score <= 100.0);
    assert!(report2.score >= 0.0 && report2.score <= 100.0);
}

#[tokio::test]
async fn test_different_profiles_same_content() {
    let html = r#"<!DOCTYPE html>
<html><head><title>Profile Test</title></head>
<body>
    <h1>Main Heading</h1>
    <p>This is test content for comparing different scoring profiles.</p>
    <h2>Section</h2>
    <p>More content with <a href="https://example.com">external link</a>.</p>
</body></html>"#;

    // Test with default profile
    let report1 = analyze("https://example.com/profile-test", Some(html))
        .await
        .unwrap();

    // All should produce valid scores
    assert!(report1.score >= 0.0 && report1.score <= 100.0);

    println!("Score: {:.2}", report1.score);
}

#[tokio::test]
async fn test_thread_safety() {
    let html = r#"<!DOCTYPE html>
<html><head><title>Thread Safety Test</title></head>
<body><h1>Test</h1><p>Thread safety content.</p></body></html>"#
        .to_string();

    // Use join_all instead of tokio::spawn to avoid Send issues
    let futures: Vec<_> = (0..5)
        .map(|i| {
            let html = html.clone();
            let url = format!("https://example.com/thread-{}", i);
            async move { analyze(&url, Some(&html)).await }
        })
        .collect();

    let results = futures::future::join_all(futures).await;

    for result in results {
        assert!(result.is_ok());
        let report = result.unwrap();
        assert!(report.score >= 0.0 && report.score <= 100.0);
    }
}

#[tokio::test]
async fn test_memory_efficiency() {
    // Test that analyzing many documents doesn't cause memory issues

    for i in 0..100 {
        let html = format!(
            r#"<!DOCTYPE html>
<html><head><title>Memory Test {}</title></head>
<body><h1>Document {}</h1><p>Content for memory efficiency testing.</p></body></html>"#,
            i, i
        );

        let url = format!("https://example.com/memory-{}", i);
        let report = analyze(&url, Some(&html)).await.unwrap();

        assert!(report.score >= 0.0 && report.score <= 100.0);
        assert_eq!(report.metadata.title, format!("Memory Test {}", i));
    }
}