From f2c783bf03cec8bdd3d38c2a3fb20ecf79b08817 Mon Sep 17 00:00:00 2001 From: Utsab Chowdhury Date: Wed, 20 Mar 2024 09:45:29 +0530 Subject: [PATCH] feat: add support for subscribing for RETL flow Adding subscribe flag default as true for traits properties object for vdm scenario --- .../destinations/klaviyo/klaviyoUtil.test.js | 156 ++++++++++++++++++ src/v0/destinations/klaviyo/transform.js | 5 +- src/v0/destinations/klaviyo/util.js | 29 +++- 3 files changed, 188 insertions(+), 2 deletions(-) create mode 100644 src/v0/destinations/klaviyo/klaviyoUtil.test.js diff --git a/src/v0/destinations/klaviyo/klaviyoUtil.test.js b/src/v0/destinations/klaviyo/klaviyoUtil.test.js new file mode 100644 index 0000000000..f64ea8335a --- /dev/null +++ b/src/v0/destinations/klaviyo/klaviyoUtil.test.js @@ -0,0 +1,156 @@ +const { addSubscribeFlagToTraits } = require('./util'); + +describe('addSubscribeFlagToTraits', () => { + // The function should add a 'subscribe' property to the 'properties' object if it exists in the input 'traitsInfo'. + it('should add subscribe property to properties object when it exists in traitsInfo', () => { + // Arrange + const traitsInfo = { + properties: { + name: 'John', + age: 30, + }, + }; + + // Act + const result = addSubscribeFlagToTraits(traitsInfo); + + // Assert + expect(result.properties.subscribe).toBe(true); + }); + + // The input 'traitsInfo' object is null. + it('should create a new traitsInfo object with properties object containing subscribe property when traitsInfo is null', () => { + // Arrange + const traitsInfo = null; + + // Act + const result = addSubscribeFlagToTraits(traitsInfo); + + // Assert + expect(result).toEqual(null); + }); + + // The function should create a new 'properties' object with a 'subscribe' property and assign it to the 'traitsInfo' if 'properties' does not exist in the input 'traitsInfo'. + it("should create a new 'properties' object with a 'subscribe' property when 'properties' does not exist in traitsInfo", () => { + // Arrange + const traitsInfo = {}; + + // Act + const result = addSubscribeFlagToTraits(traitsInfo); + + // Assert + expect(result.properties).toBeDefined(); + expect(result.properties.subscribe).toBe(true); + }); + + // The function should return the modified 'traitsInfo' object with the 'subscribe' property added. + it('should add subscribe property to properties object when it exists in traitsInfo', () => { + // Arrange + const traitsInfo = { + properties: { + name: 'John', + age: 30, + }, + }; + + // Act + const result = addSubscribeFlagToTraits(traitsInfo); + + // Assert + expect(result.properties.subscribe).toBe(true); + }); + + // The input 'traitsInfo' object has an empty 'properties' object. + it('should add subscribe property to properties object when it exists in traitsInfo', () => { + // Arrange + const traitsInfo = { + properties: {}, + }; + + // Act + const result = addSubscribeFlagToTraits(traitsInfo); + + // Assert + expect(result.properties.subscribe).toBe(true); + }); + + // The input 'traitsInfo' object has a 'properties' object with a 'subscribe' property already present. + it('should add subscribe property to properties object when it exists in traitsInfo', () => { + // Arrange + const traitsInfo = { + properties: { + name: 'John', + age: 30, + subscribe: false, + }, + }; + + // Act + const result = addSubscribeFlagToTraits(traitsInfo); + + // Assert + expect(result.properties.subscribe).toBe(false); + }); + + // The function should not modify any other properties of the 'traitsInfo' object. + it('should not modify any other properties of the traitsInfo object', () => { + // Arrange + const traitsInfo = { + properties: { + name: 'John', + age: 30, + }, + }; + + // Act + const result = addSubscribeFlagToTraits(traitsInfo); + + // Assert + expect(result.properties.subscribe).toBe(true); + expect(result.properties.name).toBe('John'); + expect(result.properties.age).toBe(30); + }); + + // The function should handle cases where the input 'traitsInfo' object has nested objects. + it('should add subscribe property to nested properties object when it exists in traitsInfo', () => { + // Arrange + const traitsInfo = { + properties: { + name: 'John', + age: 30, + address: { + street: '123 Main St', + city: 'New York', + }, + }, + }; + + // Act + const result = addSubscribeFlagToTraits(traitsInfo); + + // Assert + expect(result.properties.subscribe).toBe(true); + expect(result.properties.address).toMatchObject({ + street: '123 Main St', + city: 'New York', + }); + }); + + // The function should handle cases where the input 'traitsInfo' object has properties with null or undefined values. + it('should add subscribe property to properties object when it exists in traitsInfo', () => { + // Arrange + const traitsInfo = { + properties: { + name: 'John', + age: 30, + address: null, + }, + }; + + // Act + const result = addSubscribeFlagToTraits(traitsInfo); + + // Assert + expect(result.properties.subscribe).toBe(true); + }); +}); diff --git a/src/v0/destinations/klaviyo/transform.js b/src/v0/destinations/klaviyo/transform.js index a0fe3e81a7..77c17cdbd9 100644 --- a/src/v0/destinations/klaviyo/transform.js +++ b/src/v0/destinations/klaviyo/transform.js @@ -20,6 +20,7 @@ const { batchSubscribeEvents, getIdFromNewOrExistingProfile, profileUpdateResponseBuilder, + addSubcribeFlagToTraits, } = require('./util'); const { defaultRequestConfig, @@ -55,11 +56,13 @@ const identifyRequestHandler = async (message, category, destination, reqMetadat // If listId property is present try to subscribe/member user in list const { privateApiKey, enforceEmailAsPrimary, listId, flattenProperties } = destination.Config; const mappedToDestination = get(message, MappedToDestinationKey); + let traitsInfo = getFieldValueFromMessage(message, 'traits'); if (mappedToDestination) { addExternalIdToTraits(message); adduserIdFromExternalId(message); + traitsInfo = addSubcribeFlagToTraits(traitsInfo); } - const traitsInfo = getFieldValueFromMessage(message, 'traits'); + let propertyPayload = constructPayload(message, MAPPING_CONFIG[category.name]); // Extract other K-V property from traits about user custom properties let customPropertyPayload = {}; diff --git a/src/v0/destinations/klaviyo/util.js b/src/v0/destinations/klaviyo/util.js index df2dbb4712..d5337032f1 100644 --- a/src/v0/destinations/klaviyo/util.js +++ b/src/v0/destinations/klaviyo/util.js @@ -1,6 +1,10 @@ const { defaultRequestConfig } = require('rudder-transformer-cdk/build/utils'); const lodash = require('lodash'); -const { NetworkError, InstrumentationError } = require('@rudderstack/integrations-lib'); +const { + NetworkError, + InstrumentationError, + isDefinedAndNotNull, +} = require('@rudderstack/integrations-lib'); const { WhiteListedTraits } = require('../../../constants'); const { @@ -305,6 +309,28 @@ const batchSubscribeEvents = (subscribeRespList) => { return batchedResponseList; }; +const addSubscribeFlagToTraits = (traitsInfo) => { + let traits = traitsInfo; + if (!isDefinedAndNotNull(traits)) { + return traits; + } + // check if properties already contains subscribe flag + + if (traits.properties) { + if (traits.properties.subscribe === undefined) { + traits.properties.subscribe = true; + } else { + // return if subscribe flag is already present + return traits; + } + } else { + traits = { + properties: { subscribe: true }, + }; + } + return traits; +}; + module.exports = { subscribeUserToList, createCustomerProperties, @@ -313,4 +339,5 @@ module.exports = { batchSubscribeEvents, profileUpdateResponseBuilder, getIdFromNewOrExistingProfile, + addSubscribeFlagToTraits, };