opencode-ralph-loop-cli 0.1.0

Scaffolder CLI for OpenCode Ralph Loop plugin — one command setup
Documentation
use assert_cmd::Command;
use serde_json::Value;
use tempfile::TempDir;

fn cmd() -> Command {
    Command::cargo_bin("opencode-ralph-loop-cli").unwrap()
}

fn setup_and_init() -> TempDir {
    let dir = TempDir::new().unwrap();
    cmd()
        .args(["init", "--path", dir.path().to_str().unwrap()])
        .assert()
        .success();
    dir
}

#[test]
fn snapshot_init_json() {
    let dir = TempDir::new().unwrap();
    let output = cmd()
        .args([
            "init",
            "--path",
            dir.path().to_str().unwrap(),
            "--output",
            "json",
        ])
        .output()
        .unwrap();
    assert!(output.status.success());
    let json: Value = serde_json::from_slice(&output.stdout).unwrap();

    insta::with_settings!({
        redactions => vec![
            (".duration_ms", "[DURATION]".into()),
            (".cli_version", "[VERSION]".into()),
        ]
    }, {
        insta::assert_json_snapshot!("init_output_json", json);
    });
}

#[test]
fn snapshot_init_ndjson() {
    let dir = TempDir::new().unwrap();
    let output = cmd()
        .args([
            "init",
            "--path",
            dir.path().to_str().unwrap(),
            "--output",
            "ndjson",
        ])
        .output()
        .unwrap();
    assert!(output.status.success());

    let stdout = String::from_utf8(output.stdout).unwrap();
    let lines: Vec<Value> = stdout
        .lines()
        .filter(|l| !l.is_empty())
        .map(|l| serde_json::from_str(l).unwrap())
        .collect();

    insta::with_settings!({
        redactions => vec![
            ("[].cli_version", "[VERSION]".into()),
        ]
    }, {
        insta::assert_json_snapshot!("init_output_ndjson", lines);
    });
}

#[test]
fn snapshot_check_json_clean() {
    let dir = setup_and_init();
    let output = cmd()
        .args([
            "check",
            "--path",
            dir.path().to_str().unwrap(),
            "--output",
            "json",
            "--exit-zero",
        ])
        .output()
        .unwrap();
    assert!(output.status.success());
    let json: Value = serde_json::from_slice(&output.stdout).unwrap();

    insta::with_settings!({
        redactions => vec![
            (".duration_ms", "[DURATION]".into()),
            (".cli_version", "[VERSION]".into()),
        ]
    }, {
        insta::assert_json_snapshot!("check_output_json_clean", json);
    });
}

#[test]
fn snapshot_check_json_drift() {
    let dir = setup_and_init();
    let opencode = dir.path().join(".opencode");
    std::fs::write(
        opencode.join("plugins/ralph.ts"),
        b"content changed for drift test",
    )
    .unwrap();

    let output = cmd()
        .args([
            "check",
            "--path",
            dir.path().to_str().unwrap(),
            "--output",
            "json",
            "--exit-zero",
        ])
        .output()
        .unwrap();
    let json: Value = serde_json::from_slice(&output.stdout).unwrap();

    insta::with_settings!({
        redactions => vec![
            (".duration_ms", "[DURATION]".into()),
            (".cli_version", "[VERSION]".into()),
        ]
    }, {
        insta::assert_json_snapshot!("check_output_json_drift", json);
    });
}