@@ -154,6 +154,61 @@ describe('execute tests', () => {
154154 expect ( ApiInteractorImpl . getErrorResponse ) . toBeCalledTimes ( 1 ) ;
155155 } ) ;
156156
157+ test ( 'network client parse error with client response code is not retried' , async ( ) => {
158+ // given
159+ const expectedError = new QonversionError (
160+ QonversionErrorCode . BackendError ,
161+ 'Failed to parse JSON response' ,
162+ undefined ,
163+ 400 ,
164+ ) ;
165+ networkClient . execute = jest . fn ( ( ) => {
166+ throw expectedError ;
167+ } ) ;
168+ ApiInteractorImpl . getErrorResponse = savedGetErrorResponse ;
169+
170+ // when
171+ const response = await apiInteractor . execute ( request , new RetryPolicyExponential ( 3 ) ) ;
172+
173+ // then
174+ expect ( response ) . toStrictEqual ( {
175+ code : 400 ,
176+ message : 'Failed to parse JSON response' ,
177+ isSuccess : false ,
178+ } ) ;
179+ expect ( networkClient . execute ) . toBeCalledTimes ( 1 ) ;
180+ expect ( apiInteractor . prepareRetryConfig ) . not . toBeCalled ( ) ;
181+ } ) ;
182+
183+ test ( 'network client parse error with server response code is retried' , async ( ) => {
184+ // given
185+ const retryCount = 2 ;
186+ const expectedError = new QonversionError (
187+ QonversionErrorCode . BackendError ,
188+ 'Failed to parse JSON response' ,
189+ undefined ,
190+ 500 ,
191+ ) ;
192+ networkClient . execute = jest . fn ( ( ) => { throw expectedError } ) ;
193+ ApiInteractorImpl . getErrorResponse = savedGetErrorResponse ;
194+ apiInteractor . prepareRetryConfig = jest . fn ( ( retryPolicy , attemptIndex ) => ( {
195+ attemptIndex : attemptIndex + 1 ,
196+ delay : 1 ,
197+ shouldRetry : attemptIndex < retryCount ,
198+ } ) ) ;
199+
200+ // when
201+ const response = await apiInteractor . execute ( request , new RetryPolicyExponential ( retryCount ) ) ;
202+
203+ // then
204+ expect ( response ) . toStrictEqual ( {
205+ code : 500 ,
206+ message : 'Failed to parse JSON response' ,
207+ isSuccess : false ,
208+ } ) ;
209+ expect ( networkClient . execute ) . toBeCalledTimes ( retryCount + 1 ) ;
210+ } ) ;
211+
157212 test ( 'retryable error response without retry config' , async ( ) => {
158213 // given
159214 testResponseCode = 555 ;
@@ -375,6 +430,67 @@ describe('getErrorResponse tests', () => {
375430 expect ( result ) . toStrictEqual ( expResult ) ;
376431 } ) ;
377432
433+ test ( 'get error from malformed api error object' , ( ) => {
434+ // given
435+ const networkResponse : RawNetworkResponse = {
436+ code : 502 ,
437+ payload : { } ,
438+ } ;
439+
440+ // when
441+ const result = ApiInteractorImpl . getErrorResponse ( networkResponse )
442+
443+ // then
444+ expect ( result ) . toStrictEqual ( {
445+ apiCode : undefined ,
446+ code : 502 ,
447+ message : 'Unexpected API error response' ,
448+ type : undefined ,
449+ isSuccess : false ,
450+ } ) ;
451+ } ) ;
452+
453+ test ( 'get error from plain text payload' , ( ) => {
454+ // given
455+ const networkResponse : RawNetworkResponse = {
456+ code : 503 ,
457+ payload : 'service unavailable' ,
458+ } ;
459+
460+ // when
461+ const result = ApiInteractorImpl . getErrorResponse ( networkResponse )
462+
463+ // then
464+ expect ( result ) . toStrictEqual ( {
465+ apiCode : undefined ,
466+ code : 503 ,
467+ message : 'Unexpected API error response: service unavailable' ,
468+ type : undefined ,
469+ isSuccess : false ,
470+ } ) ;
471+ } ) ;
472+
473+ test ( 'get error from long plain text payload' , ( ) => {
474+ // given
475+ const payload = 'x' . repeat ( 130 ) ;
476+ const networkResponse : RawNetworkResponse = {
477+ code : 503 ,
478+ payload,
479+ } ;
480+
481+ // when
482+ const result = ApiInteractorImpl . getErrorResponse ( networkResponse )
483+
484+ // then
485+ expect ( result ) . toStrictEqual ( {
486+ apiCode : undefined ,
487+ code : 503 ,
488+ message : `Unexpected API error response: ${ 'x' . repeat ( 120 ) } ...` ,
489+ type : undefined ,
490+ isSuccess : false ,
491+ } ) ;
492+ } ) ;
493+
378494 test ( 'get error from execution error' , ( ) => {
379495 // given
380496 const executionError = new Error ( 'execution error' ) ;
@@ -385,7 +501,27 @@ describe('getErrorResponse tests', () => {
385501 } ) . toThrow ( executionError ) ;
386502 } ) ;
387503
388- test ( 'get error from execution error' , ( ) => {
504+ test ( 'get error from execution error with response code' , ( ) => {
505+ // given
506+ const executionError = new QonversionError (
507+ QonversionErrorCode . BackendError ,
508+ 'Failed to parse JSON response' ,
509+ undefined ,
510+ 400 ,
511+ ) ;
512+
513+ // when
514+ const result = ApiInteractorImpl . getErrorResponse ( undefined , executionError ) ;
515+
516+ // then
517+ expect ( result ) . toStrictEqual ( {
518+ code : 400 ,
519+ message : 'Failed to parse JSON response' ,
520+ isSuccess : false ,
521+ } ) ;
522+ } ) ;
523+
524+ test ( 'throw when neither response nor execution error is provided' , ( ) => {
389525 // given
390526
391527 // when and then
0 commit comments