@capillarytech/creatives-library 8.0.108 → 8.0.110-alpha.0

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 (31) hide show
  1. package/initialState.js +1 -0
  2. package/package.json +1 -1
  3. package/services/api.js +9 -4
  4. package/utils/cdnTransformation.js +1 -1
  5. package/utils/tests/__snapshots__/cdnTransformation.test.js.snap +9 -9
  6. package/utils/tests/cdnTransformation.mockdata.js +27 -28
  7. package/utils/tests/transformerUtils.test.js +2127 -0
  8. package/utils/transformerUtils.js +421 -0
  9. package/v2Components/CapTagList/index.js +2 -7
  10. package/v2Components/CapTagList/messages.js +3 -3
  11. package/v2Components/FormBuilder/index.js +7 -3
  12. package/v2Containers/Cap/actions.js +8 -0
  13. package/v2Containers/Cap/constants.js +4 -0
  14. package/v2Containers/Cap/reducer.js +6 -0
  15. package/v2Containers/Cap/sagas.js +23 -0
  16. package/v2Containers/Cap/selectors.js +6 -0
  17. package/v2Containers/Cap/tests/__snapshots__/index.test.js.snap +1 -0
  18. package/v2Containers/Cap/tests/saga.test.js +90 -1
  19. package/v2Containers/CreativesContainer/SlideBoxContent.js +5 -1
  20. package/v2Containers/CreativesContainer/constants.js +14 -1
  21. package/v2Containers/CreativesContainer/index.js +50 -2
  22. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +2 -0
  23. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +25 -0
  24. package/v2Containers/CreativesContainer/tests/index.test.js +2 -0
  25. package/v2Containers/MobilePush/Create/index.js +1 -0
  26. package/v2Containers/Sms/Edit/index.js +1 -0
  27. package/v2Containers/TemplatesV2/index.js +8 -1
  28. package/v2Containers/Whatsapp/constants.js +2 -0
  29. package/v2Containers/Whatsapp/index.js +7 -3
  30. package/v2Containers/Zalo/index.js +5 -2
  31. package/v2Containers/mockdata.js +3 -0
@@ -0,0 +1,2127 @@
1
+ /**
2
+ * Tests for transformer utils
3
+ */
4
+ import {
5
+ transformChannelPayload,
6
+ getTemplateDiffState
7
+ } from "../transformerUtils";
8
+ import {
9
+ SMS,
10
+ EMAIL,
11
+ MOBILE_PUSH,
12
+ WHATSAPP,
13
+ PUSH,
14
+ ZALO
15
+ } from "../../v2Containers/CreativesContainer/constants";
16
+
17
+ describe("transformerUtils", () => {
18
+ describe("transformChannelPayload", () => {
19
+ it("should return original data for unsupported channel", () => {
20
+ const mockData = {
21
+ channel: "UNSUPPORTED_CHANNEL",
22
+ messageBody: "test message",
23
+ };
24
+
25
+ const result = transformChannelPayload(mockData);
26
+
27
+ expect(result).toEqual(mockData);
28
+ });
29
+
30
+ it("should handle null/undefined channel gracefully", () => {
31
+ const mockData = { messageBody: "test message" };
32
+
33
+ const result = transformChannelPayload(mockData);
34
+
35
+ expect(result).toEqual(mockData);
36
+ });
37
+
38
+ it("should handle case-insensitive channel names", () => {
39
+ const mockData = {
40
+ channel: "sms",
41
+ messageBody: "test message",
42
+ };
43
+
44
+ const result = transformChannelPayload(mockData);
45
+
46
+ expect(result.centralCommsPayload.channel).toEqual(SMS);
47
+ });
48
+ });
49
+
50
+ describe("SMS payload transformation", () => {
51
+ it("should transform SMS data correctly with minimal data", () => {
52
+ const mockData = {
53
+ channel: SMS,
54
+ messageBody: "test message",
55
+ };
56
+
57
+ const result = transformChannelPayload(mockData);
58
+
59
+ expect(result.centralCommsPayload).toBeDefined();
60
+ expect(result.centralCommsPayload.channel).toEqual(SMS);
61
+ expect(result.centralCommsPayload.smsMessageContent.message).toEqual(
62
+ "test message"
63
+ );
64
+ expect(result.centralCommsPayload.clientName).toEqual("EMF");
65
+ });
66
+
67
+ it("should transform SMS data with all options", () => {
68
+ const mockData = {
69
+ channel: SMS,
70
+ messageBody: "test message",
71
+ };
72
+
73
+ const options = {
74
+ loyaltyMetaData: {
75
+ actionId: "action-123",
76
+ ouId: 456,
77
+ clientName: "TestClient",
78
+ module: "TestModule",
79
+ transformedMessageDetails: {
80
+ smsDeliverySettings: {
81
+ sendDate: "2023-01-01",
82
+ },
83
+ },
84
+ },
85
+ };
86
+
87
+ const result = transformChannelPayload(mockData, options);
88
+
89
+ expect(result.centralCommsPayload.sourceEntityId).toEqual("action-123");
90
+ expect(result.centralCommsPayload.ouId).toEqual(456);
91
+ expect(result.centralCommsPayload.clientName).toEqual("TestClient");
92
+ expect(result.centralCommsPayload.module).toEqual("TestModule");
93
+ expect(result.centralCommsPayload.smsDeliverySettings).toEqual({
94
+ sendDate: "2023-01-01",
95
+ });
96
+ });
97
+
98
+ it("should handle undefined smsData.messageBody", () => {
99
+ const mockData = {
100
+ channel: SMS,
101
+ };
102
+
103
+ const result = transformChannelPayload(mockData);
104
+
105
+ expect(result.centralCommsPayload.smsMessageContent.message).toEqual("");
106
+ });
107
+
108
+ it("should handle undefined smsDeliverySettings", () => {
109
+ const mockData = {
110
+ channel: SMS,
111
+ messageBody: "test message",
112
+ };
113
+
114
+ const options = {
115
+ loyaltyMetaData: {
116
+ transformedMessageDetails: {},
117
+ },
118
+ };
119
+
120
+ const result = transformChannelPayload(mockData, options);
121
+
122
+ expect(result.centralCommsPayload.smsDeliverySettings).toEqual({});
123
+ });
124
+
125
+ it("should preserve all original SMS data properties", () => {
126
+ const mockData = {
127
+ channel: SMS,
128
+ messageBody: "test message",
129
+ customField1: "custom value 1",
130
+ customField2: "custom value 2",
131
+ };
132
+
133
+ const result = transformChannelPayload(mockData);
134
+
135
+ expect(result.centralCommsPayload.smsMessageContent.customField1).toEqual(
136
+ "custom value 1"
137
+ );
138
+ expect(result.centralCommsPayload.smsMessageContent.customField2).toEqual(
139
+ "custom value 2"
140
+ );
141
+ });
142
+ });
143
+
144
+ describe("Email payload transformation", () => {
145
+ it("should transform Email data correctly with minimal data", () => {
146
+ const mockData = {
147
+ channel: EMAIL,
148
+ emailBody: "<p>test email body</p>",
149
+ emailSubject: "test subject",
150
+ };
151
+
152
+ const result = transformChannelPayload(mockData);
153
+
154
+ expect(result.centralCommsPayload).toBeDefined();
155
+ expect(result.centralCommsPayload.channel).toEqual(EMAIL);
156
+ expect(
157
+ result.centralCommsPayload.emailMessageContent.messageBody
158
+ ).toEqual("<p>test email body</p>");
159
+ expect(
160
+ result.centralCommsPayload.emailMessageContent.messageSubject
161
+ ).toEqual("test subject");
162
+ expect(result.centralCommsPayload.clientName).toEqual("EMF");
163
+ });
164
+
165
+ it("should transform Email data with all options", () => {
166
+ const mockData = {
167
+ channel: EMAIL,
168
+ emailBody: "<p>test email body</p>",
169
+ emailSubject: "test subject",
170
+ };
171
+
172
+ const options = {
173
+ loyaltyMetaData: {
174
+ actionId: "action-123",
175
+ ouId: 456,
176
+ clientName: "TestClient",
177
+ module: "TestModule",
178
+ transformedMessageDetails: {
179
+ emailDeliverySettings: {
180
+ sendDate: "2023-01-01",
181
+ senderAddress: "test@example.com",
182
+ },
183
+ },
184
+ },
185
+ };
186
+
187
+ const result = transformChannelPayload(mockData, options);
188
+
189
+ expect(result.centralCommsPayload.sourceEntityId).toEqual("action-123");
190
+ expect(result.centralCommsPayload.ouId).toEqual(456);
191
+ expect(result.centralCommsPayload.clientName).toEqual("TestClient");
192
+ expect(result.centralCommsPayload.module).toEqual("TestModule");
193
+ expect(result.centralCommsPayload.emailDeliverySettings).toEqual({
194
+ sendDate: "2023-01-01",
195
+ senderAddress: "test@example.com"
196
+ });
197
+ });
198
+
199
+ it("should handle undefined email content", () => {
200
+ const mockData = {
201
+ channel: EMAIL
202
+ };
203
+
204
+ const result = transformChannelPayload(mockData);
205
+
206
+ expect(
207
+ result.centralCommsPayload.emailMessageContent.messageBody
208
+ ).toEqual("");
209
+ expect(
210
+ result.centralCommsPayload.emailMessageContent.messageSubject
211
+ ).toEqual("");
212
+ });
213
+
214
+ it("should handle undefined emailDeliverySettings", () => {
215
+ const mockData = {
216
+ channel: EMAIL,
217
+ emailBody: "<p>test email body</p>",
218
+ emailSubject: "test subject"
219
+ };
220
+
221
+ const options = {
222
+ loyaltyMetaData: {
223
+ transformedMessageDetails: {}
224
+ }
225
+ };
226
+
227
+ const result = transformChannelPayload(mockData, options);
228
+
229
+ expect(result.centralCommsPayload.emailDeliverySettings).toEqual({});
230
+ });
231
+
232
+ it("should preserve all original Email data properties", () => {
233
+ const mockData = {
234
+ channel: EMAIL,
235
+ emailBody: "<p>test email body</p>",
236
+ emailSubject: "test subject",
237
+ customField1: "custom value 1",
238
+ customField2: "custom value 2"
239
+ };
240
+
241
+ const result = transformChannelPayload(mockData);
242
+
243
+ expect(
244
+ result.centralCommsPayload.emailMessageContent.customField1
245
+ ).toEqual("custom value 1");
246
+ expect(
247
+ result.centralCommsPayload.emailMessageContent.customField2
248
+ ).toEqual("custom value 2");
249
+ });
250
+ });
251
+
252
+ describe("Mobile Push payload transformation", () => {
253
+ it("should transform Mobile Push data correctly with minimal data", () => {
254
+ const mockData = {
255
+ channel: MOBILE_PUSH,
256
+ messageSubject: "test push notification"
257
+ };
258
+
259
+ const result = transformChannelPayload(mockData);
260
+
261
+ expect(result.centralCommsPayload).toBeDefined();
262
+ expect(result.centralCommsPayload.channel).toEqual(PUSH);
263
+ expect(
264
+ result.centralCommsPayload.mpushMessageContent.messageSubject
265
+ ).toEqual("test push notification");
266
+ expect(result.centralCommsPayload.clientName).toEqual("VENENO");
267
+ });
268
+
269
+ it("should transform Mobile Push data with all options", () => {
270
+ const mockData = {
271
+ channel: MOBILE_PUSH,
272
+ messageSubject: "test push notification",
273
+ accountId: 12345,
274
+ androidContent: {
275
+ title: "Android Title",
276
+ message: "Android Message",
277
+ type: "TEXT",
278
+ cta: {
279
+ actionLink: "https://example.com/android"
280
+ },
281
+ expandableDetails: {
282
+ message: "Expanded Android Message",
283
+ style: "CUSTOM_STYLE",
284
+ ctas: [{ title: "Action 1" }],
285
+ image: "image-url.jpg",
286
+ categoryId: "cat-123"
287
+ },
288
+ custom: {
289
+ prop1: "value1"
290
+ }
291
+ },
292
+ iosContent: {
293
+ title: "iOS Title",
294
+ message: "iOS Message",
295
+ type: "IMAGE",
296
+ cta: {
297
+ actionLink: "https://example.com/ios"
298
+ },
299
+ expandableDetails: {
300
+ message: "Expanded iOS Message",
301
+ style: "CUSTOM_IOS_STYLE",
302
+ ctas: [{ title: "iOS Action 1" }],
303
+ image: "ios-image-url.jpg",
304
+ categoryId: "cat-456"
305
+ },
306
+ custom: {
307
+ prop2: "value2"
308
+ }
309
+ }
310
+ };
311
+
312
+ const options = {
313
+ loyaltyMetaData: {
314
+ actionId: "action-123",
315
+ ouId: 456,
316
+ clientName: "TestClient",
317
+ module: "TestModule",
318
+ transformedMessageDetails: {
319
+ mobilePushDeliverySettings: {
320
+ sendDate: "2023-01-01"
321
+ }
322
+ }
323
+ }
324
+ };
325
+
326
+ const result = transformChannelPayload(mockData, options);
327
+
328
+ // Check base payload
329
+ expect(result.centralCommsPayload.sourceEntityId).toEqual("action-123");
330
+ expect(result.centralCommsPayload.ouId).toEqual(456);
331
+ expect(result.centralCommsPayload.clientName).toEqual("TestClient");
332
+ expect(result.centralCommsPayload.module).toEqual("TestModule");
333
+
334
+ // Check Android content
335
+ expect(
336
+ result.centralCommsPayload.mpushMessageContent.androidContent.title
337
+ ).toEqual("Android Title");
338
+ expect(
339
+ result.centralCommsPayload.mpushMessageContent.androidContent.message
340
+ ).toEqual("Android Message");
341
+ expect(
342
+ result.centralCommsPayload.mpushMessageContent.androidContent.type
343
+ ).toEqual("TEXT");
344
+ expect(
345
+ result.centralCommsPayload.mpushMessageContent.androidContent.cta
346
+ .actionLink
347
+ ).toEqual("https://example.com/android");
348
+ expect(
349
+ result.centralCommsPayload.mpushMessageContent.androidContent
350
+ .expandableDetails.style
351
+ ).toEqual("CUSTOM_STYLE");
352
+ expect(
353
+ result.centralCommsPayload.mpushMessageContent.androidContent
354
+ .expandableDetails.message
355
+ ).toEqual("Expanded Android Message");
356
+ expect(
357
+ result.centralCommsPayload.mpushMessageContent.androidContent
358
+ .expandableDetails.ctas
359
+ ).toEqual([{ title: "Action 1" }]);
360
+ expect(
361
+ result.centralCommsPayload.mpushMessageContent.androidContent
362
+ .expandableDetails.image
363
+ ).toEqual("image-url.jpg");
364
+ expect(
365
+ result.centralCommsPayload.mpushMessageContent.androidContent
366
+ .expandableDetails.categoryId
367
+ ).toEqual("cat-123");
368
+ expect(
369
+ result.centralCommsPayload.mpushMessageContent.androidContent
370
+ .customProperties
371
+ ).toEqual({ prop1: "value1" });
372
+
373
+ // Check iOS content
374
+ expect(
375
+ result.centralCommsPayload.mpushMessageContent.iosContent.title
376
+ ).toEqual("iOS Title");
377
+ expect(
378
+ result.centralCommsPayload.mpushMessageContent.iosContent.message
379
+ ).toEqual("iOS Message");
380
+ expect(
381
+ result.centralCommsPayload.mpushMessageContent.iosContent.type
382
+ ).toEqual("IMAGE");
383
+ expect(
384
+ result.centralCommsPayload.mpushMessageContent.iosContent.cta.actionLink
385
+ ).toEqual("https://example.com/ios");
386
+ expect(
387
+ result.centralCommsPayload.mpushMessageContent.iosContent
388
+ .expandableDetails.style
389
+ ).toEqual("CUSTOM_IOS_STYLE");
390
+ expect(
391
+ result.centralCommsPayload.mpushMessageContent.iosContent
392
+ .expandableDetails.message
393
+ ).toEqual("Expanded iOS Message");
394
+ expect(
395
+ result.centralCommsPayload.mpushMessageContent.iosContent
396
+ .expandableDetails.ctas
397
+ ).toEqual([{ title: "iOS Action 1" }]);
398
+ expect(
399
+ result.centralCommsPayload.mpushMessageContent.iosContent
400
+ .expandableDetails.image
401
+ ).toEqual("ios-image-url.jpg");
402
+ expect(
403
+ result.centralCommsPayload.mpushMessageContent.iosContent
404
+ .expandableDetails.categoryId
405
+ ).toEqual("cat-456");
406
+ expect(
407
+ result.centralCommsPayload.mpushMessageContent.iosContent
408
+ .customProperties
409
+ ).toEqual({ prop2: "value2" });
410
+
411
+ // Check account ID and delivery settings
412
+ expect(result.centralCommsPayload.mpushMessageContent.accountId).toEqual(
413
+ 12345
414
+ );
415
+ expect(result.centralCommsPayload.mpushDeliverySettings).toEqual({
416
+ sendDate: "2023-01-01"
417
+ });
418
+ });
419
+
420
+ it("should handle missing Android and iOS content", () => {
421
+ const mockData = {
422
+ channel: MOBILE_PUSH,
423
+ messageSubject: "test push notification"
424
+ };
425
+
426
+ const result = transformChannelPayload(mockData);
427
+
428
+ // Check default Android values
429
+ expect(
430
+ result.centralCommsPayload.mpushMessageContent.androidContent.type
431
+ ).toEqual("TEXT");
432
+ expect(
433
+ result.centralCommsPayload.mpushMessageContent.androidContent.deviceType
434
+ ).toEqual("ANDROID");
435
+ expect(
436
+ result.centralCommsPayload.mpushMessageContent.androidContent.cta.type
437
+ ).toEqual("EXTERNAL_URL");
438
+ expect(
439
+ result.centralCommsPayload.mpushMessageContent.androidContent
440
+ .expandableDetails.style
441
+ ).toEqual("BIG_TEXT");
442
+
443
+ // Check default iOS values
444
+ expect(
445
+ result.centralCommsPayload.mpushMessageContent.iosContent.type
446
+ ).toEqual("TEXT");
447
+ expect(
448
+ result.centralCommsPayload.mpushMessageContent.iosContent.deviceType
449
+ ).toEqual("IOS");
450
+ expect(
451
+ result.centralCommsPayload.mpushMessageContent.iosContent.title
452
+ ).toEqual("test push notification");
453
+ expect(
454
+ result.centralCommsPayload.mpushMessageContent.iosContent.message
455
+ ).toEqual("");
456
+ expect(
457
+ result.centralCommsPayload.mpushMessageContent.iosContent.cta.type
458
+ ).toEqual("EXTERNAL_URL");
459
+ expect(
460
+ result.centralCommsPayload.mpushMessageContent.iosContent
461
+ .expandableDetails.style
462
+ ).toEqual("BIG_TEXT");
463
+ });
464
+
465
+ it("should handle null Android and iOS CTA and expandableDetails", () => {
466
+ const mockData = {
467
+ channel: MOBILE_PUSH,
468
+ messageSubject: "test push notification",
469
+ androidContent: {},
470
+ iosContent: {}
471
+ };
472
+
473
+ const result = transformChannelPayload(mockData);
474
+
475
+ // Android content checks
476
+ expect(
477
+ result.centralCommsPayload.mpushMessageContent.androidContent.cta
478
+ ).toBeDefined();
479
+ expect(
480
+ result.centralCommsPayload.mpushMessageContent.androidContent.cta.type
481
+ ).toEqual("EXTERNAL_URL");
482
+ expect(
483
+ result.centralCommsPayload.mpushMessageContent.androidContent
484
+ .expandableDetails
485
+ ).toBeDefined();
486
+ expect(
487
+ result.centralCommsPayload.mpushMessageContent.androidContent
488
+ .expandableDetails.style
489
+ ).toEqual("BIG_TEXT");
490
+
491
+ // iOS content checks
492
+ expect(
493
+ result.centralCommsPayload.mpushMessageContent.iosContent.cta
494
+ ).toBeDefined();
495
+ expect(
496
+ result.centralCommsPayload.mpushMessageContent.iosContent.cta.type
497
+ ).toEqual("EXTERNAL_URL");
498
+ expect(
499
+ result.centralCommsPayload.mpushMessageContent.iosContent
500
+ .expandableDetails
501
+ ).toBeDefined();
502
+ expect(
503
+ result.centralCommsPayload.mpushMessageContent.iosContent
504
+ .expandableDetails.style
505
+ ).toEqual("BIG_TEXT");
506
+ });
507
+ });
508
+
509
+ describe("WhatsApp payload transformation", () => {
510
+ it("should transform WhatsApp data correctly with minimal data", () => {
511
+ const mockData = {
512
+ channel: WHATSAPP,
513
+ messageBody: "test whatsapp message"
514
+ };
515
+
516
+ const result = transformChannelPayload(mockData);
517
+
518
+ expect(result.centralCommsPayload).toBeDefined();
519
+ expect(result.centralCommsPayload.channel).toEqual(WHATSAPP);
520
+ expect(
521
+ result.centralCommsPayload.whatsappMessageContent.messageBody
522
+ ).toEqual("test whatsapp message");
523
+ expect(result.centralCommsPayload.clientName).toEqual("VENENO");
524
+ });
525
+
526
+ it("should transform WhatsApp data with all options", () => {
527
+ const mockData = {
528
+ channel: WHATSAPP,
529
+ messageBody: "test whatsapp message",
530
+ accountId: 12345,
531
+ templateConfigs: {
532
+ id: "template-123",
533
+ name: "greetings_template",
534
+ template: "https://example.com/template",
535
+ varMapped: {
536
+ name: "John Doe",
537
+ product: "Premium Subscription"
538
+ },
539
+ whatsappMedia: {
540
+ header: "Header Content",
541
+ headerVarMapped: { logo: "company-logo.png" },
542
+ footer: "Footer Content"
543
+ },
544
+ category: "MARKETING",
545
+ language: "en_US",
546
+ buttonType: "QUICK_REPLY",
547
+ buttons: [
548
+ { text: "Yes", type: "REPLY" },
549
+ { text: "No", type: "REPLY" }
550
+ ]
551
+ },
552
+ sourceAccountIdentifier: "whatsapp-account-123"
553
+ };
554
+
555
+ const options = {
556
+ loyaltyMetaData: {
557
+ actionId: "action-123",
558
+ ouId: 456,
559
+ clientName: "TestClient",
560
+ module: "TestModule",
561
+ transformedMessageDetails: {
562
+ whatsappDeliverySettings: {
563
+ sendDate: "2023-01-01",
564
+ priority: "HIGH"
565
+ }
566
+ }
567
+ }
568
+ };
569
+
570
+ const result = transformChannelPayload(mockData, options);
571
+
572
+ // Check base payload
573
+ expect(result.centralCommsPayload.sourceEntityId).toEqual("action-123");
574
+ expect(result.centralCommsPayload.ouId).toEqual(456);
575
+ expect(result.centralCommsPayload.clientName).toEqual("TestClient");
576
+ expect(result.centralCommsPayload.module).toEqual("TestModule");
577
+
578
+ // Check WhatsApp-specific content
579
+ expect(
580
+ result.centralCommsPayload.whatsappMessageContent.messageBody
581
+ ).toEqual("test whatsapp message");
582
+ expect(
583
+ result.centralCommsPayload.whatsappMessageContent.accountId
584
+ ).toEqual(12345);
585
+ expect(
586
+ result.centralCommsPayload.whatsappMessageContent
587
+ .sourceAccountIdentifier
588
+ ).toEqual("whatsapp-account-123");
589
+
590
+ // Check template configs
591
+ expect(
592
+ result.centralCommsPayload.whatsappMessageContent.templateConfigs.id
593
+ ).toEqual("template-123");
594
+ expect(
595
+ result.centralCommsPayload.whatsappMessageContent.templateConfigs.name
596
+ ).toEqual("greetings_template");
597
+ expect(
598
+ result.centralCommsPayload.whatsappMessageContent.templateConfigs
599
+ .template
600
+ ).toEqual("https://example.com/template");
601
+ expect(
602
+ result.centralCommsPayload.whatsappMessageContent.templateConfigs
603
+ .varMapped
604
+ ).toEqual({
605
+ name: "John Doe",
606
+ product: "Premium Subscription"
607
+ });
608
+ expect(
609
+ result.centralCommsPayload.whatsappMessageContent.templateConfigs
610
+ .whatsappMedia
611
+ ).toEqual({
612
+ header: "Header Content",
613
+ headerVarMapped: { logo: "company-logo.png" },
614
+ footer: "Footer Content"
615
+ });
616
+ expect(
617
+ result.centralCommsPayload.whatsappMessageContent.templateConfigs
618
+ .category
619
+ ).toEqual("MARKETING");
620
+ expect(
621
+ result.centralCommsPayload.whatsappMessageContent.templateConfigs
622
+ .language
623
+ ).toEqual("en_US");
624
+ expect(
625
+ result.centralCommsPayload.whatsappMessageContent.templateConfigs
626
+ .buttonType
627
+ ).toEqual("QUICK_REPLY");
628
+ expect(
629
+ result.centralCommsPayload.whatsappMessageContent.templateConfigs
630
+ .buttons
631
+ ).toEqual([
632
+ { text: "Yes", type: "REPLY" },
633
+ { text: "No", type: "REPLY" }
634
+ ]);
635
+
636
+ // Check delivery settings
637
+ expect(result.centralCommsPayload.whatsappDeliverySettings).toEqual({
638
+ sendDate: "2023-01-01",
639
+ priority: "HIGH"
640
+ });
641
+ });
642
+
643
+ it("should handle missing template configs", () => {
644
+ const mockData = {
645
+ channel: WHATSAPP,
646
+ messageBody: "test whatsapp message"
647
+ };
648
+
649
+ const result = transformChannelPayload(mockData);
650
+
651
+ expect(
652
+ result.centralCommsPayload.whatsappMessageContent.templateConfigs
653
+ ).toEqual({});
654
+ });
655
+
656
+ it("should handle undefined whatsappDeliverySettings", () => {
657
+ const mockData = {
658
+ channel: WHATSAPP,
659
+ messageBody: "test whatsapp message"
660
+ };
661
+
662
+ const options = {
663
+ loyaltyMetaData: {
664
+ transformedMessageDetails: {}
665
+ }
666
+ };
667
+
668
+ const result = transformChannelPayload(mockData, options);
669
+
670
+ expect(result.centralCommsPayload.whatsappDeliverySettings).toEqual({});
671
+ });
672
+ });
673
+
674
+ describe("Zalo payload transformation", () => {
675
+ it("should transform Zalo data correctly with minimal data", () => {
676
+ const mockData = {
677
+ channel: ZALO,
678
+ messageBody: "test zalo message"
679
+ };
680
+
681
+ const result = transformChannelPayload(mockData);
682
+
683
+ expect(result.centralCommsPayload).toBeDefined();
684
+ expect(result.centralCommsPayload.channel).toEqual(ZALO);
685
+ expect(result.centralCommsPayload.zaloMessageContent.messageBody).toEqual(
686
+ "test zalo message"
687
+ );
688
+ expect(result.centralCommsPayload.clientName).toEqual("VENENO");
689
+ });
690
+
691
+ it("should transform Zalo data with all options", () => {
692
+ const mockData = {
693
+ channel: ZALO,
694
+ messageBody: "test zalo message",
695
+ accountId: "zalo-account-123",
696
+ accountName: "Zalo Official Account",
697
+ token: "zalo-auth-token-xyz",
698
+ templateConfigs: {
699
+ id: "template-456",
700
+ name: "promotion_template",
701
+ template: "https://example.com/zalo-template",
702
+ varMapped: {
703
+ customer: "Jane Smith",
704
+ offer: "Summer Sale",
705
+ discount: "25%"
706
+ }
707
+ }
708
+ };
709
+
710
+ const options = {
711
+ loyaltyMetaData: {
712
+ actionId: "action-123",
713
+ ouId: 456,
714
+ clientName: "TestClient",
715
+ module: "TestModule",
716
+ transformedMessageDetails: {
717
+ zaloDeliverySettings: {
718
+ sendDate: "2023-01-01",
719
+ priority: "NORMAL"
720
+ }
721
+ }
722
+ }
723
+ };
724
+
725
+ const result = transformChannelPayload(mockData, options);
726
+
727
+ // Check base payload
728
+ expect(result.centralCommsPayload.sourceEntityId).toEqual("action-123");
729
+ expect(result.centralCommsPayload.ouId).toEqual(456);
730
+ expect(result.centralCommsPayload.clientName).toEqual("TestClient");
731
+ expect(result.centralCommsPayload.module).toEqual("TestModule");
732
+
733
+ // Check Zalo-specific content
734
+ expect(result.centralCommsPayload.zaloMessageContent.messageBody).toEqual(
735
+ "test zalo message"
736
+ );
737
+ expect(result.centralCommsPayload.zaloMessageContent.accountId).toEqual(
738
+ "zalo-account-123"
739
+ );
740
+ expect(result.centralCommsPayload.zaloMessageContent.accountName).toEqual(
741
+ "Zalo Official Account"
742
+ );
743
+ expect(result.centralCommsPayload.zaloMessageContent.token).toEqual(
744
+ "zalo-auth-token-xyz"
745
+ );
746
+
747
+ // Check template configs
748
+ expect(
749
+ result.centralCommsPayload.zaloMessageContent.templateConfigs.id
750
+ ).toEqual("template-456");
751
+ expect(
752
+ result.centralCommsPayload.zaloMessageContent.templateConfigs.name
753
+ ).toEqual("promotion_template");
754
+ expect(
755
+ result.centralCommsPayload.zaloMessageContent.templateConfigs.template
756
+ ).toEqual("https://example.com/zalo-template");
757
+ expect(
758
+ result.centralCommsPayload.zaloMessageContent.templateConfigs.varMapped
759
+ ).toEqual({
760
+ customer: "Jane Smith",
761
+ offer: "Summer Sale",
762
+ discount: "25%"
763
+ });
764
+
765
+ // Check delivery settings
766
+ expect(result.centralCommsPayload.zaloDeliverySettings).toEqual({
767
+ sendDate: "2023-01-01",
768
+ priority: "NORMAL"
769
+ });
770
+ });
771
+
772
+ it("should handle missing template configs", () => {
773
+ const mockData = {
774
+ channel: ZALO,
775
+ messageBody: "test zalo message"
776
+ };
777
+
778
+ const result = transformChannelPayload(mockData);
779
+
780
+ expect(
781
+ result.centralCommsPayload.zaloMessageContent.templateConfigs
782
+ ).toEqual({});
783
+ });
784
+
785
+ it("should handle undefined zaloDeliverySettings", () => {
786
+ const mockData = {
787
+ channel: ZALO,
788
+ messageBody: "test zalo message"
789
+ };
790
+
791
+ const options = {
792
+ loyaltyMetaData: {
793
+ transformedMessageDetails: {}
794
+ }
795
+ };
796
+
797
+ const result = transformChannelPayload(mockData, options);
798
+
799
+ expect(result.centralCommsPayload.zaloDeliverySettings).toEqual({});
800
+ });
801
+
802
+ it("should initialize default values when fields are missing", () => {
803
+ const mockData = {
804
+ channel: ZALO
805
+ };
806
+
807
+ const result = transformChannelPayload(mockData);
808
+
809
+ expect(result.centralCommsPayload.zaloMessageContent.messageBody).toEqual(
810
+ ""
811
+ );
812
+ expect(result.centralCommsPayload.zaloMessageContent.accountId).toEqual(
813
+ ""
814
+ );
815
+ expect(result.centralCommsPayload.zaloMessageContent.accountName).toEqual(
816
+ ""
817
+ );
818
+ expect(result.centralCommsPayload.zaloMessageContent.token).toEqual("");
819
+ });
820
+ });
821
+
822
+ describe("getTemplateDiffState", () => {
823
+ it("should return false for unsupported channel", () => {
824
+ const result = getTemplateDiffState("UNSUPPORTED_CHANNEL", {}, {});
825
+
826
+ expect(result).toBe(false);
827
+ });
828
+
829
+ it("should handle case-insensitive channel names", () => {
830
+ // Mock implementation for testing channelName case sensitivity
831
+ const oldData = {
832
+ transformedMessageDetails: {
833
+ smsMessageContent: {
834
+ message: "old message"
835
+ }
836
+ }
837
+ };
838
+
839
+ const newData = {
840
+ messageBody: "new message"
841
+ };
842
+
843
+ const result = getTemplateDiffState("sms", oldData, newData);
844
+
845
+ expect(result).toBe(true);
846
+ });
847
+
848
+ it("should route to correct diff checker for each channel", () => {
849
+ // SMS test
850
+ expect(
851
+ getTemplateDiffState(
852
+ SMS,
853
+ {
854
+ transformedMessageDetails: { smsMessageContent: { message: "a" } }
855
+ },
856
+ { messageBody: "b" }
857
+ )
858
+ ).toBe(true);
859
+
860
+ // EMAIL test
861
+ expect(
862
+ getTemplateDiffState(
863
+ EMAIL,
864
+ {
865
+ transformedMessageDetails: {
866
+ emailMessageContent: { messageBody: "a" }
867
+ }
868
+ },
869
+ { emailBody: "b" }
870
+ )
871
+ ).toBe(true);
872
+
873
+ // MOBILE_PUSH test
874
+ expect(
875
+ getTemplateDiffState(
876
+ MOBILE_PUSH,
877
+ {
878
+ transformedMessageDetails: {
879
+ mpushMessageContent: { messageSubject: "a" }
880
+ }
881
+ },
882
+ { messageSubject: "b" }
883
+ )
884
+ ).toBe(true);
885
+
886
+ // PUSH test (should route to same checker as MOBILE_PUSH)
887
+ expect(
888
+ getTemplateDiffState(
889
+ PUSH,
890
+ {
891
+ transformedMessageDetails: {
892
+ mpushMessageContent: { messageSubject: "a" }
893
+ }
894
+ },
895
+ { messageSubject: "b" }
896
+ )
897
+ ).toBe(true);
898
+ });
899
+ });
900
+
901
+ describe("SMS template diff checking", () => {
902
+ it("should detect changes in message content", () => {
903
+ const oldData = {
904
+ transformedMessageDetails: {
905
+ smsMessageContent: {
906
+ message: "old message"
907
+ }
908
+ }
909
+ };
910
+
911
+ const newData = {
912
+ messageBody: "new message"
913
+ };
914
+
915
+ const result = getTemplateDiffState(SMS, oldData, newData);
916
+
917
+ expect(result).toBe(true);
918
+ });
919
+
920
+ it("should return false when message content is the same", () => {
921
+ const oldData = {
922
+ transformedMessageDetails: {
923
+ smsMessageContent: {
924
+ message: "same message"
925
+ }
926
+ }
927
+ };
928
+
929
+ const newData = {
930
+ messageBody: "same message"
931
+ };
932
+
933
+ const result = getTemplateDiffState(SMS, oldData, newData);
934
+
935
+ expect(result).toBe(false);
936
+ });
937
+
938
+ it("should handle undefined/null values gracefully", () => {
939
+ // Both values undefined
940
+ expect(
941
+ getTemplateDiffState(
942
+ SMS,
943
+ { transformedMessageDetails: { smsMessageContent: {} } },
944
+ {}
945
+ )
946
+ ).toBe(false);
947
+
948
+ // Old value undefined, new value defined
949
+ expect(
950
+ getTemplateDiffState(
951
+ SMS,
952
+ { transformedMessageDetails: { smsMessageContent: {} } },
953
+ { messageBody: "new message" }
954
+ )
955
+ ).toBe(true);
956
+
957
+ // Old value defined, new value undefined
958
+ expect(
959
+ getTemplateDiffState(
960
+ SMS,
961
+ {
962
+ transformedMessageDetails: {
963
+ smsMessageContent: { message: "old message" }
964
+ }
965
+ },
966
+ {}
967
+ )
968
+ ).toBe(true);
969
+
970
+ // Completely missing properties
971
+ expect(getTemplateDiffState(SMS, {}, {})).toBe(false);
972
+ });
973
+ });
974
+
975
+ describe("Email template diff checking", () => {
976
+ it("should detect changes in email body", () => {
977
+ const oldData = {
978
+ transformedMessageDetails: {
979
+ emailMessageContent: {
980
+ messageBody: "<p>old body</p>",
981
+ messageSubject: "same subject"
982
+ }
983
+ }
984
+ };
985
+
986
+ const newData = {
987
+ emailBody: "<p>new body</p>",
988
+ emailSubject: "same subject"
989
+ };
990
+
991
+ const result = getTemplateDiffState(EMAIL, oldData, newData);
992
+
993
+ expect(result).toBe(true);
994
+ });
995
+
996
+ it("should detect changes in email subject", () => {
997
+ const oldData = {
998
+ transformedMessageDetails: {
999
+ emailMessageContent: {
1000
+ messageBody: "<p>same body</p>",
1001
+ messageSubject: "old subject"
1002
+ }
1003
+ }
1004
+ };
1005
+
1006
+ const newData = {
1007
+ emailBody: "<p>same body</p>",
1008
+ emailSubject: "new subject"
1009
+ };
1010
+
1011
+ const result = getTemplateDiffState(EMAIL, oldData, newData);
1012
+
1013
+ expect(result).toBe(true);
1014
+ });
1015
+
1016
+ it("should detect changes in both email body and subject", () => {
1017
+ const oldData = {
1018
+ transformedMessageDetails: {
1019
+ emailMessageContent: {
1020
+ messageBody: "<p>old body</p>",
1021
+ messageSubject: "old subject"
1022
+ }
1023
+ }
1024
+ };
1025
+
1026
+ const newData = {
1027
+ emailBody: "<p>new body</p>",
1028
+ emailSubject: "new subject"
1029
+ };
1030
+
1031
+ const result = getTemplateDiffState(EMAIL, oldData, newData);
1032
+
1033
+ expect(result).toBe(true);
1034
+ });
1035
+
1036
+ it("should return false when email content is the same", () => {
1037
+ const oldData = {
1038
+ transformedMessageDetails: {
1039
+ emailMessageContent: {
1040
+ messageBody: "<p>same body</p>",
1041
+ messageSubject: "same subject"
1042
+ }
1043
+ }
1044
+ };
1045
+
1046
+ const newData = {
1047
+ emailBody: "<p>same body</p>",
1048
+ emailSubject: "same subject"
1049
+ };
1050
+
1051
+ const result = getTemplateDiffState(EMAIL, oldData, newData);
1052
+
1053
+ expect(result).toBe(false);
1054
+ });
1055
+
1056
+ it("should handle undefined/null values gracefully", () => {
1057
+ // Both values undefined
1058
+ expect(
1059
+ getTemplateDiffState(
1060
+ EMAIL,
1061
+ { transformedMessageDetails: { emailMessageContent: {} } },
1062
+ {}
1063
+ )
1064
+ ).toBe(false);
1065
+
1066
+ // Old body undefined, new body defined
1067
+ expect(
1068
+ getTemplateDiffState(
1069
+ EMAIL,
1070
+ {
1071
+ transformedMessageDetails: {
1072
+ emailMessageContent: { messageSubject: "subject" }
1073
+ }
1074
+ },
1075
+ { emailBody: "<p>new body</p>", emailSubject: "subject" }
1076
+ )
1077
+ ).toBe(true);
1078
+
1079
+ // Old subject undefined, new subject defined
1080
+ expect(
1081
+ getTemplateDiffState(
1082
+ EMAIL,
1083
+ {
1084
+ transformedMessageDetails: {
1085
+ emailMessageContent: { messageBody: "<p>body</p>" }
1086
+ }
1087
+ },
1088
+ { emailBody: "<p>body</p>", emailSubject: "new subject" }
1089
+ )
1090
+ ).toBe(true);
1091
+
1092
+ // Completely missing properties
1093
+ expect(getTemplateDiffState(EMAIL, {}, {})).toBe(false);
1094
+ });
1095
+ });
1096
+
1097
+ describe("Mobile Push template diff checking", () => {
1098
+ it("should detect changes in push notification subject", () => {
1099
+ const oldData = {
1100
+ transformedMessageDetails: {
1101
+ mpushMessageContent: {
1102
+ messageSubject: "old subject",
1103
+ androidContent: {
1104
+ title: "same title",
1105
+ message: "same message",
1106
+ cta: { actionLink: "https://example.com" }
1107
+ },
1108
+ iosContent: {
1109
+ title: "same ios title",
1110
+ message: "same ios message",
1111
+ cta: { actionLink: "https://example.com" }
1112
+ }
1113
+ }
1114
+ }
1115
+ };
1116
+
1117
+ const newData = {
1118
+ messageSubject: "new subject",
1119
+ androidContent: {
1120
+ title: "same title",
1121
+ message: "same message",
1122
+ cta: { actionLink: "https://example.com" }
1123
+ },
1124
+ iosContent: {
1125
+ title: "same ios title",
1126
+ message: "same ios message",
1127
+ cta: { actionLink: "https://example.com" }
1128
+ }
1129
+ };
1130
+
1131
+ const result = getTemplateDiffState(MOBILE_PUSH, oldData, newData);
1132
+
1133
+ expect(result).toBe(true);
1134
+ });
1135
+
1136
+ it("should detect changes in Android title", () => {
1137
+ const oldData = {
1138
+ transformedMessageDetails: {
1139
+ mpushMessageContent: {
1140
+ messageSubject: "same subject",
1141
+ androidContent: {
1142
+ title: "old android title",
1143
+ message: "same message",
1144
+ cta: { actionLink: "https://example.com" }
1145
+ },
1146
+ iosContent: {
1147
+ title: "same ios title",
1148
+ message: "same ios message",
1149
+ cta: { actionLink: "https://example.com" }
1150
+ }
1151
+ }
1152
+ }
1153
+ };
1154
+
1155
+ const newData = {
1156
+ messageSubject: "same subject",
1157
+ androidContent: {
1158
+ title: "new android title",
1159
+ message: "same message",
1160
+ cta: { actionLink: "https://example.com" }
1161
+ },
1162
+ iosContent: {
1163
+ title: "same ios title",
1164
+ message: "same ios message",
1165
+ cta: { actionLink: "https://example.com" }
1166
+ }
1167
+ };
1168
+
1169
+ const result = getTemplateDiffState(MOBILE_PUSH, oldData, newData);
1170
+
1171
+ expect(result).toBe(true);
1172
+ });
1173
+
1174
+ it("should detect changes in Android message", () => {
1175
+ const oldData = {
1176
+ transformedMessageDetails: {
1177
+ mpushMessageContent: {
1178
+ messageSubject: "same subject",
1179
+ androidContent: {
1180
+ title: "same title",
1181
+ message: "old android message",
1182
+ cta: { actionLink: "https://example.com" }
1183
+ },
1184
+ iosContent: {
1185
+ title: "same ios title",
1186
+ message: "same ios message",
1187
+ cta: { actionLink: "https://example.com" }
1188
+ }
1189
+ }
1190
+ }
1191
+ };
1192
+
1193
+ const newData = {
1194
+ messageSubject: "same subject",
1195
+ androidContent: {
1196
+ title: "same title",
1197
+ message: "new android message",
1198
+ cta: { actionLink: "https://example.com" }
1199
+ },
1200
+ iosContent: {
1201
+ title: "same ios title",
1202
+ message: "same ios message",
1203
+ cta: { actionLink: "https://example.com" }
1204
+ }
1205
+ };
1206
+
1207
+ const result = getTemplateDiffState(MOBILE_PUSH, oldData, newData);
1208
+
1209
+ expect(result).toBe(true);
1210
+ });
1211
+
1212
+ it("should detect changes in Android CTA action link", () => {
1213
+ const oldData = {
1214
+ transformedMessageDetails: {
1215
+ mpushMessageContent: {
1216
+ messageSubject: "same subject",
1217
+ androidContent: {
1218
+ title: "same title",
1219
+ message: "same message",
1220
+ cta: { actionLink: "https://example.com/old" }
1221
+ },
1222
+ iosContent: {
1223
+ title: "same ios title",
1224
+ message: "same ios message",
1225
+ cta: { actionLink: "https://example.com" }
1226
+ }
1227
+ }
1228
+ }
1229
+ };
1230
+
1231
+ const newData = {
1232
+ messageSubject: "same subject",
1233
+ androidContent: {
1234
+ title: "same title",
1235
+ message: "same message",
1236
+ cta: { actionLink: "https://example.com/new" }
1237
+ },
1238
+ iosContent: {
1239
+ title: "same ios title",
1240
+ message: "same ios message",
1241
+ cta: { actionLink: "https://example.com" }
1242
+ }
1243
+ };
1244
+
1245
+ const result = getTemplateDiffState(MOBILE_PUSH, oldData, newData);
1246
+
1247
+ expect(result).toBe(true);
1248
+ });
1249
+
1250
+ it("should detect changes in iOS title", () => {
1251
+ const oldData = {
1252
+ transformedMessageDetails: {
1253
+ mpushMessageContent: {
1254
+ messageSubject: "same subject",
1255
+ androidContent: {
1256
+ title: "same title",
1257
+ message: "same message",
1258
+ cta: { actionLink: "https://example.com" }
1259
+ },
1260
+ iosContent: {
1261
+ title: "old ios title",
1262
+ message: "same ios message",
1263
+ cta: { actionLink: "https://example.com" }
1264
+ }
1265
+ }
1266
+ }
1267
+ };
1268
+
1269
+ const newData = {
1270
+ messageSubject: "same subject",
1271
+ androidContent: {
1272
+ title: "same title",
1273
+ message: "same message",
1274
+ cta: { actionLink: "https://example.com" }
1275
+ },
1276
+ iosContent: {
1277
+ title: "new ios title",
1278
+ message: "same ios message",
1279
+ cta: { actionLink: "https://example.com" }
1280
+ }
1281
+ };
1282
+
1283
+ const result = getTemplateDiffState(MOBILE_PUSH, oldData, newData);
1284
+
1285
+ expect(result).toBe(true);
1286
+ });
1287
+
1288
+ it("should detect changes in iOS message", () => {
1289
+ const oldData = {
1290
+ transformedMessageDetails: {
1291
+ mpushMessageContent: {
1292
+ messageSubject: "same subject",
1293
+ androidContent: {
1294
+ title: "same title",
1295
+ message: "same message",
1296
+ cta: { actionLink: "https://example.com" }
1297
+ },
1298
+ iosContent: {
1299
+ title: "same ios title",
1300
+ message: "old ios message",
1301
+ cta: { actionLink: "https://example.com" }
1302
+ }
1303
+ }
1304
+ }
1305
+ };
1306
+
1307
+ const newData = {
1308
+ messageSubject: "same subject",
1309
+ androidContent: {
1310
+ title: "same title",
1311
+ message: "same message",
1312
+ cta: { actionLink: "https://example.com" }
1313
+ },
1314
+ iosContent: {
1315
+ title: "same ios title",
1316
+ message: "new ios message",
1317
+ cta: { actionLink: "https://example.com" }
1318
+ }
1319
+ };
1320
+
1321
+ const result = getTemplateDiffState(MOBILE_PUSH, oldData, newData);
1322
+
1323
+ expect(result).toBe(true);
1324
+ });
1325
+
1326
+ it("should detect changes in iOS CTA action link", () => {
1327
+ const oldData = {
1328
+ transformedMessageDetails: {
1329
+ mpushMessageContent: {
1330
+ messageSubject: "same subject",
1331
+ androidContent: {
1332
+ title: "same title",
1333
+ message: "same message",
1334
+ cta: { actionLink: "https://example.com" }
1335
+ },
1336
+ iosContent: {
1337
+ title: "same ios title",
1338
+ message: "same ios message",
1339
+ cta: { actionLink: "https://example.com/old-ios" }
1340
+ }
1341
+ }
1342
+ }
1343
+ };
1344
+
1345
+ const newData = {
1346
+ messageSubject: "same subject",
1347
+ androidContent: {
1348
+ title: "same title",
1349
+ message: "same message",
1350
+ cta: { actionLink: "https://example.com" }
1351
+ },
1352
+ iosContent: {
1353
+ title: "same ios title",
1354
+ message: "same ios message",
1355
+ cta: { actionLink: "https://example.com/new-ios" }
1356
+ }
1357
+ };
1358
+
1359
+ const result = getTemplateDiffState(MOBILE_PUSH, oldData, newData);
1360
+
1361
+ expect(result).toBe(true);
1362
+ });
1363
+
1364
+ it("should return false when push data remains the same", () => {
1365
+ const oldData = {
1366
+ transformedMessageDetails: {
1367
+ mpushMessageContent: {
1368
+ messageSubject: "same subject",
1369
+ androidContent: {
1370
+ title: "same title",
1371
+ message: "same message",
1372
+ cta: { actionLink: "https://example.com" }
1373
+ },
1374
+ iosContent: {
1375
+ title: "same ios title",
1376
+ message: "same ios message",
1377
+ cta: { actionLink: "https://example.com/ios" }
1378
+ }
1379
+ }
1380
+ }
1381
+ };
1382
+
1383
+ const newData = {
1384
+ messageSubject: "same subject",
1385
+ androidContent: {
1386
+ title: "same title",
1387
+ message: "same message",
1388
+ cta: { actionLink: "https://example.com" }
1389
+ },
1390
+ iosContent: {
1391
+ title: "same ios title",
1392
+ message: "same ios message",
1393
+ cta: { actionLink: "https://example.com/ios" }
1394
+ }
1395
+ };
1396
+
1397
+ const result = getTemplateDiffState(MOBILE_PUSH, oldData, newData);
1398
+
1399
+ expect(result).toBe(false);
1400
+ });
1401
+
1402
+ it("should handle undefined/null Android and iOS content gracefully", () => {
1403
+ const oldData = {
1404
+ transformedMessageDetails: {
1405
+ mpushMessageContent: {
1406
+ messageSubject: "subject",
1407
+ androidContent: null,
1408
+ iosContent: null
1409
+ }
1410
+ }
1411
+ };
1412
+
1413
+ const newData = {
1414
+ messageSubject: "subject",
1415
+ androidContent: {
1416
+ title: "title",
1417
+ message: "message",
1418
+ cta: { actionLink: "https://example.com" }
1419
+ },
1420
+ iosContent: {
1421
+ title: "ios title",
1422
+ message: "ios message",
1423
+ cta: { actionLink: "https://example.com/ios" }
1424
+ }
1425
+ };
1426
+
1427
+ const result = getTemplateDiffState(MOBILE_PUSH, oldData, newData);
1428
+
1429
+ expect(result).toBe(true);
1430
+ });
1431
+
1432
+ it("should handle undefined/null CTA properties gracefully", () => {
1433
+ const oldData = {
1434
+ transformedMessageDetails: {
1435
+ mpushMessageContent: {
1436
+ messageSubject: "subject",
1437
+ androidContent: {
1438
+ title: "title",
1439
+ message: "message"
1440
+ // No cta property
1441
+ },
1442
+ iosContent: {
1443
+ title: "ios title",
1444
+ message: "ios message"
1445
+ // No cta property
1446
+ }
1447
+ }
1448
+ }
1449
+ };
1450
+
1451
+ const newData = {
1452
+ messageSubject: "subject",
1453
+ androidContent: {
1454
+ title: "title",
1455
+ message: "message",
1456
+ cta: { actionLink: "https://example.com" }
1457
+ },
1458
+ iosContent: {
1459
+ title: "ios title",
1460
+ message: "ios message",
1461
+ cta: { actionLink: "https://example.com/ios" }
1462
+ }
1463
+ };
1464
+
1465
+ const result = getTemplateDiffState(MOBILE_PUSH, oldData, newData);
1466
+
1467
+ expect(result).toBe(true);
1468
+ });
1469
+ });
1470
+
1471
+ describe("WhatsApp template diff checking", () => {
1472
+ it("should detect changes in message content", () => {
1473
+ const oldData = {
1474
+ transformedMessageDetails: {
1475
+ whatsappMessageContent: {
1476
+ messageBody: "old message"
1477
+ }
1478
+ }
1479
+ };
1480
+
1481
+ const newData = {
1482
+ messageBody: "new message"
1483
+ };
1484
+
1485
+ const result = getTemplateDiffState(WHATSAPP, oldData, newData);
1486
+
1487
+ expect(result).toBe(true);
1488
+ });
1489
+
1490
+ it("should detect when new templateConfigs exist but old ones do not", () => {
1491
+ const oldData = {
1492
+ transformedMessageDetails: {
1493
+ whatsappMessageContent: {
1494
+ messageBody: "same message",
1495
+ templateConfigs: {}
1496
+ }
1497
+ }
1498
+ };
1499
+
1500
+ const newData = {
1501
+ messageBody: "same message",
1502
+ templateConfigs: {
1503
+ id: "template-123",
1504
+ name: "greeting_template"
1505
+ }
1506
+ };
1507
+
1508
+ const result = getTemplateDiffState(WHATSAPP, oldData, newData);
1509
+
1510
+ expect(result).toBe(true);
1511
+ });
1512
+
1513
+ it("should detect changes in template ID", () => {
1514
+ const oldData = {
1515
+ transformedMessageDetails: {
1516
+ whatsappMessageContent: {
1517
+ messageBody: "same message",
1518
+ templateConfigs: {
1519
+ id: "old-template-123",
1520
+ name: "same_template_name",
1521
+ template: "same_template_content",
1522
+ varMapped: { customer: "John" },
1523
+ whatsappMedia: { header: "header" },
1524
+ category: "MARKETING",
1525
+ language: "en_US",
1526
+ buttonType: "QUICK_REPLY",
1527
+ buttons: [{ text: "Yes" }]
1528
+ }
1529
+ }
1530
+ }
1531
+ };
1532
+
1533
+ const newData = {
1534
+ messageBody: "same message",
1535
+ templateConfigs: {
1536
+ id: "new-template-123",
1537
+ name: "same_template_name",
1538
+ template: "same_template_content",
1539
+ varMapped: { customer: "John" },
1540
+ whatsappMedia: { header: "header" },
1541
+ category: "MARKETING",
1542
+ language: "en_US",
1543
+ buttonType: "QUICK_REPLY",
1544
+ buttons: [{ text: "Yes" }]
1545
+ }
1546
+ };
1547
+
1548
+ const result = getTemplateDiffState(WHATSAPP, oldData, newData);
1549
+
1550
+ expect(result).toBe(true);
1551
+ });
1552
+
1553
+ it("should detect changes in template name", () => {
1554
+ const oldData = {
1555
+ transformedMessageDetails: {
1556
+ whatsappMessageContent: {
1557
+ messageBody: "same message",
1558
+ templateConfigs: {
1559
+ id: "same-template-123",
1560
+ name: "old_template_name",
1561
+ template: "same_template_content"
1562
+ }
1563
+ }
1564
+ }
1565
+ };
1566
+
1567
+ const newData = {
1568
+ messageBody: "same message",
1569
+ templateConfigs: {
1570
+ id: "same-template-123",
1571
+ name: "new_template_name",
1572
+ template: "same_template_content"
1573
+ }
1574
+ };
1575
+
1576
+ const result = getTemplateDiffState(WHATSAPP, oldData, newData);
1577
+
1578
+ expect(result).toBe(true);
1579
+ });
1580
+
1581
+ it("should detect changes in template content", () => {
1582
+ const oldData = {
1583
+ transformedMessageDetails: {
1584
+ whatsappMessageContent: {
1585
+ messageBody: "same message",
1586
+ templateConfigs: {
1587
+ id: "same-template-123",
1588
+ name: "same_template_name",
1589
+ template: "old_template_content"
1590
+ }
1591
+ }
1592
+ }
1593
+ };
1594
+
1595
+ const newData = {
1596
+ messageBody: "same message",
1597
+ templateConfigs: {
1598
+ id: "same-template-123",
1599
+ name: "same_template_name",
1600
+ template: "new_template_content"
1601
+ }
1602
+ };
1603
+
1604
+ const result = getTemplateDiffState(WHATSAPP, oldData, newData);
1605
+
1606
+ expect(result).toBe(true);
1607
+ });
1608
+
1609
+ it("should detect changes in varMapped", () => {
1610
+ const oldData = {
1611
+ transformedMessageDetails: {
1612
+ whatsappMessageContent: {
1613
+ messageBody: "same message",
1614
+ templateConfigs: {
1615
+ id: "same-template-123",
1616
+ name: "same_template_name",
1617
+ template: "same_template_content",
1618
+ varMapped: { customer: "Old Name", product: "Old Product" }
1619
+ }
1620
+ }
1621
+ }
1622
+ };
1623
+
1624
+ const newData = {
1625
+ messageBody: "same message",
1626
+ templateConfigs: {
1627
+ id: "same-template-123",
1628
+ name: "same_template_name",
1629
+ template: "same_template_content",
1630
+ varMapped: { customer: "New Name", product: "New Product" }
1631
+ }
1632
+ };
1633
+
1634
+ const result = getTemplateDiffState(WHATSAPP, oldData, newData);
1635
+
1636
+ expect(result).toBe(true);
1637
+ });
1638
+
1639
+ it("should detect changes in whatsappMedia", () => {
1640
+ const oldData = {
1641
+ transformedMessageDetails: {
1642
+ whatsappMessageContent: {
1643
+ messageBody: "same message",
1644
+ templateConfigs: {
1645
+ id: "same-template-123",
1646
+ name: "same_template_name",
1647
+ template: "same_template_content",
1648
+ varMapped: { customer: "Same Name" },
1649
+ whatsappMedia: {
1650
+ header: "Old Header",
1651
+ footer: "Old Footer"
1652
+ }
1653
+ }
1654
+ }
1655
+ }
1656
+ };
1657
+
1658
+ const newData = {
1659
+ messageBody: "same message",
1660
+ templateConfigs: {
1661
+ id: "same-template-123",
1662
+ name: "same_template_name",
1663
+ template: "same_template_content",
1664
+ varMapped: { customer: "Same Name" },
1665
+ whatsappMedia: {
1666
+ header: "New Header",
1667
+ footer: "New Footer"
1668
+ }
1669
+ }
1670
+ };
1671
+
1672
+ const result = getTemplateDiffState(WHATSAPP, oldData, newData);
1673
+
1674
+ expect(result).toBe(true);
1675
+ });
1676
+
1677
+ it("should detect changes in category", () => {
1678
+ const oldData = {
1679
+ transformedMessageDetails: {
1680
+ whatsappMessageContent: {
1681
+ messageBody: "same message",
1682
+ templateConfigs: {
1683
+ id: "same-template-123",
1684
+ name: "same_template_name",
1685
+ category: "MARKETING"
1686
+ }
1687
+ }
1688
+ }
1689
+ };
1690
+
1691
+ const newData = {
1692
+ messageBody: "same message",
1693
+ templateConfigs: {
1694
+ id: "same-template-123",
1695
+ name: "same_template_name",
1696
+ category: "UTILITY"
1697
+ }
1698
+ };
1699
+
1700
+ const result = getTemplateDiffState(WHATSAPP, oldData, newData);
1701
+
1702
+ expect(result).toBe(true);
1703
+ });
1704
+
1705
+ it("should detect changes in language", () => {
1706
+ const oldData = {
1707
+ transformedMessageDetails: {
1708
+ whatsappMessageContent: {
1709
+ messageBody: "same message",
1710
+ templateConfigs: {
1711
+ id: "same-template-123",
1712
+ name: "same_template_name",
1713
+ language: "en_US"
1714
+ }
1715
+ }
1716
+ }
1717
+ };
1718
+
1719
+ const newData = {
1720
+ messageBody: "same message",
1721
+ templateConfigs: {
1722
+ id: "same-template-123",
1723
+ name: "same_template_name",
1724
+ language: "es_ES"
1725
+ }
1726
+ };
1727
+
1728
+ const result = getTemplateDiffState(WHATSAPP, oldData, newData);
1729
+
1730
+ expect(result).toBe(true);
1731
+ });
1732
+
1733
+ it("should detect changes in buttonType", () => {
1734
+ const oldData = {
1735
+ transformedMessageDetails: {
1736
+ whatsappMessageContent: {
1737
+ messageBody: "same message",
1738
+ templateConfigs: {
1739
+ id: "same-template-123",
1740
+ name: "same_template_name",
1741
+ buttonType: "QUICK_REPLY"
1742
+ }
1743
+ }
1744
+ }
1745
+ };
1746
+
1747
+ const newData = {
1748
+ messageBody: "same message",
1749
+ templateConfigs: {
1750
+ id: "same-template-123",
1751
+ name: "same_template_name",
1752
+ buttonType: "CALL_TO_ACTION"
1753
+ }
1754
+ };
1755
+
1756
+ const result = getTemplateDiffState(WHATSAPP, oldData, newData);
1757
+
1758
+ expect(result).toBe(true);
1759
+ });
1760
+
1761
+ it("should detect changes in buttons array", () => {
1762
+ const oldData = {
1763
+ transformedMessageDetails: {
1764
+ whatsappMessageContent: {
1765
+ messageBody: "same message",
1766
+ templateConfigs: {
1767
+ id: "same-template-123",
1768
+ name: "same_template_name",
1769
+ buttons: [
1770
+ { text: "Yes", type: "REPLY" },
1771
+ { text: "No", type: "REPLY" }
1772
+ ]
1773
+ }
1774
+ }
1775
+ }
1776
+ };
1777
+
1778
+ const newData = {
1779
+ messageBody: "same message",
1780
+ templateConfigs: {
1781
+ id: "same-template-123",
1782
+ name: "same_template_name",
1783
+ buttons: [
1784
+ { text: "Yes", type: "REPLY" },
1785
+ { text: "No", type: "REPLY" },
1786
+ { text: "Maybe", type: "REPLY" }
1787
+ ]
1788
+ }
1789
+ };
1790
+
1791
+ const result = getTemplateDiffState(WHATSAPP, oldData, newData);
1792
+
1793
+ expect(result).toBe(true);
1794
+ });
1795
+
1796
+ it("should detect changes in accountId", () => {
1797
+ const oldData = {
1798
+ transformedMessageDetails: {
1799
+ whatsappMessageContent: {
1800
+ messageBody: "same message",
1801
+ accountId: "old-account-123"
1802
+ }
1803
+ }
1804
+ };
1805
+
1806
+ const newData = {
1807
+ messageBody: "same message",
1808
+ accountId: "new-account-123"
1809
+ };
1810
+
1811
+ const result = getTemplateDiffState(WHATSAPP, oldData, newData);
1812
+
1813
+ expect(result).toBe(true);
1814
+ });
1815
+
1816
+ it("should detect changes in sourceAccountIdentifier", () => {
1817
+ const oldData = {
1818
+ transformedMessageDetails: {
1819
+ whatsappMessageContent: {
1820
+ messageBody: "same message",
1821
+ sourceAccountIdentifier: "old-identifier"
1822
+ }
1823
+ }
1824
+ };
1825
+
1826
+ const newData = {
1827
+ messageBody: "same message",
1828
+ sourceAccountIdentifier: "new-identifier"
1829
+ };
1830
+
1831
+ const result = getTemplateDiffState(WHATSAPP, oldData, newData);
1832
+
1833
+ expect(result).toBe(true);
1834
+ });
1835
+
1836
+ it("should return false when WhatsApp content is the same", () => {
1837
+ const oldData = {
1838
+ transformedMessageDetails: {
1839
+ whatsappMessageContent: {
1840
+ messageBody: "same message",
1841
+ accountId: "same-account",
1842
+ templateConfigs: {
1843
+ id: "same-template-123",
1844
+ name: "same_template_name",
1845
+ template: "same_template_content",
1846
+ varMapped: { customer: "John" },
1847
+ category: "MARKETING",
1848
+ language: "en_US",
1849
+ buttonType: "QUICK_REPLY",
1850
+ buttons: [{ text: "Yes" }]
1851
+ }
1852
+ }
1853
+ }
1854
+ };
1855
+
1856
+ const newData = {
1857
+ messageBody: "same message",
1858
+ accountId: "same-account",
1859
+ templateConfigs: {
1860
+ id: "same-template-123",
1861
+ name: "same_template_name",
1862
+ template: "same_template_content",
1863
+ varMapped: { customer: "John" },
1864
+ category: "MARKETING",
1865
+ language: "en_US",
1866
+ buttonType: "QUICK_REPLY",
1867
+ buttons: [{ text: "Yes" }]
1868
+ }
1869
+ };
1870
+
1871
+ const result = getTemplateDiffState(WHATSAPP, oldData, newData);
1872
+
1873
+ expect(result).toBe(false);
1874
+ });
1875
+ });
1876
+
1877
+ describe("Zalo template diff checking", () => {
1878
+ it("should detect changes in accountId", () => {
1879
+ const oldData = {
1880
+ transformedMessageDetails: {
1881
+ zaloMessageContent: {
1882
+ accountId: "old-account-123",
1883
+ token: "same-token"
1884
+ }
1885
+ }
1886
+ };
1887
+
1888
+ const newData = {
1889
+ accountId: "new-account-123",
1890
+ token: "same-token"
1891
+ };
1892
+
1893
+ const result = getTemplateDiffState(ZALO, oldData, newData);
1894
+
1895
+ expect(result).toBe(true);
1896
+ });
1897
+
1898
+ it("should detect changes in token", () => {
1899
+ const oldData = {
1900
+ transformedMessageDetails: {
1901
+ zaloMessageContent: {
1902
+ accountId: "same-account",
1903
+ token: "old-token"
1904
+ }
1905
+ }
1906
+ };
1907
+
1908
+ const newData = {
1909
+ accountId: "same-account",
1910
+ token: "new-token"
1911
+ };
1912
+
1913
+ const result = getTemplateDiffState(ZALO, oldData, newData);
1914
+
1915
+ expect(result).toBe(true);
1916
+ });
1917
+
1918
+ it("should detect when new templateConfigs exist but old ones do not", () => {
1919
+ const oldData = {
1920
+ transformedMessageDetails: {
1921
+ zaloMessageContent: {
1922
+ accountId: "same-account",
1923
+ token: "same-token",
1924
+ templateConfigs: {}
1925
+ }
1926
+ }
1927
+ };
1928
+
1929
+ const newData = {
1930
+ accountId: "same-account",
1931
+ token: "same-token",
1932
+ templateConfigs: {
1933
+ id: "template-123",
1934
+ name: "greeting_template"
1935
+ }
1936
+ };
1937
+
1938
+ const result = getTemplateDiffState(ZALO, oldData, newData);
1939
+
1940
+ expect(result).toBe(true);
1941
+ });
1942
+
1943
+ it("should detect changes in template ID", () => {
1944
+ const oldData = {
1945
+ transformedMessageDetails: {
1946
+ zaloMessageContent: {
1947
+ accountId: "same-account",
1948
+ token: "same-token",
1949
+ templateConfigs: {
1950
+ id: "old-template-123",
1951
+ name: "same_template_name",
1952
+ template: "same_template_content",
1953
+ varMapped: { customer: "John" }
1954
+ }
1955
+ }
1956
+ }
1957
+ };
1958
+
1959
+ const newData = {
1960
+ accountId: "same-account",
1961
+ token: "same-token",
1962
+ templateConfigs: {
1963
+ id: "new-template-123",
1964
+ name: "same_template_name",
1965
+ template: "same_template_content",
1966
+ varMapped: { customer: "John" }
1967
+ }
1968
+ };
1969
+
1970
+ const result = getTemplateDiffState(ZALO, oldData, newData);
1971
+
1972
+ expect(result).toBe(true);
1973
+ });
1974
+
1975
+ it("should detect changes in template name", () => {
1976
+ const oldData = {
1977
+ transformedMessageDetails: {
1978
+ zaloMessageContent: {
1979
+ accountId: "same-account",
1980
+ token: "same-token",
1981
+ templateConfigs: {
1982
+ id: "same-template-123",
1983
+ name: "old_template_name",
1984
+ template: "same_template_content"
1985
+ }
1986
+ }
1987
+ }
1988
+ };
1989
+
1990
+ const newData = {
1991
+ accountId: "same-account",
1992
+ token: "same-token",
1993
+ templateConfigs: {
1994
+ id: "same-template-123",
1995
+ name: "new_template_name",
1996
+ template: "same_template_content"
1997
+ }
1998
+ };
1999
+
2000
+ const result = getTemplateDiffState(ZALO, oldData, newData);
2001
+
2002
+ expect(result).toBe(true);
2003
+ });
2004
+
2005
+ it("should detect changes in template content", () => {
2006
+ const oldData = {
2007
+ transformedMessageDetails: {
2008
+ zaloMessageContent: {
2009
+ accountId: "same-account",
2010
+ token: "same-token",
2011
+ templateConfigs: {
2012
+ id: "same-template-123",
2013
+ name: "same_template_name",
2014
+ template: "old_template_content"
2015
+ }
2016
+ }
2017
+ }
2018
+ };
2019
+
2020
+ const newData = {
2021
+ accountId: "same-account",
2022
+ token: "same-token",
2023
+ templateConfigs: {
2024
+ id: "same-template-123",
2025
+ name: "same_template_name",
2026
+ template: "new_template_content"
2027
+ }
2028
+ };
2029
+
2030
+ const result = getTemplateDiffState(ZALO, oldData, newData);
2031
+
2032
+ expect(result).toBe(true);
2033
+ });
2034
+
2035
+ it("should detect changes in varMapped", () => {
2036
+ const oldData = {
2037
+ transformedMessageDetails: {
2038
+ zaloMessageContent: {
2039
+ accountId: "same-account",
2040
+ token: "same-token",
2041
+ templateConfigs: {
2042
+ id: "same-template-123",
2043
+ name: "same_template_name",
2044
+ template: "same_template_content",
2045
+ varMapped: { customer: "Old Name", product: "Old Product" }
2046
+ }
2047
+ }
2048
+ }
2049
+ };
2050
+
2051
+ const newData = {
2052
+ accountId: "same-account",
2053
+ token: "same-token",
2054
+ templateConfigs: {
2055
+ id: "same-template-123",
2056
+ name: "same_template_name",
2057
+ template: "same_template_content",
2058
+ varMapped: { customer: "New Name", product: "New Product" }
2059
+ }
2060
+ };
2061
+
2062
+ const result = getTemplateDiffState(ZALO, oldData, newData);
2063
+
2064
+ expect(result).toBe(true);
2065
+ });
2066
+
2067
+ it("should return false when Zalo content is the same", () => {
2068
+ const oldData = {
2069
+ transformedMessageDetails: {
2070
+ zaloMessageContent: {
2071
+ accountId: "same-account",
2072
+ token: "same-token",
2073
+ templateConfigs: {
2074
+ id: "same-template-123",
2075
+ name: "same_template_name",
2076
+ template: "same_template_content",
2077
+ varMapped: { customer: "John" }
2078
+ }
2079
+ }
2080
+ }
2081
+ };
2082
+
2083
+ const newData = {
2084
+ accountId: "same-account",
2085
+ token: "same-token",
2086
+ templateConfigs: {
2087
+ id: "same-template-123",
2088
+ name: "same_template_name",
2089
+ template: "same_template_content",
2090
+ varMapped: { customer: "John" }
2091
+ }
2092
+ };
2093
+
2094
+ const result = getTemplateDiffState(ZALO, oldData, newData);
2095
+
2096
+ expect(result).toBe(false);
2097
+ });
2098
+
2099
+ it("should handle undefined/null values gracefully", () => {
2100
+ // Both values undefined
2101
+ expect(
2102
+ getTemplateDiffState(
2103
+ ZALO,
2104
+ { transformedMessageDetails: { zaloMessageContent: {} } },
2105
+ {}
2106
+ )
2107
+ ).toBe(false);
2108
+
2109
+ // Old value has no templateConfigs, new value has templateConfigs
2110
+ expect(
2111
+ getTemplateDiffState(
2112
+ ZALO,
2113
+ {
2114
+ transformedMessageDetails: {
2115
+ zaloMessageContent: { accountId: "acc", token: "token" }
2116
+ }
2117
+ },
2118
+ {
2119
+ accountId: "acc",
2120
+ token: "token",
2121
+ templateConfigs: { id: "id", name: "name" }
2122
+ }
2123
+ )
2124
+ ).toBe(true);
2125
+ });
2126
+ });
2127
+ });