@@ -2,174 +2,15 @@ import * as sentryCore from '@sentry/core';
22import  *  as  sentryHub  from  '@sentry/hub' ; 
33import  {  Hub  }  from  '@sentry/hub' ; 
44import  {  Transaction  }  from  '@sentry/tracing' ; 
5- import  {  Baggage  }  from  '@sentry/types' ; 
5+ import  {  Baggage ,   Event  }  from  '@sentry/types' ; 
66import  {  SentryError  }  from  '@sentry/utils' ; 
77import  *  as  http  from  'http' ; 
8- import  *  as  net  from  'net' ; 
98
10- import  {  Event ,  Request ,  User  }  from  '../src' ; 
119import  {  NodeClient  }  from  '../src/client' ; 
12- import  { 
13-   errorHandler , 
14-   ExpressRequest , 
15-   extractRequestData , 
16-   parseRequest , 
17-   requestHandler , 
18-   tracingHandler , 
19- }  from  '../src/handlers' ; 
10+ import  {  errorHandler ,  requestHandler ,  tracingHandler  }  from  '../src/handlers' ; 
2011import  *  as  SDK  from  '../src/sdk' ; 
2112import  {  getDefaultNodeClientOptions  }  from  './helper/node-client-options' ; 
2213
23- describe ( 'parseRequest' ,  ( )  =>  { 
24-   let  mockReq : {  [ key : string ] : any  } ; 
25- 
26-   beforeEach ( ( )  =>  { 
27-     mockReq  =  { 
28-       baseUrl : '/routerMountPath' , 
29-       body : 'foo' , 
30-       cookies : {  test : 'test'  } , 
31-       headers : { 
32-         host : 'mattrobenolt.com' , 
33-       } , 
34-       method : 'POST' , 
35-       originalUrl : '/routerMountPath/subpath/specificValue?querystringKey=querystringValue' , 
36-       path : '/subpath/specificValue' , 
37-       query : { 
38-         querystringKey : 'querystringValue' , 
39-       } , 
40-       route : { 
41-         path : '/subpath/:parameterName' , 
42-         stack : [ 
43-           { 
44-             name : 'parameterNameRouteHandler' , 
45-           } , 
46-         ] , 
47-       } , 
48-       url : '/subpath/specificValue?querystringKey=querystringValue' , 
49-       user : { 
50-         custom_property : 'foo' , 
51- 52-         id : 123 , 
53-         username : 'tobias' , 
54-       } , 
55-     } ; 
56-   } ) ; 
57- 
58-   describe ( 'parseRequest.user properties' ,  ( )  =>  { 
59-     const  DEFAULT_USER_KEYS  =  [ 'id' ,  'username' ,  'email' ] ; 
60-     const  CUSTOM_USER_KEYS  =  [ 'custom_property' ] ; 
61- 
62-     test ( 'parseRequest.user only contains the default properties from the user' ,  ( )  =>  { 
63-       const  parsedRequest : Event  =  parseRequest ( { } ,  mockReq  as  ExpressRequest ) ; 
64-       expect ( Object . keys ( parsedRequest . user  as  User ) ) . toEqual ( DEFAULT_USER_KEYS ) ; 
65-     } ) ; 
66- 
67-     test ( 'parseRequest.user only contains the custom properties specified in the options.user array' ,  ( )  =>  { 
68-       const  parsedRequest : Event  =  parseRequest ( { } ,  mockReq  as  ExpressRequest ,  { 
69-         user : CUSTOM_USER_KEYS , 
70-       } ) ; 
71-       expect ( Object . keys ( parsedRequest . user  as  User ) ) . toEqual ( CUSTOM_USER_KEYS ) ; 
72-     } ) ; 
73- 
74-     test ( 'parseRequest.user doesnt blow up when someone passes non-object value' ,  ( )  =>  { 
75-       const  parsedRequest : Event  =  parseRequest ( 
76-         { } , 
77-         { 
78-           ...mockReq , 
79-           // @ts -ignore user is not assignable to object 
80-           user : 'wat' , 
81-         } , 
82-       ) ; 
83-       expect ( Object . keys ( parsedRequest . user  as  User ) ) . toEqual ( [ ] ) ; 
84-     } ) ; 
85-   } ) ; 
86- 
87-   describe ( 'parseRequest.ip property' ,  ( )  =>  { 
88-     test ( 'can be extracted from req.ip' ,  ( )  =>  { 
89-       const  parsedRequest : Event  =  parseRequest ( 
90-         { } , 
91-         { 
92-           ...mockReq , 
93-           ip : '123' , 
94-         }  as  ExpressRequest , 
95-         { 
96-           ip : true , 
97-         } , 
98-       ) ; 
99-       expect ( parsedRequest . user ! . ip_address ) . toEqual ( '123' ) ; 
100-     } ) ; 
101- 
102-     test ( 'can extract from req.connection.remoteAddress' ,  ( )  =>  { 
103-       const  parsedRequest : Event  =  parseRequest ( 
104-         { } , 
105-         { 
106-           ...mockReq , 
107-           connection : { 
108-             remoteAddress : '321' , 
109-           }  as  net . Socket , 
110-         }  as  ExpressRequest , 
111-         { 
112-           ip : true , 
113-         } , 
114-       ) ; 
115-       expect ( parsedRequest . user ! . ip_address ) . toEqual ( '321' ) ; 
116-     } ) ; 
117-   } ) ; 
118- 
119-   describe ( 'parseRequest.request properties' ,  ( )  =>  { 
120-     test ( 'parseRequest.request only contains the default set of properties from the request' ,  ( )  =>  { 
121-       const  DEFAULT_REQUEST_PROPERTIES  =  [ 'cookies' ,  'data' ,  'headers' ,  'method' ,  'query_string' ,  'url' ] ; 
122-       const  parsedRequest : Event  =  parseRequest ( { } ,  mockReq  as  ExpressRequest ) ; 
123-       expect ( Object . keys ( parsedRequest . request  as  Request ) ) . toEqual ( DEFAULT_REQUEST_PROPERTIES ) ; 
124-     } ) ; 
125- 
126-     test ( 'parseRequest.request only contains the specified properties in the options.request array' ,  ( )  =>  { 
127-       const  INCLUDED_PROPERTIES  =  [ 'data' ,  'headers' ,  'query_string' ,  'url' ] ; 
128-       const  parsedRequest : Event  =  parseRequest ( { } ,  mockReq  as  ExpressRequest ,  { 
129-         request : INCLUDED_PROPERTIES , 
130-       } ) ; 
131-       expect ( Object . keys ( parsedRequest . request  as  Request ) ) . toEqual ( INCLUDED_PROPERTIES ) ; 
132-     } ) ; 
133- 
134-     test ( 'parseRequest.request skips `body` property for GET and HEAD requests' ,  ( )  =>  { 
135-       expect ( parseRequest ( { } ,  mockReq  as  ExpressRequest ,  { } ) . request ) . toHaveProperty ( 'data' ) ; 
136-       expect ( parseRequest ( { } ,  {  ...mockReq ,  method : 'GET'  }  as  ExpressRequest ,  { } ) . request ) . not . toHaveProperty ( 'data' ) ; 
137-       expect ( parseRequest ( { } ,  {  ...mockReq ,  method : 'HEAD'  }  as  ExpressRequest ,  { } ) . request ) . not . toHaveProperty ( 'data' ) ; 
138-     } ) ; 
139-   } ) ; 
140- 
141-   describe ( 'parseRequest.transaction property' ,  ( )  =>  { 
142-     test ( 'extracts method and full route path by default`' ,  ( )  =>  { 
143-       const  parsedRequest : Event  =  parseRequest ( { } ,  mockReq  as  ExpressRequest ) ; 
144-       expect ( parsedRequest . transaction ) . toEqual ( 'POST /routerMountPath/subpath/:parameterName' ) ; 
145-     } ) ; 
146- 
147-     test ( 'extracts method and full path by default when mountpoint is `/`' ,  ( )  =>  { 
148-       mockReq . originalUrl  =  mockReq . originalUrl . replace ( '/routerMountpath' ,  '' ) ; 
149-       mockReq . baseUrl  =  '' ; 
150-       const  parsedRequest : Event  =  parseRequest ( { } ,  mockReq  as  ExpressRequest ) ; 
151-       // "sub"path is the full path here, because there's no router mount path 
152-       expect ( parsedRequest . transaction ) . toEqual ( 'POST /subpath/:parameterName' ) ; 
153-     } ) ; 
154- 
155-     test ( 'fallback to method and `originalUrl` if route is missing' ,  ( )  =>  { 
156-       delete  mockReq . route ; 
157-       const  parsedRequest : Event  =  parseRequest ( { } ,  mockReq  as  ExpressRequest ) ; 
158-       expect ( parsedRequest . transaction ) . toEqual ( 'POST /routerMountPath/subpath/specificValue' ) ; 
159-     } ) ; 
160- 
161-     test ( 'can extract path only instead if configured' ,  ( )  =>  { 
162-       const  parsedRequest : Event  =  parseRequest ( { } ,  mockReq  as  ExpressRequest ,  {  transaction : 'path'  } ) ; 
163-       expect ( parsedRequest . transaction ) . toEqual ( '/routerMountPath/subpath/:parameterName' ) ; 
164-     } ) ; 
165- 
166-     test ( 'can extract handler name instead if configured' ,  ( )  =>  { 
167-       const  parsedRequest : Event  =  parseRequest ( { } ,  mockReq  as  ExpressRequest ,  {  transaction : 'handler'  } ) ; 
168-       expect ( parsedRequest . transaction ) . toEqual ( 'parameterNameRouteHandler' ) ; 
169-     } ) ; 
170-   } ) ; 
171- } ) ; 
172- 
17314describe ( 'requestHandler' ,  ( )  =>  { 
17415  const  headers  =  {  ears : 'furry' ,  nose : 'wet' ,  tongue : 'spotted' ,  cookie : 'favorite=zukes'  } ; 
17516  const  method  =  'wagging' ; 
@@ -270,7 +111,7 @@ describe('requestHandler', () => {
270111    } ) ; 
271112  } ) ; 
272113
273-   it ( 'patches `res.end` when `flushTimeout` is specified' ,  ( )  =>  { 
114+   it ( 'patches `res.end` when `flushTimeout` is specified' ,  done  =>  { 
274115    const  flush  =  jest . spyOn ( SDK ,  'flush' ) . mockResolvedValue ( true ) ; 
275116
276117    const  sentryRequestMiddleware  =  requestHandler ( {  flushTimeout : 1337  } ) ; 
@@ -280,10 +121,11 @@ describe('requestHandler', () => {
280121    setImmediate ( ( )  =>  { 
281122      expect ( flush ) . toHaveBeenCalledWith ( 1337 ) ; 
282123      expect ( res . finished ) . toBe ( true ) ; 
124+       done ( ) ; 
283125    } ) ; 
284126  } ) ; 
285127
286-   it ( 'prevents errors thrown during `flush` from breaking the response' ,  async   ( )  =>  { 
128+   it ( 'prevents errors thrown during `flush` from breaking the response' ,  done  =>  { 
287129    jest . spyOn ( SDK ,  'flush' ) . mockRejectedValue ( new  SentryError ( 'HTTP Error (429)' ) ) ; 
288130
289131    const  sentryRequestMiddleware  =  requestHandler ( {  flushTimeout : 1337  } ) ; 
@@ -292,6 +134,7 @@ describe('requestHandler', () => {
292134
293135    setImmediate ( ( )  =>  { 
294136      expect ( res . finished ) . toBe ( true ) ; 
137+       done ( ) ; 
295138    } ) ; 
296139  } ) ; 
297140} ) ; 
@@ -530,181 +373,6 @@ describe('tracingHandler', () => {
530373  } ) ; 
531374} ) ; 
532375
533- describe ( 'extractRequestData()' ,  ( )  =>  { 
534-   describe ( 'default behaviour' ,  ( )  =>  { 
535-     test ( 'node' ,  ( )  =>  { 
536-       expect ( 
537-         extractRequestData ( { 
538-           headers : {  host : 'example.com'  } , 
539-           method : 'GET' , 
540-           secure : true , 
541-           originalUrl : '/' , 
542-         } ) , 
543-       ) . toEqual ( { 
544-         cookies : { } , 
545-         headers : { 
546-           host : 'example.com' , 
547-         } , 
548-         method : 'GET' , 
549-         query_string : null , 
550-         url : 'https://example.com/' , 
551-       } ) ; 
552-     } ) ; 
553- 
554-     test ( 'degrades gracefully without request data' ,  ( )  =>  { 
555-       expect ( extractRequestData ( { } ) ) . toEqual ( { 
556-         cookies : { } , 
557-         headers : { } , 
558-         method : undefined , 
559-         query_string : null , 
560-         url : 'http://<no host>' , 
561-       } ) ; 
562-     } ) ; 
563-   } ) ; 
564- 
565-   describe ( 'cookies' ,  ( )  =>  { 
566-     it ( 'uses `req.cookies` if available' ,  ( )  =>  { 
567-       expect ( 
568-         extractRequestData ( 
569-           { 
570-             cookies : {  foo : 'bar'  } , 
571-           } , 
572-           [ 'cookies' ] , 
573-         ) , 
574-       ) . toEqual ( { 
575-         cookies : {  foo : 'bar'  } , 
576-       } ) ; 
577-     } ) ; 
578- 
579-     it ( 'parses the cookie header' ,  ( )  =>  { 
580-       expect ( 
581-         extractRequestData ( 
582-           { 
583-             headers : { 
584-               cookie : 'foo=bar;' , 
585-             } , 
586-           } , 
587-           [ 'cookies' ] , 
588-         ) , 
589-       ) . toEqual ( { 
590-         cookies : {  foo : 'bar'  } , 
591-       } ) ; 
592-     } ) ; 
593- 
594-     it ( 'falls back if no cookies are defined' ,  ( )  =>  { 
595-       expect ( extractRequestData ( { } ,  [ 'cookies' ] ) ) . toEqual ( { 
596-         cookies : { } , 
597-       } ) ; 
598-     } ) ; 
599-   } ) ; 
600- 
601-   describe ( 'data' ,  ( )  =>  { 
602-     it ( 'includes data from `req.body` if available' ,  ( )  =>  { 
603-       expect ( 
604-         extractRequestData ( 
605-           { 
606-             method : 'POST' , 
607-             headers : {  'Content-Type' : 'application/x-www-form-urlencoded'  } , 
608-             body : 'foo=bar' , 
609-           } , 
610-           [ 'data' ] , 
611-         ) , 
612-       ) . toEqual ( { 
613-         data : 'foo=bar' , 
614-       } ) ; 
615-     } ) ; 
616- 
617-     it ( 'encodes JSON body contents back to a string' ,  ( )  =>  { 
618-       expect ( 
619-         extractRequestData ( 
620-           { 
621-             method : 'POST' , 
622-             headers : {  'Content-Type' : 'application/json'  } , 
623-             body : {  foo : 'bar'  } , 
624-           } , 
625-           [ 'data' ] , 
626-         ) , 
627-       ) . toEqual ( { 
628-         data : '{"foo":"bar"}' , 
629-       } ) ; 
630-     } ) ; 
631-   } ) ; 
632- 
633-   describe ( 'query_string' ,  ( )  =>  { 
634-     it ( 'parses the query parms from the url' ,  ( )  =>  { 
635-       expect ( 
636-         extractRequestData ( 
637-           { 
638-             headers : {  host : 'example.com'  } , 
639-             secure : true , 
640-             originalUrl : '/?foo=bar' , 
641-           } , 
642-           [ 'query_string' ] , 
643-         ) , 
644-       ) . toEqual ( { 
645-         query_string : 'foo=bar' , 
646-       } ) ; 
647-     } ) ; 
648- 
649-     it ( 'gracefully degrades if url cannot be determined' ,  ( )  =>  { 
650-       expect ( extractRequestData ( { } ,  [ 'query_string' ] ) ) . toEqual ( { 
651-         query_string : null , 
652-       } ) ; 
653-     } ) ; 
654-   } ) ; 
655- 
656-   describe ( 'url' ,  ( )  =>  { 
657-     test ( 'express/koa' ,  ( )  =>  { 
658-       expect ( 
659-         extractRequestData ( 
660-           { 
661-             host : 'example.com' , 
662-             protocol : 'https' , 
663-             url : '/' , 
664-           } , 
665-           [ 'url' ] , 
666-         ) , 
667-       ) . toEqual ( { 
668-         url : 'https://example.com/' , 
669-       } ) ; 
670-     } ) ; 
671- 
672-     test ( 'node' ,  ( )  =>  { 
673-       expect ( 
674-         extractRequestData ( 
675-           { 
676-             headers : {  host : 'example.com'  } , 
677-             secure : true , 
678-             originalUrl : '/' , 
679-           } , 
680-           [ 'url' ] , 
681-         ) , 
682-       ) . toEqual ( { 
683-         url : 'https://example.com/' , 
684-       } ) ; 
685-     } ) ; 
686-   } ) ; 
687- 
688-   describe ( 'custom key' ,  ( )  =>  { 
689-     it ( 'includes the custom key if present' ,  ( )  =>  { 
690-       expect ( 
691-         extractRequestData ( 
692-           { 
693-             httpVersion : '1.1' , 
694-           } , 
695-           [ 'httpVersion' ] , 
696-         ) , 
697-       ) . toEqual ( { 
698-         httpVersion : '1.1' , 
699-       } ) ; 
700-     } ) ; 
701- 
702-     it ( 'gracefully degrades if the custom key is missing' ,  ( )  =>  { 
703-       expect ( extractRequestData ( { } ,  [ 'httpVersion' ] ) ) . toEqual ( { } ) ; 
704-     } ) ; 
705-   } ) ; 
706- } ) ; 
707- 
708376describe ( 'errorHandler()' ,  ( )  =>  { 
709377  const  headers  =  {  ears : 'furry' ,  nose : 'wet' ,  tongue : 'spotted' ,  cookie : 'favorite=zukes'  } ; 
710378  const  method  =  'wagging' ; 
0 commit comments