Bones/node_modules/es6-shim/test/number.js

482 lines
18 KiB
JavaScript
Raw Normal View History

2017-05-17 13:45:25 -04:00
describe('Number', function () {
var functionsHaveNames = (function foo() {}).name === 'foo';
var ifFunctionsHaveNamesIt = functionsHaveNames ? it : xit;
var ifShimIt = (typeof process !== 'undefined' && process.env.NO_ES6_SHIM) ? it.skip : it;
var integers = [5295, -5295, -9007199254740991, 9007199254740991, 0, -0];
var nonIntegers = [-9007199254741992, 9007199254741992, 5.9];
var infinities = [Infinity, -Infinity];
var valueOfThree = { valueOf: function () { return 3; } };
var valueOfNaN = { valueOf: function () { return NaN; } };
var valueOfThrows = { valueOf: function () { throw Object(17); } };
var toStringThrows = { toString: function () { throw Object(42); } };
var toPrimitiveThrows = {
valueOf: function () { throw Object(17); },
toString: function () { throw Object(42); }
};
var nonNumbers = [
undefined,
true,
false,
null,
{},
[],
'str',
'',
valueOfThree,
valueOfNaN,
valueOfThrows,
toStringThrows,
toPrimitiveThrows,
/a/g
];
var expectTrue = function (item) {
expect(item).to.equal(true);
};
var expectFalse = function (item) {
expect(item).to.equal(false);
};
ifShimIt('is on the exported object', function () {
var exported = require('../');
expect(exported.Number).to.equal(Number);
});
describe('Number constants', function () {
it('should have max safe integer', function () {
expect(Number).to.have.property('MAX_SAFE_INTEGER');
expect(Object.prototype.propertyIsEnumerable.call(Number, 'MAX_SAFE_INTEGER')).to.equal(false);
expect(Number.MAX_SAFE_INTEGER).to.equal(Math.pow(2, 53) - 1);
});
it('should have min safe integer', function () {
expect(Number).to.have.property('MIN_SAFE_INTEGER');
expect(Object.prototype.propertyIsEnumerable.call(Number, 'MIN_SAFE_INTEGER')).to.equal(false);
expect(Number.MIN_SAFE_INTEGER).to.equal(-Math.pow(2, 53) + 1);
});
it('should have epsilon', function () {
expect(Number).to.have.property('EPSILON');
expect(Object.prototype.propertyIsEnumerable.call(Number, 'EPSILON')).to.equal(false);
expect(Number.EPSILON).to.equal(2.2204460492503130808472633361816e-16);
});
it('should have NaN', function () {
expect(Number).to.have.property('NaN');
expect(Object.prototype.propertyIsEnumerable.call(Number, 'NaN')).to.equal(false);
expect(isNaN(Number.NaN)).to.equal(true);
});
it('should have MAX_VALUE', function () {
expect(Number).to.have.property('MAX_VALUE');
expect(Object.prototype.propertyIsEnumerable.call(Number, 'MAX_VALUE')).to.equal(false);
expect(Number.MAX_VALUE).to.equal(1.7976931348623157e+308);
});
it('should have MIN_VALUE', function () {
expect(Number).to.have.property('MIN_VALUE');
expect(Object.prototype.propertyIsEnumerable.call(Number, 'MIN_VALUE')).to.equal(false);
expect(Number.MIN_VALUE).to.equal(5e-324);
});
it('should have NEGATIVE_INFINITY', function () {
expect(Number).to.have.property('NEGATIVE_INFINITY');
expect(Object.prototype.propertyIsEnumerable.call(Number, 'NEGATIVE_INFINITY')).to.equal(false);
expect(Number.NEGATIVE_INFINITY).to.equal(-Infinity);
});
it('should have POSITIVE_INFINITY', function () {
expect(Number).to.have.property('POSITIVE_INFINITY');
expect(Object.prototype.propertyIsEnumerable.call(Number, 'POSITIVE_INFINITY')).to.equal(false);
expect(Number.POSITIVE_INFINITY).to.equal(Infinity);
});
});
describe('.parseInt()', function () {
if (!Object.prototype.hasOwnProperty.call(Number, 'parseInt')) {
return it('exists', function () {
expect(Number).to.have.property('parseInt');
});
}
it('should work', function () {
/* eslint-disable radix */
expect(Number.parseInt('601')).to.equal(601);
/* eslint-enable radix */
});
ifFunctionsHaveNamesIt('has the right name', function () {
expect(Number.parseInt).to.have.property('name', 'parseInt');
});
it('is not enumerable', function () {
expect(Number).ownPropertyDescriptor('parseInt').to.have.property('enumerable', false);
});
it('has the right arity', function () {
// WebKit nightly had the wrong length; fixed in https://bugs.webkit.org/show_bug.cgi?id=143657
expect(Number.parseInt).to.have.property('length', 2);
});
it('is the same object as the global parseInt', function () {
// fixed in WebKit nightly in https://bugs.webkit.org/show_bug.cgi?id=143799#add_comment
expect(Number.parseInt).to.equal(parseInt);
});
});
describe('.parseFloat()', function () {
if (!Object.prototype.hasOwnProperty.call(Number, 'parseFloat')) {
return it('exists', function () {
expect(Number).to.have.property('parseFloat');
});
}
it('should work', function () {
expect(Number.parseFloat('5.5')).to.equal(5.5);
});
ifFunctionsHaveNamesIt('has the right name', function () {
expect(Number.parseFloat).to.have.property('name', 'parseFloat');
});
it('is not enumerable', function () {
expect(Number).ownPropertyDescriptor('parseFloat').to.have.property('enumerable', false);
});
it('has the right arity', function () {
expect(Number.parseFloat).to.have.property('length', 1);
});
});
describe('.isFinite()', function () {
if (!Object.prototype.hasOwnProperty.call(Number, 'isFinite')) {
return it('exists', function () {
expect(Number).to.have.property('isFinite');
});
}
ifFunctionsHaveNamesIt('has the right name', function () {
expect(Number.isFinite).to.have.property('name', 'isFinite');
});
it('is not enumerable', function () {
expect(Number).ownPropertyDescriptor('isFinite').to.have.property('enumerable', false);
});
it('has the right arity', function () {
expect(Number.isFinite).to.have.property('length', 1);
});
it('should work', function () {
integers.map(Number.isFinite).forEach(expectTrue);
infinities.map(Number.isFinite).forEach(expectFalse);
expect(Number.isFinite(Infinity)).to.equal(false);
expect(Number.isFinite(-Infinity)).to.equal(false);
expect(Number.isFinite(NaN)).to.equal(false);
expect(Number.isFinite(4)).to.equal(true);
expect(Number.isFinite(4.5)).to.equal(true);
expect(Number.isFinite('hi')).to.equal(false);
expect(Number.isFinite('1.3')).to.equal(false);
expect(Number.isFinite('51')).to.equal(false);
expect(Number.isFinite(0)).to.equal(true);
expect(Number.isFinite(-0)).to.equal(true);
expect(Number.isFinite(valueOfThree)).to.equal(false);
expect(Number.isFinite(valueOfNaN)).to.equal(false);
expect(Number.isFinite(valueOfThrows)).to.equal(false);
expect(Number.isFinite(toStringThrows)).to.equal(false);
expect(Number.isFinite(toPrimitiveThrows)).to.equal(false);
});
it('should not be confused by type coercion', function () {
nonNumbers.map(Number.isFinite).forEach(expectFalse);
});
});
describe('.isInteger()', function () {
if (!Object.prototype.hasOwnProperty.call(Number, 'isInteger')) {
return it('exists', function () {
expect(Number).to.have.property('isInteger');
});
}
ifFunctionsHaveNamesIt('has the right name', function () {
expect(Number.isInteger).to.have.property('name', 'isInteger');
});
it('is not enumerable', function () {
expect(Number).ownPropertyDescriptor('isInteger').to.have.property('enumerable', false);
});
it('has the right arity', function () {
expect(Number.isInteger).to.have.property('length', 1);
});
it('should be truthy on integers', function () {
integers.map(Number.isInteger).forEach(expectTrue);
expect(Number.isInteger(4)).to.equal(true);
expect(Number.isInteger(4.0)).to.equal(true);
expect(Number.isInteger(1801439850948)).to.equal(true);
});
it('should be false when the type is not number', function () {
nonNumbers.forEach(function (thing) {
expect(Number.isInteger(thing)).to.equal(false);
});
});
it('should be false when NaN', function () {
expect(Number.isInteger(NaN)).to.equal(false);
});
it('should be false when ∞', function () {
expect(Number.isInteger(Infinity)).to.equal(false);
expect(Number.isInteger(-Infinity)).to.equal(false);
});
it('should be false when number is not integer', function () {
expect(Number.isInteger(3.4)).to.equal(false);
expect(Number.isInteger(-3.4)).to.equal(false);
});
it('should be true when abs(number) is 2^53 or larger', function () {
expect(Number.isInteger(Math.pow(2, 53))).to.equal(true);
expect(Number.isInteger(Math.pow(2, 54))).to.equal(true);
expect(Number.isInteger(-Math.pow(2, 53))).to.equal(true);
expect(Number.isInteger(-Math.pow(2, 54))).to.equal(true);
});
it('should be true when abs(number) is less than 2^53', function () {
var safeIntegers = [0, 1, Math.pow(2, 53) - 1];
safeIntegers.forEach(function (integer) {
expect(Number.isInteger(integer)).to.equal(true);
expect(Number.isInteger(-integer)).to.equal(true);
});
});
});
describe('.isSafeInteger()', function () {
if (!Object.prototype.hasOwnProperty.call(Number, 'isSafeInteger')) {
return it('exists', function () {
expect(Number).to.have.property('isSafeInteger');
});
}
ifFunctionsHaveNamesIt('has the right name', function () {
expect(Number.isSafeInteger).to.have.property('name', 'isSafeInteger');
});
it('is not enumerable', function () {
expect(Number).ownPropertyDescriptor('isSafeInteger').to.have.property('enumerable', false);
});
it('has the right arity', function () {
expect(Number.isSafeInteger).to.have.property('length', 1);
});
it('should be truthy on integers', function () {
integers.map(Number.isSafeInteger).forEach(expectTrue);
expect(Number.isSafeInteger(4)).to.equal(true);
expect(Number.isSafeInteger(4.0)).to.equal(true);
expect(Number.isSafeInteger(1801439850948)).to.equal(true);
});
it('should be false when the type is not number', function () {
nonNumbers.forEach(function (thing) {
expect(Number.isSafeInteger(thing)).to.equal(false);
});
});
it('should be false when NaN', function () {
expect(Number.isSafeInteger(NaN)).to.equal(false);
});
it('should be false when ∞', function () {
expect(Number.isSafeInteger(Infinity)).to.equal(false);
expect(Number.isSafeInteger(-Infinity)).to.equal(false);
});
it('should be false when number is not integer', function () {
expect(Number.isSafeInteger(3.4)).to.equal(false);
expect(Number.isSafeInteger(-3.4)).to.equal(false);
});
it('should be false when abs(number) is 2^53 or larger', function () {
expect(Number.isSafeInteger(Math.pow(2, 53))).to.equal(false);
expect(Number.isSafeInteger(Math.pow(2, 54))).to.equal(false);
expect(Number.isSafeInteger(-Math.pow(2, 53))).to.equal(false);
expect(Number.isSafeInteger(-Math.pow(2, 54))).to.equal(false);
});
it('should be true when abs(number) is less than 2^53', function () {
var safeIntegers = [0, 1, Math.pow(2, 53) - 1];
safeIntegers.forEach(function (integer) {
expect(Number.isSafeInteger(integer)).to.equal(true);
expect(Number.isSafeInteger(-integer)).to.equal(true);
});
});
});
describe('.isNaN()', function () {
if (!Object.prototype.hasOwnProperty.call(Number, 'isNaN')) {
return it('exists', function () {
expect(Number).to.have.property('isNaN');
});
}
ifFunctionsHaveNamesIt('has the right name', function () {
expect(Number.isNaN).to.have.property('name', 'isNaN');
});
it('is not enumerable', function () {
expect(Number).ownPropertyDescriptor('isNaN').to.have.property('enumerable', false);
});
it('has the right arity', function () {
expect(Number.isNaN).to.have.property('length', 1);
});
it('should be truthy only on NaN', function () {
integers.concat(nonIntegers).map(Number.isNaN).forEach(expectFalse);
nonNumbers.map(Number.isNaN).forEach(expectFalse);
expect(Number.isNaN(NaN)).to.equal(true);
expect(Number.isNaN(0 / 0)).to.equal(true);
expect(Number.isNaN(Number('NaN'))).to.equal(true);
expect(Number.isNaN(4)).to.equal(false);
expect(Number.isNaN(4.5)).to.equal(false);
expect(Number.isNaN('hi')).to.equal(false);
expect(Number.isNaN('1.3')).to.equal(false);
expect(Number.isNaN('51')).to.equal(false);
expect(Number.isNaN(0)).to.equal(false);
expect(Number.isNaN(-0)).to.equal(false);
expect(Number.isNaN(valueOfThree)).to.equal(false);
expect(Number.isNaN(valueOfNaN)).to.equal(false);
expect(Number.isNaN(valueOfThrows)).to.equal(false);
expect(Number.isNaN(toStringThrows)).to.equal(false);
expect(Number.isNaN(toPrimitiveThrows)).to.equal(false);
});
});
describe('constructor', function () {
it('behaves like the builtin', function () {
expect((1).constructor).to.equal(Number);
expect(Number()).to.equal(0);
});
describe('strings in the constructor', function () {
it('works on normal literals', function () {
expect(Number('1')).to.equal(+'1');
expect(Number('1.1')).to.equal(+'1.1');
expect(Number('0xA')).to.equal(0xA);
});
});
describe('when called with a receiver', function () {
it('returns a primitive when called with a primitive receiver', function () {
expect((1).constructor(2)).to.equal(2);
expect((1).constructor.call(null, 3)).to.equal(3);
expect(Object(1).constructor.call(null, 5)).to.equal(5);
});
it('returns a primitive when called with a different number as an object receiver', function () {
expect(Object(1).constructor(6)).to.equal(6);
expect(Object(1).constructor.call(Object(1), 7)).to.equal(7);
});
it('returns a primitive when called with the same number as an object receiver', function () {
expect(Object(1).constructor.call(Object(8), 8)).to.equal(8);
});
});
it('works with boxed primitives', function () {
expect(1 instanceof Number).to.equal(false);
expect(Object(1) instanceof Number).to.equal(true);
});
it('works with `new`', function () {
/* jshint -W053 */
/* eslint-disable no-new-wrappers */
var one = new Number('1');
var a = new Number('0xA');
/* eslint-enable no-new-wrappers */
/* jshint +W053 */
expect(+one).to.equal(1);
expect(one instanceof Number).to.equal(true);
expect(+a).to.equal(0xA);
expect(a instanceof Number).to.equal(true);
});
it('works with binary literals in string form', function () {
expect(Number('0b1')).to.equal(1);
expect(Number(' 0b1')).to.equal(1);
expect(Number('0b1 ')).to.equal(1);
expect(Number('0b10')).to.equal(2);
expect(Number(' 0b10')).to.equal(2);
expect(Number('0b10 ')).to.equal(2);
expect(Number('0b11')).to.equal(3);
expect(Number(' 0b11')).to.equal(3);
expect(Number('0b11 ')).to.equal(3);
expect(Number({
toString: function () { return '0b100'; },
valueOf: function () { return '0b101'; }
})).to.equal(5);
});
it('works with octal literals in string form', function () {
expect(Number('0o7')).to.equal(7);
expect(Number('0o10')).to.equal(8);
expect(Number('0o11')).to.equal(9);
expect(Number({
toString: function () { return '0o12'; },
valueOf: function () { return '0o13'; }
})).to.equal(11);
});
it('should produce NaN', function () {
expect(String(Number('0b12'))).to.equal('NaN');
expect(String(Number('0o18'))).to.equal('NaN');
expect(String(Number('0x1g'))).to.equal('NaN');
expect(String(Number('+0b1'))).to.equal('NaN');
expect(String(Number('+0o1'))).to.equal('NaN');
expect(String(Number('+0x1'))).to.equal('NaN');
expect(String(Number('-0b1'))).to.equal('NaN');
expect(String(Number('-0o1'))).to.equal('NaN');
expect(String(Number('-0x1'))).to.equal('NaN');
});
it('should work with well formed and poorly formed objects', function () {
expect(String(Number({}))).to.equal('NaN');
expect(String(Number({ valueOf: '1.1' }))).to.equal('NaN');
expect(Number({ valueOf: '1.1', toString: function () { return '2.2'; } })).to.equal(2.2);
expect(Number({ valueOf: function () { return '1.1'; }, toString: '2.2' })).to.equal(1.1);
expect(Number({
valueOf: function () { return '1.1'; },
toString: function () { return '2.2'; }
})).to.equal(1.1);
expect(String(Number({ valueOf: function () { return '-0x1a2b3c'; } }))).to.equal('NaN');
expect(String(Number({ toString: function () { return '-0x1a2b3c'; } }))).to.equal('NaN');
expect(Number({ valueOf: function () { return '0o12345'; } })).to.equal(5349);
expect(Number({ toString: function () { return '0o12345'; } })).to.equal(5349);
expect(Number({ valueOf: function () { return '0b101010'; } })).to.equal(42);
expect(Number({ toString: function () { return '0b101010'; } })).to.equal(42);
});
it('should work with correct whitespaces', function () {
var whitespace = ' \t\x0b\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000';
// Zero-width space (zws), next line character (nel), and non-character (bom) are not whitespace.
var nonWhitespaces = ['\u0085', '\u200b', '\ufffe'];
expect(String(Number(nonWhitespaces[0] + '0' + nonWhitespaces[0]))).to.equal('NaN');
expect(String(Number(nonWhitespaces[1] + '1' + nonWhitespaces[1]))).to.equal('NaN');
expect(String(Number(nonWhitespaces[2] + '2' + nonWhitespaces[2]))).to.equal('NaN');
expect(String(Number(whitespace + '3' + whitespace))).to.equal('3');
});
});
});