refactor: wire up coverage (#1865)

* refactor: wire up coverage

* refactor: coverage now reacts instead of being told what to do
This commit is contained in:
André Medeiros 2019-09-05 16:35:17 -04:00 committed by Iuri Matias
parent 718d19f7d3
commit 7e839e758e
8 changed files with 89 additions and 33 deletions

View File

@ -18,14 +18,25 @@ export default class Coverage {
constructor(private embark: Embark, options: any) { constructor(private embark: Embark, options: any) {
this.fs = embark.fs; this.fs = embark.fs;
this.fs.ensureDirSync(coverageContractsPath()); this.fs.ensureDirSync(coverageContractsPath());
this.originalContractFiles = embark.config.contractsFiles;
this.contracts = this.getContracts(); this.contracts = [];
this.embark.events.setCommandHandler("coverage:prepareContracts", async (done) => { if (!options.coverage) {
return;
}
this.embark.registerActionForEvent('tests:contracts:compile:before', async (contractsFiles, cb) => {
const solcVersion = this.embark.config.embarkConfig.versions.solc;
const enhancedContracts = contractsFiles.map((file: File) => new ContractEnhanced(file.path, solcVersion));
this.mergeContracts(enhancedContracts);
await this.prepareContracts(); await this.prepareContracts();
this.swapContracts();
done(); contractsFiles.forEach((cf: any) => {
cf.path = path.join(coverageContractsPath(), cf.path);
});
cb(null, contractsFiles);
}); });
this.embark.events.on("tests:ready", this.pushDeployedContracts.bind(this)); this.embark.events.on("tests:ready", this.pushDeployedContracts.bind(this));
@ -33,9 +44,14 @@ export default class Coverage {
this.embark.events.on("tests:manualDeploy", this.registerWeb3Contract.bind(this)); this.embark.events.on("tests:manualDeploy", this.registerWeb3Contract.bind(this));
} }
private getContracts() { private async mergeContracts(contracts: ContractEnhanced[]) {
const solcVersion = this.embark.config.embarkConfig.versions.solc; contracts.forEach((contract: ContractEnhanced) => {
return this.originalContractFiles.map((file) => new ContractEnhanced(file.path, solcVersion)); if (this.contracts.some((cc: ContractEnhanced) => cc.filepath === contract.filepath)) {
return;
}
this.contracts.push(contract);
});
} }
private async prepareContracts() { private async prepareContracts() {
@ -46,14 +62,6 @@ export default class Coverage {
await Promise.all(promises); await Promise.all(promises);
} }
private swapContracts() {
this.embark.config.embarkConfig.contracts = this.originalContractFiles.map((file: File) => (
path.join(coverageContractsPath(), file.path)
));
this.embark.config.contractsFiles = [];
this.embark.config.reloadConfig();
}
private async pushDeployedContracts() { private async pushDeployedContracts() {
const newContracts = await this.getDeployedContracts(); const newContracts = await this.getDeployedContracts();
this.deployedContracts = this.deployedContracts.concat(newContracts); this.deployedContracts = this.deployedContracts.concat(newContracts);

View File

@ -9,13 +9,14 @@ const JAVASCRIPT_TEST_MATCH = /^.+\.js$/i;
const TEST_TIMEOUT = 15000; // 15 seconds in milliseconds const TEST_TIMEOUT = 15000; // 15 seconds in milliseconds
class MochaTestRunner { class MochaTestRunner {
constructor(embark, _options) { constructor(embark, options) {
this.embark = embark; this.embark = embark;
this.events = embark.events;
this.plugins = options.plugins;
this.files = []; this.files = [];
const { events } = embark; this.events.request('tests:runner:register',
events.request('tests:runner:register',
'JavaScript (Mocha)', 'JavaScript (Mocha)',
this.match.bind(this), this.match.bind(this),
this.addFile.bind(this), this.addFile.bind(this),
@ -36,7 +37,7 @@ class MochaTestRunner {
} }
run(options, cb) { run(options, cb) {
const {events} = this.embark; const {events, plugins} = this;
const {reporter} = options; const {reporter} = options;
const Module = require("module"); const Module = require("module");
@ -76,6 +77,7 @@ class MochaTestRunner {
acctCb(err, accounts); acctCb(err, accounts);
} }
events.emit('tests:ready', accounts);
done(); done();
}); });
}); });
@ -105,9 +107,15 @@ class MochaTestRunner {
(next) => { // get contract files (next) => { // get contract files
events.request("config:contractsFiles", next); events.request("config:contractsFiles", next);
}, },
(cf, next) => {
plugins.emitAndRunActionsForEvent('tests:contracts:compile:before', cf, next);
},
(cf, next) => { // compile contracts (cf, next) => { // compile contracts
events.request("compiler:contracts:compile", cf, next); events.request("compiler:contracts:compile", cf, next);
}, },
(cc, next) => {
plugins.emitAndRunActionsForEvent('tests:contracts:compile:after', cc, next);
},
(cc, next) => { // override require (cc, next) => { // override require
compiledContracts = cc; compiledContracts = cc;
@ -149,12 +157,14 @@ class MochaTestRunner {
} }
mocha.run((failures) => { mocha.run((failures) => {
next(null, failures); next();
}); });
} }
], (err, failures) => { ], (err) => {
events.emit('tests:finished');
Module.prototype.require = originalRequire; Module.prototype.require = originalRequire;
cb(err, failures); cb(err);
}); });
} }
} }

View File

@ -28,9 +28,10 @@ const ASSERT_LIB = new File({
}); });
class SolidityTestRunner { class SolidityTestRunner {
constructor(embark, _options) { constructor(embark, options) {
this.embark = embark; this.embark = embark;
this.events = embark.events; this.events = embark.events;
this.plugins = options.plugins;
this.files = []; this.files = [];
@ -56,7 +57,7 @@ class SolidityTestRunner {
run(options, cb) { run(options, cb) {
const reporter = new Reporter(options.reporter); const reporter = new Reporter(options.reporter);
const {events} = this; const {events, plugins} = this;
if (this.files.length === 0) { if (this.files.length === 0) {
return cb(null, 0); return cb(null, 0);
@ -87,9 +88,19 @@ class SolidityTestRunner {
(next) => { (next) => {
events.request("contracts:reset", next); events.request("contracts:reset", next);
}, },
/*
(next) => {
plugins.emitAndRunActionsForEvent('tests:contracts:compile:before', contractFiles, next);
},
*/
(next) => { (next) => {
events.request("compiler:contracts:compile", contractFiles, next); events.request("compiler:contracts:compile", contractFiles, next);
}, },
/*
(cc, next) => {
plugins.emitAndRunActionsForEvent('tests:contracts:compile:after', cc, next);
},
*/
(compiledContracts, next) => { (compiledContracts, next) => {
// TODO: fetch config and use it here // TODO: fetch config and use it here
events.request("contracts:build", { contracts: {} }, compiledContracts, next); events.request("contracts:build", { contracts: {} }, compiledContracts, next);
@ -110,6 +121,7 @@ class SolidityTestRunner {
events.request("deployment:contracts:deploy", contractsToDeploy, contractDependencies, next); events.request("deployment:contracts:deploy", contractsToDeploy, contractDependencies, next);
}, },
(_result, next) => { (_result, next) => {
events.emit('tests:ready');
events.request("blockchain:client:provider", "ethereum", next); events.request("blockchain:client:provider", "ethereum", next);
}, },
(bcProvider, next) => { (bcProvider, next) => {

View File

@ -52,6 +52,7 @@
"embark-i18n": "^4.1.1", "embark-i18n": "^4.1.1",
"embark-utils": "^4.1.1", "embark-utils": "^4.1.1",
"fs-extra": "7.0.1", "fs-extra": "7.0.1",
"istanbul": "0.4.5",
"mocha": "6.2.0", "mocha": "6.2.0",
"open": "6.4.0" "open": "6.4.0"
}, },

View File

@ -1,6 +1,8 @@
import { __ } from 'embark-i18n'; import { __ } from 'embark-i18n';
const async = require('async'); const async = require('async');
const chalk = require('chalk');
const path = require('path'); const path = require('path');
const { embarkPath, dappPath, runCmd } = require('embark-utils');
import fs from 'fs'; import fs from 'fs';
import { COVERAGE_GAS_LIMIT, GAS_LIMIT } from './constants'; import { COVERAGE_GAS_LIMIT, GAS_LIMIT } from './constants';
@ -60,11 +62,33 @@ class TestRunner {
}); });
async.series(runnerFns, next); async.series(runnerFns, next);
},
(_results, next) => {
if (!options.coverage) {
return next();
} }
const cmd = `${embarkPath('node_modules/.bin/istanbul')} report --root .embark --format html --format lcov`;
runCmd(cmd, {silent: false, exitOnError: false}, next);
},
], (err) => { ], (err) => {
reporter.footer(); reporter.footer();
if (!options.coverage) {
return cb(err, reporter.passes, reporter.fails);
}
process.stdout.write(chalk`{blue Coverage report created. You can find it here:}\n{white.underline ${dappPath('coverage/index.html')}}\n`);
if (options.noBrowser) {
return cb(err, reporter.passes, reporter.fails);
}
const open = require('open');
open(dappPath('coverage/index.html')).then(() => {
cb(err, reporter.passes, reporter.fails); cb(err, reporter.passes, reporter.fails);
}); });
});
} }
getFilesFromDir(filePath, cb) { getFilesFromDir(filePath, cb) {

View File

@ -36,9 +36,9 @@ class Reporter {
footer() { footer() {
const total = this.passes + this.fails; const total = this.passes + this.fails;
if (this.fails > 0) { if (this.fails > 0) {
process.stdout.write(`>>> Failed ${this.fails} / ${total} test(s).\n`); process.stdout.write(chalk`{red Failed ${this.fails} / ${total} test(s).}\n`);
} else { } else {
process.stdout.write(`>>> Passed ${this.passes} test(s).\n`); process.stdout.write(chalk`{green Passed ${this.passes} test(s).}\n`);
} }
} }

View File

@ -882,7 +882,7 @@ class EmbarkController {
engine.registerModuleGroup("compiler"); engine.registerModuleGroup("compiler");
engine.registerModuleGroup("contracts"); engine.registerModuleGroup("contracts");
engine.registerModuleGroup("pipeline"); engine.registerModuleGroup("pipeline");
engine.registerModuleGroup("tests"); engine.registerModuleGroup("tests", options);
let plugin = engine.plugins.createPlugin('cmdcontrollerplugin', {}); let plugin = engine.plugins.createPlugin('cmdcontrollerplugin', {});
plugin.registerActionForEvent("embark:engine:started", async (_params, cb) => { plugin.registerActionForEvent("embark:engine:started", async (_params, cb) => {

View File

@ -189,10 +189,11 @@ class Engine {
}); });
} }
testComponents() { testComponents(options) {
this.registerModulePackage('embark-test-runner'); this.registerModulePackage('embark-test-runner');
this.registerModulePackage('embark-solidity-tests'); this.registerModulePackage('embark-coverage', {plugins: this.plugins, coverage: options.coverage});
this.registerModulePackage('embark-mocha-tests'); this.registerModulePackage('embark-solidity-tests', {plugins: this.plugins, coverage: options.coverage});
this.registerModulePackage('embark-mocha-tests', {plugins: this.plugins, coverage: options.coverage});
} }
compilerComponents(_options) { compilerComponents(_options) {