cargo-sync-rdme 0.8.0

Cargo subcommand to synchronize README with crate documentation
//! Integration test to ensure that the generated links match the links generated by rustdoc across different Rust toolchains.

use std::{fs::File, io::Write as _};

use indoc::formatdoc;
use rstest::rstest;
use similar_asserts::assert_eq;
use test_helper::{
    self as helper, SPAN_END_MARKER, SPAN_START_MARKER, Workspace, rewrite_stdlib_urls,
};

#[rstest]
#[case::stable("stable", "std::fmt::Result")]
#[case::older_stable("1.90.0", "std::fmt::Result")]
#[case::beta("beta", "std::fmt::Result")]
#[case::nightly("nightly", "std::fmt::Result")]
fn generated_links_match_rustdoc(
    #[case] toolchain: &'static str,
    #[case] label: &str,
    #[values("version", "channel", "as-is")] standard_library_url_mode: &'static str,
) {
    let crate_name = "empty";
    let workspace = Workspace::from_fixture(crate_name);
    let readme_path = workspace
        .metadata()
        .root_package()
        .unwrap()
        .readme()
        .unwrap();
    let rustdoc_html_path = workspace
        .metadata()
        .target_directory
        .join("doc")
        .join(crate_name)
        .join("index.html");

    let doc_comment = indoc::formatdoc! {r"
        //! {SPAN_START_MARKER}
        //! [{label}]
        //! {SPAN_END_MARKER}
    "};

    let manifest = workspace.metadata().workspace_root.join("Cargo.toml");
    let mut file = File::options().append(true).open(&manifest).unwrap();
    file.write_all(
        formatdoc! {r#"
            [workspace.metadata.cargo-sync-rdme.rustdoc]
            standard-library-url-mode = "{standard_library_url_mode}"
        "#}
        .as_bytes(),
    )
    .unwrap();
    file.flush().unwrap();
    drop(file);

    let rustdoc_version = if toolchain == "stable" {
        workspace.cargo_toolchain_version(Some(toolchain))
    } else {
        toolchain.to_owned()
    };
    let channel = match toolchain {
        "stable" | "beta" | "nightly" => toolchain,
        _ => "stable",
    };
    workspace.insert_crate_doc_comment("src/lib.rs", &doc_comment);
    workspace
        .cargo_sync_rdme_default()
        .cargo_toolchain(toolchain)
        .assert()
        .success();
    workspace
        .cargo_doc_default()
        .cargo_toolchain(toolchain)
        .assert()
        .success();

    let md_links = helper::collect_links_from_markdown_file(readme_path, crate_name);
    let html_links = helper::collect_links_from_html_file(&rustdoc_html_path);
    let html_links = match standard_library_url_mode {
        "version" => html_links,
        "channel" => rewrite_stdlib_urls(&rustdoc_version, channel, html_links),
        "as-is" => rewrite_stdlib_urls(&rustdoc_version, "nightly", html_links),
        _ => unreachable!(),
    };
    assert_eq!(md_links, html_links);
    assert!(!md_links.is_empty());
}