konacha 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,70 +1,37 @@
1
- (function () {
2
- window.Konacha = {
3
- dots:"",
1
+ window.Konacha = {
2
+ dots:"",
4
3
 
5
- Reporter:function (runner) {
6
- window.mocha.reporters.Base.call(this, runner);
4
+ Reporter:function (runner) {
5
+ window.mocha.reporters.Base.call(this, runner);
7
6
 
8
- runner.on('start', function () {
9
- Konacha.results = [];
10
- });
11
-
12
- runner.on('pass', function (test) {
13
- Konacha.dots += ".";
14
- Konacha.results.push({
15
- name: test.title,
16
- passed: true
17
- });
18
- });
7
+ runner.on('start', function () {
8
+ Konacha.results = [];
9
+ });
19
10
 
20
- runner.on('fail', function (test) {
21
- Konacha.dots += "F";
22
- Konacha.results.push({
23
- name: test.title,
24
- passed: false,
25
- message: test.err.message,
26
- trace: test.err.stack
27
- });
11
+ runner.on('pass', function (test) {
12
+ Konacha.dots += ".";
13
+ Konacha.results.push({
14
+ name:test.title,
15
+ passed:true
28
16
  });
29
-
30
- runner.on('end', function () {
31
- Konacha.done = true;
17
+ });
18
+
19
+ runner.on('fail', function (test) {
20
+ Konacha.dots += "F";
21
+ Konacha.results.push({
22
+ name:test.title,
23
+ passed:false,
24
+ message:test.err.message,
25
+ trace:test.err.stack
32
26
  });
33
- },
27
+ });
34
28
 
35
- getResults:function () {
36
- return JSON.stringify(Konacha.results);
37
- }
38
- };
29
+ runner.on('end', function () {
30
+ Konacha.done = true;
31
+ });
32
+ },
39
33
 
40
- var suite = new mocha.Suite
41
- , utils = mocha.utils
42
- , Reporter = Konacha.Reporter;
43
-
44
- function parse(qs) {
45
- return utils.reduce(qs.replace('?', '').split('&'), function(obj, pair){
46
- var i = pair.indexOf('=')
47
- , key = pair.slice(0, i)
48
- , val = pair.slice(++i);
49
-
50
- obj[key] = decodeURIComponent(val);
51
- return obj;
52
- }, {});
34
+ getResults:function () {
35
+ return JSON.stringify(Konacha.results);
53
36
  }
54
-
55
- mocha.setup = function (ui) {
56
- ui = mocha.interfaces[ui];
57
- if (!ui) throw new Error('invalid mocha interface "' + ui + '"');
58
- ui(suite);
59
- suite.emit('pre-require', window);
60
- };
61
-
62
- mocha.run = function () {
63
- suite.emit('run');
64
- var runner = new mocha.Runner(suite);
65
- var reporter = new Reporter(runner);
66
- var query = parse(window.location.search || "");
67
- if (query.grep) runner.grep(new RegExp(query.grep));
68
- return runner.run();
69
- };
70
- })();
37
+ };
@@ -0,0 +1,3 @@
1
+ window.Konacha = {
2
+ Reporter: mocha.reporters.HTML
3
+ };
@@ -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
  /**
@@ -386,6 +390,65 @@ exports.getWindowSize = function(){
386
390
  };
387
391
  }); // module: browser/tty.js
388
392
 
393
+ require.register("context.js", function(module, exports, require){
394
+
395
+ /**
396
+ * Expose `Context`.
397
+ */
398
+
399
+ module.exports = Context;
400
+
401
+ /**
402
+ * Initialize a new `Context`.
403
+ *
404
+ * @api private
405
+ */
406
+
407
+ function Context(){}
408
+
409
+ /**
410
+ * Set the context `Test` to `test`.
411
+ *
412
+ * @param {Test} test
413
+ * @return {Context}
414
+ * @api private
415
+ */
416
+
417
+ Context.prototype.test = function(test){
418
+ this._test = test;
419
+ return this;
420
+ };
421
+
422
+ /**
423
+ * Set test timeout `ms`.
424
+ *
425
+ * @param {Number} ms
426
+ * @return {Context} self
427
+ * @api private
428
+ */
429
+
430
+ Context.prototype.timeout = function(ms){
431
+ this._test.timeout(ms);
432
+ return this;
433
+ };
434
+
435
+ /**
436
+ * Inspect the context void of `._test`.
437
+ *
438
+ * @return {String}
439
+ * @api private
440
+ */
441
+
442
+ Context.prototype.inspect = function(){
443
+ return JSON.stringify(this, function(key, val){
444
+ return '_test' == key
445
+ ? undefined
446
+ : val;
447
+ }, 2);
448
+ };
449
+
450
+ }); // module: context.js
451
+
389
452
  require.register("hook.js", function(module, exports, require){
390
453
 
391
454
  /**
@@ -410,6 +473,7 @@ module.exports = Hook;
410
473
 
411
474
  function Hook(title, fn) {
412
475
  Runnable.call(this, title, fn);
476
+ this.type = 'hook';
413
477
  }
414
478
 
415
479
  /**
@@ -453,6 +517,11 @@ module.exports = function(suite){
453
517
 
454
518
  suite.on('pre-require', function(context){
455
519
 
520
+ // noop variants
521
+
522
+ context.xdescribe = function(){};
523
+ context.xit = function(){};
524
+
456
525
  /**
457
526
  * Execute before running tests.
458
527
  */
@@ -789,12 +858,13 @@ require.register("mocha.js", function(module, exports, require){
789
858
  * Library version.
790
859
  */
791
860
 
792
- exports.version = '0.12.0';
861
+ exports.version = '0.14.0';
793
862
 
794
863
  exports.utils = require('./utils');
795
864
  exports.interfaces = require('./interfaces');
796
865
  exports.reporters = require('./reporters');
797
866
  exports.Runnable = require('./runnable');
867
+ exports.Context = require('./context');
798
868
  exports.Runner = require('./runner');
799
869
  exports.Suite = require('./suite');
800
870
  exports.Hook = require('./hook');
@@ -808,7 +878,8 @@ require.register("reporters/base.js", function(module, exports, require){
808
878
  * Module dependencies.
809
879
  */
810
880
 
811
- var tty = require('browser/tty');
881
+ var tty = require('browser/tty')
882
+ , diff = require('browser/diff');
812
883
 
813
884
  /**
814
885
  * Check if both stdio streams are associated with a tty.
@@ -849,6 +920,9 @@ exports.colors = {
849
920
  , 'slow': 31
850
921
  , 'green': 32
851
922
  , 'light': 90
923
+ , 'diff gutter': 90
924
+ , 'diff added': 42
925
+ , 'diff removed': 41
852
926
  };
853
927
 
854
928
  /**
@@ -936,7 +1010,41 @@ exports.list = function(failures){
936
1010
  , message = err.message || ''
937
1011
  , stack = err.stack || message
938
1012
  , index = stack.indexOf(message) + message.length
939
- , msg = stack.slice(0, index);
1013
+ , msg = stack.slice(0, index)
1014
+ , actual = err.actual
1015
+ , expected = err.expected;
1016
+
1017
+ // actual / expected diff
1018
+ if ('string' == typeof actual && 'string' == typeof expected) {
1019
+ var len = Math.max(actual.length, expected.length);
1020
+
1021
+ if (len < 20) msg = errorDiff(err, 'Chars');
1022
+ else msg = errorDiff(err, 'Words');
1023
+
1024
+ // linenos
1025
+ var lines = msg.split('\n');
1026
+ if (lines.length > 4) {
1027
+ var width = String(lines.length).length;
1028
+ msg = lines.map(function(str, i){
1029
+ return pad(++i, width) + ' |' + ' ' + str;
1030
+ }).join('\n');
1031
+ }
1032
+
1033
+ // legend
1034
+ msg = '\n'
1035
+ + color('diff removed', 'actual')
1036
+ + ' '
1037
+ + color('diff added', 'expected')
1038
+ + '\n\n'
1039
+ + msg
1040
+ + '\n';
1041
+
1042
+ // indent
1043
+ msg = msg.replace(/^/gm, ' ');
1044
+
1045
+ fmt = color('error title', ' %s) %s:\n%s')
1046
+ + color('error stack', '\n%s\n');
1047
+ }
940
1048
 
941
1049
  // indent stack trace without msg
942
1050
  stack = stack.slice(index + 1)
@@ -1040,6 +1148,51 @@ Base.prototype.epilogue = function(){
1040
1148
  console.log();
1041
1149
  };
1042
1150
 
1151
+ /**
1152
+ * Pad the given `str` to `len`.
1153
+ *
1154
+ * @param {String} str
1155
+ * @param {String} len
1156
+ * @return {String}
1157
+ * @api private
1158
+ */
1159
+
1160
+ function pad(str, len) {
1161
+ str = String(str);
1162
+ return Array(len - str.length + 1).join(' ') + str;
1163
+ }
1164
+
1165
+ /**
1166
+ * Return a character diff for `err`.
1167
+ *
1168
+ * @param {Error} err
1169
+ * @return {String}
1170
+ * @api private
1171
+ */
1172
+
1173
+ function errorDiff(err, type) {
1174
+ return diff['diff' + type](err.actual, err.expected).map(function(str){
1175
+ if (str.added) return colorLines('diff added', str.value);
1176
+ if (str.removed) return colorLines('diff removed', str.value);
1177
+ return str.value;
1178
+ }).join('');
1179
+ }
1180
+
1181
+ /**
1182
+ * Color lines for `str`, using the color `name`.
1183
+ *
1184
+ * @param {String} name
1185
+ * @param {String} str
1186
+ * @return {String}
1187
+ * @api private
1188
+ */
1189
+
1190
+ function colorLines(name, str) {
1191
+ return str.split('\n').map(function(str){
1192
+ return color(name, str);
1193
+ }).join('\n');
1194
+ }
1195
+
1043
1196
  }); // module: reporters/base.js
1044
1197
 
1045
1198
  require.register("reporters/doc.js", function(module, exports, require){
@@ -1186,6 +1339,53 @@ Dot.prototype.constructor = Dot;
1186
1339
 
1187
1340
  }); // module: reporters/dot.js
1188
1341
 
1342
+ require.register("reporters/html-cov.js", function(module, exports, require){
1343
+
1344
+ /**
1345
+ * Module dependencies.
1346
+ */
1347
+
1348
+ var JSONCov = require('./json-cov')
1349
+ , fs = require('browser/fs');
1350
+
1351
+ /**
1352
+ * Expose `HTMLCov`.
1353
+ */
1354
+
1355
+ exports = module.exports = HTMLCov;
1356
+
1357
+ /**
1358
+ * Initialize a new `JsCoverage` reporter.
1359
+ *
1360
+ * @param {Runner} runner
1361
+ * @api public
1362
+ */
1363
+
1364
+ function HTMLCov(runner) {
1365
+ var jade = require('jade')
1366
+ , file = __dirname + '/templates/coverage.jade'
1367
+ , str = fs.readFileSync(file, 'utf8')
1368
+ , fn = jade.compile(str, { filename: file })
1369
+ , self = this;
1370
+
1371
+ JSONCov.call(this, runner, false);
1372
+
1373
+ runner.on('end', function(){
1374
+ process.stdout.write(fn({
1375
+ cov: self.cov
1376
+ , coverageClass: coverageClass
1377
+ }));
1378
+ });
1379
+ }
1380
+
1381
+ function coverageClass(n) {
1382
+ if (n >= 75) return 'high';
1383
+ if (n >= 50) return 'medium';
1384
+ if (n >= 25) return 'low';
1385
+ return 'terrible';
1386
+ }
1387
+ }); // module: reporters/html-cov.js
1388
+
1189
1389
  require.register("reporters/html.js", function(module, exports, require){
1190
1390
 
1191
1391
  /**
@@ -1224,15 +1424,17 @@ var statsTemplate = '<ul id="stats">'
1224
1424
  function HTML(runner) {
1225
1425
  Base.call(this, runner);
1226
1426
 
1227
- // TODO: clean up
1228
-
1229
1427
  var self = this
1230
1428
  , stats = this.stats
1231
1429
  , total = runner.total
1232
- , root = $('#mocha')
1430
+ , root = document.getElementById('mocha')
1431
+ , stat = fragment(statsTemplate)
1432
+ , items = stat.getElementsByTagName('li')
1433
+ , passes = items[1].getElementsByTagName('em')[0]
1434
+ , failures = items[2].getElementsByTagName('em')[0]
1435
+ , duration = items[3].getElementsByTagName('em')[0]
1436
+ , canvas = stat.getElementsByTagName('canvas')[0]
1233
1437
  , stack = [root]
1234
- , stat = $(statsTemplate).appendTo(root)
1235
- , canvas = stat.find('canvas').get(0)
1236
1438
  , progress
1237
1439
  , ctx
1238
1440
 
@@ -1241,7 +1443,9 @@ function HTML(runner) {
1241
1443
  progress = new Progress;
1242
1444
  }
1243
1445
 
1244
- if (!root.length) return error('#mocha div missing, add it to your document');
1446
+ if (!root) return error('#mocha div missing, add it to your document');
1447
+
1448
+ root.appendChild(stat);
1245
1449
 
1246
1450
  if (progress) progress.size(40);
1247
1451
 
@@ -1249,12 +1453,12 @@ function HTML(runner) {
1249
1453
  if (suite.root) return;
1250
1454
 
1251
1455
  // suite
1252
- var el = $('<div class="suite"><h1>' + suite.title + '</h1></div>');
1456
+ var el = fragment('<div class="suite"><h1>%s</h1></div>', suite.title);
1253
1457
 
1254
1458
  // container
1255
- stack[0].append(el);
1256
- stack.unshift($('<div>'));
1257
- el.append(stack[0]);
1459
+ stack[0].appendChild(el);
1460
+ stack.unshift(document.createElement('div'));
1461
+ el.appendChild(stack[0]);
1258
1462
  });
1259
1463
 
1260
1464
  runner.on('suite end', function(suite){
@@ -1269,48 +1473,48 @@ function HTML(runner) {
1269
1473
  runner.on('test end', function(test){
1270
1474
  // TODO: add to stats
1271
1475
  var percent = stats.tests / total * 100 | 0;
1272
-
1273
- if (progress) {
1274
- progress.update(percent).draw(ctx);
1275
- }
1476
+ if (progress) progress.update(percent).draw(ctx);
1276
1477
 
1277
1478
  // update stats
1278
1479
  var ms = new Date - stats.start;
1279
- stat.find('.passes em').text(stats.passes);
1280
- stat.find('.failures em').text(stats.failures);
1281
- stat.find('.duration em').text((ms / 1000).toFixed(2));
1480
+ text(passes, stats.passes);
1481
+ text(failures, stats.failures);
1482
+ text(duration, (ms / 1000).toFixed(2));
1282
1483
 
1283
1484
  // test
1284
- if (test.passed) {
1285
- var el = $('<div class="test pass"><h2>' + escape(test.title) + '</h2></div>')
1485
+ if ('passed' == test.state) {
1486
+ var el = fragment('<div class="test pass"><h2>%e</h2></div>', test.title);
1286
1487
  } else if (test.pending) {
1287
- var el = $('<div class="test pass pending"><h2>' + escape(test.title) + '</h2></div>')
1488
+ var el = fragment('<div class="test pass pending"><h2>%e</h2></div>', test.title);
1288
1489
  } else {
1289
- var el = $('<div class="test fail"><h2>' + escape(test.title) + '</h2></div>');
1490
+ var el = fragment('<div class="test fail"><h2>%e</h2></div>', test.title);
1290
1491
  var str = test.err.stack || test.err;
1291
1492
 
1292
1493
  // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we
1293
1494
  // check for the result of the stringifying.
1294
1495
  if ('[object Error]' == str) str = test.err.message;
1295
1496
 
1296
- $('<pre class="error">' + escape(str) + '</pre>').appendTo(el);
1497
+ el.appendChild(fragment('<pre class="error">%e</pre>', str));
1297
1498
  }
1298
1499
 
1299
1500
  // toggle code
1300
- el.find('h2').toggle(function(){
1301
- pre && pre.slideDown('fast');
1302
- }, function(){
1303
- pre && pre.slideUp('fast');
1501
+ var h2 = el.getElementsByTagName('h2')[0];
1502
+
1503
+ on(h2, 'click', function(){
1504
+ pre.style.display = 'none' == pre.style.display
1505
+ ? 'block'
1506
+ : 'none';
1304
1507
  });
1305
1508
 
1306
1509
  // code
1307
1510
  // TODO: defer
1308
1511
  if (!test.pending) {
1309
- var code = escape(clean(test.fn.toString()));
1310
- var pre = $('<pre><code>' + code + '</code></pre>');
1311
- pre.appendTo(el).hide();
1512
+ var pre = fragment('<pre><code>%e</code></pre>', clean(test.fn.toString()));
1513
+ el.appendChild(pre);
1514
+ pre.style.display = 'none';
1312
1515
  }
1313
- stack[0].append(el);
1516
+
1517
+ stack[0].appendChild(el);
1314
1518
  });
1315
1519
  }
1316
1520
 
@@ -1319,7 +1523,50 @@ function HTML(runner) {
1319
1523
  */
1320
1524
 
1321
1525
  function error(msg) {
1322
- $('<div id="error">' + msg + '</div>').appendTo('body');
1526
+ document.body.appendChild(fragment('<div id="error">%s</div>', msg));
1527
+ }
1528
+
1529
+ /**
1530
+ * Return a DOM fragment from `html`.
1531
+ */
1532
+
1533
+ function fragment(html) {
1534
+ var args = arguments
1535
+ , div = document.createElement('div')
1536
+ , i = 1;
1537
+
1538
+ div.innerHTML = html.replace(/%([se])/g, function(_, type){
1539
+ switch (type) {
1540
+ case 's': return String(args[i++]);
1541
+ case 'e': return escape(args[i++]);
1542
+ }
1543
+ });
1544
+
1545
+ return div.firstChild;
1546
+ }
1547
+
1548
+ /**
1549
+ * Set `el` text to `str`.
1550
+ */
1551
+
1552
+ function text(el, str) {
1553
+ if (el.textContent) {
1554
+ el.textContent = str;
1555
+ } else {
1556
+ el.innerText = str;
1557
+ }
1558
+ }
1559
+
1560
+ /**
1561
+ * Listen on `event` with callback `fn`.
1562
+ */
1563
+
1564
+ function on(el, event, fn) {
1565
+ if (el.addEventListener) {
1566
+ el.addEventListener(event, fn, false);
1567
+ } else {
1568
+ el.attachEvent('on' + event, fn);
1569
+ }
1323
1570
  }
1324
1571
 
1325
1572
  /**
@@ -1356,11 +1603,166 @@ exports.List = require('./list');
1356
1603
  exports.Spec = require('./spec');
1357
1604
  exports.Progress = require('./progress');
1358
1605
  exports.Landing = require('./landing');
1606
+ exports.JSONCov = require('./json-cov');
1607
+ exports.HTMLCov = require('./html-cov');
1359
1608
  exports.JSONStream = require('./json-stream');
1360
1609
  exports.XUnit = require('./xunit')
1361
1610
 
1362
1611
  }); // module: reporters/index.js
1363
1612
 
1613
+ require.register("reporters/json-cov.js", function(module, exports, require){
1614
+
1615
+ /**
1616
+ * Module dependencies.
1617
+ */
1618
+
1619
+ var Base = require('./base');
1620
+
1621
+ /**
1622
+ * Expose `JSONCov`.
1623
+ */
1624
+
1625
+ exports = module.exports = JSONCov;
1626
+
1627
+ /**
1628
+ * Initialize a new `JsCoverage` reporter.
1629
+ *
1630
+ * @param {Runner} runner
1631
+ * @param {Boolean} output
1632
+ * @api public
1633
+ */
1634
+
1635
+ function JSONCov(runner, output) {
1636
+ var self = this
1637
+ , output = 1 == arguments.length ? true : output;
1638
+
1639
+ Base.call(this, runner);
1640
+
1641
+ var tests = []
1642
+ , failures = []
1643
+ , passes = [];
1644
+
1645
+ runner.on('test end', function(test){
1646
+ tests.push(test);
1647
+ });
1648
+
1649
+ runner.on('pass', function(test){
1650
+ passes.push(test);
1651
+ });
1652
+
1653
+ runner.on('fail', function(test){
1654
+ failures.push(test);
1655
+ });
1656
+
1657
+ runner.on('end', function(){
1658
+ var cov = global._$jscoverage || {};
1659
+ var result = self.cov = map(cov);
1660
+ result.stats = self.stats;
1661
+ result.tests = tests.map(clean);
1662
+ result.failures = failures.map(clean);
1663
+ result.passes = passes.map(clean);
1664
+ if (!output) return;
1665
+ process.stdout.write(JSON.stringify(result, null, 2 ));
1666
+ });
1667
+ }
1668
+
1669
+ /**
1670
+ * Map jscoverage data to a JSON structure
1671
+ * suitable for reporting.
1672
+ *
1673
+ * @param {Object} cov
1674
+ * @return {Object}
1675
+ * @api private
1676
+ */
1677
+
1678
+ function map(cov) {
1679
+ var ret = {
1680
+ instrumentation: 'node-jscoverage'
1681
+ , sloc: 0
1682
+ , hits: 0
1683
+ , misses: 0
1684
+ , coverage: 0
1685
+ , files: []
1686
+ };
1687
+
1688
+ for (var filename in cov) {
1689
+ var data = coverage(filename, cov[filename]);
1690
+ ret.files.push(data);
1691
+ ret.hits += data.hits;
1692
+ ret.misses += data.misses;
1693
+ ret.sloc += data.sloc;
1694
+ }
1695
+
1696
+ if (ret.sloc > 0) {
1697
+ ret.coverage = (ret.hits / ret.sloc) * 100;
1698
+ }
1699
+
1700
+ return ret;
1701
+ };
1702
+
1703
+ /**
1704
+ * Map jscoverage data for a single source file
1705
+ * to a JSON structure suitable for reporting.
1706
+ *
1707
+ * @param {String} filename name of the source file
1708
+ * @param {Object} data jscoverage coverage data
1709
+ * @return {Object}
1710
+ * @api private
1711
+ */
1712
+
1713
+ function coverage(filename, data) {
1714
+ var ret = {
1715
+ filename: filename,
1716
+ coverage: 0,
1717
+ hits: 0,
1718
+ misses: 0,
1719
+ sloc: 0,
1720
+ source: {}
1721
+ };
1722
+
1723
+ data.source.forEach(function(line, num){
1724
+ num++;
1725
+
1726
+ if (data[num] === 0) {
1727
+ ret.misses++;
1728
+ ret.sloc++;
1729
+ } else if (data[num] !== undefined) {
1730
+ ret.hits++;
1731
+ ret.sloc++;
1732
+ }
1733
+
1734
+ ret.source[num] = {
1735
+ source: line
1736
+ , coverage: data[num] === undefined
1737
+ ? ''
1738
+ : data[num]
1739
+ };
1740
+ });
1741
+
1742
+ ret.coverage = ret.hits / ret.sloc * 100;
1743
+
1744
+ return ret;
1745
+ }
1746
+
1747
+ /**
1748
+ * Return a plain-object representation of `test`
1749
+ * free of cyclic properties etc.
1750
+ *
1751
+ * @param {Object} test
1752
+ * @return {Object}
1753
+ * @api private
1754
+ */
1755
+
1756
+ function clean(test) {
1757
+ return {
1758
+ title: test.title
1759
+ , fullTitle: test.fullTitle()
1760
+ , duration: test.duration
1761
+ }
1762
+ }
1763
+
1764
+ }); // module: reporters/json-cov.js
1765
+
1364
1766
  require.register("reporters/json-stream.js", function(module, exports, require){
1365
1767
 
1366
1768
  /**
@@ -1476,7 +1878,7 @@ function JSONReporter(runner) {
1476
1878
  , passes: passes.map(clean)
1477
1879
  };
1478
1880
 
1479
- process.stdout.write(JSON.stringify(obj));
1881
+ process.stdout.write(JSON.stringify(obj, null, 2));
1480
1882
  });
1481
1883
  }
1482
1884
 
@@ -1568,7 +1970,7 @@ function Landing(runner) {
1568
1970
  : crashed;
1569
1971
 
1570
1972
  // show the crash
1571
- if (test.failed) {
1973
+ if ('failed' == test.state) {
1572
1974
  plane = color('plane crash', '✈');
1573
1975
  crashed = col;
1574
1976
  }
@@ -2048,7 +2450,7 @@ function test(test) {
2048
2450
  , time: test.duration / 1000
2049
2451
  };
2050
2452
 
2051
- if (test.failed) {
2453
+ if ('failed' == test.state) {
2052
2454
  var err = test.err;
2053
2455
  attrs.message = escape(err.message);
2054
2456
  console.log(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(err.stack))));
@@ -2117,7 +2519,6 @@ function Runnable(title, fn) {
2117
2519
  this.sync = ! this.async;
2118
2520
  this._timeout = 2000;
2119
2521
  this.timedOut = false;
2120
- this.context = this;
2121
2522
  }
2122
2523
 
2123
2524
  /**
@@ -2196,7 +2597,7 @@ Runnable.prototype.run = function(fn){
2196
2597
  var self = this
2197
2598
  , ms = this.timeout()
2198
2599
  , start = new Date
2199
- , ctx = this.context
2600
+ , ctx = this.ctx
2200
2601
  , finished
2201
2602
  , emitted;
2202
2603
 
@@ -2376,7 +2777,7 @@ Runner.prototype.checkGlobals = function(test){
2376
2777
 
2377
2778
  Runner.prototype.fail = function(test, err){
2378
2779
  ++this.failures;
2379
- test.failed = true;
2780
+ test.state = 'failed';
2380
2781
  this.emit('fail', test, err);
2381
2782
  };
2382
2783
 
@@ -2417,7 +2818,7 @@ Runner.prototype.hook = function(name, fn){
2417
2818
  var hook = hooks[i];
2418
2819
  if (!hook) return fn();
2419
2820
  self.currentRunnable = hook;
2420
- hook.context = self.test;
2821
+ hook.ctx.test(self.test);
2421
2822
 
2422
2823
  self.emit('hook', hook);
2423
2824
 
@@ -2526,6 +2927,7 @@ Runner.prototype.runTest = function(fn){
2526
2927
  , self = this;
2527
2928
 
2528
2929
  try {
2930
+ test.ctx.test(test);
2529
2931
  test.on('error', function(err){
2530
2932
  self.fail(test, err);
2531
2933
  });
@@ -2582,7 +2984,7 @@ Runner.prototype.runTests = function(suite, fn){
2582
2984
  return self.hookUp('afterEach', next);
2583
2985
  }
2584
2986
 
2585
- test.passed = true;
2987
+ test.state = 'passed';
2586
2988
  self.emit('pass', test);
2587
2989
  self.emit('test end', test);
2588
2990
  self.hookUp('afterEach', next);
@@ -2639,7 +3041,7 @@ Runner.prototype.runSuite = function(suite, fn){
2639
3041
  Runner.prototype.uncaught = function(err){
2640
3042
  debug('uncaught exception');
2641
3043
  var runnable = this.currentRunnable;
2642
- if (runnable.failed) return;
3044
+ if ('failed' == runnable.state) return;
2643
3045
  runnable.clearTimeout();
2644
3046
  err.uncaught = true;
2645
3047
  this.fail(runnable, err);
@@ -2725,7 +3127,7 @@ exports = module.exports = Suite;
2725
3127
  */
2726
3128
 
2727
3129
  exports.create = function(parent, title){
2728
- var suite = new Suite(title);
3130
+ var suite = new Suite(title, parent.ctx);
2729
3131
  suite.parent = parent;
2730
3132
  title = suite.fullTitle();
2731
3133
  parent.addSuite(suite);
@@ -2733,14 +3135,17 @@ exports.create = function(parent, title){
2733
3135
  };
2734
3136
 
2735
3137
  /**
2736
- * Initialize a new `Suite` with the given `title`.
3138
+ * Initialize a new `Suite` with the given
3139
+ * `title` and `ctx`.
2737
3140
  *
2738
3141
  * @param {String} title
3142
+ * @param {Context} ctx
2739
3143
  * @api private
2740
3144
  */
2741
3145
 
2742
- function Suite(title) {
3146
+ function Suite(title, ctx) {
2743
3147
  this.title = title;
3148
+ this.ctx = ctx;
2744
3149
  this.suites = [];
2745
3150
  this.tests = [];
2746
3151
  this._beforeEach = [];
@@ -2770,6 +3175,7 @@ Suite.prototype.constructor = Suite;
2770
3175
  Suite.prototype.clone = function(){
2771
3176
  var suite = new Suite(this.title);
2772
3177
  debug('clone');
3178
+ suite.ctx = this.ctx;
2773
3179
  suite.timeout(this.timeout());
2774
3180
  suite.bail(this.bail());
2775
3181
  return suite;
@@ -2818,6 +3224,7 @@ Suite.prototype.beforeAll = function(fn){
2818
3224
  var hook = new Hook('"before all" hook', fn);
2819
3225
  hook.parent = this;
2820
3226
  hook.timeout(this.timeout());
3227
+ hook.ctx = this.ctx;
2821
3228
  this._beforeAll.push(hook);
2822
3229
  this.emit('beforeAll', hook);
2823
3230
  return this;
@@ -2835,6 +3242,7 @@ Suite.prototype.afterAll = function(fn){
2835
3242
  var hook = new Hook('"after all" hook', fn);
2836
3243
  hook.parent = this;
2837
3244
  hook.timeout(this.timeout());
3245
+ hook.ctx = this.ctx;
2838
3246
  this._afterAll.push(hook);
2839
3247
  this.emit('afterAll', hook);
2840
3248
  return this;
@@ -2852,6 +3260,7 @@ Suite.prototype.beforeEach = function(fn){
2852
3260
  var hook = new Hook('"before each" hook', fn);
2853
3261
  hook.parent = this;
2854
3262
  hook.timeout(this.timeout());
3263
+ hook.ctx = this.ctx;
2855
3264
  this._beforeEach.push(hook);
2856
3265
  this.emit('beforeEach', hook);
2857
3266
  return this;
@@ -2869,6 +3278,7 @@ Suite.prototype.afterEach = function(fn){
2869
3278
  var hook = new Hook('"after each" hook', fn);
2870
3279
  hook.parent = this;
2871
3280
  hook.timeout(this.timeout());
3281
+ hook.ctx = this.ctx;
2872
3282
  this._afterEach.push(hook);
2873
3283
  this.emit('afterEach', hook);
2874
3284
  return this;
@@ -2902,6 +3312,7 @@ Suite.prototype.addSuite = function(suite){
2902
3312
  Suite.prototype.addTest = function(test){
2903
3313
  test.parent = this;
2904
3314
  test.timeout(this.timeout());
3315
+ test.ctx = this.ctx;
2905
3316
  this.tests.push(test);
2906
3317
  this.emit('test', test);
2907
3318
  return this;
@@ -2974,6 +3385,22 @@ Test.prototype = new Runnable;
2974
3385
  Test.prototype.constructor = Test;
2975
3386
 
2976
3387
 
3388
+ /**
3389
+ * Inspect the context void of private properties.
3390
+ *
3391
+ * @return {String}
3392
+ * @api private
3393
+ */
3394
+
3395
+ Test.prototype.inspect = function(){
3396
+ return JSON.stringify(this, function(key, val){
3397
+ return '_' == key[0]
3398
+ ? undefined
3399
+ : 'parent' == key
3400
+ ? '#<Suite>'
3401
+ : val;
3402
+ }, 2);
3403
+ };
2977
3404
  }); // module: test.js
2978
3405
 
2979
3406
  require.register("utils.js", function(module, exports, require){
@@ -3093,9 +3520,9 @@ exports.keys = Object.keys || function(obj) {
3093
3520
  var keys = []
3094
3521
  , has = Object.prototype.hasOwnProperty // for `window` on <=IE8
3095
3522
 
3096
- for (var i in obj) {
3097
- if (has.call(obj, i)) {
3098
- keys.push(i);
3523
+ for (var key in obj) {
3524
+ if (has.call(obj, key)) {
3525
+ keys.push(key);
3099
3526
  }
3100
3527
  }
3101
3528
 
@@ -3133,7 +3560,7 @@ function ignored(path){
3133
3560
  * Lookup files in the given `dir`.
3134
3561
  *
3135
3562
  * @return {Array}
3136
- * @api public
3563
+ * @api private
3137
3564
  */
3138
3565
 
3139
3566
  exports.files = function(dir, ret){
@@ -3223,9 +3650,8 @@ window.mocha = require('mocha');
3223
3650
 
3224
3651
  // boot
3225
3652
  ;(function(){
3226
- var suite = new mocha.Suite
3653
+ var suite = new mocha.Suite('', new mocha.Context)
3227
3654
  , utils = mocha.utils
3228
- , Reporter = mocha.reporters.HTML
3229
3655
 
3230
3656
  /**
3231
3657
  * Highlight the given string of `js`.
@@ -3236,13 +3662,24 @@ window.mocha = require('mocha');
3236
3662
  .replace(/</g, '&lt;')
3237
3663
  .replace(/>/g, '&gt;')
3238
3664
  .replace(/\/\/(.*)/gm, '<span class="comment">//$1</span>')
3239
- .replace(/('.*')/gm, '<span class="string">$1</span>')
3665
+ .replace(/('.*?')/gm, '<span class="string">$1</span>')
3240
3666
  .replace(/(\d+\.\d+)/gm, '<span class="number">$1</span>')
3241
3667
  .replace(/(\d+)/gm, '<span class="number">$1</span>')
3242
3668
  .replace(/\bnew *(\w+)/gm, '<span class="keyword">new</span> <span class="init">$1</span>')
3243
3669
  .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '<span class="keyword">$1</span>')
3244
3670
  }
3245
3671
 
3672
+ /**
3673
+ * Highlight code contents.
3674
+ */
3675
+
3676
+ function highlightCode() {
3677
+ var code = document.getElementsByTagName('code');
3678
+ for (var i = 0, len = code.length; i < len; ++i) {
3679
+ code[i].innerHTML = highlight(code[i].innerHTML);
3680
+ }
3681
+ }
3682
+
3246
3683
  /**
3247
3684
  * Parse the given `qs`.
3248
3685
  */
@@ -3273,17 +3710,14 @@ window.mocha = require('mocha');
3273
3710
  * Run mocha, returning the Runner.
3274
3711
  */
3275
3712
 
3276
- mocha.run = function(){
3713
+ mocha.run = function(Reporter){
3277
3714
  suite.emit('run');
3278
3715
  var runner = new mocha.Runner(suite);
3716
+ Reporter = Reporter || mocha.reporters.HTML;
3279
3717
  var reporter = new Reporter(runner);
3280
3718
  var query = parse(window.location.search || "");
3281
3719
  if (query.grep) runner.grep(new RegExp(query.grep));
3282
- runner.on('end', function(){
3283
- $('code').each(function(){
3284
- $(this).html(highlight($(this).text()));
3285
- });
3286
- });
3720
+ runner.on('end', highlightCode);
3287
3721
  return runner.run();
3288
3722
  };
3289
3723
  })();