@capillarytech/creatives-library 8.0.285-alpha.1 → 8.0.286
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/initialState.js +2 -0
- package/package.json +1 -1
- package/utils/common.js +8 -5
- package/utils/commonUtils.js +83 -2
- package/utils/tagValidations.js +222 -84
- package/utils/tests/commonUtil.test.js +118 -147
- package/utils/tests/tagValidations.test.js +358 -280
- package/v2Components/ErrorInfoNote/index.js +5 -2
- package/v2Components/FormBuilder/index.js +158 -64
- package/v2Components/FormBuilder/messages.js +8 -0
- package/v2Components/HtmlEditor/HTMLEditor.js +5 -0
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +1 -0
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +15 -0
- package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +2 -1
- package/v2Containers/Cap/mockData.js +14 -0
- package/v2Containers/Cap/reducer.js +55 -3
- package/v2Containers/Cap/tests/reducer.test.js +102 -0
- package/v2Containers/CreativesContainer/index.js +1 -0
- package/v2Containers/Email/index.js +5 -1
- package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +62 -10
- package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +115 -12
- package/v2Containers/FTP/index.js +51 -2
- package/v2Containers/FTP/messages.js +4 -0
- package/v2Containers/InApp/index.js +96 -1
- package/v2Containers/InApp/tests/index.test.js +6 -17
- package/v2Containers/InappAdvance/index.js +103 -2
- package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +24 -3
- package/v2Containers/Line/Container/Text/index.js +1 -0
- package/v2Containers/MobilePushNew/index.js +33 -2
- package/v2Containers/Rcs/index.js +37 -12
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +18 -4
- package/v2Containers/SmsTrai/Create/index.scss +1 -1
- package/v2Containers/SmsTrai/Edit/index.js +47 -6
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +6 -6
- package/v2Containers/Viber/index.js +1 -0
- package/v2Containers/Viber/index.scss +1 -1
- package/v2Containers/WebPush/Create/hooks/useTagManagement.js +3 -1
- package/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +7 -0
- package/v2Containers/WebPush/Create/index.js +2 -2
- package/v2Containers/WebPush/Create/utils/validation.js +9 -18
- package/v2Containers/WebPush/Create/utils/validation.test.js +24 -0
- package/v2Containers/Whatsapp/index.js +17 -9
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +624 -248
- package/v2Containers/Zalo/index.js +11 -3
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import '@testing-library/jest-dom';
|
|
2
2
|
import {
|
|
3
|
+
checkSupport,
|
|
4
|
+
extractNames,
|
|
3
5
|
getTagMapValue,
|
|
4
6
|
getLoyaltyTagsMapValue,
|
|
5
7
|
getForwardedMapValues,
|
|
@@ -7,8 +9,10 @@ import {
|
|
|
7
9
|
validateIfTagClosed,
|
|
8
10
|
validateTags,
|
|
9
11
|
skipTags,
|
|
12
|
+
isInsideLiquidBlock,
|
|
10
13
|
} from '../tagValidations';
|
|
11
14
|
import { containsBase64Images } from '../content';
|
|
15
|
+
import { eventContextTags } from '../../v2Containers/TagList/tests/mockdata';
|
|
12
16
|
|
|
13
17
|
describe("check if curly brackets are balanced", () => {
|
|
14
18
|
it("test for balanced curly brackets", () => {
|
|
@@ -60,41 +64,53 @@ describe("validateTags", () => {
|
|
|
60
64
|
it("should return valid response when all tags are present", () => {
|
|
61
65
|
const content = "Hello {{tag1}}, {{tag2}}, {{tag3}} {{entryTrigger.lifetimePurchases}}";
|
|
62
66
|
|
|
67
|
+
const injectedTagsParams = [];
|
|
63
68
|
const location = { query: { module: "DEFAULT" } };
|
|
64
69
|
const tagModule = null;
|
|
65
70
|
|
|
66
71
|
const result = validateTags({
|
|
67
72
|
content,
|
|
68
73
|
tagsParam,
|
|
74
|
+
injectedTagsParams,
|
|
69
75
|
location,
|
|
70
76
|
tagModule,
|
|
77
|
+
eventContextTags,
|
|
71
78
|
});
|
|
72
79
|
|
|
73
80
|
expect(result.valid).toEqual(true);
|
|
74
81
|
expect(result.missingTags).toEqual([]);
|
|
82
|
+
expect(result.unsupportedTags).toEqual([]);
|
|
75
83
|
expect(result.isBraceError).toEqual(false);
|
|
76
84
|
});
|
|
77
85
|
|
|
78
|
-
it("should return
|
|
86
|
+
it("should return invalid response when a mandatory tag is missing", () => {
|
|
79
87
|
const content = "Hello {{tag1}}, {{tag2}}, {{tag3}}";
|
|
88
|
+
const updatedTagsParam = [...tagsParam, {
|
|
89
|
+
definition: {
|
|
90
|
+
supportedModules: [{ context: "DEFAULT", mandatory: true }],
|
|
91
|
+
value: "tag4",
|
|
92
|
+
},
|
|
93
|
+
},];
|
|
94
|
+
const injectedTagsParams = [];
|
|
80
95
|
const location = { query: { module: "DEFAULT" } };
|
|
81
96
|
const tagModule = null;
|
|
82
97
|
|
|
83
98
|
const result = validateTags({
|
|
84
99
|
content,
|
|
85
|
-
|
|
100
|
+
updatedTagsParam,
|
|
101
|
+
injectedTagsParams,
|
|
86
102
|
location,
|
|
87
103
|
tagModule,
|
|
88
104
|
});
|
|
89
105
|
|
|
90
106
|
expect(result.valid).toEqual(true);
|
|
91
|
-
expect(result.
|
|
107
|
+
expect(result.unsupportedTags).toEqual(["tag1", "tag2", "tag3"]);
|
|
92
108
|
expect(result.isBraceError).toEqual(false);
|
|
93
109
|
});
|
|
94
110
|
|
|
95
|
-
it("should return
|
|
111
|
+
it("should return invalid response when an unsupported tag is present", () => {
|
|
96
112
|
const content = "Hello {{tag1}}, {{tag2}}, {{tag3}} {{missingEventContextTags}}";
|
|
97
|
-
const
|
|
113
|
+
const tagsParam = [
|
|
98
114
|
{
|
|
99
115
|
definition: {
|
|
100
116
|
supportedModules: [{ context: "DEFAULT", mandatory: true }],
|
|
@@ -108,24 +124,27 @@ describe("validateTags", () => {
|
|
|
108
124
|
},
|
|
109
125
|
},
|
|
110
126
|
];
|
|
127
|
+
const injectedTagsParams = [];
|
|
111
128
|
const location = { query: { module: "DEFAULT" } };
|
|
112
129
|
const tagModule = null;
|
|
113
130
|
|
|
114
131
|
const result = validateTags({
|
|
115
132
|
content,
|
|
116
|
-
tagsParam
|
|
133
|
+
tagsParam,
|
|
134
|
+
injectedTagsParams,
|
|
117
135
|
location,
|
|
118
136
|
tagModule,
|
|
119
137
|
});
|
|
120
138
|
|
|
121
139
|
expect(result.valid).toEqual(true);
|
|
122
140
|
expect(result.missingTags).toEqual([]);
|
|
141
|
+
expect(result.unsupportedTags).toEqual(["tag3", "missingEventContextTags"]);
|
|
123
142
|
expect(result.isBraceError).toEqual(false);
|
|
124
143
|
});
|
|
125
144
|
|
|
126
145
|
it("should return invalid response when there is an unbalanced bracket error", () => {
|
|
127
146
|
const content = "Hello {{tag1}, {{tag2}}, {{tag3}}";
|
|
128
|
-
const
|
|
147
|
+
const tagsParam = [
|
|
129
148
|
{
|
|
130
149
|
definition: {
|
|
131
150
|
supportedModules: [{ context: "DEFAULT", mandatory: true }],
|
|
@@ -145,23 +164,26 @@ describe("validateTags", () => {
|
|
|
145
164
|
},
|
|
146
165
|
},
|
|
147
166
|
];
|
|
167
|
+
const injectedTagsParams = [];
|
|
148
168
|
const location = { query: { module: "DEFAULT" } };
|
|
149
169
|
const tagModule = null;
|
|
150
170
|
|
|
151
171
|
const result = validateTags({
|
|
152
172
|
content,
|
|
153
|
-
tagsParam
|
|
173
|
+
tagsParam,
|
|
174
|
+
injectedTagsParams,
|
|
154
175
|
location,
|
|
155
176
|
tagModule,
|
|
156
177
|
});
|
|
157
178
|
|
|
158
179
|
expect(result.valid).toEqual(false);
|
|
159
|
-
expect(result.missingTags).toEqual([]);
|
|
180
|
+
expect(result.missingTags).toEqual(["tag1"]);
|
|
181
|
+
expect(result.unsupportedTags).toEqual([]);
|
|
160
182
|
expect(result.isBraceError).toEqual(true);
|
|
161
183
|
});
|
|
162
184
|
|
|
163
|
-
it("should
|
|
164
|
-
const
|
|
185
|
+
it("should remove 'unsubscribe' from missingTags if skipTags logic is triggered", () => {
|
|
186
|
+
const tagsParam = [
|
|
165
187
|
{
|
|
166
188
|
definition: {
|
|
167
189
|
supportedModules: [{ context: "DEFAULT", mandatory: true }],
|
|
@@ -169,310 +191,288 @@ describe("validateTags", () => {
|
|
|
169
191
|
},
|
|
170
192
|
},
|
|
171
193
|
];
|
|
194
|
+
// Content does not include {{unsubscribe}}, so it would be missing
|
|
195
|
+
const contentMissing = "Hello {{tag1}}";
|
|
196
|
+
const injectedTagsParams = [];
|
|
172
197
|
const location = { query: { module: "DEFAULT" } };
|
|
173
198
|
const tagModule = null;
|
|
174
199
|
|
|
175
|
-
|
|
200
|
+
// First, verify unsubscribe is missing if not present
|
|
176
201
|
const resultMissing = validateTags({
|
|
177
202
|
content: contentMissing,
|
|
178
|
-
tagsParam
|
|
203
|
+
tagsParam,
|
|
204
|
+
injectedTagsParams,
|
|
179
205
|
location,
|
|
180
206
|
tagModule,
|
|
181
207
|
});
|
|
182
208
|
expect(resultMissing.missingTags).toContain("unsubscribe");
|
|
183
|
-
expect(resultMissing.valid).toBe(false);
|
|
184
209
|
|
|
210
|
+
// Now, content includes a tag that triggers skipTags logic for unsubscribe
|
|
211
|
+
// e.g., {{unsubscribe(#123456)}} matches the skipTags regex
|
|
185
212
|
const contentWithSkippedUnsubscribe = "Hello {{unsubscribe(#123456)}}";
|
|
186
213
|
const resultSkipped = validateTags({
|
|
187
214
|
content: contentWithSkippedUnsubscribe,
|
|
188
|
-
tagsParam
|
|
215
|
+
tagsParam,
|
|
216
|
+
injectedTagsParams,
|
|
189
217
|
location,
|
|
190
218
|
tagModule,
|
|
191
219
|
});
|
|
192
220
|
expect(resultSkipped.missingTags).not.toContain("unsubscribe");
|
|
193
221
|
expect(resultSkipped.valid).toBe(true);
|
|
194
|
-
|
|
195
|
-
const contentWithWhitespaceUnsubscribe = "Hello {{ unsubscribe }}";
|
|
196
|
-
const resultWhitespace = validateTags({
|
|
197
|
-
content: contentWithWhitespaceUnsubscribe,
|
|
198
|
-
tagsParam: tagsParamUnsubscribe,
|
|
199
|
-
location,
|
|
200
|
-
tagModule,
|
|
201
|
-
});
|
|
202
|
-
expect(resultWhitespace.missingTags).not.toContain("unsubscribe");
|
|
203
|
-
expect(resultWhitespace.valid).toBe(true);
|
|
204
|
-
expect(resultWhitespace.unsupportedTags ?? []).toEqual([]);
|
|
205
222
|
});
|
|
206
223
|
});
|
|
207
224
|
|
|
208
|
-
describe(
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
225
|
+
describe("extractNames", () => {
|
|
226
|
+
it("should return an empty array when data is empty", () => {
|
|
227
|
+
const data = [];
|
|
228
|
+
const result = extractNames(data);
|
|
229
|
+
expect(result).toEqual([]);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it("should return an array of names when data contains nodes with names", () => {
|
|
233
|
+
const data = [
|
|
234
|
+
{
|
|
235
|
+
name: "Node 1",
|
|
236
|
+
children: [
|
|
237
|
+
{
|
|
238
|
+
name: "Node 1.1",
|
|
239
|
+
children: [],
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
name: "Node 1.2",
|
|
243
|
+
children: [],
|
|
244
|
+
},
|
|
245
|
+
],
|
|
214
246
|
},
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
247
|
+
{
|
|
248
|
+
name: "Node 2",
|
|
249
|
+
children: [
|
|
250
|
+
{
|
|
251
|
+
name: "Node 2.1",
|
|
252
|
+
children: [],
|
|
253
|
+
},
|
|
254
|
+
],
|
|
222
255
|
},
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
256
|
+
];
|
|
257
|
+
const result = extractNames(data);
|
|
258
|
+
expect(result).toEqual([
|
|
259
|
+
"Node 1",
|
|
260
|
+
"Node 1.1",
|
|
261
|
+
"Node 1.2",
|
|
262
|
+
"Node 2",
|
|
263
|
+
"Node 2.1",
|
|
264
|
+
]);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it("should ignore nodes without names", () => {
|
|
268
|
+
const data = [
|
|
269
|
+
{
|
|
270
|
+
name: "Node 1",
|
|
271
|
+
children: [
|
|
272
|
+
{
|
|
273
|
+
name: "Node 1.1",
|
|
274
|
+
children: [],
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
children: [],
|
|
278
|
+
},
|
|
279
|
+
],
|
|
230
280
|
},
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
location: { query: { module: 'DEFAULT' } },
|
|
253
|
-
tagModule: 'outbound',
|
|
254
|
-
});
|
|
255
|
-
expect(resultWithOutbound.missingTags).toContain('unsubscribe');
|
|
256
|
-
expect(resultWithOutbound.valid).toBe(false);
|
|
257
|
-
|
|
258
|
-
const resultWithDefault = validateTags({
|
|
259
|
-
content,
|
|
260
|
-
tagsParam: tagsWithUnsubscribe,
|
|
261
|
-
location: { query: { module: 'outbound' } },
|
|
262
|
-
tagModule: 'DEFAULT',
|
|
263
|
-
});
|
|
264
|
-
expect(resultWithDefault.missingTags).toContain('unsubscribe');
|
|
265
|
-
expect(resultWithDefault.valid).toBe(false);
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
it('uses DEFAULT (lowercase) when location is undefined', () => {
|
|
269
|
-
const content = 'Hello world';
|
|
270
|
-
const result = validateTags({
|
|
271
|
-
content,
|
|
272
|
-
tagsParam: tagsDefaultLowercase,
|
|
273
|
-
location: undefined,
|
|
274
|
-
tagModule: null,
|
|
275
|
-
});
|
|
276
|
-
expect(result.missingTags).toContain('unsubscribe');
|
|
277
|
-
expect(result.valid).toBe(false);
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
it('uses DEFAULT when location.query is undefined', () => {
|
|
281
|
-
const content = 'Hello world';
|
|
282
|
-
const result = validateTags({
|
|
283
|
-
content,
|
|
284
|
-
tagsParam: tagsDefaultLowercase,
|
|
285
|
-
location: {},
|
|
286
|
-
tagModule: null,
|
|
287
|
-
});
|
|
288
|
-
expect(result.missingTags).toContain('unsubscribe');
|
|
289
|
-
expect(result.valid).toBe(false);
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
it('uses DEFAULT when location.query.module is falsy', () => {
|
|
293
|
-
const content = 'Hello world';
|
|
294
|
-
const result = validateTags({
|
|
295
|
-
content,
|
|
296
|
-
tagsParam: tagsDefaultLowercase,
|
|
297
|
-
location: { query: { module: '' } },
|
|
298
|
-
tagModule: null,
|
|
299
|
-
});
|
|
300
|
-
expect(result.missingTags).toContain('unsubscribe');
|
|
301
|
-
expect(result.valid).toBe(false);
|
|
302
|
-
});
|
|
281
|
+
{
|
|
282
|
+
name: "Node 2",
|
|
283
|
+
children: [
|
|
284
|
+
{
|
|
285
|
+
name: "Node 2.1",
|
|
286
|
+
children: [],
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
name: "Node 2.2",
|
|
290
|
+
},
|
|
291
|
+
],
|
|
292
|
+
},
|
|
293
|
+
];
|
|
294
|
+
const result = extractNames(data);
|
|
295
|
+
expect(result).toEqual([
|
|
296
|
+
"Node 1",
|
|
297
|
+
"Node 1.1",
|
|
298
|
+
"Node 2",
|
|
299
|
+
"Node 2.1",
|
|
300
|
+
"Node 2.2",
|
|
301
|
+
]);
|
|
303
302
|
});
|
|
303
|
+
});
|
|
304
304
|
|
|
305
|
-
describe('content passed to contentForBraceCheck and contentForUnsubscribeScan', () => {
|
|
306
|
-
it('uses same content for brace check (isBraceError when unbalanced)', () => {
|
|
307
|
-
const content = 'Hello {{tag1}, {{tag2}}';
|
|
308
|
-
const result = validateTags({
|
|
309
|
-
content,
|
|
310
|
-
tagsParam: [],
|
|
311
|
-
location: { query: { module: 'DEFAULT' } },
|
|
312
|
-
});
|
|
313
|
-
expect(result.isBraceError).toBe(true);
|
|
314
|
-
expect(result.valid).toBe(false);
|
|
315
|
-
});
|
|
316
305
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
tagsParam: tagsWithUnsubscribe,
|
|
322
|
-
location: { query: { module: 'DEFAULT' } },
|
|
323
|
-
});
|
|
324
|
-
expect(result.missingTags).toContain('unsubscribe');
|
|
325
|
-
expect(result.valid).toBe(false);
|
|
326
|
-
});
|
|
327
|
-
|
|
328
|
-
it('content with {{ unsubscribe }} satisfies unsubscribe requirement', () => {
|
|
329
|
-
const content = 'Hello {{ unsubscribe }}';
|
|
330
|
-
const result = validateTags({
|
|
331
|
-
content,
|
|
332
|
-
tagsParam: tagsWithUnsubscribe,
|
|
333
|
-
location: { query: { module: 'DEFAULT' } },
|
|
334
|
-
});
|
|
335
|
-
expect(result.missingTags).not.toContain('unsubscribe');
|
|
336
|
-
expect(result.valid).toBe(true);
|
|
337
|
-
});
|
|
306
|
+
describe("checkSupport", () => {
|
|
307
|
+
it("should return an empty array when args are empty", () => {
|
|
308
|
+
const result = checkSupport();
|
|
309
|
+
expect(result).toEqual([]);
|
|
338
310
|
});
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
content,
|
|
345
|
-
tagsParam: tagsWithUnsubscribe,
|
|
346
|
-
location: { query: { module: 'DEFAULT' } },
|
|
347
|
-
isFullMode: true,
|
|
348
|
-
});
|
|
349
|
-
expect(result.missingTags).toEqual([]);
|
|
350
|
-
expect(result.valid).toBe(true);
|
|
351
|
-
});
|
|
352
|
-
|
|
353
|
-
it('when true still runs brace check', () => {
|
|
354
|
-
const content = 'Hello {{tag1}';
|
|
355
|
-
const result = validateTags({
|
|
356
|
-
content,
|
|
357
|
-
tagsParam: tagsWithUnsubscribe,
|
|
358
|
-
location: { query: { module: 'DEFAULT' } },
|
|
359
|
-
isFullMode: true,
|
|
360
|
-
});
|
|
361
|
-
expect(result.isBraceError).toBe(true);
|
|
362
|
-
expect(result.valid).toBe(false);
|
|
363
|
-
});
|
|
311
|
+
it("should return an empty array when response data is empty", () => {
|
|
312
|
+
const response = { data: [] };
|
|
313
|
+
const tagObject = {};
|
|
314
|
+
const result = checkSupport(response, tagObject);
|
|
315
|
+
expect(result).toEqual([]);
|
|
364
316
|
});
|
|
365
317
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
});
|
|
374
|
-
expect(result.missingTags).toEqual([]);
|
|
375
|
-
expect(result.isBraceError).toBe(false);
|
|
376
|
-
expect(result.valid).toBe(true);
|
|
377
|
-
});
|
|
378
|
-
|
|
379
|
-
it('when empty array: only brace check runs', () => {
|
|
380
|
-
const content = 'Hello {{a}}';
|
|
381
|
-
const result = validateTags({
|
|
382
|
-
content,
|
|
383
|
-
tagsParam: [],
|
|
384
|
-
location: { query: { module: 'DEFAULT' } },
|
|
385
|
-
});
|
|
386
|
-
expect(result.missingTags).toEqual([]);
|
|
387
|
-
expect(result.valid).toBe(true);
|
|
388
|
-
});
|
|
389
|
-
|
|
390
|
-
it('when null with unbalanced braces: returns isBraceError', () => {
|
|
391
|
-
const content = 'Hello {{a}';
|
|
392
|
-
const result = validateTags({
|
|
393
|
-
content,
|
|
394
|
-
tagsParam: null,
|
|
395
|
-
location: { query: { module: 'DEFAULT' } },
|
|
396
|
-
});
|
|
397
|
-
expect(result.isBraceError).toBe(true);
|
|
398
|
-
expect(result.valid).toBe(false);
|
|
399
|
-
expect(result.missingTags).toEqual([]);
|
|
400
|
-
});
|
|
318
|
+
it("should return an empty array when tagObject is empty", () => {
|
|
319
|
+
const response = {
|
|
320
|
+
data: [{ name: "tag1" }, { name: "tag2" }, { name: "tag3" }],
|
|
321
|
+
};
|
|
322
|
+
const tagObject = {};
|
|
323
|
+
const result = checkSupport(response, tagObject);
|
|
324
|
+
expect(result).toEqual([]);
|
|
401
325
|
});
|
|
402
326
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
isFullMode: false,
|
|
412
|
-
});
|
|
413
|
-
expect(result.valid).toBe(true);
|
|
414
|
-
expect(result.isBraceError).toBe(false);
|
|
415
|
-
});
|
|
416
|
-
|
|
417
|
-
it('Zalo / Rcs / MobilePushNew / EmailWrapper: same pattern as Whatsapp', () => {
|
|
418
|
-
const result = validateTags({
|
|
419
|
-
content: 'Hi {{ unsubscribe }}',
|
|
420
|
-
tagsParam: tagsWithUnsubscribe,
|
|
421
|
-
location: { query: { module: 'DEFAULT' } },
|
|
422
|
-
tagModule: 'DEFAULT',
|
|
423
|
-
isFullMode: false,
|
|
424
|
-
});
|
|
425
|
-
expect(result.valid).toBe(true);
|
|
426
|
-
});
|
|
327
|
+
it("should return event context tags even if tagObject is empty", () => {
|
|
328
|
+
const response = {
|
|
329
|
+
data: [{ name: "tag1" }, { name: "entryTrigger.lifetimePurchases" }],
|
|
330
|
+
};
|
|
331
|
+
const tagObject = {};
|
|
332
|
+
const result = checkSupport(response, tagObject, eventContextTags);
|
|
333
|
+
expect(result).toEqual(['entryTrigger.lifetimePurchases']);
|
|
334
|
+
});
|
|
427
335
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
const resultOk = validateTags({
|
|
441
|
-
content: 'Hello {{ unsubscribe }}',
|
|
442
|
-
tagsParam: tagsOutboundUnsubscribe,
|
|
443
|
-
location: {},
|
|
444
|
-
tagModule: 'outbound',
|
|
445
|
-
isFullMode: false,
|
|
446
|
-
});
|
|
447
|
-
expect(resultOk.valid).toBe(true);
|
|
448
|
-
});
|
|
336
|
+
it("should return an array of supported tags", () => {
|
|
337
|
+
const response = {
|
|
338
|
+
data: [{ name: "tag1" }, { name: "tag2" }, { name: "tag3" }],
|
|
339
|
+
};
|
|
340
|
+
const tagObject = {
|
|
341
|
+
tag1: { definition: { subtags: ["tag1.1", "tag1.2"] } },
|
|
342
|
+
tag2: { definition: { subtags: ["tag2.1", "tag2.2"] } },
|
|
343
|
+
tag3: { definition: { subtags: ["tag3.1", "tag3.2"] } },
|
|
344
|
+
};
|
|
345
|
+
const result = checkSupport(response, tagObject);
|
|
346
|
+
expect(result).toEqual(["tag1", "tag2", "tag3"]);
|
|
347
|
+
});
|
|
449
348
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
349
|
+
it("should return an array of supported tags with subtags", () => {
|
|
350
|
+
const response = {
|
|
351
|
+
data: [{ name: "tag1" }, { name: "tag2" }, { name: "tag3" }],
|
|
352
|
+
};
|
|
353
|
+
const tagObject = {
|
|
354
|
+
tag1: { definition: { subtags: ["tag1.1", "tag1.2"] } },
|
|
355
|
+
tag2: { definition: { subtags: ["tag2.1", "tag2.2"] } },
|
|
356
|
+
tag3: { definition: { subtags: ["tag3.1", "tag3.2"] } },
|
|
357
|
+
"tag1.1": {},
|
|
358
|
+
"tag2.1": {},
|
|
359
|
+
"tag3.1": {},
|
|
360
|
+
};
|
|
361
|
+
const result = checkSupport(response, tagObject);
|
|
362
|
+
expect(result).toEqual(["tag1", "tag2", "tag3"]);
|
|
363
|
+
});
|
|
464
364
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
365
|
+
it("should return an empty array when no tags are supported", () => {
|
|
366
|
+
const response = {
|
|
367
|
+
data: [{ name: "tag1" }, { name: "tag2" }, { name: "tag3" }],
|
|
368
|
+
};
|
|
369
|
+
const tagObject = {
|
|
370
|
+
tag4: {},
|
|
371
|
+
tag5: {},
|
|
372
|
+
tag6: {},
|
|
373
|
+
};
|
|
374
|
+
const result = checkSupport(response, tagObject);
|
|
375
|
+
expect(result).toEqual([]);
|
|
376
|
+
});
|
|
377
|
+
it("should return an array of supported tags with subtags", () => {
|
|
378
|
+
const response = {
|
|
379
|
+
data: [
|
|
380
|
+
{
|
|
381
|
+
name: "tag1",
|
|
382
|
+
children: [{ name: "tag1.1", children: [{ name: "tag1.2" }] }],
|
|
383
|
+
},
|
|
384
|
+
{ name: "tag2", children: [] },
|
|
385
|
+
{ name: "tag3" },
|
|
386
|
+
],
|
|
387
|
+
};
|
|
388
|
+
const tagObject = {
|
|
389
|
+
tag1: { definition: { subtags: [".1", "tag1.2"] } },
|
|
390
|
+
tag2: { definition: { subtags: ["tag2.1", "tag2.2"] } },
|
|
391
|
+
tag3: { definition: { subtags: ["tag3.1", "tag3.2"] } },
|
|
392
|
+
"tag1.1": {},
|
|
393
|
+
"tag2.1": {},
|
|
394
|
+
"tag3.1": {},
|
|
395
|
+
};
|
|
396
|
+
const result = checkSupport(response, tagObject);
|
|
397
|
+
expect(result).toEqual(["tag1", "tag1.1", "tag2", "tag3"]);
|
|
398
|
+
});
|
|
399
|
+
it("should return an array of supported tags children as an object", () => {
|
|
400
|
+
const response = {
|
|
401
|
+
data: [
|
|
402
|
+
{ name: "tag1", children: [{ name: "tag" }] },
|
|
403
|
+
{ name: "tag2", children: [] },
|
|
404
|
+
{ name: "tag3" },
|
|
405
|
+
],
|
|
406
|
+
};
|
|
407
|
+
const tagObject = {
|
|
408
|
+
tag1: { definition: { subtags: [".1", "tag1.2"] } },
|
|
409
|
+
tag2: { definition: { subtags: ["tag2.1", "tag2.2"] } },
|
|
410
|
+
tag3: { definition: { subtags: ["tag3.1", "tag3.2"] } },
|
|
411
|
+
"tag1.1": {},
|
|
412
|
+
"tag2.1": {},
|
|
413
|
+
"tag3.1": {},
|
|
414
|
+
};
|
|
415
|
+
const result = checkSupport(response, tagObject);
|
|
416
|
+
expect(result).toEqual(["tag1", "tag2", "tag3"]);
|
|
417
|
+
});
|
|
418
|
+
it("should return an empty array if tagObject is empty", () => {
|
|
419
|
+
const response = {
|
|
420
|
+
data: [
|
|
421
|
+
{ name: "tag1", children: [{ name: "tag" }] },
|
|
422
|
+
{ name: "tag2", children: [] },
|
|
423
|
+
{ name: "tag3" },
|
|
424
|
+
],
|
|
425
|
+
};
|
|
426
|
+
const result = checkSupport(response, {});
|
|
427
|
+
expect(result).toEqual([]);
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
it("should add childName to supportedList if it is a subtag of parentTag in eventContextTags", () => {
|
|
431
|
+
const response = { data: [{ name: "leaderboard", children: [{name: "person.userId"}]}]};
|
|
432
|
+
const tagObject = {};
|
|
433
|
+
const eventContextTags = [{ tagName: "leaderboard", subTags: ["userId"]}];
|
|
434
|
+
const isLiquidFlow = true;
|
|
435
|
+
const result = checkSupport(response, tagObject, eventContextTags, isLiquidFlow);
|
|
436
|
+
expect(result).toEqual( [ 'leaderboard', 'person.userId' ]);
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
it("should not add childName to supportedList which does not have dot in eventContextTags", () => {
|
|
440
|
+
// This case is unlikely to happen as we are not supporting tags without dot in eventContextTags
|
|
441
|
+
const response = { data: [{ name: "entryTrigger.lifetimePoints", children: [{name: "userId"}] }]};
|
|
442
|
+
const tagObject = {};
|
|
443
|
+
const eventContextTags = [{ tagName: "entryTrigger.lifetimePoints", children: [{name: "userId"}] }];
|
|
444
|
+
const isLiquidFlow = true;
|
|
445
|
+
const result = checkSupport(response, tagObject, eventContextTags, isLiquidFlow);
|
|
446
|
+
expect(result).toEqual( [ "entryTrigger.lifetimePoints" ]);
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
it("should add only parent tag to supportedList if isLiquidFlow false", () => {
|
|
450
|
+
const response = { data: [{ name: "leaderboard", children: [{name: "person.userId"}]}]};
|
|
451
|
+
const tagObject = {};
|
|
452
|
+
const eventContextTags = [{ tagName: "leaderboard", subTags: ["userId"]}];
|
|
453
|
+
const isLiquidFlow = false;
|
|
454
|
+
const result = checkSupport(response, tagObject, eventContextTags, isLiquidFlow);
|
|
455
|
+
expect(result).toEqual( [ 'leaderboard' ]);
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
it("test for checking loyalty tags in that are coming in forwardedTags", () => {
|
|
459
|
+
const response = { data: [{ name: "leaderboard", children: [{name: "person.userId"}]}]};
|
|
460
|
+
const tagObject = {};
|
|
461
|
+
const isLiquidFlow = true;
|
|
462
|
+
// forwardedTags contains tag hierarchy with parent tags and their subtags
|
|
463
|
+
// needed for loyalty email liquid tag resolution
|
|
464
|
+
const forwardedTags = {
|
|
465
|
+
leaderboard: {
|
|
466
|
+
name: "Leaderboard",
|
|
467
|
+
subtags: {
|
|
468
|
+
"person.userId": {
|
|
469
|
+
name: "User ID",
|
|
470
|
+
},
|
|
471
|
+
},
|
|
472
|
+
},
|
|
473
|
+
};
|
|
474
|
+
const result = checkSupport(response, tagObject, [], isLiquidFlow, forwardedTags);
|
|
475
|
+
expect(result).toEqual( [ 'leaderboard', 'person.userId' ]);
|
|
476
476
|
});
|
|
477
477
|
});
|
|
478
478
|
|
|
@@ -1309,6 +1309,84 @@ describe('getForwardedMapValues', () => {
|
|
|
1309
1309
|
});
|
|
1310
1310
|
});
|
|
1311
1311
|
|
|
1312
|
+
describe('isInsideLiquidBlock', () => {
|
|
1313
|
+
it('returns true for index inside a single block', () => {
|
|
1314
|
+
const content = 'Hello {% assign foo = 1 %} World';
|
|
1315
|
+
// Index of 'a' in 'assign' inside the block
|
|
1316
|
+
const tagIndex = content.indexOf('assign');
|
|
1317
|
+
expect(isInsideLiquidBlock(content, tagIndex)).toBe(true);
|
|
1318
|
+
});
|
|
1319
|
+
|
|
1320
|
+
it('returns false for index outside any block', () => {
|
|
1321
|
+
const content = 'Hello {% assign foo = 1 %} World';
|
|
1322
|
+
// Index of 'H' in 'Hello'
|
|
1323
|
+
expect(isInsideLiquidBlock(content, 0)).toBe(false);
|
|
1324
|
+
// Index of 'W' in 'World'
|
|
1325
|
+
expect(isInsideLiquidBlock(content, content.indexOf('World'))).toBe(false);
|
|
1326
|
+
});
|
|
1327
|
+
|
|
1328
|
+
it('returns true for index at the start of a block', () => {
|
|
1329
|
+
const content = 'Hello {% assign foo = 1 %} World';
|
|
1330
|
+
// Index of '{' in '{%'
|
|
1331
|
+
const tagIndex = content.indexOf('{%');
|
|
1332
|
+
expect(isInsideLiquidBlock(content, tagIndex)).toBe(true);
|
|
1333
|
+
});
|
|
1334
|
+
|
|
1335
|
+
it('returns false for index at the end of a block (exclusive)', () => {
|
|
1336
|
+
const content = 'Hello {% assign foo = 1 %} World';
|
|
1337
|
+
// Index just after the closing '%}'
|
|
1338
|
+
const blockEnd = content.indexOf('%}') + 2;
|
|
1339
|
+
expect(isInsideLiquidBlock(content, blockEnd)).toBe(false);
|
|
1340
|
+
});
|
|
1341
|
+
|
|
1342
|
+
it('returns true for index inside the second of multiple blocks', () => {
|
|
1343
|
+
const content = 'A {% first %} B {% second %} C';
|
|
1344
|
+
const tagIndex = content.indexOf('second');
|
|
1345
|
+
expect(isInsideLiquidBlock(content, tagIndex)).toBe(true);
|
|
1346
|
+
});
|
|
1347
|
+
|
|
1348
|
+
it('returns false for index between blocks', () => {
|
|
1349
|
+
const content = 'A {% first %} B {% second %} C';
|
|
1350
|
+
// Index of 'B' (between blocks)
|
|
1351
|
+
const tagIndex = content.indexOf('B');
|
|
1352
|
+
expect(isInsideLiquidBlock(content, tagIndex)).toBe(false);
|
|
1353
|
+
});
|
|
1354
|
+
|
|
1355
|
+
it('returns false for empty string', () => {
|
|
1356
|
+
expect(isInsideLiquidBlock('', 0)).toBe(false);
|
|
1357
|
+
});
|
|
1358
|
+
|
|
1359
|
+
it('returns false if there are no blocks', () => {
|
|
1360
|
+
const content = 'Just some text with no blocks';
|
|
1361
|
+
expect(isInsideLiquidBlock(content, 5)).toBe(false);
|
|
1362
|
+
});
|
|
1363
|
+
|
|
1364
|
+
it('returns false for negative index', () => {
|
|
1365
|
+
const content = 'Hello {% assign foo = 1 %} World';
|
|
1366
|
+
expect(isInsideLiquidBlock(content, -1)).toBe(false);
|
|
1367
|
+
});
|
|
1368
|
+
|
|
1369
|
+
it('returns false for index beyond string length', () => {
|
|
1370
|
+
const content = 'Hello {% assign foo = 1 %} World';
|
|
1371
|
+
expect(isInsideLiquidBlock(content, 100)).toBe(false);
|
|
1372
|
+
});
|
|
1373
|
+
|
|
1374
|
+
it('works for nested-like blocks (not truly nested)', () => {
|
|
1375
|
+
const content = 'A {% outer {% inner %} outer %} B';
|
|
1376
|
+
// Index of 'inner' (should be inside the first block)
|
|
1377
|
+
const tagIndex = content.indexOf('inner');
|
|
1378
|
+
expect(isInsideLiquidBlock(content, tagIndex)).toBe(true);
|
|
1379
|
+
});
|
|
1380
|
+
|
|
1381
|
+
it('returns true for index at last char inside block', () => {
|
|
1382
|
+
const content = 'A {% foo %} B';
|
|
1383
|
+
// Index of last char inside block (just before %})
|
|
1384
|
+
const blockStart = content.indexOf('{%');
|
|
1385
|
+
const blockEnd = content.indexOf('%}');
|
|
1386
|
+
expect(isInsideLiquidBlock(content, blockEnd - 1)).toBe(true);
|
|
1387
|
+
});
|
|
1388
|
+
});
|
|
1389
|
+
|
|
1312
1390
|
describe('containsBase64Images', () => {
|
|
1313
1391
|
let mockCapNotification;
|
|
1314
1392
|
let mockCallback;
|