[Pkg-javascript-commits] [node-errs] 01/02: Imported Upstream version 0.3.2
Thorsten Alteholz
alteholz at moszumanska.debian.org
Sun Jul 17 13:15:29 UTC 2016
This is an automated email from the git hooks/post-receive script.
alteholz pushed a commit to branch master
in repository node-errs.
commit 115daf5893927fe579299aea45f772fe1f4f0585
Author: Thorsten Alteholz <debian at alteholz.de>
Date: Sun Jul 17 15:15:27 2016 +0200
Imported Upstream version 0.3.2
---
.gitignore | 3 +
.travis.yml | 10 ++
LICENSE | 19 +++
README.md | 256 ++++++++++++++++++++++++++++++++
examples/async-uncaught-exception.js | 9 ++
examples/custom-error.js | 22 +++
examples/handling-streams.js | 14 ++
examples/stack.js | 7 +
examples/sync-uncaught-exception.js | 8 +
lib/errs.js | 276 +++++++++++++++++++++++++++++++++++
package.json | 29 ++++
test/errs-test.js | 225 ++++++++++++++++++++++++++++
test/fixtures.js | 23 +++
test/macros.js | 91 ++++++++++++
14 files changed, 992 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8d4c2d1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+node_modules
+.DS_Store
+npm-debug.log
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..b6a50e4
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,10 @@
+language: node_js
+node_js:
+ - 0.8
+ - 0.10
+
+notifications:
+ email:
+ - travis at nodejitsu.com
+ irc: "irc.freenode.org#nodejitsu"
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..12fd0a3
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2012 Charlie Robbins, Nuno Job, and the Contributors.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..f6f2e55
--- /dev/null
+++ b/README.md
@@ -0,0 +1,256 @@
+# errs [![Build Status](https://secure.travis-ci.org/flatiron/errs.png)](http://travis-ci.org/flatiron/errs)
+
+Simple error creation and passing utilities focused on:
+
+* [Creating Errors](#creating-errors)
+* [Reusing Error Types](#reusing-types)
+* [Merging with Existing Errors](#merging-errors)
+* [Optional Callback Invocation](#optional-invocation)
+* [Piping Error Events](#piping-errors)
+
+<a name="creating-errors" />
+## Creating Errors
+
+You should know by now that [a String is not an Error][0]. Unfortunately the `Error` constructor in Javascript isn't all that convenient either. How often do you find yourself in this situation?
+
+``` js
+ var err = new Error('This is an error. There are many like it.');
+ err.someProperty = 'more syntax';
+ err.someOtherProperty = 'it wont stop.';
+ err.notEven = 'for the mayor';
+
+ throw err;
+```
+
+Rest your fingers, `errs` is here to help. The following is equivalent to the above:
+
+``` js
+ var errs = require('errs');
+
+ throw errs.create({
+ message: 'This is an error. There are many like it.',
+ someProperty: 'more syntax',
+ someOtherProperty: 'it wont stop.',
+ notEven: 'for the mayor'
+ });
+```
+
+<a name="reusing-types" />
+## Reusing Custom Error Types
+
+`errs` also exposes an [inversion of control][1] interface for easily reusing custom error types across your application. Custom Error Types registered with `errs` will transparently invoke `Error` constructor and `Error.captureStackTrace` to attach transparent stack traces:
+
+``` js
+ /*
+ * file-a.js: Create and register your error type.
+ *
+ */
+
+ var util = require('util'),
+ errs = require('errs');
+
+ function MyError() {
+ this.message = 'This is my error; I made it myself. It has a transparent stack trace.';
+ }
+
+ //
+ // Alternatively `MyError.prototype.__proto__ = Error;`
+ //
+ util.inherits(MyError, Error);
+
+ //
+ // Register the error type
+ //
+ errs.register('myerror', MyError);
+
+
+
+ /*
+ * file-b.js: Use your error type.
+ *
+ */
+
+ var errs = require('errs');
+
+ console.log(
+ errs.create('myerror')
+ .stack
+ .split('\n')
+ );
+```
+
+The output from the two files above is shown below. Notice how it contains no references to `errs.js`:
+
+```
+[ 'MyError: This is my error; I made it myself. It has a transparent stack trace.',
+ ' at Object.<anonymous> (/file-b.js:19:8)',
+ ' at Module._compile (module.js:441:26)',
+ ' at Object..js (module.js:459:10)',
+ ' at Module.load (module.js:348:31)',
+ ' at Function._load (module.js:308:12)',
+ ' at Array.0 (module.js:479:10)',
+ ' at EventEmitter._tickCallback (node.js:192:40)' ]
+```
+
+<a name="merging-errors" />
+## Merging with Existing Errors
+
+When working with errors you catch or are returned in a callback you can extend those errors with properties by using the `errs.merge` method. This will also create a human readable error message and stack-trace:
+
+``` js
+process.on('uncaughtException', function(err) {
+ console.log(errs.merge(err, {namespace: 'uncaughtException'}));
+});
+
+var file = fs.createReadStream('FileDoesNotExist.here');
+```
+
+``` js
+{ [Error: Unspecified error]
+ name: 'Error',
+ namespace: 'uncaughtException',
+ errno: 34,
+ code: 'ENOENT',
+ path: 'FileDoesNotExist.here',
+ description: 'ENOENT, no such file or directory \'FileDoesNotExist.here\'',
+ stacktrace: [ 'Error: ENOENT, no such file or directory \'FileDoesNotExist.here\'' ] }
+```
+
+<a name="optional-invocation" />
+## Optional Callback Invocation
+
+Node.js handles asynchronous IO through the elegant `EventEmitter` API. In many scenarios the `callback` may be optional because you are returning an `EventEmitter` for piping or other event multiplexing. This complicates code with a lot of boilerplate:
+
+``` js
+ function importantFeature(callback) {
+ return someAsyncFn(function (err) {
+ if (err) {
+ if (callback) {
+ return callback(err);
+ }
+
+ throw err;
+ }
+ });
+ }
+```
+
+`errs` it presents a common API for both emitting `error` events and invoking continuations (i.e. callbacks) with errors. If a `callback` is supplied to `errs.handle()` it will be invoked with the error. It no `callback` is provided then an `EventEmitter` is returned which emits an `error` event on the next tick:
+
+``` js
+ function importantFeature(callback) {
+ return someAsyncFn(function (err) {
+ if (err) {
+ return errs.handle(err, callback);
+ }
+ });
+ }
+```
+
+<a name="piping-errors" />
+## Piping Errors
+
+Often when working with streams (especially when buffering for whatever reason), you may have already returned an `EventEmitter` or `Stream` instance by the time an error is handled.
+
+``` js
+ function pipeSomething(callback) {
+ //
+ // You have a stream (e.g. http.ResponseStream) and you
+ // have an optional `callback`.
+ //
+ var stream = new require('stream').Stream;
+
+ //
+ // You need to do something async which may respond with an
+ // error
+ //
+ getAnotherStream(function (err, source) {
+ if (err) {
+ if (callback)
+ callback(err);
+ }
+
+ stream.emit('error', err);
+ return;
+ }
+
+ source.pipe(stream);
+ })
+
+ return stream;
+ }
+```
+
+You may pass either a `function` or `EventEmitter` instance to `errs.handle`.
+
+``` js
+ function pipeSomething(callback) {
+ //
+ // You have a stream (e.g. http.ResponseStream) and you
+ // have an optional `callback`.
+ //
+ var stream = new require('stream').Stream;
+
+ //
+ // You need to do something async which may respond with an
+ // error
+ //
+ getAnotherStream(function (err, source) {
+ if (err) {
+ //
+ // Invoke the callback if it exists otherwise the stream.
+ //
+ return errs.handle(err, callback || stream);
+ }
+
+ source.pipe(stream);
+ })
+
+ return stream;
+ }
+```
+
+If you wish to invoke both a `callback` function and an `error` event simply pass both:
+
+``` js
+ errs.handle(err, callback, stream);
+```
+
+## Methods
+The `errs` modules exposes some simple utility methods:
+
+* `.create(type, opts)`: Creates a new error instance for with the specified `type` and `opts`. If the `type` is not registered then a new `Error` instance will be created.
+* `.register(type, proto)`: Registers the specified `proto` to `type` for future calls to `errors.create(type, opts)`.
+* `.unregister(type)`: Unregisters the specified `type` for future calls to `errors.create(type, opts)`.
+* `.handle(err, callback)`: Attempts to instantiate the given `error`. If the `error` is already a properly formed `error` object (with a `stack` property) it will not be modified.
+* `.merge(err, type, opts)`: Merges an existing error with a new error instance for with the specified `type` and `opts`.
+
+## Installation
+
+### Installing npm (node package manager)
+
+``` bash
+ $ curl http://npmjs.org/install.sh | sh
+```
+
+### Installing errs
+
+``` bash
+ $ [sudo] npm install errs
+```
+
+## Tests
+All tests are written with [vows][2] and should be run with [npm][3]:
+
+``` bash
+ $ npm test
+```
+
+#### Author: [Charlie Robbins](http://github.com/indexzero)
+#### Contributors: [Nuno Job](http://github.com/dscape)
+#### License: MIT
+
+[0]: http://www.devthought.com/2011/12/22/a-string-is-not-an-error/
+[1]: http://martinfowler.com/articles/injection.html
+[2]: https://vowsjs.org
+[3]: https://npmjs.org
diff --git a/examples/async-uncaught-exception.js b/examples/async-uncaught-exception.js
new file mode 100644
index 0000000..7cbf42d
--- /dev/null
+++ b/examples/async-uncaught-exception.js
@@ -0,0 +1,9 @@
+var fs = require('fs'),
+ errs = require('../lib/errs');
+
+process.on('uncaughtException', function(err) {
+ console.log(errs.merge(err, {namespace: 'uncaughtException'}));
+});
+
+var file = fs.createReadStream(__filename, {encoding: 'utf8'});
+file.on('data', function(b) { throw new Error('Oh Noes'); });
diff --git a/examples/custom-error.js b/examples/custom-error.js
new file mode 100644
index 0000000..b964e31
--- /dev/null
+++ b/examples/custom-error.js
@@ -0,0 +1,22 @@
+var util = require('util'),
+ errs = require('../lib/errs');
+
+function MyError () {
+ this.message = 'This is my error; I made it myself. It has a transparent stack trace.';
+}
+
+//
+// Alternatively `MyError.prototype.__proto__ = Error;`
+//
+util.inherits(MyError, Error);
+
+//
+// Register the error type
+//
+errs.register('myerror', MyError);
+
+console.log(
+ errs.create('myerror')
+ .stack
+ .split('\n')
+);
\ No newline at end of file
diff --git a/examples/handling-streams.js b/examples/handling-streams.js
new file mode 100644
index 0000000..725b59c
--- /dev/null
+++ b/examples/handling-streams.js
@@ -0,0 +1,14 @@
+var fs = require('fs'),
+ errs = require('../lib/errs');
+
+function safeReadStream(no_such_file, callback) {
+ try {
+ return fs.createReadStream(no_such_file, callback);
+ } catch (err) {
+ return errs.handle(err, callback);
+ }
+}
+
+// would throw, now even without a callback it gets picked as a stream
+var file = fs.createReadStream('FileDoesNotExist.here');
+file.on('error', function (err) { console.log(err); });
\ No newline at end of file
diff --git a/examples/stack.js b/examples/stack.js
new file mode 100644
index 0000000..3672807
--- /dev/null
+++ b/examples/stack.js
@@ -0,0 +1,7 @@
+var errs = require('../lib/errs');
+
+console.log(
+ errs.create('This is an error. There are many like it. It has a transparent stack trace.')
+ .stack
+ .split('\n')
+);
\ No newline at end of file
diff --git a/examples/sync-uncaught-exception.js b/examples/sync-uncaught-exception.js
new file mode 100644
index 0000000..11b04ef
--- /dev/null
+++ b/examples/sync-uncaught-exception.js
@@ -0,0 +1,8 @@
+var fs = require('fs'),
+ errs = require('../lib/errs');
+
+process.on('uncaughtException', function(err) {
+ console.log(errs.merge(err, {namespace: 'uncaughtException'}));
+});
+
+var file = fs.createReadStream('FileDoesNotExist.here');
diff --git a/lib/errs.js b/lib/errs.js
new file mode 100644
index 0000000..6beaaf3
--- /dev/null
+++ b/lib/errs.js
@@ -0,0 +1,276 @@
+/*
+ * errs.js: Simple error creation and passing utilities.
+ *
+ * (C) 2012, Charlie Robbins, Nuno Job, and the Contributors.
+ * MIT LICENSE
+ *
+ */
+
+var events = require('events'),
+ util = require('util');
+
+//
+// Container for registered error types.
+//
+exports.registered = {};
+
+//
+// Add `Error.prototype.toJSON` if it doesn't exist.
+//
+if (!Error.prototype.toJSON) {
+ Object.defineProperty(Error.prototype, 'toJSON', {
+ enumerable: false,
+ writable: true,
+ value: function () {
+ return mixin({
+ message: this.message,
+ stack: this.stack,
+ arguments: this.arguments,
+ type: this.type
+ }, this);
+ }
+ });
+}
+
+//
+// ### function create (type, opts)
+// #### @type {string} **Optional** Registered error type to create
+// #### @opts {string|object|Array|function} Options for creating the error:
+// * `string`: Message for the error
+// * `object`: Properties to include on the error
+// * `array`: Message for the error (' ' joined).
+// * `function`: Function to return error options.
+//
+// Creates a new error instance for with the specified `type`
+// and `options`. If the `type` is not registered then a new
+// `Error` instance will be created.
+//
+exports.create = function createErr(type, opts) {
+ if (!arguments[1] && !exports.registered[type]) {
+ opts = type;
+ type = null;
+ }
+
+ //
+ // If the `opts` has a `stack` property assume
+ // that it is already an error instance.
+ //
+ if (opts && opts.stack) {
+ return opts;
+ }
+
+ var message,
+ ErrorProto,
+ error;
+
+ //
+ // Parse arguments liberally for the message
+ //
+ if (typeof opts === 'function') {
+ opts = opts();
+ }
+
+ if (Array.isArray(opts)) {
+ message = opts.join(' ');
+ opts = null;
+ }
+ else if (opts) {
+ switch (typeof opts) {
+ case 'string':
+ message = opts || 'Unspecified error';
+ opts = null;
+ break;
+ case 'object':
+ message = (opts && opts.message) || 'Unspecified error';
+ break;
+ default:
+ message = 'Unspecified error';
+ break;
+ }
+ }
+
+ //
+ // Instantiate a new Error instance or a new
+ // registered error type (if it exists).
+ //
+ ErrorProto = type && exports.registered[type] || Error;
+ error = new (ErrorProto)(message);
+
+ if (!error.name || error.name === 'Error') {
+ error.name = (opts && opts.name) || ErrorProto.name || 'Error';
+ }
+
+ //
+ // Capture a stack trace if it does not already exist and
+ // remote the part of the stack trace referencing `errs.js`.
+ //
+ if (!error.stack) {
+ Error.call(error);
+ Error.captureStackTrace(error, createErr);
+ }
+ else {
+ error.stack = error.stack.split('\n');
+ error.stack.splice(1, 1);
+ error.stack = error.stack.join('\n');
+ }
+
+ //
+ // Copy all options to the new error instance.
+ //
+ if (opts) {
+ Object.keys(opts).forEach(function (key) {
+ error[key] = opts[key];
+ });
+ }
+
+ return error;
+};
+
+//
+// ### function merge (err, type, opts)
+// #### @err {error} **Optional** The error to merge
+// #### @type {string} **Optional** Registered error type to create
+// #### @opts {string|object|Array|function} Options for creating the error:
+// * `string`: Message for the error
+// * `object`: Properties to include on the error
+// * `array`: Message for the error (' ' joined).
+// * `function`: Function to return error options.
+//
+// Merges an existing error with a new error instance for with
+// the specified `type` and `options`.
+//
+exports.merge = function (err, type, opts) {
+ var merged = exports.create(type, opts);
+
+ //
+ // If there is no error just return the merged one
+ //
+ if (err == undefined || err == null) {
+ return merged;
+ }
+
+ //
+ // optional stuff that might be created by module
+ //
+ if (!Array.isArray(err) && typeof err === 'object') {
+ Object.keys(err).forEach(function (key) {
+ //
+ // in node v0.4 v8 errors where treated differently
+ // we need to make sure we aren't merging these properties
+ // http://code.google.com/p/v8/issues/detail?id=1215
+ //
+ if (['stack', 'type', 'arguments', 'message'].indexOf(key)===-1) {
+ merged[key] = err[key];
+ }
+ });
+ }
+
+ // merging
+ merged.name = merged.name || err.name;
+ merged.message = merged.message || err.message;
+
+ // override stack
+ merged.stack = err.stack || merged.stack;
+
+ // add human-readable errors
+ if (err.message) {
+ merged.description = err.message;
+ }
+
+ if (err.stack && err.stack.split) {
+ merged.stacktrace = err.stack.split("\n");
+ }
+
+ return merged;
+};
+
+//
+// ### function handle (error, callback)
+// #### @error {string|function|Array|object} Error to handle
+// #### @callback {function|EventEmitter} **Optional** Continuation or stream to pass the error to.
+// #### @stream {EventEmitter} **Optional** Explicit EventEmitter to use.
+//
+// Attempts to instantiate the given `error`. If the `error` is already a properly
+// formed `error` object (with a `stack` property) it will not be modified.
+//
+// * If `callback` is a function, it is invoked with the `error`.
+// * If `callback` is an `EventEmitter`, it emits the `error` event on
+// that emitter and returns it.
+// * If no `callback`, return a new `EventEmitter` which emits `error`
+// on `process.nextTick()`.
+//
+exports.handle = function (error, callback, stream) {
+ error = exports.create(error);
+
+ if (typeof callback === 'function') {
+ callback(error);
+ }
+
+ if (typeof callback !== 'function' || stream) {
+ var emitter = stream || callback || new events.EventEmitter();
+ process.nextTick(function () { emitter.emit('error', error); });
+ return emitter;
+ }
+};
+
+//
+// ### function register (type, proto)
+// #### @type {string} **Optional** Type of the error to register.
+// #### @proto {function} Constructor function of the error to register.
+//
+// Registers the specified `proto` to `type` for future calls to
+// `errors.create(type, opts)`.
+//
+exports.register = function (type, proto) {
+ if (arguments.length === 1) {
+ proto = type;
+ type = proto.name.toLowerCase();
+ }
+ exports.registered[type] = proto;
+};
+
+//
+// ### function unregister (type)
+// #### @type {string} Type of the error to unregister.
+//
+// Unregisters the specified `type` for future calls to
+// `errors.create(type, opts)`.
+//
+exports.unregister = function (type) {
+ delete exports.registered[type];
+};
+
+//
+// ### function mixin (target [source0, source1, ...])
+// Copies enumerable properties from `source0 ... sourceN`
+// onto `target` and returns the resulting object.
+//
+function mixin(target) {
+ //
+ // Quickly and performantly (in V8) `Arrayify` arguments.
+ //
+ var len = arguments.length,
+ args = new Array(len - 1),
+ i = 1;
+
+ for (; i < len; i++) {
+ args[i - 1] = arguments[i];
+ }
+
+ args.forEach(function (o) {
+ Object.keys(o).forEach(function (attr) {
+ var getter = o.__lookupGetter__(attr),
+ setter = o.__lookupSetter__(attr);
+
+ if (!getter && !setter) {
+ target[attr] = o[attr];
+ }
+ else {
+ if (setter) { target.__defineSetter__(attr, setter) }
+ if (getter) { target.__defineGetter__(attr, getter) }
+ }
+ });
+ });
+
+ return target;
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..7593a4b
--- /dev/null
+++ b/package.json
@@ -0,0 +1,29 @@
+{
+ "name": "errs",
+ "description": "Simple error creation and passing utilities",
+ "version": "0.3.2",
+ "author": "Charlie Robbins <charlie.robbins at gmail.com>",
+ "maintainers": [
+ "dscape <nuno at nodejitsu.com>"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "http://github.com/indexzero/errs.git"
+ },
+ "keywords": [
+ "errors",
+ "error",
+ "utilities"
+ ],
+ "devDependencies": {
+ "vows": "0.8.x"
+ },
+ "main": "./lib/errs",
+ "scripts": {
+ "test": "vows test/*-test.js --spec"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+}
+
diff --git a/test/errs-test.js b/test/errs-test.js
new file mode 100644
index 0000000..2c9d39a
--- /dev/null
+++ b/test/errs-test.js
@@ -0,0 +1,225 @@
+/*
+ * errs-test.js: Tests for the `errs` module.
+ *
+ * (C) 2012, Charlie Robbins, Nuno Job, and the Contributors.
+ * MIT LICENSE
+ *
+ */
+
+var assert = require('assert'),
+ events = require('events'),
+ vows = require('vows'),
+ errs = require('../lib/errs'),
+ fixtures = require('./fixtures'),
+ macros = require('./macros');
+
+var opts = [{
+ foo: 'bar',
+ status: 404,
+ whatever: 'some other property'
+}, {
+ testing: true,
+ 'some-string': 'is-a-value',
+ message: 'This is an error. There are many like it.'
+}, {
+ 'a-function': 'that returns an object',
+ should: true,
+ have: 4,
+ properties: 'yes'
+}];
+
+vows.describe('errs').addBatch({
+ "Using errs module": {
+ "the register() method": {
+ "should register the prototype": function () {
+ errs.register('named', fixtures.NamedError);
+ assert.equal(errs.registered['named'], fixtures.NamedError);
+ },
+ "should register an error without providing its name": function () {
+ errs.register(fixtures.AnError);
+ assert.equal(errs.registered['anerror'], fixtures.AnError);
+ }
+ },
+ "the create() method with": {
+ "a string": macros.create.string('An error as a string'),
+ "no parameters": macros.create.string('An error as a string'),
+ "an object": {
+ "that has no message": macros.create.object(opts[0]),
+ "that has a message": macros.create.object(opts[1]),
+ "that has a name": {
+ topic : errs.create({name: 'OverflowError'}),
+ "should respect that name in the stack trace" : function (err) {
+ assert.match(err.stack, /^OverflowError/);
+ },
+ }
+ },
+ "an error": macros.create.err(new Error('An instance of an error')),
+ "a function": macros.create.fn(function () {
+ return opts[2];
+ }),
+ "a registered type": {
+ "that exists": macros.create.registered('named', fixtures.NamedError, opts[1]),
+ "that doesnt exist": macros.create.registered('bad', null, opts[1])
+ }
+ },
+ "the handle() method": {
+ "with a callback": {
+ topic: function () {
+ var err = this.err = errs.create('Some async error');
+ errs.handle(err, this.callback.bind(this, null));
+ },
+ "should invoke the callback with the error": function (_, err) {
+ assert.equal(err, this.err);
+ }
+ },
+ "with an EventEmitter (i.e. stream)": {
+ topic: function () {
+ var err = this.err = errs.create('Some emitted error'),
+ stream = new events.EventEmitter();
+
+ stream.once('error', this.callback.bind(this, null));
+ errs.handle(err, stream);
+ },
+ "should emit the `error` event": function (_, err) {
+ assert.equal(err, this.err);
+ }
+ },
+ "with a callback and an EventEmitter": {
+ topic: function () {
+ var err = this.err = errs.create('Some emitted error'),
+ stream = new events.EventEmitter(),
+ invoked = 0,
+ that = this;
+
+ function onError(err) {
+ if (++invoked === 2) {
+ that.callback.call(that, null, err);
+ }
+ }
+
+ stream.once('error', onError);
+ errs.handle(err, onError, stream);
+ },
+ "should emit the `error` event": function (_, err) {
+ assert.equal(err, this.err);
+ }
+ },
+ "with no callback": {
+ topic: function () {
+ var err = this.err = errs.create('Some emitted error'),
+ emitter = errs.handle(err);
+
+ emitter.once('error', this.callback.bind(this, null));
+ },
+ "should emit the `error` event": function (_, err) {
+ assert.equal(err, this.err);
+ }
+ }
+ }
+ }
+}).addBatch({
+ "Using errs module": {
+ "the unregister() method": {
+ "should unregister the prototype": function () {
+ errs.unregister('named');
+ assert.isTrue(!errs.registered['named']);
+ }
+ }
+ }
+}).addBatch({
+ "Using errs module": {
+ "the merge() method": {
+ "supports": {
+ "an undefined error": function () {
+ var err = errs.merge(undefined, { message: 'oh noes!' });
+ assert.equal(err.message, 'oh noes!')
+ assert.instanceOf(err, Error);
+ },
+ "a null error": function () {
+ var err = errs.merge(null, { message: 'oh noes!' });
+ assert.equal(err.message, 'oh noes!')
+ assert.instanceOf(err, Error);
+ },
+ "a false error": function () {
+ var err = errs.merge(false, { message: 'oh noes!' });
+ assert.equal(err.message, 'oh noes!')
+ assert.instanceOf(err, Error);
+ },
+ "a string error": function () {
+ var err = errs.merge('wat', { message: 'oh noes!' });
+ assert.equal(err.message, 'oh noes!');
+ assert.instanceOf(err, Error);
+ },
+ },
+ "should preserve custom properties": function () {
+ var err = new Error('Msg!');
+ err.foo = "bar";
+ err = errs.merge(err, {message: "Override!", ns: "test"});
+ assert.equal(err.foo, "bar");
+ },
+ "should have a stack trace": function () {
+ var err = new Error('Msg!');
+ err = errs.merge(err, {});
+ assert.isTrue(Array.isArray(err.stacktrace));
+ },
+ "should preserve message specified in create": function () {
+ var err = new Error('Msg!');
+ err = errs.merge(err, {message: "Override!"});
+ assert.equal(err.message, "Override!");
+ },
+ "should preserve properties specified": function () {
+ var err = new Error('Msg!');
+ err = errs.merge(err, {ns: "test"});
+ assert.equal(err.ns, "test");
+ },
+ "with a truthy value": function () {
+ var err = errs.merge(true, {
+ message: 'Override!',
+ ns: 'lolwut'
+ })
+ assert.equal(err.message, 'Override!');
+ assert.equal(err.ns, 'lolwut');
+ },
+ "with a truthy stack": function () {
+ var err = errs.merge({ stack: true } , {
+ message: 'Override!',
+ ns: 'lolwut'
+ })
+ assert.equal(err.message, 'Override!');
+ assert.equal(err.ns, 'lolwut');
+ },
+ "with an Array stack": function () {
+ var err = errs.merge({ stack: [] } , {
+ message: 'Override!',
+ ns: 'lolwut'
+ })
+ assert.equal(err.message, 'Override!');
+ assert.equal(err.ns, 'lolwut');
+ }
+ }
+ }
+}).addBatch({
+ "Using errs module": {
+ "Error.prototype.toJSON": {
+ "should exist": function () {
+ assert.isFunction(Error.prototype.toJSON);
+
+ var json = (new Error('Testing 12345')).toJSON();
+
+ ['message', 'stack', 'arguments', 'type'].forEach(function (prop) {
+ assert.isObject(Object.getOwnPropertyDescriptor(json, prop));
+ })
+ },
+ "should be writable": function () {
+ var orig = Error.prototype.toJSON;
+ Error.prototype.toJSON = function() {
+ return 'foo';
+ };
+ var json = (new Error('Testing 12345')).toJSON();
+
+ assert.equal(json, 'foo');
+ Error.prototype.toJSON = orig;
+ }
+ }
+ }
+}).export(module);
diff --git a/test/fixtures.js b/test/fixtures.js
new file mode 100644
index 0000000..cc13b22
--- /dev/null
+++ b/test/fixtures.js
@@ -0,0 +1,23 @@
+/*
+ * fixtures.js: Test fixtures for the `errs` module.
+ *
+ * (C) 2012, Charlie Robbins, Nuno Job, and the Contributors.
+ * MIT LICENSE
+ *
+ */
+
+var util = require('util');
+
+var fixtures = exports;
+
+fixtures.NamedError = function NamedError() {
+ this.named = true;
+};
+
+util.inherits(fixtures.NamedError, Error);
+
+fixtures.AnError = function AnError() {
+ this.named = true;
+};
+
+util.inherits(fixtures.AnError, Error);
diff --git a/test/macros.js b/test/macros.js
new file mode 100644
index 0000000..2b962d4
--- /dev/null
+++ b/test/macros.js
@@ -0,0 +1,91 @@
+/*
+ * macros.js: Test macros for the `errs` module.
+ *
+ * (C) 2012, Charlie Robbins, Nuno Job, and the Contributors.
+ * MIT LICENSE
+ *
+ */
+
+var assert = require('assert'),
+ errs = require('../lib/errs');
+
+var macros = exports;
+
+function assertTransparentStack(err) {
+ assert.isString(err.stack);
+ err.stack.split('\n').forEach(function (line) {
+ assert.isFalse(/\/lib\/errs\.js\:/.test(line));
+ });
+}
+
+//
+// Macros for `errs.create(type, opts)`.
+//
+macros.create = {};
+
+macros.create.string = function (msg) {
+ return {
+ topic: errs.create(msg),
+ "should create an error with the correct message": function (err) {
+ assert.instanceOf(err, Error);
+ assert.equal(msg, err.message);
+ assertTransparentStack(err);
+ }
+ };
+};
+
+macros.create.object = function (obj) {
+ return {
+ topic: errs.create(obj),
+ "should create an error with the specified properties": function (err) {
+ assert.instanceOf(err, Error);
+ assert.equal(err.message, obj.message || 'Unspecified error');
+ assertTransparentStack(err);
+ Object.keys(obj).forEach(function (key) {
+ assert.equal(err[key], obj[key]);
+ });
+ }
+ };
+};
+
+macros.create.err = function (inst) {
+ return {
+ topic: errs.create(inst),
+ "should return the error unmodified": function (err) {
+ assert.equal(err, inst);
+ assertTransparentStack(err);
+ }
+ };
+};
+
+macros.create.fn = function (fn) {
+ var obj = fn();
+
+ return {
+ topic: errs.create(fn),
+ "should create an error with the specified properties": function (err) {
+ assert.instanceOf(err, Error);
+ assert.equal(err.message, obj.message || 'Unspecified error');
+ assertTransparentStack(err);
+ Object.keys(obj).forEach(function (key) {
+ assert.equal(err[key], obj[key]);
+ });
+ }
+ };
+};
+
+macros.create.registered = function (type, proto, obj) {
+ return {
+ topic: function () {
+ return errs.create(type, obj);
+ },
+ "should create an error of the correct type": function (err) {
+ assert.instanceOf(err, proto || Error);
+ assert.equal(err.message, obj.message || 'Unspecified error');
+ assertTransparentStack(err);
+ Object.keys(obj).forEach(function (key) {
+ assert.equal(err[key], obj[key]);
+ });
+ }
+ };
+};
\ No newline at end of file
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-errs.git
More information about the Pkg-javascript-commits
mailing list