@capillarytech/creatives-library 8.0.207 → 8.0.209
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/assets/Android.png +0 -0
- package/assets/iOS.png +0 -0
- package/package.json +16 -2
- package/v2Components/HtmlEditor/HTMLEditor.js +508 -0
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +1809 -0
- package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +532 -0
- package/v2Components/HtmlEditor/_htmlEditor.scss +304 -0
- package/v2Components/HtmlEditor/_index.lazy.scss +26 -0
- package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +376 -0
- package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +331 -0
- package/v2Components/HtmlEditor/components/DeviceToggle/__tests__/index.test.js +314 -0
- package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +244 -0
- package/v2Components/HtmlEditor/components/DeviceToggle/index.js +111 -0
- package/v2Components/HtmlEditor/components/EditorToolbar/PreviewModeGroup.js +72 -0
- package/v2Components/HtmlEditor/components/EditorToolbar/__tests__/PreviewModeGroup.test.js +1594 -0
- package/v2Components/HtmlEditor/components/EditorToolbar/_editorToolbar.scss +113 -0
- package/v2Components/HtmlEditor/components/EditorToolbar/_previewModeGroup.scss +82 -0
- package/v2Components/HtmlEditor/components/EditorToolbar/index.js +115 -0
- package/v2Components/HtmlEditor/components/FullscreenModal/_fullscreenModal.scss +57 -0
- package/v2Components/HtmlEditor/components/InAppPreviewPane/ContentOverlay.js +90 -0
- package/v2Components/HtmlEditor/components/InAppPreviewPane/DeviceFrame.js +60 -0
- package/v2Components/HtmlEditor/components/InAppPreviewPane/LayoutSelector.js +58 -0
- package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/ContentOverlay.test.js +389 -0
- package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/DeviceFrame.test.js +424 -0
- package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/LayoutSelector.test.js +248 -0
- package/v2Components/HtmlEditor/components/InAppPreviewPane/_inAppPreviewPane.scss +253 -0
- package/v2Components/HtmlEditor/components/InAppPreviewPane/constants.js +104 -0
- package/v2Components/HtmlEditor/components/InAppPreviewPane/index.js +179 -0
- package/v2Components/HtmlEditor/components/PreviewPane/_previewPane.scss +220 -0
- package/v2Components/HtmlEditor/components/PreviewPane/index.js +229 -0
- package/v2Components/HtmlEditor/components/SplitContainer/SplitContainer.js +276 -0
- package/v2Components/HtmlEditor/components/SplitContainer/__tests__/SplitContainer.test.js +295 -0
- package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +257 -0
- package/v2Components/HtmlEditor/components/SplitContainer/index.js +7 -0
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/__tests__/index.test.js +152 -0
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/_validationErrorDisplay.scss +31 -0
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/index.js +70 -0
- package/v2Components/HtmlEditor/components/ValidationPanel/__tests__/index.test.js +98 -0
- package/v2Components/HtmlEditor/components/ValidationPanel/_validationPanel.scss +311 -0
- package/v2Components/HtmlEditor/components/ValidationPanel/index.js +297 -0
- package/v2Components/HtmlEditor/components/ValidationPanel/messages.js +57 -0
- package/v2Components/HtmlEditor/components/common/EditorContext.js +84 -0
- package/v2Components/HtmlEditor/components/common/__tests__/EditorContext.test.js +660 -0
- package/v2Components/HtmlEditor/constants.js +241 -0
- package/v2Components/HtmlEditor/hooks/__tests__/useEditorContent.test.js +450 -0
- package/v2Components/HtmlEditor/hooks/__tests__/useInAppContent.test.js +785 -0
- package/v2Components/HtmlEditor/hooks/__tests__/useLayoutState.test.js +580 -0
- package/v2Components/HtmlEditor/hooks/__tests__/useValidation.enhanced.test.js +768 -0
- package/v2Components/HtmlEditor/hooks/__tests__/useValidation.test.js +590 -0
- package/v2Components/HtmlEditor/hooks/useEditorContent.js +274 -0
- package/v2Components/HtmlEditor/hooks/useInAppContent.js +407 -0
- package/v2Components/HtmlEditor/hooks/useLayoutState.js +247 -0
- package/v2Components/HtmlEditor/hooks/useValidation.js +325 -0
- package/v2Components/HtmlEditor/index.js +29 -0
- package/v2Components/HtmlEditor/index.lazy.js +114 -0
- package/v2Components/HtmlEditor/messages.js +389 -0
- package/v2Components/HtmlEditor/utils/__tests__/contentSanitizer.test.js +741 -0
- package/v2Components/HtmlEditor/utils/__tests__/htmlValidator.enhanced.test.js +1042 -0
- package/v2Components/HtmlEditor/utils/__tests__/liquidTemplateSupport.test.js +515 -0
- package/v2Components/HtmlEditor/utils/__tests__/properSyntaxHighlighting.test.js +473 -0
- package/v2Components/HtmlEditor/utils/__tests__/simplePerformance.test.js +1109 -0
- package/v2Components/HtmlEditor/utils/__tests__/validationAdapter.test.js +240 -0
- package/v2Components/HtmlEditor/utils/contentSanitizer.js +433 -0
- package/v2Components/HtmlEditor/utils/htmlValidator.js +508 -0
- package/v2Components/HtmlEditor/utils/liquidTemplateSupport.js +524 -0
- package/v2Components/HtmlEditor/utils/properSyntaxHighlighting.js +163 -0
- package/v2Components/HtmlEditor/utils/simplePerformance.js +145 -0
- package/v2Components/HtmlEditor/utils/validationAdapter.js +130 -0
- package/v2Containers/EmailWrapper/components/HTMLEditorTesting.js +200 -0
- package/v2Containers/EmailWrapper/components/__tests__/HTMLEditorTesting.test.js +545 -0
- package/v2Containers/EmailWrapper/index.js +8 -1
- package/v2Containers/Templates/constants.js +8 -0
- package/v2Containers/Templates/index.js +56 -28
- package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +5 -14
- package/v2Containers/Whatsapp/constants.js +26 -2
- package/v2Containers/Whatsapp/index.js +4 -1
- package/v2Containers/Whatsapp/tests/index.test.js +460 -18
|
@@ -0,0 +1,532 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* index.lazy.js Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for lazy loading wrapper, fallback component, and preload utilities
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import { render, screen, waitFor } from '@testing-library/react';
|
|
9
|
+
import '@testing-library/jest-dom';
|
|
10
|
+
|
|
11
|
+
// Mock CapSpin before importing the component
|
|
12
|
+
jest.mock('@capillarytech/cap-ui-library/CapSpin', () => {
|
|
13
|
+
return function MockCapSpin({ size }) {
|
|
14
|
+
return <div data-testid="cap-spin" data-size={size}>Loading...</div>;
|
|
15
|
+
};
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// Mock the HTMLEditor component
|
|
19
|
+
jest.mock('../HTMLEditor', () => {
|
|
20
|
+
return {
|
|
21
|
+
__esModule: true,
|
|
22
|
+
default: function MockHTMLEditor(props) {
|
|
23
|
+
return <div data-testid="html-editor">Mock HTML Editor - {props.variant}</div>;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
describe('index.lazy.js', () => {
|
|
29
|
+
// Reset modules before each test to ensure clean state
|
|
30
|
+
beforeEach(() => {
|
|
31
|
+
jest.clearAllMocks();
|
|
32
|
+
// Clear the window flag
|
|
33
|
+
if (typeof window !== 'undefined') {
|
|
34
|
+
delete window.__htmlEditorLoaded;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
describe('HTMLEditorFallback', () => {
|
|
39
|
+
it('renders loading fallback with default message', async () => {
|
|
40
|
+
// Import after mocks are set up
|
|
41
|
+
const { HTMLEditorFallback } = await import('../index.lazy');
|
|
42
|
+
|
|
43
|
+
render(<HTMLEditorFallback />);
|
|
44
|
+
|
|
45
|
+
expect(screen.getByTestId('cap-spin')).toBeInTheDocument();
|
|
46
|
+
expect(screen.getByText('Loading HTML Editor...')).toBeInTheDocument();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('renders loading fallback with custom message', async () => {
|
|
50
|
+
const { HTMLEditorFallback } = await import('../index.lazy');
|
|
51
|
+
|
|
52
|
+
render(<HTMLEditorFallback message="Initializing editor..." />);
|
|
53
|
+
|
|
54
|
+
expect(screen.getByTestId('cap-spin')).toBeInTheDocument();
|
|
55
|
+
expect(screen.getByText('Initializing editor...')).toBeInTheDocument();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('renders CapSpin with large size', async () => {
|
|
59
|
+
const { HTMLEditorFallback } = await import('../index.lazy');
|
|
60
|
+
|
|
61
|
+
render(<HTMLEditorFallback />);
|
|
62
|
+
|
|
63
|
+
const spinner = screen.getByTestId('cap-spin');
|
|
64
|
+
expect(spinner).toHaveAttribute('data-size', 'large');
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('applies correct container CSS class', async () => {
|
|
68
|
+
const { HTMLEditorFallback } = await import('../index.lazy');
|
|
69
|
+
|
|
70
|
+
const { container } = render(<HTMLEditorFallback />);
|
|
71
|
+
const fallbackDiv = container.firstChild;
|
|
72
|
+
|
|
73
|
+
expect(fallbackDiv).toHaveClass('html-editor-lazy-fallback');
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('applies correct container CSS class for styling', async () => {
|
|
77
|
+
const { HTMLEditorFallback } = await import('../index.lazy');
|
|
78
|
+
|
|
79
|
+
const { container } = render(<HTMLEditorFallback />);
|
|
80
|
+
const fallbackDiv = container.firstChild;
|
|
81
|
+
|
|
82
|
+
expect(fallbackDiv).toHaveClass('html-editor-lazy-fallback');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('applies correct layout CSS class', async () => {
|
|
86
|
+
const { HTMLEditorFallback } = await import('../index.lazy');
|
|
87
|
+
|
|
88
|
+
const { container } = render(<HTMLEditorFallback />);
|
|
89
|
+
const fallbackDiv = container.firstChild;
|
|
90
|
+
|
|
91
|
+
expect(fallbackDiv).toHaveClass('html-editor-lazy-fallback');
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('renders message with correct CSS class and content', async () => {
|
|
95
|
+
const { HTMLEditorFallback } = await import('../index.lazy');
|
|
96
|
+
|
|
97
|
+
const { container } = render(<HTMLEditorFallback message="Test message" />);
|
|
98
|
+
const messageDiv = container.querySelector('.html-editor-lazy-fallback__message');
|
|
99
|
+
|
|
100
|
+
expect(messageDiv).toHaveClass('html-editor-lazy-fallback__message');
|
|
101
|
+
expect(messageDiv).toHaveTextContent('Test message');
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
describe('HTMLEditorLazy', () => {
|
|
106
|
+
it('renders the lazy loaded component', async () => {
|
|
107
|
+
const HTMLEditorLazy = (await import('../index.lazy')).default;
|
|
108
|
+
|
|
109
|
+
render(<HTMLEditorLazy variant="email" />);
|
|
110
|
+
|
|
111
|
+
// Wait for lazy component to load
|
|
112
|
+
await waitFor(() => {
|
|
113
|
+
expect(screen.getByTestId('html-editor')).toBeInTheDocument();
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
expect(screen.getByText(/Mock HTML Editor - email/)).toBeInTheDocument();
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('shows fallback while loading', async () => {
|
|
120
|
+
const HTMLEditorLazy = (await import('../index.lazy')).default;
|
|
121
|
+
|
|
122
|
+
const { container } = render(<HTMLEditorLazy variant="email" />);
|
|
123
|
+
|
|
124
|
+
// Fallback should be visible initially (though it may load very quickly in tests)
|
|
125
|
+
// The Suspense boundary is in place
|
|
126
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('forwards all props to the underlying component', async () => {
|
|
130
|
+
const HTMLEditorLazy = (await import('../index.lazy')).default;
|
|
131
|
+
const mockOnSave = jest.fn();
|
|
132
|
+
|
|
133
|
+
render(
|
|
134
|
+
<HTMLEditorLazy
|
|
135
|
+
variant="inapp"
|
|
136
|
+
onSave={mockOnSave}
|
|
137
|
+
readOnly={true}
|
|
138
|
+
className="custom-class"
|
|
139
|
+
/>
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
await waitFor(() => {
|
|
143
|
+
expect(screen.getByTestId('html-editor')).toBeInTheDocument();
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
expect(screen.getByText(/Mock HTML Editor - inapp/)).toBeInTheDocument();
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('has correct display name', async () => {
|
|
150
|
+
const HTMLEditorLazy = (await import('../index.lazy')).default;
|
|
151
|
+
|
|
152
|
+
expect(HTMLEditorLazy.displayName).toBe('HTMLEditorLazy');
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('accepts variant prop', async () => {
|
|
156
|
+
const HTMLEditorLazy = (await import('../index.lazy')).default;
|
|
157
|
+
|
|
158
|
+
render(<HTMLEditorLazy variant="email" />);
|
|
159
|
+
|
|
160
|
+
await waitFor(() => {
|
|
161
|
+
expect(screen.getByTestId('html-editor')).toBeInTheDocument();
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('accepts layoutType prop', async () => {
|
|
166
|
+
const HTMLEditorLazy = (await import('../index.lazy')).default;
|
|
167
|
+
|
|
168
|
+
render(<HTMLEditorLazy layoutType="modal" />);
|
|
169
|
+
|
|
170
|
+
await waitFor(() => {
|
|
171
|
+
expect(screen.getByTestId('html-editor')).toBeInTheDocument();
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it('accepts initialContent as string', async () => {
|
|
176
|
+
const HTMLEditorLazy = (await import('../index.lazy')).default;
|
|
177
|
+
|
|
178
|
+
render(<HTMLEditorLazy initialContent="<p>Test</p>" />);
|
|
179
|
+
|
|
180
|
+
await waitFor(() => {
|
|
181
|
+
expect(screen.getByTestId('html-editor')).toBeInTheDocument();
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it('accepts initialContent as object', async () => {
|
|
186
|
+
const HTMLEditorLazy = (await import('../index.lazy')).default;
|
|
187
|
+
|
|
188
|
+
render(<HTMLEditorLazy initialContent={{ android: '<p>Android</p>', ios: '<p>iOS</p>' }} />);
|
|
189
|
+
|
|
190
|
+
await waitFor(() => {
|
|
191
|
+
expect(screen.getByTestId('html-editor')).toBeInTheDocument();
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('accepts event handler props', async () => {
|
|
196
|
+
const HTMLEditorLazy = (await import('../index.lazy')).default;
|
|
197
|
+
const mockOnSave = jest.fn();
|
|
198
|
+
const mockOnContentChange = jest.fn();
|
|
199
|
+
|
|
200
|
+
render(
|
|
201
|
+
<HTMLEditorLazy
|
|
202
|
+
onSave={mockOnSave}
|
|
203
|
+
onContentChange={mockOnContentChange}
|
|
204
|
+
/>
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
await waitFor(() => {
|
|
208
|
+
expect(screen.getByTestId('html-editor')).toBeInTheDocument();
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it('accepts configuration props', async () => {
|
|
213
|
+
const HTMLEditorLazy = (await import('../index.lazy')).default;
|
|
214
|
+
|
|
215
|
+
render(
|
|
216
|
+
<HTMLEditorLazy
|
|
217
|
+
className="custom-editor"
|
|
218
|
+
readOnly={true}
|
|
219
|
+
showFullscreenButton={false}
|
|
220
|
+
autoSave={false}
|
|
221
|
+
autoSaveInterval={60000}
|
|
222
|
+
/>
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
await waitFor(() => {
|
|
226
|
+
expect(screen.getByTestId('html-editor')).toBeInTheDocument();
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
describe('Default Props', () => {
|
|
232
|
+
it('has correct default variant', async () => {
|
|
233
|
+
const HTMLEditorLazy = (await import('../index.lazy')).default;
|
|
234
|
+
|
|
235
|
+
expect(HTMLEditorLazy.defaultProps.variant).toBe('email');
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it('has correct default initialContent', async () => {
|
|
239
|
+
const HTMLEditorLazy = (await import('../index.lazy')).default;
|
|
240
|
+
|
|
241
|
+
expect(HTMLEditorLazy.defaultProps.initialContent).toBe(null);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
it('has correct default event handlers', async () => {
|
|
245
|
+
const HTMLEditorLazy = (await import('../index.lazy')).default;
|
|
246
|
+
|
|
247
|
+
expect(HTMLEditorLazy.defaultProps.onSave).toBe(null);
|
|
248
|
+
expect(HTMLEditorLazy.defaultProps.onContentChange).toBe(null);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it('has correct default configuration', async () => {
|
|
252
|
+
const HTMLEditorLazy = (await import('../index.lazy')).default;
|
|
253
|
+
|
|
254
|
+
expect(HTMLEditorLazy.defaultProps.className).toBe('');
|
|
255
|
+
expect(HTMLEditorLazy.defaultProps.readOnly).toBe(false);
|
|
256
|
+
expect(HTMLEditorLazy.defaultProps.showFullscreenButton).toBe(true);
|
|
257
|
+
expect(HTMLEditorLazy.defaultProps.autoSave).toBe(true);
|
|
258
|
+
expect(HTMLEditorLazy.defaultProps.autoSaveInterval).toBe(30000);
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
describe('PropTypes', () => {
|
|
263
|
+
it('defines variant propType', async () => {
|
|
264
|
+
const HTMLEditorLazy = (await import('../index.lazy')).default;
|
|
265
|
+
|
|
266
|
+
expect(HTMLEditorLazy.propTypes.variant).toBeDefined();
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
it('defines layoutType propType', async () => {
|
|
270
|
+
const HTMLEditorLazy = (await import('../index.lazy')).default;
|
|
271
|
+
|
|
272
|
+
expect(HTMLEditorLazy.propTypes.layoutType).toBeDefined();
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
it('defines initialContent propType', async () => {
|
|
276
|
+
const HTMLEditorLazy = (await import('../index.lazy')).default;
|
|
277
|
+
|
|
278
|
+
expect(HTMLEditorLazy.propTypes.initialContent).toBeDefined();
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
it('defines event handler propTypes', async () => {
|
|
282
|
+
const HTMLEditorLazy = (await import('../index.lazy')).default;
|
|
283
|
+
|
|
284
|
+
expect(HTMLEditorLazy.propTypes.onSave).toBeDefined();
|
|
285
|
+
expect(HTMLEditorLazy.propTypes.onContentChange).toBeDefined();
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it('defines configuration propTypes', async () => {
|
|
289
|
+
const HTMLEditorLazy = (await import('../index.lazy')).default;
|
|
290
|
+
|
|
291
|
+
expect(HTMLEditorLazy.propTypes.className).toBeDefined();
|
|
292
|
+
expect(HTMLEditorLazy.propTypes.readOnly).toBeDefined();
|
|
293
|
+
expect(HTMLEditorLazy.propTypes.showFullscreenButton).toBeDefined();
|
|
294
|
+
expect(HTMLEditorLazy.propTypes.autoSave).toBeDefined();
|
|
295
|
+
expect(HTMLEditorLazy.propTypes.autoSaveInterval).toBeDefined();
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
describe('preloadHTMLEditor', () => {
|
|
300
|
+
it('is exported as a function', async () => {
|
|
301
|
+
const { preloadHTMLEditor } = await import('../index.lazy');
|
|
302
|
+
|
|
303
|
+
expect(typeof preloadHTMLEditor).toBe('function');
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
it('can be called without errors', async () => {
|
|
307
|
+
const { preloadHTMLEditor } = await import('../index.lazy');
|
|
308
|
+
|
|
309
|
+
expect(() => {
|
|
310
|
+
preloadHTMLEditor();
|
|
311
|
+
}).not.toThrow();
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
it('handles import failures gracefully', async () => {
|
|
315
|
+
const { preloadHTMLEditor } = await import('../index.lazy');
|
|
316
|
+
|
|
317
|
+
// Should not throw even if import fails (preloadHTMLEditor catches errors internally)
|
|
318
|
+
expect(() => {
|
|
319
|
+
preloadHTMLEditor();
|
|
320
|
+
}).not.toThrow();
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
it('returns undefined', async () => {
|
|
324
|
+
const { preloadHTMLEditor } = await import('../index.lazy');
|
|
325
|
+
|
|
326
|
+
const result = preloadHTMLEditor();
|
|
327
|
+
expect(result).toBeUndefined();
|
|
328
|
+
});
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
describe('isHTMLEditorLoaded', () => {
|
|
332
|
+
it('is exported as a function', async () => {
|
|
333
|
+
const { isHTMLEditorLoaded } = await import('../index.lazy');
|
|
334
|
+
|
|
335
|
+
expect(typeof isHTMLEditorLoaded).toBe('function');
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
it('returns false when window.__htmlEditorLoaded is not set', async () => {
|
|
339
|
+
const { isHTMLEditorLoaded } = await import('../index.lazy');
|
|
340
|
+
|
|
341
|
+
// The function returns undefined when window.__htmlEditorLoaded is not set
|
|
342
|
+
expect(isHTMLEditorLoaded()).toBeFalsy();
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
it('returns true when window.__htmlEditorLoaded is set', async () => {
|
|
346
|
+
const { isHTMLEditorLoaded } = await import('../index.lazy');
|
|
347
|
+
|
|
348
|
+
if (typeof window !== 'undefined') {
|
|
349
|
+
window.__htmlEditorLoaded = true;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
expect(isHTMLEditorLoaded()).toBe(true);
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
it('handles non-browser environment', async () => {
|
|
356
|
+
const { isHTMLEditorLoaded } = await import('../index.lazy');
|
|
357
|
+
|
|
358
|
+
// In Node.js test environment with jsdom, window is defined
|
|
359
|
+
// The function should return a value (true or falsy)
|
|
360
|
+
const result = isHTMLEditorLoaded();
|
|
361
|
+
expect([true, false, undefined]).toContain(result);
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
it('handles different window states', async () => {
|
|
365
|
+
const { isHTMLEditorLoaded } = await import('../index.lazy');
|
|
366
|
+
|
|
367
|
+
// Should not throw regardless of window state
|
|
368
|
+
expect(() => {
|
|
369
|
+
isHTMLEditorLoaded();
|
|
370
|
+
}).not.toThrow();
|
|
371
|
+
});
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
describe('Module Exports', () => {
|
|
375
|
+
it('exports HTMLEditorLazy as default', async () => {
|
|
376
|
+
const module = await import('../index.lazy');
|
|
377
|
+
|
|
378
|
+
expect(module.default).toBeDefined();
|
|
379
|
+
expect(typeof module.default).toBe('function');
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
it('exports HTMLEditorFallback as named export', async () => {
|
|
383
|
+
const { HTMLEditorFallback } = await import('../index.lazy');
|
|
384
|
+
|
|
385
|
+
expect(HTMLEditorFallback).toBeDefined();
|
|
386
|
+
expect(typeof HTMLEditorFallback).toBe('function');
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
it('exports preloadHTMLEditor as named export', async () => {
|
|
390
|
+
const { preloadHTMLEditor } = await import('../index.lazy');
|
|
391
|
+
|
|
392
|
+
expect(preloadHTMLEditor).toBeDefined();
|
|
393
|
+
expect(typeof preloadHTMLEditor).toBe('function');
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
it('exports isHTMLEditorLoaded as named export', async () => {
|
|
397
|
+
const { isHTMLEditorLoaded } = await import('../index.lazy');
|
|
398
|
+
|
|
399
|
+
expect(isHTMLEditorLoaded).toBeDefined();
|
|
400
|
+
expect(typeof isHTMLEditorLoaded).toBe('function');
|
|
401
|
+
});
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
describe('Integration Tests', () => {
|
|
405
|
+
it('renders complete lazy loading flow', async () => {
|
|
406
|
+
const HTMLEditorLazy = (await import('../index.lazy')).default;
|
|
407
|
+
|
|
408
|
+
const { container } = render(<HTMLEditorLazy variant="email" />);
|
|
409
|
+
|
|
410
|
+
// Container should exist
|
|
411
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
412
|
+
|
|
413
|
+
// Wait for actual component to load
|
|
414
|
+
await waitFor(() => {
|
|
415
|
+
expect(screen.getByTestId('html-editor')).toBeInTheDocument();
|
|
416
|
+
});
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
it('can preload and then render', async () => {
|
|
420
|
+
const { default: HTMLEditorLazy, preloadHTMLEditor } = await import('../index.lazy');
|
|
421
|
+
|
|
422
|
+
// Preload
|
|
423
|
+
preloadHTMLEditor();
|
|
424
|
+
|
|
425
|
+
// Then render
|
|
426
|
+
render(<HTMLEditorLazy variant="email" />);
|
|
427
|
+
|
|
428
|
+
await waitFor(() => {
|
|
429
|
+
expect(screen.getByTestId('html-editor')).toBeInTheDocument();
|
|
430
|
+
});
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
it('handles multiple instances', async () => {
|
|
434
|
+
const HTMLEditorLazy = (await import('../index.lazy')).default;
|
|
435
|
+
|
|
436
|
+
render(
|
|
437
|
+
<>
|
|
438
|
+
<HTMLEditorLazy variant="email" />
|
|
439
|
+
<HTMLEditorLazy variant="inapp" />
|
|
440
|
+
</>
|
|
441
|
+
);
|
|
442
|
+
|
|
443
|
+
await waitFor(() => {
|
|
444
|
+
const editors = screen.getAllByTestId('html-editor');
|
|
445
|
+
expect(editors).toHaveLength(2);
|
|
446
|
+
});
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
it('fallback and main component work together', async () => {
|
|
450
|
+
const { default: HTMLEditorLazy, HTMLEditorFallback } = await import('../index.lazy');
|
|
451
|
+
|
|
452
|
+
// Render fallback independently
|
|
453
|
+
const { unmount } = render(<HTMLEditorFallback message="Custom loading" />);
|
|
454
|
+
expect(screen.getByText('Custom loading')).toBeInTheDocument();
|
|
455
|
+
unmount();
|
|
456
|
+
|
|
457
|
+
// Render lazy component
|
|
458
|
+
render(<HTMLEditorLazy variant="email" />);
|
|
459
|
+
|
|
460
|
+
await waitFor(() => {
|
|
461
|
+
expect(screen.getByTestId('html-editor')).toBeInTheDocument();
|
|
462
|
+
});
|
|
463
|
+
});
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
describe('Edge Cases', () => {
|
|
467
|
+
it('handles undefined props gracefully', async () => {
|
|
468
|
+
const HTMLEditorLazy = (await import('../index.lazy')).default;
|
|
469
|
+
|
|
470
|
+
expect(() => {
|
|
471
|
+
render(<HTMLEditorLazy variant={undefined} />);
|
|
472
|
+
}).not.toThrow();
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
it('handles null props gracefully', async () => {
|
|
476
|
+
const HTMLEditorLazy = (await import('../index.lazy')).default;
|
|
477
|
+
|
|
478
|
+
expect(() => {
|
|
479
|
+
render(<HTMLEditorLazy onSave={null} />);
|
|
480
|
+
}).not.toThrow();
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
it('fallback handles empty message', async () => {
|
|
484
|
+
const { HTMLEditorFallback } = await import('../index.lazy');
|
|
485
|
+
|
|
486
|
+
render(<HTMLEditorFallback message="" />);
|
|
487
|
+
|
|
488
|
+
expect(screen.getByTestId('cap-spin')).toBeInTheDocument();
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
it('fallback handles null message', async () => {
|
|
492
|
+
const { HTMLEditorFallback } = await import('../index.lazy');
|
|
493
|
+
|
|
494
|
+
render(<HTMLEditorFallback message={null} />);
|
|
495
|
+
|
|
496
|
+
// Should render with default message
|
|
497
|
+
expect(screen.getByTestId('cap-spin')).toBeInTheDocument();
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
it('handles rapid mount/unmount', async () => {
|
|
501
|
+
const HTMLEditorLazy = (await import('../index.lazy')).default;
|
|
502
|
+
|
|
503
|
+
const { unmount } = render(<HTMLEditorLazy variant="email" />);
|
|
504
|
+
|
|
505
|
+
// Unmount immediately
|
|
506
|
+
unmount();
|
|
507
|
+
|
|
508
|
+
// Should not throw
|
|
509
|
+
expect(true).toBe(true);
|
|
510
|
+
});
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
describe('Performance and Code Splitting', () => {
|
|
514
|
+
it('lazy component uses React.lazy', async () => {
|
|
515
|
+
const HTMLEditorLazy = (await import('../index.lazy')).default;
|
|
516
|
+
|
|
517
|
+
// The component should be wrapped in Suspense
|
|
518
|
+
const { container } = render(<HTMLEditorLazy variant="email" />);
|
|
519
|
+
|
|
520
|
+
expect(container.firstChild).toBeInTheDocument();
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
it('does not immediately load the actual editor', async () => {
|
|
524
|
+
// This test verifies that import() is used for lazy loading
|
|
525
|
+
const module = await import('../index.lazy');
|
|
526
|
+
|
|
527
|
+
// The default export should be a wrapper component, not the actual editor
|
|
528
|
+
expect(module.default.displayName).toBe('HTMLEditorLazy');
|
|
529
|
+
});
|
|
530
|
+
});
|
|
531
|
+
});
|
|
532
|
+
|