@@ -171,13 +171,21 @@ describe('useFeedConversion', () => {
171171 fetchMock . mockRejectedValueOnce ( new Error ( 'Network error' ) ) ;
172172
173173 const { result } = renderHook ( ( ) => useFeedConversion ( ) ) ;
174- let thrownError : ( Error & { manualRetryStrategy ?: string ; retryAction ?: string } ) | undefined ;
174+ let thrownError :
175+ | ( Error & { manualRetryStrategy ?: string ; retryAction ?: string ; kind ?: string ; code ?: string ; status ?: number } )
176+ | undefined ;
175177
176178 await act ( async ( ) => {
177179 try {
178180 await result . current . convertFeed ( 'https://example.com' , 'faraday' , 'testtoken' ) ;
179181 } catch ( error ) {
180- thrownError = error as Error & { manualRetryStrategy ?: string ; retryAction ?: string } ;
182+ thrownError = error as Error & {
183+ manualRetryStrategy ?: string ;
184+ retryAction ?: string ;
185+ kind ?: string ;
186+ code ?: string ;
187+ status ?: number ;
188+ } ;
181189 }
182190 } ) ;
183191
@@ -187,6 +195,7 @@ describe('useFeedConversion', () => {
187195 expect ( thrownError ?. message ) . toBe ( 'Network error' ) ;
188196 expect ( thrownError ?. manualRetryStrategy ) . toBe ( 'browserless' ) ;
189197 expect ( thrownError ?. retryAction ) . toBe ( 'alternate' ) ;
198+ expect ( thrownError ?. kind ) . toBe ( 'network' ) ;
190199 } ) ;
191200
192201 it ( 'preserves the created feed when preview loading fails after feed creation' , async ( ) => {
@@ -623,7 +632,7 @@ describe('useFeedConversion', () => {
623632 new Response (
624633 JSON . stringify ( {
625634 success : false ,
626- error : { message : 'Unauthorized' } ,
635+ error : { code : 'UNAUTHORIZED' , message : 'Unauthorized' } ,
627636 } ) ,
628637 {
629638 status : 401 ,
@@ -633,13 +642,21 @@ describe('useFeedConversion', () => {
633642 ) ;
634643
635644 const { result } = renderHook ( ( ) => useFeedConversion ( ) ) ;
636- let thrownError : ( Error & { manualRetryStrategy ?: string ; retryAction ?: string } ) | undefined ;
645+ let thrownError :
646+ | ( Error & { manualRetryStrategy ?: string ; retryAction ?: string ; kind ?: string ; code ?: string ; status ?: number } )
647+ | undefined ;
637648
638649 await act ( async ( ) => {
639650 try {
640651 await result . current . convertFeed ( 'https://example.com/articles' , 'faraday' , 'testtoken' ) ;
641652 } catch ( error ) {
642- thrownError = error as Error & { manualRetryStrategy ?: string ; retryAction ?: string } ;
653+ thrownError = error as Error & {
654+ manualRetryStrategy ?: string ;
655+ retryAction ?: string ;
656+ kind ?: string ;
657+ code ?: string ;
658+ status ?: number ;
659+ } ;
643660 }
644661 } ) ;
645662
@@ -649,6 +666,9 @@ describe('useFeedConversion', () => {
649666 expect ( thrownError ?. message ) . toBe ( 'Unauthorized' ) ;
650667 expect ( thrownError ?. manualRetryStrategy ) . toBeUndefined ( ) ;
651668 expect ( thrownError ?. retryAction ) . toBeUndefined ( ) ;
669+ expect ( thrownError ?. kind ) . toBe ( 'auth' ) ;
670+ expect ( thrownError ?. code ) . toBe ( 'UNAUTHORIZED' ) ;
671+ expect ( thrownError ?. status ) . toBeUndefined ( ) ;
652672 } ) ;
653673
654674 it ( 'does not auto-retry when API returns a non-retryable BAD_REQUEST code' , async ( ) => {
@@ -666,13 +686,21 @@ describe('useFeedConversion', () => {
666686 ) ;
667687
668688 const { result } = renderHook ( ( ) => useFeedConversion ( ) ) ;
669- let thrownError : ( Error & { manualRetryStrategy ?: string ; retryAction ?: string } ) | undefined ;
689+ let thrownError :
690+ | ( Error & { manualRetryStrategy ?: string ; retryAction ?: string ; kind ?: string ; code ?: string ; status ?: number } )
691+ | undefined ;
670692
671693 await act ( async ( ) => {
672694 try {
673695 await result . current . convertFeed ( 'https://example.com/articles' , 'faraday' , 'testtoken' ) ;
674696 } catch ( error ) {
675- thrownError = error as Error & { manualRetryStrategy ?: string ; retryAction ?: string } ;
697+ thrownError = error as Error & {
698+ manualRetryStrategy ?: string ;
699+ retryAction ?: string ;
700+ kind ?: string ;
701+ code ?: string ;
702+ status ?: number ;
703+ } ;
676704 }
677705 } ) ;
678706
@@ -682,6 +710,9 @@ describe('useFeedConversion', () => {
682710 expect ( thrownError ?. message ) . toBe ( 'Input rejected' ) ;
683711 expect ( thrownError ?. manualRetryStrategy ) . toBeUndefined ( ) ;
684712 expect ( thrownError ?. retryAction ) . toBeUndefined ( ) ;
713+ expect ( thrownError ?. kind ) . toBe ( 'input' ) ;
714+ expect ( thrownError ?. code ) . toBe ( 'BAD_REQUEST' ) ;
715+ expect ( thrownError ?. status ) . toBeUndefined ( ) ;
685716 } ) ;
686717
687718 it ( 'still auto-retries when API returns INTERNAL_SERVER_ERROR even if message contains a url' , async ( ) => {
@@ -781,12 +812,20 @@ describe('useFeedConversion', () => {
781812
782813 const { result } = renderHook ( ( ) => useFeedConversion ( ) ) ;
783814
784- let thrownError : ( Error & { manualRetryStrategy ?: string ; retryAction ?: string } ) | undefined ;
815+ let thrownError :
816+ | ( Error & { manualRetryStrategy ?: string ; retryAction ?: string ; kind ?: string ; code ?: string ; status ?: number } )
817+ | undefined ;
785818 await act ( async ( ) => {
786819 try {
787820 await result . current . convertFeed ( 'https://example.com/articles' , 'faraday' , 'testtoken' ) ;
788821 } catch ( error ) {
789- thrownError = error as Error & { manualRetryStrategy ?: string ; retryAction ?: string } ;
822+ thrownError = error as Error & {
823+ manualRetryStrategy ?: string ;
824+ retryAction ?: string ;
825+ kind ?: string ;
826+ code ?: string ;
827+ status ?: number ;
828+ } ;
790829 }
791830 } ) ;
792831
@@ -795,6 +834,7 @@ describe('useFeedConversion', () => {
795834 ) ;
796835 expect ( thrownError ?. manualRetryStrategy ) . toBeUndefined ( ) ;
797836 expect ( thrownError ?. retryAction ) . toBe ( 'primary' ) ;
837+ expect ( thrownError ?. kind ) . toBe ( 'server' ) ;
798838 expect ( result . current . result ) . toBeUndefined ( ) ;
799839 expect ( result . current . error ) . toBe (
800840 'Tried faraday first, then browserless. First attempt failed with: Upstream timeout. Second attempt failed with: Browserless also failed'
0 commit comments