rust_scrapling 0.4.0

A Rust port of Scrapling - modern web scraping framework with CSS selectors, async HTTP, and spider-based crawling
Documentation
use rust_scrapling::spiders::request::SpiderRequest;

#[test]
fn test_basic_creation() {
    let req = SpiderRequest::new("https://example.com/page");
    assert_eq!(req.url(), "https://example.com/page");
    assert_eq!(req.method(), "GET");
    assert_eq!(req.priority(), 0);
    assert!(!req.dont_filter());
    assert_eq!(req.retry_count(), 0);
    assert!(req.callback_name().is_none());
    assert!(req.body().is_none());
    assert!(!req.fingerprint().is_empty());
}

#[test]
fn test_builder() {
    let req = SpiderRequest::builder("https://example.com")
        .method("POST")
        .priority(5)
        .session_id("sess1")
        .callback("parse_item")
        .dont_filter(true)
        .header("Accept", "text/html")
        .body("{\"key\":\"value\"}")
        .meta("depth", serde_json::json!(2))
        .build();

    assert_eq!(req.method(), "POST");
    assert_eq!(req.priority(), 5);
    assert_eq!(req.session_id(), "sess1");
    assert_eq!(req.callback_name(), Some("parse_item"));
    assert!(req.dont_filter());
    assert_eq!(req.headers().get("Accept").unwrap(), "text/html");
    assert_eq!(req.body(), Some("{\"key\":\"value\"}"));
    assert_eq!(req.meta("depth"), Some(&serde_json::json!(2)));
}

#[test]
fn test_fingerprint_equality() {
    let r1 = SpiderRequest::new("https://example.com/page");
    let r2 = SpiderRequest::new("https://example.com/page");
    assert_eq!(r1, r2);
    assert_eq!(r1.fingerprint(), r2.fingerprint());
}

#[test]
fn test_fingerprint_inequality() {
    let r1 = SpiderRequest::new("https://example.com/page1");
    let r2 = SpiderRequest::new("https://example.com/page2");
    assert_ne!(r1, r2);
    assert_ne!(r1.fingerprint(), r2.fingerprint());
}

#[test]
fn test_copy() {
    let req = SpiderRequest::new("https://example.com");
    let copy = req.copy();
    assert_eq!(req, copy);
    assert_eq!(req.url(), copy.url());
}

#[test]
fn test_domain() {
    let req = SpiderRequest::new("https://www.example.com/path?q=1");
    assert_eq!(req.domain(), Some("www.example.com".to_string()));
}

#[test]
fn test_ordering() {
    let low = SpiderRequest::builder("https://example.com/low")
        .priority(1)
        .build();
    let high = SpiderRequest::builder("https://example.com/high")
        .priority(10)
        .build();
    assert!(high > low);
}

#[test]
fn test_ord_consistent_with_partial_eq_for_same_priority_different_fingerprint() {
    // Ord's contract requires a == b iff a.cmp(b) == Equal. Two requests with
    // the same priority but different URLs (hence different fingerprints)
    // are not PartialEq-equal, so cmp must not report them Equal either —
    // it previously compared only priority, breaking the contract.
    use std::cmp::Ordering;
    let a = SpiderRequest::builder("https://example.com/a")
        .priority(1)
        .build();
    let b = SpiderRequest::builder("https://example.com/b")
        .priority(1)
        .build();
    assert_ne!(a, b);
    assert_ne!(a.cmp(&b), Ordering::Equal);
    // Priority still dominates the comparison.
    assert_eq!(a.cmp(&b), a.fingerprint().cmp(b.fingerprint()));
}

#[test]
fn test_ord_equal_only_for_equal_requests() {
    use std::cmp::Ordering;
    let a = SpiderRequest::builder("https://example.com/same")
        .priority(3)
        .build();
    let b = SpiderRequest::builder("https://example.com/same")
        .priority(3)
        .build();
    assert_eq!(a, b);
    assert_eq!(a.cmp(&b), Ordering::Equal);
}

#[test]
fn test_meta() {
    let mut req = SpiderRequest::new("https://example.com");
    assert!(req.meta("key").is_none());
    req.set_meta("key", serde_json::json!("value"));
    assert_eq!(req.meta("key"), Some(&serde_json::json!("value")));
}

#[test]
fn test_setters() {
    let mut req = SpiderRequest::new("https://example.com");
    req.set_dont_filter(true);
    assert!(req.dont_filter());
    req.set_session_id("abc");
    assert_eq!(req.session_id(), "abc");
    req.increment_retry();
    assert_eq!(req.retry_count(), 1);
    req.increment_retry();
    assert_eq!(req.retry_count(), 2);
}

#[test]
fn test_priority_values() {
    let r1 = SpiderRequest::builder("https://a.com").priority(-5).build();
    let r2 = SpiderRequest::builder("https://b.com").priority(0).build();
    let r3 = SpiderRequest::builder("https://c.com").priority(5).build();
    assert!(r3 > r2);
    assert!(r2 > r1);
}