Index: trunk/extensions/VisualEditor/modules/qunit/qunit.css |
— | — | @@ -1,9 +1,9 @@ |
2 | 2 | /** |
3 | | - * QUnit 1.2.0pre - A JavaScript Unit Testing Framework |
| 3 | + * QUnit v1.4.0pre - 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) 2012 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 | */ |
— | — | @@ -54,6 +54,10 @@ |
55 | 55 | color: #fff; |
56 | 56 | } |
57 | 57 | |
| 58 | +#qunit-header label { |
| 59 | + display: inline-block; |
| 60 | +} |
| 61 | + |
58 | 62 | #qunit-banner { |
59 | 63 | height: 5px; |
60 | 64 | } |
— | — | @@ -223,4 +227,6 @@ |
224 | 228 | position: absolute; |
225 | 229 | top: -10000px; |
226 | 230 | left: -10000px; |
| 231 | + width: 1000px; |
| 232 | + height: 1000px; |
227 | 233 | } |
Index: trunk/extensions/VisualEditor/modules/qunit/qunit.js |
— | — | @@ -1,9 +1,9 @@ |
2 | 2 | /** |
3 | | - * QUnit 1.2.0pre - A JavaScript Unit Testing Framework |
| 3 | + * QUnit v1.4.0pre - 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) 2012 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 | */ |
— | — | @@ -13,23 +13,25 @@ |
14 | 14 | var defined = { |
15 | 15 | setTimeout: typeof window.setTimeout !== "undefined", |
16 | 16 | sessionStorage: (function() { |
| 17 | + var x = "qunit-test-string"; |
17 | 18 | try { |
18 | | - return !!sessionStorage.getItem; |
| 19 | + sessionStorage.setItem(x, x); |
| 20 | + sessionStorage.removeItem(x); |
| 21 | + return true; |
19 | 22 | } catch(e) { |
20 | 23 | return false; |
21 | 24 | } |
22 | | - })() |
| 25 | + }()) |
23 | 26 | }; |
24 | 27 | |
25 | 28 | var testId = 0, |
26 | 29 | toString = Object.prototype.toString, |
27 | 30 | hasOwn = Object.prototype.hasOwnProperty; |
28 | 31 | |
29 | | -var Test = function(name, testName, expected, testEnvironmentArg, async, callback) { |
| 32 | +var Test = function(name, testName, expected, async, callback) { |
30 | 33 | this.name = name; |
31 | 34 | this.testName = testName; |
32 | 35 | this.expected = expected; |
33 | | - this.testEnvironmentArg = testEnvironmentArg; |
34 | 36 | this.async = async; |
35 | 37 | this.callback = callback; |
36 | 38 | this.assertions = []; |
— | — | @@ -62,6 +64,10 @@ |
63 | 65 | runLoggingCallbacks( 'moduleStart', QUnit, { |
64 | 66 | name: this.module |
65 | 67 | } ); |
| 68 | + } else if (config.autorun) { |
| 69 | + runLoggingCallbacks( 'moduleStart', QUnit, { |
| 70 | + name: this.module |
| 71 | + } ); |
66 | 72 | } |
67 | 73 | |
68 | 74 | config.current = this; |
— | — | @@ -69,9 +75,6 @@ |
70 | 76 | setup: function() {}, |
71 | 77 | teardown: function() {} |
72 | 78 | }, this.moduleTestEnvironment); |
73 | | - if (this.testEnvironmentArg) { |
74 | | - extend(this.testEnvironment, this.testEnvironmentArg); |
75 | | - } |
76 | 79 | |
77 | 80 | runLoggingCallbacks( 'testStart', QUnit, { |
78 | 81 | name: this.testName, |
— | — | @@ -82,14 +85,17 @@ |
83 | 86 | // TODO why?? |
84 | 87 | QUnit.current_testEnvironment = this.testEnvironment; |
85 | 88 | |
| 89 | + if ( !config.pollution ) { |
| 90 | + saveGlobal(); |
| 91 | + } |
| 92 | + if ( config.notrycatch ) { |
| 93 | + this.testEnvironment.setup.call(this.testEnvironment); |
| 94 | + return; |
| 95 | + } |
86 | 96 | try { |
87 | | - if ( !config.pollution ) { |
88 | | - saveGlobal(); |
89 | | - } |
90 | | - |
91 | 97 | this.testEnvironment.setup.call(this.testEnvironment); |
92 | 98 | } catch(e) { |
93 | | - QUnit.ok( false, "Setup failed on " + this.testName + ": " + e.message ); |
| 99 | + QUnit.pushFailure( "Setup failed on " + this.testName + ": " + e.message, extractStacktrace( e, 1 ) ); |
94 | 100 | } |
95 | 101 | }, |
96 | 102 | run: function() { |
— | — | @@ -105,8 +111,7 @@ |
106 | 112 | try { |
107 | 113 | this.callback.call(this.testEnvironment); |
108 | 114 | } catch(e) { |
109 | | - fail("Test " + this.testName + " died, exception and test follows", e, this.callback); |
110 | | - QUnit.ok( false, "Died on test #" + (this.assertions.length + 1) + ": " + e.message + " - " + QUnit.jsDump.parse(e) ); |
| 115 | + QUnit.pushFailure( "Died on test #" + (this.assertions.length + 1) + ": " + e.message, extractStacktrace( e, 1 ) ); |
111 | 116 | // else next test will carry the responsibility |
112 | 117 | saveGlobal(); |
113 | 118 | |
— | — | @@ -118,20 +123,28 @@ |
119 | 124 | }, |
120 | 125 | teardown: function() { |
121 | 126 | config.current = this; |
122 | | - try { |
| 127 | + if ( config.notrycatch ) { |
123 | 128 | this.testEnvironment.teardown.call(this.testEnvironment); |
124 | | - checkPollution(); |
125 | | - } catch(e) { |
126 | | - QUnit.ok( false, "Teardown failed on " + this.testName + ": " + e.message ); |
| 129 | + return; |
| 130 | + } else { |
| 131 | + try { |
| 132 | + this.testEnvironment.teardown.call(this.testEnvironment); |
| 133 | + } catch(e) { |
| 134 | + QUnit.pushFailure( "Teardown failed on " + this.testName + ": " + e.message, extractStacktrace( e, 1 ) ); |
| 135 | + } |
127 | 136 | } |
| 137 | + checkPollution(); |
128 | 138 | }, |
129 | 139 | finish: function() { |
130 | 140 | config.current = this; |
131 | 141 | if ( this.expected != null && this.expected != this.assertions.length ) { |
132 | | - QUnit.ok( false, "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run" ); |
| 142 | + QUnit.pushFailure( "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run" ); |
| 143 | + } else if ( this.expected == null && !this.assertions.length ) { |
| 144 | + QUnit.pushFailure( "Expected at least one assertion, but none were run - call expect(0) to accept zero assertions." ); |
133 | 145 | } |
134 | 146 | |
135 | 147 | var good = 0, bad = 0, |
| 148 | + li, i, |
136 | 149 | tests = id("qunit-tests"); |
137 | 150 | |
138 | 151 | config.stats.all += this.assertions.length; |
— | — | @@ -140,10 +153,10 @@ |
141 | 154 | if ( tests ) { |
142 | 155 | var ol = document.createElement("ol"); |
143 | 156 | |
144 | | - for ( var i = 0; i < this.assertions.length; i++ ) { |
| 157 | + for ( i = 0; i < this.assertions.length; i++ ) { |
145 | 158 | var assertion = this.assertions[i]; |
146 | 159 | |
147 | | - var li = document.createElement("li"); |
| 160 | + li = document.createElement("li"); |
148 | 161 | li.className = assertion.result ? "pass" : "fail"; |
149 | 162 | li.innerHTML = assertion.message || (assertion.result ? "okay" : "failed"); |
150 | 163 | ol.appendChild( li ); |
— | — | @@ -166,7 +179,7 @@ |
167 | 180 | } |
168 | 181 | } |
169 | 182 | |
170 | | - if (bad == 0) { |
| 183 | + if (bad === 0) { |
171 | 184 | ol.style.display = "none"; |
172 | 185 | } |
173 | 186 | |
— | — | @@ -193,7 +206,7 @@ |
194 | 207 | } |
195 | 208 | }); |
196 | 209 | |
197 | | - var li = id(this.id); |
| 210 | + li = id(this.id); |
198 | 211 | li.className = bad ? "fail" : "pass"; |
199 | 212 | li.removeChild( li.firstChild ); |
200 | 213 | li.appendChild( b ); |
— | — | @@ -201,7 +214,7 @@ |
202 | 215 | li.appendChild( ol ); |
203 | 216 | |
204 | 217 | } else { |
205 | | - for ( var i = 0; i < this.assertions.length; i++ ) { |
| 218 | + for ( i = 0; i < this.assertions.length; i++ ) { |
206 | 219 | if ( !this.assertions[i].result ) { |
207 | 220 | bad++; |
208 | 221 | config.stats.bad++; |
— | — | @@ -210,11 +223,7 @@ |
211 | 224 | } |
212 | 225 | } |
213 | 226 | |
214 | | - try { |
215 | | - QUnit.reset(); |
216 | | - } catch(e) { |
217 | | - fail("reset() failed, following Test " + this.testName + ", exception and reset fn follows", e, QUnit.reset); |
218 | | - } |
| 227 | + QUnit.reset(); |
219 | 228 | |
220 | 229 | runLoggingCallbacks( 'testDone', QUnit, { |
221 | 230 | name: this.testName, |
— | — | @@ -251,7 +260,7 @@ |
252 | 261 | run(); |
253 | 262 | } else { |
254 | 263 | synchronize(run, true); |
255 | | - }; |
| 264 | + } |
256 | 265 | } |
257 | 266 | |
258 | 267 | }; |
— | — | @@ -274,17 +283,12 @@ |
275 | 284 | }, |
276 | 285 | |
277 | 286 | test: function(testName, expected, callback, async) { |
278 | | - var name = '<span class="test-name">' + testName + '</span>', testEnvironmentArg; |
| 287 | + var name = '<span class="test-name">' + escapeInnerText(testName) + '</span>'; |
279 | 288 | |
280 | 289 | if ( arguments.length === 2 ) { |
281 | 290 | callback = expected; |
282 | 291 | expected = null; |
283 | 292 | } |
284 | | - // is 2nd argument a testEnvironment? |
285 | | - if ( expected && typeof expected === 'object') { |
286 | | - testEnvironmentArg = expected; |
287 | | - expected = null; |
288 | | - } |
289 | 293 | |
290 | 294 | if ( config.currentModule ) { |
291 | 295 | name = '<span class="module-name">' + config.currentModule + "</span>: " + name; |
— | — | @@ -294,49 +298,45 @@ |
295 | 299 | return; |
296 | 300 | } |
297 | 301 | |
298 | | - var test = new Test(name, testName, expected, testEnvironmentArg, async, callback); |
| 302 | + var test = new Test(name, testName, expected, async, callback); |
299 | 303 | test.module = config.currentModule; |
300 | 304 | test.moduleTestEnvironment = config.currentModuleTestEnviroment; |
301 | 305 | test.queue(); |
302 | 306 | }, |
303 | 307 | |
304 | | - /** |
305 | | - * Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through. |
306 | | - */ |
| 308 | + // Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through. |
307 | 309 | expect: function(asserts) { |
308 | 310 | config.current.expected = asserts; |
309 | 311 | }, |
310 | 312 | |
311 | | - /** |
312 | | - * Asserts true. |
313 | | - * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" ); |
314 | | - */ |
315 | | - ok: function(a, msg) { |
316 | | - a = !!a; |
| 313 | + // Asserts true. |
| 314 | + // @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" ); |
| 315 | + ok: function(result, msg) { |
| 316 | + if (!config.current) { |
| 317 | + throw new Error("ok() assertion outside test context, was " + sourceFromStacktrace(2)); |
| 318 | + } |
| 319 | + result = !!result; |
317 | 320 | var details = { |
318 | | - result: a, |
| 321 | + result: result, |
319 | 322 | message: msg |
320 | 323 | }; |
321 | | - msg = escapeInnerText(msg); |
| 324 | + msg = escapeInnerText(msg || (result ? "okay" : "failed")); |
| 325 | + if ( !result ) { |
| 326 | + var source = sourceFromStacktrace(2); |
| 327 | + if (source) { |
| 328 | + details.source = source; |
| 329 | + msg += '<table><tr class="test-source"><th>Source: </th><td><pre>' + escapeInnerText(source) + '</pre></td></tr></table>'; |
| 330 | + } |
| 331 | + } |
322 | 332 | runLoggingCallbacks( 'log', QUnit, details ); |
323 | 333 | config.current.assertions.push({ |
324 | | - result: a, |
| 334 | + result: result, |
325 | 335 | message: msg |
326 | 336 | }); |
327 | 337 | }, |
328 | 338 | |
329 | | - /** |
330 | | - * Checks that the first two arguments are equal, with an optional message. |
331 | | - * Prints out both actual and expected values. |
332 | | - * |
333 | | - * Prefered to ok( actual == expected, message ) |
334 | | - * |
335 | | - * @example equal( format("Received {0} bytes.", 2), "Received 2 bytes." ); |
336 | | - * |
337 | | - * @param Object actual |
338 | | - * @param Object expected |
339 | | - * @param String message (optional) |
340 | | - */ |
| 339 | + // Checks that the first two arguments are equal, with an optional message. Prints out both actual and expected values. |
| 340 | + // @example equal( format("Received {0} bytes.", 2), "Received 2 bytes." ); |
341 | 341 | equal: function(actual, expected, message) { |
342 | 342 | QUnit.push(expected == actual, actual, expected, message); |
343 | 343 | }, |
— | — | @@ -440,16 +440,21 @@ |
441 | 441 | |
442 | 442 | //We want access to the constructor's prototype |
443 | 443 | (function() { |
444 | | - function F(){}; |
| 444 | + function F(){} |
445 | 445 | F.prototype = QUnit; |
446 | 446 | QUnit = new F(); |
447 | 447 | //Make F QUnit's constructor so that we can add to the prototype later |
448 | 448 | QUnit.constructor = F; |
449 | | -})(); |
| 449 | +}()); |
450 | 450 | |
451 | | -// Backwards compatibility, deprecated |
452 | | -QUnit.equals = QUnit.equal; |
453 | | -QUnit.same = QUnit.deepEqual; |
| 451 | +// deprecated; still export them to window to provide clear error messages |
| 452 | +// next step: remove entirely |
| 453 | +QUnit.equals = function() { |
| 454 | + QUnit.push(false, false, false, "QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead"); |
| 455 | +}; |
| 456 | +QUnit.same = function() { |
| 457 | + QUnit.push(false, false, false, "QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead"); |
| 458 | +}; |
454 | 459 | |
455 | 460 | // Maintain internal state |
456 | 461 | var config = { |
— | — | @@ -504,17 +509,14 @@ |
505 | 510 | config.filter = urlParams.filter; |
506 | 511 | |
507 | 512 | // Figure out if we're running the tests from a server or not |
508 | | - QUnit.isLocal = !!(location.protocol === 'file:'); |
509 | | -})(); |
| 513 | + QUnit.isLocal = location.protocol === 'file:'; |
| 514 | +}()); |
510 | 515 | |
511 | 516 | // Expose the API as global variables, unless an 'exports' |
512 | | -// object exists, in that case we assume we're in CommonJS |
| 517 | +// object exists, in that case we assume we're in CommonJS - export everything at the end |
513 | 518 | if ( typeof exports === "undefined" || typeof require === "undefined" ) { |
514 | 519 | extend(window, QUnit); |
515 | 520 | window.QUnit = QUnit; |
516 | | -} else { |
517 | | - extend(exports, QUnit); |
518 | | - exports.QUnit = QUnit; |
519 | 521 | } |
520 | 522 | |
521 | 523 | // define these after exposing globals to keep them in these QUnit namespace only |
— | — | @@ -526,7 +528,7 @@ |
527 | 529 | extend(config, { |
528 | 530 | stats: { all: 0, bad: 0 }, |
529 | 531 | moduleStats: { all: 0, bad: 0 }, |
530 | | - started: +new Date, |
| 532 | + started: +new Date(), |
531 | 533 | updateRate: 1000, |
532 | 534 | blocking: false, |
533 | 535 | autostart: true, |
— | — | @@ -536,6 +538,16 @@ |
537 | 539 | semaphore: 0 |
538 | 540 | }); |
539 | 541 | |
| 542 | + var qunit = id( "qunit" ); |
| 543 | + if ( qunit ) { |
| 544 | + qunit.innerHTML = |
| 545 | + '<h1 id="qunit-header">' + escapeInnerText( document.title ) + '</h1>' + |
| 546 | + '<h2 id="qunit-banner"></h2>' + |
| 547 | + '<div id="qunit-testrunner-toolbar"></div>' + |
| 548 | + '<h2 id="qunit-userAgent"></h2>' + |
| 549 | + '<ol id="qunit-tests"></ol>'; |
| 550 | + } |
| 551 | + |
540 | 552 | var tests = id( "qunit-tests" ), |
541 | 553 | banner = id( "qunit-banner" ), |
542 | 554 | result = id( "qunit-testresult" ); |
— | — | @@ -561,11 +573,8 @@ |
562 | 574 | } |
563 | 575 | }, |
564 | 576 | |
565 | | - /** |
566 | | - * Resets the test setup. Useful for tests that modify the DOM. |
567 | | - * |
568 | | - * If jQuery is available, uses jQuery's html(), otherwise just innerHTML. |
569 | | - */ |
| 577 | + // Resets the test setup. Useful for tests that modify the DOM. |
| 578 | + // If jQuery is available, uses jQuery's html(), otherwise just innerHTML. |
570 | 579 | reset: function() { |
571 | 580 | if ( window.jQuery ) { |
572 | 581 | jQuery( "#qunit-fixture" ).html( config.fixture ); |
— | — | @@ -577,14 +586,8 @@ |
578 | 587 | } |
579 | 588 | }, |
580 | 589 | |
581 | | - /** |
582 | | - * Trigger an event on an element. |
583 | | - * |
584 | | - * @example triggerEvent( document.body, "click" ); |
585 | | - * |
586 | | - * @param DOMElement elem |
587 | | - * @param String type |
588 | | - */ |
| 590 | + // Trigger an event on an element. |
| 591 | + // @example triggerEvent( document.body, "click" ); |
589 | 592 | triggerEvent: function( elem, type, event ) { |
590 | 593 | if ( document.createEvent ) { |
591 | 594 | event = document.createEvent("MouseEvents"); |
— | — | @@ -615,19 +618,18 @@ |
616 | 619 | var type = toString.call( obj ).match(/^\[object\s(.*)\]$/)[1] || ''; |
617 | 620 | |
618 | 621 | switch (type) { |
619 | | - case 'Number': |
620 | | - if (isNaN(obj)) { |
621 | | - return "nan"; |
622 | | - } else { |
623 | | - return "number"; |
624 | | - } |
625 | | - case 'String': |
626 | | - case 'Boolean': |
627 | | - case 'Array': |
628 | | - case 'Date': |
629 | | - case 'RegExp': |
630 | | - case 'Function': |
631 | | - return type.toLowerCase(); |
| 622 | + case 'Number': |
| 623 | + if (isNaN(obj)) { |
| 624 | + return "nan"; |
| 625 | + } |
| 626 | + return "number"; |
| 627 | + case 'String': |
| 628 | + case 'Boolean': |
| 629 | + case 'Array': |
| 630 | + case 'Date': |
| 631 | + case 'RegExp': |
| 632 | + case 'Function': |
| 633 | + return type.toLowerCase(); |
632 | 634 | } |
633 | 635 | if (typeof obj === "object") { |
634 | 636 | return "object"; |
— | — | @@ -636,6 +638,9 @@ |
637 | 639 | }, |
638 | 640 | |
639 | 641 | push: function(result, actual, expected, message) { |
| 642 | + if (!config.current) { |
| 643 | + throw new Error("assertion outside test context, was " + sourceFromStacktrace()); |
| 644 | + } |
640 | 645 | var details = { |
641 | 646 | result: result, |
642 | 647 | message: message, |
— | — | @@ -645,21 +650,22 @@ |
646 | 651 | |
647 | 652 | message = escapeInnerText(message) || (result ? "okay" : "failed"); |
648 | 653 | message = '<span class="test-message">' + message + "</span>"; |
649 | | - expected = escapeInnerText(QUnit.jsDump.parse(expected)); |
650 | | - actual = escapeInnerText(QUnit.jsDump.parse(actual)); |
651 | | - var output = message + '<table><tr class="test-expected"><th>Expected: </th><td><pre>' + expected + '</pre></td></tr>'; |
652 | | - if (actual != expected) { |
653 | | - output += '<tr class="test-actual"><th>Result: </th><td><pre>' + actual + '</pre></td></tr>'; |
654 | | - output += '<tr class="test-diff"><th>Diff: </th><td><pre>' + QUnit.diff(expected, actual) +'</pre></td></tr>'; |
655 | | - } |
| 654 | + var output = message; |
656 | 655 | if (!result) { |
| 656 | + expected = escapeInnerText(QUnit.jsDump.parse(expected)); |
| 657 | + actual = escapeInnerText(QUnit.jsDump.parse(actual)); |
| 658 | + output += '<table><tr class="test-expected"><th>Expected: </th><td><pre>' + expected + '</pre></td></tr>'; |
| 659 | + if (actual != expected) { |
| 660 | + output += '<tr class="test-actual"><th>Result: </th><td><pre>' + actual + '</pre></td></tr>'; |
| 661 | + output += '<tr class="test-diff"><th>Diff: </th><td><pre>' + QUnit.diff(expected, actual) +'</pre></td></tr>'; |
| 662 | + } |
657 | 663 | var source = sourceFromStacktrace(); |
658 | 664 | if (source) { |
659 | 665 | details.source = source; |
660 | 666 | output += '<tr class="test-source"><th>Source: </th><td><pre>' + escapeInnerText(source) + '</pre></td></tr>'; |
661 | 667 | } |
| 668 | + output += "</table>"; |
662 | 669 | } |
663 | | - output += "</table>"; |
664 | 670 | |
665 | 671 | runLoggingCallbacks( 'log', QUnit, details ); |
666 | 672 | |
— | — | @@ -669,6 +675,23 @@ |
670 | 676 | }); |
671 | 677 | }, |
672 | 678 | |
| 679 | + pushFailure: function(message, source) { |
| 680 | + var details = { |
| 681 | + result: false, |
| 682 | + message: message |
| 683 | + }; |
| 684 | + var output = escapeInnerText(message); |
| 685 | + if (source) { |
| 686 | + details.source = source; |
| 687 | + output += '<table><tr class="test-source"><th>Source: </th><td><pre>' + escapeInnerText(source) + '</pre></td></tr></table>'; |
| 688 | + } |
| 689 | + runLoggingCallbacks( 'log', QUnit, details ); |
| 690 | + config.current.assertions.push({ |
| 691 | + result: false, |
| 692 | + message: output |
| 693 | + }); |
| 694 | + }, |
| 695 | + |
673 | 696 | url: function( params ) { |
674 | 697 | params = extend( extend( {}, QUnit.urlParams ), params ); |
675 | 698 | var querystring = "?", |
— | — | @@ -724,7 +747,8 @@ |
725 | 748 | config.blocking = false; |
726 | 749 | |
727 | 750 | var urlConfigHtml = '', len = config.urlConfig.length; |
728 | | - for ( var i = 0, val; i < len, val = config.urlConfig[i]; i++ ) { |
| 751 | + for ( var i = 0, val; i < len; i++ ) { |
| 752 | + val = config.urlConfig[i]; |
729 | 753 | config[val] = QUnit.urlParams[val]; |
730 | 754 | urlConfigHtml += '<label><input name="' + val + '" type="checkbox"' + ( config[val] ? ' checked="checked"' : '' ) + '>' + val + '</label>'; |
731 | 755 | } |
— | — | @@ -792,10 +816,10 @@ |
793 | 817 | // addEvent(window, "error") gives us a useless event object |
794 | 818 | window.onerror = function( message, file, line ) { |
795 | 819 | if ( QUnit.config.current ) { |
796 | | - ok( false, message + ", " + file + ":" + line ); |
| 820 | + QUnit.pushFailure( message, file + ":" + line ); |
797 | 821 | } else { |
798 | | - test( "global failure", function() { |
799 | | - ok( false, message + ", " + file + ":" + line ); |
| 822 | + QUnit.test( "global failure", function() { |
| 823 | + QUnit.pushFailure( message, file + ":" + line ); |
800 | 824 | }); |
801 | 825 | } |
802 | 826 | }; |
— | — | @@ -815,7 +839,7 @@ |
816 | 840 | |
817 | 841 | var banner = id("qunit-banner"), |
818 | 842 | tests = id("qunit-tests"), |
819 | | - runtime = +new Date - config.started, |
| 843 | + runtime = +new Date() - config.started, |
820 | 844 | passed = config.stats.all - config.stats.bad, |
821 | 845 | html = [ |
822 | 846 | 'Tests completed in ', |
— | — | @@ -847,6 +871,15 @@ |
848 | 872 | ].join(" "); |
849 | 873 | } |
850 | 874 | |
| 875 | + // clear own sessionStorage items if all tests passed |
| 876 | + if ( config.reorder && defined.sessionStorage && config.stats.bad === 0 ) { |
| 877 | + for (var key in sessionStorage) { |
| 878 | + if (sessionStorage.hasOwnProperty(key) && key.indexOf("qunit-") === 0 ) { |
| 879 | + sessionStorage.removeItem(key); |
| 880 | + } |
| 881 | + } |
| 882 | + } |
| 883 | + |
851 | 884 | runLoggingCallbacks( 'done', QUnit, { |
852 | 885 | failed: config.stats.bad, |
853 | 886 | passed: passed, |
— | — | @@ -881,21 +914,34 @@ |
882 | 915 | |
883 | 916 | // so far supports only Firefox, Chrome and Opera (buggy) |
884 | 917 | // could be extended in the future to use something like https://github.com/csnover/TraceKit |
885 | | -function sourceFromStacktrace() { |
| 918 | +function extractStacktrace( e, offset ) { |
| 919 | + offset = offset || 3; |
| 920 | + if (e.stacktrace) { |
| 921 | + // Opera |
| 922 | + return e.stacktrace.split("\n")[offset + 3]; |
| 923 | + } else if (e.stack) { |
| 924 | + // Firefox, Chrome |
| 925 | + var stack = e.stack.split("\n"); |
| 926 | + if (/^error$/i.test(stack[0])) { |
| 927 | + stack.shift(); |
| 928 | + } |
| 929 | + return stack[offset]; |
| 930 | + } else if (e.sourceURL) { |
| 931 | + // Safari, PhantomJS |
| 932 | + // hopefully one day Safari provides actual stacktraces |
| 933 | + // exclude useless self-reference for generated Error objects |
| 934 | + if ( /qunit.js$/.test( e.sourceURL ) ) { |
| 935 | + return; |
| 936 | + } |
| 937 | + // for actual exceptions, this is useful |
| 938 | + return e.sourceURL + ":" + e.line; |
| 939 | + } |
| 940 | +} |
| 941 | +function sourceFromStacktrace(offset) { |
886 | 942 | try { |
887 | 943 | throw new Error(); |
888 | 944 | } catch ( e ) { |
889 | | - if (e.stacktrace) { |
890 | | - // Opera |
891 | | - return e.stacktrace.split("\n")[6]; |
892 | | - } else if (e.stack) { |
893 | | - // Firefox, Chrome |
894 | | - return e.stack.split("\n")[4]; |
895 | | - } else if (e.sourceURL) { |
896 | | - // Safari, PhantomJS |
897 | | - // TODO sourceURL points at the 'throw new Error' line above, useless |
898 | | - //return e.sourceURL + ":" + e.line; |
899 | | - } |
| 945 | + return extractStacktrace( e, offset ); |
900 | 946 | } |
901 | 947 | } |
902 | 948 | |
— | — | @@ -923,6 +969,9 @@ |
924 | 970 | } |
925 | 971 | |
926 | 972 | function process( last ) { |
| 973 | + function next() { |
| 974 | + process( last ); |
| 975 | + } |
927 | 976 | var start = new Date().getTime(); |
928 | 977 | config.depth = config.depth ? config.depth + 1 : 1; |
929 | 978 | |
— | — | @@ -930,9 +979,7 @@ |
931 | 980 | if ( !defined.setTimeout || config.updateRate <= 0 || ( ( new Date().getTime() - start ) < config.updateRate ) ) { |
932 | 981 | config.queue.shift()(); |
933 | 982 | } else { |
934 | | - window.setTimeout( function(){ |
935 | | - process( last ); |
936 | | - }, 13 ); |
| 983 | + window.setTimeout( next, 13 ); |
937 | 984 | break; |
938 | 985 | } |
939 | 986 | } |
— | — | @@ -961,12 +1008,12 @@ |
962 | 1009 | |
963 | 1010 | var newGlobals = diff( config.pollution, old ); |
964 | 1011 | if ( newGlobals.length > 0 ) { |
965 | | - ok( false, "Introduced global variable(s): " + newGlobals.join(", ") ); |
| 1012 | + QUnit.pushFailure( "Introduced global variable(s): " + newGlobals.join(", ") ); |
966 | 1013 | } |
967 | 1014 | |
968 | 1015 | var deletedGlobals = diff( old, config.pollution ); |
969 | 1016 | if ( deletedGlobals.length > 0 ) { |
970 | | - ok( false, "Deleted global variable(s): " + deletedGlobals.join(", ") ); |
| 1017 | + QUnit.pushFailure( "Deleted global variable(s): " + deletedGlobals.join(", ") ); |
971 | 1018 | } |
972 | 1019 | } |
973 | 1020 | |
— | — | @@ -985,17 +1032,6 @@ |
986 | 1033 | return result; |
987 | 1034 | } |
988 | 1035 | |
989 | | -function fail(message, exception, callback) { |
990 | | - if ( typeof console !== "undefined" && console.error && console.warn ) { |
991 | | - console.error(message); |
992 | | - console.error(exception); |
993 | | - console.warn(callback.toString()); |
994 | | - |
995 | | - } else if ( window.opera && opera.postError ) { |
996 | | - opera.postError(message, exception, callback.toString); |
997 | | - } |
998 | | -} |
999 | | - |
1000 | 1036 | function extend(a, b) { |
1001 | 1037 | for ( var prop in b ) { |
1002 | 1038 | if ( b[prop] === undefined ) { |
— | — | @@ -1047,7 +1083,7 @@ |
1048 | 1084 | |
1049 | 1085 | // Test for equality any JavaScript type. |
1050 | 1086 | // Author: Philippe Rathé <prathe@gmail.com> |
1051 | | -QUnit.equiv = function () { |
| 1087 | +QUnit.equiv = (function() { |
1052 | 1088 | |
1053 | 1089 | var innerEquiv; // the real equiv function |
1054 | 1090 | var callers = []; // stack to decide between skip/abort functions |
— | — | @@ -1065,8 +1101,12 @@ |
1066 | 1102 | } |
1067 | 1103 | } |
1068 | 1104 | |
1069 | | - var callbacks = function () { |
| 1105 | + var getProto = Object.getPrototypeOf || function (obj) { |
| 1106 | + return obj.__proto__; |
| 1107 | + }; |
1070 | 1108 | |
| 1109 | + var callbacks = (function () { |
| 1110 | + |
1071 | 1111 | // for string, boolean, number and null |
1072 | 1112 | function useStrictEquality(b, a) { |
1073 | 1113 | if (b instanceof a.constructor || a instanceof b.constructor) { |
— | — | @@ -1092,17 +1132,18 @@ |
1093 | 1133 | }, |
1094 | 1134 | |
1095 | 1135 | "date" : function(b, a) { |
1096 | | - return QUnit.objectType(b) === "date" |
1097 | | - && a.valueOf() === b.valueOf(); |
| 1136 | + return QUnit.objectType(b) === "date" && a.valueOf() === b.valueOf(); |
1098 | 1137 | }, |
1099 | 1138 | |
1100 | 1139 | "regexp" : function(b, a) { |
1101 | | - return QUnit.objectType(b) === "regexp" |
1102 | | - && a.source === b.source && // the regex itself |
1103 | | - a.global === b.global && // and its modifers |
1104 | | - // (gmi) ... |
1105 | | - a.ignoreCase === b.ignoreCase |
1106 | | - && a.multiline === b.multiline; |
| 1140 | + return QUnit.objectType(b) === "regexp" && |
| 1141 | + // the regex itself |
| 1142 | + a.source === b.source && |
| 1143 | + // and its modifers |
| 1144 | + a.global === b.global && |
| 1145 | + // (gmi) ... |
| 1146 | + a.ignoreCase === b.ignoreCase && |
| 1147 | + a.multiline === b.multiline; |
1107 | 1148 | }, |
1108 | 1149 | |
1109 | 1150 | // - skip when the property is a method of an instance (OOP) |
— | — | @@ -1118,7 +1159,7 @@ |
1119 | 1160 | var len; |
1120 | 1161 | |
1121 | 1162 | // b could be an object literal here |
1122 | | - if (!(QUnit.objectType(b) === "array")) { |
| 1163 | + if (QUnit.objectType(b) !== "array") { |
1123 | 1164 | return false; |
1124 | 1165 | } |
1125 | 1166 | |
— | — | @@ -1154,7 +1195,13 @@ |
1155 | 1196 | // comparing constructors is more strict than using |
1156 | 1197 | // instanceof |
1157 | 1198 | if (a.constructor !== b.constructor) { |
1158 | | - return false; |
| 1199 | + // Allow objects with no prototype to be equivalent to |
| 1200 | + // objects with Object as their constructor. |
| 1201 | + if (!((getProto(a) === null && getProto(b) === Object.prototype) || |
| 1202 | + (getProto(b) === null && getProto(a) === Object.prototype))) |
| 1203 | + { |
| 1204 | + return false; |
| 1205 | + } |
1159 | 1206 | } |
1160 | 1207 | |
1161 | 1208 | // stack constructor before traversing properties |
— | — | @@ -1166,9 +1213,10 @@ |
1167 | 1214 | // and go deep |
1168 | 1215 | loop = false; |
1169 | 1216 | for (j = 0; j < parents.length; j++) { |
1170 | | - if (parents[j] === a[i]) |
1171 | | - loop = true; // don't go down the same path |
1172 | | - // twice |
| 1217 | + if (parents[j] === a[i]) { |
| 1218 | + // don't go down the same path twice |
| 1219 | + loop = true; |
| 1220 | + } |
1173 | 1221 | } |
1174 | 1222 | aProperties.push(i); // collect a's properties |
1175 | 1223 | |
— | — | @@ -1186,12 +1234,10 @@ |
1187 | 1235 | } |
1188 | 1236 | |
1189 | 1237 | // Ensures identical properties name |
1190 | | - return eq |
1191 | | - && innerEquiv(aProperties.sort(), bProperties |
1192 | | - .sort()); |
| 1238 | + return eq && innerEquiv(aProperties.sort(), bProperties.sort()); |
1193 | 1239 | } |
1194 | 1240 | }; |
1195 | | - }(); |
| 1241 | + }()); |
1196 | 1242 | |
1197 | 1243 | innerEquiv = function() { // can take multiple arguments |
1198 | 1244 | var args = Array.prototype.slice.apply(arguments); |
— | — | @@ -1202,23 +1248,21 @@ |
1203 | 1249 | return (function(a, b) { |
1204 | 1250 | if (a === b) { |
1205 | 1251 | return true; // catch the most you can |
1206 | | - } else if (a === null || b === null || typeof a === "undefined" |
1207 | | - || typeof b === "undefined" |
1208 | | - || QUnit.objectType(a) !== QUnit.objectType(b)) { |
| 1252 | + } else if (a === null || b === null || typeof a === "undefined" || |
| 1253 | + typeof b === "undefined" || |
| 1254 | + QUnit.objectType(a) !== QUnit.objectType(b)) { |
1209 | 1255 | return false; // don't lose time with error prone cases |
1210 | 1256 | } else { |
1211 | 1257 | return bindCallbacks(a, callbacks, [ b, a ]); |
1212 | 1258 | } |
1213 | 1259 | |
1214 | 1260 | // apply transition with (1..n) arguments |
1215 | | - })(args[0], args[1]) |
1216 | | - && arguments.callee.apply(this, args.splice(1, |
1217 | | - args.length - 1)); |
| 1261 | + }(args[0], args[1]) && arguments.callee.apply(this, args.splice(1, args.length - 1))); |
1218 | 1262 | }; |
1219 | 1263 | |
1220 | 1264 | return innerEquiv; |
1221 | 1265 | |
1222 | | -}(); |
| 1266 | +}()); |
1223 | 1267 | |
1224 | 1268 | /** |
1225 | 1269 | * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com | |
— | — | @@ -1233,33 +1277,36 @@ |
1234 | 1278 | QUnit.jsDump = (function() { |
1235 | 1279 | function quote( str ) { |
1236 | 1280 | return '"' + str.toString().replace(/"/g, '\\"') + '"'; |
1237 | | - }; |
| 1281 | + } |
1238 | 1282 | function literal( o ) { |
1239 | 1283 | return o + ''; |
1240 | | - }; |
| 1284 | + } |
1241 | 1285 | function join( pre, arr, post ) { |
1242 | 1286 | var s = jsDump.separator(), |
1243 | 1287 | base = jsDump.indent(), |
1244 | 1288 | inner = jsDump.indent(1); |
1245 | | - if ( arr.join ) |
| 1289 | + if ( arr.join ) { |
1246 | 1290 | arr = arr.join( ',' + s + inner ); |
1247 | | - if ( !arr ) |
| 1291 | + } |
| 1292 | + if ( !arr ) { |
1248 | 1293 | return pre + post; |
| 1294 | + } |
1249 | 1295 | return [ pre, inner + arr, base + post ].join(s); |
1250 | | - }; |
| 1296 | + } |
1251 | 1297 | function array( arr, stack ) { |
1252 | | - var i = arr.length, ret = Array(i); |
| 1298 | + var i = arr.length, ret = new Array(i); |
1253 | 1299 | this.up(); |
1254 | | - while ( i-- ) |
| 1300 | + while ( i-- ) { |
1255 | 1301 | ret[i] = this.parse( arr[i] , undefined , stack); |
| 1302 | + } |
1256 | 1303 | this.down(); |
1257 | 1304 | return join( '[', ret, ']' ); |
1258 | | - }; |
| 1305 | + } |
1259 | 1306 | |
1260 | 1307 | var reName = /^function (\w+)/; |
1261 | 1308 | |
1262 | 1309 | var jsDump = { |
1263 | | - parse:function( obj, type, stack ) { //type is used mostly internally, you can fix a (custom)type in advance |
| 1310 | + parse: function( obj, type, stack ) { //type is used mostly internally, you can fix a (custom)type in advance |
1264 | 1311 | stack = stack || [ ]; |
1265 | 1312 | var parser = this.parsers[ type || this.typeOf(obj) ]; |
1266 | 1313 | type = typeof parser; |
— | — | @@ -1277,7 +1324,7 @@ |
1278 | 1325 | // else |
1279 | 1326 | return (type == 'string') ? parser : this.parsers.error; |
1280 | 1327 | }, |
1281 | | - typeOf:function( obj ) { |
| 1328 | + typeOf: function( obj ) { |
1282 | 1329 | var type; |
1283 | 1330 | if ( obj === null ) { |
1284 | 1331 | type = "null"; |
— | — | @@ -1307,45 +1354,48 @@ |
1308 | 1355 | } |
1309 | 1356 | return type; |
1310 | 1357 | }, |
1311 | | - separator:function() { |
| 1358 | + separator: function() { |
1312 | 1359 | return this.multiline ? this.HTML ? '<br />' : '\n' : this.HTML ? ' ' : ' '; |
1313 | 1360 | }, |
1314 | | - indent:function( extra ) {// extra can be a number, shortcut for increasing-calling-decreasing |
1315 | | - if ( !this.multiline ) |
| 1361 | + indent: function( extra ) {// extra can be a number, shortcut for increasing-calling-decreasing |
| 1362 | + if ( !this.multiline ) { |
1316 | 1363 | return ''; |
| 1364 | + } |
1317 | 1365 | var chr = this.indentChar; |
1318 | | - if ( this.HTML ) |
| 1366 | + if ( this.HTML ) { |
1319 | 1367 | chr = chr.replace(/\t/g,' ').replace(/ /g,' '); |
1320 | | - return Array( this._depth_ + (extra||0) ).join(chr); |
| 1368 | + } |
| 1369 | + return new Array( this._depth_ + (extra||0) ).join(chr); |
1321 | 1370 | }, |
1322 | | - up:function( a ) { |
| 1371 | + up: function( a ) { |
1323 | 1372 | this._depth_ += a || 1; |
1324 | 1373 | }, |
1325 | | - down:function( a ) { |
| 1374 | + down: function( a ) { |
1326 | 1375 | this._depth_ -= a || 1; |
1327 | 1376 | }, |
1328 | | - setParser:function( name, parser ) { |
| 1377 | + setParser: function( name, parser ) { |
1329 | 1378 | this.parsers[name] = parser; |
1330 | 1379 | }, |
1331 | 1380 | // The next 3 are exposed so you can use them |
1332 | | - quote:quote, |
1333 | | - literal:literal, |
1334 | | - join:join, |
| 1381 | + quote: quote, |
| 1382 | + literal: literal, |
| 1383 | + join: join, |
1335 | 1384 | // |
1336 | 1385 | _depth_: 1, |
1337 | 1386 | // This is the list of parsers, to modify them, use jsDump.setParser |
1338 | | - parsers:{ |
| 1387 | + parsers: { |
1339 | 1388 | window: '[Window]', |
1340 | 1389 | document: '[Document]', |
1341 | | - error:'[ERROR]', //when no parser is found, shouldn't happen |
| 1390 | + error: '[ERROR]', //when no parser is found, shouldn't happen |
1342 | 1391 | unknown: '[Unknown]', |
1343 | | - 'null':'null', |
1344 | | - 'undefined':'undefined', |
1345 | | - 'function':function( fn ) { |
| 1392 | + 'null': 'null', |
| 1393 | + 'undefined': 'undefined', |
| 1394 | + 'function': function( fn ) { |
1346 | 1395 | var ret = 'function', |
1347 | 1396 | name = 'name' in fn ? fn.name : (reName.exec(fn)||[])[1];//functions never have name in IE |
1348 | | - if ( name ) |
| 1397 | + if ( name ) { |
1349 | 1398 | ret += ' ' + name; |
| 1399 | + } |
1350 | 1400 | ret += '('; |
1351 | 1401 | |
1352 | 1402 | ret = [ ret, QUnit.jsDump.parse( fn, 'functionArgs' ), '){'].join(''); |
— | — | @@ -1353,18 +1403,26 @@ |
1354 | 1404 | }, |
1355 | 1405 | array: array, |
1356 | 1406 | nodelist: array, |
1357 | | - arguments: array, |
1358 | | - object:function( map, stack ) { |
1359 | | - var ret = [ ]; |
| 1407 | + 'arguments': array, |
| 1408 | + object: function( map, stack ) { |
| 1409 | + var ret = [ ], keys, key, val, i; |
1360 | 1410 | QUnit.jsDump.up(); |
1361 | | - for ( var key in map ) { |
1362 | | - var val = map[key]; |
1363 | | - ret.push( QUnit.jsDump.parse(key,'key') + ': ' + QUnit.jsDump.parse(val, undefined, stack)); |
1364 | | - } |
| 1411 | + if (Object.keys) { |
| 1412 | + keys = Object.keys( map ); |
| 1413 | + } else { |
| 1414 | + keys = []; |
| 1415 | + for (key in map) { keys.push( key ); } |
| 1416 | + } |
| 1417 | + keys.sort(); |
| 1418 | + for (i = 0; i < keys.length; i++) { |
| 1419 | + key = keys[ i ]; |
| 1420 | + val = map[ key ]; |
| 1421 | + ret.push( QUnit.jsDump.parse( key, 'key' ) + ': ' + QUnit.jsDump.parse( val, undefined, stack ) ); |
| 1422 | + } |
1365 | 1423 | QUnit.jsDump.down(); |
1366 | 1424 | return join( '{', ret, '}' ); |
1367 | 1425 | }, |
1368 | | - node:function( node ) { |
| 1426 | + node: function( node ) { |
1369 | 1427 | var open = QUnit.jsDump.HTML ? '<' : '<', |
1370 | 1428 | close = QUnit.jsDump.HTML ? '>' : '>'; |
1371 | 1429 | |
— | — | @@ -1373,28 +1431,32 @@ |
1374 | 1432 | |
1375 | 1433 | for ( var a in QUnit.jsDump.DOMAttrs ) { |
1376 | 1434 | var val = node[QUnit.jsDump.DOMAttrs[a]]; |
1377 | | - if ( val ) |
| 1435 | + if ( val ) { |
1378 | 1436 | ret += ' ' + a + '=' + QUnit.jsDump.parse( val, 'attribute' ); |
| 1437 | + } |
1379 | 1438 | } |
1380 | 1439 | return ret + close + open + '/' + tag + close; |
1381 | 1440 | }, |
1382 | | - functionArgs:function( fn ) {//function calls it internally, it's the arguments part of the function |
| 1441 | + functionArgs: function( fn ) {//function calls it internally, it's the arguments part of the function |
1383 | 1442 | var l = fn.length; |
1384 | | - if ( !l ) return ''; |
| 1443 | + if ( !l ) { |
| 1444 | + return ''; |
| 1445 | + } |
1385 | 1446 | |
1386 | | - var args = Array(l); |
1387 | | - while ( l-- ) |
| 1447 | + var args = new Array(l); |
| 1448 | + while ( l-- ) { |
1388 | 1449 | args[l] = String.fromCharCode(97+l);//97 is 'a' |
| 1450 | + } |
1389 | 1451 | return ' ' + args.join(', ') + ' '; |
1390 | 1452 | }, |
1391 | | - key:quote, //object calls it internally, the key part of an item in a map |
1392 | | - functionCode:'[code]', //function calls it internally, it's the content of the function |
1393 | | - attribute:quote, //node calls it internally, it's an html attribute value |
1394 | | - string:quote, |
1395 | | - date:quote, |
1396 | | - regexp:literal, //regex |
1397 | | - number:literal, |
1398 | | - 'boolean':literal |
| 1453 | + key: quote, //object calls it internally, the key part of an item in a map |
| 1454 | + functionCode: '[code]', //function calls it internally, it's the content of the function |
| 1455 | + attribute: quote, //node calls it internally, it's an html attribute value |
| 1456 | + string: quote, |
| 1457 | + date: quote, |
| 1458 | + regexp: literal, //regex |
| 1459 | + number: literal, |
| 1460 | + 'boolean': literal |
1399 | 1461 | }, |
1400 | 1462 | DOMAttrs:{//attributes to dump from nodes, name=>realName |
1401 | 1463 | id:'id', |
— | — | @@ -1407,7 +1469,7 @@ |
1408 | 1470 | }; |
1409 | 1471 | |
1410 | 1472 | return jsDump; |
1411 | | -})(); |
| 1473 | +}()); |
1412 | 1474 | |
1413 | 1475 | // from Sizzle.js |
1414 | 1476 | function getText( elems ) { |
— | — | @@ -1427,7 +1489,7 @@ |
1428 | 1490 | } |
1429 | 1491 | |
1430 | 1492 | return ret; |
1431 | | -}; |
| 1493 | +} |
1432 | 1494 | |
1433 | 1495 | //from jquery.js |
1434 | 1496 | function inArray( elem, array ) { |
— | — | @@ -1462,26 +1524,29 @@ |
1463 | 1525 | function diff(o, n) { |
1464 | 1526 | var ns = {}; |
1465 | 1527 | var os = {}; |
| 1528 | + var i; |
1466 | 1529 | |
1467 | | - for (var i = 0; i < n.length; i++) { |
1468 | | - if (ns[n[i]] == null) |
| 1530 | + for (i = 0; i < n.length; i++) { |
| 1531 | + if (ns[n[i]] == null) { |
1469 | 1532 | ns[n[i]] = { |
1470 | 1533 | rows: [], |
1471 | 1534 | o: null |
1472 | 1535 | }; |
| 1536 | + } |
1473 | 1537 | ns[n[i]].rows.push(i); |
1474 | 1538 | } |
1475 | 1539 | |
1476 | | - for (var i = 0; i < o.length; i++) { |
1477 | | - if (os[o[i]] == null) |
| 1540 | + for (i = 0; i < o.length; i++) { |
| 1541 | + if (os[o[i]] == null) { |
1478 | 1542 | os[o[i]] = { |
1479 | 1543 | rows: [], |
1480 | 1544 | n: null |
1481 | 1545 | }; |
| 1546 | + } |
1482 | 1547 | os[o[i]].rows.push(i); |
1483 | 1548 | } |
1484 | 1549 | |
1485 | | - for (var i in ns) { |
| 1550 | + for (i in ns) { |
1486 | 1551 | if ( !hasOwn.call( ns, i ) ) { |
1487 | 1552 | continue; |
1488 | 1553 | } |
— | — | @@ -1497,7 +1562,7 @@ |
1498 | 1563 | } |
1499 | 1564 | } |
1500 | 1565 | |
1501 | | - for (var i = 0; i < n.length - 1; i++) { |
| 1566 | + for (i = 0; i < n.length - 1; i++) { |
1502 | 1567 | if (n[i].text != null && n[i + 1].text == null && n[i].row + 1 < o.length && o[n[i].row + 1].text == null && |
1503 | 1568 | n[i + 1] == o[n[i].row + 1]) { |
1504 | 1569 | n[i + 1] = { |
— | — | @@ -1511,7 +1576,7 @@ |
1512 | 1577 | } |
1513 | 1578 | } |
1514 | 1579 | |
1515 | | - for (var i = n.length - 1; i > 0; i--) { |
| 1580 | + for (i = n.length - 1; i > 0; i--) { |
1516 | 1581 | if (n[i].text != null && n[i - 1].text == null && n[i].row > 0 && o[n[i].row - 1].text == null && |
1517 | 1582 | n[i - 1] == o[n[i].row - 1]) { |
1518 | 1583 | n[i - 1] = { |
— | — | @@ -1534,9 +1599,10 @@ |
1535 | 1600 | return function(o, n) { |
1536 | 1601 | o = o.replace(/\s+$/, ''); |
1537 | 1602 | n = n.replace(/\s+$/, ''); |
1538 | | - var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/)); |
| 1603 | + var out = diff(o === "" ? [] : o.split(/\s+/), n === "" ? [] : n.split(/\s+/)); |
1539 | 1604 | |
1540 | 1605 | var str = ""; |
| 1606 | + var i; |
1541 | 1607 | |
1542 | 1608 | var oSpace = o.match(/\s+/g); |
1543 | 1609 | if (oSpace == null) { |
— | — | @@ -1553,8 +1619,8 @@ |
1554 | 1620 | nSpace.push(" "); |
1555 | 1621 | } |
1556 | 1622 | |
1557 | | - if (out.n.length == 0) { |
1558 | | - for (var i = 0; i < out.o.length; i++) { |
| 1623 | + if (out.n.length === 0) { |
| 1624 | + for (i = 0; i < out.o.length; i++) { |
1559 | 1625 | str += '<del>' + out.o[i] + oSpace[i] + "</del>"; |
1560 | 1626 | } |
1561 | 1627 | } |
— | — | @@ -1565,7 +1631,7 @@ |
1566 | 1632 | } |
1567 | 1633 | } |
1568 | 1634 | |
1569 | | - for (var i = 0; i < out.n.length; i++) { |
| 1635 | + for (i = 0; i < out.n.length; i++) { |
1570 | 1636 | if (out.n[i].text == null) { |
1571 | 1637 | str += '<ins>' + out.n[i] + nSpace[i] + "</ins>"; |
1572 | 1638 | } |
— | — | @@ -1582,6 +1648,12 @@ |
1583 | 1649 | |
1584 | 1650 | return str; |
1585 | 1651 | }; |
1586 | | -})(); |
| 1652 | +}()); |
1587 | 1653 | |
1588 | | -})(this); |
| 1654 | +// for CommonJS enviroments, export everything |
| 1655 | +if ( typeof exports !== "undefined" || typeof require !== "undefined" ) { |
| 1656 | + extend(exports, QUnit); |
| 1657 | +} |
| 1658 | + |
| 1659 | +// get at whatever the global object is, like window in browsers |
| 1660 | +}( (function() {return this;}.call()) )); |