From 25ceedca3c2cd3561dfa17e9620b70ef4b17a178 Mon Sep 17 00:00:00 2001 From: Admin Date: Fri, 29 Dec 2023 19:05:08 +0530 Subject: [PATCH] Adding Bluecore integration --- src/v0/destinations/bluecore/config.js | 49 + .../bluecore/data/bluecoreIdentifyConfig.json | 49 + .../bluecore/data/bluecoreTrackConfig.json | 43 + src/v0/destinations/bluecore/test.js | 35 + src/v0/destinations/bluecore/transform.js | 210 ++ src/v0/destinations/bluecore/utils.js | 344 +++ .../destinations/bluecore/processor/data.ts | 1991 +++++++++++++++++ .../destinations/bluecore/router/data.ts | 234 ++ 8 files changed, 2955 insertions(+) create mode 100644 src/v0/destinations/bluecore/config.js create mode 100644 src/v0/destinations/bluecore/data/bluecoreIdentifyConfig.json create mode 100644 src/v0/destinations/bluecore/data/bluecoreTrackConfig.json create mode 100644 src/v0/destinations/bluecore/test.js create mode 100644 src/v0/destinations/bluecore/transform.js create mode 100644 src/v0/destinations/bluecore/utils.js create mode 100644 test/integrations/destinations/bluecore/processor/data.ts create mode 100644 test/integrations/destinations/bluecore/router/data.ts diff --git a/src/v0/destinations/bluecore/config.js b/src/v0/destinations/bluecore/config.js new file mode 100644 index 0000000000..66425063c9 --- /dev/null +++ b/src/v0/destinations/bluecore/config.js @@ -0,0 +1,49 @@ +const { getMappingConfig } = require('../../util'); +const BASE_URL = 'https://api.bluecore.com/api/track/mobile/v1'; + +const CONFIG_CATEGORIES = { + IDENTIFY: { + name: 'bluecoreIdentifyConfig', + type: 'identify', + }, + TRACK: { + name: 'bluecoreTrackConfig', + type: 'track', + }, +}; + +const EVENT_NAME_MAPPING = { + 'Product Viewed': 'viewed_product', + 'Product Added': 'add_to_cart', + 'Order Completed': 'purchase', + 'Products Searched': 'search', + 'Product Added to Wishlist': 'wishlist', + 'Checkout Step Viewed': 'checkout', + 'Product Removed': 'remove_from_cart', + 'Subscribe Interest': 'subscribe_interest', + 'Unsubscribe Interest': 'unsubscribe_interest', + Identify: 'identify', +}; + +const BLUECORE_IDENTIFY_EXCLUSION = [ + 'event', + 'phone', + 'phoneNumber', + 'phone_number', + 'firstName', + 'firstname', + 'first_name', + 'lastName', + 'lastname', + 'last_name', + 'gender', +]; + +const MAPPING_CONFIG = getMappingConfig(CONFIG_CATEGORIES, __dirname); +module.exports = { + CONFIG_CATEGORIES, + MAPPING_CONFIG, + EVENT_NAME_MAPPING, + BLUECORE_IDENTIFY_EXCLUSION, + BASE_URL, +}; diff --git a/src/v0/destinations/bluecore/data/bluecoreIdentifyConfig.json b/src/v0/destinations/bluecore/data/bluecoreIdentifyConfig.json new file mode 100644 index 0000000000..df809f2678 --- /dev/null +++ b/src/v0/destinations/bluecore/data/bluecoreIdentifyConfig.json @@ -0,0 +1,49 @@ +[ + { + "destKey": "properties.distinct_id", + "sourceKeys": ["userId", "anonymousId", "email"], + "required": true + }, + { + "destKey": "properties.custormer.name", + "sourceKeys": "name", + "required": false, + "sourceFromGenericMap": true + }, + { + "destKey": "properties.custormer.age", + "sourceKeys": "age", + "required": false + }, + { + "destKey": "event", + "sourceKeys": "event", + "required": false + }, + { + "destKey": "properties.custormer.sex", + "sourceKeys": "sex", + "required": false + }, + { + "destKey": "properties.custormer.address", + "sourceKeys": "address", + "required": false + }, + { + "destKey": "properties.custormer.email", + "sourceKeys": "email", + "required": true, + "sourceFromGenericMap": true + }, + { + "destKey": "client", + "sourceKeys": "context.app.version", + "required": false + }, + { + "destKey": "properties.device", + "sourceKeys": "context.device.model", + "required": false + } +] diff --git a/src/v0/destinations/bluecore/data/bluecoreTrackConfig.json b/src/v0/destinations/bluecore/data/bluecoreTrackConfig.json new file mode 100644 index 0000000000..66df422ef1 --- /dev/null +++ b/src/v0/destinations/bluecore/data/bluecoreTrackConfig.json @@ -0,0 +1,43 @@ +[ + { + "destKey": "distinct_id", + "sourceKeys": ["userId", "anonymousId", "email"], + "required": true + }, + { + "destKey": "customer.name", + "sourceKeys": "name", + "required": false + }, + { + "destKey": "customer.age", + "sourceKeys": "age", + "required": false + }, + { + "destKey": "customer.sex", + "sourceKeys": "sex", + "required": false + }, + { + "destKey": "customer.address", + "sourceKeys": "address", + "required": false + }, + { + "destKey": "customer.email", + "sourceKeys": "email", + "required": false, + "sourceFromGenericMap": true + }, + { + "destKey": "client", + "sourceKeys": "context.app.version", + "required": false + }, + { + "destKey": "device", + "sourceKeys": "context.device.model", + "required": false + } +] diff --git a/src/v0/destinations/bluecore/test.js b/src/v0/destinations/bluecore/test.js new file mode 100644 index 0000000000..d309b572f3 --- /dev/null +++ b/src/v0/destinations/bluecore/test.js @@ -0,0 +1,35 @@ +const eventProcessor = require('./transform'); + +const sampleEvent = { + message: { + type: 'TRACK', + event: 'Product Viewed', + userId: '27340af5c8819', + properties: { + product_id: '622c6f5d5cf86a4c77358033', + sku: '8472-998-0112', + category: 'Games', + name: 'Cones of Dunshire', + brand: 'Wyatt Games', + variant: 'exapansion pack', + price: 49.99, + quantity: 5, + coupon: 'PREORDER15', + currency: 'USD', + position: 1, + url: 'https://www.website.com/product/path', + image_url: 'https://www.website.com/product/path.webp', + }, + }, + destination: { + + }, +}; + +eventProcessor.process(sampleEvent) + .then(response => { + console.log('Response:', response); + }) + .catch(error => { + console.error('Error:', error); + }); diff --git a/src/v0/destinations/bluecore/transform.js b/src/v0/destinations/bluecore/transform.js new file mode 100644 index 0000000000..e8bbf4a6de --- /dev/null +++ b/src/v0/destinations/bluecore/transform.js @@ -0,0 +1,210 @@ +const { EventType } = require('../../../constants'); +const { + constructPayload, + ErrorMessage, + defaultRequestConfig, + defaultPostRequestConfig, + getValueFromMessage, + isDefinedAndNotNull, + extractCustomFields, + simpleProcessRouterDest, +} = require('../../util'); + +const { + // getActionSource, + // handleProduct, + // handleSearch, + handleProductListViewed, + // handleOrder, + // populateCustomDataBasedOnCategory, + // getCategoryFromEvent, +} = require('./utils'); + +const { JSON_MIME_TYPE } = require('../../util/constant'); +const { + TransformationError, + InstrumentationError, + ConfigurationError, +} = require('../../util/errorTypes'); + +const { + MAPPING_CONFIG, + CONFIG_CATEGORIES, + BASE_URL, + EVENT_NAME_MAPPING, + BLUECORE_IDENTIFY_EXCLUSION, +} = require('./config'); + +function checkValidEventName(str) { + return str.includes('.') || /\d/.test(str) || str.length > 64; +} + + +const trackResponseBuilder = async (message, category, { Config }) => { + console.log('Incoming Message:', message); + console.log('Destination Category:', category); + console.log('Configuration:', Config); + + let event = getValueFromMessage(message, 'event'); + if (!event) { + throw new InstrumentationError('[BLUECORE] property:: event is required for track call'); + } + + if (!Config.eventApiKey) { + throw new ConfigurationError('[BLUECORE] event Api Keys required for Authentication.'); + } + let payload = {}; + console.log('constructed Payload :', payload); + + if (!payload) { + // fail-safety for developer error + throw new TransformationError(ErrorMessage.FailedToConstructPayload); + } + event = event.trim(); + // Check for the event type being 'Product Viewed' + if (event.toLowerCase() === 'product viewed') { + // Utilize handleProductListViewed function + + // console.log('Current Message:', message); + const properties = handleProductListViewed(message, category); + // Add other necessary properties to the payload + properties.distinct_id = 'xyz@example.com'; + properties.token = 'bluestore'; + properties.client = '4.0'; + properties.device = 'mobile/iPad'; + console.log(properties); + + payload = { event : 'viewed_product', properties : properties}; + // payload.event = event.replace(/\s+/g, '_'); + // payload.properties = properties; + // if (checkValidEventName(payload.event)) { + // throw new InstrumentationError( + // "[BLUECORE] Event shouldn't contain period(.), numeric value and contains not more than 64 characters", + // ); + // } + // payload = extractCustomFields(message, payload, ['properties'], []); + + for (const product of properties.products) { + console.log("Product Details:"); + console.log(product); + } + + // Build the response object with Bluecore payload + const response = defaultRequestConfig(); + response.endpoint = `${BASE_URL}`; + + response.method = defaultPostRequestConfig.requestMethod; + const basicAuth = Buffer.from(Config.eventApiKey).toString('base64'); + response.headers = { + Authorization: `Basic ${basicAuth}`, + 'Content-Type': JSON_MIME_TYPE, + }; + response.body.JSON = payload; + console.log('Transformed Payload:', payload); + return response; + + } + if (isDefinedAndNotNull(EVENT_NAME_MAPPING[event])) { + payload.event = EVENT_NAME_MAPPING[event]; + } + payload.event = payload.event.replace(/\s+/g, '_'); + if (checkValidEventName(payload.event)) { + throw new InstrumentationError( + "[BLUECORE] Event shouldn't contain period(.), numeric value and contains not more than 64 characters", + ); + } + payload = extractCustomFields(message, payload, ['properties'], []); + console.log('Transformed Payload:', payload); + + const response = defaultRequestConfig(); + response.endpoint = `${BASE_URL}`; + + response.method = defaultPostRequestConfig.requestMethod; + const basicAuth = Buffer.from(Config.eventApiKey).toString('base64'); + response.headers = { + Authorization: `Basic ${basicAuth}`, + 'Content-Type': JSON_MIME_TYPE, + }; + response.body.JSON = payload; + return response; +}; + +const identifyResponseBuilder = async (message, category, { Config }) => { + if (!Config.usersApiKey) { + throw new ConfigurationError('[BLUECORE] User API Key required for Authentication.'); + } + + let payload = constructPayload(message, MAPPING_CONFIG[category.name]); + let event = getValueFromMessage(message, 'event'); + console.log('Payload after constructPayload:', payload); + console.log('Payload properties after constructPayload:', payload.properties); + + if (!payload) { + // fail-safety for developer error + throw new TransformationError(ErrorMessage.FailedToConstructPayload); + } + + payload = extractCustomFields( + message, + payload, + ['traits', 'context.traits'], + BLUECORE_IDENTIFY_EXCLUSION, + ); + + console.log('Payload after extractCustomFields:', payload); + console.log('Properties after extractCustomFields:', payload.properties); + + + const response = defaultRequestConfig(); + response.endpoint = `${BASE_URL}`; + response.method = defaultPostRequestConfig.requestMethod; + + const basicAuth = Buffer.from(Config.usersApiKey).toString('base64'); + response.headers = { + Authorization: `Basic ${basicAuth}`, + 'Content-Type': JSON_MIME_TYPE, + }; + response.body.JSON = payload; + // response.body.JSON.event = event; + + console.log('Final Response before returning:', response); + + return response; +}; + + +const process = async (event) => { + const { message, destination } = event; + console.log('Incoming Event:', event); + console.log('Incoming Destination:', destination); + + if (!message.type) { + throw new InstrumentationError('Message Type is not present. Aborting message.'); + } + + const messageType = message.type.toLowerCase(); + const category = CONFIG_CATEGORIES[message.type.toUpperCase()]; + console.log('Category :', category); + let response; + switch (messageType) { + case EventType.TRACK: + response = await trackResponseBuilder(message, category, destination); + break; + case EventType.IDENTIFY: + response = await identifyResponseBuilder(message, category, destination); + break; + default: + throw new InstrumentationError(`Message type ${messageType} not supported`); + } + // Log the final response before returning it + console.log('Final Response:', response); + + return response; +}; + +const processRouterDest = async (inputs, reqMetadata) => { + const respList = await simpleProcessRouterDest(inputs, process, reqMetadata); + return respList; +}; + +module.exports = { process, processRouterDest }; diff --git a/src/v0/destinations/bluecore/utils.js b/src/v0/destinations/bluecore/utils.js new file mode 100644 index 0000000000..15c963d6a0 --- /dev/null +++ b/src/v0/destinations/bluecore/utils.js @@ -0,0 +1,344 @@ +const { InstrumentationError } = require('@rudderstack/integrations-lib'); +const { isObject } = require('../../util'); +const { + ACTION_SOURCES_VALUES, + CONFIG_CATEGORIES, + OTHER_STANDARD_EVENTS, + FB_PIXEL_CUSTOM_DATA_EXCLUDE_FLATTENING, +} = require('./config'); +const { getContentType, getContentCategory } = require('../../util/facebookUtils'); + +/** format revenue according to fb standards with max two decimal places. + * @param revenue + * @return number + */ + +const formatRevenue = (revenue) => { + const formattedRevenue = parseFloat(parseFloat(revenue || '0').toFixed(2)); + if (!Number.isNaN(formattedRevenue)) { + return formattedRevenue; + } + throw new InstrumentationError('Revenue could not be converted to number'); +}; + +/** + * Returns action source + * ref : https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/server-event#action-source + * @param {*} payload + * @param {*} channel + * @returns + */ +const getActionSource = (payload, channel) => { + let actionSource = 'other'; + if (payload.action_source) { + const isActionSourceValid = ACTION_SOURCES_VALUES.includes(payload.action_source); + if (!isActionSourceValid) { + throw new InstrumentationError('Invalid Action Source type'); + } + actionSource = payload.action_source; + } else if (channel === 'web') { + actionSource = 'website'; + } else if (channel === 'mobile') { + actionSource = 'app'; + } + + return actionSource; +}; + +/** + * + * @param {*} message Rudder element + * @param {*} categoryToContent example: [ { from: 'clothing', to: 'product' } ] + * + * Handles order completed and checkout started types of specific events + */ +const handleOrder = (message, categoryToContent) => { + const { products, revenue } = message.properties; + const value = formatRevenue(revenue); + + const contentType = getContentType(message, 'product', categoryToContent); + const contentIds = []; + // const products = []; + const { + category, + quantity, + price, + currency, + contentName, + delivery_category: deliveryCategory, + } = message.properties; + if (products) { + if (products.length > 0 && Array.isArray(products)) { + products.forEach((singleProduct) => { + const pId = singleProduct?.product_id || singleProduct?.sku || singleProduct?.id; + if (pId) { + contentIds.push(pId); + // required field for content + // ref: https://developers.facebook.com/docs/meta-pixel/reference#object-properties + const content = { + id: pId, + quantity: singleProduct.quantity || quantity || 1, + item_price: singleProduct.price || price, + delivery_category: singleProduct.delivery_category || deliveryCategory, + }; + products.push(content); + } + }); + } else { + throw new InstrumentationError("'properties.products' is not sent as an Array"); + } + } + + return { + content_category: getContentCategory(category), + content_ids: contentIds, + content_type: contentType, + currency: currency || 'USD', + value, + products, + num_items: contentIds.length, + content_name: contentName, + }; +}; + +/** + * + * @param {*} message Rudder element + * @param {*} categoryToContent example [ { from: 'clothing', to: 'product' } ] + * + * Handles product list viewed + */ +const handleProductListViewed = (message, categoryToContent) => { + const { + category, + quantity, + value, + contentName, + product_id: productId, + sku, + name, + brand, + variant, + price: priceString, // Renamed to avoid conflict with modified price + currency, + position, + url, + image_url: imageUrl, + coupon, + } = message.properties; + + const quantityValue = quantity || 1; + const price = parseFloat(priceString); // Convert price to a number + + const products = []; + + if (productId) { + products.push({ + id: productId, + sku, + name, + category, + brand, + variant, + price, + currency, + quantity: quantityValue, + position, + url, + image_url: imageUrl, + coupon, + }); + } + + return { + products, + // other properties you may include + }; +}; + +/** + * + * @param {*} message Rudder Payload + * @param {*} categoryToContent Example: [ { from: 'clothing', to: 'product' } ] + * @param {*} valueFieldIdentifier it can be either value or price which will be matched from properties and assigned to value for fb payload + */ +const handleProduct = (message, categoryToContent, valueFieldIdentifier) => { + const contentIds = []; + const products = []; + const useValue = valueFieldIdentifier === 'properties.value'; + const contentId = + message.properties?.product_id || message.properties?.sku || message.properties?.id; + const contentType = getContentType(message, 'product', categoryToContent); + const contentName = message.properties.product_name || message.properties.name || ''; + const contentCategory = message.properties.category || ''; + const currency = message.properties.currency || 'USD'; + const value = useValue + ? formatRevenue(message.properties.value) + : formatRevenue(message.properties.price); + if (contentId) { + contentIds.push(contentId); + products.push({ + id: contentId, + quantity: message.properties.quantity || 1, + item_price: message.properties.price, + }); + } + return { + content_ids: contentIds, + content_type: contentType, + content_name: contentName, + content_category: getContentCategory(contentCategory), + currency, + value, + products, + }; +}; + +const handleSearch = (message) => { + const query = message?.properties?.query; + /** + * Facebook Pixel states "search_string" a string type + * ref: https://developers.facebook.com/docs/meta-pixel/reference#:~:text=an%20exact%20value.-,search_string,-String + * But it accepts "number" and "boolean" types. So, we are also doing the same by accepting "number" and "boolean" + * and throwing an error if "Object" or other types are being sent. + */ + const validQueryType = ['string', 'number', 'boolean']; + if (query && !validQueryType.includes(typeof query)) { + throw new InstrumentationError("'query' should be in string format only"); + } + + const contentIds = []; + const products = []; + const contentId = + message.properties?.product_id || message.properties?.sku || message.properties?.id; + const contentCategory = message?.properties?.category || ''; + const value = message?.properties?.value; + if (contentId) { + contentIds.push(contentId); + products.push({ + id: contentId, + quantity: message?.properties?.quantity || 1, + item_price: message?.properties?.price, + }); + } + return { + content_ids: contentIds, + content_category: getContentCategory(contentCategory), + value: formatRevenue(value), + products, + search_string: query, + }; +}; + +const populateCustomDataBasedOnCategory = ( + customData, + message, + category, + categoryToContent, + valueFieldIdentifier, +) => { + let updatedCustomData; + switch (category.type) { + case 'product list viewed': + updatedCustomData = { + ...customData, + ...handleProductListViewed(message, categoryToContent), + }; + break; + case 'product viewed': + case 'product added': + updatedCustomData = { + ...customData, + ...handleProduct(message, categoryToContent, valueFieldIdentifier), + }; + break; + case 'order completed': + updatedCustomData = { + ...customData, + ...handleOrder(message, categoryToContent), + }; + break; + case 'products searched': { + updatedCustomData = { + ...customData, + ...handleSearch(message), + }; + break; + } + case 'checkout started': { + const orderPayload = handleOrder(message, categoryToContent); + delete orderPayload.content_name; + updatedCustomData = { + ...customData, + ...orderPayload, + }; + break; + } + case 'page_view': // executed when sending track calls but with standard type PageView + case 'page': // executed when page call is done with standard PageView turned on + case 'otherStandard': + updatedCustomData = { ...customData }; + FB_PIXEL_CUSTOM_DATA_EXCLUDE_FLATTENING.forEach((customDataParameter) => { + if (message.properties?.[customDataParameter]) { + updatedCustomData[customDataParameter] = message.properties[customDataParameter]; + } + }); + break; + default: + throw new InstrumentationError(`${category.standard} type of standard event does not exist`); + } + return updatedCustomData; +}; + +const getCategoryFromEvent = (eventName) => { + let category; + switch (eventName) { + case CONFIG_CATEGORIES.PRODUCT_LIST_VIEWED.type: + case CONFIG_CATEGORIES.PRODUCT_LIST_VIEWED.eventName: + category = CONFIG_CATEGORIES.PRODUCT_LIST_VIEWED; + break; + case CONFIG_CATEGORIES.PRODUCT_VIEWED.type: + category = CONFIG_CATEGORIES.PRODUCT_VIEWED; + break; + case CONFIG_CATEGORIES.PRODUCT_ADDED.type: + case CONFIG_CATEGORIES.PRODUCT_ADDED.eventName: + category = CONFIG_CATEGORIES.PRODUCT_ADDED; + break; + case CONFIG_CATEGORIES.ORDER_COMPLETED.type: + case CONFIG_CATEGORIES.ORDER_COMPLETED.eventName: + category = CONFIG_CATEGORIES.ORDER_COMPLETED; + break; + case CONFIG_CATEGORIES.PRODUCTS_SEARCHED.type: + case CONFIG_CATEGORIES.PRODUCTS_SEARCHED.eventName: + category = CONFIG_CATEGORIES.PRODUCTS_SEARCHED; + break; + case CONFIG_CATEGORIES.CHECKOUT_STARTED.type: + case CONFIG_CATEGORIES.CHECKOUT_STARTED.eventName: + category = CONFIG_CATEGORIES.CHECKOUT_STARTED; + break; + case CONFIG_CATEGORIES.PAGE_VIEW.eventName: + category = CONFIG_CATEGORIES.PAGE_VIEW; + break; + default: + category = CONFIG_CATEGORIES.SIMPLE_TRACK; + break; + } + + if (OTHER_STANDARD_EVENTS.includes(eventName)) { + category = CONFIG_CATEGORIES.OTHER_STANDARD; + category.eventName = eventName; + } + + return category; +}; + +module.exports = { + formatRevenue, + getActionSource, + handleProduct, + handleSearch, + handleProductListViewed, + handleOrder, + populateCustomDataBasedOnCategory, + getCategoryFromEvent, +}; diff --git a/test/integrations/destinations/bluecore/processor/data.ts b/test/integrations/destinations/bluecore/processor/data.ts new file mode 100644 index 0000000000..d489a38bd6 --- /dev/null +++ b/test/integrations/destinations/bluecore/processor/data.ts @@ -0,0 +1,1991 @@ +export const data = [ + { + name: 'blueshift', + description: 'Test 0', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + eventApiKey: 'efeb4a29aba5e75d99c8a18acd620ec1', + dataCenter: 'standard', + }, + }, + message: { + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.1.5', + }, + traits: { + name: 'hardik', + email: 'hardik@rudderstack.com', + cookie: '1234abcd-efghklkj-1234kfjadslk-34iu123', + industry: 'Education', + employees: 399, + plan: 'enterprise', + 'total billed': 830, + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.1.5', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36', + locale: 'en-US', + os: { + name: '', + version: '', + }, + }, + type: 'group', + messageId: 'e5034df0-a404-47b4-a463-76df99934fea', + anonymousId: 'my-anonymous-id-new', + userId: 'sampleusrRudder7', + traits: { + groupType: 'company', + name_trait: 'Company', + value_trait: 'Comapny-ABC', + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: 400, + error: 'Missing required value from "groupId"', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'BLUESHIFT', + module: 'destination', + implementation: 'native', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'blueshift', + description: 'Test 1', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + eventApiKey: 'efeb4a29aba5e75d99c8a18acd620ec1', + usersApiKey: 'b4a29aba5e75duic8a18acd920ec1e2e', + dataCenter: 'standard', + }, + }, + message: { + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.1.5', + }, + traits: { + name: 'hardik', + email: 'hardik@rudderstack.com', + cookie: '1234abcd-efghklkj-1234kfjadslk-34iu123', + industry: 'Education', + employees: 399, + plan: 'enterprise', + 'total billed': 830, + }, + }, + type: 'group', + userId: 'rudderstack8', + groupId: '35838', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://api.getblueshift.com/api/v1/event', + headers: { + Authorization: 'Basic ZWZlYjRhMjlhYmE1ZTc1ZDk5YzhhMThhY2Q2MjBlYzE=', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + group_id: '35838', + customer_id: 'rudderstack8', + email: 'hardik@rudderstack.com', + event: 'identify', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'blueshift', + description: 'Test 2', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + eventApiKey: 'efeb4a29aba5e75d99c8a18acd620ec1', + usersApiKey: 'b4a29aba5e75d99c8a18acd920ec1e2e', + dataCenter: 'standard', + }, + }, + message: { + context: { + ip: '14.5.67.21', + device: { + adTrackingEnabled: true, + advertisingId: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'Android', + attTrackingStatus: 3, + }, + os: { + name: 'Android', + version: '9', + }, + network: { + bluetooth: false, + carrier: 'Android', + cellular: true, + wifi: true, + }, + address: { + city: 'kolkata', + country: 'India', + postalCode: 789223, + latitude: '37.7672319', + longitude: '-122.4021353', + state: 'WB', + street: 'rajnagar', + }, + }, + properties: { + cookie: '1234abcd-efghijkj-1234kfjadslk-34iu123', + }, + messageId: '34abcd-efghijkj-1234kf', + type: 'track', + event: 'identify', + userId: 'sampleusrRudder7', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://api.getblueshift.com/api/v1/event', + headers: { + Authorization: 'Basic ZWZlYjRhMjlhYmE1ZTc1ZDk5YzhhMThhY2Q2MjBlYzE=', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + customer_id: 'sampleusrRudder7', + event: 'identify', + device_type: 'Android', + device_id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + device_idfa: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + device_idfv: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + device_manufacturer: 'Google', + os_name: 'Android', + network_carrier: 'Android', + ip: '14.5.67.21', + latitude: '37.7672319', + longitude: '-122.4021353', + event_uuid: '34abcd-efghijkj-1234kf', + cookie: '1234abcd-efghijkj-1234kfjadslk-34iu123', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'blueshift', + description: 'Test 3', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + eventApiKey: 'efeb4a29aba5e75d99c8a18acd620ec1', + usersApiKey: 'b4a29aba5e75duic8a18acd920ec1e2e', + dataCenter: 'standard', + }, + }, + message: { + type: 'track', + event: 'Product Viewed', + properties: { + cookie: '1234abcd-efghijkj-1234kfjadslk-34iu123', + checkout_id: 'C324532', + order_id: 'T1230', + value: 15.98, + revenue: 16.98, + shipping: 3, + coupon: 'FY21', + currency: 'INR', + products: [ + { + product_id: 'product-mixedfruit-jam', + sku: 'sku-1', + category: 'Food', + name: 'Food/Drink', + brand: 'Sample', + variant: 'None', + price: 10, + quantity: 2, + currency: 'INR', + position: 1, + value: 6, + typeOfProduct: 'Food', + url: 'https://www.example.com/product/bacon-jam', + image_url: 'https://www.example.com/product/bacon-jam.jpg', + }, + ], + }, + context: { + app: { + build: '1', + name: 'RudderAndroidClient', + namespace: 'com.rudderstack.demo.android', + version: '1.0', + }, + device: { + id: '7e32188a4dab669f', + manufacturer: 'Google', + model: 'Android SDK built for x86', + name: 'generic_x86', + type: 'android', + }, + library: { + name: 'com.rudderstack.android.sdk.core', + version: '0.1.4', + }, + locale: 'en-US', + network: { + carrier: 'Android', + bluetooth: false, + cellular: true, + wifi: true, + }, + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', + name: 'some campaign', + }, + os: { + name: 'Android', + version: '9', + }, + screen: { + density: 420, + height: 1794, + width: 1080, + }, + timezone: 'Asia/Mumbai', + traits: { + anonymousId: '7e32188a4dab669f', + }, + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + }, + }, + messageId: '34abcd-efghijkj-1234kf', + userId: 'sampleRudderstack9', + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://api.getblueshift.com/api/v1/event', + headers: { + Authorization: 'Basic ZWZlYjRhMjlhYmE1ZTc1ZDk5YzhhMThhY2Q2MjBlYzE=', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event: 'view', + device_type: 'android', + device_id: '7e32188a4dab669f', + device_idfv: '7e32188a4dab669f', + device_manufacturer: 'Google', + os_name: 'Android', + network_carrier: 'Android', + cookie: '1234abcd-efghijkj-1234kfjadslk-34iu123', + checkout_id: 'C324532', + order_id: 'T1230', + value: 15.98, + revenue: 16.98, + shipping: 3, + coupon: 'FY21', + currency: 'INR', + products: [ + { + product_id: 'product-mixedfruit-jam', + sku: 'sku-1', + category: 'Food', + name: 'Food/Drink', + brand: 'Sample', + variant: 'None', + price: 10, + quantity: 2, + currency: 'INR', + position: 1, + value: 6, + typeOfProduct: 'Food', + url: 'https://www.example.com/product/bacon-jam', + image_url: 'https://www.example.com/product/bacon-jam.jpg', + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'blueshift', + description: 'Test 4', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + eventApiKey: 'efeb4a29aba5e75d99c8a18acd620ec1', + usersApiKey: 'b4a29aba5e75duic8a18acd920ec1e2e', + dataCenter: 'eu', + }, + }, + message: { + type: 'track', + event: 'Products Searched', + properties: { + description: 'Sneaker purchase', + brand: 'Victory Sneakers', + colors: ['red', 'blue'], + items: [ + { + text: 'New Line Sneakers', + price: '$ 79.95', + }, + { + text: 'Old Line Sneakers', + price: '$ 79.95', + }, + { + text: 'Blue Line Sneakers', + price: '$ 79.95', + }, + ], + name: 'Hugh Manbeing', + userLocation: { + state: 'CO', + zip: '80202', + }, + }, + context: { + app: { + build: '1', + name: 'RudderAndroidClient', + namespace: 'com.rudderstack.demo.android', + version: '1.0', + }, + device: { + id: '7e32188a4dab669f', + manufacturer: 'Google', + model: 'Android SDK built for x86', + name: 'generic_x86', + type: 'android', + }, + library: { + name: 'com.rudderstack.android.sdk.core', + version: '0.1.4', + }, + locale: 'en-US', + network: { + carrier: 'Android', + bluetooth: false, + cellular: true, + wifi: true, + }, + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', + name: 'some campaign', + }, + os: { + name: 'Android', + version: '9', + }, + screen: { + density: 420, + height: 1794, + width: 1080, + }, + timezone: 'Asia/Mumbai', + traits: { + anonymousId: '7e32188a4dab669f', + }, + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + }, + }, + messageId: '34abcd-efghijkj-1234kf', + userId: 'sampleRudderstack9', + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://api.eu.getblueshift.com/api/v1/event', + headers: { + Authorization: 'Basic ZWZlYjRhMjlhYmE1ZTc1ZDk5YzhhMThhY2Q2MjBlYzE=', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + event: 'search', + device_type: 'android', + device_id: '7e32188a4dab669f', + device_idfv: '7e32188a4dab669f', + device_manufacturer: 'Google', + os_name: 'Android', + network_carrier: 'Android', + description: 'Sneaker purchase', + brand: 'Victory Sneakers', + colors: ['red', 'blue'], + items: [ + { + text: 'New Line Sneakers', + price: '$ 79.95', + }, + { + text: 'Old Line Sneakers', + price: '$ 79.95', + }, + { + text: 'Blue Line Sneakers', + price: '$ 79.95', + }, + ], + name: 'Hugh Manbeing', + userLocation: { + state: 'CO', + zip: '80202', + }, + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'blueshift', + description: 'Test 5', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + usersApiKey: 'b4a29aba5e75d99c8a18acd920ec1e2e', + dataCenter: 'standard', + }, + }, + message: { + type: 'track', + event: 'Product_purchased', + properties: { + cookie: '1234abcd-efghijkj-1234kfjadslk-34iu123', + }, + messageId: '34abcd-efghijkj-1234kf', + context: { + ip: '14.5.67.21', + device: { + adTrackingEnabled: true, + advertisingId: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'Android', + attTrackingStatus: 3, + }, + os: { + name: 'Android', + version: '9', + }, + network: { + bluetooth: false, + carrier: 'Android', + cellular: true, + wifi: true, + }, + address: { + city: 'kolkata', + country: 'India', + postalCode: 789223, + latitude: '37.7672319', + longitude: '-122.4021353', + state: 'WB', + street: 'rajnagar', + }, + }, + userId: 'sampleRudderstack9', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: 400, + error: '[BLUESHIFT] event Api Keys required for Authentication.', + statTags: { + errorCategory: 'dataValidation', + errorType: 'configuration', + destType: 'BLUESHIFT', + module: 'destination', + implementation: 'native', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'blueshift', + description: 'Test 6', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + eventApiKey: 'a5e75d99c8a18acb4a29abd920ec1e2e', + usersApiKey: 'b4a29aba5e75d99c8a18acd920ec1e2e', + dataCenter: 'standard', + }, + }, + message: { + type: 'identify', + event: 'Product_purchased', + properties: { + cookie: '1234abcd-efghijkj-1234kfjadslk-34iu123', + }, + messageId: '34abcd-efghijkj-1234kf', + context: { + ip: '14.5.67.21', + device: { + adTrackingEnabled: true, + advertisingId: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'Android', + attTrackingStatus: 3, + }, + os: { + name: 'Android', + version: '9', + }, + network: { + bluetooth: false, + carrier: 'Android', + cellular: true, + wifi: true, + }, + address: { + city: 'kolkata', + country: 'India', + postalCode: 789223, + latitude: '37.7672319', + longitude: '-122.4021353', + state: 'WB', + street: 'rajnagar', + }, + }, + userId: 'sampleRudderstack9', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: 400, + error: 'Missing required value from "email"', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'BLUESHIFT', + module: 'destination', + implementation: 'native', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'blueshift', + description: 'Test 7', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + eventApiKey: 'a5e75d99c8a18acb4a29abd920ec1e2e', + usersApiKey: 'b4a29aba5e75d99c8a18acd920ec1e2e', + dataCenter: 'standard', + }, + }, + message: { + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + locale: 'en-US', + ip: '0.0.0.0', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: 'anon_id', + type: 'identify', + traits: { + email: 'chandan@companyname.com', + userId: 'rudder123', + anonymousId: 'anon_id', + name: 'James Doe', + phone: '92374162212', + gender: 'M', + firstname: 'James', + lastname: 'Doe', + employed: true, + birthday: '1614775793', + education: 'Science', + graduate: true, + married: true, + customerType: 'Prime', + msg_push: true, + msgSms: true, + msgemail: true, + msgwhatsapp: false, + custom_tags: ['Test_User', 'Interested_User', 'DIY_Hobby'], + custom_mappings: { + Office: 'Trastkiv', + Country: 'Russia', + }, + address: { + city: 'kolkata', + country: 'India', + postalCode: 789223, + state: 'WB', + street: '', + }, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://api.getblueshift.com/api/v1/customers', + headers: { + Authorization: 'Basic YjRhMjlhYmE1ZTc1ZDk5YzhhMThhY2Q5MjBlYzFlMmU=', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + email: 'chandan@companyname.com', + customer_id: 'rudder123', + phone_number: '92374162212', + firstname: 'James', + lastname: 'Doe', + gender: 'M', + userId: 'rudder123', + anonymousId: 'anon_id', + name: 'James Doe', + employed: true, + birthday: '1614775793', + education: 'Science', + graduate: true, + married: true, + customerType: 'Prime', + msg_push: true, + msgSms: true, + msgemail: true, + msgwhatsapp: false, + custom_tags: ['Test_User', 'Interested_User', 'DIY_Hobby'], + custom_mappings: { + Office: 'Trastkiv', + Country: 'Russia', + }, + address: { + city: 'kolkata', + country: 'India', + postalCode: 789223, + state: 'WB', + street: '', + }, + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'blueshift', + description: 'Test 8', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + eventApiKey: 'a5e75d99c8a18acb4a29abd920ec1e2e', + dataCenter: 'eu', + }, + }, + message: { + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + locale: 'en-US', + ip: '0.0.0.0', + os: { + name: '', + version: '', + }, + screen: { + density: 2, + }, + }, + messageId: '84e26acc-56a5-4835-8233-591137fca468', + session_id: '3049dc4c-5a95-4ccd-a3e7-d74a7e411f22', + originalTimestamp: '2019-10-14T09:03:17.562Z', + anonymousId: 'anon_id', + type: 'identify', + traits: { + email: 'chandan@companyname.com', + userId: 'rudder123', + anonymousId: 'anon_id', + name: 'James Doe', + phone: '92374162212', + gender: 'M', + firstname: 'James', + lastname: 'Doe', + employed: true, + birthday: '1614775793', + education: 'Science', + graduate: true, + married: true, + customerType: 'Prime', + msg_push: true, + msgSms: true, + msgemail: true, + msgwhatsapp: false, + custom_tags: ['Test_User', 'Interested_User', 'DIY_Hobby'], + custom_mappings: { + Office: 'Trastkiv', + Country: 'Russia', + }, + address: { + city: 'kolkata', + country: 'India', + postalCode: 789223, + state: 'WB', + street: '', + }, + }, + integrations: { + All: true, + }, + sentAt: '2019-10-14T09:03:22.563Z', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: 400, + error: '[BLUESHIFT] User API Key required for Authentication.', + statTags: { + errorCategory: 'dataValidation', + errorType: 'configuration', + destType: 'BLUESHIFT', + module: 'destination', + implementation: 'native', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'blueshift', + description: 'Test 9', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + eventApiKey: 'a5e75d99c8a18acb4a29abd920ec1e2e', + usersApiKey: 'b4a29aba5e75d99c8a18acd920ec1e2e', + dataCenter: 'eu', + }, + }, + message: { + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + ip: '0.0.0.0', + }, + type: 'identify', + traits: { + email: 'chandan@companyname.com', + userId: 'rudder123', + anonymousId: 'anon_id', + name: 'James Doe', + phone: '92374162212', + gender: 'M', + firstname: 'James', + lastname: 'Doe', + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://api.eu.getblueshift.com/api/v1/customers', + headers: { + Authorization: 'Basic YjRhMjlhYmE1ZTc1ZDk5YzhhMThhY2Q5MjBlYzFlMmU=', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + email: 'chandan@companyname.com', + customer_id: 'rudder123', + phone_number: '92374162212', + firstname: 'James', + lastname: 'Doe', + gender: 'M', + userId: 'rudder123', + anonymousId: 'anon_id', + name: 'James Doe', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'blueshift', + description: 'Test 10', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + eventApiKey: 'a5e75d99c8a18acb4a29abd920ec1e2e', + usersApiKey: 'b4a29aba5e75d99c8a18acd920ec1e2e', + dataCenter: 'eu', + }, + }, + message: { + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + ip: '0.0.0.0', + }, + traits: { + email: 'chandan@companyname.com', + userId: 'rudder123', + anonymousId: 'anon_id', + name: 'James Doe', + phone: '92374162212', + gender: 'M', + firstname: 'James', + lastname: 'Doe', + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: 400, + error: 'Message Type is not present. Aborting message.', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'BLUESHIFT', + module: 'destination', + implementation: 'native', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'blueshift', + description: 'Test 11', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + eventApiKey: 'a5e75d99c8a18acb4a29abd920ec1e2e', + usersApiKey: 'b4a29aba5e75d99c8a18acd920ec1e2e', + dataCenter: 'eu', + }, + }, + message: { + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + locale: 'en-US', + ip: '0.0.0.0', + }, + type: 'page', + traits: { + email: 'chandan@companyname.com', + userId: 'rudder123', + anonymousId: 'anon_id', + name: 'James Doe', + phone: '92374162212', + gender: 'M', + firstname: 'James', + lastname: 'Doe', + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: 400, + error: 'Message type page not supported', + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'BLUESHIFT', + module: 'destination', + implementation: 'native', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'blueshift', + description: 'Test 12', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + eventApiKey: 'efeb4a29aba5e75d99c8a18acd620ec1', + usersApiKey: 'b4a29aba5e75duic8a18acd920ec1e2e', + dataCenter: 'eu', + }, + }, + message: { + type: 'track', + event: 'Order Completed', + properties: { + total: 1000, + products: [ + { + product_id: '507f1f77bcf86cd799439011', + sku: '45790-32', + name: 'Monopoly: 3rd Edition', + price: '19', + position: '1', + category: 'Games,Gifts,Entertainment,Toys', + url: 'https://www.example.com/product/path', + image_url: 'https://www.example.com/product/path.jpg', + }, + { + product_id: '507f1f77bcf86cd799439011', + sku: '45790-32', + name: 'Monopoly: 3rd Edition', + price: '19', + quantity: '2', + position: '1', + category: 'Games,Gifts,Entertainment,Toys', + url: 'https://www.example.com/product/path', + image_url: 'https://www.example.com/product/path.jpg', + }, + ], + }, + context: { + app: { + build: '1', + name: 'RudderAndroidClient', + namespace: 'com.rudderstack.demo.android', + version: '1.0', + }, + device: { + id: '7e32188a4dab669f', + manufacturer: 'Google', + model: 'Android SDK built for x86', + name: 'generic_x86', + type: 'android', + }, + library: { + name: 'com.rudderstack.android.sdk.core', + version: '0.1.4', + }, + locale: 'en-US', + network: { + carrier: 'Android', + bluetooth: false, + cellular: true, + wifi: true, + }, + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', + name: 'some campaign', + }, + os: { + name: 'Android', + version: '9', + }, + screen: { + density: 420, + height: 1794, + width: 1080, + }, + timezone: 'Asia/Mumbai', + traits: { + anonymousId: '7e32188a4dab669f', + }, + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + }, + userId: 'sampleRudderstack11', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://api.eu.getblueshift.com/api/v1/event', + headers: { + Authorization: 'Basic ZWZlYjRhMjlhYmE1ZTc1ZDk5YzhhMThhY2Q2MjBlYzE=', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + customer_id: 'sampleRudderstack11', + event: 'purchase', + device_type: 'android', + device_id: '7e32188a4dab669f', + device_idfv: '7e32188a4dab669f', + device_manufacturer: 'Google', + os_name: 'Android', + network_carrier: 'Android', + total: 1000, + products: [ + { + product_id: '507f1f77bcf86cd799439011', + sku: '45790-32', + name: 'Monopoly: 3rd Edition', + price: '19', + position: '1', + category: 'Games,Gifts,Entertainment,Toys', + url: 'https://www.example.com/product/path', + image_url: 'https://www.example.com/product/path.jpg', + }, + { + product_id: '507f1f77bcf86cd799439011', + sku: '45790-32', + name: 'Monopoly: 3rd Edition', + price: '19', + quantity: '2', + position: '1', + category: 'Games,Gifts,Entertainment,Toys', + url: 'https://www.example.com/product/path', + image_url: 'https://www.example.com/product/path.jpg', + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'blueshift', + description: 'Test 13', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + eventApiKey: 'efeb4a29aba5e75d99c8a18acd620ec1', + usersApiKey: 'b4a29aba5e75d99c8a18acd920ec1e2e', + dataCenter: 'eu', + }, + }, + message: { + context: { + ip: '14.5.67.21', + device: { + adTrackingEnabled: true, + advertisingId: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + manufacturer: 'Google', + model: 'AOSP on IA Emulator', + name: 'generic_x86_arm', + type: 'Android', + attTrackingStatus: 3, + }, + os: { + name: 'Android', + version: '9', + }, + network: { + bluetooth: false, + carrier: 'Android', + cellular: true, + wifi: true, + }, + address: { + city: 'kolkata', + country: 'India', + postalCode: 789223, + latitude: '37.7672319', + longitude: '-122.4021353', + state: 'WB', + street: 'rajnagar', + }, + }, + properties: { + cookie: '1234abcd-efghijkj-1234kfjadslk-34iu123', + }, + messageId: '34abcd-efghijkj-1234kf', + type: 'track', + event: 'Custom Events', + userId: 'sampleusrRudder7', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://api.eu.getblueshift.com/api/v1/event', + headers: { + Authorization: 'Basic ZWZlYjRhMjlhYmE1ZTc1ZDk5YzhhMThhY2Q2MjBlYzE=', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + customer_id: 'sampleusrRudder7', + event: 'Custom_Events', + device_type: 'Android', + device_id: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + device_idfa: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + device_idfv: '3f034872-5e28-45a1-9eda-ce22a3e36d1a', + device_manufacturer: 'Google', + os_name: 'Android', + network_carrier: 'Android', + ip: '14.5.67.21', + latitude: '37.7672319', + longitude: '-122.4021353', + event_uuid: '34abcd-efghijkj-1234kf', + cookie: '1234abcd-efghijkj-1234kfjadslk-34iu123', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'blueshift', + description: 'Test 14', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + eventApiKey: 'efeb4a29aba5e75d99c8a18acd620ec1', + usersApiKey: 'b4a29aba5e75duic8a18acd920ec1e2e', + dataCenter: 'eu', + }, + }, + message: { + type: 'track', + event: 'Order 9Completed', + properties: { + total: 1000, + products: [ + { + product_id: '507f1f77bcf86cd799439011', + sku: '45790-32', + name: 'Monopoly: 3rd Edition', + price: '19', + position: '1', + category: 'Games,Gifts,Entertainment,Toys', + url: 'https://www.example.com/product/path', + image_url: 'https://www.example.com/product/path.jpg', + }, + { + product_id: '507f1f77bcf86cd799439011', + sku: '45790-32', + name: 'Monopoly: 3rd Edition', + price: '19', + quantity: '2', + position: '1', + category: 'Games,Gifts,Entertainment,Toys', + url: 'https://www.example.com/product/path', + image_url: 'https://www.example.com/product/path.jpg', + }, + ], + }, + context: { + app: { + build: '1', + name: 'RudderAndroidClient', + namespace: 'com.rudderstack.demo.android', + version: '1.0', + }, + device: { + id: '7e32188a4dab669f', + manufacturer: 'Google', + model: 'Android SDK built for x86', + name: 'generic_x86', + type: 'android', + }, + library: { + name: 'com.rudderstack.android.sdk.core', + version: '0.1.4', + }, + locale: 'en-US', + network: { + carrier: 'Android', + bluetooth: false, + cellular: true, + wifi: true, + }, + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', + name: 'some campaign', + }, + os: { + name: 'Android', + version: '9', + }, + screen: { + density: 420, + height: 1794, + width: 1080, + }, + timezone: 'Asia/Mumbai', + traits: { + anonymousId: '7e32188a4dab669f', + }, + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + }, + userId: 'sampleRudderstack11', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: 400, + error: + "[Blueshift] Event shouldn't contain period(.), numeric value and contains not more than 64 characters", + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'BLUESHIFT', + module: 'destination', + implementation: 'native', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'blueshift', + description: 'Test 15', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + eventApiKey: 'efeb4a29aba5e75d99c8a18acd620ec1', + usersApiKey: 'b4a29aba5e75duic8a18acd920ec1e2e', + dataCenter: 'eu', + }, + }, + message: { + type: 'track', + event: 'Order.Completed', + properties: { + total: 1000, + products: [ + { + product_id: '507f1f77bcf86cd799439011', + sku: '45790-32', + name: 'Monopoly: 3rd Edition', + price: '19', + position: '1', + category: 'Games,Gifts,Entertainment,Toys', + url: 'https://www.example.com/product/path', + image_url: 'https://www.example.com/product/path.jpg', + }, + { + product_id: '507f1f77bcf86cd799439011', + sku: '45790-32', + name: 'Monopoly: 3rd Edition', + price: '19', + quantity: '2', + position: '1', + category: 'Games,Gifts,Entertainment,Toys', + url: 'https://www.example.com/product/path', + image_url: 'https://www.example.com/product/path.jpg', + }, + ], + }, + context: { + app: { + build: '1', + name: 'RudderAndroidClient', + namespace: 'com.rudderstack.demo.android', + version: '1.0', + }, + device: { + id: '7e32188a4dab669f', + manufacturer: 'Google', + model: 'Android SDK built for x86', + name: 'generic_x86', + type: 'android', + }, + library: { + name: 'com.rudderstack.android.sdk.core', + version: '0.1.4', + }, + locale: 'en-US', + network: { + carrier: 'Android', + bluetooth: false, + cellular: true, + wifi: true, + }, + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', + name: 'some campaign', + }, + os: { + name: 'Android', + version: '9', + }, + screen: { + density: 420, + height: 1794, + width: 1080, + }, + timezone: 'Asia/Mumbai', + traits: { + anonymousId: '7e32188a4dab669f', + }, + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + }, + userId: 'sampleRudderstack11', + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: 400, + error: + "[Blueshift] Event shouldn't contain period(.), numeric value and contains not more than 64 characters", + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'BLUESHIFT', + module: 'destination', + implementation: 'native', + feature: 'processor', + }, + }, + ], + }, + }, + }, + { + name: 'blueshift', + description: 'Test 16', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + eventApiKey: 'efeb4a29aba5e75d99c8a18acd620ec1', + usersApiKey: 'b4a29aba5e75duic8a18acd920ec1e2e', + dataCenter: 'standard', + }, + }, + message: { + channel: 'web', + context: { + app: { + build: '1', + name: 'RudderAndroidClient', + namespace: 'com.rudderstack.demo.android', + version: '1.0', + }, + device: { + id: '7e32188a4dab669f', + manufacturer: 'Google', + model: 'Android SDK built for x86', + name: 'generic_x86', + type: 'android', + }, + library: { + name: 'com.rudderstack.android.sdk.core', + version: '0.1.4', + }, + locale: 'en-US', + network: { + carrier: 'Android', + bluetooth: false, + cellular: true, + wifi: true, + }, + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', + name: 'some campaign', + }, + os: { + name: 'Android', + version: '9', + }, + screen: { + density: 420, + height: 1794, + width: 1080, + }, + timezone: 'Asia/Mumbai', + traits: { + anonymousId: '7e32188a4dab669f', + }, + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + }, + type: 'group', + messageId: 'e5034jh0-a404-47b4-a463-76df99934kl2', + userId: 'sampleusrRudder1', + groupId: 'group22222', + traits: { + name: 'hardik', + email: 'hardik@rudderstack.com', + cookie: '1234abcd-efghklkj-1234kfjadslk-34iu123', + industry: 'Education', + employees: 399, + plan: 'enterprise', + 'total billed': 830, + gender: 'male', + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://api.getblueshift.com/api/v1/event', + headers: { + Authorization: 'Basic ZWZlYjRhMjlhYmE1ZTc1ZDk5YzhhMThhY2Q2MjBlYzE=', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + group_id: 'group22222', + customer_id: 'sampleusrRudder1', + email: 'hardik@rudderstack.com', + device_type: 'android', + device_id: '7e32188a4dab669f', + device_idfv: '7e32188a4dab669f', + device_manufacturer: 'Google', + os_name: 'Android', + network_carrier: 'Android', + event_uuid: 'e5034jh0-a404-47b4-a463-76df99934kl2', + event: 'identify', + name: 'hardik', + cookie: '1234abcd-efghklkj-1234kfjadslk-34iu123', + industry: 'Education', + employees: 399, + plan: 'enterprise', + 'total billed': 830, + gender: 'male', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + userId: '', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'blueshift', + description: 'Test 17', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + usersApiKey: 'b4a29aba5e75duic8a18acd920ec1e2e', + dataCenter: 'eu', + }, + }, + message: { + channel: 'web', + context: { + app: { + build: '1', + name: 'RudderAndroidClient', + namespace: 'com.rudderstack.demo.android', + version: '1.0', + }, + device: { + id: '7e32188a4dab669f', + manufacturer: 'Google', + model: 'Android SDK built for x86', + name: 'generic_x86', + type: 'android', + }, + library: { + name: 'com.rudderstack.android.sdk.core', + version: '0.1.4', + }, + locale: 'en-US', + network: { + carrier: 'Android', + bluetooth: false, + cellular: true, + wifi: true, + }, + campaign: { + source: 'google', + medium: 'medium', + term: 'keyword', + content: 'some content', + name: 'some campaign', + }, + os: { + name: 'Android', + version: '9', + }, + screen: { + density: 420, + height: 1794, + width: 1080, + }, + timezone: 'Asia/Mumbai', + traits: { + anonymousId: '7e32188a4dab669f', + }, + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)', + }, + type: 'group', + messageId: 'e5034jh0-a404-47b4-a463-76df99934kl2', + userId: 'sampleusrRudder1', + groupId: 'group22222', + traits: { + name: 'hardik', + email: 'hardik@rudderstack.com', + cookie: '1234abcd-efghklkj-1234kfjadslk-34iu123', + industry: 'Education', + employees: 399, + plan: 'enterprise', + 'total billed': 830, + gender: 'male', + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + statusCode: 400, + error: '[BLUESHIFT] event API Key required for Authentication.', + statTags: { + errorCategory: 'dataValidation', + errorType: 'configuration', + destType: 'BLUESHIFT', + module: 'destination', + implementation: 'native', + feature: 'processor', + }, + }, + ], + }, + }, + }, +]; diff --git a/test/integrations/destinations/bluecore/router/data.ts b/test/integrations/destinations/bluecore/router/data.ts new file mode 100644 index 0000000000..bc9f7d4e8e --- /dev/null +++ b/test/integrations/destinations/bluecore/router/data.ts @@ -0,0 +1,234 @@ +export const data = [ + { + name: 'bluecore', + description: 'Test 0', + feature: 'router', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + input: [ + { + destination: { + Config: { + eventApiKey: 'efeb4a29aba5e75d99c8a18acd620ec1', + usersApiKey: 'b4a29aba5e75duic8a18acd920ec1e2e', + }, + }, + metadata: { + jobId: 1, + }, + message: { + type: 'TRACK', + event: 'Product Viewed', + userId: '27340af5c8819', + properties: { + product_id: '622c6f5d5cf86a4c77358033', + sku: '8472-998-0112', + category: 'Games', + name: 'Cones of Dunshire', + brand: 'Wyatt Games', + variant: 'exapansion pack', + price: 49.99, + quantity: 5, + coupon: 'PREORDER15', + currency: 'USD', + position: 1, + url: 'https://www.website.com/product/path', + image_url: 'https://www.website.com/product/path.webp', + }, + }, + }, + + + ], + destType: 'bluecore', + }, + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: [ + { + // "response": { + // "status": 200, + // "body": { + // "output": [ + // { + "batchedRequest": { + "version": "1", + "type": "REST", + "method": "POST", + "endpoint": "https://api.bluecore.com/api/track/mobile/v1", + "headers": { + "Authorization": "Basic ZWZlYjRhMjlhYmE1ZTc1ZDk5YzhhMThhY2Q2MjBlYzE=", + "Content-Type": "application/json" + }, + "params": {}, + "body": { + "JSON": { + "event": "viewed_product", + "properties": { + "products": [ + { + "id": "622c6f5d5cf86a4c77358033", + "name": "Cones of Dunshire", + "price": 49.99, + "sku": "8472-998-0112", + "category": "Games", + "brand": "Wyatt Games", + "variant": "exapansion pack", + "quantity": 5, + "coupon": "PREORDER15", + "currency": "USD", + "position": 1, + "url": "https://www.website.com/product/path", + "image_url": "https://www.website.com/product/path.webp" + } + ], + "distinct_id": "xyz@example.com", + "token": "bluestore", + "client": "4.0", + "device": "mobile/iPad" + } + }, + "JSON_ARRAY": {}, + "XML": {}, + "FORM": {} + }, + "files": {} + }, + "metadata": [ + { + "jobId": 1 + } + ], + "batched": false, + "statusCode": 200, + // }, + // ], + // }, + // "status": 200, + // }, + "destination": { + "Config": { + "eventApiKey": "efeb4a29aba5e75d99c8a18acd620ec1", + "usersApiKey": "b4a29aba5e75duic8a18acd920ec1e2e", + } + } + } + ] + } + } + }, + // ], + }, + // }, + // }, + // }, + // { + // name: 'bluecore', + // description: 'Transform Rudderstack to Bluecore event', + // feature: 'router', + // module: 'destination', + // version: 'v1', + // input: { + // request: { + // body: { + // input: [ + // { + // destination: { + // Config: { + // eventApiKey: 'efeb4a29aba5e75d99c8a18acd620ec1', + // usersApiKey: 'b4a29aba5e75duic8a18acd920ec1e2e', + // }, + // }, + // metadata: { + // jobId: 2, + // }, + // message: { + // type: 'IDENTIFY', + // event: 'identify', + // userId: '27340af5c8819', + // properties: { + // name: 'Richard Hendricks', + // email: 'rhedricks@example.com', + // logins: 2, + // }, + // }, + // }, + // ], + // destType: 'bluecore', + // }, + // method: 'POST', + // }, + // }, + // output: { + // response: { + // status: 200, + // body: { + // output: [ + // { + // response: { + // status: 200, + // body: { + // output: [ + // { + // batchedRequest: { + // version: '1', + // type: 'REST', + // method: 'POST', + // endpoint: 'https://api.bluecore.com/api/track/mobile/v1', + // headers: { + // Authorization: + // 'Basic ZWZlYjRhMjlhYmE1ZTc1ZDk5YzhhMThhY2Q2MjBlYzE=', + // 'Content-Type': 'application/json', + // }, + // params: {}, + // body: { + // JSON: { + // event: 'identify', + // properties: { + // distinct_id: '27340af5c8819', + // token: 'bluestore', + // client: '4.0', + // device: 'mobile/iPad', + // customer: { + // email: 'rhedricks@example.com', + // }, + // }, + // }, + // JSON_ARRAY: {}, + // XML: {}, + // FORM: {}, + // }, + // files: {}, + // }, + // metadata: [ + // { + // jobId: 2, + // }, + // ], + // batched: false, + // statusCode: 200, + // destination: { + // Config: { + // eventApiKey: 'efeb4a29aba5e75d99c8a18acd620ec1', + // usersApiKey: 'b4a29aba5e75duic8a18acd920ec1e2e', + // }, + // }, + // }, + // ], + // }, + // }, + // }, + // ], + // }, + // }, + // }, + // }, +];