├── .gitignore ├── .jshintignore ├── .jshintrc ├── LICENSE ├── README.md ├── index.js ├── package-lock.json ├── package.json └── test └── jsend.test.js /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | 10 | ._* 11 | 12 | node_modules 13 | 14 | pids 15 | logs 16 | results 17 | 18 | npm-debug.log 19 | -------------------------------------------------------------------------------- /.jshintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "undef": true, 4 | "eqeqeq": true, 5 | "eqnull": false, 6 | "newcap": true, 7 | "laxbreak": true, 8 | 9 | "predef": [ 10 | "describe", 11 | "it" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2014 Matthew Dunlap 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jsend 2 | 3 | Utilities and middleware to assist with sending and handling [jsend](https://github.com/omniti-labs/jsend) responses. 4 | 5 | 6 | ### Installation 7 | 8 | ```bash 9 | npm install -S jsend 10 | ``` 11 | 12 | 13 | 14 | ## Response Creation 15 | 16 | Responses can be created using the `success`, `fail`, and `error` methods: 17 | 18 | ```js 19 | // You can pass data or a jsend response to success 20 | jsend.success({ foo: 'bar' }); // { status: 'success', data: { foo: 'bar' } } 21 | jsend.success([ 'foo', 'bar' ]); // { status: 'success', data: [ 'foo', 'bar' ] } 22 | jsend.success(1337); // { status: 'success', data: 1337 } 23 | jsend.success(false); // { status: 'success', data: false } 24 | 25 | // You can pass data or a jsend response to fail 26 | jsend.fail({ itsa: 'trap' }); // { status: 'fail', data: { itsa: 'trap' } } 27 | jsend.fail(true); // { status: 'fail', data: true } 28 | 29 | // You can pass a message or an object with a message and optionally data and code 30 | jsend.error('No soup for you!'); // { status: 'error', message: 'No soup for you!' } 31 | jsend.error({ 32 | code: 123, 33 | message: 'No soup for you!' 34 | }); // { status: 'error', code: 123, message: 'No soup for you!' } 35 | jsend.error({ 36 | code: 123, 37 | message: 'No soup for you!', 38 | data: false 39 | }); // { status: 'error', code: 123, message: 'No soup for you!', data: false } 40 | ``` 41 | 42 | 43 | ### Node-style Callbacks 44 | 45 | The `fromArguments` method can be used to create jsend responses from node-style (i.e. `(err, data)`) callback arguments: 46 | 47 | ```js 48 | getData(id, function(err, data) { 49 | var response = jsend.fromArguments(err, data); 50 | }); 51 | ``` 52 | 53 | 54 | ### Http Middleware 55 | 56 | The jsend middleware has methods for easily sending "succeess", "fail" and "error" responses: 57 | 58 | ```js 59 | expressApp.use(jsend.middleware); 60 | 61 | expressApp.get('/', function(req, res) { 62 | if(!req.params.someParam) 63 | return res.jsend.fail({ validation:['someParam is required'] }); 64 | 65 | loadData(req.params.someParam, function(err, data) { 66 | if(err) return res.jsend.error(err); 67 | res.jsend.success(data); 68 | }); 69 | }); 70 | ``` 71 | 72 | Or you can use `res.jsend` as a callback to respond automatically with a jsend wrapped response: 73 | 74 | ```js 75 | expressApp.use(jsend.middleware); 76 | 77 | expressApp.get('/', function(req, res) { 78 | loadData(req.params.someParam, res.jsend); 79 | }); 80 | ``` 81 | 82 | same as: 83 | 84 | ```js 85 | expressApp.use(jsend.middleware); 86 | 87 | expressApp.get('/', function(req, res) { 88 | loadData(req.params.someParam, function(err, data) { 89 | res.jsend(err, data); 90 | }); 91 | }); 92 | ``` 93 | 94 | 95 | ### Responding with jsend sans-middleware 96 | 97 | If you don't want to use the middleware you can simply create jsend responses and send them with `res.json`: 98 | 99 | ```js 100 | getData(id, function(err, data) { 101 | res.json(jsend.fromArguments(err, data)); 102 | }); 103 | ``` 104 | 105 | 106 | 107 | ## Response Validation 108 | 109 | By default `jsend.isValid` validates that all required properties exist. 110 | 111 | ```js 112 | var jsend = require('jsend'); 113 | 114 | // Returns true 115 | jsend.isValid({ 116 | status: 'success', 117 | data: { foo:'bar' } 118 | }); 119 | 120 | // Returns false 121 | jsend.isValid({ 122 | status: 'success' 123 | }); 124 | 125 | // Returns true 126 | jsend.isValid({ 127 | status: 'success', 128 | data: { foo:'bar' }, 129 | junk: 'is ok' 130 | }); 131 | ``` 132 | 133 | Using the `strict` flag causes `jsend.isValid` to also validate that extraneous properties do not exist. 134 | 135 | ```js 136 | var jsend = require('jsend')({ strict:true }); 137 | 138 | // Returns true 139 | jsend.isValid({ 140 | status: 'success', 141 | data: { foo:'bar' } 142 | }); 143 | 144 | // Returns false 145 | jsend.isValid({ 146 | status: 'success' 147 | }); 148 | 149 | // Returns false 150 | jsend.isValid({ 151 | status: 'success', 152 | data: { foo:'bar' }, 153 | junk: 'is ok' 154 | }); 155 | ``` 156 | 157 | 158 | ### Response Forwarding 159 | 160 | You can forward a jsend response to a node style callback using the `forward` method. 161 | 162 | ```js 163 | jsend.forward(json, function(err, data) { 164 | // err will be set if status was 'error' or 'fail' 165 | // data will be set to the "data" property in all cases 166 | }); 167 | ``` 168 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var STATUSES = { 2 | success: { required: ['status', 'data'], allowed:['status', 'data'] }, 3 | fail: { required: ['status', 'data'], allowed:['status', 'data'] }, 4 | error: { required: ['status', 'message'], allowed:['status', 'message', 'data', 'code'] } 5 | }; 6 | 7 | function requireKeys(keys, json) { 8 | return keys.every(function(key) { 9 | return key in json; 10 | }); 11 | } 12 | 13 | function allowKeys(keys, json) { 14 | return Object.keys(json).every(function(key) { 15 | return ~keys.indexOf(key); 16 | }); 17 | } 18 | 19 | function jsend(config, host) { 20 | config = config || {}; 21 | host = host || {}; 22 | 23 | function isValid(json) { 24 | var spec = STATUSES[json && json.status], 25 | valid = !!spec && requireKeys(spec.required, json); 26 | 27 | if(config.strict) valid = valid && allowKeys(spec.allowed, json); 28 | 29 | return valid; 30 | } 31 | 32 | function forward(json, done) { 33 | if(!isValid(json)) 34 | json = { 35 | status: 'error', 36 | message: 'Invalid jsend object.', 37 | data: { originalObject: json } 38 | }; 39 | 40 | if(json.status === 'success') 41 | done(null, json.data); 42 | else { 43 | var err = new Error(json.message || ('Jsend response status: ' + json.status)); 44 | if('code' in json) err.code = json.code; 45 | if('data' in json) err.data = json.data; 46 | done(err, json.data); 47 | } 48 | } 49 | 50 | function fromArguments(err, json) { 51 | if(arguments.length === 1 && err.length === 2) { 52 | json = err[1]; 53 | err = err[0]; 54 | } 55 | 56 | if(err) { 57 | json = { 58 | status: 'error', 59 | message: (typeof err === 'string') 60 | ? err 61 | : err && err.message || 'Unknown error. (jsend)' 62 | }; 63 | if(err && err.stack) json.data = { stack:err.stack }; 64 | } else if(json === undefined) { 65 | json = { 66 | status: 'error', 67 | message: 'No data returned.' 68 | }; 69 | } else if(!isValid(json)) { 70 | json = { 71 | status: 'success', 72 | data: json 73 | }; 74 | } 75 | 76 | return json; 77 | } 78 | 79 | function success(data) { 80 | if(data === undefined) throw new Error('"data" must be defined when calling jsend.success. (jsend)'); 81 | return { 82 | status: 'success', 83 | data: (data && data.status === 'success' && isValid(data)) 84 | ? data.data 85 | : data 86 | }; 87 | } 88 | 89 | function fail(data) { 90 | if(data === undefined) throw new Error('"data" must be defined when calling jsend.fail. (jsend)'); 91 | return{ 92 | status: 'fail', 93 | data: (data && data.status === 'fail' && isValid(data)) 94 | ? data.data 95 | : data 96 | }; 97 | } 98 | 99 | function error(message, rest) { 100 | var json = { 101 | status: 'error' 102 | }; 103 | 104 | if(typeof message === 'string') { 105 | json.message = message; 106 | if(rest) { 107 | if(rest.code !== undefined) json.code = rest.code; 108 | if(rest.data !== undefined) json.data = rest.data; 109 | } 110 | } else if(message && message.message) { 111 | json.message = message.message; 112 | if(message.code !== undefined) json.code = message.code; 113 | if(message.data !== undefined) json.data = message.data; 114 | } else { 115 | throw new Error('"message" must be defined when calling jsend.error. (jsend)'); 116 | } 117 | 118 | return json; 119 | } 120 | 121 | host.isValid = isValid; 122 | host.forward = forward; 123 | host.fromArguments = fromArguments; 124 | host.success = success; 125 | host.fail = fail; 126 | host.error = error; 127 | 128 | host.middleware = function(req, res, next) { 129 | var middleware = res.jsend = function(err, json) { 130 | res.json(fromArguments(err, json)); 131 | }; 132 | 133 | middleware.success = function(data) { 134 | res.json(success(data)); 135 | }; 136 | middleware.fail = function(data) { 137 | res.json(fail(data)); 138 | }; 139 | middleware.error = function(message) { 140 | res.json(error(message)); 141 | }; 142 | 143 | next(); 144 | }; 145 | 146 | return host; 147 | } 148 | 149 | module.exports = jsend(null, jsend); 150 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jsend", 3 | "version": "1.1.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "assertion-error": { 8 | "version": "1.1.0", 9 | "resolved": "https://unpm.uberinternal.com/assertion-error/-/assertion-error-1.1.0.tgz", 10 | "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", 11 | "dev": true 12 | }, 13 | "balanced-match": { 14 | "version": "1.0.0", 15 | "resolved": "https://unpm.uberinternal.com/balanced-match/-/balanced-match-1.0.0.tgz", 16 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 17 | "dev": true 18 | }, 19 | "brace-expansion": { 20 | "version": "1.1.11", 21 | "resolved": "https://unpm.uberinternal.com/brace-expansion/-/brace-expansion-1.1.11.tgz", 22 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 23 | "dev": true, 24 | "requires": { 25 | "balanced-match": "^1.0.0", 26 | "concat-map": "0.0.1" 27 | } 28 | }, 29 | "chai": { 30 | "version": "3.5.0", 31 | "resolved": "https://unpm.uberinternal.com/chai/-/chai-3.5.0.tgz", 32 | "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", 33 | "dev": true, 34 | "requires": { 35 | "assertion-error": "^1.0.1", 36 | "deep-eql": "^0.1.3", 37 | "type-detect": "^1.0.0" 38 | } 39 | }, 40 | "cli": { 41 | "version": "1.0.1", 42 | "resolved": "https://unpm.uberinternal.com/cli/-/cli-1.0.1.tgz", 43 | "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=", 44 | "dev": true, 45 | "requires": { 46 | "exit": "0.1.2", 47 | "glob": "^7.1.1" 48 | } 49 | }, 50 | "commander": { 51 | "version": "2.3.0", 52 | "resolved": "https://unpm.uberinternal.com/commander/-/commander-2.3.0.tgz", 53 | "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=", 54 | "dev": true 55 | }, 56 | "concat-map": { 57 | "version": "0.0.1", 58 | "resolved": "https://unpm.uberinternal.com/concat-map/-/concat-map-0.0.1.tgz", 59 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 60 | "dev": true 61 | }, 62 | "console-browserify": { 63 | "version": "1.1.0", 64 | "resolved": "https://unpm.uberinternal.com/console-browserify/-/console-browserify-1.1.0.tgz", 65 | "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", 66 | "dev": true, 67 | "requires": { 68 | "date-now": "^0.1.4" 69 | } 70 | }, 71 | "core-util-is": { 72 | "version": "1.0.2", 73 | "resolved": "https://unpm.uberinternal.com/core-util-is/-/core-util-is-1.0.2.tgz", 74 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", 75 | "dev": true 76 | }, 77 | "date-now": { 78 | "version": "0.1.4", 79 | "resolved": "https://unpm.uberinternal.com/date-now/-/date-now-0.1.4.tgz", 80 | "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", 81 | "dev": true 82 | }, 83 | "debug": { 84 | "version": "2.2.0", 85 | "resolved": "https://unpm.uberinternal.com/debug/-/debug-2.2.0.tgz", 86 | "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", 87 | "dev": true, 88 | "requires": { 89 | "ms": "0.7.1" 90 | } 91 | }, 92 | "deep-eql": { 93 | "version": "0.1.3", 94 | "resolved": "https://unpm.uberinternal.com/deep-eql/-/deep-eql-0.1.3.tgz", 95 | "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", 96 | "dev": true, 97 | "requires": { 98 | "type-detect": "0.1.1" 99 | }, 100 | "dependencies": { 101 | "type-detect": { 102 | "version": "0.1.1", 103 | "resolved": "https://unpm.uberinternal.com/type-detect/-/type-detect-0.1.1.tgz", 104 | "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", 105 | "dev": true 106 | } 107 | } 108 | }, 109 | "diff": { 110 | "version": "1.4.0", 111 | "resolved": "https://unpm.uberinternal.com/diff/-/diff-1.4.0.tgz", 112 | "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", 113 | "dev": true 114 | }, 115 | "dom-serializer": { 116 | "version": "0.1.1", 117 | "resolved": "https://unpm.uberinternal.com/dom-serializer/-/dom-serializer-0.1.1.tgz", 118 | "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", 119 | "dev": true, 120 | "requires": { 121 | "domelementtype": "^1.3.0", 122 | "entities": "^1.1.1" 123 | }, 124 | "dependencies": { 125 | "entities": { 126 | "version": "1.1.2", 127 | "resolved": "https://unpm.uberinternal.com/entities/-/entities-1.1.2.tgz", 128 | "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", 129 | "dev": true 130 | } 131 | } 132 | }, 133 | "domelementtype": { 134 | "version": "1.3.1", 135 | "resolved": "https://unpm.uberinternal.com/domelementtype/-/domelementtype-1.3.1.tgz", 136 | "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", 137 | "dev": true 138 | }, 139 | "domhandler": { 140 | "version": "2.3.0", 141 | "resolved": "https://unpm.uberinternal.com/domhandler/-/domhandler-2.3.0.tgz", 142 | "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", 143 | "dev": true, 144 | "requires": { 145 | "domelementtype": "1" 146 | } 147 | }, 148 | "domutils": { 149 | "version": "1.5.1", 150 | "resolved": "https://unpm.uberinternal.com/domutils/-/domutils-1.5.1.tgz", 151 | "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", 152 | "dev": true, 153 | "requires": { 154 | "dom-serializer": "0", 155 | "domelementtype": "1" 156 | } 157 | }, 158 | "entities": { 159 | "version": "1.0.0", 160 | "resolved": "https://unpm.uberinternal.com/entities/-/entities-1.0.0.tgz", 161 | "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", 162 | "dev": true 163 | }, 164 | "escape-string-regexp": { 165 | "version": "1.0.2", 166 | "resolved": "https://unpm.uberinternal.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", 167 | "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=", 168 | "dev": true 169 | }, 170 | "exit": { 171 | "version": "0.1.2", 172 | "resolved": "https://unpm.uberinternal.com/exit/-/exit-0.1.2.tgz", 173 | "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", 174 | "dev": true 175 | }, 176 | "fs.realpath": { 177 | "version": "1.0.0", 178 | "resolved": "https://unpm.uberinternal.com/fs.realpath/-/fs.realpath-1.0.0.tgz", 179 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 180 | "dev": true 181 | }, 182 | "glob": { 183 | "version": "7.1.4", 184 | "resolved": "https://unpm.uberinternal.com/glob/-/glob-7.1.4.tgz", 185 | "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", 186 | "dev": true, 187 | "requires": { 188 | "fs.realpath": "^1.0.0", 189 | "inflight": "^1.0.4", 190 | "inherits": "2", 191 | "minimatch": "^3.0.4", 192 | "once": "^1.3.0", 193 | "path-is-absolute": "^1.0.0" 194 | } 195 | }, 196 | "growl": { 197 | "version": "1.9.2", 198 | "resolved": "https://unpm.uberinternal.com/growl/-/growl-1.9.2.tgz", 199 | "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", 200 | "dev": true 201 | }, 202 | "htmlparser2": { 203 | "version": "3.8.3", 204 | "resolved": "https://unpm.uberinternal.com/htmlparser2/-/htmlparser2-3.8.3.tgz", 205 | "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", 206 | "dev": true, 207 | "requires": { 208 | "domelementtype": "1", 209 | "domhandler": "2.3", 210 | "domutils": "1.5", 211 | "entities": "1.0", 212 | "readable-stream": "1.1" 213 | } 214 | }, 215 | "inflight": { 216 | "version": "1.0.6", 217 | "resolved": "https://unpm.uberinternal.com/inflight/-/inflight-1.0.6.tgz", 218 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 219 | "dev": true, 220 | "requires": { 221 | "once": "^1.3.0", 222 | "wrappy": "1" 223 | } 224 | }, 225 | "inherits": { 226 | "version": "2.0.4", 227 | "resolved": "https://unpm.uberinternal.com/inherits/-/inherits-2.0.4.tgz", 228 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 229 | "dev": true 230 | }, 231 | "isarray": { 232 | "version": "0.0.1", 233 | "resolved": "https://unpm.uberinternal.com/isarray/-/isarray-0.0.1.tgz", 234 | "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", 235 | "dev": true 236 | }, 237 | "jade": { 238 | "version": "0.26.3", 239 | "resolved": "https://unpm.uberinternal.com/jade/-/jade-0.26.3.tgz", 240 | "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", 241 | "dev": true, 242 | "requires": { 243 | "commander": "0.6.1", 244 | "mkdirp": "0.3.0" 245 | }, 246 | "dependencies": { 247 | "commander": { 248 | "version": "0.6.1", 249 | "resolved": "https://unpm.uberinternal.com/commander/-/commander-0.6.1.tgz", 250 | "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", 251 | "dev": true 252 | }, 253 | "mkdirp": { 254 | "version": "0.3.0", 255 | "resolved": "https://unpm.uberinternal.com/mkdirp/-/mkdirp-0.3.0.tgz", 256 | "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", 257 | "dev": true 258 | } 259 | } 260 | }, 261 | "jshint": { 262 | "version": "2.10.2", 263 | "resolved": "https://unpm.uberinternal.com/jshint/-/jshint-2.10.2.tgz", 264 | "integrity": "sha512-e7KZgCSXMJxznE/4WULzybCMNXNAd/bf5TSrvVEq78Q/K8ZwFpmBqQeDtNiHc3l49nV4E/+YeHU/JZjSUIrLAA==", 265 | "dev": true, 266 | "requires": { 267 | "cli": "~1.0.0", 268 | "console-browserify": "1.1.x", 269 | "exit": "0.1.x", 270 | "htmlparser2": "3.8.x", 271 | "lodash": "~4.17.11", 272 | "minimatch": "~3.0.2", 273 | "shelljs": "0.3.x", 274 | "strip-json-comments": "1.0.x" 275 | } 276 | }, 277 | "lodash": { 278 | "version": "4.17.11", 279 | "resolved": "https://unpm.uberinternal.com/lodash/-/lodash-4.17.11.tgz", 280 | "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", 281 | "dev": true 282 | }, 283 | "lru-cache": { 284 | "version": "2.7.3", 285 | "resolved": "https://unpm.uberinternal.com/lru-cache/-/lru-cache-2.7.3.tgz", 286 | "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", 287 | "dev": true 288 | }, 289 | "minimatch": { 290 | "version": "3.0.4", 291 | "resolved": "https://unpm.uberinternal.com/minimatch/-/minimatch-3.0.4.tgz", 292 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 293 | "dev": true, 294 | "requires": { 295 | "brace-expansion": "^1.1.7" 296 | } 297 | }, 298 | "minimist": { 299 | "version": "0.0.8", 300 | "resolved": "https://unpm.uberinternal.com/minimist/-/minimist-0.0.8.tgz", 301 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", 302 | "dev": true 303 | }, 304 | "mkdirp": { 305 | "version": "0.5.1", 306 | "resolved": "https://unpm.uberinternal.com/mkdirp/-/mkdirp-0.5.1.tgz", 307 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 308 | "dev": true, 309 | "requires": { 310 | "minimist": "0.0.8" 311 | } 312 | }, 313 | "mocha": { 314 | "version": "2.5.3", 315 | "resolved": "https://unpm.uberinternal.com/mocha/-/mocha-2.5.3.tgz", 316 | "integrity": "sha1-FhvlvetJZ3HrmzV0UFC2IrWu/Fg=", 317 | "dev": true, 318 | "requires": { 319 | "commander": "2.3.0", 320 | "debug": "2.2.0", 321 | "diff": "1.4.0", 322 | "escape-string-regexp": "1.0.2", 323 | "glob": "3.2.11", 324 | "growl": "1.9.2", 325 | "jade": "0.26.3", 326 | "mkdirp": "0.5.1", 327 | "supports-color": "1.2.0", 328 | "to-iso-string": "0.0.2" 329 | }, 330 | "dependencies": { 331 | "glob": { 332 | "version": "3.2.11", 333 | "resolved": "https://unpm.uberinternal.com/glob/-/glob-3.2.11.tgz", 334 | "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", 335 | "dev": true, 336 | "requires": { 337 | "inherits": "2", 338 | "minimatch": "0.3" 339 | } 340 | }, 341 | "minimatch": { 342 | "version": "0.3.0", 343 | "resolved": "https://unpm.uberinternal.com/minimatch/-/minimatch-0.3.0.tgz", 344 | "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", 345 | "dev": true, 346 | "requires": { 347 | "lru-cache": "2", 348 | "sigmund": "~1.0.0" 349 | } 350 | } 351 | } 352 | }, 353 | "ms": { 354 | "version": "0.7.1", 355 | "resolved": "https://unpm.uberinternal.com/ms/-/ms-0.7.1.tgz", 356 | "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", 357 | "dev": true 358 | }, 359 | "once": { 360 | "version": "1.4.0", 361 | "resolved": "https://unpm.uberinternal.com/once/-/once-1.4.0.tgz", 362 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 363 | "dev": true, 364 | "requires": { 365 | "wrappy": "1" 366 | } 367 | }, 368 | "path-is-absolute": { 369 | "version": "1.0.1", 370 | "resolved": "https://unpm.uberinternal.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 371 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 372 | "dev": true 373 | }, 374 | "readable-stream": { 375 | "version": "1.1.14", 376 | "resolved": "https://unpm.uberinternal.com/readable-stream/-/readable-stream-1.1.14.tgz", 377 | "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", 378 | "dev": true, 379 | "requires": { 380 | "core-util-is": "~1.0.0", 381 | "inherits": "~2.0.1", 382 | "isarray": "0.0.1", 383 | "string_decoder": "~0.10.x" 384 | } 385 | }, 386 | "shelljs": { 387 | "version": "0.3.0", 388 | "resolved": "https://unpm.uberinternal.com/shelljs/-/shelljs-0.3.0.tgz", 389 | "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=", 390 | "dev": true 391 | }, 392 | "sigmund": { 393 | "version": "1.0.1", 394 | "resolved": "https://unpm.uberinternal.com/sigmund/-/sigmund-1.0.1.tgz", 395 | "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", 396 | "dev": true 397 | }, 398 | "string_decoder": { 399 | "version": "0.10.31", 400 | "resolved": "https://unpm.uberinternal.com/string_decoder/-/string_decoder-0.10.31.tgz", 401 | "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", 402 | "dev": true 403 | }, 404 | "strip-json-comments": { 405 | "version": "1.0.4", 406 | "resolved": "https://unpm.uberinternal.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz", 407 | "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", 408 | "dev": true 409 | }, 410 | "supports-color": { 411 | "version": "1.2.0", 412 | "resolved": "https://unpm.uberinternal.com/supports-color/-/supports-color-1.2.0.tgz", 413 | "integrity": "sha1-/x7R5hFp0Gs88tWI4YixjYhH4X4=", 414 | "dev": true 415 | }, 416 | "to-iso-string": { 417 | "version": "0.0.2", 418 | "resolved": "https://unpm.uberinternal.com/to-iso-string/-/to-iso-string-0.0.2.tgz", 419 | "integrity": "sha1-TcGeZk38y+Jb2NtQiwDG2hWCVdE=", 420 | "dev": true 421 | }, 422 | "type-detect": { 423 | "version": "1.0.0", 424 | "resolved": "https://unpm.uberinternal.com/type-detect/-/type-detect-1.0.0.tgz", 425 | "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", 426 | "dev": true 427 | }, 428 | "wrappy": { 429 | "version": "1.0.2", 430 | "resolved": "https://unpm.uberinternal.com/wrappy/-/wrappy-1.0.2.tgz", 431 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 432 | "dev": true 433 | } 434 | } 435 | } 436 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jsend", 3 | "version": "1.1.0", 4 | "description": "Utilities and middleware to assist with sending and handling jsend responses.", 5 | "keywords": [ 6 | "jsend", 7 | "middleware", 8 | "json", 9 | "status" 10 | ], 11 | "main": "index.js", 12 | "scripts": { 13 | "test": "mocha test/*.test.js", 14 | "lint": "jshint ." 15 | }, 16 | "author": "Matt Dunlap ", 17 | "license": "MIT", 18 | "repository": { 19 | "type": "git", 20 | "url": "git@github.com:Prestaul/jsend.git" 21 | }, 22 | "devDependencies": { 23 | "chai": "^3.0.0", 24 | "jshint": "^2.8.0", 25 | "mocha": "^2.2.5" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /test/jsend.test.js: -------------------------------------------------------------------------------- 1 | var assert = require('chai').assert, 2 | jsend = require('../index'); 3 | 4 | 5 | describe('jsend', function() { 6 | 7 | function basicTests(jsendInstance) { 8 | 9 | describe('- isValid', function() { 10 | describe('should validate', function() { 11 | describe('"success" status', function() { 12 | it('with object data', function() { 13 | assert(jsendInstance.isValid({ 14 | status: 'success', 15 | data: { foo:'bar' } 16 | })); 17 | }); 18 | 19 | it('with array data', function() { 20 | assert(jsendInstance.isValid({ 21 | status: 'success', 22 | data: [1, 2, 3] 23 | })); 24 | }); 25 | 26 | it('with null data', function() { 27 | assert(jsendInstance.isValid({ 28 | status: 'success', 29 | data: null 30 | })); 31 | }); 32 | }); 33 | 34 | describe('"fail" status', function() { 35 | it('with object data', function() { 36 | assert(jsendInstance.isValid({ 37 | status: 'fail', 38 | data: { foo:'bar' } 39 | })); 40 | }); 41 | 42 | it('with array data', function() { 43 | assert(jsendInstance.isValid({ 44 | status: 'fail', 45 | data: [1, 2, 3] 46 | })); 47 | }); 48 | 49 | it('with null data', function() { 50 | assert(jsendInstance.isValid({ 51 | status: 'fail', 52 | data: null 53 | })); 54 | }); 55 | }); 56 | 57 | describe('"error" status', function() { 58 | it('with a message', function() { 59 | assert(jsendInstance.isValid({ 60 | status: 'error', 61 | message: 'something is wrong' 62 | })); 63 | }); 64 | 65 | it('with a message and a code', function() { 66 | assert(jsendInstance.isValid({ 67 | status: 'error', 68 | message: 'something is wrong', 69 | code: 123 70 | })); 71 | }); 72 | 73 | it('with a message and data', function() { 74 | assert(jsendInstance.isValid({ 75 | status: 'error', 76 | message: 'something is wrong', 77 | data: { stack:'this -> that -> the other' } 78 | })); 79 | }); 80 | 81 | it('with a message, a code, and data', function() { 82 | assert(jsendInstance.isValid({ 83 | status: 'error', 84 | message: 'something is wrong', 85 | code: 123, 86 | data: { stack:'this -> that -> the other' } 87 | })); 88 | }); 89 | }); 90 | }); 91 | 92 | describe('should invalidate', function() { 93 | it('object with no status', function() { 94 | assert.isFalse(jsendInstance.isValid({ 95 | data: { foo:'bar' } 96 | })); 97 | }); 98 | 99 | it('"success" status without data', function() { 100 | assert.isFalse(jsendInstance.isValid({ 101 | status: 'success' 102 | })); 103 | }); 104 | 105 | it('"fail" status without data', function() { 106 | assert.isFalse(jsendInstance.isValid({ 107 | status: 'fail' 108 | })); 109 | }); 110 | 111 | it('"error" status without message', function() { 112 | assert.isFalse(jsendInstance.isValid({ 113 | status: 'error', 114 | data: { foo:'bar' } 115 | })); 116 | }); 117 | }); 118 | }); 119 | 120 | 121 | 122 | describe('- fromArguments', function() { 123 | describe('should generate "success"', function() { 124 | it('with object data', function() { 125 | var json = { status:'success', data:{ foo:'bar' } }; 126 | assert.deepEqual(jsendInstance.fromArguments(null, json.data), json); 127 | }); 128 | 129 | it('with array data', function() { 130 | var json = { status:'success', data:[1,2,3] }; 131 | assert.deepEqual(jsendInstance.fromArguments(null, json.data), json); 132 | }); 133 | 134 | it('with string data', function() { 135 | var json = { status:'success', data:'you got it' }; 136 | assert.deepEqual(jsendInstance.fromArguments(null, json.data), json); 137 | }); 138 | 139 | it('with numeric data', function() { 140 | var json = { status:'success', data:123 }; 141 | assert.deepEqual(jsendInstance.fromArguments(null, json.data), json); 142 | }); 143 | 144 | it('with null data', function() { 145 | var json = { status:'success', data:null }; 146 | assert.deepEqual(jsendInstance.fromArguments(null, json.data), json); 147 | }); 148 | }); 149 | 150 | describe('should generate "error"', function() { 151 | it('with error message as first arg', function() { 152 | var json = { status:'error', message:'something bad' }; 153 | assert.deepEqual(jsendInstance.fromArguments(json.message), json); 154 | }); 155 | 156 | it('with Error object as first arg', function() { 157 | var json = { status:'error', message:'something bad' }, 158 | output = jsendInstance.fromArguments(new Error(json.message)); 159 | assert.isObject(output.data); 160 | assert.isString(output.data.stack); 161 | delete output.data; 162 | assert.deepEqual(output, json); 163 | }); 164 | 165 | it('with jsend error object as first arg', function() { 166 | var json = { status:'error', message:'something bad' }; 167 | assert.deepEqual(jsendInstance.fromArguments(json), json); 168 | }); 169 | 170 | it('with jsend fail object as first arg', function() { 171 | var json = { status:'fail', data:{ something:'bad' } }; 172 | assert.deepEqual(jsendInstance.fromArguments(json), { status:'error', message:'Unknown error. (jsend)' }); 173 | }); 174 | 175 | it('with jsend fail object as first arg and preserve message', function() { 176 | var json = { status:'fail', data:{ something:'bad' }, message:'Really bad!' }; 177 | assert.deepEqual(jsendInstance.fromArguments(json), { status:'error', message:'Really bad!' }); 178 | }); 179 | 180 | it('with jsend success object as first arg', function() { 181 | var json = { status:'success', data:{ something:'bad' } }; 182 | assert.deepEqual(jsendInstance.fromArguments(json), { status:'error', message:'Unknown error. (jsend)' }); 183 | }); 184 | }); 185 | }); 186 | 187 | 188 | 189 | describe('- forward', function() { 190 | function assertCall(expectedErr, expectedData) { 191 | return function(err, data) { 192 | if(expectedErr) { 193 | assert.typeOf(err, 'error'); 194 | assert.isString(err.message); 195 | if(expectedErr.message) assert.equal(err.message, expectedErr.message); 196 | if(expectedErr.code) assert.equal(err.code, expectedErr.code); 197 | } 198 | 199 | if(expectedData !== undefined) { 200 | assert.deepEqual(data, expectedData); 201 | } 202 | }; 203 | } 204 | 205 | describe('for "success"', function() { 206 | it('should pass object data', function() { 207 | var json = { status:'success', data:{ foo:'bar' } }; 208 | jsendInstance.forward(json, assertCall(null, json.data)); 209 | }); 210 | 211 | it('should pass array data', function() { 212 | var json = { status:'success', data:[1,2,3] }; 213 | jsendInstance.forward(json, assertCall(null, json.data)); 214 | }); 215 | 216 | it('should pass string data', function() { 217 | var json = { status:'success', data:'you got it' }; 218 | jsendInstance.forward(json, assertCall(null, json.data)); 219 | }); 220 | 221 | it('should pass numeric data', function() { 222 | var json = { status:'success', data:123 }; 223 | jsendInstance.forward(json, assertCall(null, json.data)); 224 | }); 225 | 226 | it('should pass null data', function() { 227 | var json = { status:'success', data:null }; 228 | jsendInstance.forward(json, assertCall(null, json.data)); 229 | }); 230 | }); 231 | 232 | describe('for "fail"', function() { 233 | it('should pass an error and data', function() { 234 | var json = { status:'fail', data:{ validation:false } }; 235 | jsendInstance.forward(json, assertCall(true, json.data)); 236 | }); 237 | }); 238 | 239 | describe('for "error"', function() { 240 | it('should pass an error', function() { 241 | var json = { status:'error', message:'something bad' }; 242 | jsendInstance.forward(json, assertCall(json)); 243 | }); 244 | 245 | it('with code should pass an error with code', function() { 246 | var json = { status:'error', message:'something bad', code:123 }; 247 | jsendInstance.forward(json, assertCall(json)); 248 | }); 249 | 250 | it('with data should pass the data', function() { 251 | var json = { status:'error', message:'something bad', code:123, data:{ foo:'bar' } }; 252 | jsendInstance.forward(json, assertCall(json, json.data)); 253 | }); 254 | }); 255 | 256 | describe('for invalid jsend responses', function() { 257 | it('passes string responses back as the error message', function() { 258 | var html = '414 Request-URI Too Large'; 259 | jsendInstance.forward(html, function(err, data) { 260 | assert.equal(err.data.originalObject, html); 261 | }); 262 | }); 263 | 264 | it('passes object responses back as the error message', function() { 265 | var html = {"invalid-jsend": true}; 266 | jsendInstance.forward(html, function(err, data) { 267 | assert.equal(err.data.originalObject["invalid-jsend"], html["invalid-jsend"]); 268 | }); 269 | }); 270 | }); 271 | }); 272 | 273 | describe('- success', function() { 274 | 275 | it('with jsend object', function() { 276 | var json = { status:'success', data:{ foo:'bar' } }; 277 | 278 | assert.deepEqual(json, jsendInstance.success(json)); 279 | }); 280 | 281 | it('with object data', function() { 282 | var json = { status:'success', data:{ foo:'bar' } }; 283 | 284 | assert.deepEqual(json, jsendInstance.success(json.data)); 285 | }); 286 | 287 | it('with array data', function() { 288 | var json = { status:'success', data:[1,2,3] }; 289 | 290 | assert.deepEqual(json, jsendInstance.success(json.data)); 291 | }); 292 | 293 | it('with string data', function() { 294 | var json = { status:'success', data:'you got it' }; 295 | 296 | assert.deepEqual(json, jsendInstance.success(json.data)); 297 | }); 298 | 299 | it('with numeric data', function() { 300 | var json = { status:'success', data:123 }; 301 | 302 | assert.deepEqual(json, jsendInstance.success(json.data)); 303 | }); 304 | 305 | it('with null data', function() { 306 | var json = { status:'success', data:null }; 307 | 308 | assert.deepEqual(json, jsendInstance.success(json.data)); 309 | }); 310 | 311 | it('should throw error with no data', function() { 312 | assert.throws(jsendInstance.success); 313 | }); 314 | }); 315 | 316 | describe('- fail', function() { 317 | 318 | it('with jsend object', function() { 319 | var json = { status:'fail', data:{ foo:'bar' } }; 320 | 321 | assert.deepEqual(json, jsendInstance.fail(json)); 322 | }); 323 | 324 | it('with object data', function() { 325 | var json = { status:'fail', data:{ foo:'bar' } }; 326 | 327 | assert.deepEqual(json, jsendInstance.fail(json.data)); 328 | }); 329 | 330 | it('with array data', function() { 331 | var json = { status:'fail', data:[1,2,3] }; 332 | 333 | assert.deepEqual(json, jsendInstance.fail(json.data)); 334 | }); 335 | 336 | it('with string data', function() { 337 | var json = { status:'fail', data:'you got it' }; 338 | 339 | assert.deepEqual(json, jsendInstance.fail(json.data)); 340 | }); 341 | 342 | it('with numeric data', function() { 343 | var json = { status:'fail', data:123 }; 344 | 345 | assert.deepEqual(json, jsendInstance.fail(json.data)); 346 | }); 347 | 348 | it('with null data', function() { 349 | var json = { status:'fail', data:null }; 350 | 351 | assert.deepEqual(json, jsendInstance.fail(json.data)); 352 | }); 353 | 354 | it('should throw error with no data', function() { 355 | assert.throws(jsendInstance.fail); 356 | }); 357 | 358 | }); 359 | 360 | describe('- error', function() { 361 | 362 | it('with message', function() { 363 | var json = { status:'error', message:'something bad' }; 364 | 365 | assert.deepEqual(json, jsendInstance.error(json.message)); 366 | }); 367 | 368 | it('with message and code', function() { 369 | var json = { status:'error', message:'something bad', code:'BAD_THINGS' }; 370 | 371 | assert.deepEqual(json, jsendInstance.error(json)); 372 | }); 373 | 374 | it('with message and data', function() { 375 | var json = { status:'error', message:'something bad', data:{ foo:'bar' } }; 376 | 377 | assert.deepEqual(json, jsendInstance.error(json)); 378 | }); 379 | 380 | it('with message and data and code', function() { 381 | var json = { status:'error', message:'something bad', code:'BAD_THINGS', data:{ foo:'bar' } }; 382 | 383 | assert.deepEqual(json, jsendInstance.error(json)); 384 | }); 385 | 386 | it('with message as first argument, and data and code as second', function () { 387 | var json = { status:'error', message:'something bad', code:'BAD_THINGS', data:{ foo:'bar' } }; 388 | var { message, ...rest } = json; 389 | 390 | assert.deepEqual(json, jsendInstance.error(message, rest)); 391 | }); 392 | 393 | it('with message as first argument, and null as second', function () { 394 | var json = { status:'error', message:'something bad' }; 395 | 396 | assert.deepEqual(json, jsendInstance.error(json.message, null)); 397 | }); 398 | 399 | it('should throw error with no message', function() { 400 | var json = { status:'error', code:'BAD_THINGS', data:{ foo:'bar' } }; 401 | 402 | assert.throws(jsendInstance.error.bind(jsendInstance, json)); 403 | }); 404 | 405 | }); 406 | 407 | describe('- middleware', function() { 408 | var req = {}; 409 | 410 | it('should call "next" callback', function(done) { 411 | jsendInstance.middleware({}, {}, done); 412 | }); 413 | 414 | describe('should respond with "error"', function() { 415 | it('with error message as first arg', function(done) { 416 | var json = { status:'error', message:'something bad' }, 417 | res = { 418 | json: function(output) { 419 | assert.deepEqual(output, { status:'error', message:'something bad' }); 420 | done(); 421 | } 422 | }; 423 | jsendInstance.middleware(req, res, function() { 424 | res.jsend(json.message); 425 | }); 426 | }); 427 | 428 | it('with Error object as first arg', function(done) { 429 | var json = { status:'error', message:'something bad' }, 430 | res = { 431 | json: function(output) { 432 | assert.isObject(output.data); 433 | assert.isString(output.data.stack); 434 | delete output.data; 435 | assert.deepEqual(output, json); 436 | done(); 437 | } 438 | }; 439 | jsendInstance.middleware(req, res, function() { 440 | res.jsend(new Error(json.message)); 441 | }); 442 | }); 443 | 444 | it('with jsend error object as first arg', function(done) { 445 | var json = { status:'error', message:'something bad' }, 446 | res = { 447 | json: function(output) { 448 | assert.deepEqual(jsendInstance.fromArguments(json), json); 449 | done(); 450 | } 451 | }; 452 | jsendInstance.middleware(req, res, function() { 453 | res.jsend(json); 454 | }); 455 | }); 456 | 457 | it('with jsend fail object as first arg', function(done) { 458 | var json = { status:'fail', data:{ something:'bad' } }, 459 | res = { 460 | json: function(output) { 461 | assert.deepEqual(jsendInstance.fromArguments(json), { status:'error', message:'Unknown error. (jsend)' }); 462 | done(); 463 | } 464 | }; 465 | jsendInstance.middleware(req, res, function() { 466 | res.jsend(json); 467 | }); 468 | }); 469 | 470 | it('with jsend fail object as first arg and preserve message', function(done) { 471 | var json = { status:'fail', data:{ something:'bad' }, message:'Really bad!' }, 472 | res = { 473 | json: function(output) { 474 | assert.deepEqual(jsendInstance.fromArguments(json), { status:'error', message:'Really bad!' }); 475 | done(); 476 | } 477 | }; 478 | jsendInstance.middleware(req, res, function() { 479 | res.jsend(json); 480 | }); 481 | }); 482 | 483 | it('with jsend success object as first arg', function(done) { 484 | var json = { status:'success', data:{ something:'bad' } }, 485 | res = { 486 | json: function(output) { 487 | assert.deepEqual(jsendInstance.fromArguments(json), { status:'error', message:'Unknown error. (jsend)' }); 488 | done(); 489 | } 490 | }; 491 | jsendInstance.middleware(req, res, function() { 492 | res.jsend(json); 493 | }); 494 | }); 495 | 496 | }); 497 | 498 | describe('should respond with "success"', function() { 499 | 500 | it('with jsend object', function(done) { 501 | var json = { status:'success', data:{ foo:'bar' } }, 502 | res = { 503 | json: function(output) { 504 | assert.deepEqual(output, json); 505 | done(); 506 | } 507 | }; 508 | jsendInstance.middleware(req, res, function() { 509 | res.jsend(null, json); 510 | }); 511 | }); 512 | 513 | it('with object data', function(done) { 514 | var json = { status:'success', data:{ foo:'bar' } }, 515 | res = { 516 | json: function(output) { 517 | assert.deepEqual(output, json); 518 | done(); 519 | } 520 | }; 521 | jsendInstance.middleware(req, res, function() { 522 | res.jsend(null, json.data); 523 | }); 524 | }); 525 | 526 | it('with array data', function(done) { 527 | var json = { status:'success', data:[1,2,3] }, 528 | res = { 529 | json: function(output) { 530 | assert.deepEqual(output, json); 531 | done(); 532 | } 533 | }; 534 | jsendInstance.middleware(req, res, function() { 535 | res.jsend(null, json.data); 536 | }); 537 | }); 538 | 539 | it('with string data', function(done) { 540 | var json = { status:'success', data:'you got it' }, 541 | res = { 542 | json: function(output) { 543 | assert.deepEqual(output, json); 544 | done(); 545 | } 546 | }; 547 | jsendInstance.middleware(req, res, function() { 548 | res.jsend(null, json.data); 549 | }); 550 | }); 551 | 552 | it('with numeric data', function(done) { 553 | var json = { status:'success', data:123 }, 554 | res = { 555 | json: function(output) { 556 | assert.deepEqual(output, json); 557 | done(); 558 | } 559 | }; 560 | jsendInstance.middleware(req, res, function() { 561 | res.jsend(null, json.data); 562 | }); 563 | }); 564 | 565 | it('with null data', function(done) { 566 | var json = { status:'success', data:null }, 567 | res = { 568 | json: function(output) { 569 | assert.deepEqual(output, json); 570 | done(); 571 | } 572 | }; 573 | jsendInstance.middleware(req, res, function() { 574 | res.jsend(null, json.data); 575 | }); 576 | }); 577 | 578 | }); 579 | 580 | describe('.success method', function() { 581 | 582 | it('with jsend object', function(done) { 583 | var json = { status:'success', data:{ foo:'bar' } }, 584 | res = { 585 | json: function(output) { 586 | assert.deepEqual(output, json); 587 | done(); 588 | } 589 | }; 590 | jsendInstance.middleware(req, res, function() { 591 | res.jsend.success(json); 592 | }); 593 | }); 594 | 595 | it('with object data', function(done) { 596 | var json = { status:'success', data:{ foo:'bar' } }, 597 | res = { 598 | json: function(output) { 599 | assert.deepEqual(output, json); 600 | done(); 601 | } 602 | }; 603 | jsendInstance.middleware(req, res, function() { 604 | res.jsend.success(json.data); 605 | }); 606 | }); 607 | 608 | it('with array data', function(done) { 609 | var json = { status:'success', data:[1,2,3] }, 610 | res = { 611 | json: function(output) { 612 | assert.deepEqual(output, json); 613 | done(); 614 | } 615 | }; 616 | jsendInstance.middleware(req, res, function() { 617 | res.jsend.success(json.data); 618 | }); 619 | }); 620 | 621 | it('with string data', function(done) { 622 | var json = { status:'success', data:'you got it' }, 623 | res = { 624 | json: function(output) { 625 | assert.deepEqual(output, json); 626 | done(); 627 | } 628 | }; 629 | jsendInstance.middleware(req, res, function() { 630 | res.jsend.success(json.data); 631 | }); 632 | }); 633 | 634 | it('with numeric data', function(done) { 635 | var json = { status:'success', data:123 }, 636 | res = { 637 | json: function(output) { 638 | assert.deepEqual(output, json); 639 | done(); 640 | } 641 | }; 642 | jsendInstance.middleware(req, res, function() { 643 | res.jsend.success(json.data); 644 | }); 645 | }); 646 | 647 | it('with null data', function(done) { 648 | var json = { status:'success', data:null }, 649 | res = { 650 | json: function(output) { 651 | assert.deepEqual(output, json); 652 | done(); 653 | } 654 | }; 655 | jsendInstance.middleware(req, res, function() { 656 | res.jsend.success(json.data); 657 | }); 658 | }); 659 | 660 | it('should throw error with no data', function(done) { 661 | var res = {}; 662 | jsendInstance.middleware(req, res, function() { 663 | assert.throws(function() { 664 | res.jsend.success(); 665 | }); 666 | done(); 667 | }); 668 | }); 669 | 670 | }); 671 | 672 | describe('.fail method', function() { 673 | 674 | it('with jsend object', function(done) { 675 | var json = { status:'fail', data:{ foo:'bar' } }, 676 | res = { 677 | json: function(output) { 678 | assert.deepEqual(output, json); 679 | done(); 680 | } 681 | }; 682 | jsendInstance.middleware(req, res, function() { 683 | res.jsend.fail(json); 684 | }); 685 | }); 686 | 687 | it('with object data', function(done) { 688 | var json = { status:'fail', data:{ foo:'bar' } }, 689 | res = { 690 | json: function(output) { 691 | assert.deepEqual(output, json); 692 | done(); 693 | } 694 | }; 695 | jsendInstance.middleware(req, res, function() { 696 | res.jsend.fail(json.data); 697 | }); 698 | }); 699 | 700 | it('with array data', function(done) { 701 | var json = { status:'fail', data:[1,2,3] }, 702 | res = { 703 | json: function(output) { 704 | assert.deepEqual(output, json); 705 | done(); 706 | } 707 | }; 708 | jsendInstance.middleware(req, res, function() { 709 | res.jsend.fail(json.data); 710 | }); 711 | }); 712 | 713 | it('with string data', function(done) { 714 | var json = { status:'fail', data:'you got it' }, 715 | res = { 716 | json: function(output) { 717 | assert.deepEqual(output, json); 718 | done(); 719 | } 720 | }; 721 | jsendInstance.middleware(req, res, function() { 722 | res.jsend.fail(json.data); 723 | }); 724 | }); 725 | 726 | it('with numeric data', function(done) { 727 | var json = { status:'fail', data:123 }, 728 | res = { 729 | json: function(output) { 730 | assert.deepEqual(output, json); 731 | done(); 732 | } 733 | }; 734 | jsendInstance.middleware(req, res, function() { 735 | res.jsend.fail(json.data); 736 | }); 737 | }); 738 | 739 | it('with null data', function(done) { 740 | var json = { status:'fail', data:null }, 741 | res = { 742 | json: function(output) { 743 | assert.deepEqual(output, json); 744 | done(); 745 | } 746 | }; 747 | jsendInstance.middleware(req, res, function() { 748 | res.jsend.fail(json.data); 749 | }); 750 | }); 751 | 752 | it('should throw error with no data', function(done) { 753 | var res = {}; 754 | jsendInstance.middleware(req, res, function() { 755 | assert.throws(function() { 756 | res.jsend.fail(); 757 | }); 758 | done(); 759 | }); 760 | }); 761 | 762 | }); 763 | 764 | describe('.error method', function() { 765 | 766 | it('with message', function(done) { 767 | var json = { status:'error', message:'something bad' }, 768 | res = { 769 | json: function(output) { 770 | assert.deepEqual(output, json); 771 | done(); 772 | } 773 | }; 774 | jsendInstance.middleware(req, res, function() { 775 | res.jsend.error(json.message); 776 | }); 777 | }); 778 | 779 | it('with message and code', function(done) { 780 | var json = { status:'error', message:'something bad', code:'BAD_THINGS' }, 781 | res = { 782 | json: function(output) { 783 | assert.deepEqual(output, json); 784 | done(); 785 | } 786 | }; 787 | jsendInstance.middleware(req, res, function() { 788 | res.jsend.error(json); 789 | }); 790 | }); 791 | 792 | it('with message and data', function(done) { 793 | var json = { status:'error', message:'something bad', data:{ foo:'bar' } }, 794 | res = { 795 | json: function(output) { 796 | assert.deepEqual(output, json); 797 | done(); 798 | } 799 | }; 800 | jsendInstance.middleware(req, res, function() { 801 | res.jsend.error(json); 802 | }); 803 | }); 804 | 805 | it('with message and data and code', function(done) { 806 | var json = { status:'error', message:'something bad', code:'BAD_THINGS', data:{ foo:'bar' } }, 807 | res = { 808 | json: function(output) { 809 | assert.deepEqual(output, json); 810 | done(); 811 | } 812 | }; 813 | jsendInstance.middleware(req, res, function() { 814 | res.jsend.error(json); 815 | }); 816 | }); 817 | 818 | it('should throw error with no message', function(done) { 819 | var json = { status:'error', code:'BAD_THINGS', data:{ foo:'bar' } }, 820 | res = {}; 821 | jsendInstance.middleware(req, res, function() { 822 | assert.throws(function() { 823 | res.jsend.error(json); 824 | }); 825 | done(); 826 | }); 827 | }); 828 | 829 | }); 830 | }); 831 | } 832 | 833 | describe('without strict flag', function() { 834 | var jsendInstance = jsend; 835 | 836 | basicTests(jsendInstance); 837 | }); 838 | 839 | describe('with strict flag', function() { 840 | var jsendInstance = jsend({ strict:true }); 841 | 842 | basicTests(jsendInstance); 843 | }); 844 | 845 | }); 846 | --------------------------------------------------------------------------------