]> ToastFreeware Gitweb - philipp/winterrodeln/wradmin.git/blob - wradmin/static/yui/yuitest/yuitest_core.js
Rename public directory to static.
[philipp/winterrodeln/wradmin.git] / wradmin / static / yui / yuitest / yuitest_core.js
1 /*
2 Copyright (c) 2009, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
5 version: 2.7.0
6 */
7 YAHOO.namespace("tool");
8
9 //-----------------------------------------------------------------------------
10 // TestCase object
11 //-----------------------------------------------------------------------------
12 (function(){
13     
14     //used for autogenerating test case names
15     var tempId = 0;
16     
17     /**
18      * Test case containing various tests to run.
19      * @param template An object containing any number of test methods, other methods,
20      *                 an optional name, and anything else the test case needs.
21      * @class TestCase
22      * @namespace YAHOO.tool
23      * @constructor
24      */
25     YAHOO.tool.TestCase = function (template /*:Object*/) {
26         
27         /**
28          * Special rules for the test case. Possible subobjects
29          * are fail, for tests that should fail, and error, for
30          * tests that should throw an error.
31          */
32         this._should /*:Object*/ = {};
33         
34         //copy over all properties from the template to this object
35         for (var prop in template) {
36             this[prop] = template[prop];
37         }    
38         
39         //check for a valid name
40         if (!YAHOO.lang.isString(this.name)){
41             /**
42              * Name for the test case.
43              */
44             this.name /*:String*/ = "testCase" + (tempId++);
45         }
46     
47     };
48     
49     
50     YAHOO.tool.TestCase.prototype = {  
51     
52         /**
53          * Resumes a paused test and runs the given function.
54          * @param {Function} segment (Optional) The function to run.
55          *      If omitted, the test automatically passes.
56          * @return {Void}
57          * @method resume
58          */
59         resume : function (segment /*:Function*/) /*:Void*/ {
60             YAHOO.tool.TestRunner.resume(segment);
61         },
62     
63         /**
64          * Causes the test case to wait a specified amount of time and then
65          * continue executing the given code.
66          * @param {Function} segment (Optional) The function to run after the delay.
67          *      If omitted, the TestRunner will wait until resume() is called.
68          * @param {int} delay (Optional) The number of milliseconds to wait before running
69          *      the function. If omitted, defaults to zero.
70          * @return {Void}
71          * @method wait
72          */
73         wait : function (segment /*:Function*/, delay /*:int*/) /*:Void*/{
74             var args = arguments;
75             if (YAHOO.lang.isFunction(args[0])){
76                 throw new YAHOO.tool.TestCase.Wait(args[0], args[1]);
77             } else {
78                 throw new YAHOO.tool.TestCase.Wait(function(){
79                     YAHOO.util.Assert.fail("Timeout: wait() called but resume() never called.");
80                 }, (YAHOO.lang.isNumber(args[0]) ? args[0] : 10000));
81             }            
82         },
83     
84         //-------------------------------------------------------------------------
85         // Stub Methods
86         //-------------------------------------------------------------------------
87     
88         /**
89          * Function to run before each test is executed.
90          * @return {Void}
91          * @method setUp
92          */
93         setUp : function () /*:Void*/ {
94         },
95         
96         /**
97          * Function to run after each test is executed.
98          * @return {Void}
99          * @method tearDown
100          */
101         tearDown: function () /*:Void*/ {    
102         }
103     };
104     
105     /**
106      * Represents a stoppage in test execution to wait for an amount of time before
107      * continuing.
108      * @param {Function} segment A function to run when the wait is over.
109      * @param {int} delay The number of milliseconds to wait before running the code.
110      * @class Wait
111      * @namespace YAHOO.tool.TestCase
112      * @constructor
113      *
114      */
115     YAHOO.tool.TestCase.Wait = function (segment /*:Function*/, delay /*:int*/) {
116         
117         /**
118          * The segment of code to run when the wait is over.
119          * @type Function
120          * @property segment
121          */
122         this.segment /*:Function*/ = (YAHOO.lang.isFunction(segment) ? segment : null);
123     
124         /**
125          * The delay before running the segment of code.
126          * @type int
127          * @property delay
128          */
129         this.delay /*:int*/ = (YAHOO.lang.isNumber(delay) ? delay : 0);
130     
131     };
132
133 })();
134
135 YAHOO.namespace("tool");
136
137
138 //-----------------------------------------------------------------------------
139 // TestSuite object
140 //-----------------------------------------------------------------------------
141
142 /**
143  * A test suite that can contain a collection of TestCase and TestSuite objects.
144  * @param {String||Object} data The name of the test suite or an object containing
145  *      a name property as well as setUp and tearDown methods.
146  * @namespace YAHOO.tool
147  * @class TestSuite
148  * @constructor
149  */
150 YAHOO.tool.TestSuite = function (data /*:String||Object*/) {
151
152     /**
153      * The name of the test suite.
154      * @type String
155      * @property name
156      */
157     this.name /*:String*/ = "";
158
159     /**
160      * Array of test suites and
161      * @private
162      */
163     this.items /*:Array*/ = [];
164
165     //initialize the properties
166     if (YAHOO.lang.isString(data)){
167         this.name = data;
168     } else if (YAHOO.lang.isObject(data)){
169         YAHOO.lang.augmentObject(this, data, true);
170     }
171
172     //double-check name
173     if (this.name === ""){
174         this.name = YAHOO.util.Dom.generateId(null, "testSuite");
175     }
176
177 };
178
179 YAHOO.tool.TestSuite.prototype = {
180     
181     /**
182      * Adds a test suite or test case to the test suite.
183      * @param {YAHOO.tool.TestSuite||YAHOO.tool.TestCase} testObject The test suite or test case to add.
184      * @return {Void}
185      * @method add
186      */
187     add : function (testObject /*:YAHOO.tool.TestSuite*/) /*:Void*/ {
188         if (testObject instanceof YAHOO.tool.TestSuite || testObject instanceof YAHOO.tool.TestCase) {
189             this.items.push(testObject);
190         }
191     },
192     
193     //-------------------------------------------------------------------------
194     // Stub Methods
195     //-------------------------------------------------------------------------
196
197     /**
198      * Function to run before each test is executed.
199      * @return {Void}
200      * @method setUp
201      */
202     setUp : function () /*:Void*/ {
203     },
204     
205     /**
206      * Function to run after each test is executed.
207      * @return {Void}
208      * @method tearDown
209      */
210     tearDown: function () /*:Void*/ {
211     }
212     
213 };
214
215 YAHOO.namespace("tool");
216
217 /**
218  * The YUI test tool
219  * @module yuitest
220  * @namespace YAHOO.tool
221  * @requires yahoo,dom,event,logger
222  */
223
224
225 //-----------------------------------------------------------------------------
226 // TestRunner object
227 //-----------------------------------------------------------------------------
228
229
230 YAHOO.tool.TestRunner = (function(){
231
232     /**
233      * A node in the test tree structure. May represent a TestSuite, TestCase, or
234      * test function.
235      * @param {Variant} testObject A TestSuite, TestCase, or the name of a test function.
236      * @class TestNode
237      * @constructor
238      * @private
239      */
240     function TestNode(testObject /*:Variant*/){
241     
242         /**
243          * The TestSuite, TestCase, or test function represented by this node.
244          * @type Variant
245          * @property testObject
246          */
247         this.testObject = testObject;
248         
249         /**
250          * Pointer to this node's first child.
251          * @type TestNode
252          * @property firstChild
253          */        
254         this.firstChild /*:TestNode*/ = null;
255         
256         /**
257          * Pointer to this node's last child.
258          * @type TestNode
259          * @property lastChild
260          */        
261         this.lastChild = null;
262         
263         /**
264          * Pointer to this node's parent.
265          * @type TestNode
266          * @property parent
267          */        
268         this.parent = null; 
269    
270         /**
271          * Pointer to this node's next sibling.
272          * @type TestNode
273          * @property next
274          */        
275         this.next = null;
276         
277         /**
278          * Test results for this test object.
279          * @type object
280          * @property results
281          */                
282         this.results /*:Object*/ = {
283             passed : 0,
284             failed : 0,
285             total : 0,
286             ignored : 0
287         };
288         
289         //initialize results
290         if (testObject instanceof YAHOO.tool.TestSuite){
291             this.results.type = "testsuite";
292             this.results.name = testObject.name;
293         } else if (testObject instanceof YAHOO.tool.TestCase){
294             this.results.type = "testcase";
295             this.results.name = testObject.name;
296         }
297        
298     }
299     
300     TestNode.prototype = {
301     
302         /**
303          * Appends a new test object (TestSuite, TestCase, or test function name) as a child
304          * of this node.
305          * @param {Variant} testObject A TestSuite, TestCase, or the name of a test function.
306          * @return {Void}
307          */
308         appendChild : function (testObject /*:Variant*/) /*:Void*/{
309             var node = new TestNode(testObject);
310             if (this.firstChild === null){
311                 this.firstChild = this.lastChild = node;
312             } else {
313                 this.lastChild.next = node;
314                 this.lastChild = node;
315             }
316             node.parent = this;
317             return node;
318         }       
319     };
320
321     /**
322      * Runs test suites and test cases, providing events to allowing for the
323      * interpretation of test results.
324      * @namespace YAHOO.tool
325      * @class TestRunner
326      * @static
327      */
328     function TestRunner(){
329     
330         //inherit from EventProvider
331         TestRunner.superclass.constructor.apply(this,arguments);
332         
333         /**
334          * Suite on which to attach all TestSuites and TestCases to be run.
335          * @type YAHOO.tool.TestSuite
336          * @property masterSuite
337          * @private
338          * @static
339          */
340         this.masterSuite /*:YAHOO.tool.TestSuite*/ = new YAHOO.tool.TestSuite("YUI Test Results");        
341
342         /**
343          * Pointer to the current node in the test tree.
344          * @type TestNode
345          * @private
346          * @property _cur
347          * @static
348          */
349         this._cur = null;
350         
351         /**
352          * Pointer to the root node in the test tree.
353          * @type TestNode
354          * @private
355          * @property _root
356          * @static
357          */
358         this._root = null;
359         
360         //create events
361         var events /*:Array*/ = [
362             this.TEST_CASE_BEGIN_EVENT,
363             this.TEST_CASE_COMPLETE_EVENT,
364             this.TEST_SUITE_BEGIN_EVENT,
365             this.TEST_SUITE_COMPLETE_EVENT,
366             this.TEST_PASS_EVENT,
367             this.TEST_FAIL_EVENT,
368             this.TEST_IGNORE_EVENT,
369             this.COMPLETE_EVENT,
370             this.BEGIN_EVENT
371         ];
372         for (var i=0; i < events.length; i++){
373             this.createEvent(events[i], { scope: this });
374         }       
375    
376     }
377     
378     YAHOO.lang.extend(TestRunner, YAHOO.util.EventProvider, {
379     
380         //-------------------------------------------------------------------------
381         // Constants
382         //-------------------------------------------------------------------------
383          
384         /**
385          * Fires when a test case is opened but before the first 
386          * test is executed.
387          * @event testcasebegin
388          */         
389         TEST_CASE_BEGIN_EVENT /*:String*/ : "testcasebegin",
390         
391         /**
392          * Fires when all tests in a test case have been executed.
393          * @event testcasecomplete
394          */        
395         TEST_CASE_COMPLETE_EVENT /*:String*/ : "testcasecomplete",
396         
397         /**
398          * Fires when a test suite is opened but before the first 
399          * test is executed.
400          * @event testsuitebegin
401          */        
402         TEST_SUITE_BEGIN_EVENT /*:String*/ : "testsuitebegin",
403         
404         /**
405          * Fires when all test cases in a test suite have been
406          * completed.
407          * @event testsuitecomplete
408          */        
409         TEST_SUITE_COMPLETE_EVENT /*:String*/ : "testsuitecomplete",
410         
411         /**
412          * Fires when a test has passed.
413          * @event pass
414          */        
415         TEST_PASS_EVENT /*:String*/ : "pass",
416         
417         /**
418          * Fires when a test has failed.
419          * @event fail
420          */        
421         TEST_FAIL_EVENT /*:String*/ : "fail",
422         
423         /**
424          * Fires when a test has been ignored.
425          * @event ignore
426          */        
427         TEST_IGNORE_EVENT /*:String*/ : "ignore",
428         
429         /**
430          * Fires when all test suites and test cases have been completed.
431          * @event complete
432          */        
433         COMPLETE_EVENT /*:String*/ : "complete",
434         
435         /**
436          * Fires when the run() method is called.
437          * @event begin
438          */        
439         BEGIN_EVENT /*:String*/ : "begin",    
440         
441         //-------------------------------------------------------------------------
442         // Test Tree-Related Methods
443         //-------------------------------------------------------------------------
444
445         /**
446          * Adds a test case to the test tree as a child of the specified node.
447          * @param {TestNode} parentNode The node to add the test case to as a child.
448          * @param {YAHOO.tool.TestCase} testCase The test case to add.
449          * @return {Void}
450          * @static
451          * @private
452          * @method _addTestCaseToTestTree
453          */
454        _addTestCaseToTestTree : function (parentNode /*:TestNode*/, testCase /*:YAHOO.tool.TestCase*/) /*:Void*/{
455             
456             //add the test suite
457             var node = parentNode.appendChild(testCase);
458             
459             //iterate over the items in the test case
460             for (var prop in testCase){
461                 if (prop.indexOf("test") === 0 && YAHOO.lang.isFunction(testCase[prop])){
462                     node.appendChild(prop);
463                 }
464             }
465          
466         },
467         
468         /**
469          * Adds a test suite to the test tree as a child of the specified node.
470          * @param {TestNode} parentNode The node to add the test suite to as a child.
471          * @param {YAHOO.tool.TestSuite} testSuite The test suite to add.
472          * @return {Void}
473          * @static
474          * @private
475          * @method _addTestSuiteToTestTree
476          */
477         _addTestSuiteToTestTree : function (parentNode /*:TestNode*/, testSuite /*:YAHOO.tool.TestSuite*/) /*:Void*/ {
478             
479             //add the test suite
480             var node = parentNode.appendChild(testSuite);
481             
482             //iterate over the items in the master suite
483             for (var i=0; i < testSuite.items.length; i++){
484                 if (testSuite.items[i] instanceof YAHOO.tool.TestSuite) {
485                     this._addTestSuiteToTestTree(node, testSuite.items[i]);
486                 } else if (testSuite.items[i] instanceof YAHOO.tool.TestCase) {
487                     this._addTestCaseToTestTree(node, testSuite.items[i]);
488                 }                   
489             }            
490         },
491         
492         /**
493          * Builds the test tree based on items in the master suite. The tree is a hierarchical
494          * representation of the test suites, test cases, and test functions. The resulting tree
495          * is stored in _root and the pointer _cur is set to the root initially.
496          * @return {Void}
497          * @static
498          * @private
499          * @method _buildTestTree
500          */
501         _buildTestTree : function () /*:Void*/ {
502         
503             this._root = new TestNode(this.masterSuite);
504             this._cur = this._root;
505             
506             //iterate over the items in the master suite
507             for (var i=0; i < this.masterSuite.items.length; i++){
508                 if (this.masterSuite.items[i] instanceof YAHOO.tool.TestSuite) {
509                     this._addTestSuiteToTestTree(this._root, this.masterSuite.items[i]);
510                 } else if (this.masterSuite.items[i] instanceof YAHOO.tool.TestCase) {
511                     this._addTestCaseToTestTree(this._root, this.masterSuite.items[i]);
512                 }                   
513             }            
514         
515         }, 
516     
517         //-------------------------------------------------------------------------
518         // Private Methods
519         //-------------------------------------------------------------------------
520         
521         /**
522          * Handles the completion of a test object's tests. Tallies test results 
523          * from one level up to the next.
524          * @param {TestNode} node The TestNode representing the test object.
525          * @return {Void}
526          * @method _handleTestObjectComplete
527          * @private
528          * @static
529          */
530         _handleTestObjectComplete : function (node /*:TestNode*/) /*:Void*/ {
531             if (YAHOO.lang.isObject(node.testObject)){
532                 node.parent.results.passed += node.results.passed;
533                 node.parent.results.failed += node.results.failed;
534                 node.parent.results.total += node.results.total;                
535                 node.parent.results.ignored += node.results.ignored;                
536                 node.parent.results[node.testObject.name] = node.results;
537             
538                 if (node.testObject instanceof YAHOO.tool.TestSuite){
539                     node.testObject.tearDown();
540                     this.fireEvent(this.TEST_SUITE_COMPLETE_EVENT, { testSuite: node.testObject, results: node.results});
541                 } else if (node.testObject instanceof YAHOO.tool.TestCase){
542                     this.fireEvent(this.TEST_CASE_COMPLETE_EVENT, { testCase: node.testObject, results: node.results});
543                 }      
544             } 
545         },                
546         
547         //-------------------------------------------------------------------------
548         // Navigation Methods
549         //-------------------------------------------------------------------------
550         
551         /**
552          * Retrieves the next node in the test tree.
553          * @return {TestNode} The next node in the test tree or null if the end is reached.
554          * @private
555          * @static
556          * @method _next
557          */
558         _next : function () /*:TestNode*/ {
559         
560             if (this._cur.firstChild) {
561                 this._cur = this._cur.firstChild;
562             } else if (this._cur.next) {
563                 this._cur = this._cur.next;            
564             } else {
565                 while (this._cur && !this._cur.next && this._cur !== this._root){
566                     this._handleTestObjectComplete(this._cur);
567                     this._cur = this._cur.parent;
568                 }
569                 
570                 if (this._cur == this._root){
571                     this._cur.results.type = "report";
572                     this._cur.results.timestamp = (new Date()).toLocaleString();
573                     this._cur.results.duration = (new Date()) - this._cur.results.duration;
574                     this.fireEvent(this.COMPLETE_EVENT, { results: this._cur.results});
575                     this._cur = null;
576                 } else {
577                     this._handleTestObjectComplete(this._cur);               
578                     this._cur = this._cur.next;                
579                 }
580             }
581         
582             return this._cur;
583         },
584         
585         /**
586          * Runs a test case or test suite, returning the results.
587          * @param {YAHOO.tool.TestCase|YAHOO.tool.TestSuite} testObject The test case or test suite to run.
588          * @return {Object} Results of the execution with properties passed, failed, and total.
589          * @private
590          * @method _run
591          * @static
592          */
593         _run : function () /*:Void*/ {
594         
595             //flag to indicate if the TestRunner should wait before continuing
596             var shouldWait /*:Boolean*/ = false;
597             
598             //get the next test node
599             var node = this._next();
600             
601             if (node !== null) {
602                 var testObject = node.testObject;
603                 
604                 //figure out what to do
605                 if (YAHOO.lang.isObject(testObject)){
606                     if (testObject instanceof YAHOO.tool.TestSuite){
607                         this.fireEvent(this.TEST_SUITE_BEGIN_EVENT, { testSuite: testObject });
608                         testObject.setUp();
609                     } else if (testObject instanceof YAHOO.tool.TestCase){
610                         this.fireEvent(this.TEST_CASE_BEGIN_EVENT, { testCase: testObject });
611                     }
612                     
613                     //some environments don't support setTimeout
614                     if (typeof setTimeout != "undefined"){                    
615                         setTimeout(function(){
616                             YAHOO.tool.TestRunner._run();
617                         }, 0);
618                     } else {
619                         this._run();
620                     }
621                 } else {
622                     this._runTest(node);
623                 }
624
625             }
626         },
627         
628         _resumeTest : function (segment /*:Function*/) /*:Void*/ {
629         
630             //get relevant information
631             var node /*:TestNode*/ = this._cur;
632             var testName /*:String*/ = node.testObject;
633             var testCase /*:YAHOO.tool.TestCase*/ = node.parent.testObject;
634             
635             //cancel other waits if available
636             if (testCase.__yui_wait){
637                 clearTimeout(testCase.__yui_wait);
638                 delete testCase.__yui_wait;
639             }            
640             
641             //get the "should" test cases
642             var shouldFail /*:Object*/ = (testCase._should.fail || {})[testName];
643             var shouldError /*:Object*/ = (testCase._should.error || {})[testName];
644             
645             //variable to hold whether or not the test failed
646             var failed /*:Boolean*/ = false;
647             var error /*:Error*/ = null;
648                 
649             //try the test
650             try {
651             
652                 //run the test
653                 segment.apply(testCase);
654                 
655                 //if it should fail, and it got here, then it's a fail because it didn't
656                 if (shouldFail){
657                     error = new YAHOO.util.ShouldFail();
658                     failed = true;
659                 } else if (shouldError){
660                     error = new YAHOO.util.ShouldError();
661                     failed = true;
662                 }
663                            
664             } catch (thrown /*:Error*/){
665                 if (thrown instanceof YAHOO.util.AssertionError) {
666                     if (!shouldFail){
667                         error = thrown;
668                         failed = true;
669                     }
670                 } else if (thrown instanceof YAHOO.tool.TestCase.Wait){
671                 
672                     if (YAHOO.lang.isFunction(thrown.segment)){
673                         if (YAHOO.lang.isNumber(thrown.delay)){
674                         
675                             //some environments don't support setTimeout
676                             if (typeof setTimeout != "undefined"){
677                                 testCase.__yui_wait = setTimeout(function(){
678                                     YAHOO.tool.TestRunner._resumeTest(thrown.segment);
679                                 }, thrown.delay);                             
680                             } else {
681                                 throw new Error("Asynchronous tests not supported in this environment.");
682                             }
683                         }
684                     }
685                     
686                     return;
687                 
688                 } else {
689                     //first check to see if it should error
690                     if (!shouldError) {                        
691                         error = new YAHOO.util.UnexpectedError(thrown);
692                         failed = true;
693                     } else {
694                         //check to see what type of data we have
695                         if (YAHOO.lang.isString(shouldError)){
696                             
697                             //if it's a string, check the error message
698                             if (thrown.message != shouldError){
699                                 error = new YAHOO.util.UnexpectedError(thrown);
700                                 failed = true;                                    
701                             }
702                         } else if (YAHOO.lang.isFunction(shouldError)){
703                         
704                             //if it's a function, see if the error is an instance of it
705                             if (!(thrown instanceof shouldError)){
706                                 error = new YAHOO.util.UnexpectedError(thrown);
707                                 failed = true;
708                             }
709                         
710                         } else if (YAHOO.lang.isObject(shouldError)){
711                         
712                             //if it's an object, check the instance and message
713                             if (!(thrown instanceof shouldError.constructor) || 
714                                     thrown.message != shouldError.message){
715                                 error = new YAHOO.util.UnexpectedError(thrown);
716                                 failed = true;                                    
717                             }
718                         
719                         }
720                     
721                     }
722                 }
723                 
724             }
725             
726             //fireEvent appropriate event
727             if (failed) {
728                 this.fireEvent(this.TEST_FAIL_EVENT, { testCase: testCase, testName: testName, error: error });
729             } else {
730                 this.fireEvent(this.TEST_PASS_EVENT, { testCase: testCase, testName: testName });
731             }
732             
733             //run the tear down
734             testCase.tearDown();
735             
736             //update results
737             node.parent.results[testName] = { 
738                 result: failed ? "fail" : "pass",
739                 message: error ? error.getMessage() : "Test passed",
740                 type: "test",
741                 name: testName
742             };
743             
744             if (failed){
745                 node.parent.results.failed++;
746             } else {
747                 node.parent.results.passed++;
748             }
749             node.parent.results.total++;
750
751             //set timeout not supported in all environments
752             if (typeof setTimeout != "undefined"){
753                 setTimeout(function(){
754                     YAHOO.tool.TestRunner._run();
755                 }, 0);
756             } else {
757                 this._run();
758             }
759         
760         },
761                 
762         /**
763          * Runs a single test based on the data provided in the node.
764          * @param {TestNode} node The TestNode representing the test to run.
765          * @return {Void}
766          * @static
767          * @private
768          * @name _runTest
769          */
770         _runTest : function (node /*:TestNode*/) /*:Void*/ {
771         
772             //get relevant information
773             var testName /*:String*/ = node.testObject;
774             var testCase /*:YAHOO.tool.TestCase*/ = node.parent.testObject;
775             var test /*:Function*/ = testCase[testName];
776             
777             //get the "should" test cases
778             var shouldIgnore /*:Object*/ = (testCase._should.ignore || {})[testName];
779             
780             //figure out if the test should be ignored or not
781             if (shouldIgnore){
782             
783                 //update results
784                 node.parent.results[testName] = { 
785                     result: "ignore",
786                     message: "Test ignored",
787                     type: "test",
788                     name: testName
789                 };
790                 
791                 node.parent.results.ignored++;
792                 node.parent.results.total++;
793             
794                 this.fireEvent(this.TEST_IGNORE_EVENT, { testCase: testCase, testName: testName });
795                 
796                 //some environments don't support setTimeout
797                 if (typeof setTimeout != "undefined"){                    
798                     setTimeout(function(){
799                         YAHOO.tool.TestRunner._run();
800                     }, 0);              
801                 } else {
802                     this._run();
803                 }
804
805             } else {
806             
807                 //run the setup
808                 testCase.setUp();
809                 
810                 //now call the body of the test
811                 this._resumeTest(test);                
812             }
813
814         },        
815         
816         //-------------------------------------------------------------------------
817         // Protected Methods
818         //-------------------------------------------------------------------------   
819     
820         /**
821          * Fires events for the TestRunner. This overrides the default fireEvent()
822          * method from EventProvider to add the type property to the data that is
823          * passed through on each event call.
824          * @param {String} type The type of event to fire.
825          * @param {Object} data (Optional) Data for the event.
826          * @method fireEvent
827          * @static
828          * @protected
829          */
830         fireEvent : function (type /*:String*/, data /*:Object*/) /*:Void*/ {
831             data = data || {};
832             data.type = type;
833             TestRunner.superclass.fireEvent.call(this, type, data);
834         },
835         
836         //-------------------------------------------------------------------------
837         // Public Methods
838         //-------------------------------------------------------------------------   
839     
840         /**
841          * Adds a test suite or test case to the list of test objects to run.
842          * @param testObject Either a TestCase or a TestSuite that should be run.
843          * @return {Void}
844          * @method add
845          * @static
846          */
847         add : function (testObject /*:Object*/) /*:Void*/ {
848             this.masterSuite.add(testObject);
849         },
850         
851         /**
852          * Removes all test objects from the runner.
853          * @return {Void}
854          * @method clear
855          * @static
856          */
857         clear : function () /*:Void*/ {
858             this.masterSuite.items = [];
859         },
860         
861         /**
862          * Resumes the TestRunner after wait() was called.
863          * @param {Function} segment The function to run as the rest
864          *      of the haulted test.
865          * @return {Void}
866          * @method resume
867          * @static
868          */
869         resume : function (segment /*:Function*/) /*:Void*/ {
870             this._resumeTest(segment || function(){});
871         },
872     
873         /**
874          * Runs the test suite.
875          * @return {Void}
876          * @method run
877          * @static
878          */
879         run : function (testObject /*:Object*/) /*:Void*/ {
880             
881             //pointer to runner to avoid scope issues 
882             var runner = YAHOO.tool.TestRunner;
883
884             //build the test tree
885             runner._buildTestTree();
886             
887             //set when the test started
888             runner._root.results.duration = (new Date()).valueOf();
889             
890             //fire the begin event
891             runner.fireEvent(runner.BEGIN_EVENT);
892        
893             //begin the testing
894             runner._run();
895         }    
896     });
897     
898     return new TestRunner();
899     
900 })();
901
902 YAHOO.namespace("util");
903
904 //-----------------------------------------------------------------------------
905 // Assert object
906 //-----------------------------------------------------------------------------
907
908 /**
909  * The Assert object provides functions to test JavaScript values against
910  * known and expected results. Whenever a comparison (assertion) fails,
911  * an error is thrown.
912  *
913  * @namespace YAHOO.util
914  * @class Assert
915  * @static
916  */
917 YAHOO.util.Assert = {
918
919     //-------------------------------------------------------------------------
920     // Helper Methods
921     //-------------------------------------------------------------------------
922     
923     /**
924      * Formats a message so that it can contain the original assertion message
925      * in addition to the custom message.
926      * @param {String} customMessage The message passed in by the developer.
927      * @param {String} defaultMessage The message created by the error by default.
928      * @return {String} The final error message, containing either or both.
929      * @protected
930      * @static
931      * @method _formatMessage
932      */
933     _formatMessage : function (customMessage /*:String*/, defaultMessage /*:String*/) /*:String*/ {
934         var message = customMessage;
935         if (YAHOO.lang.isString(customMessage) && customMessage.length > 0){
936             return YAHOO.lang.substitute(customMessage, { message: defaultMessage });
937         } else {
938             return defaultMessage;
939         }        
940     },
941     
942     //-------------------------------------------------------------------------
943     // Generic Assertion Methods
944     //-------------------------------------------------------------------------
945     
946     /** 
947      * Forces an assertion error to occur.
948      * @param {String} message (Optional) The message to display with the failure.
949      * @method fail
950      * @static
951      */
952     fail : function (message /*:String*/) /*:Void*/ {
953         throw new YAHOO.util.AssertionError(this._formatMessage(message, "Test force-failed."));
954     },       
955     
956     //-------------------------------------------------------------------------
957     // Equality Assertion Methods
958     //-------------------------------------------------------------------------    
959     
960     /**
961      * Asserts that a value is equal to another. This uses the double equals sign
962      * so type cohersion may occur.
963      * @param {Object} expected The expected value.
964      * @param {Object} actual The actual value to test.
965      * @param {String} message (Optional) The message to display if the assertion fails.
966      * @method areEqual
967      * @static
968      */
969     areEqual : function (expected /*:Object*/, actual /*:Object*/, message /*:String*/) /*:Void*/ {
970         if (expected != actual) {
971             throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Values should be equal."), expected, actual);
972         }
973     },
974     
975     /**
976      * Asserts that a value is not equal to another. This uses the double equals sign
977      * so type cohersion may occur.
978      * @param {Object} unexpected The unexpected value.
979      * @param {Object} actual The actual value to test.
980      * @param {String} message (Optional) The message to display if the assertion fails.
981      * @method areNotEqual
982      * @static
983      */
984     areNotEqual : function (unexpected /*:Object*/, actual /*:Object*/, 
985                          message /*:String*/) /*:Void*/ {
986         if (unexpected == actual) {
987             throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Values should not be equal."), unexpected);
988         }
989     },
990     
991     /**
992      * Asserts that a value is not the same as another. This uses the triple equals sign
993      * so no type cohersion may occur.
994      * @param {Object} unexpected The unexpected value.
995      * @param {Object} actual The actual value to test.
996      * @param {String} message (Optional) The message to display if the assertion fails.
997      * @method areNotSame
998      * @static
999      */
1000     areNotSame : function (unexpected /*:Object*/, actual /*:Object*/, message /*:String*/) /*:Void*/ {
1001         if (unexpected === actual) {
1002             throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Values should not be the same."), unexpected);
1003         }
1004     },
1005
1006     /**
1007      * Asserts that a value is the same as another. This uses the triple equals sign
1008      * so no type cohersion may occur.
1009      * @param {Object} expected The expected value.
1010      * @param {Object} actual The actual value to test.
1011      * @param {String} message (Optional) The message to display if the assertion fails.
1012      * @method areSame
1013      * @static
1014      */
1015     areSame : function (expected /*:Object*/, actual /*:Object*/, message /*:String*/) /*:Void*/ {
1016         if (expected !== actual) {
1017             throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Values should be the same."), expected, actual);
1018         }
1019     },    
1020     
1021     //-------------------------------------------------------------------------
1022     // Boolean Assertion Methods
1023     //-------------------------------------------------------------------------    
1024     
1025     /**
1026      * Asserts that a value is false. This uses the triple equals sign
1027      * so no type cohersion may occur.
1028      * @param {Object} actual The actual value to test.
1029      * @param {String} message (Optional) The message to display if the assertion fails.
1030      * @method isFalse
1031      * @static
1032      */
1033     isFalse : function (actual /*:Boolean*/, message /*:String*/) {
1034         if (false !== actual) {
1035             throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value should be false."), false, actual);
1036         }
1037     },
1038     
1039     /**
1040      * Asserts that a value is true. This uses the triple equals sign
1041      * so no type cohersion may occur.
1042      * @param {Object} actual The actual value to test.
1043      * @param {String} message (Optional) The message to display if the assertion fails.
1044      * @method isTrue
1045      * @static
1046      */
1047     isTrue : function (actual /*:Boolean*/, message /*:String*/) /*:Void*/ {
1048         if (true !== actual) {
1049             throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value should be true."), true, actual);
1050         }
1051
1052     },
1053     
1054     //-------------------------------------------------------------------------
1055     // Special Value Assertion Methods
1056     //-------------------------------------------------------------------------    
1057     
1058     /**
1059      * Asserts that a value is not a number.
1060      * @param {Object} actual The value to test.
1061      * @param {String} message (Optional) The message to display if the assertion fails.
1062      * @method isNaN
1063      * @static
1064      */
1065     isNaN : function (actual /*:Object*/, message /*:String*/) /*:Void*/{
1066         if (!isNaN(actual)){
1067             throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value should be NaN."), NaN, actual);
1068         }    
1069     },
1070     
1071     /**
1072      * Asserts that a value is not the special NaN value.
1073      * @param {Object} actual The value to test.
1074      * @param {String} message (Optional) The message to display if the assertion fails.
1075      * @method isNotNaN
1076      * @static
1077      */
1078     isNotNaN : function (actual /*:Object*/, message /*:String*/) /*:Void*/{
1079         if (isNaN(actual)){
1080             throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Values should not be NaN."), NaN);
1081         }    
1082     },
1083     
1084     /**
1085      * Asserts that a value is not null. This uses the triple equals sign
1086      * so no type cohersion may occur.
1087      * @param {Object} actual The actual value to test.
1088      * @param {String} message (Optional) The message to display if the assertion fails.
1089      * @method isNotNull
1090      * @static
1091      */
1092     isNotNull : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
1093         if (YAHOO.lang.isNull(actual)) {
1094             throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Values should not be null."), null);
1095         }
1096     },
1097
1098     /**
1099      * Asserts that a value is not undefined. This uses the triple equals sign
1100      * so no type cohersion may occur.
1101      * @param {Object} actual The actual value to test.
1102      * @param {String} message (Optional) The message to display if the assertion fails.
1103      * @method isNotUndefined
1104      * @static
1105      */
1106     isNotUndefined : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
1107         if (YAHOO.lang.isUndefined(actual)) {
1108             throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should not be undefined."), undefined);
1109         }
1110     },
1111
1112     /**
1113      * Asserts that a value is null. This uses the triple equals sign
1114      * so no type cohersion may occur.
1115      * @param {Object} actual The actual value to test.
1116      * @param {String} message (Optional) The message to display if the assertion fails.
1117      * @method isNull
1118      * @static
1119      */
1120     isNull : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
1121         if (!YAHOO.lang.isNull(actual)) {
1122             throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value should be null."), null, actual);
1123         }
1124     },
1125         
1126     /**
1127      * Asserts that a value is undefined. This uses the triple equals sign
1128      * so no type cohersion may occur.
1129      * @param {Object} actual The actual value to test.
1130      * @param {String} message (Optional) The message to display if the assertion fails.
1131      * @method isUndefined
1132      * @static
1133      */
1134     isUndefined : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
1135         if (!YAHOO.lang.isUndefined(actual)) {
1136             throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value should be undefined."), undefined, actual);
1137         }
1138     },    
1139     
1140     //--------------------------------------------------------------------------
1141     // Instance Assertion Methods
1142     //--------------------------------------------------------------------------    
1143    
1144     /**
1145      * Asserts that a value is an array.
1146      * @param {Object} actual The value to test.
1147      * @param {String} message (Optional) The message to display if the assertion fails.
1148      * @method isArray
1149      * @static
1150      */
1151     isArray : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
1152         if (!YAHOO.lang.isArray(actual)){
1153             throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should be an array."), actual);
1154         }    
1155     },
1156    
1157     /**
1158      * Asserts that a value is a Boolean.
1159      * @param {Object} actual The value to test.
1160      * @param {String} message (Optional) The message to display if the assertion fails.
1161      * @method isBoolean
1162      * @static
1163      */
1164     isBoolean : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
1165         if (!YAHOO.lang.isBoolean(actual)){
1166             throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should be a Boolean."), actual);
1167         }    
1168     },
1169    
1170     /**
1171      * Asserts that a value is a function.
1172      * @param {Object} actual The value to test.
1173      * @param {String} message (Optional) The message to display if the assertion fails.
1174      * @method isFunction
1175      * @static
1176      */
1177     isFunction : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
1178         if (!YAHOO.lang.isFunction(actual)){
1179             throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should be a function."), actual);
1180         }    
1181     },
1182    
1183     /**
1184      * Asserts that a value is an instance of a particular object. This may return
1185      * incorrect results when comparing objects from one frame to constructors in
1186      * another frame. For best results, don't use in a cross-frame manner.
1187      * @param {Function} expected The function that the object should be an instance of.
1188      * @param {Object} actual The object to test.
1189      * @param {String} message (Optional) The message to display if the assertion fails.
1190      * @method isInstanceOf
1191      * @static
1192      */
1193     isInstanceOf : function (expected /*:Function*/, actual /*:Object*/, message /*:String*/) /*:Void*/ {
1194         if (!(actual instanceof expected)){
1195             throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value isn't an instance of expected type."), expected, actual);
1196         }
1197     },
1198     
1199     /**
1200      * Asserts that a value is a number.
1201      * @param {Object} actual The value to test.
1202      * @param {String} message (Optional) The message to display if the assertion fails.
1203      * @method isNumber
1204      * @static
1205      */
1206     isNumber : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
1207         if (!YAHOO.lang.isNumber(actual)){
1208             throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should be a number."), actual);
1209         }    
1210     },    
1211     
1212     /**
1213      * Asserts that a value is an object.
1214      * @param {Object} actual The value to test.
1215      * @param {String} message (Optional) The message to display if the assertion fails.
1216      * @method isObject
1217      * @static
1218      */
1219     isObject : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
1220         if (!YAHOO.lang.isObject(actual)){
1221             throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should be an object."), actual);
1222         }
1223     },
1224     
1225     /**
1226      * Asserts that a value is a string.
1227      * @param {Object} actual The value to test.
1228      * @param {String} message (Optional) The message to display if the assertion fails.
1229      * @method isString
1230      * @static
1231      */
1232     isString : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
1233         if (!YAHOO.lang.isString(actual)){
1234             throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should be a string."), actual);
1235         }
1236     },
1237     
1238     /**
1239      * Asserts that a value is of a particular type. 
1240      * @param {String} expectedType The expected type of the variable.
1241      * @param {Object} actualValue The actual value to test.
1242      * @param {String} message (Optional) The message to display if the assertion fails.
1243      * @method isTypeOf
1244      * @static
1245      */
1246     isTypeOf : function (expectedType /*:String*/, actualValue /*:Object*/, message /*:String*/) /*:Void*/{
1247         if (typeof actualValue != expectedType){
1248             throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value should be of type " + expected + "."), expected, typeof actual);
1249         }
1250     }
1251 };
1252
1253 //-----------------------------------------------------------------------------
1254 // Assertion errors
1255 //-----------------------------------------------------------------------------
1256
1257 /**
1258  * AssertionError is thrown whenever an assertion fails. It provides methods
1259  * to more easily get at error information and also provides a base class
1260  * from which more specific assertion errors can be derived.
1261  *
1262  * @param {String} message The message to display when the error occurs.
1263  * @namespace YAHOO.util
1264  * @class AssertionError
1265  * @extends Error
1266  * @constructor
1267  */ 
1268 YAHOO.util.AssertionError = function (message /*:String*/){
1269
1270     //call superclass
1271     arguments.callee.superclass.constructor.call(this, message);
1272     
1273     /*
1274      * Error message. Must be duplicated to ensure browser receives it.
1275      * @type String
1276      * @property message
1277      */
1278     this.message /*:String*/ = message;
1279     
1280     /**
1281      * The name of the error that occurred.
1282      * @type String
1283      * @property name
1284      */
1285     this.name /*:String*/ = "AssertionError";
1286 };
1287
1288 //inherit methods
1289 YAHOO.lang.extend(YAHOO.util.AssertionError, Error, {
1290
1291     /**
1292      * Returns a fully formatted error for an assertion failure. This should
1293      * be overridden by all subclasses to provide specific information.
1294      * @method getMessage
1295      * @return {String} A string describing the error.
1296      */
1297     getMessage : function () /*:String*/ {
1298         return this.message;
1299     },
1300     
1301     /**
1302      * Returns a string representation of the error.
1303      * @method toString
1304      * @return {String} A string representation of the error.
1305      */
1306     toString : function () /*:String*/ {
1307         return this.name + ": " + this.getMessage();
1308     },
1309     
1310     /**
1311      * Returns a primitive value version of the error. Same as toString().
1312      * @method valueOf
1313      * @return {String} A primitive value version of the error.
1314      */
1315     valueOf : function () /*:String*/ {
1316         return this.toString();
1317     }
1318
1319 });
1320
1321 /**
1322  * ComparisonFailure is subclass of AssertionError that is thrown whenever
1323  * a comparison between two values fails. It provides mechanisms to retrieve
1324  * both the expected and actual value.
1325  *
1326  * @param {String} message The message to display when the error occurs.
1327  * @param {Object} expected The expected value.
1328  * @param {Object} actual The actual value that caused the assertion to fail.
1329  * @namespace YAHOO.util
1330  * @extends YAHOO.util.AssertionError
1331  * @class ComparisonFailure
1332  * @constructor
1333  */ 
1334 YAHOO.util.ComparisonFailure = function (message /*:String*/, expected /*:Object*/, actual /*:Object*/){
1335
1336     //call superclass
1337     arguments.callee.superclass.constructor.call(this, message);
1338     
1339     /**
1340      * The expected value.
1341      * @type Object
1342      * @property expected
1343      */
1344     this.expected /*:Object*/ = expected;
1345     
1346     /**
1347      * The actual value.
1348      * @type Object
1349      * @property actual
1350      */
1351     this.actual /*:Object*/ = actual;
1352     
1353     /**
1354      * The name of the error that occurred.
1355      * @type String
1356      * @property name
1357      */
1358     this.name /*:String*/ = "ComparisonFailure";
1359     
1360 };
1361
1362 //inherit methods
1363 YAHOO.lang.extend(YAHOO.util.ComparisonFailure, YAHOO.util.AssertionError, {
1364
1365     /**
1366      * Returns a fully formatted error for an assertion failure. This message
1367      * provides information about the expected and actual values.
1368      * @method toString
1369      * @return {String} A string describing the error.
1370      */
1371     getMessage : function () /*:String*/ {
1372         return this.message + "\nExpected: " + this.expected + " (" + (typeof this.expected) + ")"  +
1373             "\nActual:" + this.actual + " (" + (typeof this.actual) + ")";
1374     }
1375
1376 });
1377
1378 /**
1379  * UnexpectedValue is subclass of AssertionError that is thrown whenever
1380  * a value was unexpected in its scope. This typically means that a test
1381  * was performed to determine that a value was *not* equal to a certain
1382  * value.
1383  *
1384  * @param {String} message The message to display when the error occurs.
1385  * @param {Object} unexpected The unexpected value.
1386  * @namespace YAHOO.util
1387  * @extends YAHOO.util.AssertionError
1388  * @class UnexpectedValue
1389  * @constructor
1390  */ 
1391 YAHOO.util.UnexpectedValue = function (message /*:String*/, unexpected /*:Object*/){
1392
1393     //call superclass
1394     arguments.callee.superclass.constructor.call(this, message);
1395     
1396     /**
1397      * The unexpected value.
1398      * @type Object
1399      * @property unexpected
1400      */
1401     this.unexpected /*:Object*/ = unexpected;
1402     
1403     /**
1404      * The name of the error that occurred.
1405      * @type String
1406      * @property name
1407      */
1408     this.name /*:String*/ = "UnexpectedValue";
1409     
1410 };
1411
1412 //inherit methods
1413 YAHOO.lang.extend(YAHOO.util.UnexpectedValue, YAHOO.util.AssertionError, {
1414
1415     /**
1416      * Returns a fully formatted error for an assertion failure. The message
1417      * contains information about the unexpected value that was encountered.
1418      * @method getMessage
1419      * @return {String} A string describing the error.
1420      */
1421     getMessage : function () /*:String*/ {
1422         return this.message + "\nUnexpected: " + this.unexpected + " (" + (typeof this.unexpected) + ") ";
1423     }
1424
1425 });
1426
1427 /**
1428  * ShouldFail is subclass of AssertionError that is thrown whenever
1429  * a test was expected to fail but did not.
1430  *
1431  * @param {String} message The message to display when the error occurs.
1432  * @namespace YAHOO.util
1433  * @extends YAHOO.util.AssertionError
1434  * @class ShouldFail
1435  * @constructor
1436  */  
1437 YAHOO.util.ShouldFail = function (message /*:String*/){
1438
1439     //call superclass
1440     arguments.callee.superclass.constructor.call(this, message || "This test should fail but didn't.");
1441     
1442     /**
1443      * The name of the error that occurred.
1444      * @type String
1445      * @property name
1446      */
1447     this.name /*:String*/ = "ShouldFail";
1448     
1449 };
1450
1451 //inherit methods
1452 YAHOO.lang.extend(YAHOO.util.ShouldFail, YAHOO.util.AssertionError);
1453
1454 /**
1455  * ShouldError is subclass of AssertionError that is thrown whenever
1456  * a test is expected to throw an error but doesn't.
1457  *
1458  * @param {String} message The message to display when the error occurs.
1459  * @namespace YAHOO.util
1460  * @extends YAHOO.util.AssertionError
1461  * @class ShouldError
1462  * @constructor
1463  */  
1464 YAHOO.util.ShouldError = function (message /*:String*/){
1465
1466     //call superclass
1467     arguments.callee.superclass.constructor.call(this, message || "This test should have thrown an error but didn't.");
1468     
1469     /**
1470      * The name of the error that occurred.
1471      * @type String
1472      * @property name
1473      */
1474     this.name /*:String*/ = "ShouldError";
1475     
1476 };
1477
1478 //inherit methods
1479 YAHOO.lang.extend(YAHOO.util.ShouldError, YAHOO.util.AssertionError);
1480
1481 /**
1482  * UnexpectedError is subclass of AssertionError that is thrown whenever
1483  * an error occurs within the course of a test and the test was not expected
1484  * to throw an error.
1485  *
1486  * @param {Error} cause The unexpected error that caused this error to be 
1487  *                      thrown.
1488  * @namespace YAHOO.util
1489  * @extends YAHOO.util.AssertionError
1490  * @class UnexpectedError
1491  * @constructor
1492  */  
1493 YAHOO.util.UnexpectedError = function (cause /*:Object*/){
1494
1495     //call superclass
1496     arguments.callee.superclass.constructor.call(this, "Unexpected error: " + cause.message);
1497     
1498     /**
1499      * The unexpected error that occurred.
1500      * @type Error
1501      * @property cause
1502      */
1503     this.cause /*:Error*/ = cause;
1504     
1505     /**
1506      * The name of the error that occurred.
1507      * @type String
1508      * @property name
1509      */
1510     this.name /*:String*/ = "UnexpectedError";
1511     
1512     /**
1513      * Stack information for the error (if provided).
1514      * @type String
1515      * @property stack
1516      */
1517     this.stack /*:String*/ = cause.stack;
1518     
1519 };
1520
1521 //inherit methods
1522 YAHOO.lang.extend(YAHOO.util.UnexpectedError, YAHOO.util.AssertionError);
1523
1524 //-----------------------------------------------------------------------------
1525 // ArrayAssert object
1526 //-----------------------------------------------------------------------------
1527
1528 /**
1529  * The ArrayAssert object provides functions to test JavaScript array objects
1530  * for a variety of cases.
1531  *
1532  * @namespace YAHOO.util
1533  * @class ArrayAssert
1534  * @static
1535  */
1536  
1537 YAHOO.util.ArrayAssert = {
1538
1539     /**
1540      * Asserts that a value is present in an array. This uses the triple equals 
1541      * sign so no type cohersion may occur.
1542      * @param {Object} needle The value that is expected in the array.
1543      * @param {Array} haystack An array of values.
1544      * @param {String} message (Optional) The message to display if the assertion fails.
1545      * @method contains
1546      * @static
1547      */
1548     contains : function (needle /*:Object*/, haystack /*:Array*/, 
1549                            message /*:String*/) /*:Void*/ {
1550         
1551         var found /*:Boolean*/ = false;
1552         var Assert = YAHOO.util.Assert;
1553         
1554         //begin checking values
1555         for (var i=0; i < haystack.length && !found; i++){
1556             if (haystack[i] === needle) {
1557                 found = true;
1558             }
1559         }
1560         
1561         if (!found){
1562             Assert.fail(Assert._formatMessage(message, "Value " + needle + " (" + (typeof needle) + ") not found in array [" + haystack + "]."));
1563         }
1564     },
1565
1566     /**
1567      * Asserts that a set of values are present in an array. This uses the triple equals 
1568      * sign so no type cohersion may occur. For this assertion to pass, all values must
1569      * be found.
1570      * @param {Object[]} needles An array of values that are expected in the array.
1571      * @param {Array} haystack An array of values to check.
1572      * @param {String} message (Optional) The message to display if the assertion fails.
1573      * @method containsItems
1574      * @static
1575      */
1576     containsItems : function (needles /*:Object[]*/, haystack /*:Array*/, 
1577                            message /*:String*/) /*:Void*/ {
1578
1579         //begin checking values
1580         for (var i=0; i < needles.length; i++){
1581             this.contains(needles[i], haystack, message);
1582         }
1583     },
1584
1585     /**
1586      * Asserts that a value matching some condition is present in an array. This uses
1587      * a function to determine a match.
1588      * @param {Function} matcher A function that returns true if the items matches or false if not.
1589      * @param {Array} haystack An array of values.
1590      * @param {String} message (Optional) The message to display if the assertion fails.
1591      * @method containsMatch
1592      * @static
1593      */
1594     containsMatch : function (matcher /*:Function*/, haystack /*:Array*/, 
1595                            message /*:String*/) /*:Void*/ {
1596         
1597         //check for valid matcher
1598         if (typeof matcher != "function"){
1599             throw new TypeError("ArrayAssert.containsMatch(): First argument must be a function.");
1600         }
1601         
1602         var found /*:Boolean*/ = false;
1603         var Assert = YAHOO.util.Assert;
1604         
1605         //begin checking values
1606         for (var i=0; i < haystack.length && !found; i++){
1607             if (matcher(haystack[i])) {
1608                 found = true;
1609             }
1610         }
1611         
1612         if (!found){
1613             Assert.fail(Assert._formatMessage(message, "No match found in array [" + haystack + "]."));
1614         }
1615     },
1616
1617     /**
1618      * Asserts that a value is not present in an array. This uses the triple equals 
1619      * sign so no type cohersion may occur.
1620      * @param {Object} needle The value that is expected in the array.
1621      * @param {Array} haystack An array of values.
1622      * @param {String} message (Optional) The message to display if the assertion fails.
1623      * @method doesNotContain
1624      * @static
1625      */
1626     doesNotContain : function (needle /*:Object*/, haystack /*:Array*/, 
1627                            message /*:String*/) /*:Void*/ {
1628         
1629         var found /*:Boolean*/ = false;
1630         var Assert = YAHOO.util.Assert;
1631         
1632         //begin checking values
1633         for (var i=0; i < haystack.length && !found; i++){
1634             if (haystack[i] === needle) {
1635                 found = true;
1636             }
1637         }
1638         
1639         if (found){
1640             Assert.fail(Assert._formatMessage(message, "Value found in array [" + haystack + "]."));
1641         }
1642     },
1643
1644     /**
1645      * Asserts that a set of values are not present in an array. This uses the triple equals 
1646      * sign so no type cohersion may occur. For this assertion to pass, all values must
1647      * not be found.
1648      * @param {Object[]} needles An array of values that are not expected in the array.
1649      * @param {Array} haystack An array of values to check.
1650      * @param {String} message (Optional) The message to display if the assertion fails.
1651      * @method doesNotContainItems
1652      * @static
1653      */
1654     doesNotContainItems : function (needles /*:Object[]*/, haystack /*:Array*/, 
1655                            message /*:String*/) /*:Void*/ {
1656
1657         for (var i=0; i < needles.length; i++){
1658             this.doesNotContain(needles[i], haystack, message);
1659         }
1660
1661     },
1662         
1663     /**
1664      * Asserts that no values matching a condition are present in an array. This uses
1665      * a function to determine a match.
1666      * @param {Function} matcher A function that returns true if the items matches or false if not.
1667      * @param {Array} haystack An array of values.
1668      * @param {String} message (Optional) The message to display if the assertion fails.
1669      * @method doesNotContainMatch
1670      * @static
1671      */
1672     doesNotContainMatch : function (matcher /*:Function*/, haystack /*:Array*/, 
1673                            message /*:String*/) /*:Void*/ {
1674         
1675         //check for valid matcher
1676         if (typeof matcher != "function"){
1677             throw new TypeError("ArrayAssert.doesNotContainMatch(): First argument must be a function.");
1678         }
1679
1680         var found /*:Boolean*/ = false;
1681         var Assert = YAHOO.util.Assert;
1682         
1683         //begin checking values
1684         for (var i=0; i < haystack.length && !found; i++){
1685             if (matcher(haystack[i])) {
1686                 found = true;
1687             }
1688         }
1689         
1690         if (found){
1691             Assert.fail(Assert._formatMessage(message, "Value found in array [" + haystack + "]."));
1692         }
1693     },
1694         
1695     /**
1696      * Asserts that the given value is contained in an array at the specified index.
1697      * This uses the triple equals sign so no type cohersion will occur.
1698      * @param {Object} needle The value to look for.
1699      * @param {Array} haystack The array to search in.
1700      * @param {int} index The index at which the value should exist.
1701      * @param {String} message (Optional) The message to display if the assertion fails.
1702      * @method indexOf
1703      * @static
1704      */
1705     indexOf : function (needle /*:Object*/, haystack /*:Array*/, index /*:int*/, message /*:String*/) /*:Void*/ {
1706     
1707         //try to find the value in the array
1708         for (var i=0; i < haystack.length; i++){
1709             if (haystack[i] === needle){
1710                 YAHOO.util.Assert.areEqual(index, i, message || "Value exists at index " + i + " but should be at index " + index + ".");
1711                 return;
1712             }
1713         }
1714         
1715         var Assert = YAHOO.util.Assert;
1716         
1717         //if it makes it here, it wasn't found at all
1718         Assert.fail(Assert._formatMessage(message, "Value doesn't exist in array [" + haystack + "]."));
1719     },
1720         
1721     /**
1722      * Asserts that the values in an array are equal, and in the same position,
1723      * as values in another array. This uses the double equals sign
1724      * so type cohersion may occur. Note that the array objects themselves
1725      * need not be the same for this test to pass.
1726      * @param {Array} expected An array of the expected values.
1727      * @param {Array} actual Any array of the actual values.
1728      * @param {String} message (Optional) The message to display if the assertion fails.
1729      * @method itemsAreEqual
1730      * @static
1731      */
1732     itemsAreEqual : function (expected /*:Array*/, actual /*:Array*/, 
1733                            message /*:String*/) /*:Void*/ {
1734         
1735         //one may be longer than the other, so get the maximum length
1736         var len /*:int*/ = Math.max(expected.length, actual.length);
1737         var Assert = YAHOO.util.Assert;
1738        
1739         //begin checking values
1740         for (var i=0; i < len; i++){
1741             Assert.areEqual(expected[i], actual[i], 
1742                 Assert._formatMessage(message, "Values in position " + i + " are not equal."));
1743         }
1744     },
1745     
1746     /**
1747      * Asserts that the values in an array are equivalent, and in the same position,
1748      * as values in another array. This uses a function to determine if the values
1749      * are equivalent. Note that the array objects themselves
1750      * need not be the same for this test to pass.
1751      * @param {Array} expected An array of the expected values.
1752      * @param {Array} actual Any array of the actual values.
1753      * @param {Function} comparator A function that returns true if the values are equivalent
1754      *      or false if not.
1755      * @param {String} message (Optional) The message to display if the assertion fails.
1756      * @return {Void}
1757      * @method itemsAreEquivalent
1758      * @static
1759      */
1760     itemsAreEquivalent : function (expected /*:Array*/, actual /*:Array*/, 
1761                            comparator /*:Function*/, message /*:String*/) /*:Void*/ {
1762         
1763         //make sure the comparator is valid
1764         if (typeof comparator != "function"){
1765             throw new TypeError("ArrayAssert.itemsAreEquivalent(): Third argument must be a function.");
1766         }
1767         
1768         //one may be longer than the other, so get the maximum length
1769         var len /*:int*/ = Math.max(expected.length, actual.length);
1770         
1771         //begin checking values
1772         for (var i=0; i < len; i++){
1773             if (!comparator(expected[i], actual[i])){
1774                 throw new YAHOO.util.ComparisonFailure(YAHOO.util.Assert._formatMessage(message, "Values in position " + i + " are not equivalent."), expected[i], actual[i]);
1775             }
1776         }
1777     },
1778     
1779     /**
1780      * Asserts that an array is empty.
1781      * @param {Array} actual The array to test.
1782      * @param {String} message (Optional) The message to display if the assertion fails.
1783      * @method isEmpty
1784      * @static
1785      */
1786     isEmpty : function (actual /*:Array*/, message /*:String*/) /*:Void*/ {        
1787         if (actual.length > 0){
1788             var Assert = YAHOO.util.Assert;
1789             Assert.fail(Assert._formatMessage(message, "Array should be empty."));
1790         }
1791     },    
1792     
1793     /**
1794      * Asserts that an array is not empty.
1795      * @param {Array} actual The array to test.
1796      * @param {String} message (Optional) The message to display if the assertion fails.
1797      * @method isNotEmpty
1798      * @static
1799      */
1800     isNotEmpty : function (actual /*:Array*/, message /*:String*/) /*:Void*/ {        
1801         if (actual.length === 0){
1802             var Assert = YAHOO.util.Assert;
1803             Assert.fail(Assert._formatMessage(message, "Array should not be empty."));
1804         }
1805     },    
1806     
1807     /**
1808      * Asserts that the values in an array are the same, and in the same position,
1809      * as values in another array. This uses the triple equals sign
1810      * so no type cohersion will occur. Note that the array objects themselves
1811      * need not be the same for this test to pass.
1812      * @param {Array} expected An array of the expected values.
1813      * @param {Array} actual Any array of the actual values.
1814      * @param {String} message (Optional) The message to display if the assertion fails.
1815      * @method itemsAreSame
1816      * @static
1817      */
1818     itemsAreSame : function (expected /*:Array*/, actual /*:Array*/, 
1819                           message /*:String*/) /*:Void*/ {
1820         
1821         //one may be longer than the other, so get the maximum length
1822         var len /*:int*/ = Math.max(expected.length, actual.length);
1823         var Assert = YAHOO.util.Assert;
1824         
1825         //begin checking values
1826         for (var i=0; i < len; i++){
1827             Assert.areSame(expected[i], actual[i], 
1828                 Assert._formatMessage(message, "Values in position " + i + " are not the same."));
1829         }
1830     },
1831     
1832     /**
1833      * Asserts that the given value is contained in an array at the specified index,
1834      * starting from the back of the array.
1835      * This uses the triple equals sign so no type cohersion will occur.
1836      * @param {Object} needle The value to look for.
1837      * @param {Array} haystack The array to search in.
1838      * @param {int} index The index at which the value should exist.
1839      * @param {String} message (Optional) The message to display if the assertion fails.
1840      * @method lastIndexOf
1841      * @static
1842      */
1843     lastIndexOf : function (needle /*:Object*/, haystack /*:Array*/, index /*:int*/, message /*:String*/) /*:Void*/ {
1844     
1845         var Assert = YAHOO.util.Assert;
1846     
1847         //try to find the value in the array
1848         for (var i=haystack.length; i >= 0; i--){
1849             if (haystack[i] === needle){
1850                 Assert.areEqual(index, i, Assert._formatMessage(message, "Value exists at index " + i + " but should be at index " + index + "."));
1851                 return;
1852             }
1853         }
1854         
1855         //if it makes it here, it wasn't found at all
1856         Assert.fail(Assert._formatMessage(message, "Value doesn't exist in array."));        
1857     }
1858     
1859 };
1860
1861 YAHOO.namespace("util");
1862
1863
1864 //-----------------------------------------------------------------------------
1865 // ObjectAssert object
1866 //-----------------------------------------------------------------------------
1867
1868 /**
1869  * The ObjectAssert object provides functions to test JavaScript objects
1870  * for a variety of cases.
1871  *
1872  * @namespace YAHOO.util
1873  * @class ObjectAssert
1874  * @static
1875  */
1876 YAHOO.util.ObjectAssert = {
1877         
1878     /**
1879      * Asserts that all properties in the object exist in another object.
1880      * @param {Object} expected An object with the expected properties.
1881      * @param {Object} actual An object with the actual properties.
1882      * @param {String} message (Optional) The message to display if the assertion fails.
1883      * @method propertiesAreEqual
1884      * @static
1885      */
1886     propertiesAreEqual : function (expected /*:Object*/, actual /*:Object*/, 
1887                            message /*:String*/) /*:Void*/ {
1888         
1889         var Assert = YAHOO.util.Assert;
1890         
1891         //get all properties in the object
1892         var properties /*:Array*/ = [];        
1893         for (var property in expected){
1894             properties.push(property);
1895         }
1896         
1897         //see if the properties are in the expected object
1898         for (var i=0; i < properties.length; i++){
1899             Assert.isNotUndefined(actual[properties[i]], 
1900                 Assert._formatMessage(message, "Property '" + properties[i] + "' expected."));
1901         }
1902
1903     },
1904     
1905     /**
1906      * Asserts that an object has a property with the given name.
1907      * @param {String} propertyName The name of the property to test.
1908      * @param {Object} object The object to search.
1909      * @param {String} message (Optional) The message to display if the assertion fails.
1910      * @method hasProperty
1911      * @static
1912      */    
1913     hasProperty : function (propertyName /*:String*/, object /*:Object*/, message /*:String*/) /*:Void*/ {
1914         if (!(propertyName in object)){
1915             var Assert = YAHOO.util.Assert;
1916             Assert.fail(Assert._formatMessage(message, "Property '" + propertyName + "' not found on object."));
1917         }    
1918     },
1919     
1920     /**
1921      * Asserts that a property with the given name exists on an object instance (not on its prototype).
1922      * @param {String} propertyName The name of the property to test.
1923      * @param {Object} object The object to search.
1924      * @param {String} message (Optional) The message to display if the assertion fails.
1925      * @method hasProperty
1926      * @static
1927      */    
1928     hasOwnProperty : function (propertyName /*:String*/, object /*:Object*/, message /*:String*/) /*:Void*/ {
1929         if (!YAHOO.lang.hasOwnProperty(object, propertyName)){
1930             var Assert = YAHOO.util.Assert;
1931             Assert.fail(Assert._formatMessage(message, "Property '" + propertyName + "' not found on object instance."));
1932         }     
1933     }
1934 };
1935
1936 //-----------------------------------------------------------------------------
1937 // DateAssert object
1938 //-----------------------------------------------------------------------------
1939
1940 /**
1941  * The DateAssert object provides functions to test JavaScript Date objects
1942  * for a variety of cases.
1943  *
1944  * @namespace YAHOO.util
1945  * @class DateAssert
1946  * @static
1947  */
1948  
1949 YAHOO.util.DateAssert = {
1950
1951     /**
1952      * Asserts that a date's month, day, and year are equal to another date's.
1953      * @param {Date} expected The expected date.
1954      * @param {Date} actual The actual date to test.
1955      * @param {String} message (Optional) The message to display if the assertion fails.
1956      * @method datesAreEqual
1957      * @static
1958      */
1959     datesAreEqual : function (expected /*:Date*/, actual /*:Date*/, message /*:String*/){
1960         if (expected instanceof Date && actual instanceof Date){
1961             var Assert = YAHOO.util.Assert;
1962             Assert.areEqual(expected.getFullYear(), actual.getFullYear(), Assert._formatMessage(message, "Years should be equal."));
1963             Assert.areEqual(expected.getMonth(), actual.getMonth(), Assert._formatMessage(message, "Months should be equal."));
1964             Assert.areEqual(expected.getDate(), actual.getDate(), Assert._formatMessage(message, "Day of month should be equal."));
1965         } else {
1966             throw new TypeError("DateAssert.datesAreEqual(): Expected and actual values must be Date objects.");
1967         }
1968     },
1969
1970     /**
1971      * Asserts that a date's hour, minutes, and seconds are equal to another date's.
1972      * @param {Date} expected The expected date.
1973      * @param {Date} actual The actual date to test.
1974      * @param {String} message (Optional) The message to display if the assertion fails.
1975      * @method timesAreEqual
1976      * @static
1977      */
1978     timesAreEqual : function (expected /*:Date*/, actual /*:Date*/, message /*:String*/){
1979         if (expected instanceof Date && actual instanceof Date){
1980             var Assert = YAHOO.util.Assert;
1981             Assert.areEqual(expected.getHours(), actual.getHours(), Assert._formatMessage(message, "Hours should be equal."));
1982             Assert.areEqual(expected.getMinutes(), actual.getMinutes(), Assert._formatMessage(message, "Minutes should be equal."));
1983             Assert.areEqual(expected.getSeconds(), actual.getSeconds(), Assert._formatMessage(message, "Seconds should be equal."));
1984         } else {
1985             throw new TypeError("DateAssert.timesAreEqual(): Expected and actual values must be Date objects.");
1986         }
1987     }
1988     
1989 };
1990
1991 YAHOO.register("yuitest_core", YAHOO.tool.TestRunner, {version: "2.7.0", build: "1799"});