Skip to content
This repository
  • 2 commits
  • 3 files changed
  • 0 comments
  • 1 contributor
2  test/qunit-1.6.0.css → test/qunit.css
... ... @@ -1,5 +1,5 @@
1 1 /**
2   - * QUnit v1.6.0 - A JavaScript Unit Testing Framework
  2 + * QUnit v1.8.0 - A JavaScript Unit Testing Framework
3 3 *
4 4 * http://docs.jquery.com/QUnit
5 5 *
342 test/qunit-1.6.0.js → test/qunit.js
... ... @@ -1,5 +1,5 @@
1 1 /**
2   - * QUnit v1.6.0 - A JavaScript Unit Testing Framework
  2 + * QUnit v1.8.0 - A JavaScript Unit Testing Framework
3 3 *
4 4 * http://docs.jquery.com/QUnit
5 5 *
@@ -12,7 +12,9 @@
12 12
13 13 var QUnit,
14 14 config,
  15 + onErrorFnPrev,
15 16 testId = 0,
  17 + fileName = (sourceFromStacktrace( 0 ) || "" ).replace(/(:\d+)+\)?/, "").replace(/.+\//, ""),
16 18 toString = Object.prototype.toString,
17 19 hasOwn = Object.prototype.hasOwnProperty,
18 20 defined = {
@@ -29,26 +31,31 @@ var QUnit,
29 31 }())
30 32 };
31 33
32   -function Test( name, testName, expected, async, callback ) {
33   - this.name = name;
34   - this.testName = testName;
35   - this.expected = expected;
36   - this.async = async;
37   - this.callback = callback;
  34 +function Test( settings ) {
  35 + extend( this, settings );
38 36 this.assertions = [];
  37 + this.testNumber = ++Test.count;
39 38 }
40 39
  40 +Test.count = 0;
  41 +
41 42 Test.prototype = {
42 43 init: function() {
43   - var b, li,
  44 + var a, b, li,
44 45 tests = id( "qunit-tests" );
45 46
46 47 if ( tests ) {
47 48 b = document.createElement( "strong" );
48   - b.innerHTML = "Running " + this.name;
  49 + b.innerHTML = this.name;
  50 +
  51 + // `a` initialized at top of scope
  52 + a = document.createElement( "a" );
  53 + a.innerHTML = "Rerun";
  54 + a.href = QUnit.url({ testNumber: this.testNumber });
49 55
50 56 li = document.createElement( "li" );
51 57 li.appendChild( b );
  58 + li.appendChild( a );
52 59 li.className = "running";
53 60 li.id = this.id = "qunit-test-output" + testId++;
54 61
@@ -119,14 +126,14 @@ Test.prototype = {
119 126 }
120 127
121 128 if ( config.notrycatch ) {
122   - this.callback.call( this.testEnvironment );
  129 + this.callback.call( this.testEnvironment, QUnit.assert );
123 130 return;
124 131 }
125 132
126 133 try {
127   - this.callback.call( this.testEnvironment );
  134 + this.callback.call( this.testEnvironment, QUnit.assert );
128 135 } catch( e ) {
129   - QUnit.pushFailure( "Died on test #" + (this.assertions.length + 1) + ": " + e.message, extractStacktrace( e, 1 ) );
  136 + QUnit.pushFailure( "Died on test #" + (this.assertions.length + 1) + " " + this.stack + ": " + e.message, extractStacktrace( e, 0 ) );
130 137 // else next test will carry the responsibility
131 138 saveGlobal();
132 139
@@ -152,13 +159,16 @@ Test.prototype = {
152 159 },
153 160 finish: function() {
154 161 config.current = this;
155   - if ( this.expected != null && this.expected != this.assertions.length ) {
  162 + if ( config.requireExpects && this.expected == null ) {
  163 + QUnit.pushFailure( "Expected number of assertions to be defined, but expect() was not called.", this.stack );
  164 + } else if ( this.expected != null && this.expected != this.assertions.length ) {
156 165 QUnit.pushFailure( "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run", this.stack );
157 166 } else if ( this.expected == null && !this.assertions.length ) {
158 167 QUnit.pushFailure( "Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.", this.stack );
159 168 }
160 169
161 170 var assertion, a, b, i, li, ol,
  171 + test = this,
162 172 good = 0,
163 173 bad = 0,
164 174 tests = id( "qunit-tests" );
@@ -203,11 +213,6 @@ Test.prototype = {
203 213 b = document.createElement( "strong" );
204 214 b.innerHTML = this.name + " <b class='counts'>(<b class='failed'>" + bad + "</b>, <b class='passed'>" + good + "</b>, " + this.assertions.length + ")</b>";
205 215
206   - // `a` initialized at top of scope
207   - a = document.createElement( "a" );
208   - a.innerHTML = "Rerun";
209   - a.href = QUnit.url({ filter: getText([b]).replace( /\([^)]+\)$/, "" ).replace( /(^\s*|\s*$)/g, "" ) });
210   -
211 216 addEvent(b, "click", function() {
212 217 var next = b.nextSibling.nextSibling,
213 218 display = next.style.display;
@@ -220,9 +225,7 @@ Test.prototype = {
220 225 target = target.parentNode;
221 226 }
222 227 if ( window.location && target.nodeName.toLowerCase() === "strong" ) {
223   - window.location = QUnit.url({
224   - filter: getText([target]).replace( /\([^)]+\)$/, "" ).replace( /(^\s*|\s*$)/g, "" )
225   - });
  228 + window.location = QUnit.url({ testNumber: test.testNumber });
226 229 }
227 230 });
228 231
@@ -230,8 +233,9 @@ Test.prototype = {
230 233 li = id( this.id );
231 234 li.className = bad ? "fail" : "pass";
232 235 li.removeChild( li.firstChild );
  236 + a = li.firstChild;
233 237 li.appendChild( b );
234   - li.appendChild( a );
  238 + li.appendChild ( a );
235 239 li.appendChild( ol );
236 240
237 241 } else {
@@ -253,6 +257,8 @@ Test.prototype = {
253 257 });
254 258
255 259 QUnit.reset();
  260 +
  261 + config.current = undefined;
256 262 },
257 263
258 264 queue: function() {
@@ -291,6 +297,7 @@ Test.prototype = {
291 297 }
292 298 };
293 299
  300 +// Root QUnit object.
294 301 // `QUnit` initialized at top of scope
295 302 QUnit = {
296 303
@@ -322,14 +329,21 @@ QUnit = {
322 329 name = "<span class='module-name'>" + config.currentModule + "</span>: " + name;
323 330 }
324 331
325   - if ( !validTest(config.currentModule + ": " + testName) ) {
  332 + test = new Test({
  333 + name: name,
  334 + testName: testName,
  335 + expected: expected,
  336 + async: async,
  337 + callback: callback,
  338 + module: config.currentModule,
  339 + moduleTestEnvironment: config.currentModuleTestEnviroment,
  340 + stack: sourceFromStacktrace( 2 )
  341 + });
  342 +
  343 + if ( !validTest( test ) ) {
326 344 return;
327 345 }
328 346
329   - test = new Test( name, testName, expected, async, callback );
330   - test.module = config.currentModule;
331   - test.moduleTestEnvironment = config.currentModuleTestEnviroment;
332   - test.stack = sourceFromStacktrace( 2 );
333 347 test.queue();
334 348 },
335 349
@@ -338,8 +352,59 @@ QUnit = {
338 352 config.current.expected = asserts;
339 353 },
340 354
341   - // Asserts true.
342   - // @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
  355 + start: function( count ) {
  356 + config.semaphore -= count || 1;
  357 + // don't start until equal number of stop-calls
  358 + if ( config.semaphore > 0 ) {
  359 + return;
  360 + }
  361 + // ignore if start is called more often then stop
  362 + if ( config.semaphore < 0 ) {
  363 + config.semaphore = 0;
  364 + }
  365 + // A slight delay, to avoid any current callbacks
  366 + if ( defined.setTimeout ) {
  367 + window.setTimeout(function() {
  368 + if ( config.semaphore > 0 ) {
  369 + return;
  370 + }
  371 + if ( config.timeout ) {
  372 + clearTimeout( config.timeout );
  373 + }
  374 +
  375 + config.blocking = false;
  376 + process( true );
  377 + }, 13);
  378 + } else {
  379 + config.blocking = false;
  380 + process( true );
  381 + }
  382 + },
  383 +
  384 + stop: function( count ) {
  385 + config.semaphore += count || 1;
  386 + config.blocking = true;
  387 +
  388 + if ( config.testTimeout && defined.setTimeout ) {
  389 + clearTimeout( config.timeout );
  390 + config.timeout = window.setTimeout(function() {
  391 + QUnit.ok( false, "Test timed out" );
  392 + config.semaphore = 1;
  393 + QUnit.start();
  394 + }, config.testTimeout );
  395 + }
  396 + }
  397 +};
  398 +
  399 +// Asssert helpers
  400 +// All of these must call either QUnit.push() or manually do:
  401 +// - runLoggingCallbacks( "log", .. );
  402 +// - config.current.assertions.push({ .. });
  403 +QUnit.assert = {
  404 + /**
  405 + * Asserts rough true-ish result.
  406 + * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
  407 + */
343 408 ok: function( result, msg ) {
344 409 if ( !config.current ) {
345 410 throw new Error( "ok() assertion outside test context, was " + sourceFromStacktrace(2) );
@@ -369,8 +434,11 @@ QUnit = {
369 434 });
370 435 },
371 436
372   - // Checks that the first two arguments are equal, with an optional message. Prints out both actual and expected values.
373   - // @example equal( format( "Received {0} bytes.", 2), "Received 2 bytes." );
  437 + /**
  438 + * Assert that the first two arguments are equal, with an optional message.
  439 + * Prints out both actual and expected values.
  440 + * @example equal( format( "Received {0} bytes.", 2), "Received 2 bytes.", "format() replaces {0} with next argument" );
  441 + */
374 442 equal: function( actual, expected, message ) {
375 443 QUnit.push( expected == actual, actual, expected, message );
376 444 },
@@ -404,11 +472,13 @@ QUnit = {
404 472 expected = null;
405 473 }
406 474
  475 + config.current.ignoreGlobalErrors = true;
407 476 try {
408 477 block.call( config.current.testEnvironment );
409 478 } catch (e) {
410 479 actual = e;
411 480 }
  481 + config.current.ignoreGlobalErrors = false;
412 482
413 483 if ( actual ) {
414 484 // we don't want to validate thrown error
@@ -426,51 +496,22 @@ QUnit = {
426 496 }
427 497 }
428 498
429   - QUnit.ok( ok, message );
430   - },
431   -
432   - start: function( count ) {
433   - config.semaphore -= count || 1;
434   - // don't start until equal number of stop-calls
435   - if ( config.semaphore > 0 ) {
436   - return;
437   - }
438   - // ignore if start is called more often then stop
439   - if ( config.semaphore < 0 ) {
440   - config.semaphore = 0;
441   - }
442   - // A slight delay, to avoid any current callbacks
443   - if ( defined.setTimeout ) {
444   - window.setTimeout(function() {
445   - if ( config.semaphore > 0 ) {
446   - return;
447   - }
448   - if ( config.timeout ) {
449   - clearTimeout( config.timeout );
450   - }
451   -
452   - config.blocking = false;
453   - process( true );
454   - }, 13);
455   - } else {
456   - config.blocking = false;
457   - process( true );
458   - }
459   - },
  499 + QUnit.push( ok, actual, null, message );
  500 + }
  501 +};
460 502
461   - stop: function( count ) {
462   - config.semaphore += count || 1;
463   - config.blocking = true;
  503 +// @deprecated: Kept assertion helpers in root for backwards compatibility
  504 +extend( QUnit, QUnit.assert );
464 505
465   - if ( config.testTimeout && defined.setTimeout ) {
466   - clearTimeout( config.timeout );
467   - config.timeout = window.setTimeout(function() {
468   - QUnit.ok( false, "Test timed out" );
469   - config.semaphore = 1;
470   - QUnit.start();
471   - }, config.testTimeout );
472   - }
473   - }
  506 +/**
  507 + * @deprecated: Kept for backwards compatibility
  508 + * next step: remove entirely
  509 + */
  510 +QUnit.equals = function() {
  511 + QUnit.push( false, false, false, "QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead" );
  512 +};
  513 +QUnit.same = function() {
  514 + QUnit.push( false, false, false, "QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead" );
474 515 };
475 516
476 517 // We want access to the constructor's prototype
@@ -482,17 +523,11 @@ QUnit = {
482 523 QUnit.constructor = F;
483 524 }());
484 525
485   -// deprecated; still export them to window to provide clear error messages
486   -// next step: remove entirely
487   -QUnit.equals = function() {
488   - QUnit.push( false, false, false, "QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead" );
489   -};
490   -QUnit.same = function() {
491   - QUnit.push( false, false, false, "QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead" );
492   -};
493   -
494   -// Maintain internal state
495   -// `config` initialized at top of scope
  526 +/**
  527 + * Config object: Maintain internal state
  528 + * Later exposed as QUnit.config
  529 + * `config` initialized at top of scope
  530 + */
496 531 config = {
497 532 // The queue of tests to run
498 533 queue: [],
@@ -511,6 +546,9 @@ config = {
511 546 // by default, modify document.title when suite is done
512 547 altertitle: true,
513 548
  549 + // when enabled, all tests must call expect()
  550 + requireExpects: false,
  551 +
514 552 urlConfig: [ "noglobals", "notrycatch" ],
515 553
516 554 // logging callback queues
@@ -523,7 +561,7 @@ config = {
523 561 moduleDone: []
524 562 };
525 563
526   -// Load paramaters
  564 +// Initialize more QUnit.config and QUnit.urlParams
527 565 (function() {
528 566 var i,
529 567 location = window.location || { search: "", protocol: "file:" },
@@ -543,20 +581,30 @@ config = {
543 581 }
544 582
545 583 QUnit.urlParams = urlParams;
  584 +
  585 + // String search anywhere in moduleName+testName
546 586 config.filter = urlParams.filter;
547 587
  588 + // Exact match of the module name
  589 + config.module = urlParams.module;
  590 +
  591 + config.testNumber = parseInt( urlParams.testNumber, 10 ) || null;
  592 +
548 593 // Figure out if we're running the tests from a server or not
549 594 QUnit.isLocal = location.protocol === "file:";
550 595 }());
551 596
552   -// Expose the API as global variables, unless an 'exports' object exists,
553   -// in that case we assume we're in CommonJS - export everything at the end
  597 +// Export global variables, unless an 'exports' object exists,
  598 +// in that case we assume we're in CommonJS (dealt with on the bottom of the script)
554 599 if ( typeof exports === "undefined" ) {
555 600 extend( window, QUnit );
  601 +
  602 + // Expose QUnit object
556 603 window.QUnit = QUnit;
557 604 }
558 605
559   -// define these after exposing globals to keep them in these QUnit namespace only
  606 +// Extend QUnit object,
  607 +// these after set here because they should not be exposed as global functions
560 608 extend( QUnit, {
561 609 config: config,
562 610
@@ -723,6 +771,10 @@ extend( QUnit, {
723 771 },
724 772
725 773 pushFailure: function( message, source ) {
  774 + if ( !config.current ) {
  775 + throw new Error( "pushFailure() assertion outside test context, was " + sourceFromStacktrace(2) );
  776 + }
  777 +
726 778 var output,
727 779 details = {
728 780 result: false,
@@ -764,25 +816,37 @@ extend( QUnit, {
764 816 extend: extend,
765 817 id: id,
766 818 addEvent: addEvent
  819 + // load, equiv, jsDump, diff: Attached later
767 820 });
768 821
769   -// QUnit.constructor is set to the empty F() above so that we can add to it's prototype later
770   -// Doing this allows us to tell if the following methods have been overwritten on the actual
771   -// QUnit object, which is a deprecated way of using the callbacks.
  822 +/**
  823 + * @deprecated: Created for backwards compatibility with test runner that set the hook function
  824 + * into QUnit.{hook}, instead of invoking it and passing the hook function.
  825 + * QUnit.constructor is set to the empty F() above so that we can add to it's prototype here.
  826 + * Doing this allows us to tell if the following methods have been overwritten on the actual
  827 + * QUnit object.
  828 + */
772 829 extend( QUnit.constructor.prototype, {
  830 +
773 831 // Logging callbacks; all receive a single argument with the listed properties
774 832 // run test/logs.html for any related changes
775 833 begin: registerLoggingCallback( "begin" ),
  834 +
776 835 // done: { failed, passed, total, runtime }
777 836 done: registerLoggingCallback( "done" ),
  837 +
778 838 // log: { result, actual, expected, message }
779 839 log: registerLoggingCallback( "log" ),
  840 +
780 841 // testStart: { name }
781 842 testStart: registerLoggingCallback( "testStart" ),
  843 +
782 844 // testDone: { name, failed, passed, total }
783 845 testDone: registerLoggingCallback( "testDone" ),
  846 +
784 847 // moduleStart: { name }
785 848 moduleStart: registerLoggingCallback( "moduleStart" ),
  849 +
786 850 // moduleDone: { name, failed, passed, total }
787 851 moduleDone: registerLoggingCallback( "moduleDone" )
788 852 });
@@ -884,15 +948,36 @@ QUnit.load = function() {
884 948
885 949 addEvent( window, "load", QUnit.load );
886 950
887   -// addEvent(window, "error" ) gives us a useless event object
888   -window.onerror = function( message, file, line ) {
889   - if ( QUnit.config.current ) {
890   - QUnit.pushFailure( message, file + ":" + line );
891   - } else {
892   - QUnit.test( "global failure", function() {
893   - QUnit.pushFailure( message, file + ":" + line );
894   - });
  951 +// `onErrorFnPrev` initialized at top of scope
  952 +// Preserve other handlers
  953 +onErrorFnPrev = window.onerror;
  954 +
  955 +// Cover uncaught exceptions
  956 +// Returning true will surpress the default browser handler,
  957 +// returning false will let it run.
  958 +window.onerror = function ( error, filePath, linerNr ) {
  959 + var ret = false;
  960 + if ( onErrorFnPrev ) {
  961 + ret = onErrorFnPrev( error, filePath, linerNr );
895 962 }
  963 +
  964 + // Treat return value as window.onerror itself does,
  965 + // Only do our handling if not surpressed.
  966 + if ( ret !== true ) {
  967 + if ( QUnit.config.current ) {
  968 + if ( QUnit.config.current.ignoreGlobalErrors ) {
  969 + return true;
  970 + }
  971 + QUnit.pushFailure( error, filePath + ":" + linerNr );
  972 + } else {
  973 + QUnit.test( "global failure", function() {
  974 + QUnit.pushFailure( error, filePath + ":" + linerNr );
  975 + });
  976 + }
  977 + return false;
  978 + }
  979 +
  980 + return ret;
896 981 };
897 982
898 983 function done() {
@@ -962,39 +1047,46 @@ function done() {
962 1047 });
963 1048 }
964 1049
965   -function validTest( name ) {
966   - var not,
967   - filter = config.filter,
968   - run = false;
  1050 +/** @return Boolean: true if this test should be ran */
  1051 +function validTest( test ) {
  1052 + var include,
  1053 + filter = config.filter && config.filter.toLowerCase(),
  1054 + module = config.module,
  1055 + fullName = (test.module + ": " + test.testName).toLowerCase();
969 1056
970   - if ( !filter ) {
971   - return true;
  1057 + if ( config.testNumber ) {
  1058 + return test.testNumber === config.testNumber;
972 1059 }
973 1060
974   - not = filter.charAt( 0 ) === "!";
  1061 + if ( module && test.module !== module ) {
  1062 + return false;
  1063 + }
975 1064
976   - if ( not ) {
977   - filter = filter.slice( 1 );
  1065 + if ( !filter ) {
  1066 + return true;
978 1067 }
979 1068
980   - if ( name.indexOf( filter ) !== -1 ) {
981   - return !not;
  1069 + include = filter.charAt( 0 ) !== "!";
  1070 + if ( !include ) {
  1071 + filter = filter.slice( 1 );
982 1072 }
983 1073
984   - if ( not ) {
985   - run = true;
  1074 + // If the filter matches, we need to honour include
  1075 + if ( fullName.indexOf( filter ) !== -1 ) {
  1076 + return include;
986 1077 }
987 1078
988   - return run;
  1079 + // Otherwise, do the opposite
  1080 + return !include;
989 1081 }
990 1082
991 1083 // so far supports only Firefox, Chrome and Opera (buggy), Safari (for real exceptions)
992 1084 // Later Safari and IE10 are supposed to support error.stack as well
993 1085 // See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack
994 1086 function extractStacktrace( e, offset ) {
995   - offset = offset || 3;
  1087 + offset = offset === undefined ? 3 : offset;
996 1088
997   - var stack;
  1089 + var stack, include, i, regex;
998 1090
999 1091 if ( e.stacktrace ) {
1000 1092 // Opera
@@ -1005,6 +1097,18 @@ function extractStacktrace( e, offset ) {
1005 1097 if (/^error$/i.test( stack[0] ) ) {
1006 1098 stack.shift();
1007 1099 }
  1100 + if ( fileName ) {
  1101 + include = [];
  1102 + for ( i = offset; i < stack.length; i++ ) {
  1103 + if ( stack[ i ].indexOf( fileName ) != -1 ) {
  1104 + break;
  1105 + }
  1106 + include.push( stack[ i ] );
  1107 + }
  1108 + if ( include.length ) {
  1109 + return include.join( "\n" );
  1110 + }
  1111 + }
1008 1112 return stack[ offset ];
1009 1113 } else if ( e.sourceURL ) {
1010 1114 // Safari, PhantomJS
@@ -1419,11 +1523,11 @@ QUnit.jsDump = (function() {
1419 1523 type = "null";
1420 1524 } else if ( typeof obj === "undefined" ) {
1421 1525 type = "undefined";
1422   - } else if ( QUnit.is( "RegExp", obj) ) {
  1526 + } else if ( QUnit.is( "regexp", obj) ) {
1423 1527 type = "regexp";
1424   - } else if ( QUnit.is( "Date", obj) ) {
  1528 + } else if ( QUnit.is( "date", obj) ) {
1425 1529 type = "date";
1426   - } else if ( QUnit.is( "Function", obj) ) {
  1530 + } else if ( QUnit.is( "function", obj) ) {
1427 1531 type = "function";
1428 1532 } else if ( typeof obj.setInterval !== undefined && typeof obj.document !== "undefined" && typeof obj.nodeType === "undefined" ) {
1429 1533 type = "window";
4 test/views/qunit.erb
@@ -2,10 +2,10 @@
2 2 <html lang="en">
3 3 <head>
4 4 <meta charset="utf-8">
5   - <link rel="stylesheet" href="/test/qunit-1.6.0.css">
  5 + <link rel="stylesheet" href="/test/qunit.css">
6 6
7 7 <script type="text/javascript" src="/test/jquery-1.7.2.js"></script>
8   - <script type="text/javascript" src="/test/qunit-1.6.0.js"></script>
  8 + <script type="text/javascript" src="/test/qunit.js"></script>
9 9 <script type="text/javascript" src="/jquery.pjax.js"></script>
10 10 <script type="text/javascript" src="/unit/pjax.js"></script>
11 11 <script type="text/javascript" src="/unit/fn_pjax.js"></script>

No commit comments for this range

Something went wrong with that request. Please try again.