@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.
@@ -45,6 +45,7 @@ export const GIFT_CARDS = 'GIFT_CARDS';
45
45
  export const PROMO_ENGINE = 'PROMO_ENGINE';
46
46
  export const LIQUID_SUPPORT = 'ENABLE_LIQUID_SUPPORT';
47
47
  export const ENABLE_NEW_MPUSH = 'ENABLE_NEW_MPUSH';
48
+ export const ENABLE_NEW_EDITOR_FLOW_INAPP = 'ENABLE_NEW_EDITOR_FLOW_INAPP';
48
49
  export const SUPPORT_CK_EDITOR = 'SUPPORT_CK_EDITOR';
49
50
  export const CUSTOM_TAG = 'CustomTagMessage';
50
51
  export const CUSTOMER_EXTENDED_FIELD = 'Customer extended fields';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capillarytech/creatives-library",
3
3
  "author": "meharaj",
4
- "version": "8.0.304",
4
+ "version": "8.0.306",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
package/utils/common.js CHANGED
@@ -24,7 +24,8 @@ import {
24
24
  ENABLE_WEBPUSH,
25
25
  LIQUID_SUPPORT,
26
26
  SUPPORT_CK_EDITOR,
27
- ENABLE_NEW_MPUSH
27
+ ENABLE_NEW_MPUSH,
28
+ ENABLE_NEW_EDITOR_FLOW_INAPP
28
29
  } from '../constants/unified';
29
30
  import { apiMessageFormatHandler } from './commonUtils';
30
31
 
@@ -142,6 +143,11 @@ export const hasNewMobilePushFeatureEnabled = Auth.hasFeatureAccess.bind(
142
143
  ENABLE_NEW_MPUSH,
143
144
  );
144
145
 
146
+ export const hasNewEditorFlowInAppEnabled = Auth.hasFeatureAccess.bind(
147
+ null,
148
+ ENABLE_NEW_EDITOR_FLOW_INAPP,
149
+ );
150
+
145
151
  //filtering tags based on scope
146
152
  export const filterTags = (tagsToFilter, tagsList) => tagsList?.filter(
147
153
  (tag) => !tagsToFilter?.includes(tag?.definition?.value)
@@ -63,6 +63,7 @@ const CapDeviceContent = (props) => {
63
63
  deepLinkValue,
64
64
  setDeepLinkValue,
65
65
  onCopyTitleAndContent,
66
+ isOtherDeviceSupported,
66
67
  tags,
67
68
  onTagSelect,
68
69
  handleOnTagsContextChange,
@@ -167,13 +168,15 @@ const CapDeviceContent = (props) => {
167
168
  return (
168
169
  <>
169
170
  <CapRow className="creatives-device-content">
170
- <CapLink
171
- title={isAndroid
172
- ? formatMessage(messages.copyContentFromIOS)
173
- : formatMessage(messages.copyCotentFromAndroid)}
174
- className="inapp-copy-content"
175
- onClick={onCopyTitleAndContent}
176
- />
171
+ {isOtherDeviceSupported && (
172
+ <CapLink
173
+ title={isAndroid
174
+ ? formatMessage(messages.copyContentFromIOS)
175
+ : formatMessage(messages.copyCotentFromAndroid)}
176
+ className="inapp-copy-content"
177
+ onClick={onCopyTitleAndContent}
178
+ />
179
+ )}
177
180
  <CapRow className="creatives-inapp-title">
178
181
  <CapColumn
179
182
  className="inapp-content-main"
@@ -1331,7 +1331,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
1331
1331
  }
1332
1332
  onSubmitWrapper = (args) => {
1333
1333
  const {singleTab = null} = args || {};
1334
- if (this.liquidFlow()) {
1334
+ if (this.liquidFlow() && !this.props?.isFullMode) {
1335
1335
  // For MPUSH, we need to validate both Android and iOS content separately
1336
1336
  if (this.props.channel === MOBILE_PUSH || this.props?.schema?.channel?.toUpperCase() === MOBILE_PUSH) {
1337
1337
  this.validateFormBuilderMPush(this.state.formData, singleTab);
@@ -294,6 +294,7 @@ const HTMLEditor = forwardRef(({
294
294
  enableSanitization: true,
295
295
  securityLevel: 'standard',
296
296
  apiValidationErrors, // Pass API validation errors to merge with client-side validation
297
+ isFullMode, // Skip liquid validation in standalone/full mode
297
298
  }, formatSanitizerMessage, formatValidatorMessage);
298
299
 
299
300
  // Expose validation and content state via ref
@@ -1375,6 +1375,7 @@ describe('HTMLEditor', () => {
1375
1375
  debounceMs: 500,
1376
1376
  enableSanitization: true,
1377
1377
  securityLevel: 'standard',
1378
+ isFullMode: true,
1378
1379
  },
1379
1380
  expect.any(Function),
1380
1381
  expect.any(Function)
@@ -155,7 +155,7 @@ describe('useValidation', () => {
155
155
  await Promise.resolve();
156
156
  });
157
157
 
158
- expect(validateHTML).toHaveBeenCalledWith('<p>Test</p>', 'email', null);
158
+ expect(validateHTML).toHaveBeenCalledWith('<p>Test</p>', 'email', null, { skipLiquidValidation: false });
159
159
  });
160
160
 
161
161
  it('updates validation when content changes', async () => {
@@ -472,7 +472,7 @@ describe('useValidation', () => {
472
472
  await Promise.resolve();
473
473
  });
474
474
 
475
- expect(validateHTML).toHaveBeenCalledWith('<p>Test</p>', 'inapp', null);
475
+ expect(validateHTML).toHaveBeenCalledWith('<p>Test</p>', 'inapp', null, { skipLiquidValidation: false });
476
476
  });
477
477
 
478
478
  it('defaults to email variant', async () => {
@@ -487,7 +487,7 @@ describe('useValidation', () => {
487
487
  await Promise.resolve();
488
488
  });
489
489
 
490
- expect(validateHTML).toHaveBeenCalledWith('<p>Test</p>', 'email', null);
490
+ expect(validateHTML).toHaveBeenCalledWith('<p>Test</p>', 'email', null, { skipLiquidValidation: false });
491
491
  });
492
492
  });
493
493
 
@@ -1242,4 +1242,133 @@ describe('useValidation', () => {
1242
1242
  });
1243
1243
  });
1244
1244
  });
1245
+
1246
+ describe('isFullMode - skip liquid validation', () => {
1247
+ it('passes skipLiquidValidation: true to validateHTML when isFullMode is true', async () => {
1248
+ const { validateHTML } = require('../../utils/htmlValidator');
1249
+
1250
+ render(<TestComponent content="<p>Test</p>" options={{ isFullMode: true }} />);
1251
+
1252
+ await act(async () => {
1253
+ jest.advanceTimersByTime(500);
1254
+ await Promise.resolve();
1255
+ await Promise.resolve();
1256
+ await Promise.resolve();
1257
+ });
1258
+
1259
+ expect(validateHTML).toHaveBeenCalledWith('<p>Test</p>', 'email', null, { skipLiquidValidation: true });
1260
+ });
1261
+
1262
+ it('excludes API liquid errors from getAllIssues when isFullMode is true', async () => {
1263
+ let validationState;
1264
+ const onStateChange = (state) => { validationState = state; };
1265
+
1266
+ const apiValidationErrors = {
1267
+ liquidErrors: ['Unsupported tag: points_balance'],
1268
+ standardErrors: [],
1269
+ };
1270
+
1271
+ render(
1272
+ <TestComponent
1273
+ content="<p>Test</p>"
1274
+ options={{ apiValidationErrors, isFullMode: true }}
1275
+ onStateChange={onStateChange}
1276
+ />
1277
+ );
1278
+
1279
+ await act(async () => {
1280
+ jest.advanceTimersByTime(500);
1281
+ await Promise.resolve();
1282
+ await Promise.resolve();
1283
+ await Promise.resolve();
1284
+ });
1285
+
1286
+ await waitFor(() => {
1287
+ expect(validationState).toBeDefined();
1288
+ });
1289
+
1290
+ const issues = validationState.getAllIssues();
1291
+ const liquidIssues = issues.filter((i) => i.source === 'liquid-validator');
1292
+ expect(liquidIssues).toHaveLength(0);
1293
+ });
1294
+
1295
+ it('returns isClean true when only liquid errors exist and isFullMode is true', () => {
1296
+ const apiValidationErrors = {
1297
+ liquidErrors: ['Unsupported tag: points_balance'],
1298
+ standardErrors: [],
1299
+ };
1300
+
1301
+ render(
1302
+ <TestComponent
1303
+ content=""
1304
+ options={{ apiValidationErrors, isFullMode: true }}
1305
+ />
1306
+ );
1307
+
1308
+ // Before validation runs, isClean should be true because liquid errors are ignored in full mode
1309
+ expect(screen.getByTestId('is-clean')).toHaveTextContent('true');
1310
+ });
1311
+
1312
+ it('does not treat liquid errors as blocking when isFullMode is true', async () => {
1313
+ let validationState;
1314
+ const onStateChange = (state) => { validationState = state; };
1315
+
1316
+ const apiValidationErrors = {
1317
+ liquidErrors: ['Unsupported tag: points_balance'],
1318
+ standardErrors: [],
1319
+ };
1320
+
1321
+ render(
1322
+ <TestComponent
1323
+ content="<p>Valid</p>"
1324
+ options={{ apiValidationErrors, isFullMode: true }}
1325
+ onStateChange={onStateChange}
1326
+ />
1327
+ );
1328
+
1329
+ await act(async () => {
1330
+ jest.advanceTimersByTime(500);
1331
+ await Promise.resolve();
1332
+ await Promise.resolve();
1333
+ await Promise.resolve();
1334
+ });
1335
+
1336
+ await waitFor(() => {
1337
+ expect(validationState).toBeDefined();
1338
+ });
1339
+
1340
+ expect(validationState.hasBlockingErrors).toBe(false);
1341
+ });
1342
+
1343
+ it('still treats standard API errors as blocking when isFullMode is true', async () => {
1344
+ let validationState;
1345
+ const onStateChange = (state) => { validationState = state; };
1346
+
1347
+ const apiValidationErrors = {
1348
+ liquidErrors: ['Liquid error'],
1349
+ standardErrors: ['Standard error'],
1350
+ };
1351
+
1352
+ render(
1353
+ <TestComponent
1354
+ content="<p>Valid</p>"
1355
+ options={{ apiValidationErrors, isFullMode: true }}
1356
+ onStateChange={onStateChange}
1357
+ />
1358
+ );
1359
+
1360
+ await act(async () => {
1361
+ jest.advanceTimersByTime(500);
1362
+ await Promise.resolve();
1363
+ await Promise.resolve();
1364
+ await Promise.resolve();
1365
+ });
1366
+
1367
+ await waitFor(() => {
1368
+ expect(validationState).toBeDefined();
1369
+ });
1370
+
1371
+ expect(validationState.hasBlockingErrors).toBe(true);
1372
+ });
1373
+ });
1245
1374
  });
@@ -77,6 +77,7 @@ export const useValidation = (content, variant = 'email', options = {}, formatSa
77
77
  enableSanitization = true,
78
78
  securityLevel = 'standard',
79
79
  apiValidationErrors = null, // API validation errors from validateLiquidTemplateContent
80
+ isFullMode = false, // When true, skip liquid validation (standalone/full mode)
80
81
  } = options;
81
82
 
82
83
  // Validation state
@@ -137,7 +138,7 @@ export const useValidation = (content, variant = 'email', options = {}, formatSa
137
138
 
138
139
  try {
139
140
  // 1. HTML Validation
140
- const htmlValidation = validateHTML(htmlContent, variant, formatValidatorMessage);
141
+ const htmlValidation = validateHTML(htmlContent, variant, formatValidatorMessage, { skipLiquidValidation: isFullMode });
141
142
 
142
143
  // 2. CSS Validation (extract from HTML)
143
144
  const cssValidation = extractAndValidateCSS(htmlContent, formatValidatorMessage);
@@ -206,7 +207,7 @@ export const useValidation = (content, variant = 'email', options = {}, formatSa
206
207
  },
207
208
  }));
208
209
  }
209
- }, [variant, enableSanitization, securityLevel, formatSanitizerMessage, formatValidatorMessage]);
210
+ }, [variant, enableSanitization, securityLevel, formatSanitizerMessage, formatValidatorMessage, isFullMode]);
210
211
 
211
212
  /**
212
213
  * Validates content with debouncing
@@ -339,7 +340,7 @@ export const useValidation = (content, variant = 'email', options = {}, formatSa
339
340
  */
340
341
  const getAllIssues = useCallback(() => {
341
342
  // API errors (liquid + standard) are blocking – they block Save/Update/Preview/Test
342
- const apiLiquidErrors = (apiValidationErrors?.liquidErrors || []).map((errorMessage) => {
343
+ const apiLiquidErrors = (isFullMode ? [] : (apiValidationErrors?.liquidErrors || [])).map((errorMessage) => {
343
344
  const extractedLine = extractLineNumberFromMessage(errorMessage);
344
345
  return {
345
346
  type: VALIDATION_SEVERITY.ERROR,
@@ -420,19 +421,20 @@ export const useValidation = (content, variant = 'email', options = {}, formatSa
420
421
 
421
422
  // Ensure we always return an array
422
423
  return Array.isArray(allIssues) ? allIssues : [];
423
- }, [validationState, apiValidationErrors, extractLineNumberFromMessage, content]);
424
+ }, [validationState, apiValidationErrors, extractLineNumberFromMessage, content, isFullMode]);
424
425
 
425
426
  /**
426
427
  * Check if validation is clean (no errors or warnings)
427
428
  * Includes API validation errors in the check
428
429
  */
429
430
  const isClean = useCallback(() => {
430
- const hasApiErrors = (apiValidationErrors?.liquidErrors?.length || 0) + (apiValidationErrors?.standardErrors?.length || 0) > 0;
431
+ const liquidErrorCount = isFullMode ? 0 : (apiValidationErrors?.liquidErrors?.length || 0);
432
+ const hasApiErrors = liquidErrorCount + (apiValidationErrors?.standardErrors?.length || 0) > 0;
431
433
  return validationState.summary.totalErrors === 0
432
434
  && validationState.summary.totalWarnings === 0
433
435
  && !validationState.summary.hasSecurityIssues
434
436
  && !hasApiErrors;
435
- }, [validationState.summary, apiValidationErrors]);
437
+ }, [validationState.summary, apiValidationErrors, isFullMode]);
436
438
 
437
439
  // Effect to validate content when it changes
438
440
  useEffect(() => {
@@ -448,11 +450,12 @@ export const useValidation = (content, variant = 'email', options = {}, formatSa
448
450
  }
449
451
  }, []);
450
452
 
451
- const hasApiErrors = (apiValidationErrors?.liquidErrors?.length || 0) + (apiValidationErrors?.standardErrors?.length || 0) > 0;
453
+ const hasApiLiquidErrors = isFullMode ? false : (apiValidationErrors?.liquidErrors?.length || 0) > 0;
454
+ const hasApiErrors = hasApiLiquidErrors || (apiValidationErrors?.standardErrors?.length || 0) > 0;
452
455
 
453
456
  const protocolTypes = ['JavaScript Protocol', 'Data URL', 'VBScript Protocol'];
454
- // Client-side Liquid validation errors are blocking (genuine syntax errors)
455
- const hasClientSideLiquidErrors = (validationState.htmlErrors || []).some((e) => e.source === ISSUE_SOURCES.LIQUID && e.severity === VALIDATION_SEVERITY.ERROR);
457
+ // Client-side Liquid validation errors are blocking (genuine syntax errors) - skip in full mode
458
+ const hasClientSideLiquidErrors = isFullMode ? false : (validationState.htmlErrors || []).some((e) => e.source === ISSUE_SOURCES.LIQUID && e.severity === VALIDATION_SEVERITY.ERROR);
456
459
  const hasBlockingErrors = (validationState.sanitizationWarnings || []).some((w) => BLOCKING_ERROR_RULE_IDS.includes(w.rule)) || (validationState.securityIssues || []).some((s) => protocolTypes.includes(s?.type)) || hasApiErrors || hasClientSideLiquidErrors;
457
460
 
458
461
  return {
@@ -76,7 +76,7 @@ const CUSTOM_VALIDATIONS = {
76
76
  * @param {Function} formatMessage - Message formatter function for internationalization
77
77
  * @returns {Object} Validation result with errors and warnings
78
78
  */
79
- export const validateHTML = (html, variant = 'email', formatMessage = defaultMessageFormatter) => {
79
+ export const validateHTML = (html, variant = 'email', formatMessage = defaultMessageFormatter, options = {}) => {
80
80
  if (!html || typeof html !== 'string') {
81
81
  return {
82
82
  isValid: true,
@@ -133,7 +133,9 @@ export const validateHTML = (html, variant = 'email', formatMessage = defaultMes
133
133
  // Always run custom validations and Liquid validation, even if HTMLHint failed
134
134
  // This ensures unsafe protocol detection and other critical validations still run
135
135
  runCustomValidations(html, variant, results, formatMessage);
136
- runLiquidValidation(html, variant, results, formatMessage);
136
+ if (!options.skipLiquidValidation) {
137
+ runLiquidValidation(html, variant, results, formatMessage);
138
+ }
137
139
 
138
140
  return results;
139
141
  };
@@ -40,6 +40,11 @@ function BeePopupEditor(props) {
40
40
  const savedCallback = useRef();
41
41
  const beeInstanceRef = useRef(null);
42
42
  const isInitializedRef = useRef(false);
43
+ const beeJsonRef = useRef(beeJson);
44
+
45
+ useEffect(() => {
46
+ beeJsonRef.current = beeJson;
47
+ }, [beeJson]);
43
48
 
44
49
  const [visibleTaglist, setVisibleTaglist] = useState(false);
45
50
  const [selectedTag, setSelectedTag] = useState({});
@@ -111,8 +116,10 @@ function BeePopupEditor(props) {
111
116
  window.BeePlugin.create(tokenData, beeConfig, (instance) => {
112
117
  beePluginInstance = instance;
113
118
  beeInstanceRef.current = instance;
114
- // Check if beeJson is already an object (happens when layout type changes)
115
- const parseJson = typeof beeJson === 'string' ? JSON.parse(beeJson) : beeJson;
119
+ // Use ref to get the latest beeJson the closure captures the value at effect time,
120
+ // but beeJsonRef.current is always up-to-date (e.g. when template data loads async)
121
+ const latestBeeJson = beeJsonRef.current;
122
+ const parseJson = typeof latestBeeJson === 'string' ? JSON.parse(latestBeeJson) : latestBeeJson;
116
123
  beePluginInstance.start(parseJson);
117
124
  saveBeeInstance(beePluginInstance, device);
118
125
  isInitializedRef.current = true;
@@ -1078,8 +1078,38 @@ export function SlideBoxContent(props) {
1078
1078
  )}
1079
1079
 
1080
1080
  {isCreateInApp && (
1081
- <InAppWrapper
1082
- key="creatives-inapp-wrapper"
1081
+ (isFullMode && !commonUtil.hasNewEditorFlowInAppEnabled()) ||
1082
+ (!isFullMode && isLoyaltyModule) ||
1083
+ (!isFullMode && !isLoyaltyModule && !commonUtil.hasNewEditorFlowInAppEnabled()) ? (
1084
+ <InApp
1085
+ key="creatives-inapp-create"
1086
+ location={{ pathname: '/inapp/create', query, search: '' }}
1087
+ setIsLoadingContent={setIsLoadingContent}
1088
+ isGetFormData={isGetFormData}
1089
+ getFormData={getFormData}
1090
+ getDefaultTags={type}
1091
+ isFullMode={isFullMode}
1092
+ templateData={templateData}
1093
+ cap={cap}
1094
+ showTemplateName={showTemplateName}
1095
+ showLiquidErrorInFooter={showLiquidErrorInFooter}
1096
+ onValidationFail={onValidationFail}
1097
+ forwardedTags={forwardedTags}
1098
+ selectedOfferDetails={selectedOfferDetails}
1099
+ onPreviewContentClicked={onPreviewContentClicked}
1100
+ onTestContentClicked={onTestContentClicked}
1101
+ eventContextTags={eventContextTags}
1102
+ onCreateComplete={onCreateComplete}
1103
+ handleClose={handleClose}
1104
+ moduleType={moduleType}
1105
+ showTestAndPreviewSlidebox={showTestAndPreviewSlidebox}
1106
+ handleTestAndPreview={handleTestAndPreview}
1107
+ handleCloseTestAndPreview={handleCloseTestAndPreview}
1108
+ isTestAndPreviewMode={isTestAndPreviewMode}
1109
+ />
1110
+ ) : (
1111
+ <InAppWrapper
1112
+ key="creatives-inapp-wrapper"
1083
1113
  date={new Date().getMilliseconds()}
1084
1114
  setIsLoadingContent={setIsLoadingContent}
1085
1115
  onInAppEditorTypeChange={onInAppEditorTypeChange}
@@ -1114,10 +1144,12 @@ export function SlideBoxContent(props) {
1114
1144
  handleCloseTestAndPreview={handleCloseTestAndPreview}
1115
1145
  isTestAndPreviewMode={isTestAndPreviewMode}
1116
1146
  />
1147
+ )
1117
1148
  )}
1118
-
1149
+
1119
1150
  {isEditInApp && (<InApp
1120
1151
  isFullMode={isFullMode}
1152
+ isLoyaltyModule={isLoyaltyModule}
1121
1153
  templateData={templateData}
1122
1154
  getFormData={getFormData}
1123
1155
  getDefaultTags={type}
@@ -1,6 +1,5 @@
1
1
  import React from 'react';
2
2
  import { shallowWithIntl } from '../../../helpers/intl-enzym-test-helpers';
3
-
4
3
  import { SlideBoxContent } from '../SlideBoxContent';
5
4
  import mockdata from '../../mockdata';
6
5
  import { templateDetailsImage, templateDetailsVideo, templateDetailsText, templateDetails_ } from '../../Viber/tests/mockData';
@@ -42,6 +41,15 @@ jest.mock('../../WebPush', () => ({
42
41
  ),
43
42
  }));
44
43
 
44
+ jest.mock('v2Containers/InApp', () => () => <div data-test="inapp" />);
45
+ jest.mock('v2Containers/InAppWrapper', () => () => <div data-test="inapp-wrapper" />);
46
+
47
+ jest.mock('../../../utils/commonUtils', () => ({
48
+ hasNewEditorFlowInAppEnabled: jest.fn(),
49
+ }));
50
+
51
+ import commonUtil from '../../../utils/commonUtils';
52
+
45
53
  describe('Test SlideBoxContent container', () => {
46
54
  const onCreateComplete = jest.fn();
47
55
  let renderedComponent;
@@ -910,4 +918,64 @@ describe('Test SlideBoxContent container', () => {
910
918
  expect(renderedComponent).toMatchSnapshot();
911
919
  });
912
920
  });
921
+
922
+ describe('InApp vs InAppWrapper rendering conditions', () => {
923
+
924
+ beforeEach(() => {
925
+ jest.clearAllMocks();
926
+ });
927
+
928
+ it('renders InAppWrapper when isFullMode=true and new editor disabled', () => {
929
+ commonUtil.hasNewEditorFlowInAppEnabled.mockReturnValue(false);
930
+
931
+ renderFunction(
932
+ 'INAPP',
933
+ 'createTemplate',
934
+ { mode: 'create' },
935
+ { isFullMode: true, isLoyaltyModule: false }
936
+ );
937
+
938
+ expect(renderedComponent).toMatchSnapshot();
939
+ });
940
+
941
+ it('renders InApp when isFullMode=false and loyalty module enabled', () => {
942
+ commonUtil.hasNewEditorFlowInAppEnabled.mockReturnValue(false);
943
+
944
+ renderFunction(
945
+ 'INAPP',
946
+ 'createTemplate',
947
+ { mode: 'create' },
948
+ { isFullMode: false, isLoyaltyModule: true }
949
+ );
950
+
951
+ expect(renderedComponent).toMatchSnapshot();
952
+ });
953
+
954
+ it('renders InApp when not full mode, not loyalty and new editor disabled', () => {
955
+ commonUtil.hasNewEditorFlowInAppEnabled.mockReturnValue(false);
956
+
957
+ renderFunction(
958
+ 'INAPP',
959
+ 'createTemplate',
960
+ { mode: 'create' },
961
+ { isFullMode: false, isLoyaltyModule: false }
962
+ );
963
+
964
+ expect(renderedComponent).toMatchSnapshot();
965
+ });
966
+
967
+ it('renders InAppWrapper when full mode and new editor enabled', () => {
968
+ commonUtil.hasNewEditorFlowInAppEnabled.mockReturnValue(true);
969
+
970
+ renderFunction(
971
+ 'INAPP',
972
+ 'createTemplate',
973
+ { mode: 'create' },
974
+ { isFullMode: true, isLoyaltyModule: false }
975
+ );
976
+
977
+ expect(renderedComponent).toMatchSnapshot();
978
+ });
979
+
980
+ });
913
981
  });
@@ -202,6 +202,114 @@ exports[`Test SlideBoxContent container Email component isTestAndPreviewMode IIF
202
202
  </SlideBoxContent__CreativesWrapper>
203
203
  `;
204
204
 
205
+ exports[`Test SlideBoxContent container InApp vs InAppWrapper rendering conditions renders InApp when isFullMode=false and loyalty module enabled 1`] = `
206
+ <SlideBoxContent__CreativesWrapper>
207
+ <Component
208
+ getDefaultTags=""
209
+ isFullMode={false}
210
+ key="creatives-inapp-create"
211
+ location={
212
+ Object {
213
+ "pathname": "/inapp/create",
214
+ "query": Object {
215
+ "isEditFromCampaigns": undefined,
216
+ "module": "library",
217
+ "type": "embedded",
218
+ },
219
+ "search": "",
220
+ }
221
+ }
222
+ onCreateComplete={[MockFunction]}
223
+ templateData={
224
+ Object {
225
+ "mode": "create",
226
+ }
227
+ }
228
+ />
229
+ </SlideBoxContent__CreativesWrapper>
230
+ `;
231
+
232
+ exports[`Test SlideBoxContent container InApp vs InAppWrapper rendering conditions renders InApp when not full mode, not loyalty and new editor disabled 1`] = `
233
+ <SlideBoxContent__CreativesWrapper>
234
+ <Component
235
+ getDefaultTags=""
236
+ isFullMode={false}
237
+ key="creatives-inapp-create"
238
+ location={
239
+ Object {
240
+ "pathname": "/inapp/create",
241
+ "query": Object {
242
+ "isEditFromCampaigns": undefined,
243
+ "module": "library",
244
+ "type": "embedded",
245
+ },
246
+ "search": "",
247
+ }
248
+ }
249
+ onCreateComplete={[MockFunction]}
250
+ templateData={
251
+ Object {
252
+ "mode": "create",
253
+ }
254
+ }
255
+ />
256
+ </SlideBoxContent__CreativesWrapper>
257
+ `;
258
+
259
+ exports[`Test SlideBoxContent container InApp vs InAppWrapper rendering conditions renders InAppWrapper when full mode and new editor enabled 1`] = `
260
+ <SlideBoxContent__CreativesWrapper>
261
+ <Component
262
+ getDefaultTags=""
263
+ isFullMode={true}
264
+ key="creatives-inapp-create"
265
+ location={
266
+ Object {
267
+ "pathname": "/inapp/create",
268
+ "query": Object {
269
+ "isEditFromCampaigns": undefined,
270
+ "module": "default",
271
+ "type": false,
272
+ },
273
+ "search": "",
274
+ }
275
+ }
276
+ onCreateComplete={[MockFunction]}
277
+ templateData={
278
+ Object {
279
+ "mode": "create",
280
+ }
281
+ }
282
+ />
283
+ </SlideBoxContent__CreativesWrapper>
284
+ `;
285
+
286
+ exports[`Test SlideBoxContent container InApp vs InAppWrapper rendering conditions renders InAppWrapper when isFullMode=true and new editor disabled 1`] = `
287
+ <SlideBoxContent__CreativesWrapper>
288
+ <Component
289
+ getDefaultTags=""
290
+ isFullMode={true}
291
+ key="creatives-inapp-create"
292
+ location={
293
+ Object {
294
+ "pathname": "/inapp/create",
295
+ "query": Object {
296
+ "isEditFromCampaigns": undefined,
297
+ "module": "default",
298
+ "type": false,
299
+ },
300
+ "search": "",
301
+ }
302
+ }
303
+ onCreateComplete={[MockFunction]}
304
+ templateData={
305
+ Object {
306
+ "mode": "create",
307
+ }
308
+ }
309
+ />
310
+ </SlideBoxContent__CreativesWrapper>
311
+ `;
312
+
205
313
  exports[`Test SlideBoxContent container Should handle isTestAndPreviewMode IIFE implementation correctly 1`] = `
206
314
  <SlideBoxContent__CreativesWrapper>
207
315
  <ForwardRef
@@ -1103,17 +1211,26 @@ exports[`Test SlideBoxContent container Should render correct component for what
1103
1211
 
1104
1212
  exports[`Test SlideBoxContent container Should render correct component for whatsapp channel create mode 2`] = `
1105
1213
  <SlideBoxContent__CreativesWrapper>
1106
- <Connect(Connect(UserIsAuthenticated(InjectIntl(CreativesCommon))))
1107
- date={0}
1214
+ <Component
1108
1215
  getDefaultTags=""
1109
- key="creatives-inapp-wrapper"
1216
+ key="creatives-inapp-create"
1217
+ location={
1218
+ Object {
1219
+ "pathname": "/inapp/create",
1220
+ "query": Object {
1221
+ "isEditFromCampaigns": undefined,
1222
+ "module": "library",
1223
+ "type": "embedded",
1224
+ },
1225
+ "search": "",
1226
+ }
1227
+ }
1110
1228
  onCreateComplete={[MockFunction]}
1111
1229
  templateData={
1112
1230
  Object {
1113
1231
  "mode": "create",
1114
1232
  }
1115
1233
  }
1116
- type=""
1117
1234
  />
1118
1235
  </SlideBoxContent__CreativesWrapper>
1119
1236
  `;