Changeset 1928
- Timestamp:
- 2011-08-09 15:13:24 (10 months ago)
- Location:
- trunk/modules/kauri-jquery/src/test/qunit
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/modules/kauri-jquery/src/test/qunit/qunit.css
r1896 r1928 1 /** 2 * QUnit - A JavaScript Unit Testing Framework 3 * 4 * http://docs.jquery.com/QUnit 5 * 6 * Copyright (c) 2011 John Resig, Jörn Zaefferer 7 * Dual licensed under the MIT (MIT-LICENSE.txt) 8 * or GPL (GPL-LICENSE.txt) licenses. 9 */ 10 1 11 /** Font Family and Sizes */ 2 12 3 13 #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { 4 font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial ;14 font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; 5 15 } 6 16 … … 28 38 line-height: 1em; 29 39 font-weight: normal; 30 40 31 41 border-radius: 15px 15px 0 0; 32 42 -moz-border-radius: 15px 15px 0 0; … … 96 106 margin-top: 0.5em; 97 107 padding: 0.5em; 98 99 background-color: #fff; 100 108 109 background-color: #fff; 110 101 111 border-radius: 15px; 102 112 -moz-border-radius: 15px; 103 113 -webkit-border-radius: 15px; 104 114 105 115 box-shadow: inset 0px 2px 13px #999; 106 116 -moz-box-shadow: inset 0px 2px 13px #999; … … 165 175 #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } 166 176 #qunit-tests .pass .test-name { color: #366097; } 167 177 168 178 #qunit-tests .pass .test-actual, 169 179 #qunit-tests .pass .test-expected { color: #999999; } -
trunk/modules/kauri-jquery/src/test/qunit/qunit.js
r1896 r1928 1 /* 1 /** 2 2 * QUnit - A JavaScript Unit Testing Framework 3 * 3 * 4 4 * http://docs.jquery.com/QUnit 5 5 * … … 16 16 try { 17 17 return !!sessionStorage.getItem; 18 } catch(e) {18 } catch(e) { 19 19 return false; 20 20 } 21 })()21 })() 22 22 }; 23 23 … … 79 79 // TODO why?? 80 80 QUnit.current_testEnvironment = this.testEnvironment; 81 81 82 82 try { 83 83 if ( !config.pollution ) { … … 115 115 teardown: function() { 116 116 try { 117 this.testEnvironment.teardown.call(this.testEnvironment); 117 118 checkPollution(); 118 this.testEnvironment.teardown.call(this.testEnvironment);119 119 } catch(e) { 120 120 QUnit.ok( false, "Teardown failed on " + this.testName + ": " + e.message ); … … 125 125 QUnit.ok( false, "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run" ); 126 126 } 127 127 128 128 var good = 0, bad = 0, 129 129 tests = id("qunit-tests"); … … 133 133 134 134 if ( tests ) { 135 var ol = document.createElement("ol");135 var ol = document.createElement("ol"); 136 136 137 137 for ( var i = 0; i < this.assertions.length; i++ ) { … … 155 155 if ( QUnit.config.reorder && defined.sessionStorage ) { 156 156 if (bad) { 157 sessionStorage.setItem("qunit-" + this.module + "-" + this.testName, bad) 157 sessionStorage.setItem("qunit-" + this.module + "-" + this.testName, bad); 158 158 } else { 159 sessionStorage.removeItem("qunit-" + this. testName);159 sessionStorage.removeItem("qunit-" + this.module + "-" + this.testName); 160 160 } 161 161 } … … 167 167 var b = document.createElement("strong"); 168 168 b.innerHTML = this.name + " <b class='counts'>(<b class='failed'>" + bad + "</b>, <b class='passed'>" + good + "</b>, " + this.assertions.length + ")</b>"; 169 169 170 170 var a = document.createElement("a"); 171 171 a.innerHTML = "Rerun"; 172 172 a.href = QUnit.url({ filter: getText([b]).replace(/\([^)]+\)$/, "").replace(/(^\s*|\s*$)/g, "") }); 173 173 174 174 addEvent(b, "click", function() { 175 175 var next = b.nextSibling.nextSibling, … … 177 177 next.style.display = display === "none" ? "block" : "none"; 178 178 }); 179 179 180 180 addEvent(b, "dblclick", function(e) { 181 181 var target = e && e.target ? e.target : window.event.srcElement; … … 218 218 } ); 219 219 }, 220 220 221 221 queue: function() { 222 222 var test = this; … … 247 247 }; 248 248 } 249 249 250 250 }; 251 251 … … 266 266 QUnit.test(testName, expected, callback, true); 267 267 }, 268 268 269 269 test: function(testName, expected, callback, async) { 270 270 var name = '<span class="test-name">' + testName + '</span>', testEnvironmentArg; … … 276 276 // is 2nd argument a testEnvironment? 277 277 if ( expected && typeof expected === 'object') { 278 testEnvironmentArg = expected;278 testEnvironmentArg = expected; 279 279 expected = null; 280 280 } … … 287 287 return; 288 288 } 289 289 290 290 var test = new Test(name, testName, expected, testEnvironmentArg, async, callback); 291 291 test.module = config.currentModule; … … 293 293 test.queue(); 294 294 }, 295 295 296 296 /** 297 297 * Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through. … … 338 338 QUnit.push(expected != actual, actual, expected, message); 339 339 }, 340 340 341 341 deepEqual: function(actual, expected, message) { 342 342 QUnit.push(QUnit.equiv(actual, expected), actual, expected, message); … … 357 357 raises: function(block, expected, message) { 358 358 var actual, ok = false; 359 359 360 360 if (typeof expected === 'string') { 361 361 message = expected; 362 362 expected = null; 363 363 } 364 364 365 365 try { 366 366 block(); … … 368 368 actual = e; 369 369 } 370 370 371 371 if (actual) { 372 372 // we don't want to validate thrown error 373 373 if (!expected) { 374 374 ok = true; 375 // expected is a regexp 375 // expected is a regexp 376 376 } else if (QUnit.objectType(expected) === "regexp") { 377 377 ok = expected.test(actual); 378 // expected is a constructor 378 // expected is a constructor 379 379 } else if (actual instanceof expected) { 380 380 ok = true; 381 // expected is a validation function which returns true is validation passed 381 // expected is a validation function which returns true is validation passed 382 382 } else if (expected.call({}, actual) === true) { 383 383 ok = true; 384 384 } 385 385 } 386 386 387 387 QUnit.ok(ok, message); 388 388 }, … … 401 401 if ( defined.setTimeout ) { 402 402 window.setTimeout(function() { 403 if (config.semaphore > 0) { 404 return; 405 } 403 406 if ( config.timeout ) { 404 407 clearTimeout(config.timeout); … … 413 416 } 414 417 }, 415 418 416 419 stop: function(timeout) { 417 420 config.semaphore++; … … 439 442 // block until document ready 440 443 blocking: true, 441 444 445 // when enabled, show only failing tests 446 // gets persisted through sessionStorage and can be changed in UI via checkbox 447 hidepassed: false, 448 442 449 // by default, run previously failed tests first 443 450 // very useful in combination with "Hide passed tests" checked 444 451 reorder: true, 452 453 // by default, modify document.title when suite is done 454 altertitle: true, 445 455 446 456 noglobals: false, … … 520 530 result.parentNode.removeChild( result ); 521 531 } 522 532 523 533 if ( tests ) { 524 534 result = document.createElement( "p" ); … … 529 539 } 530 540 }, 531 541 532 542 /** 533 543 * Resets the test setup. Useful for tests that modify the DOM. 534 * 544 * 535 545 * If jQuery is available, uses jQuery's html(), otherwise just innerHTML. 536 546 */ 537 547 reset: function() { 538 548 if ( window.jQuery ) { 539 jQuery( "# main, #qunit-fixture" ).html( config.fixture );549 jQuery( "#qunit-fixture" ).html( config.fixture ); 540 550 } else { 541 var main = id( ' main' ) || id( 'qunit-fixture' );551 var main = id( 'qunit-fixture' ); 542 552 if ( main ) { 543 553 main.innerHTML = config.fixture; … … 545 555 } 546 556 }, 547 557 548 558 /** 549 559 * Trigger an event on an element. … … 565 575 } 566 576 }, 567 577 568 578 // Safe object type checking 569 579 is: function( type, obj ) { 570 580 return QUnit.objectType( obj ) == type; 571 581 }, 572 582 573 583 objectType: function( obj ) { 574 584 if (typeof obj === "undefined") { … … 604 614 return undefined; 605 615 }, 606 616 607 617 push: function(result, actual, expected, message) { 608 618 var details = { … … 612 622 expected: expected 613 623 }; 614 624 615 625 message = escapeHtml(message) || (result ? "okay" : "failed"); 616 626 message = '<span class="test-message">' + message + "</span>"; … … 626 636 if (source) { 627 637 details.source = source; 628 output += '<tr class="test-source"><th>Source: </th><td><pre>' + source +'</pre></td></tr>';638 output += '<tr class="test-source"><th>Source: </th><td><pre>' + escapeHtml(source) + '</pre></td></tr>'; 629 639 } 630 640 } 631 641 output += "</table>"; 632 642 633 643 QUnit.log(details); 634 644 635 645 config.current.assertions.push({ 636 646 result: !!result, … … 638 648 }); 639 649 }, 640 650 641 651 url: function( params ) { 642 652 params = extend( extend( {}, QUnit.urlParams ), params ); … … 649 659 return window.location.pathname + querystring.slice( 0, -1 ); 650 660 }, 651 661 662 extend: extend, 663 id: id, 664 addEvent: addEvent, 665 652 666 // Logging callbacks; all receive a single argument with the listed properties 653 667 // run test/logs.html for any related changes … … 671 685 } 672 686 673 addEvent(window, "load",function() {687 QUnit.load = function() { 674 688 QUnit.begin({}); 675 689 676 690 // Initialize the config, saving the execution queue 677 691 var oldconfig = extend({}, config); … … 696 710 }); 697 711 } 698 712 699 713 var toolbar = id("qunit-testrunner-toolbar"); 700 714 if ( toolbar ) { … … 712 726 if ( defined.sessionStorage ) { 713 727 if (filter.checked) { 714 sessionStorage.setItem("qunit-filter-passed-tests", "true");728 sessionStorage.setItem("qunit-filter-passed-tests", "true"); 715 729 } else { 716 730 sessionStorage.removeItem("qunit-filter-passed-tests"); … … 718 732 } 719 733 }); 720 if ( defined.sessionStorage && sessionStorage.getItem("qunit-filter-passed-tests") ) {734 if ( config.hidepassed || defined.sessionStorage && sessionStorage.getItem("qunit-filter-passed-tests") ) { 721 735 filter.checked = true; 722 736 var ol = document.getElementById("qunit-tests"); … … 731 745 } 732 746 733 var main = id(' main') || id('qunit-fixture');747 var main = id('qunit-fixture'); 734 748 if ( main ) { 735 749 config.fixture = main.innerHTML; … … 739 753 QUnit.start(); 740 754 } 741 }); 755 }; 756 757 addEvent(window, "load", QUnit.load); 742 758 743 759 function done() { … … 775 791 } 776 792 777 if ( tests ) { 793 if ( tests ) { 778 794 id( "qunit-testresult" ).innerHTML = html; 795 } 796 797 if ( config.altertitle && typeof document !== "undefined" && document.title ) { 798 // show ✖ for good, ✔ for bad suite result in title 799 // use escape sequences in case file gets loaded with non-utf-8-charset 800 document.title = [ 801 (config.stats.bad ? "\u2716" : "\u2714"), 802 document.title.replace(/^[\u2714\u2716] /i, "") 803 ].join(" "); 779 804 } 780 805 781 806 QUnit.done( { 782 807 failed: config.stats.bad, 783 passed: passed, 808 passed: passed, 784 809 total: config.stats.all, 785 810 runtime: runtime … … 795 820 } 796 821 797 not = filter.charAt( 0 ) === "!";822 var not = filter.charAt( 0 ) === "!"; 798 823 if ( not ) { 799 824 filter = filter.slice( 1 ); … … 863 888 } 864 889 } 865 if (!config.blocking && !config.queue.length) {866 done();867 }890 if (!config.blocking && !config.queue.length) { 891 done(); 892 } 868 893 } 869 894 870 895 function saveGlobal() { 871 896 config.pollution = []; 872 897 873 898 if ( config.noglobals ) { 874 899 for ( var key in window ) { … … 881 906 var old = config.pollution; 882 907 saveGlobal(); 883 908 884 909 var newGlobals = diff( config.pollution, old ); 885 910 if ( newGlobals.length > 0 ) { … … 952 977 QUnit.equiv = function () { 953 978 954 var innerEquiv; // the real equiv function 955 var callers = []; // stack to decide between skip/abort functions 956 var parents = []; // stack to avoiding loops from circular referencing 957 958 // Call the o related callback with the given arguments. 959 function bindCallbacks(o, callbacks, args) { 960 var prop = QUnit.objectType(o); 961 if (prop) { 962 if (QUnit.objectType(callbacks[prop]) === "function") { 963 return callbacks[prop].apply(callbacks, args); 964 } else { 965 return callbacks[prop]; // or undefined 966 } 967 } 968 } 969 970 var callbacks = function () { 971 972 // for string, boolean, number and null 973 function useStrictEquality(b, a) { 974 if (b instanceof a.constructor || a instanceof b.constructor) { 975 // to catch short annotaion VS 'new' annotation of a declaration 976 // e.g. var i = 1; 977 // var j = new Number(1); 978 return a == b; 979 } else { 980 return a === b; 981 } 982 } 983 984 return { 985 "string": useStrictEquality, 986 "boolean": useStrictEquality, 987 "number": useStrictEquality, 988 "null": useStrictEquality, 989 "undefined": useStrictEquality, 990 991 "nan": function (b) { 992 return isNaN(b); 993 }, 994 995 "date": function (b, a) { 996 return QUnit.objectType(b) === "date" && a.valueOf() === b.valueOf(); 997 }, 998 999 "regexp": function (b, a) { 1000 return QUnit.objectType(b) === "regexp" && 1001 a.source === b.source && // the regex itself 1002 a.global === b.global && // and its modifers (gmi) ... 1003 a.ignoreCase === b.ignoreCase && 1004 a.multiline === b.multiline; 1005 }, 1006 1007 // - skip when the property is a method of an instance (OOP) 1008 // - abort otherwise, 1009 // initial === would have catch identical references anyway 1010 "function": function () { 1011 var caller = callers[callers.length - 1]; 1012 return caller !== Object && 1013 typeof caller !== "undefined"; 1014 }, 1015 1016 "array": function (b, a) { 1017 var i, j, loop; 1018 var len; 1019 1020 // b could be an object literal here 1021 if ( ! (QUnit.objectType(b) === "array")) { 1022 return false; 1023 } 1024 1025 len = a.length; 1026 if (len !== b.length) { // safe and faster 1027 return false; 1028 } 1029 1030 //track reference to avoid circular references 1031 parents.push(a); 1032 for (i = 0; i < len; i++) { 1033 loop = false; 1034 for(j=0;j<parents.length;j++){ 1035 if(parents[j] === a[i]){ 1036 loop = true;//dont rewalk array 1037 } 1038 } 1039 if (!loop && ! innerEquiv(a[i], b[i])) { 1040 parents.pop(); 1041 return false; 1042 } 1043 } 1044 parents.pop(); 1045 return true; 1046 }, 1047 1048 "object": function (b, a) { 1049 var i, j, loop; 1050 var eq = true; // unless we can proove it 1051 var aProperties = [], bProperties = []; // collection of strings 1052 1053 // comparing constructors is more strict than using instanceof 1054 if ( a.constructor !== b.constructor) { 1055 return false; 1056 } 1057 1058 // stack constructor before traversing properties 1059 callers.push(a.constructor); 1060 //track reference to avoid circular references 1061 parents.push(a); 1062 1063 for (i in a) { // be strict: don't ensures hasOwnProperty and go deep 1064 loop = false; 1065 for(j=0;j<parents.length;j++){ 1066 if(parents[j] === a[i]) 1067 loop = true; //don't go down the same path twice 1068 } 1069 aProperties.push(i); // collect a's properties 1070 1071 if (!loop && ! innerEquiv(a[i], b[i])) { 1072 eq = false; 1073 break; 1074 } 1075 } 1076 1077 callers.pop(); // unstack, we are done 1078 parents.pop(); 1079 1080 for (i in b) { 1081 bProperties.push(i); // collect b's properties 1082 } 1083 1084 // Ensures identical properties name 1085 return eq && innerEquiv(aProperties.sort(), bProperties.sort()); 1086 } 1087 }; 1088 }(); 1089 1090 innerEquiv = function () { // can take multiple arguments 1091 var args = Array.prototype.slice.apply(arguments); 1092 if (args.length < 2) { 1093 return true; // end transition 1094 } 1095 1096 return (function (a, b) { 1097 if (a === b) { 1098 return true; // catch the most you can 1099 } else if (a === null || b === null || typeof a === "undefined" || typeof b === "undefined" || QUnit.objectType(a) !== QUnit.objectType(b)) { 1100 return false; // don't lose time with error prone cases 1101 } else { 1102 return bindCallbacks(a, callbacks, [b, a]); 1103 } 1104 1105 // apply transition with (1..n) arguments 1106 })(args[0], args[1]) && arguments.callee.apply(this, args.splice(1, args.length -1)); 1107 }; 1108 1109 return innerEquiv; 979 var innerEquiv; // the real equiv function 980 var callers = []; // stack to decide between skip/abort functions 981 var parents = []; // stack to avoiding loops from circular referencing 982 983 // Call the o related callback with the given arguments. 984 function bindCallbacks(o, callbacks, args) { 985 var prop = QUnit.objectType(o); 986 if (prop) { 987 if (QUnit.objectType(callbacks[prop]) === "function") { 988 return callbacks[prop].apply(callbacks, args); 989 } else { 990 return callbacks[prop]; // or undefined 991 } 992 } 993 } 994 995 var callbacks = function () { 996 997 // for string, boolean, number and null 998 function useStrictEquality(b, a) { 999 if (b instanceof a.constructor || a instanceof b.constructor) { 1000 // to catch short annotaion VS 'new' annotation of a 1001 // declaration 1002 // e.g. var i = 1; 1003 // var j = new Number(1); 1004 return a == b; 1005 } else { 1006 return a === b; 1007 } 1008 } 1009 1010 return { 1011 "string" : useStrictEquality, 1012 "boolean" : useStrictEquality, 1013 "number" : useStrictEquality, 1014 "null" : useStrictEquality, 1015 "undefined" : useStrictEquality, 1016 1017 "nan" : function(b) { 1018 return isNaN(b); 1019 }, 1020 1021 "date" : function(b, a) { 1022 return QUnit.objectType(b) === "date" 1023 && a.valueOf() === b.valueOf(); 1024 }, 1025 1026 "regexp" : function(b, a) { 1027 return QUnit.objectType(b) === "regexp" 1028 && a.source === b.source && // the regex itself 1029 a.global === b.global && // and its modifers 1030 // (gmi) ... 1031 a.ignoreCase === b.ignoreCase 1032 && a.multiline === b.multiline; 1033 }, 1034 1035 // - skip when the property is a method of an instance (OOP) 1036 // - abort otherwise, 1037 // initial === would have catch identical references anyway 1038 "function" : function() { 1039 var caller = callers[callers.length - 1]; 1040 return caller !== Object && typeof caller !== "undefined"; 1041 }, 1042 1043 "array" : function(b, a) { 1044 var i, j, loop; 1045 var len; 1046 1047 // b could be an object literal here 1048 if (!(QUnit.objectType(b) === "array")) { 1049 return false; 1050 } 1051 1052 len = a.length; 1053 if (len !== b.length) { // safe and faster 1054 return false; 1055 } 1056 1057 // track reference to avoid circular references 1058 parents.push(a); 1059 for (i = 0; i < len; i++) { 1060 loop = false; 1061 for (j = 0; j < parents.length; j++) { 1062 if (parents[j] === a[i]) { 1063 loop = true;// dont rewalk array 1064 } 1065 } 1066 if (!loop && !innerEquiv(a[i], b[i])) { 1067 parents.pop(); 1068 return false; 1069 } 1070 } 1071 parents.pop(); 1072 return true; 1073 }, 1074 1075 "object" : function(b, a) { 1076 var i, j, loop; 1077 var eq = true; // unless we can proove it 1078 var aProperties = [], bProperties = []; // collection of 1079 // strings 1080 1081 // comparing constructors is more strict than using 1082 // instanceof 1083 if (a.constructor !== b.constructor) { 1084 return false; 1085 } 1086 1087 // stack constructor before traversing properties 1088 callers.push(a.constructor); 1089 // track reference to avoid circular references 1090 parents.push(a); 1091 1092 for (i in a) { // be strict: don't ensures hasOwnProperty 1093 // and go deep 1094 loop = false; 1095 for (j = 0; j < parents.length; j++) { 1096 if (parents[j] === a[i]) 1097 loop = true; // don't go down the same path 1098 // twice 1099 } 1100 aProperties.push(i); // collect a's properties 1101 1102 if (!loop && !innerEquiv(a[i], b[i])) { 1103 eq = false; 1104 break; 1105 } 1106 } 1107 1108 callers.pop(); // unstack, we are done 1109 parents.pop(); 1110 1111 for (i in b) { 1112 bProperties.push(i); // collect b's properties 1113 } 1114 1115 // Ensures identical properties name 1116 return eq 1117 && innerEquiv(aProperties.sort(), bProperties 1118 .sort()); 1119 } 1120 }; 1121 }(); 1122 1123 innerEquiv = function() { // can take multiple arguments 1124 var args = Array.prototype.slice.apply(arguments); 1125 if (args.length < 2) { 1126 return true; // end transition 1127 } 1128 1129 return (function(a, b) { 1130 if (a === b) { 1131 return true; // catch the most you can 1132 } else if (a === null || b === null || typeof a === "undefined" 1133 || typeof b === "undefined" 1134 || QUnit.objectType(a) !== QUnit.objectType(b)) { 1135 return false; // don't lose time with error prone cases 1136 } else { 1137 return bindCallbacks(a, callbacks, [ b, a ]); 1138 } 1139 1140 // apply transition with (1..n) arguments 1141 })(args[0], args[1]) 1142 && arguments.callee.apply(this, args.splice(1, 1143 args.length - 1)); 1144 }; 1145 1146 return innerEquiv; 1110 1147 1111 1148 }(); 1112 1149 1113 1150 /** 1114 * jsDump 1115 * Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com1116 * Licensed under BSD (http://www.opensource.org/licenses/bsd-license.php)1117 * Date: 5/15/20081151 * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com | 1152 * http://flesler.blogspot.com Licensed under BSD 1153 * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008 1154 * 1118 1155 * @projectDescription Advanced and extensible data dumping for Javascript. 1119 1156 * @version 1.0.0 … … 1126 1163 }; 1127 1164 function literal( o ) { 1128 return o + ''; 1165 return o + ''; 1129 1166 }; 1130 1167 function join( pre, arr, post ) { … … 1138 1175 return [ pre, inner + arr, base + post ].join(s); 1139 1176 }; 1140 function array( arr ) {1141 var i = arr.length, ret = Array(i);1177 function array( arr, stack ) { 1178 var i = arr.length, ret = Array(i); 1142 1179 this.up(); 1143 1180 while ( i-- ) 1144 ret[i] = this.parse( arr[i] );1181 ret[i] = this.parse( arr[i] , undefined , stack); 1145 1182 this.down(); 1146 1183 return join( '[', ret, ']' ); 1147 1184 }; 1148 1185 1149 1186 var reName = /^function (\w+)/; 1150 1187 1151 1188 var jsDump = { 1152 parse:function( obj, type ) { //type is used mostly internally, you can fix a (custom)type in advance 1153 var parser = this.parsers[ type || this.typeOf(obj) ]; 1154 type = typeof parser; 1155 1156 return type == 'function' ? parser.call( this, obj ) : 1157 type == 'string' ? parser : 1158 this.parsers.error; 1189 parse:function( obj, type, stack ) { //type is used mostly internally, you can fix a (custom)type in advance 1190 stack = stack || [ ]; 1191 var parser = this.parsers[ type || this.typeOf(obj) ]; 1192 type = typeof parser; 1193 var inStack = inArray(obj, stack); 1194 if (inStack != -1) { 1195 return 'recursion('+(inStack - stack.length)+')'; 1196 } 1197 //else 1198 if (type == 'function') { 1199 stack.push(obj); 1200 var res = parser.call( this, obj, stack ); 1201 stack.pop(); 1202 return res; 1203 } 1204 // else 1205 return (type == 'string') ? parser : this.parsers.error; 1159 1206 }, 1160 1207 typeOf:function( obj ) { … … 1204 1251 }, 1205 1252 // The next 3 are exposed so you can use them 1206 quote:quote, 1253 quote:quote, 1207 1254 literal:literal, 1208 1255 join:join, … … 1223 1270 ret += ' ' + name; 1224 1271 ret += '('; 1225 1272 1226 1273 ret = [ ret, QUnit.jsDump.parse( fn, 'functionArgs' ), '){'].join(''); 1227 1274 return join( ret, QUnit.jsDump.parse(fn,'functionCode'), '}' ); … … 1230 1277 nodelist: array, 1231 1278 arguments: array, 1232 object:function( map ) {1279 object:function( map, stack ) { 1233 1280 var ret = [ ]; 1234 1281 QUnit.jsDump.up(); 1235 for ( var key in map ) 1236 ret.push( QUnit.jsDump.parse(key,'key') + ': ' + QUnit.jsDump.parse(map[key]) ); 1282 for ( var key in map ) { 1283 var val = map[key]; 1284 ret.push( QUnit.jsDump.parse(key,'key') + ': ' + QUnit.jsDump.parse(val, undefined, stack)); 1285 } 1237 1286 QUnit.jsDump.down(); 1238 1287 return join( '{', ret, '}' ); … … 1241 1290 var open = QUnit.jsDump.HTML ? '<' : '<', 1242 1291 close = QUnit.jsDump.HTML ? '>' : '>'; 1243 1292 1244 1293 var tag = node.nodeName.toLowerCase(), 1245 1294 ret = open + tag; 1246 1295 1247 1296 for ( var a in QUnit.jsDump.DOMAttrs ) { 1248 1297 var val = node[QUnit.jsDump.DOMAttrs[a]]; … … 1254 1303 functionArgs:function( fn ) {//function calls it internally, it's the arguments part of the function 1255 1304 var l = fn.length; 1256 if ( !l ) return ''; 1257 1305 if ( !l ) return ''; 1306 1258 1307 var args = Array(l); 1259 1308 while ( l-- ) … … 1303 1352 }; 1304 1353 1354 //from jquery.js 1355 function inArray( elem, array ) { 1356 if ( array.indexOf ) { 1357 return array.indexOf( elem ); 1358 } 1359 1360 for ( var i = 0, length = array.length; i < length; i++ ) { 1361 if ( array[ i ] === elem ) { 1362 return i; 1363 } 1364 } 1365 1366 return -1; 1367 } 1368 1305 1369 /* 1306 1370 * Javascript Diff Algorithm … … 1312 1376 * More Info: 1313 1377 * http://ejohn.org/projects/javascript-diff-algorithm/ 1314 * 1378 * 1315 1379 * Usage: QUnit.diff(expected, actual) 1316 * 1380 * 1317 1381 * QUnit.diff("the quick brown fox jumped over", "the quick fox jumps over") == "the quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over" 1318 1382 */ 1319 1383 QUnit.diff = (function() { 1320 function diff(o, n) {1384 function diff(o, n) { 1321 1385 var ns = new Object(); 1322 1386 var os = new Object(); 1323 1387 1324 1388 for (var i = 0; i < n.length; i++) { 1325 if (ns[n[i]] == null) 1389 if (ns[n[i]] == null) 1326 1390 ns[n[i]] = { 1327 1391 rows: new Array(), … … 1330 1394 ns[n[i]].rows.push(i); 1331 1395 } 1332 1396 1333 1397 for (var i = 0; i < o.length; i++) { 1334 if (os[o[i]] == null) 1398 if (os[o[i]] == null) 1335 1399 os[o[i]] = { 1336 1400 rows: new Array(), … … 1339 1403 os[o[i]].rows.push(i); 1340 1404 } 1341 1405 1342 1406 for (var i in ns) { 1343 1407 if (ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1) { … … 1352 1416 } 1353 1417 } 1354 1418 1355 1419 for (var i = 0; i < n.length - 1; i++) { 1356 1420 if (n[i].text != null && n[i + 1].text == null && n[i].row + 1 < o.length && o[n[i].row + 1].text == null && … … 1366 1430 } 1367 1431 } 1368 1432 1369 1433 for (var i = n.length - 1; i > 0; i--) { 1370 1434 if (n[i].text != null && n[i - 1].text == null && n[i].row > 0 && o[n[i].row - 1].text == null && … … 1380 1444 } 1381 1445 } 1382 1446 1383 1447 return { 1384 1448 o: o, … … 1386 1450 }; 1387 1451 } 1388 1389 return function(o, n) {1452 1453 return function(o, n) { 1390 1454 o = o.replace(/\s+$/, ''); 1391 1455 n = n.replace(/\s+$/, ''); … … 1393 1457 1394 1458 var str = ""; 1395 1459 1396 1460 var oSpace = o.match(/\s+/g); 1397 1461 if (oSpace == null) { … … 1408 1472 nSpace.push(" "); 1409 1473 } 1410 1474 1411 1475 if (out.n.length == 0) { 1412 1476 for (var i = 0; i < out.o.length; i++) { … … 1420 1484 } 1421 1485 } 1422 1486 1423 1487 for (var i = 0; i < out.n.length; i++) { 1424 1488 if (out.n[i].text == null) { … … 1427 1491 else { 1428 1492 var pre = ""; 1429 1493 1430 1494 for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++) { 1431 1495 pre += '<del>' + out.o[n] + oSpace[n] + "</del>"; … … 1435 1499 } 1436 1500 } 1437 1501 1438 1502 return str; 1439 1503 };
Note: See TracChangeset
for help on using the changeset viewer.