From e5f3aa835e86f4243ac4a2c0a5bd13f8589b945a Mon Sep 17 00:00:00 2001 From: Chandra shekar Varkala Date: Wed, 14 Feb 2024 18:04:00 -0600 Subject: [PATCH] chore: more tests --- src/controllers/__tests__/delivery.test.ts | 12 +- src/controllers/__tests__/destination.test.ts | 107 ++++++++++++++++-- src/controllers/__tests__/regulation.test.ts | 107 ++++++++++++++++++ src/controllers/__tests__/source.test.ts | 12 +- src/controllers/regulation.ts | 6 +- src/services/__tests__/misc.test.ts | 4 +- .../__tests__/nativeIntegration.test.ts | 1 - test/apitests/service.api.test.ts | 3 + 8 files changed, 221 insertions(+), 31 deletions(-) create mode 100644 src/controllers/__tests__/regulation.test.ts diff --git a/src/controllers/__tests__/delivery.test.ts b/src/controllers/__tests__/delivery.test.ts index d38424b9bb..b601ff756c 100644 --- a/src/controllers/__tests__/delivery.test.ts +++ b/src/controllers/__tests__/delivery.test.ts @@ -56,11 +56,10 @@ describe('Delivery controller tests', () => { return mockDestinationService; }); - const data = getData(); const response = await request(server) .post('/v0/destinations/__rudder_test__/proxy') .set('Accept', 'application/json') - .send(data); + .send(getData()); expect(response.status).toEqual(200); expect(response.body).toEqual({ output: testOutput }); @@ -87,11 +86,10 @@ describe('Delivery controller tests', () => { return mockDestinationService; }); - const data = getData(); const response = await request(server) .post('/v0/destinations/__rudder_test__/proxy') .set('Accept', 'application/json') - .send(data); + .send(getData()); const expectedResp = { output: { @@ -131,11 +129,10 @@ describe('Delivery controller tests', () => { return mockDestinationService; }); - const data = getData(); const response = await request(server) .post('/v1/destinations/__rudder_test__/proxy') .set('Accept', 'application/json') - .send(data); + .send(getData()); expect(response.status).toEqual(200); expect(response.body).toEqual({ output: testOutput }); @@ -162,11 +159,10 @@ describe('Delivery controller tests', () => { return mockDestinationService; }); - const data = getData(); const response = await request(server) .post('/v1/destinations/__rudder_test__/proxy') .set('Accept', 'application/json') - .send(data); + .send(getData()); const expectedResp = { output: { diff --git a/src/controllers/__tests__/destination.test.ts b/src/controllers/__tests__/destination.test.ts index 447111250f..3c49a9a0af 100644 --- a/src/controllers/__tests__/destination.test.ts +++ b/src/controllers/__tests__/destination.test.ts @@ -6,7 +6,6 @@ import { applicationRoutes } from '../../routes'; import { ServiceSelector } from '../../helpers/serviceSelector'; import { DynamicConfigParser } from '../../util/dynamicConfigParser'; import { NativeIntegrationDestinationService } from '../../services/destination/nativeIntegration'; -import exp from 'constants'; let server: any; const OLD_ENV = process.env; @@ -85,11 +84,10 @@ describe('Destination controller tests', () => { return events; }); - const data = getData(); const response = await request(server) .post('/v0/destinations/__rudder_test__') .set('Accept', 'application/json') - .send(data); + .send(getData()); expect(response.status).toEqual(200); expect(response.body).toEqual(expectedOutput); @@ -134,11 +132,10 @@ describe('Destination controller tests', () => { return events; }); - const data = getData(); const response = await request(server) .post('/v0/destinations/__rudder_test__') .set('Accept', 'application/json') - .send(data); + .send(getData()); expect(response.status).toEqual(200); expect(response.body).toEqual(expectedOutput); @@ -188,11 +185,10 @@ describe('Destination controller tests', () => { return events; }); - const data = getRouterTransformInputData(); const response = await request(server) .post('/routerTransform') .set('Accept', 'application/json') - .send(data); + .send(getRouterTransformInputData()); expect(response.status).toEqual(200); expect(response.body).toEqual({ output: expectedOutput }); @@ -221,11 +217,10 @@ describe('Destination controller tests', () => { return events; }); - const data = getRouterTransformInputData(); const response = await request(server) .post('/routerTransform') .set('Accept', 'application/json') - .send(data); + .send(getRouterTransformInputData()); const expectedOutput = [ { @@ -245,4 +240,98 @@ describe('Destination controller tests', () => { expect(mockDestinationService.doRouterTransformation).toHaveBeenCalledTimes(1); }); }); + + describe('Batch transform tests', () => { + test('successful batching at router', async () => { + const mockDestinationService = new NativeIntegrationDestinationService(); + + const expectedOutput = [ + { + message: { a: 'b1' }, + destination: {}, + metadata: { jobId: 1 }, + request: { query: {} }, + }, + { + message: { a: 'b2' }, + destination: {}, + metadata: { jobId: 2 }, + request: { query: {} }, + }, + ]; + + mockDestinationService.doBatchTransformation = jest + .fn() + .mockImplementation((events, destinationType, version, requestMetadata) => { + expect(events).toEqual(expectedOutput); + expect(destinationType).toEqual('__rudder_test__'); + expect(version).toEqual('v0'); + + return events; + }); + const getDestinationServiceSpy = jest + .spyOn(ServiceSelector, 'getDestinationService') + .mockImplementation(() => { + return mockDestinationService; + }); + + DynamicConfigParser.process = jest.fn().mockImplementation((events) => { + return events; + }); + + const response = await request(server) + .post('/batch') + .set('Accept', 'application/json') + .send(getRouterTransformInputData()); + + expect(response.status).toEqual(200); + expect(response.body).toEqual(expectedOutput); + + expect(response.header['apiversion']).toEqual('2'); + + expect(getDestinationServiceSpy).toHaveBeenCalledTimes(1); + expect(mockDestinationService.doBatchTransformation).toHaveBeenCalledTimes(1); + }); + + test('batch transformation failure', async () => { + const mockDestinationService = new NativeIntegrationDestinationService(); + + mockDestinationService.doBatchTransformation = jest + .fn() + .mockImplementation((events, destinationType, version, requestMetadata) => { + throw new Error('Batch transformation failed'); + }); + const getDestinationServiceSpy = jest + .spyOn(ServiceSelector, 'getDestinationService') + .mockImplementation(() => { + return mockDestinationService; + }); + + DynamicConfigParser.process = jest.fn().mockImplementation((events) => { + return events; + }); + + const response = await request(server) + .post('/batch') + .set('Accept', 'application/json') + .send(getRouterTransformInputData()); + + const expectedOutput = [ + { + metadata: [{ jobId: 1 }, { jobId: 2 }], + batched: false, + statusCode: 500, + error: 'Batch transformation failed', + statTags: { errorCategory: 'transformation' }, + }, + ]; + expect(response.status).toEqual(200); + expect(response.body).toEqual(expectedOutput); + + expect(response.header['apiversion']).toEqual('2'); + + expect(getDestinationServiceSpy).toHaveBeenCalledTimes(1); + expect(mockDestinationService.doBatchTransformation).toHaveBeenCalledTimes(1); + }); + }); }); diff --git a/src/controllers/__tests__/regulation.test.ts b/src/controllers/__tests__/regulation.test.ts new file mode 100644 index 0000000000..55cd8f2d37 --- /dev/null +++ b/src/controllers/__tests__/regulation.test.ts @@ -0,0 +1,107 @@ +import request from 'supertest'; +import { createHttpTerminator } from 'http-terminator'; +import Koa from 'koa'; +import bodyParser from 'koa-bodyparser'; +import { applicationRoutes } from '../../routes'; +import { ServiceSelector } from '../../helpers/serviceSelector'; +import { NativeIntegrationDestinationService } from '../../services/destination/nativeIntegration'; + +let server: any; +const OLD_ENV = process.env; + +beforeAll(async () => { + process.env = { ...OLD_ENV }; // Make a copy + const app = new Koa(); + app.use( + bodyParser({ + jsonLimit: '200mb', + }), + ); + applicationRoutes(app); + server = app.listen(9090); +}); + +afterAll(async () => { + process.env = OLD_ENV; // Restore old environment + const httpTerminator = createHttpTerminator({ + server, + }); + await httpTerminator.terminate(); +}); + +afterEach(() => { + jest.clearAllMocks(); +}); + +const getDeletionData = () => { + return [ + { userAttributes: [{ a: 'b1' }], destType: '__rudder_test__' }, + { userAttributes: [{ a: 'b1' }], destType: '__rudder_test__' }, + ]; +}; + +describe('Regulation controller tests', () => { + describe('Delete users tests', () => { + test('successful delete users request', async () => { + const mockDestinationService = new NativeIntegrationDestinationService(); + + const expectedOutput = [{ statusCode: 400 }, { statusCode: 200 }]; + + mockDestinationService.processUserDeletion = jest + .fn() + .mockImplementation((reqs, destInfo) => { + expect(reqs).toEqual(getDeletionData()); + expect(destInfo).toEqual({ a: 'test' }); + + return expectedOutput; + }); + const getDestinationServiceSpy = jest + .spyOn(ServiceSelector, 'getNativeDestinationService') + .mockImplementation(() => { + return mockDestinationService; + }); + + const response = await request(server) + .post('/deleteUsers') + .set('Accept', 'application/json') + .set('x-rudder-dest-info', '{"a": "test"}') + .send(getDeletionData()); + + expect(response.status).toEqual(400); + expect(response.body).toEqual(expectedOutput); + + expect(getDestinationServiceSpy).toHaveBeenCalledTimes(1); + expect(mockDestinationService.processUserDeletion).toHaveBeenCalledTimes(1); + }); + + test('delete users request failure', async () => { + const mockDestinationService = new NativeIntegrationDestinationService(); + + mockDestinationService.processUserDeletion = jest + .fn() + .mockImplementation((reqs, destInfo) => { + expect(reqs).toEqual(getDeletionData()); + expect(destInfo).toEqual({ a: 'test' }); + + throw new Error('processUserDeletion error'); + }); + const getDestinationServiceSpy = jest + .spyOn(ServiceSelector, 'getNativeDestinationService') + .mockImplementation(() => { + return mockDestinationService; + }); + + const response = await request(server) + .post('/deleteUsers') + .set('Accept', 'application/json') + .set('x-rudder-dest-info', '{"a": "test"}') + .send(getDeletionData()); + + expect(response.status).toEqual(500); + expect(response.body).toEqual([{ error: {}, statusCode: 500 }]); + + expect(getDestinationServiceSpy).toHaveBeenCalledTimes(1); + expect(mockDestinationService.processUserDeletion).toHaveBeenCalledTimes(1); + }); + }); +}); diff --git a/src/controllers/__tests__/source.test.ts b/src/controllers/__tests__/source.test.ts index 357b474545..565f39d559 100644 --- a/src/controllers/__tests__/source.test.ts +++ b/src/controllers/__tests__/source.test.ts @@ -69,11 +69,10 @@ describe('Source controller tests', () => { return { implementationVersion: version, input: e }; }); - const data = getData(); const response = await request(server) .post('/v0/sources/__rudder_test__') .set('Accept', 'application/json') - .send(data); + .send(getData()); expect(response.status).toEqual(200); expect(response.body).toEqual(testOutput); @@ -105,11 +104,10 @@ describe('Source controller tests', () => { throw new Error('test error'); }); - const data = getData(); const response = await request(server) .post('/v0/sources/__rudder_test__') .set('Accept', 'application/json') - .send(data); + .send(getData()); const expectedResp = [ { @@ -161,11 +159,10 @@ describe('Source controller tests', () => { return { implementationVersion: version, input: e }; }); - const data = getData(); const response = await request(server) .post('/v1/sources/__rudder_test__') .set('Accept', 'application/json') - .send(data); + .send(getData()); expect(response.status).toEqual(200); expect(response.body).toEqual(testOutput); @@ -196,11 +193,10 @@ describe('Source controller tests', () => { throw new Error('test error'); }); - const data = getData(); const response = await request(server) .post('/v1/sources/__rudder_test__') .set('Accept', 'application/json') - .send(data); + .send(getData()); const expectedResp = [ { diff --git a/src/controllers/regulation.ts b/src/controllers/regulation.ts index a50541780d..318b5ed4e7 100644 --- a/src/controllers/regulation.ts +++ b/src/controllers/regulation.ts @@ -34,7 +34,7 @@ export class RegulationController { rudderDestInfo, ); ctx.body = resplist; - ctx.status = resplist[0].statusCode; + ctx.status = resplist[0].statusCode; // TODO: check if this is the right way to set status } catch (error: CatchErr) { const metaTO = integrationService.getTags( userDeletionRequests[0].destType, @@ -46,8 +46,8 @@ export class RegulationController { const errResp = DestinationPostTransformationService.handleUserDeletionFailureEvents( error, metaTO, - ); - ctx.body = [{ error, statusCode: 500 }] as UserDeletionResponse[]; + ); // TODO: this is not used. Fix it. + ctx.body = [{ error, statusCode: 500 }] as UserDeletionResponse[]; // TODO: responses array length is always 1. Is that okay? ctx.status = 500; } stats.timing('dest_transform_request_latency', startTime, { diff --git a/src/services/__tests__/misc.test.ts b/src/services/__tests__/misc.test.ts index 046191316d..5dcd948b34 100644 --- a/src/services/__tests__/misc.test.ts +++ b/src/services/__tests__/misc.test.ts @@ -7,12 +7,12 @@ describe('Misc tests', () => { Object.keys(DestHandlerMap).forEach((key) => { expect(MiscService.getDestHandler(key, version)).toEqual( - require(`../../v0/destinations/${DestHandlerMap[key]}/transform`), + require(`../../${version}/destinations/${DestHandlerMap[key]}/transform`), ); }); expect(MiscService.getDestHandler('am', version)).toEqual( - require(`../../v0/destinations/am/transform`), + require(`../../${version}/destinations/am/transform`), ); expect(MiscService.getSourceHandler('shopify', version)).toEqual( diff --git a/src/services/__tests__/nativeIntegration.test.ts b/src/services/__tests__/nativeIntegration.test.ts index aafc950468..9e3464892a 100644 --- a/src/services/__tests__/nativeIntegration.test.ts +++ b/src/services/__tests__/nativeIntegration.test.ts @@ -6,7 +6,6 @@ import { ProcessorTransformationResponse, } from '../../types/index'; import { FetchHandler } from '../../helpers/fetchHandlers'; -import exp from 'constants'; afterEach(() => { jest.clearAllMocks(); diff --git a/test/apitests/service.api.test.ts b/test/apitests/service.api.test.ts index 04c042f11c..f68b627e9b 100644 --- a/test/apitests/service.api.test.ts +++ b/test/apitests/service.api.test.ts @@ -86,6 +86,7 @@ describe('Api tests with a mock source/destination', () => { test('(mock destination) Processor transformation scenario with single event', async () => { const destType = '__rudder_test__'; const version = 'v0'; + const getInputData = () => { return [ { message: { a: 'b1' }, destination: {}, metadata: { jobId: 1 } }, @@ -132,6 +133,7 @@ describe('Api tests with a mock source/destination', () => { test('(mock destination) Batching', async () => { const destType = '__rudder_test__'; const version = 'v0'; + const getBatchInputData = () => { return { input: [ @@ -174,6 +176,7 @@ describe('Api tests with a mock source/destination', () => { test('(mock destination) Router transformation', async () => { const destType = '__rudder_test__'; const version = 'v0'; + const getRouterTransformInputData = () => { return { input: [