diff --git a/src/cdk/v2/destinations/intercom/utils.js b/src/cdk/v2/destinations/intercom/utils.js index ae1a258b45..a66872761a 100644 --- a/src/cdk/v2/destinations/intercom/utils.js +++ b/src/cdk/v2/destinations/intercom/utils.js @@ -144,7 +144,7 @@ const searchContact = async (message, destination) => { } throw new NetworkError( - `Unable to search contact due to : ${JSON.stringify(processedUserResponse?.response?.data)}`, + `Unable to search contact due to : ${JSON.stringify(processedUserResponse?.response?.errors)}`, processedUserResponse?.status, { [tags]: getDynamicErrorType(processedUserResponse?.status), @@ -163,7 +163,6 @@ const searchContact = async (message, destination) => { const createOrUpdateCompany = async (payload, destination) => { const headers = getHeaders(destination); const finalPayload = JSON.stringify(removeUndefinedAndNullValues(payload)); - const baseEndPoint = getBaseEndpoint(destination); const endpoint = `${baseEndPoint}/${CREATE_OR_UPDATE_COMPANY_ENDPOINT}`; const response = await httpPOST(endpoint, finalPayload, { diff --git a/src/cdk/v2/destinations/intercom/utils.test.js b/src/cdk/v2/destinations/intercom/utils.test.js index 33b992944a..daab45e602 100644 --- a/src/cdk/v2/destinations/intercom/utils.test.js +++ b/src/cdk/v2/destinations/intercom/utils.test.js @@ -1,14 +1,19 @@ +const axios = require('axios'); const { getName, getHeaders, + searchContact, getLookUpField, getBaseEndpoint, getCustomAttributes, addMetadataToPayload, + createOrUpdateCompany, separateReservedAndRestMetadata, } = require('./utils'); const { BASE_ENDPOINT, BASE_EU_ENDPOINT, BASE_AU_ENDPOINT } = require('./config'); +jest.mock('axios'); + describe('separateReservedAndRestMetadata utility test', () => { it('separate reserved and rest metadata', () => { const metadata = { @@ -348,3 +353,236 @@ describe('addMetadataToPayload utility test', () => { }); }); }); + +describe('searchContact utility test', () => { + it('Should successfully search contact by email', async () => { + const message = { context: { traits: { email: 'test@rudderlabs.com' } } }; + const destination = { Config: { apiKey: 'testApiKey', apiServer: 'us' } }; + axios.post.mockResolvedValue({ + status: 200, + data: { + type: 'list', + total_count: 1, + pages: { + type: 'pages', + page: 1, + per_page: 50, + total_pages: 1, + }, + data: [ + { + type: 'contact', + id: '1', + email: 'test@rudderlabs.com', + }, + ], + }, + }); + + const result = await searchContact(message, destination); + expect(result).toEqual('1'); + }); + + it('Should return first contact id if multiple contact exist with give search field', async () => { + const message = { + context: { + traits: { email: 'test@rudderlabs.com', phone: '+91 9999999999' }, + integrations: { INTERCOM: { lookup: 'phone' } }, + }, + }; + const destination = { Config: { apiKey: 'testApiKey', apiServer: 'us' } }; + axios.post.mockResolvedValue({ + status: 200, + data: { + type: 'list', + total_count: 1, + pages: { + type: 'pages', + page: 1, + per_page: 50, + total_pages: 1, + }, + data: [ + { + type: 'contact', + id: '1', + email: 'test@rudderlabs.com', + phone: '+91 9999999999', + }, + { + type: 'contact', + id: '2', + email: 'test+1@rudderlabs.com', + phone: '+91 9999999999', + }, + ], + }, + }); + + const result = await searchContact(message, destination); + expect(result).toEqual('1'); + }); + + it('Should return null if no contact is found', async () => { + const message = { + context: { + traits: { email: 'test+10@rudderlabs.com', phone: '+91 9999999999' }, + integrations: { INTERCOM: { lookup: 'email' } }, + }, + }; + const destination = { Config: { apiKey: 'testApiKey', apiServer: 'us' } }; + axios.post.mockResolvedValue({ + status: 200, + data: { + type: 'list', + total_count: 0, + pages: { + type: 'pages', + page: 1, + per_page: 50, + total_pages: 0, + }, + data: [], + }, + }); + + const result = await searchContact(message, destination); + expect(result).toBeNull(); + }); + + it('Should throw an error in case if axios calls returns an error', async () => { + const message = { + context: { + traits: { email: 'test+3@rudderlabs.com', phone: '+91 9999999999' }, + integrations: { INTERCOM: { lookup: 'email' } }, + }, + }; + const destination = { Config: { apiKey: 'invalidTestApiKey', apiServer: 'us' } }; + axios.post.mockRejectedValue({ + status: 401, + data: { + type: 'error.list', + request_id: 'request_400', + errors: [ + { + code: 'unauthorized', + message: 'Access Token Invalid', + }, + ], + }, + }); + + try { + const result = await searchContact(message, destination); + expect(result).toEqual(''); + } catch (error) { + expect(error.message).toEqual( + 'Unable to search contact due to : [{"code":"unauthorized","message":"Access Token Invalid"}]', + ); + } + }); +}); + +describe('createOrUpdateCompany utility test', () => { + it('Should successfully create company', async () => { + const payload = { + company_id: 'rudderlabs', + name: 'RudderStack', + website: 'www.rudderstack.com', + plan: 'enterprise', + size: 500, + industry: 'CDP', + custom_attributes: {}, + }; + const destination = { Config: { apiKey: 'testApiKey', apiServer: 'us' } }; + axios.post.mockResolvedValue({ + status: 200, + data: { + type: 'company', + company_id: 'rudderlabs', + id: '1', + name: 'RudderStack', + website: 'www.rudderstack.com', + plan: 'enterprise', + size: 500, + industry: 'CDP', + remote_created_at: 1374138000, + created_at: 1701930212, + updated_at: 1701930212, + }, + }); + + const result = await createOrUpdateCompany(payload, destination); + expect(result).toEqual('1'); + }); + + it('Should throw an error in case if axios calls returns an error', async () => { + const payload = { + company_id: 'rudderlabs', + name: 'RudderStack', + website: 'www.rudderstack.com', + plan: 'enterprise', + size: 500, + industry: 'CDP', + testData: true, + }; + const destination = { Config: { apiKey: 'testApiKey', apiServer: 'us' } }; + axios.post.mockRejectedValue({ + status: 400, + data: { + type: 'error.list', + request_id: 'request_400', + errors: [ + { + code: 'bad_request', + message: "bad 'testData' parameter", + }, + ], + }, + }); + + try { + const result = await createOrUpdateCompany(payload, destination); + expect(result).toEqual(''); + } catch (error) { + expect(error.message).toEqual( + 'Unable to Create or Update Company due to : [{"code":"bad_request","message":"bad \'testData\' parameter"}]', + ); + } + }); + + it('Should throw an error in case if axios calls returns an error', async () => { + const payload = { + company_id: 'rudderlabs', + name: 'RudderStack', + website: 'www.rudderstack.com', + plan: 'enterprise', + size: 500, + industry: 'CDP', + testData: true, + }; + const destination = { Config: { apiKey: 'invalidTestApiKey', apiServer: 'us' } }; + axios.post.mockRejectedValue({ + status: 400, + data: { + type: 'error.list', + request_id: 'request_400', + errors: [ + { + code: 'unauthorized', + message: 'Access Token Invalid', + }, + ], + }, + }); + + try { + const result = await createOrUpdateCompany(payload, destination); + expect(result).toEqual(''); + } catch (error) { + expect(error.message).toEqual( + 'Unable to Create or Update Company due to : [{"code":"unauthorized","message":"Access Token Invalid"}]', + ); + } + }); +}); diff --git a/test/integrations/destinations/intercom/processor/data.ts b/test/integrations/destinations/intercom/processor/data.ts index a9871a18a0..e8dedcf6ec 100644 --- a/test/integrations/destinations/intercom/processor/data.ts +++ b/test/integrations/destinations/intercom/processor/data.ts @@ -531,7 +531,7 @@ export const data = [ }, statusCode: 401, error: - '{"message":"{\\"message\\":\\"Unable to search contact due to : undefined: Workflow: procWorkflow, Step: searchContact, ChildStep: undefined, OriginalError: Unable to search contact due to : undefined\\",\\"destinationResponse\\":{\\"response\\":{\\"type\\":\\"error.list\\",\\"request_id\\":\\"request_1\\",\\"errors\\":[{\\"code\\":\\"unauthorized\\",\\"message\\":\\"Access Token Invalid\\"}]},\\"status\\":401}}","destinationResponse":{"response":{"type":"error.list","request_id":"request_1","errors":[{"code":"unauthorized","message":"Access Token Invalid"}]},"status":401}}', + '{"message":"{\\"message\\":\\"Unable to search contact due to : [{\\\\\\"code\\\\\\":\\\\\\"unauthorized\\\\\\",\\\\\\"message\\\\\\":\\\\\\"Access Token Invalid\\\\\\"}]: Workflow: procWorkflow, Step: searchContact, ChildStep: undefined, OriginalError: Unable to search contact due to : [{\\\\\\"code\\\\\\":\\\\\\"unauthorized\\\\\\",\\\\\\"message\\\\\\":\\\\\\"Access Token Invalid\\\\\\"}]\\",\\"destinationResponse\\":{\\"response\\":{\\"type\\":\\"error.list\\",\\"request_id\\":\\"request_1\\",\\"errors\\":[{\\"code\\":\\"unauthorized\\",\\"message\\":\\"Access Token Invalid\\"}]},\\"status\\":401}}","destinationResponse":{"response":{"type":"error.list","request_id":"request_1","errors":[{"code":"unauthorized","message":"Access Token Invalid"}]},"status":401}}', statTags: { errorCategory: 'network', errorType: 'aborted',