PageSourceSearch

https://campusmentis.it/sites/all/themes/sitecampusmentis/js/scriptaculous/src/unittest.js

js campusmentis.it collected 2026-10-07 23:37:42 UTC 20,612 bytes, 565 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.