/** * @fileoverview * jsUnitCore.js contains the implementation of the core JsUnit functionality: assertions, JsUnitTestSuites, and JsUnit.Failure. * An HTML page is considered to be a JsUnit Test Page if it "includes" jsUnitCore.js, i.e. the following line is present: * * <script type="text/javascript" src="/path/to/jsUnitCore.js"></script> * * @author Edward Hieatt, edward@jsunit.net, http://www.jsunit.net * @author Alexander Kuntashov, kuntashov@gmail.com, http://kuntashov.ru * @author Go Namhyeon, gnh1201@gmail.com, https://catswords.re.kr/go/home */ var JsUnit = {}; /** * The JsUnit version * @version */ JsUnit.VERSION = 2.2; var JSUNIT_VERSION = JsUnit.VERSION; /** * For convenience, a variable that equals "undefined" */ var JSUNIT_UNDEFINED_VALUE; /** * Whether or not the current test page has been (completely) loaded yet */ var isTestPageLoaded = false; /** * Predicate used for testing JavaScript == (i.e. equality excluding type) */ JsUnit.DOUBLE_EQUALITY_PREDICATE = function(var1, var2) { return var1 == var2; }; /** * Predicate used for testing JavaScript === (i.e. equality including type) */ JsUnit.TRIPLE_EQUALITY_PREDICATE = function(var1, var2) { return var1 === var2; }; /** * Predicate used for testing whether two obects' toStrings are equal */ JsUnit.TO_STRING_EQUALITY_PREDICATE = function(var1, var2) { return var1.toString() === var2.toString(); }; /** * Hash of predicates for testing equality by primitive type */ JsUnit.PRIMITIVE_EQUALITY_PREDICATES = { 'String': JsUnit.DOUBLE_EQUALITY_PREDICATE, 'Number': JsUnit.DOUBLE_EQUALITY_PREDICATE, 'Boolean': JsUnit.DOUBLE_EQUALITY_PREDICATE, 'Date': JsUnit.TRIPLE_EQUALITY_PREDICATE, 'RegExp': JsUnit.TO_STRING_EQUALITY_PREDICATE, 'Function': JsUnit.TO_STRING_EQUALITY_PREDICATE } /** * Hack for NS62 bug * @private */ JsUnit._fixTop = function() { var tempTop = top; if (!tempTop) { tempTop = window; while (tempTop.parent) { tempTop = tempTop.parent; if (tempTop.top && tempTop.top.jsUnitTestSuite) { tempTop = tempTop.top; break; } } } try { window.top = tempTop; } catch (e) {} } //Snegopat. //JsUnit._fixTop(); /////Snegopat. /** * @param Any object * @return String - the type of the given object * @private */ JsUnit._trueTypeOf = function(something) { var result = typeof something; try { switch (result) { case 'string': break; case 'boolean': break; case 'number': break; case 'object': case 'function': switch (something.constructor) { case new String().constructor: result = 'String'; break; case new Boolean().constructor: result = 'Boolean'; break; case new Number().constructor: result = 'Number'; break; case new Array().constructor: result = 'Array'; break; case new RegExp().constructor: result = 'RegExp'; break; case new Date().constructor: result = 'Date'; break; case Function: result = 'Function'; break; default: if (something.constructor) { var m = something.constructor.toString().match(/function\s*([^( ]+)\(/); if (m) result = m[1]; else break; } else break; } break; } } finally { result = result.substr(0, 1).toUpperCase() + result.substr(1); return result; } } /** * @private */ JsUnit._displayStringForValue = function(aVar) { var result = '<' + aVar + '>'; if (!(aVar === null || aVar === JSUNIT_UNDEFINED_VALUE)) { result += ' (' + JsUnit._trueTypeOf(aVar) + ')'; } return result; } /** * @private */ JsUnit._argumentsIncludeComments = function(expectedNumberOfNonCommentArgs, args) { return args.length == expectedNumberOfNonCommentArgs + 1; } /** * @private */ JsUnit._commentArg = function(expectedNumberOfNonCommentArgs, args) { if (JsUnit._argumentsIncludeComments(expectedNumberOfNonCommentArgs, args)) return args[0]; return null; } /** * @private */ JsUnit._nonCommentArg = function(desiredNonCommentArgIndex, expectedNumberOfNonCommentArgs, args) { return JsUnit._argumentsIncludeComments(expectedNumberOfNonCommentArgs, args) ? args[desiredNonCommentArgIndex] : args[desiredNonCommentArgIndex - 1]; } /** * @private */ JsUnit._validateArguments = function(expectedNumberOfNonCommentArgs, args) { if (!(args.length == expectedNumberOfNonCommentArgs || (args.length == expectedNumberOfNonCommentArgs + 1 && (typeof(args[0]) == 'string') || args[0] == null))) throw new JsUnit.AssertionArgumentError('Incorrect arguments passed to assert function'); } /** * @private */ JsUnit._checkEquals = function(var1, var2) { return var1 === var2; } /** * @private */ JsUnit._checkNotUndefined = function(aVar) { return aVar !== JSUNIT_UNDEFINED_VALUE; } /** * @private */ JsUnit._checkNotNull = function(aVar) { return aVar !== null; } /** * All assertions ultimately go through this method. * @private */ JsUnit._assert = function(comment, booleanValue, failureMessage) { if (!booleanValue) throw new JsUnit.Failure(comment, failureMessage); } /** * Checks that the given boolean value is true. * @param comment optional, displayed in the case of failure * @value value that is expected to be true * @throws JsUnit.Failure if the given value is not true * @throws JsUnitInvalidAssertionArgument if the given value is not a boolean or if an incorrect number of arguments is passed */ function assert() { JsUnit._validateArguments(1, arguments); var booleanValue = JsUnit._nonCommentArg(1, 1, arguments); if (typeof(booleanValue) != 'boolean') throw new JsUnit.AssertionArgumentError('Bad argument to assert(boolean)'); JsUnit._assert(JsUnit._commentArg(1, arguments), booleanValue === true, 'Call to assert(boolean) with false'); } /** * Synonym for assertTrue * @see #assert */ function assertTrue() { JsUnit._validateArguments(1, arguments); assert(JsUnit._commentArg(1, arguments), JsUnit._nonCommentArg(1, 1, arguments)); } /** * Checks that a boolean value is false. * @param comment optional, displayed in the case of failure * @value value that is expected to be false * @throws JsUnit.Failure if value is not false * @throws JsUnitInvalidAssertionArgument if the given value is not a boolean or if an incorrect number of arguments is passed */ function assertFalse() { JsUnit._validateArguments(1, arguments); var booleanValue = JsUnit._nonCommentArg(1, 1, arguments); if (typeof(booleanValue) != 'boolean') throw new JsUnit.AssertionArgumentError('Bad argument to assertFalse(boolean)'); JsUnit._assert(JsUnit._commentArg(1, arguments), booleanValue === false, 'Call to assertFalse(boolean) with true'); } /** * Checks that two values are equal (using ===) * @param comment optional, displayed in the case of failure * @param expected the expected value * @param actual the actual value * @throws JsUnit.Failure if the values are not equal * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed */ function assertEquals() { JsUnit._validateArguments(2, arguments); var var1 = JsUnit._nonCommentArg(1, 2, arguments); var var2 = JsUnit._nonCommentArg(2, 2, arguments); JsUnit._assert(JsUnit._commentArg(2, arguments), JsUnit._checkEquals(var1, var2), 'Expected ' + JsUnit._displayStringForValue(var1) + ' but was ' + JsUnit._displayStringForValue(var2)); } /** * Checks that two values are not equal (using !==) * @param comment optional, displayed in the case of failure * @param value1 a value * @param value2 another value * @throws JsUnit.Failure if the values are equal * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed */ function assertNotEquals() { JsUnit._validateArguments(2, arguments); var var1 = JsUnit._nonCommentArg(1, 2, arguments); var var2 = JsUnit._nonCommentArg(2, 2, arguments); JsUnit._assert(JsUnit._commentArg(2, arguments), var1 !== var2, 'Expected not to be ' + JsUnit._displayStringForValue(var2)); } /** * Checks that a value is null * @param comment optional, displayed in the case of failure * @param value the value * @throws JsUnit.Failure if the value is not null * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed */ function assertNull() { JsUnit._validateArguments(1, arguments); var aVar = JsUnit._nonCommentArg(1, 1, arguments); JsUnit._assert(JsUnit._commentArg(1, arguments), aVar === null, 'Expected ' + JsUnit._displayStringForValue(null) + ' but was ' + JsUnit._displayStringForValue(aVar)); } /** * Checks that a value is not null * @param comment optional, displayed in the case of failure * @param value the value * @throws JsUnit.Failure if the value is null * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed */ function assertNotNull() { JsUnit._validateArguments(1, arguments); var aVar = JsUnit._nonCommentArg(1, 1, arguments); JsUnit._assert(JsUnit._commentArg(1, arguments), JsUnit._checkNotNull(aVar), 'Expected not to be ' + JsUnit._displayStringForValue(null)); } /** * Checks that a value is undefined * @param comment optional, displayed in the case of failure * @param value the value * @throws JsUnit.Failure if the value is not undefined * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed */ function assertUndefined() { JsUnit._validateArguments(1, arguments); var aVar = JsUnit._nonCommentArg(1, 1, arguments); JsUnit._assert(JsUnit._commentArg(1, arguments), aVar === JSUNIT_UNDEFINED_VALUE, 'Expected ' + JsUnit._displayStringForValue(JSUNIT_UNDEFINED_VALUE) + ' but was ' + JsUnit._displayStringForValue(aVar)); } /** * Checks that a value is not undefined * @param comment optional, displayed in the case of failure * @param value the value * @throws JsUnit.Failure if the value is undefined * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed */ function assertNotUndefined() { JsUnit._validateArguments(1, arguments); var aVar = JsUnit._nonCommentArg(1, 1, arguments); JsUnit._assert(JsUnit._commentArg(1, arguments), JsUnit._checkNotUndefined(aVar), 'Expected not to be ' + JsUnit._displayStringForValue(JSUNIT_UNDEFINED_VALUE)); } /** * Checks that a value is NaN (Not a Number) * @param comment optional, displayed in the case of failure * @param value the value * @throws JsUnit.Failure if the value is a number * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed */ function assertNaN() { JsUnit._validateArguments(1, arguments); var aVar = JsUnit._nonCommentArg(1, 1, arguments); JsUnit._assert(JsUnit._commentArg(1, arguments), isNaN(aVar), 'Expected NaN'); } /** * Checks that a value is not NaN (i.e. is a number) * @param comment optional, displayed in the case of failure * @param value the value * @throws JsUnit.Failure if the value is not a number * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed */ function assertNotNaN() { JsUnit._validateArguments(1, arguments); var aVar = JsUnit._nonCommentArg(1, 1, arguments); JsUnit._assert(JsUnit._commentArg(1, arguments), !isNaN(aVar), 'Expected not NaN'); } /** * Checks that an object is equal to another using === for primitives and their object counterparts but also desceding * into collections and calling assertObjectEquals for each element * @param comment optional, displayed in the case of failure * @param value the expected value * @param value the actual value * @throws JsUnit.Failure if the actual value does not equal the expected value * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed */ function assertObjectEquals() { JsUnit._validateArguments(2, arguments); var var1 = JsUnit._nonCommentArg(1, 2, arguments); var var2 = JsUnit._nonCommentArg(2, 2, arguments); var failureMessage = JsUnit._commentArg(2, arguments) ? JsUnit._commentArg(2, arguments) : ''; if (var1 === var2) return; var isEqual = false; var typeOfVar1 = JsUnit._trueTypeOf(var1); var typeOfVar2 = JsUnit._trueTypeOf(var2); if (typeOfVar1 == typeOfVar2) { var primitiveEqualityPredicate = JsUnit.PRIMITIVE_EQUALITY_PREDICATES[typeOfVar1]; if (primitiveEqualityPredicate) { isEqual = primitiveEqualityPredicate(var1, var2); } else { var expectedKeys = JsUnit.Util.getKeys(var1).sort().join(", "); var actualKeys = JsUnit.Util.getKeys(var2).sort().join(", "); if (expectedKeys != actualKeys) { JsUnit._assert(failureMessage, false, 'Expected keys "' + expectedKeys + '" but found "' + actualKeys + '"'); } for (var i in var1) { assertObjectEquals(failureMessage + ' found nested ' + typeOfVar1 + '@' + i + '\n', var1[i], var2[i]); } isEqual = true; } } JsUnit._assert(failureMessage, isEqual, 'Expected ' + JsUnit._displayStringForValue(var1) + ' but was ' + JsUnit._displayStringForValue(var2)); } /** * Checks that an array is equal to another by checking that both are arrays and then comparing their elements using assertObjectEquals * @param comment optional, displayed in the case of failure * @param value the expected array * @param value the actual array * @throws JsUnit.Failure if the actual value does not equal the expected value * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed */ function assertArrayEquals() { JsUnit._validateArguments(2, arguments); var array1 = JsUnit._nonCommentArg(1, 2, arguments); var array2 = JsUnit._nonCommentArg(2, 2, arguments); if (JsUnit._trueTypeOf(array1) != 'Array' || JsUnit._trueTypeOf(array2) != 'Array') { throw new JsUnit.AssertionArgumentError('Non-array passed to assertArrayEquals'); } assertObjectEquals(JsUnit._commentArg(2, arguments), JsUnit._nonCommentArg(1, 2, arguments), JsUnit._nonCommentArg(2, 2, arguments)); } /** * Checks that a value evaluates to true in the sense that value == true * @param comment optional, displayed in the case of failure * @param value the value * @throws JsUnit.Failure if the actual value does not evaluate to true * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed */ function assertEvaluatesToTrue() { JsUnit._validateArguments(1, arguments); var value = JsUnit._nonCommentArg(1, 1, arguments); if (!value) fail(JsUnit._commentArg(1, arguments)); } /** * Checks that a value evaluates to false in the sense that value == false * @param comment optional, displayed in the case of failure * @param value the value * @throws JsUnit.Failure if the actual value does not evaluate to true * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed */ function assertEvaluatesToFalse() { JsUnit._validateArguments(1, arguments); var value = JsUnit._nonCommentArg(1, 1, arguments); if (value) fail(JsUnit._commentArg(1, arguments)); } /** * Checks that a value is the same as an HTML string by "standardizing" both and comparing the result for equality. * Standardizing is done by temporarily creating a DIV, setting the innerHTML of the DIV to the string, and asking for * the innerHTML back. * @param comment optional, displayed in the case of failure * @param value1 the expected HTML string * @param value2 the actual HTML string * @throws JsUnit.Failure if the standardized actual value does not equal the standardized expected value * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed */ function assertHTMLEquals() { //Snegopat. JsUnit.error("assertHTMLEquals() íå ïîääåðæèâàåòñÿ â Ñíåãîïàòå."); //JsUnit._validateArguments(2, arguments); //var var1 = JsUnit._nonCommentArg(1, 2, arguments); //var var2 = JsUnit._nonCommentArg(2, 2, arguments); //var var1Standardized = JsUnit.Util.standardizeHTML(var1); //var var2Standardized = JsUnit.Util.standardizeHTML(var2); //JsUnit._assert(JsUnit._commentArg(2, arguments), var1Standardized === var2Standardized, 'Expected ' + JsUnit._displayStringForValue(var1Standardized) + ' but was ' + JsUnit._displayStringForValue(var2Standardized)); /////Snegopat. } /** * Checks that a hash is has the same contents as another by iterating over the expected hash and checking that each * key's value is present in the actual hash and calling assertEquals on the two values, and then checking that there is * no key in the actual hash that isn't present in the expected hash. * @param comment optional, displayed in the case of failure * @param value the expected hash * @param value the actual hash * @throws JsUnit.Failure if the actual hash does not evaluate to true * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed */ function assertHashEquals() { JsUnit._validateArguments(2, arguments); var var1 = JsUnit._nonCommentArg(1, 2, arguments); var var2 = JsUnit._nonCommentArg(2, 2, arguments); for (var key in var1) { assertNotUndefined("Expected hash had key " + key + " that was not found", var2[key]); assertEquals( "Value for key " + key + " mismatch - expected = " + var1[key] + ", actual = " + var2[key], var1[key], var2[key] ); } for (var key in var2) { assertNotUndefined("Actual hash had key " + key + " that was not expected", var1[key]); } } /** * Checks that two value are within a tolerance of one another * @param comment optional, displayed in the case of failure * @param value1 a value * @param value1 another value * @param tolerance the tolerance * @throws JsUnit.Failure if the two values are not within tolerance of each other * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments is passed */ function assertRoughlyEquals() { JsUnit._validateArguments(3, arguments); var expected = JsUnit._nonCommentArg(1, 3, arguments); var actual = JsUnit._nonCommentArg(2, 3, arguments); var tolerance = JsUnit._nonCommentArg(3, 3, arguments); assertTrue( "Expected " + expected + ", but got " + actual + " which was more than " + tolerance + " away", Math.abs(expected - actual) < tolerance ); } /** * Checks that a collection contains a value by checking that collection.indexOf(value) is not -1 * @param comment optional, displayed in the case of failure * @param collection the collection * @param value the value * @throws JsUnit.Failure if the collection does not contain the value * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments are passed */ function assertContains() { JsUnit._validateArguments(2, arguments); var value = JsUnit._nonCommentArg(1, 2, arguments); var collection = JsUnit._nonCommentArg(2, 2, arguments); assertTrue( "Expected '" + collection + "' to contain '" + value + "'", collection.indexOf(value) != -1 ); } /** * Checks that two arrays have the same contents, ignoring the order of the contents * @param comment optional, displayed in the case of failure * @param array1 first array * @param array2 second array * @throws JsUnit.Failure if the two arrays contain different contents * @throws JsUnitInvalidAssertionArgument if an incorrect number of arguments are passed */ function assertArrayEqualsIgnoringOrder() { JsUnit._validateArguments(2, arguments); var var1 = JsUnit._nonCommentArg(1, 2, arguments); var var2 = JsUnit._nonCommentArg(2, 2, arguments); var notEqualsMessage = "Expected arrays " + JsUnit._displayStringForValue(var1) + " and " + JsUnit._displayStringForValue(var2) + " to be equal (ignoring order)"; var notArraysMessage = "Expected arguments " + JsUnit._displayStringForValue(var1) + " and " + JsUnit._displayStringForValue(var2) + " to be arrays"; JsUnit._assert(JsUnit._commentArg(2, arguments), JsUnit._checkNotNull(var1), notEqualsMessage); JsUnit._assert(JsUnit._commentArg(2, arguments), JsUnit._checkNotNull(var2), notEqualsMessage); JsUnit._assert(JsUnit._commentArg(2, arguments), JsUnit._checkNotUndefined(var1.length), notArraysMessage); JsUnit._assert(JsUnit._commentArg(2, arguments), JsUnit._checkNotUndefined(var1.join), notArraysMessage); JsUnit._assert(JsUnit._commentArg(2, arguments), JsUnit._checkNotUndefined(var2.length), notArraysMessage); JsUnit._assert(JsUnit._commentArg(2, arguments), JsUnit._checkNotUndefined(var2.join), notArraysMessage); JsUnit._assert(JsUnit._commentArg(1, arguments), JsUnit._checkEquals(var1.length, var2.length), notEqualsMessage); for (var i = 0; i < var1.length; i++) { var found = false; for (var j = 0; j < var2.length; j++) { try { assertObjectEquals(notEqualsMessage, var1[i], var2[j]); found = true; } catch (ignored) {} } JsUnit._assert(JsUnit._commentArg(2, arguments), found, notEqualsMessage); } } /** * Synonym for assertArrayEqualsIgnoringOrder * @see #assertArrayEqualsIgnoringOrder */ function assertEqualsIgnoringOrder() { JsUnit._validateArguments(2, arguments); assertArrayEqualsIgnoringOrder(JsUnit._commentArg(2, arguments), JsUnit._nonCommentArg(1, 2, arguments), JsUnit._nonCommentArg(2, 2, arguments)); } /** * Causes a failure * @param failureMessage the message for the failure */ function fail(failureMessage) { throw new JsUnit.Failure("Call to fail()", failureMessage); } /** * Causes an error * @param errorMessage the message for the error */ function error(errorMessage) { throw new JsUnitError(errorMessage); } /** * @class * A JsUnit.Failure represents an assertion failure (or a call to fail()) during the execution of a Test Function * @param comment an optional comment about the failure * @param message the reason for the failure */ JsUnit.Failure = function(comment, message) { /** * Declaration that this is a JsUnit.Failure * @ignore */ this.isJsUnitFailure = true; /** * An optional comment about the failure */ this.comment = comment; /** * The reason for the failure */ this.jsUnitMessage = message; /** * The stack trace at the point at which the failure was encountered */ this.stackTrace = JsUnit.Util.getStackTrace(); } /** * @deprecated */ JsUnitFailure = JsUnit.Failure; /** * @class * A JsUnitError represents an error (an exception or a call to error()) during the execution of a Test Function * @param description the reason for the failure */ JsUnit.Error = function(description) { /** * The description of the error */ this.description = description; /** * The stack trace at the point at which the error was encountered */ this.stackTrace = JsUnit.Util.getStackTrace(); } /** * @deprecated */ JsUnitError = JsUnit.Error; /** * @class * A JsUnitAssertionArgumentError represents an invalid call to an assertion function - either an invalid argument type * or an incorrect number of arguments * @param description a description of the argument error */ JsUnit.AssertionArgumentError = function(description) { /** * A description of the argument error */ this.description = description; } function isLoaded() { return isTestPageLoaded; } /** * @private */ function setUp() {} /** * @private */ function tearDown() {} function trace(message, value, marker) { var text = message; if (value) text += ': ' + JsUnit._displayStringForValue(value); WScript.Echo(text); } function warn() { trace(arguments[0], arguments[1]); } function inform() { trace(arguments[0], arguments[1]); } function info() { trace(arguments[0], arguments[1]); } function debug() { trace(arguments[0], arguments[1]); } /** * @class * A JsUnitTestSuite represents a suite of JsUnit Test Pages. Test Pages and Test Suites can be added to a * JsUnitTestSuite * @constructor */ function JsUnitTestSuite() { /** * Declares that this object is a JsUnitTestSuite */ this.isJsUnitTestSuite = true; /** * @private */ this._testPages = Array(); /** * @private */ this._pageIndex = 0; for (var i = 0; i < arguments.length; i++) { if (arguments[i]._testPages) { this.addTestSuite(arguments[i]); } else { this.addTestPage(arguments[i]); } } } /** * Adds a Test Page to the suite * @param pageName the path to the Test Page */ JsUnitTestSuite.prototype.addTestPage = function(page) { this._testPages[this._testPages.length] = page; } /** * Adds a Test Suite to the suite * @param suite another JsUnitTestSuite object */ JsUnitTestSuite.prototype.addTestSuite = function(suite) { for (var i = 0; i < suite._testPages.length; i++) this.addTestPage(suite._testPages[i]); } /** * Whether the suite contains any Test Pages */ JsUnitTestSuite.prototype.containsTestPages = function() { return this._testPages.length > 0; } /** * Moves the suite on to its next Test Page */ JsUnitTestSuite.prototype.nextPage = function() { return this._testPages[this._pageIndex++]; } /** * Whether the suite has more Test Pages */ JsUnitTestSuite.prototype.hasMorePages = function() { return this._pageIndex < this._testPages.length; } /** * Produces a copy of the suite */ JsUnitTestSuite.prototype.clone = function() { var clone = new JsUnitTestSuite(); clone._testPages = this._testPages; return clone; } function setJsUnitTracer(aJsUnitTracer) { top.tracer = aJsUnitTracer; } function jsUnitGetParm(name) { return top.params.get(name); } JsUnit._newOnLoadEvent = function() { isTestPageLoaded = true; } JsUnit._setOnLoad = function(windowRef, onloadHandler) { JsUnit.fail("_setOnLoad() dose not supported"); } /** * @class * @constructor * Contains utility functions for the JsUnit framework */ JsUnit.Util = {}; /** * Standardizes an HTML string by temporarily creating a DIV, setting its innerHTML to the string, and the asking for * the innerHTML back * @param html */ JsUnit.Util.standardizeHTML = function(html) { JsUnit.fail("standardizeHTML() dose not supported"); } /** * Returns whether the given string is blank after being trimmed of whitespace * @param string */ JsUnit.Util.isBlank = function(string) { return JsUnit.Util.trim(string) == ''; } /** * Implemented here because the JavaScript Array.push(anObject) and Array.pop() functions are not available in IE 5.0 * @param anArray the array onto which to push * @param anObject the object to push onto the array */ JsUnit.Util.push = function(anArray, anObject) { anArray[anArray.length] = anObject; } /** * Implemented here because the JavaScript Array.push(anObject) and Array.pop() functions are not available in IE 5.0 * @param anArray the array from which to pop */ JsUnit.Util.pop = function pop(anArray) { if (anArray.length >= 1) { delete anArray[anArray.length - 1]; anArray.length--; } } /** * Returns the name of the given function, or 'anonymous' if it has no name * @param aFunction */ JsUnit.Util.getFunctionName = function(aFunction) { var regexpResult = aFunction.toString().match(/function(\s*)(\w*)/); if (regexpResult && regexpResult.length >= 2 && regexpResult[2]) { return regexpResult[2]; } return 'anonymous'; } /** * Returns the current stack trace */ JsUnit.Util.getStackTrace = function() { var result = ''; if (typeof(arguments.caller) != 'undefined') { // IE, not ECMA for (var a = arguments.caller; a != null; a = a.caller) { result += '> ' + JsUnit.Util.getFunctionName(a.callee) + '\n'; if (a.caller == a) { result += '*'; break; } } } else { // Mozilla, not ECMA // fake an exception so we can get Mozilla's error stack try { foo.bar; } catch (exception) { var stack = JsUnit.Util.parseErrorStack(exception); for (var i = 1; i < stack.length; i++) { result += '> ' + stack[i] + '\n'; } } } return result; } /** * Returns an array of stack trace elements from the given exception * @param exception */ JsUnit.Util.parseErrorStack = function(exception) { var stack = []; var name; if (!exception || !exception.stack) { return stack; } var stacklist = exception.stack.split('\n'); for (var i = 0; i < stacklist.length - 1; i++) { var framedata = stacklist[i]; name = framedata.match(/^(\w*)/)[1]; if (!name) { name = 'anonymous'; } stack[stack.length] = name; } // remove top level anonymous functions to match IE while (stack.length && stack[stack.length - 1] == 'anonymous') { stack.length = stack.length - 1; } return stack; } /** * Strips whitespace from either end of the given string * @param string */ JsUnit.Util.trim = function(string) { if (string == null) return null; var startingIndex = 0; var endingIndex = string.length - 1; var singleWhitespaceRegex = /\s/; while (string.substring(startingIndex, startingIndex + 1).match(singleWhitespaceRegex)) startingIndex++; while (string.substring(endingIndex, endingIndex + 1).match(singleWhitespaceRegex)) endingIndex--; if (endingIndex < startingIndex) return ''; return string.substring(startingIndex, endingIndex + 1); } JsUnit.Util.getKeys = function(obj) { var keys = []; for (var key in obj) { JsUnit.Util.push(keys, key); } return keys; } JsUnit.Util.inherit = function(superclass, subclass) { var x = function() {}; x.prototype = superclass.prototype; subclass.prototype = new x(); } //Defines the top level Class function Class() {} Class.extend = function(def) { var classDef = function() { if (arguments[0] !== Class) { this.construct.apply(this, arguments); } }; var _super = this.prototype; var proto = new this(Class); for (var n in def) { var item = def[n]; if (typeof def[n] == "function" && /\b_super\b/.test(def[n])) { proto[n] = (function(name, fn) { return function() { // 1. var tmp = this._super; // Add a new ._super() method that is the same method // but on the super-class this._super = _super[name]; // 2. // The method only need to be bound temporarily, so we // remove it when we're done executing var ret = fn.apply(this, arguments); // 3. this._super = tmp; return ret; }; })(n, def[n]); } else { proto[n] = item; } } classDef.prototype = proto; // Enforce the constructor to be what we expect classDef.prototype.constructor = Class; //Give this new class the same static extend method classDef.extend = this.extend; return classDef; }; JsUnit.Runner = {}; JsUnit.Runner.FSO = new ActiveXObject("Scripting.FileSystemObject"); JsUnit.Runner.runTest = function(path) { var ts = JsUnit.Runner.FSO.OpenTextFile(path); var testSource = ts.ReadAll(); ts.Close(); (function(source, jsu, cls) { var testObj try { testObj = eval(source); } catch (e) { warn(path + ": " + e.description); } var re_test = /^test/; for (var testName in testObj) { if (re_test.test(testName)) { JsUnit.Runner.safeRun(testObj, 'setUp'); JsUnit.Runner.safeRun(testObj, testName); JsUnit.Runner.safeRun(testObj, 'tearDown'); } } })(testSource, JsUnit, Class); } JsUnit.Runner.safeRun = function(tObj, tName) { if (typeof tObj[tName] == 'function') { try { tObj[tName].call(); } catch (e) { var errMsg = e.comment ? e.comment : e.description; if (e.comment) { warn("--> " + tName + ": \n\t" + e.jsUnitMessage + "\n\t" + e.comment); } else { warn("--> " + tName + ": " + errMsg); } } } } JsUnit.Runner.run = function(pathToTestDir) { var fso = JsUnit.Runner.FSO; var re_tests = /test.+?\.js$/i; (function(root) { var folder = fso.GetFolder(root); var folders = new Enumerator(folder.SubFolders); for (; !folders.atEnd(); folders.moveNext()) { inform(folders.item().Path); arguments.callee(loader, folders.item().Path); } var files = new Enumerator(folder.Files); for (; !files.atEnd(); files.moveNext()) { var file = files.item(); if (re_tests.test(file.Name)) { inform(file.Name); JsUnit.Runner.runTest(file.Path); } } })(pathToTestDir); } exports.VERSIONINFO = "JSUnit Lib (jsunit.js) version 2.2"; exports.global = global; exports.require = global.require; exports.JsUnit = JsUnit;