-
+ D95DCAA12B429103EF454C613B5FDA763667B8B98E141F08B8A312469E01B9CB313216067BFE21B73425E3610B39EFBC1B28C65218888BCB2C0F4FE023D1ED14
mp-wp/wp-includes/js/scriptaculous/unittest.js
(0 . 0)(1 . 568)
115474 // script.aculo.us unittest.js v1.8.0, Tue Nov 06 15:01:40 +0300 2007
115475
115476 // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
115477 // (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
115478 // (c) 2005-2007 Michael Schuerig (http://www.schuerig.de/michael/)
115479 //
115480 // script.aculo.us is freely distributable under the terms of an MIT-style license.
115481 // For details, see the script.aculo.us web site: http://script.aculo.us/
115482
115483 // experimental, Firefox-only
115484 Event.simulateMouse = function(element, eventName) {
115485 var options = Object.extend({
115486 pointerX: 0,
115487 pointerY: 0,
115488 buttons: 0,
115489 ctrlKey: false,
115490 altKey: false,
115491 shiftKey: false,
115492 metaKey: false
115493 }, arguments[2] || {});
115494 var oEvent = document.createEvent("MouseEvents");
115495 oEvent.initMouseEvent(eventName, true, true, document.defaultView,
115496 options.buttons, options.pointerX, options.pointerY, options.pointerX, options.pointerY,
115497 options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, 0, $(element));
115498
115499 if(this.mark) Element.remove(this.mark);
115500 this.mark = document.createElement('div');
115501 this.mark.appendChild(document.createTextNode(" "));
115502 document.body.appendChild(this.mark);
115503 this.mark.style.position = 'absolute';
115504 this.mark.style.top = options.pointerY + "px";
115505 this.mark.style.left = options.pointerX + "px";
115506 this.mark.style.width = "5px";
115507 this.mark.style.height = "5px;";
115508 this.mark.style.borderTop = "1px solid red;"
115509 this.mark.style.borderLeft = "1px solid red;"
115510
115511 if(this.step)
115512 alert('['+new Date().getTime().toString()+'] '+eventName+'/'+Test.Unit.inspect(options));
115513
115514 $(element).dispatchEvent(oEvent);
115515 };
115516
115517 // 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.
115518 // You need to downgrade to 1.0.4 for now to get this working
115519 // See https://bugzilla.mozilla.org/show_bug.cgi?id=289940 for the fix that fixed too much
115520 Event.simulateKey = function(element, eventName) {
115521 var options = Object.extend({
115522 ctrlKey: false,
115523 altKey: false,
115524 shiftKey: false,
115525 metaKey: false,
115526 keyCode: 0,
115527 charCode: 0
115528 }, arguments[2] || {});
115529
115530 var oEvent = document.createEvent("KeyEvents");
115531 oEvent.initKeyEvent(eventName, true, true, window,
115532 options.ctrlKey, options.altKey, options.shiftKey, options.metaKey,
115533 options.keyCode, options.charCode );
115534 $(element).dispatchEvent(oEvent);
115535 };
115536
115537 Event.simulateKeys = function(element, command) {
115538 for(var i=0; i<command.length; i++) {
115539 Event.simulateKey(element,'keypress',{charCode:command.charCodeAt(i)});
115540 }
115541 };
115542
115543 var Test = {}
115544 Test.Unit = {};
115545
115546 // security exception workaround
115547 Test.Unit.inspect = Object.inspect;
115548
115549 Test.Unit.Logger = Class.create();
115550 Test.Unit.Logger.prototype = {
115551 initialize: function(log) {
115552 this.log = $(log);
115553 if (this.log) {
115554 this._createLogTable();
115555 }
115556 },
115557 start: function(testName) {
115558 if (!this.log) return;
115559 this.testName = testName;
115560 this.lastLogLine = document.createElement('tr');
115561 this.statusCell = document.createElement('td');
115562 this.nameCell = document.createElement('td');
115563 this.nameCell.className = "nameCell";
115564 this.nameCell.appendChild(document.createTextNode(testName));
115565 this.messageCell = document.createElement('td');
115566 this.lastLogLine.appendChild(this.statusCell);
115567 this.lastLogLine.appendChild(this.nameCell);
115568 this.lastLogLine.appendChild(this.messageCell);
115569 this.loglines.appendChild(this.lastLogLine);
115570 },
115571 finish: function(status, summary) {
115572 if (!this.log) return;
115573 this.lastLogLine.className = status;
115574 this.statusCell.innerHTML = status;
115575 this.messageCell.innerHTML = this._toHTML(summary);
115576 this.addLinksToResults();
115577 },
115578 message: function(message) {
115579 if (!this.log) return;
115580 this.messageCell.innerHTML = this._toHTML(message);
115581 },
115582 summary: function(summary) {
115583 if (!this.log) return;
115584 this.logsummary.innerHTML = this._toHTML(summary);
115585 },
115586 _createLogTable: function() {
115587 this.log.innerHTML =
115588 '<div id="logsummary"></div>' +
115589 '<table id="logtable">' +
115590 '<thead><tr><th>Status</th><th>Test</th><th>Message</th></tr></thead>' +
115591 '<tbody id="loglines"></tbody>' +
115592 '</table>';
115593 this.logsummary = $('logsummary')
115594 this.loglines = $('loglines');
115595 },
115596 _toHTML: function(txt) {
115597 return txt.escapeHTML().replace(/\n/g,"<br/>");
115598 },
115599 addLinksToResults: function(){
115600 $$("tr.failed .nameCell").each( function(td){ // todo: limit to children of this.log
115601 td.title = "Run only this test"
115602 Event.observe(td, 'click', function(){ window.location.search = "?tests=" + td.innerHTML;});
115603 });
115604 $$("tr.passed .nameCell").each( function(td){ // todo: limit to children of this.log
115605 td.title = "Run all tests"
115606 Event.observe(td, 'click', function(){ window.location.search = "";});
115607 });
115608 }
115609 }
115610
115611 Test.Unit.Runner = Class.create();
115612 Test.Unit.Runner.prototype = {
115613 initialize: function(testcases) {
115614 this.options = Object.extend({
115615 testLog: 'testlog'
115616 }, arguments[1] || {});
115617 this.options.resultsURL = this.parseResultsURLQueryParameter();
115618 this.options.tests = this.parseTestsQueryParameter();
115619 if (this.options.testLog) {
115620 this.options.testLog = $(this.options.testLog) || null;
115621 }
115622 if(this.options.tests) {
115623 this.tests = [];
115624 for(var i = 0; i < this.options.tests.length; i++) {
115625 if(/^test/.test(this.options.tests[i])) {
115626 this.tests.push(new Test.Unit.Testcase(this.options.tests[i], testcases[this.options.tests[i]], testcases["setup"], testcases["teardown"]));
115627 }
115628 }
115629 } else {
115630 if (this.options.test) {
115631 this.tests = [new Test.Unit.Testcase(this.options.test, testcases[this.options.test], testcases["setup"], testcases["teardown"])];
115632 } else {
115633 this.tests = [];
115634 for(var testcase in testcases) {
115635 if(/^test/.test(testcase)) {
115636 this.tests.push(
115637 new Test.Unit.Testcase(
115638 this.options.context ? ' -> ' + this.options.titles[testcase] : testcase,
115639 testcases[testcase], testcases["setup"], testcases["teardown"]
115640 ));
115641 }
115642 }
115643 }
115644 }
115645 this.currentTest = 0;
115646 this.logger = new Test.Unit.Logger(this.options.testLog);
115647 setTimeout(this.runTests.bind(this), 1000);
115648 },
115649 parseResultsURLQueryParameter: function() {
115650 return window.location.search.parseQuery()["resultsURL"];
115651 },
115652 parseTestsQueryParameter: function(){
115653 if (window.location.search.parseQuery()["tests"]){
115654 return window.location.search.parseQuery()["tests"].split(',');
115655 };
115656 },
115657 // Returns:
115658 // "ERROR" if there was an error,
115659 // "FAILURE" if there was a failure, or
115660 // "SUCCESS" if there was neither
115661 getResult: function() {
115662 var hasFailure = false;
115663 for(var i=0;i<this.tests.length;i++) {
115664 if (this.tests[i].errors > 0) {
115665 return "ERROR";
115666 }
115667 if (this.tests[i].failures > 0) {
115668 hasFailure = true;
115669 }
115670 }
115671 if (hasFailure) {
115672 return "FAILURE";
115673 } else {
115674 return "SUCCESS";
115675 }
115676 },
115677 postResults: function() {
115678 if (this.options.resultsURL) {
115679 new Ajax.Request(this.options.resultsURL,
115680 { method: 'get', parameters: 'result=' + this.getResult(), asynchronous: false });
115681 }
115682 },
115683 runTests: function() {
115684 var test = this.tests[this.currentTest];
115685 if (!test) {
115686 // finished!
115687 this.postResults();
115688 this.logger.summary(this.summary());
115689 return;
115690 }
115691 if(!test.isWaiting) {
115692 this.logger.start(test.name);
115693 }
115694 test.run();
115695 if(test.isWaiting) {
115696 this.logger.message("Waiting for " + test.timeToWait + "ms");
115697 setTimeout(this.runTests.bind(this), test.timeToWait || 1000);
115698 } else {
115699 this.logger.finish(test.status(), test.summary());
115700 this.currentTest++;
115701 // tail recursive, hopefully the browser will skip the stackframe
115702 this.runTests();
115703 }
115704 },
115705 summary: function() {
115706 var assertions = 0;
115707 var failures = 0;
115708 var errors = 0;
115709 var messages = [];
115710 for(var i=0;i<this.tests.length;i++) {
115711 assertions += this.tests[i].assertions;
115712 failures += this.tests[i].failures;
115713 errors += this.tests[i].errors;
115714 }
115715 return (
115716 (this.options.context ? this.options.context + ': ': '') +
115717 this.tests.length + " tests, " +
115718 assertions + " assertions, " +
115719 failures + " failures, " +
115720 errors + " errors");
115721 }
115722 }
115723
115724 Test.Unit.Assertions = Class.create();
115725 Test.Unit.Assertions.prototype = {
115726 initialize: function() {
115727 this.assertions = 0;
115728 this.failures = 0;
115729 this.errors = 0;
115730 this.messages = [];
115731 },
115732 summary: function() {
115733 return (
115734 this.assertions + " assertions, " +
115735 this.failures + " failures, " +
115736 this.errors + " errors" + "\n" +
115737 this.messages.join("\n"));
115738 },
115739 pass: function() {
115740 this.assertions++;
115741 },
115742 fail: function(message) {
115743 this.failures++;
115744 this.messages.push("Failure: " + message);
115745 },
115746 info: function(message) {
115747 this.messages.push("Info: " + message);
115748 },
115749 error: function(error) {
115750 this.errors++;
115751 this.messages.push(error.name + ": "+ error.message + "(" + Test.Unit.inspect(error) +")");
115752 },
115753 status: function() {
115754 if (this.failures > 0) return 'failed';
115755 if (this.errors > 0) return 'error';
115756 return 'passed';
115757 },
115758 assert: function(expression) {
115759 var message = arguments[1] || 'assert: got "' + Test.Unit.inspect(expression) + '"';
115760 try { expression ? this.pass() :
115761 this.fail(message); }
115762 catch(e) { this.error(e); }
115763 },
115764 assertEqual: function(expected, actual) {
115765 var message = arguments[2] || "assertEqual";
115766 try { (expected == actual) ? this.pass() :
115767 this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
115768 '", actual "' + Test.Unit.inspect(actual) + '"'); }
115769 catch(e) { this.error(e); }
115770 },
115771 assertInspect: function(expected, actual) {
115772 var message = arguments[2] || "assertInspect";
115773 try { (expected == actual.inspect()) ? this.pass() :
115774 this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
115775 '", actual "' + Test.Unit.inspect(actual) + '"'); }
115776 catch(e) { this.error(e); }
115777 },
115778 assertEnumEqual: function(expected, actual) {
115779 var message = arguments[2] || "assertEnumEqual";
115780 try { $A(expected).length == $A(actual).length &&
115781 expected.zip(actual).all(function(pair) { return pair[0] == pair[1] }) ?
115782 this.pass() : this.fail(message + ': expected ' + Test.Unit.inspect(expected) +
115783 ', actual ' + Test.Unit.inspect(actual)); }
115784 catch(e) { this.error(e); }
115785 },
115786 assertNotEqual: function(expected, actual) {
115787 var message = arguments[2] || "assertNotEqual";
115788 try { (expected != actual) ? this.pass() :
115789 this.fail(message + ': got "' + Test.Unit.inspect(actual) + '"'); }
115790 catch(e) { this.error(e); }
115791 },
115792 assertIdentical: function(expected, actual) {
115793 var message = arguments[2] || "assertIdentical";
115794 try { (expected === actual) ? this.pass() :
115795 this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
115796 '", actual "' + Test.Unit.inspect(actual) + '"'); }
115797 catch(e) { this.error(e); }
115798 },
115799 assertNotIdentical: function(expected, actual) {
115800 var message = arguments[2] || "assertNotIdentical";
115801 try { !(expected === actual) ? this.pass() :
115802 this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
115803 '", actual "' + Test.Unit.inspect(actual) + '"'); }
115804 catch(e) { this.error(e); }
115805 },
115806 assertNull: function(obj) {
115807 var message = arguments[1] || 'assertNull'
115808 try { (obj==null) ? this.pass() :
115809 this.fail(message + ': got "' + Test.Unit.inspect(obj) + '"'); }
115810 catch(e) { this.error(e); }
115811 },
115812 assertMatch: function(expected, actual) {
115813 var message = arguments[2] || 'assertMatch';
115814 var regex = new RegExp(expected);
115815 try { (regex.exec(actual)) ? this.pass() :
115816 this.fail(message + ' : regex: "' + Test.Unit.inspect(expected) + ' did not match: ' + Test.Unit.inspect(actual) + '"'); }
115817 catch(e) { this.error(e); }
115818 },
115819 assertHidden: function(element) {
115820 var message = arguments[1] || 'assertHidden';
115821 this.assertEqual("none", element.style.display, message);
115822 },
115823 assertNotNull: function(object) {
115824 var message = arguments[1] || 'assertNotNull';
115825 this.assert(object != null, message);
115826 },
115827 assertType: function(expected, actual) {
115828 var message = arguments[2] || 'assertType';
115829 try {
115830 (actual.constructor == expected) ? this.pass() :
115831 this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
115832 '", actual "' + (actual.constructor) + '"'); }
115833 catch(e) { this.error(e); }
115834 },
115835 assertNotOfType: function(expected, actual) {
115836 var message = arguments[2] || 'assertNotOfType';
115837 try {
115838 (actual.constructor != expected) ? this.pass() :
115839 this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
115840 '", actual "' + (actual.constructor) + '"'); }
115841 catch(e) { this.error(e); }
115842 },
115843 assertInstanceOf: function(expected, actual) {
115844 var message = arguments[2] || 'assertInstanceOf';
115845 try {
115846 (actual instanceof expected) ? this.pass() :
115847 this.fail(message + ": object was not an instance of the expected type"); }
115848 catch(e) { this.error(e); }
115849 },
115850 assertNotInstanceOf: function(expected, actual) {
115851 var message = arguments[2] || 'assertNotInstanceOf';
115852 try {
115853 !(actual instanceof expected) ? this.pass() :
115854 this.fail(message + ": object was an instance of the not expected type"); }
115855 catch(e) { this.error(e); }
115856 },
115857 assertRespondsTo: function(method, obj) {
115858 var message = arguments[2] || 'assertRespondsTo';
115859 try {
115860 (obj[method] && typeof obj[method] == 'function') ? this.pass() :
115861 this.fail(message + ": object doesn't respond to [" + method + "]"); }
115862 catch(e) { this.error(e); }
115863 },
115864 assertReturnsTrue: function(method, obj) {
115865 var message = arguments[2] || 'assertReturnsTrue';
115866 try {
115867 var m = obj[method];
115868 if(!m) m = obj['is'+method.charAt(0).toUpperCase()+method.slice(1)];
115869 m() ? this.pass() :
115870 this.fail(message + ": method returned false"); }
115871 catch(e) { this.error(e); }
115872 },
115873 assertReturnsFalse: function(method, obj) {
115874 var message = arguments[2] || 'assertReturnsFalse';
115875 try {
115876 var m = obj[method];
115877 if(!m) m = obj['is'+method.charAt(0).toUpperCase()+method.slice(1)];
115878 !m() ? this.pass() :
115879 this.fail(message + ": method returned true"); }
115880 catch(e) { this.error(e); }
115881 },
115882 assertRaise: function(exceptionName, method) {
115883 var message = arguments[2] || 'assertRaise';
115884 try {
115885 method();
115886 this.fail(message + ": exception expected but none was raised"); }
115887 catch(e) {
115888 ((exceptionName == null) || (e.name==exceptionName)) ? this.pass() : this.error(e);
115889 }
115890 },
115891 assertElementsMatch: function() {
115892 var expressions = $A(arguments), elements = $A(expressions.shift());
115893 if (elements.length != expressions.length) {
115894 this.fail('assertElementsMatch: size mismatch: ' + elements.length + ' elements, ' + expressions.length + ' expressions');
115895 return false;
115896 }
115897 elements.zip(expressions).all(function(pair, index) {
115898 var element = $(pair.first()), expression = pair.last();
115899 if (element.match(expression)) return true;
115900 this.fail('assertElementsMatch: (in index ' + index + ') expected ' + expression.inspect() + ' but got ' + element.inspect());
115901 }.bind(this)) && this.pass();
115902 },
115903 assertElementMatches: function(element, expression) {
115904 this.assertElementsMatch([element], expression);
115905 },
115906 benchmark: function(operation, iterations) {
115907 var startAt = new Date();
115908 (iterations || 1).times(operation);
115909 var timeTaken = ((new Date())-startAt);
115910 this.info((arguments[2] || 'Operation') + ' finished ' +
115911 iterations + ' iterations in ' + (timeTaken/1000)+'s' );
115912 return timeTaken;
115913 },
115914 _isVisible: function(element) {
115915 element = $(element);
115916 if(!element.parentNode) return true;
115917 this.assertNotNull(element);
115918 if(element.style && Element.getStyle(element, 'display') == 'none')
115919 return false;
115920
115921 return this._isVisible(element.parentNode);
115922 },
115923 assertNotVisible: function(element) {
115924 this.assert(!this._isVisible(element), Test.Unit.inspect(element) + " was not hidden and didn't have a hidden parent either. " + ("" || arguments[1]));
115925 },
115926 assertVisible: function(element) {
115927 this.assert(this._isVisible(element), Test.Unit.inspect(element) + " was not visible. " + ("" || arguments[1]));
115928 },
115929 benchmark: function(operation, iterations) {
115930 var startAt = new Date();
115931 (iterations || 1).times(operation);
115932 var timeTaken = ((new Date())-startAt);
115933 this.info((arguments[2] || 'Operation') + ' finished ' +
115934 iterations + ' iterations in ' + (timeTaken/1000)+'s' );
115935 return timeTaken;
115936 }
115937 }
115938
115939 Test.Unit.Testcase = Class.create();
115940 Object.extend(Object.extend(Test.Unit.Testcase.prototype, Test.Unit.Assertions.prototype), {
115941 initialize: function(name, test, setup, teardown) {
115942 Test.Unit.Assertions.prototype.initialize.bind(this)();
115943 this.name = name;
115944
115945 if(typeof test == 'string') {
115946 test = test.gsub(/(\.should[^\(]+\()/,'#{0}this,');
115947 test = test.gsub(/(\.should[^\(]+)\(this,\)/,'#{1}(this)');
115948 this.test = function() {
115949 eval('with(this){'+test+'}');
115950 }
115951 } else {
115952 this.test = test || function() {};
115953 }
115954
115955 this.setup = setup || function() {};
115956 this.teardown = teardown || function() {};
115957 this.isWaiting = false;
115958 this.timeToWait = 1000;
115959 },
115960 wait: function(time, nextPart) {
115961 this.isWaiting = true;
115962 this.test = nextPart;
115963 this.timeToWait = time;
115964 },
115965 run: function() {
115966 try {
115967 try {
115968 if (!this.isWaiting) this.setup.bind(this)();
115969 this.isWaiting = false;
115970 this.test.bind(this)();
115971 } finally {
115972 if(!this.isWaiting) {
115973 this.teardown.bind(this)();
115974 }
115975 }
115976 }
115977 catch(e) { this.error(e); }
115978 }
115979 });
115980
115981 // *EXPERIMENTAL* BDD-style testing to please non-technical folk
115982 // This draws many ideas from RSpec http://rspec.rubyforge.org/
115983
115984 Test.setupBDDExtensionMethods = function(){
115985 var METHODMAP = {
115986 shouldEqual: 'assertEqual',
115987 shouldNotEqual: 'assertNotEqual',
115988 shouldEqualEnum: 'assertEnumEqual',
115989 shouldBeA: 'assertType',
115990 shouldNotBeA: 'assertNotOfType',
115991 shouldBeAn: 'assertType',
115992 shouldNotBeAn: 'assertNotOfType',
115993 shouldBeNull: 'assertNull',
115994 shouldNotBeNull: 'assertNotNull',
115995
115996 shouldBe: 'assertReturnsTrue',
115997 shouldNotBe: 'assertReturnsFalse',
115998 shouldRespondTo: 'assertRespondsTo'
115999 };
116000 var makeAssertion = function(assertion, args, object) {
116001 this[assertion].apply(this,(args || []).concat([object]));
116002 }
116003
116004 Test.BDDMethods = {};
116005 $H(METHODMAP).each(function(pair) {
116006 Test.BDDMethods[pair.key] = function() {
116007 var args = $A(arguments);
116008 var scope = args.shift();
116009 makeAssertion.apply(scope, [pair.value, args, this]); };
116010 });
116011
116012 [Array.prototype, String.prototype, Number.prototype, Boolean.prototype].each(
116013 function(p){ Object.extend(p, Test.BDDMethods) }
116014 );
116015 }
116016
116017 Test.context = function(name, spec, log){
116018 Test.setupBDDExtensionMethods();
116019
116020 var compiledSpec = {};
116021 var titles = {};
116022 for(specName in spec) {
116023 switch(specName){
116024 case "setup":
116025 case "teardown":
116026 compiledSpec[specName] = spec[specName];
116027 break;
116028 default:
116029 var testName = 'test'+specName.gsub(/\s+/,'-').camelize();
116030 var body = spec[specName].toString().split('\n').slice(1);
116031 if(/^\{/.test(body[0])) body = body.slice(1);
116032 body.pop();
116033 body = body.map(function(statement){
116034 return statement.strip()
116035 });
116036 compiledSpec[testName] = body.join('\n');
116037 titles[testName] = specName;
116038 }
116039 }
116040 new Test.Unit.Runner(compiledSpec, { titles: titles, testLog: log || 'testlog', context: name });
116041 };