import { describe, it, expect } from 'vitest'; import { validateExpression, referencedFields } from './expr-validate'; describe('validateExpression', () => { it('accepts a well-formed Vega expression', () => { expect(validateExpression('datum.price * datum.qty').valid).toBe(true); expect(validateExpression("datum.region === 'East' && datum.value > 0").valid).toBe(true); }); it('treats an empty / whitespace expression as valid (incomplete, not a mistake)', () => { expect(validateExpression('').valid).toBe(true); expect(validateExpression(' ').valid).toBe(true); }); it('rejects a malformed expression with a message', () => { const result = validateExpression('datum.price *'); expect(result.valid).toBe(false); expect(result.error).toBeTruthy(); }); }); describe('referencedFields', () => { it('collects datum.field and datum["field"] references, de-duplicated in order', () => { expect(referencedFields("datum.price * datum['qty'] + datum.price")).toEqual(['price', 'qty']); }); it('ignores function calls and non-datum identifiers', () => { expect(referencedFields('toNumber(datum.amount) + PI')).toEqual(['amount']); }); it('skips dynamic (computed, non-literal) access', () => { expect(referencedFields('datum[someVar]')).toEqual([]); }); it('returns nothing for an empty or unparseable expression', () => { expect(referencedFields('')).toEqual([]); expect(referencedFields('datum.price *')).toEqual([]); }); });