@capillarytech/creatives-library 8.0.316-alpha.4 → 8.0.317-alpha.0
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 +1 -0
- package/package.json +1 -1
- package/services/api.js +6 -0
- package/services/tests/api.test.js +7 -0
- package/utils/common.js +6 -1
- package/utils/tests/tagValidations.test.js +34 -0
- package/v2Components/CapTagList/index.js +15 -22
- package/v2Components/CapTagList/style.scss +48 -0
- package/v2Components/CapTagListWithInput/__tests__/CapTagListWithInput.test.js +63 -0
- package/v2Components/CapTagListWithInput/index.js +4 -0
- package/v2Components/CapWhatsappCTA/index.js +2 -0
- package/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +180 -0
- package/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +96 -0
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +99 -0
- package/v2Components/CommonTestAndPreview/tests/index.test.js +113 -3
- package/v2Components/FormBuilder/index.js +7 -0
- package/v2Components/HtmlEditor/HTMLEditor.js +6 -1
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +1 -0
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +927 -2
- package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +3 -0
- package/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +95 -0
- package/v2Containers/BeeEditor/index.js +3 -0
- package/v2Containers/CommunicationFlow/CommunicationFlow.js +291 -0
- package/v2Containers/CommunicationFlow/CommunicationFlow.scss +25 -0
- package/v2Containers/CommunicationFlow/Tests/CommunicationFlow.test.js +255 -0
- package/v2Containers/CommunicationFlow/constants.js +200 -0
- package/v2Containers/CommunicationFlow/index.js +102 -0
- package/v2Containers/CommunicationFlow/messages.js +346 -0
- package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.js +522 -0
- package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.scss +170 -0
- package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/Tests/ChannelSelectionStep.test.js +796 -0
- package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/index.js +5 -0
- package/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/CommunicationStrategyStep.js +95 -0
- package/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/Tests/CommunicationStrategyStep.test.js +133 -0
- package/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/index.js +5 -0
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/DeliverySettingsSection.js +289 -0
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/DeliverySettingsSection.scss +70 -0
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/SenderDetails.js +319 -0
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/SenderDetails.scss +69 -0
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/DeliverySettingsSection.test.js +616 -0
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/SenderDetails.test.js +577 -0
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/deliverySettingsConfig.test.js +1111 -0
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/deliverySettingsConfig.js +696 -0
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/index.js +7 -0
- package/v2Containers/CommunicationFlow/steps/DynamicControlsStep/DynamicControlsStep.js +102 -0
- package/v2Containers/CommunicationFlow/steps/DynamicControlsStep/DynamicControlsStep.scss +36 -0
- package/v2Containers/CommunicationFlow/steps/DynamicControlsStep/Tests/DynamicControlsStep.test.js +91 -0
- package/v2Containers/CommunicationFlow/steps/DynamicControlsStep/index.js +5 -0
- package/v2Containers/CommunicationFlow/steps/MessageTypeStep/MessageTypeStep.js +86 -0
- package/v2Containers/CommunicationFlow/steps/MessageTypeStep/Tests/MessageTypeStep.test.js +100 -0
- package/v2Containers/CommunicationFlow/steps/MessageTypeStep/index.js +5 -0
- package/v2Containers/CommunicationFlow/utils/getEnabledSteps.js +30 -0
- package/v2Containers/CreativesContainer/SlideBoxContent.js +28 -1
- package/v2Containers/CreativesContainer/constants.js +3 -0
- package/v2Containers/CreativesContainer/index.js +3 -0
- package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +104 -0
- package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +110 -0
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +363 -0
- package/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +258 -0
- package/v2Containers/Email/index.js +1 -0
- package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +7 -1
- package/v2Containers/EmailWrapper/components/EmailWrapperView.js +3 -0
- package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +20 -2
- package/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +16 -1
- package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +3 -0
- package/v2Containers/EmailWrapper/index.js +4 -0
- package/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +1 -0
- package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +9 -0
- package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +19 -0
- package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +3 -0
- package/v2Containers/InAppWrapper/index.js +3 -0
- package/v2Containers/MobilePush/Create/index.js +2 -0
- package/v2Containers/MobilePush/Edit/index.js +2 -0
- package/v2Containers/MobilepushWrapper/index.js +3 -1
- package/v2Containers/Rcs/index.js +1 -0
- package/v2Containers/Sms/Create/index.js +2 -0
- package/v2Containers/Sms/Edit/index.js +2 -0
- package/v2Containers/Sms/tests/smsFormDataHelpers.test.js +253 -0
- package/v2Containers/SmsTrai/Edit/index.js +2 -0
- package/v2Containers/SmsWrapper/index.js +2 -0
- package/v2Containers/TagList/index.js +41 -2
- package/v2Containers/TagList/messages.js +4 -0
- package/v2Containers/TagList/tests/TagList.test.js +122 -20
- package/v2Containers/TagList/tests/mockdata.js +17 -0
- package/v2Containers/Templates/tests/sagas.test.js +83 -0
- package/v2Containers/Viber/index.js +5 -0
- package/v2Containers/WebPush/Create/hooks/useTagManagement.js +0 -2
- package/v2Containers/WebPush/Create/index.js +9 -1
- package/v2Containers/Whatsapp/index.js +5 -0
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +20 -0
- package/v2Containers/Zalo/index.js +2 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CAP_SPACE_32,
|
|
3
|
+
CAP_SPACE_56,
|
|
4
|
+
CAP_SPACE_64,
|
|
5
|
+
} from '@capillarytech/cap-ui-library/styled/variables';
|
|
6
|
+
import {
|
|
7
|
+
isDeepEmpty,
|
|
8
|
+
getSlideBoxWrapperMarginFromLiquidErrors,
|
|
9
|
+
computeLiquidFooterUpdateFromFormBuilder,
|
|
10
|
+
} from '../embeddedSlideboxUtils';
|
|
11
|
+
import { ANDROID, IOS, MOBILE_PUSH, LIQUID_ERROR_MSG, STANDARD_ERROR_MSG } from '../constants';
|
|
12
|
+
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// isDeepEmpty
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
|
|
17
|
+
describe('isDeepEmpty', () => {
|
|
18
|
+
it('returns true for null', () => {
|
|
19
|
+
expect(isDeepEmpty(null)).toBe(true);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('returns true for undefined', () => {
|
|
23
|
+
expect(isDeepEmpty(undefined)).toBe(true);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('returns true for empty string', () => {
|
|
27
|
+
expect(isDeepEmpty('')).toBe(true);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('returns false for non-empty string', () => {
|
|
31
|
+
expect(isDeepEmpty('hello')).toBe(false);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('returns true for empty array', () => {
|
|
35
|
+
expect(isDeepEmpty([])).toBe(true);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('returns false for non-empty array', () => {
|
|
39
|
+
expect(isDeepEmpty(['item'])).toBe(false);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('returns true for empty object', () => {
|
|
43
|
+
expect(isDeepEmpty({})).toBe(true);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('returns true for object where all values are deep-empty', () => {
|
|
47
|
+
expect(isDeepEmpty({ a: null, b: '', c: [] })).toBe(true);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('returns false for object with at least one non-empty value', () => {
|
|
51
|
+
expect(isDeepEmpty({ a: null, b: 'something' })).toBe(false);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('returns true for nested all-empty object', () => {
|
|
55
|
+
expect(isDeepEmpty({ a: { b: null, c: [] } })).toBe(true);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('returns false for nested object with a non-empty leaf', () => {
|
|
59
|
+
expect(isDeepEmpty({ a: { b: 'value' } })).toBe(false);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('returns false for a number (non-null, non-string, non-array, non-object)', () => {
|
|
63
|
+
expect(isDeepEmpty(0)).toBe(false);
|
|
64
|
+
expect(isDeepEmpty(42)).toBe(false);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('returns false for a boolean false', () => {
|
|
68
|
+
expect(isDeepEmpty(false)).toBe(false);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
// getSlideBoxWrapperMarginFromLiquidErrors
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
|
|
76
|
+
describe('getSlideBoxWrapperMarginFromLiquidErrors', () => {
|
|
77
|
+
it('returns 0 when liquidErrorMessage is null', () => {
|
|
78
|
+
expect(getSlideBoxWrapperMarginFromLiquidErrors(null)).toBe(0);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('returns 0 when liquidErrorMessage is undefined', () => {
|
|
82
|
+
expect(getSlideBoxWrapperMarginFromLiquidErrors(undefined)).toBe(0);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('returns 0 when both error arrays are empty', () => {
|
|
86
|
+
expect(getSlideBoxWrapperMarginFromLiquidErrors({
|
|
87
|
+
STANDARD_ERROR_MSG: [],
|
|
88
|
+
LIQUID_ERROR_MSG: [],
|
|
89
|
+
})).toBe(0);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('returns 0 when neither error array is present', () => {
|
|
93
|
+
expect(getSlideBoxWrapperMarginFromLiquidErrors({})).toBe(0);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('returns CAP_SPACE_64 when both STANDARD and LIQUID errors are present', () => {
|
|
97
|
+
expect(getSlideBoxWrapperMarginFromLiquidErrors({
|
|
98
|
+
STANDARD_ERROR_MSG: ['std error'],
|
|
99
|
+
LIQUID_ERROR_MSG: ['liquid error'],
|
|
100
|
+
})).toBe(CAP_SPACE_64);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('returns CAP_SPACE_56 when only LIQUID errors are present', () => {
|
|
104
|
+
expect(getSlideBoxWrapperMarginFromLiquidErrors({
|
|
105
|
+
STANDARD_ERROR_MSG: [],
|
|
106
|
+
LIQUID_ERROR_MSG: ['liquid error'],
|
|
107
|
+
})).toBe(CAP_SPACE_56);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('returns CAP_SPACE_32 when only STANDARD errors are present', () => {
|
|
111
|
+
expect(getSlideBoxWrapperMarginFromLiquidErrors({
|
|
112
|
+
STANDARD_ERROR_MSG: ['std error'],
|
|
113
|
+
LIQUID_ERROR_MSG: [],
|
|
114
|
+
})).toBe(CAP_SPACE_32);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('returns CAP_SPACE_56 when LIQUID has multiple errors and STANDARD is absent', () => {
|
|
118
|
+
expect(getSlideBoxWrapperMarginFromLiquidErrors({
|
|
119
|
+
LIQUID_ERROR_MSG: ['err1', 'err2'],
|
|
120
|
+
})).toBe(CAP_SPACE_56);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('returns CAP_SPACE_32 when STANDARD has multiple errors and LIQUID is absent', () => {
|
|
124
|
+
expect(getSlideBoxWrapperMarginFromLiquidErrors({
|
|
125
|
+
STANDARD_ERROR_MSG: ['err1', 'err2'],
|
|
126
|
+
})).toBe(CAP_SPACE_32);
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// ---------------------------------------------------------------------------
|
|
131
|
+
// computeLiquidFooterUpdateFromFormBuilder
|
|
132
|
+
// ---------------------------------------------------------------------------
|
|
133
|
+
|
|
134
|
+
describe('computeLiquidFooterUpdateFromFormBuilder', () => {
|
|
135
|
+
const noErrors = { [LIQUID_ERROR_MSG]: [], [STANDARD_ERROR_MSG]: [] };
|
|
136
|
+
const liquidOnly = { [LIQUID_ERROR_MSG]: ['liquid err'], [STANDARD_ERROR_MSG]: [] };
|
|
137
|
+
const standardOnly = { [LIQUID_ERROR_MSG]: [], [STANDARD_ERROR_MSG]: ['std err'] };
|
|
138
|
+
const bothErrors = { [LIQUID_ERROR_MSG]: ['l'], [STANDARD_ERROR_MSG]: ['s'] };
|
|
139
|
+
|
|
140
|
+
describe('normal (non-null) returns', () => {
|
|
141
|
+
it('returns isLiquidValidationError=false when no errors', () => {
|
|
142
|
+
const result = computeLiquidFooterUpdateFromFormBuilder(noErrors, 1, {
|
|
143
|
+
previousIsLiquidValidationError: false,
|
|
144
|
+
currentChannelUpper: 'SMS',
|
|
145
|
+
});
|
|
146
|
+
expect(result).not.toBeNull();
|
|
147
|
+
expect(result.isLiquidValidationError).toBe(false);
|
|
148
|
+
expect(result.liquidErrorMessage).toEqual(noErrors);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('sets isLiquidValidationError=true when liquid errors present', () => {
|
|
152
|
+
const result = computeLiquidFooterUpdateFromFormBuilder(liquidOnly, 1, {
|
|
153
|
+
previousIsLiquidValidationError: false,
|
|
154
|
+
currentChannelUpper: 'SMS',
|
|
155
|
+
});
|
|
156
|
+
expect(result.isLiquidValidationError).toBe(true);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('sets isLiquidValidationError=true when standard errors present', () => {
|
|
160
|
+
const result = computeLiquidFooterUpdateFromFormBuilder(standardOnly, 1, {
|
|
161
|
+
previousIsLiquidValidationError: false,
|
|
162
|
+
currentChannelUpper: 'SMS',
|
|
163
|
+
});
|
|
164
|
+
expect(result.isLiquidValidationError).toBe(true);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('sets isLiquidValidationError=true when both errors present', () => {
|
|
168
|
+
const result = computeLiquidFooterUpdateFromFormBuilder(bothErrors, 1, {
|
|
169
|
+
previousIsLiquidValidationError: false,
|
|
170
|
+
currentChannelUpper: 'SMS',
|
|
171
|
+
});
|
|
172
|
+
expect(result.isLiquidValidationError).toBe(true);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it('maps tab 1 to ANDROID', () => {
|
|
176
|
+
const result = computeLiquidFooterUpdateFromFormBuilder(noErrors, 1, {
|
|
177
|
+
previousIsLiquidValidationError: false,
|
|
178
|
+
currentChannelUpper: 'SMS',
|
|
179
|
+
});
|
|
180
|
+
expect(result.activeFormBuilderTab).toBe(ANDROID);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('maps tab 2 to IOS', () => {
|
|
184
|
+
const result = computeLiquidFooterUpdateFromFormBuilder(noErrors, 2, {
|
|
185
|
+
previousIsLiquidValidationError: false,
|
|
186
|
+
currentChannelUpper: 'SMS',
|
|
187
|
+
});
|
|
188
|
+
expect(result.activeFormBuilderTab).toBe(IOS);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it('maps tab 3 (or any other tab) to null', () => {
|
|
192
|
+
const result = computeLiquidFooterUpdateFromFormBuilder(noErrors, 3, {
|
|
193
|
+
previousIsLiquidValidationError: false,
|
|
194
|
+
currentChannelUpper: 'SMS',
|
|
195
|
+
});
|
|
196
|
+
expect(result.activeFormBuilderTab).toBeNull();
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('maps undefined tab to null for activeFormBuilderTab', () => {
|
|
200
|
+
const result = computeLiquidFooterUpdateFromFormBuilder(noErrors, undefined, {
|
|
201
|
+
previousIsLiquidValidationError: false,
|
|
202
|
+
currentChannelUpper: 'SMS',
|
|
203
|
+
});
|
|
204
|
+
expect(result.activeFormBuilderTab).toBeNull();
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it('does NOT return null for Mobile Push when errors ARE present', () => {
|
|
208
|
+
const result = computeLiquidFooterUpdateFromFormBuilder(liquidOnly, 1, {
|
|
209
|
+
previousIsLiquidValidationError: true,
|
|
210
|
+
currentChannelUpper: MOBILE_PUSH,
|
|
211
|
+
});
|
|
212
|
+
expect(result).not.toBeNull();
|
|
213
|
+
expect(result.isLiquidValidationError).toBe(true);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it('does NOT return null for non-Mobile Push channel even with previousIsLiquidValidationError', () => {
|
|
217
|
+
const result = computeLiquidFooterUpdateFromFormBuilder(noErrors, 1, {
|
|
218
|
+
previousIsLiquidValidationError: true,
|
|
219
|
+
currentChannelUpper: 'SMS',
|
|
220
|
+
});
|
|
221
|
+
expect(result).not.toBeNull();
|
|
222
|
+
expect(result.isLiquidValidationError).toBe(false);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it('works without options argument (uses defaults)', () => {
|
|
226
|
+
const result = computeLiquidFooterUpdateFromFormBuilder(noErrors, 1);
|
|
227
|
+
expect(result).not.toBeNull();
|
|
228
|
+
expect(result.isLiquidValidationError).toBe(false);
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
describe('Mobile Push OLD clear (returns null)', () => {
|
|
233
|
+
it('returns null when no errors and previousIsLiquidValidationError is true for MOBILEPUSH', () => {
|
|
234
|
+
const result = computeLiquidFooterUpdateFromFormBuilder(noErrors, 1, {
|
|
235
|
+
previousIsLiquidValidationError: true,
|
|
236
|
+
currentChannelUpper: MOBILE_PUSH,
|
|
237
|
+
});
|
|
238
|
+
expect(result).toBeNull();
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it('does NOT return null when previousIsLiquidValidationError is false for MOBILEPUSH', () => {
|
|
242
|
+
const result = computeLiquidFooterUpdateFromFormBuilder(noErrors, 1, {
|
|
243
|
+
previousIsLiquidValidationError: false,
|
|
244
|
+
currentChannelUpper: MOBILE_PUSH,
|
|
245
|
+
});
|
|
246
|
+
expect(result).not.toBeNull();
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it('does NOT return null when only standard errors cleared but liquid error remains for MOBILEPUSH', () => {
|
|
250
|
+
const result = computeLiquidFooterUpdateFromFormBuilder(liquidOnly, 1, {
|
|
251
|
+
previousIsLiquidValidationError: true,
|
|
252
|
+
currentChannelUpper: MOBILE_PUSH,
|
|
253
|
+
});
|
|
254
|
+
// hasLiquid = true → condition !hasLiquid is false → does not return null
|
|
255
|
+
expect(result).not.toBeNull();
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
});
|
|
@@ -3134,6 +3134,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
3134
3134
|
moduleType={moduleType}
|
|
3135
3135
|
showLiquidErrorInFooter={this.props.showLiquidErrorInFooter}
|
|
3136
3136
|
eventContextTags={this.props?.eventContextTags}
|
|
3137
|
+
waitEventContextTags={this.props?.waitEventContextTags}
|
|
3137
3138
|
forwardedTags={this.props?.forwardedTags}
|
|
3138
3139
|
isLoyaltyModule={this.props?.isLoyaltyModule}
|
|
3139
3140
|
isTestAndPreviewMode={this.state.isTestAndPreviewMode} // Add flag to prevent validation
|
|
@@ -54,6 +54,7 @@ const EmailHTMLEditor = (props) => {
|
|
|
54
54
|
globalActions,
|
|
55
55
|
loadingTags,
|
|
56
56
|
eventContextTags,
|
|
57
|
+
waitEventContextTags,
|
|
57
58
|
forwardedTags,
|
|
58
59
|
selectedOfferDetails,
|
|
59
60
|
currentOrgDetails,
|
|
@@ -502,6 +503,7 @@ const EmailHTMLEditor = (props) => {
|
|
|
502
503
|
location,
|
|
503
504
|
tagModule: getDefaultTags,
|
|
504
505
|
isFullMode,
|
|
506
|
+
waitEventContextTags,
|
|
505
507
|
});
|
|
506
508
|
|
|
507
509
|
if (!validationResult.valid) {
|
|
@@ -510,7 +512,7 @@ const EmailHTMLEditor = (props) => {
|
|
|
510
512
|
setTagValidationError(null);
|
|
511
513
|
}
|
|
512
514
|
}
|
|
513
|
-
}, [tags, injectedTags, location, getDefaultTags, eventContextTags, showLiquidErrorInFooter]);
|
|
515
|
+
}, [tags, injectedTags, location, getDefaultTags, eventContextTags, waitEventContextTags, showLiquidErrorInFooter]);
|
|
514
516
|
|
|
515
517
|
// Store the last validation state received from HTMLEditor
|
|
516
518
|
const lastValidationStateRef = useRef(null);
|
|
@@ -1100,6 +1102,7 @@ const EmailHTMLEditor = (props) => {
|
|
|
1100
1102
|
injectedTags={injectedTags || {}}
|
|
1101
1103
|
selectedOfferDetails={selectedOfferDetails}
|
|
1102
1104
|
eventContextTags={eventContextTags}
|
|
1105
|
+
waitEventContextTags={waitEventContextTags}
|
|
1103
1106
|
showHeading
|
|
1104
1107
|
showTagList
|
|
1105
1108
|
showInput
|
|
@@ -1124,6 +1127,7 @@ const EmailHTMLEditor = (props) => {
|
|
|
1124
1127
|
injectedTags={injectedTags}
|
|
1125
1128
|
location={location}
|
|
1126
1129
|
eventContextTags={eventContextTags}
|
|
1130
|
+
waitEventContextTags={waitEventContextTags}
|
|
1127
1131
|
selectedOfferDetails={selectedOfferDetails}
|
|
1128
1132
|
channel={EMAIL}
|
|
1129
1133
|
userLocale={intl.locale || 'en'}
|
|
@@ -1151,6 +1155,7 @@ EmailHTMLEditor.propTypes = {
|
|
|
1151
1155
|
globalActions: PropTypes.object,
|
|
1152
1156
|
loadingTags: PropTypes.bool,
|
|
1153
1157
|
eventContextTags: PropTypes.array,
|
|
1158
|
+
waitEventContextTags: PropTypes.object,
|
|
1154
1159
|
forwardedTags: PropTypes.object,
|
|
1155
1160
|
selectedOfferDetails: PropTypes.array,
|
|
1156
1161
|
currentOrgDetails: PropTypes.object,
|
|
@@ -1197,6 +1202,7 @@ EmailHTMLEditor.defaultProps = {
|
|
|
1197
1202
|
globalActions: {},
|
|
1198
1203
|
loadingTags: false,
|
|
1199
1204
|
eventContextTags: [],
|
|
1205
|
+
waitEventContextTags: {},
|
|
1200
1206
|
forwardedTags: {},
|
|
1201
1207
|
selectedOfferDetails: [],
|
|
1202
1208
|
currentOrgDetails: {},
|
|
@@ -173,6 +173,7 @@ const EmailWrapperView = ({
|
|
|
173
173
|
forwardedTags,
|
|
174
174
|
selectedOfferDetails,
|
|
175
175
|
eventContextTags,
|
|
176
|
+
waitEventContextTags,
|
|
176
177
|
getFormdata,
|
|
177
178
|
isGetFormData,
|
|
178
179
|
getLiquidTags,
|
|
@@ -246,6 +247,7 @@ const EmailWrapperView = ({
|
|
|
246
247
|
globalActions,
|
|
247
248
|
loadingTags,
|
|
248
249
|
eventContextTags,
|
|
250
|
+
waitEventContextTags,
|
|
249
251
|
forwardedTags,
|
|
250
252
|
selectedOfferDetails,
|
|
251
253
|
currentOrgDetails,
|
|
@@ -371,6 +373,7 @@ EmailWrapperView.propTypes = {
|
|
|
371
373
|
forwardedTags: PropTypes.object,
|
|
372
374
|
selectedOfferDetails: PropTypes.array,
|
|
373
375
|
eventContextTags: PropTypes.array,
|
|
376
|
+
waitEventContextTags: PropTypes.object,
|
|
374
377
|
emailActions: PropTypes.object,
|
|
375
378
|
Email: PropTypes.object,
|
|
376
379
|
templateData: PropTypes.object,
|
|
@@ -71,7 +71,10 @@ jest.mock('../../../../v2Components/HtmlEditor/index.lazy', () => {
|
|
|
71
71
|
}));
|
|
72
72
|
|
|
73
73
|
return (
|
|
74
|
-
<div
|
|
74
|
+
<div
|
|
75
|
+
data-testid="html-editor"
|
|
76
|
+
data-wait-event-context-tags={JSON.stringify(props.waitEventContextTags ?? null)}
|
|
77
|
+
>
|
|
75
78
|
<button
|
|
76
79
|
onClick={() => props.onContentChange && props.onContentChange('<p>New content</p>')}
|
|
77
80
|
data-testid="trigger-content-change"
|
|
@@ -130,7 +133,10 @@ jest.mock('../../../../v2Components/HtmlEditor', () => {
|
|
|
130
133
|
}));
|
|
131
134
|
|
|
132
135
|
return (
|
|
133
|
-
<div
|
|
136
|
+
<div
|
|
137
|
+
data-testid="html-editor"
|
|
138
|
+
data-wait-event-context-tags={JSON.stringify(props.waitEventContextTags ?? null)}
|
|
139
|
+
>
|
|
134
140
|
<button
|
|
135
141
|
onClick={() => props.onContentChange && props.onContentChange('<p>New content</p>')}
|
|
136
142
|
data-testid="trigger-content-change"
|
|
@@ -364,6 +370,7 @@ const defaultProps = {
|
|
|
364
370
|
},
|
|
365
371
|
loadingTags: false,
|
|
366
372
|
eventContextTags: [],
|
|
373
|
+
waitEventContextTags: {},
|
|
367
374
|
forwardedTags: {},
|
|
368
375
|
selectedOfferDetails: [],
|
|
369
376
|
currentOrgDetails: {
|
|
@@ -522,6 +529,17 @@ describe('EmailHTMLEditor', () => {
|
|
|
522
529
|
});
|
|
523
530
|
});
|
|
524
531
|
|
|
532
|
+
describe('waitEventContextTags', () => {
|
|
533
|
+
it('forwards waitEventContextTags to HTMLEditor', () => {
|
|
534
|
+
const waitMap = { b1: { eventName: 'E', blockName: 'B', tags: ['t'] } };
|
|
535
|
+
renderWithIntl({ waitEventContextTags: waitMap });
|
|
536
|
+
expect(screen.getByTestId('html-editor')).toHaveAttribute(
|
|
537
|
+
'data-wait-event-context-tags',
|
|
538
|
+
JSON.stringify(waitMap),
|
|
539
|
+
);
|
|
540
|
+
});
|
|
541
|
+
});
|
|
542
|
+
|
|
525
543
|
describe('Content Initialization', () => {
|
|
526
544
|
it('initializes with empty content in create mode', () => {
|
|
527
545
|
renderWithIntl({ isGetFormData: false });
|
|
@@ -37,7 +37,14 @@ jest.mock('../EmailHTMLEditor', () => {
|
|
|
37
37
|
getContentForPreview: jest.fn(() => '<p>Test</p>'),
|
|
38
38
|
}));
|
|
39
39
|
|
|
40
|
-
return
|
|
40
|
+
return (
|
|
41
|
+
<div
|
|
42
|
+
data-testid="email-html-editor"
|
|
43
|
+
data-wait-event-context-tags={JSON.stringify(props.waitEventContextTags ?? null)}
|
|
44
|
+
>
|
|
45
|
+
HTML Editor
|
|
46
|
+
</div>
|
|
47
|
+
);
|
|
41
48
|
});
|
|
42
49
|
});
|
|
43
50
|
|
|
@@ -137,6 +144,7 @@ const defaultProps = {
|
|
|
137
144
|
forwardedTags: {},
|
|
138
145
|
selectedOfferDetails: [],
|
|
139
146
|
eventContextTags: [],
|
|
147
|
+
waitEventContextTags: {},
|
|
140
148
|
getFormdata: jest.fn(),
|
|
141
149
|
isGetFormData: false,
|
|
142
150
|
getLiquidTags: jest.fn(),
|
|
@@ -171,6 +179,13 @@ describe('EmailWrapperView', () => {
|
|
|
171
179
|
jest.clearAllMocks();
|
|
172
180
|
});
|
|
173
181
|
|
|
182
|
+
it('passes waitEventContextTags to EmailHTMLEditor when HTML editor is shown', () => {
|
|
183
|
+
const waitMap = { b1: { eventName: 'E', blockName: 'B', tags: [] } };
|
|
184
|
+
renderWithIntl({ waitEventContextTags: waitMap });
|
|
185
|
+
const el = screen.getByTestId('email-html-editor');
|
|
186
|
+
expect(el).toHaveAttribute('data-wait-event-context-tags', JSON.stringify(waitMap));
|
|
187
|
+
});
|
|
188
|
+
|
|
174
189
|
describe('Mode Selection UI', () => {
|
|
175
190
|
it('renders mode selection when step is MODE_SELECTION', () => {
|
|
176
191
|
renderWithIntl({ step: STEPS.MODE_SELECTION });
|
|
@@ -51,6 +51,7 @@ const useEmailWrapper = ({
|
|
|
51
51
|
editor,
|
|
52
52
|
moduleType,
|
|
53
53
|
eventContextTags,
|
|
54
|
+
waitEventContextTags,
|
|
54
55
|
isLoyaltyModule,
|
|
55
56
|
// Props for CmsTemplates component
|
|
56
57
|
cmsTemplatesLoader,
|
|
@@ -737,6 +738,7 @@ const useEmailWrapper = ({
|
|
|
737
738
|
selectedEditorMode, // Pass selected mode to Email component (only for HTML_EDITOR)
|
|
738
739
|
moduleType,
|
|
739
740
|
eventContextTags,
|
|
741
|
+
waitEventContextTags,
|
|
740
742
|
isLoyaltyModule,
|
|
741
743
|
showTestAndPreviewSlidebox,
|
|
742
744
|
handleTestAndPreview,
|
|
@@ -766,6 +768,7 @@ const useEmailWrapper = ({
|
|
|
766
768
|
editor,
|
|
767
769
|
moduleType,
|
|
768
770
|
eventContextTags,
|
|
771
|
+
waitEventContextTags,
|
|
769
772
|
isLoyaltyModule,
|
|
770
773
|
showTestAndPreviewSlidebox,
|
|
771
774
|
handleTestAndPreview,
|
|
@@ -63,6 +63,7 @@ const EmailWrapper = (props) => {
|
|
|
63
63
|
onEnterTemplateName,
|
|
64
64
|
onRemoveTemplateName,
|
|
65
65
|
eventContextTags,
|
|
66
|
+
waitEventContextTags,
|
|
66
67
|
isLoyaltyModule,
|
|
67
68
|
cmsTemplatesLoader,
|
|
68
69
|
onPreviewContentClicked,
|
|
@@ -130,6 +131,7 @@ const EmailWrapper = (props) => {
|
|
|
130
131
|
onEnterTemplateName,
|
|
131
132
|
onRemoveTemplateName,
|
|
132
133
|
eventContextTags,
|
|
134
|
+
waitEventContextTags,
|
|
133
135
|
isLoyaltyModule,
|
|
134
136
|
cmsTemplatesLoader,
|
|
135
137
|
onPreviewContentClicked,
|
|
@@ -184,6 +186,7 @@ const EmailWrapper = (props) => {
|
|
|
184
186
|
forwardedTags={forwardedTags}
|
|
185
187
|
selectedOfferDetails={selectedOfferDetails}
|
|
186
188
|
eventContextTags={eventContextTags}
|
|
189
|
+
waitEventContextTags={waitEventContextTags}
|
|
187
190
|
getFormdata={getFormdata}
|
|
188
191
|
isGetFormData={isGetFormData}
|
|
189
192
|
getLiquidTags={globalActionsProp?.getLiquidTags}
|
|
@@ -241,6 +244,7 @@ EmailWrapper.propTypes = {
|
|
|
241
244
|
onEnterTemplateName: PropTypes.func,
|
|
242
245
|
onRemoveTemplateName: PropTypes.func,
|
|
243
246
|
eventContextTags: PropTypes.array,
|
|
247
|
+
waitEventContextTags: PropTypes.object,
|
|
244
248
|
isLoyaltyModule: PropTypes.bool,
|
|
245
249
|
onPreviewContentClicked: PropTypes.func,
|
|
246
250
|
onTestContentClicked: PropTypes.func,
|
|
@@ -102,6 +102,7 @@ describe('useEmailWrapper', () => {
|
|
|
102
102
|
editor: null,
|
|
103
103
|
moduleType: '',
|
|
104
104
|
eventContextTags: [],
|
|
105
|
+
waitEventContextTags: {},
|
|
105
106
|
isLoyaltyModule: false,
|
|
106
107
|
cmsTemplatesLoader: false,
|
|
107
108
|
currentOrgDetails: { id: 'org1' },
|
|
@@ -120,6 +121,14 @@ describe('useEmailWrapper', () => {
|
|
|
120
121
|
expect(result.current.onTemplateNameChange).toBeInstanceOf(Function);
|
|
121
122
|
});
|
|
122
123
|
|
|
124
|
+
it('passes waitEventContextTags through emailProps', () => {
|
|
125
|
+
const waitMap = { block1: { eventName: 'E', blockName: 'B', tags: [] } };
|
|
126
|
+
const { result } = renderHook(() =>
|
|
127
|
+
useEmailWrapper({ ...mockProps, waitEventContextTags: waitMap }),
|
|
128
|
+
);
|
|
129
|
+
expect(result.current.emailProps.waitEventContextTags).toEqual(waitMap);
|
|
130
|
+
});
|
|
131
|
+
|
|
123
132
|
it('handles template name change correctly', () => {
|
|
124
133
|
const { result } = renderHook(() => useEmailWrapper(mockProps));
|
|
125
134
|
|
|
@@ -78,6 +78,7 @@ describe('useInAppWrapper', () => {
|
|
|
78
78
|
onPreviewContentClicked: jest.fn(),
|
|
79
79
|
onTestContentClicked: jest.fn(),
|
|
80
80
|
eventContextTags: {},
|
|
81
|
+
waitEventContextTags: {},
|
|
81
82
|
onCreateComplete: jest.fn(),
|
|
82
83
|
handleClose: jest.fn(),
|
|
83
84
|
templateData: null,
|
|
@@ -424,6 +425,24 @@ describe('useInAppWrapper', () => {
|
|
|
424
425
|
|
|
425
426
|
expect(capturedState.inAppProps.getDefaultTags).toBe('defaultTags');
|
|
426
427
|
});
|
|
428
|
+
|
|
429
|
+
it('passes waitEventContextTags through to inAppProps', () => {
|
|
430
|
+
const waitMap = { block1: { eventName: 'E', blockName: 'B', tags: [] } };
|
|
431
|
+
let capturedState = null;
|
|
432
|
+
render(
|
|
433
|
+
<TestComponent
|
|
434
|
+
hookProps={{
|
|
435
|
+
...defaultHookProps,
|
|
436
|
+
waitEventContextTags: waitMap,
|
|
437
|
+
}}
|
|
438
|
+
onStateChange={(state) => {
|
|
439
|
+
capturedState = state;
|
|
440
|
+
}}
|
|
441
|
+
/>
|
|
442
|
+
);
|
|
443
|
+
|
|
444
|
+
expect(capturedState.inAppProps.waitEventContextTags).toEqual(waitMap);
|
|
445
|
+
});
|
|
427
446
|
});
|
|
428
447
|
|
|
429
448
|
describe('isShowInAppCreate', () => {
|
|
@@ -33,6 +33,7 @@ const useInAppWrapper = ({
|
|
|
33
33
|
onPreviewContentClicked,
|
|
34
34
|
onTestContentClicked,
|
|
35
35
|
eventContextTags,
|
|
36
|
+
waitEventContextTags,
|
|
36
37
|
onCreateComplete,
|
|
37
38
|
handleClose,
|
|
38
39
|
templateData,
|
|
@@ -149,6 +150,7 @@ const useInAppWrapper = ({
|
|
|
149
150
|
onPreviewContentClicked,
|
|
150
151
|
onTestContentClicked,
|
|
151
152
|
eventContextTags,
|
|
153
|
+
waitEventContextTags,
|
|
152
154
|
onCreateComplete,
|
|
153
155
|
handleClose,
|
|
154
156
|
};
|
|
@@ -173,6 +175,7 @@ const useInAppWrapper = ({
|
|
|
173
175
|
onPreviewContentClicked,
|
|
174
176
|
onTestContentClicked,
|
|
175
177
|
eventContextTags,
|
|
178
|
+
waitEventContextTags,
|
|
176
179
|
onCreateComplete,
|
|
177
180
|
handleClose,
|
|
178
181
|
]);
|
|
@@ -36,6 +36,7 @@ const InAppWrapper = (props) => {
|
|
|
36
36
|
onPreviewContentClicked,
|
|
37
37
|
onTestContentClicked,
|
|
38
38
|
eventContextTags,
|
|
39
|
+
waitEventContextTags,
|
|
39
40
|
onCreateComplete,
|
|
40
41
|
handleClose,
|
|
41
42
|
templateData,
|
|
@@ -78,6 +79,7 @@ const InAppWrapper = (props) => {
|
|
|
78
79
|
onPreviewContentClicked,
|
|
79
80
|
onTestContentClicked,
|
|
80
81
|
eventContextTags,
|
|
82
|
+
waitEventContextTags,
|
|
81
83
|
onCreateComplete,
|
|
82
84
|
handleClose,
|
|
83
85
|
templateData,
|
|
@@ -124,6 +126,7 @@ InAppWrapper.propTypes = {
|
|
|
124
126
|
onPreviewContentClicked: PropTypes.func,
|
|
125
127
|
onTestContentClicked: PropTypes.func,
|
|
126
128
|
eventContextTags: PropTypes.array,
|
|
129
|
+
waitEventContextTags: PropTypes.object,
|
|
127
130
|
onCreateComplete: PropTypes.func,
|
|
128
131
|
handleClose: PropTypes.func,
|
|
129
132
|
templateData: PropTypes.object,
|
|
@@ -1966,6 +1966,7 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
|
|
|
1966
1966
|
hideTestAndPreviewBtn={this.props.hideTestAndPreviewBtn}
|
|
1967
1967
|
isFullMode={this.props.isFullMode}
|
|
1968
1968
|
eventContextTags={this.props?.eventContextTags}
|
|
1969
|
+
waitEventContextTags={this.props?.waitEventContextTags}
|
|
1969
1970
|
messageDetails={this.props?.messageDetails}
|
|
1970
1971
|
restrictPersonalization={this.props.restrictPersonalization}
|
|
1971
1972
|
/>
|
|
@@ -2068,6 +2069,7 @@ Create.propTypes = {
|
|
|
2068
2069
|
onPreviewContentClicked: PropTypes.func,
|
|
2069
2070
|
onTestContentClicked: PropTypes.func,
|
|
2070
2071
|
eventContextTags: PropTypes.array,
|
|
2072
|
+
waitEventContextTags: PropTypes.object,
|
|
2071
2073
|
getLiquidTags: PropTypes.func,
|
|
2072
2074
|
showLiquidErrorInFooter: PropTypes.func,
|
|
2073
2075
|
showTestAndPreviewSlidebox: PropTypes.bool,
|
|
@@ -2233,6 +2233,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2233
2233
|
hideTestAndPreviewBtn={this.props.hideTestAndPreviewBtn}
|
|
2234
2234
|
isFullMode={this.props.isFullMode}
|
|
2235
2235
|
eventContextTags={this.props?.eventContextTags}
|
|
2236
|
+
waitEventContextTags={this.props?.waitEventContextTags}
|
|
2236
2237
|
restrictPersonalization={this.props.restrictPersonalization}
|
|
2237
2238
|
/>;
|
|
2238
2239
|
})()}
|
|
@@ -2339,6 +2340,7 @@ Edit.propTypes = {
|
|
|
2339
2340
|
onTestContentClicked: PropTypes.func,
|
|
2340
2341
|
creativesMode: PropTypes.string,
|
|
2341
2342
|
eventContextTags: PropTypes.array,
|
|
2343
|
+
waitEventContextTags: PropTypes.object,
|
|
2342
2344
|
getLiquidTags: PropTypes.func,
|
|
2343
2345
|
showLiquidErrorInFooter: PropTypes.func,
|
|
2344
2346
|
showTestAndPreviewSlidebox: PropTypes.bool,
|
|
@@ -72,7 +72,7 @@ export class MobilepushWrapper extends React.Component { // eslint-disable-line
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
render() {
|
|
75
|
-
const {mobilePushCreateMode, step, getFormData, getLiquidTags, setIsLoadingContent, isGetFormData, query, isFullMode, showTemplateName, type, onValidationFail, onPreviewContentClicked, onTestContentClicked, templateData, eventContextTags = [], showTestAndPreviewSlidebox, handleTestAndPreview, handleCloseTestAndPreview, restrictPersonalization, isAnonymousType, onPersonalizationTokensChange} = this.props;
|
|
75
|
+
const {mobilePushCreateMode, step, getFormData, getLiquidTags, setIsLoadingContent, isGetFormData, query, isFullMode, showTemplateName, type, onValidationFail, onPreviewContentClicked, onTestContentClicked, templateData, eventContextTags = [], waitEventContextTags = {},showTestAndPreviewSlidebox, handleTestAndPreview, handleCloseTestAndPreview, restrictPersonalization, isAnonymousType, onPersonalizationTokensChange} = this.props;
|
|
76
76
|
const {templateName} = this.state;
|
|
77
77
|
const isShowMobilepushCreate = !isEmpty(mobilePushCreateMode);
|
|
78
78
|
return (
|
|
@@ -121,6 +121,7 @@ export class MobilepushWrapper extends React.Component { // eslint-disable-line
|
|
|
121
121
|
templateData={templateData}
|
|
122
122
|
hideTestAndPreviewBtn={this.props.hideTestAndPreviewBtn}
|
|
123
123
|
eventContextTags={eventContextTags}
|
|
124
|
+
waitEventContextTags={waitEventContextTags}
|
|
124
125
|
showLiquidErrorInFooter={this.props.showLiquidErrorInFooter}
|
|
125
126
|
showTestAndPreviewSlidebox={showTestAndPreviewSlidebox}
|
|
126
127
|
handleTestAndPreview={handleTestAndPreview}
|
|
@@ -155,6 +156,7 @@ MobilepushWrapper.propTypes = {
|
|
|
155
156
|
type: PropTypes.string,
|
|
156
157
|
onValidationFail: PropTypes.func,
|
|
157
158
|
eventContextTags: PropTypes.array,
|
|
159
|
+
waitEventContextTags: PropTypes.object,
|
|
158
160
|
showLiquidErrorInFooter: PropTypes.func,
|
|
159
161
|
showTestAndPreviewSlidebox: PropTypes.bool,
|
|
160
162
|
handleTestAndPreview: PropTypes.func,
|