diff --git a/src/routes/destination.ts b/src/routes/destination.ts index ee19fd1246..3d4be42ff3 100644 --- a/src/routes/destination.ts +++ b/src/routes/destination.ts @@ -1,6 +1,7 @@ import Router from '@koa/router'; import DestinationController from '../controllers/destination'; import RegulationController from '../controllers/regulation'; +import FeatureFlagController from '../middlewares/featureFlag'; import RouteActivationController from '../middlewares/routeActivation'; const router = new Router(); @@ -9,22 +10,25 @@ router.post( '/:version/destinations/:destination', RouteActivationController.isDestinationRouteActive, RouteActivationController.destinationProcFilter, + FeatureFlagController.handle, DestinationController.destinationTransformAtProcessor, ); router.post( '/routerTransform', RouteActivationController.isDestinationRouteActive, RouteActivationController.destinationRtFilter, + FeatureFlagController.handle, DestinationController.destinationTransformAtRouter, ); router.post( '/batch', RouteActivationController.isDestinationRouteActive, RouteActivationController.destinationBatchFilter, + FeatureFlagController.handle, DestinationController.batchProcess, ); router.post('/deleteUsers', RegulationController.deleteUsers); const destinationRoutes = router.routes(); -export default destinationRoutes; \ No newline at end of file +export default destinationRoutes; diff --git a/src/services/destination/nativeIntegration.ts b/src/services/destination/nativeIntegration.ts index 49fb806094..a788b388e4 100644 --- a/src/services/destination/nativeIntegration.ts +++ b/src/services/destination/nativeIntegration.ts @@ -50,7 +50,7 @@ export default class NativeIntegrationDestinationService implements IntegrationD events: ProcessorTransformationRequest[], destinationType: string, version: string, - _requestMetadata: NonNullable, + requestMetadata: NonNullable, ): Promise { const destHandler = FetchHandler.getDestHandler(destinationType, version); const respList: ProcessorTransformationResponse[][] = await Promise.all( @@ -58,7 +58,7 @@ export default class NativeIntegrationDestinationService implements IntegrationD try { const transformedPayloads: | ProcessorTransformationOutput - | ProcessorTransformationOutput[] = await destHandler.process(event); + | ProcessorTransformationOutput[] = await destHandler.process(event, requestMetadata); return DestinationPostTransformationService.handleProcessorTransformSucessEvents( event, transformedPayloads, @@ -88,7 +88,7 @@ export default class NativeIntegrationDestinationService implements IntegrationD events: RouterTransformationRequestData[], destinationType: string, version: string, - _requestMetadata: NonNullable, + requestMetadata: NonNullable, ): Promise { const destHandler = FetchHandler.getDestHandler(destinationType, version); const allDestEvents: NonNullable = groupBy( @@ -106,7 +106,7 @@ export default class NativeIntegrationDestinationService implements IntegrationD ); try { const doRouterTransformationResponse: RouterTransformationResponse[] = - await destHandler.processRouterDest(cloneDeep(destInputArray)); + await destHandler.processRouterDest(cloneDeep(destInputArray), requestMetadata); metaTO.metadata = destInputArray[0].metadata; return DestinationPostTransformationService.handleRouterTransformSuccessEvents( doRouterTransformationResponse, @@ -132,7 +132,7 @@ export default class NativeIntegrationDestinationService implements IntegrationD events: RouterTransformationRequestData[], destinationType: string, version: any, - _requestMetadata: NonNullable, + requestMetadata: NonNullable, ): RouterTransformationResponse[] { const destHandler = FetchHandler.getDestHandler(destinationType, version); if (!destHandler.batch) { @@ -145,7 +145,10 @@ export default class NativeIntegrationDestinationService implements IntegrationD const groupedEvents: RouterTransformationRequestData[][] = Object.values(allDestEvents); const response = groupedEvents.map((destEvents) => { try { - const destBatchedRequests: RouterTransformationResponse[] = destHandler.batch(destEvents); + const destBatchedRequests: RouterTransformationResponse[] = destHandler.batch( + destEvents, + requestMetadata, + ); return destBatchedRequests; } catch (error: any) { const metaTO = this.getTags( diff --git a/src/services/misc.ts b/src/services/misc.ts index fe38b5b2bd..4c3e2ae6da 100644 --- a/src/services/misc.ts +++ b/src/services/misc.ts @@ -30,6 +30,7 @@ export default class MiscService { return { namespace: 'Unknown', cluster: 'Unknown', + features: ctx.state?.features || {}, }; } diff --git a/src/util/errorNotifier/bugsnag.js b/src/util/errorNotifier/bugsnag.js index 09b2cd9f71..a88432f23d 100644 --- a/src/util/errorNotifier/bugsnag.js +++ b/src/util/errorNotifier/bugsnag.js @@ -23,6 +23,7 @@ const { UnhandledStatusCodeError, UnauthorizedError, NetworkInstrumentationError, + FilteredEventsError, } = require('../../v0/util/errorTypes'); const { @@ -48,6 +49,7 @@ const errorTypesDenyList = [ NetworkInstrumentationError, CDKCustomError, DataValidationError, + FilteredEventsError, ]; const pathsDenyList = [ diff --git a/src/v0/destinations/braze/transform.js b/src/v0/destinations/braze/transform.js index 5f651041ea..9816d792f1 100644 --- a/src/v0/destinations/braze/transform.js +++ b/src/v0/destinations/braze/transform.js @@ -22,8 +22,13 @@ const { isHttpStatusSuccess, simpleProcessRouterDestSync, simpleProcessRouterDest, + isNewStatusCodesAccepted, } = require('../../util'); -const { InstrumentationError, NetworkError } = require('../../util/errorTypes'); +const { + InstrumentationError, + NetworkError, + FilteredEventsError, +} = require('../../util/errorTypes'); const { ConfigCategory, mappingConfig, @@ -223,7 +228,13 @@ async function processIdentify(message, destination) { } } -function processTrackWithUserAttributes(message, destination, mappingJson, processParams) { +function processTrackWithUserAttributes( + message, + destination, + mappingJson, + processParams, + reqMetadata, +) { let payload = getUserAttributesObject(message, mappingJson); if (payload && Object.keys(payload).length > 0) { payload = setExternalIdOrAliasObject(payload, message); @@ -236,6 +247,10 @@ function processTrackWithUserAttributes(message, destination, mappingJson, proce ); if (dedupedAttributePayload) { requestJson.attributes = [dedupedAttributePayload]; + } else if (isNewStatusCodesAccepted(reqMetadata)) { + throw new FilteredEventsError( + '[Braze Deduplication]: Duplicate user detected, the user is dropped', + ); } else { throw new InstrumentationError( '[Braze Deduplication]: Duplicate user detected, the user is dropped', @@ -444,7 +459,7 @@ function processAlias(message, destination) { ); } -async function process(event, processParams = { userStore: new Map() }) { +async function process(event, processParams = { userStore: new Map() }, reqMetadata = {}) { let response; const { message, destination } = event; const messageType = message.type.toLowerCase(); @@ -490,6 +505,7 @@ async function process(event, processParams = { userStore: new Map() }) { destination, mappingConfig[category.name], processParams, + reqMetadata, ); break; case EventType.GROUP: diff --git a/src/v0/destinations/braze/util.js b/src/v0/destinations/braze/util.js index 0793ca5891..f9bcdb9496 100644 --- a/src/v0/destinations/braze/util.js +++ b/src/v0/destinations/braze/util.js @@ -22,7 +22,7 @@ const { ALIAS_BRAZE_MAX_REQ_COUNT, TRACK_BRAZE_MAX_REQ_COUNT, } = require('./config'); -const { JSON_MIME_TYPE } = require('../../util/constant'); +const { JSON_MIME_TYPE, HTTP_STATUS_CODES } = require('../../util/constant'); const { isObject } = require('../../util'); const { removeUndefinedValues, getIntegrationsObj } = require('../../util'); const { InstrumentationError } = require('../../util/errorTypes'); @@ -363,11 +363,14 @@ const processBatch = (transformedEvents) => { const purchaseArray = []; const successMetadata = []; const failureResponses = []; + const filteredResponses = []; const subscriptionsArray = []; const mergeUsersArray = []; for (const transformedEvent of transformedEvents) { if (!isHttpStatusSuccess(transformedEvent?.statusCode)) { failureResponses.push(transformedEvent); + } else if (transformedEvent?.statusCode === HTTP_STATUS_CODES.FILTER_EVENTS) { + filteredResponses.push(transformedEvent); } else if (transformedEvent?.batchedRequest?.body?.JSON) { const { attributes, events, purchases, subscription_groups, merge_updates } = transformedEvent.batchedRequest.body.JSON; @@ -446,6 +449,10 @@ const processBatch = (transformedEvents) => { finalResponse.push(...failureResponses); } + if (filteredResponses.length > 0) { + finalResponse.push(...filteredResponses); + } + return finalResponse; }; diff --git a/src/v0/destinations/klaviyo/transform.js b/src/v0/destinations/klaviyo/transform.js index 86d5880e4c..b235748fdd 100644 --- a/src/v0/destinations/klaviyo/transform.js +++ b/src/v0/destinations/klaviyo/transform.js @@ -34,10 +34,10 @@ const { checkInvalidRtTfEvents, handleRtTfSingleEventError, flattenJson, + isNewStatusCodesAccepted, } = require('../../util'); - const { ConfigurationError, InstrumentationError } = require('../../util/errorTypes'); -const { JSON_MIME_TYPE } = require('../../util/constant'); +const { JSON_MIME_TYPE, HTTP_STATUS_CODES } = require('../../util/constant'); /** * Main Identify request handler func @@ -49,9 +49,10 @@ const { JSON_MIME_TYPE } = require('../../util/constant'); * @param {*} message * @param {*} category * @param {*} destination + * @param {*} reqMetadata * @returns */ -const identifyRequestHandler = async (message, category, destination) => { +const identifyRequestHandler = async (message, category, destination, reqMetadata) => { // If listId property is present try to subscribe/member user in list const { privateApiKey, enforceEmailAsPrimary, listId, flattenProperties } = destination.Config; const mappedToDestination = get(message, MappedToDestinationKey); @@ -105,17 +106,40 @@ const identifyRequestHandler = async (message, category, destination) => { }, }; - const profileId = await getIdFromNewOrExistingProfile(endpoint, payload, requestOptions); + const { profileId, response, statusCode } = await getIdFromNewOrExistingProfile( + endpoint, + payload, + requestOptions, + ); - // Update Profile - const responseArray = [profileUpdateResponseBuilder(payload, profileId, category, privateApiKey)]; + const responseMap = { + profileUpdateResponse: profileUpdateResponseBuilder( + payload, + profileId, + category, + privateApiKey, + ), + }; // check if user wants to subscribe profile or not and listId is present or not if (traitsInfo?.properties?.subscribe && (traitsInfo.properties?.listId || listId)) { - responseArray.push(subscribeUserToList(message, traitsInfo, destination)); - return responseArray; + responseMap.subscribeUserToListResponse = subscribeUserToList(message, traitsInfo, destination); + } + + if (isNewStatusCodesAccepted(reqMetadata) && statusCode === HTTP_STATUS_CODES.CREATED) { + responseMap.suppressEventResponse = { + ...responseMap.profileUpdateResponse, + statusCode: HTTP_STATUS_CODES.SUPPRESS_EVENTS, + error: JSON.stringify(response), + }; + return responseMap.subscribeUserToListResponse + ? [responseMap.subscribeUserToListResponse] + : responseMap.suppressEventResponse; } - return responseArray[0]; + + return responseMap.subscribeUserToListResponse + ? [responseMap.profileUpdateResponse, responseMap.subscribeUserToListResponse] + : responseMap.profileUpdateResponse; }; // ---------------------- @@ -241,7 +265,7 @@ const groupRequestHandler = (message, category, destination) => { }; // Main event processor using specific handler funcs -const processEvent = async (message, destination) => { +const processEvent = async (message, destination, reqMetadata) => { if (!message.type) { throw new InstrumentationError('Event type is required'); } @@ -255,7 +279,7 @@ const processEvent = async (message, destination) => { switch (messageType) { case EventType.IDENTIFY: category = CONFIG_CATEGORIES.IDENTIFY; - response = await identifyRequestHandler(message, category, destination); + response = await identifyRequestHandler(message, category, destination, reqMetadata); break; case EventType.SCREEN: case EventType.TRACK: @@ -272,8 +296,8 @@ const processEvent = async (message, destination) => { return response; }; -const process = async (event) => { - const result = await processEvent(event.message, event.destination); +const process = async (event, reqMetadata) => { + const result = await processEvent(event.message, event.destination, reqMetadata); return result; }; @@ -312,7 +336,7 @@ const processRouterDest = async (inputs, reqMetadata) => { // if not transformed getEventChunks( { - message: await process(event), + message: await process(event, reqMetadata), metadata: event.metadata, destination, }, @@ -326,13 +350,31 @@ const processRouterDest = async (inputs, reqMetadata) => { } }), ); - let batchedSubscribeResponseList = []; + const batchedSubscribeResponseList = []; if (subscribeRespList.length > 0) { - batchedSubscribeResponseList = batchSubscribeEvents(subscribeRespList); + const batchedResponseList = batchSubscribeEvents(subscribeRespList); + batchedSubscribeResponseList.push(...batchedResponseList); } - const nonSubscribeSuccessList = nonSubscribeRespList.map((resp) => - getSuccessRespEvents(resp.message, [resp.metadata], resp.destination), - ); + const nonSubscribeSuccessList = nonSubscribeRespList.map((resp) => { + const response = resp; + const { message, metadata, destination: eventDestination } = response; + if ( + isNewStatusCodesAccepted(reqMetadata) && + message?.statusCode && + message.statusCode === HTTP_STATUS_CODES.SUPPRESS_EVENTS + ) { + delete message.statusCode; + return getSuccessRespEvents( + message, + [metadata], + eventDestination, + false, + HTTP_STATUS_CODES.SUPPRESS_EVENTS, + ); + } + return getSuccessRespEvents(message, [metadata], eventDestination); + }); + batchResponseList = [...batchedSubscribeResponseList, ...nonSubscribeSuccessList]; return [...batchResponseList, ...batchErrorRespList]; diff --git a/src/v0/destinations/klaviyo/util.js b/src/v0/destinations/klaviyo/util.js index 21a492739b..4304edd78f 100644 --- a/src/v0/destinations/klaviyo/util.js +++ b/src/v0/destinations/klaviyo/util.js @@ -12,14 +12,13 @@ const { getSuccessRespEvents, defaultPatchRequestConfig, } = require('../../util'); - -const { BASE_ENDPOINT, MAPPING_CONFIG, CONFIG_CATEGORIES, MAX_BATCH_SIZE } = require('./config'); -const { JSON_MIME_TYPE } = require('../../util/constant'); -const { NetworkError, InstrumentationError } = require('../../util/errorTypes'); -const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils'); const tags = require('../../util/tags'); const { handleHttpRequest } = require('../../../adapters/network'); +const { JSON_MIME_TYPE, HTTP_STATUS_CODES } = require('../../util/constant'); +const { NetworkError, InstrumentationError } = require('../../util/errorTypes'); +const { getDynamicErrorType } = require('../../../adapters/utils/networkUtils'); const { client: errNotificationClient } = require('../../../util/errorNotifier'); +const { BASE_ENDPOINT, MAPPING_CONFIG, CONFIG_CATEGORIES, MAX_BATCH_SIZE } = require('./config'); const REVISION_CONSTANT = '2023-02-22'; @@ -35,6 +34,7 @@ const REVISION_CONSTANT = '2023-02-22'; * @returns */ const getIdFromNewOrExistingProfile = async (endpoint, payload, requestOptions) => { + let response; let profileId; const endpointPath = '/api/profiles'; const { processedResponse: resp } = await handleHttpRequest( @@ -48,15 +48,22 @@ const getIdFromNewOrExistingProfile = async (endpoint, payload, requestOptions) endpointPath, }, ); - if (resp.status === 201) { + + /** + * 201 - profile is created with updated payload no need to update it again (suppress event with 299 status code) + * 409 - profile is already exist, it needs to get updated + */ + if (resp.status === HTTP_STATUS_CODES.CREATED) { profileId = resp.response?.data?.id; - } else if (resp.status === 409) { + const { data } = resp.response; + response = { id: data.id, attributes: data.attributes }; + } else if (resp.status === HTTP_STATUS_CODES.CONFLICT) { const { errors } = resp.response; profileId = errors?.[0]?.meta?.duplicate_profile_id; } if (profileId) { - return profileId; + return { profileId, response, statusCode: resp.status }; } let statusCode = resp.status; @@ -80,6 +87,14 @@ const getIdFromNewOrExistingProfile = async (endpoint, payload, requestOptions) ); }; +/** + * Update profile response builder + * @param {*} payload + * @param {*} profileId + * @param {*} category + * @param {*} privateApiKey + * @returns + */ const profileUpdateResponseBuilder = (payload, profileId, category, privateApiKey) => { const updatedPayload = payload; const identifyResponse = defaultRequestConfig(); @@ -238,7 +253,7 @@ const generateBatchedPaylaodForArray = (events) => { * @param {*} subscribeResponseList * @returns */ -const groupSubsribeResponsesUsingListId = (subscribeResponseList) => { +const groupSubscribeResponsesUsingListId = (subscribeResponseList) => { const subscribeEventGroups = lodash.groupBy( subscribeResponseList, (event) => event.message.body.JSON.data.attributes.list_id, @@ -262,9 +277,13 @@ const getBatchedResponseList = (subscribeEventGroups, identifyResponseList) => { }); batchedResponseList = [...batchedResponseList, ...batchedResponse]; }); - identifyResponseList.forEach((response) => { - batchedResponseList[0].batchedRequest.push(response); - }); + + if (identifyResponseList.length > 0) { + identifyResponseList.forEach((response) => { + batchedResponseList[0].batchedRequest.push(response); + }); + } + return batchedResponseList; }; @@ -272,6 +291,7 @@ const batchSubscribeEvents = (subscribeRespList) => { const identifyResponseList = []; subscribeRespList.forEach((event) => { const processedEvent = event; + // for group and identify events (it will contain only subscribe response) if (processedEvent.message.length === 2) { // the array will contain one update profile reponse and one subscribe reponse identifyResponseList.push(event.message[0]); @@ -282,7 +302,7 @@ const batchSubscribeEvents = (subscribeRespList) => { } }); - const subscribeEventGroups = groupSubsribeResponsesUsingListId(subscribeRespList); + const subscribeEventGroups = groupSubscribeResponsesUsingListId(subscribeRespList); const batchedResponseList = getBatchedResponseList(subscribeEventGroups, identifyResponseList); @@ -295,6 +315,6 @@ module.exports = { populateCustomFieldsFromTraits, generateBatchedPaylaodForArray, batchSubscribeEvents, - getIdFromNewOrExistingProfile, profileUpdateResponseBuilder, + getIdFromNewOrExistingProfile, }; diff --git a/src/v0/util/constant.js b/src/v0/util/constant.js index a06fbd8b9a..50f1b76a74 100644 --- a/src/v0/util/constant.js +++ b/src/v0/util/constant.js @@ -10,6 +10,8 @@ const API_CALL = 'api_call_count'; const JSON_MIME_TYPE = 'application/json'; +const FEATURE_FILTER_CODE = 'filter-code'; + const HTTP_STATUS_CODES = { // 1xx Informational CONTINUE: 100, @@ -25,6 +27,8 @@ const HTTP_STATUS_CODES = { RESET_CONTENT: 205, PARTIAL_CONTENT: 206, MULTI_STATUS: 207, + FILTER_EVENTS: 298, + SUPPRESS_EVENTS: 299, // 3xx Redirection MULTIPLE_CHOICES: 300, @@ -75,14 +79,14 @@ const HTTP_STATUS_CODES = { GATEWAY_TIMEOUT: 504, HTTP_VERSION_NOT_SUPPORTED: 505, INSUFFICIENT_STORAGE: 507, - NETWORK_AUTHENTICATION_REQUIRED: 511 + NETWORK_AUTHENTICATION_REQUIRED: 511, }; - module.exports = { API_CALL, AUTH_CACHE_TTL, - USER_LEAD_CACHE_TTL, JSON_MIME_TYPE, - HTTP_STATUS_CODES + HTTP_STATUS_CODES, + USER_LEAD_CACHE_TTL, + FEATURE_FILTER_CODE, }; diff --git a/src/v0/util/errorTypes/filteredEventsError.js b/src/v0/util/errorTypes/filteredEventsError.js new file mode 100644 index 0000000000..35a384f4e3 --- /dev/null +++ b/src/v0/util/errorTypes/filteredEventsError.js @@ -0,0 +1,14 @@ +const tags = require('../tags'); +const { BaseError } = require('./base'); +const { HTTP_STATUS_CODES } = require('../constant'); + +class FilteredEventsError extends BaseError { + constructor(message, statusCode = HTTP_STATUS_CODES.FILTER_EVENTS) { + const finalStatTags = { + [tags.TAG_NAMES.ERROR_CATEGORY]: tags.ERROR_CATEGORIES.TRANSFORMATION, + }; + super(message, statusCode, finalStatTags); + } +} + +module.exports = FilteredEventsError; diff --git a/src/v0/util/errorTypes/index.js b/src/v0/util/errorTypes/index.js index 01708caa15..2926306dcd 100644 --- a/src/v0/util/errorTypes/index.js +++ b/src/v0/util/errorTypes/index.js @@ -14,6 +14,7 @@ const UnhandledStatusCodeError = require('./unhandledStatusCodeError'); const UnauthorizedError = require('./unauthorizedError'); const NetworkInstrumentationError = require('./networkInstrumentationError'); const UnsupportedEventError = require('./unsupportedEventError'); +const FilteredEventsError = require('./filteredEventsError'); module.exports = { BaseError, @@ -32,4 +33,5 @@ module.exports = { NetworkInstrumentationError, UnsupportedEventError, RedisError, + FilteredEventsError, }; diff --git a/src/v0/util/index.js b/src/v0/util/index.js index 42a4100510..71c89a5a86 100644 --- a/src/v0/util/index.js +++ b/src/v0/util/index.js @@ -32,6 +32,7 @@ const { REFRESH_TOKEN, AUTH_STATUS_INACTIVE, } = require('../../adapters/networkhandler/authConstants'); +const { FEATURE_FILTER_CODE } = require('./constant'); // ======================================================================== // INLINERS // ======================================================================== @@ -78,6 +79,14 @@ const isPrimitive = (arg) => { return arg == null || (type !== 'object' && type !== 'function'); }; +const isNewStatusCodesAccepted = (reqMetadata = {}) => { + if (reqMetadata && typeof reqMetadata === 'object' && !Array.isArray(reqMetadata)) { + const { features } = reqMetadata; + return !!(features && features[FEATURE_FILTER_CODE]); + } + return false; +}; + /** * * @param {*} arg @@ -454,11 +463,17 @@ const defaultBatchRequestConfig = () => ({ // Router transformer // Success responses -const getSuccessRespEvents = (message, metadata, destination, batched = false) => ({ +const getSuccessRespEvents = ( + message, + metadata, + destination, + batched = false, + statusCode = 200, +) => ({ batchedRequest: message, metadata, batched, - statusCode: 200, + statusCode, destination, }); @@ -1704,7 +1719,7 @@ const simpleProcessRouterDestSync = async (inputs, singleTfFunc, reqMetadata, pr // transform if not already done if (!input.message.statusCode) { // eslint-disable-next-line no-await-in-loop - resp = await singleTfFunc(input, processParams); + resp = await singleTfFunc(input, processParams, reqMetadata); } respList.push(getSuccessRespEvents(resp, [input.metadata], input.destination)); } catch (error) { @@ -2129,4 +2144,5 @@ module.exports = { hasCircularReference, getAuthErrCategoryFromErrDetailsAndStCode, getAuthErrCategoryFromStCode, + isNewStatusCodesAccepted, }; diff --git a/src/v0/util/tags.js b/src/v0/util/tags.js index 95e78825c3..81e6b9a2a6 100644 --- a/src/v0/util/tags.js +++ b/src/v0/util/tags.js @@ -51,6 +51,7 @@ const ERROR_TYPES = { OAUTH_SECRET: 'oAuthSecret', UNSUPPORTED: 'unsupported', REDIS: 'redis', + FILTERED: 'filtered', }; const METADATA = { diff --git a/test/__mocks__/klaviyo.mock.js b/test/__mocks__/klaviyo.mock.js index f768af0fb3..020387d1f2 100644 --- a/test/__mocks__/klaviyo.mock.js +++ b/test/__mocks__/klaviyo.mock.js @@ -19,6 +19,7 @@ const klaviyoPostRequestHandler = (url, payload) => { data: { data: { id: '01GW3PHVY0MTCDGS0A1612HARX', + attributes: {} }, } }; diff --git a/test/__tests__/braze.test.js b/test/__tests__/braze.test.js index 9e4a663d51..c1d317c6ba 100644 --- a/test/__tests__/braze.test.js +++ b/test/__tests__/braze.test.js @@ -1,3 +1,4 @@ +const cloneDeep = require('lodash/cloneDeep'); const integration = "braze"; const name = "Braze"; @@ -6,6 +7,7 @@ const path = require("path"); const version = "v0"; +const { FEATURE_FILTER_CODE } = require('../../src/v0/util/constant'); const transformer = require(`../../src/${version}/destinations/${integration}/transform`); const inputDataFile = fs.readFileSync( path.resolve(__dirname, `./data/${integration}_input.json`) @@ -18,38 +20,57 @@ const expectedData = JSON.parse(outputDataFile); inputData.forEach((input, index) => { it(`${name} Tests: payload - ${index}`, async () => { - let output, expected; + let output1, output2, output3, expected; try { - output = await transformer.process(input); + // default reqMetadata + output1 = await transformer.process(cloneDeep(input)); + // null reqMetadata + output2 = await transformer.process(cloneDeep(input), { userStore: new Map() }, null); + // undefined reqMetadata + output3 = await transformer.process(cloneDeep(input), { userStore: new Map() }, undefined); expected = expectedData[index]; } catch (error) { - output = error.message; + output1 = error.message; + output2 = error.message; + output3 = error.message; expected = expectedData[index].message; } - expect(output).toEqual(expected); + expect(output1).toEqual(expected); + expect(output2).toEqual(expected); + expect(output3).toEqual(expected); }); }); + // Router Test Data -const inputRouterDataFile = fs.readFileSync( - path.resolve(__dirname, `./data/${integration}_router_input.json`) -); -const outputRouterDataFile = fs.readFileSync( - path.resolve(__dirname, `./data/${integration}_router_output.json`) +const routerTestDataFile = fs.readFileSync( + path.resolve(__dirname, `./data/${integration}_router.json`) ); -const inputRouterData = JSON.parse(inputRouterDataFile); -const expectedRouterData = JSON.parse(outputRouterDataFile); +const routerTestData = JSON.parse(routerTestDataFile); +const { simpleRouterTestData, dedupEnabledRouterTestData } = routerTestData; describe(`${name} Tests`, () => { describe("Simple Router Tests", () => { - it("Payload", async () => { - const routerOutput = await transformer.processRouterDest(inputRouterData.simpleRouterRequests); - expect(routerOutput).toEqual(expectedRouterData.simpleRouterResponse); + simpleRouterTestData.forEach((dataPoint, index) => { + it(`${index}. ${integration} - ${dataPoint.description}`, async () => { + const output = await transformer.processRouterDest(dataPoint.input); + expect(output).toEqual(dataPoint.output); + }); }); }); describe("Dedupenabled Router Tests", () => { - it("Payload", async () => { - const routerOutput = await transformer.processRouterDest(inputRouterData.dedupEnabledRouterRequests); - expect(routerOutput).toEqual(expectedRouterData.dedupEnabledRouterResponse); + dedupEnabledRouterTestData.forEach((dataPoint, index) => { + it(`${index}. ${integration} - ${dataPoint.description}`, async () => { + // default reqMetadata + const oldTransformerOutput = await transformer.processRouterDest(cloneDeep(dataPoint.input)); + // valid reqMetadata + const newTransformerOutput = await transformer.processRouterDest(cloneDeep(dataPoint.input), { features: { [FEATURE_FILTER_CODE]: true } }); + // invalid reqMetadata + const invalidRequestMetadataOutput = await transformer.processRouterDest(cloneDeep(dataPoint.input), [{ features: { [FEATURE_FILTER_CODE]: true } }]); + + expect(oldTransformerOutput).toEqual(dataPoint.oldTransformerOutput); + expect(newTransformerOutput).toEqual(dataPoint.newTransformerOutput); + expect(invalidRequestMetadataOutput).toEqual(dataPoint.oldTransformerOutput); + }); }); }); }); diff --git a/test/__tests__/data/braze_router.json b/test/__tests__/data/braze_router.json new file mode 100644 index 0000000000..8bfd7c7d42 --- /dev/null +++ b/test/__tests__/data/braze_router.json @@ -0,0 +1,1036 @@ +{ + "simpleRouterTestData": [ + { + "description": "simple router tests", + "input": [ + { + "destination": { + "Config": { + "restApiKey": "dummyApiKey", + "prefixProperties": true, + "useNativeSDK": false, + "dataCenter": "eu-01" + }, + "DestinationDefinition": { + "DisplayName": "Braze", + "ID": "1WhbSZ6uA3H5ChVifHpfL2H6sie", + "Name": "BRAZE" + }, + "Enabled": true, + "ID": "1WhcOCGgj9asZu850HvugU2C3Aq", + "Name": "Braze", + "Transformations": [] + }, + "metadata": { + "jobId": 1 + }, + "message": { + "anonymousId": "e6ab2c5e-2cda-44a9-a962-e2f67df78bca", + "channel": "web", + "context": { + "app": { + "build": "1.0.0", + "name": "RudderLabs JavaScript SDK", + "namespace": "com.rudderlabs.javascript", + "version": "1.0.5" + }, + "ip": "0.0.0.0", + "library": { + "name": "RudderLabs JavaScript SDK", + "version": "1.0.5" + }, + "locale": "en-GB", + "os": { + "name": "", + "version": "" + }, + "screen": { + "density": 2 + }, + "traits": {}, + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36" + }, + "integrations": { + "All": true + }, + "messageId": "dd266c67-9199-4a52-ba32-f46ddde67312", + "originalTimestamp": "2020-01-24T06:29:02.358Z", + "properties": { + "path": "/tests/html/index2.html", + "referrer": "", + "search": "", + "title": "", + "url": "http://localhost/tests/html/index2.html" + }, + "receivedAt": "2020-01-24T11:59:02.403+05:30", + "request_ip": "[::1]:53708", + "sentAt": "2020-01-24T06:29:02.359Z", + "timestamp": "2020-01-24T11:59:02.402+05:30", + "type": "page", + "userId": "" + } + }, + { + "destination": { + "Config": { + "restApiKey": "dummyApiKey", + "prefixProperties": true, + "useNativeSDK": false, + "dataCenter": "us-01" + }, + "DestinationDefinition": { + "DisplayName": "Braze", + "ID": "1WhbSZ6uA3H5ChVifHpfL2H6sie", + "Name": "BRAZE" + }, + "Enabled": true, + "ID": "1WhcOCGgj9asZu850HvugU2C3Aq", + "Name": "Braze", + "Transformations": [] + }, + "metadata": { + "jobId": 2 + }, + "message": { + "anonymousId": "e6ab2c5e-2cda-44a9-a962-e2f67df78bca", + "channel": "web", + "context": { + "app": { + "build": "1.0.0", + "name": "RudderLabs JavaScript SDK", + "namespace": "com.rudderlabs.javascript", + "version": "1.0.5" + }, + "ip": "0.0.0.0", + "library": { + "name": "RudderLabs JavaScript SDK", + "version": "1.0.5" + }, + "locale": "en-GB", + "os": { + "name": "", + "version": "" + }, + "screen": { + "density": 2 + }, + "traits": { + "city": "Disney", + "country": "USA", + "email": "mickey@disney.com", + "firstname": "Mickey" + }, + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36" + }, + "integrations": { + "All": true + }, + "messageId": "2536eda4-d638-4c93-8014-8ffe3f083214", + "originalTimestamp": "2020-01-24T06:29:02.362Z", + "receivedAt": "2020-01-24T11:59:02.403+05:30", + "request_ip": "[::1]:53709", + "sentAt": "2020-01-24T06:29:02.363Z", + "timestamp": "2020-01-24T11:59:02.402+05:30", + "type": "identify", + "userId": "" + } + }, + { + "destination": { + "Config": { + "restApiKey": "dummyApiKey", + "prefixProperties": true, + "useNativeSDK": false, + "dataCenter": "us-01", + "enableSubscriptionGroupInGroupCall": true + }, + "DestinationDefinition": { + "DisplayName": "Braze", + "ID": "1WhbSZ6uA3H5ChVifHpfL2H6sie", + "Name": "BRAZE" + }, + "Enabled": true, + "ID": "1WhcOCGgj9asZu850HvugU2C3Aq", + "Name": "Braze", + "Transformations": [] + }, + "metadata": { + "jobId": 3 + }, + "message": { + "anonymousId": "56yrtsdfgbgxcb-22b4-401d-aae5-1b994be9a969", + "groupId": "c90f0fd2-2a02-4f2f-bf07-7e7d2c2ed2b1", + "traits": { + "phone": "5055077683", + "subscriptionState": "subscribed" + }, + "userId": "user123", + "type": "group" + } + }, + { + "destination": { + "Config": { + "restApiKey": "dummyApiKey", + "prefixProperties": true, + "useNativeSDK": false, + "dataCenter": "us-01", + "enableSubscriptionGroupInGroupCall": true + }, + "DestinationDefinition": { + "DisplayName": "Braze", + "ID": "1WhbSZ6uA3H5ChVifHpfL2H6sie", + "Name": "BRAZE" + }, + "Enabled": true, + "ID": "1WhcOCGgj9asZu850HvugU2C3Aq", + "Name": "Braze", + "Transformations": [] + }, + "metadata": { + "jobId": 4 + }, + "message": { + "anonymousId": "dfgdfgdfg-22b4-401d-aae5-1b994be9a969", + "groupId": "58d0a278-b55b-4f10-b7d2-98d1c5dd4c30", + "traits": { + "phone": "5055077683", + "subscriptionState": "subscribed" + }, + "userId": "user877", + "type": "group" + } + }, + { + "destination": { + "Config": { + "restApiKey": "dummyApiKey", + "prefixProperties": true, + "useNativeSDK": false, + "dataCenter": "us-01", + "enableSubscriptionGroupInGroupCall": true + }, + "DestinationDefinition": { + "DisplayName": "Braze", + "ID": "1WhbSZ6uA3H5ChVifHpfL2H6sie", + "Name": "BRAZE" + }, + "Enabled": true, + "ID": "1WhcOCGgj9asZu850HvugU2C3Aq", + "Name": "Braze", + "Transformations": [] + }, + "metadata": { + "jobId": 5 + }, + "message": { + "type": "alias", + "previousId": "adsfsaf", + "userId": "dsafsdf" + } + }, + { + "destination": { + "Config": { + "restApiKey": "dummyApiKey", + "prefixProperties": true, + "useNativeSDK": false, + "dataCenter": "us-01", + "enableSubscriptionGroupInGroupCall": true + }, + "DestinationDefinition": { + "DisplayName": "Braze", + "ID": "1WhbSZ6uA3H5ChVifHpfL2H6sie", + "Name": "BRAZE" + }, + "Enabled": true, + "ID": "1WhcOCGgj9asZu850HvugU2C3Aq", + "Name": "Braze", + "Transformations": [] + }, + "metadata": { + "jobId": 6 + }, + "message": { + "type": "alias", + "previousId": "adsfsaf2", + "userId": "dsafsdf2" + } + } + ], + "output": [ + { + "batchedRequest": [ + { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://rest.fra-01.braze.eu/users/track", + "headers": { + "Content-Type": "application/json", + "Accept": "application/json", + "Authorization": "Bearer dummyApiKey" + }, + "params": {}, + "body": { + "JSON": { + "partner": "RudderStack", + "events": [ + { + "name": "Page Viewed", + "time": "2020-01-24T11:59:02.402+05:30", + "properties": { + "path": "/tests/html/index2.html", + "referrer": "", + "search": "", + "title": "", + "url": "http://localhost/tests/html/index2.html" + }, + "_update_existing_only": false, + "user_alias": { + "alias_name": "e6ab2c5e-2cda-44a9-a962-e2f67df78bca", + "alias_label": "rudder_id" + } + } + ], + "attributes": [ + { + "email": "mickey@disney.com", + "city": "Disney", + "country": "USA", + "firstname": "Mickey", + "_update_existing_only": false, + "user_alias": { + "alias_name": "e6ab2c5e-2cda-44a9-a962-e2f67df78bca", + "alias_label": "rudder_id" + } + } + ] + }, + "XML": {}, + "JSON_ARRAY": {}, + "FORM": {} + }, + "files": {} + }, + { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://rest.fra-01.braze.eu/v2/subscription/status/set", + "headers": { + "Content-Type": "application/json", + "Accept": "application/json", + "Authorization": "Bearer dummyApiKey" + }, + "params": {}, + "body": { + "JSON": { + "subscription_groups": [ + { + "external_id": ["user123"], + "phones": ["5055077683"], + "subscription_group_id": "c90f0fd2-2a02-4f2f-bf07-7e7d2c2ed2b1", + "subscription_state": "subscribed" + }, + { + "external_id": ["user877"], + "phones": ["5055077683"], + "subscription_group_id": "58d0a278-b55b-4f10-b7d2-98d1c5dd4c30", + "subscription_state": "subscribed" + } + ] + }, + "XML": {}, + "JSON_ARRAY": {}, + "FORM": {} + }, + "files": {} + }, + { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://rest.fra-01.braze.eu/users/merge", + "headers": { + "Content-Type": "application/json", + "Accept": "application/json", + "Authorization": "Bearer dummyApiKey" + }, + "params": {}, + "body": { + "JSON": { + "merge_updates": [ + { + "identifier_to_keep": { + "external_id": "dsafsdf" + }, + "identifier_to_merge": { + "external_id": "adsfsaf" + } + }, + { + "identifier_to_keep": { + "external_id": "dsafsdf2" + }, + "identifier_to_merge": { + "external_id": "adsfsaf2" + } + } + ] + }, + "XML": {}, + "JSON_ARRAY": {}, + "FORM": {} + }, + "files": {} + } + ], + "metadata": [ + { + "jobId": 1 + }, + { + "jobId": 2 + }, + { + "jobId": 3 + }, + { + "jobId": 4 + }, + { + "jobId": 5 + }, + { + "jobId": 6 + } + ], + "batched": true, + "statusCode": 200, + "destination": { + "Config": { + "restApiKey": "dummyApiKey", + "prefixProperties": true, + "useNativeSDK": false, + "dataCenter": "eu-01" + }, + "DestinationDefinition": { + "DisplayName": "Braze", + "ID": "1WhbSZ6uA3H5ChVifHpfL2H6sie", + "Name": "BRAZE" + }, + "Enabled": true, + "ID": "1WhcOCGgj9asZu850HvugU2C3Aq", + "Name": "Braze", + "Transformations": [] + } + } + ] + } + ], + "dedupEnabledRouterTestData": [ + { + "description": "dedup enabled router tests", + "input": [ + { + "destination": { + "ID": "2N9UakqKF0D35wfzSeofIxPdL8X", + "Name": "Braze-Test", + "Config": { + "appKey": "0e5440c3-226b-45d0-91b5-c64da56cde16", + "blacklistedEvents": [], + "dataCenter": "US-03", + "enableNestedArrayOperations": false, + "enableSubscriptionGroupInGroupCall": false, + "eventFilteringOption": "disable", + "oneTrustCookieCategories": [], + "restApiKey": "dummyApiKey", + "supportDedup": true, + "trackAnonymousUser": true, + "whitelistedEvents": [] + }, + "Enabled": true, + "WorkspaceID": "27O0bhB6p5ehfOWeeZlOSsSDTLg", + "Transformations": [], + "IsProcessorEnabled": true, + "RevisionID": "2N9Uaf2tWq2QRmatBWQm03Rz6qX" + }, + "metadata": { + "jobId": 1 + }, + "message": { + "type": "track", + "event": "Sign In Completed", + "sentAt": "2023-03-10T18:36:04.738Z", + "userId": "braze_test_user", + "channel": "web", + "context": { + "locale": "en-US", + "traits": { + "subscribe_once": true, + "pwa": true, + "email": "jackson24miranda@gmail.com", + "lastName": "Miranda", + "firstName": "Spencer", + "is_registered": true, + "last_identify": "GOOGLE_SIGN_IN", + "account_region": "ON", + "is_pickup_selected": "false", + "has_tradein_attempt": false, + "custom_obj_attr": { + "key1": "value1", + "key2": "value2", + "key4": "value4" + }, + "custom_arr": [1, 2, "str1"] + }, + "library": { + "name": "RudderLabs JavaScript SDK", + "version": "2.9.5" + }, + "campaign": {}, + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36" + }, + "rudderId": "4118560d-e4fc-4fd1-a734-9c69eae2c047", + "messageId": "1a342814-a882-4b65-9cc9-347544997268", + "timestamp": "2023-03-10T18:36:05.028Z", + "properties": { + "cause": "/redirector", + "method": "GOOGLE", + "region": "ON", + "orderId": "6179367977099", + "order_id": "6179367977099", + "webhookurl": "https://my.test.com", + "countingMethod": "standard", + "is_first_time_signin": false + }, + "receivedAt": "2023-03-18T01:41:42.257+05:30", + "request_ip": "[::1]", + "anonymousId": "77e278c9-e984-4cdd-950c-cd0b61befd03", + "originalTimestamp": "2023-03-10T18:36:04.733Z" + } + }, + { + "destination": { + "ID": "2N9UakqKF0D35wfzSeofIxPdL8X", + "Name": "Braze-Test", + "Config": { + "appKey": "0e5440c3-226b-45d0-91b5-c64da56cde16", + "blacklistedEvents": [], + "dataCenter": "US-03", + "enableNestedArrayOperations": false, + "enableSubscriptionGroupInGroupCall": false, + "eventFilteringOption": "disable", + "oneTrustCookieCategories": [], + "restApiKey": "dummyApiKey", + "supportDedup": true, + "trackAnonymousUser": true, + "whitelistedEvents": [] + }, + "Enabled": true, + "WorkspaceID": "27O0bhB6p5ehfOWeeZlOSsSDTLg", + "Transformations": [], + "IsProcessorEnabled": true, + "RevisionID": "2N9Uaf2tWq2QRmatBWQm03Rz6qX" + }, + "metadata": { + "jobId": 2 + }, + "message": { + "type": "track", + "event": "Sign In Completed", + "sentAt": "2023-03-10T18:36:04.738Z", + "userId": "braze_test_user", + "channel": "web", + "context": { + "locale": "en-US", + "traits": { + "subscribe_once": true, + "pwa": true, + "email": "jackson24miranda@gmail.com", + "lastName": "Miranda 2", + "firstName": "Spencer", + "is_registered": true, + "last_identify": "GOOGLE_SIGN_IN", + "account_region": "ON", + "is_pickup_selected": "true", + "has_tradein_attempt": false, + "custom_obj_attr": { + "key1": "value1", + "key2": "value2", + "key4": "value4" + }, + "custom_arr": ["1", "2", "str1"] + }, + "library": { + "name": "RudderLabs JavaScript SDK", + "version": "2.9.5" + }, + "campaign": {}, + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36" + }, + "rudderId": "4118560d-e4fc-4fd1-a734-9c69eae2c047", + "messageId": "1a342814-a882-4b65-9cc9-347544997268", + "timestamp": "2023-03-10T18:36:05.028Z", + "properties": { + "cause": "/redirector", + "method": "GOOGLE", + "region": "ON", + "orderId": "6179367977099", + "order_id": "6179367977099", + "webhookurl": "https://my.test.com", + "countingMethod": "standard", + "is_first_time_signin": false + }, + "receivedAt": "2023-03-18T01:41:42.257+05:30", + "request_ip": "[::1]", + "anonymousId": "77e278c9-e984-4cdd-950c-cd0b61befd03", + "originalTimestamp": "2023-03-10T18:36:04.733Z" + } + }, + { + "destination": { + "ID": "2N9UakqKF0D35wfzSeofIxPdL8X", + "Name": "Braze-Test", + "Config": { + "appKey": "0e5440c3-226b-45d0-91b5-c64da56cde16", + "blacklistedEvents": [], + "dataCenter": "US-03", + "enableNestedArrayOperations": false, + "enableSubscriptionGroupInGroupCall": false, + "eventFilteringOption": "disable", + "oneTrustCookieCategories": [], + "restApiKey": "dummyApiKey", + "supportDedup": true, + "trackAnonymousUser": true, + "whitelistedEvents": [] + }, + "Enabled": true, + "WorkspaceID": "27O0bhB6p5ehfOWeeZlOSsSDTLg", + "Transformations": [], + "IsProcessorEnabled": true, + "RevisionID": "2N9Uaf2tWq2QRmatBWQm03Rz6qX" + }, + "metadata": { + "jobId": 3 + }, + "message": { + "anonymousId": "e6ab2c5e-2cda-44a9-a962-e2f67df78bca", + "channel": "web", + "context": { + "app": { + "build": "1.0.0", + "name": "RudderLabs JavaScript SDK", + "namespace": "com.rudderlabs.javascript", + "version": "1.0.5" + }, + "ip": "0.0.0.0", + "library": { + "name": "RudderLabs JavaScript SDK", + "version": "1.0.5" + }, + "locale": "en-GB", + "os": { + "name": "", + "version": "" + }, + "screen": { + "density": 2 + }, + "traits": { + "city": "Disney", + "country": "USA", + "email": "mickey@disney.com", + "firstName": "Mickey" + }, + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36" + }, + "integrations": { + "All": true + }, + "messageId": "2536eda4-d638-4c93-8014-8ffe3f083214", + "type": "identify", + "userId": "user@50" + } + }, + { + "destination": { + "ID": "2N9UakqKF0D35wfzSeofIxPdL8X", + "Name": "Braze-Test", + "Config": { + "appKey": "0e5440c3-226b-45d0-91b5-c64da56cde16", + "blacklistedEvents": [], + "dataCenter": "US-03", + "enableNestedArrayOperations": false, + "enableSubscriptionGroupInGroupCall": false, + "eventFilteringOption": "disable", + "oneTrustCookieCategories": [], + "restApiKey": "dummyApiKey", + "supportDedup": true, + "trackAnonymousUser": true, + "whitelistedEvents": [] + }, + "Enabled": true, + "WorkspaceID": "27O0bhB6p5ehfOWeeZlOSsSDTLg", + "Transformations": [], + "IsProcessorEnabled": true, + "RevisionID": "2N9Uaf2tWq2QRmatBWQm03Rz6qX" + }, + "metadata": { + "jobId": 4 + }, + "message": { + "anonymousId": "e6ab2c5e-2cda-44a9-a962-e2f67df78bca", + "channel": "web", + "context": { + "app": { + "build": "1.0.0", + "name": "RudderLabs JavaScript SDK", + "namespace": "com.rudderlabs.javascript", + "version": "1.0.5" + }, + "ip": "0.0.0.0", + "library": { + "name": "RudderLabs JavaScript SDK", + "version": "1.0.5" + }, + "locale": "en-GB", + "os": { + "name": "", + "version": "" + }, + "screen": { + "density": 2 + }, + "traits": { + "city": "Disney", + "country": "USA", + "email": "mickey@disney.com", + "firstName": "Mickey" + }, + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36" + }, + "integrations": { + "All": true + }, + "messageId": "2536eda4-d638-4c93-8014-8ffe3f083214", + "type": "identify", + "userId": "user@50" + } + } + ], + "newTransformerOutput": [ + { + "batchedRequest": [ + { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://rest.iad-03.braze.com/users/track", + "headers": { + "Content-Type": "application/json", + "Accept": "application/json", + "Authorization": "Bearer dummyApiKey" + }, + "params": {}, + "body": { + "JSON": { + "partner": "RudderStack", + "attributes": [ + { + "first_name": "Spencer", + "subscribe_once": true, + "pwa": true, + "external_id": "braze_test_user", + "custom_obj_attr": { + "key1": "value1", + "key2": "value2", + "key4": "value4" + } + }, + { + "last_name": "Miranda 2", + "is_pickup_selected": "true", + "external_id": "braze_test_user", + "custom_arr": ["1", "2", "str1"] + }, + { + "city": "Disney", + "country": "USA", + "email": "mickey@disney.com", + "external_id": "user@50", + "first_name": "Mickey" + } + ], + "events": [ + { + "name": "Sign In Completed", + "time": "2023-03-10T18:36:05.028Z", + "properties": { + "cause": "/redirector", + "method": "GOOGLE", + "region": "ON", + "orderId": "6179367977099", + "order_id": "6179367977099", + "webhookurl": "https://my.test.com", + "countingMethod": "standard", + "is_first_time_signin": false + }, + "external_id": "braze_test_user" + }, + { + "name": "Sign In Completed", + "time": "2023-03-10T18:36:05.028Z", + "properties": { + "cause": "/redirector", + "method": "GOOGLE", + "region": "ON", + "orderId": "6179367977099", + "order_id": "6179367977099", + "webhookurl": "https://my.test.com", + "countingMethod": "standard", + "is_first_time_signin": false + }, + "external_id": "braze_test_user" + } + ] + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {} + } + ], + "metadata": [ + { + "jobId": 1 + }, + { + "jobId": 2 + }, + { + "jobId": 3 + } + ], + "batched": true, + "statusCode": 200, + "destination": { + "ID": "2N9UakqKF0D35wfzSeofIxPdL8X", + "Name": "Braze-Test", + "Config": { + "appKey": "0e5440c3-226b-45d0-91b5-c64da56cde16", + "blacklistedEvents": [], + "dataCenter": "US-03", + "enableNestedArrayOperations": false, + "enableSubscriptionGroupInGroupCall": false, + "eventFilteringOption": "disable", + "oneTrustCookieCategories": [], + "restApiKey": "dummyApiKey", + "supportDedup": true, + "trackAnonymousUser": true, + "whitelistedEvents": [] + }, + "Enabled": true, + "WorkspaceID": "27O0bhB6p5ehfOWeeZlOSsSDTLg", + "Transformations": [], + "IsProcessorEnabled": true, + "RevisionID": "2N9Uaf2tWq2QRmatBWQm03Rz6qX" + } + }, + { + "error": "[Braze Deduplication]: Duplicate user detected, the user is dropped", + "statTags": { + "errorCategory": "transformation" + }, + "statusCode": 298, + "batched": false, + "metadata": [ + { + "jobId": 4 + } + ], + "destination": { + "ID": "2N9UakqKF0D35wfzSeofIxPdL8X", + "Name": "Braze-Test", + "Config": { + "appKey": "0e5440c3-226b-45d0-91b5-c64da56cde16", + "blacklistedEvents": [], + "dataCenter": "US-03", + "enableNestedArrayOperations": false, + "enableSubscriptionGroupInGroupCall": false, + "eventFilteringOption": "disable", + "oneTrustCookieCategories": [], + "restApiKey": "dummyApiKey", + "supportDedup": true, + "trackAnonymousUser": true, + "whitelistedEvents": [] + }, + "Enabled": true, + "WorkspaceID": "27O0bhB6p5ehfOWeeZlOSsSDTLg", + "Transformations": [], + "IsProcessorEnabled": true, + "RevisionID": "2N9Uaf2tWq2QRmatBWQm03Rz6qX" + } + } + ], + "oldTransformerOutput": [ + { + "batchedRequest": [ + { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://rest.iad-03.braze.com/users/track", + "headers": { + "Content-Type": "application/json", + "Accept": "application/json", + "Authorization": "Bearer dummyApiKey" + }, + "params": {}, + "body": { + "JSON": { + "partner": "RudderStack", + "attributes": [ + { + "first_name": "Spencer", + "subscribe_once": true, + "pwa": true, + "external_id": "braze_test_user", + "custom_obj_attr": { + "key1": "value1", + "key2": "value2", + "key4": "value4" + } + }, + { + "last_name": "Miranda 2", + "is_pickup_selected": "true", + "external_id": "braze_test_user", + "custom_arr": ["1", "2", "str1"] + }, + { + "city": "Disney", + "country": "USA", + "email": "mickey@disney.com", + "external_id": "user@50", + "first_name": "Mickey" + } + ], + "events": [ + { + "name": "Sign In Completed", + "time": "2023-03-10T18:36:05.028Z", + "properties": { + "cause": "/redirector", + "method": "GOOGLE", + "region": "ON", + "orderId": "6179367977099", + "order_id": "6179367977099", + "webhookurl": "https://my.test.com", + "countingMethod": "standard", + "is_first_time_signin": false + }, + "external_id": "braze_test_user" + }, + { + "name": "Sign In Completed", + "time": "2023-03-10T18:36:05.028Z", + "properties": { + "cause": "/redirector", + "method": "GOOGLE", + "region": "ON", + "orderId": "6179367977099", + "order_id": "6179367977099", + "webhookurl": "https://my.test.com", + "countingMethod": "standard", + "is_first_time_signin": false + }, + "external_id": "braze_test_user" + } + ] + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {} + } + ], + "metadata": [ + { + "jobId": 1 + }, + { + "jobId": 2 + }, + { + "jobId": 3 + } + ], + "batched": true, + "statusCode": 200, + "destination": { + "ID": "2N9UakqKF0D35wfzSeofIxPdL8X", + "Name": "Braze-Test", + "Config": { + "appKey": "0e5440c3-226b-45d0-91b5-c64da56cde16", + "blacklistedEvents": [], + "dataCenter": "US-03", + "enableNestedArrayOperations": false, + "enableSubscriptionGroupInGroupCall": false, + "eventFilteringOption": "disable", + "oneTrustCookieCategories": [], + "restApiKey": "dummyApiKey", + "supportDedup": true, + "trackAnonymousUser": true, + "whitelistedEvents": [] + }, + "Enabled": true, + "WorkspaceID": "27O0bhB6p5ehfOWeeZlOSsSDTLg", + "Transformations": [], + "IsProcessorEnabled": true, + "RevisionID": "2N9Uaf2tWq2QRmatBWQm03Rz6qX" + } + }, + { + "error": "[Braze Deduplication]: Duplicate user detected, the user is dropped", + "statTags": { + "errorCategory": "dataValidation", + "errorType": "instrumentation" + }, + "statusCode": 400, + "batched": false, + "metadata": [ + { + "jobId": 4 + } + ], + "destination": { + "ID": "2N9UakqKF0D35wfzSeofIxPdL8X", + "Name": "Braze-Test", + "Config": { + "appKey": "0e5440c3-226b-45d0-91b5-c64da56cde16", + "blacklistedEvents": [], + "dataCenter": "US-03", + "enableNestedArrayOperations": false, + "enableSubscriptionGroupInGroupCall": false, + "eventFilteringOption": "disable", + "oneTrustCookieCategories": [], + "restApiKey": "dummyApiKey", + "supportDedup": true, + "trackAnonymousUser": true, + "whitelistedEvents": [] + }, + "Enabled": true, + "WorkspaceID": "27O0bhB6p5ehfOWeeZlOSsSDTLg", + "Transformations": [], + "IsProcessorEnabled": true, + "RevisionID": "2N9Uaf2tWq2QRmatBWQm03Rz6qX" + } + } + ] + } + ] +} diff --git a/test/__tests__/data/braze_router_input.json b/test/__tests__/data/braze_router_input.json deleted file mode 100644 index 074287823e..0000000000 --- a/test/__tests__/data/braze_router_input.json +++ /dev/null @@ -1,416 +0,0 @@ -{ - "simpleRouterRequests": [ - { - "destination": { - "Config": { - "restApiKey": "dummyApiKey", - "prefixProperties": true, - "useNativeSDK": false, - "dataCenter": "eu-01" - }, - "DestinationDefinition": { - "DisplayName": "Braze", - "ID": "1WhbSZ6uA3H5ChVifHpfL2H6sie", - "Name": "BRAZE" - }, - "Enabled": true, - "ID": "1WhcOCGgj9asZu850HvugU2C3Aq", - "Name": "Braze", - "Transformations": [] - }, - "metadata": { - "jobId": 1 - }, - "message": { - "anonymousId": "e6ab2c5e-2cda-44a9-a962-e2f67df78bca", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.5" - }, - "ip": "0.0.0.0", - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.5" - }, - "locale": "en-GB", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "traits": {}, - "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36" - }, - "integrations": { - "All": true - }, - "messageId": "dd266c67-9199-4a52-ba32-f46ddde67312", - "originalTimestamp": "2020-01-24T06:29:02.358Z", - "properties": { - "path": "/tests/html/index2.html", - "referrer": "", - "search": "", - "title": "", - "url": "http://localhost/tests/html/index2.html" - }, - "receivedAt": "2020-01-24T11:59:02.403+05:30", - "request_ip": "[::1]:53708", - "sentAt": "2020-01-24T06:29:02.359Z", - "timestamp": "2020-01-24T11:59:02.402+05:30", - "type": "page", - "userId": "" - } - }, - { - "destination": { - "Config": { - "restApiKey": "dummyApiKey", - "prefixProperties": true, - "useNativeSDK": false, - "dataCenter": "us-01" - }, - "DestinationDefinition": { - "DisplayName": "Braze", - "ID": "1WhbSZ6uA3H5ChVifHpfL2H6sie", - "Name": "BRAZE" - }, - "Enabled": true, - "ID": "1WhcOCGgj9asZu850HvugU2C3Aq", - "Name": "Braze", - "Transformations": [] - }, - "metadata": { - "jobId": 2 - }, - "message": { - "anonymousId": "e6ab2c5e-2cda-44a9-a962-e2f67df78bca", - "channel": "web", - "context": { - "app": { - "build": "1.0.0", - "name": "RudderLabs JavaScript SDK", - "namespace": "com.rudderlabs.javascript", - "version": "1.0.5" - }, - "ip": "0.0.0.0", - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.0.5" - }, - "locale": "en-GB", - "os": { - "name": "", - "version": "" - }, - "screen": { - "density": 2 - }, - "traits": { - "city": "Disney", - "country": "USA", - "email": "mickey@disney.com", - "firstname": "Mickey" - }, - "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36" - }, - "integrations": { - "All": true - }, - "messageId": "2536eda4-d638-4c93-8014-8ffe3f083214", - "originalTimestamp": "2020-01-24T06:29:02.362Z", - "receivedAt": "2020-01-24T11:59:02.403+05:30", - "request_ip": "[::1]:53709", - "sentAt": "2020-01-24T06:29:02.363Z", - "timestamp": "2020-01-24T11:59:02.402+05:30", - "type": "identify", - "userId": "" - } - }, - { - "destination": { - "Config": { - "restApiKey": "dummyApiKey", - "prefixProperties": true, - "useNativeSDK": false, - "dataCenter": "us-01", - "enableSubscriptionGroupInGroupCall": true - }, - "DestinationDefinition": { - "DisplayName": "Braze", - "ID": "1WhbSZ6uA3H5ChVifHpfL2H6sie", - "Name": "BRAZE" - }, - "Enabled": true, - "ID": "1WhcOCGgj9asZu850HvugU2C3Aq", - "Name": "Braze", - "Transformations": [] - }, - "metadata": { - "jobId": 3 - }, - "message": { - "anonymousId": "56yrtsdfgbgxcb-22b4-401d-aae5-1b994be9a969", - "groupId": "c90f0fd2-2a02-4f2f-bf07-7e7d2c2ed2b1", - "traits": { - "phone": "5055077683", - "subscriptionState": "subscribed" - }, - "userId": "user123", - "type": "group" - } - }, - { - "destination": { - "Config": { - "restApiKey": "dummyApiKey", - "prefixProperties": true, - "useNativeSDK": false, - "dataCenter": "us-01", - "enableSubscriptionGroupInGroupCall": true - }, - "DestinationDefinition": { - "DisplayName": "Braze", - "ID": "1WhbSZ6uA3H5ChVifHpfL2H6sie", - "Name": "BRAZE" - }, - "Enabled": true, - "ID": "1WhcOCGgj9asZu850HvugU2C3Aq", - "Name": "Braze", - "Transformations": [] - }, - "metadata": { - "jobId": 4 - }, - "message": { - "anonymousId": "dfgdfgdfg-22b4-401d-aae5-1b994be9a969", - "groupId": "58d0a278-b55b-4f10-b7d2-98d1c5dd4c30", - "traits": { - "phone": "5055077683", - "subscriptionState": "subscribed" - }, - "userId": "user877", - "type": "group" - } - }, - { - "destination": { - "Config": { - "restApiKey": "dummyApiKey", - "prefixProperties": true, - "useNativeSDK": false, - "dataCenter": "us-01", - "enableSubscriptionGroupInGroupCall": true - }, - "DestinationDefinition": { - "DisplayName": "Braze", - "ID": "1WhbSZ6uA3H5ChVifHpfL2H6sie", - "Name": "BRAZE" - }, - "Enabled": true, - "ID": "1WhcOCGgj9asZu850HvugU2C3Aq", - "Name": "Braze", - "Transformations": [] - }, - "metadata": { - "jobId": 5 - }, - "message": { - "type": "alias", - "previousId": "adsfsaf", - "userId": "dsafsdf" - } - }, - { - "destination": { - "Config": { - "restApiKey": "dummyApiKey", - "prefixProperties": true, - "useNativeSDK": false, - "dataCenter": "us-01", - "enableSubscriptionGroupInGroupCall": true - }, - "DestinationDefinition": { - "DisplayName": "Braze", - "ID": "1WhbSZ6uA3H5ChVifHpfL2H6sie", - "Name": "BRAZE" - }, - "Enabled": true, - "ID": "1WhcOCGgj9asZu850HvugU2C3Aq", - "Name": "Braze", - "Transformations": [] - }, - "metadata": { - "jobId": 6 - }, - "message": { - "type": "alias", - "previousId": "adsfsaf2", - "userId": "dsafsdf2" - } - } - ], - "dedupEnabledRouterRequests": [ - { - "destination": { - "ID": "2N9UakqKF0D35wfzSeofIxPdL8X", - "Name": "Braze-Test", - "Config": { - "appKey": "0e5440c3-226b-45d0-91b5-c64da56cde16", - "blacklistedEvents": [], - "dataCenter": "US-03", - "enableNestedArrayOperations": false, - "enableSubscriptionGroupInGroupCall": false, - "eventFilteringOption": "disable", - "oneTrustCookieCategories": [], - "restApiKey": "dummyApiKey", - "supportDedup": true, - "trackAnonymousUser": true, - "whitelistedEvents": [] - }, - "Enabled": true, - "WorkspaceID": "27O0bhB6p5ehfOWeeZlOSsSDTLg", - "Transformations": [], - "IsProcessorEnabled": true, - "RevisionID": "2N9Uaf2tWq2QRmatBWQm03Rz6qX" - }, - "metadata": { - "jobId": 1 - }, - "message": { - "type": "track", - "event": "Sign In Completed", - "sentAt": "2023-03-10T18:36:04.738Z", - "userId": "braze_test_user", - "channel": "web", - "context": { - "locale": "en-US", - "traits": { - "subscribe_once": true, - "pwa": true, - "email": "jackson24miranda@gmail.com", - "lastName": "Miranda", - "firstName": "Spencer", - "is_registered": true, - "last_identify": "GOOGLE_SIGN_IN", - "account_region": "ON", - "is_pickup_selected": "false", - "has_tradein_attempt": false, - "custom_obj_attr": { - "key1": "value1", - "key2": "value2", - "key4": "value4" - }, - "custom_arr": [1, 2, "str1"] - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "2.9.5" - }, - "campaign": {}, - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36" - }, - "rudderId": "4118560d-e4fc-4fd1-a734-9c69eae2c047", - "messageId": "1a342814-a882-4b65-9cc9-347544997268", - "timestamp": "2023-03-10T18:36:05.028Z", - "properties": { - "cause": "/redirector", - "method": "GOOGLE", - "region": "ON", - "orderId": "6179367977099", - "order_id": "6179367977099", - "webhookurl": "https://my.test.com", - "countingMethod": "standard", - "is_first_time_signin": false - }, - "receivedAt": "2023-03-18T01:41:42.257+05:30", - "request_ip": "[::1]", - "anonymousId": "77e278c9-e984-4cdd-950c-cd0b61befd03", - "originalTimestamp": "2023-03-10T18:36:04.733Z" - } - }, - { - "destination": { - "ID": "2N9UakqKF0D35wfzSeofIxPdL8X", - "Name": "Braze-Test", - "Config": { - "appKey": "0e5440c3-226b-45d0-91b5-c64da56cde16", - "blacklistedEvents": [], - "dataCenter": "US-03", - "enableNestedArrayOperations": false, - "enableSubscriptionGroupInGroupCall": false, - "eventFilteringOption": "disable", - "oneTrustCookieCategories": [], - "restApiKey": "dummyApiKey", - "supportDedup": true, - "trackAnonymousUser": true, - "whitelistedEvents": [] - }, - "Enabled": true, - "WorkspaceID": "27O0bhB6p5ehfOWeeZlOSsSDTLg", - "Transformations": [], - "IsProcessorEnabled": true, - "RevisionID": "2N9Uaf2tWq2QRmatBWQm03Rz6qX" - }, - "metadata": { - "jobId": 2 - }, - "message": { - "type": "track", - "event": "Sign In Completed", - "sentAt": "2023-03-10T18:36:04.738Z", - "userId": "braze_test_user", - "channel": "web", - "context": { - "locale": "en-US", - "traits": { - "subscribe_once": true, - "pwa": true, - "email": "jackson24miranda@gmail.com", - "lastName": "Miranda 2", - "firstName": "Spencer", - "is_registered": true, - "last_identify": "GOOGLE_SIGN_IN", - "account_region": "ON", - "is_pickup_selected": "true", - "has_tradein_attempt": false, - "custom_obj_attr": { - "key1": "value1", - "key2": "value2", - "key4": "value4" - }, - "custom_arr": ["1", "2", "str1"] - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "2.9.5" - }, - "campaign": {}, - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36" - }, - "rudderId": "4118560d-e4fc-4fd1-a734-9c69eae2c047", - "messageId": "1a342814-a882-4b65-9cc9-347544997268", - "timestamp": "2023-03-10T18:36:05.028Z", - "properties": { - "cause": "/redirector", - "method": "GOOGLE", - "region": "ON", - "orderId": "6179367977099", - "order_id": "6179367977099", - "webhookurl": "https://my.test.com", - "countingMethod": "standard", - "is_first_time_signin": false - }, - "receivedAt": "2023-03-18T01:41:42.257+05:30", - "request_ip": "[::1]", - "anonymousId": "77e278c9-e984-4cdd-950c-cd0b61befd03", - "originalTimestamp": "2023-03-10T18:36:04.733Z" - } - } - ] -} diff --git a/test/__tests__/data/braze_router_output.json b/test/__tests__/data/braze_router_output.json deleted file mode 100644 index d3ec0581dc..0000000000 --- a/test/__tests__/data/braze_router_output.json +++ /dev/null @@ -1,281 +0,0 @@ -{ - "simpleRouterResponse": [ - { - "batchedRequest": [ - { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://rest.fra-01.braze.eu/users/track", - "headers": { - "Content-Type": "application/json", - "Accept": "application/json", - "Authorization": "Bearer dummyApiKey" - }, - "params": {}, - "body": { - "JSON": { - "partner": "RudderStack", - "events": [ - { - "name": "Page Viewed", - "time": "2020-01-24T11:59:02.402+05:30", - "properties": { - "path": "/tests/html/index2.html", - "referrer": "", - "search": "", - "title": "", - "url": "http://localhost/tests/html/index2.html" - }, - "_update_existing_only": false, - "user_alias": { - "alias_name": "e6ab2c5e-2cda-44a9-a962-e2f67df78bca", - "alias_label": "rudder_id" - } - } - ], - "attributes": [ - { - "email": "mickey@disney.com", - "city": "Disney", - "country": "USA", - "firstname": "Mickey", - "_update_existing_only": false, - "user_alias": { - "alias_name": "e6ab2c5e-2cda-44a9-a962-e2f67df78bca", - "alias_label": "rudder_id" - } - } - ] - }, - "XML": {}, - "JSON_ARRAY": {}, - "FORM": {} - }, - "files": {} - }, - { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://rest.fra-01.braze.eu/v2/subscription/status/set", - "headers": { - "Content-Type": "application/json", - "Accept": "application/json", - "Authorization": "Bearer dummyApiKey" - }, - "params": {}, - "body": { - "JSON": { - "subscription_groups": [ - { - "external_id": ["user123"], - "phones": ["5055077683"], - "subscription_group_id": "c90f0fd2-2a02-4f2f-bf07-7e7d2c2ed2b1", - "subscription_state": "subscribed" - }, - { - "external_id": ["user877"], - "phones": ["5055077683"], - "subscription_group_id": "58d0a278-b55b-4f10-b7d2-98d1c5dd4c30", - "subscription_state": "subscribed" - } - ] - }, - "XML": {}, - "JSON_ARRAY": {}, - "FORM": {} - }, - "files": {} - }, - { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://rest.fra-01.braze.eu/users/merge", - "headers": { - "Content-Type": "application/json", - "Accept": "application/json", - "Authorization": "Bearer dummyApiKey" - }, - "params": {}, - "body": { - "JSON": { - "merge_updates": [ - { - "identifier_to_keep": { - "external_id": "dsafsdf" - }, - "identifier_to_merge": { - "external_id": "adsfsaf" - } - }, - { - "identifier_to_keep": { - "external_id": "dsafsdf2" - }, - "identifier_to_merge": { - "external_id": "adsfsaf2" - } - } - ] - }, - "XML": {}, - "JSON_ARRAY": {}, - "FORM": {} - }, - "files": {} - } - ], - "metadata": [ - { - "jobId": 1 - }, - { - "jobId": 2 - }, - { - "jobId": 3 - }, - { - "jobId": 4 - }, - { - "jobId": 5 - }, - { - "jobId": 6 - } - ], - "batched": true, - "statusCode": 200, - "destination": { - "Config": { - "restApiKey": "dummyApiKey", - "prefixProperties": true, - "useNativeSDK": false, - "dataCenter": "eu-01" - }, - "DestinationDefinition": { - "DisplayName": "Braze", - "ID": "1WhbSZ6uA3H5ChVifHpfL2H6sie", - "Name": "BRAZE" - }, - "Enabled": true, - "ID": "1WhcOCGgj9asZu850HvugU2C3Aq", - "Name": "Braze", - "Transformations": [] - } - } - ], - "dedupEnabledRouterResponse": [ - { - "batchedRequest": [ - { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://rest.iad-03.braze.com/users/track", - "headers": { - "Content-Type": "application/json", - "Accept": "application/json", - "Authorization": "Bearer dummyApiKey" - }, - "params": {}, - "body": { - "JSON": { - "partner": "RudderStack", - "attributes": [ - { - "first_name": "Spencer", - "subscribe_once": true, - "pwa": true, - "external_id": "braze_test_user", - "custom_obj_attr": { - "key1": "value1", - "key2": "value2", - "key4": "value4" - } - }, - { - "last_name": "Miranda 2", - "is_pickup_selected": "true", - "external_id": "braze_test_user", - "custom_arr": ["1", "2", "str1"] - } - ], - "events": [ - { - "name": "Sign In Completed", - "time": "2023-03-10T18:36:05.028Z", - "properties": { - "cause": "/redirector", - "method": "GOOGLE", - "region": "ON", - "orderId": "6179367977099", - "order_id": "6179367977099", - "webhookurl": "https://my.test.com", - "countingMethod": "standard", - "is_first_time_signin": false - }, - "external_id": "braze_test_user" - }, - { - "name": "Sign In Completed", - "time": "2023-03-10T18:36:05.028Z", - "properties": { - "cause": "/redirector", - "method": "GOOGLE", - "region": "ON", - "orderId": "6179367977099", - "order_id": "6179367977099", - "webhookurl": "https://my.test.com", - "countingMethod": "standard", - "is_first_time_signin": false - }, - "external_id": "braze_test_user" - } - ] - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} - } - ], - "metadata": [ - { - "jobId": 1 - }, - { - "jobId": 2 - } - ], - "batched": true, - "statusCode": 200, - "destination": { - "ID": "2N9UakqKF0D35wfzSeofIxPdL8X", - "Name": "Braze-Test", - "Config": { - "appKey": "0e5440c3-226b-45d0-91b5-c64da56cde16", - "blacklistedEvents": [], - "dataCenter": "US-03", - "enableNestedArrayOperations": false, - "enableSubscriptionGroupInGroupCall": false, - "eventFilteringOption": "disable", - "oneTrustCookieCategories": [], - "restApiKey": "dummyApiKey", - "supportDedup": true, - "trackAnonymousUser": true, - "whitelistedEvents": [] - }, - "Enabled": true, - "WorkspaceID": "27O0bhB6p5ehfOWeeZlOSsSDTLg", - "Transformations": [], - "IsProcessorEnabled": true, - "RevisionID": "2N9Uaf2tWq2QRmatBWQm03Rz6qX" - } - } - ] -} diff --git a/test/__tests__/data/klaviyo.json b/test/__tests__/data/klaviyo.json index 1fc46a6e4c..796d9ed8e0 100644 --- a/test/__tests__/data/klaviyo.json +++ b/test/__tests__/data/klaviyo.json @@ -1,11 +1,11 @@ [ { - "description": "Profile updation call and subcribe user", + "description": "Profile updating call and subscribe user (old transformer)", "input": { "destination": { "Config": { - "publicApiKey": "WJqij9", - "privateApiKey": "pk_b68c7b5163d98807fcb57e6f921216629d" + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey" } }, "message": { @@ -71,9 +71,9 @@ "method": "PATCH", "endpoint": "https://a.klaviyo.com/api/profiles/01GW3PHVY0MTCDGS0A1612HARX", "headers": { - "Accept": "application/json", - "Authorization": "Klaviyo-API-Key pk_b68c7b5163d98807fcb57e6f921216629d", + "Authorization": "Klaviyo-API-Key dummyPrivateApiKey", "Content-Type": "application/json", + "Accept": "application/json", "revision": "2023-02-22" }, "params": {}, @@ -117,7 +117,7 @@ "headers": { "Content-Type": "application/json", "Accept": "application/json", - "Authorization": "Klaviyo-API-Key pk_b68c7b5163d98807fcb57e6f921216629d", + "Authorization": "Klaviyo-API-Key dummyPrivateApiKey", "revision": "2023-02-22" }, "params": {}, @@ -149,12 +149,12 @@ ] }, { - "description": "Identify call for with flattenProperties enabled", + "description": "Identify call for with flattenProperties enabled (old transformer)", "input": { "destination": { "Config": { - "publicApiKey": "WJqij9", - "privateApiKey": "pk_b68c7b5163d98807fcb57e6f921216629d", + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey", "flattenProperties": true } }, @@ -228,9 +228,9 @@ "method": "PATCH", "endpoint": "https://a.klaviyo.com/api/profiles/01GW3PHVY0MTCDGS0A1612HARX", "headers": { - "Accept": "application/json", - "Authorization": "Klaviyo-API-Key pk_b68c7b5163d98807fcb57e6f921216629d", + "Authorization": "Klaviyo-API-Key dummyPrivateApiKey", "Content-Type": "application/json", + "Accept": "application/json", "revision": "2023-02-22" }, "params": {}, @@ -253,11 +253,11 @@ "zip": "100-0001" }, "properties": { - "Flagged": false, - "Residence": "Shibuya", "friend.age": 25, "friend.names.first": "Alice", - "friend.names.last": "Smith" + "friend.names.last": "Smith", + "Flagged": false, + "Residence": "Shibuya" } }, "id": "01GW3PHVY0MTCDGS0A1612HARX" @@ -277,7 +277,7 @@ "headers": { "Content-Type": "application/json", "Accept": "application/json", - "Authorization": "Klaviyo-API-Key pk_b68c7b5163d98807fcb57e6f921216629d", + "Authorization": "Klaviyo-API-Key dummyPrivateApiKey", "revision": "2023-02-22" }, "params": {}, @@ -313,8 +313,8 @@ "input": { "destination": { "Config": { - "publicApiKey": "WJqij9", - "privateApiKey": "pk_b68c7b5163d98807fcb57e6f921216629d" + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey" } }, "message": { @@ -382,8 +382,8 @@ "input": { "destination": { "Config": { - "publicApiKey": "WJqij9", - "privateApiKey": "pk_b68c7b5163d98807fcb57e6f921216629d" + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey" } }, "message": { @@ -447,9 +447,9 @@ "method": "PATCH", "endpoint": "https://a.klaviyo.com/api/profiles/01GW3PHVY0MTCDGS0A1612HARX", "headers": { - "Accept": "application/json", - "Authorization": "Klaviyo-API-Key pk_b68c7b5163d98807fcb57e6f921216629d", + "Authorization": "Klaviyo-API-Key dummyPrivateApiKey", "Content-Type": "application/json", + "Accept": "application/json", "revision": "2023-02-22" }, "params": {}, @@ -491,8 +491,8 @@ "input": { "destination": { "Config": { - "publicApiKey": "WJqij9", - "privateApiKey": "pk_b68c7b5163d98807fcb57e6f921216629d", + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey", "enforceEmailAsPrimary": true } }, @@ -559,9 +559,9 @@ "method": "PATCH", "endpoint": "https://a.klaviyo.com/api/profiles/01GW3PHVY0MTCDGS0A1612HARX", "headers": { - "Accept": "application/json", - "Authorization": "Klaviyo-API-Key pk_b68c7b5163d98807fcb57e6f921216629d", + "Authorization": "Klaviyo-API-Key dummyPrivateApiKey", "Content-Type": "application/json", + "Accept": "application/json", "revision": "2023-02-22" }, "params": {}, @@ -605,7 +605,7 @@ "headers": { "Content-Type": "application/json", "Accept": "application/json", - "Authorization": "Klaviyo-API-Key pk_b68c7b5163d98807fcb57e6f921216629d", + "Authorization": "Klaviyo-API-Key dummyPrivateApiKey", "revision": "2023-02-22" }, "params": {}, @@ -641,8 +641,8 @@ "input": { "destination": { "Config": { - "publicApiKey": "WJqij9", - "privateApiKey": "pk_b68c7b5163d98807fcb57e6f921216629d", + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey", "enforceEmailAsPrimary": true } }, @@ -709,8 +709,8 @@ "input": { "destination": { "Config": { - "publicApiKey": "WJqij9", - "privateApiKey": "pk_b68c7b5163d98807fcb57e6f921216629d" + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey" } }, "message": { @@ -784,7 +784,7 @@ "endpoint": "https://a.klaviyo.com/api/events", "headers": { "Accept": "application/json", - "Authorization": "Klaviyo-API-Key pk_b68c7b5163d98807fcb57e6f921216629d", + "Authorization": "Klaviyo-API-Key dummyPrivateApiKey", "Content-Type": "application/json", "revision": "2023-02-22" }, @@ -823,8 +823,8 @@ "input": { "destination": { "Config": { - "publicApiKey": "WJqij9", - "privateApiKey": "pk_b68c7b5163d98807fcb57e6f921216629d", + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey", "flattenProperties": true } }, @@ -905,7 +905,7 @@ "endpoint": "https://a.klaviyo.com/api/events", "headers": { "Accept": "application/json", - "Authorization": "Klaviyo-API-Key pk_b68c7b5163d98807fcb57e6f921216629d", + "Authorization": "Klaviyo-API-Key dummyPrivateApiKey", "Content-Type": "application/json", "revision": "2023-02-22" }, @@ -946,8 +946,8 @@ "input": { "destination": { "Config": { - "publicApiKey": "WJqij9", - "privateApiKey": "pk_b68c7b5163d98807fcb57e6f921216629d" + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey" } }, "message": { @@ -1024,7 +1024,7 @@ "endpoint": "https://a.klaviyo.com/api/events", "headers": { "Accept": "application/json", - "Authorization": "Klaviyo-API-Key pk_b68c7b5163d98807fcb57e6f921216629d", + "Authorization": "Klaviyo-API-Key dummyPrivateApiKey", "Content-Type": "application/json", "revision": "2023-02-22" }, @@ -1066,8 +1066,8 @@ "input": { "destination": { "Config": { - "publicApiKey": "WJqij9", - "privateApiKey": "pk_b68c7b5163d98807fcb57e6f921216629d", + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey", "enforceEmailAsPrimary": true } }, @@ -1142,7 +1142,7 @@ "endpoint": "https://a.klaviyo.com/api/events", "headers": { "Accept": "application/json", - "Authorization": "Klaviyo-API-Key pk_b68c7b5163d98807fcb57e6f921216629d", + "Authorization": "Klaviyo-API-Key dummyPrivateApiKey", "Content-Type": "application/json", "revision": "2023-02-22" }, @@ -1181,8 +1181,8 @@ "input": { "destination": { "Config": { - "publicApiKey": "WJqij9", - "privateApiKey": "pk_b68c7b5163d98807fcb57e6f921216629d", + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey", "enforceEmailAsPrimary": true } }, @@ -1257,8 +1257,8 @@ "input": { "destination": { "Config": { - "publicApiKey": "WJqij9", - "privateApiKey": "pk_b68c7b5163d98807fcb57e6f921216629d" + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey" } }, "message": { @@ -1291,7 +1291,7 @@ "headers": { "Content-Type": "application/json", "Accept": "application/json", - "Authorization": "Klaviyo-API-Key pk_b68c7b5163d98807fcb57e6f921216629d", + "Authorization": "Klaviyo-API-Key dummyPrivateApiKey", "revision": "2023-02-22" }, "params": {}, @@ -1323,8 +1323,8 @@ "input": { "destination": { "Config": { - "publicApiKey": "WJqij9", - "privateApiKey": "pk_b68c7b5163d98807fcb57e6f921216629d" + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey" } }, "message": { @@ -1357,8 +1357,8 @@ "input": { "destination": { "Config": { - "publicApiKey": "WJqij9", - "privateApiKey": "pk_b68c7b5163d98807fcb57e6f921216629d" + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey" } }, "message": { @@ -1391,8 +1391,8 @@ "input": { "destination": { "Config": { - "publicApiKey": "WJqij9", - "privateApiKey": "pk_b68c7b5163d98807fcb57e6f921216629d" + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey" } }, "message": { @@ -1472,7 +1472,7 @@ "method": "POST", "endpoint": "https://a.klaviyo.com/api/events", "headers": { - "Authorization": "Klaviyo-API-Key pk_b68c7b5163d98807fcb57e6f921216629d", + "Authorization": "Klaviyo-API-Key dummyPrivateApiKey", "Content-Type": "application/json", "Accept": "application/json", "revision": "2023-02-22" @@ -1519,8 +1519,8 @@ "input": { "destination": { "Config": { - "publicApiKey": "WJqij9", - "privateApiKey": "pk_b68c7b5163d98807fcb57e6f921216629d", + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey", "flattenProperties": true } }, @@ -1622,7 +1622,7 @@ "method": "POST", "endpoint": "https://a.klaviyo.com/api/events", "headers": { - "Authorization": "Klaviyo-API-Key pk_b68c7b5163d98807fcb57e6f921216629d", + "Authorization": "Klaviyo-API-Key dummyPrivateApiKey", "Content-Type": "application/json", "Accept": "application/json", "revision": "2023-02-22" @@ -1675,8 +1675,8 @@ "input": { "destination": { "Config": { - "publicApiKey": "WJqij9", - "privateApiKey": "pk_b68c7b5163d98807fcb57e6f921216629d" + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey" } }, "message": { @@ -1769,7 +1769,7 @@ "method": "POST", "endpoint": "https://a.klaviyo.com/api/events", "headers": { - "Authorization": "Klaviyo-API-Key pk_b68c7b5163d98807fcb57e6f921216629d", + "Authorization": "Klaviyo-API-Key dummyPrivateApiKey", "Content-Type": "application/json", "Accept": "application/json", "revision": "2023-02-22" diff --git a/test/__tests__/data/klaviyo_router.json b/test/__tests__/data/klaviyo_router.json new file mode 100644 index 0000000000..da857369f1 --- /dev/null +++ b/test/__tests__/data/klaviyo_router.json @@ -0,0 +1,599 @@ +[ + { + "description": "Router tests", + "input": [ + { + "destination": { + "Config": { + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey" + } + }, + "metadata": { + "jobId": 1 + }, + "message": { + "type": "identify", + "sentAt": "2021-01-03T17:02:53.195Z", + "userId": "test", + "channel": "web", + "context": { + "os": { + "name": "", + "version": "" + }, + "app": { + "name": "RudderLabs JavaScript SDK", + "build": "1.0.0", + "version": "1.1.11", + "namespace": "com.rudderlabs.javascript" + }, + "traits": { + "firstName": "Test", + "lastName": "Rudderlabs", + "email": "test@rudderstack.com", + "phone": "+12 345 578 900", + "userId": "Testc", + "title": "Developer", + "organization": "Rudder", + "city": "Tokyo", + "region": "Kanto", + "country": "JP", + "zip": "100-0001", + "Flagged": false, + "Residence": "Shibuya", + "properties": { + "consent": ["email", "sms"] + } + }, + "locale": "en-US", + "screen": { + "density": 2 + }, + "library": { + "name": "RudderLabs JavaScript SDK", + "version": "1.1.11" + }, + "campaign": {}, + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.16; rv:84.0) Gecko/20100101 Firefox/84.0" + }, + "rudderId": "8f8fa6b5-8e24-489c-8e22-61f23f2e364f", + "messageId": "2116ef8c-efc3-4ca4-851b-02ee60dad6ff", + "anonymousId": "97c46c81-3140-456d-b2a9-690d70aaca35", + "integrations": { + "All": true + }, + "originalTimestamp": "2021-01-03T17:02:53.193Z" + } + }, + { + "destination": { + "Config": { + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey" + } + }, + "metadata": { + "jobId": 2 + }, + "message": { + "type": "identify", + "sentAt": "2021-01-03T17:02:53.195Z", + "userId": "test", + "channel": "web", + "context": { + "os": { + "name": "", + "version": "" + }, + "app": { + "name": "RudderLabs JavaScript SDK", + "build": "1.0.0", + "version": "1.1.11", + "namespace": "com.rudderlabs.javascript" + }, + "traits": { + "firstName": "Test", + "lastName": "Rudderlabs", + "email": "test@rudderstack.com", + "phone": "+12 345 578 900", + "userId": "test", + "title": "Developer", + "organization": "Rudder", + "city": "Tokyo", + "region": "Kanto", + "country": "JP", + "zip": "100-0001", + "Flagged": false, + "Residence": "Shibuya", + "properties": { + "listId": "XUepkK", + "subscribe": true, + "consent": ["email", "sms"] + } + }, + "locale": "en-US", + "screen": { + "density": 2 + }, + "library": { + "name": "RudderLabs JavaScript SDK", + "version": "1.1.11" + }, + "campaign": {}, + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.16; rv:84.0) Gecko/20100101 Firefox/84.0" + }, + "rudderId": "8f8fa6b5-8e24-489c-8e22-61f23f2e364f", + "messageId": "2116ef8c-efc3-4ca4-851b-02ee60dad6ff", + "anonymousId": "97c46c81-3140-456d-b2a9-690d70aaca35", + "integrations": { + "All": true + }, + "originalTimestamp": "2021-01-03T17:02:53.193Z" + } + }, + { + "destination": { + "Config": { + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey" + } + }, + "metadata": { + "jobId": 3 + }, + "message": { + "userId": "user123", + "type": "group", + "groupId": "XUepkK", + "traits": { + "subscribe": true + }, + "context": { + "traits": { + "email": "test@rudderstack.com", + "phone": "+12 345 678 900", + "consent": ["email"] + }, + "ip": "14.5.67.21", + "library": { + "name": "http" + } + }, + "timestamp": "2020-01-21T00:21:34.208Z" + } + }, + { + "destination": { + "Config": { + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey" + } + }, + "metadata": { + "jobId": 4 + }, + "message": { + "userId": "user123", + "type": "random", + "groupId": "XUepkK", + "traits": { + "subscribe": true + }, + "context": { + "traits": { + "email": "test@rudderstack.com", + "phone": "+12 345 678 900", + "consent": "email" + }, + "ip": "14.5.67.21", + "library": { + "name": "http" + } + }, + "timestamp": "2020-01-21T00:21:34.208Z" + } + }, + { + "destination": { + "Config": { + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey" + } + }, + "metadata": { + "jobId": 5 + }, + "message": { + "userId": "user123", + "type": "group", + "groupId": "", + "traits": { + "subscribe": true + }, + "context": { + "traits": { + "email": "test@rudderstack.com", + "phone": "+12 345 678 900", + "consent": "email" + }, + "ip": "14.5.67.21", + "library": { + "name": "http" + } + }, + "timestamp": "2020-01-21T00:21:34.208Z" + } + } + ], + "newTransformerOutput": [ + { + "batchedRequest": [ + { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://a.klaviyo.com/api/profile-subscription-bulk-create-jobs", + "headers": { + "Authorization": "Klaviyo-API-Key dummyPrivateApiKey", + "Content-Type": "application/json", + "Accept": "application/json", + "revision": "2023-02-22" + }, + "params": {}, + "body": { + "JSON": { + "data": { + "type": "profile-subscription-bulk-create-job", + "attributes": { + "list_id": "XUepkK", + "subscriptions": [ + { + "email": "test@rudderstack.com", + "phone_number": "+12 345 678 900" + }, + { + "email": "test@rudderstack.com", + "phone_number": "+12 345 578 900", + "channels": { + "email": ["MARKETING"], + "sms": ["MARKETING"] + } + } + ] + } + } + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {} + } + ], + "metadata": [ + { + "jobId": 3 + }, + { + "jobId": 2 + } + ], + "batched": true, + "statusCode": 200, + "destination": { + "Config": { + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey" + } + } + }, + { + "batchedRequest": { + "version": "1", + "type": "REST", + "method": "PATCH", + "endpoint": "https://a.klaviyo.com/api/profiles/01GW3PHVY0MTCDGS0A1612HARX", + "headers": { + "Authorization": "Klaviyo-API-Key dummyPrivateApiKey", + "Content-Type": "application/json", + "Accept": "application/json", + "revision": "2023-02-22" + }, + "params": {}, + "body": { + "JSON": { + "data": { + "type": "profile", + "attributes": { + "external_id": "test", + "email": "test@rudderstack.com", + "first_name": "Test", + "last_name": "Rudderlabs", + "phone_number": "+12 345 578 900", + "title": "Developer", + "organization": "Rudder", + "location": { + "city": "Tokyo", + "region": "Kanto", + "country": "JP", + "zip": "100-0001" + }, + "properties": { + "Flagged": false, + "Residence": "Shibuya" + } + }, + "id": "01GW3PHVY0MTCDGS0A1612HARX" + } + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {}, + "error": "{\"id\":\"01GW3PHVY0MTCDGS0A1612HARX\",\"attributes\":{}}" + }, + "metadata": [ + { + "jobId": 1 + } + ], + "batched": false, + "statusCode": 299, + "destination": { + "Config": { + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey" + } + } + }, + { + "error": "Event type random is not supported", + "metadata": [ + { + "jobId": 4 + } + ], + "batched": false, + "statTags": { + "errorCategory": "dataValidation", + "errorType": "instrumentation" + }, + "statusCode": 400, + "destination": { + "Config": { + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey" + } + } + }, + { + "error": "groupId is a required field for group events", + "metadata": [ + { + "jobId": 5 + } + ], + "batched": false, + "statTags": { + "errorCategory": "dataValidation", + "errorType": "instrumentation" + }, + "statusCode": 400, + "destination": { + "Config": { + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey" + } + } + } + ], + "oldTransformerOutput": [ + { + "batchedRequest": [ + { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://a.klaviyo.com/api/profile-subscription-bulk-create-jobs", + "headers": { + "Authorization": "Klaviyo-API-Key dummyPrivateApiKey", + "Content-Type": "application/json", + "Accept": "application/json", + "revision": "2023-02-22" + }, + "params": {}, + "body": { + "JSON": { + "data": { + "type": "profile-subscription-bulk-create-job", + "attributes": { + "list_id": "XUepkK", + "subscriptions": [ + { + "email": "test@rudderstack.com", + "phone_number": "+12 345 678 900" + }, + { + "email": "test@rudderstack.com", + "phone_number": "+12 345 578 900", + "channels": { + "email": ["MARKETING"], + "sms": ["MARKETING"] + } + } + ] + } + } + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {} + }, + { + "version": "1", + "type": "REST", + "method": "PATCH", + "endpoint": "https://a.klaviyo.com/api/profiles/01GW3PHVY0MTCDGS0A1612HARX", + "headers": { + "Authorization": "Klaviyo-API-Key dummyPrivateApiKey", + "Content-Type": "application/json", + "Accept": "application/json", + "revision": "2023-02-22" + }, + "params": {}, + "body": { + "JSON": { + "data": { + "type": "profile", + "attributes": { + "external_id": "test", + "email": "test@rudderstack.com", + "first_name": "Test", + "last_name": "Rudderlabs", + "phone_number": "+12 345 578 900", + "title": "Developer", + "organization": "Rudder", + "location": { + "city": "Tokyo", + "region": "Kanto", + "country": "JP", + "zip": "100-0001" + }, + "properties": { + "Flagged": false, + "Residence": "Shibuya" + } + }, + "id": "01GW3PHVY0MTCDGS0A1612HARX" + } + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {} + } + ], + "metadata": [ + { + "jobId": 3 + }, + { + "jobId": 2 + } + ], + "batched": true, + "statusCode": 200, + "destination": { + "Config": { + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey" + } + } + }, + { + "batchedRequest": { + "version": "1", + "type": "REST", + "method": "PATCH", + "endpoint": "https://a.klaviyo.com/api/profiles/01GW3PHVY0MTCDGS0A1612HARX", + "headers": { + "Authorization": "Klaviyo-API-Key dummyPrivateApiKey", + "Content-Type": "application/json", + "Accept": "application/json", + "revision": "2023-02-22" + }, + "params": {}, + "body": { + "JSON": { + "data": { + "type": "profile", + "attributes": { + "external_id": "test", + "email": "test@rudderstack.com", + "first_name": "Test", + "last_name": "Rudderlabs", + "phone_number": "+12 345 578 900", + "title": "Developer", + "organization": "Rudder", + "location": { + "city": "Tokyo", + "region": "Kanto", + "country": "JP", + "zip": "100-0001" + }, + "properties": { + "Flagged": false, + "Residence": "Shibuya" + } + }, + "id": "01GW3PHVY0MTCDGS0A1612HARX" + } + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {} + }, + "metadata": [ + { + "jobId": 1 + } + ], + "batched": false, + "statusCode": 200, + "destination": { + "Config": { + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey" + } + } + }, + { + "metadata": [ + { + "jobId": 4 + } + ], + "batched": false, + "statusCode": 400, + "error": "Event type random is not supported", + "statTags": { + "errorCategory": "dataValidation", + "errorType": "instrumentation" + }, + "destination": { + "Config": { + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey" + } + } + }, + { + "metadata": [ + { + "jobId": 5 + } + ], + "batched": false, + "statusCode": 400, + "error": "groupId is a required field for group events", + "statTags": { + "errorCategory": "dataValidation", + "errorType": "instrumentation" + }, + "destination": { + "Config": { + "publicApiKey": "dummyPublicApiKey", + "privateApiKey": "dummyPrivateApiKey" + } + } + } + ] + } +] diff --git a/test/__tests__/data/klaviyo_router_input.json b/test/__tests__/data/klaviyo_router_input.json deleted file mode 100644 index 9150bc5522..0000000000 --- a/test/__tests__/data/klaviyo_router_input.json +++ /dev/null @@ -1,227 +0,0 @@ -[ - { - "destination": { - "Config": { - "publicApiKey": "WJqij9", - "privateApiKey": "pk_b68c7b5163d98807fcb57e6f921216629d" - } - }, - "metadata": { - "jobId": 1 - }, - "message": { - "type": "identify", - "sentAt": "2021-01-03T17:02:53.195Z", - "userId": "test", - "channel": "web", - "context": { - "os": { - "name": "", - "version": "" - }, - "app": { - "name": "RudderLabs JavaScript SDK", - "build": "1.0.0", - "version": "1.1.11", - "namespace": "com.rudderlabs.javascript" - }, - "traits": { - "firstName": "Test", - "lastName": "Rudderlabs", - "email": "test@rudderstack.com", - "phone": "+12 345 578 900", - "userId": "Testc", - "title": "Developer", - "organization": "Rudder", - "city": "Tokyo", - "region": "Kanto", - "country": "JP", - "zip": "100-0001", - "Flagged": false, - "Residence": "Shibuya", - "properties": { - "listId": "XUepkK", - "subscribe": true, - "consent": ["email", "sms"] - } - }, - "locale": "en-US", - "screen": { - "density": 2 - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.1.11" - }, - "campaign": {}, - "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.16; rv:84.0) Gecko/20100101 Firefox/84.0" - }, - "rudderId": "8f8fa6b5-8e24-489c-8e22-61f23f2e364f", - "messageId": "2116ef8c-efc3-4ca4-851b-02ee60dad6ff", - "anonymousId": "97c46c81-3140-456d-b2a9-690d70aaca35", - "integrations": { - "All": true - }, - "originalTimestamp": "2021-01-03T17:02:53.193Z" - } - }, - { - "destination": { - "Config": { - "publicApiKey": "WJqij9", - "privateApiKey": "pk_b68c7b5163d98807fcb57e6f921216629d" - } - }, - "metadata": { - "jobId": 2 - }, - "message": { - "type": "identify", - "sentAt": "2021-01-03T17:02:53.195Z", - "userId": "test", - "channel": "web", - "context": { - "os": { - "name": "", - "version": "" - }, - "app": { - "name": "RudderLabs JavaScript SDK", - "build": "1.0.0", - "version": "1.1.11", - "namespace": "com.rudderlabs.javascript" - }, - "traits": { - "firstName": "Test", - "lastName": "Rudderlabs", - "email": "test@rudderstack.com", - "phone": "+12 345 578 900", - "userId": "test", - "title": "Developer", - "organization": "Rudder", - "city": "Tokyo", - "region": "Kanto", - "country": "JP", - "zip": "100-0001", - "Flagged": false, - "Residence": "Shibuya", - "properties": { - "listId": "XUepkK", - "subscribe": true, - "consent": ["email", "sms"] - } - }, - "locale": "en-US", - "screen": { - "density": 2 - }, - "library": { - "name": "RudderLabs JavaScript SDK", - "version": "1.1.11" - }, - "campaign": {}, - "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.16; rv:84.0) Gecko/20100101 Firefox/84.0" - }, - "rudderId": "8f8fa6b5-8e24-489c-8e22-61f23f2e364f", - "messageId": "2116ef8c-efc3-4ca4-851b-02ee60dad6ff", - "anonymousId": "97c46c81-3140-456d-b2a9-690d70aaca35", - "integrations": { - "All": true - }, - "originalTimestamp": "2021-01-03T17:02:53.193Z" - } - }, - { - "destination": { - "Config": { - "publicApiKey": "WJqij9", - "privateApiKey": "pk_b68c7b5163d98807fcb57e6f921216629d" - } - }, - "metadata": { - "jobId": 3 - }, - "message": { - "userId": "user123", - "type": "group", - "groupId": "XUepkK", - "traits": { - "subscribe": true - }, - "context": { - "traits": { - "email": "test@rudderstack.com", - "phone": "+12 345 678 900", - "consent": ["email"] - }, - "ip": "14.5.67.21", - "library": { - "name": "http" - } - }, - "timestamp": "2020-01-21T00:21:34.208Z" - } - }, - { - "destination": { - "Config": { - "publicApiKey": "WJqij9", - "privateApiKey": "pk_b68c7b5163d98807fcb57e6f921216629d" - } - }, - "metadata": { - "jobId": 4 - }, - "message": { - "userId": "user123", - "type": "random", - "groupId": "XUepkK", - "traits": { - "subscribe": true - }, - "context": { - "traits": { - "email": "test@rudderstack.com", - "phone": "+12 345 678 900", - "consent": "email" - }, - "ip": "14.5.67.21", - "library": { - "name": "http" - } - }, - "timestamp": "2020-01-21T00:21:34.208Z" - } - }, - { - "destination": { - "Config": { - "publicApiKey": "WJqij9", - "privateApiKey": "pk_b68c7b5163d98807fcb57e6f921216629d" - } - }, - "metadata": { - "jobId": 5 - }, - "message": { - "userId": "user123", - "type": "group", - "groupId": "", - "traits": { - "subscribe": true - }, - "context": { - "traits": { - "email": "test@rudderstack.com", - "phone": "+12 345 678 900", - "consent": "email" - }, - "ip": "14.5.67.21", - "library": { - "name": "http" - } - }, - "timestamp": "2020-01-21T00:21:34.208Z" - } - } -] diff --git a/test/__tests__/data/klaviyo_router_output.json b/test/__tests__/data/klaviyo_router_output.json deleted file mode 100644 index fbc9ad65cf..0000000000 --- a/test/__tests__/data/klaviyo_router_output.json +++ /dev/null @@ -1,202 +0,0 @@ -[ - { - "batchedRequest": [ - { - "version": "1", - "type": "REST", - "method": "POST", - "endpoint": "https://a.klaviyo.com/api/profile-subscription-bulk-create-jobs", - "headers": { - "Content-Type": "application/json", - "Accept": "application/json", - "Authorization": "Klaviyo-API-Key pk_b68c7b5163d98807fcb57e6f921216629d", - "revision": "2023-02-22" - }, - "params": {}, - "body": { - "JSON": { - "data": { - "type": "profile-subscription-bulk-create-job", - "attributes": { - "list_id": "XUepkK", - "subscriptions": [ - { - "email": "test@rudderstack.com", - "phone_number": "+12 345 678 900" - }, - { - "email": "test@rudderstack.com", - "phone_number": "+12 345 578 900", - "channels": { - "email": ["MARKETING"], - "sms": ["MARKETING"] - } - }, - { - "email": "test@rudderstack.com", - "phone_number": "+12 345 578 900", - "channels": { - "email": ["MARKETING"], - "sms": ["MARKETING"] - } - } - ] - } - } - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} - }, - { - "version": "1", - "type": "REST", - "method": "PATCH", - "endpoint": "https://a.klaviyo.com/api/profiles/01GW3PHVY0MTCDGS0A1612HARX", - "headers": { - "Accept": "application/json", - "Authorization": "Klaviyo-API-Key pk_b68c7b5163d98807fcb57e6f921216629d", - "Content-Type": "application/json", - "revision": "2023-02-22" - }, - "params": {}, - "body": { - "JSON": { - "data": { - "type": "profile", - "attributes": { - "external_id": "test", - "email": "test@rudderstack.com", - "first_name": "Test", - "last_name": "Rudderlabs", - "phone_number": "+12 345 578 900", - "title": "Developer", - "organization": "Rudder", - "location": { - "city": "Tokyo", - "region": "Kanto", - "country": "JP", - "zip": "100-0001" - }, - "properties": { - "Flagged": false, - "Residence": "Shibuya" - } - }, - "id": "01GW3PHVY0MTCDGS0A1612HARX" - } - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} - }, - { - "version": "1", - "type": "REST", - "method": "PATCH", - "endpoint": "https://a.klaviyo.com/api/profiles/01GW3PHVY0MTCDGS0A1612HARX", - "headers": { - "Accept": "application/json", - "Authorization": "Klaviyo-API-Key pk_b68c7b5163d98807fcb57e6f921216629d", - "Content-Type": "application/json", - "revision": "2023-02-22" - }, - "params": {}, - "body": { - "JSON": { - "data": { - "type": "profile", - "attributes": { - "email": "test@rudderstack.com", - "external_id": "test", - "first_name": "Test", - "last_name": "Rudderlabs", - "phone_number": "+12 345 578 900", - "title": "Developer", - "organization": "Rudder", - "location": { - "city": "Tokyo", - "region": "Kanto", - "country": "JP", - "zip": "100-0001" - }, - "properties": { - "Flagged": false, - "Residence": "Shibuya" - } - }, - "id": "01GW3PHVY0MTCDGS0A1612HARX" - } - }, - "JSON_ARRAY": {}, - "XML": {}, - "FORM": {} - }, - "files": {} - } - ], - "metadata": [ - { - "jobId": 3 - }, - { - "jobId": 1 - }, - { - "jobId": 2 - } - ], - "batched": true, - "statusCode": 200, - "destination": { - "Config": { - "publicApiKey": "WJqij9", - "privateApiKey": "pk_b68c7b5163d98807fcb57e6f921216629d" - } - } - }, - { - "error": "Event type random is not supported", - "metadata": [ - { - "jobId": 4 - } - ], - "batched": false, - "statTags": { - "errorCategory": "dataValidation", - "errorType": "instrumentation" - }, - "statusCode": 400, - "destination": { - "Config": { - "publicApiKey": "WJqij9", - "privateApiKey": "pk_b68c7b5163d98807fcb57e6f921216629d" - } - } - }, - { - "error": "groupId is a required field for group events", - "metadata": [ - { - "jobId": 5 - } - ], - "batched": false, - "statTags": { - "errorCategory": "dataValidation", - "errorType": "instrumentation" - }, - "statusCode": 400, - "destination": { - "Config": { - "publicApiKey": "WJqij9", - "privateApiKey": "pk_b68c7b5163d98807fcb57e6f921216629d" - } - } - } -] diff --git a/test/__tests__/klaviyo.test.js b/test/__tests__/klaviyo.test.js index 871bf1f28c..209811b007 100644 --- a/test/__tests__/klaviyo.test.js +++ b/test/__tests__/klaviyo.test.js @@ -5,6 +5,7 @@ const integration = "klaviyo"; const name = "Klaviyo"; const version = "v0"; +const { FEATURE_FILTER_CODE } = require('../../src/v0/util/constant'); const transformer = require(`../../src/${version}/destinations/${integration}/transform`); // Processor Test Data @@ -14,14 +15,10 @@ const testDataFile = fs.readFileSync( const testData = JSON.parse(testDataFile); // Router Test Data -const inputRouterDataFile = fs.readFileSync( - path.resolve(__dirname, `./data/${integration}_router_input.json`) +const routerTestDataFile = fs.readFileSync( + path.resolve(__dirname, `./data/${integration}_router.json`) ); -const outputRouterDataFile = fs.readFileSync( - path.resolve(__dirname, `./data/${integration}_router_output.json`) -); -const inputRouterData = JSON.parse(inputRouterDataFile); -const expectedRouterData = JSON.parse(outputRouterDataFile); +const routerTestData = JSON.parse(routerTestDataFile); describe(`${name} Tests`, () => { describe("Processor", () => { @@ -37,10 +34,14 @@ describe(`${name} Tests`, () => { }); }); - describe("Router Tests", () => { - it("Payload", async () => { - const routerOutput = await transformer.processRouterDest(inputRouterData); - expect(routerOutput).toEqual(expectedRouterData); + describe("Router", () => { + routerTestData.forEach((dataPoint, index) => { + it(`${index}. ${integration} - ${dataPoint.description}`, async () => { + const oldTransformerOutput = await transformer.processRouterDest(dataPoint.input); + const newTransformerOutput = await transformer.processRouterDest(dataPoint.input, { features: { [FEATURE_FILTER_CODE]: true } }); + expect(oldTransformerOutput).toEqual(dataPoint.oldTransformerOutput); + expect(newTransformerOutput).toEqual(dataPoint.newTransformerOutput); + }); }); }); });