mocha_rails 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -57,6 +57,10 @@ module.exports = function(type){
57
57
  };
58
58
  }); // module: browser/debug.js
59
59
 
60
+ require.register("browser/diff.js", function(module, exports, require){
61
+
62
+ }); // module: browser/diff.js
63
+
60
64
  require.register("browser/events.js", function(module, exports, require){
61
65
 
62
66
  /**
@@ -513,6 +517,11 @@ module.exports = function(suite){
513
517
 
514
518
  suite.on('pre-require', function(context){
515
519
 
520
+ // noop variants
521
+
522
+ context.xdescribe = function(){};
523
+ context.xit = function(){};
524
+
516
525
  /**
517
526
  * Execute before running tests.
518
527
  */
@@ -845,11 +854,27 @@ require.register("mocha.js", function(module, exports, require){
845
854
  * MIT Licensed
846
855
  */
847
856
 
857
+ /**
858
+ * Module dependencies.
859
+ */
860
+
861
+ var path = require('browser/path');
862
+
863
+ /**
864
+ * Expose `Mocha`.
865
+ */
866
+
867
+ exports = module.exports = Mocha;
868
+
848
869
  /**
849
870
  * Library version.
850
871
  */
851
872
 
852
- exports.version = '0.12.0';
873
+ exports.version = '1.0.0';
874
+
875
+ /**
876
+ * Expose internals.
877
+ */
853
878
 
854
879
  exports.utils = require('./utils');
855
880
  exports.interfaces = require('./interfaces');
@@ -861,6 +886,144 @@ exports.Suite = require('./suite');
861
886
  exports.Hook = require('./hook');
862
887
  exports.Test = require('./test');
863
888
 
889
+ /**
890
+ * Return image `name` path.
891
+ *
892
+ * @param {String} name
893
+ * @return {String}
894
+ * @api private
895
+ */
896
+
897
+ function image(name) {
898
+ return __dirname + '/../images/' + name + '.png';
899
+ }
900
+
901
+ /**
902
+ * Setup mocha with `options`.
903
+ *
904
+ * Options:
905
+ *
906
+ * - `ui` name "bdd", "tdd", "exports" etc
907
+ * - `reporter` reporter instance, defaults to `mocha.reporters.Dot`
908
+ * - `globals` array of accepted globals
909
+ * - `timeout` timeout in milliseconds
910
+ * - `ignoreLeaks` ignore global leaks
911
+ *
912
+ * @param {Object} options
913
+ * @api public
914
+ */
915
+
916
+ function Mocha(options) {
917
+ options = options || {};
918
+ this.files = [];
919
+ this.options = options;
920
+ this.suite = new exports.Suite('', new exports.Context);
921
+ this.ui(options.ui);
922
+ this.reporter(options.reporter);
923
+ if (options.timeout) this.suite.timeout(options.timeout);
924
+ }
925
+
926
+ /**
927
+ * Add test `file`.
928
+ *
929
+ * @param {String} file
930
+ * @api public
931
+ */
932
+
933
+ Mocha.prototype.addFile = function(file){
934
+ this.files.push(file);
935
+ return this;
936
+ };
937
+
938
+ /**
939
+ * Set reporter to `name`, defaults to "dot".
940
+ *
941
+ * @param {String} name
942
+ * @api public
943
+ */
944
+
945
+ Mocha.prototype.reporter = function(name){
946
+ name = name || 'dot';
947
+ this._reporter = require('./reporters/' + name);
948
+ if (!this._reporter) throw new Error('invalid reporter "' + name + '"');
949
+ return this;
950
+ };
951
+
952
+ /**
953
+ * Set test UI `name`, defaults to "bdd".
954
+ *
955
+ * @param {String} bdd
956
+ * @api public
957
+ */
958
+
959
+ Mocha.prototype.ui = function(name){
960
+ name = name || 'bdd';
961
+ this._ui = exports.interfaces[name];
962
+ if (!this._ui) throw new Error('invalid interface "' + name + '"');
963
+ this._ui = this._ui(this.suite);
964
+ return this;
965
+ };
966
+
967
+ /**
968
+ * Load registered files.
969
+ *
970
+ * @api private
971
+ */
972
+
973
+ Mocha.prototype.loadFiles = function(){
974
+ var suite = this.suite;
975
+ this.files.forEach(function(file){
976
+ file = path.resolve(file);
977
+ suite.emit('pre-require', global, file);
978
+ suite.emit('require', require(file), file);
979
+ suite.emit('post-require', global, file);
980
+ });
981
+ };
982
+
983
+ /**
984
+ * Enable growl support.
985
+ *
986
+ * @api private
987
+ */
988
+
989
+ Mocha.prototype.growl = function(runner, reporter) {
990
+ var notify = require('growl');
991
+
992
+ runner.on('end', function(){
993
+ var stats = reporter.stats;
994
+ if (stats.failures) {
995
+ var msg = stats.failures + ' of ' + runner.total + ' tests failed';
996
+ notify(msg, { title: 'Failed', image: image('fail') });
997
+ } else {
998
+ notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', {
999
+ title: 'Passed'
1000
+ , image: image('pass')
1001
+ });
1002
+ }
1003
+ });
1004
+ };
1005
+
1006
+ /**
1007
+ * Run tests and invoke `fn()` when complete.
1008
+ *
1009
+ * @param {Function} fn
1010
+ * @return {Runner}
1011
+ * @api public
1012
+ */
1013
+
1014
+ Mocha.prototype.run = function(fn){
1015
+ this.loadFiles();
1016
+ var suite = this.suite;
1017
+ var options = this.options;
1018
+ var runner = new exports.Runner(suite);
1019
+ var reporter = new this._reporter(runner);
1020
+ runner.ignoreLeaks = options.ignoreLeaks;
1021
+ if (options.grep) runner.grep(options.grep);
1022
+ if (options.globals) runner.globals(options.globals);
1023
+ if (options.growl) this.growl(runner, reporter);
1024
+ return runner.run(fn);
1025
+ };
1026
+
864
1027
  }); // module: mocha.js
865
1028
 
866
1029
  require.register("reporters/base.js", function(module, exports, require){
@@ -869,7 +1032,8 @@ require.register("reporters/base.js", function(module, exports, require){
869
1032
  * Module dependencies.
870
1033
  */
871
1034
 
872
- var tty = require('browser/tty');
1035
+ var tty = require('browser/tty')
1036
+ , diff = require('browser/diff');
873
1037
 
874
1038
  /**
875
1039
  * Check if both stdio streams are associated with a tty.
@@ -910,6 +1074,9 @@ exports.colors = {
910
1074
  , 'slow': 31
911
1075
  , 'green': 32
912
1076
  , 'light': 90
1077
+ , 'diff gutter': 90
1078
+ , 'diff added': 42
1079
+ , 'diff removed': 41
913
1080
  };
914
1081
 
915
1082
  /**
@@ -997,10 +1164,44 @@ exports.list = function(failures){
997
1164
  , message = err.message || ''
998
1165
  , stack = err.stack || message
999
1166
  , index = stack.indexOf(message) + message.length
1000
- , msg = stack.slice(0, index);
1167
+ , msg = stack.slice(0, index)
1168
+ , actual = err.actual
1169
+ , expected = err.expected;
1170
+
1171
+ // actual / expected diff
1172
+ if ('string' == typeof actual && 'string' == typeof expected) {
1173
+ var len = Math.max(actual.length, expected.length);
1174
+
1175
+ if (len < 20) msg = errorDiff(err, 'Chars');
1176
+ else msg = errorDiff(err, 'Words');
1177
+
1178
+ // linenos
1179
+ var lines = msg.split('\n');
1180
+ if (lines.length > 4) {
1181
+ var width = String(lines.length).length;
1182
+ msg = lines.map(function(str, i){
1183
+ return pad(++i, width) + ' |' + ' ' + str;
1184
+ }).join('\n');
1185
+ }
1186
+
1187
+ // legend
1188
+ msg = '\n'
1189
+ + color('diff removed', 'actual')
1190
+ + ' '
1191
+ + color('diff added', 'expected')
1192
+ + '\n\n'
1193
+ + msg
1194
+ + '\n';
1195
+
1196
+ // indent
1197
+ msg = msg.replace(/^/gm, ' ');
1198
+
1199
+ fmt = color('error title', ' %s) %s:\n%s')
1200
+ + color('error stack', '\n%s\n');
1201
+ }
1001
1202
 
1002
1203
  // indent stack trace without msg
1003
- stack = stack.slice(index + 1)
1204
+ stack = stack.slice(index ? index + 1 : index)
1004
1205
  .replace(/^/gm, ' ');
1005
1206
 
1006
1207
  console.error(fmt, (i + 1), test.fullTitle(), msg, stack);
@@ -1101,6 +1302,51 @@ Base.prototype.epilogue = function(){
1101
1302
  console.log();
1102
1303
  };
1103
1304
 
1305
+ /**
1306
+ * Pad the given `str` to `len`.
1307
+ *
1308
+ * @param {String} str
1309
+ * @param {String} len
1310
+ * @return {String}
1311
+ * @api private
1312
+ */
1313
+
1314
+ function pad(str, len) {
1315
+ str = String(str);
1316
+ return Array(len - str.length + 1).join(' ') + str;
1317
+ }
1318
+
1319
+ /**
1320
+ * Return a character diff for `err`.
1321
+ *
1322
+ * @param {Error} err
1323
+ * @return {String}
1324
+ * @api private
1325
+ */
1326
+
1327
+ function errorDiff(err, type) {
1328
+ return diff['diff' + type](err.actual, err.expected).map(function(str){
1329
+ if (str.added) return colorLines('diff added', str.value);
1330
+ if (str.removed) return colorLines('diff removed', str.value);
1331
+ return str.value;
1332
+ }).join('');
1333
+ }
1334
+
1335
+ /**
1336
+ * Color lines for `str`, using the color `name`.
1337
+ *
1338
+ * @param {String} name
1339
+ * @param {String} str
1340
+ * @return {String}
1341
+ * @api private
1342
+ */
1343
+
1344
+ function colorLines(name, str) {
1345
+ return str.split('\n').map(function(str){
1346
+ return color(name, str);
1347
+ }).join('\n');
1348
+ }
1349
+
1104
1350
  }); // module: reporters/base.js
1105
1351
 
1106
1352
  require.register("reporters/doc.js", function(module, exports, require){
@@ -1247,6 +1493,53 @@ Dot.prototype.constructor = Dot;
1247
1493
 
1248
1494
  }); // module: reporters/dot.js
1249
1495
 
1496
+ require.register("reporters/html-cov.js", function(module, exports, require){
1497
+
1498
+ /**
1499
+ * Module dependencies.
1500
+ */
1501
+
1502
+ var JSONCov = require('./json-cov')
1503
+ , fs = require('browser/fs');
1504
+
1505
+ /**
1506
+ * Expose `HTMLCov`.
1507
+ */
1508
+
1509
+ exports = module.exports = HTMLCov;
1510
+
1511
+ /**
1512
+ * Initialize a new `JsCoverage` reporter.
1513
+ *
1514
+ * @param {Runner} runner
1515
+ * @api public
1516
+ */
1517
+
1518
+ function HTMLCov(runner) {
1519
+ var jade = require('jade')
1520
+ , file = __dirname + '/templates/coverage.jade'
1521
+ , str = fs.readFileSync(file, 'utf8')
1522
+ , fn = jade.compile(str, { filename: file })
1523
+ , self = this;
1524
+
1525
+ JSONCov.call(this, runner, false);
1526
+
1527
+ runner.on('end', function(){
1528
+ process.stdout.write(fn({
1529
+ cov: self.cov
1530
+ , coverageClass: coverageClass
1531
+ }));
1532
+ });
1533
+ }
1534
+
1535
+ function coverageClass(n) {
1536
+ if (n >= 75) return 'high';
1537
+ if (n >= 50) return 'medium';
1538
+ if (n >= 25) return 'low';
1539
+ return 'terrible';
1540
+ }
1541
+ }); // module: reporters/html-cov.js
1542
+
1250
1543
  require.register("reporters/html.js", function(module, exports, require){
1251
1544
 
1252
1545
  /**
@@ -1285,15 +1578,17 @@ var statsTemplate = '<ul id="stats">'
1285
1578
  function HTML(runner) {
1286
1579
  Base.call(this, runner);
1287
1580
 
1288
- // TODO: clean up
1289
-
1290
1581
  var self = this
1291
1582
  , stats = this.stats
1292
1583
  , total = runner.total
1293
- , root = $('#mocha')
1584
+ , root = document.getElementById('mocha')
1585
+ , stat = fragment(statsTemplate)
1586
+ , items = stat.getElementsByTagName('li')
1587
+ , passes = items[1].getElementsByTagName('em')[0]
1588
+ , failures = items[2].getElementsByTagName('em')[0]
1589
+ , duration = items[3].getElementsByTagName('em')[0]
1590
+ , canvas = stat.getElementsByTagName('canvas')[0]
1294
1591
  , stack = [root]
1295
- , stat = $(statsTemplate).appendTo(root)
1296
- , canvas = stat.find('canvas').get(0)
1297
1592
  , progress
1298
1593
  , ctx
1299
1594
 
@@ -1302,7 +1597,9 @@ function HTML(runner) {
1302
1597
  progress = new Progress;
1303
1598
  }
1304
1599
 
1305
- if (!root.length) return error('#mocha div missing, add it to your document');
1600
+ if (!root) return error('#mocha div missing, add it to your document');
1601
+
1602
+ root.appendChild(stat);
1306
1603
 
1307
1604
  if (progress) progress.size(40);
1308
1605
 
@@ -1310,12 +1607,12 @@ function HTML(runner) {
1310
1607
  if (suite.root) return;
1311
1608
 
1312
1609
  // suite
1313
- var el = $('<div class="suite"><h1>' + suite.title + '</h1></div>');
1610
+ var el = fragment('<div class="suite"><h1>%s</h1></div>', suite.title);
1314
1611
 
1315
1612
  // container
1316
- stack[0].append(el);
1317
- stack.unshift($('<div>'));
1318
- el.append(stack[0]);
1613
+ stack[0].appendChild(el);
1614
+ stack.unshift(document.createElement('div'));
1615
+ el.appendChild(stack[0]);
1319
1616
  });
1320
1617
 
1321
1618
  runner.on('suite end', function(suite){
@@ -1330,48 +1627,58 @@ function HTML(runner) {
1330
1627
  runner.on('test end', function(test){
1331
1628
  // TODO: add to stats
1332
1629
  var percent = stats.tests / total * 100 | 0;
1333
-
1334
- if (progress) {
1335
- progress.update(percent).draw(ctx);
1336
- }
1630
+ if (progress) progress.update(percent).draw(ctx);
1337
1631
 
1338
1632
  // update stats
1339
1633
  var ms = new Date - stats.start;
1340
- stat.find('.passes em').text(stats.passes);
1341
- stat.find('.failures em').text(stats.failures);
1342
- stat.find('.duration em').text((ms / 1000).toFixed(2));
1634
+ text(passes, stats.passes);
1635
+ text(failures, stats.failures);
1636
+ text(duration, (ms / 1000).toFixed(2));
1343
1637
 
1344
1638
  // test
1345
- if (test.passed) {
1346
- var el = $('<div class="test pass"><h2>' + escape(test.title) + '</h2></div>')
1639
+ if ('passed' == test.state) {
1640
+ var el = fragment('<div class="test pass"><h2>%e</h2></div>', test.title);
1347
1641
  } else if (test.pending) {
1348
- var el = $('<div class="test pass pending"><h2>' + escape(test.title) + '</h2></div>')
1642
+ var el = fragment('<div class="test pass pending"><h2>%e</h2></div>', test.title);
1349
1643
  } else {
1350
- var el = $('<div class="test fail"><h2>' + escape(test.title) + '</h2></div>');
1351
- var str = test.err.stack || test.err;
1644
+ var el = fragment('<div class="test fail"><h2>%e</h2></div>', test.title);
1645
+ var str = test.err.stack || test.err.toString();
1646
+
1647
+ // FF / Opera do not add the message
1648
+ if (!~str.indexOf(test.err.message)) {
1649
+ str = test.err.message + '\n' + str;
1650
+ }
1352
1651
 
1353
1652
  // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we
1354
1653
  // check for the result of the stringifying.
1355
1654
  if ('[object Error]' == str) str = test.err.message;
1356
1655
 
1357
- $('<pre class="error">' + escape(str) + '</pre>').appendTo(el);
1656
+ // Safari doesn't give you a stack. Let's at least provide a source line.
1657
+ if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) {
1658
+ str += "\n(" + test.err.sourceURL + ":" + test.err.line + ")";
1659
+ }
1660
+
1661
+ el.appendChild(fragment('<pre class="error">%e</pre>', str));
1358
1662
  }
1359
1663
 
1360
1664
  // toggle code
1361
- el.find('h2').toggle(function(){
1362
- pre && pre.slideDown('fast');
1363
- }, function(){
1364
- pre && pre.slideUp('fast');
1665
+ var h2 = el.getElementsByTagName('h2')[0];
1666
+
1667
+ on(h2, 'click', function(){
1668
+ pre.style.display = 'none' == pre.style.display
1669
+ ? 'block'
1670
+ : 'none';
1365
1671
  });
1366
1672
 
1367
1673
  // code
1368
1674
  // TODO: defer
1369
1675
  if (!test.pending) {
1370
- var code = escape(clean(test.fn.toString()));
1371
- var pre = $('<pre><code>' + code + '</code></pre>');
1372
- pre.appendTo(el).hide();
1676
+ var pre = fragment('<pre><code>%e</code></pre>', clean(test.fn.toString()));
1677
+ el.appendChild(pre);
1678
+ pre.style.display = 'none';
1373
1679
  }
1374
- stack[0].append(el);
1680
+
1681
+ stack[0].appendChild(el);
1375
1682
  });
1376
1683
  }
1377
1684
 
@@ -1380,7 +1687,50 @@ function HTML(runner) {
1380
1687
  */
1381
1688
 
1382
1689
  function error(msg) {
1383
- $('<div id="error">' + msg + '</div>').appendTo('body');
1690
+ document.body.appendChild(fragment('<div id="error">%s</div>', msg));
1691
+ }
1692
+
1693
+ /**
1694
+ * Return a DOM fragment from `html`.
1695
+ */
1696
+
1697
+ function fragment(html) {
1698
+ var args = arguments
1699
+ , div = document.createElement('div')
1700
+ , i = 1;
1701
+
1702
+ div.innerHTML = html.replace(/%([se])/g, function(_, type){
1703
+ switch (type) {
1704
+ case 's': return String(args[i++]);
1705
+ case 'e': return escape(args[i++]);
1706
+ }
1707
+ });
1708
+
1709
+ return div.firstChild;
1710
+ }
1711
+
1712
+ /**
1713
+ * Set `el` text to `str`.
1714
+ */
1715
+
1716
+ function text(el, str) {
1717
+ if (el.textContent) {
1718
+ el.textContent = str;
1719
+ } else {
1720
+ el.innerText = str;
1721
+ }
1722
+ }
1723
+
1724
+ /**
1725
+ * Listen on `event` with callback `fn`.
1726
+ */
1727
+
1728
+ function on(el, event, fn) {
1729
+ if (el.addEventListener) {
1730
+ el.addEventListener(event, fn, false);
1731
+ } else {
1732
+ el.attachEvent('on' + event, fn);
1733
+ }
1384
1734
  }
1385
1735
 
1386
1736
  /**
@@ -1414,14 +1764,171 @@ exports.TAP = require('./tap');
1414
1764
  exports.JSON = require('./json');
1415
1765
  exports.HTML = require('./html');
1416
1766
  exports.List = require('./list');
1767
+ exports.Min = require('./min');
1417
1768
  exports.Spec = require('./spec');
1418
1769
  exports.Progress = require('./progress');
1419
1770
  exports.Landing = require('./landing');
1771
+ exports.JSONCov = require('./json-cov');
1772
+ exports.HTMLCov = require('./html-cov');
1420
1773
  exports.JSONStream = require('./json-stream');
1421
1774
  exports.XUnit = require('./xunit')
1775
+ exports.Teamcity = require('./teamcity')
1422
1776
 
1423
1777
  }); // module: reporters/index.js
1424
1778
 
1779
+ require.register("reporters/json-cov.js", function(module, exports, require){
1780
+
1781
+ /**
1782
+ * Module dependencies.
1783
+ */
1784
+
1785
+ var Base = require('./base');
1786
+
1787
+ /**
1788
+ * Expose `JSONCov`.
1789
+ */
1790
+
1791
+ exports = module.exports = JSONCov;
1792
+
1793
+ /**
1794
+ * Initialize a new `JsCoverage` reporter.
1795
+ *
1796
+ * @param {Runner} runner
1797
+ * @param {Boolean} output
1798
+ * @api public
1799
+ */
1800
+
1801
+ function JSONCov(runner, output) {
1802
+ var self = this
1803
+ , output = 1 == arguments.length ? true : output;
1804
+
1805
+ Base.call(this, runner);
1806
+
1807
+ var tests = []
1808
+ , failures = []
1809
+ , passes = [];
1810
+
1811
+ runner.on('test end', function(test){
1812
+ tests.push(test);
1813
+ });
1814
+
1815
+ runner.on('pass', function(test){
1816
+ passes.push(test);
1817
+ });
1818
+
1819
+ runner.on('fail', function(test){
1820
+ failures.push(test);
1821
+ });
1822
+
1823
+ runner.on('end', function(){
1824
+ var cov = global._$jscoverage || {};
1825
+ var result = self.cov = map(cov);
1826
+ result.stats = self.stats;
1827
+ result.tests = tests.map(clean);
1828
+ result.failures = failures.map(clean);
1829
+ result.passes = passes.map(clean);
1830
+ if (!output) return;
1831
+ process.stdout.write(JSON.stringify(result, null, 2 ));
1832
+ });
1833
+ }
1834
+
1835
+ /**
1836
+ * Map jscoverage data to a JSON structure
1837
+ * suitable for reporting.
1838
+ *
1839
+ * @param {Object} cov
1840
+ * @return {Object}
1841
+ * @api private
1842
+ */
1843
+
1844
+ function map(cov) {
1845
+ var ret = {
1846
+ instrumentation: 'node-jscoverage'
1847
+ , sloc: 0
1848
+ , hits: 0
1849
+ , misses: 0
1850
+ , coverage: 0
1851
+ , files: []
1852
+ };
1853
+
1854
+ for (var filename in cov) {
1855
+ var data = coverage(filename, cov[filename]);
1856
+ ret.files.push(data);
1857
+ ret.hits += data.hits;
1858
+ ret.misses += data.misses;
1859
+ ret.sloc += data.sloc;
1860
+ }
1861
+
1862
+ if (ret.sloc > 0) {
1863
+ ret.coverage = (ret.hits / ret.sloc) * 100;
1864
+ }
1865
+
1866
+ return ret;
1867
+ };
1868
+
1869
+ /**
1870
+ * Map jscoverage data for a single source file
1871
+ * to a JSON structure suitable for reporting.
1872
+ *
1873
+ * @param {String} filename name of the source file
1874
+ * @param {Object} data jscoverage coverage data
1875
+ * @return {Object}
1876
+ * @api private
1877
+ */
1878
+
1879
+ function coverage(filename, data) {
1880
+ var ret = {
1881
+ filename: filename,
1882
+ coverage: 0,
1883
+ hits: 0,
1884
+ misses: 0,
1885
+ sloc: 0,
1886
+ source: {}
1887
+ };
1888
+
1889
+ data.source.forEach(function(line, num){
1890
+ num++;
1891
+
1892
+ if (data[num] === 0) {
1893
+ ret.misses++;
1894
+ ret.sloc++;
1895
+ } else if (data[num] !== undefined) {
1896
+ ret.hits++;
1897
+ ret.sloc++;
1898
+ }
1899
+
1900
+ ret.source[num] = {
1901
+ source: line
1902
+ , coverage: data[num] === undefined
1903
+ ? ''
1904
+ : data[num]
1905
+ };
1906
+ });
1907
+
1908
+ ret.coverage = ret.hits / ret.sloc * 100;
1909
+
1910
+ return ret;
1911
+ }
1912
+
1913
+ /**
1914
+ * Return a plain-object representation of `test`
1915
+ * free of cyclic properties etc.
1916
+ *
1917
+ * @param {Object} test
1918
+ * @return {Object}
1919
+ * @api private
1920
+ */
1921
+
1922
+ function clean(test) {
1923
+ return {
1924
+ title: test.title
1925
+ , fullTitle: test.fullTitle()
1926
+ , duration: test.duration
1927
+ }
1928
+ }
1929
+
1930
+ }); // module: reporters/json-cov.js
1931
+
1425
1932
  require.register("reporters/json-stream.js", function(module, exports, require){
1426
1933
 
1427
1934
  /**
@@ -1537,7 +2044,7 @@ function JSONReporter(runner) {
1537
2044
  , passes: passes.map(clean)
1538
2045
  };
1539
2046
 
1540
- process.stdout.write(JSON.stringify(obj));
2047
+ process.stdout.write(JSON.stringify(obj, null, 2));
1541
2048
  });
1542
2049
  }
1543
2050
 
@@ -1629,7 +2136,7 @@ function Landing(runner) {
1629
2136
  : crashed;
1630
2137
 
1631
2138
  // show the crash
1632
- if (test.failed) {
2139
+ if ('failed' == test.state) {
1633
2140
  plane = color('plane crash', '✈');
1634
2141
  crashed = col;
1635
2142
  }
@@ -1731,6 +2238,162 @@ List.prototype.constructor = List;
1731
2238
 
1732
2239
  }); // module: reporters/list.js
1733
2240
 
2241
+ require.register("reporters/markdown.js", function(module, exports, require){
2242
+
2243
+ /**
2244
+ * Module dependencies.
2245
+ */
2246
+
2247
+ var Base = require('./base')
2248
+ , utils = require('../utils');
2249
+
2250
+ /**
2251
+ * Expose `Markdown`.
2252
+ */
2253
+
2254
+ exports = module.exports = Markdown;
2255
+
2256
+ /**
2257
+ * Initialize a new `Markdown` reporter.
2258
+ *
2259
+ * @param {Runner} runner
2260
+ * @api public
2261
+ */
2262
+
2263
+ function Markdown(runner) {
2264
+ Base.call(this, runner);
2265
+
2266
+ var self = this
2267
+ , stats = this.stats
2268
+ , total = runner.total
2269
+ , level = 0
2270
+ , buf = '';
2271
+
2272
+ function title(str) {
2273
+ return Array(level).join('#') + ' ' + str;
2274
+ }
2275
+
2276
+ function indent() {
2277
+ return Array(level).join(' ');
2278
+ }
2279
+
2280
+ function mapTOC(suite, obj) {
2281
+ var ret = obj;
2282
+ obj = obj[suite.title] = obj[suite.title] || { suite: suite };
2283
+ suite.suites.forEach(function(suite){
2284
+ mapTOC(suite, obj);
2285
+ });
2286
+ return ret;
2287
+ }
2288
+
2289
+ function stringifyTOC(obj, level) {
2290
+ ++level;
2291
+ var buf = '';
2292
+ var link;
2293
+ for (var key in obj) {
2294
+ if ('suite' == key) continue;
2295
+ if (key) link = ' - [' + key + '](#' + utils.slug(obj[key].suite.fullTitle()) + ')\n';
2296
+ if (key) buf += Array(level).join(' ') + link;
2297
+ buf += stringifyTOC(obj[key], level);
2298
+ }
2299
+ --level;
2300
+ return buf;
2301
+ }
2302
+
2303
+ function generateTOC(suite) {
2304
+ var obj = mapTOC(suite, {});
2305
+ return stringifyTOC(obj, 0);
2306
+ }
2307
+
2308
+ generateTOC(runner.suite);
2309
+
2310
+ runner.on('suite', function(suite){
2311
+ ++level;
2312
+ var slug = utils.slug(suite.fullTitle());
2313
+ buf += '<a name="' + slug + '" />' + '\n';
2314
+ buf += title(suite.title) + '\n';
2315
+ });
2316
+
2317
+ runner.on('suite end', function(suite){
2318
+ --level;
2319
+ });
2320
+
2321
+ runner.on('pass', function(test){
2322
+ var code = clean(test.fn.toString());
2323
+ buf += test.title + '.\n';
2324
+ buf += '\n```js';
2325
+ buf += code + '\n';
2326
+ buf += '```\n\n';
2327
+ });
2328
+
2329
+ runner.on('end', function(){
2330
+ process.stdout.write('# TOC\n');
2331
+ process.stdout.write(generateTOC(runner.suite));
2332
+ process.stdout.write(buf);
2333
+ });
2334
+ }
2335
+
2336
+ /**
2337
+ * Strip the function definition from `str`,
2338
+ * and re-indent for pre whitespace.
2339
+ */
2340
+
2341
+ function clean(str) {
2342
+ str = str
2343
+ .replace(/^function *\(.*\) *{/, '')
2344
+ .replace(/\s+\}$/, '');
2345
+
2346
+ var spaces = str.match(/^\n?( *)/)[1].length
2347
+ , re = new RegExp('^ {' + spaces + '}', 'gm');
2348
+
2349
+ str = str.replace(re, '');
2350
+
2351
+ return str;
2352
+ }
2353
+ }); // module: reporters/markdown.js
2354
+
2355
+ require.register("reporters/min.js", function(module, exports, require){
2356
+ /**
2357
+ * Module dependencies.
2358
+ */
2359
+
2360
+ var Base = require('./base');
2361
+
2362
+ /**
2363
+ * Expose `Min`.
2364
+ */
2365
+
2366
+ exports = module.exports = Min;
2367
+
2368
+ /**
2369
+ * Initialize a new `Min` minimal test reporter (best used with --watch).
2370
+ *
2371
+ * @param {Runner} runner
2372
+ * @api public
2373
+ */
2374
+
2375
+ function Min(runner) {
2376
+ Base.call(this, runner);
2377
+
2378
+ runner.on('start', function(){
2379
+ // clear screen
2380
+ process.stdout.write('\033[2J');
2381
+ // set cursor position
2382
+ process.stdout.write('\033[1;3H');
2383
+ });
2384
+
2385
+ runner.on('end', this.epilogue.bind(this));
2386
+ }
2387
+
2388
+ /**
2389
+ * Inherit from `Base.prototype`.
2390
+ */
2391
+
2392
+ Min.prototype = new Base;
2393
+ Min.prototype.constructor = Min;
2394
+
2395
+ }); // module: reporters/min.js
2396
+
1734
2397
  require.register("reporters/progress.js", function(module, exports, require){
1735
2398
 
1736
2399
  /**
@@ -2109,7 +2772,7 @@ function test(test) {
2109
2772
  , time: test.duration / 1000
2110
2773
  };
2111
2774
 
2112
- if (test.failed) {
2775
+ if ('failed' == test.state) {
2113
2776
  var err = test.err;
2114
2777
  attrs.message = escape(err.message);
2115
2778
  console.log(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(err.stack))));
@@ -2436,7 +3099,7 @@ Runner.prototype.checkGlobals = function(test){
2436
3099
 
2437
3100
  Runner.prototype.fail = function(test, err){
2438
3101
  ++this.failures;
2439
- test.failed = true;
3102
+ test.state = 'failed';
2440
3103
  this.emit('fail', test, err);
2441
3104
  };
2442
3105
 
@@ -2643,7 +3306,7 @@ Runner.prototype.runTests = function(suite, fn){
2643
3306
  return self.hookUp('afterEach', next);
2644
3307
  }
2645
3308
 
2646
- test.passed = true;
3309
+ test.state = 'passed';
2647
3310
  self.emit('pass', test);
2648
3311
  self.emit('test end', test);
2649
3312
  self.hookUp('afterEach', next);
@@ -2700,7 +3363,7 @@ Runner.prototype.runSuite = function(suite, fn){
2700
3363
  Runner.prototype.uncaught = function(err){
2701
3364
  debug('uncaught exception');
2702
3365
  var runnable = this.currentRunnable;
2703
- if (runnable.failed) return;
3366
+ if ('failed' == runnable.state) return;
2704
3367
  runnable.clearTimeout();
2705
3368
  err.uncaught = true;
2706
3369
  this.fail(runnable, err);
@@ -2834,6 +3497,7 @@ Suite.prototype.constructor = Suite;
2834
3497
  Suite.prototype.clone = function(){
2835
3498
  var suite = new Suite(this.title);
2836
3499
  debug('clone');
3500
+ suite.ctx = this.ctx;
2837
3501
  suite.timeout(this.timeout());
2838
3502
  suite.bail(this.bail());
2839
3503
  return suite;
@@ -3178,9 +3842,9 @@ exports.keys = Object.keys || function(obj) {
3178
3842
  var keys = []
3179
3843
  , has = Object.prototype.hasOwnProperty // for `window` on <=IE8
3180
3844
 
3181
- for (var i in obj) {
3182
- if (has.call(obj, i)) {
3183
- keys.push(i);
3845
+ for (var key in obj) {
3846
+ if (has.call(obj, key)) {
3847
+ keys.push(key);
3184
3848
  }
3185
3849
  }
3186
3850
 
@@ -3218,7 +3882,7 @@ function ignored(path){
3218
3882
  * Lookup files in the given `dir`.
3219
3883
  *
3220
3884
  * @return {Array}
3221
- * @api public
3885
+ * @api private
3222
3886
  */
3223
3887
 
3224
3888
  exports.files = function(dir, ret){
@@ -3237,6 +3901,20 @@ exports.files = function(dir, ret){
3237
3901
 
3238
3902
  return ret;
3239
3903
  };
3904
+
3905
+ /**
3906
+ * Compute a slug from the given `str`.
3907
+ *
3908
+ * @param {String} str
3909
+ * @return {String}
3910
+ */
3911
+
3912
+ exports.slug = function(str){
3913
+ return str
3914
+ .toLowerCase()
3915
+ .replace(/ +/g, '-')
3916
+ .replace(/[^-\w]/g, '');
3917
+ };
3240
3918
  }); // module: utils.js
3241
3919
 
3242
3920
  /**
@@ -3310,13 +3988,7 @@ window.mocha = require('mocha');
3310
3988
  ;(function(){
3311
3989
  var suite = new mocha.Suite('', new mocha.Context)
3312
3990
  , utils = mocha.utils
3313
- , Reporter = mocha.reporters.HTML
3314
-
3315
- $(function(){
3316
- $('code').each(function(){
3317
- $(this).html(highlight($(this).text()));
3318
- });
3319
- });
3991
+ , options = {}
3320
3992
 
3321
3993
  /**
3322
3994
  * Highlight the given string of `js`.
@@ -3327,13 +3999,24 @@ window.mocha = require('mocha');
3327
3999
  .replace(/</g, '&lt;')
3328
4000
  .replace(/>/g, '&gt;')
3329
4001
  .replace(/\/\/(.*)/gm, '<span class="comment">//$1</span>')
3330
- .replace(/('.*')/gm, '<span class="string">$1</span>')
4002
+ .replace(/('.*?')/gm, '<span class="string">$1</span>')
3331
4003
  .replace(/(\d+\.\d+)/gm, '<span class="number">$1</span>')
3332
4004
  .replace(/(\d+)/gm, '<span class="number">$1</span>')
3333
4005
  .replace(/\bnew *(\w+)/gm, '<span class="keyword">new</span> <span class="init">$1</span>')
3334
4006
  .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '<span class="keyword">$1</span>')
3335
4007
  }
3336
4008
 
4009
+ /**
4010
+ * Highlight code contents.
4011
+ */
4012
+
4013
+ function highlightCode() {
4014
+ var code = document.getElementsByTagName('code');
4015
+ for (var i = 0, len = code.length; i < len; ++i) {
4016
+ code[i].innerHTML = highlight(code[i].innerHTML);
4017
+ }
4018
+ }
4019
+
3337
4020
  /**
3338
4021
  * Parse the given `qs`.
3339
4022
  */
@@ -3350,12 +4033,16 @@ window.mocha = require('mocha');
3350
4033
  }
3351
4034
 
3352
4035
  /**
3353
- * Setup mocha with the give `ui` name.
4036
+ * Setup mocha with the given setting options.
3354
4037
  */
3355
4038
 
3356
- mocha.setup = function(ui){
3357
- ui = mocha.interfaces[ui];
4039
+ mocha.setup = function(opts){
4040
+ if ('string' === typeof opts) options.ui = opts;
4041
+ else options = opts;
4042
+
4043
+ ui = mocha.interfaces[options.ui];
3358
4044
  if (!ui) throw new Error('invalid mocha interface "' + ui + '"');
4045
+ if (options.timeout) suite.timeout(options.timeout);
3359
4046
  ui(suite);
3360
4047
  suite.emit('pre-require', window);
3361
4048
  };
@@ -3367,14 +4054,14 @@ window.mocha = require('mocha');
3367
4054
  mocha.run = function(){
3368
4055
  suite.emit('run');
3369
4056
  var runner = new mocha.Runner(suite);
4057
+ var Reporter = options.reporter || mocha.reporters.HTML;
3370
4058
  var reporter = new Reporter(runner);
3371
4059
  var query = parse(window.location.search || "");
3372
4060
  if (query.grep) runner.grep(new RegExp(query.grep));
3373
- runner.on('end', function(){
3374
- $('code').each(function(){
3375
- $(this).html(highlight($(this).text()));
3376
- });
3377
- });
4061
+ if (options.ignoreLeaks) runner.ignoreLeaks = true;
4062
+ if (options.globals) runner.globals(options.globals);
4063
+ runner.globals(['location']);
4064
+ runner.on('end', highlightCode);
3378
4065
  return runner.run();
3379
4066
  };
3380
4067
  })();