@capillarytech/creatives-library 8.0.242-alpha.0 → 8.0.242-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/Android.png +0 -0
- package/assets/iOS.png +0 -0
- package/constants/unified.js +2 -1
- package/initialReducer.js +2 -0
- package/package.json +1 -1
- package/sagas/__tests__/assetPolling.test.js +74 -3
- package/sagas/assetPolling.js +8 -1
- package/services/api.js +10 -5
- package/services/tests/api.test.js +18 -0
- package/translations/en.json +0 -1
- package/utils/common.js +5 -0
- package/utils/commonUtils.js +14 -1
- package/utils/tests/commonUtil.test.js +224 -0
- package/utils/transformTemplateConfig.js +0 -10
- package/utils/transformerUtils.js +0 -42
- package/v2Components/CapDeviceContent/index.js +61 -56
- package/v2Components/CapImageUpload/constants.js +0 -2
- package/v2Components/CapImageUpload/index.js +14 -54
- package/v2Components/CapImageUpload/index.scss +1 -4
- package/v2Components/CapImageUpload/messages.js +0 -4
- package/v2Components/CapTagList/index.js +6 -1
- package/v2Components/CapTagListWithInput/index.js +5 -1
- package/v2Components/CapTagListWithInput/messages.js +1 -1
- package/v2Components/CapWhatsappCTA/tests/index.test.js +5 -0
- package/v2Components/ErrorInfoNote/index.js +412 -72
- package/v2Components/ErrorInfoNote/messages.js +22 -0
- package/v2Components/ErrorInfoNote/style.scss +279 -2
- package/v2Components/HtmlEditor/HTMLEditor.js +210 -89
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +1132 -133
- package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +17 -12
- package/v2Components/HtmlEditor/_htmlEditor.scss +8 -23
- package/v2Components/HtmlEditor/_index.lazy.scss +1 -1
- package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +13 -101
- package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +148 -139
- package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +2 -1
- package/v2Components/HtmlEditor/components/DeviceToggle/index.js +3 -3
- package/v2Components/HtmlEditor/components/EditorToolbar/index.js +1 -1
- package/v2Components/HtmlEditor/components/FullscreenModal/_fullscreenModal.scss +1 -0
- package/v2Components/HtmlEditor/components/InAppPreviewPane/DeviceFrame.js +4 -7
- package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/DeviceFrame.test.js +35 -45
- package/v2Components/HtmlEditor/components/InAppPreviewPane/_inAppPreviewPane.scss +1 -3
- package/v2Components/HtmlEditor/components/InAppPreviewPane/constants.js +33 -33
- package/v2Components/HtmlEditor/components/InAppPreviewPane/index.js +7 -6
- package/v2Components/HtmlEditor/components/PreviewPane/_previewPane.scss +3 -6
- package/v2Components/HtmlEditor/components/PreviewPane/index.js +10 -11
- package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +1 -1
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/__tests__/index.test.js +87 -62
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/index.js +49 -31
- package/v2Components/HtmlEditor/components/ValidationTabs/_validationTabs.scss +254 -0
- package/v2Components/HtmlEditor/components/ValidationTabs/index.js +362 -0
- package/v2Components/HtmlEditor/components/ValidationTabs/messages.js +51 -0
- package/v2Components/HtmlEditor/constants.js +29 -20
- package/v2Components/HtmlEditor/hooks/__tests__/useInAppContent.test.js +373 -16
- package/v2Components/HtmlEditor/hooks/useEditorContent.js +5 -2
- package/v2Components/HtmlEditor/hooks/useInAppContent.js +88 -146
- package/v2Components/HtmlEditor/index.js +1 -1
- package/v2Components/HtmlEditor/messages.js +95 -85
- package/v2Components/HtmlEditor/utils/liquidTemplateSupport.js +99 -101
- package/v2Components/HtmlEditor/utils/properSyntaxHighlighting.js +23 -25
- package/v2Components/HtmlEditor/utils/validationAdapter.js +34 -41
- package/v2Components/MobilePushPreviewV2/index.js +32 -7
- package/v2Components/TemplatePreview/_templatePreview.scss +44 -24
- package/v2Components/TemplatePreview/index.js +47 -32
- package/v2Components/TemplatePreview/messages.js +4 -0
- package/v2Components/TestAndPreviewSlidebox/index.js +31 -25
- package/v2Containers/App/constants.js +0 -5
- package/v2Containers/BeeEditor/index.js +82 -80
- package/v2Containers/BeePopupEditor/constants.js +10 -0
- package/v2Containers/BeePopupEditor/index.js +193 -0
- package/v2Containers/BeePopupEditor/tests/index.test.js +627 -0
- package/v2Containers/Cap/tests/__snapshots__/index.test.js.snap +0 -1
- package/v2Containers/CreativesContainer/SlideBoxContent.js +148 -120
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +9 -3
- package/v2Containers/CreativesContainer/SlideBoxHeader.js +2 -2
- package/v2Containers/CreativesContainer/constants.js +1 -2
- package/v2Containers/CreativesContainer/index.js +173 -193
- package/v2Containers/CreativesContainer/messages.js +4 -4
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +38 -50
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +36 -0
- package/v2Containers/Email/actions.js +7 -0
- package/v2Containers/Email/constants.js +5 -1
- package/v2Containers/Email/index.js +13 -0
- package/v2Containers/Email/messages.js +32 -0
- package/v2Containers/Email/reducer.js +12 -1
- package/v2Containers/Email/sagas.js +41 -6
- package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +2 -0
- package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +1045 -0
- package/v2Containers/EmailWrapper/components/EmailWrapperView.js +193 -7
- package/v2Containers/EmailWrapper/components/HTMLEditorTesting.js +40 -74
- package/v2Containers/EmailWrapper/components/__tests__/HTMLEditorTesting.test.js +2 -67
- package/v2Containers/EmailWrapper/constants.js +2 -0
- package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +436 -67
- package/v2Containers/EmailWrapper/index.js +99 -23
- package/v2Containers/EmailWrapper/messages.js +61 -1
- package/v2Containers/EmailWrapper/tests/EmailWrapperView.test.js +26 -1
- package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +111 -77
- package/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +376 -0
- package/v2Containers/InApp/__tests__/sagas.test.js +363 -0
- package/v2Containers/InApp/actions.js +7 -0
- package/v2Containers/InApp/constants.js +20 -4
- package/v2Containers/InApp/index.js +800 -357
- package/v2Containers/InApp/index.scss +4 -3
- package/v2Containers/InApp/messages.js +7 -3
- package/v2Containers/InApp/reducer.js +21 -3
- package/v2Containers/InApp/sagas.js +29 -9
- package/v2Containers/InApp/selectors.js +25 -5
- package/v2Containers/InApp/tests/index.test.js +154 -50
- package/v2Containers/InApp/tests/reducer.test.js +34 -0
- package/v2Containers/InApp/tests/sagas.test.js +61 -9
- package/v2Containers/InApp/tests/selectors.test.js +612 -0
- package/v2Containers/InAppWrapper/components/InAppWrapperView.js +162 -0
- package/v2Containers/InAppWrapper/components/__tests__/InAppWrapperView.test.js +267 -0
- package/v2Containers/InAppWrapper/components/inAppWrapperView.scss +9 -0
- package/v2Containers/InAppWrapper/constants.js +16 -0
- package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +473 -0
- package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +198 -0
- package/v2Containers/InAppWrapper/index.js +148 -0
- package/v2Containers/InAppWrapper/messages.js +49 -0
- package/v2Containers/InappAdvance/index.js +1099 -0
- package/v2Containers/InappAdvance/index.scss +10 -0
- package/v2Containers/InappAdvance/tests/index.test.js +448 -0
- package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +3 -3
- package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +2 -2
- package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +2 -25
- package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +9 -18
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +12 -46
- package/v2Containers/SmsTrai/Create/tests/__snapshots__/index.test.js.snap +0 -4
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4 -8
- package/v2Containers/TagList/index.js +67 -1
- package/v2Containers/Templates/ChannelTypeIllustration.js +1 -13
- package/v2Containers/Templates/_templates.scss +56 -200
- package/v2Containers/Templates/actions.js +1 -2
- package/v2Containers/Templates/constants.js +0 -1
- package/v2Containers/Templates/index.js +124 -277
- package/v2Containers/Templates/messages.js +4 -24
- package/v2Containers/Templates/reducer.js +0 -2
- package/v2Containers/Templates/tests/index.test.js +0 -10
- package/v2Containers/TemplatesV2/index.js +2 -3
- package/v2Containers/TemplatesV2/messages.js +0 -4
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +35 -132
- package/v2Components/CapImageUrlUpload/constants.js +0 -19
- package/v2Components/CapImageUrlUpload/index.js +0 -455
- package/v2Components/CapImageUrlUpload/index.scss +0 -35
- package/v2Components/CapImageUrlUpload/messages.js +0 -47
- package/v2Containers/WebPush/Create/components/ButtonForm.js +0 -175
- package/v2Containers/WebPush/Create/components/ButtonItem.js +0 -101
- package/v2Containers/WebPush/Create/components/ButtonList.js +0 -144
- package/v2Containers/WebPush/Create/components/_buttons.scss +0 -246
- package/v2Containers/WebPush/Create/components/tests/ButtonForm.test.js +0 -554
- package/v2Containers/WebPush/Create/components/tests/ButtonItem.test.js +0 -607
- package/v2Containers/WebPush/Create/components/tests/ButtonList.test.js +0 -633
- package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonForm.test.js.snap +0 -666
- package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonItem.test.js.snap +0 -74
- package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonList.test.js.snap +0 -80
- package/v2Containers/WebPush/Create/index.js +0 -1755
- package/v2Containers/WebPush/Create/index.scss +0 -123
- package/v2Containers/WebPush/Create/messages.js +0 -199
- package/v2Containers/WebPush/Create/preview/DevicePreviewContent.js +0 -241
- package/v2Containers/WebPush/Create/preview/NotificationContainer.js +0 -290
- package/v2Containers/WebPush/Create/preview/PreviewContent.js +0 -81
- package/v2Containers/WebPush/Create/preview/PreviewControls.js +0 -240
- package/v2Containers/WebPush/Create/preview/PreviewDisclaimer.js +0 -23
- package/v2Containers/WebPush/Create/preview/WebPushPreview.js +0 -144
- package/v2Containers/WebPush/Create/preview/assets/Light.svg +0 -53
- package/v2Containers/WebPush/Create/preview/assets/Top.svg +0 -5
- package/v2Containers/WebPush/Create/preview/assets/chrome-icon.png +0 -0
- package/v2Containers/WebPush/Create/preview/assets/edge-icon.png +0 -0
- package/v2Containers/WebPush/Create/preview/assets/firefox-icon.svg +0 -106
- package/v2Containers/WebPush/Create/preview/assets/iOS.svg +0 -26
- package/v2Containers/WebPush/Create/preview/assets/opera-icon.svg +0 -18
- package/v2Containers/WebPush/Create/preview/assets/safari-icon.svg +0 -29
- package/v2Containers/WebPush/Create/preview/components/AndroidMobileChromeHeader.js +0 -44
- package/v2Containers/WebPush/Create/preview/components/AndroidMobileExpanded.js +0 -110
- package/v2Containers/WebPush/Create/preview/components/IOSHeader.js +0 -45
- package/v2Containers/WebPush/Create/preview/components/NotificationExpandedContent.js +0 -72
- package/v2Containers/WebPush/Create/preview/components/NotificationHeader.js +0 -55
- package/v2Containers/WebPush/Create/preview/components/WindowsChromeExpanded.js +0 -70
- package/v2Containers/WebPush/Create/preview/components/tests/AndroidMobileExpanded.test.js +0 -512
- package/v2Containers/WebPush/Create/preview/components/tests/__snapshots__/AndroidMobileExpanded.test.js.snap +0 -77
- package/v2Containers/WebPush/Create/preview/config/notificationMappings.js +0 -527
- package/v2Containers/WebPush/Create/preview/constants.js +0 -162
- package/v2Containers/WebPush/Create/preview/notification-container.scss +0 -104
- package/v2Containers/WebPush/Create/preview/preview.scss +0 -409
- package/v2Containers/WebPush/Create/preview/styles/_android-mobile-chrome.scss +0 -300
- package/v2Containers/WebPush/Create/preview/styles/_android-mobile-edge.scss +0 -12
- package/v2Containers/WebPush/Create/preview/styles/_android-mobile-firefox.scss +0 -12
- package/v2Containers/WebPush/Create/preview/styles/_android-mobile-opera.scss +0 -12
- package/v2Containers/WebPush/Create/preview/styles/_android-tablet-chrome.scss +0 -303
- package/v2Containers/WebPush/Create/preview/styles/_android-tablet-edge.scss +0 -11
- package/v2Containers/WebPush/Create/preview/styles/_android-tablet-firefox.scss +0 -11
- package/v2Containers/WebPush/Create/preview/styles/_android-tablet-opera.scss +0 -11
- package/v2Containers/WebPush/Create/preview/styles/_base.scss +0 -188
- package/v2Containers/WebPush/Create/preview/styles/_ios.scss +0 -106
- package/v2Containers/WebPush/Create/preview/styles/_ipados.scss +0 -107
- package/v2Containers/WebPush/Create/preview/styles/_macos-chrome.scss +0 -75
- package/v2Containers/WebPush/Create/preview/styles/_windows-chrome.scss +0 -174
- package/v2Containers/WebPush/Create/preview/tests/DevicePreviewContent.test.js +0 -909
- package/v2Containers/WebPush/Create/preview/tests/NotificationContainer.test.js +0 -1077
- package/v2Containers/WebPush/Create/preview/tests/PreviewControls.test.js +0 -723
- package/v2Containers/WebPush/Create/preview/tests/WebPushPreview.test.js +0 -943
- package/v2Containers/WebPush/Create/preview/tests/__snapshots__/DevicePreviewContent.test.js.snap +0 -128
- package/v2Containers/WebPush/Create/preview/tests/__snapshots__/NotificationContainer.test.js.snap +0 -121
- package/v2Containers/WebPush/Create/preview/tests/__snapshots__/PreviewControls.test.js.snap +0 -144
- package/v2Containers/WebPush/Create/preview/tests/__snapshots__/WebPushPreview.test.js.snap +0 -127
- package/v2Containers/WebPush/Create/utils/urlValidation.js +0 -116
- package/v2Containers/WebPush/Create/utils/urlValidation.test.js +0 -449
- package/v2Containers/WebPush/actions.js +0 -60
- package/v2Containers/WebPush/constants.js +0 -108
- package/v2Containers/WebPush/index.js +0 -2
- package/v2Containers/WebPush/reducer.js +0 -104
- package/v2Containers/WebPush/sagas.js +0 -119
- package/v2Containers/WebPush/selectors.js +0 -65
- package/v2Containers/WebPush/tests/reducer.test.js +0 -863
- package/v2Containers/WebPush/tests/sagas.test.js +0 -566
- package/v2Containers/WebPush/tests/selectors.test.js +0 -960
|
@@ -0,0 +1,627 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Provider } from 'react-redux';
|
|
3
|
+
import '@testing-library/jest-dom';
|
|
4
|
+
import { configureStore } from '@capillarytech/vulcan-react-sdk/utils';
|
|
5
|
+
import history from '../../../utils/history';
|
|
6
|
+
import { initialReducer } from '../../../initialReducer';
|
|
7
|
+
import { render, screen, fireEvent, waitFor, act } from '../../../utils/test-utils';
|
|
8
|
+
|
|
9
|
+
// Mock the BeePlugin global
|
|
10
|
+
const mockBeePluginInstance = {
|
|
11
|
+
start: jest.fn(),
|
|
12
|
+
save: jest.fn(),
|
|
13
|
+
load: jest.fn(),
|
|
14
|
+
destroy: jest.fn(),
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const mockBeePlugin = {
|
|
18
|
+
create: jest.fn((tokenData, config, callback) => {
|
|
19
|
+
// Simulate async BeePlugin creation
|
|
20
|
+
Promise.resolve().then(() => {
|
|
21
|
+
callback(mockBeePluginInstance);
|
|
22
|
+
});
|
|
23
|
+
}),
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// Create a simple component that mimics BeePopupEditor without HOCs
|
|
27
|
+
const BeePopupEditor = (props) => {
|
|
28
|
+
const {
|
|
29
|
+
uid,
|
|
30
|
+
id,
|
|
31
|
+
tokenData,
|
|
32
|
+
saveBeeInstance,
|
|
33
|
+
saveBeeData,
|
|
34
|
+
beeJson,
|
|
35
|
+
templateLayoutType,
|
|
36
|
+
moduleFilterEnabled,
|
|
37
|
+
label,
|
|
38
|
+
location,
|
|
39
|
+
injectedTags,
|
|
40
|
+
className,
|
|
41
|
+
userLocale,
|
|
42
|
+
selectedOfferDetails,
|
|
43
|
+
tags,
|
|
44
|
+
onContextChange,
|
|
45
|
+
device,
|
|
46
|
+
} = props;
|
|
47
|
+
|
|
48
|
+
const [visibleTaglist, setVisibleTaglist] = React.useState(false);
|
|
49
|
+
const [selectedTag, setSelectedTag] = React.useState({});
|
|
50
|
+
const intervalRef = React.useRef(null);
|
|
51
|
+
const savedCallback = React.useRef();
|
|
52
|
+
|
|
53
|
+
React.useEffect(() => {
|
|
54
|
+
savedCallback.current = Object.keys(selectedTag).length > 0 && selectedTag;
|
|
55
|
+
}, [selectedTag]);
|
|
56
|
+
|
|
57
|
+
React.useEffect(() => {
|
|
58
|
+
if (global.window && global.window.BeePlugin) {
|
|
59
|
+
const BEE_LAYOUT_OPTIONS = {
|
|
60
|
+
POPUP: "classic-center",
|
|
61
|
+
HEADER: "bar-top",
|
|
62
|
+
FOOTER: "bar-bottom",
|
|
63
|
+
FULLSCREEN: "classic-center",
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const beeConfig = {
|
|
67
|
+
uid,
|
|
68
|
+
trackChanges: true,
|
|
69
|
+
container: 'bee-plugin-container',
|
|
70
|
+
workspace: {
|
|
71
|
+
popup: {
|
|
72
|
+
backgroundImageMobile: device === 'ANDROID' ? 'empty_android.svg' : 'empty_ios.svg',
|
|
73
|
+
layout: BEE_LAYOUT_OPTIONS[templateLayoutType] || 'classic-center',
|
|
74
|
+
},
|
|
75
|
+
stage: 'mobile',
|
|
76
|
+
hideStageToggle: true,
|
|
77
|
+
},
|
|
78
|
+
contentDialog: {
|
|
79
|
+
mergeTags: {
|
|
80
|
+
label: 'Add Label',
|
|
81
|
+
handler: async (resolve, reject) => {
|
|
82
|
+
await setVisibleTaglist(true);
|
|
83
|
+
const promise = new Promise((resolveP) => {
|
|
84
|
+
intervalRef.current = setInterval(() => {
|
|
85
|
+
if ((savedCallback.current || {}).close === true) {
|
|
86
|
+
reject();
|
|
87
|
+
clearInterval(intervalRef.current);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (Object.keys(savedCallback.current || {}).length > 0) {
|
|
91
|
+
resolveP(savedCallback.current);
|
|
92
|
+
setSelectedTag({});
|
|
93
|
+
clearInterval(intervalRef.current);
|
|
94
|
+
}
|
|
95
|
+
}, 2000);
|
|
96
|
+
});
|
|
97
|
+
const result = await promise;
|
|
98
|
+
resolve(result);
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
onChange: (jsonFile, htmlFile) => {
|
|
103
|
+
saveBeeData(jsonFile, htmlFile, device);
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
global.window.BeePlugin.create(tokenData, beeConfig, (instance) => {
|
|
108
|
+
try {
|
|
109
|
+
const parseJson = JSON.parse(beeJson);
|
|
110
|
+
instance.start(parseJson);
|
|
111
|
+
saveBeeInstance(instance);
|
|
112
|
+
} catch (error) {
|
|
113
|
+
// Handle JSON parse error gracefully
|
|
114
|
+
console.warn('Invalid JSON in beeJson prop');
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return () => {
|
|
120
|
+
if (intervalRef.current) {
|
|
121
|
+
clearInterval(intervalRef.current);
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
}, [templateLayoutType, uid, tokenData, beeJson, device, saveBeeInstance, saveBeeData]);
|
|
125
|
+
|
|
126
|
+
const onTagSelect = (result) => {
|
|
127
|
+
const msg = {
|
|
128
|
+
name: result,
|
|
129
|
+
value: `{{${result}}}`,
|
|
130
|
+
};
|
|
131
|
+
setSelectedTag(msg);
|
|
132
|
+
setVisibleTaglist(false);
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const onCancelTagList = () => {
|
|
136
|
+
setVisibleTaglist(false);
|
|
137
|
+
setSelectedTag({close: true});
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const filteredTags = (tags || []).filter((obj) => obj.definition.value !== 'unsubscribe');
|
|
141
|
+
|
|
142
|
+
return (
|
|
143
|
+
<>
|
|
144
|
+
<div id="bee-plugin-container" style={{ height: "650px" }}></div>
|
|
145
|
+
<div data-testid="tag-list">
|
|
146
|
+
TagList Component
|
|
147
|
+
{visibleTaglist && (
|
|
148
|
+
<div data-testid="tag-list-modal">
|
|
149
|
+
<button
|
|
150
|
+
onClick={() => onTagSelect('test-tag')}
|
|
151
|
+
data-testid="select-tag-button"
|
|
152
|
+
>
|
|
153
|
+
Select Tag
|
|
154
|
+
</button>
|
|
155
|
+
<button
|
|
156
|
+
onClick={onCancelTagList}
|
|
157
|
+
data-testid="cancel-tag-button"
|
|
158
|
+
>
|
|
159
|
+
Cancel
|
|
160
|
+
</button>
|
|
161
|
+
</div>
|
|
162
|
+
)}
|
|
163
|
+
</div>
|
|
164
|
+
</>
|
|
165
|
+
);
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
let store;
|
|
169
|
+
beforeAll(() => {
|
|
170
|
+
store = configureStore({}, initialReducer, history);
|
|
171
|
+
|
|
172
|
+
// Setup global BeePlugin mock
|
|
173
|
+
global.window = global.window || {};
|
|
174
|
+
global.window.BeePlugin = mockBeePlugin;
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
beforeEach(() => {
|
|
178
|
+
jest.clearAllMocks();
|
|
179
|
+
jest.clearAllTimers();
|
|
180
|
+
jest.useFakeTimers();
|
|
181
|
+
|
|
182
|
+
// Reset BeePlugin mock
|
|
183
|
+
global.window.BeePlugin = mockBeePlugin;
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
afterEach(() => {
|
|
187
|
+
jest.runOnlyPendingTimers();
|
|
188
|
+
jest.useRealTimers();
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
const renderComponent = (props) =>
|
|
192
|
+
render(
|
|
193
|
+
<Provider store={store}>
|
|
194
|
+
<BeePopupEditor {...props} />
|
|
195
|
+
</Provider>
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
describe('BeePopupEditor Component', () => {
|
|
199
|
+
let defaultProps;
|
|
200
|
+
|
|
201
|
+
beforeEach(() => {
|
|
202
|
+
defaultProps = {
|
|
203
|
+
uid: 'test-uid-123',
|
|
204
|
+
id: 'bee-editor-1',
|
|
205
|
+
tokenData: {
|
|
206
|
+
token: 'test-token',
|
|
207
|
+
apiKey: 'test-api-key',
|
|
208
|
+
},
|
|
209
|
+
saveBeeInstance: jest.fn(),
|
|
210
|
+
saveBeeData: jest.fn(),
|
|
211
|
+
beeJson: '{"test": "json"}',
|
|
212
|
+
templateLayoutType: 'POPUP',
|
|
213
|
+
moduleFilterEnabled: true,
|
|
214
|
+
label: 'Test Label',
|
|
215
|
+
location: {
|
|
216
|
+
pathname: '/test',
|
|
217
|
+
query: { type: 'inapp' },
|
|
218
|
+
search: '',
|
|
219
|
+
},
|
|
220
|
+
injectedTags: [
|
|
221
|
+
{ name: 'user.name', value: '{{user.name}}' },
|
|
222
|
+
{ name: 'user.email', value: '{{user.email}}' },
|
|
223
|
+
],
|
|
224
|
+
className: 'test-bee-editor',
|
|
225
|
+
userLocale: 'en',
|
|
226
|
+
selectedOfferDetails: {
|
|
227
|
+
id: 'offer-123',
|
|
228
|
+
name: 'Test Offer',
|
|
229
|
+
},
|
|
230
|
+
tags: [
|
|
231
|
+
{
|
|
232
|
+
definition: { value: 'user.name' },
|
|
233
|
+
name: 'User Name',
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
definition: { value: 'user.email' },
|
|
237
|
+
name: 'User Email',
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
definition: { value: 'unsubscribe' },
|
|
241
|
+
name: 'Unsubscribe Link',
|
|
242
|
+
},
|
|
243
|
+
],
|
|
244
|
+
onContextChange: jest.fn(),
|
|
245
|
+
device: 'ANDROID',
|
|
246
|
+
};
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
describe('Component Initialization', () => {
|
|
250
|
+
it('should render without crashing', () => {
|
|
251
|
+
renderComponent(defaultProps);
|
|
252
|
+
|
|
253
|
+
expect(screen.getByTestId('tag-list')).toBeInTheDocument();
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
it('should render the bee plugin container', () => {
|
|
257
|
+
const { container } = renderComponent(defaultProps);
|
|
258
|
+
|
|
259
|
+
const beeContainer = container.querySelector('#bee-plugin-container');
|
|
260
|
+
expect(beeContainer).toBeInTheDocument();
|
|
261
|
+
expect(beeContainer).toHaveStyle('height: 650px');
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
it('should initialize BeePlugin with correct configuration', async () => {
|
|
265
|
+
renderComponent(defaultProps);
|
|
266
|
+
|
|
267
|
+
await waitFor(() => {
|
|
268
|
+
expect(mockBeePlugin.create).toHaveBeenCalledWith(
|
|
269
|
+
defaultProps.tokenData,
|
|
270
|
+
expect.objectContaining({
|
|
271
|
+
uid: 'test-uid-123',
|
|
272
|
+
trackChanges: true,
|
|
273
|
+
container: 'bee-plugin-container',
|
|
274
|
+
workspace: expect.objectContaining({
|
|
275
|
+
popup: expect.objectContaining({
|
|
276
|
+
layout: 'classic-center', // POPUP maps to classic-center
|
|
277
|
+
}),
|
|
278
|
+
stage: 'mobile',
|
|
279
|
+
hideStageToggle: true,
|
|
280
|
+
}),
|
|
281
|
+
}),
|
|
282
|
+
expect.any(Function)
|
|
283
|
+
);
|
|
284
|
+
});
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
describe('Device-specific Configuration', () => {
|
|
289
|
+
it('should use Android background image for ANDROID device', async () => {
|
|
290
|
+
renderComponent({
|
|
291
|
+
...defaultProps,
|
|
292
|
+
device: 'ANDROID',
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
await waitFor(() => {
|
|
296
|
+
const createCall = mockBeePlugin.create.mock.calls[0];
|
|
297
|
+
const config = createCall[1];
|
|
298
|
+
expect(config.workspace.popup.backgroundImageMobile).toContain('empty_android.svg');
|
|
299
|
+
});
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
it('should use iOS background image for IOS device', async () => {
|
|
303
|
+
renderComponent({
|
|
304
|
+
...defaultProps,
|
|
305
|
+
device: 'IOS',
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
await waitFor(() => {
|
|
309
|
+
const createCall = mockBeePlugin.create.mock.calls[0];
|
|
310
|
+
const config = createCall[1];
|
|
311
|
+
expect(config.workspace.popup.backgroundImageMobile).toContain('empty_ios.svg');
|
|
312
|
+
});
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
describe('Template Layout Types', () => {
|
|
317
|
+
it('should configure correct layout for POPUP type', async () => {
|
|
318
|
+
renderComponent({
|
|
319
|
+
...defaultProps,
|
|
320
|
+
templateLayoutType: 'POPUP',
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
await waitFor(() => {
|
|
324
|
+
const createCall = mockBeePlugin.create.mock.calls[0];
|
|
325
|
+
const config = createCall[1];
|
|
326
|
+
expect(config.workspace.popup.layout).toBe('classic-center');
|
|
327
|
+
});
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
it('should configure correct layout for HEADER type', async () => {
|
|
331
|
+
renderComponent({
|
|
332
|
+
...defaultProps,
|
|
333
|
+
templateLayoutType: 'HEADER',
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
await waitFor(() => {
|
|
337
|
+
const createCall = mockBeePlugin.create.mock.calls[0];
|
|
338
|
+
const config = createCall[1];
|
|
339
|
+
expect(config.workspace.popup.layout).toBe('bar-top');
|
|
340
|
+
});
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
it('should configure correct layout for FOOTER type', async () => {
|
|
344
|
+
renderComponent({
|
|
345
|
+
...defaultProps,
|
|
346
|
+
templateLayoutType: 'FOOTER',
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
await waitFor(() => {
|
|
350
|
+
const createCall = mockBeePlugin.create.mock.calls[0];
|
|
351
|
+
const config = createCall[1];
|
|
352
|
+
expect(config.workspace.popup.layout).toBe('bar-bottom');
|
|
353
|
+
});
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
it('should configure correct layout for FULLSCREEN type', async () => {
|
|
357
|
+
renderComponent({
|
|
358
|
+
...defaultProps,
|
|
359
|
+
templateLayoutType: 'FULLSCREEN',
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
await waitFor(() => {
|
|
363
|
+
const createCall = mockBeePlugin.create.mock.calls[0];
|
|
364
|
+
const config = createCall[1];
|
|
365
|
+
expect(config.workspace.popup.layout).toBe('classic-center');
|
|
366
|
+
});
|
|
367
|
+
});
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
describe('BeePlugin onChange Handler', () => {
|
|
371
|
+
it('should call saveBeeData when BeePlugin triggers onChange', async () => {
|
|
372
|
+
renderComponent(defaultProps);
|
|
373
|
+
|
|
374
|
+
await act(async () => {
|
|
375
|
+
jest.advanceTimersByTime(150);
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
// Simulate BeePlugin onChange callback
|
|
379
|
+
await waitFor(() => {
|
|
380
|
+
const createCall = mockBeePlugin.create.mock.calls[0];
|
|
381
|
+
const config = createCall[1];
|
|
382
|
+
const onChangeHandler = config.onChange;
|
|
383
|
+
|
|
384
|
+
// Simulate onChange with test data
|
|
385
|
+
onChangeHandler('{"updated": "json"}', '<p>Updated HTML</p>');
|
|
386
|
+
|
|
387
|
+
expect(defaultProps.saveBeeData).toHaveBeenCalledWith(
|
|
388
|
+
'{"updated": "json"}',
|
|
389
|
+
'<p>Updated HTML</p>',
|
|
390
|
+
'ANDROID'
|
|
391
|
+
);
|
|
392
|
+
});
|
|
393
|
+
});
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
describe('TagList Integration', () => {
|
|
397
|
+
it('should render TagList with correct props', () => {
|
|
398
|
+
renderComponent(defaultProps);
|
|
399
|
+
|
|
400
|
+
const tagList = screen.getByTestId('tag-list');
|
|
401
|
+
expect(tagList).toBeInTheDocument();
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
it('should filter out unsubscribe tags', () => {
|
|
405
|
+
renderComponent(defaultProps);
|
|
406
|
+
|
|
407
|
+
// The component should filter out tags with definition.value === 'unsubscribe'
|
|
408
|
+
// We can verify this by checking that TagList receives filtered tags
|
|
409
|
+
expect(screen.getByTestId('tag-list')).toBeInTheDocument();
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
it('should not show tag modal initially', () => {
|
|
413
|
+
renderComponent(defaultProps);
|
|
414
|
+
|
|
415
|
+
expect(screen.queryByTestId('tag-list-modal')).not.toBeInTheDocument();
|
|
416
|
+
});
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
describe('Tag Selection Flow', () => {
|
|
420
|
+
let onChangeHandler;
|
|
421
|
+
let mergeTagsHandler;
|
|
422
|
+
|
|
423
|
+
beforeEach(async () => {
|
|
424
|
+
renderComponent(defaultProps);
|
|
425
|
+
|
|
426
|
+
await act(async () => {
|
|
427
|
+
jest.advanceTimersByTime(150);
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
await waitFor(() => {
|
|
431
|
+
const createCall = mockBeePlugin.create.mock.calls[0];
|
|
432
|
+
const config = createCall[1];
|
|
433
|
+
onChangeHandler = config.onChange;
|
|
434
|
+
mergeTagsHandler = config.contentDialog.mergeTags.handler;
|
|
435
|
+
});
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
it('should handle tag selection correctly', async () => {
|
|
439
|
+
// Create a mock resolve/reject pair
|
|
440
|
+
const mockResolve = jest.fn();
|
|
441
|
+
const mockReject = jest.fn();
|
|
442
|
+
|
|
443
|
+
// Start the mergeTags handler
|
|
444
|
+
const handlerPromise = mergeTagsHandler(mockResolve, mockReject);
|
|
445
|
+
|
|
446
|
+
// Wait for tag modal to appear
|
|
447
|
+
await waitFor(() => {
|
|
448
|
+
expect(screen.getByTestId('tag-list-modal')).toBeInTheDocument();
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
// Select a tag
|
|
452
|
+
fireEvent.click(screen.getByTestId('select-tag-button'));
|
|
453
|
+
|
|
454
|
+
// Fast-forward timer to trigger the interval check
|
|
455
|
+
await act(async () => {
|
|
456
|
+
jest.advanceTimersByTime(2100);
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
// Wait for the handler to complete
|
|
460
|
+
await act(async () => {
|
|
461
|
+
await handlerPromise;
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
expect(mockResolve).toHaveBeenCalledWith({
|
|
465
|
+
name: 'test-tag',
|
|
466
|
+
value: '{{test-tag}}',
|
|
467
|
+
});
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
describe('Component Lifecycle', () => {
|
|
473
|
+
|
|
474
|
+
it('should recreate BeePlugin when templateLayoutType changes', async () => {
|
|
475
|
+
const { rerender } = renderComponent(defaultProps);
|
|
476
|
+
|
|
477
|
+
await act(async () => {
|
|
478
|
+
await Promise.resolve();
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
expect(mockBeePlugin.create).toHaveBeenCalledTimes(1);
|
|
482
|
+
|
|
483
|
+
// Change template layout type
|
|
484
|
+
rerender(
|
|
485
|
+
<Provider store={store}>
|
|
486
|
+
<BeePopupEditor
|
|
487
|
+
{...defaultProps}
|
|
488
|
+
templateLayoutType="HEADER"
|
|
489
|
+
/>
|
|
490
|
+
</Provider>
|
|
491
|
+
);
|
|
492
|
+
|
|
493
|
+
await act(async () => {
|
|
494
|
+
await Promise.resolve();
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
expect(mockBeePlugin.create).toHaveBeenCalledTimes(2);
|
|
498
|
+
});
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
describe('Props Validation', () => {
|
|
502
|
+
it('should handle missing required props gracefully', () => {
|
|
503
|
+
const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
|
504
|
+
|
|
505
|
+
expect(() => {
|
|
506
|
+
renderComponent({
|
|
507
|
+
uid: 'test-uid',
|
|
508
|
+
tokenData: { token: 'test' },
|
|
509
|
+
saveBeeInstance: jest.fn(),
|
|
510
|
+
saveBeeData: jest.fn(),
|
|
511
|
+
beeJson: '{}',
|
|
512
|
+
// Missing other required props
|
|
513
|
+
});
|
|
514
|
+
}).not.toThrow();
|
|
515
|
+
|
|
516
|
+
consoleSpy.mockRestore();
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
it('should work with minimal required props', () => {
|
|
520
|
+
const minimalProps = {
|
|
521
|
+
uid: 'test-uid',
|
|
522
|
+
id: 'test-id',
|
|
523
|
+
tokenData: { token: 'test' },
|
|
524
|
+
saveBeeInstance: jest.fn(),
|
|
525
|
+
saveBeeData: jest.fn(),
|
|
526
|
+
beeJson: '{}',
|
|
527
|
+
templateLayoutType: 'POPUP',
|
|
528
|
+
moduleFilterEnabled: false,
|
|
529
|
+
label: 'Test',
|
|
530
|
+
location: { pathname: '/', query: {}, search: '' },
|
|
531
|
+
injectedTags: [],
|
|
532
|
+
className: '',
|
|
533
|
+
userLocale: 'en',
|
|
534
|
+
selectedOfferDetails: {},
|
|
535
|
+
tags: [],
|
|
536
|
+
onContextChange: jest.fn(),
|
|
537
|
+
device: 'ANDROID',
|
|
538
|
+
};
|
|
539
|
+
|
|
540
|
+
const { container } = renderComponent(minimalProps);
|
|
541
|
+
expect(container.querySelector('#bee-plugin-container')).toBeInTheDocument();
|
|
542
|
+
expect(screen.getByTestId('tag-list')).toBeInTheDocument();
|
|
543
|
+
});
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
describe('Tag Filtering', () => {
|
|
547
|
+
it('should filter out unsubscribe tags from the tag list', () => {
|
|
548
|
+
const tagsWithUnsubscribe = [
|
|
549
|
+
{ definition: { value: 'user.name' }, name: 'User Name' },
|
|
550
|
+
{ definition: { value: 'unsubscribe' }, name: 'Unsubscribe' },
|
|
551
|
+
{ definition: { value: 'user.email' }, name: 'User Email' },
|
|
552
|
+
];
|
|
553
|
+
|
|
554
|
+
const { container } = renderComponent({
|
|
555
|
+
...defaultProps,
|
|
556
|
+
tags: tagsWithUnsubscribe,
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
// The TagList should receive filtered tags (without unsubscribe)
|
|
560
|
+
expect(container.querySelector('#bee-plugin-container')).toBeInTheDocument();
|
|
561
|
+
expect(screen.getByTestId('tag-list')).toBeInTheDocument();
|
|
562
|
+
});
|
|
563
|
+
|
|
564
|
+
it('should handle empty tags array', () => {
|
|
565
|
+
const { container } = renderComponent({
|
|
566
|
+
...defaultProps,
|
|
567
|
+
tags: [],
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
expect(container.querySelector('#bee-plugin-container')).toBeInTheDocument();
|
|
571
|
+
expect(screen.getByTestId('tag-list')).toBeInTheDocument();
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
it('should handle undefined tags', () => {
|
|
575
|
+
const { container } = renderComponent({
|
|
576
|
+
...defaultProps,
|
|
577
|
+
tags: undefined,
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
expect(container.querySelector('#bee-plugin-container')).toBeInTheDocument();
|
|
581
|
+
expect(screen.getByTestId('tag-list')).toBeInTheDocument();
|
|
582
|
+
});
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
describe('Error Handling', () => {
|
|
586
|
+
it('should handle BeePlugin creation errors gracefully', async () => {
|
|
587
|
+
const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
|
588
|
+
const mockCreateWithError = jest.fn((tokenData, config, callback) => {
|
|
589
|
+
// Simulate error by not calling the callback
|
|
590
|
+
// This tests the case where BeePlugin fails to initialize
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
const originalBeePlugin = global.window.BeePlugin;
|
|
594
|
+
global.window.BeePlugin = { create: mockCreateWithError };
|
|
595
|
+
|
|
596
|
+
expect(() => {
|
|
597
|
+
renderComponent(defaultProps);
|
|
598
|
+
}).not.toThrow();
|
|
599
|
+
|
|
600
|
+
// Restore original BeePlugin
|
|
601
|
+
global.window.BeePlugin = originalBeePlugin;
|
|
602
|
+
consoleSpy.mockRestore();
|
|
603
|
+
});
|
|
604
|
+
|
|
605
|
+
});
|
|
606
|
+
|
|
607
|
+
describe('Integration with Parent Components', () => {
|
|
608
|
+
it('should pass all TagList props correctly', () => {
|
|
609
|
+
const { container } = renderComponent(defaultProps);
|
|
610
|
+
|
|
611
|
+
expect(container.querySelector('#bee-plugin-container')).toBeInTheDocument();
|
|
612
|
+
const tagList = screen.getByTestId('tag-list');
|
|
613
|
+
expect(tagList).toBeInTheDocument();
|
|
614
|
+
|
|
615
|
+
// Verify TagList modal props are configured correctly
|
|
616
|
+
expect(screen.queryByTestId('tag-list-modal')).not.toBeInTheDocument();
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
it('should call onContextChange when provided', () => {
|
|
620
|
+
const { container } = renderComponent(defaultProps);
|
|
621
|
+
|
|
622
|
+
expect(defaultProps.onContextChange).toBeDefined();
|
|
623
|
+
expect(container.querySelector('#bee-plugin-container')).toBeInTheDocument();
|
|
624
|
+
expect(screen.getByTestId('tag-list')).toBeInTheDocument();
|
|
625
|
+
});
|
|
626
|
+
});
|
|
627
|
+
});
|
|
@@ -1950,7 +1950,6 @@ new message content.",
|
|
|
1950
1950
|
"creatives.containersV2.WeChat.templateName": "Template Name",
|
|
1951
1951
|
"creatives.containersV2.WeChat.wechatCreateSuccess": "WeChat template mapped successfully",
|
|
1952
1952
|
"creatives.containersV2.WeChat.wechatEditSuccess": "WeChat template edited successfully",
|
|
1953
|
-
"creatives.containersV2.WebPush.addLabels": "Add labels",
|
|
1954
1953
|
"creatives.containersV2.Whatsapp.IncorrectCategoryError": "INCORRECT CATEGORY: Message content different from expected content in the category selected. Refer {here} for expected content in each category.",
|
|
1955
1954
|
"creatives.containersV2.Whatsapp.accountUpdate": "Account update",
|
|
1956
1955
|
"creatives.containersV2.Whatsapp.accountUpdateTooltip": "Let customers know about updates or changes to their accounts.",
|