[ Index ]

PHP Cross Reference of vtigercrm-6.1.0

title

Body

[close]

/libraries/jquery/defunkt-jquery-pjax/test/ -> qunit-1.6.0.js (source)

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


Generated: Fri Nov 28 20:08:37 2014 Cross-referenced by PHPXref 0.7.1