diff --git a/ci/makeMockCompiler.js b/ci/makeMockCompiler.js index 987f408d49..82c6049d44 100644 --- a/ci/makeMockCompiler.js +++ b/ci/makeMockCompiler.js @@ -9,7 +9,6 @@ compiler.loadRemoteVersion(defaultVersion, (error, solcSnapshot) => { if (error) console.log(error) var compilationResult = {} gatherCompilationResults('./test-browser/tests/', compilationResult, solcSnapshot) - gatherCompilationResults('./test-browser/tests/units/', compilationResult, solcSnapshot) replaceSolCompiler(compilationResult, solcSnapshot) }) diff --git a/package.json b/package.json index 894b2e92f5..ba37f98705 100644 --- a/package.json +++ b/package.json @@ -153,7 +153,8 @@ "make-mock-compiler": "node ci/makeMockCompiler.js", "minify": "uglifyjs --in-source-map inline --source-map-inline -c warnings=false", "nightwatch_local": "nightwatch --config nightwatch.js --env local", - "nightwatch_local_general": "nightwatch ./test-browser/tests/generalTests.js --config nightwatch.js --env local ", + "nightwatch_local_recorder": "nightwatch ./test-browser/tests/recorder.js --config nightwatch.js --env local ", + "nightwatch_local_signingMessage": "nightwatch ./test-browser/tests/signingMessage.js --config nightwatch.js --env local ", "nightwatch_local_sharedFolderExplorer": "nightwatch ./test-browser/tests/sharedFolderExplorer.js --config nightwatch.js --env local ", "nightwatch_local_debugger": "nightwatch --config nightwatch_debugger.js --env local", "nightwatch_remote_chrome": "nightwatch --config nightwatch.js --env chrome", diff --git a/test-browser/commands/clickInstance.js b/test-browser/commands/clickInstance.js new file mode 100644 index 0000000000..2f81ab47a1 --- /dev/null +++ b/test-browser/commands/clickInstance.js @@ -0,0 +1,11 @@ +const EventEmitter = require('events') + +class ClickInstance extends EventEmitter { + command (index) { + index = index + 2 + this.api.click('.instance:nth-of-type(' + index + ') > div > button').perform(() => { this.emit('complete') }) + return this + } +} + +module.exports = ClickInstance diff --git a/test-browser/tests/generalTests.js b/test-browser/tests/generalTests.js deleted file mode 100644 index ad3de924d1..0000000000 --- a/test-browser/tests/generalTests.js +++ /dev/null @@ -1,359 +0,0 @@ -'use strict' -var init = require('../helpers/init') -var sauce = require('./sauce') - -module.exports = { - before: function (browser, done) { - init(browser, done) - }, - '@sources': function () { - return sources - }, - 'Test Simple Contract': function (browser) { - console.log('testSimpleContract') - browser.testContracts('Untitled.sol', sources[0]['browser/Untitled.sol'], ['test1', 'test2']) - }, - 'Test Success Import': function (browser) { - console.log('testSuccessImport') - browser.addFile('Untitled1.sol', sources[1]['browser/Untitled1.sol']) - .addFile('Untitled2.sol', sources[1]['browser/Untitled2.sol']) - .switchFile('browser/Untitled1.sol') - .verifyContracts(['test6', 'test4', 'test5']) - }, - - 'Test Failed Import': function (browser) { - console.log('testFailedImport') - browser.addFile('Untitled3.sol', sources[2]['browser/Untitled3.sol']) - .clickLaunchIcon('solidity') - .assert.containsText('#compileTabView .error pre', 'Unable to import "browser/Untitled11.sol": File not found') - }, - 'Add Lib Test File': function (browser) { - browser.addFile('Untitled5.sol', sources[5]['browser/Untitled5.sol']) - }, - 'Test Auto Deploy Lib': function (browser) { - console.log('testAutoDeployLib') - let addressRef - browser.verifyContracts(['test']) - .selectContract('test') - .createContract('') - .getAddressAtPosition(0, (address) => { - console.log('testAutoDeployLib ' + address) - addressRef = address - }) - .waitForElementPresent('.instance:nth-of-type(2)') - .click('.instance:nth-of-type(2) > div > button') - .perform((done) => { - browser.testConstantFunction(addressRef, 'get - call', '', '0: uint256: 45').perform(() => { - done() - }) - }) - }, - 'Test Manual Deploy Lib': function (browser) { - console.log('testManualDeployLib') - browser.click('i[class^="clearinstance"]') - .pause(5000) - .clickLaunchIcon('settings') - .click('#generatecontractmetadata') - .clickLaunchIcon('solidity') - .click('#compileTabView button[title="Compile"]') // that should generate the JSON artefact - .verifyContracts(['test']) - .selectContract('lib') // deploy lib - .createContract('') - .perform((done) => { - browser.getAddressAtPosition(0, (address) => { - console.log(address) - checkDeployShouldFail(browser, () => { - checkDeployShouldSucceed(browser, address, () => { - done() - }) - }) - }) - }) - }, - 'Test Signature': function (browser) { - let hash, signature - browser.signMessage('test message', (h, s) => { - hash = h - signature = s - console.log('hash', hash) - console.log('signature', signature) - 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[6]['browser/signMassage.sol']) - .switchFile('browser/signMassage.sol') - .selectContract('ECVerify') - .createContract('') - .waitForElementPresent('.instance:nth-of-type(4)') - .click('.instance:nth-of-type(4) > div > button') - .perform((done) => { - browser.getAttribute('.instance:nth-of-type(4)', 'id', (result) => { - // skip 'instance' part of e.g. 'instance0x692a70d2e424a56d2c6c27aa97d1a86395877b3a' - const address = result.value.slice('instance'.length) - console.log('Test Signature', result) - var inputs = `"${hash.value}","${signature.value}"` - console.log('Test Signature Input', inputs) - browser.clickFunction('ecrecovery - call', { types: 'bytes32 hash, bytes sig', values: inputs }) - .pause(5000) - .verifyCallReturnValue( - address, - ['0: address: 0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c']) - .perform(() => { - done() - }) - }) - }) - .end() - }, - tearDown: sauce -} - -function checkDeployShouldFail (browser, callback) { - let config - browser.switchFile('browser/test.json') - .getEditorValue((content) => { - config = JSON.parse(content) - config.deploy['VM:-'].autoDeployLib = false - }) - .perform(() => { - browser.setEditorValue(JSON.stringify(config)) - }) - .switchFile('browser/Untitled5.sol') - .selectContract('test') // deploy lib - .createContract('') - .assert.containsText('div[class^="terminal"]', '
is not a valid address') - .perform(() => { callback() }) -} - -function checkDeployShouldSucceed (browser, address, callback) { - let addressRef - let config - browser.switchFile('browser/test.json') - .getEditorValue((content) => { - config = JSON.parse(content) - config.deploy['VM:-'].autoDeployLib = false - config.deploy['VM:-']['linkReferences']['browser/Untitled5.sol'].lib = address - }) - .perform(() => { - browser.setEditorValue(JSON.stringify(config)) - }) - .switchFile('browser/Untitled5.sol') - .selectContract('test') // deploy lib - .createContract('') - .getAddressAtPosition(1, (address) => { - addressRef = address - }) - .waitForElementPresent('.instance:nth-of-type(3)') - .click('.instance:nth-of-type(3) > div > button') - .perform(() => { - browser - .testConstantFunction(addressRef, 'get - call', '', '0: uint256: 45') - .perform(() => { callback() }) - }) -} - -/* -function testGitHubImport (browser, callback) { - contractHelper.addFile(browser, 'Untitled4.sol', sources[3]['browser/Untitled4.sol'], () => { - browser.pause(10000) - .perform(function () { - contractHelper.verifyContract(browser, ['browser/Untitled4.sol:test7', 'github.com/ethereum/ens/contracts/AbstractENS.sol:AbstractENS', 'github.com/ethereum/ens/contracts/ENS.sol:ENS'], function () { - callback(null, browser) - }) - }) - }) -} -*/ - -var abstractENS = ` -contract AbstractENS { - function owner(bytes32 node) public view returns(address); - function resolver(bytes32 node) public view returns(address); - function ttl(bytes32 node) public view returns(uint64); - function setOwner(bytes32 node, address owner) public; - function setSubnodeOwner(bytes32 node, bytes32 label, address owner) public; - function setResolver(bytes32 node, address resolver) public; - function setTTL(bytes32 node, uint64 ttl) public; - - // Logged when the owner of a node assigns a new owner to a subnode. - event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner); - - // Logged when the owner of a node transfers ownership to a new account. - event Transfer(bytes32 indexed node, address owner); - - // Logged when the resolver for a node changes. - event NewResolver(bytes32 indexed node, address resolver); - - // Logged when the TTL of a node changes - event NewTTL(bytes32 indexed node, uint64 ttl); -}` - -var ENS = `pragma solidity ^0.4.0; - -import './AbstractENS.sol'; - -/** - * The ENS registry contract. - */ -contract ENS is AbstractENS { - struct Record { - address owner; - address resolver; - uint64 ttl; - } - - mapping(bytes32=>Record) records; - - // Permits modifications only by the owner of the specified node. - modifier only_owner(bytes32 node) { - if (records[node].owner != msg.sender) revert(); - _; - } - - /** - * Constructs a new ENS registrar. - */ - constructor() public { - records[0].owner = msg.sender; - } - - /** - * Returns the address that owns the specified node. - */ - function owner(bytes32 node) public view returns (address) { - return records[node].owner; - } - - /** - * Returns the address of the resolver for the specified node. - */ - function resolver(bytes32 node) public view returns (address) { - return records[node].resolver; - } - - /** - * Returns the TTL of a node, and any records associated with it. - */ - function ttl(bytes32 node) public view returns (uint64) { - return records[node].ttl; - } - - /** - * Transfers ownership of a node to a new address. May only be called by the current - * owner of the node. - * @param node The node to transfer ownership of. - * @param owner The address of the new owner. - */ - function setOwner(bytes32 node, address owner) public only_owner(node) { - emit Transfer(node, owner); - records[node].owner = owner; - } - - /** - * Transfers ownership of a subnode sha3(node, label) to a new address. May only be - * called by the owner of the parent node. - * @param node The parent node. - * @param label The hash of the label specifying the subnode. - * @param owner The address of the new owner. - */ - function setSubnodeOwner(bytes32 node, bytes32 label, address owner) public only_owner(node) { - bytes32 subnode = keccak256(abi.encodePacked(node, label)); - emit NewOwner(node, label, owner); - records[subnode].owner = owner; - } - - /** - * Sets the resolver address for the specified node. - * @param node The node to update. - * @param resolver The address of the resolver. - */ - function setResolver(bytes32 node, address resolver) public only_owner(node) { - emit NewResolver(node, resolver); - records[node].resolver = resolver; - } - - /** - * Sets the TTL for the specified node. - * @param node The node to update. - * @param ttl The TTL in seconds. - */ - function setTTL(bytes32 node, uint64 ttl) public only_owner(node) { - emit NewTTL(node, ttl); - records[node].ttl = ttl; - } -}` - -var sources = [ - { - 'browser/Untitled.sol': {content: 'contract test1 {} contract test2 {}'} - }, - { - 'browser/Untitled1.sol': {content: 'import "./Untitled2.sol"; contract test6 {}'}, - 'browser/Untitled2.sol': {content: 'contract test4 {} contract test5 {}'} - }, - { - 'browser/Untitled3.sol': {content: 'import "./Untitled11.sol"; contract test6 {}'} - }, - { - 'browser/Untitled4.sol': {content: 'import "github.com/ethereum/ens/contracts/ENS.sol"; contract test7 {}'}, - 'github.com/ethereum/ens/contracts/ENS.sol': {content: ENS} - }, - { - 'browser/Untitled4.sol': {content: 'import "github.com/ethereum/ens/contracts/ENS.sol"; contract test7 {}'}, - 'github.com/ethereum/ens/contracts/ENS.sol': {content: ENS}, - 'github.com/ethereum/ens/contracts/AbstractENS.sol': {content: abstractENS} - }, - { - 'browser/Untitled5.sol': {content: `library lib { - function getInt () public view returns (uint) { - return 45; - } - } - - contract test { - function get () public view returns (uint) { - return lib.getInt(); - } - }`} - }, - { - 'browser/signMassage.sol': {content: ` - contract SignMassageTest { - function testRecovery(bytes32 h, uint8 v, bytes32 r, bytes32 s) public pure returns (address) { - return ecrecover(h, v, r, s); - } - } - - library ECVerify { - function ecrecovery(bytes32 hash, bytes memory sig) public pure returns (address) { - bytes32 r; - bytes32 s; - uint8 v; - - if (sig.length != 65) { - return address(0); - } - - assembly { - r := mload(add(sig, 32)) - s := mload(add(sig, 64)) - v := and(mload(add(sig, 65)), 255) - } - - if (v < 27) { - v += 27; - } - - if (v != 27 && v != 28) { - return address(0); - } - - return ecrecover(hash, v, r, s); - } - - function ecverify(bytes32 hash, bytes memory sig, address signer) public pure returns (bool) { - return signer == ecrecovery(hash, sig); - } - }`} - } -] diff --git a/test-browser/tests/libraryDeployment.js b/test-browser/tests/libraryDeployment.js new file mode 100644 index 0000000000..415b9c36fa --- /dev/null +++ b/test-browser/tests/libraryDeployment.js @@ -0,0 +1,115 @@ +'use strict' +var init = require('../helpers/init') +var sauce = require('./sauce') + +module.exports = { + before: function (browser, done) { + init(browser, done) + }, + '@sources': function () { + return sources + }, + 'Add Lib Test File': function (browser) { + browser.addFile('Untitled5.sol', sources[0]['browser/Untitled5.sol']) + }, + 'Test Auto Deploy Lib': function (browser) { + let addressRef + browser.verifyContracts(['test']) + .selectContract('test') + .createContract('') + .getAddressAtPosition(0, (address) => { + console.log('testAutoDeployLib ' + address) + addressRef = address + }) + .waitForElementPresent('.instance:nth-of-type(2)') + .click('.instance:nth-of-type(2) > div > button') + .perform((done) => { + browser.testConstantFunction(addressRef, 'get - call', '', '0: uint256: 45').perform(() => { + done() + }) + }) + }, + 'Test Manual Deploy Lib': function (browser) { + console.log('testManualDeployLib') + browser.click('i[class^="clearinstance"]') + .pause(5000) + .clickLaunchIcon('settings') + .click('#generatecontractmetadata') + .clickLaunchIcon('solidity') + .click('#compileTabView button[title="Compile"]') // that should generate the JSON artefact + .verifyContracts(['test']) + .selectContract('lib') // deploy lib + .createContract('') + .perform((done) => { + browser.getAddressAtPosition(0, (address) => { + console.log(address) + checkDeployShouldFail(browser, () => { + checkDeployShouldSucceed(browser, address, () => { + done() + }) + }) + }) + }) + }, + tearDown: sauce +} + +function checkDeployShouldFail (browser, callback) { + let config + browser.switchFile('browser/test.json') + .getEditorValue((content) => { + config = JSON.parse(content) + config.deploy['VM:-'].autoDeployLib = false + }) + .perform(() => { + browser.setEditorValue(JSON.stringify(config)) + }) + .switchFile('browser/Untitled5.sol') + .selectContract('test') // deploy lib + .createContract('') + .assert.containsText('div[class^="terminal"]', ' is not a valid address') + .perform(() => { callback() }) +} + +function checkDeployShouldSucceed (browser, address, callback) { + let addressRef + let config + browser.switchFile('browser/test.json') + .getEditorValue((content) => { + config = JSON.parse(content) + config.deploy['VM:-'].autoDeployLib = false + config.deploy['VM:-']['linkReferences']['browser/Untitled5.sol'].lib = address + }) + .perform(() => { + browser.setEditorValue(JSON.stringify(config)) + }) + .switchFile('browser/Untitled5.sol') + .selectContract('test') // deploy lib + .createContract('') + .getAddressAtPosition(1, (address) => { + addressRef = address + }) + .waitForElementPresent('.instance:nth-of-type(3)') + .click('.instance:nth-of-type(3) > div > button') + .perform(() => { + browser + .testConstantFunction(addressRef, 'get - call', '', '0: uint256: 45') + .perform(() => { callback() }) + }) +} + +var sources = [ + { + 'browser/Untitled5.sol': {content: `library lib { + function getInt () public view returns (uint) { + return 45; + } + } + + contract test { + function get () public view returns (uint) { + return lib.getInt(); + } + }`} + } +] diff --git a/test-browser/tests/units/testRecorder.js b/test-browser/tests/recorder.js similarity index 94% rename from test-browser/tests/units/testRecorder.js rename to test-browser/tests/recorder.js index 8a2996800c..50b8972e6a 100644 --- a/test-browser/tests/units/testRecorder.js +++ b/test-browser/tests/recorder.js @@ -1,11 +1,16 @@ 'use strict' +var sauce = require('./sauce') +var init = require('../helpers/init') module.exports = { - '@disabled': true, // run by compiling. + before: function (browser, done) { + init(browser, done) + }, '@sources': function () { return sources }, - test: function (browser, callback) { + 'Test Recorder': function (browser) { + var addressRef browser.addFile('scenario.json', {content: records}) .clickLaunchIcon('run') .click('div[class^="cardContainer"] i[class^="arrow"]') @@ -18,8 +23,14 @@ module.exports = { .clickFunction('getAddress - call') .clickFunction('getFromLib - call') .waitForElementPresent('div[class^="contractActionsContainer"] div[class^="value"] ul') - .verifyCallReturnValue('0x35ef07393b57464e93deb59175ff72e6499450cf', ['0: uint256: 1', '0: uint256: 3456', '0: address: 0x35eF07393b57464e93dEB59175fF72E6499450cF']) - + .getAddressAtPosition(1, (address) => { + console.log('Test Recorder ' + address) + addressRef = address + }) + .perform((done) => { + browser.verifyCallReturnValue(addressRef, ['0: uint256: 1', '0: uint256: 3456', '0: address: 0xbBF289D846208c16EDc8474705C748aff07732dB']) + .perform(() => done()) + }) .click('i[class^="clearinstance"]') .testContracts('testRecorder.sol', sources[0]['browser/testRecorder.sol'], ['testRecorder']) .createContract('12') @@ -41,10 +52,9 @@ module.exports = { browser.assert.equal(JSON.stringify(parsed.transactions[1].record.type), JSON.stringify(scenario.transactions[1].record.type)) browser.assert.equal(JSON.stringify(parsed.transactions[1].record.from), JSON.stringify(scenario.transactions[1].record.from)) }) - .perform(() => { - callback() - }) - } + .end() + }, + tearDown: sauce } var sources = [{'browser/testRecorder.sol': {content: `contract testRecorder { diff --git a/test-browser/tests/signingMessage.js b/test-browser/tests/signingMessage.js new file mode 100644 index 0000000000..4e9a8aa6a6 --- /dev/null +++ b/test-browser/tests/signingMessage.js @@ -0,0 +1,89 @@ +'use strict' +var init = require('../helpers/init') +var sauce = require('./sauce') + +module.exports = { + before: function (browser, done) { + init(browser, done) + }, + '@sources': function () { + return sources + }, + 'Test Signature': function (browser) { + let hash, signature + browser.clickLaunchIcon('run').signMessage('test message', (h, s) => { + hash = h + signature = s + console.log('hash', hash) + console.log('signature', signature) + 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']) + .switchFile('browser/signMassage.sol') + .selectContract('ECVerify') + .createContract('') + .clickInstance(0) + .perform((done) => { + browser.getAddressAtPosition(0, (address) => { + // skip 'instance' part of e.g. 'instance0x692a70d2e424a56d2c6c27aa97d1a86395877b3a' + console.log('Test Signature address', address) + var inputs = `"${hash.value}","${signature.value}"` + console.log('Test Signature Input', inputs) + browser.clickFunction('ecrecovery - call', { types: 'bytes32 hash, bytes sig', values: inputs }) + .pause(5000) + .verifyCallReturnValue( + address, + ['0: address: 0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c']) + .perform(() => { + done() + }) + }) + }) + .end() + }, + tearDown: sauce +} + +var sources = [ + { + 'browser/signMassage.sol': {content: ` + contract SignMassageTest { + function testRecovery(bytes32 h, uint8 v, bytes32 r, bytes32 s) public pure returns (address) { + return ecrecover(h, v, r, s); + } + } + + library ECVerify { + function ecrecovery(bytes32 hash, bytes memory sig) public pure returns (address) { + bytes32 r; + bytes32 s; + uint8 v; + + if (sig.length != 65) { + return address(0); + } + + assembly { + r := mload(add(sig, 32)) + s := mload(add(sig, 64)) + v := and(mload(add(sig, 65)), 255) + } + + if (v < 27) { + v += 27; + } + + if (v != 27 && v != 28) { + return address(0); + } + + return ecrecover(hash, v, r, s); + } + + function ecverify(bytes32 hash, bytes memory sig, address signer) public pure returns (bool) { + return signer == ecrecovery(hash, sig); + } + }`} + } +] diff --git a/test-browser/tests/solidityImport.js b/test-browser/tests/solidityImport.js new file mode 100644 index 0000000000..57d222c2cc --- /dev/null +++ b/test-browser/tests/solidityImport.js @@ -0,0 +1,169 @@ +'use strict' +var init = require('../helpers/init') +var sauce = require('./sauce') + +module.exports = { + before: function (browser, done) { + init(browser, done) + }, + '@sources': function () { + return sources + }, + 'Test Simple Contract': function (browser) { + browser.testContracts('Untitled.sol', sources[0]['browser/Untitled.sol'], ['test1', 'test2']) + }, + 'Test Success Import': function (browser) { + browser.addFile('Untitled1.sol', sources[1]['browser/Untitled1.sol']) + .addFile('Untitled2.sol', sources[1]['browser/Untitled2.sol']) + .switchFile('browser/Untitled1.sol') + .verifyContracts(['test6', 'test4', 'test5']) + }, + + 'Test Failed Import': function (browser) { + browser.addFile('Untitled3.sol', sources[2]['browser/Untitled3.sol']) + .clickLaunchIcon('solidity') + .assert.containsText('#compileTabView .error pre', 'Unable to import "browser/Untitled11.sol": File not found') + .end() + }, + tearDown: sauce +} + +var abstractENS = ` +contract AbstractENS { + function owner(bytes32 node) public view returns(address); + function resolver(bytes32 node) public view returns(address); + function ttl(bytes32 node) public view returns(uint64); + function setOwner(bytes32 node, address owner) public; + function setSubnodeOwner(bytes32 node, bytes32 label, address owner) public; + function setResolver(bytes32 node, address resolver) public; + function setTTL(bytes32 node, uint64 ttl) public; + + // Logged when the owner of a node assigns a new owner to a subnode. + event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner); + + // Logged when the owner of a node transfers ownership to a new account. + event Transfer(bytes32 indexed node, address owner); + + // Logged when the resolver for a node changes. + event NewResolver(bytes32 indexed node, address resolver); + + // Logged when the TTL of a node changes + event NewTTL(bytes32 indexed node, uint64 ttl); +}` + +var ENS = `pragma solidity ^0.4.0; + +import './AbstractENS.sol'; + +/** + * The ENS registry contract. + */ +contract ENS is AbstractENS { + struct Record { + address owner; + address resolver; + uint64 ttl; + } + + mapping(bytes32=>Record) records; + + // Permits modifications only by the owner of the specified node. + modifier only_owner(bytes32 node) { + if (records[node].owner != msg.sender) revert(); + _; + } + + /** + * Constructs a new ENS registrar. + */ + constructor() public { + records[0].owner = msg.sender; + } + + /** + * Returns the address that owns the specified node. + */ + function owner(bytes32 node) public view returns (address) { + return records[node].owner; + } + + /** + * Returns the address of the resolver for the specified node. + */ + function resolver(bytes32 node) public view returns (address) { + return records[node].resolver; + } + + /** + * Returns the TTL of a node, and any records associated with it. + */ + function ttl(bytes32 node) public view returns (uint64) { + return records[node].ttl; + } + + /** + * Transfers ownership of a node to a new address. May only be called by the current + * owner of the node. + * @param node The node to transfer ownership of. + * @param owner The address of the new owner. + */ + function setOwner(bytes32 node, address owner) public only_owner(node) { + emit Transfer(node, owner); + records[node].owner = owner; + } + + /** + * Transfers ownership of a subnode sha3(node, label) to a new address. May only be + * called by the owner of the parent node. + * @param node The parent node. + * @param label The hash of the label specifying the subnode. + * @param owner The address of the new owner. + */ + function setSubnodeOwner(bytes32 node, bytes32 label, address owner) public only_owner(node) { + bytes32 subnode = keccak256(abi.encodePacked(node, label)); + emit NewOwner(node, label, owner); + records[subnode].owner = owner; + } + + /** + * Sets the resolver address for the specified node. + * @param node The node to update. + * @param resolver The address of the resolver. + */ + function setResolver(bytes32 node, address resolver) public only_owner(node) { + emit NewResolver(node, resolver); + records[node].resolver = resolver; + } + + /** + * Sets the TTL for the specified node. + * @param node The node to update. + * @param ttl The TTL in seconds. + */ + function setTTL(bytes32 node, uint64 ttl) public only_owner(node) { + emit NewTTL(node, ttl); + records[node].ttl = ttl; + } +}` + +var sources = [ + { + 'browser/Untitled.sol': {content: 'contract test1 {} contract test2 {}'} + }, + { + 'browser/Untitled1.sol': {content: 'import "./Untitled2.sol"; contract test6 {}'}, + 'browser/Untitled2.sol': {content: 'contract test4 {} contract test5 {}'} + }, + { + 'browser/Untitled3.sol': {content: 'import "./Untitled11.sol"; contract test6 {}'} + }, + { + 'browser/Untitled4.sol': {content: 'import "github.com/ethereum/ens/contracts/ENS.sol"; contract test7 {}'}, + 'github.com/ethereum/ens/contracts/ENS.sol': {content: ENS} + }, + { + 'browser/Untitled4.sol': {content: 'import "github.com/ethereum/ens/contracts/ENS.sol"; contract test7 {}'}, + 'github.com/ethereum/ens/contracts/ENS.sol': {content: ENS}, + 'github.com/ethereum/ens/contracts/AbstractENS.sol': {content: abstractENS} + } +] diff --git a/test-browser/tests/compiling.js b/test-browser/tests/transactionExecution.js similarity index 96% rename from test-browser/tests/compiling.js rename to test-browser/tests/transactionExecution.js index 73836e2e7c..da7759544d 100644 --- a/test-browser/tests/compiling.js +++ b/test-browser/tests/transactionExecution.js @@ -1,7 +1,6 @@ 'use strict' var init = require('../helpers/init') var sauce = require('./sauce') -var testRecorder = require('./units/testRecorder') module.exports = { before: function (browser, done) { @@ -11,7 +10,7 @@ module.exports = { return sources }, - 'Test Simple Contract': function (browser) { + 'Execute Simple Contract and Test Terminal': function (browser) { browser.testContracts('Untitled.sol', sources[0]['browser/Untitled.sol'], ['TestContract']) .clickLaunchIcon('run') .click('#runTabView button[class^="instanceButton"]') @@ -38,7 +37,7 @@ module.exports = { .click('i[class^="clearinstance"]') }, - 'Test Return Values': function (browser) { + 'Test Complex Return Values': function (browser) { browser.testContracts('returnValues.sol', sources[1]['browser/returnValues.sol'], ['testReturnValues']) .clickLaunchIcon('run') .click('#runTabView button[class^="instanceButton"]') @@ -75,7 +74,7 @@ module.exports = { }`).click('i[class^="clearinstance"]') }, - 'Test Input Values': function (browser) { + 'Test Complex Input Values': function (browser) { browser.testContracts('inputValues.sol', sources[2]['browser/inputValues.sol'], ['test']) .clickLaunchIcon('run') .click('#runTabView button[class^="instanceButton"]') @@ -125,12 +124,7 @@ module.exports = { } ]`) .click('i[class^="clearinstance"]') - }, - - 'Test Recorder': function (browser) { - testRecorder.test(browser, () => { - browser.end() - }) + .end() }, tearDown: sauce