webpage_quality_analyzer 1.0.2

High-performance webpage quality analyzer with 115 comprehensive metrics - Rust library with WASM, C++, and Python bindings
Documentation
//! Test Suite for 07: WASM API
//!
//! Tests WASM bindings functionality
//!
//! Note: These tests run in WASM mode using wasm-bindgen-test
//! Run with: wasm-pack test --headless --firefox

#![cfg(target_arch = "wasm32")]

use wasm_bindgen_test::*;
use webpage_quality_analyzer::wasm::*;

wasm_bindgen_test_configure!(run_in_browser);

const TEST_HTML: &str = r#"<!DOCTYPE html>
<html lang="en">
<head>
    <title>WASM Test Page</title>
    <meta name="description" content="Testing WASM bindings">
</head>
<body>
    <h1>Main Heading</h1>
    <p>This is test content for WASM API testing.</p>
    <p>Second paragraph with more content.</p>
</body>
</html>"#;

/// Test 1: WasmAnalyzer constructor
#[wasm_bindgen_test]
fn test_wasm_analyzer_new() {
    let analyzer = WasmAnalyzer::new();
    assert!(analyzer.is_ok(), "WasmAnalyzer::new() should succeed");
}

/// Test 2: WasmAnalyzer with_config
#[wasm_bindgen_test]
fn test_wasm_analyzer_with_config() {
    let analyzer = WasmAnalyzer::with_config(Some("general".to_string()), Some(true), Some(true));
    assert!(
        analyzer.is_ok(),
        "WasmAnalyzer::with_config() should succeed"
    );
}

/// Test 3: Analyze HTML
#[wasm_bindgen_test]
async fn test_wasm_analyze() {
    let analyzer = WasmAnalyzer::new().unwrap();
    let result = analyzer.analyze(TEST_HTML.to_string()).await;
    assert!(result.is_ok(), "analyze() should succeed");
}

/// Test 4: Analyze with URL
#[wasm_bindgen_test]
async fn test_wasm_analyze_with_url() {
    let analyzer = WasmAnalyzer::new().unwrap();
    let result = analyzer
        .analyze_with_url(
            "https://example.com/test".to_string(),
            TEST_HTML.to_string(),
        )
        .await;
    assert!(result.is_ok(), "analyze_with_url() should succeed");
}

/// Test 5: Get available profiles
#[wasm_bindgen_test]
fn test_wasm_get_available_profiles() {
    let profiles = WasmAnalyzer::get_available_profiles();
    assert!(profiles.len() >= 8, "Should have at least 8 profiles");
    assert!(profiles.contains(&"general".to_string()));
    assert!(profiles.contains(&"content_article".to_string()));
    assert!(profiles.contains(&"news".to_string()));
}

/// Test 6: Get version
#[wasm_bindgen_test]
fn test_wasm_get_version() {
    let version = WasmAnalyzer::get_version();
    assert!(!version.is_empty(), "Version should not be empty");
    assert!(version.contains('.'), "Version should have format X.Y.Z");
}

/// Test 7: WasmBatchAnalyzer
#[wasm_bindgen_test]
fn test_wasm_batch_analyzer_new() {
    let batch_analyzer = WasmBatchAnalyzer::new();
    assert!(
        batch_analyzer.is_ok(),
        "WasmBatchAnalyzer::new() should succeed"
    );
}

/// Test 8: WasmFieldSelector
#[wasm_bindgen_test]
fn test_wasm_field_selector() {
    let _selector = WasmFieldSelector::new()
        .include_fields(vec!["score".to_string(), "url".to_string()])
        .exclude_fields(vec!["metadata".to_string()]);

    // If we got here without panic, the builder pattern works
    assert!(true, "WasmFieldSelector builder should work");
}

/// Test 9: WasmAnalyzerBuilder
#[wasm_bindgen_test]
fn test_wasm_analyzer_builder() {
    let builder = WasmAnalyzerBuilder::new()
        .with_profile("news".to_string())
        .enable_nlp(true)
        .add_report(true);

    let analyzer = builder.build();
    assert!(
        analyzer.is_ok(),
        "WasmAnalyzerBuilder should build successfully"
    );
}

/// Test 10: Builder with metric customization
#[wasm_bindgen_test]
fn test_wasm_builder_metric_customization() {
    let builder = WasmAnalyzerBuilder::new()
        .enable_metric("word_count".to_string())
        .disable_metric("some_metric".to_string())
        .set_metric_weight("title_length".to_string(), 2.0);

    let analyzer = builder.build();
    assert!(
        analyzer.is_ok(),
        "Builder with metric customization should work"
    );
}

/// Test 11: Penalties - Below threshold
#[wasm_bindgen_test]
fn test_wasm_penalties_below() {
    let analyzer = WasmAnalyzerBuilder::new()
        .with_profile("general".to_string())
        .add_penalty_below(
            "short_content".to_string(),
            "word_count".to_string(),
            100.0,
            10.0,
            "Too short".to_string(),
        )
        .build();

    assert!(analyzer.is_ok(), "add_penalty_below should work");
}

/// Test 12: Bonuses - Above threshold
#[wasm_bindgen_test]
fn test_wasm_bonuses_above() {
    let analyzer = WasmAnalyzerBuilder::new()
        .with_profile("general".to_string())
        .add_bonus_above(
            "long_content".to_string(),
            "word_count".to_string(),
            500.0,
            5.0,
            "Long content".to_string(),
        )
        .build();

    assert!(analyzer.is_ok(), "add_bonus_above should work");
}

/// Test 13: Config loading - JSON
#[wasm_bindgen_test]
fn test_wasm_config_json() {
    let config = r#"{"analyzer": {"profile": "general"}}"#;
    let analyzer = WasmAnalyzerBuilder::from_config_json(config);
    assert!(analyzer.is_ok(), "from_config_json should work");
}

/// Test 14: Config loading - YAML
#[wasm_bindgen_test]
fn test_wasm_config_yaml() {
    let config = "analyzer:\n  profile: news\n";
    let analyzer = WasmAnalyzerBuilder::from_config_yaml(config);
    assert!(analyzer.is_ok(), "from_config_yaml should work");
}

/// Test 15: Config loading - TOML
#[wasm_bindgen_test]
fn test_wasm_config_toml() {
    let config = "[analyzer]\nprofile = \"content_article\"\n";
    let analyzer = WasmAnalyzerBuilder::from_config_toml(config);
    assert!(analyzer.is_ok(), "from_config_toml should work");
}

/// Test 16: All profiles work
#[wasm_bindgen_test]
async fn test_wasm_all_profiles() {
    let profiles = vec![
        "content_article",
        "news",
        "product",
        "homepage",
        "portfolio",
        "login_page",
        "general",
        "blog",
    ];

    for profile in profiles {
        let analyzer =
            WasmAnalyzer::with_config(Some(profile.to_string()), Some(false), Some(false)).unwrap();

        let result = analyzer.analyze(TEST_HTML.to_string()).await;
        assert!(result.is_ok(), "Profile {} should work", profile);
    }
}

/// Test 17: Builder chaining
#[wasm_bindgen_test]
fn test_wasm_builder_chaining() {
    let analyzer = WasmAnalyzerBuilder::new()
        .with_profile("news".to_string())
        .enable_nlp(true)
        .add_report(true)
        .set_metric_weight("word_count".to_string(), 1.5)
        .add_penalty_below(
            "short_content".to_string(),
            "word_count".to_string(),
            50.0,
            5.0,
            "Too short".to_string(),
        )
        .add_bonus_above(
            "good_length".to_string(),
            "word_count".to_string(),
            500.0,
            5.0,
            "Good length".to_string(),
        )
        .build();

    assert!(analyzer.is_ok(), "Complex builder chain should work");
}

/// Test 18: Error handling - invalid profile
#[wasm_bindgen_test]
fn test_wasm_error_invalid_profile() {
    let analyzer = WasmAnalyzer::with_config(
        Some("nonexistent_profile".to_string()),
        Some(false),
        Some(false),
    );
    assert!(analyzer.is_err(), "Invalid profile should fail");
}

/// Test 19: Batch analysis
#[wasm_bindgen_test]
async fn test_wasm_batch_analysis() {
    let batch_analyzer = WasmBatchAnalyzer::new().unwrap();

    let html_docs = vec![TEST_HTML.to_string(), TEST_HTML.to_string()];

    let result = batch_analyzer.analyze_batch(html_docs).await;
    assert!(result.is_ok(), "Batch analysis should succeed");

    let batch_result = result.unwrap();
    assert_eq!(batch_result.get_count(), 2, "Should analyze 2 documents");
}

/// Test 20: Field selection with analyze
#[wasm_bindgen_test]
async fn test_wasm_analyze_with_fields() {
    let analyzer = WasmAnalyzer::new().unwrap();
    let fields = vec!["score".to_string(), "url".to_string()];

    let result = analyzer
        .analyze_with_fields(TEST_HTML.to_string(), fields)
        .await;
    assert!(result.is_ok(), "analyze_with_fields should succeed");
}

/// Test 21: Field selector with analyze
#[wasm_bindgen_test]
async fn test_wasm_analyze_with_selector() {
    let analyzer = WasmAnalyzer::new().unwrap();
    let selector =
        WasmFieldSelector::new().include_fields(vec!["score".to_string(), "verdict".to_string()]);

    let result = analyzer
        .analyze_with_selector(TEST_HTML.to_string(), &selector)
        .await;
    assert!(result.is_ok(), "analyze_with_selector should succeed");
}

/// Final verification: All WASM features work
#[wasm_bindgen_test]
async fn test_wasm_final_verification() {
    web_sys::console::log_1(&"=== WASM API Final Verification ===".into());

    // 1. Basic analyzer
    let analyzer = WasmAnalyzer::new().unwrap();
    let _result1 = analyzer.analyze(TEST_HTML.to_string()).await.unwrap();
    web_sys::console::log_1(&"✅ Basic analyzer works".into());

    // 2. Builder pattern
    let analyzer2 = WasmAnalyzerBuilder::new()
        .with_profile("news".to_string())
        .build()
        .unwrap();
    let _result2 = analyzer2.analyze(TEST_HTML.to_string()).await.unwrap();
    web_sys::console::log_1(&"✅ Builder pattern works".into());

    // 3. Config loading
    let analyzer3 =
        WasmAnalyzerBuilder::from_config_json(r#"{"analyzer": {"profile": "general"}}"#).unwrap();
    let _result3 = analyzer3.analyze(TEST_HTML.to_string()).await.unwrap();
    web_sys::console::log_1(&"✅ Config loading works".into());

    // 4. Batch processing
    let batch = WasmBatchAnalyzer::new().unwrap();
    let _batch_result = batch
        .analyze_batch(vec![TEST_HTML.to_string()])
        .await
        .unwrap();
    web_sys::console::log_1(&"✅ Batch processing works".into());

    // 5. Field selection
    let selector = WasmFieldSelector::new().include_fields(vec!["score".to_string()]);
    let _result5 = analyzer
        .analyze_with_selector(TEST_HTML.to_string(), &selector)
        .await
        .unwrap();
    web_sys::console::log_1(&"✅ Field selection works".into());

    web_sys::console::log_1(&"=== ✅ ALL WASM FEATURES VERIFIED ===".into());
}