#[test]
fn ported_project_then_limit_keeps_reversed_slice_head() {
let rows = vec![
row(json!({"netgroups": ["ansatt-373034", "ucore", "usit"]})),
row(json!({"netgroups": ["ansatt-373034"]})),
row(json!({"value": "standalone"})),
];
let output = run_rows_pipeline(rows, "P netgroups[::-1] | L 2");
let OutputItems::Rows(rows) = output.items else {
panic!("expected flat rows");
};
assert_eq!(
rows,
vec![
row(json!({"netgroups": "usit"})),
row(json!({"netgroups": "ucore"})),
]
);
}
#[test]
fn ported_project_group_networks_fans_out_then_groups_cleanly() {
let rows = vec![row(json!({
"networks": [
{"network": "129.240.130.0/24", "vlan": 200},
{"network": "2001:700:100:4003::/64", "vlan": 200},
]
}))];
let output = run_rows_pipeline(rows, "P networks[] | P network | G network");
let OutputItems::Groups(groups) = output.items else {
panic!("expected grouped rows");
};
assert_eq!(groups.len(), 2);
assert_eq!(groups[0].rows.len(), 1);
assert_eq!(groups[1].rows.len(), 1);
assert_eq!(
groups
.iter()
.map(|group| group.groups["network"].clone())
.collect::<Vec<_>>(),
vec![json!("129.240.130.0/24"), json!("2001:700:100:4003::/64"),]
);
assert_eq!(
groups[0].rows[0].keys().collect::<Vec<_>>(),
vec!["network"]
);
}
#[test]
fn ported_quick_path_scoping_distinguishes_nested_and_explicit_root_matches() {
let rows = vec![row(json!({
"id": 55753,
"txts": {"id": 27994},
"ipaddresses": [{"id": 57171}, {"id": 57172}],
"metadata": {"asset": {"id": 42}}
}))];
let asset = run_rows_pipeline(rows.clone(), "asset.id");
let OutputItems::Rows(asset_rows) = asset.items else {
panic!("expected flat rows");
};
assert_eq!(
asset_rows,
vec![row(json!({
"metadata": {"asset": {"id": 42}}
}))]
);
let root_only = run_rows_pipeline(rows.clone(), ".asset.id");
let OutputItems::Rows(root_rows) = root_only.items else {
panic!("expected flat rows");
};
assert!(root_rows.is_empty());
let root_id = run_rows_pipeline(rows, ".id");
let OutputItems::Rows(id_rows) = root_id.items else {
panic!("expected flat rows");
};
assert_eq!(
id_rows,
vec![row(json!({
"id": 55753
}))]
);
}
#[test]
fn ported_quick_collects_all_exact_matches_across_nested_fields() {
let rows = vec![row(json!({
"id": 55753,
"txts": {"id": 27994},
"ipaddresses": [{"id": 57171}, {"id": 57172}],
"metadata": {"asset": {"id": 42}}
}))];
let output = run_rows_pipeline(rows, "id");
let OutputItems::Rows(rows) = output.items else {
panic!("expected flat rows");
};
assert_eq!(
rows,
vec![row(json!({
"id": 55753,
"txts": {"id": 27994},
"ipaddresses": [{"id": 57171}, {"id": 57172}],
"metadata": {"asset": {"id": 42}}
}))]
);
}
#[test]
fn ported_quick_list_selector_fanout_preserves_selector_order() {
let rows = vec![row(json!({
"networks": [
{"network": "129.240.130.0/24", "vlan": 200},
{"network": "2001:700:100:4003::/64", "vlan": 200}
]
}))];
let output = run_rows_pipeline(rows, "networks[]");
let OutputItems::Rows(rows) = output.items else {
panic!("expected flat rows");
};
assert_eq!(
rows,
vec![
row(json!({"network": "129.240.130.0/24", "vlan": 200})),
row(json!({"network": "2001:700:100:4003::/64", "vlan": 200})),
]
);
}
#[test]
fn ported_group_nested_slice_chain_uses_selector_result() {
let rows = vec![row(json!({
"metadata": {
"items": [
{
"props": [
{"key": "x", "value": "one"},
{"key": "y", "value": "two"}
]
},
{
"props": [
{"key": "z", "value": "three"}
]
}
]
}
}))];
let output = run_rows_pipeline(rows, "G metadata.items[:1].props[:1].key");
let OutputItems::Groups(groups) = output.items else {
panic!("expected grouped rows");
};
assert_eq!(groups.len(), 1);
assert_eq!(
groups[0].groups["metadata.items[:1].props[:1].key"],
json!("x")
);
}
#[test]
fn ported_filter_datetime_comparison_handles_naive_rhs() {
let rows = vec![
row(json!({"ts": "2026-02-13T20:00:00+00:00"})),
row(json!({"ts": "2026-02-12T08:00:00+00:00"})),
];
let output = run_rows_pipeline(rows, "F ts>2026-02-13 00:00:00");
let OutputItems::Rows(rows) = output.items else {
panic!("expected flat rows");
};
assert_eq!(rows, vec![row(json!({"ts": "2026-02-13T20:00:00+00:00"}))]);
}