jazz-tools 0.18.14 → 0.18.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +45 -33
- package/CHANGELOG.md +23 -0
- package/dist/better-auth/database-adapter/index.d.ts +50 -0
- package/dist/better-auth/database-adapter/index.d.ts.map +1 -0
- package/dist/better-auth/database-adapter/index.js +920 -0
- package/dist/better-auth/database-adapter/index.js.map +1 -0
- package/dist/better-auth/database-adapter/repository/account.d.ts +24 -0
- package/dist/better-auth/database-adapter/repository/account.d.ts.map +1 -0
- package/dist/better-auth/database-adapter/repository/generic.d.ts +45 -0
- package/dist/better-auth/database-adapter/repository/generic.d.ts.map +1 -0
- package/dist/better-auth/database-adapter/repository/index.d.ts +6 -0
- package/dist/better-auth/database-adapter/repository/index.d.ts.map +1 -0
- package/dist/better-auth/database-adapter/repository/session.d.ts +29 -0
- package/dist/better-auth/database-adapter/repository/session.d.ts.map +1 -0
- package/dist/better-auth/database-adapter/repository/user.d.ts +30 -0
- package/dist/better-auth/database-adapter/repository/user.d.ts.map +1 -0
- package/dist/better-auth/database-adapter/repository/verification.d.ts +18 -0
- package/dist/better-auth/database-adapter/repository/verification.d.ts.map +1 -0
- package/dist/better-auth/database-adapter/schema.d.ts +27 -0
- package/dist/better-auth/database-adapter/schema.d.ts.map +1 -0
- package/dist/better-auth/database-adapter/tests/index.test.d.ts +2 -0
- package/dist/better-auth/database-adapter/tests/index.test.d.ts.map +1 -0
- package/dist/better-auth/database-adapter/tests/repository/account.test.d.ts +2 -0
- package/dist/better-auth/database-adapter/tests/repository/account.test.d.ts.map +1 -0
- package/dist/better-auth/database-adapter/tests/repository/generic.test.d.ts +2 -0
- package/dist/better-auth/database-adapter/tests/repository/generic.test.d.ts.map +1 -0
- package/dist/better-auth/database-adapter/tests/repository/session.test.d.ts +2 -0
- package/dist/better-auth/database-adapter/tests/repository/session.test.d.ts.map +1 -0
- package/dist/better-auth/database-adapter/tests/repository/user.test.d.ts +2 -0
- package/dist/better-auth/database-adapter/tests/repository/user.test.d.ts.map +1 -0
- package/dist/better-auth/database-adapter/tests/repository/verification.test.d.ts +2 -0
- package/dist/better-auth/database-adapter/tests/repository/verification.test.d.ts.map +1 -0
- package/dist/better-auth/database-adapter/tests/sync-utils.d.ts +16 -0
- package/dist/better-auth/database-adapter/tests/sync-utils.d.ts.map +1 -0
- package/dist/better-auth/database-adapter/tests/utils.test.d.ts +2 -0
- package/dist/better-auth/database-adapter/tests/utils.test.d.ts.map +1 -0
- package/dist/better-auth/database-adapter/utils.d.ts +16 -0
- package/dist/better-auth/database-adapter/utils.d.ts.map +1 -0
- package/dist/worker/edge-wasm.d.ts +2 -0
- package/dist/worker/edge-wasm.d.ts.map +1 -0
- package/dist/worker/edge-wasm.js +5 -0
- package/dist/worker/edge-wasm.js.map +1 -0
- package/jazz-tools-0.18.6.tgz +0 -0
- package/package.json +15 -5
- package/src/better-auth/database-adapter/index.ts +228 -0
- package/src/better-auth/database-adapter/repository/account.ts +131 -0
- package/src/better-auth/database-adapter/repository/generic.ts +297 -0
- package/src/better-auth/database-adapter/repository/index.ts +5 -0
- package/src/better-auth/database-adapter/repository/session.ts +190 -0
- package/src/better-auth/database-adapter/repository/user.ts +158 -0
- package/src/better-auth/database-adapter/repository/verification.ts +37 -0
- package/src/better-auth/database-adapter/schema.ts +222 -0
- package/src/better-auth/database-adapter/tests/index.test.ts +690 -0
- package/src/better-auth/database-adapter/tests/repository/account.test.ts +149 -0
- package/src/better-auth/database-adapter/tests/repository/generic.test.ts +183 -0
- package/src/better-auth/database-adapter/tests/repository/session.test.ts +419 -0
- package/src/better-auth/database-adapter/tests/repository/user.test.ts +673 -0
- package/src/better-auth/database-adapter/tests/repository/verification.test.ts +101 -0
- package/src/better-auth/database-adapter/tests/sync-utils.ts +127 -0
- package/src/better-auth/database-adapter/tests/utils.test.ts +787 -0
- package/src/better-auth/database-adapter/utils.ts +178 -0
- package/src/worker/edge-wasm.ts +5 -0
- package/tsup.config.ts +8 -0
@@ -0,0 +1,787 @@
|
|
1
|
+
import { CleanedWhere } from "better-auth/adapters";
|
2
|
+
import { describe, expect, it } from "vitest";
|
3
|
+
import {
|
4
|
+
filterListByWhere,
|
5
|
+
isWhereBySingleField,
|
6
|
+
paginateList,
|
7
|
+
sortListByField,
|
8
|
+
} from "../utils.js";
|
9
|
+
|
10
|
+
describe("filterListByWhere", () => {
|
11
|
+
const testData = [
|
12
|
+
{ id: 1, name: "Alice", age: 25, email: "alice@example.com", active: true },
|
13
|
+
{ id: 2, name: "Bob", age: 30, email: "bob@example.com", active: false },
|
14
|
+
{
|
15
|
+
id: 3,
|
16
|
+
name: "Charlie",
|
17
|
+
age: 35,
|
18
|
+
email: "charlie@example.com",
|
19
|
+
active: true,
|
20
|
+
},
|
21
|
+
{ id: 4, name: "David", age: 28, email: "david@test.com", active: true },
|
22
|
+
{ id: 5, name: "Eve", age: 22, email: "eve@example.com", active: false },
|
23
|
+
];
|
24
|
+
|
25
|
+
describe("basic functionality", () => {
|
26
|
+
it("should return all data when where is undefined", () => {
|
27
|
+
const result = filterListByWhere(testData, undefined);
|
28
|
+
expect(result).toEqual(testData);
|
29
|
+
});
|
30
|
+
|
31
|
+
it("should return all data when where is empty array", () => {
|
32
|
+
const result = filterListByWhere(testData, []);
|
33
|
+
expect(result).toEqual(testData);
|
34
|
+
});
|
35
|
+
|
36
|
+
it("should throw error when data is not an array", () => {
|
37
|
+
expect(() => filterListByWhere(null as any, [])).toThrow(
|
38
|
+
"Expected data to be an array",
|
39
|
+
);
|
40
|
+
expect(() => filterListByWhere(undefined as any, [])).toThrow(
|
41
|
+
"Expected data to be an array",
|
42
|
+
);
|
43
|
+
expect(() => filterListByWhere("string" as any, [])).toThrow(
|
44
|
+
"Expected data to be an array",
|
45
|
+
);
|
46
|
+
});
|
47
|
+
|
48
|
+
it("should throw error when where is not an array", () => {
|
49
|
+
expect(() => filterListByWhere(testData, null as any)).toThrow(
|
50
|
+
"Expected where to be an array",
|
51
|
+
);
|
52
|
+
expect(() => filterListByWhere(testData, "string" as any)).toThrow(
|
53
|
+
"Expected where to be an array",
|
54
|
+
);
|
55
|
+
});
|
56
|
+
});
|
57
|
+
|
58
|
+
describe("equality operators", () => {
|
59
|
+
it("should filter with eq operator", () => {
|
60
|
+
const where: CleanedWhere[] = [
|
61
|
+
{ field: "name", operator: "eq", value: "Alice", connector: "AND" },
|
62
|
+
];
|
63
|
+
const result = filterListByWhere(testData, where);
|
64
|
+
expect(result).toEqual([
|
65
|
+
{
|
66
|
+
id: 1,
|
67
|
+
name: "Alice",
|
68
|
+
age: 25,
|
69
|
+
email: "alice@example.com",
|
70
|
+
active: true,
|
71
|
+
},
|
72
|
+
]);
|
73
|
+
});
|
74
|
+
|
75
|
+
it("should filter with ne operator", () => {
|
76
|
+
const where: CleanedWhere[] = [
|
77
|
+
{ field: "name", operator: "ne", value: "Alice", connector: "AND" },
|
78
|
+
];
|
79
|
+
const result = filterListByWhere(testData, where);
|
80
|
+
expect(result).toHaveLength(4);
|
81
|
+
expect(result.every((item) => item.name !== "Alice")).toBe(true);
|
82
|
+
});
|
83
|
+
|
84
|
+
it("should handle null values correctly", () => {
|
85
|
+
const dataWithNull = [
|
86
|
+
{ id: 1, name: "Alice", age: null },
|
87
|
+
{ id: 2, name: "Bob", age: 30 },
|
88
|
+
];
|
89
|
+
const where: CleanedWhere[] = [
|
90
|
+
{ field: "age", operator: "eq", value: null, connector: "AND" },
|
91
|
+
];
|
92
|
+
const result = filterListByWhere(dataWithNull, where);
|
93
|
+
expect(result).toEqual([{ id: 1, name: "Alice", age: null }]);
|
94
|
+
});
|
95
|
+
});
|
96
|
+
|
97
|
+
describe("comparison operators", () => {
|
98
|
+
it("should filter with lt operator", () => {
|
99
|
+
const where: CleanedWhere[] = [
|
100
|
+
{ field: "age", operator: "lt", value: 30, connector: "AND" },
|
101
|
+
];
|
102
|
+
const result = filterListByWhere(testData, where);
|
103
|
+
expect(result).toEqual([
|
104
|
+
{
|
105
|
+
id: 1,
|
106
|
+
name: "Alice",
|
107
|
+
age: 25,
|
108
|
+
email: "alice@example.com",
|
109
|
+
active: true,
|
110
|
+
},
|
111
|
+
{
|
112
|
+
id: 4,
|
113
|
+
name: "David",
|
114
|
+
age: 28,
|
115
|
+
email: "david@test.com",
|
116
|
+
active: true,
|
117
|
+
},
|
118
|
+
{
|
119
|
+
id: 5,
|
120
|
+
name: "Eve",
|
121
|
+
age: 22,
|
122
|
+
email: "eve@example.com",
|
123
|
+
active: false,
|
124
|
+
},
|
125
|
+
]);
|
126
|
+
});
|
127
|
+
|
128
|
+
it("should filter with lte operator", () => {
|
129
|
+
const where: CleanedWhere[] = [
|
130
|
+
{ field: "age", operator: "lte", value: 30, connector: "AND" },
|
131
|
+
];
|
132
|
+
const result = filterListByWhere(testData, where);
|
133
|
+
expect(result).toEqual([
|
134
|
+
{
|
135
|
+
id: 1,
|
136
|
+
name: "Alice",
|
137
|
+
age: 25,
|
138
|
+
email: "alice@example.com",
|
139
|
+
active: true,
|
140
|
+
},
|
141
|
+
{
|
142
|
+
id: 2,
|
143
|
+
name: "Bob",
|
144
|
+
age: 30,
|
145
|
+
email: "bob@example.com",
|
146
|
+
active: false,
|
147
|
+
},
|
148
|
+
{
|
149
|
+
id: 4,
|
150
|
+
name: "David",
|
151
|
+
age: 28,
|
152
|
+
email: "david@test.com",
|
153
|
+
active: true,
|
154
|
+
},
|
155
|
+
{
|
156
|
+
id: 5,
|
157
|
+
name: "Eve",
|
158
|
+
age: 22,
|
159
|
+
email: "eve@example.com",
|
160
|
+
active: false,
|
161
|
+
},
|
162
|
+
]);
|
163
|
+
});
|
164
|
+
|
165
|
+
it("should filter with gt operator", () => {
|
166
|
+
const where: CleanedWhere[] = [
|
167
|
+
{ field: "age", operator: "gt", value: 30, connector: "AND" },
|
168
|
+
];
|
169
|
+
const result = filterListByWhere(testData, where);
|
170
|
+
expect(result).toEqual([
|
171
|
+
{
|
172
|
+
id: 3,
|
173
|
+
name: "Charlie",
|
174
|
+
age: 35,
|
175
|
+
email: "charlie@example.com",
|
176
|
+
active: true,
|
177
|
+
},
|
178
|
+
]);
|
179
|
+
});
|
180
|
+
|
181
|
+
it("should filter with gte operator", () => {
|
182
|
+
const where: CleanedWhere[] = [
|
183
|
+
{ field: "age", operator: "gte", value: 30, connector: "AND" },
|
184
|
+
];
|
185
|
+
const result = filterListByWhere(testData, where);
|
186
|
+
expect(result).toEqual([
|
187
|
+
{
|
188
|
+
id: 2,
|
189
|
+
name: "Bob",
|
190
|
+
age: 30,
|
191
|
+
email: "bob@example.com",
|
192
|
+
active: false,
|
193
|
+
},
|
194
|
+
{
|
195
|
+
id: 3,
|
196
|
+
name: "Charlie",
|
197
|
+
age: 35,
|
198
|
+
email: "charlie@example.com",
|
199
|
+
active: true,
|
200
|
+
},
|
201
|
+
]);
|
202
|
+
});
|
203
|
+
|
204
|
+
it("should handle null values in comparison operators", () => {
|
205
|
+
const where: CleanedWhere[] = [
|
206
|
+
{ field: "age", operator: "lt", value: null, connector: "AND" },
|
207
|
+
];
|
208
|
+
const result = filterListByWhere(testData, where);
|
209
|
+
expect(result).toEqual([]);
|
210
|
+
});
|
211
|
+
});
|
212
|
+
|
213
|
+
describe("string operators", () => {
|
214
|
+
it("should filter with contains operator", () => {
|
215
|
+
const where: CleanedWhere[] = [
|
216
|
+
{
|
217
|
+
field: "email",
|
218
|
+
operator: "contains",
|
219
|
+
value: "test",
|
220
|
+
connector: "AND",
|
221
|
+
},
|
222
|
+
];
|
223
|
+
const result = filterListByWhere(testData, where);
|
224
|
+
expect(result).toEqual([
|
225
|
+
{
|
226
|
+
id: 4,
|
227
|
+
name: "David",
|
228
|
+
age: 28,
|
229
|
+
email: "david@test.com",
|
230
|
+
active: true,
|
231
|
+
},
|
232
|
+
]);
|
233
|
+
});
|
234
|
+
|
235
|
+
it("should filter with starts_with operator", () => {
|
236
|
+
const where: CleanedWhere[] = [
|
237
|
+
{
|
238
|
+
field: "name",
|
239
|
+
operator: "starts_with",
|
240
|
+
value: "A",
|
241
|
+
connector: "AND",
|
242
|
+
},
|
243
|
+
];
|
244
|
+
const result = filterListByWhere(testData, where);
|
245
|
+
expect(result).toEqual([
|
246
|
+
{
|
247
|
+
id: 1,
|
248
|
+
name: "Alice",
|
249
|
+
age: 25,
|
250
|
+
email: "alice@example.com",
|
251
|
+
active: true,
|
252
|
+
},
|
253
|
+
]);
|
254
|
+
});
|
255
|
+
|
256
|
+
it("should filter with ends_with operator", () => {
|
257
|
+
const where: CleanedWhere[] = [
|
258
|
+
{ field: "name", operator: "ends_with", value: "e", connector: "AND" },
|
259
|
+
];
|
260
|
+
const result = filterListByWhere(testData, where);
|
261
|
+
expect(result).toEqual([
|
262
|
+
{
|
263
|
+
id: 1,
|
264
|
+
name: "Alice",
|
265
|
+
age: 25,
|
266
|
+
email: "alice@example.com",
|
267
|
+
active: true,
|
268
|
+
},
|
269
|
+
{
|
270
|
+
id: 3,
|
271
|
+
name: "Charlie",
|
272
|
+
age: 35,
|
273
|
+
email: "charlie@example.com",
|
274
|
+
active: true,
|
275
|
+
},
|
276
|
+
{
|
277
|
+
id: 5,
|
278
|
+
name: "Eve",
|
279
|
+
age: 22,
|
280
|
+
email: "eve@example.com",
|
281
|
+
active: false,
|
282
|
+
},
|
283
|
+
]);
|
284
|
+
});
|
285
|
+
|
286
|
+
it("should handle non-string values in string operators", () => {
|
287
|
+
const where: CleanedWhere[] = [
|
288
|
+
{ field: "age", operator: "contains", value: "test", connector: "AND" },
|
289
|
+
];
|
290
|
+
const result = filterListByWhere(testData, where);
|
291
|
+
expect(result).toEqual([]);
|
292
|
+
});
|
293
|
+
});
|
294
|
+
|
295
|
+
describe("in operator", () => {
|
296
|
+
it("should filter with in operator for strings", () => {
|
297
|
+
const where: CleanedWhere[] = [
|
298
|
+
{
|
299
|
+
field: "name",
|
300
|
+
operator: "in",
|
301
|
+
value: ["Alice", "Bob"],
|
302
|
+
connector: "AND",
|
303
|
+
},
|
304
|
+
];
|
305
|
+
const result = filterListByWhere(testData, where);
|
306
|
+
expect(result).toEqual([
|
307
|
+
{
|
308
|
+
id: 1,
|
309
|
+
name: "Alice",
|
310
|
+
age: 25,
|
311
|
+
email: "alice@example.com",
|
312
|
+
active: true,
|
313
|
+
},
|
314
|
+
{
|
315
|
+
id: 2,
|
316
|
+
name: "Bob",
|
317
|
+
age: 30,
|
318
|
+
email: "bob@example.com",
|
319
|
+
active: false,
|
320
|
+
},
|
321
|
+
]);
|
322
|
+
});
|
323
|
+
|
324
|
+
it("should filter with in operator for numbers", () => {
|
325
|
+
const where: CleanedWhere[] = [
|
326
|
+
{ field: "age", operator: "in", value: [25, 30, 35], connector: "AND" },
|
327
|
+
];
|
328
|
+
const result = filterListByWhere(testData, where);
|
329
|
+
expect(result).toEqual([
|
330
|
+
{
|
331
|
+
id: 1,
|
332
|
+
name: "Alice",
|
333
|
+
age: 25,
|
334
|
+
email: "alice@example.com",
|
335
|
+
active: true,
|
336
|
+
},
|
337
|
+
{
|
338
|
+
id: 2,
|
339
|
+
name: "Bob",
|
340
|
+
age: 30,
|
341
|
+
email: "bob@example.com",
|
342
|
+
active: false,
|
343
|
+
},
|
344
|
+
{
|
345
|
+
id: 3,
|
346
|
+
name: "Charlie",
|
347
|
+
age: 35,
|
348
|
+
email: "charlie@example.com",
|
349
|
+
active: true,
|
350
|
+
},
|
351
|
+
]);
|
352
|
+
});
|
353
|
+
|
354
|
+
it("should filter with in operator for booleans", () => {
|
355
|
+
const where: CleanedWhere[] = [
|
356
|
+
{
|
357
|
+
field: "active",
|
358
|
+
operator: "in",
|
359
|
+
value: [true] as any,
|
360
|
+
connector: "AND",
|
361
|
+
},
|
362
|
+
];
|
363
|
+
const result = filterListByWhere(testData, where);
|
364
|
+
expect(result).toEqual([
|
365
|
+
{
|
366
|
+
id: 1,
|
367
|
+
name: "Alice",
|
368
|
+
age: 25,
|
369
|
+
email: "alice@example.com",
|
370
|
+
active: true,
|
371
|
+
},
|
372
|
+
{
|
373
|
+
id: 3,
|
374
|
+
name: "Charlie",
|
375
|
+
age: 35,
|
376
|
+
email: "charlie@example.com",
|
377
|
+
active: true,
|
378
|
+
},
|
379
|
+
{
|
380
|
+
id: 4,
|
381
|
+
name: "David",
|
382
|
+
age: 28,
|
383
|
+
email: "david@test.com",
|
384
|
+
active: true,
|
385
|
+
},
|
386
|
+
]);
|
387
|
+
});
|
388
|
+
|
389
|
+
it("should handle non-array values in in operator", () => {
|
390
|
+
const where: CleanedWhere[] = [
|
391
|
+
{
|
392
|
+
field: "name",
|
393
|
+
operator: "in",
|
394
|
+
value: "Alice" as any,
|
395
|
+
connector: "AND",
|
396
|
+
},
|
397
|
+
];
|
398
|
+
const result = filterListByWhere(testData, where);
|
399
|
+
expect(result).toEqual([]);
|
400
|
+
});
|
401
|
+
});
|
402
|
+
|
403
|
+
describe("connectors", () => {
|
404
|
+
it("should use explicit AND connector", () => {
|
405
|
+
const where: CleanedWhere[] = [
|
406
|
+
{ field: "age", operator: "gte", value: 25, connector: "AND" },
|
407
|
+
{ field: "active", operator: "eq", value: true, connector: "AND" },
|
408
|
+
];
|
409
|
+
const result = filterListByWhere(testData, where);
|
410
|
+
expect(result).toEqual([
|
411
|
+
{
|
412
|
+
id: 1,
|
413
|
+
name: "Alice",
|
414
|
+
age: 25,
|
415
|
+
email: "alice@example.com",
|
416
|
+
active: true,
|
417
|
+
},
|
418
|
+
{
|
419
|
+
id: 3,
|
420
|
+
name: "Charlie",
|
421
|
+
age: 35,
|
422
|
+
email: "charlie@example.com",
|
423
|
+
active: true,
|
424
|
+
},
|
425
|
+
{
|
426
|
+
id: 4,
|
427
|
+
name: "David",
|
428
|
+
age: 28,
|
429
|
+
email: "david@test.com",
|
430
|
+
active: true,
|
431
|
+
},
|
432
|
+
]);
|
433
|
+
});
|
434
|
+
|
435
|
+
it("should use OR connector", () => {
|
436
|
+
const where: CleanedWhere[] = [
|
437
|
+
{ field: "age", operator: "lt", value: 25, connector: "OR" },
|
438
|
+
{ field: "active", operator: "eq", value: false, connector: "OR" },
|
439
|
+
];
|
440
|
+
const result = filterListByWhere(testData, where);
|
441
|
+
expect(result).toEqual([
|
442
|
+
{
|
443
|
+
id: 2,
|
444
|
+
name: "Bob",
|
445
|
+
age: 30,
|
446
|
+
email: "bob@example.com",
|
447
|
+
active: false,
|
448
|
+
},
|
449
|
+
{
|
450
|
+
id: 5,
|
451
|
+
name: "Eve",
|
452
|
+
age: 22,
|
453
|
+
email: "eve@example.com",
|
454
|
+
active: false,
|
455
|
+
},
|
456
|
+
]);
|
457
|
+
});
|
458
|
+
|
459
|
+
it("should throw error for unsupported connector", () => {
|
460
|
+
const where: CleanedWhere[] = [
|
461
|
+
{ field: "name", operator: "eq", value: "Alice", connector: "AND" },
|
462
|
+
{ field: "age", operator: "eq", value: 25, connector: "XOR" as any },
|
463
|
+
];
|
464
|
+
expect(() => filterListByWhere(testData, where)).toThrow(
|
465
|
+
"Unsupported connector: XOR",
|
466
|
+
);
|
467
|
+
});
|
468
|
+
});
|
469
|
+
|
470
|
+
describe("error handling", () => {
|
471
|
+
it("should throw error for unsupported operator", () => {
|
472
|
+
const where: CleanedWhere[] = [
|
473
|
+
{
|
474
|
+
field: "name",
|
475
|
+
operator: "unsupported" as any,
|
476
|
+
value: "Alice",
|
477
|
+
connector: "AND",
|
478
|
+
},
|
479
|
+
];
|
480
|
+
expect(() => filterListByWhere(testData, where)).toThrow(
|
481
|
+
"Unsupported operator: unsupported",
|
482
|
+
);
|
483
|
+
});
|
484
|
+
});
|
485
|
+
});
|
486
|
+
|
487
|
+
describe("filterListByWhere with id => $jazz.id", () => {
|
488
|
+
const testData = [
|
489
|
+
{ $jazz: { id: "a1" }, name: "Alice", age: 25, active: true },
|
490
|
+
{ $jazz: { id: "b2" }, name: "Bob", age: 30, active: false },
|
491
|
+
{ $jazz: { id: "c3" }, name: "Charlie", age: 35, active: true },
|
492
|
+
] as any[];
|
493
|
+
|
494
|
+
it("should match by $jazz.id when where field is 'id' (eq)", () => {
|
495
|
+
const where: CleanedWhere[] = [
|
496
|
+
{ field: "id", operator: "eq", value: "a1", connector: "AND" },
|
497
|
+
];
|
498
|
+
const result = filterListByWhere(testData, where);
|
499
|
+
expect(result).toEqual([
|
500
|
+
{ $jazz: { id: "a1" }, name: "Alice", age: 25, active: true },
|
501
|
+
]);
|
502
|
+
});
|
503
|
+
|
504
|
+
it("should return empty when no $jazz.id matches", () => {
|
505
|
+
const where: CleanedWhere[] = [
|
506
|
+
{ field: "id", operator: "eq", value: "z9", connector: "AND" },
|
507
|
+
];
|
508
|
+
const result = filterListByWhere(testData, where);
|
509
|
+
expect(result).toEqual([]);
|
510
|
+
});
|
511
|
+
});
|
512
|
+
|
513
|
+
describe("sortListByField", () => {
|
514
|
+
const testData = [
|
515
|
+
{ id: 3, name: "Charlie", age: 35, score: 85.5 },
|
516
|
+
{ id: 1, name: "Alice", age: 25, score: 92.0 },
|
517
|
+
{ id: 2, name: "Bob", age: 30, score: 78.3 },
|
518
|
+
{ id: 4, name: "David", age: 28, score: 95.7 },
|
519
|
+
];
|
520
|
+
|
521
|
+
describe("basic functionality", () => {
|
522
|
+
it("should return data unchanged when sort is undefined", () => {
|
523
|
+
const result = sortListByField(testData, undefined);
|
524
|
+
expect(result).toEqual(testData);
|
525
|
+
});
|
526
|
+
|
527
|
+
it("should sort numbers in ascending order", () => {
|
528
|
+
const result = sortListByField(testData, {
|
529
|
+
field: "age",
|
530
|
+
direction: "asc",
|
531
|
+
});
|
532
|
+
expect(result.map((item) => item.age)).toEqual([25, 28, 30, 35]);
|
533
|
+
});
|
534
|
+
|
535
|
+
it("should sort numbers in descending order", () => {
|
536
|
+
const result = sortListByField(testData, {
|
537
|
+
field: "age",
|
538
|
+
direction: "desc",
|
539
|
+
});
|
540
|
+
expect(result.map((item) => item.age)).toEqual([35, 30, 28, 25]);
|
541
|
+
});
|
542
|
+
|
543
|
+
it("should sort strings in ascending order", () => {
|
544
|
+
const result = sortListByField(testData, {
|
545
|
+
field: "name",
|
546
|
+
direction: "asc",
|
547
|
+
});
|
548
|
+
expect(result.map((item) => item.name)).toEqual([
|
549
|
+
"Alice",
|
550
|
+
"Bob",
|
551
|
+
"Charlie",
|
552
|
+
"David",
|
553
|
+
]);
|
554
|
+
});
|
555
|
+
|
556
|
+
it("should sort strings in descending order", () => {
|
557
|
+
const result = sortListByField(testData, {
|
558
|
+
field: "name",
|
559
|
+
direction: "desc",
|
560
|
+
});
|
561
|
+
expect(result.map((item) => item.name)).toEqual([
|
562
|
+
"David",
|
563
|
+
"Charlie",
|
564
|
+
"Bob",
|
565
|
+
"Alice",
|
566
|
+
]);
|
567
|
+
});
|
568
|
+
|
569
|
+
it("should sort floating point numbers correctly", () => {
|
570
|
+
const result = sortListByField(testData, {
|
571
|
+
field: "score",
|
572
|
+
direction: "asc",
|
573
|
+
});
|
574
|
+
expect(result.map((item) => item.score)).toEqual([
|
575
|
+
78.3, 85.5, 92.0, 95.7,
|
576
|
+
]);
|
577
|
+
});
|
578
|
+
});
|
579
|
+
|
580
|
+
describe("edge cases", () => {
|
581
|
+
it("should handle empty array", () => {
|
582
|
+
const result = sortListByField([], { field: "name", direction: "asc" });
|
583
|
+
expect(result).toEqual([]);
|
584
|
+
});
|
585
|
+
|
586
|
+
it("should handle single item array", () => {
|
587
|
+
const singleItem = [{ id: 1, name: "Alice" }];
|
588
|
+
const result = sortListByField(singleItem, {
|
589
|
+
field: "name",
|
590
|
+
direction: "asc",
|
591
|
+
});
|
592
|
+
expect(result).toEqual(singleItem);
|
593
|
+
});
|
594
|
+
|
595
|
+
it("should handle mixed data types gracefully", () => {
|
596
|
+
const mixedData = [
|
597
|
+
{ id: 1, value: "string" },
|
598
|
+
{ id: 2, value: 42 },
|
599
|
+
{ id: 3, value: "another" },
|
600
|
+
];
|
601
|
+
const result = sortListByField(mixedData, {
|
602
|
+
field: "value",
|
603
|
+
direction: "asc",
|
604
|
+
});
|
605
|
+
// Should not throw error, but behavior may be unpredictable
|
606
|
+
expect(result).toHaveLength(3);
|
607
|
+
});
|
608
|
+
|
609
|
+
it("should handle undefined field values", () => {
|
610
|
+
const dataWithUndefined = [
|
611
|
+
{ id: 1, name: "Alice", age: 25 },
|
612
|
+
{ id: 2, name: "Bob", age: undefined },
|
613
|
+
{ id: 3, name: "Charlie", age: 30 },
|
614
|
+
];
|
615
|
+
const result = sortListByField(dataWithUndefined, {
|
616
|
+
field: "age",
|
617
|
+
direction: "asc",
|
618
|
+
});
|
619
|
+
expect(result).toHaveLength(3);
|
620
|
+
});
|
621
|
+
});
|
622
|
+
});
|
623
|
+
|
624
|
+
describe("paginateList", () => {
|
625
|
+
const testData = [
|
626
|
+
{ id: 1, name: "Alice" },
|
627
|
+
{ id: 2, name: "Bob" },
|
628
|
+
{ id: 3, name: "Charlie" },
|
629
|
+
{ id: 4, name: "David" },
|
630
|
+
{ id: 5, name: "Eve" },
|
631
|
+
{ id: 6, name: "Frank" },
|
632
|
+
{ id: 7, name: "Grace" },
|
633
|
+
{ id: 8, name: "Henry" },
|
634
|
+
];
|
635
|
+
|
636
|
+
describe("basic functionality", () => {
|
637
|
+
it("should return all data when limit and offset are undefined", () => {
|
638
|
+
const result = paginateList(testData, undefined, undefined);
|
639
|
+
expect(result).toEqual(testData);
|
640
|
+
});
|
641
|
+
|
642
|
+
it("should return all data when limit and offset are undefined (explicit)", () => {
|
643
|
+
const result = paginateList(testData, undefined, undefined);
|
644
|
+
expect(result).toEqual(testData);
|
645
|
+
});
|
646
|
+
|
647
|
+
it("should apply only limit when offset is undefined", () => {
|
648
|
+
const result = paginateList(testData, 3, undefined);
|
649
|
+
expect(result).toEqual([
|
650
|
+
{ id: 1, name: "Alice" },
|
651
|
+
{ id: 2, name: "Bob" },
|
652
|
+
{ id: 3, name: "Charlie" },
|
653
|
+
]);
|
654
|
+
});
|
655
|
+
|
656
|
+
it("should apply only offset when limit is undefined", () => {
|
657
|
+
const result = paginateList(testData, undefined, 3);
|
658
|
+
expect(result).toEqual([
|
659
|
+
{ id: 4, name: "David" },
|
660
|
+
{ id: 5, name: "Eve" },
|
661
|
+
{ id: 6, name: "Frank" },
|
662
|
+
{ id: 7, name: "Grace" },
|
663
|
+
{ id: 8, name: "Henry" },
|
664
|
+
]);
|
665
|
+
});
|
666
|
+
|
667
|
+
it("should apply both limit and offset", () => {
|
668
|
+
const result = paginateList(testData, 3, 2);
|
669
|
+
expect(result).toEqual([
|
670
|
+
{ id: 3, name: "Charlie" },
|
671
|
+
{ id: 4, name: "David" },
|
672
|
+
{ id: 5, name: "Eve" },
|
673
|
+
]);
|
674
|
+
});
|
675
|
+
});
|
676
|
+
|
677
|
+
describe("edge cases", () => {
|
678
|
+
it("should handle empty array", () => {
|
679
|
+
const result = paginateList([], 5, 0);
|
680
|
+
expect(result).toEqual([]);
|
681
|
+
});
|
682
|
+
|
683
|
+
it("should handle offset beyond array length", () => {
|
684
|
+
const result = paginateList(testData, 5, 10);
|
685
|
+
expect(result).toEqual([]);
|
686
|
+
});
|
687
|
+
|
688
|
+
it("should handle limit larger than remaining items", () => {
|
689
|
+
const result = paginateList(testData, 10, 5);
|
690
|
+
expect(result).toEqual([
|
691
|
+
{ id: 6, name: "Frank" },
|
692
|
+
{ id: 7, name: "Grace" },
|
693
|
+
{ id: 8, name: "Henry" },
|
694
|
+
]);
|
695
|
+
});
|
696
|
+
|
697
|
+
it("should handle zero limit", () => {
|
698
|
+
const result = paginateList(testData, 0, 2);
|
699
|
+
expect(result).toEqual([]);
|
700
|
+
});
|
701
|
+
|
702
|
+
it("should handle zero offset", () => {
|
703
|
+
const result = paginateList(testData, 3, 0);
|
704
|
+
expect(result).toEqual([
|
705
|
+
{ id: 1, name: "Alice" },
|
706
|
+
{ id: 2, name: "Bob" },
|
707
|
+
{ id: 3, name: "Charlie" },
|
708
|
+
]);
|
709
|
+
});
|
710
|
+
|
711
|
+
it("should handle negative offset (treats as 0)", () => {
|
712
|
+
const result = paginateList(testData, 3, -1);
|
713
|
+
expect(result).toEqual([
|
714
|
+
{ id: 1, name: "Alice" },
|
715
|
+
{ id: 2, name: "Bob" },
|
716
|
+
{ id: 3, name: "Charlie" },
|
717
|
+
]);
|
718
|
+
});
|
719
|
+
|
720
|
+
it("should handle exact boundary conditions", () => {
|
721
|
+
const result = paginateList(testData, 4, 4);
|
722
|
+
expect(result).toEqual([
|
723
|
+
{ id: 5, name: "Eve" },
|
724
|
+
{ id: 6, name: "Frank" },
|
725
|
+
{ id: 7, name: "Grace" },
|
726
|
+
{ id: 8, name: "Henry" },
|
727
|
+
]);
|
728
|
+
});
|
729
|
+
});
|
730
|
+
|
731
|
+
describe("boundary testing", () => {
|
732
|
+
it("should handle offset at array boundary", () => {
|
733
|
+
const result = paginateList(testData, 5, 8);
|
734
|
+
expect(result).toEqual([]);
|
735
|
+
});
|
736
|
+
|
737
|
+
it("should handle limit that matches remaining items exactly", () => {
|
738
|
+
const result = paginateList(testData, 3, 5);
|
739
|
+
expect(result).toEqual([
|
740
|
+
{ id: 6, name: "Frank" },
|
741
|
+
{ id: 7, name: "Grace" },
|
742
|
+
{ id: 8, name: "Henry" },
|
743
|
+
]);
|
744
|
+
});
|
745
|
+
|
746
|
+
it("should handle single item result", () => {
|
747
|
+
const result = paginateList(testData, 1, 4);
|
748
|
+
expect(result).toEqual([{ id: 5, name: "Eve" }]);
|
749
|
+
});
|
750
|
+
});
|
751
|
+
});
|
752
|
+
|
753
|
+
describe("isWhereBySingleField", () => {
|
754
|
+
it("should return true if the where condition is an id", () => {
|
755
|
+
const where: CleanedWhere[] = [
|
756
|
+
{ field: "id", operator: "eq", value: "1", connector: "AND" },
|
757
|
+
];
|
758
|
+
expect(isWhereBySingleField("id", where)).toBe(true);
|
759
|
+
});
|
760
|
+
|
761
|
+
it("should return false if the where condition is not an id", () => {
|
762
|
+
const where: CleanedWhere[] = [
|
763
|
+
{ field: "name", operator: "eq", value: "Alice", connector: "AND" },
|
764
|
+
];
|
765
|
+
expect(isWhereBySingleField("id", where)).toBe(false);
|
766
|
+
});
|
767
|
+
|
768
|
+
it("should return false if the where condition has more than one condition", () => {
|
769
|
+
const where: CleanedWhere[] = [
|
770
|
+
{ field: "name", operator: "eq", value: "Alice", connector: "AND" },
|
771
|
+
{ field: "id", operator: "eq", value: "1", connector: "AND" },
|
772
|
+
];
|
773
|
+
expect(isWhereBySingleField("id", where)).toBe(false);
|
774
|
+
});
|
775
|
+
|
776
|
+
it("should return false if the where condition has no condition", () => {
|
777
|
+
const where: CleanedWhere[] = [];
|
778
|
+
expect(isWhereBySingleField("id", where)).toBe(false);
|
779
|
+
});
|
780
|
+
|
781
|
+
it("should return false if the where condition on ID is not eq", () => {
|
782
|
+
const where: CleanedWhere[] = [
|
783
|
+
{ field: "id", operator: "gt", value: "1", connector: "AND" },
|
784
|
+
];
|
785
|
+
expect(isWhereBySingleField("id", where)).toBe(false);
|
786
|
+
});
|
787
|
+
});
|