lb-ratio
Version:
Provides a Fraction, Rational, and Ratio object for javascript.
1,162 lines (1,069 loc) • 38.5 kB
JavaScript
/**
* @project Ratio.js
* @purpose Testcases for new Ratio.js
* @author Larry Battle , <http://bateru.com/news/>
* @license MIT and GPL 3.0
*/
var exports = {};
// contains all tests.
var runTests = function() {
module("Required Static Ratio Functions");
test("test Ratio.isNumeric()", function() {
var func = Ratio.isNumeric;
equal(func(null), false);
equal(func(true), false);
equal(func(false), false);
equal(func("NaN"), false);
equal(func(NaN), false);
equal(func([]), false);
equal(func({}), false);
equal(func({}), false);
equal(func(undefined), false);
equal(func(+(12)), true);
equal(func(1), true);
equal(func(0x3), true);
equal(func(1.1e10), true);
});
test("test Ratio.getNumeratorWithSign()", function() {
var func = Ratio.getNumeratorWithSign;
equal(func(1, 1), 1);
equal(func(-1, -1), 1);
equal(func(-1, 1), -1);
equal(func(1, -1), -1);
equal(func(Infinity, 1), Infinity);
equal(func(-Infinity, -1), Infinity);
equal(func(-Infinity, 1), -Infinity);
equal(func(1, -Infinity), -1);
});
test("test Ratio.gcd()", function() {
var func = Ratio.gcd;
equal(func(0, 2), 2);
equal(func(-1, 2), 1);
equal(func(1, 1), 1);
equal(func(1, 2), 1);
equal(func(3, 6), 3);
equal(func(-3, 6), 3);
equal(func(4, 8), 4);
equal(func(10, 20), 10);
equal(func(41329375731, 82658751462), 41329375731);
});
test("test Ratio.gcd() with bad input", function() {
var func = Ratio.gcd;
equal(isNaN(func({}, 2)), true);
equal(func(null, true), 1);
equal(func(1, true), 1);
equal(func(1), 1);
equal(func(1, Infinity), Infinity);
});
test("test Ratio.gcd() edge condition", function() {
var func = Ratio.gcd;
equal(func(10, 0), 10);
equal(func(0, 10), 10);
equal(func(200, 15), 5);
equal(func(200, 55), 5);
equal(func(200, 50), 50);
equal(func(2, 50), 2);
equal(func(2, 5), 1);
});
test("test Ratio.getValueIfDefined()", function() {
var func = Ratio.getValueIfDefined,
a;
equal(func(), a);
equal(func(0), 0);
equal(func(1), 1);
equal(func(1, a), 1);
equal(func(1, null), 1);
deepEqual(func([]), []);
deepEqual(func(1, []), []);
});
module("Ratio Global Constants");
test("test for version number", function() {
equal(typeof Ratio.VERSION, "string", "Ratio.VERISON is detected.");
equal(typeof Ratio.MIN_VALUE, "number", "Ratio.MIN_VALUE is detected.");
equal(typeof Ratio.MAX_VALUE, "number", "Ratio.MAX_VALUE is detected.");
equal(typeof Ratio.MAX_PRECISION, "number", "Ratio.MAX_PRECISION is detected.");
});
module("Instantiation");
test("test new Ratio creation", function() {
var func = function(a, b) {
return new Ratio(a, b).toLocaleString();
};
equal(new Ratio(), "0");
equal(func(), "0");
equal(func(3), "3");
equal(func(1, 3), "1/3");
equal(func(3, 1), "3");
equal(func(10, 10), "1");
equal(func(400, 5), "80");
equal(func(3, 2), "1 1/2");
equal(func(1, 3), "1/3");
equal(func(-4, 3), "-1 1/3");
equal(func(4, -3), "-1 1/3");
equal(func(-4, -3), "1 1/3");
});
test("test new Ratio creation with scientific notated numbers.", function() {
var func = function(a, b) {
return new Ratio(a, b).toLocaleString();
};
equal(func(3e30), "3e+30");
equal(func(-3e30, 1e25), "-300000");
equal(func(1e21, 3e30), "1e+21/3e+30");
equal(func(1e-23), "1e-23");
equal(func(-1e30, 1e-23), "-1e+53");
equal(func(1e-33, 1e50), "1e-33/1e+50");
});
test("test Ratio creation with invalid input", function() {
var func = function(a, b) {
return new Ratio(a, b).toLocaleString();
};
equal((func()), "0");
equal((func(null, null)), "NaN");
equal(func(null, 2), "0");
equal(func({}, 2), "NaN");
equal(func([], 1), "0");
equal(func(true, 1), "1");
equal(func(function() {}, 2), "NaN");
equal(func(false, 2), "0");
equal(func(false, true), "0");
equal(func("ten", "ten"), "NaN");
equal(func(/ten/, 1), "NaN");
equal(func(Infinity), Infinity);
equal(func(Infinity, 1), Infinity);
equal(func(Infinity, "0"), Infinity);
equal(func(-Infinity, "0"), -Infinity);
equal((func(Infinity, Infinity)), "NaN");
equal((func(NaN, 0)), "NaN");
});
module("Cloning");
test("test Ratio.prototype.clone with no arguments", function() {
var a = new Ratio(1, 3),
b = a.clone(),
c = new Ratio(20, 9);
equal(a.equals(b), true);
equal(b.equals(a), true);
equal(b.equals(c), false);
equal(c.equals(a), false);
});
test("test Ratio.prototype.clone with arguments", function() {
var func = Ratio,
a = new Ratio(11, 12, true);
deepEqual(a.clone(), a);
deepEqual(a.clone(7), func(7, 12, true));
deepEqual(a.clone(null, 7), func(11, 7, true));
deepEqual(a.clone(null, null), func(11, 12, true));
deepEqual(a.clone(null, null, false), func(11, 12, false));
deepEqual(a.clone(1, null, false), func(1, 12, false));
deepEqual(a.clone(1, 2, false), func(1, 2, false));
deepEqual(a.clone(1, 2, false), func(1, 2, false));
});
test("test Ratio.prototype.clone with change to internal attributes", function() {
var a = new Ratio(1, 3),
b = a.clone();
equal(a.equals(b), true);
});
module("toString output");
test("test Ratio.prototype.toString() for valid input: proper fractions", function() {
var func = function(a, b) {
return new Ratio(a, b).toString();
};
equal(func(1, 2), "1/2");
equal(func(-1, 2), "-1/2");
equal(func(1e23, 2e25), "1e+23/2e+25");
equal(func(-1e23, 2e25), "-1e+23/2e+25");
});
test("test Ratio.prototype.toString() for valid input: whole numbers", function() {
var func = function(a, b) {
return new Ratio(a, b).toString();
};
equal(func(), "0/1");
equal(func(2, 1), "2/1");
equal(func(10, 5), "10/5");
equal(func(1, Infinity), "1/Infinity");
equal(func(0, 3), "0/3");
equal(func(3, 3), "3/3");
equal(func(12, 3), "12/3");
equal(func(1, 1e300), "1/1e+300");
equal(func(0, 3e40), "0/3e+40");
equal(func(3e40, 1e40), "3e+40/1e+40");
equal(func(-1, Infinity), "-1/Infinity");
equal(func(-0, 3), "0/3");
equal(func(-3, 3), "-3/3");
equal(func(-12, 3), "-12/3");
equal(func(-1, 1e300), "-1/1e+300");
equal(func(-0, 3e40), "0/3e+40");
});
test("test Ratio.prototype.toString() for valid input: Scientific notated numbers", function() {
var func = function(a, b) {
return new Ratio(a, b).toString();
};
equal(func(9e99, 9e24), "9e+99/9e+24");
equal(func(9e-99, 9e24), "9e-99/9e+24");
equal(func(9e99, -9e24), "-9e+99/9e+24");
equal(func(-9e-99, 9e24), "-9e-99/9e+24");
});
test("test Ratio.prototype.toString() for valid input: mixed numbers", function() {
var func = function(a, b) {
return new Ratio(a, b).toString();
};
equal(func(3, 2), "3/2");
equal(func(50, 4), "50/4");
equal(func(3e+23, 29), "3e+23/29");
equal(func(-3, 2), "-3/2");
equal(func(-50, 4), "-50/4");
equal(func(-3e+23, 29), "-3e+23/29");
});
test("test Ratio.prototype.toString() for invalid input: decimal in fraction", function() {
var func = function(a, b) {
return new Ratio(a, b).toString();
};
equal(func(0.11, 0.3), "0.11/0.3");
});
test("test Ratio.prototype.toString() for invalid input: Infinity", function() {
var func = function(a, b) {
return new Ratio(a, b).toString();
};
equal(func(1, 0), "1/0");
equal(func(Infinity, 1), "Infinity/1");
equal(func(Infinity, 0), "Infinity/0");
});
test("test Ratio.prototype.toString() for invalid input: NaN", function() {
var func = function(a, b) {
return new Ratio(a, b).toString();
};
equal(func(Infinity, -Infinity), "-Infinity/Infinity");
equal(func(32, "i12"), "32/NaN");
equal(func("-i", 12), "NaN/12");
equal(func("palm", "fist"), "NaN/NaN");
equal(func("19", "fist"), "19/NaN");
equal(func("palm", "o"), "NaN/NaN");
equal(func("-i", "i"), "NaN/NaN");
});
module("toLocaleString output");
test("test Ratio.prototype.toLocaleString() for valid input: proper fraction", function() {
var func = function(a, b) {
return new Ratio(a, b).toLocaleString();
};
equal(func(1, 2), "1/2");
equal(func(-1, 2), "-1/2");
equal(func(1e23, 2e25), "1e+23/2e+25");
equal(func(-1e23, 2e25), "-1e+23/2e+25");
});
test("test Ratio.prototype.toLocaleString() for valid input: whole numbers", function() {
var func = function(a, b) {
return new Ratio(a, b).toLocaleString();
};
equal(func(1, Infinity), "0");
equal(func(0, 3), "0");
equal(func(0, 3e40), "0");
equal(func(3, 3), "1");
equal(func(3e40, 1e40), "3");
equal(func(12, 3), "4");
equal(func(-1, Infinity), "0");
equal(func(-0, 3), "0");
equal(func(-0, 3e40), "0");
equal(func(-3, 3), "-1");
equal(func(-3e40, 1e40), "-3");
equal(func(-12, 3), "-4");
});
test("test Ratio.prototype.toLocaleString() for valid input: mixed numbers", function() {
var func = function(a, b) {
return new Ratio(a, b).toLocaleString();
};
equal(func(3, 2), "1 1/2");
equal(func(50, 4), "12 2/4");
equal(func(-3, 2), "-1 1/2");
equal(func(-50, 4), "-12 2/4");
});
test("test Ratio.prototype.toLocaleString() for valid input: Scientific notated numbers", function() {
var func = function(a, b) {
return new Ratio(a, b).toLocaleString();
};
equal(func(1e2, 2e4), "100/20000");
equal(func(-1e100, 4), "-2.5e+99");
equal(func(-1e22, 21), "1e+22/21");
equal(func(-3e+23, 29), "-3e+23/29");
equal(func(-7e30, 3e25), "-233333 1e+30/3e+25");
equal(func(3e+23, 29), "3e+23/29");
equal(func(7e30, 3e25), "233333 1e+30/3e+25");
});
test("test Ratio.prototype.toLocaleString() for invalid input: decimal in fraction", function() {
var func = function(a, b) {
return new Ratio(a, b).toLocaleString();
};
equal(func(0.11, 0.3), "0.11/0.3");
});
test("test Ratio.prototype.toLocaleString() for invalid input: Infinity", function() {
var func = function(a, b) {
return new Ratio(a, b).toLocaleString();
};
equal(func(1, 0), "Infinity");
equal(func(Infinity, 1), "Infinity");
equal(func(Infinity, 0), "Infinity");
});
test("test Ratio.prototype.toLocaleString() for invalid input: NaN", function() {
var func = function(a, b) {
return new Ratio(a, b).toLocaleString();
};
equal(func(Infinity, -Infinity), "NaN");
equal(func(32, "i12"), "NaN");
equal(func("-i", 12), "NaN");
equal(func("palm", "fist"), "NaN");
equal(func("19", "fist"), "NaN");
equal(func("palm", "o"), "NaN");
equal(func("-i", "i"), "NaN");
});
module("Alternative Output Formats");
test("test Ratio.prototype.toArray()", function() {
var func = function(a, b) {
return new Ratio(a, b).toArray();
};
deepEqual(func(1, 2), [1, 2]);
deepEqual(func(-1, -2), [1, 2]);
deepEqual(func(0.34, 2e3), [0.34, 2e3]);
deepEqual(func(10.23e100, -23.04), [-10.23e100, 23.04]);
});
test("test Ratio.prototype.valueOf()", function() {
equal(new Ratio(2, 2), 1);
equal(new Ratio(1, 2), 1 / 2);
equal(new Ratio(1, 4), 1 / 4);
equal(new Ratio(1, 3), 1 / 3);
equal(new Ratio(1e100, 4), 1e100 / 4);
equal(new Ratio(1e-4, 3), 1e-4 / 3);
});
module("Ratio Instance Property Change");
test("test divider sign change", function() {
var a = new Ratio(1, 2);
equal(a.toLocaleString(), "1/2");
a.divSign = ":";
equal(a.toLocaleString(), "1:2");
});
test("test changing numerator", function() {
var a,
b;
a = new Ratio(1, 2);
b = new Ratio(3, 2);
a.numerator(3);
equal(a.equals(b), true);
});
test("test changing denominator", function() {
var a,
b;
a = new Ratio(1, 2);
b = new Ratio(1, 3);
a.denominator(3);
equal(a.equals(b), true);
});
module("Guess Input Type");
test("test Ratio.guessType() for output as `Ratio`", function() {
var func = Ratio.guessType;
equal(func(new Ratio()), "Ratio");
equal(func(new Ratio(1, 2)), "Ratio");
equal(func(new Ratio(2e3)), "Ratio");
});
test("test Ratio.guessType() for output as `number`", function() {
var func = Ratio.guessType;
equal(func(23), "number");
equal(func(+23), "number");
equal(func(-23), "number");
});
test("test Ratio.guessType() for output as `decimal`", function() {
var func = Ratio.guessType;
equal(func(1.1), "decimal");
equal(func("-1.1"), "decimal");
equal(func("+1.1"), "decimal");
});
test("test Ratio.guessType() for output as `e`", function() {
var func = Ratio.guessType;
equal(func(1.1e30), "e");
equal(func(-1.1e-23), "e");
equal(func(+1.1e+23), "e");
});
test("test Ratio.guessType() for output as `mixed`", function() {
var func = Ratio.guessType;
equal(func("10 1/2"), "mixed");
equal(func("-10 -1/2"), "mixed");
equal(func("+10 -1/+2"), "mixed");
});
test("test Ratio.guessType() for output as `fraction`", function() {
var func = Ratio.guessType;
equal(func("+1/2"), "fraction");
equal(func("-1e12/+2e103"), "fraction");
equal(func("+2.3e32/23.3"), "fraction");
equal(func("-Infinity/1"), "fraction");
equal(func("- Infinity/1"), "fraction");
equal(func("+ Infinity/1"), "fraction");
equal(func("-23/Infinity"), "fraction");
});
test("test Ratio.guessType() for output as `NaN`", function() {
var func = Ratio.guessType;
equal(func(), "NaN");
equal(func(function() {}), "NaN");
equal(func("E"), "NaN");
equal(func(NaN), "NaN");
equal(func("10e-"), "NaN");
equal(func(Math), "NaN");
equal(func("o"), "NaN");
equal(func("1.1.1"), "NaN");
equal(func("1e1e"), "NaN");
equal(func("10 a/b"), "NaN");
equal(func("a/b"), "NaN");
});
module("Parse Value to Array");
test("test Ratio.parseToArray() with invalid input", function() {
var func = Ratio.parseToArray;
deepEqual(func({}), [NaN, 1]);
deepEqual(func("apple"), [NaN, 1]);
deepEqual(func("apples"), [NaN, 1]);
deepEqual(func(NaN), [NaN, 1]);
deepEqual(func("happy"), [NaN, 1]);
deepEqual(func("1.1e1.1"), [NaN, 1]);
});
test("test Ratio.parseToArray() with whole numbers", function() {
var func = Ratio.parseToArray;
deepEqual(func(null), [0, 1]);
deepEqual(func([]), [0, 1]);
deepEqual(func("0"), [0, 1]);
deepEqual(func("15"), [15, 1]);
deepEqual(func(1), [1, 1]);
deepEqual(func(0), [0, 1]);
deepEqual(func(123), [123, 1]);
deepEqual(func(423), [423, 1]);
deepEqual(func("3"), [3, 1]);
deepEqual(func(" 3 "), [3, 1]);
deepEqual(func(-1), [-1, 1]);
});
test("test Ratio.parseToArray() with Ratio objects", function() {
var func = Ratio.parseToArray;
deepEqual(func((new Ratio(4, 3))), [4, 3]);
deepEqual(func((new Ratio(-4, 3))), [-4, 3]);
deepEqual(func((new Ratio(4, -3))), [-4, 3]);
deepEqual(func((new Ratio(-4, -3))), [4, 3]);
});
test("test Ratio.parseToArray() with decimals", function() {
var func = Ratio.parseToArray;
deepEqual(func(Number(1.12)), [112, 100]);
deepEqual(func(0.771), [771, 1000]);
deepEqual(func("0.112"), [112, 1000]);
deepEqual(func("23.0"), [23, 1]);
deepEqual(func("23.123"), [23123, 1000]);
deepEqual(func(1.2e6), [1200000, 1]);
deepEqual(func(0.231), [231, 1000]);
deepEqual(func(-123.484), [-123484, 1000]);
});
test("test Ratio.parseToArray() with scientific notated numbers", function() {
var func = Ratio.parseToArray;
deepEqual(func(1e3), [1000, 1]);
deepEqual(func("1e-5"), [1, 100000]);
deepEqual(func("-1e-5"), [-1, 100000]);
deepEqual(func(1.01e3), [1010, 1]);
deepEqual(func(1e101), [1e101, 1]);
deepEqual(func(1.01e-3), [101, 100000]);
deepEqual(func(1.01e-30), [101, 1e32]);
deepEqual(func(-1.01e-30), [-101, 1e32]);
deepEqual(func("10"), [10, 1]);
deepEqual(func("2e1"), [20, 1]);
deepEqual(func("-2.0004e2"), [-20004, 100]);
deepEqual(func("-2.0004e5"), [-200040, 1]);
deepEqual(func("-2.0004e-2"), [-20004, 1000000]);
deepEqual(func("-2.0004e-5"), [-20004, 1000000000]);
deepEqual(func("-1.34e-30"), [-134, 1e+32]);
});
test("test Ratio.parseToArray() with fractions", function() {
var func = Ratio.parseToArray;
deepEqual(func(" 3/1"), [3, 1]);
deepEqual(func("3/ 2"), [3, 2]);
deepEqual(func("1 / 3"), [1, 3]);
deepEqual(func("-4/ 3"), [-4, 3]);
deepEqual(func(" 4 /-3"), [-4, 3]);
deepEqual(func("-4 /-3"), [4, 3]);
});
test("test Ratio.parseToArray() with mixed numbers for sign correction", function() {
var func = Ratio.parseToArray;
deepEqual(func("0 1/2"), [1, 2]);
deepEqual(func("-0 1/2"), [1, 2]);
deepEqual(func("0 -1/2"), [-1, 2]);
deepEqual(func("-0 -1/2"), [-1, 2]);
deepEqual(func("1 1/2"), [3, 2]);
deepEqual(func("-1 1/2"), [-3, 2]);
deepEqual(func("1 -1/2"), [-3, 2], "Invalid expression, assume negative.");
deepEqual(func("-1 -1/2"), [-3, 2], "Invalid expression, assume negative.");
});
module("Parsing Value to Ratio");
test("test Ratio.parse() with single arguments.", function() {
var func = function(a) {
return Ratio.parse(a).toLocaleString();
};
equal(func("-0.125"), "-125/1000");
equal(func(new Ratio(3)), "3");
equal(func(3), "3");
equal(func("-3.0e-1"), "-3/10");
equal(func(3.0), "3");
equal(func(new Ratio(-1, 3)), "-1/3");
});
test("test Ratio.parse() with double arguments.", function() {
var func = function(a, b) {
return Ratio.parse(a, b).toLocaleString();
};
equal(func(0.125, 0.5), "1250/5000");
equal(func(0.125, "1/2"), "250/1000");
equal(func(3, new Ratio(2)), "1 1/2");
equal(func(3, new Ratio(1)), "3");
equal(func(new Ratio(1), 3), "1/3");
equal(func(new Ratio(-4), new Ratio(3)), "-1 1/3");
equal(func(new Ratio(4, 5).toString(), new Ratio(-3, 2).toString()), "-8/15");
});
module("Random Ratio");
test("test Ratio.random()", function() {
var fn = function() {
return Ratio.random().valueOf();
};
ok(fn() <= 1, "Must be less than or equal to 1");
ok(0 <= fn(), "Must be greater than or equal to 0");
});
module("Clean Scientific Notated Values");
test("test Ratio.getCleanENotation()", function() {
var func = Ratio.getCleanENotation;
equal(func(null), "0");
equal(func("bear"), "0");
equal(func("9.999999e+22"), "9.999999e+22");
equal(func("9.999999999999999e+22"), "1e+23");
equal(func("1.1000000000000003e-30"), "1.1e-30");
});
test("test Ratio.prototype.cleanFormat()", function() {
var func = function(a, b) {
return new Ratio(a, b).cleanFormat().toString();
};
equal(func(1.2, 1.5), Ratio.parse(1.2, 1.5).toString());
equal(func(1.2e30, 1.5), Ratio.parse(1.2e30, 1.5).toString());
equal(func(1.00000000000000009e30, 1.5), Ratio.parse(1.0e30, 1.5).toString());
equal(func(-1.2e-10, 1.5e15), new Ratio(-1.2e-10, 1.5e15).toString());
});
module("Comparison Functions");
test("test Ratio.prototype.equals() against self using `.valueOf()`, `.toString()`, and `.toLocaleString()`", function() {
var func = function(a, b) {
var x = new Ratio(a, b),
errMsg = "";
errMsg = x.equals(x.valueOf()) ? "" : "x.equals( x.valueOf() )";
errMsg = x.equals(x.toString()) ? "" : "x.equals( x.toString() )";
errMsg = x.equals(x.toLocaleString()) ? "" : "x.equals( x.toLocaleString() )";
if (errMsg) {
errMsg = "x = " + x.toString() + ", problem with " + errMsg;
}
return errMsg;
},
check = function(a, b) {
equal(func(a, b), "", "checking for a = " + a + " and b = " + b);
};
check(0);
check(1);
check(109);
check(40, 3);
check(3, 40);
check(40, 40);
check(1, 7);
check(7, 6);
});
test("test Ratio.prototype.equals() against self using `.valueOf()`, `.toString()`, and `.toLocaleString()`", function() {
var func = function(a, b) {
var x = Ratio.parse(a, b),
errMsg = "";
errMsg = x.equals(x.valueOf()) ? "" : "x.equals( x.valueOf() )";
errMsg = x.equals(x.toString()) ? "" : "x.equals( x.toString() )";
errMsg = x.equals(x.toLocaleString()) ? "" : "x.equals( x.toLocaleString() )";
if (errMsg) {
errMsg = "x = " + x.toString() + ", problem with " + errMsg;
}
return errMsg;
},
check = function(a, b) {
equal(func(a, b), "", "checking for a = " + a + " and b = " + b);
};
check("0/4");
check("1/1");
check("109");
check("40/3");
check("3/40");
check("40/40");
check("1/7");
check("7/6");
});
test("test Ratio.prototype.equals() for false comparisons", function() {
var func = function(a, b, c) {
return Ratio.parse(a, b).equals(c);
};
equal(func(1, 2, 2), false);
equal(func(1, 2, "1/22"), false);
equal(func(1, 5, "5"), false);
});
test("test Ratio.prototype.deepEquals()", function() {
var func = function(a, b, c) {
return Ratio.parse(a, b).deepEquals(c);
},
x = new Ratio(1, 2);
equal(func(1, 2, x), true);
equal(func(1e40, 2, Ratio.parse(1e40, 2)), true);
equal(func(4, 4, Ratio.parse(4, 4)), true);
equal(func(1e20, 1, Ratio.parse(1e40, 2)), false);
equal(func(2, 2, Ratio.parse(4, 4)), false);
});
test("test equivalance using Ratio.prototype.equals and ==", function() {
var a = new Ratio(),
b = new Ratio(),
c = new Ratio(3, 4),
d = new Ratio(3, 4),
e = new Ratio(12, 12),
f = new Ratio(12, 12);
equal(a.equals(a), true, "identity check using equals");
equal(b.equals(b), true, "identity check using equals");
equal(c.equals(c), true, "identity check using equals");
equal(d.equals(d), true, "identity check using equals");
equal(a.equals(b), true, "identity check using equals");
equal(+a === +b, true, "identity check using ==");
equal(c.equals(d), true, "identity check using equals");
equal(+c === +d, true, "identity check using ==");
equal(a.equals(c), false, "identity check");
equal(+a === +c, false, "identity check");
equal(e.equals(c), false, "identity check");
equal(f.equals(c), false, "identity check");
});
test("test comparison, Ratio.prototype.valueOf() is called", function() {
var a = new Ratio(1, 2),
b = new Ratio(1, 4),
c = new Ratio(150, 3);
ok(a > b);
ok(c >= b);
ok(c >= a);
ok(b < a);
ok(b <= c);
});
test("test Ratio.prototype.isNaN()", function() {
var fn = function(a, b) {
return Ratio.parse(a, b).isNaN();
}
equal(fn(1, 0), true);
equal(fn(Infinity, 0), true);
equal(fn(Infinity, -Infinity), true);
equal(fn("apples", "oranges"), true);
equal(fn(1, 2), false);
equal(fn(1e49, 22.34), false);
equal(fn(1, -2), false);
equal(fn(-1e-50), false);
});
module("Math Operations Requiring Extra Terms");
test("test addition with +, Ratio.prototype.valueOf() is called", function() {
var func = function(a, b, c, d) {
return (new Ratio(a, b) + new Ratio(c, d));
},
x;
equal(func(), 0);
equal(func(0, x, 0, x), 0);
equal(func(-1, x, 1, x), 0);
equal(func(1, x, 2, x), 3);
equal(func(40, x, 2, x), 42);
equal(func(20001, 40002, 400, 800), 1);
equal(func(1, 2, 1, 2), 1);
equal(func(1, x, 1, 2), 1.5);
equal(func(1, x, 1, 3), 4 / 3);
equal(func(1, 3, -1, 3), 0);
});
test("test Ratio.prototype.add()", function() {
var func = function(a, b, c, d) {
return new Ratio(a, b).add(new Ratio(c, d)).toLocaleString();
},
x;
equal(func(), "0");
equal(func(0, x, 0, x), "0");
equal(func(0, x, 1, 2), "1/2");
equal(func(1, 2, 0, x), "1/2");
equal(func(2, 4, 4, 8), "1");
equal(func(2, 4, 4, 8), "1");
equal(func(1, 2, 1, 2), "1");
equal(func(1, x, 1, x), "2");
equal(func(1, x, 2, x), "3");
equal(func(40, x, 2, x), "42");
equal(func(1, x, 1, 2), "1 1/2");
equal(func(2, 5, 3, 4), "1 3/20");
equal(func(1, 3, 3, 9), "6/9");
equal(func(4, 9, 3, 9), "7/9");
});
test("test addition with -, Ratio.prototype.valueOf() is called", function() {
var func = function(a, b, c, d) {
return (new Ratio(a, b) - new Ratio(c, d));
};
equal(func(), 0);
equal(func(1, 4, 1, 4), 0);
equal(func(1, 5, 1, 2), "-0.3");
equal(func(1, 20, 1, 100), "0.04");
});
test("test Ratio.prototype.subtract()", function() {
var func = function(a, b, c, d) {
return new Ratio(a, b).subtract(new Ratio(c, d)).toLocaleString();
},
x;
equal(func(), "0");
equal(func(0, x, 0, 0), "NaN", "0 - 0/0 is NaN");
equal(func(0, x, 0, x), "0");
equal(func(0, 0, 1, 2), "NaN");
equal(func(0, 0, 0, 0), "NaN");
equal(func(1, 2, 0, 0), "NaN");
equal(func(1, 2, 0, x), "1/2");
equal(func(0, x, 1, 2), "-1/2");
equal(func(1, 2, 0, x), "1/2");
equal(func(1, 3, 3, 9), "0");
equal(func(2, 4, 4, 8), "0");
equal(func(1, x, 1, 2), "1/2");
equal(func(4, x, 1, x), "3");
equal(func(4, 9, 3, 9), "1/9");
equal(func(10, 2, 9, 19), "4 20/38");
equal(func(1, x, 3, 2), "-1/2");
equal(func(1, x, 4, x), "-3");
equal(func(2, 5, 3, 4), "-7/20");
equal(func(1, 9, 4, 9), "-3/9");
});
test("test Ratio.prototype.multiply()", function() {
var func = function(a, b, c, d) {
return (new Ratio(a, b)).multiply(c, d).toLocaleString();
};
equal(func(1, 1, 1, 1), "1");
equal(func(1, 1, 2, 1), "2");
equal(func(-100, 1, 432, -1), "43200");
equal(func(2, 3, 4, 9), "8/27");
equal(func(12, 34, 2, -54), "-24/" + (34 * 54));
equal(func(12, 34, 2, -54), "-24/" + (34 * 54));
equal(func(-213, -423, -123, -123), (213 * 123) + "/" + (123 * 423));
equal(func(-213, -423, 0, 0), "NaN");
});
test("test Ratio.prototype.divide()", function() {
var func = function(a, b, c, d) {
return (new Ratio(a, b)).divide(c, d).toLocaleString();
};
equal(func(0, 1, 1, 10), "0");
equal(func(1, 1, 1, 1), "1");
equal(func(10, 3, 100, 30), "1");
equal(func(1, 4, 1, 20), "5");
equal(func(-10, 23, 13, -39), "1 91/299");
equal(func(-12, -34, -45, -67), (12 * 67) + "/" + (45 * 34));
});
test("test Ratio.prototype.descale", function() {
var func = function(a, b, c) {
return (new Ratio(a, b)).descale(c).toLocaleString();
};
equal(func(25, 100, 5), "5/20");
equal(func(5, 100, 5), "1/20");
equal(func(5, 100, 5.0), "1/20");
notEqual(func(5, 100, 5.1), "1/20");
});
test("test Ratio.prototype.scale()", function() {
var func = function(a, b, c) {
return (new Ratio(a, b)).scale(c).toLocaleString();
};
equal(func(2, 3, 5), "10/15");
equal(func(2, 3, 3e-10), "6e-10/9e-10");
equal(func(1, 2, 5), "5/10");
equal(func(1, 2, 2.5), "2.5/5");
});
module("Math Operations Performed on Self");
test("test Ratio.prototype.abs()", function() {
var func = function(a, b) {
return (new Ratio(a, b)).abs().toLocaleString();
};
equal(func(1, 2), "1/2");
equal(func(-1, 2), "1/2");
equal(func(-1, -2), "1/2");
equal(func(1, 2), "1/2");
});
test("test Ratio.prototype.mod()", function() {
var func = function(a, b) {
return (new Ratio(a, b)).mod().toLocaleString();
};
equal(func(5, 0), "NaN");
equal(func(5, 1), "0");
equal(func(5, 2), "1");
equal(func(5, 20), "5");
equal(func(5e2, 21), "17");
});
test("test Ratio.prototype.negate()", function() {
var func = function(a, b) {
return (new Ratio(a, b)).negate().toLocaleString();
};
equal(func(1, 2), "-1/2");
equal(func(-1, 2), "1/2");
equal(func(1, -2), "1/2");
equal(func(-1e-10, 2e22), "1e-10/2e+22");
});
test("test Ratio.prototype.ceil()", function() {
var func = function(a, b) {
return (new Ratio(a, b)).ceil().toString();
};
equal(func(1, 2), "1/1");
equal(func(-1, 2), "0/1");
equal(func(1, -2), "0/1");
equal(func(-1e-10, 2e22), "0/1");
});
test("test Ratio.prototype.floor()", function() {
var func = function(a, b) {
return (new Ratio(a, b)).floor().toString();
};
equal(func(1, 2), "0/1");
equal(func(-1, 2), "-1/1");
equal(func(1, -2), "-1/1");
equal(func(-1e-10, 2e22), "-1/1");
});
test("test Ratio.prototype.reciprocal()", function() {
equal(new Ratio(1, 2).reciprocal().toString(), "2/1");
});
module("Finding the repeating decimals");
test("test Ratio.getRepeatProps() with invalid input", function() {
var func = Ratio.getRepeatProps;
deepEqual(func(""), []);
deepEqual(func([]), []);
deepEqual(func({}), []);
deepEqual(func(Math.PI), []);
deepEqual(func(null), []);
deepEqual(func(true), []);
deepEqual(func(Infinity), []);
deepEqual(func(NaN), []);
deepEqual(func(1 / 5), []);
deepEqual(func(1 / 100), []);
deepEqual(func("1.2.3"), []);
deepEqual(func("1.333333"), []);
});
test("test Ratio.getRepeatProps() with decimal numbers as string", function() {
var func = Ratio.getRepeatProps;
deepEqual(func("1.1111111111"), ["1", "", "1"]);
deepEqual(func("1234.11111111111"), ["1234", "", "1"]);
deepEqual(func("1.12312311111111"), ["1", "123123", "1"]);
deepEqual(func("12.12121212121212"), ["12", "", "12"]);
deepEqual(func("1234.1111212121212"), ["1234", "111", "12"]);
deepEqual(func("2.123412341234"), ["2", "", "1234"]);
deepEqual(func("3534.3344512341234"), ["3534", "33445", "1234"]);
});
test("test Ratio.getRepeatProps() with computed decimal numbers", function() {
var func = Ratio.getRepeatProps;
deepEqual(func(1 / 333), ["0", "", "003"]);
deepEqual(func(7 / 13), ["0", "5384", "615384"]);
deepEqual(func(1 / 111), ["0", "", "009"]);
deepEqual(func(11 / 111), ["0", "", "099"]);
deepEqual(func(100 / 11), ["9", "", "09"]);
deepEqual(func(100 / 13), ["7", "692", "307692"]);
deepEqual(func(1 / 3), ["0", "", "3"]);
deepEqual(func(4 / 3), ["1", "", "3"]);
});
module("Ratio Reduction Functions");
test("test Ratio.simplify()", function() {
var func = Ratio.simplify;
deepEqual(func(0, 200), [0, 1]);
deepEqual(func(1, 2), [1, 2]);
deepEqual(func(4, 8), [1, 2]);
deepEqual(func(100, 200), [1, 2]);
deepEqual(func(-42, 42), [-1, 1]);
deepEqual(func(134, -3), [-134, 3]);
});
test("test Ratio.prototype.simplify()", function() {
var func = function(a, b) {
return Ratio.parse(a, b).simplify().toString();
};
equal(func(), "NaN/NaN");
equal(func(0), "0/1");
equal(func(0, 200), "0/1");
equal(func(1), "1/1");
equal(func(1, 3), "1/3");
equal(func(3, 9), "1/3");
equal(func(1 / 100), "1/100");
equal(func(7 / 3), "7/3");
equal(func(1 / 111), "1/111");
equal(func(1 / 333), "1/333");
});
module("Use Cases");
test("test user case 1", function() {
var a = new Ratio(1, 2);
equal(a.toString(), "1/2");
a = a.add(3);
equal(a.toString(), "7/2");
a = a.subtract(2);
equal(a.toString(), "3/2");
a = a.divide("3/2");
equal(a.toLocaleString(), "1");
equal(a.multiply(12).simplify().toLocaleString(), 12);
equal(a.toLocaleString(), "1");
});
test("test user case 2: Calculate PI", function() {
var a = Ratio(16).multiply(Ratio(Math.atan(Ratio(1) / Ratio(5)))),
b = Ratio(4).multiply(Ratio(Math.atan(Ratio(1) / Ratio(239)))),
computedPI = a.subtract(b);
equal(Math.PI <= computedPI, true, "Math.PI(" + Math.PI + ") <= computedPI(" + computedPI + ")");
});
// test("test user case 3: 2x2 Matrix of Ratios ", function () {
// });
// test("test user case 4: ?", function () {
// });
// test("test user case 5: ?", function () {
// });
module("Proper");
test("test Ratio.prototype.isProper()", function() {
var func = function(a, b) {
return (new Ratio(a, b)).isProper();
};
equal(func(1, 2), true);
equal(func(1e2, 2e2), true);
equal(func(10, 2), false);
equal(func(1e5, 2e2), false);
});
test("test Ratio.prototype.makeProper()", function() {
var func = function(a, b) {
return Ratio.parse(a, b).makeProper().toString();
};
equal(func(1, 2), "1/2");
equal(func(7, 5), "2/5");
equal(func(100, 200), "100/200");
equal(func(10, 2), "0/2");
equal(func(4.2), "2/10");
equal(func(-1, 2), "-1/2");
equal(func(-7, 5), "-2/5");
equal(func(-100, 200), "-100/200");
equal(func(-10, 2), "0/2");
equal(func(1e34, 200), "0/200");
equal(func(-1e34, 200), "0/200");
});
module("Find Prime Factors");
test("test Ratio.getPrimeFactors()", function() {
var func = Ratio.getPrimeFactors;
deepEqual(func(Infinity), []);
deepEqual(func({}), []);
deepEqual(func(null), []);
deepEqual(func(-1), []);
deepEqual(func(0), []);
deepEqual(func(1), []);
deepEqual(func(2), [2]);
deepEqual(func(6), [2, 3]);
deepEqual(func(9), [3, 3]);
deepEqual(func("729"), [3, 3, 3, 3, 3, 3]);
deepEqual(func(3333333791), [2347, 1420253]);
deepEqual(func(123456789), [3, 3, 3607, 3803]);
deepEqual(func(9876543210), [2, 3, 3, 5, 17, 17, 379721]);
deepEqual(func("103103103"), [3, 103, 333667]);
});
module("Find x");
test("test Ratio.prototype.findX() with invalid input", function() {
var func = function(a, b, str) {
return (new Ratio(a, b)).findX(str);
};
equal(func(1, 2, "10"), null);
equal(func(1, 2, "10/10"), null);
equal(func(1, 2, "Infinity"), null);
equal(func(1, 2, "Infinity/1e40"), null);
equal(func(1, 2, "x10"), null);
equal(func(1, 2, "x/1/2"), null);
equal(func(1, 2, "I like turtles"), null);
});
test("test Ratio.prototype.findX() with valid input", function() {
var func = function(a, b, str) {
return (new Ratio(a, b)).findX(str).simplify().toString();
};
equal(func(1, 2, "x/10"), "5/1");
equal(func(1, 2, "x/1"), "1/2");
equal(func(5, -2, "x/24"), "-60/1");
equal(func(3, 7, "10/x"), "70/3");
equal(func(11, -9, "10/x"), "-90/11");
equal(func(1, -201, "10/x"), "-2010/1");
equal(func(1, 4, "-1e+8/x"), "-400000000/1");
equal(func(1, 4, "Infinity / x"), "NaN");
equal(func(1, -4, "Infinity / -x"), "NaN");
});
module("Quantify Approximation");
test("test Ratio.prototype.toQuantityOf() with invalid input", function() {
var func = function(a, b, base) {
return Ratio.parse(a, b).toQuantityOf(base).toString();
};
equal(func(1, 3, {}), "NaN/3");
equal(func(1, 3, "ten"), "NaN/3");
equal(Ratio.parse(1, 3).toQuantityOf().toString(), "NaN/3");
});
test("test Ratio.prototype.toQuantityOf() with single arguments", function() {
var func = function(a, b, base) {
return Ratio.parse(a, b).toQuantityOf(base).toString();
};
equal(func(1, 2, 2), "1/2");
equal(func(1, 2, 3), "2/3");
equal(func(5, 10, 2), "1/2");
equal(func(5, 10, 7), "4/7");
equal(func(27, 100, 3), "1/3");
equal(func(77, 100, 3), "2/3");
equal(func(99, 100, 9), "9/9");
equal(func(1, 100, 1e6), "10000/1000000");
equal(func(97, -100, 3), "-3/3");
equal(func(-27, 100, 3), "-1/3");
});
test("Ratio.prototype.toQuantityOf() with multiple arguments", function() {
var func = function(a, b, units) {
var x = Ratio.parse(a, b);
return x.toQuantityOf.apply(x, units).toString();
};
equal(func(3, 8, [2, 3, 4]), "1/3");
equal(func(1, 3, [2, 4, 8]), "3/8");
equal(func(1, 2, [1, 2, 3, 4]), "1/2");
});
module("Common.js Support");
test("test Nodes.js( NPM ) support", function() {
ok(exports.Ratio === Ratio, "The Ratio object is the export object.");
ok(exports.Ratio.VERSION, "Ratio was added to exports.");
});
module("Empty Argument Calls");
test("test Ratio static methods for errors when functions with required arguments aren't supplied when called.", function() {
var fn;
for (var fnName in Ratio) {
fn = Ratio[fnName];
if (typeof fn !== "function" || fn.length === 0) {
continue;
}
try {
equal(true, true, "Ratio." + fnName + "() returns " + String(fn()));
} catch (e) {
equal(true, false, "Ratio." + fnName + "() throw an error. Error = " + e.toString());
}
}
});
test("test Ratio.prototype methods for errors when functions with required arguments aren't supplied when called.", function() {
var a = new Ratio();
for (var fnName in a) {
if (typeof a[fnName] !== "function" || a[fnName].length === 0) {
continue;
}
try {
equal(true, true, "Ratio.prototype." + fnName + "() returns " + String(a[fnName]()));
} catch (e) {
equal(true, false, "Ratio.prototype." + fnName + "() throw an error. Error = " + e.toString());
}
}
});
module("Non-destructive Method Calls");
test("test that non-destructive methods don't modify passed objects", function() {
var makeStatement = function(a, b, c) {
return a.toString() + " + " + b.toString() + " = " + c.toString();
};
var avoidThese = {
numerator: 1,
denominator: 1
};
var a = new Ratio(5, 4),
b = new Ratio(1, 2),
c = new Ratio(3, 4),
str = makeStatement(a, b, c);
for (var fnName in Ratio.prototype) {
if (avoidThese[fnName] || typeof a[fnName] !== "function" || a[fnName].length === 0 || a[fnName] === Ratio) {
continue;
}
a = new Ratio(5, 4);
b = new Ratio(1, 2);
c = new Ratio(3, 4);
a[fnName](b, c);
equal(str, makeStatement(a, b, c), "Ratio.prototype." + fnName + " is non-destructive.");
}
});
};
var reRunTests = function() {
QUnit.reset(); // should clear the DOM
QUnit.init(); // resets the qunit test environment
QUnit.start(); // allows for the new test to be captured.
runTests();
};