@capillarytech/creatives-library 8.0.271 → 8.0.273
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/services/api.js +10 -0
- package/services/tests/api.test.js +34 -0
- package/tests/integration/TemplateCreation/TemplateCreation.integration.test.js +17 -35
- package/tests/integration/TemplateCreation/api-response.js +31 -1
- package/tests/integration/TemplateCreation/msw-handler.js +2 -0
- package/utils/common.js +5 -0
- package/utils/commonUtils.js +28 -5
- package/utils/imageUrlUpload.js +13 -14
- package/utils/tests/commonUtil.test.js +224 -0
- package/utils/tests/imageUrlUpload.test.js +298 -0
- package/utils/transformTemplateConfig.js +0 -10
- package/v2Components/CapDeviceContent/index.js +61 -56
- 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/constants.js +1 -0
- package/v2Components/ErrorInfoNote/index.js +402 -72
- package/v2Components/ErrorInfoNote/messages.js +32 -6
- package/v2Components/ErrorInfoNote/style.scss +278 -6
- package/v2Components/FormBuilder/tests/index.test.js +13 -4
- package/v2Components/HtmlEditor/HTMLEditor.js +418 -99
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +870 -0
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +1882 -133
- package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +27 -16
- package/v2Components/HtmlEditor/_htmlEditor.scss +108 -45
- package/v2Components/HtmlEditor/_index.lazy.scss +0 -1
- package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +23 -102
- package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +148 -140
- package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +2 -1
- package/v2Components/HtmlEditor/components/DeviceToggle/index.js +3 -3
- package/v2Components/HtmlEditor/components/EditorToolbar/_editorToolbar.scss +9 -1
- package/v2Components/HtmlEditor/components/EditorToolbar/index.js +31 -6
- package/v2Components/HtmlEditor/components/FullscreenModal/_fullscreenModal.scss +22 -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 +7 -10
- package/v2Components/HtmlEditor/components/PreviewPane/index.js +22 -43
- package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +1 -1
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/_validationErrorDisplay.scss +18 -0
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/index.js +36 -31
- package/v2Components/HtmlEditor/components/ValidationPanel/_validationPanel.scss +46 -34
- package/v2Components/HtmlEditor/components/ValidationPanel/constants.js +6 -0
- package/v2Components/HtmlEditor/components/ValidationPanel/index.js +52 -46
- package/v2Components/HtmlEditor/components/ValidationTabs/_validationTabs.scss +277 -0
- package/v2Components/HtmlEditor/components/ValidationTabs/index.js +295 -0
- package/v2Components/HtmlEditor/components/ValidationTabs/messages.js +51 -0
- package/v2Components/HtmlEditor/constants.js +45 -20
- package/v2Components/HtmlEditor/hooks/__tests__/useInAppContent.test.js +373 -16
- package/v2Components/HtmlEditor/hooks/__tests__/useValidation.test.js +351 -16
- package/v2Components/HtmlEditor/hooks/useEditorContent.js +5 -2
- package/v2Components/HtmlEditor/hooks/useInAppContent.js +88 -146
- package/v2Components/HtmlEditor/hooks/useValidation.js +213 -56
- package/v2Components/HtmlEditor/index.js +1 -1
- package/v2Components/HtmlEditor/messages.js +102 -94
- package/v2Components/HtmlEditor/utils/__tests__/htmlValidator.enhanced.test.js +214 -45
- package/v2Components/HtmlEditor/utils/__tests__/validationAdapter.test.js +134 -0
- package/v2Components/HtmlEditor/utils/contentSanitizer.js +40 -41
- package/v2Components/HtmlEditor/utils/htmlValidator.js +71 -72
- package/v2Components/HtmlEditor/utils/liquidTemplateSupport.js +158 -124
- package/v2Components/HtmlEditor/utils/properSyntaxHighlighting.js +23 -25
- package/v2Components/HtmlEditor/utils/validationAdapter.js +66 -41
- package/v2Components/HtmlEditor/utils/validationConstants.js +38 -0
- package/v2Components/MobilePushPreviewV2/constants.js +6 -0
- package/v2Components/MobilePushPreviewV2/index.js +33 -7
- package/v2Components/TemplatePreview/_templatePreview.scss +55 -24
- package/v2Components/TemplatePreview/index.js +47 -32
- package/v2Components/TemplatePreview/messages.js +4 -0
- package/v2Components/TestAndPreviewSlidebox/_testAndPreviewSlidebox.scss +1 -0
- package/v2Containers/BeeEditor/index.js +172 -90
- package/v2Containers/BeePopupEditor/_beePopupEditor.scss +14 -0
- package/v2Containers/BeePopupEditor/constants.js +10 -0
- package/v2Containers/BeePopupEditor/index.js +194 -0
- package/v2Containers/BeePopupEditor/tests/index.test.js +627 -0
- package/v2Containers/CreativesContainer/SlideBoxContent.js +127 -51
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +156 -13
- package/v2Containers/CreativesContainer/SlideBoxHeader.js +2 -1
- package/v2Containers/CreativesContainer/constants.js +1 -0
- package/v2Containers/CreativesContainer/index.js +251 -47
- package/v2Containers/CreativesContainer/messages.js +8 -0
- package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +11 -2
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +38 -50
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +103 -0
- package/v2Containers/Email/actions.js +7 -0
- package/v2Containers/Email/constants.js +5 -1
- package/v2Containers/Email/index.js +234 -29
- package/v2Containers/Email/messages.js +32 -0
- package/v2Containers/Email/reducer.js +12 -1
- package/v2Containers/Email/sagas.js +61 -7
- package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +2 -0
- package/v2Containers/Email/tests/reducer.test.js +46 -0
- package/v2Containers/Email/tests/sagas.test.js +320 -29
- package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +1246 -0
- package/v2Containers/EmailWrapper/components/EmailWrapperView.js +212 -21
- package/v2Containers/EmailWrapper/components/HTMLEditorTesting.js +40 -74
- package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +2614 -0
- package/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +520 -0
- package/v2Containers/EmailWrapper/components/__tests__/HTMLEditorTesting.test.js +2 -67
- package/v2Containers/EmailWrapper/constants.js +2 -0
- package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +627 -79
- package/v2Containers/EmailWrapper/index.js +103 -23
- package/v2Containers/EmailWrapper/messages.js +65 -1
- package/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +955 -0
- package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +596 -82
- 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 +802 -360
- 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 +151 -0
- package/v2Containers/InAppWrapper/components/__tests__/InAppWrapperView.test.js +267 -0
- package/v2Containers/InAppWrapper/components/inAppWrapperView.scss +23 -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 -0
- package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +2 -0
- package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +2 -0
- package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +9 -0
- package/v2Containers/MobilePush/Create/index.js +1 -1
- package/v2Containers/MobilePush/Edit/index.js +10 -6
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +12 -0
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4 -0
- package/v2Containers/TagList/index.js +62 -19
- package/v2Containers/Templates/_templates.scss +60 -1
- package/v2Containers/Templates/index.js +89 -4
- package/v2Containers/Templates/messages.js +4 -0
- package/v2Containers/TemplatesV2/TemplatesV2.style.js +4 -2
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +34 -0
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/__tests__/index.test.js +0 -152
- package/v2Containers/EmailWrapper/tests/EmailWrapperView.test.js +0 -214
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Provider } from 'react-redux';
|
|
3
|
+
import '@testing-library/jest-dom';
|
|
4
|
+
import { injectIntl } from 'react-intl';
|
|
5
|
+
import { configureStore } from '@capillarytech/vulcan-react-sdk/utils';
|
|
6
|
+
import history from '../../../utils/history';
|
|
7
|
+
import { initialReducer } from '../../../initialReducer';
|
|
8
|
+
import { InappAdvanced } from '../index';
|
|
9
|
+
import { render, screen, fireEvent, waitFor } from '../../../utils/test-utils';
|
|
10
|
+
|
|
11
|
+
// Mock child components that are complex or not under test
|
|
12
|
+
jest.mock('../../BeePopupEditor', () => ({
|
|
13
|
+
__esModule: true,
|
|
14
|
+
default: (props) => (
|
|
15
|
+
<div
|
|
16
|
+
data-testid={`bee-popup-editor-${props.device}`}
|
|
17
|
+
data-device={props.device}
|
|
18
|
+
data-template-layout-type={props.templateLayoutType}
|
|
19
|
+
>
|
|
20
|
+
BeePopupEditor - {props.device}
|
|
21
|
+
<button
|
|
22
|
+
onClick={() => props.saveBeeData('{"test": "json"}', '<p>Test HTML</p>', props.device)}
|
|
23
|
+
data-testid={`save-bee-data-${props.device}`}
|
|
24
|
+
>
|
|
25
|
+
Save Bee Data
|
|
26
|
+
</button>
|
|
27
|
+
<button
|
|
28
|
+
onClick={() => props.saveBeeInstance({ mockInstance: true })}
|
|
29
|
+
data-testid={`save-bee-instance-${props.device}`}
|
|
30
|
+
>
|
|
31
|
+
Save Bee Instance
|
|
32
|
+
</button>
|
|
33
|
+
</div>
|
|
34
|
+
),
|
|
35
|
+
}));
|
|
36
|
+
|
|
37
|
+
let store;
|
|
38
|
+
beforeAll(() => {
|
|
39
|
+
store = configureStore({}, initialReducer, history);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const ComponentToRender = injectIntl(InappAdvanced);
|
|
43
|
+
const renderComponent = (props) =>
|
|
44
|
+
render(
|
|
45
|
+
<Provider store={store}>
|
|
46
|
+
<ComponentToRender {...props} />
|
|
47
|
+
</Provider>
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
describe('InappAdvanced Component', () => {
|
|
51
|
+
let defaultProps;
|
|
52
|
+
let mockActions;
|
|
53
|
+
|
|
54
|
+
beforeEach(() => {
|
|
55
|
+
mockActions = {
|
|
56
|
+
getBeePopupBuilderToken: jest.fn(),
|
|
57
|
+
createInAppTemplate: jest.fn(),
|
|
58
|
+
editTemplate: jest.fn(),
|
|
59
|
+
clearCreateResponse: jest.fn(),
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const mockGlobalActions = {
|
|
63
|
+
fetchSchemaForEntity: jest.fn(),
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
defaultProps = {
|
|
67
|
+
intl: {
|
|
68
|
+
formatMessage: jest.fn((msg) => msg.defaultMessage || msg.id),
|
|
69
|
+
},
|
|
70
|
+
actions: mockActions,
|
|
71
|
+
globalActions: mockGlobalActions,
|
|
72
|
+
isFullMode: true,
|
|
73
|
+
onCreateComplete: jest.fn(),
|
|
74
|
+
params: { id: 'test-id' },
|
|
75
|
+
templateData: {},
|
|
76
|
+
editData: {},
|
|
77
|
+
accountData: {
|
|
78
|
+
selectedWeChatAccount: {
|
|
79
|
+
sourceAccountIdentifier: 'test-account',
|
|
80
|
+
id: 'account-123',
|
|
81
|
+
configs: {
|
|
82
|
+
android: '1',
|
|
83
|
+
ios: '1',
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
location: {
|
|
88
|
+
pathname: '/inapp/create',
|
|
89
|
+
query: { type: 'inapp' },
|
|
90
|
+
search: '',
|
|
91
|
+
},
|
|
92
|
+
getDefaultTags: 'inapp',
|
|
93
|
+
supportedTags: [],
|
|
94
|
+
metaEntities: {
|
|
95
|
+
tags: {
|
|
96
|
+
standard: [],
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
injectedTags: [],
|
|
100
|
+
getFormData: jest.fn(),
|
|
101
|
+
templateName: 'Test Template',
|
|
102
|
+
setTemplateName: jest.fn(),
|
|
103
|
+
beePopupBuilderTokenFetching: false,
|
|
104
|
+
beePopupBuilderToken: {
|
|
105
|
+
uuid: 'test-uuid-123',
|
|
106
|
+
token: 'test-token-456',
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
describe('Component Initialization', () => {
|
|
112
|
+
it('should render without crashing', () => {
|
|
113
|
+
renderComponent(defaultProps);
|
|
114
|
+
|
|
115
|
+
expect(screen.getByText('Create')).toBeInTheDocument();
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('should call getBeePopupBuilderToken on mount', () => {
|
|
119
|
+
renderComponent(defaultProps);
|
|
120
|
+
|
|
121
|
+
expect(mockActions.getBeePopupBuilderToken).toHaveBeenCalledTimes(1);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('should show loading spinner when beePopupBuilderTokenFetching is true', () => {
|
|
125
|
+
renderComponent({
|
|
126
|
+
...defaultProps,
|
|
127
|
+
beePopupBuilderTokenFetching: true,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// The spinner should be present but we can't easily test for it without mocking
|
|
131
|
+
expect(screen.getByText('Create')).toBeInTheDocument();
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
describe('Layout Selection', () => {
|
|
136
|
+
it('should render layout selection when isFullMode is true', () => {
|
|
137
|
+
renderComponent({
|
|
138
|
+
...defaultProps,
|
|
139
|
+
isFullMode: true,
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
expect(screen.getByText('Creative layout')).toBeInTheDocument();
|
|
143
|
+
// CapSelect from cap-ui-library should render a select element
|
|
144
|
+
const selectElements = screen.getAllByRole('button');
|
|
145
|
+
expect(selectElements.length).toBeGreaterThan(0);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('should update layout type when selection changes', () => {
|
|
149
|
+
renderComponent(defaultProps);
|
|
150
|
+
|
|
151
|
+
// Layout selection should be rendered
|
|
152
|
+
expect(screen.getByText('Creative layout')).toBeInTheDocument();
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
describe('Device Tabs', () => {
|
|
157
|
+
it('should render device tabs with Android and iOS options', () => {
|
|
158
|
+
renderComponent(defaultProps);
|
|
159
|
+
|
|
160
|
+
expect(screen.getByText('Android')).toBeInTheDocument();
|
|
161
|
+
expect(screen.getByText('IOS')).toBeInTheDocument();
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('should show BeePopupEditor for Android when Android tab is active', () => {
|
|
165
|
+
renderComponent({
|
|
166
|
+
...defaultProps,
|
|
167
|
+
beePopupBuilderToken: { uuid: 'test-uuid' },
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
expect(screen.getByTestId('bee-popup-editor-ANDROID')).toBeInTheDocument();
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('should only show supported device tabs', () => {
|
|
174
|
+
renderComponent({
|
|
175
|
+
...defaultProps,
|
|
176
|
+
accountData: {
|
|
177
|
+
selectedWeChatAccount: {
|
|
178
|
+
configs: {
|
|
179
|
+
android: '0', // Not supported
|
|
180
|
+
ios: '1', // Supported
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
expect(screen.queryByText('Android')).not.toBeInTheDocument();
|
|
187
|
+
expect(screen.getByText('IOS')).toBeInTheDocument();
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
describe('BeePopupEditor Integration', () => {
|
|
192
|
+
it('should pass correct props to BeePopupEditor', () => {
|
|
193
|
+
renderComponent({
|
|
194
|
+
...defaultProps,
|
|
195
|
+
beePopupBuilderToken: { uuid: 'test-uuid' },
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
const beeEditor = screen.getByTestId('bee-popup-editor-ANDROID');
|
|
199
|
+
expect(beeEditor).toHaveAttribute('data-device', 'ANDROID');
|
|
200
|
+
expect(beeEditor).toHaveAttribute('data-template-layout-type', 'MODAL');
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('should handle saveBeeData callback correctly', () => {
|
|
204
|
+
renderComponent({
|
|
205
|
+
...defaultProps,
|
|
206
|
+
beePopupBuilderToken: { uuid: 'test-uuid' },
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
const saveBeeDataButton = screen.getByTestId('save-bee-data-ANDROID');
|
|
210
|
+
fireEvent.click(saveBeeDataButton);
|
|
211
|
+
|
|
212
|
+
// The component should update its internal state with the JSON and HTML
|
|
213
|
+
expect(saveBeeDataButton).toBeInTheDocument(); // Basic check that callback was handled
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it('should handle saveBeeInstance callback correctly', () => {
|
|
217
|
+
renderComponent({
|
|
218
|
+
...defaultProps,
|
|
219
|
+
beePopupBuilderToken: { uuid: 'test-uuid' },
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
const saveBeeInstanceButton = screen.getByTestId('save-bee-instance-ANDROID');
|
|
223
|
+
fireEvent.click(saveBeeInstanceButton);
|
|
224
|
+
|
|
225
|
+
// The component should store the bee instance
|
|
226
|
+
expect(saveBeeInstanceButton).toBeInTheDocument(); // Basic check that callback was handled
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
it('should not render BeePopupEditor when no token is available', () => {
|
|
230
|
+
renderComponent({
|
|
231
|
+
...defaultProps,
|
|
232
|
+
beePopupBuilderToken: null,
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
expect(screen.queryByTestId('bee-popup-editor-ANDROID')).not.toBeInTheDocument();
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
describe('Action Buttons', () => {
|
|
240
|
+
it('should render Create button in full mode for new templates', () => {
|
|
241
|
+
renderComponent({
|
|
242
|
+
...defaultProps,
|
|
243
|
+
isFullMode: true,
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
expect(screen.getByText('Create')).toBeInTheDocument();
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it('should render Update button in edit mode', () => {
|
|
250
|
+
renderComponent({
|
|
251
|
+
...defaultProps,
|
|
252
|
+
isFullMode: true,
|
|
253
|
+
editData: {
|
|
254
|
+
templateDetails: {
|
|
255
|
+
name: 'Existing Template',
|
|
256
|
+
versions: {
|
|
257
|
+
base: {
|
|
258
|
+
content: {
|
|
259
|
+
ANDROID: { title: 'Test' },
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
expect(screen.getByText('Update')).toBeInTheDocument();
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
it('should render Done button in library mode', () => {
|
|
271
|
+
renderComponent({
|
|
272
|
+
...defaultProps,
|
|
273
|
+
isFullMode: false,
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
expect(screen.getByText('Done')).toBeInTheDocument();
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
it('should call appropriate action when Create button is clicked', async () => {
|
|
280
|
+
renderComponent({
|
|
281
|
+
...defaultProps,
|
|
282
|
+
isFullMode: true,
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
const createButton = screen.getByText('Create');
|
|
286
|
+
fireEvent.click(createButton);
|
|
287
|
+
|
|
288
|
+
// Wait for async operations to complete
|
|
289
|
+
await waitFor(() => {
|
|
290
|
+
expect(mockActions.createInAppTemplate).toHaveBeenCalled();
|
|
291
|
+
}, { timeout: 3000 });
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
describe('Form Data Integration', () => {
|
|
296
|
+
it('should call getFormData when in library mode', async () => {
|
|
297
|
+
const mockGetFormData = jest.fn();
|
|
298
|
+
renderComponent({
|
|
299
|
+
...defaultProps,
|
|
300
|
+
isFullMode: false,
|
|
301
|
+
getFormData: mockGetFormData,
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
const doneButton = screen.getByText('Done');
|
|
305
|
+
fireEvent.click(doneButton);
|
|
306
|
+
|
|
307
|
+
// Wait for async operations to complete
|
|
308
|
+
await waitFor(() => {
|
|
309
|
+
expect(mockGetFormData).toHaveBeenCalledWith({
|
|
310
|
+
value: expect.any(Object),
|
|
311
|
+
_id: 'test-id',
|
|
312
|
+
validity: true,
|
|
313
|
+
type: 'INAPP',
|
|
314
|
+
});
|
|
315
|
+
}, { timeout: 3000 });
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
describe('Template Name Integration', () => {
|
|
320
|
+
it('should display the template name when provided', () => {
|
|
321
|
+
renderComponent({
|
|
322
|
+
...defaultProps,
|
|
323
|
+
templateName: 'My Awesome Template',
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
// Template name should be used in the payload creation
|
|
327
|
+
expect(screen.getByText('Create')).toBeInTheDocument();
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
it('should handle setTemplateName callback', () => {
|
|
331
|
+
const mockSetTemplateName = jest.fn();
|
|
332
|
+
renderComponent({
|
|
333
|
+
...defaultProps,
|
|
334
|
+
setTemplateName: mockSetTemplateName,
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
// The component should be able to update template name
|
|
338
|
+
expect(mockSetTemplateName).toBeDefined();
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
describe('Account Data Integration', () => {
|
|
343
|
+
it('should handle missing account data gracefully', () => {
|
|
344
|
+
renderComponent({
|
|
345
|
+
...defaultProps,
|
|
346
|
+
accountData: {},
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
// Component should render without crashing
|
|
350
|
+
expect(screen.getByText('Create')).toBeInTheDocument();
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
it('should use account data in payload creation', () => {
|
|
354
|
+
renderComponent({
|
|
355
|
+
...defaultProps,
|
|
356
|
+
accountData: {
|
|
357
|
+
selectedWeChatAccount: {
|
|
358
|
+
sourceAccountIdentifier: 'test-account-123',
|
|
359
|
+
id: 'account-456',
|
|
360
|
+
},
|
|
361
|
+
},
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
// Account data should be used when creating the payload
|
|
365
|
+
expect(screen.getByText('Create')).toBeInTheDocument();
|
|
366
|
+
});
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
describe('Edit Flow', () => {
|
|
370
|
+
it('should initialize edit flow when editData is provided', () => {
|
|
371
|
+
renderComponent({
|
|
372
|
+
...defaultProps,
|
|
373
|
+
editData: {
|
|
374
|
+
templateDetails: {
|
|
375
|
+
name: 'Existing Template',
|
|
376
|
+
createdAt: '2023-01-01',
|
|
377
|
+
versions: {
|
|
378
|
+
base: {
|
|
379
|
+
content: {
|
|
380
|
+
ANDROID: {
|
|
381
|
+
isBEEeditor: true,
|
|
382
|
+
beeJson: '{"test": "json"}',
|
|
383
|
+
beeHtml: '<p>Test HTML</p>',
|
|
384
|
+
},
|
|
385
|
+
IOS: {
|
|
386
|
+
isBEEeditor: true,
|
|
387
|
+
beeJson: '{"test": "ios-json"}',
|
|
388
|
+
beeHtml: '<p>iOS Test HTML</p>',
|
|
389
|
+
},
|
|
390
|
+
},
|
|
391
|
+
},
|
|
392
|
+
},
|
|
393
|
+
},
|
|
394
|
+
},
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
// Should show Update button in edit flow
|
|
398
|
+
expect(screen.getByText('Update')).toBeInTheDocument();
|
|
399
|
+
});
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
describe('Error Handling', () => {
|
|
403
|
+
it('should handle missing props gracefully', () => {
|
|
404
|
+
expect(() => {
|
|
405
|
+
renderComponent({
|
|
406
|
+
intl: {
|
|
407
|
+
formatMessage: jest.fn((msg) => msg.defaultMessage || msg.id),
|
|
408
|
+
},
|
|
409
|
+
actions: mockActions,
|
|
410
|
+
globalActions: {
|
|
411
|
+
fetchSchemaForEntity: jest.fn(),
|
|
412
|
+
},
|
|
413
|
+
location: {
|
|
414
|
+
pathname: '/inapp/create',
|
|
415
|
+
query: { type: 'inapp' },
|
|
416
|
+
search: '',
|
|
417
|
+
},
|
|
418
|
+
});
|
|
419
|
+
}).not.toThrow();
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
it('should handle undefined beePopupBuilderToken gracefully', () => {
|
|
423
|
+
renderComponent({
|
|
424
|
+
...defaultProps,
|
|
425
|
+
beePopupBuilderToken: undefined,
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
expect(screen.getByText('Create')).toBeInTheDocument();
|
|
429
|
+
});
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
describe('Responsive Behavior', () => {
|
|
433
|
+
it('should apply correct CSS classes for different modes', () => {
|
|
434
|
+
const { container } = renderComponent(defaultProps);
|
|
435
|
+
|
|
436
|
+
expect(container.querySelector('.cap-inapp-creatives')).toBeInTheDocument();
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
it('should show footer with correct classes in library mode', () => {
|
|
440
|
+
const { container } = renderComponent({
|
|
441
|
+
...defaultProps,
|
|
442
|
+
isFullMode: false,
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
expect(container.querySelector('.inapp-footer-lib')).toBeInTheDocument();
|
|
446
|
+
});
|
|
447
|
+
});
|
|
448
|
+
});
|
|
@@ -2281,6 +2281,7 @@ new message content.",
|
|
|
2281
2281
|
"email": [Function],
|
|
2282
2282
|
"facebookPreview": [Function],
|
|
2283
2283
|
"gallery": [Function],
|
|
2284
|
+
"inApp": [Function],
|
|
2284
2285
|
"language": [Function],
|
|
2285
2286
|
"navigationConfig": [Function],
|
|
2286
2287
|
"previewAndTest": [Function],
|
|
@@ -5964,6 +5965,7 @@ new message content.",
|
|
|
5964
5965
|
"email": [Function],
|
|
5965
5966
|
"facebookPreview": [Function],
|
|
5966
5967
|
"gallery": [Function],
|
|
5968
|
+
"inApp": [Function],
|
|
5967
5969
|
"language": [Function],
|
|
5968
5970
|
"navigationConfig": [Function],
|
|
5969
5971
|
"previewAndTest": [Function],
|
|
@@ -9786,6 +9788,7 @@ new message content.",
|
|
|
9786
9788
|
"email": [Function],
|
|
9787
9789
|
"facebookPreview": [Function],
|
|
9788
9790
|
"gallery": [Function],
|
|
9791
|
+
"inApp": [Function],
|
|
9789
9792
|
"language": [Function],
|
|
9790
9793
|
"navigationConfig": [Function],
|
|
9791
9794
|
"previewAndTest": [Function],
|
|
@@ -2281,6 +2281,7 @@ new message content.",
|
|
|
2281
2281
|
"email": [Function],
|
|
2282
2282
|
"facebookPreview": [Function],
|
|
2283
2283
|
"gallery": [Function],
|
|
2284
|
+
"inApp": [Function],
|
|
2284
2285
|
"language": [Function],
|
|
2285
2286
|
"navigationConfig": [Function],
|
|
2286
2287
|
"previewAndTest": [Function],
|
|
@@ -21554,6 +21555,7 @@ new message content.",
|
|
|
21554
21555
|
"email": [Function],
|
|
21555
21556
|
"facebookPreview": [Function],
|
|
21556
21557
|
"gallery": [Function],
|
|
21558
|
+
"inApp": [Function],
|
|
21557
21559
|
"language": [Function],
|
|
21558
21560
|
"navigationConfig": [Function],
|
|
21559
21561
|
"previewAndTest": [Function],
|
|
@@ -2281,6 +2281,7 @@ new message content.",
|
|
|
2281
2281
|
"email": [Function],
|
|
2282
2282
|
"facebookPreview": [Function],
|
|
2283
2283
|
"gallery": [Function],
|
|
2284
|
+
"inApp": [Function],
|
|
2284
2285
|
"language": [Function],
|
|
2285
2286
|
"navigationConfig": [Function],
|
|
2286
2287
|
"previewAndTest": [Function],
|
|
@@ -34885,6 +34886,7 @@ new message content.",
|
|
|
34885
34886
|
"email": [Function],
|
|
34886
34887
|
"facebookPreview": [Function],
|
|
34887
34888
|
"gallery": [Function],
|
|
34889
|
+
"inApp": [Function],
|
|
34888
34890
|
"language": [Function],
|
|
34889
34891
|
"navigationConfig": [Function],
|
|
34890
34892
|
"previewAndTest": [Function],
|
|
@@ -2281,6 +2281,7 @@ new message content.",
|
|
|
2281
2281
|
"email": [Function],
|
|
2282
2282
|
"facebookPreview": [Function],
|
|
2283
2283
|
"gallery": [Function],
|
|
2284
|
+
"inApp": [Function],
|
|
2284
2285
|
"language": [Function],
|
|
2285
2286
|
"navigationConfig": [Function],
|
|
2286
2287
|
"previewAndTest": [Function],
|
|
@@ -11299,6 +11300,7 @@ new message content.",
|
|
|
11299
11300
|
"email": [Function],
|
|
11300
11301
|
"facebookPreview": [Function],
|
|
11301
11302
|
"gallery": [Function],
|
|
11303
|
+
"inApp": [Function],
|
|
11302
11304
|
"language": [Function],
|
|
11303
11305
|
"navigationConfig": [Function],
|
|
11304
11306
|
"previewAndTest": [Function],
|
|
@@ -20501,6 +20503,7 @@ new message content.",
|
|
|
20501
20503
|
"email": [Function],
|
|
20502
20504
|
"facebookPreview": [Function],
|
|
20503
20505
|
"gallery": [Function],
|
|
20506
|
+
"inApp": [Function],
|
|
20504
20507
|
"language": [Function],
|
|
20505
20508
|
"navigationConfig": [Function],
|
|
20506
20509
|
"previewAndTest": [Function],
|
|
@@ -29980,6 +29983,7 @@ new message content.",
|
|
|
29980
29983
|
"email": [Function],
|
|
29981
29984
|
"facebookPreview": [Function],
|
|
29982
29985
|
"gallery": [Function],
|
|
29986
|
+
"inApp": [Function],
|
|
29983
29987
|
"language": [Function],
|
|
29984
29988
|
"navigationConfig": [Function],
|
|
29985
29989
|
"previewAndTest": [Function],
|
|
@@ -41680,6 +41684,7 @@ new message content.",
|
|
|
41680
41684
|
"email": [Function],
|
|
41681
41685
|
"facebookPreview": [Function],
|
|
41682
41686
|
"gallery": [Function],
|
|
41687
|
+
"inApp": [Function],
|
|
41683
41688
|
"language": [Function],
|
|
41684
41689
|
"navigationConfig": [Function],
|
|
41685
41690
|
"previewAndTest": [Function],
|
|
@@ -53422,6 +53427,7 @@ new message content.",
|
|
|
53422
53427
|
"email": [Function],
|
|
53423
53428
|
"facebookPreview": [Function],
|
|
53424
53429
|
"gallery": [Function],
|
|
53430
|
+
"inApp": [Function],
|
|
53425
53431
|
"language": [Function],
|
|
53426
53432
|
"navigationConfig": [Function],
|
|
53427
53433
|
"previewAndTest": [Function],
|
|
@@ -61214,6 +61220,7 @@ new message content.",
|
|
|
61214
61220
|
"email": [Function],
|
|
61215
61221
|
"facebookPreview": [Function],
|
|
61216
61222
|
"gallery": [Function],
|
|
61223
|
+
"inApp": [Function],
|
|
61217
61224
|
"language": [Function],
|
|
61218
61225
|
"navigationConfig": [Function],
|
|
61219
61226
|
"previewAndTest": [Function],
|
|
@@ -69424,6 +69431,7 @@ new message content.",
|
|
|
69424
69431
|
"email": [Function],
|
|
69425
69432
|
"facebookPreview": [Function],
|
|
69426
69433
|
"gallery": [Function],
|
|
69434
|
+
"inApp": [Function],
|
|
69427
69435
|
"language": [Function],
|
|
69428
69436
|
"navigationConfig": [Function],
|
|
69429
69437
|
"previewAndTest": [Function],
|
|
@@ -77911,6 +77919,7 @@ new message content.",
|
|
|
77911
77919
|
"email": [Function],
|
|
77912
77920
|
"facebookPreview": [Function],
|
|
77913
77921
|
"gallery": [Function],
|
|
77922
|
+
"inApp": [Function],
|
|
77914
77923
|
"language": [Function],
|
|
77915
77924
|
"navigationConfig": [Function],
|
|
77916
77925
|
"previewAndTest": [Function],
|
|
@@ -114,7 +114,7 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
|
|
|
114
114
|
if (nextProps.iosCtasData && isEmpty(this.state.templateCta)) {
|
|
115
115
|
this.setState({showIosCtaTable: true});
|
|
116
116
|
}
|
|
117
|
-
if (nextProps.metaEntities && nextProps.metaEntities.layouts && nextProps.metaEntities.layouts.length > 0 && isEmpty(this.state.schema)) {
|
|
117
|
+
if (nextProps.metaEntities && nextProps.metaEntities.layouts && nextProps.metaEntities.layouts.length > 0 && isEmpty(this.state.schema) && isEmpty(this.state.formData)) {
|
|
118
118
|
const schema = this.props.params.mode === "text" ? nextProps.metaEntities.layouts[0].definition.textSchema : nextProps.metaEntities.layouts[0].definition.imageSchema;
|
|
119
119
|
const isAndroidSupported = get(this, "props.Templates.selectedWeChatAccount.configs.android") === '1';
|
|
120
120
|
const isIosSupported = get(this, "props.Templates.selectedWeChatAccount.configs.ios") === '1';
|
|
@@ -167,8 +167,8 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
167
167
|
};
|
|
168
168
|
this.props.actions.getMobilepushTemplatesList('mobilepush', params);
|
|
169
169
|
}
|
|
170
|
-
if (nextProps.metaEntities && nextProps.metaEntities.layouts && nextProps.metaEntities.layouts.length > 0 && _.isEmpty(this.state.fullSchema)) {
|
|
171
|
-
this.setState({fullSchema: nextProps.metaEntities.layouts[0].definition, schema: (nextProps.location.query.module === 'loyalty') ? nextProps.metaEntities.layouts[0].definition.textSchema : {}}, () => {
|
|
170
|
+
if (nextProps.metaEntities && nextProps.metaEntities.layouts && nextProps.metaEntities.layouts.length > 0 && _.isEmpty(this.state.fullSchema) && _.isEmpty(this.state.formData)) {
|
|
171
|
+
this.setState({ fullSchema: nextProps.metaEntities.layouts[0].definition, schema: (nextProps.location.query.module === 'loyalty') ? nextProps.metaEntities.layouts[0].definition.textSchema : {} }, () => {
|
|
172
172
|
this.handleEditSchemaOnPropsChange(nextProps, selectedWeChatAccount);
|
|
173
173
|
const templateId = get(this, "props.params.id");
|
|
174
174
|
if (nextProps.location.query.module !== 'loyalty' && templateId && templateId !== 'temp') {
|
|
@@ -388,11 +388,11 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
388
388
|
}
|
|
389
389
|
});
|
|
390
390
|
} else {
|
|
391
|
-
selectedAccount = accounts[0];
|
|
391
|
+
selectedAccount = accounts?.[0];
|
|
392
392
|
formData['mobilepush-accounts'] = selectedAccount?.id;
|
|
393
393
|
}
|
|
394
394
|
this.props.actions.setWeChatAccount(selectedAccount);
|
|
395
|
-
this.setState({formData, accountsOptions: accounts
|
|
395
|
+
this.setState({ formData, accountsOptions: accounts?.map((acc) => ({ key: acc.id, label: acc.name, value: acc.id })) });
|
|
396
396
|
};
|
|
397
397
|
|
|
398
398
|
createDefinition = (account) => ({
|
|
@@ -2018,12 +2018,16 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2018
2018
|
if (this.props.supportedTags) {
|
|
2019
2019
|
tags = this.props.supportedTags;
|
|
2020
2020
|
}
|
|
2021
|
+
if (this.props.supportedTags) {
|
|
2022
|
+
tags = this.props.supportedTags;
|
|
2023
|
+
}
|
|
2021
2024
|
return (
|
|
2022
2025
|
<div className="creatives-mobilepush-edit mobilepush-wrapper">
|
|
2023
2026
|
<CapSpin spinning={spinning}>
|
|
2024
2027
|
<CapRow>
|
|
2025
2028
|
<CapColumn>
|
|
2026
|
-
|
|
2029
|
+
<FormBuilder
|
|
2030
|
+
key={!_.isEmpty(schema) ? 'has-schema' : 'no-schema'}
|
|
2027
2031
|
channel={MOBILE_PUSH}
|
|
2028
2032
|
schema={schema}
|
|
2029
2033
|
showLiquidErrorInFooter={this.props.showLiquidErrorInFooter}
|
|
@@ -2058,7 +2062,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2058
2062
|
hideTestAndPreviewBtn={this.props.hideTestAndPreviewBtn}
|
|
2059
2063
|
isFullMode={this.props.isFullMode}
|
|
2060
2064
|
eventContextTags={this.props?.eventContextTags}
|
|
2061
|
-
/>
|
|
2065
|
+
/>
|
|
2062
2066
|
</CapColumn>
|
|
2063
2067
|
{this.props.iosCtasData && this.state.showIosCtaTable &&
|
|
2064
2068
|
<CapSlideBox
|