Intial Commit

This commit is contained in:
valki
2020-10-17 18:42:50 +02:00
commit 664c6d8ca3
5892 changed files with 759183 additions and 0 deletions

View File

@@ -0,0 +1,521 @@
var assert = require('assert'),
array = require('../../lib/utils/array'),
resize = array.resize;
size = array.size;
describe('util.array', function() {
describe('size', function () {
it('should calculate the size of a scalar', function () {
assert.deepEqual(size(2), []);
assert.deepEqual(size("string"), []);
});
it('should calculate the size of a 1-dimensional array', function () {
assert.deepEqual(size([]), [0]);
assert.deepEqual(size([1]), [1]);
assert.deepEqual(size([1,2,3]), [3]);
});
it('should calculate the size of a 2-dimensional array', function () {
assert.deepEqual(size([[]]), [1,0]);
assert.deepEqual(size([[], []]), [2,0]);
assert.deepEqual(size([[1,2],[3,4]]), [2,2]);
assert.deepEqual(size([[1,2,3],[4,5,6]]), [2,3]);
});
it('should calculate the size of a 3-dimensional array', function () {
assert.deepEqual(size([[[]]]), [1,1,0]);
assert.deepEqual(size([[[], []]]), [1,2,0]);
assert.deepEqual(size([[[], []],[[], []]]), [2,2,0]);
assert.deepEqual(size([[[1],[2]],[[3],[4]]]), [2,2,1]);
assert.deepEqual(size([[[1,2],[3,4]],[[5,6],[7,8]]]), [2,2,2]);
assert.deepEqual(size([
[[1,2,3,4],[5,6,7,8]],
[[1,2,3,4],[5,6,7,8]],
[[1,2,3,4],[5,6,7,8]]
]), [3,2,4]);
});
it('should not validate whether all dimensions match', function () {
assert.deepEqual(size([[1,2],[3,4,5]]), [2,2]);
});
});
describe('resize', function () {
it('should resize a 1 dimensional array', function () {
var a = [];
// resize with a default value
a = resize(a, [3], 100);
assert.deepEqual(a, [100,100,100]);
// resize without default value
a = resize(a, [5]);
assert.deepEqual(a, [100,100,100, 0, 0]);
a = resize(a, [2]);
assert.deepEqual(a, [100,100]);
});
it('should resize a 1 dimensional array with UNINITIALIZED defaultValue', function () {
var a = [];
// resize with default value UNINITIALIZED
a = resize(a, [3], array.UNINITIALIZED);
assert.deepEqual(a, arr(uninit, uninit, uninit));
});
it('should resize a 2 dimensional array', function () {
var a = [
[0, 1],
[2, 3]
];
a = resize(a, [2, 4]);
assert.deepEqual(a, [
[0, 1, 0, 0],
[2, 3, 0, 0]
]);
a = resize(a, [4, 4]);
assert.deepEqual(a, [
[0, 1, 0, 0],
[2, 3, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]
]);
a = resize(a, [4, 2]);
assert.deepEqual(a, [
[0, 1],
[2, 3],
[0, 0],
[0, 0]
]);
a = resize(a, [2, 2]);
assert.deepEqual(a, [
[0, 1],
[2, 3]
]);
a = resize(a, [1, 1]);
assert.deepEqual(a, [
[0]
]);
});
it('should resize a 2 dimensional array with default value', function () {
var a = [
[0, 1],
[2, 3]
];
a = resize(a, [2, 4], 100);
assert.deepEqual(a, [
[0, 1, 100, 100],
[2, 3, 100, 100]
]);
a = resize(a, [4, 4], 100);
assert.deepEqual(a, [
[0, 1, 100, 100],
[2, 3, 100, 100],
[100, 100, 100, 100],
[100, 100, 100, 100]
]);
a = resize(a, [4, 2]);
assert.deepEqual(a, [
[0, 1],
[2, 3],
[100, 100],
[100, 100]
]);
a = resize(a, [2, 2]);
assert.deepEqual(a, [
[0, 1],
[2, 3]
]);
a = resize(a, [1, 1]);
assert.deepEqual(a, [
[0]
]);
});
it('should resize a 1 dimensional array to 2 dimensional', function () {
var a = [1, 2];
a = resize(a, [4], 3);
assert.deepEqual(a, [1, 2, 3, 3]);
a = resize(a, [4, 2], 4);
assert.deepEqual(a, [
[1, 4],
[2, 4],
[3, 4],
[3, 4]
]);
// without default value
var b = [1, 2];
b = resize(b, [4]);
assert.deepEqual(b, [1, 2, 0, 0]);
b = resize(b, [4, 2]);
assert.deepEqual(b, [
[1, 0],
[2, 0],
[0, 0],
[0, 0]
]);
// TODO: would be nicer if this returns uninit everwhere and not undefined on some places
});
it('should resize a 2 dimensional array to 1 dimensional', function () {
var a = [[1,2],[3,4],[5,6],[7,8]];
a = resize(a, [6]);
assert.deepEqual(a, [1,3,5,7,0,0]);
var b = [[],[]];
b = resize(b, [2], 8);
assert.deepEqual(b, [undefined, undefined]);
var b = [];
b = resize(b, [2], 8);
assert.deepEqual(b, [8, 8]);
});
it('should resize a 3 dimensional array', function () {
var a = [];
a = resize(a, [2,3], 5);
assert.deepEqual(a, [[5,5,5], [5,5,5]]);
a = resize(a, [2,3,2], 7);
assert.deepEqual(a, [[[5,7],[5,7],[5,7]], [[5,7],[5,7],[5,7]]]);
a = resize(a, [3,2], 9);
assert.deepEqual(a, [[5,5], [5,5], [9, 9]]);
});
it('should resize to an empty array', function () {
var a = [];
a = resize(a, [2,3], 5);
assert.deepEqual(a, [[5,5,5], [5,5,5]]);
a = resize(a, [0]);
assert.deepEqual(a, []);
});
it('should throw an error when resizing to a scalar', function () {
var a = [];
assert.throws(function () {a = resize(a, []);}, /Resizing to scalar is not supported/);
});
it('should throw an error in case of wrong type of arguments', function () {
assert.throws(function () {resize([], 2)}, /Array expected/);
assert.throws(function () {resize(2)}, /Array expected/);
});
});
describe('squeeze', function () {
it('should squeeze a scalar', function () {
assert.deepEqual(array.squeeze(2), 2);
assert.deepEqual(array.squeeze({}), {});
assert.deepEqual(array.squeeze('string'), 'string');
});
it('should squeeze an array', function () {
// leave zero dimensions as is
assert.deepEqual(array.squeeze([]), []);
assert.deepEqual(array.squeeze([[]]), []);
assert.deepEqual(array.squeeze([[[]]]), []);
assert.deepEqual(array.squeeze([[[], []]]), [[], []]);
assert.deepEqual(array.squeeze([[[]], [[]]]), [[[]], [[]]]);
assert.deepEqual(array.squeeze(2), 2);
assert.deepEqual(array.squeeze([[2]]), 2);
assert.deepEqual(array.squeeze([[[2]]]), 2);
assert.deepEqual(array.squeeze([1, 2, 3]), [1, 2, 3]);
assert.deepEqual(array.squeeze([[1, 2, 3]]), [1, 2, 3]);
assert.deepEqual(array.squeeze([[[1, 2, 3]]]), [1, 2, 3]);
assert.deepEqual(array.squeeze([[1], [2], [3]]), [1, 2, 3]);
assert.deepEqual(array.squeeze([[1, 2], [3, 4]]), [[1, 2], [3, 4]]);
assert.deepEqual(array.squeeze([[[1, 2]], [[3, 4]]]), [[[1, 2]], [[3, 4]]]);
assert.deepEqual(array.squeeze([[[1, 2], [3, 4]]]), [[1, 2], [3, 4]]);
assert.deepEqual(array.squeeze([[[1], [2]], [[3], [4]]]), [[1, 2], [3, 4]]);
assert.deepEqual(array.squeeze([[[1]], [[2]], [[3]], [[4]]]), [1, 2, 3, 4]);
});
it('should adjust size when squeezing an array', function () {
var a = [[[1], [2]], [[3], [4]]];
var size = [2,2,1];
a = array.squeeze(a, size);
assert.deepEqual(a, [[1, 2], [3, 4]]);
assert.deepEqual(size, [2,2]);
a = [[1,2]];
size = [1,2];
a = array.squeeze(a, size);
assert.deepEqual(a, [1,2]);
assert.deepEqual(size, [2]);
a = [[[1]], [[2]], [[3]], [[4]]];
size = [4,1,1];
a = array.squeeze(a, size);
assert.deepEqual(a, [1, 2, 3, 4]);
assert.deepEqual(size, [4]);
});
});
describe('unsqueeze', function () {
it('should unsqueeze a scalar', function () {
assert.deepEqual(array.unsqueeze(2, 0), 2);
assert.deepEqual(array.unsqueeze(2, 1), [2]);
assert.deepEqual(array.unsqueeze(2, 2), [[2]]);
assert.deepEqual(array.unsqueeze('string', 2), [['string']]);
});
it('should ignore empty arrays in unsqueeze', function () {
// should do nothing with empty arrays
assert.deepEqual(array.unsqueeze([], 0), []);
assert.deepEqual(array.unsqueeze([], 1), []);
assert.deepEqual(array.unsqueeze([], 2), []);
assert.deepEqual(array.unsqueeze([], 3), []);
assert.deepEqual(array.unsqueeze([[]], 0), [[]]);
assert.deepEqual(array.unsqueeze([[]], 1), [[]]);
assert.deepEqual(array.unsqueeze([[]], 2), [[]]);
assert.deepEqual(array.unsqueeze([[]], 3), [[]]);
});
it('should unsqueeze an array', function () {
assert.deepEqual(array.unsqueeze([1, 2, 3], 1), [1, 2, 3]);
assert.deepEqual(array.unsqueeze([1, 2, 3], 2), [[1], [2], [3]]);
assert.deepEqual(array.unsqueeze([1, 2, 3], 3), [[[1]], [[2]], [[3]]]);
assert.deepEqual(array.unsqueeze([1, 2, 3], 3, 1), [[[1], [2], [3]]]);
assert.deepEqual(array.unsqueeze([1, 2, 3], 3, 2), [[[1, 2, 3]]]);
assert.deepEqual(array.unsqueeze([[1, 2], [3, 4]], 1), [[1, 2], [3, 4]]);
assert.deepEqual(array.unsqueeze([[1, 2], [3, 4]], 2), [[1, 2], [3, 4]]);
assert.deepEqual(array.unsqueeze([[1, 2], [3, 4]], 3), [[[1], [2]], [[3], [4]]]);
});
it('should adjust size when unsqueezing an array', function () {
var a = [[1, 2], [3, 4]];
var size = [2,2];
array.unsqueeze(a, 3, 0, size);
assert.deepEqual(a, [[[1], [2]], [[3], [4]]]);
assert.deepEqual(size, [2,2,1]);
a = [1, 2, 3, 4];
size = [4];
array.unsqueeze(a, 3, 0, size);
assert.deepEqual(a, [[[1]], [[2]], [[3]], [[4]]]);
assert.deepEqual(size, [4,1,1]);
});
});
describe('resize', function () {
it('should test whether an object is an array', function () {
assert.equal(array.isArray([]), true);
assert.equal(array.isArray({}), false);
assert.equal(array.isArray(2), false);
assert.equal(array.isArray('string'), false);
});
});
describe('validateIndex', function () {
it('should validate whether an index contains integers', function () {
assert.equal(array.validateIndex(2), undefined);
assert.equal(array.validateIndex(10), undefined);
assert.throws(function () {array.validateIndex(2.3)}, /Index must be an integer/);
assert.throws(function () {array.validateIndex('str')}, /Index must be an integer/);
assert.throws(function () {array.validateIndex(true)}, /Index must be an integer/);
});
it('should validate whether an index doesn\'t exceed the minimum 0', function () {
assert.equal(array.validateIndex(2), undefined);
assert.equal(array.validateIndex(0), undefined);
assert.throws(function () {array.validateIndex(-1)}, /Index out of range/);
assert.throws(function () {array.validateIndex(-100)}, /Index out of range/);
});
it('should validate whether an index doesn\'t exceed both minimum and maximum', function () {
assert.equal(array.validateIndex(0, 10), undefined);
assert.equal(array.validateIndex(4, 10), undefined);
assert.equal(array.validateIndex(9, 10), undefined);
assert.throws(function () {array.validateIndex(-1, 10)}, /Index out of range/);
assert.throws(function () {array.validateIndex(10, 10)}, /Index out of range/);
assert.throws(function () {array.validateIndex(11, 10)}, /Index out of range/);
assert.throws(function () {array.validateIndex(100, 10)}, /Index out of range/);
});
it('thrown IndexError should contain the right index, max, and min properties', function () {
try {
array.validateIndex(4, 3);
assert.ok(false, 'should not reach this point');
}
catch(err) {
assert.equal(err.toString(), 'IndexError: Index out of range (4 > 2)');
assert.equal(err.index, 4);
assert.equal(err.min, 0);
assert.equal(err.max, 3);
}
try {
array.validateIndex(-1, 3);
assert.ok(false, 'should not reach this point');
}
catch(err) {
assert.equal(err.toString(), 'IndexError: Index out of range (-1 < 0)');
assert.equal(err.index, -1);
assert.equal(err.min, 0);
assert.equal(err.max, 3);
}
try {
array.validateIndex(-1);
assert.ok(false, 'should not reach this point');
}
catch(err) {
assert.equal(err.toString(), 'IndexError: Index out of range (-1 < 0)');
assert.equal(err.index, -1);
assert.equal(err.min, 0);
assert.equal(err.max, undefined);
}
});
});
describe('validate', function () {
it('should validate whether all elements in a vector have correct size', function () {
// valid vector with correct size
assert.equal(array.validate([], [0]), undefined);
assert.equal(array.validate([1], [1]), undefined);
assert.equal(array.validate([1,2,3], [3]), undefined);
// valid matrix but wrong size
assert.throws(function () {array.validate([1,2,3], [2])}, /Dimension mismatch/);
assert.throws(function () {array.validate([1,2,3], [4])}, /Dimension mismatch/);
assert.throws(function () {array.validate([1,2,3], [])}, /Dimension mismatch/);
assert.throws(function () {array.validate([1,2,3], [3,2])}, /Dimension mismatch/);
// invalid vector
assert.throws(function () {array.validate([1,[2],3], [3])}, /Dimension mismatch/);
});
it('should validate whether all elements in a 2d matrix have correct size', function () {
// valid matrix with correct size
assert.equal(array.validate([[1,2],[3,4]], [2,2]), undefined);
assert.equal(array.validate([[1,2,3],[4,5,6]], [2,3]), undefined);
assert.equal(array.validate([[1,2],[3,4],[5,6]], [3,2]), undefined);
// valid matrix with wrong size
assert.throws(function () {array.validate([[1,2],[3,4]], [2,1])}, /Dimension mismatch/);
assert.throws(function () {array.validate([[1,2],[3,4]], [3,2])}, /Dimension mismatch/);
assert.throws(function () {array.validate([[1,2,3],[4,5,6]], [2,4])}, /Dimension mismatch/);
assert.throws(function () {array.validate([[1,2],[3,4],[5,6]], [4,3])}, /Dimension mismatch/);
// invalid matrix
assert.throws(function () {array.validate([[1,2],[3,4,5]], [2,2])}, /Dimension mismatch/);
assert.throws(function () {array.validate([[1,2],[3]], [2,2])}, /Dimension mismatch/);
assert.throws(function () {array.validate([[1,2],3], [2,2])}, /Dimension mismatch/);
assert.throws(function () {array.validate([1,2], [2,2])}, /Dimension mismatch/);
assert.throws(function () {array.validate([[[1,2],[3,4]]], [2,2])}, /Dimension mismatch/);
});
it('should validate whether all elements in a multi dimensional matrix have correct size', function () {
// valid matrix with correct size
assert.equal(array.validate([[[1,2],[3,4]],[[5,6],[7,8]]], [2,2,2]), undefined);
assert.equal(array.validate([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]], [2,2,3]), undefined);
assert.equal(array.validate([[[1,2],[3,4],[5,6]],[[7,8],[9,10],[11,12]]], [2,3,2]), undefined);
assert.equal(array.validate([[[1,2],[3,4]],[[5,6],[7,8]],[[9,10],[11,12]]], [3,2,2]), undefined);
// valid matrix with wrong size
assert.throws(function () {array.validate([[[1,2],[3,4]],[[5,6],[7,8]]], [2,2,3])}, /Dimension mismatch/);
assert.throws(function () {array.validate([[[1,2],[3,4]],[[5,6],[7,8]]], [2,2])}, /Dimension mismatch/);
assert.throws(function () {array.validate([[[1,2],[3,4]],[[5,6],[7,8]]], [2,2,2,2])}, /Dimension mismatch/);
assert.throws(function () {array.validate([[[1,2],[3,4]],[[5,6],[7,8]]], [3,2,2])}, /Dimension mismatch/);
assert.throws(function () {array.validate([[[1,2],[3,4]],[[5,6],[7,8]]], [2,3,2])}, /Dimension mismatch/);
// invalid matrix
assert.throws(function () {array.validate([[[1,2],[3,4]],[[5,6],[7,8,9]]], [2,2,2])}, /Dimension mismatch/);
assert.throws(function () {array.validate([[[1,2],[3,4]],[[5,6,6.5],[7,8]]], [2,2,2])}, /Dimension mismatch/);
assert.throws(function () {array.validate([[[1,2],[3,4]],[[5,6],7]], [2,2,2])}, /Dimension mismatch/);
assert.throws(function () {array.validate([[[1,2],[3,4]],[6,[7,8]]], [2,2,2])}, /Dimension mismatch/);
});
it('should validate whether a variable contains a scalar', function () {
assert.equal(array.validate(2.3, []), undefined);
assert.equal(array.validate(new Date(), []), undefined);
assert.equal(array.validate({}, []), undefined);
assert.throws(function () {array.validate([], [])}, /Dimension mismatch/);
assert.throws(function () {array.validate([1,2,3], [])}, /Dimension mismatch/);
assert.throws(function () {array.validate([[1,2],[3,4]], [])}, /Dimension mismatch/);
});
});
describe('flatten', function () {
it('should flatten a scalar', function () {
assert.deepEqual(array.flatten(1), 1);
});
it('should flatten a 1 dimensional array', function () {
assert.deepEqual(array.flatten([1,2,3]), [1,2,3]);
});
it('should flatten a 2 dimensional array', function () {
assert.deepEqual(array.flatten([[1,2],[3,4]]), [1,2,3,4]);
});
it('should flatten a 3 dimensional array', function () {
assert.deepEqual(array.flatten([[[1,2],[3,4]],[[5,6],[7,8]]]), [1,2,3,4,5,6,7,8]);
});
it('should return a new array', function () {
var input = [3,2,1];
var flat = array.flatten(input);
flat.sort();
assert.deepEqual(input, [3,2,1]);
});
});
});
/**
* Helper function to create an Array containing uninitialized values
* Example: arr(uninit, uninit, 2); // [ , , 2 ]
*/
var uninit = {};
function arr() {
var array = [];
array.length = arguments.length;
for (var i = 0; i < arguments.length; i++) {
var value = arguments[i];
if (value !== uninit) {
array[i] = value;
}
}
return array;
}

View File

@@ -0,0 +1,40 @@
// test bignumber utils
var assert = require('assert');
var BigNumber = require('decimal.js');
var Big32 = BigNumber.clone({precision: 32});
var Big64 = BigNumber.clone({precision: 64});
var constants = require('../../../lib/utils/bignumber/constants');
describe('bignumber', function() {
it('should calculate a bignumber e', function() {
assert.equal(constants.e(Big32),
'2.7182818284590452353602874713527');
assert.equal(constants.e(Big64),
'2.718281828459045235360287471352662497757247093699959574966967628');
});
it('should calculate a bignumber pi', function() {
assert.equal(constants.pi(Big32),
'3.1415926535897932384626433832795');
assert.equal(constants.pi(Big64),
'3.141592653589793238462643383279502884197169399375105820974944592');
});
it('should calculate a bignumber tau', function() {
assert.equal(constants.tau(Big32),
'6.283185307179586476925286766559');
assert.equal(constants.tau(Big64),
'6.283185307179586476925286766559005768394338798750211641949889184');
});
it('should calculate a bignumber phi', function() {
// FIXME: round-off error
//assert.equal(bignumber.phi(32), '1.6180339887498948482045868343656');
assert.equal(constants.phi(Big32),
'1.6180339887498948482045868343657');
assert.equal(constants.phi(Big64),
'1.618033988749894848204586834365638117720309179805762862135448623');
});
});

View File

@@ -0,0 +1,245 @@
var assert = require('assert');
var BigNumber = require('decimal.js');
var formatter = require('../../../lib/utils/bignumber/formatter');
describe('format', function () {
describe('format', function () {
var B = null;
before (function () {
B = BigNumber.clone({precision: 20}); // ensure the precision is 20 digits
});
it ('should format special values Infinity, NaN', function () {
assert.equal(formatter.format(new BigNumber(Infinity)), 'Infinity');
assert.equal(formatter.format(new BigNumber(-Infinity)), '-Infinity');
assert.equal(formatter.format(new BigNumber(NaN)), 'NaN');
});
it('auto notation', function () {
assert.equal(formatter.format(new B(2).dividedBy(7)), '0.28571428571428571429');
assert.equal(formatter.format(new B(0.10400)), '0.104');
assert.equal(formatter.format(new B(1000)), '1000');
assert.equal(formatter.format(new B(0)), '0');
assert.equal(formatter.format(new B(2.4e-7)), '2.4e-7');
assert.equal(formatter.format(new B(2.4e-6)), '2.4e-6');
assert.equal(formatter.format(new B(2.4e-5)), '2.4e-5');
assert.equal(formatter.format(new B(2.4e-4)), '2.4e-4');
assert.equal(formatter.format(new B(2.3e-3)), '0.0023');
assert.equal(formatter.format(new B(2.3456e-3)), '0.0023456');
assert.equal(formatter.format(new B(2.3e-2)), '0.023');
assert.equal(formatter.format(new B(2.3e-1)), '0.23');
assert.equal(formatter.format(new B(2.3)), '2.3');
assert.equal(formatter.format(new B(2.3e+1)), '23');
assert.equal(formatter.format(new B(2.3e+2)), '230');
assert.equal(formatter.format(new B(2.3e+3)), '2300');
assert.equal(formatter.format(new B(2.3e+4)), '23000');
assert.equal(formatter.format(new B(2.3e+5)), '2.3e+5');
assert.equal(formatter.format(new B(2.3e+6)), '2.3e+6');
assert.equal(formatter.format(new B(1.000000012)), '1.000000012');
assert.equal(formatter.format(new B(1000000012)), '1.000000012e+9');
assert.equal(formatter.format(new B(1234567)), '1.234567e+6');
assert.equal(formatter.format(new B(123456789123456)), '1.23456789123456e+14');
assert.equal(formatter.format(new B(123456789123456e-14)), '1.23456789123456');
assert.equal(formatter.format(new B('123456789123456789')), '1.23456789123456789e+17');
assert.equal(formatter.format(new B('123456789123456789123456789')), '1.23456789123456789123456789e+26');
assert.equal(formatter.format(new B(0.1111e+6)), '1.111e+5');
assert.equal(formatter.format(new B(0.3333e+6)), '3.333e+5');
assert.equal(formatter.format(new B(0.6666e+6)), '6.666e+5');
assert.equal(formatter.format(new B(0.9999e+6)), '9.999e+5');
assert.equal(formatter.format(new B(1.111e+6)), '1.111e+6');
});
it('auto notation with precision as second parameter', function() {
assert.deepEqual(formatter.format(new B('1.23456'), 3), '1.23');
assert.deepEqual(formatter.format(new B('12345678'), 4), '1.235e+7');
assert.equal(formatter.format(new B(1).dividedBy(3)), '0.33333333333333333333');
assert.equal(formatter.format(new B(1).dividedBy(3), 5), '0.33333');
assert.equal(formatter.format(new B(1).dividedBy(3), 3), '0.333');
assert.equal(formatter.format(new B(2).dividedBy(3), 3), '0.667');
});
describe('should apply options', function () {
it('auto notation with precision', function () {
assert.equal(formatter.format(new B(1).div(3)), '0.33333333333333333333');
assert.equal(formatter.format(new B(1).div(3), {precision: 3}), '0.333');
assert.equal(formatter.format(new B(1).div(3), {precision: 4}), '0.3333');
assert.equal(formatter.format(new B(1).div(3), {precision: 5}), '0.33333');
assert.equal(formatter.format(new B(1000.000), {precision: 5}), '1000');
assert.equal(formatter.format(new B(1000.0010), {precision: 5}), '1000'); // rounded off at 5 digits
assert.equal(formatter.format(new B(1234), {precision: 3}), '1230');
assert.equal(formatter.format(new B(123.4), {precision: 6}), '123.4');
assert.equal(formatter.format(new B(0.001234), {precision: 3}), '0.00123');
assert.equal(formatter.format(new B(1234567), {precision: 4}), '1.235e+6');
assert.equal(formatter.format(new B(1234567), {precision: 2}), '1.2e+6');
assert.equal(formatter.format(new B(123e-6), {precision: 2}), '1.2e-4');
assert.equal(formatter.format(new B(123e-6), {precision: 8}), '1.23e-4'); // should remove trailing zeros
assert.equal(formatter.format(new B(3e+6), {precision: 8}), '3e+6'); // should remove trailing zeros
assert.equal(formatter.format(new B(1234), {precision: 2}), '1200');
// overflow the maximum precision of 20
assert.equal(formatter.format(new B(2.3), {precision: 30}), '2.3');
});
it('auto notation with custom lower and upper bound', function () {
var options = {
exponential: {
lower: 1e-6,
upper: 1e+9
}
};
assert.equal(formatter.format(new B(0), options), '0');
assert.equal(formatter.format(new B(1234567), options), '1234567');
assert.equal(formatter.format(new B(1e+9), options), '1e+9');
assert.equal(formatter.format(new B(1e+9-1), options), '999999999');
assert.equal(formatter.format(new B(1e-6), options), '0.000001');
assert.equal(formatter.format(new B(0.999e-6), options), '9.99e-7');
assert.equal(formatter.format(new B(123456789123), options), '1.23456789123e+11');
});
});
it('should format bignumbers with a custom formatting function', function() {
function asCurrency (value) {
return '$' + value.toFixed(2);
}
assert.equal(formatter.format(new BigNumber(12.4264), asCurrency), '$12.43');
assert.equal(formatter.format(new BigNumber(0.1), asCurrency), '$0.10');
assert.equal(formatter.format(new BigNumber(1.2e+6), asCurrency), '$1200000.00');
});
it('should format bignumbers in exponential notation', function() {
var options = {
notation: 'exponential'
};
assert.deepEqual(formatter.format(new B('1.23456'), options), '1.23456e+0');
assert.deepEqual(formatter.format(new B('12345678'), options), '1.2345678e+7');
assert.deepEqual(formatter.format(new B('2.3e+30'), options), '2.3e+30');
assert.deepEqual(formatter.format(new B('0.23e+30'), options), '2.3e+29');
assert.deepEqual(formatter.format(new B('2.3e-30'), options), '2.3e-30');
assert.deepEqual(formatter.format(new B('0.23e-30'), options), '2.3e-31');
});
it('should format bignumbers in exponential notation with precision', function() {
var options = {
notation: 'exponential',
precision: 18
};
assert.deepEqual(formatter.format(new B(1).div(3), options), '3.33333333333333333e-1');
});
it('should format bignumbers with custom precision, lower, and upper bound', function() {
var Big = BigNumber.clone({precision: 100});
var options = {
notation: 'auto',
precision : 50,
exponential: {
lower: 1e-50,
upper: 1e+50
}
};
assert.deepEqual(formatter.format(new Big(5).div(3), options), '1.6666666666666666666666666666666666666666666666667');
assert.deepEqual(formatter.format(new Big(5e+40).div(3), options), '16666666666666666666666666666666666666666.666666667');
assert.deepEqual(formatter.format(new Big(5e-40).div(3), options),
'0.00000000000000000000000000000000000000016666666666666666666666666666666666666666666666667');
assert.deepEqual(formatter.format(new Big(5e+60).div(3), options), '1.6666666666666666666666666666666666666666666666667e+60');
assert.deepEqual(formatter.format(new Big(5e-60).div(3), options), '1.6666666666666666666666666666666666666666666666667e-60');
assert.deepEqual(formatter.format(new Big(5e-80).div(3), options), '1.6666666666666666666666666666666666666666666666667e-80');
});
it('auto notation with custom lower bound', function () {
var options = {
exponential: {
lower: 1e-6
}
};
assert.equal(formatter.format(new BigNumber(0), options), '0');
assert.equal(formatter.format(new BigNumber(1e-5), options), '0.00001');
assert.equal(formatter.format(new BigNumber(1e-6), options), '0.000001');
assert.equal(formatter.format(new BigNumber(0.999e-6), options), '9.99e-7');
assert.equal(formatter.format(new BigNumber(1e-7), options), '1e-7');
});
it('auto notation with custom upper bound', function () {
var options = {
exponential: {
upper: 1e+9
}
};
assert.equal(formatter.format(new BigNumber(1e+9), options), '1e+9');
assert.equal(formatter.format(new BigNumber(1e+9-1), options), '999999999');
});
it('should format bignumbers in fixed notation', function() {
var options = {
notation: 'fixed'
};
assert.deepEqual(formatter.format(new BigNumber('1.23456'), options), '1');
assert.deepEqual(formatter.format(new BigNumber('1.7'), options), '2');
assert.deepEqual(formatter.format(new BigNumber('12345678'), options), '12345678');
assert.deepEqual(formatter.format(new BigNumber('12e18'), options), '12000000000000000000');
assert.deepEqual(formatter.format(new BigNumber('12e30'), options), '12000000000000000000000000000000');
});
it('should format bignumbers in fixed notation with precision', function() {
options = {
notation: 'fixed',
precision: 2
};
assert.deepEqual(formatter.format(new BigNumber('1.23456'), options), '1.23');
assert.deepEqual(formatter.format(new BigNumber('12345678'), options), '12345678.00');
assert.deepEqual(formatter.format(new BigNumber('12e18'), options), '12000000000000000000.00');
assert.deepEqual(formatter.format(new BigNumber('12e30'), options), '12000000000000000000000000000000.00');
});
it('should throw an error on unknown notation', function () {
assert.throws(function () {
formatter.format(new BigNumber(123), {notation: 'non existing'})
});
});
});
it('should format a bignumber using toFixed', function() {
var Big = BigNumber.clone({precision: 100});
assert.equal(formatter.toFixed(new Big(2.34)), '2');
assert.equal(formatter.toFixed(new Big(2.34), 1), '2.3');
assert.equal(formatter.toFixed(new Big(2), 20), '2.00000000000000000000');
assert.equal(formatter.toFixed(new Big(2), 21), '2.000000000000000000000');
assert.equal(formatter.toFixed(new Big(2), 22), '2.0000000000000000000000');
assert.equal(formatter.toFixed(new Big(2), 30), '2.000000000000000000000000000000');
});
it('should format a bignumber using toExponential', function() {
var Big = BigNumber.clone({precision: 100});
assert.equal(formatter.toExponential(new Big(2.34)), '2.34e+0');
assert.equal(formatter.toExponential(new Big(2.34e+3)), '2.34e+3');
assert.equal(formatter.toExponential(new Big(2.34e-3)), '2.34e-3');
assert.equal(formatter.toExponential(new Big(2.34e+3), 2), '2.3e+3');
assert.equal(formatter.toExponential(new Big(2e+3), 20), '2.0000000000000000000e+3');
assert.equal(formatter.toExponential(new Big(2e+3), 21), '2.00000000000000000000e+3');
assert.equal(formatter.toExponential(new Big(2e+3), 22), '2.000000000000000000000e+3');
assert.equal(formatter.toExponential(new Big(2e+3), 30), '2.00000000000000000000000000000e+3');
assert.equal(formatter.toExponential(new Big('2e+300'), 30), '2.00000000000000000000000000000e+300');
assert.equal(formatter.toExponential(new Big('2e-300'), 30), '2.00000000000000000000000000000e-300');
});
});

View File

@@ -0,0 +1,84 @@
var assert = require('assert');
var BigNumber = require('decimal.js');
var nearlyEqual = require('../../../lib/utils/bignumber/nearlyEqual');
describe('nearlyEqual', function () {
it('should test whether two BigNumbers are nearly equal', function () {
var epsilon = 1e-2;
assert.equal(nearlyEqual(new BigNumber(1), new BigNumber(0.9), epsilon), false);
assert.equal(nearlyEqual(new BigNumber(1), new BigNumber(0.95), epsilon), false);
assert.equal(nearlyEqual(new BigNumber(1), new BigNumber(0.98), epsilon), false);
assert.equal(nearlyEqual(new BigNumber(1), new BigNumber(0.99), epsilon), true);
assert.equal(nearlyEqual(new BigNumber(1), new BigNumber(0.991), epsilon), true);
assert.equal(nearlyEqual(new BigNumber(1), new BigNumber(1.1), epsilon), false);
assert.equal(nearlyEqual(new BigNumber(1), new BigNumber(1.05), epsilon), false);
assert.equal(nearlyEqual(new BigNumber(1), new BigNumber(1.02), epsilon), false);
assert.equal(nearlyEqual(new BigNumber(1), new BigNumber(1.01), epsilon), true);
assert.equal(nearlyEqual(new BigNumber(1), new BigNumber(1), epsilon), true);
// smaller epsilon
var epsilon2 = 1e-4;
assert.equal(nearlyEqual(new BigNumber(1), new BigNumber(0.99), epsilon2), false);
assert.equal(nearlyEqual(new BigNumber(1), new BigNumber(0.999), epsilon2), false);
assert.equal(nearlyEqual(new BigNumber(1), new BigNumber(0.9999), epsilon2), true);
});
it('should test whether a positive and negative number are nearly equal', function () {
var epsilon = 1e-3;
assert.equal(nearlyEqual(new BigNumber( 1.2), new BigNumber( 1.2), epsilon), true);
assert.equal(nearlyEqual(new BigNumber( 1.2), new BigNumber(-1.2), epsilon), false);
assert.equal(nearlyEqual(new BigNumber(-1.2), new BigNumber( 1.2), epsilon), false);
assert.equal(nearlyEqual(new BigNumber(-1.2), new BigNumber(-1.2), epsilon), true);
});
it('should test whether two large numbers are nearly equal', function () {
var epsilon = 1e-2;
assert.equal(nearlyEqual(new BigNumber('1e500'), new BigNumber('0.90e500'), epsilon), false);
assert.equal(nearlyEqual(new BigNumber('1e500'), new BigNumber('0.95e500'), epsilon), false);
assert.equal(nearlyEqual(new BigNumber('1e500'), new BigNumber('0.98e500'), epsilon), false);
assert.equal(nearlyEqual(new BigNumber('1e500'), new BigNumber('0.99e500'), epsilon), true);
});
it('should test whether two small numbers are nearly equal (always true)', function () {
var epsilon = 1e-2;
assert.equal(nearlyEqual(new BigNumber('1e-200'), new BigNumber('0.99e-200'), epsilon), true);
assert.equal(nearlyEqual(new BigNumber('1e-200'), new BigNumber('10e-200'), epsilon), false);
});
it('should compare with zero', function () {
var epsilon = 1e-3;
assert.equal(nearlyEqual(new BigNumber(0), new BigNumber(0), epsilon), true);
assert.equal(nearlyEqual(new BigNumber(0), new BigNumber(-0), epsilon), true);
assert.equal(nearlyEqual(new BigNumber(0), new BigNumber(1.2), epsilon), false);
assert.equal(nearlyEqual(new BigNumber(0), new BigNumber(1e30), epsilon), false);
assert.equal(nearlyEqual(new BigNumber(0), new BigNumber(1e-30), epsilon), false);
});
it('should compare with Infinity', function () {
var epsilon = 1e-3;
assert.equal(nearlyEqual(new BigNumber(1.2), new BigNumber(Infinity), epsilon), false);
assert.equal(nearlyEqual(new BigNumber(Infinity), new BigNumber(1.2), epsilon), false);
assert.equal(nearlyEqual(new BigNumber(Infinity), new BigNumber(Infinity), epsilon), true);
assert.equal(nearlyEqual(new BigNumber(Infinity), new BigNumber(-Infinity), epsilon), false);
assert.equal(nearlyEqual(new BigNumber(-Infinity), new BigNumber(Infinity), epsilon), false);
assert.equal(nearlyEqual(new BigNumber(-Infinity), new BigNumber(-Infinity), epsilon), true);
});
it('should compare with NaN', function () {
var epsilon = 1e-3;
assert.equal(nearlyEqual(new BigNumber(1.2), new BigNumber(NaN), epsilon), false);
assert.equal(nearlyEqual(new BigNumber(NaN), new BigNumber(1.2), epsilon), false);
assert.equal(nearlyEqual(new BigNumber(NaN), new BigNumber(NaN), epsilon), false);
});
it('should do exact comparison when epsilon is null or undefined', function () {
assert.equal(nearlyEqual(new BigNumber(1.2), new BigNumber(1.2)), true);
assert.equal(nearlyEqual(new BigNumber(1.2), new BigNumber(1.2), null), true);
assert.equal(nearlyEqual(new BigNumber(1.2).plus(1e-18), new BigNumber(1.2)), false);
assert.equal(nearlyEqual(new BigNumber(1.2).plus(1e-18), new BigNumber(1.2), null), false);
});
});

View File

@@ -0,0 +1,23 @@
// test boolean utils
var assert = require('assert'),
approx = require('../../tools/approx'),
boolean = require('../../lib/utils/boolean');
describe ('boolean', function () {
it('isBoolean', function() {
assert.equal(boolean.isBoolean(true), true);
assert.equal(boolean.isBoolean(false), true);
assert.equal(boolean.isBoolean(Boolean(false)), true);
assert.equal(boolean.isBoolean('hi'), false);
assert.equal(boolean.isBoolean(23), false);
assert.equal(boolean.isBoolean([]), false);
assert.equal(boolean.isBoolean({}), false);
assert.equal(boolean.isBoolean(new Date()), false);
// we don't support non primitive Boolean anymore
assert.equal(boolean.isBoolean(new Boolean(true)), false);
assert.equal(boolean.isBoolean(new Boolean(false)), false);
});
});

View File

@@ -0,0 +1,104 @@
var assert = require('assert');
var functionUtils = require('../../lib/utils/function');
describe('util.function', function() {
describe('memoize', function () {
it('should memoize a function with one argument', function () {
var f = function (x) {return x * x};
var m = functionUtils.memoize(f);
assert.strictEqual(m(2), 4);
assert.strictEqual(m(3), 9);
});
it('should memoize a function with two arguments', function () {
var f = function (x, y) {return x * y};
var m = functionUtils.memoize(f);
assert.strictEqual(m(2, 3), 6);
// hash should differ
assert.strictEqual(m(1, 23), 23);
assert.strictEqual(m(12, 3), 36);
});
it('should memoize a function with objects as arguments', function () {
var f = function (obj) {return obj.x * obj.y};
var m = functionUtils.memoize(f);
assert.strictEqual(m({x: 2, y: 3}), 6);
assert.deepEqual(Object.keys(m.cache), ['[{"x":2,"y":3}]']);
assert.strictEqual(m.cache['[{"x":2,"y":3}]'], 6);
});
it('should memoize a function with a custom hashIt function', function () {
var f = function (obj) {return obj.id};
var hashIt = function (args) {
return 'id:' + args[0].id;
};
var m = functionUtils.memoize(f, hashIt);
assert.strictEqual(m({id: 2}), 2);
assert.deepEqual(Object.keys(m.cache), ['id:2']);
assert.strictEqual(m.cache['id:2'], 2);
});
it('should really return the cached result', function () {
var a = 2;
var f = function (x) {return a}; // trick: no pure function
var m = functionUtils.memoize(f);
assert.strictEqual(m(4), 2);
a = 3;
assert.strictEqual(m(4), 2);
});
});
describe ('maxArgumentCount', function () {
it('should calculate the max argument count of a typed function', function() {
var a = function () {};
a.signatures = {
'number, number': function () {},
'number': function () {}
};
assert.equal(functionUtils.maxArgumentCount(a), 2);
var b = function () {};
b.signatures = {
'number': function () {},
'number, number': function () {}
};
assert.equal(functionUtils.maxArgumentCount(b), 2);
var c = function () {};
c.signatures = {
'number': function () {},
'BigNumber': function () {}
};
assert.equal(functionUtils.maxArgumentCount(c), 1);
var d = function () {};
d.signatures = {
'number,number': function () {},
'number': function () {},
'number,any,number': function () {}
};
assert.equal(functionUtils.maxArgumentCount(d), 3);
});
it('should return -1 for regular functions', function() {
assert.equal(functionUtils.maxArgumentCount(function () {}), -1);
});
});
});

View File

@@ -0,0 +1,12 @@
var assert = require('assert'),
latex = require('../../lib/utils/latex');
describe('util.latex', function() {
it('should convert symbols with indices', function () {
assert.equal(latex.toSymbol('alpha_1'), '\\alpha_{1}');
});
it('should convert units', function () {
assert.equal(latex.toSymbol('deg', true), '^\\circ');
});
});

View File

@@ -0,0 +1,591 @@
// test number utils
var assert = require('assert'),
approx = require('../../tools/approx'),
number = require('../../lib/utils/number');
describe('number', function() {
it('isInteger', function() {
assert.equal(number.isInteger(1), true);
assert.equal(number.isInteger(3), true);
assert.equal(number.isInteger(-4), true);
assert.equal(number.isInteger(0), true);
assert.equal(number.isInteger(12000), true);
assert.equal(number.isInteger(-3000), true);
assert.equal(number.isInteger(1.1), false);
assert.equal(number.isInteger(0.1), false);
assert.equal(number.isInteger(-2.3), false);
assert.equal(number.isInteger(-2.3), false);
assert.equal(number.isInteger(NaN), false);
});
it('isNumber', function() {
assert.equal(number.isNumber(1), true);
assert.equal(number.isNumber(2e+3), true);
assert.equal(number.isNumber(Number(2.3)), true);
assert.equal(number.isNumber(NaN), true);
assert.equal(number.isNumber(-23), true);
assert.equal(number.isNumber(parseFloat('123')), true);
assert.equal(number.isNumber('23'), false);
assert.equal(number.isNumber('str'), false);
assert.equal(number.isNumber(new Date()), false);
assert.equal(number.isNumber({}), false);
assert.equal(number.isNumber([]), false);
assert.equal(number.isNumber(/regexp/), false);
assert.equal(number.isNumber(true), false);
assert.equal(number.isNumber(false), false);
assert.equal(number.isNumber(null), false);
assert.equal(number.isNumber(undefined), false);
assert.equal(number.isNumber(), false);
// we don't support non primitive Numbers anymore
assert.equal(number.isNumber(new Number(23)), false);
});
it('sign', function() {
assert.equal(number.sign(1), 1);
assert.equal(number.sign(3), 1);
assert.equal(number.sign(4.5), 1);
assert.equal(number.sign(0.00234), 1);
assert.equal(number.sign(0), 0);
assert.equal(number.sign(-1), -1);
assert.equal(number.sign(-3), -1);
assert.equal(number.sign(-0.23), -1);
});
it('should count the number of significant digits of a number', function() {
assert.equal(number.digits(0), 0);
assert.equal(number.digits(2), 1);
assert.equal(number.digits(1234), 4);
assert.equal(number.digits(2.34), 3);
assert.equal(number.digits(3000), 1);
assert.equal(number.digits(0.0034), 2);
assert.equal(number.digits(120.5e50), 4);
assert.equal(number.digits(1120.5e+50), 5);
assert.equal(number.digits(120.52e-50), 5);
assert.equal(number.digits(Math.PI), 16);
});
it('should format a number using toFixed', function() {
assert.equal(number.toFixed(2.34), '2');
assert.equal(number.toFixed(2.34, 1), '2.3');
assert.equal(number.toFixed(-2.34, 1), '-2.3');
assert.equal(number.toFixed(2.34e10, 1), '23400000000.0');
assert.equal(number.toFixed(2.34e30, 1), '2340000000000000000000000000000.0'); // test above the 21 digit limit of toPrecision
assert.equal(number.toFixed(2.34e-10, 1), '0.0');
assert.equal(number.toFixed(2, 20), '2.00000000000000000000');
assert.equal(number.toFixed(2, 21), '2.000000000000000000000');
assert.equal(number.toFixed(2, 22), '2.0000000000000000000000');
assert.equal(number.toFixed(2, 30), '2.000000000000000000000000000000');
assert.equal(number.toFixed(-2e3, 0), '-2000');
assert.equal(number.toFixed(5.555, 1), '5.6');
assert.equal(number.toFixed(-5.555, 1), '-5.6');
assert.equal(number.toFixed(-0.005555, 4), '-0.0056');
assert.equal(number.toFixed(2.135, 2), '2.14');
});
it('should format a number using toPrecision', function() {
assert.equal(number.toPrecision(2.34), '2.34');
assert.equal(number.toPrecision(2.34, 2), '2.3');
assert.equal(number.toPrecision(-2.34, 2), '-2.3');
assert.equal(number.toPrecision(2.34e10, 2), '2.3e+10');
assert.equal(number.toPrecision(2.34e-10, 2), '2.3e-10');
assert.equal(number.toPrecision(2, 4), '2.000');
assert.equal(number.toPrecision(-0.005555, 2), '-0.0056');
assert.equal(number.toPrecision(2.135, 3), '2.14');
// TODO: test upper and lower bounds here
});
it('should format a number using toExponential', function() {
assert.equal(number.toExponential(2.34), '2.34e+0');
assert.equal(number.toExponential(2.34e+3), '2.34e+3');
assert.equal(number.toExponential(2.34e-3), '2.34e-3');
assert.equal(number.toExponential(2.34e+3, 2), '2.3e+3');
assert.equal(number.toExponential(2.135, 3), '2.14e+0');
assert.equal(number.toExponential(2e+3, 20), '2.0000000000000000000e+3');
assert.equal(number.toExponential(2e+3, 21), '2.00000000000000000000e+3');
assert.equal(number.toExponential(2e+3, 22), '2.000000000000000000000e+3');
assert.equal(number.toExponential(2e+3, 30), '2.00000000000000000000000000000e+3');
});
describe('format', function () {
it('should format special values Infinity, NaN', function () {
assert.equal(number.format(Infinity), 'Infinity');
assert.equal(number.format(-Infinity), '-Infinity');
assert.equal(number.format('no number'), 'NaN');
});
describe('should apply options', function () {
it('fixed notation', function () {
var options = {notation: 'fixed'};
assert.equal(number.format(0, options), '0');
assert.equal(number.format(123, options), '123');
assert.equal(number.format(123.456, options), '123');
assert.equal(number.format(123.7, options), '124');
assert.equal(number.format(-123.7, options), '-124');
assert.equal(number.format(-66, options), '-66');
assert.equal(number.format(0.123456, options), '0');
assert.equal(number.format(123456789, options), '123456789');
assert.equal(number.format(-123456789, options), '-123456789');
assert.equal(number.format(123456789e+9, options), '123456789000000000');
assert.equal(number.format(123456789e+17, options), '12345678900000000000000000');
assert.equal(number.format(123456789e+18, options), '123456789000000000000000000');
assert.equal(number.format(123456789e+19, options), '1234567890000000000000000000');
assert.equal(number.format(123456789e+20, options), '12345678900000000000000000000');
assert.equal(number.format(123456789e+21, options), '123456789000000000000000000000');
assert.equal(number.format(123456789e+22, options), '1234567890000000000000000000000');
assert.equal(number.format(1e-18, options), '0');
assert.equal(number.format(1e-22, options), '0');
assert.equal(number.format(1e-32, options), '0');
});
it('fixed notation with precision', function () {
var options = {notation: 'fixed', precision: 2};
assert.equal(number.format(0, options), '0.00');
assert.equal(number.format(123, options), '123.00');
assert.equal(number.format(123.456, options), '123.46');
assert.equal(number.format(123.7, options), '123.70');
assert.equal(number.format(0.123456, options), '0.12');
assert.equal(number.format(-0.5555, options), '-0.56');
assert.equal(number.format(123456789, options), '123456789.00');
assert.equal(number.format(123456789e+9, options), '123456789000000000.00');
assert.equal(number.format(123456789e+18, options), '123456789000000000000000000.00');
assert.equal(number.format(123456789e+19, options), '1234567890000000000000000000.00');
assert.equal(number.format(123456789e+20, options), '12345678900000000000000000000.00');
assert.equal(number.format(123456789e+21, options), '123456789000000000000000000000.00');
assert.equal(number.format(123456789e+22, options), '1234567890000000000000000000000.00');
assert.equal(number.format(1.2e-14, options), '0.00');
assert.equal(number.format(1.3e-18, options), '0.00');
assert.equal(number.format(1.3e-19, options), '0.00');
assert.equal(number.format(1.3e-20, options), '0.00');
assert.equal(number.format(1.3e-21, options), '0.00');
assert.equal(number.format(1.3e-22, options), '0.00');
assert.equal(number.format(5.6789e-30, {notation: 'fixed', precision: 32}),
'0.00000000000000000000000000000568');
assert.equal(number.format(5.6999e-30, {notation: 'fixed', precision: 32}),
'0.00000000000000000000000000000570');
});
it('exponential notation', function () {
var options = {notation: 'exponential'};
assert.equal(number.format(0, options), '0e+0');
assert.equal(number.format(123, options), '1.23e+2');
assert.equal(number.format(123.456, options), '1.23456e+2');
assert.equal(number.format(0.0123, options), '1.23e-2');
assert.equal(number.format(123456789, options), '1.23456789e+8');
assert.equal(number.format(123456789e+9, options), '1.23456789e+17');
assert.equal(number.format(123456789e-9, options), '1.23456789e-1');
});
it('exponential notation with precision', function () {
var options = {notation: 'exponential', precision: 3};
assert.equal(number.format(123, options), '1.23e+2');
assert.equal(number.format(123.456, options), '1.23e+2');
assert.equal(number.format(2, options), '2.00e+0');
});
it('auto notation', function () {
assert.equal(number.format(2/7), '0.2857142857142857');
assert.equal(number.format(0.10400), '0.104');
assert.equal(number.format(1000), '1000');
//assert.equal(number.format(-0.005), '-0.005');
assert.equal(number.format(-2300), '-2300');
assert.equal(number.format(-1.2e12), '-1.2e+12');
assert.equal(number.format(0), '0');
assert.equal(number.format(2.4e-7), '2.4e-7');
assert.equal(number.format(2.4e-6), '2.4e-6');
assert.equal(number.format(2.4e-5), '2.4e-5');
assert.equal(number.format(2.4e-4), '2.4e-4');
assert.equal(number.format(2.3e-3), '0.0023');
assert.equal(number.format(2.3e-2), '0.023');
assert.equal(number.format(2.3e-1), '0.23');
assert.equal(number.format(2.3), '2.3');
assert.equal(number.format(2.3e+1), '23');
assert.equal(number.format(2.3e+2), '230');
assert.equal(number.format(2.3e+3), '2300');
assert.equal(number.format(2.3e+4), '23000');
assert.equal(number.format(2.3e+5), '2.3e+5');
assert.equal(number.format(2.3e+6), '2.3e+6');
assert.equal(number.format(1.000000012), '1.000000012');
assert.equal(number.format(1000000012), '1.000000012e+9');
assert.equal(number.format(1234567), '1.234567e+6');
assert.equal(number.format(123456789123456), '1.23456789123456e+14');
assert.equal(number.format(123456789123456e-14), '1.23456789123456');
assert.equal(number.format(123456789123456789), '1.2345678912345678e+17');
assert.equal(number.format(0.1111e+6), '1.111e+5');
assert.equal(number.format(0.3333e+6), '3.333e+5');
assert.equal(number.format(0.6666e+6), '6.666e+5');
assert.equal(number.format(0.9999e+6), '9.999e+5');
assert.equal(number.format(1.111e+6), '1.111e+6');
});
it('auto notation with precision', function () {
assert.equal(number.format(1/3), '0.3333333333333333');
assert.equal(number.format(1/3, {precision: 3}), '0.333');
assert.equal(number.format(1/3, {precision: 4}), '0.3333');
assert.equal(number.format(1/3, {precision: 5}), '0.33333');
assert.equal(number.format(0.05555, {precision: 2}), '0.056');
assert.equal(number.format(-0.05555, {precision: 2}), '-0.056');
assert.equal(number.format(1000.000, {precision: 5}), '1000');
assert.equal(number.format(1000.0010, {precision: 5}), '1000'); // rounded off at 5 digits
assert.equal(number.format(1234, {precision: 3}), '1230');
assert.equal(number.format(123.4, {precision: 6}), '123.4');
assert.equal(number.format(0.001234, {precision: 3}), '0.00123');
assert.equal(number.format(1234567, {precision: 4}), '1.235e+6');
assert.equal(number.format(1234567, {precision: 2}), '1.2e+6');
assert.equal(number.format(123e-6, {precision: 2}), '1.2e-4');
assert.equal(number.format(123e-6, {precision: 8}), '1.23e-4'); // should remove trailing zeros
assert.equal(number.format(3e+6, {precision: 8}), '3e+6'); // should remove trailing zeros
assert.equal(number.format(1234, {precision: 2}), '1200');
// overflow the maximum allowed precision of 20
assert.equal(number.format(4, {precision: 30}), '4');
});
it('auto notation with custom lower and upper bound', function () {
var options = {
exponential: {
lower: 1e-6,
upper: 1e+9
}
};
assert.equal(number.format(0, options), '0');
assert.equal(number.format(1234567, options), '1234567');
assert.equal(number.format(1e+9, options), '1e+9');
assert.equal(number.format(1e+9-1, options), '999999999');
assert.equal(number.format(1e-6, options), '0.000001');
assert.equal(number.format(0.999e-6, options), '9.99e-7');
assert.equal(number.format(123456789123, options), '1.23456789123e+11');
assert.equal(number.format(Math.pow(2, 53), {exponential: {upper: 1e+20}}), '9007199254740992');
});
it('auto notation with custom lower bound', function () {
var options = { exponential: { lower: 1e-6 } };
assert.equal(number.format(0, options), '0');
assert.equal(number.format(1e-6, options), '0.000001');
assert.equal(number.format(0.999e-6, options), '9.99e-7');
});
it('auto notation with very large custom lower bound', function () {
assert.equal(number.format(1, { exponential: { lower: 1e-2 } }), '1');
assert.equal(number.format(1e-1, { exponential: { lower: 1e-2 } }), '0.1');
assert.equal(number.format(1e-2, { exponential: { lower: 1e-2} }), '0.01');
assert.equal(number.format(1e-3, { exponential: { lower: 1e-2 } }), '1e-3');
});
it('auto notation with very small custom lower bound', function () {
assert.equal(number.format(1e-18, { exponential: { lower: 1e-30 } }), '0.000000000000000001');
assert.equal(number.format(1e-19, { exponential: { lower: 1e-30 } }), '0.0000000000000000001');
assert.equal(number.format(1e-20, { exponential: { lower: 1e-30 } }), '0.00000000000000000001');
assert.equal(number.format(1e-21, { exponential: { lower: 1e-30 } }), '0.000000000000000000001');
assert.equal(number.format(1e-22, { exponential: { lower: 1e-30 } }), '0.0000000000000000000001');
assert.equal(number.format(1e-23, { exponential: { lower: 1e-30 } }), '0.00000000000000000000001');
assert.equal(number.format(1e-24, { exponential: { lower: 1e-30 } }), '0.000000000000000000000001');
});
it('auto notation with custom upper bound', function () {
var options = { exponential: { upper: 1e+9 } };
assert.equal(number.format(1e+9, options), '1e+9');
assert.equal(number.format(1e+9-1, options), '999999999');
});
it('auto notation with very large custom upper bound', function () {
assert.equal(number.format(1e+18, { exponential: { upper: 1e+30 } }), '1000000000000000000');
assert.equal(number.format(1e+19, { exponential: { upper: 1e+30 } }), '10000000000000000000');
assert.equal(number.format(1e+20, { exponential: { upper: 1e+30 } }), '100000000000000000000');
assert.equal(number.format(1e+21, { exponential: { upper: 1e+30 } }), '1000000000000000000000');
assert.equal(number.format(1e+22, { exponential: { upper: 1e+30 } }), '10000000000000000000000');
assert.equal(number.format(1e+23, { exponential: { upper: 1e+30 } }), '100000000000000000000000');
assert.equal(number.format(1e+24, { exponential: { upper: 1e+30 } }), '1000000000000000000000000');
});
it('auto notation with very small custom upper bound', function () {
assert.equal(number.format(1, { exponential: { upper: 1e2 } }), '1');
assert.equal(number.format(1e1, { exponential: { upper: 1e2 } }), '10');
assert.equal(number.format(1e2, { exponential: { upper: 1e2 } }), '1e+2');
assert.equal(number.format(1e3, { exponential: { upper: 1e2 } }), '1e+3');
});
it('auto notation with custom precision, lower, and upper bound', function () {
var options = {
precision: 4,
exponential: {
lower: 1e-6,
upper: 1e+9
}
};
assert.equal(number.format(0, options), '0');
assert.equal(number.format(1234567, options), '1235000');
assert.equal(number.format(1e+9, options), '1e+9');
assert.equal(number.format(1.1e+9, options), '1.1e+9');
assert.equal(number.format(1e+9-1, options), '1000000000');
assert.equal(number.format(1e-6, options), '0.000001');
assert.equal(number.format(0.999e-6, options), '9.99e-7');
assert.equal(number.format(123456789123, options), '1.235e+11');
});
it('should throw an error on unknown notation', function () {
assert.throws(function () {
number.format(123, {notation: 'non existing'})
});
});
it('should split a number into sign, coefficient, exponent', function () {
assert.deepEqual(number.splitNumber(0), {sign: '', coefficients: [0], exponent: 0});
assert.deepEqual(number.splitNumber(2.3), {sign: '', coefficients: [2, 3], exponent: 0});
var a = number.splitNumber(2.3);
assert.strictEqual(a.coefficients[0], 2);
assert.strictEqual(a.coefficients[1], 3);
assert.strictEqual(a.exponent, 0);
assert.deepEqual(number.splitNumber(-2.3), {sign: '-', coefficients: [2, 3], exponent: 0});
assert.deepEqual(number.splitNumber('02.3'), {sign: '', coefficients: [2, 3], exponent: 0});
assert.deepEqual(number.splitNumber(2300), {sign: '', coefficients: [2, 3], exponent: 3});
assert.deepEqual(number.splitNumber(0.00023), {sign: '', coefficients: [2, 3], exponent: -4});
assert.deepEqual(number.splitNumber('0.00023'),{sign: '', coefficients: [2, 3], exponent: -4});
assert.deepEqual(number.splitNumber('000.0002300'), {sign: '', coefficients: [2, 3], exponent: -4});
assert.deepEqual(number.splitNumber('002300'), {sign: '', coefficients: [2, 3], exponent: 3});
assert.deepEqual(number.splitNumber('2.3e3'), {sign: '', coefficients: [2, 3], exponent: 3});
assert.deepEqual(number.splitNumber('2.3e+3'), {sign: '', coefficients: [2, 3], exponent: 3});
assert.deepEqual(number.splitNumber('-2.3e3'), {sign: '-', coefficients: [2, 3], exponent: 3});
assert.deepEqual(number.splitNumber('23e3'), {sign: '', coefficients: [2, 3], exponent: 4});
assert.deepEqual(number.splitNumber('-23e3'), {sign: '-', coefficients: [2, 3], exponent: 4});
assert.deepEqual(number.splitNumber('2.3e-3'), {sign: '', coefficients: [2, 3], exponent: -3});
assert.deepEqual(number.splitNumber('23e-3'), {sign: '', coefficients: [2, 3], exponent: -2});
assert.deepEqual(number.splitNumber('-23e-3'), {sign: '-', coefficients: [2, 3], exponent: -2});
assert.deepEqual(number.splitNumber('99.99'), {sign: '', coefficients: [9,9,9,9], exponent: 1});
});
it('should round digits of a a split number', function () {
assert.deepEqual(number.roundDigits(number.splitNumber(123456), 3), number.splitNumber(123000));
assert.deepEqual(number.roundDigits(number.splitNumber(123456), 4), number.splitNumber(123500));
assert.deepEqual(number.roundDigits(number.splitNumber(0.00555), 2), number.splitNumber(0.0056));
assert.deepEqual(number.roundDigits(number.splitNumber(99.99), 2), number.splitNumber(100));
});
it('should format a number with toFixed', function () {
assert.strictEqual(number.toFixed(0), '0');
assert.strictEqual(number.toFixed(2300), '2300');
assert.strictEqual(number.toFixed(-2300), '-2300');
assert.strictEqual(number.toFixed(19.9), '20');
assert.strictEqual(number.toFixed(99.9), '100');
assert.strictEqual(number.toFixed(99.5), '100');
assert.strictEqual(number.toFixed(99.4), '99');
assert.strictEqual(number.toFixed(2.3), '2');
assert.strictEqual(number.toFixed(2.5), '3');
assert.strictEqual(number.toFixed(2.9), '3');
assert.strictEqual(number.toFixed(1.5), '2');
assert.strictEqual(number.toFixed(-1.5), '-2');
assert.strictEqual(number.toFixed(123.45), '123');
assert.strictEqual(number.toFixed(0.005), '0');
assert.strictEqual(number.toFixed(0.7), '1');
assert.strictEqual(number.toFixed(0.15, 1), '0.2');
assert.strictEqual(number.toFixed(123.4567, 1), '123.5');
assert.strictEqual(number.toFixed(-123.4567, 1), '-123.5');
assert.strictEqual(number.toFixed(0.23, 1), '0.2');
assert.strictEqual(number.toFixed(0.005, 5), '0.00500');
assert.strictEqual(number.toFixed(0.00567, 4), '0.0057');
assert.strictEqual(number.toFixed(0.00999, 2), '0.01');
assert.strictEqual(number.toFixed(0.00999, 3), '0.010');
assert.strictEqual(number.toFixed(-0.00999, 3), '-0.010');
assert.strictEqual(number.toFixed(NaN, 2), 'NaN');
assert.strictEqual(number.toFixed(Infinity, 2), 'Infinity');
assert.strictEqual(number.toFixed(-Infinity, 2), '-Infinity');
});
it('should format a number with toExponential', function () {
assert.strictEqual(number.toExponential(0), '0e+0');
assert.strictEqual(number.toExponential(0.15), '1.5e-1');
assert.strictEqual(number.toExponential(1), '1e+0');
assert.strictEqual(number.toExponential(-1), '-1e+0');
assert.strictEqual(number.toExponential(1000), '1e+3');
assert.strictEqual(number.toExponential(2300), '2.3e+3');
assert.strictEqual(number.toExponential(-2300), '-2.3e+3');
assert.strictEqual(number.toExponential(3.568), '3.568e+0');
assert.strictEqual(number.toExponential(0.00123), '1.23e-3');
assert.strictEqual(number.toExponential(-0.00123), '-1.23e-3');
assert.strictEqual(number.toExponential('20.3e2'), '2.03e+3');
assert.strictEqual(number.toExponential(0, 2), '0.0e+0');
assert.strictEqual(number.toExponential(0.15, 1), '2e-1');
assert.strictEqual(number.toExponential(1234, 2), '1.2e+3');
assert.strictEqual(number.toExponential(-1234, 2), '-1.2e+3');
assert.strictEqual(number.toExponential(1234, 6), '1.23400e+3');
assert.strictEqual(number.toExponential(9999, 2), '1.0e+4');
assert.strictEqual(number.toExponential(NaN, 2), 'NaN');
assert.strictEqual(number.toExponential(Infinity, 2), 'Infinity');
assert.strictEqual(number.toExponential(-Infinity, 2), '-Infinity');
});
it('should format a number with toPrecision', function () {
assert.strictEqual(number.toPrecision(0), '0');
assert.strictEqual(number.toPrecision(0.15), '0.15');
assert.strictEqual(number.toPrecision(2300), '2300');
assert.strictEqual(number.toPrecision(-2300), '-2300');
assert.strictEqual(number.toPrecision(0.00123), '0.00123');
assert.strictEqual(number.toPrecision(-0.00123), '-0.00123');
assert.strictEqual(number.toPrecision(1.2e-8), '1.2e-8');
assert.strictEqual(number.toPrecision(2300, 6), '2300.00');
assert.strictEqual(number.toPrecision(1234.5678, 6), '1234.57');
assert.strictEqual(number.toPrecision(1234.5678, 2), '1200');
assert.strictEqual(number.toPrecision(1234, 2), '1200');
assert.strictEqual(number.toPrecision(0.15, 1), '0.2');
assert.strictEqual(number.toPrecision(0.004, 3), '0.00400');
assert.strictEqual(number.toPrecision(0.00123456, 5), '0.0012346');
assert.strictEqual(number.toPrecision(999, 2), '1000');
assert.strictEqual(number.toPrecision(99900, 2), '100000');
assert.strictEqual(number.toPrecision(99999, 2), '100000');
assert.strictEqual(number.toPrecision(999e7, 2), '1.0e+10');
assert.strictEqual(number.toPrecision(0.00999, 2), '0.010');
assert.strictEqual(number.toPrecision(-0.00999, 2), '-0.010');
assert.strictEqual(number.toPrecision(NaN, 2), 'NaN');
assert.strictEqual(number.toPrecision(Infinity, 2), 'Infinity');
assert.strictEqual(number.toPrecision(-Infinity, 2), '-Infinity');
});
it('should should throw an error on invalid input', function () {
assert.throws(function () {number.splitNumber('2.3.4')}, /SyntaxError/);
assert.throws(function () {number.splitNumber('2.3ee')}, /SyntaxError/);
assert.throws(function () {number.splitNumber('2.3e4.3')}, /SyntaxError/);
assert.throws(function () {number.splitNumber('2.3a')}, /SyntaxError/);
assert.throws(function () {number.splitNumber('foo')}, /SyntaxError/);
assert.throws(function () {number.splitNumber(NaN)}, /SyntaxError/);
assert.throws(function () {number.splitNumber('NaN')}, /SyntaxError/);
assert.throws(function () {number.splitNumber(new Date())}, /SyntaxError/);
});
});
it('should format numbers with precision as second parameter', function() {
assert.equal(number.format(1/3), '0.3333333333333333');
assert.equal(number.format(1/3, 5), '0.33333');
assert.equal(number.format(1/3, 3), '0.333');
assert.equal(number.format(2/3, 3), '0.667');
});
it('should format numbers with a custom formatting function', function() {
function asCurrency (value) {
return '$' + value.toFixed(2);
}
assert.equal(number.format(12.4264, asCurrency), '$12.43');
assert.equal(number.format(0.1, asCurrency), '$0.10');
assert.equal(number.format(1.2e+6, asCurrency), '$1200000.00');
});
});
describe('nearlyEqual', function () {
it('should test whether two numbers are nearly equal', function () {
var epsilon = 1e-2;
assert.equal(number.nearlyEqual(1, 0.9, epsilon), false);
assert.equal(number.nearlyEqual(1, 0.95, epsilon), false);
assert.equal(number.nearlyEqual(1, 0.98, epsilon), false);
assert.equal(number.nearlyEqual(1, 0.991, epsilon), true);
assert.equal(number.nearlyEqual(1, 1.1, epsilon), false);
assert.equal(number.nearlyEqual(1, 1.05, epsilon), false);
assert.equal(number.nearlyEqual(1, 1.02, epsilon), false);
assert.equal(number.nearlyEqual(1, 1.01, epsilon), true);
assert.equal(number.nearlyEqual(1, 1, epsilon), true);
// smaller epsilon
var epsilon2 = 1e-4;
assert.equal(number.nearlyEqual(1, 0.99, epsilon2), false);
assert.equal(number.nearlyEqual(1, 0.999, epsilon2), false);
assert.equal(number.nearlyEqual(1, 0.9999, epsilon2), true);
// test one of these famous round-off errors
assert.equal((0.1+0.2) == 0.3, false);
assert.equal(number.nearlyEqual(0.1+0.2, 0.3, 1e-14), true);
});
it('should test whether a positive and negative number are nearly equal', function () {
var epsilon = 1e-3;
assert.equal(number.nearlyEqual( 1.2, 1.2, epsilon), true);
assert.equal(number.nearlyEqual( 1.2, -1.2, epsilon), false);
assert.equal(number.nearlyEqual(-1.2, 1.2, epsilon), false);
assert.equal(number.nearlyEqual(-1.2, -1.2, epsilon), true);
});
it('should test whether two large numbers are nearly equal', function () {
var epsilon = 1e-2;
assert.equal(number.nearlyEqual(1e200, 0.90e200, epsilon), false);
assert.equal(number.nearlyEqual(1e200, 0.95e200, epsilon), false);
assert.equal(number.nearlyEqual(1e200, 0.98e200, epsilon), false);
assert.equal(number.nearlyEqual(1e200, 0.99e200, epsilon), true);
});
it('should test whether two small numbers are nearly equal (always true)', function () {
var epsilon = 1e-2;
assert.equal(number.nearlyEqual(1e-200, 0.99e-200, epsilon), true);
assert.equal(number.nearlyEqual(1e-200, 10e-200, epsilon), true); // FIXME: why is this true?
});
it('should compare with zero', function () {
var epsilon = 1e-3;
assert.equal(number.nearlyEqual(0, 0, epsilon), true);
assert.equal(number.nearlyEqual(0, -0, epsilon), true);
assert.equal(number.nearlyEqual(0, 1.2, epsilon), false);
assert.equal(number.nearlyEqual(0, 1e30, epsilon), false);
assert.equal(number.nearlyEqual(0, 1e-30, epsilon), true); // FIXME: why is this true?
});
it('should compare with Infinity', function () {
var epsilon = 1e-3;
assert.equal(number.nearlyEqual(1.2, Infinity, epsilon), false);
assert.equal(number.nearlyEqual(Infinity, 1.2, epsilon), false);
assert.equal(number.nearlyEqual(Infinity, Infinity, epsilon), true);
assert.equal(number.nearlyEqual(Infinity, -Infinity, epsilon), false);
assert.equal(number.nearlyEqual(-Infinity, Infinity, epsilon), false);
assert.equal(number.nearlyEqual(-Infinity, -Infinity, epsilon), true);
});
it('should compare with NaN', function () {
var epsilon = 1e-3;
assert.equal(number.nearlyEqual(1.2, NaN, epsilon), false);
assert.equal(number.nearlyEqual(NaN, 1.2, epsilon), false);
assert.equal(number.nearlyEqual(NaN, NaN, epsilon), false);
});
it('should do exact comparison when epsilon is null or undefined', function () {
assert.equal(number.nearlyEqual(1.2, 1.2), true);
assert.equal(number.nearlyEqual(1.2, 1.2, null), true);
assert.equal(number.nearlyEqual(0.1 + 0.2, 0.3), false);
assert.equal(number.nearlyEqual(0.1 + 0.2, 0.3, null), false);
});
});
});

View File

@@ -0,0 +1,289 @@
// test object utils
var assert = require('assert'),
approx = require('../../tools/approx'),
object = require('../../lib/utils/object');
describe ('object', function () {
describe('clone', function() {
it('should clone undefined', function () {
assert.strictEqual(object.clone(undefined), undefined);
});
it('should clone null', function () {
assert.strictEqual(object.clone(null), null);
});
it('should clone booleans', function () {
assert.strictEqual(object.clone(true), true);
assert.strictEqual(object.clone(false), false);
assert.ok(object.clone(new Boolean(true)) instanceof Boolean);
assert.equal(object.clone(new Boolean(true)), true);
assert.equal(object.clone(new Boolean(false)), false);
});
it('should clone numbers', function () {
assert.strictEqual(object.clone(2.3), 2.3);
assert.ok(object.clone(new Number(2.3)) instanceof Number);
assert.equal(object.clone(new Number(2.3)), 2.3);
});
it('should clone strings', function () {
assert.strictEqual(object.clone('hello'), 'hello');
assert.ok(object.clone(new String('hello')) instanceof String);
assert.equal(object.clone(new String('hello')), 'hello');
});
it('should (deep) clone objects', function () {
var obj = {a: {b: 'c', d: new Date(2014,0,1)}};
var clone = object.clone(obj);
assert.deepEqual(obj, clone);
// check whether the clone remains unchanged when changing the original object
obj.a.b = 'cc';
assert.equal(clone.a.b, 'c');
obj.a.d.setMonth(2);
assert.equal(clone.a.d.valueOf(), new Date(2014,0,1).valueOf());
});
it('should clone dates', function () {
var d1 = new Date(2014,1,1);
var d2 = object.clone(d1);
assert.equal(d1.valueOf(), d2.valueOf());
d1.setMonth(2);
assert.notEqual(d1, d2);
});
it('should (deep) clone arrays', function () {
var d = new Date(2014,0,1);
var arr = [1, 2, d, {a: 3}]
var clone = object.clone(arr);
assert.deepEqual(arr, clone);
assert.notStrictEqual(arr, clone);
assert.notStrictEqual(arr[2], clone[2]);
assert.notStrictEqual(arr[3], clone[3]);
// check whether the clone remains unchanged when changing the original object
arr[2] = null;
arr[3].a = 1;
d.setMonth(2);
assert.equal(clone[2].valueOf(), new Date(2014,0,1).valueOf());
assert.equal(clone[3].a, 3);
});
it('should throw an error in case of an unsupported type', function () {
assert.throws(function () {object.clone(/a regexp/)}, /Cannot clone/);
});
});
describe('extend', function() {
it ('should extend an object with all properties of an other object', function () {
var e = {};
var o1 = {a: 2, b: 3};
var o2 = {a: 4, b: null, c: undefined, d: 5, e: e};
var o3 = object.extend(o1, o2);
assert.strictEqual(o1, o3);
assert.strictEqual(o1.e, o3.e);
assert.deepEqual(o3, {a: 4, b: null, c: undefined, d: 5, e: e});
assert.deepEqual(o2, {a: 4, b: null, c: undefined, d: 5, e: e}); // should be unchanged
});
it('should ignore inherited properties when extending an object', function () {
Object.prototype.foo = 'bar';
var o1 = {a: 2, b: 3};
var o2 = object.extend({}, o1);
assert.equal(o2['foo'], 'bar');
assert.equal(o2.hasOwnProperty('foo'), false);
delete Object.prototype.foo;
});
});
describe('deepExtend', function() {
it ('should deep extend an object with all properties of an other object', function () {
var e = {f: {g: 3}};
var o1 = {a: 2, b: 3};
var o2 = {a: 4, b: null, c: undefined, d: 5, e: e};
var o3 = object.deepExtend(o1, o2);
assert.strictEqual(o1, o3);
assert.notStrictEqual(o3.e, o2.e);
assert.deepEqual(o3, {a: 4, b: null, c: undefined, d: 5, e: {f: {g: 3}}});
assert.deepEqual(o2, {a: 4, b: null, c: undefined, d: 5, e: {f: {g: 3}}}); // should be unchanged
e.f.g = 4;
assert.deepEqual(o3, {a: 4, b: null, c: undefined, d: 5, e: {f: {g: 3}}}); // should be unchanged
assert.deepEqual(o2, {a: 4, b: null, c: undefined, d: 5, e: {f: {g: 4}}}); // should be changed
});
it ('should throw an error when deep extending an array (is not yet supported)', function () {
assert.throws(function () {object.deepExtend({}, [])}, /Arrays are not supported by deepExtend/);
assert.throws(function () {object.deepExtend({}, {a: []})}, /Arrays are not supported by deepExtend/);
assert.throws(function () {object.deepExtend({}, {a: {b: []}})}, /Arrays are not supported by deepExtend/);
});
it('should ignore inherited properties when deep extending an object', function () {
Object.prototype.foo = 'bar';
var o1 = {a: 2, b: 3};
var o2 = object.deepExtend({}, o1);
assert.equal(o2['foo'], 'bar');
assert.equal(o2.hasOwnProperty('foo'), false);
delete Object.prototype.foo;
});
});
describe('deepEqual', function() {
it('should deep compare two objects', function () {
assert.equal(object.deepEqual({}, {}), true);
assert.equal(object.deepEqual({a: 2, b: 3}, {a: 2, b: 3}), true);
assert.equal(object.deepEqual({a: 2, b: 3}, {a: 2, b: 4}), false);
assert.equal(object.deepEqual({a: 2, b: 3}, {a: 2}), false);
assert.equal(object.deepEqual({a: 2}, {a: 2, b: 3}), false);
assert.equal(object.deepEqual({a: 2, b: 3}, {a: 2, b: {}}), false);
assert.equal(object.deepEqual({a: 2, b: {}}, {a: 2, b: {}}), true);
assert.equal(object.deepEqual({a: 2, b: {c: 4}}, {a: 2, b: {c: 4}}), true);
assert.equal(object.deepEqual({a: 2, b: {c: 4}}, {a: 2, b: {c : 5}}), false);
assert.equal(object.deepEqual({a: 2, b: {c: 4}}, {a: 2, b: {}}), false);
assert.equal(object.deepEqual({a: 2, b: {}}, {a: 2, b: {c: 4}}), false);
});
it('should deep compare two arrays', function () {
assert.equal(object.deepEqual([], []), true);
assert.equal(object.deepEqual([1, 2], [1, 2]), true);
assert.equal(object.deepEqual([1, 2], [1, 2, 3]), false);
assert.equal(object.deepEqual([1, 0, 3], [1, 2, 3]), false);
assert.equal(object.deepEqual([1, 2, [3, 4]], [1, 2, [3, 4]]), true);
assert.equal(object.deepEqual([1, 2, [3]], [1, 2, [3, 4]]), false);
assert.equal(object.deepEqual([1, 2, [3, 4]], [1, 2, [3]]), false);
assert.equal(object.deepEqual([1, 2, null], [1, 2, [3]]), false);
assert.equal(object.deepEqual([1, 2, [3]], [1, 2, null]), false);
assert.equal(object.deepEqual([1, 2, 3], [1, 2, [3]]), false);
assert.equal(object.deepEqual([1, 2, [3]], [1, 2, 3]), false);
});
it('should deep compare mixed objects an arrays', function () {
assert.equal(object.deepEqual({}, []), false);
assert.equal(object.deepEqual({a: {}}, {a: []}), false);
assert.equal(object.deepEqual({a: [1,2,3]}, {a:[1,2,3]}), true);
assert.equal(object.deepEqual({a: [1,2,{}]}, {a:[1,2,{}]}), true);
assert.equal(object.deepEqual({a: [1,2,{b: 4}]}, {a:[1,2,{b: 4}]}), true);
assert.equal(object.deepEqual({a: [1,2,{b: 4}]}, {a:[1,2,{b: 5}]}), false);
assert.equal(object.deepEqual({a: [1,2,{b: 4}]}, {a:[1,2,{}]}), false);
assert.equal(object.deepEqual([1, 2, {}], [1, 2, {}]), true);
assert.equal(object.deepEqual([1, 2, {a: 3}], [1, 2, {a : 3}]), true);
assert.equal(object.deepEqual([1, 2, {a: 3}], [1, 2, {a : 4}]), false);
assert.equal(object.deepEqual([1, 2, {a: 3}], [1, 2, 3]), false);
assert.equal(object.deepEqual([1, 2, 3], [1, 2, {a: 3}]), false);
assert.equal(object.deepEqual([1, 2, {a: [3, 4]}], [1, 2, {a: [3, 4]}]), true);
assert.equal(object.deepEqual([1, 2, {a: [3, 4]}], [1, 2, {a: [3, 4, 5]}]), false);
});
it('should not ignore inherited properties during comparison', function () {
Object.prototype.foo = 'bar';
assert.equal(object.deepEqual({}, {}), true);
assert.equal(object.deepEqual({foo: 'bar'}, {}), true);
delete Object.prototype.foo;
});
});
describe('canDefineProperty', function() {
it('should test whether defineProperty is available', function () {
assert.equal(object.canDefineProperty(), true);
});
});
describe('lazy', function() {
it('should get a lazy property', function () {
var obj = {};
var count = 0;
object.lazy(obj, 'x', function () {
count++;
return 2;
});
var x = obj.x;
assert.equal(x, 2);
assert.equal(count, 1);
var x2 = obj.x;
assert.equal(x2, 2);
assert.equal(count, 1);
});
it('should set a lazy property', function () {
var obj = {};
object.lazy(obj, 'x', function () {
return 2;
});
obj.x = 3;
var x = obj.x;
assert.equal(x, 3);
});
});
describe('traverse', function() {
it('should traverse an existing path into an object', function () {
var a = {};
var b = {a: a};
var c = {b: b};
assert.strictEqual(object.traverse(c), c);
assert.strictEqual(object.traverse(c, ''), c);
assert.strictEqual(object.traverse(c, 'b'), b);
assert.strictEqual(object.traverse(c, 'b.a'), a);
});
it('should append missing piece of a path', function () {
var a = {};
var b = {a: a};
var c = {b: b};
assert.strictEqual(object.traverse(c), c);
assert.strictEqual(object.traverse(c, ''), c);
assert.strictEqual(object.traverse(c, 'b'), b);
assert.strictEqual(object.traverse(c, 'b.a'), a);
assert.strictEqual(object.traverse(c, 'b.d'), b.d);
assert.strictEqual(object.traverse(c, 'b.e.f'), b.e.f);
});
});
describe ('isFactory', function () {
it('should test whether an object is a factory', function () {
assert.equal(object.isFactory({}), false);
assert.equal(object.isFactory({foo: true}), false);
assert.equal(object.isFactory({name: 'foo'}), false);
assert.equal(object.isFactory({name: 'foo', factory: 'bar'}), false);
assert.equal(object.isFactory({name: 2, factory: function () {}}), true);
assert.equal(object.isFactory({factory: function () {}}), true);
assert.equal(object.isFactory({name: 'foo', factory: function () {}}), true);
assert.equal(object.isFactory({name: 'foo', factory: function () {}, foo: 'bar'}), true);
});
})
});

View File

@@ -0,0 +1,126 @@
// test string utils
var assert = require('assert');
var approx = require('../../tools/approx');
var BigNumber = require('decimal.js');
var math = require('../../index');
var string = require('../../lib/utils/string');
describe ('string', function () {
it('isString', function() {
assert.equal(string.isString('hi'), true);
assert.equal(string.isString(String('hi')), true);
assert.equal(string.isString(23), false);
assert.equal(string.isString(true), false);
assert.equal(string.isString(new Date()), false);
// we don't support non primitive Strings anymore
assert.equal(string.isString(new String('hi')), false);
});
it('endsWith', function() {
assert.equal(string.endsWith('hello', 'hello'), true);
assert.equal(string.endsWith('hello', 'lo'), true);
assert.equal(string.endsWith('hello', ''), true);
assert.equal(string.endsWith('hello!', 'lo'), false);
assert.equal(string.endsWith('hello', 'LO'), false);
assert.equal(string.endsWith('hello', 'hellohello'), false);
});
describe('format', function () {
it ('should format null', function () {
assert.equal(string.format(null), 'null');
});
it ('should format undefined', function () {
assert.equal(string.format(undefined), 'undefined');
});
it ('should format a number', function () {
assert.equal(string.format(2.3), '2.3');
});
it ('should format a bignumber', function () {
var B = BigNumber.config({
precision: 20
});
assert.equal(string.format(new B(1).div(3)), '0.33333333333333333333');
});
it ('should format a fraction without options', function () {
assert.equal(string.format(math.fraction(1,3)), '1/3');
assert.equal(string.format(math.fraction(2,6)), '1/3');
assert.equal(string.format(math.fraction(-0.125)), '-1/8');
});
it ('should format a fraction with option fraction=\'ratio\'', function () {
assert.equal(string.format(math.fraction(1,3), {fraction: 'ratio'}), '1/3');
assert.equal(string.format(math.fraction(2,6), {fraction: 'ratio'}), '1/3');
});
it ('should format a fraction with option fraction=\'decimal\'', function () {
assert.equal(string.format(math.fraction(1,3), {fraction: 'decimal'}), '0.(3)');
assert.equal(string.format(math.fraction(2,6), {fraction: 'decimal'}), '0.(3)');
});
it ('should format a number with configuration', function () {
assert.equal(string.format(1.23456, 3), '1.23');
assert.equal(string.format(1.23456, {precision: 3}), '1.23');
});
it ('should format an array', function () {
assert.equal(string.format([1,2,3]), '[1, 2, 3]');
assert.equal(string.format([[1,2],[3,4]]), '[[1, 2], [3, 4]]');
});
it ('should format a string', function () {
assert.equal(string.format('string'), '"string"');
});
it ('should format an object', function () {
var obj = {
a: 1.1111,
b: math.complex(2.2222,3)
};
assert.equal(string.format(obj), '{"a": 1.1111, "b": 2.2222 + 3i}');
assert.equal(string.format(obj, 3), '{"a": 1.11, "b": 2.22 + 3i}');
});
it ('should format an object with its own format function', function () {
var obj = {
format: function (options) {
var str = 'obj';
if (options !== undefined) {
str += ' ' + JSON.stringify(options);
}
return str;
}
};
assert.equal(string.format(obj), 'obj');
assert.equal(string.format(obj, 4), 'obj 4');
assert.equal(string.format(obj, {precision: 4}), 'obj {"precision":4}');
});
it ('should format a function', function () {
assert.equal(string.format(function (a, b) {return a + b}), 'function');
var f = function (a, b) {return a + b};
f.syntax = 'f(x, y)';
assert.equal(string.format(f), 'f(x, y)');
});
it ('should format unknown objects by converting them to string', function () {
assert.equal(string.format({}), '{}');
});
it ('should format unknown primitives by converting them to string', function () {
assert.equal(string.format(true), 'true');
});
});
});

View File

@@ -0,0 +1,57 @@
// test types utils
var assert = require('assert'),
approx = require('../../tools/approx'),
types = require('../../lib/utils/types');
describe ('types', function () {
it('should return the type of null', function () {
assert.equal(types.type(null), 'null');
});
it('should return the type of undefined', function () {
assert.equal(types.type(undefined), 'undefined');
assert.equal(types.type(), 'undefined');
});
it('should return the type of a boolean', function () {
assert.equal(types.type(false), 'boolean');
assert.equal(types.type(true), 'boolean');
});
it('should return the type of a number', function () {
assert.equal(types.type(2.3), 'number');
assert.equal(types.type(Number(2.3)), 'number');
assert.equal(types.type(new Number(2.3)), 'number');
assert.equal(types.type(NaN), 'number');
});
it('should return the type of a string', function () {
assert.equal(types.type('bla'), 'string');
assert.equal(types.type(new String('bla')), 'string');
});
it('should return the type of an object', function () {
assert.equal(types.type({}), 'Object');
assert.equal(types.type(new Object()), 'Object');
});
it('should return the type of an array', function () {
assert.equal(types.type([]), 'Array');
assert.equal(types.type(new Array()), 'Array');
});
it('should return the type of a function', function () {
assert.equal(types.type(function () {}), 'Function');
});
it('should return the type of a date', function () {
assert.equal(types.type(new Date()), 'Date');
});
it('should return the type of a regexp', function () {
assert.equal(types.type(/regexp/), 'RegExp');
});
});