@capillarytech/creatives-library 8.0.345-alpha.14 → 8.0.345-alpha.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/constants/unified.js +29 -0
- package/package.json +1 -1
- package/services/tests/api.test.js +13 -0
- package/utils/commonUtils.js +19 -1
- package/utils/rcsPayloadUtils.js +92 -0
- package/utils/templateVarUtils.js +201 -0
- package/utils/tests/templateVarUtils.test.js +204 -0
- package/v2Components/CapActionButton/constants.js +7 -0
- package/v2Components/CapActionButton/index.js +167 -109
- package/v2Components/CapActionButton/index.scss +157 -6
- package/v2Components/CapActionButton/messages.js +19 -3
- package/v2Components/CapActionButton/tests/index.test.js +41 -17
- package/v2Components/CapTagList/index.js +10 -0
- package/v2Components/CommonTestAndPreview/CustomValuesEditor.js +70 -49
- package/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +8 -2
- package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +207 -21
- package/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +16 -0
- package/v2Components/CommonTestAndPreview/DeliverySettings/index.js +85 -10
- package/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +30 -0
- package/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +79 -11
- package/v2Components/CommonTestAndPreview/SendTestMessage.js +10 -5
- package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js +160 -15
- package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js.rej +18 -0
- package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +341 -76
- package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +133 -4
- package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +11 -0
- package/v2Components/CommonTestAndPreview/constants.js +38 -2
- package/v2Components/CommonTestAndPreview/index.js +676 -186
- package/v2Components/CommonTestAndPreview/messages.js +49 -3
- package/v2Components/CommonTestAndPreview/previewApiUtils.js +59 -0
- package/v2Components/CommonTestAndPreview/sagas.js +15 -6
- package/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +308 -284
- package/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +231 -65
- package/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +118 -5
- package/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +341 -0
- package/v2Components/CommonTestAndPreview/tests/PreviewSection.test.js +8 -1
- package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +34 -13
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/RcsPreviewContent.test.js +281 -283
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +199 -1
- package/v2Components/CommonTestAndPreview/tests/index.test.js +132 -4
- package/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +67 -0
- package/v2Components/CommonTestAndPreview/tests/sagas.test.js +2 -2
- package/v2Components/FormBuilder/index.js +8 -10
- package/v2Components/SmsFallback/SmsFallbackLocalSelector.js +87 -0
- package/v2Components/SmsFallback/constants.js +73 -0
- package/v2Components/SmsFallback/index.js +955 -0
- package/v2Components/SmsFallback/index.scss +265 -0
- package/v2Components/SmsFallback/messages.js +78 -0
- package/v2Components/SmsFallback/smsFallbackUtils.js +118 -0
- package/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +50 -0
- package/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +147 -0
- package/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +304 -0
- package/v2Components/SmsFallback/tests/smsFallbackUi.test.js +197 -0
- package/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +277 -0
- package/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +422 -0
- package/v2Components/SmsFallback/useLocalTemplateList.js +92 -0
- package/v2Components/TemplatePreview/_templatePreview.scss +33 -23
- package/v2Components/TemplatePreview/constants.js +2 -0
- package/v2Components/TemplatePreview/index.js +143 -28
- package/v2Components/TemplatePreview/tests/index.test.js +142 -0
- package/v2Components/TestAndPreviewSlidebox/index.js +13 -1
- package/v2Components/TestAndPreviewSlidebox/sagas.js +11 -4
- package/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +3 -1
- package/v2Components/VarSegmentMessageEditor/constants.js +2 -0
- package/v2Components/VarSegmentMessageEditor/index.js +125 -0
- package/v2Components/VarSegmentMessageEditor/index.scss +46 -0
- package/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +43 -0
- package/v2Containers/CreativesContainer/SlideBoxContent.js +36 -4
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +10 -1
- package/v2Containers/CreativesContainer/SlideBoxHeader.js +29 -4
- package/v2Containers/CreativesContainer/constants.js +9 -0
- package/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +67 -0
- package/v2Containers/CreativesContainer/index.js +300 -103
- package/v2Containers/CreativesContainer/index.scss +51 -1
- package/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +90 -0
- package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +78 -34
- package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +79 -16
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +8 -0
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +357 -98
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +20 -15
- package/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +258 -0
- package/v2Containers/CreativesContainer/tests/index.test.js +71 -9
- package/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +125 -0
- package/v2Containers/Email/reducer.js +3 -11
- package/v2Containers/Email/sagas.js +5 -9
- package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +0 -4
- package/v2Containers/Email/tests/sagas.test.js +3 -21
- package/v2Containers/Rcs/constants.js +119 -8
- package/v2Containers/Rcs/index.js +2379 -807
- package/v2Containers/Rcs/index.js.rej +1336 -0
- package/v2Containers/Rcs/index.scss +276 -6
- package/v2Containers/Rcs/index.scss.rej +74 -0
- package/v2Containers/Rcs/messages.js +38 -3
- package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +225 -0
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +98018 -70073
- package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +0 -5
- package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap.rej +128 -0
- package/v2Containers/Rcs/tests/index.test.js +152 -121
- package/v2Containers/Rcs/tests/mockData.js +38 -0
- package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +318 -0
- package/v2Containers/Rcs/tests/utils.test.js +646 -30
- package/v2Containers/Rcs/utils.js +478 -11
- package/v2Containers/Sms/Create/index.js +100 -40
- package/v2Containers/Sms/smsFormDataHelpers.js +67 -0
- package/v2Containers/Sms/tests/smsFormDataHelpers.test.js +253 -0
- package/v2Containers/SmsTrai/Create/index.js +9 -4
- package/v2Containers/SmsTrai/Edit/constants.js +2 -0
- package/v2Containers/SmsTrai/Edit/index.js +636 -130
- package/v2Containers/SmsTrai/Edit/index.scss +121 -0
- package/v2Containers/SmsTrai/Edit/messages.js +14 -4
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4328 -2375
- package/v2Containers/SmsWrapper/index.js +37 -8
- package/v2Containers/TagList/index.js +6 -0
- package/v2Containers/Templates/TemplatesActionBar.js +101 -0
- package/v2Containers/Templates/_templates.scss +163 -2
- package/v2Containers/Templates/actions.js +11 -0
- package/v2Containers/Templates/constants.js +2 -0
- package/v2Containers/Templates/index.js +119 -54
- package/v2Containers/Templates/sagas.js +57 -12
- package/v2Containers/Templates/tests/TemplatesActionBar.test.js +120 -0
- package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1043 -1079
- package/v2Containers/Templates/tests/sagas.test.js +193 -123
- package/v2Containers/Templates/tests/smsTemplatesListApi.test.js +180 -0
- package/v2Containers/Templates/utils/smsTemplatesListApi.js +79 -0
- package/v2Containers/TemplatesV2/TemplatesV2.style.js +72 -1
- package/v2Containers/TemplatesV2/index.js +86 -23
- package/v2Containers/TemplatesV2/tests/TemplatesV2.localTemplates.test.js +131 -0
- package/v2Containers/Whatsapp/index.js +3 -20
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +578 -34
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getUnmappedDesc,
|
|
3
|
+
hasRcsVarTokens,
|
|
4
|
+
normalizeLibraryLoadedTitleDesc,
|
|
5
|
+
mergeRcsSmsFallBackContentFromDetails,
|
|
6
|
+
mergeRcsSmsFallbackVarMapLayers,
|
|
7
|
+
pickFirstSmsFallbackTemplateString,
|
|
8
|
+
syncCardVarMappedSemanticsFromSlots,
|
|
9
|
+
hasMeaningfulSmsFallbackShape,
|
|
10
|
+
getLibrarySmsFallbackApiBaselineFromTemplateData,
|
|
11
|
+
extractRegisteredSenderIdsFromSmsFallbackRecord,
|
|
12
|
+
pickRcsCardVarMappedEntries,
|
|
13
|
+
} from '../rcsLibraryHydrationUtils';
|
|
14
|
+
import { rcsVarRegex } from '../constants';
|
|
15
|
+
|
|
16
|
+
describe('rcsLibraryHydrationUtils', () => {
|
|
17
|
+
describe('mergeRcsSmsFallBackContentFromDetails', () => {
|
|
18
|
+
it('returns empty object for missing details', () => {
|
|
19
|
+
expect(mergeRcsSmsFallBackContentFromDetails(null)).toEqual({});
|
|
20
|
+
expect(mergeRcsSmsFallBackContentFromDetails(undefined)).toEqual({});
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('merges nested RCS smsFallBackContent with root mirror; nested wins on overlap', () => {
|
|
24
|
+
const details = {
|
|
25
|
+
versions: {
|
|
26
|
+
base: {
|
|
27
|
+
content: {
|
|
28
|
+
RCS: {
|
|
29
|
+
smsFallBackContent: {
|
|
30
|
+
smsTemplateName: 'OldName',
|
|
31
|
+
message: 'from nested',
|
|
32
|
+
smsContent: 'nested body',
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
smsFallBackContent: {
|
|
39
|
+
message: 'from root',
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
const out = mergeRcsSmsFallBackContentFromDetails(details);
|
|
43
|
+
expect(out.message).toBe('from nested');
|
|
44
|
+
expect(out.smsContent).toBe('nested body');
|
|
45
|
+
expect(out.smsTemplateName).toBe('OldName');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('uses root when nested path is absent', () => {
|
|
49
|
+
const details = {
|
|
50
|
+
smsFallBackContent: { message: 'only root' },
|
|
51
|
+
};
|
|
52
|
+
expect(mergeRcsSmsFallBackContentFromDetails(details)).toEqual({ message: 'only root' });
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
describe('mergeRcsSmsFallbackVarMapLayers', () => {
|
|
57
|
+
it('merges API map with local so empty local object does not wipe API slots', () => {
|
|
58
|
+
const api = { rcsSmsFallbackVarMapped: { '{#a#}_0': 'x' } };
|
|
59
|
+
const local = { rcsSmsFallbackVarMapped: {} };
|
|
60
|
+
expect(mergeRcsSmsFallbackVarMapLayers(api, local)).toEqual({ '{#a#}_0': 'x' });
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('local slot values win on same key', () => {
|
|
64
|
+
const api = { rcsSmsFallbackVarMapped: { '{#a#}_0': 'old' } };
|
|
65
|
+
const local = { rcsSmsFallbackVarMapped: { '{#a#}_0': 'new' } };
|
|
66
|
+
expect(mergeRcsSmsFallbackVarMapLayers(api, local)).toEqual({ '{#a#}_0': 'new' });
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('reads kebab-case var map from a layer when camel is absent', () => {
|
|
70
|
+
const api = { 'rcs-sms-fallback-var-mapped': { '{#b#}_1': 'y' } };
|
|
71
|
+
expect(mergeRcsSmsFallbackVarMapLayers(api, {})).toEqual({ '{#b#}_1': 'y' });
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
describe('hasMeaningfulSmsFallbackShape', () => {
|
|
76
|
+
it('is false for empty / missing', () => {
|
|
77
|
+
expect(hasMeaningfulSmsFallbackShape(null)).toBe(false);
|
|
78
|
+
expect(hasMeaningfulSmsFallbackShape({})).toBe(false);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('is true when template body or name or var map exists', () => {
|
|
82
|
+
expect(hasMeaningfulSmsFallbackShape({ message: 'hi' })).toBe(true);
|
|
83
|
+
expect(hasMeaningfulSmsFallbackShape({ smsTemplateName: 'T' })).toBe(true);
|
|
84
|
+
expect(hasMeaningfulSmsFallbackShape({ rcsSmsFallbackVarMapped: { '{#a#}_0': 'x' } })).toBe(true);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe('getLibrarySmsFallbackApiBaselineFromTemplateData', () => {
|
|
89
|
+
it('merges root and nested; nested wins on overlap', () => {
|
|
90
|
+
const templateData = {
|
|
91
|
+
smsFallBackContent: { message: 'root' },
|
|
92
|
+
versions: {
|
|
93
|
+
base: {
|
|
94
|
+
content: {
|
|
95
|
+
RCS: {
|
|
96
|
+
smsFallBackContent: { message: 'nested', smsTemplateName: 'N' },
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
const out = getLibrarySmsFallbackApiBaselineFromTemplateData(templateData);
|
|
103
|
+
expect(out.message).toBe('nested');
|
|
104
|
+
expect(out.smsTemplateName).toBe('N');
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
describe('extractRegisteredSenderIdsFromSmsFallbackRecord', () => {
|
|
109
|
+
it('returns null for missing / empty', () => {
|
|
110
|
+
expect(extractRegisteredSenderIdsFromSmsFallbackRecord(null)).toBe(null);
|
|
111
|
+
expect(extractRegisteredSenderIdsFromSmsFallbackRecord({})).toBe(null);
|
|
112
|
+
expect(
|
|
113
|
+
extractRegisteredSenderIdsFromSmsFallbackRecord({ registeredSenderIds: [] }),
|
|
114
|
+
).toBe(null);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('prefers top-level registeredSenderIds', () => {
|
|
118
|
+
expect(
|
|
119
|
+
extractRegisteredSenderIdsFromSmsFallbackRecord({
|
|
120
|
+
registeredSenderIds: ['A'],
|
|
121
|
+
templateConfigs: { registeredSenderIds: ['B'] },
|
|
122
|
+
}),
|
|
123
|
+
).toEqual(['A']);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('reads templateConfigs.registeredSenderIds when top-level absent', () => {
|
|
127
|
+
expect(
|
|
128
|
+
extractRegisteredSenderIdsFromSmsFallbackRecord({
|
|
129
|
+
templateConfigs: { registeredSenderIds: ['DLT1', 'DLT2'] },
|
|
130
|
+
}),
|
|
131
|
+
).toEqual(['DLT1', 'DLT2']);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('falls back to templateConfigs.header array', () => {
|
|
135
|
+
expect(
|
|
136
|
+
extractRegisteredSenderIdsFromSmsFallbackRecord({
|
|
137
|
+
templateConfigs: { header: ['H1'] },
|
|
138
|
+
}),
|
|
139
|
+
).toEqual(['H1']);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
describe('pickFirstSmsFallbackTemplateString', () => {
|
|
144
|
+
it('prefers smsTemplateContent over resolved message so DLT tokens stay in the string', () => {
|
|
145
|
+
const sms = {
|
|
146
|
+
message: 'Hello user',
|
|
147
|
+
smsTemplateContent: 'Hello {#name#}',
|
|
148
|
+
};
|
|
149
|
+
expect(pickFirstSmsFallbackTemplateString(sms)).toBe('Hello {#name#}');
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('skips whitespace-only templateContent and uses next field', () => {
|
|
153
|
+
expect(
|
|
154
|
+
pickFirstSmsFallbackTemplateString({
|
|
155
|
+
templateContent: ' ',
|
|
156
|
+
message: 'x',
|
|
157
|
+
}),
|
|
158
|
+
).toBe('x');
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
describe('getUnmappedDesc', () => {
|
|
163
|
+
it('returns empty string for falsy str', () => {
|
|
164
|
+
expect(getUnmappedDesc('', { a: '1' })).toBe('');
|
|
165
|
+
expect(getUnmappedDesc(null, { a: '1' })).toBe('');
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('returns str when mapping is empty or missing', () => {
|
|
169
|
+
expect(getUnmappedDesc('hello', null)).toBe('hello');
|
|
170
|
+
expect(getUnmappedDesc('hello', {})).toBe('hello');
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('replaces literal values with {{key}} placeholders', () => {
|
|
174
|
+
expect(getUnmappedDesc('Hi Alice', { user_name: 'Alice' })).toBe('Hi {{user_name}}');
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('skips mapping entries with empty or whitespace-only values', () => {
|
|
178
|
+
expect(getUnmappedDesc('x', { a: '', b: ' ' })).toBe('x');
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('treats already-braced raw values without duplicating braced needle', () => {
|
|
182
|
+
expect(getUnmappedDesc('v {{user_id}}', { user_id: '{{user_id}}' })).toContain('{{user_id}}');
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it('adds braced needle when resolved value is not already in {{…}} form', () => {
|
|
186
|
+
const out = getUnmappedDesc('Hello Bob', { nick: 'Bob' });
|
|
187
|
+
expect(out).toBe('Hello {{nick}}');
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('ignores undefined mapping values', () => {
|
|
191
|
+
expect(getUnmappedDesc('x', { a: undefined })).toBe('x');
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it('matches longer needles first to avoid partial replaces', () => {
|
|
195
|
+
const out = getUnmappedDesc('ab', { x: 'a', y: 'ab' });
|
|
196
|
+
expect(out).toBe('{{y}}');
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('escapes regex metacharacters in resolved values', () => {
|
|
200
|
+
expect(getUnmappedDesc('price 9.99', { p: '9.99' })).toBe('price {{p}}');
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
describe('hasRcsVarTokens', () => {
|
|
205
|
+
it('is false for empty or non-matching strings', () => {
|
|
206
|
+
expect(hasRcsVarTokens('', rcsVarRegex)).toBe(false);
|
|
207
|
+
expect(hasRcsVarTokens('plain', rcsVarRegex)).toBe(false);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('is true when string contains {{word}} tokens', () => {
|
|
211
|
+
expect(hasRcsVarTokens('{{1}} hi', rcsVarRegex)).toBe(true);
|
|
212
|
+
expect(hasRcsVarTokens('{{user_id}}', rcsVarRegex)).toBe(true);
|
|
213
|
+
expect(hasRcsVarTokens('{{dynamic_expiry_date_after_3_days.FORMAT_1}}', rcsVarRegex)).toBe(true);
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
describe('normalizeLibraryLoadedTitleDesc', () => {
|
|
218
|
+
const cardVarMappedAfterHydration = { user_id: '123' };
|
|
219
|
+
|
|
220
|
+
it('returns originals in full mode', () => {
|
|
221
|
+
const out = normalizeLibraryLoadedTitleDesc({
|
|
222
|
+
loadedTitle: 'Hello 123',
|
|
223
|
+
loadedDesc: 'Desc',
|
|
224
|
+
isFullMode: true,
|
|
225
|
+
cardVarMappedAfterHydration,
|
|
226
|
+
rcsVarRegex,
|
|
227
|
+
});
|
|
228
|
+
expect(out).toEqual({ normalizedTitle: 'Hello 123', normalizedDesc: 'Desc' });
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it('unmaps when library mode, map present, and no mustache tokens', () => {
|
|
232
|
+
const out = normalizeLibraryLoadedTitleDesc({
|
|
233
|
+
loadedTitle: 'Hello 123',
|
|
234
|
+
loadedDesc: 'World 123',
|
|
235
|
+
isFullMode: false,
|
|
236
|
+
cardVarMappedAfterHydration,
|
|
237
|
+
rcsVarRegex,
|
|
238
|
+
});
|
|
239
|
+
expect(out.normalizedTitle).toBe('Hello {{user_id}}');
|
|
240
|
+
expect(out.normalizedDesc).toBe('World {{user_id}}');
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it('keeps {{numeric}} slots when tokens already exist', () => {
|
|
244
|
+
const out = normalizeLibraryLoadedTitleDesc({
|
|
245
|
+
loadedTitle: 'Hi {{1}}',
|
|
246
|
+
loadedDesc: 'Body 123',
|
|
247
|
+
isFullMode: false,
|
|
248
|
+
cardVarMappedAfterHydration,
|
|
249
|
+
rcsVarRegex,
|
|
250
|
+
});
|
|
251
|
+
expect(out.normalizedTitle).toBe('Hi {{1}}');
|
|
252
|
+
expect(out.normalizedDesc).toBe('Body {{user_id}}');
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it('does not unmap when cardVarMappedAfterHydration is empty', () => {
|
|
256
|
+
const out = normalizeLibraryLoadedTitleDesc({
|
|
257
|
+
loadedTitle: 'Hello',
|
|
258
|
+
loadedDesc: 'D',
|
|
259
|
+
isFullMode: false,
|
|
260
|
+
cardVarMappedAfterHydration: {},
|
|
261
|
+
rcsVarRegex,
|
|
262
|
+
});
|
|
263
|
+
expect(out).toEqual({ normalizedTitle: 'Hello', normalizedDesc: 'D' });
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
describe('syncCardVarMappedSemanticsFromSlots', () => {
|
|
268
|
+
it('copies numeric slot values onto empty semantic keys (campaign round-trip)', () => {
|
|
269
|
+
const out = syncCardVarMappedSemanticsFromSlots(
|
|
270
|
+
{ 1: '[FirstName]', user_name: '', 2: 'x', other: '' },
|
|
271
|
+
'Hi {{user_name}}',
|
|
272
|
+
'More {{other}}',
|
|
273
|
+
rcsVarRegex,
|
|
274
|
+
);
|
|
275
|
+
expect(out.user_name).toBe('[FirstName]');
|
|
276
|
+
expect(out.other).toBe('x');
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
it('does not overwrite non-empty semantic keys', () => {
|
|
280
|
+
const out = syncCardVarMappedSemanticsFromSlots(
|
|
281
|
+
{ 1: 'from-slot', user_name: 'kept' },
|
|
282
|
+
'Hello {{user_name}}',
|
|
283
|
+
'',
|
|
284
|
+
rcsVarRegex,
|
|
285
|
+
);
|
|
286
|
+
expect(out.user_name).toBe('kept');
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
describe('pickRcsCardVarMappedEntries', () => {
|
|
291
|
+
it('returns {} for null, undefined, and array inputs', () => {
|
|
292
|
+
expect(pickRcsCardVarMappedEntries(null)).toEqual({});
|
|
293
|
+
expect(pickRcsCardVarMappedEntries(undefined)).toEqual({});
|
|
294
|
+
expect(pickRcsCardVarMappedEntries(['{#v#}_0', 'x'])).toEqual({});
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
it('keeps numeric slot keys', () => {
|
|
298
|
+
expect(pickRcsCardVarMappedEntries({ 1: 'a', 2: 'b' })).toEqual({ 1: 'a', 2: 'b' });
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
it('keeps semantic word keys', () => {
|
|
302
|
+
expect(pickRcsCardVarMappedEntries({ user_name: 'Alice', gt: '{{tag}}' })).toEqual({
|
|
303
|
+
user_name: 'Alice',
|
|
304
|
+
gt: '{{tag}}',
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
it('strips SMS fallback slot keys like {#var#}_0', () => {
|
|
309
|
+
const input = { 1: 'x', user_name: 'y', '{#promo#}_0': 'z', '{{name}}_1': 'w' };
|
|
310
|
+
const out = pickRcsCardVarMappedEntries(input);
|
|
311
|
+
expect(out).toEqual({ 1: 'x', user_name: 'y' });
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
it('returns {} for an empty object', () => {
|
|
315
|
+
expect(pickRcsCardVarMappedEntries({})).toEqual({});
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
});
|