From b84110da51fdb0b1efe4f9e72be9a715b4548acd Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 16 Aug 2018 14:37:44 +0200 Subject: [PATCH 1/7] add missing css to dark style --- src/app/ui/styles-guide/styleGuideDark.js | 26 +++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/app/ui/styles-guide/styleGuideDark.js b/src/app/ui/styles-guide/styleGuideDark.js index 70ad6b8b43..8e2ca1aa3b 100644 --- a/src/app/ui/styles-guide/styleGuideDark.js +++ b/src/app/ui/styles-guide/styleGuideDark.js @@ -644,6 +644,32 @@ function styleGuideDark () { }, + /* :::::::::::::: + TEST TAB + ::::::::::::::: */ + testTab: { + box_listTests: appProperties.uiElements.solidBorderBox({ + BackgroundColor: appProperties.solidBorderBox_BackgroundColor, + BorderColor: appProperties.solidBorderBox_BackgroundColor, + Color: appProperties.solidBorderBox_TextColor + }), + + button_runTests: appProperties.uiElements.button({ + BackgroundColor: appProperties.primaryButton_BackgroundColor, + BorderColor: appProperties.primaryButton_BorderColor, + Color: appProperties.primaryButton_TextColor + }), + + button_generateTestFile: appProperties.uiElements.button({ + BackgroundColor: appProperties.primaryButton_BackgroundColor, + BorderColor: appProperties.primaryButton_BorderColor, + Color: appProperties.primaryButton_TextColor + }), + + color_testPass: appProperties.success_BackgroundColor, + color_testFail: appProperties.danger_BackgroundColor + }, + /* :::::::::::::: SETTINGS TAB ::::::::::::::: */ From 010c990316442fe03ae038e1922479a474c287f0 Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 16 Aug 2018 14:38:08 +0200 Subject: [PATCH 2/7] add generate test file --- src/app/tabs/styles/test-tab-styles.js | 4 ++ src/app/tabs/test-tab.js | 59 ++++++++++++++++++++++++++ src/app/ui/styles-guide/style-guide.js | 6 +++ src/lib/helper.js | 9 ++-- 4 files changed, 75 insertions(+), 3 deletions(-) diff --git a/src/app/tabs/styles/test-tab-styles.js b/src/app/tabs/styles/test-tab-styles.js index e04f5dfb8e..cb6dfd8f7c 100644 --- a/src/app/tabs/styles/test-tab-styles.js +++ b/src/app/tabs/styles/test-tab-styles.js @@ -49,6 +49,10 @@ var css = csjs` .runButton { ${styles.rightPanel.testTab.button_runTests}; } + .generateTestFile { + ${styles.rightPanel.testTab.button_generateTestFile}; + min-width: 100px + } ` module.exports = css diff --git a/src/app/tabs/test-tab.js b/src/app/tabs/test-tab.js index 84b535bb16..f1f386deb1 100644 --- a/src/app/tabs/test-tab.js +++ b/src/app/tabs/test-tab.js @@ -1,5 +1,7 @@ var yo = require('yo-yo') var async = require('async') +var helper = require('../../lib/helper.js') +var modalDialogCustom = require('../ui/modal-dialog-custom') var globalRegistry = require('../../global/registry') var css = require('./styles/test-tab-styles') var remixTests = require('remix-tests') @@ -129,12 +131,29 @@ module.exports = class TestTab { async.eachOfSeries(tests, (value, key, callback) => { runTest(value, callback) }) } + var generateTestFile = function () { + var fileManager = self._deps.fileManager + var path = fileManager.currentPath() + var fileProvider = fileManager.fileProviderOf(path) + if (fileProvider) { + helper.createNonClashingNameWithPrefix(path + '/test.sol', fileProvider, '_test', (error, newFile) => { + if (error) return modalDialogCustom.alert('Failed to create file. ' + newFile + ' ' + error) + if (!fileProvider.set(newFile, testContractSample)) { + modalDialogCustom.alert('Failed to create test file ' + newFile) + } else { + fileManager.switchFile(newFile) + } + }) + } + } + var el = yo`
Test your smart contract by creating a foo_test.sol file. Open ballot_test.sol to see the example. For more details, see How to test smart contracts guide in our documentation. +
Generate test file
${listTests()}
@@ -150,3 +169,43 @@ module.exports = class TestTab { return el } } + +var testContractSample = `pragma solidity ^0.4.0; +import "remix_tests.sol"; // this import is automatically injected by Remix. + +// file name has to end with '_test.sol' +contract test_1 { + + function beforeAll () { + // here should instanciate tested contract + } + + function check1 () public { + // this function is not constant, use 'Assert' to test the contract + Assert.equal(uint(2), uint(1), "error message"); + Assert.equal(uint(2), uint(2), "error message"); + } + + function check2 () public constant returns (bool) { + // this function is constant, use the return value (true or false) to test the contract + return true; + } +} + +contract test_2 { + + function beforeAll () { + // here should instanciate tested contract + } + + function check1 () public { + // this function is not constant, use 'Assert' to test the contract + Assert.equal(uint(2), uint(1), "error message"); + Assert.equal(uint(2), uint(2), "error message"); + } + + function check2 () public constant returns (bool) { + // this function is constant, use the return value (true or false) to test the contract + return true; + } +}` diff --git a/src/app/ui/styles-guide/style-guide.js b/src/app/ui/styles-guide/style-guide.js index 0833b364b0..ba30df9a95 100644 --- a/src/app/ui/styles-guide/style-guide.js +++ b/src/app/ui/styles-guide/style-guide.js @@ -670,6 +670,12 @@ function styleGuide () { Color: appProperties.primaryButton_TextColor }), + button_generateTestFile: appProperties.uiElements.button({ + BackgroundColor: appProperties.primaryButton_BackgroundColor, + BorderColor: appProperties.primaryButton_BorderColor, + Color: appProperties.primaryButton_TextColor + }), + color_testPass: appProperties.success_BackgroundColor, color_testFail: appProperties.danger_BackgroundColor }, diff --git a/src/lib/helper.js b/src/lib/helper.js index b186dc4ffb..758fbef843 100644 --- a/src/lib/helper.js +++ b/src/lib/helper.js @@ -11,7 +11,7 @@ module.exports = { var len = data.length return data.slice(0, 5) + '...' + data.slice(len - 5, len) }, - createNonClashingName (name, fileProvider, cb) { + createNonClashingNameWithPrefix (name, fileProvider, prefix, cb) { var counter = '' var ext = 'sol' var reg = /(.*)\.([^.]+)/g @@ -24,7 +24,7 @@ module.exports = { async.whilst( () => { return exist }, (callback) => { - fileProvider.exists(name + counter + '.' + ext, (error, currentExist) => { + fileProvider.exists(name + counter + prefix + '.' + ext, (error, currentExist) => { if (error) { callback(error) } else { @@ -34,9 +34,12 @@ module.exports = { } }) }, - (error) => { cb(error, name + counter + '.' + ext) } + (error) => { cb(error, name + counter + prefix + '.' + ext) } ) }, + createNonClashingName (name, fileProvider, cb) { + this.createNonClashingNameWithPrefix(name, fileProvider, '', cb) + }, checkSpecialChars (name) { return name.match(/[/:*?"<>\\'|]/) != null }, From 2559c9796f06328705b50049594e1d36a1cd7b30 Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 16 Aug 2018 16:24:23 +0200 Subject: [PATCH 3/7] fix tab name --- src/app/panels/righthand-panel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/panels/righthand-panel.js b/src/app/panels/righthand-panel.js index 42e8f04acc..ed025509c4 100644 --- a/src/app/panels/righthand-panel.js +++ b/src/app/panels/righthand-panel.js @@ -115,7 +115,7 @@ module.exports = class RighthandPanel { self._components.tabbedMenu.addTab('Analysis', 'staticanalysisView', analysis.render()) self._components.tabbedMenu.addTab('Debugger', 'debugView', debug.render()) self._components.tabbedMenu.addTab('Support', 'supportView', support.render()) - self._components.tabbedMenu.addTab('Test', 'testView', test.render()) + self._components.tabbedMenu.addTab('Testing', 'testView', test.render()) self._components.tabbedMenu.selectTabByTitle('Compile') } // showDebugger () { From f53f2ce41373eb2518f4fa64eb5ce3c0a906ae0b Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 16 Aug 2018 16:24:55 +0200 Subject: [PATCH 4/7] fix description --- src/app/tabs/styles/test-tab-styles.js | 5 +++++ src/app/tabs/test-tab.js | 9 +++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/app/tabs/styles/test-tab-styles.js b/src/app/tabs/styles/test-tab-styles.js index cb6dfd8f7c..cc79dc8f18 100644 --- a/src/app/tabs/styles/test-tab-styles.js +++ b/src/app/tabs/styles/test-tab-styles.js @@ -53,6 +53,11 @@ var css = csjs` ${styles.rightPanel.testTab.button_generateTestFile}; min-width: 100px } + .title { + font-size: 1.1em; + font-weight: bold; + margin-bottom: 1em; + } ` module.exports = css diff --git a/src/app/tabs/test-tab.js b/src/app/tabs/test-tab.js index f1f386deb1..d906c55451 100644 --- a/src/app/tabs/test-tab.js +++ b/src/app/tabs/test-tab.js @@ -150,8 +150,13 @@ module.exports = class TestTab { var el = yo`
- Test your smart contract by creating a foo_test.sol file. - Open ballot_test.sol to see the example. For more details, see +
Unit Testing
+ Test your smart contract by creating a foo_test.sol file. Open ballot_test.sol to see the example. +
+ Then use the stand alone NPM module remix-tests to run unit tests in your Continuous Integration + https://www.npmjs.com/package/remix-tests. +
+ For more details, see How to test smart contracts guide in our documentation.
Generate test file
From 2f2e62f652371bcd72a29b3b22a29978982c2bd3 Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 16 Aug 2018 16:25:02 +0200 Subject: [PATCH 5/7] fix test tab --- src/app/tabs/test-tab.js | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/app/tabs/test-tab.js b/src/app/tabs/test-tab.js index d906c55451..0b00d960d6 100644 --- a/src/app/tabs/test-tab.js +++ b/src/app/tabs/test-tab.js @@ -1,6 +1,7 @@ var yo = require('yo-yo') var async = require('async') var helper = require('../../lib/helper.js') +var tooltip = require('../ui/tooltip') var modalDialogCustom = require('../ui/modal-dialog-custom') var globalRegistry = require('../../global/registry') var css = require('./styles/test-tab-styles') @@ -19,13 +20,12 @@ module.exports = class TestTab { filePanel: self._components.registry.get('filepanel').api } self.data = {} + self.testList = yo`
` } render () { const self = this var testsOutput = yo`` var testsSummary = yo`` - self.data.allTests = getTests(self) - self.data.selectedTests = [...self.data.allTests] var testCallback = function (result) { testsOutput.hidden = false @@ -81,29 +81,38 @@ module.exports = class TestTab { }) } - function getTests (self) { + function getTests (self, cb) { var path = self._deps.fileManager.currentPath() var provider = self._deps.fileManager.fileProviderOf(path) var tests = [] self._deps.fileManager.filesFromPath(path, (error, files) => { + if (error) return cb(error) if (!error) { for (var file in files) { if (/.(_test.sol)$/.exec(file)) tests.push(provider.type + '/' + file) } + cb(null, tests) } }) - return tests } self._deps.filePanel.event.register('newTestFileCreated', file => { var testList = document.querySelector("[class^='testList']") - var test = yo`` + var test = yo`` testList.appendChild(test) self.data.allTests.push(file) self.data.selectedTests.push(file) }) self._deps.fileManager.event.register('currentFileChanged', (file, provider) => { + getTests(self, (error, tests) => { + if (error) return tooltip(error) + self.data.allTests = tests + self.data.selectedTests = [...self.data.allTests] + yo.update(self.testList, yo`
${listTests()}
`) + testsOutput.innerHTML = '' + testsSummary.innerHTML = '' + }) }) // self._events.filePanel.register('fileRenamed', (oldName, newName, isFolder) => { @@ -161,7 +170,7 @@ module.exports = class TestTab {
Generate test file
-
${listTests()}
+ ${self.testList}
Run Tests
From e9251de5c60ee292ac4e3f65ac7eb7be4ce19693 Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 16 Aug 2018 16:31:51 +0200 Subject: [PATCH 6/7] add "no test file available" --- src/app/tabs/test-tab.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/app/tabs/test-tab.js b/src/app/tabs/test-tab.js index 0b00d960d6..bca4c5d254 100644 --- a/src/app/tabs/test-tab.js +++ b/src/app/tabs/test-tab.js @@ -109,7 +109,13 @@ module.exports = class TestTab { if (error) return tooltip(error) self.data.allTests = tests self.data.selectedTests = [...self.data.allTests] - yo.update(self.testList, yo`
${listTests()}
`) + if (!tests.length) { + yo.update(self.testList, yo`
No test file available
`) + } else { + yo.update(self.testList, yo`
${listTests()}
`) + } + testsOutput.hidden = true + testsSummary.hidden = true testsOutput.innerHTML = '' testsSummary.innerHTML = '' }) From c53e1e41bb9f77a8ff2e0e65e5e8cbe7feb5dd7a Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 16 Aug 2018 16:36:57 +0200 Subject: [PATCH 7/7] tab ordering --- src/app/panels/righthand-panel.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/panels/righthand-panel.js b/src/app/panels/righthand-panel.js index ed025509c4..e1852c9b5d 100644 --- a/src/app/panels/righthand-panel.js +++ b/src/app/panels/righthand-panel.js @@ -111,11 +111,11 @@ module.exports = class RighthandPanel { const { compile, run, settings, analysis, debug, support, test } = self._components self._components.tabbedMenu.addTab('Compile', 'compileView', compile.render()) self._components.tabbedMenu.addTab('Run', 'runView', run.render()) - self._components.tabbedMenu.addTab('Settings', 'settingsView', settings.render()) self._components.tabbedMenu.addTab('Analysis', 'staticanalysisView', analysis.render()) + self._components.tabbedMenu.addTab('Testing', 'testView', test.render()) self._components.tabbedMenu.addTab('Debugger', 'debugView', debug.render()) + self._components.tabbedMenu.addTab('Settings', 'settingsView', settings.render()) self._components.tabbedMenu.addTab('Support', 'supportView', support.render()) - self._components.tabbedMenu.addTab('Testing', 'testView', test.render()) self._components.tabbedMenu.selectTabByTitle('Compile') } // showDebugger () {