diff --git a/remix-tests/src/compiler.ts b/remix-tests/src/compiler.ts index 34721198fa..28f768f260 100644 --- a/remix-tests/src/compiler.ts +++ b/remix-tests/src/compiler.ts @@ -72,7 +72,16 @@ function processFile(filePath: string, sources: SrcIfc, isRoot: boolean = false) const userAgent = (typeof (navigator) !== 'undefined') && navigator.userAgent ? navigator.userAgent.toLowerCase() : '-' const isBrowser = !(typeof (window) === 'undefined' || userAgent.indexOf(' electron/') > -1) -// TODO: replace this with remix's own compiler code +/** + * @dev Compile file or files before running tests (used for CLI execution) + * @param filename Name of file + * @param isDirectory True, if path is a directory + * @param opts Options + * @param cb Callback + * + * TODO: replace this with remix's own compiler code + */ + export function compileFileOrFiles(filename: string, isDirectory: boolean, opts: any, cb: Function) { let compiler: any const accounts: string[] = opts.accounts || [] @@ -125,11 +134,20 @@ export function compileFileOrFiles(filename: string, isDirectory: boolean, opts: if (!isBrowser) require('signale').fatal(errors) return cb(errors) } - cb(err, result.contracts, result.sources) + cb(err, result.contracts, result.sources) //return callback with contract details & ASTs }) } } +/** + * @dev Compile contract source before running tests (used for IDE tests execution) + * @param sources sources + * @param versionUrl url of selected compiler version to load + * @param usingWorker if true, load compiler using web worker + * @param importFileCb Import file callback + * @param opts Options + * @param cb Callback + */ export function compileContractSources(sources: SrcIfc, versionUrl: any, usingWorker: boolean, importFileCb: any, opts: any, cb: Function) { let compiler, filepath: string const accounts: string[] = opts.accounts || [] @@ -172,6 +190,6 @@ export function compileContractSources(sources: SrcIfc, versionUrl: any, usingWo if (!isBrowser) require('signale').fatal(errors) return cb(errors) } - cb(err, result.contracts, result.sources) + cb(err, result.contracts, result.sources) // return callback with contract details & ASTs }) } diff --git a/remix-tests/src/runTestFiles.ts b/remix-tests/src/runTestFiles.ts index a4d283c21f..f0b2e5f1f1 100644 --- a/remix-tests/src/runTestFiles.ts +++ b/remix-tests/src/runTestFiles.ts @@ -8,6 +8,14 @@ import Web3 = require('web3') import { compileFileOrFiles } from './compiler' import { deployAll } from './deployer' +/** + * @dev run test contract files (used for CLI) + * @param filepath Path of file + * @param isDirectory True, if path is a directory + * @param web3 Web3 + * @param opts Options + */ + export function runTestFiles(filepath: string, isDirectory: boolean, web3: Web3, opts?: object) { opts = opts || {} let sourceASTs: any = {} @@ -46,6 +54,7 @@ export function runTestFiles(filepath: string, isDirectory: boolean, web3: Web3, compileFileOrFiles(filepath, isDirectory, { accounts }, next) }, function deployAllContracts (compilationResult, asts, next: Function) { + // Extract AST of test contract file source for(const filename in asts) { if(filename.includes('_test.sol')) diff --git a/remix-tests/src/runTestSources.ts b/remix-tests/src/runTestSources.ts index addd437dee..d0fc218d3f 100644 --- a/remix-tests/src/runTestSources.ts +++ b/remix-tests/src/runTestSources.ts @@ -4,7 +4,7 @@ require('colors') import { compileContractSources } from './compiler' import { deployAll } from './deployer' import { runTest } from './testRunner' -import { TestResultInterface, ResultsInterface } from './types' +import { TestResultInterface } from './types' import Web3 = require('web3') import { Provider } from 'remix-simulator' @@ -18,6 +18,17 @@ const createWeb3Provider = async function () { return web3 } +/** + * @dev Run tests from source of a test contract file (used for IDE) + * @param contractSources Sources of contract + * @param versionUrl url of selected compiler version to load + * @param usingWorker if true, load compiler using web worker + * @param testCallback Test callback + * @param resultCallback Result Callback + * @param finalCallback Final Callback + * @param importFileCb Import file callback + * @param opts Options + */ export async function runTestSources(contractSources, versionUrl, usingWorker, testCallback, resultCallback, finalCallback, importFileCb, opts) { opts = opts || {} let sourceASTs: any = {} diff --git a/remix-tests/src/testRunner.ts b/remix-tests/src/testRunner.ts index 299a023d0e..b9095b1343 100644 --- a/remix-tests/src/testRunner.ts +++ b/remix-tests/src/testRunner.ts @@ -19,26 +19,45 @@ function getOverridedSender (userdoc, signature: string, methodIdentifiers) { return fullName && accountIndex ? accountIndex[1] : null } -function getAvailableFunctions (fileAST, testContractName) { - let contractAST: any[] = fileAST.nodes.filter(node => node.name === testContractName && node.nodeType === 'ContractDefinition') - let funcNodes: any[] = contractAST[0].nodes.filter(node => node.kind === 'function' && node.nodeType === "FunctionDefinition") - let funcList: string[] = funcNodes.map(node => node.name) +/** + * @dev returns functions of a test contract file in same sequence they appear in file (using passed AST) + * @param fileAST AST of test contract file source + * @param testContractName Name of test contract + */ + +function getAvailableFunctions (fileAST: any, testContractName: string) { + const contractAST: any[] = fileAST.nodes.filter(node => node.name === testContractName && node.nodeType === 'ContractDefinition') + const funcNodes: any[] = contractAST[0].nodes.filter(node => node.kind === 'function' && node.nodeType === "FunctionDefinition") + const funcList: string[] = funcNodes.map(node => node.name) return funcList; } -function getTestFunctionsInterface (jsonInterface, funcList: string[]) { - let resutantInterface: any[] = [] - let specialFunctions = ['beforeAll', 'beforeEach', 'afterAll', 'afterEach'] +/** + * @dev returns ABI of passed method list from passed interface + * @param jsonInterface Json Interface + * @param funcList Methods to extract the interface of + */ + +function getTestFunctionsInterface (jsonInterface: any, funcList: string[]) { + let functionsInterface: any[] = [] + const specialFunctions = ['beforeAll', 'beforeEach', 'afterAll', 'afterEach'] for(const func of funcList){ if(!specialFunctions.includes(func)) - resutantInterface.push(jsonInterface.find(node => node.type === 'function' && node.name === func)) + functionsInterface.push(jsonInterface.find(node => node.type === 'function' && node.name === func)) } - return resutantInterface + return functionsInterface } -function createRunList (jsonInterface, fileAST, testContractName): RunListInterface[] { - let availableFunctions = getAvailableFunctions(fileAST, testContractName) - let testFunctionsInterface = getTestFunctionsInterface(jsonInterface, availableFunctions) +/** + * @dev Prepare a list of tests to run using test contract file ABI, AST & contract name + * @param jsonInterface File JSON interface + * @param fileAST File AST + * @param testContractName Test contract name + */ + +function createRunList (jsonInterface: any, fileAST: any, testContractName: string): RunListInterface[] { + const availableFunctions: string[] = getAvailableFunctions(fileAST, testContractName) + const testFunctionsInterface: any[] = getTestFunctionsInterface(jsonInterface, availableFunctions) let runList: RunListInterface[] = [] @@ -46,7 +65,7 @@ function createRunList (jsonInterface, fileAST, testContractName): RunListInterf runList.push({ name: 'beforeAll', type: 'internal', constant: false }) } - for (let func of testFunctionsInterface) { + for (const func of testFunctionsInterface) { if (availableFunctions.indexOf('beforeEach') >= 0) { runList.push({ name: 'beforeEach', type: 'internal', constant: false }) } @@ -64,11 +83,11 @@ function createRunList (jsonInterface, fileAST, testContractName): RunListInterf } export function runTest (testName, testObject: any, contractDetails: any, fileAST: any, opts: any, testCallback: TestCbInterface, resultsCallback: ResultCbInterface) { - let runList = createRunList(testObject._jsonInterface, fileAST, testName) + const runList: RunListInterface[] = createRunList(testObject._jsonInterface, fileAST, testName) let passingNum: number = 0 let failureNum: number = 0 let timePassed: number = 0 - let web3 = new Web3() + const web3 = new Web3() const accts: TestResultInterface = { type: 'accountList', @@ -95,11 +114,11 @@ export function runTest (testName, testObject: any, contractDetails: any, fileAS let sendParams if (sender) sendParams = { from: sender } - let method = testObject.methods[func.name].apply(testObject.methods[func.name], []) - let startTime = Date.now() + const method = testObject.methods[func.name].apply(testObject.methods[func.name], []) + const startTime = Date.now() if (func.constant) { method.call(sendParams).then((result) => { - let time = (Date.now() - startTime) / 1000.0 + const time = (Date.now() - startTime) / 1000.0 if (result) { const resp: TestResultInterface = { type: 'testPass', @@ -126,12 +145,12 @@ export function runTest (testName, testObject: any, contractDetails: any, fileAS } else { method.send(sendParams).on('receipt', (receipt) => { try { - let time: number = (Date.now() - startTime) / 1000.0 - let topic = Web3.utils.sha3('AssertionEvent(bool,string)') + const time: number = (Date.now() - startTime) / 1000.0 + const topic = Web3.utils.sha3('AssertionEvent(bool,string)') let testPassed: boolean = false - for (let i in receipt.events) { - let event = receipt.events[i] + for (const i in receipt.events) { + const event = receipt.events[i] if (event.raw.topics.indexOf(topic) >= 0) { const testEvent = web3.eth.abi.decodeParameters(['bool', 'string'], event.raw.data) if (!testEvent[0]) { @@ -168,7 +187,7 @@ export function runTest (testName, testObject: any, contractDetails: any, fileAS } }).on('error', function (err: any) { console.error(err) - let time: number = (Date.now() - startTime) / 1000.0 + const time: number = (Date.now() - startTime) / 1000.0 const resp: TestResultInterface = { type: 'testFailure', value: changeCase.sentenceCase(func.name), diff --git a/remix-tests/tests/testRunner.ts b/remix-tests/tests/testRunner.ts index ff7151bded..9fdceba2ef 100644 --- a/remix-tests/tests/testRunner.ts +++ b/remix-tests/tests/testRunner.ts @@ -103,7 +103,7 @@ describe('testRunner', () => { describe('#runTest', () => { describe('test with beforeAll', () => { - let filename: string = 'tests/examples_1/simple_storage_test.sol' + const filename: string = 'tests/examples_1/simple_storage_test.sol' before((done) => { compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[]) => { @@ -134,7 +134,7 @@ describe('testRunner', () => { }) describe('test with beforeEach', function () { - let filename = 'tests/examples_2/simple_storage_test.sol' + const filename: string = 'tests/examples_2/simple_storage_test.sol' before(function (done) { compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[]) { @@ -164,7 +164,7 @@ describe('testRunner', () => { // Test string equality describe('test string equality', function () { - let filename = 'tests/examples_3/simple_string_test.sol' + const filename: string = 'tests/examples_3/simple_string_test.sol' before(function (done) { compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[]) { @@ -190,7 +190,7 @@ describe('testRunner', () => { // Test multiple directory import in test contract describe('test multiple directory import in test contract', function () { - let filename = 'tests/examples_5/test/simple_storage_test.sol' + const filename: string = 'tests/examples_5/test/simple_storage_test.sol' before(function (done) { compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[]) { @@ -217,7 +217,7 @@ describe('testRunner', () => { //Test signed/unsigned integer weight describe('test number weight', function () { - let filename = 'tests/number/number_test.sol' + const filename: string = 'tests/number/number_test.sol' before(function (done) { compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[]) { @@ -237,7 +237,7 @@ describe('testRunner', () => { // Test Transaction with different sender describe('various sender', function () { - let filename = 'tests/various_sender/sender_test.sol' + const filename: string = 'tests/various_sender/sender_test.sol' before(function (done) { compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[]) {