@capillarytech/creatives-library 8.0.271 → 8.0.273

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 (153) hide show
  1. package/assets/Android.png +0 -0
  2. package/assets/iOS.png +0 -0
  3. package/constants/unified.js +2 -1
  4. package/initialReducer.js +2 -0
  5. package/package.json +1 -1
  6. package/services/api.js +10 -0
  7. package/services/tests/api.test.js +34 -0
  8. package/tests/integration/TemplateCreation/TemplateCreation.integration.test.js +17 -35
  9. package/tests/integration/TemplateCreation/api-response.js +31 -1
  10. package/tests/integration/TemplateCreation/msw-handler.js +2 -0
  11. package/utils/common.js +5 -0
  12. package/utils/commonUtils.js +28 -5
  13. package/utils/imageUrlUpload.js +13 -14
  14. package/utils/tests/commonUtil.test.js +224 -0
  15. package/utils/tests/imageUrlUpload.test.js +298 -0
  16. package/utils/transformTemplateConfig.js +0 -10
  17. package/v2Components/CapDeviceContent/index.js +61 -56
  18. package/v2Components/CapTagList/index.js +6 -1
  19. package/v2Components/CapTagListWithInput/index.js +5 -1
  20. package/v2Components/CapTagListWithInput/messages.js +1 -1
  21. package/v2Components/CapWhatsappCTA/tests/index.test.js +5 -0
  22. package/v2Components/ErrorInfoNote/constants.js +1 -0
  23. package/v2Components/ErrorInfoNote/index.js +402 -72
  24. package/v2Components/ErrorInfoNote/messages.js +32 -6
  25. package/v2Components/ErrorInfoNote/style.scss +278 -6
  26. package/v2Components/FormBuilder/tests/index.test.js +13 -4
  27. package/v2Components/HtmlEditor/HTMLEditor.js +418 -99
  28. package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +870 -0
  29. package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +1882 -133
  30. package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +27 -16
  31. package/v2Components/HtmlEditor/_htmlEditor.scss +108 -45
  32. package/v2Components/HtmlEditor/_index.lazy.scss +0 -1
  33. package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +23 -102
  34. package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +148 -140
  35. package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +2 -1
  36. package/v2Components/HtmlEditor/components/DeviceToggle/index.js +3 -3
  37. package/v2Components/HtmlEditor/components/EditorToolbar/_editorToolbar.scss +9 -1
  38. package/v2Components/HtmlEditor/components/EditorToolbar/index.js +31 -6
  39. package/v2Components/HtmlEditor/components/FullscreenModal/_fullscreenModal.scss +22 -0
  40. package/v2Components/HtmlEditor/components/InAppPreviewPane/DeviceFrame.js +4 -7
  41. package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/DeviceFrame.test.js +35 -45
  42. package/v2Components/HtmlEditor/components/InAppPreviewPane/_inAppPreviewPane.scss +1 -3
  43. package/v2Components/HtmlEditor/components/InAppPreviewPane/constants.js +33 -33
  44. package/v2Components/HtmlEditor/components/InAppPreviewPane/index.js +7 -6
  45. package/v2Components/HtmlEditor/components/PreviewPane/_previewPane.scss +7 -10
  46. package/v2Components/HtmlEditor/components/PreviewPane/index.js +22 -43
  47. package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +1 -1
  48. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/_validationErrorDisplay.scss +18 -0
  49. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/index.js +36 -31
  50. package/v2Components/HtmlEditor/components/ValidationPanel/_validationPanel.scss +46 -34
  51. package/v2Components/HtmlEditor/components/ValidationPanel/constants.js +6 -0
  52. package/v2Components/HtmlEditor/components/ValidationPanel/index.js +52 -46
  53. package/v2Components/HtmlEditor/components/ValidationTabs/_validationTabs.scss +277 -0
  54. package/v2Components/HtmlEditor/components/ValidationTabs/index.js +295 -0
  55. package/v2Components/HtmlEditor/components/ValidationTabs/messages.js +51 -0
  56. package/v2Components/HtmlEditor/constants.js +45 -20
  57. package/v2Components/HtmlEditor/hooks/__tests__/useInAppContent.test.js +373 -16
  58. package/v2Components/HtmlEditor/hooks/__tests__/useValidation.test.js +351 -16
  59. package/v2Components/HtmlEditor/hooks/useEditorContent.js +5 -2
  60. package/v2Components/HtmlEditor/hooks/useInAppContent.js +88 -146
  61. package/v2Components/HtmlEditor/hooks/useValidation.js +213 -56
  62. package/v2Components/HtmlEditor/index.js +1 -1
  63. package/v2Components/HtmlEditor/messages.js +102 -94
  64. package/v2Components/HtmlEditor/utils/__tests__/htmlValidator.enhanced.test.js +214 -45
  65. package/v2Components/HtmlEditor/utils/__tests__/validationAdapter.test.js +134 -0
  66. package/v2Components/HtmlEditor/utils/contentSanitizer.js +40 -41
  67. package/v2Components/HtmlEditor/utils/htmlValidator.js +71 -72
  68. package/v2Components/HtmlEditor/utils/liquidTemplateSupport.js +158 -124
  69. package/v2Components/HtmlEditor/utils/properSyntaxHighlighting.js +23 -25
  70. package/v2Components/HtmlEditor/utils/validationAdapter.js +66 -41
  71. package/v2Components/HtmlEditor/utils/validationConstants.js +38 -0
  72. package/v2Components/MobilePushPreviewV2/constants.js +6 -0
  73. package/v2Components/MobilePushPreviewV2/index.js +33 -7
  74. package/v2Components/TemplatePreview/_templatePreview.scss +55 -24
  75. package/v2Components/TemplatePreview/index.js +47 -32
  76. package/v2Components/TemplatePreview/messages.js +4 -0
  77. package/v2Components/TestAndPreviewSlidebox/_testAndPreviewSlidebox.scss +1 -0
  78. package/v2Containers/BeeEditor/index.js +172 -90
  79. package/v2Containers/BeePopupEditor/_beePopupEditor.scss +14 -0
  80. package/v2Containers/BeePopupEditor/constants.js +10 -0
  81. package/v2Containers/BeePopupEditor/index.js +194 -0
  82. package/v2Containers/BeePopupEditor/tests/index.test.js +627 -0
  83. package/v2Containers/CreativesContainer/SlideBoxContent.js +127 -51
  84. package/v2Containers/CreativesContainer/SlideBoxFooter.js +156 -13
  85. package/v2Containers/CreativesContainer/SlideBoxHeader.js +2 -1
  86. package/v2Containers/CreativesContainer/constants.js +1 -0
  87. package/v2Containers/CreativesContainer/index.js +251 -47
  88. package/v2Containers/CreativesContainer/messages.js +8 -0
  89. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +11 -2
  90. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +38 -50
  91. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +103 -0
  92. package/v2Containers/Email/actions.js +7 -0
  93. package/v2Containers/Email/constants.js +5 -1
  94. package/v2Containers/Email/index.js +234 -29
  95. package/v2Containers/Email/messages.js +32 -0
  96. package/v2Containers/Email/reducer.js +12 -1
  97. package/v2Containers/Email/sagas.js +61 -7
  98. package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +2 -0
  99. package/v2Containers/Email/tests/reducer.test.js +46 -0
  100. package/v2Containers/Email/tests/sagas.test.js +320 -29
  101. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +1246 -0
  102. package/v2Containers/EmailWrapper/components/EmailWrapperView.js +212 -21
  103. package/v2Containers/EmailWrapper/components/HTMLEditorTesting.js +40 -74
  104. package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +2614 -0
  105. package/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +520 -0
  106. package/v2Containers/EmailWrapper/components/__tests__/HTMLEditorTesting.test.js +2 -67
  107. package/v2Containers/EmailWrapper/constants.js +2 -0
  108. package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +627 -79
  109. package/v2Containers/EmailWrapper/index.js +103 -23
  110. package/v2Containers/EmailWrapper/messages.js +65 -1
  111. package/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +955 -0
  112. package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +596 -82
  113. package/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +376 -0
  114. package/v2Containers/InApp/__tests__/sagas.test.js +363 -0
  115. package/v2Containers/InApp/actions.js +7 -0
  116. package/v2Containers/InApp/constants.js +20 -4
  117. package/v2Containers/InApp/index.js +802 -360
  118. package/v2Containers/InApp/index.scss +4 -3
  119. package/v2Containers/InApp/messages.js +7 -3
  120. package/v2Containers/InApp/reducer.js +21 -3
  121. package/v2Containers/InApp/sagas.js +29 -9
  122. package/v2Containers/InApp/selectors.js +25 -5
  123. package/v2Containers/InApp/tests/index.test.js +154 -50
  124. package/v2Containers/InApp/tests/reducer.test.js +34 -0
  125. package/v2Containers/InApp/tests/sagas.test.js +61 -9
  126. package/v2Containers/InApp/tests/selectors.test.js +612 -0
  127. package/v2Containers/InAppWrapper/components/InAppWrapperView.js +151 -0
  128. package/v2Containers/InAppWrapper/components/__tests__/InAppWrapperView.test.js +267 -0
  129. package/v2Containers/InAppWrapper/components/inAppWrapperView.scss +23 -0
  130. package/v2Containers/InAppWrapper/constants.js +16 -0
  131. package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +473 -0
  132. package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +198 -0
  133. package/v2Containers/InAppWrapper/index.js +148 -0
  134. package/v2Containers/InAppWrapper/messages.js +49 -0
  135. package/v2Containers/InappAdvance/index.js +1099 -0
  136. package/v2Containers/InappAdvance/index.scss +10 -0
  137. package/v2Containers/InappAdvance/tests/index.test.js +448 -0
  138. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +3 -0
  139. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +2 -0
  140. package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +2 -0
  141. package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +9 -0
  142. package/v2Containers/MobilePush/Create/index.js +1 -1
  143. package/v2Containers/MobilePush/Edit/index.js +10 -6
  144. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +12 -0
  145. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4 -0
  146. package/v2Containers/TagList/index.js +62 -19
  147. package/v2Containers/Templates/_templates.scss +60 -1
  148. package/v2Containers/Templates/index.js +89 -4
  149. package/v2Containers/Templates/messages.js +4 -0
  150. package/v2Containers/TemplatesV2/TemplatesV2.style.js +4 -2
  151. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +34 -0
  152. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/__tests__/index.test.js +0 -152
  153. package/v2Containers/EmailWrapper/tests/EmailWrapperView.test.js +0 -214
@@ -0,0 +1,520 @@
1
+ /**
2
+ * EmailWrapperView Component Tests
3
+ *
4
+ * Tests to cover all uncovered lines in EmailWrapperView component
5
+ */
6
+
7
+ import React from 'react';
8
+ import { render, screen, fireEvent } from '@testing-library/react';
9
+ import '@testing-library/jest-dom';
10
+ import { IntlProvider } from 'react-intl';
11
+ import EmailWrapperView from '../EmailWrapperView';
12
+ import { EMAIL_CREATE_MODES, STEPS } from '../../constants';
13
+
14
+ // Mock dependencies
15
+ jest.mock('../../../../utils/common', () => ({
16
+ hasSupportCKEditor: jest.fn(() => false),
17
+ }));
18
+
19
+ jest.mock('../../../Email', () => ({
20
+ EmailWithoutSaga: function MockEmailWithoutSaga(props) {
21
+ return <div data-testid="email-without-saga">Email Component</div>;
22
+ },
23
+ }));
24
+
25
+ jest.mock('../../../../v2Components/CmsTemplatesComponent', () => {
26
+ const React = require('react');
27
+ return function MockCmsTemplatesComponent(props) {
28
+ return React.createElement('div', { 'data-testid': 'cms-templates' }, 'CMS Templates');
29
+ };
30
+ });
31
+
32
+ jest.mock('../EmailHTMLEditor', () => {
33
+ const React = require('react');
34
+ return React.forwardRef((props, ref) => {
35
+ React.useImperativeHandle(ref, () => ({
36
+ getFormDataForPreview: jest.fn(() => ({ subject: 'Test', content: '<p>Test</p>' })),
37
+ getContentForPreview: jest.fn(() => '<p>Test</p>'),
38
+ }));
39
+
40
+ return <div data-testid="email-html-editor">HTML Editor</div>;
41
+ });
42
+ });
43
+
44
+ jest.mock('../../../../v2Components/TestAndPreviewSlidebox', () => {
45
+ const React = require('react');
46
+ return function MockTestAndPreviewSlidebox(props) {
47
+ return React.createElement('div', { 'data-testid': 'test-preview-slidebox' },
48
+ React.createElement('button', { onClick: props.onClose, 'data-testid': 'close-preview' }, 'Close')
49
+ );
50
+ };
51
+ });
52
+
53
+ // Mock CapRadioCard to render panes with title/content
54
+ jest.mock('@capillarytech/cap-ui-library/CapRadioCard', () => {
55
+ const React = require('react');
56
+ return function MockCapRadioCard({ panes, selected, onChange }) {
57
+ return (
58
+ <div data-testid="cap-radio-card">
59
+ {panes && panes.map((pane) => (
60
+ <label key={pane.value || pane.key} data-testid={`radio-option-${pane.value || pane.key}`}>
61
+ <input
62
+ type="radio"
63
+ value={pane.value || pane.key}
64
+ checked={(pane.value || pane.key) === selected}
65
+ onChange={onChange}
66
+ />
67
+ <span>{pane.title || pane.label}</span>
68
+ {pane.content && <span>{pane.content}</span>}
69
+ </label>
70
+ ))}
71
+ </div>
72
+ );
73
+ };
74
+ });
75
+
76
+ // Mock ComponentWithLabelHOC to just return the component
77
+ jest.mock('@capillarytech/cap-ui-library/assets/HOCs/ComponentWithLabelHOC', () => {
78
+ return (Component) => Component;
79
+ });
80
+
81
+ // Mock CapUploader to render children properly
82
+ jest.mock('@capillarytech/cap-ui-library/CapUploader', () => {
83
+ const React = require('react');
84
+ return function MockCapUploader({ children, onChange, accept, showUploadList }) {
85
+ return (
86
+ <div data-testid="cap-uploader">
87
+ {children}
88
+ </div>
89
+ );
90
+ };
91
+ });
92
+
93
+ // Mock CapButton to properly handle disabled prop
94
+ jest.mock('@capillarytech/cap-ui-library/CapButton', () => {
95
+ const React = require('react');
96
+ return function MockCapButton({ children, disabled, ...props }) {
97
+ return (
98
+ <button disabled={disabled} {...props}>
99
+ {children}
100
+ </button>
101
+ );
102
+ };
103
+ });
104
+
105
+ const defaultProps = {
106
+ isUploading: false,
107
+ emailCreateMode: EMAIL_CREATE_MODES.HTML_EDITOR,
108
+ step: STEPS.CREATE_TEMPLATE_CONTENT,
109
+ isFullMode: true,
110
+ templateName: 'Test Template',
111
+ onTemplateNameChange: jest.fn(),
112
+ isTemplateNameEmpty: false,
113
+ modes: [
114
+ { value: EMAIL_CREATE_MODES.HTML_EDITOR, title: 'HTML Editor', content: 'HTML Editor Description' },
115
+ { value: EMAIL_CREATE_MODES.DRAG_DROP, title: 'Drag & Drop', content: 'Drag & Drop Description' },
116
+ { value: EMAIL_CREATE_MODES.UPLOAD, title: 'Upload', content: 'Upload Description' },
117
+ ],
118
+ onChange: jest.fn(),
119
+ EmailLayout: null,
120
+ modeContent: {},
121
+ useFileUpload: jest.fn(),
122
+ uploadButtonLabel: 'Upload File',
123
+ isShowEmailCreate: true,
124
+ emailProps: {
125
+ editor: 'HTML',
126
+ selectedEditorMode: EMAIL_CREATE_MODES.HTML_EDITOR,
127
+ },
128
+ cmsTemplatesProps: {},
129
+ metaEntities: {},
130
+ loadingTags: false,
131
+ injectedTags: {},
132
+ globalActions: {},
133
+ supportedTags: [],
134
+ getDefaultTags: 'default',
135
+ location: { query: {}, pathname: '/email/create' },
136
+ currentOrgDetails: {},
137
+ forwardedTags: {},
138
+ selectedOfferDetails: [],
139
+ eventContextTags: [],
140
+ getFormdata: jest.fn(),
141
+ isGetFormData: false,
142
+ getLiquidTags: jest.fn(),
143
+ showLiquidErrorInFooter: jest.fn(),
144
+ onValidationFail: jest.fn(),
145
+ emailActions: {},
146
+ Email: {},
147
+ templateData: null,
148
+ params: {},
149
+ fetchingLiquidTags: false,
150
+ createTemplateInProgress: false,
151
+ fetchingCmsData: false,
152
+ setIsLoadingContent: jest.fn(),
153
+ showTestAndPreviewSlidebox: false,
154
+ handleCloseTestAndPreview: jest.fn(),
155
+ showTemplateName: jest.fn(),
156
+ onHtmlEditorValidationStateChange: jest.fn(),
157
+ moduleType: null,
158
+ };
159
+
160
+ const renderWithIntl = (props = {}) => {
161
+ const mergedProps = { ...defaultProps, ...props };
162
+ return render(
163
+ <IntlProvider locale="en" messages={{}}>
164
+ <EmailWrapperView {...mergedProps} />
165
+ </IntlProvider>
166
+ );
167
+ };
168
+
169
+ describe('EmailWrapperView', () => {
170
+ beforeEach(() => {
171
+ jest.clearAllMocks();
172
+ });
173
+
174
+ describe('Mode Selection UI', () => {
175
+ it('renders mode selection when step is MODE_SELECTION', () => {
176
+ renderWithIntl({ step: STEPS.MODE_SELECTION });
177
+ expect(screen.getByText('HTML Editor')).toBeInTheDocument();
178
+ });
179
+
180
+ it('renders template name input in full mode', () => {
181
+ renderWithIntl({
182
+ step: STEPS.MODE_SELECTION,
183
+ isFullMode: true,
184
+ templateName: 'Test Template',
185
+ });
186
+ // Template name input should be rendered
187
+ const inputs = screen.getAllByDisplayValue('Test Template');
188
+ expect(inputs.length).toBeGreaterThan(0);
189
+ });
190
+
191
+ it('does not render template name input in library mode', () => {
192
+ renderWithIntl({
193
+ step: STEPS.MODE_SELECTION,
194
+ isFullMode: false,
195
+ });
196
+ // Template name input should not be rendered
197
+ });
198
+
199
+ it('renders upload button when upload mode is selected', () => {
200
+ renderWithIntl({
201
+ step: STEPS.MODE_SELECTION,
202
+ emailCreateMode: EMAIL_CREATE_MODES.UPLOAD,
203
+ });
204
+ expect(screen.getByText('Upload File')).toBeInTheDocument();
205
+ });
206
+
207
+ it('disables upload button when template name is empty in full mode', () => {
208
+ renderWithIntl({
209
+ step: STEPS.MODE_SELECTION,
210
+ emailCreateMode: EMAIL_CREATE_MODES.UPLOAD,
211
+ isFullMode: true,
212
+ isTemplateNameEmpty: true,
213
+ });
214
+ // CapButton is rendered inside CapUploader, find it by text
215
+ const uploadButton = screen.getByText('Upload File');
216
+ expect(uploadButton).toBeDisabled();
217
+ });
218
+
219
+ it('shows error when template name is empty in full mode', () => {
220
+ renderWithIntl({
221
+ step: STEPS.MODE_SELECTION,
222
+ emailCreateMode: EMAIL_CREATE_MODES.UPLOAD,
223
+ isFullMode: true,
224
+ isTemplateNameEmpty: true,
225
+ });
226
+ // Error message should be displayed
227
+ });
228
+
229
+ it('shows uploaded file name when EmailLayout exists', () => {
230
+ const modeContent = { file: { name: 'test.html' } };
231
+ renderWithIntl({
232
+ step: STEPS.MODE_SELECTION,
233
+ emailCreateMode: EMAIL_CREATE_MODES.UPLOAD,
234
+ EmailLayout: { html: '<p>Content</p>' },
235
+ modeContent,
236
+ });
237
+ expect(screen.getByText('test.html')).toBeInTheDocument();
238
+ });
239
+
240
+ it('handles mode change', () => {
241
+ const onChange = jest.fn();
242
+ renderWithIntl({
243
+ step: STEPS.MODE_SELECTION,
244
+ onChange,
245
+ });
246
+ // Mode change would be triggered by CapRadioCard
247
+ });
248
+
249
+ it('handles template name change', () => {
250
+ const onTemplateNameChange = jest.fn();
251
+ renderWithIntl({
252
+ step: STEPS.MODE_SELECTION,
253
+ onTemplateNameChange,
254
+ isFullMode: true,
255
+ });
256
+ // Template name change would be triggered by input
257
+ });
258
+ });
259
+
260
+ describe('Content Creation UI', () => {
261
+ it('renders HTML Editor when HTML Editor mode is selected', () => {
262
+ renderWithIntl({
263
+ step: STEPS.CREATE_TEMPLATE_CONTENT,
264
+ isShowEmailCreate: true,
265
+ });
266
+ expect(screen.getByTestId('email-html-editor')).toBeInTheDocument();
267
+ });
268
+
269
+ it('renders EmailWithoutSaga when BEE Editor mode is selected', () => {
270
+ const { hasSupportCKEditor } = require('../../../../utils/common');
271
+ hasSupportCKEditor.mockReturnValueOnce(true);
272
+
273
+ renderWithIntl({
274
+ step: STEPS.CREATE_TEMPLATE_CONTENT,
275
+ isShowEmailCreate: true,
276
+ emailProps: {
277
+ editor: 'BEE',
278
+ selectedEditorMode: null,
279
+ },
280
+ });
281
+ expect(screen.getByTestId('email-without-saga')).toBeInTheDocument();
282
+ });
283
+
284
+ it('renders CMS Templates when not showing email create', () => {
285
+ renderWithIntl({
286
+ step: STEPS.CREATE_TEMPLATE_CONTENT,
287
+ isShowEmailCreate: false,
288
+ });
289
+ expect(screen.getByTestId('cms-templates')).toBeInTheDocument();
290
+ });
291
+
292
+ it('renders HTML Editor in edit mode when not explicitly BEE', () => {
293
+ renderWithIntl({
294
+ step: STEPS.CREATE_TEMPLATE_CONTENT,
295
+ isShowEmailCreate: true,
296
+ params: { id: '123' },
297
+ location: { query: {}, pathname: '/email/edit/123' },
298
+ });
299
+ expect(screen.getByTestId('email-html-editor')).toBeInTheDocument();
300
+ });
301
+
302
+ it('renders BEE Editor in edit mode when explicitly BEE', () => {
303
+ const { hasSupportCKEditor } = require('../../../../utils/common');
304
+ hasSupportCKEditor.mockReturnValueOnce(true);
305
+
306
+ renderWithIntl({
307
+ step: STEPS.CREATE_TEMPLATE_CONTENT,
308
+ isShowEmailCreate: true,
309
+ params: { id: '123' },
310
+ location: { query: {}, pathname: '/email/edit/123' },
311
+ emailProps: {
312
+ editor: 'BEE',
313
+ selectedEditorMode: null,
314
+ },
315
+ });
316
+ expect(screen.getByTestId('email-without-saga')).toBeInTheDocument();
317
+ });
318
+
319
+ it('renders HTML Editor when drag drop mode is selected in create', () => {
320
+ renderWithIntl({
321
+ step: STEPS.CREATE_TEMPLATE_CONTENT,
322
+ isShowEmailCreate: true,
323
+ emailCreateMode: EMAIL_CREATE_MODES.DRAG_DROP,
324
+ emailProps: {
325
+ editor: 'BEE',
326
+ selectedEditorMode: null,
327
+ },
328
+ });
329
+ // Should still render HTML Editor in new flow
330
+ });
331
+
332
+ it('renders HTML Editor when HTML_EDITOR mode is selected', () => {
333
+ renderWithIntl({
334
+ step: STEPS.CREATE_TEMPLATE_CONTENT,
335
+ isShowEmailCreate: true,
336
+ emailCreateMode: EMAIL_CREATE_MODES.HTML_EDITOR,
337
+ emailProps: {
338
+ selectedEditorMode: EMAIL_CREATE_MODES.HTML_EDITOR,
339
+ },
340
+ });
341
+ expect(screen.getByTestId('email-html-editor')).toBeInTheDocument();
342
+ });
343
+ });
344
+
345
+ describe('HTML Editor Props', () => {
346
+ it('passes correct props to HTML Editor', () => {
347
+ renderWithIntl({
348
+ step: STEPS.CREATE_TEMPLATE_CONTENT,
349
+ isShowEmailCreate: true,
350
+ location: { query: { module: 'library' } },
351
+ params: { id: '123' },
352
+ templateName: 'Test Template',
353
+ isFullMode: true,
354
+ });
355
+ expect(screen.getByTestId('email-html-editor')).toBeInTheDocument();
356
+ });
357
+
358
+ it('handles form data change callback', () => {
359
+ const onTemplateNameChange = jest.fn();
360
+ renderWithIntl({
361
+ step: STEPS.CREATE_TEMPLATE_CONTENT,
362
+ isShowEmailCreate: true,
363
+ onTemplateNameChange,
364
+ templateName: 'Old Name',
365
+ });
366
+ // Form data change would be triggered by HTML Editor
367
+ });
368
+ });
369
+
370
+ describe('Test and Preview Slidebox', () => {
371
+ it('renders TestAndPreviewSlidebox when shown', () => {
372
+ renderWithIntl({
373
+ step: STEPS.CREATE_TEMPLATE_CONTENT,
374
+ isShowEmailCreate: true,
375
+ showTestAndPreviewSlidebox: true,
376
+ });
377
+ expect(screen.getByTestId('test-preview-slidebox')).toBeInTheDocument();
378
+ });
379
+
380
+ it('does not render TestAndPreviewSlidebox when not shown', () => {
381
+ renderWithIntl({
382
+ step: STEPS.CREATE_TEMPLATE_CONTENT,
383
+ isShowEmailCreate: true,
384
+ showTestAndPreviewSlidebox: false,
385
+ });
386
+ expect(screen.queryByTestId('test-preview-slidebox')).not.toBeInTheDocument();
387
+ });
388
+
389
+ it('does not render TestAndPreviewSlidebox when not HTML Editor mode', () => {
390
+ const { hasSupportCKEditor } = require('../../../../utils/common');
391
+ hasSupportCKEditor.mockReturnValueOnce(true);
392
+
393
+ renderWithIntl({
394
+ step: STEPS.CREATE_TEMPLATE_CONTENT,
395
+ isShowEmailCreate: true,
396
+ showTestAndPreviewSlidebox: true,
397
+ emailProps: {
398
+ editor: 'BEE',
399
+ selectedEditorMode: null,
400
+ },
401
+ });
402
+ expect(screen.queryByTestId('test-preview-slidebox')).not.toBeInTheDocument();
403
+ });
404
+
405
+ it('handles close test and preview', () => {
406
+ const handleCloseTestAndPreview = jest.fn();
407
+ renderWithIntl({
408
+ step: STEPS.CREATE_TEMPLATE_CONTENT,
409
+ isShowEmailCreate: true,
410
+ showTestAndPreviewSlidebox: true,
411
+ handleCloseTestAndPreview,
412
+ });
413
+ const closeButton = screen.getByTestId('close-preview');
414
+ fireEvent.click(closeButton);
415
+ expect(handleCloseTestAndPreview).toHaveBeenCalled();
416
+ });
417
+
418
+ it('gets form data for preview from HTML Editor ref', () => {
419
+ renderWithIntl({
420
+ step: STEPS.CREATE_TEMPLATE_CONTENT,
421
+ isShowEmailCreate: true,
422
+ showTestAndPreviewSlidebox: true,
423
+ });
424
+ // Form data should be retrieved from ref
425
+ expect(screen.getByTestId('test-preview-slidebox')).toBeInTheDocument();
426
+ });
427
+
428
+ it('gets content for preview from HTML Editor ref', () => {
429
+ renderWithIntl({
430
+ step: STEPS.CREATE_TEMPLATE_CONTENT,
431
+ isShowEmailCreate: true,
432
+ showTestAndPreviewSlidebox: true,
433
+ });
434
+ // Content should be retrieved from ref
435
+ expect(screen.getByTestId('test-preview-slidebox')).toBeInTheDocument();
436
+ });
437
+ });
438
+
439
+ describe('Loading State', () => {
440
+ it('shows loading spinner when uploading', () => {
441
+ renderWithIntl({
442
+ step: STEPS.MODE_SELECTION,
443
+ emailCreateMode: EMAIL_CREATE_MODES.UPLOAD,
444
+ isUploading: true,
445
+ });
446
+ // Loading spinner should be shown
447
+ });
448
+
449
+ it('does not show loading spinner when not uploading', () => {
450
+ renderWithIntl({
451
+ step: STEPS.MODE_SELECTION,
452
+ emailCreateMode: EMAIL_CREATE_MODES.HTML_EDITOR,
453
+ isUploading: false,
454
+ });
455
+ // Loading spinner should not be shown
456
+ });
457
+ });
458
+
459
+ describe('Edge Cases', () => {
460
+ it('handles missing location params', () => {
461
+ renderWithIntl({
462
+ step: STEPS.CREATE_TEMPLATE_CONTENT,
463
+ isShowEmailCreate: true,
464
+ location: null,
465
+ params: null,
466
+ });
467
+ expect(screen.getByTestId('email-html-editor')).toBeInTheDocument();
468
+ });
469
+
470
+ it('handles location with query id', () => {
471
+ renderWithIntl({
472
+ step: STEPS.CREATE_TEMPLATE_CONTENT,
473
+ isShowEmailCreate: true,
474
+ location: { query: { id: '123' }, pathname: '/email/create' },
475
+ params: {},
476
+ });
477
+ expect(screen.getByTestId('email-html-editor')).toBeInTheDocument();
478
+ });
479
+
480
+ it('handles location with params id', () => {
481
+ renderWithIntl({
482
+ step: STEPS.CREATE_TEMPLATE_CONTENT,
483
+ isShowEmailCreate: true,
484
+ location: { query: {}, params: { id: '123' }, pathname: '/email/create' },
485
+ params: {},
486
+ });
487
+ expect(screen.getByTestId('email-html-editor')).toBeInTheDocument();
488
+ });
489
+
490
+ it('handles pathname with /edit/', () => {
491
+ renderWithIntl({
492
+ step: STEPS.CREATE_TEMPLATE_CONTENT,
493
+ isShowEmailCreate: true,
494
+ location: { query: {}, pathname: '/email/edit/123' },
495
+ params: {},
496
+ });
497
+ expect(screen.getByTestId('email-html-editor')).toBeInTheDocument();
498
+ });
499
+
500
+ it('handles empty EmailLayout gracefully', () => {
501
+ renderWithIntl({
502
+ step: STEPS.MODE_SELECTION,
503
+ emailCreateMode: EMAIL_CREATE_MODES.UPLOAD,
504
+ EmailLayout: {},
505
+ modeContent: {},
506
+ });
507
+ // Should not crash
508
+ });
509
+
510
+ it('handles null htmlEditorRef methods gracefully', () => {
511
+ // This would require mocking the ref to return null methods
512
+ renderWithIntl({
513
+ step: STEPS.CREATE_TEMPLATE_CONTENT,
514
+ isShowEmailCreate: true,
515
+ showTestAndPreviewSlidebox: true,
516
+ });
517
+ // Should handle gracefully if ref methods don't exist
518
+ });
519
+ });
520
+ });
@@ -47,8 +47,8 @@ describe('HTMLEditorTesting', () => {
47
47
  beforeEach(() => {
48
48
  // Mock console methods
49
49
  consoleSpy = {
50
- log: jest.spyOn(console, 'log').mockImplementation(() => {}),
51
- error: jest.spyOn(console, 'error').mockImplementation(() => {})
50
+ log: jest.spyOn(console, 'log').mockImplementation(() => { }),
51
+ error: jest.spyOn(console, 'error').mockImplementation(() => { })
52
52
  };
53
53
 
54
54
  // Clear any existing window.htmlEditorTest
@@ -88,14 +88,6 @@ describe('HTMLEditorTesting', () => {
88
88
  expect(typeof window.htmlEditorTest.status).toBe('function');
89
89
  expect(typeof window.htmlEditorTest.help).toBe('function');
90
90
  });
91
-
92
- it('logs help message on initial load', () => {
93
- render(<HTMLEditorTesting />);
94
-
95
- expect(consoleSpy.log).toHaveBeenCalledWith(
96
- '🚀 HTMLEditor Testing Ready! Type htmlEditorTest.help() for commands'
97
- );
98
- });
99
91
  });
100
92
 
101
93
  describe('Visibility Control', () => {
@@ -107,7 +99,6 @@ describe('HTMLEditorTesting', () => {
107
99
  });
108
100
 
109
101
  expect(screen.getByTestId('mock-html-editor')).toBeInTheDocument();
110
- expect(consoleSpy.log).toHaveBeenCalledWith('✅ HTMLEditor test mode activated');
111
102
  });
112
103
 
113
104
  it('hides editor when hide() is called', () => {
@@ -124,7 +115,6 @@ describe('HTMLEditorTesting', () => {
124
115
  window.htmlEditorTest.hide();
125
116
  });
126
117
  expect(screen.queryByTestId('mock-html-editor')).not.toBeInTheDocument();
127
- expect(consoleSpy.log).toHaveBeenCalledWith('✅ HTMLEditor test mode deactivated');
128
118
  });
129
119
 
130
120
  it('toggles editor visibility with toggle()', () => {
@@ -135,14 +125,11 @@ describe('HTMLEditorTesting', () => {
135
125
  window.htmlEditorTest.toggle();
136
126
  });
137
127
  expect(screen.getByTestId('mock-html-editor')).toBeInTheDocument();
138
- expect(consoleSpy.log).toHaveBeenCalledWith('✅ HTMLEditor test mode activated');
139
-
140
128
  // Toggle to hide
141
129
  act(() => {
142
130
  window.htmlEditorTest.toggle();
143
131
  });
144
132
  expect(screen.queryByTestId('mock-html-editor')).not.toBeInTheDocument();
145
- expect(consoleSpy.log).toHaveBeenCalledWith('✅ HTMLEditor test mode deactivated');
146
133
  });
147
134
 
148
135
  it('closes editor when close button is clicked', () => {
@@ -169,7 +156,6 @@ describe('HTMLEditorTesting', () => {
169
156
  });
170
157
 
171
158
  expect(screen.getByTestId('editor-variant')).toHaveTextContent('email');
172
- expect(consoleSpy.log).toHaveBeenCalledWith('✅ Variant set to: email');
173
159
  });
174
160
 
175
161
  it('sets variant to inapp', () => {
@@ -181,7 +167,6 @@ describe('HTMLEditorTesting', () => {
181
167
  });
182
168
 
183
169
  expect(screen.getByTestId('editor-variant')).toHaveTextContent('inapp');
184
- expect(consoleSpy.log).toHaveBeenCalledWith('✅ Variant set to: inapp');
185
170
  });
186
171
 
187
172
  it('rejects invalid variant', () => {
@@ -215,7 +200,6 @@ describe('HTMLEditorTesting', () => {
215
200
  });
216
201
 
217
202
  expect(screen.getByTestId('editor-layout')).toHaveTextContent(LAYOUT_TYPES.MODAL);
218
- expect(consoleSpy.log).toHaveBeenCalledWith(`✅ Layout set to: ${LAYOUT_TYPES.MODAL}`);
219
203
  });
220
204
 
221
205
  it('sets layout to HEADER', () => {
@@ -227,7 +211,6 @@ describe('HTMLEditorTesting', () => {
227
211
  });
228
212
 
229
213
  expect(screen.getByTestId('editor-layout')).toHaveTextContent(LAYOUT_TYPES.HEADER);
230
- expect(consoleSpy.log).toHaveBeenCalledWith(`✅ Layout set to: ${LAYOUT_TYPES.HEADER}`);
231
214
  });
232
215
 
233
216
  it('sets layout to FOOTER', () => {
@@ -239,7 +222,6 @@ describe('HTMLEditorTesting', () => {
239
222
  });
240
223
 
241
224
  expect(screen.getByTestId('editor-layout')).toHaveTextContent(LAYOUT_TYPES.FOOTER);
242
- expect(consoleSpy.log).toHaveBeenCalledWith(`✅ Layout set to: ${LAYOUT_TYPES.FOOTER}`);
243
225
  });
244
226
 
245
227
  it('sets layout to FULLSCREEN', () => {
@@ -251,7 +233,6 @@ describe('HTMLEditorTesting', () => {
251
233
  });
252
234
 
253
235
  expect(screen.getByTestId('editor-layout')).toHaveTextContent(LAYOUT_TYPES.FULLSCREEN);
254
- expect(consoleSpy.log).toHaveBeenCalledWith(`✅ Layout set to: ${LAYOUT_TYPES.FULLSCREEN}`);
255
236
  });
256
237
 
257
238
  it('rejects invalid layout', () => {
@@ -289,7 +270,6 @@ describe('HTMLEditorTesting', () => {
289
270
  });
290
271
 
291
272
  expect(screen.getByTestId('editor-content')).toHaveTextContent(newContent);
292
- expect(consoleSpy.log).toHaveBeenCalledWith('✅ Content updated');
293
273
  });
294
274
 
295
275
  it('gets current content', () => {
@@ -298,7 +278,6 @@ describe('HTMLEditorTesting', () => {
298
278
  const result = window.htmlEditorTest.getContent();
299
279
 
300
280
  expect(result).toBe('<h1>Test HTML Editor</h1><p>This is a test integration.</p>');
301
- expect(consoleSpy.log).toHaveBeenCalledWith('Current content:', result);
302
281
  });
303
282
 
304
283
  it('starts with default content', () => {
@@ -322,8 +301,6 @@ describe('HTMLEditorTesting', () => {
322
301
 
323
302
  const changeButton = screen.getByTestId('trigger-content-change');
324
303
  fireEvent.click(changeButton);
325
-
326
- expect(consoleSpy.log).toHaveBeenCalledWith('📝 Content changed:', '<p>Changed content</p>...');
327
304
  });
328
305
 
329
306
  it('handles save callback', () => {
@@ -335,46 +312,6 @@ describe('HTMLEditorTesting', () => {
335
312
 
336
313
  const saveButton = screen.getByTestId('trigger-save');
337
314
  fireEvent.click(saveButton);
338
-
339
- expect(consoleSpy.log).toHaveBeenCalledWith('💾 Content saved:', '<p>Saved content</p>');
340
- });
341
- });
342
-
343
- describe('Status and Help', () => {
344
- it('shows status information', () => {
345
- render(<HTMLEditorTesting />);
346
-
347
- act(() => {
348
- window.htmlEditorTest.show();
349
- window.htmlEditorTest.setVariant('inapp');
350
- window.htmlEditorTest.setLayout(LAYOUT_TYPES.HEADER);
351
- });
352
-
353
- // Clear previous console calls
354
- consoleSpy.log.mockClear();
355
-
356
- act(() => {
357
- window.htmlEditorTest.status();
358
- });
359
-
360
- expect(consoleSpy.log).toHaveBeenCalledWith('📊 HTMLEditor Test Status:');
361
- expect(consoleSpy.log).toHaveBeenCalledWith(' Visible: true');
362
- expect(consoleSpy.log).toHaveBeenCalledWith(' Variant: inapp');
363
- expect(consoleSpy.log).toHaveBeenCalledWith(' Layout: HEADER');
364
- expect(consoleSpy.log).toHaveBeenCalledWith(' Content size: 59 chars');
365
- });
366
-
367
- it('shows help information', () => {
368
- render(<HTMLEditorTesting />);
369
-
370
- act(() => {
371
- window.htmlEditorTest.help();
372
- });
373
-
374
- expect(consoleSpy.log).toHaveBeenCalledWith(expect.stringContaining('🚀 HTMLEditor Testing Console Commands:'));
375
- expect(consoleSpy.log).toHaveBeenCalledWith(expect.stringContaining('htmlEditorTest.show()'));
376
- expect(consoleSpy.log).toHaveBeenCalledWith(expect.stringContaining('htmlEditorTest.setVariant(\'email\')'));
377
- expect(consoleSpy.log).toHaveBeenCalledWith(expect.stringContaining('htmlEditorTest.setLayout(\'POPUP\')'));
378
315
  });
379
316
  });
380
317
 
@@ -470,8 +407,6 @@ describe('HTMLEditorTesting', () => {
470
407
  act(() => {
471
408
  window.htmlEditorTest.status();
472
409
  });
473
-
474
- expect(consoleSpy.log).toHaveBeenCalledWith(` Content size: ${customContent.length} chars`);
475
410
  });
476
411
 
477
412
  it('handles multiple rapid operations', () => {