mirror of https://github.com/embarklabs/embark.git
fix(@embark/core): Fix tests for shim/monorepo
When embark was running as module inside the dapp’s `node_modules`, the tests were failing due to several issues: 1. `web3` was not being set in the global namespace of vm2. `EmbarkJS.Blockchain.setProvider` was therefore failing because it relies on `global.web3` to be set. I guess somehow this works when the test app was running in a child tree of the executing program. maybe this is a security feature of vm2, but i’m not sure. 2. `embarkjs` provider code being injected to the vm twice. This really was the initial point of failure, as this piece of code is requiring embarkjs, so i’m assuming, but again not sure, that maybe it was getting a second instance of `EmbarkJS` which did not have it’s providers set up correctly (hence the error with `ENS provider not set`). Fixes for those issues in this PR: 1. To circumvent the web3 issue, we are now setting `global.web3` for tests only (the global web3 accessible in the tests), and `web3` is now explicitly passed in to `EmbarkJS.Blockchain.setProvider` 2. To fix the `embarkjs` code being called twice, we are not re-injecting this code to the VM during test initialisations
This commit is contained in:
parent
756a916428
commit
eb4da28a61
|
@ -3,6 +3,7 @@ const fs = require('../../fs');
|
|||
|
||||
class CodeRunner {
|
||||
constructor(options) {
|
||||
this.ready = false;
|
||||
this.config = options.config;
|
||||
this.plugins = options.plugins;
|
||||
this.logger = options.logger;
|
||||
|
@ -38,6 +39,7 @@ class CodeRunner {
|
|||
this.registerEvents();
|
||||
this.registerCommands();
|
||||
this.events.emit('runcode:ready');
|
||||
this.ready = true;
|
||||
}
|
||||
|
||||
registerIpcEvents() {
|
||||
|
@ -74,6 +76,23 @@ class CodeRunner {
|
|||
cb(this.vm.options.sandbox);
|
||||
});
|
||||
this.events.setCommandHandler('runcode:eval', this.evalCode.bind(this));
|
||||
this.events.setCommandHandler('runcode:ready', (cb) => {
|
||||
if (this.ready) {
|
||||
return cb();
|
||||
}
|
||||
this.events.once("runcode:ready", cb);
|
||||
});
|
||||
this.events.setCommandHandler('runcode:embarkjs:reset', this.resetEmbarkJS.bind(this));
|
||||
}
|
||||
|
||||
resetEmbarkJS(cb) {
|
||||
this.events.request('blockchain:get', (web3) => {
|
||||
this.events.emit("runcode:register", "web3", web3, false, () => {
|
||||
this.events.request("code-generator:embarkjs:init-provider-code", async (code) => {
|
||||
await this.evalCode(code, cb, true);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
registerVar(varName, code, toRecord = true, cb = () => {}) {
|
||||
|
|
|
@ -16,6 +16,7 @@ class TestRunner {
|
|||
this.fs = embark.fs;
|
||||
this.ipc = options.ipc;
|
||||
this.runResults = [];
|
||||
this.embarkjs = null;
|
||||
|
||||
this.events.setCommandHandler('tests:run', (options, callback) => {
|
||||
this.run(options, callback);
|
||||
|
@ -145,10 +146,10 @@ class TestRunner {
|
|||
|
||||
runJSTests(files, options, cb) {
|
||||
const self = this;
|
||||
const test = new Test({loglevel: options.loglevel, node: options.node, events: self.events, logger: self.logger,
|
||||
config: self.embark.config, ipc: self.ipc, coverage: options.coverage, inProcess: options.inProcess});
|
||||
async.waterfall([
|
||||
function setupGlobalNamespace(next) {
|
||||
const test = new Test({loglevel: options.loglevel, node: options.node, events: self.events, logger: self.logger,
|
||||
config: self.embark.config, ipc: self.ipc, coverage: options.coverage, inProcess: options.inProcess});
|
||||
global.embark = test;
|
||||
global.assert = assert;
|
||||
global.config = test.config.bind(test);
|
||||
|
@ -162,20 +163,27 @@ class TestRunner {
|
|||
global.deployAll = deprecatedWarning;
|
||||
global.EmbarkSpec = {};
|
||||
global.EmbarkSpec.deployAll = deprecatedWarning;
|
||||
|
||||
global.contract = function (describeName, callback) {
|
||||
return Mocha.describe(describeName, callback);
|
||||
};
|
||||
next();
|
||||
},
|
||||
function overrideRequire (next) {
|
||||
// Override require to enable `require('Embark/contracts/contractName');`
|
||||
const Module = require('module');
|
||||
const originalRequire = require('module').prototype.require;
|
||||
Module.prototype.require = function (requireName) {
|
||||
if (requireName.startsWith('Embark/EmbarkJS')) {
|
||||
return self.embarkjs;
|
||||
}
|
||||
if (requireName.startsWith('Embark')) {
|
||||
return test.require(...arguments);
|
||||
}
|
||||
return originalRequire.apply(this, arguments);
|
||||
};
|
||||
|
||||
global.contract = function (describeName, callback) {
|
||||
return Mocha.describe(describeName, callback);
|
||||
};
|
||||
next();
|
||||
},
|
||||
function initTest(next) {
|
||||
|
||||
test.init((err) => {
|
||||
next(err, files);
|
||||
|
@ -200,7 +208,11 @@ class TestRunner {
|
|||
global.config({});
|
||||
}
|
||||
global.embark.onReady((err) => {
|
||||
done(err);
|
||||
if(err) return done(err);
|
||||
self.events.request('runcode:eval', 'EmbarkJS', (err, embarkjs) => {
|
||||
self.embarkjs = embarkjs;
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
mocha.run(function (fails) {
|
||||
|
|
|
@ -120,10 +120,16 @@ class SolcTest extends Test {
|
|||
methodIdentifiers: contract.functionHashes
|
||||
}
|
||||
};
|
||||
remixTests.runTest(contract.className, Test.getWeb3Contract(contract, web3), contractDetails, {accounts},
|
||||
self._prettyPrint.bind(self), _callback);
|
||||
this.getWeb3Contract(contract, web3, (err, web3contract) => {
|
||||
if(err) {
|
||||
return _callback(err);
|
||||
}
|
||||
remixTests.runTest(contract.className, web3contract, contractDetails, {accounts},
|
||||
self._prettyPrint.bind(self), _callback);
|
||||
});
|
||||
};
|
||||
fns.push(fn);
|
||||
|
||||
});
|
||||
async.series(fns, next);
|
||||
}
|
||||
|
|
|
@ -2,13 +2,10 @@ import * as utilsContractsConfig from "../../utils/contractsConfig";
|
|||
|
||||
const async = require('async');
|
||||
const AccountParser = require('../../utils/accountParser');
|
||||
const EmbarkJS = require('embarkjs');
|
||||
const utils = require('../../utils/utils');
|
||||
const constants = require('../../constants');
|
||||
const web3Utils = require('web3-utils');
|
||||
const VM = require('../../core/modules/coderunner/vm');
|
||||
const Web3 = require('web3');
|
||||
const IpfsApi = require("ipfs-api");
|
||||
const EmbarkJS = require('embarkjs');
|
||||
|
||||
const BALANCE_10_ETHER_IN_HEX = '0x8AC7230489E80000';
|
||||
|
||||
|
@ -32,24 +29,26 @@ class Test {
|
|||
}
|
||||
|
||||
init(callback) {
|
||||
this.gasLimit = constants.tests.gasLimit;
|
||||
this.events.request('deploy:setGasLimit', this.gasLimit);
|
||||
const waitingForReady = setTimeout(() => {
|
||||
this.logger.warn('Waiting for the blockchain connector to be ready...');
|
||||
// TODO add docs link to how to install one
|
||||
this.logger.warn('If you did not install a blockchain connector, stop this process and install one');
|
||||
}, 5000);
|
||||
this.events.request('blockchain:connector:ready', () => {
|
||||
clearTimeout(waitingForReady);
|
||||
if (this.options.node !== 'embark') {
|
||||
this.showNodeHttpWarning();
|
||||
return callback();
|
||||
}
|
||||
if (!this.ipc.connected) {
|
||||
this.logger.error("Could not connect to Embark's IPC. Is embark running?");
|
||||
if (!this.options.inProcess) process.exit(1);
|
||||
}
|
||||
this.connectToIpcNode(callback);
|
||||
this.events.request('runcode:ready', () => {
|
||||
this.gasLimit = constants.tests.gasLimit;
|
||||
this.events.request('deploy:setGasLimit', this.gasLimit);
|
||||
const waitingForReady = setTimeout(() => {
|
||||
this.logger.warn('Waiting for the blockchain connector to be ready...');
|
||||
// TODO add docs link to how to install one
|
||||
this.logger.warn('If you did not install a blockchain connector, stop this process and install one');
|
||||
}, 5000);
|
||||
this.events.request('blockchain:connector:ready', () => {
|
||||
clearTimeout(waitingForReady);
|
||||
if (this.options.node !== 'embark') {
|
||||
this.showNodeHttpWarning();
|
||||
return callback();
|
||||
}
|
||||
if (!this.ipc.connected) {
|
||||
this.logger.error("Could not connect to Embark's IPC. Is embark running?");
|
||||
if (!this.options.inProcess) process.exit(1);
|
||||
}
|
||||
this.connectToIpcNode(callback);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -229,7 +228,6 @@ class Test {
|
|||
}
|
||||
self.ready = true;
|
||||
self.error = false;
|
||||
self.events.emit('tests:ready');
|
||||
next(null, accounts);
|
||||
});
|
||||
},
|
||||
|
@ -243,31 +241,16 @@ class Test {
|
|||
// TODO Do not exit in case of not a normal run (eg after a change)
|
||||
if (!self.options.inProcess) process.exit(1);
|
||||
}
|
||||
self.events.emit('tests:ready');
|
||||
callback(null, accounts);
|
||||
});
|
||||
}
|
||||
|
||||
resetEmbarkJS(cb) {
|
||||
this.events.request('blockchain:get', (web3) => {
|
||||
// global web3 used in the tests, not in the vm
|
||||
global.web3 = web3;
|
||||
this.vm = new VM({
|
||||
sandbox: {
|
||||
EmbarkJS,
|
||||
web3: web3,
|
||||
Web3: Web3,
|
||||
IpfsApi
|
||||
}
|
||||
});
|
||||
this.events.request("code-generator:embarkjs:provider-code", (code) => {
|
||||
this.vm.doEval(code, false, (err, _result) => {
|
||||
if(err) return cb(err);
|
||||
this.events.request("code-generator:embarkjs:init-provider-code", (code) => {
|
||||
this.vm.doEval(code, false, (err, _result) => {
|
||||
cb(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
this.events.request("runcode:embarkjs:reset", cb);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -339,7 +322,14 @@ class Test {
|
|||
|
||||
const testContractFactoryPlugin = self.plugins.getPluginsFor('testContractFactory').slice(-1)[0];
|
||||
|
||||
const newContract = testContractFactoryPlugin ? testContractFactoryPlugin.testContractFactory(contract, web3) : Test.getWeb3Contract(contract, web3);
|
||||
if (!testContractFactoryPlugin) {
|
||||
return self.getWeb3Contract(contract, web3, (err, web3Contract) => {
|
||||
Object.setPrototypeOf(self.contracts[contract.className], web3Contract);
|
||||
eachCb();
|
||||
});
|
||||
}
|
||||
|
||||
const newContract = testContractFactoryPlugin.testContractFactory(contract, web3);
|
||||
Object.setPrototypeOf(self.contracts[contract.className], newContract);
|
||||
|
||||
eachCb();
|
||||
|
@ -359,7 +349,7 @@ class Test {
|
|||
});
|
||||
}
|
||||
|
||||
static getWeb3Contract(contract, web3) {
|
||||
getWeb3Contract(contract, web3, cb) {
|
||||
const newContract = new EmbarkJS.Blockchain.Contract({
|
||||
abi: contract.abiDefinition,
|
||||
address: contract.deployedAddress,
|
||||
|
@ -378,11 +368,11 @@ class Test {
|
|||
newContract.options.gas = constants.tests.gasLimit;
|
||||
}
|
||||
|
||||
return newContract;
|
||||
cb(null, newContract);
|
||||
}
|
||||
|
||||
require(path) {
|
||||
const [contractsPrefix, embarkJSPrefix] = ['Embark/contracts/', 'Embark/EmbarkJS'];
|
||||
const contractsPrefix = 'Embark/contracts/';
|
||||
|
||||
// Contract require
|
||||
if (path.startsWith(contractsPrefix)) {
|
||||
|
@ -397,11 +387,6 @@ class Test {
|
|||
return newContract;
|
||||
}
|
||||
|
||||
// EmbarkJS require
|
||||
if (path.startsWith(embarkJSPrefix)) {
|
||||
return EmbarkJS;
|
||||
}
|
||||
|
||||
throw new Error(__('Unknown module %s', path));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
const web3Connector = {};
|
||||
|
||||
web3Connector.init = function(_config) {
|
||||
global.web3 = config.web3 || global.web3;
|
||||
// Check if the global web3 object uses the old web3 (0.x)
|
||||
if (global.web3 && typeof global.web3.version !== 'string') {
|
||||
// If so, use a new instance using 1.0, but use its provider
|
||||
|
|
Loading…
Reference in New Issue