@capillarytech/creatives-library 8.0.304 → 8.0.306

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.
@@ -956,8 +956,8 @@ const EmailHTMLEditor = (props) => {
956
956
  }
957
957
  };
958
958
 
959
- // If liquid enabled, validate first using extractTags API
960
- if (isLiquidEnabled && getLiquidTags) {
959
+ // If liquid enabled, validate first using extractTags API (skip in full/standalone mode)
960
+ if (isLiquidEnabled && getLiquidTags && !isFullMode) {
961
961
  // Note: API validation errors are already cleared at the start of handleSave
962
962
  // This ensures fresh validation on every save attempt
963
963
 
@@ -1176,9 +1176,10 @@ describe('EmailHTMLEditor', () => {
1176
1176
  mockGetAllIssues.mockReturnValue([]);
1177
1177
 
1178
1178
  // Set subject and content via component interactions
1179
+ // Use isFullMode: false (library mode) to test liquid validation path
1179
1180
  const { rerender } = renderWithIntl({
1180
1181
  isGetFormData: false,
1181
- isFullMode: true,
1182
+ isFullMode: false,
1182
1183
  metaEntities: {
1183
1184
  tags: {
1184
1185
  standard: [{ name: 'customer.name' }],
@@ -1206,7 +1207,7 @@ describe('EmailHTMLEditor', () => {
1206
1207
  <EmailHTMLEditor
1207
1208
  {...defaultProps}
1208
1209
  isGetFormData
1209
- isFullMode
1210
+ isFullMode={false}
1210
1211
  metaEntities={{
1211
1212
  tags: {
1212
1213
  standard: [{ name: 'customer.name' }],
@@ -1231,9 +1232,10 @@ describe('EmailHTMLEditor', () => {
1231
1232
  mockGetAllIssues.mockReturnValue([]);
1232
1233
 
1233
1234
  // Set subject and content via component interactions
1235
+ // Use isFullMode: false (library mode) to test liquid validation path
1234
1236
  const { rerender } = renderWithIntl({
1235
1237
  isGetFormData: false,
1236
- isFullMode: true,
1238
+ isFullMode: false,
1237
1239
  isLiquidEnabled: true,
1238
1240
  getLiquidTags,
1239
1241
  });
@@ -1253,7 +1255,7 @@ describe('EmailHTMLEditor', () => {
1253
1255
  await act(async () => {
1254
1256
  rerender(
1255
1257
  <IntlProvider locale="en" messages={{}}>
1256
- <EmailHTMLEditor {...defaultProps} isGetFormData isFullMode getLiquidTags={getLiquidTags} />
1258
+ <EmailHTMLEditor {...defaultProps} isGetFormData isFullMode={false} getLiquidTags={getLiquidTags} />
1257
1259
  </IntlProvider>
1258
1260
  );
1259
1261
  });
@@ -1281,9 +1283,10 @@ describe('EmailHTMLEditor', () => {
1281
1283
  mockGetAllIssues.mockReturnValue([]);
1282
1284
 
1283
1285
  // Set subject and content via component interactions
1286
+ // Use isFullMode: false (library mode) to test liquid validation path
1284
1287
  const { rerender } = renderWithIntl({
1285
1288
  isGetFormData: false,
1286
- isFullMode: true,
1289
+ isFullMode: false,
1287
1290
  isLiquidEnabled: true,
1288
1291
  getLiquidTags,
1289
1292
  showLiquidErrorInFooter,
@@ -1305,7 +1308,7 @@ describe('EmailHTMLEditor', () => {
1305
1308
  await act(async () => {
1306
1309
  rerender(
1307
1310
  <IntlProvider locale="en" messages={{}}>
1308
- <EmailHTMLEditor {...defaultProps} isGetFormData isFullMode getLiquidTags={getLiquidTags} showLiquidErrorInFooter={showLiquidErrorInFooter} onValidationFail={onValidationFail} />
1311
+ <EmailHTMLEditor {...defaultProps} isGetFormData isFullMode={false} getLiquidTags={getLiquidTags} showLiquidErrorInFooter={showLiquidErrorInFooter} onValidationFail={onValidationFail} />
1309
1312
  </IntlProvider>
1310
1313
  );
1311
1314
  });
@@ -1325,13 +1328,7 @@ describe('EmailHTMLEditor', () => {
1325
1328
  return Promise.resolve(true);
1326
1329
  });
1327
1330
 
1328
- const emailActions = {
1329
- ...defaultProps.emailActions,
1330
- transformEmailTemplate: jest.fn((obj, callback) => callback(obj)),
1331
- createTemplate: jest.fn((obj, callback) => {
1332
- callback({ templateId: { _id: '123', versions: {} } });
1333
- }),
1334
- };
1331
+ const getFormdata = jest.fn();
1335
1332
  const getLiquidTags = jest.fn((content, callback) => {
1336
1333
  callback({ askAiraResponse: { data: [] }, isError: false });
1337
1334
  });
@@ -1339,12 +1336,12 @@ describe('EmailHTMLEditor', () => {
1339
1336
  mockGetAllIssues.mockReturnValue([]);
1340
1337
 
1341
1338
  // Set subject and content via component interactions
1339
+ // Use isFullMode: false (library mode) to test liquid validation path
1342
1340
  const { rerender } = renderWithIntl({
1343
1341
  isGetFormData: false,
1344
- isFullMode: true,
1345
- isLiquidEnabled: true,
1342
+ isFullMode: false,
1346
1343
  getLiquidTags,
1347
- emailActions,
1344
+ getFormdata,
1348
1345
  templateName: 'New Template',
1349
1346
  });
1350
1347
  const input = screen.getByTestId('subject-input');
@@ -1363,7 +1360,7 @@ describe('EmailHTMLEditor', () => {
1363
1360
  await act(async () => {
1364
1361
  rerender(
1365
1362
  <IntlProvider locale="en" messages={{}}>
1366
- <EmailHTMLEditor {...defaultProps} isGetFormData isFullMode getLiquidTags={getLiquidTags} emailActions={emailActions} templateName="New Template" />
1363
+ <EmailHTMLEditor {...defaultProps} isGetFormData isFullMode={false} getLiquidTags={getLiquidTags} getFormdata={getFormdata} templateName="New Template" />
1367
1364
  </IntlProvider>
1368
1365
  );
1369
1366
  });
@@ -1372,8 +1369,9 @@ describe('EmailHTMLEditor', () => {
1372
1369
  expect(validateLiquidTemplateContent).toHaveBeenCalled();
1373
1370
  }, { timeout: 5000 });
1374
1371
 
1372
+ // In library mode (isFullMode=false), save proceeds via getFormdata
1375
1373
  await waitFor(() => {
1376
- expect(emailActions.createTemplate).toHaveBeenCalled();
1374
+ expect(getFormdata).toHaveBeenCalled();
1377
1375
  }, { timeout: 5000 });
1378
1376
  });
1379
1377
 
@@ -2711,4 +2709,98 @@ describe('EmailHTMLEditor', () => {
2711
2709
  expect(screen.getByTestId('html-editor')).toBeInTheDocument();
2712
2710
  });
2713
2711
  });
2712
+
2713
+ describe('isFullMode - skip liquid validation on save', () => {
2714
+ it('skips liquid validation when isFullMode is true', async () => {
2715
+ validateLiquidTemplateContent.mockClear();
2716
+ const getLiquidTags = jest.fn((content, callback) => {
2717
+ callback({ askAiraResponse: { data: [] }, isError: false });
2718
+ });
2719
+ const getFormdata = jest.fn();
2720
+ // Ensure no HTML/Label/Liquid errors from HtmlEditor
2721
+ mockGetAllIssues.mockReturnValue([]);
2722
+
2723
+ const { rerender } = renderWithIntl({
2724
+ isGetFormData: false,
2725
+ isFullMode: true,
2726
+ isLiquidEnabled: true,
2727
+ getLiquidTags,
2728
+ getFormdata,
2729
+ });
2730
+ const input = screen.getByTestId('subject-input');
2731
+ await act(async () => {
2732
+ fireEvent.change(input, { target: { value: 'Valid Subject' } });
2733
+ });
2734
+ const changeButton = screen.getByTestId('trigger-content-change');
2735
+ await act(async () => {
2736
+ fireEvent.click(changeButton);
2737
+ });
2738
+ await act(async () => {
2739
+ await new Promise((resolve) => setTimeout(resolve, 100));
2740
+ });
2741
+ // Trigger save
2742
+ await act(async () => {
2743
+ rerender(
2744
+ <IntlProvider locale="en" messages={{}}>
2745
+ <EmailHTMLEditor {...defaultProps} isGetFormData isFullMode getLiquidTags={getLiquidTags} getFormdata={getFormdata} />
2746
+ </IntlProvider>
2747
+ );
2748
+ });
2749
+
2750
+ // In full mode, liquid validation should be skipped entirely
2751
+ await act(async () => {
2752
+ await new Promise((resolve) => setTimeout(resolve, 200));
2753
+ });
2754
+ expect(validateLiquidTemplateContent).not.toHaveBeenCalled();
2755
+ });
2756
+
2757
+ it('proceeds directly to save without liquid validation in full mode', async () => {
2758
+ validateLiquidTemplateContent.mockClear();
2759
+ const getLiquidTags = jest.fn((content, callback) => {
2760
+ callback({ askAiraResponse: { data: [] }, isError: false });
2761
+ });
2762
+ const emailActions = {
2763
+ ...defaultProps.emailActions,
2764
+ transformEmailTemplate: jest.fn((obj, callback) => callback(obj)),
2765
+ createTemplate: jest.fn((obj, callback) => {
2766
+ callback({ templateId: { _id: '123', versions: {} } });
2767
+ }),
2768
+ };
2769
+ // Ensure no HTML/Label/Liquid errors from HtmlEditor
2770
+ mockGetAllIssues.mockReturnValue([]);
2771
+
2772
+ const { rerender } = renderWithIntl({
2773
+ isGetFormData: false,
2774
+ isFullMode: true,
2775
+ getLiquidTags,
2776
+ emailActions,
2777
+ templateName: 'New Template',
2778
+ });
2779
+ const input = screen.getByTestId('subject-input');
2780
+ await act(async () => {
2781
+ fireEvent.change(input, { target: { value: 'Valid Subject' } });
2782
+ });
2783
+ const changeButton = screen.getByTestId('trigger-content-change');
2784
+ await act(async () => {
2785
+ fireEvent.click(changeButton);
2786
+ });
2787
+ await act(async () => {
2788
+ await new Promise((resolve) => setTimeout(resolve, 100));
2789
+ });
2790
+ // Trigger save
2791
+ await act(async () => {
2792
+ rerender(
2793
+ <IntlProvider locale="en" messages={{}}>
2794
+ <EmailHTMLEditor {...defaultProps} isGetFormData isFullMode getLiquidTags={getLiquidTags} emailActions={emailActions} templateName="New Template" />
2795
+ </IntlProvider>
2796
+ );
2797
+ });
2798
+
2799
+ // Should skip liquid validation and proceed to save directly
2800
+ await waitFor(() => {
2801
+ expect(emailActions.createTemplate).toHaveBeenCalled();
2802
+ }, { timeout: 5000 });
2803
+ expect(validateLiquidTemplateContent).not.toHaveBeenCalled();
2804
+ });
2805
+ });
2714
2806
  });
@@ -39,33 +39,58 @@ jest.mock('../../../utils/common', () => ({
39
39
  // Mock HTMLEditor component - must be before imports
40
40
  jest.mock('../../../v2Components/HtmlEditor', () => {
41
41
  const React = require('react');
42
- const MockHTMLEditor = function MockHTMLEditor({ variant, initialContent, onContentChange, onSave, 'data-test': dataTest }) {
43
- return React.createElement('div', { 'data-testid': dataTest || 'html-editor' },
42
+
43
+ const MockHTMLEditor = function MockHTMLEditor({
44
+ variant,
45
+ initialContent,
46
+ onContentChange,
47
+ onSave,
48
+ 'data-test': dataTest,
49
+ }) {
50
+ return React.createElement(
51
+ 'div',
52
+ { 'data-testid': dataTest || 'inapp-html-editor' },
44
53
  React.createElement('div', { 'data-testid': 'html-editor-variant' }, variant),
45
- React.createElement('div', { 'data-testid': 'html-editor-initial-android' }, initialContent?.android || ''),
46
- React.createElement('div', { 'data-testid': 'html-editor-initial-ios' }, initialContent?.ios || ''),
47
- React.createElement('button', {
48
- 'data-testid': 'html-editor-change-button',
49
- onClick: () => {
50
- if (onContentChange) {
51
- onContentChange({
52
- android: '<p>Updated Android HTML</p>',
53
- ios: '<p>Updated iOS HTML</p>',
54
- });
55
- }
56
- }
57
- }, 'Simulate Content Change'),
58
- React.createElement('button', {
59
- 'data-testid': 'html-editor-save-button',
60
- onClick: () => {
61
- if (onSave) {
62
- onSave({
63
- android: '<p>Saved Android HTML</p>',
64
- ios: '<p>Saved iOS HTML</p>',
65
- });
66
- }
67
- }
68
- }, 'Simulate Save')
54
+ React.createElement(
55
+ 'div',
56
+ { 'data-testid': 'html-editor-initial-android' },
57
+ initialContent?.android || ''
58
+ ),
59
+ React.createElement(
60
+ 'div',
61
+ { 'data-testid': 'html-editor-initial-ios' },
62
+ initialContent?.ios || ''
63
+ ),
64
+ React.createElement(
65
+ 'button',
66
+ {
67
+ 'data-testid': 'html-editor-change-button',
68
+ onClick: () => {
69
+ if (onContentChange) {
70
+ onContentChange({
71
+ android: '<p>Updated Android HTML</p>',
72
+ ios: '<p>Updated iOS HTML</p>',
73
+ });
74
+ }
75
+ },
76
+ },
77
+ 'Simulate Content Change'
78
+ ),
79
+ React.createElement(
80
+ 'button',
81
+ {
82
+ 'data-testid': 'html-editor-save-button',
83
+ onClick: () => {
84
+ if (onSave) {
85
+ onSave({
86
+ android: '<p>Saved Android HTML</p>',
87
+ ios: '<p>Saved iOS HTML</p>',
88
+ });
89
+ }
90
+ },
91
+ },
92
+ 'Simulate Save'
93
+ )
69
94
  );
70
95
  };
71
96
  MockHTMLEditor.displayName = 'MockHTMLEditor';
@@ -75,22 +100,25 @@ jest.mock('../../../v2Components/HtmlEditor', () => {
75
100
  };
76
101
  });
77
102
 
78
- import React from 'react';
79
- import { render, screen, fireEvent, waitFor, act } from '@testing-library/react';
80
- import '@testing-library/jest-dom';
81
- import { IntlProvider } from 'react-intl';
82
- import { Provider } from 'react-redux';
83
- import { configureStore } from '@capillarytech/vulcan-react-sdk/utils';
84
- import history from '../../../utils/history';
85
- import { initialReducer } from '../../../initialReducer';
86
- import { InApp } from '../index';
87
- import { INAPP_EDITOR_TYPES } from '../../InAppWrapper/constants';
88
-
89
-
90
- // Mock other dependencies
103
+ /**
104
+ * Mock CapDeviceContent to ensure HTMLEditor renders
105
+ */
91
106
  jest.mock('../../../v2Components/CapDeviceContent', () => {
107
+ const React = require('react');
108
+ const HTMLEditor = require('../../../v2Components/HtmlEditor').default;
109
+
92
110
  return function MockCapDeviceContent() {
93
- return <div data-testid="cap-device-content">Device Content</div>;
111
+ return (
112
+ <div data-testid="cap-device-content">
113
+ <HTMLEditor
114
+ variant="inapp"
115
+ initialContent={{ android: '', ios: '' }}
116
+ onContentChange={jest.fn()}
117
+ onSave={jest.fn()}
118
+ data-test="inapp-html-editor"
119
+ />
120
+ </div>
121
+ );
94
122
  };
95
123
  });
96
124
 
@@ -100,7 +128,20 @@ jest.mock('../../../v2Components/TemplatePreview', () => {
100
128
  };
101
129
  });
102
130
 
131
+ import React from 'react';
132
+ import { render, screen, fireEvent, act } from '@testing-library/react';
133
+ import '@testing-library/jest-dom';
134
+ import { IntlProvider } from 'react-intl';
135
+ import { Provider } from 'react-redux';
136
+ import { configureStore } from '@capillarytech/vulcan-react-sdk/utils';
137
+
138
+ import history from '../../../utils/history';
139
+ import { initialReducer } from '../../../initialReducer';
140
+ import { InApp } from '../index';
141
+ import { INAPP_EDITOR_TYPES } from '../../InAppWrapper/constants';
142
+
103
143
  let store;
144
+
104
145
  beforeAll(() => {
105
146
  store = configureStore({}, initialReducer, history);
106
147
  });
@@ -135,8 +176,6 @@ const defaultProps = {
135
176
  configs: {
136
177
  android: '1',
137
178
  ios: '1',
138
- accessToken: 'test-token',
139
- deeplink: '{}',
140
179
  },
141
180
  },
142
181
  },
@@ -145,7 +184,6 @@ const defaultProps = {
145
184
  query: {},
146
185
  search: '',
147
186
  },
148
- getDefaultTags: null,
149
187
  supportedTags: [],
150
188
  metaEntities: {
151
189
  tags: {
@@ -158,26 +196,11 @@ const defaultProps = {
158
196
  currentOrgDetails: {
159
197
  accessibleFeatures: [],
160
198
  },
161
- fetchingLiquidValidation: false,
162
- getTemplateDetailsInProgress: false,
163
- isEditInApp: false,
164
- };
165
-
166
- // Create stable defaultData objects outside renderComponent to avoid reference changes
167
- const createStableDefaultData = (editorType) => {
168
- if (!editorType) return {};
169
- return { 'editor-type': editorType };
170
199
  };
171
200
 
172
201
  const renderComponent = (props = {}) => {
173
202
  const mergedProps = { ...defaultProps, ...props };
174
- // Ensure defaultData is always an object and stable
175
- if (!mergedProps.defaultData) {
176
- mergedProps.defaultData = {};
177
- } else if (mergedProps.defaultData['editor-type']) {
178
- // Create a stable reference for defaultData
179
- mergedProps.defaultData = createStableDefaultData(mergedProps.defaultData['editor-type']);
180
- }
203
+
181
204
  return render(
182
205
  <Provider store={store}>
183
206
  <IntlProvider locale="en" messages={{}}>
@@ -195,36 +218,33 @@ describe('InApp HTMLEditor Integration', () => {
195
218
  describe('Template Name Editing', () => {
196
219
  test('should not truncate template name when editing', async () => {
197
220
  const showTemplateNameMock = jest.fn();
221
+
198
222
  renderComponent({
199
- defaultData: { 'editor-type': INAPP_EDITOR_TYPES.HTML_EDITOR, 'template-name': 'abcd' },
223
+ defaultData: {
224
+ 'editor-type': INAPP_EDITOR_TYPES.HTML_EDITOR,
225
+ 'template-name': 'abcd',
226
+ },
200
227
  showTemplateName: showTemplateNameMock,
201
228
  });
202
229
 
203
- // Wait for HTML editor to render
204
- await waitFor(() => {
205
- expect(screen.getByTestId('inapp-html-editor')).toBeInTheDocument();
206
- });
207
-
208
- // Verify showTemplateName was called with the template name
209
- // The template name input is handled by the wrapper, not the InApp component
210
- // So we verify that the callback was set up correctly
230
+ const editor = await screen.findByTestId('inapp-html-editor');
231
+ expect(editor).toBeInTheDocument();
211
232
  expect(showTemplateNameMock).toBeDefined();
212
233
  });
213
234
 
214
235
  test('should preserve template name when showTemplateName callback is provided', async () => {
215
236
  const showTemplateNameMock = jest.fn();
237
+
216
238
  renderComponent({
217
- defaultData: { 'editor-type': INAPP_EDITOR_TYPES.HTML_EDITOR, 'template-name': 'test' },
239
+ defaultData: {
240
+ 'editor-type': INAPP_EDITOR_TYPES.HTML_EDITOR,
241
+ 'template-name': 'test',
242
+ },
218
243
  showTemplateName: showTemplateNameMock,
219
244
  });
220
245
 
221
- // Wait for HTML editor to render
222
- await waitFor(() => {
223
- expect(screen.getByTestId('inapp-html-editor')).toBeInTheDocument();
224
- });
225
-
226
- // Verify the component renders correctly with template name
227
- // The template name is managed by the wrapper component
246
+ const editor = await screen.findByTestId('inapp-html-editor');
247
+ expect(editor).toBeInTheDocument();
228
248
  expect(showTemplateNameMock).toBeDefined();
229
249
  });
230
250
  });
@@ -232,40 +252,7 @@ describe('InApp HTMLEditor Integration', () => {
232
252
  describe('TAG API Calls', () => {
233
253
  test('should only make one TAG API call when HTML Editor is used', async () => {
234
254
  const fetchSchemaForEntityMock = jest.fn();
235
-
236
- renderComponent({
237
- defaultData: { 'editor-type': INAPP_EDITOR_TYPES.HTML_EDITOR },
238
- globalActions: {
239
- ...defaultProps.globalActions,
240
- fetchSchemaForEntity: fetchSchemaForEntityMock,
241
- },
242
- });
243
-
244
- // Wait for component to mount and initialize
245
- await waitFor(() => {
246
- // Component should be rendered
247
- expect(screen.getByTestId('inapp-html-editor')).toBeInTheDocument();
248
- });
249
255
 
250
- // Wait a bit for all useEffects to complete
251
- await waitFor(() => {
252
- // After isHTMLTemplate is set to true, fetchSchemaForEntity should not be called again
253
- // The initial call might happen before isHTMLTemplate is set, but subsequent calls should not happen
254
- // For HTML Editor, tags should only be fetched via handleOnTagsContextChange
255
- }, { timeout: 1000 });
256
-
257
- // For HTML Editor, fetchSchemaForEntity should not be called after isHTMLTemplate is set
258
- // (It might be called once initially before isHTMLTemplate is set, but that's acceptable)
259
- // The key is that it's not called multiple times
260
- const callCount = fetchSchemaForEntityMock.mock.calls.length;
261
- // Allow 0 or 1 calls (1 if it was called before isHTMLTemplate was set)
262
- expect(callCount).toBeLessThanOrEqual(1);
263
- });
264
-
265
- test('should make TAG API call only once when handleOnTagsContextChange is called', async () => {
266
- const fetchSchemaForEntityMock = jest.fn();
267
-
268
- // We need to access the handler, but since it's internal, we'll test via HTMLEditor's onContextChange
269
256
  renderComponent({
270
257
  defaultData: { 'editor-type': INAPP_EDITOR_TYPES.HTML_EDITOR },
271
258
  globalActions: {
@@ -274,19 +261,8 @@ describe('InApp HTMLEditor Integration', () => {
274
261
  },
275
262
  });
276
263
 
277
- await waitFor(() => {
278
- expect(screen.getByTestId('inapp-html-editor')).toBeInTheDocument();
279
- });
280
-
281
- // Wait a bit for all useEffects to complete
282
- await waitFor(() => {
283
- // After isHTMLTemplate is set to true, fetchSchemaForEntity should not be called again
284
- }, { timeout: 1000 });
264
+ await screen.findByTestId('inapp-html-editor');
285
265
 
286
- // Simulate context change from HTMLEditor (which would call onContextChange)
287
- // Since we can't directly access the handler, we verify the behavior
288
- // by checking that fetchSchemaForEntity is not called multiple times
289
- // (It might be called once initially before isHTMLTemplate is set, but that's acceptable)
290
266
  const callCount = fetchSchemaForEntityMock.mock.calls.length;
291
267
  expect(callCount).toBeLessThanOrEqual(1);
292
268
  });
@@ -298,45 +274,37 @@ describe('InApp HTMLEditor Integration', () => {
298
274
  defaultData: { 'editor-type': INAPP_EDITOR_TYPES.HTML_EDITOR },
299
275
  });
300
276
 
301
- await waitFor(() => {
302
- expect(screen.getByTestId('inapp-html-editor')).toBeInTheDocument();
303
- });
277
+ await screen.findByTestId('inapp-html-editor');
304
278
 
305
- // Simulate content being added
306
279
  const changeButton = screen.getByTestId('html-editor-change-button');
280
+
307
281
  act(() => {
308
282
  fireEvent.click(changeButton);
309
283
  });
310
284
 
311
- // Get the layout radio buttons
312
285
  const layoutRadios = container.querySelectorAll('input[type="radio"]');
313
- expect(layoutRadios.length).toBeGreaterThan(0);
314
286
 
315
- // Change layout type
316
287
  if (layoutRadios.length > 1) {
317
288
  act(() => {
318
- fireEvent.change(layoutRadios[1], { target: { value: 'HEADER' } });
289
+ fireEvent.change(layoutRadios[1], {
290
+ target: { value: 'HEADER' },
291
+ });
319
292
  });
320
293
 
321
- // Content should still be present in the editor
322
- // The HTMLEditor should preserve content via initialContent prop
323
- await waitFor(() => {
324
- const editor = screen.getByTestId('inapp-html-editor');
325
- expect(editor).toBeInTheDocument();
326
- });
294
+ const editor = await screen.findByTestId('inapp-html-editor');
295
+ expect(editor).toBeInTheDocument();
327
296
  }
328
297
  });
329
298
  });
330
299
 
331
300
  describe('Layout Labels', () => {
332
301
  test('should use correct layout labels in constants', () => {
333
- const { INAPP_LAYOUT_DETAILS, INAPP_MESSAGE_LAYOUT_TYPES } = require('../constants');
334
-
335
- // Verify that HEADER maps to Top banner
302
+ const { INAPP_LAYOUT_DETAILS, INAPP_MESSAGE_LAYOUT_TYPES } =
303
+ require('../constants');
304
+
336
305
  expect(INAPP_MESSAGE_LAYOUT_TYPES.TOPBANNER).toBe('HEADER');
337
306
  expect(INAPP_LAYOUT_DETAILS.HEADER).toBeDefined();
338
-
339
- // Verify that FOOTER maps to Bottom banner
307
+
340
308
  expect(INAPP_MESSAGE_LAYOUT_TYPES.BOTTOMBANNER).toBe('FOOTER');
341
309
  expect(INAPP_LAYOUT_DETAILS.FOOTER).toBeDefined();
342
310
  });
@@ -346,29 +314,16 @@ describe('InApp HTMLEditor Integration', () => {
346
314
  test('should allow creating template with Android-only content when both devices supported', async () => {
347
315
  renderComponent({
348
316
  defaultData: { 'editor-type': INAPP_EDITOR_TYPES.HTML_EDITOR },
349
- accountData: {
350
- selectedWeChatAccount: {
351
- ...defaultProps.accountData.selectedWeChatAccount,
352
- configs: {
353
- android: '1',
354
- ios: '1',
355
- },
356
- },
357
- },
358
317
  });
359
318
 
360
- await waitFor(() => {
361
- expect(screen.getByTestId('inapp-html-editor')).toBeInTheDocument();
362
- });
319
+ await screen.findByTestId('inapp-html-editor');
363
320
 
364
- // Simulate adding content only for Android
365
321
  const changeButton = screen.getByTestId('html-editor-change-button');
322
+
366
323
  act(() => {
367
324
  fireEvent.click(changeButton);
368
325
  });
369
326
 
370
- // Done button should be enabled (not disabled)
371
- // We can't directly test isDisableDone, but we can verify the component renders
372
327
  expect(screen.getByTestId('inapp-html-editor')).toBeInTheDocument();
373
328
  });
374
329
  });