diff --git a/apps/debugger/.babelrc b/apps/debugger/.babelrc new file mode 100644 index 0000000000..09d67939cc --- /dev/null +++ b/apps/debugger/.babelrc @@ -0,0 +1,4 @@ +{ + "presets": ["@nrwl/react/babel"], + "plugins": [] +} diff --git a/apps/debugger/.browserslistrc b/apps/debugger/.browserslistrc new file mode 100644 index 0000000000..f1d12df4fa --- /dev/null +++ b/apps/debugger/.browserslistrc @@ -0,0 +1,16 @@ +# This file is used by: +# 1. autoprefixer to adjust CSS to support the below specified browsers +# 2. babel preset-env to adjust included polyfills +# +# For additional information regarding the format and rule options, please see: +# https://github.com/browserslist/browserslist#queries +# +# If you need to support different browsers in production, you may tweak the list below. + +last 1 Chrome version +last 1 Firefox version +last 2 Edge major versions +last 2 Safari major version +last 2 iOS major versions +Firefox ESR +not IE 9-11 # For IE 9-11 support, remove 'not'. \ No newline at end of file diff --git a/apps/debugger/src/app/app.tsx b/apps/debugger/src/app/app.tsx new file mode 100644 index 0000000000..5cee11a2d9 --- /dev/null +++ b/apps/debugger/src/app/app.tsx @@ -0,0 +1,17 @@ +import React, { useState, useEffect } from 'react'; + +import { DebuggerUI } from '@remix-ui/debugger-ui' // eslint-disable-line + +import { DebuggerClientApi } from './debugger' + +const remix = new DebuggerClientApi() + +export const App = () => { + return ( +
+ +
+ ); +}; + +export default App; diff --git a/apps/debugger/src/app/debugger-api.ts b/apps/debugger/src/app/debugger-api.ts new file mode 100644 index 0000000000..6d52279ccd --- /dev/null +++ b/apps/debugger/src/app/debugger-api.ts @@ -0,0 +1,157 @@ +import Web3 from 'web3' +import remixDebug, { TransactionDebugger as Debugger } from '@remix-project/remix-debug' +import { CompilationOutput, Sources } from '@remix-ui/debugger-ui' +import type { CompilationResult } from '@remix-project/remix-solidity-ts' + +export const DebuggerApiMixin = (Base) => class extends Base { + initDebuggerApi () { + this.debugHash = null + + const self = this + this.web3Provider = { + sendAsync(payload, callback) { + self.call('web3Provider', 'sendAsync', payload) + .then(result => callback(null, result)) + .catch(e => callback(e)) + } + } + this._web3 = new Web3(this.web3Provider) + + this.offsetToLineColumnConverter = { + async offsetToLineColumn (rawLocation, file, sources, asts) { + return await self.call('offsetToLineColumnConverter', 'offsetToLineColumn', rawLocation, file, sources, asts) + } + } + } + + // on() + // call() + // onDebugRequested() + // onRemoveHighlights() + + web3 () { + return this._web3 + } + + async discardHighlight () { + await this.call('editor', 'discardHighlight') + } + + async highlight (lineColumnPos, path) { + await this.call('editor', 'highlight', lineColumnPos, path) + } + + async getFile (path) { + return await this.call('fileManager', 'getFile', path) + } + + async setFile (path, content) { + await this.call('fileManager', 'setFile', path, content) + } + + onBreakpointCleared (listener) { + this.onBreakpointClearedListener = listener + } + + onBreakpointAdded (listener) { + this.onBreakpointAddedListener = listener + } + + onEditorContentChanged (listener) { + this.onEditorContentChangedListener = listener + } + + onDebugRequested (listener) { + this.onDebugRequestedListener = listener + } + + onRemoveHighlights (listener) { + this.onRemoveHighlightsListener = listener + } + + async fetchContractAndCompile (address, receipt) { + const target = (address && remixDebug.traceHelper.isContractCreation(address)) ? receipt.contractAddress : address + const targetAddress = target || receipt.contractAddress || receipt.to + const codeAtAddress = await this._web3.eth.getCode(targetAddress) + const output = await this.call('fetchAndCompile', 'resolve', targetAddress, codeAtAddress, 'browser/.debug') + return new CompilerAbstract(output.languageversion, output.data, output.source) + } + + async getDebugWeb3 () { + let web3 + let network + try { + network = await this.call('network', 'detectNetwork') + } catch (e) { + web3 = this.web3() + } + if (!web3) { + const webDebugNode = remixDebug.init.web3DebugNode(network.name) + web3 = !webDebugNode ? this.web3() : webDebugNode + } + remixDebug.init.extendWeb3(web3) + return web3 + } + + async getTrace (hash) { + if (!hash) return + const web3 = await this.getDebugWeb3() + const currentReceipt = await web3.eth.getTransactionReceipt(hash) + const debug = new Debugger({ + web3, + offsetToLineColumnConverter: this.offsetToLineColumnConverter, + compilationResult: async (address) => { + try { + return await this.fetchContractAndCompile(address, currentReceipt) + } catch (e) { + console.error(e) + } + return null + }, + debugWithGeneratedSources: false + }) + return await debug.debugger.traceManager.getTrace(hash) + } + + debug (hash) { + this.debugHash = hash + this.onDebugRequestedListener(hash) + } + + onActivation () { + this.on('editor', 'breakpointCleared', (fileName, row) => this.onBreakpointClearedListener(fileName, row)) + this.on('editor', 'breakpointAdded', (fileName, row) => this.onBreakpointAddedListener(fileName, row)) + this.on('editor', 'contentChanged', () => this.onEditorContentChangedListener()) + } + + onDeactivation () { + this.onRemoveHighlightsListener() + this.off('editor', 'breakpointCleared') + this.off('editor', 'breakpointAdded') + this.off('editor', 'contentChanged') + } +} + +export class CompilerAbstract implements CompilationOutput { // this is a subset of /remix-ide/src/app/compiler/compiler-abstract.js + languageversion + data + source + + constructor (languageversion: string, data: CompilationResult, source: { sources: Sources, target: string }) { + this.languageversion = languageversion + this.data = data + this.source = source // source code + } + + getSourceName (fileIndex) { + if (this.data && this.data.sources) { + return Object.keys(this.data.sources)[fileIndex] + } else if (Object.keys(this.source.sources).length === 1) { + // if we don't have ast, we return the only one filename present. + const sourcesArray = Object.keys(this.source.sources) + return sourcesArray[0] + } + return null + } +} + diff --git a/apps/debugger/src/app/debugger.ts b/apps/debugger/src/app/debugger.ts new file mode 100644 index 0000000000..4c14f6a3d2 --- /dev/null +++ b/apps/debugger/src/app/debugger.ts @@ -0,0 +1,28 @@ +import { PluginClient } from "@remixproject/plugin"; +import { createClient } from "@remixproject/plugin-webview"; +import { IDebuggerApi, RawLocation, Sources, Asts, LineColumnLocation, + onBreakpointClearedListener, onBreakpointAddedListener, onEditorContentChanged, TransactionReceipt } from '@remix-ui/debugger-ui' +import { DebuggerApiMixin, CompilerAbstract} from './debugger-api' + +export class DebuggerClientApi extends DebuggerApiMixin(PluginClient) { + constructor () { + super() + createClient(this as any) + this.initDebuggerApi() + } + + offsetToLineColumnConverter: IDebuggerApi['offsetToLineColumnConverter'] + debugHash: string + debugHashRequest: number + removeHighlights: boolean + onBreakpointCleared: (listener: onBreakpointClearedListener) => void + onBreakpointAdded: (listener: onBreakpointAddedListener) => void + onEditorContentChanged: (listener: onEditorContentChanged) => void + discardHighlight: () => Promise + highlight: (lineColumnPos: LineColumnLocation, path: string) => Promise + fetchContractAndCompile: (address: string, currentReceipt: TransactionReceipt) => Promise + getFile: (path: string) => Promise + setFile: (path: string, content: string) => Promise + getDebugWeb3: () => any // returns an instance of web3.js +} + diff --git a/apps/debugger/src/assets/.gitkeep b/apps/debugger/src/assets/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/debugger/src/environments/environment.prod.ts b/apps/debugger/src/environments/environment.prod.ts new file mode 100644 index 0000000000..3612073bc3 --- /dev/null +++ b/apps/debugger/src/environments/environment.prod.ts @@ -0,0 +1,3 @@ +export const environment = { + production: true +}; diff --git a/apps/debugger/src/environments/environment.ts b/apps/debugger/src/environments/environment.ts new file mode 100644 index 0000000000..d9370e924b --- /dev/null +++ b/apps/debugger/src/environments/environment.ts @@ -0,0 +1,6 @@ +// This file can be replaced during build by using the `fileReplacements` array. +// When building for production, this file is replaced with `environment.prod.ts`. + +export const environment = { + production: false +}; diff --git a/apps/debugger/src/favicon.ico b/apps/debugger/src/favicon.ico new file mode 100644 index 0000000000..317ebcb233 Binary files /dev/null and b/apps/debugger/src/favicon.ico differ diff --git a/apps/debugger/src/index.html b/apps/debugger/src/index.html new file mode 100644 index 0000000000..e44825a34e --- /dev/null +++ b/apps/debugger/src/index.html @@ -0,0 +1,15 @@ + + + + + Debugger + + + + + + + +
+ + diff --git a/apps/debugger/src/index.ts b/apps/debugger/src/index.ts new file mode 100644 index 0000000000..b38e3a7942 --- /dev/null +++ b/apps/debugger/src/index.ts @@ -0,0 +1 @@ +export * from './app/debugger-api'; diff --git a/apps/debugger/src/main.tsx b/apps/debugger/src/main.tsx new file mode 100644 index 0000000000..bc1579ec0f --- /dev/null +++ b/apps/debugger/src/main.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; + +import App from './app/app'; + +ReactDOM.render( + , + document.getElementById('root') +); diff --git a/apps/debugger/src/polyfills.ts b/apps/debugger/src/polyfills.ts new file mode 100644 index 0000000000..2adf3d05b6 --- /dev/null +++ b/apps/debugger/src/polyfills.ts @@ -0,0 +1,7 @@ +/** + * Polyfill stable language features. These imports will be optimized by `@babel/preset-env`. + * + * See: https://github.com/zloirock/core-js#babel + */ +import 'core-js/stable'; +import 'regenerator-runtime/runtime'; diff --git a/apps/debugger/src/styles.css b/apps/debugger/src/styles.css new file mode 100644 index 0000000000..90d4ee0072 --- /dev/null +++ b/apps/debugger/src/styles.css @@ -0,0 +1 @@ +/* You can add global styles to this file, and also import other style files */ diff --git a/apps/debugger/tsconfig.app.json b/apps/debugger/tsconfig.app.json new file mode 100644 index 0000000000..2151bb6497 --- /dev/null +++ b/apps/debugger/tsconfig.app.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "types": ["node"] + }, + "exclude": ["**/*.spec.ts", "**/*.spec.tsx"], + "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] +} diff --git a/apps/debugger/tsconfig.json b/apps/debugger/tsconfig.json new file mode 100644 index 0000000000..7c6fcde8f2 --- /dev/null +++ b/apps/debugger/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "jsx": "react", + "allowJs": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "types": ["node", "jest"], + "resolveJsonModule": true + }, + "files": [ + "../../node_modules/@nrwl/react/typings/cssmodule.d.ts", + "../../node_modules/@nrwl/react/typings/image.d.ts" + ], + "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] +} diff --git a/apps/debugger/tsconfig.spec.json b/apps/debugger/tsconfig.spec.json new file mode 100644 index 0000000000..559410b96a --- /dev/null +++ b/apps/debugger/tsconfig.spec.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "**/*.spec.ts", + "**/*.spec.tsx", + "**/*.spec.js", + "**/*.spec.jsx", + "**/*.d.ts" + ] +} diff --git a/apps/debugger/webpack.config.js b/apps/debugger/webpack.config.js new file mode 100644 index 0000000000..bacc6e251e --- /dev/null +++ b/apps/debugger/webpack.config.js @@ -0,0 +1,17 @@ +const nxWebpack = require('@nrwl/react/plugins/webpack') + +module.exports = config => { + const nxWebpackConfig = nxWebpack(config) + + return { + ...nxWebpackConfig, + node: { + fs: 'empty', + tls: 'empty', + readline: 'empty', + net: 'empty', + module: 'empty', + child_process: 'empty' + } + } +} diff --git a/apps/remix-ide-e2e/src/commands/addFile.ts b/apps/remix-ide-e2e/src/commands/addFile.ts index 149d0fa43b..4eeca25002 100644 --- a/apps/remix-ide-e2e/src/commands/addFile.ts +++ b/apps/remix-ide-e2e/src/commands/addFile.ts @@ -14,21 +14,17 @@ class AddFile extends EventEmitter { } function addFile (browser: NightwatchBrowser, name: string, content: NightwatchContractContent, done: VoidFunction) { - browser.clickLaunchIcon('udapp').clickLaunchIcon('fileExplorers').click('.newFile') - .waitForElementVisible('#modal-dialog') - .perform((client, done) => { - browser.execute(function (fileName) { - if (fileName !== 'Untitled.sol') { - document.querySelector('#modal-dialog #prompt_text').setAttribute('value', fileName) - } - const elem = document.querySelector('#modal-footer-ok') as HTMLElement - - elem.click() - }, [name], function (result) { - console.log(result) - done() - }) - }) + browser.clickLaunchIcon('udapp') + .clickLaunchIcon('fileExplorers') + .click('li[data-id="treeViewLitreeViewItembrowser/README.txt"]') // focus on root directory + .click('.newFile') + .waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/blank"]') + // .scrollAndClick('*[data-id="treeViewLitreeViewItembrowser/blank"] .remixui_items') + .sendKeys('*[data-id="treeViewLitreeViewItembrowser/blank"] .remixui_items', name) + .sendKeys('*[data-id="treeViewLitreeViewItembrowser/blank"] .remixui_items', browser.Keys.ENTER) + .pause(2000) + .waitForElementVisible(`li[data-id="treeViewLitreeViewItembrowser/${name}"]`) + .click(`li[data-id="treeViewLitreeViewItembrowser/${name}"]`) .setEditorValue(content.content) .pause(1000) .perform(function () { diff --git a/apps/remix-ide-e2e/src/commands/debugTransaction.ts b/apps/remix-ide-e2e/src/commands/debugTransaction.ts index 85b2b24238..d4d9100800 100644 --- a/apps/remix-ide-e2e/src/commands/debugTransaction.ts +++ b/apps/remix-ide-e2e/src/commands/debugTransaction.ts @@ -19,7 +19,7 @@ function checkStyle (browser: NightwatchBrowser, index: number, callback: VoidFu debugBtn && debugBtn.click() }, [index], function () { - callback() + browser.waitForElementVisible('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]').perform(() => callback()) }) } diff --git a/apps/remix-ide-e2e/src/commands/getModalBody.ts b/apps/remix-ide-e2e/src/commands/getModalBody.ts index 85ee421aab..103044c0f2 100644 --- a/apps/remix-ide-e2e/src/commands/getModalBody.ts +++ b/apps/remix-ide-e2e/src/commands/getModalBody.ts @@ -3,8 +3,8 @@ import EventEmitter from "events" class GetModalBody extends EventEmitter { command (this: NightwatchBrowser, callback: (value: string, cb: VoidFunction) => void) { - this.api.waitForElementVisible('.modal-body') - .getText('.modal-body', (result) => { + this.api.waitForElementPresent('.modal-body') + .getText('#modal-dialog', (result) => { console.log(result) const value = typeof result.value === 'string' ? result.value : null diff --git a/apps/remix-ide-e2e/src/commands/goToVMTraceStep.ts b/apps/remix-ide-e2e/src/commands/goToVMTraceStep.ts index 7d01074158..c7eda61ebf 100644 --- a/apps/remix-ide-e2e/src/commands/goToVMTraceStep.ts +++ b/apps/remix-ide-e2e/src/commands/goToVMTraceStep.ts @@ -14,6 +14,7 @@ function goToVMtraceStep (browser: NightwatchBrowser, step: number, incr: number browser.execute(function () { return document.querySelector('#stepdetail').innerHTML }, [], function (result) { + console.log('goToVMtraceStep', result) if (typeof result.value === 'string' && ( result.value.indexOf('vm trace step:') !== -1 && result.value.indexOf(step.toString()) !== -1)) { done() } else if (incr > 1000) { diff --git a/apps/remix-ide-e2e/src/commands/openFile.ts b/apps/remix-ide-e2e/src/commands/openFile.ts index 262c9dddaf..00e411b234 100644 --- a/apps/remix-ide-e2e/src/commands/openFile.ts +++ b/apps/remix-ide-e2e/src/commands/openFile.ts @@ -16,8 +16,8 @@ class OpenFile extends EventEmitter { // click on fileExplorer can toggle it. We go through settings to be sure FE is open function openFile (browser: NightwatchBrowser, name: string, done: VoidFunction) { browser.clickLaunchIcon('settings').clickLaunchIcon('fileExplorers') - .waitForElementVisible('li[key="' + name + '"]') - .click('li[key="' + name + '"]') + .waitForElementVisible('li[data-id="treeViewLitreeViewItem' + name + '"') + .click('li[data-id="treeViewLitreeViewItem' + name + '"') .pause(2000) .perform(() => { done() diff --git a/apps/remix-ide-e2e/src/commands/removeFile.ts b/apps/remix-ide-e2e/src/commands/removeFile.ts index 512f7c0c3b..89281eeb41 100644 --- a/apps/remix-ide-e2e/src/commands/removeFile.ts +++ b/apps/remix-ide-e2e/src/commands/removeFile.ts @@ -34,13 +34,19 @@ function removeFile (browser: NightwatchBrowser, path: string, done: VoidFunctio contextMenuClick(document.querySelector('[data-path="' + path + '"]')) }, [path], function () { browser - .waitForElementVisible('#menuitemdelete', 2000) + .waitForElementVisible('#menuitemdelete') .click('#menuitemdelete') - .pause(500) - .waitForElementVisible('#modal-footer-ok', 2000) - .click('#modal-footer-ok') - .waitForElementNotPresent('[data-path="' + path + '"]') + .pause(2000) .perform(() => { + if (path.indexOf('browser') !== -1) { + browser.waitForElementVisible('[data-id="browser-modal-footer-ok-react"]') + .click('[data-id="browser-modal-footer-ok-react"]') + .waitForElementNotPresent('[data-path="' + path + '"]') + } else if (path.indexOf('localhost') !== -1) { + browser.waitForElementVisible('[data-id="localhost-modal-footer-ok-react"]') + .click('[data-id="localhost-modal-footer-ok-react"]') + .waitForElementNotPresent('[data-path="' + path + '"]') + } done() }) }) diff --git a/apps/remix-ide-e2e/src/commands/renameFile.ts b/apps/remix-ide-e2e/src/commands/renamePath.ts similarity index 84% rename from apps/remix-ide-e2e/src/commands/renameFile.ts rename to apps/remix-ide-e2e/src/commands/renamePath.ts index 551ea3365c..552f159587 100644 --- a/apps/remix-ide-e2e/src/commands/renameFile.ts +++ b/apps/remix-ide-e2e/src/commands/renamePath.ts @@ -1,10 +1,10 @@ import EventEmitter from 'events' import { NightwatchBrowser } from 'nightwatch' -class RenameFile extends EventEmitter { +class RenamePath extends EventEmitter { command (this: NightwatchBrowser, path: string, newFileName: string, renamedPath: string) { this.api.perform((done) => { - renameFile(this.api, path, newFileName, renamedPath, () => { + renamePath(this.api, path, newFileName, renamedPath, () => { done() this.emit('complete') }) @@ -13,7 +13,7 @@ class RenameFile extends EventEmitter { } } -function renameFile (browser: NightwatchBrowser, path: string, newFileName: string, renamedPath: string, done: VoidFunction) { +function renamePath (browser: NightwatchBrowser, path: string, newFileName: string, renamedPath: string, done: VoidFunction) { browser.execute(function (path: string) { function contextMenuClick (element) { const evt = element.ownerDocument.createEvent('MouseEvents') @@ -41,10 +41,9 @@ function renameFile (browser: NightwatchBrowser, path: string, newFileName: stri doneSetValue() }) }) - .click('body') // blur - .waitForElementVisible('#modal-footer-ok', 100000) + .pause(1000) + .click('li[data-id="treeViewLitreeViewItembrowser/README.txt"]') // focus on root directory .pause(2000) - .click('#modal-footer-ok') .waitForElementNotPresent('[data-path="' + path + '"]') .waitForElementPresent('[data-path="' + renamedPath + '"]') .perform(() => { @@ -53,4 +52,4 @@ function renameFile (browser: NightwatchBrowser, path: string, newFileName: stri }) } -module.exports = RenameFile \ No newline at end of file +module.exports = RenamePath diff --git a/apps/remix-ide-e2e/src/tests/ballot.test.ts b/apps/remix-ide-e2e/src/tests/ballot.test.ts index 692eb1bf4d..80528bf886 100644 --- a/apps/remix-ide-e2e/src/tests/ballot.test.ts +++ b/apps/remix-ide-e2e/src/tests/ballot.test.ts @@ -39,10 +39,11 @@ module.exports = { 'Debug Ballot / delegate': function (browser: NightwatchBrowser) { browser.pause(500) .click('*[data-id="txLoggerDebugButton0x41fab8ea5b1d9fba5e0a6545ca1a2d62fff518578802c033c2b9a031a01c31b3"]') - .pause(2000) + .waitForElementVisible('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]') // .clickLaunchIcon('debugger') .click('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]') .pause(2000) + .waitForElementVisible('#stepdetail') .goToVMTraceStep(79) .pause(1000) .checkVariableDebug('soliditystate', stateCheck) diff --git a/apps/remix-ide-e2e/src/tests/ballot_0_4_11.test.ts b/apps/remix-ide-e2e/src/tests/ballot_0_4_11.test.ts index 17f83c4778..ee71c13a58 100644 --- a/apps/remix-ide-e2e/src/tests/ballot_0_4_11.test.ts +++ b/apps/remix-ide-e2e/src/tests/ballot_0_4_11.test.ts @@ -50,8 +50,10 @@ module.exports = { browser.pause(500) .click('*[data-id="txLoggerDebugButton0x41fab8ea5b1d9fba5e0a6545ca1a2d62fff518578802c033c2b9a031a01c31b3"]') .pause(2000) + .waitForElementVisible('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]') .click('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]') .pause(2000) + .waitForElementVisible('#stepdetail') .goToVMTraceStep(20) .pause(1000) .checkVariableDebug('callstackpanel', ["0x692a70D2e424a56D2C6C27aA97D1a86395877b3A"]) diff --git a/apps/remix-ide-e2e/src/tests/debugger.test.ts b/apps/remix-ide-e2e/src/tests/debugger.test.ts index 53095537f8..9e3b84eea3 100644 --- a/apps/remix-ide-e2e/src/tests/debugger.test.ts +++ b/apps/remix-ide-e2e/src/tests/debugger.test.ts @@ -89,6 +89,7 @@ module.exports = { .createContract('"tokenName", "symbol"') .debugTransaction(2) .pause(2000) + .waitForElementVisible('#stepdetail') .goToVMTraceStep(10) .getEditorValue((content) => { browser.assert.ok(content.indexOf(`constructor (string memory name_, string memory symbol_) public { @@ -109,7 +110,8 @@ module.exports = { browser .clickLaunchIcon('solidity') .setSolidityCompilerVersion('soljson-v0.6.12+commit.27d51765.js') - .clickLaunchIcon('udapp') + .clickLaunchIcon('fileExplorers') + .click('li[data-id="treeViewLitreeViewItembrowser/externalImport.sol"') .testContracts('withABIEncoderV2.sol', sources[2]['browser/withABIEncoderV2.sol'], ['test']) .clickLaunchIcon('udapp') .selectContract('test') @@ -117,7 +119,8 @@ module.exports = { .clickInstance(2) .clickFunction('test1 - transact (not payable)', {types: 'bytes userData', values: '0x000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000015b38da6a701c568545dcfcb03fcb875f56beddc4'}) .debugTransaction(4) - .pause(2000) + .pause(2000) + .waitForElementVisible('#stepdetail') .goToVMTraceStep(261) .pause(1000) /* diff --git a/apps/remix-ide-e2e/src/tests/defaultLayout.test.ts b/apps/remix-ide-e2e/src/tests/defaultLayout.test.ts index 94ab72bd2b..3378a49c85 100644 --- a/apps/remix-ide-e2e/src/tests/defaultLayout.test.ts +++ b/apps/remix-ide-e2e/src/tests/defaultLayout.test.ts @@ -20,10 +20,10 @@ 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/contracts"]') - .waitForElementVisible('li[key="browser/scripts"]') - .waitForElementVisible('li[key="browser/tests"]') - .waitForElementVisible('li[key="browser/README.txt"]') + .waitForElementVisible('[data-id="treeViewLitreeViewItembrowser/contracts"]') + .waitForElementVisible('[data-id="treeViewLitreeViewItembrowser/scripts"]') + .waitForElementVisible('[data-id="treeViewLitreeViewItembrowser/tests"]') + .waitForElementVisible('[data-id="treeViewLitreeViewItembrowser/README.txt"]') }, 'Loads Main View': function (browser: NightwatchBrowser) { @@ -61,17 +61,17 @@ module.exports = { 'Toggles File Explorer Browser': function (browser: NightwatchBrowser) { browser .waitForElementVisible('div[data-id="filePanelFileExplorerTree"]') - .assert.visible('ul[key="browser"]') - .click('div[data-id="treeViewTogglebrowser"]') - .assert.hidden('ul[key="browser"]') - .click('div[data-id="treeViewTogglebrowser"]') - .assert.visible('ul[key="browser"]') + .waitForElementPresent('[data-id="treeViewLitreeViewItembrowser/contracts"]') + .click('[data-path="browser"]') + .waitForElementNotPresent('[data-id="treeViewLitreeViewItembrowser/contracts"]') + .click('[data-path="browser"]') + .waitForElementPresent('[data-id="treeViewLitreeViewItembrowser/contracts"]') }, 'Switch Tabs using tabs icon': function (browser: NightwatchBrowser) { browser .waitForElementVisible('div[data-id="filePanelFileExplorerTree"]') - .click('*[data-id="treeViewTogglebrowser/contracts"]') + .click('[data-id="treeViewLitreeViewItembrowser/contracts"]') .openFile('browser/contracts/3_Ballot.sol') .assert.containsText('div[title="browser/contracts/3_Ballot.sol"]', '3_Ballot.sol') .click('span[class^=dropdownCaret]') diff --git a/apps/remix-ide-e2e/src/tests/editor.test.ts b/apps/remix-ide-e2e/src/tests/editor.test.ts index 37f69bf68e..e6ef792298 100644 --- a/apps/remix-ide-e2e/src/tests/editor.test.ts +++ b/apps/remix-ide-e2e/src/tests/editor.test.ts @@ -14,7 +14,6 @@ module.exports = { browser.waitForElementVisible('div[data-id="mainPanelPluginsContainer"]') .clickLaunchIcon('fileExplorers') .waitForElementVisible('div[data-id="filePanelFileExplorerTree"]') - .click('*[data-id="treeViewLibrowser/contracts"]') .openFile('browser/contracts/1_Storage.sol') .waitForElementVisible('*[data-id="editorInput"]') .checkElementStyle('*[data-id="editorInput"]', 'font-size', '12px') @@ -81,7 +80,8 @@ module.exports = { 'Should highlight source code': function (browser: NightwatchBrowser) { // include all files here because switching between plugins in side-panel removes highlight - browser.addFile('sourcehighlight.js', sourcehighlightScript) + browser + .addFile('sourcehighlight.js', sourcehighlightScript) .addFile('removeSourcehighlightScript.js', removeSourcehighlightScript) .addFile('removeAllSourcehighlightScript.js', removeAllSourcehighlightScript) .openFile('browser/sourcehighlight.js') @@ -96,27 +96,26 @@ module.exports = { }, 'Should remove 1 highlight from source code': function (browser: NightwatchBrowser) { - browser.waitForElementVisible('li[key="browser/removeSourcehighlightScript.js"]') - .click('li[key="browser/removeSourcehighlightScript.js"]') + browser.waitForElementVisible('li[data-id="treeViewLitreeViewItembrowser/removeSourcehighlightScript.js"]') + .click('li[data-id="treeViewLitreeViewItembrowser/removeSourcehighlightScript.js"]') .pause(2000) .executeScript('remix.exeCurrent()') - .waitForElementVisible('li[key="browser/contracts"]') - .click('li[key="browser/contracts"]') // files don't appear, so we click twice to get the files - .click('li[key="browser/contracts"]') - .waitForElementVisible('li[key="browser/contracts/3_Ballot.sol"]') - .click('li[key="browser/contracts/3_Ballot.sol"]') + .waitForElementVisible('li[data-id="treeViewLitreeViewItembrowser/contracts"]') + .click('li[data-id="treeViewLitreeViewItembrowser/contracts"]') + .waitForElementVisible('li[data-id="treeViewLitreeViewItembrowser/contracts/3_Ballot.sol"]') + .click('li[data-id="treeViewLitreeViewItembrowser/contracts/3_Ballot.sol"]') .waitForElementNotPresent('.highlightLine32') .checkElementStyle('.highlightLine40', 'background-color', 'rgb(8, 108, 181)') .checkElementStyle('.highlightLine50', 'background-color', 'rgb(8, 108, 181)') }, 'Should remove all highlights from source code': function (browser: NightwatchBrowser) { - browser.waitForElementVisible('li[key="browser/removeAllSourcehighlightScript.js"]') - .click('li[key="browser/removeAllSourcehighlightScript.js"]') + browser.waitForElementVisible('li[data-id="treeViewLitreeViewItembrowser/removeAllSourcehighlightScript.js"]') + .click('li[data-id="treeViewLitreeViewItembrowser/removeAllSourcehighlightScript.js"]') .pause(2000) .executeScript('remix.exeCurrent()') - .waitForElementVisible('li[key="browser/contracts/3_Ballot.sol"]') - .click('li[key="browser/contracts/3_Ballot.sol"]') + .waitForElementVisible('li[data-id="treeViewLitreeViewItembrowser/contracts/3_Ballot.sol"]') + .click('li[data-id="treeViewLitreeViewItembrowser/contracts/3_Ballot.sol"]') .pause(2000) .waitForElementNotPresent('.highlightLine32') .waitForElementNotPresent('.highlightLine40') diff --git a/apps/remix-ide-e2e/src/tests/fileExplorer.test.ts b/apps/remix-ide-e2e/src/tests/fileExplorer.test.ts index b9e7f89fd4..b0bbb056d8 100644 --- a/apps/remix-ide-e2e/src/tests/fileExplorer.test.ts +++ b/apps/remix-ide-e2e/src/tests/fileExplorer.test.ts @@ -21,70 +21,74 @@ module.exports = { .clickLaunchIcon('fileExplorers') .assert.containsText('h6[data-id="sidePanelSwapitTitle"]', 'FILE EXPLORERS') .click('*[data-id="fileExplorerNewFilecreateNewFile"]') - .waitForElementVisible('*[data-id="modalDialogContainer"]') - .setValue('*[data-id="modalDialogCustomPromptText"]', '5_New_contract.sol') - .modalFooterOKClick() - .waitForElementVisible('*[data-id="treeViewLibrowser/5_New_contract.sol"]', 7000) + .pause(1000) + .waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/blank"]') + .sendKeys('*[data-id="treeViewLitreeViewItembrowser/blank"] .remixui_items', '5_New_contract.sol') + .sendKeys('*[data-id="treeViewLitreeViewItembrowser/blank"] .remixui_items', browser.Keys.ENTER) + .waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/5_New_contract.sol"]', 7000) }, 'Should rename `5_New_contract.sol` to 5_Renamed_Contract.sol': function (browser: NightwatchBrowser) { browser - .waitForElementVisible('*[data-id="treeViewLibrowser/5_New_contract.sol"]') - .renameFile('browser/5_New_contract.sol', '5_Renamed_Contract.sol', 'browser/5_Renamed_Contract.sol') - .waitForElementVisible('*[data-id="treeViewLibrowser/5_Renamed_Contract.sol"]') + .waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/5_New_contract.sol"]') + .renamePath('browser/5_New_contract.sol', '5_Renamed_Contract.sol', 'browser/5_Renamed_Contract.sol') + .waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/5_Renamed_Contract.sol"]') }, 'Should delete file `5_Renamed_Contract.sol` from file explorer': function (browser: NightwatchBrowser) { browser - .waitForElementVisible('*[data-id="treeViewLibrowser/5_Renamed_Contract.sol"]') + .waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/5_Renamed_Contract.sol"]') .rightClick('[data-path="browser/5_Renamed_Contract.sol"]') .click('*[id="menuitemdelete"]') - .waitForElementVisible('*[data-id="modalDialogContainer"]') - .modalFooterOKClick() - .waitForElementNotPresent('*[data-id="treeViewLibrowser/5_Renamed_Contract.sol"') + .waitForElementVisible('*[data-id="browserModalDialogContainer-react"]') + .pause(2000) + .click('.modal-ok') + .waitForElementNotPresent('*[data-id="treeViewLitreeViewItembrowser/5_Renamed_Contract.sol"') }, 'Should create a new folder': function (browser: NightwatchBrowser) { browser - .waitForElementVisible('*[data-id="treeViewLibrowser/README.txt"]') - .rightClick('[data-path="browser/README.txt"]') - .click('*[id="menuitemcreate folder"]') - .waitForElementVisible('*[data-id="modalDialogContainer"]') - .setValue('*[data-id="modalDialogCustomPromptText"]', 'Browser_Tests') - .modalFooterOKClick() - .waitForElementVisible('*[data-id="treeViewLibrowser/Browser_Tests"]') + .waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/README.txt"]') + .click('[data-id="fileExplorerNewFilecreateNewFolder"]') + .pause(1000) + .waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/blank"]') + .sendKeys('*[data-id="treeViewLitreeViewItembrowser/blank"] .remixui_items', 'Browser_Tests') + .sendKeys('*[data-id="treeViewLitreeViewItembrowser/blank"] .remixui_items', browser.Keys.ENTER) + .waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/Browser_Tests"]') }, 'Should rename Browser_Tests folder to Browser_E2E_Tests': function (browser: NightwatchBrowser) { browser - .waitForElementVisible('*[data-id="treeViewLibrowser/Browser_Tests"]') - .rightClick('[data-path="browser/Browser_Tests"]') - .click('*[id="menuitemrename"]') - .sendKeys('[data-path="browser/Browser_Tests"]', 'Browser_E2E_Tests') - .sendKeys('[data-path="browser/Browser_Tests"]', browser.Keys.ENTER) - .waitForElementVisible('*[data-id="treeViewLibrowser/Browser_E2E_Tests"]') + .waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/Browser_Tests"]') + .renamePath('browser/Browser_Tests', 'Browser_E2E_Tests', 'browser/Browser_E2E_Tests') + .waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/Browser_E2E_Tests"]') }, 'Should delete Browser_E2E_Tests folder': function (browser: NightwatchBrowser) { browser - .waitForElementVisible('*[data-id="treeViewLibrowser/Browser_E2E_Tests"]') + .waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/Browser_E2E_Tests"]') .rightClick('[data-path="browser/Browser_E2E_Tests"]') .click('*[id="menuitemdelete"]') - .waitForElementVisible('*[data-id="modalDialogContainer"]') - .modalFooterOKClick() - .waitForElementNotPresent('*[data-id="treeViewLibrowser/Browser_E2E_Tests"]') + .waitForElementVisible('*[data-id="browserModalDialogContainer-react"]') + .pause(2000) + .click('.modal-ok') + .waitForElementNotPresent('*[data-id="treeViewLitreeViewItembrowser/Browser_E2E_Tests"]') }, 'Should publish all explorer files to github gist': function (browser: NightwatchBrowser) { const runtimeBrowser = browser.options.desiredCapabilities.browserName - browser + browser.refresh() + .pause(10000) .waitForElementVisible('*[data-id="fileExplorerNewFilepublishToGist"]') .click('*[data-id="fileExplorerNewFilepublishToGist"]') - .waitForElementVisible('*[data-id="modalDialogContainer"]') - .modalFooterOKClick() - .waitForElementVisible('*[data-id="modalDialogContainer"]', 7000) - .modalFooterOKClick() + .waitForElementVisible('*[data-id="browserModalDialogContainer-react"]') + .pause(2000) + .click('.modal-ok') + .pause(2000) + .waitForElementVisible('*[data-id="browserModalDialogContainer-react"]') + .pause(2000) + .click('.modal-ok') .pause(2000) .perform((done) => { if (runtimeBrowser === 'chrome') { @@ -101,9 +105,9 @@ module.exports = { .setValue('*[data-id="fileExplorerFileUpload"]', testData.testFile1) .setValue('*[data-id="fileExplorerFileUpload"]', testData.testFile2) .setValue('*[data-id="fileExplorerFileUpload"]', testData.testFile3) - .waitForElementVisible('*[key="browser/editor.test.js"]') - .waitForElementVisible('*[key="browser/fileExplorer.test.js"]') - .waitForElementVisible('*[key="browser/generalSettings.test.js"]') + .waitForElementVisible('[data-id="treeViewLitreeViewItembrowser/editor.test.js"]') + .waitForElementVisible('[data-id="treeViewLitreeViewItembrowser/fileExplorer.test.js"]') + .waitForElementVisible('[data-id="treeViewLitreeViewItembrowser/generalSettings.test.js"]') .end() }, diff --git a/apps/remix-ide-e2e/src/tests/fileManager_api.test.ts b/apps/remix-ide-e2e/src/tests/fileManager_api.test.ts index 80d0653a8e..2eb4c73d00 100644 --- a/apps/remix-ide-e2e/src/tests/fileManager_api.test.ts +++ b/apps/remix-ide-e2e/src/tests/fileManager_api.test.ts @@ -63,7 +63,7 @@ module.exports = { .addFile('renameFile.js', { content: executeRename }) .executeScript(`remix.exeCurrent()`) .pause(2000) - .waitForElementPresent('[data-id="treeViewLibrowser/old_contract.sol"]') + .waitForElementPresent('[data-id="treeViewLitreeViewItembrowser/old_contract.sol"]') }, 'Should execute `mkdir` api from file manager external api': function (browser: NightwatchBrowser) { @@ -71,7 +71,7 @@ module.exports = { .addFile('mkdirFile.js', { content: executeMkdir }) .executeScript(`remix.exeCurrent()`) .pause(2000) - .waitForElementPresent('[data-id="treeViewLibrowser/Test_Folder"]') + .waitForElementPresent('[data-id="treeViewLitreeViewItembrowser/Test_Folder"]') }, 'Should execute `readdir` api from file manager external api': function (browser: NightwatchBrowser) { @@ -87,15 +87,16 @@ module.exports = { .addFile('removeFile.js', { content: executeRemove }) .executeScript(`remix.exeCurrent()`) .pause(2000) - .waitForElementNotPresent('[data-id="treeViewLibrowser/old_contract.sol"]') + .waitForElementNotPresent('[data-id="treeViewLitreeViewItembrowser/old_contract.sol"]') }, - 'Should execute `remove` api from file manager external api on a folder': function (browser: NightwatchBrowser) { + // TODO: Fix remove root directory prefix for browser and localhost + 'Should execute `remove` api from file manager external api on a folder': '' + function (browser: NightwatchBrowser) { browser .addFile('test_jsRemoveFolder.js', { content: executeRemoveOnFolder }) .executeScript('remix.exeCurrent()') .pause(2000) - .waitForElementNotPresent('*[key="browser/tests"]') + .waitForElementNotPresent('[data-id="treeViewLitreeViewItembrowser/tests"]') .end() }, diff --git a/apps/remix-ide-e2e/src/tests/generalSettings.test.ts b/apps/remix-ide-e2e/src/tests/generalSettings.test.ts index daa94963d3..f06d093ea6 100644 --- a/apps/remix-ide-e2e/src/tests/generalSettings.test.ts +++ b/apps/remix-ide-e2e/src/tests/generalSettings.test.ts @@ -20,7 +20,7 @@ module.exports = { browser.waitForElementVisible('*[data-id="remixIdeSidePanel"]', 5000) .waitForElementVisible('*[data-id="settingsTabGenerateContractMetadataLabel"]', 5000) .click('*[data-id="verticalIconsFileExplorerIcons"]') - .click('*[data-id="treeViewTogglebrowser/contracts"]') + .click('[data-id="treeViewLitreeViewItembrowser/contracts"]') .openFile('browser/contracts/3_Ballot.sol') .click('*[data-id="verticalIconsKindsolidity"]') .pause(2000) diff --git a/apps/remix-ide-e2e/src/tests/gist.test.ts b/apps/remix-ide-e2e/src/tests/gist.test.ts index 9c75fced9a..4884904123 100644 --- a/apps/remix-ide-e2e/src/tests/gist.test.ts +++ b/apps/remix-ide-e2e/src/tests/gist.test.ts @@ -13,7 +13,7 @@ module.exports = { before: function (browser: NightwatchBrowser, done: VoidFunction) { init(browser, done) }, - 'UploadToGists': function (browser: NightwatchBrowser) { + UploadToGists: function (browser: NightwatchBrowser) { /* - set the access token - publish to gist @@ -24,18 +24,24 @@ module.exports = { const runtimeBrowser = browser.options.desiredCapabilities.browserName browser + .refresh() + .pause(10000) .waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000) - .clickLaunchIcon('fileExplorers') - .rightClick('[data-path="browser/README.txt"]') - .click('*[id="menuitemcreate folder"]') - .waitForElementVisible('*[data-id="modalDialogContainer"]') - .setValue('*[data-id="modalDialogCustomPromptText"]', 'Browser_Tests') - .modalFooterOKClick() - .waitForElementVisible('*[data-id="treeViewLibrowser/Browser_Tests"]') + .click('[data-id="fileExplorerNewFilecreateNewFolder"]') + .pause(1000) + .waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/blank"]') + .sendKeys('*[data-id="treeViewLitreeViewItembrowser/blank"] .remixui_items', 'Browser_Tests') + .sendKeys('*[data-id="treeViewLitreeViewItembrowser/blank"] .remixui_items', browser.Keys.ENTER) + .waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/Browser_Tests"]') .addFile('File.sol', { content: '' }) .click('*[data-id="fileExplorerNewFilepublishToGist"]') - .modalFooterOKClick() - .getModalBody((value, done) => { + .waitForElementVisible('*[data-id="browserModalDialogContainer-react"]') + .pause(2000) + .click('.modal-ok') + .pause(10000) + .getText('[data-id="browserModalDialogModalBody-react"]', (result) => { + console.log(result) + const value = typeof result.value === 'string' ? result.value : null const reg = /gist.github.com\/([^.]+)/ const id = value.match(reg) @@ -45,13 +51,12 @@ module.exports = { } else { const gistid = id[1] browser - .modalFooterCancelClick() + .click('[data-id="browser-modal-footer-cancel-react"]') .executeScript(`remix.loadgist('${gistid}')`) .perform((done) => { if (runtimeBrowser === 'chrome') { browser.openFile('browser/gists') } done() }) - .waitForElementVisible(`li[key="browser/gists/${gistid}"]`) - .click(`li[key="browser/gists/${gistid}"]`) + .waitForElementVisible(`[data-id="treeViewLitreeViewItembrowser/gists/${gistid}"]`) + .click(`[data-id="treeViewLitreeViewItembrowser/gists/${gistid}"]`) .openFile(`browser/gists/${gistid}/README.txt`) - .perform(done) } }) }, diff --git a/apps/remix-ide-e2e/src/tests/publishContract.test.ts b/apps/remix-ide-e2e/src/tests/publishContract.test.ts index 01c22165ea..671893a26e 100644 --- a/apps/remix-ide-e2e/src/tests/publishContract.test.ts +++ b/apps/remix-ide-e2e/src/tests/publishContract.test.ts @@ -16,10 +16,11 @@ module.exports = { browser .waitForElementVisible('#icon-panel', 10000) .clickLaunchIcon('fileExplorers') - .click('*[data-id="treeViewTogglebrowser/contracts"]') + .click('[data-id="treeViewLitreeViewItembrowser/contracts"]') .openFile('browser/contracts/3_Ballot.sol') .verifyContracts(['Ballot']) .click('#publishOnIpfs') + .pause(8000) .getModalBody((value, done) => { if (value.indexOf('Metadata of "ballot" was published successfully.') === -1) browser.assert.fail('ipfs deploy failed', '', '') if (value.indexOf('dweb:/ipfs') === -1) browser.assert.fail('ipfs deploy failed', '', '') @@ -31,6 +32,7 @@ module.exports = { 'Publish on Swarm': '' + function (browser: NightwatchBrowser) { browser .click('#publishOnSwarm') + .pause(8000) .getModalBody((value, done) => { if (value.indexOf('Metadata of "ballot" was successfully.') === -1) browser.assert.fail('swarm deploy failed', '', '') if (value.indexOf('bzz') === -1) browser.assert.fail('swarm deploy failed', '', '') @@ -43,24 +45,24 @@ module.exports = { browser .waitForElementVisible('#icon-panel') .clickLaunchIcon('fileExplorers') - .click('*[data-id="treeViewLibrowser/contracts"]') - .click('*[data-id="treeViewLibrowser/contracts"]') .openFile('browser/contracts/1_Storage.sol') .clickLaunchIcon('udapp') .waitForElementPresent('*[data-id="contractDropdownIpfsCheckbox"]') .click('*[data-id="contractDropdownIpfsCheckbox"]') .click('*[data-id="Deploy - transact (not payable)"]') - .pause(5000) - .assert.containsText('*[data-id="modalDialogModalBody"]', 'Metadata of "storage" was published successfully.') + .pause(8000) + .getModalBody((value, done) => { + if (value.indexOf('Metadata of "storage" was published successfully.') === -1) browser.assert.fail('ipfs deploy failed', '', '') + done() + }) .modalFooterOKClick() }, 'Should remember choice after page refresh': function (browser: NightwatchBrowser) { browser .refresh() - .waitForElementVisible('*[data-id="treeViewLibrowser/contracts"]') - .click('*[data-id="treeViewLibrowser/contracts"]') - .click('*[data-id="treeViewLibrowser/contracts"]') + .waitForElementVisible('[data-id="treeViewLitreeViewItembrowser/contracts"]') + .click('[data-id="treeViewLitreeViewItembrowser/contracts"]') .openFile('browser/contracts/1_Storage.sol') .clickLaunchIcon('udapp') .waitForElementPresent('*[data-id="contractDropdownIpfsCheckbox"]') diff --git a/apps/remix-ide-e2e/src/tests/remixd.test.ts b/apps/remix-ide-e2e/src/tests/remixd.test.ts index c45c95a660..d82f8a3800 100644 --- a/apps/remix-ide-e2e/src/tests/remixd.test.ts +++ b/apps/remix-ide-e2e/src/tests/remixd.test.ts @@ -121,7 +121,7 @@ function runTests (browser: NightwatchBrowser) { .setEditorValue('contract test1 { function get () returns (uint) { return 10; }}') .click('[data-path="localhost/folder1/contract_' + browserName + '.sol"]') // rename a file and check .pause(1000) - .renameFile('localhost/folder1/contract_' + browserName + '.sol', 'renamed_contract_' + browserName + '.sol', 'localhost/folder1/renamed_contract_' + browserName + '.sol') + .renamePath('localhost/folder1/contract_' + browserName + '.sol', 'renamed_contract_' + browserName + '.sol', 'localhost/folder1/renamed_contract_' + browserName + '.sol') .pause(1000) .removeFile('localhost/folder1/contract_' + browserName + '_toremove.sol') .perform(function (done) { diff --git a/apps/remix-ide-e2e/src/tests/runAndDeploy.ts b/apps/remix-ide-e2e/src/tests/runAndDeploy.ts index d318ea4f9c..5d7218bd2c 100644 --- a/apps/remix-ide-e2e/src/tests/runAndDeploy.ts +++ b/apps/remix-ide-e2e/src/tests/runAndDeploy.ts @@ -128,6 +128,7 @@ module.exports = { .waitForElementPresent('.transaction-status--submitted') .pause(25000) .switchBrowserTab(0) + .end() }, 'Should connect to Ethereum Main Network using MetaMask': '' + function (browser: NightwatchBrowser) { diff --git a/apps/remix-ide-e2e/src/tests/solidityImport.test.ts b/apps/remix-ide-e2e/src/tests/solidityImport.test.ts index e559e7805f..a34e974f50 100644 --- a/apps/remix-ide-e2e/src/tests/solidityImport.test.ts +++ b/apps/remix-ide-e2e/src/tests/solidityImport.test.ts @@ -48,6 +48,8 @@ module.exports = { 'Test Github Import - no branch specified': function (browser: NightwatchBrowser) { browser .setSolidityCompilerVersion('soljson-v0.6.2+commit.bacdbe57.js') // open-zeppelin moved to pragma ^0.6.0 (master branch) + .clickLaunchIcon('fileExplorers') + .click('li[data-id="treeViewLitreeViewItembrowser/README.txt"') .addFile('Untitled6.sol', sources[5]['browser/Untitled6.sol']) .clickLaunchIcon('fileExplorers') .verifyContracts(['test10', 'ERC20', 'SafeMath'], {wait: 10000}) @@ -55,6 +57,8 @@ module.exports = { 'Test Github Import - raw URL': function (browser: NightwatchBrowser) { browser + .clickLaunchIcon('fileExplorers') + .click('li[data-id="treeViewLitreeViewItembrowser/README.txt"') .addFile('Untitled7.sol', sources[6]['browser/Untitled7.sol']) .clickLaunchIcon('fileExplorers') .verifyContracts(['test11', 'ERC20', 'SafeMath'], {wait: 10000}) @@ -63,6 +67,8 @@ module.exports = { 'Test switch to a github import from a solidity warning': function (browser: NightwatchBrowser) { browser .setSolidityCompilerVersion('soljson-v0.7.4+commit.3f05b770.js') + .clickLaunchIcon('fileExplorers') + .click('li[data-id="treeViewLitreeViewItembrowser/README.txt"') .addFile('Untitled8.sol', sources[7]['browser/Untitled8.sol']) .clickLaunchIcon('fileExplorers') .clickLaunchIcon('solidity') diff --git a/apps/remix-ide-e2e/src/tests/solidityUnittests.test.ts b/apps/remix-ide-e2e/src/tests/solidityUnittests.test.ts index 6a465b9e7a..83a1071633 100644 --- a/apps/remix-ide-e2e/src/tests/solidityUnittests.test.ts +++ b/apps/remix-ide-e2e/src/tests/solidityUnittests.test.ts @@ -144,7 +144,8 @@ module.exports = { }, 'Changing current path': function (browser: NightwatchBrowser) { - browser.waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]') + 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') @@ -167,7 +168,7 @@ function runTests (browser: NightwatchBrowser) { browser .waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]') .clickLaunchIcon('fileExplorers') - .click('*[data-id="treeViewTogglebrowser/contracts"]') + .click('*[data-id="treeViewLitreeViewItembrowser/contracts"]') .openFile('browser/contracts/3_Ballot.sol') .clickLaunchIcon('solidityUnitTesting') .pause(500) diff --git a/apps/remix-ide-e2e/src/tests/usingWebWorker.test.ts b/apps/remix-ide-e2e/src/tests/usingWebWorker.test.ts index d5dc8f52cd..d987357954 100644 --- a/apps/remix-ide-e2e/src/tests/usingWebWorker.test.ts +++ b/apps/remix-ide-e2e/src/tests/usingWebWorker.test.ts @@ -28,7 +28,7 @@ module.exports = { browser .waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000) .clickLaunchIcon('fileExplorers') - .addFile('browser/basic.sol', sources[0]['browser/basic.sol']) + .addFile('basic.sol', sources[0]['browser/basic.sol']) .clickLaunchIcon('solidity') .execute(function() { const elem = document.getElementById('nightlies') as HTMLInputElement diff --git a/apps/remix-ide-e2e/src/tests/verticalIconsPanel.test.ts b/apps/remix-ide-e2e/src/tests/verticalIconsPanel.test.ts new file mode 100644 index 0000000000..c094e2b3c8 --- /dev/null +++ b/apps/remix-ide-e2e/src/tests/verticalIconsPanel.test.ts @@ -0,0 +1,35 @@ +'use strict' +import { NightwatchBrowser } from 'nightwatch' +import init from '../helpers/init' +import sauce from './sauce' + +module.exports = { + before: function (browser: NightwatchBrowser, done: VoidFunction) { + init(browser, done, 'http://127.0.0.1:8080', false) + }, + + 'Checks vertical icons panelcontex menu': function (browser: NightwatchBrowser) { + browser.waitForElementVisible('div[data-id="remixIdeIconPanel"]', 10000) + .waitForElementVisible('*[data-id="verticalIconsKindpluginManager"]') + .click('*[data-id="verticalIconsKindpluginManager"]') + .scrollAndClick('*[data-id="pluginManagerComponentActivateButtondebugger"]') + .waitForElementVisible('*[data-id="pluginManagerComponentDeactivateButtondebugger"]', 7000) + .rightClick('[data-id="verticalIconsKinddebugger"]') + .waitForElementVisible('*[id="menuitemdeactivate"]') + .waitForElementVisible('*[id="menuitemdocumentation"]') + .click('*[data-id="remixIdeIconPanel"]') + }, + + 'Checks vertical icons panel contex menu deactivate': function (browser: NightwatchBrowser) { + browser.waitForElementVisible('div[data-id="remixIdeIconPanel"]', 10000) + .waitForElementVisible('*[data-id="verticalIconsKinddebugger"]', 7000) + .rightClick('[data-id="verticalIconsKinddebugger"]') + .click('*[id="menuitemdeactivate"]') + .click('*[data-id="verticalIconsKindsettings"]') + .click('*[data-id="verticalIconsKindpluginManager"]') + .scrollInto('*[data-id="pluginManagerComponentActivateButtondebugger"]') + .waitForElementVisible('*[data-id="pluginManagerComponentActivateButtondebugger"]') + }, + + tearDown: sauce +} diff --git a/apps/remix-ide-e2e/src/types/index.d.ts b/apps/remix-ide-e2e/src/types/index.d.ts index afd92f7e2f..320cee78a4 100644 --- a/apps/remix-ide-e2e/src/types/index.d.ts +++ b/apps/remix-ide-e2e/src/types/index.d.ts @@ -28,7 +28,7 @@ declare module "nightwatch" { checkElementStyle(cssSelector: string, styleProperty: string, expectedResult: string): NightwatchBrowser, openFile(name: string): NightwatchBrowser, editorScroll(direction: 'up' | 'down', numberOfTimes: number): NightwatchBrowser, - renameFile(path: string, newFileName: string, renamedPath: string): NightwatchBrowser, + renamePath(path: string, newFileName: string, renamedPath: string): NightwatchBrowser, rightClick(cssSelector: string): NightwatchBrowser, waitForElementContainsText(id: string, value: string): NightwatchBrowser, getModalBody(callback: (value: string, cb: VoidFunction) => void): NightwatchBrowser, @@ -63,6 +63,10 @@ declare module "nightwatch" { sendKeys: (selector: string, inputValue: string | string[], callback?: (this: NightwatchAPI, result: NightwatchCallbackResult) => void) => NightwatchBrowser } + export interface NightwatchAPI { + keys(keysToSend: string, callback?: (this: NightwatchAPI, result: NightwatchCallbackResult) => void): NightwatchAPI + } + export interface NightwatchContractContent { content: string; } diff --git a/apps/remix-ide/src/app.js b/apps/remix-ide/src/app.js index fb1788e08c..042204cf07 100644 --- a/apps/remix-ide/src/app.js +++ b/apps/remix-ide/src/app.js @@ -50,7 +50,7 @@ const CompilersArtefacts = require('./app/compiler/compiler-artefacts') const CompileTab = require('./app/tabs/compile-tab') const SettingsTab = require('./app/tabs/settings-tab') const AnalysisTab = require('./app/tabs/analysis-tab') -const DebuggerTab = require('./app/tabs/debugger-tab') +const { DebuggerTab } = require('./app/tabs/debugger-tab') const TestTab = require('./app/tabs/test-tab') const FilePanel = require('./app/panels/file-panel') const Editor = require('./app/editor/editor') @@ -370,10 +370,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org registry.get('fileproviders/browser').api ) const analysis = new AnalysisTab(registry) - const debug = new DebuggerTab( - blockchain, - registry.get('editor').api, - registry.get('offsettolinecolumnconverter').api) + const debug = new DebuggerTab() const test = new TestTab( registry.get('filemanager').api, registry.get('offsettolinecolumnconverter').api, diff --git a/apps/remix-ide/src/app/compiler/compiler-sourceVerifier-fetchAndCompile.js b/apps/remix-ide/src/app/compiler/compiler-sourceVerifier-fetchAndCompile.js index d9fbdc5cce..4a513e2129 100644 --- a/apps/remix-ide/src/app/compiler/compiler-sourceVerifier-fetchAndCompile.js +++ b/apps/remix-ide/src/app/compiler/compiler-sourceVerifier-fetchAndCompile.js @@ -26,10 +26,11 @@ export default class FetchAndCompile extends Plugin { * Returns compilation data * * @param {string} contractAddress - Address of the contrac to resolve - * @param {string} compilersartefacts - Object containing a mapping of compilation results (byContractAddress and __last) + * @param {string} deployedBytecode - deployedBytecode of the contract + * @param {string} targetPath - Folder where to save the compilation arfefacts * @return {CompilerAbstract} - compilation data targeting the given @arg contractAddress */ - async resolve (contractAddress, targetPath, web3) { + async resolve (contractAddress, codeAtAddress, targetPath) { contractAddress = ethutil.toChecksumAddress(contractAddress) const compilersartefacts = globalRegistry.get('compilersartefacts').api @@ -52,7 +53,6 @@ export default class FetchAndCompile extends Plugin { if (!this.sourceVerifierNetWork.includes(network.name)) return localCompilation() // check if the contract if part of the local compilation result - const codeAtAddress = await web3.eth.getCode(contractAddress) const compilation = localCompilation() if (compilation) { let found = false diff --git a/apps/remix-ide/src/app/components/local-plugin.js b/apps/remix-ide/src/app/components/local-plugin.js index 1db3cae6e5..c93bb6775b 100644 --- a/apps/remix-ide/src/app/components/local-plugin.js +++ b/apps/remix-ide/src/app/components/local-plugin.js @@ -67,11 +67,20 @@ module.exports = class LocalPlugin { this.profile[key] = e.target.value } + updateMethods ({ target }) { + if (target.value) { + try { + this.profile.methods = target.value.split(',') + } catch (e) {} + } + } + /** The form to create a local plugin */ form () { const name = this.profile.name || '' const url = this.profile.url || '' const displayName = this.profile.displayName || '' + const methods = (this.profile.methods && this.profile.methods.join(',')) || '' const radioSelection = (key, label, message) => { return this.profile[key] === label ? yo`
@@ -94,6 +103,12 @@ module.exports = class LocalPlugin {
+ +
+ + +
+
diff --git a/apps/remix-ide/src/app/components/vertical-icons.js b/apps/remix-ide/src/app/components/vertical-icons.js index 855050926a..35b9f0ac17 100644 --- a/apps/remix-ide/src/app/components/vertical-icons.js +++ b/apps/remix-ide/src/app/components/vertical-icons.js @@ -4,9 +4,10 @@ var yo = require('yo-yo') var csjs = require('csjs-inject') var helper = require('../../lib/helper') const globalRegistry = require('../../global/registry') +const contextMenu = require('../ui/contextMenu') const { Plugin } = require('@remixproject/engine') - const EventEmitter = require('events') +let VERTICALMENU_HANDLE const profile = { name: 'menuicons', @@ -63,7 +64,7 @@ export class VerticalIcons extends Plugin { * Add an icon to the map * @param {ModuleProfile} profile The profile of the module */ - addIcon ({ kind, name, icon, displayName, tooltip }) { + addIcon ({ kind, name, icon, displayName, tooltip, documentation }) { let title = (tooltip || displayName || name) title = title.replace(/^\w/, c => c.toUpperCase()) this.icons[name] = yo` @@ -72,6 +73,7 @@ export class VerticalIcons extends Plugin { onclick="${() => { this.toggle(name) }}" plugin="${name}" title="${title}" + oncontextmenu="${(e) => this.itemContextMenu(e, name, documentation)}" data-id="verticalIconsKind${name}"> ${name}
` @@ -221,6 +223,26 @@ export class VerticalIcons extends Plugin { } } + async itemContextMenu (e, name, documentation) { + const actions = {} + if (await this.appManager.canDeactivatePlugin(profile, { name })) { + actions.Deactivate = () => { + // this.call('manager', 'deactivatePlugin', name) + this.appManager.deactivatePlugin(name) + } + } + const links = {} + if (documentation) { + links.Documentation = documentation + } + if (Object.keys(actions).length || Object.keys(links).length) { + VERTICALMENU_HANDLE && VERTICALMENU_HANDLE.hide(null, true) + VERTICALMENU_HANDLE = contextMenu(e, actions, links) + } + e.preventDefault() + e.stopPropagation() + } + render () { const home = yo`
{ this._onChange() - this.event.trigger('sessionSwitched', []) + this.triggerEvent('sessionSwitched', []) this.editor.getSession().on('change', () => { this._onChange() this.sourceHighlighters.discardAllHighlights() - this.event.trigger('contentChanged', []) + this.triggerEvent('contentChanged', []) }) }) } + triggerEvent (name, params) { + this.event.trigger(name, params) // internal stack + this.emit(name, ...params) // plugin stack + } + onActivation () { this.on('sidePanel', 'focusChanged', (name) => this.sourceHighlighters.hideHighlightsExcept(name)) this.on('sidePanel', 'pluginDisabled', (name) => this.sourceHighlighters.discardHighlight(name)) @@ -247,7 +252,7 @@ class Editor extends Plugin { window.clearTimeout(this.saveTimeout) } this.saveTimeout = window.setTimeout(() => { - this.event.trigger('requiringToSaveCurrentfile', []) + this.triggerEvent('requiringToSaveCurrentfile', []) }, 5000) } diff --git a/apps/remix-ide/src/app/files/fileManager.js b/apps/remix-ide/src/app/files/fileManager.js index eef16bdb51..f46d76dd36 100644 --- a/apps/remix-ide/src/app/files/fileManager.js +++ b/apps/remix-ide/src/app/files/fileManager.js @@ -424,15 +424,15 @@ class FileManager extends Plugin { } fileRemovedEvent (path) { + // TODO: Only keep `this.emit` (issue#2210) + this.emit('fileRemoved', path) + this.events.emit('fileRemoved', path) if (!this.openedFiles[path]) return if (path === this._deps.config.get('currentFile')) { this._deps.config.set('currentFile', '') } this.editor.discard(path) delete this.openedFiles[path] - // TODO: Only keep `this.emit` (issue#2210) - this.emit('fileRemoved', path) - this.events.emit('fileRemoved', path) this.openFile() } diff --git a/apps/remix-ide/src/app/files/remixDProvider.js b/apps/remix-ide/src/app/files/remixDProvider.js index ecbd416581..8579b516be 100644 --- a/apps/remix-ide/src/app/files/remixDProvider.js +++ b/apps/remix-ide/src/app/files/remixDProvider.js @@ -115,6 +115,13 @@ module.exports = class RemixDProvider { }) } + async createDir (path, cb) { + if (!this._isReady) return cb && cb('provider not ready') + const unprefixedpath = this.removePrefix(path) + + return this._appManager.call('remixd', 'createDir', { path: unprefixedpath }) + } + isReadOnly (path) { return this._readOnlyMode || this._readOnlyFiles[path] === 1 } diff --git a/apps/remix-ide/src/app/files/remixd-handle.js b/apps/remix-ide/src/app/files/remixd-handle.js index 311883e020..8d6bff9ee8 100644 --- a/apps/remix-ide/src/app/files/remixd-handle.js +++ b/apps/remix-ide/src/app/files/remixd-handle.js @@ -22,7 +22,7 @@ const profile = { name: 'remixd', displayName: 'RemixD', url: 'ws://127.0.0.1:65520', - methods: ['folderIsReadOnly', 'resolveDirectory', 'get', 'exists', 'isFile', 'set', 'rename', 'remove', 'isDirectory', 'list'], + methods: ['folderIsReadOnly', 'resolveDirectory', 'get', 'exists', 'isFile', 'set', 'rename', 'remove', 'isDirectory', 'list', 'createDir'], events: [], description: 'Using Remixd daemon, allow to access file system', kind: 'other', @@ -47,7 +47,6 @@ export class RemixdHandle extends WebsocketPlugin { } activate () { - this.fileSystemExplorer.show() this.connectToLocalhost() } @@ -83,7 +82,9 @@ export class RemixdHandle extends WebsocketPlugin { this.canceled() } }, 3000) - this.locahostProvider.init(_ => this.fileSystemExplorer.ensureRoot()) + this.locahostProvider.init(() => { + this.fileSystemExplorer.show() + }) this.call('manager', 'activatePlugin', 'git') } } diff --git a/apps/remix-ide/src/app/panels/file-panel.js b/apps/remix-ide/src/app/panels/file-panel.js index e210ca8ef0..9eb9a04c04 100644 --- a/apps/remix-ide/src/app/panels/file-panel.js +++ b/apps/remix-ide/src/app/panels/file-panel.js @@ -1,13 +1,16 @@ import { ViewPlugin } from '@remixproject/engine-web' import * as packageJson from '../../../../../package.json' +import React from 'react' // eslint-disable-line +import ReactDOM from 'react-dom' +import { FileExplorer } from '@remix-ui/file-explorer' // eslint-disable-line +import './styles/file-panel-styles.css' var yo = require('yo-yo') var EventManager = require('../../lib/events') -var FileExplorer = require('../files/file-explorer') +// var FileExplorer = require('../files/file-explorer') var { RemixdHandle } = require('../files/remixd-handle.js') var { GitHandle } = require('../files/git-handle.js') var globalRegistry = require('../../global/registry') -var css = require('./styles/file-panel-styles') var canUpload = window.File || window.FileReader || window.FileList || window.Blob @@ -44,63 +47,85 @@ const profile = { module.exports = class Filepanel extends ViewPlugin { constructor (appManager) { super(profile) - var self = this - self._components = {} - self._components.registry = globalRegistry - self._deps = { - fileProviders: self._components.registry.get('fileproviders').api, - fileManager: self._components.registry.get('filemanager').api, - config: self._components.registry.get('config').api + this._components = {} + this._components.registry = globalRegistry + this._deps = { + fileProviders: this._components.registry.get('fileproviders').api, + fileManager: this._components.registry.get('filemanager').api, + config: this._components.registry.get('config').api } - - function createProvider (key, menuItems) { - return new FileExplorer(self._components.registry, self._deps.fileProviders[key], menuItems, self) + this.hideRemixdExplorer = true + this.remixdExplorer = { + hide: () => { + this.hideRemixdExplorer = true + this.renderComponent() + }, + show: () => { + this.hideRemixdExplorer = false + this.renderComponent() + } } - - var fileExplorer = createProvider('browser', ['createNewFile', 'publishToGist', canUpload ? 'uploadFile' : '']) - var fileSystemExplorer = createProvider('localhost') - - self.remixdHandle = new RemixdHandle(fileSystemExplorer, self._deps.fileProviders.localhost, appManager) - self.gitHandle = new GitHandle() - - const explorers = yo` -
-
${fileExplorer.init()}
-
${fileSystemExplorer.init()}
+ this.el = yo` +
` - function template () { - return yo` -
-
-
- ${explorers} -
-
-
- ` - } + this.remixdHandle = new RemixdHandle(this.remixdExplorer, this._deps.fileProviders.localhost, appManager) + this.gitHandle = new GitHandle() - var event = new EventManager() - self.event = event - var element = template() - fileExplorer.ensureRoot() - self._deps.fileProviders.localhost.event.register('connecting', (event) => { + this.event = new EventManager() + this._deps.fileProviders.localhost.event.register('connecting', (event) => { }) - self._deps.fileProviders.localhost.event.register('connected', (event) => { - fileSystemExplorer.show() + this._deps.fileProviders.localhost.event.register('connected', (event) => { + this.remixdExplorer.show() }) - self._deps.fileProviders.localhost.event.register('errored', (event) => { - fileSystemExplorer.hide() + this._deps.fileProviders.localhost.event.register('errored', (event) => { + this.remixdExplorer.hide() }) - self._deps.fileProviders.localhost.event.register('closed', (event) => { - fileSystemExplorer.hide() + this._deps.fileProviders.localhost.event.register('closed', (event) => { + this.remixdExplorer.hide() }) - self.render = function render () { return element } + this.renderComponent() + } + + render () { + return this.el + } + + renderComponent () { + ReactDOM.render( +
+
+
+
+
+ +
+
+ { !this.hideRemixdExplorer && + + } +
+
+
+
+
+ , this.el) } } diff --git a/apps/remix-ide/src/app/panels/styles/file-panel-styles.css b/apps/remix-ide/src/app/panels/styles/file-panel-styles.css new file mode 100644 index 0000000000..087c59e8e3 --- /dev/null +++ b/apps/remix-ide/src/app/panels/styles/file-panel-styles.css @@ -0,0 +1,56 @@ +.remixui_container { + display : flex; + flex-direction : row; + width : 100%; + height : 100%; + box-sizing : border-box; +} +.remixui_fileexplorer { + display : flex; + flex-direction : column; + position : relative; + width : 100%; + padding-left : 6px; + padding-top : 6px; +} +.remixui_fileExplorerTree { + cursor : default; +} +.remixui_gist { + padding : 10px; +} +.remixui_gist i { + cursor : pointer; +} +.remixui_gist i:hover { + color : orange; +} +.remixui_connectToLocalhost { + padding : 10px; +} +.remixui_connectToLocalhost i { + cursor : pointer; +} +.remixui_connectToLocalhost i:hover { + color : var(--secondary) +} +.remixui_uploadFile { + padding : 10px; +} +.remixui_uploadFile label:hover { + color : var(--secondary) +} +.remixui_uploadFile label { + cursor : pointer; +} +.remixui_treeview { + overflow-y : auto; +} +.remixui_dialog { + display: flex; + flex-direction: column; +} +.remixui_dialogParagraph { + margin-bottom: 2em; + word-break: break-word; +} diff --git a/apps/remix-ide/src/app/panels/tab-proxy.js b/apps/remix-ide/src/app/panels/tab-proxy.js index dc571258e4..6af15ad7c3 100644 --- a/apps/remix-ide/src/app/panels/tab-proxy.js +++ b/apps/remix-ide/src/app/panels/tab-proxy.js @@ -194,7 +194,7 @@ export class TabProxy extends Plugin { } this._view.filetabs.addTab({ - id: name, + id: name.split(' ').join(''), title, icon, tooltip: name diff --git a/apps/remix-ide/src/app/tabs/debugger-tab.js b/apps/remix-ide/src/app/tabs/debugger-tab.js index b471ecb320..3b218fed58 100644 --- a/apps/remix-ide/src/app/tabs/debugger-tab.js +++ b/apps/remix-ide/src/app/tabs/debugger-tab.js @@ -1,7 +1,7 @@ import toaster from '../ui/tooltip' import { DebuggerUI } from '@remix-ui/debugger-ui' // eslint-disable-line +import { DebuggerApiMixin } from '@remixproject/debugger-plugin' import { ViewPlugin } from '@remixproject/engine-web' -import remixDebug, { TransactionDebugger as Debugger } from '@remix-project/remix-debug' import * as packageJson from '../../../../../package.json' import React from 'react' // eslint-disable-line import ReactDOM from 'react-dom' @@ -21,16 +21,11 @@ const profile = { version: packageJson.version } -class DebuggerTab extends ViewPlugin { - constructor (blockchain, editor, offsetToLineColumnConverter) { +export class DebuggerTab extends DebuggerApiMixin(ViewPlugin) { + constructor () { super(profile) this.el = null - this.editor = editor - this.offsetToLineColumnConverter = offsetToLineColumnConverter - this.blockchain = blockchain - this.debugHash = null - this.removeHighlights = false - this.debugHashRequest = 0 + this.initDebuggerApi() } render () { @@ -63,90 +58,12 @@ class DebuggerTab extends ViewPlugin { this.renderComponent() - // this.call('manager', 'activatePlugin', 'udapp') - return this.el } - async discardHighlight () { - await this.call('editor', 'discardHighlight') - } - - async highlight (lineColumnPos, path) { - await this.call('editor', 'highlight', lineColumnPos, path) - } - - async getFile (path) { - await this.call('fileManager', 'getFile', path) - } - - async setFile (path, content) { - await this.call('fileManager', 'setFile', path, content) - } - renderComponent () { ReactDOM.render( , this.el) } - - deactivate () { - this.removeHighlights = true - this.renderComponent() - super.deactivate() - } - - debug (hash) { - this.debugHash = hash - this.debugHashRequest++ // so we can trigger a debug using the same hash 2 times in a row. that's needs to be improved - this.renderComponent() - } - - getDebugWeb3 () { - return new Promise((resolve, reject) => { - this.blockchain.detectNetwork((error, network) => { - let web3 - if (error || !network) { - web3 = remixDebug.init.web3DebugNode(this.blockchain.web3()) - } else { - const webDebugNode = remixDebug.init.web3DebugNode(network.name) - web3 = !webDebugNode ? this.blockchain.web3() : webDebugNode - } - remixDebug.init.extendWeb3(web3) - resolve(web3) - }) - }) - } - - async getTrace (hash) { - if (!hash) return - const web3 = await this.getDebugWeb3() - const currentReceipt = await web3.eth.getTransactionReceipt(hash) - const debug = new Debugger({ - web3, - offsetToLineColumnConverter: this.offsetToLineColumnConverter, - compilationResult: async (address) => { - try { - return await this.fetchContractAndCompile(address, currentReceipt) - } catch (e) { - console.error(e) - } - return null - }, - debugWithGeneratedSources: false - }) - return await debug.debugger.traceManager.getTrace(hash) - } - - fetchContractAndCompile (address, receipt) { - const target = (address && remixDebug.traceHelper.isContractCreation(address)) ? receipt.contractAddress : address - const targetAddress = target || receipt.contractAddress || receipt.to - return this.call('fetchAndCompile', 'resolve', targetAddress, 'browser/.debug', this.blockchain.web3()) - } - - // debugger () { - // return this.debuggerUI - // } } - -module.exports = DebuggerTab diff --git a/apps/remix-ide/src/app/tabs/test-tab.js b/apps/remix-ide/src/app/tabs/test-tab.js index 807e7b5c34..e1853ae500 100644 --- a/apps/remix-ide/src/app/tabs/test-tab.js +++ b/apps/remix-ide/src/app/tabs/test-tab.js @@ -52,7 +52,7 @@ module.exports = class TestTab extends ViewPlugin { listenToEvents () { this.filePanel.event.register('newTestFileCreated', file => { - var testList = this.view.querySelector("[class^='testList']") + var testList = this._view.el.querySelector("[class^='testList']") var test = this.createSingleTest(file) testList.appendChild(test) this.data.allTests.push(file) diff --git a/apps/remix-ide/src/app/ui/contextMenu.js b/apps/remix-ide/src/app/ui/contextMenu.js index f97720c6cd..0bc2dae605 100644 --- a/apps/remix-ide/src/app/ui/contextMenu.js +++ b/apps/remix-ide/src/app/ui/contextMenu.js @@ -30,7 +30,7 @@ var css = csjs` } ` -module.exports = (event, items) => { +module.exports = (event, items, linkItems) => { event.preventDefault() function hide (event, force) { @@ -45,7 +45,21 @@ module.exports = (event, items) => { current.onclick = () => { hide(null, true); items[item]() } return current }) - const container = yo`` + + let menuForLinks = yo`` + if (linkItems) { + menuForLinks = Object.keys(linkItems).map((item, index) => { + const current = yo`` + current.onclick = () => { hide(null, true) } + return current + }) + } + + const container = yo` + + ` container.style.left = event.pageX + 'px' container.style.top = event.pageY + 'px' diff --git a/apps/remix-ide/src/app/ui/modaldialog.js b/apps/remix-ide/src/app/ui/modaldialog.js index 7d336a4121..1aeae287a4 100644 --- a/apps/remix-ide/src/app/ui/modaldialog.js +++ b/apps/remix-ide/src/app/ui/modaldialog.js @@ -6,10 +6,10 @@ module.exports = (title, content, ok, cancel, focusSelector, opts) => { let agreed = true let footerIsActive = false opts = opts || {} - var container = document.querySelector('.modal') + var container = document.getElementById('modal-dialog') if (!container) { document.querySelector('body').appendChild(html(opts)) - container = document.querySelector('.modal') + container = document.getElementById('modal-dialog') incomingModal = false } else incomingModal = true @@ -24,8 +24,8 @@ module.exports = (title, content, ok, cancel, focusSelector, opts) => { cancelDiv.innerHTML = (cancel && cancel.label !== undefined) ? cancel.label : 'Cancel' cancelDiv.style.display = cancelDiv.innerHTML === '' ? 'none' : 'inline-block' - var modal = document.querySelector('.modal-body') - var modalTitle = document.querySelector('.modal-header h6') + var modal = document.getElementById('modal-body-id') + var modalTitle = document.getElementById('modal-title-h6') modalTitle.innerHTML = '' if (title) modalTitle.innerText = title @@ -134,12 +134,12 @@ function html (opts) {