Skip to content

Commit

Permalink
feat: response.stream() (#284)
Browse files Browse the repository at this point in the history
* feat: response.stream()

Provide `Readable` response through `response.stream()`

* Update README.md

Signed-off-by: Frazer Smith <frazer.dev@outlook.com>

---------

Signed-off-by: Frazer Smith <frazer.dev@outlook.com>
Co-authored-by: Frazer Smith <frazer.dev@outlook.com>
  • Loading branch information
climba03003 and Fdawgs authored Mar 18, 2024
1 parent 31bed7c commit 87efe4f
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ Injects a fake request into an HTTP server.
- `rawPayload` - the raw payload as a Buffer.
- `trailers` - an object containing the response trailers.
- `json` - a function that parses a json response payload and returns an object.
- `stream` - a function that provides a `Readable` stream of the response payload.
- `cookies` - a getter that parses the `set-cookie` response header and returns an array with all the cookies and their metadata.

Notes:
Expand Down
7 changes: 6 additions & 1 deletion lib/response.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict'

const http = require('node:http')
const { Writable } = require('node:stream')
const { Writable, Readable } = require('node:stream')
const util = require('node:util')

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

// Provide stream Readable for advanced user
res.stream = function streamPayload () {
return Readable.from(response._lightMyRequest.payloadChunks)
}

return res
}

Expand Down
32 changes: 32 additions & 0 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1421,6 +1421,38 @@ test('Response.json() should throw an error if the payload is not of valid JSON
})
})

test('Response.stream() should provide a Readable stream', (t) => {
const lines = [
JSON.stringify({ foo: 'bar' }),
JSON.stringify({ hello: 'world' })
]

t.plan(2 + lines.length)

const dispatch = function (req, res) {
res.writeHead(200, { 'Content-Type': 'multiple/json' })
for (const line of lines) {
res.write(line)
}
res.end()
}

inject(dispatch, { method: 'GET', path: 'http://example.com:8080/hello' }, (err, res) => {
t.error(err)
const readable = res.stream()
const payload = []
t.equal(readable instanceof Readable, true)
readable.on('data', function (chunk) {
payload.push(chunk)
})
readable.on('end', function () {
for (let i = 0; i < lines.length; i++) {
t.equal(lines[i], payload[i].toString())
}
})
})
})

test('promise api should auto start (fire and forget)', (t) => {
t.plan(1)

Expand Down
2 changes: 2 additions & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as http from 'http'
import { Readable } from 'stream'

type HTTPMethods = 'DELETE' | 'delete' |
'GET' | 'get' |
Expand Down Expand Up @@ -87,6 +88,7 @@ declare namespace inject {
payload: string
body: string
json: <T = any>() => T
stream: () => Readable
cookies: Array<Cookie>
}

Expand Down
3 changes: 3 additions & 0 deletions types/index.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as http from 'http'
import { inject, isInjection, Response, DispatchFunc, InjectOptions, Chain } from '..'
import { expectType, expectAssignable, expectNotAssignable } from 'tsd'
import { Readable } from 'stream'

expectAssignable<InjectOptions>({ url: '/' })
expectAssignable<InjectOptions>({ autoStart: true })
Expand All @@ -26,8 +27,10 @@ const expectResponse = function (res: Response | undefined) {
expectType<Response>(res)
console.log(res.payload)
expectAssignable<Function>(res.json)
expectAssignable<Function>(res.stream)
expectAssignable<http.ServerResponse>(res.raw.res)
expectAssignable<http.IncomingMessage>(res.raw.req)
expectType<Readable>(res.stream())
expectType<string>(res.payload)
expectType<string>(res.body)
expectAssignable<Array<any>>(res.cookies)
Expand Down

0 comments on commit 87efe4f

Please sign in to comment.