tests/cli.rs

use std::io::Write;
use std::process::Command;

use assert_cmd::prelude::*;
use predicates::prelude::*;
use tempfile::NamedTempFile;

fn bin() -> Command {
    Command::cargo_bin("ripgrab").expect("binary built")
}

fn seed_file(lines: &[&str]) -> NamedTempFile {
    let mut f = NamedTempFile::new().expect("tempfile");
    for line in lines {
        writeln!(f, "{line}").unwrap();
    }
    f.flush().unwrap();
    f
}

#[test]
fn requires_a_path() {
    bin()
        .assert()
        .failure()
        .stderr(predicate::str::contains("required"));
}

#[test]
fn prints_matches_in_no_follow_mode() {
    let f = seed_file(&[
        "INFO: started",
        "ERROR: disk full",
        "INFO: ticked",
        "ERROR: timeout",
    ]);
    bin()
        .arg("--no-follow")
        .arg("--no-color")
        .arg("--match")
        .arg("ERROR")
        .arg("-n")
        .arg("100")
        .arg(f.path())
        .assert()
        .success()
        .stdout(predicate::str::contains("disk full"))
        .stdout(predicate::str::contains("timeout"))
        .stdout(predicate::str::contains("ticked").not());
}

#[test]
fn extract_renders_named_fields() {
    let f = seed_file(&[
        "t=1 rid=aaa111 ms=5 path=/a",
        "t=2 rid=bbb222 ms=42 path=/b",
        "t=3 no match here",
    ]);
    let output = bin()
        .arg("--no-follow")
        .arg("--no-color")
        .arg("-n")
        .arg("100")
        .arg("--extract")
        .arg(r"rid=(?P<rid>\w+) ms=(?P<ms>\d+)")
        .arg(f.path())
        .assert()
        .success()
        .get_output()
        .stdout
        .clone();
    let stdout = String::from_utf8(output).unwrap();
    assert!(stdout.contains("rid=aaa111"));
    assert!(stdout.contains("ms=42"));
}

#[test]
fn rejects_extract_without_named_groups() {
    bin()
        .arg("--no-follow")
        .arg("--extract")
        .arg(r"\d+")
        .arg("/dev/null")
        .assert()
        .failure()
        .stderr(predicate::str::contains("named capture"));
}