Skip to content

Commit 61f6777

Browse files
Merge branch 'main' into feat/rtn-web-browser-unit-tests
2 parents 96294b8 + 8399513 commit 61f6777

File tree

8 files changed

+538
-42
lines changed

8 files changed

+538
-42
lines changed

packages/datastore-storage-adapter/__tests__/SQLiteUtils.test.ts

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,91 @@ describe('SQLiteUtils tests', () => {
282282

283283
expect(whereClauseFromPredicate(predicateGroup as any)).toEqual(expected);
284284
});
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+
});
285370
});
286371

287372
describe('whereConditionFromPredicateObject', () => {
@@ -337,6 +422,126 @@ describe('SQLiteUtils tests', () => {
337422
expected,
338423
);
339424
});
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+
});
340545
});
341546

342547
describe('limitClauseFromPagination', () => {

packages/datastore-storage-adapter/src/common/CommonSQLiteAdapter.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
PredicateObject,
1717
PredicatesGroup,
1818
QueryOne,
19+
SchemaModel,
1920
StorageAdapter,
2021
isPredicateObj,
2122
utils,
@@ -86,9 +87,9 @@ export class CommonSQLiteAdapter implements StorageAdapter {
8687

8788
try {
8889
const usesCPKCodegen = Object.values(
89-
this.schema.namespaces.user.models,
90+
this.schema.namespaces.user?.models || {},
9091
).some(model =>
91-
Object.values(model.fields).some(field =>
92+
Object.values((model as SchemaModel).fields).some((field: any) =>
9293
// eslint-disable-next-line no-prototype-builtins
9394
field.association?.hasOwnProperty('targetNames'),
9495
),

0 commit comments

Comments
 (0)