chore: add \!file_exists condition
This commit is contained in:
parent
25e779a390
commit
f7f7fec13b
@ -3,6 +3,7 @@
|
||||
//! Provides logic for evaluating `when` conditions on form elements.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
|
||||
use super::types::FormDefinition;
|
||||
|
||||
@ -120,9 +121,16 @@ pub fn should_load_fragment(
|
||||
/// - "field_name contains value"
|
||||
/// - "field_name startswith value"
|
||||
/// - "value in field_name" (array membership)
|
||||
/// - "file_exists(path)" (file existence check)
|
||||
/// - "!file_exists(path)" (negated file existence check)
|
||||
pub fn evaluate_condition(condition: &str, results: &HashMap<String, serde_json::Value>) -> bool {
|
||||
let condition = condition.trim();
|
||||
|
||||
// Check for function calls first (file_exists, etc.)
|
||||
if let Some(result) = evaluate_function_call(condition) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check string operators first (word boundaries)
|
||||
let string_operators = ["contains", "startswith", "endswith", "in"];
|
||||
for op_str in &string_operators {
|
||||
@ -246,6 +254,44 @@ pub fn evaluate_condition(condition: &str, results: &HashMap<String, serde_json:
|
||||
true
|
||||
}
|
||||
|
||||
/// Evaluate function calls in conditions
|
||||
/// Returns Some(bool) if a function call was found and evaluated
|
||||
/// Returns None if no function call was found
|
||||
fn evaluate_function_call(condition: &str) -> Option<bool> {
|
||||
let condition = condition.trim();
|
||||
|
||||
// Handle negation prefix
|
||||
let (is_negated, clean_condition) = if let Some(stripped) = condition.strip_prefix('!') {
|
||||
(true, stripped.trim())
|
||||
} else {
|
||||
(false, condition)
|
||||
};
|
||||
|
||||
// Check for file_exists() function
|
||||
if clean_condition.starts_with("file_exists(") && clean_condition.ends_with(')') {
|
||||
let start = "file_exists(".len();
|
||||
let end = clean_condition.len() - 1;
|
||||
let path_arg = clean_condition[start..end].trim();
|
||||
|
||||
// Remove quotes if present
|
||||
let path = if (path_arg.starts_with('"') && path_arg.ends_with('"'))
|
||||
|| (path_arg.starts_with('\'') && path_arg.ends_with('\''))
|
||||
{
|
||||
&path_arg[1..path_arg.len() - 1]
|
||||
} else {
|
||||
path_arg
|
||||
};
|
||||
|
||||
// Check if file exists
|
||||
let exists = Path::new(path).exists();
|
||||
|
||||
// Apply negation if needed
|
||||
return Some(if is_negated { !exists } else { exists });
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Parse a value from condition right-hand side
|
||||
fn parse_condition_value(s: &str) -> serde_json::Value {
|
||||
let s = s.trim();
|
||||
@ -467,4 +513,87 @@ mod tests {
|
||||
assert!(evaluate_condition("enable_feature == true", &results));
|
||||
assert!(evaluate_condition("name == test", &results));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_file_exists_with_existing_file() {
|
||||
let results = HashMap::new();
|
||||
|
||||
// Create a temporary file
|
||||
let temp_dir = std::env::temp_dir();
|
||||
let test_file = temp_dir.join("typedialog_test_file.txt");
|
||||
std::fs::write(&test_file, "test content").unwrap();
|
||||
|
||||
// Test with double quotes
|
||||
let condition = format!("file_exists(\"{}\")", test_file.display());
|
||||
assert!(evaluate_condition(&condition, &results));
|
||||
|
||||
// Test with single quotes
|
||||
let condition = format!("file_exists('{}')", test_file.display());
|
||||
assert!(evaluate_condition(&condition, &results));
|
||||
|
||||
// Test without quotes
|
||||
let condition = format!("file_exists({})", test_file.display());
|
||||
assert!(evaluate_condition(&condition, &results));
|
||||
|
||||
// Clean up
|
||||
std::fs::remove_file(&test_file).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_file_exists_with_nonexistent_file() {
|
||||
let results = HashMap::new();
|
||||
|
||||
// Use a path that definitely doesn't exist
|
||||
let nonexistent = "/tmp/typedialog_nonexistent_file_12345.txt";
|
||||
|
||||
let condition = format!("file_exists(\"{}\")", nonexistent);
|
||||
assert!(!evaluate_condition(&condition, &results));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_file_exists_negated() {
|
||||
let results = HashMap::new();
|
||||
|
||||
// Create a temporary file
|
||||
let temp_dir = std::env::temp_dir();
|
||||
let test_file = temp_dir.join("typedialog_test_negation.txt");
|
||||
std::fs::write(&test_file, "test").unwrap();
|
||||
|
||||
// Negated: should return false for existing file
|
||||
let condition = format!("!file_exists(\"{}\")", test_file.display());
|
||||
assert!(!evaluate_condition(&condition, &results));
|
||||
|
||||
// Clean up
|
||||
std::fs::remove_file(&test_file).unwrap();
|
||||
|
||||
// After removal, negated should return true
|
||||
let condition = format!("!file_exists(\"{}\")", test_file.display());
|
||||
assert!(evaluate_condition(&condition, &results));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_file_exists_with_directory() {
|
||||
let results = HashMap::new();
|
||||
|
||||
// Test with an existing directory
|
||||
let temp_dir = std::env::temp_dir();
|
||||
let condition = format!("file_exists(\"{}\")", temp_dir.display());
|
||||
|
||||
// Path::exists() returns true for both files and directories
|
||||
assert!(evaluate_condition(&condition, &results));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_file_exists_with_relative_path() {
|
||||
let results = HashMap::new();
|
||||
|
||||
// Create a file in current directory
|
||||
std::fs::write("typedialog_test_relative.txt", "test").unwrap();
|
||||
|
||||
let condition = "file_exists(\"typedialog_test_relative.txt\")";
|
||||
assert!(evaluate_condition(condition, &results));
|
||||
|
||||
// Clean up
|
||||
std::fs::remove_file("typedialog_test_relative.txt").unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user