haematite-cli 0.21.7

The haematite command: serve a store, its door and Studio, answer MCP, query with jq, and host the store's assistant seat
Documentation
use std::error::Error;
use std::time::Duration;

use super::{DEFAULT_LONG_WAIT_INTERVAL, long_wait_help, parse, parse_date};

#[test]
fn serve_default_is_the_named_thirty_second_interval() -> Result<(), Box<dyn Error>> {
    let options = parse(["--config", "/config.json"].map(str::to_owned).into_iter())?
        .ok_or("serve options")?;
    assert_eq!(DEFAULT_LONG_WAIT_INTERVAL, Duration::from_secs(30));
    assert_eq!(options.long_wait_interval, DEFAULT_LONG_WAIT_INTERVAL);
    assert!(long_wait_help().contains("default: 30s"));
    Ok(())
}

#[test]
fn serve_explicit_interval_is_carried_into_the_engine_options() -> Result<(), Box<dyn Error>> {
    let options = parse(
        ["--config", "/config.json", "--long-wait-interval", "125ms"]
            .map(str::to_owned)
            .into_iter(),
    )?
    .ok_or("serve options")?;
    let runtime = super::super::storage::runtime_options(options.long_wait_interval)?;
    assert_eq!(runtime.long_wait_interval, Duration::from_millis(125));
    Ok(())
}

#[test]
fn release_date_keeps_request_fields_and_carries_the_interval() -> Result<(), Box<dyn Error>> {
    let arguments = [
        "--config",
        "/config.json",
        "--branch",
        "work",
        "--generation",
        "7",
        "--at",
        "9",
    ];
    let (path, options) = parse_date(arguments.map(str::to_owned).into_iter())?;
    assert_eq!(path, std::path::PathBuf::from("/config.json"));
    assert_eq!(
        (options.branch.as_str(), options.generation, options.at),
        ("work", 7, 9)
    );
    assert_eq!(options.long_wait_interval, DEFAULT_LONG_WAIT_INTERVAL);
    let explicit = arguments
        .into_iter()
        .chain(["--long-wait-interval", "2m"])
        .map(str::to_owned);
    let (_, options) = parse_date(explicit)?;
    let runtime = super::super::storage::runtime_options(options.long_wait_interval)?;
    assert_eq!(runtime.long_wait_interval, Duration::from_secs(120));
    Ok(())
}

#[test]
fn invalid_intervals_are_refused_at_the_cli_boundary() {
    for value in [
        "0s",
        "-1s",
        "1",
        "1.5s",
        "1fortnight",
        "18446744073709551615h",
    ] {
        let parsed = parse(
            ["--config", "/config.json", "--long-wait-interval", value]
                .map(str::to_owned)
                .into_iter(),
        );
        assert!(parsed.is_err(), "interval {value}");
    }
    let refused = parse(
        ["--config", "/config.json", "--long-wait-interval", "0s"]
            .map(str::to_owned)
            .into_iter(),
    );
    assert!(
        matches!(refused, Err(message) if message.contains("long-wait interval 0ns is refused"))
    );
    let repeated = parse(
        [
            "--config",
            "/config.json",
            "--long-wait-interval",
            "1s",
            "--long-wait-interval",
            "2s",
        ]
        .map(str::to_owned)
        .into_iter(),
    );
    assert!(repeated.is_err());
}

#[test]
fn help_does_not_require_a_configuration_or_open_a_store() -> Result<(), String> {
    super::run(["--help".to_owned()].into_iter())?;
    super::release(["date", "--help"].map(str::to_owned).into_iter())?;
    Ok(())
}