Commits

Quentin Raynaud committed 7f28cb3

catch: add new Error & predicate optional arguments to catch

  • Participants
  • Parent commits 7053060

Comments (0)

Files changed (3)

File src/promise/catch.js

+'use strict';
+
+var newq = require('../newq');
+
+function checkErrorsAndPredicates(errorsAndPredicates, err) {
+  var any = !errorsAndPredicates.length;
+  _.each(errorsAndPredicates, function(test) {
+    if (!_.isFunction(test))
+      throw new Error('Invalid argument.');
+
+    if (test instanceof Error || test.prototype instanceof Error) {
+      any = any || err instanceof test;
+
+      return !any;
+    }
+
+    any = any || test(err);
+    return !any;
+  });
+  return any;
+}
+
+module.exports = function() {
+  var errorsAndPredicates = _.toArray(arguments);
+  var callback = errorsAndPredicates.pop();
+
+  return this.$$catch(function(err) {
+    if (!_.isFunction(callback) || !checkErrorsAndPredicates(errorsAndPredicates, err))
+      return newq.reject(err);
+
+    return callback.call(this, err);
+  });
+};

File src/promise/decorate.js

   any: callNewQ('any'),
   bind: require('./bind'),
   call: require('./call'),
-  'catch': function() {
-    return this.$$catch.apply(this, arguments);
-  },
+  'catch': require('./catch'),
   delay: require('./delay'),
   done: require('./done'),
   each: callNewQ('each'),

File tests/functionals/promise/catch.js

     $rootScope = _$rootScope_;
   }));
 
+  function createError() {
+    function SubError() {};
+    SubError.prototype = Object.create(Error.prototype);
+
+    return SubError;
+  }
+
+  function createPredicate(prom) {
+    return function(err) {
+      return !!err[prom];
+    }
+  }
+
   it('should be called on errors', function(done) {
     var test = new Error();
 
 
     $rootScope.$digest();
   });
+
+  it('should allow to catch only a specific error', function(done) {
+    var MyError1 = createError();
+    var MyError2 = createError();
+
+    var spy1 = sinon.spy();
+    var spy2 = sinon.spy(function(err) {
+      expect(err).to.be.an.instanceOf(MyError2);
+    });
+
+    expect(newq.reject(new MyError2()).catch(MyError1, spy1).catch(MyError2, spy2))
+      .to.eventually.be.fulfilled
+      .notify(done)
+    ;
+
+    $rootScope.$digest();
+
+    expect(spy1).to.not.have.been.called;
+    expect(spy2).to.have.been.calledOnce;
+  });
+
+  it('should allow to catch errors validating a given predicate', function(done) {
+    var test = new Error();
+    test.prop2 = true;
+
+    var spy1 = sinon.spy();
+    var spy2 = sinon.spy(function(err) {
+      expect(err).to.be.equal(test);
+    });
+
+    expect(newq.reject(test).catch(createPredicate('prop1'), spy1).catch(createPredicate('prop2'), spy2))
+      .to.eventually.be.fulfilled
+      .notify(done)
+    ;
+
+    $rootScope.$digest();
+
+    expect(spy1).to.not.have.been.called;
+    expect(spy2).to.have.been.calledOnce;
+  });
+
+  it('should support multiple error & predicates conditions', function(done) {
+    var test = new Error();
+
+    var spy1 = sinon.spy();
+    var spy2 = sinon.spy(function(err) {
+      expect(err).to.be.equal(test);
+    });
+
+    expect(newq.reject(test).catch(createPredicate('prop1'), createPredicate('prop2'), Error, spy2))
+      .to.eventually.be.fulfilled
+      .notify(done)
+    ;
+
+    $rootScope.$digest();
+
+    expect(spy1).to.not.have.been.called;
+    expect(spy2).to.have.been.calledOnce;
+  });
 });