Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for custom request types #190

Merged
merged 10 commits into from
May 4, 2022
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ Injects a fake request into an HTTP server.

- `dispatchFunc` - listener function. The same as you would pass to `Http.createServer` when making a node HTTP server. Has the signature `function (req, res)` where:
- `req` - a simulated request object. Inherits from `Stream.Readable`.
Optionally inherits from another class, managed by
`options.customRequestType`
- `res` - a simulated response object. Inherits from node's `Http.ServerResponse`.
- `options` - request options object where:
- `url` | `path` - a string specifying the request URL.
Expand All @@ -162,6 +164,8 @@ Injects a fake request into an HTTP server.
- `server` - Optional http server. It is used for binding the `dispatchFunc`.
- `autoStart` - Automatically start the request as soon as the method
is called. It is only valid when not passing a callback. Defaults to `true`.
- `customRequestType` - Optional type from which the `request` object should
inherit besides `stream.Readable`
- `callback` - the callback function using the signature `function (err, res)` where:
- `err` - error object
- `res` - a response object where:
Expand Down
5 changes: 5 additions & 0 deletions lib/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class MockSocket extends EventEmitter {
* @param {Object} [options.cookies]
* @param {Object} [options.headers]
* @param {Object} [options.query]
* @param {Object} [options.customRequestType]
* @param {any} [options.payload]
*/
function Request (options) {
Expand Down Expand Up @@ -121,6 +122,10 @@ function Request (options) {
simulate: options.simulate || {}
}

if (options.customRequestType) {
util.inherits(this.constructor, options.customRequestType)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This alters the constructor, which is a singleton property. This means that after the first execution, all the constructors will have this set. Moreover concurrent usage will be broken too.

Could we move this block next to the other util.inherits?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mcollina you're right about the constructor. I've updated the code so that custom requests are dealt independently from Request.


About moving this util.inherits call down next to the other one: that'd remove the proposed generality, ie users wouldn't be able to provide specific classes/functions from which the request would inherit. Or am I missing something?

In any case this is more of a curiosity than anything. With the new approach this shouldn't be needed.

}

return this
}

Expand Down
13 changes: 13 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,19 @@ test('request has rawHeaders', (t) => {
})
})

test('request has custom type', (t) => {
t.plan(2)
const dispatch = function (req, res) {
t.ok(req instanceof http.IncomingMessage)
res.writeHead(200)
res.end()
}

inject(dispatch, { method: 'GET', url: 'http://example.com:8080/hello', customRequestType: http.IncomingMessage }, (err, res) => {
t.error(err)
})
})

test('passes remote address', (t) => {
t.plan(2)
const dispatch = function (req, res) {
Expand Down