qunit-rails 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * QUnit v1.5.0 - A JavaScript Unit Testing Framework
2
+ * QUnit v1.9.0 - A JavaScript Unit Testing Framework
3
3
  *
4
4
  * http://docs.jquery.com/QUnit
5
5
  *
@@ -38,10 +38,10 @@
38
38
  line-height: 1em;
39
39
  font-weight: normal;
40
40
 
41
- border-radius: 15px 15px 0 0;
42
- -moz-border-radius: 15px 15px 0 0;
43
- -webkit-border-top-right-radius: 15px;
44
- -webkit-border-top-left-radius: 15px;
41
+ border-radius: 5px 5px 0 0;
42
+ -moz-border-radius: 5px 5px 0 0;
43
+ -webkit-border-top-right-radius: 5px;
44
+ -webkit-border-top-left-radius: 5px;
45
45
  }
46
46
 
47
47
  #qunit-header a {
@@ -54,8 +54,9 @@
54
54
  color: #fff;
55
55
  }
56
56
 
57
- #qunit-header label {
57
+ #qunit-testrunner-toolbar label {
58
58
  display: inline-block;
59
+ padding: 0 .5em 0 .1em;
59
60
  }
60
61
 
61
62
  #qunit-banner {
@@ -112,13 +113,9 @@
112
113
 
113
114
  background-color: #fff;
114
115
 
115
- border-radius: 15px;
116
- -moz-border-radius: 15px;
117
- -webkit-border-radius: 15px;
118
-
119
- box-shadow: inset 0px 2px 13px #999;
120
- -moz-box-shadow: inset 0px 2px 13px #999;
121
- -webkit-box-shadow: inset 0px 2px 13px #999;
116
+ border-radius: 5px;
117
+ -moz-border-radius: 5px;
118
+ -webkit-border-radius: 5px;
122
119
  }
123
120
 
124
121
  #qunit-tests table {
@@ -161,8 +158,7 @@
161
158
  #qunit-tests b.failed { color: #710909; }
162
159
 
163
160
  #qunit-tests li li {
164
- margin: 0.5em;
165
- padding: 0.4em 0.5em 0.4em 0.5em;
161
+ padding: 5px;
166
162
  background-color: #fff;
167
163
  border-bottom: none;
168
164
  list-style-position: inside;
@@ -171,9 +167,9 @@
171
167
  /*** Passing Styles */
172
168
 
173
169
  #qunit-tests li li.pass {
174
- color: #5E740B;
170
+ color: #3c510c;
175
171
  background-color: #fff;
176
- border-left: 26px solid #C6E746;
172
+ border-left: 10px solid #C6E746;
177
173
  }
178
174
 
179
175
  #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
@@ -189,15 +185,15 @@
189
185
  #qunit-tests li li.fail {
190
186
  color: #710909;
191
187
  background-color: #fff;
192
- border-left: 26px solid #EE5757;
188
+ border-left: 10px solid #EE5757;
193
189
  white-space: pre;
194
190
  }
195
191
 
196
192
  #qunit-tests > li:last-child {
197
- border-radius: 0 0 15px 15px;
198
- -moz-border-radius: 0 0 15px 15px;
199
- -webkit-border-bottom-right-radius: 15px;
200
- -webkit-border-bottom-left-radius: 15px;
193
+ border-radius: 0 0 5px 5px;
194
+ -moz-border-radius: 0 0 5px 5px;
195
+ -webkit-border-bottom-right-radius: 5px;
196
+ -webkit-border-bottom-left-radius: 5px;
201
197
  }
202
198
 
203
199
  #qunit-tests .fail { color: #000000; background-color: #EE5757; }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qunit-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-25 00:00:00.000000000 Z
12
+ date: 2012-08-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: railties
@@ -27,7 +27,7 @@ dependencies:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
29
  version: 3.2.3
30
- description: Support for the Rails 3.2 asset pipeline
30
+ description: QUnit for Rails 3.2+
31
31
  email:
32
32
  - lrodriguezsanc@gmail.com
33
33
  executables: []
@@ -40,20 +40,20 @@ files:
40
40
  - MIT-LICENSE
41
41
  - README.md
42
42
  - Rakefile
43
- - app/controllers/qunit/rails/application_controller.rb
44
43
  - app/controllers/qunit/rails/test_controller.rb
45
44
  - app/views/qunit/rails/test/index.html.erb
46
- - config/initializers/qunitizer.rb
45
+ - config/initializers/qunit-rails.rb
47
46
  - config/routes.rb
48
- - lib/assets/javascripts/qunit.js
49
- - lib/assets/stylesheets/qunit.css
50
47
  - lib/generators/qunit/install_generator.rb
51
48
  - lib/generators/templates/test_helper.css
52
49
  - lib/generators/templates/test_helper.js
50
+ - lib/generators/templates/test_helper.js.coffee
53
51
  - lib/qunit-rails.rb
54
52
  - lib/qunit/rails/engine.rb
55
53
  - lib/qunit/rails/version.rb
56
54
  - qunit-rails.gemspec
55
+ - vendor/assets/javascripts/qunit.js
56
+ - vendor/assets/stylesheets/qunit.css
57
57
  homepage: https://github.com/frodsan/qunit-rails
58
58
  licenses: []
59
59
  post_install_message:
@@ -79,3 +79,4 @@ signing_key:
79
79
  specification_version: 3
80
80
  summary: Qunit for Rails 3.2+
81
81
  test_files: []
82
+ has_rdoc:
@@ -1,6 +0,0 @@
1
- module Qunit
2
- module Rails
3
- class ApplicationController < ActionController::Base
4
- end
5
- end
6
- end
@@ -1,1669 +0,0 @@
1
- /**
2
- * QUnit v1.5.0 - A JavaScript Unit Testing Framework
3
- *
4
- * http://docs.jquery.com/QUnit
5
- *
6
- * Copyright (c) 2012 John Resig, Jörn Zaefferer
7
- * Dual licensed under the MIT (MIT-LICENSE.txt)
8
- * or GPL (GPL-LICENSE.txt) licenses.
9
- */
10
-
11
- (function(window) {
12
-
13
- var defined = {
14
- setTimeout: typeof window.setTimeout !== "undefined",
15
- sessionStorage: (function() {
16
- var x = "qunit-test-string";
17
- try {
18
- sessionStorage.setItem(x, x);
19
- sessionStorage.removeItem(x);
20
- return true;
21
- } catch(e) {
22
- return false;
23
- }
24
- }())
25
- };
26
-
27
- var testId = 0,
28
- toString = Object.prototype.toString,
29
- hasOwn = Object.prototype.hasOwnProperty;
30
-
31
- var Test = function(name, testName, expected, async, callback) {
32
- this.name = name;
33
- this.testName = testName;
34
- this.expected = expected;
35
- this.async = async;
36
- this.callback = callback;
37
- this.assertions = [];
38
- };
39
- Test.prototype = {
40
- init: function() {
41
- var tests = id("qunit-tests");
42
- if (tests) {
43
- var b = document.createElement("strong");
44
- b.innerHTML = "Running " + this.name;
45
- var li = document.createElement("li");
46
- li.appendChild( b );
47
- li.className = "running";
48
- li.id = this.id = "test-output" + testId++;
49
- tests.appendChild( li );
50
- }
51
- },
52
- setup: function() {
53
- if (this.module != config.previousModule) {
54
- if ( config.previousModule ) {
55
- runLoggingCallbacks('moduleDone', QUnit, {
56
- name: config.previousModule,
57
- failed: config.moduleStats.bad,
58
- passed: config.moduleStats.all - config.moduleStats.bad,
59
- total: config.moduleStats.all
60
- } );
61
- }
62
- config.previousModule = this.module;
63
- config.moduleStats = { all: 0, bad: 0 };
64
- runLoggingCallbacks( 'moduleStart', QUnit, {
65
- name: this.module
66
- } );
67
- } else if (config.autorun) {
68
- runLoggingCallbacks( 'moduleStart', QUnit, {
69
- name: this.module
70
- } );
71
- }
72
-
73
- config.current = this;
74
- this.testEnvironment = extend({
75
- setup: function() {},
76
- teardown: function() {}
77
- }, this.moduleTestEnvironment);
78
-
79
- runLoggingCallbacks( 'testStart', QUnit, {
80
- name: this.testName,
81
- module: this.module
82
- });
83
-
84
- // allow utility functions to access the current test environment
85
- // TODO why??
86
- QUnit.current_testEnvironment = this.testEnvironment;
87
-
88
- if ( !config.pollution ) {
89
- saveGlobal();
90
- }
91
- if ( config.notrycatch ) {
92
- this.testEnvironment.setup.call(this.testEnvironment);
93
- return;
94
- }
95
- try {
96
- this.testEnvironment.setup.call(this.testEnvironment);
97
- } catch(e) {
98
- QUnit.pushFailure( "Setup failed on " + this.testName + ": " + e.message, extractStacktrace( e, 1 ) );
99
- }
100
- },
101
- run: function() {
102
- config.current = this;
103
-
104
- var running = id("qunit-testresult");
105
-
106
- if ( running ) {
107
- running.innerHTML = "Running: <br/>" + this.name;
108
- }
109
-
110
- if ( this.async ) {
111
- QUnit.stop();
112
- }
113
-
114
- if ( config.notrycatch ) {
115
- this.callback.call(this.testEnvironment);
116
- return;
117
- }
118
- try {
119
- this.callback.call(this.testEnvironment);
120
- } catch(e) {
121
- QUnit.pushFailure( "Died on test #" + (this.assertions.length + 1) + ": " + e.message, extractStacktrace( e, 1 ) );
122
- // else next test will carry the responsibility
123
- saveGlobal();
124
-
125
- // Restart the tests if they're blocking
126
- if ( config.blocking ) {
127
- QUnit.start();
128
- }
129
- }
130
- },
131
- teardown: function() {
132
- config.current = this;
133
- if ( config.notrycatch ) {
134
- this.testEnvironment.teardown.call(this.testEnvironment);
135
- return;
136
- } else {
137
- try {
138
- this.testEnvironment.teardown.call(this.testEnvironment);
139
- } catch(e) {
140
- QUnit.pushFailure( "Teardown failed on " + this.testName + ": " + e.message, extractStacktrace( e, 1 ) );
141
- }
142
- }
143
- checkPollution();
144
- },
145
- finish: function() {
146
- config.current = this;
147
- if ( this.expected != null && this.expected != this.assertions.length ) {
148
- QUnit.pushFailure( "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run" );
149
- } else if ( this.expected == null && !this.assertions.length ) {
150
- QUnit.pushFailure( "Expected at least one assertion, but none were run - call expect(0) to accept zero assertions." );
151
- }
152
-
153
- var good = 0, bad = 0,
154
- li, i,
155
- tests = id("qunit-tests");
156
-
157
- config.stats.all += this.assertions.length;
158
- config.moduleStats.all += this.assertions.length;
159
-
160
- if ( tests ) {
161
- var ol = document.createElement("ol");
162
-
163
- for ( i = 0; i < this.assertions.length; i++ ) {
164
- var assertion = this.assertions[i];
165
-
166
- li = document.createElement("li");
167
- li.className = assertion.result ? "pass" : "fail";
168
- li.innerHTML = assertion.message || (assertion.result ? "okay" : "failed");
169
- ol.appendChild( li );
170
-
171
- if ( assertion.result ) {
172
- good++;
173
- } else {
174
- bad++;
175
- config.stats.bad++;
176
- config.moduleStats.bad++;
177
- }
178
- }
179
-
180
- // store result when possible
181
- if ( QUnit.config.reorder && defined.sessionStorage ) {
182
- if (bad) {
183
- sessionStorage.setItem("qunit-test-" + this.module + "-" + this.testName, bad);
184
- } else {
185
- sessionStorage.removeItem("qunit-test-" + this.module + "-" + this.testName);
186
- }
187
- }
188
-
189
- if (bad === 0) {
190
- ol.style.display = "none";
191
- }
192
-
193
- var b = document.createElement("strong");
194
- b.innerHTML = this.name + " <b class='counts'>(<b class='failed'>" + bad + "</b>, <b class='passed'>" + good + "</b>, " + this.assertions.length + ")</b>";
195
-
196
- var a = document.createElement("a");
197
- a.innerHTML = "Rerun";
198
- a.href = QUnit.url({ filter: getText([b]).replace(/\([^)]+\)$/, "").replace(/(^\s*|\s*$)/g, "") });
199
-
200
- addEvent(b, "click", function() {
201
- var next = b.nextSibling.nextSibling,
202
- display = next.style.display;
203
- next.style.display = display === "none" ? "block" : "none";
204
- });
205
-
206
- addEvent(b, "dblclick", function(e) {
207
- var target = e && e.target ? e.target : window.event.srcElement;
208
- if ( target.nodeName.toLowerCase() == "span" || target.nodeName.toLowerCase() == "b" ) {
209
- target = target.parentNode;
210
- }
211
- if ( window.location && target.nodeName.toLowerCase() === "strong" ) {
212
- window.location = QUnit.url({ filter: getText([target]).replace(/\([^)]+\)$/, "").replace(/(^\s*|\s*$)/g, "") });
213
- }
214
- });
215
-
216
- li = id(this.id);
217
- li.className = bad ? "fail" : "pass";
218
- li.removeChild( li.firstChild );
219
- li.appendChild( b );
220
- li.appendChild( a );
221
- li.appendChild( ol );
222
-
223
- } else {
224
- for ( i = 0; i < this.assertions.length; i++ ) {
225
- if ( !this.assertions[i].result ) {
226
- bad++;
227
- config.stats.bad++;
228
- config.moduleStats.bad++;
229
- }
230
- }
231
- }
232
-
233
- QUnit.reset();
234
-
235
- runLoggingCallbacks( 'testDone', QUnit, {
236
- name: this.testName,
237
- module: this.module,
238
- failed: bad,
239
- passed: this.assertions.length - bad,
240
- total: this.assertions.length
241
- } );
242
- },
243
-
244
- queue: function() {
245
- var test = this;
246
- synchronize(function() {
247
- test.init();
248
- });
249
- function run() {
250
- // each of these can by async
251
- synchronize(function() {
252
- test.setup();
253
- });
254
- synchronize(function() {
255
- test.run();
256
- });
257
- synchronize(function() {
258
- test.teardown();
259
- });
260
- synchronize(function() {
261
- test.finish();
262
- });
263
- }
264
- // defer when previous test run passed, if storage is available
265
- var bad = QUnit.config.reorder && defined.sessionStorage && +sessionStorage.getItem("qunit-test-" + this.module + "-" + this.testName);
266
- if (bad) {
267
- run();
268
- } else {
269
- synchronize(run, true);
270
- }
271
- }
272
-
273
- };
274
-
275
- var QUnit = {
276
-
277
- // call on start of module test to prepend name to all tests
278
- module: function(name, testEnvironment) {
279
- config.currentModule = name;
280
- config.currentModuleTestEnviroment = testEnvironment;
281
- },
282
-
283
- asyncTest: function(testName, expected, callback) {
284
- if ( arguments.length === 2 ) {
285
- callback = expected;
286
- expected = null;
287
- }
288
-
289
- QUnit.test(testName, expected, callback, true);
290
- },
291
-
292
- test: function(testName, expected, callback, async) {
293
- var name = '<span class="test-name">' + escapeInnerText(testName) + '</span>';
294
-
295
- if ( arguments.length === 2 ) {
296
- callback = expected;
297
- expected = null;
298
- }
299
-
300
- if ( config.currentModule ) {
301
- name = '<span class="module-name">' + config.currentModule + "</span>: " + name;
302
- }
303
-
304
- if ( !validTest(config.currentModule + ": " + testName) ) {
305
- return;
306
- }
307
-
308
- var test = new Test(name, testName, expected, async, callback);
309
- test.module = config.currentModule;
310
- test.moduleTestEnvironment = config.currentModuleTestEnviroment;
311
- test.queue();
312
- },
313
-
314
- // Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.
315
- expect: function(asserts) {
316
- config.current.expected = asserts;
317
- },
318
-
319
- // Asserts true.
320
- // @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
321
- ok: function(result, msg) {
322
- if (!config.current) {
323
- throw new Error("ok() assertion outside test context, was " + sourceFromStacktrace(2));
324
- }
325
- result = !!result;
326
- var details = {
327
- result: result,
328
- message: msg
329
- };
330
- msg = escapeInnerText(msg || (result ? "okay" : "failed"));
331
- if ( !result ) {
332
- var source = sourceFromStacktrace(2);
333
- if (source) {
334
- details.source = source;
335
- msg += '<table><tr class="test-source"><th>Source: </th><td><pre>' + escapeInnerText(source) + '</pre></td></tr></table>';
336
- }
337
- }
338
- runLoggingCallbacks( 'log', QUnit, details );
339
- config.current.assertions.push({
340
- result: result,
341
- message: msg
342
- });
343
- },
344
-
345
- // Checks that the first two arguments are equal, with an optional message. Prints out both actual and expected values.
346
- // @example equal( format("Received {0} bytes.", 2), "Received 2 bytes." );
347
- equal: function(actual, expected, message) {
348
- QUnit.push(expected == actual, actual, expected, message);
349
- },
350
-
351
- notEqual: function(actual, expected, message) {
352
- QUnit.push(expected != actual, actual, expected, message);
353
- },
354
-
355
- deepEqual: function(actual, expected, message) {
356
- QUnit.push(QUnit.equiv(actual, expected), actual, expected, message);
357
- },
358
-
359
- notDeepEqual: function(actual, expected, message) {
360
- QUnit.push(!QUnit.equiv(actual, expected), actual, expected, message);
361
- },
362
-
363
- strictEqual: function(actual, expected, message) {
364
- QUnit.push(expected === actual, actual, expected, message);
365
- },
366
-
367
- notStrictEqual: function(actual, expected, message) {
368
- QUnit.push(expected !== actual, actual, expected, message);
369
- },
370
-
371
- raises: function(block, expected, message) {
372
- var actual, ok = false;
373
-
374
- if (typeof expected === 'string') {
375
- message = expected;
376
- expected = null;
377
- }
378
-
379
- try {
380
- block.call(config.current.testEnvironment);
381
- } catch (e) {
382
- actual = e;
383
- }
384
-
385
- if (actual) {
386
- // we don't want to validate thrown error
387
- if (!expected) {
388
- ok = true;
389
- // expected is a regexp
390
- } else if (QUnit.objectType(expected) === "regexp") {
391
- ok = expected.test(actual);
392
- // expected is a constructor
393
- } else if (actual instanceof expected) {
394
- ok = true;
395
- // expected is a validation function which returns true is validation passed
396
- } else if (expected.call({}, actual) === true) {
397
- ok = true;
398
- }
399
- }
400
-
401
- QUnit.ok(ok, message);
402
- },
403
-
404
- start: function(count) {
405
- config.semaphore -= count || 1;
406
- if (config.semaphore > 0) {
407
- // don't start until equal number of stop-calls
408
- return;
409
- }
410
- if (config.semaphore < 0) {
411
- // ignore if start is called more often then stop
412
- config.semaphore = 0;
413
- }
414
- // A slight delay, to avoid any current callbacks
415
- if ( defined.setTimeout ) {
416
- window.setTimeout(function() {
417
- if (config.semaphore > 0) {
418
- return;
419
- }
420
- if ( config.timeout ) {
421
- clearTimeout(config.timeout);
422
- }
423
-
424
- config.blocking = false;
425
- process(true);
426
- }, 13);
427
- } else {
428
- config.blocking = false;
429
- process(true);
430
- }
431
- },
432
-
433
- stop: function(count) {
434
- config.semaphore += count || 1;
435
- config.blocking = true;
436
-
437
- if ( config.testTimeout && defined.setTimeout ) {
438
- clearTimeout(config.timeout);
439
- config.timeout = window.setTimeout(function() {
440
- QUnit.ok( false, "Test timed out" );
441
- config.semaphore = 1;
442
- QUnit.start();
443
- }, config.testTimeout);
444
- }
445
- }
446
- };
447
-
448
- //We want access to the constructor's prototype
449
- (function() {
450
- function F(){}
451
- F.prototype = QUnit;
452
- QUnit = new F();
453
- //Make F QUnit's constructor so that we can add to the prototype later
454
- QUnit.constructor = F;
455
- }());
456
-
457
- // deprecated; still export them to window to provide clear error messages
458
- // next step: remove entirely
459
- QUnit.equals = function() {
460
- QUnit.push(false, false, false, "QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead");
461
- };
462
- QUnit.same = function() {
463
- QUnit.push(false, false, false, "QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead");
464
- };
465
-
466
- // Maintain internal state
467
- var config = {
468
- // The queue of tests to run
469
- queue: [],
470
-
471
- // block until document ready
472
- blocking: true,
473
-
474
- // when enabled, show only failing tests
475
- // gets persisted through sessionStorage and can be changed in UI via checkbox
476
- hidepassed: false,
477
-
478
- // by default, run previously failed tests first
479
- // very useful in combination with "Hide passed tests" checked
480
- reorder: true,
481
-
482
- // by default, modify document.title when suite is done
483
- altertitle: true,
484
-
485
- urlConfig: ['noglobals', 'notrycatch'],
486
-
487
- //logging callback queues
488
- begin: [],
489
- done: [],
490
- log: [],
491
- testStart: [],
492
- testDone: [],
493
- moduleStart: [],
494
- moduleDone: []
495
- };
496
-
497
- // Load paramaters
498
- (function() {
499
- var location = window.location || { search: "", protocol: "file:" },
500
- params = location.search.slice( 1 ).split( "&" ),
501
- length = params.length,
502
- urlParams = {},
503
- current;
504
-
505
- if ( params[ 0 ] ) {
506
- for ( var i = 0; i < length; i++ ) {
507
- current = params[ i ].split( "=" );
508
- current[ 0 ] = decodeURIComponent( current[ 0 ] );
509
- // allow just a key to turn on a flag, e.g., test.html?noglobals
510
- current[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true;
511
- urlParams[ current[ 0 ] ] = current[ 1 ];
512
- }
513
- }
514
-
515
- QUnit.urlParams = urlParams;
516
- config.filter = urlParams.filter;
517
-
518
- // Figure out if we're running the tests from a server or not
519
- QUnit.isLocal = location.protocol === 'file:';
520
- }());
521
-
522
- // Expose the API as global variables, unless an 'exports'
523
- // object exists, in that case we assume we're in CommonJS - export everything at the end
524
- if ( typeof exports === "undefined" || typeof require === "undefined" ) {
525
- extend(window, QUnit);
526
- window.QUnit = QUnit;
527
- }
528
-
529
- // define these after exposing globals to keep them in these QUnit namespace only
530
- extend(QUnit, {
531
- config: config,
532
-
533
- // Initialize the configuration options
534
- init: function() {
535
- extend(config, {
536
- stats: { all: 0, bad: 0 },
537
- moduleStats: { all: 0, bad: 0 },
538
- started: +new Date(),
539
- updateRate: 1000,
540
- blocking: false,
541
- autostart: true,
542
- autorun: false,
543
- filter: "",
544
- queue: [],
545
- semaphore: 0
546
- });
547
-
548
- var qunit = id( "qunit" );
549
- if ( qunit ) {
550
- qunit.innerHTML =
551
- '<h1 id="qunit-header">' + escapeInnerText( document.title ) + '</h1>' +
552
- '<h2 id="qunit-banner"></h2>' +
553
- '<div id="qunit-testrunner-toolbar"></div>' +
554
- '<h2 id="qunit-userAgent"></h2>' +
555
- '<ol id="qunit-tests"></ol>';
556
- }
557
-
558
- var tests = id( "qunit-tests" ),
559
- banner = id( "qunit-banner" ),
560
- result = id( "qunit-testresult" );
561
-
562
- if ( tests ) {
563
- tests.innerHTML = "";
564
- }
565
-
566
- if ( banner ) {
567
- banner.className = "";
568
- }
569
-
570
- if ( result ) {
571
- result.parentNode.removeChild( result );
572
- }
573
-
574
- if ( tests ) {
575
- result = document.createElement( "p" );
576
- result.id = "qunit-testresult";
577
- result.className = "result";
578
- tests.parentNode.insertBefore( result, tests );
579
- result.innerHTML = 'Running...<br/>&nbsp;';
580
- }
581
- },
582
-
583
- // Resets the test setup. Useful for tests that modify the DOM.
584
- // If jQuery is available, uses jQuery's html(), otherwise just innerHTML.
585
- reset: function() {
586
- if ( window.jQuery ) {
587
- jQuery( "#qunit-fixture" ).html( config.fixture );
588
- } else {
589
- var main = id( 'qunit-fixture' );
590
- if ( main ) {
591
- main.innerHTML = config.fixture;
592
- }
593
- }
594
- },
595
-
596
- // Trigger an event on an element.
597
- // @example triggerEvent( document.body, "click" );
598
- triggerEvent: function( elem, type, event ) {
599
- if ( document.createEvent ) {
600
- event = document.createEvent("MouseEvents");
601
- event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView,
602
- 0, 0, 0, 0, 0, false, false, false, false, 0, null);
603
- elem.dispatchEvent( event );
604
-
605
- } else if ( elem.fireEvent ) {
606
- elem.fireEvent("on"+type);
607
- }
608
- },
609
-
610
- // Safe object type checking
611
- is: function( type, obj ) {
612
- return QUnit.objectType( obj ) == type;
613
- },
614
-
615
- objectType: function( obj ) {
616
- if (typeof obj === "undefined") {
617
- return "undefined";
618
-
619
- // consider: typeof null === object
620
- }
621
- if (obj === null) {
622
- return "null";
623
- }
624
-
625
- var type = toString.call( obj ).match(/^\[object\s(.*)\]$/)[1] || '';
626
-
627
- switch (type) {
628
- case 'Number':
629
- if (isNaN(obj)) {
630
- return "nan";
631
- }
632
- return "number";
633
- case 'String':
634
- case 'Boolean':
635
- case 'Array':
636
- case 'Date':
637
- case 'RegExp':
638
- case 'Function':
639
- return type.toLowerCase();
640
- }
641
- if (typeof obj === "object") {
642
- return "object";
643
- }
644
- return undefined;
645
- },
646
-
647
- push: function(result, actual, expected, message) {
648
- if (!config.current) {
649
- throw new Error("assertion outside test context, was " + sourceFromStacktrace());
650
- }
651
- var details = {
652
- result: result,
653
- message: message,
654
- actual: actual,
655
- expected: expected
656
- };
657
-
658
- message = escapeInnerText(message) || (result ? "okay" : "failed");
659
- message = '<span class="test-message">' + message + "</span>";
660
- var output = message;
661
- if (!result) {
662
- expected = escapeInnerText(QUnit.jsDump.parse(expected));
663
- actual = escapeInnerText(QUnit.jsDump.parse(actual));
664
- output += '<table><tr class="test-expected"><th>Expected: </th><td><pre>' + expected + '</pre></td></tr>';
665
- if (actual != expected) {
666
- output += '<tr class="test-actual"><th>Result: </th><td><pre>' + actual + '</pre></td></tr>';
667
- output += '<tr class="test-diff"><th>Diff: </th><td><pre>' + QUnit.diff(expected, actual) +'</pre></td></tr>';
668
- }
669
- var source = sourceFromStacktrace();
670
- if (source) {
671
- details.source = source;
672
- output += '<tr class="test-source"><th>Source: </th><td><pre>' + escapeInnerText(source) + '</pre></td></tr>';
673
- }
674
- output += "</table>";
675
- }
676
-
677
- runLoggingCallbacks( 'log', QUnit, details );
678
-
679
- config.current.assertions.push({
680
- result: !!result,
681
- message: output
682
- });
683
- },
684
-
685
- pushFailure: function(message, source) {
686
- var details = {
687
- result: false,
688
- message: message
689
- };
690
- var output = escapeInnerText(message);
691
- if (source) {
692
- details.source = source;
693
- output += '<table><tr class="test-source"><th>Source: </th><td><pre>' + escapeInnerText(source) + '</pre></td></tr></table>';
694
- }
695
- runLoggingCallbacks( 'log', QUnit, details );
696
- config.current.assertions.push({
697
- result: false,
698
- message: output
699
- });
700
- },
701
-
702
- url: function( params ) {
703
- params = extend( extend( {}, QUnit.urlParams ), params );
704
- var querystring = "?",
705
- key;
706
- for ( key in params ) {
707
- if ( !hasOwn.call( params, key ) ) {
708
- continue;
709
- }
710
- querystring += encodeURIComponent( key ) + "=" +
711
- encodeURIComponent( params[ key ] ) + "&";
712
- }
713
- return window.location.pathname + querystring.slice( 0, -1 );
714
- },
715
-
716
- extend: extend,
717
- id: id,
718
- addEvent: addEvent
719
- });
720
-
721
- //QUnit.constructor is set to the empty F() above so that we can add to it's prototype later
722
- //Doing this allows us to tell if the following methods have been overwritten on the actual
723
- //QUnit object, which is a deprecated way of using the callbacks.
724
- extend(QUnit.constructor.prototype, {
725
- // Logging callbacks; all receive a single argument with the listed properties
726
- // run test/logs.html for any related changes
727
- begin: registerLoggingCallback('begin'),
728
- // done: { failed, passed, total, runtime }
729
- done: registerLoggingCallback('done'),
730
- // log: { result, actual, expected, message }
731
- log: registerLoggingCallback('log'),
732
- // testStart: { name }
733
- testStart: registerLoggingCallback('testStart'),
734
- // testDone: { name, failed, passed, total }
735
- testDone: registerLoggingCallback('testDone'),
736
- // moduleStart: { name }
737
- moduleStart: registerLoggingCallback('moduleStart'),
738
- // moduleDone: { name, failed, passed, total }
739
- moduleDone: registerLoggingCallback('moduleDone')
740
- });
741
-
742
- if ( typeof document === "undefined" || document.readyState === "complete" ) {
743
- config.autorun = true;
744
- }
745
-
746
- QUnit.load = function() {
747
- runLoggingCallbacks( 'begin', QUnit, {} );
748
-
749
- // Initialize the config, saving the execution queue
750
- var oldconfig = extend({}, config);
751
- QUnit.init();
752
- extend(config, oldconfig);
753
-
754
- config.blocking = false;
755
-
756
- var urlConfigHtml = '', len = config.urlConfig.length;
757
- for ( var i = 0, val; i < len; i++ ) {
758
- val = config.urlConfig[i];
759
- config[val] = QUnit.urlParams[val];
760
- urlConfigHtml += '<label><input name="' + val + '" type="checkbox"' + ( config[val] ? ' checked="checked"' : '' ) + '>' + val + '</label>';
761
- }
762
-
763
- var userAgent = id("qunit-userAgent");
764
- if ( userAgent ) {
765
- userAgent.innerHTML = navigator.userAgent;
766
- }
767
- var banner = id("qunit-header");
768
- if ( banner ) {
769
- banner.innerHTML = '<a href="' + QUnit.url({ filter: undefined }) + '"> ' + banner.innerHTML + '</a> ' + urlConfigHtml;
770
- addEvent( banner, "change", function( event ) {
771
- var params = {};
772
- params[ event.target.name ] = event.target.checked ? true : undefined;
773
- window.location = QUnit.url( params );
774
- });
775
- }
776
-
777
- var toolbar = id("qunit-testrunner-toolbar");
778
- if ( toolbar ) {
779
- var filter = document.createElement("input");
780
- filter.type = "checkbox";
781
- filter.id = "qunit-filter-pass";
782
- addEvent( filter, "click", function() {
783
- var ol = document.getElementById("qunit-tests");
784
- if ( filter.checked ) {
785
- ol.className = ol.className + " hidepass";
786
- } else {
787
- var tmp = " " + ol.className.replace( /[\n\t\r]/g, " " ) + " ";
788
- ol.className = tmp.replace(/ hidepass /, " ");
789
- }
790
- if ( defined.sessionStorage ) {
791
- if (filter.checked) {
792
- sessionStorage.setItem("qunit-filter-passed-tests", "true");
793
- } else {
794
- sessionStorage.removeItem("qunit-filter-passed-tests");
795
- }
796
- }
797
- });
798
- if ( config.hidepassed || defined.sessionStorage && sessionStorage.getItem("qunit-filter-passed-tests") ) {
799
- filter.checked = true;
800
- var ol = document.getElementById("qunit-tests");
801
- ol.className = ol.className + " hidepass";
802
- }
803
- toolbar.appendChild( filter );
804
-
805
- var label = document.createElement("label");
806
- label.setAttribute("for", "qunit-filter-pass");
807
- label.innerHTML = "Hide passed tests";
808
- toolbar.appendChild( label );
809
- }
810
-
811
- var main = id('qunit-fixture');
812
- if ( main ) {
813
- config.fixture = main.innerHTML;
814
- }
815
-
816
- if (config.autostart) {
817
- QUnit.start();
818
- }
819
- };
820
-
821
- addEvent(window, "load", QUnit.load);
822
-
823
- // addEvent(window, "error") gives us a useless event object
824
- window.onerror = function( message, file, line ) {
825
- if ( QUnit.config.current ) {
826
- QUnit.pushFailure( message, file + ":" + line );
827
- } else {
828
- QUnit.test( "global failure", function() {
829
- QUnit.pushFailure( message, file + ":" + line );
830
- });
831
- }
832
- };
833
-
834
- function done() {
835
- config.autorun = true;
836
-
837
- // Log the last module results
838
- if ( config.currentModule ) {
839
- runLoggingCallbacks( 'moduleDone', QUnit, {
840
- name: config.currentModule,
841
- failed: config.moduleStats.bad,
842
- passed: config.moduleStats.all - config.moduleStats.bad,
843
- total: config.moduleStats.all
844
- } );
845
- }
846
-
847
- var banner = id("qunit-banner"),
848
- tests = id("qunit-tests"),
849
- runtime = +new Date() - config.started,
850
- passed = config.stats.all - config.stats.bad,
851
- html = [
852
- 'Tests completed in ',
853
- runtime,
854
- ' milliseconds.<br/>',
855
- '<span class="passed">',
856
- passed,
857
- '</span> tests of <span class="total">',
858
- config.stats.all,
859
- '</span> passed, <span class="failed">',
860
- config.stats.bad,
861
- '</span> failed.'
862
- ].join('');
863
-
864
- if ( banner ) {
865
- banner.className = (config.stats.bad ? "qunit-fail" : "qunit-pass");
866
- }
867
-
868
- if ( tests ) {
869
- id( "qunit-testresult" ).innerHTML = html;
870
- }
871
-
872
- if ( config.altertitle && typeof document !== "undefined" && document.title ) {
873
- // show ✖ for good, ✔ for bad suite result in title
874
- // use escape sequences in case file gets loaded with non-utf-8-charset
875
- document.title = [
876
- (config.stats.bad ? "\u2716" : "\u2714"),
877
- document.title.replace(/^[\u2714\u2716] /i, "")
878
- ].join(" ");
879
- }
880
-
881
- // clear own sessionStorage items if all tests passed
882
- if ( config.reorder && defined.sessionStorage && config.stats.bad === 0 ) {
883
- var key;
884
- for ( var i = 0; i < sessionStorage.length; i++ ) {
885
- key = sessionStorage.key( i++ );
886
- if ( key.indexOf("qunit-test-") === 0 ) {
887
- sessionStorage.removeItem( key );
888
- }
889
- }
890
- }
891
-
892
- runLoggingCallbacks( 'done', QUnit, {
893
- failed: config.stats.bad,
894
- passed: passed,
895
- total: config.stats.all,
896
- runtime: runtime
897
- } );
898
- }
899
-
900
- function validTest( name ) {
901
- var filter = config.filter,
902
- run = false;
903
-
904
- if ( !filter ) {
905
- return true;
906
- }
907
-
908
- var not = filter.charAt( 0 ) === "!";
909
- if ( not ) {
910
- filter = filter.slice( 1 );
911
- }
912
-
913
- if ( name.indexOf( filter ) !== -1 ) {
914
- return !not;
915
- }
916
-
917
- if ( not ) {
918
- run = true;
919
- }
920
-
921
- return run;
922
- }
923
-
924
- // so far supports only Firefox, Chrome and Opera (buggy), Safari (for real exceptions)
925
- // Later Safari and IE10 are supposed to support error.stack as well
926
- // See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack
927
- function extractStacktrace( e, offset ) {
928
- offset = offset || 3;
929
- if (e.stacktrace) {
930
- // Opera
931
- return e.stacktrace.split("\n")[offset + 3];
932
- } else if (e.stack) {
933
- // Firefox, Chrome
934
- var stack = e.stack.split("\n");
935
- if (/^error$/i.test(stack[0])) {
936
- stack.shift();
937
- }
938
- return stack[offset];
939
- } else if (e.sourceURL) {
940
- // Safari, PhantomJS
941
- // hopefully one day Safari provides actual stacktraces
942
- // exclude useless self-reference for generated Error objects
943
- if ( /qunit.js$/.test( e.sourceURL ) ) {
944
- return;
945
- }
946
- // for actual exceptions, this is useful
947
- return e.sourceURL + ":" + e.line;
948
- }
949
- }
950
- function sourceFromStacktrace(offset) {
951
- try {
952
- throw new Error();
953
- } catch ( e ) {
954
- return extractStacktrace( e, offset );
955
- }
956
- }
957
-
958
- function escapeInnerText(s) {
959
- if (!s) {
960
- return "";
961
- }
962
- s = s + "";
963
- return s.replace(/[\&<>]/g, function(s) {
964
- switch(s) {
965
- case "&": return "&amp;";
966
- case "<": return "&lt;";
967
- case ">": return "&gt;";
968
- default: return s;
969
- }
970
- });
971
- }
972
-
973
- function synchronize( callback, last ) {
974
- config.queue.push( callback );
975
-
976
- if ( config.autorun && !config.blocking ) {
977
- process(last);
978
- }
979
- }
980
-
981
- function process( last ) {
982
- function next() {
983
- process( last );
984
- }
985
- var start = new Date().getTime();
986
- config.depth = config.depth ? config.depth + 1 : 1;
987
-
988
- while ( config.queue.length && !config.blocking ) {
989
- if ( !defined.setTimeout || config.updateRate <= 0 || ( ( new Date().getTime() - start ) < config.updateRate ) ) {
990
- config.queue.shift()();
991
- } else {
992
- window.setTimeout( next, 13 );
993
- break;
994
- }
995
- }
996
- config.depth--;
997
- if ( last && !config.blocking && !config.queue.length && config.depth === 0 ) {
998
- done();
999
- }
1000
- }
1001
-
1002
- function saveGlobal() {
1003
- config.pollution = [];
1004
-
1005
- if ( config.noglobals ) {
1006
- for ( var key in window ) {
1007
- if ( !hasOwn.call( window, key ) ) {
1008
- continue;
1009
- }
1010
- config.pollution.push( key );
1011
- }
1012
- }
1013
- }
1014
-
1015
- function checkPollution( name ) {
1016
- var old = config.pollution;
1017
- saveGlobal();
1018
-
1019
- var newGlobals = diff( config.pollution, old );
1020
- if ( newGlobals.length > 0 ) {
1021
- QUnit.pushFailure( "Introduced global variable(s): " + newGlobals.join(", ") );
1022
- }
1023
-
1024
- var deletedGlobals = diff( old, config.pollution );
1025
- if ( deletedGlobals.length > 0 ) {
1026
- QUnit.pushFailure( "Deleted global variable(s): " + deletedGlobals.join(", ") );
1027
- }
1028
- }
1029
-
1030
- // returns a new Array with the elements that are in a but not in b
1031
- function diff( a, b ) {
1032
- var result = a.slice();
1033
- for ( var i = 0; i < result.length; i++ ) {
1034
- for ( var j = 0; j < b.length; j++ ) {
1035
- if ( result[i] === b[j] ) {
1036
- result.splice(i, 1);
1037
- i--;
1038
- break;
1039
- }
1040
- }
1041
- }
1042
- return result;
1043
- }
1044
-
1045
- function extend(a, b) {
1046
- for ( var prop in b ) {
1047
- if ( b[prop] === undefined ) {
1048
- delete a[prop];
1049
-
1050
- // Avoid "Member not found" error in IE8 caused by setting window.constructor
1051
- } else if ( prop !== "constructor" || a !== window ) {
1052
- a[prop] = b[prop];
1053
- }
1054
- }
1055
-
1056
- return a;
1057
- }
1058
-
1059
- function addEvent(elem, type, fn) {
1060
- if ( elem.addEventListener ) {
1061
- elem.addEventListener( type, fn, false );
1062
- } else if ( elem.attachEvent ) {
1063
- elem.attachEvent( "on" + type, fn );
1064
- } else {
1065
- fn();
1066
- }
1067
- }
1068
-
1069
- function id(name) {
1070
- return !!(typeof document !== "undefined" && document && document.getElementById) &&
1071
- document.getElementById( name );
1072
- }
1073
-
1074
- function registerLoggingCallback(key){
1075
- return function(callback){
1076
- config[key].push( callback );
1077
- };
1078
- }
1079
-
1080
- // Supports deprecated method of completely overwriting logging callbacks
1081
- function runLoggingCallbacks(key, scope, args) {
1082
- //debugger;
1083
- var callbacks;
1084
- if ( QUnit.hasOwnProperty(key) ) {
1085
- QUnit[key].call(scope, args);
1086
- } else {
1087
- callbacks = config[key];
1088
- for( var i = 0; i < callbacks.length; i++ ) {
1089
- callbacks[i].call( scope, args );
1090
- }
1091
- }
1092
- }
1093
-
1094
- // Test for equality any JavaScript type.
1095
- // Author: Philippe Rathé <prathe@gmail.com>
1096
- QUnit.equiv = (function() {
1097
-
1098
- var innerEquiv; // the real equiv function
1099
- var callers = []; // stack to decide between skip/abort functions
1100
- var parents = []; // stack to avoiding loops from circular referencing
1101
-
1102
- // Call the o related callback with the given arguments.
1103
- function bindCallbacks(o, callbacks, args) {
1104
- var prop = QUnit.objectType(o);
1105
- if (prop) {
1106
- if (QUnit.objectType(callbacks[prop]) === "function") {
1107
- return callbacks[prop].apply(callbacks, args);
1108
- } else {
1109
- return callbacks[prop]; // or undefined
1110
- }
1111
- }
1112
- }
1113
-
1114
- var getProto = Object.getPrototypeOf || function (obj) {
1115
- return obj.__proto__;
1116
- };
1117
-
1118
- var callbacks = (function () {
1119
-
1120
- // for string, boolean, number and null
1121
- function useStrictEquality(b, a) {
1122
- if (b instanceof a.constructor || a instanceof b.constructor) {
1123
- // to catch short annotaion VS 'new' annotation of a
1124
- // declaration
1125
- // e.g. var i = 1;
1126
- // var j = new Number(1);
1127
- return a == b;
1128
- } else {
1129
- return a === b;
1130
- }
1131
- }
1132
-
1133
- return {
1134
- "string" : useStrictEquality,
1135
- "boolean" : useStrictEquality,
1136
- "number" : useStrictEquality,
1137
- "null" : useStrictEquality,
1138
- "undefined" : useStrictEquality,
1139
-
1140
- "nan" : function(b) {
1141
- return isNaN(b);
1142
- },
1143
-
1144
- "date" : function(b, a) {
1145
- return QUnit.objectType(b) === "date" && a.valueOf() === b.valueOf();
1146
- },
1147
-
1148
- "regexp" : function(b, a) {
1149
- return QUnit.objectType(b) === "regexp" &&
1150
- // the regex itself
1151
- a.source === b.source &&
1152
- // and its modifers
1153
- a.global === b.global &&
1154
- // (gmi) ...
1155
- a.ignoreCase === b.ignoreCase &&
1156
- a.multiline === b.multiline;
1157
- },
1158
-
1159
- // - skip when the property is a method of an instance (OOP)
1160
- // - abort otherwise,
1161
- // initial === would have catch identical references anyway
1162
- "function" : function() {
1163
- var caller = callers[callers.length - 1];
1164
- return caller !== Object && typeof caller !== "undefined";
1165
- },
1166
-
1167
- "array" : function(b, a) {
1168
- var i, j, loop;
1169
- var len;
1170
-
1171
- // b could be an object literal here
1172
- if (QUnit.objectType(b) !== "array") {
1173
- return false;
1174
- }
1175
-
1176
- len = a.length;
1177
- if (len !== b.length) { // safe and faster
1178
- return false;
1179
- }
1180
-
1181
- // track reference to avoid circular references
1182
- parents.push(a);
1183
- for (i = 0; i < len; i++) {
1184
- loop = false;
1185
- for (j = 0; j < parents.length; j++) {
1186
- if (parents[j] === a[i]) {
1187
- loop = true;// dont rewalk array
1188
- }
1189
- }
1190
- if (!loop && !innerEquiv(a[i], b[i])) {
1191
- parents.pop();
1192
- return false;
1193
- }
1194
- }
1195
- parents.pop();
1196
- return true;
1197
- },
1198
-
1199
- "object" : function(b, a) {
1200
- var i, j, loop;
1201
- var eq = true; // unless we can proove it
1202
- var aProperties = [], bProperties = []; // collection of
1203
- // strings
1204
-
1205
- // comparing constructors is more strict than using
1206
- // instanceof
1207
- if (a.constructor !== b.constructor) {
1208
- // Allow objects with no prototype to be equivalent to
1209
- // objects with Object as their constructor.
1210
- if (!((getProto(a) === null && getProto(b) === Object.prototype) ||
1211
- (getProto(b) === null && getProto(a) === Object.prototype)))
1212
- {
1213
- return false;
1214
- }
1215
- }
1216
-
1217
- // stack constructor before traversing properties
1218
- callers.push(a.constructor);
1219
- // track reference to avoid circular references
1220
- parents.push(a);
1221
-
1222
- for (i in a) { // be strict: don't ensures hasOwnProperty
1223
- // and go deep
1224
- loop = false;
1225
- for (j = 0; j < parents.length; j++) {
1226
- if (parents[j] === a[i]) {
1227
- // don't go down the same path twice
1228
- loop = true;
1229
- }
1230
- }
1231
- aProperties.push(i); // collect a's properties
1232
-
1233
- if (!loop && !innerEquiv(a[i], b[i])) {
1234
- eq = false;
1235
- break;
1236
- }
1237
- }
1238
-
1239
- callers.pop(); // unstack, we are done
1240
- parents.pop();
1241
-
1242
- for (i in b) {
1243
- bProperties.push(i); // collect b's properties
1244
- }
1245
-
1246
- // Ensures identical properties name
1247
- return eq && innerEquiv(aProperties.sort(), bProperties.sort());
1248
- }
1249
- };
1250
- }());
1251
-
1252
- innerEquiv = function() { // can take multiple arguments
1253
- var args = Array.prototype.slice.apply(arguments);
1254
- if (args.length < 2) {
1255
- return true; // end transition
1256
- }
1257
-
1258
- return (function(a, b) {
1259
- if (a === b) {
1260
- return true; // catch the most you can
1261
- } else if (a === null || b === null || typeof a === "undefined" ||
1262
- typeof b === "undefined" ||
1263
- QUnit.objectType(a) !== QUnit.objectType(b)) {
1264
- return false; // don't lose time with error prone cases
1265
- } else {
1266
- return bindCallbacks(a, callbacks, [ b, a ]);
1267
- }
1268
-
1269
- // apply transition with (1..n) arguments
1270
- }(args[0], args[1]) && arguments.callee.apply(this, args.splice(1, args.length - 1)));
1271
- };
1272
-
1273
- return innerEquiv;
1274
-
1275
- }());
1276
-
1277
- /**
1278
- * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com |
1279
- * http://flesler.blogspot.com Licensed under BSD
1280
- * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008
1281
- *
1282
- * @projectDescription Advanced and extensible data dumping for Javascript.
1283
- * @version 1.0.0
1284
- * @author Ariel Flesler
1285
- * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html}
1286
- */
1287
- QUnit.jsDump = (function() {
1288
- function quote( str ) {
1289
- return '"' + str.toString().replace(/"/g, '\\"') + '"';
1290
- }
1291
- function literal( o ) {
1292
- return o + '';
1293
- }
1294
- function join( pre, arr, post ) {
1295
- var s = jsDump.separator(),
1296
- base = jsDump.indent(),
1297
- inner = jsDump.indent(1);
1298
- if ( arr.join ) {
1299
- arr = arr.join( ',' + s + inner );
1300
- }
1301
- if ( !arr ) {
1302
- return pre + post;
1303
- }
1304
- return [ pre, inner + arr, base + post ].join(s);
1305
- }
1306
- function array( arr, stack ) {
1307
- var i = arr.length, ret = new Array(i);
1308
- this.up();
1309
- while ( i-- ) {
1310
- ret[i] = this.parse( arr[i] , undefined , stack);
1311
- }
1312
- this.down();
1313
- return join( '[', ret, ']' );
1314
- }
1315
-
1316
- var reName = /^function (\w+)/;
1317
-
1318
- var jsDump = {
1319
- parse: function( obj, type, stack ) { //type is used mostly internally, you can fix a (custom)type in advance
1320
- stack = stack || [ ];
1321
- var parser = this.parsers[ type || this.typeOf(obj) ];
1322
- type = typeof parser;
1323
- var inStack = inArray(obj, stack);
1324
- if (inStack != -1) {
1325
- return 'recursion('+(inStack - stack.length)+')';
1326
- }
1327
- //else
1328
- if (type == 'function') {
1329
- stack.push(obj);
1330
- var res = parser.call( this, obj, stack );
1331
- stack.pop();
1332
- return res;
1333
- }
1334
- // else
1335
- return (type == 'string') ? parser : this.parsers.error;
1336
- },
1337
- typeOf: function( obj ) {
1338
- var type;
1339
- if ( obj === null ) {
1340
- type = "null";
1341
- } else if (typeof obj === "undefined") {
1342
- type = "undefined";
1343
- } else if (QUnit.is("RegExp", obj)) {
1344
- type = "regexp";
1345
- } else if (QUnit.is("Date", obj)) {
1346
- type = "date";
1347
- } else if (QUnit.is("Function", obj)) {
1348
- type = "function";
1349
- } else if (typeof obj.setInterval !== undefined && typeof obj.document !== "undefined" && typeof obj.nodeType === "undefined") {
1350
- type = "window";
1351
- } else if (obj.nodeType === 9) {
1352
- type = "document";
1353
- } else if (obj.nodeType) {
1354
- type = "node";
1355
- } else if (
1356
- // native arrays
1357
- toString.call( obj ) === "[object Array]" ||
1358
- // NodeList objects
1359
- ( typeof obj.length === "number" && typeof obj.item !== "undefined" && ( obj.length ? obj.item(0) === obj[0] : ( obj.item( 0 ) === null && typeof obj[0] === "undefined" ) ) )
1360
- ) {
1361
- type = "array";
1362
- } else {
1363
- type = typeof obj;
1364
- }
1365
- return type;
1366
- },
1367
- separator: function() {
1368
- return this.multiline ? this.HTML ? '<br />' : '\n' : this.HTML ? '&nbsp;' : ' ';
1369
- },
1370
- indent: function( extra ) {// extra can be a number, shortcut for increasing-calling-decreasing
1371
- if ( !this.multiline ) {
1372
- return '';
1373
- }
1374
- var chr = this.indentChar;
1375
- if ( this.HTML ) {
1376
- chr = chr.replace(/\t/g,' ').replace(/ /g,'&nbsp;');
1377
- }
1378
- return new Array( this._depth_ + (extra||0) ).join(chr);
1379
- },
1380
- up: function( a ) {
1381
- this._depth_ += a || 1;
1382
- },
1383
- down: function( a ) {
1384
- this._depth_ -= a || 1;
1385
- },
1386
- setParser: function( name, parser ) {
1387
- this.parsers[name] = parser;
1388
- },
1389
- // The next 3 are exposed so you can use them
1390
- quote: quote,
1391
- literal: literal,
1392
- join: join,
1393
- //
1394
- _depth_: 1,
1395
- // This is the list of parsers, to modify them, use jsDump.setParser
1396
- parsers: {
1397
- window: '[Window]',
1398
- document: '[Document]',
1399
- error: '[ERROR]', //when no parser is found, shouldn't happen
1400
- unknown: '[Unknown]',
1401
- 'null': 'null',
1402
- 'undefined': 'undefined',
1403
- 'function': function( fn ) {
1404
- var ret = 'function',
1405
- name = 'name' in fn ? fn.name : (reName.exec(fn)||[])[1];//functions never have name in IE
1406
- if ( name ) {
1407
- ret += ' ' + name;
1408
- }
1409
- ret += '(';
1410
-
1411
- ret = [ ret, QUnit.jsDump.parse( fn, 'functionArgs' ), '){'].join('');
1412
- return join( ret, QUnit.jsDump.parse(fn,'functionCode'), '}' );
1413
- },
1414
- array: array,
1415
- nodelist: array,
1416
- 'arguments': array,
1417
- object: function( map, stack ) {
1418
- var ret = [ ], keys, key, val, i;
1419
- QUnit.jsDump.up();
1420
- if (Object.keys) {
1421
- keys = Object.keys( map );
1422
- } else {
1423
- keys = [];
1424
- for (key in map) { keys.push( key ); }
1425
- }
1426
- keys.sort();
1427
- for (i = 0; i < keys.length; i++) {
1428
- key = keys[ i ];
1429
- val = map[ key ];
1430
- ret.push( QUnit.jsDump.parse( key, 'key' ) + ': ' + QUnit.jsDump.parse( val, undefined, stack ) );
1431
- }
1432
- QUnit.jsDump.down();
1433
- return join( '{', ret, '}' );
1434
- },
1435
- node: function( node ) {
1436
- var open = QUnit.jsDump.HTML ? '&lt;' : '<',
1437
- close = QUnit.jsDump.HTML ? '&gt;' : '>';
1438
-
1439
- var tag = node.nodeName.toLowerCase(),
1440
- ret = open + tag;
1441
-
1442
- for ( var a in QUnit.jsDump.DOMAttrs ) {
1443
- var val = node[QUnit.jsDump.DOMAttrs[a]];
1444
- if ( val ) {
1445
- ret += ' ' + a + '=' + QUnit.jsDump.parse( val, 'attribute' );
1446
- }
1447
- }
1448
- return ret + close + open + '/' + tag + close;
1449
- },
1450
- functionArgs: function( fn ) {//function calls it internally, it's the arguments part of the function
1451
- var l = fn.length;
1452
- if ( !l ) {
1453
- return '';
1454
- }
1455
-
1456
- var args = new Array(l);
1457
- while ( l-- ) {
1458
- args[l] = String.fromCharCode(97+l);//97 is 'a'
1459
- }
1460
- return ' ' + args.join(', ') + ' ';
1461
- },
1462
- key: quote, //object calls it internally, the key part of an item in a map
1463
- functionCode: '[code]', //function calls it internally, it's the content of the function
1464
- attribute: quote, //node calls it internally, it's an html attribute value
1465
- string: quote,
1466
- date: quote,
1467
- regexp: literal, //regex
1468
- number: literal,
1469
- 'boolean': literal
1470
- },
1471
- DOMAttrs:{//attributes to dump from nodes, name=>realName
1472
- id:'id',
1473
- name:'name',
1474
- 'class':'className'
1475
- },
1476
- HTML:false,//if true, entities are escaped ( <, >, \t, space and \n )
1477
- indentChar:' ',//indentation unit
1478
- multiline:true //if true, items in a collection, are separated by a \n, else just a space.
1479
- };
1480
-
1481
- return jsDump;
1482
- }());
1483
-
1484
- // from Sizzle.js
1485
- function getText( elems ) {
1486
- var ret = "", elem;
1487
-
1488
- for ( var i = 0; elems[i]; i++ ) {
1489
- elem = elems[i];
1490
-
1491
- // Get the text from text nodes and CDATA nodes
1492
- if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
1493
- ret += elem.nodeValue;
1494
-
1495
- // Traverse everything else, except comment nodes
1496
- } else if ( elem.nodeType !== 8 ) {
1497
- ret += getText( elem.childNodes );
1498
- }
1499
- }
1500
-
1501
- return ret;
1502
- }
1503
-
1504
- //from jquery.js
1505
- function inArray( elem, array ) {
1506
- if ( array.indexOf ) {
1507
- return array.indexOf( elem );
1508
- }
1509
-
1510
- for ( var i = 0, length = array.length; i < length; i++ ) {
1511
- if ( array[ i ] === elem ) {
1512
- return i;
1513
- }
1514
- }
1515
-
1516
- return -1;
1517
- }
1518
-
1519
- /*
1520
- * Javascript Diff Algorithm
1521
- * By John Resig (http://ejohn.org/)
1522
- * Modified by Chu Alan "sprite"
1523
- *
1524
- * Released under the MIT license.
1525
- *
1526
- * More Info:
1527
- * http://ejohn.org/projects/javascript-diff-algorithm/
1528
- *
1529
- * Usage: QUnit.diff(expected, actual)
1530
- *
1531
- * 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"
1532
- */
1533
- QUnit.diff = (function() {
1534
- function diff(o, n) {
1535
- var ns = {};
1536
- var os = {};
1537
- var i;
1538
-
1539
- for (i = 0; i < n.length; i++) {
1540
- if (ns[n[i]] == null) {
1541
- ns[n[i]] = {
1542
- rows: [],
1543
- o: null
1544
- };
1545
- }
1546
- ns[n[i]].rows.push(i);
1547
- }
1548
-
1549
- for (i = 0; i < o.length; i++) {
1550
- if (os[o[i]] == null) {
1551
- os[o[i]] = {
1552
- rows: [],
1553
- n: null
1554
- };
1555
- }
1556
- os[o[i]].rows.push(i);
1557
- }
1558
-
1559
- for (i in ns) {
1560
- if ( !hasOwn.call( ns, i ) ) {
1561
- continue;
1562
- }
1563
- if (ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1) {
1564
- n[ns[i].rows[0]] = {
1565
- text: n[ns[i].rows[0]],
1566
- row: os[i].rows[0]
1567
- };
1568
- o[os[i].rows[0]] = {
1569
- text: o[os[i].rows[0]],
1570
- row: ns[i].rows[0]
1571
- };
1572
- }
1573
- }
1574
-
1575
- for (i = 0; i < n.length - 1; i++) {
1576
- if (n[i].text != null && n[i + 1].text == null && n[i].row + 1 < o.length && o[n[i].row + 1].text == null &&
1577
- n[i + 1] == o[n[i].row + 1]) {
1578
- n[i + 1] = {
1579
- text: n[i + 1],
1580
- row: n[i].row + 1
1581
- };
1582
- o[n[i].row + 1] = {
1583
- text: o[n[i].row + 1],
1584
- row: i + 1
1585
- };
1586
- }
1587
- }
1588
-
1589
- for (i = n.length - 1; i > 0; i--) {
1590
- if (n[i].text != null && n[i - 1].text == null && n[i].row > 0 && o[n[i].row - 1].text == null &&
1591
- n[i - 1] == o[n[i].row - 1]) {
1592
- n[i - 1] = {
1593
- text: n[i - 1],
1594
- row: n[i].row - 1
1595
- };
1596
- o[n[i].row - 1] = {
1597
- text: o[n[i].row - 1],
1598
- row: i - 1
1599
- };
1600
- }
1601
- }
1602
-
1603
- return {
1604
- o: o,
1605
- n: n
1606
- };
1607
- }
1608
-
1609
- return function(o, n) {
1610
- o = o.replace(/\s+$/, '');
1611
- n = n.replace(/\s+$/, '');
1612
- var out = diff(o === "" ? [] : o.split(/\s+/), n === "" ? [] : n.split(/\s+/));
1613
-
1614
- var str = "";
1615
- var i;
1616
-
1617
- var oSpace = o.match(/\s+/g);
1618
- if (oSpace == null) {
1619
- oSpace = [" "];
1620
- }
1621
- else {
1622
- oSpace.push(" ");
1623
- }
1624
- var nSpace = n.match(/\s+/g);
1625
- if (nSpace == null) {
1626
- nSpace = [" "];
1627
- }
1628
- else {
1629
- nSpace.push(" ");
1630
- }
1631
-
1632
- if (out.n.length === 0) {
1633
- for (i = 0; i < out.o.length; i++) {
1634
- str += '<del>' + out.o[i] + oSpace[i] + "</del>";
1635
- }
1636
- }
1637
- else {
1638
- if (out.n[0].text == null) {
1639
- for (n = 0; n < out.o.length && out.o[n].text == null; n++) {
1640
- str += '<del>' + out.o[n] + oSpace[n] + "</del>";
1641
- }
1642
- }
1643
-
1644
- for (i = 0; i < out.n.length; i++) {
1645
- if (out.n[i].text == null) {
1646
- str += '<ins>' + out.n[i] + nSpace[i] + "</ins>";
1647
- }
1648
- else {
1649
- var pre = "";
1650
-
1651
- for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++) {
1652
- pre += '<del>' + out.o[n] + oSpace[n] + "</del>";
1653
- }
1654
- str += " " + out.n[i].text + nSpace[i] + pre;
1655
- }
1656
- }
1657
- }
1658
-
1659
- return str;
1660
- };
1661
- }());
1662
-
1663
- // for CommonJS enviroments, export everything
1664
- if ( typeof exports !== "undefined" || typeof require !== "undefined" ) {
1665
- extend(exports, QUnit);
1666
- }
1667
-
1668
- // get at whatever the global object is, like window in browsers
1669
- }( (function() {return this;}.call()) ));