dom/tests/mochitest/ajax/scriptaculous/src/unittest.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 // script.aculo.us unittest.js v1.7.1_beta2, Tue May 15 15:15:45 EDT 2007
     3 // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
     4 //           (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
     5 //           (c) 2005-2007 Michael Schuerig (http://www.schuerig.de/michael/)
     6 //
     7 // script.aculo.us is freely distributable under the terms of an MIT-style license.
     8 // For details, see the script.aculo.us web site: http://script.aculo.us/
    10 // experimental, Firefox-only
    11 Event.simulateMouse = function(element, eventName) {
    12   var options = Object.extend({
    13     pointerX: 0,
    14     pointerY: 0,
    15     buttons:  0,
    16     ctrlKey:  false,
    17     altKey:   false,
    18     shiftKey: false,
    19     metaKey:  false
    20   }, arguments[2] || {});
    21   var oEvent = document.createEvent("MouseEvents");
    22   oEvent.initMouseEvent(eventName, true, true, document.defaultView, 
    23     options.buttons, options.pointerX, options.pointerY, options.pointerX, options.pointerY, 
    24     options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, 0, $(element));
    26   if(this.mark) Element.remove(this.mark);
    27   this.mark = document.createElement('div');
    28   this.mark.appendChild(document.createTextNode(" "));
    29   document.body.appendChild(this.mark);
    30   this.mark.style.position = 'absolute';
    31   this.mark.style.top = options.pointerY + "px";
    32   this.mark.style.left = options.pointerX + "px";
    33   this.mark.style.width = "5px";
    34   this.mark.style.height = "5px;";
    35   this.mark.style.borderTop = "1px solid red;"
    36   this.mark.style.borderLeft = "1px solid red;"
    38   if(this.step)
    39     alert('['+new Date().getTime().toString()+'] '+eventName+'/'+Test.Unit.inspect(options));
    41   $(element).dispatchEvent(oEvent);
    42 };
    44 // Note: Due to a fix in Firefox 1.0.5/6 that probably fixed "too much", this doesn't work in 1.0.6 or DP2.
    45 // You need to downgrade to 1.0.4 for now to get this working
    46 // See https://bugzilla.mozilla.org/show_bug.cgi?id=289940 for the fix that fixed too much
    47 Event.simulateKey = function(element, eventName) {
    48   var options = Object.extend({
    49     ctrlKey: false,
    50     altKey: false,
    51     shiftKey: false,
    52     metaKey: false,
    53     keyCode: 0,
    54     charCode: 0
    55   }, arguments[2] || {});
    57   var oEvent = document.createEvent("KeyEvents");
    58   oEvent.initKeyEvent(eventName, true, true, window, 
    59     options.ctrlKey, options.altKey, options.shiftKey, options.metaKey,
    60     options.keyCode, options.charCode );
    61   $(element).dispatchEvent(oEvent);
    62 };
    64 Event.simulateKeys = function(element, command) {
    65   for(var i=0; i<command.length; i++) {
    66     Event.simulateKey(element,'keypress',{charCode:command.charCodeAt(i)});
    67   }
    68 };
    70 var Test = {}
    71 Test.Unit = {};
    73 // security exception workaround
    74 Test.Unit.inspect = Object.inspect;
    76 Test.Unit.Logger = Class.create();
    77 Test.Unit.Logger.prototype = {
    78   initialize: function(log) {
    79     this.log = $(log);
    80     if (this.log) {
    81       this._createLogTable();
    82     }
    83   },
    84   start: function(testName) {
    85     if (!this.log) return;
    86     this.testName = testName;
    87     this.lastLogLine = document.createElement('tr');
    88     this.statusCell = document.createElement('td');
    89     this.nameCell = document.createElement('td');
    90     this.nameCell.className = "nameCell";
    91     this.nameCell.appendChild(document.createTextNode(testName));
    92     this.messageCell = document.createElement('td');
    93     this.lastLogLine.appendChild(this.statusCell);
    94     this.lastLogLine.appendChild(this.nameCell);
    95     this.lastLogLine.appendChild(this.messageCell);
    96     this.loglines.appendChild(this.lastLogLine);
    97   },
    98   finish: function(status, summary) {
    99     if (!this.log) return;
   100     this.lastLogLine.className = status;
   101     this.statusCell.innerHTML = status;
   102     this.messageCell.innerHTML = this._toHTML(summary);
   103     this.addLinksToResults();
   104   },
   105   message: function(message) {
   106     if (!this.log) return;
   107     this.messageCell.innerHTML = this._toHTML(message);
   108   },
   109   summary: function(summary) {
   110     if (!this.log) return;
   111     this.logsummary.innerHTML = this._toHTML(summary);
   112   },
   113   _createLogTable: function() {
   114     this.log.innerHTML =
   115     '<div id="logsummary"></div>' +
   116     '<table id="logtable">' +
   117     '<thead><tr><th>Status</th><th>Test</th><th>Message</th></tr></thead>' +
   118     '<tbody id="loglines"></tbody>' +
   119     '</table>';
   120     this.logsummary = $('logsummary')
   121     this.loglines = $('loglines');
   122   },
   123   _toHTML: function(txt) {
   124     return txt.escapeHTML().replace(/\n/g,"<br/>");
   125   },
   126   addLinksToResults: function(){ 
   127     $$("tr.failed .nameCell").each( function(td){ // todo: limit to children of this.log
   128       td.title = "Run only this test"
   129       Event.observe(td, 'click', function(){ window.location.search = "?tests=" + td.innerHTML;});
   130     });
   131     $$("tr.passed .nameCell").each( function(td){ // todo: limit to children of this.log
   132       td.title = "Run all tests"
   133       Event.observe(td, 'click', function(){ window.location.search = "";});
   134     });
   135   }
   136 }
   138 Test.Unit.Runner = Class.create();
   139 Test.Unit.Runner.prototype = {
   140   initialize: function(testcases) {
   141     this.options = Object.extend({
   142       testLog: 'testlog'
   143     }, arguments[1] || {});
   144     this.options.resultsURL = this.parseResultsURLQueryParameter();
   145     this.options.tests      = this.parseTestsQueryParameter();
   146     if (this.options.testLog) {
   147       this.options.testLog = $(this.options.testLog) || null;
   148     }
   149     if(this.options.tests) {
   150       this.tests = [];
   151       for(var i = 0; i < this.options.tests.length; i++) {
   152         if(/^test/.test(this.options.tests[i])) {
   153           this.tests.push(new Test.Unit.Testcase(this.options.tests[i], testcases[this.options.tests[i]], testcases["setup"], testcases["teardown"]));
   154         }
   155       }
   156     } else {
   157       if (this.options.test) {
   158         this.tests = [new Test.Unit.Testcase(this.options.test, testcases[this.options.test], testcases["setup"], testcases["teardown"])];
   159       } else {
   160         this.tests = [];
   161         for(var testcase in testcases) {
   162           if(/^test/.test(testcase)) {
   163             this.tests.push(
   164                new Test.Unit.Testcase(
   165                  this.options.context ? ' -> ' + this.options.titles[testcase] : testcase, 
   166                  testcases[testcase], testcases["setup"], testcases["teardown"]
   167                ));
   168           }
   169         }
   170       }
   171     }
   172     this.currentTest = 0;
   173     this.logger = new Test.Unit.Logger(this.options.testLog);
   174     setTimeout(this.runTests.bind(this), 1000);
   175   },
   176   parseResultsURLQueryParameter: function() {
   177     return window.location.search.parseQuery()["resultsURL"];
   178   },
   179   parseTestsQueryParameter: function(){
   180     if (window.location.search.parseQuery()["tests"]){
   181         return window.location.search.parseQuery()["tests"].split(',');
   182     };
   183   },
   184   // Returns:
   185   //  "ERROR" if there was an error,
   186   //  "FAILURE" if there was a failure, or
   187   //  "SUCCESS" if there was neither
   188   getResult: function() {
   189     var hasFailure = false;
   190     for(var i=0;i<this.tests.length;i++) {
   191       if (this.tests[i].errors > 0) {
   192         return "ERROR";
   193       }
   194       if (this.tests[i].failures > 0) {
   195         hasFailure = true;
   196       }
   197     }
   198     if (hasFailure) {
   199       return "FAILURE";
   200     } else {
   201       return "SUCCESS";
   202     }
   203   },
   204   postResults: function() {
   205     if (this.options.resultsURL) {
   206       new Ajax.Request(this.options.resultsURL, 
   207         { method: 'get', parameters: 'result=' + this.getResult(), asynchronous: false });
   208     }
   209   },
   210   runTests: function() {
   211     var test = this.tests[this.currentTest];
   212     if (!test) {
   213       // finished!
   214       this.postResults();
   215       this.logger.summary(this.summary());
   216       return;
   217     }
   218     if(!test.isWaiting) {
   219       this.logger.start(test.name);
   220     }
   221     test.run();
   222     if(test.isWaiting) {
   223       this.logger.message("Waiting for " + test.timeToWait + "ms");
   224       setTimeout(this.runTests.bind(this), test.timeToWait || 1000);
   225     } else {
   226       this.logger.finish(test.status(), test.summary());
   227       this.currentTest++;
   228       // tail recursive, hopefully the browser will skip the stackframe
   229       this.runTests();
   230     }
   231   },
   232   summary: function() {
   233     var assertions = 0;
   234     var failures = 0;
   235     var errors = 0;
   236     var messages = [];
   237     for(var i=0;i<this.tests.length;i++) {
   238       assertions +=   this.tests[i].assertions;
   239       failures   +=   this.tests[i].failures;
   240       errors     +=   this.tests[i].errors;
   241     }
   242     return (
   243       (this.options.context ? this.options.context + ': ': '') + 
   244       this.tests.length + " tests, " + 
   245       assertions + " assertions, " + 
   246       failures   + " failures, " +
   247       errors     + " errors");
   248   }
   249 }
   251 Test.Unit.Assertions = Class.create();
   252 Test.Unit.Assertions.prototype = {
   253   initialize: function() {
   254     this.assertions = 0;
   255     this.failures   = 0;
   256     this.errors     = 0;
   257     this.messages   = [];
   258   },
   259   summary: function() {
   260     return (
   261       this.assertions + " assertions, " + 
   262       this.failures   + " failures, " +
   263       this.errors     + " errors" + "\n" +
   264       this.messages.join("\n"));
   265   },
   266   pass: function() {
   267     this.assertions++;
   268   },
   269   fail: function(message) {
   270     this.failures++;
   271     this.messages.push("Failure: " + message);
   272   },
   273   info: function(message) {
   274     this.messages.push("Info: " + message);
   275   },
   276   error: function(error) {
   277     this.errors++;
   278     this.messages.push(error.name + ": "+ error.message + "(" + Test.Unit.inspect(error) +")");
   279   },
   280   status: function() {
   281     if (this.failures > 0) return 'failed';
   282     if (this.errors > 0) return 'error';
   283     return 'passed';
   284   },
   285   assert: function(expression) {
   286     var message = arguments[1] || 'assert: got "' + Test.Unit.inspect(expression) + '"';
   287     try { expression ? this.pass() : 
   288       this.fail(message); }
   289     catch(e) { this.error(e); }
   290   },
   291   assertEqual: function(expected, actual) {
   292     var message = arguments[2] || "assertEqual";
   293     try { (expected == actual) ? this.pass() :
   294       this.fail(message + ': expected "' + Test.Unit.inspect(expected) + 
   295         '", actual "' + Test.Unit.inspect(actual) + '"'); }
   296     catch(e) { this.error(e); }
   297   },
   298   assertInspect: function(expected, actual) {
   299     var message = arguments[2] || "assertInspect";
   300     try { (expected == actual.inspect()) ? this.pass() :
   301       this.fail(message + ': expected "' + Test.Unit.inspect(expected) + 
   302         '", actual "' + Test.Unit.inspect(actual) + '"'); }
   303     catch(e) { this.error(e); }
   304   },
   305   assertEnumEqual: function(expected, actual) {
   306     var message = arguments[2] || "assertEnumEqual";
   307     try { $A(expected).length == $A(actual).length && 
   308       expected.zip(actual).all(function(pair) { return pair[0] == pair[1] }) ?
   309         this.pass() : this.fail(message + ': expected ' + Test.Unit.inspect(expected) + 
   310           ', actual ' + Test.Unit.inspect(actual)); }
   311     catch(e) { this.error(e); }
   312   },
   313   assertNotEqual: function(expected, actual) {
   314     var message = arguments[2] || "assertNotEqual";
   315     try { (expected != actual) ? this.pass() : 
   316       this.fail(message + ': got "' + Test.Unit.inspect(actual) + '"'); }
   317     catch(e) { this.error(e); }
   318   },
   319   assertIdentical: function(expected, actual) { 
   320     var message = arguments[2] || "assertIdentical"; 
   321     try { (expected === actual) ? this.pass() : 
   322       this.fail(message + ': expected "' + Test.Unit.inspect(expected) +  
   323         '", actual "' + Test.Unit.inspect(actual) + '"'); } 
   324     catch(e) { this.error(e); } 
   325   },
   326   assertNotIdentical: function(expected, actual) { 
   327     var message = arguments[2] || "assertNotIdentical"; 
   328     try { !(expected === actual) ? this.pass() : 
   329       this.fail(message + ': expected "' + Test.Unit.inspect(expected) +  
   330         '", actual "' + Test.Unit.inspect(actual) + '"'); } 
   331     catch(e) { this.error(e); } 
   332   },
   333   assertNull: function(obj) {
   334     var message = arguments[1] || 'assertNull'
   335     try { (obj==null) ? this.pass() : 
   336       this.fail(message + ': got "' + Test.Unit.inspect(obj) + '"'); }
   337     catch(e) { this.error(e); }
   338   },
   339   assertMatch: function(expected, actual) {
   340     var message = arguments[2] || 'assertMatch';
   341     var regex = new RegExp(expected);
   342     try { (regex.exec(actual)) ? this.pass() :
   343       this.fail(message + ' : regex: "' +  Test.Unit.inspect(expected) + ' did not match: ' + Test.Unit.inspect(actual) + '"'); }
   344     catch(e) { this.error(e); }
   345   },
   346   assertHidden: function(element) {
   347     var message = arguments[1] || 'assertHidden';
   348     this.assertEqual("none", element.style.display, message);
   349   },
   350   assertNotNull: function(object) {
   351     var message = arguments[1] || 'assertNotNull';
   352     this.assert(object != null, message);
   353   },
   354   assertType: function(expected, actual) {
   355     var message = arguments[2] || 'assertType';
   356     try { 
   357       (actual.constructor == expected) ? this.pass() : 
   358       this.fail(message + ': expected "' + Test.Unit.inspect(expected) +  
   359         '", actual "' + (actual.constructor) + '"'); }
   360     catch(e) { this.error(e); }
   361   },
   362   assertNotOfType: function(expected, actual) {
   363     var message = arguments[2] || 'assertNotOfType';
   364     try { 
   365       (actual.constructor != expected) ? this.pass() : 
   366       this.fail(message + ': expected "' + Test.Unit.inspect(expected) +  
   367         '", actual "' + (actual.constructor) + '"'); }
   368     catch(e) { this.error(e); }
   369   },
   370   assertInstanceOf: function(expected, actual) {
   371     var message = arguments[2] || 'assertInstanceOf';
   372     try { 
   373       (actual instanceof expected) ? this.pass() : 
   374       this.fail(message + ": object was not an instance of the expected type"); }
   375     catch(e) { this.error(e); } 
   376   },
   377   assertNotInstanceOf: function(expected, actual) {
   378     var message = arguments[2] || 'assertNotInstanceOf';
   379     try { 
   380       !(actual instanceof expected) ? this.pass() : 
   381       this.fail(message + ": object was an instance of the not expected type"); }
   382     catch(e) { this.error(e); } 
   383   },
   384   assertRespondsTo: function(method, obj) {
   385     var message = arguments[2] || 'assertRespondsTo';
   386     try {
   387       (obj[method] && typeof obj[method] == 'function') ? this.pass() : 
   388       this.fail(message + ": object doesn't respond to [" + method + "]"); }
   389     catch(e) { this.error(e); }
   390   },
   391   assertReturnsTrue: function(method, obj) {
   392     var message = arguments[2] || 'assertReturnsTrue';
   393     try {
   394       var m = obj[method];
   395       if(!m) m = obj['is'+method.charAt(0).toUpperCase()+method.slice(1)];
   396       m() ? this.pass() : 
   397       this.fail(message + ": method returned false"); }
   398     catch(e) { this.error(e); }
   399   },
   400   assertReturnsFalse: function(method, obj) {
   401     var message = arguments[2] || 'assertReturnsFalse';
   402     try {
   403       var m = obj[method];
   404       if(!m) m = obj['is'+method.charAt(0).toUpperCase()+method.slice(1)];
   405       !m() ? this.pass() : 
   406       this.fail(message + ": method returned true"); }
   407     catch(e) { this.error(e); }
   408   },
   409   assertRaise: function(exceptionName, method) {
   410     var message = arguments[2] || 'assertRaise';
   411     try { 
   412       method();
   413       this.fail(message + ": exception expected but none was raised"); }
   414     catch(e) {
   415       ((exceptionName == null) || (e.name==exceptionName)) ? this.pass() : this.error(e); 
   416     }
   417   },
   418   assertElementsMatch: function() {
   419     var expressions = $A(arguments), elements = $A(expressions.shift());
   420     if (elements.length != expressions.length) {
   421       this.fail('assertElementsMatch: size mismatch: ' + elements.length + ' elements, ' + expressions.length + ' expressions');
   422       return false;
   423     }
   424     elements.zip(expressions).all(function(pair, index) {
   425       var element = $(pair.first()), expression = pair.last();
   426       if (element.match(expression)) return true;
   427       this.fail('assertElementsMatch: (in index ' + index + ') expected ' + expression.inspect() + ' but got ' + element.inspect());
   428     }.bind(this)) && this.pass();
   429   },
   430   assertElementMatches: function(element, expression) {
   431     this.assertElementsMatch([element], expression);
   432   },
   433   benchmark: function(operation, iterations) {
   434     var startAt = new Date();
   435     (iterations || 1).times(operation);
   436     var timeTaken = ((new Date())-startAt);
   437     this.info((arguments[2] || 'Operation') + ' finished ' + 
   438        iterations + ' iterations in ' + (timeTaken/1000)+'s' );
   439     return timeTaken;
   440   },
   441   _isVisible: function(element) {
   442     element = $(element);
   443     if(!element.parentNode) return true;
   444     this.assertNotNull(element);
   445     if(element.style && Element.getStyle(element, 'display') == 'none')
   446       return false;
   448     return this._isVisible(element.parentNode);
   449   },
   450   assertNotVisible: function(element) {
   451     this.assert(!this._isVisible(element), Test.Unit.inspect(element) + " was not hidden and didn't have a hidden parent either. " + ("" || arguments[1]));
   452   },
   453   assertVisible: function(element) {
   454     this.assert(this._isVisible(element), Test.Unit.inspect(element) + " was not visible. " + ("" || arguments[1]));
   455   },
   456   benchmark: function(operation, iterations) {
   457     var startAt = new Date();
   458     (iterations || 1).times(operation);
   459     var timeTaken = ((new Date())-startAt);
   460     this.info((arguments[2] || 'Operation') + ' finished ' + 
   461        iterations + ' iterations in ' + (timeTaken/1000)+'s' );
   462     return timeTaken;
   463   }
   464 }
   466 Test.Unit.Testcase = Class.create();
   467 Object.extend(Object.extend(Test.Unit.Testcase.prototype, Test.Unit.Assertions.prototype), {
   468   initialize: function(name, test, setup, teardown) {
   469     Test.Unit.Assertions.prototype.initialize.bind(this)();
   470     this.name           = name;
   472     if(typeof test == 'string') {
   473       test = test.gsub(/(\.should[^\(]+\()/,'#{0}this,');
   474       test = test.gsub(/(\.should[^\(]+)\(this,\)/,'#{1}(this)');
   475       this.test = function() {
   476         eval('with(this){'+test+'}');
   477       }
   478     } else {
   479       this.test = test || function() {};
   480     }
   482     this.setup          = setup || function() {};
   483     this.teardown       = teardown || function() {};
   484     this.isWaiting      = false;
   485     this.timeToWait     = 1000;
   486   },
   487   wait: function(time, nextPart) {
   488     this.isWaiting = true;
   489     this.test = nextPart;
   490     this.timeToWait = time;
   491   },
   492   run: function() {
   493     try {
   494       try {
   495         if (!this.isWaiting) this.setup.bind(this)();
   496         this.isWaiting = false;
   497         this.test.bind(this)();
   498       } finally {
   499         if(!this.isWaiting) {
   500           this.teardown.bind(this)();
   501         }
   502       }
   503     }
   504     catch(e) { this.error(e); }
   505   }
   506 });
   508 // *EXPERIMENTAL* BDD-style testing to please non-technical folk
   509 // This draws many ideas from RSpec http://rspec.rubyforge.org/
   511 Test.setupBDDExtensionMethods = function(){
   512   var METHODMAP = {
   513     shouldEqual:     'assertEqual',
   514     shouldNotEqual:  'assertNotEqual',
   515     shouldEqualEnum: 'assertEnumEqual',
   516     shouldBeA:       'assertType',
   517     shouldNotBeA:    'assertNotOfType',
   518     shouldBeAn:      'assertType',
   519     shouldNotBeAn:   'assertNotOfType',
   520     shouldBeNull:    'assertNull',
   521     shouldNotBeNull: 'assertNotNull',
   523     shouldBe:        'assertReturnsTrue',
   524     shouldNotBe:     'assertReturnsFalse',
   525     shouldRespondTo: 'assertRespondsTo'
   526   };
   527   Test.BDDMethods = {};
   528   for(m in METHODMAP) {
   529     Test.BDDMethods[m] = eval(
   530       'function(){'+
   531       'var args = $A(arguments);'+
   532       'var scope = args.shift();'+
   533       'scope.'+METHODMAP[m]+'.apply(scope,(args || []).concat([this])); }');
   534   }
   535   [Array.prototype, String.prototype, Number.prototype].each(
   536     function(p){ Object.extend(p, Test.BDDMethods) }
   537   );
   538 }
   540 Test.context = function(name, spec, log){
   541   Test.setupBDDExtensionMethods();
   543   var compiledSpec = {};
   544   var titles = {};
   545   for(specName in spec) {
   546     switch(specName){
   547       case "setup":
   548       case "teardown":
   549         compiledSpec[specName] = spec[specName];
   550         break;
   551       default:
   552         var testName = 'test'+specName.gsub(/\s+/,'-').camelize();
   553         var body = spec[specName].toString().split('\n').slice(1);
   554         if(/^\{/.test(body[0])) body = body.slice(1);
   555         body.pop();
   556         body = body.map(function(statement){ 
   557           return statement.strip()
   558         });
   559         compiledSpec[testName] = body.join('\n');
   560         titles[testName] = specName;
   561     }
   562   }
   563   new Test.Unit.Runner(compiledSpec, { titles: titles, testLog: log || 'testlog', context: name });
   564 };
   566 if ( parent.SimpleTest && parent.runAJAXTest ) (function(){
   567         var finish = Test.Unit.Logger.prototype.finish;
   568         Test.Unit.Logger.prototype.finish = function(status,summary){
   569 		var match = summary.match(/(\d+).*(\d+).*(\d+)/)
   570 		var fail = parseInt(match[2]) + parseInt(match[3]);
   571 		var pass = match[1] - fail;
   573 		for ( var i = 0; i < pass; i++ )
   574                 	parent.SimpleTest.ok( true, this.testName, summary );
   576 		for ( var i = 0; i < fail; i++ )
   577                 	parent.SimpleTest.ok( false, this.testName, summary );
   579                 return finish.apply( this, arguments );
   580         };
   582         // Intentionally overwrite (to stop the Ajax request)
   583         Test.Unit.Runner.prototype.postResults = parent.runAJAXTest;
   585 	Ajax.InPlaceEditor.prototype.onFailure = function(){};
   586 })();

mercurial