#[path = "testutils/mod.rs"]
mod testutils;
use graphlite::Value;
use testutils::test_fixture::TestFixture;
#[test]
fn test_duration_function_in_node_insert() {
let fixture = TestFixture::new().expect("Failed to create fixture");
fixture
.setup_graph("duration_node_test")
.expect("Failed to setup graph");
let result = fixture
.query("INSERT (:Example {age: duration('P30Y')})")
.expect("INSERT with duration() should succeed");
assert_eq!(result.rows_affected, 1, "Should have inserted 1 node");
let query_result = fixture
.query("MATCH (e:Example) RETURN e.age as age")
.expect("Query should succeed");
assert_eq!(query_result.rows.len(), 1, "Should return 1 node");
let age_value = &query_result.rows[0].values["age"];
assert!(age_value != &Value::Null, "Duration should not be null");
assert!(
matches!(age_value, Value::Number(_)),
"Duration should be a number"
);
}
#[test]
fn test_duration_function_in_edge_insert() {
let fixture = TestFixture::new().expect("Failed to create fixture");
fixture
.setup_graph("duration_edge_test")
.expect("Failed to setup graph");
fixture
.query("INSERT (:Person {name: 'Alice'})")
.expect("Failed to create first node");
fixture
.query("INSERT (:Person {name: 'Bob'})")
.expect("Failed to create second node");
let result = fixture
.query(
"MATCH (a:Person {name: 'Alice'}), (b:Person {name: 'Bob'}) \
INSERT (a)-[:KNOWS {duration: duration('P5Y'), since: 2020}]->(b)",
)
.expect("INSERT edge with duration() should succeed");
assert_eq!(result.rows_affected, 1, "Should have inserted 1 edge");
let query_result = fixture
.query(
"MATCH (a:Person {name: 'Alice'})-[r:KNOWS]->(b:Person {name: 'Bob'}) \
RETURN r.duration as duration, r.since as since",
)
.expect("Query should succeed");
assert_eq!(query_result.rows.len(), 1, "Should return 1 edge");
let duration_value = &query_result.rows[0].values["duration"];
assert!(
duration_value != &Value::Null,
"Duration should not be null"
);
assert!(
matches!(duration_value, Value::Number(_)),
"Duration should be a number"
);
let since_value = &query_result.rows[0].values["since"];
assert_eq!(since_value, &Value::Number(2020.0), "Since should be 2020");
}
#[test]
fn test_multiple_function_types_in_node_insert() {
let fixture = TestFixture::new().expect("Failed to create fixture");
fixture
.setup_graph("multi_function_node_test")
.expect("Failed to setup graph");
fixture
.query("INSERT (:StringTest {value: upper('hello')})")
.expect("INSERT with upper() should succeed");
fixture
.query("INSERT (:StringTest {value: lower('WORLD')})")
.expect("INSERT with lower() should succeed");
fixture
.query("INSERT (:MathTest {value: abs(-42.5)})")
.expect("INSERT with abs() should succeed");
fixture
.query("INSERT (:MathTest {value: floor(42.7)})")
.expect("INSERT with floor() should succeed");
fixture
.query("INSERT (:MathTest {value: ceil(4.3)})")
.expect("INSERT with ceil() should succeed");
fixture
.query("INSERT (:MathTest {value: round(3.14159)})")
.expect("INSERT with round() should succeed");
let upper_result = fixture
.query("MATCH (s:StringTest {value: 'HELLO'}) RETURN s.value as value")
.expect("Query should succeed");
assert_eq!(upper_result.rows.len(), 1, "upper() should create 'HELLO'");
let lower_result = fixture
.query("MATCH (s:StringTest {value: 'world'}) RETURN s.value as value")
.expect("Query should succeed");
assert_eq!(lower_result.rows.len(), 1, "lower() should create 'world'");
}
#[test]
fn test_multiple_function_types_in_edge_insert() {
let fixture = TestFixture::new().expect("Failed to create fixture");
fixture
.setup_graph("multi_function_edge_test")
.expect("Failed to setup graph");
fixture
.query("INSERT (:User {id: 1, name: 'Alice'})")
.expect("Failed to create first node");
fixture
.query("INSERT (:User {id: 2, name: 'Bob'})")
.expect("Failed to create second node");
let result = fixture
.query(
"MATCH (a:User {id: 1}), (b:User {id: 2}) \
INSERT (a)-[:SENT_MESSAGE { \
subject: upper('hello'), \
preview: substring('This is a preview of the message', 0, 10), \
priority: abs(-5), \
sent_at: duration('P0DT1H30M'), \
word_count: round(123.7) \
}]->(b)",
)
.expect("INSERT edge with multiple functions should succeed");
assert_eq!(result.rows_affected, 1, "Should have inserted 1 edge");
let query_result = fixture
.query(
"MATCH (a:User {id: 1})-[r:SENT_MESSAGE]->(b:User {id: 2}) \
RETURN r.subject as subject, r.preview as preview, r.priority as priority, \
r.sent_at as sent_at, r.word_count as word_count",
)
.expect("Query should succeed");
assert_eq!(query_result.rows.len(), 1, "Should return 1 edge");
let row = &query_result.rows[0].values;
assert_eq!(
row.get("subject"),
Some(&Value::String("HELLO".to_string())),
"upper() should work in edge"
);
assert_eq!(
row.get("preview"),
Some(&Value::String("This is a ".to_string())),
"substring() should work in edge"
);
assert_eq!(
row.get("priority"),
Some(&Value::Number(5.0)),
"abs() should work in edge"
);
assert!(
row.get("sent_at") != Some(&Value::Null),
"duration() should work in edge"
);
assert_eq!(
row.get("word_count"),
Some(&Value::Number(124.0)),
"round() should work in edge"
);
}
#[test]
fn test_nested_function_calls_in_insert() {
let fixture = TestFixture::new().expect("Failed to create fixture");
fixture
.setup_graph("nested_function_test")
.expect("Failed to setup graph");
let result = fixture
.query(
"INSERT (:Data { \
value: round(abs(-42.7)), \
text: upper(lower('MiXeD CaSe')) \
})",
)
.expect("INSERT with nested functions should succeed");
assert_eq!(result.rows_affected, 1, "Should have inserted 1 node");
let query_result = fixture
.query("MATCH (d:Data) RETURN d.value as value, d.text as text")
.expect("Query should succeed");
let row = &query_result.rows[0].values;
assert_eq!(
row.get("value"),
Some(&Value::Number(43.0)),
"Nested round(abs()) should work"
);
assert_eq!(
row.get("text"),
Some(&Value::String("MIXED CASE".to_string())),
"Nested upper(lower()) should work"
);
}
#[test]
fn test_comprehensive_function_coverage() {
let fixture = TestFixture::new().expect("Failed to create fixture");
fixture
.setup_graph("comprehensive_test")
.expect("Failed to setup graph");
fixture
.query("INSERT (:Test {str1: upper('test'), str2: lower('TEST')})")
.expect("String functions should work");
fixture
.query("INSERT (:Test {math1: abs(-100), math2: floor(99.9), math3: ceil(0.1)})")
.expect("Math functions should work");
fixture
.query("INSERT (:Test {temp1: duration('P1Y')})")
.expect("Temporal functions should work");
let string_result = fixture
.query("MATCH (t:Test) WHERE t.str1 IS NOT NULL RETURN t.str1 as upper, t.str2 as lower")
.expect("Query should succeed");
assert_eq!(string_result.rows.len(), 1);
assert_eq!(
string_result.rows[0].values.get("upper"),
Some(&Value::String("TEST".to_string()))
);
assert_eq!(
string_result.rows[0].values.get("lower"),
Some(&Value::String("test".to_string()))
);
let math_result = fixture.query("MATCH (t:Test) WHERE t.math1 IS NOT NULL RETURN t.math1 as abs, t.math2 as floor, t.math3 as ceil")
.expect("Query should succeed");
assert_eq!(math_result.rows.len(), 1);
assert_eq!(
math_result.rows[0].values.get("abs"),
Some(&Value::Number(100.0))
);
assert_eq!(
math_result.rows[0].values.get("floor"),
Some(&Value::Number(99.0))
);
assert_eq!(
math_result.rows[0].values.get("ceil"),
Some(&Value::Number(1.0))
);
}