/** * Class: JSL.test * UnitTest library. This is a plugin and not the part of the main codebase. It can be called like this.. * JSL.test("Test Name").AssertType("The Real Value", "The Correct Value"); * Example: * JSL.test_starup(); * JSL.test("Find if 1 is true").assertTrue(1); * JSL.test("Find if 0 is false").assertFalse(0); * JSL.test("Find if 1 is 0").assertEquals(1,0); * JSL.test_run(); */ (function() { function _test_init(test_description, test_id, show_test_details) { this.test_description = test_description; this._div_id = test_id; this.show_test_details = show_test_details; return this; } _test_init.prototype = { "_current_test_id" : "", /// The ID of the LI element which is the most recent. "show_test_details": true, /// taken from JSL._test_show_details "_div_id" : "", // Will be taken from JSL._test_div_id variable //User Defined functions "onTest":false, "onSuccess":false, "onFail":false, /** * Test will succeed if the given value(1st argument) is true. * Example: JSL.test("Is 1==1 returning true?").assertTrue(1 == 1) */ "assertTrue" : function() { var test = this._startTest(arguments); this._saveTest(test, test.real_value ); }, /** * Test will succeed if the given value(1st argument) is true. * Example: JSL.test("1==1 should return true").assert(1 == 1) */ "assert" : function() { var test = this._startTest(arguments); this._saveTest(test, test.real_value ); }, /** * Test will succeed if the given value(1st argument) is false * Example: JSL("1 != 1 should return false").test.assertFalse(1 != 1) */ "assertFalse" : function() { var test = this._startTest(arguments); this._saveTest(test, test.real_value == false); }, /** * Test will succeed if the given values are equal. The values could be strings, numbers, chars - basciacally anything that could be compaired by == . Arrays are not supported. * Arguments : should_be_value - The first argument is the correct value - the ideal value * real_value - The second argument is the real value. Ideally, the 'real_value' should be equal to the 'should_be_value' * Example: JSL.test.assertEquals(1,1) */ "assertEquals" : function() { var test = this._startTest(arguments); this._saveTest(test, test.real_value == test.should_be_value); }, /** * Test will succeed if the given values are not equal. The values could be strings, numbers, arrays, list - basciacally anything that could be compaired by != * Arguments : $arg_1 - The first value * $arg_2 - The second value * Example: JSL.test.assertNotEquals(1,2) */ "assertNotEquals" : function() { var test = this._startTest(arguments); this._saveTest(test, test.real_value != test.should_be_value); }, /** * Test will succeed if the two given arrays are equal. The values could be arrays or lists * Arguments : should_be_value - The first argument is the correct value - the ideal value * real_value - The second argument is the real value. Ideally, the 'real_value' should be equal to the 'should_be_value' * Example: * JSL.test.assertEquals([23,200,3],[23,200,3]); * JSL.test.assertEquals({"car":"Porshe", "bike":"Yamaha", "plane":"Lear"},{"bike":"Yamaha", "car":"Porshe", "plane":"Lear"}); */ "assertArrayEquals" : function() { var test = this._startTest(arguments); this._saveTest(test, this._arrayIsSame(test.real_value, test.should_be_value)); }, /** * Test will succeed if the two given arrays are NOT equal. The values could be arrays or lists * Example: * JSL.test.assertArrayNotEquals([23,200,3],[23,100,13]) */ "assertArrayNotEquals" : function() { var test = this._startTest(arguments); this._saveTest(test, !this._arrayIsSame(test.real_value, test.should_be_value)); }, /// Checks to see if the given value is null - the test will succeed if its a null "assertNull" : function() { var test = this._startTest(arguments); this._saveTest(test, (test.real_value == false && typeof(test.real_value) == "object")); }, /// Checks to see if the given value is NOT null - the test will succeed if it is NOT null "assertNotNull" : function() { var test = this._startTest(arguments); this._saveTest(test, test.real_value != null); }, /// Checks to see if the given value is defined or not - the test will succeed if it is undefined "assertUndefined" : function() { var test = this._startTest(arguments); this._saveTest(test, typeof(test.real_value) == "undefined"); }, /// Checks to see if the given value is NOT undefined - the test will succeed if it is defined "assertNotUndefined" : function() { var test = this._startTest(arguments); this._saveTest(test, typeof(test.real_value) != "undefined"); }, /** * Saves the test to an global array so that it could be ran later - when the runTests() is called. */ "_saveTest": function(test, result) { if(window.JSL["_test_run_immediatly"]) this._decide(test, result); else window.JSL["_test_all_tests"].push({"test":test, "result":result}); }, /** * Decides wether the current test is a success or a failure based on the second argument. * This function will call _onSuccess or _onFail function based on the the result. */ "_decide" : function(test, success) { if(success) this._onSuccess(test); else this._onFail(test); return success; }, /// Test Initalizer. Gets the arguments, increments the counter and calls _onTest "_startTest": function(args) { this.test = this._getArgs(args); this.test['index'] = ++JSL._test_count; if(window.JSL["_test_run_immediatly"]) this._onTest(this.test); return this.test; }, /// Happens before a test is ran. If onTest function exist, the test details will be send to that. "_onTest": function(test, total_tests) { if(this.onTest) this.onTest.call(test); this._current_test_id = this._div_id + "_test_" + JSL._test_count; // Show the number of the current test. var index; if(total_tests) index = test.index + "/" + total_tests + ") "; else index = test.index + ") "; this._show(index + test.message + " : ") }, /** * Happens when a test succeeds - if the onSuccess function is defined by the user, * this function will call it with the details of the current test */ "_onSuccess": function(test) { if(this.onSuccess) this.onSuccess.call(test); this._show("SUCCESS
", true); }, /** * Happens when a test fail - if the onFail function is defined by the user, * this function will call it with the details of the current test */ "_onFail": function(test) { if(this.onFail) this.onFail.call(test); this._show("FAILED
", true); }, /// Shows the result of the current test by appending it to the main list. "_show": function(details, test_result) { if(this.show_test_details) { if(test_result) { document.getElementById(this._current_test_id).innerHTML += details; } else { var li = document.createElement("li"); li.setAttribute("id", this._current_test_id); li.appendChild(document.createTextNode(details)); document.getElementById(this._div_id + "_testing").appendChild(li); } } }, /** * This will create and return an associative array with the details of the current test. * The array will have the following values - 'message', 'real_value' and 'should_be_value'. * Later, the 'status' will be added to indicate wether the test was a success or not. */ "_getArgs": function(args) { var description = this.test_description; var real_value; var should_be_value; if(args.length == 1) { real_value = args[0]; } else if(args.length == 2) { should_be_value = args[0]; real_value = args[1]; } return {"message":description, "real_value": real_value, "should_be_value":should_be_value}; }, /** * This function checks to see if the 2 given arrays are the same - works * with both list and associative arrays. Returns true if both are the same * and false if they are not. */ "_arrayIsSame" : function (arr1, arr2) { var length_check = true; if(arr1.length) length_check = (arr1.length == arr2.length); //Applicable for lists/numerical arrays only if(typeof(arr1) == typeof(arr2) && typeof(arr2) == "object" && length_check) { //Some basic sanity checks var element_count_1 = 0; for(var index in arr1) { if(arr1[index] !== arr2[index]) return false; //Make sure each element is the same element_count_1++; } if(!arr1.length) { //Implementing a length check for associative arrays. var element_count_2 = 0; for(var index in arr2) {element_count_2++;} if(element_count_1 !== element_count_2) return false; } return true; } else { return false; } } } //Add it to the JSL array. window.JSL['test'] = function(test_description) { return new _test_init(test_description, JSL._test_div_id, JSL._test_show_details); } /** * This function must be manually called before starting the test. It will create a div with id "jsl_test_details" * - this is where all the test details will be shown. * Arguments: * run_immediately - If this is true, all the tests will be executed and shown on call. If not, it will wait until JSL.test_run() call is made. * Example: JSL.test_startup() */ window.JSL['test_startup'] = function(run_immediately) { //Global(wrt this library) stuff window.JSL["_test_count"] = 0; /// The number of tests run window.JSL["_test_div_id"] = "jsl_test_details"; /// The ID of the DIV that shows the details of the test. window.JSL["_test_show_details"] = true; /// If this is true, the details of the test will be shown in the window. window.JSL["_test_all_tests"] = []; /// This holds all the test in an array if run_immediately is off /// If this is true, the result of the test is shown immediatly - if not, it will wait until test_run() function is called. window.JSL["_test_run_immediatly"] = (run_immediately) ? true : false; //Could be undefined. if(!(document.getElementById(this._test_div_id))) { if(this._test_show_details) { var body = document.getElementsByTagName("body")[0]; var div = document.createElement("div"); div.setAttribute("id", this._test_div_id); div.setAttribute("style", "position:absolute;top:0px;left:0px;color:#000;font-family:Verdana,Arial,Helvetica,sans-serif;font-size:11px;background-color:#d6e4ff;"); var ul = document.createElement("ul"); ul.setAttribute("id", this._test_div_id + "_testing"); div.appendChild(ul); body.appendChild(div); } else { document.getElementById(this._test_div_id + "_testing").innerHTML = ""; } } } /// Run all the cached tests. window.JSL["test_run"] = function() { if(!window.JSL["_test_all_tests"] || window.JSL["_test_run_immediatly"]) return; var total_tests = window.JSL["_test_all_tests"].length; var test_object = JSL.test(""); //We need an empty test object. // _jsl_test_all_tests is a global variable - so using different objects is not an issue. JSL.array(window.JSL["_test_all_tests"]).each(function(ele,i, arr, self) { self._onTest(ele.test, total_tests); self._decide(ele.test, ele.result); }, test_object); } })();