2 Copyright (c) 2011, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.com/yui/license.html
7 YAHOO.namespace("tool");
9 //-----------------------------------------------------------------------------
11 //-----------------------------------------------------------------------------
14 //used for autogenerating test case names
18 * Test case containing various tests to run.
19 * @param template An object containing any number of test methods, other methods,
20 * an optional name, and anything else the test case needs.
22 * @namespace YAHOO.tool
25 YAHOO.tool.TestCase = function (template /*:Object*/) {
28 * Special rules for the test case. Possible subobjects
29 * are fail, for tests that should fail, and error, for
30 * tests that should throw an error.
32 this._should /*:Object*/ = {};
34 //copy over all properties from the template to this object
35 for (var prop in template) {
36 this[prop] = template[prop];
39 //check for a valid name
40 if (!YAHOO.lang.isString(this.name)){
42 * Name for the test case.
44 this.name /*:String*/ = "testCase" + (tempId++);
50 YAHOO.tool.TestCase.prototype = {
53 * Resumes a paused test and runs the given function.
54 * @param {Function} segment (Optional) The function to run.
55 * If omitted, the test automatically passes.
59 resume : function (segment /*:Function*/) /*:Void*/ {
60 YAHOO.tool.TestRunner.resume(segment);
64 * Causes the test case to wait a specified amount of time and then
65 * continue executing the given code.
66 * @param {Function} segment (Optional) The function to run after the delay.
67 * If omitted, the TestRunner will wait until resume() is called.
68 * @param {int} delay (Optional) The number of milliseconds to wait before running
69 * the function. If omitted, defaults to zero.
73 wait : function (segment /*:Function*/, delay /*:int*/) /*:Void*/{
75 if (YAHOO.lang.isFunction(args[0])){
76 throw new YAHOO.tool.TestCase.Wait(args[0], args[1]);
78 throw new YAHOO.tool.TestCase.Wait(function(){
79 YAHOO.util.Assert.fail("Timeout: wait() called but resume() never called.");
80 }, (YAHOO.lang.isNumber(args[0]) ? args[0] : 10000));
84 //-------------------------------------------------------------------------
86 //-------------------------------------------------------------------------
89 * Function to run before each test is executed.
93 setUp : function () /*:Void*/ {
97 * Function to run after each test is executed.
101 tearDown: function () /*:Void*/ {
106 * Represents a stoppage in test execution to wait for an amount of time before
108 * @param {Function} segment A function to run when the wait is over.
109 * @param {int} delay The number of milliseconds to wait before running the code.
111 * @namespace YAHOO.tool.TestCase
115 YAHOO.tool.TestCase.Wait = function (segment /*:Function*/, delay /*:int*/) {
118 * The segment of code to run when the wait is over.
122 this.segment /*:Function*/ = (YAHOO.lang.isFunction(segment) ? segment : null);
125 * The delay before running the segment of code.
129 this.delay /*:int*/ = (YAHOO.lang.isNumber(delay) ? delay : 0);
134 YAHOO.namespace("tool");
137 //-----------------------------------------------------------------------------
139 //-----------------------------------------------------------------------------
142 * A test suite that can contain a collection of TestCase and TestSuite objects.
143 * @param {String||Object} data The name of the test suite or an object containing
144 * a name property as well as setUp and tearDown methods.
145 * @namespace YAHOO.tool
149 YAHOO.tool.TestSuite = function (data /*:String||Object*/) {
152 * The name of the test suite.
156 this.name /*:String*/ = "";
159 * Array of test suites and
162 this.items /*:Array*/ = [];
164 //initialize the properties
165 if (YAHOO.lang.isString(data)){
167 } else if (YAHOO.lang.isObject(data)){
168 YAHOO.lang.augmentObject(this, data, true);
172 if (this.name === ""){
173 this.name = YAHOO.util.Dom.generateId(null, "testSuite");
178 YAHOO.tool.TestSuite.prototype = {
181 * Adds a test suite or test case to the test suite.
182 * @param {YAHOO.tool.TestSuite||YAHOO.tool.TestCase} testObject The test suite or test case to add.
186 add : function (testObject /*:YAHOO.tool.TestSuite*/) /*:Void*/ {
187 if (testObject instanceof YAHOO.tool.TestSuite || testObject instanceof YAHOO.tool.TestCase) {
188 this.items.push(testObject);
192 //-------------------------------------------------------------------------
194 //-------------------------------------------------------------------------
197 * Function to run before each test is executed.
201 setUp : function () /*:Void*/ {
205 * Function to run after each test is executed.
209 tearDown: function () /*:Void*/ {
213 YAHOO.namespace("tool");
218 * @namespace YAHOO.tool
219 * @requires yahoo,dom,event,logger
220 * @optional event-simulate
224 //-----------------------------------------------------------------------------
226 //-----------------------------------------------------------------------------
229 YAHOO.tool.TestRunner = (function(){
232 * A node in the test tree structure. May represent a TestSuite, TestCase, or
234 * @param {Variant} testObject A TestSuite, TestCase, or the name of a test function.
239 function TestNode(testObject /*:Variant*/){
242 * The TestSuite, TestCase, or test function represented by this node.
244 * @property testObject
246 this.testObject = testObject;
249 * Pointer to this node's first child.
251 * @property firstChild
253 this.firstChild /*:TestNode*/ = null;
256 * Pointer to this node's last child.
258 * @property lastChild
260 this.lastChild = null;
263 * Pointer to this node's parent.
270 * Pointer to this node's next sibling.
277 * Test results for this test object.
281 this.results /*:Object*/ = {
290 if (testObject instanceof YAHOO.tool.TestSuite){
291 this.results.type = "testsuite";
292 this.results.name = testObject.name;
293 } else if (testObject instanceof YAHOO.tool.TestCase){
294 this.results.type = "testcase";
295 this.results.name = testObject.name;
300 TestNode.prototype = {
303 * Appends a new test object (TestSuite, TestCase, or test function name) as a child
305 * @param {Variant} testObject A TestSuite, TestCase, or the name of a test function.
308 appendChild : function (testObject /*:Variant*/) /*:Void*/{
309 var node = new TestNode(testObject);
310 if (this.firstChild === null){
311 this.firstChild = this.lastChild = node;
313 this.lastChild.next = node;
314 this.lastChild = node;
322 * Runs test suites and test cases, providing events to allowing for the
323 * interpretation of test results.
324 * @namespace YAHOO.tool
328 function TestRunner(){
330 //inherit from EventProvider
331 TestRunner.superclass.constructor.apply(this,arguments);
334 * Suite on which to attach all TestSuites and TestCases to be run.
335 * @type YAHOO.tool.TestSuite
336 * @property masterSuite
340 this.masterSuite = new YAHOO.tool.TestSuite("yuitests" + (new Date()).getTime());
343 * Pointer to the current node in the test tree.
352 * Pointer to the root node in the test tree.
361 * Indicates if the TestRunner is currently running tests.
367 this._running = false;
370 * Holds copy of the results object generated when all tests are
374 * @property _lastResults
377 this._lastResults = null;
380 var events /*:Array*/ = [
381 this.TEST_CASE_BEGIN_EVENT,
382 this.TEST_CASE_COMPLETE_EVENT,
383 this.TEST_SUITE_BEGIN_EVENT,
384 this.TEST_SUITE_COMPLETE_EVENT,
385 this.TEST_PASS_EVENT,
386 this.TEST_FAIL_EVENT,
387 this.TEST_IGNORE_EVENT,
391 for (var i=0; i < events.length; i++){
392 this.createEvent(events[i], { scope: this });
397 YAHOO.lang.extend(TestRunner, YAHOO.util.EventProvider, {
399 //-------------------------------------------------------------------------
401 //-------------------------------------------------------------------------
404 * Fires when a test case is opened but before the first
406 * @event testcasebegin
408 TEST_CASE_BEGIN_EVENT /*:String*/ : "testcasebegin",
411 * Fires when all tests in a test case have been executed.
412 * @event testcasecomplete
414 TEST_CASE_COMPLETE_EVENT /*:String*/ : "testcasecomplete",
417 * Fires when a test suite is opened but before the first
419 * @event testsuitebegin
421 TEST_SUITE_BEGIN_EVENT /*:String*/ : "testsuitebegin",
424 * Fires when all test cases in a test suite have been
426 * @event testsuitecomplete
428 TEST_SUITE_COMPLETE_EVENT /*:String*/ : "testsuitecomplete",
431 * Fires when a test has passed.
434 TEST_PASS_EVENT /*:String*/ : "pass",
437 * Fires when a test has failed.
440 TEST_FAIL_EVENT /*:String*/ : "fail",
443 * Fires when a test has been ignored.
446 TEST_IGNORE_EVENT /*:String*/ : "ignore",
449 * Fires when all test suites and test cases have been completed.
452 COMPLETE_EVENT /*:String*/ : "complete",
455 * Fires when the run() method is called.
458 BEGIN_EVENT /*:String*/ : "begin",
460 //-------------------------------------------------------------------------
462 //-------------------------------------------------------------------------
465 * Retrieves the name of the current result set.
466 * @return {String} The name of the result set.
470 return this.masterSuite.name;
474 * The name assigned to the master suite of the TestRunner. This is the name
475 * that is output as the root's name when results are retrieved.
476 * @param {String} name The name of the result set.
480 setName: function(name){
481 this.masterSuite.name = name;
485 //-------------------------------------------------------------------------
486 // State-Related Methods
487 //-------------------------------------------------------------------------
490 * Indicates that the TestRunner is busy running tests and therefore can't
491 * be stopped and results cannot be gathered.
492 * @return {Boolean} True if the TestRunner is running, false if not.
495 isRunning: function(){
496 return this._running;
500 * Returns the last complete results set from the TestRunner. Null is returned
501 * if the TestRunner is running or no tests have been run.
502 * @param {Function} format (Optional) A test format to return the results in.
503 * @return {Object|String} Either the results object or, if a test format is
504 * passed as the argument, a string representing the results in a specific
508 getResults: function(format){
509 if (!this._running && this._lastResults){
510 if (YAHOO.lang.isFunction(format)){
511 return format(this._lastResults);
513 return this._lastResults;
521 * Returns the coverage report for the files that have been executed.
522 * This returns only coverage information for files that have been
523 * instrumented using YUI Test Coverage and only those that were run
525 * @param {Function} format (Optional) A coverage format to return results in.
526 * @return {Object|String} Either the coverage object or, if a coverage
527 * format is specified, a string representing the results in that format.
528 * @method getCoverage
530 getCoverage: function(format){
531 if (!this._running && typeof _yuitest_coverage == "object"){
532 if (YAHOO.lang.isFunction(format)){
533 return format(_yuitest_coverage);
535 return _yuitest_coverage;
542 //-------------------------------------------------------------------------
544 //-------------------------------------------------------------------------
547 * Retrieves the name of the current result set.
548 * @return {String} The name of the result set.
552 return this.masterSuite.name;
556 * The name assigned to the master suite of the TestRunner. This is the name
557 * that is output as the root's name when results are retrieved.
558 * @param {String} name The name of the result set.
562 setName: function(name){
563 this.masterSuite.name = name;
566 //-------------------------------------------------------------------------
567 // Test Tree-Related Methods
568 //-------------------------------------------------------------------------
571 * Adds a test case to the test tree as a child of the specified node.
572 * @param {TestNode} parentNode The node to add the test case to as a child.
573 * @param {YAHOO.tool.TestCase} testCase The test case to add.
577 * @method _addTestCaseToTestTree
579 _addTestCaseToTestTree : function (parentNode /*:TestNode*/, testCase /*:YAHOO.tool.TestCase*/) /*:Void*/{
582 var node = parentNode.appendChild(testCase);
584 //iterate over the items in the test case
585 for (var prop in testCase){
586 if (prop.indexOf("test") === 0 && YAHOO.lang.isFunction(testCase[prop])){
587 node.appendChild(prop);
594 * Adds a test suite to the test tree as a child of the specified node.
595 * @param {TestNode} parentNode The node to add the test suite to as a child.
596 * @param {YAHOO.tool.TestSuite} testSuite The test suite to add.
600 * @method _addTestSuiteToTestTree
602 _addTestSuiteToTestTree : function (parentNode /*:TestNode*/, testSuite /*:YAHOO.tool.TestSuite*/) /*:Void*/ {
605 var node = parentNode.appendChild(testSuite);
607 //iterate over the items in the master suite
608 for (var i=0; i < testSuite.items.length; i++){
609 if (testSuite.items[i] instanceof YAHOO.tool.TestSuite) {
610 this._addTestSuiteToTestTree(node, testSuite.items[i]);
611 } else if (testSuite.items[i] instanceof YAHOO.tool.TestCase) {
612 this._addTestCaseToTestTree(node, testSuite.items[i]);
618 * Builds the test tree based on items in the master suite. The tree is a hierarchical
619 * representation of the test suites, test cases, and test functions. The resulting tree
620 * is stored in _root and the pointer _cur is set to the root initially.
624 * @method _buildTestTree
626 _buildTestTree : function () /*:Void*/ {
628 this._root = new TestNode(this.masterSuite);
629 //this._cur = this._root;
631 //iterate over the items in the master suite
632 for (var i=0; i < this.masterSuite.items.length; i++){
633 if (this.masterSuite.items[i] instanceof YAHOO.tool.TestSuite) {
634 this._addTestSuiteToTestTree(this._root, this.masterSuite.items[i]);
635 } else if (this.masterSuite.items[i] instanceof YAHOO.tool.TestCase) {
636 this._addTestCaseToTestTree(this._root, this.masterSuite.items[i]);
642 //-------------------------------------------------------------------------
644 //-------------------------------------------------------------------------
647 * Handles the completion of a test object's tests. Tallies test results
648 * from one level up to the next.
649 * @param {TestNode} node The TestNode representing the test object.
651 * @method _handleTestObjectComplete
655 _handleTestObjectComplete : function (node /*:TestNode*/) /*:Void*/ {
656 if (YAHOO.lang.isObject(node.testObject)){
657 node.parent.results.passed += node.results.passed;
658 node.parent.results.failed += node.results.failed;
659 node.parent.results.total += node.results.total;
660 node.parent.results.ignored += node.results.ignored;
661 node.parent.results[node.testObject.name] = node.results;
663 if (node.testObject instanceof YAHOO.tool.TestSuite){
664 node.testObject.tearDown();
665 node.results.duration = (new Date()) - node._start;
666 this.fireEvent(this.TEST_SUITE_COMPLETE_EVENT, { testSuite: node.testObject, results: node.results});
667 } else if (node.testObject instanceof YAHOO.tool.TestCase){
668 node.results.duration = (new Date()) - node._start;
669 this.fireEvent(this.TEST_CASE_COMPLETE_EVENT, { testCase: node.testObject, results: node.results});
674 //-------------------------------------------------------------------------
675 // Navigation Methods
676 //-------------------------------------------------------------------------
679 * Retrieves the next node in the test tree.
680 * @return {TestNode} The next node in the test tree or null if the end is reached.
685 _next : function () /*:TestNode*/ {
687 if (this._cur === null){
688 this._cur = this._root;
689 } else if (this._cur.firstChild) {
690 this._cur = this._cur.firstChild;
691 } else if (this._cur.next) {
692 this._cur = this._cur.next;
694 while (this._cur && !this._cur.next && this._cur !== this._root){
695 this._handleTestObjectComplete(this._cur);
696 this._cur = this._cur.parent;
699 if (this._cur == this._root){
700 this._cur.results.type = "report";
701 this._cur.results.timestamp = (new Date()).toLocaleString();
702 this._cur.results.duration = (new Date()) - this._cur._start;
703 this._lastResults = this._cur.results;
704 this._running = false;
705 this.fireEvent(this.COMPLETE_EVENT, { results: this._lastResults});
708 this._handleTestObjectComplete(this._cur);
709 this._cur = this._cur.next;
717 * Runs a test case or test suite, returning the results.
718 * @param {YAHOO.tool.TestCase|YAHOO.tool.TestSuite} testObject The test case or test suite to run.
719 * @return {Object} Results of the execution with properties passed, failed, and total.
724 _run : function () /*:Void*/ {
726 //flag to indicate if the TestRunner should wait before continuing
727 var shouldWait = false;
729 //get the next test node
730 var node = this._next();
735 //set flag to say the testrunner is running
736 this._running = true;
738 //eliminate last results
739 this._lastResult = null;
741 var testObject = node.testObject;
743 //figure out what to do
744 if (YAHOO.lang.isObject(testObject)){
745 if (testObject instanceof YAHOO.tool.TestSuite){
746 this.fireEvent(this.TEST_SUITE_BEGIN_EVENT, { testSuite: testObject });
747 node._start = new Date();
749 } else if (testObject instanceof YAHOO.tool.TestCase){
750 this.fireEvent(this.TEST_CASE_BEGIN_EVENT, { testCase: testObject });
751 node._start = new Date();
754 //some environments don't support setTimeout
755 if (typeof setTimeout != "undefined"){
756 setTimeout(function(){
757 YAHOO.tool.TestRunner._run();
769 _resumeTest : function (segment /*:Function*/) /*:Void*/ {
771 //get relevant information
772 var node /*:TestNode*/ = this._cur;
773 var testName /*:String*/ = node.testObject;
774 var testCase /*:YAHOO.tool.TestCase*/ = node.parent.testObject;
776 //cancel other waits if available
777 if (testCase.__yui_wait){
778 clearTimeout(testCase.__yui_wait);
779 delete testCase.__yui_wait;
782 //get the "should" test cases
783 var shouldFail /*:Object*/ = (testCase._should.fail || {})[testName];
784 var shouldError /*:Object*/ = (testCase._should.error || {})[testName];
786 //variable to hold whether or not the test failed
787 var failed /*:Boolean*/ = false;
788 var error /*:Error*/ = null;
794 segment.apply(testCase);
796 //if it should fail, and it got here, then it's a fail because it didn't
798 error = new YAHOO.util.ShouldFail();
800 } else if (shouldError){
801 error = new YAHOO.util.ShouldError();
805 } catch (thrown /*:Error*/){
806 if (thrown instanceof YAHOO.util.AssertionError) {
811 } else if (thrown instanceof YAHOO.tool.TestCase.Wait){
813 if (YAHOO.lang.isFunction(thrown.segment)){
814 if (YAHOO.lang.isNumber(thrown.delay)){
816 //some environments don't support setTimeout
817 if (typeof setTimeout != "undefined"){
818 testCase.__yui_wait = setTimeout(function(){
819 YAHOO.tool.TestRunner._resumeTest(thrown.segment);
822 throw new Error("Asynchronous tests not supported in this environment.");
830 //first check to see if it should error
832 error = new YAHOO.util.UnexpectedError(thrown);
835 //check to see what type of data we have
836 if (YAHOO.lang.isString(shouldError)){
838 //if it's a string, check the error message
839 if (thrown.message != shouldError){
840 error = new YAHOO.util.UnexpectedError(thrown);
843 } else if (YAHOO.lang.isFunction(shouldError)){
845 //if it's a function, see if the error is an instance of it
846 if (!(thrown instanceof shouldError)){
847 error = new YAHOO.util.UnexpectedError(thrown);
851 } else if (YAHOO.lang.isObject(shouldError)){
853 //if it's an object, check the instance and message
854 if (!(thrown instanceof shouldError.constructor) ||
855 thrown.message != shouldError.message){
856 error = new YAHOO.util.UnexpectedError(thrown);
867 //fireEvent appropriate event
869 this.fireEvent(this.TEST_FAIL_EVENT, { testCase: testCase, testName: testName, error: error });
871 this.fireEvent(this.TEST_PASS_EVENT, { testCase: testCase, testName: testName });
878 var duration = (new Date()) - node._start;
881 node.parent.results[testName] = {
882 result: failed ? "fail" : "pass",
883 message: error ? error.getMessage() : "Test passed",
890 node.parent.results.failed++;
892 node.parent.results.passed++;
894 node.parent.results.total++;
896 //set timeout not supported in all environments
897 if (typeof setTimeout != "undefined"){
898 setTimeout(function(){
899 YAHOO.tool.TestRunner._run();
908 * Runs a single test based on the data provided in the node.
909 * @param {TestNode} node The TestNode representing the test to run.
915 _runTest : function (node /*:TestNode*/) /*:Void*/ {
917 //get relevant information
918 var testName /*:String*/ = node.testObject;
919 var testCase /*:YAHOO.tool.TestCase*/ = node.parent.testObject;
920 var test /*:Function*/ = testCase[testName];
922 //get the "should" test cases
923 var shouldIgnore /*:Object*/ = (testCase._should.ignore || {})[testName];
925 //figure out if the test should be ignored or not
929 node.parent.results[testName] = {
931 message: "Test ignored",
936 node.parent.results.ignored++;
937 node.parent.results.total++;
939 this.fireEvent(this.TEST_IGNORE_EVENT, { testCase: testCase, testName: testName });
941 //some environments don't support setTimeout
942 if (typeof setTimeout != "undefined"){
943 setTimeout(function(){
944 YAHOO.tool.TestRunner._run();
952 //mark the start time
953 node._start = new Date();
958 //now call the body of the test
959 this._resumeTest(test);
964 //-------------------------------------------------------------------------
966 //-------------------------------------------------------------------------
969 * Fires events for the TestRunner. This overrides the default fireEvent()
970 * method from EventProvider to add the type property to the data that is
971 * passed through on each event call.
972 * @param {String} type The type of event to fire.
973 * @param {Object} data (Optional) Data for the event.
978 fireEvent : function (type /*:String*/, data /*:Object*/) /*:Void*/ {
981 TestRunner.superclass.fireEvent.call(this, type, data);
984 //-------------------------------------------------------------------------
986 //-------------------------------------------------------------------------
989 * Adds a test suite or test case to the list of test objects to run.
990 * @param testObject Either a TestCase or a TestSuite that should be run.
995 add : function (testObject /*:Object*/) /*:Void*/ {
996 this.masterSuite.add(testObject);
1000 * Removes all test objects from the runner.
1005 clear : function () /*:Void*/ {
1006 this.masterSuite = new YAHOO.tool.TestSuite("yuitests" + (new Date()).getTime());
1010 * Resumes the TestRunner after wait() was called.
1011 * @param {Function} segment The function to run as the rest
1012 * of the haulted test.
1017 resume : function (segment /*:Function*/) /*:Void*/ {
1018 this._resumeTest(segment || function(){});
1022 * Runs the test suite.
1023 * @param {Boolean} oldMode (Optional) Specifies that the <= 2.8 way of
1024 * internally managing test suites should be used.
1029 run : function (oldMode) {
1031 //pointer to runner to avoid scope issues
1032 var runner = YAHOO.tool.TestRunner;
1034 //if there's only one suite on the masterSuite, move it up
1035 if (!oldMode && this.masterSuite.items.length == 1 && this.masterSuite.items[0] instanceof YAHOO.tool.TestSuite){
1036 this.masterSuite = this.masterSuite.items[0];
1039 //build the test tree
1040 runner._buildTestTree();
1042 //set when the test started
1043 runner._root._start = new Date();
1045 //fire the begin event
1046 runner.fireEvent(runner.BEGIN_EVENT);
1053 return new TestRunner();
1056 YAHOO.namespace("util");
1058 //-----------------------------------------------------------------------------
1060 //-----------------------------------------------------------------------------
1063 * The Assert object provides functions to test JavaScript values against
1064 * known and expected results. Whenever a comparison (assertion) fails,
1065 * an error is thrown.
1067 * @namespace YAHOO.util
1071 YAHOO.util.Assert = {
1073 //-------------------------------------------------------------------------
1075 //-------------------------------------------------------------------------
1078 * Formats a message so that it can contain the original assertion message
1079 * in addition to the custom message.
1080 * @param {String} customMessage The message passed in by the developer.
1081 * @param {String} defaultMessage The message created by the error by default.
1082 * @return {String} The final error message, containing either or both.
1085 * @method _formatMessage
1087 _formatMessage : function (customMessage /*:String*/, defaultMessage /*:String*/) /*:String*/ {
1088 var message = customMessage;
1089 if (YAHOO.lang.isString(customMessage) && customMessage.length > 0){
1090 return YAHOO.lang.substitute(customMessage, { message: defaultMessage });
1092 return defaultMessage;
1096 //-------------------------------------------------------------------------
1097 // Generic Assertion Methods
1098 //-------------------------------------------------------------------------
1101 * Forces an assertion error to occur.
1102 * @param {String} message (Optional) The message to display with the failure.
1106 fail : function (message /*:String*/) /*:Void*/ {
1107 throw new YAHOO.util.AssertionError(this._formatMessage(message, "Test force-failed."));
1110 //-------------------------------------------------------------------------
1111 // Equality Assertion Methods
1112 //-------------------------------------------------------------------------
1115 * Asserts that a value is equal to another. This uses the double equals sign
1116 * so type coercion may occur.
1117 * @param {Object} expected The expected value.
1118 * @param {Object} actual The actual value to test.
1119 * @param {String} message (Optional) The message to display if the assertion fails.
1123 areEqual : function (expected /*:Object*/, actual /*:Object*/, message /*:String*/) /*:Void*/ {
1124 if (expected != actual) {
1125 throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Values should be equal."), expected, actual);
1130 * Asserts that a value is not equal to another. This uses the double equals sign
1131 * so type coercion may occur.
1132 * @param {Object} unexpected The unexpected value.
1133 * @param {Object} actual The actual value to test.
1134 * @param {String} message (Optional) The message to display if the assertion fails.
1135 * @method areNotEqual
1138 areNotEqual : function (unexpected /*:Object*/, actual /*:Object*/,
1139 message /*:String*/) /*:Void*/ {
1140 if (unexpected == actual) {
1141 throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Values should not be equal."), unexpected);
1146 * Asserts that a value is not the same as another. This uses the triple equals sign
1147 * so no type coercion may occur.
1148 * @param {Object} unexpected The unexpected value.
1149 * @param {Object} actual The actual value to test.
1150 * @param {String} message (Optional) The message to display if the assertion fails.
1151 * @method areNotSame
1154 areNotSame : function (unexpected /*:Object*/, actual /*:Object*/, message /*:String*/) /*:Void*/ {
1155 if (unexpected === actual) {
1156 throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Values should not be the same."), unexpected);
1161 * Asserts that a value is the same as another. This uses the triple equals sign
1162 * so no type coercion may occur.
1163 * @param {Object} expected The expected value.
1164 * @param {Object} actual The actual value to test.
1165 * @param {String} message (Optional) The message to display if the assertion fails.
1169 areSame : function (expected /*:Object*/, actual /*:Object*/, message /*:String*/) /*:Void*/ {
1170 if (expected !== actual) {
1171 throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Values should be the same."), expected, actual);
1175 //-------------------------------------------------------------------------
1176 // Boolean Assertion Methods
1177 //-------------------------------------------------------------------------
1180 * Asserts that a value is false. This uses the triple equals sign
1181 * so no type coercion may occur.
1182 * @param {Object} actual The actual value to test.
1183 * @param {String} message (Optional) The message to display if the assertion fails.
1187 isFalse : function (actual /*:Boolean*/, message /*:String*/) {
1188 if (false !== actual) {
1189 throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value should be false."), false, actual);
1194 * Asserts that a value is true. This uses the triple equals sign
1195 * so no type coercion may occur.
1196 * @param {Object} actual The actual value to test.
1197 * @param {String} message (Optional) The message to display if the assertion fails.
1201 isTrue : function (actual /*:Boolean*/, message /*:String*/) /*:Void*/ {
1202 if (true !== actual) {
1203 throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value should be true."), true, actual);
1208 //-------------------------------------------------------------------------
1209 // Special Value Assertion Methods
1210 //-------------------------------------------------------------------------
1213 * Asserts that a value is not a number.
1214 * @param {Object} actual The value to test.
1215 * @param {String} message (Optional) The message to display if the assertion fails.
1219 isNaN : function (actual /*:Object*/, message /*:String*/) /*:Void*/{
1220 if (!isNaN(actual)){
1221 throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value should be NaN."), NaN, actual);
1226 * Asserts that a value is not the special NaN value.
1227 * @param {Object} actual The value to test.
1228 * @param {String} message (Optional) The message to display if the assertion fails.
1232 isNotNaN : function (actual /*:Object*/, message /*:String*/) /*:Void*/{
1234 throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Values should not be NaN."), NaN);
1239 * Asserts that a value is not null. This uses the triple equals sign
1240 * so no type coercion may occur.
1241 * @param {Object} actual The actual value to test.
1242 * @param {String} message (Optional) The message to display if the assertion fails.
1246 isNotNull : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
1247 if (YAHOO.lang.isNull(actual)) {
1248 throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Values should not be null."), null);
1253 * Asserts that a value is not undefined. This uses the triple equals sign
1254 * so no type coercion may occur.
1255 * @param {Object} actual The actual value to test.
1256 * @param {String} message (Optional) The message to display if the assertion fails.
1257 * @method isNotUndefined
1260 isNotUndefined : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
1261 if (YAHOO.lang.isUndefined(actual)) {
1262 throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should not be undefined."), undefined);
1267 * Asserts that a value is null. This uses the triple equals sign
1268 * so no type coercion may occur.
1269 * @param {Object} actual The actual value to test.
1270 * @param {String} message (Optional) The message to display if the assertion fails.
1274 isNull : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
1275 if (!YAHOO.lang.isNull(actual)) {
1276 throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value should be null."), null, actual);
1281 * Asserts that a value is undefined. This uses the triple equals sign
1282 * so no type coercion may occur.
1283 * @param {Object} actual The actual value to test.
1284 * @param {String} message (Optional) The message to display if the assertion fails.
1285 * @method isUndefined
1288 isUndefined : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
1289 if (!YAHOO.lang.isUndefined(actual)) {
1290 throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value should be undefined."), undefined, actual);
1294 //--------------------------------------------------------------------------
1295 // Instance Assertion Methods
1296 //--------------------------------------------------------------------------
1299 * Asserts that a value is an array.
1300 * @param {Object} actual The value to test.
1301 * @param {String} message (Optional) The message to display if the assertion fails.
1305 isArray : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
1306 if (!YAHOO.lang.isArray(actual)){
1307 throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should be an array."), actual);
1312 * Asserts that a value is a Boolean.
1313 * @param {Object} actual The value to test.
1314 * @param {String} message (Optional) The message to display if the assertion fails.
1318 isBoolean : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
1319 if (!YAHOO.lang.isBoolean(actual)){
1320 throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should be a Boolean."), actual);
1325 * Asserts that a value is a function.
1326 * @param {Object} actual The value to test.
1327 * @param {String} message (Optional) The message to display if the assertion fails.
1328 * @method isFunction
1331 isFunction : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
1332 if (!YAHOO.lang.isFunction(actual)){
1333 throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should be a function."), actual);
1338 * Asserts that a value is an instance of a particular object. This may return
1339 * incorrect results when comparing objects from one frame to constructors in
1340 * another frame. For best results, don't use in a cross-frame manner.
1341 * @param {Function} expected The function that the object should be an instance of.
1342 * @param {Object} actual The object to test.
1343 * @param {String} message (Optional) The message to display if the assertion fails.
1344 * @method isInstanceOf
1347 isInstanceOf : function (expected /*:Function*/, actual /*:Object*/, message /*:String*/) /*:Void*/ {
1348 if (!(actual instanceof expected)){
1349 throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value isn't an instance of expected type."), expected, actual);
1354 * Asserts that a value is a number.
1355 * @param {Object} actual The value to test.
1356 * @param {String} message (Optional) The message to display if the assertion fails.
1360 isNumber : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
1361 if (!YAHOO.lang.isNumber(actual)){
1362 throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should be a number."), actual);
1367 * Asserts that a value is an object.
1368 * @param {Object} actual The value to test.
1369 * @param {String} message (Optional) The message to display if the assertion fails.
1373 isObject : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
1374 if (!YAHOO.lang.isObject(actual)){
1375 throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should be an object."), actual);
1380 * Asserts that a value is a string.
1381 * @param {Object} actual The value to test.
1382 * @param {String} message (Optional) The message to display if the assertion fails.
1386 isString : function (actual /*:Object*/, message /*:String*/) /*:Void*/ {
1387 if (!YAHOO.lang.isString(actual)){
1388 throw new YAHOO.util.UnexpectedValue(this._formatMessage(message, "Value should be a string."), actual);
1393 * Asserts that a value is of a particular type.
1394 * @param {String} expectedType The expected type of the variable.
1395 * @param {Object} actualValue The actual value to test.
1396 * @param {String} message (Optional) The message to display if the assertion fails.
1400 isTypeOf : function (expected /*:String*/, actual /*:Object*/, message /*:String*/) /*:Void*/{
1401 if (typeof actual != expected){
1402 throw new YAHOO.util.ComparisonFailure(this._formatMessage(message, "Value should be of type " + expected + "."), expected, typeof actual);
1407 //-----------------------------------------------------------------------------
1409 //-----------------------------------------------------------------------------
1412 * AssertionError is thrown whenever an assertion fails. It provides methods
1413 * to more easily get at error information and also provides a base class
1414 * from which more specific assertion errors can be derived.
1416 * @param {String} message The message to display when the error occurs.
1417 * @namespace YAHOO.util
1418 * @class AssertionError
1422 YAHOO.util.AssertionError = function (message /*:String*/){
1425 //arguments.callee.superclass.constructor.call(this, message);
1428 * Error message. Must be duplicated to ensure browser receives it.
1432 this.message /*:String*/ = message;
1435 * The name of the error that occurred.
1439 this.name /*:String*/ = "AssertionError";
1443 YAHOO.lang.extend(YAHOO.util.AssertionError, Object, {
1446 * Returns a fully formatted error for an assertion failure. This should
1447 * be overridden by all subclasses to provide specific information.
1448 * @method getMessage
1449 * @return {String} A string describing the error.
1451 getMessage : function () /*:String*/ {
1452 return this.message;
1456 * Returns a string representation of the error.
1458 * @return {String} A string representation of the error.
1460 toString : function () /*:String*/ {
1461 return this.name + ": " + this.getMessage();
1467 * ComparisonFailure is subclass of AssertionError that is thrown whenever
1468 * a comparison between two values fails. It provides mechanisms to retrieve
1469 * both the expected and actual value.
1471 * @param {String} message The message to display when the error occurs.
1472 * @param {Object} expected The expected value.
1473 * @param {Object} actual The actual value that caused the assertion to fail.
1474 * @namespace YAHOO.util
1475 * @extends YAHOO.util.AssertionError
1476 * @class ComparisonFailure
1479 YAHOO.util.ComparisonFailure = function (message /*:String*/, expected /*:Object*/, actual /*:Object*/){
1482 YAHOO.util.AssertionError.call(this, message);
1485 * The expected value.
1487 * @property expected
1489 this.expected /*:Object*/ = expected;
1496 this.actual /*:Object*/ = actual;
1499 * The name of the error that occurred.
1503 this.name /*:String*/ = "ComparisonFailure";
1508 YAHOO.lang.extend(YAHOO.util.ComparisonFailure, YAHOO.util.AssertionError, {
1511 * Returns a fully formatted error for an assertion failure. This message
1512 * provides information about the expected and actual values.
1514 * @return {String} A string describing the error.
1516 getMessage : function () /*:String*/ {
1517 return this.message + "\nExpected: " + this.expected + " (" + (typeof this.expected) + ")" +
1518 "\nActual:" + this.actual + " (" + (typeof this.actual) + ")";
1524 * UnexpectedValue is subclass of AssertionError that is thrown whenever
1525 * a value was unexpected in its scope. This typically means that a test
1526 * was performed to determine that a value was *not* equal to a certain
1529 * @param {String} message The message to display when the error occurs.
1530 * @param {Object} unexpected The unexpected value.
1531 * @namespace YAHOO.util
1532 * @extends YAHOO.util.AssertionError
1533 * @class UnexpectedValue
1536 YAHOO.util.UnexpectedValue = function (message /*:String*/, unexpected /*:Object*/){
1539 YAHOO.util.AssertionError.call(this, message);
1542 * The unexpected value.
1544 * @property unexpected
1546 this.unexpected /*:Object*/ = unexpected;
1549 * The name of the error that occurred.
1553 this.name /*:String*/ = "UnexpectedValue";
1558 YAHOO.lang.extend(YAHOO.util.UnexpectedValue, YAHOO.util.AssertionError, {
1561 * Returns a fully formatted error for an assertion failure. The message
1562 * contains information about the unexpected value that was encountered.
1563 * @method getMessage
1564 * @return {String} A string describing the error.
1566 getMessage : function () /*:String*/ {
1567 return this.message + "\nUnexpected: " + this.unexpected + " (" + (typeof this.unexpected) + ") ";
1573 * ShouldFail is subclass of AssertionError that is thrown whenever
1574 * a test was expected to fail but did not.
1576 * @param {String} message The message to display when the error occurs.
1577 * @namespace YAHOO.util
1578 * @extends YAHOO.util.AssertionError
1582 YAHOO.util.ShouldFail = function (message /*:String*/){
1585 YAHOO.util.AssertionError.call(this, message || "This test should fail but didn't.");
1588 * The name of the error that occurred.
1592 this.name /*:String*/ = "ShouldFail";
1597 YAHOO.lang.extend(YAHOO.util.ShouldFail, YAHOO.util.AssertionError);
1600 * ShouldError is subclass of AssertionError that is thrown whenever
1601 * a test is expected to throw an error but doesn't.
1603 * @param {String} message The message to display when the error occurs.
1604 * @namespace YAHOO.util
1605 * @extends YAHOO.util.AssertionError
1606 * @class ShouldError
1609 YAHOO.util.ShouldError = function (message /*:String*/){
1612 YAHOO.util.AssertionError.call(this, message || "This test should have thrown an error but didn't.");
1615 * The name of the error that occurred.
1619 this.name /*:String*/ = "ShouldError";
1624 YAHOO.lang.extend(YAHOO.util.ShouldError, YAHOO.util.AssertionError);
1627 * UnexpectedError is subclass of AssertionError that is thrown whenever
1628 * an error occurs within the course of a test and the test was not expected
1629 * to throw an error.
1631 * @param {Error} cause The unexpected error that caused this error to be
1633 * @namespace YAHOO.util
1634 * @extends YAHOO.util.AssertionError
1635 * @class UnexpectedError
1638 YAHOO.util.UnexpectedError = function (cause /*:Object*/){
1641 YAHOO.util.AssertionError.call(this, "Unexpected error: " + cause.message);
1644 * The unexpected error that occurred.
1648 this.cause /*:Error*/ = cause;
1651 * The name of the error that occurred.
1655 this.name /*:String*/ = "UnexpectedError";
1658 * Stack information for the error (if provided).
1662 this.stack /*:String*/ = cause.stack;
1667 YAHOO.lang.extend(YAHOO.util.UnexpectedError, YAHOO.util.AssertionError);
1668 //-----------------------------------------------------------------------------
1669 // ArrayAssert object
1670 //-----------------------------------------------------------------------------
1673 * The ArrayAssert object provides functions to test JavaScript array objects
1674 * for a variety of cases.
1676 * @namespace YAHOO.util
1677 * @class ArrayAssert
1681 YAHOO.util.ArrayAssert = {
1684 * Asserts that a value is present in an array. This uses the triple equals
1685 * sign so no type coercion may occur.
1686 * @param {Object} needle The value that is expected in the array.
1687 * @param {Array} haystack An array of values.
1688 * @param {String} message (Optional) The message to display if the assertion fails.
1692 contains : function (needle /*:Object*/, haystack /*:Array*/,
1693 message /*:String*/) /*:Void*/ {
1695 var found /*:Boolean*/ = false;
1696 var Assert = YAHOO.util.Assert;
1698 //begin checking values
1699 for (var i=0; i < haystack.length && !found; i++){
1700 if (haystack[i] === needle) {
1706 Assert.fail(Assert._formatMessage(message, "Value " + needle + " (" + (typeof needle) + ") not found in array [" + haystack + "]."));
1711 * Asserts that a set of values are present in an array. This uses the triple equals
1712 * sign so no type coercion may occur. For this assertion to pass, all values must
1714 * @param {Object[]} needles An array of values that are expected in the array.
1715 * @param {Array} haystack An array of values to check.
1716 * @param {String} message (Optional) The message to display if the assertion fails.
1717 * @method containsItems
1720 containsItems : function (needles /*:Object[]*/, haystack /*:Array*/,
1721 message /*:String*/) /*:Void*/ {
1723 //begin checking values
1724 for (var i=0; i < needles.length; i++){
1725 this.contains(needles[i], haystack, message);
1730 * Asserts that a value matching some condition is present in an array. This uses
1731 * a function to determine a match.
1732 * @param {Function} matcher A function that returns true if the items matches or false if not.
1733 * @param {Array} haystack An array of values.
1734 * @param {String} message (Optional) The message to display if the assertion fails.
1735 * @method containsMatch
1738 containsMatch : function (matcher /*:Function*/, haystack /*:Array*/,
1739 message /*:String*/) /*:Void*/ {
1741 //check for valid matcher
1742 if (typeof matcher != "function"){
1743 throw new TypeError("ArrayAssert.containsMatch(): First argument must be a function.");
1746 var found /*:Boolean*/ = false;
1747 var Assert = YAHOO.util.Assert;
1749 //begin checking values
1750 for (var i=0; i < haystack.length && !found; i++){
1751 if (matcher(haystack[i])) {
1757 Assert.fail(Assert._formatMessage(message, "No match found in array [" + haystack + "]."));
1762 * Asserts that a value is not present in an array. This uses the triple equals
1763 * sign so no type coercion may occur.
1764 * @param {Object} needle The value that is expected in the array.
1765 * @param {Array} haystack An array of values.
1766 * @param {String} message (Optional) The message to display if the assertion fails.
1767 * @method doesNotContain
1770 doesNotContain : function (needle /*:Object*/, haystack /*:Array*/,
1771 message /*:String*/) /*:Void*/ {
1773 var found /*:Boolean*/ = false;
1774 var Assert = YAHOO.util.Assert;
1776 //begin checking values
1777 for (var i=0; i < haystack.length && !found; i++){
1778 if (haystack[i] === needle) {
1784 Assert.fail(Assert._formatMessage(message, "Value found in array [" + haystack + "]."));
1789 * Asserts that a set of values are not present in an array. This uses the triple equals
1790 * sign so no type coercion may occur. For this assertion to pass, all values must
1792 * @param {Object[]} needles An array of values that are not expected in the array.
1793 * @param {Array} haystack An array of values to check.
1794 * @param {String} message (Optional) The message to display if the assertion fails.
1795 * @method doesNotContainItems
1798 doesNotContainItems : function (needles /*:Object[]*/, haystack /*:Array*/,
1799 message /*:String*/) /*:Void*/ {
1801 for (var i=0; i < needles.length; i++){
1802 this.doesNotContain(needles[i], haystack, message);
1808 * Asserts that no values matching a condition are present in an array. This uses
1809 * a function to determine a match.
1810 * @param {Function} matcher A function that returns true if the items matches or false if not.
1811 * @param {Array} haystack An array of values.
1812 * @param {String} message (Optional) The message to display if the assertion fails.
1813 * @method doesNotContainMatch
1816 doesNotContainMatch : function (matcher /*:Function*/, haystack /*:Array*/,
1817 message /*:String*/) /*:Void*/ {
1819 //check for valid matcher
1820 if (typeof matcher != "function"){
1821 throw new TypeError("ArrayAssert.doesNotContainMatch(): First argument must be a function.");
1824 var found /*:Boolean*/ = false;
1825 var Assert = YAHOO.util.Assert;
1827 //begin checking values
1828 for (var i=0; i < haystack.length && !found; i++){
1829 if (matcher(haystack[i])) {
1835 Assert.fail(Assert._formatMessage(message, "Value found in array [" + haystack + "]."));
1840 * Asserts that the given value is contained in an array at the specified index.
1841 * This uses the triple equals sign so no type coercion will occur.
1842 * @param {Object} needle The value to look for.
1843 * @param {Array} haystack The array to search in.
1844 * @param {int} index The index at which the value should exist.
1845 * @param {String} message (Optional) The message to display if the assertion fails.
1849 indexOf : function (needle /*:Object*/, haystack /*:Array*/, index /*:int*/, message /*:String*/) /*:Void*/ {
1851 //try to find the value in the array
1852 for (var i=0; i < haystack.length; i++){
1853 if (haystack[i] === needle){
1854 YAHOO.util.Assert.areEqual(index, i, message || "Value exists at index " + i + " but should be at index " + index + ".");
1859 var Assert = YAHOO.util.Assert;
1861 //if it makes it here, it wasn't found at all
1862 Assert.fail(Assert._formatMessage(message, "Value doesn't exist in array [" + haystack + "]."));
1866 * Asserts that the values in an array are equal, and in the same position,
1867 * as values in another array. This uses the double equals sign
1868 * so type coercion may occur. Note that the array objects themselves
1869 * need not be the same for this test to pass.
1870 * @param {Array} expected An array of the expected values.
1871 * @param {Array} actual Any array of the actual values.
1872 * @param {String} message (Optional) The message to display if the assertion fails.
1873 * @method itemsAreEqual
1876 itemsAreEqual : function (expected /*:Array*/, actual /*:Array*/,
1877 message /*:String*/) /*:Void*/ {
1879 //one may be longer than the other, so get the maximum length
1880 var len /*:int*/ = Math.max(expected.length, actual.length || 0);
1881 var Assert = YAHOO.util.Assert;
1883 //begin checking values
1884 for (var i=0; i < len; i++){
1885 Assert.areEqual(expected[i], actual[i],
1886 Assert._formatMessage(message, "Values in position " + i + " are not equal."));
1891 * Asserts that the values in an array are equivalent, and in the same position,
1892 * as values in another array. This uses a function to determine if the values
1893 * are equivalent. Note that the array objects themselves
1894 * need not be the same for this test to pass.
1895 * @param {Array} expected An array of the expected values.
1896 * @param {Array} actual Any array of the actual values.
1897 * @param {Function} comparator A function that returns true if the values are equivalent
1899 * @param {String} message (Optional) The message to display if the assertion fails.
1901 * @method itemsAreEquivalent
1904 itemsAreEquivalent : function (expected /*:Array*/, actual /*:Array*/,
1905 comparator /*:Function*/, message /*:String*/) /*:Void*/ {
1907 //make sure the comparator is valid
1908 if (typeof comparator != "function"){
1909 throw new TypeError("ArrayAssert.itemsAreEquivalent(): Third argument must be a function.");
1912 //one may be longer than the other, so get the maximum length
1913 var len /*:int*/ = Math.max(expected.length, actual.length || 0);
1915 //begin checking values
1916 for (var i=0; i < len; i++){
1917 if (!comparator(expected[i], actual[i])){
1918 throw new YAHOO.util.ComparisonFailure(YAHOO.util.Assert._formatMessage(message, "Values in position " + i + " are not equivalent."), expected[i], actual[i]);
1924 * Asserts that an array is empty.
1925 * @param {Array} actual The array to test.
1926 * @param {String} message (Optional) The message to display if the assertion fails.
1930 isEmpty : function (actual /*:Array*/, message /*:String*/) /*:Void*/ {
1931 if (actual.length > 0){
1932 var Assert = YAHOO.util.Assert;
1933 Assert.fail(Assert._formatMessage(message, "Array should be empty."));
1938 * Asserts that an array is not empty.
1939 * @param {Array} actual The array to test.
1940 * @param {String} message (Optional) The message to display if the assertion fails.
1941 * @method isNotEmpty
1944 isNotEmpty : function (actual /*:Array*/, message /*:String*/) /*:Void*/ {
1945 if (actual.length === 0){
1946 var Assert = YAHOO.util.Assert;
1947 Assert.fail(Assert._formatMessage(message, "Array should not be empty."));
1952 * Asserts that the values in an array are the same, and in the same position,
1953 * as values in another array. This uses the triple equals sign
1954 * so no type coercion will occur. Note that the array objects themselves
1955 * need not be the same for this test to pass.
1956 * @param {Array} expected An array of the expected values.
1957 * @param {Array} actual Any array of the actual values.
1958 * @param {String} message (Optional) The message to display if the assertion fails.
1959 * @method itemsAreSame
1962 itemsAreSame : function (expected /*:Array*/, actual /*:Array*/,
1963 message /*:String*/) /*:Void*/ {
1965 //one may be longer than the other, so get the maximum length
1966 var len /*:int*/ = Math.max(expected.length, actual.length || 0);
1967 var Assert = YAHOO.util.Assert;
1969 //begin checking values
1970 for (var i=0; i < len; i++){
1971 Assert.areSame(expected[i], actual[i],
1972 Assert._formatMessage(message, "Values in position " + i + " are not the same."));
1977 * Asserts that the given value is contained in an array at the specified index,
1978 * starting from the back of the array.
1979 * This uses the triple equals sign so no type coercion will occur.
1980 * @param {Object} needle The value to look for.
1981 * @param {Array} haystack The array to search in.
1982 * @param {int} index The index at which the value should exist.
1983 * @param {String} message (Optional) The message to display if the assertion fails.
1984 * @method lastIndexOf
1987 lastIndexOf : function (needle /*:Object*/, haystack /*:Array*/, index /*:int*/, message /*:String*/) /*:Void*/ {
1989 var Assert = YAHOO.util.Assert;
1991 //try to find the value in the array
1992 for (var i=haystack.length; i >= 0; i--){
1993 if (haystack[i] === needle){
1994 Assert.areEqual(index, i, Assert._formatMessage(message, "Value exists at index " + i + " but should be at index " + index + "."));
1999 //if it makes it here, it wasn't found at all
2000 Assert.fail(Assert._formatMessage(message, "Value doesn't exist in array."));
2004 YAHOO.namespace("util");
2007 //-----------------------------------------------------------------------------
2008 // ObjectAssert object
2009 //-----------------------------------------------------------------------------
2012 * The ObjectAssert object provides functions to test JavaScript objects
2013 * for a variety of cases.
2015 * @namespace YAHOO.util
2016 * @class ObjectAssert
2019 YAHOO.util.ObjectAssert = {
2022 * Asserts that all properties in the object exist in another object.
2023 * @param {Object} expected An object with the expected properties.
2024 * @param {Object} actual An object with the actual properties.
2025 * @param {String} message (Optional) The message to display if the assertion fails.
2026 * @method propertiesAreEqual
2029 propertiesAreEqual : function (expected /*:Object*/, actual /*:Object*/,
2030 message /*:String*/) /*:Void*/ {
2032 var Assert = YAHOO.util.Assert;
2034 //get all properties in the object
2035 var properties /*:Array*/ = [];
2036 for (var property in expected){
2037 properties.push(property);
2040 //see if the properties are in the expected object
2041 for (var i=0; i < properties.length; i++){
2042 Assert.isNotUndefined(actual[properties[i]],
2043 Assert._formatMessage(message, "Property '" + properties[i] + "' expected."));
2049 * Asserts that an object has a property with the given name.
2050 * @param {String} propertyName The name of the property to test.
2051 * @param {Object} object The object to search.
2052 * @param {String} message (Optional) The message to display if the assertion fails.
2053 * @method hasProperty
2056 hasProperty : function (propertyName /*:String*/, object /*:Object*/, message /*:String*/) /*:Void*/ {
2057 if (!(propertyName in object)){
2058 var Assert = YAHOO.util.Assert;
2059 Assert.fail(Assert._formatMessage(message, "Property '" + propertyName + "' not found on object."));
2064 * Asserts that a property with the given name exists on an object instance (not on its prototype).
2065 * @param {String} propertyName The name of the property to test.
2066 * @param {Object} object The object to search.
2067 * @param {String} message (Optional) The message to display if the assertion fails.
2068 * @method hasProperty
2071 hasOwnProperty : function (propertyName /*:String*/, object /*:Object*/, message /*:String*/) /*:Void*/ {
2072 if (!YAHOO.lang.hasOwnProperty(object, propertyName)){
2073 var Assert = YAHOO.util.Assert;
2074 Assert.fail(Assert._formatMessage(message, "Property '" + propertyName + "' not found on object instance."));
2078 //-----------------------------------------------------------------------------
2079 // DateAssert object
2080 //-----------------------------------------------------------------------------
2083 * The DateAssert object provides functions to test JavaScript Date objects
2084 * for a variety of cases.
2086 * @namespace YAHOO.util
2091 YAHOO.util.DateAssert = {
2094 * Asserts that a date's month, day, and year are equal to another date's.
2095 * @param {Date} expected The expected date.
2096 * @param {Date} actual The actual date to test.
2097 * @param {String} message (Optional) The message to display if the assertion fails.
2098 * @method datesAreEqual
2101 datesAreEqual : function (expected /*:Date*/, actual /*:Date*/, message /*:String*/){
2102 if (expected instanceof Date && actual instanceof Date){
2103 var Assert = YAHOO.util.Assert;
2104 Assert.areEqual(expected.getFullYear(), actual.getFullYear(), Assert._formatMessage(message, "Years should be equal."));
2105 Assert.areEqual(expected.getMonth(), actual.getMonth(), Assert._formatMessage(message, "Months should be equal."));
2106 Assert.areEqual(expected.getDate(), actual.getDate(), Assert._formatMessage(message, "Day of month should be equal."));
2108 throw new TypeError("DateAssert.datesAreEqual(): Expected and actual values must be Date objects.");
2113 * Asserts that a date's hour, minutes, and seconds are equal to another date's.
2114 * @param {Date} expected The expected date.
2115 * @param {Date} actual The actual date to test.
2116 * @param {String} message (Optional) The message to display if the assertion fails.
2117 * @method timesAreEqual
2120 timesAreEqual : function (expected /*:Date*/, actual /*:Date*/, message /*:String*/){
2121 if (expected instanceof Date && actual instanceof Date){
2122 var Assert = YAHOO.util.Assert;
2123 Assert.areEqual(expected.getHours(), actual.getHours(), Assert._formatMessage(message, "Hours should be equal."));
2124 Assert.areEqual(expected.getMinutes(), actual.getMinutes(), Assert._formatMessage(message, "Minutes should be equal."));
2125 Assert.areEqual(expected.getSeconds(), actual.getSeconds(), Assert._formatMessage(message, "Seconds should be equal."));
2127 throw new TypeError("DateAssert.timesAreEqual(): Expected and actual values must be Date objects.");
2132 YAHOO.register("yuitest_core", YAHOO.tool.TestRunner, {version: "2.9.0", build: "2800"});