@capillarytech/creatives-library 8.0.315 → 8.0.316-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.
- package/package.json +1 -1
- package/services/tests/getSchema.test.js +95 -0
- package/utils/tests/common.test.js +265 -323
- package/utils/tests/commonUtils.test.js +581 -0
- package/utils/tests/messageUtils.test.js +95 -0
- package/utils/tests/smsCharCount.test.js +304 -0
- package/utils/tests/smsCharCountV2.test.js +213 -10
|
@@ -0,0 +1,581 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test suite for commonUtils utility functions
|
|
3
|
+
*/
|
|
4
|
+
import {
|
|
5
|
+
apiMessageFormatHandler,
|
|
6
|
+
addBaseToTemplate,
|
|
7
|
+
isEmbeddedEditOrPreview,
|
|
8
|
+
transformCustomFieldsData,
|
|
9
|
+
isTagIncluded,
|
|
10
|
+
getChannelData,
|
|
11
|
+
validateCarouselCards,
|
|
12
|
+
hasPersonalizationTags,
|
|
13
|
+
getMessageForDevice,
|
|
14
|
+
getTitleForDevice,
|
|
15
|
+
checkForPersonalizationTokens,
|
|
16
|
+
extractContent,
|
|
17
|
+
} from '../commonUtils';
|
|
18
|
+
|
|
19
|
+
// Use actual constant values as they're defined in the source
|
|
20
|
+
const EMBEDDED = 'embedded';
|
|
21
|
+
const EDIT = 'edit';
|
|
22
|
+
const PREVIEW = 'preview';
|
|
23
|
+
|
|
24
|
+
describe('commonUtils Utility Functions', () => {
|
|
25
|
+
describe('apiMessageFormatHandler', () => {
|
|
26
|
+
it('should return a FormattedMessage component', () => {
|
|
27
|
+
const result = apiMessageFormatHandler('test.id', 'Fallback message');
|
|
28
|
+
expect(result).toBeDefined();
|
|
29
|
+
expect(result.type).toBeDefined();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should pass id and defaultMessage props', () => {
|
|
33
|
+
const result = apiMessageFormatHandler('app.test', 'Default text');
|
|
34
|
+
expect(result.props.id).toBe('app.test');
|
|
35
|
+
expect(result.props.defaultMessage).toBe('Default text');
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
describe('addBaseToTemplate', () => {
|
|
40
|
+
it('should add base from first history item if not present', () => {
|
|
41
|
+
const template = {
|
|
42
|
+
versions: {
|
|
43
|
+
history: [{ subject: 'First version', content: 'Old content' }],
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
const result = addBaseToTemplate(template);
|
|
47
|
+
|
|
48
|
+
expect(result.versions.base).toBeDefined();
|
|
49
|
+
expect(result.versions.base.subject).toBe('First version');
|
|
50
|
+
expect(result.versions.base.content).toBe('Old content');
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('should preserve existing base subject if present', () => {
|
|
54
|
+
const template = {
|
|
55
|
+
versions: {
|
|
56
|
+
base: { subject: 'Existing subject' },
|
|
57
|
+
history: [{ subject: 'History subject' }],
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
const result = addBaseToTemplate(template);
|
|
61
|
+
|
|
62
|
+
expect(result.versions.base.subject).toBe('Existing subject');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should return original template if no history', () => {
|
|
66
|
+
const template = { versions: {} };
|
|
67
|
+
const result = addBaseToTemplate(template);
|
|
68
|
+
|
|
69
|
+
expect(result).toEqual(template);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('should return original template if template is null/undefined', () => {
|
|
73
|
+
expect(addBaseToTemplate(null)).toBeNull();
|
|
74
|
+
expect(addBaseToTemplate(undefined)).toBeUndefined();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('should handle empty history array', () => {
|
|
78
|
+
const template = { versions: { history: [] } };
|
|
79
|
+
const result = addBaseToTemplate(template);
|
|
80
|
+
|
|
81
|
+
expect(result).toEqual(template);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
describe('isEmbeddedEditOrPreview', () => {
|
|
86
|
+
it('should return true for EMBEDDED with EDIT mode', () => {
|
|
87
|
+
const result = isEmbeddedEditOrPreview(EMBEDDED, EDIT);
|
|
88
|
+
expect(result).toBe(true);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('should return true for EMBEDDED with PREVIEW mode', () => {
|
|
92
|
+
const result = isEmbeddedEditOrPreview(EMBEDDED, PREVIEW);
|
|
93
|
+
expect(result).toBe(true);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('should return false for non-EMBEDDED queryType', () => {
|
|
97
|
+
const result = isEmbeddedEditOrPreview('other', EDIT);
|
|
98
|
+
expect(result).toBe(false);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('should return false for EMBEDDED with non-EDIT/PREVIEW mode', () => {
|
|
102
|
+
const result = isEmbeddedEditOrPreview(EMBEDDED, 'view');
|
|
103
|
+
expect(result).toBe(false);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
describe('transformCustomFieldsData', () => {
|
|
108
|
+
it('should transform custom fields with loyalty_registration scope', () => {
|
|
109
|
+
const customFields = {
|
|
110
|
+
field1: { name: 'firstName', scope: 'loyalty_registration' },
|
|
111
|
+
};
|
|
112
|
+
const result = transformCustomFieldsData(customFields);
|
|
113
|
+
|
|
114
|
+
expect(result['Registration custom fields']).toBeDefined();
|
|
115
|
+
expect(result['Registration custom fields'].subtags['custom_field.firstName']).toBeDefined();
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('should transform custom fields with org_custom_field scope', () => {
|
|
119
|
+
const customFields = {
|
|
120
|
+
field1: { name: 'orgField', scope: 'org_custom_field', label: 'Organization Field' },
|
|
121
|
+
};
|
|
122
|
+
const result = transformCustomFieldsData(customFields);
|
|
123
|
+
|
|
124
|
+
expect(result['Organization custom fields']).toBeDefined();
|
|
125
|
+
expect(result['Organization custom fields'].subtags['org_custom_field.orgField']).toBeDefined();
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('should transform custom fields with store_custom_fields scope', () => {
|
|
129
|
+
const customFields = {
|
|
130
|
+
field1: { name: 'storeField', scope: 'store_custom_fields' },
|
|
131
|
+
};
|
|
132
|
+
const result = transformCustomFieldsData(customFields);
|
|
133
|
+
|
|
134
|
+
expect(result['Organization custom fields']).toBeDefined();
|
|
135
|
+
expect(result['Organization custom fields'].subtags['store_custom_field.storeField']).toBeDefined();
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('should remove empty sections', () => {
|
|
139
|
+
const customFields = {
|
|
140
|
+
field1: { name: 'unknownField', scope: 'unknown_scope' },
|
|
141
|
+
};
|
|
142
|
+
const result = transformCustomFieldsData(customFields);
|
|
143
|
+
|
|
144
|
+
expect(Object.keys(result).length).toBe(0);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('should handle empty custom fields object', () => {
|
|
148
|
+
const result = transformCustomFieldsData({});
|
|
149
|
+
expect(result).toEqual({});
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('should handle multiple fields in same section', () => {
|
|
153
|
+
const customFields = {
|
|
154
|
+
field1: { name: 'field1', scope: 'loyalty_registration' },
|
|
155
|
+
field2: { name: 'field2', scope: 'loyalty_registration' },
|
|
156
|
+
};
|
|
157
|
+
const result = transformCustomFieldsData(customFields);
|
|
158
|
+
|
|
159
|
+
expect(Object.keys(result['Registration custom fields'].subtags).length).toBe(2);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
describe('isTagIncluded', () => {
|
|
164
|
+
it('should return true when value contains both {{ and }}', () => {
|
|
165
|
+
expect(isTagIncluded('Hello {{name}}')).toBe(true);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('should return false when value does not contain tags', () => {
|
|
169
|
+
expect(isTagIncluded('Hello world')).toBe(false);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('should return false for empty string', () => {
|
|
173
|
+
// isTagIncluded returns falsy value (undefined/null) for empty string
|
|
174
|
+
expect(isTagIncluded('')).toBeFalsy();
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('should return false for null or undefined', () => {
|
|
178
|
+
// isTagIncluded returns falsy value for null/undefined input
|
|
179
|
+
expect(isTagIncluded(null)).toBeFalsy();
|
|
180
|
+
expect(isTagIncluded(undefined)).toBeFalsy();
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('should return false if only opening tag present', () => {
|
|
184
|
+
expect(isTagIncluded('Hello {{ name')).toBe(false);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('should return false if only closing tag present', () => {
|
|
188
|
+
expect(isTagIncluded('Hello name}}')).toBe(false);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it('should handle multiple tags', () => {
|
|
192
|
+
expect(isTagIncluded('{{firstName}} {{lastName}}')).toBe(true);
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
describe('getChannelData', () => {
|
|
197
|
+
it('should handle EMAIL channel', () => {
|
|
198
|
+
const formData = {
|
|
199
|
+
base: {
|
|
200
|
+
en: {
|
|
201
|
+
'template-content': '<p>Email body</p>',
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
};
|
|
205
|
+
const result = getChannelData('email', formData, 'en');
|
|
206
|
+
expect(result).toBeDefined();
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it('should handle SMS channel', () => {
|
|
210
|
+
const formData = {
|
|
211
|
+
base: {
|
|
212
|
+
'sms-editor': 'Hello {{name}}',
|
|
213
|
+
},
|
|
214
|
+
'template-name': 'SMS Template',
|
|
215
|
+
};
|
|
216
|
+
const result = getChannelData('sms', formData, 'en');
|
|
217
|
+
expect(result).toContain('Hello');
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('should return stringified JSON for unknown channel', () => {
|
|
221
|
+
const formData = { someData: 'value' };
|
|
222
|
+
const result = getChannelData('unknown', formData, 'en');
|
|
223
|
+
expect(result).toBe(JSON.stringify(formData));
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
it('should be case insensitive for channel', () => {
|
|
227
|
+
const formData = {
|
|
228
|
+
base: {
|
|
229
|
+
en: {
|
|
230
|
+
'template-content': '<p>Email</p>',
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
const result = getChannelData('EMAIL', formData, 'en');
|
|
235
|
+
expect(result).toBeDefined();
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it('should handle missing form data gracefully', () => {
|
|
239
|
+
const result = getChannelData('sms', {}, 'en');
|
|
240
|
+
expect(result).toBeDefined();
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
describe('validateCarouselCards', () => {
|
|
245
|
+
it('should return valid when all cards are correct', () => {
|
|
246
|
+
const carouselData = [
|
|
247
|
+
{
|
|
248
|
+
bodyText: 'Card 1',
|
|
249
|
+
imageSrc: 'image1.jpg',
|
|
250
|
+
buttons: [{ isSaved: true }],
|
|
251
|
+
},
|
|
252
|
+
];
|
|
253
|
+
const result = validateCarouselCards(carouselData, 'image');
|
|
254
|
+
|
|
255
|
+
expect(result.isValid).toBe(true);
|
|
256
|
+
expect(result.reasons).toHaveLength(0);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it('should detect missing body text', () => {
|
|
260
|
+
const carouselData = [
|
|
261
|
+
{
|
|
262
|
+
bodyText: '',
|
|
263
|
+
imageSrc: 'image.jpg',
|
|
264
|
+
},
|
|
265
|
+
];
|
|
266
|
+
const result = validateCarouselCards(carouselData, 'image');
|
|
267
|
+
|
|
268
|
+
expect(result.isValid).toBe(false);
|
|
269
|
+
expect(result.reasons[0]).toContain('bodyText empty');
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it('should detect missing image when media type is image', () => {
|
|
273
|
+
const carouselData = [
|
|
274
|
+
{
|
|
275
|
+
bodyText: 'Card text',
|
|
276
|
+
imageSrc: '',
|
|
277
|
+
},
|
|
278
|
+
];
|
|
279
|
+
const result = validateCarouselCards(carouselData, 'image');
|
|
280
|
+
|
|
281
|
+
expect(result.isValid).toBe(false);
|
|
282
|
+
expect(result.reasons[0]).toContain('imageSrc missing');
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
it('should detect missing video when media type is video', () => {
|
|
286
|
+
const carouselData = [
|
|
287
|
+
{
|
|
288
|
+
bodyText: 'Card text',
|
|
289
|
+
videoSrc: '',
|
|
290
|
+
},
|
|
291
|
+
];
|
|
292
|
+
const result = validateCarouselCards(carouselData, 'video');
|
|
293
|
+
|
|
294
|
+
expect(result.isValid).toBe(false);
|
|
295
|
+
expect(result.reasons[0]).toContain('videoSrc missing');
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
it('should detect unsaved buttons', () => {
|
|
299
|
+
const carouselData = [
|
|
300
|
+
{
|
|
301
|
+
bodyText: 'Card text',
|
|
302
|
+
imageSrc: 'image.jpg',
|
|
303
|
+
buttons: [{ isSaved: false }],
|
|
304
|
+
},
|
|
305
|
+
];
|
|
306
|
+
const result = validateCarouselCards(carouselData, 'image');
|
|
307
|
+
|
|
308
|
+
expect(result.isValid).toBe(false);
|
|
309
|
+
expect(result.reasons[0]).toContain('some buttons not saved');
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
it('should handle empty carousel data', () => {
|
|
313
|
+
const result = validateCarouselCards([], 'image');
|
|
314
|
+
|
|
315
|
+
expect(result.isValid).toBe(true);
|
|
316
|
+
expect(result.reasons).toHaveLength(0);
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
it('should be case insensitive for media type', () => {
|
|
320
|
+
const carouselData = [
|
|
321
|
+
{
|
|
322
|
+
bodyText: 'Card text',
|
|
323
|
+
imageSrc: 'image.jpg',
|
|
324
|
+
},
|
|
325
|
+
];
|
|
326
|
+
const result = validateCarouselCards(carouselData, 'IMAGE');
|
|
327
|
+
|
|
328
|
+
expect(result.isValid).toBe(true);
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
it('should use custom constants for media types', () => {
|
|
332
|
+
const carouselData = [
|
|
333
|
+
{
|
|
334
|
+
bodyText: 'Card text',
|
|
335
|
+
imageSrc: 'image.jpg',
|
|
336
|
+
},
|
|
337
|
+
];
|
|
338
|
+
const result = validateCarouselCards(
|
|
339
|
+
carouselData,
|
|
340
|
+
'photo',
|
|
341
|
+
{ imageConstant: 'PHOTO' }
|
|
342
|
+
);
|
|
343
|
+
|
|
344
|
+
expect(result.isValid).toBe(true);
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
it('should detect body errors', () => {
|
|
348
|
+
const carouselData = [
|
|
349
|
+
{
|
|
350
|
+
bodyError: 'Invalid format',
|
|
351
|
+
bodyText: 'Card text',
|
|
352
|
+
imageSrc: 'image.jpg',
|
|
353
|
+
},
|
|
354
|
+
];
|
|
355
|
+
const result = validateCarouselCards(carouselData, 'image');
|
|
356
|
+
|
|
357
|
+
expect(result.isValid).toBe(false);
|
|
358
|
+
expect(result.reasons[0]).toContain('bodyError');
|
|
359
|
+
});
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
describe('hasPersonalizationTags', () => {
|
|
363
|
+
it('should return true for liquid tags {{ }}', () => {
|
|
364
|
+
expect(hasPersonalizationTags('Hello {{name}}')).toBe(true);
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
it('should return true for bracket tags [ ]', () => {
|
|
368
|
+
expect(hasPersonalizationTags('Hello [user.name]')).toBe(true);
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
it('should return false for no tags', () => {
|
|
372
|
+
expect(hasPersonalizationTags('Hello world')).toBe(false);
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
it('should return false for empty string', () => {
|
|
376
|
+
// hasPersonalizationTags returns falsy value for empty string
|
|
377
|
+
expect(hasPersonalizationTags('')).toBeFalsy();
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
it('should handle nested tags', () => {
|
|
381
|
+
expect(hasPersonalizationTags('{{outer {{inner}}}}')).toBe(true);
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
it('should return false for only opening tags', () => {
|
|
385
|
+
expect(hasPersonalizationTags('Hello {{ world')).toBe(false);
|
|
386
|
+
});
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
describe('getMessageForDevice', () => {
|
|
390
|
+
it('should extract message for specific device', () => {
|
|
391
|
+
const templateData = {
|
|
392
|
+
versions: {
|
|
393
|
+
android: {
|
|
394
|
+
base: {
|
|
395
|
+
expandableDetails: {
|
|
396
|
+
message: 'Android message',
|
|
397
|
+
},
|
|
398
|
+
},
|
|
399
|
+
},
|
|
400
|
+
},
|
|
401
|
+
};
|
|
402
|
+
const result = getMessageForDevice(templateData, 'android');
|
|
403
|
+
|
|
404
|
+
expect(result).toBe('Android message');
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
it('should return undefined if message not found', () => {
|
|
408
|
+
const templateData = {
|
|
409
|
+
versions: {
|
|
410
|
+
android: {
|
|
411
|
+
base: {},
|
|
412
|
+
},
|
|
413
|
+
},
|
|
414
|
+
};
|
|
415
|
+
const result = getMessageForDevice(templateData, 'android');
|
|
416
|
+
|
|
417
|
+
expect(result).toBeUndefined();
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
it('should handle undefined templateData', () => {
|
|
421
|
+
const result = getMessageForDevice(undefined, 'android');
|
|
422
|
+
expect(result).toBeUndefined();
|
|
423
|
+
});
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
describe('getTitleForDevice', () => {
|
|
427
|
+
it('should extract title for specific device', () => {
|
|
428
|
+
const templateData = {
|
|
429
|
+
versions: {
|
|
430
|
+
ios: {
|
|
431
|
+
base: {
|
|
432
|
+
title: 'iOS title',
|
|
433
|
+
},
|
|
434
|
+
},
|
|
435
|
+
},
|
|
436
|
+
};
|
|
437
|
+
const result = getTitleForDevice(templateData, 'ios');
|
|
438
|
+
|
|
439
|
+
expect(result).toBe('iOS title');
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
it('should return empty string if title not found', () => {
|
|
443
|
+
const templateData = {
|
|
444
|
+
versions: {
|
|
445
|
+
ios: {
|
|
446
|
+
base: {},
|
|
447
|
+
},
|
|
448
|
+
},
|
|
449
|
+
};
|
|
450
|
+
const result = getTitleForDevice(templateData, 'ios');
|
|
451
|
+
|
|
452
|
+
expect(result).toBe('');
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
it('should handle undefined templateData', () => {
|
|
456
|
+
const result = getTitleForDevice(undefined, 'ios');
|
|
457
|
+
expect(result).toBe('');
|
|
458
|
+
});
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
describe('checkForPersonalizationTokens', () => {
|
|
462
|
+
it('should detect liquid tags {{ }}', () => {
|
|
463
|
+
const formData = {
|
|
464
|
+
tab1: {
|
|
465
|
+
field1: 'Hello {{name}}',
|
|
466
|
+
},
|
|
467
|
+
};
|
|
468
|
+
const result = checkForPersonalizationTokens(formData);
|
|
469
|
+
|
|
470
|
+
expect(result).toBe(true);
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
it('should detect bracket tags [ ]', () => {
|
|
474
|
+
const formData = {
|
|
475
|
+
tab1: {
|
|
476
|
+
field1: 'Hello [user.name]',
|
|
477
|
+
},
|
|
478
|
+
};
|
|
479
|
+
const result = checkForPersonalizationTokens(formData);
|
|
480
|
+
|
|
481
|
+
expect(result).toBe(true);
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
it('should return false when no tokens present', () => {
|
|
485
|
+
const formData = {
|
|
486
|
+
tab1: {
|
|
487
|
+
field1: 'Hello world',
|
|
488
|
+
},
|
|
489
|
+
};
|
|
490
|
+
const result = checkForPersonalizationTokens(formData);
|
|
491
|
+
|
|
492
|
+
expect(result).toBe(false);
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
it('should handle empty form data', () => {
|
|
496
|
+
const result = checkForPersonalizationTokens({});
|
|
497
|
+
expect(result).toBe(false);
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
it('should handle null form data', () => {
|
|
501
|
+
const result = checkForPersonalizationTokens(null);
|
|
502
|
+
expect(result).toBe(false);
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
it('should search through multiple tabs', () => {
|
|
506
|
+
const formData = {
|
|
507
|
+
tab1: { field1: 'No tokens' },
|
|
508
|
+
tab2: { field2: 'Hello {{user}}' },
|
|
509
|
+
};
|
|
510
|
+
const result = checkForPersonalizationTokens(formData);
|
|
511
|
+
|
|
512
|
+
expect(result).toBe(true);
|
|
513
|
+
});
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
describe('extractContent', () => {
|
|
517
|
+
it('should extract content from regular platform data', () => {
|
|
518
|
+
const platformData = {
|
|
519
|
+
title: 'Title',
|
|
520
|
+
message: 'Message',
|
|
521
|
+
};
|
|
522
|
+
const result = extractContent(platformData);
|
|
523
|
+
|
|
524
|
+
expect(result).toContain('Title');
|
|
525
|
+
expect(result).toContain('Message');
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
it('should extract content with CTAs', () => {
|
|
529
|
+
const platformData = {
|
|
530
|
+
title: 'Title',
|
|
531
|
+
message: 'Message',
|
|
532
|
+
ctas: [
|
|
533
|
+
{ text: 'Button 1' },
|
|
534
|
+
{ actionLink: 'Link 2' },
|
|
535
|
+
],
|
|
536
|
+
};
|
|
537
|
+
const result = extractContent(platformData);
|
|
538
|
+
|
|
539
|
+
expect(result).toContain('Button 1');
|
|
540
|
+
expect(result).toContain('Link 2');
|
|
541
|
+
});
|
|
542
|
+
|
|
543
|
+
it('should handle null platform data', () => {
|
|
544
|
+
const result = extractContent(null);
|
|
545
|
+
expect(result).toBe('');
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
it('should extract from BEE editor with string html', () => {
|
|
549
|
+
const platformData = {
|
|
550
|
+
title: 'Title',
|
|
551
|
+
isBEEeditor: true,
|
|
552
|
+
beeHtml: '<p>HTML content</p>',
|
|
553
|
+
};
|
|
554
|
+
const result = extractContent(platformData);
|
|
555
|
+
|
|
556
|
+
expect(result).toContain('HTML content');
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
it('should extract from BEE editor with object html', () => {
|
|
560
|
+
const platformData = {
|
|
561
|
+
title: 'Title',
|
|
562
|
+
isBEEeditor: true,
|
|
563
|
+
beeHtml: { value: '<p>HTML content</p>' },
|
|
564
|
+
};
|
|
565
|
+
const result = extractContent(platformData);
|
|
566
|
+
|
|
567
|
+
expect(result).toContain('HTML content');
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
it('should filter out empty values', () => {
|
|
571
|
+
const platformData = {
|
|
572
|
+
title: 'Title',
|
|
573
|
+
message: '',
|
|
574
|
+
ctas: [{ text: '' }],
|
|
575
|
+
};
|
|
576
|
+
const result = extractContent(platformData);
|
|
577
|
+
|
|
578
|
+
expect(result).toBe('Title');
|
|
579
|
+
});
|
|
580
|
+
});
|
|
581
|
+
});
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test suite for messageUtils
|
|
3
|
+
*/
|
|
4
|
+
import { getMessageObject } from '../messageUtils';
|
|
5
|
+
|
|
6
|
+
describe('messageUtils', () => {
|
|
7
|
+
describe('getMessageObject', () => {
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
jest.clearAllMocks();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('should create a message object with all parameters', () => {
|
|
13
|
+
const result = getMessageObject('success', 'Operation completed', false);
|
|
14
|
+
|
|
15
|
+
expect(result).toHaveProperty('id');
|
|
16
|
+
expect(result).toHaveProperty('text', 'Operation completed');
|
|
17
|
+
expect(result).toHaveProperty('type', 'success');
|
|
18
|
+
expect(result).toHaveProperty('hideProgressBar', false);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('should create a message object with type and message only', () => {
|
|
22
|
+
const result = getMessageObject('error', 'Something went wrong');
|
|
23
|
+
|
|
24
|
+
expect(result.type).toBe('error');
|
|
25
|
+
expect(result.text).toBe('Something went wrong');
|
|
26
|
+
expect(result.hideProgressBar).toBe(false);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('should create a message object with hideProgressBar set to true', () => {
|
|
30
|
+
const result = getMessageObject('info', 'Loading', true);
|
|
31
|
+
|
|
32
|
+
expect(result.type).toBe('info');
|
|
33
|
+
expect(result.text).toBe('Loading');
|
|
34
|
+
expect(result.hideProgressBar).toBe(true);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('should generate a numeric id string based on Date.now()', () => {
|
|
38
|
+
const mockTime = 1612267539410;
|
|
39
|
+
jest.spyOn(Date, 'now').mockReturnValue(mockTime);
|
|
40
|
+
|
|
41
|
+
const result = getMessageObject('success', 'Test');
|
|
42
|
+
|
|
43
|
+
expect(result.id).toBe(`${mockTime}`);
|
|
44
|
+
expect(/^\d+$/.test(result.id)).toBe(true);
|
|
45
|
+
|
|
46
|
+
Date.now.mockRestore();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should generate different ids for consecutive calls', () => {
|
|
50
|
+
jest.spyOn(Date, 'now')
|
|
51
|
+
.mockReturnValueOnce(1000)
|
|
52
|
+
.mockReturnValueOnce(2000);
|
|
53
|
+
|
|
54
|
+
const result1 = getMessageObject('success', 'First');
|
|
55
|
+
const result2 = getMessageObject('success', 'Second');
|
|
56
|
+
|
|
57
|
+
expect(result1.id).not.toBe(result2.id);
|
|
58
|
+
expect(result1.id).toBe('1000');
|
|
59
|
+
expect(result2.id).toBe('2000');
|
|
60
|
+
|
|
61
|
+
Date.now.mockRestore();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('should handle empty message string', () => {
|
|
65
|
+
const result = getMessageObject('warning', '');
|
|
66
|
+
|
|
67
|
+
expect(result.text).toBe('');
|
|
68
|
+
expect(result.type).toBe('warning');
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('should support different message types', () => {
|
|
72
|
+
const types = ['success', 'error', 'warning', 'info', 'default'];
|
|
73
|
+
|
|
74
|
+
types.forEach((type) => {
|
|
75
|
+
const result = getMessageObject(type, 'Test message');
|
|
76
|
+
expect(result.type).toBe(type);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('should handle long message strings', () => {
|
|
81
|
+
const longMessage = 'A'.repeat(1000);
|
|
82
|
+
const result = getMessageObject('info', longMessage);
|
|
83
|
+
|
|
84
|
+
expect(result.text).toBe(longMessage);
|
|
85
|
+
expect(result.text.length).toBe(1000);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('should handle special characters in message', () => {
|
|
89
|
+
const specialMessage = 'Error: "Failed" & <Retry>';
|
|
90
|
+
const result = getMessageObject('error', specialMessage);
|
|
91
|
+
|
|
92
|
+
expect(result.text).toBe(specialMessage);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
});
|