@segment/action-destinations 3.477.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.
Files changed (84) hide show
  1. package/dist/destinations/klaviyo/addProfileToList/index.js +1 -1
  2. package/dist/destinations/klaviyo/addProfileToList/index.js.map +1 -1
  3. package/dist/destinations/klaviyo/properties.js +10 -2
  4. package/dist/destinations/klaviyo/properties.js.map +1 -1
  5. package/dist/destinations/klaviyo/removeProfile/index.js +1 -1
  6. package/dist/destinations/klaviyo/removeProfile/index.js.map +1 -1
  7. package/dist/destinations/klaviyo/removeProfileFromList/index.js +1 -1
  8. package/dist/destinations/klaviyo/removeProfileFromList/index.js.map +1 -1
  9. package/dist/destinations/klaviyo/subscribeProfile/generated-types.d.ts +1 -0
  10. package/dist/destinations/klaviyo/subscribeProfile/index.js +6 -0
  11. package/dist/destinations/klaviyo/subscribeProfile/index.js.map +1 -1
  12. package/dist/destinations/klaviyo/trackEvent/index.js +1 -1
  13. package/dist/destinations/klaviyo/trackEvent/index.js.map +1 -1
  14. package/dist/destinations/klaviyo/unsubscribeProfile/generated-types.d.ts +1 -0
  15. package/dist/destinations/klaviyo/unsubscribeProfile/index.js +6 -0
  16. package/dist/destinations/klaviyo/unsubscribeProfile/index.js.map +1 -1
  17. package/dist/destinations/klaviyo/upsertProfile/index.js +1 -1
  18. package/dist/destinations/klaviyo/upsertProfile/index.js.map +1 -1
  19. package/dist/destinations/klime/index.d.ts +1 -1
  20. package/dist/destinations/klime/index.js +25 -1
  21. package/dist/destinations/klime/index.js.map +1 -1
  22. package/dist/destinations/liveramp-audiences/awsClient.js +6 -1
  23. package/dist/destinations/liveramp-audiences/awsClient.js.map +1 -1
  24. package/dist/destinations/pendo-audiences/constants.d.ts +22 -3
  25. package/dist/destinations/pendo-audiences/constants.js +23 -4
  26. package/dist/destinations/pendo-audiences/constants.js.map +1 -1
  27. package/dist/destinations/pendo-audiences/functions.d.ts +4 -2
  28. package/dist/destinations/pendo-audiences/functions.js +16 -5
  29. package/dist/destinations/pendo-audiences/functions.js.map +1 -1
  30. package/dist/destinations/pendo-audiences/generated-types.d.ts +1 -0
  31. package/dist/destinations/pendo-audiences/index.js +19 -8
  32. package/dist/destinations/pendo-audiences/index.js.map +1 -1
  33. package/dist/destinations/pendo-audiences/syncAudience/fields.js +2 -2
  34. package/dist/destinations/pendo-audiences/syncAudience/functions.d.ts +1 -1
  35. package/dist/destinations/pendo-audiences/syncAudience/functions.js +17 -35
  36. package/dist/destinations/pendo-audiences/syncAudience/functions.js.map +1 -1
  37. package/dist/destinations/pendo-audiences/syncAudience/index.js +4 -4
  38. package/dist/destinations/pendo-audiences/syncAudience/index.js.map +1 -1
  39. package/dist/destinations/pendo-audiences/syncAudience/types.d.ts +0 -3
  40. package/dist/destinations/pendo-audiences/types.d.ts +2 -4
  41. package/dist/destinations/salesforce-marketing-cloud/_tests_/contactDataExtensionV2.test.d.ts +1 -0
  42. package/dist/destinations/salesforce-marketing-cloud/_tests_/contactDataExtensionV2.test.js +650 -0
  43. package/dist/destinations/salesforce-marketing-cloud/_tests_/contactDataExtensionV2.test.js.map +1 -0
  44. package/dist/destinations/salesforce-marketing-cloud/_tests_/dataExtensionV2.test.d.ts +1 -0
  45. package/dist/destinations/salesforce-marketing-cloud/_tests_/dataExtensionV2.test.js +501 -0
  46. package/dist/destinations/salesforce-marketing-cloud/_tests_/dataExtensionV2.test.js.map +1 -0
  47. package/dist/destinations/the-trade-desk-crm/awsClient.d.ts +6 -1
  48. package/dist/destinations/the-trade-desk-crm/awsClient.js +8 -2
  49. package/dist/destinations/the-trade-desk-crm/awsClient.js.map +1 -1
  50. package/dist/destinations/the-trade-desk-crm/functions.d.ts +16 -1
  51. package/dist/destinations/the-trade-desk-crm/functions.js +7 -2
  52. package/dist/destinations/the-trade-desk-crm/functions.js.map +1 -1
  53. package/dist/destinations/the-trade-desk-crm/syncAudience/index.js +8 -6
  54. package/dist/destinations/the-trade-desk-crm/syncAudience/index.js.map +1 -1
  55. package/dist/destinations/yahoo-audiences/index.js +1 -14
  56. package/dist/destinations/yahoo-audiences/index.js.map +1 -1
  57. package/dist/destinations/yahoo-audiences/types.d.ts +3 -0
  58. package/dist/destinations/yahoo-audiences/utils-tax.d.ts +1 -1
  59. package/dist/destinations/yahoo-audiences/utils-tax.js +25 -15
  60. package/dist/destinations/yahoo-audiences/utils-tax.js.map +1 -1
  61. package/dist/destinations/youappi-audiences/constants.d.ts +1 -0
  62. package/dist/destinations/youappi-audiences/constants.js +5 -0
  63. package/dist/destinations/youappi-audiences/constants.js.map +1 -0
  64. package/dist/destinations/youappi-audiences/generated-types.d.ts +3 -0
  65. package/dist/destinations/youappi-audiences/generated-types.js +3 -0
  66. package/dist/destinations/youappi-audiences/generated-types.js.map +1 -0
  67. package/dist/destinations/youappi-audiences/index.d.ts +4 -0
  68. package/dist/destinations/youappi-audiences/index.js +45 -0
  69. package/dist/destinations/youappi-audiences/index.js.map +1 -0
  70. package/dist/destinations/youappi-audiences/sync/functions.d.ts +7 -0
  71. package/dist/destinations/youappi-audiences/sync/functions.js +105 -0
  72. package/dist/destinations/youappi-audiences/sync/functions.js.map +1 -0
  73. package/dist/destinations/youappi-audiences/sync/generated-types.d.ts +12 -0
  74. package/dist/destinations/youappi-audiences/sync/generated-types.js +3 -0
  75. package/dist/destinations/youappi-audiences/sync/generated-types.js.map +1 -0
  76. package/dist/destinations/youappi-audiences/sync/index.d.ts +5 -0
  77. package/dist/destinations/youappi-audiences/sync/index.js +101 -0
  78. package/dist/destinations/youappi-audiences/sync/index.js.map +1 -0
  79. package/dist/destinations/youappi-audiences/sync/types.d.ts +14 -0
  80. package/dist/destinations/youappi-audiences/sync/types.js +3 -0
  81. package/dist/destinations/youappi-audiences/sync/types.js.map +1 -0
  82. package/dist/lib/test-data.js +24 -7
  83. package/dist/lib/test-data.js.map +1 -1
  84. 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