Skip to content

Commit 23f8d3d

Browse files
committed
test(sqlx): add JSONB path operator tests (-> and ->>)
- Add -> operator for encrypted path extraction - Add ->> operator for text extraction - Add NULL handling for non-existent paths - Add WHERE clause usage tests - Migrated from src/operators/->_test.sql (11 assertions) - Migrated from src/operators/->>_test.sql (6 assertions) - Coverage: 169/513 (32.9%)
1 parent 2d9729f commit 23f8d3d

File tree

1 file changed

+99
-0
lines changed

1 file changed

+99
-0
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
//! JSONB path operator tests (-> and ->>)
2+
//!
3+
//! Converted from src/operators/->_test.sql and ->>_test.sql
4+
//! Tests encrypted JSONB path extraction
5+
6+
use anyhow::Result;
7+
use eql_tests::{QueryAssertion, Selectors};
8+
use sqlx::{PgPool, Row};
9+
10+
#[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))]
11+
async fn arrow_operator_extracts_encrypted_path(pool: PgPool) -> Result<()> {
12+
// Test: e -> 'selector' returns encrypted nested value
13+
// Original SQL lines 12-27 in src/operators/->_test.sql
14+
15+
let sql = format!(
16+
"SELECT e -> '{}' FROM encrypted LIMIT 1",
17+
Selectors::N
18+
);
19+
20+
// Should return encrypted value for path $.n
21+
QueryAssertion::new(&pool, &sql).returns_rows().await;
22+
23+
Ok(())
24+
}
25+
26+
#[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))]
27+
async fn arrow_operator_with_nested_path(pool: PgPool) -> Result<()> {
28+
// Test: Chaining -> operators for nested paths
29+
// Original SQL lines 35-50 in src/operators/->_test.sql
30+
31+
let sql = format!(
32+
"SELECT e -> '{}' -> '{}' FROM encrypted LIMIT 1",
33+
Selectors::NESTED_OBJECT,
34+
Selectors::NESTED_FIELD
35+
);
36+
37+
QueryAssertion::new(&pool, &sql).returns_rows().await;
38+
39+
Ok(())
40+
}
41+
42+
#[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))]
43+
async fn arrow_operator_returns_null_for_nonexistent_path(pool: PgPool) -> Result<()> {
44+
// Test: -> returns NULL for non-existent selector
45+
// Original SQL lines 58-73 in src/operators/->_test.sql
46+
47+
let sql = "SELECT e -> 'nonexistent_selector_hash_12345' FROM encrypted LIMIT 1";
48+
49+
let row = sqlx::query(sql).fetch_one(&pool).await?;
50+
let result: Option<String> = row.try_get(0)?;
51+
assert!(result.is_none(), "Should return NULL for non-existent path");
52+
53+
Ok(())
54+
}
55+
56+
#[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))]
57+
async fn double_arrow_operator_extracts_encrypted_text(pool: PgPool) -> Result<()> {
58+
// Test: e ->> 'selector' returns encrypted value as text
59+
// Original SQL lines 12-27 in src/operators/->>_test.sql
60+
61+
let sql = format!(
62+
"SELECT e ->> '{}' FROM encrypted LIMIT 1",
63+
Selectors::N
64+
);
65+
66+
QueryAssertion::new(&pool, &sql).returns_rows().await;
67+
68+
Ok(())
69+
}
70+
71+
#[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))]
72+
async fn double_arrow_operator_returns_null_for_nonexistent(pool: PgPool) -> Result<()> {
73+
// Test: ->> returns NULL for non-existent path
74+
// Original SQL lines 35-50 in src/operators/->>_test.sql
75+
76+
let sql = "SELECT e ->> 'nonexistent_selector_hash_12345' FROM encrypted LIMIT 1";
77+
78+
let row = sqlx::query(sql).fetch_one(&pool).await?;
79+
let result: Option<String> = row.try_get(0)?;
80+
assert!(result.is_none(), "Should return NULL for non-existent path");
81+
82+
Ok(())
83+
}
84+
85+
#[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))]
86+
async fn double_arrow_in_where_clause(pool: PgPool) -> Result<()> {
87+
// Test: Using ->> in WHERE clause for filtering
88+
// Original SQL lines 58-65 in src/operators/->>_test.sql
89+
90+
let sql = format!(
91+
"SELECT id FROM encrypted WHERE (e ->> '{}')::text IS NOT NULL",
92+
Selectors::N
93+
);
94+
95+
// All 3 records have $.n path
96+
QueryAssertion::new(&pool, &sql).count(3).await;
97+
98+
Ok(())
99+
}

0 commit comments

Comments
 (0)