11import { act , renderHook , waitFor } from '@testing-library/react' ;
2- import axios from 'axios' ;
2+ import axios , { AxiosError } from 'axios' ;
33import nock from 'nock' ;
44
55import { mockAccounts , mockSettings } from '../__mocks__/mock-state' ;
@@ -50,17 +50,20 @@ describe('hooks/useNotifications.ts', () => {
5050 } ) ;
5151
5252 describe ( 'should fetch notifications with failures - github.com & enterprise' , ( ) => {
53- it ( 'bad credentials' , async ( ) => {
54- const status = 401 ;
55- const message = 'Bad credentials' ;
53+ it ( 'network error' , async ( ) => {
54+ const code = AxiosError . ERR_NETWORK ;
5655
5756 nock ( 'https://api.github.com/' )
5857 . get ( '/notifications?participating=false' )
59- . reply ( status , { message } ) ;
58+ . replyWithError ( {
59+ code : code ,
60+ } ) ;
6061
6162 nock ( 'https://github.gitify.io/api/v3/' )
6263 . get ( '/notifications?participating=false' )
63- . reply ( status , { message } ) ;
64+ . replyWithError ( {
65+ code : code ,
66+ } ) ;
6467
6568 const { result } = renderHook ( ( ) => useNotifications ( ) ) ;
6669
@@ -70,107 +73,245 @@ describe('hooks/useNotifications.ts', () => {
7073
7174 await waitFor ( ( ) => {
7275 expect ( result . current . requestFailed ) . toBe ( true ) ;
73- expect ( result . current . errorDetails ) . toBe ( Errors . BAD_CREDENTIALS ) ;
76+ expect ( result . current . errorDetails ) . toBe ( Errors . NETWORK ) ;
7477 } ) ;
7578 } ) ;
7679
77- it ( 'missing scopes' , async ( ) => {
78- const status = 403 ;
79- const message = "Missing the 'notifications' scope" ;
80-
81- nock ( 'https://api.github.com/' )
82- . get ( '/notifications?participating=false' )
83- . reply ( status , { message } ) ;
80+ describe ( 'bad request errors' , ( ) => {
81+ it ( 'bad credentials' , async ( ) => {
82+ const code = AxiosError . ERR_BAD_REQUEST ;
83+ const status = 401 ;
84+ const message = 'Bad credentials' ;
85+
86+ nock ( 'https://api.github.com/' )
87+ . get ( '/notifications?participating=false' )
88+ . replyWithError ( {
89+ code,
90+ response : {
91+ status,
92+ data : {
93+ message,
94+ } ,
95+ } ,
96+ } ) ;
97+
98+ nock ( 'https://github.gitify.io/api/v3/' )
99+ . get ( '/notifications?participating=false' )
100+ . replyWithError ( {
101+ code,
102+ response : {
103+ status,
104+ data : {
105+ message,
106+ } ,
107+ } ,
108+ } ) ;
84109
85- nock ( 'https://github.gitify.io/api/v3/' )
86- . get ( '/notifications?participating=false' )
87- . reply ( status , { message } ) ;
110+ const { result } = renderHook ( ( ) => useNotifications ( ) ) ;
88111
89- const { result } = renderHook ( ( ) => useNotifications ( ) ) ;
112+ act ( ( ) => {
113+ result . current . fetchNotifications ( mockAccounts , mockSettings ) ;
114+ } ) ;
90115
91- act ( ( ) => {
92- result . current . fetchNotifications ( mockAccounts , mockSettings ) ;
116+ await waitFor ( ( ) => {
117+ expect ( result . current . requestFailed ) . toBe ( true ) ;
118+ expect ( result . current . errorDetails ) . toBe ( Errors . BAD_CREDENTIALS ) ;
119+ } ) ;
93120 } ) ;
94121
95- await waitFor ( ( ) => {
96- expect ( result . current . requestFailed ) . toBe ( true ) ;
97- expect ( result . current . errorDetails ) . toBe ( Errors . MISSING_SCOPES ) ;
98- } ) ;
99- } ) ;
122+ it ( 'missing scopes' , async ( ) => {
123+ const code = AxiosError . ERR_BAD_REQUEST ;
124+ const status = 403 ;
125+ const message = "Missing the 'notifications' scope" ;
126+
127+ nock ( 'https://api.github.com/' )
128+ . get ( '/notifications?participating=false' )
129+ . replyWithError ( {
130+ code,
131+ response : {
132+ status,
133+ data : {
134+ message,
135+ } ,
136+ } ,
137+ } ) ;
138+
139+ nock ( 'https://github.gitify.io/api/v3/' )
140+ . get ( '/notifications?participating=false' )
141+ . replyWithError ( {
142+ code,
143+ response : {
144+ status,
145+ data : {
146+ message,
147+ } ,
148+ } ,
149+ } ) ;
100150
101- it ( 'rate limited - primary' , async ( ) => {
102- const status = 403 ;
103- const message = 'API rate limit exceeded' ;
151+ const { result } = renderHook ( ( ) => useNotifications ( ) ) ;
104152
105- nock ( 'https://api.github.com/' )
106- . get ( '/notifications?participating=false' )
107- . reply ( status , { message } ) ;
153+ act ( ( ) => {
154+ result . current . fetchNotifications ( mockAccounts , mockSettings ) ;
155+ } ) ;
108156
109- nock ( 'https://github.gitify.io/api/v3/' )
110- . get ( '/notifications?participating=false' )
111- . reply ( status , { message } ) ;
157+ await waitFor ( ( ) => {
158+ expect ( result . current . requestFailed ) . toBe ( true ) ;
159+ expect ( result . current . errorDetails ) . toBe ( Errors . MISSING_SCOPES ) ;
160+ } ) ;
161+ } ) ;
112162
113- const { result } = renderHook ( ( ) => useNotifications ( ) ) ;
163+ it ( 'rate limited - primary' , async ( ) => {
164+ const code = AxiosError . ERR_BAD_REQUEST ;
165+ const status = 403 ;
166+ const message = 'API rate limit exceeded' ;
167+
168+ nock ( 'https://api.github.com/' )
169+ . get ( '/notifications?participating=false' )
170+ . replyWithError ( {
171+ code,
172+ response : {
173+ status,
174+ data : {
175+ message,
176+ } ,
177+ } ,
178+ } ) ;
179+
180+ nock ( 'https://github.gitify.io/api/v3/' )
181+ . get ( '/notifications?participating=false' )
182+ . replyWithError ( {
183+ code,
184+ response : {
185+ status,
186+ data : {
187+ message,
188+ } ,
189+ } ,
190+ } ) ;
114191
115- act ( ( ) => {
116- result . current . fetchNotifications ( mockAccounts , mockSettings ) ;
192+ const { result } = renderHook ( ( ) => useNotifications ( ) ) ;
193+
194+ act ( ( ) => {
195+ result . current . fetchNotifications ( mockAccounts , mockSettings ) ;
196+ } ) ;
197+
198+ await waitFor ( ( ) => {
199+ expect ( result . current . requestFailed ) . toBe ( true ) ;
200+ expect ( result . current . errorDetails ) . toBe ( Errors . RATE_LIMITED ) ;
201+ } ) ;
117202 } ) ;
118203
119- await waitFor ( ( ) => {
120- expect ( result . current . requestFailed ) . toBe ( true ) ;
121- expect ( result . current . errorDetails ) . toBe ( Errors . RATE_LIMITED ) ;
204+ it ( 'rate limited - secondary' , async ( ) => {
205+ const code = AxiosError . ERR_BAD_REQUEST ;
206+ const status = 403 ;
207+ const message = 'You have exceeded a secondary rate limit' ;
208+
209+ nock ( 'https://api.github.com/' )
210+ . get ( '/notifications?participating=false' )
211+ . replyWithError ( {
212+ code,
213+ response : {
214+ status,
215+ data : {
216+ message,
217+ } ,
218+ } ,
219+ } ) ;
220+
221+ nock ( 'https://github.gitify.io/api/v3/' )
222+ . get ( '/notifications?participating=false' )
223+ . replyWithError ( {
224+ code,
225+ response : {
226+ status,
227+ data : {
228+ message,
229+ } ,
230+ } ,
231+ } ) ;
232+
233+ const { result } = renderHook ( ( ) => useNotifications ( ) ) ;
234+
235+ act ( ( ) => {
236+ result . current . fetchNotifications ( mockAccounts , mockSettings ) ;
237+ } ) ;
238+
239+ await waitFor ( ( ) => {
240+ expect ( result . current . requestFailed ) . toBe ( true ) ;
241+ expect ( result . current . errorDetails ) . toBe ( Errors . RATE_LIMITED ) ;
242+ } ) ;
122243 } ) ;
123- } ) ;
124244
125- it ( 'rate limited - secondary' , async ( ) => {
126- const status = 403 ;
127- const message = 'You have exceeded a secondary rate limit' ;
245+ it ( 'unhandled bad request error' , async ( ) => {
246+ const code = AxiosError . ERR_BAD_REQUEST ;
247+ const status = 400 ;
248+ const message = 'Oops! Something went wrong.' ;
249+
250+ nock ( 'https://api.github.com/' )
251+ . get ( '/notifications?participating=false' )
252+ . replyWithError ( {
253+ code,
254+ response : {
255+ status,
256+ data : {
257+ message,
258+ } ,
259+ } ,
260+ } ) ;
261+
262+ nock ( 'https://github.gitify.io/api/v3/' )
263+ . get ( '/notifications?participating=false' )
264+ . replyWithError ( {
265+ code,
266+ response : {
267+ status,
268+ data : {
269+ message,
270+ } ,
271+ } ,
272+ } ) ;
128273
129- nock ( 'https://api.github.com/' )
130- . get ( '/notifications?participating=false' )
131- . reply ( status , { message } ) ;
274+ const { result } = renderHook ( ( ) => useNotifications ( ) ) ;
132275
133- nock ( 'https://github.gitify.io/api/v3/' )
134- . get ( '/notifications?participating=false' )
135- . reply ( status , { message } ) ;
276+ act ( ( ) => {
277+ result . current . fetchNotifications ( mockAccounts , mockSettings ) ;
278+ } ) ;
136279
137- const { result } = renderHook ( ( ) => useNotifications ( ) ) ;
280+ expect ( result . current . isFetching ) . toBe ( true ) ;
138281
139- act ( ( ) => {
140- result . current . fetchNotifications ( mockAccounts , mockSettings ) ;
141- } ) ;
282+ await waitFor ( ( ) => {
283+ expect ( result . current . isFetching ) . toBe ( false ) ;
284+ } ) ;
142285
143- await waitFor ( ( ) => {
144286 expect ( result . current . requestFailed ) . toBe ( true ) ;
145- expect ( result . current . errorDetails ) . toBe ( Errors . RATE_LIMITED ) ;
146287 } ) ;
147288 } ) ;
148289
149- it ( 'default error' , async ( ) => {
150- const status = 400 ;
151- const message = 'Oops! Something went wrong.' ;
290+ it ( 'unknown error' , async ( ) => {
291+ const code = 'anything' ;
152292
153293 nock ( 'https://api.github.com/' )
154294 . get ( '/notifications?participating=false' )
155- . reply ( status , { message } ) ;
295+ . replyWithError ( {
296+ code : code ,
297+ } ) ;
156298
157299 nock ( 'https://github.gitify.io/api/v3/' )
158300 . get ( '/notifications?participating=false' )
159- . reply ( status , { message } ) ;
301+ . replyWithError ( {
302+ code : code ,
303+ } ) ;
160304
161305 const { result } = renderHook ( ( ) => useNotifications ( ) ) ;
162306
163307 act ( ( ) => {
164308 result . current . fetchNotifications ( mockAccounts , mockSettings ) ;
165309 } ) ;
166310
167- expect ( result . current . isFetching ) . toBe ( true ) ;
168-
169311 await waitFor ( ( ) => {
170- expect ( result . current . isFetching ) . toBe ( false ) ;
312+ expect ( result . current . requestFailed ) . toBe ( true ) ;
313+ expect ( result . current . errorDetails ) . toBe ( Errors . UNKNOWN ) ;
171314 } ) ;
172-
173- expect ( result . current . requestFailed ) . toBe ( true ) ;
174315 } ) ;
175316 } ) ;
176317 } ) ;
0 commit comments