emberflow 1.3.46 → 1.3.47
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/lib/index-utils.d.ts +9 -2
- package/lib/index-utils.js +156 -7
- package/lib/index-utils.js.map +1 -1
- package/lib/index.d.ts +9 -4
- package/lib/index.js +23 -5
- package/lib/index.js.map +1 -1
- package/lib/logics/view-logics.d.ts +2 -2
- package/lib/logics/view-logics.js +2 -4
- package/lib/logics/view-logics.js.map +1 -1
- package/lib/sample-custom/db-structure.d.ts +10 -1
- package/lib/sample-custom/db-structure.js +9 -0
- package/lib/sample-custom/db-structure.js.map +1 -1
- package/lib/tests/index-utils.test.js +538 -43
- package/lib/tests/index-utils.test.js.map +1 -1
- package/lib/tests/index.test.js +8 -8
- package/lib/tests/index.test.js.map +1 -1
- package/lib/tests/logics/view-logics.test.js +40 -40
- package/lib/tests/logics/view-logics.test.js.map +1 -1
- package/lib/tests/utils/distribution.test.js +19 -27
- package/lib/tests/utils/distribution.test.js.map +1 -1
- package/lib/tests/utils/forms.test.js +14 -18
- package/lib/tests/utils/forms.test.js.map +1 -1
- package/lib/tests/utils/paths.test.js +4 -0
- package/lib/tests/utils/paths.test.js.map +1 -1
- package/lib/tests/utils/pubsub.test.js +58 -20
- package/lib/tests/utils/pubsub.test.js.map +1 -1
- package/lib/types.d.ts +6 -3
- package/lib/utils/distribution.js +2 -4
- package/lib/utils/distribution.js.map +1 -1
- package/lib/utils/forms.js +2 -3
- package/lib/utils/forms.js.map +1 -1
- package/lib/utils/pubsub.d.ts +1 -0
- package/lib/utils/pubsub.js +15 -3
- package/lib/utils/pubsub.js.map +1 -1
- package/package.json +1 -1
- package/src/sample-custom/db-structure.ts +9 -0
|
@@ -24,7 +24,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
26
|
const admin = __importStar(require("firebase-admin"));
|
|
27
|
-
const
|
|
27
|
+
const indexUtils = __importStar(require("../index-utils"));
|
|
28
28
|
const firebase_admin_1 = require("firebase-admin");
|
|
29
29
|
const index_1 = require("../index");
|
|
30
30
|
const db_structure_1 = require("../sample-custom/db-structure");
|
|
@@ -35,6 +35,10 @@ const paths_1 = require("../utils/paths");
|
|
|
35
35
|
const batch_1 = require("../utils/batch");
|
|
36
36
|
const distribution = __importStar(require("../utils/distribution"));
|
|
37
37
|
const forms = __importStar(require("../utils/forms"));
|
|
38
|
+
const indexutils = __importStar(require("../index-utils"));
|
|
39
|
+
const pubsub = __importStar(require("../utils/pubsub"));
|
|
40
|
+
const misc = __importStar(require("../utils/misc"));
|
|
41
|
+
const index_utils_1 = require("../index-utils");
|
|
38
42
|
jest.spyOn(console, "log").mockImplementation();
|
|
39
43
|
jest.spyOn(console, "info").mockImplementation();
|
|
40
44
|
const projectConfig = {
|
|
@@ -84,7 +88,7 @@ describe("distributeDoc", () => {
|
|
|
84
88
|
priority: "normal",
|
|
85
89
|
dstPath: "/users/test-user-id/documents/test-doc-id",
|
|
86
90
|
};
|
|
87
|
-
await
|
|
91
|
+
await indexUtils.distributeDoc(logicResultDoc);
|
|
88
92
|
expect(admin.firestore().doc).toHaveBeenCalledTimes(1);
|
|
89
93
|
expect(admin.firestore().doc).toHaveBeenCalledWith("/users/test-user-id/documents/test-doc-id");
|
|
90
94
|
expect(docDeleteMock).toHaveBeenCalledTimes(1);
|
|
@@ -97,7 +101,7 @@ describe("distributeDoc", () => {
|
|
|
97
101
|
priority: "normal",
|
|
98
102
|
dstPath: "/users/test-user-id/documents/test-doc-id",
|
|
99
103
|
};
|
|
100
|
-
await
|
|
104
|
+
await indexUtils.distributeDoc(logicResultDoc, batch);
|
|
101
105
|
expect(admin.firestore().doc).toHaveBeenCalledTimes(1);
|
|
102
106
|
expect(admin.firestore().doc).toHaveBeenCalledWith("/users/test-user-id/documents/test-doc-id");
|
|
103
107
|
expect(batchDeleteSpy).toHaveBeenCalledTimes(1);
|
|
@@ -111,7 +115,7 @@ describe("distributeDoc", () => {
|
|
|
111
115
|
doc: { name: "test-doc-name-updated" },
|
|
112
116
|
};
|
|
113
117
|
const expectedData = Object.assign(Object.assign({}, logicResultDoc.doc), { "@id": "test-doc-id" });
|
|
114
|
-
await
|
|
118
|
+
await indexUtils.distributeDoc(logicResultDoc);
|
|
115
119
|
expect(admin.firestore().doc).toHaveBeenCalledTimes(1);
|
|
116
120
|
expect(admin.firestore().doc).toHaveBeenCalledWith("/users/test-user-id/documents/test-doc-id");
|
|
117
121
|
expect(docSetMock).toHaveBeenCalledTimes(1);
|
|
@@ -131,7 +135,7 @@ describe("distributeDoc", () => {
|
|
|
131
135
|
dstPath: "/users/test-user-id/documents/test-doc-id",
|
|
132
136
|
};
|
|
133
137
|
const expectedData = Object.assign(Object.assign({}, logicResultDoc.doc), { "@id": "test-doc-id" });
|
|
134
|
-
await
|
|
138
|
+
await indexUtils.distributeDoc(logicResultDoc);
|
|
135
139
|
expect(admin.firestore().doc).toHaveBeenCalledTimes(1);
|
|
136
140
|
expect(admin.firestore().doc).toHaveBeenCalledWith("/users/test-user-id/documents/test-doc-id");
|
|
137
141
|
expect(queueInstructionsSpy).toHaveBeenCalledTimes(1);
|
|
@@ -146,7 +150,7 @@ describe("distributeDoc", () => {
|
|
|
146
150
|
priority: "normal",
|
|
147
151
|
dstPath: "/users/test-user-id/documents/test-doc-id",
|
|
148
152
|
};
|
|
149
|
-
await
|
|
153
|
+
await indexUtils.distributeDoc(logicResultDoc, batch);
|
|
150
154
|
expect(admin.firestore().doc).toHaveBeenCalledTimes(1);
|
|
151
155
|
expect(admin.firestore().doc).toHaveBeenCalledWith("/users/test-user-id/documents/test-doc-id");
|
|
152
156
|
expect(batchSetSpy).toHaveBeenCalledTimes(1);
|
|
@@ -161,7 +165,7 @@ describe("distributeDoc", () => {
|
|
|
161
165
|
dstPath: "/users/test-user-id/documents/test-doc-id",
|
|
162
166
|
};
|
|
163
167
|
const formData = Object.assign({ "@docPath": logicResultDoc.dstPath, "@actionType": "create" }, logicResultDoc.doc);
|
|
164
|
-
await
|
|
168
|
+
await indexUtils.distributeDoc(logicResultDoc, batch);
|
|
165
169
|
expect(admin.firestore().doc).toHaveBeenCalledTimes(1);
|
|
166
170
|
expect(admin.firestore().doc).toHaveBeenCalledWith("/users/test-user-id/documents/test-doc-id");
|
|
167
171
|
expect(queueSubmitFormSpy).toHaveBeenCalledTimes(1);
|
|
@@ -187,6 +191,7 @@ describe("distribute", () => {
|
|
|
187
191
|
doc: jest.fn(() => dbDoc),
|
|
188
192
|
});
|
|
189
193
|
queueInstructionsSpy = jest.spyOn(distribution, "queueInstructions").mockResolvedValue();
|
|
194
|
+
jest.spyOn(pubsub, "createPubSubTopics").mockResolvedValue();
|
|
190
195
|
});
|
|
191
196
|
afterEach(() => {
|
|
192
197
|
dbSpy.mockRestore();
|
|
@@ -211,7 +216,7 @@ describe("distribute", () => {
|
|
|
211
216
|
}],
|
|
212
217
|
]]);
|
|
213
218
|
(0, index_1.initializeEmberFlow)(projectConfig, admin, db_structure_1.dbStructure, db_structure_1.Entity, security_1.securityConfig, validators_1.validatorConfig, []);
|
|
214
|
-
await
|
|
219
|
+
await indexUtils.distribute(userDocsByDstPath);
|
|
215
220
|
expect(admin.firestore().doc).toHaveBeenCalledTimes(1);
|
|
216
221
|
expect(admin.firestore().doc).toHaveBeenCalledWith("/users/test-user-id/documents/test-doc-id");
|
|
217
222
|
expect(queueInstructionsSpy).toHaveBeenCalledTimes(1);
|
|
@@ -237,7 +242,7 @@ describe("distribute", () => {
|
|
|
237
242
|
dstPath: "/users/test-user-id/documents/test-doc-id",
|
|
238
243
|
}],
|
|
239
244
|
]]);
|
|
240
|
-
await
|
|
245
|
+
await indexUtils.distribute(userDocsByDstPath);
|
|
241
246
|
expect(admin.firestore().doc).toHaveBeenCalledTimes(1);
|
|
242
247
|
expect(admin.firestore().doc).toHaveBeenCalledWith("/users/test-user-id/documents/test-doc-id");
|
|
243
248
|
expect(batchDeleteSpy).toHaveBeenCalledTimes(1);
|
|
@@ -270,7 +275,7 @@ describe("distributeLater", () => {
|
|
|
270
275
|
["/users/test-user-id/documents/doc1", [doc1]],
|
|
271
276
|
["/users/test-user-id/documents/doc2", [doc2]],
|
|
272
277
|
]);
|
|
273
|
-
await
|
|
278
|
+
await indexUtils.distributeLater(usersDocsByDstPath);
|
|
274
279
|
expect(queueForDistributionLaterSpy).toHaveBeenCalledTimes(1);
|
|
275
280
|
expect(queueForDistributionLaterSpy).toHaveBeenCalledWith(doc1, doc2);
|
|
276
281
|
});
|
|
@@ -283,7 +288,7 @@ describe("validateForm", () => {
|
|
|
283
288
|
email: "johndoe@example.com",
|
|
284
289
|
password: "abc123",
|
|
285
290
|
};
|
|
286
|
-
const [hasValidationError, validationResult] = await
|
|
291
|
+
const [hasValidationError, validationResult] = await indexUtils.validateForm(entity, document);
|
|
287
292
|
expect(hasValidationError).toBe(false);
|
|
288
293
|
expect(validationResult).toEqual({});
|
|
289
294
|
});
|
|
@@ -294,7 +299,7 @@ describe("validateForm", () => {
|
|
|
294
299
|
email: "johndoe@example.com",
|
|
295
300
|
password: "abc",
|
|
296
301
|
};
|
|
297
|
-
const [hasValidationError, validationResult] = await
|
|
302
|
+
const [hasValidationError, validationResult] = await indexUtils.validateForm(entity, document);
|
|
298
303
|
expect(hasValidationError).toBe(true);
|
|
299
304
|
expect(validationResult).toEqual({ name: ["Name is required"] });
|
|
300
305
|
});
|
|
@@ -302,7 +307,7 @@ describe("validateForm", () => {
|
|
|
302
307
|
describe("getFormModifiedFields", () => {
|
|
303
308
|
it("should return an empty object when there are no form fields", () => {
|
|
304
309
|
const document = { name: "John Doe", age: 30 };
|
|
305
|
-
const modifiedFields =
|
|
310
|
+
const modifiedFields = indexUtils.getFormModifiedFields({}, document);
|
|
306
311
|
expect(modifiedFields).toEqual({});
|
|
307
312
|
});
|
|
308
313
|
it("should return an array of modified form fields", () => {
|
|
@@ -310,7 +315,7 @@ describe("getFormModifiedFields", () => {
|
|
|
310
315
|
"name": "John Doe",
|
|
311
316
|
"age": 30,
|
|
312
317
|
};
|
|
313
|
-
const modifiedFields =
|
|
318
|
+
const modifiedFields = indexUtils.getFormModifiedFields({
|
|
314
319
|
"name": "Jane Doe",
|
|
315
320
|
"address": "123 Main St",
|
|
316
321
|
"@status": "submit",
|
|
@@ -327,7 +332,7 @@ describe("delayFormSubmissionAndCheckIfCancelled", () => {
|
|
|
327
332
|
val: () => ({ "@form": { "@status": "delay" } }),
|
|
328
333
|
}),
|
|
329
334
|
};
|
|
330
|
-
const cancelFormSubmission = await
|
|
335
|
+
const cancelFormSubmission = await indexUtils.delayFormSubmissionAndCheckIfCancelled(delay, formResponseRef);
|
|
331
336
|
expect(cancelFormSubmission).toBe(false);
|
|
332
337
|
expect(formResponseRef.update).toHaveBeenCalledTimes(1);
|
|
333
338
|
expect(formResponseRef.update).toHaveBeenCalledWith({ "@status": "delay" });
|
|
@@ -342,7 +347,7 @@ describe("delayFormSubmissionAndCheckIfCancelled", () => {
|
|
|
342
347
|
val: () => ({ "@status": "cancel" }),
|
|
343
348
|
}),
|
|
344
349
|
};
|
|
345
|
-
const cancelFormSubmission = await
|
|
350
|
+
const cancelFormSubmission = await indexUtils.delayFormSubmissionAndCheckIfCancelled(delay, formResponseRef);
|
|
346
351
|
expect(cancelFormSubmission).toBe(true);
|
|
347
352
|
expect(formResponseRef.update).toHaveBeenCalledTimes(1);
|
|
348
353
|
expect(formResponseRef.update).toHaveBeenCalledWith({ "@status": "delay" });
|
|
@@ -366,7 +371,7 @@ describe("runBusinessLogics", () => {
|
|
|
366
371
|
docId: "document123",
|
|
367
372
|
formId: "form123",
|
|
368
373
|
docPath: "users/user123",
|
|
369
|
-
entity:
|
|
374
|
+
entity: entity,
|
|
370
375
|
},
|
|
371
376
|
actionType,
|
|
372
377
|
document: {
|
|
@@ -383,11 +388,16 @@ describe("runBusinessLogics", () => {
|
|
|
383
388
|
let logicFn2;
|
|
384
389
|
let logicFn3;
|
|
385
390
|
let dbSpy;
|
|
391
|
+
let simulateSubmitFormSpy;
|
|
392
|
+
let updateLogicMetricsSpy;
|
|
393
|
+
let actionRef;
|
|
386
394
|
beforeEach(() => {
|
|
387
395
|
distributeFn = jest.fn();
|
|
388
396
|
logicFn1 = jest.fn().mockResolvedValue({ status: "finished" });
|
|
389
397
|
logicFn2 = jest.fn().mockResolvedValue({ status: "finished" });
|
|
390
398
|
logicFn3 = jest.fn().mockResolvedValue({ status: "error", message: "Error message" });
|
|
399
|
+
simulateSubmitFormSpy = jest.spyOn(indexUtils._mockable, "simulateSubmitForm").mockResolvedValue();
|
|
400
|
+
updateLogicMetricsSpy = jest.spyOn(indexUtils._mockable, "updateLogicMetrics").mockResolvedValue();
|
|
391
401
|
const dbDoc = {
|
|
392
402
|
get: jest.fn().mockResolvedValue({
|
|
393
403
|
data: jest.fn().mockReturnValue({
|
|
@@ -396,6 +406,17 @@ describe("runBusinessLogics", () => {
|
|
|
396
406
|
}),
|
|
397
407
|
};
|
|
398
408
|
dbSpy = jest.spyOn(admin.firestore(), "doc").mockReturnValue(dbDoc);
|
|
409
|
+
const setActionMock = jest.fn().mockResolvedValue({
|
|
410
|
+
update: jest.fn(),
|
|
411
|
+
});
|
|
412
|
+
const updateActionMock = jest.fn().mockResolvedValue({
|
|
413
|
+
update: jest.fn(),
|
|
414
|
+
});
|
|
415
|
+
actionRef = {
|
|
416
|
+
set: setActionMock,
|
|
417
|
+
update: updateActionMock,
|
|
418
|
+
};
|
|
419
|
+
jest.spyOn(index_1._mockable, "initActionRef").mockReturnValue(actionRef);
|
|
399
420
|
});
|
|
400
421
|
afterEach(() => {
|
|
401
422
|
// Cleanup
|
|
@@ -404,6 +425,8 @@ describe("runBusinessLogics", () => {
|
|
|
404
425
|
logicFn3.mockRestore();
|
|
405
426
|
distributeFn.mockRestore();
|
|
406
427
|
dbSpy.mockRestore();
|
|
428
|
+
simulateSubmitFormSpy.mockRestore();
|
|
429
|
+
updateLogicMetricsSpy.mockRestore();
|
|
407
430
|
});
|
|
408
431
|
it("should call all matching logics and pass their results to distributeFn", async () => {
|
|
409
432
|
const logics = [
|
|
@@ -430,13 +453,12 @@ describe("runBusinessLogics", () => {
|
|
|
430
453
|
},
|
|
431
454
|
];
|
|
432
455
|
(0, index_1.initializeEmberFlow)(projectConfig, admin, db_structure_1.dbStructure, db_structure_1.Entity, security_1.securityConfig, validators_1.validatorConfig, logics);
|
|
433
|
-
const runStatus = await
|
|
456
|
+
const runStatus = await indexUtils.runBusinessLogics(actionRef, action, distributeFn);
|
|
434
457
|
expect(logicFn1).toHaveBeenCalledWith(action, undefined);
|
|
435
458
|
expect(logicFn2).toHaveBeenCalledWith(action, undefined);
|
|
436
459
|
expect(logicFn3).not.toHaveBeenCalled();
|
|
437
460
|
expect(distributeFn).toHaveBeenCalledTimes(1);
|
|
438
|
-
expect(distributeFn).toHaveBeenCalledWith([
|
|
439
|
-
expect.objectContaining({
|
|
461
|
+
expect(distributeFn).toHaveBeenCalledWith(actionRef, [expect.objectContaining({
|
|
440
462
|
status: "finished",
|
|
441
463
|
execTime: expect.any(Number),
|
|
442
464
|
timeFinished: expect.any(Timestamp),
|
|
@@ -445,9 +467,10 @@ describe("runBusinessLogics", () => {
|
|
|
445
467
|
status: "finished",
|
|
446
468
|
execTime: expect.any(Number),
|
|
447
469
|
timeFinished: expect.any(Timestamp),
|
|
448
|
-
}),
|
|
449
|
-
], 0);
|
|
470
|
+
})], 0);
|
|
450
471
|
expect(runStatus).toEqual("done");
|
|
472
|
+
expect(updateLogicMetricsSpy).toHaveBeenCalledTimes(1);
|
|
473
|
+
expect(simulateSubmitFormSpy).toHaveBeenCalledTimes(1);
|
|
451
474
|
});
|
|
452
475
|
it("should recall logic when it returns \"partial-result\" status", async () => {
|
|
453
476
|
logicFn2.mockResolvedValueOnce({ status: "partial-result", nextPage: {} });
|
|
@@ -468,12 +491,12 @@ describe("runBusinessLogics", () => {
|
|
|
468
491
|
},
|
|
469
492
|
];
|
|
470
493
|
(0, index_1.initializeEmberFlow)(projectConfig, admin, db_structure_1.dbStructure, db_structure_1.Entity, security_1.securityConfig, validators_1.validatorConfig, logics);
|
|
471
|
-
const runStatus = await
|
|
494
|
+
const runStatus = await indexUtils.runBusinessLogics(actionRef, action, distributeFn);
|
|
472
495
|
expect(logicFn1).toHaveBeenCalledWith(action, undefined);
|
|
473
496
|
expect(logicFn2).toHaveBeenCalledWith(action, undefined);
|
|
474
497
|
expect(distributeFn).toHaveBeenCalledTimes(2);
|
|
475
|
-
expect(distributeFn.mock.calls[0]).toEqual([
|
|
476
|
-
|
|
498
|
+
expect(distributeFn.mock.calls[0]).toEqual([actionRef,
|
|
499
|
+
[expect.objectContaining({
|
|
477
500
|
status: "partial-result",
|
|
478
501
|
nextPage: {},
|
|
479
502
|
execTime: expect.any(Number),
|
|
@@ -483,16 +506,14 @@ describe("runBusinessLogics", () => {
|
|
|
483
506
|
status: "finished",
|
|
484
507
|
execTime: expect.any(Number),
|
|
485
508
|
timeFinished: expect.any(Timestamp),
|
|
486
|
-
}),
|
|
487
|
-
], 0]);
|
|
509
|
+
})], 0]);
|
|
488
510
|
expect(logicFn2).toHaveBeenCalledWith(action, {});
|
|
489
|
-
expect(distributeFn.mock.calls[1]).toEqual([
|
|
490
|
-
|
|
511
|
+
expect(distributeFn.mock.calls[1]).toEqual([actionRef,
|
|
512
|
+
[expect.objectContaining({
|
|
491
513
|
status: "finished",
|
|
492
514
|
execTime: expect.any(Number),
|
|
493
515
|
timeFinished: expect.any(Timestamp),
|
|
494
|
-
}),
|
|
495
|
-
], 1]);
|
|
516
|
+
})], 1]);
|
|
496
517
|
expect(runStatus).toEqual("done");
|
|
497
518
|
});
|
|
498
519
|
it("should not call any logic when no matching logics are found but distributeFn should still be " +
|
|
@@ -521,12 +542,12 @@ describe("runBusinessLogics", () => {
|
|
|
521
542
|
},
|
|
522
543
|
];
|
|
523
544
|
(0, index_1.initializeEmberFlow)(projectConfig, admin, db_structure_1.dbStructure, db_structure_1.Entity, security_1.securityConfig, validators_1.validatorConfig, logics);
|
|
524
|
-
const runStatus = await
|
|
545
|
+
const runStatus = await indexUtils.runBusinessLogics(actionRef, action, distributeFn);
|
|
525
546
|
expect(logicFn1).not.toHaveBeenCalled();
|
|
526
547
|
expect(logicFn2).not.toHaveBeenCalled();
|
|
527
548
|
expect(logicFn3).not.toHaveBeenCalled();
|
|
528
549
|
expect(distributeFn).toHaveBeenCalledTimes(1);
|
|
529
|
-
expect(distributeFn).toHaveBeenCalledWith([], 0);
|
|
550
|
+
expect(distributeFn).toHaveBeenCalledWith(actionRef, [], 0);
|
|
530
551
|
expect(runStatus).toEqual("no-matching-logics");
|
|
531
552
|
});
|
|
532
553
|
it("should recall logic when it returns \"partial-result\" status indefinitely up to the config maxLogicResultPages", async () => {
|
|
@@ -548,7 +569,7 @@ describe("runBusinessLogics", () => {
|
|
|
548
569
|
},
|
|
549
570
|
];
|
|
550
571
|
(0, index_1.initializeEmberFlow)(projectConfig, admin, db_structure_1.dbStructure, db_structure_1.Entity, security_1.securityConfig, validators_1.validatorConfig, logics);
|
|
551
|
-
const runStatus = await
|
|
572
|
+
const runStatus = await indexUtils.runBusinessLogics(actionRef, action, distributeFn);
|
|
552
573
|
expect(logicFn1).toHaveBeenCalledWith(action, undefined);
|
|
553
574
|
expect(logicFn2).toHaveBeenCalledWith(action, undefined);
|
|
554
575
|
expect(logicFn1).toHaveBeenCalledTimes(1);
|
|
@@ -583,7 +604,7 @@ describe("runBusinessLogics", () => {
|
|
|
583
604
|
},
|
|
584
605
|
];
|
|
585
606
|
(0, index_1.initializeEmberFlow)(projectConfig, admin, db_structure_1.dbStructure, db_structure_1.Entity, security_1.securityConfig, validators_1.validatorConfig, logics);
|
|
586
|
-
const runStatus = await
|
|
607
|
+
const runStatus = await indexUtils.runBusinessLogics(actionRef, action, distributeFn);
|
|
587
608
|
expect(logicFn1).not.toHaveBeenCalled();
|
|
588
609
|
expect(logicFn2).toHaveBeenCalledWith(action, undefined);
|
|
589
610
|
expect(logicFn3).toHaveBeenCalledWith(action, undefined);
|
|
@@ -593,6 +614,356 @@ describe("runBusinessLogics", () => {
|
|
|
593
614
|
expect(runStatus).toEqual("cancel-then-retry");
|
|
594
615
|
});
|
|
595
616
|
});
|
|
617
|
+
describe("simulateSubmitForm", () => {
|
|
618
|
+
const eventContext = {
|
|
619
|
+
id: "test-event-id",
|
|
620
|
+
uid: "test-user-id",
|
|
621
|
+
docPath: "servers/test-doc-id",
|
|
622
|
+
docId: "test-doc-id",
|
|
623
|
+
formId: "test-form-id",
|
|
624
|
+
entity: "servers",
|
|
625
|
+
};
|
|
626
|
+
const user = {
|
|
627
|
+
"@id": "test-user-id",
|
|
628
|
+
"username": "Topic Creator",
|
|
629
|
+
"avatarUrl": "Avatar URL",
|
|
630
|
+
"firstName": "Topic",
|
|
631
|
+
"lastName": "Creator",
|
|
632
|
+
};
|
|
633
|
+
const action = {
|
|
634
|
+
actionType: "create",
|
|
635
|
+
eventContext: eventContext,
|
|
636
|
+
user: user,
|
|
637
|
+
document: {},
|
|
638
|
+
status: "new",
|
|
639
|
+
timeCreated: admin.firestore.Timestamp.now(),
|
|
640
|
+
modifiedFields: {},
|
|
641
|
+
};
|
|
642
|
+
const distributeFn = jest.fn();
|
|
643
|
+
let runBusinessLogicsSpy;
|
|
644
|
+
let dataMock;
|
|
645
|
+
let docMock;
|
|
646
|
+
let now;
|
|
647
|
+
beforeEach(() => {
|
|
648
|
+
jest.spyOn(console, "debug").mockImplementation();
|
|
649
|
+
jest.spyOn(console, "warn").mockImplementation();
|
|
650
|
+
dataMock = jest.fn().mockReturnValue({});
|
|
651
|
+
const getMock = {
|
|
652
|
+
data: dataMock,
|
|
653
|
+
};
|
|
654
|
+
docMock = {
|
|
655
|
+
set: jest.fn(),
|
|
656
|
+
get: jest.fn().mockResolvedValue(getMock),
|
|
657
|
+
collection: jest.fn(() => collectionMock),
|
|
658
|
+
};
|
|
659
|
+
const collectionMock = {
|
|
660
|
+
doc: jest.fn(() => docMock),
|
|
661
|
+
};
|
|
662
|
+
jest.spyOn(admin.firestore(), "doc").mockReturnValue(docMock);
|
|
663
|
+
jest.spyOn(admin.firestore(), "collection").mockReturnValue(collectionMock);
|
|
664
|
+
now = Timestamp.now();
|
|
665
|
+
jest.spyOn(indexUtils._mockable, "createNowTimestamp").mockReturnValue(now);
|
|
666
|
+
runBusinessLogicsSpy =
|
|
667
|
+
jest.spyOn(indexutils, "runBusinessLogics").mockResolvedValue("done");
|
|
668
|
+
});
|
|
669
|
+
afterEach(() => {
|
|
670
|
+
jest.restoreAllMocks();
|
|
671
|
+
});
|
|
672
|
+
it("should skip when there is no logic result doc with 'simulate-submit-form' action", async () => {
|
|
673
|
+
await indexUtils._mockable.simulateSubmitForm([], action, distributeFn);
|
|
674
|
+
expect(console.debug).toHaveBeenCalledTimes(1);
|
|
675
|
+
expect(console.debug).toHaveBeenCalledWith("Simulating submit form: ", 0);
|
|
676
|
+
expect(runBusinessLogicsSpy).not.toHaveBeenCalled();
|
|
677
|
+
});
|
|
678
|
+
it("should skip when entity is undefined", async () => {
|
|
679
|
+
const logicResults = [];
|
|
680
|
+
const logicResultDoc = {
|
|
681
|
+
action: "simulate-submit-form",
|
|
682
|
+
dstPath: "no-entity/sample-doc-id",
|
|
683
|
+
doc: {
|
|
684
|
+
"@id": "no-entity/sample-doc-id",
|
|
685
|
+
},
|
|
686
|
+
};
|
|
687
|
+
const logicResult = {
|
|
688
|
+
name: "sampleLogicResult",
|
|
689
|
+
status: "finished",
|
|
690
|
+
documents: [logicResultDoc],
|
|
691
|
+
};
|
|
692
|
+
logicResults.push(logicResult);
|
|
693
|
+
await indexUtils._mockable.simulateSubmitForm(logicResults, action, distributeFn);
|
|
694
|
+
expect(console.warn).toHaveBeenCalledTimes(1);
|
|
695
|
+
expect(console.warn).toHaveBeenCalledWith("No matching entity found for logic no-entity/sample-doc-id. Skipping");
|
|
696
|
+
expect(runBusinessLogicsSpy).not.toHaveBeenCalled();
|
|
697
|
+
});
|
|
698
|
+
it("should skip when logic result doc is undefined", async () => {
|
|
699
|
+
const logicResults = [];
|
|
700
|
+
const logicResultDoc = {
|
|
701
|
+
action: "simulate-submit-form",
|
|
702
|
+
dstPath: "servers/sample-server-id",
|
|
703
|
+
};
|
|
704
|
+
const logicResult = {
|
|
705
|
+
name: "sampleLogicResult",
|
|
706
|
+
status: "finished",
|
|
707
|
+
documents: [logicResultDoc],
|
|
708
|
+
};
|
|
709
|
+
logicResults.push(logicResult);
|
|
710
|
+
await indexUtils._mockable.simulateSubmitForm(logicResults, action, distributeFn);
|
|
711
|
+
expect(console.warn).toHaveBeenCalledTimes(1);
|
|
712
|
+
expect(console.warn).toHaveBeenCalledWith("LogicResultDoc.doc should not be undefined. Skipping");
|
|
713
|
+
expect(runBusinessLogicsSpy).not.toHaveBeenCalled();
|
|
714
|
+
});
|
|
715
|
+
it("should skip when @actionType is undefined", async () => {
|
|
716
|
+
const logicResults = [];
|
|
717
|
+
const logicResultDoc = {
|
|
718
|
+
action: "simulate-submit-form",
|
|
719
|
+
dstPath: "servers/sample-server-id",
|
|
720
|
+
doc: { "@id": "sample-server-id" },
|
|
721
|
+
};
|
|
722
|
+
const logicResult = {
|
|
723
|
+
name: "sampleLogicResult",
|
|
724
|
+
status: "finished",
|
|
725
|
+
documents: [logicResultDoc],
|
|
726
|
+
};
|
|
727
|
+
logicResults.push(logicResult);
|
|
728
|
+
await indexUtils._mockable.simulateSubmitForm(logicResults, action, distributeFn);
|
|
729
|
+
expect(console.warn).toHaveBeenCalledTimes(1);
|
|
730
|
+
expect(console.warn).toHaveBeenCalledWith("No @actionType found. Skipping");
|
|
731
|
+
expect(runBusinessLogicsSpy).not.toHaveBeenCalled();
|
|
732
|
+
});
|
|
733
|
+
it("should skip when submitFormAs data is undefined", async () => {
|
|
734
|
+
dataMock.mockReturnValueOnce(undefined);
|
|
735
|
+
const logicResults = [];
|
|
736
|
+
const logicResultDoc = {
|
|
737
|
+
action: "simulate-submit-form",
|
|
738
|
+
dstPath: "servers/sample-server-id",
|
|
739
|
+
doc: {
|
|
740
|
+
"@actionType": "create",
|
|
741
|
+
"@submitFormAs": "test-user-id",
|
|
742
|
+
},
|
|
743
|
+
};
|
|
744
|
+
const logicResult = {
|
|
745
|
+
name: "sampleLogicResult",
|
|
746
|
+
status: "finished",
|
|
747
|
+
documents: [logicResultDoc],
|
|
748
|
+
};
|
|
749
|
+
logicResults.push(logicResult);
|
|
750
|
+
await indexUtils._mockable.simulateSubmitForm(logicResults, action, distributeFn);
|
|
751
|
+
expect(console.warn).toHaveBeenCalledTimes(1);
|
|
752
|
+
expect(console.warn).toHaveBeenCalledWith("User test-user-id not found. Skipping");
|
|
753
|
+
expect(runBusinessLogicsSpy).not.toHaveBeenCalled();
|
|
754
|
+
});
|
|
755
|
+
it("should simulate submit form correctly when submitFormAs is defined", async () => {
|
|
756
|
+
dataMock.mockReturnValueOnce({ "@id": "test-user-id" });
|
|
757
|
+
const logicResults = [];
|
|
758
|
+
const logicResultDoc = {
|
|
759
|
+
action: "simulate-submit-form",
|
|
760
|
+
dstPath: "servers/sample-server-id",
|
|
761
|
+
doc: {
|
|
762
|
+
"@actionType": "create",
|
|
763
|
+
"@submitFormAs": "test-user-id",
|
|
764
|
+
"name": "sample-server-name",
|
|
765
|
+
"createdAt": now,
|
|
766
|
+
},
|
|
767
|
+
};
|
|
768
|
+
const logicResult = {
|
|
769
|
+
name: "sampleLogicResult",
|
|
770
|
+
status: "finished",
|
|
771
|
+
documents: [logicResultDoc],
|
|
772
|
+
};
|
|
773
|
+
logicResults.push(logicResult);
|
|
774
|
+
const expectedEventContext = {
|
|
775
|
+
id: action.eventContext.id + "-1",
|
|
776
|
+
uid: action.eventContext.uid,
|
|
777
|
+
formId: action.eventContext.formId + "-1",
|
|
778
|
+
docId: "sample-server-id",
|
|
779
|
+
docPath: logicResultDoc.dstPath,
|
|
780
|
+
entity: "server",
|
|
781
|
+
};
|
|
782
|
+
const expectedAction = {
|
|
783
|
+
eventContext: expectedEventContext,
|
|
784
|
+
actionType: "create",
|
|
785
|
+
document: {},
|
|
786
|
+
modifiedFields: {
|
|
787
|
+
"name": "sample-server-name",
|
|
788
|
+
"createdAt": now,
|
|
789
|
+
},
|
|
790
|
+
user: { "@id": "test-user-id" },
|
|
791
|
+
status: "new",
|
|
792
|
+
timeCreated: now,
|
|
793
|
+
};
|
|
794
|
+
await indexUtils._mockable.simulateSubmitForm(logicResults, action, distributeFn);
|
|
795
|
+
expect(docMock.set).toHaveBeenCalledTimes(1);
|
|
796
|
+
expect(docMock.set).toHaveBeenCalledWith(expectedAction);
|
|
797
|
+
expect(runBusinessLogicsSpy).toHaveBeenCalledTimes(1);
|
|
798
|
+
expect(runBusinessLogicsSpy).toHaveBeenCalledWith(docMock, expectedAction, distributeFn);
|
|
799
|
+
});
|
|
800
|
+
it("should simulate submit form correctly when submitFormAs is undefined", async () => {
|
|
801
|
+
const logicResults = [];
|
|
802
|
+
const logicResultDoc = {
|
|
803
|
+
action: "simulate-submit-form",
|
|
804
|
+
dstPath: "servers/sample-server-id",
|
|
805
|
+
doc: {
|
|
806
|
+
"@actionType": "create",
|
|
807
|
+
"name": "sample-server-name",
|
|
808
|
+
"createdAt": now,
|
|
809
|
+
},
|
|
810
|
+
};
|
|
811
|
+
const logicResult = {
|
|
812
|
+
name: "sampleLogicResult",
|
|
813
|
+
status: "finished",
|
|
814
|
+
documents: [logicResultDoc],
|
|
815
|
+
};
|
|
816
|
+
logicResults.push(logicResult);
|
|
817
|
+
const expectedEventContext = {
|
|
818
|
+
id: action.eventContext.id + "-1",
|
|
819
|
+
uid: action.eventContext.uid,
|
|
820
|
+
formId: action.eventContext.formId + "-1",
|
|
821
|
+
docId: "sample-server-id",
|
|
822
|
+
docPath: logicResultDoc.dstPath,
|
|
823
|
+
entity: "server",
|
|
824
|
+
};
|
|
825
|
+
const expectedAction = {
|
|
826
|
+
eventContext: expectedEventContext,
|
|
827
|
+
actionType: "create",
|
|
828
|
+
document: {},
|
|
829
|
+
modifiedFields: {
|
|
830
|
+
"name": "sample-server-name",
|
|
831
|
+
"createdAt": now,
|
|
832
|
+
},
|
|
833
|
+
user: user,
|
|
834
|
+
status: "new",
|
|
835
|
+
timeCreated: now,
|
|
836
|
+
};
|
|
837
|
+
await indexUtils._mockable.simulateSubmitForm(logicResults, action, distributeFn);
|
|
838
|
+
expect(docMock.set).toHaveBeenCalledTimes(1);
|
|
839
|
+
expect(docMock.set).toHaveBeenCalledWith(expectedAction);
|
|
840
|
+
expect(runBusinessLogicsSpy).toHaveBeenCalledTimes(1);
|
|
841
|
+
expect(runBusinessLogicsSpy).toHaveBeenCalledWith(docMock, expectedAction, distributeFn);
|
|
842
|
+
});
|
|
843
|
+
it("should simulate submit form correctly with multiple logic result docs", async () => {
|
|
844
|
+
const logicResults = [];
|
|
845
|
+
const logicResultDoc1 = {
|
|
846
|
+
action: "simulate-submit-form",
|
|
847
|
+
dstPath: "servers/sample-server-id",
|
|
848
|
+
doc: {
|
|
849
|
+
"@actionType": "create",
|
|
850
|
+
"name": "sample-server-name",
|
|
851
|
+
"createdAt": now,
|
|
852
|
+
},
|
|
853
|
+
};
|
|
854
|
+
const logicResultDoc2 = {
|
|
855
|
+
action: "merge",
|
|
856
|
+
dstPath: "servers/merge-server-id",
|
|
857
|
+
doc: {
|
|
858
|
+
"@actionType": "update",
|
|
859
|
+
"name": "sample-server-name",
|
|
860
|
+
},
|
|
861
|
+
};
|
|
862
|
+
const logicResultDoc3 = {
|
|
863
|
+
action: "simulate-submit-form",
|
|
864
|
+
dstPath: "users/sample-user-id",
|
|
865
|
+
doc: {
|
|
866
|
+
"@actionType": "create",
|
|
867
|
+
"name": "sample-user-name",
|
|
868
|
+
},
|
|
869
|
+
};
|
|
870
|
+
const logicResult1 = {
|
|
871
|
+
name: "serverLogicResult",
|
|
872
|
+
status: "finished",
|
|
873
|
+
documents: [logicResultDoc1, logicResultDoc2],
|
|
874
|
+
};
|
|
875
|
+
const logicResult2 = {
|
|
876
|
+
name: "userLogicResult",
|
|
877
|
+
status: "finished",
|
|
878
|
+
documents: [logicResultDoc3],
|
|
879
|
+
};
|
|
880
|
+
logicResults.push(logicResult1);
|
|
881
|
+
logicResults.push(logicResult2);
|
|
882
|
+
const expectedServerEventContext = {
|
|
883
|
+
id: action.eventContext.id + "-1",
|
|
884
|
+
uid: action.eventContext.uid,
|
|
885
|
+
formId: action.eventContext.formId + "-1",
|
|
886
|
+
docId: "sample-server-id",
|
|
887
|
+
docPath: logicResultDoc1.dstPath,
|
|
888
|
+
entity: "server",
|
|
889
|
+
};
|
|
890
|
+
const expectedServerAction = {
|
|
891
|
+
eventContext: expectedServerEventContext,
|
|
892
|
+
actionType: "create",
|
|
893
|
+
document: {},
|
|
894
|
+
modifiedFields: {
|
|
895
|
+
"name": "sample-server-name",
|
|
896
|
+
"createdAt": now,
|
|
897
|
+
},
|
|
898
|
+
user: user,
|
|
899
|
+
status: "new",
|
|
900
|
+
timeCreated: now,
|
|
901
|
+
};
|
|
902
|
+
const expectedUserEventContext = {
|
|
903
|
+
id: action.eventContext.id + "-2",
|
|
904
|
+
uid: action.eventContext.uid,
|
|
905
|
+
formId: action.eventContext.formId + "-2",
|
|
906
|
+
docId: "sample-user-id",
|
|
907
|
+
docPath: logicResultDoc3.dstPath,
|
|
908
|
+
entity: "user",
|
|
909
|
+
};
|
|
910
|
+
const expectedUserAction = {
|
|
911
|
+
eventContext: expectedUserEventContext,
|
|
912
|
+
actionType: "create",
|
|
913
|
+
document: {},
|
|
914
|
+
modifiedFields: {
|
|
915
|
+
"name": "sample-user-name",
|
|
916
|
+
},
|
|
917
|
+
user: user,
|
|
918
|
+
status: "new",
|
|
919
|
+
timeCreated: now,
|
|
920
|
+
};
|
|
921
|
+
await indexUtils._mockable.simulateSubmitForm(logicResults, action, distributeFn);
|
|
922
|
+
expect(docMock.set).toHaveBeenCalledTimes(2);
|
|
923
|
+
expect(docMock.set).toHaveBeenNthCalledWith(1, expectedServerAction);
|
|
924
|
+
expect(docMock.set).toHaveBeenNthCalledWith(2, expectedUserAction);
|
|
925
|
+
expect(runBusinessLogicsSpy).toHaveBeenCalledTimes(2);
|
|
926
|
+
expect(runBusinessLogicsSpy).toHaveBeenNthCalledWith(1, docMock, expectedServerAction, distributeFn);
|
|
927
|
+
expect(runBusinessLogicsSpy).toHaveBeenNthCalledWith(2, docMock, expectedUserAction, distributeFn);
|
|
928
|
+
});
|
|
929
|
+
it("should skip when maximum retry count is reached", async () => {
|
|
930
|
+
runBusinessLogicsSpy.mockResolvedValueOnce("cancel-then-retry")
|
|
931
|
+
.mockResolvedValueOnce("cancel-then-retry")
|
|
932
|
+
.mockResolvedValueOnce("cancel-then-retry")
|
|
933
|
+
.mockResolvedValueOnce("cancel-then-retry")
|
|
934
|
+
.mockResolvedValueOnce("cancel-then-retry")
|
|
935
|
+
.mockResolvedValueOnce("cancel-then-retry");
|
|
936
|
+
const logicResults = [];
|
|
937
|
+
const doc = {
|
|
938
|
+
"@actionType": "create",
|
|
939
|
+
};
|
|
940
|
+
const logicResultDoc = {
|
|
941
|
+
action: "simulate-submit-form",
|
|
942
|
+
dstPath: "servers/sample-server-id",
|
|
943
|
+
doc: doc,
|
|
944
|
+
};
|
|
945
|
+
const logicResult = {
|
|
946
|
+
name: "sampleLogicResult",
|
|
947
|
+
status: "finished",
|
|
948
|
+
documents: [logicResultDoc],
|
|
949
|
+
};
|
|
950
|
+
logicResults.push(logicResult);
|
|
951
|
+
const dateSpy = jest.spyOn(Date, "now");
|
|
952
|
+
dateSpy.mockReturnValueOnce(now.toMillis())
|
|
953
|
+
.mockReturnValueOnce(now.toMillis() + 2000)
|
|
954
|
+
.mockReturnValueOnce(now.toMillis())
|
|
955
|
+
.mockReturnValueOnce(now.toMillis() + 4000)
|
|
956
|
+
.mockReturnValueOnce(now.toMillis())
|
|
957
|
+
.mockReturnValueOnce(now.toMillis() + 8000)
|
|
958
|
+
.mockReturnValueOnce(now.toMillis())
|
|
959
|
+
.mockReturnValueOnce(now.toMillis() + 16000)
|
|
960
|
+
.mockReturnValueOnce(now.toMillis())
|
|
961
|
+
.mockReturnValueOnce(now.toMillis() + 32000);
|
|
962
|
+
await indexUtils._mockable.simulateSubmitForm(logicResults, action, distributeFn);
|
|
963
|
+
expect(console.warn).toHaveBeenCalledTimes(1);
|
|
964
|
+
expect(console.warn).toHaveBeenCalledWith("Maximum retry count reached for logic servers/sample-server-id");
|
|
965
|
+
});
|
|
966
|
+
});
|
|
596
967
|
describe("groupDocsByUserAndDstPath", () => {
|
|
597
968
|
(0, index_1.initializeEmberFlow)(projectConfig, admin, db_structure_1.dbStructure, db_structure_1.Entity, {}, {}, []);
|
|
598
969
|
const docsByDstPath = new Map([
|
|
@@ -615,7 +986,7 @@ describe("groupDocsByUserAndDstPath", () => {
|
|
|
615
986
|
["othercollection/document5", [{ action: "merge", priority: "normal", dstPath: "othercollection/document5", doc: { field5: "value5" } }]],
|
|
616
987
|
]),
|
|
617
988
|
};
|
|
618
|
-
const results =
|
|
989
|
+
const results = indexUtils.groupDocsByUserAndDstPath(docsByDstPath, userId);
|
|
619
990
|
expect(results).toEqual(expectedResults);
|
|
620
991
|
});
|
|
621
992
|
});
|
|
@@ -727,7 +1098,7 @@ describe("expandConsolidateAndGroupByDstPath", () => {
|
|
|
727
1098
|
];
|
|
728
1099
|
// Act
|
|
729
1100
|
const logicResultDocs = logicResults.map((logicResult) => logicResult.documents).flat();
|
|
730
|
-
const result = await
|
|
1101
|
+
const result = await indexUtils.expandConsolidateAndGroupByDstPath(logicResultDocs);
|
|
731
1102
|
// Assert
|
|
732
1103
|
const expectedResult = new Map([
|
|
733
1104
|
["path1/doc1", [{ action: "merge", priority: "normal", dstPath: "path1/doc1", doc: { field1: "value1a", field3: "value3" }, instructions: { field2: "--", field4: "--" } }]],
|
|
@@ -773,7 +1144,7 @@ describe("expandConsolidateAndGroupByDstPath", () => {
|
|
|
773
1144
|
];
|
|
774
1145
|
// Act
|
|
775
1146
|
const logicResultDocs = logicResults.map((logicResult) => logicResult.documents).flat();
|
|
776
|
-
const result = await
|
|
1147
|
+
const result = await indexUtils.expandConsolidateAndGroupByDstPath(logicResultDocs);
|
|
777
1148
|
// Assert
|
|
778
1149
|
const expectedResult = new Map([
|
|
779
1150
|
["path1/doc1", [{
|
|
@@ -836,7 +1207,7 @@ describe("expandConsolidateAndGroupByDstPath", () => {
|
|
|
836
1207
|
];
|
|
837
1208
|
// Act
|
|
838
1209
|
const logicResultDocs = logicResults.map((logicResult) => logicResult.documents).flat();
|
|
839
|
-
const result = await
|
|
1210
|
+
const result = await indexUtils.expandConsolidateAndGroupByDstPath(logicResultDocs);
|
|
840
1211
|
// Assert
|
|
841
1212
|
const expectedResult = new Map([
|
|
842
1213
|
["path1/doc1", [{
|
|
@@ -892,7 +1263,7 @@ describe("expandConsolidateAndGroupByDstPath", () => {
|
|
|
892
1263
|
];
|
|
893
1264
|
// Act
|
|
894
1265
|
const logicResultDocs = logicResults.map((logicResult) => logicResult.documents).flat();
|
|
895
|
-
const result = await
|
|
1266
|
+
const result = await indexUtils.expandConsolidateAndGroupByDstPath(logicResultDocs);
|
|
896
1267
|
// Assert
|
|
897
1268
|
const expectedResult = new Map([
|
|
898
1269
|
["path1/doc1", [{
|
|
@@ -940,7 +1311,7 @@ describe("runViewLogics", () => {
|
|
|
940
1311
|
},
|
|
941
1312
|
];
|
|
942
1313
|
beforeEach(() => {
|
|
943
|
-
jest.spyOn(
|
|
1314
|
+
jest.spyOn(indexUtils._mockable, "getViewLogicsConfig").mockReturnValue(customViewLogicsConfig);
|
|
944
1315
|
});
|
|
945
1316
|
it("should run view logics properly", async () => {
|
|
946
1317
|
const logicResult1 = {
|
|
@@ -956,8 +1327,8 @@ describe("runViewLogics", () => {
|
|
|
956
1327
|
};
|
|
957
1328
|
viewLogicFn1.mockResolvedValue({});
|
|
958
1329
|
viewLogicFn2.mockResolvedValue({});
|
|
959
|
-
const results1 = await
|
|
960
|
-
const results2 = await
|
|
1330
|
+
const results1 = await indexUtils.runViewLogics(logicResult1);
|
|
1331
|
+
const results2 = await indexUtils.runViewLogics(logicResult2);
|
|
961
1332
|
const results = [...results1, ...results2];
|
|
962
1333
|
expect(viewLogicFn1).toHaveBeenCalledTimes(2);
|
|
963
1334
|
expect(viewLogicFn1.mock.calls[0][0]).toBe(logicResult1);
|
|
@@ -967,4 +1338,128 @@ describe("runViewLogics", () => {
|
|
|
967
1338
|
expect(results).toHaveLength(3);
|
|
968
1339
|
});
|
|
969
1340
|
});
|
|
1341
|
+
describe("updateLogicMetrics", () => {
|
|
1342
|
+
let colSpy;
|
|
1343
|
+
let docMock;
|
|
1344
|
+
let queueInstructionsSpy;
|
|
1345
|
+
let warnSpy;
|
|
1346
|
+
let setMock;
|
|
1347
|
+
beforeEach(() => {
|
|
1348
|
+
setMock = jest.fn().mockResolvedValue({});
|
|
1349
|
+
warnSpy = jest.spyOn(console, "warn").mockImplementation();
|
|
1350
|
+
docMock = jest.fn().mockImplementation((doc) => {
|
|
1351
|
+
return {
|
|
1352
|
+
path: `@metrics/${doc}`,
|
|
1353
|
+
collection: jest.fn().mockReturnValue({
|
|
1354
|
+
doc: jest.fn().mockReturnValue({
|
|
1355
|
+
set: setMock,
|
|
1356
|
+
}),
|
|
1357
|
+
}),
|
|
1358
|
+
};
|
|
1359
|
+
});
|
|
1360
|
+
colSpy = jest.spyOn(admin.firestore(), "collection").mockReturnValue({
|
|
1361
|
+
doc: docMock,
|
|
1362
|
+
});
|
|
1363
|
+
queueInstructionsSpy = jest.spyOn(distribution, "queueInstructions").mockResolvedValue();
|
|
1364
|
+
});
|
|
1365
|
+
afterEach(() => {
|
|
1366
|
+
colSpy.mockRestore();
|
|
1367
|
+
docMock.mockRestore();
|
|
1368
|
+
queueInstructionsSpy.mockRestore();
|
|
1369
|
+
warnSpy.mockRestore();
|
|
1370
|
+
});
|
|
1371
|
+
it("should skip logic result when execTime is undefined", async () => {
|
|
1372
|
+
const logicResults = [];
|
|
1373
|
+
const logicResult = {
|
|
1374
|
+
name: "sampleLogicResult",
|
|
1375
|
+
};
|
|
1376
|
+
logicResults.push(logicResult);
|
|
1377
|
+
await indexUtils._mockable.updateLogicMetrics(logicResults);
|
|
1378
|
+
expect(colSpy).toHaveBeenCalledTimes(1);
|
|
1379
|
+
expect(colSpy).toHaveBeenCalledWith("@metrics");
|
|
1380
|
+
expect(warnSpy).toHaveBeenCalledTimes(1);
|
|
1381
|
+
expect(warnSpy).toHaveBeenCalledWith("No execTime found for logic sampleLogicResult");
|
|
1382
|
+
expect(docMock).not.toHaveBeenCalled();
|
|
1383
|
+
expect(setMock).not.toHaveBeenCalled();
|
|
1384
|
+
expect(queueInstructionsSpy).not.toHaveBeenCalled();
|
|
1385
|
+
});
|
|
1386
|
+
it("should queue logic result metrics", async () => {
|
|
1387
|
+
const logicResults = [];
|
|
1388
|
+
const logicResult1 = {
|
|
1389
|
+
name: "sampleLogicResult",
|
|
1390
|
+
execTime: 100,
|
|
1391
|
+
};
|
|
1392
|
+
const logicResult2 = {
|
|
1393
|
+
name: "anotherLogicResult",
|
|
1394
|
+
execTime: 200,
|
|
1395
|
+
};
|
|
1396
|
+
logicResults.push(logicResult1);
|
|
1397
|
+
logicResults.push(logicResult2);
|
|
1398
|
+
await indexUtils._mockable.updateLogicMetrics(logicResults);
|
|
1399
|
+
expect(colSpy).toHaveBeenCalledTimes(1);
|
|
1400
|
+
expect(colSpy).toHaveBeenCalledWith("@metrics");
|
|
1401
|
+
expect(warnSpy).toHaveBeenCalledWith("anotherLogicResult took 200ms to execute");
|
|
1402
|
+
expect(docMock).toHaveBeenCalledTimes(2);
|
|
1403
|
+
expect(docMock).toHaveBeenNthCalledWith(1, "sampleLogicResult");
|
|
1404
|
+
expect(docMock).toHaveBeenNthCalledWith(2, "anotherLogicResult");
|
|
1405
|
+
expect(queueInstructionsSpy).toHaveBeenCalledTimes(2);
|
|
1406
|
+
expect(queueInstructionsSpy).toHaveBeenNthCalledWith(1, `@metrics/${logicResult1.name}`, {
|
|
1407
|
+
totalExecTime: `+${logicResult1.execTime}`,
|
|
1408
|
+
totalExecCount: "++",
|
|
1409
|
+
});
|
|
1410
|
+
expect(queueInstructionsSpy).toHaveBeenNthCalledWith(2, `@metrics/${logicResult2.name}`, {
|
|
1411
|
+
totalExecTime: `+${logicResult2.execTime}`,
|
|
1412
|
+
totalExecCount: "++",
|
|
1413
|
+
});
|
|
1414
|
+
expect(setMock).toHaveBeenCalledTimes(2);
|
|
1415
|
+
expect(setMock).toHaveBeenNthCalledWith(1, {
|
|
1416
|
+
execDate: expect.any(Timestamp),
|
|
1417
|
+
execTime: logicResult1.execTime,
|
|
1418
|
+
});
|
|
1419
|
+
expect(setMock).toHaveBeenNthCalledWith(2, {
|
|
1420
|
+
execDate: expect.any(Timestamp),
|
|
1421
|
+
execTime: logicResult2.execTime,
|
|
1422
|
+
});
|
|
1423
|
+
});
|
|
1424
|
+
});
|
|
1425
|
+
describe("cleanLogicMetricsExecutions", () => {
|
|
1426
|
+
let colGetMock;
|
|
1427
|
+
let deleteCollectionSpy;
|
|
1428
|
+
beforeEach(() => {
|
|
1429
|
+
colGetMock = jest.fn().mockResolvedValue({
|
|
1430
|
+
docs: [
|
|
1431
|
+
{
|
|
1432
|
+
ref: {
|
|
1433
|
+
collection: jest.fn().mockReturnValue({
|
|
1434
|
+
where: jest.fn().mockReturnValue({}),
|
|
1435
|
+
}),
|
|
1436
|
+
},
|
|
1437
|
+
},
|
|
1438
|
+
],
|
|
1439
|
+
});
|
|
1440
|
+
jest.spyOn(admin.firestore(), "collection").mockReturnValue({
|
|
1441
|
+
get: colGetMock,
|
|
1442
|
+
});
|
|
1443
|
+
deleteCollectionSpy = jest.spyOn(misc, "deleteCollection")
|
|
1444
|
+
.mockImplementation(async (query, callback) => {
|
|
1445
|
+
if (callback) {
|
|
1446
|
+
await callback({ size: 1 });
|
|
1447
|
+
}
|
|
1448
|
+
return Promise.resolve();
|
|
1449
|
+
});
|
|
1450
|
+
});
|
|
1451
|
+
afterEach(() => {
|
|
1452
|
+
jest.restoreAllMocks();
|
|
1453
|
+
});
|
|
1454
|
+
it("should clean logic metrics executions", async () => {
|
|
1455
|
+
jest.spyOn(console, "info").mockImplementation();
|
|
1456
|
+
await (0, index_utils_1.cleanLogicMetricsExecutions)({});
|
|
1457
|
+
expect(console.info).toHaveBeenCalledWith("Running cleanLogicMetricsExecutions");
|
|
1458
|
+
expect(admin.firestore().collection).toHaveBeenCalledTimes(1);
|
|
1459
|
+
expect(admin.firestore().collection).toHaveBeenCalledWith("@metrics");
|
|
1460
|
+
expect(colGetMock).toHaveBeenCalledTimes(1);
|
|
1461
|
+
expect(deleteCollectionSpy).toHaveBeenCalled();
|
|
1462
|
+
expect(console.info).toHaveBeenCalledWith("Cleaned 1 logic metrics executions");
|
|
1463
|
+
});
|
|
1464
|
+
});
|
|
970
1465
|
//# sourceMappingURL=index-utils.test.js.map
|