jira-cli 0.3.5

Agent-friendly Jira CLI with JSON output, structured exit codes, and schema introspection
Documentation
use std::process::Command;

use assert_cmd::prelude::*;
use jira_cli::output::exit_codes;
use jira_cli::test_support::{EnvVarGuard, ProcessEnvLock, set_config_dir_env, write_config};
use tempfile::TempDir;

fn config_fixture() -> &'static str {
    r#"
[default]
host = "work.atlassian.net"
email = "me@example.com"
token = "secret-token"
"#
}

#[test]
fn config_show_auto_json_when_piped() {
    let _env = ProcessEnvLock::acquire().unwrap();
    let dir = TempDir::new().unwrap();
    let config_path = write_config(dir.path(), config_fixture()).unwrap();
    let _config_dir = set_config_dir_env(dir.path());
    let _host = EnvVarGuard::unset("JIRA_HOST");
    let _email = EnvVarGuard::unset("JIRA_EMAIL");
    let _token = EnvVarGuard::unset("JIRA_TOKEN");
    let _profile = EnvVarGuard::unset("JIRA_PROFILE");

    let output = Command::cargo_bin("jira")
        .unwrap()
        .args(["config", "show"])
        .output()
        .unwrap();

    assert!(output.status.success());
    assert!(output.stderr.is_empty());

    let json: serde_json::Value = serde_json::from_slice(&output.stdout).unwrap();
    assert_eq!(json["configPath"], config_path.display().to_string());
    assert_eq!(json["host"], "work.atlassian.net");
    assert_eq!(json["email"], "me@example.com");
    assert_eq!(json["tokenMasked"], "***oken");
}

#[test]
fn config_init_auto_json_when_piped() {
    let _env = ProcessEnvLock::acquire().unwrap();
    let dir = TempDir::new().unwrap();
    let _config_dir = set_config_dir_env(dir.path());

    let output = Command::cargo_bin("jira")
        .unwrap()
        .args(["config", "init"])
        .output()
        .unwrap();

    assert!(output.status.success());
    assert!(output.stderr.is_empty());

    let json: serde_json::Value = serde_json::from_slice(&output.stdout).unwrap();
    assert_eq!(
        json["configPath"],
        dir.path()
            .join("jira")
            .join("config.toml")
            .display()
            .to_string()
    );
    assert_eq!(
        json["tokenInstructions"],
        "https://id.atlassian.com/manage-profile/security/api-tokens"
    );
    assert_eq!(
        json["example"]["default"]["host"],
        "mycompany.atlassian.net"
    );
    assert!(json["pathResolution"].as_str().is_some());
    assert!(json["recommendedPermissions"].as_str().is_some());
    // configExists reflects whether the config file was present at the time of the call
    assert_eq!(json["configExists"], false);
}

#[test]
fn init_alias_matches_config_init_json_contract() {
    let _env = ProcessEnvLock::acquire().unwrap();
    let dir = TempDir::new().unwrap();
    let _config_dir = set_config_dir_env(dir.path());

    let output = Command::cargo_bin("jira")
        .unwrap()
        .args(["init"])
        .output()
        .unwrap();

    assert!(output.status.success());
    assert!(output.stderr.is_empty());

    let json: serde_json::Value = serde_json::from_slice(&output.stdout).unwrap();
    assert_eq!(
        json["configPath"],
        dir.path()
            .join("jira")
            .join("config.toml")
            .display()
            .to_string()
    );
    assert_eq!(
        json["tokenInstructions"],
        "https://id.atlassian.com/manage-profile/security/api-tokens"
    );
}

#[test]
fn config_show_invalid_config_returns_input_exit_code() {
    let _env = ProcessEnvLock::acquire().unwrap();
    let dir = TempDir::new().unwrap();
    let _config_dir = set_config_dir_env(dir.path());
    let _host = EnvVarGuard::unset("JIRA_HOST");
    let _email = EnvVarGuard::unset("JIRA_EMAIL");
    let _token = EnvVarGuard::unset("JIRA_TOKEN");
    let _profile = EnvVarGuard::unset("JIRA_PROFILE");

    let output = Command::cargo_bin("jira")
        .unwrap()
        .args(["config", "show"])
        .output()
        .unwrap();

    assert_eq!(output.status.code(), Some(exit_codes::INPUT_ERROR));
    assert!(output.stdout.is_empty());

    let stderr = String::from_utf8(output.stderr).unwrap();
    assert!(stderr.contains("No Jira host configured"));
}

#[test]
fn completions_install_powershell_returns_input_error() {
    let output = Command::cargo_bin("jira")
        .unwrap()
        .args(["completions", "powershell", "--install"])
        .output()
        .unwrap();

    assert_eq!(output.status.code(), Some(exit_codes::INPUT_ERROR));
    assert!(output.stdout.is_empty());

    let stderr = String::from_utf8(output.stderr).unwrap();
    assert!(stderr.contains("not supported"));
    assert!(stderr.to_lowercase().contains("redirect"));
}