1
1
import { RPCType } from '@opentelemetry/core' ;
2
2
import { ATTR_HTTP_ROUTE } from '@opentelemetry/semantic-conventions' ;
3
3
import {
4
+ flush ,
4
5
getActiveSpan ,
5
6
getRootSpan ,
6
7
getTraceMetaTags ,
7
8
SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ,
8
9
SEMANTIC_ATTRIBUTE_SENTRY_SOURCE ,
10
+ vercelWaitUntil ,
9
11
} from '@sentry/core' ;
10
12
import { PassThrough } from 'stream' ;
11
13
import { beforeEach , describe , expect , test , vi } from 'vitest' ;
@@ -22,13 +24,66 @@ vi.mock('@sentry/core', () => ({
22
24
getActiveSpan : vi . fn ( ) ,
23
25
getRootSpan : vi . fn ( ) ,
24
26
getTraceMetaTags : vi . fn ( ) ,
27
+ flush : vi . fn ( ) ,
28
+ vercelWaitUntil : vi . fn ( ) ,
25
29
} ) ) ;
26
30
27
31
describe ( 'wrapSentryHandleRequest' , ( ) => {
28
32
beforeEach ( ( ) => {
29
33
vi . clearAllMocks ( ) ;
30
34
} ) ;
31
35
36
+ test ( 'should call flush on successful execution' , async ( ) => {
37
+ const originalHandler = vi . fn ( ) . mockResolvedValue ( 'success response' ) ;
38
+ const wrappedHandler = wrapSentryHandleRequest ( originalHandler ) ;
39
+
40
+ const request = new Request ( 'https://example.com' ) ;
41
+ const responseStatusCode = 200 ;
42
+ const responseHeaders = new Headers ( ) ;
43
+ const routerContext = { staticHandlerContext : { matches : [ ] } } as any ;
44
+ const loadContext = { } as any ;
45
+
46
+ await wrappedHandler ( request , responseStatusCode , responseHeaders , routerContext , loadContext ) ;
47
+
48
+ expect ( vercelWaitUntil ) . toHaveBeenCalledWith ( flush ( ) ) ;
49
+ expect ( flush ) . toHaveBeenCalled ( ) ;
50
+ } ) ;
51
+
52
+ test ( 'should call flush even when original handler throws an error' , async ( ) => {
53
+ const mockError = new Error ( 'Handler failed' ) ;
54
+ const originalHandler = vi . fn ( ) . mockRejectedValue ( mockError ) ;
55
+ const wrappedHandler = wrapSentryHandleRequest ( originalHandler ) ;
56
+
57
+ const request = new Request ( 'https://example.com' ) ;
58
+ const responseStatusCode = 200 ;
59
+ const responseHeaders = new Headers ( ) ;
60
+ const routerContext = { staticHandlerContext : { matches : [ ] } } as any ;
61
+ const loadContext = { } as any ;
62
+
63
+ await expect (
64
+ wrappedHandler ( request , responseStatusCode , responseHeaders , routerContext , loadContext ) ,
65
+ ) . rejects . toThrow ( 'Handler failed' ) ;
66
+
67
+ expect ( vercelWaitUntil ) . toHaveBeenCalledWith ( flush ( ) ) ;
68
+ expect ( flush ) . toHaveBeenCalled ( ) ;
69
+ } ) ;
70
+
71
+ test ( 'should propagate errors from original handler' , async ( ) => {
72
+ const mockError = new Error ( 'Test error' ) ;
73
+ const originalHandler = vi . fn ( ) . mockRejectedValue ( mockError ) ;
74
+ const wrappedHandler = wrapSentryHandleRequest ( originalHandler ) ;
75
+
76
+ const request = new Request ( 'https://example.com' ) ;
77
+ const responseStatusCode = 500 ;
78
+ const responseHeaders = new Headers ( ) ;
79
+ const routerContext = { staticHandlerContext : { matches : [ ] } } as any ;
80
+ const loadContext = { } as any ;
81
+
82
+ await expect ( wrappedHandler ( request , responseStatusCode , responseHeaders , routerContext , loadContext ) ) . rejects . toBe (
83
+ mockError ,
84
+ ) ;
85
+ } ) ;
86
+
32
87
test ( 'should call original handler with same parameters' , async ( ) => {
33
88
const originalHandler = vi . fn ( ) . mockResolvedValue ( 'original response' ) ;
34
89
const wrappedHandler = wrapSentryHandleRequest ( originalHandler ) ;
@@ -62,7 +117,8 @@ describe('wrapSentryHandleRequest', () => {
62
117
( getActiveSpan as unknown as ReturnType < typeof vi . fn > ) . mockReturnValue ( mockActiveSpan ) ;
63
118
( getRootSpan as unknown as ReturnType < typeof vi . fn > ) . mockReturnValue ( mockRootSpan ) ;
64
119
const getRPCMetadata = vi . fn ( ) . mockReturnValue ( mockRpcMetadata ) ;
65
- vi . mocked ( vi . importActual ( '@opentelemetry/core' ) ) . getRPCMetadata = getRPCMetadata ;
120
+ ( vi . importActual ( '@opentelemetry/core' ) as unknown as { getRPCMetadata : typeof getRPCMetadata } ) . getRPCMetadata =
121
+ getRPCMetadata ;
66
122
67
123
const routerContext = {
68
124
staticHandlerContext : {
@@ -110,7 +166,8 @@ describe('wrapSentryHandleRequest', () => {
110
166
( getActiveSpan as unknown as ReturnType < typeof vi . fn > ) . mockReturnValue ( null ) ;
111
167
112
168
const getRPCMetadata = vi . fn ( ) . mockReturnValue ( mockRpcMetadata ) ;
113
- vi . mocked ( vi . importActual ( '@opentelemetry/core' ) ) . getRPCMetadata = getRPCMetadata ;
169
+ ( vi . importActual ( '@opentelemetry/core' ) as unknown as { getRPCMetadata : typeof getRPCMetadata } ) . getRPCMetadata =
170
+ getRPCMetadata ;
114
171
115
172
const routerContext = {
116
173
staticHandlerContext : {
@@ -132,7 +189,7 @@ describe('getMetaTagTransformer', () => {
132
189
) ;
133
190
} ) ;
134
191
135
- test ( 'should inject meta tags before closing head tag' , done => {
192
+ test ( 'should inject meta tags before closing head tag' , ( ) => {
136
193
const outputStream = new PassThrough ( ) ;
137
194
const bodyStream = new PassThrough ( ) ;
138
195
const transformer = getMetaTagTransformer ( bodyStream ) ;
@@ -145,7 +202,6 @@ describe('getMetaTagTransformer', () => {
145
202
outputStream . on ( 'end' , ( ) => {
146
203
expect ( outputData ) . toContain ( '<meta name="sentry-trace" content="test-trace-id"></head>' ) ;
147
204
expect ( outputData ) . not . toContain ( '</head></head>' ) ;
148
- done ( ) ;
149
205
} ) ;
150
206
151
207
transformer . pipe ( outputStream ) ;
@@ -154,7 +210,7 @@ describe('getMetaTagTransformer', () => {
154
210
bodyStream . end ( ) ;
155
211
} ) ;
156
212
157
- test ( 'should not modify chunks without head closing tag' , done => {
213
+ test ( 'should not modify chunks without head closing tag' , ( ) => {
158
214
const outputStream = new PassThrough ( ) ;
159
215
const bodyStream = new PassThrough ( ) ;
160
216
const transformer = getMetaTagTransformer ( bodyStream ) ;
@@ -167,7 +223,6 @@ describe('getMetaTagTransformer', () => {
167
223
outputStream . on ( 'end' , ( ) => {
168
224
expect ( outputData ) . toBe ( '<html><body>Test</body></html>' ) ;
169
225
expect ( getTraceMetaTags ) . toHaveBeenCalled ( ) ;
170
- done ( ) ;
171
226
} ) ;
172
227
173
228
transformer . pipe ( outputStream ) ;
@@ -176,7 +231,7 @@ describe('getMetaTagTransformer', () => {
176
231
bodyStream . end ( ) ;
177
232
} ) ;
178
233
179
- test ( 'should handle buffer input' , done => {
234
+ test ( 'should handle buffer input' , ( ) => {
180
235
const outputStream = new PassThrough ( ) ;
181
236
const bodyStream = new PassThrough ( ) ;
182
237
const transformer = getMetaTagTransformer ( bodyStream ) ;
@@ -188,7 +243,6 @@ describe('getMetaTagTransformer', () => {
188
243
189
244
outputStream . on ( 'end' , ( ) => {
190
245
expect ( outputData ) . toContain ( '<meta name="sentry-trace" content="test-trace-id"></head>' ) ;
191
- done ( ) ;
192
246
} ) ;
193
247
194
248
transformer . pipe ( outputStream ) ;
0 commit comments