From 3522abff73fa50fd40ee21b36a4895761872a348 Mon Sep 17 00:00:00 2001 From: shrouti1507 Date: Tue, 30 Apr 2024 13:09:16 +0530 Subject: [PATCH] fix: emersys unit test cases --- src/cdk/v2/destinations/emersys/config.js | 1 + src/cdk/v2/destinations/emersys/utils.js | 62 ++++----- src/cdk/v2/destinations/emersys/utils.test.js | 127 +++++++++++++++++- 3 files changed, 157 insertions(+), 33 deletions(-) diff --git a/src/cdk/v2/destinations/emersys/config.js b/src/cdk/v2/destinations/emersys/config.js index 604cac8cec..cbbf00f753 100644 --- a/src/cdk/v2/destinations/emersys/config.js +++ b/src/cdk/v2/destinations/emersys/config.js @@ -5,4 +5,5 @@ module.exports = { EMAIL_FIELD_ID: 3, OPT_IN_FILED_ID: 31, ALLOWED_OPT_IN_VALUES, + MAX_BATCH_SIZE_BYTES: 8000000, // 8 MB }; diff --git a/src/cdk/v2/destinations/emersys/utils.js b/src/cdk/v2/destinations/emersys/utils.js index f1aa5cdf2b..4dd515dc45 100644 --- a/src/cdk/v2/destinations/emersys/utils.js +++ b/src/cdk/v2/destinations/emersys/utils.js @@ -17,20 +17,21 @@ const { MAX_BATCH_SIZE, OPT_IN_FILED_ID, ALLOWED_OPT_IN_VALUES, + MAX_BATCH_SIZE_BYTES, } = require('./config'); -function base64Sha(str) { +const base64Sha = (str) => { const hexDigest = crypto.createHash('sha1').update(str).digest('hex'); return Buffer.from(hexDigest).toString('base64'); -} +}; -function getWsseHeader(user, secret) { +const getWsseHeader = (user, secret) => { const nonce = crypto.randomBytes(16).toString('hex'); const timestamp = new Date().toISOString(); const digest = base64Sha(nonce + timestamp + secret); return `UsernameToken Username="${user}", PasswordDigest="${digest}", Nonce="${nonce}", Created="${timestamp}"`; -} +}; const buildHeader = (destConfig) => { const { emersysUsername, emersysUserSecret } = destConfig; @@ -96,12 +97,12 @@ const buildIdentifyPayload = (message, destination) => { return { eventType: message.type, destinationPayload }; }; -function findRudderPropertyByEmersysProperty(emersysProperty, fieldMapping) { +const findRudderPropertyByEmersysProperty = (emersysProperty, fieldMapping) => { // Use lodash to find the object where the emersysProperty matches the input const item = lodash.find(fieldMapping, { emersysProperty }); // Return the rudderProperty if the object is found, otherwise return null return item ? item.rudderProperty : null; -} +}; const buildGroupPayload = (message, destination) => { const { emersysCustomIdentifier, defaultContactList, fieldMapping } = destination.Config; @@ -149,16 +150,15 @@ const deduceEndPoint = (message, destConfig, batchGroupId = undefined) => { return endPoint; }; -function estimateJsonSize(obj) { - return new Blob([JSON.stringify(obj)]).size; -} +const estimateJsonSize = (obj) => new Blob([JSON.stringify(obj)]).size; -function createPayload(keyId, contacts, contactListId) { - return { key_id: keyId, contacts, contact_list_id: contactListId }; -} +const createSingleIdentifyPayload = (keyId, contacts, contactListId) => ({ + key_id: keyId, + contacts, + contact_list_id: contactListId, +}); -function ensureSizeConstraints(contacts) { - const MAX_SIZE_BYTES = 8000000; // 8 MB +const ensureSizeConstraints = (contacts) => { const chunks = []; let currentBatch = []; @@ -166,7 +166,7 @@ function ensureSizeConstraints(contacts) { // Start a new batch if adding the next contact exceeds size limits if ( currentBatch.length === 0 || - estimateJsonSize([...currentBatch, contact]) < MAX_SIZE_BYTES + estimateJsonSize([...currentBatch, contact]) < MAX_BATCH_SIZE_BYTES ) { currentBatch.push(contact); } else { @@ -181,9 +181,9 @@ function ensureSizeConstraints(contacts) { } return chunks; -} +}; -function createIdentifyBatches(events) { +const createIdentifyBatches = (events) => { const groupedIdentifyPayload = lodash.groupBy( events, (item) => @@ -204,13 +204,13 @@ function createIdentifyBatches(events) { // Include metadata for each chunk return finalChunks.map((contacts) => ({ - payload: createPayload(key_id, contacts, contact_list_id), - metadata: group.map((g) => g.metadata), // assuming metadata is needed per original event grouping + payload: createSingleIdentifyPayload(key_id, contacts, contact_list_id), + metadata: group.map((g) => g.metadata), })); }); -} +}; -function createGroupBatches(events) { +const createGroupBatches = (events) => { const grouped = lodash.groupBy( events, (item) => @@ -237,16 +237,15 @@ function createGroupBatches(events) { metadata: group.map((g) => g.metadata), // assuming metadata is needed per original event grouping })); }); -} -function formatIdentifyPayloadsWithEndpoint(combinedPayloads, endpointUrl = '') { - return combinedPayloads.map((payload) => ({ +}; +const formatIdentifyPayloadsWithEndpoint = (combinedPayloads, endpointUrl = '') => + combinedPayloads.map((payload) => ({ endpoint: endpointUrl, payload, })); -} -function buildBatchedRequest(batches, method, constants) { - return batches.map((batch) => ({ +const buildBatchedRequest = (batches, method, constants) => + batches.map((batch) => ({ batchedRequest: { body: { JSON: batch.payload, @@ -267,9 +266,8 @@ function buildBatchedRequest(batches, method, constants) { statusCode: 200, destination: constants.destination, })); -} -function batchResponseBuilder(successfulEvents) { +const batchResponseBuilder = (successfulEvents) => { const finaloutput = []; const groupedSuccessfulPayload = { identify: { @@ -334,7 +332,7 @@ function batchResponseBuilder(successfulEvents) { } return finaloutput; -} +}; module.exports = { buildIdentifyPayload, buildGroupPayload, @@ -345,4 +343,8 @@ module.exports = { getWsseHeader, findRudderPropertyByEmersysProperty, formatIdentifyPayloadsWithEndpoint, + createSingleIdentifyPayload, + createIdentifyBatches, + ensureSizeConstraints, + createGroupBatches, }; diff --git a/src/cdk/v2/destinations/emersys/utils.test.js b/src/cdk/v2/destinations/emersys/utils.test.js index d45171a82c..a113ced60d 100644 --- a/src/cdk/v2/destinations/emersys/utils.test.js +++ b/src/cdk/v2/destinations/emersys/utils.test.js @@ -1,14 +1,14 @@ +const lodash = require('lodash'); const { EVENT_TYPE } = require('rudder-transformer-cdk/build/constants'); const { buildIdentifyPayload, buildGroupPayload, - deduceEndPoint, - batchResponseBuilder, base64Sha, getWsseHeader, findRudderPropertyByEmersysProperty, - formatIdentifyPayloadsWithEndpoint, + createGroupBatches, } = require('./utils'); +const utils = require('./utils'); const crypto = require('crypto'); const { InstrumentationError } = require('@rudderstack/integrations-lib'); @@ -288,3 +288,124 @@ describe('buildGroupPayload', () => { }).toThrow(InstrumentationError); }); }); + +describe('createGroupBatches', () => { + // Should group events by key_id and contactListId + it('should group events by key_id and contactListId when events are provided', () => { + // Arrange + const events = [ + { + message: { + body: { + JSON: { + destinationPayload: { + payload: { + key_id: 'key1', + external_ids: ['id1', 'id2'], + }, + contactListId: 'list1', + }, + }, + }, + }, + metadata: { jobId: 1, userId: 'u1' }, + }, + { + message: { + body: { + JSON: { + destinationPayload: { + payload: { + key_id: 'key2', + external_ids: ['id3', 'id4'], + }, + contactListId: 'list2', + }, + }, + }, + }, + metadata: { jobId: 2, userId: 'u2' }, + }, + { + message: { + body: { + JSON: { + destinationPayload: { + payload: { + key_id: 'key1', + external_ids: ['id5', 'id6'], + }, + contactListId: 'list1', + }, + }, + }, + }, + metadata: { jobId: 3, userId: 'u3' }, + }, + ]; + + // Act + const result = createGroupBatches(events); + + // Assert + expect(result).toEqual([ + { + endpoint: 'https://api.emarsys.net/api/v2/contactlist/list1/add', + payload: { + key_id: 'key1', + external_ids: ['id1', 'id2', 'id5', 'id6'], + }, + metadata: [ + { jobId: 1, userId: 'u1' }, + { jobId: 3, userId: 'u3' }, + ], + }, + { + endpoint: 'https://api.emarsys.net/api/v2/contactlist/list2/add', + payload: { + key_id: 'key2', + external_ids: ['id3', 'id4'], + }, + metadata: [{ jobId: 2, userId: 'u2' }], + }, + ]); + }); + + // Should return an empty array if no events are provided + it('should return an empty array when no events are provided', () => { + // Arrange + const events = []; + + // Act + const result = createGroupBatches(events); + + // Assert + expect(result).toEqual([]); + }); +}); + +describe('findRudderPropertyByEmersysProperty', () => { + // Returns the correct rudderProperty when given a valid emersysProperty and fieldMapping + it('should return the correct rudderProperty when given a valid emersysProperty and fieldMapping', () => { + const emersysProperty = 'email'; + const fieldMapping = [ + { emersysProperty: 'email', rudderProperty: 'email' }, + { emersysProperty: 'firstName', rudderProperty: 'firstName' }, + { emersysProperty: 'lastName', rudderProperty: 'lastName' }, + ]; + + const result = findRudderPropertyByEmersysProperty(emersysProperty, fieldMapping); + + expect(result).toBe('email'); + }); + + // Returns null when given an empty fieldMapping + it('should return null when given an empty fieldMapping', () => { + const emersysProperty = 'email'; + const fieldMapping = []; + + const result = findRudderPropertyByEmersysProperty(emersysProperty, fieldMapping); + + expect(result).toBeNull(); + }); +});