1+ /* eslint-disable no-process-env */
12import { Context } from 'aws-lambda' ;
23import { mock , mockReset } from 'jest-mock-extended' ;
4+ import { InvalidMacError } from './domain/errors/invalid-mac.error' ;
5+ import { MaxRetriesError } from './domain/errors/max-retries.error' ;
36import { handler } from './index' ;
47import { LinkedinProfileService } from './services/linkedin-profile.service' ;
8+ import { QueueClient } from './services/queue.client' ;
59import {
610 createMockedLinkedinProfile ,
711 createMockedLinkedinProfileEmpty ,
@@ -15,57 +19,135 @@ jest.mock('./services/linkedin-profile.service', () => ({
1519 LinkedinProfileService : jest . fn ( ( ) => linkedinProfileService )
1620} ) ) ;
1721
22+ jest . mock ( './services/queue.client' , ( ) => ( {
23+ QueueClient : {
24+ sendToResultQueue : jest . fn ( ) . mockResolvedValue ( undefined ) ,
25+ resendMessage : jest . fn ( ) . mockResolvedValue ( undefined )
26+ }
27+ } ) ) ;
28+
1829describe ( 'Linkedin lambda handler' , ( ) => {
1930 beforeEach ( ( ) => {
20- jest . clearAllMocks ( ) ;
2131 mockReset ( linkedinProfileService ) ;
32+ jest . clearAllMocks ( ) ;
33+
34+ process . env . AWS_QUEUE_URL = 'queue-url' ;
35+ process . env . AWS_RESULT_QUEUE_URL = 'result-queue-url' ;
2236 } ) ;
2337
24- it ( 'should handle message and return a response with Linkedin Profile as Mac Profile' , async ( ) => {
25- const event = createMockedSqsSEvent ( ) ;
26- const expectedLinkedinProfile = createMockedLinkedinProfile ( ) ;
38+ describe ( 'when handling a successful request' , ( ) => {
39+ it ( 'should return a response with Linkedin Profile as Mac Profile' , async ( ) => {
40+ const event = createMockedSqsSEvent ( ) ;
41+ const expectedLinkedinProfile = createMockedLinkedinProfile ( ) ;
42+
43+ linkedinProfileService . getLinkedinProfile . calledWith ( 'fake-token' ) . mockResolvedValue ( {
44+ linkedinProfile : expectedLinkedinProfile ,
45+ isEmptyProfile : false ,
46+ timeElapsed : 1000
47+ } ) ;
2748
28- linkedinProfileService . getLinkedinProfile . calledWith ( 'fake-token' ) . mockResolvedValue ( {
29- linkedinProfile : expectedLinkedinProfile ,
30- isEmptyProfile : false
49+ const response = await handler ( event , { } as Context , ( ) => { } ) ;
50+
51+ expect ( response ) . toMatchSnapshot ( ) ;
3152 } ) ;
3253
33- const response = await handler ( event , { } as Context , ( ) => { } ) ;
54+ it ( 'should send response to sqs result queue ' , async ( ) => {
55+ const event = createMockedSqsSEvent ( ) ;
56+ const expectedLinkedinProfile = createMockedLinkedinProfile ( ) ;
57+
58+ linkedinProfileService . getLinkedinProfile . calledWith ( 'fake-token' ) . mockResolvedValue ( {
59+ linkedinProfile : expectedLinkedinProfile ,
60+ isEmptyProfile : false ,
61+ timeElapsed : 1000
62+ } ) ;
63+
64+ const response = await handler ( event , { } as Context , ( ) => { } ) ;
3465
35- expect ( response ) . toMatchSnapshot ( ) ;
66+ expect ( QueueClient . sendToResultQueue ) . toHaveBeenCalledWith ( response , expect . anything ( ) ) ;
67+ } ) ;
3668 } ) ;
3769
38- it ( 'should throw an error if number of messages is not 1' , async ( ) => {
39- const event = createMockedSqsSEvent ( ) ;
40- event . Records = [ { ...event . Records [ 0 ] } , { ...event . Records [ 0 ] } ] ;
70+ describe ( 'when handling a failed request' , ( ) => {
71+ it ( 'should throw an error if number of messages is not 1' , async ( ) => {
72+ const event = createMockedSqsSEvent ( ) ;
73+ event . Records = [ { ...event . Records [ 0 ] } , { ...event . Records [ 0 ] } ] ;
74+
75+ await expect ( handler ( event , { } as Context , ( ) => { } ) ) . rejects . toThrow (
76+ new Error ( '[LinkedinProfileRequestMapper] Batch size must be configured to 1' )
77+ ) ;
78+ } ) ;
79+
80+ it ( 'should throw an error if message is not a valid LinkedinProfileRequest' , async ( ) => {
81+ const request = createMockedLinkedinProfileRequest ( ) ;
82+ request . linkedinApiToken = undefined as unknown as string ; // missing required field
83+ const event = createMockedSqsSEvent ( request ) ;
84+ const expectedErrorString =
85+ '[LinkedinProfileRequestMapper] Validation failed: ["property: linkedinApiToken errors: linkedinApiToken must be a string"]' ;
4186
42- await expect ( handler ( event , { } as Context , ( ) => { } ) ) . rejects . toThrow (
43- new Error ( '[LinkedinProfileRequestMapper] Batch size must be configured to 1' )
44- ) ;
87+ await expect ( handler ( event , { } as Context , ( ) => { } ) ) . rejects . toThrow ( new Error ( expectedErrorString ) ) ;
88+ } ) ;
4589 } ) ;
4690
47- it ( 'should throw an error if message is not a valid LinkedinProfileRequest' , async ( ) => {
48- const request = createMockedLinkedinProfileRequest ( ) ;
49- request . linkedinApiToken = undefined as unknown as string ; // missing required field
50- const event = createMockedSqsSEvent ( request ) ;
51- const expectedErrorString =
52- '[LinkedinProfileRequestMapper] Validation failed: ["property: linkedinApiToken errors: linkedinApiToken must be a string"]' ;
91+ describe ( 'when handling an empty response' , ( ) => {
92+ it ( 'should resend message to sqs queue if empty response and no reached max retries ' , async ( ) => {
93+ const event = createMockedSqsSEvent ( ) ;
94+ const expectedLinkedinProfile = createMockedLinkedinProfileEmpty ( ) ;
95+
96+ linkedinProfileService . getLinkedinProfile . calledWith ( 'fake-token' ) . mockResolvedValue ( {
97+ linkedinProfile : expectedLinkedinProfile ,
98+ isEmptyProfile : true ,
99+ timeElapsed : 1000
100+ } ) ;
101+
102+ await handler ( event , { } as Context , ( ) => { } ) ;
103+ expect ( QueueClient . resendMessage ) . toHaveBeenCalled ( ) ;
104+ } ) ;
105+
106+ it ( 'should throw an error if max retries reached' , async ( ) => {
107+ const request = createMockedLinkedinProfileRequest ( { attempt : 3 } ) ;
108+ const event = createMockedSqsSEvent ( request ) ;
109+ const expectedLinkedinProfile = createMockedLinkedinProfileEmpty ( ) ;
53110
54- await expect ( handler ( event , { } as Context , ( ) => { } ) ) . rejects . toThrow ( new Error ( expectedErrorString ) ) ;
111+ linkedinProfileService . getLinkedinProfile . calledWith ( 'fake-token' ) . mockResolvedValue ( {
112+ linkedinProfile : expectedLinkedinProfile ,
113+ isEmptyProfile : true ,
114+ timeElapsed : 1000
115+ } ) ;
116+
117+ await expect ( handler ( event , { } as Context , ( ) => { } ) ) . rejects . toThrow ( MaxRetriesError ) ;
118+ } ) ;
55119 } ) ;
56120
57- // TODO: Review this corner case: this should be valid?
58- it ( 'should throw an error if response is not a valid LinkedinProfileResponse' , async ( ) => {
59- const event = createMockedSqsSEvent ( ) ;
60- const expectedLinkedinProfile = createMockedLinkedinProfileEmpty ( ) ;
61- const expectedErrorString =
62- '[LinkedinProfileResponseMapper] MAC Validation failed: ["property: mac.aboutMe.profile.title errors: title should not be empty"]' ;
121+ describe ( 'when handling a failed response' , ( ) => {
122+ it ( 'should throw an error if response is not a valid LinkedinProfileResponse' , async ( ) => {
123+ const event = createMockedSqsSEvent ( ) ;
124+ const expectedLinkedinProfile = createMockedLinkedinProfileEmpty ( ) ;
125+ const expectedErrorString =
126+ '[LinkedinProfileResponseMapper] MAC Validation failed: ["property: profile.aboutMe.profile.title errors: title should not be empty"]' ;
127+
128+ linkedinProfileService . getLinkedinProfile . calledWith ( 'fake-token' ) . mockResolvedValue ( {
129+ linkedinProfile : expectedLinkedinProfile ,
130+ isEmptyProfile : false ,
131+ timeElapsed : 1000
132+ } ) ;
63133
64- linkedinProfileService . getLinkedinProfile . calledWith ( 'fake-token' ) . mockResolvedValue ( {
65- linkedinProfile : expectedLinkedinProfile ,
66- isEmptyProfile : false
134+ await expect ( handler ( event , { } as Context , ( ) => { } ) ) . rejects . toThrow ( new InvalidMacError ( expectedErrorString ) ) ;
67135 } ) ;
68136
69- await expect ( handler ( event , { } as Context , ( ) => { } ) ) . rejects . toThrow ( new Error ( expectedErrorString ) ) ;
137+ it ( 'should send response to sqs result queue ' , async ( ) => {
138+ const event = createMockedSqsSEvent ( ) ;
139+ const expectedLinkedinProfile = createMockedLinkedinProfileEmpty ( ) ;
140+ const expectedErrorString =
141+ '[LinkedinProfileResponseMapper] MAC Validation failed: ["property: profile.aboutMe.profile.title errors: title should not be empty"]' ;
142+
143+ linkedinProfileService . getLinkedinProfile . calledWith ( 'fake-token' ) . mockResolvedValue ( {
144+ linkedinProfile : expectedLinkedinProfile ,
145+ isEmptyProfile : false ,
146+ timeElapsed : 1000
147+ } ) ;
148+
149+ await expect ( handler ( event , { } as Context , ( ) => { } ) ) . rejects . toThrow ( new Error ( expectedErrorString ) ) ;
150+ expect ( QueueClient . sendToResultQueue ) . toHaveBeenCalled ( ) ;
151+ } ) ;
70152 } ) ;
71153} ) ;
0 commit comments