From 48478e1374a1ad748ae304b6690b51869b1ae7a0 Mon Sep 17 00:00:00 2001 From: Dakuan Date: Sat, 14 Feb 2015 20:24:09 +0000 Subject: [PATCH 1/6] options --- README.md | 16 +++++++++++++-- example/index.js | 2 +- package.json | 7 +++++-- src/handlers/error.js | 34 ++++++++++++++++++++++++++------ index.js => src/index.js | 2 +- src/util/random-element.js | 6 ++++++ src/util/run-on-prop.js | 2 +- tests/handlers/errors-spec.js | 37 +++++++++++++++++++++++++++++++++++ 8 files changed, 93 insertions(+), 13 deletions(-) rename index.js => src/index.js (95%) create mode 100644 src/util/random-element.js create mode 100644 tests/handlers/errors-spec.js diff --git a/README.md b/README.md index 6132090..17bd7cd 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,9 @@ app.use(chaos({ delay: 300 }); -// requests might return a 500 (default) +// requests might return an error code +// Client error codes: 400, 401, 402, 403, 404, 405, 406, 407, 407, 409, 410, 411, 412, 413, 414, 415, 416, 417 +// Server Error codes: 500, 501, 502, 503, 504, 505 app.use(chaos({ error: true }); @@ -41,7 +43,17 @@ app.use(chaos({ error: 401 }); -// requests might return 500 or be delayed by 6000ms +// requests might return a code in the array +app.use(chaos({ + error: [404, 500] +})); + +// requests might return a code that matches the regex +app.use(chaos(){ + error: /^40/ +}); + +// requests might return an erro code or be delayed by 6000ms app.use(chaos({ error: true, delay: 6000 diff --git a/example/index.js b/example/index.js index 3e99292..b7a7c37 100644 --- a/example/index.js +++ b/example/index.js @@ -1,6 +1,6 @@ var express = require('express'), app = express(), - chaos = require('../index'); + chaos = require('../src/index'); app.use(chaos()); diff --git a/package.json b/package.json index e2d5cb2..3460872 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "connect / express middleware that causes chaos", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "mocha tests/**/*-spec.js" }, "repository": { "type": "git", @@ -14,7 +14,7 @@ "chaos", "express", "chaos monkey", - "testing", + "testing", "connect" ], "author": { @@ -29,5 +29,8 @@ "homepage": "https://github.com/Dakuan/connect-chaos", "dependencies": { "ramda": "^0.8.0" + }, + "devDependencies": { + "mocha": "^2.1.0" } } diff --git a/src/handlers/error.js b/src/handlers/error.js index e48d4a0..f19dde3 100644 --- a/src/handlers/error.js +++ b/src/handlers/error.js @@ -1,17 +1,39 @@ var R = require('ramda'), - runOnProp = require('../util/run-on-prop'); + randomElement = require('../util/random-element'), + runOnProp = require('../util/run-on-prop'); + +var clientErrors = R.range(400, 418); +var serverErrors = R.range(500, 506); +var all = R.concat(clientErrors, serverErrors); + +var codeMatchingRegex = function(regex) { + return R.find(function(c) { + return R.func('test', regex, c); + }, all); +} + +var parseOpt = R.cond( + [R.is(Number), R.I], // if number then that pick that error code + [R.is(Array), randomElement], // if array pick from those + [R.is(RegExp), codeMatchingRegex], // if regex then code matching that regex + [R.alwaysTrue, function() { + return randomElement.call(null, all); + }] // random error code +); // sends an error code function _error(code) { - var code = code || 500; - return function _errorHandler(req, res, next) { + var hander = function _errorHandler(req, res, next) { + var code = parseOpt(code); console.log('CHAOS: throwing ' + code); res.status(code); res.end(); } + hander.code = code; + return hander; } module.exports = { - predicate: R.has('error'), - factory: runOnProp(_error, 'error') -}; \ No newline at end of file + predicate: R.has('error'), + factory: runOnProp(_error, 'error') +}; diff --git a/index.js b/src/index.js similarity index 95% rename from index.js rename to src/index.js index 2a9f66b..80fbf67 100644 --- a/index.js +++ b/src/index.js @@ -1,5 +1,5 @@ var R = require('ramda'), - handlers = require('./src/handlers/handlers'); + handlers = require('../src/handlers/handlers'); // picks random element from an array function _randomElement(array) { diff --git a/src/util/random-element.js b/src/util/random-element.js new file mode 100644 index 0000000..16c53f7 --- /dev/null +++ b/src/util/random-element.js @@ -0,0 +1,6 @@ +// picks random element from an array +function _randomElement(array) { + return array[Math.floor(Math.random() * array.length)]; +} + +module.exports = _randomElement; \ No newline at end of file diff --git a/src/util/run-on-prop.js b/src/util/run-on-prop.js index 0fc9ac0..5b05cbc 100644 --- a/src/util/run-on-prop.js +++ b/src/util/run-on-prop.js @@ -7,7 +7,7 @@ function _runOnProp(fn, prop) { return R.compose( fn, // apply the function R.prop('value'), // unwrap the monad - R.map(R.ifElse(R.is(Number), R.I, R.always())), // if the prop isn't a number use undefined + // R.map(R.ifElse(R.is(Number), R.I, R.always())), // if the prop isn't a number use undefined R.map(R.prop(prop)), // get the prop if the argument is truthy Maybe // Maybe null ); diff --git a/tests/handlers/errors-spec.js b/tests/handlers/errors-spec.js new file mode 100644 index 0000000..3ed1aba --- /dev/null +++ b/tests/handlers/errors-spec.js @@ -0,0 +1,37 @@ +var subject = require('../../src/handlers/error'), + R = require('ramda'), + assert = require('assert'); + +describe("Error handler", function() { + describe("when a valid number is provided ", function() { + it("should use that error code", function() { + assert(subject.factory({ + error: 420 + }).code === 420); + }); + }); + + describe("when an array is provided", function() { + it("should use a value from the array", function() { + assert(subject.factory({ + error: [123] + }).code === 123); + }); + }); + + describe("when a regex is provided", function() { + it("should use a value that matches the regex", function() { + assert(subject.factory({ + error: /^400/ + }).code === 400); + }); + }); + describe("when nothing is provided", function() { + it("should use a valid error code", function() { + var code = subject.factory().code; + assert(code >= 400); + assert(code <= 506); + assert(R.is(Number, code)); + }); + }); +}); From 926190c2040921da46cd81d47737fecba77b48d0 Mon Sep 17 00:00:00 2001 From: Dakuan Date: Sat, 14 Feb 2015 20:26:31 +0000 Subject: [PATCH 2/6] path the things --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3460872..6030a58 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "connect-chaos", "version": "0.1.0", "description": "connect / express middleware that causes chaos", - "main": "index.js", + "main": "src/index.js", "scripts": { "test": "mocha tests/**/*-spec.js" }, From 06114980472a4c45abf73536df526508fa0f8deb Mon Sep 17 00:00:00 2001 From: Dakuan Date: Sat, 14 Feb 2015 20:28:56 +0000 Subject: [PATCH 3/6] colon --- src/handlers/error.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/handlers/error.js b/src/handlers/error.js index f19dde3..77c6eb6 100644 --- a/src/handlers/error.js +++ b/src/handlers/error.js @@ -10,7 +10,7 @@ var codeMatchingRegex = function(regex) { return R.find(function(c) { return R.func('test', regex, c); }, all); -} +}; var parseOpt = R.cond( [R.is(Number), R.I], // if number then that pick that error code From b46be3f5fef9203b4f2fbf3a70498daf38ba1600 Mon Sep 17 00:00:00 2001 From: Dakuan Date: Sat, 14 Feb 2015 20:30:20 +0000 Subject: [PATCH 4/6] ws --- src/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/index.js b/src/index.js index 80fbf67..200f897 100644 --- a/src/index.js +++ b/src/index.js @@ -11,6 +11,7 @@ function _truthy(val) { return !!val; } + // calls a method on a object with the args // flipped to accept the object last var _flipFunc = R.curry(function(method, args, obj) { From 01618b5fedd5d40da94e0f6e4eb57b7b06d5b713 Mon Sep 17 00:00:00 2001 From: Dakuan Date: Sun, 15 Feb 2015 09:05:24 +0000 Subject: [PATCH 5/6] fix spec --- src/handlers/error.js | 12 +++++------ src/util/run-on-prop.js | 1 + tests/handlers/errors-spec.js | 40 +++++++++++++++++++++++++---------- 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/src/handlers/error.js b/src/handlers/error.js index 77c6eb6..0b55f10 100644 --- a/src/handlers/error.js +++ b/src/handlers/error.js @@ -17,20 +17,18 @@ var parseOpt = R.cond( [R.is(Array), randomElement], // if array pick from those [R.is(RegExp), codeMatchingRegex], // if regex then code matching that regex [R.alwaysTrue, function() { - return randomElement.call(null, all); + return randomElement.call(null, all); }] // random error code ); // sends an error code function _error(code) { - var hander = function _errorHandler(req, res, next) { - var code = parseOpt(code); - console.log('CHAOS: throwing ' + code); - res.status(code); + return function(req, res, next) { + var toThrow = parseOpt(code); + console.log('CHAOS: throwing ' + toThrow); + res.status(toThrow); res.end(); } - hander.code = code; - return hander; } module.exports = { diff --git a/src/util/run-on-prop.js b/src/util/run-on-prop.js index 5b05cbc..4b5ee71 100644 --- a/src/util/run-on-prop.js +++ b/src/util/run-on-prop.js @@ -7,6 +7,7 @@ function _runOnProp(fn, prop) { return R.compose( fn, // apply the function R.prop('value'), // unwrap the monad + // R.map(R.I), // R.map(R.ifElse(R.is(Number), R.I, R.always())), // if the prop isn't a number use undefined R.map(R.prop(prop)), // get the prop if the argument is truthy Maybe // Maybe null diff --git a/tests/handlers/errors-spec.js b/tests/handlers/errors-spec.js index 3ed1aba..bce2942 100644 --- a/tests/handlers/errors-spec.js +++ b/tests/handlers/errors-spec.js @@ -1,37 +1,55 @@ var subject = require('../../src/handlers/error'), - R = require('ramda'), + R = require('ramda'), assert = require('assert'); +function assertStatus(handler, expectedCode) { + handler(null, { + status: function(code) { + assert(code === expectedCode); + }, + end: function() {} + }); +} + describe("Error handler", function() { describe("when a valid number is provided ", function() { it("should use that error code", function() { - assert(subject.factory({ + var handler = subject.factory({ error: 420 - }).code === 420); + }); + assertStatus(handler, 420); }); }); describe("when an array is provided", function() { it("should use a value from the array", function() { - assert(subject.factory({ + var handler = subject.factory({ error: [123] - }).code === 123); + }); + assertStatus(handler, 123); }); }); describe("when a regex is provided", function() { it("should use a value that matches the regex", function() { - assert(subject.factory({ + var handler = subject.factory({ error: /^400/ - }).code === 400); + }); + assertStatus(handler, 400); }); }); + describe("when nothing is provided", function() { it("should use a valid error code", function() { - var code = subject.factory().code; - assert(code >= 400); - assert(code <= 506); - assert(R.is(Number, code)); + var handler = subject.factory(); + handler(null, { + status: function(code) { + assert(code >= 400); + assert(code <= 506); + assert(R.is(Number, code)); + }, + end: function() {} + }); }); }); }); From 7e8616d4e15dd5b0b9c0611c7050215cb898c0d2 Mon Sep 17 00:00:00 2001 From: Dakuan Date: Sun, 15 Feb 2015 09:08:25 +0000 Subject: [PATCH 6/6] bump spec --- README.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 17bd7cd..df05b82 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ connect-chaos ============= +[![Circle CI](https://circleci.com/gh/Dakuan/connect-chaos.svg?style=svg&circle-token=be329dbcfa94b3635df9ae15d1f89133e5b05a95)](https://circleci.com/gh/Dakuan/connect-chaos) + ## Connect / Express middleware that causes chaos diff --git a/package.json b/package.json index 6030a58..d91d446 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "connect-chaos", - "version": "0.1.0", + "version": "0.2.0", "description": "connect / express middleware that causes chaos", "main": "src/index.js", "scripts": {