@@ -58,18 +58,24 @@ describe("authenticated fetch bearer validation", () => {
5858 let originalFetch : typeof globalThis . fetch ;
5959 let requests : { url : string ; authorization : string | null } [ ] ;
6060
61+ /** Mock responses while recording the actual request URL and Authorization. */
62+ function mockResponses (
63+ respond : ( url : string , authorization : string | null ) => Response
64+ ) : typeof fetch {
65+ return mockFetch ( ( input , init ) => {
66+ const url = extractFetchUrl ( input ) ;
67+ const authorization = new Headers ( init ?. headers ) . get ( "Authorization" ) ;
68+ requests . push ( { url, authorization } ) ;
69+ return Promise . resolve ( respond ( url , authorization ) ) ;
70+ } ) ;
71+ }
72+
6173 beforeEach ( async ( ) => {
6274 await resetHostScopingState ( ) ;
6375 resetAuthenticatedFetch ( ) ;
6476 originalFetch = globalThis . fetch ;
6577 requests = [ ] ;
66- globalThis . fetch = mockFetch ( ( input , init ) => {
67- requests . push ( {
68- url : extractFetchUrl ( input ) ,
69- authorization : new Headers ( init ?. headers ) . get ( "Authorization" ) ,
70- } ) ;
71- return Promise . resolve ( new Response ( "{}" , { status : 200 } ) ) ;
72- } ) ;
78+ globalThis . fetch = mockResponses ( ( ) => new Response ( "{}" , { status : 200 } ) ) ;
7379 } ) ;
7480
7581 afterEach ( async ( ) => {
@@ -220,23 +226,17 @@ describe("authenticated fetch bearer validation", () => {
220226
221227 test ( "stores Vary: Authorization with the credential actually sent" , async ( ) => {
222228 storeLegacyToken ( "\x1fsynthetic-token\x7f" ) ;
223- globalThis . fetch = mockFetch ( ( input , init ) => {
224- requests . push ( {
225- url : extractFetchUrl ( input ) ,
226- authorization : new Headers ( init ?. headers ) . get ( "Authorization" ) ,
227- } ) ;
228- return Promise . resolve (
229- Response . json (
230- { source : "network" } ,
231- {
232- headers : {
233- "Cache-Control" : "private, max-age=300" ,
234- Vary : "Authorization" ,
235- } ,
236- }
237- )
238- ) ;
239- } ) ;
229+ globalThis . fetch = mockResponses ( ( ) =>
230+ Response . json (
231+ { source : "network" } ,
232+ {
233+ headers : {
234+ "Cache-Control" : "private, max-age=300" ,
235+ Vary : "Authorization" ,
236+ } ,
237+ }
238+ )
239+ ) ;
240240
241241 await request ( ) ;
242242
@@ -260,7 +260,7 @@ describe("authenticated fetch bearer validation", () => {
260260 url : "https://other-sentry.example.com" ,
261261 org : "synthetic-org" ,
262262 } ) ;
263- setAuthToken ( ` \n${ token } \t ` ) ;
263+ storeLegacyToken ( ` \n${ token } \t ` ) ;
264264 await expect ( request ( ) ) . rejects . toBeInstanceOf ( HostScopeError ) ;
265265 expect ( requests ) . toEqual ( [ ] ) ;
266266 } ) ;
@@ -319,24 +319,17 @@ describe("authenticated fetch bearer validation", () => {
319319 ] ) ( "retries with a normalized valid refreshed bearer %#" , async ( token ) => {
320320 process . env . SENTRY_CLIENT_ID = "synthetic-client-id" ;
321321 setAuthToken ( "stored-token" , 3600 , "synthetic-refresh-token" ) ;
322- globalThis . fetch = mockFetch ( ( input , init ) => {
323- const url = extractFetchUrl ( input ) ;
324- const authorization = new Headers ( init ?. headers ) . get ( "Authorization" ) ;
325- requests . push ( { url, authorization } ) ;
322+ globalThis . fetch = mockResponses ( ( url , authorization ) => {
326323 if ( url . endsWith ( "/oauth/token/" ) ) {
327- return Promise . resolve (
328- Response . json ( {
329- access_token : token ,
330- token_type : "bearer" ,
331- expires_in : 3600 ,
332- } )
333- ) ;
324+ return Response . json ( {
325+ access_token : token ,
326+ token_type : "bearer" ,
327+ expires_in : 3600 ,
328+ } ) ;
334329 }
335- return Promise . resolve (
336- new Response ( "{}" , {
337- status : authorization === "Bearer stored-token" ? 401 : 200 ,
338- } )
339- ) ;
330+ return new Response ( "{}" , {
331+ status : authorization === "Bearer stored-token" ? 401 : 200 ,
332+ } ) ;
340333 } ) ;
341334
342335 expect ( ( await request ( ) ) . status ) . toBe ( 200 ) ;
@@ -357,23 +350,16 @@ describe("authenticated fetch bearer validation", () => {
357350 ] ) ( "rejects malformed refreshed credentials without retrying the request %#" , async ( token ) => {
358351 process . env . SENTRY_CLIENT_ID = "synthetic-client-id" ;
359352 setAuthToken ( "stored-token" , 3600 , "synthetic-refresh-token" ) ;
360- globalThis . fetch = mockFetch ( ( input , init ) => {
361- const url = extractFetchUrl ( input ) ;
362- requests . push ( {
363- url,
364- authorization : new Headers ( init ?. headers ) . get ( "Authorization" ) ,
365- } ) ;
353+ globalThis . fetch = mockResponses ( ( url ) => {
366354 if ( url . endsWith ( "/oauth/token/" ) ) {
367- return Promise . resolve (
368- Response . json ( {
369- access_token : token ,
370- token_type : "bearer" ,
371- expires_in : 3600 ,
372- refresh_token : "synthetic-refresh-token" ,
373- } )
374- ) ;
355+ return Response . json ( {
356+ access_token : token ,
357+ token_type : "bearer" ,
358+ expires_in : 3600 ,
359+ refresh_token : "synthetic-refresh-token" ,
360+ } ) ;
375361 }
376- return Promise . resolve ( new Response ( "{}" , { status : 401 } ) ) ;
362+ return new Response ( "{}" , { status : 401 } ) ;
377363 } ) ;
378364
379365 for ( let attempt = 0 ; attempt < 2 ; attempt ++ ) {
@@ -408,23 +394,16 @@ describe("authenticated fetch bearer validation", () => {
408394 process . env [ source ] = MALFORMED_TOKEN ;
409395 }
410396 setAuthToken ( "expired-token" , - 1 , "synthetic-refresh-token" ) ;
411- globalThis . fetch = mockFetch ( ( input , init ) => {
412- const url = extractFetchUrl ( input ) ;
413- requests . push ( {
414- url,
415- authorization : new Headers ( init ?. headers ) . get ( "Authorization" ) ,
416- } ) ;
417- return Promise . resolve (
418- url . endsWith ( "/oauth/token/" )
419- ? Response . json ( {
420- access_token : "\x1f \nrefreshed-token\r\t\x7f" ,
421- token_type : "bearer" ,
422- expires_in : 3600 ,
423- refresh_token : "replacement-refresh-token" ,
424- } )
425- : Response . json ( { } )
426- ) ;
427- } ) ;
397+ globalThis . fetch = mockResponses ( ( url ) =>
398+ url . endsWith ( "/oauth/token/" )
399+ ? Response . json ( {
400+ access_token : "\x1f \nrefreshed-token\r\t\x7f" ,
401+ token_type : "bearer" ,
402+ expires_in : 3600 ,
403+ refresh_token : "replacement-refresh-token" ,
404+ } )
405+ : Response . json ( { } )
406+ ) ;
428407
429408 expect ( ( await request ( ) ) . status ) . toBe ( 200 ) ;
430409 expect ( getAuthConfig ( ) ) . toMatchObject ( {
@@ -440,20 +419,14 @@ describe("authenticated fetch bearer validation", () => {
440419 test ( "rejects malformed proactive refresh before storing or using the token" , async ( ) => {
441420 process . env . SENTRY_CLIENT_ID = "synthetic-client-id" ;
442421 setAuthToken ( "expired-token" , - 1 , "synthetic-refresh-token" ) ;
443- globalThis . fetch = mockFetch ( ( input , init ) => {
444- requests . push ( {
445- url : extractFetchUrl ( input ) ,
446- authorization : new Headers ( init ?. headers ) . get ( "Authorization" ) ,
447- } ) ;
448- return Promise . resolve (
449- Response . json ( {
450- access_token : "opaque-\0-secret-tail" ,
451- token_type : "bearer" ,
452- expires_in : 3600 ,
453- refresh_token : "replacement-refresh-token" ,
454- } )
455- ) ;
456- } ) ;
422+ globalThis . fetch = mockResponses ( ( ) =>
423+ Response . json ( {
424+ access_token : "opaque-\0-secret-tail" ,
425+ token_type : "bearer" ,
426+ expires_in : 3600 ,
427+ refresh_token : "replacement-refresh-token" ,
428+ } )
429+ ) ;
457430
458431 await expect ( request ( ) ) . rejects . toMatchObject ( {
459432 reason : "invalid" ,
0 commit comments