Comparing version 0.1.3 to 0.1.4
33
index.js
@@ -7,27 +7,26 @@ "use strict" | ||
module.exports.run = function(callbackOrPort, maybePort) { | ||
module.exports.run = function (callbackOrPort, maybePort) { | ||
const sim = new SimServer() | ||
if (typeof callbackOrPort === 'function') { | ||
return new SimServer().start(s => { | ||
callbackOrPort(s, s.address().port) | ||
}, maybePort) | ||
return sim.start(s => callbackOrPort(s.address().port, sim.stats, s), maybePort) | ||
} | ||
return new SimServer().start(null, callbackOrPort) | ||
return sim.start(null, callbackOrPort) | ||
} | ||
module.exports.test = function(routine, done, timeout=10*1000) { | ||
module.exports.test = function (routine, done, timeout = 10 * 1000) { | ||
if (!routine) { | ||
throw new Error('Test routine is required') | ||
} | ||
const server = new SimServer() | ||
const safety = setTimeout(() => server.close(), timeout) | ||
const sim = new SimServer() | ||
const safety = setTimeout(() => sim.close(), timeout) | ||
if (typeof done !== 'function') { | ||
return new Promise((resolve, reject) => { | ||
server.start(async s => { | ||
sim.start(async s => { | ||
try { | ||
resolve(await routine(s, s.address().port)) | ||
resolve(await routine(s.address().port, sim.stats, s)) | ||
} catch (e) { | ||
reject(e) | ||
} finally { | ||
server.close() | ||
sim.close() | ||
clearTimeout(safety) | ||
@@ -38,9 +37,9 @@ } | ||
} else { | ||
const closeAndDone = e => { | ||
server.close(_ => done(e)) | ||
clearTimeout(safety) | ||
} | ||
server.start(async s => { | ||
sim.start(async s => { | ||
const closeAndDone = e => { | ||
sim.close(() => done(e)) | ||
clearTimeout(safety) | ||
} | ||
try { | ||
routine(s, s.address().port, closeAndDone) | ||
routine(s.address().port, sim.stats, s, closeAndDone) | ||
} catch (e) { | ||
@@ -47,0 +46,0 @@ closeAndDone(e) |
@@ -29,2 +29,3 @@ "use strict" | ||
bodySize: this.parseUInt(q.bs), | ||
echoBody: this.parseUInt(q.eb) === 1, | ||
echoHeaders: this.parseUInt(q.eh) === 1, | ||
@@ -31,0 +32,0 @@ body: undefined, |
@@ -13,2 +13,7 @@ "use strict" | ||
limits.init(this, customLimits) | ||
this.stats = { | ||
calls: 0, | ||
drops: 0, | ||
sents: 0, | ||
} | ||
} | ||
@@ -33,7 +38,15 @@ | ||
acceptRequest(req, res) { | ||
this.stats.calls++ | ||
res.once('finish', () => this.stats.sents++) | ||
const setting = limits.apply(this, settings.parse(req.url)) | ||
this.emit('request', req, res, setting) | ||
if (res.finished) { | ||
return | ||
} | ||
if (req.socket.destroyed) { | ||
this.stats.drops++ | ||
return | ||
} | ||
if (setting.latency.actual) { | ||
@@ -49,20 +62,35 @@ setTimeout(() => this.sendResponse(req, res, setting), setting.latency.actual) | ||
req.socket.destroy() | ||
this.stats.drops++ | ||
return | ||
} | ||
if (setting.response.status) { | ||
res.statusCode = setting.response.status | ||
} | ||
let body = setting.response.body | ||
if (!body) { | ||
if (setting.response.echoHeaders) { | ||
body = JSON.stringify(req.headers) | ||
if (!setting.response.body) { | ||
if (setting.response.echoBody) { | ||
setting.response.body = null | ||
} else if (setting.response.echoHeaders) { | ||
setting.response.body = JSON.stringify(req.headers) | ||
} else if (setting.response.bodySize) { | ||
body = utils.makeJsonString(setting.response.bodySize) | ||
setting.response.body = utils.makeJsonString(setting.response.bodySize) | ||
} | ||
if (body) { | ||
if (setting.response.body) { | ||
res.setHeader('Content-Type', 'application/json') | ||
} | ||
} | ||
if (body) { | ||
res.end(body + '\n') | ||
if (setting.response.status) { | ||
res.statusCode = setting.response.status | ||
} | ||
this.emit('response', req, res, setting) | ||
if (res.finished) { | ||
return | ||
} | ||
if (req.socket.destroyed) { | ||
this.stats.drops++ | ||
return | ||
} | ||
if (setting.response.body) { | ||
res.end(setting.response.body + '\n') | ||
} else if (setting.response.echoBody) { | ||
req.pipe(res) | ||
} else { | ||
@@ -69,0 +97,0 @@ res.end() |
{ | ||
"name": "simdummy", | ||
"version": "0.1.3", | ||
"version": "0.1.4", | ||
"description": "Simple tool for HTTP response simulation, automated and load testing", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -23,3 +23,3 @@ | ||
run((server, port) => { | ||
run((port, stats, server) => { | ||
console.log(`Simulation server started at ${port}`) | ||
@@ -35,2 +35,4 @@ }, 9999) | ||
### Testing with Promises | ||
To start HTTP listener to test asynchronous code with promises and async/await: | ||
@@ -42,5 +44,6 @@ | ||
it('test async promise', async () => { | ||
await test(async (server, port) => { | ||
const res = await yourFavoriteHttpClient.get(`http://localhost:${port}`) | ||
assert.equal(res.status, 200) | ||
await test(async (port, stats, server) => { | ||
const res = await yourHttpClient.get(`http://localhost:${port}`) | ||
expect(res.status).to.equal(200) | ||
expect(stats.calls).to.equal(1) | ||
}) | ||
@@ -50,2 +53,10 @@ }) | ||
Sim server collects basic statistics about number of requests received, responses sent and calls droped. The _stats_ are exposed on sim sever instance as property and passed to _run_ and _test_ callbacks as argument: | ||
- calls - number of requests accepted | ||
- sents - number of responses sent | ||
- drops - number of responses dropped | ||
### Testing with Callbacks | ||
To start HTTP listener to test asynchronous code with callbacks, pass _done_ to _test_ call: | ||
@@ -55,5 +66,6 @@ | ||
it('test async callback', done => { | ||
test((server, port, done) => { | ||
yourFavoriteHttpClient.get(`http://localhost:${port}`, res => { | ||
assert.equal(res.status, 200) | ||
test((port, stats, server, done) => { | ||
yourHttpClient.get(`http://localhost:${port}`, res => { | ||
expect(res.status).to.equal(200) | ||
expect(stats.calls).to.equal(1) | ||
done() | ||
@@ -65,18 +77,18 @@ }) | ||
### Simulation Settings | ||
## Simulation Options | ||
Simulation settings are passed as query string parameters: | ||
Available query string parameters: | ||
- l=200 - base latency | ||
- n=50 - latency noise | ||
- s=404 - response status | ||
- eb=1 - request body is piped to response body | ||
- eh=1 - request headers are stringified to response body | ||
- bs=1024 - response body size in bytes, rounded to octet | ||
- eh=1 - request headers are stringified to response body | ||
- d=1 - destroy socket | ||
- d=1 - destroy request socket | ||
## Startup Options | ||
## Startup Options and Events | ||
Simulation server can be started directly: | ||
Here is an example of how the simulation server can be started and which events are exposed. | ||
@@ -101,3 +113,3 @@ ``` | ||
server.on('request', (req, res, settings) => { | ||
console.log('Simulating response') | ||
console.log('Accepted request') | ||
@@ -114,2 +126,16 @@ // override response latency | ||
// response event is emitted before sending response | ||
server.on('response', (req, res, settings) => { | ||
console.log('Sending response') | ||
// pipe request to response | ||
settings.response.echoBody = true | ||
// or override the whole body | ||
settings.response.body = 'Hello, world!' | ||
// set different status code | ||
res.statusCode = 201 | ||
}) | ||
// stop the server | ||
@@ -116,0 +142,0 @@ server.close(err => { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
11851
210
147