Repository: chaijs/chai
Pull request #779 (2016-09-01 17:37:38)

Adding `.finite`. Fixes #271
As discussed in #271, `.isNumber` currently passes for `NaN`. This issue recently bit our team and so we wanted to move forward on the proposal in that issue. 

The implementation is the polyfill from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite.


Patch:
diff --git a/lib/chai/core/assertions.js b/lib/chai/core/assertions.js
index ee442b2..d38aaae 100644
--- a/lib/chai/core/assertions.js
+++ b/lib/chai/core/assertions.js
@@ -2145,4 +2145,27 @@ module.exports = function (chai, _) {
       , 'expected #{this} to not be frozen'
     );
   });
+
+  /**
+   * ### .finite
+   *
+   * Asserts that the target is a finite number. Unlike `.a('number')`, this will fail for `NaN` and `Infinity`.
+   *
+   *     expect(4).to.be.finite;
+   *     expect(NaN).to.not.be.finite;
+   *
+   * @name finite
+   * @namespace BDD
+   * @api public
+   */
+
+  Assertion.addProperty('finite', function(msg) {
+    var obj = flag(this, 'object');
+
+    this.assert(
+        typeof obj === "number" && isFinite(obj)
+      , 'expected #{this} to be a finite number'
+      , 'expected #{this} to not be a finite number'
+    );
+  });
 };
diff --git a/lib/chai/interface/assert.js b/lib/chai/interface/assert.js
index 898e5b6..3d1f692 100644
--- a/lib/chai/interface/assert.js
+++ b/lib/chai/interface/assert.js
@@ -732,6 +732,27 @@ module.exports = function (chai, util) {
     new Assertion(val, msg).to.not.be.a('number');
   };
 
+   /**
+   * ### .isFinite(value, [message])
+   *
+   * Asserts that `value` is a finite number. Unlike `.isNumber`, this will fail for `NaN` and `Infinity`
+   *
+   *     var cups = 2;
+   *     assert.isFinite(cups, 'how many cups');
+   *
+   *     assert.isFinite(NaN); // throws
+   *
+   * @name isFinite
+   * @param {Number} value
+   * @param {String} message
+   * @namespace Assert
+   * @api public
+   */
+
+  assert.isFinite = function (val, msg) {
+    new Assertion(val, msg).to.be.finite;
+  };
+
   /**
    * ### .isBoolean(value, [message])
    *


Test patch:
diff --git a/test/assert.js b/test/assert.js
index 91da9d5..8140b7a 100644
--- a/test/assert.js
+++ b/test/assert.js
@@ -459,6 +459,31 @@ describe('assert', function () {
     }, "expected 4 not to be a number");
   });
 
+  it('isFinite', function() {
+    assert.isFinite(4);
+    assert.isFinite(-10);
+
+    err(function(){
+      assert.isFinite(NaN);
+    }, "expected NaN to be a finite number");
+
+    err(function(){
+      assert.isFinite(Infinity);
+    }, "expected Infinity to be a finite number");
+
+    err(function(){
+      assert.isFinite('foo');
+    }, "expected \'foo\' to be a finite number");
+
+    err(function(){
+      assert.isFinite([]);
+    }, "expected [] to be a finite number");
+
+    err(function(){
+      assert.isFinite({});
+    }, "expected {} to be a finite number");
+  })
+
   it('isBoolean', function() {
     assert.isBoolean(true);
     assert.isBoolean(false);
diff --git a/test/expect.js b/test/expect.js
index 8560608..42b50e6 100644
--- a/test/expect.js
+++ b/test/expect.js
@@ -493,6 +493,31 @@ describe('expect', function () {
     }, "expected 'foo' not to be NaN");
   });
 
+  it('finite', function() {
+    expect(4).to.be.finite;
+    expect(-10).to.be.finite;
+
+    err(function(){
+      expect(NaN).to.be.finite;
+    }, "expected NaN to be a finite number");
+
+    err(function(){
+      expect(Infinity).to.be.finite;
+    }, "expected Infinity to be a finite number");
+
+    err(function(){
+      expect('foo').to.be.finite;
+    }, "expected \'foo\' to be a finite number");
+
+    err(function(){
+      expect([]).to.be.finite;
+    }, "expected [] to be a finite number");
+
+    err(function(){
+      expect({}).to.be.finite;
+    }, "expected {} to be a finite number");
+  });
+
   it('property(name)', function(){
     expect('test').to.have.property('length');
     expect(4).to.not.have.property('length');
diff --git a/test/should.js b/test/should.js
index 19a90ac..c32a9e3 100644
--- a/test/should.js
+++ b/test/should.js
@@ -431,6 +431,31 @@ describe('should', function() {
     }, "expected { foo: \'bar\' } to be empty");
   });
 
+  it('finite(value)', function() {
+    (4).should.be.finite;
+    (-10).should.be.finite;
+
+    err(function(){
+      (NaN).should.be.finite;
+    }, "expected NaN to be a finite number");
+
+    err(function(){
+      (Infinity).should.be.finite;
+    }, "expected Infinity to be a finite number");
+
+    err(function(){
+      ('foo').should.be.finite;
+    }, "expected \'foo\' to be a finite number");
+
+    err(function(){
+      ([]).should.be.finite;
+    }, "expected [] to be a finite number");
+
+    err(function(){
+      ({}).should.be.finite;
+    }, "expected {} to be a finite number");
+  });
+
   it('property(name)', function(){
     'test'.should.have.property('length');
     (4).should.not.have.property('length');