Test your smart contract in Solidity.
-
Click on "Generate" to generate a sample test file.
+
Select directory to load and generate test files.
+
+ ${availablePaths}
@@ -518,6 +552,7 @@ module.exports = class TestTab extends ViewPlugin {
`
this._view.el = el
+ this.testTabLogic.setCurrentPath(this.defaultPath)
this.updateForNewCurrent(this.fileManager.currentFile())
return el
}
diff --git a/src/app/tabs/testTab/testTab.js b/src/app/tabs/testTab/testTab.js
index ce95bf52f50..964b431337c 100644
--- a/src/app/tabs/testTab/testTab.js
+++ b/src/app/tabs/testTab/testTab.js
@@ -1,52 +1,71 @@
const helper = require('../../../lib/helper.js')
const modalDialogCustom = require('../../ui/modal-dialog-custom')
+const remixPath = require('path')
class TestTabLogic {
constructor (fileManager) {
this.fileManager = fileManager
+ this.currentPath = 'browser/tests'
+ }
+
+ setCurrentPath (path) {
+ if (path.indexOf('/') === 0) return
+ this.currentPath = path
+ const fileProvider = this.fileManager.fileProviderOf(path.split('/')[0])
+ fileProvider.exists(path, (e, res) => { if (!res) fileProvider.createDir(path) })
}
generateTestFile () {
- const path = this.fileManager.currentPath()
- const fileName = this.fileManager.currentFile()
- const fileProvider = this.fileManager.fileProviderOf(path)
+ let fileName = this.fileManager.currentFile()
+ const hasCurrent = !!fileName && this.fileManager.currentFile().split('.').pop().toLowerCase() === 'sol'
+ if (!hasCurrent) fileName = this.currentPath + '/newFile.sol'
+ const fileProvider = this.fileManager.fileProviderOf(this.currentPath)
if (!fileProvider) return
- helper.createNonClashingNameWithPrefix(fileName, fileProvider, '_test', (error, newFile) => {
+ const splittedFileName = fileName.split('/')
+ let fileNameToImport = (!hasCurrent) ? fileName : this.currentPath + '/' + splittedFileName[splittedFileName.length - 1]
+ helper.createNonClashingNameWithPrefix(fileNameToImport, fileProvider, '_test', (error, newFile) => {
if (error) return modalDialogCustom.alert('Failed to create file. ' + newFile + ' ' + error)
- const splittedFileName = fileName.split('/')
- // This is fine for now because test file is created on same path where file to be tested is.
- // This should be updated to pass complete path, if test file comes from different directory/path
- const fileNameToImport = splittedFileName[splittedFileName.length - 1]
- if (!fileProvider.set(newFile, this.generateTestContractSample(fileNameToImport))) return modalDialogCustom.alert('Failed to create test file ' + newFile)
+ if (!fileProvider.set(newFile, this.generateTestContractSample(hasCurrent, fileName))) return modalDialogCustom.alert('Failed to create test file ' + newFile)
this.fileManager.open(newFile)
+ this.fileManager.syncEditor(newFile)
})
}
+ dirList (path) {
+ return this.fileManager.dirList(path)
+ }
+
+ isRemixDActive () {
+ return this.fileManager.isRemixDActive()
+ }
+
async getTests (cb) {
- const path = this.fileManager.currentPath()
- if (!path) return cb(null, [])
- const provider = this.fileManager.fileProviderOf(path)
+ if (!this.currentPath) return cb(null, [])
+ const provider = this.fileManager.fileProviderOf(this.currentPath)
if (!provider) return cb(null, [])
const tests = []
let files
try {
- files = await this.fileManager.readdir(path)
+ files = await this.fileManager.readdir(this.currentPath)
} catch (e) {
cb(e.message)
}
for (var file in files) {
if (/.(_test.sol)$/.exec(file)) tests.push(provider.type + '/' + file)
}
- cb(null, tests, path)
+ cb(null, tests, this.currentPath)
}
// @todo(#2758): If currently selected file is compiled and compilation result is available,
// 'contractName' should be
+ '_testSuite'
- generateTestContractSample (fileToImport, contractName = 'testSuite') {
+ generateTestContractSample (hasCurrent, fileToImport, contractName = 'testSuite') {
+ let relative = remixPath.relative(this.currentPath, remixPath.dirname(fileToImport))
+ if (relative === '') relative = '.'
+ const comment = hasCurrent ? `import "${relative}/${remixPath.basename(fileToImport)}";` : '// Import here the file to test.'
return `pragma solidity >=0.4.22 <0.7.0;
import "remix_tests.sol"; // this import is automatically injected by Remix.
-import "./${fileToImport}";
+${comment}
// File name has to end with '_test.sol', this file can contain more than one testSuite contracts
contract ${contractName} {
@@ -65,7 +84,7 @@ contract ${contractName} {
Assert.notEqual(uint(2), uint(3), "2 should not be equal to 3");
}
- function checkSuccess2() public view returns (bool) {
+ function checkSuccess2() public pure returns (bool) {
// Use the return value (true or false) to test the contract
return true;
}
diff --git a/test-browser/tests/defaultLayout.test.js b/test-browser/tests/defaultLayout.test.js
index f4857c7f86d..3e1a3970050 100644
--- a/test-browser/tests/defaultLayout.test.js
+++ b/test-browser/tests/defaultLayout.test.js
@@ -18,7 +18,7 @@ module.exports = {
browser.waitForElementVisible('div[data-id="remixIdeSidePanel"]')
.assert.containsText('h6[data-id="sidePanelSwapitTitle"]', 'FILE EXPLORERS')
.waitForElementVisible('div[data-id="filePanelFileExplorerTree"]')
- .waitForElementVisible('li[key="browser/4_Ballot_test.sol"]')
+ .waitForElementVisible('li[key="browser/3_Ballot.sol"]')
},
'Loads Main View': function (browser) {
diff --git a/test-browser/tests/fileExplorer.test.js b/test-browser/tests/fileExplorer.test.js
index c39fb9ff047..9647c93d089 100644
--- a/test-browser/tests/fileExplorer.test.js
+++ b/test-browser/tests/fileExplorer.test.js
@@ -22,8 +22,7 @@ module.exports = {
.waitForElementVisible('*[data-id="modalDialogContainer"]')
.setValue('*[data-id="modalDialogCustomPromptText"]', '5_New_contract.sol')
.modalFooterOKClick()
- .pause(2000)
- .waitForElementVisible('*[data-id="treeViewLibrowser/5_New_contract.sol"]')
+ .waitForElementVisible('*[data-id="treeViewLibrowser/5_New_contract.sol"]', 7000)
},
'Should rename `5_New_contract.sol` to 5_Renamed_Contract.sol': function (browser) {
@@ -86,8 +85,7 @@ module.exports = {
.click('*[data-id="fileExplorerNewFilepublishToGist"]')
.waitForElementVisible('*[data-id="modalDialogContainer"]')
.modalFooterOKClick()
- .pause(10000)
- .waitForElementVisible('*[data-id="modalDialogContainer"]')
+ .waitForElementVisible('*[data-id="modalDialogContainer"]', 7000)
.modalFooterOKClick()
.pause(2000)
.perform((done) => {
diff --git a/test-browser/tests/generalSettings.test.js b/test-browser/tests/generalSettings.test.js
index ea9ab48c87b..a47484a6729 100644
--- a/test-browser/tests/generalSettings.test.js
+++ b/test-browser/tests/generalSettings.test.js
@@ -37,7 +37,6 @@ module.exports = {
.click('*[data-id="compilerContainerCompileBtn"]')
.pause(3000)
.click('*[data-id="verticalIconsKindfileExplorers"]')
- .openFile('browser/artifacts')
.openFile('browser/artifacts/Ballot.json')
},
diff --git a/test-browser/tests/gist.test.js b/test-browser/tests/gist.test.js
index 5c01f6f5a94..a939bcdc176 100644
--- a/test-browser/tests/gist.test.js
+++ b/test-browser/tests/gist.test.js
@@ -45,7 +45,6 @@ module.exports = {
.modalFooterCancelClick()
.executeScript(`remix.loadgist('${gistid}')`)
.perform((done) => { if (runtimeBrowser === 'chrome') { browser.openFile('browser/gists') } done() })
- .openFile(`browser/gists/${gistid}`)
.openFile(`browser/gists/${gistid}/1_Storage.sol`)
.perform(done)
}
@@ -86,7 +85,6 @@ module.exports = {
.waitForElementVisible('*[data-id="modalDialogCustomPromptText"]')
.setValue('*[data-id="modalDialogCustomPromptText"]', testData.validGistId)
.modalFooterOKClick()
- .openFile(`browser/gists/${testData.validGistId}`)
.openFile(`browser/gists/${testData.validGistId}/ApplicationRegistry`)
.waitForElementVisible(`div[title='browser/gists/${testData.validGistId}/ApplicationRegistry']`)
.assert.containsText(`div[title='browser/gists/${testData.validGistId}/ApplicationRegistry'] > span`, 'ApplicationRegistry')
diff --git a/test-browser/tests/solidityUnittests.test.js b/test-browser/tests/solidityUnittests.test.js
index cdb99c4e039..a3dd412ee33 100644
--- a/test-browser/tests/solidityUnittests.test.js
+++ b/test-browser/tests/solidityUnittests.test.js
@@ -31,14 +31,16 @@ module.exports = {
.click('*[data-id="verticalIconsKindsolidityUnitTesting"]')
.waitForElementPresent('*[data-id="testTabGenerateTestFile"]')
.click('*[data-id="testTabGenerateTestFile"]')
- .waitForElementPresent('*[title="browser/simple_storage_test.sol"]')
+ .waitForElementPresent('*[title="browser/tests/simple_storage_test.sol"]')
.clickLaunchIcon('fileExplorers')
- .removeFile('browser/simple_storage_test.sol')
+ .pause(10000)
+ .openFile('browser/tests/simple_storage_test.sol')
+ .removeFile('browser/tests/simple_storage_test.sol')
},
'Should run simple unit test `simple_storage_test.sol` ': function (browser) {
browser.waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]')
- .addFile('simple_storage_test.sol', sources[0]['browser/simple_storage_test.sol'])
+ .addFile('tests/simple_storage_test.sol', sources[0]['browser/tests/simple_storage_test.sol'])
.click('*[data-id="verticalIconsKindsolidityUnitTesting"]')
.waitForElementPresent('*[data-id="testTabCheckAllTests"]')
.click('*[data-id="testTabCheckAllTests"]')
@@ -46,19 +48,19 @@ module.exports = {
.scrollAndClick('*[data-id="testTabRunTestsTabRunAction"]')
.waitForElementPresent('*[data-id="testTabSolidityUnitTestsOutputheader"]', 80000)
.pause(5000)
- .assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'MyTest (browser/simple_storage_test.sol)')
+ .assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'MyTest (browser/tests/simple_storage_test.sol)')
.assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', '✓ Initial value should be100')
.assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', '✓ Value is set200')
.assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', '✘ Should fail for wrong value200')
.assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'Passing: 2')
.assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'Failing: 1')
- .assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'FAIL MyTest (browser/simple_storage_test.sol)')
+ .assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'FAIL MyTest (browser/tests/simple_storage_test.sol)')
},
'Should run advance unit test using natspec and experimental ABIEncoderV2 `ks2b_test.sol` ': function (browser) {
browser.waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]')
.clickLaunchIcon('fileExplorers')
- .addFile('ks2b_test.sol', sources[0]['browser/ks2b_test.sol'])
+ .addFile('tests/ks2b_test.sol', sources[0]['browser/tests/ks2b_test.sol'])
.click('*[data-id="verticalIconsKindsolidityUnitTesting"]')
.waitForElementPresent('*[data-id="testTabCheckAllTests"]')
.click('*[data-id="testTabCheckAllTests"]')
@@ -66,7 +68,7 @@ module.exports = {
.scrollAndClick('*[data-id="testTabRunTestsTabRunAction"]')
.waitForElementPresent('*[data-id="testTabSolidityUnitTestsOutputheader"]', 40000)
.pause(5000)
- .assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'browser/ks2b_test.sol')
+ .assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'browser/tests/ks2b_test.sol')
.assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', '✓ Check project exists')
.assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', '✘ Check wrong project owner')
.assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', '✘ Check wrong sender')
@@ -89,18 +91,18 @@ module.exports = {
.pause(1000)
.assert.containsText('*[data-id="testTabRunTestsTabStopAction"]', 'Stopping')
.waitForElementPresent('*[data-id="testTabSolidityUnitTestsOutputheader"]', 40000)
- .assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'browser/ks2b_test.sol')
- .notContainsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'browser/4_Ballot_test.sol')
- .notContainsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'browser/simple_storage_test.sol')
- .pause(6000)
+ .assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'browser/tests/ks2b_test.sol')
+ .notContainsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'browser/tests/4_Ballot_test.sol')
+ .notContainsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'browser/tests/simple_storage_test.sol')
+ .pause(7000)
.assert.containsText('*[data-id="testTabTestsExecutionStopped"]', 'The test execution has been stopped')
},
'Should fail on compilation': function (browser) {
browser.waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]')
- .addFile('compilationError_test.sol', sources[0]['browser/compilationError_test.sol'])
+ .addFile('tests/compilationError_test.sol', sources[0]['browser/compilationError_test.sol'])
.clickLaunchIcon('fileExplorers')
- .openFile('browser/compilationError_test.sol')
+ .openFile('browser/tests/compilationError_test.sol')
.clickLaunchIcon('solidityUnitTesting')
.click('*[data-id="testTabCheckAllTests"]')
.clickElementAtPosition('.singleTestLabel', 3)
@@ -113,9 +115,9 @@ module.exports = {
'Should fail on deploy': function (browser) {
browser.waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]')
- .addFile('deployError_test.sol', sources[0]['browser/deployError_test.sol'])
+ .addFile('tests/deployError_test.sol', sources[0]['browser/tests/deployError_test.sol'])
.clickLaunchIcon('fileExplorers')
- .openFile('browser/deployError_test.sol')
+ .openFile('browser/tests/deployError_test.sol')
.clickLaunchIcon('solidityUnitTesting')
.click('*[data-id="testTabCheckAllTests"]')
.clickElementAtPosition('.singleTestLabel', 4)
@@ -127,9 +129,9 @@ module.exports = {
'Should fail when parameters are to method in test contract': function (browser) {
browser.waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]')
- .addFile('methodFailure_test.sol', sources[0]['browser/methodFailure_test.sol'])
+ .addFile('tests/methodFailure_test.sol', sources[0]['browser/tests/methodFailure_test.sol'])
.clickLaunchIcon('fileExplorers')
- .openFile('browser/methodFailure_test.sol')
+ .openFile('browser/tests/methodFailure_test.sol')
.clickLaunchIcon('solidityUnitTesting')
.click('*[data-id="testTabCheckAllTests"]')
.clickElementAtPosition('.singleTestLabel', 5)
@@ -139,6 +141,19 @@ module.exports = {
.assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', `Method 'add' can not have parameters inside a test contract`)
},
+ 'Changing current path': function (browser) {
+ browser.waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]')
+ .addFile('myTests/simple_storage_test.sol', sources[0]['browser/tests/simple_storage_test.sol'])
+ .clickLaunchIcon('solidityUnitTesting')
+ .setValue('*[data-id="uiPathInput"]', 'browser/myTests')
+ .clickElementAtPosition('.singleTestLabel', 0)
+ .scrollAndClick('*[data-id="testTabRunTestsTabRunAction"]')
+ .waitForElementPresent('*[data-id="testTabSolidityUnitTestsOutputheader"]', 40000)
+ .waitForElementPresent('*[data-id="testTabSolidityUnitTestsOutput"]')
+ .clearValue('*[data-id="uiPathInput"]')
+ .setValue('*[data-id="uiPathInput"]', 'browser/tests')
+ },
+
'Solidity Unittests': function (browser) {
runTests(browser)
},
@@ -157,7 +172,7 @@ function runTests (browser) {
.waitForElementPresent('*[data-id="testTabSolidityUnitTestsOutputheader"]', 40000)
.pause(5000)
.waitForElementPresent('#solidityUnittestsOutput div[class^="testPass"]')
- .assert.containsText('#solidityUnittestsOutput', 'browser/4_Ballot_test.sol')
+ .assert.containsText('#solidityUnittestsOutput', 'browser/tests/4_Ballot_test.sol')
.assert.containsText('#solidityUnittestsOutput', '✓ Check winning proposal')
.assert.containsText('#solidityUnittestsOutput', '✓ Check winnin proposal with return value')
.end()
@@ -186,11 +201,11 @@ var sources = [
}
`
},
- 'browser/simple_storage_test.sol': {
+ 'browser/tests/simple_storage_test.sol': {
content: `
pragma solidity >=0.4.22 <0.7.0;
import "remix_tests.sol";
- import "./simple_storage.sol";
+ import "../simple_storage.sol";
contract MyTest {
SimpleStorage foo;
@@ -269,14 +284,14 @@ var sources = [
}
`
},
- 'browser/ks2b_test.sol': {
+ 'browser/tests/ks2b_test.sol': {
content: `
pragma solidity >=0.4.22 <0.6.0;
pragma experimental ABIEncoderV2;
import "remix_tests.sol"; // this import is automatically injected by Remix.
import "remix_accounts.sol";
- import "./ks2a.sol";
+ import "../ks2a.sol";
contract kickstarterTest {
enum State { Started, Completed }
@@ -339,7 +354,7 @@ var sources = [
}
`
},
- 'browser/deployError_test.sol': {
+ 'browser/tests/deployError_test.sol': {
content: `
pragma solidity ^0.6.0;
@@ -350,7 +365,7 @@ var sources = [
}
`
},
- 'browser/methodFailure_test.sol': {
+ 'browser/tests/methodFailure_test.sol': {
content: `
pragma solidity ^0.6.0;