UNPKG

18.4 kBJavaScriptView Raw
1describe('Number', function () {
2 var functionsHaveNames = (function foo() {}).name === 'foo';
3 var ifFunctionsHaveNamesIt = functionsHaveNames ? it : xit;
4 var ifShimIt = (typeof process !== 'undefined' && process.env.NO_ES6_SHIM) ? it.skip : it;
5
6 var integers = [5295, -5295, -9007199254740991, 9007199254740991, 0, -0];
7 var nonIntegers = [-9007199254741992, 9007199254741992, 5.9];
8 var infinities = [Infinity, -Infinity];
9
10 var valueOfThree = { valueOf: function () { return 3; } };
11 var valueOfNaN = { valueOf: function () { return NaN; } };
12 var valueOfThrows = { valueOf: function () { throw Object(17); } };
13 var toStringThrows = { toString: function () { throw Object(42); } };
14 var toPrimitiveThrows = {
15 valueOf: function () { throw Object(17); },
16 toString: function () { throw Object(42); }
17 };
18
19 var nonNumbers = [
20 undefined,
21 true,
22 false,
23 null,
24 {},
25 [],
26 'str',
27 '',
28 valueOfThree,
29 valueOfNaN,
30 valueOfThrows,
31 toStringThrows,
32 toPrimitiveThrows,
33 /a/g
34 ];
35 var expectTrue = function (item) {
36 expect(item).to.equal(true);
37 };
38 var expectFalse = function (item) {
39 expect(item).to.equal(false);
40 };
41
42 ifShimIt('is on the exported object', function () {
43 var exported = require('../');
44 expect(exported.Number).to.equal(Number);
45 });
46
47 describe('Number constants', function () {
48 it('should have max safe integer', function () {
49 expect(Number).to.have.property('MAX_SAFE_INTEGER');
50 expect(Object.prototype.propertyIsEnumerable.call(Number, 'MAX_SAFE_INTEGER')).to.equal(false);
51 expect(Number.MAX_SAFE_INTEGER).to.equal(Math.pow(2, 53) - 1);
52 });
53
54 it('should have min safe integer', function () {
55 expect(Number).to.have.property('MIN_SAFE_INTEGER');
56 expect(Object.prototype.propertyIsEnumerable.call(Number, 'MIN_SAFE_INTEGER')).to.equal(false);
57 expect(Number.MIN_SAFE_INTEGER).to.equal(-Math.pow(2, 53) + 1);
58 });
59
60 it('should have epsilon', function () {
61 expect(Number).to.have.property('EPSILON');
62 expect(Object.prototype.propertyIsEnumerable.call(Number, 'EPSILON')).to.equal(false);
63 expect(Number.EPSILON).to.equal(2.2204460492503130808472633361816e-16);
64 });
65
66 it('should have NaN', function () {
67 expect(Number).to.have.property('NaN');
68 expect(Object.prototype.propertyIsEnumerable.call(Number, 'NaN')).to.equal(false);
69 expect(isNaN(Number.NaN)).to.equal(true);
70 });
71
72 it('should have MAX_VALUE', function () {
73 expect(Number).to.have.property('MAX_VALUE');
74 expect(Object.prototype.propertyIsEnumerable.call(Number, 'MAX_VALUE')).to.equal(false);
75 expect(Number.MAX_VALUE).to.equal(1.7976931348623157e+308);
76 });
77
78 it('should have MIN_VALUE', function () {
79 expect(Number).to.have.property('MIN_VALUE');
80 expect(Object.prototype.propertyIsEnumerable.call(Number, 'MIN_VALUE')).to.equal(false);
81 expect(Number.MIN_VALUE).to.equal(5e-324);
82 });
83
84 it('should have NEGATIVE_INFINITY', function () {
85 expect(Number).to.have.property('NEGATIVE_INFINITY');
86 expect(Object.prototype.propertyIsEnumerable.call(Number, 'NEGATIVE_INFINITY')).to.equal(false);
87 expect(Number.NEGATIVE_INFINITY).to.equal(-Infinity);
88 });
89
90 it('should have POSITIVE_INFINITY', function () {
91 expect(Number).to.have.property('POSITIVE_INFINITY');
92 expect(Object.prototype.propertyIsEnumerable.call(Number, 'POSITIVE_INFINITY')).to.equal(false);
93 expect(Number.POSITIVE_INFINITY).to.equal(Infinity);
94 });
95 });
96
97 describe('.parseInt()', function () {
98 if (!Object.prototype.hasOwnProperty.call(Number, 'parseInt')) {
99 return it('exists', function () {
100 expect(Number).to.have.property('parseInt');
101 });
102 }
103
104 it('should work', function () {
105 /* eslint-disable radix */
106 expect(Number.parseInt('601')).to.equal(601);
107 /* eslint-enable radix */
108 });
109
110 ifFunctionsHaveNamesIt('has the right name', function () {
111 expect(Number.parseInt).to.have.property('name', 'parseInt');
112 });
113
114 it('is not enumerable', function () {
115 expect(Number).ownPropertyDescriptor('parseInt').to.have.property('enumerable', false);
116 });
117
118 it('has the right arity', function () {
119 // WebKit nightly had the wrong length; fixed in https://bugs.webkit.org/show_bug.cgi?id=143657
120 expect(Number.parseInt).to.have.property('length', 2);
121 });
122
123 it('is the same object as the global parseInt', function () {
124 // fixed in WebKit nightly in https://bugs.webkit.org/show_bug.cgi?id=143799#add_comment
125 expect(Number.parseInt).to.equal(parseInt);
126 });
127 });
128
129 describe('.parseFloat()', function () {
130 if (!Object.prototype.hasOwnProperty.call(Number, 'parseFloat')) {
131 return it('exists', function () {
132 expect(Number).to.have.property('parseFloat');
133 });
134 }
135
136 it('should work', function () {
137 expect(Number.parseFloat('5.5')).to.equal(5.5);
138 });
139
140 ifFunctionsHaveNamesIt('has the right name', function () {
141 expect(Number.parseFloat).to.have.property('name', 'parseFloat');
142 });
143
144 it('is not enumerable', function () {
145 expect(Number).ownPropertyDescriptor('parseFloat').to.have.property('enumerable', false);
146 });
147
148 it('has the right arity', function () {
149 expect(Number.parseFloat).to.have.property('length', 1);
150 });
151 });
152
153 describe('.isFinite()', function () {
154 if (!Object.prototype.hasOwnProperty.call(Number, 'isFinite')) {
155 return it('exists', function () {
156 expect(Number).to.have.property('isFinite');
157 });
158 }
159
160 ifFunctionsHaveNamesIt('has the right name', function () {
161 expect(Number.isFinite).to.have.property('name', 'isFinite');
162 });
163
164 it('is not enumerable', function () {
165 expect(Number).ownPropertyDescriptor('isFinite').to.have.property('enumerable', false);
166 });
167
168 it('has the right arity', function () {
169 expect(Number.isFinite).to.have.property('length', 1);
170 });
171
172 it('should work', function () {
173 integers.map(Number.isFinite).forEach(expectTrue);
174 infinities.map(Number.isFinite).forEach(expectFalse);
175 expect(Number.isFinite(Infinity)).to.equal(false);
176 expect(Number.isFinite(-Infinity)).to.equal(false);
177 expect(Number.isFinite(NaN)).to.equal(false);
178 expect(Number.isFinite(4)).to.equal(true);
179 expect(Number.isFinite(4.5)).to.equal(true);
180 expect(Number.isFinite('hi')).to.equal(false);
181 expect(Number.isFinite('1.3')).to.equal(false);
182 expect(Number.isFinite('51')).to.equal(false);
183 expect(Number.isFinite(0)).to.equal(true);
184 expect(Number.isFinite(-0)).to.equal(true);
185 expect(Number.isFinite(valueOfThree)).to.equal(false);
186 expect(Number.isFinite(valueOfNaN)).to.equal(false);
187 expect(Number.isFinite(valueOfThrows)).to.equal(false);
188 expect(Number.isFinite(toStringThrows)).to.equal(false);
189 expect(Number.isFinite(toPrimitiveThrows)).to.equal(false);
190 });
191
192 it('should not be confused by type coercion', function () {
193 nonNumbers.map(Number.isFinite).forEach(expectFalse);
194 });
195 });
196
197 describe('.isInteger()', function () {
198 if (!Object.prototype.hasOwnProperty.call(Number, 'isInteger')) {
199 return it('exists', function () {
200 expect(Number).to.have.property('isInteger');
201 });
202 }
203
204 ifFunctionsHaveNamesIt('has the right name', function () {
205 expect(Number.isInteger).to.have.property('name', 'isInteger');
206 });
207
208 it('is not enumerable', function () {
209 expect(Number).ownPropertyDescriptor('isInteger').to.have.property('enumerable', false);
210 });
211
212 it('has the right arity', function () {
213 expect(Number.isInteger).to.have.property('length', 1);
214 });
215
216 it('should be truthy on integers', function () {
217 integers.map(Number.isInteger).forEach(expectTrue);
218 expect(Number.isInteger(4)).to.equal(true);
219 expect(Number.isInteger(4.0)).to.equal(true);
220 expect(Number.isInteger(1801439850948)).to.equal(true);
221 });
222
223 it('should be false when the type is not number', function () {
224 nonNumbers.forEach(function (thing) {
225 expect(Number.isInteger(thing)).to.equal(false);
226 });
227 });
228
229 it('should be false when NaN', function () {
230 expect(Number.isInteger(NaN)).to.equal(false);
231 });
232
233 it('should be false when ∞', function () {
234 expect(Number.isInteger(Infinity)).to.equal(false);
235 expect(Number.isInteger(-Infinity)).to.equal(false);
236 });
237
238 it('should be false when number is not integer', function () {
239 expect(Number.isInteger(3.4)).to.equal(false);
240 expect(Number.isInteger(-3.4)).to.equal(false);
241 });
242
243 it('should be true when abs(number) is 2^53 or larger', function () {
244 expect(Number.isInteger(Math.pow(2, 53))).to.equal(true);
245 expect(Number.isInteger(Math.pow(2, 54))).to.equal(true);
246 expect(Number.isInteger(-Math.pow(2, 53))).to.equal(true);
247 expect(Number.isInteger(-Math.pow(2, 54))).to.equal(true);
248 });
249
250 it('should be true when abs(number) is less than 2^53', function () {
251 var safeIntegers = [0, 1, Math.pow(2, 53) - 1];
252 safeIntegers.forEach(function (integer) {
253 expect(Number.isInteger(integer)).to.equal(true);
254 expect(Number.isInteger(-integer)).to.equal(true);
255 });
256 });
257 });
258
259 describe('.isSafeInteger()', function () {
260 if (!Object.prototype.hasOwnProperty.call(Number, 'isSafeInteger')) {
261 return it('exists', function () {
262 expect(Number).to.have.property('isSafeInteger');
263 });
264 }
265
266 ifFunctionsHaveNamesIt('has the right name', function () {
267 expect(Number.isSafeInteger).to.have.property('name', 'isSafeInteger');
268 });
269
270 it('is not enumerable', function () {
271 expect(Number).ownPropertyDescriptor('isSafeInteger').to.have.property('enumerable', false);
272 });
273
274 it('has the right arity', function () {
275 expect(Number.isSafeInteger).to.have.property('length', 1);
276 });
277
278 it('should be truthy on integers', function () {
279 integers.map(Number.isSafeInteger).forEach(expectTrue);
280 expect(Number.isSafeInteger(4)).to.equal(true);
281 expect(Number.isSafeInteger(4.0)).to.equal(true);
282 expect(Number.isSafeInteger(1801439850948)).to.equal(true);
283 });
284
285 it('should be false when the type is not number', function () {
286 nonNumbers.forEach(function (thing) {
287 expect(Number.isSafeInteger(thing)).to.equal(false);
288 });
289 });
290
291 it('should be false when NaN', function () {
292 expect(Number.isSafeInteger(NaN)).to.equal(false);
293 });
294
295 it('should be false when ∞', function () {
296 expect(Number.isSafeInteger(Infinity)).to.equal(false);
297 expect(Number.isSafeInteger(-Infinity)).to.equal(false);
298 });
299
300 it('should be false when number is not integer', function () {
301 expect(Number.isSafeInteger(3.4)).to.equal(false);
302 expect(Number.isSafeInteger(-3.4)).to.equal(false);
303 });
304
305 it('should be false when abs(number) is 2^53 or larger', function () {
306 expect(Number.isSafeInteger(Math.pow(2, 53))).to.equal(false);
307 expect(Number.isSafeInteger(Math.pow(2, 54))).to.equal(false);
308 expect(Number.isSafeInteger(-Math.pow(2, 53))).to.equal(false);
309 expect(Number.isSafeInteger(-Math.pow(2, 54))).to.equal(false);
310 });
311
312 it('should be true when abs(number) is less than 2^53', function () {
313 var safeIntegers = [0, 1, Math.pow(2, 53) - 1];
314 safeIntegers.forEach(function (integer) {
315 expect(Number.isSafeInteger(integer)).to.equal(true);
316 expect(Number.isSafeInteger(-integer)).to.equal(true);
317 });
318 });
319 });
320
321 describe('.isNaN()', function () {
322 if (!Object.prototype.hasOwnProperty.call(Number, 'isNaN')) {
323 return it('exists', function () {
324 expect(Number).to.have.property('isNaN');
325 });
326 }
327
328 ifFunctionsHaveNamesIt('has the right name', function () {
329 expect(Number.isNaN).to.have.property('name', 'isNaN');
330 });
331
332 it('is not enumerable', function () {
333 expect(Number).ownPropertyDescriptor('isNaN').to.have.property('enumerable', false);
334 });
335
336 it('has the right arity', function () {
337 expect(Number.isNaN).to.have.property('length', 1);
338 });
339
340 it('should be truthy only on NaN', function () {
341 integers.concat(nonIntegers).map(Number.isNaN).forEach(expectFalse);
342 nonNumbers.map(Number.isNaN).forEach(expectFalse);
343 expect(Number.isNaN(NaN)).to.equal(true);
344 expect(Number.isNaN(0 / 0)).to.equal(true);
345 expect(Number.isNaN(Number('NaN'))).to.equal(true);
346 expect(Number.isNaN(4)).to.equal(false);
347 expect(Number.isNaN(4.5)).to.equal(false);
348 expect(Number.isNaN('hi')).to.equal(false);
349 expect(Number.isNaN('1.3')).to.equal(false);
350 expect(Number.isNaN('51')).to.equal(false);
351 expect(Number.isNaN(0)).to.equal(false);
352 expect(Number.isNaN(-0)).to.equal(false);
353 expect(Number.isNaN(valueOfThree)).to.equal(false);
354 expect(Number.isNaN(valueOfNaN)).to.equal(false);
355 expect(Number.isNaN(valueOfThrows)).to.equal(false);
356 expect(Number.isNaN(toStringThrows)).to.equal(false);
357 expect(Number.isNaN(toPrimitiveThrows)).to.equal(false);
358 });
359 });
360
361 describe('constructor', function () {
362 it('behaves like the builtin', function () {
363 expect((1).constructor).to.equal(Number);
364 expect(Number()).to.equal(0);
365 });
366
367 describe('strings in the constructor', function () {
368 it('works on normal literals', function () {
369 expect(Number('1')).to.equal(+'1');
370 expect(Number('1.1')).to.equal(+'1.1');
371 expect(Number('0xA')).to.equal(0xA);
372 });
373 });
374
375 describe('when called with a receiver', function () {
376 it('returns a primitive when called with a primitive receiver', function () {
377 expect((1).constructor(2)).to.equal(2);
378 expect((1).constructor.call(null, 3)).to.equal(3);
379 expect(Object(1).constructor.call(null, 5)).to.equal(5);
380 });
381
382 it('returns a primitive when called with a different number as an object receiver', function () {
383 expect(Object(1).constructor(6)).to.equal(6);
384 expect(Object(1).constructor.call(Object(1), 7)).to.equal(7);
385 });
386
387 it('returns a primitive when called with the same number as an object receiver', function () {
388 expect(Object(1).constructor.call(Object(8), 8)).to.equal(8);
389 });
390 });
391
392 it('works with boxed primitives', function () {
393 expect(1 instanceof Number).to.equal(false);
394 expect(Object(1) instanceof Number).to.equal(true);
395 });
396
397 it('works with `new`', function () {
398 /* eslint-disable no-new-wrappers */
399 var one = new Number('1');
400 var a = new Number('0xA');
401 /* eslint-enable no-new-wrappers */
402
403 expect(+one).to.equal(1);
404 expect(one instanceof Number).to.equal(true);
405 expect(+a).to.equal(0xA);
406 expect(a instanceof Number).to.equal(true);
407 });
408
409 it('works with binary literals in string form', function () {
410 expect(Number('0b1')).to.equal(1);
411 expect(Number(' 0b1')).to.equal(1);
412 expect(Number('0b1 ')).to.equal(1);
413
414 expect(Number('0b10')).to.equal(2);
415 expect(Number(' 0b10')).to.equal(2);
416 expect(Number('0b10 ')).to.equal(2);
417
418 expect(Number('0b11')).to.equal(3);
419 expect(Number(' 0b11')).to.equal(3);
420 expect(Number('0b11 ')).to.equal(3);
421
422 expect(Number({
423 toString: function () { return '0b100'; },
424 valueOf: function () { return '0b101'; }
425 })).to.equal(5);
426 });
427
428 it('works with octal literals in string form', function () {
429 expect(Number('0o7')).to.equal(7);
430 expect(Number('0o10')).to.equal(8);
431 expect(Number('0o11')).to.equal(9);
432 expect(Number({
433 toString: function () { return '0o12'; },
434 valueOf: function () { return '0o13'; }
435 })).to.equal(11);
436 });
437
438 it('should produce NaN', function () {
439 expect(String(Number('0b12'))).to.equal('NaN');
440 expect(String(Number('0o18'))).to.equal('NaN');
441 expect(String(Number('0x1g'))).to.equal('NaN');
442 expect(String(Number('+0b1'))).to.equal('NaN');
443 expect(String(Number('+0o1'))).to.equal('NaN');
444 expect(String(Number('+0x1'))).to.equal('NaN');
445 expect(String(Number('-0b1'))).to.equal('NaN');
446 expect(String(Number('-0o1'))).to.equal('NaN');
447 expect(String(Number('-0x1'))).to.equal('NaN');
448 });
449
450 it('should work with well formed and poorly formed objects', function () {
451 expect(String(Number({}))).to.equal('NaN');
452 expect(String(Number({ valueOf: '1.1' }))).to.equal('NaN');
453 expect(Number({ valueOf: '1.1', toString: function () { return '2.2'; } })).to.equal(2.2);
454 expect(Number({ valueOf: function () { return '1.1'; }, toString: '2.2' })).to.equal(1.1);
455 expect(Number({
456 valueOf: function () { return '1.1'; },
457 toString: function () { return '2.2'; }
458 })).to.equal(1.1);
459 expect(String(Number({ valueOf: function () { return '-0x1a2b3c'; } }))).to.equal('NaN');
460 expect(String(Number({ toString: function () { return '-0x1a2b3c'; } }))).to.equal('NaN');
461 expect(Number({ valueOf: function () { return '0o12345'; } })).to.equal(5349);
462 expect(Number({ toString: function () { return '0o12345'; } })).to.equal(5349);
463 expect(Number({ valueOf: function () { return '0b101010'; } })).to.equal(42);
464 expect(Number({ toString: function () { return '0b101010'; } })).to.equal(42);
465 });
466
467 it('should work with correct whitespaces', function () {
468 // Zero-width space (zws), next line character (nel), and non-character (bom) are not whitespace.
469 var nonWhitespaces = ['\u0085', '\u200b', '\ufffe'];
470
471 expect(String(Number(nonWhitespaces[0] + '0' + nonWhitespaces[0]))).to.equal('NaN');
472 expect(String(Number(nonWhitespaces[1] + '1' + nonWhitespaces[1]))).to.equal('NaN');
473 expect(String(Number(nonWhitespaces[2] + '2' + nonWhitespaces[2]))).to.equal('NaN');
474 });
475
476 it.skip('it works with updated unicode values', function () {
477 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';
478
479 expect(String(Number(whitespace + '3' + whitespace))).to.equal('3');
480 });
481 });
482});