diff --git a/CHANGELOG.md b/CHANGELOG.md index 5659f1fd9a2..9305e68efa0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,19 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [1.75.0](https://github.com/rudderlabs/rudder-transformer/compare/v1.74.1...v1.75.0) (2024-08-12) + + +### Features + +* move hubspot to transformer proxy to enable partial batch handling ([#3308](https://github.com/rudderlabs/rudder-transformer/issues/3308)) ([8450021](https://github.com/rudderlabs/rudder-transformer/commit/8450021672c51ac798ec0aeab422f5fceea5e53e)) + + +### Bug Fixes + +* handle attentive tag null, undefined properties ([#3647](https://github.com/rudderlabs/rudder-transformer/issues/3647)) ([9327925](https://github.com/rudderlabs/rudder-transformer/commit/932792561c98833baf9881a83ee36ae5000e37b4)) +* handle null values for braze dedupe ([#3638](https://github.com/rudderlabs/rudder-transformer/issues/3638)) ([0a9b681](https://github.com/rudderlabs/rudder-transformer/commit/0a9b68118241158623d45ee28896377296bafd91)) + ### [1.74.1](https://github.com/rudderlabs/rudder-transformer/compare/v1.74.0...v1.74.1) (2024-08-08) diff --git a/package-lock.json b/package-lock.json index b5db5aa72e4..e765269ec70 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "rudder-transformer", - "version": "1.74.1", + "version": "1.75.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "rudder-transformer", - "version": "1.74.1", + "version": "1.75.0", "license": "ISC", "dependencies": { "@amplitude/ua-parser-js": "0.7.24", diff --git a/package.json b/package.json index dce50ee36de..2dbaeda368b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rudder-transformer", - "version": "1.74.1", + "version": "1.75.0", "description": "", "homepage": "https://github.com/rudderlabs/rudder-transformer#readme", "bugs": { diff --git a/src/v0/destinations/attentive_tag/util.js b/src/v0/destinations/attentive_tag/util.js index c96d03028f2..abecf765422 100644 --- a/src/v0/destinations/attentive_tag/util.js +++ b/src/v0/destinations/attentive_tag/util.js @@ -19,11 +19,13 @@ const { mappingConfig, ConfigCategory } = require('./config'); */ const getPropertiesKeyValidation = (payload) => { const validationArray = [`'`, `"`, `{`, `}`, `[`, `]`, ',', `,`]; - const keys = Object.keys(payload.properties); - for (const key of keys) { - for (const validationChar of validationArray) { - if (key.includes(validationChar)) { - return false; + if (payload.properties) { + const keys = Object.keys(payload.properties); + for (const key of keys) { + for (const validationChar of validationArray) { + if (key.includes(validationChar)) { + return false; + } } } } diff --git a/src/v0/destinations/braze/braze.util.test.js b/src/v0/destinations/braze/braze.util.test.js index f2726c32839..8199aae70b2 100644 --- a/src/v0/destinations/braze/braze.util.test.js +++ b/src/v0/destinations/braze/braze.util.test.js @@ -785,6 +785,136 @@ describe('dedup utility tests', () => { const result = BrazeDedupUtility.deduplicate(userData, store); expect(result).toBeNull(); }); + + test('deduplicates user data correctly when user data is null and it doesnt exist in stored data', () => { + const userData = { + external_id: '123', + nullProperty: null, + color: 'green', + age: 30, + }; + const storeData = { + external_id: '123', + custom_attributes: { + color: 'green', + age: 30, + }, + }; + store.set('123', storeData); + const result = BrazeDedupUtility.deduplicate(userData, store); + expect(store.size).toBe(1); + expect(result).toEqual(null); + }); + + test('deduplicates user data correctly when user data is null and it is same in stored data', () => { + const userData = { + external_id: '123', + nullProperty: null, + color: 'green', + age: 30, + }; + const storeData = { + external_id: '123', + custom_attributes: { + color: 'green', + age: 30, + nullProperty: null, + }, + }; + store.set('123', storeData); + const result = BrazeDedupUtility.deduplicate(userData, store); + expect(store.size).toBe(1); + expect(result).toEqual(null); + }); + + test('deduplicates user data correctly when user data is null and it is different in stored data', () => { + const userData = { + external_id: '123', + nullProperty: null, + color: 'green', + age: 30, + }; + const storeData = { + external_id: '123', + custom_attributes: { + color: 'green', + age: 30, + nullProperty: 'valid data', + }, + }; + store.set('123', storeData); + const result = BrazeDedupUtility.deduplicate(userData, store); + expect(store.size).toBe(1); + expect(result).toEqual({ + external_id: '123', + nullProperty: null, + }); + }); + + test('deduplicates user data correctly when user data is undefined and it doesnt exist in stored data', () => { + const userData = { + external_id: '123', + undefinedProperty: undefined, + color: 'green', + age: 30, + }; + const storeData = { + external_id: '123', + custom_attributes: { + color: 'green', + age: 30, + }, + }; + store.set('123', storeData); + const result = BrazeDedupUtility.deduplicate(userData, store); + expect(store.size).toBe(1); + expect(result).toEqual(null); + }); + + test('deduplicates user data correctly when user data is undefined and it is same in stored data', () => { + const userData = { + external_id: '123', + undefinedProperty: undefined, + color: 'green', + age: 30, + }; + const storeData = { + external_id: '123', + custom_attributes: { + color: 'green', + undefinedProperty: undefined, + age: 30, + }, + }; + store.set('123', storeData); + const result = BrazeDedupUtility.deduplicate(userData, store); + expect(store.size).toBe(1); + expect(result).toEqual(null); + }); + + test('deduplicates user data correctly when user data is undefined and it is defined in stored data', () => { + const userData = { + external_id: '123', + undefinedProperty: undefined, + color: 'green', + age: 30, + }; + const storeData = { + external_id: '123', + custom_attributes: { + color: 'green', + undefinedProperty: 'defined data', + age: 30, + }, + }; + store.set('123', storeData); + const result = BrazeDedupUtility.deduplicate(userData, store); + expect(store.size).toBe(1); + expect(result).toEqual({ + external_id: '123', + undefinedProperty: undefined, + }); + }); }); }); diff --git a/src/v0/destinations/braze/util.js b/src/v0/destinations/braze/util.js index 00ef308fe9c..7f4afaf6c1f 100644 --- a/src/v0/destinations/braze/util.js +++ b/src/v0/destinations/braze/util.js @@ -288,7 +288,14 @@ const BrazeDedupUtility = { if (keys.length > 0) { keys.forEach((key) => { - if (!_.isEqual(userData[key], storedUserData[key])) { + // ref: https://www.braze.com/docs/user_guide/data_and_analytics/custom_data/custom_attributes/#adding-descriptions + // null is a valid value in braze for unsetting, so we need to compare the values only if the key is present in the stored user data + // in case of keys having null values only compare if the key is present in the stored user data + if (userData[key] === null) { + if (isDefinedAndNotNull(storedUserData[key])) { + deduplicatedUserData[key] = userData[key]; + } + } else if (!_.isEqual(userData[key], storedUserData[key])) { deduplicatedUserData[key] = userData[key]; } }); diff --git a/src/v0/destinations/hs/transform.js b/src/v0/destinations/hs/transform.js index 6cf69e3c3b5..1d1a81b6b02 100644 --- a/src/v0/destinations/hs/transform.js +++ b/src/v0/destinations/hs/transform.js @@ -19,6 +19,7 @@ const { fetchFinalSetOfTraits, getProperties, validateDestinationConfig, + convertToResponseFormat, } = require('./util'); const processSingleMessage = async ({ message, destination, metadata }, propertyMap) => { @@ -147,20 +148,38 @@ const processBatchRouter = async (inputs, reqMetadata) => { }), ); - if (successRespList.length > 0) { + const dontBatchTrueResponses = []; + const dontBatchFalseOrUndefinedResponses = []; + // segregating successRepList depending on dontbatch value + successRespList.forEach((successResp) => { + if (successResp.metadata?.dontBatch) { + dontBatchTrueResponses.push(successResp); + } else { + dontBatchFalseOrUndefinedResponses.push(successResp); + } + }); + + // batch implementation + if (dontBatchFalseOrUndefinedResponses.length > 0) { if (destination.Config.apiVersion === API_VERSION.v3) { - batchedResponseList = batchEvents(successRespList); + batchedResponseList = batchEvents(dontBatchFalseOrUndefinedResponses); } else { - batchedResponseList = legacyBatchEvents(successRespList); + batchedResponseList = legacyBatchEvents(dontBatchFalseOrUndefinedResponses); } } - return { batchedResponseList, errorRespList }; + return { + batchedResponseList, + errorRespList, + // if there are any events where dontbatch set to true we need to update them according to the response format + dontBatchEvents: convertToResponseFormat(dontBatchTrueResponses), + }; }; // we are batching by default at routerTransform const processRouterDest = async (inputs, reqMetadata) => { const tempNewInputs = batchEventsInOrder(inputs); const batchedResponseList = []; const errorRespList = []; + const dontBatchEvents = []; const promises = tempNewInputs.map(async (inputEvents) => { const response = await processBatchRouter(inputEvents, reqMetadata); return response; @@ -171,8 +190,10 @@ const processRouterDest = async (inputs, reqMetadata) => { results.forEach((response) => { errorRespList.push(...response.errorRespList); batchedResponseList.push(...response.batchedResponseList); + dontBatchEvents.push(...response.dontBatchEvents); }); - return [...batchedResponseList, ...errorRespList]; + console.log(JSON.stringify([...batchedResponseList, ...errorRespList, ...dontBatchEvents])); + return [...batchedResponseList, ...errorRespList, ...dontBatchEvents]; }; module.exports = { process, processRouterDest }; diff --git a/src/v0/destinations/hs/util.js b/src/v0/destinations/hs/util.js index 38b2e636b90..fc22a89d69b 100644 --- a/src/v0/destinations/hs/util.js +++ b/src/v0/destinations/hs/util.js @@ -22,6 +22,9 @@ const { getValueFromMessage, isNull, validateEventName, + defaultBatchRequestConfig, + defaultPostRequestConfig, + getSuccessRespEvents, } = require('../../util'); const { CONTACT_PROPERTY_MAP_ENDPOINT, @@ -844,6 +847,34 @@ const addExternalIdToHSTraits = (message) => { set(getFieldValueFromMessage(message, 'traits'), externalIdObj.identifierType, externalIdObj.id); }; +const convertToResponseFormat = (successRespListWithDontBatchTrue) => { + const response = []; + if (Array.isArray(successRespListWithDontBatchTrue)) { + successRespListWithDontBatchTrue.forEach((event) => { + const { message, metadata, destination } = event; + const endpoint = get(message, 'endpoint'); + + const batchedResponse = defaultBatchRequestConfig(); + batchedResponse.batchedRequest.headers = message.headers; + batchedResponse.batchedRequest.endpoint = endpoint; + batchedResponse.batchedRequest.body = message.body; + batchedResponse.batchedRequest.params = message.params; + batchedResponse.batchedRequest.method = defaultPostRequestConfig.requestMethod; + batchedResponse.metadata = [metadata]; + batchedResponse.destination = destination; + + response.push( + getSuccessRespEvents( + batchedResponse.batchedRequest, + batchedResponse.metadata, + batchedResponse.destination, + ), + ); + }); + } + return response; +}; + module.exports = { validateDestinationConfig, addExternalIdToHSTraits, @@ -863,4 +894,5 @@ module.exports = { getObjectAndIdentifierType, extractIDsForSearchAPI, getRequestData, + convertToResponseFormat, }; diff --git a/src/v1/destinations/hs/networkHandler.ts b/src/v1/destinations/hs/networkHandler.ts new file mode 100644 index 00000000000..8293a7240c1 --- /dev/null +++ b/src/v1/destinations/hs/networkHandler.ts @@ -0,0 +1,147 @@ +import { TransformerProxyError } from '../../../v0/util/errorTypes'; +import { prepareProxyRequest, proxyRequest } from '../../../adapters/network'; +import { isHttpStatusSuccess, getAuthErrCategoryFromStCode } from '../../../v0/util/index'; +import { DeliveryV1Response, DeliveryJobState } from '../../../types/index'; + +import { processAxiosResponse, getDynamicErrorType } from '../../../adapters/utils/networkUtils'; + +const tags = require('../../../v0/util/tags'); + +/** + * + * @param results + * @param rudderJobMetadata + * @param destinationConfig + * @returns boolean + */ + +const findFeatureandVersion = (response, rudderJobMetadata, destinationConfig) => { + const { results, errors } = response; + if (Array.isArray(rudderJobMetadata) && rudderJobMetadata.length === 1) { + return 'singleEvent'; + } + if (destinationConfig?.apiVersion === 'legacyApi') { + return 'legacyApiWithMultipleEvents'; + } + if (destinationConfig?.apiVersion === 'newApi') { + if (Array.isArray(results) && results.length === rudderJobMetadata.length) + return 'newApiWithMultipleEvents'; + + if ( + Array.isArray(results) && + results.length !== rudderJobMetadata.length && + results.length + errors.length === rudderJobMetadata.length + ) + return 'newApiWithMultipleEventsAndErrors'; + } + return 'unableToFindVersionWithMultipleEvents'; +}; + +const populateResponseWithDontBatch = (rudderJobMetadata, response) => { + const errorMessage = JSON.stringify(response); + const responseWithIndividualEvents: DeliveryJobState[] = []; + + rudderJobMetadata.forEach((metadata) => { + responseWithIndividualEvents.push({ + statusCode: 500, + metadata: { ...metadata, dontBatch: true }, + error: errorMessage, + }); + }); + return responseWithIndividualEvents; +}; + +type Response = { + status?: string; + results?: Array; + errors?: Array; + startedAt?: Date; + completedAt?: Date; + message?: string; + correlationId?: string; + failureMessages?: Array; +}; + +const responseHandler = (responseParams) => { + const { destinationResponse, rudderJobMetadata, destinationRequest } = responseParams; + const successMessage = `[HUBSPOT Response V1 Handler] - Request Processed Successfully`; + const failureMessage = + 'HUBSPOT: Error in transformer proxy v1 during HUBSPOT response transformation'; + const responseWithIndividualEvents: DeliveryJobState[] = []; + const { response, status } = destinationResponse; + + if (isHttpStatusSuccess(status)) { + // populate different response for each event + const destResponse = response as Response; + let proxyOutputObj: DeliveryJobState; + const featureAndVersion = findFeatureandVersion( + destResponse, + rudderJobMetadata, + destinationRequest?.destinationConfig, + ); + switch (featureAndVersion) { + case 'singleEvent': + proxyOutputObj = { + statusCode: status, + metadata: rudderJobMetadata[0], + error: JSON.stringify(destResponse), + }; + responseWithIndividualEvents.push(proxyOutputObj); + break; + case 'newApiWithMultipleEvents': + rudderJobMetadata.forEach((metadata: any, index: string | number) => { + proxyOutputObj = { + statusCode: 200, + metadata, + error: JSON.stringify(destResponse.results?.[index]), + }; + responseWithIndividualEvents.push(proxyOutputObj); + }); + break; + default: + rudderJobMetadata.forEach((metadata) => { + proxyOutputObj = { + statusCode: 200, + metadata, + error: 'success', + }; + responseWithIndividualEvents.push(proxyOutputObj); + }); + break; + } + return { + status, + message: successMessage, + response: responseWithIndividualEvents, + } as DeliveryV1Response; + } + + // At least one event in the batch is invalid. + if (status === 400 && Array.isArray(rudderJobMetadata) && rudderJobMetadata.length > 1) { + // sending back 500 for retry only when events came in a batch + return { + status: 500, + message: failureMessage, + response: populateResponseWithDontBatch(rudderJobMetadata, response), + } as DeliveryV1Response; + } + throw new TransformerProxyError( + failureMessage, + status, + { + [tags.TAG_NAMES.ERROR_TYPE]: getDynamicErrorType(status), + }, + destinationResponse, + getAuthErrCategoryFromStCode(status), + response, + ); +}; + +function networkHandler(this: any) { + this.prepareProxy = prepareProxyRequest; + this.proxy = proxyRequest; + this.processAxiosResponse = processAxiosResponse; + this.responseHandler = responseHandler; +} + +module.exports = { networkHandler }; diff --git a/test/integrations/destinations/attentive_tag/processor/data.ts b/test/integrations/destinations/attentive_tag/processor/data.ts index 12e0f4bea17..2e602610e08 100644 --- a/test/integrations/destinations/attentive_tag/processor/data.ts +++ b/test/integrations/destinations/attentive_tag/processor/data.ts @@ -1678,4 +1678,95 @@ export const data = [ }, }, }, + { + name: 'attentive_tag', + description: 'Test 16', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + message: { + channel: 'web', + context: { + app: { + build: '1.0.0', + name: 'RudderLabs JavaScript SDK', + namespace: 'com.rudderlabs.javascript', + version: '1.0.0', + }, + traits: {}, + 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: { + id: '72e528f869711c3d', + manufacturer: 'Google', + model: 'sdk_gphone_x86', + name: 'generic_x86_arm', + token: 'some_device_token', + type: 'android', + }, + screen: { + density: 2, + }, + }, + type: 'track', + event: 'Application Backgrounded', + anonymousId: '00000000000000000000000000', + userId: '123456', + integrations: { + All: true, + }, + }, + destination: { + Config: { + apiKey: 'dummyApiKey', + signUpSourceId: '240654', + }, + }, + }, + ], + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + version: '1', + type: 'REST', + method: 'POST', + userId: '', + endpoint: 'https://api.attentivemobile.com/v1/events/custom', + headers: { + Authorization: 'Bearer dummyApiKey', + 'Content-Type': 'application/json', + }, + params: {}, + body: { + JSON: { + user: {}, + type: 'Application Backgrounded', + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + statusCode: 200, + }, + ], + }, + }, + }, ].map((d) => ({ ...d, mockFns })); diff --git a/test/integrations/destinations/hs/dataDelivery/business.ts b/test/integrations/destinations/hs/dataDelivery/business.ts new file mode 100644 index 00000000000..2239abfb951 --- /dev/null +++ b/test/integrations/destinations/hs/dataDelivery/business.ts @@ -0,0 +1,593 @@ +import { generateMetadata, generateProxyV1Payload } from '../../../testUtils'; + +const commonStatTags = { + destType: 'HS', + destinationId: 'default-destinationId', + errorCategory: 'network', + errorType: 'retryable', + feature: 'dataDelivery', + implementation: 'native', + module: 'destination', + workspaceId: 'default-workspaceId', +}; +export const businessData = [ + { + name: 'hs', + description: 'successfully creating users from a batch with legacy api', + feature: 'dataDelivery', + module: 'destination', + id: 'successWithLegacyApi', + version: 'v1', + input: { + request: { + body: generateProxyV1Payload( + { + endpoint: 'https://api.hubapi.com/contacts/v1/contact/batch/', + JSON_ARRAY: { + batch: + '[{"email":"identify111051@test.com","properties":[{"property":"firstname","value":"John1051"},{"property":"lastname","value":"Sparrow1051"}]},{"email":"identify111052@test.com","properties":[{"property":"firstname","value":"John1052"},{"property":"lastname","value":"Sparrow1052"}]},{"email":"identify111053@test.com","properties":[{"property":"firstname","value":"John1053"},{"property":"lastname","value":"Sparrow1053"}]}]', + }, + headers: { + Authorization: 'Bearer validApiKey', + 'Content-Type': 'application/json', + }, + }, + [generateMetadata(1), generateMetadata(2)], + { + apiVersion: 'legacyApi', + }, + ), + }, + }, + output: { + response: { + status: 200, + body: { + output: { + message: '[HUBSPOT Response V1 Handler] - Request Processed Successfully', + response: [ + { + error: 'success', + metadata: generateMetadata(1), + statusCode: 200, + }, + { + error: 'success', + metadata: generateMetadata(2), + statusCode: 200, + }, + ], + status: 200, + }, + }, + }, + }, + }, + { + name: 'hs', + description: 'failed to create users from a batch with legacy api', + feature: 'dataDelivery', + module: 'destination', + id: 'failureWithLegacyApi', + version: 'v1', + input: { + request: { + body: generateProxyV1Payload( + { + endpoint: 'https://api.hubapi.com/contacts/v1/contact/batch/', + JSON_ARRAY: { + batch: + '[{"email":"identify111051@test.com","properties":[{"property":"firstname","value":"John1051"},{"property":"lastname","value":"Sparrow1051"}]},{"email":"identify111052@test.con","properties":[{"property":"firstname","value":"John1052"},{"property":"lastname","value":"Sparrow1052"}]},{"email":"identify111053@test.com","properties":[{"property":"firstname","value":"John1053"},{"property":"lastname","value":"Sparrow1053"}]}]', + }, + headers: { + Authorization: 'Bearer inValidApiKey', + 'Content-Type': 'application/json', + }, + }, + [generateMetadata(1), generateMetadata(2)], + { + apiVersion: 'legacyApi', + }, + ), + }, + }, + output: { + response: { + status: 200, + body: { + output: { + message: + 'HUBSPOT: Error in transformer proxy v1 during HUBSPOT response transformation', + response: [ + { + error: + '{"status":"error","message":"Errors found processing batch update","correlationId":"a716ef20-79df-44d4-98bd-9136af7bdefc","invalidEmails":["identify111052@test.con"],"failureMessages":[{"index":1,"error":{"status":"error","message":"Email address identify111052@test.con is invalid"}}]}', + metadata: { ...generateMetadata(1), dontBatch: true }, + statusCode: 500, + }, + { + error: + '{"status":"error","message":"Errors found processing batch update","correlationId":"a716ef20-79df-44d4-98bd-9136af7bdefc","invalidEmails":["identify111052@test.con"],"failureMessages":[{"index":1,"error":{"status":"error","message":"Email address identify111052@test.con is invalid"}}]}', + metadata: { ...generateMetadata(2), dontBatch: true }, + statusCode: 500, + }, + ], + status: 500, + }, + }, + }, + }, + }, + { + name: 'hs', + description: 'successfully deliver events with legacy api', + feature: 'dataDelivery', + module: 'destination', + version: 'v1', + id: 'successEventsWithLegacyApi', + input: { + request: { + body: generateProxyV1Payload( + { + headers: { + 'Content-Type': 'application/json', + }, + method: 'GET', + params: { + _a: 'dummy-hubId', + _n: 'test track event HS', + _m: 4.99, + email: 'testhubspot2@email.com', + firstname: 'Test Hubspot', + }, + endpoint: 'https://track.hubspot.com/v1/event', + }, + [generateMetadata(1)], + { + apiVersion: 'legacyApi', + }, + ), + }, + }, + output: { + response: { + status: 200, + body: { + output: { + message: '[HUBSPOT Response V1 Handler] - Request Processed Successfully', + response: [ + { + error: '{}', + metadata: generateMetadata(1), + statusCode: 200, + }, + ], + status: 200, + }, + }, + }, + }, + }, + { + name: 'hs', + description: 'successfully creating users from a batch with new api', + feature: 'dataDelivery', + module: 'destination', + version: 'v1', + id: 'successCreatingBatchOfUsersWithNewApi', + input: { + request: { + body: generateProxyV1Payload( + { + headers: { + 'Content-Type': 'application/json', + Authorization: 'Bearer validAccessToken', + }, + method: 'POST', + endpoint: 'https://api.hubapi.com/crm/v3/objects/contacts/batch/create', + JSON: { + inputs: [ + { + properties: { + email: 'testuser31848@testmail.com', + }, + }, + { + properties: { + email: 'testuser31847@testmail.com', + }, + }, + ], + }, + }, + [generateMetadata(1), generateMetadata(2)], + { + apiVersion: 'newApi', + }, + ), + }, + }, + output: { + response: { + status: 200, + body: { + output: { + message: '[HUBSPOT Response V1 Handler] - Request Processed Successfully', + response: [ + { + error: + '{"id":"44188066992","properties":{"createdate":"2024-07-31T03:21:03.176Z","email":"testuser31848@testmail.com","hs_all_contact_vids":"44188066992","hs_email_domain":"testmail.com","hs_is_contact":"true","hs_is_unworked":"true","hs_lifecyclestage_lead_date":"2024-07-31T03:21:03.176Z","hs_membership_has_accessed_private_content":"0","hs_object_id":"44188066992","hs_object_source":"INTEGRATION","hs_object_source_id":"3209723","hs_object_source_label":"INTEGRATION","hs_pipeline":"contacts-lifecycle-pipeline","hs_registered_member":"0","lastmodifieddate":"2024-07-31T03:21:03.176Z","lifecyclestage":"lead"},"createdAt":"2024-07-31T03:21:03.176Z","updatedAt":"2024-07-31T03:21:03.176Z","archived":false}', + metadata: generateMetadata(1), + statusCode: 200, + }, + { + error: + '{"id":"44188066993","properties":{"createdate":"2024-07-31T03:21:03.176Z","email":"testuser31847@testmail.com","hs_all_contact_vids":"44188066993","hs_email_domain":"testmail.com","hs_is_contact":"true","hs_is_unworked":"true","hs_lifecyclestage_lead_date":"2024-07-31T03:21:03.176Z","hs_membership_has_accessed_private_content":"0","hs_object_id":"44188066993","hs_object_source":"INTEGRATION","hs_object_source_id":"3209723","hs_object_source_label":"INTEGRATION","hs_pipeline":"contacts-lifecycle-pipeline","hs_registered_member":"0","lastmodifieddate":"2024-07-31T03:21:03.176Z","lifecyclestage":"lead"},"createdAt":"2024-07-31T03:21:03.176Z","updatedAt":"2024-07-31T03:21:03.176Z","archived":false}', + metadata: generateMetadata(2), + statusCode: 200, + }, + ], + status: 200, + }, + }, + }, + }, + }, + { + name: 'hs', + description: 'successfully updating users from a batch with new api', + feature: 'dataDelivery', + module: 'destination', + version: 'v1', + input: { + request: { + body: generateProxyV1Payload( + { + endpoint: 'https://api.hubapi.com/crm/v3/objects/contacts/batch/update', + JSON: { + inputs: [ + { + properties: { + firstname: 'testmail1217', + }, + id: '12877907024', + }, + { + properties: { + firstname: 'test1', + email: 'test1@mail.com', + }, + id: '12877907025', + }, + ], + }, + }, + [generateMetadata(1), generateMetadata(2)], + { + apiVersion: 'newApi', + }, + ), + }, + }, + output: { + response: { + status: 200, + body: { + output: { + status: 200, + message: '[HUBSPOT Response V1 Handler] - Request Processed Successfully', + response: [ + { + error: + '{"id":"12877907025","properties":{"createdate":"2024-04-16T09:50:16.034Z","email":"test1@mail.com","firstname":"test1","hs_is_unworked":"true","hs_object_id":"12877907025","hs_pipeline":"contacts-lifecycle-pipeline","lastmodifieddate":"2024-04-23T11:52:03.723Z","lifecyclestage":"lead"},"createdAt":"2024-04-16T09:50:16.034Z","updatedAt":"2024-04-23T11:52:03.723Z","archived":false}', + metadata: generateMetadata(1), + statusCode: 200, + }, + { + error: + '{"id":"12877907024","properties":{"createdate":"2024-04-16T09:50:16.034Z","firstname":"testmail1217","hs_is_unworked":"true","hs_object_id":"12877907024","hs_pipeline":"contacts-lifecycle-pipeline","lastmodifieddate":"2024-04-23T11:52:03.723Z","lifecyclestage":"lead"},"createdAt":"2024-04-16T09:50:16.034Z","updatedAt":"2024-04-23T11:52:03.723Z","archived":false}', + metadata: generateMetadata(2), + statusCode: 200, + }, + ], + }, + }, + }, + }, + }, + { + name: 'hs', + description: 'failed due to duplicate in a batch', + id: 'hs_datadelivery_01', + feature: 'dataDelivery', + module: 'destination', + version: 'v1', + input: { + request: { + body: generateProxyV1Payload( + { + endpoint: 'https://api.hubapi.com/crm/v3/objects/contacts/batch/update', + JSON: { + inputs: [ + { + properties: { + firstname: 'test5', + email: 'test1@mail.com', + }, + id: '12877907025', + }, + { + properties: { + firstname: 'testmail1217', + email: 'test1@mail.com', + }, + id: '12877907025', + }, + ], + }, + }, + [generateMetadata(1), generateMetadata(2)], + ), + }, + }, + output: { + response: { + status: 200, + body: { + output: { + message: + 'HUBSPOT: Error in transformer proxy v1 during HUBSPOT response transformation', + response: [ + { + error: + '{"status":"error","message":"Duplicate IDs found in batch input: [12877907025]. IDs must be unique","correlationId":"d24ec5cd-8998-4674-a928-59603ae6b0eb","context":{"ids":["12877907025"]},"category":"VALIDATION_ERROR"}', + metadata: { + ...generateMetadata(1), + dontBatch: true, + }, + statusCode: 500, + }, + { + error: + '{"status":"error","message":"Duplicate IDs found in batch input: [12877907025]. IDs must be unique","correlationId":"d24ec5cd-8998-4674-a928-59603ae6b0eb","context":{"ids":["12877907025"]},"category":"VALIDATION_ERROR"}', + metadata: { + ...generateMetadata(2), + dontBatch: true, + }, + statusCode: 500, + }, + ], + status: 500, + }, + }, + }, + }, + }, + { + name: 'hs', + description: 'failed due to wrong email format in a batch', + feature: 'dataDelivery', + module: 'destination', + version: 'v1', + input: { + request: { + body: generateProxyV1Payload( + { + endpoint: 'https://api.hubapi.com/crm/v3/objects/contacts/batch/update', + JSON: { + inputs: [ + [ + { + properties: { + firstname: 'test1', + email: 'test1@mail.com', + }, + }, + { + properties: { + firstname: 'testmail1217', + email: 'testmail1217@testmail.com', + }, + }, + { + properties: { + firstname: 'test5', + email: 'test5@xmail.con', + }, + }, + ], + ], + }, + }, + [generateMetadata(1), generateMetadata(2), generateMetadata(3)], + ), + }, + }, + output: { + response: { + status: 200, + body: { + output: { + message: + 'HUBSPOT: Error in transformer proxy v1 during HUBSPOT response transformation', + response: [ + { + error: + '{"status":"error","message":"Invalid input JSON on line 3, column 9: Cannot deserialize value of type `com.hubspot.inbounddb.publicobject.core.v2.SimplePublicObjectBatchInput$Json` from Array value (token `JsonToken.START_ARRAY`)","correlationId":"99df04b9-da11-4504-bd97-2c15f58d0943"}', + metadata: { + ...generateMetadata(1), + dontBatch: true, + }, + statusCode: 500, + }, + { + error: + '{"status":"error","message":"Invalid input JSON on line 3, column 9: Cannot deserialize value of type `com.hubspot.inbounddb.publicobject.core.v2.SimplePublicObjectBatchInput$Json` from Array value (token `JsonToken.START_ARRAY`)","correlationId":"99df04b9-da11-4504-bd97-2c15f58d0943"}', + metadata: { + ...generateMetadata(2), + dontBatch: true, + }, + statusCode: 500, + }, + { + error: + '{"status":"error","message":"Invalid input JSON on line 3, column 9: Cannot deserialize value of type `com.hubspot.inbounddb.publicobject.core.v2.SimplePublicObjectBatchInput$Json` from Array value (token `JsonToken.START_ARRAY`)","correlationId":"99df04b9-da11-4504-bd97-2c15f58d0943"}', + metadata: { + ...generateMetadata(3), + dontBatch: true, + }, + statusCode: 500, + }, + ], + status: 500, + }, + }, + }, + }, + }, + { + name: 'hs', + description: 'succeed to send a custom event', + feature: 'dataDelivery', + module: 'destination', + id: 'succeedEventWithNewApi', + version: 'v1', + input: { + request: { + body: generateProxyV1Payload( + { + endpoint: 'https://api.hubapi.com/events/v3/send', + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: 'Bearer dummy-access-token', + }, + JSON: { + email: 'osvaldocostaferreira98@gmail.com', + eventName: 'pe22315509_rs_hub_test', + properties: { + value: 'name1', + }, + }, + }, + [generateMetadata(1)], + ), + }, + }, + output: { + response: { + status: 200, + body: { + output: { + message: '[HUBSPOT Response V1 Handler] - Request Processed Successfully', + response: [ + { + error: '{}', + metadata: generateMetadata(1), + statusCode: 200, + }, + ], + status: 200, + }, + }, + }, + }, + }, + { + name: 'hs', + description: 'succeed to send a custom event', + feature: 'dataDelivery', + module: 'destination', + id: 'failedEventWithNewApi', + version: 'v1', + input: { + request: { + body: generateProxyV1Payload( + { + endpoint: 'https://api.hubapi.com/events/v3/send', + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: 'Bearer invalid-dummy-access-token', + }, + JSON: { + email: 'osvaldocostaferreira98@gmail.com', + eventName: 'pe22315509_rs_hub_test', + properties: { + value: 'name1', + }, + }, + }, + [generateMetadata(1)], + ), + }, + }, + output: { + response: { + status: 401, + body: { + output: { + authErrorCategory: 'REFRESH_TOKEN', + message: + 'HUBSPOT: Error in transformer proxy v1 during HUBSPOT response transformation', + response: [ + { + error: + '{"status":"error","message":"Authentication credentials not found. This API supports OAuth 2.0 authentication and you can find more details at https://developers.hubspot.com/docs/methods/auth/oauth-overview","correlationId":"501651f6-bb90-40f1-b0db-349f62916993","category":"INVALID_AUTHENTICATION"}', + metadata: generateMetadata(1), + statusCode: 401, + }, + ], + statTags: { ...commonStatTags, errorType: 'aborted' }, + status: 401, + }, + }, + }, + }, + }, + { + name: 'hs', + description: 'succeed to send an event with association', + feature: 'dataDelivery', + module: 'destination', + id: 'succeedAssociationWithNewApi', + version: 'v1', + input: { + request: { + body: generateProxyV1Payload( + { + endpoint: 'https://api.hubapi.com/crm/v3/associations/companies/contacts/batch/create', + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: 'Bearer dummy-access-token', + }, + JSON: { + inputs: [{ to: { id: 1 }, from: { id: 9405415215 }, type: 'contact_to_company' }], + }, + }, + [generateMetadata(1)], + ), + }, + }, + output: { + response: { + status: 200, + body: { + output: { + message: '[HUBSPOT Response V1 Handler] - Request Processed Successfully', + response: [ + { + error: + '{"completedAt":"2024-07-31T04:46:34.391Z","requestedAt":"2024-07-31T04:46:34.391Z","startedAt":"2024-07-31T04:46:34.391Z","results":[{"from":{"id":"9405415215"},"to":{"id":"1"},"type":"contact_to_company"}],"status":"PENDING"}', + metadata: generateMetadata(1), + statusCode: 201, + }, + ], + status: 201, + }, + }, + }, + }, + }, +]; diff --git a/test/integrations/destinations/hs/dataDelivery/data.ts b/test/integrations/destinations/hs/dataDelivery/data.ts new file mode 100644 index 00000000000..5b2060d0014 --- /dev/null +++ b/test/integrations/destinations/hs/dataDelivery/data.ts @@ -0,0 +1,4 @@ +import { businessData } from './business'; +import { otherData } from './other'; + +export const data = [...businessData, ...otherData]; diff --git a/test/integrations/destinations/hs/dataDelivery/other.ts b/test/integrations/destinations/hs/dataDelivery/other.ts new file mode 100644 index 00000000000..202b665a51e --- /dev/null +++ b/test/integrations/destinations/hs/dataDelivery/other.ts @@ -0,0 +1,245 @@ +import { generateMetadata } from '../../../testUtils'; + +const commonStatTags = { + destType: 'HS', + destinationId: 'default-destinationId', + errorCategory: 'network', + errorType: 'retryable', + feature: 'dataDelivery', + implementation: 'native', + module: 'destination', + workspaceId: 'default-workspaceId', +}; + +const commonBody = { + version: '1', + type: 'REST', + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: 'Bearer dummyAccessToken', + }, + params: {}, + files: {}, + metadata: [generateMetadata(1), generateMetadata(2)], + body: { + JSON: { + inputs: [ + { + properties: { + firstname: 'testmail1217', + }, + id: '12877907024', + }, + { + properties: { + firstname: 'test1', + email: 'test1@mail.com', + }, + id: '12877907025', + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, +}; + +export const otherData = [ + { + name: 'hs', + id: 'hs_datadelivery_other_00', + description: 'failed due to gateway timeout from hubspot', + feature: 'dataDelivery', + module: 'destination', + version: 'v1', + input: { + request: { + body: { + endpoint: 'https://random_test_url/test_for_gateway_time_out', + ...commonBody, + }, + }, + }, + output: { + response: { + status: 200, + body: { + output: { + message: + 'HUBSPOT: Error in transformer proxy v1 during HUBSPOT response transformation', + response: [ + { + error: '"Gateway Timeout"', + metadata: generateMetadata(1), + statusCode: 504, + }, + { + error: '"Gateway Timeout"', + metadata: generateMetadata(2), + statusCode: 504, + }, + ], + statTags: commonStatTags, + status: 504, + }, + }, + }, + }, + }, + { + name: 'hs', + id: 'hs_datadelivery_other_01', + description: 'failed due to internal server error from hubspot', + feature: 'dataDelivery', + module: 'destination', + version: 'v1', + input: { + request: { + body: { + endpoint: 'https://random_test_url/test_for_internal_server_error', + ...commonBody, + }, + }, + }, + output: { + response: { + status: 200, + body: { + output: { + message: + 'HUBSPOT: Error in transformer proxy v1 during HUBSPOT response transformation', + response: [ + { + error: '"Internal Server Error"', + metadata: generateMetadata(1), + statusCode: 500, + }, + { + error: '"Internal Server Error"', + metadata: generateMetadata(2), + statusCode: 500, + }, + ], + statTags: commonStatTags, + status: 500, + }, + }, + }, + }, + }, + { + name: 'hs', + id: 'hs_datadelivery_other_02', + description: 'failed due to service unavailable error from hubspot', + feature: 'dataDelivery', + module: 'destination', + version: 'v1', + input: { + request: { + body: { + endpoint: 'https://random_test_url/test_for_service_not_available', + ...commonBody, + }, + }, + }, + output: { + response: { + status: 200, + body: { + output: { + message: + 'HUBSPOT: Error in transformer proxy v1 during HUBSPOT response transformation', + response: [ + { + error: + '{"error":{"message":"Service Unavailable","description":"The server is currently unable to handle the request due to temporary overloading or maintenance of the server. Please try again later."}}', + metadata: generateMetadata(1), + statusCode: 503, + }, + { + error: + '{"error":{"message":"Service Unavailable","description":"The server is currently unable to handle the request due to temporary overloading or maintenance of the server. Please try again later."}}', + metadata: generateMetadata(2), + statusCode: 503, + }, + ], + statTags: commonStatTags, + status: 503, + }, + }, + }, + }, + }, + { + name: 'hs', + id: 'hs_datadelivery_other_03', + description: 'getting success response but not in the expected format', + feature: 'dataDelivery', + module: 'destination', + version: 'v1', + input: { + request: { + body: { + endpoint: 'https://api.hubapi.com/crm/v3/objects/contacts/batch/update', + version: '1', + type: 'REST', + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: 'Bearer dummyAccessToken', + }, + params: {}, + files: {}, + metadata: [generateMetadata(1), generateMetadata(2)], + body: { + JSON: { + inputs: [ + { + properties: { + firstname: 'testmail12178', + }, + id: '12877907024', + }, + { + properties: { + firstname: 'test1', + email: 'test1@mail.com', + }, + id: '12877907025', + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + }, + }, + }, + output: { + response: { + status: 200, + body: { + output: { + message: '[HUBSPOT Response V1 Handler] - Request Processed Successfully', + response: [ + { + error: 'success', + metadata: generateMetadata(1), + statusCode: 200, + }, + { + error: 'success', + metadata: generateMetadata(2), + statusCode: 200, + }, + ], + status: 200, + }, + }, + }, + }, + }, +]; diff --git a/test/integrations/destinations/hs/network.ts b/test/integrations/destinations/hs/network.ts index 3d3b8fd83ff..9d8658ff6b0 100644 --- a/test/integrations/destinations/hs/network.ts +++ b/test/integrations/destinations/hs/network.ts @@ -692,4 +692,380 @@ export const networkCallsData = [ status: 200, }, }, + { + httpReq: { + url: 'https://api.hubapi.com/crm/v3/objects/contacts/batch/update', + method: 'POST', + data: { + inputs: [ + { + properties: { + firstname: 'testmail1217', + }, + id: '12877907024', + }, + { + properties: { + firstname: 'test1', + email: 'test1@mail.com', + }, + id: '12877907025', + }, + ], + }, + }, + httpRes: { + status: 200, + data: { + status: 'COMPLETE', + results: [ + { + id: '12877907025', + properties: { + createdate: '2024-04-16T09:50:16.034Z', + email: 'test1@mail.com', + firstname: 'test1', + hs_is_unworked: 'true', + hs_object_id: '12877907025', + hs_pipeline: 'contacts-lifecycle-pipeline', + lastmodifieddate: '2024-04-23T11:52:03.723Z', + lifecyclestage: 'lead', + }, + createdAt: '2024-04-16T09:50:16.034Z', + updatedAt: '2024-04-23T11:52:03.723Z', + archived: false, + }, + { + id: '12877907024', + properties: { + createdate: '2024-04-16T09:50:16.034Z', + firstname: 'testmail1217', + hs_is_unworked: 'true', + hs_object_id: '12877907024', + hs_pipeline: 'contacts-lifecycle-pipeline', + lastmodifieddate: '2024-04-23T11:52:03.723Z', + lifecyclestage: 'lead', + }, + createdAt: '2024-04-16T09:50:16.034Z', + updatedAt: '2024-04-23T11:52:03.723Z', + archived: false, + }, + ], + startedAt: '2024-04-24T05:11:51.090Z', + completedAt: '2024-04-24T05:11:51.190Z', + }, + }, + }, + { + httpReq: { + url: 'https://api.hubapi.com/crm/v3/objects/contacts/batch/update', + method: 'POST', + data: { + inputs: [ + { + properties: { + firstname: 'test5', + email: 'test1@mail.com', + }, + id: '12877907025', + }, + { + properties: { + firstname: 'testmail1217', + email: 'test1@mail.com', + }, + id: '12877907025', + }, + ], + }, + }, + httpRes: { + status: 400, + data: { + status: 'error', + message: 'Duplicate IDs found in batch input: [12877907025]. IDs must be unique', + correlationId: 'd24ec5cd-8998-4674-a928-59603ae6b0eb', + context: { + ids: ['12877907025'], + }, + category: 'VALIDATION_ERROR', + }, + }, + }, + { + httpReq: { + url: 'https://api.hubapi.com/crm/v3/objects/contacts/batch/update', + method: 'POST', + data: { + inputs: [ + [ + { + properties: { + firstname: 'test1', + email: 'test1@mail.com', + }, + }, + { + properties: { + firstname: 'testmail1217', + email: 'testmail1217@testmail.com', + }, + }, + { + properties: { + firstname: 'test5', + email: 'test5@xmail.con', + }, + }, + ], + ], + }, + }, + httpRes: { + status: 400, + data: { + status: 'error', + message: + 'Invalid input JSON on line 3, column 9: Cannot deserialize value of type `com.hubspot.inbounddb.publicobject.core.v2.SimplePublicObjectBatchInput$Json` from Array value (token `JsonToken.START_ARRAY`)', + correlationId: '99df04b9-da11-4504-bd97-2c15f58d0943', + }, + }, + }, + { + httpReq: { + url: 'https://api.hubapi.com/crm/v3/objects/contacts/batch/update', + method: 'POST', + data: { + inputs: [ + { + properties: { + firstname: 'testmail12178', + }, + id: '12877907024', + }, + { + properties: { + firstname: 'test1', + email: 'test1@mail.com', + }, + id: '12877907025', + }, + ], + }, + }, + httpRes: { + status: 200, + data: { + message: 'unknown response', + }, + }, + }, + { + httpReq: { + url: 'https://api.hubapi.com/crm/v3/objects/contacts/search', + method: 'POST', + headers: { + Authorization: 'Bearer dontbatchtrueaccesstoken', + }, + }, + httpRes: { + data: { + total: 0, + results: [], + }, + status: 200, + }, + }, + { + httpReq: { + url: 'https://api.hubapi.com/contacts/v1/contact/batch/', + method: 'POST', + headers: { + 'User-Agent': 'RudderLabs', + 'Content-Type': 'application/json', + Authorization: 'Bearer validApiKey', + }, + }, + httpRes: { + status: 200, + }, + }, + { + httpReq: { + url: 'https://api.hubapi.com/contacts/v1/contact/batch/', + method: 'POST', + headers: { + 'User-Agent': 'RudderLabs', + 'Content-Type': 'application/json', + Authorization: 'Bearer inValidApiKey', + }, + }, + httpRes: { + status: 400, + data: { + status: 'error', + message: 'Errors found processing batch update', + correlationId: 'a716ef20-79df-44d4-98bd-9136af7bdefc', + invalidEmails: ['identify111052@test.con'], + failureMessages: [ + { + index: 1, + error: { + status: 'error', + message: 'Email address identify111052@test.con is invalid', + }, + }, + ], + }, + }, + }, + { + httpReq: { + url: 'https://track.hubspot.com/v1/event', + method: 'GET', + params: { + _a: 'dummy-hubId', + _n: 'test track event HS', + _m: 4.99, + email: 'testhubspot2@email.com', + firstname: 'Test Hubspot', + }, + }, + httpRes: { + status: 200, + data: {}, + }, + }, + { + httpReq: { + url: 'https://api.hubapi.com/crm/v3/objects/contacts/batch/create', + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: 'Bearer validAccessToken', + }, + }, + httpRes: { + status: 200, + data: { + status: 'COMPLETE', + results: [ + { + id: '44188066992', + properties: { + createdate: '2024-07-31T03:21:03.176Z', + email: 'testuser31848@testmail.com', + hs_all_contact_vids: '44188066992', + hs_email_domain: 'testmail.com', + hs_is_contact: 'true', + hs_is_unworked: 'true', + hs_lifecyclestage_lead_date: '2024-07-31T03:21:03.176Z', + hs_membership_has_accessed_private_content: '0', + hs_object_id: '44188066992', + hs_object_source: 'INTEGRATION', + hs_object_source_id: '3209723', + hs_object_source_label: 'INTEGRATION', + hs_pipeline: 'contacts-lifecycle-pipeline', + hs_registered_member: '0', + lastmodifieddate: '2024-07-31T03:21:03.176Z', + lifecyclestage: 'lead', + }, + createdAt: '2024-07-31T03:21:03.176Z', + updatedAt: '2024-07-31T03:21:03.176Z', + archived: false, + }, + { + id: '44188066993', + properties: { + createdate: '2024-07-31T03:21:03.176Z', + email: 'testuser31847@testmail.com', + hs_all_contact_vids: '44188066993', + hs_email_domain: 'testmail.com', + hs_is_contact: 'true', + hs_is_unworked: 'true', + hs_lifecyclestage_lead_date: '2024-07-31T03:21:03.176Z', + hs_membership_has_accessed_private_content: '0', + hs_object_id: '44188066993', + hs_object_source: 'INTEGRATION', + hs_object_source_id: '3209723', + hs_object_source_label: 'INTEGRATION', + hs_pipeline: 'contacts-lifecycle-pipeline', + hs_registered_member: '0', + lastmodifieddate: '2024-07-31T03:21:03.176Z', + lifecyclestage: 'lead', + }, + createdAt: '2024-07-31T03:21:03.176Z', + updatedAt: '2024-07-31T03:21:03.176Z', + archived: false, + }, + ], + startedAt: '2024-07-31T03:21:03.133Z', + completedAt: '2024-07-31T03:21:03.412Z', + }, + }, + }, + { + httpReq: { + url: 'https://api.hubapi.com/events/v3/send', + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: 'Bearer dummy-access-token', + }, + }, + httpRes: { + status: 200, + data: {}, + }, + }, + { + httpReq: { + url: 'https://api.hubapi.com/events/v3/send', + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: 'Bearer invalid-dummy-access-token', + }, + }, + httpRes: { + status: 401, + data: { + status: 'error', + message: + 'Authentication credentials not found. This API supports OAuth 2.0 authentication and you can find more details at https://developers.hubspot.com/docs/methods/auth/oauth-overview', + correlationId: '501651f6-bb90-40f1-b0db-349f62916993', + category: 'INVALID_AUTHENTICATION', + }, + }, + }, + { + httpReq: { + url: 'https://api.hubapi.com/crm/v3/associations/companies/contacts/batch/create', + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: 'Bearer dummy-access-token', + }, + }, + httpRes: { + status: 201, + data: { + completedAt: '2024-07-31T04:46:34.391Z', + requestedAt: '2024-07-31T04:46:34.391Z', + startedAt: '2024-07-31T04:46:34.391Z', + results: [ + { + from: { + id: '9405415215', + }, + to: { + id: '1', + }, + type: 'contact_to_company', + }, + ], + status: 'PENDING', + }, + }, + }, ]; diff --git a/test/integrations/destinations/hs/router/data.ts b/test/integrations/destinations/hs/router/data.ts index e12efef4d01..989a581e553 100644 --- a/test/integrations/destinations/hs/router/data.ts +++ b/test/integrations/destinations/hs/router/data.ts @@ -1913,6 +1913,937 @@ export const data = [ }, }, }, + { + name: 'hs', + description: 'if dontBatch is true we are not going to create a batch out of those events', + feature: 'router', + module: 'destination', + version: 'v0', + scenario: 'buisness', + id: 'dontbatchtrue', + successCriteria: + 'should not create a batch with the events if that events contains dontBatch true', + input: { + request: { + body: { + input: [ + { + message: { + type: 'identify', + sentAt: '2024-05-23T16:49:57.461+05:30', + userId: 'sample_user_id425', + channel: 'mobile', + context: { + traits: { + age: '30', + name: 'John Sparrow', + email: 'identify425@test.com', + phone: '9112340425', + lastname: 'Sparrow', + firstname: 'John', + }, + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)', + }, + timestamp: '2024-05-23T16:49:57.070+05:30', + receivedAt: '2024-05-23T16:49:57.071+05:30', + anonymousId: '8d872292709c6fbe', + }, + metadata: { + jobId: 1, + sourceId: '2RnN36pc7p5lzoApxZnDfRnYFx0', + destinationId: '2RnSBhn4zPTOF8NdqAIrnVPPnfr', + transformAt: 'router', + workspaceId: '2QapBTEvZYwuf6O9KB5AEvvBt8j', + dontBatch: true, + }, + destination: { + ID: '2RnSBhn4zPTOF8NdqAIrnVPPnfr', + Name: 'hs-1', + Config: { + accessToken: 'dontbatchtrueaccesstoken', + apiKey: '', + apiVersion: 'newApi', + authorizationType: 'newPrivateAppApi', + blacklistedEvents: [], + connectionMode: 'cloud', + doAssociation: false, + eventDelivery: false, + eventDeliveryTS: 1687884567403, + eventFilteringOption: 'disable', + hubID: '25092171', + hubspotEvents: [ + { + eventProperties: [ + { + from: 'first_name', + to: 'first_name', + }, + { + from: 'last_name', + to: 'last_name', + }, + ], + hubspotEventName: 'pedummy-hubId_rs_hub_chair', + rsEventName: 'Order Complete', + }, + ], + ketchConsentPurposes: [ + { + purpose: '', + }, + ], + lookupField: 'email', + oneTrustCookieCategories: [], + useNativeSDK: false, + whitelistedEvents: [], + }, + Enabled: true, + WorkspaceID: '2QapBTEvZYwuf6O9KB5AEvvBt8j', + Transformations: [], + IsProcessorEnabled: true, + RevisionID: '2gqf7Mc7WEwqQtQy3G105O22s3D', + }, + request: { + query: {}, + }, + }, + { + message: { + type: 'identify', + sentAt: '2024-05-23T16:49:57.461+05:30', + userId: 'sample_user_id738', + channel: 'mobile', + context: { + traits: { + age: '30', + name: 'John Sparrow738', + email: 'identify425@test.con', + phone: '9112340738', + lastname: 'Sparrow738', + firstname: 'John', + }, + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)', + }, + timestamp: '2024-05-23T16:49:57.071+05:30', + anonymousId: '8d872292709c6fbe738', + }, + metadata: { + userId: '<<>>8d872292709c6fbe738<<>>sample_user_id738', + jobId: 2, + sourceId: '2RnN36pc7p5lzoApxZnDfRnYFx0', + destinationId: '2RnSBhn4zPTOF8NdqAIrnVPPnfr', + transformAt: 'router', + workspaceId: '2QapBTEvZYwuf6O9KB5AEvvBt8j', + workerAssignedTime: '2024-05-23T16:49:58.569269+05:30', + dontBatch: true, + }, + destination: { + ID: '2RnSBhn4zPTOF8NdqAIrnVPPnfr', + Name: 'hs-1', + Config: { + accessToken: 'dontbatchtrueaccesstoken', + apiKey: '', + apiVersion: 'newApi', + authorizationType: 'newPrivateAppApi', + blacklistedEvents: [], + connectionMode: 'cloud', + doAssociation: false, + eventDelivery: false, + eventDeliveryTS: 1687884567403, + eventFilteringOption: 'disable', + hubID: '25092171', + hubspotEvents: [ + { + eventProperties: [ + { + from: 'first_name', + to: 'first_name', + }, + { + from: 'last_name', + to: 'last_name', + }, + ], + hubspotEventName: 'pedummy-hubId_rs_hub_chair', + rsEventName: 'Order Complete', + }, + ], + ketchConsentPurposes: [ + { + purpose: '', + }, + ], + lookupField: 'email', + oneTrustCookieCategories: [], + useNativeSDK: false, + whitelistedEvents: [], + }, + Enabled: true, + WorkspaceID: '2QapBTEvZYwuf6O9KB5AEvvBt8j', + Transformations: [], + IsProcessorEnabled: true, + RevisionID: '2gqf7Mc7WEwqQtQy3G105O22s3D', + }, + request: { + query: {}, + }, + }, + { + message: { + type: 'identify', + sentAt: '2024-05-23T16:49:57.462+05:30', + userId: 'sample_user_id803', + channel: 'mobile', + context: { + traits: { + age: '30', + name: 'John Sparrow803', + email: 'identify803@test.com', + phone: '9112340803', + lastname: 'Sparrow803', + firstname: 'John', + }, + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)', + }, + anonymousId: '8d872292709c6fbe803', + originalTimestamp: '2024-05-23T16:49:57.462+05:30', + }, + metadata: { + userId: '<<>>8d872292709c6fbe803<<>>sample_user_id803', + jobId: 3, + sourceId: '2RnN36pc7p5lzoApxZnDfRnYFx0', + destinationId: '2RnSBhn4zPTOF8NdqAIrnVPPnfr', + transformAt: 'router', + workspaceId: '2QapBTEvZYwuf6O9KB5AEvvBt8j', + }, + destination: { + ID: '2RnSBhn4zPTOF8NdqAIrnVPPnfr', + Name: 'hs-1', + Config: { + accessToken: 'dontbatchtrueaccesstoken', + apiKey: '', + apiVersion: 'newApi', + authorizationType: 'newPrivateAppApi', + blacklistedEvents: [], + connectionMode: 'cloud', + doAssociation: false, + eventDelivery: false, + eventDeliveryTS: 1687884567403, + eventFilteringOption: 'disable', + hubID: '25092171', + hubspotEvents: [ + { + eventProperties: [ + { + from: 'first_name', + to: 'first_name', + }, + { + from: 'last_name', + to: 'last_name', + }, + ], + hubspotEventName: 'pedummy-hubId_rs_hub_chair', + rsEventName: 'Order Complete', + }, + ], + ketchConsentPurposes: [ + { + purpose: '', + }, + ], + lookupField: 'email', + oneTrustCookieCategories: [], + useNativeSDK: false, + whitelistedEvents: [], + }, + Enabled: true, + WorkspaceID: '2QapBTEvZYwuf6O9KB5AEvvBt8j', + Transformations: [], + IsProcessorEnabled: true, + RevisionID: '2gqf7Mc7WEwqQtQy3G105O22s3D', + }, + request: { + query: {}, + }, + }, + { + message: { + type: 'identify', + sentAt: '2024-05-23T16:49:57.462+05:30', + userId: 'sample_user_id804', + channel: 'mobile', + context: { + traits: { + age: '30', + name: 'John Sparrow804', + email: 'identify804@test.con', + phone: '9112340804', + lastname: 'Sparrow804', + firstname: 'John', + }, + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)', + }, + anonymousId: '8d872292709c6fbe804', + originalTimestamp: '2024-05-23T16:49:57.462+05:30', + }, + metadata: { + userId: '<<>>8d872292709c6fbe804<<>>sample_user_id804', + jobId: 4, + sourceId: '2RnN36pc7p5lzoApxZnDfRnYFx0', + destinationId: '2RnSBhn4zPTOF8NdqAIrnVPPnfr', + transformAt: 'router', + workspaceId: '2QapBTEvZYwuf6O9KB5AEvvBt8j', + dontBatch: false, + }, + destination: { + ID: '2RnSBhn4zPTOF8NdqAIrnVPPnfr', + Name: 'hs-1', + Config: { + accessToken: 'dontbatchtrueaccesstoken', + apiKey: '', + apiVersion: 'newApi', + authorizationType: 'newPrivateAppApi', + blacklistedEvents: [], + connectionMode: 'cloud', + doAssociation: false, + eventDelivery: false, + eventDeliveryTS: 1687884567403, + eventFilteringOption: 'disable', + hubID: '25092171', + hubspotEvents: [ + { + eventProperties: [ + { + from: 'first_name', + to: 'first_name', + }, + { + from: 'last_name', + to: 'last_name', + }, + ], + hubspotEventName: 'pedummy-hubId_rs_hub_chair', + rsEventName: 'Order Complete', + }, + ], + ketchConsentPurposes: [ + { + purpose: '', + }, + ], + lookupField: 'email', + oneTrustCookieCategories: [], + useNativeSDK: false, + whitelistedEvents: [], + }, + Enabled: true, + WorkspaceID: '2QapBTEvZYwuf6O9KB5AEvvBt8j', + Transformations: [], + IsProcessorEnabled: true, + RevisionID: '2gqf7Mc7WEwqQtQy3G105O22s3D', + }, + request: { + query: {}, + }, + }, + ], + destType: 'hs', + }, + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: [ + { + batched: true, + batchedRequest: { + body: { + FORM: {}, + JSON: { + inputs: [ + { + properties: { + email: 'identify803@test.com', + firstname: 'John', + lastname: 'Sparrow803', + phone: '9112340803', + }, + }, + { + properties: { + email: 'identify804@test.con', + firstname: 'John', + lastname: 'Sparrow804', + phone: '9112340804', + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + }, + endpoint: 'https://api.hubapi.com/crm/v3/objects/contacts/batch/create', + files: {}, + headers: { + Authorization: 'Bearer dontbatchtrueaccesstoken', + 'Content-Type': 'application/json', + }, + method: 'POST', + params: {}, + type: 'REST', + version: '1', + }, + destination: { + Config: { + accessToken: 'dontbatchtrueaccesstoken', + apiKey: '', + apiVersion: 'newApi', + authorizationType: 'newPrivateAppApi', + blacklistedEvents: [], + connectionMode: 'cloud', + doAssociation: false, + eventDelivery: false, + eventDeliveryTS: 1687884567403, + eventFilteringOption: 'disable', + hubID: '25092171', + hubspotEvents: [ + { + eventProperties: [ + { + from: 'first_name', + to: 'first_name', + }, + { + from: 'last_name', + to: 'last_name', + }, + ], + hubspotEventName: 'pedummy-hubId_rs_hub_chair', + rsEventName: 'Order Complete', + }, + ], + ketchConsentPurposes: [ + { + purpose: '', + }, + ], + lookupField: 'email', + oneTrustCookieCategories: [], + useNativeSDK: false, + whitelistedEvents: [], + }, + Enabled: true, + ID: '2RnSBhn4zPTOF8NdqAIrnVPPnfr', + IsProcessorEnabled: true, + Name: 'hs-1', + RevisionID: '2gqf7Mc7WEwqQtQy3G105O22s3D', + Transformations: [], + WorkspaceID: '2QapBTEvZYwuf6O9KB5AEvvBt8j', + }, + metadata: [ + { + destinationId: '2RnSBhn4zPTOF8NdqAIrnVPPnfr', + jobId: 3, + sourceId: '2RnN36pc7p5lzoApxZnDfRnYFx0', + transformAt: 'router', + userId: '<<>>8d872292709c6fbe803<<>>sample_user_id803', + workspaceId: '2QapBTEvZYwuf6O9KB5AEvvBt8j', + }, + { + destinationId: '2RnSBhn4zPTOF8NdqAIrnVPPnfr', + dontBatch: false, + jobId: 4, + sourceId: '2RnN36pc7p5lzoApxZnDfRnYFx0', + transformAt: 'router', + userId: '<<>>8d872292709c6fbe804<<>>sample_user_id804', + workspaceId: '2QapBTEvZYwuf6O9KB5AEvvBt8j', + }, + ], + statusCode: 200, + }, + { + batched: false, + batchedRequest: { + body: { + FORM: {}, + JSON: { + properties: { + email: 'identify425@test.com', + firstname: 'John', + lastname: 'Sparrow', + phone: '9112340425', + }, + }, + JSON_ARRAY: {}, + XML: {}, + }, + endpoint: 'https://api.hubapi.com/crm/v3/objects/contacts', + files: {}, + headers: { + Authorization: 'Bearer dontbatchtrueaccesstoken', + 'Content-Type': 'application/json', + }, + method: 'POST', + params: {}, + type: 'REST', + version: '1', + }, + destination: { + Config: { + accessToken: 'dontbatchtrueaccesstoken', + apiKey: '', + apiVersion: 'newApi', + authorizationType: 'newPrivateAppApi', + blacklistedEvents: [], + connectionMode: 'cloud', + doAssociation: false, + eventDelivery: false, + eventDeliveryTS: 1687884567403, + eventFilteringOption: 'disable', + hubID: '25092171', + hubspotEvents: [ + { + eventProperties: [ + { + from: 'first_name', + to: 'first_name', + }, + { + from: 'last_name', + to: 'last_name', + }, + ], + hubspotEventName: 'pedummy-hubId_rs_hub_chair', + rsEventName: 'Order Complete', + }, + ], + ketchConsentPurposes: [ + { + purpose: '', + }, + ], + lookupField: 'email', + oneTrustCookieCategories: [], + useNativeSDK: false, + whitelistedEvents: [], + }, + Enabled: true, + ID: '2RnSBhn4zPTOF8NdqAIrnVPPnfr', + IsProcessorEnabled: true, + Name: 'hs-1', + RevisionID: '2gqf7Mc7WEwqQtQy3G105O22s3D', + Transformations: [], + WorkspaceID: '2QapBTEvZYwuf6O9KB5AEvvBt8j', + }, + metadata: [ + { + destinationId: '2RnSBhn4zPTOF8NdqAIrnVPPnfr', + dontBatch: true, + jobId: 1, + sourceId: '2RnN36pc7p5lzoApxZnDfRnYFx0', + transformAt: 'router', + workspaceId: '2QapBTEvZYwuf6O9KB5AEvvBt8j', + }, + ], + statusCode: 200, + }, + { + batched: false, + batchedRequest: { + body: { + FORM: {}, + JSON: { + properties: { + email: 'identify425@test.con', + firstname: 'John', + lastname: 'Sparrow738', + phone: '9112340738', + }, + }, + JSON_ARRAY: {}, + XML: {}, + }, + endpoint: 'https://api.hubapi.com/crm/v3/objects/contacts', + files: {}, + headers: { + Authorization: 'Bearer dontbatchtrueaccesstoken', + 'Content-Type': 'application/json', + }, + method: 'POST', + params: {}, + type: 'REST', + version: '1', + }, + destination: { + Config: { + accessToken: 'dontbatchtrueaccesstoken', + apiKey: '', + apiVersion: 'newApi', + authorizationType: 'newPrivateAppApi', + blacklistedEvents: [], + connectionMode: 'cloud', + doAssociation: false, + eventDelivery: false, + eventDeliveryTS: 1687884567403, + eventFilteringOption: 'disable', + hubID: '25092171', + hubspotEvents: [ + { + eventProperties: [ + { + from: 'first_name', + to: 'first_name', + }, + { + from: 'last_name', + to: 'last_name', + }, + ], + hubspotEventName: 'pedummy-hubId_rs_hub_chair', + rsEventName: 'Order Complete', + }, + ], + ketchConsentPurposes: [ + { + purpose: '', + }, + ], + lookupField: 'email', + oneTrustCookieCategories: [], + useNativeSDK: false, + whitelistedEvents: [], + }, + Enabled: true, + ID: '2RnSBhn4zPTOF8NdqAIrnVPPnfr', + IsProcessorEnabled: true, + Name: 'hs-1', + RevisionID: '2gqf7Mc7WEwqQtQy3G105O22s3D', + Transformations: [], + WorkspaceID: '2QapBTEvZYwuf6O9KB5AEvvBt8j', + }, + metadata: [ + { + destinationId: '2RnSBhn4zPTOF8NdqAIrnVPPnfr', + dontBatch: true, + jobId: 2, + sourceId: '2RnN36pc7p5lzoApxZnDfRnYFx0', + transformAt: 'router', + userId: '<<>>8d872292709c6fbe738<<>>sample_user_id738', + workerAssignedTime: '2024-05-23T16:49:58.569269+05:30', + workspaceId: '2QapBTEvZYwuf6O9KB5AEvvBt8j', + }, + ], + statusCode: 200, + }, + ], + }, + }, + }, + }, + { + name: 'hs', + description: 'if dontBatch is not available we are considering those as dontbatch false', + feature: 'router', + module: 'destination', + version: 'v0', + scenario: 'buisness', + id: 'dontbatchundefined', + successCriteria: 'all events should be batched', + input: { + request: { + body: { + input: [ + { + message: { + type: 'identify', + sentAt: '2024-05-23T16:49:57.461+05:30', + userId: 'sample_user_id425', + channel: 'mobile', + context: { + traits: { + age: '30', + name: 'John Sparrow', + email: 'identify425@test.com', + phone: '9112340425', + lastname: 'Sparrow', + firstname: 'John', + }, + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)', + }, + timestamp: '2024-05-23T16:49:57.070+05:30', + receivedAt: '2024-05-23T16:49:57.071+05:30', + anonymousId: '8d872292709c6fbe', + }, + metadata: { + jobId: 1, + sourceId: '2RnN36pc7p5lzoApxZnDfRnYFx0', + destinationId: '2RnSBhn4zPTOF8NdqAIrnVPPnfr', + transformAt: 'router', + workspaceId: '2QapBTEvZYwuf6O9KB5AEvvBt8j', + }, + destination: { + ID: '2RnSBhn4zPTOF8NdqAIrnVPPnfr', + Name: 'hs-1', + Config: { + accessToken: 'dontbatchtrueaccesstoken', + apiKey: '', + apiVersion: 'newApi', + authorizationType: 'newPrivateAppApi', + blacklistedEvents: [], + connectionMode: 'cloud', + doAssociation: false, + eventDelivery: false, + eventDeliveryTS: 1687884567403, + eventFilteringOption: 'disable', + hubID: '25092171', + hubspotEvents: [ + { + eventProperties: [ + { + from: 'first_name', + to: 'first_name', + }, + { + from: 'last_name', + to: 'last_name', + }, + ], + hubspotEventName: 'pedummy-hubId_rs_hub_chair', + rsEventName: 'Order Complete', + }, + ], + ketchConsentPurposes: [ + { + purpose: '', + }, + ], + lookupField: 'email', + oneTrustCookieCategories: [], + useNativeSDK: false, + whitelistedEvents: [], + }, + Enabled: true, + WorkspaceID: '2QapBTEvZYwuf6O9KB5AEvvBt8j', + Transformations: [], + IsProcessorEnabled: true, + RevisionID: '2gqf7Mc7WEwqQtQy3G105O22s3D', + }, + request: { + query: {}, + }, + }, + { + message: { + type: 'identify', + sentAt: '2024-05-23T16:49:57.461+05:30', + userId: 'sample_user_id738', + channel: 'mobile', + context: { + traits: { + age: '30', + name: 'John Sparrow738', + email: 'identify425@test.con', + phone: '9112340738', + lastname: 'Sparrow738', + firstname: 'John', + }, + userAgent: + 'Dalvik/2.1.0 (Linux; U; Android 9; AOSP on IA Emulator Build/PSR1.180720.117)', + }, + timestamp: '2024-05-23T16:49:57.071+05:30', + anonymousId: '8d872292709c6fbe738', + }, + metadata: { + userId: '<<>>8d872292709c6fbe738<<>>sample_user_id738', + jobId: 2, + sourceId: '2RnN36pc7p5lzoApxZnDfRnYFx0', + destinationId: '2RnSBhn4zPTOF8NdqAIrnVPPnfr', + transformAt: 'router', + workspaceId: '2QapBTEvZYwuf6O9KB5AEvvBt8j', + workerAssignedTime: '2024-05-23T16:49:58.569269+05:30', + }, + destination: { + ID: '2RnSBhn4zPTOF8NdqAIrnVPPnfr', + Name: 'hs-1', + Config: { + accessToken: 'dontbatchtrueaccesstoken', + apiKey: '', + apiVersion: 'newApi', + authorizationType: 'newPrivateAppApi', + blacklistedEvents: [], + connectionMode: 'cloud', + doAssociation: false, + eventDelivery: false, + eventDeliveryTS: 1687884567403, + eventFilteringOption: 'disable', + hubID: '25092171', + hubspotEvents: [ + { + eventProperties: [ + { + from: 'first_name', + to: 'first_name', + }, + { + from: 'last_name', + to: 'last_name', + }, + ], + hubspotEventName: 'pedummy-hubId_rs_hub_chair', + rsEventName: 'Order Complete', + }, + ], + ketchConsentPurposes: [ + { + purpose: '', + }, + ], + lookupField: 'email', + oneTrustCookieCategories: [], + useNativeSDK: false, + whitelistedEvents: [], + }, + Enabled: true, + WorkspaceID: '2QapBTEvZYwuf6O9KB5AEvvBt8j', + Transformations: [], + IsProcessorEnabled: true, + RevisionID: '2gqf7Mc7WEwqQtQy3G105O22s3D', + }, + request: { + query: {}, + }, + }, + ], + destType: 'hs', + }, + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: { + output: [ + { + batched: true, + batchedRequest: { + body: { + FORM: {}, + JSON: { + inputs: [ + { + properties: { + email: 'identify425@test.com', + firstname: 'John', + lastname: 'Sparrow', + phone: '9112340425', + }, + }, + { + properties: { + email: 'identify425@test.con', + firstname: 'John', + lastname: 'Sparrow738', + phone: '9112340738', + }, + }, + ], + }, + JSON_ARRAY: {}, + XML: {}, + }, + endpoint: 'https://api.hubapi.com/crm/v3/objects/contacts/batch/create', + files: {}, + headers: { + Authorization: 'Bearer dontbatchtrueaccesstoken', + 'Content-Type': 'application/json', + }, + method: 'POST', + params: {}, + type: 'REST', + version: '1', + }, + destination: { + Config: { + accessToken: 'dontbatchtrueaccesstoken', + apiKey: '', + apiVersion: 'newApi', + authorizationType: 'newPrivateAppApi', + blacklistedEvents: [], + connectionMode: 'cloud', + doAssociation: false, + eventDelivery: false, + eventDeliveryTS: 1687884567403, + eventFilteringOption: 'disable', + hubID: '25092171', + hubspotEvents: [ + { + eventProperties: [ + { + from: 'first_name', + to: 'first_name', + }, + { + from: 'last_name', + to: 'last_name', + }, + ], + hubspotEventName: 'pedummy-hubId_rs_hub_chair', + rsEventName: 'Order Complete', + }, + ], + ketchConsentPurposes: [ + { + purpose: '', + }, + ], + lookupField: 'email', + oneTrustCookieCategories: [], + useNativeSDK: false, + whitelistedEvents: [], + }, + Enabled: true, + ID: '2RnSBhn4zPTOF8NdqAIrnVPPnfr', + IsProcessorEnabled: true, + Name: 'hs-1', + RevisionID: '2gqf7Mc7WEwqQtQy3G105O22s3D', + Transformations: [], + WorkspaceID: '2QapBTEvZYwuf6O9KB5AEvvBt8j', + }, + metadata: [ + { + destinationId: '2RnSBhn4zPTOF8NdqAIrnVPPnfr', + jobId: 1, + sourceId: '2RnN36pc7p5lzoApxZnDfRnYFx0', + transformAt: 'router', + workspaceId: '2QapBTEvZYwuf6O9KB5AEvvBt8j', + }, + { + destinationId: '2RnSBhn4zPTOF8NdqAIrnVPPnfr', + jobId: 2, + sourceId: '2RnN36pc7p5lzoApxZnDfRnYFx0', + transformAt: 'router', + userId: '<<>>8d872292709c6fbe738<<>>sample_user_id738', + workerAssignedTime: '2024-05-23T16:49:58.569269+05:30', + workspaceId: '2QapBTEvZYwuf6O9KB5AEvvBt8j', + }, + ], + statusCode: 200, + }, + ], + }, + }, + }, + }, { name: 'hs', description: 'router job ordering ',