haematite-cli 0.21.9

The haematite command: serve a store, its door and Studio, answer MCP, query with jq, and host the store's assistant seat
Documentation
use super::super::{Span, Stage, pipeline};

type TestResult = Result<(), Box<dyn std::error::Error>>;

#[test]
fn percentile_grammar_retains_field_number_and_byte_span() -> TestResult {
    let text = "patients | percentile ( .reading ; 95.5 ) | count";
    let plan = pipeline(text)?;
    assert_eq!(
        plan.stages[0].value,
        Stage::Percentile {
            field: "reading".to_owned(),
            percentile: serde_json::from_str("95.5")?,
        }
    );
    assert_eq!(plan.stages[0].span, Span { start: 11, end: 41 });
    assert_eq!(plan.stages[1].value, Stage::Count);
    Ok(())
}

#[test]
fn percentile_out_of_range_is_named_and_marks_the_number() -> TestResult {
    for number in ["101", "-1", "100.000000000000000001"] {
        let text = format!("patients | percentile(.reading; {number})");
        let error = pipeline(&text).err().ok_or("invalid percentile accepted")?;
        assert_eq!(error.code(), "query_percentile_range");
        assert!(error.to_string().contains("percentile"));
        assert_eq!(
            text.get(error.span().start..error.span().end)
                .ok_or("invalid percentile span")?,
            number
        );
    }
    Ok(())
}

#[test]
fn percentile_malformed_arguments_and_stage_position_are_refused() -> TestResult {
    for text in [
        "patients | percentile",
        "patients | percentile()",
        "patients | percentile(.reading)",
        "patients | percentile(reading; 95)",
        "patients | percentile(.reading.inner; 95)",
        "patients | percentile(.reading; true)",
        "patients | percentile(.reading; NaN)",
        "patients | percentile(.reading; 95; 99)",
        "patients | percentile(.reading; 95",
        "percentile(.reading; 95)",
        "patients | '.' | percentile(.reading; 95)",
    ] {
        let error = pipeline(text)
            .err()
            .ok_or("invalid percentile grammar accepted")?;
        assert_eq!(error.code(), "query_parse", "{text}");
        assert!(error.to_string().contains("percentile"), "{error}");
    }
    Ok(())
}

#[test]
fn percentile_in_quotes_remains_jq_with_exact_text() -> TestResult {
    let plan = pipeline("patients | 'percentile(.reading; 95)'")?;
    assert_eq!(plan.stages.len(), 1);
    assert_eq!(
        plan.stages[0].value,
        Stage::Jq("percentile(.reading; 95)".to_owned())
    );
    Ok(())
}