Unverified Commit c5e80f99 authored by Rob's avatar Rob Committed by GitHub

Merge branch 'master' into remixd_terminal

parents 860af891 983bee53
...@@ -4,6 +4,9 @@ import { CompilationOutput, Sources } from '@remix-ui/debugger-ui' ...@@ -4,6 +4,9 @@ import { CompilationOutput, Sources } from '@remix-ui/debugger-ui'
import type { CompilationResult } from '@remix-project/remix-solidity-ts' import type { CompilationResult } from '@remix-project/remix-solidity-ts'
export const DebuggerApiMixin = (Base) => class extends Base { export const DebuggerApiMixin = (Base) => class extends Base {
initialWeb3
initDebuggerApi () { initDebuggerApi () {
this.debugHash = null this.debugHash = null
...@@ -16,6 +19,8 @@ export const DebuggerApiMixin = (Base) => class extends Base { ...@@ -16,6 +19,8 @@ export const DebuggerApiMixin = (Base) => class extends Base {
} }
} }
this._web3 = new Web3(this.web3Provider) this._web3 = new Web3(this.web3Provider)
// this._web3 can be overwritten and reset to initial value in 'debug' method
this.initialWeb3 = this._web3
remixDebug.init.extendWeb3(this._web3) remixDebug.init.extendWeb3(this._web3)
this.offsetToLineColumnConverter = { this.offsetToLineColumnConverter = {
...@@ -123,7 +128,9 @@ export const DebuggerApiMixin = (Base) => class extends Base { ...@@ -123,7 +128,9 @@ export const DebuggerApiMixin = (Base) => class extends Base {
debug (hash, web3?) { debug (hash, web3?) {
this.debugHash = hash this.debugHash = hash
if (web3) remixDebug.init.extendWeb3(web3) if (web3) this._web3 = web3
else this._web3 = this.initialWeb3
remixDebug.init.extendWeb3(this._web3)
if (this.onDebugRequestedListener) this.onDebugRequestedListener(hash, web3) if (this.onDebugRequestedListener) this.onDebugRequestedListener(hash, web3)
} }
......
...@@ -232,7 +232,7 @@ module.exports = { ...@@ -232,7 +232,7 @@ module.exports = {
.removeFile('tests/ballotFailedLog_test.sol', 'workspace_new') .removeFile('tests/ballotFailedLog_test.sol', 'workspace_new')
}, },
'Debug failed test using debugger': function (browser: NightwatchBrowser) { 'Debug tests using debugger': function (browser: NightwatchBrowser) {
browser browser
.waitForElementPresent('*[data-id="verticalIconsKindfilePanel"]') .waitForElementPresent('*[data-id="verticalIconsKindfilePanel"]')
.addFile('tests/ballotFailedDebug_test.sol', sources[0]['tests/ballotFailedDebug_test.sol']) .addFile('tests/ballotFailedDebug_test.sol', sources[0]['tests/ballotFailedDebug_test.sol'])
...@@ -242,20 +242,50 @@ module.exports = { ...@@ -242,20 +242,50 @@ module.exports = {
.click('#runTestsTabRunAction') .click('#runTestsTabRunAction')
.waitForElementVisible('*[data-id="testTabSolidityUnitTestsOutputheader"]', 120000) .waitForElementVisible('*[data-id="testTabSolidityUnitTestsOutputheader"]', 120000)
.waitForElementContainsText('#solidityUnittestsOutput', 'tests/ballotFailedDebug_test.sol', 60000) .waitForElementContainsText('#solidityUnittestsOutput', 'tests/ballotFailedDebug_test.sol', 60000)
.waitForElementContainsText('#solidityUnittestsOutput', '✘ Check winning proposal', 60000) .waitForElementContainsText('#solidityUnittestsOutput', '✘ Check winning proposal failed', 60000)
.waitForElementContainsText('#solidityUnittestsOutput', '✓ Check winning proposal passed', 60000)
.waitForElementContainsText('#solidityUnittestsOutput', '✘ Check winning proposal again', 60000)
.waitForElementContainsText('#solidityUnittestsOutput', '✓ Check winnin proposal with return value', 60000) .waitForElementContainsText('#solidityUnittestsOutput', '✓ Check winnin proposal with return value', 60000)
.click('.fa-bug') .click('#Check_winning_proposal_failed')
.waitForElementContainsText('*[data-id="sidePanelSwapitTitle"]', 'DEBUGGER', 60000) .waitForElementContainsText('*[data-id="sidePanelSwapitTitle"]', 'DEBUGGER', 60000)
.waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinningProposal()', 60000) .waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinningProposalFailed()', 60000)
.click('*[data-id="dropdownPanelSolidityLocals"]') .click('*[data-id="dropdownPanelSolidityLocals"]')
.waitForElementContainsText('*[data-id="solidityLocals"]', 'no locals', 60000) .waitForElementContainsText('*[data-id="solidityLocals"]', 'no locals', 60000)
// eslint-disable-next-line dot-notation // eslint-disable-next-line dot-notation
.execute(function () { document.getElementById('slider')['value'] = '235' }) // It only moves slider to 235 but vm traces are not updated .execute(function () { document.getElementById('slider')['value'] = '315' }) // It only moves slider to 315 but vm traces are not updated
.setValue('*[data-id="slider"]', new Array(1).fill(browser.Keys.RIGHT_ARROW)) .setValue('*[data-id="slider"]', new Array(1).fill(browser.Keys.RIGHT_ARROW))
.waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinningProposal()', 60000) .waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinningProposalFailed()', 60000)
.waitForElementContainsText('*[data-id="functionPanel"]', 'vote(proposal)', 60000) .waitForElementContainsText('*[data-id="functionPanel"]', 'vote(proposal)', 60000)
.pause(2000) .pause(1000)
.checkVariableDebug('soliditylocals', locals) .checkVariableDebug('soliditylocals', locals)
.clickLaunchIcon('solidityUnitTesting')
.scrollAndClick('#Check_winning_proposal_passed')
.waitForElementContainsText('*[data-id="sidePanelSwapitTitle"]', 'DEBUGGER', 60000)
.waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinningProposalPassed()', 60000)
// eslint-disable-next-line dot-notation
.execute(function () { document.getElementById('slider')['value'] = '1450' })
.setValue('*[data-id="slider"]', new Array(1).fill(browser.Keys.RIGHT_ARROW))
.waitForElementContainsText('*[data-id="functionPanel"]', 'equal(a, b, message)', 60000)
.waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinningProposalPassed()', 60000)
.pause(1000)
.clickLaunchIcon('solidityUnitTesting')
.scrollAndClick('#Check_winning_proposal_again')
.waitForElementContainsText('*[data-id="sidePanelSwapitTitle"]', 'DEBUGGER', 60000)
.waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinningProposalAgain()', 60000)
// eslint-disable-next-line dot-notation
.execute(function () { document.getElementById('slider')['value'] = '1150' })
.setValue('*[data-id="slider"]', new Array(1).fill(browser.Keys.RIGHT_ARROW))
.waitForElementContainsText('*[data-id="functionPanel"]', 'equal(a, b, message)', 60000)
.waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinningProposalAgain()', 60000)
.pause(1000)
.clickLaunchIcon('solidityUnitTesting')
.scrollAndClick('#Check_winnin_proposal_with_return_value')
.waitForElementContainsText('*[data-id="sidePanelSwapitTitle"]', 'DEBUGGER', 60000)
.waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinninProposalWithReturnValue()', 60000)
// eslint-disable-next-line dot-notation
.execute(function () { document.getElementById('slider')['value'] = '320' })
.setValue('*[data-id="slider"]', new Array(1).fill(browser.Keys.RIGHT_ARROW))
.waitForElementContainsText('*[data-id="functionPanel"]', 'checkWinninProposalWithReturnValue()', 60000)
.clickLaunchIcon('filePanel') .clickLaunchIcon('filePanel')
.pause(2000) .pause(2000)
.openFile('tests/ballotFailedDebug_test.sol') .openFile('tests/ballotFailedDebug_test.sol')
...@@ -461,7 +491,7 @@ const sources = [ ...@@ -461,7 +491,7 @@ const sources = [
}, },
'tests/deployError_test.sol': { 'tests/deployError_test.sol': {
content: ` content: `
pragma solidity ^0.7.0; pragma solidity ^0.8.0;
contract failingDeploy { contract failingDeploy {
constructor() { constructor() {
...@@ -472,7 +502,7 @@ const sources = [ ...@@ -472,7 +502,7 @@ const sources = [
}, },
'tests/methodFailure_test.sol': { 'tests/methodFailure_test.sol': {
content: ` content: `
pragma solidity ^0.7.0; pragma solidity ^0.8.0;
contract methodfailure { contract methodfailure {
function add(uint a, uint b) public { function add(uint a, uint b) public {
...@@ -499,11 +529,20 @@ const sources = [ ...@@ -499,11 +529,20 @@ const sources = [
ballotToTest = new Ballot(proposalNames); ballotToTest = new Ballot(proposalNames);
} }
function checkWinningProposal () public { function checkWinningProposalFailed () public {
ballotToTest.vote(1); // This will revert the transaction ballotToTest.vote(1);
Assert.equal(ballotToTest.winningProposal(), uint(0), "proposal at index 0 should be the winning proposal");
}
function checkWinningProposalPassed () public {
ballotToTest.vote(0);
Assert.equal(ballotToTest.winningProposal(), uint(0), "proposal at index 0 should be the winning proposal"); Assert.equal(ballotToTest.winningProposal(), uint(0), "proposal at index 0 should be the winning proposal");
} }
function checkWinningProposalAgain () public {
Assert.equal(ballotToTest.winningProposal(), uint(1), "proposal at index 0 should be the winning proposal");
}
function checkWinninProposalWithReturnValue () public view returns (bool) { function checkWinninProposalWithReturnValue () public view returns (bool) {
return ballotToTest.winningProposal() == 0; return ballotToTest.winningProposal() == 0;
} }
......
...@@ -247,6 +247,14 @@ module.exports = class TestTab extends ViewPlugin { ...@@ -247,6 +247,14 @@ module.exports = class TestTab extends ViewPlugin {
testCallback (result, runningTests) { testCallback (result, runningTests) {
this.testsOutput.hidden = false this.testsOutput.hidden = false
let debugBtn = yo``
if ((result.type === 'testPass' || result.type === 'testFailure') && result.debugTxHash) {
const { web3, debugTxHash } = result
debugBtn = yo`<div id=${result.value.replaceAll(' ', '_')} class="btn border btn btn-sm ml-1" title="Start debugging" onclick=${() => this.startDebug(debugTxHash, web3)}>
<i class="fas fa-bug"></i>
</div>`
debugBtn.style.cursor = 'pointer'
}
if (result.type === 'contract') { if (result.type === 'contract') {
this.testSuite = result.value this.testSuite = result.value
if (this.testSuites) { if (this.testSuites) {
...@@ -268,29 +276,18 @@ module.exports = class TestTab extends ViewPlugin { ...@@ -268,29 +276,18 @@ module.exports = class TestTab extends ViewPlugin {
<div <div
id="${this.runningTestFileName}" id="${this.runningTestFileName}"
data-id="testTabSolidityUnitTestsOutputheader" data-id="testTabSolidityUnitTestsOutputheader"
class="${css.testPass} ${css.testLog} bg-light mb-2 text-success border-0" class="${css.testPass} ${css.testLog} bg-light mb-2 px-2 text-success border-0"
onclick=${() => this.discardHighlight()} onclick=${() => this.discardHighlight()}
> >
${result.value} <div class="d-flex my-1 align-items-start justify-content-between">
<span style="margin-block: auto" > ✓ ${result.value}</span>
${debugBtn}
</div>
</div> </div>
`) `)
} else if (result.type === 'testFailure') { } else if (result.type === 'testFailure') {
if (result.hhLogs && result.hhLogs.length) this.printHHLogs(result.hhLogs, result.value) if (result.hhLogs && result.hhLogs.length) this.printHHLogs(result.hhLogs, result.value)
if (!result.assertMethod) { if (!result.assertMethod) {
let debugBtn = yo``
if (result.errMsg.includes('Transaction has been reverted by the EVM')) {
const txHash = JSON.parse(result.errMsg.replace('Transaction has been reverted by the EVM:', '')).transactionHash
const { web3 } = result
debugBtn = yo`<div
class="btn border btn btn-sm ml-1"
title="Start debugging"
onclick=${() => this.startDebug(txHash, web3)}
>
<i class="fas fa-bug"></i>
</div>`
debugBtn.style.visibility = 'visible'
debugBtn.style.cursor = 'pointer'
} else debugBtn.style.visibility = 'hidden'
this.testsOutput.appendChild(yo` this.testsOutput.appendChild(yo`
<div <div
class="bg-light mb-2 px-2 ${css.testLog} d-flex flex-column text-danger border-0" class="bg-light mb-2 px-2 ${css.testLog} d-flex flex-column text-danger border-0"
...@@ -315,7 +312,10 @@ module.exports = class TestTab extends ViewPlugin { ...@@ -315,7 +312,10 @@ module.exports = class TestTab extends ViewPlugin {
id="UTContext${result.context}" id="UTContext${result.context}"
onclick=${() => this.highlightLocation(result.location, runningTests, result.filename)} onclick=${() => this.highlightLocation(result.location, runningTests, result.filename)}
> >
<div class="d-flex my-1 align-items-start justify-content-between">
<span> ✘ ${result.value}</span> <span> ✘ ${result.value}</span>
${debugBtn}
</div>
<span class="text-dark">Error Message:</span> <span class="text-dark">Error Message:</span>
<span class="pb-2 text-break">"${result.errMsg}"</span> <span class="pb-2 text-break">"${result.errMsg}"</span>
<span class="text-dark">Assertion:</span> <span class="text-dark">Assertion:</span>
...@@ -499,7 +499,7 @@ module.exports = class TestTab extends ViewPlugin { ...@@ -499,7 +499,7 @@ module.exports = class TestTab extends ViewPlugin {
usingWorker: canUseWorker(currentVersion), usingWorker: canUseWorker(currentVersion),
runs runs
} }
this.testRunner.runTestSources(runningTest, compilerConfig, () => {}, () => {}, (error, result) => { this.testRunner.runTestSources(runningTest, compilerConfig, () => {}, () => {}, null, (error, result) => {
if (error) return reject(error) if (error) return reject(error)
resolve(result) resolve(result)
}, (url, cb) => { }, (url, cb) => {
...@@ -527,17 +527,22 @@ module.exports = class TestTab extends ViewPlugin { ...@@ -527,17 +527,22 @@ module.exports = class TestTab extends ViewPlugin {
usingWorker: canUseWorker(currentVersion), usingWorker: canUseWorker(currentVersion),
runs runs
} }
const deployCb = async (file, contractAddress) => {
const compilerData = await this.call('compilerArtefacts', 'getCompilerAbstract', file)
await this.call('compilerArtefacts', 'addResolvedContract', contractAddress, compilerData)
}
this.testRunner.runTestSources( this.testRunner.runTestSources(
runningTests, runningTests,
compilerConfig, compilerConfig,
(result) => this.testCallback(result, runningTests), (result) => this.testCallback(result, runningTests),
(_err, result, cb) => this.resultsCallback(_err, result, cb), (_err, result, cb) => this.resultsCallback(_err, result, cb),
deployCb,
(error, result) => { (error, result) => {
this.updateFinalResult(error, result, testFilePath) this.updateFinalResult(error, result, testFilePath)
callback(error) callback(error)
}, (url, cb) => { }, (url, cb) => {
return this.contentImport.resolveAndSave(url).then((result) => cb(null, result)).catch((error) => cb(error.message)) return this.contentImport.resolveAndSave(url).then((result) => cb(null, result)).catch((error) => cb(error.message))
} }, { testFilePath }
) )
}).catch((error) => { }).catch((error) => {
if (error) return // eslint-disable-line if (error) return // eslint-disable-line
......
...@@ -4,7 +4,7 @@ import { CompilerAbstract } from '@remix-project/remix-solidity' ...@@ -4,7 +4,7 @@ import { CompilerAbstract } from '@remix-project/remix-solidity'
const profile = { const profile = {
name: 'compilerArtefacts', name: 'compilerArtefacts',
methods: ['get', 'addResolvedContract'], methods: ['get', 'addResolvedContract', 'getCompilerAbstract'],
events: [], events: [],
version: '0.0.1' version: '0.0.1'
} }
......
...@@ -171,8 +171,9 @@ export function compileFileOrFiles (filename: string, isDirectory: boolean, opts ...@@ -171,8 +171,9 @@ export function compileFileOrFiles (filename: string, isDirectory: boolean, opts
* @param cb Callback * @param cb Callback
*/ */
export function compileContractSources (sources: SrcIfc, compilerConfig: CompilerConfiguration, importFileCb: any, opts: any, cb): void { export function compileContractSources (sources: SrcIfc, compilerConfig: CompilerConfiguration, importFileCb: any, opts: any, cb): void {
let compiler, filepath: string let compiler
const accounts: string[] = opts.accounts || [] const accounts: string[] = opts.accounts || []
const filepath = opts.testFilePath || ''
// Iterate over sources keys. Inject test libraries. Inject test library import statements. // Iterate over sources keys. Inject test libraries. Inject test library import statements.
if (!('remix_tests.sol' in sources) && !('tests.sol' in sources)) { if (!('remix_tests.sol' in sources) && !('tests.sol' in sources)) {
sources['tests.sol'] = { content: require('../sol/tests.sol.js') } sources['tests.sol'] = { content: require('../sol/tests.sol.js') }
......
...@@ -11,7 +11,7 @@ import { compilationInterface } from './types' ...@@ -11,7 +11,7 @@ import { compilationInterface } from './types'
* @param callback Callback * @param callback Callback
*/ */
export function deployAll (compileResult: compilationInterface, web3: Web3, withDoubleGas: boolean, callback) { export function deployAll (compileResult: compilationInterface, web3: Web3, withDoubleGas: boolean, deployCb, callback) {
const compiledObject = {} const compiledObject = {}
const contracts = {} const contracts = {}
let accounts: string[] = [] let accounts: string[] = []
...@@ -70,7 +70,7 @@ export function deployAll (compileResult: compilationInterface, web3: Web3, with ...@@ -70,7 +70,7 @@ export function deployAll (compileResult: compilationInterface, web3: Web3, with
deployObject.send({ deployObject.send({
from: accounts[0], from: accounts[0],
gas: gas gas: gas
}).on('receipt', function (receipt) { }).on('receipt', async function (receipt) {
contractObject.options.address = receipt.contractAddress contractObject.options.address = receipt.contractAddress
contractObject.options.from = accounts[0] contractObject.options.from = accounts[0]
contractObject.options.gas = 5000 * 1000 contractObject.options.gas = 5000 * 1000
...@@ -79,6 +79,7 @@ export function deployAll (compileResult: compilationInterface, web3: Web3, with ...@@ -79,6 +79,7 @@ export function deployAll (compileResult: compilationInterface, web3: Web3, with
contracts[contractName] = contractObject contracts[contractName] = contractObject
contracts[contractName].filename = filename contracts[contractName].filename = filename
if (deployCb) await deployCb(filename, receipt.contractAddress)
callback(null, { receipt: { contractAddress: receipt.contractAddress } }) // TODO this will only work with JavaScriptV VM callback(null, { receipt: { contractAddress: receipt.contractAddress } }) // TODO this will only work with JavaScriptV VM
}).on('error', function (err) { }).on('error', function (err) {
console.error(err) console.error(err)
......
...@@ -61,13 +61,13 @@ export function runTestFiles (filepath: string, isDirectory: boolean, web3: Web3 ...@@ -61,13 +61,13 @@ export function runTestFiles (filepath: string, isDirectory: boolean, web3: Web3
for (const filename in asts) { for (const filename in asts) {
if (filename.endsWith('_test.sol')) { sourceASTs[filename] = asts[filename].ast } if (filename.endsWith('_test.sol')) { sourceASTs[filename] = asts[filename].ast }
} }
deployAll(compilationResult, web3, false, (err, contracts) => { deployAll(compilationResult, web3, false, null, (err, contracts) => {
if (err) { if (err) {
// If contract deployment fails because of 'Out of Gas' error, try again with double gas // 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 // This is temporary, should be removed when remix-tests will have a dedicated UI to
// accept deployment params from UI // accept deployment params from UI
if (err.message.includes('The contract code couldn\'t be stored, please check your gas limit')) { if (err.message.includes('The contract code couldn\'t be stored, please check your gas limit')) {
deployAll(compilationResult, web3, true, (error, contracts) => { deployAll(compilationResult, web3, true, null, (error, contracts) => {
if (error) next([{ message: 'contract deployment failed after trying twice: ' + error.message, severity: 'error' }]) // IDE expects errors in array if (error) next([{ message: 'contract deployment failed after trying twice: ' + error.message, severity: 'error' }]) // IDE expects errors in array
else next(null, compilationResult, contracts) else next(null, compilationResult, contracts)
}) })
......
...@@ -39,7 +39,7 @@ export class UnitTestRunner { ...@@ -39,7 +39,7 @@ export class UnitTestRunner {
* @param importFileCb Import file callback * @param importFileCb Import file callback
* @param opts Options * @param opts Options
*/ */
async runTestSources (contractSources: SrcIfc, compilerConfig: CompilerConfiguration, testCallback, resultCallback, finalCallback: any, importFileCb, opts: Options) { async runTestSources (contractSources: SrcIfc, compilerConfig: CompilerConfiguration, testCallback, resultCallback, deployCb:any, finalCallback: any, importFileCb, opts: Options) {
opts = opts || {} opts = opts || {}
const sourceASTs: any = {} const sourceASTs: any = {}
const web3 = opts.web3 || await this.createWeb3Provider() const web3 = opts.web3 || await this.createWeb3Provider()
...@@ -53,19 +53,19 @@ export class UnitTestRunner { ...@@ -53,19 +53,19 @@ export class UnitTestRunner {
}) })
}, },
(next) => { (next) => {
compileContractSources(contractSources, compilerConfig, importFileCb, { accounts, event: this.event }, next) compileContractSources(contractSources, compilerConfig, importFileCb, { accounts, testFilePath: opts.testFilePath, event: this.event }, next)
}, },
function deployAllContracts (compilationResult: compilationInterface, asts: ASTInterface, next) { function deployAllContracts (compilationResult: compilationInterface, asts: ASTInterface, next) {
for (const filename in asts) { for (const filename in asts) {
if (filename.endsWith('_test.sol')) { sourceASTs[filename] = asts[filename].ast } if (filename.endsWith('_test.sol')) { sourceASTs[filename] = asts[filename].ast }
} }
deployAll(compilationResult, web3, false, (err, contracts) => { deployAll(compilationResult, web3, false, deployCb, (err, contracts) => {
if (err) { if (err) {
// If contract deployment fails because of 'Out of Gas' error, try again with double gas // 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 // This is temporary, should be removed when remix-tests will have a dedicated UI to
// accept deployment params from UI // accept deployment params from UI
if (err.message.includes('The contract code couldn\'t be stored, please check your gas limit')) { if (err.message.includes('The contract code couldn\'t be stored, please check your gas limit')) {
deployAll(compilationResult, web3, true, (error, contracts) => { deployAll(compilationResult, web3, true, deployCb, (error, contracts) => {
if (error) next([{ message: 'contract deployment failed after trying twice: ' + error.message, severity: 'error' }]) // IDE expects errors in array if (error) next([{ message: 'contract deployment failed after trying twice: ' + error.message, severity: 'error' }]) // IDE expects errors in array
else next(null, compilationResult, contracts) else next(null, compilationResult, contracts)
}) })
......
...@@ -244,6 +244,7 @@ export function runTest (testName: string, testObject: any, contractDetails: Com ...@@ -244,6 +244,7 @@ export function runTest (testName: string, testObject: any, contractDetails: Com
if (func.inputs && func.inputs.length > 0) { return resultsCallback(new Error(`Method '${func.name}' can not have parameters inside a test contract`), { passingNum, failureNum, timePassed }) } if (func.inputs && func.inputs.length > 0) { return resultsCallback(new Error(`Method '${func.name}' can not have parameters inside a test contract`), { passingNum, failureNum, timePassed }) }
const method = testObject.methods[func.name].apply(testObject.methods[func.name], []) const method = testObject.methods[func.name].apply(testObject.methods[func.name], [])
const startTime = Date.now() const startTime = Date.now()
let debugTxHash:string
if (func.constant) { if (func.constant) {
sendParams = {} sendParams = {}
const tagTimestamp = 'remix_tests_tag' + Date.now() const tagTimestamp = 'remix_tests_tag' + Date.now()
...@@ -253,13 +254,16 @@ export function runTest (testName: string, testObject: any, contractDetails: Com ...@@ -253,13 +254,16 @@ export function runTest (testName: string, testObject: any, contractDetails: Com
let tagTxHash let tagTxHash
if (web3.eth && web3.eth.getHashFromTagBySimulator) tagTxHash = await web3.eth.getHashFromTagBySimulator(tagTimestamp) if (web3.eth && web3.eth.getHashFromTagBySimulator) tagTxHash = await web3.eth.getHashFromTagBySimulator(tagTimestamp)
if (web3.eth && web3.eth.getHHLogsForTx) hhLogs = await web3.eth.getHHLogsForTx(tagTxHash) if (web3.eth && web3.eth.getHHLogsForTx) hhLogs = await web3.eth.getHHLogsForTx(tagTxHash)
debugTxHash = tagTxHash
if (result) { if (result) {
const resp: TestResultInterface = { const resp: TestResultInterface = {
type: 'testPass', type: 'testPass',
value: changeCase.sentenceCase(func.name), value: changeCase.sentenceCase(func.name),
filename: testObject.filename, filename: testObject.filename,
time: time, time: time,
context: testName context: testName,
web3,
debugTxHash
} }
if (hhLogs && hhLogs.length) resp.hhLogs = hhLogs if (hhLogs && hhLogs.length) resp.hhLogs = hhLogs
testCallback(undefined, resp) testCallback(undefined, resp)
...@@ -272,7 +276,9 @@ export function runTest (testName: string, testObject: any, contractDetails: Com ...@@ -272,7 +276,9 @@ export function runTest (testName: string, testObject: any, contractDetails: Com
filename: testObject.filename, filename: testObject.filename,
time: time, time: time,
errMsg: 'function returned false', errMsg: 'function returned false',
context: testName context: testName,
web3,
debugTxHash
} }
if (hhLogs && hhLogs.length) resp.hhLogs = hhLogs if (hhLogs && hhLogs.length) resp.hhLogs = hhLogs
testCallback(undefined, resp) testCallback(undefined, resp)
...@@ -293,6 +299,7 @@ export function runTest (testName: string, testObject: any, contractDetails: Com ...@@ -293,6 +299,7 @@ export function runTest (testName: string, testObject: any, contractDetails: Com
sendParams.gas = 10000000 * 8 sendParams.gas = 10000000 * 8
method.send(sendParams).on('receipt', async (receipt) => { method.send(sendParams).on('receipt', async (receipt) => {
try { try {
debugTxHash = receipt.transactionHash
if (web3.eth && web3.eth.getHHLogsForTx) hhLogs = await web3.eth.getHHLogsForTx(receipt.transactionHash) if (web3.eth && web3.eth.getHHLogsForTx) hhLogs = await web3.eth.getHHLogsForTx(receipt.transactionHash)
const time: number = (Date.now() - startTime) / 1000.0 const time: number = (Date.now() - startTime) / 1000.0
const assertionEventHashes = assertionEvents.map(e => Web3.utils.sha3(e.name + '(' + e.params.join() + ')')) const assertionEventHashes = assertionEvents.map(e => Web3.utils.sha3(e.name + '(' + e.params.join() + ')'))
...@@ -322,7 +329,8 @@ export function runTest (testName: string, testObject: any, contractDetails: Com ...@@ -322,7 +329,8 @@ export function runTest (testName: string, testObject: any, contractDetails: Com
returned: testEvent[3], returned: testEvent[3],
expected: testEvent[4], expected: testEvent[4],
location, location,
web3 web3,
debugTxHash
} }
if (hhLogs && hhLogs.length) resp.hhLogs = hhLogs if (hhLogs && hhLogs.length) resp.hhLogs = hhLogs
testCallback(undefined, resp) testCallback(undefined, resp)
...@@ -341,7 +349,9 @@ export function runTest (testName: string, testObject: any, contractDetails: Com ...@@ -341,7 +349,9 @@ export function runTest (testName: string, testObject: any, contractDetails: Com
value: changeCase.sentenceCase(func.name), value: changeCase.sentenceCase(func.name),
filename: testObject.filename, filename: testObject.filename,
time: time, time: time,
context: testName context: testName,
web3,
debugTxHash
} }
if (hhLogs && hhLogs.length) resp.hhLogs = hhLogs if (hhLogs && hhLogs.length) resp.hhLogs = hhLogs
testCallback(undefined, resp) testCallback(undefined, resp)
...@@ -380,6 +390,7 @@ export function runTest (testName: string, testObject: any, contractDetails: Com ...@@ -380,6 +390,7 @@ export function runTest (testName: string, testObject: any, contractDetails: Com
const txHash = JSON.parse(err.message.replace('Transaction has been reverted by the EVM:', '')).transactionHash const txHash = JSON.parse(err.message.replace('Transaction has been reverted by the EVM:', '')).transactionHash
if (web3.eth && web3.eth.getHHLogsForTx) hhLogs = await web3.eth.getHHLogsForTx(txHash) if (web3.eth && web3.eth.getHHLogsForTx) hhLogs = await web3.eth.getHHLogsForTx(txHash)
if (hhLogs && hhLogs.length) resp.hhLogs = hhLogs if (hhLogs && hhLogs.length) resp.hhLogs = hhLogs
resp.debugTxHash = txHash
} }
testCallback(undefined, resp) testCallback(undefined, resp)
failureNum += 1 failureNum += 1
......
...@@ -38,6 +38,7 @@ export interface TestResultInterface { ...@@ -38,6 +38,7 @@ export interface TestResultInterface {
location?: string location?: string
hhLogs?: [] hhLogs?: []
web3?: any web3?: any
debugTxHash?: string
} }
export interface TestCbInterface { export interface TestCbInterface {
(error: Error | null | undefined, result: TestResultInterface) : void; (error: Error | null | undefined, result: TestResultInterface) : void;
...@@ -48,6 +49,7 @@ export interface ResultCbInterface { ...@@ -48,6 +49,7 @@ export interface ResultCbInterface {
export interface Options { export interface Options {
accounts?: string[] | null, accounts?: string[] | null,
testFilePath?: string
web3?: any web3?: any
} }
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment