diff --git a/src/cdk/v2/destinations/bluecore/data/bluecoreCommonConfig.json b/src/cdk/v2/destinations/bluecore/data/bluecoreCommonConfig.json index be74c7c4b3..536f77a045 100644 --- a/src/cdk/v2/destinations/bluecore/data/bluecoreCommonConfig.json +++ b/src/cdk/v2/destinations/bluecore/data/bluecoreCommonConfig.json @@ -35,7 +35,7 @@ }, { "destKey": "properties.customer.email", - "sourceKeys": "email", + "sourceKeys": "emailOnly", "required": false, "sourceFromGenericMap": true }, diff --git a/src/cdk/v2/destinations/rakuten/data/propertiesMapping.json b/src/cdk/v2/destinations/rakuten/data/propertiesMapping.json index db5d36fc4d..1a69f53205 100644 --- a/src/cdk/v2/destinations/rakuten/data/propertiesMapping.json +++ b/src/cdk/v2/destinations/rakuten/data/propertiesMapping.json @@ -6,8 +6,10 @@ }, { "sourceKeys": ["properties.tr", "properties.ran_site_id", "properties.ranSiteID"], - "required": true, - "destKey": "tr" + "destKey": "tr", + "metadata": { + "defaultValue": " " + } }, { "sourceKeys": ["properties.land", "properties.land_time", "properties.landTime"], diff --git a/src/cdk/v2/destinations/reddit/procWorkflow.yaml b/src/cdk/v2/destinations/reddit/procWorkflow.yaml index 59725c1257..7b989f15e4 100644 --- a/src/cdk/v2/destinations/reddit/procWorkflow.yaml +++ b/src/cdk/v2/destinations/reddit/procWorkflow.yaml @@ -12,6 +12,7 @@ bindings: path: ../../../../v0/util/index - name: OAuthSecretError path: '@rudderstack/integrations-lib' + - path: ./utils steps: - name: validateInput @@ -56,14 +57,14 @@ steps: const event_type = (eventNames.length === 0 || eventNames[0]==="") ? ({"tracking_type": "Custom", "custom_event_name": event}): ({tracking_type: eventNames[0]}); - name: customFields - condition: $.outputs.prepareTrackPayload.eventType.tracking_type === "Purchase" + condition: $.outputs.prepareTrackPayload.eventType.tracking_type in ['Purchase', 'AddToCart', 'ViewContent'] reference: 'https://ads-api.reddit.com/docs/v2/#tag/Conversions/paths/~1api~1v2.0~1conversions~1events~1%7Baccount_id%7D/post' template: | - const revenue_in_cents = .message.properties.revenue ? Math.round(Number(.message.properties.revenue)*100) + const revenue_in_cents = $.populateRevenueField($.outputs.prepareTrackPayload.eventType.tracking_type,^.message.properties) const customFields = .message.().({ "currency": .properties.currency, "value_decimal": revenue_in_cents ? revenue_in_cents / 100, - "item_count": (Array.isArray(.properties.products) && .properties.products.length) || (.properties.itemCount && Number(.properties.itemCount)), + "item_count": $.outputs.prepareTrackPayload.eventType.tracking_type === 'Purchase' ? (Array.isArray(.properties.products) && .properties.products.length) || (.properties.itemCount && Number(.properties.itemCount)) : null, "value": revenue_in_cents, "conversion_id": .properties.conversionId || .messageId, }); diff --git a/src/cdk/v2/destinations/reddit/utils.js b/src/cdk/v2/destinations/reddit/utils.js index c108603235..f562d31313 100644 --- a/src/cdk/v2/destinations/reddit/utils.js +++ b/src/cdk/v2/destinations/reddit/utils.js @@ -28,6 +28,59 @@ const batchEvents = (successfulEvents) => { const batchedEvents = batchEventChunks(eventChunks); return batchedEvents; }; + +const calculateDefaultRevenue = (properties) => { + // Check if working with products array + if (properties?.products && properties.products.length > 0) { + // Check if all product prices are undefined + if (properties.products.every((product) => product.price === undefined)) { + return null; // Return null if all product prices are undefined + } + // Proceed with calculation if not all prices are undefined + return properties.products.reduce( + (acc, product) => acc + (product.price || 0) * (product.quantity || 1), + 0, + ); + } + // For single product scenario, check if price is undefined + if (properties.price === undefined) { + return null; // Return null if price is undefined + } + // Proceed with calculation if price is defined + return properties.price * (properties.quantity ?? 1); +}; + +const populateRevenueField = (eventType, properties) => { + let revenueInCents; + switch (eventType) { + case 'Purchase': + revenueInCents = + properties.revenue && !Number.isNaN(properties.revenue) + ? Math.round(Number(properties?.revenue) * 100) + : null; + break; + case 'AddToCart': + revenueInCents = + properties.price && !Number.isNaN(properties.price) + ? Math.round(Number(properties?.price) * Number(properties?.quantity || 1) * 100) + : null; + break; + default: + // for viewContent + // eslint-disable-next-line no-case-declarations + const revenue = calculateDefaultRevenue(properties); + revenueInCents = revenue ? revenue * 100 : null; + break; + } + + if (lodash.isNaN(revenueInCents)) { + return null; + } + // Return the value as it is if it's not NaN + return revenueInCents; +}; module.exports = { batchEvents, + populateRevenueField, + calculateDefaultRevenue, }; diff --git a/src/cdk/v2/destinations/reddit/utils.test.js b/src/cdk/v2/destinations/reddit/utils.test.js new file mode 100644 index 0000000000..7cfa87e38f --- /dev/null +++ b/src/cdk/v2/destinations/reddit/utils.test.js @@ -0,0 +1,121 @@ +const { calculateDefaultRevenue, populateRevenueField } = require('./utils'); + +describe('calculateDefaultRevenue', () => { + // Calculates revenue for a single product with defined price and quantity + it('should calculate revenue for a single product with defined price and quantity', () => { + const properties = { + price: 10, + quantity: 2, + }; + + const result = calculateDefaultRevenue(properties); + + expect(result).toBe(20); + }); + + // Returns null for properties parameter being undefined + it('should return null for price parameter being undefined', () => { + const properties = { products: [{ quantity: 1 }] }; + + const result = calculateDefaultRevenue(properties); + + expect(result).toBeNull(); + }); + + // Calculates revenue for a single product with defined price and default quantity + it('should calculate revenue for a single product with defined price and default quantity', () => { + const properties = { + price: 10, + }; + + const result = calculateDefaultRevenue(properties); + + expect(result).toBe(10); + }); + + // Calculates revenue for multiple products with defined prices and quantities + it('should calculate revenue for multiple products with defined prices and quantities', () => { + const properties = { + products: [{ price: 10, quantity: 2 }, { quantity: 3 }], + }; + + const result = calculateDefaultRevenue(properties); + + expect(result).toBe(20); + }); + + // Calculates revenue for multiple products with defined prices and default quantities + it('should calculate revenue for multiple products with defined prices and default quantities', () => { + const properties = { + products: [{ price: 10 }, { price: 5 }], + }; + + const result = calculateDefaultRevenue(properties); + + expect(result).toBe(15); + }); +}); + +describe('populateRevenueField', () => { + // Returns revenue in cents for Purchase event type with valid revenue property + it('should return revenue in cents when Purchase event type has valid revenue property', () => { + const eventType = 'Purchase'; + const properties = { + revenue: '10.50', + }; + const expected = 1050; + + const result = populateRevenueField(eventType, properties); + + expect(result).toBe(expected); + }); + + // Returns null for Purchase event type with revenue property as non-numeric string + it('should return null when Purchase event type has revenue property as non-numeric string', () => { + const eventType = 'Purchase'; + const properties = { + revenue: 'invalid', + }; + const expected = null; + + const result = populateRevenueField(eventType, properties); + + expect(result).toBe(expected); + }); + + // Returns revenue in cents for AddToCart event type with valid price and quantity properties + it('should return revenue in cents when AddToCart event type has valid price and quantity properties', () => { + const eventType = 'AddToCart'; + const properties = { + price: '10.50', + quantity: 2, + }; + const expected = 2100; + + const result = populateRevenueField(eventType, properties); + + expect(result).toBe(expected); + }); + + // Returns revenue in cents for ViewContent event type with valid properties + it('should return revenue in cents when ViewContent event type has valid properties', () => { + const eventType = 'ViewContent'; + const properties = { + products: [ + { + price: '10.50', + quantity: 2, + }, + { + price: '5.25', + quantity: 3, + }, + ], + }; + const expected = 3675; + + const result = populateRevenueField(eventType, properties); + + expect(result).toBe(expected); + }); +}); diff --git a/src/util/openfaas/index.js b/src/util/openfaas/index.js index 878fa706d9..00b3720e13 100644 --- a/src/util/openfaas/index.js +++ b/src/util/openfaas/index.js @@ -27,6 +27,7 @@ const FAAS_AST_VID = 'ast'; const FAAS_AST_FN_NAME = 'fn-ast'; const CUSTOM_NETWORK_POLICY_WORKSPACE_IDS = process.env.CUSTOM_NETWORK_POLICY_WORKSPACE_IDS || ''; const customNetworkPolicyWorkspaceIds = CUSTOM_NETWORK_POLICY_WORKSPACE_IDS.split(','); +const CUSTOMER_TIER = process.env.CUSTOMER_TIER || 'shared'; // Initialise node cache const functionListCache = new NodeCache(); @@ -151,6 +152,10 @@ const deployFaasFunction = async ( 'com.openfaas.scale.min': FAAS_MIN_PODS_IN_TEXT, transformationId: trMetadata.transformationId, workspaceId: trMetadata.workspaceId, + team: 'data-management', + service: 'openfaas-fn', + customer: 'shared', + 'customer-tier': CUSTOMER_TIER, }; if ( trMetadata.workspaceId && diff --git a/src/util/redis/testData/shopify_source.json b/src/util/redis/testData/shopify_source.json index 04b80b8fc9..2120475baf 100644 --- a/src/util/redis/testData/shopify_source.json +++ b/src/util/redis/testData/shopify_source.json @@ -65,11 +65,8 @@ } }, "output": { - "outputToSource": { - "body": "T0s=", - "contentType": "text/plain" - }, - "statusCode": 200 + "error": "Error: Error setting value in Redis due Error: Connection is Closed", + "statusCode": 500 } }, { diff --git a/src/v0/destinations/active_campaign/data/ACIdentify.json b/src/v0/destinations/active_campaign/data/ACIdentify.json index 6cee9e72c6..134955d52e 100644 --- a/src/v0/destinations/active_campaign/data/ACIdentify.json +++ b/src/v0/destinations/active_campaign/data/ACIdentify.json @@ -1,7 +1,7 @@ [ { "destKey": "email", - "sourceKeys": "email", + "sourceKeys": "emailOnly", "sourceFromGenericMap": true, "required": true }, diff --git a/src/v0/destinations/awin/transform.js b/src/v0/destinations/awin/transform.js index 49a115c1ff..0d7fd95c33 100644 --- a/src/v0/destinations/awin/transform.js +++ b/src/v0/destinations/awin/transform.js @@ -2,10 +2,12 @@ const { InstrumentationError, ConfigurationError } = require('@rudderstack/integ const { BASE_URL, ConfigCategory, mappingConfig } = require('./config'); const { defaultRequestConfig, constructPayload, simpleProcessRouterDest } = require('../../util'); -const { getParams } = require('./utils'); +const { getParams, trackProduct } = require('./utils'); const responseBuilder = (message, { Config }) => { const { advertiserId, eventsToTrack } = Config; + const { event, properties } = message; + let finalParams = {}; const payload = constructPayload(message, mappingConfig[ConfigCategory.TRACK.name]); @@ -17,8 +19,14 @@ const responseBuilder = (message, { Config }) => { }); // if the event is present in eventsList - if (eventsList.includes(message.event)) { + if (eventsList.includes(event)) { params = getParams(payload.params, advertiserId); + const productTrackObject = trackProduct(properties, advertiserId, params.parts); + + finalParams = { + ...params, + ...productTrackObject, + }; } else { throw new InstrumentationError( "Event is not present in 'Events to Track' list. Aborting message.", @@ -27,7 +35,7 @@ const responseBuilder = (message, { Config }) => { } } const response = defaultRequestConfig(); - response.params = params; + response.params = finalParams; response.endpoint = BASE_URL; return response; diff --git a/src/v0/destinations/awin/utils.js b/src/v0/destinations/awin/utils.js index 1616227c55..be5f22474d 100644 --- a/src/v0/destinations/awin/utils.js +++ b/src/v0/destinations/awin/utils.js @@ -1,3 +1,5 @@ +const lodash = require('lodash'); + /** * Returns final params * @param {*} params @@ -24,6 +26,55 @@ const getParams = (parameters, advertiserId) => { return params; }; +const areAllValuesDefined = (obj) => + lodash.every(lodash.values(obj), (value) => !lodash.isUndefined(value)); + +const buildProductPayloadString = (payload) => { + // URL-encode each value, and join back with the same key. + const encodedPayload = Object.entries(payload).reduce((acc, [key, value]) => { + // Encode each value. Assuming that all values are either strings or can be + // safely converted to strings. + acc[key] = encodeURIComponent(value); + return acc; + }, {}); + + return `AW:P|${encodedPayload.advertiserId}|${encodedPayload.orderReference}|${encodedPayload.productId}|${encodedPayload.productName}|${encodedPayload.productItemPrice}|${encodedPayload.productQuantity}|${encodedPayload.productSku}|${encodedPayload.commissionGroupCode}|${encodedPayload.productCategory}`; +}; + +// ref: https://wiki.awin.com/index.php/Advertiser_Tracking_Guide/Product_Level_Tracking#PLT_Via_Conversion_Pixel +const trackProduct = (properties, advertiserId, commissionParts) => { + const transformedProductInfoObj = {}; + if ( + properties?.products && + Array.isArray(properties?.products) && + properties.products.length > 0 + ) { + const productsArray = properties.products; + let productIndex = 0; + productsArray.forEach((product) => { + const productPayloadNew = { + advertiserId, + orderReference: properties.order_id || properties.orderId, + productId: product.product_id || product.productId, + productName: product.name, + productItemPrice: product.price, + productQuantity: product.quantity, + productSku: product.sku || '', + commissionGroupCode: commissionParts || 'DEFAULT', + productCategory: product.category || '', + }; + if (areAllValuesDefined(productPayloadNew)) { + transformedProductInfoObj[`bd[${productIndex}]`] = + buildProductPayloadString(productPayloadNew); + productIndex += 1; + } + }); + } + return transformedProductInfoObj; +}; + module.exports = { getParams, + trackProduct, + buildProductPayloadString, }; diff --git a/src/v0/destinations/awin/utils.test.js b/src/v0/destinations/awin/utils.test.js new file mode 100644 index 0000000000..e60c07e96c --- /dev/null +++ b/src/v0/destinations/awin/utils.test.js @@ -0,0 +1,165 @@ +const { buildProductPayloadString, trackProduct } = require('./utils'); + +describe('buildProductPayloadString', () => { + // Should correctly build the payload string with all fields provided + it('should correctly build the payload string with all fields provided', () => { + const payload = { + advertiserId: '123', + orderReference: 'order123', + productId: 'prod123', + productName: 'Product 1', + productItemPrice: '10.99', + productQuantity: '2', + productSku: 'sku123', + commissionGroupCode: 'DEFAULT', + productCategory: 'Category 1', + }; + + const expected = 'AW:P|123|order123|prod123|Product%201|10.99|2|sku123|DEFAULT|Category%201'; + const result = buildProductPayloadString(payload); + + expect(result).toBe(expected); + }); + + // Should correctly handle extremely long string values for all fields + it('should correctly handle extremely long string values for all fields', () => { + const payload = { + advertiserId: '123', + orderReference: 'order123', + productId: 'prod123', + productName: 'Product 1'.repeat(100000), + productItemPrice: '10.99'.repeat(100000), + productQuantity: '2'.repeat(100000), + productSku: 'sku123'.repeat(100000), + commissionGroupCode: 'DEFAULT', + productCategory: 'Category 1'.repeat(100000), + }; + + const expected = `AW:P|123|order123|prod123|${encodeURIComponent('Product 1'.repeat(100000))}|${encodeURIComponent('10.99'.repeat(100000))}|${encodeURIComponent('2'.repeat(100000))}|${encodeURIComponent('sku123'.repeat(100000))}|DEFAULT|${encodeURIComponent('Category 1'.repeat(100000))}`; + const result = buildProductPayloadString(payload); + + expect(result).toBe(expected); + }); +}); + +describe('trackProduct', () => { + // Given a valid 'properties' object with a non-empty 'products' array, it should transform each product into a valid payload string and return an object with the transformed products. + it("should transform each product into a valid payload string and return an object with the transformed products when given a valid 'properties' object with a non-empty 'products' array", () => { + // Arrange + const properties = { + products: [ + { + product_id: '123', + name: 'Product 1', + price: 10, + quantity: 1, + sku: 'SKU123', + category: 'Category 1', + }, + { + product_id: '456', + name: 'Product 2', + price: 20, + quantity: 2, + sku: 'SKU456', + category: 'Category 2', + }, + ], + order_id: 'order123', + }; + const advertiserId = 'advertiser123'; + const commissionParts = 'COMMISSION'; + + // Act + const result = trackProduct(properties, advertiserId, commissionParts); + + // Assert + expect(result).toEqual({ + 'bd[0]': 'AW:P|advertiser123|order123|123|Product%201|10|1|SKU123|COMMISSION|Category%201', + 'bd[1]': 'AW:P|advertiser123|order123|456|Product%202|20|2|SKU456|COMMISSION|Category%202', + }); + }); + + // Given an invalid 'properties' object, it should return an empty object. + it("should return an empty object when given an invalid 'properties' object", () => { + // Arrange + const properties = {}; + const advertiserId = 'advertiser123'; + const commissionParts = 'COMMISSION'; + + // Act + const result = trackProduct(properties, advertiserId, commissionParts); + + // Assert + expect(result).toEqual({}); + }); + + it('should ignore the product which has missing properties', () => { + // Arrange + const properties = { + products: [ + { + price: 10, + quantity: 1, + sku: 'SKU123', + category: 'Category 1', + }, + { + product_id: '456', + name: 'Product 2', + price: 20, + quantity: 2, + sku: 'SKU456', + category: 'Category 2', + }, + ], + order_id: 'order123', + }; + const advertiserId = 'advertiser123'; + const commissionParts = 'COMMISSION'; + + // Act + const result = trackProduct(properties, advertiserId, commissionParts); + + // Assert + expect(result).toEqual({ + 'bd[0]': 'AW:P|advertiser123|order123|456|Product%202|20|2|SKU456|COMMISSION|Category%202', + }); + }); + + it('category and sku if undefined we put blank', () => { + // Arrange + const properties = { + products: [ + { + product_id: '123', + name: 'Product 1', + price: 10, + quantity: 1, + sku: undefined, + category: 'Category 1', + }, + { + product_id: '456', + name: 'Product 2', + price: 20, + quantity: 2, + sku: 'SKU456', + category: undefined, + }, + ], + order_id: 'order123', + }; + const advertiserId = 'advertiser123'; + const commissionParts = 'COMMISSION'; + + // Act + const result = trackProduct(properties, advertiserId, commissionParts); + + // Assert + expect(result).toEqual({ + 'bd[0]': 'AW:P|advertiser123|order123|123|Product%201|10|1||COMMISSION|Category%201', + 'bd[1]': 'AW:P|advertiser123|order123|456|Product%202|20|2|SKU456|COMMISSION|', + }); + }); +}); diff --git a/src/v0/destinations/blueshift/data/blueshiftGroupConfig.json b/src/v0/destinations/blueshift/data/blueshiftGroupConfig.json index 41e846c509..e246a059d9 100644 --- a/src/v0/destinations/blueshift/data/blueshiftGroupConfig.json +++ b/src/v0/destinations/blueshift/data/blueshiftGroupConfig.json @@ -13,7 +13,7 @@ }, { "destKey": "email", - "sourceKeys": "email", + "sourceKeys": "emailOnly", "sourceFromGenericMap": true, "required": false }, diff --git a/src/v0/destinations/blueshift/data/blueshiftIdentifyConfig.json b/src/v0/destinations/blueshift/data/blueshiftIdentifyConfig.json index cd099b2cc3..506c313aa1 100644 --- a/src/v0/destinations/blueshift/data/blueshiftIdentifyConfig.json +++ b/src/v0/destinations/blueshift/data/blueshiftIdentifyConfig.json @@ -1,7 +1,7 @@ [ { "destKey": "email", - "sourceKeys": "email", + "sourceKeys": "emailOnly", "sourceFromGenericMap": true, "required": true }, diff --git a/src/v0/destinations/blueshift/data/blueshiftTrackConfig.json b/src/v0/destinations/blueshift/data/blueshiftTrackConfig.json index 5fb1be691a..9841450754 100644 --- a/src/v0/destinations/blueshift/data/blueshiftTrackConfig.json +++ b/src/v0/destinations/blueshift/data/blueshiftTrackConfig.json @@ -7,7 +7,7 @@ }, { "destKey": "email", - "sourceKeys": "email", + "sourceKeys": "emailOnly", "sourceFromGenericMap": true, "required": false }, diff --git a/src/v0/destinations/custify/data/CUSTIFYIdentifyConfig.json b/src/v0/destinations/custify/data/CUSTIFYIdentifyConfig.json index 4a7a785e1d..00a8ea0584 100644 --- a/src/v0/destinations/custify/data/CUSTIFYIdentifyConfig.json +++ b/src/v0/destinations/custify/data/CUSTIFYIdentifyConfig.json @@ -7,7 +7,7 @@ }, { "destKey": "email", - "sourceKeys": "email", + "sourceKeys": "emailOnly", "sourceFromGenericMap": true, "required": false }, diff --git a/src/v0/destinations/custify/data/CUSTIFYTrackConfig.json b/src/v0/destinations/custify/data/CUSTIFYTrackConfig.json index f68e9f18ac..1751c84230 100644 --- a/src/v0/destinations/custify/data/CUSTIFYTrackConfig.json +++ b/src/v0/destinations/custify/data/CUSTIFYTrackConfig.json @@ -7,7 +7,7 @@ }, { "destKey": "email", - "sourceKeys": "email", + "sourceKeys": "emailOnly", "sourceFromGenericMap": true, "required": false }, diff --git a/src/v0/destinations/facebook_offline_conversions/data/FbOfflineConversionsTrackConfig.json b/src/v0/destinations/facebook_offline_conversions/data/FbOfflineConversionsTrackConfig.json index fc5f6c48fa..3f2fa1875f 100644 --- a/src/v0/destinations/facebook_offline_conversions/data/FbOfflineConversionsTrackConfig.json +++ b/src/v0/destinations/facebook_offline_conversions/data/FbOfflineConversionsTrackConfig.json @@ -39,7 +39,7 @@ }, { "destKey": "email", - "sourceKeys": "email", + "sourceKeys": "emailOnly", "required": false, "sourceFromGenericMap": true }, diff --git a/src/v0/destinations/freshmarketer/data/FRESHMARKETERIdentifyConfig.json b/src/v0/destinations/freshmarketer/data/FRESHMARKETERIdentifyConfig.json index da1a8bccbe..d8abb484b2 100644 --- a/src/v0/destinations/freshmarketer/data/FRESHMARKETERIdentifyConfig.json +++ b/src/v0/destinations/freshmarketer/data/FRESHMARKETERIdentifyConfig.json @@ -1,7 +1,7 @@ [ { "destKey": "emails", - "sourceKeys": "email", + "sourceKeys": "emailOnly", "sourceFromGenericMap": true, "required": true }, diff --git a/src/v0/destinations/freshsales/data/identifyConfig.json b/src/v0/destinations/freshsales/data/identifyConfig.json index 9be9d9d855..94a15fd43d 100644 --- a/src/v0/destinations/freshsales/data/identifyConfig.json +++ b/src/v0/destinations/freshsales/data/identifyConfig.json @@ -1,7 +1,7 @@ [ { "destKey": "emails", - "sourceKeys": "email", + "sourceKeys": "emailOnly", "sourceFromGenericMap": true, "required": true }, diff --git a/src/v0/destinations/google_adwords_enhanced_conversions/data/trackConfig.json b/src/v0/destinations/google_adwords_enhanced_conversions/data/trackConfig.json index 562a77f0e8..bf5485270b 100644 --- a/src/v0/destinations/google_adwords_enhanced_conversions/data/trackConfig.json +++ b/src/v0/destinations/google_adwords_enhanced_conversions/data/trackConfig.json @@ -51,7 +51,7 @@ }, { "destKey": "conversionAdjustments[0].userIdentifiers[0].hashedEmail", - "sourceKeys": "email", + "sourceKeys": "emailOnly", "sourceFromGenericMap": true, "required": false, "metadata": { diff --git a/src/v0/destinations/hs/util.js b/src/v0/destinations/hs/util.js index 359c93dc1a..838da08b3b 100644 --- a/src/v0/destinations/hs/util.js +++ b/src/v0/destinations/hs/util.js @@ -20,6 +20,7 @@ const { getDestinationExternalIDInfoForRetl, getValueFromMessage, isNull, + validateEventName, } = require('../../util'); const { CONTACT_PROPERTY_MAP_ENDPOINT, @@ -435,6 +436,7 @@ const getEventAndPropertiesFromConfig = (message, destination, payload) => { if (!hubspotEvents) { throw new InstrumentationError('Event and property mappings are required for track call'); } + validateEventName(event); event = event.trim().toLowerCase(); let eventName; let eventProperties; diff --git a/src/v0/destinations/impact/data/ImpactConversionConfig.json b/src/v0/destinations/impact/data/ImpactConversionConfig.json index 7ae0cc72eb..a898e6a98c 100644 --- a/src/v0/destinations/impact/data/ImpactConversionConfig.json +++ b/src/v0/destinations/impact/data/ImpactConversionConfig.json @@ -120,7 +120,7 @@ }, { "destKey": "CustomerEmail", - "sourceKeys": "email", + "sourceKeys": "emailOnly", "sourceFromGenericMap": true, "required": false }, diff --git a/src/v0/destinations/impact/data/ImpactPageLoadConfig.json b/src/v0/destinations/impact/data/ImpactPageLoadConfig.json index 0ca0a26e69..700557d3e0 100644 --- a/src/v0/destinations/impact/data/ImpactPageLoadConfig.json +++ b/src/v0/destinations/impact/data/ImpactPageLoadConfig.json @@ -7,7 +7,7 @@ }, { "destKey": "CustomerEmail", - "sourceKeys": "email", + "sourceKeys": "emailOnly", "sourceFromGenericMap": true, "required": false }, diff --git a/src/v0/destinations/klaviyo/data/KlaviyoGroup.json b/src/v0/destinations/klaviyo/data/KlaviyoGroup.json index baf6bcee86..b03cc9ee0a 100644 --- a/src/v0/destinations/klaviyo/data/KlaviyoGroup.json +++ b/src/v0/destinations/klaviyo/data/KlaviyoGroup.json @@ -1,7 +1,7 @@ [ { "destKey": "email", - "sourceKeys": "email", + "sourceKeys": "emailOnly", "required": false, "sourceFromGenericMap": true }, diff --git a/src/v0/destinations/klaviyo/data/KlaviyoIdentify.json b/src/v0/destinations/klaviyo/data/KlaviyoIdentify.json index b358919bc1..fd46b6cda9 100644 --- a/src/v0/destinations/klaviyo/data/KlaviyoIdentify.json +++ b/src/v0/destinations/klaviyo/data/KlaviyoIdentify.json @@ -7,7 +7,7 @@ }, { "destKey": "email", - "sourceKeys": "email", + "sourceKeys": "emailOnly", "required": false, "sourceFromGenericMap": true }, diff --git a/src/v0/destinations/klaviyo/data/KlaviyoProfile.json b/src/v0/destinations/klaviyo/data/KlaviyoProfile.json index 329ecd978f..03f155e787 100644 --- a/src/v0/destinations/klaviyo/data/KlaviyoProfile.json +++ b/src/v0/destinations/klaviyo/data/KlaviyoProfile.json @@ -1,7 +1,7 @@ [ { "destKey": "$email", - "sourceKeys": "email", + "sourceKeys": "emailOnly", "required": false, "sourceFromGenericMap": true }, diff --git a/src/v0/destinations/mailjet/data/MailJetIdentifyConfig.json b/src/v0/destinations/mailjet/data/MailJetIdentifyConfig.json index e32463e034..106560a447 100644 --- a/src/v0/destinations/mailjet/data/MailJetIdentifyConfig.json +++ b/src/v0/destinations/mailjet/data/MailJetIdentifyConfig.json @@ -1,7 +1,7 @@ [ { "destKey": "email", - "sourceKeys": "email", + "sourceKeys": "emailOnly", "required": true, "sourceFromGenericMap": true }, diff --git a/src/v0/destinations/mp/data/MPIdentifyConfig.json b/src/v0/destinations/mp/data/MPIdentifyConfig.json index 679ce66d7f..b5e4f51970 100644 --- a/src/v0/destinations/mp/data/MPIdentifyConfig.json +++ b/src/v0/destinations/mp/data/MPIdentifyConfig.json @@ -7,7 +7,7 @@ }, { "destKey": "$email", - "sourceKeys": "email", + "sourceKeys": "emailOnly", "required": false, "sourceFromGenericMap": true }, diff --git a/src/v0/destinations/pinterest_tag/data/pinterestUserConfig.json b/src/v0/destinations/pinterest_tag/data/pinterestUserConfig.json index 0ab963ac3c..b95f539e7c 100644 --- a/src/v0/destinations/pinterest_tag/data/pinterestUserConfig.json +++ b/src/v0/destinations/pinterest_tag/data/pinterestUserConfig.json @@ -1,7 +1,7 @@ [ { "destKey": "em", - "sourceKeys": "email", + "sourceKeys": "emailOnly", "sourceFromGenericMap": true, "required": false }, diff --git a/src/v0/destinations/revenue_cat/data/RCIdentifyConfig.json b/src/v0/destinations/revenue_cat/data/RCIdentifyConfig.json index f7e6fa7acc..b31f1355a6 100644 --- a/src/v0/destinations/revenue_cat/data/RCIdentifyConfig.json +++ b/src/v0/destinations/revenue_cat/data/RCIdentifyConfig.json @@ -13,7 +13,7 @@ }, { "destKey": "$email.value", - "sourceKeys": "email", + "sourceKeys": "emailOnly", "sourceFromGenericMap": true, "required": false }, diff --git a/src/v0/destinations/rockerbox/data/RockerboxTrackConfig.json b/src/v0/destinations/rockerbox/data/RockerboxTrackConfig.json index e405f1477d..cc3a4d5ec5 100644 --- a/src/v0/destinations/rockerbox/data/RockerboxTrackConfig.json +++ b/src/v0/destinations/rockerbox/data/RockerboxTrackConfig.json @@ -12,7 +12,7 @@ "sourceFromGenericMap": false }, { - "sourceKeys": "email", + "sourceKeys": "emailOnly", "destKey": "email", "required": false, "sourceFromGenericMap": true diff --git a/src/v0/destinations/sendgrid/data/SendgridIdentify.json b/src/v0/destinations/sendgrid/data/SendgridIdentify.json index e70378dd28..bfafd0da01 100644 --- a/src/v0/destinations/sendgrid/data/SendgridIdentify.json +++ b/src/v0/destinations/sendgrid/data/SendgridIdentify.json @@ -1,7 +1,7 @@ [ { "destKey": "email", - "sourceKeys": "email", + "sourceKeys": "emailOnly", "required": true, "sourceFromGenericMap": true }, diff --git a/src/v0/destinations/serenytics/data/SerenyticsIdentifyConfig.json b/src/v0/destinations/serenytics/data/SerenyticsIdentifyConfig.json index 4c50cb4a54..9161a7c698 100644 --- a/src/v0/destinations/serenytics/data/SerenyticsIdentifyConfig.json +++ b/src/v0/destinations/serenytics/data/SerenyticsIdentifyConfig.json @@ -35,7 +35,7 @@ }, { "destKey": "email", - "sourceKeys": "email", + "sourceKeys": "emailOnly", "sourceFromGenericMap": true, "required": false }, diff --git a/src/v0/destinations/user/data/USERGroupConfig.json b/src/v0/destinations/user/data/USERGroupConfig.json index c87653442d..c31020b68f 100644 --- a/src/v0/destinations/user/data/USERGroupConfig.json +++ b/src/v0/destinations/user/data/USERGroupConfig.json @@ -17,7 +17,7 @@ "required": true }, { - "sourceKeys": "email", + "sourceKeys": "emailOnly", "destKey": "email", "required": false, "sourceFromGenericMap": true diff --git a/src/v0/destinations/user/data/USERIdentifyConfig.json b/src/v0/destinations/user/data/USERIdentifyConfig.json index 2b89c2a3a6..f87bdd01fd 100644 --- a/src/v0/destinations/user/data/USERIdentifyConfig.json +++ b/src/v0/destinations/user/data/USERIdentifyConfig.json @@ -7,7 +7,7 @@ }, { "destKey": "email", - "sourceKeys": "email", + "sourceKeys": "emailOnly", "required": false, "sourceFromGenericMap": true }, diff --git a/src/v0/destinations/vero/data/VeroIdentifyConfig.json b/src/v0/destinations/vero/data/VeroIdentifyConfig.json index 8ea456cc1c..8ec589aaed 100644 --- a/src/v0/destinations/vero/data/VeroIdentifyConfig.json +++ b/src/v0/destinations/vero/data/VeroIdentifyConfig.json @@ -5,7 +5,7 @@ "sourceFromGenericMap": true }, { - "sourceKeys": "email", + "sourceKeys": "emailOnly", "destKey": "email", "sourceFromGenericMap": true }, diff --git a/src/v0/destinations/vero/data/VeroTrackConfig.json b/src/v0/destinations/vero/data/VeroTrackConfig.json index a3a23a6e66..04974c5eb2 100644 --- a/src/v0/destinations/vero/data/VeroTrackConfig.json +++ b/src/v0/destinations/vero/data/VeroTrackConfig.json @@ -5,7 +5,7 @@ "sourceFromGenericMap": true }, { - "sourceKeys": "email", + "sourceKeys": "emailOnly", "destKey": "identity.email", "sourceFromGenericMap": true }, diff --git a/src/v0/destinations/webengage/data/WEBENGAGEIdentifyConfig.json b/src/v0/destinations/webengage/data/WEBENGAGEIdentifyConfig.json index a99fc47a3f..4e04703fc0 100644 --- a/src/v0/destinations/webengage/data/WEBENGAGEIdentifyConfig.json +++ b/src/v0/destinations/webengage/data/WEBENGAGEIdentifyConfig.json @@ -55,7 +55,7 @@ }, { "destKey": "email", - "sourceKeys": "email", + "sourceKeys": "emailOnly", "sourceFromGenericMap": true, "required": false }, diff --git a/src/v0/sources/shopify/transform.js b/src/v0/sources/shopify/transform.js index 93e3ed0c72..b6d2a4c6cf 100644 --- a/src/v0/sources/shopify/transform.js +++ b/src/v0/sources/shopify/transform.js @@ -1,6 +1,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ const lodash = require('lodash'); const get = require('get-value'); +const { RedisError } = require('@rudderstack/integrations-lib'); const stats = require('../../../util/stats'); const { getShopifyTopic, @@ -249,16 +250,11 @@ const processIdentifierEvent = async (event, metricMetadata) => { source: metricMetadata.source, writeKey: metricMetadata.writeKey, }); + // returning 500 as status code in case of redis failure + throw new RedisError(`${e}`, 500); } } - const result = { - outputToSource: { - body: Buffer.from('OK').toString('base64'), - contentType: 'text/plain', - }, - statusCode: 200, - }; - return result; + return NO_OPERATION_SUCCESS; }; const process = async (event) => { const metricMetadata = { diff --git a/test/integrations/destinations/awin/data.ts b/test/integrations/destinations/awin/data.ts index 64c8fbc2a1..8ca294b5fb 100644 --- a/test/integrations/destinations/awin/data.ts +++ b/test/integrations/destinations/awin/data.ts @@ -843,4 +843,319 @@ export const data = [ }, }, }, + { + name: 'awin', + description: 'Track call- with product array', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + advertiserId: '1234', + eventsToTrack: [ + { + eventName: 'abc', + }, + { + eventName: 'prop2', + }, + { + eventName: 'prop3', + }, + ], + }, + }, + message: { + type: 'track', + event: 'prop2', + sentAt: '2022-01-20T13:39:21.033Z', + userId: 'user123456001', + channel: 'web', + properties: { + currency: 'INR', + voucherCode: '1bcu1', + amount: 500, + commissionGroup: 'sales', + cks: 'new', + testMode: '1', + order_id: 'QW123', + products: [ + { + product_id: '123', + name: 'Product 1', + price: 10, + quantity: 1, + sku: undefined, + category: 'Category 1', + }, + { + product_id: '456', + name: 'Product 2', + price: 20, + quantity: 2, + sku: 'SKU456', + category: undefined, + }, + ], + }, + context: { + os: { + name: '', + version: '', + }, + app: { + name: 'RudderLabs JavaScript SDK', + build: '1.0.0', + version: '1.2.20', + namespace: 'com.rudderlabs.javascript', + }, + page: { + url: 'http://127.0.0.1:7307/Testing/App_for_LaunchDarkly/ourSdk.html', + path: '/Testing/App_for_LaunchDarkly/ourSdk.html', + title: 'Document', + search: '', + tab_url: 'http://127.0.0.1:7307/Testing/App_for_LaunchDarkly/ourSdk.html', + referrer: 'http://127.0.0.1:7307/Testing/App_for_LaunchDarkly/', + initial_referrer: '$direct', + referring_domain: '127.0.0.1:7307', + initial_referring_domain: '', + }, + locale: 'en-US', + screen: { + width: 1440, + height: 900, + density: 2, + innerWidth: 536, + innerHeight: 689, + }, + traits: { + city: 'Pune', + name: 'First User', + email: 'firstUser@testmail.com', + title: 'VP', + gender: 'female', + avatar: 'https://i.pravatar.cc/300', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.2.20', + }, + campaign: {}, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36', + }, + rudderId: '553b5522-c575-40a7-8072-9741c5f9a647', + messageId: '831f1fa5-de84-4f22-880a-4c3f23fc3f04', + anonymousId: 'bf412108-0357-4330-b119-7305e767823c', + integrations: { + All: true, + }, + originalTimestamp: '2022-01-20T13:39:21.032Z', + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://www.awin1.com/sread.php', + headers: {}, + params: { + amount: 500, + ch: 'aw', + parts: 'sales:500', + cr: 'INR', + tt: 'ss', + tv: '2', + vc: '1bcu1', + cks: 'new', + merchant: '1234', + testmode: '1', + ref: 'QW123', + 'bd[0]': 'AW:P|1234|QW123|123|Product%201|10|1||sales%3A500|Category%201', + 'bd[1]': 'AW:P|1234|QW123|456|Product%202|20|2|SKU456|sales%3A500|', + }, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'awin', + description: 'Track call- with product array where important keys might be missing.', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + advertiserId: '1234', + eventsToTrack: [ + { + eventName: 'abc', + }, + { + eventName: 'prop2', + }, + { + eventName: 'prop3', + }, + ], + }, + }, + message: { + type: 'track', + event: 'prop2', + sentAt: '2022-01-20T13:39:21.033Z', + userId: 'user123456001', + channel: 'web', + properties: { + currency: 'INR', + voucherCode: '1bcu1', + amount: 500, + commissionGroup: 'sales', + cks: 'new', + testMode: '1', + order_id: 'QW123', + products: [ + { + price: 10, + quantity: 1, + sku: undefined, + category: 'Category 1', + }, + { + product_id: '456', + name: 'Product 2', + price: 20, + quantity: 2, + sku: 'SKU456', + category: undefined, + }, + ], + }, + context: { + os: { + name: '', + version: '', + }, + app: { + name: 'RudderLabs JavaScript SDK', + build: '1.0.0', + version: '1.2.20', + namespace: 'com.rudderlabs.javascript', + }, + page: { + url: 'http://127.0.0.1:7307/Testing/App_for_LaunchDarkly/ourSdk.html', + path: '/Testing/App_for_LaunchDarkly/ourSdk.html', + title: 'Document', + search: '', + tab_url: 'http://127.0.0.1:7307/Testing/App_for_LaunchDarkly/ourSdk.html', + referrer: 'http://127.0.0.1:7307/Testing/App_for_LaunchDarkly/', + initial_referrer: '$direct', + referring_domain: '127.0.0.1:7307', + initial_referring_domain: '', + }, + locale: 'en-US', + screen: { + width: 1440, + height: 900, + density: 2, + innerWidth: 536, + innerHeight: 689, + }, + traits: { + city: 'Pune', + name: 'First User', + email: 'firstUser@testmail.com', + title: 'VP', + gender: 'female', + avatar: 'https://i.pravatar.cc/300', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.2.20', + }, + campaign: {}, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36', + }, + rudderId: '553b5522-c575-40a7-8072-9741c5f9a647', + messageId: '831f1fa5-de84-4f22-880a-4c3f23fc3f04', + anonymousId: 'bf412108-0357-4330-b119-7305e767823c', + integrations: { + All: true, + }, + originalTimestamp: '2022-01-20T13:39:21.032Z', + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://www.awin1.com/sread.php', + headers: {}, + params: { + amount: 500, + ch: 'aw', + parts: 'sales:500', + cr: 'INR', + tt: 'ss', + tv: '2', + vc: '1bcu1', + cks: 'new', + merchant: '1234', + testmode: '1', + ref: 'QW123', + 'bd[0]': 'AW:P|1234|QW123|456|Product%202|20|2|SKU456|sales%3A500|', + }, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, ]; diff --git a/test/integrations/destinations/blueshift/processor/data.ts b/test/integrations/destinations/blueshift/processor/data.ts index d489a38bd6..be23521621 100644 --- a/test/integrations/destinations/blueshift/processor/data.ts +++ b/test/integrations/destinations/blueshift/processor/data.ts @@ -739,7 +739,7 @@ export const data = [ body: [ { statusCode: 400, - error: 'Missing required value from "email"', + error: 'Missing required value from "emailOnly"', statTags: { errorCategory: 'dataValidation', errorType: 'instrumentation', diff --git a/test/integrations/destinations/freshmarketer/processor/data.ts b/test/integrations/destinations/freshmarketer/processor/data.ts index ed920faef0..07112d762f 100644 --- a/test/integrations/destinations/freshmarketer/processor/data.ts +++ b/test/integrations/destinations/freshmarketer/processor/data.ts @@ -375,7 +375,7 @@ export const data = [ status: 200, body: [ { - error: 'Missing required value from "email"', + error: 'Missing required value from "emailOnly"', statTags: { destType: 'FRESHMARKETER', errorCategory: 'dataValidation', @@ -964,7 +964,7 @@ export const data = [ status: 200, body: [ { - error: 'Missing required value from "email"', + error: 'Missing required value from "emailOnly"', statTags: { destType: 'FRESHMARKETER', errorCategory: 'dataValidation', diff --git a/test/integrations/destinations/freshsales/processor/data.ts b/test/integrations/destinations/freshsales/processor/data.ts index eca3b88d9d..7c0eca0926 100644 --- a/test/integrations/destinations/freshsales/processor/data.ts +++ b/test/integrations/destinations/freshsales/processor/data.ts @@ -505,7 +505,7 @@ export const data = [ status: 200, body: [ { - error: 'Missing required value from "email"', + error: 'Missing required value from "emailOnly"', statTags: { destType: 'FRESHSALES', errorCategory: 'dataValidation', @@ -1094,7 +1094,7 @@ export const data = [ status: 200, body: [ { - error: 'Missing required value from "email"', + error: 'Missing required value from "emailOnly"', statTags: { destType: 'FRESHSALES', errorCategory: 'dataValidation', diff --git a/test/integrations/destinations/hs/processor/data.ts b/test/integrations/destinations/hs/processor/data.ts index f45f3a719b..0867f2cb54 100644 --- a/test/integrations/destinations/hs/processor/data.ts +++ b/test/integrations/destinations/hs/processor/data.ts @@ -5373,4 +5373,57 @@ export const data = [ }, }, }, + { + name: 'hs', + description: 'if event name is anything other than string we throw error', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + channel: 'web', + context: { + traits: { + email: 'testhubspot2@email.com', + firstname: 'Test Hubspot', + }, + }, + type: 'track', + originalTimestamp: '2019-10-15T09:35:31.291Z', + userId: '12345', + event: { name: 'event' }, + properties: { + user_actual_role: 'system_admin, system_user', + user_actual_id: 12345, + }, + sentAt: '2019-10-14T11:15:53.296Z', + }, + destination: destination, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + error: 'Event is a required field and should be a string', + statTags: { + destType: 'HS', + errorCategory: 'dataValidation', + errorType: 'instrumentation', + feature: 'processor', + implementation: 'native', + module: 'destination', + }, + statusCode: 400, + }, + ], + }, + }, + }, ]; diff --git a/test/integrations/destinations/mailjet/processor/data.ts b/test/integrations/destinations/mailjet/processor/data.ts index 71e06dc14e..03c3232e72 100644 --- a/test/integrations/destinations/mailjet/processor/data.ts +++ b/test/integrations/destinations/mailjet/processor/data.ts @@ -141,7 +141,7 @@ export const data = [ status: 200, body: [ { - error: 'Missing required value from "email"', + error: 'Missing required value from "emailOnly"', statTags: { destType: 'MAILJET', errorCategory: 'dataValidation', diff --git a/test/integrations/destinations/rakuten/processor/commonConfig.ts b/test/integrations/destinations/rakuten/processor/commonConfig.ts index e7e2af7fbd..96bc6669c2 100644 --- a/test/integrations/destinations/rakuten/processor/commonConfig.ts +++ b/test/integrations/destinations/rakuten/processor/commonConfig.ts @@ -63,3 +63,27 @@ export const commonProperties = { storeId: '12345', storecat: 'Electronics', }; +export const commonPropertiesWithoutRansiteID = { + orderId: 'SampleOrderId', + landTime: '20240129_1200', + date: '20240129_1300', + altord: 'SampleAlternateOrderId', + currency: 'INR', + creditCardType: 'Visa', + commReason: 'SampleCommReason', + isComm: 'Y', + consumed: '20240129_1400', + coupon: 'SampleCoupon', + custId: 'SampleCustomerId', + custScore: 'A', + custStatus: 'New', + dId: 'SampleDeviceId', + disamt: '50.00', + ordStatus: 'Pending', + segment: 'SampleSegment', + shipcountry: 'USA', + shipped: '20240129_1500', + sitename: 'SampleSiteName', + storeId: '12345', + storecat: 'Electronics', +}; diff --git a/test/integrations/destinations/rakuten/processor/track.ts b/test/integrations/destinations/rakuten/processor/track.ts index 49b26e4658..74d09b8d4c 100644 --- a/test/integrations/destinations/rakuten/processor/track.ts +++ b/test/integrations/destinations/rakuten/processor/track.ts @@ -4,6 +4,7 @@ import { commonProperties, endpoint, singleProductWithAllProperties, + commonPropertiesWithoutRansiteID, } from './commonConfig'; import { transformResultBuilder } from '../../../testUtils'; export const trackSuccess = [ @@ -449,4 +450,129 @@ export const trackSuccess = [ }, }, }, + { + id: 'rakuten-test-track-success-5', + name: 'rakuten', + description: 'Track call no ranSiteId in input', + scenario: 'Business', + successCriteria: + 'Response should contain only properties with tr as empty string (ransiteId) and product payload and status code should be 200', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination, + message: { + type: 'track', + event: 'product purchased', + sentAt: '2021-01-25T16:12:02.048Z', + userId: 'sajal12', + channel: 'mobile', + rudderId: 'b7b24f86-f7bf-46d8-b2b4-ccafc080239c', + messageId: '1611588776408-ee5a3212-fbf9-4cbb-bbad-3ed0f7c6a2ce', + properties: { + ...commonPropertiesWithoutRansiteID, + products: [ + { ...singleProductWithAllProperties }, + { + sku: 'custom sku 1', + quantity: 5, + amount: 25, + name: 'name_1', + }, + { + sku: 'custom sku 2', + name: 'SampleProduct', + quantity: 1, + amount: 30, + coupon: 'SALE50', + }, + ], + }, + anonymousId: '9c6bd77ea9da3e68', + integrations: { + All: true, + }, + originalTimestamp: '2021-01-25T15:32:56.409Z', + }, + metadata: { + destinationId: 'dummyDestId', + jobId: '1', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + metadata: { + destinationId: 'dummyDestId', + jobId: '1', + }, + output: transformResultBuilder({ + method: 'GET', + endpoint, + headers: commonOutputHeaders, + params: { + mid: 'dummyMarketingId', + xml: 1, + source: 'rudderstack', + amtlist: '2000|2500|3000', + brandlist: 'SampleBrand||', + catidlist: '12345||', + catlist: 'Electronics||', + couponlist: 'SALE20||SALE50', + disamtlist: '10.5||', + distypelist: 'Percentage||', + ismarketplacelist: 'N||', + sequencelist: '123||', + shipbylist: 'Express||', + shipidlist: 'SHIP123||', + qlist: '5|5|1', + marginlist: '0.15||', + markdownlist: '5||', + taxexemptlist: 'N||', + namelist: 'SampleProduct|name_1|SampleProduct', + skulist: 'ABC123|custom sku 1|custom sku 2', + issalelist: 'Y||', + itmstatuslist: 'In Stock||', + isclearancelist: 'Y||', + ord: 'SampleOrderId', + tr: ' ', + land: '20240129_1200', + date: '20240129_1300', + altord: 'SampleAlternateOrderId', + cur: 'INR', + cc: 'Visa', + commreason: 'SampleCommReason', + iscomm: 'Y', + consumed: '20240129_1400', + coupon: 'SampleCoupon', + custid: 'SampleCustomerId', + custscore: 'A', + custstatus: 'New', + did: 'SampleDeviceId', + disamt: '50.00', + ordstatus: 'Pending', + segment: 'SampleSegment', + shipcountry: 'USA', + shipped: '20240129_1500', + sitename: 'SampleSiteName', + storeid: '12345', + storecat: 'Electronics', + }, + userId: '', + }), + statusCode: 200, + }, + ], + }, + }, + }, ]; diff --git a/test/integrations/destinations/rakuten/processor/transformationFailure.ts b/test/integrations/destinations/rakuten/processor/transformationFailure.ts index e35ab26b69..5485efae03 100644 --- a/test/integrations/destinations/rakuten/processor/transformationFailure.ts +++ b/test/integrations/destinations/rakuten/processor/transformationFailure.ts @@ -202,9 +202,9 @@ export const transformationFailures = [ { id: 'rakuten-test-5', name: 'rakuten', - description: 'No eligible property available for required field tr present', + description: 'No eligible property available for required field land present', scenario: 'Framework', - successCriteria: 'Transformationn Error for required field tr not present', + successCriteria: 'Transformationn Error for required field land not present', feature: 'processor', module: 'destination', version: 'v0', @@ -245,7 +245,7 @@ export const transformationFailures = [ body: [ { error: - 'Missing required value from ["properties.tr","properties.ran_site_id","properties.ranSiteID"]: Workflow: procWorkflow, Step: prepareTrackPayload, ChildStep: undefined, OriginalError: Missing required value from ["properties.tr","properties.ran_site_id","properties.ranSiteID"]', + 'Missing required value from ["properties.land","properties.land_time","properties.landTime"]: Workflow: procWorkflow, Step: prepareTrackPayload, ChildStep: undefined, OriginalError: Missing required value from ["properties.land","properties.land_time","properties.landTime"]', metadata: { destinationId: 'dummyDestId', jobId: '1', diff --git a/test/integrations/destinations/reddit/processor/data.ts b/test/integrations/destinations/reddit/processor/data.ts index 49e0cd2baa..a97ae23d2a 100644 --- a/test/integrations/destinations/reddit/processor/data.ts +++ b/test/integrations/destinations/reddit/processor/data.ts @@ -443,6 +443,8 @@ export const data = [ }, event_metadata: { item_count: 0, + value: 2600, + value_decimal: 26, products: [ { id: '017c6f5d5cf86a4b22432066', @@ -581,6 +583,8 @@ export const data = [ }, event_metadata: { item_count: 5, + value: 24995, + value_decimal: 249.95, products: [ { id: '622c6f5d5cf86a4c77358033', @@ -847,6 +851,8 @@ export const data = [ }, event_metadata: { item_count: 5, + value: 24995, + value_decimal: 249.95, products: [ { id: '622c6f5d5cf86a4c77358033', diff --git a/test/integrations/destinations/reddit/router/data.ts b/test/integrations/destinations/reddit/router/data.ts index 723afff374..b5bed48ae7 100644 --- a/test/integrations/destinations/reddit/router/data.ts +++ b/test/integrations/destinations/reddit/router/data.ts @@ -90,6 +90,8 @@ export const data = [ properties: { list_id: 'list1', category: "What's New", + value: 2600, + value_decimal: 26, products: [ { product_id: '017c6f5d5cf86a4b22432066', @@ -230,6 +232,8 @@ export const data = [ }, event_metadata: { item_count: 0, + value: 2600, + value_decimal: 26, products: [ { id: '017c6f5d5cf86a4b22432066', @@ -259,6 +263,8 @@ export const data = [ }, event_metadata: { item_count: 5, + value: 24995, + value_decimal: 249.95, products: [ { id: '622c6f5d5cf86a4c77358033', @@ -349,6 +355,8 @@ export const data = [ properties: { list_id: 'list1', category: "What's New", + value: 2600, + value_decimal: 26, products: [ { product_id: '017c6f5d5cf86a4b22432066',