@capillarytech/creatives-library 8.0.353-alpha.2 → 8.0.353-alpha.5
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/v2Components/CommonTestAndPreview/UnifiedPreview/PreviewHeader.js +17 -0
- package/v2Components/CommonTestAndPreview/UnifiedPreview/WebPushPreviewContent.js +169 -0
- package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +70 -0
- package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +44 -5
- package/v2Components/CommonTestAndPreview/constants.js +2 -0
- package/v2Components/CommonTestAndPreview/index.js +51 -2
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/PreviewHeader.test.js +159 -0
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/WebPushPreviewContent.test.js +522 -0
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +255 -0
- package/v2Components/CommonTestAndPreview/tests/constants.test.js +2 -1
- package/v2Components/CommonTestAndPreview/tests/index.test.js +194 -0
- package/v2Components/FormBuilder/index.js +10 -48
- package/v2Components/TestAndPreviewSlidebox/index.js +2 -2
- package/v2Containers/App/constants.js +3 -0
- package/v2Containers/App/tests/constants.test.js +61 -0
- package/v2Containers/CreativesContainer/index.js +25 -61
- package/v2Containers/Email/index.js +2 -33
- package/v2Containers/Templates/index.js +68 -2
- package/v2Containers/Templates/tests/webpush.test.js +375 -0
- package/v2Containers/WebPush/Create/index.js +91 -8
- package/v2Containers/WebPush/Create/index.scss +7 -0
- package/v2Containers/WebPush/Create/tests/getTemplateContent.test.js +338 -0
- package/v2Containers/WebPush/Create/tests/testAndPreviewIntegration.test.js +325 -0
|
@@ -45,6 +45,8 @@ import {
|
|
|
45
45
|
ACTION_TYPES,
|
|
46
46
|
NOTIFICATION_TITLE_MAX_LENGTH,
|
|
47
47
|
MESSAGE_MAX_LENGTH,
|
|
48
|
+
EXTERNAL_URL,
|
|
49
|
+
SITE_URL,
|
|
48
50
|
} from '../constants';
|
|
49
51
|
import * as actions from '../actions';
|
|
50
52
|
import {
|
|
@@ -73,6 +75,9 @@ import {
|
|
|
73
75
|
import './index.scss';
|
|
74
76
|
import { WEBPUSH } from '../../CreativesContainer/constants';
|
|
75
77
|
import { isAiContentBotDisabled } from '../../../utils/common';
|
|
78
|
+
import TestAndPreviewSlidebox from '../../../v2Components/TestAndPreviewSlidebox';
|
|
79
|
+
import creativesMessages from '../../CreativesContainer/messages';
|
|
80
|
+
import CapButton from '@capillarytech/cap-ui-library/CapButton';
|
|
76
81
|
|
|
77
82
|
// Memoized TagList wrapper components for better performance
|
|
78
83
|
const MemoizedTagList = memo(({
|
|
@@ -182,6 +187,7 @@ const WebPushCreate = ({
|
|
|
182
187
|
const [redirectUrlError, setRedirectUrlError] = useState('');
|
|
183
188
|
const [activeUploadField, setActiveUploadField] = useState(null);
|
|
184
189
|
const [templateIdError, setTemplateIdError] = useState('');
|
|
190
|
+
const [showTestAndPreviewSlidebox, setShowTestAndPreviewSlidebox] = useState(false);
|
|
185
191
|
|
|
186
192
|
// Refs
|
|
187
193
|
const titleCountRef = useRef(null);
|
|
@@ -569,6 +575,67 @@ const WebPushCreate = ({
|
|
|
569
575
|
return !(templateNameInvalid || titleValidation || messageValidation);
|
|
570
576
|
};
|
|
571
577
|
|
|
578
|
+
const getTemplateContent = useCallback(() => {
|
|
579
|
+
let cta = null;
|
|
580
|
+
if (onClickBehaviour === ON_CLICK_BEHAVIOUR_OPTIONS.REDIRECT_TO_URL && redirectUrl) {
|
|
581
|
+
cta = { type: EXTERNAL_URL, actionLink: redirectUrl.trim() };
|
|
582
|
+
} else if (onClickBehaviour === ON_CLICK_BEHAVIOUR_OPTIONS.SITE_URL && websiteLink) {
|
|
583
|
+
cta = { type: SITE_URL, actionLink: websiteLink };
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
const hasImage = mediaType === WEBPUSH_MEDIA_TYPES.IMAGE && imageSrc;
|
|
587
|
+
const hasCtas = buttons && buttons.length > 0;
|
|
588
|
+
let expandableDetails = null;
|
|
589
|
+
if (hasImage || hasCtas) {
|
|
590
|
+
expandableDetails = {
|
|
591
|
+
media: hasImage ? [{ url: imageSrc, type: WEBPUSH_MEDIA_TYPES.IMAGE }] : [],
|
|
592
|
+
ctas: hasCtas ? buttons.map((btn) => ({
|
|
593
|
+
type: EXTERNAL_URL,
|
|
594
|
+
action: '',
|
|
595
|
+
title: btn.text || '',
|
|
596
|
+
actionLink: btn.url || '',
|
|
597
|
+
})) : [],
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
const iconImageUrl = brandIconOption !== BRAND_ICON_OPTIONS.DONT_SHOW && brandIconSrc ? brandIconSrc : undefined;
|
|
602
|
+
|
|
603
|
+
return {
|
|
604
|
+
channel: WEBPUSH,
|
|
605
|
+
accountId,
|
|
606
|
+
content: {
|
|
607
|
+
title: notificationTitle || '',
|
|
608
|
+
message: message || '',
|
|
609
|
+
...(iconImageUrl ? { iconImageUrl } : {}),
|
|
610
|
+
...(cta ? { cta } : {}),
|
|
611
|
+
...(expandableDetails ? { expandableDetails } : {}),
|
|
612
|
+
},
|
|
613
|
+
messageSubject: templateName || notificationTitle || '',
|
|
614
|
+
offers: [],
|
|
615
|
+
};
|
|
616
|
+
}, [
|
|
617
|
+
notificationTitle,
|
|
618
|
+
message,
|
|
619
|
+
accountId,
|
|
620
|
+
mediaType,
|
|
621
|
+
imageSrc,
|
|
622
|
+
brandIconOption,
|
|
623
|
+
brandIconSrc,
|
|
624
|
+
buttons,
|
|
625
|
+
onClickBehaviour,
|
|
626
|
+
redirectUrl,
|
|
627
|
+
websiteLink,
|
|
628
|
+
templateName,
|
|
629
|
+
]);
|
|
630
|
+
|
|
631
|
+
const handleTestAndPreview = useCallback(() => {
|
|
632
|
+
setShowTestAndPreviewSlidebox(true);
|
|
633
|
+
}, []);
|
|
634
|
+
|
|
635
|
+
const handleCloseTestAndPreview = useCallback(() => {
|
|
636
|
+
setShowTestAndPreviewSlidebox(false);
|
|
637
|
+
}, []);
|
|
638
|
+
|
|
572
639
|
const isFormValid = () => {
|
|
573
640
|
const templateNameInvalid = isFullMode && validateTemplateName(templateName);
|
|
574
641
|
const titleValidation = validateTitle(notificationTitle);
|
|
@@ -1040,14 +1107,23 @@ const WebPushCreate = ({
|
|
|
1040
1107
|
formatMessage={formatMessage}
|
|
1041
1108
|
messages={messages}
|
|
1042
1109
|
/>
|
|
1043
|
-
<
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1110
|
+
<CapRow className="webpush-test-preview-action">
|
|
1111
|
+
<FormActions
|
|
1112
|
+
onSave={handleSave}
|
|
1113
|
+
isSaveDisabled={isSaveDisabled}
|
|
1114
|
+
errorText={errorText}
|
|
1115
|
+
accountErrorText={accountErrorText}
|
|
1116
|
+
formatMessage={formatMessage}
|
|
1117
|
+
messages={messages}
|
|
1118
|
+
/>
|
|
1119
|
+
<CapButton
|
|
1120
|
+
type="secondary"
|
|
1121
|
+
onClick={handleTestAndPreview}
|
|
1122
|
+
className="webpush-test-preview-btn"
|
|
1123
|
+
>
|
|
1124
|
+
{formatMessage(creativesMessages.testAndPreview)}
|
|
1125
|
+
</CapButton>
|
|
1126
|
+
</CapRow>
|
|
1051
1127
|
</CapColumn>
|
|
1052
1128
|
<CapColumn className="preview-section" span={10}>
|
|
1053
1129
|
<WebPushPreview
|
|
@@ -1059,6 +1135,13 @@ const WebPushCreate = ({
|
|
|
1059
1135
|
buttons={buttons}
|
|
1060
1136
|
/>
|
|
1061
1137
|
</CapColumn>
|
|
1138
|
+
<TestAndPreviewSlidebox
|
|
1139
|
+
show={showTestAndPreviewSlidebox}
|
|
1140
|
+
onClose={handleCloseTestAndPreview}
|
|
1141
|
+
content={getTemplateContent()}
|
|
1142
|
+
currentChannel={WEBPUSH}
|
|
1143
|
+
accountId={accountId || null}
|
|
1144
|
+
/>
|
|
1062
1145
|
</CapRow>
|
|
1063
1146
|
);
|
|
1064
1147
|
};
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for getTemplateContent logic used in WebPushCreate
|
|
3
|
+
*
|
|
4
|
+
* The getTemplateContent function (useCallback) transforms component state
|
|
5
|
+
* into a structured content object for TestAndPreviewSlidebox.
|
|
6
|
+
* Tested here as a pure function matching the exact implementation logic.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
WEBPUSH_MEDIA_TYPES,
|
|
11
|
+
BRAND_ICON_OPTIONS,
|
|
12
|
+
ON_CLICK_BEHAVIOUR_OPTIONS,
|
|
13
|
+
} from '../../constants';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Mirrors the getTemplateContent useCallback in WebPushCreate/index.js.
|
|
17
|
+
* Keep in sync if the source function changes.
|
|
18
|
+
*/
|
|
19
|
+
const getTemplateContent = ({
|
|
20
|
+
notificationTitle = '',
|
|
21
|
+
message = '',
|
|
22
|
+
accountId = null,
|
|
23
|
+
mediaType = WEBPUSH_MEDIA_TYPES.NONE,
|
|
24
|
+
imageSrc = '',
|
|
25
|
+
brandIconOption = BRAND_ICON_OPTIONS.DONT_SHOW,
|
|
26
|
+
brandIconSrc = '',
|
|
27
|
+
buttons = [],
|
|
28
|
+
onClickBehaviour = ON_CLICK_BEHAVIOUR_OPTIONS.SITE_URL,
|
|
29
|
+
redirectUrl = '',
|
|
30
|
+
websiteLink = '',
|
|
31
|
+
templateName = '',
|
|
32
|
+
} = {}) => {
|
|
33
|
+
let cta = null;
|
|
34
|
+
if (onClickBehaviour === ON_CLICK_BEHAVIOUR_OPTIONS.REDIRECT_TO_URL && redirectUrl) {
|
|
35
|
+
cta = { type: 'EXTERNAL_URL', actionLink: redirectUrl.trim() };
|
|
36
|
+
} else if (onClickBehaviour === ON_CLICK_BEHAVIOUR_OPTIONS.SITE_URL && websiteLink) {
|
|
37
|
+
cta = { type: 'SITE_URL', actionLink: websiteLink };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const hasImage = mediaType === WEBPUSH_MEDIA_TYPES.IMAGE && imageSrc;
|
|
41
|
+
const hasCtas = buttons && buttons.length > 0;
|
|
42
|
+
let expandableDetails = null;
|
|
43
|
+
if (hasImage || hasCtas) {
|
|
44
|
+
expandableDetails = {
|
|
45
|
+
media: hasImage ? [{ url: imageSrc, type: 'IMAGE' }] : [],
|
|
46
|
+
ctas: hasCtas
|
|
47
|
+
? buttons.map((btn) => ({
|
|
48
|
+
type: 'EXTERNAL_URL',
|
|
49
|
+
action: '',
|
|
50
|
+
title: btn.text || '',
|
|
51
|
+
actionLink: btn.url || '',
|
|
52
|
+
}))
|
|
53
|
+
: [],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const iconImageUrl =
|
|
58
|
+
brandIconOption !== BRAND_ICON_OPTIONS.DONT_SHOW && brandIconSrc ? brandIconSrc : undefined;
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
channel: 'WEBPUSH',
|
|
62
|
+
accountId,
|
|
63
|
+
content: {
|
|
64
|
+
title: notificationTitle || '',
|
|
65
|
+
message: message || '',
|
|
66
|
+
...(iconImageUrl ? { iconImageUrl } : {}),
|
|
67
|
+
...(cta ? { cta } : {}),
|
|
68
|
+
...(expandableDetails ? { expandableDetails } : {}),
|
|
69
|
+
},
|
|
70
|
+
messageSubject: templateName || notificationTitle || '',
|
|
71
|
+
offers: [],
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
describe('getTemplateContent (WebPushCreate)', () => {
|
|
76
|
+
describe('Basic structure', () => {
|
|
77
|
+
it('should return channel WEBPUSH', () => {
|
|
78
|
+
const result = getTemplateContent({ notificationTitle: 'T', message: 'M' });
|
|
79
|
+
expect(result.channel).toBe('WEBPUSH');
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('should include accountId', () => {
|
|
83
|
+
const result = getTemplateContent({ accountId: 'acc-123' });
|
|
84
|
+
expect(result.accountId).toBe('acc-123');
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('should return null accountId when not provided', () => {
|
|
88
|
+
const result = getTemplateContent({});
|
|
89
|
+
expect(result.accountId).toBeNull();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should include title in content', () => {
|
|
93
|
+
const result = getTemplateContent({ notificationTitle: 'Hello World' });
|
|
94
|
+
expect(result.content.title).toBe('Hello World');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should include message in content', () => {
|
|
98
|
+
const result = getTemplateContent({ message: 'Body text' });
|
|
99
|
+
expect(result.content.message).toBe('Body text');
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('should default title to empty string', () => {
|
|
103
|
+
const result = getTemplateContent({});
|
|
104
|
+
expect(result.content.title).toBe('');
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('should default message to empty string', () => {
|
|
108
|
+
const result = getTemplateContent({});
|
|
109
|
+
expect(result.content.message).toBe('');
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('should include offers as empty array', () => {
|
|
113
|
+
const result = getTemplateContent({});
|
|
114
|
+
expect(result.offers).toEqual([]);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
describe('messageSubject', () => {
|
|
119
|
+
it('should use templateName as messageSubject', () => {
|
|
120
|
+
const result = getTemplateContent({ templateName: 'My Template', notificationTitle: 'T' });
|
|
121
|
+
expect(result.messageSubject).toBe('My Template');
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('should fall back to notificationTitle when templateName is empty', () => {
|
|
125
|
+
const result = getTemplateContent({ templateName: '', notificationTitle: 'Push Title' });
|
|
126
|
+
expect(result.messageSubject).toBe('Push Title');
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('should be empty string when both templateName and notificationTitle are empty', () => {
|
|
130
|
+
const result = getTemplateContent({ templateName: '', notificationTitle: '' });
|
|
131
|
+
expect(result.messageSubject).toBe('');
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
describe('CTA - REDIRECT_TO_URL', () => {
|
|
136
|
+
it('should set EXTERNAL_URL cta when behaviour is REDIRECT_TO_URL with url', () => {
|
|
137
|
+
const result = getTemplateContent({
|
|
138
|
+
onClickBehaviour: ON_CLICK_BEHAVIOUR_OPTIONS.REDIRECT_TO_URL,
|
|
139
|
+
redirectUrl: 'https://redirect.com',
|
|
140
|
+
});
|
|
141
|
+
expect(result.content.cta).toEqual({ type: 'EXTERNAL_URL', actionLink: 'https://redirect.com' });
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('should trim redirectUrl whitespace', () => {
|
|
145
|
+
const result = getTemplateContent({
|
|
146
|
+
onClickBehaviour: ON_CLICK_BEHAVIOUR_OPTIONS.REDIRECT_TO_URL,
|
|
147
|
+
redirectUrl: ' https://redirect.com ',
|
|
148
|
+
});
|
|
149
|
+
expect(result.content.cta.actionLink).toBe('https://redirect.com');
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('should NOT set cta when REDIRECT_TO_URL but redirectUrl is empty', () => {
|
|
153
|
+
const result = getTemplateContent({
|
|
154
|
+
onClickBehaviour: ON_CLICK_BEHAVIOUR_OPTIONS.REDIRECT_TO_URL,
|
|
155
|
+
redirectUrl: '',
|
|
156
|
+
});
|
|
157
|
+
expect(result.content.cta).toBeUndefined();
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
describe('CTA - SITE_URL', () => {
|
|
162
|
+
it('should set SITE_URL cta when behaviour is SITE_URL with websiteLink', () => {
|
|
163
|
+
const result = getTemplateContent({
|
|
164
|
+
onClickBehaviour: ON_CLICK_BEHAVIOUR_OPTIONS.SITE_URL,
|
|
165
|
+
websiteLink: 'https://mysite.com',
|
|
166
|
+
});
|
|
167
|
+
expect(result.content.cta).toEqual({ type: 'SITE_URL', actionLink: 'https://mysite.com' });
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('should NOT set cta when SITE_URL but websiteLink is empty', () => {
|
|
171
|
+
const result = getTemplateContent({
|
|
172
|
+
onClickBehaviour: ON_CLICK_BEHAVIOUR_OPTIONS.SITE_URL,
|
|
173
|
+
websiteLink: '',
|
|
174
|
+
});
|
|
175
|
+
expect(result.content.cta).toBeUndefined();
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it('should NOT include cta key at all when no url configured', () => {
|
|
179
|
+
const result = getTemplateContent({
|
|
180
|
+
onClickBehaviour: ON_CLICK_BEHAVIOUR_OPTIONS.SITE_URL,
|
|
181
|
+
websiteLink: '',
|
|
182
|
+
redirectUrl: '',
|
|
183
|
+
});
|
|
184
|
+
expect(Object.keys(result.content)).not.toContain('cta');
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
describe('expandableDetails - image', () => {
|
|
189
|
+
it('should include image media when mediaType is IMAGE and imageSrc is set', () => {
|
|
190
|
+
const result = getTemplateContent({
|
|
191
|
+
mediaType: WEBPUSH_MEDIA_TYPES.IMAGE,
|
|
192
|
+
imageSrc: 'https://example.com/img.jpg',
|
|
193
|
+
});
|
|
194
|
+
expect(result.content.expandableDetails).toBeDefined();
|
|
195
|
+
expect(result.content.expandableDetails.media).toEqual([
|
|
196
|
+
{ url: 'https://example.com/img.jpg', type: 'IMAGE' },
|
|
197
|
+
]);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it('should NOT include expandableDetails when mediaType is NONE', () => {
|
|
201
|
+
const result = getTemplateContent({
|
|
202
|
+
mediaType: WEBPUSH_MEDIA_TYPES.NONE,
|
|
203
|
+
imageSrc: 'https://example.com/img.jpg',
|
|
204
|
+
});
|
|
205
|
+
expect(result.content.expandableDetails).toBeUndefined();
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it('should NOT include expandableDetails when imageSrc is empty even if mediaType is IMAGE', () => {
|
|
209
|
+
const result = getTemplateContent({
|
|
210
|
+
mediaType: WEBPUSH_MEDIA_TYPES.IMAGE,
|
|
211
|
+
imageSrc: '',
|
|
212
|
+
buttons: [],
|
|
213
|
+
});
|
|
214
|
+
expect(result.content.expandableDetails).toBeUndefined();
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
describe('expandableDetails - buttons', () => {
|
|
219
|
+
it('should include ctas when buttons are provided', () => {
|
|
220
|
+
const result = getTemplateContent({
|
|
221
|
+
buttons: [{ text: 'Click Me', url: 'https://click.com' }],
|
|
222
|
+
});
|
|
223
|
+
expect(result.content.expandableDetails).toBeDefined();
|
|
224
|
+
expect(result.content.expandableDetails.ctas).toEqual([
|
|
225
|
+
{ type: 'EXTERNAL_URL', action: '', title: 'Click Me', actionLink: 'https://click.com' },
|
|
226
|
+
]);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
it('should map multiple buttons to ctas', () => {
|
|
230
|
+
const result = getTemplateContent({
|
|
231
|
+
buttons: [
|
|
232
|
+
{ text: 'Btn1', url: 'https://a.com' },
|
|
233
|
+
{ text: 'Btn2', url: 'https://b.com' },
|
|
234
|
+
],
|
|
235
|
+
});
|
|
236
|
+
expect(result.content.expandableDetails.ctas).toHaveLength(2);
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it('should handle button with empty text and url', () => {
|
|
240
|
+
const result = getTemplateContent({
|
|
241
|
+
buttons: [{ text: '', url: '' }],
|
|
242
|
+
});
|
|
243
|
+
expect(result.content.expandableDetails.ctas[0]).toEqual({
|
|
244
|
+
type: 'EXTERNAL_URL',
|
|
245
|
+
action: '',
|
|
246
|
+
title: '',
|
|
247
|
+
actionLink: '',
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it('should NOT include expandableDetails when buttons array is empty', () => {
|
|
252
|
+
const result = getTemplateContent({ buttons: [] });
|
|
253
|
+
expect(result.content.expandableDetails).toBeUndefined();
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
describe('expandableDetails - image + buttons combined', () => {
|
|
258
|
+
it('should include both media and ctas when image and buttons present', () => {
|
|
259
|
+
const result = getTemplateContent({
|
|
260
|
+
mediaType: WEBPUSH_MEDIA_TYPES.IMAGE,
|
|
261
|
+
imageSrc: 'https://img.com/a.jpg',
|
|
262
|
+
buttons: [{ text: 'Go', url: 'https://go.com' }],
|
|
263
|
+
});
|
|
264
|
+
expect(result.content.expandableDetails.media).toHaveLength(1);
|
|
265
|
+
expect(result.content.expandableDetails.ctas).toHaveLength(1);
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
describe('brandIcon (iconImageUrl)', () => {
|
|
270
|
+
it('should include iconImageUrl when brandIconOption is not DONT_SHOW and brandIconSrc is set', () => {
|
|
271
|
+
const result = getTemplateContent({
|
|
272
|
+
brandIconOption: BRAND_ICON_OPTIONS.UPLOAD_IMAGE,
|
|
273
|
+
brandIconSrc: 'https://example.com/brand.png',
|
|
274
|
+
});
|
|
275
|
+
expect(result.content.iconImageUrl).toBe('https://example.com/brand.png');
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
it('should NOT include iconImageUrl when brandIconOption is DONT_SHOW', () => {
|
|
279
|
+
const result = getTemplateContent({
|
|
280
|
+
brandIconOption: BRAND_ICON_OPTIONS.DONT_SHOW,
|
|
281
|
+
brandIconSrc: 'https://example.com/brand.png',
|
|
282
|
+
});
|
|
283
|
+
expect(result.content.iconImageUrl).toBeUndefined();
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it('should NOT include iconImageUrl when brandIconSrc is empty', () => {
|
|
287
|
+
const result = getTemplateContent({
|
|
288
|
+
brandIconOption: BRAND_ICON_OPTIONS.UPLOAD_IMAGE,
|
|
289
|
+
brandIconSrc: '',
|
|
290
|
+
});
|
|
291
|
+
expect(result.content.iconImageUrl).toBeUndefined();
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
it('should NOT include iconImageUrl key when not applicable', () => {
|
|
295
|
+
const result = getTemplateContent({
|
|
296
|
+
brandIconOption: BRAND_ICON_OPTIONS.DONT_SHOW,
|
|
297
|
+
brandIconSrc: '',
|
|
298
|
+
});
|
|
299
|
+
expect(Object.keys(result.content)).not.toContain('iconImageUrl');
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
describe('Full payload with all fields', () => {
|
|
304
|
+
it('should build complete payload with title, message, cta, expandableDetails, iconImageUrl', () => {
|
|
305
|
+
const result = getTemplateContent({
|
|
306
|
+
notificationTitle: 'Full Title',
|
|
307
|
+
message: 'Full body',
|
|
308
|
+
accountId: 'acc-full',
|
|
309
|
+
templateName: 'Full Template',
|
|
310
|
+
mediaType: WEBPUSH_MEDIA_TYPES.IMAGE,
|
|
311
|
+
imageSrc: 'https://img.com/full.jpg',
|
|
312
|
+
brandIconOption: BRAND_ICON_OPTIONS.UPLOAD_IMAGE,
|
|
313
|
+
brandIconSrc: 'https://icon.com/full.png',
|
|
314
|
+
buttons: [{ text: 'Action', url: 'https://action.com' }],
|
|
315
|
+
onClickBehaviour: ON_CLICK_BEHAVIOUR_OPTIONS.REDIRECT_TO_URL,
|
|
316
|
+
redirectUrl: 'https://redirect.com',
|
|
317
|
+
websiteLink: '',
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
expect(result).toEqual({
|
|
321
|
+
channel: 'WEBPUSH',
|
|
322
|
+
accountId: 'acc-full',
|
|
323
|
+
content: {
|
|
324
|
+
title: 'Full Title',
|
|
325
|
+
message: 'Full body',
|
|
326
|
+
iconImageUrl: 'https://icon.com/full.png',
|
|
327
|
+
cta: { type: 'EXTERNAL_URL', actionLink: 'https://redirect.com' },
|
|
328
|
+
expandableDetails: {
|
|
329
|
+
media: [{ url: 'https://img.com/full.jpg', type: 'IMAGE' }],
|
|
330
|
+
ctas: [{ type: 'EXTERNAL_URL', action: '', title: 'Action', actionLink: 'https://action.com' }],
|
|
331
|
+
},
|
|
332
|
+
},
|
|
333
|
+
messageSubject: 'Full Template',
|
|
334
|
+
offers: [],
|
|
335
|
+
});
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
});
|