@capillarytech/creatives-library 9.0.70-alpha.sprint-cap-213712.13 → 9.0.70
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/package.json +1 -1
- package/v2Components/FormBuilder/Classic.js +3 -0
- package/v2Containers/CreativesContainer/SlideBoxContent.js +39 -30
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +6 -2
- package/v2Containers/CreativesContainer/constants.js +1 -0
- package/v2Containers/CreativesContainer/index.js +26 -1
- package/v2Containers/CreativesContainer/messages.js +4 -0
- package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +40 -12
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +10 -0
- package/v2Containers/CreativesContainer/tests/switchToEditAfterCreate.test.js +152 -0
- package/v2Containers/Email/index.js +41 -6
- package/v2Containers/Email/tests/index.test.js +123 -0
- package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +32 -12
- package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +34 -0
- package/v2Containers/InApp/index.js +19 -23
- package/v2Containers/InApp/tests/index.test.js +52 -9
- package/v2Containers/InappAdvance/index.js +19 -24
- package/v2Containers/InappAdvance/tests/index.test.js +39 -15
- package/v2Containers/Line/Container/index.js +18 -8
- package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +129 -108
- package/v2Containers/Line/Container/tests/index.test.js +68 -0
- package/v2Containers/MobilePush/Create/index.js +24 -5
- package/v2Containers/MobilePush/Create/test/stayOpenOnSave.test.js +80 -0
- package/v2Containers/MobilePush/Edit/index.js +15 -9
- package/v2Containers/MobilePush/Edit/test/stayOpenOnSave.test.js +60 -0
- package/v2Containers/MobilePushNew/index.js +41 -7
- package/v2Containers/MobilePushNew/tests/index.test.js +61 -0
- package/v2Containers/Sms/Create/index.js +32 -14
- package/v2Containers/Sms/Create/test/stayOpenOnSave.test.js +92 -0
- package/v2Containers/Sms/Edit/index.js +22 -14
- package/v2Containers/Sms/Edit/tests/index.test.js +66 -0
- package/v2Containers/Templates/index.js +17 -4
- package/v2Containers/Viber/index.js +15 -6
- package/v2Containers/Viber/tests/index.test.js +97 -28
- package/v2Containers/WebPush/Create/components/FormActions.js +1 -1
- package/v2Containers/WebPush/Create/components/FormActions.test.js +3 -3
- package/v2Containers/WebPush/Create/index.js +32 -6
- package/v2Containers/WebPush/Create/messages.js +0 -4
- package/v2Containers/WebPush/Create/tests/stayOpenOnSave.test.js +268 -0
package/package.json
CHANGED
|
@@ -3327,6 +3327,9 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
3327
3327
|
let computedStyle = val.style ?? {};
|
|
3328
3328
|
if (val.id === EXPORT_HTML_LABEL_ID && this.props?.exportHtmlLocked) {
|
|
3329
3329
|
computedStyle = { ...computedStyle, opacity: 0.5, cursor: 'not-allowed', pointerEvents: 'none' };
|
|
3330
|
+
} else if (val.id === EXPORT_HTML_LABEL_ID && this.props?.exportHtmlEnabled) {
|
|
3331
|
+
// Enabled after an in-place save; prop-driven, like the lock above.
|
|
3332
|
+
computedStyle = { ...computedStyle, opacity: 1, cursor: 'pointer', pointerEvents: 'auto' };
|
|
3330
3333
|
}
|
|
3331
3334
|
const divElement = (
|
|
3332
3335
|
<div
|
|
@@ -20,6 +20,7 @@ import { RICH_MEDIA, MAP_TEMPLATE, CREATE } from '../WeChat/Wrapper/constants';
|
|
|
20
20
|
import CallTask from '../CallTask';
|
|
21
21
|
import MobliPushEdit from '../MobilePush/Edit';
|
|
22
22
|
import * as constants from './constants';
|
|
23
|
+
import { SMS as SMS_LOWERCASE } from '../../constants/unified';
|
|
23
24
|
import LineContainer from '../Line/Container';
|
|
24
25
|
import FTP from '../FTP';
|
|
25
26
|
import Viber from '../Viber';
|
|
@@ -184,6 +185,8 @@ export function SlideBoxContent(props) {
|
|
|
184
185
|
onHtmlEditorValidationStateChange,
|
|
185
186
|
onEmbeddedSmsFooterValidity,
|
|
186
187
|
onContentValidityChange,
|
|
188
|
+
canStayOpenAfterCreate,
|
|
189
|
+
onCreateContinuedAsEdit,
|
|
187
190
|
} = props;
|
|
188
191
|
const localTemplatesConfig = props.localTemplatesConfig || pick(props, constants.LOCAL_TEMPLATE_CONFIG_KEYS);
|
|
189
192
|
const useLocalTemplates = !!get(localTemplatesConfig, 'useLocalTemplates');
|
|
@@ -262,6 +265,35 @@ export function SlideBoxContent(props) {
|
|
|
262
265
|
isEditInApp = isEdit && channel === constants.INAPP;
|
|
263
266
|
}
|
|
264
267
|
const isDltEnabled = commonUtil.isTraiDLTEnable(isFullMode, smsRegister);
|
|
268
|
+
|
|
269
|
+
// Shared by the regular and background (create → edit) SMS Edit; each adds its own templateData.
|
|
270
|
+
const smsEditWrapperProps = {
|
|
271
|
+
showLiquidErrorInFooter,
|
|
272
|
+
setIsLoadingContent,
|
|
273
|
+
isEditSms: true,
|
|
274
|
+
location: creativesLocationProps,
|
|
275
|
+
isFullMode,
|
|
276
|
+
route: { name: SMS_LOWERCASE },
|
|
277
|
+
isGetFormData,
|
|
278
|
+
getFormSubscriptionData: getFormData,
|
|
279
|
+
getDefaultTags: type,
|
|
280
|
+
forwardedTags,
|
|
281
|
+
selectedOfferDetails,
|
|
282
|
+
onPreviewContentClicked,
|
|
283
|
+
onTestContentClicked,
|
|
284
|
+
handleClose,
|
|
285
|
+
onCreateComplete,
|
|
286
|
+
smsRegister,
|
|
287
|
+
eventContextTags,
|
|
288
|
+
waitEventContextTags,
|
|
289
|
+
getLiquidTags,
|
|
290
|
+
showTestAndPreviewSlidebox,
|
|
291
|
+
handleTestAndPreview,
|
|
292
|
+
handleCloseTestAndPreview,
|
|
293
|
+
isTestAndPreviewMode,
|
|
294
|
+
onValidationFail,
|
|
295
|
+
onEmbeddedSmsFooterValidity,
|
|
296
|
+
};
|
|
265
297
|
const hasJPLocaleHideFeatureEnabled = commonUtil?.hasJPLocaleHideFeatureEnabled();
|
|
266
298
|
|
|
267
299
|
const getChannelPreviewContent = (templateDataObject) => {
|
|
@@ -579,35 +611,7 @@ export function SlideBoxContent(props) {
|
|
|
579
611
|
/>
|
|
580
612
|
}
|
|
581
613
|
{isEditSms && (
|
|
582
|
-
<SmsWrapper
|
|
583
|
-
showLiquidErrorInFooter={showLiquidErrorInFooter}
|
|
584
|
-
setIsLoadingContent={setIsLoadingContent}
|
|
585
|
-
isEditSms={isEditSms}
|
|
586
|
-
location={creativesLocationProps}
|
|
587
|
-
isFullMode={isFullMode}
|
|
588
|
-
route={{ name: 'sms' }}
|
|
589
|
-
params={{id: templateData._id}}
|
|
590
|
-
isGetFormData={isGetFormData}
|
|
591
|
-
getFormSubscriptionData={getFormData}
|
|
592
|
-
getDefaultTags={type}
|
|
593
|
-
templateData={templateData}
|
|
594
|
-
forwardedTags={forwardedTags}
|
|
595
|
-
selectedOfferDetails={selectedOfferDetails}
|
|
596
|
-
onPreviewContentClicked={onPreviewContentClicked}
|
|
597
|
-
onTestContentClicked={onTestContentClicked}
|
|
598
|
-
handleClose={handleClose}
|
|
599
|
-
onCreateComplete={onCreateComplete}
|
|
600
|
-
smsRegister={smsRegister}
|
|
601
|
-
eventContextTags={eventContextTags}
|
|
602
|
-
waitEventContextTags={waitEventContextTags}
|
|
603
|
-
getLiquidTags={getLiquidTags}
|
|
604
|
-
showTestAndPreviewSlidebox={showTestAndPreviewSlidebox}
|
|
605
|
-
handleTestAndPreview={handleTestAndPreview}
|
|
606
|
-
handleCloseTestAndPreview={handleCloseTestAndPreview}
|
|
607
|
-
isTestAndPreviewMode={isTestAndPreviewMode}
|
|
608
|
-
onValidationFail={onValidationFail}
|
|
609
|
-
onEmbeddedSmsFooterValidity={onEmbeddedSmsFooterValidity}
|
|
610
|
-
/>
|
|
614
|
+
<SmsWrapper {...smsEditWrapperProps} templateData={templateData} />
|
|
611
615
|
)}
|
|
612
616
|
{isEditFTP && (
|
|
613
617
|
<FTP
|
|
@@ -667,7 +671,7 @@ export function SlideBoxContent(props) {
|
|
|
667
671
|
showLiquidErrorInFooter={showLiquidErrorInFooter}
|
|
668
672
|
setIsLoadingContent={setIsLoadingContent}
|
|
669
673
|
location={creativesLocationProps}
|
|
670
|
-
route={{ name:
|
|
674
|
+
route={{ name: SMS_LOWERCASE }}
|
|
671
675
|
isCreateSms={isCreateSms}
|
|
672
676
|
isComponent
|
|
673
677
|
templateData={templateData}
|
|
@@ -1289,6 +1293,8 @@ export function SlideBoxContent(props) {
|
|
|
1289
1293
|
isAnonymousType={isAnonymousType}
|
|
1290
1294
|
waitEventContextTags={waitEventContextTags}
|
|
1291
1295
|
onContentValidityChange={onContentValidityChange}
|
|
1296
|
+
canStayOpenAfterCreate={canStayOpenAfterCreate}
|
|
1297
|
+
onCreateContinuedAsEdit={onCreateContinuedAsEdit}
|
|
1292
1298
|
/>
|
|
1293
1299
|
)}
|
|
1294
1300
|
{isCreateRcs && (<Rcs
|
|
@@ -1349,6 +1355,9 @@ SlideBoxContent.propTypes = {
|
|
|
1349
1355
|
onResetStep: PropTypes.func,
|
|
1350
1356
|
onCallTaskSubmit: PropTypes.func,
|
|
1351
1357
|
isFullMode: PropTypes.bool,
|
|
1358
|
+
// Full mode: host allows a create to continue in place as an edit (edit permission)
|
|
1359
|
+
canStayOpenAfterCreate: PropTypes.bool,
|
|
1360
|
+
onCreateContinuedAsEdit: PropTypes.func,
|
|
1352
1361
|
setIsLoadingContent: PropTypes.func,
|
|
1353
1362
|
onMobilepushModeChange: PropTypes.func,
|
|
1354
1363
|
mobilePushCreateMode: PropTypes.string,
|
|
@@ -11,7 +11,11 @@ import { EMAIL_CREATE_MODES } from '../EmailWrapper/constants';
|
|
|
11
11
|
import { hasSupportCKEditor } from '../../utils/common';
|
|
12
12
|
import { getMessageForDevice, getTitleForDevice } from '../../utils/commonUtils';
|
|
13
13
|
|
|
14
|
-
function getFullModeSaveBtn(slidBoxContent, isCreatingTemplate) {
|
|
14
|
+
function getFullModeSaveBtn(slidBoxContent, isCreatingTemplate, isStayOpenChannel) {
|
|
15
|
+
// Email / push: "Save" in both modes
|
|
16
|
+
if (isStayOpenChannel) {
|
|
17
|
+
return <FormattedMessage {...messages.creativesTemplatesSaveButton} />;
|
|
18
|
+
}
|
|
15
19
|
if (isCreatingTemplate) {
|
|
16
20
|
return <FormattedMessage {...messages.creativesTemplatesDone} />;
|
|
17
21
|
}
|
|
@@ -171,7 +175,7 @@ function SlideBoxFooter(props) {
|
|
|
171
175
|
|
|
172
176
|
function getSaveButtonLabel() {
|
|
173
177
|
if (primarySaveButtonMessage) return <FormattedMessage {...primarySaveButtonMessage} />;
|
|
174
|
-
if (isFullMode) return getFullModeSaveBtn(slidBoxContent, isCreatingTemplate);
|
|
178
|
+
if (isFullMode) return getFullModeSaveBtn(slidBoxContent, isCreatingTemplate, isEmailChannel || isMobilePushChannel);
|
|
175
179
|
return <FormattedMessage {...messages.creativesTemplatesSave} />;
|
|
176
180
|
}
|
|
177
181
|
|
|
@@ -25,6 +25,7 @@ export const INAPP = "INAPP";
|
|
|
25
25
|
export const WEBPUSH = "WEBPUSH";
|
|
26
26
|
export const WEBPUSH_BRAND_ICON = "WEBPUSH_BRAND_ICON";
|
|
27
27
|
export const PREVIEW = "preview";
|
|
28
|
+
export const CREATE_TEMPLATE = "createTemplate";
|
|
28
29
|
export const EDIT_TEMPLATE = "editTemplate";
|
|
29
30
|
export const JOURNEY = "journey";
|
|
30
31
|
export const HTML = "HTML";
|
|
@@ -200,6 +200,8 @@ export class Creatives extends React.Component {
|
|
|
200
200
|
// Live content-validity signal for channels that report it (currently SMS create) —
|
|
201
201
|
// false by default so unwired channels are never blocked by this flag.
|
|
202
202
|
isContentInvalid: false,
|
|
203
|
+
// Full mode: a create continued in place as an edit (form kept) — header shows the edit title
|
|
204
|
+
isCreateContinuedAsEdit: false,
|
|
203
205
|
};
|
|
204
206
|
this.creativesTemplateSteps = {
|
|
205
207
|
1: 'modeSelection',
|
|
@@ -1703,7 +1705,24 @@ export class Creatives extends React.Component {
|
|
|
1703
1705
|
};
|
|
1704
1706
|
}
|
|
1705
1707
|
|
|
1708
|
+
// Channel kept its form after a create and will update on the next save: show the edit header
|
|
1709
|
+
handleCreateContinuedAsEdit = () => {
|
|
1710
|
+
if (!this.state.isCreateContinuedAsEdit) {
|
|
1711
|
+
this.setState({ isCreateContinuedAsEdit: true });
|
|
1712
|
+
}
|
|
1713
|
+
};
|
|
1714
|
+
|
|
1706
1715
|
getFormData = (template) => {
|
|
1716
|
+
// Full-mode save that stays open: host only refreshes its list (creates need edit permission).
|
|
1717
|
+
const canStayOpen = this.state.slidBoxContent !== constants.CREATE_TEMPLATE || this.props.switchToEditAfterCreate;
|
|
1718
|
+
if (this.props.isFullMode && template?.keepSlideBoxOpen && canStayOpen) {
|
|
1719
|
+
this.setState({ isGetFormData: false });
|
|
1720
|
+
if (template.continuedAsEdit) {
|
|
1721
|
+
this.handleCreateContinuedAsEdit(); // header switches to the edit title
|
|
1722
|
+
}
|
|
1723
|
+
this.props.getCreativesData({ channel: this.state.currentChannel?.toUpperCase(), keepSlideBoxOpen: true });
|
|
1724
|
+
return;
|
|
1725
|
+
}
|
|
1707
1726
|
// Always reset isGetFormData so the child does not re-send form data on every re-render
|
|
1708
1727
|
// (e.g. when user fixes validation error by typing, we must not auto-close the slidebox)
|
|
1709
1728
|
this.setState(
|
|
@@ -2336,7 +2355,10 @@ export class Creatives extends React.Component {
|
|
|
2336
2355
|
key="creatives-container-slidebox-header"
|
|
2337
2356
|
channel={currentChannel}
|
|
2338
2357
|
messages={this.props.messages}
|
|
2339
|
-
|
|
2358
|
+
// Edit title after an in-place create
|
|
2359
|
+
slidBoxContent={this.state.isCreateContinuedAsEdit && this.state.slidBoxContent === constants.CREATE_TEMPLATE
|
|
2360
|
+
? constants.EDIT_TEMPLATE
|
|
2361
|
+
: this.state.slidBoxContent}
|
|
2340
2362
|
templateData={templateData}
|
|
2341
2363
|
onShowTemplates={this.onShowTemplates}
|
|
2342
2364
|
creativesMode={creativesMode}
|
|
@@ -2439,6 +2461,8 @@ export class Creatives extends React.Component {
|
|
|
2439
2461
|
onContentValidityChange={this.handleContentValidityChange}
|
|
2440
2462
|
onPersonalizationTokensChange={this.handlePersonalizationTokensChange}
|
|
2441
2463
|
localTemplatesConfig={pick(this.props.localTemplatesConfig || this.props, constants.LOCAL_TEMPLATE_CONFIG_KEYS)}
|
|
2464
|
+
canStayOpenAfterCreate={!!(isFullMode && this.props.switchToEditAfterCreate)}
|
|
2465
|
+
onCreateContinuedAsEdit={this.handleCreateContinuedAsEdit}
|
|
2442
2466
|
/>
|
|
2443
2467
|
)}
|
|
2444
2468
|
footer={this.shouldShowFooter() ? (
|
|
@@ -2505,6 +2529,7 @@ Creatives.propTypes = {
|
|
|
2505
2529
|
handleCloseCreatives: PropTypes.func,
|
|
2506
2530
|
templateData: PropTypes.object,
|
|
2507
2531
|
isFullMode: PropTypes.bool,
|
|
2532
|
+
switchToEditAfterCreate: PropTypes.bool,
|
|
2508
2533
|
channel: PropTypes.string,
|
|
2509
2534
|
templateActions: PropTypes.object,
|
|
2510
2535
|
globalActions: PropTypes.object,
|
|
@@ -282,6 +282,10 @@ export default defineMessages({
|
|
|
282
282
|
id: `${scope}.creativesTemplatesUpdate`,
|
|
283
283
|
defaultMessage: `Update`,
|
|
284
284
|
},
|
|
285
|
+
"creativesTemplatesSaveButton": {
|
|
286
|
+
id: `${scope}.creativesTemplatesSaveButton`,
|
|
287
|
+
defaultMessage: `Save`,
|
|
288
|
+
},
|
|
285
289
|
"creativesTemplatesDone": {
|
|
286
290
|
id: `${scope}.creativesTemplatesDone`,
|
|
287
291
|
defaultMessage: `Done`,
|
|
@@ -61,7 +61,7 @@ describe("test for empty email empty template name", () => {
|
|
|
61
61
|
renderComponent(props);
|
|
62
62
|
const errorMessage = await screen.findByText(/template name cannot be empty/i);
|
|
63
63
|
expect(errorMessage).toBeInTheDocument();
|
|
64
|
-
const updateBtn = screen.getByRole('button', { name:
|
|
64
|
+
const updateBtn = screen.getByRole('button', { name: /^save$/i });
|
|
65
65
|
expect(updateBtn).toBeDisabled();
|
|
66
66
|
renderComponent({
|
|
67
67
|
...props,
|
|
@@ -71,7 +71,7 @@ describe("test for empty email empty template name", () => {
|
|
|
71
71
|
issueCounts: { html: 0, label: 0, liquid: 0, total: 0 },
|
|
72
72
|
},
|
|
73
73
|
});
|
|
74
|
-
const updateBtns = screen.getAllByRole('button', { name:
|
|
74
|
+
const updateBtns = screen.getAllByRole('button', { name: /^save$/i });
|
|
75
75
|
expect(updateBtns[1]).toBeEnabled();
|
|
76
76
|
});
|
|
77
77
|
});
|
|
@@ -96,7 +96,7 @@ describe('shouldCheckValidation (line 79)', () => {
|
|
|
96
96
|
issueCounts: { html: 1, label: 0, liquid: 0, total: 1 },
|
|
97
97
|
},
|
|
98
98
|
});
|
|
99
|
-
const updateBtn = screen.getByRole('button', { name:
|
|
99
|
+
const updateBtn = screen.getByRole('button', { name: /^save$/i });
|
|
100
100
|
expect(updateBtn).toBeDisabled();
|
|
101
101
|
});
|
|
102
102
|
|
|
@@ -115,7 +115,7 @@ describe('shouldCheckValidation (line 79)', () => {
|
|
|
115
115
|
issueCounts: { html: 0, label: 0, liquid: 0, total: 0 },
|
|
116
116
|
},
|
|
117
117
|
});
|
|
118
|
-
const updateBtn = screen.getByRole('button', { name:
|
|
118
|
+
const updateBtn = screen.getByRole('button', { name: /^save$/i });
|
|
119
119
|
expect(updateBtn).toBeEnabled();
|
|
120
120
|
});
|
|
121
121
|
|
|
@@ -147,7 +147,7 @@ describe('shouldCheckValidation (line 79)', () => {
|
|
|
147
147
|
slidBoxContent: 'editTemplate',
|
|
148
148
|
htmlEditorValidationState: null,
|
|
149
149
|
});
|
|
150
|
-
const updateBtn = screen.getByRole('button', { name:
|
|
150
|
+
const updateBtn = screen.getByRole('button', { name: /^save$/i });
|
|
151
151
|
expect(updateBtn).toBeEnabled();
|
|
152
152
|
});
|
|
153
153
|
|
|
@@ -166,7 +166,7 @@ describe('shouldCheckValidation (line 79)', () => {
|
|
|
166
166
|
issueCounts: { html: 1, label: 0, liquid: 0, total: 1 },
|
|
167
167
|
},
|
|
168
168
|
});
|
|
169
|
-
const updateBtn = screen.getByRole('button', { name:
|
|
169
|
+
const updateBtn = screen.getByRole('button', { name: /^save$/i });
|
|
170
170
|
expect(updateBtn).toBeEnabled();
|
|
171
171
|
});
|
|
172
172
|
|
|
@@ -187,7 +187,7 @@ describe('shouldCheckValidation (line 79)', () => {
|
|
|
187
187
|
issueCounts: { html: 0, label: 0, liquid: 0, total: 0 },
|
|
188
188
|
},
|
|
189
189
|
});
|
|
190
|
-
const saveBtn = screen.getByRole('button', { name:
|
|
190
|
+
const saveBtn = screen.getByRole('button', { name: /^save$/i });
|
|
191
191
|
expect(saveBtn).toBeDisabled();
|
|
192
192
|
});
|
|
193
193
|
|
|
@@ -555,7 +555,7 @@ describe('SlideBoxFooter — isHtmlEditorValidationStateActive via issueCounts',
|
|
|
555
555
|
// isHtmlEditorValidationStateActive = true (via issueCounts.total > 0)
|
|
556
556
|
// isHTMLEditorModeInEdit = true, shouldCheckValidation = true
|
|
557
557
|
// hasValidationErrors = false, shouldDisableButtons = false (no hasErrors)
|
|
558
|
-
const updateBtn = screen.getByRole('button', { name:
|
|
558
|
+
const updateBtn = screen.getByRole('button', { name: /^save$/i });
|
|
559
559
|
expect(updateBtn).toBeEnabled();
|
|
560
560
|
});
|
|
561
561
|
|
|
@@ -578,7 +578,7 @@ describe('SlideBoxFooter — isHtmlEditorValidationStateActive via issueCounts',
|
|
|
578
578
|
// isHtmlEditorValidationStateActive = false → isHTMLEditorModeInEdit = false
|
|
579
579
|
// isBEEEditor = true (isEditMode && !isHtmlEditorValidationStateActive)
|
|
580
580
|
// shouldCheckValidation = false → button enabled
|
|
581
|
-
const updateBtn = screen.getByRole('button', { name:
|
|
581
|
+
const updateBtn = screen.getByRole('button', { name: /^save$/i });
|
|
582
582
|
expect(updateBtn).toBeEnabled();
|
|
583
583
|
});
|
|
584
584
|
});
|
|
@@ -607,7 +607,7 @@ describe('SlideBoxFooter — isBEEEditor detection in create mode via emailCreat
|
|
|
607
607
|
});
|
|
608
608
|
// selectedEmailCreateMode=drag_drop → isBEEEditor = true (DRAG_DROP branch)
|
|
609
609
|
// shouldCheckValidation = false → button not disabled by validation
|
|
610
|
-
const createBtn = screen.getByRole('button', { name:
|
|
610
|
+
const createBtn = screen.getByRole('button', { name: /^save$/i });
|
|
611
611
|
expect(createBtn).toBeInTheDocument();
|
|
612
612
|
});
|
|
613
613
|
|
|
@@ -630,7 +630,7 @@ describe('SlideBoxFooter — isBEEEditor detection in create mode via emailCreat
|
|
|
630
630
|
});
|
|
631
631
|
// isHTMLEditorModeInCreate = false (selectedEmailCreateMode is undefined, not html_editor)
|
|
632
632
|
// emailCreateMode === 'editor' && !isHTMLEditorMode → isBEEEditor = true
|
|
633
|
-
const createBtn = screen.getByRole('button', { name:
|
|
633
|
+
const createBtn = screen.getByRole('button', { name: /^save$/i });
|
|
634
634
|
expect(createBtn).toBeInTheDocument();
|
|
635
635
|
expect(createBtn).not.toBeDisabled();
|
|
636
636
|
});
|
|
@@ -687,4 +687,32 @@ describe('SlideBoxFooter — isContentInvalid (live content-validity signal, e.g
|
|
|
687
687
|
});
|
|
688
688
|
expect(screen.getByRole('button', { name: /update/i })).not.toBeDisabled();
|
|
689
689
|
});
|
|
690
|
-
});
|
|
690
|
+
});
|
|
691
|
+
|
|
692
|
+
describe('SlideBoxFooter — full-mode email button label', () => {
|
|
693
|
+
it.each([
|
|
694
|
+
['create', 'createTemplate', true],
|
|
695
|
+
['edit', 'editTemplate', false],
|
|
696
|
+
])('reads "Save" in %s mode', (_mode, slidBoxContent, isCreatingTemplate) => {
|
|
697
|
+
renderComponent({
|
|
698
|
+
...baseFooterProps,
|
|
699
|
+
currentChannel: 'EMAIL',
|
|
700
|
+
slidBoxContent,
|
|
701
|
+
isCreatingTemplate,
|
|
702
|
+
});
|
|
703
|
+
expect(screen.getByRole('button', { name: /^save$/i })).toBeInTheDocument();
|
|
704
|
+
});
|
|
705
|
+
});
|
|
706
|
+
describe('SlideBoxFooter — full-mode push notification button label', () => {
|
|
707
|
+
it.each([
|
|
708
|
+
['create', 'createTemplate'],
|
|
709
|
+
['edit', 'editTemplate'],
|
|
710
|
+
])('reads "Save" in %s mode', (_mode, slidBoxContent) => {
|
|
711
|
+
renderComponent({
|
|
712
|
+
...baseFooterProps,
|
|
713
|
+
currentChannel: 'MOBILEPUSH',
|
|
714
|
+
slidBoxContent,
|
|
715
|
+
});
|
|
716
|
+
expect(screen.getByRole('button', { name: /^save$/i })).toBeInTheDocument();
|
|
717
|
+
});
|
|
718
|
+
});
|
|
@@ -9,6 +9,7 @@ exports[`Test SlideBoxContent container campaign message, add creative click rcs
|
|
|
9
9
|
<CapSlideBox
|
|
10
10
|
content={
|
|
11
11
|
<SlideBoxContent
|
|
12
|
+
canStayOpenAfterCreate={false}
|
|
12
13
|
channelsToHide={Array []}
|
|
13
14
|
currentChannel="RCS"
|
|
14
15
|
customerType=""
|
|
@@ -30,6 +31,7 @@ exports[`Test SlideBoxContent container campaign message, add creative click rcs
|
|
|
30
31
|
onChannelChange={[Function]}
|
|
31
32
|
onContentValidityChange={[Function]}
|
|
32
33
|
onCreateComplete={[MockFunction]}
|
|
34
|
+
onCreateContinuedAsEdit={[Function]}
|
|
33
35
|
onCreateNew={[Function]}
|
|
34
36
|
onCreateNextStep={[Function]}
|
|
35
37
|
onEmailModeChange={[Function]}
|
|
@@ -105,6 +107,7 @@ exports[`Test SlideBoxContent container campaign message, add creative click wha
|
|
|
105
107
|
<CapSlideBox
|
|
106
108
|
content={
|
|
107
109
|
<SlideBoxContent
|
|
110
|
+
canStayOpenAfterCreate={false}
|
|
108
111
|
channelsToHide={Array []}
|
|
109
112
|
currentChannel="WHATSAPP"
|
|
110
113
|
customerType=""
|
|
@@ -126,6 +129,7 @@ exports[`Test SlideBoxContent container campaign message, add creative click wha
|
|
|
126
129
|
onChannelChange={[Function]}
|
|
127
130
|
onContentValidityChange={[Function]}
|
|
128
131
|
onCreateComplete={[MockFunction]}
|
|
132
|
+
onCreateContinuedAsEdit={[Function]}
|
|
129
133
|
onCreateNew={[Function]}
|
|
130
134
|
onCreateNextStep={[Function]}
|
|
131
135
|
onEmailModeChange={[Function]}
|
|
@@ -201,6 +205,7 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit all data
|
|
|
201
205
|
<CapSlideBox
|
|
202
206
|
content={
|
|
203
207
|
<SlideBoxContent
|
|
208
|
+
canStayOpenAfterCreate={false}
|
|
204
209
|
channelsToHide={Array []}
|
|
205
210
|
currentChannel="WHATSAPP"
|
|
206
211
|
customerType=""
|
|
@@ -222,6 +227,7 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit all data
|
|
|
222
227
|
onChannelChange={[Function]}
|
|
223
228
|
onContentValidityChange={[Function]}
|
|
224
229
|
onCreateComplete={[MockFunction]}
|
|
230
|
+
onCreateContinuedAsEdit={[Function]}
|
|
225
231
|
onCreateNew={[Function]}
|
|
226
232
|
onCreateNextStep={[Function]}
|
|
227
233
|
onEmailModeChange={[Function]}
|
|
@@ -341,6 +347,7 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit min data
|
|
|
341
347
|
<CapSlideBox
|
|
342
348
|
content={
|
|
343
349
|
<SlideBoxContent
|
|
350
|
+
canStayOpenAfterCreate={false}
|
|
344
351
|
channelsToHide={Array []}
|
|
345
352
|
currentChannel="WHATSAPP"
|
|
346
353
|
customerType=""
|
|
@@ -362,6 +369,7 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit min data
|
|
|
362
369
|
onChannelChange={[Function]}
|
|
363
370
|
onContentValidityChange={[Function]}
|
|
364
371
|
onCreateComplete={[MockFunction]}
|
|
372
|
+
onCreateContinuedAsEdit={[Function]}
|
|
365
373
|
onCreateNew={[Function]}
|
|
366
374
|
onCreateNextStep={[Function]}
|
|
367
375
|
onEmailModeChange={[Function]}
|
|
@@ -481,6 +489,7 @@ exports[`Test SlideBoxContent container it should clear the url, on channel chan
|
|
|
481
489
|
<CapSlideBox
|
|
482
490
|
content={
|
|
483
491
|
<SlideBoxContent
|
|
492
|
+
canStayOpenAfterCreate={false}
|
|
484
493
|
channelsToHide={Array []}
|
|
485
494
|
currentChannel="WHATSAPP"
|
|
486
495
|
customerType=""
|
|
@@ -502,6 +511,7 @@ exports[`Test SlideBoxContent container it should clear the url, on channel chan
|
|
|
502
511
|
onChannelChange={[Function]}
|
|
503
512
|
onContentValidityChange={[Function]}
|
|
504
513
|
onCreateComplete={[MockFunction]}
|
|
514
|
+
onCreateContinuedAsEdit={[Function]}
|
|
505
515
|
onCreateNew={[Function]}
|
|
506
516
|
onCreateNextStep={[Function]}
|
|
507
517
|
onEmailModeChange={[Function]}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { shallowWithIntl } from '../../../helpers/intl-enzym-test-helpers';
|
|
3
|
+
|
|
4
|
+
import { Creatives } from '../index';
|
|
5
|
+
import { SMS } from '../constants';
|
|
6
|
+
|
|
7
|
+
jest.mock('../../../v2Components/FormBuilder', () => ({
|
|
8
|
+
__esModule: true,
|
|
9
|
+
default: () => <div className="FormBuilder-mock">FormBuilder</div>,
|
|
10
|
+
}));
|
|
11
|
+
|
|
12
|
+
describe('CreativesContainer: full-mode SMS create continues in place', () => {
|
|
13
|
+
const getCreativesData = jest.fn();
|
|
14
|
+
const handleCloseCreatives = jest.fn();
|
|
15
|
+
|
|
16
|
+
const render = (props = {}) => shallowWithIntl(
|
|
17
|
+
<Creatives
|
|
18
|
+
isFullMode
|
|
19
|
+
creativesMode="create"
|
|
20
|
+
channel="SMS"
|
|
21
|
+
templateData={{ mode: 'create' }}
|
|
22
|
+
Templates={{}}
|
|
23
|
+
getCreativesData={getCreativesData}
|
|
24
|
+
handleCloseCreatives={handleCloseCreatives}
|
|
25
|
+
switchToEditAfterCreate
|
|
26
|
+
{...props}
|
|
27
|
+
/>,
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
beforeEach(() => jest.clearAllMocks());
|
|
31
|
+
|
|
32
|
+
it('create save: stays open, refreshes the host list and switches the header (content stays as is)', () => {
|
|
33
|
+
const wrapper = render();
|
|
34
|
+
wrapper.instance().getFormData({ _id: 'tpl-1', validity: true, keepSlideBoxOpen: true, continuedAsEdit: true });
|
|
35
|
+
wrapper.update();
|
|
36
|
+
|
|
37
|
+
expect(getCreativesData).toHaveBeenCalledWith({ channel: SMS, keepSlideBoxOpen: true });
|
|
38
|
+
expect(handleCloseCreatives).not.toHaveBeenCalled();
|
|
39
|
+
expect(wrapper.state('slidBoxContent')).toBe('createTemplate');
|
|
40
|
+
expect(wrapper.find('CapSlideBox').prop('header').props.slidBoxContent).toBe('editTemplate');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('on an edit save in full mode, keeps the slidebox open and only lets the host refresh', () => {
|
|
44
|
+
const instance = render({ creativesMode: 'edit', templateData: { _id: 'tpl-1', type: SMS } }).instance();
|
|
45
|
+
expect(instance.state.slidBoxContent).toBe('editTemplate');
|
|
46
|
+
instance.setState({ isGetFormData: true });
|
|
47
|
+
instance.getFormData({ value: { base: {} }, _id: 'tpl-1', validity: true, keepSlideBoxOpen: true });
|
|
48
|
+
|
|
49
|
+
expect(instance.state.slidBoxContent).toBe('editTemplate');
|
|
50
|
+
expect(instance.state.showSlideBox).toBe(true);
|
|
51
|
+
expect(instance.state.isGetFormData).toBe(false);
|
|
52
|
+
expect(getCreativesData).toHaveBeenCalledTimes(1);
|
|
53
|
+
expect(getCreativesData).toHaveBeenCalledWith({ channel: SMS, keepSlideBoxOpen: true });
|
|
54
|
+
expect(handleCloseCreatives).not.toHaveBeenCalled();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('create save without edit permission closes as before (no header switch)', () => {
|
|
58
|
+
const wrapper = render({ switchToEditAfterCreate: false });
|
|
59
|
+
wrapper.instance().getFormData({ _id: 'tpl-1', validity: true, keepSlideBoxOpen: true, continuedAsEdit: true });
|
|
60
|
+
|
|
61
|
+
expect(getCreativesData).not.toHaveBeenCalledWith({ channel: SMS, keepSlideBoxOpen: true });
|
|
62
|
+
expect(wrapper.state('isCreateContinuedAsEdit')).toBe(false);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe('CreativesContainer: full-mode email create continues in place', () => {
|
|
67
|
+
const getCreativesData = jest.fn();
|
|
68
|
+
const render = (props = {}) => shallowWithIntl(
|
|
69
|
+
<Creatives
|
|
70
|
+
isFullMode
|
|
71
|
+
creativesMode="create"
|
|
72
|
+
channel="EMAIL"
|
|
73
|
+
templateData={{ mode: 'create' }}
|
|
74
|
+
Templates={{}}
|
|
75
|
+
getCreativesData={getCreativesData}
|
|
76
|
+
handleCloseCreatives={jest.fn()}
|
|
77
|
+
switchToEditAfterCreate
|
|
78
|
+
{...props}
|
|
79
|
+
/>,
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
beforeEach(() => jest.clearAllMocks());
|
|
83
|
+
|
|
84
|
+
it('stays open after a create save and only lets the host refresh its list', () => {
|
|
85
|
+
const instance = render().instance();
|
|
86
|
+
instance.setState({ isGetFormData: true });
|
|
87
|
+
instance.getFormData({ _id: 'email-1', validity: true, keepSlideBoxOpen: true });
|
|
88
|
+
|
|
89
|
+
expect(instance.state.slidBoxContent).toBe('createTemplate');
|
|
90
|
+
expect(instance.state.isGetFormData).toBe(false);
|
|
91
|
+
expect(getCreativesData).toHaveBeenCalledWith({ channel: 'EMAIL', keepSlideBoxOpen: true });
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('closes as before after a create save when the user cannot edit', () => {
|
|
95
|
+
const instance = render({ switchToEditAfterCreate: false }).instance();
|
|
96
|
+
instance.getFormData({ _id: 'email-1', validity: true, keepSlideBoxOpen: true });
|
|
97
|
+
|
|
98
|
+
expect(getCreativesData).not.toHaveBeenCalledWith({ channel: 'EMAIL', keepSlideBoxOpen: true });
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
describe('CreativesContainer: header after a create continued in place (web push)', () => {
|
|
103
|
+
it('shows the edit title in the header while the content stays mounted in create mode', () => {
|
|
104
|
+
const wrapper = shallowWithIntl(
|
|
105
|
+
<Creatives
|
|
106
|
+
isFullMode
|
|
107
|
+
creativesMode="create"
|
|
108
|
+
channel="WEBPUSH"
|
|
109
|
+
templateData={{ mode: 'create' }}
|
|
110
|
+
Templates={{}}
|
|
111
|
+
getCreativesData={jest.fn()}
|
|
112
|
+
handleCloseCreatives={jest.fn()}
|
|
113
|
+
switchToEditAfterCreate
|
|
114
|
+
/>,
|
|
115
|
+
);
|
|
116
|
+
const headerContent = () => wrapper.find('CapSlideBox').prop('header').props.slidBoxContent;
|
|
117
|
+
expect(headerContent()).toBe('createTemplate');
|
|
118
|
+
|
|
119
|
+
wrapper.instance().handleCreateContinuedAsEdit();
|
|
120
|
+
wrapper.update();
|
|
121
|
+
|
|
122
|
+
expect(headerContent()).toBe('editTemplate');
|
|
123
|
+
expect(wrapper.state('slidBoxContent')).toBe('createTemplate');
|
|
124
|
+
expect(wrapper.find('CapSlideBox').prop('content').props.slidBoxContent).toBe('createTemplate');
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
describe('CreativesContainer: a stay-open create marked continuedAsEdit (Viber)', () => {
|
|
129
|
+
it('stays open, refreshes the host list and switches the header to the edit title', () => {
|
|
130
|
+
const getCreativesData = jest.fn();
|
|
131
|
+
const wrapper = shallowWithIntl(
|
|
132
|
+
<Creatives
|
|
133
|
+
isFullMode
|
|
134
|
+
creativesMode="create"
|
|
135
|
+
channel="VIBER"
|
|
136
|
+
templateData={{ mode: 'create' }}
|
|
137
|
+
Templates={{}}
|
|
138
|
+
getCreativesData={getCreativesData}
|
|
139
|
+
handleCloseCreatives={jest.fn()}
|
|
140
|
+
switchToEditAfterCreate
|
|
141
|
+
/>,
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
wrapper.instance().getFormData({ _id: 'vb-1', validity: true, keepSlideBoxOpen: true, continuedAsEdit: true });
|
|
145
|
+
wrapper.update();
|
|
146
|
+
|
|
147
|
+
expect(getCreativesData).toHaveBeenCalledWith({ channel: 'VIBER', keepSlideBoxOpen: true });
|
|
148
|
+
expect(wrapper.state('isCreateContinuedAsEdit')).toBe(true);
|
|
149
|
+
expect(wrapper.find('CapSlideBox').prop('header').props.slidBoxContent).toBe('editTemplate');
|
|
150
|
+
expect(wrapper.state('slidBoxContent')).toBe('createTemplate');
|
|
151
|
+
});
|
|
152
|
+
});
|