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