@capillarytech/creatives-library 9.0.29 → 9.0.31
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/constants/unified.js +29 -0
- package/global-styles.js +1 -1
- package/package.json +1 -1
- package/services/tests/api.test.js +35 -20
- package/utils/commonUtils.js +22 -1
- package/utils/rcsPayloadUtils.js +102 -0
- package/utils/templateVarUtils.js +198 -0
- package/utils/tests/rcsPayloadUtils.test.js +295 -0
- package/utils/tests/templateVarUtils.test.js +204 -0
- package/v2Components/CapActionButton/constants.js +21 -1
- package/v2Components/CapActionButton/index.js +261 -144
- package/v2Components/CapActionButton/index.scss +245 -14
- package/v2Components/CapActionButton/messages.js +32 -3
- package/v2Components/CapActionButton/tests/index.test.js +74 -19
- package/v2Components/CapImageUpload/index.js +2 -2
- package/v2Components/CapTagList/index.js +9 -0
- package/v2Components/CommonTestAndPreview/CustomValuesEditor.js +70 -48
- package/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +8 -2
- package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +214 -21
- package/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +16 -0
- package/v2Components/CommonTestAndPreview/DeliverySettings/index.js +83 -9
- package/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +30 -0
- package/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +58 -11
- package/v2Components/CommonTestAndPreview/SendTestMessage.js +10 -5
- package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js +186 -22
- package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +381 -80
- package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +155 -8
- package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +11 -0
- package/v2Components/CommonTestAndPreview/constants.js +35 -2
- package/v2Components/CommonTestAndPreview/index.js +774 -231
- package/v2Components/CommonTestAndPreview/messages.js +45 -3
- package/v2Components/CommonTestAndPreview/previewApiUtils.js +59 -0
- package/v2Components/CommonTestAndPreview/sagas.js +25 -6
- package/v2Components/CommonTestAndPreview/tests/CommonTestAndPreview.addTestCustomer.test.js +1 -0
- package/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +412 -257
- package/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +337 -63
- package/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +118 -5
- package/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +341 -0
- package/v2Components/CommonTestAndPreview/tests/PreviewSection.test.js +8 -1
- package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +108 -15
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/RcsPreviewContent.test.js +281 -283
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +199 -1
- package/v2Components/CommonTestAndPreview/tests/index.test.js +133 -4
- package/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +67 -0
- package/v2Components/CommonTestAndPreview/tests/sagas.test.js +31 -24
- package/v2Components/CommonTestAndPreview/tests/utils.test.js +151 -0
- package/v2Components/CommonTestAndPreview/utils.js +84 -0
- package/v2Components/SmsFallback/SmsFallbackLocalSelector.js +91 -0
- package/v2Components/SmsFallback/constants.js +94 -0
- package/v2Components/SmsFallback/index.js +958 -0
- package/v2Components/SmsFallback/index.scss +266 -0
- package/v2Components/SmsFallback/messages.js +78 -0
- package/v2Components/SmsFallback/smsFallbackUtils.js +120 -0
- package/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +50 -0
- package/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +147 -0
- package/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +304 -0
- package/v2Components/SmsFallback/tests/smsFallbackUi.test.js +208 -0
- package/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +309 -0
- package/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +471 -0
- package/v2Components/SmsFallback/useLocalTemplateList.js +92 -0
- package/v2Components/TemplatePreview/_templatePreview.scss +45 -25
- package/v2Components/TemplatePreview/constants.js +2 -0
- package/v2Components/TemplatePreview/index.js +147 -32
- package/v2Components/TemplatePreview/tests/index.test.js +142 -0
- package/v2Components/TestAndPreviewSlidebox/CustomValuesEditor.js +6 -6
- package/v2Components/TestAndPreviewSlidebox/index.js +13 -1
- package/v2Components/TestAndPreviewSlidebox/sagas.js +11 -4
- package/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +3 -1
- package/v2Components/VarSegmentMessageEditor/constants.js +2 -0
- package/v2Components/VarSegmentMessageEditor/index.js +125 -0
- package/v2Components/VarSegmentMessageEditor/index.scss +46 -0
- package/v2Containers/CommunicationFlow/Tests/CommunicationFlow.test.js +4 -1
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/DeliverySettingsSection.test.js +4 -0
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/SenderDetails.test.js +20 -20
- package/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +27 -0
- package/v2Containers/CreativesContainer/SlideBoxContent.js +37 -4
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +14 -5
- package/v2Containers/CreativesContainer/SlideBoxHeader.js +36 -5
- package/v2Containers/CreativesContainer/constants.js +11 -0
- package/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +77 -0
- package/v2Containers/CreativesContainer/index.js +322 -106
- package/v2Containers/CreativesContainer/index.scss +102 -1
- package/v2Containers/CreativesContainer/tests/CreativesSlideBoxWrapper.test.js +58 -0
- package/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +90 -0
- package/v2Containers/CreativesContainer/tests/SlideBoxContent.smsDltPreview.test.js +73 -0
- package/v2Containers/CreativesContainer/tests/SlideBoxContent.test.js +37 -0
- package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +103 -34
- package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +193 -15
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +88 -0
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +549 -57
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +20 -15
- package/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +258 -0
- package/v2Containers/CreativesContainer/tests/index.test.js +71 -9
- package/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +125 -0
- package/v2Containers/MobilePush/Create/test/saga.test.js +2 -2
- package/v2Containers/Rcs/carouselUtils.js +224 -0
- package/v2Containers/Rcs/components/CarouselCard.js +317 -0
- package/v2Containers/Rcs/components/CarouselCardButtons.js +113 -0
- package/v2Containers/Rcs/components/CarouselCardMedia.js +136 -0
- package/v2Containers/Rcs/components/CarouselCharacterCount.js +31 -0
- package/v2Containers/Rcs/components/CarouselDimensionSelection.js +80 -0
- package/v2Containers/Rcs/constants.js +132 -16
- package/v2Containers/Rcs/index.js +1822 -946
- package/v2Containers/Rcs/index.scss +443 -8
- package/v2Containers/Rcs/messages.js +45 -22
- package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +494 -0
- package/v2Containers/Rcs/tests/CarouselCard.test.js +464 -0
- package/v2Containers/Rcs/tests/CarouselCardButtons.test.js +211 -0
- package/v2Containers/Rcs/tests/CarouselCardMedia.test.js +160 -0
- package/v2Containers/Rcs/tests/CarouselCharacterCount.test.js +50 -0
- package/v2Containers/Rcs/tests/CarouselDimensionSelection.test.js +119 -0
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +74440 -39387
- package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +10 -74
- package/v2Containers/Rcs/tests/carouselUtils.test.js +916 -0
- package/v2Containers/Rcs/tests/index.test.js +275 -40
- package/v2Containers/Rcs/tests/mockData.js +38 -0
- package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +912 -0
- package/v2Containers/Rcs/tests/utils.test.js +682 -30
- package/v2Containers/Rcs/utils.js +514 -12
- package/v2Containers/Sms/Create/index.js +115 -48
- package/v2Containers/Sms/smsFormDataHelpers.js +67 -0
- package/v2Containers/Sms/tests/smsFormDataHelpers.test.js +253 -0
- package/v2Containers/SmsTrai/Create/index.js +9 -4
- package/v2Containers/SmsTrai/Edit/constants.js +2 -0
- package/v2Containers/SmsTrai/Edit/index.js +678 -169
- package/v2Containers/SmsTrai/Edit/index.scss +126 -0
- package/v2Containers/SmsTrai/Edit/messages.js +14 -4
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +5615 -3014
- package/v2Containers/SmsWrapper/index.js +37 -8
- package/v2Containers/TagList/index.js +5 -0
- package/v2Containers/Templates/TemplatesActionBar.js +101 -0
- package/v2Containers/Templates/_templates.scss +196 -12
- package/v2Containers/Templates/actions.js +11 -0
- package/v2Containers/Templates/constants.js +2 -0
- package/v2Containers/Templates/index.js +131 -59
- package/v2Containers/Templates/sagas.js +57 -13
- package/v2Containers/Templates/tests/TemplatesActionBar.test.js +129 -0
- package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1060 -1015
- package/v2Containers/Templates/tests/sagas.test.js +199 -16
- package/v2Containers/Templates/tests/smsTemplatesListApi.test.js +180 -0
- package/v2Containers/Templates/utils/smsTemplatesListApi.js +79 -0
- package/v2Containers/TemplatesV2/TemplatesV2.style.js +72 -1
- package/v2Containers/TemplatesV2/index.js +88 -25
- package/v2Containers/TemplatesV2/tests/TemplatesV2.localTemplates.test.js +131 -0
- package/v2Containers/WeChat/MapTemplates/test/saga.test.js +9 -9
- package/v2Containers/Whatsapp/index.js +3 -20
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +578 -34
|
@@ -10,8 +10,8 @@ import { connect } from 'react-redux';
|
|
|
10
10
|
import { injectIntl, intlShape, FormattedMessage } from 'react-intl';
|
|
11
11
|
import { createStructuredSelector } from 'reselect';
|
|
12
12
|
import { bindActionCreators, compose } from 'redux';
|
|
13
|
-
import { CapTab, CapCustomCard, CapButton, CapHeader,
|
|
14
|
-
import { find, get } from 'lodash';
|
|
13
|
+
import { CapTab, CapCustomCard, CapButton, CapHeader, CapIcon, CapSpin, CapTooltip } from '@capillarytech/cap-ui-library';
|
|
14
|
+
import { find, get, pick } from 'lodash';
|
|
15
15
|
import Helmet from 'react-helmet';
|
|
16
16
|
|
|
17
17
|
import { UserIsAuthenticated } from '../../utils/authWrapper';
|
|
@@ -41,13 +41,14 @@ import { makeSelectAuthenticated, selectCurrentOrgDetails } from "../../v2Contai
|
|
|
41
41
|
import {
|
|
42
42
|
CALL_TASK,
|
|
43
43
|
COMMON_CHANNELS,
|
|
44
|
+
LOCAL_TEMPLATE_CONFIG_KEYS_FOR_PICK,
|
|
44
45
|
LOYALTY_SUPPORTED_ACTION,
|
|
45
46
|
MOBILE_PUSH,
|
|
46
47
|
NORMALIZED_CHANNEL_ALIASES,
|
|
47
48
|
SMS,
|
|
48
49
|
} from "../CreativesContainer/constants";
|
|
49
50
|
|
|
50
|
-
const {CapCustomCardList} = CapCustomCard;
|
|
51
|
+
const { CapCustomCardList } = CapCustomCard;
|
|
51
52
|
|
|
52
53
|
const StyledCapTab = withStyles(CapTab, CapTabStyle);
|
|
53
54
|
export class TemplatesV2 extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
@@ -124,9 +125,9 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
124
125
|
return !normalizedChannelsToHideSet.has(paneKey);
|
|
125
126
|
});
|
|
126
127
|
|
|
127
|
-
if (isFullMode) {
|
|
128
|
-
filteredPanes.push({ content: <div></div>, tab: intl.formatMessage(messages.gallery), key:
|
|
129
|
-
} else {
|
|
128
|
+
if (isFullMode && !normalizedChannelsToHideSet.has(normalizeChannel(ASSETS))) {
|
|
129
|
+
filteredPanes.push({ content: <div></div>, tab: intl.formatMessage(messages.gallery), key: ASSETS });
|
|
130
|
+
} else if (!isFullMode) {
|
|
130
131
|
// Add special-mode panes only when not hidden (use normalized checks)
|
|
131
132
|
if (!normalizedChannelsToHideSet.has(CALL_TASK.toLowerCase())) {
|
|
132
133
|
filteredPanes.push({ content: <div></div>, tab: intl.formatMessage(messages.callTask), key: CALL_TASK.toLowerCase() });
|
|
@@ -227,7 +228,8 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
227
228
|
this.setState({selectedChannel: nextProps.channel, panes });
|
|
228
229
|
}
|
|
229
230
|
}
|
|
230
|
-
|
|
231
|
+
|
|
232
|
+
getTemplateDataForGrid = ({ templates, handlers, filterContent, channel, isLoading, loadingTip }) => {
|
|
231
233
|
const currentChannel = channel.toUpperCase();
|
|
232
234
|
const cardDataList = templates.map((template) => {
|
|
233
235
|
const templateData =
|
|
@@ -253,7 +255,8 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
253
255
|
</CapSpin>
|
|
254
256
|
|
|
255
257
|
</div>);
|
|
256
|
-
}
|
|
258
|
+
};
|
|
259
|
+
|
|
257
260
|
getGalleryComponent = (location) => <Gallery location={location} isFullMode={this.props.isFullMode}/>
|
|
258
261
|
getCallTaskComponent = () => (
|
|
259
262
|
<CallTask
|
|
@@ -317,6 +320,29 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
317
320
|
if (messageStrategy !== "X_ENGAGE" && channel === 'facebook' && !isFullMode) {
|
|
318
321
|
return this.getFacebookComponent();
|
|
319
322
|
}
|
|
323
|
+
const localConfig = this.props.localTemplatesConfig || pick(this.props, LOCAL_TEMPLATE_CONFIG_KEYS_FOR_PICK);
|
|
324
|
+
const useLocalTemplates = localConfig.useLocalTemplates;
|
|
325
|
+
if (useLocalTemplates && channel === (this.props.channel || 'sms')) {
|
|
326
|
+
// Reuse full Templates component (same UI as Redux flow) with local data only
|
|
327
|
+
const location = { pathname: `/${channel}`, search: '', query: !this.props.isFullMode ? { type: 'embedded', module: 'library' } : {} };
|
|
328
|
+
return (
|
|
329
|
+
<Templates
|
|
330
|
+
key={`${channel}-local`}
|
|
331
|
+
location={location}
|
|
332
|
+
route={{ name: channel }}
|
|
333
|
+
router={this.props.router}
|
|
334
|
+
isFullMode={this.props.isFullMode}
|
|
335
|
+
createNew={this.props.createNew}
|
|
336
|
+
onSelectTemplate={this.props.onSelectTemplate}
|
|
337
|
+
handlePeviewTemplate={this.props.handlePeviewTemplate}
|
|
338
|
+
messageStrategy={this.props.messageStrategy}
|
|
339
|
+
smsRegister={this.props.smsRegister}
|
|
340
|
+
hideTestAndPreviewBtn={this.props.hideTestAndPreviewBtn}
|
|
341
|
+
localTemplatesConfig={localConfig}
|
|
342
|
+
/>
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
|
|
320
346
|
const location = {pathname: `/${channel}`, search: '', query};
|
|
321
347
|
switch (channel) {
|
|
322
348
|
case 'call_task':
|
|
@@ -366,31 +392,57 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
366
392
|
}
|
|
367
393
|
render() {
|
|
368
394
|
const { isFullMode, className, cap = {}, Global = {}} = this.props;
|
|
395
|
+
const useLocalTemplates = get(this.props, 'localTemplatesConfig.useLocalTemplates', false);
|
|
369
396
|
const { accessiblePermissions = []} = cap.user || Global.user || {};
|
|
370
397
|
let isCreativeAccessible = true;
|
|
371
398
|
if (!accessiblePermissions.includes(CREATIVES_UI_VIEW)) {
|
|
372
399
|
isCreativeAccessible = false;
|
|
373
400
|
}
|
|
401
|
+
// Recompute active pane content every render so local-list mode updates
|
|
402
|
+
// (templates/loading/search UI) are not stuck with the initial cached pane.
|
|
403
|
+
const panes = this.setChannelContent(this.state.selectedChannel, this.state.panes);
|
|
404
|
+
const hideChannelTabsForLocalSms = useLocalTemplates && panes.length === 1;
|
|
405
|
+
const activeLocalPane = hideChannelTabsForLocalSms
|
|
406
|
+
? (panes.find(
|
|
407
|
+
(pane) => String(pane.key).toLowerCase() === String(this.state.selectedChannel).toLowerCase(),
|
|
408
|
+
) || panes[0])
|
|
409
|
+
: null;
|
|
374
410
|
return (
|
|
375
411
|
!isCreativeAccessible ? <AccessForbidden /> : (
|
|
376
|
-
<
|
|
377
|
-
{isFullMode
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
panes={this.state.panes}
|
|
387
|
-
onChange={this.channelChange}
|
|
388
|
-
activeKey={this.state.selectedChannel}
|
|
389
|
-
defaultActiveKey={this.state.selectedChannel}
|
|
390
|
-
isFullMode={isFullMode}
|
|
412
|
+
<section
|
|
413
|
+
className={`${className} creatives-templates-container ${isFullMode ? 'fullmode' : 'library-mode'}${useLocalTemplates ? ' creatives-templates-container--local-sms' : ''}`}
|
|
414
|
+
data-testid="cap-wrapper"
|
|
415
|
+
>
|
|
416
|
+
{isFullMode && !useLocalTemplates && (
|
|
417
|
+
<Helmet
|
|
418
|
+
title={this.props.intl.formatMessage(messages.creatives)}
|
|
419
|
+
meta={[
|
|
420
|
+
{ name: 'description', content: this.props.intl.formatMessage(messages.creativesDesc) },
|
|
421
|
+
]}
|
|
391
422
|
/>
|
|
392
|
-
|
|
393
|
-
|
|
423
|
+
)}
|
|
424
|
+
<section className="component-wrapper">
|
|
425
|
+
{isFullMode && (
|
|
426
|
+
<CapHeader
|
|
427
|
+
title={<FormattedMessage {...messages.creatives} />}
|
|
428
|
+
{...(!useLocalTemplates && {
|
|
429
|
+
description: <FormattedMessage {...messages.creativesDesc} />,
|
|
430
|
+
})}
|
|
431
|
+
/>
|
|
432
|
+
)}
|
|
433
|
+
{hideChannelTabsForLocalSms ? (
|
|
434
|
+
<section className="templates-v2-local-sms-pane">{activeLocalPane?.content}</section>
|
|
435
|
+
) : (
|
|
436
|
+
<StyledCapTab
|
|
437
|
+
panes={panes}
|
|
438
|
+
onChange={this.channelChange}
|
|
439
|
+
activeKey={this.state.selectedChannel}
|
|
440
|
+
defaultActiveKey={this.state.selectedChannel}
|
|
441
|
+
isFullMode={isFullMode}
|
|
442
|
+
/>
|
|
443
|
+
)}
|
|
444
|
+
</section>
|
|
445
|
+
</section>
|
|
394
446
|
)
|
|
395
447
|
);
|
|
396
448
|
}
|
|
@@ -420,6 +472,17 @@ TemplatesV2.propTypes = {
|
|
|
420
472
|
currentOrgDetails: PropTypes.object,
|
|
421
473
|
restrictPersonalization: PropTypes.bool,
|
|
422
474
|
isAnonymousType: PropTypes.bool,
|
|
475
|
+
// Optional: reuse grid UI with local template list (e.g. SMS fallback). Pass object or same keys as individual props.
|
|
476
|
+
localTemplatesConfig: PropTypes.shape({
|
|
477
|
+
useLocalTemplates: PropTypes.bool,
|
|
478
|
+
localTemplates: PropTypes.arrayOf(PropTypes.object),
|
|
479
|
+
localTemplatesLoading: PropTypes.bool,
|
|
480
|
+
localTemplatesLoadingTip: PropTypes.string,
|
|
481
|
+
localTemplatesFilterContent: PropTypes.node,
|
|
482
|
+
localTemplatesFooterContent: PropTypes.node,
|
|
483
|
+
localTemplatesOnPageChange: PropTypes.func,
|
|
484
|
+
localTemplatesUseSkeleton: PropTypes.bool,
|
|
485
|
+
}),
|
|
423
486
|
};
|
|
424
487
|
|
|
425
488
|
TemplatesV2.defaultProps = {
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedded SMS template list: localTemplatesConfig + SMS-only channel visibility (RCS SMS fallback).
|
|
3
|
+
*/
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import { injectIntl } from 'react-intl';
|
|
6
|
+
import '@testing-library/jest-dom';
|
|
7
|
+
import cloneDeep from 'lodash/cloneDeep';
|
|
8
|
+
import { Provider } from 'react-redux';
|
|
9
|
+
import { configureStore } from '@capillarytech/vulcan-react-sdk/utils';
|
|
10
|
+
import history from '../../../utils/history';
|
|
11
|
+
import { initialReducer } from '../../../initialReducer';
|
|
12
|
+
import { render, screen } from '../../../utils/test-utils';
|
|
13
|
+
import { TemplatesV2 } from '../index';
|
|
14
|
+
import { Templates, authData, currentOrgDetails as currentOrgDetailsMock } from './mockData';
|
|
15
|
+
import { CHANNELS_TO_HIDE_FOR_SMS_ONLY } from '../../../v2Components/SmsFallback/constants';
|
|
16
|
+
|
|
17
|
+
const mockTemplates = jest.fn(() => <div data-testid="templates-mock">Templates</div>);
|
|
18
|
+
jest.mock('v2Containers/Templates', () => ({
|
|
19
|
+
__esModule: true,
|
|
20
|
+
default: (props) => mockTemplates(props),
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
jest.mock('../../../utils/authWrapper', () => ({
|
|
24
|
+
UserIsAuthenticated: jest.fn((config) => config),
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
const ComponentToRender = injectIntl(TemplatesV2);
|
|
28
|
+
const renderComponent = (p) => {
|
|
29
|
+
const store = configureStore({}, initialReducer, history);
|
|
30
|
+
return render(
|
|
31
|
+
<Provider store={store}>
|
|
32
|
+
<ComponentToRender {...p} />
|
|
33
|
+
</Provider>,
|
|
34
|
+
);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
describe('TemplatesV2 local SMS templates (embedded)', () => {
|
|
38
|
+
const templateActions = {
|
|
39
|
+
templateActions: jest.fn(),
|
|
40
|
+
deleteTemplate: jest.fn(),
|
|
41
|
+
getAccountsSettings: jest.fn(),
|
|
42
|
+
getAllTemplates: jest.fn(),
|
|
43
|
+
getCdnTransformationConfig: jest.fn(),
|
|
44
|
+
getDefaultBeeTemplates: jest.fn(),
|
|
45
|
+
getSenderDetails: jest.fn(),
|
|
46
|
+
getTemplateDetails: jest.fn(),
|
|
47
|
+
getUserList: jest.fn(),
|
|
48
|
+
getWeCrmAccounts: jest.fn(),
|
|
49
|
+
handleHtmlUpload: jest.fn(),
|
|
50
|
+
handleZipUpload: jest.fn(),
|
|
51
|
+
resetAccount: jest.fn(),
|
|
52
|
+
resetTemplate: jest.fn(),
|
|
53
|
+
resetTemplateData: jest.fn(),
|
|
54
|
+
resetTemplateStoreData: jest.fn(),
|
|
55
|
+
resetUploadData: jest.fn(),
|
|
56
|
+
setBEETemplate: jest.fn(),
|
|
57
|
+
setChannelAccount: jest.fn(),
|
|
58
|
+
setEdmTemplate: jest.fn(),
|
|
59
|
+
setFacebookAccount: jest.fn(),
|
|
60
|
+
setViberAccount: jest.fn(),
|
|
61
|
+
setWeChatAccount: jest.fn(),
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const baseProps = {
|
|
65
|
+
cap: {
|
|
66
|
+
user: { accessiblePermissions: ['CREATIVES_UI_VIEW'] },
|
|
67
|
+
},
|
|
68
|
+
actions: { defaultAction: jest.fn(), getTemplates: jest.fn() },
|
|
69
|
+
Templates,
|
|
70
|
+
TemplatesList: Templates?.templates,
|
|
71
|
+
authData,
|
|
72
|
+
templateActions,
|
|
73
|
+
isFullMode: false,
|
|
74
|
+
className: 'embed-test',
|
|
75
|
+
channel: 'sms',
|
|
76
|
+
channelsToHide: CHANNELS_TO_HIDE_FOR_SMS_ONLY,
|
|
77
|
+
channelsToDisable: [],
|
|
78
|
+
onChannelChange: jest.fn(),
|
|
79
|
+
enableNewChannels: [],
|
|
80
|
+
/** Without JP_LOCALE_HIDE_FEATURE so SMS panes are not stripped to Email/Line/Gallery only */
|
|
81
|
+
currentOrgDetails: {
|
|
82
|
+
...currentOrgDetailsMock,
|
|
83
|
+
accessibleFeatures: (currentOrgDetailsMock.accessibleFeatures || []).filter(
|
|
84
|
+
(f) => f !== 'JP_LOCALE_HIDE_FEATURE',
|
|
85
|
+
),
|
|
86
|
+
},
|
|
87
|
+
location: {
|
|
88
|
+
pathname: 'v2',
|
|
89
|
+
basename: '/creatives/ui/',
|
|
90
|
+
query: {},
|
|
91
|
+
},
|
|
92
|
+
router: { push: jest.fn() },
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
beforeEach(() => {
|
|
96
|
+
mockTemplates.mockClear();
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('adds local-sms container class and single-pane layout when only SMS is visible', () => {
|
|
100
|
+
const p = cloneDeep(baseProps);
|
|
101
|
+
p.localTemplatesConfig = {
|
|
102
|
+
useLocalTemplates: true,
|
|
103
|
+
localTemplates: [],
|
|
104
|
+
localTemplatesLoading: false,
|
|
105
|
+
};
|
|
106
|
+
renderComponent(p);
|
|
107
|
+
|
|
108
|
+
const wrapper = screen.getByTestId('cap-wrapper');
|
|
109
|
+
expect(wrapper).toHaveClass('creatives-templates-container--local-sms');
|
|
110
|
+
expect(document.querySelector('.templates-v2-local-sms-pane')).toBeTruthy();
|
|
111
|
+
expect(mockTemplates).toHaveBeenCalled();
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('passes localTemplatesConfig into Templates for the SMS pane', () => {
|
|
115
|
+
const localConfig = {
|
|
116
|
+
useLocalTemplates: true,
|
|
117
|
+
localTemplates: [{ _id: '1', name: 'A' }],
|
|
118
|
+
localTemplatesLoading: false,
|
|
119
|
+
};
|
|
120
|
+
const p = cloneDeep(baseProps);
|
|
121
|
+
p.localTemplatesConfig = localConfig;
|
|
122
|
+
renderComponent(p);
|
|
123
|
+
|
|
124
|
+
expect(mockTemplates).toHaveBeenCalled();
|
|
125
|
+
const passed = mockTemplates.mock.calls.find(
|
|
126
|
+
(call) => call[0] && call[0].localTemplatesConfig && call[0].localTemplatesConfig.useLocalTemplates,
|
|
127
|
+
);
|
|
128
|
+
expect(passed).toBeTruthy();
|
|
129
|
+
expect(passed[0].localTemplatesConfig).toMatchObject(localConfig);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
@@ -11,7 +11,7 @@ describe('WeChat Template Management Sagas', () => {
|
|
|
11
11
|
describe('getDefaultWeChatTemplates Saga', () => {
|
|
12
12
|
const params = { channel: 'WeChat', queryParams: { type: 'default' } };
|
|
13
13
|
|
|
14
|
-
it
|
|
14
|
+
it('handles fetching default WeChat templates successfully', () => {
|
|
15
15
|
const fakeResponse = {
|
|
16
16
|
response: {
|
|
17
17
|
unMapped: [{ id: 1, name: 'Template One' }],
|
|
@@ -31,7 +31,7 @@ describe('WeChat Template Management Sagas', () => {
|
|
|
31
31
|
.run();
|
|
32
32
|
});
|
|
33
33
|
|
|
34
|
-
it
|
|
34
|
+
it('handles failure in fetching default WeChat templates', () => {
|
|
35
35
|
const error = new Error('Fetch failed');
|
|
36
36
|
|
|
37
37
|
return expectSaga(sagas.getDefaultWeChatTemplates, params)
|
|
@@ -48,7 +48,7 @@ describe('WeChat Template Management Sagas', () => {
|
|
|
48
48
|
|
|
49
49
|
describe('createTemplate Saga', () => {
|
|
50
50
|
const template = { name: 'New WeChat Template' };
|
|
51
|
-
test
|
|
51
|
+
test('handles creating a WeChat template successfully', () => {
|
|
52
52
|
const fakeResponse = {
|
|
53
53
|
response: template,
|
|
54
54
|
status: { code: 200 }
|
|
@@ -64,7 +64,7 @@ describe('WeChat Template Management Sagas', () => {
|
|
|
64
64
|
})
|
|
65
65
|
.run();
|
|
66
66
|
});
|
|
67
|
-
test
|
|
67
|
+
test('handles failure when creating a WeChat template', () => {
|
|
68
68
|
const error = new Error('Creation failed');
|
|
69
69
|
return expectSaga(sagas.createTemplate, template)
|
|
70
70
|
.provide([
|
|
@@ -79,7 +79,7 @@ describe('WeChat Template Management Sagas', () => {
|
|
|
79
79
|
});
|
|
80
80
|
|
|
81
81
|
describe('fetchWeCrmAccounts Saga', () => {
|
|
82
|
-
it
|
|
82
|
+
it('handles fetching WeCrm accounts successfully', () => {
|
|
83
83
|
const fakeResponse = {
|
|
84
84
|
response: [{ id: 1, name: 'Account One' }]
|
|
85
85
|
};
|
|
@@ -95,7 +95,7 @@ describe('WeChat Template Management Sagas', () => {
|
|
|
95
95
|
.run();
|
|
96
96
|
});
|
|
97
97
|
|
|
98
|
-
it
|
|
98
|
+
it('handles failure in fetching WeCrm accounts', () => {
|
|
99
99
|
const error = new Error('Fetch failed');
|
|
100
100
|
|
|
101
101
|
return expectSaga(sagas.fetchWeCrmAccounts)
|
|
@@ -113,7 +113,7 @@ describe('WeChat Template Management Sagas', () => {
|
|
|
113
113
|
describe('getTemplateDetails Saga', () => {
|
|
114
114
|
const id = '123';
|
|
115
115
|
|
|
116
|
-
it
|
|
116
|
+
it('handles fetching template details successfully', () => {
|
|
117
117
|
const fakeResponse = {
|
|
118
118
|
response: { id: 123, name: 'Detailed Template' }
|
|
119
119
|
};
|
|
@@ -129,7 +129,7 @@ describe('WeChat Template Management Sagas', () => {
|
|
|
129
129
|
.run();
|
|
130
130
|
});
|
|
131
131
|
|
|
132
|
-
it
|
|
132
|
+
it('handles failure in fetching template details', () => {
|
|
133
133
|
const error = new Error('Fetch failed');
|
|
134
134
|
|
|
135
135
|
return expectSaga(sagas.getTemplateDetails, id)
|
|
@@ -148,7 +148,7 @@ describe('WeChat Template Management Sagas', () => {
|
|
|
148
148
|
|
|
149
149
|
// Test combined saga
|
|
150
150
|
describe('Combined v2WechatMapTemplatesSagas', () => {
|
|
151
|
-
it
|
|
151
|
+
it('should initialize all WeChat-related watcher sagas without error', () => {
|
|
152
152
|
return expectSaga(v2WechatMapTemplatesSagas)
|
|
153
153
|
.run();
|
|
154
154
|
});
|
|
@@ -119,6 +119,7 @@ import { ANDROID } from '../../v2Components/CommonTestAndPreview/constants';
|
|
|
119
119
|
import CapImageUpload from '../../v2Components/CapImageUpload';
|
|
120
120
|
import TagList from '../TagList';
|
|
121
121
|
import { validateTags } from '../../utils/tagValidations';
|
|
122
|
+
import { splitContentByOrderedVarTokens } from '../../utils/templateVarUtils';
|
|
122
123
|
import { capitalizeString } from '../../utils/Formatter';
|
|
123
124
|
import CapWhatsappCTA from '../../v2Components/CapWhatsappCTA';
|
|
124
125
|
import {
|
|
@@ -496,28 +497,10 @@ export const Whatsapp = (props) => {
|
|
|
496
497
|
);
|
|
497
498
|
};
|
|
498
499
|
|
|
499
|
-
const converStringToVarArr = (validVarArr, content) => {
|
|
500
|
-
const templateVarArray = [];
|
|
501
|
-
while (content?.length !== 0) {
|
|
502
|
-
//converting content string to an array split at var
|
|
503
|
-
const index = content.indexOf(validVarArr?.[0]);
|
|
504
|
-
if (index !== -1) {
|
|
505
|
-
templateVarArray.push(content.substring(0, index)); //push string before var
|
|
506
|
-
templateVarArray.push(validVarArr?.[0]); //push var
|
|
507
|
-
content = content.substring(index + validVarArr?.[0]?.length, content?.length); //remaining str
|
|
508
|
-
validVarArr?.shift(); //remove considered var
|
|
509
|
-
} else {
|
|
510
|
-
templateVarArray.push(content); //remaining str
|
|
511
|
-
break;
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
return templateVarArray;
|
|
515
|
-
}
|
|
516
|
-
|
|
517
500
|
const computeTextMessage = (msg, varMap, regex) => {
|
|
518
501
|
const validVarArr = msg?.match(regex) || [];
|
|
519
502
|
//conerting msg string to variable arr
|
|
520
|
-
const templateHeaderArray =
|
|
503
|
+
const templateHeaderArray = splitContentByOrderedVarTokens(validVarArr, msg);
|
|
521
504
|
if (templateHeaderArray?.length !== 0) {
|
|
522
505
|
let clonedVarMap = {};
|
|
523
506
|
if (!isEmpty(varMap)) {
|
|
@@ -571,7 +554,7 @@ export const Whatsapp = (props) => {
|
|
|
571
554
|
setUnsubscribeRequired(true);
|
|
572
555
|
}
|
|
573
556
|
//converting msg string to variable arr
|
|
574
|
-
const templateMessageArray =
|
|
557
|
+
const templateMessageArray = splitContentByOrderedVarTokens(validVarArr, msg);
|
|
575
558
|
updateTempMsgArray(templateMessageArray.filter((i) => i === 0 || i));
|
|
576
559
|
};
|
|
577
560
|
|