atproto-devtool 0.1.0

A multitool for the atproto developer ecosystem
Documentation
//! CLI tests for the labeler conformance suite: --help output, --no-color, --verbose, and
//! invalid-argument error codes.

use assert_cmd::Command;

/// `test labeler --help` lists every user-facing flag and the target argument.
#[test]
fn help_lists_all_flags() {
    let mut cmd = Command::cargo_bin("atproto-devtool").expect("bin not found");
    let output = cmd
        .arg("test")
        .arg("labeler")
        .arg("--help")
        .output()
        .expect("failed to run atproto-devtool");

    assert!(
        output.status.success(),
        "--help should exit successfully, got {:?}",
        output.status,
    );

    let stdout = String::from_utf8_lossy(&output.stdout);
    for needle in [
        "--did",
        "--subscribe-timeout",
        "--verbose",
        "--no-color",
        "<TARGET>",
    ] {
        assert!(
            stdout.contains(needle),
            "--help stdout missing expected token `{needle}`, got:\n{stdout}",
        );
    }
}

/// Invalid CLI args (missing required argument) exit with code 2.
#[test]
fn bootstrap_failure_exits_two() {
    let mut cmd = Command::cargo_bin("atproto-devtool").expect("bin not found");
    let assert = cmd.arg("test").arg("labeler").assert();

    // Exit code should be 2 for bootstrap/CLI parsing errors.
    // This test invokes the labeler without a required target argument.
    assert.code(2);
}

/// `--no-color` causes the rendered report to be emitted without ANSI escape
/// sequences. Exercises a real pipeline run against an invalid `did:web` target
/// that fails fast on DNS so the command reaches report rendering.
#[test]
fn no_color_renders_without_ansi() {
    let mut cmd = Command::cargo_bin("atproto-devtool").expect("bin not found");
    cmd.env_remove("NO_COLOR");
    cmd.arg("test")
        .arg("labeler")
        .arg("--no-color")
        .arg("did:web:nonexistent.invalid");

    let output = cmd.output().expect("failed to run atproto-devtool");
    let stdout = String::from_utf8_lossy(&output.stdout);

    assert!(
        !stdout.contains("\x1b["),
        "Stdout must not contain ANSI escape sequences with --no-color, got:\n{stdout}",
    );
    assert!(
        stdout.contains("== Identity =="),
        "Stdout should contain a rendered identity section, got:\n{stdout}",
    );
    assert!(
        stdout.contains("[FAIL]") || stdout.contains("[NET]"),
        "Stdout should contain at least one failure or network-error check glyph, got:\n{stdout}",
    );
}

/// `--verbose` emits `DEBUG`-level tracing to stderr. Exercises a real pipeline
/// run so that at least one `tracing::debug!` call site fires.
#[test]
fn verbose_flag_emits_debug_tracing_to_stderr() {
    let mut cmd = Command::cargo_bin("atproto-devtool").expect("bin not found");
    cmd.arg("test")
        .arg("labeler")
        .arg("--verbose")
        .arg("--no-color")
        .arg("did:web:nonexistent.invalid");

    let output = cmd.output().expect("failed to run atproto-devtool");
    let stderr = String::from_utf8_lossy(&output.stderr);

    assert!(
        stderr.contains("DEBUG"),
        "Stderr should contain DEBUG tracing output with --verbose, got:\n{stderr}",
    );
}