Merge pull request #1046 from ethereum/fixlocalhost

Fix localhost explorer & add tests
pull/1/head
yann300 7 years ago committed by GitHub
commit 4bf5f6820b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      contracts/folder1/contract_chrome_toremove.sol
  2. 1
      contracts/folder1/contract_firefox_toremove.sol
  3. 7
      src/app/files/basicReadOnlyExplorer.js
  4. 18
      src/app/files/file-explorer.js
  5. 2
      src/app/files/fileManager.js
  6. 6
      src/app/files/shared-folder.js
  7. 23
      src/app/ui/contextMenu.js
  8. 82
      test-browser/helpers/contracts.js
  9. 66
      test-browser/tests/sharedFolderExplorer.js

@ -0,0 +1 @@
contract test2 { function get () returns (uint) { return 11; }}

@ -0,0 +1 @@
contract test2 { function get () returns (uint) { return 11; }}

@ -23,11 +23,13 @@ class BasicReadOnlyExplorer {
exists (path) {
if (!this.files) return false
return this.files[path] !== undefined
var unprefixedPath = this.removePrefix(path)
return this.files[unprefixedPath] !== undefined
}
get (path, cb) {
var content = this.files[path]
var unprefixedPath = this.removePrefix(path)
var content = this.files[unprefixedPath]
if (!content) {
content = this.files[this.type + '/' + this.normalizedNames[path]]
}
@ -48,6 +50,7 @@ class BasicReadOnlyExplorer {
try { // lazy try to format JSON
content = JSON.stringify(JSON.parse(content), null, '\t')
} catch (e) {}
if (!rawPath) rawPath = path
// splitting off the path in a tree structure, the json tree is used in `resolveDirectory`
var split = path
var folder = false

@ -6,6 +6,7 @@ var modalDialogCustom = require('../ui/modal-dialog-custom')
var remixLib = require('remix-lib')
var EventManager = remixLib.EventManager
var contextMenu = require('../ui/contextMenu')
var addTooltip = require('../ui/tooltip')
var helper = require('../../lib/helper')
var styleGuide = remixLib.ui.themeChooser
@ -163,11 +164,12 @@ function fileExplorer (appAPI, files) {
self.treeView.event.register('leafRightClick', function (key, data, label, event) {
contextMenu(event, {
'Rename': () => {
if (self.files.readonly) return
if (self.files.readonly) { return addTooltip('cannot rename. ' + self.files.type + ' is a read only explorer') }
var name = label.querySelector('label[data-path="' + key + '"]')
if (name) editModeOn(name)
},
'Delete': () => {
if (self.files.readonly) { return addTooltip('cannot delete. ' + self.files.type + ' is a read only explorer') }
modalDialogCustom.confirm(null, 'Do you want to delete this file?', () => { files.remove(key) }, () => {})
}
})
@ -218,13 +220,21 @@ function fileExplorer (appAPI, files) {
})
var textUnderEdit = null
var textInRename = false
function selectElementContents (el) {
var range = document.createRange()
range.selectNodeContents(el)
var sel = window.getSelection()
sel.removeAllRanges()
sel.addRange(range)
}
function editModeOn (label) {
textUnderEdit = label.innerText
label.setAttribute('contenteditable', true)
label.classList.add(css.rename)
label.focus()
selectElementContents(label)
}
function editModeOff (event) {
@ -249,8 +259,7 @@ function fileExplorer (appAPI, files) {
}
if (event.which === 13) event.preventDefault()
if (!textInRename && (event.type === 'blur' || event.which === 27 || event.which === 13) && label.getAttribute('contenteditable')) {
textInRename = true
if (event.type === 'blur' || event.which === 13 && label.getAttribute('contenteditable')) {
var isFolder = label.className.indexOf('folder') !== -1
var save = textUnderEdit !== label.innerText
if (save) {
@ -258,7 +267,6 @@ function fileExplorer (appAPI, files) {
}
label.removeAttribute('contenteditable')
label.classList.remove(css.rename)
textInRename = false
}
}
}

@ -114,8 +114,6 @@ class FileManager {
return $(this).find('.name').text() === newfile
})
if (active.length) active.addClass('active')
else this.switchFile()
// $('#input').toggle(active)
$('#output').toggle(active)
}

@ -49,8 +49,10 @@ module.exports = class SharedFolder {
}
init (cb) {
this._isReady = true
cb()
this._remixd.ensureSocket((error) => {
this._isReady = !error
cb(error)
})
}
// @TODO: refactor all `this._remixd.call(....)` uses into `this.remixd[api](...)`

@ -13,6 +13,7 @@ var css = csjs`
width:150px;
background: ${styles.appProperties.solidBorderBox_BackgroundColor};
border-radius: 2px;
z-index: 1000;
}
.liitem
@ -42,9 +43,17 @@ var css = csjs`
module.exports = (event, items) => {
event.preventDefault()
function hide (event, force) {
if (force || (event.target !== container)) {
container.parentElement.removeChild(container)
}
window.removeEventListener('click', hide)
}
var menu = Object.keys(items).map((item, index) => {
var current = yo`<li class=${css.liitem}>${item}</li>`
current.onclick = () => items[item]()
var current = yo`<li id="menuitem${item.toLowerCase()}" class=${css.liitem}>${item}</li>`
current.onclick = () => { hide(null, true); items[item]() }
return current
})
var container = yo`<div class=${css.container}><ul id='menuitems'>${menu}</ul></div>`
@ -52,12 +61,8 @@ module.exports = (event, items) => {
container.style.top = event.pageY + 'px'
container.style.display = 'block'
function hide (event) {
if (event.target !== container) {
container.parentElement.removeChild(container)
}
window.removeEventListener('click', hide)
}
window.addEventListener('click', hide)
document.querySelector('body').appendChild(container)
setTimeout(() => {
window.addEventListener('click', hide)
}, 500)
}

@ -17,7 +17,10 @@ module.exports = {
createContract,
modalFooterOKClick,
setEditorValue,
getEditorValue
getEditorValue,
testEditorValue,
renameFile,
removeFile
}
function getCompiledContracts (browser, compiled, callback) {
@ -146,12 +149,13 @@ function testFunction (fnFullName, txHash, log, expectedInput, expectedReturn, e
return this
}
function setEditorValue (value) {
function setEditorValue (value, callback) {
this.perform((client, done) => {
this.execute(function (value) {
document.getElementById('input').editor.session.setValue(value)
}, [value], function (result) {
done()
if (callback) callback()
})
})
return this
@ -184,6 +188,13 @@ function getEditorValue (callback) {
return this
}
function testEditorValue (testvalue, callback) {
this.getEditorValue((value) => {
this.assert.equal(testvalue, value)
callback()
})
}
function modalFooterOKClick () {
this.perform((client, done) => {
this.execute(function () {
@ -215,6 +226,73 @@ function addFile (browser, name, content, done) {
})
}
function renameFile (browser, path, newFileName, renamedPath, done) {
browser.execute(function (path) {
function contextMenuClick (element) {
var evt = element.ownerDocument.createEvent('MouseEvents')
var RIGHT_CLICK_BUTTON_CODE = 2 // the same for FF and IE
evt.initMouseEvent('contextmenu', true, true,
element.ownerDocument.defaultView, 1, 0, 0, 0, 0, false,
false, false, false, RIGHT_CLICK_BUTTON_CODE, null)
if (document.createEventObject) {
// dispatch for IE
return element.fireEvent('onclick', evt)
} else {
// dispatch for firefox + others
return !element.dispatchEvent(evt)
}
}
contextMenuClick(document.querySelector('[data-path="' + path + '"]'))
}, [path], function (result) {
browser
.click('#menuitemrename')
.perform((client, doneSetValue) => {
browser.execute(function (path, addvalue) {
document.querySelector('[data-path="' + path + '"]').innerHTML = addvalue
}, [path, newFileName], () => {
doneSetValue()
})
})
.click('body') // blur
.pause(500)
.click('#modal-footer-ok')
.waitForElementNotPresent('[data-path="' + path + '"]')
.waitForElementPresent('[data-path="' + renamedPath + '"]')
.perform(() => {
done()
})
})
}
function removeFile (browser, path, done) {
browser.execute(function (path, value) {
function contextMenuClick (element) {
var evt = element.ownerDocument.createEvent('MouseEvents')
var RIGHT_CLICK_BUTTON_CODE = 2 // the same for FF and IE
evt.initMouseEvent('contextmenu', true, true,
element.ownerDocument.defaultView, 1, 0, 0, 0, 0, false,
false, false, false, RIGHT_CLICK_BUTTON_CODE, null)
if (document.createEventObject) {
// dispatch for IE
return element.fireEvent('onclick', evt)
} else {
// dispatch for firefox + others
return !element.dispatchEvent(evt)
}
}
contextMenuClick(document.querySelector('[data-path="' + path + '"]'))
}, [path], function (result) {
browser
.click('#menuitemdelete')
.pause(500)
.click('#modal-footer-ok')
.waitForElementNotPresent('[data-path="' + path + '"]')
.perform(() => {
done()
})
})
}
function useFilter (browser, filter, test, done) {
if (browser.options.desiredCapabilities.browserName === 'chrome') { // nightwatch deos not handle well that part.... works locally
done()

@ -23,6 +23,12 @@ module.exports = {
}
function runTests (browser, testData) {
browser.testFunction = contractHelper.testFunction
browser.clickFunction = contractHelper.clickFunction
browser.setEditorValue = contractHelper.setEditorValue
browser.modalFooterOKClick = contractHelper.modalFooterOKClick
browser.getEditorValue = contractHelper.getEditorValue
browser.testEditorValue = contractHelper.testEditorValue
var browserName = browser.options.desiredCapabilities.browserName
if (browserName === 'safari' || browserName === 'internet explorer') {
console.log('do not run remixd test for ' + browserName + ': sauce labs doesn\'t seems to handle websocket')
@ -38,14 +44,66 @@ function runTests (browser, testData) {
.click('[data-path="localhost"]')
.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')
.assert.containsText('[data-path="localhost/folder1/contract1.sol"]', 'contract1.sol')
.assert.containsText('[data-path="localhost/folder1/contract2.sol"]', 'contract2.sol')
.assert.containsText('[data-path="localhost/folder1/contract2.sol"]', 'contract2.sol') // load and test sub folder
.click('[data-path="localhost/folder1/contract2.sol"]')
.waitForElementPresent('#compileTabView select option', 50000, true, function () {
contractHelper.verifyContract(browser, ['test2'], function () {
browser.click('.websocketconn').end()
.click('[data-path="localhost/folder1/contract1.sol"]') // open localhost/folder1/contract1.sol
.pause(1000)
.perform(function (done) { // check the content and replace by another
browser.testEditorValue('contract test1 { function get () returns (uint) { return 10; }}', () => {
console.log('testEditorValue')
done()
})
})
.perform(function (done) {
browser.setEditorValue('contract test1Changed { function get () returns (uint) { return 10; }}', () => {
console.log('setEditorValue')
done()
})
})
.perform(function (done) {
browser.testEditorValue('contract test1Changed { function get () returns (uint) { return 10; }}', () => {
console.log('testEditorValue')
done()
})
})
.perform(function (done) {
browser.setEditorValue('contract test1 { function get () returns (uint) { return 10; }}', () => {
console.log('setEditorValue')
done()
})
})
.click('[data-path="localhost/folder1/contract_' + browserName + '.sol"]') // rename a file and check
.pause(1000)
.perform(function (done) {
contractHelper.renameFile(browser, 'localhost/folder1/contract_' + browserName + '.sol', 'renamed_contract_' + browserName + '.sol',
'localhost/folder1/renamed_contract_' + browserName + '.sol', () => {
console.log('tested file renaming')
done()
})
})
.pause(1000)
.perform(function (done) { // remove a file and check
contractHelper.removeFile(browser, 'localhost/folder1/contract_' + browserName + '_toremove.sol', () => {
console.log('tested file removing')
done()
})
})
.perform(function () {
browser.click('[data-path="localhost"]') // collapse and expand
.waitForElementNotVisible('[data-path="localhost/folder1"]')
.click('[data-path="localhost"]')
.waitForElementVisible('[data-path="localhost/folder1"]')
.click('[data-path="localhost/folder1"]')
.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"]')
.click('.websocketconn')
.end()
})
}

Loading…
Cancel
Save