diff --git a/test/integrations/destinations/koala/processor/data.ts b/test/integrations/destinations/koala/processor/data.ts index 9c1ea97a77..b866353066 100644 --- a/test/integrations/destinations/koala/processor/data.ts +++ b/test/integrations/destinations/koala/processor/data.ts @@ -31,7 +31,7 @@ export const data = [ value: 10, }, context: { - network: 'wifi' + network: 'wifi', }, originalTimestamp: '2024-01-23T08:35:17.562Z', sentAt: '2024-01-23T08:35:17.562Z', @@ -58,20 +58,22 @@ export const data = [ JSON: { ip: '192.11.22.33', email: 'johndoe@somemail.com', - events: [{ - type: 'track', - event: 'User Signed Up', - sent_at: '2024-01-23T08:35:17.562Z', - message_id: '84e26acc-56a5-4835-8233-591137fca468', - properties: { - email: 'johndoe@somemail.com', - label: 'test', - value: 10, - }, - context: { - network: 'wifi' + events: [ + { + type: 'track', + event: 'User Signed Up', + sent_at: '2024-01-23T08:35:17.562Z', + message_id: '84e26acc-56a5-4835-8233-591137fca468', + properties: { + email: 'johndoe@somemail.com', + label: 'test', + value: 10, + }, + context: { + network: 'wifi', + }, }, - }] + ], }, }, endpoint: 'https://api2.getkoala.com/web/projects/kkooaallaa321/batch', @@ -127,7 +129,7 @@ export const data = [ postalCode: '94107', }, email: 'johndoe@somemail.com', - ko_profile_id: 'xxxx-2222-xxxx-xxxx' + ko_profile_id: 'xxxx-2222-xxxx-xxxx', }, originalTimestamp: '2024-01-23T08:35:17.342Z', sentAt: '2024-01-23T08:35:35.234Z', @@ -153,20 +155,22 @@ export const data = [ JSON: { email: 'johndoe@somemail.com', profile_id: 'xxxx-2222-xxxx-xxxx', - identifies: [{ - type: 'identify', - sent_at: '2024-01-23T08:35:17.342Z', - traits: { - FirstName: 'John', - LastName: 'Doe', - address: { - city: 'San Francisco', - state: 'CA', - postalCode: '94107', + identifies: [ + { + type: 'identify', + sent_at: '2024-01-23T08:35:17.342Z', + traits: { + FirstName: 'John', + LastName: 'Doe', + address: { + city: 'San Francisco', + state: 'CA', + postalCode: '94107', + }, + email: 'johndoe@somemail.com', }, - email: 'johndoe@somemail.com', }, - }], + ], }, }, endpoint: 'https://api2.getkoala.com/web/projects/kkooaallaa321/batch', diff --git a/test/integrations/destinations/koala/router/data.ts b/test/integrations/destinations/koala/router/data.ts index fb0db3e3fb..f998f48dc4 100644 --- a/test/integrations/destinations/koala/router/data.ts +++ b/test/integrations/destinations/koala/router/data.ts @@ -27,14 +27,14 @@ export const data = [ type: 'track', messageId: '84e26acc-56a5-4835-8233-591137fca468', traits: { - email: 'johndoe@somemail.com' + email: 'johndoe@somemail.com', }, properties: { label: 'test', value: 10, }, context: { - network: 'wifi' + network: 'wifi', }, originalTimestamp: '2024-01-23T08:35:17.562Z', sentAt: '2024-01-23T08:35:17.562Z', @@ -44,8 +44,8 @@ export const data = [ jobId: 1, userId: 'u1', destinationId: 'destId', - workspaceId: 'wspId' - } + workspaceId: 'wspId', + }, }, { destination: { @@ -65,14 +65,14 @@ export const data = [ type: 'track', messageId: '8bc79b03-2a5c-4615-b2da-54c0aaaaaae8', traits: { - ko_profile_id: '123456' + ko_profile_id: '123456', }, properties: { attr1: 'foo', - attr2: 'bar' + attr2: 'bar', }, context: { - network: 'wifi' + network: 'wifi', }, originalTimestamp: '2024-01-23T08:35:17.562Z', sentAt: '2024-01-23T08:35:17.562Z', @@ -82,14 +82,14 @@ export const data = [ jobId: 2, userId: 'u1', destinationId: 'destId', - workspaceId: 'wspId' - } + workspaceId: 'wspId', + }, }, ], destType: 'koala', }, - method: 'POST' - } + method: 'POST', + }, }, output: { response: { @@ -105,19 +105,21 @@ export const data = [ JSON: { ip: '192.11.22.33', email: 'johndoe@somemail.com', - events: [{ - type: 'track', - event: 'User Signed Up', - sent_at: '2024-01-23T08:35:17.562Z', - message_id: '84e26acc-56a5-4835-8233-591137fca468', - properties: { - label: 'test', - value: 10, + events: [ + { + type: 'track', + event: 'User Signed Up', + sent_at: '2024-01-23T08:35:17.562Z', + message_id: '84e26acc-56a5-4835-8233-591137fca468', + properties: { + label: 'test', + value: 10, + }, + context: { + network: 'wifi', + }, }, - context: { - network: 'wifi' - }, - }] + ], }, }, endpoint: 'https://api2.getkoala.com/web/projects/kkooaallaa321/batch', @@ -153,19 +155,21 @@ export const data = [ JSON: { ip: '192.11.55.1', profile_id: '123456', - events: [{ - type: 'track', - event: 'User Deleted account', - sent_at: '2024-01-23T08:35:17.562Z', - message_id: '8bc79b03-2a5c-4615-b2da-54c0aaaaaae8', - properties: { - attr1: 'foo', - attr2: 'bar' - }, - context: { - network: 'wifi' + events: [ + { + type: 'track', + event: 'User Deleted account', + sent_at: '2024-01-23T08:35:17.562Z', + message_id: '8bc79b03-2a5c-4615-b2da-54c0aaaaaae8', + properties: { + attr1: 'foo', + attr2: 'bar', + }, + context: { + network: 'wifi', + }, }, - }] + ], }, }, endpoint: 'https://api2.getkoala.com/web/projects/kkooaallaa321/batch', @@ -191,10 +195,10 @@ export const data = [ }, }, }, - } - ] - } - } - } - } -] + }, + ], + }, + }, + }, + }, +]; diff --git a/test/integrations/destinations/the_trade_desk/common.ts b/test/integrations/destinations/the_trade_desk/common.ts index 28f46df829..08ba0ee6ea 100644 --- a/test/integrations/destinations/the_trade_desk/common.ts +++ b/test/integrations/destinations/the_trade_desk/common.ts @@ -5,8 +5,7 @@ const destTypeInUpperCase = 'THE_TRADE_DESK'; const advertiserId = 'test-advertiser-id'; const dataProviderId = 'rudderstack'; const segmentName = 'test-segment'; - -const trackerId = 'test-trackerId'; +const firstPartyDataEndpoint = 'https://sin-data.adsrvr.org/data/advertiser'; const sampleDestination: Destination = { Config: { @@ -48,6 +47,22 @@ const sampleContext = { sources: sampleSource, }; +const proxyV1AbortableErrorStatTags = { + destType: destTypeInUpperCase, + destinationId: 'default-destinationId', + errorCategory: 'network', + errorType: 'aborted', + feature: 'dataDelivery', + implementation: 'native', + module: 'destination', + workspaceId: 'default-workspaceId', +}; + +const { errorType: _, ...proxyV1PlatformErrorStatTags } = proxyV1AbortableErrorStatTags; +proxyV1PlatformErrorStatTags.errorCategory = 'platform'; + +const proxyV1RetryableErrorStatTags = { ...proxyV1AbortableErrorStatTags, errorType: 'retryable' }; + export { destType, destTypeInUpperCase, @@ -56,4 +71,8 @@ export { segmentName, sampleDestination, sampleContext, + proxyV1AbortableErrorStatTags, + proxyV1PlatformErrorStatTags, + proxyV1RetryableErrorStatTags, + firstPartyDataEndpoint, }; diff --git a/test/integrations/destinations/the_trade_desk/delivery/business.ts b/test/integrations/destinations/the_trade_desk/delivery/business.ts new file mode 100644 index 0000000000..0406a5f0bc --- /dev/null +++ b/test/integrations/destinations/the_trade_desk/delivery/business.ts @@ -0,0 +1,175 @@ +import { ProxyV1TestData } from '../../../testTypes'; +import { generateProxyV1Payload, generateMetadata } from '../../../testUtils'; +import { + destType, + advertiserId, + dataProviderId, + segmentName, + sampleDestination, + proxyV1AbortableErrorStatTags, + firstPartyDataEndpoint, +} from '../common'; + +const validRequestPayload1 = { + AdvertiserId: advertiserId, + DataProviderId: dataProviderId, + Items: [ + { + DAID: 'test-daid-1', + Data: [ + { + Name: segmentName, + TTLInMinutes: 43200, + }, + ], + }, + { + Data: [ + { + Name: segmentName, + TTLInMinutes: 43200, + }, + ], + UID2: 'test-uid2-1', + }, + { + DAID: 'test-daid-2', + Data: [ + { + Name: segmentName, + TTLInMinutes: 0, + }, + ], + }, + { + Data: [ + { + Name: segmentName, + TTLInMinutes: 0, + }, + ], + UID2: 'test-uid2-2', + }, + ], +}; + +const invalidRequestPayload1 = { + AdvertiserId: advertiserId, + DataProviderId: dataProviderId, + Items: [ + { + DAID: 'test-daid', + Data: [ + { + Name: segmentName, + TTLInMinutes: 43200, + }, + ], + }, + { + Data: [ + { + Name: segmentName, + TTLInMinutes: 43200, + }, + ], + UID2: 'test-invalid-uid2', + }, + ], +}; + +const metadataArray = [generateMetadata(1)]; + +export const businessProxyV1: ProxyV1TestData[] = [ + { + id: 'ttd_v1_scenario_1', + name: destType, + description: + '[Proxy v1 API] :: Test for a valid request - Successful delivery of Add/Remove IDs to Trade Desk', + successCriteria: 'Should return 200 with no error with destination response', + scenario: 'Business', + feature: 'dataDelivery', + module: 'destination', + version: 'v1', + input: { + request: { + body: generateProxyV1Payload( + { + headers: {}, + params: {}, + JSON: validRequestPayload1, + endpoint: firstPartyDataEndpoint, + }, + metadataArray, + sampleDestination.Config, + ), + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: { + status: 200, + message: 'Request Processed Successfully', + response: [ + { + statusCode: 200, + metadata: generateMetadata(1), + error: '{}', + }, + ], + }, + }, + }, + }, + }, + { + id: 'ttd_v1_scenario_2', + name: destType, + description: + '[Proxy v1 API] :: Test for invalid ID - where the destination responds with 200 with invalid ID', + successCriteria: 'Should return 400 with error with destination response', + scenario: 'Business', + feature: 'dataDelivery', + module: 'destination', + version: 'v1', + input: { + request: { + body: generateProxyV1Payload( + { + headers: {}, + params: {}, + JSON: invalidRequestPayload1, + endpoint: firstPartyDataEndpoint, + }, + metadataArray, + sampleDestination.Config, + ), + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: { + message: + 'Request failed with status: 200 due to {"FailedLines":[{"ErrorCode":"MissingUserId","Message":"Invalid UID2, item #2"}]}', + response: [ + { + error: + '{"FailedLines":[{"ErrorCode":"MissingUserId","Message":"Invalid UID2, item #2"}]}', + metadata: generateMetadata(1), + statusCode: 400, + }, + ], + statTags: proxyV1AbortableErrorStatTags, + status: 400, + }, + }, + }, + }, + }, +]; diff --git a/test/integrations/destinations/the_trade_desk/delivery/data.ts b/test/integrations/destinations/the_trade_desk/delivery/data.ts index 320eb6dcfe..5099eafce7 100644 --- a/test/integrations/destinations/the_trade_desk/delivery/data.ts +++ b/test/integrations/destinations/the_trade_desk/delivery/data.ts @@ -1,248 +1,3 @@ -import { - destType, - destTypeInUpperCase, - advertiserId, - dataProviderId, - segmentName, - sampleDestination, -} from '../common'; - -beforeAll(() => { - process.env.THE_TRADE_DESK_DATA_PROVIDER_SECRET_KEY = 'mockedDataProviderSecretKey'; -}); - -afterAll(() => { - delete process.env.THE_TRADE_DESK_DATA_PROVIDER_SECRET_KEY; -}); - -export const data = [ - { - name: destType, - description: 'Successful delivery of Add/Remove IDs to/from Trade Desk', - feature: 'dataDelivery', - module: 'destination', - version: 'v0', - input: { - request: { - body: { - version: '1', - type: 'REST', - method: 'POST', - endpoint: 'https://sin-data.adsrvr.org/data/advertiser', - headers: {}, - params: {}, - destinationConfig: sampleDestination.Config, - body: { - JSON: { - AdvertiserId: advertiserId, - DataProviderId: dataProviderId, - Items: [ - { - DAID: 'test-daid-1', - Data: [ - { - Name: segmentName, - TTLInMinutes: 43200, - }, - ], - }, - { - Data: [ - { - Name: segmentName, - TTLInMinutes: 43200, - }, - ], - UID2: 'test-uid2-1', - }, - { - DAID: 'test-daid-2', - Data: [ - { - Name: segmentName, - TTLInMinutes: 0, - }, - ], - }, - { - Data: [ - { - Name: segmentName, - TTLInMinutes: 0, - }, - ], - UID2: 'test-uid2-2', - }, - ], - }, - JSON_ARRAY: {}, - XML: {}, - FORM: {}, - }, - files: {}, - userId: '', - }, - method: 'POST', - }, - }, - output: { - response: { - status: 200, - body: { - output: { - destinationResponse: { - response: {}, - status: 200, - }, - message: 'Request Processed Successfully', - status: 200, - }, - }, - }, - }, - }, - { - name: destType, - description: 'Error response from The Trade Desk due to invalid IDs', - feature: 'dataDelivery', - module: 'destination', - version: 'v0', - input: { - request: { - body: { - version: '1', - type: 'REST', - method: 'POST', - endpoint: 'https://sin-data.adsrvr.org/data/advertiser', - headers: {}, - params: {}, - destinationConfig: sampleDestination.Config, - body: { - JSON: { - AdvertiserId: advertiserId, - DataProviderId: dataProviderId, - Items: [ - { - DAID: 'test-daid', - Data: [ - { - Name: segmentName, - TTLInMinutes: 43200, - }, - ], - }, - { - Data: [ - { - Name: segmentName, - TTLInMinutes: 43200, - }, - ], - UID2: 'test-invalid-uid2', - }, - ], - }, - JSON_ARRAY: {}, - XML: {}, - FORM: {}, - }, - files: {}, - userId: '', - }, - method: 'POST', - }, - }, - output: { - response: { - status: 400, - body: { - output: { - destinationResponse: { - response: { - FailedLines: [{ ErrorCode: 'MissingUserId', Message: 'Invalid UID2, item #2' }], - }, - status: 200, - }, - message: - 'Request failed with status: 200 due to {"FailedLines":[{"ErrorCode":"MissingUserId","Message":"Invalid UID2, item #2"}]}', - statTags: { - destType: destTypeInUpperCase, - destinationId: 'Non-determininable', - errorCategory: 'network', - errorType: 'aborted', - feature: 'dataDelivery', - implementation: 'native', - module: 'destination', - workspaceId: 'Non-determininable', - }, - status: 400, - }, - }, - }, - }, - }, - { - name: destType, - description: - 'Missing advertiser secret key in destination config from proxy request from server', - feature: 'dataDelivery', - module: 'destination', - version: 'v0', - input: { - request: { - body: { - version: '1', - type: 'REST', - method: 'POST', - endpoint: 'https://sin-data.adsrvr.org/data/advertiser', - headers: {}, - params: {}, - body: { - JSON: { - AdvertiserId: advertiserId, - DataProviderId: dataProviderId, - Items: [ - { - DAID: 'test-daid-1', - Data: [ - { - Name: segmentName, - TTLInMinutes: 43200, - }, - ], - }, - ], - }, - JSON_ARRAY: {}, - XML: {}, - FORM: {}, - }, - files: {}, - userId: '', - }, - method: 'POST', - }, - }, - output: { - response: { - status: 400, - body: { - output: { - destinationResponse: '', - message: 'Advertiser secret key is missing in destination config. Aborting', - statTags: { - destType: destTypeInUpperCase, - destinationId: 'Non-determininable', - errorCategory: 'platform', - feature: 'dataDelivery', - implementation: 'native', - module: 'destination', - workspaceId: 'Non-determininable', - }, - status: 400, - }, - }, - }, - }, - }, -]; +import { businessProxyV1 } from './business'; +import { otherProxyV1 } from './other'; +export const data = [...businessProxyV1, ...otherProxyV1]; diff --git a/test/integrations/destinations/the_trade_desk/delivery/other.ts b/test/integrations/destinations/the_trade_desk/delivery/other.ts new file mode 100644 index 0000000000..bed10e6ec5 --- /dev/null +++ b/test/integrations/destinations/the_trade_desk/delivery/other.ts @@ -0,0 +1,290 @@ +import { ProxyV1TestData } from '../../../testTypes'; +import { generateProxyV1Payload, generateMetadata } from '../../../testUtils'; +import { + destType, + advertiserId, + dataProviderId, + segmentName, + proxyV1PlatformErrorStatTags, + proxyV1RetryableErrorStatTags, + firstPartyDataEndpoint, + sampleDestination, +} from '../common'; +import { envMock } from '../mocks'; + +envMock(); + +const validRequestPayload1 = { + AdvertiserId: advertiserId, + DataProviderId: dataProviderId, + Items: [ + { + DAID: 'test-daid-1', + Data: [ + { + Name: segmentName, + TTLInMinutes: 43200, + }, + ], + }, + ], +}; + +const metadataArray = [generateMetadata(1)]; + +// https://partner.thetradedesk.com/v3/portal/data/doc/post-data-advertiser-external#error-codes-messages +export const otherProxyV1: ProxyV1TestData[] = [ + { + id: 'ttd_v1_other_scenario_1', + name: destType, + description: + '[Proxy v1 API] :: Missing advertiser secret key in destination config from proxy request from server', + successCriteria: 'Should return 400 with platform error', + scenario: 'Framework', + feature: 'dataDelivery', + module: 'destination', + version: 'v1', + input: { + request: { + body: generateProxyV1Payload( + { + headers: {}, + params: {}, + JSON: validRequestPayload1, + endpoint: firstPartyDataEndpoint, + }, + metadataArray, + ), + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: { + message: 'Advertiser secret key is missing in destination config. Aborting', + response: [ + { + error: 'Advertiser secret key is missing in destination config. Aborting', + metadata: generateMetadata(1), + statusCode: 400, + }, + ], + statTags: proxyV1PlatformErrorStatTags, + status: 400, + }, + }, + }, + }, + }, + { + id: 'ttd_v1_other_scenario_2', + name: destType, + description: + '[Proxy v1 API] :: Scenario for testing Service Unavailable error from destination', + successCriteria: 'Should return 500 status code with error message', + scenario: 'Framework', + feature: 'dataDelivery', + module: 'destination', + version: 'v1', + input: { + request: { + body: generateProxyV1Payload( + { + endpoint: 'https://random_test_url/test_for_service_not_available', + }, + metadataArray, + sampleDestination.Config, + ), + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: { + response: [ + { + error: + '{"error":{"message":"Service Unavailable","description":"The server is currently unable to handle the request due to temporary overloading or maintenance of the server. Please try again later."}}', + statusCode: 503, + metadata: generateMetadata(1), + }, + ], + statTags: proxyV1RetryableErrorStatTags, + message: + 'Request failed with status: 503 due to {"error":{"message":"Service Unavailable","description":"The server is currently unable to handle the request due to temporary overloading or maintenance of the server. Please try again later."}}', + status: 503, + }, + }, + }, + }, + }, + { + id: 'ttd_v1_other_scenario_3', + name: destType, + description: '[Proxy v1 API] :: Scenario for testing Internal Server error from destination', + successCriteria: 'Should return 500 status code with error message', + scenario: 'Framework', + feature: 'dataDelivery', + module: 'destination', + version: 'v1', + input: { + request: { + body: generateProxyV1Payload( + { + endpoint: 'https://random_test_url/test_for_internal_server_error', + }, + metadataArray, + sampleDestination.Config, + ), + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: { + response: [ + { + error: '"Internal Server Error"', + statusCode: 500, + metadata: generateMetadata(1), + }, + ], + statTags: proxyV1RetryableErrorStatTags, + message: 'Request failed with status: 500 due to "Internal Server Error"', + status: 500, + }, + }, + }, + }, + }, + { + id: 'ttd_v1_other_scenario_4', + name: destType, + description: '[Proxy v1 API] :: Scenario for testing Gateway Time Out error from destination', + successCriteria: 'Should return 504 status code with error message', + scenario: 'Framework', + feature: 'dataDelivery', + module: 'destination', + version: 'v1', + input: { + request: { + body: generateProxyV1Payload( + { + endpoint: 'https://random_test_url/test_for_gateway_time_out', + }, + metadataArray, + sampleDestination.Config, + ), + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: { + response: [ + { + error: '"Gateway Timeout"', + statusCode: 504, + metadata: generateMetadata(1), + }, + ], + statTags: proxyV1RetryableErrorStatTags, + message: 'Request failed with status: 504 due to "Gateway Timeout"', + status: 504, + }, + }, + }, + }, + }, + { + id: 'ttd_v1_other_scenario_5', + name: destType, + description: '[Proxy v1 API] :: Scenario for testing null response from destination', + successCriteria: 'Should return 500 status code with error message', + scenario: 'Framework', + feature: 'dataDelivery', + module: 'destination', + version: 'v1', + input: { + request: { + body: generateProxyV1Payload( + { + endpoint: 'https://random_test_url/test_for_null_response', + }, + metadataArray, + sampleDestination.Config, + ), + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: { + response: [ + { + error: '""', + statusCode: 500, + metadata: generateMetadata(1), + }, + ], + statTags: proxyV1RetryableErrorStatTags, + message: 'Request failed with status: 500 due to ""', + status: 500, + }, + }, + }, + }, + }, + { + id: 'ttd_v1_other_scenario_6', + name: destType, + description: + '[Proxy v1 API] :: Scenario for testing null and no status response from destination', + successCriteria: 'Should return 500 status code with error message', + scenario: 'Framework', + feature: 'dataDelivery', + module: 'destination', + version: 'v1', + input: { + request: { + body: generateProxyV1Payload( + { + endpoint: 'https://random_test_url/test_for_null_and_no_status', + }, + metadataArray, + sampleDestination.Config, + ), + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: { + response: [ + { + error: '""', + statusCode: 500, + metadata: generateMetadata(1), + }, + ], + statTags: proxyV1RetryableErrorStatTags, + message: 'Request failed with status: 500 due to ""', + status: 500, + }, + }, + }, + }, + }, +]; diff --git a/test/integrations/destinations/the_trade_desk/mocks.ts b/test/integrations/destinations/the_trade_desk/mocks.ts index ddcbebae88..bf9d910d42 100644 --- a/test/integrations/destinations/the_trade_desk/mocks.ts +++ b/test/integrations/destinations/the_trade_desk/mocks.ts @@ -3,3 +3,12 @@ import config from '../../../../src/cdk/v2/destinations/the_trade_desk/config'; export const defaultMockFns = () => { jest.replaceProperty(config, 'MAX_REQUEST_SIZE_IN_BYTES', 250); }; + +export const envMock = () => { + process.env.THE_TRADE_DESK_DATA_PROVIDER_SECRET_KEY = 'mockedDataProviderSecretKey'; + + // Clean up after all tests are done + afterAll(() => { + delete process.env.THE_TRADE_DESK_DATA_PROVIDER_SECRET_KEY; + }); +};