mock-web-server
Advanced tools
Comparing version
mock-web-server | ||
================ | ||
## 0.9.2 | ||
- support preResponse hook | ||
- change lisence to ISC | ||
## 0.9.1 | ||
@@ -5,0 +9,0 @@ - fix issue #1 - after .reset(response) - server still responds with old response |
@@ -10,14 +10,20 @@ const bodyParser = require('body-parser'); | ||
const parsers = mockSvrFactory.mapParsers(bodyParsers); | ||
//a REPL-friendly request view | ||
const collectAccepted = ({ httpVersion, method, url, headers, rawHeaders, upgrade, body, trailers, rawTrailers }, parseError) => { | ||
const mapped = {httpVersion, method, url, headers, rawHeaders, upgrade, parseError, body, trailers, rawTrailers}; | ||
accepted.push(mapped); | ||
return mapped; | ||
}; | ||
const svr = require('http').createServer((q,r) => { | ||
parseBody(parsers, q,r, (parseError) => { | ||
{//keep a REPL-friendly request view | ||
const {httpVersion, method, url, headers, rawHeaders, upgrade, body, trailers, rawTrailers} = q; | ||
accepted.push({httpVersion, method, url, headers, rawHeaders, upgrade, parseError, body, trailers, rawTrailers}); | ||
} | ||
{//emit headers | ||
const {headers = {}} = response; | ||
const acc = collectAccepted(q, parseError); | ||
{//emit response | ||
const { status, body, headers = {} } = | ||
'function' == typeof response.preResponse | ||
? Object.assign({}, response, response.preResponse(acc, response) || response) | ||
: response; | ||
Object.keys(headers).forEach(h => r.setHeader(h, headers[h])) | ||
r.statusCode = status || 200; | ||
r.end( JSON.stringify(body) ) | ||
} | ||
r.statusCode = response.status || 200; | ||
r.end( JSON.stringify(response.body) ) | ||
}) | ||
@@ -24,0 +30,0 @@ }); |
{ | ||
"name": "mock-web-server", | ||
"version": "0.9.1", | ||
"version": "0.9.2", | ||
"description": "", | ||
@@ -18,3 +18,3 @@ "main": "lib", | ||
}, | ||
"license": "MIT", | ||
"license": "ISC", | ||
"repository": { | ||
@@ -25,3 +25,3 @@ "type": "git", | ||
"publishConfig": { | ||
"registry": "http://registry.npmjs.org/" | ||
"registry": "https://registry.npmjs.org/" | ||
}, | ||
@@ -28,0 +28,0 @@ "scripts": { |
158
README.md
@@ -26,5 +26,12 @@ # mock-web-server [](http://travis-ci.org/osher/mock-web-server) [](https://coveralls.io/github/osher/mock-web-server) | ||
## Example | ||
This example uses mocha, however - it can be used with every test runner for node. | ||
## Example - the common simple case: | ||
This example uses a simple static response descriptor. | ||
Every time the server receives a request - it will: | ||
1. capture a REPL-friendly detailed view of the request. | ||
2. respond with the same respopnse, no matter what are the characteristics of the request. | ||
You can replace the response descriptor using `svr.reset(newResponseDescriptor)`. | ||
This example uses mocha, however - it can be used with every any test runner. | ||
```javascript | ||
@@ -126,6 +133,73 @@ const mockSvrFactory = require('mock-web-server'); | ||
``` | ||
## Example - logic for dynamic responses | ||
(since: `0.9.2`) | ||
In most cases, a static response to a single API is enough. | ||
However, sometimes you need your mock server to support few endpoints, and/or control for a non-idempotent API that accumulates state between responses. | ||
For this, you can provide an `preResponse` hook. The hook can map an accepted request to a response, or mutate the response object behind the server. | ||
* The hook should be synchronous. | ||
* The hook is passed the accepted request view as a 1st argument. | ||
* The hook is passed the response descriptor the server holds as a 2nd parameter. | ||
* The hook is also called on the context of the response descriptor. | ||
The server will keep collecting REPL-friendly views of the accepted requests as usual, so you can ask it what it heard from your tested client. | ||
### mapper preResponse hook | ||
If you return a value from your preResponse hook - its props cascades their equivalents on the response descriptor the server holds. | ||
In this example, the response descriptor the sever is initiated with defaults to a reply of *Not-found*. However, when the uri represents a supported entry - the returned object cascades the `status: 200` and the `body` for that entry. | ||
```js | ||
const routes = { | ||
'/api/user/1': { name: 'John Snow '}, | ||
'/api/user/2': { name: 'John Doe '}, | ||
}; | ||
const svr = mockSvrFactory({ | ||
status: 404, | ||
headers: { | ||
'Content-Type': 'application/json; charset: utf-8', | ||
}, | ||
body: { err: 'not-found' }, | ||
preResponse: ({ uri }) => routes[uri] && ({ status: 200, body: this.routes[uri] }), | ||
}); | ||
``` | ||
### mutator preResponse hook | ||
Using the hook as a mutator lets you manage a simple in-memory state on the response descriptor. | ||
If you don't want to manage it in a closure - you can use this object as a context object. | ||
The response descriptor is both passed to the hook as a 2nd argument, and used as the context on which the hook is called, so you can use `this`, or an arrow-function according to your preferences. | ||
This example uses a queue of bodies on the response descriptor, and accesses it via the `this` keyword. | ||
```js | ||
const faker = require('faker'); | ||
const svr = mockSvrFactory({ | ||
queue: [{ one: 1 }, { two: 2 }, { three: 3 }], | ||
preResponse: ({ method }, response) => { | ||
const body = this.queue.unshift(); | ||
if (!body) return { status: 404, body: { status: 'empty' } }; | ||
return { status: 200, body }; | ||
}, | ||
}); | ||
``` | ||
This example uses a `sum` counter on the response desriptor, and accesses it via the 2nd argument: | ||
```js | ||
const svr = mockSvrFactory({ | ||
sum: 0, | ||
preResponse: ({ body: { sum = 0 } }, response) => { | ||
this.sum += sum; | ||
return { status: 200, body: { requests: svr.accepted.length, sum: this.sum } }; | ||
}, | ||
}); | ||
``` | ||
## Specs | ||
@@ -135,58 +209,68 @@ | ||
mock-web-server | ||
√ should be a factory function that names 1 arguments - response (it has an optional 2nd param for options) | ||
✓ should be a factory function that names 1 arguments - response (it has an optional 2nd param for options) | ||
when provided only a response object | ||
√ should not fail and return an server instance | ||
✓ should not fail and return an server instance | ||
when provided a response object and the optional config object | ||
√ should not fail and return an server instance | ||
✓ should not fail and return an server instance | ||
a server instance obtained by the factory | ||
supported API: | ||
√ method .listen(port, done) to start the server | ||
√ method .close(done) to close it | ||
√ attribute .response as the provided response | ||
√ attribute .accepted as array of accepted requests | ||
√ method .reset() to clear the accepted requests and optionally - reset the response | ||
✓ method .listen(port, done) to start the server | ||
✓ method .close(done) to close it | ||
✓ attribute .response as the provided response | ||
✓ attribute .accepted as array of accepted requests | ||
✓ method .reset() to clear the accepted requests and optionally - reset the response | ||
starting and closing the server should work | ||
and the server should serve requests with | ||
√ the provided status code | ||
√ the provided headers | ||
√ the provided body | ||
✓ the provided status code | ||
✓ the provided headers | ||
✓ the provided body | ||
and server keeps a REPL-friendly view of the accepted requests that is cleared with .reset() | ||
√ found 3 requests | ||
√ views are serializable | ||
√ .reset() returns the interface and clears the accepted array | ||
√ .reset(response) returns the interface and sets the response | ||
✓ found 3 requests | ||
✓ views are serializable | ||
✓ .reset() returns the interface and clears the accepted array | ||
✓ .reset(response) returns the interface and sets the response | ||
structure of a request view should contain | ||
√ httpVersion | ||
√ method | ||
√ url | ||
√ headers | ||
√ rawHeaders | ||
√ upgrade | ||
√ body | ||
√ trailers | ||
√ rawTrailers | ||
✓ httpVersion | ||
✓ method | ||
✓ url | ||
✓ headers | ||
✓ rawHeaders | ||
✓ upgrade | ||
✓ body | ||
✓ trailers | ||
✓ rawTrailers | ||
when response object has a preResponse hook | ||
and the response hook returns an object | ||
the server should serve request with response returned by the hook | ||
✓ the provided status code | ||
✓ the provided headers | ||
✓ the provided body | ||
and the response hook mutates current response using `this` | ||
the server should serve request with response mutated by the hook | ||
✓ the provided status code | ||
✓ the provided headers | ||
✓ the provided body | ||
closing the server with a callback | ||
√ should call the callback as well as closing the server | ||
✓ should call the callback as well as closing the server | ||
an error passed by body-parser | ||
√ should be collected to the request view as .parseError | ||
✓ should be collected to the request view as .parseError | ||
~internals | ||
.mapParsers(parsers) | ||
√ should be a function that names 1 argument - parsers | ||
✓ should be a function that names 1 argument - parsers | ||
when called with an object element | ||
√ should not fail | ||
✓ should not fail | ||
when called with a function element | ||
√ should not fail | ||
✓ should not fail | ||
when called with a string element that is not a body-parser built-in | ||
√ should not fail and map it to an instance produced by the required module | ||
✓ should not fail and map it to an instance produced by the required module | ||
when called with an object element who's first key is not a body-parser built-in | ||
√ should not fail | ||
√ should map it to an instance produced by the required module | ||
√ should pass it the arguments | ||
✓ should not fail | ||
✓ should map it to an instance produced by the required module | ||
✓ should pass it the arguments | ||
33 passing (94ms) | ||
39 passing (53ms) | ||
``` |
Sorry, the diff of this file is not supported yet
14502
37.23%62
10.71%274
44.21%