@futdevpro/nts-dynamo 1.15.2 → 1.15.3

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 (121) hide show
  1. package/.cursor/rules/__assistant_guide.mdc +30 -0
  2. package/.cursor/rules/__main.mdc +62 -0
  3. package/.cursor/rules/_ag_backend-structure.mdc +86 -0
  4. package/.cursor/rules/_ag_backend.mdc +16 -0
  5. package/.cursor/rules/_ag_debug.mdc +8 -0
  6. package/.cursor/rules/_ag_documentation_writing_rules.mdc +372 -0
  7. package/.cursor/rules/_ag_file-refactoring.mdc +113 -0
  8. package/.cursor/rules/_ag_fixes_rules.mdc +6 -0
  9. package/.cursor/rules/_ag_frontend-structure.mdc +87 -0
  10. package/.cursor/rules/_ag_frontend.mdc +40 -0
  11. package/.cursor/rules/_ag_import-rules.mdc +45 -0
  12. package/.cursor/rules/_ag_naming.mdc +116 -0
  13. package/.cursor/rules/_ag_running_commands.mdc +5 -0
  14. package/.cursor/rules/_ag_server-controller.mdc +6 -0
  15. package/.cursor/rules/_ag_should-be.mdc +7 -0
  16. package/.cursor/rules/_ag_swearing.mdc +47 -0
  17. package/.cursor/rules/ai_development_guide.md +61 -0
  18. package/.cursor/rules/ai_directives.md +114 -0
  19. package/.cursor/rules/cursor-rules.md +160 -0
  20. package/.cursor/rules/default-command.mdc +229 -0
  21. package/.cursor/rules/error_code_pattern.md +40 -0
  22. package/.cursor/rules/saved rule mcp server use.md +16 -0
  23. package/build/_modules/custom-data/custom-data.controller.d.ts.map +1 -1
  24. package/build/_modules/custom-data/custom-data.controller.js +1 -2
  25. package/build/_modules/custom-data/custom-data.controller.js.map +1 -1
  26. package/build/_services/core/api.service.d.ts.map +1 -1
  27. package/build/_services/core/api.service.js +1 -0
  28. package/build/_services/core/api.service.js.map +1 -1
  29. package/package.json +5 -4
  30. package/scripts/run-coverage-tests.js +5 -1
  31. package/spec/support/helpers/spec-reporter-loader.js +359 -0
  32. package/spec/support/helpers/ts-node-helper.js +84 -0
  33. package/spec/support/jasmine.coverage.json +2 -1
  34. package/spec/support/jasmine.json +3 -3
  35. package/src/_collections/archive.util.spec.ts +36 -0
  36. package/src/_collections/get-environment-settings.util.spec.ts +210 -0
  37. package/src/_collections/star.controller.spec.ts +224 -0
  38. package/src/_models/control-models/api-call-params.control-model.spec.ts +62 -3
  39. package/src/_models/control-models/app-ext-system-controls.control-model.spec.ts +52 -0
  40. package/src/_models/control-models/app-params.control-model.spec.ts +158 -2
  41. package/src/_models/control-models/endpoint-params.control-model.spec.ts +578 -0
  42. package/src/_modules/ai/_modules/document-ai/_collections/dai-chunking.util.spec.ts +242 -0
  43. package/src/_modules/ai/_modules/document-ai/_collections/dai-document.util.spec.ts +209 -0
  44. package/src/_modules/ai/_modules/open-ai/_services/data-services/oai-document.data-service.spec.ts +342 -0
  45. package/src/_modules/ai/_modules/open-ai/_services/data-services/oai-vector-data.service.spec.ts +550 -0
  46. package/src/_modules/ai/_modules/open-ai/_services/oai-embedding.control-service.spec.ts +240 -0
  47. package/src/_modules/ai/_modules/open-ai/_services/oai-llm-chat.service-base.spec.ts +462 -0
  48. package/src/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.spec.ts +437 -0
  49. package/src/_modules/ai/_services/ai-embedding.service-base.spec.ts +98 -0
  50. package/src/_modules/ai/_services/ai-llm-chat.service-base.spec.ts +229 -0
  51. package/src/_modules/ai/_services/ai-llm.service-base.spec.ts +250 -0
  52. package/src/_modules/ai/_services/ai-provider.service-base.spec.ts +79 -0
  53. package/src/_modules/assistant/_collections/ass.util.spec.ts +176 -0
  54. package/src/_modules/assistant/_services/ass-io.control-service.spec.ts +140 -0
  55. package/src/_modules/assistant/_services/ass-main.control-service.spec.ts +192 -0
  56. package/src/_modules/bot/_modules/discord-bot/_services/dib-messaging-provider.control-service.spec.ts +431 -0
  57. package/src/_modules/bot/_modules/dynamo-bot/_collections/dyb-operations.util.spec.ts +160 -0
  58. package/src/_modules/bot/_modules/dynamo-bot/_services/dyb-messaging-provider.control-service.spec.ts +374 -0
  59. package/src/_modules/bot/_modules/slack-bot/_services/slb-messaging-provider.control-service.spec.ts +344 -0
  60. package/src/_modules/bot/_modules/teams-bot/_services/teb-messaging-provider.control-service.spec.ts +345 -0
  61. package/src/_modules/bot/_services/bot-commands.control-service.spec.ts +116 -0
  62. package/src/_modules/bot/_services/bot-io.control-service.spec.ts +285 -0
  63. package/src/_modules/bot/_services/bot-main.control-service.spec.ts +208 -0
  64. package/src/_modules/bot/_services/bot-messaging-provider.service-base.spec.ts +349 -0
  65. package/src/_modules/bot/_services/bot-routines.control-service.spec.ts +111 -0
  66. package/src/_modules/custom-data/custom-data.controller.spec.ts +49 -0
  67. package/src/_modules/custom-data/custom-data.controller.ts +1 -3
  68. package/src/_modules/custom-data/custom-data.data-service.spec.ts +54 -0
  69. package/src/_modules/custom-data/get-custom-data-routing-module.util.spec.ts +28 -0
  70. package/src/_modules/defaults/_services/default-auth.service.spec.ts +269 -0
  71. package/src/_modules/defaults/_services/default-socket-events.service.spec.ts +42 -0
  72. package/src/_modules/defaults/_services/default-user.data-service.spec.ts +187 -0
  73. package/src/_modules/discord-assistant/_collections/dias.util.spec.ts +366 -0
  74. package/src/_modules/discord-assistant/_services/dias-io.control-service.spec.ts +108 -0
  75. package/src/_modules/discord-assistant/_services/dias-main.control-service.spec.ts +22 -0
  76. package/src/_modules/discord-assistant/_services/dias.service-base.spec.ts +195 -0
  77. package/src/_modules/discord-assistant-voiced/_services/dias-discord-bot.control-service.spec.ts +34 -0
  78. package/src/_modules/discord-bot/_collections/dibo-operations.util.spec.ts +214 -0
  79. package/src/_modules/discord-bot/_services/dibo-commands.control-service.spec.ts +154 -0
  80. package/src/_modules/discord-bot/_services/dibo-io.control-service.spec.ts +264 -0
  81. package/src/_modules/discord-bot/_services/dibo-main.control-service.spec.ts +408 -0
  82. package/src/_modules/discord-bot/_services/dibo-routines.control-service.spec.ts +105 -0
  83. package/src/_modules/local-vector-search/_services/lvs-doc-chunk-data.service.spec.ts +418 -0
  84. package/src/_modules/local-vector-search/_services/lvs-local-vector-search.data-service.spec.ts +345 -0
  85. package/src/_modules/messaging/_collections/msg.util.spec.ts +226 -0
  86. package/src/_modules/messaging/_services/msg-events.service.spec.ts +219 -0
  87. package/src/_modules/messaging/_services/msg-main.control-service.spec.ts +147 -0
  88. package/src/_modules/messaging/_services/msg.controller.spec.ts +201 -0
  89. package/src/_modules/mock/data-model.mock.spec.ts +27 -24
  90. package/src/_modules/oauth2/_routes/oauth2.controller.spec.ts +107 -0
  91. package/src/_modules/oauth2/_services/oauth2.auth-service.spec.ts +254 -0
  92. package/src/_modules/oauth2/_services/oauth2.control-service.spec.ts +585 -0
  93. package/src/_modules/server/errors/errors.control-service.spec.ts +230 -0
  94. package/src/_modules/server/errors/errors.controller.spec.ts +165 -0
  95. package/src/_modules/server/errors/errors.data-service.spec.ts +355 -0
  96. package/src/_modules/server/server-status/server-status-snapshot.control-service.spec.ts +70 -0
  97. package/src/_modules/server/server-status/server-status-snapshot.data-service.spec.ts +77 -0
  98. package/src/_modules/server/server-status/server-status.control-service.spec.ts +516 -0
  99. package/src/_modules/server/server-status/server-status.controller.spec.ts +156 -0
  100. package/src/_modules/socket/_models/socket-client-service-params.control-model.spec.ts +6 -3
  101. package/src/_modules/socket/_models/socket-presence.control-model.spec.ts +164 -0
  102. package/src/_modules/socket/_services/socket-client.service.spec.ts +15 -0
  103. package/src/_modules/test/get-test-routing-module.util.spec.ts +28 -0
  104. package/src/_modules/test/test.controller.spec.ts +72 -0
  105. package/src/_modules/usage/usage.controller.spec.ts +81 -0
  106. package/src/_modules/usage/usage.data-service.spec.ts +332 -0
  107. package/src/_services/base/api.service-base.spec.ts +125 -0
  108. package/src/_services/base/archive-data.service.spec.ts +196 -0
  109. package/src/_services/base/data.service.spec.ts +493 -0
  110. package/src/_services/base/db.service.spec.ts +59 -18
  111. package/src/_services/base/singleton.service-base.spec.ts +28 -0
  112. package/src/_services/base/singleton.service.spec.ts +114 -0
  113. package/src/_services/core/api.service.ts +1 -0
  114. package/src/_services/core/auth.service.spec.ts +159 -0
  115. package/src/_services/core/email.service.spec.ts +14 -22
  116. package/src/_services/core/global.service.spec.ts +275 -0
  117. package/src/_services/core/service-collection.service.spec.ts +46 -0
  118. package/src/_services/route/routing-module.service.spec.ts +8 -6
  119. package/src/_services/shared.static-service.spec.ts +89 -0
  120. package/src/_modules/socket/app-extended.server.spec.ts +0 -227
  121. package/src/_services/server/app.server.spec.ts +0 -138
@@ -0,0 +1,418 @@
1
+
2
+ import { DyNTS_LVS_DocChunkDataService } from './lvs-doc-chunk-data.service';
3
+ import { DyFM_OAI_Settings, DyFM_OAI_Model } from '@futdevpro/fsm-dynamo/ai/open-ai';
4
+ import { DyNTS_DAI_DocChunk, DyNTS_DAI_docChunk_dataParams } from '../../ai/_modules/document-ai/_models/data-models/dai-doc-chunk.data-model';
5
+ import { DyNTS_DAI_DocPage } from '../../ai/_modules/document-ai/_models/data-models/dai-doc-page.data-model';
6
+ import { DyNTS_DAI_DocChunkCompareResult } from '../../ai/_modules/document-ai/_models/interfaces/dai-doc-chunk-compare-result.interface';
7
+ import { DyNTS_DAI_CompareResult_Type } from '../../ai/_modules/document-ai/_enums/dai-compare-result-type.enum';
8
+ import { DyFM_Error, DyFM_EnvironmentFlag } from '@futdevpro/fsm-dynamo';
9
+ import { DyNTS_DAI_DocChunking_Util } from '../../ai/_modules/document-ai/_collections/dai-chunking.util';
10
+ import { DyNTS_DAI_Document_Util } from '../../ai/_modules/document-ai/_collections/dai-document.util';
11
+ import { DyNTS_global_settings } from '../../../_collections/global-settings.const';
12
+ import { DyNTS_GlobalService } from '../../../_services/core/global.service';
13
+
14
+ describe('| DyNTS_LVS_DocChunkDataService', () => {
15
+ let service: DyNTS_LVS_DocChunkDataService;
16
+ let mockOpenAISettings: DyFM_OAI_Settings;
17
+ let mockDBService: jasmine.SpyObj<{
18
+ find: (filter: unknown) => Promise<unknown[]>;
19
+ findOne: (filter: unknown) => Promise<unknown>;
20
+ getDataById: (id: string) => Promise<unknown>;
21
+ getAll: () => Promise<unknown[]>;
22
+ createData: (data: unknown, issuer: string) => Promise<unknown>;
23
+ modifyData: (data: unknown, issuer: string, dontUpdateModified?: boolean) => Promise<unknown>;
24
+ markDeletedById: (id: string, issuer: string) => Promise<void>;
25
+ }>;
26
+
27
+ beforeEach(() => {
28
+ DyNTS_global_settings.env_settings = {
29
+ environment: DyFM_EnvironmentFlag.local,
30
+ mongoUri: 'mongodb://localhost:27017/test',
31
+ } as typeof DyNTS_global_settings.env_settings;
32
+
33
+ mockDBService = jasmine.createSpyObj('DyNTS_DBService', [
34
+ 'find',
35
+ 'findOne',
36
+ 'getDataById',
37
+ 'getAll',
38
+ 'getDataListByIds',
39
+ 'getDataByDependencyId',
40
+ 'getDataListByDependencyId',
41
+ 'getDataListByDependencyIds',
42
+ 'createData',
43
+ 'modifyData',
44
+ 'updateOne',
45
+ 'markDeletedById',
46
+ 'trueDeleteDataById',
47
+ 'trueDeleteAllData',
48
+ 'restoreDeletedById',
49
+ ]);
50
+ spyOn(DyNTS_GlobalService, 'getDBService').and.returnValue(mockDBService as never);
51
+ spyOn(DyNTS_GlobalService, 'getDBServiceByKey').and.returnValue(mockDBService as never);
52
+
53
+ mockOpenAISettings = {
54
+ config: {
55
+ apiKey: 'test-api-key',
56
+ organization: 'test-org',
57
+ },
58
+ defaultSettings: {
59
+ useModel: DyFM_OAI_Model.textEmbedding_3Small,
60
+ },
61
+ };
62
+
63
+ service = new DyNTS_LVS_DocChunkDataService(
64
+ 'test-issuer',
65
+ mockOpenAISettings
66
+ );
67
+ service.clickupWorkspaceId = 'workspace-123';
68
+ });
69
+
70
+ describe('| constructor', () => {
71
+ it('| should initialize with issuer and settings', () => {
72
+ expect((service as any).issuer).toBe('test-issuer');
73
+ expect((service as any).openAISettings).toEqual(mockOpenAISettings);
74
+ });
75
+ });
76
+
77
+ describe('| getDocumentDataService', () => {
78
+ it('| should return document data service', () => {
79
+ const result = service.getDocumentDataService();
80
+
81
+ expect(result).toBeDefined();
82
+ expect((result as any).issuer).toBe('test-issuer');
83
+ });
84
+ });
85
+
86
+ describe('| getDocPageDataService', () => {
87
+ it('| should return doc page data service', () => {
88
+ const result = service.getDocPageDataService();
89
+
90
+ expect(result).toBeDefined();
91
+ expect((result as any).issuer).toBe('test-issuer');
92
+ });
93
+ });
94
+
95
+ describe('| getPageLink', () => {
96
+ it('| should return page link', () => {
97
+ const mockPage = {
98
+ name: 'Test Page',
99
+ externalDocumentId: 'doc-123',
100
+ externalPageId: 'page-456',
101
+ } as any;
102
+
103
+ spyOn(DyNTS_DAI_Document_Util, 'getClickupPageLink').and.returnValue('[Test Page](link)');
104
+
105
+ const result = service.getPageLink(mockPage);
106
+
107
+ expect(result).toBe('[Test Page](link)');
108
+ expect(DyNTS_DAI_Document_Util.getClickupPageLink).toHaveBeenCalledWith(
109
+ 'Test Page',
110
+ 'workspace-123',
111
+ 'doc-123',
112
+ 'page-456'
113
+ );
114
+ });
115
+ });
116
+
117
+ describe('| chunkPage', () => {
118
+ it('| should chunk page content', async () => {
119
+ const mockPage: DyNTS_DAI_DocPage = {
120
+ _id: 'page-123',
121
+ name: 'Test Page',
122
+ content: '# Test\n\nContent here',
123
+ chunks: [],
124
+ externalDocumentId: 'doc-123',
125
+ externalPageId: 'page-456',
126
+ } as any;
127
+
128
+ spyOn(DyNTS_DAI_DocChunking_Util, 'chunkMdContent').and.returnValue(Promise.resolve([
129
+ {
130
+ _id: 'chunk-1',
131
+ chunkContent: '# Test\n\nContent here',
132
+ chunkIndex: 0,
133
+ } as any,
134
+ ]));
135
+
136
+ const result = await service.chunkPage(mockPage);
137
+
138
+ expect(result).toBeDefined();
139
+ expect(result.length).toBeGreaterThan(0);
140
+ expect(DyNTS_DAI_DocChunking_Util.chunkMdContent).toHaveBeenCalled();
141
+ });
142
+
143
+ it('| should handle chunking errors', async () => {
144
+ const mockPage: DyNTS_DAI_DocPage = {
145
+ _id: 'page-123',
146
+ name: 'Test Page',
147
+ content: '# Test\n\nContent here',
148
+ chunks: [],
149
+ } as any;
150
+
151
+ const error = new Error('Chunking failed');
152
+ spyOn(DyNTS_DAI_DocChunking_Util, 'chunkMdContent').and.returnValue(Promise.reject(error));
153
+
154
+ try {
155
+ await service.chunkPage(mockPage);
156
+ fail('Should have thrown an error');
157
+ } catch (err) {
158
+ expect(err).toBeInstanceOf(DyFM_Error);
159
+ expect((err as DyFM_Error)._errorCode).toContain('DCH-CSB-CP0');
160
+ }
161
+ });
162
+ });
163
+
164
+ describe('| compareChunk', () => {
165
+ it('| should return equal when chunks are identical', async () => {
166
+ const oldChunk: DyNTS_DAI_DocChunk = {
167
+ _id: 'chunk-1',
168
+ chunkContent: 'Test content',
169
+ path: 'test/path',
170
+ documentName: 'Test Doc',
171
+ pageName: 'Test Page',
172
+ pageLink: '[Test Page](link)',
173
+ allFlaggedParents: ['flag1', 'flag2'],
174
+ } as any;
175
+
176
+ const newChunk: DyNTS_DAI_DocChunk = {
177
+ _id: 'chunk-1',
178
+ chunkContent: 'Test content',
179
+ path: 'test/path',
180
+ documentName: 'Test Doc',
181
+ pageName: 'Test Page',
182
+ pageLink: '[Test Page](link)',
183
+ allFlaggedParents: ['flag1', 'flag2'],
184
+ } as any;
185
+
186
+ const result = await service.compareChunk(newChunk, oldChunk);
187
+
188
+ expect(result.result).toBe(DyNTS_DAI_CompareResult_Type.equal);
189
+ expect(result.newChunk).toBe(newChunk);
190
+ expect(result.oldChunk).toBe(oldChunk);
191
+ });
192
+
193
+ it('| should return modified when chunks differ', async () => {
194
+ const oldChunk: DyNTS_DAI_DocChunk = {
195
+ _id: 'chunk-1',
196
+ chunkContent: 'Old content',
197
+ path: 'test/path',
198
+ documentName: 'Test Doc',
199
+ pageName: 'Test Page',
200
+ pageLink: '[Test Page](link)',
201
+ allFlaggedParents: ['flag1'],
202
+ } as any;
203
+
204
+ const newChunk: DyNTS_DAI_DocChunk = {
205
+ _id: 'chunk-1',
206
+ chunkContent: 'New content',
207
+ path: 'test/path',
208
+ documentName: 'Test Doc',
209
+ pageName: 'Test Page',
210
+ pageLink: '[Test Page](link)',
211
+ allFlaggedParents: ['flag1'],
212
+ } as any;
213
+
214
+ const result = await service.compareChunk(newChunk, oldChunk);
215
+
216
+ expect(result.result).toBe(DyNTS_DAI_CompareResult_Type.modified);
217
+ expect(result.newChunk).toBe(newChunk);
218
+ expect(result.oldChunk).toBe(oldChunk);
219
+ });
220
+
221
+ it('| should throw error if oldChunk is missing', async () => {
222
+ const newChunk: DyNTS_DAI_DocChunk = {
223
+ _id: 'chunk-1',
224
+ chunkContent: 'New content',
225
+ } as any;
226
+
227
+ try {
228
+ await service.compareChunk(newChunk, null as any);
229
+ fail('Should have thrown an error');
230
+ } catch (err) {
231
+ expect(err).toBeInstanceOf(DyFM_Error);
232
+ expect((err as DyFM_Error)._errorCode).toContain('DCH-CSB-CC1');
233
+ }
234
+ });
235
+
236
+ it('| should detect changes in allFlaggedParents', async () => {
237
+ const oldChunk: DyNTS_DAI_DocChunk = {
238
+ _id: 'chunk-1',
239
+ chunkContent: 'Test content',
240
+ path: 'test/path',
241
+ documentName: 'Test Doc',
242
+ pageName: 'Test Page',
243
+ pageLink: '[Test Page](link)',
244
+ allFlaggedParents: ['flag1'],
245
+ } as any;
246
+
247
+ const newChunk: DyNTS_DAI_DocChunk = {
248
+ _id: 'chunk-1',
249
+ chunkContent: 'Test content',
250
+ path: 'test/path',
251
+ documentName: 'Test Doc',
252
+ pageName: 'Test Page',
253
+ pageLink: '[Test Page](link)',
254
+ allFlaggedParents: ['flag1', 'flag2'],
255
+ } as any;
256
+
257
+ const result = await service.compareChunk(newChunk, oldChunk);
258
+
259
+ expect(result.result).toBe(DyNTS_DAI_CompareResult_Type.modified);
260
+ });
261
+ });
262
+
263
+ describe('| processNewPage', () => {
264
+ it('| should process new page and return compare results', async () => {
265
+ const mockPage: DyNTS_DAI_DocPage = {
266
+ _id: 'page-123',
267
+ name: 'Test Page',
268
+ content: '# Test\n\nContent here',
269
+ chunks: [],
270
+ documentId: 'doc-123',
271
+ externalDocumentId: 'ext-doc-123',
272
+ externalPageId: 'ext-page-123',
273
+ } as any;
274
+
275
+ const mockChunk: DyNTS_DAI_DocChunk = {
276
+ _id: 'chunk-1',
277
+ chunkContent: 'Test content',
278
+ chunkIndex: 0,
279
+ } as any;
280
+
281
+ spyOn(service, 'chunkPage').and.returnValue(Promise.resolve([mockChunk]));
282
+ spyOn(service, 'saveData').and.returnValue(Promise.resolve(mockChunk));
283
+
284
+ const result = await service.processNewPage(mockPage);
285
+
286
+ expect(result).toBeDefined();
287
+ expect(result.length).toBe(1);
288
+ expect(result[0].result).toBe(DyNTS_DAI_CompareResult_Type.new);
289
+ expect(result[0].newChunk).toBe(mockChunk);
290
+ expect(result[0].oldChunk).toBeNull();
291
+ });
292
+
293
+ it('| should handle processing errors', async () => {
294
+ const mockPage: DyNTS_DAI_DocPage = {
295
+ _id: 'page-123',
296
+ name: 'Test Page',
297
+ content: '# Test\n\nContent here',
298
+ chunks: [],
299
+ } as any;
300
+
301
+ const error = new Error('Processing failed');
302
+ spyOn(service, 'chunkPage').and.returnValue(Promise.reject(error));
303
+
304
+ try {
305
+ await service.processNewPage(mockPage);
306
+ fail('Should have thrown an error');
307
+ } catch (err) {
308
+ expect(err).toBeInstanceOf(DyFM_Error);
309
+ expect((err as DyFM_Error)._errorCode).toContain('DCH-CSB-PNP0');
310
+ }
311
+ });
312
+ });
313
+
314
+ describe('| processPage', () => {
315
+ it('| should process page and return compare results', async () => {
316
+ const mockPage: DyNTS_DAI_DocPage = {
317
+ _id: 'page-123',
318
+ name: 'Test Page',
319
+ content: '# Test\n\nContent here',
320
+ chunks: [],
321
+ documentId: 'doc-123',
322
+ externalDocumentId: 'ext-doc-123',
323
+ externalPageId: 'ext-page-123',
324
+ } as any;
325
+
326
+ const mockNewChunk: DyNTS_DAI_DocChunk = {
327
+ _id: 'chunk-1',
328
+ chunkContent: 'New content',
329
+ chunkIndex: 0,
330
+ } as any;
331
+
332
+ const mockOldChunk: DyNTS_DAI_DocChunk = {
333
+ _id: 'chunk-1',
334
+ chunkContent: 'Old content',
335
+ chunkIndex: 0,
336
+ } as any;
337
+
338
+ spyOn(service, 'chunkPage').and.returnValue(Promise.resolve([mockNewChunk]));
339
+ spyOn(service, 'findDataList').and.returnValue(Promise.resolve([mockOldChunk]));
340
+ spyOn(service, 'compareChunk').and.returnValue(Promise.resolve({
341
+ result: DyNTS_DAI_CompareResult_Type.modified,
342
+ newChunk: mockNewChunk,
343
+ oldChunk: mockOldChunk,
344
+ }));
345
+ spyOn(service, 'saveData').and.returnValue(Promise.resolve(mockNewChunk));
346
+
347
+ const result = await service.processPage(mockPage);
348
+
349
+ expect(result).toBeDefined();
350
+ expect(result.length).toBeGreaterThan(0);
351
+ });
352
+
353
+ it('| should handle processing errors', async () => {
354
+ const mockPage: DyNTS_DAI_DocPage = {
355
+ _id: 'page-123',
356
+ name: 'Test Page',
357
+ content: '# Test\n\nContent here',
358
+ chunks: [],
359
+ } as any;
360
+
361
+ const error = new Error('Processing failed');
362
+ spyOn(service, 'chunkPage').and.returnValue(Promise.reject(error));
363
+
364
+ try {
365
+ await service.processPage(mockPage);
366
+ fail('Should have thrown an error');
367
+ } catch (err) {
368
+ expect(err).toBeInstanceOf(DyFM_Error);
369
+ expect((err as DyFM_Error)._errorCode).toContain('DCH-CSB-PP0');
370
+ }
371
+ });
372
+
373
+ it('| should delete old chunks when new page has fewer chunks', async () => {
374
+ const mockPage: DyNTS_DAI_DocPage = {
375
+ _id: 'page-123',
376
+ name: 'Test Page',
377
+ content: '# Test\n\nContent here',
378
+ chunks: [],
379
+ documentId: 'doc-123',
380
+ externalDocumentId: 'ext-doc-123',
381
+ externalPageId: 'ext-page-123',
382
+ } as any;
383
+
384
+ const mockNewChunk: DyNTS_DAI_DocChunk = {
385
+ _id: 'chunk-1',
386
+ chunkContent: 'New content',
387
+ chunkIndex: 0,
388
+ } as any;
389
+
390
+ const mockOldChunk1: DyNTS_DAI_DocChunk = {
391
+ _id: 'chunk-1',
392
+ chunkContent: 'Old content',
393
+ chunkIndex: 0,
394
+ } as any;
395
+
396
+ const mockOldChunk2: DyNTS_DAI_DocChunk = {
397
+ _id: 'chunk-2',
398
+ chunkContent: 'Old content 2',
399
+ chunkIndex: 1,
400
+ } as any;
401
+
402
+ spyOn(service, 'chunkPage').and.returnValue(Promise.resolve([mockNewChunk]));
403
+ spyOn(service, 'findDataList').and.returnValue(Promise.resolve([mockOldChunk1, mockOldChunk2]));
404
+ spyOn(service, 'compareChunk').and.returnValue(Promise.resolve({
405
+ result: DyNTS_DAI_CompareResult_Type.equal,
406
+ newChunk: mockNewChunk,
407
+ oldChunk: mockOldChunk1,
408
+ }));
409
+ spyOn(service, 'deleteData').and.returnValue(Promise.resolve());
410
+
411
+ const result = await service.processPage(mockPage);
412
+
413
+ expect(service.deleteData).toHaveBeenCalledWith('chunk-2');
414
+ expect(result.some(r => r.result === DyNTS_DAI_CompareResult_Type.deleted)).toBeTrue();
415
+ });
416
+ });
417
+ });
418
+