qunit-rails 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.md +0 -0
- data/Gemfile.lock +20 -20
- data/{MIT-LICENSE → LICENSE.md} +3 -1
- data/README.md +28 -8
- data/app/views/qunit/rails/test/index.html.erb +2 -1
- data/config/initializers/qunit-rails.rb +1 -1
- data/lib/generators/qunit/install_generator.rb +4 -4
- data/lib/generators/templates/{test_helper.js.coffee → test_helper.coffee} +0 -0
- data/qunit-rails.gemspec +9 -7
- data/vendor/assets/javascripts/qunit.js +393 -173
- data/vendor/assets/stylesheets/qunit.css +20 -7
- metadata +15 -12
- data/lib/qunit/rails/version.rb +0 -5
@@ -1,35 +1,87 @@
|
|
1
1
|
/**
|
2
|
-
* QUnit v1.
|
2
|
+
* QUnit v1.11.0 - A JavaScript Unit Testing Framework
|
3
3
|
*
|
4
|
-
* http://
|
4
|
+
* http://qunitjs.com
|
5
5
|
*
|
6
|
-
* Copyright
|
7
|
-
*
|
8
|
-
*
|
6
|
+
* Copyright 2012 jQuery Foundation and other contributors
|
7
|
+
* Released under the MIT license.
|
8
|
+
* http://jquery.org/license
|
9
9
|
*/
|
10
10
|
|
11
11
|
(function( window ) {
|
12
12
|
|
13
13
|
var QUnit,
|
14
|
+
assert,
|
14
15
|
config,
|
15
16
|
onErrorFnPrev,
|
16
17
|
testId = 0,
|
17
18
|
fileName = (sourceFromStacktrace( 0 ) || "" ).replace(/(:\d+)+\)?/, "").replace(/.+\//, ""),
|
18
19
|
toString = Object.prototype.toString,
|
19
20
|
hasOwn = Object.prototype.hasOwnProperty,
|
21
|
+
// Keep a local reference to Date (GH-283)
|
22
|
+
Date = window.Date,
|
20
23
|
defined = {
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
24
|
+
setTimeout: typeof window.setTimeout !== "undefined",
|
25
|
+
sessionStorage: (function() {
|
26
|
+
var x = "qunit-test-string";
|
27
|
+
try {
|
28
|
+
sessionStorage.setItem( x, x );
|
29
|
+
sessionStorage.removeItem( x );
|
30
|
+
return true;
|
31
|
+
} catch( e ) {
|
32
|
+
return false;
|
33
|
+
}
|
34
|
+
}())
|
35
|
+
},
|
36
|
+
/**
|
37
|
+
* Provides a normalized error string, correcting an issue
|
38
|
+
* with IE 7 (and prior) where Error.prototype.toString is
|
39
|
+
* not properly implemented
|
40
|
+
*
|
41
|
+
* Based on http://es5.github.com/#x15.11.4.4
|
42
|
+
*
|
43
|
+
* @param {String|Error} error
|
44
|
+
* @return {String} error message
|
45
|
+
*/
|
46
|
+
errorString = function( error ) {
|
47
|
+
var name, message,
|
48
|
+
errorString = error.toString();
|
49
|
+
if ( errorString.substring( 0, 7 ) === "[object" ) {
|
50
|
+
name = error.name ? error.name.toString() : "Error";
|
51
|
+
message = error.message ? error.message.toString() : "";
|
52
|
+
if ( name && message ) {
|
53
|
+
return name + ": " + message;
|
54
|
+
} else if ( name ) {
|
55
|
+
return name;
|
56
|
+
} else if ( message ) {
|
57
|
+
return message;
|
58
|
+
} else {
|
59
|
+
return "Error";
|
60
|
+
}
|
61
|
+
} else {
|
62
|
+
return errorString;
|
30
63
|
}
|
31
|
-
}
|
32
|
-
|
64
|
+
},
|
65
|
+
/**
|
66
|
+
* Makes a clone of an object using only Array or Object as base,
|
67
|
+
* and copies over the own enumerable properties.
|
68
|
+
*
|
69
|
+
* @param {Object} obj
|
70
|
+
* @return {Object} New object with only the own properties (recursively).
|
71
|
+
*/
|
72
|
+
objectValues = function( obj ) {
|
73
|
+
// Grunt 0.3.x uses an older version of jshint that still has jshint/jshint#392.
|
74
|
+
/*jshint newcap: false */
|
75
|
+
var key, val,
|
76
|
+
vals = QUnit.is( "array", obj ) ? [] : {};
|
77
|
+
for ( key in obj ) {
|
78
|
+
if ( hasOwn.call( obj, key ) ) {
|
79
|
+
val = obj[key];
|
80
|
+
vals[key] = val === Object(val) ? objectValues(val) : val;
|
81
|
+
}
|
82
|
+
}
|
83
|
+
return vals;
|
84
|
+
};
|
33
85
|
|
34
86
|
function Test( settings ) {
|
35
87
|
extend( this, settings );
|
@@ -42,11 +94,11 @@ Test.count = 0;
|
|
42
94
|
Test.prototype = {
|
43
95
|
init: function() {
|
44
96
|
var a, b, li,
|
45
|
-
|
97
|
+
tests = id( "qunit-tests" );
|
46
98
|
|
47
99
|
if ( tests ) {
|
48
100
|
b = document.createElement( "strong" );
|
49
|
-
b.innerHTML = this.
|
101
|
+
b.innerHTML = this.nameHtml;
|
50
102
|
|
51
103
|
// `a` initialized at top of scope
|
52
104
|
a = document.createElement( "a" );
|
@@ -90,6 +142,7 @@ Test.prototype = {
|
|
90
142
|
teardown: function() {}
|
91
143
|
}, this.moduleTestEnvironment );
|
92
144
|
|
145
|
+
this.started = +new Date();
|
93
146
|
runLoggingCallbacks( "testStart", QUnit, {
|
94
147
|
name: this.testName,
|
95
148
|
module: this.module
|
@@ -109,7 +162,7 @@ Test.prototype = {
|
|
109
162
|
try {
|
110
163
|
this.testEnvironment.setup.call( this.testEnvironment );
|
111
164
|
} catch( e ) {
|
112
|
-
QUnit.pushFailure( "Setup failed on " + this.testName + ": " + e.message, extractStacktrace( e, 1 ) );
|
165
|
+
QUnit.pushFailure( "Setup failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) );
|
113
166
|
}
|
114
167
|
},
|
115
168
|
run: function() {
|
@@ -118,22 +171,28 @@ Test.prototype = {
|
|
118
171
|
var running = id( "qunit-testresult" );
|
119
172
|
|
120
173
|
if ( running ) {
|
121
|
-
running.innerHTML = "Running: <br/>" + this.
|
174
|
+
running.innerHTML = "Running: <br/>" + this.nameHtml;
|
122
175
|
}
|
123
176
|
|
124
177
|
if ( this.async ) {
|
125
178
|
QUnit.stop();
|
126
179
|
}
|
127
180
|
|
181
|
+
this.callbackStarted = +new Date();
|
182
|
+
|
128
183
|
if ( config.notrycatch ) {
|
129
184
|
this.callback.call( this.testEnvironment, QUnit.assert );
|
185
|
+
this.callbackRuntime = +new Date() - this.callbackStarted;
|
130
186
|
return;
|
131
187
|
}
|
132
188
|
|
133
189
|
try {
|
134
190
|
this.callback.call( this.testEnvironment, QUnit.assert );
|
191
|
+
this.callbackRuntime = +new Date() - this.callbackStarted;
|
135
192
|
} catch( e ) {
|
136
|
-
|
193
|
+
this.callbackRuntime = +new Date() - this.callbackStarted;
|
194
|
+
|
195
|
+
QUnit.pushFailure( "Died on test #" + (this.assertions.length + 1) + " " + this.stack + ": " + ( e.message || e ), extractStacktrace( e, 0 ) );
|
137
196
|
// else next test will carry the responsibility
|
138
197
|
saveGlobal();
|
139
198
|
|
@@ -146,38 +205,43 @@ Test.prototype = {
|
|
146
205
|
teardown: function() {
|
147
206
|
config.current = this;
|
148
207
|
if ( config.notrycatch ) {
|
208
|
+
if ( typeof this.callbackRuntime === "undefined" ) {
|
209
|
+
this.callbackRuntime = +new Date() - this.callbackStarted;
|
210
|
+
}
|
149
211
|
this.testEnvironment.teardown.call( this.testEnvironment );
|
150
212
|
return;
|
151
213
|
} else {
|
152
214
|
try {
|
153
215
|
this.testEnvironment.teardown.call( this.testEnvironment );
|
154
216
|
} catch( e ) {
|
155
|
-
QUnit.pushFailure( "Teardown failed on " + this.testName + ": " + e.message, extractStacktrace( e, 1 ) );
|
217
|
+
QUnit.pushFailure( "Teardown failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) );
|
156
218
|
}
|
157
219
|
}
|
158
220
|
checkPollution();
|
159
221
|
},
|
160
222
|
finish: function() {
|
161
223
|
config.current = this;
|
162
|
-
if ( config.requireExpects && this.expected
|
224
|
+
if ( config.requireExpects && this.expected === null ) {
|
163
225
|
QUnit.pushFailure( "Expected number of assertions to be defined, but expect() was not called.", this.stack );
|
164
|
-
} else if ( this.expected
|
226
|
+
} else if ( this.expected !== null && this.expected !== this.assertions.length ) {
|
165
227
|
QUnit.pushFailure( "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run", this.stack );
|
166
|
-
} else if ( this.expected
|
228
|
+
} else if ( this.expected === null && !this.assertions.length ) {
|
167
229
|
QUnit.pushFailure( "Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.", this.stack );
|
168
230
|
}
|
169
231
|
|
170
|
-
var assertion, a, b,
|
232
|
+
var i, assertion, a, b, time, li, ol,
|
171
233
|
test = this,
|
172
234
|
good = 0,
|
173
235
|
bad = 0,
|
174
236
|
tests = id( "qunit-tests" );
|
175
237
|
|
238
|
+
this.runtime = +new Date() - this.started;
|
176
239
|
config.stats.all += this.assertions.length;
|
177
240
|
config.moduleStats.all += this.assertions.length;
|
178
241
|
|
179
242
|
if ( tests ) {
|
180
243
|
ol = document.createElement( "ol" );
|
244
|
+
ol.className = "qunit-assert-list";
|
181
245
|
|
182
246
|
for ( i = 0; i < this.assertions.length; i++ ) {
|
183
247
|
assertion = this.assertions[i];
|
@@ -206,22 +270,22 @@ Test.prototype = {
|
|
206
270
|
}
|
207
271
|
|
208
272
|
if ( bad === 0 ) {
|
209
|
-
ol
|
273
|
+
addClass( ol, "qunit-collapsed" );
|
210
274
|
}
|
211
275
|
|
212
276
|
// `b` initialized at top of scope
|
213
277
|
b = document.createElement( "strong" );
|
214
|
-
b.innerHTML = this.
|
278
|
+
b.innerHTML = this.nameHtml + " <b class='counts'>(<b class='failed'>" + bad + "</b>, <b class='passed'>" + good + "</b>, " + this.assertions.length + ")</b>";
|
215
279
|
|
216
280
|
addEvent(b, "click", function() {
|
217
|
-
var next = b.
|
218
|
-
|
219
|
-
|
281
|
+
var next = b.parentNode.lastChild,
|
282
|
+
collapsed = hasClass( next, "qunit-collapsed" );
|
283
|
+
( collapsed ? removeClass : addClass )( next, "qunit-collapsed" );
|
220
284
|
});
|
221
285
|
|
222
286
|
addEvent(b, "dblclick", function( e ) {
|
223
287
|
var target = e && e.target ? e.target : window.event.srcElement;
|
224
|
-
if ( target.nodeName.toLowerCase()
|
288
|
+
if ( target.nodeName.toLowerCase() === "span" || target.nodeName.toLowerCase() === "b" ) {
|
225
289
|
target = target.parentNode;
|
226
290
|
}
|
227
291
|
if ( window.location && target.nodeName.toLowerCase() === "strong" ) {
|
@@ -229,13 +293,19 @@ Test.prototype = {
|
|
229
293
|
}
|
230
294
|
});
|
231
295
|
|
296
|
+
// `time` initialized at top of scope
|
297
|
+
time = document.createElement( "span" );
|
298
|
+
time.className = "runtime";
|
299
|
+
time.innerHTML = this.runtime + " ms";
|
300
|
+
|
232
301
|
// `li` initialized at top of scope
|
233
302
|
li = id( this.id );
|
234
303
|
li.className = bad ? "fail" : "pass";
|
235
304
|
li.removeChild( li.firstChild );
|
236
305
|
a = li.firstChild;
|
237
306
|
li.appendChild( b );
|
238
|
-
li.appendChild
|
307
|
+
li.appendChild( a );
|
308
|
+
li.appendChild( time );
|
239
309
|
li.appendChild( ol );
|
240
310
|
|
241
311
|
} else {
|
@@ -253,7 +323,8 @@ Test.prototype = {
|
|
253
323
|
module: this.module,
|
254
324
|
failed: bad,
|
255
325
|
passed: this.assertions.length - bad,
|
256
|
-
total: this.assertions.length
|
326
|
+
total: this.assertions.length,
|
327
|
+
duration: this.runtime
|
257
328
|
});
|
258
329
|
|
259
330
|
QUnit.reset();
|
@@ -304,7 +375,8 @@ QUnit = {
|
|
304
375
|
// call on start of module test to prepend name to all tests
|
305
376
|
module: function( name, testEnvironment ) {
|
306
377
|
config.currentModule = name;
|
307
|
-
config.
|
378
|
+
config.currentModuleTestEnvironment = testEnvironment;
|
379
|
+
config.modules[name] = true;
|
308
380
|
},
|
309
381
|
|
310
382
|
asyncTest: function( testName, expected, callback ) {
|
@@ -318,7 +390,7 @@ QUnit = {
|
|
318
390
|
|
319
391
|
test: function( testName, expected, callback, async ) {
|
320
392
|
var test,
|
321
|
-
|
393
|
+
nameHtml = "<span class='test-name'>" + escapeText( testName ) + "</span>";
|
322
394
|
|
323
395
|
if ( arguments.length === 2 ) {
|
324
396
|
callback = expected;
|
@@ -326,17 +398,17 @@ QUnit = {
|
|
326
398
|
}
|
327
399
|
|
328
400
|
if ( config.currentModule ) {
|
329
|
-
|
401
|
+
nameHtml = "<span class='module-name'>" + escapeText( config.currentModule ) + "</span>: " + nameHtml;
|
330
402
|
}
|
331
403
|
|
332
404
|
test = new Test({
|
333
|
-
|
405
|
+
nameHtml: nameHtml,
|
334
406
|
testName: testName,
|
335
407
|
expected: expected,
|
336
408
|
async: async,
|
337
409
|
callback: callback,
|
338
410
|
module: config.currentModule,
|
339
|
-
moduleTestEnvironment: config.
|
411
|
+
moduleTestEnvironment: config.currentModuleTestEnvironment,
|
340
412
|
stack: sourceFromStacktrace( 2 )
|
341
413
|
});
|
342
414
|
|
@@ -349,10 +421,26 @@ QUnit = {
|
|
349
421
|
|
350
422
|
// Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.
|
351
423
|
expect: function( asserts ) {
|
352
|
-
|
424
|
+
if (arguments.length === 1) {
|
425
|
+
config.current.expected = asserts;
|
426
|
+
} else {
|
427
|
+
return config.current.expected;
|
428
|
+
}
|
353
429
|
},
|
354
430
|
|
355
431
|
start: function( count ) {
|
432
|
+
// QUnit hasn't been initialized yet.
|
433
|
+
// Note: RequireJS (et al) may delay onLoad
|
434
|
+
if ( config.semaphore === undefined ) {
|
435
|
+
QUnit.begin(function() {
|
436
|
+
// This is triggered at the top of QUnit.load, push start() to the event loop, to allow QUnit.load to finish first
|
437
|
+
setTimeout(function() {
|
438
|
+
QUnit.start( count );
|
439
|
+
});
|
440
|
+
});
|
441
|
+
return;
|
442
|
+
}
|
443
|
+
|
356
444
|
config.semaphore -= count || 1;
|
357
445
|
// don't start until equal number of stop-calls
|
358
446
|
if ( config.semaphore > 0 ) {
|
@@ -361,6 +449,8 @@ QUnit = {
|
|
361
449
|
// ignore if start is called more often then stop
|
362
450
|
if ( config.semaphore < 0 ) {
|
363
451
|
config.semaphore = 0;
|
452
|
+
QUnit.pushFailure( "Called start() while already started (QUnit.config.semaphore was 0 already)", null, sourceFromStacktrace(2) );
|
453
|
+
return;
|
364
454
|
}
|
365
455
|
// A slight delay, to avoid any current callbacks
|
366
456
|
if ( defined.setTimeout ) {
|
@@ -396,11 +486,14 @@ QUnit = {
|
|
396
486
|
}
|
397
487
|
};
|
398
488
|
|
489
|
+
// `assert` initialized at top of scope
|
399
490
|
// Asssert helpers
|
400
|
-
// All of these must call
|
491
|
+
// All of these must either call QUnit.push() or manually do:
|
401
492
|
// - runLoggingCallbacks( "log", .. );
|
402
493
|
// - config.current.assertions.push({ .. });
|
403
|
-
QUnit
|
494
|
+
// We attach it to the QUnit object *after* we expose the public API,
|
495
|
+
// otherwise `assert` will become a global variable in browsers (#341).
|
496
|
+
assert = {
|
404
497
|
/**
|
405
498
|
* Asserts rough true-ish result.
|
406
499
|
* @name ok
|
@@ -415,18 +508,20 @@ QUnit.assert = {
|
|
415
508
|
|
416
509
|
var source,
|
417
510
|
details = {
|
511
|
+
module: config.current.module,
|
512
|
+
name: config.current.testName,
|
418
513
|
result: result,
|
419
514
|
message: msg
|
420
515
|
};
|
421
516
|
|
422
|
-
msg =
|
517
|
+
msg = escapeText( msg || (result ? "okay" : "failed" ) );
|
423
518
|
msg = "<span class='test-message'>" + msg + "</span>";
|
424
519
|
|
425
520
|
if ( !result ) {
|
426
521
|
source = sourceFromStacktrace( 2 );
|
427
522
|
if ( source ) {
|
428
523
|
details.source = source;
|
429
|
-
msg += "<table><tr class='test-source'><th>Source: </th><td><pre>" +
|
524
|
+
msg += "<table><tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr></table>";
|
430
525
|
}
|
431
526
|
}
|
432
527
|
runLoggingCallbacks( "log", QUnit, details );
|
@@ -444,6 +539,7 @@ QUnit.assert = {
|
|
444
539
|
* @example equal( format( "Received {0} bytes.", 2), "Received 2 bytes.", "format() replaces {0} with next argument" );
|
445
540
|
*/
|
446
541
|
equal: function( actual, expected, message ) {
|
542
|
+
/*jshint eqeqeq:false */
|
447
543
|
QUnit.push( expected == actual, actual, expected, message );
|
448
544
|
},
|
449
545
|
|
@@ -452,9 +548,30 @@ QUnit.assert = {
|
|
452
548
|
* @function
|
453
549
|
*/
|
454
550
|
notEqual: function( actual, expected, message ) {
|
551
|
+
/*jshint eqeqeq:false */
|
455
552
|
QUnit.push( expected != actual, actual, expected, message );
|
456
553
|
},
|
457
554
|
|
555
|
+
/**
|
556
|
+
* @name propEqual
|
557
|
+
* @function
|
558
|
+
*/
|
559
|
+
propEqual: function( actual, expected, message ) {
|
560
|
+
actual = objectValues(actual);
|
561
|
+
expected = objectValues(expected);
|
562
|
+
QUnit.push( QUnit.equiv(actual, expected), actual, expected, message );
|
563
|
+
},
|
564
|
+
|
565
|
+
/**
|
566
|
+
* @name notPropEqual
|
567
|
+
* @function
|
568
|
+
*/
|
569
|
+
notPropEqual: function( actual, expected, message ) {
|
570
|
+
actual = objectValues(actual);
|
571
|
+
expected = objectValues(expected);
|
572
|
+
QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );
|
573
|
+
},
|
574
|
+
|
458
575
|
/**
|
459
576
|
* @name deepEqual
|
460
577
|
* @function
|
@@ -487,8 +604,9 @@ QUnit.assert = {
|
|
487
604
|
QUnit.push( expected !== actual, actual, expected, message );
|
488
605
|
},
|
489
606
|
|
490
|
-
throws: function( block, expected, message ) {
|
607
|
+
"throws": function( block, expected, message ) {
|
491
608
|
var actual,
|
609
|
+
expectedOutput = expected,
|
492
610
|
ok = false;
|
493
611
|
|
494
612
|
// 'expected' is optional
|
@@ -509,18 +627,20 @@ QUnit.assert = {
|
|
509
627
|
// we don't want to validate thrown error
|
510
628
|
if ( !expected ) {
|
511
629
|
ok = true;
|
630
|
+
expectedOutput = null;
|
512
631
|
// expected is a regexp
|
513
632
|
} else if ( QUnit.objectType( expected ) === "regexp" ) {
|
514
|
-
ok = expected.test( actual );
|
633
|
+
ok = expected.test( errorString( actual ) );
|
515
634
|
// expected is a constructor
|
516
635
|
} else if ( actual instanceof expected ) {
|
517
636
|
ok = true;
|
518
637
|
// expected is a validation function which returns true is validation passed
|
519
638
|
} else if ( expected.call( {}, actual ) === true ) {
|
639
|
+
expectedOutput = null;
|
520
640
|
ok = true;
|
521
641
|
}
|
522
642
|
|
523
|
-
QUnit.push( ok, actual,
|
643
|
+
QUnit.push( ok, actual, expectedOutput, message );
|
524
644
|
} else {
|
525
645
|
QUnit.pushFailure( message, null, 'No exception was thrown.' );
|
526
646
|
}
|
@@ -529,15 +649,16 @@ QUnit.assert = {
|
|
529
649
|
|
530
650
|
/**
|
531
651
|
* @deprecate since 1.8.0
|
532
|
-
* Kept assertion helpers in root for backwards compatibility
|
652
|
+
* Kept assertion helpers in root for backwards compatibility.
|
533
653
|
*/
|
534
|
-
extend( QUnit,
|
654
|
+
extend( QUnit, assert );
|
535
655
|
|
536
656
|
/**
|
537
657
|
* @deprecated since 1.9.0
|
538
|
-
* Kept
|
658
|
+
* Kept root "raises()" for backwards compatibility.
|
659
|
+
* (Note that we don't introduce assert.raises).
|
539
660
|
*/
|
540
|
-
QUnit.raises =
|
661
|
+
QUnit.raises = assert[ "throws" ];
|
541
662
|
|
542
663
|
/**
|
543
664
|
* @deprecated since 1.0.0, replaced with error pushes since 1.3.0
|
@@ -600,6 +721,9 @@ config = {
|
|
600
721
|
}
|
601
722
|
],
|
602
723
|
|
724
|
+
// Set of all modules.
|
725
|
+
modules: {},
|
726
|
+
|
603
727
|
// logging callback queues
|
604
728
|
begin: [],
|
605
729
|
done: [],
|
@@ -610,6 +734,15 @@ config = {
|
|
610
734
|
moduleDone: []
|
611
735
|
};
|
612
736
|
|
737
|
+
// Export global variables, unless an 'exports' object exists,
|
738
|
+
// in that case we assume we're in CommonJS (dealt with on the bottom of the script)
|
739
|
+
if ( typeof exports === "undefined" ) {
|
740
|
+
extend( window, QUnit );
|
741
|
+
|
742
|
+
// Expose QUnit object
|
743
|
+
window.QUnit = QUnit;
|
744
|
+
}
|
745
|
+
|
613
746
|
// Initialize more QUnit.config and QUnit.urlParams
|
614
747
|
(function() {
|
615
748
|
var i,
|
@@ -643,18 +776,11 @@ config = {
|
|
643
776
|
QUnit.isLocal = location.protocol === "file:";
|
644
777
|
}());
|
645
778
|
|
646
|
-
// Export global variables, unless an 'exports' object exists,
|
647
|
-
// in that case we assume we're in CommonJS (dealt with on the bottom of the script)
|
648
|
-
if ( typeof exports === "undefined" ) {
|
649
|
-
extend( window, QUnit );
|
650
|
-
|
651
|
-
// Expose QUnit object
|
652
|
-
window.QUnit = QUnit;
|
653
|
-
}
|
654
|
-
|
655
779
|
// Extend QUnit object,
|
656
780
|
// these after set here because they should not be exposed as global functions
|
657
781
|
extend( QUnit, {
|
782
|
+
assert: assert,
|
783
|
+
|
658
784
|
config: config,
|
659
785
|
|
660
786
|
// Initialize the configuration options
|
@@ -669,7 +795,7 @@ extend( QUnit, {
|
|
669
795
|
autorun: false,
|
670
796
|
filter: "",
|
671
797
|
queue: [],
|
672
|
-
semaphore:
|
798
|
+
semaphore: 1
|
673
799
|
});
|
674
800
|
|
675
801
|
var tests, banner, result,
|
@@ -677,7 +803,7 @@ extend( QUnit, {
|
|
677
803
|
|
678
804
|
if ( qunit ) {
|
679
805
|
qunit.innerHTML =
|
680
|
-
"<h1 id='qunit-header'>" +
|
806
|
+
"<h1 id='qunit-header'>" + escapeText( document.title ) + "</h1>" +
|
681
807
|
"<h2 id='qunit-banner'></h2>" +
|
682
808
|
"<div id='qunit-testrunner-toolbar'></div>" +
|
683
809
|
"<h2 id='qunit-userAgent'></h2>" +
|
@@ -710,17 +836,10 @@ extend( QUnit, {
|
|
710
836
|
},
|
711
837
|
|
712
838
|
// Resets the test setup. Useful for tests that modify the DOM.
|
713
|
-
// If jQuery is available, uses jQuery's html(), otherwise just innerHTML.
|
714
839
|
reset: function() {
|
715
|
-
var fixture;
|
716
|
-
|
717
|
-
|
718
|
-
jQuery( "#qunit-fixture" ).html( config.fixture );
|
719
|
-
} else {
|
720
|
-
fixture = id( "qunit-fixture" );
|
721
|
-
if ( fixture ) {
|
722
|
-
fixture.innerHTML = config.fixture;
|
723
|
-
}
|
840
|
+
var fixture = id( "qunit-fixture" );
|
841
|
+
if ( fixture ) {
|
842
|
+
fixture.innerHTML = config.fixture;
|
724
843
|
}
|
725
844
|
},
|
726
845
|
|
@@ -740,7 +859,7 @@ extend( QUnit, {
|
|
740
859
|
|
741
860
|
// Safe object type checking
|
742
861
|
is: function( type, obj ) {
|
743
|
-
return QUnit.objectType( obj )
|
862
|
+
return QUnit.objectType( obj ) === type;
|
744
863
|
},
|
745
864
|
|
746
865
|
objectType: function( obj ) {
|
@@ -752,7 +871,8 @@ extend( QUnit, {
|
|
752
871
|
return "null";
|
753
872
|
}
|
754
873
|
|
755
|
-
var
|
874
|
+
var match = toString.call( obj ).match(/^\[object\s(.*)\]$/),
|
875
|
+
type = match && match[1] || "";
|
756
876
|
|
757
877
|
switch ( type ) {
|
758
878
|
case "Number":
|
@@ -781,22 +901,24 @@ extend( QUnit, {
|
|
781
901
|
|
782
902
|
var output, source,
|
783
903
|
details = {
|
904
|
+
module: config.current.module,
|
905
|
+
name: config.current.testName,
|
784
906
|
result: result,
|
785
907
|
message: message,
|
786
908
|
actual: actual,
|
787
909
|
expected: expected
|
788
910
|
};
|
789
911
|
|
790
|
-
message =
|
912
|
+
message = escapeText( message ) || ( result ? "okay" : "failed" );
|
791
913
|
message = "<span class='test-message'>" + message + "</span>";
|
792
914
|
output = message;
|
793
915
|
|
794
916
|
if ( !result ) {
|
795
|
-
expected =
|
796
|
-
actual =
|
917
|
+
expected = escapeText( QUnit.jsDump.parse(expected) );
|
918
|
+
actual = escapeText( QUnit.jsDump.parse(actual) );
|
797
919
|
output += "<table><tr class='test-expected'><th>Expected: </th><td><pre>" + expected + "</pre></td></tr>";
|
798
920
|
|
799
|
-
if ( actual
|
921
|
+
if ( actual !== expected ) {
|
800
922
|
output += "<tr class='test-actual'><th>Result: </th><td><pre>" + actual + "</pre></td></tr>";
|
801
923
|
output += "<tr class='test-diff'><th>Diff: </th><td><pre>" + QUnit.diff( expected, actual ) + "</pre></td></tr>";
|
802
924
|
}
|
@@ -805,7 +927,7 @@ extend( QUnit, {
|
|
805
927
|
|
806
928
|
if ( source ) {
|
807
929
|
details.source = source;
|
808
|
-
output += "<tr class='test-source'><th>Source: </th><td><pre>" +
|
930
|
+
output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr>";
|
809
931
|
}
|
810
932
|
|
811
933
|
output += "</table>";
|
@@ -826,23 +948,25 @@ extend( QUnit, {
|
|
826
948
|
|
827
949
|
var output,
|
828
950
|
details = {
|
951
|
+
module: config.current.module,
|
952
|
+
name: config.current.testName,
|
829
953
|
result: false,
|
830
954
|
message: message
|
831
955
|
};
|
832
956
|
|
833
|
-
message =
|
957
|
+
message = escapeText( message ) || "error";
|
834
958
|
message = "<span class='test-message'>" + message + "</span>";
|
835
959
|
output = message;
|
836
960
|
|
837
961
|
output += "<table>";
|
838
962
|
|
839
963
|
if ( actual ) {
|
840
|
-
output += "<tr class='test-actual'><th>Result: </th><td><pre>" +
|
964
|
+
output += "<tr class='test-actual'><th>Result: </th><td><pre>" + escapeText( actual ) + "</pre></td></tr>";
|
841
965
|
}
|
842
966
|
|
843
967
|
if ( source ) {
|
844
968
|
details.source = source;
|
845
|
-
output += "<tr class='test-source'><th>Source: </th><td><pre>" +
|
969
|
+
output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr>";
|
846
970
|
}
|
847
971
|
|
848
972
|
output += "</table>";
|
@@ -867,7 +991,8 @@ extend( QUnit, {
|
|
867
991
|
querystring += encodeURIComponent( key ) + "=" +
|
868
992
|
encodeURIComponent( params[ key ] ) + "&";
|
869
993
|
}
|
870
|
-
return window.location.
|
994
|
+
return window.location.protocol + "//" + window.location.host +
|
995
|
+
window.location.pathname + querystring.slice( 0, -1 );
|
871
996
|
},
|
872
997
|
|
873
998
|
extend: extend,
|
@@ -898,7 +1023,7 @@ extend( QUnit.constructor.prototype, {
|
|
898
1023
|
// testStart: { name }
|
899
1024
|
testStart: registerLoggingCallback( "testStart" ),
|
900
1025
|
|
901
|
-
// testDone: { name, failed, passed, total }
|
1026
|
+
// testDone: { name, failed, passed, total, duration }
|
902
1027
|
testDone: registerLoggingCallback( "testDone" ),
|
903
1028
|
|
904
1029
|
// moduleStart: { name }
|
@@ -916,7 +1041,10 @@ QUnit.load = function() {
|
|
916
1041
|
runLoggingCallbacks( "begin", QUnit, {} );
|
917
1042
|
|
918
1043
|
// Initialize the config, saving the execution queue
|
919
|
-
var banner, filter, i, label, len, main, ol, toolbar, userAgent, val,
|
1044
|
+
var banner, filter, i, label, len, main, ol, toolbar, userAgent, val,
|
1045
|
+
urlConfigCheckboxesContainer, urlConfigCheckboxes, moduleFilter,
|
1046
|
+
numModules = 0,
|
1047
|
+
moduleFilterHtml = "",
|
920
1048
|
urlConfigHtml = "",
|
921
1049
|
oldconfig = extend( {}, config );
|
922
1050
|
|
@@ -937,9 +1065,28 @@ QUnit.load = function() {
|
|
937
1065
|
};
|
938
1066
|
}
|
939
1067
|
config[ val.id ] = QUnit.urlParams[ val.id ];
|
940
|
-
urlConfigHtml += "<input id='qunit-urlconfig-" +
|
1068
|
+
urlConfigHtml += "<input id='qunit-urlconfig-" + escapeText( val.id ) +
|
1069
|
+
"' name='" + escapeText( val.id ) +
|
1070
|
+
"' type='checkbox'" + ( config[ val.id ] ? " checked='checked'" : "" ) +
|
1071
|
+
" title='" + escapeText( val.tooltip ) +
|
1072
|
+
"'><label for='qunit-urlconfig-" + escapeText( val.id ) +
|
1073
|
+
"' title='" + escapeText( val.tooltip ) + "'>" + val.label + "</label>";
|
941
1074
|
}
|
942
1075
|
|
1076
|
+
moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label><select id='qunit-modulefilter' name='modulefilter'><option value='' " +
|
1077
|
+
( config.module === undefined ? "selected='selected'" : "" ) +
|
1078
|
+
">< All Modules ></option>";
|
1079
|
+
|
1080
|
+
for ( i in config.modules ) {
|
1081
|
+
if ( config.modules.hasOwnProperty( i ) ) {
|
1082
|
+
numModules += 1;
|
1083
|
+
moduleFilterHtml += "<option value='" + escapeText( encodeURIComponent(i) ) + "' " +
|
1084
|
+
( config.module === i ? "selected='selected'" : "" ) +
|
1085
|
+
">" + escapeText(i) + "</option>";
|
1086
|
+
}
|
1087
|
+
}
|
1088
|
+
moduleFilterHtml += "</select>";
|
1089
|
+
|
943
1090
|
// `userAgent` initialized at top of scope
|
944
1091
|
userAgent = id( "qunit-userAgent" );
|
945
1092
|
if ( userAgent ) {
|
@@ -994,14 +1141,33 @@ QUnit.load = function() {
|
|
994
1141
|
label.innerHTML = "Hide passed tests";
|
995
1142
|
toolbar.appendChild( label );
|
996
1143
|
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1144
|
+
urlConfigCheckboxesContainer = document.createElement("span");
|
1145
|
+
urlConfigCheckboxesContainer.innerHTML = urlConfigHtml;
|
1146
|
+
urlConfigCheckboxes = urlConfigCheckboxesContainer.getElementsByTagName("input");
|
1147
|
+
// For oldIE support:
|
1148
|
+
// * Add handlers to the individual elements instead of the container
|
1149
|
+
// * Use "click" instead of "change"
|
1150
|
+
// * Fallback from event.target to event.srcElement
|
1151
|
+
addEvents( urlConfigCheckboxes, "click", function( event ) {
|
1152
|
+
var params = {},
|
1153
|
+
target = event.target || event.srcElement;
|
1154
|
+
params[ target.name ] = target.checked ? true : undefined;
|
1002
1155
|
window.location = QUnit.url( params );
|
1003
1156
|
});
|
1004
|
-
toolbar.appendChild(
|
1157
|
+
toolbar.appendChild( urlConfigCheckboxesContainer );
|
1158
|
+
|
1159
|
+
if (numModules > 1) {
|
1160
|
+
moduleFilter = document.createElement( 'span' );
|
1161
|
+
moduleFilter.setAttribute( 'id', 'qunit-modulefilter-container' );
|
1162
|
+
moduleFilter.innerHTML = moduleFilterHtml;
|
1163
|
+
addEvent( moduleFilter.lastChild, "change", function() {
|
1164
|
+
var selectBox = moduleFilter.getElementsByTagName("select")[0],
|
1165
|
+
selectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value);
|
1166
|
+
|
1167
|
+
window.location = QUnit.url( { module: ( selectedModule === "" ) ? undefined : selectedModule } );
|
1168
|
+
});
|
1169
|
+
toolbar.appendChild(moduleFilter);
|
1170
|
+
}
|
1005
1171
|
}
|
1006
1172
|
|
1007
1173
|
// `main` initialized at top of scope
|
@@ -1039,9 +1205,9 @@ window.onerror = function ( error, filePath, linerNr ) {
|
|
1039
1205
|
}
|
1040
1206
|
QUnit.pushFailure( error, filePath + ":" + linerNr );
|
1041
1207
|
} else {
|
1042
|
-
QUnit.test( "global failure", function() {
|
1208
|
+
QUnit.test( "global failure", extend( function() {
|
1043
1209
|
QUnit.pushFailure( error, filePath + ":" + linerNr );
|
1044
|
-
});
|
1210
|
+
}, { validTest: validTest } ) );
|
1045
1211
|
}
|
1046
1212
|
return false;
|
1047
1213
|
}
|
@@ -1073,7 +1239,7 @@ function done() {
|
|
1073
1239
|
" milliseconds.<br/>",
|
1074
1240
|
"<span class='passed'>",
|
1075
1241
|
passed,
|
1076
|
-
"</span>
|
1242
|
+
"</span> assertions of <span class='total'>",
|
1077
1243
|
config.stats.all,
|
1078
1244
|
"</span> passed, <span class='failed'>",
|
1079
1245
|
config.stats.bad,
|
@@ -1108,6 +1274,11 @@ function done() {
|
|
1108
1274
|
}
|
1109
1275
|
}
|
1110
1276
|
|
1277
|
+
// scroll back to top to show results
|
1278
|
+
if ( window.scrollTo ) {
|
1279
|
+
window.scrollTo(0, 0);
|
1280
|
+
}
|
1281
|
+
|
1111
1282
|
runLoggingCallbacks( "done", QUnit, {
|
1112
1283
|
failed: config.stats.bad,
|
1113
1284
|
passed: passed,
|
@@ -1123,6 +1294,12 @@ function validTest( test ) {
|
|
1123
1294
|
module = config.module && config.module.toLowerCase(),
|
1124
1295
|
fullName = (test.module + ": " + test.testName).toLowerCase();
|
1125
1296
|
|
1297
|
+
// Internally-generated tests are always valid
|
1298
|
+
if ( test.callback && test.callback.validTest === validTest ) {
|
1299
|
+
delete test.callback.validTest;
|
1300
|
+
return true;
|
1301
|
+
}
|
1302
|
+
|
1126
1303
|
if ( config.testNumber ) {
|
1127
1304
|
return test.testNumber === config.testNumber;
|
1128
1305
|
}
|
@@ -1155,7 +1332,7 @@ function validTest( test ) {
|
|
1155
1332
|
function extractStacktrace( e, offset ) {
|
1156
1333
|
offset = offset === undefined ? 3 : offset;
|
1157
1334
|
|
1158
|
-
var stack, include, i
|
1335
|
+
var stack, include, i;
|
1159
1336
|
|
1160
1337
|
if ( e.stacktrace ) {
|
1161
1338
|
// Opera
|
@@ -1169,7 +1346,7 @@ function extractStacktrace( e, offset ) {
|
|
1169
1346
|
if ( fileName ) {
|
1170
1347
|
include = [];
|
1171
1348
|
for ( i = offset; i < stack.length; i++ ) {
|
1172
|
-
if ( stack[ i ].indexOf( fileName )
|
1349
|
+
if ( stack[ i ].indexOf( fileName ) !== -1 ) {
|
1173
1350
|
break;
|
1174
1351
|
}
|
1175
1352
|
include.push( stack[ i ] );
|
@@ -1198,17 +1375,27 @@ function sourceFromStacktrace( offset ) {
|
|
1198
1375
|
}
|
1199
1376
|
}
|
1200
1377
|
|
1201
|
-
|
1378
|
+
/**
|
1379
|
+
* Escape text for attribute or text content.
|
1380
|
+
*/
|
1381
|
+
function escapeText( s ) {
|
1202
1382
|
if ( !s ) {
|
1203
1383
|
return "";
|
1204
1384
|
}
|
1205
1385
|
s = s + "";
|
1206
|
-
|
1386
|
+
// Both single quotes and double quotes (for attributes)
|
1387
|
+
return s.replace( /['"<>&]/g, function( s ) {
|
1207
1388
|
switch( s ) {
|
1208
|
-
case
|
1209
|
-
|
1210
|
-
case "
|
1211
|
-
|
1389
|
+
case '\'':
|
1390
|
+
return ''';
|
1391
|
+
case '"':
|
1392
|
+
return '"';
|
1393
|
+
case '<':
|
1394
|
+
return '<';
|
1395
|
+
case '>':
|
1396
|
+
return '>';
|
1397
|
+
case '&':
|
1398
|
+
return '&';
|
1212
1399
|
}
|
1213
1400
|
});
|
1214
1401
|
}
|
@@ -1256,7 +1443,7 @@ function saveGlobal() {
|
|
1256
1443
|
}
|
1257
1444
|
}
|
1258
1445
|
|
1259
|
-
function checkPollution(
|
1446
|
+
function checkPollution() {
|
1260
1447
|
var newGlobals,
|
1261
1448
|
deletedGlobals,
|
1262
1449
|
old = config.pollution;
|
@@ -1305,16 +1492,53 @@ function extend( a, b ) {
|
|
1305
1492
|
return a;
|
1306
1493
|
}
|
1307
1494
|
|
1495
|
+
/**
|
1496
|
+
* @param {HTMLElement} elem
|
1497
|
+
* @param {string} type
|
1498
|
+
* @param {Function} fn
|
1499
|
+
*/
|
1308
1500
|
function addEvent( elem, type, fn ) {
|
1501
|
+
// Standards-based browsers
|
1309
1502
|
if ( elem.addEventListener ) {
|
1310
1503
|
elem.addEventListener( type, fn, false );
|
1311
|
-
|
1312
|
-
elem.attachEvent( "on" + type, fn );
|
1504
|
+
// IE
|
1313
1505
|
} else {
|
1314
|
-
fn
|
1506
|
+
elem.attachEvent( "on" + type, fn );
|
1315
1507
|
}
|
1316
1508
|
}
|
1317
1509
|
|
1510
|
+
/**
|
1511
|
+
* @param {Array|NodeList} elems
|
1512
|
+
* @param {string} type
|
1513
|
+
* @param {Function} fn
|
1514
|
+
*/
|
1515
|
+
function addEvents( elems, type, fn ) {
|
1516
|
+
var i = elems.length;
|
1517
|
+
while ( i-- ) {
|
1518
|
+
addEvent( elems[i], type, fn );
|
1519
|
+
}
|
1520
|
+
}
|
1521
|
+
|
1522
|
+
function hasClass( elem, name ) {
|
1523
|
+
return (" " + elem.className + " ").indexOf(" " + name + " ") > -1;
|
1524
|
+
}
|
1525
|
+
|
1526
|
+
function addClass( elem, name ) {
|
1527
|
+
if ( !hasClass( elem, name ) ) {
|
1528
|
+
elem.className += (elem.className ? " " : "") + name;
|
1529
|
+
}
|
1530
|
+
}
|
1531
|
+
|
1532
|
+
function removeClass( elem, name ) {
|
1533
|
+
var set = " " + elem.className + " ";
|
1534
|
+
// Class name may appear multiple times
|
1535
|
+
while ( set.indexOf(" " + name + " ") > -1 ) {
|
1536
|
+
set = set.replace(" " + name + " " , " ");
|
1537
|
+
}
|
1538
|
+
// If possible, trim it for prettiness, but not neccecarily
|
1539
|
+
elem.className = window.jQuery ? jQuery.trim( set ) : ( set.trim ? set.trim() : set );
|
1540
|
+
}
|
1541
|
+
|
1318
1542
|
function id( name ) {
|
1319
1543
|
return !!( typeof document !== "undefined" && document && document.getElementById ) &&
|
1320
1544
|
document.getElementById( name );
|
@@ -1328,7 +1552,6 @@ function registerLoggingCallback( key ) {
|
|
1328
1552
|
|
1329
1553
|
// Supports deprecated method of completely overwriting logging callbacks
|
1330
1554
|
function runLoggingCallbacks( key, scope, args ) {
|
1331
|
-
//debugger;
|
1332
1555
|
var i, callbacks;
|
1333
1556
|
if ( QUnit.hasOwnProperty( key ) ) {
|
1334
1557
|
QUnit[ key ].call(scope, args );
|
@@ -1370,6 +1593,7 @@ QUnit.equiv = (function() {
|
|
1370
1593
|
|
1371
1594
|
// for string, boolean, number and null
|
1372
1595
|
function useStrictEquality( b, a ) {
|
1596
|
+
/*jshint eqeqeq:false */
|
1373
1597
|
if ( b instanceof a.constructor || a instanceof b.constructor ) {
|
1374
1598
|
// to catch short annotaion VS 'new' annotation of a
|
1375
1599
|
// declaration
|
@@ -1404,7 +1628,8 @@ QUnit.equiv = (function() {
|
|
1404
1628
|
a.global === b.global &&
|
1405
1629
|
// (gmi) ...
|
1406
1630
|
a.ignoreCase === b.ignoreCase &&
|
1407
|
-
a.multiline === b.multiline
|
1631
|
+
a.multiline === b.multiline &&
|
1632
|
+
a.sticky === b.sticky;
|
1408
1633
|
},
|
1409
1634
|
|
1410
1635
|
// - skip when the property is a method of an instance (OOP)
|
@@ -1565,7 +1790,8 @@ QUnit.jsDump = (function() {
|
|
1565
1790
|
|
1566
1791
|
var reName = /^function (\w+)/,
|
1567
1792
|
jsDump = {
|
1568
|
-
|
1793
|
+
// type is used mostly internally, you can fix a (custom)type in advance
|
1794
|
+
parse: function( obj, type, stack ) {
|
1569
1795
|
stack = stack || [ ];
|
1570
1796
|
var inStack, res,
|
1571
1797
|
parser = this.parsers[ type || this.typeOf(obj) ];
|
@@ -1573,18 +1799,16 @@ QUnit.jsDump = (function() {
|
|
1573
1799
|
type = typeof parser;
|
1574
1800
|
inStack = inArray( obj, stack );
|
1575
1801
|
|
1576
|
-
if ( inStack
|
1802
|
+
if ( inStack !== -1 ) {
|
1577
1803
|
return "recursion(" + (inStack - stack.length) + ")";
|
1578
1804
|
}
|
1579
|
-
|
1580
|
-
if ( type == "function" ) {
|
1805
|
+
if ( type === "function" ) {
|
1581
1806
|
stack.push( obj );
|
1582
1807
|
res = parser.call( this, obj, stack );
|
1583
1808
|
stack.pop();
|
1584
1809
|
return res;
|
1585
1810
|
}
|
1586
|
-
|
1587
|
-
return ( type == "string" ) ? parser : this.parsers.error;
|
1811
|
+
return ( type === "string" ) ? parser : this.parsers.error;
|
1588
1812
|
},
|
1589
1813
|
typeOf: function( obj ) {
|
1590
1814
|
var type;
|
@@ -1611,6 +1835,8 @@ QUnit.jsDump = (function() {
|
|
1611
1835
|
( typeof obj.length === "number" && typeof obj.item !== "undefined" && ( obj.length ? obj.item(0) === obj[0] : ( obj.item( 0 ) === null && typeof obj[0] === "undefined" ) ) )
|
1612
1836
|
) {
|
1613
1837
|
type = "array";
|
1838
|
+
} else if ( obj.constructor === Error.prototype.constructor ) {
|
1839
|
+
type = "error";
|
1614
1840
|
} else {
|
1615
1841
|
type = typeof obj;
|
1616
1842
|
}
|
@@ -1619,7 +1845,8 @@ QUnit.jsDump = (function() {
|
|
1619
1845
|
separator: function() {
|
1620
1846
|
return this.multiline ? this.HTML ? "<br />" : "\n" : this.HTML ? " " : " ";
|
1621
1847
|
},
|
1622
|
-
|
1848
|
+
// extra can be a number, shortcut for increasing-calling-decreasing
|
1849
|
+
indent: function( extra ) {
|
1623
1850
|
if ( !this.multiline ) {
|
1624
1851
|
return "";
|
1625
1852
|
}
|
@@ -1648,13 +1875,16 @@ QUnit.jsDump = (function() {
|
|
1648
1875
|
parsers: {
|
1649
1876
|
window: "[Window]",
|
1650
1877
|
document: "[Document]",
|
1651
|
-
error:
|
1878
|
+
error: function(error) {
|
1879
|
+
return "Error(\"" + error.message + "\")";
|
1880
|
+
},
|
1652
1881
|
unknown: "[Unknown]",
|
1653
1882
|
"null": "null",
|
1654
1883
|
"undefined": "undefined",
|
1655
1884
|
"function": function( fn ) {
|
1656
1885
|
var ret = "function",
|
1657
|
-
|
1886
|
+
// functions never have name in IE
|
1887
|
+
name = "name" in fn ? fn.name : (reName.exec(fn) || [])[1];
|
1658
1888
|
|
1659
1889
|
if ( name ) {
|
1660
1890
|
ret += " " + name;
|
@@ -1670,13 +1900,9 @@ QUnit.jsDump = (function() {
|
|
1670
1900
|
object: function( map, stack ) {
|
1671
1901
|
var ret = [ ], keys, key, val, i;
|
1672
1902
|
QUnit.jsDump.up();
|
1673
|
-
|
1674
|
-
|
1675
|
-
|
1676
|
-
keys = [];
|
1677
|
-
for ( key in map ) {
|
1678
|
-
keys.push( key );
|
1679
|
-
}
|
1903
|
+
keys = [];
|
1904
|
+
for ( key in map ) {
|
1905
|
+
keys.push( key );
|
1680
1906
|
}
|
1681
1907
|
keys.sort();
|
1682
1908
|
for ( i = 0; i < keys.length; i++ ) {
|
@@ -1688,21 +1914,34 @@ QUnit.jsDump = (function() {
|
|
1688
1914
|
return join( "{", ret, "}" );
|
1689
1915
|
},
|
1690
1916
|
node: function( node ) {
|
1691
|
-
var
|
1917
|
+
var len, i, val,
|
1692
1918
|
open = QUnit.jsDump.HTML ? "<" : "<",
|
1693
1919
|
close = QUnit.jsDump.HTML ? ">" : ">",
|
1694
1920
|
tag = node.nodeName.toLowerCase(),
|
1695
|
-
ret = open + tag
|
1696
|
-
|
1697
|
-
|
1698
|
-
|
1699
|
-
|
1700
|
-
|
1921
|
+
ret = open + tag,
|
1922
|
+
attrs = node.attributes;
|
1923
|
+
|
1924
|
+
if ( attrs ) {
|
1925
|
+
for ( i = 0, len = attrs.length; i < len; i++ ) {
|
1926
|
+
val = attrs[i].nodeValue;
|
1927
|
+
// IE6 includes all attributes in .attributes, even ones not explicitly set.
|
1928
|
+
// Those have values like undefined, null, 0, false, "" or "inherit".
|
1929
|
+
if ( val && val !== "inherit" ) {
|
1930
|
+
ret += " " + attrs[i].nodeName + "=" + QUnit.jsDump.parse( val, "attribute" );
|
1931
|
+
}
|
1701
1932
|
}
|
1702
1933
|
}
|
1703
|
-
|
1934
|
+
ret += close;
|
1935
|
+
|
1936
|
+
// Show content of TextNode or CDATASection
|
1937
|
+
if ( node.nodeType === 3 || node.nodeType === 4 ) {
|
1938
|
+
ret += node.nodeValue;
|
1939
|
+
}
|
1940
|
+
|
1941
|
+
return ret + open + "/" + tag + close;
|
1704
1942
|
},
|
1705
|
-
|
1943
|
+
// function calls it internally, it's the arguments part of the function
|
1944
|
+
functionArgs: function( fn ) {
|
1706
1945
|
var args,
|
1707
1946
|
l = fn.length;
|
1708
1947
|
|
@@ -1712,54 +1951,34 @@ QUnit.jsDump = (function() {
|
|
1712
1951
|
|
1713
1952
|
args = new Array(l);
|
1714
1953
|
while ( l-- ) {
|
1715
|
-
|
1954
|
+
// 97 is 'a'
|
1955
|
+
args[l] = String.fromCharCode(97+l);
|
1716
1956
|
}
|
1717
1957
|
return " " + args.join( ", " ) + " ";
|
1718
1958
|
},
|
1719
|
-
|
1720
|
-
|
1721
|
-
|
1959
|
+
// object calls it internally, the key part of an item in a map
|
1960
|
+
key: quote,
|
1961
|
+
// function calls it internally, it's the content of the function
|
1962
|
+
functionCode: "[code]",
|
1963
|
+
// node calls it internally, it's an html attribute value
|
1964
|
+
attribute: quote,
|
1722
1965
|
string: quote,
|
1723
1966
|
date: quote,
|
1724
|
-
regexp: literal,
|
1967
|
+
regexp: literal,
|
1725
1968
|
number: literal,
|
1726
1969
|
"boolean": literal
|
1727
1970
|
},
|
1728
|
-
|
1729
|
-
|
1730
|
-
|
1731
|
-
|
1732
|
-
|
1733
|
-
|
1734
|
-
HTML: false,//if true, entities are escaped ( <, >, \t, space and \n )
|
1735
|
-
indentChar: " ",//indentation unit
|
1736
|
-
multiline: true //if true, items in a collection, are separated by a \n, else just a space.
|
1971
|
+
// if true, entities are escaped ( <, >, \t, space and \n )
|
1972
|
+
HTML: false,
|
1973
|
+
// indentation unit
|
1974
|
+
indentChar: " ",
|
1975
|
+
// if true, items in a collection, are separated by a \n, else just a space.
|
1976
|
+
multiline: true
|
1737
1977
|
};
|
1738
1978
|
|
1739
1979
|
return jsDump;
|
1740
1980
|
}());
|
1741
1981
|
|
1742
|
-
// from Sizzle.js
|
1743
|
-
function getText( elems ) {
|
1744
|
-
var i, elem,
|
1745
|
-
ret = "";
|
1746
|
-
|
1747
|
-
for ( i = 0; elems[i]; i++ ) {
|
1748
|
-
elem = elems[i];
|
1749
|
-
|
1750
|
-
// Get the text from text nodes and CDATA nodes
|
1751
|
-
if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
|
1752
|
-
ret += elem.nodeValue;
|
1753
|
-
|
1754
|
-
// Traverse everything else, except comment nodes
|
1755
|
-
} else if ( elem.nodeType !== 8 ) {
|
1756
|
-
ret += getText( elem.childNodes );
|
1757
|
-
}
|
1758
|
-
}
|
1759
|
-
|
1760
|
-
return ret;
|
1761
|
-
}
|
1762
|
-
|
1763
1982
|
// from jquery.js
|
1764
1983
|
function inArray( elem, array ) {
|
1765
1984
|
if ( array.indexOf ) {
|
@@ -1790,13 +2009,14 @@ function inArray( elem, array ) {
|
|
1790
2009
|
* 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"
|
1791
2010
|
*/
|
1792
2011
|
QUnit.diff = (function() {
|
2012
|
+
/*jshint eqeqeq:false, eqnull:true */
|
1793
2013
|
function diff( o, n ) {
|
1794
2014
|
var i,
|
1795
2015
|
ns = {},
|
1796
2016
|
os = {};
|
1797
2017
|
|
1798
2018
|
for ( i = 0; i < n.length; i++ ) {
|
1799
|
-
if ( ns
|
2019
|
+
if ( !hasOwn.call( ns, n[i] ) ) {
|
1800
2020
|
ns[ n[i] ] = {
|
1801
2021
|
rows: [],
|
1802
2022
|
o: null
|
@@ -1806,7 +2026,7 @@ QUnit.diff = (function() {
|
|
1806
2026
|
}
|
1807
2027
|
|
1808
2028
|
for ( i = 0; i < o.length; i++ ) {
|
1809
|
-
if ( os
|
2029
|
+
if ( !hasOwn.call( os, o[i] ) ) {
|
1810
2030
|
os[ o[i] ] = {
|
1811
2031
|
rows: [],
|
1812
2032
|
n: null
|
@@ -1819,7 +2039,7 @@ QUnit.diff = (function() {
|
|
1819
2039
|
if ( !hasOwn.call( ns, i ) ) {
|
1820
2040
|
continue;
|
1821
2041
|
}
|
1822
|
-
if ( ns[i].rows.length
|
2042
|
+
if ( ns[i].rows.length === 1 && hasOwn.call( os, i ) && os[i].rows.length === 1 ) {
|
1823
2043
|
n[ ns[i].rows[0] ] = {
|
1824
2044
|
text: n[ ns[i].rows[0] ],
|
1825
2045
|
row: os[i].rows[0]
|
@@ -1925,7 +2145,7 @@ QUnit.diff = (function() {
|
|
1925
2145
|
|
1926
2146
|
// for CommonJS enviroments, export everything
|
1927
2147
|
if ( typeof exports !== "undefined" ) {
|
1928
|
-
extend(exports, QUnit);
|
2148
|
+
extend( exports, QUnit );
|
1929
2149
|
}
|
1930
2150
|
|
1931
2151
|
// get at whatever the global object is, like window in browsers
|