unhtml 0.8.0

A magic html parser
Documentation
use crate::{
    scraper::{Html, Selector},
    ElemIter, Element, FromHtml, Result, Text,
};

#[derive(Debug, Eq, PartialEq)]
struct Link {
    href: String,
    text: String,
}

impl FromHtml for Link {
    fn from_elements(select: ElemIter) -> Result<Self> {
        let elements: Vec<_> = select.collect();
        Ok(Self {
            href: elements.clone().into_iter().attr("href")?,
            text: elements.clone().into_iter().inner_text()?,
        })
    }
}

#[test]
fn test_element() {
    let selector = Selector::parse("a").unwrap();
    let html = Html::parse_fragment(
        r##"
        <div>
            <div>
                <a href="https://github.com"> Github </a>
            </div>
            <div>
                <a href="https://www.zjuqsc.com"> ZJU QSC </a>
            </div>
            <a href="https://google.com"> Google </a>
        </div>
    "##,
    );
    assert_eq!(
        Link {
            href: "https://github.com".into(),
            text: "Github".into(),
        },
        html.select(&selector).element().unwrap()
    );
}

#[test]
fn test_vec_element() {
    let selector = Selector::parse("a").unwrap();
    let html = Html::parse_fragment(
        r##"
        <div>
            <div>
                <a href="https://github.com"> Github </a>
            </div>
            <div>
                <a href="https://www.zjuqsc.com"> ZJU QSC </a>
            </div>
            <a href="https://google.com"> Google </a>
        </div>
    "##,
    );

    let actual: Vec<Link> = html.select(&selector).element().unwrap();
    assert_eq!(
        actual,
        vec![
            Link {
                href: "https://github.com".into(),
                text: "Github".into(),
            },
            Link {
                href: "https://www.zjuqsc.com".into(),
                text: "ZJU QSC".into(),
            },
            Link {
                href: "https://google.com".into(),
                text: "Google".into(),
            },
        ]
    );
}

#[test]
fn test_fail_element() {
    let foo_selector = Selector::parse("p").unwrap();
    let html = Html::parse_fragment(
        r##"
        <div>
            <div>
                <a href="https://github.com"> Github </a>
            </div>
            <div>
                <a href="https://www.zjuqsc.com"> ZJU QSC </a>
            </div>
            <a href="https://google.com"> Google </a>
        </div>
    "##,
    );
    let result: Result<Link> = html.select(&foo_selector).element();
    assert!(!result.is_ok());
}

#[test]
fn test_option_element() {
    let selector = Selector::parse("a").unwrap();
    let foo_selector = Selector::parse("p").unwrap();
    let html = Html::parse_fragment(
        r##"
        <div>
            <div>
                <a href="https://github.com"> Github </a>
            </div>
            <div>
                <a href="https://www.zjuqsc.com"> ZJU QSC </a>
            </div>
            <a href="https://google.com"> Google </a>
        </div>
    "##,
    );
    assert_eq!(
        Some(Link {
            href: "https://github.com".into(),
            text: "Github".into(),
        }),
        html.select(&selector).element().unwrap()
    );
    let result: Option<Link> = html.select(&foo_selector).element().unwrap();
    assert_eq!(result, None);
}