cueloop 0.5.0

A Rust CLI for managing AI agent loops with a structured JSON task queue
Documentation
//! Integration tests for init command validation and config wiring.
//!
//! Purpose:
//! - Integration tests for init command validation and config wiring.
//!
//! Responsibilities:
//! - Provide focused implementation or regression coverage for this file's owning feature.
//!
//! Scope:
//! - Limited to this file's owning feature boundary.
//!
//!
//! Usage:
//! - Used through the crate module tree or integration test harness.
//!
//! Invariants/Assumptions:
//! - Keep behavior aligned with CueLoop's canonical CLI, machine-contract, and queue semantics.

use anyhow::Result;
use cueloop::commands::init::{InitOptions, run_init};
use cueloop::config::Resolved;
use cueloop::contracts::Config;
use tempfile::TempDir;

fn resolved_for(dir: &TempDir) -> Resolved {
    let repo_root = dir.path().to_path_buf();
    let queue_path = repo_root.join(".cueloop/queue.jsonc");
    let done_path = repo_root.join(".cueloop/done.jsonc");
    let project_config_path = Some(repo_root.join(".cueloop/config.jsonc"));
    Resolved {
        config: Config::default(),
        repo_root,
        queue_path,
        done_path,
        id_prefix: "RQ".to_string(),
        id_width: 4,
        global_config_path: None,
        project_config_path,
    }
}

#[test]
fn init_fails_on_invalid_config_json() -> Result<()> {
    let dir = TempDir::new()?;
    let resolved = resolved_for(&dir);
    std::fs::create_dir_all(resolved.repo_root.join(".cueloop"))?;

    // Write invalid JSON to config
    std::fs::write(resolved.project_config_path.as_ref().unwrap(), "NOT JSON")?;

    // Write valid queue/done to focus on config failure
    std::fs::write(&resolved.queue_path, r#"{"version":1,"tasks":[]}"#)?;
    std::fs::write(&resolved.done_path, r#"{"version":1,"tasks":[]}"#)?;

    let result = run_init(
        &resolved,
        InitOptions {
            force: false,
            force_lock: false,
            interactive: false,
        },
    );

    assert!(result.is_err(), "Init should fail on invalid config JSON");
    Ok(())
}

#[test]
fn init_fails_on_structurally_invalid_queue() -> Result<()> {
    let dir = TempDir::new()?;
    let resolved = resolved_for(&dir);
    std::fs::create_dir_all(resolved.repo_root.join(".cueloop"))?;

    // Create a queue with missing required fields (structurally invalid for domain logic)
    // Here we omit created_at/updated_at/etc
    let queue_json = r#"{
  "version": 1,
  "tasks": [
    {
      "id": "RQ-0001",
      "status": "todo",
      "title": "Invalid Task"
    }
  ]
}"#;
    std::fs::write(&resolved.queue_path, queue_json)?;
    std::fs::write(&resolved.done_path, r#"{"version":1,"tasks":[]}"#)?;
    std::fs::write(
        resolved.project_config_path.as_ref().unwrap(),
        r#"{"version":2,"project_type":"code"}"#,
    )?;

    let result = run_init(
        &resolved,
        InitOptions {
            force: false,
            force_lock: false,
            interactive: false,
        },
    );

    assert!(result.is_err());
    let err = result.unwrap_err();
    assert!(
        err.to_string().contains("validate existing queue"),
        "Error should reference queue validation failure"
    );
    Ok(())
}