@@ -282,6 +282,91 @@ describe('SQLiteUtils tests', () => {
282
282
283
283
expect ( whereClauseFromPredicate ( predicateGroup as any ) ) . toEqual ( expected ) ;
284
284
} ) ;
285
+
286
+ it ( 'should generate valid WHERE clause with `in` operator and AND condition' , ( ) => {
287
+ const predicateGroup = {
288
+ type : 'and' ,
289
+ predicates : [
290
+ {
291
+ field : 'status' ,
292
+ operator : 'in' ,
293
+ operand : [ 'active' , 'pending' ] ,
294
+ } ,
295
+ {
296
+ field : 'priority' ,
297
+ operator : 'ge' ,
298
+ operand : 5 ,
299
+ } ,
300
+ ] ,
301
+ } ;
302
+
303
+ const expected = [
304
+ `WHERE ("status" IN (?, ?) AND "priority" >= ?)` ,
305
+ [ 'active' , 'pending' , 5 ] ,
306
+ ] ;
307
+
308
+ expect ( whereClauseFromPredicate ( predicateGroup as any ) ) . toEqual ( expected ) ;
309
+ } ) ;
310
+
311
+ it ( 'should generate valid WHERE clause with `notIn` operator and OR condition' , ( ) => {
312
+ const predicateGroup = {
313
+ type : 'or' ,
314
+ predicates : [
315
+ {
316
+ field : 'status' ,
317
+ operator : 'notIn' ,
318
+ operand : [ 'archived' , 'deleted' ] ,
319
+ } ,
320
+ {
321
+ field : 'isActive' ,
322
+ operator : 'eq' ,
323
+ operand : true ,
324
+ } ,
325
+ ] ,
326
+ } ;
327
+
328
+ const expected = [
329
+ `WHERE ("status" NOT IN (?, ?) OR "isActive" = ?)` ,
330
+ [ 'archived' , 'deleted' , true ] ,
331
+ ] ;
332
+
333
+ expect ( whereClauseFromPredicate ( predicateGroup as any ) ) . toEqual ( expected ) ;
334
+ } ) ;
335
+
336
+ it ( 'should generate valid WHERE clause with nested AND/OR containing `in` operators' , ( ) => {
337
+ const predicateGroup = {
338
+ type : 'and' ,
339
+ predicates : [
340
+ {
341
+ type : 'or' ,
342
+ predicates : [
343
+ {
344
+ field : 'category' ,
345
+ operator : 'in' ,
346
+ operand : [ 'tech' , 'science' ] ,
347
+ } ,
348
+ {
349
+ field : 'featured' ,
350
+ operator : 'eq' ,
351
+ operand : true ,
352
+ } ,
353
+ ] ,
354
+ } ,
355
+ {
356
+ field : 'status' ,
357
+ operator : 'notIn' ,
358
+ operand : [ 'draft' , 'archived' ] ,
359
+ } ,
360
+ ] ,
361
+ } ;
362
+
363
+ const expected = [
364
+ `WHERE (("category" IN (?, ?) OR "featured" = ?) AND "status" NOT IN (?, ?))` ,
365
+ [ 'tech' , 'science' , true , 'draft' , 'archived' ] ,
366
+ ] ;
367
+
368
+ expect ( whereClauseFromPredicate ( predicateGroup as any ) ) . toEqual ( expected ) ;
369
+ } ) ;
285
370
} ) ;
286
371
287
372
describe ( 'whereConditionFromPredicateObject' , ( ) => {
@@ -337,6 +422,126 @@ describe('SQLiteUtils tests', () => {
337
422
expected ,
338
423
) ;
339
424
} ) ;
425
+
426
+ it ( 'should generate valid `in` condition with string array' , ( ) => {
427
+ const predicate = {
428
+ field : 'status' ,
429
+ operator : 'in' ,
430
+ operand : [ 'active' , 'pending' , 'draft' ] ,
431
+ } ;
432
+
433
+ const expected = [ `"status" IN (?, ?, ?)` , [ 'active' , 'pending' , 'draft' ] ] ;
434
+
435
+ expect ( whereConditionFromPredicateObject ( predicate as any ) ) . toEqual ( expected ) ;
436
+ } ) ;
437
+
438
+ it ( 'should generate valid `notIn` condition with string array' , ( ) => {
439
+ const predicate = {
440
+ field : 'status' ,
441
+ operator : 'notIn' ,
442
+ operand : [ 'archived' , 'deleted' ] ,
443
+ } ;
444
+
445
+ const expected = [ `"status" NOT IN (?, ?)` , [ 'archived' , 'deleted' ] ] ;
446
+
447
+ expect ( whereConditionFromPredicateObject ( predicate as any ) ) . toEqual ( expected ) ;
448
+ } ) ;
449
+
450
+ it ( 'should generate valid `in` condition with number array' , ( ) => {
451
+ const predicate = {
452
+ field : 'priority' ,
453
+ operator : 'in' ,
454
+ operand : [ 1 , 3 , 5 ] ,
455
+ } ;
456
+
457
+ const expected = [ `"priority" IN (?, ?, ?)` , [ 1 , 3 , 5 ] ] ;
458
+
459
+ expect ( whereConditionFromPredicateObject ( predicate as any ) ) . toEqual ( expected ) ;
460
+ } ) ;
461
+
462
+ it ( 'should generate valid `notIn` condition with mixed types' , ( ) => {
463
+ const predicate = {
464
+ field : 'value' ,
465
+ operator : 'notIn' ,
466
+ operand : [ 1 , 'two' , true , null ] ,
467
+ } ;
468
+
469
+ const expected = [ `"value" NOT IN (?, ?, ?, ?)` , [ 1 , 'two' , true , null ] ] ;
470
+
471
+ expect ( whereConditionFromPredicateObject ( predicate as any ) ) . toEqual ( expected ) ;
472
+ } ) ;
473
+
474
+ it ( 'should handle empty array for `in` (always false)' , ( ) => {
475
+ const predicate = {
476
+ field : 'status' ,
477
+ operator : 'in' ,
478
+ operand : [ ] ,
479
+ } ;
480
+
481
+ const expected = [ `1 = 0` , [ ] ] ;
482
+
483
+ expect ( whereConditionFromPredicateObject ( predicate as any ) ) . toEqual ( expected ) ;
484
+ } ) ;
485
+
486
+ it ( 'should handle empty array for `notIn` (always true)' , ( ) => {
487
+ const predicate = {
488
+ field : 'status' ,
489
+ operator : 'notIn' ,
490
+ operand : [ ] ,
491
+ } ;
492
+
493
+ const expected = [ `1 = 1` , [ ] ] ;
494
+
495
+ expect ( whereConditionFromPredicateObject ( predicate as any ) ) . toEqual ( expected ) ;
496
+ } ) ;
497
+
498
+ it ( 'should throw error for `in` with non-array operand' , ( ) => {
499
+ const predicate = {
500
+ field : 'status' ,
501
+ operator : 'in' ,
502
+ operand : 'not-an-array' ,
503
+ } ;
504
+
505
+ expect ( ( ) => whereConditionFromPredicateObject ( predicate as any ) ) . toThrow (
506
+ 'Operand for in must be an array' ,
507
+ ) ;
508
+ } ) ;
509
+
510
+ it ( 'should throw error for `notIn` with non-array operand' , ( ) => {
511
+ const predicate = {
512
+ field : 'status' ,
513
+ operator : 'notIn' ,
514
+ operand : 'not-an-array' ,
515
+ } ;
516
+
517
+ expect ( ( ) => whereConditionFromPredicateObject ( predicate as any ) ) . toThrow (
518
+ 'Operand for notIn must be an array' ,
519
+ ) ;
520
+ } ) ;
521
+
522
+ it ( 'should handle `in` with complex objects (JSON.stringify)' , ( ) => {
523
+ const predicate = {
524
+ field : 'metadata' ,
525
+ operator : 'in' ,
526
+ operand : [ { id : 1 } , { id : 2 } ] ,
527
+ } ;
528
+
529
+ const expected = [ `"metadata" IN (?, ?)` , [ '{"id":1}' , '{"id":2}' ] ] ;
530
+
531
+ expect ( whereConditionFromPredicateObject ( predicate as any ) ) . toEqual ( expected ) ;
532
+ } ) ;
533
+
534
+ it ( 'should handle `notIn` with null values' , ( ) => {
535
+ const predicate = {
536
+ field : 'tags' ,
537
+ operator : 'notIn' ,
538
+ operand : [ 'urgent' , null , 'archived' ] ,
539
+ } ;
540
+
541
+ const expected = [ `"tags" NOT IN (?, ?, ?)` , [ 'urgent' , null , 'archived' ] ] ;
542
+
543
+ expect ( whereConditionFromPredicateObject ( predicate as any ) ) . toEqual ( expected ) ;
544
+ } ) ;
340
545
} ) ;
341
546
342
547
describe ( 'limitClauseFromPagination' , ( ) => {
0 commit comments