Merge pull request #2733 from ethereum/filemanager-api

Move filemanager api to new api
pull/5370/head
yann300 5 years ago committed by GitHub
commit db18ddbb61
  1. 23999
      package-lock.json
  2. 4
      package.json
  3. 2
      src/app.js
  4. 2
      src/app/editor/contextView.js
  5. 4
      src/app/editor/sourceHighlighter.js
  6. 34
      src/app/files/file-explorer.js
  7. 264
      src/app/files/fileManager.js
  8. 58
      src/app/files/fileProvider.js
  9. 31
      src/app/files/remixDProvider.js
  10. 2
      src/app/panels/main-view.js
  11. 8
      src/app/panels/tab-proxy.js
  12. 2
      src/app/tabs/compileTab/compilerContainer.js
  13. 2
      src/app/tabs/runTab/model/recorder.js
  14. 4
      src/app/tabs/test-tab.js
  15. 4
      src/app/tabs/testTab/testTab.js
  16. 2
      src/app/ui/renderer.js
  17. 4
      src/lib/cmdInterpreterAPI.js
  18. 38
      src/lib/remixd.js
  19. 8
      test-browser/commands/openFile.js
  20. 2
      test-browser/tests/defaultLayout.test.js
  21. 12
      test-browser/tests/editor.test.js
  22. 6
      test-browser/tests/generalSettings.test.js
  23. 10
      test-browser/tests/gist.test.js
  24. 8
      test-browser/tests/libraryDeployment.test.js
  25. 2
      test-browser/tests/pluginManager.test.js
  26. 6
      test-browser/tests/publishContract.test.js
  27. 2
      test-browser/tests/remixd.test.js
  28. 4
      test-browser/tests/runAndDeploy.js
  29. 2
      test-browser/tests/signingMessage.test.js
  30. 2
      test-browser/tests/solidityImport.test.js
  31. 10
      test-browser/tests/solidityUnittests.test.js
  32. 6
      test-browser/tests/terminal.test.js

23999
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -62,7 +62,7 @@
"remix-solidity": "0.3.30", "remix-solidity": "0.3.30",
"remix-tabs": "1.0.48", "remix-tabs": "1.0.48",
"remix-tests": "0.1.33", "remix-tests": "0.1.33",
"remixd": "0.1.8-alpha.10", "remixd": "0.1.8-alpha.16",
"request": "^2.83.0", "request": "^2.83.0",
"rimraf": "^2.6.1", "rimraf": "^2.6.1",
"selenium-standalone": "^6.17.0", "selenium-standalone": "^6.17.0",
@ -81,7 +81,6 @@
"dependencies": { "dependencies": {
"@remixproject/engine": "^0.2.3", "@remixproject/engine": "^0.2.3",
"http-server": "^0.11.1", "http-server": "^0.11.1",
"remixd": "0.1.8-alpha.10",
"standard": "^8.5.0" "standard": "^8.5.0"
}, },
"repository": { "repository": {
@ -185,7 +184,6 @@
"nightwatch_local_fileExplorer": "nightwatch ./test-browser/tests/fileExplorer.test.js --config nightwatch.js --env chrome ", "nightwatch_local_fileExplorer": "nightwatch ./test-browser/tests/fileExplorer.test.js --config nightwatch.js --env chrome ",
"nightwatch_local_debugger": "nightwatch ./test-browser/tests/debugger.test.js --config nightwatch.js --env chrome ", "nightwatch_local_debugger": "nightwatch ./test-browser/tests/debugger.test.js --config nightwatch.js --env chrome ",
"nightwatch_local_editor": "nightwatch ./test-browser/tests/editor.test.js --config nightwatch.js --env chrome ", "nightwatch_local_editor": "nightwatch ./test-browser/tests/editor.test.js --config nightwatch.js --env chrome ",
"nightwatch_local_runAndDeploy": "nightwatch ./test-browser/tests/runAndDeploy.js --config nightwatch.js --env chrome-runAndDeploy ", "nightwatch_local_runAndDeploy": "nightwatch ./test-browser/tests/runAndDeploy.js --config nightwatch.js --env chrome-runAndDeploy ",
"onchange": "onchange build/app.js -- npm-run-all lint", "onchange": "onchange build/app.js -- npm-run-all lint",
"prepublish": "mkdirp build; npm-run-all -ls downloadsolc_root build", "prepublish": "mkdirp build; npm-run-all -ls downloadsolc_root build",

@ -419,7 +419,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
if (error) console.error(error) if (error) console.error(error)
if (Object.keys(filesList).length === 0) { if (Object.keys(filesList).length === 0) {
for (let file in examples) { for (let file in examples) {
fileManager.setFile(examples[file].name, examples[file].content) fileManager.writeFile(examples[file].name, examples[file].content)
} }
} }
}) })

@ -112,7 +112,7 @@ class ContextView {
if (provider) { if (provider) {
provider.exists(filename, (error, exist) => { provider.exists(filename, (error, exist) => {
if (error) return console.log(error) if (error) return console.log(error)
this._deps.fileManager.switchFile(filename) this._deps.fileManager.open(filename)
jumpToLine(lineColumn) jumpToLine(lineColumn)
}) })
} }

@ -31,7 +31,7 @@ class SourceHighlighter {
} }
} }
currentSourceLocationFromfileName (lineColumnPos, filePath, style) { async currentSourceLocationFromfileName (lineColumnPos, filePath, style) {
if (this.statementMarker) this._deps.editor.removeMarker(this.statementMarker, this.source) if (this.statementMarker) this._deps.editor.removeMarker(this.statementMarker, this.source)
if (this.fullLineMarker) this._deps.editor.removeMarker(this.fullLineMarker, this.source) if (this.fullLineMarker) this._deps.editor.removeMarker(this.fullLineMarker, this.source)
this.statementMarker = null this.statementMarker = null
@ -40,7 +40,7 @@ class SourceHighlighter {
if (lineColumnPos) { if (lineColumnPos) {
this.source = filePath this.source = filePath
if (this._deps.config.get('currentFile') !== this.source) { if (this._deps.config.get('currentFile') !== this.source) {
this._deps.fileManager.switchFile(this.source) await this._deps.fileManager.open(this.source)
} }
const css = csjs` const css = csjs`

@ -60,7 +60,7 @@ function fileExplorer (localRegistry, files, menuItems) {
} }
self.events.register('focus', function (path) { self.events.register('focus', function (path) {
self._deps.fileManager.switchFile(path) self._deps.fileManager.open(path)
}) })
self._components.registry.put({ api: self, name: `fileexplorer/${self.files.type}` }) self._components.registry.put({ api: self, name: `fileexplorer/${self.files.type}` })
@ -234,11 +234,16 @@ function fileExplorer (localRegistry, files, menuItems) {
const currentFoldername = extractNameFromKey(key) const currentFoldername = extractNameFromKey(key)
modalDialogCustom.confirm(`Confirm to delete folder`, `Are you sure you want to delete ${currentFoldername} folder?`, modalDialogCustom.confirm(`Confirm to delete folder`, `Are you sure you want to delete ${currentFoldername} folder?`,
() => { async () => {
if (!files.remove(key)) { const fileManager = self._deps.fileManager
const removeFolder = await fileManager.remove(key)
if (!removeFolder) {
tooltip(`failed to remove ${key}. Make sure the directory is empty before removing it.`) tooltip(`failed to remove ${key}. Make sure the directory is empty before removing it.`)
} else { } else {
self.updatePath('browser') const { type } = fileManager.currentFileProvider()
self.updatePath(type)
} }
}, () => {}) }, () => {})
} }
@ -275,9 +280,16 @@ function fileExplorer (localRegistry, files, menuItems) {
modalDialogCustom.confirm( modalDialogCustom.confirm(
`Delete file`, `Are you sure you want to delete ${currentFilename} file?`, `Delete file`, `Are you sure you want to delete ${currentFilename} file?`,
() => { async () => {
files.remove(key) const fileManager = self._deps.fileManager
self.updatePath('browser') const removeFile = await fileManager.remove(key)
if (!removeFile) {
tooltip(`Failed to remove file ${key}.`)
} else {
const { type } = fileManager.currentFileProvider()
self.updatePath(type)
}
}, },
() => {} () => {}
) )
@ -578,13 +590,15 @@ fileExplorer.prototype.createNewFile = function (parentFolder = 'browser') {
let self = this let self = this
modalDialogCustom.prompt('Create new file', 'File Name (e.g Untitled.sol)', 'Untitled.sol', (input) => { modalDialogCustom.prompt('Create new file', 'File Name (e.g Untitled.sol)', 'Untitled.sol', (input) => {
if (!input) input = 'New file' if (!input) input = 'New file'
helper.createNonClashingName(parentFolder + '/' + input, self.files, (error, newName) => { helper.createNonClashingName(parentFolder + '/' + input, self.files, async (error, newName) => {
if (error) return tooltip('Failed to create file ' + newName + ' ' + error) if (error) return tooltip('Failed to create file ' + newName + ' ' + error)
const fileManager = self._deps.fileManager
const createFile = await fileManager.writeFile(newName, '')
if (!self.files.set(newName, '')) { if (!createFile) {
tooltip('Failed to create file ' + newName) tooltip('Failed to create file ' + newName)
} else { } else {
self._deps.fileManager.switchFile(newName) await fileManager.open(newName)
if (newName.includes('_test.sol')) { if (newName.includes('_test.sol')) {
self.events.trigger('newTestFileCreated', [newName]) self.events.trigger('newTestFileCreated', [newName])
} }

@ -23,12 +23,19 @@ const profile = {
icon: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iMTc5MiIgaGVpZ2h0PSIxNzkyIiB2aWV3Qm94PSIwIDAgMTc5MiAxNzkyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik0xNjk2IDM4NHE0MCAwIDY4IDI4dDI4IDY4djEyMTZxMCA0MC0yOCA2OHQtNjggMjhoLTk2MHEtNDAgMC02OC0yOHQtMjgtNjh2LTI4OGgtNTQ0cS00MCAwLTY4LTI4dC0yOC02OHYtNjcycTAtNDAgMjAtODh0NDgtNzZsNDA4LTQwOHEyOC0yOCA3Ni00OHQ4OC0yMGg0MTZxNDAgMCA2OCAyOHQyOCA2OHYzMjhxNjgtNDAgMTI4LTQwaDQxNnptLTU0NCAyMTNsLTI5OSAyOTloMjk5di0yOTl6bS02NDAtMzg0bC0yOTkgMjk5aDI5OXYtMjk5em0xOTYgNjQ3bDMxNi0zMTZ2LTQxNmgtMzg0djQxNnEwIDQwLTI4IDY4dC02OCAyOGgtNDE2djY0MGg1MTJ2LTI1NnEwLTQwIDIwLTg4dDQ4LTc2em05NTYgODA0di0xMTUyaC0zODR2NDE2cTAgNDAtMjggNjh0LTY4IDI4aC00MTZ2NjQwaDg5NnoiLz48L3N2Zz4=', icon: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iMTc5MiIgaGVpZ2h0PSIxNzkyIiB2aWV3Qm94PSIwIDAgMTc5MiAxNzkyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik0xNjk2IDM4NHE0MCAwIDY4IDI4dDI4IDY4djEyMTZxMCA0MC0yOCA2OHQtNjggMjhoLTk2MHEtNDAgMC02OC0yOHQtMjgtNjh2LTI4OGgtNTQ0cS00MCAwLTY4LTI4dC0yOC02OHYtNjcycTAtNDAgMjAtODh0NDgtNzZsNDA4LTQwOHEyOC0yOCA3Ni00OHQ4OC0yMGg0MTZxNDAgMCA2OCAyOHQyOCA2OHYzMjhxNjgtNDAgMTI4LTQwaDQxNnptLTU0NCAyMTNsLTI5OSAyOTloMjk5di0yOTl6bS02NDAtMzg0bC0yOTkgMjk5aDI5OXYtMjk5em0xOTYgNjQ3bDMxNi0zMTZ2LTQxNmgtMzg0djQxNnEwIDQwLTI4IDY4dC02OCAyOGgtNDE2djY0MGg1MTJ2LTI1NnEwLTQwIDIwLTg4dDQ4LTc2em05NTYgODA0di0xMTUyaC0zODR2NDE2cTAgNDAtMjggNjh0LTY4IDI4aC00MTZ2NjQwaDg5NnoiLz48L3N2Zz4=',
permission: true, permission: true,
version: packageJson.version, version: packageJson.version,
methods: ['getFolder', 'getCurrentFile', 'getFile', 'setFile', 'switchFile'], methods: ['file', 'exists', 'open', 'writeFile', 'readFile', 'copyFile', 'rename', 'readdir', 'remove', 'getCurrentFile', 'getFile', 'getFolder', 'setFile', 'switchFile'],
kind: 'file-system' kind: 'file-system'
} }
const errorMsg = {
// File System profile ENOENT: 'No such file or directory',
// - methods: ['getFolder', 'getCurrentFile', 'getFile', 'setFile', 'switchFile'] EISDIR: 'Path is a directory',
ENOTDIR: 'Path is not on a directory',
EEXIST: 'File already exists',
EPERM: 'Permission denied'
}
const createError = (err) => {
return new Error(`${errorMsg[err.code]} ${err.message || ''}`)
}
class FileManager extends Plugin { class FileManager extends Plugin {
constructor (editor) { constructor (editor) {
@ -42,6 +49,202 @@ class FileManager extends Plugin {
this.init() this.init()
} }
/**
* Emit error if path doesn't exist
* @param {string} path path of the file/directory
* @param {string} message message to display if path doesn't exist.
*/
async _handleExists (path, message) {
const exists = await this.exists(path)
if (!exists) {
throw createError({ code: 'ENOENT', message })
}
}
/**
* Emit error if path is not a file
* @param {string} path path of the file/directory
* @param {string} message message to display if path is not a file.
*/
async _handleIsFile (path, message) {
const isFile = await this.isFile(path)
if (!isFile) {
throw createError({ code: 'EISDIR', message })
}
}
/**
* Emit error if path is not a directory
* @param {string} path path of the file/directory
* @param {string} message message to display if path is not a directory.
*/
async _handleIsDir (path, message) {
const isDir = await this.isDirectory(path)
if (!isDir) {
throw createError({ code: 'ENOTDIR', message })
}
}
/** The current opened file */
file () {
const file = this.currentFile()
if (!file) throw createError({ code: 'ENOENT', message: 'No file selected' })
return file
}
/**
* Verify if the path exists (directory or file)
* @param {string} path path of the directory or file
* @returns {boolean} true if the path exists
*/
exists (path) {
const provider = this.fileProviderOf(path)
const result = provider.exists(path, (err, result) => {
if (err) return false
return result
})
return result
}
/**
* Verify if the path provided is a file
* @param {string} path path of the directory or file
* @returns {boolean} true if path is a file.
*/
isFile (path) {
const provider = this.fileProviderOf(path)
const result = provider.isFile(path)
return result
}
/**
* Verify if the path provided is a directory
* @param {string} path path of the directory
* @returns {boolean} true if path is a directory.
*/
isDirectory (path) {
const provider = this.fileProviderOf(path)
const result = provider.isDirectory(path)
return result
}
/**
* Open the content of the file in the context (eg: Editor)
* @param {string} path path of the file
* @returns {void}
*/
async open (path) {
await this._handleExists(path, `Cannot open file ${path}`)
await this._handleIsFile(path, `Cannot open file ${path}`)
return this.openFile(path)
}
/**
* Set the content of a specific file
* @param {string} path path of the file
* @param {string} data content to write on the file
* @returns {void}
*/
async writeFile (path, data) {
if (await this.exists(path)) {
await this._handleIsFile(path, `Cannot write file ${path}`)
return await this.setFileContent(path, data)
} else {
return await this.setFileContent(path, data)
}
}
/**
* Return the content of a specific file
* @param {string} path path of the file
* @returns {string} content of the file
*/
async readFile (path) {
await this._handleExists(path, `Cannot read file ${path}`)
await this._handleIsFile(path, `Cannot read file ${path}`)
return this.getFileContent(path)
}
/**
* Upsert a file with the content of the source file
* @param {string} src path of the source file
* @param {string} dest path of the destrination file
* @returns {void}
*/
async copyFile (src, dest) {
await this._handleExists(src, `Cannot copy from ${src}`)
await this._handleIsFile(src, `Cannot copy from ${src}`)
await this._handleIsFile(dest, `Cannot paste content into ${dest}`)
const content = await this.readFile(src)
await this.writeFile(dest, content)
}
/**
* Change the path of a file/directory
* @param {string} oldPath current path of the file/directory
* @param {string} newPath new path of the file/directory
* @returns {void}
*/
async rename (oldPath, newPath) {
await this.__handleExists(oldPath, `Cannot rename ${oldPath}`)
const isFile = await this.isFile(oldPath)
this.fileRenamedEvent(oldPath, newPath, !isFile)
}
/**
* Create a directory
* @param {string} path path of the new directory
* @returns {void}
*/
async mkdir (path) {
if (await this.exists(path)) {
throw createError({ code: 'EEXIST', message: `Cannot create directory ${path}` })
}
const provider = this.fileProviderOf(path)
provider.createDir(path)
}
/**
* Get the list of files in the directory
* @param {string} path path of the directory
* @returns {string[]} list of the file/directory name in this directory
*/
async readdir (path) {
await this._handleExists(path)
await this._handleIsDir(path)
return new Promise((resolve, reject) => {
const provider = this.fileProviderOf(path)
provider.resolveDirectory(path, (error, filesProvider) => {
if (error) reject(error)
resolve(filesProvider)
})
})
}
/**
* Removes a file or directory recursively
* @param {string} path path of the directory/file to remove
* @returns {void}
*/
async remove (path) {
await this._handleExists(path, `Cannot remove file or directory ${path}`)
const provider = this.fileProviderOf(path)
return await provider.remove(path)
}
init () { init () {
this._deps = { this._deps = {
config: this._components.registry.get('config').api, config: this._components.registry.get('config').api,
@ -56,6 +259,11 @@ class FileManager extends Plugin {
this._deps.localhostExplorer.event.register('fileRemoved', (path) => { this.fileRemovedEvent(path) }) 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('errored', (event) => { this.removeTabsOf(this._deps.localhostExplorer) })
this._deps.localhostExplorer.event.register('closed', (event) => { this.removeTabsOf(this._deps.localhostExplorer) }) this._deps.localhostExplorer.event.register('closed', (event) => { this.removeTabsOf(this._deps.localhostExplorer) })
this.getCurrentFile = this.file
this.getFile = this.readFile
this.getFolder = this.readdir
this.setFile = this.writeFile
this.switchFile = this.open
} }
fileChangedEvent (path) { fileChangedEvent (path) {
@ -71,7 +279,7 @@ class FileManager extends Plugin {
delete this.openedFiles[oldName] delete this.openedFiles[oldName]
this.openedFiles[newName] = newName this.openedFiles[newName] = newName
} }
this.switchFile(newName) this.openFile(newName)
} else { } else {
var newFocus var newFocus
for (var k in this.openedFiles) { for (var k in this.openedFiles) {
@ -85,7 +293,7 @@ class FileManager extends Plugin {
} }
} }
if (newFocus) { if (newFocus) {
this.switchFile(newFocus) this.openFile(newFocus)
} }
} }
// TODO: Only keep `this.emit` (issue#2210) // TODO: Only keep `this.emit` (issue#2210)
@ -129,15 +337,10 @@ class FileManager extends Plugin {
return path ? path[1] : null return path ? path[1] : null
} }
getCurrentFile () { getFileContent (path) {
const path = this.currentFile()
if (!path) throw new Error('No file selected')
return path
}
getFile (path) {
const provider = this.fileProviderOf(path) const provider = this.fileProviderOf(path)
if (!provider) throw new Error(`${path} not available`)
if (!provider) throw createError({ code: 'ENOENT', message: `${path} not available` })
// TODO: change provider to Promise // TODO: change provider to Promise
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (this.currentFile() === path) return resolve(this.editor.currentContent()) if (this.currentFile() === path) return resolve(this.editor.currentContent())
@ -148,9 +351,9 @@ class FileManager extends Plugin {
}) })
} }
async setFile (path, content) { async setFileContent (path, content) {
if (this.currentRequest) { if (this.currentRequest) {
const canCall = await this.askUserPermission('setFile', '') const canCall = await this.askUserPermission('writeFile', '')
if (canCall) { if (canCall) {
this._setFileInternal(path, content) this._setFileInternal(path, content)
// inform the user about modification after permission is granted and even if permission was saved before // inform the user about modification after permission is granted and even if permission was saved before
@ -167,12 +370,12 @@ class FileManager extends Plugin {
`, '', { time: 3000 }) `, '', { time: 3000 })
} }
} }
this._setFileInternal(path, content) return await this._setFileInternal(path, content)
} }
_setFileInternal (path, content) { _setFileInternal (path, content) {
const provider = this.fileProviderOf(path) const provider = this.fileProviderOf(path)
if (!provider) throw new Error(`${path} not availble`) if (!provider) throw createError({ code: 'ENOENT', message: `${path} not available` })
// TODO : Add permission // TODO : Add permission
// TODO : Change Provider to Promise // TODO : Change Provider to Promise
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -189,11 +392,10 @@ class FileManager extends Plugin {
if (fileProvider) { if (fileProvider) {
helper.createNonClashingNameWithPrefix(path, fileProvider, '', (error, copyName) => { helper.createNonClashingNameWithPrefix(path, fileProvider, '', (error, copyName) => {
if (error) { if (error) {
console.log('createNonClashingNameWithPrefix', error)
copyName = path + '.' + this.currentRequest.from copyName = path + '.' + this.currentRequest.from
} }
this._setFileInternal(copyName, content) this._setFileInternal(copyName, content)
this.switchFile(copyName) this.openFile(copyName)
}) })
} }
} }
@ -216,7 +418,7 @@ class FileManager extends Plugin {
// TODO: Only keep `this.emit` (issue#2210) // TODO: Only keep `this.emit` (issue#2210)
this.emit('fileRemoved', path) this.emit('fileRemoved', path)
this.events.emit('fileRemoved', path) this.events.emit('fileRemoved', path)
this.switchFile() this.openFile()
} }
unselectCurrentFile () { unselectCurrentFile () {
@ -227,8 +429,8 @@ class FileManager extends Plugin {
this.events.emit('noFileSelected') this.events.emit('noFileSelected')
} }
switchFile (file) { openFile (file) {
const _switchFile = (file) => { const _openFile = (file) => {
this.saveCurrentFile() this.saveCurrentFile()
this._deps.config.set('currentFile', file) this._deps.config.set('currentFile', file)
this.openedFiles[file] = file this.openedFiles[file] = file
@ -247,14 +449,14 @@ class FileManager extends Plugin {
} }
}) })
} }
if (file) return _switchFile(file) if (file) return _openFile(file)
else { else {
var browserProvider = this._deps.filesProviders['browser'] var browserProvider = this._deps.filesProviders['browser']
browserProvider.resolveDirectory('browser', (error, filesProvider) => { browserProvider.resolveDirectory('browser', (error, filesProvider) => {
if (error) console.error(error) if (error) console.error(error)
var fileList = Object.keys(filesProvider) var fileList = Object.keys(filesProvider)
if (fileList.length) { if (fileList.length) {
_switchFile(browserProvider.type + '/' + fileList[0]) _openFile(browserProvider.type + '/' + fileList[0])
} else { } else {
// TODO: Only keep `this.emit` (issue#2210) // TODO: Only keep `this.emit` (issue#2210)
this.emit('noFileSelected') this.emit('noFileSelected')
@ -264,18 +466,6 @@ class FileManager extends Plugin {
} }
} }
getFolder (path) {
// TODO : Change provider with promise
return new Promise((resolve, reject) => {
const provider = this.fileProviderOf(path)
if (!provider) return reject(`provider for path ${path} not found`)
provider.resolveDirectory(path, (error, filesProvider) => {
if (error) reject(error)
resolve(filesProvider)
})
})
}
getProvider (name) { getProvider (name) {
return this._deps.filesProviders[name] return this._deps.filesProviders[name]
} }

@ -66,12 +66,12 @@ class FileProvider {
exists (path, cb) { exists (path, cb) {
// todo check the type (directory/file) as well #2386 // todo check the type (directory/file) as well #2386
// currently it is not possible to have a file and folder with same path // currently it is not possible to have a file and folder with same path
cb(null, this._exists(path)) return cb(null, this._exists(path))
} }
_exists (path) { _exists (path) {
var unprefixedpath = this.removePrefix(path) var unprefixedpath = this.removePrefix(path)
return window.remixFileSystem.existsSync(unprefixedpath) return path === this.type ? true : window.remixFileSystem.existsSync(unprefixedpath)
} }
init (cb) { init (cb) {
@ -94,19 +94,8 @@ class FileProvider {
var unprefixedpath = this.removePrefix(path) var unprefixedpath = this.removePrefix(path)
var exists = window.remixFileSystem.existsSync(unprefixedpath) var exists = window.remixFileSystem.existsSync(unprefixedpath)
if (exists && window.remixFileSystem.readFileSync(unprefixedpath, 'utf8') === content) return true if (exists && window.remixFileSystem.readFileSync(unprefixedpath, 'utf8') === content) return true
if (!exists && unprefixedpath.indexOf('/') !== -1) { if (!exists && unprefixedpath.indexOf('/') !== -1) {
const paths = unprefixedpath.split('/') this.createDir(path)
paths.pop() // last element should the filename
if (paths.length && paths[0] === '') paths.shift()
let currentCheck = ''
paths.forEach((value) => {
currentCheck = currentCheck + '/' + value
if (!window.remixFileSystem.existsSync(currentCheck)) {
window.remixFileSystem.mkdirSync(currentCheck)
this.event.trigger('folderAdded', [this._normalizePath(currentCheck)])
}
})
} }
try { try {
window.remixFileSystem.writeFileSync(unprefixedpath, content) window.remixFileSystem.writeFileSync(unprefixedpath, content)
@ -123,6 +112,22 @@ class FileProvider {
return true return true
} }
createDir (path, cb) {
var unprefixedpath = this.removePrefix(path)
const paths = unprefixedpath.split('/')
paths.pop() // last element should the filename
if (paths.length && paths[0] === '') paths.shift()
let currentCheck = ''
paths.forEach((value) => {
currentCheck = currentCheck + '/' + value
if (!window.remixFileSystem.existsSync(currentCheck)) {
window.remixFileSystem.mkdirSync(currentCheck)
this.event.trigger('folderAdded', [this._normalizePath(currentCheck)])
}
})
if (cb) cb()
}
// this will not add a folder as readonly but keep the original url to be able to restore it later // this will not add a folder as readonly but keep the original url to be able to restore it later
addExternal (path, content, url) { addExternal (path, content, url) {
if (url) this.addNormalizedName(path, url) if (url) this.addNormalizedName(path, url)
@ -134,7 +139,14 @@ class FileProvider {
} }
isDirectory (path) { isDirectory (path) {
return window.remixFileSystem.statSync(path).isDirectory() const unprefixedpath = this.removePrefix(path)
return path === this.type ? true : window.remixFileSystem.statSync(unprefixedpath).isDirectory()
}
isFile (path) {
path = this.removePrefix(path)
return window.remixFileSystem.statSync(path).isFile()
} }
/** /**
@ -147,9 +159,7 @@ class FileProvider {
const stat = window.remixFileSystem.statSync(path) const stat = window.remixFileSystem.statSync(path)
try { try {
if (!stat.isDirectory()) { if (!stat.isDirectory()) {
window.remixFileSystem.unlinkSync(path, console.log) return this.removeFile(path)
this.event.trigger('fileRemoved', [this._normalizePath(path)])
return true
} else { } else {
const items = window.remixFileSystem.readdirSync(path) const items = window.remixFileSystem.readdirSync(path)
if (items.length !== 0) { if (items.length !== 0) {
@ -158,8 +168,7 @@ class FileProvider {
if (window.remixFileSystem.statSync(curPath).isDirectory()) { // delete folder if (window.remixFileSystem.statSync(curPath).isDirectory()) { // delete folder
this.remove(curPath) this.remove(curPath)
} else { // delete file } else { // delete file
window.remixFileSystem.unlinkSync(curPath, console.log) this.removeFile(curPath)
this.event.trigger('fileRemoved', [this._normalizePath(path)])
} }
}) })
if (window.remixFileSystem.readdirSync(path).length === 0) window.remixFileSystem.rmdirSync(path, console.log) if (window.remixFileSystem.readdirSync(path).length === 0) window.remixFileSystem.rmdirSync(path, console.log)
@ -176,6 +185,15 @@ class FileProvider {
return true return true
} }
removeFile (path) {
path = this.removePrefix(path)
if (window.remixFileSystem.existsSync(path) && !window.remixFileSystem.statSync(path).isDirectory()) {
window.remixFileSystem.unlinkSync(path, console.log)
this.event.trigger('fileRemoved', [this._normalizePath(path)])
return true
} else return false
}
rename (oldPath, newPath, isFolder) { rename (oldPath, newPath, isFolder) {
var unprefixedoldPath = this.removePrefix(oldPath) var unprefixedoldPath = this.removePrefix(oldPath)
var unprefixednewPath = this.removePrefix(newPath) var unprefixednewPath = this.removePrefix(newPath)

@ -81,11 +81,12 @@ module.exports = class RemixDProvider {
// //
// this.remixd.exists(path, (error, isValid) => {}) // this.remixd.exists(path, (error, isValid) => {})
exists (path, cb) { async exists (path, cb) {
var unprefixedpath = this.removePrefix(path) const unprefixedpath = this.removePrefix(path)
this._remixd.call('sharedfolder', 'exists', {path: unprefixedpath}, (error, result) => { const callId = await this._remixd.call('sharedfolder', 'exists', {path: unprefixedpath})
cb(error, result) const result = await this._remixd.receiveResponse(callId)
})
return cb(null, result)
} }
get (path, cb) { get (path, cb) {
@ -117,9 +118,9 @@ module.exports = class RemixDProvider {
return this._readOnlyMode || this._readOnlyFiles[path] === 1 return this._readOnlyMode || this._readOnlyFiles[path] === 1
} }
remove (path) { async remove (path) {
var unprefixedpath = this.removePrefix(path) var unprefixedpath = this.removePrefix(path)
this._remixd.call('sharedfolder', 'remove', {path: unprefixedpath}, (error, result) => { const callId = await this._remixd.call('sharedfolder', 'remove', {path: unprefixedpath}, (error, result) => {
if (error) console.log(error) if (error) console.log(error)
var path = this.type + '/' + unprefixedpath var path = this.type + '/' + unprefixedpath
delete this.filesContent[path] delete this.filesContent[path]
@ -127,6 +128,8 @@ module.exports = class RemixDProvider {
this.event.trigger('fileRemoved', [path]) this.event.trigger('fileRemoved', [path])
}) })
}) })
return await this._remixd.receiveResponse(callId)
} }
rename (oldPath, newPath, isFolder) { rename (oldPath, newPath, isFolder) {
@ -167,6 +170,20 @@ module.exports = class RemixDProvider {
path = self.removePrefix(path) path = self.removePrefix(path)
self.remixd.dir(path, callback) self.remixd.dir(path, callback)
} }
async isDirectory (path) {
const unprefixedpath = this.removePrefix(path)
const callId = await this._remixd.call('sharedfolder', 'isDirectory', {path: unprefixedpath})
return await this._remixd.receiveResponse(callId)
}
async isFile (path) {
const unprefixedpath = this.removePrefix(path)
const callId = await this._remixd.call('sharedfolder', 'isFile', {path: unprefixedpath})
return await this._remixd.receiveResponse(callId)
}
} }
function remixapi (remixd, self) { function remixapi (remixd, self) {

@ -61,7 +61,7 @@ export class MainView {
self._view.mainPanel.style.display = 'none' self._view.mainPanel.style.display = 'none'
self._components.contextView.show() self._components.contextView.show()
}) })
self.tabProxy.event.on('switchFile', (file) => { self.tabProxy.event.on('openFile', (file) => {
self._view.editor.style.display = 'block' self._view.editor.style.display = 'block'
self._view.mainPanel.style.display = 'none' self._view.mainPanel.style.display = 'none'
self._components.contextView.show() self._components.contextView.show()

@ -34,8 +34,8 @@ export class TabProxy {
return return
} }
this.addTab(file, '', () => { this.addTab(file, '', () => {
this.fileManager.switchFile(file) this.fileManager.open(file)
this.event.emit('switchFile', file) this.event.emit('openFile', file)
}, },
() => { () => {
this.fileManager.closeFile(file) this.fileManager.closeFile(file)
@ -47,8 +47,8 @@ export class TabProxy {
if (isFolder) return if (isFolder) return
// should change the tab title too // should change the tab title too
this.addTab(newName, '', () => { this.addTab(newName, '', () => {
this.fileManager.switchFile(newName) this.fileManager.open(newName)
this.event.emit('switchFile', newName) this.event.emit('openFile', newName)
}, },
() => { () => {
this.fileManager.closeFile(newName) this.fileManager.closeFile(newName)

@ -141,7 +141,7 @@ class CompilerContainer {
// Load solc compiler version according to pragma in contract file // Load solc compiler version according to pragma in contract file
_setCompilerVersionFromPragma (filename) { _setCompilerVersionFromPragma (filename) {
if (!this.data.allversions) return if (!this.data.allversions) return
this.compileTabLogic.fileManager.getFile(filename).then(data => { this.compileTabLogic.fileManager.readFile(filename).then(data => {
const pragmaArr = data.match(/(pragma solidity (.+?);)/g) const pragmaArr = data.match(/(pragma solidity (.+?);)/g)
if (pragmaArr && pragmaArr.length === 1) { if (pragmaArr && pragmaArr.length === 1) {
const pragmaStr = pragmaArr[0].replace('pragma solidity', '').trim() const pragmaStr = pragmaArr[0].replace('pragma solidity', '').trim()

@ -319,7 +319,7 @@ class Recorder {
helper.createNonClashingName(newFile, fileProvider, (error, newFile) => { helper.createNonClashingName(newFile, fileProvider, (error, newFile) => {
if (error) return cb('Failed to create file. ' + newFile + ' ' + error) if (error) return cb('Failed to create file. ' + newFile + ' ' + error)
if (!fileProvider.set(newFile, txJSON)) return cb('Failed to create file ' + newFile) if (!fileProvider.set(newFile, txJSON)) return cb('Failed to create file ' + newFile)
this.fileManager.switchFile(newFile) this.fileManager.open(newFile)
}) })
}) })
} }

@ -289,7 +289,7 @@ module.exports = class TestTab extends ViewPlugin {
} }
async testFromPath (path) { async testFromPath (path) {
const fileContent = await this.fileManager.getFile(path) const fileContent = await this.fileManager.readFile(path)
return this.testFromSource(fileContent, path) return this.testFromSource(fileContent, path)
} }
@ -323,7 +323,7 @@ module.exports = class TestTab extends ViewPlugin {
return return
} }
this.resultStatistics.hidden = false this.resultStatistics.hidden = false
this.fileManager.getFile(testFilePath).then((content) => { this.fileManager.readFile(testFilePath).then((content) => {
const runningTest = {} const runningTest = {}
runningTest[testFilePath] = { content } runningTest[testFilePath] = { content }
const {currentVersion, evmVersion, optimize} = this.compileTab.getCurrentCompilerConfig() const {currentVersion, evmVersion, optimize} = this.compileTab.getCurrentCompilerConfig()

@ -19,7 +19,7 @@ class TestTabLogic {
// This should be updated to pass complete path, if test file comes from different directory/path // This should be updated to pass complete path, if test file comes from different directory/path
const fileNameToImport = splittedFileName[splittedFileName.length - 1] const fileNameToImport = splittedFileName[splittedFileName.length - 1]
if (!fileProvider.set(newFile, this.generateTestContractSample(fileNameToImport))) return modalDialogCustom.alert('Failed to create test file ' + newFile) if (!fileProvider.set(newFile, this.generateTestContractSample(fileNameToImport))) return modalDialogCustom.alert('Failed to create test file ' + newFile)
this.fileManager.switchFile(newFile) this.fileManager.open(newFile)
}) })
} }
@ -31,7 +31,7 @@ class TestTabLogic {
const tests = [] const tests = []
let files let files
try { try {
files = await this.fileManager.getFolder(path) files = await this.fileManager.readdir(path)
} catch (e) { } catch (e) {
cb(e.message) cb(e.message)
} }

@ -41,7 +41,7 @@ Renderer.prototype._errorClick = function (errFile, errLine, errCol) {
if (provider) { if (provider) {
provider.exists(errFile, (error, exist) => { provider.exists(errFile, (error, exist) => {
if (error) return console.log(error) if (error) return console.log(error)
self._deps.fileManager.switchFile(errFile) self._deps.fileManager.open(errFile)
editor.gotoLine(errLine, errCol) editor.gotoLine(errLine, errCol)
}) })
} }

@ -151,7 +151,7 @@ class CmdInterpreterAPI {
toolTip(`Unable to load ${url}: ${err}`) toolTip(`Unable to load ${url}: ${err}`)
if (cb) cb(err) if (cb) cb(err)
} else { } else {
self._deps.fileManager.setFile(type + '/' + cleanUrl, content) self._deps.fileManager.writeFile(type + '/' + cleanUrl, content)
try { try {
content = JSON.parse(content) content = JSON.parse(content)
async.eachOfSeries(content.sources, (value, file, callbackSource) => { async.eachOfSeries(content.sources, (value, file, callbackSource) => {
@ -164,7 +164,7 @@ class CmdInterpreterAPI {
return callbackSource(`Cannot retrieve the content of ${url}: ${error}`) return callbackSource(`Cannot retrieve the content of ${url}: ${error}`)
} else { } else {
try { try {
await self._deps.fileManager.setFile(type + '/' + cleanUrl, content) await self._deps.fileManager.writeFile(type + '/' + cleanUrl, content)
callbackSource() callbackSource()
} catch (e) { } catch (e) {
callbackSource(e.message) callbackSource(e.message)

@ -11,6 +11,7 @@ class Remixd {
this.callid = 0 this.callid = 0
this.socket = null this.socket = null
this.connected = false this.connected = false
this.receiveResponse()
} }
online () { online () {
@ -74,6 +75,17 @@ class Remixd {
}) })
} }
async receiveResponse (requestId) {
return new Promise((resolve, reject) => {
this.event.register('replied', (data) => {
if (data.id === requestId) {
if (data.error) reject(data.error)
else resolve(data.result)
}
})
})
}
errored (event) { errored (event) {
function remixdDialog () { function remixdDialog () {
return yo`<div>Connection to Remixd closed. Localhost connection not available anymore.</div>` return yo`<div>Connection to Remixd closed. Localhost connection not available anymore.</div>`
@ -87,15 +99,23 @@ class Remixd {
} }
call (service, fn, args, callback) { call (service, fn, args, callback) {
this.ensureSocket((error) => { return new Promise((resolve, reject) => {
if (error) return callback(error) this.ensureSocket((error) => {
if (this.socket && this.socket.readyState === this.socket.OPEN) { if (error) {
var data = this.format(service, fn, args) callback && typeof callback === 'function' && callback(error)
this.callbacks[data.id] = callback reject(error)
this.socket.send(JSON.stringify(data)) return
} else { }
callback('Socket not ready. state:' + this.socket.readyState) if (this.socket && this.socket.readyState === this.socket.OPEN) {
} var data = this.format(service, fn, args)
this.callbacks[data.id] = callback
this.socket.send(JSON.stringify(data))
resolve(data.id)
} else {
callback && typeof callback === 'function' && callback('Socket not ready. state:' + this.socket.readyState)
reject('Socket not ready. state:' + this.socket.readyState)
}
})
}) })
} }

@ -1,9 +1,9 @@
const EventEmitter = require('events') const EventEmitter = require('events')
class SwitchFile extends EventEmitter { class OpenFile extends EventEmitter {
command (name) { command (name) {
this.api.perform((done) => { this.api.perform((done) => {
switchFile(this.api, name, () => { openFile(this.api, name, () => {
done() done()
this.emit('complete') this.emit('complete')
}) })
@ -13,7 +13,7 @@ class SwitchFile extends EventEmitter {
} }
// click on fileExplorer can toggle it. We go through settings to be sure FE is open // click on fileExplorer can toggle it. We go through settings to be sure FE is open
function switchFile (browser, name, done) { function openFile (browser, name, done) {
browser.clickLaunchIcon('settings').clickLaunchIcon('fileExplorers') browser.clickLaunchIcon('settings').clickLaunchIcon('fileExplorers')
.waitForElementVisible('li[key="' + name + '"]') .waitForElementVisible('li[key="' + name + '"]')
.click('li[key="' + name + '"]') .click('li[key="' + name + '"]')
@ -23,4 +23,4 @@ function switchFile (browser, name, done) {
}) })
} }
module.exports = SwitchFile module.exports = OpenFile

@ -66,7 +66,7 @@ module.exports = {
'Switch Tabs using tabs icon': function (browser) { 'Switch Tabs using tabs icon': function (browser) {
browser browser
.waitForElementVisible('div[data-id="filePanelFileExplorerTree"]') .waitForElementVisible('div[data-id="filePanelFileExplorerTree"]')
.switchFile('browser/3_Ballot.sol') .openFile('browser/3_Ballot.sol')
.assert.containsText('div[title="browser/3_Ballot.sol"]', '3_Ballot.sol') .assert.containsText('div[title="browser/3_Ballot.sol"]', '3_Ballot.sol')
.click('span[class^=dropdownCaret]') .click('span[class^=dropdownCaret]')
.click('#homeItem') .click('#homeItem')

@ -10,7 +10,7 @@ module.exports = {
'Should zoom in editor': function (browser) { 'Should zoom in editor': function (browser) {
browser.waitForElementVisible('div[data-id="mainPanelPluginsContainer"]') browser.waitForElementVisible('div[data-id="mainPanelPluginsContainer"]')
.switchFile('browser/1_Storage.sol') .openFile('browser/1_Storage.sol')
.waitForElementVisible('*[data-id="editorInput"]') .waitForElementVisible('*[data-id="editorInput"]')
.checkElementStyle('*[data-id="editorInput"]', 'font-size', '12px') .checkElementStyle('*[data-id="editorInput"]', 'font-size', '12px')
.click('*[data-id="tabProxyZoomIn"]') .click('*[data-id="tabProxyZoomIn"]')
@ -74,7 +74,7 @@ module.exports = {
'Should highlight source code': function (browser) { 'Should highlight source code': function (browser) {
browser.addFile('sourcehighlight.js', sourcehighlightScript) browser.addFile('sourcehighlight.js', sourcehighlightScript)
.switchFile('browser/sourcehighlight.js') .openFile('browser/sourcehighlight.js')
.executeScript('remix.exeCurrent()') .executeScript('remix.exeCurrent()')
.editorScroll('down', 60) .editorScroll('down', 60)
.waitForElementPresent('.highlightLine32') .waitForElementPresent('.highlightLine32')
@ -87,9 +87,9 @@ module.exports = {
'Should remove 1 highlight from source code': function (browser) { 'Should remove 1 highlight from source code': function (browser) {
browser.addFile('removeSourcehighlightScript.js', removeSourcehighlightScript) browser.addFile('removeSourcehighlightScript.js', removeSourcehighlightScript)
.switchFile('browser/removeSourcehighlightScript.js') .openFile('browser/removeSourcehighlightScript.js')
.executeScript('remix.exeCurrent()') .executeScript('remix.exeCurrent()')
.switchFile('browser/3_Ballot.sol') .openFile('browser/3_Ballot.sol')
.editorScroll('down', 60) .editorScroll('down', 60)
.waitForElementNotPresent('.highlightLine32') .waitForElementNotPresent('.highlightLine32')
.checkElementStyle('.highlightLine40', 'background-color', 'rgb(8, 108, 181)') .checkElementStyle('.highlightLine40', 'background-color', 'rgb(8, 108, 181)')
@ -98,9 +98,9 @@ module.exports = {
'Should remove all highlights from source code': function (browser) { 'Should remove all highlights from source code': function (browser) {
browser.addFile('removeAllSourcehighlightScript.js', removeAllSourcehighlightScript) browser.addFile('removeAllSourcehighlightScript.js', removeAllSourcehighlightScript)
.switchFile('browser/removeAllSourcehighlightScript.js') .openFile('browser/removeAllSourcehighlightScript.js')
.executeScript('remix.exeCurrent()') .executeScript('remix.exeCurrent()')
.switchFile('browser/3_Ballot.sol') .openFile('browser/3_Ballot.sol')
.editorScroll('down', 60) .editorScroll('down', 60)
.waitForElementNotPresent('.highlightLine32') .waitForElementNotPresent('.highlightLine32')
.waitForElementNotPresent('.highlightLine40') .waitForElementNotPresent('.highlightLine40')

@ -31,14 +31,14 @@ module.exports = {
.waitForElementVisible('*[data-id="settingsTabGenerateContractMetadata"]', 5000) .waitForElementVisible('*[data-id="settingsTabGenerateContractMetadata"]', 5000)
.click('*[data-id="settingsTabGenerateContractMetadata"]') .click('*[data-id="settingsTabGenerateContractMetadata"]')
.click('*[data-id="verticalIconsFileExplorerIcons"]') .click('*[data-id="verticalIconsFileExplorerIcons"]')
.switchFile('browser/3_Ballot.sol') .openFile('browser/3_Ballot.sol')
.click('*[data-id="verticalIconsKindsolidity"]') .click('*[data-id="verticalIconsKindsolidity"]')
.pause(2000) .pause(2000)
.click('*[data-id="compilerContainerCompileBtn"]') .click('*[data-id="compilerContainerCompileBtn"]')
.pause(3000) .pause(3000)
.click('*[data-id="verticalIconsKindfileExplorers"]') .click('*[data-id="verticalIconsKindfileExplorers"]')
.switchFile('browser/artifacts') .openFile('browser/artifacts')
.switchFile('browser/artifacts/Ballot.json') .openFile('browser/artifacts/Ballot.json')
}, },
'Should add new github access token': function (browser) { 'Should add new github access token': function (browser) {

@ -44,9 +44,9 @@ module.exports = {
browser browser
.modalFooterCancelClick() .modalFooterCancelClick()
.executeScript(`remix.loadgist('${gistid}')`) .executeScript(`remix.loadgist('${gistid}')`)
.perform((done) => { if (runtimeBrowser === 'chrome') { browser.switchFile('browser/gists') } done() }) .perform((done) => { if (runtimeBrowser === 'chrome') { browser.openFile('browser/gists') } done() })
.switchFile(`browser/gists/${gistid}`) .openFile(`browser/gists/${gistid}`)
.switchFile(`browser/gists/${gistid}/1_Storage.sol`) .openFile(`browser/gists/${gistid}/1_Storage.sol`)
.perform(done) .perform(done)
} }
}) })
@ -86,8 +86,8 @@ module.exports = {
.waitForElementVisible('*[data-id="modalDialogCustomPromptText"]') .waitForElementVisible('*[data-id="modalDialogCustomPromptText"]')
.setValue('*[data-id="modalDialogCustomPromptText"]', testData.validGistId) .setValue('*[data-id="modalDialogCustomPromptText"]', testData.validGistId)
.modalFooterOKClick() .modalFooterOKClick()
.switchFile(`browser/gists/${testData.validGistId}`) .openFile(`browser/gists/${testData.validGistId}`)
.switchFile(`browser/gists/${testData.validGistId}/ApplicationRegistry`) .openFile(`browser/gists/${testData.validGistId}/ApplicationRegistry`)
.waitForElementVisible(`div[title='browser/gists/${testData.validGistId}/ApplicationRegistry']`) .waitForElementVisible(`div[title='browser/gists/${testData.validGistId}/ApplicationRegistry']`)
.assert.containsText(`div[title='browser/gists/${testData.validGistId}/ApplicationRegistry'] > span`, 'ApplicationRegistry') .assert.containsText(`div[title='browser/gists/${testData.validGistId}/ApplicationRegistry'] > span`, 'ApplicationRegistry')
.end() .end()

@ -59,7 +59,7 @@ module.exports = {
function checkDeployShouldFail (browser, callback) { function checkDeployShouldFail (browser, callback) {
let config let config
browser.switchFile('browser/artifacts').switchFile('browser/artifacts/test.json') browser.openFile('browser/artifacts').openFile('browser/artifacts/test.json')
.getEditorValue((content) => { .getEditorValue((content) => {
config = JSON.parse(content) config = JSON.parse(content)
config.deploy['VM:-'].autoDeployLib = false config.deploy['VM:-'].autoDeployLib = false
@ -67,7 +67,7 @@ function checkDeployShouldFail (browser, callback) {
.perform(() => { .perform(() => {
browser.setEditorValue(JSON.stringify(config)) browser.setEditorValue(JSON.stringify(config))
}) })
.switchFile('browser/Untitled5.sol') .openFile('browser/Untitled5.sol')
.selectContract('test') // deploy lib .selectContract('test') // deploy lib
.createContract('') .createContract('')
.assert.containsText('div[class^="terminal"]', '<address> is not a valid address') .assert.containsText('div[class^="terminal"]', '<address> is not a valid address')
@ -77,7 +77,7 @@ function checkDeployShouldFail (browser, callback) {
function checkDeployShouldSucceed (browser, address, callback) { function checkDeployShouldSucceed (browser, address, callback) {
let addressRef let addressRef
let config let config
browser.switchFile('browser/artifacts').switchFile('browser/artifacts/test.json') browser.openFile('browser/artifacts').openFile('browser/artifacts/test.json')
.getEditorValue((content) => { .getEditorValue((content) => {
config = JSON.parse(content) config = JSON.parse(content)
config.deploy['VM:-'].autoDeployLib = false config.deploy['VM:-'].autoDeployLib = false
@ -86,7 +86,7 @@ function checkDeployShouldSucceed (browser, address, callback) {
.perform(() => { .perform(() => {
browser.setEditorValue(JSON.stringify(config)) browser.setEditorValue(JSON.stringify(config))
}) })
.switchFile('browser/Untitled5.sol') .openFile('browser/Untitled5.sol')
.selectContract('test') // deploy lib .selectContract('test') // deploy lib
.createContract('') .createContract('')
.getAddressAtPosition(1, (address) => { .getAddressAtPosition(1, (address) => {

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

@ -13,7 +13,7 @@ module.exports = {
browser browser
.waitForElementVisible('#icon-panel', 10000) .waitForElementVisible('#icon-panel', 10000)
.clickLaunchIcon('fileExplorers') .clickLaunchIcon('fileExplorers')
.switchFile('browser/3_Ballot.sol') .openFile('browser/3_Ballot.sol')
.verifyContracts(['Ballot']) .verifyContracts(['Ballot'])
.click('#publishOnIpfs') .click('#publishOnIpfs')
.getModalBody((value, done) => { .getModalBody((value, done) => {
@ -37,7 +37,7 @@ module.exports = {
browser browser
.waitForElementVisible('#icon-panel') .waitForElementVisible('#icon-panel')
.clickLaunchIcon('fileExplorers') .clickLaunchIcon('fileExplorers')
.switchFile('browser/1_Storage.sol') .openFile('browser/1_Storage.sol')
.clickLaunchIcon('udapp') .clickLaunchIcon('udapp')
.waitForElementVisible('*[data-id="contractDropdownIpfsCheckbox"]') .waitForElementVisible('*[data-id="contractDropdownIpfsCheckbox"]')
.click('*[data-id="contractDropdownIpfsCheckbox"]') .click('*[data-id="contractDropdownIpfsCheckbox"]')
@ -49,7 +49,7 @@ module.exports = {
'Should remember choice after page refresh': function (browser) { 'Should remember choice after page refresh': function (browser) {
browser browser
.refresh() .refresh()
.switchFile('browser/1_Storage.sol') .openFile('browser/1_Storage.sol')
.clickLaunchIcon('udapp') .clickLaunchIcon('udapp')
.waitForElementVisible('*[data-id="contractDropdownIpfsCheckbox"]') .waitForElementVisible('*[data-id="contractDropdownIpfsCheckbox"]')
.verify.elementPresent('*[data-id="contractDropdownIpfsCheckbox"]:checked') .verify.elementPresent('*[data-id="contractDropdownIpfsCheckbox"]:checked')

@ -115,6 +115,8 @@ function runTests (browser, testData) {
}) })
.clickLaunchIcon('fileExplorers') .clickLaunchIcon('fileExplorers')
.waitForElementVisible('[data-path="localhost/folder1"]') .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/contract1.sol"]')
.waitForElementVisible('[data-path="localhost/folder1/renamed_contract_' + browserName + '.sol"]') // check if renamed file is preset .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 + '.sol"]') // check if renamed (old) file is not present

@ -90,7 +90,7 @@ module.exports = {
'Should deploy contract on Goerli Test Network using MetaMask': function (browser) { 'Should deploy contract on Goerli Test Network using MetaMask': function (browser) {
browser.waitForElementPresent('*[data-id="runTabSelectAccount"] option') browser.waitForElementPresent('*[data-id="runTabSelectAccount"] option')
.clickLaunchIcon('fileExplorers') .clickLaunchIcon('fileExplorers')
.switchFile('browser/Greet.sol') .openFile('browser/Greet.sol')
.clickLaunchIcon('udapp') .clickLaunchIcon('udapp')
.waitForElementPresent('*[data-id="Deploy - transact (not payable)"]') .waitForElementPresent('*[data-id="Deploy - transact (not payable)"]')
.click('*[data-id="Deploy - transact (not payable)"]') .click('*[data-id="Deploy - transact (not payable)"]')
@ -141,7 +141,7 @@ module.exports = {
'Should deploy contract on Ethereum Main Network using MetaMask': function (browser) { 'Should deploy contract on Ethereum Main Network using MetaMask': function (browser) {
browser.waitForElementPresent('*[data-id="runTabSelectAccount"] option') browser.waitForElementPresent('*[data-id="runTabSelectAccount"] option')
.clickLaunchIcon('fileExplorers') .clickLaunchIcon('fileExplorers')
.switchFile('browser/Greet.sol') .openFile('browser/Greet.sol')
.clickLaunchIcon('udapp') .clickLaunchIcon('udapp')
.waitForElementPresent('*[data-id="Deploy - transact (not payable)"]') .waitForElementPresent('*[data-id="Deploy - transact (not payable)"]')
.click('*[data-id="Deploy - transact (not payable)"]') .click('*[data-id="Deploy - transact (not payable)"]')

@ -23,7 +23,7 @@ module.exports = {
browser.assert.ok(typeof signature.value === 'string', 'type of signature.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']) .addFile('signMassage.sol', sources[0]['browser/signMassage.sol'])
.switchFile('browser/signMassage.sol') .openFile('browser/signMassage.sol')
.pause(5000) .pause(5000)
.selectContract('ECVerify') .selectContract('ECVerify')
.createContract('') .createContract('')

@ -15,7 +15,7 @@ module.exports = {
'Test Success Import': function (browser) { 'Test Success Import': function (browser) {
browser.addFile('Untitled1.sol', sources[1]['browser/Untitled1.sol']) browser.addFile('Untitled1.sol', sources[1]['browser/Untitled1.sol'])
.addFile('Untitled2.sol', sources[1]['browser/Untitled2.sol']) .addFile('Untitled2.sol', sources[1]['browser/Untitled2.sol'])
.switchFile('browser/Untitled1.sol') .openFile('browser/Untitled1.sol')
.verifyContracts(['test6', 'test4', 'test5']) .verifyContracts(['test6', 'test4', 'test5'])
}, },

@ -27,7 +27,7 @@ module.exports = {
'Should generate test file': function (browser) { 'Should generate test file': function (browser) {
browser.waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]') browser.waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]')
.clickLaunchIcon('fileExplorers') .clickLaunchIcon('fileExplorers')
.switchFile('browser/simple_storage.sol') .openFile('browser/simple_storage.sol')
.click('*[data-id="verticalIconsKindsolidityUnitTesting"]') .click('*[data-id="verticalIconsKindsolidityUnitTesting"]')
.waitForElementPresent('*[data-id="testTabGenerateTestFile"]') .waitForElementPresent('*[data-id="testTabGenerateTestFile"]')
.click('*[data-id="testTabGenerateTestFile"]') .click('*[data-id="testTabGenerateTestFile"]')
@ -100,7 +100,7 @@ module.exports = {
browser.waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]') browser.waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]')
.addFile('compilationError_test.sol', sources[0]['browser/compilationError_test.sol']) .addFile('compilationError_test.sol', sources[0]['browser/compilationError_test.sol'])
.clickLaunchIcon('fileExplorers') .clickLaunchIcon('fileExplorers')
.switchFile('browser/compilationError_test.sol') .openFile('browser/compilationError_test.sol')
.clickLaunchIcon('solidityUnitTesting') .clickLaunchIcon('solidityUnitTesting')
.click('*[data-id="testTabCheckAllTests"]') .click('*[data-id="testTabCheckAllTests"]')
.clickElementAtPosition('.singleTestLabel', 3) .clickElementAtPosition('.singleTestLabel', 3)
@ -115,7 +115,7 @@ module.exports = {
browser.waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]') browser.waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]')
.addFile('deployError_test.sol', sources[0]['browser/deployError_test.sol']) .addFile('deployError_test.sol', sources[0]['browser/deployError_test.sol'])
.clickLaunchIcon('fileExplorers') .clickLaunchIcon('fileExplorers')
.switchFile('browser/deployError_test.sol') .openFile('browser/deployError_test.sol')
.clickLaunchIcon('solidityUnitTesting') .clickLaunchIcon('solidityUnitTesting')
.click('*[data-id="testTabCheckAllTests"]') .click('*[data-id="testTabCheckAllTests"]')
.clickElementAtPosition('.singleTestLabel', 4) .clickElementAtPosition('.singleTestLabel', 4)
@ -129,7 +129,7 @@ module.exports = {
browser.waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]') browser.waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]')
.addFile('methodFailure_test.sol', sources[0]['browser/methodFailure_test.sol']) .addFile('methodFailure_test.sol', sources[0]['browser/methodFailure_test.sol'])
.clickLaunchIcon('fileExplorers') .clickLaunchIcon('fileExplorers')
.switchFile('browser/methodFailure_test.sol') .openFile('browser/methodFailure_test.sol')
.clickLaunchIcon('solidityUnitTesting') .clickLaunchIcon('solidityUnitTesting')
.click('*[data-id="testTabCheckAllTests"]') .click('*[data-id="testTabCheckAllTests"]')
.clickElementAtPosition('.singleTestLabel', 5) .clickElementAtPosition('.singleTestLabel', 5)
@ -150,7 +150,7 @@ function runTests (browser) {
browser browser
.waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]') .waitForElementPresent('*[data-id="verticalIconsKindfileExplorers"]')
.clickLaunchIcon('fileExplorers') .clickLaunchIcon('fileExplorers')
.switchFile('browser/3_Ballot.sol') .openFile('browser/3_Ballot.sol')
.clickLaunchIcon('solidityUnitTesting') .clickLaunchIcon('solidityUnitTesting')
.pause(500) .pause(500)
.scrollAndClick('#runTestsTabRunAction') .scrollAndClick('#runTestsTabRunAction')

@ -57,7 +57,7 @@ module.exports = {
'Async/Await Script': function (browser) { 'Async/Await Script': function (browser) {
browser browser
.addFile('asyncAwait.js', { content: asyncAwait }) .addFile('asyncAwait.js', { content: asyncAwait })
.switchFile('browser/asyncAwait.js') .openFile('browser/asyncAwait.js')
.executeScript(`remix.execute('browser/asyncAwait.js')`) .executeScript(`remix.execute('browser/asyncAwait.js')`)
.journalLastChild('Waiting Promise') .journalLastChild('Waiting Promise')
.pause(5500) .pause(5500)
@ -67,7 +67,7 @@ module.exports = {
'Call Remix File Manager from a script': function (browser) { 'Call Remix File Manager from a script': function (browser) {
browser browser
.addFile('asyncAwaitWithFileManagerAccess.js', { content: asyncAwaitWithFileManagerAccess }) .addFile('asyncAwaitWithFileManagerAccess.js', { content: asyncAwaitWithFileManagerAccess })
.switchFile('browser/asyncAwaitWithFileManagerAccess.js') .openFile('browser/asyncAwaitWithFileManagerAccess.js')
.pause(5000) .pause(5000)
.executeScript(`remix.execute('browser/asyncAwaitWithFileManagerAccess.js')`) .executeScript(`remix.execute('browser/asyncAwaitWithFileManagerAccess.js')`)
.pause(6000) .pause(6000)
@ -108,7 +108,7 @@ const asyncAwaitWithFileManagerAccess = `
var run = async () => { var run = async () => {
console.log('Waiting Promise') console.log('Waiting Promise')
var result = await p() var result = await p()
let text = await remix.call('fileManager', 'getFile', 'browser/3_Ballot.sol') let text = await remix.call('fileManager', 'readFile', 'browser/3_Ballot.sol')
console.log('result - ', text) console.log('result - ', text)
} }

Loading…
Cancel
Save