diff --git a/lib/constants.json b/lib/constants.json new file mode 100644 index 00000000..ff5e643d --- /dev/null +++ b/lib/constants.json @@ -0,0 +1,3 @@ +{ + "httpContractsDirectory": ".embark/contracts/" +} diff --git a/lib/core/config.js b/lib/core/config.js index a77185d6..f83c1827 100644 --- a/lib/core/config.js +++ b/lib/core/config.js @@ -3,8 +3,7 @@ const File = require('./file.js'); const Plugins = require('./plugins.js'); const utils = require('../utils/utils.js'); const path = require('path'); - -const httpContractDir = '.embark/contracts/'; +const constants = require('../constants'); var Config = function(options) { this.env = options.env; @@ -152,7 +151,7 @@ Config.prototype.getExternalContractUrl = function (contract) { const match = contract.file.match(/https:\/\/github\.[a-z]+\/(.*)/); if (!match) { this.logger.error(MALFORMED_ERROR + contract.file); - return ''; + return null; } url = `${RAW_URL}${match[1].replace('blob/', '')}`; } else if (contract.file.startsWith('git')) { @@ -164,11 +163,11 @@ Config.prototype.getExternalContractUrl = function (contract) { // [4] path // [5] branch const match = contract.file.match( - /(git:\/\/)?github\.[a-z]+\/([a-zA-Z0-9_\-.]+)\/([a-zA-Z0-9_\-7]+)\/([a-zA-Z0-9_\-\/.]+)#?([a-zA-Z0-1_\-.]*)?/ + /(git:\/\/)?github\.[a-z]+\/([a-zA-Z0-9_\-.]+)\/([a-zA-Z0-9_\-]+)\/([a-zA-Z0-9_\-\/.]+)#?([a-zA-Z0-1_\-.]*)?/ ); if (!match) { this.logger.error(MALFORMED_ERROR + contract.file); - return ''; + return null; } let branch = match[5]; if (!branch) { @@ -178,7 +177,13 @@ Config.prototype.getExternalContractUrl = function (contract) { } else { url = contract.file; } - return url; + const match = url.match( + /\.[a-z]+\/([a-zA-Z0-9_\-\/.]+)/ + ); + return { + url, + filePath: match[1] + }; }; Config.prototype.loadExternalContractsFiles = function() { @@ -189,9 +194,12 @@ Config.prototype.loadExternalContractsFiles = function() { continue; } if (contract.file.startsWith('http') || contract.file.startsWith('git')) { - const url = this.getExternalContractUrl(contract); - const localFile = httpContractDir + path.basename(url); - this.contractsFiles.push(new File({filename: localFile, type: File.types.http, basedir: '', path: url})); + const fileObj = this.getExternalContractUrl(contract); + if (!fileObj) { + return this.logger.error("HTTP contract file not found: " + contract.file); + } + const localFile = constants.httpContractsDirectory + fileObj.filePath; + this.contractsFiles.push(new File({filename: localFile, type: File.types.http, basedir: '', path: fileObj.url})); } else if (fs.existsSync(contract.file)) { this.contractsFiles.push(new File({filename: contract.file, type: File.types.dapp_file, basedir: '', path: contract.file})); } else if (fs.existsSync(path.join('./node_modules/', contract.file))) { @@ -259,7 +267,7 @@ Config.prototype.loadEmbarkConfigFile = function() { }).map((dir) => { return dir.split("*.")[0]; }); - this.contractDirectories.push(httpContractDir); + this.contractDirectories.push(constants.httpContractsDirectory); this.buildDir = this.embarkConfig.buildDir; this.configDir = this.embarkConfig.config; diff --git a/lib/core/file.js b/lib/core/file.js index 09498fc9..c2a65dd9 100644 --- a/lib/core/file.js +++ b/lib/core/file.js @@ -13,11 +13,35 @@ class File { this.resolver = options.resolver; } - downloadFile (callback) { + parseFileForImport(content, callback) { + const self = this; + if (self.filename.indexOf('.sol') < 0) { + // Only supported in Solidity + return callback(); + } + const regex = /import "([a-zA-Z0-9_\-.\\\/]+)";/g; + let matches; + const filesToDownload = []; + const pathWithoutFile = path.dirname(self.path); + while ((matches = regex.exec(content))) { + filesToDownload.push({ + fileRelativePath: path.join(path.dirname(self.filename), matches[1]), + url: `${pathWithoutFile}/${matches[1]}` + }); + } + + async.each(filesToDownload, ((fileObj, eachCb) => { + self.downloadFile(fileObj.fileRelativePath, fileObj.url, (_content) => { + eachCb(); + }); + }), callback); + } + + downloadFile (filename, url, callback) { const self = this; async.waterfall([ function makeTheDir(next) { - fs.mkdirp(path.dirname(self.filename), (err) => { + fs.mkdirp(path.dirname(filename), (err) => { if (err) { return next(err); } @@ -25,22 +49,23 @@ class File { }); }, function downloadTheFile(next) { - request(self.path) + request(url) .on('response', function (response) { if (response.statusCode !== 200) { next('Getting file returned code ' + response.statusCode); } }) .on('error', next) - .pipe(fs.createWriteStream(self.filename)) - .on('finish', () => { - self.path = self.filename; - self.type = File.types.dapp_file; - next(); - }); + .pipe(fs.createWriteStream(filename)) + .on('finish', next); }, function readFile(next) { - fs.readFile(self.path, next); + fs.readFile(filename, next); + }, + function parseForImports(content, next) { + self.parseFileForImport(content, (err) => { + next(err, content); + }); } ], (err, content) => { if (err) { @@ -59,7 +84,14 @@ class File { } else if (this.type === File.types.custom) { return this.resolver(callback); } else if (this.type === File.types.http) { - this.downloadFile(callback); + this.downloadFile(this.filename, this.path, (content) => { + if (!content) { + return callback(content); + } + this.path = this.filename; + this.type = File.types.dapp_file; + callback(content); + }); } else { throw new Error("unknown file: " + this.filename); } diff --git a/lib/modules/solidity/solcP.js b/lib/modules/solidity/solcP.js index 2922c088..8042ed83 100644 --- a/lib/modules/solidity/solcP.js +++ b/lib/modules/solidity/solcP.js @@ -1,7 +1,8 @@ let solc; -let fs = require('fs-extra'); -let path = require('path'); +const fs = require('fs-extra'); +const path = require('path'); +const constants = require('../../constants'); function findImports(filename) { if (fs.existsSync(filename)) { @@ -10,6 +11,9 @@ function findImports(filename) { if (fs.existsSync(path.join('./node_modules/', filename))) { return {contents: fs.readFileSync(path.join('./node_modules/', filename)).toString()}; } + if (fs.existsSync(path.join(constants.httpContractsDirectory, filename))) { + return {contents: fs.readFileSync(path.join('./.embark/contracts', filename)).toString()}; + } return {error: 'File not found'}; } diff --git a/package-lock.json b/package-lock.json index 3eca91aa..4461c466 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,14 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@sinonjs/formatio": { + "version": "2.0.0", + "resolved": "http://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", + "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==", + "requires": { + "samsam": "1.3.0" + } + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -3077,15 +3085,6 @@ "mime-types": "2.1.18" } }, - "formatio": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", - "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=", - "dev": true, - "requires": { - "samsam": "1.1.2" - } - }, "forwarded": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", @@ -5468,6 +5467,11 @@ "verror": "1.10.0" } }, + "just-extend": { + "version": "1.1.27", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-1.1.27.tgz", + "integrity": "sha512-mJVp13Ix6gFo3SBAy9U/kL+oeZqzlYYYLQBwXVBlVzIsZwBqGREnOro24oC/8s8aox+rJhtZ2DiQof++IrkA+g==" + }, "keccakjs": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/keccakjs/-/keccakjs-0.2.1.tgz", @@ -5701,6 +5705,11 @@ "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", "integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=" }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, "lodash.map": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", @@ -5737,10 +5746,9 @@ "integrity": "sha1-5QndTEVcGu190QWhdpTapbmsV58=" }, "lolex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", - "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", - "dev": true + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.3.2.tgz", + "integrity": "sha512-A5pN2tkFj7H0dGIAM6MFvHKMJcPnjZsOMvR7ujCjfgW5TbV6H9vb1PgxLtHvjqNZTHsUolz+6/WEO0N1xNx2ng==" }, "longest": { "version": "1.0.1", @@ -6421,6 +6429,33 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.0.tgz", "integrity": "sha1-drHIIxMMyias+6zMj7rwovozsY8=" }, + "nise": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.3.3.tgz", + "integrity": "sha512-v1J/FLUB9PfGqZLGDBhQqODkbLotP0WtLo9R4EJY2PPu5f5Xg4o0rA8FDlmrjFSv9vBBKcfnOSpfYYuu5RTHqg==", + "requires": { + "@sinonjs/formatio": "2.0.0", + "just-extend": "1.1.27", + "lolex": "2.3.2", + "path-to-regexp": "1.7.0", + "text-encoding": "0.6.4" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "path-to-regexp": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", + "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", + "requires": { + "isarray": "0.0.1" + } + } + } + }, "node-forge": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.4.tgz", @@ -8347,10 +8382,9 @@ } }, "samsam": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", - "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=", - "dev": true + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", + "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==" }, "sax": { "version": "1.2.4", @@ -8594,15 +8628,37 @@ } }, "sinon": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", - "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=", - "dev": true, + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.5.0.tgz", + "integrity": "sha512-trdx+mB0VBBgoYucy6a9L7/jfQOmvGeaKZT4OOJ+lPAtI8623xyGr8wLiE4eojzBS8G9yXbhx42GHUOVLr4X2w==", "requires": { - "formatio": "1.1.1", - "lolex": "1.3.2", - "samsam": "1.1.2", - "util": "0.10.3" + "@sinonjs/formatio": "2.0.0", + "diff": "3.5.0", + "lodash.get": "4.4.2", + "lolex": "2.3.2", + "nise": "1.3.3", + "supports-color": "5.4.0", + "type-detect": "4.0.8" + }, + "dependencies": { + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } } }, "slash": { @@ -9511,6 +9567,11 @@ } } }, + "text-encoding": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", + "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=" + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -9690,6 +9751,11 @@ "prelude-ls": "1.1.2" } }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + }, "type-is": { "version": "1.6.16", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", diff --git a/package.json b/package.json index fd8a1d65..e34b98e4 100644 --- a/package.json +++ b/package.json @@ -88,6 +88,6 @@ "matchdep": "^1.0.1", "mocha": "^3.2.0", "mocha-sinon": "^1.1.4", - "sinon": "^1.15.4" + "sinon": "^4.5.0" } } diff --git a/test/config.js b/test/config.js index 82c1485a..0f8af614 100644 --- a/test/config.js +++ b/test/config.js @@ -59,72 +59,89 @@ describe('embark.Config', function () { describe('#getExternalContractUrl', function () { it('should get the right url for a https://github file', function () { - const url = config.getExternalContractUrl( + const fileObj = config.getExternalContractUrl( {file: 'https://github.com/embark-framework/embark/blob/master/test_app/app/contracts/simple_storage.sol'} ); - assert.strictEqual(url, - 'https://raw.githubusercontent.com/embark-framework/embark/master/test_app/app/contracts/simple_storage.sol'); + assert.deepEqual(fileObj, + { + filePath: 'embark-framework/embark/master/test_app/app/contracts/simple_storage.sol', + url: 'https://raw.githubusercontent.com/embark-framework/embark/master/test_app/app/contracts/simple_storage.sol' + }); }); it('should fail for a malformed https://github file', function () { - const url = config.getExternalContractUrl( + const fileObj = config.getExternalContractUrl( {file: 'https://github/embark-framework/embark/blob/master/test_app/app/contracts/simple_storage.sol'} ); - assert.strictEqual(url, ''); + assert.strictEqual(fileObj, null); }); it('should get the right url for a git:// file with no branch #', function () { - const url = config.getExternalContractUrl( + const fileObj = config.getExternalContractUrl( {file: 'git://github.com/status-im/contracts/contracts/identity/ERC725.sol'} ); - console.log(url); - assert.strictEqual(url, - 'https://raw.githubusercontent.com/status-im/contracts/master/contracts/identity/ERC725.sol'); + assert.deepEqual(fileObj, + { + filePath: 'status-im/contracts/master/contracts/identity/ERC725.sol', + url: 'https://raw.githubusercontent.com/status-im/contracts/master/contracts/identity/ERC725.sol' + }); }); it('should get the right url for a git:// file with a branch #', function () { - const url = config.getExternalContractUrl( + const fileObj = config.getExternalContractUrl( {file: 'git://github.com/status-im/contracts/contracts/identity/ERC725.sol#myBranch'} ); - assert.strictEqual(url, - 'https://raw.githubusercontent.com/status-im/contracts/myBranch/contracts/identity/ERC725.sol'); + assert.deepEqual(fileObj, + { + filePath: 'status-im/contracts/myBranch/contracts/identity/ERC725.sol', + url: 'https://raw.githubusercontent.com/status-im/contracts/myBranch/contracts/identity/ERC725.sol' + }); }); it('should fail when the git:// file is malformed', function () { - const url = config.getExternalContractUrl( + const fileObj = config.getExternalContractUrl( {file: 'git://github.com/identity/ERC725.sol#myBranch'} ); - assert.strictEqual(url, ''); + assert.strictEqual(fileObj, null); }); it('should get the right url with a github.com file without branch #', function () { - const url = config.getExternalContractUrl( + const fileObj = config.getExternalContractUrl( {file: 'github.com/status-im/contracts/contracts/identity/ERC725.sol'} ); - assert.strictEqual(url, - 'https://raw.githubusercontent.com/status-im/contracts/master/contracts/identity/ERC725.sol'); + assert.deepEqual(fileObj, + { + filePath: 'status-im/contracts/master/contracts/identity/ERC725.sol', + url: 'https://raw.githubusercontent.com/status-im/contracts/master/contracts/identity/ERC725.sol' + }); }); it('should get the right url with a github.com file with branch #', function () { - const url = config.getExternalContractUrl( + const fileObj = config.getExternalContractUrl( {file: 'github.com/status-im/contracts/contracts/identity/ERC725.sol#theBranch'} ); - assert.strictEqual(url, - 'https://raw.githubusercontent.com/status-im/contracts/theBranch/contracts/identity/ERC725.sol'); + assert.deepEqual(fileObj, + { + filePath: 'status-im/contracts/theBranch/contracts/identity/ERC725.sol', + url: 'https://raw.githubusercontent.com/status-im/contracts/theBranch/contracts/identity/ERC725.sol' + }); }); it('should fail with a malformed github.com url', function () { - const url = config.getExternalContractUrl( + const fileObj = config.getExternalContractUrl( {file: 'github/status-im/contracts/contracts/identity/ERC725.sol#theBranch'} ); - assert.strictEqual(url, ''); + assert.strictEqual(fileObj, null); }); it('should succeed with a generic http url', function () { - const url = config.getExternalContractUrl( + const fileObj = config.getExternalContractUrl( {file: 'http://myurl.com/myFile.sol'} ); - assert.strictEqual(url, 'http://myurl.com/myFile.sol'); + assert.deepEqual(fileObj, { + filePath: 'myFile.sol', + url: 'http://myurl.com/myFile.sol' + }); }); }); @@ -141,14 +158,14 @@ describe('embark.Config', function () { ]; const expected = [ { - "filename": ".embark/contracts/simple_storage.sol", + "filename": ".embark/contracts/embark-framework/embark/master/test_app/app/contracts/simple_storage.sol", "type": "http", "path": "https://raw.githubusercontent.com/embark-framework/embark/master/test_app/app/contracts/simple_storage.sol", "basedir": "", "resolver": undefined }, { - "filename": ".embark/contracts/ERC725.sol", + "filename": ".embark/contracts/status-im/contracts/master/contracts/identity/ERC725.sol", "type": "http", "path": "https://raw.githubusercontent.com/status-im/contracts/master/contracts/identity/ERC725.sol", "basedir": "", diff --git a/test/contracts/contract_with_import.sol b/test/contracts/contract_with_import.sol new file mode 100644 index 00000000..7a07a304 --- /dev/null +++ b/test/contracts/contract_with_import.sol @@ -0,0 +1,19 @@ +pragma solidity ^0.4.7; +contract SimpleStorage { + uint public storedData; + import "./ownable.sol"; + + function SimpleStorage(uint initialValue) { + storedData = initialValue; + } + + function set(uint x) { + storedData = x; + } + + function get() constant returns (uint retVal) { + return storedData; + } + +} + diff --git a/test/file.js b/test/file.js new file mode 100644 index 00000000..1fb47405 --- /dev/null +++ b/test/file.js @@ -0,0 +1,29 @@ +/*globals describe, it*/ +const File = require('../lib/core/file'); +const fs = require('fs-extra'); +const path = require('path'); +const assert = require('assert'); +const sinon = require('sinon'); + +describe('embark.File', function () { + describe('parseFileForImport', () => { + it('should find all the imports', function (done) { + const contract = fs.readFileSync('./test/contracts/contract_with_import.sol').toString(); + const file = new File({filename: '.embark/contracts/embark-framework/embark/master/test_app/app/contracts/simple_storage.sol', + path: 'https://raw.githubusercontent.com/embark-framework/embark/develop/test_apps/test_app/app/contracts/simple_storage.sol'}); + const downloadFileStub = sinon.stub(file, 'downloadFile') + .callsFake((path, url, cb) => { + cb(); + }); + + file.parseFileForImport(contract, () => { + assert.strictEqual(downloadFileStub.callCount, 1); + assert.strictEqual(downloadFileStub.firstCall.args[0], + path.normalize('.embark/contracts/embark-framework/embark/master/test_app/app/contracts/ownable.sol')); + assert.strictEqual(downloadFileStub.firstCall.args[1], + 'https://raw.githubusercontent.com/embark-framework/embark/develop/test_apps/test_app/app/contracts/./ownable.sol'); + done(); + }); + }); + }); +}); diff --git a/test_apps/test_app/config/contracts.json b/test_apps/test_app/config/contracts.json index 3ae09f34..4f59c276 100644 --- a/test_apps/test_app/config/contracts.json +++ b/test_apps/test_app/config/contracts.json @@ -72,8 +72,8 @@ 1000 ] }, - "ERC725": { - "file": "https://github.com/status-im/contracts/blob/master/contracts/identity/ERC725.sol" + "Identity": { + "file": "https://github.com/status-im/contracts/blob/master/contracts/identity/Identity.sol" } }, "afterDeploy": [ diff --git a/test_apps/test_app/test/http_contract_test.js b/test_apps/test_app/test/http_contract_test.js index 0c515f1d..c1cddd67 100644 --- a/test_apps/test_app/test/http_contract_test.js +++ b/test_apps/test_app/test/http_contract_test.js @@ -3,16 +3,24 @@ const fs = require('fs-extra'); const assert = require('assert'); describe('http contracts', () => { - describe('ERC725', () => { - const contractPath = '.embark/contracts/ERC725.sol'; + const contractPath = '.embark/contracts/status-im/contracts/master/contracts/identity/Identity.sol'; + const contractImportPath = '.embark/contracts/status-im/contracts/master/contracts/identity/ERC725.sol'; - it('should have downloaded the file in .embark/contracts', (done) => { - fs.access(contractPath, (err) => { - if (err) { - assert.fail(contractPath + ' was not downloaded'); - } - done(); - }); + it('should have downloaded the file in .embark/contracts', (done) => { + fs.access(contractPath, (err) => { + if (err) { + assert.fail(contractPath + ' was not downloaded'); + } + done(); + }); + }); + + it('should have downloaded the file import file too', (done) => { + fs.access(contractImportPath, (err) => { + if (err) { + assert.fail(contractPath + ' was not downloaded'); + } + done(); }); }); });