[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 YUI.add('yui2-yuitest', function(Y) { 2 var YAHOO = Y.YUI2; 3 /* 4 Copyright (c) 2011, Yahoo! Inc. All rights reserved. 5 Code licensed under the BSD License: 6 http://developer.yahoo.com/yui/license.html 7 version: 2.9.0 8 */ 9 YAHOO.namespace("tool"); 10 11 //----------------------------------------------------------------------------- 12 // TestCase object 13 //----------------------------------------------------------------------------- 14 (function(){ 15 16 //used for autogenerating test case names 17 var tempId = 0; 18 19 /** 20 * Test case containing various tests to run. 21 * @param template An object containing any number of test methods, other methods, 22 * an optional name, and anything else the test case needs. 23 * @class TestCase 24 * @namespace YAHOO.tool 25 * @constructor 26 */ 27 YAHOO.tool.TestCase = function (template /*:Object*/) { 28 29 /** 30 * Special rules for the test case. Possible subobjects 31 * are fail, for tests that should fail, and error, for 32 * tests that should throw an error. 33 */ 34 this._should /*:Object*/ = {}; 35 36 //copy over all properties from the template to this object 37 for (var prop in template) { 38 this[prop] = template[prop]; 39 } 40 41 //check for a valid name 42 if (!YAHOO.lang.isString(this.name)){ 43 /** 44 * Name for the test case. 45 */ 46 this.name /*:String*/ = "testCase" + (tempId++); 47 } 48 49 }; 50 51 52 YAHOO.tool.TestCase.prototype = { 53 54 /** 55 * Resumes a paused test and runs the given function. 56 * @param {Function} segment (Optional) The function to run. 57 * If omitted, the test automatically passes. 58 * @return {Void} 59 * @method resume 60 */ 61 resume : function (segment /*:Function*/) /*:Void*/ { 62 YAHOO.tool.TestRunner.resume(segment); 63 }, 64 65 /** 66 * Causes the test case to wait a specified amount of time and then 67 * continue executing the given code. 68 * @param {Function} segment (Optional) The function to run after the delay. 69 * If omitted, the TestRunner will wait until resume() is called. 70 * @param {int} delay (Optional) The number of milliseconds to wait before running 71 * the function. If omitted, defaults to zero. 72 * @return {Void} 73 * @method wait 74 */ 75 wait : function (segment /*:Function*/, delay /*:int*/) /*:Void*/{ 76 var args = arguments; 77 if (YAHOO.lang.isFunction(args[0])){ 78 throw new YAHOO.tool.TestCase.Wait(args[0], args[1]); 79 } else { 80 throw new YAHOO.tool.TestCase.Wait(function(){ 81 YAHOO.util.Assert.fail("Timeout: wait() called but resume() never called."); 82 }, (YAHOO.lang.isNumber(args[0]) ? args[0] : 10000)); 83 } 84 }, 85 86 //------------------------------------------------------------------------- 87 // Stub Methods 88 //------------------------------------------------------------------------- 89 90 /** 91 * Function to run before each test is executed. 92 * @return {Void} 93 * @method setUp 94 */ 95 setUp : function () /*:Void*/ { 96 }, 97 98 /** 99 * Function to run after each test is executed. 100 * @return {Void} 101 * @method tearDown 102 */ 103 tearDown: function () /*:Void*/ { 104 } 105 }; 106 107 /** 108 * Represents a stoppage in test execution to wait for an amount of time before 109 * continuing. 110 * @param {Function} segment A function to run when the wait is over. 111 * @param {int} delay The number of milliseconds to wait before running the code. 112 * @class Wait 113 * @namespace YAHOO.tool.TestCase 114 * @constructor 115 * 116 */ 117 YAHOO.tool.TestCase.Wait = function (segment /*:Function*/, delay /*:int*/) { 118 119 /** 120 * The segment of code to run when the wait is over. 121 * @type Function 122 * @property segment 123 */ 124 this.segment /*:Function*/ = (YAHOO.lang.isFunction(segment) ? segment : null); 125 126 /** 127 * The delay before running the segment of code. 128 * @type int 129 * @property delay 130 */ 131 this.delay /*:int*/ = (YAHOO.lang.isNumber(delay) ? delay : 0); 132 133 }; 134 135 })(); 136 YAHOO.namespace("tool"); 137 138 139 //----------------------------------------------------------------------------- 140 // TestSuite object 141 //----------------------------------------------------------------------------- 142 143 /** 144 * A test suite that can contain a collection of TestCase and TestSuite objects. 145 * @param {String||Object} data The name of the test suite or an object containing 146 * a name property as well as setUp and tearDown methods. 147 * @namespace YAHOO.tool 148 * @class TestSuite 149 * @constructor 150 */ 151 YAHOO.tool.TestSuite = function (data /*:String||Object*/) { 152 153 /** 154 * The name of the test suite. 155 * @type String 156 * @property name 157 */ 158 this.name /*:String*/ = ""; 159 160 /** 161 * Array of test suites and 162 * @private 163 */ 164 this.items /*:Array*/ = []; 165 166 //initialize the properties 167 if (YAHOO.lang.isString(data)){ 168 this.name = data; 169 } else if (YAHOO.lang.isObject(data)){ 170 YAHOO.lang.augmentObject(this, data, true); 171 } 172 173 //double-check name 174 if (this.name === ""){ 175 this.name = YAHOO.util.Dom.generateId(null, "testSuite"); 176 } 177 178 }; 179 180 YAHOO.tool.TestSuite.prototype = { 181 182 /** 183 * Adds a test suite or test case to the test suite. 184 * @param {YAHOO.tool.TestSuite||YAHOO.tool.TestCase} testObject The test suite or test case to add. 185 * @return {Void} 186 * @method add 187 */ 188 add : function (testObject /*:YAHOO.tool.TestSuite*/) /*:Void*/ { 189 if (testObject instanceof YAHOO.tool.TestSuite || testObject instanceof YAHOO.tool.TestCase) { 190 this.items.push(testObject); 191 } 192 }, 193 194 //------------------------------------------------------------------------- 195 // Stub Methods 196 //------------------------------------------------------------------------- 197 198 /** 199 * Function to run before each test is executed. 200 * @return {Void} 201 * @method setUp 202 */ 203 setUp : function () /*:Void*/ { 204 }, 205 206 /** 207 * Function to run after each test is executed. 208 * @return {Void} 209 * @method tearDown 210 */ 211 tearDown: function () /*:Void*/ { 212 } 213 214 }; 215 YAHOO.namespace("tool"); 216 217 /** 218 * The YUI test tool 219 * @module yuitest 220 * @namespace YAHOO.tool 221 * @requires yahoo,dom,event,logger 222 * @optional event-simulate 223 */ 224 225 226 //----------------------------------------------------------------------------- 227 // TestRunner object 228 //----------------------------------------------------------------------------- 229 230 231 YAHOO.tool.TestRunner = (function(){ 232 233 /** 234 * A node in the test tree structure. May represent a TestSuite, TestCase, or 235 * test function. 236 * @param {Variant} testObject A TestSuite, TestCase, or the name of a test function. 237 * @class TestNode 238 * @constructor 239 * @private 240 */ 241 function TestNode(testObject /*:Variant*/){ 242 243 /** 244 * The TestSuite, TestCase, or test function represented by this node. 245 * @type Variant 246 * @property testObject 247 */ 248 this.testObject = testObject; 249 250 /** 251 * Pointer to this node's first child. 252 * @type TestNode 253 * @property firstChild 254 */ 255 this.firstChild /*:TestNode*/ = null; 256 257 /** 258 * Pointer to this node's last child. 259 * @type TestNode 260 * @property lastChild 261 */ 262 this.lastChild = null; 263 264 /** 265 * Pointer to this node's parent. 266 * @type TestNode 267 * @property parent 268 */ 269 this.parent = null; 270 271 /** 272 * Pointer to this node's next sibling. 273 * @type TestNode 274 * @property next 275 */ 276 this.next = null; 277 278 /** 279 * Test results for this test object. 280 * @type object 281 * @property results 282 */ 283 this.results /*:Object*/ = { 284 passed : 0, 285 failed : 0, 286 total : 0, 287 ignored : 0, 288 duration: 0 289 }; 290 291 //initialize results 292 if (testObject instanceof YAHOO.tool.TestSuite){ 293 this.results.type = "testsuite"; 294 this.results.name = testObject.name; 295 } else if (testObject instanceof YAHOO.tool.TestCase){ 296 this.results.type = "testcase"; 297 this.results.name = testObject.name; 298 } 299 300 } 301 302 TestNode.prototype = { 303 304 /** 305 * Appends a new test object (TestSuite, TestCase, or test function name) as a child 306 * of this node. 307 * @param {Variant} testObject A TestSuite, TestCase, or the name of a test function. 308 * @return {Void} 309 */ 310 appendChild : function (testObject /*:Variant*/) /*:Void*/{ 311 var node = new TestNode(testObject); 312 if (this.firstChild === null){ 313 this.firstChild = this.lastChild = node; 314 } else { 315 this.lastChild.next = node; 316 this.lastChild = node; 317 } 318 node.parent = this; 319 return node; 320 } 321 }; 322 323 /** 324 * Runs test suites and test cases, providing events to allowing for the 325 * interpretation of test results. 326 * @namespace YAHOO.tool 327 * @class TestRunner 328 * @static 329 */ 330 function TestRunner(){ 331 332 //inherit from EventProvider 333 TestRunner.superclass.constructor.apply(this,arguments); 334 335 /** 336 * Suite on which to attach all TestSuites and TestCases to be run. 337 * @type YAHOO.tool.TestSuite 338 * @property masterSuite 339 * @private 340 * @static 341 */ 342 this.masterSuite = new YAHOO.tool.TestSuite("yuitests" + (new Date()).getTime()); 343 344 /** 345 * Pointer to the current node in the test tree. 346 * @type TestNode 347 * @private 348 * @property _cur 349 * @static 350 */ 351 this._cur = null; 352 353 /** 354 * Pointer to the root node in the test tree. 355 * @type TestNode 356 * @private 357 * @property _root 358 * @static 359 */ 360 this._root = null; 361 362 /** 363 * Indicates if the TestRunner is currently running tests. 364 * @type Boolean 365 * @private 366 * @property _running 367 * @static 368 */ 369 this._running = false; 370 371 /** 372 * Holds copy of the results object generated when all tests are 373 * complete. 374 * @type Object 375 * @private 376 * @property _lastResults 377 * @static 378 */ 379 this._lastResults = null; 380 381 //create events 382 var events /*:Array*/ = [ 383 this.TEST_CASE_BEGIN_EVENT, 384 this.TEST_CASE_COMPLETE_EVENT, 385 this.TEST_SUITE_BEGIN_EVENT, 386 this.TEST_SUITE_COMPLETE_EVENT, 387 this.TEST_PASS_EVENT, 388 this.TEST_FAIL_EVENT, 389 this.TEST_IGNORE_EVENT, 390 this.COMPLETE_EVENT, 391 this.BEGIN_EVENT 392 ]; 393 for (var i=0; i < events.length; i++){ 394 this.createEvent(events[i], { scope: this }); 395 } 396 397 } 398 399 YAHOO.lang.extend(TestRunner, YAHOO.util.EventProvider, { 400 401 //------------------------------------------------------------------------- 402 // Constants 403 //------------------------------------------------------------------------- 404 405 /** 406 * Fires when a test case is opened but before the first 407 * test is executed. 408 * @event testcasebegin 409 */ 410 TEST_CASE_BEGIN_EVENT /*:String*/ : "testcasebegin", 411 412 /** 413 * Fires when all tests in a test case have been executed. 414 * @event testcasecomplete 415 */ 416 TEST_CASE_COMPLETE_EVENT /*:String*/ : "testcasecomplete", 417 418 /** 419 * Fires when a test suite is opened but before the first 420 * test is executed. 421 * @event testsuitebegin 422 */ 423 TEST_SUITE_BEGIN_EVENT /*:String*/ : "testsuitebegin", 424 425 /** 426 * Fires when all test cases in a test suite have been 427 * completed. 428 * @event testsuitecomplete 429 */ 430 TEST_SUITE_COMPLETE_EVENT /*:String*/ : "testsuitecomplete", 431 432 /** 433 * Fires when a test has passed. 434 * @event pass 435 */ 436 TEST_PASS_EVENT /*:String*/ : "pass", 437 438 /** 439 * Fires when a test has failed. 440 * @event fail 441 */ 442 TEST_FAIL_EVENT /*:String*/ : "fail", 443 444 /** 445 * Fires when a test has been ignored. 446 * @event ignore 447 */ 448 TEST_IGNORE_EVENT /*:String*/ : "ignore", 449 450 /** 451 * Fires when all test suites and test cases have been completed. 452 * @event complete 453 */ 454 COMPLETE_EVENT /*:String*/ : "complete", 455 456 /** 457 * Fires when the run() method is called. 458 * @event begin 459 */ 460 BEGIN_EVENT /*:String*/ : "begin", 461 462 //------------------------------------------------------------------------- 463 // Misc Methods 464 //------------------------------------------------------------------------- 465 466 /** 467 * Retrieves the name of the current result set. 468 * @return {String} The name of the result set. 469 * @method getName 470 */ 471 getName: function(){ 472 return this.masterSuite.name; 473 }, 474 475 /** 476 * The name assigned to the master suite of the TestRunner. This is the name 477 * that is output as the root's name when results are retrieved. 478 * @param {String} name The name of the result set. 479 * @return {Void} 480 * @method setName 481 */ 482 setName: function(name){ 483 this.masterSuite.name = name; 484 }, 485 486 487 //------------------------------------------------------------------------- 488 // State-Related Methods 489 //------------------------------------------------------------------------- 490 491 /** 492 * Indicates that the TestRunner is busy running tests and therefore can't 493 * be stopped and results cannot be gathered. 494 * @return {Boolean} True if the TestRunner is running, false if not. 495 * @method isRunning 496 */ 497 isRunning: function(){ 498 return this._running; 499 }, 500 501 /** 502 * Returns the last complete results set from the TestRunner. Null is returned 503 * if the TestRunner is running or no tests have been run. 504 * @param {Function} format (Optional) A test format to return the results in. 505 * @return {Object|String} Either the results object or, if a test format is 506 * passed as the argument, a string representing the results in a specific 507 * format. 508 * @method getResults 509 */ 510 getResults: function(format){ 511 if (!this._running && this._lastResults){ 512 if (YAHOO.lang.isFunction(format)){ 513 return format(this._lastResults); 514 } else { 515 return this._lastResults; 516 } 517 } else { 518 return null; 519 } 520 }, 521 522 /** 523 * Returns the coverage report for the files that have been executed. 524 * This returns only coverage information for files that have been 525 * instrumented using YUI Test Coverage and only those that were run 526 * in the same pass. 527 * @param {Function} format (Optional) A coverage format to return results in. 528 * @return {Object|String} Either the coverage object or, if a coverage 529 * format is specified, a string representing the results in that format. 530 * @method getCoverage 531 */ 532 getCoverage: function(format){ 533 if (!this._running && typeof _yuitest_coverage == "object"){ 534 if (YAHOO.lang.isFunction(format)){ 535 return format(_yuitest_coverage); 536 } else { 537 return _yuitest_coverage; 538 } 539 } else { 540 return null; 541 } 542 }, 543 544 //------------------------------------------------------------------------- 545 // Misc Methods 546 //------------------------------------------------------------------------- 547 548 /** 549 * Retrieves the name of the current result set. 550 * @return {String} The name of the result set. 551 * @method getName 552 */ 553 getName: function(){ 554 return this.masterSuite.name; 555 }, 556 557 /** 558 * The name assigned to the master suite of the TestRunner. This is the name 559 * that is output as the root's name when results are retrieved. 560 * @param {String} name The name of the result set. 561 * @return {Void} 562 * @method setName 563 */ 564 setName: function(name){ 565 this.masterSuite.name = name; 566 }, 567 568 //------------------------------------------------------------------------- 569 // Test Tree-Related Methods 570 //------------------------------------------------------------------------- 571 572 /** 573 * Adds a test case to the test tree as a child of the specified node. 574 * @param {TestNode} parentNode The node to add the test case to as a child. 575 * @param {YAHOO.tool.TestCase} testCase The test case to add. 576 * @return {Void} 577 * @static 578 * @private 579 * @method _addTestCaseToTestTree 580 */ 581 _addTestCaseToTestTree : function (parentNode /*:TestNode*/, testCase /*:YAHOO.tool.TestCase*/) /*:Void*/{ 582 583 //add the test suite 584 var node = parentNode.appendChild(testCase); 585 586 //iterate over the items in the test case 587 for (var prop in testCase){ 588 if (prop.indexOf("test") === 0 && YAHOO.lang.isFunction(testCase[prop])){ 589 node.appendChild(prop); 590 } 591 } 592 593 }, 594 595 /** 596 * Adds a test suite to the test tree as a child of the specified node. 597 * @param {TestNode} parentNode The node to add the test suite to as a child. 598 * @param {YAHOO.tool.TestSuite} testSuite The test suite to add. 599 * @return {Void} 600 * @static 601 * @private 602 * @method _addTestSuiteToTestTree 603 */ 604 _addTestSuiteToTestTree : function (parentNode /*:TestNode*/, testSuite /*:YAHOO.tool.TestSuite*/) /*:Void*/ { 605 606 //add the test suite 607 var node = parentNode.appendChild(testSuite); 608 609 //iterate over the items in the master suite 610 for (var i=0; i < testSuite.items.length; i++){ 611 if (testSuite.items[i] instanceof YAHOO.tool.TestSuite) { 612 this._addTestSuiteToTestTree(node, testSuite.items[i]); 613 } else if (testSuite.items[i] instanceof YAHOO.tool.TestCase) { 614 this._addTestCaseToTestTree(node, testSuite.items[i]); 615 } 616 } 617 }, 618 619 /** 620 * Builds the test tree based on items in the master suite. The tree is a hierarchical 621 * representation of the test suites, test cases, and test functions. The resulting tree 622 * is stored in _root and the pointer _cur is set to the root initially. 623 * @return {Void} 624 * @static 625 * @private 626 * @method _buildTestTree 627 */ 628 _buildTestTree : function () /*:Void*/ { 629 630 this._root = new TestNode(this.masterSuite); 631 //this._cur = this._root; 632 633 //iterate over the items in the master suite 634 for (var i=0; i < this.masterSuite.items.length; i++){ 635 if (this.masterSuite.items[i] instanceof YAHOO.tool.TestSuite) { 636 this._addTestSuiteToTestTree(this._root, this.masterSuite.items[i]); 637 } else if (this.masterSuite.items[i] instanceof YAHOO.tool.TestCase) { 638 this._addTestCaseToTestTree(this._root, this.masterSuite.items[i]); 639 } 640 } 641 642 }, 643 644 //------------------------------------------------------------------------- 645 // Private Methods 646 //------------------------------------------------------------------------- 647 648 /** 649 * Handles the completion of a test object's tests. Tallies test results 650 * from one level up to the next. 651 * @param {TestNode} node The TestNode representing the test object. 652 * @return {Void} 653 * @method _handleTestObjectComplete 654 * @private 655 * @static 656 */ 657 _handleTestObjectComplete : function (node /*:TestNode*/) /*:Void*/ { 658 if (YAHOO.lang.isObject(node.testObject)){ 659 node.parent.results.passed += node.results.passed; 660 node.parent.results.failed += node.results.failed; 661 node.parent.results.total += node.results.total; 662 node.parent.results.ignored += node.results.ignored; 663 node.parent.results[node.testObject.name] = node.results; 664 665 if (node.testObject instanceof YAHOO.tool.TestSuite){ 666 node.testObject.tearDown(); 667 node.results.duration = (new Date()) - node._start; 668 this.fireEvent(this.TEST_SUITE_COMPLETE_EVENT, { testSuite: node.testObject, results: node.results}); 669 } else if (node.testObject instanceof YAHOO.tool.TestCase){ 670 node.results.duration = (new Date()) - node._start; 671 this.fireEvent(this.TEST_CASE_COMPLETE_EVENT, { testCase: node.testObject, results: node.results}); 672 } 673 } 674 }, 675 676 //------------------------------------------------------------------------- 677 // Navigation Methods 678 //------------------------------------------------------------------------- 679 680 /** 681 * Retrieves the next node in the test tree. 682 * @return {TestNode} The next node in the test tree or null if the end is reached. 683 * @private 684 * @static 685 * @method _next 686 */ 687 _next : function () /*:TestNode*/ { 688 689 if (this._cur === null){ 690 this._cur = this._root; 691 } else if (this._cur.firstChild) { 692 this._cur = this._cur.firstChild; 693 } else if (this._cur.next) { 694 this._cur = this._cur.next; 695 } else { 696 while (this._cur && !this._cur.next && this._cur !== this._root){ 697 this._handleTestObjectComplete(this._cur); 698 this._cur = this._cur.parent; 699 } 700 701 if (this._cur == this._root){ 702 this._cur.results.type = "report"; 703 this._cur.results.timestamp = (new Date()).toLocaleString(); 704 this._cur.results.duration = (new Date()) - this._cur._start; 705 this._lastResults = this._cur.results; 706 this._running = false; 707 this.fireEvent(this.COMPLETE_EVENT, { results: this._lastResults}); 708 this._cur = null; 709 } else { 710 this._handleTestObjectComplete(this._cur); 711 this._cur = this._cur.next; 712 } 713 } 714 715 return this._cur; 716 }, 717 718 /** 719 * Runs a test case or test suite, returning the results. 720 * @param {YAHOO.tool.TestCase|YAHOO.tool.TestSuite} testObject The test case or test suite to run. 721 * @return {Object} Results of the execution with properties passed, failed, and total. 722 * @private 723 * @method _run 724 * @static 725 */ 726 _run : function () /*:Void*/ { 727 728 //flag to indicate if the TestRunner should wait before continuing 729 var shouldWait = false; 730 731 //get the next test node 732 var node = this._next(); 733 734 735 if (node !== null) { 736 737 //set flag to say the testrunner is running 738 this._running = true; 739 740 //eliminate last results 741 this._lastResult = null; 742 743 var testObject = node.testObject; 744 745 //figure out what to do 746 if (YAHOO.lang.isObject(testObject)){ 747 if (testObject instanceof YAHOO.tool.TestSuite){ 748 this.fireEvent(this.TEST_SUITE_BEGIN_EVENT, { testSuite: testObject }); 749 node._start = new Date(); 750 testObject.setUp(); 751 } else if (testObject instanceof YAHOO.tool.TestCase){ 752 this.fireEvent(this.TEST_CASE_BEGIN_EVENT, { testCase: testObject }); 753 node._start = new Date(); 754 } 755 756 //some environments don't support setTimeout 757 if (typeof setTimeout != "undefined"){ 758 setTimeout(function(){ 759 YAHOO.tool.TestRunner._run(); 760 }, 0); 761 } else { 762 this._run(); 763 } 764 } else { 765 this._runTest(node); 766 } 767 768 } 769 }, 770 771 _resumeTest : function (segment /*:Function*/) /*:Void*/ { 772 773 //get relevant information 774 var node /*:TestNode*/ = this._cur; 775 var testName /*:String*/ = node.testObject; 776 var testCase /*:YAHOO.tool.TestCase*/ = node.parent.testObject; 777 778 //cancel other waits if available 779 if (testCase.__yui_wait){ 780 clearTimeout(testCase.__yui_wait); 781 delete testCase.__yui_wait; 782 } 783 784 //get the "should" test cases 785 var shouldFail /*:Object*/ = (testCase._should.fail || {})[testName]; 786 var shouldError /*:Object*/ = (testCase._should.error || {})[testName]; 787 788 //variable to hold whether or not the test failed 789 var failed /*:Boolean*/ = false; 790 var error /*:Error*/ = null; 791 792 //try the test 793 try { 794 795 //run the test 796 segment.apply(testCase); 797 798 //if it should fail, and it got here, then it's a fail because it didn't 799 if (shouldFail){ 800 error = new YAHOO.util.ShouldFail(); 801 failed = true; 802 } else if (shouldError){ 803 error = new YAHOO.util.ShouldError(); 804 failed = true; 805 } 806 807 } catch (thrown /*:Error*/){ 808 if (thrown instanceof YAHOO.util.AssertionError) { 809 if (!shouldFail){ 810 error = thrown; 811 failed = true; 812 } 813 } else if (thrown instanceof YAHOO.tool.TestCase.Wait){ 814 815 if (YAHOO.lang.isFunction(thrown.segment)){ 816 if (YAHOO.lang.isNumber(thrown.delay)){ 817 818 //some environments don't support setTimeout 819 if (typeof setTimeout != "undefined"){ 820 testCase.__yui_wait = setTimeout(function(){ 821 YAHOO.tool.TestRunner._resumeTest(thrown.segment); 822 }, thrown.delay); 823 } else { 824 throw new Error("Asynchronous tests not supported in this environment."); 825 } 826 } 827 } 828 829 return; 830 831 } else { 832 //first check to see if it should error 833 if (!shouldError) { 834 error = new YAHOO.util.UnexpectedError(thrown); 835 failed = true; 836 } else { 837 //check to see what type of data we have 838 if (YAHOO.lang.isString(shouldError)){ 839 840 //if it's a string, check the error message 841 if (thrown.message != shouldError){ 842 error = new YAHOO.util.UnexpectedError(thrown); 843 failed = true; 844 } 845 } else if (YAHOO.lang.isFunction(shouldError)){ 846 847 //if it's a function, see if the error is an instance of it 848 if (!(thrown instanceof shouldError)){ 849 error = new YAHOO.util.UnexpectedError(thrown); 850 failed = true; 851 } 852 853 } else if (YAHOO.lang.isObject(shouldError)){ 854 855 //if it's an object, check the instance and message 856 if (!(thrown instanceof shouldError.constructor) || 857 thrown.message != shouldError.message){ 858 error = new YAHOO.util.UnexpectedError(thrown); 859 failed = true; 860 } 861 862 } 863 864 } 865 } 866 867 } 868 869 //fireEvent appropriate event 870 if (failed) { 871 this.fireEvent(this.TEST_FAIL_EVENT, { testCase: testCase, testName: testName, error: error }); 872 } else { 873 this.fireEvent(this.TEST_PASS_EVENT, { testCase: testCase, testName: testName }); 874 } 875 876 //run the tear down 877 testCase.tearDown(); 878 879 //calculate duration 880 var duration = (new Date()) - node._start; 881 882 //update results 883 node.parent.results[testName] = { 884 result: failed ? "fail" : "pass", 885 message: error ? error.getMessage() : "Test passed", 886 type: "test", 887 name: testName, 888 duration: duration 889 }; 890 891 if (failed){ 892 node.parent.results.failed++; 893 } else { 894 node.parent.results.passed++; 895 } 896 node.parent.results.total++; 897 898 //set timeout not supported in all environments 899 if (typeof setTimeout != "undefined"){ 900 setTimeout(function(){ 901 YAHOO.tool.TestRunner._run(); 902 }, 0); 903 } else { 904 this._run(); 905 } 906 907 }, 908 909 /** 910 * Runs a single test based on the data provided in the node. 911 * @param {TestNode} node The TestNode representing the test to run. 912 * @return {Void} 913 * @static 914 * @private 915 * @name _runTest 916 */ 917 _runTest : function (node /*:TestNode*/) /*:Void*/ { 918 919 //get relevant information 920 var testName /*:String*/ = node.testObject; 921 var testCase /*:YAHOO.tool.TestCase*/ = node.parent.testObject; 922 var test /*:Function*/ = testCase[testName]; 923 924 //get the "should" test cases 925 var shouldIgnore /*:Object*/ = (testCase._should.ignore || {})[testName]; 926 927 //figure out if the test should be ignored or not 928 if (shouldIgnore){ 929 930 //update results 931 node.parent.results[testName] = { 932 result: "ignore", 933 message: "Test ignored", 934 type: "test", 935 name: testName 936 }; 937 938 node.parent.results.ignored++; 939 node.parent.results.total++; 940 941 this.fireEvent(this.TEST_IGNORE_EVENT, { testCase: testCase, testName: testName }); 942 943 //some environments don't support setTimeout 944 if (typeof setTimeout != "undefined"){ 945 setTimeout(function(){ 946 YAHOO.tool.TestRunner._run(); 947 }, 0); 948 } else { 949 this._run(); 950 } 951 952 } else { 953 954 //mark the start time 955 node._start = new Date(); 956 957 //run the setup 958 testCase.setUp(); 959 960 //now call the body of the test 961 this._resumeTest(test); 962 } 963 964 }, 965 966 //------------------------------------------------------------------------- 967 // Protected Methods 968 //------------------------------------------------------------------------- 969 970 /** 971 * Fires events for the TestRunner. This overrides the default fireEvent() 972 * method from EventProvider to add the type property to the data that is 973 * passed through on each event call. 974 * @param {String} type The type of event to fire. 975 * @param {Object} data (Optional) Data for the event. 976 * @method fireEvent 977 * @static 978 * @protected 979 */ 980 fireEvent : function (type /*:String*/, data /*:Object*/) /*:Void*/ { 981 data = data || {}; 982 data.type = type; 983 TestRunner.superclass.fireEvent.call(this, type, data); 984 }, 985 986 //------------------------------------------------------------------------- 987 // Public Methods 988 //------------------------------------------------------------------------- 989 990 /** 991 * Adds a test suite or test case to the list of test objects to run. 992 * @param testObject Either a TestCase or a TestSuite that should be run. 993 * @return {Void} 994 * @method add 995 * @static 996 */ 997 add : function (testObject /*:Object*/) /*:Void*/ { 998 this.masterSuite.add(testObject); 999 }, 1000 1001 /** 1002 * Removes all test objects from the runner. 1003 * @return {Void} 1004 * @method clear 1005 * @static 1006 */ 1007 clear : function () /*:Void*/ { 1008 this.masterSuite = new YAHOO.tool.TestSuite("yuitests" + (new Date()).getTime()); 1009 }, 1010 1011 /** 1012 * Resumes the TestRunner after wait() was called. 1013 * @param {Function} segment The function to run as the rest 1014 * of the haulted test. 1015 * @return {Void} 1016 * @method resume 1017 * @static 1018 */ 1019 resume : function (segment /*:Function*/) /*:Void*/ { 1020 this._resumeTest(segment || function(){}); 1021 }, 1022 1023 /** 1024 * Runs the test suite. 1025 * @param {Boolean} oldMode (Optional) Specifies that the <= 2.8 way of 1026 * internally managing test suites should be used. 1027 * @return {Void} 1028 * @method run 1029 * @static 1030 */ 1031 run : function (oldMode) { 1032 1033 //pointer to runner to avoid scope issues 1034 var runner = YAHOO.tool.TestRunner; 1035 1036 //if there's only one suite on the masterSuite, move it up 1037 if (!oldMode && this.masterSuite.items.length == 1 && this.masterSuite.items[0] instanceof YAHOO.tool.TestSuite){ 1038 this.masterSuite = this.masterSuite.items[0]; 1039 } 1040 1041 //build the test tree 1042 runner._buildTestTree(); 1043 1044 //set when the test started 1045 runner._root._start = new Date(); 1046 1047 //fire the begin event 1048 runner.fireEvent(runner.BEGIN_EVENT); 1049 1050 //begin the testing 1051 runner._run(); 1052 } 1053 }); 1054 1055 return new TestRunner(); 1056 1057 })(); 1058 YAHOO.namespace("util"); 1059 1060 //----------------------------------------------------------------------------- 1061 // Assert object 1062 //----------------------------------------------------------------------------- 1063 1064 /** 1065 * The Assert object provides functions to test JavaScript values against 1066 * known and expected results. Whenever a comparison (assertion) fails, 1067 * an error is thrown. 1068 * 1069 * @namespace YAHOO.util 1070 * @class Assert 1071 * @static 1072 */ 1073 YAHOO.util.Assert = { 1074 1075 //------------------------------------------------------------------------- 1076 // Helper Methods 1077 //------------------------------------------------------------------------- 1078 1079 /** 1080 * Formats a message so that it can contain the original assertion message 1081 * in addition to the custom message. 1082 * @param {String} customMessage The message passed in by the developer. 1083 * @param {String} defaultMessage The message created by the error by default. 1084 * @return {String} The final error message, containing either or both. 1085 * @protected 1086 * @static 1087 * @method _formatMessage 1088 */ 1089 _formatMessage : function (customMessage /*:String*/, defaultMessage /*:String*/) /*:String*/ { 1090 var message = customMessage; 1091 if (YAHOO.lang.isString(customMessage) && customMessage.length > 0){ 1092 return YAHOO.lang.substitute(customMessage, { message: defaultMessage }); 1093 } else { 1094 return defaultMessage; 1095 } 1096 }, 1097 1098 //------------------------------------------------------------------------- 1099 // Generic Assertion Methods 1100 //------------------------------------------------------------------------- 1101 1102 /** 1103 * Forces an assertion error to occur. 1104 * @param {String} message (Optional) The message to display with the failure. 1105 * @method fail 1106 * @static 1107 */ 1108 fail : function (message /*:String*/) /*:Void*/ { 1109 throw new YAHOO.util.AssertionError(this._formatMessage(message, "Test force-failed.")); 1110 }, 1111 1112 //------------------------------------------------------------------------- 1113 // Equality Assertion Methods 1114 //------------------------------------------------------------------------- 1115 1116 /** 1117 * Asserts that a value is equal to another. This uses the double equals sign 1118 * so type coercion may occur. 1119 * @param {Object} expected The expected value. 1120 * @param {Object} actual The actual value to test. 1121 * @param {String} message (Optional) The message to display if the assertion fails. 1122 * @method areEqual 1123 * @static 1124 */ 1125 areEqual : function (expected /*:Object*/, actual /*:Object*/, message /*:String*/) /*:Void*/ { 1126 if (expected != actual) { 1127 throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Values should be equal."), expected, actual); 1128 } 1129 }, 1130 1131 /** 1132 * Asserts that a value is not equal to another. This uses the double equals sign 1133 * so type coercion may occur. 1134 * @param {Object} unexpected The unexpected value. 1135 * @param {Object} actual The actual value to test. 1136 * @param {String} message (Optional) The message to display if the assertion fails. 1137 * @method areNotEqual 1138 * @static 1139 */ 1140 areNotEqual : function (unexpected /*:Object*/, actual /*:Object*/, 1141 message /*:String*/) /*:Void*/ { 1142 if (unexpected == actual) { 1143 throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Values should not be equal."), unexpected); 1144 } 1145 }, 1146 1147 /** 1148 * Asserts that a value is not the same as another. This uses the triple equals sign 1149 * so no type coercion may occur. 1150 * @param {Object} unexpected The unexpected value. 1151 * @param {Object} actual The actual value to test. 1152 * @param {String} message (Optional) The message to display if the assertion fails. 1153 * @method areNotSame 1154 * @static 1155 */ 1156 areNotSame : function (unexpected /*:Object*/, actual /*:Object*/, message /*:String*/) /*:Void*/ { 1157 if (unexpected === actual) { 1158 throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Values should not be the same."), unexpected); 1159 } 1160 }, 1161 1162 /** 1163 * Asserts that a value is the same as another. This uses the triple equals sign 1164 * so no type coercion may occur. 1165 * @param {Object} expected The expected value. 1166 * @param {Object} actual The actual value to test. 1167 * @param {String} message (Optional) The message to display if the assertion fails. 1168 * @method areSame 1169 * @static 1170 */ 1171 areSame : function (expected /*:Object*/, actual /*:Object*/, message /*:String*/) /*:Void*/ { 1172 if (expected !== actual) { 1173 throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Values should be the same."), expected, actual); 1174 } 1175 }, 1176 1177 //------------------------------------------------------------------------- 1178 // Boolean Assertion Methods 1179 //------------------------------------------------------------------------- 1180 1181 /** 1182 * Asserts that a value is false. This uses the triple equals sign 1183 * so no type coercion may occur. 1184 * @param {Object} actual The actual value to test. 1185 * @param {String} message (Optional) The message to display if the assertion fails. 1186 * @method isFalse 1187 * @static 1188 */ 1189 isFalse : function (actual /*:Boolean*/, message /*:String*/) { 1190 if (false !== actual) { 1191 throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value should be false."), false, actual); 1192 } 1193 }, 1194 1195 /** 1196 * Asserts that a value is true. This uses the triple equals sign 1197 * so no type coercion may occur. 1198 * @param {Object} actual The actual value to test. 1199 * @param {String} message (Optional) The message to display if the assertion fails. 1200 * @method isTrue 1201 * @static 1202 */ 1203 isTrue : function (actual /*:Boolean*/, message /*:String*/) /*:Void*/ { 1204 if (true !== actual) { 1205 throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value should be true."), true, actual); 1206 } 1207 1208 }, 1209 1210 //------------------------------------------------------------------------- 1211 // Special Value Assertion Methods 1212 //------------------------------------------------------------------------- 1213 1214 /** 1215 * Asserts that a value is not a number. 1216 * @param {Object} actual The value to test. 1217 * @param {String} message (Optional) The message to display if the assertion fails. 1218 * @method isNaN 1219 * @static 1220 */ 1221 isNaN : function (actual /*:Object*/, message /*:String*/) /*:Void*/{ 1222 if (!isNaN(actual)){ 1223 throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value should be NaN."), NaN, actual); 1224 } 1225 }, 1226 1227 /** 1228 * Asserts that a value is not the special NaN value. 1229 * @param {Object} actual The value to test. 1230 * @param {String} message (Optional) The message to display if the assertion fails. 1231 * @method isNotNaN 1232 * @static 1233 */ 1234 isNotNaN : function (actual /*:Object*/, message /*:String*/) /*:Void*/{ 1235 if (isNaN(actual)){ 1236 throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Values should not be NaN."), NaN); 1237 } 1238 }, 1239 1240 /** 1241 * Asserts that a value is not null. This uses the triple equals sign 1242 * so no type coercion may occur. 1243 * @param {Object} actual The actual value to test. 1244 * @param {String} message (Optional) The message to display if the assertion fails. 1245 * @method isNotNull 1246 * @static 1247 */ 1248 isNotNull : function (actual /*:Object*/, message /*:String*/) /*:Void*/ { 1249 if (YAHOO.lang.isNull(actual)) { 1250 throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Values should not be null."), null); 1251 } 1252 }, 1253 1254 /** 1255 * Asserts that a value is not undefined. This uses the triple equals sign 1256 * so no type coercion may occur. 1257 * @param {Object} actual The actual value to test. 1258 * @param {String} message (Optional) The message to display if the assertion fails. 1259 * @method isNotUndefined 1260 * @static 1261 */ 1262 isNotUndefined : function (actual /*:Object*/, message /*:String*/) /*:Void*/ { 1263 if (YAHOO.lang.isUndefined(actual)) { 1264 throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should not be undefined."), undefined); 1265 } 1266 }, 1267 1268 /** 1269 * Asserts that a value is null. This uses the triple equals sign 1270 * so no type coercion may occur. 1271 * @param {Object} actual The actual value to test. 1272 * @param {String} message (Optional) The message to display if the assertion fails. 1273 * @method isNull 1274 * @static 1275 */ 1276 isNull : function (actual /*:Object*/, message /*:String*/) /*:Void*/ { 1277 if (!YAHOO.lang.isNull(actual)) { 1278 throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value should be null."), null, actual); 1279 } 1280 }, 1281 1282 /** 1283 * Asserts that a value is undefined. This uses the triple equals sign 1284 * so no type coercion may occur. 1285 * @param {Object} actual The actual value to test. 1286 * @param {String} message (Optional) The message to display if the assertion fails. 1287 * @method isUndefined 1288 * @static 1289 */ 1290 isUndefined : function (actual /*:Object*/, message /*:String*/) /*:Void*/ { 1291 if (!YAHOO.lang.isUndefined(actual)) { 1292 throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value should be undefined."), undefined, actual); 1293 } 1294 }, 1295 1296 //-------------------------------------------------------------------------- 1297 // Instance Assertion Methods 1298 //-------------------------------------------------------------------------- 1299 1300 /** 1301 * Asserts that a value is an array. 1302 * @param {Object} actual The value to test. 1303 * @param {String} message (Optional) The message to display if the assertion fails. 1304 * @method isArray 1305 * @static 1306 */ 1307 isArray : function (actual /*:Object*/, message /*:String*/) /*:Void*/ { 1308 if (!YAHOO.lang.isArray(actual)){ 1309 throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should be an array."), actual); 1310 } 1311 }, 1312 1313 /** 1314 * Asserts that a value is a Boolean. 1315 * @param {Object} actual The value to test. 1316 * @param {String} message (Optional) The message to display if the assertion fails. 1317 * @method isBoolean 1318 * @static 1319 */ 1320 isBoolean : function (actual /*:Object*/, message /*:String*/) /*:Void*/ { 1321 if (!YAHOO.lang.isBoolean(actual)){ 1322 throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should be a Boolean."), actual); 1323 } 1324 }, 1325 1326 /** 1327 * Asserts that a value is a function. 1328 * @param {Object} actual The value to test. 1329 * @param {String} message (Optional) The message to display if the assertion fails. 1330 * @method isFunction 1331 * @static 1332 */ 1333 isFunction : function (actual /*:Object*/, message /*:String*/) /*:Void*/ { 1334 if (!YAHOO.lang.isFunction(actual)){ 1335 throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should be a function."), actual); 1336 } 1337 }, 1338 1339 /** 1340 * Asserts that a value is an instance of a particular object. This may return 1341 * incorrect results when comparing objects from one frame to constructors in 1342 * another frame. For best results, don't use in a cross-frame manner. 1343 * @param {Function} expected The function that the object should be an instance of. 1344 * @param {Object} actual The object to test. 1345 * @param {String} message (Optional) The message to display if the assertion fails. 1346 * @method isInstanceOf 1347 * @static 1348 */ 1349 isInstanceOf : function (expected /*:Function*/, actual /*:Object*/, message /*:String*/) /*:Void*/ { 1350 if (!(actual instanceof expected)){ 1351 throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value isn't an instance of expected type."), expected, actual); 1352 } 1353 }, 1354 1355 /** 1356 * Asserts that a value is a number. 1357 * @param {Object} actual The value to test. 1358 * @param {String} message (Optional) The message to display if the assertion fails. 1359 * @method isNumber 1360 * @static 1361 */ 1362 isNumber : function (actual /*:Object*/, message /*:String*/) /*:Void*/ { 1363 if (!YAHOO.lang.isNumber(actual)){ 1364 throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should be a number."), actual); 1365 } 1366 }, 1367 1368 /** 1369 * Asserts that a value is an object. 1370 * @param {Object} actual The value to test. 1371 * @param {String} message (Optional) The message to display if the assertion fails. 1372 * @method isObject 1373 * @static 1374 */ 1375 isObject : function (actual /*:Object*/, message /*:String*/) /*:Void*/ { 1376 if (!YAHOO.lang.isObject(actual)){ 1377 throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should be an object."), actual); 1378 } 1379 }, 1380 1381 /** 1382 * Asserts that a value is a string. 1383 * @param {Object} actual The value to test. 1384 * @param {String} message (Optional) The message to display if the assertion fails. 1385 * @method isString 1386 * @static 1387 */ 1388 isString : function (actual /*:Object*/, message /*:String*/) /*:Void*/ { 1389 if (!YAHOO.lang.isString(actual)){ 1390 throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should be a string."), actual); 1391 } 1392 }, 1393 1394 /** 1395 * Asserts that a value is of a particular type. 1396 * @param {String} expectedType The expected type of the variable. 1397 * @param {Object} actualValue The actual value to test. 1398 * @param {String} message (Optional) The message to display if the assertion fails. 1399 * @method isTypeOf 1400 * @static 1401 */ 1402 isTypeOf : function (expected /*:String*/, actual /*:Object*/, message /*:String*/) /*:Void*/{ 1403 if (typeof actual != expected){ 1404 throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value should be of type " + expected + "."), expected, typeof actual); 1405 } 1406 } 1407 }; 1408 1409 //----------------------------------------------------------------------------- 1410 // Assertion errors 1411 //----------------------------------------------------------------------------- 1412 1413 /** 1414 * AssertionError is thrown whenever an assertion fails. It provides methods 1415 * to more easily get at error information and also provides a base class 1416 * from which more specific assertion errors can be derived. 1417 * 1418 * @param {String} message The message to display when the error occurs. 1419 * @namespace YAHOO.util 1420 * @class AssertionError 1421 * @extends Error 1422 * @constructor 1423 */ 1424 YAHOO.util.AssertionError = function (message /*:String*/){ 1425 1426 //call superclass 1427 //arguments.callee.superclass.constructor.call(this, message); 1428 1429 /* 1430 * Error message. Must be duplicated to ensure browser receives it. 1431 * @type String 1432 * @property message 1433 */ 1434 this.message /*:String*/ = message; 1435 1436 /** 1437 * The name of the error that occurred. 1438 * @type String 1439 * @property name 1440 */ 1441 this.name /*:String*/ = "AssertionError"; 1442 }; 1443 1444 //inherit methods 1445 YAHOO.lang.extend(YAHOO.util.AssertionError, Object, { 1446 1447 /** 1448 * Returns a fully formatted error for an assertion failure. This should 1449 * be overridden by all subclasses to provide specific information. 1450 * @method getMessage 1451 * @return {String} A string describing the error. 1452 */ 1453 getMessage : function () /*:String*/ { 1454 return this.message; 1455 }, 1456 1457 /** 1458 * Returns a string representation of the error. 1459 * @method toString 1460 * @return {String} A string representation of the error. 1461 */ 1462 toString : function () /*:String*/ { 1463 return this.name + ": " + this.getMessage(); 1464 } 1465 1466 }); 1467 1468 /** 1469 * ComparisonFailure is subclass of AssertionError that is thrown whenever 1470 * a comparison between two values fails. It provides mechanisms to retrieve 1471 * both the expected and actual value. 1472 * 1473 * @param {String} message The message to display when the error occurs. 1474 * @param {Object} expected The expected value. 1475 * @param {Object} actual The actual value that caused the assertion to fail. 1476 * @namespace YAHOO.util 1477 * @extends YAHOO.util.AssertionError 1478 * @class ComparisonFailure 1479 * @constructor 1480 */ 1481 YAHOO.util.ComparisonFailure = function (message /*:String*/, expected /*:Object*/, actual /*:Object*/){ 1482 1483 //call superclass 1484 YAHOO.util.AssertionError.call(this, message); 1485 1486 /** 1487 * The expected value. 1488 * @type Object 1489 * @property expected 1490 */ 1491 this.expected /*:Object*/ = expected; 1492 1493 /** 1494 * The actual value. 1495 * @type Object 1496 * @property actual 1497 */ 1498 this.actual /*:Object*/ = actual; 1499 1500 /** 1501 * The name of the error that occurred. 1502 * @type String 1503 * @property name 1504 */ 1505 this.name /*:String*/ = "ComparisonFailure"; 1506 1507 }; 1508 1509 //inherit methods 1510 YAHOO.lang.extend(YAHOO.util.ComparisonFailure, YAHOO.util.AssertionError, { 1511 1512 /** 1513 * Returns a fully formatted error for an assertion failure. This message 1514 * provides information about the expected and actual values. 1515 * @method toString 1516 * @return {String} A string describing the error. 1517 */ 1518 getMessage : function () /*:String*/ { 1519 return this.message + "\nExpected: " + this.expected + " (" + (typeof this.expected) + ")" + 1520 "\nActual:" + this.actual + " (" + (typeof this.actual) + ")"; 1521 } 1522 1523 }); 1524 1525 /** 1526 * UnexpectedValue is subclass of AssertionError that is thrown whenever 1527 * a value was unexpected in its scope. This typically means that a test 1528 * was performed to determine that a value was *not* equal to a certain 1529 * value. 1530 * 1531 * @param {String} message The message to display when the error occurs. 1532 * @param {Object} unexpected The unexpected value. 1533 * @namespace YAHOO.util 1534 * @extends YAHOO.util.AssertionError 1535 * @class UnexpectedValue 1536 * @constructor 1537 */ 1538 YAHOO.util.UnexpectedValue = function (message /*:String*/, unexpected /*:Object*/){ 1539 1540 //call superclass 1541 YAHOO.util.AssertionError.call(this, message); 1542 1543 /** 1544 * The unexpected value. 1545 * @type Object 1546 * @property unexpected 1547 */ 1548 this.unexpected /*:Object*/ = unexpected; 1549 1550 /** 1551 * The name of the error that occurred. 1552 * @type String 1553 * @property name 1554 */ 1555 this.name /*:String*/ = "UnexpectedValue"; 1556 1557 }; 1558 1559 //inherit methods 1560 YAHOO.lang.extend(YAHOO.util.UnexpectedValue, YAHOO.util.AssertionError, { 1561 1562 /** 1563 * Returns a fully formatted error for an assertion failure. The message 1564 * contains information about the unexpected value that was encountered. 1565 * @method getMessage 1566 * @return {String} A string describing the error. 1567 */ 1568 getMessage : function () /*:String*/ { 1569 return this.message + "\nUnexpected: " + this.unexpected + " (" + (typeof this.unexpected) + ") "; 1570 } 1571 1572 }); 1573 1574 /** 1575 * ShouldFail is subclass of AssertionError that is thrown whenever 1576 * a test was expected to fail but did not. 1577 * 1578 * @param {String} message The message to display when the error occurs. 1579 * @namespace YAHOO.util 1580 * @extends YAHOO.util.AssertionError 1581 * @class ShouldFail 1582 * @constructor 1583 */ 1584 YAHOO.util.ShouldFail = function (message /*:String*/){ 1585 1586 //call superclass 1587 YAHOO.util.AssertionError.call(this, message || "This test should fail but didn't."); 1588 1589 /** 1590 * The name of the error that occurred. 1591 * @type String 1592 * @property name 1593 */ 1594 this.name /*:String*/ = "ShouldFail"; 1595 1596 }; 1597 1598 //inherit methods 1599 YAHOO.lang.extend(YAHOO.util.ShouldFail, YAHOO.util.AssertionError); 1600 1601 /** 1602 * ShouldError is subclass of AssertionError that is thrown whenever 1603 * a test is expected to throw an error but doesn't. 1604 * 1605 * @param {String} message The message to display when the error occurs. 1606 * @namespace YAHOO.util 1607 * @extends YAHOO.util.AssertionError 1608 * @class ShouldError 1609 * @constructor 1610 */ 1611 YAHOO.util.ShouldError = function (message /*:String*/){ 1612 1613 //call superclass 1614 YAHOO.util.AssertionError.call(this, message || "This test should have thrown an error but didn't."); 1615 1616 /** 1617 * The name of the error that occurred. 1618 * @type String 1619 * @property name 1620 */ 1621 this.name /*:String*/ = "ShouldError"; 1622 1623 }; 1624 1625 //inherit methods 1626 YAHOO.lang.extend(YAHOO.util.ShouldError, YAHOO.util.AssertionError); 1627 1628 /** 1629 * UnexpectedError is subclass of AssertionError that is thrown whenever 1630 * an error occurs within the course of a test and the test was not expected 1631 * to throw an error. 1632 * 1633 * @param {Error} cause The unexpected error that caused this error to be 1634 * thrown. 1635 * @namespace YAHOO.util 1636 * @extends YAHOO.util.AssertionError 1637 * @class UnexpectedError 1638 * @constructor 1639 */ 1640 YAHOO.util.UnexpectedError = function (cause /*:Object*/){ 1641 1642 //call superclass 1643 YAHOO.util.AssertionError.call(this, "Unexpected error: " + cause.message); 1644 1645 /** 1646 * The unexpected error that occurred. 1647 * @type Error 1648 * @property cause 1649 */ 1650 this.cause /*:Error*/ = cause; 1651 1652 /** 1653 * The name of the error that occurred. 1654 * @type String 1655 * @property name 1656 */ 1657 this.name /*:String*/ = "UnexpectedError"; 1658 1659 /** 1660 * Stack information for the error (if provided). 1661 * @type String 1662 * @property stack 1663 */ 1664 this.stack /*:String*/ = cause.stack; 1665 1666 }; 1667 1668 //inherit methods 1669 YAHOO.lang.extend(YAHOO.util.UnexpectedError, YAHOO.util.AssertionError); 1670 //----------------------------------------------------------------------------- 1671 // ArrayAssert object 1672 //----------------------------------------------------------------------------- 1673 1674 /** 1675 * The ArrayAssert object provides functions to test JavaScript array objects 1676 * for a variety of cases. 1677 * 1678 * @namespace YAHOO.util 1679 * @class ArrayAssert 1680 * @static 1681 */ 1682 1683 YAHOO.util.ArrayAssert = { 1684 1685 /** 1686 * Asserts that a value is present in an array. This uses the triple equals 1687 * sign so no type coercion may occur. 1688 * @param {Object} needle The value that is expected in the array. 1689 * @param {Array} haystack An array of values. 1690 * @param {String} message (Optional) The message to display if the assertion fails. 1691 * @method contains 1692 * @static 1693 */ 1694 contains : function (needle /*:Object*/, haystack /*:Array*/, 1695 message /*:String*/) /*:Void*/ { 1696 1697 var found /*:Boolean*/ = false; 1698 var Assert = YAHOO.util.Assert; 1699 1700 //begin checking values 1701 for (var i=0; i < haystack.length && !found; i++){ 1702 if (haystack[i] === needle) { 1703 found = true; 1704 } 1705 } 1706 1707 if (!found){ 1708 Assert.fail(Assert._formatMessage(message, "Value " + needle + " (" + (typeof needle) + ") not found in array [" + haystack + "].")); 1709 } 1710 }, 1711 1712 /** 1713 * Asserts that a set of values are present in an array. This uses the triple equals 1714 * sign so no type coercion may occur. For this assertion to pass, all values must 1715 * be found. 1716 * @param {Object[]} needles An array of values that are expected in the array. 1717 * @param {Array} haystack An array of values to check. 1718 * @param {String} message (Optional) The message to display if the assertion fails. 1719 * @method containsItems 1720 * @static 1721 */ 1722 containsItems : function (needles /*:Object[]*/, haystack /*:Array*/, 1723 message /*:String*/) /*:Void*/ { 1724 1725 //begin checking values 1726 for (var i=0; i < needles.length; i++){ 1727 this.contains(needles[i], haystack, message); 1728 } 1729 }, 1730 1731 /** 1732 * Asserts that a value matching some condition is present in an array. This uses 1733 * a function to determine a match. 1734 * @param {Function} matcher A function that returns true if the items matches or false if not. 1735 * @param {Array} haystack An array of values. 1736 * @param {String} message (Optional) The message to display if the assertion fails. 1737 * @method containsMatch 1738 * @static 1739 */ 1740 containsMatch : function (matcher /*:Function*/, haystack /*:Array*/, 1741 message /*:String*/) /*:Void*/ { 1742 1743 //check for valid matcher 1744 if (typeof matcher != "function"){ 1745 throw new TypeError("ArrayAssert.containsMatch(): First argument must be a function."); 1746 } 1747 1748 var found /*:Boolean*/ = false; 1749 var Assert = YAHOO.util.Assert; 1750 1751 //begin checking values 1752 for (var i=0; i < haystack.length && !found; i++){ 1753 if (matcher(haystack[i])) { 1754 found = true; 1755 } 1756 } 1757 1758 if (!found){ 1759 Assert.fail(Assert._formatMessage(message, "No match found in array [" + haystack + "].")); 1760 } 1761 }, 1762 1763 /** 1764 * Asserts that a value is not present in an array. This uses the triple equals 1765 * sign so no type coercion may occur. 1766 * @param {Object} needle The value that is expected in the array. 1767 * @param {Array} haystack An array of values. 1768 * @param {String} message (Optional) The message to display if the assertion fails. 1769 * @method doesNotContain 1770 * @static 1771 */ 1772 doesNotContain : function (needle /*:Object*/, haystack /*:Array*/, 1773 message /*:String*/) /*:Void*/ { 1774 1775 var found /*:Boolean*/ = false; 1776 var Assert = YAHOO.util.Assert; 1777 1778 //begin checking values 1779 for (var i=0; i < haystack.length && !found; i++){ 1780 if (haystack[i] === needle) { 1781 found = true; 1782 } 1783 } 1784 1785 if (found){ 1786 Assert.fail(Assert._formatMessage(message, "Value found in array [" + haystack + "].")); 1787 } 1788 }, 1789 1790 /** 1791 * Asserts that a set of values are not present in an array. This uses the triple equals 1792 * sign so no type coercion may occur. For this assertion to pass, all values must 1793 * not be found. 1794 * @param {Object[]} needles An array of values that are not expected in the array. 1795 * @param {Array} haystack An array of values to check. 1796 * @param {String} message (Optional) The message to display if the assertion fails. 1797 * @method doesNotContainItems 1798 * @static 1799 */ 1800 doesNotContainItems : function (needles /*:Object[]*/, haystack /*:Array*/, 1801 message /*:String*/) /*:Void*/ { 1802 1803 for (var i=0; i < needles.length; i++){ 1804 this.doesNotContain(needles[i], haystack, message); 1805 } 1806 1807 }, 1808 1809 /** 1810 * Asserts that no values matching a condition are present in an array. This uses 1811 * a function to determine a match. 1812 * @param {Function} matcher A function that returns true if the items matches or false if not. 1813 * @param {Array} haystack An array of values. 1814 * @param {String} message (Optional) The message to display if the assertion fails. 1815 * @method doesNotContainMatch 1816 * @static 1817 */ 1818 doesNotContainMatch : function (matcher /*:Function*/, haystack /*:Array*/, 1819 message /*:String*/) /*:Void*/ { 1820 1821 //check for valid matcher 1822 if (typeof matcher != "function"){ 1823 throw new TypeError("ArrayAssert.doesNotContainMatch(): First argument must be a function."); 1824 } 1825 1826 var found /*:Boolean*/ = false; 1827 var Assert = YAHOO.util.Assert; 1828 1829 //begin checking values 1830 for (var i=0; i < haystack.length && !found; i++){ 1831 if (matcher(haystack[i])) { 1832 found = true; 1833 } 1834 } 1835 1836 if (found){ 1837 Assert.fail(Assert._formatMessage(message, "Value found in array [" + haystack + "].")); 1838 } 1839 }, 1840 1841 /** 1842 * Asserts that the given value is contained in an array at the specified index. 1843 * This uses the triple equals sign so no type coercion will occur. 1844 * @param {Object} needle The value to look for. 1845 * @param {Array} haystack The array to search in. 1846 * @param {int} index The index at which the value should exist. 1847 * @param {String} message (Optional) The message to display if the assertion fails. 1848 * @method indexOf 1849 * @static 1850 */ 1851 indexOf : function (needle /*:Object*/, haystack /*:Array*/, index /*:int*/, message /*:String*/) /*:Void*/ { 1852 1853 //try to find the value in the array 1854 for (var i=0; i < haystack.length; i++){ 1855 if (haystack[i] === needle){ 1856 YAHOO.util.Assert.areEqual(index, i, message || "Value exists at index " + i + " but should be at index " + index + "."); 1857 return; 1858 } 1859 } 1860 1861 var Assert = YAHOO.util.Assert; 1862 1863 //if it makes it here, it wasn't found at all 1864 Assert.fail(Assert._formatMessage(message, "Value doesn't exist in array [" + haystack + "].")); 1865 }, 1866 1867 /** 1868 * Asserts that the values in an array are equal, and in the same position, 1869 * as values in another array. This uses the double equals sign 1870 * so type coercion may occur. Note that the array objects themselves 1871 * need not be the same for this test to pass. 1872 * @param {Array} expected An array of the expected values. 1873 * @param {Array} actual Any array of the actual values. 1874 * @param {String} message (Optional) The message to display if the assertion fails. 1875 * @method itemsAreEqual 1876 * @static 1877 */ 1878 itemsAreEqual : function (expected /*:Array*/, actual /*:Array*/, 1879 message /*:String*/) /*:Void*/ { 1880 1881 //one may be longer than the other, so get the maximum length 1882 var len /*:int*/ = Math.max(expected.length, actual.length || 0); 1883 var Assert = YAHOO.util.Assert; 1884 1885 //begin checking values 1886 for (var i=0; i < len; i++){ 1887 Assert.areEqual(expected[i], actual[i], 1888 Assert._formatMessage(message, "Values in position " + i + " are not equal.")); 1889 } 1890 }, 1891 1892 /** 1893 * Asserts that the values in an array are equivalent, and in the same position, 1894 * as values in another array. This uses a function to determine if the values 1895 * are equivalent. Note that the array objects themselves 1896 * need not be the same for this test to pass. 1897 * @param {Array} expected An array of the expected values. 1898 * @param {Array} actual Any array of the actual values. 1899 * @param {Function} comparator A function that returns true if the values are equivalent 1900 * or false if not. 1901 * @param {String} message (Optional) The message to display if the assertion fails. 1902 * @return {Void} 1903 * @method itemsAreEquivalent 1904 * @static 1905 */ 1906 itemsAreEquivalent : function (expected /*:Array*/, actual /*:Array*/, 1907 comparator /*:Function*/, message /*:String*/) /*:Void*/ { 1908 1909 //make sure the comparator is valid 1910 if (typeof comparator != "function"){ 1911 throw new TypeError("ArrayAssert.itemsAreEquivalent(): Third argument must be a function."); 1912 } 1913 1914 //one may be longer than the other, so get the maximum length 1915 var len /*:int*/ = Math.max(expected.length, actual.length || 0); 1916 1917 //begin checking values 1918 for (var i=0; i < len; i++){ 1919 if (!comparator(expected[i], actual[i])){ 1920 throw new YAHOO.util.ComparisonFailure(YAHOO.util.Assert._formatMessage(message, "Values in position " + i + " are not equivalent."), expected[i], actual[i]); 1921 } 1922 } 1923 }, 1924 1925 /** 1926 * Asserts that an array is empty. 1927 * @param {Array} actual The array to test. 1928 * @param {String} message (Optional) The message to display if the assertion fails. 1929 * @method isEmpty 1930 * @static 1931 */ 1932 isEmpty : function (actual /*:Array*/, message /*:String*/) /*:Void*/ { 1933 if (actual.length > 0){ 1934 var Assert = YAHOO.util.Assert; 1935 Assert.fail(Assert._formatMessage(message, "Array should be empty.")); 1936 } 1937 }, 1938 1939 /** 1940 * Asserts that an array is not empty. 1941 * @param {Array} actual The array to test. 1942 * @param {String} message (Optional) The message to display if the assertion fails. 1943 * @method isNotEmpty 1944 * @static 1945 */ 1946 isNotEmpty : function (actual /*:Array*/, message /*:String*/) /*:Void*/ { 1947 if (actual.length === 0){ 1948 var Assert = YAHOO.util.Assert; 1949 Assert.fail(Assert._formatMessage(message, "Array should not be empty.")); 1950 } 1951 }, 1952 1953 /** 1954 * Asserts that the values in an array are the same, and in the same position, 1955 * as values in another array. This uses the triple equals sign 1956 * so no type coercion will occur. Note that the array objects themselves 1957 * need not be the same for this test to pass. 1958 * @param {Array} expected An array of the expected values. 1959 * @param {Array} actual Any array of the actual values. 1960 * @param {String} message (Optional) The message to display if the assertion fails. 1961 * @method itemsAreSame 1962 * @static 1963 */ 1964 itemsAreSame : function (expected /*:Array*/, actual /*:Array*/, 1965 message /*:String*/) /*:Void*/ { 1966 1967 //one may be longer than the other, so get the maximum length 1968 var len /*:int*/ = Math.max(expected.length, actual.length || 0); 1969 var Assert = YAHOO.util.Assert; 1970 1971 //begin checking values 1972 for (var i=0; i < len; i++){ 1973 Assert.areSame(expected[i], actual[i], 1974 Assert._formatMessage(message, "Values in position " + i + " are not the same.")); 1975 } 1976 }, 1977 1978 /** 1979 * Asserts that the given value is contained in an array at the specified index, 1980 * starting from the back of the array. 1981 * This uses the triple equals sign so no type coercion will occur. 1982 * @param {Object} needle The value to look for. 1983 * @param {Array} haystack The array to search in. 1984 * @param {int} index The index at which the value should exist. 1985 * @param {String} message (Optional) The message to display if the assertion fails. 1986 * @method lastIndexOf 1987 * @static 1988 */ 1989 lastIndexOf : function (needle /*:Object*/, haystack /*:Array*/, index /*:int*/, message /*:String*/) /*:Void*/ { 1990 1991 var Assert = YAHOO.util.Assert; 1992 1993 //try to find the value in the array 1994 for (var i=haystack.length; i >= 0; i--){ 1995 if (haystack[i] === needle){ 1996 Assert.areEqual(index, i, Assert._formatMessage(message, "Value exists at index " + i + " but should be at index " + index + ".")); 1997 return; 1998 } 1999 } 2000 2001 //if it makes it here, it wasn't found at all 2002 Assert.fail(Assert._formatMessage(message, "Value doesn't exist in array.")); 2003 } 2004 2005 }; 2006 YAHOO.namespace("util"); 2007 2008 2009 //----------------------------------------------------------------------------- 2010 // ObjectAssert object 2011 //----------------------------------------------------------------------------- 2012 2013 /** 2014 * The ObjectAssert object provides functions to test JavaScript objects 2015 * for a variety of cases. 2016 * 2017 * @namespace YAHOO.util 2018 * @class ObjectAssert 2019 * @static 2020 */ 2021 YAHOO.util.ObjectAssert = { 2022 2023 /** 2024 * Asserts that all properties in the object exist in another object. 2025 * @param {Object} expected An object with the expected properties. 2026 * @param {Object} actual An object with the actual properties. 2027 * @param {String} message (Optional) The message to display if the assertion fails. 2028 * @method propertiesAreEqual 2029 * @static 2030 */ 2031 propertiesAreEqual : function (expected /*:Object*/, actual /*:Object*/, 2032 message /*:String*/) /*:Void*/ { 2033 2034 var Assert = YAHOO.util.Assert; 2035 2036 //get all properties in the object 2037 var properties /*:Array*/ = []; 2038 for (var property in expected){ 2039 properties.push(property); 2040 } 2041 2042 //see if the properties are in the expected object 2043 for (var i=0; i < properties.length; i++){ 2044 Assert.isNotUndefined(actual[properties[i]], 2045 Assert._formatMessage(message, "Property '" + properties[i] + "' expected.")); 2046 } 2047 2048 }, 2049 2050 /** 2051 * Asserts that an object has a property with the given name. 2052 * @param {String} propertyName The name of the property to test. 2053 * @param {Object} object The object to search. 2054 * @param {String} message (Optional) The message to display if the assertion fails. 2055 * @method hasProperty 2056 * @static 2057 */ 2058 hasProperty : function (propertyName /*:String*/, object /*:Object*/, message /*:String*/) /*:Void*/ { 2059 if (!(propertyName in object)){ 2060 var Assert = YAHOO.util.Assert; 2061 Assert.fail(Assert._formatMessage(message, "Property '" + propertyName + "' not found on object.")); 2062 } 2063 }, 2064 2065 /** 2066 * Asserts that a property with the given name exists on an object instance (not on its prototype). 2067 * @param {String} propertyName The name of the property to test. 2068 * @param {Object} object The object to search. 2069 * @param {String} message (Optional) The message to display if the assertion fails. 2070 * @method hasProperty 2071 * @static 2072 */ 2073 hasOwnProperty : function (propertyName /*:String*/, object /*:Object*/, message /*:String*/) /*:Void*/ { 2074 if (!YAHOO.lang.hasOwnProperty(object, propertyName)){ 2075 var Assert = YAHOO.util.Assert; 2076 Assert.fail(Assert._formatMessage(message, "Property '" + propertyName + "' not found on object instance.")); 2077 } 2078 } 2079 }; 2080 //----------------------------------------------------------------------------- 2081 // DateAssert object 2082 //----------------------------------------------------------------------------- 2083 2084 /** 2085 * The DateAssert object provides functions to test JavaScript Date objects 2086 * for a variety of cases. 2087 * 2088 * @namespace YAHOO.util 2089 * @class DateAssert 2090 * @static 2091 */ 2092 2093 YAHOO.util.DateAssert = { 2094 2095 /** 2096 * Asserts that a date's month, day, and year are equal to another date's. 2097 * @param {Date} expected The expected date. 2098 * @param {Date} actual The actual date to test. 2099 * @param {String} message (Optional) The message to display if the assertion fails. 2100 * @method datesAreEqual 2101 * @static 2102 */ 2103 datesAreEqual : function (expected /*:Date*/, actual /*:Date*/, message /*:String*/){ 2104 if (expected instanceof Date && actual instanceof Date){ 2105 var Assert = YAHOO.util.Assert; 2106 Assert.areEqual(expected.getFullYear(), actual.getFullYear(), Assert._formatMessage(message, "Years should be equal.")); 2107 Assert.areEqual(expected.getMonth(), actual.getMonth(), Assert._formatMessage(message, "Months should be equal.")); 2108 Assert.areEqual(expected.getDate(), actual.getDate(), Assert._formatMessage(message, "Day of month should be equal.")); 2109 } else { 2110 throw new TypeError("DateAssert.datesAreEqual(): Expected and actual values must be Date objects."); 2111 } 2112 }, 2113 2114 /** 2115 * Asserts that a date's hour, minutes, and seconds are equal to another date's. 2116 * @param {Date} expected The expected date. 2117 * @param {Date} actual The actual date to test. 2118 * @param {String} message (Optional) The message to display if the assertion fails. 2119 * @method timesAreEqual 2120 * @static 2121 */ 2122 timesAreEqual : function (expected /*:Date*/, actual /*:Date*/, message /*:String*/){ 2123 if (expected instanceof Date && actual instanceof Date){ 2124 var Assert = YAHOO.util.Assert; 2125 Assert.areEqual(expected.getHours(), actual.getHours(), Assert._formatMessage(message, "Hours should be equal.")); 2126 Assert.areEqual(expected.getMinutes(), actual.getMinutes(), Assert._formatMessage(message, "Minutes should be equal.")); 2127 Assert.areEqual(expected.getSeconds(), actual.getSeconds(), Assert._formatMessage(message, "Seconds should be equal.")); 2128 } else { 2129 throw new TypeError("DateAssert.timesAreEqual(): Expected and actual values must be Date objects."); 2130 } 2131 } 2132 2133 }; 2134 YAHOO.namespace("tool"); 2135 2136 //----------------------------------------------------------------------------- 2137 // TestManager object 2138 //----------------------------------------------------------------------------- 2139 2140 /** 2141 * Runs pages containing test suite definitions. 2142 * @namespace YAHOO.tool 2143 * @class TestManager 2144 * @static 2145 */ 2146 YAHOO.tool.TestManager = { 2147 2148 /** 2149 * Constant for the testpagebegin custom event 2150 * @property TEST_PAGE_BEGIN_EVENT 2151 * @static 2152 * @type string 2153 * @final 2154 */ 2155 TEST_PAGE_BEGIN_EVENT /*:String*/ : "testpagebegin", 2156 2157 /** 2158 * Constant for the testpagecomplete custom event 2159 * @property TEST_PAGE_COMPLETE_EVENT 2160 * @static 2161 * @type string 2162 * @final 2163 */ 2164 TEST_PAGE_COMPLETE_EVENT /*:String*/ : "testpagecomplete", 2165 2166 /** 2167 * Constant for the testmanagerbegin custom event 2168 * @property TEST_MANAGER_BEGIN_EVENT 2169 * @static 2170 * @type string 2171 * @final 2172 */ 2173 TEST_MANAGER_BEGIN_EVENT /*:String*/ : "testmanagerbegin", 2174 2175 /** 2176 * Constant for the testmanagercomplete custom event 2177 * @property TEST_MANAGER_COMPLETE_EVENT 2178 * @static 2179 * @type string 2180 * @final 2181 */ 2182 TEST_MANAGER_COMPLETE_EVENT /*:String*/ : "testmanagercomplete", 2183 2184 //------------------------------------------------------------------------- 2185 // Private Properties 2186 //------------------------------------------------------------------------- 2187 2188 2189 /** 2190 * The URL of the page currently being executed. 2191 * @type String 2192 * @private 2193 * @property _curPage 2194 * @static 2195 */ 2196 _curPage /*:String*/ : null, 2197 2198 /** 2199 * The frame used to load and run tests. 2200 * @type Window 2201 * @private 2202 * @property _frame 2203 * @static 2204 */ 2205 _frame /*:Window*/ : null, 2206 2207 /** 2208 * The logger used to output results from the various tests. 2209 * @type YAHOO.tool.TestLogger 2210 * @private 2211 * @property _logger 2212 * @static 2213 */ 2214 _logger : null, 2215 2216 /** 2217 * The timeout ID for the next iteration through the tests. 2218 * @type int 2219 * @private 2220 * @property _timeoutId 2221 * @static 2222 */ 2223 _timeoutId /*:int*/ : 0, 2224 2225 /** 2226 * Array of pages to load. 2227 * @type String[] 2228 * @private 2229 * @property _pages 2230 * @static 2231 */ 2232 _pages /*:String[]*/ : [], 2233 2234 /** 2235 * Aggregated results 2236 * @type Object 2237 * @private 2238 * @property _results 2239 * @static 2240 */ 2241 _results: null, 2242 2243 //------------------------------------------------------------------------- 2244 // Private Methods 2245 //------------------------------------------------------------------------- 2246 2247 /** 2248 * Handles TestRunner.COMPLETE_EVENT, storing the results and beginning 2249 * the loop again. 2250 * @param {Object} data Data about the event. 2251 * @return {Void} 2252 * @private 2253 * @static 2254 */ 2255 _handleTestRunnerComplete : function (data /*:Object*/) /*:Void*/ { 2256 2257 this.fireEvent(this.TEST_PAGE_COMPLETE_EVENT, { 2258 page: this._curPage, 2259 results: data.results 2260 }); 2261 2262 //save results 2263 //this._results[this.curPage] = data.results; 2264 2265 //process 'em 2266 this._processResults(this._curPage, data.results); 2267 2268 this._logger.clearTestRunner(); 2269 2270 //if there's more to do, set a timeout to begin again 2271 if (this._pages.length){ 2272 this._timeoutId = setTimeout(function(){ 2273 YAHOO.tool.TestManager._run(); 2274 }, 1000); 2275 } else { 2276 this.fireEvent(this.TEST_MANAGER_COMPLETE_EVENT, this._results); 2277 } 2278 }, 2279 2280 /** 2281 * Processes the results of a test page run, outputting log messages 2282 * for failed tests. 2283 * @return {Void} 2284 * @private 2285 * @static 2286 */ 2287 _processResults : function (page /*:String*/, results /*:Object*/) /*:Void*/ { 2288 2289 var r = this._results; 2290 2291 r.passed += results.passed; 2292 r.failed += results.failed; 2293 r.ignored += results.ignored; 2294 r.total += results.total; 2295 r.duration += results.duration; 2296 2297 if (results.failed){ 2298 r.failedPages.push(page); 2299 } else { 2300 r.passedPages.push(page); 2301 } 2302 2303 results.name = page; 2304 results.type = "page"; 2305 2306 r[page] = results; 2307 }, 2308 2309 /** 2310 * Loads the next test page into the iframe. 2311 * @return {Void} 2312 * @static 2313 * @private 2314 */ 2315 _run : function () /*:Void*/ { 2316 2317 //set the current page 2318 this._curPage = this._pages.shift(); 2319 2320 this.fireEvent(this.TEST_PAGE_BEGIN_EVENT, this._curPage); 2321 2322 //load the frame - destroy history in case there are other iframes that 2323 //need testing 2324 this._frame.location.replace(this._curPage); 2325 2326 }, 2327 2328 //------------------------------------------------------------------------- 2329 // Public Methods 2330 //------------------------------------------------------------------------- 2331 2332 /** 2333 * Signals that a test page has been loaded. This should be called from 2334 * within the test page itself to notify the TestManager that it is ready. 2335 * @return {Void} 2336 * @static 2337 */ 2338 load : function () /*:Void*/ { 2339 if (parent.YAHOO.tool.TestManager !== this){ 2340 parent.YAHOO.tool.TestManager.load(); 2341 } else { 2342 2343 if (this._frame) { 2344 //assign event handling 2345 var TestRunner = this._frame.YAHOO.tool.TestRunner; 2346 2347 this._logger.setTestRunner(TestRunner); 2348 TestRunner.subscribe(TestRunner.COMPLETE_EVENT, this._handleTestRunnerComplete, this, true); 2349 2350 //run it 2351 TestRunner.run(); 2352 } 2353 } 2354 }, 2355 2356 /** 2357 * Sets the pages to be loaded. 2358 * @param {String[]} pages An array of URLs to load. 2359 * @return {Void} 2360 * @static 2361 */ 2362 setPages : function (pages /*:String[]*/) /*:Void*/ { 2363 this._pages = pages; 2364 }, 2365 2366 /** 2367 * Begins the process of running the tests. 2368 * @return {Void} 2369 * @static 2370 */ 2371 start : function () /*:Void*/ { 2372 2373 if (!this._initialized) { 2374 2375 /** 2376 * Fires when loading a test page 2377 * @event testpagebegin 2378 * @param curPage {string} the page being loaded 2379 * @static 2380 */ 2381 this.createEvent(this.TEST_PAGE_BEGIN_EVENT); 2382 2383 /** 2384 * Fires when a test page is complete 2385 * @event testpagecomplete 2386 * @param obj {page: string, results: object} the name of the 2387 * page that was loaded, and the test suite results 2388 * @static 2389 */ 2390 this.createEvent(this.TEST_PAGE_COMPLETE_EVENT); 2391 2392 /** 2393 * Fires when the test manager starts running all test pages 2394 * @event testmanagerbegin 2395 * @static 2396 */ 2397 this.createEvent(this.TEST_MANAGER_BEGIN_EVENT); 2398 2399 /** 2400 * Fires when the test manager finishes running all test pages. External 2401 * test runners should subscribe to this event in order to get the 2402 * aggregated test results. 2403 * @event testmanagercomplete 2404 * @param obj { pages_passed: int, pages_failed: int, tests_passed: int 2405 * tests_failed: int, passed: string[], failed: string[], 2406 * page_results: {} } 2407 * @static 2408 */ 2409 this.createEvent(this.TEST_MANAGER_COMPLETE_EVENT); 2410 2411 //create iframe if not already available 2412 if (!this._frame){ 2413 var frame /*:HTMLElement*/ = document.createElement("iframe"); 2414 frame.style.visibility = "hidden"; 2415 frame.style.position = "absolute"; 2416 document.body.appendChild(frame); 2417 this._frame = frame.contentWindow || frame.contentDocument.parentWindow; 2418 } 2419 2420 //create test logger if not already available 2421 if (!this._logger){ 2422 this._logger = new YAHOO.tool.TestLogger(); 2423 } 2424 2425 this._initialized = true; 2426 } 2427 2428 2429 // reset the results cache 2430 this._results = { 2431 2432 passed: 0, 2433 failed: 0, 2434 ignored: 0, 2435 total: 0, 2436 type: "report", 2437 name: "YUI Test Results", 2438 duration: 0, 2439 failedPages:[], 2440 passedPages:[] 2441 /* 2442 // number of pages that pass 2443 pages_passed: 0, 2444 // number of pages that fail 2445 pages_failed: 0, 2446 // total number of tests passed 2447 tests_passed: 0, 2448 // total number of tests failed 2449 tests_failed: 0, 2450 // array of pages that passed 2451 passed: [], 2452 // array of pages that failed 2453 failed: [], 2454 // map of full results for each page 2455 page_results: {}*/ 2456 }; 2457 2458 this.fireEvent(this.TEST_MANAGER_BEGIN_EVENT, null); 2459 this._run(); 2460 2461 }, 2462 2463 /** 2464 * Stops the execution of tests. 2465 * @return {Void} 2466 * @static 2467 */ 2468 stop : function () /*:Void*/ { 2469 clearTimeout(this._timeoutId); 2470 } 2471 2472 }; 2473 2474 YAHOO.lang.augmentObject(YAHOO.tool.TestManager, YAHOO.util.EventProvider.prototype); 2475 2476 YAHOO.namespace("tool"); 2477 2478 //----------------------------------------------------------------------------- 2479 // TestLogger object 2480 //----------------------------------------------------------------------------- 2481 2482 /** 2483 * Displays test execution progress and results, providing filters based on 2484 * different key events. 2485 * @namespace YAHOO.tool 2486 * @class TestLogger 2487 * @constructor 2488 * @param {HTMLElement} element (Optional) The element to create the logger in. 2489 * @param {Object} config (Optional) Configuration options for the logger. 2490 */ 2491 YAHOO.tool.TestLogger = function (element, config) { 2492 YAHOO.tool.TestLogger.superclass.constructor.call(this, element, config); 2493 this.init(); 2494 }; 2495 2496 YAHOO.lang.extend(YAHOO.tool.TestLogger, YAHOO.widget.LogReader, { 2497 2498 footerEnabled : true, 2499 newestOnTop : false, 2500 2501 /** 2502 * Formats message string to HTML for output to console. 2503 * @private 2504 * @method formatMsg 2505 * @param oLogMsg {Object} Log message object. 2506 * @return {String} HTML-formatted message for output to console. 2507 */ 2508 formatMsg : function(message /*:Object*/) { 2509 2510 var category /*:String*/ = message.category; 2511 var text /*:String*/ = this.html2Text(message.msg); 2512 2513 return "<pre><p><span class=\"" + category + "\">" + category.toUpperCase() + "</span> " + text + "</p></pre>"; 2514 2515 }, 2516 2517 //------------------------------------------------------------------------- 2518 // Private Methods 2519 //------------------------------------------------------------------------- 2520 2521 /* 2522 * Initializes the logger. 2523 * @private 2524 */ 2525 init : function () { 2526 2527 //attach to any available TestRunner 2528 if (YAHOO.tool.TestRunner){ 2529 this.setTestRunner(YAHOO.tool.TestRunner); 2530 } 2531 2532 //hide useless sources 2533 this.hideSource("global"); 2534 this.hideSource("LogReader"); 2535 2536 //hide useless message categories 2537 this.hideCategory("warn"); 2538 this.hideCategory("window"); 2539 this.hideCategory("time"); 2540 2541 //reset the logger 2542 this.clearConsole(); 2543 }, 2544 2545 /** 2546 * Clears the reference to the TestRunner from previous operations. This 2547 * unsubscribes all events and removes the object reference. 2548 * @return {Void} 2549 * @static 2550 */ 2551 clearTestRunner : function () /*:Void*/ { 2552 if (this._runner){ 2553 this._runner.unsubscribeAll(); 2554 this._runner = null; 2555 } 2556 }, 2557 2558 /** 2559 * Sets the source test runner that the logger should monitor. 2560 * @param {YAHOO.tool.TestRunner} testRunner The TestRunner to observe. 2561 * @return {Void} 2562 * @static 2563 */ 2564 setTestRunner : function (testRunner /*:YAHOO.tool.TestRunner*/) /*:Void*/ { 2565 2566 if (this._runner){ 2567 this.clearTestRunner(); 2568 } 2569 2570 this._runner = testRunner; 2571 2572 //setup event _handlers 2573 testRunner.subscribe(testRunner.TEST_PASS_EVENT, this._handleTestRunnerEvent, this, true); 2574 testRunner.subscribe(testRunner.TEST_FAIL_EVENT, this._handleTestRunnerEvent, this, true); 2575 testRunner.subscribe(testRunner.TEST_IGNORE_EVENT, this._handleTestRunnerEvent, this, true); 2576 testRunner.subscribe(testRunner.BEGIN_EVENT, this._handleTestRunnerEvent, this, true); 2577 testRunner.subscribe(testRunner.COMPLETE_EVENT, this._handleTestRunnerEvent, this, true); 2578 testRunner.subscribe(testRunner.TEST_SUITE_BEGIN_EVENT, this._handleTestRunnerEvent, this, true); 2579 testRunner.subscribe(testRunner.TEST_SUITE_COMPLETE_EVENT, this._handleTestRunnerEvent, this, true); 2580 testRunner.subscribe(testRunner.TEST_CASE_BEGIN_EVENT, this._handleTestRunnerEvent, this, true); 2581 testRunner.subscribe(testRunner.TEST_CASE_COMPLETE_EVENT, this._handleTestRunnerEvent, this, true); 2582 }, 2583 2584 //------------------------------------------------------------------------- 2585 // Event Handlers 2586 //------------------------------------------------------------------------- 2587 2588 /** 2589 * Handles all TestRunner events, outputting appropriate data into the console. 2590 * @param {Object} data The event data object. 2591 * @return {Void} 2592 * @private 2593 */ 2594 _handleTestRunnerEvent : function (data /*:Object*/) /*:Void*/ { 2595 2596 //shortcut variables 2597 var TestRunner /*:Object*/ = YAHOO.tool.TestRunner; 2598 2599 //data variables 2600 var message /*:String*/ = ""; 2601 var messageType /*:String*/ = ""; 2602 2603 switch(data.type){ 2604 case TestRunner.BEGIN_EVENT: 2605 message = "Testing began at " + (new Date()).toString() + "."; 2606 messageType = "info"; 2607 break; 2608 2609 case TestRunner.COMPLETE_EVENT: 2610 message = "Testing completed at " + (new Date()).toString() + ".\nPassed:" + 2611 data.results.passed + " Failed:" + data.results.failed + " Total:" + data.results.total; 2612 messageType = "info"; 2613 break; 2614 2615 case TestRunner.TEST_FAIL_EVENT: 2616 message = data.testName + ": " + data.error.getMessage(); 2617 messageType = "fail"; 2618 break; 2619 2620 case TestRunner.TEST_IGNORE_EVENT: 2621 message = data.testName + ": ignored."; 2622 messageType = "ignore"; 2623 break; 2624 2625 case TestRunner.TEST_PASS_EVENT: 2626 message = data.testName + ": passed."; 2627 messageType = "pass"; 2628 break; 2629 2630 case TestRunner.TEST_SUITE_BEGIN_EVENT: 2631 message = "Test suite \"" + data.testSuite.name + "\" started."; 2632 messageType = "info"; 2633 break; 2634 2635 case TestRunner.TEST_SUITE_COMPLETE_EVENT: 2636 message = "Test suite \"" + data.testSuite.name + "\" completed.\nPassed:" + 2637 data.results.passed + " Failed:" + data.results.failed + " Total:" + data.results.total; 2638 messageType = "info"; 2639 break; 2640 2641 case TestRunner.TEST_CASE_BEGIN_EVENT: 2642 message = "Test case \"" + data.testCase.name + "\" started."; 2643 messageType = "info"; 2644 break; 2645 2646 case TestRunner.TEST_CASE_COMPLETE_EVENT: 2647 message = "Test case \"" + data.testCase.name + "\" completed.\nPassed:" + 2648 data.results.passed + " Failed:" + data.results.failed + " Total:" + data.results.total; 2649 messageType = "info"; 2650 break; 2651 default: 2652 message = "Unexpected event " + data.type; 2653 message = "info"; 2654 } 2655 2656 YAHOO.log(message, messageType, "TestRunner"); 2657 } 2658 2659 }); 2660 YAHOO.namespace("tool.TestFormat"); 2661 2662 (function(){ 2663 2664 /** 2665 * Returns test results formatted as a JSON string. Requires JSON utility. 2666 * @param {Object} result The results object created by TestRunner. 2667 * @return {String} An XML-formatted string of results. 2668 * @namespace YAHOO.tool.TestFormat 2669 * @method JSON 2670 * @static 2671 */ 2672 YAHOO.tool.TestFormat.JSON = function(results) { 2673 return YAHOO.lang.JSON.stringify(results); 2674 }; 2675 2676 /* (intentionally not documented) 2677 * Simple escape function for XML attribute values. 2678 * @param {String} text The text to escape. 2679 * @return {String} The escaped text. 2680 */ 2681 function xmlEscape(text){ 2682 return text.replace(/["'<>&]/g, function(c){ 2683 switch(c){ 2684 case "<": return "<"; 2685 case ">": return ">"; 2686 case "\"": return """; 2687 case "'": return "'"; 2688 case "&": return "&"; 2689 } 2690 }); 2691 } 2692 2693 /** 2694 * Returns test results formatted as an XML string. 2695 * @param {Object} result The results object created by TestRunner. 2696 * @return {String} An XML-formatted string of results. 2697 * @namespace YAHOO.tool.TestFormat 2698 * @method XML 2699 * @static 2700 */ 2701 YAHOO.tool.TestFormat.XML = function(results) { 2702 2703 function serializeToXML(results){ 2704 var l = YAHOO.lang, 2705 xml = "<" + results.type + " name=\"" + xmlEscape(results.name) + "\""; 2706 2707 if (l.isNumber(results.duration)){ 2708 xml += " duration=\"" + results.duration + "\""; 2709 } 2710 2711 if (results.type == "test"){ 2712 xml += " result=\"" + results.result + "\" message=\"" + xmlEscape(results.message) + "\">"; 2713 } else { 2714 xml += " passed=\"" + results.passed + "\" failed=\"" + results.failed + "\" ignored=\"" + results.ignored + "\" total=\"" + results.total + "\">"; 2715 for (var prop in results) { 2716 if (l.hasOwnProperty(results, prop) && l.isObject(results[prop]) && !l.isArray(results[prop])){ 2717 xml += serializeToXML(results[prop]); 2718 } 2719 } 2720 } 2721 2722 xml += "</" + results.type + ">"; 2723 2724 return xml; 2725 } 2726 2727 return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + serializeToXML(results); 2728 2729 }; 2730 2731 2732 /** 2733 * Returns test results formatted in JUnit XML format. 2734 * @param {Object} result The results object created by TestRunner. 2735 * @return {String} An XML-formatted string of results. 2736 * @namespace YAHOO.tool.TestFormat 2737 * @method JUnitXML 2738 * @static 2739 */ 2740 YAHOO.tool.TestFormat.JUnitXML = function(results) { 2741 2742 2743 function serializeToJUnitXML(results){ 2744 var l = YAHOO.lang, 2745 xml = "", 2746 prop; 2747 2748 switch (results.type){ 2749 //equivalent to testcase in JUnit 2750 case "test": 2751 if (results.result != "ignore"){ 2752 xml = "<testcase name=\"" + xmlEscape(results.name) + "\">"; 2753 if (results.result == "fail"){ 2754 xml += "<failure message=\"" + xmlEscape(results.message) + "\"><![CDATA[" + results.message + "]]></failure>"; 2755 } 2756 xml+= "</testcase>"; 2757 } 2758 break; 2759 2760 //equivalent to testsuite in JUnit 2761 case "testcase": 2762 2763 xml = "<testsuite name=\"" + xmlEscape(results.name) + "\" tests=\"" + results.total + "\" failures=\"" + results.failed + "\">"; 2764 2765 for (prop in results) { 2766 if (l.hasOwnProperty(results, prop) && l.isObject(results[prop]) && !l.isArray(results[prop])){ 2767 xml += serializeToJUnitXML(results[prop]); 2768 } 2769 } 2770 2771 xml += "</testsuite>"; 2772 break; 2773 2774 case "testsuite": 2775 for (prop in results) { 2776 if (l.hasOwnProperty(results, prop) && l.isObject(results[prop]) && !l.isArray(results[prop])){ 2777 xml += serializeToJUnitXML(results[prop]); 2778 } 2779 } 2780 2781 //skip output - no JUnit equivalent 2782 break; 2783 2784 case "report": 2785 2786 xml = "<testsuites>"; 2787 2788 for (prop in results) { 2789 if (l.hasOwnProperty(results, prop) && l.isObject(results[prop]) && !l.isArray(results[prop])){ 2790 xml += serializeToJUnitXML(results[prop]); 2791 } 2792 } 2793 2794 xml += "</testsuites>"; 2795 2796 //no default 2797 } 2798 2799 return xml; 2800 2801 } 2802 2803 return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + serializeToJUnitXML(results); 2804 }; 2805 2806 /** 2807 * Returns test results formatted in TAP format. 2808 * For more information, see <a href="http://testanything.org/">Test Anything Protocol</a>. 2809 * @param {Object} result The results object created by TestRunner. 2810 * @return {String} A TAP-formatted string of results. 2811 * @namespace YAHOO.tool.TestFormat 2812 * @method TAP 2813 * @static 2814 */ 2815 YAHOO.tool.TestFormat.TAP = function(results) { 2816 2817 var currentTestNum = 1; 2818 2819 function serializeToTAP(results){ 2820 var l = YAHOO.lang, 2821 text = ""; 2822 2823 switch (results.type){ 2824 2825 case "test": 2826 if (results.result != "ignore"){ 2827 2828 text = "ok " + (currentTestNum++) + " - " + results.name; 2829 2830 if (results.result == "fail"){ 2831 text = "not " + text + " - " + results.message; 2832 } 2833 2834 text += "\n"; 2835 } else { 2836 text = "#Ignored test " + results.name + "\n"; 2837 } 2838 break; 2839 2840 case "testcase": 2841 2842 text = "#Begin testcase " + results.name + "(" + results.failed + " failed of " + results.total + ")\n"; 2843 2844 2845 for (prop in results) { 2846 if (l.hasOwnProperty(results, prop) && l.isObject(results[prop]) && !l.isArray(results[prop])){ 2847 text += serializeToTAP(results[prop]); 2848 } 2849 } 2850 2851 text += "#End testcase " + results.name + "\n"; 2852 2853 2854 break; 2855 2856 case "testsuite": 2857 2858 text = "#Begin testsuite " + results.name + "(" + results.failed + " failed of " + results.total + ")\n"; 2859 2860 for (prop in results) { 2861 if (l.hasOwnProperty(results, prop) && l.isObject(results[prop]) && !l.isArray(results[prop])){ 2862 text += serializeToTAP(results[prop]); 2863 } 2864 } 2865 2866 text += "#End testsuite " + results.name + "\n"; 2867 break; 2868 2869 case "report": 2870 2871 for (prop in results) { 2872 if (l.hasOwnProperty(results, prop) && l.isObject(results[prop]) && !l.isArray(results[prop])){ 2873 text += serializeToTAP(results[prop]); 2874 } 2875 } 2876 2877 //no default 2878 } 2879 2880 return text; 2881 2882 } 2883 2884 return "1.." + results.total + "\n" + serializeToTAP(results); 2885 }; 2886 2887 })(); 2888 YAHOO.namespace("tool.CoverageFormat"); 2889 2890 /** 2891 * Returns the coverage report in JSON format. This is the straight 2892 * JSON representation of the native coverage report. 2893 * @param {Object} coverage The coverage report object. 2894 * @return {String} A JSON-formatted string of coverage data. 2895 * @method JSON 2896 * @namespace YAHOO.tool.CoverageFormat 2897 */ 2898 YAHOO.tool.CoverageFormat.JSON = function(coverage){ 2899 return YAHOO.lang.JSON.stringify(coverage); 2900 }; 2901 2902 /** 2903 * Returns the coverage report in a JSON format compatible with 2904 * Xdebug. See <a href="http://www.xdebug.com/docs/code_coverage">Xdebug Documentation</a> 2905 * for more information. Note: function coverage is not available 2906 * in this format. 2907 * @param {Object} coverage The coverage report object. 2908 * @return {String} A JSON-formatted string of coverage data. 2909 * @method XdebugJSON 2910 * @namespace YAHOO.tool.CoverageFormat 2911 */ 2912 YAHOO.tool.CoverageFormat.XdebugJSON = function(coverage){ 2913 var report = {}, 2914 prop; 2915 for (prop in coverage){ 2916 if (coverage.hasOwnProperty(prop)){ 2917 report[prop] = coverage[prop].lines; 2918 } 2919 } 2920 2921 return YAHOO.lang.JSON.stringify(report); 2922 }; 2923 2924 YAHOO.namespace("tool"); 2925 2926 /** 2927 * An object capable of sending test results to a server. 2928 * @param {String} url The URL to submit the results to. 2929 * @param {Function} format (Optiona) A function that outputs the results in a specific format. 2930 * Default is YAHOO.tool.TestFormat.XML. 2931 * @constructor 2932 * @namespace YAHOO.tool 2933 * @class TestReporter 2934 */ 2935 YAHOO.tool.TestReporter = function(url /*:String*/, format /*:Function*/) { 2936 2937 /** 2938 * The URL to submit the data to. 2939 * @type String 2940 * @property url 2941 */ 2942 this.url /*:String*/ = url; 2943 2944 /** 2945 * The formatting function to call when submitting the data. 2946 * @type Function 2947 * @property format 2948 */ 2949 this.format /*:Function*/ = format || YAHOO.tool.TestFormat.XML; 2950 2951 /** 2952 * Extra fields to submit with the request. 2953 * @type Object 2954 * @property _fields 2955 * @private 2956 */ 2957 this._fields /*:Object*/ = new Object(); 2958 2959 /** 2960 * The form element used to submit the results. 2961 * @type HTMLFormElement 2962 * @property _form 2963 * @private 2964 */ 2965 this._form /*:HTMLElement*/ = null; 2966 2967 /** 2968 * Iframe used as a target for form submission. 2969 * @type HTMLIFrameElement 2970 * @property _iframe 2971 * @private 2972 */ 2973 this._iframe /*:HTMLElement*/ = null; 2974 }; 2975 2976 YAHOO.tool.TestReporter.prototype = { 2977 2978 //restore missing constructor 2979 constructor: YAHOO.tool.TestReporter, 2980 2981 /** 2982 * Convert a date into ISO format. 2983 * From Douglas Crockford's json2.js 2984 * @param {Date} date The date to convert. 2985 * @return {String} An ISO-formatted date string 2986 * @method _convertToISOString 2987 * @private 2988 */ 2989 _convertToISOString: function(date){ 2990 function f(n) { 2991 // Format integers to have at least two digits. 2992 return n < 10 ? '0' + n : n; 2993 } 2994 2995 return date.getUTCFullYear() + '-' + 2996 f(date.getUTCMonth() + 1) + '-' + 2997 f(date.getUTCDate()) + 'T' + 2998 f(date.getUTCHours()) + ':' + 2999 f(date.getUTCMinutes()) + ':' + 3000 f(date.getUTCSeconds()) + 'Z'; 3001 3002 }, 3003 3004 /** 3005 * Adds a field to the form that submits the results. 3006 * @param {String} name The name of the field. 3007 * @param {Variant} value The value of the field. 3008 * @return {Void} 3009 * @method addField 3010 */ 3011 addField : function (name /*:String*/, value /*:Variant*/) /*:Void*/{ 3012 this._fields[name] = value; 3013 }, 3014 3015 /** 3016 * Removes all previous defined fields. 3017 * @return {Void} 3018 * @method addField 3019 */ 3020 clearFields : function() /*:Void*/{ 3021 this._fields = new Object(); 3022 }, 3023 3024 /** 3025 * Cleans up the memory associated with the TestReporter, removing DOM elements 3026 * that were created. 3027 * @return {Void} 3028 * @method destroy 3029 */ 3030 destroy : function() /*:Void*/ { 3031 if (this._form){ 3032 this._form.parentNode.removeChild(this._form); 3033 this._form = null; 3034 } 3035 if (this._iframe){ 3036 this._iframe.parentNode.removeChild(this._iframe); 3037 this._iframe = null; 3038 } 3039 this._fields = null; 3040 }, 3041 3042 /** 3043 * Sends the report to the server. 3044 * @param {Object} results The results object created by TestRunner. 3045 * @return {Void} 3046 * @method report 3047 */ 3048 report : function(results /*:Object*/) /*:Void*/{ 3049 3050 //if the form hasn't been created yet, create it 3051 if (!this._form){ 3052 this._form = document.createElement("form"); 3053 this._form.method = "post"; 3054 this._form.style.visibility = "hidden"; 3055 this._form.style.position = "absolute"; 3056 this._form.style.top = 0; 3057 document.body.appendChild(this._form); 3058 3059 //IE won't let you assign a name using the DOM, must do it the hacky way 3060 if (YAHOO.env.ua.ie){ 3061 this._iframe = document.createElement("<iframe name=\"yuiTestTarget\" />"); 3062 } else { 3063 this._iframe = document.createElement("iframe"); 3064 this._iframe.name = "yuiTestTarget"; 3065 } 3066 3067 this._iframe.src = "javascript:false"; 3068 this._iframe.style.visibility = "hidden"; 3069 this._iframe.style.position = "absolute"; 3070 this._iframe.style.top = 0; 3071 document.body.appendChild(this._iframe); 3072 3073 this._form.target = "yuiTestTarget"; 3074 } 3075 3076 //set the form's action 3077 this._form.action = this.url; 3078 3079 //remove any existing fields 3080 while(this._form.hasChildNodes()){ 3081 this._form.removeChild(this._form.lastChild); 3082 } 3083 3084 //create default fields 3085 this._fields.results = this.format(results); 3086 this._fields.useragent = navigator.userAgent; 3087 this._fields.timestamp = this._convertToISOString(new Date()); 3088 3089 //add fields to the form 3090 for (var prop in this._fields){ 3091 if (YAHOO.lang.hasOwnProperty(this._fields, prop) && typeof this._fields[prop] != "function"){ 3092 if (YAHOO.env.ua.ie){ 3093 input = document.createElement("<input name=\"" + prop + "\" >"); 3094 } else { 3095 input = document.createElement("input"); 3096 input.name = prop; 3097 } 3098 input.type = "hidden"; 3099 input.value = this._fields[prop]; 3100 this._form.appendChild(input); 3101 } 3102 } 3103 3104 //remove default fields 3105 delete this._fields.results; 3106 delete this._fields.useragent; 3107 delete this._fields.timestamp; 3108 3109 if (arguments[1] !== false){ 3110 this._form.submit(); 3111 } 3112 3113 } 3114 3115 }; 3116 /*Stub for future compatibility*/ 3117 YUITest = { 3118 TestRunner: YAHOO.tool.TestRunner, 3119 ResultsFormat: YAHOO.tool.TestFormat, 3120 CoverageFormat: YAHOO.tool.CoverageFormat 3121 }; 3122 YAHOO.register("yuitest", YAHOO.tool.TestRunner, {version: "2.9.0", build: "2800"}); 3123 3124 }, '2.9.0' ,{"requires": ["yui2-skin-sam-yuitest", "yui2-yahoo", "yui2-dom", "yui2-event", "yui2-skin-sam-logger", "yui2-logger"], "optional": ["yui2-event-simulate"]});
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |