~loggerhead-team/loggerhead/trunk-rich

« back to all changes in this revision

Viewing changes to loggerhead/static/javascript/yui/build/yuitest/yuitest-debug.js

[rs=thumper] merge loggerhead trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
 
3
Code licensed under the BSD License:
 
4
http://developer.yahoo.net/yui/license.txt
 
5
version: 3.0.0pr2
 
6
*/
 
7
YUI.add('yuitest', function(Y) {
 
8
 
 
9
    /**
 
10
     * YUI JavaScript Testing Framework
 
11
     *
 
12
     * @module yuitest
 
13
     */
 
14
 
 
15
    
 
16
    Y.namespace("Test");
 
17
    
 
18
    /**
 
19
     * Test case containing various tests to run.
 
20
     * @param template An object containing any number of test methods, other methods,
 
21
     *                 an optional name, and anything else the test case needs.
 
22
     * @class Case
 
23
     * @namespace Test
 
24
     * @constructor
 
25
     */
 
26
    Y.Test.Case = function (template /*:Object*/) {
 
27
        
 
28
        /**
 
29
         * Special rules for the test case. Possible subobjects
 
30
         * are fail, for tests that should fail, and error, for
 
31
         * tests that should throw an error.
 
32
         */
 
33
        this._should /*:Object*/ = {};
 
34
        
 
35
        //copy over all properties from the template to this object
 
36
        for (var prop in template) {
 
37
            this[prop] = template[prop];
 
38
        }    
 
39
        
 
40
        //check for a valid name
 
41
        if (!Y.Lang.isString(this.name)){
 
42
            /**
 
43
             * Name for the test case.
 
44
             */
 
45
            this.name /*:String*/ = "testCase" + Y.guid();
 
46
        }
 
47
    
 
48
    };
 
49
            
 
50
    Y.Test.Case.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
            Y.Test.Runner.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 (Y.Lang.isFunction(args[0])){
 
76
                throw new Y.Test.Wait(args[0], args[1]);
 
77
            } else {
 
78
                throw new Y.Test.Wait(function(){
 
79
                    Y.Assert.fail("Timeout: wait() called but resume() never called.");
 
80
                }, (Y.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 Test
 
112
     * @constructor
 
113
     *
 
114
     */
 
115
    Y.Test.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*/ = (Y.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*/ = (Y.Lang.isNumber(delay) ? delay : 0);        
 
130
    };
 
131
 
 
132
 
 
133
        
 
134
    Y.namespace("Test");
 
135
    
 
136
    /**
 
137
     * A test suite that can contain a collection of TestCase and TestSuite objects.
 
138
     * @param {String||Object} data The name of the test suite or an object containing
 
139
     *      a name property as well as setUp and tearDown methods.
 
140
     * @namespace Test
 
141
     * @class Suite
 
142
     * @constructor
 
143
     */
 
144
    Y.Test.Suite = function (data /*:String||Object*/) {
 
145
    
 
146
        /**
 
147
         * The name of the test suite.
 
148
         * @type String
 
149
         * @property name
 
150
         */
 
151
        this.name /*:String*/ = "";
 
152
    
 
153
        /**
 
154
         * Array of test suites and
 
155
         * @private
 
156
         */
 
157
        this.items /*:Array*/ = [];
 
158
    
 
159
        //initialize the properties
 
160
        if (Y.Lang.isString(data)){
 
161
            this.name = data;
 
162
        } else if (Y.Lang.isObject(data)){
 
163
            Y.mix(this, data, true);
 
164
        }
 
165
    
 
166
        //double-check name
 
167
        if (this.name === ""){
 
168
            this.name = "testSuite" + Y.guid();
 
169
        }
 
170
    
 
171
    };
 
172
    
 
173
    Y.Test.Suite.prototype = {
 
174
        
 
175
        /**
 
176
         * Adds a test suite or test case to the test suite.
 
177
         * @param {Y.Test.Suite||Y.Test.Case} testObject The test suite or test case to add.
 
178
         * @return {Void}
 
179
         * @method add
 
180
         */
 
181
        add : function (testObject /*:Y.Test.Suite*/) /*:Void*/ {
 
182
            if (testObject instanceof Y.Test.Suite || testObject instanceof Y.Test.Case) {
 
183
                this.items.push(testObject);
 
184
            }
 
185
        },
 
186
        
 
187
        //-------------------------------------------------------------------------
 
188
        // Stub Methods
 
189
        //-------------------------------------------------------------------------
 
190
    
 
191
        /**
 
192
         * Function to run before each test is executed.
 
193
         * @return {Void}
 
194
         * @method setUp
 
195
         */
 
196
        setUp : function () /*:Void*/ {
 
197
        },
 
198
        
 
199
        /**
 
200
         * Function to run after each test is executed.
 
201
         * @return {Void}
 
202
         * @method tearDown
 
203
         */
 
204
        tearDown: function () /*:Void*/ {
 
205
        }
 
206
        
 
207
    };
 
208
 
 
209
    
 
210
    /*
 
211
     * Runs test suites and test cases, providing events to allowing for the
 
212
     * interpretation of test results.
 
213
     * @namespace Test
 
214
     * @class Runner
 
215
     * @static
 
216
     */
 
217
    Y.Test.Runner = (function(){
 
218
    
 
219
        /**
 
220
         * A node in the test tree structure. May represent a TestSuite, TestCase, or
 
221
         * test function.
 
222
         * @param {Variant} testObject A TestSuite, TestCase, or the name of a test function.
 
223
         * @class TestNode
 
224
         * @constructor
 
225
         * @private
 
226
         */
 
227
        function TestNode(testObject /*:Variant*/){
 
228
        
 
229
            /**
 
230
             * The TestSuite, TestCase, or test function represented by this node.
 
231
             * @type Variant
 
232
             * @property testObject
 
233
             */
 
234
            this.testObject = testObject;
 
235
            
 
236
            /**
 
237
             * Pointer to this node's first child.
 
238
             * @type TestNode
 
239
             * @property firstChild
 
240
             */        
 
241
            this.firstChild /*:TestNode*/ = null;
 
242
            
 
243
            /**
 
244
             * Pointer to this node's last child.
 
245
             * @type TestNode
 
246
             * @property lastChild
 
247
             */        
 
248
            this.lastChild = null;
 
249
            
 
250
            /**
 
251
             * Pointer to this node's parent.
 
252
             * @type TestNode
 
253
             * @property parent
 
254
             */        
 
255
            this.parent = null; 
 
256
       
 
257
            /**
 
258
             * Pointer to this node's next sibling.
 
259
             * @type TestNode
 
260
             * @property next
 
261
             */        
 
262
            this.next = null;
 
263
            
 
264
            /**
 
265
             * Test results for this test object.
 
266
             * @type object
 
267
             * @property results
 
268
             */                
 
269
            this.results /*:Object*/ = {
 
270
                passed : 0,
 
271
                failed : 0,
 
272
                total : 0,
 
273
                ignored : 0
 
274
            };
 
275
            
 
276
            //initialize results
 
277
            if (testObject instanceof Y.Test.Suite){
 
278
                this.results.type = "testsuite";
 
279
                this.results.name = testObject.name;
 
280
            } else if (testObject instanceof Y.Test.Case){
 
281
                this.results.type = "testcase";
 
282
                this.results.name = testObject.name;
 
283
            }
 
284
           
 
285
        }
 
286
        
 
287
        TestNode.prototype = {
 
288
        
 
289
            /**
 
290
             * Appends a new test object (TestSuite, TestCase, or test function name) as a child
 
291
             * of this node.
 
292
             * @param {Variant} testObject A TestSuite, TestCase, or the name of a test function.
 
293
             * @return {Void}
 
294
             */
 
295
            appendChild : function (testObject /*:Variant*/) /*:Void*/{
 
296
                var node = new TestNode(testObject);
 
297
                if (this.firstChild === null){
 
298
                    this.firstChild = this.lastChild = node;
 
299
                } else {
 
300
                    this.lastChild.next = node;
 
301
                    this.lastChild = node;
 
302
                }
 
303
                node.parent = this;
 
304
                return node;
 
305
            }       
 
306
        };
 
307
    
 
308
        /**
 
309
         * Runs test suites and test cases, providing events to allowing for the
 
310
         * interpretation of test results.
 
311
         * @namespace Test
 
312
         * @class Runner
 
313
         * @static
 
314
         */
 
315
        function TestRunner(){
 
316
        
 
317
            //inherit from EventProvider
 
318
            TestRunner.superclass.constructor.apply(this,arguments);
 
319
            
 
320
            /**
 
321
             * Suite on which to attach all TestSuites and TestCases to be run.
 
322
             * @type Y.Test.Suite
 
323
             * @property masterSuite
 
324
             * @static
 
325
             * @private
 
326
             */
 
327
            this.masterSuite /*:Y.Test.Suite*/ = new Y.Test.Suite("YUI Test Results");        
 
328
    
 
329
            /**
 
330
             * Pointer to the current node in the test tree.
 
331
             * @type TestNode
 
332
             * @private
 
333
             * @property _cur
 
334
             * @static
 
335
             */
 
336
            this._cur = null;
 
337
            
 
338
            /**
 
339
             * Pointer to the root node in the test tree.
 
340
             * @type TestNode
 
341
             * @private
 
342
             * @property _root
 
343
             * @static
 
344
             */
 
345
            this._root = null;
 
346
            
 
347
            /**
 
348
             * Indicates if the TestRunner will log events or not.
 
349
             * @type Boolean
 
350
             * @property _log
 
351
             * @private
 
352
             * @static
 
353
             */
 
354
            this._log = true;
 
355
            
 
356
            //create events
 
357
            var events = [
 
358
                this.TEST_CASE_BEGIN_EVENT,
 
359
                this.TEST_CASE_COMPLETE_EVENT,
 
360
                this.TEST_SUITE_BEGIN_EVENT,
 
361
                this.TEST_SUITE_COMPLETE_EVENT,
 
362
                this.TEST_PASS_EVENT,
 
363
                this.TEST_FAIL_EVENT,
 
364
                this.TEST_IGNORE_EVENT,
 
365
                this.COMPLETE_EVENT,
 
366
                this.BEGIN_EVENT
 
367
            ];
 
368
            for (var i=0; i < events.length; i++){
 
369
                this.subscribe(events[i], this._logEvent, this, true);
 
370
            }      
 
371
       
 
372
        }
 
373
        
 
374
        Y.extend(TestRunner, Y.Event.Target, {
 
375
        
 
376
            //-------------------------------------------------------------------------
 
377
            // Constants
 
378
            //-------------------------------------------------------------------------
 
379
             
 
380
            /**
 
381
             * Fires when a test case is opened but before the first 
 
382
             * test is executed.
 
383
             * @event testcasebegin
 
384
             * @static
 
385
             */         
 
386
            TEST_CASE_BEGIN_EVENT /*:String*/ : "testcasebegin",
 
387
            
 
388
            /**
 
389
             * Fires when all tests in a test case have been executed.
 
390
             * @event testcasecomplete
 
391
             * @static
 
392
             */        
 
393
            TEST_CASE_COMPLETE_EVENT /*:String*/ : "testcasecomplete",
 
394
            
 
395
            /**
 
396
             * Fires when a test suite is opened but before the first 
 
397
             * test is executed.
 
398
             * @event testsuitebegin
 
399
             * @static
 
400
             */        
 
401
            TEST_SUITE_BEGIN_EVENT /*:String*/ : "testsuitebegin",
 
402
            
 
403
            /**
 
404
             * Fires when all test cases in a test suite have been
 
405
             * completed.
 
406
             * @event testsuitecomplete
 
407
             * @static
 
408
             */        
 
409
            TEST_SUITE_COMPLETE_EVENT /*:String*/ : "testsuitecomplete",
 
410
            
 
411
            /**
 
412
             * Fires when a test has passed.
 
413
             * @event pass
 
414
             * @static
 
415
             */        
 
416
            TEST_PASS_EVENT /*:String*/ : "pass",
 
417
            
 
418
            /**
 
419
             * Fires when a test has failed.
 
420
             * @event fail
 
421
             * @static
 
422
             */        
 
423
            TEST_FAIL_EVENT /*:String*/ : "fail",
 
424
            
 
425
            /**
 
426
             * Fires when a test has been ignored.
 
427
             * @event ignore
 
428
             * @static
 
429
             */        
 
430
            TEST_IGNORE_EVENT /*:String*/ : "ignore",
 
431
            
 
432
            /**
 
433
             * Fires when all test suites and test cases have been completed.
 
434
             * @event complete
 
435
             * @static
 
436
             */        
 
437
            COMPLETE_EVENT /*:String*/ : "complete",
 
438
            
 
439
            /**
 
440
             * Fires when the run() method is called.
 
441
             * @event begin
 
442
             * @static
 
443
             */        
 
444
            BEGIN_EVENT /*:String*/ : "begin",    
 
445
            
 
446
            //-------------------------------------------------------------------------
 
447
            // Logging-Related Methods
 
448
            //-------------------------------------------------------------------------
 
449
    
 
450
            
 
451
            /**
 
452
             * Disable logging via Y.log(). Test output will not be visible unless
 
453
             * TestRunner events are subscribed to.
 
454
             * @return {Void}
 
455
             * @method disableLogging
 
456
             * @static
 
457
             */
 
458
            disableLogging: function(){
 
459
                this._log = false;
 
460
            },    
 
461
            
 
462
            /**
 
463
             * Enable logging via Y.log(). Test output is published and can be read via
 
464
             * logreader.
 
465
             * @return {Void}
 
466
             * @method enableLogging
 
467
             * @static
 
468
             */
 
469
            enableLogging: function(){
 
470
                this._log = true;
 
471
            },
 
472
            
 
473
            /**
 
474
             * Logs TestRunner events using Y.log().
 
475
             * @param {Object} event The event object for the event.
 
476
             * @return {Void}
 
477
             * @method _logEvent
 
478
             * @private
 
479
             * @static
 
480
             */
 
481
            _logEvent: function(event){
 
482
                
 
483
                //data variables
 
484
                var message /*:String*/ = "";
 
485
                var messageType /*:String*/ = "";
 
486
                
 
487
                switch(event.type){
 
488
                    case this.BEGIN_EVENT:
 
489
                        message = "Testing began at " + (new Date()).toString() + ".";
 
490
                        messageType = "info";
 
491
                        break;
 
492
                        
 
493
                    case this.COMPLETE_EVENT:
 
494
                        message = "Testing completed at " + (new Date()).toString() + ".\nPassed:" + 
 
495
                            event.results.passed + " Failed:" + event.results.failed + " Total:" + event.results.total;
 
496
                        messageType = "info";
 
497
                        break;
 
498
                        
 
499
                    case this.TEST_FAIL_EVENT:
 
500
                        message = event.testName + ": " + event.error.getMessage();
 
501
                        messageType = "fail";
 
502
                        break;
 
503
                        
 
504
                    case this.TEST_IGNORE_EVENT:
 
505
                        message = event.testName + ": ignored.";
 
506
                        messageType = "ignore";
 
507
                        break;
 
508
                        
 
509
                    case this.TEST_PASS_EVENT:
 
510
                        message = event.testName + ": passed.";
 
511
                        messageType = "pass";
 
512
                        break;
 
513
                        
 
514
                    case this.TEST_SUITE_BEGIN_EVENT:
 
515
                        message = "Test suite \"" + event.testSuite.name + "\" started.";
 
516
                        messageType = "info";
 
517
                        break;
 
518
                        
 
519
                    case this.TEST_SUITE_COMPLETE_EVENT:
 
520
                        message = "Test suite \"" + event.testSuite.name + "\" completed.\nPassed:" + 
 
521
                            event.results.passed + " Failed:" + event.results.failed + " Total:" + event.results.total;
 
522
                        messageType = "info";
 
523
                        break;
 
524
                        
 
525
                    case this.TEST_CASE_BEGIN_EVENT:
 
526
                        message = "Test case \"" + event.testCase.name + "\" started.";
 
527
                        messageType = "info";
 
528
                        break;
 
529
                        
 
530
                    case this.TEST_CASE_COMPLETE_EVENT:
 
531
                        message = "Test case \"" + event.testCase.name + "\" completed.\nPassed:" + 
 
532
                            event.results.passed + " Failed:" + event.results.failed + " Total:" + event.results.total;
 
533
                        messageType = "info";
 
534
                        break;
 
535
                    default:
 
536
                        message = "Unexpected event " + event.type;
 
537
                        message = "info";
 
538
                }
 
539
            
 
540
                //only log if required
 
541
                if (this._log){
 
542
                    Y.log(message, messageType, "TestRunner");
 
543
                }
 
544
            },
 
545
 
 
546
            //-------------------------------------------------------------------------
 
547
            // Test Tree-Related Methods
 
548
            //-------------------------------------------------------------------------
 
549
    
 
550
            /**
 
551
             * Adds a test case to the test tree as a child of the specified node.
 
552
             * @param {TestNode} parentNode The node to add the test case to as a child.
 
553
             * @param {Y.Test.Case} testCase The test case to add.
 
554
             * @return {Void}
 
555
             * @static
 
556
             * @private
 
557
             * @method _addTestCaseToTestTree
 
558
             */
 
559
           _addTestCaseToTestTree : function (parentNode /*:TestNode*/, testCase /*:Y.Test.Case*/) /*:Void*/{
 
560
                
 
561
                //add the test suite
 
562
                var node = parentNode.appendChild(testCase);
 
563
                
 
564
                //iterate over the items in the test case
 
565
                for (var prop in testCase){
 
566
                    if (prop.indexOf("test") === 0 && Y.Lang.isFunction(testCase[prop])){
 
567
                        node.appendChild(prop);
 
568
                    }
 
569
                }
 
570
             
 
571
            },
 
572
            
 
573
            /**
 
574
             * Adds a test suite to the test tree as a child of the specified node.
 
575
             * @param {TestNode} parentNode The node to add the test suite to as a child.
 
576
             * @param {Y.Test.Suite} testSuite The test suite to add.
 
577
             * @return {Void}
 
578
             * @static
 
579
             * @private
 
580
             * @method _addTestSuiteToTestTree
 
581
             */
 
582
            _addTestSuiteToTestTree : function (parentNode /*:TestNode*/, testSuite /*:Y.Test.Suite*/) /*:Void*/ {
 
583
                
 
584
                //add the test suite
 
585
                var node = parentNode.appendChild(testSuite);
 
586
                
 
587
                //iterate over the items in the master suite
 
588
                for (var i=0; i < testSuite.items.length; i++){
 
589
                    if (testSuite.items[i] instanceof Y.Test.Suite) {
 
590
                        this._addTestSuiteToTestTree(node, testSuite.items[i]);
 
591
                    } else if (testSuite.items[i] instanceof Y.Test.Case) {
 
592
                        this._addTestCaseToTestTree(node, testSuite.items[i]);
 
593
                    }                   
 
594
                }            
 
595
            },
 
596
            
 
597
            /**
 
598
             * Builds the test tree based on items in the master suite. The tree is a hierarchical
 
599
             * representation of the test suites, test cases, and test functions. The resulting tree
 
600
             * is stored in _root and the pointer _cur is set to the root initially.
 
601
             * @return {Void}
 
602
             * @static
 
603
             * @private
 
604
             * @method _buildTestTree
 
605
             */
 
606
            _buildTestTree : function () /*:Void*/ {
 
607
            
 
608
                this._root = new TestNode(this.masterSuite);
 
609
                this._cur = this._root;
 
610
                
 
611
                //iterate over the items in the master suite
 
612
                for (var i=0; i < this.masterSuite.items.length; i++){
 
613
                    if (this.masterSuite.items[i] instanceof Y.Test.Suite) {
 
614
                        this._addTestSuiteToTestTree(this._root, this.masterSuite.items[i]);
 
615
                    } else if (this.masterSuite.items[i] instanceof Y.Test.Case) {
 
616
                        this._addTestCaseToTestTree(this._root, this.masterSuite.items[i]);
 
617
                    }                   
 
618
                }            
 
619
            
 
620
            }, 
 
621
        
 
622
            //-------------------------------------------------------------------------
 
623
            // Private Methods
 
624
            //-------------------------------------------------------------------------
 
625
            
 
626
            /**
 
627
             * Handles the completion of a test object's tests. Tallies test results 
 
628
             * from one level up to the next.
 
629
             * @param {TestNode} node The TestNode representing the test object.
 
630
             * @return {Void}
 
631
             * @method _handleTestObjectComplete
 
632
             * @private
 
633
             */
 
634
            _handleTestObjectComplete : function (node /*:TestNode*/) /*:Void*/ {
 
635
                if (Y.Lang.isObject(node.testObject)){
 
636
                    node.parent.results.passed += node.results.passed;
 
637
                    node.parent.results.failed += node.results.failed;
 
638
                    node.parent.results.total += node.results.total;                
 
639
                    node.parent.results.ignored += node.results.ignored;                
 
640
                    node.parent.results[node.testObject.name] = node.results;
 
641
                
 
642
                    if (node.testObject instanceof Y.Test.Suite){
 
643
                        node.testObject.tearDown();
 
644
                        this.fire(this.TEST_SUITE_COMPLETE_EVENT, { testSuite: node.testObject, results: node.results});
 
645
                    } else if (node.testObject instanceof Y.Test.Case){
 
646
                        this.fire(this.TEST_CASE_COMPLETE_EVENT, { testCase: node.testObject, results: node.results});
 
647
                    }      
 
648
                } 
 
649
            },                
 
650
            
 
651
            //-------------------------------------------------------------------------
 
652
            // Navigation Methods
 
653
            //-------------------------------------------------------------------------
 
654
            
 
655
            /**
 
656
             * Retrieves the next node in the test tree.
 
657
             * @return {TestNode} The next node in the test tree or null if the end is reached.
 
658
             * @private
 
659
             * @static
 
660
             * @method _next
 
661
             */
 
662
            _next : function () /*:TestNode*/ {
 
663
            
 
664
                if (this._cur.firstChild) {
 
665
                    this._cur = this._cur.firstChild;
 
666
                } else if (this._cur.next) {
 
667
                    this._cur = this._cur.next;            
 
668
                } else {
 
669
                    while (this._cur && !this._cur.next && this._cur !== this._root){
 
670
                        this._handleTestObjectComplete(this._cur);
 
671
                        this._cur = this._cur.parent;
 
672
                    }
 
673
                    
 
674
                    if (this._cur == this._root){
 
675
                        this._cur.results.type = "report";
 
676
                        this._cur.results.timestamp = (new Date()).toLocaleString();
 
677
                        this._cur.results.duration = (new Date()) - this._cur.results.duration;                            
 
678
                        this.fire(this.COMPLETE_EVENT, { results: this._cur.results});
 
679
                        this._cur = null;
 
680
                    } else {
 
681
                        this._handleTestObjectComplete(this._cur);               
 
682
                        this._cur = this._cur.next;                
 
683
                    }
 
684
                }
 
685
            
 
686
                return this._cur;
 
687
            },
 
688
            
 
689
            /**
 
690
             * Runs a test case or test suite, returning the results.
 
691
             * @param {Y.Test.Case|Y.Test.Suite} testObject The test case or test suite to run.
 
692
             * @return {Object} Results of the execution with properties passed, failed, and total.
 
693
             * @private
 
694
             * @method _run
 
695
             * @static
 
696
             */
 
697
            _run : function () /*:Void*/ {
 
698
            
 
699
                //flag to indicate if the TestRunner should wait before continuing
 
700
                var shouldWait /*:Boolean*/ = false;
 
701
                
 
702
                //get the next test node
 
703
                var node = this._next();
 
704
                
 
705
                if (node !== null) {
 
706
                    var testObject = node.testObject;
 
707
                    
 
708
                    //figure out what to do
 
709
                    if (Y.Lang.isObject(testObject)){
 
710
                        if (testObject instanceof Y.Test.Suite){
 
711
                            this.fire(this.TEST_SUITE_BEGIN_EVENT, { testSuite: testObject });
 
712
                            testObject.setUp();
 
713
                        } else if (testObject instanceof Y.Test.Case){
 
714
                            this.fire(this.TEST_CASE_BEGIN_EVENT, { testCase: testObject });
 
715
                        }
 
716
                        
 
717
                        //some environments don't support setTimeout
 
718
                        if (typeof setTimeout != "undefined"){                    
 
719
                            setTimeout(function(){
 
720
                                Y.Test.Runner._run();
 
721
                            }, 0);
 
722
                        } else {
 
723
                            this._run();
 
724
                        }
 
725
                    } else {
 
726
                        this._runTest(node);
 
727
                    }
 
728
    
 
729
                }
 
730
            },
 
731
            
 
732
            _resumeTest : function (segment /*:Function*/) /*:Void*/ {
 
733
            
 
734
                //get relevant information
 
735
                var node /*:TestNode*/ = this._cur;
 
736
                
 
737
                //if there's no node, it probably means a wait() was called after resume()
 
738
                if (!node){
 
739
                    //TODO: Handle in some way?
 
740
                    //console.log("wait() called after resume()");
 
741
                    //this.fire("error", { testCase: "(unknown)", test: "(unknown)", error: new Error("wait() called after resume()")} );
 
742
                    return;
 
743
                }
 
744
                
 
745
                var testName /*:String*/ = node.testObject;
 
746
                var testCase /*:Y.Test.Case*/ = node.parent.testObject;
 
747
            
 
748
                //cancel other waits if available
 
749
                if (testCase.__yui_wait){
 
750
                    clearTimeout(testCase.__yui_wait);
 
751
                    delete testCase.__yui_wait;
 
752
                }
 
753
 
 
754
                //get the "should" test cases
 
755
                var shouldFail /*:Object*/ = (testCase._should.fail || {})[testName];
 
756
                var shouldError /*:Object*/ = (testCase._should.error || {})[testName];
 
757
                
 
758
                //variable to hold whether or not the test failed
 
759
                var failed /*:Boolean*/ = false;
 
760
                var error /*:Error*/ = null;
 
761
                    
 
762
                //try the test
 
763
                try {
 
764
                
 
765
                    //run the test
 
766
                    segment.apply(testCase);
 
767
                    
 
768
                    //if it should fail, and it got here, then it's a fail because it didn't
 
769
                    if (shouldFail){
 
770
                        error = new Y.Assert.ShouldFail();
 
771
                        failed = true;
 
772
                    } else if (shouldError){
 
773
                        error = new Y.Assert.ShouldError();
 
774
                        failed = true;
 
775
                    }
 
776
                               
 
777
                } catch (thrown /*:Error*/){
 
778
 
 
779
                    //cancel any pending waits, the test already failed
 
780
                    if (testCase.__yui_wait){
 
781
                        clearTimeout(testCase.__yui_wait);
 
782
                        delete testCase.__yui_wait;
 
783
                    }                    
 
784
                
 
785
                    //figure out what type of error it was
 
786
                    if (thrown instanceof Y.Assert.Error) {
 
787
                        if (!shouldFail){
 
788
                            error = thrown;
 
789
                            failed = true;
 
790
                        }
 
791
                    } else if (thrown instanceof Y.Test.Wait){
 
792
                    
 
793
                        if (Y.Lang.isFunction(thrown.segment)){
 
794
                            if (Y.Lang.isNumber(thrown.delay)){
 
795
                            
 
796
                                //some environments don't support setTimeout
 
797
                                if (typeof setTimeout != "undefined"){
 
798
                                    testCase.__yui_wait = setTimeout(function(){
 
799
                                        Y.Test.Runner._resumeTest(thrown.segment);
 
800
                                    }, thrown.delay);
 
801
                                } else {
 
802
                                    throw new Error("Asynchronous tests not supported in this environment.");
 
803
                                }
 
804
                            }
 
805
                        }
 
806
                        
 
807
                        return;
 
808
                    
 
809
                    } else {
 
810
                        //first check to see if it should error
 
811
                        if (!shouldError) {                        
 
812
                            error = new Y.Assert.UnexpectedError(thrown);
 
813
                            failed = true;
 
814
                        } else {
 
815
                            //check to see what type of data we have
 
816
                            if (Y.Lang.isString(shouldError)){
 
817
                                
 
818
                                //if it's a string, check the error message
 
819
                                if (thrown.message != shouldError){
 
820
                                    error = new Y.Assert.UnexpectedError(thrown);
 
821
                                    failed = true;                                    
 
822
                                }
 
823
                            } else if (Y.Lang.isFunction(shouldError)){
 
824
                            
 
825
                                //if it's a function, see if the error is an instance of it
 
826
                                if (!(thrown instanceof shouldError)){
 
827
                                    error = new Y.Assert.UnexpectedError(thrown);
 
828
                                    failed = true;
 
829
                                }
 
830
                            
 
831
                            } else if (Y.Lang.isObject(shouldError)){
 
832
                            
 
833
                                //if it's an object, check the instance and message
 
834
                                if (!(thrown instanceof shouldError.constructor) || 
 
835
                                        thrown.message != shouldError.message){
 
836
                                    error = new Y.Assert.UnexpectedError(thrown);
 
837
                                    failed = true;                                    
 
838
                                }
 
839
                            
 
840
                            }
 
841
                        
 
842
                        }
 
843
                    }
 
844
                    
 
845
                }
 
846
                
 
847
                //fire appropriate event
 
848
                if (failed) {
 
849
                    this.fire(this.TEST_FAIL_EVENT, { testCase: testCase, testName: testName, error: error });
 
850
                } else {
 
851
                    this.fire(this.TEST_PASS_EVENT, { testCase: testCase, testName: testName });
 
852
                }
 
853
                
 
854
                //run the tear down
 
855
                testCase.tearDown();
 
856
                
 
857
                //update results
 
858
                node.parent.results[testName] = { 
 
859
                    result: failed ? "fail" : "pass",
 
860
                    message: error ? error.getMessage() : "Test passed",
 
861
                    type: "test",
 
862
                    name: testName
 
863
                };
 
864
                
 
865
                if (failed){
 
866
                    node.parent.results.failed++;
 
867
                } else {
 
868
                    node.parent.results.passed++;
 
869
                }
 
870
                node.parent.results.total++;
 
871
    
 
872
                //set timeout not supported in all environments
 
873
                if (typeof setTimeout != "undefined"){
 
874
                    setTimeout(function(){
 
875
                        Y.Test.Runner._run();
 
876
                    }, 0);
 
877
                } else {
 
878
                    this._run();
 
879
                }
 
880
            
 
881
            },
 
882
                    
 
883
            /**
 
884
             * Runs a single test based on the data provided in the node.
 
885
             * @param {TestNode} node The TestNode representing the test to run.
 
886
             * @return {Void}
 
887
             * @static
 
888
             * @private
 
889
             * @name _runTest
 
890
             */
 
891
            _runTest : function (node /*:TestNode*/) /*:Void*/ {
 
892
            
 
893
                //get relevant information
 
894
                var testName /*:String*/ = node.testObject;
 
895
                var testCase /*:Y.Test.Case*/ = node.parent.testObject;
 
896
                var test /*:Function*/ = testCase[testName];
 
897
                
 
898
                //get the "should" test cases
 
899
                var shouldIgnore /*:Object*/ = (testCase._should.ignore || {})[testName];
 
900
                
 
901
                //figure out if the test should be ignored or not
 
902
                if (shouldIgnore){
 
903
                
 
904
                    //update results
 
905
                    node.parent.results[testName] = { 
 
906
                        result: "ignore",
 
907
                        message: "Test ignored",
 
908
                        type: "test",
 
909
                        name: testName
 
910
                    };
 
911
                    
 
912
                    node.parent.results.ignored++;
 
913
                    node.parent.results.total++;
 
914
                
 
915
                    this.fire(this.TEST_IGNORE_EVENT, { testCase: testCase, testName: testName });
 
916
                    
 
917
                    //some environments don't support setTimeout
 
918
                    if (typeof setTimeout != "undefined"){                    
 
919
                        setTimeout(function(){
 
920
                            Y.Test.Runner._run();
 
921
                        }, 0);              
 
922
                    } else {
 
923
                        this._run();
 
924
                    }
 
925
    
 
926
                } else {
 
927
                
 
928
                    //run the setup
 
929
                    testCase.setUp();
 
930
                    
 
931
                    //now call the body of the test
 
932
                    this._resumeTest(test);                
 
933
                }
 
934
    
 
935
            },        
 
936
            
 
937
            //-------------------------------------------------------------------------
 
938
            // Protected Methods
 
939
            //-------------------------------------------------------------------------   
 
940
        
 
941
            /*
 
942
             * Fires events for the TestRunner. This overrides the default fire()
 
943
             * method from EventProvider to add the type property to the data that is
 
944
             * passed through on each event call.
 
945
             * @param {String} type The type of event to fire.
 
946
             * @param {Object} data (Optional) Data for the event.
 
947
             * @method fire
 
948
             * @static
 
949
             * @protected
 
950
             */
 
951
            fire : function (type /*:String*/, data /*:Object*/) /*:Void*/ {
 
952
                data = data || {};
 
953
                data.type = type;
 
954
                TestRunner.superclass.fire.call(this, type, data);
 
955
            },
 
956
            
 
957
            //-------------------------------------------------------------------------
 
958
            // Public Methods
 
959
            //-------------------------------------------------------------------------   
 
960
        
 
961
            /**
 
962
             * Adds a test suite or test case to the list of test objects to run.
 
963
             * @param testObject Either a TestCase or a TestSuite that should be run.
 
964
             * @return {Void}
 
965
             * @method add
 
966
             * @static
 
967
             */
 
968
            add : function (testObject /*:Object*/) /*:Void*/ {
 
969
                this.masterSuite.add(testObject);
 
970
            },
 
971
            
 
972
            /**
 
973
             * Removes all test objects from the runner.
 
974
             * @return {Void}
 
975
             * @method clear
 
976
             * @static
 
977
             */
 
978
            clear : function () /*:Void*/ {
 
979
                this.masterSuite.items = [];
 
980
            },
 
981
            
 
982
            /**
 
983
             * Resumes the TestRunner after wait() was called.
 
984
             * @param {Function} segment The function to run as the rest
 
985
             *      of the haulted test.
 
986
             * @return {Void}
 
987
             * @method resume
 
988
             * @static
 
989
             */
 
990
            resume : function (segment /*:Function*/) /*:Void*/ {
 
991
                this._resumeTest(segment || function(){});
 
992
            },
 
993
        
 
994
            /**
 
995
             * Runs the test suite.
 
996
             * @return {Void}
 
997
             * @method run
 
998
             * @static
 
999
             */
 
1000
            run : function (testObject /*:Object*/) /*:Void*/ {
 
1001
                
 
1002
                //pointer to runner to avoid scope issues 
 
1003
                var runner = Y.Test.Runner;
 
1004
    
 
1005
                //build the test tree
 
1006
                runner._buildTestTree();
 
1007
                            
 
1008
                //set when the test started
 
1009
                runner._root.results.duration = (new Date()).valueOf();
 
1010
                
 
1011
                //fire the begin event
 
1012
                runner.fire(runner.BEGIN_EVENT);
 
1013
           
 
1014
                //begin the testing
 
1015
                runner._run();
 
1016
            }    
 
1017
        });
 
1018
        
 
1019
        return new TestRunner();
 
1020
        
 
1021
    })();
 
1022
 
 
1023
  
 
1024
    /**
 
1025
     * The Assert object provides functions to test JavaScript values against
 
1026
     * known and expected results. Whenever a comparison (assertion) fails,
 
1027
     * an error is thrown.
 
1028
     *
 
1029
     * @class Assert
 
1030
     * @static
 
1031
     */
 
1032
    Y.Assert = {
 
1033
    
 
1034
        //-------------------------------------------------------------------------
 
1035
        // Helper Methods
 
1036
        //-------------------------------------------------------------------------
 
1037
        
 
1038
        /**
 
1039
         * Formats a message so that it can contain the original assertion message
 
1040
         * in addition to the custom message.
 
1041
         * @param {String} customMessage The message passed in by the developer.
 
1042
         * @param {String} defaultMessage The message created by the error by default.
 
1043
         * @return {String} The final error message, containing either or both.
 
1044
         * @protected
 
1045
         * @static
 
1046
         * @method _formatMessage
 
1047
         */
 
1048
        _formatMessage : function (customMessage /*:String*/, defaultMessage /*:String*/) /*:String*/ {
 
1049
            var message = customMessage;
 
1050
            if (Y.Lang.isString(customMessage) && customMessage.length > 0){
 
1051
                return Y.Lang.substitute(customMessage, { message: defaultMessage });
 
1052
            } else {
 
1053
                return defaultMessage;
 
1054
            }        
 
1055
        },
 
1056
        
 
1057
        //-------------------------------------------------------------------------
 
1058
        // Generic Assertion Methods
 
1059
        //-------------------------------------------------------------------------
 
1060
        
 
1061
        /** 
 
1062
         * Forces an assertion error to occur.
 
1063
         * @param {String} message (Optional) The message to display with the failure.
 
1064
         * @method fail
 
1065
         * @static
 
1066
         */
 
1067
        fail : function (message /*:String*/) /*:Void*/ {
 
1068
            throw new Y.Assert.Error(Y.Assert._formatMessage(message, "Test force-failed."));
 
1069
        },       
 
1070
        
 
1071
        //-------------------------------------------------------------------------
 
1072
        // Equality Assertion Methods
 
1073
        //-------------------------------------------------------------------------    
 
1074
        
 
1075
        /**
 
1076
         * Asserts that a value is equal to another. This uses the double equals sign
 
1077
         * so type cohersion may occur.
 
1078
         * @param {Object} expected The expected value.
 
1079
         * @param {Object} actual The actual value to test.
 
1080
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1081
         * @method areEqual
 
1082
         * @static
 
1083
         */
 
1084
        areEqual : function (expected /*:Object*/, actual /*:Object*/, message /*:String*/) /*:Void*/ {
 
1085
            if (expected != actual) {
 
1086
                throw new Y.Assert.ComparisonFailure(Y.Assert._formatMessage(message, "Values should be equal."), expected, actual);
 
1087
            }
 
1088
        },
 
1089
        
 
1090
        /**
 
1091
         * Asserts that a value is not equal to another. This uses the double equals sign
 
1092
         * so type cohersion may occur.
 
1093
         * @param {Object} unexpected The unexpected value.
 
1094
         * @param {Object} actual The actual value to test.
 
1095
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1096
         * @method areNotEqual
 
1097
         * @static
 
1098
         */
 
1099
        areNotEqual : function (unexpected /*:Object*/, actual /*:Object*/, 
 
1100
                             message /*:String*/) /*:Void*/ {
 
1101
            if (unexpected == actual) {
 
1102
                throw new Y.Assert.UnexpectedValue(Y.Assert._formatMessage(message, "Values should not be equal."), unexpected);
 
1103
            }
 
1104
        },
 
1105
        
 
1106
        /**
 
1107
         * Asserts that a value is not the same as another. This uses the triple equals sign
 
1108
         * so no type cohersion may occur.
 
1109
         * @param {Object} unexpected The unexpected value.
 
1110
         * @param {Object} actual The actual value to test.
 
1111
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1112
         * @method areNotSame
 
1113
         * @static
 
1114
         */
 
1115
        areNotSame : function (unexpected /*:Object*/, actual /*:Object*/, message /*:String*/) /*:Void*/ {
 
1116
            if (unexpected === actual) {
 
1117
                throw new Y.Assert.UnexpectedValue(Y.Assert._formatMessage(message, "Values should not be the same."), unexpected);
 
1118
            }
 
1119
        },
 
1120
    
 
1121
        /**
 
1122
         * Asserts that a value is the same as another. This uses the triple equals sign
 
1123
         * so no type cohersion may occur.
 
1124
         * @param {Object} expected The expected value.
 
1125
         * @param {Object} actual The actual value to test.
 
1126
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1127
         * @method areSame
 
1128
         * @static
 
1129
         */
 
1130
        areSame : function (expected /*:Object*/, actual /*:Object*/, message /*:String*/) /*:Void*/ {
 
1131
            if (expected !== actual) {
 
1132
                throw new Y.Assert.ComparisonFailure(Y.Assert._formatMessage(message, "Values should be the same."), expected, actual);
 
1133
            }
 
1134
        },    
 
1135
        
 
1136
        //-------------------------------------------------------------------------
 
1137
        // Boolean Assertion Methods
 
1138
        //-------------------------------------------------------------------------    
 
1139
        
 
1140
        /**
 
1141
         * Asserts that a value is false. This uses the triple equals sign
 
1142
         * so no type cohersion may occur.
 
1143
         * @param {Object} actual The actual value to test.
 
1144
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1145
         * @method isFalse
 
1146
         * @static
 
1147
         */
 
1148
        isFalse : function (actual /*:Boolean*/, message /*:String*/) {
 
1149
            if (false !== actual) {
 
1150
                throw new Y.Assert.ComparisonFailure(Y.Assert._formatMessage(message, "Value should be false."), false, actual);
 
1151
            }
 
1152
        },
 
1153
        
 
1154
        /**
 
1155
         * Asserts that a value is true. This uses the triple equals sign
 
1156
         * so no type cohersion may occur.
 
1157
         * @param {Object} actual The actual value to test.
 
1158
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1159
         * @method isTrue
 
1160
         * @static
 
1161
         */
 
1162
        isTrue : function (actual /*:Boolean*/, message /*:String*/) /*:Void*/ {
 
1163
            if (true !== actual) {
 
1164
                throw new Y.Assert.ComparisonFailure(Y.Assert._formatMessage(message, "Value should be true."), true, actual);
 
1165
            }
 
1166
    
 
1167
        },
 
1168
        
 
1169
        //-------------------------------------------------------------------------
 
1170
        // Special Value Assertion Methods
 
1171
        //-------------------------------------------------------------------------    
 
1172
        
 
1173
        /**
 
1174
         * Asserts that a value is not a number.
 
1175
         * @param {Object} actual The value to test.
 
1176
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1177
         * @method isNaN
 
1178
         * @static
 
1179
         */
 
1180
        isNaN : function (actual /*:Object*/, message /*:String*/) /*:Void*/{
 
1181
            if (!isNaN(actual)){
 
1182
                throw new Y.Assert.ComparisonFailure(Y.Assert._formatMessage(message, "Value should be NaN."), NaN, actual);
 
1183
            }    
 
1184
        },
 
1185
        
 
1186
        /**
 
1187
         * Asserts that a value is not the special NaN value.
 
1188
         * @param {Object} actual The value to test.
 
1189
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1190
         * @method isNotNaN
 
1191
         * @static
 
1192
         */
 
1193
        isNotNaN : function (actual /*:Object*/, message /*:String*/) /*:Void*/{
 
1194
            if (isNaN(actual)){
 
1195
                throw new Y.Assert.UnexpectedValue(Y.Assert._formatMessage(message, "Values should not be NaN."), NaN);
 
1196
            }    
 
1197
        },
 
1198
        
 
1199
        /**
 
1200
         * Asserts that a value is not null. This uses the triple equals sign
 
1201
         * so no type cohersion may occur.
 
1202
         * @param {Object} actual The actual value to test.
 
1203
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1204
         * @method isNotNull
 
1205
         * @static
 
1206
         */
 
1207
        isNotNull : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
 
1208
            if (Y.Lang.isNull(actual)) {
 
1209
                throw new Y.Assert.UnexpectedValue(Y.Assert._formatMessage(message, "Values should not be null."), null);
 
1210
            }
 
1211
        },
 
1212
    
 
1213
        /**
 
1214
         * Asserts that a value is not undefined. This uses the triple equals sign
 
1215
         * so no type cohersion may occur.
 
1216
         * @param {Object} actual The actual value to test.
 
1217
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1218
         * @method isNotUndefined
 
1219
         * @static
 
1220
         */
 
1221
        isNotUndefined : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
 
1222
            if (Y.Lang.isUndefined(actual)) {
 
1223
                throw new Y.Assert.UnexpectedValue(Y.Assert._formatMessage(message, "Value should not be undefined."), undefined);
 
1224
            }
 
1225
        },
 
1226
    
 
1227
        /**
 
1228
         * Asserts that a value is null. This uses the triple equals sign
 
1229
         * so no type cohersion may occur.
 
1230
         * @param {Object} actual The actual value to test.
 
1231
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1232
         * @method isNull
 
1233
         * @static
 
1234
         */
 
1235
        isNull : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
 
1236
            if (!Y.Lang.isNull(actual)) {
 
1237
                throw new Y.Assert.ComparisonFailure(Y.Assert._formatMessage(message, "Value should be null."), null, actual);
 
1238
            }
 
1239
        },
 
1240
            
 
1241
        /**
 
1242
         * Asserts that a value is undefined. This uses the triple equals sign
 
1243
         * so no type cohersion may occur.
 
1244
         * @param {Object} actual The actual value to test.
 
1245
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1246
         * @method isUndefined
 
1247
         * @static
 
1248
         */
 
1249
        isUndefined : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
 
1250
            if (!Y.Lang.isUndefined(actual)) {
 
1251
                throw new Y.Assert.ComparisonFailure(Y.Assert._formatMessage(message, "Value should be undefined."), undefined, actual);
 
1252
            }
 
1253
        },    
 
1254
        
 
1255
        //--------------------------------------------------------------------------
 
1256
        // Instance Assertion Methods
 
1257
        //--------------------------------------------------------------------------    
 
1258
       
 
1259
        /**
 
1260
         * Asserts that a value is an array.
 
1261
         * @param {Object} actual The value to test.
 
1262
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1263
         * @method isArray
 
1264
         * @static
 
1265
         */
 
1266
        isArray : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
 
1267
            if (!Y.Lang.isArray(actual)){
 
1268
                throw new Y.Assert.UnexpectedValue(Y.Assert._formatMessage(message, "Value should be an array."), actual);
 
1269
            }    
 
1270
        },
 
1271
       
 
1272
        /**
 
1273
         * Asserts that a value is a Boolean.
 
1274
         * @param {Object} actual The value to test.
 
1275
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1276
         * @method isBoolean
 
1277
         * @static
 
1278
         */
 
1279
        isBoolean : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
 
1280
            if (!Y.Lang.isBoolean(actual)){
 
1281
                throw new Y.Assert.UnexpectedValue(Y.Assert._formatMessage(message, "Value should be a Boolean."), actual);
 
1282
            }    
 
1283
        },
 
1284
       
 
1285
        /**
 
1286
         * Asserts that a value is a function.
 
1287
         * @param {Object} actual The value to test.
 
1288
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1289
         * @method isFunction
 
1290
         * @static
 
1291
         */
 
1292
        isFunction : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
 
1293
            if (!Y.Lang.isFunction(actual)){
 
1294
                throw new Y.Assert.UnexpectedValue(Y.Assert._formatMessage(message, "Value should be a function."), actual);
 
1295
            }    
 
1296
        },
 
1297
       
 
1298
        /**
 
1299
         * Asserts that a value is an instance of a particular object. This may return
 
1300
         * incorrect results when comparing objects from one frame to constructors in
 
1301
         * another frame. For best results, don't use in a cross-frame manner.
 
1302
         * @param {Function} expected The function that the object should be an instance of.
 
1303
         * @param {Object} actual The object to test.
 
1304
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1305
         * @method isInstanceOf
 
1306
         * @static
 
1307
         */
 
1308
        isInstanceOf : function (expected /*:Function*/, actual /*:Object*/, message /*:String*/) /*:Void*/ {
 
1309
            if (!(actual instanceof expected)){
 
1310
                throw new Y.Assert.ComparisonFailure(Y.Assert._formatMessage(message, "Value isn't an instance of expected type."), expected, actual);
 
1311
            }
 
1312
        },
 
1313
        
 
1314
        /**
 
1315
         * Asserts that a value is a number.
 
1316
         * @param {Object} actual The value to test.
 
1317
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1318
         * @method isNumber
 
1319
         * @static
 
1320
         */
 
1321
        isNumber : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
 
1322
            if (!Y.Lang.isNumber(actual)){
 
1323
                throw new Y.Assert.UnexpectedValue(Y.Assert._formatMessage(message, "Value should be a number."), actual);
 
1324
            }    
 
1325
        },    
 
1326
        
 
1327
        /**
 
1328
         * Asserts that a value is an object.
 
1329
         * @param {Object} actual The value to test.
 
1330
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1331
         * @method isObject
 
1332
         * @static
 
1333
         */
 
1334
        isObject : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
 
1335
            if (!Y.Lang.isObject(actual)){
 
1336
                throw new Y.Assert.UnexpectedValue(Y.Assert._formatMessage(message, "Value should be an object."), actual);
 
1337
            }
 
1338
        },
 
1339
        
 
1340
        /**
 
1341
         * Asserts that a value is a string.
 
1342
         * @param {Object} actual The value to test.
 
1343
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1344
         * @method isString
 
1345
         * @static
 
1346
         */
 
1347
        isString : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
 
1348
            if (!Y.Lang.isString(actual)){
 
1349
                throw new Y.Assert.UnexpectedValue(Y.Assert._formatMessage(message, "Value should be a string."), actual);
 
1350
            }
 
1351
        },
 
1352
        
 
1353
        /**
 
1354
         * Asserts that a value is of a particular type. 
 
1355
         * @param {String} expectedType The expected type of the variable.
 
1356
         * @param {Object} actualValue The actual value to test.
 
1357
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1358
         * @method isTypeOf
 
1359
         * @static
 
1360
         */
 
1361
        isTypeOf : function (expectedType /*:String*/, actualValue /*:Object*/, message /*:String*/) /*:Void*/{
 
1362
            if (typeof actualValue != expectedType){
 
1363
                throw new Y.Assert.ComparisonFailure(Y.Assert._formatMessage(message, "Value should be of type " + expectedType + "."), expected, typeof actualValue);
 
1364
            }
 
1365
        }
 
1366
    };
 
1367
    
 
1368
    //-----------------------------------------------------------------------------
 
1369
    // Assertion errors
 
1370
    //-----------------------------------------------------------------------------
 
1371
    
 
1372
    /**
 
1373
     * Error is thrown whenever an assertion fails. It provides methods
 
1374
     * to more easily get at error information and also provides a base class
 
1375
     * from which more specific assertion errors can be derived.
 
1376
     *
 
1377
     * @param {String} message The message to display when the error occurs.
 
1378
     * @namespace Assert
 
1379
     * @class Error
 
1380
     * @constructor
 
1381
     */ 
 
1382
    Y.Assert.Error = function (message /*:String*/){
 
1383
    
 
1384
        //call superclass
 
1385
        arguments.callee.superclass.constructor.call(this, message);
 
1386
        
 
1387
        /*
 
1388
         * Error message. Must be duplicated to ensure browser receives it.
 
1389
         * @type String
 
1390
         * @property message
 
1391
         */
 
1392
        this.message /*:String*/ = message;
 
1393
        
 
1394
        /**
 
1395
         * The name of the error that occurred.
 
1396
         * @type String
 
1397
         * @property name
 
1398
         */
 
1399
        this.name /*:String*/ = "Assert Error";
 
1400
    };
 
1401
    
 
1402
    //inherit methods
 
1403
    Y.extend(Y.Assert.Error, Error, {
 
1404
    
 
1405
        /**
 
1406
         * Returns a fully formatted error for an assertion failure. This should
 
1407
         * be overridden by all subclasses to provide specific information.
 
1408
         * @method getMessage
 
1409
         * @return {String} A string describing the error.
 
1410
         */
 
1411
        getMessage : function () /*:String*/ {
 
1412
            return this.message;
 
1413
        },
 
1414
        
 
1415
        /**
 
1416
         * Returns a string representation of the error.
 
1417
         * @method toString
 
1418
         * @return {String} A string representation of the error.
 
1419
         */
 
1420
        toString : function () /*:String*/ {
 
1421
            return this.name + ": " + this.getMessage();
 
1422
        },
 
1423
        
 
1424
        /**
 
1425
         * Returns a primitive value version of the error. Same as toString().
 
1426
         * @method valueOf
 
1427
         * @return {String} A primitive value version of the error.
 
1428
         */
 
1429
        valueOf : function () /*:String*/ {
 
1430
            return this.toString();
 
1431
        }
 
1432
    
 
1433
    });
 
1434
    
 
1435
    /**
 
1436
     * ComparisonFailure is subclass of Error that is thrown whenever
 
1437
     * a comparison between two values fails. It provides mechanisms to retrieve
 
1438
     * both the expected and actual value.
 
1439
     *
 
1440
     * @param {String} message The message to display when the error occurs.
 
1441
     * @param {Object} expected The expected value.
 
1442
     * @param {Object} actual The actual value that caused the assertion to fail.
 
1443
     * @namespace Assert 
 
1444
     * @extends Assert.Error
 
1445
     * @class ComparisonFailure
 
1446
     * @constructor
 
1447
     */ 
 
1448
    Y.Assert.ComparisonFailure = function (message /*:String*/, expected /*:Object*/, actual /*:Object*/){
 
1449
    
 
1450
        //call superclass
 
1451
        arguments.callee.superclass.constructor.call(this, message);
 
1452
        
 
1453
        /**
 
1454
         * The expected value.
 
1455
         * @type Object
 
1456
         * @property expected
 
1457
         */
 
1458
        this.expected /*:Object*/ = expected;
 
1459
        
 
1460
        /**
 
1461
         * The actual value.
 
1462
         * @type Object
 
1463
         * @property actual
 
1464
         */
 
1465
        this.actual /*:Object*/ = actual;
 
1466
        
 
1467
        /**
 
1468
         * The name of the error that occurred.
 
1469
         * @type String
 
1470
         * @property name
 
1471
         */
 
1472
        this.name /*:String*/ = "ComparisonFailure";
 
1473
        
 
1474
    };
 
1475
    
 
1476
    //inherit methods
 
1477
    Y.extend(Y.Assert.ComparisonFailure, Y.Assert.Error, {
 
1478
    
 
1479
        /**
 
1480
         * Returns a fully formatted error for an assertion failure. This message
 
1481
         * provides information about the expected and actual values.
 
1482
         * @method toString
 
1483
         * @return {String} A string describing the error.
 
1484
         */
 
1485
        getMessage : function () /*:String*/ {
 
1486
            return this.message + "\nExpected: " + this.expected + " (" + (typeof this.expected) + ")"  +
 
1487
                "\nActual:" + this.actual + " (" + (typeof this.actual) + ")";
 
1488
        }
 
1489
    
 
1490
    });
 
1491
    
 
1492
    /**
 
1493
     * UnexpectedValue is subclass of Error that is thrown whenever
 
1494
     * a value was unexpected in its scope. This typically means that a test
 
1495
     * was performed to determine that a value was *not* equal to a certain
 
1496
     * value.
 
1497
     *
 
1498
     * @param {String} message The message to display when the error occurs.
 
1499
     * @param {Object} unexpected The unexpected value.
 
1500
     * @namespace Assert
 
1501
     * @extends Assert.Error
 
1502
     * @class UnexpectedValue
 
1503
     * @constructor
 
1504
     */ 
 
1505
    Y.Assert.UnexpectedValue = function (message /*:String*/, unexpected /*:Object*/){
 
1506
    
 
1507
        //call superclass
 
1508
        arguments.callee.superclass.constructor.call(this, message);
 
1509
        
 
1510
        /**
 
1511
         * The unexpected value.
 
1512
         * @type Object
 
1513
         * @property unexpected
 
1514
         */
 
1515
        this.unexpected /*:Object*/ = unexpected;
 
1516
        
 
1517
        /**
 
1518
         * The name of the error that occurred.
 
1519
         * @type String
 
1520
         * @property name
 
1521
         */
 
1522
        this.name /*:String*/ = "UnexpectedValue";
 
1523
        
 
1524
    };
 
1525
    
 
1526
    //inherit methods
 
1527
    Y.extend(Y.Assert.UnexpectedValue, Y.Assert.Error, {
 
1528
    
 
1529
        /**
 
1530
         * Returns a fully formatted error for an assertion failure. The message
 
1531
         * contains information about the unexpected value that was encountered.
 
1532
         * @method getMessage
 
1533
         * @return {String} A string describing the error.
 
1534
         */
 
1535
        getMessage : function () /*:String*/ {
 
1536
            return this.message + "\nUnexpected: " + this.unexpected + " (" + (typeof this.unexpected) + ") ";
 
1537
        }
 
1538
    
 
1539
    });
 
1540
    
 
1541
    /**
 
1542
     * ShouldFail is subclass of Error that is thrown whenever
 
1543
     * a test was expected to fail but did not.
 
1544
     *
 
1545
     * @param {String} message The message to display when the error occurs.
 
1546
     * @namespace Assert
 
1547
     * @extends Assert.Error
 
1548
     * @class ShouldFail
 
1549
     * @constructor
 
1550
     */  
 
1551
    Y.Assert.ShouldFail = function (message /*:String*/){
 
1552
    
 
1553
        //call superclass
 
1554
        arguments.callee.superclass.constructor.call(this, message || "This test should fail but didn't.");
 
1555
        
 
1556
        /**
 
1557
         * The name of the error that occurred.
 
1558
         * @type String
 
1559
         * @property name
 
1560
         */
 
1561
        this.name /*:String*/ = "ShouldFail";
 
1562
        
 
1563
    };
 
1564
    
 
1565
    //inherit methods
 
1566
    Y.extend(Y.Assert.ShouldFail, Y.Assert.Error);
 
1567
    
 
1568
    /**
 
1569
     * ShouldError is subclass of Error that is thrown whenever
 
1570
     * a test is expected to throw an error but doesn't.
 
1571
     *
 
1572
     * @param {String} message The message to display when the error occurs.
 
1573
     * @namespace Assert
 
1574
     * @extends Assert.Error
 
1575
     * @class ShouldError
 
1576
     * @constructor
 
1577
     */  
 
1578
    Y.Assert.ShouldError = function (message /*:String*/){
 
1579
    
 
1580
        //call superclass
 
1581
        arguments.callee.superclass.constructor.call(this, message || "This test should have thrown an error but didn't.");
 
1582
        
 
1583
        /**
 
1584
         * The name of the error that occurred.
 
1585
         * @type String
 
1586
         * @property name
 
1587
         */
 
1588
        this.name /*:String*/ = "ShouldError";
 
1589
        
 
1590
    };
 
1591
    
 
1592
    //inherit methods
 
1593
    Y.extend(Y.Assert.ShouldError, Y.Assert.Error);
 
1594
    
 
1595
    /**
 
1596
     * UnexpectedError is subclass of Error that is thrown whenever
 
1597
     * an error occurs within the course of a test and the test was not expected
 
1598
     * to throw an error.
 
1599
     *
 
1600
     * @param {Error} cause The unexpected error that caused this error to be 
 
1601
     *                      thrown.
 
1602
     * @namespace Assert
 
1603
     * @extends Assert.Error
 
1604
     * @class UnexpectedError
 
1605
     * @constructor
 
1606
     */  
 
1607
    Y.Assert.UnexpectedError = function (cause /*:Object*/){
 
1608
    
 
1609
        //call superclass
 
1610
        arguments.callee.superclass.constructor.call(this, "Unexpected error: " + cause.message);
 
1611
        
 
1612
        /**
 
1613
         * The unexpected error that occurred.
 
1614
         * @type Error
 
1615
         * @property cause
 
1616
         */
 
1617
        this.cause /*:Error*/ = cause;
 
1618
        
 
1619
        /**
 
1620
         * The name of the error that occurred.
 
1621
         * @type String
 
1622
         * @property name
 
1623
         */
 
1624
        this.name /*:String*/ = "UnexpectedError";
 
1625
        
 
1626
        /**
 
1627
         * Stack information for the error (if provided).
 
1628
         * @type String
 
1629
         * @property stack
 
1630
         */
 
1631
        this.stack /*:String*/ = cause.stack;
 
1632
        
 
1633
    };
 
1634
    
 
1635
    //inherit methods
 
1636
    Y.extend(Y.Assert.UnexpectedError, Y.Assert.Error);
 
1637
    
 
1638
 
 
1639
    
 
1640
    /**
 
1641
     * The ArrayAssert object provides functions to test JavaScript array objects
 
1642
     * for a variety of cases.
 
1643
     *
 
1644
     * @class ArrayAssert
 
1645
     * @static
 
1646
     */
 
1647
     
 
1648
    Y.ArrayAssert = {
 
1649
    
 
1650
        /**
 
1651
         * Asserts that a value is present in an array. This uses the triple equals 
 
1652
         * sign so no type cohersion may occur.
 
1653
         * @param {Object} needle The value that is expected in the array.
 
1654
         * @param {Array} haystack An array of values.
 
1655
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1656
         * @method contains
 
1657
         * @static
 
1658
         */
 
1659
        contains : function (needle /*:Object*/, haystack /*:Array*/, 
 
1660
                               message /*:String*/) /*:Void*/ {
 
1661
            
 
1662
            var found /*:Boolean*/ = false;
 
1663
            
 
1664
            //begin checking values
 
1665
            for (var i=0; i < haystack.length && !found; i++){
 
1666
                if (haystack[i] === needle) {
 
1667
                    found = true;
 
1668
                }
 
1669
            }
 
1670
            
 
1671
            if (!found){
 
1672
                Y.Assert.fail(Y.Assert._formatMessage(message, "Value " + needle + " (" + (typeof needle) + ") not found in array [" + haystack + "]."));
 
1673
            }
 
1674
        },
 
1675
    
 
1676
        /**
 
1677
         * Asserts that a set of values are present in an array. This uses the triple equals 
 
1678
         * sign so no type cohersion may occur. For this assertion to pass, all values must
 
1679
         * be found.
 
1680
         * @param {Object[]} needles An array of values that are expected in the array.
 
1681
         * @param {Array} haystack An array of values to check.
 
1682
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1683
         * @method containsItems
 
1684
         * @static
 
1685
         */
 
1686
        containsItems : function (needles /*:Object[]*/, haystack /*:Array*/, 
 
1687
                               message /*:String*/) /*:Void*/ {
 
1688
    
 
1689
            //begin checking values
 
1690
            for (var i=0; i < needles.length; i++){
 
1691
                this.contains(needles[i], haystack, message);
 
1692
            }
 
1693
        },
 
1694
    
 
1695
        /**
 
1696
         * Asserts that a value matching some condition is present in an array. This uses
 
1697
         * a function to determine a match.
 
1698
         * @param {Function} matcher A function that returns true if the items matches or false if not.
 
1699
         * @param {Array} haystack An array of values.
 
1700
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1701
         * @method containsMatch
 
1702
         * @static
 
1703
         */
 
1704
        containsMatch : function (matcher /*:Function*/, haystack /*:Array*/, 
 
1705
                               message /*:String*/) /*:Void*/ {
 
1706
            
 
1707
            //check for valid matcher
 
1708
            if (typeof matcher != "function"){
 
1709
                throw new TypeError("ArrayAssert.containsMatch(): First argument must be a function.");
 
1710
            }
 
1711
            
 
1712
            var found /*:Boolean*/ = false;
 
1713
            
 
1714
            //begin checking values
 
1715
            for (var i=0; i < haystack.length && !found; i++){
 
1716
                if (matcher(haystack[i])) {
 
1717
                    found = true;
 
1718
                }
 
1719
            }
 
1720
            
 
1721
            if (!found){
 
1722
                Y.Assert.fail(Y.Assert._formatMessage(message, "No match found in array [" + haystack + "]."));
 
1723
            }
 
1724
        },
 
1725
    
 
1726
        /**
 
1727
         * Asserts that a value is not present in an array. This uses the triple equals 
 
1728
         * Asserts that a value is not present in an array. This uses the triple equals 
 
1729
         * sign so no type cohersion may occur.
 
1730
         * @param {Object} needle The value that is expected in the array.
 
1731
         * @param {Array} haystack An array of values.
 
1732
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1733
         * @method doesNotContain
 
1734
         * @static
 
1735
         */
 
1736
        doesNotContain : function (needle /*:Object*/, haystack /*:Array*/, 
 
1737
                               message /*:String*/) /*:Void*/ {
 
1738
            
 
1739
            var found /*:Boolean*/ = false;
 
1740
            
 
1741
            //begin checking values
 
1742
            for (var i=0; i < haystack.length && !found; i++){
 
1743
                if (haystack[i] === needle) {
 
1744
                    found = true;
 
1745
                }
 
1746
            }
 
1747
            
 
1748
            if (found){
 
1749
                Y.Assert.fail(Y.Assert._formatMessage(message, "Value found in array [" + haystack + "]."));
 
1750
            }
 
1751
        },
 
1752
    
 
1753
        /**
 
1754
         * Asserts that a set of values are not present in an array. This uses the triple equals 
 
1755
         * sign so no type cohersion may occur. For this assertion to pass, all values must
 
1756
         * not be found.
 
1757
         * @param {Object[]} needles An array of values that are not expected in the array.
 
1758
         * @param {Array} haystack An array of values to check.
 
1759
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1760
         * @method doesNotContainItems
 
1761
         * @static
 
1762
         */
 
1763
        doesNotContainItems : function (needles /*:Object[]*/, haystack /*:Array*/, 
 
1764
                               message /*:String*/) /*:Void*/ {
 
1765
    
 
1766
            for (var i=0; i < needles.length; i++){
 
1767
                this.doesNotContain(needles[i], haystack, message);
 
1768
            }
 
1769
    
 
1770
        },
 
1771
            
 
1772
        /**
 
1773
         * Asserts that no values matching a condition are present in an array. This uses
 
1774
         * a function to determine a match.
 
1775
         * @param {Function} matcher A function that returns true if the items matches or false if not.
 
1776
         * @param {Array} haystack An array of values.
 
1777
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1778
         * @method doesNotContainMatch
 
1779
         * @static
 
1780
         */
 
1781
        doesNotContainMatch : function (matcher /*:Function*/, haystack /*:Array*/, 
 
1782
                               message /*:String*/) /*:Void*/ {
 
1783
            
 
1784
            //check for valid matcher
 
1785
            if (typeof matcher != "function"){
 
1786
                throw new TypeError("ArrayAssert.doesNotContainMatch(): First argument must be a function.");
 
1787
            }
 
1788
    
 
1789
            var found /*:Boolean*/ = false;
 
1790
            
 
1791
            //begin checking values
 
1792
            for (var i=0; i < haystack.length && !found; i++){
 
1793
                if (matcher(haystack[i])) {
 
1794
                    found = true;
 
1795
                }
 
1796
            }
 
1797
            
 
1798
            if (found){
 
1799
                Y.Assert.fail(Y.Assert._formatMessage(message, "Value found in array [" + haystack + "]."));
 
1800
            }
 
1801
        },
 
1802
            
 
1803
        /**
 
1804
         * Asserts that the given value is contained in an array at the specified index.
 
1805
         * This uses the triple equals sign so no type cohersion will occur.
 
1806
         * @param {Object} needle The value to look for.
 
1807
         * @param {Array} haystack The array to search in.
 
1808
         * @param {int} index The index at which the value should exist.
 
1809
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1810
         * @method indexOf
 
1811
         * @static
 
1812
         */
 
1813
        indexOf : function (needle /*:Object*/, haystack /*:Array*/, index /*:int*/, message /*:String*/) /*:Void*/ {
 
1814
        
 
1815
            //try to find the value in the array
 
1816
            for (var i=0; i < haystack.length; i++){
 
1817
                if (haystack[i] === needle){
 
1818
                    Y.Assert.areEqual(index, i, message || "Value exists at index " + i + " but should be at index " + index + ".");
 
1819
                    return;
 
1820
                }
 
1821
            }
 
1822
            
 
1823
            //if it makes it here, it wasn't found at all
 
1824
            Y.Assert.fail(Y.Assert._formatMessage(message, "Value doesn't exist in array [" + haystack + "]."));
 
1825
        },
 
1826
            
 
1827
        /**
 
1828
         * Asserts that the values in an array are equal, and in the same position,
 
1829
         * as values in another array. This uses the double equals sign
 
1830
         * so type cohersion may occur. Note that the array objects themselves
 
1831
         * need not be the same for this test to pass.
 
1832
         * @param {Array} expected An array of the expected values.
 
1833
         * @param {Array} actual Any array of the actual values.
 
1834
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1835
         * @method itemsAreEqual
 
1836
         * @static
 
1837
         */
 
1838
        itemsAreEqual : function (expected /*:Array*/, actual /*:Array*/, 
 
1839
                               message /*:String*/) /*:Void*/ {
 
1840
            
 
1841
            //one may be longer than the other, so get the maximum length
 
1842
            var len /*:int*/ = Math.max(expected.length, actual.length);
 
1843
           
 
1844
            //begin checking values
 
1845
            for (var i=0; i < len; i++){
 
1846
                Y.Assert.areEqual(expected[i], actual[i], 
 
1847
                    Y.Assert._formatMessage(message, "Values in position " + i + " are not equal."));
 
1848
            }
 
1849
        },
 
1850
        
 
1851
        /**
 
1852
         * Asserts that the values in an array are equivalent, and in the same position,
 
1853
         * as values in another array. This uses a function to determine if the values
 
1854
         * are equivalent. Note that the array objects themselves
 
1855
         * need not be the same for this test to pass.
 
1856
         * @param {Array} expected An array of the expected values.
 
1857
         * @param {Array} actual Any array of the actual values.
 
1858
         * @param {Function} comparator A function that returns true if the values are equivalent
 
1859
         *      or false if not.
 
1860
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1861
         * @return {Void}
 
1862
         * @method itemsAreEquivalent
 
1863
         * @static
 
1864
         */
 
1865
        itemsAreEquivalent : function (expected /*:Array*/, actual /*:Array*/, 
 
1866
                               comparator /*:Function*/, message /*:String*/) /*:Void*/ {
 
1867
            
 
1868
            //make sure the comparator is valid
 
1869
            if (typeof comparator != "function"){
 
1870
                throw new TypeError("ArrayAssert.itemsAreEquivalent(): Third argument must be a function.");
 
1871
            }
 
1872
            
 
1873
            //one may be longer than the other, so get the maximum length
 
1874
            var len /*:int*/ = Math.max(expected.length, actual.length);
 
1875
            
 
1876
            //begin checking values
 
1877
            for (var i=0; i < len; i++){
 
1878
                if (!comparator(expected[i], actual[i])){
 
1879
                    throw new Y.Assert.ComparisonFailure(Y.Assert._formatMessage(message, "Values in position " + i + " are not equivalent."), expected[i], actual[i]);
 
1880
                }
 
1881
            }
 
1882
        },
 
1883
        
 
1884
        /**
 
1885
         * Asserts that an array is empty.
 
1886
         * @param {Array} actual The array to test.
 
1887
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1888
         * @method isEmpty
 
1889
         * @static
 
1890
         */
 
1891
        isEmpty : function (actual /*:Array*/, message /*:String*/) /*:Void*/ {        
 
1892
            if (actual.length > 0){
 
1893
                Y.Assert.fail(Y.Assert._formatMessage(message, "Array should be empty."));
 
1894
            }
 
1895
        },    
 
1896
        
 
1897
        /**
 
1898
         * Asserts that an array is not empty.
 
1899
         * @param {Array} actual The array to test.
 
1900
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1901
         * @method isNotEmpty
 
1902
         * @static
 
1903
         */
 
1904
        isNotEmpty : function (actual /*:Array*/, message /*:String*/) /*:Void*/ {        
 
1905
            if (actual.length === 0){
 
1906
                Y.Assert.fail(Y.Assert._formatMessage(message, "Array should not be empty."));
 
1907
            }
 
1908
        },    
 
1909
        
 
1910
        /**
 
1911
         * Asserts that the values in an array are the same, and in the same position,
 
1912
         * as values in another array. This uses the triple equals sign
 
1913
         * so no type cohersion will occur. Note that the array objects themselves
 
1914
         * need not be the same for this test to pass.
 
1915
         * @param {Array} expected An array of the expected values.
 
1916
         * @param {Array} actual Any array of the actual values.
 
1917
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1918
         * @method itemsAreSame
 
1919
         * @static
 
1920
         */
 
1921
        itemsAreSame : function (expected /*:Array*/, actual /*:Array*/, 
 
1922
                              message /*:String*/) /*:Void*/ {
 
1923
            
 
1924
            //one may be longer than the other, so get the maximum length
 
1925
            var len /*:int*/ = Math.max(expected.length, actual.length);
 
1926
            
 
1927
            //begin checking values
 
1928
            for (var i=0; i < len; i++){
 
1929
                Y.Assert.areSame(expected[i], actual[i], 
 
1930
                    Y.Assert._formatMessage(message, "Values in position " + i + " are not the same."));
 
1931
            }
 
1932
        },
 
1933
        
 
1934
        /**
 
1935
         * Asserts that the given value is contained in an array at the specified index,
 
1936
         * starting from the back of the array.
 
1937
         * This uses the triple equals sign so no type cohersion will occur.
 
1938
         * @param {Object} needle The value to look for.
 
1939
         * @param {Array} haystack The array to search in.
 
1940
         * @param {int} index The index at which the value should exist.
 
1941
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1942
         * @method lastIndexOf
 
1943
         * @static
 
1944
         */
 
1945
        lastIndexOf : function (needle /*:Object*/, haystack /*:Array*/, index /*:int*/, message /*:String*/) /*:Void*/ {
 
1946
        
 
1947
            //try to find the value in the array
 
1948
            for (var i=haystack.length; i >= 0; i--){
 
1949
                if (haystack[i] === needle){
 
1950
                    Y.Assert.areEqual(index, i, Y.Assert._formatMessage(message, "Value exists at index " + i + " but should be at index " + index + "."));
 
1951
                    return;
 
1952
                }
 
1953
            }
 
1954
            
 
1955
            //if it makes it here, it wasn't found at all
 
1956
            Y.Assert.fail(Y.Assert._formatMessage(message, "Value doesn't exist in array."));        
 
1957
        }
 
1958
        
 
1959
    };
 
1960
 
 
1961
 
 
1962
    /**
 
1963
     * The ObjectAssert object provides functions to test JavaScript objects
 
1964
     * for a variety of cases.
 
1965
     *
 
1966
     * @class ObjectAssert
 
1967
     * @static
 
1968
     */
 
1969
    Y.ObjectAssert = {
 
1970
    
 
1971
        areEqual: function(expected /*:Object*/, actual /*:Object*/, message /*:String*/) /*:Void*/ {
 
1972
            Y.Object.each(expected, function(value, name){
 
1973
                Y.Assert.areEqual(expected[name], actual[name], Y.Assert._formatMessage(message, "Values should be equal for property " + name));
 
1974
            });            
 
1975
        },
 
1976
        
 
1977
        /**
 
1978
         * Asserts that an object has a property with the given name.
 
1979
         * @param {String} propertyName The name of the property to test.
 
1980
         * @param {Object} object The object to search.
 
1981
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1982
         * @method has
 
1983
         * @static
 
1984
         */    
 
1985
        has : function (propertyName /*:String*/, object /*:Object*/, message /*:String*/) /*:Void*/ {
 
1986
            if (!(propertyName in object)){
 
1987
                Y.Assert.fail(Y.Assert._formatMessage(message, "Property '" + propertyName + "' not found on object."));
 
1988
            }    
 
1989
        },
 
1990
        
 
1991
        /**
 
1992
         * Asserts that an object has all properties of a reference object.
 
1993
         * @param {Object} refObject The object whose properties should be on the object to test.
 
1994
         * @param {Object} object The object to search.
 
1995
         * @param {String} message (Optional) The message to display if the assertion fails.
 
1996
         * @method hasAll
 
1997
         * @static
 
1998
         */    
 
1999
        hasAll : function (refObject /*:Object*/, object /*:Object*/, message /*:String*/) /*:Void*/ {
 
2000
            Y.Object.each(refObject, function(value, name){
 
2001
                if (!(name in object)){
 
2002
                    Y.Assert.fail(Y.Assert._formatMessage(message, "Property '" + name + "' not found on object."));
 
2003
                }    
 
2004
            });
 
2005
        },
 
2006
        
 
2007
        /**
 
2008
         * Asserts that a property with the given name exists on an object instance (not on its prototype).
 
2009
         * @param {String} propertyName The name of the property to test.
 
2010
         * @param {Object} object The object to search.
 
2011
         * @param {String} message (Optional) The message to display if the assertion fails.
 
2012
         * @method owns
 
2013
         * @static
 
2014
         */    
 
2015
        owns : function (propertyName /*:String*/, object /*:Object*/, message /*:String*/) /*:Void*/ {
 
2016
            if (!Y.Object.owns(object, propertyName)){
 
2017
                Y.Assert.fail(Y.Assert._formatMessage(message, "Property '" + propertyName + "' not found on object instance."));
 
2018
            }     
 
2019
        },
 
2020
        
 
2021
        /**
 
2022
         * Asserts that all properties on a given object also exist on an object instance (not on its prototype).
 
2023
         * @param {Object} refObject The object whose properties should be owned by the object to test.
 
2024
         * @param {Object} object The object to search.
 
2025
         * @param {String} message (Optional) The message to display if the assertion fails.
 
2026
         * @method ownsAll
 
2027
         * @static
 
2028
         */    
 
2029
        ownsAll : function (refObject /*:Object*/, object /*:Object*/, message /*:String*/) /*:Void*/ {
 
2030
            Y.Object.each(refObject, function(value, name){
 
2031
                if (!Y.Object.owns(object, name)){
 
2032
                    Y.Assert.fail(Y.Assert._formatMessage(message, "Property '" + name + "' not found on object instance."));
 
2033
                }     
 
2034
            });
 
2035
        }
 
2036
    };
 
2037
 
 
2038
 
 
2039
    
 
2040
    /**
 
2041
     * The DateAssert object provides functions to test JavaScript Date objects
 
2042
     * for a variety of cases.
 
2043
     *
 
2044
     * @class DateAssert
 
2045
     * @static
 
2046
     */
 
2047
     
 
2048
    Y.DateAssert = {
 
2049
    
 
2050
        /**
 
2051
         * Asserts that a date's month, day, and year are equal to another date's.
 
2052
         * @param {Date} expected The expected date.
 
2053
         * @param {Date} actual The actual date to test.
 
2054
         * @param {String} message (Optional) The message to display if the assertion fails.
 
2055
         * @method datesAreEqual
 
2056
         * @static
 
2057
         */
 
2058
        datesAreEqual : function (expected /*:Date*/, actual /*:Date*/, message /*:String*/){
 
2059
            if (expected instanceof Date && actual instanceof Date){
 
2060
                Y.AssertareEqual(expected.getFullYear(), actual.getFullYear(), Y.Assert_formatMessage(message, "Years should be equal."));
 
2061
                Y.AssertareEqual(expected.getMonth(), actual.getMonth(), Y.Assert_formatMessage(message, "Months should be equal."));
 
2062
                Y.AssertareEqual(expected.getDate(), actual.getDate(), Y.Assert_formatMessage(message, "Day of month should be equal."));
 
2063
            } else {
 
2064
                throw new TypeError("DateY.AssertdatesAreEqual(): Expected and actual values must be Date objects.");
 
2065
            }
 
2066
        },
 
2067
    
 
2068
        /**
 
2069
         * Asserts that a date's hour, minutes, and seconds are equal to another date's.
 
2070
         * @param {Date} expected The expected date.
 
2071
         * @param {Date} actual The actual date to test.
 
2072
         * @param {String} message (Optional) The message to display if the assertion fails.
 
2073
         * @method timesAreEqual
 
2074
         * @static
 
2075
         */
 
2076
        timesAreEqual : function (expected /*:Date*/, actual /*:Date*/, message /*:String*/){
 
2077
            if (expected instanceof Date && actual instanceof Date){
 
2078
                Y.AssertareEqual(expected.getHours(), actual.getHours(), Y.Assert_formatMessage(message, "Hours should be equal."));
 
2079
                Y.AssertareEqual(expected.getMinutes(), actual.getMinutes(), Y.Assert_formatMessage(message, "Minutes should be equal."));
 
2080
                Y.AssertareEqual(expected.getSeconds(), actual.getSeconds(), Y.Assert_formatMessage(message, "Seconds should be equal."));
 
2081
            } else {
 
2082
                throw new TypeError("DateY.AsserttimesAreEqual(): Expected and actual values must be Date objects.");
 
2083
            }
 
2084
        }
 
2085
        
 
2086
    };
 
2087
 
 
2088
    
 
2089
    Y.namespace("Test.Format");
 
2090
    
 
2091
    /**
 
2092
     * Returns test results formatted as a JSON string. Requires JSON utility.
 
2093
     * @param {Object} result The results object created by TestRunner.
 
2094
     * @return {String} A JSON-formatted string of results.
 
2095
     * @namespace Test.Format
 
2096
     * @method JSON
 
2097
     * @static
 
2098
     */
 
2099
    Y.Test.Format.JSON = function(results /*:Object*/) /*:String*/ {
 
2100
        return Y.JSON.stringify(results);
 
2101
    };
 
2102
    
 
2103
    /**
 
2104
     * Returns test results formatted as an XML string.
 
2105
     * @param {Object} result The results object created by TestRunner.
 
2106
     * @return {String} An XML-formatted string of results.
 
2107
     * @namespace Test.Format
 
2108
     * @method XML
 
2109
     * @static
 
2110
     */
 
2111
    Y.Test.Format.XML = function(results /*:Object*/) /*:String*/ {
 
2112
    
 
2113
        var l = Y.Lang;
 
2114
        var xml /*:String*/ = "<" + results.type + " name=\"" + results.name.replace(/"/g, "&quot;").replace(/'/g, "&apos;") + "\"";
 
2115
        
 
2116
        if (results.type == "test"){
 
2117
            xml += " result=\"" + results.result + "\" message=\"" + results.message + "\">";
 
2118
        } else {
 
2119
            xml += " passed=\"" + results.passed + "\" failed=\"" + results.failed + "\" ignored=\"" + results.ignored + "\" total=\"" + results.total + "\">";
 
2120
            for (var prop in results) {
 
2121
                if (Y.Object.owns(results, prop) && l.isObject(results[prop]) && !l.isArray(results[prop])){
 
2122
                    xml += arguments.callee(results[prop]);
 
2123
                }
 
2124
            }        
 
2125
        }
 
2126
    
 
2127
        xml += "</" + results.type + ">";
 
2128
        
 
2129
        return xml;
 
2130
    
 
2131
    };
 
2132
 
 
2133
 
 
2134
    Y.namespace("Test");
 
2135
    
 
2136
    /**
 
2137
     * An object capable of sending test results to a server.
 
2138
     * @param {String} url The URL to submit the results to.
 
2139
     * @param {Function} format (Optiona) A function that outputs the results in a specific format.
 
2140
     *      Default is Y.Test.Format.XML.
 
2141
     * @constructor
 
2142
     * @namespace Test
 
2143
     * @class Reporter
 
2144
     */
 
2145
    Y.Test.Reporter = function(url /*:String*/, format /*:Function*/) {
 
2146
    
 
2147
        /**
 
2148
         * The URL to submit the data to.
 
2149
         * @type String
 
2150
         * @property url
 
2151
         */
 
2152
        this.url /*:String*/ = url;
 
2153
    
 
2154
        /**
 
2155
         * The formatting function to call when submitting the data.
 
2156
         * @type Function
 
2157
         * @property format
 
2158
         */
 
2159
        this.format /*:Function*/ = format || Y.Test.Format.XML;
 
2160
    
 
2161
        /**
 
2162
         * Extra fields to submit with the request.
 
2163
         * @type Object
 
2164
         * @property _fields
 
2165
         * @private
 
2166
         */
 
2167
        this._fields /*:Object*/ = new Object();
 
2168
        
 
2169
        /**
 
2170
         * The form element used to submit the results.
 
2171
         * @type HTMLFormElement
 
2172
         * @property _form
 
2173
         * @private
 
2174
         */
 
2175
        this._form /*:HTMLElement*/ = null;
 
2176
    
 
2177
        /**
 
2178
         * Iframe used as a target for form submission.
 
2179
         * @type HTMLIFrameElement
 
2180
         * @property _iframe
 
2181
         * @private
 
2182
         */
 
2183
        this._iframe /*:HTMLElement*/ = null;
 
2184
    };
 
2185
    
 
2186
    Y.Test.Reporter.prototype = {
 
2187
    
 
2188
        //restore missing constructor
 
2189
        constructor: Y.Test.Reporter,
 
2190
    
 
2191
        /**
 
2192
         * Adds a field to the form that submits the results.
 
2193
         * @param {String} name The name of the field.
 
2194
         * @param {Variant} value The value of the field.
 
2195
         * @return {Void}
 
2196
         * @method addField
 
2197
         */
 
2198
        addField : function (name /*:String*/, value /*:Variant*/) /*:Void*/{
 
2199
            this._fields[name] = value;    
 
2200
        },
 
2201
        
 
2202
        /**
 
2203
         * Removes all previous defined fields.
 
2204
         * @return {Void}
 
2205
         * @method addField
 
2206
         */
 
2207
        clearFields : function() /*:Void*/{
 
2208
            this._fields = new Object();
 
2209
        },
 
2210
    
 
2211
        /**
 
2212
         * Cleans up the memory associated with the TestReporter, removing DOM elements
 
2213
         * that were created.
 
2214
         * @return {Void}
 
2215
         * @method destroy
 
2216
         */
 
2217
        destroy : function() /*:Void*/ {
 
2218
            if (this._form){
 
2219
                this._form.parentNode.removeChild(this._form);
 
2220
                this._form = null;
 
2221
            }        
 
2222
            if (this._iframe){
 
2223
                this._iframe.parentNode.removeChild(this._iframe);
 
2224
                this._iframe = null;
 
2225
            }
 
2226
            this._fields = null;
 
2227
        },
 
2228
    
 
2229
        /**
 
2230
         * Sends the report to the server.
 
2231
         * @param {Object} results The results object created by TestRunner.
 
2232
         * @return {Void}
 
2233
         * @method report
 
2234
         */
 
2235
        report : function(results /*:Object*/) /*:Void*/{
 
2236
        
 
2237
            //if the form hasn't been created yet, create it
 
2238
            if (!this._form){
 
2239
                this._form = document.createElement("form");
 
2240
                this._form.method = "post";
 
2241
                this._form.style.visibility = "hidden";
 
2242
                this._form.style.position = "absolute";
 
2243
                this._form.style.top = 0;
 
2244
                document.body.appendChild(this._form);
 
2245
            
 
2246
                //IE won't let you assign a name using the DOM, must do it the hacky way
 
2247
                if (Y.UA.ie){
 
2248
                    this._iframe = document.createElement("<iframe name=\"yuiTestTarget\" />");
 
2249
                } else {
 
2250
                    this._iframe = document.createElement("iframe");
 
2251
                    this._iframe.name = "yuiTestTarget";
 
2252
                }
 
2253
    
 
2254
                this._iframe.src = "javascript:false";
 
2255
                this._iframe.style.visibility = "hidden";
 
2256
                this._iframe.style.position = "absolute";
 
2257
                this._iframe.style.top = 0;
 
2258
                document.body.appendChild(this._iframe);
 
2259
    
 
2260
                this._form.target = "yuiTestTarget";
 
2261
            }
 
2262
    
 
2263
            //set the form's action
 
2264
            this._form.action = this.url;
 
2265
        
 
2266
            //remove any existing fields
 
2267
            while(this._form.hasChildNodes()){
 
2268
                this._form.removeChild(this._form.lastChild);
 
2269
            }
 
2270
            
 
2271
            //create default fields
 
2272
            this._fields.results = this.format(results);
 
2273
            this._fields.useragent = navigator.userAgent;
 
2274
            this._fields.timestamp = (new Date()).toLocaleString();
 
2275
    
 
2276
            //add fields to the form
 
2277
            for (var prop in this._fields){
 
2278
                if (Y.Object.owns(this._fields, prop) && typeof this._fields[prop] != "function"){
 
2279
                    var input = document.createElement("input");
 
2280
                    input.type = "hidden";
 
2281
                    input.name = prop;
 
2282
                    input.value = this._fields[prop];
 
2283
                    this._form.appendChild(input);
 
2284
                }
 
2285
            }
 
2286
    
 
2287
            //remove default fields
 
2288
            delete this._fields.results;
 
2289
            delete this._fields.useragent;
 
2290
            delete this._fields.timestamp;
 
2291
            
 
2292
            if (arguments[1] !== false){
 
2293
                this._form.submit();
 
2294
            }
 
2295
        
 
2296
        }
 
2297
    
 
2298
    };
 
2299
 
 
2300
    /**
 
2301
     * Creates a new mock object.
 
2302
     * @class Mock
 
2303
     * @constructor
 
2304
     * @param {Object} template (Optional) An object whose methods
 
2305
     *      should be stubbed out on the mock object.
 
2306
     */
 
2307
    Y.Mock = function(template){
 
2308
    
 
2309
        //use blank object is nothing is passed in
 
2310
        template = template || {};
 
2311
        
 
2312
        var mock = null;
 
2313
        
 
2314
        //try to create mock that keeps prototype chain intact
 
2315
        try {
 
2316
            mock = Y.Object(template);
 
2317
        } catch (ex) {
 
2318
            mock = {};
 
2319
            Y.log("Couldn't create mock with prototype.", "warn", "Mock");
 
2320
        }
 
2321
        
 
2322
        //create new versions of the methods so that they don't actually do anything
 
2323
        Y.Object.each(template, function(name){
 
2324
            if (Y.Lang.isFunction(template[name])){
 
2325
                mock[name] = function(){
 
2326
                    Y.Assert.fail("Method " + name + "() was called but was not expected to be.");
 
2327
                };
 
2328
            }
 
2329
        });
 
2330
        
 
2331
        //return it
 
2332
        return mock;    
 
2333
    };
 
2334
        
 
2335
    /**
 
2336
     * Assigns an expectation to a mock object. This is used to create
 
2337
     * methods and properties on the mock object that are monitored for
 
2338
     * calls and changes, respectively.
 
2339
     * @param {Object} mock The object to add the expectation to.
 
2340
     * @param {Object} expectation An object defining the expectation. For
 
2341
     *      a method, the keys "method" and "args" are required with
 
2342
     *      an optional "returns" key available. For properties, the keys
 
2343
     *      "property" and "value" are required.
 
2344
     * @return {void}
 
2345
     * @method expect
 
2346
     * @static
 
2347
     */ 
 
2348
    Y.Mock.expect = function(mock /*:Object*/, expectation /*:Object*/){
 
2349
 
 
2350
        //make sure there's a place to store the expectations
 
2351
        if (!mock.__expectations) {
 
2352
            mock.__expectations = {};
 
2353
        }
 
2354
 
 
2355
        //method expectation
 
2356
        if (expectation.method){
 
2357
            var name = expectation.method,
 
2358
                args = expectation.args || expectation.arguments || [],
 
2359
                result = expectation.returns,
 
2360
                callCount = Y.Lang.isNumber(expectation.callCount) ? expectation.callCount : 1,
 
2361
                error = expectation.error,
 
2362
                run = expectation.run || function(){};
 
2363
                
 
2364
            //save expectations
 
2365
            mock.__expectations[name] = expectation;
 
2366
            expectation.callCount = callCount;
 
2367
            expectation.actualCallCount = 0;
 
2368
                
 
2369
            //process arguments
 
2370
            Y.Array.each(args, function(arg, i, array){
 
2371
                if (!(array[i] instanceof Y.Mock.Value)){
 
2372
                    array[i] = Y.Mock.Value(Y.Assert.areSame, [arg], "Argument " + i + " of " + name + "() is incorrect.");
 
2373
                }
 
2374
            });
 
2375
        
 
2376
            //if the method is expected to be called
 
2377
            if (callCount > 0){
 
2378
                mock[name] = function(){   
 
2379
                    expectation.actualCallCount++;
 
2380
                    Y.Assert.areEqual(args.length, arguments.length, "Method " + name + "() passed incorrect number of arguments.");
 
2381
                    for (var i=0, len=args.length; i < len; i++){
 
2382
                        if (args[i]){
 
2383
                            args[i].verify(arguments[i]);
 
2384
                        } else {
 
2385
                            Y.Assert.fail("Argument " + i + " (" + arguments[i] + ") was not expected to be used.");
 
2386
                        }
 
2387
                        
 
2388
                    }                
 
2389
 
 
2390
                    run.apply(this, arguments);
 
2391
                    
 
2392
                    if (error){
 
2393
                        throw error;
 
2394
                    }
 
2395
                    
 
2396
                    return result;
 
2397
                };
 
2398
            } else {
 
2399
            
 
2400
                //method should fail if called when not expected
 
2401
                mock[name] = function(){
 
2402
                    Y.Assert.fail("Method " + name + "() should not have been called.");
 
2403
                };
 
2404
            }
 
2405
        } else if (expectation.property){
 
2406
            //save expectations
 
2407
            mock.__expectations[name] = expectation;
 
2408
        }
 
2409
    };
 
2410
 
 
2411
    /**
 
2412
     * Verifies that all expectations of a mock object have been met and
 
2413
     * throws an assertion error if not.
 
2414
     * @param {Object} mock The object to verify..
 
2415
     * @return {void}
 
2416
     * @method verify
 
2417
     * @static
 
2418
     */ 
 
2419
    Y.Mock.verify = function(mock /*:Object*/){    
 
2420
        Y.Object.each(mock.__expectations, function(expectation){
 
2421
            if (expectation.method) {
 
2422
                Y.Assert.areEqual(expectation.callCount, expectation.actualCallCount, "Method " + expectation.method + "() wasn't called the expected number of times.");
 
2423
            } else if (expectation.property){
 
2424
                Y.Assert.areEqual(expectation.value, mock[expectation.property], "Property " + expectation.property + " wasn't set to the correct value."); 
 
2425
            }
 
2426
        });    
 
2427
    };
 
2428
 
 
2429
    Y.Mock.Value = function(method, args, message){
 
2430
        if (this instanceof Y.Mock.Value){
 
2431
            this.verify = function(value){
 
2432
                args = [].concat(args);
 
2433
                args.push(value);
 
2434
                args.push(message);
 
2435
                method.apply(null, args);
 
2436
            };
 
2437
        } else {
 
2438
            return new Y.Mock.Value(method, args, message);
 
2439
        }
 
2440
    };
 
2441
    
 
2442
    Y.Mock.Value.Any = Y.Mock.Value(function(){},[]);
 
2443
    Y.Mock.Value.Boolean = Y.Mock.Value(Y.Assert.isBoolean,[]);
 
2444
    Y.Mock.Value.Number = Y.Mock.Value(Y.Assert.isNumber,[]);
 
2445
    Y.Mock.Value.String = Y.Mock.Value(Y.Assert.isString,[]);
 
2446
    Y.Mock.Value.Object = Y.Mock.Value(Y.Assert.isObject,[]);
 
2447
    Y.Mock.Value.Function = Y.Mock.Value(Y.Assert.isFunction,[]);
 
2448
 
 
2449
 
 
2450
 
 
2451
}, '3.0.0pr2' ,{requires:['substitute','event-custom','array','oop','event-target','event-simulate']});