const Base = require('mocha/lib/reporters/base'); const ms = require('mocha/lib/ms'); const color = Base.color; class EmbarkSpec extends Base { constructor(runner, options) { super(runner, options); const self = this; self.listenForGas = true; self.embarkEvents = options.reporterOptions.events; self.gasDetails = options.reporterOptions.gasDetails; self.gasLimit = options.reporterOptions.gasLimit; let indents = 0; let n = 0; self.stats.totalGasCost = 0; self.stats.test = {}; self.stats.test.gasUsed = 0; function onContractReceipt(receipt) { const fmt = color('bright pass', ' ') + color('suite', ' %s') + color('light', ' deployed for ') + color(self.getGasColor(receipt.gasUsed), '%s') + color('light', ' gas'); console.log(fmt, receipt.className, receipt.gasUsed); } function onBlockHeader(blockHeader) { self.stats.totalGasCost += blockHeader.gasUsed; self.stats.test.gasUsed += blockHeader.gasUsed; } function onBlockHeader(blockHeader) { if(!self.listenForGas) { return; } self.stats.totalGasCost += blockHeader.gasUsed; self.stats.test.gasUsed += blockHeader.gasUsed; } if (self.gasDetails) { self.embarkEvents.on("deploy:contract:receipt", onContractReceipt); } self.embarkEvents.on("block:header", onBlockHeader); self.embarkEvents.setCommandHandler("reporter:toggleGasListener", () => { self.listenForGas = !self.listenForGas; }); function indent() { return Array(indents).join(' '); } runner.on('start', function () { console.log(); }); runner.on('suite', function (suite) { ++indents; if (self.gasDetails) { console.log(); } console.log(color('suite', '%s%s'), indent(), suite.title); }); runner.on('suite end', function () { --indents; if (indents === 1) { console.log(); } }); runner.on('pending', function (test) { const fmt = indent() + color('pending', ' - %s'); console.log(fmt, test.title); }); runner.on('test', function () { self.stats.test.gasUsed = 0; }); runner.on('pass', function (test) { let fmt = indent() + color('checkmark', ' ' + Base.symbols.ok) + color('pass', ' %s') + color(test.speed, ' (%dms)') + ' - ' + color(self.getGasColor(self.stats.test.gasUsed), '[%d gas]'); console.log(fmt, test.title, test.duration, self.stats.test.gasUsed); }); runner.on('fail', function (test) { console.log(indent() + color('fail', ' %d) %s') + ' - ' + color(self.getGasColor(self.stats.test.gasUsed), '[%d gas]'), ++n, test.title, self.stats.test.gasUsed); }); runner.once('end', function () { runner.removeAllListeners(); self.embarkEvents.removeListener("deploy:contract:receipt", onContractReceipt); self.embarkEvents.removeListener("block:header", onBlockHeader); self.epilogue(); }); } getGasColor(gasCost) { if (gasCost <= this.gasLimit / 10) { return 'fast'; } if (gasCost <= 3 * (this.gasLimit / 4)) { return 'medium'; } return 'slow'; } epilogue() { const stats = this.stats; let fmt; console.log(); // passes fmt = color('bright pass', ' ') + color('green', ' %d passing') + color('light', ' (%s)') + color('light', ' - [Total: %s gas]'); console.log(fmt, stats.passes || 0, ms(stats.duration), stats.totalGasCost); // pending if (stats.pending) { fmt = color('pending', ' ') + color('pending', ' %d pending'); console.log(fmt, stats.pending); } // failures if (stats.failures) { fmt = color('fail', ' %d failing'); console.log(fmt, stats.failures); Base.list(this.failures); console.log(); } console.log(); } } module.exports = EmbarkSpec;