[ Index ]
 

Code source de Symfony 1.0.0

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/data/web/sf/prototype/js/ -> unittest.js (source)

   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  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));
  25    
  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;"
  37    
  38    if(this.step)
  39      alert('['+new Date().getTime().toString()+'] '+eventName+'/'+Test.Unit.inspect(options));
  40    
  41    $(element).dispatchEvent(oEvent);
  42  };
  43  
  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] || {});
  56  
  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  };
  63  
  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  };
  69  
  70  var Test = {}
  71  Test.Unit = {};
  72  
  73  // security exception workaround
  74  Test.Unit.inspect = Object.inspect;
  75  
  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  }
 137  
 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  }
 250  
 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;
 447      
 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  }
 465  
 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;
 471      
 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      }
 481      
 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  });
 507  
 508  // *EXPERIMENTAL* BDD-style testing to please non-technical folk
 509  // This draws many ideas from RSpec http://rspec.rubyforge.org/
 510  
 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',
 522      
 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  }
 539  
 540  Test.context = function(name, spec, log){
 541    Test.setupBDDExtensionMethods();
 542    
 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  };


Généré le : Fri Mar 16 22:42:14 2007 par Balluche grâce à PHPXref 0.7