refactor: nested $json/$select syntax, migrate stored queries
This commit is contained in:
+21
-34
@@ -75,45 +75,32 @@ pub fn evaluate(query: &Value, response: &Response) -> Result<bool> {
|
||||
return eval_condition(cond, &val, response);
|
||||
}
|
||||
|
||||
// $json — JSONPath shorthand
|
||||
if let Some(json_path) = map.get("$json") {
|
||||
let path_str = json_path.as_str().unwrap_or("");
|
||||
let resolved = resolve_json_path(&response.body, path_str);
|
||||
for (op, val) in map {
|
||||
if op == "$json" { continue; }
|
||||
if !eval_op(op, &resolved, val, response)? { return Ok(false); }
|
||||
// $json — { "$json": { "$.path": { "$op": val } } }
|
||||
if let Some(json_path_map) = map.get("$json") {
|
||||
let path_map = match json_path_map {
|
||||
Value::Object(m) => m,
|
||||
_ => bail!("$json expects an object {{ path: condition }}"),
|
||||
};
|
||||
for (path, condition) in path_map {
|
||||
let resolved = resolve_json_path(&response.body, path);
|
||||
if !eval_condition(condition, &resolved, response)? { return Ok(false); }
|
||||
}
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
// CSS selector shorthand: { "$select": "...", "$eq": "..." }
|
||||
if let Some(sel) = map.get("$select") {
|
||||
let sel_str = sel.as_str().unwrap_or("");
|
||||
let selected = css_select(&response.body, sel_str);
|
||||
if let Some(op_val) = map.get("$eq") {
|
||||
return Ok(selected.as_deref() == op_val.as_str());
|
||||
// $select — { "$select": { "css.selector": { "$op": val } } }
|
||||
if let Some(sel_map) = map.get("$select") {
|
||||
let sel_obj = match sel_map {
|
||||
Value::Object(m) => m,
|
||||
_ => bail!("$select expects an object {{ selector: condition }}"),
|
||||
};
|
||||
for (selector, condition) in sel_obj {
|
||||
let selected = css_select(&response.body, selector)
|
||||
.map(Value::String)
|
||||
.unwrap_or(Value::Null);
|
||||
if !eval_condition(condition, &selected, response)? { return Ok(false); }
|
||||
}
|
||||
if let Some(op_val) = map.get("$ne") {
|
||||
return Ok(selected.as_deref() != op_val.as_str());
|
||||
}
|
||||
if let Some(op_val) = map.get("$contains") {
|
||||
let needle = op_val.as_str().unwrap_or("");
|
||||
return Ok(selected.map(|s| s.contains(needle)).unwrap_or(false));
|
||||
}
|
||||
if let Some(op_val) = map.get("$startsWith") {
|
||||
let needle = op_val.as_str().unwrap_or("");
|
||||
return Ok(selected.map(|s| s.starts_with(needle)).unwrap_or(false));
|
||||
}
|
||||
if let Some(op_val) = map.get("$endsWith") {
|
||||
let needle = op_val.as_str().unwrap_or("");
|
||||
return Ok(selected.map(|s| s.ends_with(needle)).unwrap_or(false));
|
||||
}
|
||||
if let Some(op_val) = map.get("$regex") {
|
||||
let pattern = op_val.as_str().unwrap_or("");
|
||||
let re = Regex::new(pattern).unwrap_or_else(|_| Regex::new("$^").unwrap());
|
||||
return Ok(selected.map(|s| re.is_match(&s)).unwrap_or(false));
|
||||
}
|
||||
return Ok(selected.is_some());
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
// Field-level checks
|
||||
|
||||
Reference in New Issue
Block a user