light-my-request
Advanced tools
Comparing version 4.9.0 to 4.10.0
24
index.js
@@ -29,2 +29,9 @@ 'use strict' | ||
const ajv = new Ajv() | ||
ajv.addKeyword({ | ||
keyword: 'prototypedType', | ||
validate: (_, data) => | ||
data && data.prototype && typeof data.prototype === 'object' | ||
}) | ||
const schema = { | ||
@@ -59,3 +66,4 @@ type: 'object', | ||
method: { type: 'string', enum: http.METHODS.concat(http.METHODS.map(toLowerCase)) }, | ||
validate: { type: 'boolean' } | ||
validate: { type: 'boolean' }, | ||
Request: { prototypedType: true } | ||
// payload type => any | ||
@@ -105,4 +113,8 @@ }, | ||
const RequestConstructor = options.Request | ||
? Request.CustomRequest | ||
: Request | ||
if (typeof callback === 'function') { | ||
const req = new Request(options) | ||
const req = new RequestConstructor(options) | ||
const res = new Response(req, callback) | ||
@@ -113,3 +125,3 @@ | ||
return new Promise((resolve, reject) => { | ||
const req = new Request(options) | ||
const req = new RequestConstructor(options) | ||
const res = new Response(req, resolve, reject) | ||
@@ -210,3 +222,7 @@ | ||
function isInjection (obj) { | ||
return (obj instanceof Request || obj instanceof Response) | ||
return ( | ||
obj instanceof Request || | ||
obj instanceof Response || | ||
(obj && obj.constructor && obj.constructor.name === '_CustomLMRRequest') | ||
) | ||
} | ||
@@ -213,0 +229,0 @@ |
@@ -43,2 +43,34 @@ 'use strict' | ||
/** | ||
* CustomRequest | ||
* | ||
* @constructor | ||
* @param {Object} options | ||
* @param {(Object|String)} options.url || options.path | ||
* @param {String} [options.method='GET'] | ||
* @param {String} [options.remoteAddress] | ||
* @param {Object} [options.cookies] | ||
* @param {Object} [options.headers] | ||
* @param {Object} [options.query] | ||
* @param {Object} [options.Request] | ||
* @param {any} [options.payload] | ||
*/ | ||
function CustomRequest (options) { | ||
return new _CustomLMRRequest() | ||
function _CustomLMRRequest () { | ||
Request.call(this, { | ||
...options, | ||
Request: undefined | ||
}) | ||
for (const fn of Object.keys(Request.prototype)) { | ||
this.constructor.prototype[fn] = Request.prototype[fn] | ||
} | ||
util.inherits(this.constructor, options.Request) | ||
return this | ||
} | ||
} | ||
/** | ||
* Request | ||
@@ -129,2 +161,3 @@ * | ||
util.inherits(Request, Readable) | ||
util.inherits(CustomRequest, Request) | ||
@@ -202,1 +235,3 @@ Request.prototype.prepare = function (next) { | ||
module.exports = Request | ||
module.exports.Request = Request | ||
module.exports.CustomRequest = CustomRequest |
{ | ||
"name": "light-my-request", | ||
"version": "4.9.0", | ||
"version": "4.10.0", | ||
"description": "Fake HTTP injection library", | ||
@@ -8,3 +8,3 @@ "main": "index.js", | ||
"ajv": "^8.1.0", | ||
"cookie": "^0.4.0", | ||
"cookie": "^0.5.0", | ||
"process-warning": "^1.0.0", | ||
@@ -23,7 +23,8 @@ "set-cookie-parser": "^2.4.1" | ||
"semver": "^7.3.5", | ||
"standard": "^16.0.1", | ||
"standard": "^17.0.0", | ||
"tap": "^16.0.0", | ||
"tsd": "^0.19.0" | ||
"tsd": "^0.20.0" | ||
}, | ||
"scripts": { | ||
"benchmark": "node test/benchmark.js", | ||
"coverage": "npm run unit -- --cov --coverage-report=html", | ||
@@ -30,0 +31,0 @@ "lint": "standard", |
@@ -133,3 +133,5 @@ # Light my Request | ||
- `InjectOptions` - options object for `inject` method | ||
- `Request` - custom light-my-request `request` object interface. Extends Node.js `stream.Readable` type | ||
- `Request` - custom light-my-request `request` object interface. Extends | ||
Node.js `stream.Readable` type by default. This behavior can be changed by | ||
setting the `Request` option in the `inject` method's options | ||
- `Response` - custom light-my-request `response` object interface. Extends Node.js `http.ServerResponse` type | ||
@@ -144,3 +146,5 @@ | ||
- `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`. | ||
- `req` - a simulated request object. Inherits from `Stream.Readable` by | ||
default. Optionally inherits from another class, set in | ||
`options.Request` | ||
- `res` - a simulated response object. Inherits from node's `Http.ServerResponse`. | ||
@@ -167,2 +171,4 @@ - `options` - request options object where: | ||
is called. It is only valid when not passing a callback. Defaults to `true`. | ||
- `Request` - Optional type from which the `request` object should inherit | ||
instead of `stream.Readable` | ||
- `callback` - the callback function using the signature `function (err, res)` where: | ||
@@ -184,4 +190,19 @@ - `err` - error object | ||
Note: You can also pass a string in place of the `options` object as a shorthand for `{url: string, method: 'GET'}`. | ||
Notes: | ||
- You can also pass a string in place of the `options` object as a shorthand | ||
for `{url: string, method: 'GET'}`. | ||
- Beware when using the `Request` option. That might make _light-my-request_ | ||
slower. Sample benchmark result run on an i5-8600K CPU with `Request` set to | ||
`http.IncomingMessage`: | ||
``` | ||
Request x 155,018 ops/sec ±0.47% (94 runs sampled) | ||
Custom Request x 30,373 ops/sec ±0.64% (90 runs sampled) | ||
Request With Cookies x 125,696 ops/sec ±0.29% (96 runs sampled) | ||
Request With Cookies n payload x 114,391 ops/sec ±0.33% (97 runs sampled) | ||
ParseUrl x 255,790 ops/sec ±0.23% (99 runs sampled) | ||
ParseUrl and query x 194,479 ops/sec ±0.16% (99 runs sampled) | ||
``` | ||
#### `inject.isInjection(obj)` | ||
@@ -188,0 +209,0 @@ |
@@ -0,1 +1,3 @@ | ||
const http = require('http') | ||
const Benchmark = require('benchmark') | ||
@@ -16,2 +18,13 @@ const suite = new Benchmark.Suite() | ||
} | ||
const mockCustomReq = { | ||
url: 'http://localhost', | ||
method: 'GET', | ||
headers: { | ||
foo: 'bar', | ||
'content-type': 'html', | ||
accepts: 'json', | ||
authorization: 'granted' | ||
}, | ||
Request: http.IncomingMessage | ||
} | ||
const mockReqCookies = { | ||
@@ -46,2 +59,5 @@ url: 'http://localhost', | ||
}) | ||
.add('Custom Request', function () { | ||
new Request.CustomRequest(mockCustomReq) | ||
}) | ||
.add('Request With Cookies', function () { | ||
@@ -48,0 +64,0 @@ new Request(mockReqCookies) |
@@ -102,2 +102,34 @@ 'use strict' | ||
test('request inherits from custom class', (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', Request: http.IncomingMessage }, (err, res) => { | ||
t.error(err) | ||
}) | ||
}) | ||
test('assert Request option has a valid prototype', (t) => { | ||
t.plan(2) | ||
const dispatch = function (req, res) { | ||
t.error('should not get here') | ||
res.writeHead(500) | ||
res.end() | ||
} | ||
const MyInvalidRequest = {} | ||
t.throws(() => { | ||
inject(dispatch, { method: 'GET', url: 'http://example.com:8080/hello', Request: MyInvalidRequest }, () => {}) | ||
}, {}) | ||
t.throws(() => { | ||
inject(dispatch, { method: 'GET', url: 'http://example.com:8080/hello', Request: 'InvalidRequest' }, () => {}) | ||
}, {}) | ||
}) | ||
test('passes remote address', (t) => { | ||
@@ -428,4 +460,4 @@ t.plan(2) | ||
test('identifies injection object', (t) => { | ||
t.plan(3) | ||
const dispatch = function (req, res) { | ||
t.plan(6) | ||
const dispatchRequest = function (req, res) { | ||
t.equal(inject.isInjection(req), true) | ||
@@ -438,5 +470,15 @@ t.equal(inject.isInjection(res), true) | ||
inject(dispatch, { method: 'GET', url: '/' }, (err, res) => { | ||
t.error(err) | ||
}) | ||
const dispatchCustomRequest = function (req, res) { | ||
t.equal(inject.isInjection(req), true) | ||
t.equal(inject.isInjection(res), true) | ||
res.writeHead(200, { 'Content-Length': 0 }) | ||
res.end() | ||
} | ||
const options = { method: 'GET', url: '/' } | ||
const cb = (err, res) => { t.error(err) } | ||
inject(dispatchRequest, options, cb) | ||
inject(dispatchCustomRequest, { ...options, Request: http.IncomingMessage }, cb) | ||
}) | ||
@@ -883,3 +925,3 @@ | ||
inject(dispatch, { method: 'GET', url: 'http://example.com:8080/hello', server: server }) | ||
inject(dispatch, { method: 'GET', url: 'http://example.com:8080/hello', server }) | ||
.then(res => t.equal(res.statusCode, 200)) | ||
@@ -1758,3 +1800,3 @@ .catch(err => t.fail(err)) | ||
inject(dispatch, { method: 'GET', url: 'http://example.com:8080//hello', server: server }) | ||
inject(dispatch, { method: 'GET', url: 'http://example.com:8080//hello', server }) | ||
.then(res => { t.equal(res.body, '//hello') }) | ||
@@ -1761,0 +1803,0 @@ .catch(err => t.error(err)) |
87337
2405
260
4
+ Addedcookie@0.5.0(transitive)
- Removedcookie@0.4.2(transitive)
Updatedcookie@^0.5.0