@@ -3,11 +3,18 @@ import type { IncomingMessage, ServerResponse } from 'node:http'
3
3
import { Buffer } from 'node:buffer'
4
4
import { Readable } from 'node:stream'
5
5
import { isAsyncIteratorObject } from '@orpc/shared'
6
+ import * as StandardServerModule from '@orpc/standard-server'
6
7
import request from 'supertest'
7
8
import { toNodeHttpBody , toStandardBody } from './body'
8
9
import * as EventIteratorModule from './event-iterator'
9
10
10
11
const toEventStreamSpy = vi . spyOn ( EventIteratorModule , 'toEventStream' )
12
+ const generateContentDispositionSpy = vi . spyOn ( StandardServerModule , 'generateContentDisposition' )
13
+ const getFilenameFromContentDispositionSpy = vi . spyOn ( StandardServerModule , 'getFilenameFromContentDisposition' )
14
+
15
+ beforeEach ( ( ) => {
16
+ vi . clearAllMocks ( )
17
+ } )
11
18
12
19
describe ( 'toStandardBody' , ( ) => {
13
20
it ( 'undefined' , async ( ) => {
@@ -131,31 +138,60 @@ describe('toStandardBody', () => {
131
138
expect ( standardBody . name ) . toBe ( 'blob' )
132
139
expect ( standardBody . type ) . toBe ( 'application/pdf' )
133
140
expect ( await standardBody . text ( ) ) . toBe ( 'foo' )
141
+
142
+ expect ( getFilenameFromContentDispositionSpy ) . toHaveBeenCalledTimes ( 0 )
134
143
} )
135
144
136
145
it ( 'file' , async ( ) => {
137
146
let standardBody : any
138
147
148
+ getFilenameFromContentDispositionSpy . mockReturnValue ( '__name__' )
149
+
139
150
await request ( async ( req : IncomingMessage , res : ServerResponse ) => {
140
151
standardBody = await toStandardBody ( req )
141
152
res . end ( )
142
153
} )
143
154
. delete ( '/' )
144
- . type ( 'application/pdf ' )
155
+ . type ( 'application/json ' )
145
156
. set ( 'content-disposition' , 'attachment; filename="foo.pdf"' )
146
- . send ( Buffer . from ( 'foo' ) )
157
+ . send ( { value : 123 } )
147
158
148
159
expect ( standardBody ) . toBeInstanceOf ( File )
149
- expect ( standardBody . name ) . toBe ( 'foo.pdf' )
150
- expect ( standardBody . type ) . toBe ( 'application/pdf' )
151
- expect ( await standardBody . text ( ) ) . toBe ( 'foo' )
160
+ expect ( standardBody . name ) . toBe ( '__name__' )
161
+ expect ( standardBody . type ) . toBe ( 'application/json' )
162
+ expect ( await standardBody . text ( ) ) . toBe ( '{"value":123}' )
163
+
164
+ expect ( getFilenameFromContentDispositionSpy ) . toHaveBeenCalledTimes ( 1 )
165
+ expect ( getFilenameFromContentDispositionSpy ) . toHaveBeenCalledWith ( 'attachment; filename="foo.pdf"' )
166
+ } )
167
+
168
+ it ( 'file with content-disposition (no filename)' , async ( ) => {
169
+ let standardBody : any
170
+
171
+ getFilenameFromContentDispositionSpy . mockReturnValue ( undefined )
172
+
173
+ await request ( async ( req : IncomingMessage , res : ServerResponse ) => {
174
+ standardBody = await toStandardBody ( req )
175
+ res . end ( )
176
+ } )
177
+ . delete ( '/' )
178
+ . type ( 'application/json' )
179
+ . set ( 'content-disposition' , 'attachment' )
180
+ . send ( { value : 123 } )
181
+
182
+ expect ( standardBody ) . toBeInstanceOf ( File )
183
+ expect ( standardBody . name ) . toBe ( 'blob' )
184
+ expect ( standardBody . type ) . toBe ( 'application/json' )
185
+ expect ( await standardBody . text ( ) ) . toBe ( '{"value":123}' )
186
+
187
+ expect ( getFilenameFromContentDispositionSpy ) . toHaveBeenCalledTimes ( 1 )
188
+ expect ( getFilenameFromContentDispositionSpy ) . toHaveBeenCalledWith ( 'attachment' )
152
189
} )
153
190
} )
154
191
155
192
describe ( 'toNodeHttpBody' , ( ) => {
156
193
const baseHeaders = {
157
194
'content-type' : 'application/json' ,
158
- 'content-disposition' : 'attachment; filename="foo.pdf"' ,
159
195
'x-custom-header' : 'custom-value' ,
160
196
}
161
197
@@ -220,16 +256,21 @@ describe('toNodeHttpBody', () => {
220
256
const headers = { ...baseHeaders }
221
257
const blob = new Blob ( [ 'foo' ] , { type : 'application/pdf' } )
222
258
259
+ generateContentDispositionSpy . mockReturnValue ( '__mocked__' )
260
+
223
261
const body = toNodeHttpBody ( blob , headers , { } )
224
262
225
263
expect ( body ) . toBeInstanceOf ( Readable )
226
264
expect ( headers ) . toEqual ( {
227
- 'content-disposition' : 'inline; filename="blob" ' ,
265
+ 'content-disposition' : '__mocked__ ' ,
228
266
'content-length' : '3' ,
229
267
'content-type' : 'application/pdf' ,
230
268
'x-custom-header' : 'custom-value' ,
231
269
} )
232
270
271
+ expect ( generateContentDispositionSpy ) . toHaveBeenCalledTimes ( 1 )
272
+ expect ( generateContentDispositionSpy ) . toHaveBeenCalledWith ( 'blob' )
273
+
233
274
const response = new Response ( body , {
234
275
headers,
235
276
} )
@@ -243,16 +284,46 @@ describe('toNodeHttpBody', () => {
243
284
const headers = { ...baseHeaders }
244
285
const blob = new File ( [ 'foo' ] , 'foo.pdf' , { type : 'application/pdf' } )
245
286
287
+ generateContentDispositionSpy . mockReturnValue ( '__mocked__' )
288
+
289
+ const body = toNodeHttpBody ( blob , headers , { } )
290
+
291
+ expect ( body ) . instanceOf ( Readable )
292
+ expect ( headers ) . toEqual ( {
293
+ 'content-disposition' : '__mocked__' ,
294
+ 'content-length' : '3' ,
295
+ 'content-type' : 'application/pdf' ,
296
+ 'x-custom-header' : 'custom-value' ,
297
+ } )
298
+
299
+ expect ( generateContentDispositionSpy ) . toHaveBeenCalledTimes ( 1 )
300
+ expect ( generateContentDispositionSpy ) . toHaveBeenCalledWith ( 'foo.pdf' )
301
+
302
+ const response = new Response ( body , {
303
+ headers,
304
+ } )
305
+ const resBlob = await response . blob ( )
306
+
307
+ expect ( resBlob . type ) . toBe ( 'application/pdf' )
308
+ expect ( await resBlob . text ( ) ) . toBe ( 'foo' )
309
+ } )
310
+
311
+ it ( 'file with content-disposition' , async ( ) => {
312
+ const headers = { ...baseHeaders , 'content-disposition' : 'attachment; filename="foo.pdf"' }
313
+ const blob = new File ( [ 'foo' ] , 'foo.pdf' , { type : 'application/pdf' } )
314
+
246
315
const body = toNodeHttpBody ( blob , headers , { } )
247
316
248
317
expect ( body ) . instanceOf ( Readable )
249
318
expect ( headers ) . toEqual ( {
250
- 'content-disposition' : 'inline ; filename="foo.pdf"' ,
319
+ 'content-disposition' : 'attachment ; filename="foo.pdf"' ,
251
320
'content-length' : '3' ,
252
321
'content-type' : 'application/pdf' ,
253
322
'x-custom-header' : 'custom-value' ,
254
323
} )
255
324
325
+ expect ( generateContentDispositionSpy ) . toHaveBeenCalledTimes ( 0 )
326
+
256
327
const response = new Response ( body , {
257
328
headers,
258
329
} )
0 commit comments