tellaro-query-language 2.0.0

A flexible, human-friendly query language for searching and filtering structured data
Documentation
//! Split mutator tests - matching Python test_split_mutator.py
//!
//! Tests for the split string mutator functionality.

use serde_json::json;
use tellaro_query_language::Tql;

// =============================================================================
// Basic Split Mutator Tests
// =============================================================================

#[test]
fn test_split_mutator_positional_parameter() {
    let tql = Tql::new();
    let data = vec![json!({"path": "/home/user/documents/file.txt"})];

    // Split with positional delimiter parameter
    let results = tql
        .query(&data, "path | split('/') exists")
        .expect("Query should succeed");
    assert_eq!(results.len(), 1);
}

#[test]
fn test_split_mutator_named_parameter() {
    let tql = Tql::new();
    let data = vec![json!({"tags": "python,rust,java"})];

    // Split with named delimiter parameter
    let results = tql
        .query(&data, "tags | split(delimiter=',') exists")
        .expect("Query should succeed");
    assert_eq!(results.len(), 1);
}

#[test]
fn test_split_mutator_chained_with_length() {
    let tql = Tql::new();
    let data = vec![json!({"tags": "a,b,c,d,e"}), json!({"tags": "x,y"})];

    // Split and then get length - filter for arrays with more than 3 elements
    let results = tql
        .query(&data, "tags | split(',') | length > 3")
        .expect("Query should succeed");
    assert_eq!(results.len(), 1);
    assert_eq!(results[0]["tags"], "a,b,c,d,e");
}

#[test]
fn test_split_mutator_pipe_delimiter() {
    let tql = Tql::new();
    let data = vec![json!({"values": "one|two|three"})];

    // Split with pipe delimiter
    let results = tql
        .query(&data, "values | split('|') | length = 3")
        .expect("Query should succeed");
    assert_eq!(results.len(), 1);
}

#[test]
fn test_split_mutator_space_delimiter() {
    let tql = Tql::new();
    let data = vec![json!({"sentence": "hello world test"})];

    // Split with space delimiter
    let results = tql
        .query(&data, "sentence | split(' ') | length = 3")
        .expect("Query should succeed");
    assert_eq!(results.len(), 1);
}

#[test]
fn test_split_mutator_dot_delimiter() {
    let tql = Tql::new();
    let data = vec![json!({"ip": "192.168.1.100"})];

    // Split IP address by dot
    let results = tql
        .query(&data, "ip | split('.') | length = 4")
        .expect("Query should succeed");
    assert_eq!(results.len(), 1);
}

#[test]
fn test_split_mutator_hyphen_delimiter() {
    let tql = Tql::new();
    let data = vec![json!({"date": "2024-01-15"})];

    // Split date by hyphen
    let results = tql
        .query(&data, "date | split('-') | length = 3")
        .expect("Query should succeed");
    assert_eq!(results.len(), 1);
}

#[test]
fn test_split_mutator_colon_delimiter() {
    let tql = Tql::new();
    let data = vec![json!({"time": "14:30:45"})];

    // Split time by colon
    let results = tql
        .query(&data, "time | split(':') | length = 3")
        .expect("Query should succeed");
    assert_eq!(results.len(), 1);
}

#[test]
fn test_split_mutator_with_empty_parts() {
    let tql = Tql::new();
    let data = vec![json!({"value": "a,,b,,c"})];

    // Split should include empty parts
    let results = tql
        .query(&data, "value | split(',') | length = 5")
        .expect("Query should succeed");
    assert_eq!(results.len(), 1);
}

#[test]
fn test_split_mutator_on_number() {
    let tql = Tql::new();
    let data = vec![json!({"value": 12345})];

    // Split on number (should convert to string first)
    let results = tql
        .query(&data, "value | split('3') exists")
        .expect("Query should succeed");
    assert_eq!(results.len(), 1);
}

#[test]
fn test_split_mutator_on_boolean() {
    let tql = Tql::new();
    let data = vec![json!({"flag": true})];

    // Split on boolean (should convert to string first)
    let results = tql
        .query(&data, "flag | split('r') exists")
        .expect("Query should succeed");
    assert_eq!(results.len(), 1);
}

#[test]
fn test_split_mutator_no_delimiter_found() {
    let tql = Tql::new();
    let data = vec![json!({"value": "nodashes"})];

    // Split with delimiter not in string - returns array with single element
    let results = tql
        .query(&data, "value | split('-') | length = 1")
        .expect("Query should succeed");
    assert_eq!(results.len(), 1);
}

#[test]
fn test_split_mutator_empty_string() {
    let tql = Tql::new();
    let data = vec![json!({"value": ""})];

    // Split empty string
    let results = tql
        .query(&data, "value | split(',') exists")
        .expect("Query should succeed");
    assert_eq!(results.len(), 1);
}

#[test]
fn test_split_mutator_single_char_string() {
    let tql = Tql::new();
    let data = vec![json!({"value": "x"})];

    // Split single character string
    let results = tql
        .query(&data, "value | split(',') | length = 1")
        .expect("Query should succeed");
    assert_eq!(results.len(), 1);
}

#[test]
fn test_split_mutator_unicode_content() {
    let tql = Tql::new();
    let data = vec![json!({"value": "hello,world,\u{4e16}\u{754c}"})];

    // Split string with unicode characters
    let results = tql
        .query(&data, "value | split(',') | length = 3")
        .expect("Query should succeed");
    assert_eq!(results.len(), 1);
}

#[test]
fn test_split_mutator_result_is_array() {
    let tql = Tql::new();
    let data = vec![
        json!({"tags": "python,rust,java"}),
        json!({"tags": "go,c++"}),
    ];

    // Split produces an array, check the length
    let results = tql
        .query(&data, "tags | split(',') | length = 3")
        .expect("Query should succeed");
    assert_eq!(results.len(), 1);
    assert_eq!(results[0]["tags"], "python,rust,java");
}

#[test]
fn test_split_mutator_length_filter() {
    let tql = Tql::new();
    let data = vec![json!({"numbers": "1,2,3"}), json!({"numbers": "10,20,30"})];

    // Split and check length
    let results = tql
        .query(&data, "numbers | split(',') | length > 0")
        .expect("Query should succeed");
    assert_eq!(results.len(), 2);
}

// =============================================================================
// Split Mutator with Filtering
// =============================================================================

#[test]
fn test_split_mutator_filter_by_array_length() {
    let tql = Tql::new();
    let data = vec![
        json!({"path": "/a/b/c/d"}),
        json!({"path": "/x/y"}),
        json!({"path": "/single"}),
    ];

    // Filter paths with more than 3 segments
    let results = tql
        .query(&data, "path | split('/') | length > 3")
        .expect("Query should succeed");
    assert_eq!(results.len(), 1);
    assert_eq!(results[0]["path"], "/a/b/c/d");
}

#[test]
fn test_split_mutator_complex_query() {
    let tql = Tql::new();
    let data = vec![
        json!({"name": "Alice", "skills": "python,rust,java"}),
        json!({"name": "Bob", "skills": "go,python"}),
        json!({"name": "Charlie", "skills": "javascript"}),
    ];

    // Complex query: name starts with 'A' AND has more than 2 skills
    let results = tql
        .query(
            &data,
            "name startswith 'A' AND skills | split(',') | length > 2",
        )
        .expect("Query should succeed");
    assert_eq!(results.len(), 1);
    assert_eq!(results[0]["name"], "Alice");
}

// =============================================================================
// Edge Cases
// =============================================================================

#[test]
fn test_split_mutator_delimiter_at_start() {
    let tql = Tql::new();
    let data = vec![json!({"value": ",a,b,c"})];

    // Delimiter at start creates empty first element
    let results = tql
        .query(&data, "value | split(',') | length = 4")
        .expect("Query should succeed");
    assert_eq!(results.len(), 1);
}

#[test]
fn test_split_mutator_delimiter_at_end() {
    let tql = Tql::new();
    let data = vec![json!({"value": "a,b,c,"})];

    // Delimiter at end creates empty last element
    let results = tql
        .query(&data, "value | split(',') | length = 4")
        .expect("Query should succeed");
    assert_eq!(results.len(), 1);
}

#[test]
fn test_split_mutator_consecutive_delimiters() {
    let tql = Tql::new();
    let data = vec![json!({"value": "a,,,b"})];

    // Consecutive delimiters create empty elements
    let results = tql
        .query(&data, "value | split(',') | length = 4")
        .expect("Query should succeed");
    assert_eq!(results.len(), 1);
}