diff --git a/src/v0/destinations/mp/transform.js b/src/v0/destinations/mp/transform.js index 24890c0eb1..6a489473c3 100644 --- a/src/v0/destinations/mp/transform.js +++ b/src/v0/destinations/mp/transform.js @@ -37,6 +37,7 @@ const { groupEventsByEndpoint, batchEvents, trimTraits, + generatePageOrScreenCustomEventName, } = require('./util'); const { CommonUtils } = require('../../../util/common'); @@ -298,17 +299,25 @@ const processIdentifyEvents = async (message, type, destination) => { }; const processPageOrScreenEvents = (message, type, destination) => { + const { + token, + identityMergeApi, + useUserDefinedPageEventName, + userDefinedPageEventString, + useUserDefinedScreenEventName, + userDefinedScreenEventString, + } = destination.Config; const mappedProperties = constructPayload(message, mPEventPropertiesConfigJson); let properties = { ...get(message, 'context.traits'), ...message.properties, ...mappedProperties, - token: destination.Config.token, + token, distinct_id: message.userId || message.anonymousId, time: toUnixTimestampInMS(message.timestamp || message.originalTimestamp), ...buildUtmParams(message.context?.campaign), }; - if (destination.Config?.identityMergeApi === 'simplified') { + if (identityMergeApi === 'simplified') { properties = { ...properties, distinct_id: message.userId || `$device:${message.anonymousId}`, @@ -327,7 +336,18 @@ const processPageOrScreenEvents = (message, type, destination) => { properties.$browser = browser.name; properties.$browser_version = browser.version; } - const eventName = type === 'page' ? 'Loaded a Page' : 'Loaded a Screen'; + + let eventName; + if (type === 'page') { + eventName = useUserDefinedPageEventName + ? generatePageOrScreenCustomEventName(message, userDefinedPageEventString) + : 'Loaded a Page'; + } else { + eventName = useUserDefinedScreenEventName + ? generatePageOrScreenCustomEventName(message, userDefinedScreenEventString) + : 'Loaded a Screen'; + } + const payload = { event: eventName, properties, diff --git a/src/v0/destinations/mp/util.js b/src/v0/destinations/mp/util.js index 8e943f41dd..0883bb38bd 100644 --- a/src/v0/destinations/mp/util.js +++ b/src/v0/destinations/mp/util.js @@ -301,6 +301,32 @@ function trimTraits(traits, contextTraits, setOnceProperties) { }; } +/** + * Generates a custom event name for a page or screen. + * + * @param {Object} message - The message object. + * @param {string} userDefinedEventString - The user-defined event string. + * @returns {string} - The generated custom event name. + * @throws {InstrumentationError} - If the event does not contain the configured path. + * @example + * + * const message = {name: 'Home'}; + * const userDefinedEventString = 'Viewed a {{ name }} page'; + * -> Viewed a Home page + */ +const generatePageOrScreenCustomEventName = (message, userDefinedEventString) => { + const getMessagePath = userDefinedEventString?.match(/{\s*([^{}]+)\s*}/)?.[1]?.trim(); + if (!getMessagePath) return userDefinedEventString; + + const value = get(message, getMessagePath); + if (!value) { + throw new InstrumentationError( + `'Use Custom Page/Screen Event Name' setting is enabled but the event does not contain the ${getMessagePath} configured in 'Page/Screen Event Name Format' setting`, + ); + } + return userDefinedEventString?.trim().replaceAll(/{{([^{}]+)}}/g, value); +}; + module.exports = { createIdentifyResponse, isImportAuthCredentialsAvailable, @@ -309,4 +335,5 @@ module.exports = { generateBatchedPayloadForArray, batchEvents, trimTraits, + generatePageOrScreenCustomEventName, }; diff --git a/src/v0/destinations/mp/util.test.js b/src/v0/destinations/mp/util.test.js index 866119a336..02aba8bf64 100644 --- a/src/v0/destinations/mp/util.test.js +++ b/src/v0/destinations/mp/util.test.js @@ -4,45 +4,88 @@ const { generateBatchedPayloadForArray, buildUtmParams, trimTraits, + generatePageOrScreenCustomEventName, } = require('./util'); const { FEATURE_GZIP_SUPPORT } = require('../../util/constant'); - -const destinationMock = { - Config: { - token: 'test_api_token', - prefixProperties: true, - useNativeSDK: false, - useOldMapping: true, - }, - DestinationDefinition: { - DisplayName: 'Mixpanel', - ID: 'test_destination_definition_id', - Name: 'MP', - }, - Enabled: true, - ID: 'test_id', - Name: 'Mixpanel', - Transformations: [], -}; +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const maxBatchSizeMock = 2; -describe('Mixpanel utils test', () => { - describe('Unit test cases for groupEventsByEndpoint', () => { - it('should return an object with empty arrays for all properties when the events array is empty', () => { - const events = []; - const result = groupEventsByEndpoint(events); - expect(result).toEqual({ - engageEvents: [], - groupsEvents: [], - trackEvents: [], - importEvents: [], - batchErrorRespList: [], - }); +describe('Unit test cases for groupEventsByEndpoint', () => { + it('should return an object with empty arrays for all properties when the events array is empty', () => { + const events = []; + const result = groupEventsByEndpoint(events); + expect(result).toEqual({ + engageEvents: [], + groupsEvents: [], + trackEvents: [], + importEvents: [], + batchErrorRespList: [], }); + }); - it('should return an object with all properties containing their respective events when the events array contains events of all types', () => { - const events = [ + it('should return an object with all properties containing their respective events when the events array contains events of all types', () => { + const events = [ + { + message: { + endpoint: '/engage', + body: { + JSON_ARRAY: { + batch: '[{prop:1}]', + }, + }, + userId: 'user1', + }, + }, + { + message: { + endpoint: '/engage', + body: { + JSON_ARRAY: { + batch: '[{prop:2}]', + }, + }, + userId: 'user2', + }, + }, + { + message: { + endpoint: '/groups', + body: { + JSON_ARRAY: { + batch: '[{prop:3}]', + }, + }, + userId: 'user1', + }, + }, + { + message: { + endpoint: '/track', + body: { + JSON_ARRAY: { + batch: '[{prop:4}]', + }, + }, + userId: 'user1', + }, + }, + { + message: { + endpoint: '/import', + body: { + JSON_ARRAY: { + batch: '[{prop:5}]', + }, + }, + userId: 'user2', + }, + }, + { error: 'Message type abc not supported' }, + ]; + const result = groupEventsByEndpoint(events); + expect(result).toEqual({ + engageEvents: [ { message: { endpoint: '/engage', @@ -65,6 +108,8 @@ describe('Mixpanel utils test', () => { userId: 'user2', }, }, + ], + groupsEvents: [ { message: { endpoint: '/groups', @@ -76,6 +121,8 @@ describe('Mixpanel utils test', () => { userId: 'user1', }, }, + ], + trackEvents: [ { message: { endpoint: '/track', @@ -87,6 +134,8 @@ describe('Mixpanel utils test', () => { userId: 'user1', }, }, + ], + importEvents: [ { message: { endpoint: '/import', @@ -98,371 +147,337 @@ describe('Mixpanel utils test', () => { userId: 'user2', }, }, - { error: 'Message type abc not supported' }, - ]; - const result = groupEventsByEndpoint(events); - expect(result).toEqual({ - engageEvents: [ - { - message: { - endpoint: '/engage', - body: { - JSON_ARRAY: { - batch: '[{prop:1}]', - }, - }, - userId: 'user1', - }, - }, - { - message: { - endpoint: '/engage', - body: { - JSON_ARRAY: { - batch: '[{prop:2}]', - }, - }, - userId: 'user2', - }, - }, - ], - groupsEvents: [ - { - message: { - endpoint: '/groups', - body: { - JSON_ARRAY: { - batch: '[{prop:3}]', - }, - }, - userId: 'user1', - }, - }, - ], - trackEvents: [ - { - message: { - endpoint: '/track', - body: { - JSON_ARRAY: { - batch: '[{prop:4}]', - }, - }, - userId: 'user1', - }, - }, - ], - importEvents: [ - { - message: { - endpoint: '/import', - body: { - JSON_ARRAY: { - batch: '[{prop:5}]', - }, - }, - userId: 'user2', - }, - }, - ], - batchErrorRespList: [{ error: 'Message type abc not supported' }], - }); + ], + batchErrorRespList: [{ error: 'Message type abc not supported' }], }); }); +}); - describe('Unit test cases for batchEvents', () => { - it('should return an array of batched events with correct payload and metadata', () => { - const successRespList = [ - { - message: { - endpoint: '/engage', - body: { - JSON_ARRAY: { - batch: '[{"prop":1}]', - }, +describe('Unit test cases for batchEvents', () => { + it('should return an array of batched events with correct payload and metadata', () => { + const successRespList = [ + { + message: { + endpoint: '/engage', + body: { + JSON_ARRAY: { + batch: '[{"prop":1}]', }, - headers: {}, - params: {}, - userId: 'user1', }, - metadata: { jobId: 3 }, + headers: {}, + params: {}, + userId: 'user1', }, - { - message: { - endpoint: '/engage', - body: { - JSON_ARRAY: { - batch: '[{"prop":2}]', - }, + metadata: { jobId: 3 }, + }, + { + message: { + endpoint: '/engage', + body: { + JSON_ARRAY: { + batch: '[{"prop":2}]', }, - headers: {}, - params: {}, - userId: 'user2', }, - metadata: { jobId: 4 }, + headers: {}, + params: {}, + userId: 'user2', }, - { - message: { - endpoint: '/engage', - body: { - JSON_ARRAY: { - batch: '[{"prop":3}]', - }, + metadata: { jobId: 4 }, + }, + { + message: { + endpoint: '/engage', + body: { + JSON_ARRAY: { + batch: '[{"prop":3}]', }, - headers: {}, - params: {}, - userId: 'user2', }, - metadata: { jobId: 6 }, + headers: {}, + params: {}, + userId: 'user2', }, - ]; - - const result = batchEvents(successRespList, maxBatchSizeMock); - - expect(result).toEqual([ - { - batched: true, - batchedRequest: { - body: { FORM: {}, JSON: {}, JSON_ARRAY: { batch: '[{"prop":1},{"prop":2}]' }, XML: {} }, - endpoint: '/engage', - files: {}, - headers: {}, - method: 'POST', - params: {}, - type: 'REST', - version: '1', - }, - destination: undefined, - metadata: [{ jobId: 3 }, { jobId: 4 }], - statusCode: 200, + metadata: { jobId: 6 }, + }, + ]; + + const result = batchEvents(successRespList, maxBatchSizeMock); + + expect(result).toEqual([ + { + batched: true, + batchedRequest: { + body: { FORM: {}, JSON: {}, JSON_ARRAY: { batch: '[{"prop":1},{"prop":2}]' }, XML: {} }, + endpoint: '/engage', + files: {}, + headers: {}, + method: 'POST', + params: {}, + type: 'REST', + version: '1', }, - { - batched: true, - batchedRequest: { - body: { FORM: {}, JSON: {}, JSON_ARRAY: { batch: '[{"prop":3}]' }, XML: {} }, - endpoint: '/engage', - files: {}, - headers: {}, - method: 'POST', - params: {}, - type: 'REST', - version: '1', - }, - destination: undefined, - metadata: [{ jobId: 6 }], - statusCode: 200, + destination: undefined, + metadata: [{ jobId: 3 }, { jobId: 4 }], + statusCode: 200, + }, + { + batched: true, + batchedRequest: { + body: { FORM: {}, JSON: {}, JSON_ARRAY: { batch: '[{"prop":3}]' }, XML: {} }, + endpoint: '/engage', + files: {}, + headers: {}, + method: 'POST', + params: {}, + type: 'REST', + version: '1', }, - ]); - }); + destination: undefined, + metadata: [{ jobId: 6 }], + statusCode: 200, + }, + ]); + }); - it('should return an empty array when successRespList is empty', () => { - const successRespList = []; - const result = batchEvents(successRespList, maxBatchSizeMock); - expect(result).toEqual([]); - }); + it('should return an empty array when successRespList is empty', () => { + const successRespList = []; + const result = batchEvents(successRespList, maxBatchSizeMock); + expect(result).toEqual([]); }); +}); - describe('Unit test cases for generateBatchedPayloadForArray', () => { - it('should generate a batched payload with GZIP payload for /import endpoint when given an array of events', () => { - const events = [ - { - body: { JSON_ARRAY: { batch: '[{"event": "event1"}]' } }, - endpoint: '/import', - headers: { 'Content-Type': 'application/json' }, - params: {}, - }, - { - body: { JSON_ARRAY: { batch: '[{"event": "event2"}]' } }, - endpoint: '/import', - headers: { 'Content-Type': 'application/json' }, - params: {}, - }, - ]; - const expectedBatchedRequest = { - body: { - FORM: {}, - JSON: {}, - JSON_ARRAY: {}, - XML: {}, - GZIP: { - payload: '[{"event":"event1"},{"event":"event2"}]', - }, - }, +describe('Unit test cases for generateBatchedPayloadForArray', () => { + it('should generate a batched payload with GZIP payload for /import endpoint when given an array of events', () => { + const events = [ + { + body: { JSON_ARRAY: { batch: '[{"event": "event1"}]' } }, endpoint: '/import', - files: {}, headers: { 'Content-Type': 'application/json' }, - method: 'POST', params: {}, - type: 'REST', - version: '1', - }; - - const result = generateBatchedPayloadForArray(events, { - features: { [FEATURE_GZIP_SUPPORT]: true }, - }); - - expect(result).toEqual(expectedBatchedRequest); + }, + { + body: { JSON_ARRAY: { batch: '[{"event": "event2"}]' } }, + endpoint: '/import', + headers: { 'Content-Type': 'application/json' }, + params: {}, + }, + ]; + const expectedBatchedRequest = { + body: { + FORM: {}, + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + GZIP: { + payload: '[{"event":"event1"},{"event":"event2"}]', + }, + }, + endpoint: '/import', + files: {}, + headers: { 'Content-Type': 'application/json' }, + method: 'POST', + params: {}, + type: 'REST', + version: '1', + }; + + const result = generateBatchedPayloadForArray(events, { + features: { [FEATURE_GZIP_SUPPORT]: true }, }); - it('should generate a batched payload with JSON_ARRAY body when given an array of events', () => { - const events = [ - { - body: { JSON_ARRAY: { batch: '[{"event": "event1"}]' } }, - endpoint: '/endpoint', - headers: { 'Content-Type': 'application/json' }, - params: {}, - }, - { - body: { JSON_ARRAY: { batch: '[{"event": "event2"}]' } }, - endpoint: '/endpoint', - headers: { 'Content-Type': 'application/json' }, - params: {}, - }, - ]; - const expectedBatchedRequest = { - body: { - FORM: {}, - JSON: {}, - JSON_ARRAY: { batch: '[{"event":"event1"},{"event":"event2"}]' }, - XML: {}, - }, + expect(result).toEqual(expectedBatchedRequest); + }); + + it('should generate a batched payload with JSON_ARRAY body when given an array of events', () => { + const events = [ + { + body: { JSON_ARRAY: { batch: '[{"event": "event1"}]' } }, endpoint: '/endpoint', - files: {}, headers: { 'Content-Type': 'application/json' }, - method: 'POST', params: {}, - type: 'REST', - version: '1', - }; - - const result = generateBatchedPayloadForArray(events, { - features: { [FEATURE_GZIP_SUPPORT]: true }, - }); - - expect(result).toEqual(expectedBatchedRequest); + }, + { + body: { JSON_ARRAY: { batch: '[{"event": "event2"}]' } }, + endpoint: '/endpoint', + headers: { 'Content-Type': 'application/json' }, + params: {}, + }, + ]; + const expectedBatchedRequest = { + body: { + FORM: {}, + JSON: {}, + JSON_ARRAY: { batch: '[{"event":"event1"},{"event":"event2"}]' }, + XML: {}, + }, + endpoint: '/endpoint', + files: {}, + headers: { 'Content-Type': 'application/json' }, + method: 'POST', + params: {}, + type: 'REST', + version: '1', + }; + + const result = generateBatchedPayloadForArray(events, { + features: { [FEATURE_GZIP_SUPPORT]: true }, }); + + expect(result).toEqual(expectedBatchedRequest); }); +}); - describe('Unit test cases for buildUtmParams', () => { - it('should return an empty object when campaign is undefined', () => { - const campaign = undefined; - const result = buildUtmParams(campaign); - expect(result).toEqual({}); - }); +describe('Unit test cases for buildUtmParams', () => { + it('should return an empty object when campaign is undefined', () => { + const campaign = undefined; + const result = buildUtmParams(campaign); + expect(result).toEqual({}); + }); - it('should return an empty object when campaign is an empty object', () => { - const campaign = {}; - const result = buildUtmParams(campaign); - expect(result).toEqual({}); - }); + it('should return an empty object when campaign is an empty object', () => { + const campaign = {}; + const result = buildUtmParams(campaign); + expect(result).toEqual({}); + }); - it('should return an empty object when campaign is not an object', () => { - const campaign = [{ name: 'test' }]; - const result = buildUtmParams(campaign); - expect(result).toEqual({}); - }); + it('should return an empty object when campaign is not an object', () => { + const campaign = [{ name: 'test' }]; + const result = buildUtmParams(campaign); + expect(result).toEqual({}); + }); - it('should handle campaign object with null/undefined values', () => { - const campaign = { name: null, source: 'rudder', medium: 'rudder', test: undefined }; - const result = buildUtmParams(campaign); - expect(result).toEqual({ - utm_campaign: null, - utm_source: 'rudder', - utm_medium: 'rudder', - test: undefined, - }); + it('should handle campaign object with null/undefined values', () => { + const campaign = { name: null, source: 'rudder', medium: 'rudder', test: undefined }; + const result = buildUtmParams(campaign); + expect(result).toEqual({ + utm_campaign: null, + utm_source: 'rudder', + utm_medium: 'rudder', + test: undefined, }); }); - describe('Unit test cases for trimTraits', () => { - // Given a valid traits object and contextTraits object, and a valid setOnceProperties array, the function should return an object containing traits, contextTraits, and setOnce properties. - it('should return an object containing traits, contextTraits, and setOnce properties when given valid inputs', () => { - const traits = { name: 'John', age: 30 }; - const contextTraits = { email: 'john@example.com' }; - const setOnceProperties = ['name', 'email']; - - const result = trimTraits(traits, contextTraits, setOnceProperties); - - expect(result).toEqual({ - traits: { - age: 30, - }, - contextTraits: {}, - setOnce: { $name: 'John', $email: 'john@example.com' }, - }); +}); +describe('Unit test cases for trimTraits', () => { + // Given a valid traits object and contextTraits object, and a valid setOnceProperties array, the function should return an object containing traits, contextTraits, and setOnce properties. + it('should return an object containing traits, contextTraits, and setOnce properties when given valid inputs', () => { + const traits = { name: 'John', age: 30 }; + const contextTraits = { email: 'john@example.com' }; + const setOnceProperties = ['name', 'email']; + + const result = trimTraits(traits, contextTraits, setOnceProperties); + + expect(result).toEqual({ + traits: { + age: 30, + }, + contextTraits: {}, + setOnce: { $name: 'John', $email: 'john@example.com' }, }); + }); - // Given an empty traits object and contextTraits object, and a valid setOnceProperties array, the function should return an object containing empty traits and contextTraits, and an empty setOnce property. - it('should return an object containing empty traits and contextTraits, and an empty setOnce property when given empty traits and contextTraits objects', () => { - const traits = {}; - const contextTraits = {}; - const setOnceProperties = ['name', 'email']; + // Given an empty traits object and contextTraits object, and a valid setOnceProperties array, the function should return an object containing empty traits and contextTraits, and an empty setOnce property. + it('should return an object containing empty traits and contextTraits, and an empty setOnce property when given empty traits and contextTraits objects', () => { + const traits = {}; + const contextTraits = {}; + const setOnceProperties = ['name', 'email']; - const result = trimTraits(traits, contextTraits, setOnceProperties); + const result = trimTraits(traits, contextTraits, setOnceProperties); - expect(result).toEqual({ - traits: {}, - contextTraits: {}, - setOnce: {}, - }); + expect(result).toEqual({ + traits: {}, + contextTraits: {}, + setOnce: {}, }); + }); - // Given an empty setOnceProperties array, the function should return an object containing the original traits and contextTraits objects, and an empty setOnce property. - it('should return an object containing the original traits and contextTraits objects, and an empty setOnce property when given an empty setOnceProperties array', () => { - const traits = { name: 'John', age: 30 }; - const contextTraits = { email: 'john@example.com' }; - const setOnceProperties = []; + // Given an empty setOnceProperties array, the function should return an object containing the original traits and contextTraits objects, and an empty setOnce property. + it('should return an object containing the original traits and contextTraits objects, and an empty setOnce property when given an empty setOnceProperties array', () => { + const traits = { name: 'John', age: 30 }; + const contextTraits = { email: 'john@example.com' }; + const setOnceProperties = []; - const result = trimTraits(traits, contextTraits, setOnceProperties); + const result = trimTraits(traits, contextTraits, setOnceProperties); - expect(result).toEqual({ - traits: { name: 'John', age: 30 }, - contextTraits: { email: 'john@example.com' }, - setOnce: {}, - }); + expect(result).toEqual({ + traits: { name: 'John', age: 30 }, + contextTraits: { email: 'john@example.com' }, + setOnce: {}, }); + }); - // Given a setOnceProperties array containing properties that do not exist in either traits or contextTraits objects, the function should not add the property to the setOnce property. - it('should not add properties to the setOnce property when given setOnceProperties array with non-existent properties', () => { - const traits = { name: 'John', age: 30 }; - const contextTraits = { email: 'john@example.com' }; - const setOnceProperties = ['name', 'email', 'address']; + // Given a setOnceProperties array containing properties that do not exist in either traits or contextTraits objects, the function should not add the property to the setOnce property. + it('should not add properties to the setOnce property when given setOnceProperties array with non-existent properties', () => { + const traits = { name: 'John', age: 30 }; + const contextTraits = { email: 'john@example.com' }; + const setOnceProperties = ['name', 'email', 'address']; - const result = trimTraits(traits, contextTraits, setOnceProperties); + const result = trimTraits(traits, contextTraits, setOnceProperties); - expect(result).toEqual({ - traits: { age: 30 }, - contextTraits: {}, - setOnce: { $name: 'John', $email: 'john@example.com' }, - }); + expect(result).toEqual({ + traits: { age: 30 }, + contextTraits: {}, + setOnce: { $name: 'John', $email: 'john@example.com' }, }); + }); - // Given a setOnceProperties array containing properties with nested paths that do not exist in either traits or contextTraits objects, the function should not add the property to the setOnce property. - it('should not add properties to the setOnce property when given setOnceProperties array with non-existent nested properties', () => { - const traits = { name: 'John', age: 30, address: 'kolkata' }; - const contextTraits = { email: 'john@example.com' }; - const setOnceProperties = ['name', 'email', 'address.city']; + // Given a setOnceProperties array containing properties with nested paths that do not exist in either traits or contextTraits objects, the function should not add the property to the setOnce property. + it('should not add properties to the setOnce property when given setOnceProperties array with non-existent nested properties', () => { + const traits = { name: 'John', age: 30, address: 'kolkata' }; + const contextTraits = { email: 'john@example.com' }; + const setOnceProperties = ['name', 'email', 'address.city']; - const result = trimTraits(traits, contextTraits, setOnceProperties); + const result = trimTraits(traits, contextTraits, setOnceProperties); - expect(result).toEqual({ - traits: { age: 30, address: 'kolkata' }, - contextTraits: {}, - setOnce: { $name: 'John', $email: 'john@example.com' }, - }); + expect(result).toEqual({ + traits: { age: 30, address: 'kolkata' }, + contextTraits: {}, + setOnce: { $name: 'John', $email: 'john@example.com' }, }); + }); - it('should add properties to the setOnce property when given setOnceProperties array with existent nested properties', () => { - const traits = { name: 'John', age: 30, address: { city: 'kolkata' }, isAdult: false }; - const contextTraits = { email: 'john@example.com' }; - const setOnceProperties = ['name', 'email', 'address.city']; + it('should add properties to the setOnce property when given setOnceProperties array with existent nested properties', () => { + const traits = { name: 'John', age: 30, address: { city: 'kolkata' }, isAdult: false }; + const contextTraits = { email: 'john@example.com' }; + const setOnceProperties = ['name', 'email', 'address.city']; - const result = trimTraits(traits, contextTraits, setOnceProperties); + const result = trimTraits(traits, contextTraits, setOnceProperties); - expect(result).toEqual({ - traits: { age: 30, address: {}, isAdult: false }, - contextTraits: {}, - setOnce: { $name: 'John', $email: 'john@example.com', $city: 'kolkata' }, - }); + expect(result).toEqual({ + traits: { age: 30, address: {}, isAdult: false }, + contextTraits: {}, + setOnce: { $name: 'John', $email: 'john@example.com', $city: 'kolkata' }, }); }); }); + +describe('generatePageOrScreenCustomEventName', () => { + it('should generate a custom event name when userDefinedEventString contains handlebars and message object is provided', () => { + const message = { name: 'Home' }; + const userDefinedEventString = 'Viewed a {{ name }} page'; + const expected = 'Viewed a Home page'; + const result = generatePageOrScreenCustomEventName(message, userDefinedEventString); + expect(result).toBe(expected); + }); + + it('should return the undefined name when userDefinedEventString is not provided', () => { + const message = { name: 'Home' }; + const userDefinedEventString = undefined; + const result = generatePageOrScreenCustomEventName(message, userDefinedEventString); + expect(result).toBe(undefined); + }); + + it('should return the userDefinedEventString when it does not contain handlebars', () => { + const message = { name: 'Home' }; + const userDefinedEventString = 'Viewed a Home page'; + const expected = 'Viewed a Home page'; + const result = generatePageOrScreenCustomEventName(message, userDefinedEventString); + expect(result).toBe(expected); + }); + + it('should throw an InstrumentationError when getMessagePath is not present in the message object', () => { + const message = { name: 'Home' }; + const userDefinedEventString = 'Viewed a {{ path }} page'; + expect(() => { + generatePageOrScreenCustomEventName(message, userDefinedEventString); + }).toThrow(InstrumentationError); + }); +}); diff --git a/test/integrations/destinations/mp/processor/data.ts b/test/integrations/destinations/mp/processor/data.ts index dfa94352c9..2458c836cb 100644 --- a/test/integrations/destinations/mp/processor/data.ts +++ b/test/integrations/destinations/mp/processor/data.ts @@ -121,7 +121,10 @@ export const data = [ request: { body: [ { - destination: sampleDestination, + destination: overrideDestination(sampleDestination, { + useUserDefinedPageEventName: true, + userDefinedPageEventString: 'Viewed a {{ name }} page', + }), message: { anonymousId: 'e6ab2c5e-2cda-44a9-a962-e2f67df78bca', channel: 'web', @@ -195,7 +198,7 @@ export const data = [ JSON: {}, JSON_ARRAY: { batch: - '[{"event":"Loaded a Page","properties":{"ip":"0.0.0.0","$user_id":"hjikl","$current_url":"https://docs.rudderstack.com/destinations/mixpanel","$screen_dpi":2,"mp_lib":"RudderLabs JavaScript SDK","$app_build_number":"1.0.0","$app_version_string":"1.0.5","$insert_id":"dd266c67-9199-4a52-ba32-f46ddde67312","token":"dummyApiKey","distinct_id":"hjikl","time":1579847342402,"name":"Contact Us","category":"Contact","$browser":"Chrome","$browser_version":"79.0.3945.117"}}]', + '[{"event":"Viewed a Contact Us page","properties":{"ip":"0.0.0.0","$user_id":"hjikl","$current_url":"https://docs.rudderstack.com/destinations/mixpanel","$screen_dpi":2,"mp_lib":"RudderLabs JavaScript SDK","$app_build_number":"1.0.0","$app_version_string":"1.0.5","$insert_id":"dd266c67-9199-4a52-ba32-f46ddde67312","token":"dummyApiKey","distinct_id":"hjikl","time":1579847342402,"name":"Contact Us","category":"Contact","$browser":"Chrome","$browser_version":"79.0.3945.117"}}]', }, XML: {}, FORM: {},