Merge branch 'master' of https://github.com/ethereum/remix-project into linetexts

pull/5370/head
bunsenstraat 3 years ago
commit 2078995b1e
  1. 2
      .circleci/config.yml
  2. 8
      apps/remix-ide-e2e/nightwatch.ts
  3. 4
      apps/remix-ide-e2e/src/commands/executeScriptInTerminal.ts
  4. 3
      apps/remix-ide-e2e/src/commands/getEditorValue.ts
  5. 4
      apps/remix-ide-e2e/src/commands/journalChildIncludes.ts
  6. 11
      apps/remix-ide-e2e/src/commands/openFile.ts
  7. 8
      apps/remix-ide-e2e/src/commands/rightClickCustom.ts
  8. 4
      apps/remix-ide-e2e/src/commands/switchWorkspace.ts
  9. 11
      apps/remix-ide-e2e/src/commands/testFunction.ts
  10. 2
      apps/remix-ide-e2e/src/commands/validateValueInput.ts
  11. 2
      apps/remix-ide-e2e/src/helpers/init.ts
  12. 7
      apps/remix-ide-e2e/src/select_tests.sh
  13. 8
      apps/remix-ide-e2e/src/tests/compiler_api.test.ts
  14. 4
      apps/remix-ide-e2e/src/tests/debugger.test.ts
  15. 2
      apps/remix-ide-e2e/src/tests/defaultLayout.test.ts
  16. 6
      apps/remix-ide-e2e/src/tests/editor.test.ts
  17. 30
      apps/remix-ide-e2e/src/tests/fileExplorer.test.ts
  18. 24
      apps/remix-ide-e2e/src/tests/fileManager_api.test.ts
  19. 4
      apps/remix-ide-e2e/src/tests/gist.test.ts
  20. 4
      apps/remix-ide-e2e/src/tests/importFromGithub.test.ts
  21. 2
      apps/remix-ide-e2e/src/tests/pluginManager.test.ts
  22. 8
      apps/remix-ide-e2e/src/tests/plugin_api.ts
  23. 4
      apps/remix-ide-e2e/src/tests/remixd.test.ts
  24. 20
      apps/remix-ide-e2e/src/tests/runAndDeploy.test.ts
  25. 4
      apps/remix-ide-e2e/src/tests/search.test.ts
  26. 12
      apps/remix-ide-e2e/src/tests/solidityUnittests.test.ts
  27. 26
      apps/remix-ide-e2e/src/tests/specialFunctions.test.ts
  28. 4
      apps/remix-ide-e2e/src/tests/staticAnalysis.test.ts
  29. 62
      apps/remix-ide-e2e/src/tests/terminal.test.ts
  30. 4
      apps/remix-ide-e2e/src/tests/transactionExecution.test.ts
  31. 6
      apps/remix-ide-e2e/src/tests/txListener.test.ts
  32. 58
      apps/remix-ide-e2e/src/tests/url.test.ts
  33. 4
      apps/remix-ide-e2e/src/tests/verticalIconsPanel.test.ts
  34. 309
      apps/remix-ide-e2e/src/tests/workspace.test.ts
  35. 4
      apps/remix-ide-e2e/src/types/index.d.ts
  36. 3
      apps/remix-ide/ci/browser_test.sh
  37. 2
      apps/remix-ide/src/app/panels/file-panel.js
  38. 2
      apps/remix-ide/src/blockchain/execution-context.js
  39. 3
      apps/solidity-compiler/src/app/compiler-api.ts
  40. 2
      apps/vyper/src/app/app.tsx
  41. 2
      libs/remix-analyzer/test/analysis/staticAnalysisIntegration-test-0.4.24.ts
  42. 36
      libs/remix-core-plugin/src/lib/helpers/fetch-etherscan.ts
  43. 12
      libs/remix-tests/src/run.ts
  44. 3
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/global-variables.tsx
  45. 133
      libs/remix-ui/editor/src/lib/cairoSyntax.ts
  46. 20
      libs/remix-ui/editor/src/lib/remix-ui-editor.tsx
  47. 132
      libs/remix-ui/editor/src/lib/syntaxes/cairo.ts
  48. 4
      libs/remix-ui/editor/src/lib/syntaxes/solidity.ts
  49. 144
      libs/remix-ui/editor/src/lib/syntaxes/zokrates.ts
  50. 2
      libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx
  51. 13
      libs/remix-ui/run-tab/src/lib/components/recorderCardUI.tsx
  52. 6
      libs/remix-ui/search/src/lib/context/context.tsx
  53. 6
      libs/remix-ui/settings/src/lib/github-settings.tsx
  54. 14
      libs/remix-ui/settings/src/lib/remix-ui-settings.tsx
  55. 18
      libs/remix-ui/solidity-unit-testing/src/lib/solidity-unit-testing.tsx
  56. 10
      libs/remix-ui/static-analyser/src/lib/Button/StaticAnalyserButton.tsx
  57. 70
      libs/remix-ui/static-analyser/src/lib/remix-ui-static-analyser.tsx
  58. 12
      libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx
  59. 16
      libs/remix-ui/workspace/src/lib/actions/index.ts
  60. 9
      package.json
  61. 1599
      yarn.lock

@ -8,7 +8,7 @@ parameters:
type: boolean
default: false
orbs:
browser-tools: circleci/browser-tools@1.2.3
browser-tools: circleci/browser-tools@1.3.0
jobs:
build:
docker:

@ -29,7 +29,13 @@ module.exports = {
javascriptEnabled: true,
acceptSslCerts: true,
'goog:chromeOptions': {
args: ['window-size=2560,1440', 'start-fullscreen', '--no-sandbox', '--headless', '--verbose']
args: ['window-size=2560,1440',
'start-fullscreen',
'--no-sandbox',
'--headless',
'--verbose',
"--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36",
]
}
}
},

@ -1,7 +1,7 @@
import { NightwatchBrowser } from 'nightwatch'
import EventEmitter from 'events'
class ExecuteScript extends EventEmitter {
class ExecuteScriptInTerminal extends EventEmitter {
command (this: NightwatchBrowser, script: string): NightwatchBrowser {
this.api
.clearEditableContent('*[data-id="terminalCliInput"]')
@ -17,4 +17,4 @@ class ExecuteScript extends EventEmitter {
}
}
module.exports = ExecuteScript
module.exports = ExecuteScriptInTerminal

@ -9,11 +9,10 @@ class GetEditorValue extends EventEmitter {
return elem.currentContent()
}, [], (result) => {
done()
const value = typeof result.value === 'string' ? result.value : null
callback(value)
this.emit('complete')
done()
})
})
return this

@ -1,4 +1,4 @@
import { NightwatchBrowser } from 'nightwatch'
import { ELEMENT_KEY, NightwatchBrowser } from 'nightwatch'
import EventEmitter from 'events'
/*
@ -11,7 +11,7 @@ class JournalChildIncludes extends EventEmitter {
let occurence = 0
this.api.elements('css selector', '*[data-id="terminalJournal"]', (res) => {
Array.isArray(res.value) && res.value.forEach(function (jsonWebElement) {
const jsonWebElementId = jsonWebElement.ELEMENT || jsonWebElement[Object.keys(jsonWebElement)[0]]
const jsonWebElementId = jsonWebElement[ELEMENT_KEY] || jsonWebElement[Object.keys(jsonWebElement)[0]]
browser.elementIdText(jsonWebElementId, (jsonElement) => {
const text = jsonElement.value

@ -22,9 +22,16 @@ function openFile (browser: NightwatchBrowser, name: string, done: VoidFunction)
browser.element('css selector', '[data-id="verticalIconsKindfilePanel"] img[data-id="selected"]', (result) => {
if (result.status === 0) {
done()
} else browser.clickLaunchIcon('filePanel').perform(done)
} else browser.clickLaunchIcon('filePanel').perform(() => {
done()
})
})
} else browser.clickLaunchIcon('filePanel').perform(done)
} else {
browser.clickLaunchIcon('filePanel').perform(() => {
done()
})
}
})
})
.waitForElementVisible('li[data-id="treeViewLitreeViewItem' + name + '"', 60000)

@ -1,10 +1,10 @@
import EventEmitter from 'events'
import { NightwatchBrowser } from 'nightwatch'
class RightClick extends EventEmitter {
class RightClickCustom extends EventEmitter {
command (this: NightwatchBrowser, cssSelector: string) {
this.api.perform((done) => {
rightClick(this.api, cssSelector, () => {
rightClickCustom(this.api, cssSelector, () => {
done()
this.emit('complete')
})
@ -13,7 +13,7 @@ class RightClick extends EventEmitter {
}
}
function rightClick (browser: NightwatchBrowser, cssSelector: string, callback: VoidFunction) {
function rightClickCustom (browser: NightwatchBrowser, cssSelector: string, callback: VoidFunction) {
browser.execute(function (cssSelector: string) {
const element: any = document.querySelector(cssSelector)
const evt = element.ownerDocument.createEvent('MouseEvents')
@ -34,4 +34,4 @@ function rightClick (browser: NightwatchBrowser, cssSelector: string, callback:
})
}
module.exports = RightClick
module.exports = RightClickCustom

@ -6,7 +6,9 @@ class switchWorkspace extends EventEmitter {
this.api.waitForElementVisible('[data-id="workspacesSelect"]')
.click('[data-id="workspacesSelect"]')
.waitForElementVisible(`[data-id="dropdown-item-${workspaceName}"]`)
.pause(2000)
.click(`[data-id="dropdown-item-${workspaceName}"]`)
.pause(3000)
.perform((done) => {
done()
this.emit('complete')
@ -15,4 +17,4 @@ class switchWorkspace extends EventEmitter {
}
}
module.exports = switchWorkspace
module.exports = switchWorkspace

@ -1,4 +1,4 @@
import { NightwatchBrowser, NightwatchTestFunctionExpectedInput } from 'nightwatch'
import { ELEMENT_KEY, NightwatchBrowser, NightwatchTestFunctionExpectedInput } from 'nightwatch'
import EventEmitter from 'events'
const deepequal = require('deep-equal')
@ -22,14 +22,17 @@ class TestFunction extends EventEmitter {
})
})
.perform((done) => {
browser.waitForElementVisible(`[data-id="block_tx${txHash}"]`, 60000)
browser
.waitForElementVisible(`[data-id="block_tx${txHash}"]`, 60000)
.moveToElement(`[data-id="block_tx${txHash}"]`, 0, 0)
.pause(2000)
.click(`[data-id="block_tx${txHash}"]`)
.pause(3000)
.waitForElementVisible(`*[data-id="txLoggerTable${txHash}"]`, 60000)
// fetch and format transaction logs as key => pair object
.elements('css selector', `*[data-shared="key_${txHash}"]`, (res) => {
Array.isArray(res.value) && res.value.forEach(function (jsonWebElement) {
const jsonWebElementId: string = jsonWebElement.ELEMENT || jsonWebElement[Object.keys(jsonWebElement)[0]]
const jsonWebElementId: string = jsonWebElement[ELEMENT_KEY] || jsonWebElement[Object.keys(jsonWebElement)[0]]
browser.elementIdText(jsonWebElementId, (jsonElement) => {
const key = typeof jsonElement.value === 'string' ? jsonElement.value.trim() : null
@ -40,7 +43,7 @@ class TestFunction extends EventEmitter {
})
.elements('css selector', `*[data-shared="pair_${txHash}"]`, (res) => {
Array.isArray(res.value) && res.value.forEach(function (jsonWebElement, index) {
const jsonWebElementId = jsonWebElement.ELEMENT || jsonWebElement[Object.keys(jsonWebElement)[0]]
const jsonWebElementId = jsonWebElement[ELEMENT_KEY] || jsonWebElement[Object.keys(jsonWebElement)[0]]
browser.elementIdText(jsonWebElementId, (jsonElement) => {
let value = jsonElement.value

@ -7,7 +7,7 @@ class ValidateValueInput extends EventEmitter {
browser.perform((done) => {
browser.clearValue(selector)
.pause(2000)
.setValue(selector, valueTosSet)
.setValue(selector, valueTosSet).pause(2000)
.execute(function (selector) {
const elem = document.querySelector(selector) as HTMLInputElement
return elem.value

@ -22,7 +22,7 @@ export default function (browser: NightwatchBrowser, callback: VoidFunction, url
}, [loadPlugin])
.refresh()
.pause(6000)
.perform(done)
.perform(done())
})
.maximizeWindow()
.fullscreenWindow(() => {

@ -3,7 +3,7 @@
# Bash Menu Script Example
PS3='Select a browser: '
BROWSERS=( "chrome" "firefox" "exit" )
BROWSERS=( "chrome" "chrome headless" "firefox" "exit" )
select opt in "${BROWSERS[@]}"
do
case $opt in
@ -12,6 +12,11 @@ do
BROWSER="chromeDesktop"
break
;;
"chrome headless")
echo "Chrome headless selected"
BROWSER="chrome"
break
;;
"firefox")
echo "Firefox selected"
BROWSER="firefoxDesktop"

@ -21,7 +21,7 @@ module.exports = {
'Should compile using "compileWithParamaters" API #group1': function (browser: NightwatchBrowser) {
browser
.addFile('test_jsCompile.js', { content: jsCompile })
.executeScript('remix.exeCurrent()')
.executeScriptInTerminal('remix.exeCurrent()')
.waitForElementContainsText('*[data-id="terminalJournal"]', '"languageversion":"0.6.8+commit.0bbfe453"', 60000)
.click('*[data-id="terminalClearConsole"]')
},
@ -29,7 +29,7 @@ module.exports = {
'Should compile using "compileWithParamaters" API with optimization On #group2': function (browser: NightwatchBrowser) {
browser
.addFile('test_jsCompileWithOptimization.js', { content: jsCompileWithOptimization })
.executeScript('remix.exeCurrent()')
.executeScriptInTerminal('remix.exeCurrent()')
.waitForElementContainsText('*[data-id="terminalJournal"]', '\\"optimizer\\":{\\"enabled\\":true,\\"runs\\":300}', 60000)
.click('*[data-id="terminalClearConsole"]')
},
@ -37,7 +37,7 @@ module.exports = {
'Should compile using "compileWithParamaters" API with optimization off check default runs #group3': function (browser: NightwatchBrowser) {
browser
.addFile('test_jsCompileWithOptimizationDefault.js', { content: jsCompileWithOptimizationDefault })
.executeScript('remix.exeCurrent()')
.executeScriptInTerminal('remix.exeCurrent()')
.waitForElementContainsText('*[data-id="terminalJournal"]', '\\"optimizer\\":{\\"enabled\\":false,\\"runs\\":200}', 60000)
.click('*[data-id="terminalClearConsole"]')
},
@ -45,7 +45,7 @@ module.exports = {
'Should update the compiler configuration with "setCompilerConfig" API #group4': function (browser: NightwatchBrowser) {
browser
.addFile('test_updateConfiguration.js', { content: updateConfiguration })
.executeScript('remix.exeCurrent()')
.executeScriptInTerminal('remix.exeCurrent()')
.pause(15000)
.addFile('test_updateConfiguration.sol', { content: simpleContract })
.verifyContracts(['StorageTestUpdateConfiguration'], { wait: 5000, version: '0.6.8+commit.0bbfe453' })

@ -192,7 +192,7 @@ module.exports = {
'Should call the debugger api: getTrace #group4': function (browser: NightwatchBrowser) {
browser
.addFile('test_jsGetTrace.js', { content: jsGetTrace })
.executeScript('remix.exeCurrent()')
.executeScriptInTerminal('remix.exeCurrent()')
.pause(3000)
.waitForElementContainsText('*[data-id="terminalJournal"]', '{"gas":"0x575f","return":"0x0000000000000000000000000000000000000000000000000000000000000000","structLogs":', 60000)
},
@ -200,7 +200,7 @@ module.exports = {
'Should call the debugger api: debug #group4': function (browser: NightwatchBrowser) {
browser
.addFile('test_jsDebug.js', { content: jsDebug })
.executeScript('remix.exeCurrent()')
.executeScriptInTerminal('remix.exeCurrent()')
.pause(3000)
.clickLaunchIcon('debugger')
.waitForElementVisible('*[data-id="slider"]')

@ -42,7 +42,7 @@ module.exports = {
browser.waitForElementVisible('div[data-id="remixIdeSidePanel"]')
.assert.containsText('h6[data-id="sidePanelSwapitTitle"]', 'FILE EXPLORER')
.clickLaunchIcon('filePanel')
.assert.hidden('div[data-id="remixIdeSidePanel"]')
.assert.not.visible('div[data-id="remixIdeSidePanel"]')
.clickLaunchIcon('filePanel')
.assert.visible('div[data-id="remixIdeSidePanel"]')
.assert.containsText('h6[data-id="sidePanelSwapitTitle"]', 'FILE EXPLORER')

@ -89,7 +89,7 @@ module.exports = {
.addFile('sourcehighlight.js', sourcehighlightScript)
.addFile('removeAllSourcehighlightScript.js', removeAllSourcehighlightScript)
.openFile('sourcehighlight.js')
.executeScript('remix.exeCurrent()')
.executeScriptInTerminal('remix.exeCurrent()')
.scrollToLine(32)
.waitForElementPresent('.highlightLine33', 60000)
.checkElementStyle('.highlightLine33', 'background-color', 'rgb(52, 152, 219)')
@ -105,7 +105,7 @@ module.exports = {
browser.waitForElementVisible('li[data-id="treeViewLitreeViewItemremoveSourcehighlightScript.js"]')
.click('li[data-id="treeViewLitreeViewItemremoveSourcehighlightScript.js"]')
.pause(2000)
.executeScript('remix.exeCurrent()')
.executeScriptInTerminal('remix.exeCurrent()')
.waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts"]')
.click('li[data-id="treeViewLitreeViewItemcontracts"]')
.waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/3_Ballot.sol"]')
@ -119,7 +119,7 @@ module.exports = {
browser.waitForElementVisible('li[data-id="treeViewLitreeViewItemremoveAllSourcehighlightScript.js"]')
.click('li[data-id="treeViewLitreeViewItemremoveAllSourcehighlightScript.js"]')
.pause(2000)
.executeScript('remix.exeCurrent()')
.executeScriptInTerminal('remix.exeCurrent()')
.waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/3_Ballot.sol"]')
.click('li[data-id="treeViewLitreeViewItemcontracts/3_Ballot.sol"]')
.pause(2000)

@ -10,12 +10,12 @@ const testData = {
}
module.exports = {
'@disabled': true,
before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done)
},
'Should create a new file `5_New_contract.sol` in file explorer': function (browser: NightwatchBrowser) {
'Should create a new file `5_New_contract.sol` in file explorer #group1': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('div[data-id="remixIdeSidePanel"]')
.clickLaunchIcon('filePanel')
.assert.containsText('h6[data-id="sidePanelSwapitTitle"]', 'FILE EXPLORER')
@ -28,7 +28,7 @@ module.exports = {
.waitForElementVisible('*[data-id="treeViewLitreeViewItem5_New_contract.sol"]', 7000)
},
'Should rename `5_New_contract.sol` to 5_Renamed_Contract.sol': function (browser: NightwatchBrowser) {
'Should rename `5_New_contract.sol` to 5_Renamed_Contract.sol #group1': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('*[data-id="treeViewLitreeViewItem5_New_contract.sol"]')
.click('*[data-id="treeViewLitreeViewItem5_New_contract.sol"]')
@ -36,14 +36,14 @@ module.exports = {
.waitForElementVisible('*[data-id="treeViewLitreeViewItem5_Renamed_Contract.sol"]')
},
'Should delete file `5_Renamed_Contract.sol` from file explorer': function (browser: NightwatchBrowser) {
'Should delete file `5_Renamed_Contract.sol` from file explorer #group1': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('*[data-id="treeViewLitreeViewItem5_Renamed_Contract.sol"]')
.removeFile('5_Renamed_Contract.sol', 'default_workspace')
.waitForElementNotPresent('*[data-id="treeViewLitreeViewItem5_Renamed_Contract.sol"')
},
'Should create a new folder': function (browser: NightwatchBrowser) {
'Should create a new folder #group1': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('*[data-id="treeViewLitreeViewItemREADME.txt"]')
.click('li[data-id="treeViewLitreeViewItemREADME.txt"]') // focus on root directory
@ -55,7 +55,7 @@ module.exports = {
.waitForElementVisible('*[data-id="treeViewLitreeViewItemBrowser_Tests"]')
},
'Should rename Browser_Tests folder to Browser_E2E_Tests': function (browser: NightwatchBrowser) {
'Should rename Browser_Tests folder to Browser_E2E_Tests #group1': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('*[data-id="treeViewLitreeViewItemBrowser_Tests"]')
.click('*[data-id="treeViewLitreeViewItemBrowser_Tests"]')
@ -63,10 +63,10 @@ module.exports = {
.waitForElementVisible('*[data-id="treeViewLitreeViewItemBrowser_E2E_Tests"]')
},
'Should delete Browser_E2E_Tests folder': function (browser: NightwatchBrowser) {
'Should delete Browser_E2E_Tests folder #group1': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('*[data-id="treeViewLitreeViewItemBrowser_E2E_Tests"]')
.rightClick('[data-path="Browser_E2E_Tests"]')
.rightClickCustom('[data-path="Browser_E2E_Tests"]')
.click('*[id="menuitemdelete"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok', 60000)
.pause(2000)
@ -99,12 +99,16 @@ module.exports = {
})
},
'Should open local filesystem explorer': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('*[data-id="filePanelFileExplorerTree"]')
'Should open local filesystem explorer #group2': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('div[data-id="remixIdeSidePanel"]')
.clickLaunchIcon('filePanel')
.waitForElementVisible('*[data-id="filePanelFileExplorerTree"]')
.click('[data-id="remixUIWorkspaceExplorer"]')
.setValue('*[data-id="fileExplorerFileUpload"]', testData.testFile1)
.setValue('*[data-id="fileExplorerFileUpload"]', testData.testFile2)
.setValue('*[data-id="fileExplorerFileUpload"]', testData.testFile3)
.waitForElementPresent('*[data-id="fileExplorerFileUpload"]')
.uploadFile('*[data-id="fileExplorerFileUpload"]', testData.testFile1)
.uploadFile('*[data-id="fileExplorerFileUpload"]', testData.testFile2)
.uploadFile('*[data-id="fileExplorerFileUpload"]', testData.testFile3)
.waitForElementVisible('[data-id="treeViewLitreeViewItemeditor.test.js"]')
.waitForElementVisible('[data-id="treeViewLitreeViewItemfileExplorer.test.js"]')
.waitForElementVisible('[data-id="treeViewLitreeViewItemgeneralSettings.test.js"]')

@ -11,7 +11,7 @@ module.exports = {
'Should execute `file` api from file manager external api #group1': function (browser: NightwatchBrowser) {
browser
.addFile('file.js', { content: executeFile })
.executeScript('remix.exeCurrent()')
.executeScriptInTerminal('remix.exeCurrent()')
.pause(1000)
.waitForElementContainsText('*[data-id="terminalJournal"]', 'file.js', 60000)
},
@ -19,7 +19,7 @@ module.exports = {
'Should execute `exists` api from file manager external api #group1': function (browser: NightwatchBrowser) {
browser
.addFile('exists.js', { content: executeExists })
.executeScript('remix.exeCurrent()')
.executeScriptInTerminal('remix.exeCurrent()')
.waitForElementContainsText('*[data-id="terminalJournal"]', 'exists.js true', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', 'non-exists.js false', 60000)
},
@ -27,14 +27,14 @@ module.exports = {
'Should execute `open` api from file manager external api #group1': function (browser: NightwatchBrowser) {
browser
.addFile('open.js', { content: executeOpen })
.executeScript('remix.exeCurrent()')
.executeScriptInTerminal('remix.exeCurrent()')
.waitForElementContainsText('*[data-id="terminalJournal"]', 'contracts/3_Ballot.sol', 60000)
},
'Should execute `writeFile` api from file manager external api #group1': function (browser: NightwatchBrowser) {
browser
.addFile('writeFile.js', { content: executeWriteFile })
.executeScript('remix.exeCurrent()')
.executeScriptInTerminal('remix.exeCurrent()')
.pause(2000)
.openFile('new_contract.sol')
.getEditorValue((content) => {
@ -45,23 +45,23 @@ module.exports = {
'Should execute `readFile` api from file manager external api #group2': function (browser: NightwatchBrowser) {
browser
.addFile('writeFile.js', { content: executeWriteFile })
.executeScript('remix.exeCurrent()')
.executeScriptInTerminal('remix.exeCurrent()')
.addFile('readFile.js', { content: executeReadFile })
.executeScript('remix.exeCurrent()')
.executeScriptInTerminal('remix.exeCurrent()')
.waitForElementContainsText('*[data-id="terminalJournal"]', 'pragma solidity ^0.6.0', 60000)
},
'Should execute `copyFile` api from file manager external api #group2': function (browser: NightwatchBrowser) {
browser
.addFile('copyFile.js', { content: executeCopyFile })
.executeScript('remix.exeCurrent()')
.executeScriptInTerminal('remix.exeCurrent()')
.waitForElementContainsText('*[data-id="terminalJournal"]', 'pragma solidity >=0.7.0 <0.9.0;', 60000)
},
'Should execute `rename` api from file manager external api #group2': function (browser: NightwatchBrowser) {
browser
.addFile('renameFile.js', { content: executeRename })
.executeScript('remix.exeCurrent()')
.executeScriptInTerminal('remix.exeCurrent()')
.pause(2000)
.waitForElementPresent('[data-id="treeViewLitreeViewItemold_contract.sol"]', 60000)
},
@ -69,7 +69,7 @@ module.exports = {
'Should execute `mkdir` api from file manager external api #group3': function (browser: NightwatchBrowser) {
browser
.addFile('mkdirFile.js', { content: executeMkdir })
.executeScript('remix.exeCurrent()')
.executeScriptInTerminal('remix.exeCurrent()')
.pause(2000)
.waitForElementPresent('[data-id="treeViewLitreeViewItemTest_Folder"]', 80000)
},
@ -77,7 +77,7 @@ module.exports = {
'Should execute `readdir` api from file manager external api #group3': function (browser: NightwatchBrowser) {
browser
.addFile('readdirFile.js', { content: executeReaddir })
.executeScript('remix.exeCurrent()')
.executeScriptInTerminal('remix.exeCurrent()')
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Test_Folder isDirectory', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', 'true', 5000)
},
@ -86,7 +86,7 @@ module.exports = {
browser
.addFile('old_contract.sol', { content: 'test' })
.addFile('removeFile.js', { content: executeRemove })
.executeScript('remix.exeCurrent()')
.executeScriptInTerminal('remix.exeCurrent()')
.pause(2000)
.waitForElementNotPresent('[data-id="treeViewLitreeViewItemold_contract.sol"]', 60000)
},
@ -95,7 +95,7 @@ module.exports = {
'Should execute `remove` api from file manager external api on a folder #group4': function (browser: NightwatchBrowser) {
browser
.addFile('test_jsRemoveFolder.js', { content: executeRemoveOnFolder })
.executeScript('remix.exeCurrent()')
.executeScriptInTerminal('remix.exeCurrent()')
.pause(2000)
.waitForElementNotPresent('[data-id="treeViewLitreeViewItemcontracts"]', 60000)
.end()

@ -34,7 +34,7 @@ module.exports = {
.sendKeys('*[data-id$="/blank"] .remixui_items', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemBrowser_Tests"]')
.addFile('File.sol', { content: '' })
.executeScript(`remix.loadgist('${gistid}')`)
.executeScriptInTerminal(`remix.loadgist('${gistid}')`)
// .perform((done) => { if (runtimeBrowser === 'chrome') { browser.openFile('gists') } done() })
.waitForElementVisible(`[data-id="treeViewLitreeViewItemgist-${gistid}"]`)
.click(`[data-id="treeViewLitreeViewItemgist-${gistid}"]`)
@ -58,7 +58,7 @@ module.exports = {
const gistid = id[1]
browser
.click('[data-id="default_workspace-modal-footer-cancel-react"]')
.executeScript(`remix.loadgist('${gistid}')`)
.executeScriptInTerminal(`remix.loadgist('${gistid}')`)
// .perform((done) => { if (runtimeBrowser === 'chrome') { browser.openFile('gists') } done() })
.waitForElementVisible(`[data-id="treeViewLitreeViewItemgist-${gistid}"]`)
.click(`[data-id="treeViewLitreeViewItemgist-${gistid}"]`)

@ -37,8 +37,8 @@ module.exports = {
.setValue('input[data-id="homeTabModalDialogCustomPromptText"]', testData.invalidURL)
.waitForElementVisible('*[data-id="homeTab-modal-footer-ok-react"]')
.click('[data-id="homeTab-modal-footer-ok-react"]') // submitted
.waitForElementVisible('*[data-shared="tooltipPopup"]')
.assert.containsText('*[data-shared="tooltipPopup"] span', 'not found ' + testData.invalidURL)
//.waitForElementVisible('*[data-shared="tooltipPopup"]')
//.waitForElementContainsText('*[data-shared="tooltipPopup"] span', 'not found ' + testData.invalidURL)
},
'Import From GitHub For Valid URL #group2': function (browser: NightwatchBrowser) {

@ -109,7 +109,7 @@ module.exports = {
'Should load back installed plugins after reload': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('*[data-id="remixIdeSidePanel"]')
.waitForElementVisible('*[data-id="remixIdeSidePanel"]',3000)
.waitForElementVisible('*[data-id="pluginManagerComponentPluginManager"]')
.getInstalledPlugins((plugins) => {
browser.refresh()

@ -214,7 +214,7 @@ module.exports = {
}
})
.waitForElementVisible('[data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]')
.rightClick('[data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]').useXpath().waitForElementVisible('//*[@id="menuitemtestcommand"]').click('//*[@id="menuitemtestcommand"]', async () => {
.rightClickCustom('[data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]').useXpath().waitForElementVisible('//*[@id="menuitemtestcommand"]').click('//*[@id="menuitemtestcommand"]', async () => {
// @ts-ignore
browser.click('//*[@data-id="verticalIconsKindlocalPlugin"]').frame(0, async () => {
await clickAndCheckLog(browser, null, { id: 'localPlugin', name: 'testCommand', label: 'testCommand', type: [], extension: ['.sol'], path: ['contracts/1_Storage.sol'], pattern: [] }, null, null)
@ -321,14 +321,14 @@ module.exports = {
// DGIT
'Should have changes on new workspace #group3': async function (browser: NightwatchBrowser) {
await clickAndCheckLog(browser, 'filePanel:createWorkspace', null, null, 'dgit')
await clickAndCheckLog(browser, 'dGitProvider:status', [['README.txt', 0, 2, 0], ['contracts/1_Storage.sol', 0, 2, 0], ['contracts/2_Owner.sol', 0, 2, 0], ['contracts/3_Ballot.sol', 0, 2, 0], ['scripts/deploy_with_ethers.ts', 0, 2, 0], ['scripts/deploy_with_web3.ts', 0, 2, 0], ['tests/Ballot_test.sol', 0, 2, 0]], ['tests/storage.test.js', 0, 2, 0], null, null)
await clickAndCheckLog(browser, 'dGitProvider:status', [["README.txt",0,2,0],["contracts/1_Storage.sol",0,2,0],["contracts/2_Owner.sol",0,2,0],["contracts/3_Ballot.sol",0,2,0],["scripts/deploy_with_ethers.ts",0,2,0],["scripts/deploy_with_web3.ts",0,2,0],["scripts/ethers-lib.ts",0,2,0],["scripts/web3-lib.ts",0,2,0],["tests/Ballot_test.sol",0,2,0],["tests/storage.test.js",0,2,0]], null, null)
},
'Should stage contract #group3': async function (browser: NightwatchBrowser) {
await clickAndCheckLog(browser, 'dGitProvider:add', null, null, {
filepath: 'contracts/1_Storage.sol'
})
await clickAndCheckLog(browser, 'dGitProvider:status', [['README.txt', 0, 2, 0], ['contracts/1_Storage.sol', 0, 2, 2], ['contracts/2_Owner.sol', 0, 2, 0], ['contracts/3_Ballot.sol', 0, 2, 0], ['scripts/deploy_with_ethers.ts', 0, 2, 0], ['scripts/deploy_with_web3.ts', 0, 2, 0], ['tests/Ballot_test.sol', 0, 2, 0]], ['tests/storage.test.js', 0, 2, 0], null, null)
await clickAndCheckLog(browser, 'dGitProvider:status', [["README.txt",0,2,0],["contracts/1_Storage.sol",0,2,2],["contracts/2_Owner.sol",0,2,0],["contracts/3_Ballot.sol",0,2,0],["scripts/deploy_with_ethers.ts",0,2,0],["scripts/deploy_with_web3.ts",0,2,0],["scripts/ethers-lib.ts",0,2,0],["scripts/web3-lib.ts",0,2,0],["tests/Ballot_test.sol",0,2,0],["tests/storage.test.js",0,2,0]], null, null)
},
'Should commit changes #group3': async function (browser: NightwatchBrowser) {
await clickAndCheckLog(browser, 'dGitProvider:commit', null, null, { author: { name: 'Remix', email: 'Remix' }, message: 'commit-message' })
@ -417,7 +417,7 @@ module.exports = {
.frameParent()
.useCss()
.addFile('test_modal.js', { content: testModalToasterApi })
.executeScript('remix.execute(\'test_modal.js\')')
.executeScriptInTerminal('remix.execute(\'test_modal.js\')')
.useCss()
.waitForElementVisible('*[data-id="test_id_1_ModalDialogModalBody-react"]', 60000)
.assert.containsText('*[data-id="test_id_1_ModalDialogModalBody-react"]', 'message 1')

@ -55,6 +55,7 @@ module.exports = {
},
'start Remixd': function (browser) {
startRemixd(browser)
},
'run Remixd tests #group4': function (browser) {
runTests(browser)
@ -102,7 +103,7 @@ module.exports = {
'Run git status': '' + function (browser) {
browser
.executeScript('git status')
.executeScriptInTerminal('git status')
.pause(3000)
.journalLastChildIncludes('On branch ')
},
@ -131,6 +132,7 @@ function startRemixd (browser: NightwatchBrowser) {
.waitForElementVisible('*[data-id="remixdConnect-modal-footer-ok-react"]', 2000)
.pause(2000)
.click('*[data-id="remixdConnect-modal-footer-ok-react"]')
.pause(10000)
// .click('*[data-id="workspacesModalDialog-modal-footer-ok-react"]')
}

@ -39,8 +39,8 @@ module.exports = {
.waitForElementVisible('*[data-id="signMessageTextarea"]', 120000)
.click('*[data-id="signMessageTextarea"]')
.setValue('*[data-id="signMessageTextarea"]', 'Remix is cool!')
.assert.elementNotPresent('*[data-id="settingsRemixRunSignMsgHash"]')
.assert.elementNotPresent('*[data-id="settingsRemixRunSignMsgSignature"]')
.assert.not.elementPresent('*[data-id="settingsRemixRunSignMsgHash"]')
.assert.not.elementPresent('*[data-id="settingsRemixRunSignMsgSignature"]')
.pause(2000)
.waitForElementPresent('[data-id="udappNotify-modal-footer-ok-react"]')
.click('[data-id="udappNotify-modal-footer-ok-react"]')
@ -80,7 +80,7 @@ module.exports = {
.end()
},
'Should connect to Goerli Test Network using MetaMask': '' + function (browser: NightwatchBrowser) {
'Should connect to Goerli Test Network using MetaMask': !function (browser: NightwatchBrowser) {
browser.waitForElementPresent('*[data-id="remixIdeSidePanel"]')
.setupMetamask(passphrase, password)
.click('.network-indicator__down-arrow')
@ -101,7 +101,7 @@ module.exports = {
.switchBrowserTab(0)
},
'Should deploy contract on Goerli Test Network using MetaMask': '' + function (browser: NightwatchBrowser) {
'Should deploy contract on Goerli Test Network using MetaMask': !function (browser: NightwatchBrowser) {
browser.waitForElementPresent('*[data-id="runTabSelectAccount"] option')
.clickLaunchIcon('filePanel')
.openFile('Greet.sol')
@ -118,7 +118,7 @@ module.exports = {
.switchBrowserTab(0)
},
'Should run low level interaction (fallback function) on Goerli Test Network using MetaMask': '' + function (browser: NightwatchBrowser) {
'Should run low level interaction (fallback function) on Goerli Test Network using MetaMask': !function (browser: NightwatchBrowser) {
browser.waitForElementPresent('*[data-id="remixIdeSidePanel"]')
.waitForElementPresent('*[data-id="universalDappUiTitleExpander"]')
.click('*[data-id="universalDappUiTitleExpander"]')
@ -135,7 +135,7 @@ module.exports = {
.end()
},
'Should connect to Ethereum Main Network using MetaMask': '' + function (browser: NightwatchBrowser) {
'Should connect to Ethereum Main Network using MetaMask': !function (browser: NightwatchBrowser) {
browser.waitForElementPresent('*[data-id="remixIdeSidePanel"]')
.switchBrowserTab(2)
.waitForElementPresent('.network-indicator__down-arrow')
@ -153,7 +153,7 @@ module.exports = {
.assert.containsText('*[data-id="settingsNetworkEnv"]', 'Main (1) network')
},
'Should deploy contract on Ethereum Main Network using MetaMask': '' + function (browser: NightwatchBrowser) {
'Should deploy contract on Ethereum Main Network using MetaMask': !function (browser: NightwatchBrowser) {
browser.waitForElementPresent('*[data-id="runTabSelectAccount"] option')
.clickLaunchIcon('filePanel')
.openFile('Greet.sol')
@ -173,7 +173,7 @@ module.exports = {
* - Ropsten node for retrieving the trace and storage
*
*/
'Should debug Ropsten transaction with source highlighting using the source verifier service and MetaMask': '' + function (browser: NightwatchBrowser) {
'Should debug Ropsten transaction with source highlighting using the source verifier service and MetaMask': !function (browser: NightwatchBrowser) {
browser.waitForElementPresent('*[data-id="remixIdeSidePanel"]')
.waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000)
.switchBrowserTab(2)
@ -198,9 +198,9 @@ module.exports = {
.assert.containsText('*[data-id="solidityLocals"]', 'to: 0x6C3CCC7FBA111707D5A1AAF2758E9D4F4AC5E7B1')
},
'Call web3.eth.getAccounts() using Injected Provider (Metamask)': '' + function (browser: NightwatchBrowser) {
'Call web3.eth.getAccounts() using Injected Provider (Metamask)': !function (browser: NightwatchBrowser) {
browser
.executeScript('web3.eth.getAccounts()')
.executeScriptInTerminal('web3.eth.getAccounts()')
.pause(2000)
.journalLastChildIncludes('[ "0x76a3ABb5a12dcd603B52Ed22195dED17ee82708f" ]')
.end()

@ -12,7 +12,7 @@ module.exports = {
browser.waitForElementVisible('*[data-id="remixIdeSidePanel"]')
.click('*[plugin="search"]').waitForElementVisible('*[id="search_input"]')
.waitForElementVisible('*[id="search_include"]')
.setValue('*[id="search_include"]', ', *.txt').pause(2000)
.setValue('*[id="search_include"]', ', *.*').pause(2000)
.setValue('*[id="search_input"]', 'read').sendKeys('*[id="search_input"]', browser.Keys.ENTER)
.pause(1000)
.waitForElementContainsText('*[data-id="search_results"]', '3_BALLOT.SOL', 60000)
@ -100,7 +100,7 @@ module.exports = {
browser.click('*[data-id="confirm_replace_label"]').pause(500)
.clearValue('*[id="search_input"]')
.setValue('*[id="search_input"]', 'replacing').sendKeys('*[id="search_input"]', browser.Keys.ENTER).pause(1000)
.setValue('*[id="search_replace"]', '2').pause(1000)
.setValue('*[id="search_replace"]', 'replacing2').pause(1000)
.waitForElementVisible('*[data-id="contracts/2_Owner.sol-33-71"]')
.moveToElement('*[data-id="contracts/2_Owner.sol-33-71"]', 10, 10)
.waitForElementVisible('*[data-id="replace-contracts/2_Owner.sol-33-71"]')

@ -177,10 +177,16 @@ module.exports = {
// creating a new workspace
.click('*[data-id="workspaceCreate"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
// eslint-disable-next-line dot-notation
.execute(function () { document.querySelector('*[data-id="modalDialogCustomPromptTextCreate"]')['value'] = 'workspace_new' })
.click('*[data-id="fileSystemModalDialogContainer-react"] input[data-id="modalDialogCustomPromptTextCreate"]')
.setValue('*[data-id="fileSystemModalDialogContainer-react"] input[data-id="modalDialogCustomPromptTextCreate"]', 'workspace_new')
.pause(2000)
.getValue('*[data-id="fileSystemModalDialogContainer-react"] input[data-id="modalDialogCustomPromptTextCreate"]', (result) => {
console.log(result)
browser.assert.equal(result.value, 'workspace_new')
})
.waitForElementVisible('*[data-id="fileSystem-modal-footer-ok-react"]')
.execute(function () { (document.querySelector('[data-id="fileSystem-modal-footer-ok-react"]') as HTMLElement).click() })
.click('*[data-id="fileSystem-modal-footer-ok-react"]')
.pause(3000)
.currentWorkspaceIs('workspace_new')
.waitForElementVisible('li[data-id="treeViewLitreeViewItem.deps/remix-tests/remix_tests.sol"]')
.waitForElementVisible('li[data-id="treeViewLitreeViewItem.deps/remix-tests/remix_accounts.sol"]')

@ -33,7 +33,7 @@ module.exports = {
.journalLastChildIncludes('to: CheckSpecials.(fallback)')
.journalLastChildIncludes('value: 0 wei')
.journalLastChildIncludes('data: 0xaa')
.perform(done)
.perform(done())
})
})
},
@ -46,7 +46,7 @@ module.exports = {
.pause(1000)
.waitForElementVisible(`#instance${address} label[id="deployAndRunLLTxError"]`)
.assert.containsText(`#instance${address} label[id="deployAndRunLLTxError"]`, 'The calldata should be a valid hexadecimal value with size of at least one byte.')
.perform(done)
.perform(done())
})
})
},
@ -58,7 +58,7 @@ module.exports = {
.pause(1000)
.waitForElementVisible(`#instance${address} label[id="deployAndRunLLTxError"]`)
.assert.containsText(`#instance${address} label[id="deployAndRunLLTxError"]`, 'The calldata should be a valid hexadecimal value.')
.perform(done)
.perform(done())
})
})
},
@ -71,7 +71,7 @@ module.exports = {
.journalLastChildIncludes('to: CheckSpecials.(receive)')
.journalLastChildIncludes('value: 1 wei')
.journalLastChildIncludes('data: 0x')
.perform(done)
.perform(done())
})
})
},
@ -83,7 +83,7 @@ module.exports = {
.pause(1000)
.journalLastChildIncludes('to CheckSpecials.(fallback) errored:')
.journalLastChildIncludes('The called function should be payable if you send value')
.perform(done)
.perform(done())
})
})
},
@ -101,7 +101,7 @@ module.exports = {
.journalLastChildIncludes('to: CheckSpecials.(receive)')
.journalLastChildIncludes('value: 1 wei')
.journalLastChildIncludes('data: 0x')
.perform(done)
.perform(done())
})
})
},
@ -113,7 +113,7 @@ module.exports = {
.pause(1000)
.waitForElementVisible(`#instance${address} label[id="deployAndRunLLTxError"]`)
.assert.containsText(`#instance${address} label[id="deployAndRunLLTxError"]`, '\'Fallback\' function is not defined')
.perform(done)
.perform(done())
})
})
},
@ -131,7 +131,7 @@ module.exports = {
.journalLastChildIncludes('to: CheckSpecials.(fallback)')
.journalLastChildIncludes('value: 1 wei')
.journalLastChildIncludes('data: 0x')
.perform(done)
.perform(done())
})
})
},
@ -144,7 +144,7 @@ module.exports = {
.journalLastChildIncludes('to: CheckSpecials.(fallback)')
.journalLastChildIncludes('value: 1 wei')
.journalLastChildIncludes('data: 0xaa')
.perform(done)
.perform(done())
})
})
},
@ -161,7 +161,7 @@ module.exports = {
.pause(1000)
.waitForElementVisible(`#instance${address} label[id="deployAndRunLLTxError"]`)
.assert.containsText(`#instance${address} label[id="deployAndRunLLTxError"]`, 'should have either \'receive\' or payable \'fallback\'')
.perform(done)
.perform(done())
})
})
},
@ -184,7 +184,7 @@ module.exports = {
.journalLastChildIncludes('to: CheckSpecials.(fallback)')
.journalLastChildIncludes('value: 999999998765257135 wei')
.journalLastChildIncludes('data: 0xaa')
.perform(done)
.perform(done())
})
})
},
@ -196,7 +196,7 @@ module.exports = {
.journalLastChildIncludes('to: CheckSpecials.(receive)')
.journalLastChildIncludes('value: 1 wei')
.journalLastChildIncludes('data: 0x')
.perform(done)
.perform(done())
})
})
},
@ -217,7 +217,7 @@ module.exports = {
.pause(1000)
.waitForElementVisible(`#instance${address} label[id="deployAndRunLLTxError"]`)
.assert.containsText(`#instance${address} label[id="deployAndRunLLTxError"]`, 'Both \'receive\' and \'fallback\' functions are not defined')
.perform(done)
.perform(done())
})
})
.end()

@ -42,7 +42,7 @@ module.exports = {
.waitForElementPresent('#staticanalysisresult .warning', 5000)
.assert.containsText('#verticalIconsKindsolidityStaticAnalysis .remixui_status', '1') // Check warning count
.verify.elementPresent('input[name="showLibWarnings"]')
.verify.elementNotPresent('input[name="showLibWarnings"]:checked')
.verify.not.elementPresent('input[name="showLibWarnings"]:checked')
.verify.elementPresent('label[id="headingshowLibWarnings"]')
.click('label[id="headingshowLibWarnings"]')
.pause(1000)
@ -62,7 +62,7 @@ function runTests (browser: NightwatchBrowser) {
.testContracts('Untitled.sol', sources[0]['Untitled.sol'], ['TooMuchGas', 'test1', 'test2'])
.clickLaunchIcon('solidityStaticAnalysis')
.click('#staticanalysisButton button')
.waitForElementPresent('#staticanalysisresult .warning', 2000, true, function () {
.waitForElementPresent('#staticanalysisresult .warning', 2000, 500, true, function () {
listSelectorContains(['Use of tx.origin',
'Fallback function of contract TooMuchGas requires too much gas',
'TooMuchGas.() : Variables have very similar names "test" and "test1".',

@ -10,7 +10,7 @@ module.exports = {
'Should execution a simple console command #group1 #group999': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('*[data-id="terminalCli"]', 10000)
.executeScript('console.log(1 + 1)')
.executeScriptInTerminal('console.log(1 + 1)')
.pause(2000)
.waitForElementContainsText('*[data-id="terminalJournal"]', '2', 60000)
},
@ -26,7 +26,7 @@ module.exports = {
'Async/Await Script #group1': function (browser: NightwatchBrowser) {
browser
.addFile('asyncAwait.js', { content: asyncAwait })
.executeScript('remix.execute("asyncAwait.js")')
.executeScriptInTerminal('remix.execute("asyncAwait.js")')
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Waiting Promise', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', 'result - ', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Promise Resolved', 60000)
@ -35,13 +35,13 @@ module.exports = {
'Call Remix File Manager from a script #group2': function (browser: NightwatchBrowser) {
browser
.addFile('asyncAwaitWithFileManagerAccess.js', { content: asyncAwaitWithFileManagerAccess })
.executeScript('remix.execute(\'asyncAwaitWithFileManagerAccess.js\')')
.executeScriptInTerminal('remix.execute(\'asyncAwaitWithFileManagerAccess.js\')')
.waitForElementContainsText('*[data-id="terminalJournal"]', 'contract Ballot {', 60000)
},
'Call web3.eth.getAccounts() using Remix VM #group2': function (browser: NightwatchBrowser) {
browser
.executeScript('web3.eth.getAccounts()')
.executeScriptInTerminal('web3.eth.getAccounts()')
.waitForElementContainsText('*[data-id="terminalJournal"]', '["0x5B38Da6a701c568545dCfcB03FcB875f56beddC4","0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2","0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db","0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB","0x617F2E2fD72FD9D5503197092aC168c91465E7f2","0x17F6AD8Ef982297579C203069C1DbfFE4348c372","0x5c6B0f7Bf3E7ce046039Bd8FABdfD3f9F5021678","0x03C6FcED478cBbC9a4FAB34eF9f40767739D1Ff7","0x1aE0EA34a72D944a8C7603FfB3eC30a6669E454C","0x0A098Eda01Ce92ff4A4CCb7A4fFFb5A43EBC70DC","0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c","0x14723A09ACff6D2A60DcdF7aA4AFf308FDDC160C","0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB","0x583031D1113aD414F02576BD6afaBfb302140225","0xdD870fA1b7C4700F2BD7f44238821C26f7392148"]')
},
@ -51,7 +51,7 @@ module.exports = {
.clickLaunchIcon('udapp')
.switchEnvironment('External Http Provider')
.modalFooterOKClick('basic-http-provider')
.executeScript('web3.eth.getAccounts()')
.executeScriptInTerminal('web3.eth.getAccounts()')
.waitForElementContainsText('*[data-id="terminalJournal"]', '["', 60000) // we check if an array is present, don't need to check for the content
.waitForElementContainsText('*[data-id="terminalJournal"]', '"]', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', '","', 60000)
@ -63,7 +63,7 @@ module.exports = {
.addFile('resolveExternalUrlAndSave.js', { content: resolveExternalUrlAndSave })
.openFile('resolveExternalUrlAndSave.js')
.pause(1000)
.executeScript('remix.execute(\'resolveExternalUrlAndSave.js\')')
.executeScriptInTerminal('remix.execute(\'resolveExternalUrlAndSave.js\')')
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Implementation of the {IERC20} interface.', 60000)
.openFile('.deps/github/OpenZeppelin/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol')
},
@ -74,7 +74,7 @@ module.exports = {
.addFile('resolveUrl.js', { content: resolveUrl })
.openFile('resolveUrl.js')
.pause(1000)
.executeScript('remix.execute(\'resolveUrl.js\')')
.executeScriptInTerminal('remix.execute(\'resolveUrl.js\')')
.waitForElementContainsText('*[data-id="terminalJournal"]', 'contract Ballot {', 60000)
},
@ -84,7 +84,7 @@ module.exports = {
.addFile('resolveExternalUrlAndSaveToaPath.js', { content: resolveExternalUrlAndSaveToaPath })
.openFile('resolveExternalUrlAndSaveToaPath.js')
.pause(1000)
.executeScript('remix.execute(\'resolveExternalUrlAndSaveToaPath.js\')')
.executeScriptInTerminal('remix.execute(\'resolveExternalUrlAndSaveToaPath.js\')')
.waitForElementContainsText('*[data-id="terminalJournal"]', 'abstract contract ERC20Burnable', 60000)
.openFile('.deps/github/newFile.sol')
@ -105,7 +105,7 @@ module.exports = {
.openFile('contracts/2_Owner.sol')
.clickLaunchIcon('solidity')
.click('*[data-id="compilerContainerCompileBtn"]').pause(5000) // compile Owner
.executeScript('remix.execute(\'deployWithEthersJs.js\')')
.executeScriptInTerminal('remix.execute(\'deployWithEthersJs.js\')')
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Contract Address:', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', '0xd9145CCE52D386f254917e481eB44e9943F39138', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Deployment successful.', 60000)
@ -127,7 +127,7 @@ module.exports = {
.clickLaunchIcon('solidity')
.click('*[data-id="compilerContainerCompileBtn"]')
.pause(1000) // compile Storage
.executeScript('remix.execute(\'scripts/storage.test.js\')')
.executeScriptInTerminal('remix.execute(\'scripts/storage.test.js\')')
.pause(1000)
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Running tests....')
.waitForElementContainsText('*[data-id="terminalJournal"]', 'storage contract Address:')
@ -149,7 +149,7 @@ module.exports = {
.clickLaunchIcon('solidity')
.click('*[data-id="compilerContainerCompileBtn"]')
.pause(1000) // compile StorageWithLib
.executeScript('remix.execute(\'scripts/storageWithLib.test.js\')')
.executeScriptInTerminal('remix.execute(\'scripts/storageWithLib.test.js\')')
.pause(1000)
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Running tests....')
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Storage with lib')
@ -200,7 +200,31 @@ module.exports = {
.sendKeys('body', [browser.Keys.CONTROL, browser.Keys.SHIFT, 's'])
.pause(15000)
.journalLastChildIncludes('147')
}
},
'Should run a script which log transaction and block using web3.js and ethers #group7': function (browser: NightwatchBrowser) {
browser
.clickLaunchIcon('udapp')
.switchEnvironment('External Http Provider')
.waitForElementPresent('[data-id="basic-http-provider-modal-footer-ok-react"]')
.execute(() => {
(document.querySelector('*[data-id="basic-http-providerModalDialogContainer-react"] input[data-id="modalDialogCustomPromp"]') as any).focus()
}, [], () => {})
.setValue('[data-id="modalDialogCustomPromp"]', 'https://remix-goerli.ethdevops.io')
.modalFooterOKClick('basic-http-provider')
.clickLaunchIcon('filePanel')
.openFile('README.txt')
.addFile('scripts/log_tx_block.js', { content: scriptBlockAndTransaction } )
.pause(1000)
.executeScriptInTerminal('remix.execute(\'scripts/log_tx_block.js\')')
.pause(10000)
// check if the input of the transaction is being logged (web3 call)
.journalChildIncludes('0x775526410000000000000000000000000000000000000000000000000000000000000060464c0335b2f1609abd9de25141c0a3b49db516fc7375970dc737c32b986e88e3000000000000000000000000000000000000000000000000000000000000039e000000000000000000000000000000000000000000000000000000000000000602926b30b10e7a514d92bc71e085f5bff2687fac2856ae43ef7621bf1756fa370516d310bec5727543089be9a4d5f68471174ee528e95a2520b0ca36c2b6c6eb0000000000000000000000000000000000000000000000000000000000046f49036f5e4ea4dd042801c8841e3db8e654124305da0f11824fc1db60c405dbb39f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000')
// check if the logsBloom is being logged (web3 call)
.journalChildIncludes('0x00000000000000000000000000100000000000000000020000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000040000000060000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000100000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000001')
// check if the logsBloom is being logged (ethers.js call)
.journalChildIncludes('"hex":"0x025cd8"')
}
}
const asyncAwait = `
@ -605,3 +629,17 @@ const scriptAutoExec = {
})()
`
}
const scriptBlockAndTransaction = `
// Right click on the script name and hit "Run" to execute
(async () => {
try {
web3.eth.getTransaction('0x022ccd55747677ac50f8d9dfd1bf5b843fa2f36438a28c1d0a0958e057bb3e2a').then(console.log)
web3.eth.getBlock('7367447').then(console.log);
let ethersProvider = new ethers.providers.Web3Provider(web3Provider)
ethersProvider.getBlock(7367447).then(console.log)
} catch (e) {
console.log(e.message)
}
})()
`

@ -23,8 +23,8 @@ module.exports = {
status: 'true Transaction mined and execution succeed',
'decoded output': { 0: 'uint256: 8' }
})
.pause(500)
.checkTerminalFilter('0x12332162e2e31397dc1e07ed0a1cf08f728e9b4487c6f9ed79d2f39410c92782', '')
.pause(120000)
//.checkTerminalFilter('0x12332162e2e31397dc1e07ed0a1cf08f728e9b4487c6f9ed79d2f39410c92782', '')
.clickFunction('g - transact (not payable)')
.testFunction('last',
{

@ -9,13 +9,14 @@ const sources = [
]
module.exports = {
'@disabled': true,
before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done)
},
'@sources': function () {
return sources
},
'The sequence: Compiling / Deploying / Compiling another contract / calling the first contract - should display in the log the transaction with all the decoded information': function (browser: NightwatchBrowser) {
'The sequence: Compiling / Deploying / Compiling another contract / calling the first contract - should display in the log the transaction with all the decoded information #group1': function (browser: NightwatchBrowser) {
// https://github.com/ethereum/remix-ide/issues/2864
browser
.waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000)
@ -36,8 +37,7 @@ module.exports = {
.clickLaunchIcon('solidity')
.testContracts('Untitled1.sol', sources[1]['Untitled1.sol'], ['test'])
.clickLaunchIcon('udapp')
.clickFunction('delegate - transact (not payable)', { types: 'address to', values: '' })
.pause(5000)
.clickFunction('delegate - transact (not payable)', { types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"' })
.testFunction('last',
{
status: 'false Transaction mined but execution failed',

@ -41,6 +41,7 @@ const sources = [
]
module.exports = {
'@disabled': true,
before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done, 'http://127.0.0.1:8080/#optimize=true&runs=300&evmVersion=istanbul&version=soljson-v0.7.4+commit.3f05b770.js', true)
},
@ -49,7 +50,7 @@ module.exports = {
return sources
},
'Should load the code from URL params (code param)': function (browser: NightwatchBrowser) {
'Should load the code from URL params (code param) #group1': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('[for="autoCompile"]')
.click('[for="autoCompile"]') // we set it too false in the local storage
@ -66,11 +67,11 @@ module.exports = {
.getEditorValue((content) => {
browser.assert.ok(content && content.indexOf(
'https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol') !== -1,
'code has not been loaded')
'code has not been loaded')
})
},
'Should load the code from URL params (url param)': function (browser: NightwatchBrowser) {
'Should load the code from URL params (url param) #group1': function (browser: NightwatchBrowser) {
browser
.pause(5000)
.url('http://127.0.0.1:8080/#optimize=true&runs=300&evmVersion=istanbul&version=soljson-v0.7.4+commit.3f05b770.js&url=https://github.com/ethereum/remix-project/blob/master/apps/remix-ide/contracts/app/solidity/mode.sol')
@ -80,11 +81,40 @@ module.exports = {
.getEditorValue((content) => {
browser.assert.ok(content && content.indexOf(
'proposals.length = _numProposals;') !== -1,
'url has not been loaded')
'url has not been loaded')
})
},
'Should load the code from URL & code params': function (browser: NightwatchBrowser) {
'Should load Etherscan verified contractss from URL "address" param) #group2': function (browser: NightwatchBrowser) {
browser
.pause(5000)
.url('http://127.0.0.1:8080/#address=0x56db08fb78bc6689a1ef66efd079083fed0e4915')
.refresh()
.pause(7000)
.currentWorkspaceIs('etherscan-code-sample')
.assert.elementPresent('*[data-id=treeViewLitreeViewItemropsten]')
.assert.elementPresent('*[data-id=treeViewLitreeViewItemrinkeby]')
.assert.elementPresent('*[data-id="treeViewLitreeViewItemrinkeby/0x56db08fb78bc6689a1ef66efd079083fed0e4915"]')
.assert.elementPresent('*[data-id="treeViewLitreeViewItemrinkeby/0x56db08fb78bc6689a1ef66efd079083fed0e4915/Sample.sol"]')
.getEditorValue((content) => {
browser.assert.ok(content && content.indexOf(
'contract Sample {') !== -1)
})
.url('http://127.0.0.1:8080/#address=0xdac17f958d2ee523a2206206994597c13d831ec7')
.refresh()
.pause(7000)
.currentWorkspaceIs('etherscan-code-sample')
.assert.elementPresent('*[data-id=treeViewLitreeViewItemmainnet]')
.assert.elementPresent('*[data-id="treeViewLitreeViewItemmainnet/0xdac17f958d2ee523a2206206994597c13d831ec7"]')
.assert.elementPresent('*[data-id="treeViewLitreeViewItemmainnet/0xdac17f958d2ee523a2206206994597c13d831ec7/TetherToken.sol"]')
.getEditorValue((content) => {
browser.assert.ok(content && content.indexOf(
'contract TetherToken is Pausable, StandardToken, BlackList {') !== -1)
})
},
'Should load the code from URL & code params #group1': function (browser: NightwatchBrowser) {
browser
.pause(5000)
.url('http://127.0.0.1:8080/#optimize=true&runs=300&evmVersion=istanbul&version=soljson-v0.7.4+commit.3f05b770.js&url=https://github.com/ethereum/remix-project/blob/master/apps/remix-ide/contracts/app/solidity/mode.sol&code=cHJhZ21hIHNvbGlkaXR5ID49MC42LjAgPDAuNy4wOwoKaW1wb3J0ICJodHRwczovL2dpdGh1Yi5jb20vT3BlblplcHBlbGluL29wZW56ZXBwZWxpbi1jb250cmFjdHMvYmxvYi9tYXN0ZXIvY29udHJhY3RzL2FjY2Vzcy9Pd25hYmxlLnNvbCI7Cgpjb250cmFjdCBHZXRQYWlkIGlzIE93bmFibGUgewogIGZ1bmN0aW9uIHdpdGhkcmF3KCkgZXh0ZXJuYWwgb25seU93bmVyIHsKICB9Cn0')
@ -95,7 +125,7 @@ module.exports = {
.getEditorValue((content) => {
browser.assert.ok(content && content.indexOf(
'proposals.length = _numProposals;') !== -1,
'code has not been loaded')
'code has not been loaded')
})
.openFile('contract-76747f6e19.sol')
.openFile('ethereum')
@ -108,7 +138,7 @@ module.exports = {
.openFile('ethereum/remix-project/apps/remix-ide/contracts/app/solidity/mode.sol')
},
'Should load the code from language & code params': function (browser: NightwatchBrowser) {
'Should load the code from language & code params #group1': function (browser: NightwatchBrowser) {
browser
.pause(5000)
.url('http://127.0.0.1:8080/#language=yul&version=soljson-v0.8.7+commit.e28d00a7.js&code=Ly8gQSBjb250cmFjdCBjb25zaXN0cyBvZiBhIHNpbmdsZSBvYmplY3Qgd2l0aCBzdWItb2JqZWN0cyByZXByZXNlbnRpbmcKLy8gdGhlIGNvZGUgdG8gYmUgZGVwbG95ZWQgb3Igb3RoZXIgY29udHJhY3RzIGl0IGNhbiBjcmVhdGUuCi8vIFRoZSBzaW5nbGUgImNvZGUiIG5vZGUgaXMgdGhlIGV4ZWN1dGFibGUgY29kZSBvZiB0aGUgb2JqZWN0LgovLyBFdmVyeSAob3RoZXIpIG5hbWVkIG9iamVjdCBvciBkYXRhIHNlY3Rpb24gaXMgc2VyaWFsaXplZCBhbmQKLy8gbWFkZSBhY2Nlc3NpYmxlIHRvIHRoZSBzcGVjaWFsIGJ1aWx0LWluIGZ1bmN0aW9ucyBkYXRhY29weSAvIGRhdGFvZmZzZXQgLyBkYXRhc2l6ZQovLyBUaGUgY3VycmVudCBvYmplY3QsIHN1Yi1vYmplY3RzIGFuZCBkYXRhIGl0ZW1zIGluc2lkZSB0aGUgY3VycmVudCBvYmplY3QKLy8gYXJlIGluIHNjb3BlLgpvYmplY3QgIkNvbnRyYWN0MSIgewogICAgLy8gVGhpcyBpcyB0aGUgY29uc3RydWN0b3IgY29kZSBvZiB0aGUgY29udHJhY3QuCiAgICBjb2RlIHsKICAgICAgICBmdW5jdGlvbiBhbGxvY2F0ZShzaXplKSAtPiBwdHIgewogICAgICAgICAgICBwdHIgOj0gbWxvYWQoMHg0MCkKICAgICAgICAgICAgaWYgaXN6ZXJvKHB0cikgeyBwdHIgOj0gMHg2MCB9CiAgICAgICAgICAgIG1zdG9yZSgweDQwLCBhZGQocHRyLCBzaXplKSkKICAgICAgICB9CgogICAgICAgIC8vIGZpcnN0IGNyZWF0ZSAiQ29udHJhY3QyIgogICAgICAgIGxldCBzaXplIDo9IGRhdGFzaXplKCJDb250cmFjdDIiKQogICAgICAgIGxldCBvZmZzZXQgOj0gYWxsb2NhdGUoc2l6ZSkKICAgICAgICAvLyBUaGlzIHdpbGwgdHVybiBpbnRvIGNvZGVjb3B5IGZvciBFVk0KICAgICAgICBkYXRhY29weShvZmZzZXQsIGRhdGFvZmZzZXQoIkNvbnRyYWN0MiIpLCBzaXplKQogICAgICAgIC8vIGNvbnN0cnVjdG9yIHBhcmFtZXRlciBpcyBhIHNpbmdsZSBudW1iZXIgMHgxMjM0CiAgICAgICAgbXN0b3JlKGFkZChvZmZzZXQsIHNpemUpLCAweDEyMzQpCiAgICAgICAgcG9wKGNyZWF0ZShvZmZzZXQsIGFkZChzaXplLCAzMiksIDApKQoKICAgICAgICAvLyBub3cgcmV0dXJuIHRoZSBydW50aW1lIG9iamVjdCAodGhlIGN1cnJlbnRseQogICAgICAgIC8vIGV4ZWN1dGluZyBjb2RlIGlzIHRoZSBjb25zdHJ1Y3RvciBjb2RlKQogICAgICAgIHNpemUgOj0gZGF0YXNpemUoIkNvbnRyYWN0MV9kZXBsb3llZCIpCiAgICAgICAgb2Zmc2V0IDo9IGFsbG9jYXRlKHNpemUpCiAgICAgICAgLy8gVGhpcyB3aWxsIHR1cm4gaW50byBhIG1lbW9yeS0+bWVtb3J5IGNvcHkgZm9yIEV3YXNtIGFuZAogICAgICAgIC8vIGEgY29kZWNvcHkgZm9yIEVWTQogICAgICAgIGRhdGFjb3B5KG9mZnNldCwgZGF0YW9mZnNldCgiQ29udHJhY3QxX2RlcGxveWVkIiksIHNpemUpCiAgICAgICAgcmV0dXJuKG9mZnNldCwgc2l6ZSkKICAgIH0KCiAgICBkYXRhICJUYWJsZTIiIGhleCI0MTIzIgoKICAgIG9iamVjdCAiQ29udHJhY3QxX2RlcGxveWVkIiB7CiAgICAgICAgY29kZSB7CiAgICAgICAgICAgIGZ1bmN0aW9uIGFsbG9jYXRlKHNpemUpIC0+IHB0ciB7CiAgICAgICAgICAgICAgICBwdHIgOj0gbWxvYWQoMHg0MCkKICAgICAgICAgICAgICAgIGlmIGlzemVybyhwdHIpIHsgcHRyIDo9IDB4NjAgfQogICAgICAgICAgICAgICAgbXN0b3JlKDB4NDAsIGFkZChwdHIsIHNpemUpKQogICAgICAgICAgICB9CgogICAgICAgICAgICAvLyBydW50aW1lIGNvZGUKCiAgICAgICAgICAgIG1zdG9yZSgwLCAiSGVsbG8sIFdvcmxkISIpCiAgICAgICAgICAgIHJldHVybigwLCAweDIwKQogICAgICAgIH0KICAgIH0KCiAgICAvLyBFbWJlZGRlZCBvYmplY3QuIFVzZSBjYXNlIGlzIHRoYXQgdGhlIG91dHNpZGUgaXMgYSBmYWN0b3J5IGNvbnRyYWN0LAogICAgLy8gYW5kIENvbnRyYWN0MiBpcyB0aGUgY29kZSB0byBiZSBjcmVhdGVkIGJ5IHRoZSBmYWN0b3J5CiAgICBvYmplY3QgIkNvbnRyYWN0MiIgewogICAgICAgIGNvZGUgewogICAgICAgICAgICAvLyBjb2RlIGhlcmUgLi4uCiAgICAgICAgfQoKICAgICAgICBvYmplY3QgIkNvbnRyYWN0Ml9kZXBsb3llZCIgewogICAgICAgICAgICBjb2RlIHsKICAgICAgICAgICAgICAgIC8vIGNvZGUgaGVyZSAuLi4KICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgZGF0YSAiVGFibGUxIiBoZXgiNDEyMyIKICAgIH0KfQ&optimize=false&runs=200&evmVersion=null')
@ -124,7 +154,7 @@ module.exports = {
})
},
'Should select deploy with proxy option from URL params': function (browser: NightwatchBrowser) {
'Should select deploy with proxy option from URL params #group1': function (browser: NightwatchBrowser) {
browser
.url('http://127.0.0.1:8080/#optimize=false&runs=200&deployProxy=true')
.refresh()
@ -142,7 +172,7 @@ module.exports = {
.expect.element('[data-id="contractGUIDeployWithProxy"]').to.be.selected
},
'Should select upgrade with proxy option from URL params': function (browser: NightwatchBrowser) {
'Should select upgrade with proxy option from URL params #group1': function (browser: NightwatchBrowser) {
browser
.url('http://127.0.0.1:8080/#optimize=false&runs=200&upgradeProxy=true')
.refresh()
@ -159,7 +189,7 @@ module.exports = {
.expect.element('[data-id="contractGUIUpgradeImplementation"]').to.be.selected
},
'Should load using various URL compiler params': function (browser: NightwatchBrowser) {
'Should load using various URL compiler params #group1': function (browser: NightwatchBrowser) {
browser
.pause(5000)
.url('http://127.0.0.1:8080/#optimize=true&runs=300&autoCompile=true&evmVersion=istanbul&version=soljson-v0.7.4+commit.3f05b770.js&language=Yul')
@ -185,7 +215,7 @@ module.exports = {
.assert.containsText('#versionSelector option[data-id="selected"]', '0.8.15+commit.e14f2714')
},
'Should load using compiler from link passed in remix URL': function (browser: NightwatchBrowser) {
'Should load using compiler from link passed in remix URL #group1': function (browser: NightwatchBrowser) {
browser
.url('http://127.0.0.1:8080/#version=https://solidity-blog.s3.eu-central-1.amazonaws.com/data/08preview/soljson.js&optimize=false')
.refresh()
@ -194,16 +224,16 @@ module.exports = {
.pause(5000)
.click('*[data-id="scConfigExpander"]')
.assert.containsText('#versionSelector option[data-id="selected"]', 'custom')
// default values
// default values
.assert.containsText('#evmVersionSelector option[data-id="selected"]', 'default')
.verify.elementPresent('#optimize')
.assert.elementNotPresent('#optimize:checked')
.assert.not.elementPresent('#optimize:checked')
.verify.elementPresent('#runs:disabled')
.click('[for="optimize"')
.verify.attributeEquals('#runs', 'value', '200')
},
'Should load json files from link passed in remix URL': function (browser: NightwatchBrowser) {
'Should load json files from link passed in remix URL #group1': function (browser: NightwatchBrowser) {
browser
.url('http://127.0.0.1:8080/#optimize=false&runs=200&evmVersion=null&version=soljson-v0.6.12+commit.27d51765.js&url=https://raw.githubusercontent.com/EthVM/evm-source-verification/main/contracts/1/0x011e5846975c6463a8c6337eecf3cbf64e328884/input.json')
.refresh()

@ -13,7 +13,7 @@ module.exports = {
.click('*[data-id="verticalIconsKindpluginManager"]')
.scrollAndClick('*[data-id="pluginManagerComponentActivateButtondebugger"]')
.waitForElementVisible('*[data-id="pluginManagerComponentDeactivateButtondebugger"]', 7000)
.rightClick('[data-id="verticalIconsKinddebugger"]')
.rightClickCustom('[data-id="verticalIconsKinddebugger"]')
.waitForElementVisible('*[id="menuitemdeactivate"]')
.waitForElementVisible('*[id="menuitemdocumentation"]')
.click('*[data-id="remixIdeIconPanel"]')
@ -23,7 +23,7 @@ module.exports = {
browser.waitForElementVisible('div[data-id="remixIdeIconPanel"]', 10000)
.waitForElementVisible('*[data-id="verticalIconsKinddebugger"]', 7000)
.pause(5000)
.rightClick('[data-id="verticalIconsKinddebugger"]')
.rightClickCustom('[data-id="verticalIconsKinddebugger"]')
.click('*[id="menuitemdeactivate"]')
.click('*[data-id="verticalIconsKindsettings"]')
.click('*[data-id="verticalIconsKindpluginManager"]')

@ -33,7 +33,7 @@ module.exports = {
// WORKSPACE TEMPLATES E2E START
'Should create Remix default workspace with files': function (browser: NightwatchBrowser) {
'Should create Remix default workspace with files #group1': function (browser: NightwatchBrowser) {
browser
.clickLaunchIcon('filePanel')
.click('*[data-id="workspaceCreate"]')
@ -44,53 +44,53 @@ module.exports = {
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
.pause(1000)
.assert.elementPresent('*[data-id="treeViewLitreeViewItemcontracts"]')
.assert.elementPresent('*[data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]')
.assert.elementPresent('*[data-id="treeViewLitreeViewItemcontracts/2_Owner.sol"]')
.assert.elementPresent('*[data-id="treeViewLitreeViewItemcontracts/3_Ballot.sol"]')
.assert.elementPresent('*[data-id="treeViewLitreeViewItemscripts"]')
.assert.elementPresent('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/2_Owner.sol"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/3_Ballot.sol"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]')
// check js and ts files are not transformed
.click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]')
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(`import { deploy } from './web3-lib'`) !== -1,
'Incorrect content')
'Incorrect content')
})
.assert.elementPresent('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]')
.click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]')
.pause(100)
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(`import { deploy } from './ethers-lib'`) !== -1,
'Incorrect content')
'Incorrect content')
})
.assert.elementPresent('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]')
.click('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]')
.pause(2000)
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(`export const deploy = async (contractName: string, args: Array<any>, from?: string, gas?: number): Promise<Options> => {`) !== -1,
'Incorrect content')
'Incorrect content')
})
.assert.elementPresent('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]')
.click('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]')
.pause(100)
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(`export const deploy = async (contractName: string, args: Array<any>, accountIndex?: number): Promise<ethers.Contract> => {`) !== -1,
'Incorrect content')
'Incorrect content')
})
.assert.elementPresent('*[data-id="treeViewLitreeViewItemtests"]')
.assert.elementPresent('*[data-id="treeViewLitreeViewItemtests/storage.test.js"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtests"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtests/storage.test.js"]')
.click('*[data-id="treeViewLitreeViewItemtests/storage.test.js"]')
.pause(100)
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(`const { expect } = require("chai");`) !== -1,
'Incorrect content')
'Incorrect content')
})
.assert.elementPresent('*[data-id="treeViewLitreeViewItemtests/Ballot_test.sol"]')
.assert.elementPresent('*[data-id="treeViewLitreeViewItemREADME.txt"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtests/Ballot_test.sol"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemREADME.txt"]')
},
'Should create blank workspace with no files': function (browser: NightwatchBrowser) {
'Should create blank workspace with no files #group1': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="workspaceCreate"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
@ -102,16 +102,16 @@ module.exports = {
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
.pause(100)
.assert.elementPresent('*[data-id="treeViewUltreeViewMenu"]')
.waitForElementPresent('*[data-id="treeViewUltreeViewMenu"]')
.execute(function () {
const fileList = document.querySelector('*[data-id="treeViewUltreeViewMenu"]')
return fileList.getElementsByTagName('li').length;
}, [], function(result){
browser.assert.equal(result.value, 0, 'Incorrect number of files');
}, [], function (result) {
browser.assert.equal(result.value, 0, 'Incorrect number of files');
});
},
'Should create ERC20 workspace with files': function (browser: NightwatchBrowser) {
'Should create ERC20 workspace with files #group1': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="workspaceCreate"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
@ -123,43 +123,43 @@ module.exports = {
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
.pause(100)
.assert.elementPresent('*[data-id="treeViewLitreeViewItemcontracts"]')
.assert.elementPresent('*[data-id="treeViewLitreeViewItemcontracts/SampleERC20.sol"]')
.assert.elementPresent('*[data-id="treeViewLitreeViewItemscripts"]')
.assert.elementPresent('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/SampleERC20.sol"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]')
// check js and ts files are not transformed
.click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]')
.getEditorValue((content) => {
.pause(5000)
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(`import { deploy } from './web3-lib'`) !== -1,
'Incorrect content')
'Incorrect content')
})
.assert.elementPresent('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]')
.click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]')
.pause(100)
.getEditorValue((content) => {
.pause(4000)
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(`import { deploy } from './ethers-lib'`) !== -1,
'Incorrect content')
'Incorrect content')
})
.assert.elementPresent('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]')
.click('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]')
.pause(100)
.getEditorValue((content) => {
.pause(4000)
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(`export const deploy = async (contractName: string, args: Array<any>, from?: string, gas?: number): Promise<Options> => {`) !== -1,
'Incorrect content')
'Incorrect content')
})
.assert.elementPresent('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]')
.click('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]')
.pause(100)
.getEditorValue((content) => {
.pause(4000)
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(`export const deploy = async (contractName: string, args: Array<any>, accountIndex?: number): Promise<ethers.Contract> => {`) !== -1,
'Incorrect content')
'Incorrect content')
})
.assert.elementPresent('*[data-id="treeViewLitreeViewItemtests"]')
.assert.elementPresent('*[data-id="treeViewLitreeViewItemtests/SampleERC20_test.sol"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtests"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtests/SampleERC20_test.sol"]')
},
'Should create ERC721 workspace with files': function (browser: NightwatchBrowser) {
'Should create ERC721 workspace with files #group1': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="workspaceCreate"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
@ -171,72 +171,70 @@ module.exports = {
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
.pause(100)
.assert.elementPresent('*[data-id="treeViewLitreeViewItemcontracts"]')
.assert.elementPresent('*[data-id="treeViewLitreeViewItemcontracts/SampleERC721.sol"]')
.assert.elementPresent('*[data-id="treeViewLitreeViewItemscripts"]')
.assert.elementPresent('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/SampleERC721.sol"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]')
// check js and ts files are not transformed
.click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]')
.getEditorValue((content) => {
.pause(4000)
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(`import { deploy } from './web3-lib'`) !== -1,
'Incorrect content')
'Incorrect content')
})
.assert.elementPresent('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]')
.click('*[data-id="treeViewLitreeViewItemscripts/deploy_with_ethers.ts"]')
.pause(100)
.getEditorValue((content) => {
.pause(4000)
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(`import { deploy } from './ethers-lib'`) !== -1,
'Incorrect content')
'Incorrect content')
})
.assert.elementPresent('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]')
.click('*[data-id="treeViewLitreeViewItemscripts/web3-lib.ts"]')
.pause(100)
.getEditorValue((content) => {
.pause(4000)
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(`export const deploy = async (contractName: string, args: Array<any>, from?: string, gas?: number): Promise<Options> => {`) !== -1,
'Incorrect content')
'Incorrect content')
})
.assert.elementPresent('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]')
.click('*[data-id="treeViewLitreeViewItemscripts/ethers-lib.ts"]')
.pause(100)
.getEditorValue((content) => {
.pause(4000)
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(`export const deploy = async (contractName: string, args: Array<any>, accountIndex?: number): Promise<ethers.Contract> => {`) !== -1,
'Incorrect content')
'Incorrect content')
})
.assert.elementPresent('*[data-id="treeViewLitreeViewItemtests"]')
.assert.elementPresent('*[data-id="treeViewLitreeViewItemtests/SampleERC721_test.sol"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtests"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtests/SampleERC721_test.sol"]')
},
// WORKSPACE TEMPLATES E2E END
'Should create two workspace and switch to the first one': function (browser: NightwatchBrowser) {
'Should create two workspace and switch to the first one #group1': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="workspaceCreate"]') // create workspace_name
.click('*[data-id="workspaceCreate"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
.click('*[data-id="modalDialogCustomPromptTextCreate"]')
.clearValue('*[data-id="modalDialogCustomPromptTextCreate"]')
.setValue('*[data-id="modalDialogCustomPromptTextCreate"]', 'workspace_name')
.click('*[data-id="fileSystemModalDialogContainer-react"] input[data-id="modalDialogCustomPromptTextCreate"]')
.setValue('*[data-id="fileSystemModalDialogContainer-react"] input[data-id="modalDialogCustomPromptTextCreate"]', 'workspace_name')
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.click('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtests"]')
.pause(1000)
.addFile('test.sol', { content: 'test' })
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtest.sol"]')
.click('*[data-id="workspaceCreate"]') // create workspace_name_1
.click('*[data-id="workspaceCreate"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
.click('*[data-id="modalDialogCustomPromptTextCreate"]')
.clearValue('*[data-id="modalDialogCustomPromptTextCreate"]')
.setValue('*[data-id="modalDialogCustomPromptTextCreate"]', 'workspace_name_1')
.click('*[data-id="fileSystemModalDialogContainer-react"] input[data-id="modalDialogCustomPromptTextCreate"]')
.setValue('*[data-id="fileSystemModalDialogContainer-react"] input[data-id="modalDialogCustomPromptTextCreate"]', 'workspace_name_1')
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.click('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.click('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.pause(2000)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtests"]')
.pause(2000)
.waitForElementNotPresent('*[data-id="treeViewLitreeViewItemtest.sol"]')
.pause(2000)
.switchWorkspace('workspace_name')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtests"]')
.currentWorkspaceIs('workspace_name')
},
'Should rename a workspace #group1': function (browser: NightwatchBrowser) {
@ -251,9 +249,11 @@ module.exports = {
.click('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.switchWorkspace('workspace_name_1')
.pause(2000)
.currentWorkspaceIs('workspace_name_1')
.waitForElementNotPresent('*[data-id="treeViewLitreeViewItemtest.sol"]')
.switchWorkspace('workspace_name_renamed')
.pause(2000)
.currentWorkspaceIs('workspace_name_renamed')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtest.sol"]')
},
@ -268,84 +268,85 @@ module.exports = {
.waitForElementNotPresent(`[data-id="dropdown-item-workspace_name_1"]`)
},
// CLONE REPOSITORY E2E START
// CLONE REPOSITORY E2E START
'Should clone a repository #group2': function (browser: NightwatchBrowser) {
browser
.clickLaunchIcon('filePanel')
.waitForElementVisible('[data-id="cloneGitRepository"]')
.click('[data-id="cloneGitRepository"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalBody-react"]')
.click('[data-id="fileSystemModalDialogModalBody-react"]')
.waitForElementVisible('[data-id="modalDialogCustomPromptTextClone"]')
.setValue('[data-id="modalDialogCustomPromptTextClone"]', 'https://github.com/ethereum/awesome-remix')
.click('[data-id="fileSystem-modal-footer-ok-react"]')
.waitForElementPresent('.fa-spinner')
.pause(5000)
.waitForElementNotPresent('.fa-spinner')
.waitForElementVisible('*[data-id="treeViewLitreeViewItem.git"]')
.waitForElementContainsText('[data-id="workspacesSelect"]', 'awesome-remix')
},
'Should clone a repository #group2': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('[data-id="cloneGitRepository"]')
.click('[data-id="cloneGitRepository"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalBody-react"]')
.click('[data-id="fileSystemModalDialogModalBody-react"]')
.waitForElementVisible('[data-id="modalDialogCustomPromptTextClone"]')
.setValue('[data-id="modalDialogCustomPromptTextClone"]', 'https://github.com/ethereum/awesome-remix')
.click('[data-id="fileSystem-modal-footer-ok-react"]')
.waitForElementPresent('.fa-spinner')
.pause(5000)
.waitForElementNotPresent('.fa-spinner')
.waitForElementVisible('*[data-id="treeViewLitreeViewItem.git"]')
.waitForElementContainsText('[data-id="workspacesSelect"]', 'awesome-remix')
},
'Should display dgit icon for cloned workspace #group2': function (browser: NightwatchBrowser) {
browser
.switchWorkspace('default_workspace')
.waitForElementNotVisible('[data-id="workspacesSelect"] .fa-code-branch')
.switchWorkspace('awesome-remix')
.waitForElementVisible('[data-id="workspacesSelect"] .fa-code-branch')
},
'Should display dgit icon for cloned workspace #group2': function (browser: NightwatchBrowser) {
browser
.switchWorkspace('default_workspace')
.waitForElementNotVisible('[data-id="workspacesSelect"] .fa-code-branch')
.switchWorkspace('awesome-remix')
.waitForElementVisible('[data-id="workspacesSelect"] .fa-code-branch')
},
'Should display non-clashing names for duplicate clone #group2': '' + function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('[data-id="cloneGitRepository"]')
.click('[data-id="cloneGitRepository"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalBody-react"]')
.click('[data-id="fileSystemModalDialogModalBody-react"]')
.waitForElementVisible('[data-id="modalDialogCustomPromptTextClone"]')
.setValue('[data-id="modalDialogCustomPromptTextClone"]', 'https://github.com/ethereum/awesome-remix')
.click('[data-id="fileSystem-modal-footer-ok-react"]')
.pause(5000)
.waitForElementContainsText('[data-id="workspacesSelect"]', 'awesome-remix1')
.waitForElementVisible('[data-id="cloneGitRepository"]')
.click('[data-id="cloneGitRepository"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalBody-react"]')
.click('[data-id="fileSystemModalDialogModalBody-react"]')
.waitForElementVisible('[data-id="modalDialogCustomPromptTextClone"]')
.setValue('[data-id="modalDialogCustomPromptTextClone"]', 'https://github.com/ethereum/awesome-remix')
.click('[data-id="fileSystem-modal-footer-ok-react"]')
.pause(5000)
.waitForElementContainsText('[data-id="workspacesSelect"]', 'awesome-remix2')
.waitForElementVisible('[data-id="cloneGitRepository"]')
.click('[data-id="cloneGitRepository"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalBody-react"]')
.click('[data-id="fileSystemModalDialogModalBody-react"]')
.waitForElementVisible('[data-id="modalDialogCustomPromptTextClone"]')
.setValue('[data-id="modalDialogCustomPromptTextClone"]', 'https://github.com/ethereum/awesome-remix')
.click('[data-id="fileSystem-modal-footer-ok-react"]')
.pause(5000)
.waitForElementContainsText('[data-id="workspacesSelect"]', 'awesome-remix3')
.switchWorkspace('awesome-remix')
.switchWorkspace('awesome-remix1')
.switchWorkspace('awesome-remix2')
.switchWorkspace('awesome-remix3')
},
'Should display non-clashing names for duplicate clone #group2': '' + function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('[data-id="cloneGitRepository"]')
.click('[data-id="cloneGitRepository"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalBody-react"]')
.click('[data-id="fileSystemModalDialogModalBody-react"]')
.waitForElementVisible('[data-id="modalDialogCustomPromptTextClone"]')
.setValue('[data-id="modalDialogCustomPromptTextClone"]', 'https://github.com/ethereum/awesome-remix')
.click('[data-id="fileSystem-modal-footer-ok-react"]')
.pause(5000)
.waitForElementContainsText('[data-id="workspacesSelect"]', 'awesome-remix1')
.waitForElementVisible('[data-id="cloneGitRepository"]')
.click('[data-id="cloneGitRepository"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalBody-react"]')
.click('[data-id="fileSystemModalDialogModalBody-react"]')
.waitForElementVisible('[data-id="modalDialogCustomPromptTextClone"]')
.setValue('[data-id="modalDialogCustomPromptTextClone"]', 'https://github.com/ethereum/awesome-remix')
.click('[data-id="fileSystem-modal-footer-ok-react"]')
.pause(5000)
.waitForElementContainsText('[data-id="workspacesSelect"]', 'awesome-remix2')
.waitForElementVisible('[data-id="cloneGitRepository"]')
.click('[data-id="cloneGitRepository"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalBody-react"]')
.click('[data-id="fileSystemModalDialogModalBody-react"]')
.waitForElementVisible('[data-id="modalDialogCustomPromptTextClone"]')
.setValue('[data-id="modalDialogCustomPromptTextClone"]', 'https://github.com/ethereum/awesome-remix')
.click('[data-id="fileSystem-modal-footer-ok-react"]')
.pause(5000)
.waitForElementContainsText('[data-id="workspacesSelect"]', 'awesome-remix3')
.switchWorkspace('awesome-remix')
.switchWorkspace('awesome-remix1')
.switchWorkspace('awesome-remix2')
.switchWorkspace('awesome-remix3')
},
'Should display error message in modal for failed clone #group2': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('[data-id="cloneGitRepository"]')
.click('[data-id="cloneGitRepository"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalBody-react"]')
.click('[data-id="fileSystemModalDialogModalBody-react"]')
.waitForElementVisible('[data-id="modalDialogCustomPromptTextClone"]')
.setValue('[data-id="modalDialogCustomPromptTextClone"]', 'https://github.com/ethereum/non-existent-repo')
.click('[data-id="fileSystem-modal-footer-ok-react"]')
.pause(5000)
.waitForElementVisible('[data-id="cloneGitRepositoryModalDialogModalBody-react"]')
.waitForElementContainsText('[data-id="cloneGitRepositoryModalDialogModalBody-react"]', 'An error occurred: Please check that you have the correct URL for the repo. If the repo is private, you need to add your github credentials (with the valid token permissions) in Settings plugin')
.click('[data-id="cloneGitRepository-modal-footer-ok-react"]')
.end()
},
'Should display error message in modal for failed clone #group2': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('[data-id="cloneGitRepository"]')
.click('[data-id="cloneGitRepository"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalBody-react"]')
.click('[data-id="fileSystemModalDialogModalBody-react"]')
.waitForElementVisible('[data-id="modalDialogCustomPromptTextClone"]')
.setValue('[data-id="modalDialogCustomPromptTextClone"]', 'https://github.com/ethereum/non-existent-repo')
.click('[data-id="fileSystem-modal-footer-ok-react"]')
.pause(5000)
.waitForElementVisible('[data-id="cloneGitRepositoryModalDialogModalBody-react"]')
.waitForElementContainsText('[data-id="cloneGitRepositoryModalDialogModalBody-react"]', 'An error occurred: Please check that you have the correct URL for the repo. If the repo is private, you need to add your github credentials (with the valid token permissions) in Settings plugin')
.click('[data-id="cloneGitRepository-modal-footer-ok-react"]')
.end()
},
// CLONE REPOSITORY E2E END
// CLONE REPOSITORY E2E END
tearDown: sauce
}

@ -21,14 +21,14 @@ declare module 'nightwatch' {
modalFooterOKClick(id?: string): NightwatchBrowser,
clickInstance(index: number): NightwatchBrowser,
journalLastChildIncludes(val: string): NightwatchBrowser,
executeScript(script: string): NightwatchBrowser,
executeScriptInTerminal(script: string): NightwatchBrowser,
clearEditableContent(cssSelector: string): NightwatchBrowser,
journalChildIncludes(val: string, opts = { shouldHaveOnlyOneOccurence: boolean }): NightwatchBrowser,
debugTransaction(index: number): NightwatchBrowser,
checkElementStyle(cssSelector: string, styleProperty: string, expectedResult: string): NightwatchBrowser,
openFile(name: string): NightwatchBrowser,
renamePath(path: string, newFileName: string, renamedPath: string): NightwatchBrowser,
rightClick(cssSelector: string): NightwatchBrowser,
rightClickCustom(cssSelector: string): NightwatchBrowser,
scrollToLine(line: number): NightwatchBrowser,
waitForElementContainsText(id: string, value: string, timeout?: number): NightwatchBrowser,
getModalBody(callback: (value: string, cb: VoidFunction) => void): NightwatchBrowser,

@ -14,8 +14,7 @@ yarn run remixd &
sleep 5
yarn run build:e2e
TESTFILES=$(grep -IRiL "\'@disabled\': \?true" "dist/apps/remix-ide-e2e/src/tests" | grep "\.spec\|\.test" | sort | circleci tests split )
TESTFILES=$(grep -IRiL "@disabled" "dist/apps/remix-ide-e2e/src/tests" | grep "\.spec\|\.test" | sort | circleci tests split )
for TESTFILE in $TESTFILES; do
npx nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js $TESTFILE --env=$1 || TEST_EXITCODE=1
done

@ -57,7 +57,7 @@ module.exports = class Filepanel extends ViewPlugin {
this.slitherHandle = new SlitherHandle()
this.workspaces = []
this.appManager = appManager
this.currentWorkspaceMetadata = {}
this.currentWorkspaceMetadata = null
}
render () {

@ -156,7 +156,7 @@ export class ExecutionContext {
return cb()
} else {
if (injectedProvider && injectedProvider._metamask && injectedProvider._metamask.isUnlocked) {
if (!await injectedProvider._metamask.isUnlocked()) this.call('notification', 'toast', 'Please make sure the injected provider is unlocked (e.g Metamask).')
if (!await injectedProvider._metamask.isUnlocked()) infoCb('Please make sure the injected provider is unlocked (e.g Metamask).')
}
this.askPermission()
this.executionContext = context

@ -222,9 +222,10 @@ export const CompilerApiMixin = (Base) => class extends Base {
}
this.compiler.event.register('loadingCompiler', this.data.eventHandlers.onLoadingCompiler)
this.data.eventHandlers.onCompilerLoaded = () => {
this.data.eventHandlers.onCompilerLoaded = (version) => {
this.data.loading = false
this.statusChanged({ key: 'none' })
this.emit('compilerLoaded', version)
}
this.compiler.event.register('compilerLoaded', this.data.eventHandlers.onCompilerLoaded)

@ -59,7 +59,7 @@ const App: React.FC = () => {
function compilerUrl() {
return state.environment === 'remote'
? 'https://vyper.live/compile'
? 'https://vyper.remixproject.org/compile'
: state.localUrl
}

@ -38,7 +38,7 @@ const testFiles: string[] = [
'forLoopIteratesOverDynamicArray.sol'
]
let compilationResults: Record<string, CompilationResult> = {}
const compilationResults: Record<string, CompilationResult> = {}
test('setup', function (t: test.Test) {
solcOrg.loadRemoteVersion('v0.4.24+commit.e67f0147', (error, compiler) => {

@ -1,24 +1,28 @@
export const fetchContractFromEtherscan = async (plugin, network, contractAddress, targetPath, key?) => {
export const fetchContractFromEtherscan = async (plugin, network, contractAddress, targetPath, shouldSetFile = true, key?) => {
let data
const compilationTargets = {}
let etherscanKey
if (!key) etherscanKey = await plugin.call('config', 'getAppParameter', 'etherscan-access-token')
else etherscanKey = key
if (etherscanKey) {
const endpoint = network.id == 1 ? 'api.etherscan.io' : 'api-' + network.name + '.etherscan.io'
data = await fetch('https://' + endpoint + '/api?module=contract&action=getsourcecode&address=' + contractAddress + '&apikey=' + etherscanKey)
data = await data.json()
// etherscan api doc https://docs.etherscan.io/api-endpoints/contracts
if (data.message === 'OK' && data.status === "1") {
if (data.result.length) {
if (data.result[0].SourceCode === '') throw new Error(`contract not verified on Etherscan ${network.name} network`)
if (data.result[0].SourceCode.startsWith('{')) {
data.result[0].SourceCode = JSON.parse(data.result[0].SourceCode.replace(/(?:\r\n|\r|\n)/g, '').replace(/^{{/,'{').replace(/}}$/,'}'))
try {
data = await fetch('https://' + endpoint + '/api?module=contract&action=getsourcecode&address=' + contractAddress + '&apikey=' + etherscanKey)
data = await data.json()
// etherscan api doc https://docs.etherscan.io/api-endpoints/contracts
if (data.message === 'OK' && data.status === "1") {
if (data.result.length) {
if (data.result[0].SourceCode === '') throw new Error(`contract not verified on Etherscan ${network.name} network`)
if (data.result[0].SourceCode.startsWith('{')) {
data.result[0].SourceCode = JSON.parse(data.result[0].SourceCode.replace(/(?:\r\n|\r|\n)/g, '').replace(/^{{/, '{').replace(/}}$/, '}'))
}
}
}
} else throw new Error('unable to retrieve contract data ' + data.message)
} else throw new Error('unable to retrieve contract data ' + data.message)
} catch (e) {
throw new Error('unable to retrieve contract data: ' + e.message)
}
} else throw new Error('unable to try fetching the source code from etherscan: etherscan access token not found. please go to the Remix settings page and provide an access token.')
if (!data || !data.result) {
@ -27,7 +31,7 @@ export const fetchContractFromEtherscan = async (plugin, network, contractAddres
if (typeof data.result[0].SourceCode === 'string') {
const fileName = `${targetPath}/${data.result[0].ContractName}.sol`
await plugin.call('fileManager', 'setFile', fileName , data.result[0].SourceCode)
if (shouldSetFile) await plugin.call('fileManager', 'setFile', fileName, data.result[0].SourceCode)
compilationTargets[fileName] = { content: data.result[0].SourceCode }
} else if (data.result[0].SourceCode && typeof data.result[0].SourceCode == 'object') {
const sources = data.result[0].SourceCode.sources
@ -36,10 +40,10 @@ export const fetchContractFromEtherscan = async (plugin, network, contractAddres
file = file.replace(/^\//g, '') // remove first slash.
if (await plugin.call('contentImport', 'isExternalUrl', file)) {
// nothing to do, the compiler callback will handle those
} else {
} else {
const path = `${targetPath}/${file}`
const content = (source as any).content
await plugin.call('fileManager', 'setFile', path, content)
if (shouldSetFile) await plugin.call('fileManager', 'setFile', path, content)
compilationTargets[path] = { content }
}
}
@ -47,7 +51,7 @@ export const fetchContractFromEtherscan = async (plugin, network, contractAddres
let runs = 0
try {
runs = parseInt(data.result[0].Runs)
} catch (e) {}
} catch (e) { }
const settings = {
version: data.result[0].CompilerVersion.replace(/^v/, ''),
language: 'Solidity',

@ -64,7 +64,7 @@ commander
// If path is for a file, file name must have `_test.sol` suffix
if (!isDirectory && !testsPath.endsWith('_test.sol')) {
log.error('Test filename should end with "_test.sol"')
process.exit()
process.exit(1)
}
// Console message
@ -85,7 +85,7 @@ commander
const compString = releases ? releases[compVersion] : null
if (!compString) {
log.error(`No compiler found in releases with version ${compVersion}`)
process.exit()
process.exit(1)
} else {
compilerConfig.currentCompilerUrl = compString.replace('soljson-', '').replace('.js', '')
log.info(`Compiler version set to ${compVersion}. Latest version is ${latestRelease}`)
@ -105,7 +105,7 @@ commander
if (commander.runs) {
if (!commander.optimize) {
log.error('Optimization should be enabled for runs')
process.exit()
process.exit(1)
}
compilerConfig.runs = commander.runs
log.info(`Runs set to ${compilerConfig.runs}`)
@ -116,12 +116,14 @@ commander
await provider.init()
web3.setProvider(provider)
extend(web3)
runTestFiles(path.resolve(testsPath), isDirectory, web3, compilerConfig)
runTestFiles(path.resolve(testsPath), isDirectory, web3, compilerConfig, (error) => {
if (error) process.exit(1)
})
})
if (!process.argv.slice(2).length) {
log.error('Please specify a file or directory path')
process.exit()
process.exit(1)
}
commander.parse(process.argv)

@ -1,6 +1,7 @@
import React from 'react' // eslint-disable-line
import DropdownPanel from './dropdown-panel' // eslint-disable-line
import { BN } from 'ethereumjs-util'
import Web3 from 'web3'
export const GlobalVariables = ({ block, receipt, tx }) => {
// see https://docs.soliditylang.org/en/latest/units-and-global-variables.html#block-and-transaction-properties
@ -17,7 +18,7 @@ export const GlobalVariables = ({ block, receipt, tx }) => {
'tx.origin': tx.from
}
if (block.baseFeePerGas) {
globals['block.basefee'] = (new BN(block.baseFeePerGas.replace('0x', ''), 'hex')).toString(10) + ` Wei (${block.baseFeePerGas})`
globals['block.basefee'] = Web3.utils.toBN(block.baseFeePerGas).toString(10) + ` Wei (${block.baseFeePerGas})`
}
return (

@ -1,133 +0,0 @@
/* eslint-disable */
export const cairoConf = {
comments: {
lineComment: '#'
},
brackets: [
['{', '}'],
['[', ']'],
['(', ')'],
['%{', '%}']
],
autoClosingPairs: [
{ open: '{', close: '}' },
{ open: '[', close: ']' },
{ open: '(', close: ')' },
{ open: '%{', close: '%}' },
{ open: "'", close: "'", notIn: ['string', 'comment'] }
],
surroundingPairs: [
{ open: '{', close: '}' },
{ open: '[', close: ']' },
{ open: '(', close: ')' },
{ open: '%{', close: '%}' },
{ open: "'", close: "'" }
]
}
export const cairoLang = {
defaultToken: '',
tokenPostfix: '.cairo',
brackets: [
{ token: 'delimiter.curly', open: '{', close: '}' },
{ token: 'delimiter.parenthesis', open: '(', close: ')' },
{ token: 'delimiter.square', open: '[', close: ']' },
{ token: 'delimiter.curly', open: '%{', close: '%}' }
],
keywords: [
// control
'if',
'else',
'end',
// meta
'alloc_locals',
'as',
'assert',
'cast',
'const',
'dw',
'felt',
'from',
'func',
'import',
'let',
'local',
'member',
'nondet',
'return',
'static_assert',
'struct',
'tempvar',
'with_attr',
'with',
// register
'ap',
'fp',
// opcode
'call',
'jmp',
'ret',
'abs',
'rel'
],
operators: ['=', ':', '==', '++', '+', '-', '*', '**', '/', '&', '%', '_'],
// we include these common regular expressions
symbols: /[=><!~?:&|+\-*\/\^%]+/,
numberDecimal: /[+-]?[0-9]+/,
numberHex: /[+-]?0x[0-9a-fA-F]+/,
// The main tokenizer for our languages
tokenizer: {
root: [
// identifiers and keywords
[
/[a-zA-Z_]\w*/,
{
cases: {
'@keywords': { token: 'keyword.$0' },
'@default': 'identifier'
}
}
],
// whitespace
{ include: '@whitespace' },
// directives
[/^%[a-zA-Z]\w*/, 'tag'],
// delimiters and operators
[/[{}()\[\]]/, '@brackets'],
[/[<>](?!@symbols)/, '@brackets'],
[
/@symbols/,
{
cases: {
'@operators': 'delimiter',
'@default': ''
}
}
],
// numbers
[/(@numberHex)/, 'number.hex'],
[/(@numberDecimal)/, 'number'],
// strings
[/'[^']*'/, 'string']
],
whitespace: [
[/\s+/, 'white'],
[/(^#.*$)/, 'comment']
]
}
}

@ -2,8 +2,9 @@ import React, { useState, useRef, useEffect, useReducer } from 'react' // eslint
import { RemixUiEditorContextView, astNode } from '@remix-ui/editor-context-view'
import Editor, { loader } from '@monaco-editor/react'
import { reducerActions, reducerListener, initialState } from './actions/editor'
import { language, conf } from './syntax'
import { cairoLang, cairoConf } from './cairoSyntax'
import { solidityTokensProvider, solidityLanguageConfig } from './syntaxes/solidity'
import { cairoTokensProvider, cairoLanguageConfig } from './syntaxes/cairo'
import { zokratesTokensProvider, zokratesLanguageConfig } from './syntaxes/zokrates'
import { IMarkdownString } from 'monaco-editor'
import './remix-ui-editor.css'
@ -275,6 +276,8 @@ export const EditorUI = (props: EditorUIProps) => {
monacoRef.current.editor.setModelLanguage(file.model, 'remix-solidity')
} else if (file.language === 'cairo') {
monacoRef.current.editor.setModelLanguage(file.model, 'remix-cairo')
} else if (file.language === 'zokrates') {
monacoRef.current.editor.setModelLanguage(file.model, 'remix-zokrates')
}
}, [props.currentFile])
@ -497,12 +500,17 @@ export const EditorUI = (props: EditorUIProps) => {
// Register a new language
monacoRef.current.languages.register({ id: 'remix-solidity' })
monacoRef.current.languages.register({ id: 'remix-cairo' })
monacoRef.current.languages.register({ id: 'remix-zokrates' })
// Register a tokens provider for the language
monacoRef.current.languages.setMonarchTokensProvider('remix-solidity', language)
monacoRef.current.languages.setLanguageConfiguration('remix-solidity', conf)
monacoRef.current.languages.setMonarchTokensProvider('remix-solidity', solidityTokensProvider)
monacoRef.current.languages.setLanguageConfiguration('remix-solidity', solidityLanguageConfig)
monacoRef.current.languages.setMonarchTokensProvider('remix-cairo', cairoTokensProvider)
monacoRef.current.languages.setLanguageConfiguration('remix-cairo', cairoLanguageConfig)
monacoRef.current.languages.setMonarchTokensProvider('remix-cairo', cairoLang)
monacoRef.current.languages.setLanguageConfiguration('remix-cairo', cairoConf)
monacoRef.current.languages.setMonarchTokensProvider('remix-zokrates', zokratesTokensProvider)
monacoRef.current.languages.setLanguageConfiguration('remix-zokrates', zokratesLanguageConfig)
loadTypes(monacoRef.current)
}

@ -0,0 +1,132 @@
/* eslint-disable */
export const cairoLanguageConfig = {
comments: {
lineComment: "#",
},
brackets: [
["{", "}"],
["[", "]"],
["(", ")"],
["%{", "%}"],
],
autoClosingPairs: [
{ open: "{", close: "}" },
{ open: "[", close: "]" },
{ open: "(", close: ")" },
{ open: "%{", close: "%}" },
{ open: "'", close: "'", notIn: ["string", "comment"] },
],
surroundingPairs: [
{ open: "{", close: "}" },
{ open: "[", close: "]" },
{ open: "(", close: ")" },
{ open: "%{", close: "%}" },
{ open: "'", close: "'" },
],
}
export const cairoTokensProvider = {
defaultToken: "",
tokenPostfix: ".cairo",
brackets: [
{ token: "delimiter.curly", open: "{", close: "}" },
{ token: "delimiter.parenthesis", open: "(", close: ")" },
{ token: "delimiter.square", open: "[", close: "]" },
{ token: "delimiter.curly", open: "%{", close: "%}" },
],
keywords: [
// control
"if",
"else",
"end",
// meta
"alloc_locals",
"as",
"assert",
"cast",
"const",
"dw",
"felt",
"from",
"func",
"import",
"let",
"local",
"member",
"nondet",
"return",
"static_assert",
"struct",
"tempvar",
"with_attr",
"with",
// register
"ap",
"fp",
// opcode
"call",
"jmp",
"ret",
"abs",
"rel",
],
operators: ["=", ":", "==", "++", "+", "-", "*", "**", "/", "&", "%", "_"],
// we include these common regular expressions
symbols: /[=><!~?:&|+\-*\/\^%]+/,
numberDecimal: /[+-]?[0-9]+/,
numberHex: /[+-]?0x[0-9a-fA-F]+/,
// The main tokenizer for our languages
tokenizer: {
root: [
// identifiers and keywords
[
/[a-zA-Z_]\w*/,
{
cases: {
"@keywords": { token: "keyword.$0" },
"@default": "identifier",
},
},
],
// whitespace
{ include: "@whitespace" },
// directives
[/^%[a-zA-Z]\w*/, "tag"],
// delimiters and operators
[/[{}()\[\]]/, "@brackets"],
[/[<>](?!@symbols)/, "@brackets"],
[
/@symbols/,
{
cases: {
"@operators": "delimiter",
"@default": "",
},
},
],
// numbers
[/(@numberHex)/, "number.hex"],
[/(@numberDecimal)/, "number"],
// strings
[/'[^']*'/, "string"],
],
whitespace: [
[/\s+/, "white"],
[/(^#.*$)/, "comment"],
],
},
}

@ -1,5 +1,5 @@
/* eslint-disable */
export const conf = {
export const solidityLanguageConfig = {
comments: {
lineComment: '//',
blockComment: ['/*', '*/']
@ -19,7 +19,7 @@ export const conf = {
]
}
export const language = {
export const solidityTokensProvider = {
defaultToken: '',
tokenPostfix: '.sol',

@ -0,0 +1,144 @@
/* eslint-disable */
export const zokratesLanguageConfig = {
comments: {
lineComment: '//',
blockComment: ['/*', '*/']
},
brackets: [
['{', '}'],
['[', ']'],
['(', ')'],
['<', '>']
],
autoClosingPairs: [
{ open: '"', close: '"', notIn: ['string', 'comment'] },
{ open: '{', close: '}', notIn: ['string', 'comment'] },
{ open: '[', close: ']', notIn: ['string', 'comment'] },
{ open: '(', close: ')', notIn: ['string', 'comment'] },
{ open: '<', close: '>', notIn: ['string', 'comment'] }
]
}
export const zokratesTokensProvider = {
defaultToken: "",
tokenPostfix: ".zok",
keywords: [
"log",
"assert",
"as",
"bool",
"const",
"def",
"else",
"false",
"field",
"for",
"if",
"import",
"from",
"in",
"mut",
"private",
"public",
"return",
"struct",
"true",
"type",
"u8",
"u16",
"u32",
"u64",
],
typeKeywords: ["bool", "field", "u8", "u16", "u32", "u64"],
operators: [
"=",
">",
"<",
"!",
"?",
":",
"==",
"<=",
">=",
"!=",
"&&",
"||",
"+",
"-",
"*",
"**",
"/",
"&",
"|",
"^",
"%",
"<<",
">>",
],
decimalSuffix: /(u16|u32|u64|u8|f)?/,
// we include these common regular expressions
symbols: /[=><!~?:&|+\-*\/\^%]+/,
escapes:
/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
// The main tokenizer for our languages
tokenizer: {
root: [
// identifiers and keywords
[
/[a-zA-Z]\w*/,
{
cases: {
"@typeKeywords": "type.identifier",
"@keywords": "keyword",
"@default": "identifier",
},
},
],
// whitespace
{ include: "@whitespace" },
// delimiters and operators
[/[{}()\[\]]/, "@brackets"],
[/[<>](?!@symbols)/, "@brackets"],
[/@symbols/, { cases: { "@operators": "operator", "@default": "" } }],
// numbers
[/0[xX][0-9a-fA-F]+/, "number.hex"],
[/\d+(@decimalSuffix)/, "number"],
// delimiter
[/[;,.]/, "delimiter"],
// strings
[/"([^"\\]|\\.)*$/, "string.invalid"], // non-teminated string
[/"/, { token: "string.quote", bracket: "@open", next: "@string" }],
],
comment: [
[/[^\/*]+/, "comment"],
[/\/\*/, "comment", "@push"], // nested comment
["\\*/", "comment", "@pop"],
[/[\/*]/, "comment"],
],
string: [
[/[^\\"]+/, "string"],
[/@escapes/, "string.escape"],
[/\\./, "string.escape.invalid"],
[/"/, { token: "string.quote", bracket: "@close", next: "@pop" }],
],
whitespace: [
[/[ \t\r\n]+/, "white"],
[/\/\*/, "comment", "@comment"],
[/\/\/.*$/, "comment"],
],
},
}

@ -237,7 +237,7 @@ export const RemixUiHomeTab = (props: RemixUiHomeTabProps) => {
<div>
<i className="pl-4 text-danger fas fa-exclamation-triangle"></i>
<span className="px-2 remixui_home_text text-danger mt-4 pt-4">
Scam Alert: Beware of online videos promoting "liquidity front runner bots".
Scam Alert: There are video tutorials going around that provide urls other than remix.ethereum.org, and could be scams. Also, beware of online videos promoting "liquidity front runner bots".
</span>
<a className="remixui_home_text" target="__blank" href="https://medium.com/remix-ide/remix-in-youtube-crypto-scams-71c338da32d">Learn more</a>
</div>

@ -25,22 +25,23 @@ export function RecorderUI (props: RecorderProps) {
setToggleExpander(!toggleExpander)
}
return (
<div className="udapp_cardContainer list-group-item border border-bottom">
<div className="udapp_recorderSection d-flex justify-content-between" onClick={toggleClass}>
<div className="d-flex">
<div className="d-flex justify-content-center align-items-center">
<label className="mt-1 udapp_recorderSectionLabel">Transactions recorded</label>
<div className="ml-2 mb-2 badge badge-pill badge-primary" title="The number of recorded transactions">{props.count}</div>
<div className="ml-2 badge badge-pill badge-primary text-center" title="The number of recorded transactions">{props.count}</div>
<OverlayTrigger placement={'right'} overlay={
<Tooltip className="text-nowrap" id="info-recorder">
<span>Save transactions (deployed contracts and function executions) and replay them in another environment. <br/> e.g Transactions created in Remix VM can be replayed in the Injected Provider.
</span>
</Tooltip>
}>
<i style={{ fontSize: 'medium' }} className={'ml-2 fal fa-info-circle'} aria-hidden="true"></i>
<i style={{ fontSize: 'medium' }} className={'ml-2 fal fa-info-circle align-self-center'} aria-hidden="true"></i>
</OverlayTrigger>
</div>
<div>
<div className="p-3">
<span data-id='udappRecorderTitleExpander' onClick={toggleClass}>
<i className={!toggleExpander ? 'fas fa-angle-right' : 'fas fa-angle-down'} aria-hidden="true"></i>
</span>
@ -56,7 +57,7 @@ export function RecorderUI (props: RecorderProps) {
}>
<label className="form-check-label custom-control-label" data-id="runtabLivemodeInput" htmlFor="livemode-recorder">Run transactions using the latest compilation result</label>
</OverlayTrigger>
</div>
</div>
<div className="mb-1 mt-1 udapp_transactionActions">
<OverlayTrigger placement={'right'} overlay={
<Tooltip className="text-nowrap" id="tooltip-save-recorder">
@ -72,7 +73,7 @@ export function RecorderUI (props: RecorderProps) {
}>
<button className="btn btn-sm btn-info runtransaction udapp_runTxs" data-id="runtransaction" title={enableRunButton ? 'No scenario file selected' : ''} disabled={enableRunButton} onClick={handleClickRunButton}>Run</button>
</OverlayTrigger>
</div>
</div>
</div>
</div>
)

@ -338,8 +338,10 @@ export const SearchProvider = ({
async function fetchWorkspace() {
try {
const workspace = await plugin.call('filePanel', 'getCurrentWorkspace')
if (workspace) value.setCurrentWorkspace(workspace.name)
setFiles(await getDirectory('/', plugin))
if (workspace) {
value.setCurrentWorkspace(workspace.name)
setFiles(await getDirectory('/', plugin))
}
} catch (e) {
console.log(e)
}

@ -51,7 +51,7 @@ export function GithubSettings (props: GithubSettingsProps) {
<p className="">Go to github token page (link below) to create a new token and save it in Remix. Make sure this token has only \'create gist\' permission.</p>
<p className="mb-1"><a className="text-primary" target="_blank" href="https://github.com/settings/tokens">https://github.com/settings/tokens</a></p>
<div>
<label>TOKEN:</label>
<label className="mb-0 pb-0">TOKEN:</label>
<div className="input-group text-secondary mb-0 h6">
<input id="gistaccesstoken" data-id="settingsTabGistAccessToken" type="password" className="form-control" onChange={(e) => handleChangeTokenState(e)} value={ githubToken } />
<div className="input-group-append">
@ -60,13 +60,13 @@ export function GithubSettings (props: GithubSettingsProps) {
</div>
</div>
<div>
<label>USERNAME:</label>
<label className="pt-2 mb-0 pb-0">USERNAME:</label>
<div className="text-secondary mb-0 h6">
<input id="githubusername" data-id="settingsTabGithubUsername" type="text" className="form-control" onChange={(e) => handleChangeUserNameState(e)} value={ githubUserName } />
</div>
</div>
<div>
<label>EMAIL:</label>
<label className="pt-2 mb-0 pb-0">EMAIL:</label>
<div className="text-secondary mb-0 h6">
<input id="githubemail" data-id="settingsTabGithubEmail" type="text" className="form-control" onChange={(e) => handleChangeEmailState(e)} value={ githubEmail } />
<div className="d-flex justify-content-end pt-2">

@ -248,12 +248,12 @@ export const RemixUiSettings = (props: RemixUiSettingsProps) => {
<div className="border-top">
<div className="card-body pt-3 pb-2">
<h6 className="card-title">{ swarmSettingsTitle }</h6>
<div className="pt-2 mb-1"><label>PRIVATE BEE ADDRESS:</label>
<div className="pt-2 pt-2 mb-0 pb-0"><label>PRIVATE BEE ADDRESS:</label>
<div className="text-secondary mb-0 h6">
<input id="swarmprivatebeeaddress" data-id="settingsPrivateBeeAddress" className="form-control" onChange={handleSavePrivateBeeAddress} value={ privateBeeAddress } />
</div>
</div>
<div className=""><label>POSTAGE STAMP ID:</label>
<div className="pt-2 mb-0 pb-0"><label>POSTAGE STAMP ID:</label>
<div className="text-secondary mb-0 h6">
<input id="swarmpostagestamp" data-id="settingsPostageStampId" className="form-control" onChange={handleSavePostageStampId} value={ postageStampId } />
<div className="d-flex justify-content-end pt-2">
@ -312,27 +312,27 @@ export const RemixUiSettings = (props: RemixUiSettingsProps) => {
<div className="border-top">
<div className="card-body pt-3 pb-2">
<h6 className="card-title">{ ipfsSettingsText }</h6>
<div className="pt-2 mb-1"><label>IPFS HOST:</label>
<div className="pt-2 mb-0"><label>IPFS HOST:</label>
<div className="text-secondary mb-0 h6">
<input placeholder='e.g. ipfs.infura.io' id="settingsIpfsUrl" data-id="settingsIpfsUrl" className="form-control" onChange={handleSaveIpfsUrl} value={ ipfsUrl } />
</div>
</div>
<div className=""><label>IPFS PROTOCOL:</label>
<div className="pt-2 mb-0 pb-0"><label>IPFS PROTOCOL:</label>
<div className="text-secondary mb-0 h6">
<input placeholder='e.g. https' id="settingsIpfsProtocol" data-id="settingsIpfsProtocol" className="form-control" onChange={handleSaveIpfsProtocol} value={ ipfsProtocol } />
</div>
</div>
<div className=""><label>IPFS PORT:</label>
<div className="pt-2 mb-0 pb-0"><label>IPFS PORT:</label>
<div className="text-secondary mb-0 h6">
<input placeholder='e.g. 5001' id="settingsIpfsPort" data-id="settingsIpfsPort" className="form-control" onChange={handleSaveIpfsPort} value={ ipfsPort } />
</div>
</div>
<div className=""><label>IPFS PROJECT ID [ INFURA ]:</label>
<div className="pt-2 mb-0 pb-0"><label>IPFS PROJECT ID [ INFURA ]:</label>
<div className="text-secondary mb-0 h6">
<input id="settingsIpfsProjectId" data-id="settingsIpfsProjectId" className="form-control" onChange={handleSaveIpfsProjectId} value={ ipfsProjectId } />
</div>
</div>
<div className=""><label>IPFS PROJECT SECRET [ INFURA ]:</label>
<div className="pt-2 mb-0 pb-0"><label>IPFS PROJECT SECRET [ INFURA ]:</label>
<div className="text-secondary mb-0 h6">
<input id="settingsIpfsProjectSecret" data-id="settingsIpfsProjectSecret" className="form-control" type="password" onChange={handleSaveIpfsSecret} value={ ipfsProjectSecret } />
</div>

@ -1,4 +1,5 @@
import React, { useState, useRef, useEffect, ReactElement } from 'react' // eslint-disable-line
import * as semver from 'semver'
import { eachOfSeries } from 'async' // eslint-disable-line
import type Web3 from 'web3'
import { canUseWorker, urlFromVersion } from '@remix-project/remix-solidity'
@ -154,8 +155,23 @@ export const SolidityUnitTesting = (props: Record<string, any>) => { // eslint-d
await setCurrentPath(defaultPath)
})
const truncateVersion = (version: string) => {
const tmp: RegExpExecArray | null = /^(\d+.\d+.\d+)/.exec(version)
return tmp ? tmp[1] : version
}
testTab.fileManager.events.on('noFileSelected', async () => { await updateForNewCurrent() })
testTab.fileManager.events.on('currentFileChanged', async (file: string) => await updateForNewCurrent(file))
testTab.fileManager.events.on('currentFileChanged', async (file: string) => {
await updateForNewCurrent(file)
})
testTab.on('solidity', 'compilerLoaded', async (version: string) => {
const { currentVersion } = testTab.compileTab.getCurrentCompilerConfig()
if (!semver.gt(truncateVersion(currentVersion), '0.4.12')) {
setDisableRunButton(true)
setRunButtonTitle('Please select Solidity compiler version greater than 0.4.12.')
}
})
}, []) // eslint-disable-line

@ -3,16 +3,20 @@ import React from 'react' //eslint-disable-line
interface StaticAnalyserButtonProps {
onClick: (event) => void
buttonText: string,
disabled?: boolean
disabled?: boolean,
title?: string
}
const StaticAnalyserButton = ({
onClick,
buttonText,
disabled
disabled,
title
}: StaticAnalyserButtonProps) => {
let classList = "btn btn-sm w-25 btn-primary"
classList += disabled ? " disabled" : ""
return (
<button className="btn btn-sm w-25 btn-primary" onClick={onClick} disabled={disabled}>
<button className={classList} disabled={disabled} title={title} onClick={onClick}>
{buttonText}
</button>
)

@ -2,6 +2,7 @@ import React, { useEffect, useState, useReducer, useRef } from 'react' // eslint
import Button from './Button/StaticAnalyserButton' // eslint-disable-line
import { util } from '@remix-project/remix-lib'
import _ from 'lodash'
import * as semver from 'semver'
import { TreeView, TreeViewItem } from '@remix-ui/tree-view' // eslint-disable-line
import { RemixUiCheckbox } from '@remix-ui/checkbox' // eslint-disable-line
import ErrorRenderer from './ErrorRenderer' // eslint-disable-line
@ -64,14 +65,30 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => {
const [autoRun, setAutoRun] = useState(true)
const [slitherEnabled, setSlitherEnabled] = useState(false)
const [showSlither, setShowSlither] = useState(false)
const [isSupportedVersion, setIsSupportedVersion] = useState(false)
let [showLibsWarning, setShowLibsWarning] = useState(false) // eslint-disable-line prefer-const
const [categoryIndex, setCategoryIndex] = useState(groupedModuleIndex(groupedModules))
const [warningState, setWarningState] = useState({})
const [runButtonTitle, setRunButtonTitle] = useState<string>('Run Static Analysis')
const warningContainer = useRef(null)
const allWarnings = useRef({})
const [state, dispatch] = useReducer(analysisReducer, initialState)
const setDisableForRun = (version: string) => {
const truncateVersion = (version: string) => {
const tmp: RegExpExecArray | null = /^(\d+.\d+.\d+)/.exec(version)
return tmp ? tmp[1] : version
}
if (version != '' && !semver.gt(truncateVersion(version), '0.4.12')) {
setIsSupportedVersion(false)
setRunButtonTitle('Sselect Solidity compiler version greater than 0.4.12.')
} else {
setIsSupportedVersion(true)
setRunButtonTitle('Run static analysis')
}
}
useEffect(() => {
compilation(props.analysisModule, dispatch)
}, [props])
@ -91,6 +108,10 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => {
return () => { }
}, [state])
useEffect(() => {
props.analysisModule.call('solidity', 'getCompilerState').then((compilerState) => setDisableForRun(compilerState.currentVersion))
}, [])
useEffect(() => {
props.analysisModule.on('filePanel', 'setWorkspace', (currentWorkspace) => {
// Reset warning state
@ -119,20 +140,24 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => {
setSlitherEnabled(false)
}
})
props.analysisModule.on('solidity', 'compilerLoaded', async (version: string) => {
setDisableForRun(version)
})
return () => { }
}, [props])
const message = (name, warning, more, fileName, locationString) : string => {
return (`
<span className='d-flex flex-column'>
<span className='h6 font-weight-bold'>${name}</span>
${warning}
${more
? (<span><a href={more} target='_blank'>more</a></span>)
: (<span> </span>)
}
<span className="" title={Position in ${fileName}}>Pos: ${locationString}</span>
</span>`
<span className='d-flex flex-column'>
<span className='h6 font-weight-bold'>${name}</span>
${warning}
${more
? (<span><a href={more} target='_blank'>more</a></span>)
: (<span> </span>)
}
<span className="" title={Position in ${fileName}}>Pos: ${locationString}</span>
</span>`
)
}
@ -183,6 +208,7 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => {
}
const run = async (lastCompilationResult, lastCompilationSource, currentFile) => {
if (!isSupportedVersion) return
if (state.data !== null) {
if (lastCompilationResult && (categoryIndex.length > 0 || slitherEnabled)) {
const warningMessage = []
@ -474,7 +500,12 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => {
label="Autorun"
onChange={() => {}}
/>
<Button buttonText="Run" onClick={async () => await run(state.data, state.source, state.file)} disabled={(state.data === null || categoryIndex.length === 0) && !slitherEnabled }/>
<Button
buttonText="Run"
title={runButtonTitle}
onClick={async () => await run(state.data, state.source, state.file)}
disabled={(state.data === null || categoryIndex.length === 0) && !slitherEnabled || !isSupportedVersion }
/>
</div>
{ showSlither &&
<div className="d-flex mt-2" id="enableSlitherAnalysis">
@ -520,15 +551,15 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => {
{Object.entries(warningState).length > 0 &&
<div id='staticanalysisresult' >
<RemixUiCheckbox
id="showLibWarnings"
name="showLibWarnings"
categoryId="showLibWarnings"
title="when checked, the results are also displayed for external contract libraries"
inputType="checkbox"
checked={showLibsWarning}
label="Show warnings for external libraries"
onClick={handleShowLibsWarning}
onChange={() => {}}
id="showLibWarnings"
name="showLibWarnings"
categoryId="showLibWarnings"
title="when checked, the results are also displayed for external contract libraries"
inputType="checkbox"
checked={showLibsWarning}
label="Show warnings for external libraries"
onClick={handleShowLibsWarning}
onChange={() => {}}
/>
<br/>
<div className="mb-4">
@ -541,7 +572,6 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => {
<div data-id={`staticAnalysisModule${x.warningModuleName}${i}`} id={`staticAnalysisModule${x.warningModuleName}${i}`} key={i}>
<ErrorRenderer name={`staticAnalysisModule${x.warningModuleName}${i}`} message={x.msg} opt={x.options} warningErrors={ x.warningErrors} editor={props.analysisModule}/>
</div>
) : null
))}
</div>

@ -543,17 +543,25 @@ export const RemixUiTerminal = (props: RemixUiTerminalProps) => {
})
} else if (Array.isArray(x.message)) {
return x.message.map((msg, i) => {
if (!msg) msg = 'null'
if (React.isValidElement(msg)) {
return (
<div className="px-4 block" data-id="block" key={i}><span className={x.style}>{ msg }</span></div>
)
} else if (typeof msg === 'object') {
let stringified
try {
stringified = JSON.stringify(msg)
} catch (e) {
console.error(e)
stringified = '< value not displayable >'
}
return (
<div className={classNameBlock} data-id="block" key={i}><span className={x.style}>{ msg.value && typeof msg.value !== 'object' ? parse(msg.value) : JSON.stringify(msg) } </span></div>
<div className={classNameBlock} data-id="block" key={i}><span className={x.style}>{ stringified } </span></div>
)
} else {
return (
<div className={classNameBlock} data-id="block" key={i}><span className={x.style}>{msg? msg.toString() : null}</span></div>
<div className={classNameBlock} data-id="block" key={i}><span className={x.style}>{msg ? msg.toString() : null}</span></div>
)
}
})

@ -4,7 +4,7 @@ import Gists from 'gists'
import { customAction } from '@remixproject/plugin-api/lib/file-system/file-panel/type'
import { displayNotification, displayPopUp, fetchDirectoryError, fetchDirectoryRequest, fetchDirectorySuccess, focusElement, fsInitializationCompleted, hidePopUp, removeInputFieldSuccess, setCurrentWorkspace, setExpandPath, setMode, setWorkspaces } from './payload'
import { listenOnPluginEvents, listenOnProviderEvents } from './events'
import { createWorkspaceTemplate, getWorkspaces, loadWorkspacePreset, setPlugin } from './workspace'
import { createWorkspaceTemplate, getWorkspaces, loadWorkspacePreset, setPlugin, workspaceExists } from './workspace'
import { QueryParams } from '@remix-project/remix-lib'
import { fetchContractFromEtherscan } from '@remix-project/core-plugin' // eslint-disable-line
import JSZip from 'jszip'
@ -80,11 +80,13 @@ export const initWorkspace = (filePanelPlugin) => async (reducerDispatch: React.
{id: 5, name: 'goerli'}
]
let found = false
const workspaceName = 'etherscan-code-sample'
let filePath
const foundOnNetworks = []
for (const network of networks) {
const target = `/${network.name}/${contractAddress}`
try {
data = await fetchContractFromEtherscan(plugin, network, contractAddress, target, etherscanKey)
data = await fetchContractFromEtherscan(plugin, network, contractAddress, target, false, etherscanKey)
} catch (error) {
if ((error.message.startsWith('contract not verified on Etherscan') || error.message.startsWith('unable to retrieve contract data')) && network.id !== 5)
continue
@ -95,15 +97,15 @@ export const initWorkspace = (filePanelPlugin) => async (reducerDispatch: React.
}
found = true
foundOnNetworks.push(network.name)
await createWorkspaceTemplate('etherscan-code-sample', 'code-template')
plugin.setWorkspace({ name: 'etherscan-code-sample', isLocalhost: false })
dispatch(setCurrentWorkspace({ name: 'etherscan-code-sample', isGitRepo: false }))
let filePath
if (await workspaceExists(workspaceName)) workspaceProvider.setWorkspace(workspaceName)
else await createWorkspaceTemplate(workspaceName, 'code-template')
plugin.setWorkspace({ name: workspaceName, isLocalhost: false })
dispatch(setCurrentWorkspace({ name: workspaceName, isGitRepo: false }))
count = count + (Object.keys(data.compilationTargets)).length
for (filePath in data.compilationTargets)
await workspaceProvider.set(filePath, data.compilationTargets[filePath]['content'])
plugin.on('editor', 'editorMounted', async () => await plugin.fileManager.openFile(filePath))
}
plugin.on('editor', 'editorMounted', async () => await plugin.fileManager.openFile(filePath))
plugin.call('notification', 'toast', `Added ${count} verified contract${count === 1 ? '': 's'} from ${foundOnNetworks.join(',')} network${foundOnNetworks.length === 1 ? '': 's'} of Etherscan for contract address ${contractAddress} !!`)
} catch (error) {
await basicWorkspaceInit(workspaces, workspaceProvider)

@ -153,7 +153,7 @@
"@ethereumjs/vm": "^5.5.3",
"@ethersphere/bee-js": "^3.2.0",
"@isomorphic-git/lightning-fs": "^4.4.1",
"@monaco-editor/react": "^4.3.1",
"@monaco-editor/react": "4.4.5",
"@remixproject/engine": "^0.3.31",
"@remixproject/engine-web": "^0.3.31",
"@remixproject/plugin": "^0.3.31",
@ -161,6 +161,7 @@
"@remixproject/plugin-utils": "^0.3.31",
"@remixproject/plugin-webview": "^0.3.31",
"@remixproject/plugin-ws": "^0.3.31",
"@types/nightwatch": "^2.3.1",
"ansi-gray": "^0.1.1",
"async": "^2.6.2",
"axios": ">=0.26.0",
@ -210,7 +211,7 @@
"time-stamp": "^2.2.0",
"ts-loader": "^9.2.6",
"tslib": "^2.3.0",
"web3": "^1.5.1",
"web3": "^1.7.5",
"winston": "^3.3.3",
"ws": "^7.3.0"
},
@ -245,13 +246,13 @@
"@types/jest": "^27.0.2",
"@types/lodash": "^4.14.172",
"@types/mocha": "^7.0.2",
"@types/nightwatch": "1.3.4",
"@types/node": "~8.9.4",
"@types/react": "^17.0.24",
"@types/react-beautiful-dnd": "^13.1.2",
"@types/react-dom": "^17.0.9",
"@types/react-router-dom": "^5.3.0",
"@types/request": "^2.48.7",
"@types/semver": "^7.3.10",
"@types/tape": "^4.13.0",
"@types/ws": "^7.2.4",
"@typescript-eslint/eslint-plugin": "^4.32.0",
@ -307,7 +308,7 @@
"mkdirp": "^0.5.1",
"mocha": "^8.0.1",
"nanohtml": "^1.6.3",
"nightwatch": "^1.7.11",
"nightwatch": "^2.3",
"nodemon": "^2.0.4",
"notify-error": "^1.2.0",
"npm-link-local": "^1.1.0",

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save