diff --git a/apps/remix-ide/src/app/tabs/test-tab.js b/apps/remix-ide/src/app/tabs/test-tab.js index 313f66c529..117a88769c 100644 --- a/apps/remix-ide/src/app/tabs/test-tab.js +++ b/apps/remix-ide/src/app/tabs/test-tab.js @@ -7,7 +7,7 @@ var async = require('async') var tooltip = require('../ui/tooltip') var Renderer = require('../ui/renderer') var css = require('./styles/test-tab-styles') -var { UnitTestRunner } = require('@remix-project/remix-tests') +var { UnitTestRunner, assertLibCode } = require('@remix-project/remix-tests') const _paq = window._paq = window._paq || [] @@ -79,6 +79,12 @@ module.exports = class TestTab extends ViewPlugin { if (!isSolidityActive) { await this.call('manager', 'activatePlugin', 'solidity') } + await this.testRunner.init() + const provider = await this.fileManager.getProviderOf() + if (provider) { + provider.addExternal('.deps/remix-tests/remix_tests.sol', assertLibCode, 'remix_tests.sol') + provider.addExternal('.deps/remix-tests/remix_accounts.sol', this.testRunner.accountsLibCode, 'remix_accounts.sol') + } this.updateRunAction() } diff --git a/libs/remix-core-plugin/src/lib/compiler-content-imports.ts b/libs/remix-core-plugin/src/lib/compiler-content-imports.ts index 3dc0e05778..8c243e37a8 100644 --- a/libs/remix-core-plugin/src/lib/compiler-content-imports.ts +++ b/libs/remix-core-plugin/src/lib/compiler-content-imports.ts @@ -1,8 +1,6 @@ 'use strict' import { Plugin } from '@remixproject/engine' import { RemixURLResolver } from '@remix-project/remix-url-resolver' -// const remixTests = require('@remix-project/remix-tests') -var { assertLibCode, getAccountsLib } = require('@remix-project/remix-tests') const profile = { name: 'contentImport', @@ -107,15 +105,6 @@ export class CompilerImports extends Plugin { }) } - async importTestFiles (url) { - const provider = await this.call('fileManager', 'getProviderOf', null) - let content - if (url === 'remix_tests.sol' || url === 'tests.sol') content = assertLibCode - else if (url === 'remix_accounts.sol') content = getAccountsLib() - if (provider) provider.addExternal('.deps/remix-tests/' + url, content, url) - return content - } - /** * import the content of @arg url. * first look in the browser localstorage (browser explorer) or locahost explorer. if the url start with `browser/*` or `localhost/*` @@ -127,7 +116,6 @@ export class CompilerImports extends Plugin { * @returns {Promise} - string content */ async resolveAndSave (url, targetPath) { - if (['remix_tests.sol', 'tests.sol', 'remix_accounts.sol'].includes(url)) return await this.importTestFiles(url) try { const provider = await this.call('fileManager', 'getProviderOf', url) if (provider) { diff --git a/libs/remix-tests/src/compiler.ts b/libs/remix-tests/src/compiler.ts index 299b121b62..f4b9250ecf 100644 --- a/libs/remix-tests/src/compiler.ts +++ b/libs/remix-tests/src/compiler.ts @@ -6,18 +6,13 @@ import { Compiler as RemixCompiler } from '@remix-project/remix-solidity' import { SrcIfc, CompilerConfiguration, CompilationErrors } from './types' const logger = new Log() const log = logger.logger -var accountsLibCode - -export function getAccountsLib () { - return accountsLibCode -} function regexIndexOf (inputString: string, regex: RegExp, startpos = 0) { const indexOf = inputString.substring(startpos).search(regex) return (indexOf >= 0) ? (indexOf + (startpos)) : indexOf } -function writeTestAccountsContract (accounts: string[]) { +export function writeTestAccountsContract (accounts: string[]) { const testAccountContract = require('../sol/tests_accounts.sol') let body = `address[${accounts.length}] memory accounts;` if (!accounts.length) body += ';' @@ -26,7 +21,7 @@ function writeTestAccountsContract (accounts: string[]) { body += `\n\t\taccounts[${index}] = ${address};\n` }) } - accountsLibCode = testAccountContract.replace('>accounts<', body) + return testAccountContract.replace('>accounts<', body) } /** @@ -92,11 +87,10 @@ const isBrowser = !(typeof (window) === 'undefined' || userAgent.indexOf(' elect export function compileFileOrFiles (filename: string, isDirectory: boolean, opts: any, compilerConfig: CompilerConfiguration, cb): void { let compiler: any const accounts: string[] = opts.accounts || [] - writeTestAccountsContract(accounts) const sources: SrcIfc = { 'tests.sol': { content: require('../sol/tests.sol') }, 'remix_tests.sol': { content: require('../sol/tests.sol') }, - 'remix_accounts.sol': { content: getAccountsLib() } + 'remix_accounts.sol': { content: writeTestAccountsContract(accounts) } } const filepath: string = (isDirectory ? filename : path.dirname(filename)) try { @@ -178,8 +172,6 @@ export function compileFileOrFiles (filename: string, isDirectory: boolean, opts */ export function compileContractSources (sources: SrcIfc, compilerConfig: CompilerConfiguration, importFileCb: any, opts: any, cb): void { let compiler - const accounts: string[] = opts.accounts || [] - writeTestAccountsContract(accounts) const filepath = opts.testFilePath || '' const testFileImportRegEx = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm diff --git a/libs/remix-tests/src/index.ts b/libs/remix-tests/src/index.ts index 986fb061c1..37862a47c6 100644 --- a/libs/remix-tests/src/index.ts +++ b/libs/remix-tests/src/index.ts @@ -3,4 +3,4 @@ export { UnitTestRunner } from './runTestSources' export { runTest } from './testRunner' export * from './types' export const assertLibCode = require('../sol/tests.sol') -export { getAccountsLib } from './compiler' +export { writeTestAccountsContract } from './compiler' diff --git a/libs/remix-tests/src/runTestSources.ts b/libs/remix-tests/src/runTestSources.ts index ecc35aa3f2..33825fbc91 100644 --- a/libs/remix-tests/src/runTestSources.ts +++ b/libs/remix-tests/src/runTestSources.ts @@ -1,9 +1,7 @@ import async, { ErrorCallback } from 'async' - -import { compileContractSources } from './compiler' +import { compileContractSources, writeTestAccountsContract } from './compiler' import { deployAll } from './deployer' import { runTest } from './testRunner' - import Web3 from 'web3' import { EventEmitter } from 'events' import { Provider, extend } from '@remix-project/remix-simulator' @@ -15,13 +13,22 @@ require('colors') export class UnitTestRunner { event + accountsLibCode + testsAccounts: string[] | null + web3 constructor () { this.event = new EventEmitter() } - async createWeb3Provider () { - const web3 = new Web3() + async init (web3 = null, accounts = null) { + this.web3 = await this.createWeb3Provider(web3) + this.testsAccounts = accounts || await this.web3.eth.getAccounts() + this.accountsLibCode = writeTestAccountsContract(this.testsAccounts) + } + + async createWeb3Provider (optWeb3) { + const web3 = optWeb3 || new Web3() const provider: any = new Provider() await provider.init() web3.setProvider(provider) @@ -42,30 +49,23 @@ export class UnitTestRunner { async runTestSources (contractSources: SrcIfc, compilerConfig: CompilerConfiguration, testCallback, resultCallback, deployCb:any, finalCallback: any, importFileCb, opts: Options) { opts = opts || {} const sourceASTs: any = {} - const web3 = opts.web3 || await this.createWeb3Provider() - let accounts: string[] | null = opts.accounts || null + if (opts.web3 || opts.accounts) this.init(opts.web3, opts.accounts) + async.waterfall([ - function getAccountList (next) { - if (accounts) return next() - web3.eth.getAccounts((_err, _accounts) => { - accounts = _accounts - next() - }) - }, (next) => { - compileContractSources(contractSources, compilerConfig, importFileCb, { accounts, testFilePath: opts.testFilePath, event: this.event }, next) + compileContractSources(contractSources, compilerConfig, importFileCb, { accounts: this.testsAccounts, testFilePath: opts.testFilePath, event: this.event }, next) }, - function deployAllContracts (compilationResult: compilationInterface, asts: ASTInterface, next) { + (compilationResult: compilationInterface, asts: ASTInterface, next) => { for (const filename in asts) { if (filename.endsWith('_test.sol')) { sourceASTs[filename] = asts[filename].ast } } - deployAll(compilationResult, web3, false, deployCb, (err, contracts) => { + deployAll(compilationResult, this.web3, false, deployCb, (err, contracts) => { if (err) { // If contract deployment fails because of 'Out of Gas' error, try again with double gas // This is temporary, should be removed when remix-tests will have a dedicated UI to // accept deployment params from UI if (err.message.includes('The contract code couldn\'t be stored, please check your gas limit')) { - deployAll(compilationResult, web3, true, deployCb, (error, contracts) => { + deployAll(compilationResult, this.web3, true, deployCb, (error, contracts) => { if (error) next([{ message: 'contract deployment failed after trying twice: ' + error.message, severity: 'error' }]) // IDE expects errors in array else next(null, compilationResult, contracts) }) @@ -88,7 +88,7 @@ export class UnitTestRunner { } next(null, contractsToTest, contractsToTestDetails, contracts) }, - function runTests (contractsToTest: string[], contractsToTestDetails: any[], contracts: any, next) { + (contractsToTest: string[], contractsToTestDetails: any[], contracts: any, next) => { let totalPassing = 0 let totalFailing = 0 let totalTime = 0 @@ -111,7 +111,7 @@ export class UnitTestRunner { async.eachOfLimit(contractsToTest, 1, (contractName: string, index: string | number, cb: ErrorCallback) => { const fileAST: AstNode = sourceASTs[contracts[contractName]['filename']] - runTest(contractName, contracts[contractName], contractsToTestDetails[index], fileAST, { accounts, web3 }, _testCallback, (err, result) => { + runTest(contractName, contracts[contractName], contractsToTestDetails[index], fileAST, { accounts: this.testsAccounts, web3: this.web3 }, _testCallback, (err, result) => { if (err) { return cb(err) }