yosh 0.2.2

A POSIX-compliant shell implemented in Rust
use std::process::Command;

fn yosh_bin() -> Command {
    Command::new(env!("CARGO_BIN_EXE_yosh"))
}

#[test]
fn help_flag_prints_usage_and_exits_zero() {
    let output = yosh_bin().arg("--help").output().unwrap();
    assert!(output.status.success(), "exit code should be 0");
    let stdout = String::from_utf8_lossy(&output.stdout);
    assert!(
        stdout.contains("yosh - A POSIX-compliant shell"),
        "should contain description"
    );
    assert!(stdout.contains("Usage:"), "should contain Usage section");
    assert!(
        stdout.contains("Options:"),
        "should contain Options section"
    );
    assert!(stdout.contains("--help"), "should list --help option");
    assert!(stdout.contains("--version"), "should list --version option");
    assert!(stdout.contains("-c <command>"), "should list -c option");
    assert!(stdout.contains("plugin"), "should list plugin subcommand");
}

#[test]
fn short_help_flag_works() {
    let output = yosh_bin().arg("-h").output().unwrap();
    assert!(output.status.success(), "exit code should be 0");
    let stdout = String::from_utf8_lossy(&output.stdout);
    assert!(
        stdout.contains("yosh - A POSIX-compliant shell"),
        "should contain description"
    );
    assert!(stdout.contains("Usage:"), "should contain Usage section");
}

#[test]
fn version_flag_prints_version_and_exits_zero() {
    let output = yosh_bin().arg("--version").output().unwrap();
    assert!(output.status.success(), "exit code should be 0");
    let stdout = String::from_utf8_lossy(&output.stdout);
    assert!(stdout.starts_with("yosh "), "should start with 'yosh '");
    assert!(
        stdout.contains(env!("CARGO_PKG_VERSION")),
        "should contain package version"
    );
    // Version format: yosh 0.1.0 (hash date)
    assert!(stdout.contains('('), "should contain build info in parens");
}

#[test]
fn help_output_goes_to_stdout() {
    let output = yosh_bin().arg("--help").output().unwrap();
    assert!(!output.stdout.is_empty(), "stdout should have content");
    assert!(output.stderr.is_empty(), "stderr should be empty");
}

#[test]
fn help_no_color_when_env_set() {
    let output = yosh_bin()
        .arg("--help")
        .env("NO_COLOR", "1")
        .output()
        .unwrap();
    let stdout = String::from_utf8_lossy(&output.stdout);
    // ANSI escape sequences start with \x1b[
    assert!(
        !stdout.contains('\x1b'),
        "should not contain ANSI escapes when NO_COLOR is set"
    );
}

#[test]
fn help_color_forced_with_clicolor_force() {
    let output = yosh_bin()
        .arg("--help")
        .env("CLICOLOR_FORCE", "1")
        .output()
        .unwrap();
    let stdout = String::from_utf8_lossy(&output.stdout);
    assert!(
        stdout.contains('\x1b'),
        "should contain ANSI escapes when CLICOLOR_FORCE=1"
    );
}

#[test]
fn help_clicolor_force_zero_does_not_force() {
    // CLICOLOR_FORCE=0 should not force colors; since test stdout is not a TTY, no color
    let output = yosh_bin()
        .arg("--help")
        .env("CLICOLOR_FORCE", "0")
        .output()
        .unwrap();
    let stdout = String::from_utf8_lossy(&output.stdout);
    assert!(
        !stdout.contains('\x1b'),
        "CLICOLOR_FORCE=0 should not force ANSI escapes"
    );
}

#[test]
fn help_clicolor_zero_disables_colors() {
    let output = yosh_bin()
        .arg("--help")
        .env("CLICOLOR", "0")
        .output()
        .unwrap();
    let stdout = String::from_utf8_lossy(&output.stdout);
    assert!(
        !stdout.contains('\x1b'),
        "CLICOLOR=0 should disable ANSI escapes"
    );
}

#[test]
fn help_clicolor_force_overrides_clicolor_zero() {
    let output = yosh_bin()
        .arg("--help")
        .env("CLICOLOR_FORCE", "1")
        .env("CLICOLOR", "0")
        .output()
        .unwrap();
    let stdout = String::from_utf8_lossy(&output.stdout);
    assert!(
        stdout.contains('\x1b'),
        "CLICOLOR_FORCE=1 should override CLICOLOR=0 (force wins, matching bat/git)"
    );
}

#[test]
fn help_no_color_overrides_clicolor() {
    let output = yosh_bin()
        .arg("--help")
        .env("NO_COLOR", "1")
        .env("CLICOLOR", "1")
        .output()
        .unwrap();
    let stdout = String::from_utf8_lossy(&output.stdout);
    assert!(
        !stdout.contains('\x1b'),
        "NO_COLOR should disable colors even with CLICOLOR=1"
    );
}