Merge pull request #866 from ethereum/open-save-workspace

open save workspace
pull/831/head^2
yann300 4 years ago committed by GitHub
commit 332ef9b93c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 12
      apps/remix-ide-e2e/src/commands/addFile.ts
  2. 36
      apps/remix-ide-e2e/src/commands/getLastTransactionHash.ts
  3. 13
      apps/remix-ide-e2e/src/commands/removeFile.ts
  4. 2
      apps/remix-ide-e2e/src/commands/renamePath.ts
  5. 95
      apps/remix-ide-e2e/src/commands/testFunction.ts
  6. 12
      apps/remix-ide-e2e/src/tests/ballot.test.ts
  7. 14
      apps/remix-ide-e2e/src/tests/ballot_0_4_11.test.ts
  8. 7
      apps/remix-ide-e2e/src/tests/compiler_api.test.ts
  9. 22
      apps/remix-ide-e2e/src/tests/debugger.test.ts
  10. 24
      apps/remix-ide-e2e/src/tests/defaultLayout.test.ts
  11. 33
      apps/remix-ide-e2e/src/tests/editor.test.ts
  12. 60
      apps/remix-ide-e2e/src/tests/fileExplorer.test.ts
  13. 48
      apps/remix-ide-e2e/src/tests/fileManager_api.test.ts
  14. 8
      apps/remix-ide-e2e/src/tests/generalSettings.test.ts
  15. 37
      apps/remix-ide-e2e/src/tests/gist.test.ts
  16. 14
      apps/remix-ide-e2e/src/tests/libraryDeployment.test.ts
  17. 2
      apps/remix-ide-e2e/src/tests/pluginManager.test.ts
  18. 12
      apps/remix-ide-e2e/src/tests/publishContract.test.ts
  19. 13
      apps/remix-ide-e2e/src/tests/recorder.test.ts
  20. 70
      apps/remix-ide-e2e/src/tests/remixd.test.ts
  21. 18
      apps/remix-ide-e2e/src/tests/runAndDeploy.ts
  22. 6
      apps/remix-ide-e2e/src/tests/signingMessage.test.ts
  23. 52
      apps/remix-ide-e2e/src/tests/solidityImport.test.ts
  24. 66
      apps/remix-ide-e2e/src/tests/solidityUnittests.test.ts
  25. 24
      apps/remix-ide-e2e/src/tests/specialFunctions.test.ts
  26. 4
      apps/remix-ide-e2e/src/tests/staticAnalysis.test.ts
  27. 28
      apps/remix-ide-e2e/src/tests/terminal.test.ts
  28. 37
      apps/remix-ide-e2e/src/tests/transactionExecution.test.ts
  29. 14
      apps/remix-ide-e2e/src/tests/txListener.test.ts
  30. 2
      apps/remix-ide-e2e/src/tests/url.test.ts
  31. 4
      apps/remix-ide-e2e/src/tests/usingWebWorker.test.ts
  32. 22
      apps/remix-ide-e2e/src/tests/workspace.test.ts
  33. 1
      apps/remix-ide-e2e/src/types/index.d.ts
  34. 1
      apps/remix-ide/.gitignore
  35. 1
      apps/remix-ide/contracts/README.txt
  36. 33
      apps/remix-ide/src/app.js
  37. 7
      apps/remix-ide/src/app/compiler/compiler-imports.js
  38. 1
      apps/remix-ide/src/app/editor/editor.js
  39. 13
      apps/remix-ide/src/app/files/compiler-metadata.js
  40. 4
      apps/remix-ide/src/app/files/file-explorer.js
  41. 48
      apps/remix-ide/src/app/files/fileManager.js
  42. 36
      apps/remix-ide/src/app/files/fileProvider.js
  43. 22
      apps/remix-ide/src/app/files/remixDProvider.js
  44. 2
      apps/remix-ide/src/app/files/remixd-handle.js
  45. 45
      apps/remix-ide/src/app/files/workspaceFileProvider.js
  46. 226
      apps/remix-ide/src/app/panels/file-panel.js
  47. 3
      apps/remix-ide/src/app/panels/styles/file-panel-styles.css
  48. 1
      apps/remix-ide/src/app/tabs/compile-tab.js
  49. 15
      apps/remix-ide/src/app/tabs/test-tab.js
  50. 2
      apps/remix-ide/src/app/tabs/testTab/testTab.js
  51. 18
      apps/remix-ide/src/config.js
  52. 11
      apps/remix-ide/src/lib/gist-handler.js
  53. 5
      apps/remix-ide/src/lib/helper.js
  54. 29
      apps/remix-ide/src/migrateFileSystem.js
  55. 7
      apps/remix-ide/src/remixAppManager.js
  56. 1
      libs/remix-debug/src/debugger/debugger.ts
  57. 2
      libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx
  58. 37
      libs/remix-ui/file-explorer/src/lib/file-explorer.tsx

@ -16,15 +16,13 @@ class AddFile extends EventEmitter {
function addFile (browser: NightwatchBrowser, name: string, content: NightwatchContractContent, done: VoidFunction) {
browser.clickLaunchIcon('udapp')
.clickLaunchIcon('fileExplorers')
.click('li[data-id="treeViewLitreeViewItembrowser/README.txt"]') // focus on root directory
.click('li[data-id="treeViewLitreeViewItemREADME.txt"]') // focus on root directory
.click('.newFile')
.waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/blank"]')
// .scrollAndClick('*[data-id="treeViewLitreeViewItembrowser/blank"] .remixui_items')
.sendKeys('*[data-id="treeViewLitreeViewItembrowser/blank"] .remixui_items', name)
.sendKeys('*[data-id="treeViewLitreeViewItembrowser/blank"] .remixui_items', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItem/blank"]')
.sendKeys('*[data-id="treeViewLitreeViewItem/blank"] .remixui_items', name)
.sendKeys('*[data-id="treeViewLitreeViewItem/blank"] .remixui_items', browser.Keys.ENTER)
.pause(2000)
.waitForElementVisible(`li[data-id="treeViewLitreeViewItembrowser/${name}"]`)
// .click(`li[data-id="treeViewLitreeViewItembrowser/${name}"]`)
.waitForElementVisible(`li[data-id="treeViewLitreeViewItem${name}"]`)
.setEditorValue(content.content)
.pause(1000)
.perform(function () {

@ -0,0 +1,36 @@
import { NightwatchBrowser } from 'nightwatch'
import EventEmitter from 'events'
class GetLastTransactionHash extends EventEmitter {
command (this: NightwatchBrowser, cb: (hash: string) => void): NightwatchBrowser {
this.api.perform((done) => {
getLastTransactionHash(this.api, (hash) => {
cb(hash)
done()
this.emit('complete')
})
})
return this
}
}
function getLastTransactionHash (browser: NightwatchBrowser, callback: (hash: string) => void) {
browser.waitForElementPresent('*[data-shared="universalDappUiInstance"]')
.execute(function () {
const deployedContracts = document.querySelectorAll('*[data-id="terminalJournal"] > div')
for (let i = deployedContracts.length - 1; i >= 0; i--) {
const current = deployedContracts[i]
const attr = current.getAttribute('data-id')
if (attr && attr.replace('block_tx', '').startsWith('0x')) {
return attr.replace('block_tx', '')
}
}
return ''
}, [], function (result) {
const hash = typeof result.value === 'string' ? result.value : null
callback(hash)
})
}
module.exports = GetLastTransactionHash

@ -38,15 +38,10 @@ function removeFile (browser: NightwatchBrowser, path: string, done: VoidFunctio
.click('#menuitemdelete')
.pause(2000)
.perform(() => {
if (path.indexOf('browser') !== -1) {
browser.waitForElementVisible('[data-id="browser-modal-footer-ok-react"]')
.click('[data-id="browser-modal-footer-ok-react"]')
.waitForElementNotPresent('[data-path="' + path + '"]')
} else if (path.indexOf('localhost') !== -1) {
browser.waitForElementVisible('[data-id="localhost-modal-footer-ok-react"]')
.click('[data-id="localhost-modal-footer-ok-react"]')
.waitForElementNotPresent('[data-path="' + path + '"]')
}
console.log(path, 'to remove')
browser.waitForElementVisible('.modal-ok')
.click('.modal-ok')
.waitForElementNotPresent('[data-path="' + path + '"]')
done()
})
})

@ -42,7 +42,7 @@ function renamePath (browser: NightwatchBrowser, path: string, newFileName: stri
})
})
.pause(1000)
.click('li[data-id="treeViewLitreeViewItembrowser/README.txt"]') // focus on root directory
.click('div[data-id="remixIdeMainPanel"]') // focus out to save
.pause(2000)
.waitForElementNotPresent('[data-path="' + path + '"]')
.waitForElementPresent('[data-path="' + renamedPath + '"]')

@ -12,59 +12,68 @@ class TestFunction extends EventEmitter {
}
browser
.waitForElementVisible(`[data-id="block_tx${txHash}"]`)
.click(`[data-id="block_tx${txHash}"]`)
.waitForElementVisible(`*[data-id="txLoggerTable${txHash}"]`)
// 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]]
browser.elementIdText(jsonWebElementId, (jsonElement) => {
const key = typeof jsonElement.value === 'string' ? jsonElement.value.trim() : null
logs[key] = null
})
.perform((done) => {
browser.getLastTransactionHash((hash) => {
if (txHash === 'last') {
console.log(hash)
txHash = hash
}
done()
})
})
.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]]
.perform((done) => {
browser.waitForElementVisible(`[data-id="block_tx${txHash}"]`)
.click(`[data-id="block_tx${txHash}"]`)
.waitForElementVisible(`*[data-id="txLoggerTable${txHash}"]`)
// 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]]
browser.elementIdText(jsonWebElementId, (jsonElement) => {
let value = jsonElement.value
browser.elementIdText(jsonWebElementId, (jsonElement) => {
const key = typeof jsonElement.value === 'string' ? jsonElement.value.trim() : null
try {
value = JSON.parse(<string>jsonElement.value)
setLog(index, <string>value)
} catch (e) {
setLog(index, <string>value)
}
logs[key] = null
})
})
})
})
})
.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]]
browser.elementIdText(jsonWebElementId, (jsonElement) => {
let value = jsonElement.value
browser.perform(() => {
Object.keys(expectedValue).forEach(key => {
let equal = false
try {
value = JSON.parse(<string>jsonElement.value)
setLog(index, <string>value)
} catch (e) {
setLog(index, <string>value)
}
})
})
}).perform(() => done())
})
.perform(() => {
Object.keys(expectedValue).forEach(key => {
let equal = false
try {
const receivedValue = JSON.parse(logs[key])
try {
const receivedValue = JSON.parse(logs[key])
equal = deepequal(receivedValue, expectedValue[key])
} catch (err) {
equal = deepequal(logs[key], expectedValue[key])
}
equal = deepequal(receivedValue, expectedValue[key])
} catch (err) {
equal = deepequal(logs[key], expectedValue[key])
}
if (!equal) {
browser.assert.fail(`Expected ${JSON.stringify(expectedValue[key])} but got ${JSON.stringify(logs[key])}`)
} else {
browser.assert.ok(true, `Expected value matched returned value ${JSON.stringify(expectedValue[key])}`)
}
if (!equal) {
browser.assert.fail(`Expected ${JSON.stringify(expectedValue[key])} but got ${JSON.stringify(logs[key])}`)
} else {
browser.assert.ok(true, `Expected value matched returned value ${JSON.stringify(expectedValue[key])}`)
}
})
this.emit('complete')
})
this.emit('complete')
})
return this
}
}

@ -6,7 +6,7 @@ import sauce from './sauce'
import examples from '../examples/example-contracts'
const sources = [
{ 'browser/Untitled.sol': { content: examples.ballot.content } }
{ 'Untitled.sol': { content: examples.ballot.content } }
]
module.exports = {
@ -20,7 +20,7 @@ module.exports = {
browser
.waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000)
.clickLaunchIcon('solidity')
.testContracts('Untitled.sol', sources[0]['browser/Untitled.sol'], ['Ballot'])
.testContracts('Untitled.sol', sources[0]['Untitled.sol'], ['Ballot'])
.clickLaunchIcon('udapp')
.selectAccount('0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c')
.setValue('input[placeholder="bytes32[] proposalNames"]', '["0x48656c6c6f20576f726c64210000000000000000000000000000000000000000"]')
@ -28,10 +28,9 @@ module.exports = {
.waitForElementPresent('*[data-id="universalDappUiContractActionWrapper"]')
.click('*[data-id="universalDappUiTitleExpander"]')
.clickFunction('delegate - transact (not payable)', { types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"' })
.testFunction('0x41fab8ea5b1d9fba5e0a6545ca1a2d62fff518578802c033c2b9a031a01c31b3',
.testFunction('last',
{
status: 'true Transaction mined and execution succeed',
'transaction hash': '0x41fab8ea5b1d9fba5e0a6545ca1a2d62fff518578802c033c2b9a031a01c31b3',
'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' }
})
},
@ -61,10 +60,9 @@ module.exports = {
.waitForElementPresent('*[data-id="universalDappUiContractActionWrapper"]')
.click('*[data-id="universalDappUiTitleExpander"]')
.clickFunction('delegate - transact (not payable)', { types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"' })
.testFunction('0xca58080c8099429caeeffe43b8104df919c2c543dceb9edf9242fa55f045c803',
.testFunction('last',
{
status: 'false Transaction mined but execution failed',
'transaction hash': '0xca58080c8099429caeeffe43b8104df919c2c543dceb9edf9242fa55f045c803',
'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' }
})
},
@ -74,7 +72,7 @@ module.exports = {
.click('*[data-id="settingsWeb3Mode"]')
.modalFooterOKClick()
.clickLaunchIcon('solidity')
.testContracts('Untitled.sol', sources[0]['browser/Untitled.sol'], ['Ballot'])
.testContracts('Untitled.sol', sources[0]['Untitled.sol'], ['Ballot'])
.clickLaunchIcon('udapp')
.setValue('input[placeholder="bytes32[] proposalNames"]', '["0x48656c6c6f20576f726c64210000000000000000000000000000000000000000"]')
.click('*[data-id="Deploy - transact (not payable)"]')

@ -6,7 +6,7 @@ import sauce from './sauce'
import examples from '../examples/example-contracts'
const sources = [
{ 'browser/Untitled.sol': { content: examples.ballot_0_4_11.content } }
{ 'Untitled.sol': { content: examples.ballot_0_4_11.content } }
]
module.exports = {
@ -24,12 +24,12 @@ module.exports = {
.waitForElementVisible('[for="autoCompile"]')
.click('[for="autoCompile"]')
.verify.elementPresent('[data-id="compilerContainerAutoCompile"]:checked')
.testContracts('Untitled.sol', sources[0]['browser/Untitled.sol'], ['Ballot'])
.testContracts('Untitled.sol', sources[0]['Untitled.sol'], ['Ballot'])
},
'Deploy Ballot': function (browser: NightwatchBrowser) {
browser.pause(500)
.testContracts('Untitled.sol', sources[0]['browser/Untitled.sol'], ['Ballot'])
.testContracts('Untitled.sol', sources[0]['Untitled.sol'], ['Ballot'])
.clickLaunchIcon('udapp')
.selectAccount('0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c')
.setValue('input[placeholder="uint8 _numProposals"]', '2')
@ -37,10 +37,9 @@ module.exports = {
.waitForElementPresent('*[data-id="universalDappUiContractActionWrapper"]')
.click('*[data-id="universalDappUiTitleExpander"]')
.clickFunction('delegate - transact (not payable)', { types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"' })
.testFunction('0x41fab8ea5b1d9fba5e0a6545ca1a2d62fff518578802c033c2b9a031a01c31b3',
.testFunction('last',
{
status: 'true Transaction mined and execution succeed',
'transaction hash': '0x41fab8ea5b1d9fba5e0a6545ca1a2d62fff518578802c033c2b9a031a01c31b3',
'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' }
})
},
@ -69,10 +68,9 @@ module.exports = {
.waitForElementPresent('*[data-id="universalDappUiContractActionWrapper"]')
.click('*[data-id="universalDappUiTitleExpander"]')
.clickFunction('delegate - transact (not payable)', { types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"' })
.testFunction('0xca58080c8099429caeeffe43b8104df919c2c543dceb9edf9242fa55f045c803',
.testFunction('last',
{
status: 'true Transaction mined and execution succeed',
'transaction hash': '0xca58080c8099429caeeffe43b8104df919c2c543dceb9edf9242fa55f045c803',
'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' }
})
},
@ -82,7 +80,7 @@ module.exports = {
.click('*[data-id="settingsWeb3Mode"]')
.modalFooterOKClick()
.clickLaunchIcon('solidity')
.testContracts('Untitled.sol', sources[0]['browser/Untitled.sol'], ['Ballot'])
.testContracts('Untitled.sol', sources[0]['Untitled.sol'], ['Ballot'])
.clickLaunchIcon('udapp')
.setValue('input[placeholder="uint8 _numProposals"]', '2')
.click('*[data-id="Deploy - transact (not payable)"]')

@ -6,7 +6,7 @@ import sauce from './sauce'
import examples from '../examples/example-contracts'
const sources = [
{ 'browser/Untitled.sol': { content: examples.ballot.content } }
{ 'Untitled.sol': { content: examples.ballot.content } }
]
module.exports = {
@ -24,6 +24,7 @@ module.exports = {
.executeScript('remix.exeCurrent()')
.pause(5000)
.journalChildIncludes('"languageversion": "0.6.8+commit.0bbfe453"')
.click('*[data-id="terminalClearConsole"]')
},
'Should compile using "compileWithParamaters" API with optimization On': function (browser: NightwatchBrowser) {
@ -32,6 +33,7 @@ module.exports = {
.executeScript('remix.exeCurrent()')
.pause(10000)
.journalChildIncludes('\\"optimizer\\":{\\"enabled\\":true,\\"runs\\":300}')
.click('*[data-id="terminalClearConsole"]')
},
'Should compile using "compileWithParamaters" API with optimization off check default runs': function (browser: NightwatchBrowser) {
@ -40,6 +42,7 @@ module.exports = {
.executeScript('remix.exeCurrent()')
.pause(10000)
.journalChildIncludes('\\"optimizer\\":{\\"enabled\\":false,\\"runs\\":200}')
.click('*[data-id="terminalClearConsole"]')
},
'Should update the compiler configuration with "setCompilerConfig" API': function (browser: NightwatchBrowser) {
@ -55,7 +58,7 @@ module.exports = {
tearDown: sauce
}
const simpleContract = `pragma solidity >=0.4.22 <0.7.0;
const simpleContract = `pragma solidity >=0.4.22 <0.9.1;
/**
* @title Storage

@ -14,7 +14,7 @@ module.exports = {
},
'Should launch debugger': function (browser: NightwatchBrowser) {
browser.addFile('blah.sol', sources[0]['browser/blah.sol'])
browser.addFile('blah.sol', sources[0]['blah.sol'])
.clickLaunchIcon('udapp')
.waitForElementPresent('*[title="Deploy - transact (not payable)"]', 65000)
.click('*[title="Deploy - transact (not payable)"]')
@ -80,7 +80,7 @@ module.exports = {
'Should display solidity imported code while debugging github import': function (browser: NightwatchBrowser) {
browser
.clickLaunchIcon('solidity')
.testContracts('externalImport.sol', sources[1]['browser/externalImport.sol'], ['ERC20'])
.testContracts('externalImport.sol', sources[1]['externalImport.sol'], ['ERC20'])
.clickLaunchIcon('udapp')
.waitForElementPresent('*[title="Deploy - transact (not payable)"]', 35000)
.selectContract('ERC20')
@ -108,8 +108,8 @@ module.exports = {
.clickLaunchIcon('solidity')
.setSolidityCompilerVersion('soljson-v0.6.12+commit.27d51765.js')
.clickLaunchIcon('fileExplorers')
.click('li[data-id="treeViewLitreeViewItembrowser/externalImport.sol"')
.testContracts('withABIEncoderV2.sol', sources[2]['browser/withABIEncoderV2.sol'], ['test'])
.click('li[data-id="treeViewLitreeViewItemexternalImport.sol"')
.testContracts('withABIEncoderV2.sol', sources[2]['withABIEncoderV2.sol'], ['test'])
.clickLaunchIcon('udapp')
.selectContract('test')
.createContract('')
@ -142,7 +142,7 @@ module.exports = {
'Should load more solidity locals array': function (browser: NightwatchBrowser) {
browser
.clickLaunchIcon('solidity')
.testContracts('locals.sol', sources[3]['browser/locals.sol'], ['testLocals'])
.testContracts('locals.sol', sources[3]['locals.sol'], ['testLocals'])
.clickLaunchIcon('udapp')
.waitForElementPresent('*[title="Deploy - transact (not payable)"]', 40000)
.createContract('')
@ -167,7 +167,7 @@ module.exports = {
browser
.clickLaunchIcon('solidity')
.pause(2000)
.testContracts('withGeneratedSources.sol', sources[4]['browser/withGeneratedSources.sol'], ['A'])
.testContracts('withGeneratedSources.sol', sources[4]['withGeneratedSources.sol'], ['A'])
.clickLaunchIcon('udapp')
.createContract('')
.clickInstance(4)
@ -217,7 +217,7 @@ module.exports = {
const sources = [
{
'browser/blah.sol': {
'blah.sol': {
content: `
pragma solidity >=0.7.0 <0.9.0;
@ -250,10 +250,10 @@ const sources = [
}
},
{
'browser/externalImport.sol': { content: 'import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol"; contract test7 {}' }
'externalImport.sol': { content: 'import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol"; contract test7 {}' }
},
{
'browser/withABIEncoderV2.sol': {
'withABIEncoderV2.sol': {
content: `
pragma experimental ABIEncoderV2;
@ -277,7 +277,7 @@ const sources = [
}
},
{
'browser/locals.sol': {
'locals.sol': {
content: `
pragma solidity ^0.8.0;
contract testLocals {
@ -292,7 +292,7 @@ const sources = [
}
},
{
'browser/withGeneratedSources.sol': {
'withGeneratedSources.sol': {
content: `
// SPDX-License-Identifier: GPL-3.0
pragma experimental ABIEncoderV2;

@ -20,10 +20,10 @@ module.exports = {
browser.waitForElementVisible('div[data-id="remixIdeSidePanel"]')
.assert.containsText('h6[data-id="sidePanelSwapitTitle"]', 'FILE EXPLORERS')
.waitForElementVisible('div[data-id="filePanelFileExplorerTree"]')
.waitForElementVisible('[data-id="treeViewLitreeViewItembrowser/contracts"]')
.waitForElementVisible('[data-id="treeViewLitreeViewItembrowser/scripts"]')
.waitForElementVisible('[data-id="treeViewLitreeViewItembrowser/tests"]')
.waitForElementVisible('[data-id="treeViewLitreeViewItembrowser/README.txt"]')
.waitForElementVisible('[data-id="treeViewLitreeViewItemcontracts"]')
.waitForElementVisible('[data-id="treeViewLitreeViewItemscripts"]')
.waitForElementVisible('[data-id="treeViewLitreeViewItemtests"]')
.waitForElementVisible('[data-id="treeViewLitreeViewItemREADME.txt"]')
},
'Loads Main View': function (browser: NightwatchBrowser) {
@ -58,22 +58,12 @@ module.exports = {
.assert.visible('div[data-id="terminalContainerDisplay"]')
},
'Toggles File Explorer Browser': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('div[data-id="filePanelFileExplorerTree"]')
.waitForElementPresent('[data-id="treeViewLitreeViewItembrowser/contracts"]')
.click('[data-path="browser"]')
.waitForElementNotPresent('[data-id="treeViewLitreeViewItembrowser/contracts"]')
.click('[data-path="browser"]')
.waitForElementPresent('[data-id="treeViewLitreeViewItembrowser/contracts"]')
},
'Switch Tabs using tabs icon': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('div[data-id="filePanelFileExplorerTree"]')
.click('[data-id="treeViewLitreeViewItembrowser/contracts"]')
.openFile('browser/contracts/3_Ballot.sol')
.assert.containsText('div[title="browser/contracts/3_Ballot.sol"]', '3_Ballot.sol')
.click('[data-id="treeViewLitreeViewItemcontracts"]')
.openFile('contracts/3_Ballot.sol')
.assert.containsText('div[title="contracts/3_Ballot.sol"]', '3_Ballot.sol')
.click('span[class^=dropdownCaret]')
.click('#homeItem')
.assert.containsText('div[title="home"]', 'Home')

@ -14,7 +14,8 @@ module.exports = {
browser.waitForElementVisible('div[data-id="mainPanelPluginsContainer"]')
.clickLaunchIcon('fileExplorers')
.waitForElementVisible('div[data-id="filePanelFileExplorerTree"]')
.openFile('browser/contracts/1_Storage.sol')
.openFile('contracts')
.openFile('contracts/1_Storage.sol')
.waitForElementVisible('*[data-id="editorInput"]')
.checkElementStyle('*[data-id="editorInput"]', 'font-size', '12px')
.click('*[data-id="tabProxyZoomIn"]')
@ -89,7 +90,7 @@ module.exports = {
.addFile('sourcehighlight.js', sourcehighlightScript)
.addFile('removeSourcehighlightScript.js', removeSourcehighlightScript)
.addFile('removeAllSourcehighlightScript.js', removeAllSourcehighlightScript)
.openFile('browser/sourcehighlight.js')
.openFile('sourcehighlight.js')
.executeScript('remix.exeCurrent()')
.editorScroll('down', 60)
.waitForElementPresent('.highlightLine32')
@ -101,26 +102,26 @@ module.exports = {
},
'Should remove 1 highlight from source code': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('li[data-id="treeViewLitreeViewItembrowser/removeSourcehighlightScript.js"]')
.click('li[data-id="treeViewLitreeViewItembrowser/removeSourcehighlightScript.js"]')
browser.waitForElementVisible('li[data-id="treeViewLitreeViewItemremoveSourcehighlightScript.js"]')
.click('li[data-id="treeViewLitreeViewItemremoveSourcehighlightScript.js"]')
.pause(2000)
.executeScript('remix.exeCurrent()')
.waitForElementVisible('li[data-id="treeViewLitreeViewItembrowser/contracts"]')
.click('li[data-id="treeViewLitreeViewItembrowser/contracts"]')
.waitForElementVisible('li[data-id="treeViewLitreeViewItembrowser/contracts/3_Ballot.sol"]')
.click('li[data-id="treeViewLitreeViewItembrowser/contracts/3_Ballot.sol"]')
.waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts"]')
.click('li[data-id="treeViewLitreeViewItemcontracts"]')
.waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/3_Ballot.sol"]')
.click('li[data-id="treeViewLitreeViewItemcontracts/3_Ballot.sol"]')
.waitForElementNotPresent('.highlightLine32')
.checkElementStyle('.highlightLine40', 'background-color', 'rgb(8, 108, 181)')
.checkElementStyle('.highlightLine50', 'background-color', 'rgb(8, 108, 181)')
},
'Should remove all highlights from source code': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('li[data-id="treeViewLitreeViewItembrowser/removeAllSourcehighlightScript.js"]')
.click('li[data-id="treeViewLitreeViewItembrowser/removeAllSourcehighlightScript.js"]')
browser.waitForElementVisible('li[data-id="treeViewLitreeViewItemremoveAllSourcehighlightScript.js"]')
.click('li[data-id="treeViewLitreeViewItemremoveAllSourcehighlightScript.js"]')
.pause(2000)
.executeScript('remix.exeCurrent()')
.waitForElementVisible('li[data-id="treeViewLitreeViewItembrowser/contracts/3_Ballot.sol"]')
.click('li[data-id="treeViewLitreeViewItembrowser/contracts/3_Ballot.sol"]')
.waitForElementVisible('li[data-id="treeViewLitreeViewItemcontracts/3_Ballot.sol"]')
.click('li[data-id="treeViewLitreeViewItemcontracts/3_Ballot.sol"]')
.pause(2000)
.waitForElementNotPresent('.highlightLine32')
.waitForElementNotPresent('.highlightLine40')
@ -160,7 +161,7 @@ const sourcehighlightScript = {
column: 20
}
}
await remix.call('editor', 'highlight', pos, 'browser/contracts/3_Ballot.sol')
await remix.call('editor', 'highlight', pos, 'contracts/3_Ballot.sol')
const pos2 = {
start: {
@ -172,7 +173,7 @@ const sourcehighlightScript = {
column: 20
}
}
await remix.call('editor', 'highlight', pos2, 'browser/contracts/3_Ballot.sol')
await remix.call('editor', 'highlight', pos2, 'contracts/3_Ballot.sol')
const pos3 = {
start: {
@ -184,7 +185,7 @@ const sourcehighlightScript = {
column: 20
}
}
await remix.call('editor', 'highlight', pos3, 'browser/contracts/3_Ballot.sol')
await remix.call('editor', 'highlight', pos3, 'contracts/3_Ballot.sol')
} catch (e) {
console.log(e.message)
}
@ -196,7 +197,7 @@ const removeSourcehighlightScript = {
content: `
(async () => {
try {
await remix.call('editor', 'discardHighlightAt', 32, 'browser/contracts/3_Ballot.sol')
await remix.call('editor', 'discardHighlightAt', 32, 'contracts/3_Ballot.sol')
} catch (e) {
console.log(e.message)
}

@ -20,59 +20,63 @@ module.exports = {
browser.waitForElementVisible('div[data-id="remixIdeSidePanel"]')
.clickLaunchIcon('fileExplorers')
.assert.containsText('h6[data-id="sidePanelSwapitTitle"]', 'FILE EXPLORERS')
.click('li[data-id="treeViewLitreeViewItemREADME.txt"]') // focus on root directory
.click('*[data-id="fileExplorerNewFilecreateNewFile"]')
.pause(1000)
.waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/blank"]')
.sendKeys('*[data-id="treeViewLitreeViewItembrowser/blank"] .remixui_items', '5_New_contract.sol')
.sendKeys('*[data-id="treeViewLitreeViewItembrowser/blank"] .remixui_items', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/5_New_contract.sol"]', 7000)
.waitForElementVisible('*[data-id="treeViewLitreeViewItem/blank"]')
.sendKeys('*[data-id="treeViewLitreeViewItem/blank"] .remixui_items', '5_New_contract.sol')
.sendKeys('*[data-id="treeViewLitreeViewItem/blank"] .remixui_items', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItem5_New_contract.sol"]', 7000)
},
'Should rename `5_New_contract.sol` to 5_Renamed_Contract.sol': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/5_New_contract.sol"]')
.renamePath('browser/5_New_contract.sol', '5_Renamed_Contract.sol', 'browser/5_Renamed_Contract.sol')
.waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/5_Renamed_Contract.sol"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItem5_New_contract.sol"]')
.click('*[data-id="treeViewLitreeViewItem5_New_contract.sol"]')
.renamePath('5_New_contract.sol', '5_Renamed_Contract.sol', '5_Renamed_Contract.sol')
.waitForElementVisible('*[data-id="treeViewLitreeViewItem5_Renamed_Contract.sol"]')
},
'Should delete file `5_Renamed_Contract.sol` from file explorer': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/5_Renamed_Contract.sol"]')
.rightClick('[data-path="browser/5_Renamed_Contract.sol"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItem5_Renamed_Contract.sol"]')
.rightClick('[data-path="5_Renamed_Contract.sol"]')
.click('*[id="menuitemdelete"]')
.waitForElementVisible('*[data-id="browserModalDialogContainer-react"]')
.waitForElementVisible('*[data-id="default_workspaceModalDialogContainer-react"]')
.pause(2000)
.click('.modal-ok')
.waitForElementNotPresent('*[data-id="treeViewLitreeViewItembrowser/5_Renamed_Contract.sol"')
.waitForElementNotPresent('*[data-id="treeViewLitreeViewItem5_Renamed_Contract.sol"')
},
'Should create a new folder': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/README.txt"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemREADME.txt"]')
.click('li[data-id="treeViewLitreeViewItemREADME.txt"]') // focus on root directory
.click('[data-id="fileExplorerNewFilecreateNewFolder"]')
.pause(1000)
.waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/blank"]')
.sendKeys('*[data-id="treeViewLitreeViewItembrowser/blank"] .remixui_items', 'Browser_Tests')
.sendKeys('*[data-id="treeViewLitreeViewItembrowser/blank"] .remixui_items', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/Browser_Tests"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItem/blank"]')
.sendKeys('*[data-id="treeViewLitreeViewItem/blank"] .remixui_items', 'Browser_Tests')
.sendKeys('*[data-id="treeViewLitreeViewItem/blank"] .remixui_items', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemBrowser_Tests"]')
},
'Should rename Browser_Tests folder to Browser_E2E_Tests': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/Browser_Tests"]')
.renamePath('browser/Browser_Tests', 'Browser_E2E_Tests', 'browser/Browser_E2E_Tests')
.waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/Browser_E2E_Tests"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemBrowser_Tests"]')
.click('*[data-id="treeViewLitreeViewItemBrowser_Tests"]')
.renamePath('Browser_Tests', 'Browser_E2E_Tests', 'Browser_E2E_Tests')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemBrowser_E2E_Tests"]')
},
'Should delete Browser_E2E_Tests folder': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/Browser_E2E_Tests"]')
.rightClick('[data-path="browser/Browser_E2E_Tests"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemBrowser_E2E_Tests"]')
.rightClick('[data-path="Browser_E2E_Tests"]')
.click('*[id="menuitemdelete"]')
.waitForElementVisible('*[data-id="browserModalDialogContainer-react"]')
.waitForElementVisible('*[data-id="default_workspaceModalDialogContainer-react"]')
.pause(2000)
.click('.modal-ok')
.waitForElementNotPresent('*[data-id="treeViewLitreeViewItembrowser/Browser_E2E_Tests"]')
.waitForElementNotPresent('*[data-id="treeViewLitreeViewItemBrowser_E2E_Tests"]')
},
'Should publish all explorer files to github gist': function (browser: NightwatchBrowser) {
@ -82,11 +86,11 @@ module.exports = {
.pause(10000)
.waitForElementVisible('*[data-id="fileExplorerNewFilepublishToGist"]')
.click('*[data-id="fileExplorerNewFilepublishToGist"]')
.waitForElementVisible('*[data-id="browserModalDialogContainer-react"]')
.waitForElementVisible('*[data-id="default_workspaceModalDialogContainer-react"]')
.pause(2000)
.click('.modal-ok')
.pause(2000)
.waitForElementVisible('*[data-id="browserModalDialogContainer-react"]')
.waitForElementVisible('*[data-id="default_workspaceModalDialogContainer-react"]')
.pause(2000)
.click('.modal-ok')
.pause(2000)
@ -105,9 +109,9 @@ module.exports = {
.setValue('*[data-id="fileExplorerFileUpload"]', testData.testFile1)
.setValue('*[data-id="fileExplorerFileUpload"]', testData.testFile2)
.setValue('*[data-id="fileExplorerFileUpload"]', testData.testFile3)
.waitForElementVisible('[data-id="treeViewLitreeViewItembrowser/editor.test.js"]')
.waitForElementVisible('[data-id="treeViewLitreeViewItembrowser/fileExplorer.test.js"]')
.waitForElementVisible('[data-id="treeViewLitreeViewItembrowser/generalSettings.test.js"]')
.waitForElementVisible('[data-id="treeViewLitreeViewItemeditor.test.js"]')
.waitForElementVisible('[data-id="treeViewLitreeViewItemfileExplorer.test.js"]')
.waitForElementVisible('[data-id="treeViewLitreeViewItemgeneralSettings.test.js"]')
.end()
},

@ -13,7 +13,7 @@ module.exports = {
.addFile('file.js', { content: executeFile })
.executeScript('remix.exeCurrent()')
.pause(5000)
.journalLastChildIncludes('browser/file.js')
.journalLastChildIncludes('file.js')
},
'Should execute `exists` api from file manager external api': function (browser: NightwatchBrowser) {
@ -21,8 +21,8 @@ module.exports = {
.addFile('exists.js', { content: executeExists })
.executeScript('remix.exeCurrent()')
.pause(2000)
.journalChildIncludes('browser/exists.js true')
.journalChildIncludes('browser/non-exists.js false')
.journalChildIncludes('exists.js true')
.journalChildIncludes('non-exists.js false')
},
'Should execute `open` api from file manager external api': function (browser: NightwatchBrowser) {
@ -30,7 +30,7 @@ module.exports = {
.addFile('open.js', { content: executeOpen })
.executeScript('remix.exeCurrent()')
.pause(2000)
.journalLastChildIncludes('browser/contracts/3_Ballot.sol')
.journalLastChildIncludes('contracts/3_Ballot.sol')
},
'Should execute `writeFile` api from file manager external api': function (browser: NightwatchBrowser) {
@ -38,7 +38,7 @@ module.exports = {
.addFile('writeFile.js', { content: executeWriteFile })
.executeScript('remix.exeCurrent()')
.pause(2000)
.openFile('browser/new_contract.sol')
.openFile('new_contract.sol')
.assert.containsText('[data-id="editorInput"]', 'pragma solidity ^0.6.0')
},
@ -63,7 +63,7 @@ module.exports = {
.addFile('renameFile.js', { content: executeRename })
.executeScript('remix.exeCurrent()')
.pause(2000)
.waitForElementPresent('[data-id="treeViewLitreeViewItembrowser/old_contract.sol"]')
.waitForElementPresent('[data-id="treeViewLitreeViewItemold_contract.sol"]')
},
'Should execute `mkdir` api from file manager external api': function (browser: NightwatchBrowser) {
@ -71,7 +71,7 @@ module.exports = {
.addFile('mkdirFile.js', { content: executeMkdir })
.executeScript('remix.exeCurrent()')
.pause(2000)
.waitForElementPresent('[data-id="treeViewLitreeViewItembrowser/Test_Folder"]')
.waitForElementPresent('[data-id="treeViewLitreeViewItemTest_Folder"]')
},
'Should execute `readdir` api from file manager external api': function (browser: NightwatchBrowser) {
@ -87,16 +87,16 @@ module.exports = {
.addFile('removeFile.js', { content: executeRemove })
.executeScript('remix.exeCurrent()')
.pause(2000)
.waitForElementNotPresent('[data-id="treeViewLitreeViewItembrowser/old_contract.sol"]')
.waitForElementNotPresent('[data-id="treeViewLitreeViewItemold_contract.sol"]')
},
// TODO: Fix remove root directory prefix for browser and localhost
'Should execute `remove` api from file manager external api on a folder': '' + function (browser: NightwatchBrowser) {
'Should execute `remove` api from file manager external api on a folder': function (browser: NightwatchBrowser) {
browser
.addFile('test_jsRemoveFolder.js', { content: executeRemoveOnFolder })
.executeScript('remix.exeCurrent()')
.pause(2000)
.waitForElementNotPresent('[data-id="treeViewLitreeViewItembrowser/tests"]')
.waitForElementNotPresent('[data-id="treeViewLitreeViewItemTest_Folder"]')
.end()
},
@ -115,11 +115,11 @@ const executeFile = `
const executeExists = `
const run = async () => {
const result1 = await remix.call('fileManager', 'exists', 'browser/exists.js')
const result2 = await remix.call('fileManager', 'exists', 'browser/non-exists.js')
const result1 = await remix.call('fileManager', 'exists', 'exists.js')
const result2 = await remix.call('fileManager', 'exists', 'non-exists.js')
console.log('browser/exists.js ' + result1)
console.log('browser/non-exists.js ' + result2)
console.log('exists.js ' + result1)
console.log('non-exists.js ' + result2)
}
run()
@ -127,7 +127,7 @@ const executeExists = `
const executeOpen = `
const run = async () => {
await remix.call('fileManager', 'open', 'browser/contracts/3_Ballot.sol')
await remix.call('fileManager', 'open', 'contracts/3_Ballot.sol')
const result = await remix.call('fileManager', 'file')
console.log(result)
@ -138,7 +138,7 @@ const executeOpen = `
const executeWriteFile = `
const run = async () => {
await remix.call('fileManager', 'writeFile', 'browser/new_contract.sol', 'pragma solidity ^0.6.0')
await remix.call('fileManager', 'writeFile', 'new_contract.sol', 'pragma solidity ^0.6.0')
}
run()
@ -146,7 +146,7 @@ const executeWriteFile = `
const executeReadFile = `
const run = async () => {
const result = await remix.call('fileManager', 'readFile', 'browser/new_contract.sol')
const result = await remix.call('fileManager', 'readFile', 'new_contract.sol')
console.log(result)
}
@ -156,8 +156,8 @@ const executeReadFile = `
const executeCopyFile = `
const run = async () => {
await remix.call('fileManager', 'copyFile', 'browser/contracts/3_Ballot.sol', 'browser/new_contract.sol')
const result = await remix.call('fileManager', 'readFile', 'browser/new_contract.sol')
await remix.call('fileManager', 'copyFile', 'contracts/3_Ballot.sol', 'new_contract.sol')
const result = await remix.call('fileManager', 'readFile', 'new_contract.sol')
console.log(result)
}
@ -167,7 +167,7 @@ const executeCopyFile = `
const executeRename = `
const run = async () => {
await remix.call('fileManager', 'rename', 'browser/new_contract.sol', 'browser/old_contract.sol')
await remix.call('fileManager', 'rename', 'new_contract.sol', 'old_contract.sol')
}
run()
@ -175,7 +175,7 @@ const executeRename = `
const executeMkdir = `
const run = async () => {
await remix.call('fileManager', 'mkdir', 'browser/Test_Folder/')
await remix.call('fileManager', 'mkdir', 'Test_Folder/')
}
run()
@ -183,7 +183,7 @@ const executeMkdir = `
const executeReaddir = `
const run = async () => {
const result = await remix.call('fileManager', 'readdir', 'browser/')
const result = await remix.call('fileManager', 'readdir', '/')
console.log('Test_Folder isDirectory ', result["Test_Folder"].isDirectory)
}
@ -193,7 +193,7 @@ const executeReaddir = `
const executeRemove = `
const run = async () => {
await remix.call('fileManager', 'remove', 'browser/old_contract.sol')
await remix.call('fileManager', 'remove', 'old_contract.sol')
}
run()
@ -201,7 +201,7 @@ const executeRemove = `
const executeRemoveOnFolder = `(async () => {
try {
await remix.call('fileManager', 'remove', 'browser')
await remix.call('fileManager', 'remove', 'Test_Folder')
} catch (e) {
console.log(e.message)
}

@ -20,15 +20,15 @@ module.exports = {
browser.waitForElementVisible('*[data-id="remixIdeSidePanel"]', 5000)
.waitForElementVisible('*[data-id="settingsTabGenerateContractMetadataLabel"]', 5000)
.click('*[data-id="verticalIconsFileExplorerIcons"]')
.click('[data-id="treeViewLitreeViewItembrowser/contracts"]')
.openFile('browser/contracts/3_Ballot.sol')
.click('[data-id="treeViewLitreeViewItemcontracts"]')
.openFile('contracts/3_Ballot.sol')
.click('*[data-id="verticalIconsKindsolidity"]')
.pause(2000)
.click('*[data-id="compilerContainerCompileBtn"]')
.pause(3000)
.click('*[data-id="verticalIconsKindfileExplorers"]')
.openFile('browser/contracts/artifacts/Ballot.json')
.openFile('browser/contracts/artifacts/Ballot_metadata.json')
.openFile('contracts/artifacts/Ballot.json')
.openFile('contracts/artifacts/Ballot_metadata.json')
.getEditorValue((content) => {
const metadata = JSON.parse(content)
browser.assert.equal(metadata.language, 'Solidity')

@ -21,25 +21,26 @@ module.exports = {
- switch to a file in the new gist
*/
console.log('token', process.env.gist_token)
const runtimeBrowser = browser.options.desiredCapabilities.browserName
browser
.refresh()
.pause(10000)
.waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000)
.click('li[data-id="treeViewLitreeViewItemREADME.txt"]') // focus on root directory
.waitForElementVisible('*[data-id="fileExplorerNewFilecreateNewFolder"]')
.click('[data-id="fileExplorerNewFilecreateNewFolder"]')
.pause(1000)
.waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/blank"]')
.sendKeys('*[data-id="treeViewLitreeViewItembrowser/blank"] .remixui_items', 'Browser_Tests')
.sendKeys('*[data-id="treeViewLitreeViewItembrowser/blank"] .remixui_items', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/Browser_Tests"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItem/blank"]')
.sendKeys('*[data-id="treeViewLitreeViewItem/blank"] .remixui_items', 'Browser_Tests')
.sendKeys('*[data-id="treeViewLitreeViewItem/blank"] .remixui_items', browser.Keys.ENTER)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemBrowser_Tests"]')
.addFile('File.sol', { content: '' })
.click('*[data-id="fileExplorerNewFilepublishToGist"]')
.waitForElementVisible('*[data-id="browserModalDialogContainer-react"]')
.pause(2000)
.waitForElementVisible('*[data-id="default_workspaceModalDialogContainer-react"]')
.click('.modal-ok')
.pause(10000)
.getText('[data-id="browserModalDialogModalBody-react"]', (result) => {
.getText('[data-id="default_workspaceModalDialogModalBody-react"]', (result) => {
console.log(result)
const value = typeof result.value === 'string' ? result.value : null
const reg = /gist.github.com\/([^.]+)/
@ -51,12 +52,12 @@ module.exports = {
} else {
const gistid = id[1]
browser
.click('[data-id="browser-modal-footer-cancel-react"]')
.click('[data-id="default_workspace-modal-footer-cancel-react"]')
.executeScript(`remix.loadgist('${gistid}')`)
.perform((done) => { if (runtimeBrowser === 'chrome') { browser.openFile('browser/gists') } done() })
.waitForElementVisible(`[data-id="treeViewLitreeViewItembrowser/gists/${gistid}"]`)
.click(`[data-id="treeViewLitreeViewItembrowser/gists/${gistid}"]`)
.openFile(`browser/gists/${gistid}/README.txt`)
// .perform((done) => { if (runtimeBrowser === 'chrome') { browser.openFile('gists') } done() })
.waitForElementVisible(`[data-id="treeViewLitreeViewItem${gistid}"]`)
.click(`[data-id="treeViewLitreeViewItem${gistid}"]`)
.openFile(`${gistid}/README.txt`)
}
})
},
@ -96,14 +97,14 @@ module.exports = {
.clickLaunchIcon('fileExplorers')
.waitForElementVisible('*[data-id="fileExplorerNewFilepublishToGist"]')
.click('*[data-id="fileExplorerNewFilepublishToGist"]')
.waitForElementVisible('*[data-id="browserModalDialogContainer-react"]')
.waitForElementVisible('*[data-id="default_workspaceModalDialogContainer-react"]')
.pause(2000)
.click('.modal-ok')
.pause(10000)
.getText('[data-id="browserModalDialogModalBody-react"]', (result) => {
.getText('[data-id="default_workspaceModalDialogModalBody-react"]', (result) => {
browser.assert.ok(result.value === 'Remix requires an access token (which includes gists creation permission). Please go to the settings tab to create one.', 'Assert failed. Gist token error message not displayed.')
})
.click('[data-id="browser-modal-footer-ok-react"]')
.click('[data-id="default_workspace-modal-footer-ok-react"]')
},
'Import From Gist For Valid Gist ID': function (browser: NightwatchBrowser) {
@ -118,9 +119,9 @@ module.exports = {
.waitForElementVisible('*[data-id="modalDialogCustomPromptText"]')
.setValue('*[data-id="modalDialogCustomPromptText"]', testData.validGistId)
.modalFooterOKClick()
.openFile(`browser/gists/${testData.validGistId}/ApplicationRegistry`)
.waitForElementVisible(`div[title='browser/gists/${testData.validGistId}/ApplicationRegistry']`)
.assert.containsText(`div[title='browser/gists/${testData.validGistId}/ApplicationRegistry'] > span`, 'ApplicationRegistry')
.openFile(`${testData.validGistId}/ApplicationRegistry`)
.waitForElementVisible(`div[title='${testData.validGistId}/ApplicationRegistry']`)
.assert.containsText(`div[title='${testData.validGistId}/ApplicationRegistry'] > span`, 'ApplicationRegistry')
.end()
},

@ -13,7 +13,7 @@ module.exports = {
},
'Add Lib Test File': function (browser: NightwatchBrowser) {
browser.addFile('Untitled5.sol', sources[0]['browser/Untitled5.sol'])
browser.addFile('Untitled5.sol', sources[0]['Untitled5.sol'])
.clickLaunchIcon('udapp')
.selectAccount('0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c') // this account will be used for this test suite
},
@ -67,7 +67,7 @@ module.exports = {
function checkDeployShouldFail (browser: NightwatchBrowser, callback: VoidFunction) {
let config
browser.openFile('browser/artifacts').openFile('browser/artifacts/test.json')
browser.openFile('artifacts/test.json')
.getEditorValue((content) => {
config = JSON.parse(content)
config.deploy['VM:-'].autoDeployLib = false
@ -75,7 +75,7 @@ function checkDeployShouldFail (browser: NightwatchBrowser, callback: VoidFuncti
.perform(() => {
browser.setEditorValue(JSON.stringify(config))
})
.openFile('browser/Untitled5.sol')
.openFile('Untitled5.sol')
.clickLaunchIcon('udapp')
.selectContract('test') // deploy lib
.createContract('')
@ -89,16 +89,16 @@ function checkDeployShouldFail (browser: NightwatchBrowser, callback: VoidFuncti
function checkDeployShouldSucceed (browser: NightwatchBrowser, address: string, callback: VoidFunction) {
let addressRef: string
let config
browser.openFile('browser/artifacts').openFile('browser/artifacts/test.json')
browser.openFile('artifacts/test.json')
.getEditorValue((content) => {
config = JSON.parse(content)
config.deploy['VM:-'].autoDeployLib = false
config.deploy['VM:-'].linkReferences['browser/Untitled5.sol'].lib = address
config.deploy['VM:-'].linkReferences['Untitled5.sol'].lib = address
})
.perform(() => {
browser.setEditorValue(JSON.stringify(config))
})
.openFile('browser/Untitled5.sol')
.openFile('Untitled5.sol')
.clickLaunchIcon('udapp')
.selectContract('test') // deploy lib
.createContract('')
@ -116,7 +116,7 @@ function checkDeployShouldSucceed (browser: NightwatchBrowser, address: string,
const sources = [
{
'browser/Untitled5.sol': {
'Untitled5.sol': {
content: `library lib {
function getInt () public view returns (uint) {
return 45;

@ -72,7 +72,7 @@ module.exports = {
.assert.containsText('*[data-id="pluginManagerSettingsPermissionForm"]', 'No Permission requested yet')
.modalFooterOKClick()
.click('*[data-id="verticalIconsFileExplorerIcons"]')
.openFile('browser/3_Ballot.sol')
.openFile('3_Ballot.sol')
.click('*[plugin="ZoKrates"]')
.pause(5000)
.frame(0)

@ -16,8 +16,8 @@ module.exports = {
browser
.waitForElementVisible('#icon-panel', 10000)
.clickLaunchIcon('fileExplorers')
.click('[data-id="treeViewLitreeViewItembrowser/contracts"]')
.openFile('browser/contracts/3_Ballot.sol')
.click('[data-id="treeViewLitreeViewItemcontracts"]')
.openFile('contracts/3_Ballot.sol')
.verifyContracts(['Ballot'])
.click('#publishOnIpfs')
.pause(8000)
@ -45,7 +45,7 @@ module.exports = {
browser
.waitForElementVisible('#icon-panel')
.clickLaunchIcon('fileExplorers')
.openFile('browser/contracts/1_Storage.sol')
.openFile('contracts/1_Storage.sol')
.clickLaunchIcon('udapp')
.waitForElementPresent('*[data-id="contractDropdownIpfsCheckbox"]')
.click('*[data-id="contractDropdownIpfsCheckbox"]')
@ -61,9 +61,9 @@ module.exports = {
'Should remember choice after page refresh': function (browser: NightwatchBrowser) {
browser
.refresh()
.waitForElementVisible('[data-id="treeViewLitreeViewItembrowser/contracts"]')
.click('[data-id="treeViewLitreeViewItembrowser/contracts"]')
.openFile('browser/contracts/1_Storage.sol')
.waitForElementVisible('[data-id="treeViewLitreeViewItemcontracts"]')
.click('[data-id="treeViewLitreeViewItemcontracts"]')
.openFile('contracts/1_Storage.sol')
.clickLaunchIcon('udapp')
.waitForElementPresent('*[data-id="contractDropdownIpfsCheckbox"]')
.verify.elementPresent('*[data-id="contractDropdownIpfsCheckbox"]:checked')

@ -37,7 +37,7 @@ module.exports = {
.perform(() => done())
})
.click('*[data-id="deployAndRunClearInstances"]')
.testContracts('testRecorder.sol', sources[0]['browser/testRecorder.sol'], ['testRecorder'])
.testContracts('testRecorder.sol', sources[0]['testRecorder.sol'], ['testRecorder'])
.clickLaunchIcon('udapp')
.createContract('12')
.waitForElementPresent('.instance:nth-of-type(2)')
@ -64,7 +64,7 @@ module.exports = {
// deploy 2 contracts (2 different ABIs), save the record, reexecute and test one of the function.
browser
.click('*[data-id="deployAndRunClearInstances"]')
.testContracts('multipleContracts.sol', sources[1]['browser/multipleContracts.sol'], ['t1est', 't2est'])
.testContracts('multipleContracts.sol', sources[1]['multipleContracts.sol'], ['t1est', 't2est'])
.clickLaunchIcon('udapp')
.selectContract('t1est')
.pause(1000)
@ -81,10 +81,9 @@ module.exports = {
.clickInstance(1)
.pause(1000)
.clickFunction('set2 - transact (not payable)', { types: 'uint256 _po', values: '10' })
.testFunction('0xa88bf726e706480f61f04a066452929030c0a0216cc6923106f863963339bdb7',
.testFunction('last',
{
status: 'true Transaction mined and execution succeed',
'transaction hash': '0xa88bf726e706480f61f04a066452929030c0a0216cc6923106f863963339bdb7',
'decoded input': { 'uint256 _po': { type: 'BigNumber', hex: '0x0a' } }
})
.end()
@ -93,7 +92,7 @@ module.exports = {
}
const sources = [{
'browser/testRecorder.sol': {
'testRecorder.sol': {
content: `contract testRecorder {
constructor(uint p) public {
@ -105,7 +104,7 @@ const sources = [{
}
},
{
'browser/multipleContracts.sol': {
'multipleContracts.sol': {
content: `contract t1est {
uint p;
t2est t;
@ -163,7 +162,7 @@ const records = `{
"contractName": "test",
"bytecode": "60606040526040516020806102b183398101604052808051906020019091905050806000819055505061027a806100376000396000f300606060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632f30c6f61461006757806338cc48311461009e57806362738998146100f357806387cc10e11461011c575b600080fd5b61009c600480803590602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610145565b005b34156100a957600080fd5b6100b1610191565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156100fe57600080fd5b6101066101bb565b6040518082815260200191505060405180910390f35b341561012757600080fd5b61012f6101c4565b6040518082815260200191505060405180910390f35b8160008190555080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008054905090565b600073__browser/ballot.sol:testLib____________636d4ce63c6000604051602001526040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160206040518083038186803b151561022e57600080fd5b6102c65a03f4151561023f57600080fd5b505050604051805190509050905600a165627a7a72305820e0b2510bb2890a0334bfe5613d96db3e72442e63b514cdeaee8fc2c6bbd19d3a0029",
"linkReferences": {
"browser/ballot.sol": {
"ballot.sol": {
"testLib": [
{
"length": 20,

@ -31,10 +31,10 @@ const sources = [
'localhost/src/gmbh/contract.sol': { content: gmbhTestContract }
},
{
'browser/test_import_node_modules.sol': { content: 'import "openzeppelin-solidity/contracts/math/SafeMath.sol";' }
'test_import_node_modules.sol': { content: 'import "openzeppelin-solidity/contracts/math/SafeMath.sol";' }
},
{
'browser/test_import_node_modules_with_github_import.sol': { content: 'import "openzeppelin-solidity/contracts/sample.sol";' }
'test_import_node_modules_with_github_import.sol': { content: 'import "openzeppelin-solidity/contracts/sample.sol";' }
}
]
@ -57,18 +57,20 @@ module.exports = {
*/
browser.waitForElementVisible('#icon-panel', 2000)
.clickLaunchIcon('fileExplorers')
.addFile('test_import_node_modules.sol', sources[3]['browser/test_import_node_modules.sol'])
// .clickLaunchIcon('fileExplorers')
.click('[data-path="ballot.sol"]')
.addFile('test_import_node_modules.sol', sources[3]['test_import_node_modules.sol'])
.clickLaunchIcon('solidity')
.testContracts('test_import_node_modules.sol', sources[3]['browser/test_import_node_modules.sol'], ['SafeMath'])
.setSolidityCompilerVersion('soljson-v0.5.0+commit.1d4f565a.js')
.testContracts('test_import_node_modules.sol', sources[3]['test_import_node_modules.sol'], ['SafeMath'])
},
'Import from node_modules and reference a github import': function (browser) {
browser.waitForElementVisible('#icon-panel', 2000)
.clickLaunchIcon('fileExplorers')
.addFile('test_import_node_modules_with_github_import.sol', sources[4]['browser/test_import_node_modules_with_github_import.sol'])
.addFile('test_import_node_modules_with_github_import.sol', sources[4]['test_import_node_modules_with_github_import.sol'])
.clickLaunchIcon('solidity')
.setSolidityCompilerVersion('soljson-v0.8.0+commit.c7dfd78e.js') // open-zeppelin moved to pragma ^0.8.0
.testContracts('test_import_node_modules_with_github_import.sol', sources[4]['browser/test_import_node_modules_with_github_import.sol'], ['ERC20', 'test11'])
.testContracts('test_import_node_modules_with_github_import.sol', sources[4]['test_import_node_modules_with_github_import.sol'], ['ERC20', 'test11'])
},
'Run git status': function (browser) {
@ -104,48 +106,48 @@ function runTests (browser: NightwatchBrowser) {
.pause(2000)
.click('#modal-footer-ok')
.clickLaunchIcon('fileExplorers')
.waitForElementVisible('[data-path="localhost/folder1"]')
.click('[data-path="localhost/folder1"]')
.waitForElementVisible('[data-path="localhost/contract1.sol"]')
.assert.containsText('[data-path="localhost/contract1.sol"]', 'contract1.sol')
.assert.containsText('[data-path="localhost/contract2.sol"]', 'contract2.sol')
.waitForElementVisible('[data-path="localhost/folder1/contract1.sol"]')
.assert.containsText('[data-path="localhost/folder1/contract1.sol"]', 'contract1.sol')
.assert.containsText('[data-path="localhost/folder1/contract2.sol"]', 'contract2.sol') // load and test sub folder
.click('[data-path="localhost/folder1/contract2.sol"]')
.click('[data-path="localhost/folder1/contract1.sol"]') // open localhost/folder1/contract1.sol
.waitForElementVisible('[data-path="folder1"]')
.click('[data-path="folder1"]')
.waitForElementVisible('[data-path="contract1.sol"]')
.assert.containsText('[data-path="contract1.sol"]', 'contract1.sol')
.assert.containsText('[data-path="contract2.sol"]', 'contract2.sol')
.waitForElementVisible('[data-path="folder1/contract1.sol"]')
.assert.containsText('[data-path="folder1/contract1.sol"]', 'contract1.sol')
.assert.containsText('[data-path="folder1/contract2.sol"]', 'contract2.sol') // load and test sub folder
.click('[data-path="folder1/contract2.sol"]')
.click('[data-path="folder1/contract1.sol"]') // open localhost/folder1/contract1.sol
.pause(1000)
.testEditorValue('contract test1 { function get () returns (uint) { return 10; }}') // check the content and replace by another
.setEditorValue('contract test1Changed { function get () returns (uint) { return 10; }}')
.testEditorValue('contract test1Changed { function get () returns (uint) { return 10; }}')
.setEditorValue('contract test1 { function get () returns (uint) { return 10; }}')
.click('[data-path="localhost/folder1/contract_' + browserName + '.sol"]') // rename a file and check
.click('[data-path="folder1/contract_' + browserName + '.sol"]') // rename a file and check
.pause(1000)
.renamePath('localhost/folder1/contract_' + browserName + '.sol', 'renamed_contract_' + browserName + '.sol', 'localhost/folder1/renamed_contract_' + browserName + '.sol')
.renamePath('folder1/contract_' + browserName + '.sol', 'renamed_contract_' + browserName + '.sol', 'folder1/renamed_contract_' + browserName + '.sol')
.pause(1000)
.removeFile('localhost/folder1/contract_' + browserName + '_toremove.sol')
.removeFile('folder1/contract_' + browserName + '_toremove.sol')
.perform(function (done) {
testImportFromRemixd(browser, () => { done() })
})
.clickLaunchIcon('fileExplorers')
.waitForElementVisible('[data-path="localhost/folder1"]')
.click('[data-path="localhost/folder1"]')
.click('[data-path="localhost/folder1"]') // click twice because remixd does not return nested folder details after update
.waitForElementVisible('[data-path="localhost/folder1/contract1.sol"]')
.waitForElementVisible('[data-path="localhost/folder1/renamed_contract_' + browserName + '.sol"]') // check if renamed file is preset
.waitForElementNotPresent('[data-path="localhost/folder1/contract_' + browserName + '.sol"]') // check if renamed (old) file is not present
.waitForElementNotPresent('[data-path="localhost/folder1/contract_' + browserName + '_toremove.sol"]') // check if removed (old) file is not present
.click('[data-path="localhost/folder1/renamed_contract_' + browserName + '.sol"]')
.waitForElementVisible('[data-path="folder1"]')
.click('[data-path="folder1"]')
.click('[data-path="folder1"]') // click twice because remixd does not return nested folder details after update
.waitForElementVisible('[data-path="folder1/contract1.sol"]')
.waitForElementVisible('[data-path="folder1/renamed_contract_' + browserName + '.sol"]') // check if renamed file is preset
.waitForElementNotPresent('[data-path="folder1/contract_' + browserName + '.sol"]') // check if renamed (old) file is not present
.waitForElementNotPresent('[data-path="folder1/contract_' + browserName + '_toremove.sol"]') // check if removed (old) file is not present
// .click('[data-path="folder1/renamed_contract_' + browserName + '.sol"]')
}
function testImportFromRemixd (browser: NightwatchBrowser, callback: VoidFunction) {
browser
.waitForElementVisible('[data-path="localhost/src"]', 100000)
.click('[data-path="localhost/src"]')
.waitForElementVisible('[data-path="localhost/src/gmbh"]', 100000)
.click('[data-path="localhost/src/gmbh"]')
.waitForElementVisible('[data-path="localhost/src/gmbh/company.sol"]', 100000)
.click('[data-path="localhost/src/gmbh/company.sol"]')
.waitForElementVisible('[data-path="src"]', 100000)
.click('[data-path="src"]')
.waitForElementVisible('[data-path="src/gmbh"]', 100000)
.click('[data-path="src/gmbh"]')
.waitForElementVisible('[data-path="src/gmbh/company.sol"]', 100000)
.click('[data-path="src/gmbh/company.sol"]')
.pause(1000)
.verifyContracts(['Assets', 'gmbh'])
.perform(() => { callback() })

@ -49,15 +49,14 @@ module.exports = {
'Should deploy contract on JavascriptVM': function (browser: NightwatchBrowser) {
browser.waitForElementPresent('*[data-id="remixIdeSidePanel"]')
.clickLaunchIcon('fileExplorers')
.addFile('Greet.sol', sources[0]['browser/Greet.sol'])
.addFile('Greet.sol', sources[0]['Greet.sol'])
.clickLaunchIcon('udapp')
.selectAccount('0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c')
.waitForElementPresent('*[data-id="Deploy - transact (not payable)"]', 45000)
.click('*[data-id="Deploy - transact (not payable)"]')
.pause(5000)
.testFunction('0xcc391e151ace69f4cfb51cda42fb6c2e1092f28c8c2757af20b1aae5ec076ead', {
status: 'true Transaction mined and execution succeed',
'transaction hash': '0xcc391e151ace69f4cfb51cda42fb6c2e1092f28c8c2757af20b1aae5ec076ead'
.testFunction('last', {
status: 'true Transaction mined and execution succeed'
})
},
@ -68,9 +67,8 @@ module.exports = {
.waitForElementPresent('*[data-id="pluginManagerSettingsDeployAndRunLLTxSendTransaction"]')
.click('*[data-id="pluginManagerSettingsDeployAndRunLLTxSendTransaction"]')
.pause(5000)
.testFunction('0xfe718871ee0b4d03cdcac0e12e5b164efaf7e23ba952c07db76e62692867019b', {
status: 'true Transaction mined and execution succeed',
'transaction hash': '0xfe718871ee0b4d03cdcac0e12e5b164efaf7e23ba952c07db76e62692867019b'
.testFunction('last', {
status: 'true Transaction mined and execution succeed'
})
.end()
},
@ -99,7 +97,7 @@ module.exports = {
'Should deploy contract on Goerli Test Network using MetaMask': '' + function (browser: NightwatchBrowser) {
browser.waitForElementPresent('*[data-id="runTabSelectAccount"] option')
.clickLaunchIcon('fileExplorers')
.openFile('browser/Greet.sol')
.openFile('Greet.sol')
.clickLaunchIcon('udapp')
.waitForElementPresent('*[data-id="Deploy - transact (not payable)"]')
.click('*[data-id="Deploy - transact (not payable)"]')
@ -151,7 +149,7 @@ module.exports = {
'Should deploy contract on Ethereum Main Network using MetaMask': '' + function (browser: NightwatchBrowser) {
browser.waitForElementPresent('*[data-id="runTabSelectAccount"] option')
.clickLaunchIcon('fileExplorers')
.openFile('browser/Greet.sol')
.openFile('Greet.sol')
.clickLaunchIcon('udapp')
.waitForElementPresent('*[data-id="Deploy - transact (not payable)"]')
.click('*[data-id="Deploy - transact (not payable)"]')
@ -205,7 +203,7 @@ module.exports = {
const sources = [
{
'browser/Greet.sol': {
'Greet.sol': {
content:
`
pragma solidity ^0.8.0;

@ -25,8 +25,8 @@ module.exports = {
browser.assert.ok(typeof hash.value === 'string', 'type of hash.value must be String')
browser.assert.ok(typeof signature.value === 'string', 'type of signature.value must be String')
})
.addFile('signMassage.sol', sources[0]['browser/signMassage.sol'])
.openFile('browser/signMassage.sol')
.addFile('signMassage.sol', sources[0]['signMassage.sol'])
.openFile('signMassage.sol')
.clickLaunchIcon('solidity')
.click('*[data-id="compilerContainerCompileBtn"]')
.clickLaunchIcon('udapp')
@ -57,7 +57,7 @@ module.exports = {
const sources = [
{
'browser/signMassage.sol': {
'signMassage.sol': {
content: `
pragma solidity >=0.4.22 <0.9.0;
contract SignMassageTest {

@ -13,26 +13,26 @@ module.exports = {
},
'Test Simple Contract': function (browser: NightwatchBrowser) {
browser.testContracts('Untitled.sol', sources[0]['browser/Untitled.sol'], ['test1', 'test2'])
browser.testContracts('Untitled.sol', sources[0]['Untitled.sol'], ['test1', 'test2'])
},
'Test Success Import': function (browser: NightwatchBrowser) {
browser.addFile('Untitled1.sol', sources[1]['browser/Untitled1.sol'])
.addFile('Untitled2.sol', sources[1]['browser/Untitled2.sol'])
.openFile('browser/Untitled1.sol')
browser.addFile('Untitled1.sol', sources[1]['Untitled1.sol'])
.addFile('Untitled2.sol', sources[1]['Untitled2.sol'])
.openFile('Untitled1.sol')
.verifyContracts(['test6', 'test4', 'test5'])
},
'Test Failed Import': function (browser: NightwatchBrowser) {
browser.addFile('Untitled3.sol', sources[2]['browser/Untitled3.sol'])
browser.addFile('Untitled3.sol', sources[2]['Untitled3.sol'])
.clickLaunchIcon('solidity')
.assert.containsText('#compileTabView .error pre', 'not found browser/Untitled11.sol')
.assert.containsText('#compileTabView .error pre', 'not found Untitled11.sol')
},
'Test Github Import - from master branch': function (browser: NightwatchBrowser) {
browser
.setSolidityCompilerVersion('soljson-v0.8.0+commit.c7dfd78e.js') // open-zeppelin moved to pragma ^0.8.0 (master branch)
.addFile('Untitled4.sol', sources[3]['browser/Untitled4.sol'])
.addFile('Untitled4.sol', sources[3]['Untitled4.sol'])
.clickLaunchIcon('fileExplorers')
.verifyContracts(['test7', 'ERC20'], { wait: 10000 })
},
@ -40,7 +40,7 @@ module.exports = {
'Test Github Import - from other branch': function (browser: NightwatchBrowser) {
browser
.setSolidityCompilerVersion('soljson-v0.5.0+commit.1d4f565a.js') // switch back to 0.5.0 : release-v2.3.0 branch is not solidity 0.6 compliant
.addFile('Untitled5.sol', sources[4]['browser/Untitled5.sol'])
.addFile('Untitled5.sol', sources[4]['Untitled5.sol'])
.clickLaunchIcon('fileExplorers')
.verifyContracts(['test8', 'ERC20', 'SafeMath'], { wait: 10000 })
},
@ -49,8 +49,8 @@ module.exports = {
browser
.setSolidityCompilerVersion('soljson-v0.8.0+commit.c7dfd78e.js') // open-zeppelin moved to pragma ^0.8.0 (master branch)
.clickLaunchIcon('fileExplorers')
.click('li[data-id="treeViewLitreeViewItembrowser/README.txt"')
.addFile('Untitled6.sol', sources[5]['browser/Untitled6.sol'])
.click('li[data-id="treeViewLitreeViewItemREADME.txt"')
.addFile('Untitled6.sol', sources[5]['Untitled6.sol'])
.clickLaunchIcon('fileExplorers')
.verifyContracts(['test10', 'ERC20'], { wait: 10000 })
},
@ -58,8 +58,8 @@ module.exports = {
'Test Github Import - raw URL': function (browser: NightwatchBrowser) {
browser
.clickLaunchIcon('fileExplorers')
.click('li[data-id="treeViewLitreeViewItembrowser/README.txt"')
.addFile('Untitled7.sol', sources[6]['browser/Untitled7.sol'])
.click('li[data-id="treeViewLitreeViewItemREADME.txt"')
.addFile('Untitled7.sol', sources[6]['Untitled7.sol'])
.clickLaunchIcon('fileExplorers')
.verifyContracts(['test11', 'ERC20'], { wait: 10000 })
},
@ -68,8 +68,8 @@ module.exports = {
browser
.setSolidityCompilerVersion('soljson-v0.7.4+commit.3f05b770.js')
.clickLaunchIcon('fileExplorers')
.click('li[data-id="treeViewLitreeViewItembrowser/README.txt"')
.addFile('Untitled8.sol', sources[7]['browser/Untitled8.sol'])
.click('li[data-id="treeViewLitreeViewItemREADME.txt"')
.addFile('Untitled8.sol', sources[7]['Untitled8.sol'])
.clickLaunchIcon('fileExplorers')
.clickLaunchIcon('solidity')
.waitForElementPresent('[data-id="compiledErrors"] div:nth-child(3)', 45000)
@ -85,8 +85,8 @@ module.exports = {
browser
// .setSolidityCompilerVersion('soljson-v0.8.0+commit.c7dfd78e.js')
.clickLaunchIcon('fileExplorers')
.click('li[data-id="treeViewLitreeViewItembrowser/README.txt"')
.addFile('Untitled9.sol', sources[8]['browser/Untitled9.sol'])
.click('li[data-id="treeViewLitreeViewItemREADME.txt"')
.addFile('Untitled9.sol', sources[8]['Untitled9.sol'])
.clickLaunchIcon('fileExplorers')
.verifyContracts(['test13', 'ERC20', 'SafeMath'], { wait: 30000 })
.end()
@ -96,31 +96,31 @@ module.exports = {
const sources = [
{
'browser/Untitled.sol': { content: 'contract test1 {} contract test2 {}' }
'Untitled.sol': { content: 'contract test1 {} contract test2 {}' }
},
{
'browser/Untitled1.sol': { content: 'import "./Untitled2.sol"; contract test6 {}' },
'browser/Untitled2.sol': { content: 'contract test4 {} contract test5 {}' }
'Untitled1.sol': { content: 'import "./Untitled2.sol"; contract test6 {}' },
'Untitled2.sol': { content: 'contract test4 {} contract test5 {}' }
},
{
'browser/Untitled3.sol': { content: 'import "./Untitled11.sol"; contract test6 {}' }
'Untitled3.sol': { content: 'import "./Untitled11.sol"; contract test6 {}' }
},
{
'browser/Untitled4.sol': { content: 'import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol"; contract test7 {}' }
'Untitled4.sol': { content: 'import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol"; contract test7 {}' }
},
{
'browser/Untitled5.sol': { content: 'import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v2.3.0/contracts/token/ERC20/ERC20.sol"; contract test8 {}' }
'Untitled5.sol': { content: 'import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v2.3.0/contracts/token/ERC20/ERC20.sol"; contract test8 {}' }
},
{
'browser/Untitled6.sol': { content: 'import "https://github.com/OpenZeppelin/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; contract test10 {}' }
'Untitled6.sol': { content: 'import "https://github.com/OpenZeppelin/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; contract test10 {}' }
},
{
'browser/Untitled7.sol': { content: 'import "https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/master/contracts/token/ERC20/ERC20.sol"; contract test11 {}' }
'Untitled7.sol': { content: 'import "https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/master/contracts/token/ERC20/ERC20.sol"; contract test11 {}' }
},
{
'browser/Untitled8.sol': { content: 'import "https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/master/contracts/token/ERC20/ERC20.sol"; contract test12 {}' }
'Untitled8.sol': { content: 'import "https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/master/contracts/token/ERC20/ERC20.sol"; contract test12 {}' }
},
{
'browser/Untitled9.sol': { content: 'pragma solidity >=0.6.0 <0.8.0; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract test13 {}' }
'Untitled9.sol': { content: 'pragma solidity >=0.6.0 <0.8.0; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract test13 {}' }
}
]

@ -17,8 +17,8 @@ module.exports = {
'Should launch solidity unit test plugin': function (browser: NightwatchBrowser) {
browser.waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]')
.clickLaunchIcon('fileExplorers')
.addFile('simple_storage.sol', sources[0]['browser/simple_storage.sol'])
.addFile('ks2a.sol', sources[0]['browser/ks2a.sol'])
.addFile('simple_storage.sol', sources[0]['simple_storage.sol'])
.addFile('ks2a.sol', sources[0]['ks2a.sol'])
.clickLaunchIcon('pluginManager')
.scrollAndClick('*[data-id="pluginManagerComponentActivateButtonsolidityUnitTesting"]')
.click('*[data-id="verticalIconsKindsolidityUnitTesting"]')
@ -29,20 +29,20 @@ module.exports = {
'Should generate test file': function (browser: NightwatchBrowser) {
browser.waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]')
.clickLaunchIcon('fileExplorers')
.openFile('browser/simple_storage.sol')
.openFile('simple_storage.sol')
.click('*[data-id="verticalIconsKindsolidityUnitTesting"]')
.waitForElementPresent('*[data-id="testTabGenerateTestFile"]')
.click('*[data-id="testTabGenerateTestFile"]')
.waitForElementPresent('*[title="browser/tests/simple_storage_test.sol"]')
.waitForElementPresent('*[title="tests/simple_storage_test.sol"]')
.clickLaunchIcon('fileExplorers')
.pause(10000)
.openFile('browser/tests/simple_storage_test.sol')
.removeFile('browser/tests/simple_storage_test.sol')
.openFile('tests/simple_storage_test.sol')
.removeFile('tests/simple_storage_test.sol')
},
'Should run simple unit test `simple_storage_test.sol` ': function (browser: NightwatchBrowser) {
browser.waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]')
.addFile('tests/simple_storage_test.sol', sources[0]['browser/tests/simple_storage_test.sol'])
.addFile('tests/simple_storage_test.sol', sources[0]['tests/simple_storage_test.sol'])
.click('*[data-id="verticalIconsKindsolidityUnitTesting"]')
.waitForElementPresent('*[data-id="testTabCheckAllTests"]')
.click('*[data-id="testTabCheckAllTests"]')
@ -50,19 +50,19 @@ module.exports = {
.scrollAndClick('*[data-id="testTabRunTestsTabRunAction"]')
.waitForElementPresent('*[data-id="testTabSolidityUnitTestsOutputheader"]', 80000)
.pause(5000)
.assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'MyTest (browser/tests/simple_storage_test.sol)')
.assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'MyTest (/tests/simple_storage_test.sol)')
.assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', '✓ Initial value should be100')
.assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', '✓ Value is set200')
.assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', '✘ Should fail for wrong value200')
.assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'Passing: 2')
.assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'Failing: 1')
.assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'FAIL MyTest (browser/tests/simple_storage_test.sol)')
.assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'FAIL MyTest (/tests/simple_storage_test.sol)')
},
'Should run advance unit test using natspec and experimental ABIEncoderV2 `ks2b_test.sol` ': function (browser: NightwatchBrowser) {
browser.waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]')
.clickLaunchIcon('fileExplorers')
.addFile('tests/ks2b_test.sol', sources[0]['browser/tests/ks2b_test.sol'])
.addFile('tests/ks2b_test.sol', sources[0]['tests/ks2b_test.sol'])
.click('*[data-id="verticalIconsKindsolidityUnitTesting"]')
.waitForElementPresent('*[data-id="testTabCheckAllTests"]')
.click('*[data-id="testTabCheckAllTests"]')
@ -70,7 +70,7 @@ module.exports = {
.scrollAndClick('*[data-id="testTabRunTestsTabRunAction"]')
.waitForElementPresent('*[data-id="testTabSolidityUnitTestsOutputheader"]', 40000)
.pause(5000)
.assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'browser/tests/ks2b_test.sol')
.assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', '/tests/ks2b_test.sol')
.assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', '✓ Check project exists')
.assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', '✘ Check wrong project owner')
.assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', '✘ Check wrong sender')
@ -93,18 +93,18 @@ module.exports = {
// .pause(1000)
.assert.containsText('*[data-id="testTabRunTestsTabStopAction"]', 'Stopping')
.waitForElementPresent('*[data-id="testTabSolidityUnitTestsOutputheader"]', 40000)
.assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'browser/tests/ks2b_test.sol')
.notContainsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'browser/tests/4_Ballot_test.sol')
.notContainsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'browser/tests/simple_storage_test.sol')
.assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', '/tests/ks2b_test.sol')
.notContainsText('*[data-id="testTabSolidityUnitTestsOutput"]', '/tests/4_Ballot_test.sol')
.notContainsText('*[data-id="testTabSolidityUnitTestsOutput"]', '/tests/simple_storage_test.sol')
.pause(7000)
.assert.containsText('*[data-id="testTabTestsExecutionStopped"]', 'The test execution has been stopped')
},
'Should fail on compilation': function (browser: NightwatchBrowser) {
browser.waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]')
.addFile('tests/compilationError_test.sol', sources[0]['browser/compilationError_test.sol'])
.addFile('tests/compilationError_test.sol', sources[0]['compilationError_test.sol'])
.clickLaunchIcon('fileExplorers')
.openFile('browser/tests/compilationError_test.sol')
.openFile('tests/compilationError_test.sol')
.clickLaunchIcon('solidityUnitTesting')
.click('*[data-id="testTabCheckAllTests"]')
.clickElementAtPosition('.singleTestLabel', 3)
@ -117,9 +117,9 @@ module.exports = {
'Should fail on deploy': function (browser: NightwatchBrowser) {
browser.waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]')
.addFile('tests/deployError_test.sol', sources[0]['browser/tests/deployError_test.sol'])
.addFile('tests/deployError_test.sol', sources[0]['tests/deployError_test.sol'])
.clickLaunchIcon('fileExplorers')
.openFile('browser/tests/deployError_test.sol')
.openFile('tests/deployError_test.sol')
.clickLaunchIcon('solidityUnitTesting')
.click('*[data-id="testTabCheckAllTests"]')
.clickElementAtPosition('.singleTestLabel', 4)
@ -131,9 +131,9 @@ module.exports = {
'Should fail when parameters are to method in test contract': function (browser: NightwatchBrowser) {
browser.waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]')
.addFile('tests/methodFailure_test.sol', sources[0]['browser/tests/methodFailure_test.sol'])
.addFile('tests/methodFailure_test.sol', sources[0]['tests/methodFailure_test.sol'])
.clickLaunchIcon('fileExplorers')
.openFile('browser/tests/methodFailure_test.sol')
.openFile('tests/methodFailure_test.sol')
.clickLaunchIcon('solidityUnitTesting')
.click('*[data-id="testTabCheckAllTests"]')
.clickElementAtPosition('.singleTestLabel', 5)
@ -146,15 +146,15 @@ module.exports = {
'Changing current path': function (browser: NightwatchBrowser) {
browser
.waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]')
.addFile('myTests/simple_storage_test.sol', sources[0]['browser/tests/simple_storage_test.sol'])
.addFile('myTests/simple_storage_test.sol', sources[0]['tests/simple_storage_test.sol'])
.clickLaunchIcon('solidityUnitTesting')
.setValue('*[data-id="uiPathInput"]', 'browser/myTests')
.setValue('*[data-id="uiPathInput"]', 'myTests')
.clickElementAtPosition('.singleTestLabel', 0)
.scrollAndClick('*[data-id="testTabRunTestsTabRunAction"]')
.waitForElementPresent('*[data-id="testTabSolidityUnitTestsOutputheader"]', 40000)
.waitForElementPresent('*[data-id="testTabSolidityUnitTestsOutput"]')
.clearValue('*[data-id="uiPathInput"]')
.setValue('*[data-id="uiPathInput"]', 'browser/tests')
.setValue('*[data-id="uiPathInput"]', 'tests')
},
'Solidity Unittests': function (browser: NightwatchBrowser) {
@ -168,14 +168,14 @@ function runTests (browser: NightwatchBrowser) {
browser
.waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]')
.clickLaunchIcon('fileExplorers')
.click('*[data-id="treeViewLitreeViewItembrowser/contracts"]')
.openFile('browser/contracts/3_Ballot.sol')
.click('*[data-id="treeViewLitreeViewItemcontracts"]')
.openFile('contracts/3_Ballot.sol')
.clickLaunchIcon('solidityUnitTesting')
.pause(500)
.scrollAndClick('#runTestsTabRunAction')
.waitForElementPresent('*[data-id="testTabSolidityUnitTestsOutputheader"]', 40000)
.waitForElementPresent('#solidityUnittestsOutput div[class^="testPass"]', 10000)
.assert.containsText('#solidityUnittestsOutput', 'browser/tests/4_Ballot_test.sol')
.assert.containsText('#solidityUnittestsOutput', '/tests/4_Ballot_test.sol')
.assert.containsText('#solidityUnittestsOutput', '✓ Check winning proposal')
.assert.containsText('#solidityUnittestsOutput', '✓ Check winnin proposal with return value')
.end()
@ -183,7 +183,7 @@ function runTests (browser: NightwatchBrowser) {
const sources = [
{
'browser/simple_storage.sol': {
'simple_storage.sol': {
content: `
pragma solidity >=0.4.22 <0.9.0;
@ -204,7 +204,7 @@ const sources = [
}
`
},
'browser/tests/simple_storage_test.sol': {
'tests/simple_storage_test.sol': {
content: `
pragma solidity >=0.4.22 <0.9.0;
import "remix_tests.sol";
@ -233,7 +233,7 @@ const sources = [
}
`
},
'browser/ks2a.sol': {
'ks2a.sol': {
content: `
pragma solidity >=0.4.22 <0.9.0;
contract Kickstarter {
@ -287,7 +287,7 @@ const sources = [
}
`
},
'browser/tests/ks2b_test.sol': {
'tests/ks2b_test.sol': {
content: `
pragma solidity >=0.4.22 <0.9.0;
pragma experimental ABIEncoderV2;
@ -346,7 +346,7 @@ const sources = [
}
`
},
'browser/compilationError_test.sol': {
'compilationError_test.sol': {
content: `
pragma solidity ^0.7.0;
@ -357,7 +357,7 @@ const sources = [
}
`
},
'browser/tests/deployError_test.sol': {
'tests/deployError_test.sol': {
content: `
pragma solidity ^0.7.0;
@ -368,7 +368,7 @@ const sources = [
}
`
},
'browser/tests/methodFailure_test.sol': {
'tests/methodFailure_test.sol': {
content: `
pragma solidity ^0.7.0;

@ -20,7 +20,7 @@ module.exports = {
'Use special functions receive/fallback - both are declared, sending data': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('#icon-panel', 10000)
.testContracts('receiveAndFallback.sol', sources[0]['browser/receiveAndFallback.sol'], ['CheckSpecials']) // compile
.testContracts('receiveAndFallback.sol', sources[0]['receiveAndFallback.sol'], ['CheckSpecials']) // compile
.clickLaunchIcon('udapp')
.selectAccount('0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c') // this account will be used for this test suite
.selectContract('CheckSpecials')
@ -89,7 +89,7 @@ module.exports = {
},
'Use special functions receive/fallback - only receive is declared, sending wei': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('#icon-panel', 10000)
.testContracts('receiveOnly.sol', sources[1]['browser/receiveOnly.sol'], ['CheckSpecials'])
.testContracts('receiveOnly.sol', sources[1]['receiveOnly.sol'], ['CheckSpecials'])
.clickLaunchIcon('udapp')
.selectContract('CheckSpecials')
.createContract('')
@ -119,7 +119,7 @@ module.exports = {
},
'Use special functions receive/fallback - only fallback declared and is payable, sending wei': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('#icon-panel', 10000)
.testContracts('fallbackOnlyPayable.sol', sources[2]['browser/fallbackOnlyPayable.sol'], ['CheckSpecials'])
.testContracts('fallbackOnlyPayable.sol', sources[2]['fallbackOnlyPayable.sol'], ['CheckSpecials'])
.clickLaunchIcon('udapp')
.selectContract('CheckSpecials')
.createContract('')
@ -150,7 +150,7 @@ module.exports = {
},
'Use special functions receive/fallback - only fallback is declared, fallback should fail cause not payable, sending wei': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('#icon-panel', 10000)
.testContracts('fallbackOnlyNotPayable.sol', sources[3]['browser/fallbackOnlyNotPayable.sol'], ['CheckSpecials'])
.testContracts('fallbackOnlyNotPayable.sol', sources[3]['fallbackOnlyNotPayable.sol'], ['CheckSpecials'])
.clickLaunchIcon('udapp')
.selectContract('CheckSpecials')
.createContract('')
@ -167,7 +167,7 @@ module.exports = {
},
'Use special functions receive/fallback - receive and fallback are declared, sending data and wei': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('#icon-panel', 10000)
.testContracts('receiveAndFallbackBothPayable.sol', sources[4]['browser/receiveAndFallbackBothPayable.sol'], ['CheckSpecials'])
.testContracts('receiveAndFallbackBothPayable.sol', sources[4]['receiveAndFallbackBothPayable.sol'], ['CheckSpecials'])
.clickLaunchIcon('udapp')
.selectContract('CheckSpecials')
.waitForElementVisible('#value')
@ -201,7 +201,7 @@ module.exports = {
},
'Use special functions receive/fallback - receive and fallback are not declared, sending nothing': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('#icon-panel', 10000)
.testContracts('notSpecial.sol', sources[5]['browser/notSpecial.sol'], ['CheckSpecials'])
.testContracts('notSpecial.sol', sources[5]['notSpecial.sol'], ['CheckSpecials'])
.clickLaunchIcon('udapp')
.selectContract('CheckSpecials')
.waitForElementVisible('#value')
@ -226,7 +226,7 @@ module.exports = {
const sources = [
{
'browser/receiveAndFallback.sol': {
'receiveAndFallback.sol': {
content: `
contract CheckSpecials {
receive() payable external{}
@ -236,7 +236,7 @@ const sources = [
}
},
{
'browser/receiveOnly.sol': {
'receiveOnly.sol': {
content: `
contract CheckSpecials {
receive() payable external {}
@ -245,7 +245,7 @@ const sources = [
}
},
{
'browser/fallbackOnlyPayable.sol': {
'fallbackOnlyPayable.sol': {
content: `
contract CheckSpecials {
fallback() payable external {}
@ -254,7 +254,7 @@ const sources = [
}
},
{
'browser/fallbackOnlyNotPayable.sol': {
'fallbackOnlyNotPayable.sol': {
content: `
contract CheckSpecials {
fallback() external {}
@ -263,7 +263,7 @@ const sources = [
}
},
{
'browser/receiveAndFallbackBothPayable.sol': {
'receiveAndFallbackBothPayable.sol': {
content: `
contract CheckSpecials {
receive() payable external {}
@ -273,7 +273,7 @@ const sources = [
}
},
{
'browser/notSpecial.sol': {
'notSpecial.sol': {
content: `
contract CheckSpecials {
function otherFallback() payable external {}

@ -5,7 +5,7 @@ import sauce from './sauce'
const sources = [
{
'browser/Untitled.sol': {
'Untitled.sol': {
content: `
pragma solidity >=0.6.0 <0.8.0;
contract test1 { address test = tx.origin; }
@ -40,7 +40,7 @@ function runTests (browser: NightwatchBrowser) {
.waitForElementVisible('#icon-panel', 10000)
.clickLaunchIcon('solidity')
.pause(10000)
.testContracts('Untitled.sol', sources[0]['browser/Untitled.sol'], ['TooMuchGas', 'test1', 'test2'])
.testContracts('Untitled.sol', sources[0]['Untitled.sol'], ['TooMuchGas', 'test1', 'test2'])
.clickLaunchIcon('solidityStaticAnalysis')
.click('#staticanalysisView button')
.waitForElementPresent('#staticanalysisresult .warning', 2000, true, function () {

@ -45,8 +45,8 @@ module.exports = {
'Async/Await Script': function (browser: NightwatchBrowser) {
browser
.addFile('asyncAwait.js', { content: asyncAwait })
.openFile('browser/asyncAwait.js')
.executeScript('remix.execute(\'browser/asyncAwait.js\')')
.openFile('asyncAwait.js')
.executeScript('remix.execute(\'asyncAwait.js\')')
.journalLastChild('Waiting Promise')
.pause(5500)
.journalLastChild('result - Promise Resolved')
@ -55,9 +55,9 @@ module.exports = {
'Call Remix File Manager from a script': function (browser: NightwatchBrowser) {
browser
.addFile('asyncAwaitWithFileManagerAccess.js', { content: asyncAwaitWithFileManagerAccess })
.openFile('browser/asyncAwaitWithFileManagerAccess.js')
.openFile('asyncAwaitWithFileManagerAccess.js')
.pause(5000)
.executeScript('remix.execute(\'browser/asyncAwaitWithFileManagerAccess.js\')')
.executeScript('remix.execute(\'asyncAwaitWithFileManagerAccess.js\')')
.pause(6000)
.journalLastChildIncludes('contract Ballot {')
},
@ -86,21 +86,21 @@ module.exports = {
browser
.click('*[data-id="terminalClearConsole"]') // clear the terminal
.addFile('resolveExternalUrlAndSave.js', { content: resolveExternalUrlAndSave })
.openFile('browser/resolveExternalUrlAndSave.js')
.openFile('resolveExternalUrlAndSave.js')
.pause(1000)
.executeScript('remix.execute(\'browser/resolveExternalUrlAndSave.js\')')
.executeScript('remix.execute(\'resolveExternalUrlAndSave.js\')')
.pause(6000)
.journalLastChildIncludes('Implementation of the {IERC20} interface.')
.openFile('browser/github/OpenZeppelin/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol')
.openFile('github/OpenZeppelin/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol')
},
'Call Remix File Resolver (internal URL) from a script': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="terminalClearConsole"]') // clear the terminal
.addFile('resolveUrl.js', { content: resolveUrl })
.openFile('browser/resolveUrl.js')
.openFile('resolveUrl.js')
.pause(1000)
.executeScript('remix.execute(\'browser/resolveUrl.js\')')
.executeScript('remix.execute(\'resolveUrl.js\')')
.pause(6000)
.journalLastChildIncludes('contract Ballot {')
},
@ -109,12 +109,12 @@ module.exports = {
browser
.click('*[data-id="terminalClearConsole"]') // clear the terminal
.addFile('resolveExternalUrlAndSaveToaPath.js', { content: resolveExternalUrlAndSaveToaPath })
.openFile('browser/resolveExternalUrlAndSaveToaPath.js')
.openFile('resolveExternalUrlAndSaveToaPath.js')
.pause(1000)
.executeScript('remix.execute(\'browser/resolveExternalUrlAndSaveToaPath.js\')')
.executeScript('remix.execute(\'resolveExternalUrlAndSaveToaPath.js\')')
.pause(6000)
.journalLastChildIncludes('abstract contract ERC20Burnable')
.openFile('browser/github/newFile.sol')
.openFile('github/newFile.sol')
.end()
},
@ -151,7 +151,7 @@ const asyncAwaitWithFileManagerAccess = `
var run = async () => {
console.log('Waiting Promise')
var result = await p()
let text = await remix.call('fileManager', 'readFile', 'browser/contracts/3_Ballot.sol')
let text = await remix.call('fileManager', 'readFile', 'contracts/3_Ballot.sol')
console.log('result - ', text)
}
@ -184,7 +184,7 @@ const resolveUrl = `
(async () => {
try {
console.log('start')
console.log(await remix.call('contentImport', 'resolveAndSave', 'browser/contracts/3_Ballot.sol'))
console.log(await remix.call('contentImport', 'resolveAndSave', 'contracts/3_Ballot.sol'))
} catch (e) {
console.log(e.message)
}

@ -12,7 +12,7 @@ module.exports = {
},
'Execute Simple Contract and Test Terminal': function (browser: NightwatchBrowser) {
browser.testContracts('Untitled.sol', sources[0]['browser/Untitled.sol'], ['TestContract'])
browser.testContracts('Untitled.sol', sources[0]['Untitled.sol'], ['TestContract'])
.clickLaunchIcon('udapp')
.selectAccount('0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c') // this account will be used for this test suite
.click('#runTabView button[class^="instanceButton"]')
@ -21,19 +21,17 @@ module.exports = {
.click('#runTabView .instance div[class^="title"]')
.click('#runTabView .instance div[class^="title"]')
.clickFunction('f - transact (not payable)')
.testFunction('0x38bb944fa4709ed9e163d6c670259f97284b4defd916d512a2fcc3f35bb53e03',
.testFunction('last',
{
status: 'true Transaction mined and execution succeed',
'transaction hash': '0x38bb944fa4709ed9e163d6c670259f97284b4defd916d512a2fcc3f35bb53e03',
'decoded output': { 0: 'uint256: 8' }
})
.pause(500)
.checkTerminalFilter('0x12332162e2e31397dc1e07ed0a1cf08f728e9b4487c6f9ed79d2f39410c92782', '')
.clickFunction('g - transact (not payable)')
.testFunction('0xab4f794ca0b531f27fc6eace623666b440facbf20e77615a057d728c67b500f0',
.testFunction('last',
{
status: 'true Transaction mined and execution succeed',
'transaction hash': '0xab4f794ca0b531f27fc6eace623666b440facbf20e77615a057d728c67b500f0',
'decoded output': {
0: 'uint256: 345',
1: 'string: comment_comment_',
@ -45,16 +43,15 @@ module.exports = {
},
'Test Complex Return Values': function (browser: NightwatchBrowser) {
browser.testContracts('returnValues.sol', sources[1]['browser/returnValues.sol'], ['testReturnValues'])
browser.testContracts('returnValues.sol', sources[1]['returnValues.sol'], ['testReturnValues'])
.clickLaunchIcon('udapp')
.click('#runTabView button[class^="instanceButton"]')
.waitForElementPresent('.instance:nth-of-type(2)')
.click('.instance:nth-of-type(2) > div > button')
.clickFunction('retunValues1 - transact (not payable)')
.testFunction('0x09c6716a67f0f8c7a0ca2b3ddf59c25982da856a95aefd640b767f9b9feee39d',
.testFunction('last',
{
status: 'true Transaction mined and execution succeed',
'transaction hash': '0x09c6716a67f0f8c7a0ca2b3ddf59c25982da856a95aefd640b767f9b9feee39d',
'decoded output': {
0: 'bool: _b true',
1: 'uint256: _u 345',
@ -63,10 +60,9 @@ module.exports = {
}
})
.clickFunction('retunValues2 - transact (not payable)')
.testFunction('0xe884953e0695399d60914af3e1ea2dad59fe41f3c0c20665c130fa40dd0fb6bf',
.testFunction('last',
{
status: 'true Transaction mined and execution succeed',
'transaction hash': '0xe884953e0695399d60914af3e1ea2dad59fe41f3c0c20665c130fa40dd0fb6bf',
'decoded output': {
0: 'bytes1: _b 0x12',
1: 'bytes2: _b2 0x1223',
@ -81,10 +77,9 @@ module.exports = {
}
}).pause(500)
.clickFunction('retunValues3 - transact (not payable)')
.testFunction('0xb4108649d5e65a4a0776d6ac98c2c356540a7e99d641705a82352a845d467eb5',
.testFunction('last',
{
status: 'true Transaction mined and execution succeed',
'transaction hash': '0xb4108649d5e65a4a0776d6ac98c2c356540a7e99d641705a82352a845d467eb5',
'decoded output': {
0: 'uint8: _en 2',
1: 'int256[5][]: _a1 1,-45,-78,56,60,-1,42,334,-45455,-446,1,10,-5435,45,-7'
@ -93,16 +88,15 @@ module.exports = {
},
'Test Complex Input Values': function (browser: NightwatchBrowser) {
browser.testContracts('inputValues.sol', sources[2]['browser/inputValues.sol'], ['test'])
browser.testContracts('inputValues.sol', sources[2]['inputValues.sol'], ['test'])
.clickLaunchIcon('udapp')
.click('#runTabView button[class^="instanceButton"]')
.waitForElementPresent('.instance:nth-of-type(2)')
.click('.instance:nth-of-type(2) > div > button')
.clickFunction('inputValue1 - transact (not payable)', { types: 'uint256 _u, int256 _i, string _str', values: '"2343242", "-4324324", "string _ string _ string _ string _ string _ string _ string _ string _ string _ string _"' })
.testFunction('0xe9678b5486674a0425301a1d7e925c22cfb9f7f7ec6242697d742009f7ef5b97',
.testFunction('last',
{
status: 'true Transaction mined and execution succeed',
'transaction hash': '0xe9678b5486674a0425301a1d7e925c22cfb9f7f7ec6242697d742009f7ef5b97',
'decoded output': {
0: 'uint256: _uret 2343242',
1: 'int256: _iret -4324324',
@ -111,9 +105,8 @@ module.exports = {
})
.pause(500)
.clickFunction('inputValue2 - transact (not payable)', { types: 'uint256[3] _n, bytes8[4] _b8', values: '[1,2,3], ["0x1234000000000000", "0x1234000000000000","0x1234000000000000","0x1234000000000000"]' })
.testFunction('0x21724b08c3699bda8375803f8dc842194aea370f2aac284e55144b452dca321f', {
.testFunction('last', {
status: 'true Transaction mined and execution succeed',
'transaction hash': '0x21724b08c3699bda8375803f8dc842194aea370f2aac284e55144b452dca321f',
'decoded output': {
0: 'uint256[3]: _nret 1,2,3',
1: 'bytes8[4]: _b8ret 0x1234000000000000,0x1234000000000000,0x1234000000000000,0x1234000000000000'
@ -140,7 +133,7 @@ module.exports = {
},
'Should Compile and Deploy a contract which has an event declaring a function as parameter': function (browser: NightwatchBrowser) {
browser.testContracts('eventFunctionInput.sol', sources[3]['browser/eventFunctionInput.sol'], ['C'])
browser.testContracts('eventFunctionInput.sol', sources[3]['eventFunctionInput.sol'], ['C'])
.clickLaunchIcon('udapp')
.selectAccount('0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c') // this account will be used for this test suite
.click('#runTabView button[class^="instanceButton"]')
@ -155,7 +148,7 @@ module.exports = {
const sources = [
{
'browser/Untitled.sol': {
'Untitled.sol': {
content: `
contract TestContract { function f() public returns (uint) { return 8; }
function g() public returns (uint, string memory, bool, uint) {
@ -167,7 +160,7 @@ const sources = [
}
},
{
'browser/returnValues.sol': {
'returnValues.sol': {
content: `
contract testReturnValues {
enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill }
@ -202,7 +195,7 @@ const sources = [
}
},
{
'browser/inputValues.sol': {
'inputValues.sol': {
content: `
contract test {
event event1(int _i, uint indexed _u, string indexed _str, bytes4 _b, string _notIndexed);
@ -221,7 +214,7 @@ const sources = [
},
// https://github.com/ethereum/remix-project/issues/404
{
'browser/eventFunctionInput.sol': {
'eventFunctionInput.sol': {
content: `
pragma solidity >= 0.7.0;
contract C {

@ -5,8 +5,8 @@ import sauce from './sauce'
import examples from '../examples/example-contracts'
const sources = [
{ 'browser/Untitled.sol': { content: examples.ballot.content } },
{ 'browser/Untitled1.sol': { content: 'contract test {}' } }
{ 'Untitled.sol': { content: examples.ballot.content } },
{ 'Untitled1.sol': { content: 'contract test {}' } }
]
module.exports = {
@ -21,7 +21,7 @@ module.exports = {
browser
.waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000)
.clickLaunchIcon('solidity')
.testContracts('Untitled.sol', sources[0]['browser/Untitled.sol'], ['Ballot'])
.testContracts('Untitled.sol', sources[0]['Untitled.sol'], ['Ballot'])
.clickLaunchIcon('udapp')
.selectAccount('0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c')
.setValue('input[placeholder="bytes32[] proposalNames"]', '["0x48656c6c6f20576f726c64210000000000000000000000000000000000000000"]')
@ -29,21 +29,19 @@ module.exports = {
.waitForElementPresent('*[data-id="universalDappUiContractActionWrapper"]')
.click('*[data-id="universalDappUiTitleExpander"]')
.clickFunction('delegate - transact (not payable)', { types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"' })
.testFunction('0x41fab8ea5b1d9fba5e0a6545ca1a2d62fff518578802c033c2b9a031a01c31b3',
.testFunction('last',
{
status: 'true Transaction mined and execution succeed',
'transaction hash': '0x41fab8ea5b1d9fba5e0a6545ca1a2d62fff518578802c033c2b9a031a01c31b3',
'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' }
})
.clickLaunchIcon('solidity')
.testContracts('Untitled1.sol', sources[1]['browser/Untitled1.sol'], ['test'])
.testContracts('Untitled1.sol', sources[1]['Untitled1.sol'], ['test'])
.clickLaunchIcon('udapp')
.clickFunction('delegate - transact (not payable)', { types: 'address to', values: '' })
.pause(5000)
.testFunction('0xca58080c8099429caeeffe43b8104df919c2c543dceb9edf9242fa55f045c803',
.testFunction('last',
{
status: 'false Transaction mined but execution failed',
'transaction hash': '0xca58080c8099429caeeffe43b8104df919c2c543dceb9edf9242fa55f045c803',
'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' }
})
.end()

@ -6,7 +6,7 @@ import sauce from './sauce'
import examples from '../examples/example-contracts'
const sources = [
{ 'browser/Untitled.sol': { content: examples.ballot.content } }
{ 'Untitled.sol': { content: examples.ballot.content } }
]
module.exports = {

@ -5,7 +5,7 @@ import sauce from './sauce'
const sources = [
{
'browser/basic.sol': {
'basic.sol': {
content:
`pragma solidity >=0.2.0 <0.7.0;
@ -31,7 +31,7 @@ module.exports = {
browser
.waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000)
.clickLaunchIcon('fileExplorers')
.addFile('basic.sol', sources[0]['browser/basic.sol'])
.addFile('basic.sol', sources[0]['basic.sol'])
.clickLaunchIcon('solidity')
.execute(function () {
const elem = document.getElementById('nightlies') as HTMLInputElement

@ -26,6 +26,28 @@ module.exports = {
'Home page should be deactivated': function (browser: NightwatchBrowser) {
browser
.waitForElementNotPresent('[data-id="landingPageHomeContainer"]')
},
'Should create two workspace and switch to the first one': function (browser: NightwatchBrowser) {
browser
.clickLaunchIcon('fileExplorers')
.click('*[data-id="workspaceCreate"]') // create workspace_name
.waitForElementVisible('*[data-id="modalDialogCustomPromptText"]')
.clearValue('*[data-id="modalDialogCustomPromptText"]')
.setValue('*[data-id="modalDialogCustomPromptText"]', 'workspace_name')
.modalFooterOKClick()
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtests"]')
.addFile('test.sol', { content: 'test' })
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtest.sol"]')
.click('*[data-id="workspaceCreate"]') // create workspace_name_1
.waitForElementVisible('*[data-id="modalDialogCustomPromptText"]')
.clearValue('*[data-id="modalDialogCustomPromptText"]')
.setValue('*[data-id="modalDialogCustomPromptText"]', 'workspace_name_1')
.modalFooterOKClick()
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtests"]')
.waitForElementNotPresent('*[data-id="treeViewLitreeViewItemtest.sol"]')
.click('*[data-id="workspacesSelect"] option[value="workspace_name"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtests"]')
.end()
},

@ -55,6 +55,7 @@ declare module "nightwatch" {
validateValueInput(selector: string, valueTosSet: string, expectedValue: string): NightwatchBrowser
checkAnnotations(type: string, line: number): NightwatchBrowser
checkAnnotationsNotPresent(type: string): NightwatchBrowser
getLastTransactionHash(callback: (hash: string) => void)
}
export interface NightwatchBrowser {

@ -9,7 +9,6 @@ soljson.js.*
npm-debug.log*
remix
.DS_Store
contracts
TODO
.tern-port
temp_publish_docker

@ -18,7 +18,7 @@ import { LandingPage } from './app/ui/landing-page/landing-page'
import { MainPanel } from './app/components/main-panel'
import FetchAndCompile from './app/compiler/compiler-sourceVerifier-fetchAndCompile'
import migrateFileSystem from './migrateFileSystem'
import migrateFileSystem, { migrateToWorkspace } from './migrateFileSystem'
var isElectron = require('is-electron')
var csjs = require('csjs-inject')
@ -28,14 +28,13 @@ var registry = require('./global/registry')
var loadFileFromParent = require('./loadFilesFromParent')
var { OffsetToLineColumnConverter } = require('./lib/offsetToLineColumnConverter')
var QueryParams = require('./lib/query-params')
var GistHandler = require('./lib/gist-handler')
var Storage = remixLib.Storage
var RemixDProvider = require('./app/files/remixDProvider')
var Config = require('./config')
var examples = require('./app/editor/examples')
var modalDialogCustom = require('./app/ui/modal-dialog-custom')
var FileManager = require('./app/files/fileManager')
var FileProvider = require('./app/files/fileProvider')
var WorkspaceFileProvider = require('./app/files/workspaceFileProvider')
var toolTip = require('./app/ui/tooltip')
var CompilerMetadata = require('./app/files/compiler-metadata')
var CompilerImport = require('./app/compiler/compiler-imports')
@ -145,6 +144,9 @@ class App {
registry.put({ api: self._components.filesProviders.browser, name: 'fileproviders/browser' })
self._components.filesProviders.localhost = new RemixDProvider(self.appManager)
registry.put({ api: self._components.filesProviders.localhost, name: 'fileproviders/localhost' })
self._components.filesProviders.workspace = new WorkspaceFileProvider()
registry.put({ api: self._components.filesProviders.workspace, name: 'fileproviders/workspace' })
registry.put({ api: self._components.filesProviders, name: 'fileproviders' })
migrateFileSystem(self._components.filesProviders.browser)
@ -438,29 +440,8 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
// get the file list from the parent iframe
loadFileFromParent(fileManager)
// get the file from gist
const gistHandler = new GistHandler()
const loadedFromGist = gistHandler.loadFromGist(params, fileManager)
if (!loadedFromGist) {
// insert example contracts if there are no files to show
self._components.filesProviders.browser.resolveDirectory('/', (error, filesList) => {
if (error) console.error(error)
if (Object.keys(filesList).length === 0) {
for (const file in examples) {
fileManager.writeFile(examples[file].name, examples[file].content)
}
}
})
}
migrateToWorkspace(fileManager)
if (params.code) {
try {
const path = 'browser/.code-sample/contract.sol'
await fileManager.writeFile(path, atob(params.code))
await fileManager.openFile(path)
} catch (e) {
console.error(e)
}
}
filePanel.initWorkspace()
if (params.embed) framingService.embed()
}

@ -77,7 +77,7 @@ module.exports = class CompilerImports extends Plugin {
}
cb(null, content, cleanUrl, type, url)
} catch (e) {
return cb('Unable to import url : ' + e.message)
return cb(new Error('not found ' + url))
}
}
@ -88,9 +88,9 @@ module.exports = class CompilerImports extends Plugin {
(error, content, cleanUrl, type, url) => {
if (error) return cb(error)
if (this.fileManager) {
const browser = this.fileManager.fileProviderOf('browser/')
const workspace = this.fileManager.getProvider('workspace')
const path = targetPath || type + '/' + cleanUrl
if (browser) browser.addExternal(path, content, url)
if (workspace) workspace.addExternal(path, content, url)
}
cb(null, content)
})
@ -123,7 +123,6 @@ module.exports = class CompilerImports extends Plugin {
}
provider.exists(url, (error, exist) => {
if (error) return reject(error)
if (!exist && provider.type === 'localhost') return reject(new Error(`not found ${url}`))
/*
if the path is absolute and the file does not exist, we can stop here

@ -355,7 +355,6 @@ class Editor extends Plugin {
- URL prepended with "browser"
- URL not prepended with the file explorer. We assume (as it is in the whole app, that this is a "browser" URL
*/
if (!path.startsWith('localhost') && !path.startsWith('browser')) path = `browser/${path}`
if (!this.sessions[path]) {
const session = this._createSession(content, this._getMode(path))
this.sessions[path] = session

@ -1,6 +1,7 @@
'use strict'
import { Plugin } from '@remixproject/engine'
import * as packageJson from '../../../../../package.json'
import { joinPath } from '../../lib/helper'
var CompilerAbstract = require('../compiler/compiler-abstract')
const profile = {
@ -21,11 +22,11 @@ class CompilerMetadata extends Plugin {
}
_JSONFileName (path, contractName) {
return path + '/' + this.innerPath + '/' + contractName + '.json'
return joinPath(path, this.innerPath, contractName + '.json')
}
_MetadataFileName (path, contractName) {
return path + '/' + this.innerPath + '/' + contractName + '_metadata' + '.json'
return joinPath(path, this.innerPath, contractName + '_metadata.json')
}
onActivation () {
@ -33,9 +34,9 @@ class CompilerMetadata extends Plugin {
this.on('solidity', 'compilationFinished', (file, source, languageVersion, data) => {
if (!self.config.get('settings/generate-contract-metadata')) return
const compiler = new CompilerAbstract(languageVersion, data, source)
var provider = self.fileManager.currentFileProvider()
var path = self.fileManager.currentPath()
if (provider && path) {
var provider = self.fileManager.fileProviderOf(source.target)
var path = self.fileManager.extractPathOf(source.target)
if (provider) {
compiler.visitContracts((contract) => {
if (contract.file !== source.target) return
@ -117,7 +118,7 @@ class CompilerMetadata extends Plugin {
path = this.fileManager.currentPath()
}
if (provider && path) {
if (provider) {
this.blockchain.detectNetwork((err, { id, name } = {}) => {
if (err) {
console.log(err)

@ -506,7 +506,7 @@ fileExplorer.prototype.toGist = function (id) {
}
// If 'id' is not defined, it is not a gist update but a creation so we have to take the files from the browser explorer.
const folder = id ? 'browser/gists/' + id : 'browser/'
const folder = id ? '/gists/' + id : '/'
this.packageFiles(this.files, folder, (error, packaged) => {
if (error) {
console.log(error)
@ -596,7 +596,7 @@ fileExplorer.prototype.packageFiles = function (filesProvider, directory, callba
})
}
fileExplorer.prototype.createNewFile = function (parentFolder = 'browser') {
fileExplorer.prototype.createNewFile = function (parentFolder = '/') {
const self = this
modalDialogCustom.prompt('Create new file', 'File Name (e.g Untitled.sol)', 'Untitled.sol', (input) => {
if (!input) input = 'New file'

@ -39,6 +39,7 @@ const createError = (err) => {
class FileManager extends Plugin {
constructor (editor, appManager) {
super(profile)
this.mode = 'browser'
this.openedFiles = {} // list all opened files
this.events = new EventEmitter()
this.editor = editor
@ -48,6 +49,10 @@ class FileManager extends Plugin {
this.init()
}
setMode (mode) {
this.mode = mode
}
/**
* Emit error if path doesn't exist
* @param {string} path path of the file/directory
@ -265,6 +270,7 @@ class FileManager extends Plugin {
config: this._components.registry.get('config').api,
browserExplorer: this._components.registry.get('fileproviders/browser').api,
localhostExplorer: this._components.registry.get('fileproviders/localhost').api,
workspaceExplorer: this._components.registry.get('fileproviders/workspace').api,
filesProviders: this._components.registry.get('fileproviders').api
}
this._deps.browserExplorer.event.register('fileChanged', (path) => { this.fileChangedEvent(path) })
@ -275,6 +281,11 @@ class FileManager extends Plugin {
this._deps.localhostExplorer.event.register('fileRemoved', (path) => { this.fileRemovedEvent(path) })
this._deps.localhostExplorer.event.register('errored', (event) => { this.removeTabsOf(this._deps.localhostExplorer) })
this._deps.localhostExplorer.event.register('closed', (event) => { this.removeTabsOf(this._deps.localhostExplorer) })
this._deps.workspaceExplorer.event.register('fileChanged', (path) => { this.fileChangedEvent(path) })
this._deps.workspaceExplorer.event.register('fileRenamed', (oldName, newName, isFolder) => { this.fileRenamedEvent(oldName, newName, isFolder) })
this._deps.workspaceExplorer.event.register('fileRemoved', (path) => { this.fileRemovedEvent(path) })
this._deps.workspaceExplorer.event.register('fileAdded', (path) => { this.fileAddedEvent(path) })
this.getCurrentFile = this.file
this.getFile = this.readFile
this.getFolder = this.readdir
@ -349,7 +360,7 @@ class FileManager extends Plugin {
extractPathOf (file) {
var reg = /(.*)(\/).*/
var path = reg.exec(file)
return path ? path[1] : null
return path ? path[1] : '/'
}
getFileContent (path) {
@ -468,18 +479,8 @@ class FileManager extends Plugin {
}
if (file) return _openFile(file)
else {
var browserProvider = this._deps.filesProviders.browser
browserProvider.resolveDirectory('browser', (error, filesProvider) => {
if (error) console.error(error)
var fileList = Object.keys(filesProvider)
if (fileList.length) {
_openFile(browserProvider.type + '/' + fileList[0])
} else {
// TODO: Only keep `this.emit` (issue#2210)
this.emit('noFileSelected')
this.events.emit('noFileSelected')
}
})
this.emit('noFileSelected')
this.events.emit('noFileSelected')
}
}
@ -488,10 +489,13 @@ class FileManager extends Plugin {
}
fileProviderOf (file) {
if (file.indexOf('localhost') === 0) {
if (file.startsWith('localhost') || this.mode === 'localhost') {
return this._deps.filesProviders.localhost
}
return this._deps.filesProviders.browser
if (file.startsWith('browser')) {
return this._deps.filesProviders.browser
}
return this._deps.filesProviders.workspace
}
// returns the list of directories inside path
@ -501,10 +505,8 @@ class FileManager extends Plugin {
return new Promise((resolve, reject) => {
this.readdir(path).then((ls) => {
const promises = Object.keys(ls).map((item, index) => {
const root = (path.indexOf('/') === -1) ? path : path.substr(0, path.indexOf('/'))
const curPath = `${root}/${item}` // adding 'browser' or 'localhost'
if (ls[item].isDirectory && !dirPaths.includes(curPath)) {
dirPaths.push(curPath)
if (ls[item].isDirectory && !dirPaths.includes(item)) {
dirPaths.push(item)
resolve(dirPaths)
}
return new Promise((resolve, reject) => { resolve() })
@ -579,6 +581,14 @@ class FileManager extends Plugin {
if (callback) callback(error)
})
}
async createWorkspace (name) {
const workspaceProvider = this._deps.filesProviders.workspace
const workspacePath = 'browser/' + workspaceProvider.workspacesPath + '/' + name
const workspaceRootPath = 'browser/' + workspaceProvider.workspacesPath
if (!this.exists(workspaceRootPath)) await this.mkdir(workspaceRootPath)
if (!this.exists(workspacePath)) await this.mkdir(workspacePath)
}
}
module.exports = FileManager

@ -193,6 +193,39 @@ class FileProvider {
})
}
/**
* copy the folder recursively
* @param {string} path is the folder to be copied over
* @param {string} destination is the destination folder
*/
copyFolderToJson (path) {
return new Promise((resolve, reject) => {
const json = {}
path = this.removePrefix(path)
if (window.remixFileSystem.existsSync(path)) {
try {
const items = window.remixFileSystem.readdirSync(path)
if (items.length !== 0) {
items.forEach(async (item, index) => {
const file = {}
const curPath = `${path}${path.endsWith('/') ? '' : '/'}${item}`
if (window.remixFileSystem.statSync(curPath).isDirectory()) {
file.children = await this.copyFolderToJson(curPath)
} else {
file.content = window.remixFileSystem.readFileSync(curPath, 'utf8')
}
json[curPath] = file
})
}
} catch (e) {
console.log(e)
return reject(e)
}
}
return resolve(json)
})
}
removeFile (path) {
path = this.removePrefix(path)
if (window.remixFileSystem.existsSync(path) && !window.remixFileSystem.statSync(path).isDirectory()) {
@ -227,6 +260,8 @@ class FileProvider {
if (files) {
files.forEach(element => {
path = path.replace(/^\/|\/$/g, '') // remove first and last slash
element = element.replace(/^\/|\/$/g, '') // remove first and last slash
const absPath = (path === '/' ? '' : path) + '/' + element
ret[absPath.indexOf('/') === 0 ? absPath.substr(1, absPath.length) : absPath] = { isDirectory: window.remixFileSystem.statSync(absPath).isDirectory() }
// ^ ret does not accept path starting with '/'
@ -243,7 +278,6 @@ class FileProvider {
}
_normalizePath (path) {
if (path.indexOf('/') !== 0) path = '/' + path
return this.type + path
}
}

@ -23,23 +23,23 @@ module.exports = class RemixDProvider {
})
this._appManager.on('remixd', 'folderAdded', (path) => {
this.event.trigger('folderAdded', [this.addPrefix(path)])
this.event.trigger('folderAdded', [path])
})
this._appManager.on('remixd', 'fileAdded', (path) => {
this.event.trigger('fileAdded', [this.addPrefix(path)])
this.event.trigger('fileAdded', [path])
})
this._appManager.on('remixd', 'fileChanged', (path) => {
this.event.trigger('fileChanged', [this.addPrefix(path)])
this.event.trigger('fileChanged', [path])
})
this._appManager.on('remixd', 'fileRemoved', (path) => {
this.event.trigger('fileRemoved', [this.addPrefix(path)])
this.event.trigger('fileRemoved', [path])
})
this._appManager.on('remixd', 'fileRenamed', (oldPath, newPath) => {
this.event.trigger('fileRemoved', [this.addPrefix(oldPath), this.addPrefix(newPath)])
this.event.trigger('fileRemoved', [oldPath, newPath])
})
this._appManager.on('remixd', 'rootFolderChanged', () => {
@ -136,7 +136,7 @@ module.exports = class RemixDProvider {
const unprefixedpath = this.removePrefix(path)
this._appManager.call('remixd', 'remove', { path: unprefixedpath })
.then(result => {
const path = this.type + '/' + unprefixedpath
const path = unprefixedpath
delete this.filesContent[path]
resolve(true)
@ -154,8 +154,8 @@ module.exports = class RemixDProvider {
if (!this._isReady) return new Promise((resolve, reject) => reject(new Error('provider not ready')))
return this._appManager.call('remixd', 'rename', { oldPath: unprefixedoldPath, newPath: unprefixednewPath })
.then(result => {
const newPath = this.type + '/' + unprefixednewPath
const oldPath = this.type + '/' + unprefixedoldPath
const newPath = unprefixednewPath
const oldPath = unprefixedoldPath
this.filesContent[newPath] = this.filesContent[oldPath]
delete this.filesContent[oldPath]
@ -181,12 +181,6 @@ module.exports = class RemixDProvider {
return path
}
addPrefix (path) {
if (path.indexOf(this.type + '/') === 0) return path
if (path[0] === '/') return 'localhost' + path
return 'localhost/' + path
}
resolveDirectory (path, callback) {
var self = this
if (path[0] === '/') path = path.substring(1)

@ -51,8 +51,8 @@ export class RemixdHandle extends WebsocketPlugin {
}
async canceled () {
this.call('manager', 'deactivatePlugin', 'remixd')
this.call('manager', 'deactivatePlugin', 'git')
this.call('manager', 'deactivatePlugin', 'remixd')
}
/**

@ -0,0 +1,45 @@
'use strict'
const FileProvider = require('./fileProvider')
class WorkspaceFileProvider extends FileProvider {
constructor () {
super('')
this.workspacesPath = '.workspaces'
}
setWorkspace (workspace) {
workspace = workspace.replace(/^\/|\/$/g, '') // remove first and last slash
this.workspace = workspace
}
clearWorkspace () {
this.workspace = null
}
removePrefix (path) {
path = path.replace(/^\/|\/$/g, '') // remove first and last slash
if (path.startsWith(this.workspacesPath + '/' + this.workspace)) return path
if (path.startsWith(this.workspace)) return this.workspacesPath + '/' + this.workspace
path = super.removePrefix(path)
const ret = this.workspacesPath + '/' + this.workspace + '/' + (path === '/' ? '' : path)
return ret.replace(/^\/|\/$/g, '')
}
resolveDirectory (path, callback) {
super.resolveDirectory(path, (error, files) => {
if (error) return callback(error)
const unscoped = {}
for (const file in files) {
unscoped[file.replace(this.workspacesPath + '/' + this.workspace + '/', '')] = files[file]
}
callback(null, unscoped)
})
}
_normalizePath (path) {
return path.replace(this.workspacesPath + '/' + this.workspace + '/', '')
}
}
module.exports = WorkspaceFileProvider

@ -5,12 +5,16 @@ import React from 'react' // eslint-disable-line
import ReactDOM from 'react-dom'
import { FileExplorer } from '@remix-ui/file-explorer' // eslint-disable-line
import './styles/file-panel-styles.css'
var ethutil = require('ethereumjs-util')
var yo = require('yo-yo')
var EventManager = require('../../lib/events')
// var FileExplorer = require('../files/file-explorer')
var { RemixdHandle } = require('../files/remixd-handle.js')
var { GitHandle } = require('../files/git-handle.js')
var globalRegistry = require('../../global/registry')
var examples = require('../editor/examples')
var GistHandler = require('../../lib/gist-handler')
var QueryParams = require('../../lib/query-params')
const modalDialog = require('../ui/modal-dialog-custom')
var canUpload = window.File || window.FileReader || window.FileList || window.Blob
@ -34,8 +38,8 @@ var canUpload = window.File || window.FileReader || window.FileList || window.Bl
const profile = {
name: 'fileExplorers',
displayName: 'File explorers',
methods: ['createNewFile', 'uploadFile'],
events: [],
methods: ['createNewFile', 'uploadFile', 'getCurrentWorkspace', 'getWorkspaces', 'createWorkspace'],
events: ['setWorkspace', 'renameWorkspace', 'deleteWorkspace'],
icon: 'assets/img/fileManager.webp',
description: ' - ',
kind: 'fileexplorer',
@ -54,13 +58,18 @@ module.exports = class Filepanel extends ViewPlugin {
fileManager: this._components.registry.get('filemanager').api,
config: this._components.registry.get('config').api
}
this.LOCALHOST = ' - connect to localhost - '
this.NO_WORKSPACE = ' - none - '
this.hideRemixdExplorer = true
this.remixdExplorer = {
hide: () => {
if (this.currentWorkspace === this.LOCALHOST) this.setWorkspace(this.NO_WORKSPACE)
this._deps.fileManager.setMode('browser')
this.hideRemixdExplorer = true
this.renderComponent()
},
show: () => {
this._deps.fileManager.setMode('localhost')
this.hideRemixdExplorer = false
this.renderComponent()
}
@ -93,9 +102,64 @@ module.exports = class Filepanel extends ViewPlugin {
this.remixdExplorer.hide()
})
this.currentWorkspace = null
const workspacesPath = this._deps.fileProviders.workspace.workspacesPath
this._deps.fileProviders.browser.resolveDirectory('/' + workspacesPath, (error, fileTree) => {
if (error) return console.error(error)
this.setWorkspace(Object.keys(fileTree)[0].replace(workspacesPath + '/', ''))
})
this.renderComponent()
}
async initWorkspace () {
const workspacesPath = this._deps.fileProviders.workspace.workspacesPath
const queryParams = new QueryParams()
const params = queryParams.get()
// get the file from gist
const gistHandler = new GistHandler()
const loadedFromGist = gistHandler.loadFromGist(params, this._deps.fileManager)
if (loadedFromGist) return
if (params.code) {
try {
await this._deps.fileManager.createWorkspace('code-sample')
var hash = ethutil.bufferToHex(ethutil.keccak(params.code))
const fileName = 'contract-' + hash.replace('0x', '').substring(0, 10) + '.sol'
const path = 'browser/' + workspacesPath + '/code-sample/' + fileName
await this._deps.fileManager.writeFile(path, atob(params.code))
this.setWorkspace('code-sample')
await this._deps.fileManager.openFile(path)
} catch (e) {
console.error(e)
}
return
}
// insert example contracts if there are no files to show
this._deps.fileProviders.browser.resolveDirectory('/', async (error, filesList) => {
if (error) console.error(error)
if (Object.keys(filesList).length === 0) {
for (const file in examples) {
await this._deps.fileManager.writeFile('browser/' + workspacesPath + '/default_workspace/' + examples[file].name, examples[file].content)
}
this.setWorkspace('default_workspace')
}
})
}
async refreshWorkspacesList () {
if (!document.getElementById('workspacesSelect')) return
const workspaces = await this.getWorkspaces()
workspaces.push(this.LOCALHOST)
workspaces.push(this.NO_WORKSPACE)
ReactDOM.render(
(
workspaces
.map((folder) => {
return <option selected={this.currentWorkspace === folder} value={folder}>{folder}</option>
})), document.getElementById('workspacesSelect')
)
}
resetFocus (value) {
this.reset = value
this.renderComponent()
@ -125,6 +189,40 @@ module.exports = class Filepanel extends ViewPlugin {
return this.el
}
getWorkspaces () {
return new Promise((resolve, reject) => {
const workspacesPath = this._deps.fileProviders.workspace.workspacesPath
this._deps.fileProviders.browser.resolveDirectory('/' + workspacesPath, (error, items) => {
if (error) return reject(error)
resolve(Object.keys(items)
.filter((item) => items[item].isDirectory)
.map((folder) => folder.replace(workspacesPath + '/', '')))
})
})
}
getCurrentWorkspace () {
return this.currentWorkspace
}
async setWorkspace (name) {
this._deps.fileManager.removeTabsOf(this._deps.fileProviders.workspace)
this.currentWorkspace = name
if (name === this.LOCALHOST) {
this._deps.fileProviders.workspace.clearWorkspace()
this.call('manager', 'activatePlugin', 'remixd')
} else if (name === this.NO_WORKSPACE) {
this._deps.fileProviders.workspace.clearWorkspace()
} else {
this._deps.fileProviders.workspace.setWorkspace(name)
}
if (name !== this.LOCALHOST && await this.call('manager', 'isActive', 'remixd')) {
this.call('manager', 'deactivatePlugin', 'remixd')
}
this.renderComponent()
this.emit('setWorkspace', { name })
}
/**
*
* @param item { id: string, name: string, type?: string[], path?: string[], extension?: string[], pattern?: string[] }
@ -139,24 +237,107 @@ module.exports = class Filepanel extends ViewPlugin {
this.renderComponent()
}
renameWorkspace () {
modalDialog.prompt('Rename Workspace', 'Please choose a name for the workspace', this.currentWorkspace, async (value) => {
const workspacesPath = this._deps.fileProviders.workspace.workspacesPath
await this._deps.fileManager.rename('browser/' + workspacesPath + '/' + this.currentWorkspace, 'browser/' + workspacesPath + '/' + value)
this.setWorkspace(value)
this.emit('renameWorkspace', { name: value })
})
}
createWorkspace () {
return new Promise((resolve, reject) => {
const workspace = `workspace_${Date.now()}`
modalDialog.prompt('New Workspace', 'Please choose a name for the workspace', workspace, (value) => {
const workspacesPath = this._deps.fileProviders.workspace.workspacesPath
this._deps.fileProviders.browser.createDir(workspacesPath + '/' + value, async () => {
this.setWorkspace(value)
for (const file in examples) {
await this._deps.fileManager.writeFile(`${examples[file].name}`, examples[file].content)
}
resolve(value)
})
}, () => reject(new Error('workspace creation rejected by user')))
})
}
deleteCurrentWorkspace () {
if (!this.currentWorkspace) return
modalDialog.confirm('Delete Workspace', 'Please confirm workspace deletion', () => {
const workspacesPath = this._deps.fileProviders.workspace.workspacesPath
this._deps.fileProviders.browser.remove(workspacesPath + '/' + this.currentWorkspace)
const name = this.currentWorkspace
this.currentWorkspace = null
this.setWorkspace(this.NO_WORKSPACE)
this.renderComponent()
this.emit('deleteWorkspace', { name })
})
}
renderComponent () {
ReactDOM.render(
<div className='remixui_container'>
<div className='remixui_fileexplorer' onClick={() => this.resetFocus(true)}>
<div>
<header>
<div className="mb-2">
<label className="form-check-label" htmlFor="workspacesSelect">
Workspaces
</label>
<span className="remixui_menu">
<span
id='workspaceCreate'
data-id='workspaceCreate'
onClick={(e) => {
e.stopPropagation()
this.createWorkspace()
}}
className='far fa-plus-square remixui_menuicon'
title='Create a new Workspace'>
</span>
<span
hidden={this.currentWorkspace === this.LOCALHOST || this.currentWorkspace === this.NO_WORKSPACE}
id='workspaceRename'
data-id='workspaceRename'
onClick={(e) => {
e.stopPropagation()
this.renameWorkspace()
}}
className='far fa-edit remixui_menuicon'
title='Rename current Workspace'>
</span>
<span
hidden={this.currentWorkspace === this.LOCALHOST || this.currentWorkspace === this.NO_WORKSPACE}
id='workspaceDelete'
data-id='workspaceDelete'
onClick={(e) => {
e.stopPropagation()
this.deleteCurrentWorkspace()
}}
className='fas fa-trash'
title='Delete current Workspace'>
</span>
</span>
<select id="workspacesSelect" data-id="workspacesSelect" onChange={(e) => this.setWorkspace(e.target.value)} className="form-control custom-select">
</select>
</div>
</header>
</div>
<div className='remixui_fileExplorerTree'>
<div>
<div className='pl-2 remixui_treeview' data-id='filePanelFileExplorerTree'>
<FileExplorer
name='browser'
registry={this._components.registry}
filesProvider={this._deps.fileProviders.browser}
menuItems={['createNewFile', 'createNewFolder', 'publishToGist', canUpload ? 'uploadFile' : '']}
plugin={this}
focusRoot={this.reset}
contextMenuItems={this.registeredMenuItems}
displayInput={this.displayNewFile}
externalUploads={this.uploadFileEvent}
/>
{ this.hideRemixdExplorer && this.currentWorkspace && this.currentWorkspace !== this.NO_WORKSPACE &&
<FileExplorer
name={this.currentWorkspace}
registry={this._components.registry}
filesProvider={this._deps.fileProviders.workspace}
menuItems={['createNewFile', 'createNewFolder', 'publishToGist', canUpload ? 'uploadFile' : '']}
plugin={this}
focusRoot={this.reset}
contextMenuItems={this.registeredMenuItems}
/>
}
</div>
<div className='pl-2 filesystemexplorer remixui_treeview'>
{ !this.hideRemixdExplorer &&
@ -171,10 +352,27 @@ module.exports = class Filepanel extends ViewPlugin {
/>
}
</div>
<div className='pl-2 remixui_treeview'>
{ false && <FileExplorer
name='browser'
registry={this._components.registry}
filesProvider={this._deps.fileProviders.browser}
menuItems={['createNewFile', 'createNewFolder', 'publishToGist', canUpload ? 'uploadFile' : '']}
plugin={this}
focusRoot={this.reset}
contextMenuItems={this.registeredMenuItems}
displayInput={this.displayNewFile}
externalUploads={this.uploadFileEvent}
/>
}
</div>
</div>
</div>
</div>
</div>
, this.el)
setTimeout(() => {
this.refreshWorkspacesList()
}, 500)
}
}

@ -54,3 +54,6 @@
margin-bottom: 2em;
word-break: break-word;
}
.remixui_menuicon {
padding-right : 10px;
}

@ -227,6 +227,7 @@ class CompileTab extends ViewPlugin {
* @param {object} settings {evmVersion, optimize, runs, version, language}
*/
async compileWithParameters (compilationTargets, settings) {
settings.version = settings.version || this.compilerContainer.data.selectedVersion
const res = await compile(compilationTargets, settings)
return res
}

@ -35,7 +35,7 @@ module.exports = class TestTab extends ViewPlugin {
this.runningTestsNumber = 0
this.readyTestsNumber = 0
this.areTestsRunning = false
this.defaultPath = 'browser/tests'
this.defaultPath = 'tests'
this.offsetToLineColumnConverter = offsetToLineColumnConverter
appManager.event.on('activate', (name) => {
@ -551,12 +551,17 @@ module.exports = class TestTab extends ViewPlugin {
updateDirList () {
for (var o of this.uiPathList.querySelectorAll('option')) o.remove()
this.uiPathList.appendChild(yo`<option>browser</option>`)
if (this.testTabLogic.isRemixDActive()) this.uiPathList.appendChild(yo`<option>localhost</option>`)
if (!this._view.el) return
this.testTabLogic.dirList(this.inputPath.value).then((options) => {
this.testTabLogic.dirList('/').then((options) => {
options.forEach((path) => this.uiPathList.appendChild(yo`<option>${path}</option>`))
})
/*
It is not possible anymore to see folder from outside of the current workspace
if (this.inputPath.value) {
this.testTabLogic.dirList(this.inputPath.value).then((options) => {
options.forEach((path) => this.uiPathList.appendChild(yo`<option>${path}</option>`))
})
}
*/
}
render () {

@ -5,7 +5,7 @@ const remixPath = require('path')
class TestTabLogic {
constructor (fileManager) {
this.fileManager = fileManager
this.currentPath = 'browser/tests'
this.currentPath = '/tests'
}
setCurrentPath (path) {

@ -22,7 +22,6 @@ function Config (storage) {
}
this.get = function (key) {
this.ensureStorageUpdated(key)
return this.items[key]
}
@ -35,23 +34,6 @@ function Config (storage) {
}
}
this.ensureStorageUpdated = function (key) {
if (key === 'currentFile') {
if (this.items[key] && this.items[key] !== '' &&
this.items[key].indexOf('config/') !== 0 &&
this.items[key].indexOf('browser/') !== 0 &&
this.items[key].indexOf('localhost/') !== 0 &&
this.items[key].indexOf('swarm/') !== 0 &&
this.items[key].indexOf('gist/') !== 0 &&
this.items[key].indexOf('github/') !== 0 &&
this.items[key].indexOf('ipfs/') !== 0 &&
this.items[key].indexOf('http/') !== 0 &&
this.items[key].indexOf('https/') !== 0) {
this.items[key] = 'browser/' + this.items[key]
}
}
}
this.getUnpersistedProperty = function (key) {
return this.unpersistedItems[key]
}

@ -42,25 +42,24 @@ function GistHandler (_window) {
}
this.loadFromGist = (params, fileManager) => {
const gistProvider = fileManager.fileProviderOf('browser')
const self = this
return self.handleLoad(params, function (gistId) {
request.get({
url: `https://api.github.com/gists/${gistId}`,
json: true
}, (error, response, data = {}) => {
}, async (error, response, data = {}) => {
if (error || !data.files) {
modalDialogCustom.alert(`Gist load error: ${error || data.message}`)
return
}
const obj = {}
Object.keys(data.files).forEach((element) => {
obj['/gists/' + gistId + '/' + element] = data.files[element]
obj['/' + gistId + '/' + element] = data.files[element]
})
fileManager.setBatchFiles(obj, 'browser', true, (errorLoadingFile) => {
fileManager.setBatchFiles(obj, 'workspace', true, (errorLoadingFile) => {
if (!errorLoadingFile) {
gistProvider.id = gistId
gistProvider.origGistFiles = data.files
const provider = fileManager.getProvider('workspace')
provider.lastLoadedGistId = gistId
}
})
})

@ -79,6 +79,11 @@ module.exports = {
? 'fak fa-vyper-mono' : path.endsWith('.lex')
? 'fak fa-lexon' : path.endsWith('.contract')
? 'fab fa-ethereum' : 'far fa-file'
},
joinPath (...paths) {
paths = paths.filter((value) => value !== '').map((path) => path.replace(/^\/|\/$/g, '')) // remove first and last slash)
if (paths.length === 1) return paths[0]
return paths.join('/')
}
}

@ -1,5 +1,5 @@
import { Storage } from '@remix-project/remix-lib'
import { joinPath } from './lib/helper'
/*
Migrating the files to the BrowserFS storage instead or raw localstorage
@ -20,3 +20,30 @@ export default (fileProvider) => {
})
fileStorageBrowserFS.set(flag, 'done')
}
export async function migrateToWorkspace (fileManager) {
const browserProvider = fileManager.getProvider('browser')
const workspaceProvider = fileManager.getProvider('workspace')
const flag = 'status'
const fileStorageBrowserWorkspace = new Storage('remix_browserWorkspace_migration:')
if (fileStorageBrowserWorkspace.get(flag) === 'done') return
const files = await browserProvider.copyFolderToJson('/')
console.log(files)
const workspaceName = 'default_workspace'
const workspacePath = joinPath('browser', workspaceProvider.workspacesPath, workspaceName)
await fileManager.createWorkspace(workspaceName)
await populateWorkspace(workspacePath, files, fileManager)
fileStorageBrowserWorkspace.set(flag, 'done')
}
const populateWorkspace = async (workspace, json, fileManager) => {
for (const item in json) {
const isFolder = json[item].content === undefined
if (isFolder) {
await fileManager.mkdir(joinPath(workspace, item))
await populateWorkspace(workspace, json[item].children, fileManager)
} else {
await fileManager.writeFile(joinPath(workspace, item), json[item].content)
}
}
}

@ -130,13 +130,12 @@ class PluginLoader {
constructor () {
const queryParams = new QueryParams()
this.donotAutoReload = ['remixd'] // that would be a bad practice to force loading some plugins at page load.
this.donotAutoReload = ['remixd', 'git'] // that would be a bad practice to force loading some plugins at page load.
this.loaders = {}
this.loaders.localStorage = {
set: (plugin, actives) => {
if (!this.donotAutoReload.includes(plugin.name)) {
localStorage.setItem('workspace', JSON.stringify(actives))
}
const saved = actives.filter((name) => !this.donotAutoReload.includes(name))
localStorage.setItem('workspace', JSON.stringify(saved))
},
get: () => { return JSON.parse(localStorage.getItem('workspace')) }
}

@ -140,6 +140,7 @@ export class Debugger {
this.step_manager = new DebuggerStepManager(this.debugger, this.debugger.traceManager)
this.debugger.codeManager.event.register('changed', this, (code, address, instIndex) => {
if (!this.debugger.solidityProxy.contracts) return
this.debugger.callTree.sourceLocationTracker.getValidSourceLocationFromVMTraceIndex(address, this.step_manager.currentStepIndex, this.debugger.solidityProxy.contracts).then((sourceLocation) => {
this.vmDebuggerLogic.event.trigger('sourceLocationChanged', [sourceLocation])
})

@ -187,7 +187,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
const ret = await debuggerModule.fetchContractAndCompile(address, currentReceipt)
return ret
} catch (e) {
debuggerModule.showMessage('Debugging error', 'Unable to fetch a transaction.')
// debuggerModule.showMessage('Debugging error', 'Unable to fetch a transaction.')
console.error(e)
}
return null

@ -19,12 +19,13 @@ export const FileExplorer = (props: FileExplorerProps) => {
const { filesProvider, name, registry, plugin, focusRoot, contextMenuItems, displayInput, externalUploads } = props
const [state, setState] = useState({
focusElement: [{
key: name,
key: '',
type: 'folder'
}],
focusPath: null,
files: [],
fileManager: null,
filesProvider,
ctrlKey: false,
newFileName: '',
actions: [],
@ -119,10 +120,10 @@ export const FileExplorer = (props: FileExplorerProps) => {
}]
setState(prevState => {
return { ...prevState, fileManager, files, actions }
return { ...prevState, fileManager, files, actions, expandPath: [name] }
})
})()
}, [])
}, [name])
useEffect(() => {
if (state.fileManager) {
@ -165,7 +166,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
useEffect(() => {
if (focusRoot) {
setState(prevState => {
return { ...prevState, focusElement: [{ key: name, type: 'folder' }] }
return { ...prevState, focusElement: [{ key: '', type: 'folder' }] }
})
plugin.resetFocus(false)
}
@ -219,7 +220,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
}, [state.modals])
const resolveDirectory = async (folderPath, dir: File[], isChild = false): Promise<File[]> => {
if (!isChild && (state.focusEdit.element === `${name}/blank`) && state.focusEdit.isNew && (dir.findIndex(({ path }) => path === `${name}/blank`) === -1)) {
if (!isChild && (state.focusEdit.element === '/blank') && state.focusEdit.isNew && (dir.findIndex(({ path }) => path === '/blank') === -1)) {
dir = state.focusEdit.type === 'file' ? [...dir, {
path: state.focusEdit.element,
name: '',
@ -261,20 +262,21 @@ export const FileExplorer = (props: FileExplorerProps) => {
return new Promise((resolve) => {
filesProvider.resolveDirectory(folderPath, (error, fileTree) => {
if (error) console.error(error)
const files = normalize(folderPath, fileTree)
const files = normalize(fileTree)
resolve(files)
})
})
}
const normalize = (path, filesList): File[] => {
const normalize = (filesList): File[] => {
const folders = []
const files = []
const prefix = path.split('/')[0]
Object.keys(filesList || {}).forEach(key => {
const path = prefix + '/' + key
key = key.replace(/^\/|\/$/g, '') // remove first and last slash
let path = key
path = path.replace(/^\/|\/$/g, '') // remove first and last slash
if (filesList[key].isDirectory) {
folders.push({
@ -533,7 +535,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
}
fileReader.readAsText(file)
}
const name = filesProvider.type + '/' + file.name
const name = file.name
filesProvider.exists(name, (error, exist) => {
if (error) console.log(error)
@ -607,7 +609,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
}
// If 'id' is not defined, it is not a gist update but a creation so we have to take the files from the browser explorer.
const folder = id ? 'browser/gists/' + id : 'browser/'
const folder = id ? '/gists/' + id : '/'
packageFiles(filesProvider, folder, async (error, packaged) => {
if (error) {
@ -809,7 +811,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
}, null)
} else {
if (state.focusEdit.isNew) {
state.focusEdit.type === 'file' ? createNewFile(parentFolder + '/' + content) : createNewFolder(parentFolder + '/' + content)
state.focusEdit.type === 'file' ? createNewFile(joinPath(parentFolder, content)) : createNewFolder(joinPath(parentFolder, content))
const files = removePath(state.focusEdit.element, state.files)
const updatedFiles = files.filter(file => file)
@ -1020,6 +1022,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
<div>
<TreeView id='treeView'>
<TreeViewItem id="treeViewItem"
controlBehaviour={true}
label={
<div onClick={(e) => {
e.stopPropagation()
@ -1036,7 +1039,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
plugin.resetFocus(true)
}}>
<FileExplorerMenu
title={name}
title={''}
menuItems={props.menuItems}
createNewFile={handleNewFileInput}
createNewFolder={handleNewFolderInput}
@ -1046,7 +1049,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
/>
</div>
}
expand={state.expandPath.includes(props.name)}>
expand={true}>
<div className='pb-2'>
<TreeView id='treeViewMenu'>
{
@ -1100,3 +1103,9 @@ function packageFiles (filesProvider, directory, callback) {
}
})
}
function joinPath (...paths) {
paths = paths.filter((value) => value !== '').map((path) => path.replace(/^\/|\/$/g, '')) // remove first and last slash)
if (paths.length === 1) return paths[0]
return paths.join('/')
}

Loading…
Cancel
Save