diff --git a/.gitignore b/.gitignore index af13303645..c664a6e412 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,5 @@ package-lock.json remix .DS_Store contracts +TODO +.tern-port diff --git a/package.json b/package.json index b9175f126e..e358d0cdf6 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "remix-core": "latest", "remix-lib": "latest", "remix-solidity": "latest", + "remix-tests": "latest", "remixd": "git+https://github.com/ethereum/remixd.git", "request": "^2.83.0", "rimraf": "^2.6.1", @@ -52,7 +53,7 @@ "web3": "^0.18.0", "webworkify": "^1.2.1", "yo-yo": "^1.2.2", - "yo-yoify": "^3.1.0" + "yo-yoify": "^3.7.3" }, "dependencies": { "http-server": "0.9.0", diff --git a/src/app.js b/src/app.js index 1d2542e27e..c72a65d1f6 100644 --- a/src/app.js +++ b/src/app.js @@ -6,6 +6,7 @@ var yo = require('yo-yo') var async = require('async') var request = require('request') var remixLib = require('remix-lib') +var remixTests = require('remix-tests') var EventManager = remixLib.EventManager var UniversalDApp = require('./universal-dapp.js') @@ -251,7 +252,9 @@ Please make a backup of your contracts and start using http://remix.ethereum.org }, (error, content, cleanUrl, type, url) => { if (!error) { - filesProviders[type].addReadOnly(cleanUrl, content, url) + if (filesProviders[type]) { + filesProviders[type].addReadOnly(cleanUrl, content, url) + } cb(null, content) } else { cb(error) @@ -260,6 +263,9 @@ Please make a backup of your contracts and start using http://remix.ethereum.org } function importFileCb (url, filecb) { + if (url.indexOf('/remix_tests.sol') !== -1) { + return filecb(null, remixTests.assertLibCode) + } var provider = fileManager.fileProviderOf(url) if (provider) { provider.exists(url, (error, exist) => { @@ -723,6 +729,10 @@ Please make a backup of your contracts and start using http://remix.ethereum.org // ---------------- Righthand-panel -------------------- var rhpAPI = { + importFileCb: importFileCb, + filesFromPath: (path, cb) => { + fileManager.filesFromPath(path, cb) + }, newAccount: (pass, cb) => { udapp.newAccount(pass, cb) }, diff --git a/src/app/files/fileManager.js b/src/app/files/fileManager.js index 0d974200fb..9af4d38420 100644 --- a/src/app/files/fileManager.js +++ b/src/app/files/fileManager.js @@ -155,6 +155,14 @@ class FileManager { } } + filesFromPath (path, cb) { + var provider = this.fileProviderOf(path) + if (provider) { + return provider.resolveDirectory(path, (error, filesTree) => { cb(error, filesTree) }) + } + cb(`provider for path ${path} not found`) + } + fileProviderOf (file) { var provider = file.match(/[^/]*/) if (provider !== null && this.opt.filesProviders[provider[0]]) { diff --git a/src/app/panels/righthand-panel.js b/src/app/panels/righthand-panel.js index 84aff7cceb..bc0136146f 100644 --- a/src/app/panels/righthand-panel.js +++ b/src/app/panels/righthand-panel.js @@ -9,6 +9,7 @@ var AnalysisTab = require('../tabs/analysis-tab') var DebuggerTab = require('../tabs/debugger-tab') var SupportTab = require('../tabs/support-tab') var PluginTab = require('../tabs/plugin-tab') +var TestTab = require('../tabs/test-tab') var PluginManager = require('../plugin/pluginManager') var css = require('./styles/righthand-panel-styles') @@ -54,12 +55,15 @@ function RighthandPanel (appAPI = {}, events = {}, opts = {}) { optionViews.appendChild(debuggerTab.render()) var supportTab = new SupportTab(appAPI, events, opts) optionViews.appendChild(supportTab.render()) + var testTab = new TestTab(appAPI, events, opts) + optionViews.appendChild(testTab.render()) this._view.tabbedMenu.addTab('Compile', 'compileView', optionViews.querySelector('#compileTabView')) this._view.tabbedMenu.addTab('Run', 'runView', optionViews.querySelector('#runTabView')) this._view.tabbedMenu.addTab('Settings', 'settingsView', optionViews.querySelector('#settingsView')) this._view.tabbedMenu.addTab('Analysis', 'staticanalysisView', optionViews.querySelector('#staticanalysisView')) this._view.tabbedMenu.addTab('Debugger', 'debugView', optionViews.querySelector('#debugView')) this._view.tabbedMenu.addTab('Support', 'supportView', optionViews.querySelector('#supportView')) + this._view.tabbedMenu.addTab('Test', 'testView', optionViews.querySelector('#testView')) this._view.tabbedMenu.selectTabByTitle('Compile') self.pluginManager = new PluginManager(opts.pluginAPI, events) diff --git a/src/app/tabs/styles/test-tab-styles.js b/src/app/tabs/styles/test-tab-styles.js new file mode 100644 index 0000000000..882ef5f7eb --- /dev/null +++ b/src/app/tabs/styles/test-tab-styles.js @@ -0,0 +1,56 @@ +var csjs = require('csjs-inject') +var styleGuide = require('../../ui/styles-guide/theme-chooser') +var styles = styleGuide.chooser() + +var css = csjs` +.opts_li { + display: block; + font-weight: bold; + color: ${styles.rightPanel.text_Teriary}; +} +.opts_li.active { + color: ${styles.rightPanel.text_Primary}; +} +.opts_li:hover { + color: ${styles.rightPanel.icon_HoverColor_TogglePanel}; +} +.solIcon { + margin-left: 10px; + margin-right: 30px; + display: flex; + align-self: center; + height: 29px; + width: 20px; + background-color: ${styles.colors.transparent}; +} +a { + color: ${styles.rightPanel.text_link}; +} +#optionViews > div { + display: none; +} +#optionViews .pre { + word-wrap: break-word; + background-color: ${styles.rightPanel.BackgroundColor_Pre}; + border-radius: 3px; + display: inline-block; + padding: 0 0.6em; +} +#optionViews .hide { + display: none; +} +.infoBox { + ${styles.infoTextBox} + margin-bottom: 1em; +} +.textBox { + ${styles.textBoxL} + margin-bottom: 1em; +} +.icon { + height: 70%; + margin-right: 2%; +} +` + +module.exports = css diff --git a/src/app/tabs/test-tab.js b/src/app/tabs/test-tab.js new file mode 100644 index 0000000000..ae778bad3d --- /dev/null +++ b/src/app/tabs/test-tab.js @@ -0,0 +1,106 @@ +var yo = require('yo-yo') +var async = require('async') +var css = require('./styles/test-tab-styles') +var remixTests = require('remix-tests') + +function append (container, txt) { + let child = yo`