@capillarytech/creatives-library 8.0.264 → 8.0.265

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 (158) hide show
  1. package/constants/unified.js +0 -1
  2. package/package.json +1 -1
  3. package/services/api.js +0 -5
  4. package/utils/common.js +0 -6
  5. package/utils/tagValidations.js +1 -2
  6. package/utils/tests/transformerUtils.test.js +0 -297
  7. package/utils/transformerUtils.js +0 -40
  8. package/v2Components/CapImageUpload/constants.js +0 -2
  9. package/v2Components/CapImageUpload/index.js +16 -65
  10. package/v2Components/CapImageUpload/index.scss +1 -4
  11. package/v2Components/CapImageUpload/messages.js +1 -5
  12. package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +2 -2
  13. package/v2Components/FormBuilder/index.js +8 -8
  14. package/v2Containers/App/constants.js +0 -5
  15. package/v2Containers/CreativesContainer/SlideBoxContent.js +2 -57
  16. package/v2Containers/CreativesContainer/SlideBoxHeader.js +0 -1
  17. package/v2Containers/CreativesContainer/constants.js +0 -3
  18. package/v2Containers/CreativesContainer/index.js +0 -168
  19. package/v2Containers/CreativesContainer/messages.js +0 -4
  20. package/v2Containers/CreativesContainer/tests/SlideBoxContent.test.js +0 -210
  21. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +0 -304
  22. package/v2Containers/Email/index.js +7 -3
  23. package/v2Containers/FTP/index.js +1 -1
  24. package/v2Containers/InApp/index.js +0 -1
  25. package/v2Containers/Line/Container/Text/index.js +0 -1
  26. package/v2Containers/MobilePushNew/index.js +0 -1
  27. package/v2Containers/Rcs/index.js +0 -3
  28. package/v2Containers/SmsTrai/Edit/index.js +0 -1
  29. package/v2Containers/Templates/ChannelTypeIllustration.js +1 -13
  30. package/v2Containers/Templates/_templates.scss +0 -205
  31. package/v2Containers/Templates/actions.js +1 -2
  32. package/v2Containers/Templates/constants.js +0 -1
  33. package/v2Containers/Templates/index.js +34 -274
  34. package/v2Containers/Templates/messages.js +0 -24
  35. package/v2Containers/Templates/reducer.js +0 -2
  36. package/v2Containers/Templates/tests/index.test.js +0 -10
  37. package/v2Containers/TemplatesV2/index.js +7 -15
  38. package/v2Containers/TemplatesV2/messages.js +0 -4
  39. package/v2Containers/Viber/index.js +0 -1
  40. package/v2Containers/Whatsapp/index.js +0 -1
  41. package/v2Containers/Zalo/index.js +0 -1
  42. package/v2Containers/Zalo/tests/index.test.js +5 -1
  43. package/utils/imageUrlUpload.js +0 -141
  44. package/v2Components/CapImageUrlUpload/constants.js +0 -26
  45. package/v2Components/CapImageUrlUpload/index.js +0 -365
  46. package/v2Components/CapImageUrlUpload/index.scss +0 -35
  47. package/v2Components/CapImageUrlUpload/messages.js +0 -47
  48. package/v2Containers/WebPush/Create/components/BrandIconSection.js +0 -108
  49. package/v2Containers/WebPush/Create/components/ButtonForm.js +0 -172
  50. package/v2Containers/WebPush/Create/components/ButtonItem.js +0 -101
  51. package/v2Containers/WebPush/Create/components/ButtonList.js +0 -145
  52. package/v2Containers/WebPush/Create/components/ButtonsLinksSection.js +0 -164
  53. package/v2Containers/WebPush/Create/components/ButtonsLinksSection.test.js +0 -463
  54. package/v2Containers/WebPush/Create/components/FormActions.js +0 -54
  55. package/v2Containers/WebPush/Create/components/FormActions.test.js +0 -163
  56. package/v2Containers/WebPush/Create/components/MediaSection.js +0 -142
  57. package/v2Containers/WebPush/Create/components/MediaSection.test.js +0 -341
  58. package/v2Containers/WebPush/Create/components/MessageSection.js +0 -103
  59. package/v2Containers/WebPush/Create/components/MessageSection.test.js +0 -268
  60. package/v2Containers/WebPush/Create/components/NotificationTitleSection.js +0 -87
  61. package/v2Containers/WebPush/Create/components/NotificationTitleSection.test.js +0 -210
  62. package/v2Containers/WebPush/Create/components/TemplateNameSection.js +0 -54
  63. package/v2Containers/WebPush/Create/components/TemplateNameSection.test.js +0 -143
  64. package/v2Containers/WebPush/Create/components/__snapshots__/ButtonsLinksSection.test.js.snap +0 -86
  65. package/v2Containers/WebPush/Create/components/__snapshots__/FormActions.test.js.snap +0 -16
  66. package/v2Containers/WebPush/Create/components/__snapshots__/MediaSection.test.js.snap +0 -41
  67. package/v2Containers/WebPush/Create/components/__snapshots__/MessageSection.test.js.snap +0 -54
  68. package/v2Containers/WebPush/Create/components/__snapshots__/NotificationTitleSection.test.js.snap +0 -37
  69. package/v2Containers/WebPush/Create/components/__snapshots__/TemplateNameSection.test.js.snap +0 -21
  70. package/v2Containers/WebPush/Create/components/_buttons.scss +0 -246
  71. package/v2Containers/WebPush/Create/components/tests/ButtonForm.test.js +0 -554
  72. package/v2Containers/WebPush/Create/components/tests/ButtonItem.test.js +0 -607
  73. package/v2Containers/WebPush/Create/components/tests/ButtonList.test.js +0 -633
  74. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonForm.test.js.snap +0 -666
  75. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonItem.test.js.snap +0 -74
  76. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonList.test.js.snap +0 -78
  77. package/v2Containers/WebPush/Create/hooks/useButtonManagement.js +0 -138
  78. package/v2Containers/WebPush/Create/hooks/useButtonManagement.test.js +0 -406
  79. package/v2Containers/WebPush/Create/hooks/useCharacterCount.js +0 -30
  80. package/v2Containers/WebPush/Create/hooks/useCharacterCount.test.js +0 -151
  81. package/v2Containers/WebPush/Create/hooks/useImageUpload.js +0 -104
  82. package/v2Containers/WebPush/Create/hooks/useImageUpload.test.js +0 -538
  83. package/v2Containers/WebPush/Create/hooks/useTagManagement.js +0 -122
  84. package/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +0 -633
  85. package/v2Containers/WebPush/Create/index.js +0 -1148
  86. package/v2Containers/WebPush/Create/index.scss +0 -134
  87. package/v2Containers/WebPush/Create/messages.js +0 -211
  88. package/v2Containers/WebPush/Create/preview/DevicePreviewContent.js +0 -228
  89. package/v2Containers/WebPush/Create/preview/NotificationContainer.js +0 -294
  90. package/v2Containers/WebPush/Create/preview/PreviewContent.js +0 -90
  91. package/v2Containers/WebPush/Create/preview/PreviewControls.js +0 -305
  92. package/v2Containers/WebPush/Create/preview/PreviewDisclaimer.js +0 -25
  93. package/v2Containers/WebPush/Create/preview/WebPushPreview.js +0 -155
  94. package/v2Containers/WebPush/Create/preview/assets/Light.svg +0 -53
  95. package/v2Containers/WebPush/Create/preview/assets/Top.svg +0 -5
  96. package/v2Containers/WebPush/Create/preview/assets/android-arrow-down.svg +0 -9
  97. package/v2Containers/WebPush/Create/preview/assets/android-arrow-up.svg +0 -9
  98. package/v2Containers/WebPush/Create/preview/assets/chrome-icon.png +0 -0
  99. package/v2Containers/WebPush/Create/preview/assets/edge-icon.png +0 -0
  100. package/v2Containers/WebPush/Create/preview/assets/firefox-icon.svg +0 -106
  101. package/v2Containers/WebPush/Create/preview/assets/iOS.svg +0 -26
  102. package/v2Containers/WebPush/Create/preview/assets/macos-arrow-down-icon.svg +0 -9
  103. package/v2Containers/WebPush/Create/preview/assets/macos-triple-dot-icon.svg +0 -9
  104. package/v2Containers/WebPush/Create/preview/assets/opera-icon.svg +0 -18
  105. package/v2Containers/WebPush/Create/preview/assets/safari-icon.svg +0 -29
  106. package/v2Containers/WebPush/Create/preview/assets/windows-close-icon.svg +0 -9
  107. package/v2Containers/WebPush/Create/preview/assets/windows-triple-dot-icon.svg +0 -9
  108. package/v2Containers/WebPush/Create/preview/components/AndroidMobileChromeHeader.js +0 -51
  109. package/v2Containers/WebPush/Create/preview/components/AndroidMobileExpanded.js +0 -145
  110. package/v2Containers/WebPush/Create/preview/components/IOSHeader.js +0 -45
  111. package/v2Containers/WebPush/Create/preview/components/NotificationExpandedContent.js +0 -68
  112. package/v2Containers/WebPush/Create/preview/components/NotificationHeader.js +0 -61
  113. package/v2Containers/WebPush/Create/preview/components/WindowsChromeExpanded.js +0 -99
  114. package/v2Containers/WebPush/Create/preview/components/tests/AndroidMobileExpanded.test.js +0 -733
  115. package/v2Containers/WebPush/Create/preview/components/tests/WindowsChromeExpanded.test.js +0 -571
  116. package/v2Containers/WebPush/Create/preview/components/tests/__snapshots__/AndroidMobileExpanded.test.js.snap +0 -85
  117. package/v2Containers/WebPush/Create/preview/components/tests/__snapshots__/WindowsChromeExpanded.test.js.snap +0 -81
  118. package/v2Containers/WebPush/Create/preview/config/notificationMappings.js +0 -50
  119. package/v2Containers/WebPush/Create/preview/constants.js +0 -637
  120. package/v2Containers/WebPush/Create/preview/notification-container.scss +0 -79
  121. package/v2Containers/WebPush/Create/preview/preview.scss +0 -358
  122. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-chrome.scss +0 -370
  123. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-edge.scss +0 -12
  124. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-firefox.scss +0 -12
  125. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-opera.scss +0 -12
  126. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-chrome.scss +0 -47
  127. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-edge.scss +0 -11
  128. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-firefox.scss +0 -11
  129. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-opera.scss +0 -11
  130. package/v2Containers/WebPush/Create/preview/styles/_base.scss +0 -207
  131. package/v2Containers/WebPush/Create/preview/styles/_ios.scss +0 -153
  132. package/v2Containers/WebPush/Create/preview/styles/_ipados.scss +0 -107
  133. package/v2Containers/WebPush/Create/preview/styles/_macos-chrome.scss +0 -101
  134. package/v2Containers/WebPush/Create/preview/styles/_windows-chrome.scss +0 -229
  135. package/v2Containers/WebPush/Create/preview/tests/DevicePreviewContent.test.js +0 -909
  136. package/v2Containers/WebPush/Create/preview/tests/NotificationContainer.test.js +0 -1081
  137. package/v2Containers/WebPush/Create/preview/tests/PreviewControls.test.js +0 -723
  138. package/v2Containers/WebPush/Create/preview/tests/WebPushPreview.test.js +0 -1327
  139. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/DevicePreviewContent.test.js.snap +0 -131
  140. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/NotificationContainer.test.js.snap +0 -112
  141. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/PreviewControls.test.js.snap +0 -144
  142. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/WebPushPreview.test.js.snap +0 -129
  143. package/v2Containers/WebPush/Create/utils/payloadBuilder.js +0 -96
  144. package/v2Containers/WebPush/Create/utils/payloadBuilder.test.js +0 -396
  145. package/v2Containers/WebPush/Create/utils/previewUtils.js +0 -89
  146. package/v2Containers/WebPush/Create/utils/urlValidation.js +0 -115
  147. package/v2Containers/WebPush/Create/utils/urlValidation.test.js +0 -449
  148. package/v2Containers/WebPush/Create/utils/validation.js +0 -76
  149. package/v2Containers/WebPush/Create/utils/validation.test.js +0 -283
  150. package/v2Containers/WebPush/actions.js +0 -60
  151. package/v2Containers/WebPush/constants.js +0 -132
  152. package/v2Containers/WebPush/index.js +0 -2
  153. package/v2Containers/WebPush/reducer.js +0 -104
  154. package/v2Containers/WebPush/sagas.js +0 -119
  155. package/v2Containers/WebPush/selectors.js +0 -65
  156. package/v2Containers/WebPush/tests/reducer.test.js +0 -863
  157. package/v2Containers/WebPush/tests/sagas.test.js +0 -566
  158. package/v2Containers/WebPush/tests/selectors.test.js +0 -960
@@ -1,283 +0,0 @@
1
- import {
2
- validateTemplateName,
3
- validateTitle,
4
- validateUrl,
5
- validateMessageContent,
6
- } from './validation';
7
- import { isValidHttpUrl } from './urlValidation';
8
-
9
- // Mock the urlValidation module
10
- jest.mock('./urlValidation', () => ({
11
- isValidHttpUrl: jest.fn(),
12
- }));
13
-
14
- // Mock the tagValidations module
15
- jest.mock('../../../../utils/tagValidations', () => ({
16
- validateTags: jest.fn(),
17
- }));
18
-
19
- // Mock the globalMessages
20
- jest.mock('../../../Cap/messages', () => ({
21
- unsupportedTagsValidationError: {
22
- defaultMessage: 'Unsupported tags: {unsupportedTags}',
23
- },
24
- unbalanacedCurlyBraces: {
25
- defaultMessage: 'Unbalanced curly braces',
26
- },
27
- }));
28
-
29
- import { validateTags } from '../../../../utils/tagValidations';
30
- import globalMessages from '../../../Cap/messages';
31
-
32
- describe('validation', () => {
33
- let mockFormatMessage;
34
- const mockMessages = {
35
- titleRequired: {
36
- defaultMessage: 'Title is required',
37
- },
38
- urlRequired: {
39
- defaultMessage: 'URL is required',
40
- },
41
- urlInvalid: {
42
- defaultMessage: 'URL is invalid',
43
- },
44
- messageRequired: {
45
- defaultMessage: 'Message is required',
46
- },
47
- };
48
-
49
- beforeEach(() => {
50
- jest.clearAllMocks();
51
- mockFormatMessage = jest.fn((message, values) => {
52
- if (values) {
53
- return message.defaultMessage.replace('{unsupportedTags}', values.unsupportedTags);
54
- }
55
- return message.defaultMessage || message;
56
- });
57
- });
58
-
59
- describe('validateTemplateName', () => {
60
- it('should return true for empty string', () => {
61
- expect(validateTemplateName('')).toBe(true);
62
- });
63
-
64
- it('should return true for whitespace-only string', () => {
65
- expect(validateTemplateName(' ')).toBe(true);
66
- });
67
-
68
- it('should return true for null', () => {
69
- expect(validateTemplateName(null)).toBe(true);
70
- });
71
-
72
- it('should return true for undefined', () => {
73
- expect(validateTemplateName(undefined)).toBe(true);
74
- });
75
-
76
- it('should return false for valid template name', () => {
77
- expect(validateTemplateName('Valid Template Name')).toBe(false);
78
- });
79
-
80
- it('should return false for template name with leading/trailing spaces that has content', () => {
81
- expect(validateTemplateName(' Valid Template ')).toBe(false);
82
- });
83
- });
84
-
85
- describe('validateTitle', () => {
86
- it('should return error message for empty string', () => {
87
- const result = validateTitle('', mockFormatMessage, mockMessages);
88
- expect(result).toBe('Title is required');
89
- expect(mockFormatMessage).toHaveBeenCalledWith(mockMessages.titleRequired);
90
- });
91
-
92
- it('should return error message for whitespace-only string', () => {
93
- const result = validateTitle(' ', mockFormatMessage, mockMessages);
94
- expect(result).toBe('Title is required');
95
- });
96
-
97
- it('should return error message for null', () => {
98
- const result = validateTitle(null, mockFormatMessage, mockMessages);
99
- expect(result).toBe('Title is required');
100
- });
101
-
102
- it('should return error message for undefined', () => {
103
- const result = validateTitle(undefined, mockFormatMessage, mockMessages);
104
- expect(result).toBe('Title is required');
105
- });
106
-
107
- it('should return empty string for valid title', () => {
108
- const result = validateTitle('Valid Title', mockFormatMessage, mockMessages);
109
- expect(result).toBe('');
110
- });
111
-
112
- it('should return empty string for title with content after trimming', () => {
113
- const result = validateTitle(' Valid Title ', mockFormatMessage, mockMessages);
114
- expect(result).toBe('');
115
- });
116
- });
117
-
118
- describe('validateUrl', () => {
119
- beforeEach(() => {
120
- isValidHttpUrl.mockClear();
121
- });
122
-
123
- it('should return error message for empty string', () => {
124
- const result = validateUrl('', mockFormatMessage, mockMessages);
125
- expect(result).toBe('URL is required');
126
- expect(mockFormatMessage).toHaveBeenCalledWith(mockMessages.urlRequired);
127
- expect(isValidHttpUrl).not.toHaveBeenCalled();
128
- });
129
-
130
- it('should return error message for whitespace-only string', () => {
131
- const result = validateUrl(' ', mockFormatMessage, mockMessages);
132
- expect(result).toBe('URL is required');
133
- });
134
-
135
- it('should return error message for null', () => {
136
- const result = validateUrl(null, mockFormatMessage, mockMessages);
137
- expect(result).toBe('URL is required');
138
- });
139
-
140
- it('should return error message for undefined', () => {
141
- const result = validateUrl(undefined, mockFormatMessage, mockMessages);
142
- expect(result).toBe('URL is required');
143
- });
144
-
145
- it('should return error message for invalid URL', () => {
146
- isValidHttpUrl.mockReturnValue(false);
147
- const result = validateUrl('not-a-url', mockFormatMessage, mockMessages);
148
- expect(result).toBe('URL is invalid');
149
- expect(mockFormatMessage).toHaveBeenCalledWith(mockMessages.urlInvalid);
150
- expect(isValidHttpUrl).toHaveBeenCalledWith('not-a-url');
151
- });
152
-
153
- it('should return empty string for valid URL', () => {
154
- isValidHttpUrl.mockReturnValue(true);
155
- const result = validateUrl('https://example.com', mockFormatMessage, mockMessages);
156
- expect(result).toBe('');
157
- expect(isValidHttpUrl).toHaveBeenCalledWith('https://example.com');
158
- });
159
-
160
- it('should pass URL with whitespace to isValidHttpUrl without trimming', () => {
161
- isValidHttpUrl.mockReturnValue(true);
162
- const result = validateUrl(' https://example.com ', mockFormatMessage, mockMessages);
163
- expect(result).toBe('');
164
- // Contract: validateUrl delegates to isValidHttpUrl with original (untrimmed) value
165
- expect(isValidHttpUrl).toHaveBeenCalledWith(' https://example.com ');
166
- });
167
- });
168
-
169
- describe('validateMessageContent', () => {
170
- const mockValidationConfig = {
171
- tagsParam: [],
172
- injectedTagsParams: [],
173
- location: {},
174
- tagModule: '',
175
- eventContextTags: [],
176
- };
177
-
178
- beforeEach(() => {
179
- validateTags.mockClear();
180
- });
181
-
182
- it('should return error message for empty string', () => {
183
- const result = validateMessageContent('', mockFormatMessage, mockMessages, mockValidationConfig);
184
- expect(result).toBe('Message is required');
185
- expect(mockFormatMessage).toHaveBeenCalledWith(mockMessages.messageRequired);
186
- expect(validateTags).not.toHaveBeenCalled();
187
- });
188
-
189
- it('should return error message for whitespace-only string', () => {
190
- const result = validateMessageContent(' ', mockFormatMessage, mockMessages, mockValidationConfig);
191
- expect(result).toBe('Message is required');
192
- });
193
-
194
- it('should return error message for null', () => {
195
- const result = validateMessageContent(null, mockFormatMessage, mockMessages, mockValidationConfig);
196
- expect(result).toBe('Message is required');
197
- });
198
-
199
- it('should return error message for undefined', () => {
200
- const result = validateMessageContent(undefined, mockFormatMessage, mockMessages, mockValidationConfig);
201
- expect(result).toBe('Message is required');
202
- });
203
-
204
- it('should return empty string for valid message without tags', () => {
205
- validateTags.mockReturnValue({});
206
- const result = validateMessageContent('Valid message', mockFormatMessage, mockMessages, mockValidationConfig);
207
- expect(result).toBe('');
208
- expect(validateTags).toHaveBeenCalledWith({
209
- content: 'Valid message',
210
- ...mockValidationConfig,
211
- });
212
- });
213
-
214
- it('should return error message for unsupported tags', () => {
215
- validateTags.mockReturnValue({
216
- unsupportedTags: ['tag1', 'tag2'],
217
- });
218
- const result = validateMessageContent('Message with {tag1} and {tag2}', mockFormatMessage, mockMessages, mockValidationConfig);
219
- expect(result).toBe('Unsupported tags: tag1, tag2');
220
- expect(mockFormatMessage).toHaveBeenCalledWith(globalMessages.unsupportedTagsValidationError, {
221
- unsupportedTags: 'tag1, tag2',
222
- });
223
- });
224
-
225
- it('should return error message for unbalanced curly braces', () => {
226
- validateTags.mockReturnValue({
227
- isBraceError: true,
228
- });
229
- const result = validateMessageContent('Message with {unclosed', mockFormatMessage, mockMessages, mockValidationConfig);
230
- expect(result).toBe('Unbalanced curly braces');
231
- expect(mockFormatMessage).toHaveBeenCalledWith(globalMessages.unbalanacedCurlyBraces);
232
- });
233
-
234
- it('should return error message for both unsupported tags and brace error (unsupported tags takes precedence)', () => {
235
- validateTags.mockReturnValue({
236
- unsupportedTags: ['tag1'],
237
- isBraceError: true,
238
- });
239
- const result = validateMessageContent('Message with {tag1}', mockFormatMessage, mockMessages, mockValidationConfig);
240
- expect(result).toBe('Unsupported tags: tag1');
241
- });
242
-
243
- it('should pass validation config to validateTags', () => {
244
- const customConfig = {
245
- tagsParam: [{ id: 1, name: 'Tag1' }],
246
- injectedTagsParams: [{ id: 2, name: 'Tag2' }],
247
- location: { query: { type: 'test' } },
248
- tagModule: 'custom',
249
- eventContextTags: [{ id: 3, name: 'Tag3' }],
250
- };
251
- validateTags.mockReturnValue({});
252
- validateMessageContent('Valid message', mockFormatMessage, mockMessages, customConfig);
253
- expect(validateTags).toHaveBeenCalledWith({
254
- content: 'Valid message',
255
- ...customConfig,
256
- });
257
- });
258
-
259
- it('should handle validateTags returning null', () => {
260
- validateTags.mockReturnValue(null);
261
- const result = validateMessageContent('Valid message', mockFormatMessage, mockMessages, mockValidationConfig);
262
- expect(result).toBe('');
263
- });
264
-
265
- it('should handle validateTags returning undefined', () => {
266
- validateTags.mockReturnValue(undefined);
267
- const result = validateMessageContent('Valid message', mockFormatMessage, mockMessages, mockValidationConfig);
268
- expect(result).toBe('');
269
- });
270
-
271
- it('should pass message with whitespace to validateTags without trimming', () => {
272
- validateTags.mockReturnValue({});
273
- const result = validateMessageContent(' Valid message ', mockFormatMessage, mockMessages, mockValidationConfig);
274
- expect(result).toBe('');
275
- // Contract: validateMessageContent delegates to validateTags with original (untrimmed) value
276
- expect(validateTags).toHaveBeenCalledWith({
277
- content: ' Valid message ',
278
- ...mockValidationConfig,
279
- });
280
- });
281
- });
282
- });
283
-
@@ -1,60 +0,0 @@
1
- /*
2
- *
3
- * WebPush actions
4
- *
5
- */
6
-
7
- import * as types from './constants';
8
-
9
- export function createTemplate(template, callback, meta) {
10
- return {
11
- type: types.CREATE_TEMPLATE_REQUEST,
12
- template,
13
- callback,
14
- meta,
15
- };
16
- }
17
-
18
- export function clearCreateResponse() {
19
- return {
20
- type: types.CLEAR_CREATE_RESPONSE_REQUEST,
21
- };
22
- }
23
-
24
- export function editTemplate(template, callback) {
25
- return {
26
- type: types.EDIT_TEMPLATE_REQUEST,
27
- template,
28
- callback,
29
- };
30
- }
31
-
32
- export function clearEditResponse() {
33
- return {
34
- type: types.CLEAR_EDIT_RESPONSE_REQUEST,
35
- };
36
- }
37
-
38
- export function defaultAction() {
39
- return {
40
- type: types.DEFAULT_ACTION,
41
- };
42
- }
43
-
44
- export function uploadWebPushAsset(file, type, fileParams, templateType) {
45
- return {
46
- type: types.UPLOAD_WEBPUSH_ASSET_REQUEST,
47
- file,
48
- assetType: type,
49
- fileParams,
50
- templateType,
51
- };
52
- }
53
-
54
- export function clearWebPushAsset(templateType) {
55
- return {
56
- type: types.CLEAR_WEBPUSH_ASSET,
57
- templateType,
58
- };
59
- }
60
-
@@ -1,132 +0,0 @@
1
- export const DEFAULT_ACTION = 'app/v2Containers/WebPush/DEFAULT_ACTION';
2
-
3
- export const CREATE_TEMPLATE_REQUEST = 'app/v2Containers/WebPush/Create/CREATE_TEMPLATE_REQUEST';
4
- export const CREATE_TEMPLATE_SUCCESS = 'app/v2Containers/WebPush/Create/CREATE_TEMPLATE_SUCCESS';
5
- export const CREATE_TEMPLATE_FAILURE = 'app/v2Containers/WebPush/Create/CREATE_TEMPLATE_FAILURE';
6
-
7
- export const CLEAR_CREATE_RESPONSE_REQUEST = 'app/v2Containers/WebPush/Create/CLEAR_CREATE_RESPONSE_REQUEST';
8
- export const CLEAR_CREATE_RESPONSE_SUCCESS = 'app/v2Containers/WebPush/Create/CLEAR_CREATE_RESPONSE_SUCCESS';
9
- export const CLEAR_CREATE_RESPONSE_FAILURE = 'app/v2Containers/WebPush/Create/CLEAR_CREATE_RESPONSE_FAILURE';
10
-
11
- export const EDIT_TEMPLATE_REQUEST = 'app/v2Containers/WebPush/Edit/EDIT_TEMPLATE_REQUEST';
12
- export const EDIT_TEMPLATE_SUCCESS = 'app/v2Containers/WebPush/Edit/EDIT_TEMPLATE_SUCCESS';
13
- export const EDIT_TEMPLATE_FAILURE = 'app/v2Containers/WebPush/Edit/EDIT_TEMPLATE_FAILURE';
14
-
15
- export const CLEAR_EDIT_RESPONSE_REQUEST = 'app/v2Containers/WebPush/Edit/CLEAR_EDIT_RESPONSE_REQUEST';
16
- export const CLEAR_EDIT_RESPONSE_SUCCESS = 'app/v2Containers/WebPush/Edit/CLEAR_EDIT_RESPONSE_SUCCESS';
17
- export const CLEAR_EDIT_RESPONSE_FAILURE = 'app/v2Containers/WebPush/Edit/CLEAR_EDIT_RESPONSE_FAILURE';
18
-
19
- // Media Types
20
- export const WEBPUSH_MEDIA_TYPES = {
21
- NONE: "NONE",
22
- IMAGE: "IMAGE",
23
- };
24
-
25
- export const WEBPUSH_MEDIA_TYPES_OPTIONS = [
26
- { label: "None", value: WEBPUSH_MEDIA_TYPES.NONE },
27
- { label: "Image", value: WEBPUSH_MEDIA_TYPES.IMAGE },
28
- ];
29
-
30
- // Image Upload Constants
31
- export const ALLOWED_IMAGE_EXTENSIONS_REGEX = /\.(jpe?g|png)$/i;
32
- export const WEBPUSH_IMG_SIZE = 5000000; // 5MB
33
-
34
- // Note: image width/height validation will be ignored for the web push channel inside CapImageUpload
35
- export const WEBPUSH_RECOMMENDED_DIMENSIONS = [
36
- { width: 1440, height: 720 },
37
- { width: 512, height: 256 },
38
- ];
39
-
40
- // Brand Icon Options
41
- export const BRAND_ICON_OPTIONS = {
42
- DONT_SHOW: 'DONT_SHOW',
43
- UPLOAD_IMAGE: 'UPLOAD_IMAGE',
44
- ADD_IMAGE_URL: 'ADD_IMAGE_URL',
45
- };
46
-
47
- // Brand Icon Upload Constants
48
- export const WEBPUSH_BRAND_ICON_SIZE = 1000000; // 1MB
49
- // Note: image width/height validation will be ignored for the web push channel inside CapImageUpload
50
- export const WEBPUSH_BRAND_ICON_RECOMMENDED_DIMENSIONS = [
51
- { width: 192, height: 192 },
52
- { width: 256, height: 256 },
53
- ];
54
-
55
- // Image Upload Methods
56
- export const IMAGE_UPLOAD_METHODS = {
57
- UPLOAD_IMAGE: 'UPLOAD_IMAGE',
58
- ADD_IMAGE_URL: 'ADD_IMAGE_URL',
59
- };
60
-
61
- // Upload Asset Actions
62
- const prefix = "app/v2Containers/WebPush";
63
- export const UPLOAD_WEBPUSH_ASSET_REQUEST = `${prefix}/UPLOAD_WEBPUSH_ASSET_REQUEST`;
64
- export const UPLOAD_WEBPUSH_ASSET_SUCCESS = `${prefix}/UPLOAD_WEBPUSH_ASSET_SUCCESS`;
65
- export const UPLOAD_WEBPUSH_ASSET_FAILURE = `${prefix}/UPLOAD_WEBPUSH_ASSET_FAILURE`;
66
- export const CLEAR_WEBPUSH_ASSET = `${prefix}/CLEAR_WEBPUSH_ASSET`;
67
-
68
- // Upload Field Identifiers
69
- export const UPLOAD_FIELD_TYPES = {
70
- IMAGE: 'image',
71
- BRAND_ICON: 'brandIcon',
72
- };
73
-
74
- // Button Types
75
- export const WEBPUSH_BUTTON_TYPES = {
76
- PRIMARY: 'primary',
77
- SECONDARY: 'secondary',
78
- };
79
-
80
- // OnClick Behaviour Options
81
- export const ON_CLICK_BEHAVIOUR_OPTIONS = {
82
- SITE_URL: 'SITE_URL',
83
- REDIRECT_TO_URL: 'REDIRECT_TO_URL',
84
- };
85
-
86
- // Action Types
87
- export const ACTION_TYPES = {
88
- URL: 'URL',
89
- SITE_URL: 'SITE_URL',
90
- };
91
-
92
- // WebPush Content Field Names
93
- // Field names used in template data structure (versions.base.content.webpush)
94
- export const WEBPUSH_CONTENT_FIELDS = {
95
- TITLE: 'title',
96
- MESSAGE: 'message',
97
- IMAGE: 'image',
98
- BRAND_ICON: 'brandIcon',
99
- MEDIA_TYPE: 'mediaType',
100
- ON_CLICK_ACTION: 'onClickAction',
101
- CTAS: 'ctas',
102
- };
103
-
104
- // Template Data Path Constants
105
- export const WEBPUSH_TEMPLATE_PATHS = {
106
- CONTENT: 'versions.base.content.webpush',
107
- NAME: 'name',
108
- };
109
-
110
- // Character Count Configuration
111
- export const SHOW_CHARACTER_COUNT = true;
112
-
113
- // Maximum Character Limits for Web Push Fields
114
- export const NOTIFICATION_TITLE_MAX_LENGTH = 65;
115
- export const MESSAGE_MAX_LENGTH = 240;
116
- export const BUTTON_TEXT_MAX_LENGTH = 20;
117
-
118
- // URL Validation Constants
119
- export const SUPPORTED_PROTOCOLS = new Set(['http:', 'https:']);
120
- export const HTTP_URL_PATTERN = /^https?:\/\/.+/i;
121
- // Pattern to ensure URL has a TLD (Top Level Domain): protocol://domain.tld
122
- // Requires at least one dot in the domain part, followed by 2+ word characters
123
- // before path separator (/), query (?), hash (#), port (:), or end of string
124
- export const TLD_PATTERN = /^https?:\/\/[^/?#:]+\.\w{2,}(?:\/|$|\?|#|:)/i;
125
-
126
- // Utility Constants
127
- // Stable empty array to prevent unnecessary re-renders when used as default prop values
128
- export const EMPTY_ARRAY = [];
129
-
130
- export const EXTERNAL_URL = 'EXTERNAL_URL';
131
- export const SITE_URL = 'SITE_URL';
132
- export const URL = 'URL';
@@ -1,2 +0,0 @@
1
- export { default } from './Create';
2
-
@@ -1,104 +0,0 @@
1
- /*
2
- *
3
- * WebPush reducer
4
- *
5
- */
6
-
7
- import { fromJS } from "immutable";
8
- import * as types from "./constants";
9
-
10
- const initialState = fromJS({
11
- createTemplateInProgress: false,
12
- response: {},
13
- createTemplateErrorMessage: "",
14
- editTemplateInProgress: false,
15
- editResponse: {},
16
- editTemplateErrorMessage: "",
17
- uploadedAssetData: {},
18
- uploadAssetSuccess: false,
19
- assetUploading: false,
20
- });
21
-
22
- export function webPushReducer(state = initialState, action) {
23
- // Handle null or undefined action
24
- if (!action || typeof action !== 'object') {
25
- return state;
26
- }
27
-
28
- switch (action.type) {
29
- case types.DEFAULT_ACTION:
30
- return state;
31
- case types.CREATE_TEMPLATE_REQUEST:
32
- return state
33
- .set("createTemplateInProgress", true)
34
- .set("createTemplateError", false)
35
- .set("createTemplateErrorMessage", fromJS(""));
36
- case types.CREATE_TEMPLATE_SUCCESS:
37
- return state
38
- .set("createTemplateInProgress", false)
39
- .set("response", action.data)
40
- .set(
41
- "createTemplateError",
42
- action.statusCode !== undefined && action.statusCode > 300
43
- );
44
- case types.CREATE_TEMPLATE_FAILURE:
45
- return state
46
- .set("createTemplateInProgress", false)
47
- .set("createTemplateError", true)
48
- .set("createTemplateErrorMessage", fromJS(action.error));
49
- case types.CLEAR_CREATE_RESPONSE_REQUEST:
50
- return state.set("response", {});
51
- case types.EDIT_TEMPLATE_REQUEST:
52
- return state
53
- .set("editTemplateInProgress", true)
54
- .set("editTemplateError", false)
55
- .set("editTemplateErrorMessage", fromJS(""));
56
- case types.EDIT_TEMPLATE_SUCCESS:
57
- return state
58
- .set("editTemplateInProgress", false)
59
- .set("editResponse", action.data)
60
- .set(
61
- "editTemplateError",
62
- action.statusCode !== undefined && action.statusCode > 300
63
- );
64
- case types.EDIT_TEMPLATE_FAILURE:
65
- return state
66
- .set("editTemplateInProgress", false)
67
- .set("editTemplateError", true)
68
- .set("editTemplateErrorMessage", fromJS(action.error || action.errorMsg || ""));
69
- case types.CLEAR_EDIT_RESPONSE_REQUEST:
70
- return state.set("editResponse", {});
71
- case types.UPLOAD_WEBPUSH_ASSET_REQUEST:
72
- return state.set("uploadAssetSuccess", false).set("assetUploading", true);
73
- case types.UPLOAD_WEBPUSH_ASSET_SUCCESS:
74
- return state
75
- .set(
76
- "uploadAssetSuccess",
77
- action.statusCode !== undefined &&
78
- action.statusCode !== "" &&
79
- action.statusCode < 300,
80
- )
81
- .set("assetUploading", false)
82
- .set(
83
- action.templateType !== undefined
84
- ? `uploadedAssetData${action.templateType}`
85
- : "uploadedAssetData",
86
- action.data,
87
- );
88
- case types.UPLOAD_WEBPUSH_ASSET_FAILURE:
89
- return state
90
- .set("uploadAssetSuccess", false)
91
- .set("assetUploading", false);
92
- case types.CLEAR_WEBPUSH_ASSET:
93
- return state.delete(
94
- action.templateType !== undefined
95
- ? `uploadedAssetData${action.templateType}`
96
- : "uploadedAssetData",
97
- );
98
- default:
99
- return state;
100
- }
101
- }
102
-
103
- export default webPushReducer;
104
-
@@ -1,119 +0,0 @@
1
- import {
2
- call, put, takeLatest, all,
3
- } from 'redux-saga/effects';
4
- import * as Api from '../../services/api';
5
- import * as types from './constants';
6
-
7
- export function* createTemplate({ template, callback, meta }) {
8
- let errorMsg;
9
- try {
10
- const result = yield call(Api.createWebPushTemplate, template);
11
- if (result.status && result.status.code >= 400) {
12
- errorMsg = result.message;
13
- throw errorMsg;
14
- }
15
- if (result.message) {
16
- errorMsg = result.message;
17
- }
18
- // Merge meta into response if provided
19
- const responseWithMeta = meta ? { ...result.response, meta } : result.response;
20
- if (callback) {
21
- yield call(callback, responseWithMeta);
22
- }
23
- yield put({
24
- type: types.CREATE_TEMPLATE_SUCCESS,
25
- data: responseWithMeta,
26
- statusCode: result.status ? result.status.code : '',
27
- errorMsg,
28
- });
29
- } catch (error) {
30
- yield put({ type: types.CREATE_TEMPLATE_FAILURE, error, errorMsg });
31
- }
32
- }
33
-
34
- export function* clearCreateResponse() {
35
- yield put({ type: types.CLEAR_CREATE_RESPONSE_SUCCESS });
36
- }
37
-
38
- export function* editTemplate({ template, callback }) {
39
- let errorMsg;
40
- try {
41
- const result = yield call(Api.createWebPushTemplate, template);
42
- if (result.status && result.status.code >= 400) {
43
- errorMsg = result.message;
44
- throw errorMsg;
45
- }
46
- if (result.message) {
47
- errorMsg = result.message;
48
- }
49
- if (callback) {
50
- callback(result.response, errorMsg);
51
- }
52
- yield put({
53
- type: types.EDIT_TEMPLATE_SUCCESS,
54
- data: result.response,
55
- statusCode: result.status ? result.status.code : '',
56
- errorMsg,
57
- });
58
- } catch (error) {
59
- yield put({ type: types.EDIT_TEMPLATE_FAILURE, error, errorMsg });
60
- if (callback) {
61
- callback(null, errorMsg);
62
- }
63
- }
64
- }
65
-
66
- export function* clearEditResponse() {
67
- yield put({ type: types.CLEAR_EDIT_RESPONSE_SUCCESS });
68
- }
69
-
70
- export function* uploadWebPushAsset({ file, assetType, fileParams, templateType }) {
71
- try {
72
- const result = yield call(Api.uploadFile, {
73
- file,
74
- assetType,
75
- fileParams,
76
- });
77
- yield put({
78
- type: types.UPLOAD_WEBPUSH_ASSET_SUCCESS,
79
- data: result?.response?.asset,
80
- statusCode: result?.status?.code || '',
81
- templateType,
82
- });
83
- } catch (error) {
84
- yield put({ type: types.UPLOAD_WEBPUSH_ASSET_FAILURE, error });
85
- }
86
- }
87
-
88
- export function* watchCreateTemplate() {
89
- yield takeLatest(types.CREATE_TEMPLATE_REQUEST, createTemplate);
90
- }
91
-
92
- export function* watchClearCreateResponse() {
93
- yield takeLatest(types.CLEAR_CREATE_RESPONSE_REQUEST, clearCreateResponse);
94
- }
95
-
96
- export function* watchEditTemplate() {
97
- yield takeLatest(types.EDIT_TEMPLATE_REQUEST, editTemplate);
98
- }
99
-
100
- export function* watchClearEditResponse() {
101
- yield takeLatest(types.CLEAR_EDIT_RESPONSE_REQUEST, clearEditResponse);
102
- }
103
-
104
- export function* watchUploadWebPushAsset() {
105
- yield takeLatest(
106
- types.UPLOAD_WEBPUSH_ASSET_REQUEST,
107
- uploadWebPushAsset,
108
- );
109
- }
110
-
111
- export default function* webPushSagas() {
112
- yield all([
113
- watchCreateTemplate(),
114
- watchClearCreateResponse(),
115
- watchEditTemplate(),
116
- watchClearEditResponse(),
117
- watchUploadWebPushAsset(),
118
- ]);
119
- }