codoc 0.1.0

Unified documentation parser for Ruby and TypeScript codebases
Documentation
//! CLI integration tests.

use assert_cmd::Command;
use predicates::prelude::*;
use std::fs;
use std::path::PathBuf;
use tempfile::tempdir;

fn codoc_cmd() -> Command {
    Command::cargo_bin("codoc").unwrap()
}

fn fixtures_path() -> PathBuf {
    PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures")
}

#[test]
fn test_help() {
    codoc_cmd()
        .arg("--help")
        .assert()
        .success()
        .stdout(predicate::str::contains("codoc"));
}

#[test]
fn test_parse_ruby_file() {
    let output_dir = tempdir().unwrap();
    let output_file = output_dir.path().join("output.json");

    codoc_cmd()
        .arg("parse")
        .arg(fixtures_path().join("ruby/basic_class.rb"))
        .arg("-l")
        .arg("ruby")
        .arg("-n")
        .arg("TestProject")
        .arg("-o")
        .arg(&output_file)
        .assert()
        .success();

    // Verify output file exists
    assert!(output_file.exists());

    // Verify it's valid JSON
    let content = fs::read_to_string(&output_file).unwrap();
    let json: serde_json::Value = serde_json::from_str(&content).unwrap();

    // Verify structure - name is in metadata
    assert!(json.get("metadata").is_some());
    assert_eq!(json["metadata"]["name"], "TestProject");
    assert!(json.get("entities").is_some());
}

#[test]
fn test_parse_typescript_file() {
    let output_dir = tempdir().unwrap();
    let output_file = output_dir.path().join("output.json");

    codoc_cmd()
        .arg("parse")
        .arg(fixtures_path().join("typescript/basic_class.ts"))
        .arg("-l")
        .arg("typescript")
        .arg("-n")
        .arg("TSProject")
        .arg("-o")
        .arg(&output_file)
        .assert()
        .success();

    // Verify output
    assert!(output_file.exists());
    let content = fs::read_to_string(&output_file).unwrap();
    let json: serde_json::Value = serde_json::from_str(&content).unwrap();

    assert_eq!(json["metadata"]["name"], "TSProject");
    assert!(json.get("entities").is_some());
}

#[test]
fn test_parse_ruby_directory() {
    let output_dir = tempdir().unwrap();
    let output_file = output_dir.path().join("output.json");

    codoc_cmd()
        .arg("parse")
        .arg(fixtures_path().join("ruby"))
        .arg("-l")
        .arg("ruby")
        .arg("-n")
        .arg("RubyProject")
        .arg("-o")
        .arg(&output_file)
        .assert()
        .success();

    // Verify output contains entities from multiple files
    let content = fs::read_to_string(&output_file).unwrap();
    let json: serde_json::Value = serde_json::from_str(&content).unwrap();

    let entities = json["entities"].as_array().unwrap();
    // Should have entities from multiple files
    assert!(entities.len() > 1);
}

#[test]
fn test_parse_typescript_directory() {
    let output_dir = tempdir().unwrap();
    let output_file = output_dir.path().join("output.json");

    codoc_cmd()
        .arg("parse")
        .arg(fixtures_path().join("typescript"))
        .arg("-l")
        .arg("typescript")
        .arg("-n")
        .arg("TSProject")
        .arg("-o")
        .arg(&output_file)
        .assert()
        .success();

    // Verify output contains items from multiple files
    let content = fs::read_to_string(&output_file).unwrap();
    let json: serde_json::Value = serde_json::from_str(&content).unwrap();

    let entities = json["entities"].as_array().unwrap();
    assert!(entities.len() > 1);
}

#[test]
fn test_id_prefix() {
    let output_dir = tempdir().unwrap();
    let output_file = output_dir.path().join("output.json");

    codoc_cmd()
        .arg("parse")
        .arg(fixtures_path().join("ruby/basic_class.rb"))
        .arg("-l")
        .arg("ruby")
        .arg("-n")
        .arg("TestProject")
        .arg("--id-prefix")
        .arg("rb:")
        .arg("-o")
        .arg(&output_file)
        .assert()
        .success();

    let content = fs::read_to_string(&output_file).unwrap();
    let json: serde_json::Value = serde_json::from_str(&content).unwrap();

    // Check that idPrefix is set in metadata
    // The prefix is stored for consumers to use when generating links
    assert_eq!(json["metadata"]["idPrefix"], "rb:");

    // Entities should exist
    let entities = json["entities"].as_array().unwrap();
    assert!(!entities.is_empty());
}

#[test]
fn test_invalid_language() {
    codoc_cmd()
        .arg("parse")
        .arg(fixtures_path().join("ruby"))
        .arg("-l")
        .arg("invalid")
        .arg("-n")
        .arg("Test")
        .assert()
        .failure();
}

#[test]
fn test_output_to_stdout() {
    codoc_cmd()
        .arg("parse")
        .arg(fixtures_path().join("ruby/basic_class.rb"))
        .arg("-l")
        .arg("ruby")
        .arg("-n")
        .arg("TestProject")
        .assert()
        .success()
        .stdout(predicate::str::contains("\"name\": \"TestProject\""));
}