parsoid 0.10.1

Wrapper around Parsoid HTML that provides convenient accessors for processing and manipulation
Documentation
// SPDX-FileCopyrightText: 2024 Kunal Mehta <legoktm@debian.org>
// SPDX-License-Identifier: GPL-3.0-or-later
use crate::prelude::*;
use crate::tests::test_client;
use anyhow::Result;
use std::collections::HashMap;

#[tokio::test]
async fn test_refs() -> Result<()> {
    let client = test_client::testwp_client();
    let code = client.get("Mwbot-rs/Cite").await?.into_mutable();
    let ref_links = code.filter_reference_links();
    dbg!(&ref_links);
    assert_eq!(
        ref_links.len(),
        code.descendants()
            .filter_map(|node| node.as_reference_link())
            .count()
    );

    let all_refs: HashMap<_, _> = code
        .filter_references()
        .into_iter()
        .map(|ref_| (ref_.id(), ref_))
        .collect();
    assert_eq!(
        all_refs.len(),
        code.descendants()
            .filter_map(|node| node.as_reference())
            .count()
    );

    assert_eq!(ref_links.len(), 4);
    // refs[0] == <ref>This is a [[reference]].</ref>
    assert_eq!(ref_links[0].group()?, None);
    assert_eq!(ref_links[0].name()?, None);
    assert_eq!(ref_links[0].text_contents(), "[1]");
    assert_eq!(
        ref_links[0].reference_id()?,
        "mw-reference-text-cite_note-1"
    );
    assert_eq!(ref_links[0].id(), "cite_ref-1");
    assert_eq!(
        all_refs
            .get(&ref_links[0].reference_id()?)
            .unwrap()
            .contents()
            .text_contents(),
        "This is a reference."
    );
    assert_eq!(ref_links[1].name()?, Some("foo".to_string()));
    assert_eq!(
        ref_links[1].reference_id()?,
        "mw-reference-text-cite_note-foo-2"
    );
    assert_eq!(ref_links[1].id(), "cite_ref-foo_2-0");
    // first use of the reference, so it isn't reused
    assert!(!ref_links[1].is_reused()?);
    assert_eq!(
        all_refs
            .get(&ref_links[1].reference_id()?)
            .unwrap()
            .contents()
            .text_contents(),
        "Named reference."
    );
    assert_eq!(ref_links[2].name()?, Some("foo".to_string()));
    assert_eq!(
        ref_links[2].reference_id()?,
        "mw-reference-text-cite_note-foo-2"
    );
    assert_eq!(ref_links[2].id(), "cite_ref-foo_2-1");
    // second use of it, so it is reused
    assert!(ref_links[2].is_reused()?);
    assert_eq!(
        all_refs
            .get(&ref_links[2].reference_id()?)
            .unwrap()
            .contents()
            .text_contents(),
        "Named reference."
    );
    assert_eq!(ref_links[3].group()?, Some("group".to_string()));
    assert_eq!(
        ref_links[3].reference_id()?,
        "mw-reference-text-cite_note-bar-3"
    );
    assert_eq!(ref_links[3].id(), "cite_ref-bar_3-0");
    assert_eq!(
        all_refs
            .get(&ref_links[3].reference_id()?)
            .unwrap()
            .contents()
            .text_contents(),
        "reference!"
    );

    ref_links[0].set_group("new-group".to_string())?;
    let wikitext = client.transform_to_wikitext(&code).await?;
    dbg!(&wikitext);
    assert!(&wikitext
        .contains("<ref group=\"new-group\">This is a [[reference]].</ref>"));

    Ok(())
}

/// Verify you can edit a template inside a <ref> node
#[tokio::test]
async fn test_mutablity() -> Result<()> {
    let client = test_client::testwp_client();
    let code = client.get("Mwbot-rs/Cite").await?.into_mutable();
    let refs_ = code.filter_references();
    let temps = refs_[0].filter_templates()?;
    dbg!(&refs_[0]);
    temps[0].set_param("2", "a second value")?;

    let wikitext = client.transform_to_wikitext(&code).await?;
    dbg!(&wikitext);
    assert!(wikitext.contains("{{1x|reference!|a second value}}"));
    Ok(())
}

#[tokio::test]
async fn test_reference_lists() -> Result<()> {
    let client = test_client::testwp_client();
    let code = client.get("Mwbot-rs/Cite").await?.into_mutable();

    let lists = code.filter_reference_lists();
    assert_eq!(
        lists.len(),
        code.descendants()
            .filter_map(|node| node.as_reference_list())
            .count()
    );

    dbg!(&lists);
    assert_eq!(lists.len(), 2);

    assert_eq!(lists[0].group()?, Some("group".to_string()));
    assert!(lists[1].is_auto_generated()?);
    Ok(())
}