nils-api-testing-core 0.27.0

Library crate for nils-api-testing-core in the nils-cli workspace.
Documentation
use anyhow::Context;

use crate::Result;
use crate::grpc::runner::GrpcExecutedRequest;
use crate::grpc::schema::GrpcRequest;

pub fn evaluate_main_response(request: &GrpcRequest, executed: &GrpcExecutedRequest) -> Result<()> {
    let Some(expect) = request.expect.as_ref() else {
        return Ok(());
    };

    if let Some(status) = expect.status
        && executed.grpc_status != status
    {
        anyhow::bail!(
            "gRPC expect.status failed: expected {}, got {}",
            status,
            executed.grpc_status
        );
    }

    if let Some(expr) = expect.jq.as_deref() {
        let json: serde_json::Value = serde_json::from_slice(&executed.response_body)
            .context("gRPC expect.jq requires a JSON response body")?;
        if !crate::jq::eval_exit_status(&json, expr).unwrap_or(false) {
            anyhow::bail!("gRPC expect.jq failed: {expr}");
        }
    }

    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::grpc::schema::{GrpcExpect, GrpcRequest};

    fn base_request(expect: Option<GrpcExpect>) -> GrpcRequest {
        GrpcRequest {
            method: "health.HealthService/Check".to_string(),
            body: serde_json::json!({}),
            metadata: Vec::new(),
            proto: None,
            import_paths: Vec::new(),
            plaintext: true,
            authority: None,
            timeout_seconds: None,
            expect,
            raw: serde_json::json!({}),
        }
    }

    fn base_executed(body: serde_json::Value) -> GrpcExecutedRequest {
        GrpcExecutedRequest {
            target: "127.0.0.1:50051".to_string(),
            method: "health.HealthService/Check".to_string(),
            grpc_status: 0,
            response_body: serde_json::to_vec(&body).unwrap(),
            stderr: String::new(),
        }
    }

    #[test]
    fn grpc_expect_accepts_matching_status_and_jq() {
        let request = base_request(Some(GrpcExpect {
            status: Some(0),
            jq: Some(".ok == true".to_string()),
        }));
        let executed = base_executed(serde_json::json!({"ok": true}));
        evaluate_main_response(&request, &executed).unwrap();
    }

    #[test]
    fn grpc_expect_rejects_mismatched_status() {
        let request = base_request(Some(GrpcExpect {
            status: Some(2),
            jq: None,
        }));
        let executed = base_executed(serde_json::json!({"ok": true}));
        let err = evaluate_main_response(&request, &executed).unwrap_err();
        assert!(format!("{err:#}").contains("expect.status failed"));
    }

    #[test]
    fn grpc_expect_rejects_failed_jq() {
        let request = base_request(Some(GrpcExpect {
            status: Some(0),
            jq: Some(".ok == false".to_string()),
        }));
        let executed = base_executed(serde_json::json!({"ok": true}));
        let err = evaluate_main_response(&request, &executed).unwrap_err();
        assert!(format!("{err:#}").contains("expect.jq failed"));
    }
}