@@ -28,7 +28,7 @@ describe('PictConstraintsLexer with single constraints', () => {
2828
2929 it ( 'should handle NOT conditions correctly' , ( ) => {
3030 const lexer = new PictConstraintsLexer ( `
31- IF NOT [PRODUCT] = "Book" THEN [AVAILABLE] = "Yes " ELSE [AVAILABLE] = "No";
31+ IF NOT [PRODUCT] = "Book" THEN [AVAILABLE] <> "No " ELSE [AVAILABLE] = "No";
3232 ` , false ) ;
3333 const row1 = { PRODUCT : 'Pen' , AVAILABLE : 'Yes' } ;
3434 expect ( lexer . filter ( row1 ) ) . toBe ( true ) ;
@@ -47,7 +47,7 @@ describe('PictConstraintsLexer with single constraints', () => {
4747 const row1 = { CATEGORY : 'Electronics' , BRAND : 'Sony' , WARRANTY : 'Included' } ;
4848 expect ( lexer . filter ( row1 ) ) . toBe ( true ) ;
4949
50- const row2 = { CATEGORY : 'Electronics' , BRAND : 'Samsung ' , WARRANTY : 'Not Included' } ;
50+ const row2 = { CATEGORY : 'Electronics' , BRAND : 'General Electric Company ' , WARRANTY : 'Not Included' } ;
5151 expect ( lexer . filter ( row2 ) ) . toBe ( true ) ;
5252
5353 const row3 = { CATEGORY : 'Electronics' , BRAND : 'Sony' , WARRANTY : 'Not Included' } ;
@@ -71,17 +71,17 @@ describe('PictConstraintsLexer with single constraints', () => {
7171 expect ( lexer . filter ( row4 ) ) . toBe ( false ) ;
7272 } ) ;
7373
74- it ( 'should handle string equality conditions ' , ( ) => {
74+ it ( 'should handle fields containing spaces ' , ( ) => {
7575 const lexer = new PictConstraintsLexer ( `
76- IF [NAME] = "Bob " THEN [STATUS] = "Inactive" ELSE [STATUS] = "Active" ;
76+ IF [PRODUCT NAME] = "Laptop " THEN [PRICE] > 500 ELSE [PRICE] <= 500 ;
7777 ` , false ) ;
78- const row1 = { NAME : 'Bob ' , STATUS : 'Inactive' } ;
78+ const row1 = { 'PRODUCT NAME' : 'Laptop ' , PRICE : 600 } ;
7979 expect ( lexer . filter ( row1 ) ) . toBe ( true ) ;
8080
81- const row2 = { NAME : 'Alice ' , STATUS : 'Active' } ;
82- expect ( lexer . filter ( row2 ) ) . toBe ( true ) ;
81+ const row2 = { 'PRODUCT NAME' : 'Laptop ' , PRICE : 400 } ;
82+ expect ( lexer . filter ( row2 ) ) . toBe ( false ) ;
8383
84- const row3 = { NAME : 'Bob ' , STATUS : 'Active' } ;
84+ const row3 = { 'PRODUCT NAME' : 'Desktop ' , PRICE : 600 } ;
8585 expect ( lexer . filter ( row3 ) ) . toBe ( false ) ;
8686 } ) ;
8787
@@ -118,6 +118,40 @@ describe('PictConstraintsLexer with single constraints', () => {
118118 const row5 = { AGE : 25 , COUNTRY : 'Canada' , STATUS : 'Denied' } ;
119119 expect ( lexer . filter ( row5 ) ) . toBe ( false ) ;
120120 } ) ;
121+ it ( 'should handle false in ELSE condition' , ( ) => {
122+ const lexer = new PictConstraintsLexer ( `
123+ IF [NAME] = "Bob" THEN [STATUS] = "Inactive" ELSE FALSE;
124+ ` , false ) ;
125+ const row1 = { NAME : 'Bob' , STATUS : 'Inactive' } ;
126+ expect ( lexer . filter ( row1 ) ) . toBe ( true ) ;
127+
128+ const row2 = { NAME : 'Alice' , STATUS : 'Active' } ;
129+ expect ( lexer . filter ( row2 ) ) . toBe ( false ) ;
130+ } ) ;
131+
132+ it ( 'should handle true in ELSE condition' , ( ) => {
133+ const lexer = new PictConstraintsLexer ( `
134+ IF [NAME] = "Bob" THEN [STATUS] = "Inactive" ELSE true;
135+ ` , false ) ;
136+ const row1 = { NAME : 'Bob' , STATUS : 'Inactive' } ;
137+ expect ( lexer . filter ( row1 ) ) . toBe ( true ) ;
138+
139+ const row2 = { NAME : 'Alice' , STATUS : 'Active' } ;
140+ expect ( lexer . filter ( row2 ) ) . toBe ( true ) ;
141+ } ) ;
142+ it ( 'Compare with other fields' , ( ) => {
143+ const lexer = new PictConstraintsLexer ( `
144+ IF [NAME] = [ALIAS] THEN [AGE] <= 26;
145+ ` , false ) ;
146+ const row1 = { NAME : 'Bob' , ALIAS : 'Bob' , AGE : 18 } ;
147+ expect ( lexer . filter ( row1 ) ) . toBe ( true ) ;
148+
149+ const row2 = { NAME : 'Alice' , ALIAS : 'Lissie' , AGE : 25 } ;
150+ expect ( lexer . filter ( row2 ) ) . toBe ( true ) ;
151+
152+ const row3 = { NAME : 'Shohei' , ALIAS : 'Shohei' , AGE : 30 } ;
153+ expect ( lexer . filter ( row3 ) ) . toBe ( false ) ;
154+ } ) ;
121155} ) ;
122156
123157describe ( 'PictConstraintsLexer with multiple constraints' , ( ) => {
@@ -248,3 +282,102 @@ describe('PictConstraintsLexer with multiple constraints', () => {
248282 expect ( lexer . filter ( row3 ) ) . toBe ( true ) ;
249283 } ) ;
250284} ) ;
285+
286+ describe ( 'PictConstraintsLexer with invalid constraints' , ( ) => {
287+ it ( 'Unknown comparer' , ( ) => {
288+ const lexer = new PictConstraintsLexer ( `
289+ IF [NAME] @ "Alice" THEN [STATUS] = "Active" ELSE [STATUS] = "Inactive";
290+ ` , false ) ;
291+ expect ( lexer . errors . length ) . toBe ( 1 ) ;
292+ expect ( lexer . errors [ 0 ] ) . toBe ( 'Unknown comparison operator: @' ) ;
293+ } ) ;
294+
295+ it ( 'Comparison operator missing, got a value' , ( ) => {
296+ const lexer = new PictConstraintsLexer ( `
297+ IF [NAME] "Alice" THEN [STATUS] = "Active" ELSE [STATUS] = "Inactive";
298+ ` , false ) ;
299+ expect ( lexer . errors . length ) . toBe ( 1 ) ;
300+ expect ( lexer . errors [ 0 ] ) . toBe ( 'Expected comparison operator but found value: "Alice"' ) ;
301+ } ) ;
302+
303+ it ( 'Comparison operator missing, got an operator' , ( ) => {
304+ const lexer = new PictConstraintsLexer ( `
305+ IF [NAME] AND TRUE THEN [STATUS] = "Active" ELSE [STATUS] = "Inactive";
306+ ` , false ) ;
307+ expect ( lexer . errors . length ) . toBe ( 1 ) ;
308+ expect ( lexer . errors [ 0 ] ) . toBe ( 'Expected comparison operator but found operator: AND' ) ;
309+ } ) ;
310+
311+ it ( 'Comparison operator and value missing, got then' , ( ) => {
312+ const lexer = new PictConstraintsLexer ( `
313+ IF [NAME] THEN [STATUS] = "Active" ELSE [STATUS] = "Inactive"
314+ ` , false ) ;
315+ expect ( lexer . errors . length ) . toBe ( 1 ) ;
316+ expect ( lexer . errors [ 0 ] ) . toBe ( 'A comparison operator and value are required after the field.' ) ;
317+ } ) ;
318+ it ( 'Nothing after IF' , ( ) => {
319+ const lexer = new PictConstraintsLexer ( `
320+ IF THEN [STATUS] = "Active" ELSE [STATUS] = "Inactive"
321+ ` , false ) ;
322+ expect ( lexer . errors . length ) . toBe ( 1 ) ;
323+ expect ( lexer . errors [ 0 ] ) . toBe ( 'Expected field or value after "IF", "THEN", "ELSE"' ) ;
324+ } ) ;
325+
326+ it ( 'Nothing after THEN' , ( ) => {
327+ const lexer = new PictConstraintsLexer ( `
328+ IF [NAME] = "Summer" THEN ELSE [STATUS] = "Active"
329+ ` , false ) ;
330+ expect ( lexer . errors . length ) . toBe ( 1 ) ;
331+ expect ( lexer . errors [ 0 ] ) . toBe ( 'Expected field or value after "IF", "THEN", "ELSE"' ) ;
332+ } ) ;
333+
334+ it ( 'Nothing after ELSE' , ( ) => {
335+ const lexer = new PictConstraintsLexer ( `
336+ IF [NAME] = "Summer" THEN [STATUS] = "Active" ELSE
337+ ` , false ) ;
338+ expect ( lexer . errors . length ) . toBe ( 1 ) ;
339+ expect ( lexer . errors [ 0 ] ) . toBe ( 'Expected field or value after "IF", "THEN", "ELSE"' ) ;
340+ } ) ;
341+
342+
343+ it ( 'IF is missing, typo' , ( ) => {
344+ const lexer = new PictConstraintsLexer ( `
345+ F [NAME] = "Summer" THEN [STATUS] = "Active"
346+ ` , false ) ;
347+ expect ( lexer . errors . length ) . toBe ( 1 ) ;
348+ expect ( lexer . errors [ 0 ] ) . toBe ( 'Unknown token: F' ) ;
349+ } ) ;
350+
351+ it ( 'IF is nothing' , ( ) => {
352+ const lexer = new PictConstraintsLexer ( `
353+ [NAME] = "Summer" THEN [STATUS] = "Active"
354+ ` , false ) ;
355+ expect ( lexer . errors . length ) . toBe ( 1 ) ;
356+ expect ( lexer . errors [ 0 ] ) . toBe ( 'The leading "IF" is missing, found [NAME]' ) ;
357+ } ) ;
358+
359+
360+ it ( 'Multiple invalid expressions' , ( ) => {
361+ const lexer = new PictConstraintsLexer ( `
362+ IF [NAME] THEN [STATUS] = "Active";
363+ IF [NAME] = "Summer" THEN [STATUS] = "Active";
364+ IF [NAME] = "Summer" THEN [STATUS] = "Active" ELSE;
365+ IF [NAME] = "Summer" THEN [STATUS] = "Active";
366+ IF [NAME] @ "Summer" THEN [STATUS] = "Active" ELSE [STATUS] = "Inactive";
367+ ` , false ) ;
368+
369+ expect ( lexer . errors . length ) . toBe ( 5 ) ;
370+
371+ expect ( lexer . errors [ 0 ] ) . toBe ( 'A comparison operator and value are required after the field.' ) ;
372+ expect ( lexer . errors [ 1 ] ) . toBe ( null ) ;
373+ expect ( lexer . errors [ 2 ] ) . toBe ( 'Expected field or value after "IF", "THEN", "ELSE"' ) ;
374+ expect ( lexer . errors [ 3 ] ) . toBe ( null ) ;
375+ expect ( lexer . errors [ 4 ] ) . toBe ( 'Unknown comparison operator: @' ) ;
376+
377+ expect ( lexer . filters [ 0 ] ) . toBeNull ( ) ;
378+ expect ( lexer . filters [ 1 ] ) . not . toBeNull ( ) ;
379+ expect ( lexer . filters [ 2 ] ) . toBeNull ( ) ;
380+ expect ( lexer . filters [ 3 ] ) . not . toBeNull ( ) ;
381+ expect ( lexer . filters [ 4 ] ) . toBeNull ( ) ;
382+ } ) ;
383+ } ) ;
0 commit comments