1var JSUNIT_UNDEFINED_VALUE;
2var JSUNIT_VERSION = 2.2;
3var isTestPageLoaded = false;
4
5//hack for NS62 bug
6function jsUnitFixTop() {
7    var tempTop = top;
8    if (!tempTop) {
9        tempTop = window;
10        while (tempTop.parent) {
11            tempTop = tempTop.parent;
12            if (tempTop.top && tempTop.top.jsUnitTestSuite) {
13                tempTop = tempTop.top;
14                break;
15            }
16        }
17    }
18    try {
19        window.top = tempTop;
20    } catch (e) {
21    }
22}
23
24jsUnitFixTop();
25
26/**
27 + * A more functional typeof
28 + * @param Object o
29 + * @return String
30 + */
31function _trueTypeOf(something) {
32    var result = typeof something;
33    try {
34        switch (result) {
35            case 'string':
36            case 'boolean':
37            case 'number':
38                break;
39            case 'object':
40            case 'function':
41                switch (something.constructor)
42                        {
43                    case String:
44                        result = 'String';
45                        break;
46                    case Boolean:
47                        result = 'Boolean';
48                        break;
49                    case Number:
50                        result = 'Number';
51                        break;
52                    case Array:
53                        result = 'Array';
54                        break;
55                    case RegExp:
56                        result = 'RegExp';
57                        break;
58                    case Function:
59                        result = 'Function';
60                        break;
61                    default:
62                        var m = something.constructor.toString().match(/function\s*([^( ]+)\(/);
63                        if (m)
64                            result = m[1];
65                        else
66                            break;
67                }
68                break;
69        }
70    }
71    finally {
72        result = result.substr(0, 1).toUpperCase() + result.substr(1);
73        return result;
74    }
75}
76
77function _displayStringForValue(aVar) {
78    var result = '<' + aVar + '>';
79    if (!(aVar === null || aVar === top.JSUNIT_UNDEFINED_VALUE)) {
80        result += ' (' + _trueTypeOf(aVar) + ')';
81    }
82    return result;
83}
84
85function fail(failureMessage) {
86    throw new JsUnitException("Call to fail()", failureMessage);
87}
88
89function error(errorMessage) {
90    var errorObject = new Object();
91    errorObject.description = errorMessage;
92    errorObject.stackTrace = getStackTrace();
93    throw errorObject;
94}
95
96function argumentsIncludeComments(expectedNumberOfNonCommentArgs, args) {
97    return args.length == expectedNumberOfNonCommentArgs + 1;
98}
99
100function commentArg(expectedNumberOfNonCommentArgs, args) {
101    if (argumentsIncludeComments(expectedNumberOfNonCommentArgs, args))
102        return args[0];
103
104    return null;
105}
106
107function nonCommentArg(desiredNonCommentArgIndex, expectedNumberOfNonCommentArgs, args) {
108    return argumentsIncludeComments(expectedNumberOfNonCommentArgs, args) ?
109           args[desiredNonCommentArgIndex] :
110           args[desiredNonCommentArgIndex - 1];
111}
112
113function _validateArguments(expectedNumberOfNonCommentArgs, args) {
114    if (!( args.length == expectedNumberOfNonCommentArgs ||
115           (args.length == expectedNumberOfNonCommentArgs + 1 && typeof(args[0]) == 'string') ))
116        error('Incorrect arguments passed to assert function');
117}
118
119function _assert(comment, booleanValue, failureMessage) {
120    if (!booleanValue)
121        throw new JsUnitException(comment, failureMessage);
122}
123
124function assert() {
125    _validateArguments(1, arguments);
126    var booleanValue = nonCommentArg(1, 1, arguments);
127
128    if (typeof(booleanValue) != 'boolean')
129        error('Bad argument to assert(boolean)');
130
131    _assert(commentArg(1, arguments), booleanValue === true, 'Call to assert(boolean) with false');
132}
133
134function assertTrue() {
135    _validateArguments(1, arguments);
136    var booleanValue = nonCommentArg(1, 1, arguments);
137
138    if (typeof(booleanValue) != 'boolean')
139        error('Bad argument to assertTrue(boolean)');
140
141    _assert(commentArg(1, arguments), booleanValue === true, 'Call to assertTrue(boolean) with false');
142}
143
144function assertFalse() {
145    _validateArguments(1, arguments);
146    var booleanValue = nonCommentArg(1, 1, arguments);
147
148    if (typeof(booleanValue) != 'boolean')
149        error('Bad argument to assertFalse(boolean)');
150
151    _assert(commentArg(1, arguments), booleanValue === false, 'Call to assertFalse(boolean) with true');
152}
153
154function assertEquals() {
155    _validateArguments(2, arguments);
156    var var1 = nonCommentArg(1, 2, arguments);
157    var var2 = nonCommentArg(2, 2, arguments);
158    _assert(commentArg(2, arguments), var1 === var2, 'Expected ' + _displayStringForValue(var1) + ' but was ' + _displayStringForValue(var2));
159}
160
161function assertNotEquals() {
162    _validateArguments(2, arguments);
163    var var1 = nonCommentArg(1, 2, arguments);
164    var var2 = nonCommentArg(2, 2, arguments);
165    _assert(commentArg(2, arguments), var1 !== var2, 'Expected not to be ' + _displayStringForValue(var2));
166}
167
168function assertNull() {
169    _validateArguments(1, arguments);
170    var aVar = nonCommentArg(1, 1, arguments);
171    _assert(commentArg(1, arguments), aVar === null, 'Expected ' + _displayStringForValue(null) + ' but was ' + _displayStringForValue(aVar));
172}
173
174function assertNotNull() {
175    _validateArguments(1, arguments);
176    var aVar = nonCommentArg(1, 1, arguments);
177    _assert(commentArg(1, arguments), aVar !== null, 'Expected not to be ' + _displayStringForValue(null));
178}
179
180function assertUndefined() {
181    _validateArguments(1, arguments);
182    var aVar = nonCommentArg(1, 1, arguments);
183    _assert(commentArg(1, arguments), aVar === top.JSUNIT_UNDEFINED_VALUE, 'Expected ' + _displayStringForValue(top.JSUNIT_UNDEFINED_VALUE) + ' but was ' + _displayStringForValue(aVar));
184}
185
186function assertNotUndefined() {
187    _validateArguments(1, arguments);
188    var aVar = nonCommentArg(1, 1, arguments);
189    _assert(commentArg(1, arguments), aVar !== top.JSUNIT_UNDEFINED_VALUE, 'Expected not to be ' + _displayStringForValue(top.JSUNIT_UNDEFINED_VALUE));
190}
191
192function assertNaN() {
193    _validateArguments(1, arguments);
194    var aVar = nonCommentArg(1, 1, arguments);
195    _assert(commentArg(1, arguments), isNaN(aVar), 'Expected NaN');
196}
197
198function assertNotNaN() {
199    _validateArguments(1, arguments);
200    var aVar = nonCommentArg(1, 1, arguments);
201    _assert(commentArg(1, arguments), !isNaN(aVar), 'Expected not NaN');
202}
203
204function assertObjectEquals() {
205    _validateArguments(2, arguments);
206    var var1 = nonCommentArg(1, 2, arguments);
207    var var2 = nonCommentArg(2, 2, arguments);
208    var type;
209    var msg = commentArg(2, arguments)?commentArg(2, arguments):'';
210    var isSame = (var1 === var2);
211    //shortpath for references to same object
212    var isEqual = ( (type = _trueTypeOf(var1)) == _trueTypeOf(var2) );
213    if (isEqual && !isSame) {
214        switch (type) {
215            case 'String':
216            case 'Number':
217                isEqual = (var1 == var2);
218                break;
219            case 'Boolean':
220            case 'Date':
221                isEqual = (var1 === var2);
222                break;
223            case 'RegExp':
224            case 'Function':
225                isEqual = (var1.toString() === var2.toString());
226                break;
227            default: //Object | Array
228                var i;
229                if (isEqual = (var1.length === var2.length))
230                    for (i in var1)
231                        assertObjectEquals(msg + ' found nested ' + type + '@' + i + '\n', var1[i], var2[i]);
232        }
233        _assert(msg, isEqual, 'Expected ' + _displayStringForValue(var1) + ' but was ' + _displayStringForValue(var2));
234    }
235}
236
237assertArrayEquals = assertObjectEquals;
238
239function assertEvaluatesToTrue() {
240    _validateArguments(1, arguments);
241    var value = nonCommentArg(1, 1, arguments);
242    if (!value)
243        fail(commentArg(1, arguments));
244}
245
246function assertEvaluatesToFalse() {
247    _validateArguments(1, arguments);
248    var value = nonCommentArg(1, 1, arguments);
249    if (value)
250        fail(commentArg(1, arguments));
251}
252
253function assertHTMLEquals() {
254    _validateArguments(2, arguments);
255    var var1 = nonCommentArg(1, 2, arguments);
256    var var2 = nonCommentArg(2, 2, arguments);
257    var var1Standardized = standardizeHTML(var1);
258    var var2Standardized = standardizeHTML(var2);
259
260    _assert(commentArg(2, arguments), var1Standardized === var2Standardized, 'Expected ' + _displayStringForValue(var1Standardized) + ' but was ' + _displayStringForValue(var2Standardized));
261}
262
263function assertHashEquals() {
264    _validateArguments(2, arguments);
265    var var1 = nonCommentArg(1, 2, arguments);
266    var var2 = nonCommentArg(2, 2, arguments);
267    for (var key in var1) {
268        assertNotUndefined("Expected hash had key " + key + " that was not found", var2[key]);
269        assertEquals(
270                "Value for key " + key + " mismatch - expected = " + var1[key] + ", actual = " + var2[key],
271                var1[key], var2[key]
272                );
273    }
274    for (var key in var2) {
275        assertNotUndefined("Actual hash had key " + key + " that was not expected", var1[key]);
276    }
277}
278
279function assertRoughlyEquals() {
280    _validateArguments(3, arguments);
281    var expected = nonCommentArg(1, 3, arguments);
282    var actual = nonCommentArg(2, 3, arguments);
283    var tolerance = nonCommentArg(3, 3, arguments);
284    assertTrue(
285            "Expected " + expected + ", but got " + actual + " which was more than " + tolerance + " away",
286            Math.abs(expected - actual) < tolerance
287            );
288}
289
290function assertContains() {
291    _validateArguments(2, arguments);
292    var contained = nonCommentArg(1, 2, arguments);
293    var container = nonCommentArg(2, 2, arguments);
294    assertTrue(
295            "Expected '" + container + "' to contain '" + contained + "'",
296            container.indexOf(contained) != -1
297            );
298}
299
300function standardizeHTML(html) {
301    var translator = document.createElement("DIV");
302    translator.innerHTML = html;
303    return translator.innerHTML;
304}
305
306function isLoaded() {
307    return isTestPageLoaded;
308}
309
310function setUp() {
311}
312
313function tearDown() {
314}
315
316function getFunctionName(aFunction) {
317    var regexpResult = aFunction.toString().match(/function(\s*)(\w*)/);
318    if (regexpResult && regexpResult.length >= 2 && regexpResult[2]) {
319        return regexpResult[2];
320    }
321    return 'anonymous';
322}
323
324function getStackTrace() {
325    var result = '';
326
327    if (typeof(arguments.caller) != 'undefined') { // IE, not ECMA
328        for (var a = arguments.caller; a != null; a = a.caller) {
329            result += '> ' + getFunctionName(a.callee) + '\n';
330            if (a.caller == a) {
331                result += '*';
332                break;
333            }
334        }
335    }
336    else { // Mozilla, not ECMA
337        // fake an exception so we can get Mozilla's error stack
338        var testExcp;
339        try
340        {
341            foo.bar;
342        }
343        catch(testExcp)
344        {
345            var stack = parseErrorStack(testExcp);
346            for (var i = 1; i < stack.length; i++)
347            {
348                result += '> ' + stack[i] + '\n';
349            }
350        }
351    }
352
353    return result;
354}
355
356function parseErrorStack(excp)
357{
358    var stack = [];
359    var name;
360
361    if (!excp || !excp.stack)
362    {
363        return stack;
364    }
365
366    var stacklist = excp.stack.split('\n');
367
368    for (var i = 0; i < stacklist.length - 1; i++)
369    {
370        var framedata = stacklist[i];
371
372        name = framedata.match(/^(\w*)/)[1];
373        if (!name) {
374            name = 'anonymous';
375        }
376
377        stack[stack.length] = name;
378    }
379    // remove top level anonymous functions to match IE
380
381    while (stack.length && stack[stack.length - 1] == 'anonymous')
382    {
383        stack.length = stack.length - 1;
384    }
385    return stack;
386}
387
388function JsUnitException(comment, message) {
389    this.isJsUnitException = true;
390    this.comment = comment;
391    this.jsUnitMessage = message;
392    this.stackTrace = getStackTrace();
393}
394
395function warn() {
396    if (top.tracer != null)
397        top.tracer.warn(arguments[0], arguments[1]);
398}
399
400function inform() {
401    if (top.tracer != null)
402        top.tracer.inform(arguments[0], arguments[1]);
403}
404
405function info() {
406    inform(arguments[0], arguments[1]);
407}
408
409function debug() {
410    if (top.tracer != null)
411        top.tracer.debug(arguments[0], arguments[1]);
412}
413
414function setJsUnitTracer(aJsUnitTracer) {
415    top.tracer = aJsUnitTracer;
416}
417
418function trim(str) {
419    if (str == null)
420        return null;
421
422    var startingIndex = 0;
423    var endingIndex = str.length - 1;
424
425    while (str.substring(startingIndex, startingIndex + 1) == ' ')
426        startingIndex++;
427
428    while (str.substring(endingIndex, endingIndex + 1) == ' ')
429        endingIndex--;
430
431    if (endingIndex < startingIndex)
432        return '';
433
434    return str.substring(startingIndex, endingIndex + 1);
435}
436
437function isBlank(str) {
438    return trim(str) == '';
439}
440
441// the functions push(anArray, anObject) and pop(anArray)
442// exist because the JavaScript Array.push(anObject) and Array.pop()
443// functions are not available in IE 5.0
444
445function push(anArray, anObject) {
446    anArray[anArray.length] = anObject;
447}
448function pop(anArray) {
449    if (anArray.length >= 1) {
450        delete anArray[anArray.length - 1];
451        anArray.length--;
452    }
453}
454
455function jsUnitGetParm(name)
456{
457    if (typeof(top.jsUnitParmHash[name]) != 'undefined')
458    {
459        return top.jsUnitParmHash[name];
460    }
461    return null;
462}
463
464if (top && typeof(top.xbDEBUG) != 'undefined' && top.xbDEBUG.on && top.testManager)
465{
466    top.xbDebugTraceObject('top.testManager.containerTestFrame', 'JSUnitException');
467    // asserts
468    top.xbDebugTraceFunction('top.testManager.containerTestFrame', '_displayStringForValue');
469    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'error');
470    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'argumentsIncludeComments');
471    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'commentArg');
472    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'nonCommentArg');
473    top.xbDebugTraceFunction('top.testManager.containerTestFrame', '_validateArguments');
474    top.xbDebugTraceFunction('top.testManager.containerTestFrame', '_assert');
475    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assert');
476    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertTrue');
477    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertEquals');
478    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertNotEquals');
479    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertNull');
480    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertNotNull');
481    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertUndefined');
482    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertNotUndefined');
483    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertNaN');
484    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertNotNaN');
485    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'isLoaded');
486    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'setUp');
487    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'tearDown');
488    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'getFunctionName');
489    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'getStackTrace');
490    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'warn');
491    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'inform');
492    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'debug');
493    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'setJsUnitTracer');
494    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'trim');
495    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'isBlank');
496    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'newOnLoadEvent');
497    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'push');
498    top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'pop');
499}
500
501function newOnLoadEvent() {
502    isTestPageLoaded = true;
503}
504
505function jsUnitSetOnLoad(windowRef, onloadHandler)
506{
507    var isKonqueror = navigator.userAgent.indexOf('Konqueror/') != -1 ||
508                      navigator.userAgent.indexOf('Safari/') != -1;
509
510    if (typeof(windowRef.attachEvent) != 'undefined') {
511        // Internet Explorer, Opera
512        windowRef.attachEvent("onload", onloadHandler);
513    } else if (typeof(windowRef.addEventListener) != 'undefined' && !isKonqueror) {
514        // Mozilla, Konqueror
515        // exclude Konqueror due to load issues
516        windowRef.addEventListener("load", onloadHandler, false);
517    } else if (typeof(windowRef.document.addEventListener) != 'undefined' && !isKonqueror) {
518        // DOM 2 Events
519        // exclude Mozilla, Konqueror due to load issues
520        windowRef.document.addEventListener("load", onloadHandler, false);
521    } else if (typeof(windowRef.onload) != 'undefined' && windowRef.onload) {
522        windowRef.jsunit_original_onload = windowRef.onload;
523        windowRef.onload = function() {
524            windowRef.jsunit_original_onload();
525            onloadHandler();
526        };
527    } else {
528        // browsers that do not support windowRef.attachEvent or
529        // windowRef.addEventListener will override a page's own onload event
530        windowRef.onload = onloadHandler;
531    }
532}
533
534jsUnitSetOnLoad(window, newOnLoadEvent);
535
536top.JSUNIT_JSCORE_LOCATION = findPath('jsUnitCore.js');
537/**
538 *  return full path to the script
539 *
540 *  @param {String} sname script name
541 *  @return {String, Null} mixed string full path or null
542 *  @scope public
543 */
544function findPath (sname /* :String */) /* :String */{
545  var sc = document.getElementsByTagName('script'),
546      sr = new RegExp('^(.*/|)('+sname+')([#?]|$)');
547  for (var i=0,scL=sc.length; i<scL; i++) {
548    // matched desired script
549    var m = String(sc[i].src).match(sr);
550    if (m) {
551      /*
552      *  we've matched the full path
553      */
554      if (m[1].match(/^((https?|file)\:\/{2,}|\w:[\\])/)) return m[1];
555      /*
556      *  we've matched absolute path from the site root
557      */
558      if (m[1].indexOf("/")==0) return m[1];
559      b = document.getElementsByTagName('base');
560      if (b[0] && b[0].href) return b[0].href+m[1];
561      /*
562      *  return matching part of the document location and path to js file
563      */
564      return (document.location.pathname.match(/(.*[\/\\])/)[0]+m[1]).replace(/^\/+(?=\w:)/,"");
565    }
566  }
567  return null;
568}