zilliz 1.4.2

TUI and CLI tool for managing Zilliz Cloud clusters and Milvus operations
Documentation
use serde_json::Value;
use zilliz::cli::dispatch::parse_args;
use zilliz::model::types::{HttpConfig, Operation, Param};

fn make_param(name: &str, param_type: &str, required: bool) -> Param {
    Param {
        name: name.to_string(),
        param_type: param_type.to_string(),
        cli_name: None,
        required,
        default: None,
        position: None,
        required_unless: None,
        required_when: None,
        description: None,
        choices: None,
        transform: None,
    }
}

fn make_operation(params: Vec<Param>) -> Operation {
    Operation {
        http: HttpConfig {
            method: "GET".to_string(),
            path: "/test".to_string(),
        },
        params,
        body_param: None,
        output: Default::default(),
        pagination: None,
        description: None,
        examples: vec![],
        dedicated_only: false,
        body_transform: None,
        body_defaults: Default::default(),
    }
}

#[test]
fn test_missing_params_non_tty_produces_error() {
    // When running non-interactively (e.g., in tests/CI), missing required
    // params should produce an error -- stdin is not a TTY here.
    let op = make_operation(vec![make_param("name", "string", true)]);
    let raw_args: Vec<String> = vec![];
    let param_values = parse_args(&raw_args, &op).unwrap();
    let missing: Vec<&Param> = op
        .params
        .iter()
        .filter(|p| p.required && !param_values.contains_key(&p.name))
        .collect();
    assert_eq!(missing.len(), 1);
    assert_eq!(missing[0].name, "name");
}

#[test]
fn test_complex_types_not_promptable() {
    let params = [
        make_param("name", "string", true),
        make_param("schema", "array", true),
        make_param("config", "object", true),
    ];
    let refs: Vec<&Param> = params.iter().collect();
    let (promptable, complex): (Vec<&Param>, Vec<&Param>) = refs
        .into_iter()
        .partition(|p| !matches!(p.param_type.as_str(), "array" | "object"));
    assert_eq!(promptable.len(), 1);
    assert_eq!(promptable[0].name, "name");
    assert_eq!(complex.len(), 2);
}

#[test]
fn test_provided_params_not_prompted() {
    let op = make_operation(vec![
        make_param("name", "string", true),
        make_param("clusterId", "string", true),
    ]);
    let raw_args: Vec<String> = vec!["--name".to_string(), "test".to_string()];
    let param_values = parse_args(&raw_args, &op).unwrap();
    let missing: Vec<&Param> = op
        .params
        .iter()
        .filter(|p| p.required && !param_values.contains_key(&p.name))
        .collect();
    assert_eq!(missing.len(), 1);
    assert_eq!(missing[0].name, "clusterId");
}

#[test]
fn test_all_params_provided_no_missing() {
    let op = make_operation(vec![make_param("name", "string", true)]);
    let raw_args: Vec<String> = vec!["--name".to_string(), "test".to_string()];
    let param_values = parse_args(&raw_args, &op).unwrap();
    let missing: Vec<&Param> = op
        .params
        .iter()
        .filter(|p| p.required && !param_values.contains_key(&p.name))
        .collect();
    assert!(missing.is_empty());
}

#[test]
fn test_boolean_param_default_true() {
    let op = make_operation(vec![make_param("autoIndex", "boolean", false)]);
    let raw_args: Vec<String> = vec!["--autoIndex".to_string()];
    let values = parse_args(&raw_args, &op).unwrap();
    assert_eq!(values.get("autoIndex"), Some(&Value::Bool(true)));
}