MDL-11082 Improved groups upgrade performance 1.8x -> 1.9; thanks Eloy for telling...
[moodle-pu.git] / lib / yui / yuitest / yuitest-beta-debug.js
blob0efbbf536f6f28faeec4be0d89004d3dbe0771c2
1 /*
2 Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
5 version: 2.3.0
6 */
7 YAHOO.namespace("tool");
9 //-----------------------------------------------------------------------------
10 // TestLogger object
11 //-----------------------------------------------------------------------------
13 /**
14 * Displays test execution progress and results, providing filters based on
15 * different key events.
16 * @namespace YAHOO.tool
17 * @class TestLogger
18 * @constructor
19 * @param {HTMLElement} element (Optional) The element to create the logger in.
20 * @param {Object} config (Optional) Configuration options for the logger.
22 YAHOO.tool.TestLogger = function (element, config) {
23 YAHOO.tool.TestLogger.superclass.constructor.call(this, element, config);
24 this.init();
27 YAHOO.lang.extend(YAHOO.tool.TestLogger, YAHOO.widget.LogReader, {
29 footerEnabled : true,
30 newestOnTop : false,
32 /**
33 * Formats message string to HTML for output to console.
34 * @private
35 * @method formatMsg
36 * @param oLogMsg {Object} Log message object.
37 * @return {String} HTML-formatted message for output to console.
39 formatMsg : function(message /*:Object*/) {
41 var category /*:String*/ = message.category;
42 var text /*:String*/ = this.html2Text(message.msg);
44 return "<pre><p><span class=\"" + category + "\">" + category.toUpperCase() + "</span> " + text + "</p></pre>";
48 //-------------------------------------------------------------------------
49 // Private Methods
50 //-------------------------------------------------------------------------
53 * Initializes the logger.
54 * @private
56 init : function () {
58 //attach to any available TestRunner
59 if (YAHOO.tool.TestRunner){
60 this.setTestRunner(YAHOO.tool.TestRunner);
63 //hide useless sources
64 this.hideSource("global");
65 this.hideSource("LogReader");
67 //hide useless message categories
68 this.hideCategory("warn");
69 this.hideCategory("window");
70 this.hideCategory("time");
72 //reset the logger
73 this.clearConsole();
76 /**
77 * Clears the reference to the TestRunner from previous operations. This
78 * unsubscribes all events and removes the object reference.
79 * @return {Void}
80 * @static
82 clearTestRunner : function () /*:Void*/ {
83 if (this._runner){
84 this._runner.unsubscribeAll();
85 this._runner = null;
89 /**
90 * Sets the source test runner that the logger should monitor.
91 * @param {YAHOO.tool.TestRunner} testRunner The TestRunner to observe.
92 * @return {Void}
93 * @static
95 setTestRunner : function (testRunner /*:YAHOO.tool.TestRunner*/) /*:Void*/ {
97 if (this._runner){
98 this.clearTestRunner();
101 this._runner = testRunner;
103 //setup event _handlers
104 testRunner.subscribe(testRunner.TEST_PASS_EVENT, this._handleTestRunnerEvent, this, true);
105 testRunner.subscribe(testRunner.TEST_FAIL_EVENT, this._handleTestRunnerEvent, this, true);
106 testRunner.subscribe(testRunner.TEST_IGNORE_EVENT, this._handleTestRunnerEvent, this, true);
107 testRunner.subscribe(testRunner.BEGIN_EVENT, this._handleTestRunnerEvent, this, true);
108 testRunner.subscribe(testRunner.COMPLETE_EVENT, this._handleTestRunnerEvent, this, true);
109 testRunner.subscribe(testRunner.TEST_SUITE_BEGIN_EVENT, this._handleTestRunnerEvent, this, true);
110 testRunner.subscribe(testRunner.TEST_SUITE_COMPLETE_EVENT, this._handleTestRunnerEvent, this, true);
111 testRunner.subscribe(testRunner.TEST_CASE_BEGIN_EVENT, this._handleTestRunnerEvent, this, true);
112 testRunner.subscribe(testRunner.TEST_CASE_COMPLETE_EVENT, this._handleTestRunnerEvent, this, true);
115 //-------------------------------------------------------------------------
116 // Event Handlers
117 //-------------------------------------------------------------------------
120 * Handles all TestRunner events, outputting appropriate data into the console.
121 * @param {Object} data The event data object.
122 * @return {Void}
123 * @private
125 _handleTestRunnerEvent : function (data /*:Object*/) /*:Void*/ {
127 //shortcut variables
128 var TestRunner /*:Object*/ = YAHOO.tool.TestRunner;
130 //data variables
131 var message /*:String*/ = "";
132 var messageType /*:String*/ = "";
134 switch(data.type){
135 case TestRunner.BEGIN_EVENT:
136 message = "Testing began at " + (new Date()).toString() + ".";
137 messageType = "info";
138 break;
140 case TestRunner.COMPLETE_EVENT:
141 message = "Testing completed at " + (new Date()).toString() + ".\nPassed:"
142 + data.results.passed + " Failed:" + data.results.failed + " Total:" + data.results.total;
143 messageType = "info";
144 break;
146 case TestRunner.TEST_FAIL_EVENT:
147 message = data.testName + ": " + data.error.getMessage();
148 messageType = "fail";
149 break;
151 case TestRunner.TEST_IGNORE_EVENT:
152 message = data.testName + ": ignored.";
153 messageType = "ignore";
154 break;
156 case TestRunner.TEST_PASS_EVENT:
157 message = data.testName + ": passed.";
158 messageType = "pass";
159 break;
161 case TestRunner.TEST_SUITE_BEGIN_EVENT:
162 message = "Test suite \"" + data.testSuite.name + "\" started.";
163 messageType = "info";
164 break;
166 case TestRunner.TEST_SUITE_COMPLETE_EVENT:
167 message = "Test suite \"" + data.testSuite.name + "\" completed.\nPassed:"
168 + data.results.passed + " Failed:" + data.results.failed + " Total:" + data.results.total;
169 messageType = "info";
170 break;
172 case TestRunner.TEST_CASE_BEGIN_EVENT:
173 message = "Test case \"" + data.testCase.name + "\" started.";
174 messageType = "info";
175 break;
177 case TestRunner.TEST_CASE_COMPLETE_EVENT:
178 message = "Test case \"" + data.testCase.name + "\" completed.\nPassed:"
179 + data.results.passed + " Failed:" + data.results.failed + " Total:" + data.results.total;
180 messageType = "info";
181 break;
182 default:
183 message = "Unexpected event " + data.type;
184 message = "info";
187 YAHOO.log(message, messageType, "TestRunner");
191 YAHOO.namespace("tool");
194 * The YUI test tool
195 * @module yuitest
196 * @namespace YAHOO.tool
197 * @requires yahoo,dom,event,logger
201 //-----------------------------------------------------------------------------
202 // TestRunner object
203 //-----------------------------------------------------------------------------
206 * Runs test suites and test cases, providing events to allowing for the
207 * interpretation of test results.
208 * @namespace YAHOO.tool
209 * @class TestRunner
210 * @static
212 YAHOO.tool.TestRunner = (function(){
214 function TestRunner(){
216 //inherit from EventProvider
217 TestRunner.superclass.constructor.apply(this,arguments);
220 * The test objects to run.
221 * @type Array
222 * @private
224 this.items /*:Array*/ = [];
226 //create events
227 var events /*:Array*/ = [
228 this.TEST_CASE_BEGIN_EVENT,
229 this.TEST_CASE_COMPLETE_EVENT,
230 this.TEST_SUITE_BEGIN_EVENT,
231 this.TEST_SUITE_COMPLETE_EVENT,
232 this.TEST_PASS_EVENT,
233 this.TEST_FAIL_EVENT,
234 this.TEST_IGNORE_EVENT,
235 this.COMPLETE_EVENT,
236 this.BEGIN_EVENT
238 for (var i=0; i < events.length; i++){
239 this.createEvent(events[i], { scope: this });
245 YAHOO.lang.extend(TestRunner, YAHOO.util.EventProvider, {
247 //-------------------------------------------------------------------------
248 // Constants
249 //-------------------------------------------------------------------------
252 * Fires when a test case is opened but before the first
253 * test is executed.
254 * @event testcasebegin
256 TEST_CASE_BEGIN_EVENT /*:String*/ : "testcasebegin",
259 * Fires when all tests in a test case have been executed.
260 * @event testcasecomplete
262 TEST_CASE_COMPLETE_EVENT /*:String*/ : "testcasecomplete",
265 * Fires when a test suite is opened but before the first
266 * test is executed.
267 * @event testsuitebegin
269 TEST_SUITE_BEGIN_EVENT /*:String*/ : "testsuitebegin",
272 * Fires when all test cases in a test suite have been
273 * completed.
274 * @event testsuitecomplete
276 TEST_SUITE_COMPLETE_EVENT /*:String*/ : "testsuitecomplete",
279 * Fires when a test has passed.
280 * @event pass
282 TEST_PASS_EVENT /*:String*/ : "pass",
285 * Fires when a test has failed.
286 * @event fail
288 TEST_FAIL_EVENT /*:String*/ : "fail",
291 * Fires when a test has been ignored.
292 * @event ignore
294 TEST_IGNORE_EVENT /*:String*/ : "ignore",
297 * Fires when all test suites and test cases have been completed.
298 * @event complete
300 COMPLETE_EVENT /*:String*/ : "complete",
303 * Fires when the run() method is called.
304 * @event begin
306 BEGIN_EVENT /*:String*/ : "begin",
308 //-------------------------------------------------------------------------
309 // Private Methods
310 //-------------------------------------------------------------------------
313 * Runs a given test case.
314 * @param {YAHOO.tool.TestCase} testCase The test case to run.
315 * @return {Object} Results of the execution with properties passed, failed, and total.
316 * @method _runTestCase
317 * @private
318 * @static
320 _runTestCase : function (testCase /*YAHOO.tool.TestCase*/) /*:Void*/{
322 //object to store results
323 var results /*:Object*/ = {};
325 //test case begins
326 this.fireEvent(this.TEST_CASE_BEGIN_EVENT, { testCase: testCase });
328 //gather the test functions
329 var tests /*:Array*/ = [];
330 for (var prop in testCase){
331 if (prop.indexOf("test") === 0 && typeof testCase[prop] == "function") {
332 tests.push(prop);
336 //get the "should" test cases
337 var shouldFail /*:Object*/ = testCase._should.fail || {};
338 var shouldError /*:Object*/ = testCase._should.error || {};
339 var shouldIgnore /*:Object*/ = testCase._should.ignore || {};
341 //test counts
342 var failCount /*:int*/ = 0;
343 var passCount /*:int*/ = 0;
344 var runCount /*:int*/ = 0;
346 //run each test
347 for (var i=0; i < tests.length; i++){
349 //figure out if the test should be ignored or not
350 if (shouldIgnore[tests[i]]){
351 this.fireEvent(this.TEST_IGNORE_EVENT, { testCase: testCase, testName: tests[i] });
352 continue;
355 //variable to hold whether or not the test failed
356 var failed /*:Boolean*/ = false;
357 var error /*:Error*/ = null;
359 //run the setup
360 testCase.setUp();
362 //try the test
363 try {
365 //run the test
366 testCase[tests[i]]();
368 //if it should fail, and it got here, then it's a fail because it didn't
369 if (shouldFail[tests[i]]){
370 error = new YAHOO.util.ShouldFail();
371 failed = true;
372 } else if (shouldError[tests[i]]){
373 error = new YAHOO.util.ShouldError();
374 failed = true;
377 } catch (thrown /*:Error*/){
378 if (thrown instanceof YAHOO.util.AssertionError) {
379 if (!shouldFail[tests[i]]){
380 error = thrown;
381 failed = true;
383 } else {
384 //first check to see if it should error
385 if (!shouldError[tests[i]]) {
386 error = new YAHOO.util.UnexpectedError(thrown);
387 failed = true;
388 } else {
389 //check to see what type of data we have
390 if (YAHOO.lang.isString(shouldError[tests[i]])){
392 //if it's a string, check the error message
393 if (thrown.message != shouldError[tests[i]]){
394 error = new YAHOO.util.UnexpectedError(thrown);
395 failed = true;
397 } else if (YAHOO.lang.isObject(shouldError[tests[i]])){
399 //if it's an object, check the instance and message
400 if (!(thrown instanceof shouldError[tests[i]].constructor) ||
401 thrown.message != shouldError[tests[i]].message){
402 error = new YAHOO.util.UnexpectedError(thrown);
403 failed = true;
411 } finally {
413 //fireEvent appropriate event
414 if (failed) {
415 this.fireEvent(this.TEST_FAIL_EVENT, { testCase: testCase, testName: tests[i], error: error });
416 } else {
417 this.fireEvent(this.TEST_PASS_EVENT, { testCase: testCase, testName: tests[i] });
421 //run the tear down
422 testCase.tearDown();
424 //update results
425 results[tests[i]] = {
426 result: failed ? "fail" : "pass",
427 message : error ? error.getMessage() : "Test passed"
430 //update counts
431 runCount++;
432 failCount += (failed ? 1 : 0);
433 passCount += (failed ? 0 : 1);
436 //add test counts to results
437 results.total = runCount;
438 results.failed = failCount;
439 results.passed = passCount;
441 //test case is done
442 this.fireEvent(this.TEST_CASE_COMPLETE_EVENT, { testCase: testCase, results: results });
444 //return results
445 return results;
450 * Runs all the tests in a test suite.
451 * @param {YAHOO.tool.TestSuite} testSuite The test suite to run.
452 * @return {Object} Results of the execution with properties passed, failed, and total.
453 * @method _runTestSuite
454 * @private
455 * @static
457 _runTestSuite : function (testSuite /*:YAHOO.tool.TestSuite*/) {
459 //object to store results
460 var results /*:Object*/ = {
461 passed: 0,
462 failed: 0,
463 total: 0
466 //fireEvent event for beginning of test suite run
467 this.fireEvent(this.TEST_SUITE_BEGIN_EVENT, { testSuite: testSuite });
469 //iterate over the test suite items
470 for (var i=0; i < testSuite.items.length; i++){
471 var result = null;
472 if (testSuite.items[i] instanceof YAHOO.tool.TestSuite) {
473 result = this._runTestSuite(testSuite.items[i]);
474 } else if (testSuite.items[i] instanceof YAHOO.tool.TestCase) {
475 result = this._runTestCase(testSuite.items[i]);
478 if (result !== null){
479 results.total += result.total;
480 results.passed += result.passed;
481 results.failed += result.failed;
482 results[testSuite.items[i].name] = result;
486 //fireEvent event for completion of test suite run
487 this.fireEvent(this.TEST_SUITE_COMPLETE_EVENT, { testSuite: testSuite, results: results });
489 //return the results
490 return results;
495 * Runs a test case or test suite, returning the results.
496 * @param {YAHOO.tool.TestCase|YAHOO.tool.TestSuite} testObject The test case or test suite to run.
497 * @return {Object} Results of the execution with properties passed, failed, and total.
498 * @private
499 * @method _run
500 * @static
502 _run : function (testObject /*:YAHOO.tool.TestCase|YAHOO.tool.TestSuite*/) /*:Void*/ {
503 if (YAHOO.lang.isObject(testObject)){
504 if (testObject instanceof YAHOO.tool.TestSuite) {
505 return this._runTestSuite(testObject);
506 } else if (testObject instanceof YAHOO.tool.TestCase) {
507 return this._runTestCase(testObject);
508 } else {
509 throw new TypeError("_run(): Expected either YAHOO.tool.TestCase or YAHOO.tool.TestSuite.");
514 //-------------------------------------------------------------------------
515 // Protected Methods
516 //-------------------------------------------------------------------------
519 * Fires events for the TestRunner. This overrides the default fireEvent()
520 * method from EventProvider to add the type property to the data that is
521 * passed through on each event call.
522 * @param {String} type The type of event to fire.
523 * @param {Object} data (Optional) Data for the event.
524 * @method fireEvent
525 * @static
526 * @protected
528 fireEvent : function (type /*:String*/, data /*:Object*/) /*:Void*/ {
529 data = data || {};
530 data.type = type;
531 TestRunner.superclass.fireEvent.call(this, type, data);
534 //-------------------------------------------------------------------------
535 // Public Methods
536 //-------------------------------------------------------------------------
539 * Adds a test suite or test case to the list of test objects to run.
540 * @param testObject Either a TestCase or a TestSuite that should be run.
542 add : function (testObject /*:Object*/) /*:Void*/ {
543 this.items.push(testObject);
547 * Removes all test objects from the runner.
549 clear : function () /*:Void*/ {
550 while(this.items.length){
551 this.items.pop();
556 * Runs the test suite.
558 run : function (testObject /*:Object*/) /*:Void*/ {
559 var results = null;
561 this.fireEvent(this.BEGIN_EVENT);
563 //an object passed in overrides everything else
564 if (YAHOO.lang.isObject(testObject)){
565 results = this._run(testObject);
566 } else {
567 results = {
568 passed: 0,
569 failed: 0,
570 total: 0
572 for (var i=0; i < this.items.length; i++){
573 var result = this._run(this.items[i]);
574 results.passed += result.passed;
575 results.failed += result.failed;
576 results.total += result.total;
577 results[this.items[i].name] = result;
581 this.fireEvent(this.COMPLETE_EVENT, { results: results });
585 return new TestRunner();
587 })();
588 YAHOO.namespace("tool");
591 //-----------------------------------------------------------------------------
592 // TestSuite object
593 //-----------------------------------------------------------------------------
596 * A test suite that can contain a collection of TestCase and TestSuite objects.
597 * @param {String} name The name of the test fixture.
598 * @namespace YAHOO.tool
599 * @class TestSuite
600 * @constructor
602 YAHOO.tool.TestSuite = function (name /*:String*/) {
605 * The name of the test suite.
607 this.name /*:String*/ = name || YAHOO.util.Dom.generateId(null, "testSuite");
610 * Array of test suites and
611 * @private
613 this.items /*:Array*/ = [];
617 YAHOO.tool.TestSuite.prototype = {
620 * Adds a test suite or test case to the test suite.
621 * @param {YAHOO.tool.TestSuite||YAHOO.tool.TestCase} testObject The test suite or test case to add.
623 add : function (testObject /*:YAHOO.tool.TestSuite*/) /*:Void*/ {
624 if (testObject instanceof YAHOO.tool.TestSuite || testObject instanceof YAHOO.tool.TestCase) {
625 this.items.push(testObject);
630 YAHOO.namespace("tool");
632 //-----------------------------------------------------------------------------
633 // TestCase object
634 //-----------------------------------------------------------------------------
637 * Test case containing various tests to run.
638 * @param template An object containing any number of test methods, other methods,
639 * an optional name, and anything else the test case needs.
640 * @class TestCase
641 * @namespace YAHOO.tool
642 * @constructor
644 YAHOO.tool.TestCase = function (template /*:Object*/) {
647 * Special rules for the test case. Possible subobjects
648 * are fail, for tests that should fail, and error, for
649 * tests that should throw an error.
651 this._should /*:Object*/ = {};
653 //copy over all properties from the template to this object
654 for (var prop in template) {
655 this[prop] = template[prop];
658 //check for a valid name
659 if (!YAHOO.lang.isString(this.name)){
661 * Name for the test case.
663 this.name /*:String*/ = YAHOO.util.Dom.generateId(null, "testCase");
668 YAHOO.tool.TestCase.prototype = {
670 //-------------------------------------------------------------------------
671 // Test Methods
672 //-------------------------------------------------------------------------
675 * Function to run before each test is executed.
677 setUp : function () /*:Void*/ {
681 * Function to run after each test is executed.
683 tearDown: function () /*:Void*/ {
686 YAHOO.namespace("util");
688 //-----------------------------------------------------------------------------
689 // Assert object
690 //-----------------------------------------------------------------------------
693 * The Assert object provides functions to test JavaScript values against
694 * known and expected results. Whenever a comparison (assertion) fails,
695 * an error is thrown.
697 * @namespace YAHOO.util
698 * @class Assert
699 * @static
701 YAHOO.util.Assert = {
703 //-------------------------------------------------------------------------
704 // Generic Assertion Methods
705 //-------------------------------------------------------------------------
707 /**
708 * Forces an assertion error to occur.
709 * @param {String} message (Optional) The message to display with the failure.
710 * @method fail
711 * @static
713 fail : function (message /*:String*/) /*:Void*/ {
714 throw new YAHOO.util.AssertionError(message || "Test force-failed.");
717 //-------------------------------------------------------------------------
718 // Equality Assertion Methods
719 //-------------------------------------------------------------------------
722 * Asserts that a value is equal to another. This uses the double equals sign
723 * so type cohersion may occur.
724 * @param {Object} expected The expected value.
725 * @param {Object} actual The actual value to test.
726 * @param {String} message (Optional) The message to display if the assertion fails.
727 * @method areEqual
728 * @static
730 areEqual : function (expected /*:Object*/, actual /*:Object*/, message /*:String*/) /*:Void*/ {
731 if (expected != actual) {
732 throw new YAHOO.util.ComparisonFailure(message || "Values should be equal.", expected, actual);
737 * Asserts that a value is not equal to another. This uses the double equals sign
738 * so type cohersion may occur.
739 * @param {Object} unexpected The unexpected value.
740 * @param {Object} actual The actual value to test.
741 * @param {String} message (Optional) The message to display if the assertion fails.
742 * @method areNotEqual
743 * @static
745 areNotEqual : function (unexpected /*:Object*/, actual /*:Object*/,
746 message /*:String*/) /*:Void*/ {
747 if (unexpected == actual) {
748 throw new YAHOO.util.UnexpectedValue(message || "Values should not be equal.", unexpected);
753 * Asserts that a value is not the same as another. This uses the triple equals sign
754 * so no type cohersion may occur.
755 * @param {Object} unexpected The unexpected value.
756 * @param {Object} actual The actual value to test.
757 * @param {String} message (Optional) The message to display if the assertion fails.
758 * @method areNotSame
759 * @static
761 areNotSame : function (unexpected /*:Object*/, actual /*:Object*/, message /*:String*/) /*:Void*/ {
762 if (unexpected === actual) {
763 throw new YAHOO.util.UnexpectedValue(message || "Values should not be the same.", unexpected);
768 * Asserts that a value is the same as another. This uses the triple equals sign
769 * so no type cohersion may occur.
770 * @param {Object} expected The expected value.
771 * @param {Object} actual The actual value to test.
772 * @param {String} message (Optional) The message to display if the assertion fails.
773 * @method areSame
774 * @static
776 areSame : function (expected /*:Object*/, actual /*:Object*/, message /*:String*/) /*:Void*/ {
777 if (expected !== actual) {
778 throw new YAHOO.util.ComparisonFailure(message || "Values should be the same.", expected, actual);
782 //-------------------------------------------------------------------------
783 // Boolean Assertion Methods
784 //-------------------------------------------------------------------------
787 * Asserts that a value is false. This uses the triple equals sign
788 * so no type cohersion may occur.
789 * @param {Object} actual The actual value to test.
790 * @param {String} message (Optional) The message to display if the assertion fails.
791 * @method isFalse
792 * @static
794 isFalse : function (actual /*:Boolean*/, message /*:String*/) {
795 if (false !== actual) {
796 throw new YAHOO.util.ComparisonFailure(message || "Value should be false.", false, actual);
801 * Asserts that a value is true. This uses the triple equals sign
802 * so no type cohersion may occur.
803 * @param {Object} actual The actual value to test.
804 * @param {String} message (Optional) The message to display if the assertion fails.
805 * @method isTrue
806 * @static
808 isTrue : function (actual /*:Boolean*/, message /*:String*/) /*:Void*/ {
809 if (true !== actual) {
810 throw new YAHOO.util.ComparisonFailure(message || "Value should be true.", true, actual);
815 //-------------------------------------------------------------------------
816 // Special Value Assertion Methods
817 //-------------------------------------------------------------------------
820 * Asserts that a value is not a number.
821 * @param {Object} actual The value to test.
822 * @param {String} message (Optional) The message to display if the assertion fails.
823 * @method isNaN
824 * @static
826 isNaN : function (actual /*:Object*/, message /*:String*/) /*:Void*/{
827 if (!isNaN(actual)){
828 throw new YAHOO.util.ComparisonFailure(message || "Value should be NaN.", NaN, actual);
833 * Asserts that a value is not the special NaN value.
834 * @param {Object} actual The value to test.
835 * @param {String} message (Optional) The message to display if the assertion fails.
836 * @method isNotNaN
837 * @static
839 isNotNaN : function (actual /*:Object*/, message /*:String*/) /*:Void*/{
840 if (isNaN(actual)){
841 throw new YAHOO.util.UnexpectedValue(message || "Values should not be NaN.", NaN);
846 * Asserts that a value is not null. This uses the triple equals sign
847 * so no type cohersion may occur.
848 * @param {Object} actual The actual value to test.
849 * @param {String} message (Optional) The message to display if the assertion fails.
850 * @method isNotNull
851 * @static
853 isNotNull : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
854 if (YAHOO.lang.isNull(actual)) {
855 throw new YAHOO.util.UnexpectedValue(message || "Values should not be null.", null);
860 * Asserts that a value is not undefined. This uses the triple equals sign
861 * so no type cohersion may occur.
862 * @param {Object} actual The actual value to test.
863 * @param {String} message (Optional) The message to display if the assertion fails.
864 * @method isNotUndefined
865 * @static
867 isNotUndefined : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
868 if (YAHOO.lang.isUndefined(actual)) {
869 throw new YAHOO.util.UnexpectedValue(message || "Value should not be undefined.", undefined);
874 * Asserts that a value is null. This uses the triple equals sign
875 * so no type cohersion may occur.
876 * @param {Object} actual The actual value to test.
877 * @param {String} message (Optional) The message to display if the assertion fails.
878 * @method isNull
879 * @static
881 isNull : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
882 if (!YAHOO.lang.isNull(actual)) {
883 throw new YAHOO.util.ComparisonFailure(message || "Value should be null.", null, actual);
888 * Asserts that a value is undefined. This uses the triple equals sign
889 * so no type cohersion may occur.
890 * @param {Object} expected The expected value.
891 * @param {Object} actual The actual value to test.
892 * @param {String} message (Optional) The message to display if the assertion fails.
893 * @method isUndefined
894 * @static
896 isUndefined : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
897 if (!YAHOO.lang.isUndefined(actual)) {
898 throw new YAHOO.util.ComparisonFailure(message || "Value should be undefined.", undefined, actual);
902 //--------------------------------------------------------------------------
903 // Instance Assertion Methods
904 //--------------------------------------------------------------------------
907 * Asserts that a value is an array.
908 * @param {Object} actual The value to test.
909 * @param {String} message (Optional) The message to display if the assertion fails.
910 * @method isArray
911 * @static
913 isArray : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
914 if (!YAHOO.lang.isArray(actual)){
915 throw new YAHOO.util.UnexpectedValue(message || "Value should be an array.", actual);
920 * Asserts that a value is a Boolean.
921 * @param {Object} actual The value to test.
922 * @param {String} message (Optional) The message to display if the assertion fails.
923 * @method isBoolean
924 * @static
926 isBoolean : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
927 if (!YAHOO.lang.isBoolean(actual)){
928 throw new YAHOO.util.UnexpectedValue(message || "Value should be a Boolean.", actual);
933 * Asserts that a value is a function.
934 * @param {Object} actual The value to test.
935 * @param {String} message (Optional) The message to display if the assertion fails.
936 * @method isFunction
937 * @static
939 isFunction : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
940 if (!YAHOO.lang.isFunction(actual)){
941 throw new YAHOO.util.UnexpectedValue(message || "Value should be a function.", actual);
946 * Asserts that a value is an instance of a particular object. This may return
947 * incorrect results when comparing objects from one frame to constructors in
948 * another frame. For best results, don't use in a cross-frame manner.
949 * @param {Function} expected The function that the object should be an instance of.
950 * @param {Object} actual The object to test.
951 * @param {String} message (Optional) The message to display if the assertion fails.
952 * @method isInstanceOf
953 * @static
955 isInstanceOf : function (expected /*:Function*/, actual /*:Object*/, message /*:String*/) /*:Void*/ {
956 if (!(actual instanceof expected)){
957 throw new YAHOO.util.ComparisonFailure(message || "Value isn't an instance of expected type.", expected, actual);
962 * Asserts that a value is a number.
963 * @param {Object} actual The value to test.
964 * @param {String} message (Optional) The message to display if the assertion fails.
965 * @method isNumber
966 * @static
968 isNumber : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
969 if (!YAHOO.lang.isNumber(actual)){
970 throw new YAHOO.util.UnexpectedValue(message || "Value should be a number.", actual);
975 * Asserts that a value is an object.
976 * @param {Object} actual The value to test.
977 * @param {String} message (Optional) The message to display if the assertion fails.
978 * @method isObject
979 * @static
981 isObject : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
982 if (!YAHOO.lang.isObject(actual)){
983 throw new YAHOO.util.UnexpectedValue(message || "Value should be an object.", actual);
988 * Asserts that a value is a string.
989 * @param {Object} actual The value to test.
990 * @param {String} message (Optional) The message to display if the assertion fails.
991 * @method isString
992 * @static
994 isString : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
995 if (!YAHOO.lang.isString(actual)){
996 throw new YAHOO.util.UnexpectedValue(message || "Value should be a string.", actual);
1001 * Asserts that a value is of a particular type.
1002 * @param {String} expectedType The expected type of the variable.
1003 * @param {Object} actualValue The actual value to test.
1004 * @param {String} message (Optional) The message to display if the assertion fails.
1005 * @method isTypeOf
1006 * @static
1008 isTypeOf : function (expectedType /*:String*/, actualValue /*:Object*/, message /*:String*/) /*:Void*/{
1009 if (typeof actualValue != expectedType){
1010 throw new YAHOO.util.ComparisonFailure(message || "Value should be of type " + expected + ".", expected, typeof actual);
1015 //-----------------------------------------------------------------------------
1016 // Assertion errors
1017 //-----------------------------------------------------------------------------
1020 * AssertionError is thrown whenever an assertion fails. It provides methods
1021 * to more easily get at error information and also provides a base class
1022 * from which more specific assertion errors can be derived.
1024 * @param {String} message The message to display when the error occurs.
1025 * @namespace YAHOO.util
1026 * @class AssertionError
1027 * @extends Error
1028 * @constructor
1030 YAHOO.util.AssertionError = function (message /*:String*/){
1032 //call superclass
1033 arguments.callee.superclass.constructor.call(this, message);
1036 * Error message. Must be duplicated to ensure browser receives it.
1037 * @type String
1038 * @property message
1040 this.message /*:String*/ = message;
1043 * The name of the error that occurred.
1044 * @type String
1045 * @property name
1047 this.name /*:String*/ = "AssertionError";
1050 //inherit methods
1051 YAHOO.lang.extend(YAHOO.util.AssertionError, Error, {
1054 * Returns a fully formatted error for an assertion failure. This should
1055 * be overridden by all subclasses to provide specific information.
1056 * @method getMessage
1057 * @return {String} A string describing the error.
1059 getMessage : function () /*:String*/ {
1060 return this.message;
1064 * Returns a string representation of the error.
1065 * @method toString
1066 * @return {String} A string representation of the error.
1068 toString : function () /*:String*/ {
1069 return this.name + ": " + this.getMessage();
1073 * Returns a primitive value version of the error. Same as toString().
1074 * @method valueOf
1075 * @return {String} A primitive value version of the error.
1077 valueOf : function () /*:String*/ {
1078 return this.toString();
1084 * ComparisonFailure is subclass of AssertionError that is thrown whenever
1085 * a comparison between two values fails. It provides mechanisms to retrieve
1086 * both the expected and actual value.
1088 * @param {String} message The message to display when the error occurs.
1089 * @param {Object} expected The expected value.
1090 * @param {Object} actual The actual value that caused the assertion to fail.
1091 * @namespace YAHOO.util
1092 * @extends YAHOO.util.AssertionError
1093 * @class ComparisonFailure
1094 * @constructor
1096 YAHOO.util.ComparisonFailure = function (message /*:String*/, expected /*:Object*/, actual /*:Object*/){
1098 //call superclass
1099 arguments.callee.superclass.constructor.call(this, message);
1102 * The expected value.
1103 * @type Object
1104 * @property expected
1106 this.expected /*:Object*/ = expected;
1109 * The actual value.
1110 * @type Object
1111 * @property actual
1113 this.actual /*:Object*/ = actual;
1116 * The name of the error that occurred.
1117 * @type String
1118 * @property name
1120 this.name /*:String*/ = "ComparisonFailure";
1124 //inherit methods
1125 YAHOO.lang.extend(YAHOO.util.ComparisonFailure, YAHOO.util.AssertionError, {
1128 * Returns a fully formatted error for an assertion failure. This message
1129 * provides information about the expected and actual values.
1130 * @method toString
1131 * @return {String} A string describing the error.
1133 getMessage : function () /*:String*/ {
1134 return this.message + "\nExpected: " + this.expected + " (" + (typeof this.expected) + ")" +
1135 "\nActual:" + this.actual + " (" + (typeof this.actual) + ")";
1141 * UnexpectedValue is subclass of AssertionError that is thrown whenever
1142 * a value was unexpected in its scope. This typically means that a test
1143 * was performed to determine that a value was *not* equal to a certain
1144 * value.
1146 * @param {String} message The message to display when the error occurs.
1147 * @param {Object} unexpected The unexpected value.
1148 * @namespace YAHOO.util
1149 * @extends YAHOO.util.AssertionError
1150 * @class UnexpectedValue
1151 * @constructor
1153 YAHOO.util.UnexpectedValue = function (message /*:String*/, unexpected /*:Object*/){
1155 //call superclass
1156 arguments.callee.superclass.constructor.call(this, message);
1159 * The unexpected value.
1160 * @type Object
1161 * @property unexpected
1163 this.unexpected /*:Object*/ = unexpected;
1166 * The name of the error that occurred.
1167 * @type String
1168 * @property name
1170 this.name /*:String*/ = "UnexpectedValue";
1174 //inherit methods
1175 YAHOO.lang.extend(YAHOO.util.UnexpectedValue, YAHOO.util.AssertionError, {
1178 * Returns a fully formatted error for an assertion failure. The message
1179 * contains information about the unexpected value that was encountered.
1180 * @method getMessage
1181 * @return {String} A string describing the error.
1183 getMessage : function () /*:String*/ {
1184 return this.message + "\nUnexpected: " + this.unexpected + " (" + (typeof this.unexpected) + ") ";
1190 * ShouldFail is subclass of AssertionError that is thrown whenever
1191 * a test was expected to fail but did not.
1193 * @param {String} message The message to display when the error occurs.
1194 * @namespace YAHOO.util
1195 * @extends YAHOO.util.AssertionError
1196 * @class ShouldFail
1197 * @constructor
1199 YAHOO.util.ShouldFail = function (message /*:String*/){
1201 //call superclass
1202 arguments.callee.superclass.constructor.call(this, message || "This test should fail but didn't.");
1205 * The name of the error that occurred.
1206 * @type String
1207 * @property name
1209 this.name /*:String*/ = "ShouldFail";
1213 //inherit methods
1214 YAHOO.lang.extend(YAHOO.util.ShouldFail, YAHOO.util.AssertionError);
1217 * ShouldError is subclass of AssertionError that is thrown whenever
1218 * a test is expected to throw an error but doesn't.
1220 * @param {String} message The message to display when the error occurs.
1221 * @namespace YAHOO.util
1222 * @extends YAHOO.util.AssertionError
1223 * @class ShouldError
1224 * @constructor
1226 YAHOO.util.ShouldError = function (message /*:String*/){
1228 //call superclass
1229 arguments.callee.superclass.constructor.call(this, message || "This test should have thrown an error but didn't.");
1232 * The name of the error that occurred.
1233 * @type String
1234 * @property name
1236 this.name /*:String*/ = "ShouldError";
1240 //inherit methods
1241 YAHOO.lang.extend(YAHOO.util.ShouldError, YAHOO.util.AssertionError);
1244 * UnexpectedError is subclass of AssertionError that is thrown whenever
1245 * an error occurs within the course of a test and the test was not expected
1246 * to throw an error.
1248 * @param {Error} cause The unexpected error that caused this error to be
1249 * thrown.
1250 * @namespace YAHOO.util
1251 * @extends YAHOO.util.AssertionError
1252 * @class UnexpectedError
1253 * @constructor
1255 YAHOO.util.UnexpectedError = function (cause /*:Object*/){
1257 //call superclass
1258 arguments.callee.superclass.constructor.call(this, "Unexpected error: " + cause.message);
1261 * The unexpected error that occurred.
1262 * @type Error
1263 * @property cause
1265 this.cause /*:Error*/ = cause;
1268 * The name of the error that occurred.
1269 * @type String
1270 * @property name
1272 this.name /*:String*/ = "UnexpectedError";
1276 //inherit methods
1277 YAHOO.lang.extend(YAHOO.util.UnexpectedError, YAHOO.util.AssertionError);
1278 //-----------------------------------------------------------------------------
1279 // ArrayAssert object
1280 //-----------------------------------------------------------------------------
1283 * The ArrayAssert object provides functions to test JavaScript array objects
1284 * for a variety of cases.
1286 * @namespace YAHOO.util
1287 * @class ArrayAssert
1288 * @static
1291 YAHOO.util.ArrayAssert = {
1294 * Asserts that a value is present in an array. This uses the triple equals
1295 * sign so no type cohersion may occur.
1296 * @param {Object} needle The value that is expected in the array.
1297 * @param {Array} haystack An array of values.
1298 * @param {String} message (Optional) The message to display if the assertion fails.
1299 * @method contains
1300 * @static
1302 contains : function (needle /*:Object*/, haystack /*:Array*/,
1303 message /*:String*/) /*:Void*/ {
1305 var found /*:Boolean*/ = false;
1307 //begin checking values
1308 for (var i=0; i < haystack.length && !found; i++){
1309 if (haystack[i] === needle) {
1310 found = true;
1314 if (!found){
1315 YAHOO.util.Assert.fail(message || "Value (" + needle + ") not found in array.");
1320 * Asserts that a set of values are present in an array. This uses the triple equals
1321 * sign so no type cohersion may occur. For this assertion to pass, all values must
1322 * be found.
1323 * @param {Object[]} needles An array of values that are expected in the array.
1324 * @param {Array} haystack An array of values to check.
1325 * @param {String} message (Optional) The message to display if the assertion fails.
1326 * @method containsItems
1327 * @static
1329 containsItems : function (needles /*:Object[]*/, haystack /*:Array*/,
1330 message /*:String*/) /*:Void*/ {
1332 //begin checking values
1333 for (var i=0; i < needles.length; i++){
1334 this.contains(needles[i], haystack, message);
1337 if (!found){
1338 YAHOO.util.Assert.fail(message || "Value not found in array.");
1343 * Asserts that a value matching some condition is present in an array. This uses
1344 * a function to determine a match.
1345 * @param {Function} matcher A function that returns true if the items matches or false if not.
1346 * @param {Array} haystack An array of values.
1347 * @param {String} message (Optional) The message to display if the assertion fails.
1348 * @method containsMatch
1349 * @static
1351 containsMatch : function (matcher /*:Function*/, haystack /*:Array*/,
1352 message /*:String*/) /*:Void*/ {
1354 //check for valid matcher
1355 if (typeof matcher != "function"){
1356 throw new TypeError("ArrayAssert.containsMatch(): First argument must be a function.");
1359 var found /*:Boolean*/ = false;
1361 //begin checking values
1362 for (var i=0; i < haystack.length && !found; i++){
1363 if (matcher(haystack[i])) {
1364 found = true;
1368 if (!found){
1369 YAHOO.util.Assert.fail(message || "No match found in array.");
1374 * Asserts that a value is not present in an array. This uses the triple equals
1375 * sign so no type cohersion may occur.
1376 * @param {Object} needle The value that is expected in the array.
1377 * @param {Array} haystack An array of values.
1378 * @param {String} message (Optional) The message to display if the assertion fails.
1379 * @method doesNotContain
1380 * @static
1382 doesNotContain : function (needle /*:Object*/, haystack /*:Array*/,
1383 message /*:String*/) /*:Void*/ {
1385 var found /*:Boolean*/ = false;
1387 //begin checking values
1388 for (var i=0; i < haystack.length && !found; i++){
1389 if (haystack[i] === needle) {
1390 found = true;
1394 if (found){
1395 YAHOO.util.Assert.fail(message || "Value found in array.");
1400 * Asserts that a set of values are not present in an array. This uses the triple equals
1401 * sign so no type cohersion may occur. For this assertion to pass, all values must
1402 * not be found.
1403 * @param {Object[]} needles An array of values that are not expected in the array.
1404 * @param {Array} haystack An array of values to check.
1405 * @param {String} message (Optional) The message to display if the assertion fails.
1406 * @method doesNotContainItems
1407 * @static
1409 doesNotContainItems : function (needles /*:Object[]*/, haystack /*:Array*/,
1410 message /*:String*/) /*:Void*/ {
1412 for (var i=0; i < needles.length; i++){
1413 this.doesNotContain(needles[i], haystack, message);
1419 * Asserts that no values matching a condition are present in an array. This uses
1420 * a function to determine a match.
1421 * @param {Function} matcher A function that returns true if the items matches or false if not.
1422 * @param {Array} haystack An array of values.
1423 * @param {String} message (Optional) The message to display if the assertion fails.
1424 * @method doesNotContainMatch
1425 * @static
1427 doesNotContainMatch : function (matcher /*:Function*/, haystack /*:Array*/,
1428 message /*:String*/) /*:Void*/ {
1430 //check for valid matcher
1431 if (typeof matcher != "function"){
1432 throw new TypeError("ArrayAssert.doesNotContainMatch(): First argument must be a function.");
1435 var found /*:Boolean*/ = false;
1437 //begin checking values
1438 for (var i=0; i < haystack.length && !found; i++){
1439 if (matcher(haystack[i])) {
1440 found = true;
1444 if (found){
1445 YAHOO.util.Assert.fail(message || "Value found in array.");
1450 * Asserts that the given value is contained in an array at the specified index.
1451 * This uses the triple equals sign so no type cohersion will occur.
1452 * @param {Object} needle The value to look for.
1453 * @param {Array} haystack The array to search in.
1454 * @param {int} index The index at which the value should exist.
1455 * @param {String} message (Optional) The message to display if the assertion fails.
1456 * @method indexOf
1457 * @static
1459 indexOf : function (needle /*:Object*/, haystack /*:Array*/, index /*:int*/, message /*:String*/) /*:Void*/ {
1461 //try to find the value in the array
1462 for (var i=0; i < haystack.length; i++){
1463 if (haystack[i] === needle){
1464 YAHOO.util.Assert.areEqual(index, i, message || "Value exists at index " + i + " but should be at index " + index + ".");
1465 return;
1469 //if it makes it here, it wasn't found at all
1470 YAHOO.util.Assert.fail(message || "Value doesn't exist in array.");
1474 * Asserts that the values in an array are equal, and in the same position,
1475 * as values in another array. This uses the double equals sign
1476 * so type cohersion may occur. Note that the array objects themselves
1477 * need not be the same for this test to pass.
1478 * @param {Array} expected An array of the expected values.
1479 * @param {Array} actual Any array of the actual values.
1480 * @param {String} message (Optional) The message to display if the assertion fails.
1481 * @method itemsAreEqual
1482 * @static
1484 itemsAreEqual : function (expected /*:Array*/, actual /*:Array*/,
1485 message /*:String*/) /*:Void*/ {
1487 //one may be longer than the other, so get the maximum length
1488 var len /*:int*/ = Math.max(expected.length, actual.length);
1490 //begin checking values
1491 for (var i=0; i < len; i++){
1492 YAHOO.util.Assert.areEqual(expected[i], actual[i], message ||
1493 "Values in position " + i + " are not equal.");
1498 * Asserts that the values in an array are equivalent, and in the same position,
1499 * as values in another array. This uses a function to determine if the values
1500 * are equivalent. Note that the array objects themselves
1501 * need not be the same for this test to pass.
1502 * @param {Array} expected An array of the expected values.
1503 * @param {Array} actual Any array of the actual values.
1504 * @param {Function} comparator A function that returns true if the values are equivalent
1505 * or false if not.
1506 * @param {String} message (Optional) The message to display if the assertion fails.
1507 * @return {Void}
1508 * @method itemsAreEquivalent
1509 * @static
1511 itemsAreEquivalent : function (expected /*:Array*/, actual /*:Array*/,
1512 comparator /*:Function*/, message /*:String*/) /*:Void*/ {
1514 //make sure the comparator is valid
1515 if (typeof comparator != "function"){
1516 throw new TypeError("ArrayAssert.itemsAreEquivalent(): Third argument must be a function.");
1519 //one may be longer than the other, so get the maximum length
1520 var len /*:int*/ = Math.max(expected.length, actual.length);
1522 //begin checking values
1523 for (var i=0; i < len; i++){
1524 if (!comparator(expected[i], actual[i])){
1525 throw new YAHOO.util.ComparisonFailure(message || "Values in position " + i + " are not equivalent.", expected[i], actual[i]);
1531 * Asserts that an array is empty.
1532 * @param {Array} actual The array to test.
1533 * @param {String} message (Optional) The message to display if the assertion fails.
1534 * @method isEmpty
1535 * @static
1537 isEmpty : function (actual /*:Array*/, message /*:String*/) /*:Void*/ {
1538 if (actual.length > 0){
1539 YAHOO.util.Assert.fail(message || "Array should be empty.");
1544 * Asserts that an array is not empty.
1545 * @param {Array} actual The array to test.
1546 * @param {String} message (Optional) The message to display if the assertion fails.
1547 * @method isNotEmpty
1548 * @static
1550 isNotEmpty : function (actual /*:Array*/, message /*:String*/) /*:Void*/ {
1551 if (actual.length === 0){
1552 YAHOO.util.Assert.fail(message || "Array should not be empty.");
1557 * Asserts that the values in an array are the same, and in the same position,
1558 * as values in another array. This uses the triple equals sign
1559 * so no type cohersion will occur. Note that the array objects themselves
1560 * need not be the same for this test to pass.
1561 * @param {Array} expected An array of the expected values.
1562 * @param {Array} actual Any array of the actual values.
1563 * @param {String} message (Optional) The message to display if the assertion fails.
1564 * @method itemsAreSame
1565 * @static
1567 itemsAreSame : function (expected /*:Array*/, actual /*:Array*/,
1568 message /*:String*/) /*:Void*/ {
1570 //one may be longer than the other, so get the maximum length
1571 var len /*:int*/ = Math.max(expected.length, actual.length);
1573 //begin checking values
1574 for (var i=0; i < len; i++){
1575 YAHOO.util.Assert.areSame(expected[i], actual[i],
1576 message || "Values in position " + i + " are not the same.");
1581 * Asserts that the given value is contained in an array at the specified index,
1582 * starting from the back of the array.
1583 * This uses the triple equals sign so no type cohersion will occur.
1584 * @param {Object} needle The value to look for.
1585 * @param {Array} haystack The array to search in.
1586 * @param {int} index The index at which the value should exist.
1587 * @param {String} message (Optional) The message to display if the assertion fails.
1588 * @method lastIndexOf
1589 * @static
1591 lastIndexOf : function (needle /*:Object*/, haystack /*:Array*/, index /*:int*/, message /*:String*/) /*:Void*/ {
1593 //try to find the value in the array
1594 for (var i=haystack.length; i >= 0; i--){
1595 if (haystack[i] === needle){
1596 YAHOO.util.Assert.areEqual(index, i, message || "Value exists at index " + i + " but should be at index " + index + ".");
1597 return;
1601 //if it makes it here, it wasn't found at all
1602 YAHOO.util.Assert.fail(message || "Value doesn't exist in array.");
1606 YAHOO.namespace("util");
1609 //-----------------------------------------------------------------------------
1610 // ObjectAssert object
1611 //-----------------------------------------------------------------------------
1614 * The ObjectAssert object provides functions to test JavaScript objects
1615 * for a variety of cases.
1617 * @namespace YAHOO.util
1618 * @class ObjectAssert
1619 * @static
1621 YAHOO.util.ObjectAssert = {
1624 * Asserts that all properties in the object exist in another object.
1625 * @param {Object} expected An object with the expected properties.
1626 * @param {Object} actual An object with the actual properties.
1627 * @param {String} message (Optional) The message to display if the assertion fails.
1628 * @method propertiesAreEqual
1629 * @static
1631 propertiesAreEqual : function (expected /*:Object*/, actual /*:Object*/,
1632 message /*:String*/) /*:Void*/ {
1634 //get all properties in the object
1635 var properties /*:Array*/ = [];
1636 for (var property in expected){
1637 properties.push(property);
1640 //see if the properties are in the expected object
1641 for (var i=0; i < properties.length; i++){
1642 YAHOO.util.Assert.isNotUndefined(actual[properties[i]], message ||
1643 "Property'" + properties[i] + "' expected.");
1649 * Asserts that an object has a property with the given name.
1650 * @param {String} propertyName The name of the property to test.
1651 * @param {Object} object The object to search.
1652 * @param {String} message (Optional) The message to display if the assertion fails.
1653 * @method hasProperty
1654 * @static
1656 hasProperty : function (propertyName /*:String*/, object /*:Object*/, message /*:String*/) /*:Void*/ {
1657 if (YAHOO.lang.isUndefined(object[propertyName])){
1658 YAHOO.util.Assert.fail(message ||
1659 "Property " + propertyName + " not found on object.");
1664 * Asserts that a property with the given name exists on an object instance (not on its prototype).
1665 * @param {String} propertyName The name of the property to test.
1666 * @param {Object} object The object to search.
1667 * @param {String} message (Optional) The message to display if the assertion fails.
1668 * @method hasProperty
1669 * @static
1671 hasOwnProperty : function (propertyName /*:String*/, object /*:Object*/, message /*:String*/) /*:Void*/ {
1672 if (!YAHOO.lang.hasOwnProperty(object, propertyName)){
1673 YAHOO.util.Assert.fail(message ||
1674 "Property " + propertyName + " not found on object instance.");
1678 //-----------------------------------------------------------------------------
1679 // DateAssert object
1680 //-----------------------------------------------------------------------------
1683 * The DateAssert object provides functions to test JavaScript Date objects
1684 * for a variety of cases.
1686 * @namespace YAHOO.util
1687 * @class DateAssert
1688 * @static
1691 YAHOO.util.DateAssert = {
1694 * Asserts that a date's month, day, and year are equal to another date's.
1695 * @param {Date} expected The expected date.
1696 * @param {Date} actual The actual date to test.
1697 * @param {String} message (Optional) The message to display if the assertion fails.
1698 * @method areEqual
1699 * @static
1701 datesAreEqual : function (expected /*:Date*/, actual /*:Date*/, message /*:String*/){
1702 if (expected instanceof Date && actual instanceof Date){
1703 YAHOO.util.Assert.areEqual(expected.getFullYear(), actual.getFullYear(), message || "Years should be equal.");
1704 YAHOO.util.Assert.areEqual(expected.getMonth(), actual.getMonth(), message || "Months should be equal.");
1705 YAHOO.util.Assert.areEqual(expected.getDate(), actual.getDate(), message || "Day of month should be equal.");
1706 } else {
1707 throw new TypeError("DateAssert.datesAreEqual(): Expected and actual values must be Date objects.");
1712 * Asserts that a date's hour, minutes, and seconds are equal to another date's.
1713 * @param {Date} expected The expected date.
1714 * @param {Date} actual The actual date to test.
1715 * @param {String} message (Optional) The message to display if the assertion fails.
1716 * @method areEqual
1717 * @static
1719 timesAreEqual : function (expected /*:Date*/, actual /*:Date*/, message /*:String*/){
1720 if (expected instanceof Date && actual instanceof Date){
1721 YAHOO.util.Assert.areEqual(expected.getHours(), actual.getHours(), message || "Hours should be equal.");
1722 YAHOO.util.Assert.areEqual(expected.getMinutes(), actual.getMinutes(), message || "Minutes should be equal.");
1723 YAHOO.util.Assert.areEqual(expected.getSeconds(), actual.getSeconds(), message || "Seconds should be equal.");
1724 } else {
1725 throw new TypeError("DateAssert.timesAreEqual(): Expected and actual values must be Date objects.");
1730 YAHOO.namespace("util");
1733 * The UserAction object provides functions that simulate events occurring in
1734 * the browser. Since these are simulated events, they do not behave exactly
1735 * as regular, user-initiated events do, but can be used to test simple
1736 * user interactions safely.
1738 * @namespace YAHOO.util
1739 * @class UserAction
1740 * @static
1742 YAHOO.util.UserAction = {
1744 //--------------------------------------------------------------------------
1745 // Generic event methods
1746 //--------------------------------------------------------------------------
1749 * Simulates a key event using the given event information to populate
1750 * the generated event object. This method does browser-equalizing
1751 * calculations to account for differences in the DOM and IE event models
1752 * as well as different browser quirks. Note: keydown causes Safari 2.x to
1753 * crash.
1754 * @method simulateKeyEvent
1755 * @private
1756 * @static
1757 * @param {HTMLElement} target The target of the given event.
1758 * @param {String} type The type of event to fire. This can be any one of
1759 * the following: keyup, keydown, and keypress.
1760 * @param {Boolean} bubbles (Optional) Indicates if the event can be
1761 * bubbled up. DOM Level 3 specifies that all key events bubble by
1762 * default. The default is true.
1763 * @param {Boolean} cancelable (Optional) Indicates if the event can be
1764 * canceled using preventDefault(). DOM Level 3 specifies that all
1765 * key events can be cancelled. The default
1766 * is true.
1767 * @param {Window} view (Optional) The view containing the target. This is
1768 * typically the window object. The default is window.
1769 * @param {Boolean} ctrlKey (Optional) Indicates if one of the CTRL keys
1770 * is pressed while the event is firing. The default is false.
1771 * @param {Boolean} altKey (Optional) Indicates if one of the ALT keys
1772 * is pressed while the event is firing. The default is false.
1773 * @param {Boolean} shiftKey (Optional) Indicates if one of the SHIFT keys
1774 * is pressed while the event is firing. The default is false.
1775 * @param {Boolean} metaKey (Optional) Indicates if one of the META keys
1776 * is pressed while the event is firing. The default is false.
1777 * @param {int} keyCode (Optional) The code for the key that is in use.
1778 * The default is 0.
1779 * @param {int} charCode (Optional) The Unicode code for the character
1780 * associated with the key being used. The default is 0.
1782 simulateKeyEvent : function (target /*:HTMLElement*/, type /*:String*/,
1783 bubbles /*:Boolean*/, cancelable /*:Boolean*/,
1784 view /*:Window*/,
1785 ctrlKey /*:Boolean*/, altKey /*:Boolean*/,
1786 shiftKey /*:Boolean*/, metaKey /*:Boolean*/,
1787 keyCode /*:int*/, charCode /*:int*/) /*:Void*/
1789 //check target
1790 target = YAHOO.util.Dom.get(target);
1791 if (!target){
1792 throw new Error("simulateKeyEvent(): Invalid target.");
1795 //check event type
1796 if (YAHOO.lang.isString(type)){
1797 type = type.toLowerCase();
1798 switch(type){
1799 case "keyup":
1800 case "keydown":
1801 case "keypress":
1802 break;
1803 case "textevent": //DOM Level 3
1804 type = "keypress";
1805 break;
1806 // @TODO was the fallthrough intentional, if so throw error
1807 default:
1808 throw new Error("simulateKeyEvent(): Event type '" + type + "' not supported.");
1810 } else {
1811 throw new Error("simulateKeyEvent(): Event type must be a string.");
1814 //setup default values
1815 if (!YAHOO.lang.isBoolean(bubbles)){
1816 bubbles = true; //all key events bubble
1818 if (!YAHOO.lang.isBoolean(cancelable)){
1819 cancelable = true; //all key events can be cancelled
1821 if (!YAHOO.lang.isObject(view)){
1822 view = window; //view is typically window
1824 if (!YAHOO.lang.isBoolean(ctrlKey)){
1825 ctrlKey = false;
1827 if (!YAHOO.lang.isBoolean(altKey)){
1828 altKey = false;
1830 if (!YAHOO.lang.isBoolean(shiftKey)){
1831 shiftKey = false;
1833 if (!YAHOO.lang.isBoolean(metaKey)){
1834 metaKey = false;
1836 if (!YAHOO.lang.isNumber(keyCode)){
1837 keyCode = 0;
1839 if (!YAHOO.lang.isNumber(charCode)){
1840 charCode = 0;
1843 //check for DOM-compliant browsers first
1844 if (YAHOO.lang.isFunction(document.createEvent)){
1846 //try to create a mouse event
1847 var event /*:MouseEvent*/ = null;
1849 try {
1851 //try to create key event
1852 event = document.createEvent("KeyEvents");
1855 * Interesting problem: Firefox implemented a non-standard
1856 * version of initKeyEvent() based on DOM Level 2 specs.
1857 * Key event was removed from DOM Level 2 and re-introduced
1858 * in DOM Level 3 with a different interface. Firefox is the
1859 * only browser with any implementation of Key Events, so for
1860 * now, assume it's Firefox if the above line doesn't error.
1862 //TODO: Decipher between Firefox's implementation and a correct one.
1863 event.initKeyEvent(type, bubbles, cancelable, view, ctrlKey,
1864 altKey, shiftKey, metaKey, keyCode, charCode);
1866 } catch (ex /*:Error*/){
1869 * If it got here, that means key events aren't officially supported.
1870 * Safari/WebKit is a real problem now. WebKit 522 won't let you
1871 * set keyCode, charCode, or other properties if you use a
1872 * UIEvent, so we first must try to create a generic event. The
1873 * fun part is that this will throw an error on Safari 2.x. The
1874 * end result is that we need another try...catch statement just to
1875 * deal with this mess.
1877 try {
1879 //try to create generic event - will fail in Safari 2.x
1880 event = document.createEvent("Events");
1882 } catch (uierror /*:Error*/){
1884 //the above failed, so create a UIEvent for Safari 2.x
1885 event = document.createEvent("UIEvents");
1887 } finally {
1889 event.initEvent(type, bubbles, cancelable);
1891 //initialize
1892 event.view = view;
1893 event.altKey = altKey;
1894 event.ctrlKey = ctrlKey;
1895 event.shiftKey = shiftKey;
1896 event.metaKey = metaKey;
1897 event.keyCode = keyCode;
1898 event.charCode = charCode;
1904 //fire the event
1905 target.dispatchEvent(event);
1907 } else if (YAHOO.lang.isObject(document.createEventObject)){ //IE
1909 //create an IE event object
1910 event = document.createEventObject();
1912 //assign available properties
1913 event.bubbles = bubbles;
1914 event.cancelable = cancelable;
1915 event.view = view;
1916 event.ctrlKey = ctrlKey;
1917 event.altKey = altKey;
1918 event.shiftKey = shiftKey;
1919 event.metaKey = metaKey;
1922 * IE doesn't support charCode explicitly. CharCode should
1923 * take precedence over any keyCode value for accurate
1924 * representation.
1926 event.keyCode = (charCode > 0) ? charCode : keyCode;
1928 //fire the event
1929 target.fireEvent("on" + type, event);
1931 } else {
1932 throw new Error("simulateKeyEvent(): No event simulation framework present.");
1937 * Simulates a mouse event using the given event information to populate
1938 * the generated event object. This method does browser-equalizing
1939 * calculations to account for differences in the DOM and IE event models
1940 * as well as different browser quirks.
1941 * @method simulateMouseEvent
1942 * @private
1943 * @static
1944 * @param {HTMLElement} target The target of the given event.
1945 * @param {String} type The type of event to fire. This can be any one of
1946 * the following: click, dblclick, mousedown, mouseup, mouseout,
1947 * mouseover, and mousemove.
1948 * @param {Boolean} bubbles (Optional) Indicates if the event can be
1949 * bubbled up. DOM Level 2 specifies that all mouse events bubble by
1950 * default. The default is true.
1951 * @param {Boolean} cancelable (Optional) Indicates if the event can be
1952 * canceled using preventDefault(). DOM Level 2 specifies that all
1953 * mouse events except mousemove can be cancelled. The default
1954 * is true for all events except mousemove, for which the default
1955 * is false.
1956 * @param {Window} view (Optional) The view containing the target. This is
1957 * typically the window object. The default is window.
1958 * @param {int} detail (Optional) The number of times the mouse button has
1959 * been used. The default value is 1.
1960 * @param {int} screenX (Optional) The x-coordinate on the screen at which
1961 * point the event occured. The default is 0.
1962 * @param {int} screenY (Optional) The y-coordinate on the screen at which
1963 * point the event occured. The default is 0.
1964 * @param {int} clientX (Optional) The x-coordinate on the client at which
1965 * point the event occured. The default is 0.
1966 * @param {int} clientY (Optional) The y-coordinate on the client at which
1967 * point the event occured. The default is 0.
1968 * @param {Boolean} ctrlKey (Optional) Indicates if one of the CTRL keys
1969 * is pressed while the event is firing. The default is false.
1970 * @param {Boolean} altKey (Optional) Indicates if one of the ALT keys
1971 * is pressed while the event is firing. The default is false.
1972 * @param {Boolean} shiftKey (Optional) Indicates if one of the SHIFT keys
1973 * is pressed while the event is firing. The default is false.
1974 * @param {Boolean} metaKey (Optional) Indicates if one of the META keys
1975 * is pressed while the event is firing. The default is false.
1976 * @param {int} button (Optional) The button being pressed while the event
1977 * is executing. The value should be 0 for the primary mouse button
1978 * (typically the left button), 1 for the terciary mouse button
1979 * (typically the middle button), and 2 for the secondary mouse button
1980 * (typically the right button). The default is 0.
1981 * @param {HTMLElement} relatedTarget (Optional) For mouseout events,
1982 * this is the element that the mouse has moved to. For mouseover
1983 * events, this is the element that the mouse has moved from. This
1984 * argument is ignored for all other events. The default is null.
1986 simulateMouseEvent : function (target /*:HTMLElement*/, type /*:String*/,
1987 bubbles /*:Boolean*/, cancelable /*:Boolean*/,
1988 view /*:Window*/, detail /*:int*/,
1989 screenX /*:int*/, screenY /*:int*/,
1990 clientX /*:int*/, clientY /*:int*/,
1991 ctrlKey /*:Boolean*/, altKey /*:Boolean*/,
1992 shiftKey /*:Boolean*/, metaKey /*:Boolean*/,
1993 button /*:int*/, relatedTarget /*:HTMLElement*/) /*:Void*/
1996 //check target
1997 target = YAHOO.util.Dom.get(target);
1998 if (!target){
1999 throw new Error("simulateMouseEvent(): Invalid target.");
2002 //check event type
2003 if (YAHOO.lang.isString(type)){
2004 type = type.toLowerCase();
2005 switch(type){
2006 case "mouseover":
2007 case "mouseout":
2008 case "mousedown":
2009 case "mouseup":
2010 case "click":
2011 case "dblclick":
2012 case "mousemove":
2013 break;
2014 default:
2015 throw new Error("simulateMouseEvent(): Event type '" + type + "' not supported.");
2017 } else {
2018 throw new Error("simulateMouseEvent(): Event type must be a string.");
2021 //setup default values
2022 if (!YAHOO.lang.isBoolean(bubbles)){
2023 bubbles = true; //all mouse events bubble
2025 if (!YAHOO.lang.isBoolean(cancelable)){
2026 cancelable = (type != "mousemove"); //mousemove is the only one that can't be cancelled
2028 if (!YAHOO.lang.isObject(view)){
2029 view = window; //view is typically window
2031 if (!YAHOO.lang.isNumber(detail)){
2032 detail = 1; //number of mouse clicks must be at least one
2034 if (!YAHOO.lang.isNumber(screenX)){
2035 screenX = 0;
2037 if (!YAHOO.lang.isNumber(screenY)){
2038 screenY = 0;
2040 if (!YAHOO.lang.isNumber(clientX)){
2041 clientX = 0;
2043 if (!YAHOO.lang.isNumber(clientY)){
2044 clientY = 0;
2046 if (!YAHOO.lang.isBoolean(ctrlKey)){
2047 ctrlKey = false;
2049 if (!YAHOO.lang.isBoolean(altKey)){
2050 altKey = false;
2052 if (!YAHOO.lang.isBoolean(shiftKey)){
2053 shiftKey = false;
2055 if (!YAHOO.lang.isBoolean(metaKey)){
2056 metaKey = false;
2058 if (!YAHOO.lang.isNumber(button)){
2059 button = 0;
2062 //check for DOM-compliant browsers first
2063 if (YAHOO.lang.isFunction(document.createEvent)){
2065 //try to create a mouse event
2066 var event /*:MouseEvent*/ = document.createEvent("MouseEvents");
2068 //Safari 2.x (WebKit 418) still doesn't implement initMouseEvent()
2069 if (event.initMouseEvent){
2070 event.initMouseEvent(type, bubbles, cancelable, view, detail,
2071 screenX, screenY, clientX, clientY,
2072 ctrlKey, altKey, shiftKey, metaKey,
2073 button, relatedTarget);
2074 } else { //Safari
2076 //the closest thing available in Safari 2.x is UIEvents
2077 event = document.createEvent("UIEvents");
2078 event.initEvent(type, bubbles, cancelable);
2079 event.view = view;
2080 event.detail = detail;
2081 event.screenX = screenX;
2082 event.screenY = screenY;
2083 event.clientX = clientX;
2084 event.clientY = clientY;
2085 event.ctrlKey = ctrlKey;
2086 event.altKey = altKey;
2087 event.metaKey = metaKey;
2088 event.shiftKey = shiftKey;
2089 event.button = button;
2090 event.relatedTarget = relatedTarget;
2094 * Check to see if relatedTarget has been assigned. Firefox
2095 * versions less than 2.0 don't allow it to be assigned via
2096 * initMouseEvent() and the property is readonly after event
2097 * creation, so in order to keep YAHOO.util.getRelatedTarget()
2098 * working, assign to the IE proprietary toElement property
2099 * for mouseout event and fromElement property for mouseover
2100 * event.
2102 if (relatedTarget && !event.relatedTarget){
2103 if (type == "mouseout"){
2104 event.toElement = relatedTarget;
2105 } else if (type == "mouseover"){
2106 event.fromElement = relatedTarget;
2110 //fire the event
2111 target.dispatchEvent(event);
2113 } else if (YAHOO.lang.isObject(document.createEventObject)){ //IE
2115 //create an IE event object
2116 event = document.createEventObject();
2118 //assign available properties
2119 event.bubbles = bubbles;
2120 event.cancelable = cancelable;
2121 event.view = view;
2122 event.detail = detail;
2123 event.screenX = screenX;
2124 event.screenY = screenY;
2125 event.clientX = clientX;
2126 event.clientY = clientY;
2127 event.ctrlKey = ctrlKey;
2128 event.altKey = altKey;
2129 event.metaKey = metaKey;
2130 event.shiftKey = shiftKey;
2132 //fix button property for IE's wacky implementation
2133 switch(button){
2134 case 0:
2135 event.button = 1;
2136 break;
2137 case 1:
2138 event.button = 4;
2139 break;
2140 case 2:
2141 //leave as is
2142 break;
2143 default:
2144 event.button = 0;
2148 * Have to use relatedTarget because IE won't allow assignment
2149 * to toElement or fromElement on generic events. This keeps
2150 * YAHOO.util.Event.getRelatedTarget() functional.
2152 event.relatedTarget = relatedTarget;
2154 //fire the event
2155 target.fireEvent("on" + type, event);
2157 } else {
2158 throw new Error("simulateMouseEvent(): No event simulation framework present.");
2162 //--------------------------------------------------------------------------
2163 // Mouse events
2164 //--------------------------------------------------------------------------
2167 * Simulates a mouse event on a particular element.
2168 * @param {HTMLElement} target The element to click on.
2169 * @param {String} type The type of event to fire. This can be any one of
2170 * the following: click, dblclick, mousedown, mouseup, mouseout,
2171 * mouseover, and mousemove.
2172 * @param {Object} options Additional event options (use DOM standard names).
2173 * @method mouseEvent
2174 * @static
2176 fireMouseEvent : function (target /*:HTMLElement*/, type /*:String*/,
2177 options /*:Object*/) /*:Void*/
2179 options = options || {};
2180 this.simulateMouseEvent(target, type, options.bubbles,
2181 options.cancelable, options.view, options.detail, options.screenX,
2182 options.screenY, options.clientX, options.clientY, options.ctrlKey,
2183 options.altKey, options.shiftKey, options.metaKey, options.button,
2184 options.relatedTarget);
2188 * Simulates a click on a particular element.
2189 * @param {HTMLElement} target The element to click on.
2190 * @param {Object} options Additional event options (use DOM standard names).
2191 * @method click
2192 * @static
2194 click : function (target /*:HTMLElement*/, options /*:Object*/) /*:Void*/ {
2195 this.fireMouseEvent(target, "click", options);
2199 * Simulates a double click on a particular element.
2200 * @param {HTMLElement} target The element to double click on.
2201 * @param {Object} options Additional event options (use DOM standard names).
2202 * @method dblclick
2203 * @static
2205 dblclick : function (target /*:HTMLElement*/, options /*:Object*/) /*:Void*/ {
2206 this.fireMouseEvent( target, "dblclick", options);
2210 * Simulates a mousedown on a particular element.
2211 * @param {HTMLElement} target The element to act on.
2212 * @param {Object} options Additional event options (use DOM standard names).
2213 * @method mousedown
2214 * @static
2216 mousedown : function (target /*:HTMLElement*/, options /*Object*/) /*:Void*/ {
2217 this.fireMouseEvent(target, "mousedown", options);
2221 * Simulates a mousemove on a particular element.
2222 * @param {HTMLElement} target The element to act on.
2223 * @param {Object} options Additional event options (use DOM standard names).
2224 * @method mousemove
2225 * @static
2227 mousemove : function (target /*:HTMLElement*/, options /*Object*/) /*:Void*/ {
2228 this.fireMouseEvent(target, "mousemove", options);
2232 * Simulates a mouseout event on a particular element. Use "relatedTarget"
2233 * on the options object to specify where the mouse moved to.
2234 * Quirks: Firefox less than 2.0 doesn't set relatedTarget properly, so
2235 * toElement is assigned in its place. IE doesn't allow toElement to be
2236 * be assigned, so relatedTarget is assigned in its place. Both of these
2237 * concessions allow YAHOO.util.Event.getRelatedTarget() to work correctly
2238 * in both browsers.
2239 * @param {HTMLElement} target The element to act on.
2240 * @param {Object} options Additional event options (use DOM standard names).
2241 * @method mouseout
2242 * @static
2244 mouseout : function (target /*:HTMLElement*/, options /*Object*/) /*:Void*/ {
2245 this.fireMouseEvent(target, "mouseout", options);
2249 * Simulates a mouseover event on a particular element. Use "relatedTarget"
2250 * on the options object to specify where the mouse moved from.
2251 * Quirks: Firefox less than 2.0 doesn't set relatedTarget properly, so
2252 * fromElement is assigned in its place. IE doesn't allow fromElement to be
2253 * be assigned, so relatedTarget is assigned in its place. Both of these
2254 * concessions allow YAHOO.util.Event.getRelatedTarget() to work correctly
2255 * in both browsers.
2256 * @param {HTMLElement} target The element to act on.
2257 * @param {Object} options Additional event options (use DOM standard names).
2258 * @method mouseover
2259 * @static
2261 mouseover : function (target /*:HTMLElement*/, options /*Object*/) /*:Void*/ {
2262 this.fireMouseEvent(target, "mouseover", options);
2266 * Simulates a mouseup on a particular element.
2267 * @param {HTMLElement} target The element to act on.
2268 * @param {Object} options Additional event options (use DOM standard names).
2269 * @method mouseup
2270 * @static
2272 mouseup : function (target /*:HTMLElement*/, options /*Object*/) /*:Void*/ {
2273 this.fireMouseEvent(target, "mouseup", options);
2276 //--------------------------------------------------------------------------
2277 // Key events
2278 //--------------------------------------------------------------------------
2281 * Fires an event that normally would be fired by the keyboard (keyup,
2282 * keydown, keypress). Make sure to specify either keyCode or charCode as
2283 * an option.
2284 * @private
2285 * @param {String} type The type of event ("keyup", "keydown" or "keypress").
2286 * @param {HTMLElement} target The target of the event.
2287 * @param {Object} options Options for the event. Either keyCode or charCode
2288 * are required.
2289 * @method fireKeyEvent
2290 * @static
2292 fireKeyEvent : function (type /*:String*/, target /*:HTMLElement*/,
2293 options /*:Object*/) /*:Void*/
2295 options = options || {};
2296 this.simulateKeyEvent(target, type, options.bubbles,
2297 options.cancelable, options.view, options.ctrlKey,
2298 options.altKey, options.shiftKey, options.metaKey,
2299 options.keyCode, options.charCode);
2303 * Simulates a keydown event on a particular element.
2304 * @param {HTMLElement} target The element to act on.
2305 * @param {Object} options Additional event options (use DOM standard names).
2306 * @method keydown
2307 * @static
2309 keydown : function (target /*:HTMLElement*/, options /*:Object*/) /*:Void*/ {
2310 this.fireKeyEvent("keydown", target, options);
2314 * Simulates a keypress on a particular element.
2315 * @param {HTMLElement} target The element to act on.
2316 * @param {Object} options Additional event options (use DOM standard names).
2317 * @method keypress
2318 * @static
2320 keypress : function (target /*:HTMLElement*/, options /*:Object*/) /*:Void*/ {
2321 this.fireKeyEvent("keypress", target, options);
2325 * Simulates a keyup event on a particular element.
2326 * @param {HTMLElement} target The element to act on.
2327 * @param {Object} options Additional event options (use DOM standard names).
2328 * @method keyup
2329 * @static
2331 keyup : function (target /*:HTMLElement*/, options /*Object*/) /*:Void*/ {
2332 this.fireKeyEvent("keyup", target, options);
2337 YAHOO.namespace("tool");
2339 //-----------------------------------------------------------------------------
2340 // TestManager object
2341 //-----------------------------------------------------------------------------
2344 * Runs pages containing test suite definitions.
2345 * @namespace YAHOO.tool
2346 * @class TestManager
2347 * @static
2349 YAHOO.tool.TestManager = {
2352 * Constant for the testpagebegin custom event
2353 * @property TEST_PAGE_BEGIN_EVENT
2354 * @static
2355 * @type string
2356 * @final
2358 TEST_PAGE_BEGIN_EVENT /*:String*/ : "testpagebegin",
2361 * Constant for the testpagecomplete custom event
2362 * @property TEST_PAGE_COMPLETE_EVENT
2363 * @static
2364 * @type string
2365 * @final
2367 TEST_PAGE_COMPLETE_EVENT /*:String*/ : "testpagecomplete",
2370 * Constant for the testmanagerbegin custom event
2371 * @property TEST_MANAGER_BEGIN_EVENT
2372 * @static
2373 * @type string
2374 * @final
2376 TEST_MANAGER_BEGIN_EVENT /*:String*/ : "testmanagerbegin",
2379 * Constant for the testmanagercomplete custom event
2380 * @property TEST_MANAGER_COMPLETE_EVENT
2381 * @static
2382 * @type string
2383 * @final
2385 TEST_MANAGER_COMPLETE_EVENT /*:String*/ : "testmanagercomplete",
2387 //-------------------------------------------------------------------------
2388 // Private Properties
2389 //-------------------------------------------------------------------------
2393 * The URL of the page currently being executed.
2394 * @type String
2395 * @private
2396 * @property _curPage
2397 * @static
2399 _curPage /*:String*/ : null,
2402 * The frame used to load and run tests.
2403 * @type Window
2404 * @private
2405 * @property _frame
2406 * @static
2408 _frame /*:Window*/ : null,
2411 * The logger used to output results from the various tests.
2412 * @type YAHOO.tool.TestLogger
2413 * @private
2414 * @property _logger
2415 * @static
2417 _logger : null,
2420 * The timeout ID for the next iteration through the tests.
2421 * @type int
2422 * @private
2423 * @property _timeoutId
2424 * @static
2426 _timeoutId /*:int*/ : 0,
2429 * Array of pages to load.
2430 * @type String[]
2431 * @private
2432 * @property _pages
2433 * @static
2435 _pages /*:String[]*/ : [],
2438 * Aggregated results
2439 * @type Object
2440 * @private
2441 * @property _results
2442 * @static
2444 _results: null,
2446 //-------------------------------------------------------------------------
2447 // Private Methods
2448 //-------------------------------------------------------------------------
2451 * Handles TestRunner.COMPLETE_EVENT, storing the results and beginning
2452 * the loop again.
2453 * @param {Object} data Data about the event.
2454 * @return {Void}
2455 * @private
2456 * @static
2458 _handleTestRunnerComplete : function (data /*:Object*/) /*:Void*/ {
2460 this.fireEvent(this.TEST_PAGE_COMPLETE_EVENT, {
2461 page: this._curPage,
2462 results: data.results
2465 //save results
2466 //this._results[this.curPage] = data.results;
2468 //process 'em
2469 this._processResults(this._curPage, data.results);
2471 this._logger.clearTestRunner();
2473 //if there's more to do, set a timeout to begin again
2474 if (this._pages.length){
2475 this._timeoutId = setTimeout(function(){
2476 YAHOO.tool.TestManager._run();
2477 }, 1000);
2482 * Processes the results of a test page run, outputting log messages
2483 * for failed tests.
2484 * @return {Void}
2485 * @private
2486 * @static
2488 _processResults : function (page /*:String*/, results /*:Object*/) /*:Void*/ {
2490 var r = this._results;
2492 r.page_results[page] = results;
2494 if (results.passed) {
2495 r.pages_passed++;
2496 r.tests_passed += results.passed;
2499 if (results.failed) {
2500 r.pages_failed++;
2501 r.tests_failed += results.failed;
2502 r.failed.push(page);
2503 } else {
2504 r.passed.push(page);
2507 if (!this._pages.length) {
2508 this.fireEvent(this.TEST_MANAGER_COMPLETE_EVENT, this._results);
2514 * Loads the next test page into the iframe.
2515 * @return {Void}
2516 * @static
2517 * @private
2519 _run : function () /*:Void*/ {
2521 //set the current page
2522 this._curPage = this._pages.shift();
2524 this.fireEvent(this.TEST_PAGE_BEGIN_EVENT, this._curPage);
2526 //load the frame - destroy history in case there are other iframes that
2527 //need testing
2528 this._frame.location.replace(this._curPage);
2532 //-------------------------------------------------------------------------
2533 // Public Methods
2534 //-------------------------------------------------------------------------
2537 * Signals that a test page has been loaded. This should be called from
2538 * within the test page itself to notify the TestManager that it is ready.
2539 * @return {Void}
2540 * @static
2542 load : function () /*:Void*/ {
2543 if (parent.YAHOO.tool.TestManager !== this){
2544 parent.YAHOO.tool.TestManager.load();
2545 } else {
2547 if (this._frame) {
2548 //assign event handling
2549 var TestRunner = this._frame.YAHOO.tool.TestRunner;
2551 this._logger.setTestRunner(TestRunner);
2552 TestRunner.subscribe(TestRunner.COMPLETE_EVENT, this._handleTestRunnerComplete, this, true);
2554 //run it
2555 TestRunner.run();
2561 * Sets the pages to be loaded.
2562 * @param {String[]} pages An array of URLs to load.
2563 * @return {Void}
2564 * @static
2566 setPages : function (pages /*:String[]*/) /*:Void*/ {
2567 this._pages = pages;
2571 * Begins the process of running the tests.
2572 * @return {Void}
2573 * @static
2575 start : function () /*:Void*/ {
2577 if (!this._initialized) {
2580 * Fires when loading a test page
2581 * @event testpagebegin
2582 * @param curPage {string} the page being loaded
2583 * @static
2585 this.createEvent(this.TEST_PAGE_BEGIN_EVENT);
2588 * Fires when a test page is complete
2589 * @event testpagecomplete
2590 * @param obj {page: string, results: object} the name of the
2591 * page that was loaded, and the test suite results
2592 * @static
2594 this.createEvent(this.TEST_PAGE_COMPLETE_EVENT);
2597 * Fires when the test manager starts running all test pages
2598 * @event testmanagerbegin
2599 * @static
2601 this.createEvent(this.TEST_MANAGER_BEGIN_EVENT);
2604 * Fires when the test manager finishes running all test pages. External
2605 * test runners should subscribe to this event in order to get the
2606 * aggregated test results.
2607 * @event testmanagercomplete
2608 * @param obj { pages_passed: int, pages_failed: int, tests_passed: int
2609 * tests_failed: int, passed: string[], failed: string[],
2610 * page_results: {} }
2611 * @static
2613 this.createEvent(this.TEST_MANAGER_COMPLETE_EVENT);
2615 //create iframe if not already available
2616 if (!this._frame){
2617 var frame /*:HTMLElement*/ = document.createElement("iframe");
2618 frame.style.visibility = "hidden";
2619 frame.style.position = "absolute";
2620 document.body.appendChild(frame);
2621 this._frame = frame.contentWindow || frame.contentDocument.ownerWindow;
2624 //create test logger if not already available
2625 if (!this._logger){
2626 this._logger = new YAHOO.tool.TestLogger();
2629 this._initialized = true;
2633 // reset the results cache
2634 this._results = {
2635 // number of pages that pass
2636 pages_passed: 0,
2637 // number of pages that fail
2638 pages_failed: 0,
2639 // total number of tests passed
2640 tests_passed: 0,
2641 // total number of tests failed
2642 tests_failed: 0,
2643 // array of pages that passed
2644 passed: [],
2645 // array of pages that failed
2646 failed: [],
2647 // map of full results for each page
2648 page_results: {}
2651 this.fireEvent(this.TEST_MANAGER_BEGIN_EVENT, null);
2652 this._run();
2657 * Stops the execution of tests.
2658 * @return {Void}
2659 * @static
2661 stop : function () /*:Void*/ {
2662 clearTimeout(this._timeoutId);
2667 YAHOO.lang.augmentObject(YAHOO.tool.TestManager, YAHOO.util.EventProvider.prototype);
2669 YAHOO.register("yuitest", YAHOO.tool.TestRunner, {version: "2.3.0", build: "442"});