Skip to content

Commit 4f3f7be

Browse files
committed
feat(cel-proto-parser): add fixture-based round-trip testing
- Add basic.txt fixture file with handful of representative CEL expressions - Update test-roundtrip.ts to load fixtures from file via CLI argument - Run with: npx tsx scripts/test-roundtrip.ts __fixtures__/expressions/basic.txt
1 parent 23fffba commit 4f3f7be

2 files changed

Lines changed: 149 additions & 84 deletions

File tree

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Basic CEL Expression Fixtures for Round-Trip Testing
2+
# A small handful of representative expressions
3+
4+
# Simple values
5+
42
6+
3.14
7+
true
8+
"hello"
9+
10+
# Field access
11+
request.auth
12+
request.auth.claims.email
13+
14+
# Arithmetic
15+
1 + 2
16+
a * b + c
17+
18+
# Comparison
19+
x == y
20+
size(list) > 0
21+
22+
# Logical
23+
a && b
24+
!enabled
25+
26+
# Ternary
27+
x ? 1 : 2
28+
29+
# Collections
30+
[1, 2, 3]
31+
{"key": "value"}
32+
33+
# Function calls
34+
size(items)

packages/cel-proto-parser/scripts/test-roundtrip.ts

Lines changed: 115 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,18 @@
66
* for parsing and our deparser for converting back to CEL strings.
77
*
88
* Run with: npx ts-node --esm scripts/test-roundtrip.ts
9+
* Or with a fixture file: npx ts-node --esm scripts/test-roundtrip.ts __fixtures__/expressions/basic.txt
910
*/
1011

1112
import { parse } from '@marcbachmann/cel-js';
1213
import { deparse, Expr } from '../src/deparser';
1314
import { convertToProtoExpr, MarcAstNode } from '../src/converter';
15+
import { readFileSync } from 'fs';
16+
import { resolve, dirname } from 'path';
17+
import { fileURLToPath } from 'url';
18+
19+
const __filename = fileURLToPath(import.meta.url);
20+
const __dirname = dirname(__filename);
1421

1522
interface TestResult {
1623
expression: string;
@@ -51,90 +58,114 @@ function testRoundTrip(expression: string): TestResult {
5158
}
5259
}
5360

54-
const testCases = [
55-
// Literals
56-
'1',
57-
'42',
58-
'3.14',
59-
'true',
60-
'false',
61-
'null',
62-
'"hello"',
63-
'"hello world"',
64-
65-
// Unsigned integers
66-
'1u',
67-
'42u',
68-
69-
// Identifiers
70-
'x',
71-
'foo',
72-
'request',
73-
74-
// Field access
75-
'request.auth',
76-
'request.auth.claims',
77-
'request.auth.claims.email',
78-
79-
// Arithmetic operators
80-
'1 + 2',
81-
'a + b',
82-
'x - y',
83-
'a * b',
84-
'x / y',
85-
'1 + 2 * 3',
86-
87-
// Comparison operators
88-
'a == b',
89-
'x != y',
90-
'a < b',
91-
'a <= b',
92-
'a > b',
93-
'a >= b',
94-
95-
// Logical operators
96-
'a && b',
97-
'x || y',
98-
'!a',
99-
'a && b && c',
100-
'a || b || c',
101-
102-
// Ternary conditional
103-
'x ? 1 : 2',
104-
'a == b ? "yes" : "no"',
105-
106-
// List literals
107-
'[]',
108-
'[1]',
109-
'[1, 2, 3]',
110-
111-
// Map literals
112-
'{}',
113-
'{"a": 1}',
114-
'{"a": 1, "b": 2}',
115-
116-
// Index access
117-
'list[0]',
118-
'map["key"]',
119-
120-
// Function calls
121-
'size(list)',
122-
'int(x)',
123-
'string(42)',
124-
125-
// Method calls
126-
'list.size()',
127-
'str.contains("test")',
128-
129-
// In operator
130-
'x in list',
131-
'"admin" in roles',
132-
133-
// Complex expressions
134-
'request.auth.claims.email == "admin@example.com"',
135-
'size(request.body) > 0 && request.method == "POST"',
136-
'user.age >= 18 && "admin" in user.roles'
137-
];
61+
/**
62+
* Load CEL expressions from a fixture file
63+
* Lines starting with # are comments, empty lines are ignored
64+
*/
65+
function loadFixtures(filePath: string): string[] {
66+
const content = readFileSync(filePath, 'utf-8');
67+
return content
68+
.split('\n')
69+
.map((line) => line.trim())
70+
.filter((line) => line && !line.startsWith('#'));
71+
}
72+
73+
// Check if a fixture file was provided as argument
74+
const fixtureArg = process.argv[2];
75+
let testCases: string[];
76+
77+
if (fixtureArg) {
78+
// Load from fixture file
79+
const fixturePath = resolve(__dirname, '..', fixtureArg);
80+
console.log(`Loading fixtures from: ${fixturePath}\n`);
81+
testCases = loadFixtures(fixturePath);
82+
} else {
83+
// Use default test cases
84+
testCases = [
85+
// Literals
86+
'1',
87+
'42',
88+
'3.14',
89+
'true',
90+
'false',
91+
'null',
92+
'"hello"',
93+
'"hello world"',
94+
95+
// Unsigned integers
96+
'1u',
97+
'42u',
98+
99+
// Identifiers
100+
'x',
101+
'foo',
102+
'request',
103+
104+
// Field access
105+
'request.auth',
106+
'request.auth.claims',
107+
'request.auth.claims.email',
108+
109+
// Arithmetic operators
110+
'1 + 2',
111+
'a + b',
112+
'x - y',
113+
'a * b',
114+
'x / y',
115+
'1 + 2 * 3',
116+
117+
// Comparison operators
118+
'a == b',
119+
'x != y',
120+
'a < b',
121+
'a <= b',
122+
'a > b',
123+
'a >= b',
124+
125+
// Logical operators
126+
'a && b',
127+
'x || y',
128+
'!a',
129+
'a && b && c',
130+
'a || b || c',
131+
132+
// Ternary conditional
133+
'x ? 1 : 2',
134+
'a == b ? "yes" : "no"',
135+
136+
// List literals
137+
'[]',
138+
'[1]',
139+
'[1, 2, 3]',
140+
141+
// Map literals
142+
'{}',
143+
'{"a": 1}',
144+
'{"a": 1, "b": 2}',
145+
146+
// Index access
147+
'list[0]',
148+
'map["key"]',
149+
150+
// Function calls
151+
'size(list)',
152+
'int(x)',
153+
'string(42)',
154+
155+
// Method calls
156+
'list.size()',
157+
'str.contains("test")',
158+
159+
// In operator
160+
'x in list',
161+
'"admin" in roles',
162+
163+
// Complex expressions
164+
'request.auth.claims.email == "admin@example.com"',
165+
'size(request.body) > 0 && request.method == "POST"',
166+
'user.age >= 18 && "admin" in user.roles'
167+
];
168+
}
138169

139170
console.log('CEL Round-Trip Tests');
140171
console.log('====================\n');

0 commit comments

Comments
 (0)