Skip to content

Commit

Permalink
fix: emersys unit test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
shrouti1507 committed Apr 30, 2024
1 parent 33b87be commit 3522abf
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 33 deletions.
1 change: 1 addition & 0 deletions src/cdk/v2/destinations/emersys/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
};
62 changes: 32 additions & 30 deletions src/cdk/v2/destinations/emersys/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -149,24 +150,23 @@ 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 = [];

contacts.forEach((contact) => {
// 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 {
Expand All @@ -181,9 +181,9 @@ function ensureSizeConstraints(contacts) {
}

return chunks;
}
};

function createIdentifyBatches(events) {
const createIdentifyBatches = (events) => {
const groupedIdentifyPayload = lodash.groupBy(
events,
(item) =>
Expand All @@ -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) =>
Expand All @@ -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,
Expand All @@ -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: {
Expand Down Expand Up @@ -334,7 +332,7 @@ function batchResponseBuilder(successfulEvents) {
}

return finaloutput;
}
};
module.exports = {
buildIdentifyPayload,
buildGroupPayload,
Expand All @@ -345,4 +343,8 @@ module.exports = {
getWsseHeader,
findRudderPropertyByEmersysProperty,
formatIdentifyPayloadsWithEndpoint,
createSingleIdentifyPayload,
createIdentifyBatches,
ensureSizeConstraints,
createGroupBatches,
};
127 changes: 124 additions & 3 deletions src/cdk/v2/destinations/emersys/utils.test.js
Original file line number Diff line number Diff line change
@@ -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');

Expand Down Expand Up @@ -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();
});
});

0 comments on commit 3522abf

Please sign in to comment.