@segment/action-destinations 3.478.0 → 3.479.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/dist/destinations/klaviyo/addProfileToList/index.js +1 -1
- package/dist/destinations/klaviyo/addProfileToList/index.js.map +1 -1
- package/dist/destinations/klaviyo/properties.js +10 -2
- package/dist/destinations/klaviyo/properties.js.map +1 -1
- package/dist/destinations/klaviyo/removeProfile/index.js +1 -1
- package/dist/destinations/klaviyo/removeProfile/index.js.map +1 -1
- package/dist/destinations/klaviyo/removeProfileFromList/index.js +1 -1
- package/dist/destinations/klaviyo/removeProfileFromList/index.js.map +1 -1
- package/dist/destinations/klaviyo/subscribeProfile/generated-types.d.ts +1 -0
- package/dist/destinations/klaviyo/subscribeProfile/index.js +6 -0
- package/dist/destinations/klaviyo/subscribeProfile/index.js.map +1 -1
- package/dist/destinations/klaviyo/trackEvent/index.js +1 -1
- package/dist/destinations/klaviyo/trackEvent/index.js.map +1 -1
- package/dist/destinations/klaviyo/unsubscribeProfile/generated-types.d.ts +1 -0
- package/dist/destinations/klaviyo/unsubscribeProfile/index.js +6 -0
- package/dist/destinations/klaviyo/unsubscribeProfile/index.js.map +1 -1
- package/dist/destinations/klaviyo/upsertProfile/index.js +1 -1
- package/dist/destinations/klaviyo/upsertProfile/index.js.map +1 -1
- package/dist/destinations/salesforce-marketing-cloud/_tests_/contactDataExtensionV2.test.d.ts +1 -0
- package/dist/destinations/salesforce-marketing-cloud/_tests_/contactDataExtensionV2.test.js +650 -0
- package/dist/destinations/salesforce-marketing-cloud/_tests_/contactDataExtensionV2.test.js.map +1 -0
- package/dist/destinations/salesforce-marketing-cloud/_tests_/dataExtensionV2.test.d.ts +1 -0
- package/dist/destinations/salesforce-marketing-cloud/_tests_/dataExtensionV2.test.js +501 -0
- package/dist/destinations/salesforce-marketing-cloud/_tests_/dataExtensionV2.test.js.map +1 -0
- package/dist/destinations/yahoo-audiences/index.js +1 -14
- package/dist/destinations/yahoo-audiences/index.js.map +1 -1
- package/dist/destinations/yahoo-audiences/types.d.ts +3 -0
- package/dist/destinations/yahoo-audiences/utils-tax.d.ts +1 -1
- package/dist/destinations/yahoo-audiences/utils-tax.js +25 -15
- package/dist/destinations/yahoo-audiences/utils-tax.js.map +1 -1
- package/dist/lib/test-data.js +24 -7
- package/dist/lib/test-data.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,650 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const nock_1 = __importDefault(require("nock"));
|
|
7
|
+
const actions_core_1 = require("@segment/actions-core");
|
|
8
|
+
const index_1 = __importDefault(require("../index"));
|
|
9
|
+
const testDestination = (0, actions_core_1.createTestIntegration)(index_1.default);
|
|
10
|
+
const timestamp = '2025-10-13T4:00:00.449Z';
|
|
11
|
+
const settings = {
|
|
12
|
+
subdomain: 'test123',
|
|
13
|
+
client_id: 'test123',
|
|
14
|
+
client_secret: 'test123',
|
|
15
|
+
account_id: 'test123'
|
|
16
|
+
};
|
|
17
|
+
const dataExtensionId = '1234567890';
|
|
18
|
+
const event = (0, actions_core_1.createTestEvent)({
|
|
19
|
+
timestamp: timestamp,
|
|
20
|
+
type: 'identify',
|
|
21
|
+
userId: 'harryStyles1',
|
|
22
|
+
traits: {
|
|
23
|
+
firstName: 'Harry',
|
|
24
|
+
lastName: 'Styles'
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
const payload = {
|
|
28
|
+
keys: {
|
|
29
|
+
contactKey: 'harryStyles1',
|
|
30
|
+
id: 'HS1'
|
|
31
|
+
},
|
|
32
|
+
values: {
|
|
33
|
+
firstName: 'Harry',
|
|
34
|
+
lastName: 'Styles'
|
|
35
|
+
},
|
|
36
|
+
onMappingSave: {
|
|
37
|
+
inputs: {},
|
|
38
|
+
outputs: {
|
|
39
|
+
id: dataExtensionId
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
const retlPayload = {
|
|
44
|
+
keys: {
|
|
45
|
+
contactKey: 'harryStyles1',
|
|
46
|
+
id: 'HS1'
|
|
47
|
+
},
|
|
48
|
+
values: {
|
|
49
|
+
firstName: 'Harry',
|
|
50
|
+
lastName: 'Styles'
|
|
51
|
+
},
|
|
52
|
+
retlOnMappingSave: {
|
|
53
|
+
inputs: {},
|
|
54
|
+
outputs: {
|
|
55
|
+
id: dataExtensionId
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
describe('Salesforce Marketing Cloud', () => {
|
|
60
|
+
describe('Contact Data Extension V2', () => {
|
|
61
|
+
beforeEach(() => {
|
|
62
|
+
nock_1.default.cleanAll();
|
|
63
|
+
});
|
|
64
|
+
afterEach(() => {
|
|
65
|
+
nock_1.default.cleanAll();
|
|
66
|
+
});
|
|
67
|
+
describe('perform', () => {
|
|
68
|
+
it('should send contact data to the data extension endpoint using dataExtensionId', async () => {
|
|
69
|
+
(0, nock_1.default)(`https://${settings.subdomain}.rest.marketingcloudapis.com`)
|
|
70
|
+
.post(`/hub/v1/dataevents/${dataExtensionId}/rowset`, [
|
|
71
|
+
{
|
|
72
|
+
keys: { contactKey: 'harryStyles1', id: 'HS1' },
|
|
73
|
+
values: { firstName: 'Harry', lastName: 'Styles' }
|
|
74
|
+
}
|
|
75
|
+
])
|
|
76
|
+
.reply(200, [
|
|
77
|
+
{
|
|
78
|
+
message: 'Contact created successfully'
|
|
79
|
+
}
|
|
80
|
+
]);
|
|
81
|
+
const responses = await testDestination.testAction('contactDataExtensionV2', {
|
|
82
|
+
event,
|
|
83
|
+
settings,
|
|
84
|
+
mapping: payload
|
|
85
|
+
});
|
|
86
|
+
expect(responses.length).toBe(1);
|
|
87
|
+
expect(responses[0].status).toBe(200);
|
|
88
|
+
expect(responses[0].data).toEqual([
|
|
89
|
+
{
|
|
90
|
+
message: 'Contact created successfully'
|
|
91
|
+
}
|
|
92
|
+
]);
|
|
93
|
+
});
|
|
94
|
+
it('should use default contactKey mapping from userId', async () => {
|
|
95
|
+
(0, nock_1.default)(`https://${settings.subdomain}.rest.marketingcloudapis.com`)
|
|
96
|
+
.post(`/hub/v1/dataevents/${dataExtensionId}/rowset`, [
|
|
97
|
+
{
|
|
98
|
+
keys: { contactKey: 'harryStyles1' },
|
|
99
|
+
values: { firstName: 'Harry', lastName: 'Styles' }
|
|
100
|
+
}
|
|
101
|
+
])
|
|
102
|
+
.reply(200, [
|
|
103
|
+
{
|
|
104
|
+
message: 'Contact created successfully'
|
|
105
|
+
}
|
|
106
|
+
]);
|
|
107
|
+
const responses = await testDestination.testAction('contactDataExtensionV2', {
|
|
108
|
+
event,
|
|
109
|
+
settings,
|
|
110
|
+
useDefaultMappings: true,
|
|
111
|
+
mapping: {
|
|
112
|
+
values: {
|
|
113
|
+
firstName: { '@path': '$.traits.firstName' },
|
|
114
|
+
lastName: { '@path': '$.traits.lastName' }
|
|
115
|
+
},
|
|
116
|
+
onMappingSave: {
|
|
117
|
+
inputs: {},
|
|
118
|
+
outputs: {
|
|
119
|
+
id: dataExtensionId
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
expect(responses.length).toBe(1);
|
|
125
|
+
expect(responses[0].status).toBe(200);
|
|
126
|
+
});
|
|
127
|
+
it('should work with retlOnMappingSave hook outputs', async () => {
|
|
128
|
+
(0, nock_1.default)(`https://${settings.subdomain}.rest.marketingcloudapis.com`)
|
|
129
|
+
.post(`/hub/v1/dataevents/${dataExtensionId}/rowset`)
|
|
130
|
+
.reply(200, [
|
|
131
|
+
{
|
|
132
|
+
message: 'Contact created successfully'
|
|
133
|
+
}
|
|
134
|
+
]);
|
|
135
|
+
const responses = await testDestination.testAction('contactDataExtensionV2', {
|
|
136
|
+
event,
|
|
137
|
+
settings,
|
|
138
|
+
mapping: retlPayload
|
|
139
|
+
});
|
|
140
|
+
expect(responses.length).toBe(1);
|
|
141
|
+
expect(responses[0].status).toBe(200);
|
|
142
|
+
});
|
|
143
|
+
it('should throw an error if no data extension is connected', async () => {
|
|
144
|
+
await expect(testDestination.testAction('contactDataExtensionV2', {
|
|
145
|
+
event,
|
|
146
|
+
settings,
|
|
147
|
+
mapping: {
|
|
148
|
+
keys: {
|
|
149
|
+
contactKey: 'harryStyles1',
|
|
150
|
+
id: 'HS1'
|
|
151
|
+
},
|
|
152
|
+
values: {
|
|
153
|
+
firstName: 'Harry',
|
|
154
|
+
lastName: 'Styles'
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
})).rejects.toThrowError('No Data Extension Connected');
|
|
158
|
+
});
|
|
159
|
+
it('should handle API error', async () => {
|
|
160
|
+
(0, nock_1.default)(`https://${settings.subdomain}.rest.marketingcloudapis.com`)
|
|
161
|
+
.post(`/hub/v1/dataevents/${dataExtensionId}/rowset`)
|
|
162
|
+
.reply(400, {
|
|
163
|
+
message: 'Bad Request - Invalid contactKey',
|
|
164
|
+
errorcode: 12345
|
|
165
|
+
});
|
|
166
|
+
await expect(testDestination.testAction('contactDataExtensionV2', {
|
|
167
|
+
event,
|
|
168
|
+
settings,
|
|
169
|
+
mapping: payload
|
|
170
|
+
})).rejects.toThrow('Bad Request');
|
|
171
|
+
});
|
|
172
|
+
it('should handle 500 server error', async () => {
|
|
173
|
+
(0, nock_1.default)(`https://${settings.subdomain}.rest.marketingcloudapis.com`)
|
|
174
|
+
.post(`/hub/v1/dataevents/${dataExtensionId}/rowset`)
|
|
175
|
+
.reply(500, {
|
|
176
|
+
message: 'Internal Server Error'
|
|
177
|
+
});
|
|
178
|
+
await expect(testDestination.testAction('contactDataExtensionV2', {
|
|
179
|
+
event,
|
|
180
|
+
settings,
|
|
181
|
+
mapping: payload
|
|
182
|
+
})).rejects.toThrow('Internal Server Error');
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
describe('performBatch', () => {
|
|
186
|
+
it('should send batched contact data to the data extension endpoint', async () => {
|
|
187
|
+
(0, nock_1.default)(`https://${settings.subdomain}.rest.marketingcloudapis.com`)
|
|
188
|
+
.post(`/hub/v1/dataevents/${dataExtensionId}/rowset`)
|
|
189
|
+
.reply(200, [{ message: 'Success 1' }, { message: 'Success 2' }, { message: 'Success 3' }]);
|
|
190
|
+
const events = [
|
|
191
|
+
(0, actions_core_1.createTestEvent)({
|
|
192
|
+
type: 'identify',
|
|
193
|
+
userId: 'user1',
|
|
194
|
+
traits: {
|
|
195
|
+
keys: { contactKey: 'user1', id: 'U1' },
|
|
196
|
+
values: { firstName: 'User', lastName: 'One' }
|
|
197
|
+
}
|
|
198
|
+
}),
|
|
199
|
+
(0, actions_core_1.createTestEvent)({
|
|
200
|
+
type: 'identify',
|
|
201
|
+
userId: 'user2',
|
|
202
|
+
traits: {
|
|
203
|
+
keys: { contactKey: 'user2', id: 'U2' },
|
|
204
|
+
values: { firstName: 'User', lastName: 'Two' }
|
|
205
|
+
}
|
|
206
|
+
}),
|
|
207
|
+
(0, actions_core_1.createTestEvent)({
|
|
208
|
+
type: 'identify',
|
|
209
|
+
userId: 'user3',
|
|
210
|
+
traits: {
|
|
211
|
+
keys: { contactKey: 'user3', id: 'U3' },
|
|
212
|
+
values: { firstName: 'User', lastName: 'Three' }
|
|
213
|
+
}
|
|
214
|
+
})
|
|
215
|
+
];
|
|
216
|
+
const mapping = {
|
|
217
|
+
keys: { '@path': '$.traits.keys' },
|
|
218
|
+
values: { '@path': '$.traits.values' },
|
|
219
|
+
onMappingSave: {
|
|
220
|
+
inputs: {},
|
|
221
|
+
outputs: {
|
|
222
|
+
id: dataExtensionId
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
const responses = await testDestination.executeBatch('contactDataExtensionV2', {
|
|
227
|
+
events,
|
|
228
|
+
settings,
|
|
229
|
+
mapping
|
|
230
|
+
});
|
|
231
|
+
expect(responses.length).toBe(3);
|
|
232
|
+
expect(responses[0].status).toBe(200);
|
|
233
|
+
expect(responses[0].body).toEqual({ message: 'Success 1' });
|
|
234
|
+
expect(responses[1].status).toBe(200);
|
|
235
|
+
expect(responses[2].status).toBe(200);
|
|
236
|
+
});
|
|
237
|
+
it('should send multiple contacts in batch mode', async () => {
|
|
238
|
+
(0, nock_1.default)(`https://${settings.subdomain}.rest.marketingcloudapis.com`)
|
|
239
|
+
.post(`/hub/v1/dataevents/${dataExtensionId}/rowset`)
|
|
240
|
+
.reply(200, [{ message: 'Success 1' }, { message: 'Success 2' }]);
|
|
241
|
+
const events = [
|
|
242
|
+
(0, actions_core_1.createTestEvent)({
|
|
243
|
+
type: 'identify',
|
|
244
|
+
userId: 'user1',
|
|
245
|
+
traits: {
|
|
246
|
+
keys: { contactKey: 'user1' },
|
|
247
|
+
values: { firstName: 'User', lastName: 'One' }
|
|
248
|
+
}
|
|
249
|
+
}),
|
|
250
|
+
(0, actions_core_1.createTestEvent)({
|
|
251
|
+
type: 'identify',
|
|
252
|
+
userId: 'user2',
|
|
253
|
+
traits: {
|
|
254
|
+
keys: { contactKey: 'user2' },
|
|
255
|
+
values: { firstName: 'User', lastName: 'Two' }
|
|
256
|
+
}
|
|
257
|
+
})
|
|
258
|
+
];
|
|
259
|
+
const mapping = {
|
|
260
|
+
keys: { '@path': '$.traits.keys' },
|
|
261
|
+
values: { '@path': '$.traits.values' },
|
|
262
|
+
onMappingSave: {
|
|
263
|
+
inputs: {},
|
|
264
|
+
outputs: {
|
|
265
|
+
id: dataExtensionId
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
const responses = await testDestination.executeBatch('contactDataExtensionV2', {
|
|
270
|
+
events,
|
|
271
|
+
settings,
|
|
272
|
+
mapping
|
|
273
|
+
});
|
|
274
|
+
expect(responses.length).toBe(2);
|
|
275
|
+
expect(responses[0].status).toBe(200);
|
|
276
|
+
expect(responses[1].status).toBe(200);
|
|
277
|
+
});
|
|
278
|
+
it('should throw an error if no data extension is connected in batch mode', async () => {
|
|
279
|
+
const events = [
|
|
280
|
+
(0, actions_core_1.createTestEvent)({
|
|
281
|
+
type: 'identify',
|
|
282
|
+
userId: 'user1',
|
|
283
|
+
traits: {
|
|
284
|
+
keys: { contactKey: 'user1', id: 'U1' },
|
|
285
|
+
values: { firstName: 'User', lastName: 'One' }
|
|
286
|
+
}
|
|
287
|
+
})
|
|
288
|
+
];
|
|
289
|
+
const mapping = {
|
|
290
|
+
keys: { '@path': '$.traits.keys' },
|
|
291
|
+
values: { '@path': '$.traits.values' }
|
|
292
|
+
};
|
|
293
|
+
await expect(testDestination.executeBatch('contactDataExtensionV2', {
|
|
294
|
+
events,
|
|
295
|
+
settings,
|
|
296
|
+
mapping
|
|
297
|
+
})).rejects.toThrowError('No Data Extension Connected');
|
|
298
|
+
});
|
|
299
|
+
it('should work with retlOnMappingSave hook outputs in batch mode', async () => {
|
|
300
|
+
(0, nock_1.default)(`https://${settings.subdomain}.rest.marketingcloudapis.com`)
|
|
301
|
+
.post(`/hub/v1/dataevents/${dataExtensionId}/rowset`)
|
|
302
|
+
.reply(200, [{ message: 'Success' }]);
|
|
303
|
+
const events = [
|
|
304
|
+
(0, actions_core_1.createTestEvent)({
|
|
305
|
+
type: 'identify',
|
|
306
|
+
userId: 'user1',
|
|
307
|
+
traits: {
|
|
308
|
+
keys: { contactKey: 'user1', id: 'U1' },
|
|
309
|
+
values: { firstName: 'User', lastName: 'One' }
|
|
310
|
+
}
|
|
311
|
+
})
|
|
312
|
+
];
|
|
313
|
+
const mapping = {
|
|
314
|
+
keys: { '@path': '$.traits.keys' },
|
|
315
|
+
values: { '@path': '$.traits.values' },
|
|
316
|
+
retlOnMappingSave: {
|
|
317
|
+
inputs: {},
|
|
318
|
+
outputs: {
|
|
319
|
+
id: dataExtensionId
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
const responses = await testDestination.executeBatch('contactDataExtensionV2', {
|
|
324
|
+
events,
|
|
325
|
+
settings,
|
|
326
|
+
mapping
|
|
327
|
+
});
|
|
328
|
+
expect(responses.length).toBe(1);
|
|
329
|
+
expect(responses[0].status).toBe(200);
|
|
330
|
+
});
|
|
331
|
+
it('should handle API error in batch mode', async () => {
|
|
332
|
+
(0, nock_1.default)(`https://${settings.subdomain}.rest.marketingcloudapis.com`)
|
|
333
|
+
.post(`/hub/v1/dataevents/${dataExtensionId}/rowset`)
|
|
334
|
+
.reply(400, {
|
|
335
|
+
message: 'Bad Request in batch',
|
|
336
|
+
errorcode: 12345,
|
|
337
|
+
additionalErrors: [
|
|
338
|
+
{
|
|
339
|
+
message: 'Invalid contact key format'
|
|
340
|
+
}
|
|
341
|
+
]
|
|
342
|
+
});
|
|
343
|
+
const events = [
|
|
344
|
+
(0, actions_core_1.createTestEvent)({
|
|
345
|
+
type: 'identify',
|
|
346
|
+
userId: 'user1',
|
|
347
|
+
traits: {
|
|
348
|
+
keys: { contactKey: 'user1', id: 'U1' },
|
|
349
|
+
values: { firstName: 'User', lastName: 'One' }
|
|
350
|
+
}
|
|
351
|
+
})
|
|
352
|
+
];
|
|
353
|
+
const mapping = {
|
|
354
|
+
keys: { '@path': '$.traits.keys' },
|
|
355
|
+
values: { '@path': '$.traits.values' },
|
|
356
|
+
onMappingSave: {
|
|
357
|
+
inputs: {},
|
|
358
|
+
outputs: {
|
|
359
|
+
id: dataExtensionId
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
const responses = await testDestination.executeBatch('contactDataExtensionV2', {
|
|
364
|
+
events,
|
|
365
|
+
settings,
|
|
366
|
+
mapping
|
|
367
|
+
});
|
|
368
|
+
expect(responses.length).toBe(1);
|
|
369
|
+
expect(responses[0]).toMatchObject({
|
|
370
|
+
status: 400,
|
|
371
|
+
errortype: 'BAD_REQUEST',
|
|
372
|
+
errormessage: 'Invalid contact key format'
|
|
373
|
+
});
|
|
374
|
+
});
|
|
375
|
+
it('should handle 500 server error in batch mode', async () => {
|
|
376
|
+
(0, nock_1.default)(`https://${settings.subdomain}.rest.marketingcloudapis.com`)
|
|
377
|
+
.post(`/hub/v1/dataevents/${dataExtensionId}/rowset`)
|
|
378
|
+
.reply(500, {
|
|
379
|
+
message: 'Internal Server Error in batch'
|
|
380
|
+
});
|
|
381
|
+
const events = [
|
|
382
|
+
(0, actions_core_1.createTestEvent)({
|
|
383
|
+
type: 'identify',
|
|
384
|
+
userId: 'user1',
|
|
385
|
+
traits: {
|
|
386
|
+
keys: { contactKey: 'user1', id: 'U1' },
|
|
387
|
+
values: { firstName: 'User', lastName: 'One' }
|
|
388
|
+
}
|
|
389
|
+
})
|
|
390
|
+
];
|
|
391
|
+
const mapping = {
|
|
392
|
+
keys: { '@path': '$.traits.keys' },
|
|
393
|
+
values: { '@path': '$.traits.values' },
|
|
394
|
+
onMappingSave: {
|
|
395
|
+
inputs: {},
|
|
396
|
+
outputs: {
|
|
397
|
+
id: dataExtensionId
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
const responses = await testDestination.executeBatch('contactDataExtensionV2', {
|
|
402
|
+
events,
|
|
403
|
+
settings,
|
|
404
|
+
mapping
|
|
405
|
+
});
|
|
406
|
+
expect(responses.length).toBe(1);
|
|
407
|
+
expect(responses[0]).toMatchObject({
|
|
408
|
+
status: 500
|
|
409
|
+
});
|
|
410
|
+
expect(responses[0]).toHaveProperty('errormessage');
|
|
411
|
+
expect(responses[0].errormessage).toContain('Internal Server Error');
|
|
412
|
+
});
|
|
413
|
+
it('should handle retryable error (error code 10006) in batch mode', async () => {
|
|
414
|
+
(0, nock_1.default)(`https://${settings.subdomain}.rest.marketingcloudapis.com`)
|
|
415
|
+
.post(`/hub/v1/dataevents/${dataExtensionId}/rowset`)
|
|
416
|
+
.reply(400, {
|
|
417
|
+
message: 'Unable to save rows for data extension ID',
|
|
418
|
+
errorcode: 10006
|
|
419
|
+
});
|
|
420
|
+
const events = [
|
|
421
|
+
(0, actions_core_1.createTestEvent)({
|
|
422
|
+
type: 'identify',
|
|
423
|
+
userId: 'user1',
|
|
424
|
+
traits: {
|
|
425
|
+
keys: { contactKey: 'user1', id: 'U1' },
|
|
426
|
+
values: { firstName: 'User', lastName: 'One' }
|
|
427
|
+
}
|
|
428
|
+
})
|
|
429
|
+
];
|
|
430
|
+
const mapping = {
|
|
431
|
+
keys: { '@path': '$.traits.keys' },
|
|
432
|
+
values: { '@path': '$.traits.values' },
|
|
433
|
+
onMappingSave: {
|
|
434
|
+
inputs: {},
|
|
435
|
+
outputs: {
|
|
436
|
+
id: dataExtensionId
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
};
|
|
440
|
+
const responses = await testDestination.executeBatch('contactDataExtensionV2', {
|
|
441
|
+
events,
|
|
442
|
+
settings,
|
|
443
|
+
mapping
|
|
444
|
+
});
|
|
445
|
+
expect(responses.length).toBe(1);
|
|
446
|
+
expect(responses[0]).toMatchObject({
|
|
447
|
+
status: 500,
|
|
448
|
+
errortype: 'INTERNAL_SERVER_ERROR'
|
|
449
|
+
});
|
|
450
|
+
});
|
|
451
|
+
it('should handle multistatus responses with partial failures', async () => {
|
|
452
|
+
(0, nock_1.default)(`https://${settings.subdomain}.rest.marketingcloudapis.com`)
|
|
453
|
+
.post(`/hub/v1/dataevents/${dataExtensionId}/rowset`)
|
|
454
|
+
.reply(400, {
|
|
455
|
+
message: 'Partial failure',
|
|
456
|
+
additionalErrors: [
|
|
457
|
+
{
|
|
458
|
+
message: 'Contact key already exists'
|
|
459
|
+
}
|
|
460
|
+
]
|
|
461
|
+
});
|
|
462
|
+
const events = [
|
|
463
|
+
(0, actions_core_1.createTestEvent)({
|
|
464
|
+
type: 'identify',
|
|
465
|
+
userId: 'user1',
|
|
466
|
+
traits: {
|
|
467
|
+
keys: { contactKey: 'user1', id: 'U1' },
|
|
468
|
+
values: { firstName: 'User', lastName: 'One' }
|
|
469
|
+
}
|
|
470
|
+
}),
|
|
471
|
+
(0, actions_core_1.createTestEvent)({
|
|
472
|
+
type: 'identify',
|
|
473
|
+
userId: 'user2',
|
|
474
|
+
traits: {
|
|
475
|
+
keys: { contactKey: 'user2', id: 'U2' },
|
|
476
|
+
values: { firstName: 'User', lastName: 'Two' }
|
|
477
|
+
}
|
|
478
|
+
})
|
|
479
|
+
];
|
|
480
|
+
const mapping = {
|
|
481
|
+
keys: { '@path': '$.traits.keys' },
|
|
482
|
+
values: { '@path': '$.traits.values' },
|
|
483
|
+
onMappingSave: {
|
|
484
|
+
inputs: {},
|
|
485
|
+
outputs: {
|
|
486
|
+
id: dataExtensionId
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
};
|
|
490
|
+
const responses = await testDestination.executeBatch('contactDataExtensionV2', {
|
|
491
|
+
events,
|
|
492
|
+
settings,
|
|
493
|
+
mapping
|
|
494
|
+
});
|
|
495
|
+
expect(responses.length).toBe(2);
|
|
496
|
+
expect(responses[0]).toMatchObject({
|
|
497
|
+
status: 400,
|
|
498
|
+
errormessage: 'Contact key already exists'
|
|
499
|
+
});
|
|
500
|
+
expect(responses[1]).toMatchObject({
|
|
501
|
+
status: 400,
|
|
502
|
+
errormessage: 'Contact key already exists'
|
|
503
|
+
});
|
|
504
|
+
});
|
|
505
|
+
});
|
|
506
|
+
describe('Dynamic Fields', () => {
|
|
507
|
+
it('should return primary key fields for keys.__keys__', async () => {
|
|
508
|
+
(0, nock_1.default)(`https://${settings.subdomain}.auth.marketingcloudapis.com`).post('/v2/token').reply(200, {
|
|
509
|
+
access_token: 'test-access-token',
|
|
510
|
+
token_type: 'Bearer',
|
|
511
|
+
expires_in: 3600
|
|
512
|
+
});
|
|
513
|
+
(0, nock_1.default)(`https://${settings.subdomain}.rest.marketingcloudapis.com`)
|
|
514
|
+
.get(`/data/v1/customobjects/${dataExtensionId}/fields`)
|
|
515
|
+
.reply(200, {
|
|
516
|
+
fields: [
|
|
517
|
+
{ name: 'contactKey', isPrimaryKey: true },
|
|
518
|
+
{ name: 'id', isPrimaryKey: true },
|
|
519
|
+
{ name: 'email', isPrimaryKey: false },
|
|
520
|
+
{ name: 'firstName', isPrimaryKey: false }
|
|
521
|
+
]
|
|
522
|
+
});
|
|
523
|
+
const response = (await testDestination.testDynamicField('contactDataExtensionV2', 'keys.__keys__', {
|
|
524
|
+
settings,
|
|
525
|
+
payload: {
|
|
526
|
+
onMappingSave: {
|
|
527
|
+
outputs: {
|
|
528
|
+
id: dataExtensionId
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
}));
|
|
533
|
+
expect(response.choices).toHaveLength(2);
|
|
534
|
+
expect(response.choices).toEqual(expect.arrayContaining([
|
|
535
|
+
{ value: 'contactKey', label: 'contactKey' },
|
|
536
|
+
{ value: 'id', label: 'id' }
|
|
537
|
+
]));
|
|
538
|
+
});
|
|
539
|
+
it('should return non-primary key fields for values.__keys__', async () => {
|
|
540
|
+
(0, nock_1.default)(`https://${settings.subdomain}.auth.marketingcloudapis.com`).post('/v2/token').reply(200, {
|
|
541
|
+
access_token: 'test-access-token',
|
|
542
|
+
token_type: 'Bearer',
|
|
543
|
+
expires_in: 3600
|
|
544
|
+
});
|
|
545
|
+
(0, nock_1.default)(`https://${settings.subdomain}.rest.marketingcloudapis.com`)
|
|
546
|
+
.get(`/data/v1/customobjects/${dataExtensionId}/fields`)
|
|
547
|
+
.reply(200, {
|
|
548
|
+
fields: [
|
|
549
|
+
{ name: 'contactKey', isPrimaryKey: true },
|
|
550
|
+
{ name: 'email', isPrimaryKey: false },
|
|
551
|
+
{ name: 'firstName', isPrimaryKey: false },
|
|
552
|
+
{ name: 'lastName', isPrimaryKey: false }
|
|
553
|
+
]
|
|
554
|
+
});
|
|
555
|
+
const response = (await testDestination.testDynamicField('contactDataExtensionV2', 'values.__keys__', {
|
|
556
|
+
settings,
|
|
557
|
+
payload: {
|
|
558
|
+
onMappingSave: {
|
|
559
|
+
outputs: {
|
|
560
|
+
id: dataExtensionId
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}));
|
|
565
|
+
expect(response.choices).toHaveLength(3);
|
|
566
|
+
expect(response.choices).toEqual(expect.arrayContaining([
|
|
567
|
+
{ value: 'email', label: 'email' },
|
|
568
|
+
{ value: 'firstName', label: 'firstName' },
|
|
569
|
+
{ value: 'lastName', label: 'lastName' }
|
|
570
|
+
]));
|
|
571
|
+
});
|
|
572
|
+
it('should return error when no data extension ID is provided', async () => {
|
|
573
|
+
const response = (await testDestination.testDynamicField('contactDataExtensionV2', 'keys.__keys__', {
|
|
574
|
+
settings,
|
|
575
|
+
payload: {}
|
|
576
|
+
}));
|
|
577
|
+
expect(response.choices).toHaveLength(0);
|
|
578
|
+
expect(response.error).toEqual({
|
|
579
|
+
message: 'No Data Extension ID provided',
|
|
580
|
+
code: 'BAD_REQUEST'
|
|
581
|
+
});
|
|
582
|
+
});
|
|
583
|
+
it('should work with retlOnMappingSave for keys.__keys__', async () => {
|
|
584
|
+
(0, nock_1.default)(`https://${settings.subdomain}.auth.marketingcloudapis.com`).post('/v2/token').reply(200, {
|
|
585
|
+
access_token: 'test-access-token',
|
|
586
|
+
token_type: 'Bearer',
|
|
587
|
+
expires_in: 3600
|
|
588
|
+
});
|
|
589
|
+
(0, nock_1.default)(`https://${settings.subdomain}.rest.marketingcloudapis.com`)
|
|
590
|
+
.get(`/data/v1/customobjects/${dataExtensionId}/fields`)
|
|
591
|
+
.reply(200, {
|
|
592
|
+
fields: [
|
|
593
|
+
{ name: 'contactKey', isPrimaryKey: true },
|
|
594
|
+
{ name: 'subscriber_key', isPrimaryKey: true },
|
|
595
|
+
{ name: 'first_name', isPrimaryKey: false }
|
|
596
|
+
]
|
|
597
|
+
});
|
|
598
|
+
const response = (await testDestination.testDynamicField('contactDataExtensionV2', 'keys.__keys__', {
|
|
599
|
+
settings,
|
|
600
|
+
payload: {
|
|
601
|
+
retlOnMappingSave: {
|
|
602
|
+
outputs: {
|
|
603
|
+
id: dataExtensionId
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
}));
|
|
608
|
+
expect(response.choices).toHaveLength(2);
|
|
609
|
+
expect(response.choices).toEqual(expect.arrayContaining([
|
|
610
|
+
{ value: 'contactKey', label: 'contactKey' },
|
|
611
|
+
{ value: 'subscriber_key', label: 'subscriber_key' }
|
|
612
|
+
]));
|
|
613
|
+
});
|
|
614
|
+
it('should work with retlOnMappingSave for values.__keys__', async () => {
|
|
615
|
+
(0, nock_1.default)(`https://${settings.subdomain}.auth.marketingcloudapis.com`).post('/v2/token').reply(200, {
|
|
616
|
+
access_token: 'test-access-token',
|
|
617
|
+
token_type: 'Bearer',
|
|
618
|
+
expires_in: 3600
|
|
619
|
+
});
|
|
620
|
+
(0, nock_1.default)(`https://${settings.subdomain}.rest.marketingcloudapis.com`)
|
|
621
|
+
.get(`/data/v1/customobjects/${dataExtensionId}/fields`)
|
|
622
|
+
.reply(200, {
|
|
623
|
+
fields: [
|
|
624
|
+
{ name: 'contactKey', isPrimaryKey: true },
|
|
625
|
+
{ name: 'email', isPrimaryKey: false },
|
|
626
|
+
{ name: 'first_name', isPrimaryKey: false },
|
|
627
|
+
{ name: 'last_name', isPrimaryKey: false }
|
|
628
|
+
]
|
|
629
|
+
});
|
|
630
|
+
const response = (await testDestination.testDynamicField('contactDataExtensionV2', 'values.__keys__', {
|
|
631
|
+
settings,
|
|
632
|
+
payload: {
|
|
633
|
+
retlOnMappingSave: {
|
|
634
|
+
outputs: {
|
|
635
|
+
id: dataExtensionId
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
}));
|
|
640
|
+
expect(response.choices).toHaveLength(3);
|
|
641
|
+
expect(response.choices).toEqual(expect.arrayContaining([
|
|
642
|
+
{ value: 'email', label: 'email' },
|
|
643
|
+
{ value: 'first_name', label: 'first_name' },
|
|
644
|
+
{ value: 'last_name', label: 'last_name' }
|
|
645
|
+
]));
|
|
646
|
+
});
|
|
647
|
+
});
|
|
648
|
+
});
|
|
649
|
+
});
|
|
650
|
+
//# sourceMappingURL=contactDataExtensionV2.test.js.map
|