hola-server 1.0.11 → 2.0.1

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.
Files changed (83) hide show
  1. package/README.md +196 -1
  2. package/core/array.js +79 -142
  3. package/core/bash.js +208 -259
  4. package/core/chart.js +26 -16
  5. package/core/cron.js +14 -3
  6. package/core/date.js +15 -44
  7. package/core/encrypt.js +19 -9
  8. package/core/file.js +42 -29
  9. package/core/lhs.js +32 -6
  10. package/core/meta.js +213 -289
  11. package/core/msg.js +20 -7
  12. package/core/number.js +105 -103
  13. package/core/obj.js +15 -12
  14. package/core/random.js +9 -6
  15. package/core/role.js +69 -77
  16. package/core/thread.js +12 -2
  17. package/core/type.js +300 -261
  18. package/core/url.js +20 -12
  19. package/core/validate.js +29 -26
  20. package/db/db.js +297 -227
  21. package/db/entity.js +631 -963
  22. package/db/gridfs.js +120 -166
  23. package/design/add_default_field_attr.md +56 -0
  24. package/http/context.js +22 -8
  25. package/http/cors.js +25 -8
  26. package/http/error.js +27 -9
  27. package/http/express.js +70 -41
  28. package/http/params.js +70 -42
  29. package/http/router.js +51 -40
  30. package/http/session.js +59 -36
  31. package/index.js +85 -9
  32. package/package.json +2 -2
  33. package/router/clone.js +28 -36
  34. package/router/create.js +21 -26
  35. package/router/delete.js +24 -28
  36. package/router/read.js +137 -123
  37. package/router/update.js +38 -56
  38. package/setting.js +22 -6
  39. package/skills/array.md +155 -0
  40. package/skills/bash.md +91 -0
  41. package/skills/chart.md +54 -0
  42. package/skills/code.md +422 -0
  43. package/skills/context.md +177 -0
  44. package/skills/date.md +58 -0
  45. package/skills/express.md +255 -0
  46. package/skills/file.md +60 -0
  47. package/skills/lhs.md +54 -0
  48. package/skills/meta.md +1023 -0
  49. package/skills/msg.md +30 -0
  50. package/skills/number.md +88 -0
  51. package/skills/obj.md +36 -0
  52. package/skills/params.md +206 -0
  53. package/skills/random.md +22 -0
  54. package/skills/role.md +59 -0
  55. package/skills/session.md +281 -0
  56. package/skills/storage.md +743 -0
  57. package/skills/thread.md +22 -0
  58. package/skills/type.md +547 -0
  59. package/skills/url.md +34 -0
  60. package/skills/validate.md +48 -0
  61. package/test/cleanup/close-db.js +5 -0
  62. package/test/core/array.js +226 -0
  63. package/test/core/chart.js +51 -0
  64. package/test/core/file.js +59 -0
  65. package/test/core/lhs.js +44 -0
  66. package/test/core/number.js +167 -12
  67. package/test/core/obj.js +47 -0
  68. package/test/core/random.js +24 -0
  69. package/test/core/thread.js +20 -0
  70. package/test/core/type.js +216 -0
  71. package/test/core/validate.js +67 -0
  72. package/test/db/db-ops.js +99 -0
  73. package/test/db/pipe_test.txt +0 -0
  74. package/test/db/test_case_design.md +528 -0
  75. package/test/db/test_db_class.js +613 -0
  76. package/test/db/test_entity_class.js +414 -0
  77. package/test/db/test_gridfs_class.js +234 -0
  78. package/test/entity/create.js +1 -1
  79. package/test/entity/delete-mixed.js +156 -0
  80. package/test/entity/ref-filter.js +63 -0
  81. package/tool/gen_i18n.js +55 -21
  82. package/test/crud/router.js +0 -99
  83. package/test/router/user.js +0 -17
@@ -0,0 +1,528 @@
1
+ # Test Case Design for hola-server/db Module
2
+
3
+ This document outlines detailed test case designs for the API methods in the `db` module. The module consists of three classes:
4
+
5
+ 1. **DB** (`db.js`) - Low-level MongoDB operations wrapper
6
+ 2. **Entity** (`entity.js`) - Metadata-driven entity CRUD operations
7
+ 3. **GridFS** (`gridfs.js`) - GridFS file storage utilities
8
+
9
+ ---
10
+
11
+ ## 1. DB Class Test Cases (`db.js`)
12
+
13
+ ### 1.1 ObjectId Utilities
14
+
15
+ #### `oid(id)`
16
+ | Test ID | Description | Input | Expected Behavior |
17
+ |---------|-------------|-------|-------------------|
18
+ | OID-001 | Create ObjectId from valid 24-char hex string | `"507f1f77bcf86cd799439011"` | Returns valid MongoDB ObjectId |
19
+ | OID-002 | Create ObjectId from null | `null` | Throws error or returns null |
20
+ | OID-003 | Create ObjectId from invalid string | `"invalid-id"` | Throws error |
21
+ | OID-004 | Create ObjectId from empty string | `""` | Throws error |
22
+
23
+ #### `oid_query(id)`
24
+ | Test ID | Description | Input | Expected Behavior |
25
+ |---------|-------------|-------|-------------------|
26
+ | OIDQ-001 | Build query from valid id string | `"507f1f77bcf86cd799439011"` | Returns `{ _id: ObjectId(...) }` |
27
+ | OIDQ-002 | Build query from invalid id | `"invalid-id"` | Returns `null` |
28
+ | OIDQ-003 | Build query from undefined | `undefined` | Returns `null` |
29
+ | OIDQ-004 | Build query from null | `null` | Returns `null` |
30
+
31
+ #### `oid_queries(ids)`
32
+ | Test ID | Description | Input | Expected Behavior |
33
+ |---------|-------------|-------|-------------------|
34
+ | OIDQS-001 | Build $in query from valid id array | `["id1", "id2"]` | Returns `{ _id: { $in: [...] } }` |
35
+ | OIDQS-002 | Build $in query with some invalid ids | `["valid", "invalid"]` | Returns `null` |
36
+ | OIDQS-003 | Build $in query from empty array | `[]` | Returns `null` or empty query |
37
+ | OIDQS-004 | Build $in query from mixed valid ids | Multiple valid ids | Returns proper $in query |
38
+
39
+ ---
40
+
41
+ ### 1.2 DB Class Constructor
42
+
43
+ #### `constructor(url, options, callback)`
44
+ | Test ID | Description | Input | Expected Behavior |
45
+ |---------|-------------|-------|-------------------|
46
+ | DBC-001 | Initialize with valid MongoDB URL | Valid URL | DB instance created successfully |
47
+ | DBC-002 | Initialize without URL | `null` or `undefined` | Throws "Mongo url is required" error |
48
+ | DBC-003 | Initialize with callback | URL + callback function | Callback invoked on connection |
49
+ | DBC-004 | Initialize with options | URL + connection options | Options applied correctly |
50
+
51
+ ---
52
+
53
+ ### 1.3 CRUD Operations
54
+
55
+ #### `create(code, obj)`
56
+ | Test ID | Description | Input | Expected Behavior |
57
+ |---------|-------------|-------|-------------------|
58
+ | CRT-001 | Create document with simple fields | Collection + simple object | Returns inserted document with `_id` |
59
+ | CRT-002 | Create document with nested object | Object with nested data | Nested data preserved |
60
+ | CRT-003 | Create document with Date field | Object with Date | Date stored correctly |
61
+ | CRT-004 | Create document with array field | Object with array | Array stored correctly |
62
+ | CRT-005 | Create document with dotted key | Object with "name.key" | Dotted key preserved |
63
+ | CRT-006 | Create document in non-existent collection | New collection name | Collection auto-created |
64
+
65
+ #### `update(code, query, obj)`
66
+ | Test ID | Description | Input | Expected Behavior |
67
+ |---------|-------------|-------|-------------------|
68
+ | UPD-001 | Update existing document | Matching query + update obj | Document updated |
69
+ | UPD-002 | Update with upsert (no match) | Non-matching query | New document created |
70
+ | UPD-003 | Update multiple documents | Query matching multiple | All matching docs updated |
71
+ | UPD-004 | Update specific fields only | Partial update object | Only specified fields changed |
72
+ | UPD-005 | Update with $set operator | `{ $set: {...} }` | Correct MongoDB $set behavior |
73
+ | UPD-006 | Update non-existent collection | New collection + upsert | Document created in new collection |
74
+
75
+ #### `delete(code, query)`
76
+ | Test ID | Description | Input | Expected Behavior |
77
+ |---------|-------------|-------|-------------------|
78
+ | DEL-001 | Delete single document | Query matching one doc | One document removed |
79
+ | DEL-002 | Delete multiple documents | Query matching many | All matching docs removed |
80
+ | DEL-003 | Delete with empty query | `{}` | All documents removed |
81
+ | DEL-004 | Delete no match | Non-matching query | No error, 0 deleted |
82
+ | DEL-005 | Delete from non-existent collection | Invalid collection | No error |
83
+
84
+ ---
85
+
86
+ ### 1.4 Query Operations
87
+
88
+ #### `find(code, query, attr)`
89
+ | Test ID | Description | Input | Expected Behavior |
90
+ |---------|-------------|-------|-------------------|
91
+ | FND-001 | Find all documents | Empty query `{}` | Returns all documents |
92
+ | FND-002 | Find with simple filter | `{ name: "test" }` | Returns matching docs |
93
+ | FND-003 | Find with projection | Query + `{ name: 1 }` | Only specified fields returned |
94
+ | FND-004 | Find with exclusion projection | `{ password: 0 }` | Specified field excluded |
95
+ | FND-005 | Find no matches | Non-matching query | Returns empty array |
96
+ | FND-006 | Find with comparison operators | `{ age: { $gt: 18 } }` | Returns correct matches |
97
+
98
+ #### `find_one(code, query, attr)`
99
+ | Test ID | Description | Input | Expected Behavior |
100
+ |---------|-------------|-------|-------------------|
101
+ | FNO-001 | Find one existing document | Matching query | Returns single document |
102
+ | FNO-002 | Find one with multiple matches | Query matching many | Returns first match only |
103
+ | FNO-003 | Find one no match | Non-matching query | Returns `null` |
104
+ | FNO-004 | Find one with projection | Query + attr | Only specified fields |
105
+
106
+ #### `find_sort(code, query, sort, attr)`
107
+ | Test ID | Description | Input | Expected Behavior |
108
+ |---------|-------------|-------|-------------------|
109
+ | FNS-001 | Sort ascending by field | `{ age: 1 }` | Ascending order |
110
+ | FNS-002 | Sort descending by field | `{ age: -1 }` | Descending order |
111
+ | FNS-003 | Sort by multiple fields | `{ name: 1, age: -1 }` | Multi-field sort |
112
+ | FNS-004 | Sort with projection | Sort + projection | Sorted with specified fields only |
113
+ | FNS-005 | Sort empty collection | Empty result set | Returns empty array |
114
+
115
+ #### `find_page(code, query, sort, page, limit, attr)`
116
+ | Test ID | Description | Input | Expected Behavior |
117
+ |---------|-------------|-------|-------------------|
118
+ | FNP-001 | Get first page | page=1, limit=10 | First 10 documents |
119
+ | FNP-002 | Get middle page | page=2, limit=5 | Documents 6-10 |
120
+ | FNP-003 | Get last partial page | page beyond full pages | Remaining documents |
121
+ | FNP-004 | Page with limit 0 | limit=0 | Empty array or default |
122
+ | FNP-005 | Page with negative page number | page=-1 | Error or defaults to 1 |
123
+ | FNP-006 | Consistent pagination order | Same params, multiple calls | Same order guaranteed |
124
+ | FNP-007 | Page with sort and projection | All options combined | Correct pagination |
125
+
126
+ ---
127
+
128
+ ### 1.5 Aggregate Operations
129
+
130
+ #### `count(code, query)`
131
+ | Test ID | Description | Input | Expected Behavior |
132
+ |---------|-------------|-------|-------------------|
133
+ | CNT-001 | Count all documents | Empty query | Total document count |
134
+ | CNT-002 | Count with filter | Filter query | Matching document count |
135
+ | CNT-003 | Count empty collection | Empty collection | Returns 0 |
136
+ | CNT-004 | Count no matches | Non-matching query | Returns 0 |
137
+
138
+ #### `sum(code, query, field)`
139
+ | Test ID | Description | Input | Expected Behavior |
140
+ |---------|-------------|-------|-------------------|
141
+ | SUM-001 | Sum numeric field | Valid numeric field | Correct sum |
142
+ | SUM-002 | Sum with filter | Query + field | Sum of matching docs only |
143
+ | SUM-003 | Sum empty result | No matches | Returns 0 |
144
+ | SUM-004 | Sum non-numeric field | String field | Returns 0 or handles gracefully |
145
+ | SUM-005 | Sum non-existent field | Invalid field name | Returns 0 |
146
+ | SUM-006 | Sum with mixed null values | Some docs have null | Handles nulls correctly |
147
+
148
+ ---
149
+
150
+ ### 1.6 Array Operations
151
+
152
+ #### `push(code, query, ele)`
153
+ | Test ID | Description | Input | Expected Behavior |
154
+ |---------|-------------|-------|-------------------|
155
+ | PSH-001 | Push to existing array | `{ tags: "new" }` | Element added to array |
156
+ | PSH-002 | Push duplicate element | Same element twice | Duplicate added |
157
+ | PSH-003 | Push to non-existent array | New field | Array created with element |
158
+ | PSH-004 | Push to multiple documents | Query matching many | All docs updated |
159
+
160
+ #### `pull(code, query, ele)`
161
+ | Test ID | Description | Input | Expected Behavior |
162
+ |---------|-------------|-------|-------------------|
163
+ | PLL-001 | Pull existing element | Matching element | Element removed |
164
+ | PLL-002 | Pull non-existent element | Non-matching element | No error, array unchanged |
165
+ | PLL-003 | Pull all occurrences | Duplicate elements | All occurrences removed |
166
+
167
+ #### `add_to_set(code, query, ele)`
168
+ | Test ID | Description | Input | Expected Behavior |
169
+ |---------|-------------|-------|-------------------|
170
+ | ATS-001 | Add unique element | New element | Element added |
171
+ | ATS-002 | Add duplicate element | Existing element | No duplicate added |
172
+ | ATS-003 | Add to non-existent array | New field | Array created |
173
+
174
+ ---
175
+
176
+ ### 1.7 Bulk Operations
177
+
178
+ #### `bulk_update(col, items, attrs)`
179
+ | Test ID | Description | Input | Expected Behavior |
180
+ |---------|-------------|-------|-------------------|
181
+ | BLK-001 | Bulk upsert new items | New items array | All items inserted |
182
+ | BLK-002 | Bulk update existing items | Matching attr items | Items updated |
183
+ | BLK-003 | Bulk mixed insert/update | Some new, some existing | Correct upsert behavior |
184
+ | BLK-004 | Bulk with single attr key | Single attr in array | Correct key matching |
185
+ | BLK-005 | Bulk with composite key | Multiple attrs | Composite key matching |
186
+ | BLK-006 | Bulk empty items | Empty array | No error |
187
+
188
+ ---
189
+
190
+ ### 1.8 Logging Functions
191
+
192
+ #### `log_debug/log_info/log_warn/log_error`
193
+ | Test ID | Description | Input | Expected Behavior |
194
+ |---------|-------------|-------|-------------------|
195
+ | LOG-001 | Log debug when enabled | Debug message | Log persisted if enabled |
196
+ | LOG-002 | Log error with extra data | Message + `{ code: 500 }` | Extra data saved |
197
+ | LOG-003 | Log when save_db disabled | Any log call | No database write |
198
+ | LOG-004 | Log with user session | Request with user | user_id captured |
199
+ | LOG-005 | Log categories | Different LOG_* categories | Category saved correctly |
200
+ | LOG-006 | Log level filtering | Lower than configured level | Log not persisted |
201
+
202
+ ---
203
+
204
+ ### 1.9 Connection Management
205
+
206
+ #### `get_db(callback)`
207
+ | Test ID | Description | Input | Expected Behavior |
208
+ |---------|-------------|-------|-------------------|
209
+ | GDB-001 | Get singleton instance | First call | New DB instance created |
210
+ | GDB-002 | Get singleton instance again | Second call | Same instance returned |
211
+ | GDB-003 | Get with callback | Callback function | Callback invoked |
212
+
213
+ #### `close_db()`
214
+ | Test ID | Description | Input | Expected Behavior |
215
+ |---------|-------------|-------|-------------------|
216
+ | CDB-001 | Close open connection | Active connection | Connection closed |
217
+ | CDB-002 | Close already closed | Closed connection | No error |
218
+
219
+ ---
220
+
221
+ ## 2. Entity Class Test Cases (`entity.js`)
222
+
223
+ ### 2.1 Constructor & Initialization
224
+
225
+ #### `constructor(meta)`
226
+ | Test ID | Description | Input | Expected Behavior |
227
+ |---------|-------------|-------|-------------------|
228
+ | ENT-001 | Initialize with meta object | Meta definition object | Entity initialized |
229
+ | ENT-002 | Initialize with string (collection name) | `"users"` | Meta resolved from registry |
230
+ | ENT-003 | Initialize with undefined meta | `undefined` | Error or default behavior |
231
+
232
+ ---
233
+
234
+ ### 2.2 Entity CRUD Operations
235
+
236
+ #### `list_entity(query_params, query, param_obj, view)`
237
+ | Test ID | Description | Input | Expected Behavior |
238
+ |---------|-------------|-------|-------------------|
239
+ | LST-001 | List all entities | Empty params | Returns all with pagination |
240
+ | LST-002 | List with search filters | Search params | Filtered results |
241
+ | LST-003 | List with pagination | page=2, limit=10 | Correct page returned |
242
+ | LST-004 | List with sort | Sort params | Sorted results |
243
+ | LST-005 | List with view filter | Specific view | View-filtered fields |
244
+ | LST-006 | List returns total count | Any query | Total count in response |
245
+ | LST-007 | List with comparison operators | `>=100`, `<50` | Comparison query built |
246
+ | LST-008 | List with regex search | String search value | Regex query applied |
247
+
248
+ #### `create_entity(param_obj, view)`
249
+ | Test ID | Description | Input | Expected Behavior |
250
+ |---------|-------------|-------|-------------------|
251
+ | CRE-001 | Create with valid data | Required fields | Entity created with SUCCESS |
252
+ | CRE-002 | Create with missing required field | Incomplete data | Returns NO_PARAMS or INVALID_PARAMS |
253
+ | CRE-003 | Create with duplicate primary key | Existing key | Returns DUPLICATE_KEY |
254
+ | CRE-004 | Create triggers before_create hook | Data with hook defined | Hook executed |
255
+ | CRE-005 | Create triggers after_create hook | Data with hook defined | Hook executed |
256
+ | CRE-006 | Create with ref field validation | Invalid ref value | Returns REF_NOT_FOUND |
257
+ | CRE-007 | Create with ref_label resolution | Ref label string | Resolved to ObjectId |
258
+ | CRE-008 | Create with view-filtered fields | Fields not in view | Extra fields ignored |
259
+
260
+ #### `update_entity(_id, param_obj, view)`
261
+ | Test ID | Description | Input | Expected Behavior |
262
+ |---------|-------------|-------|-------------------|
263
+ | UPE-001 | Update existing entity | Valid _id + update data | Entity updated |
264
+ | UPE-002 | Update non-existent entity | Invalid _id | Returns NOT_FOUND |
265
+ | UPE-003 | Update with invalid _id format | Malformed _id | Returns error |
266
+ | UPE-004 | Update triggers before_update hook | Hook defined | Hook executed |
267
+ | UPE-005 | Update by primary key | null _id + primary key obj | Updated by PK |
268
+ | UPE-006 | Update with invalid ref | Bad ref value | Returns REF_NOT_FOUND |
269
+ | UPE-007 | Update readonly fields | Try to update readonly | Fields unchanged |
270
+
271
+ #### `clone_entity(_id, param_obj, view)`
272
+ | Test ID | Description | Input | Expected Behavior |
273
+ |---------|-------------|-------|-------------------|
274
+ | CLN-001 | Clone existing entity | Valid source _id | New entity created |
275
+ | CLN-002 | Clone with override values | _id + override params | Overrides applied |
276
+ | CLN-003 | Clone non-existent entity | Invalid _id | Returns NOT_FOUND |
277
+ | CLN-004 | Clone with duplicate key | Conflicting key | Returns DUPLICATE_KEY |
278
+
279
+ #### `batch_update_entity(_ids, param_obj, view)`
280
+ | Test ID | Description | Input | Expected Behavior |
281
+ |---------|-------------|-------|-------------------|
282
+ | BAT-001 | Batch update multiple entities | Array of _ids | All entities updated |
283
+ | BAT-002 | Batch update with some invalid | Mixed valid/invalid ids | Partial success or error |
284
+ | BAT-003 | Batch update empty array | `[]` | No-op or error |
285
+
286
+ #### `read_entity(_id, attr_names, view)`
287
+ | Test ID | Description | Input | Expected Behavior |
288
+ |---------|-------------|-------|-------------------|
289
+ | REE-001 | Read existing entity | Valid _id | Returns entity data |
290
+ | REE-002 | Read with specific attributes | _id + "name,age" | Only specified attrs |
291
+ | REE-003 | Read non-existent entity | Invalid _id | Returns NOT_FOUND |
292
+ | REE-004 | Read with ref conversion | Entity with ref fields | Refs resolved to labels |
293
+ | REE-005 | Read with link attributes | Entity with links | Link data populated |
294
+ | REE-006 | Read with view filter | Specific view | View-allowed fields only |
295
+
296
+ #### `read_property(_id, attr_names, view)`
297
+ | Test ID | Description | Input | Expected Behavior |
298
+ |---------|-------------|-------|-------------------|
299
+ | REP-001 | Read raw properties | Valid _id | Returns without ref conversion |
300
+ | REP-002 | Read specific properties | _id + attr list | Only specified attrs |
301
+
302
+ #### `delete_entity(id_array)`
303
+ | Test ID | Description | Input | Expected Behavior |
304
+ |---------|-------------|-------|-------------------|
305
+ | DLE-001 | Delete single entity | Single _id array | Entity deleted |
306
+ | DLE-002 | Delete multiple entities | Multiple _ids | All deleted |
307
+ | DLE-003 | Delete with references | Entity referenced elsewhere | Returns HAS_REF |
308
+ | DLE-004 | Delete triggers before_delete hook | Hook defined | Hook executed |
309
+ | DLE-005 | Delete non-existent | Invalid _id | Returns NOT_FOUND or no-op |
310
+ | DLE-006 | Delete with cascade | Referencing entities exist | Error or cascade |
311
+
312
+ ---
313
+
314
+ ### 2.3 Reference Validation
315
+
316
+ #### `validate_ref(param_obj)`
317
+ | Test ID | Description | Input | Expected Behavior |
318
+ |---------|-------------|-------|-------------------|
319
+ | VRF-001 | Validate existing ref value | Valid ObjectId | Returns SUCCESS |
320
+ | VRF-002 | Validate by ref_label | Label string | Resolves to ObjectId |
321
+ | VRF-003 | Validate non-existent ref | Invalid ref value | Returns REF_NOT_FOUND |
322
+ | VRF-004 | Validate ambiguous ref_label | Multiple matches | Returns REF_NOT_UNIQUE |
323
+ | VRF-005 | Validate with ref_filter | Filter applied | Filtered validation |
324
+
325
+ ---
326
+
327
+ ### 2.4 Search Query Building
328
+
329
+ #### `get_search_query(param_obj)`
330
+ | Test ID | Description | Input | Expected Behavior |
331
+ |---------|-------------|-------|-------------------|
332
+ | GSQ-001 | Build query from string field | `{ name: "test" }` | Regex query built |
333
+ | GSQ-002 | Build query with comparison | `{ age: ">=18" }` | `$gte` operator |
334
+ | GSQ-003 | Build query with exact match | Boolean/number field | Exact match query |
335
+ | GSQ-004 | Build query no search fields | Empty/null params | Returns null |
336
+ | GSQ-005 | Build query with type conversion | String to number | Value converted |
337
+
338
+ ---
339
+
340
+ ### 2.5 Reference & Link Operations
341
+
342
+ #### `convert_ref_attrs(elements, ref_fields)`
343
+ | Test ID | Description | Input | Expected Behavior |
344
+ |---------|-------------|-------|-------------------|
345
+ | CRA-001 | Convert ObjectId to ref_label | Elements with refs | Labels resolved |
346
+ | CRA-002 | Convert null ref | Null ref value | Handled gracefully |
347
+ | CRA-003 | Convert invalid ObjectId ref | Corrupted ref | Error handled |
348
+
349
+ #### `read_link_attrs(elements, link_fields)`
350
+ | Test ID | Description | Input | Expected Behavior |
351
+ |---------|-------------|-------|-------------------|
352
+ | RLA-001 | Read single link | Link field defined | Linked data fetched |
353
+ | RLA-002 | Read multiple links | Multiple link fields | All links resolved |
354
+ | RLA-003 | Read link no match | No matching linked data | Empty/null link |
355
+
356
+ #### `get_filtered_ref_labels(ref_by_entity, client_query)`
357
+ | Test ID | Description | Input | Expected Behavior |
358
+ |---------|-------------|-------|-------------------|
359
+ | GFL-001 | Get labels with filter | Query string | Filtered labels returned |
360
+ | GFL-002 | Get labels empty query | Empty query | All available labels |
361
+ | GFL-003 | Get labels with ref_filter | Filter config | Filter applied |
362
+
363
+ ---
364
+
365
+ ### 2.6 Utility Methods
366
+
367
+ #### `filter_fields_by_view(fields, view)`
368
+ | Test ID | Description | Input | Expected Behavior |
369
+ |---------|-------------|-------|-------------------|
370
+ | FFV-001 | Filter by existing view | Valid view name | Matching fields returned |
371
+ | FFV-002 | Filter by non-existent view | Invalid view | All fields or empty |
372
+
373
+ #### `primary_key_query(param_obj)`
374
+ | Test ID | Description | Input | Expected Behavior |
375
+ |---------|-------------|-------|-------------------|
376
+ | PKQ-001 | Build PK query single key | Object with PK | Returns query object |
377
+ | PKQ-002 | Build PK composite key | Multiple PK fields | Composite query |
378
+ | PKQ-003 | Build PK missing field | Incomplete PK | Returns null |
379
+
380
+ #### `check_refer_entity(id_array)`
381
+ | Test ID | Description | Input | Expected Behavior |
382
+ |---------|-------------|-------|-------------------|
383
+ | CRF-001 | Check with references | Referenced entity ids | Returns ref descriptions |
384
+ | CRF-002 | Check no references | Unreferenced ids | Returns empty array |
385
+
386
+ ---
387
+
388
+ ## 3. GridFS Class Test Cases (`gridfs.js`)
389
+
390
+ ### 3.1 Singleton Instance
391
+
392
+ #### `get_gridfs_instance()`
393
+ | Test ID | Description | Input | Expected Behavior |
394
+ |---------|-------------|-------|-------------------|
395
+ | GGI-001 | Get instance first time | None | Creates new GridFS instance |
396
+ | GGI-002 | Get instance again | None | Returns same singleton |
397
+
398
+ ---
399
+
400
+ ### 3.2 GridFS Class Methods
401
+
402
+ #### `bucket(bucket_name)`
403
+ | Test ID | Description | Input | Expected Behavior |
404
+ |---------|-------------|-------|-------------------|
405
+ | BKT-001 | Get bucket by name | Valid bucket name | Returns GridFSBucket |
406
+ | BKT-002 | Get bucket creates with correct chunk size | Any name | 1MB chunk size |
407
+
408
+ #### `save_file(bucket_name, filename, source)`
409
+ | Test ID | Description | Input | Expected Behavior |
410
+ |---------|-------------|-------|-------------------|
411
+ | SVF-001 | Save file from path | Path string | File saved to GridFS |
412
+ | SVF-002 | Save file from stream | Readable stream | Stream piped to GridFS |
413
+ | SVF-003 | Save replaces existing | Same filename | Old file deleted, new saved |
414
+ | SVF-004 | Save to new bucket | Non-existent bucket | Bucket auto-created |
415
+ | SVF-005 | Save non-existent file | Invalid path | Error thrown |
416
+ | SVF-006 | Save empty file | Empty file | File saved (0 bytes) |
417
+ | SVF-007 | Save large file | Large file (multi-chunk) | File chunked correctly |
418
+
419
+ #### `read_file(bucket_name, filename, response)`
420
+ | Test ID | Description | Input | Expected Behavior |
421
+ |---------|-------------|-------|-------------------|
422
+ | RDF-001 | Read existing file | Valid filename + response | File streamed to response |
423
+ | RDF-002 | Read non-existent file | Invalid filename | Response 404 |
424
+ | RDF-003 | Read from non-existent bucket | Invalid bucket | Error or 404 |
425
+
426
+ #### `pipe_file(bucket_name, filename, dest_path)`
427
+ | Test ID | Description | Input | Expected Behavior |
428
+ |---------|-------------|-------|-------------------|
429
+ | PPF-001 | Pipe file to disk | Valid file + dest path | File written to disk |
430
+ | PPF-002 | Pipe non-existent file | Invalid filename | Error thrown |
431
+ | PPF-003 | Pipe to invalid path | Non-writable path | Error thrown |
432
+
433
+ #### `delete_file(bucket_name, filename)`
434
+ | Test ID | Description | Input | Expected Behavior |
435
+ |---------|-------------|-------|-------------------|
436
+ | DLF-001 | Delete existing file | Valid filename | File removed |
437
+ | DLF-002 | Delete non-existent file | Invalid filename | No error (idempotent) |
438
+ | DLF-003 | Delete from non-existent bucket | Invalid bucket | No error |
439
+
440
+ ---
441
+
442
+ ### 3.3 Entity File Field Helpers
443
+
444
+ #### `set_file_fields(meta, req, obj)`
445
+ | Test ID | Description | Input | Expected Behavior |
446
+ |---------|-------------|-------|-------------------|
447
+ | SFF-001 | Set single file field | Single file upload | Field set to PK-based name |
448
+ | SFF-002 | Set multiple file fields | Multiple uploads | Each field named with suffix |
449
+ | SFF-003 | Set with no files | Empty req.files | Fields deleted from obj |
450
+ | SFF-004 | Set with no file_fields meta | No meta definition | No-op |
451
+
452
+ #### `save_file_fields_to_db(collection, file_fields, req, obj)`
453
+ | Test ID | Description | Input | Expected Behavior |
454
+ |---------|-------------|-------|-------------------|
455
+ | SFD-001 | Save uploaded files | Valid file uploads | Files saved to GridFS |
456
+ | SFD-002 | Save cleans up temp files | After save | Temp files deleted |
457
+ | SFD-003 | Save with no files | Empty req.files | No-op |
458
+ | SFD-004 | Save with missing field value | Field not in obj | Skipped |
459
+
460
+ ---
461
+
462
+ ### 3.4 Wrapper API Functions
463
+
464
+ #### `save_file(collection, filename, filepath)`
465
+ | Test ID | Description | Input | Expected Behavior |
466
+ |---------|-------------|-------|-------------------|
467
+ | WRP-001 | Wrapper save delegates | All params | Calls GridFS.save_file |
468
+
469
+ #### `read_file(collection, filename, response)`
470
+ | Test ID | Description | Input | Expected Behavior |
471
+ |---------|-------------|-------|-------------------|
472
+ | WRP-002 | Wrapper read delegates | All params | Calls GridFS.read_file |
473
+
474
+ #### `pipe_file(collection, filename, dest_filename)`
475
+ | Test ID | Description | Input | Expected Behavior |
476
+ |---------|-------------|-------|-------------------|
477
+ | WRP-003 | Wrapper pipe delegates | All params | Calls GridFS.pipe_file |
478
+
479
+ #### `delete_file(collection, filename)`
480
+ | Test ID | Description | Input | Expected Behavior |
481
+ |---------|-------------|-------|-------------------|
482
+ | WRP-004 | Wrapper delete delegates | All params | Calls GridFS.delete_file |
483
+
484
+ ---
485
+
486
+ ## 4. Test Case Categories Summary
487
+
488
+ | Category | Test Count | Priority |
489
+ |----------|------------|----------|
490
+ | DB ObjectId Utilities | 12 | High |
491
+ | DB CRUD Operations | 21 | Critical |
492
+ | DB Query Operations | 23 | Critical |
493
+ | DB Aggregate Operations | 10 | High |
494
+ | DB Array Operations | 10 | Medium |
495
+ | DB Bulk Operations | 6 | Medium |
496
+ | DB Logging | 6 | Low |
497
+ | DB Connection | 5 | High |
498
+ | Entity CRUD | 35 | Critical |
499
+ | Entity Reference Validation | 5 | High |
500
+ | Entity Search Query | 5 | Medium |
501
+ | Entity Ref/Link Operations | 9 | High |
502
+ | Entity Utilities | 6 | Medium |
503
+ | GridFS Instance | 2 | High |
504
+ | GridFS Operations | 17 | High |
505
+ | GridFS Entity Helpers | 8 | Medium |
506
+ | GridFS Wrapper API | 4 | Low |
507
+
508
+ **Total Test Cases: 184**
509
+
510
+ ---
511
+
512
+ ## 5. Test Execution Notes
513
+
514
+ ### Prerequisites
515
+ - MongoDB instance running
516
+ - Test database configured in settings
517
+ - Clean test collections before/after each test
518
+
519
+ ### Test Data Patterns
520
+ - Use unique collection names per test suite (e.g., `test_user_001`)
521
+ - Clean up test data in `afterEach` hooks
522
+ - Use descriptive test names matching Test IDs
523
+
524
+ ### Mocking Considerations
525
+ - Mock `get_settings()` for logging tests
526
+ - Mock HTTP response objects for GridFS streaming tests
527
+ - Mock `fs` for file operation tests
528
+ - Consider mocking MongoDB for unit tests vs. using real DB for integration tests