evidence.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059
  1. /* evidence.js, version 0.6
  2. *
  3. * Copyright (c) 2009 Tobie Langel (http://tobielangel.com)
  4. *
  5. * evidence.js is freely distributable under the terms of an MIT-style license.
  6. *--------------------------------------------------------------------------*/
  7. (function(global) {
  8. var originalEvidence = global.Evidence,
  9. originalOnload = global.onload;
  10. function Evidence() {
  11. TestCase.extend.apply(TestCase, arguments);
  12. }
  13. function noConflict() {
  14. global.Evidence = originalEvidence;
  15. return Evidence;
  16. }
  17. Evidence.noConflict = noConflict;
  18. Evidence.VERSION = '0.6';
  19. var FILE_REGEXP = /.*?\/(\w+\.html)(.*)/;
  20. function getNameFromFile() {
  21. return (global.location || '').toString().replace(FILE_REGEXP, '$1');
  22. }
  23. function chain(subclass, superclass) {
  24. function Subclass() {}
  25. Subclass.prototype = superclass.prototype;
  26. subclass.prototype = new Subclass();
  27. subclass.prototype.constructor = subclass;
  28. return subclass;
  29. }
  30. function defer(block, context) {
  31. if ('setTimeout' in global) {
  32. window.setTimeout(function() {
  33. block.call(context);
  34. }, 10);
  35. } else {
  36. block.call(context);
  37. }
  38. }
  39. function AssertionSkippedError(message) {
  40. this.message = message;
  41. }
  42. AssertionSkippedError.displayName = 'AssertionSkippedError';
  43. (function(p) {
  44. p.name = 'AssertionSkippedError';
  45. })(AssertionSkippedError.prototype);
  46. Evidence.AssertionSkippedError = AssertionSkippedError;
  47. function AssertionFailedError(message, template, args) {
  48. this.message = message;
  49. this.template = template || '';
  50. this.args = args;
  51. }
  52. AssertionFailedError.displayName = 'AssertionFailedError';
  53. (function(p) {
  54. p.name = 'AssertionFailedError';
  55. })(AssertionFailedError.prototype);
  56. Evidence.AssertionFailedError = AssertionFailedError;
  57. function AssertionMessage(message, template, args) {
  58. this.message = message.replace(/%/g, '%%');
  59. this.template = template || '';
  60. this.args = args;
  61. }
  62. AssertionMessage.displayName = 'AssertionMessage';
  63. (function(p) {
  64. function toString() {
  65. return UI.printf(this.message + this.template, this.args);
  66. }
  67. p.toString = toString;
  68. })(AssertionMessage.prototype);
  69. Evidence.AssertionMessage = AssertionMessage;
  70. var Assertions = (function() {
  71. function _assertExpression(expression, message, template) {
  72. /*for (var i=0; i < 100000; i++) {
  73. (function(){})()
  74. }*/
  75. if (expression) {
  76. this.addAssertion();
  77. } else {
  78. var args = Array.prototype.slice.call(arguments, 3);
  79. throw new AssertionFailedError(message, template, args);
  80. }
  81. }
  82. function skip(message) {
  83. throw new AssertionSkippedError(message || 'Skipped!');
  84. }
  85. function fail(message) {
  86. this._assertExpression(false, message || 'Flunked!');
  87. }
  88. function assert(test, message) {
  89. this._assertExpression(
  90. !!test,
  91. message || 'Failed assertion.',
  92. 'Expected %o to evaluate to true.', test
  93. );
  94. }
  95. function refute(test, message) {
  96. this._assertExpression(
  97. !test,
  98. message || 'Failed refutation.',
  99. 'Expected %o to evaluate to false.', test
  100. );
  101. }
  102. function assertTrue(test, message) {
  103. this._assertExpression(
  104. (test === true),
  105. message || 'Failed assertion.',
  106. 'Expected %o to be true.', test
  107. );
  108. }
  109. function refuteTrue(test, message) {
  110. this._assertExpression(
  111. (test !== true),
  112. message || 'Failed refutation.',
  113. 'Expected %o to not be true.', test
  114. );
  115. }
  116. function assertNull(test, message) {
  117. this._assertExpression(
  118. (test === null),
  119. message || 'Failed assertion.',
  120. 'Expected %o to be null.', test
  121. );
  122. }
  123. function refuteNull(test, message) {
  124. this._assertExpression(
  125. (test !== null),
  126. message || 'Failed refutation.',
  127. 'Expected %o to not be null.', test
  128. );
  129. }
  130. function assertUndefined(test, message) {
  131. this._assertExpression(
  132. (typeof test === 'undefined'),
  133. message || 'Failed assertion.',
  134. 'Expected %o to be undefined.', test
  135. );
  136. }
  137. function refuteUndefined(test, message) {
  138. this._assertExpression(
  139. (typeof test !== 'undefined'),
  140. message || 'Failed refutation.',
  141. 'Expected %o to not be undefined.', test
  142. );
  143. }
  144. function assertFalse(test, message) {
  145. this._assertExpression(
  146. (test === false),
  147. message || 'Failed assertion.',
  148. 'Expected %o to be false.', test
  149. );
  150. }
  151. function refuteFalse(test, message) {
  152. this._assertExpression(
  153. (test !== false),
  154. message || 'Failed refutation.',
  155. 'Expected %o to not be false.', test
  156. );
  157. }
  158. function assertEqual(expected, actual, message) {
  159. this._assertExpression(
  160. (expected == actual),
  161. message || 'Failed assertion.',
  162. 'Expected %o to be == to %o.', actual, expected
  163. );
  164. }
  165. function refuteEqual(expected, actual, message) {
  166. this._assertExpression(
  167. (expected != actual),
  168. message || 'Failed refutation.',
  169. 'Expected %o to be != to %o.', actual, expected
  170. );
  171. }
  172. function assertIdentical(expected, actual, message) {
  173. this._assertExpression(
  174. (expected === actual),
  175. message || 'Failed assertion.',
  176. 'Expected %o to be === to %o.', actual, expected
  177. );
  178. }
  179. function refuteIdentical(expected, actual, message) {
  180. this._assertExpression(
  181. (expected !== actual),
  182. message || 'Failed refutation.',
  183. 'Expected %o to be !== to %o.', actual, expected
  184. );
  185. }
  186. function assertIn(property, object, message) {
  187. this._assertExpression(
  188. (property in object),
  189. message || 'Failed assertion.',
  190. 'Expected "%s" to be a property of %o.', property, object
  191. );
  192. }
  193. function refuteIn(property, object, message) {
  194. this._assertExpression(
  195. !(property in object),
  196. message || 'Failed refutation.',
  197. 'Expected "%s" to not be a property of %o.', property, object
  198. );
  199. }
  200. return {
  201. _assertExpression: _assertExpression,
  202. skip: skip,
  203. assert: assert,
  204. refute: refute,
  205. assertNot: refute,
  206. assertTrue: assertTrue,
  207. assertNull: assertNull,
  208. assertUndefined: assertUndefined,
  209. assertFalse: assertFalse,
  210. assertIdentical: assertIdentical,
  211. refuteIdentical: refuteIdentical,
  212. assertEqual: assertEqual,
  213. refuteEqual: refuteEqual,
  214. assertIn: assertIn,
  215. refuteIn: refuteIn,
  216. fail: fail,
  217. flunk: fail
  218. };
  219. })();
  220. Evidence.Assertions = Assertions;
  221. function TestCase(methodName) {
  222. this._methodName = methodName;
  223. this.name = methodName;
  224. }
  225. (function() {
  226. function extend(name, methods) {
  227. function TestCaseSubclass(methodName) {
  228. TestCase.call(this, methodName);
  229. }
  230. if (!methods) {
  231. methods = name;
  232. name = getNameFromFile();
  233. }
  234. chain(TestCaseSubclass, this);
  235. TestCaseSubclass.displayName = name;
  236. TestCaseSubclass.extend = extend;
  237. for(var prop in methods) {
  238. TestCaseSubclass.prototype[prop] = methods[prop];
  239. }
  240. TestCase.subclasses.push(TestCaseSubclass);
  241. return TestCaseSubclass;
  242. }
  243. function AssertionsMixin() {}
  244. AssertionsMixin.prototype = Assertions;
  245. TestCase.prototype = new AssertionsMixin();
  246. TestCase.constructor = TestCase;
  247. TestCase.displayName = 'TestCase';
  248. TestCase.extend = extend;
  249. TestCase.subclasses = [];
  250. TestCase.defaultTimeout = 10000;
  251. })();
  252. (function(p) {
  253. function run(result) {
  254. if (result) { this._result = result; }
  255. try {
  256. if (this._nextAssertions) {
  257. this._result.restartTest(this);
  258. this._nextAssertions(this);
  259. } else {
  260. /*this._globalProperties = objectKeys(global);*/
  261. this._result.startTest(this);
  262. this.setUp(this);
  263. this[this._methodName](this);
  264. }
  265. } catch(e) {
  266. this._filterException(e);
  267. } finally {
  268. if (this._paused) {
  269. this._result.pauseTest(this);
  270. } else {
  271. try {
  272. this.tearDown(this);
  273. } catch(e) {
  274. this._filterException(e);
  275. } finally {
  276. this._nextAssertions = null;
  277. this._result.stopTest(this);
  278. defer(function() {
  279. this.parent.next();
  280. }, this);
  281. }
  282. }
  283. }
  284. }
  285. function _filterException(e) {
  286. var name = e.name;
  287. switch(name) {
  288. case 'AssertionFailedError':
  289. this._result.addFailure(this, e);
  290. break;
  291. case 'AssertionSkippedError':
  292. this._result.addSkip(this, e);
  293. break;
  294. default:
  295. this._result.addError(this, e + ('stack' in e ? "\n"+e.stack : ''));
  296. }
  297. }
  298. function pause(assertions) {
  299. this._paused = true;
  300. var self = this;
  301. if (assertions) { this._nextAssertions = assertions; }
  302. self._timeoutId = global.setTimeout(function() {
  303. self.resume(function() {
  304. self.fail('Test timed out. Testing was not resumed after being paused.');
  305. });
  306. }, TestCase.defaultTimeout);
  307. }
  308. function resume(assertions) {
  309. if (this._paused) { // avoid race conditions
  310. this._paused = false;
  311. global.clearTimeout(this._timeoutId);
  312. if (assertions) { this._nextAssertions = assertions; }
  313. this.run();
  314. }
  315. }
  316. function size() {
  317. return 1;
  318. }
  319. function toString() {
  320. return this.constructor.displayName + '#' + this.name;
  321. }
  322. function addAssertion() {
  323. this._result.addAssertion();
  324. }
  325. p.run = run;
  326. p.addAssertion = addAssertion;
  327. p._filterException = _filterException;
  328. p.pause = pause;
  329. p.resume = resume;
  330. p.size = size;
  331. p.toString = toString;
  332. p.setUp = function() {};
  333. p.tearDown = function() {};
  334. })(TestCase.prototype);
  335. Evidence.TestCase = TestCase;
  336. function TestSuite(name, tests) {
  337. this.name = name;
  338. this._tests = [];
  339. if (tests) {
  340. this.push.apply(this, tests);
  341. }
  342. }
  343. TestSuite.displayName = 'TestSuite';
  344. (function(p) {
  345. function run(result) {
  346. this._index = 0;
  347. this._result = result;
  348. result.startSuite(this);
  349. this.next();
  350. return result;
  351. }
  352. function next() {
  353. var next = this._tests[this._index];
  354. if (next) {
  355. this._index++;
  356. next.run(this._result);
  357. } else {
  358. this._result.stopSuite(this);
  359. if (this.parent) {
  360. this.parent.next();
  361. } else {
  362. this._result.stop(new Date());
  363. }
  364. }
  365. }
  366. function push() {
  367. for (var i = 0, length = arguments.length; i < length; i++) {
  368. var test = arguments[i];
  369. test.parent = this;
  370. this._tests.push(test);
  371. }
  372. }
  373. function addTest(test) {
  374. test.parent = this;
  375. this._tests.push(test);
  376. }
  377. function addTests(tests) {
  378. for (var i = 0, length = tests.length; i < length; i++) {
  379. this.addTest(tests[i]);
  380. }
  381. }
  382. function size() {
  383. var tests = this._tests,
  384. length = tests.length,
  385. sum = 0;
  386. for (var i = 0; i < length; i++) {
  387. sum += tests[i].size();
  388. }
  389. return sum;
  390. }
  391. function isEmpty() {
  392. return this.size() === 0;
  393. }
  394. function toString() {
  395. return this.name;
  396. }
  397. p.run = run;
  398. p.next = next;
  399. p.push = push;
  400. p.size = size;
  401. p.isEmpty = isEmpty;
  402. p.toString = toString;
  403. })(TestSuite.prototype);
  404. Evidence.TestSuite = TestSuite;
  405. function TestRunner() {
  406. }
  407. TestRunner.displayName = 'TestRunner';
  408. (function(p) {
  409. function run(suite) {
  410. suite.parent = null;
  411. var result = this._makeResult();
  412. result.start(new Date());
  413. suite.run(result);
  414. return result;
  415. }
  416. function _makeResult() {
  417. return new TestResult();
  418. }
  419. p.run = run;
  420. p._makeResult = _makeResult;
  421. })(TestRunner.prototype);
  422. Evidence.TestRunner = TestRunner;
  423. function TestLoader() {
  424. }
  425. TestLoader.displayName = 'TestLoader';
  426. (function(p) {
  427. function loadTestsFromTestCase(testcaseClass) {
  428. var suite = new TestSuite(testcaseClass.displayName),
  429. props = this.getTestCaseNames(testcaseClass);
  430. for (var i=0; i < props.length; i++) {
  431. suite.push(new testcaseClass(props[i]));
  432. }
  433. return suite;
  434. }
  435. function loadTestsFromTestCases(testcases) {
  436. var suite = new TestSuite(getNameFromFile());
  437. for (var i = 0; i < testcases.length; i++) {
  438. var testcase = testcases[i];
  439. var subSuite = defaultLoader.loadTestsFromTestCase(testcase);
  440. if (!subSuite.isEmpty()) { suite.push(subSuite); }
  441. }
  442. return suite;
  443. }
  444. function getTestCaseNames(testcaseClass) {
  445. var results = [],
  446. proto = testcaseClass.prototype,
  447. prefix = this.testMethodPrefix;
  448. for (var property in proto) {
  449. if (property.indexOf(prefix) === 0) {
  450. results.push(property);
  451. }
  452. }
  453. return results.sort();
  454. }
  455. function loadRegisteredTestCases() {
  456. return loadTestsFromTestCases(TestCase.subclasses);
  457. }
  458. p.loadTestsFromTestCase = loadTestsFromTestCase;
  459. p.loadRegisteredTestCases = loadRegisteredTestCases;
  460. p.loadTestsFromTestCases = loadTestsFromTestCases;
  461. p.testMethodPrefix = 'test';
  462. p.getTestCaseNames = getTestCaseNames;
  463. })(TestLoader.prototype);
  464. Evidence.TestLoader = TestLoader;
  465. function AutoRunner() {
  466. if (global.console && global.console.log) {
  467. this.logger = Logger;
  468. } else if (Object.prototype.toString.call(global.environment) === '[object Environment]' && global.print) {
  469. this.logger = CommandLineLogger;
  470. } else {
  471. this.logger = PopupLogger;
  472. }
  473. this.autoRun = true;
  474. this.verbosity = Logger.INFO;
  475. this.runner = ConsoleTestRunner;
  476. }
  477. (function() {
  478. function run(options) {
  479. var autoRunner = new this();
  480. options = options || autoRunner.retrieveOptions();
  481. autoRunner.processOptions(options);
  482. if (autoRunner.autoRun) { autoRunner.run() };
  483. }
  484. AutoRunner.run = run;
  485. AutoRunner.displayName = 'AutoRunner';
  486. AutoRunner.LOGGERS = {
  487. console: Logger,
  488. popup: PopupLogger,
  489. command_line: CommandLineLogger
  490. };
  491. AutoRunner.RUNNERS = {
  492. console: ConsoleTestRunner
  493. };
  494. })();
  495. (function(p) {
  496. function run() {
  497. var logger = new this.logger(this.verbosity),
  498. runner = new this.runner(logger),
  499. suite = defaultLoader.loadRegisteredTestCases();
  500. if (suite._tests.length <= 1) {
  501. suite = suite._tests[0];
  502. }
  503. return runner.run(suite);
  504. }
  505. function processQueryString(str) {
  506. var results = {};
  507. str = (str + '').match(/^(?:[^?#]*\?)([^#]+?)(?:#.*)?$/);
  508. str = str && str[1];
  509. if (!str) { return results; }
  510. var pairs = str.split('&'),
  511. length = pairs.length;
  512. if (!length) { return results; }
  513. for (var i = 0; i < length; i++) {
  514. var pair = pairs[i].split('='),
  515. key = decodeURIComponent(pair[0]),
  516. value = pair[1];
  517. value = value ? decodeURIComponent(value) : true;
  518. results[key] = value;
  519. }
  520. return results;
  521. }
  522. function processArguments(args) { // RHINO
  523. var results = {};
  524. for (var i = 0; i < args.length; i++) {
  525. var arg = args[i];
  526. if (arg.indexOf('-') === 0) {
  527. var value = args[i + 1];
  528. if (value && value.indexOf('-') !== 0) {
  529. i++;
  530. } else {
  531. value = true;
  532. }
  533. results[arg.substr(1)] = value;
  534. }
  535. }
  536. return results;
  537. }
  538. function retrieveOptions() {
  539. if (global.location) {
  540. return this.processQueryString(global.location);
  541. }
  542. if (global.arguments) {
  543. return this.processArguments(global.arguments);
  544. }
  545. return {};
  546. }
  547. function processOptions(options) {
  548. for(var key in options) {
  549. var value = options[key];
  550. switch(key) {
  551. case 'timeout':
  552. TestCase.defaultTimeout = global.parseFloat(value) * 1000;
  553. break;
  554. case 'run':
  555. this.autoRun = value === 'false' ? false : true;
  556. break;
  557. case 'logger':
  558. this.logger = AutoRunner.LOGGERS[value];
  559. break;
  560. case 'verbosity':
  561. var i = global.parseInt(value);
  562. this.verbosity = global.isNaN(i) ? Logger[value] : i;
  563. break;
  564. case 'runner':
  565. this.runner = AutoRunner.RUNNERS[value];
  566. break;
  567. }
  568. }
  569. }
  570. p.run = run;
  571. p.processQueryString = processQueryString;
  572. p.processArguments = processArguments;
  573. p.retrieveOptions = retrieveOptions;
  574. p.processOptions = processOptions;
  575. })(AutoRunner.prototype);
  576. Evidence.AutoRunner = AutoRunner;
  577. function TestResult() {
  578. this.testCount = 0;
  579. this.assertionCount = 0;
  580. this.skipCount = 0;
  581. this.skips = [];
  582. this.failureCount = 0;
  583. this.failures = [];
  584. this.errors = [];
  585. this.errorCount = 0;
  586. this.testCount = 0;
  587. }
  588. TestResult.displayName = 'TestResult';
  589. (function(p) {
  590. function addAssertion() {
  591. this.assertionCount++;
  592. }
  593. function addSkip(testcase, reason) {
  594. this.skipCount++;
  595. this.skips.push(reason);
  596. }
  597. function addFailure(testcase, reason) {
  598. this.failureCount++;
  599. this.failures.push(reason);
  600. }
  601. function addError(testcase, error) {
  602. this.errorCount++;
  603. this.errors.push(error);
  604. }
  605. function startTest(testcase) {
  606. this.testCount++;
  607. }
  608. function stopTest(testcase) {}
  609. function pauseTest(testcase) {}
  610. function restartTest(testcase) {}
  611. function startSuite(suite) {}
  612. function stopSuite(suite) {}
  613. function start(t0) {
  614. this.t0 = t0;
  615. }
  616. function stop(t1) {
  617. this.t1 = t1;
  618. }
  619. function toString() {
  620. return this.testCount + ' tests, ' +
  621. this.assertionCount + ' assertions, ' +
  622. this.failureCount + ' failures, ' +
  623. this.errorCount + ' errors, ' +
  624. this.skipCount + ' skips';
  625. }
  626. p.addAssertion = addAssertion;
  627. p.addSkip = addSkip;
  628. p.addFailure = addFailure;
  629. p.addError = addError;
  630. p.startTest = startTest;
  631. p.stopTest = stopTest;
  632. p.pauseTest = pauseTest;
  633. p.restartTest = restartTest;
  634. p.startSuite = startSuite;
  635. p.stopSuite = stopSuite;
  636. p.start = start;
  637. p.stop = stop;
  638. p.toString = toString;
  639. })(TestResult.prototype);
  640. Evidence.TestResult = TestResult;
  641. var Console = {};
  642. function Logger(level) {
  643. if (typeof level !== 'undefined') {
  644. this.level = level;
  645. }
  646. }
  647. Logger.displayName = 'Logger';
  648. Logger.LEVELS = ['NOTSET', 'DEBUG', 'INFO', 'WARN', 'ERROR', 'CRITICAL'];
  649. Logger.CRITICAL = 5;
  650. Logger.ERROR = 4;
  651. Logger.WARN = 3;
  652. Logger.INFO = 2;
  653. Logger.DEBUG = 1;
  654. Logger.NOTSET = 0;
  655. (function(p) {
  656. function critical(template, params) {
  657. this.log(Logger.CRITICAL, template, params);
  658. }
  659. function error(template, params) {
  660. this.log(Logger.ERROR, template, params);
  661. }
  662. function warn(template, params) {
  663. this.log(Logger.WARN, template, params);
  664. }
  665. function info(template, params) {
  666. this.log(Logger.INFO, template, params);
  667. }
  668. function debug(template, params) {
  669. this.log(Logger.DEBUG, template, params);
  670. }
  671. function log(level, template, params) {
  672. level = level || Logger.NOTSET;
  673. var c = global.console;
  674. var method = Logger.LEVELS[level].toLowerCase();
  675. if (method === 'critical') { method = 'error'; }
  676. method = (method in c) ? method : 'log';
  677. if (level >= this.level) {
  678. if (params) {
  679. params = params.slice(0);
  680. params.unshift(template);
  681. c[method].apply(c, params);
  682. } else {
  683. c[method](template);
  684. }
  685. }
  686. }
  687. p.log = log;
  688. p.critical = critical;
  689. p.error = error;
  690. p.warn = warn;
  691. p.info = info;
  692. p.debug = debug;
  693. p.level = 0;
  694. })(Logger.prototype);
  695. Console.Logger = Logger;
  696. function PopupLogger(level) {
  697. Logger.call(this, level);
  698. }
  699. chain(PopupLogger, Logger);
  700. PopupLogger.displayName = 'PopupLogger';
  701. (function(p) {
  702. var BASIC_STYLES = 'color: #333; background-color: #fff; font-family: monospace; border-bottom: 1px solid #ccc;';
  703. var STYLES = {
  704. WARN: 'color: #000; background-color: #fc6;',
  705. ERROR: 'color: #f00; background-color: #fcc;',
  706. CRITICAL: 'color: #fff; background-color: #000;'
  707. };
  708. function _cleanup(html) {
  709. return html.replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&').replace(/[\n\r]+/, '<br />');
  710. }
  711. function _makePopup() {
  712. var popup = global.open('','popup','height=400,width=400');
  713. var doc = popup.document;
  714. doc.write('<!doctype html>\
  715. <html lang="en">\
  716. <head>\
  717. <meta charset="utf-8">\
  718. <title>Console</title>\
  719. </head>\
  720. <body><div id="evidence_console"></div></body>\
  721. </html>');
  722. doc.close();
  723. popup.focus();
  724. return popup;
  725. }
  726. function _appendLine(level, msg) {
  727. this.popup = this.popup || this._makePopup();
  728. var levelName = Logger.LEVELS[level];
  729. var html = '<div style="';
  730. html += BASIC_STYLES;
  731. html += STYLES[levelName] || '';
  732. html += '">';
  733. if (level > Logger.INFO) {
  734. html += '<span style="font-weight: bold;">';
  735. html += levelName;
  736. html += ':</span> ';
  737. }
  738. html += _cleanup(msg);
  739. html += '</div>';
  740. var doc = this.popup.document,
  741. div = doc.createElement('div');
  742. div.innerHTML = html;
  743. html = div.firstChild;
  744. div = null;
  745. doc.getElementById('evidence_console').appendChild(html);
  746. }
  747. function log(level, msg, params) {
  748. level = level || Logger.NOTSET;
  749. if (level >= this.level) {
  750. if (params) {
  751. msg = UI.printf(msg, params);
  752. }
  753. this._appendLine(level, msg);
  754. }
  755. }
  756. p.log = log;
  757. p._makePopup = _makePopup;
  758. p._appendLine = _appendLine;
  759. })(PopupLogger.prototype);
  760. Console.PopupLogger = PopupLogger;
  761. function CommandLineLogger(level) {
  762. Logger.call(this, level);
  763. }
  764. chain(CommandLineLogger, Logger);
  765. CommandLineLogger.displayName = 'CommandLineLogger';
  766. (function(p) {
  767. function log(level, msg, params) {
  768. level = level || Logger.NOTSET;
  769. if (level >= this.level) {
  770. var prefix = '';
  771. if (level > Logger.INFO) {
  772. prefix = Logger.LEVELS[level]+ ': ';
  773. }
  774. if (params) {
  775. msg = UI.printf(msg, params);
  776. }
  777. global.print(prefix + msg);
  778. }
  779. }
  780. p.log = log;
  781. })(CommandLineLogger.prototype);
  782. Console.CommandLineLogger = CommandLineLogger;
  783. function ConsoleTestRunner(logger) {
  784. TestRunner.call(this);
  785. this.logger = logger;
  786. }
  787. chain(ConsoleTestRunner, TestRunner);
  788. ConsoleTestRunner.displayName = 'ConsoleTestRunner';
  789. (function(p) {
  790. function _makeResult() {
  791. return new ConsoleTestResult(this.logger);
  792. }
  793. p._makeResult = _makeResult;
  794. })(ConsoleTestRunner.prototype);
  795. Console.TestRunner = ConsoleTestRunner;
  796. function ConsoleTestResult(logger) {
  797. TestResult.call(this);
  798. this.logger = logger;
  799. }
  800. chain(ConsoleTestResult, TestResult);
  801. ConsoleTestResult.displayName = 'ConsoleTestResult';
  802. (function(p) {
  803. var _super = TestResult.prototype;
  804. function addAssertion() {
  805. this.assertionCount++;
  806. }
  807. function addSkip(testcase, msg) {
  808. _super.addSkip.call(this, testcase, msg);
  809. this.logger.warn('Skipping testcase ' + testcase + ': ' + msg.message);
  810. }
  811. function addFailure(testcase, msg) {
  812. _super.addFailure.call(this, testcase, msg);
  813. this.logger.error(testcase + ': ' + msg.message + ' ' + msg.template, msg.args);
  814. }
  815. function addError(testcase, error) {
  816. _super.addError.call(this, testcase, error);
  817. this.logger.error(testcase + ' threw an error. ' + error);
  818. }
  819. function startTest(testcase) {
  820. _super.startTest.call(this, testcase);
  821. this.logger.debug('Started testcase ' + testcase + '.');
  822. }
  823. function stopTest(testcase) {
  824. this.logger.debug('Completed testcase ' + testcase + '.');
  825. }
  826. function pauseTest(testcase) {
  827. this.logger.info('Paused testcase ' + testcase + '.');
  828. }
  829. function restartTest(testcase) {
  830. this.logger.info('Restarted testcase ' + testcase + '.');
  831. }
  832. function startSuite(suite) {
  833. this.logger.info('Started suite ' + suite + '.');
  834. }
  835. function stopSuite(suite) {
  836. this.logger.info('Completed suite ' + suite + '.');
  837. }
  838. function start(t0) {
  839. _super.start.call(this, t0);
  840. this.logger.info('Started tests.');
  841. }
  842. function stop(t1) {
  843. _super.stop.call(this, t1);
  844. this.logger.info('Completed tests in ' + ((t1 - this.t0)/1000) + 's.');
  845. this.logger.info(this.toString() + '.');
  846. }
  847. p.addAssertion = addAssertion;
  848. p.addSkip = addSkip;
  849. p.addFailure = addFailure;
  850. p.addError = addError;
  851. p.startTest = startTest;
  852. p.stopTest = stopTest;
  853. p.pauseTest = pauseTest;
  854. p.restartTest = restartTest;
  855. p.startSuite = startSuite;
  856. p.stopSuite = stopSuite;
  857. p.start = start;
  858. p.stop = stop;
  859. })(ConsoleTestResult.prototype);
  860. Console.TestResult = ConsoleTestResult;
  861. var UI = (function() {
  862. function printf(template, args, inspector) {
  863. var parts = [], m,
  864. regexp = /(^%|.%)([a-zA-Z])/,
  865. args = args.slice(0); // clone args
  866. inspector = inspector || String;
  867. if (template.length <= 0) {
  868. return '';
  869. }
  870. while (m = regexp.exec(template)) {
  871. var match = m[0], index = m.index, type, arg;
  872. if (match.indexOf('%%') === 0) {
  873. parts.push(template.substr(0, index));
  874. parts.push(match.substr(1));
  875. } else {
  876. parts.push(template.substr(0, match.indexOf('%' === 0) ? index + 1 : index));
  877. type = m[2];
  878. arg = args.shift();
  879. arg = inspector(arg, type);
  880. parts.push(arg);
  881. }
  882. template = template.substr(index + match.length);
  883. }
  884. parts.push(template);
  885. return parts.join('');
  886. }
  887. return {
  888. printf: printf,
  889. Console: Console
  890. };
  891. })();
  892. Evidence.UI = UI;
  893. var defaultLoader = new TestLoader();
  894. Evidence.defaultLoader = defaultLoader;
  895. global.Evidence = Evidence;
  896. if (global.location) {
  897. global.onload = function() {
  898. if (typeof originalOnload === 'function') {
  899. originalOnload.call(global);
  900. }
  901. AutoRunner.run();
  902. };
  903. } else if (global.arguments) {
  904. var runtime = java.lang.Runtime.getRuntime();
  905. var thread = new java.lang.Thread(function() {
  906. AutoRunner.run();
  907. });
  908. runtime.addShutdownHook(thread);
  909. }
  910. })(this);