Skip to content

Commit 87efe4f

Browse files
climba03003Fdawgs
andauthored
feat: response.stream() (#284)
* feat: response.stream() Provide `Readable` response through `response.stream()` * Update README.md Signed-off-by: Frazer Smith <[email protected]> --------- Signed-off-by: Frazer Smith <[email protected]> Co-authored-by: Frazer Smith <[email protected]>
1 parent 31bed7c commit 87efe4f

File tree

5 files changed

+44
-1
lines changed

5 files changed

+44
-1
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ Injects a fake request into an HTTP server.
182182
- `rawPayload` - the raw payload as a Buffer.
183183
- `trailers` - an object containing the response trailers.
184184
- `json` - a function that parses a json response payload and returns an object.
185+
- `stream` - a function that provides a `Readable` stream of the response payload.
185186
- `cookies` - a getter that parses the `set-cookie` response header and returns an array with all the cookies and their metadata.
186187

187188
Notes:

lib/response.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict'
22

33
const http = require('node:http')
4-
const { Writable } = require('node:stream')
4+
const { Writable, Readable } = require('node:stream')
55
const util = require('node:util')
66

77
const setCookie = require('set-cookie-parser')
@@ -143,6 +143,11 @@ function generatePayload (response) {
143143
return JSON.parse(res.payload)
144144
}
145145

146+
// Provide stream Readable for advanced user
147+
res.stream = function streamPayload () {
148+
return Readable.from(response._lightMyRequest.payloadChunks)
149+
}
150+
146151
return res
147152
}
148153

test/index.test.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1421,6 +1421,38 @@ test('Response.json() should throw an error if the payload is not of valid JSON
14211421
})
14221422
})
14231423

1424+
test('Response.stream() should provide a Readable stream', (t) => {
1425+
const lines = [
1426+
JSON.stringify({ foo: 'bar' }),
1427+
JSON.stringify({ hello: 'world' })
1428+
]
1429+
1430+
t.plan(2 + lines.length)
1431+
1432+
const dispatch = function (req, res) {
1433+
res.writeHead(200, { 'Content-Type': 'multiple/json' })
1434+
for (const line of lines) {
1435+
res.write(line)
1436+
}
1437+
res.end()
1438+
}
1439+
1440+
inject(dispatch, { method: 'GET', path: 'http://example.com:8080/hello' }, (err, res) => {
1441+
t.error(err)
1442+
const readable = res.stream()
1443+
const payload = []
1444+
t.equal(readable instanceof Readable, true)
1445+
readable.on('data', function (chunk) {
1446+
payload.push(chunk)
1447+
})
1448+
readable.on('end', function () {
1449+
for (let i = 0; i < lines.length; i++) {
1450+
t.equal(lines[i], payload[i].toString())
1451+
}
1452+
})
1453+
})
1454+
})
1455+
14241456
test('promise api should auto start (fire and forget)', (t) => {
14251457
t.plan(1)
14261458

types/index.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as http from 'http'
2+
import { Readable } from 'stream'
23

34
type HTTPMethods = 'DELETE' | 'delete' |
45
'GET' | 'get' |
@@ -87,6 +88,7 @@ declare namespace inject {
8788
payload: string
8889
body: string
8990
json: <T = any>() => T
91+
stream: () => Readable
9092
cookies: Array<Cookie>
9193
}
9294

types/index.test-d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as http from 'http'
22
import { inject, isInjection, Response, DispatchFunc, InjectOptions, Chain } from '..'
33
import { expectType, expectAssignable, expectNotAssignable } from 'tsd'
4+
import { Readable } from 'stream'
45

56
expectAssignable<InjectOptions>({ url: '/' })
67
expectAssignable<InjectOptions>({ autoStart: true })
@@ -26,8 +27,10 @@ const expectResponse = function (res: Response | undefined) {
2627
expectType<Response>(res)
2728
console.log(res.payload)
2829
expectAssignable<Function>(res.json)
30+
expectAssignable<Function>(res.stream)
2931
expectAssignable<http.ServerResponse>(res.raw.res)
3032
expectAssignable<http.IncomingMessage>(res.raw.req)
33+
expectType<Readable>(res.stream())
3134
expectType<string>(res.payload)
3235
expectType<string>(res.body)
3336
expectAssignable<Array<any>>(res.cookies)

0 commit comments

Comments
 (0)