From 1125fde1f9af0b561206369a1475e271c16d49b9 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 26 Oct 2016 11:51:48 +0200 Subject: [PATCH 1/5] automate ui testing --- ci/makeMockCompiler.js | 43 +++++++++++---- test-browser/helpers/contracts.js | 40 +++++++------- test-browser/mockcompiler/requests.js | 79 --------------------------- test-browser/tests/ballot.js | 34 +++++------- test-browser/tests/simpleContract.js | 27 ++++----- 5 files changed, 77 insertions(+), 146 deletions(-) delete mode 100644 test-browser/mockcompiler/requests.js diff --git a/ci/makeMockCompiler.js b/ci/makeMockCompiler.js index e1a9014b21..365c26f048 100644 --- a/ci/makeMockCompiler.js +++ b/ci/makeMockCompiler.js @@ -4,20 +4,39 @@ var fs = require('fs') var solc = require('solc/wrapper') var soljson = require('../soljson') var compiler = solc(soljson) -var inputs = require('../test-browser/mockcompiler/requests.js') -var compilationResult = gatherCompilationResults(inputs) -replaceSolCompiler(compilationResult) -function gatherCompilationResults (sol) { - var compilationResult = {} - for (var k in sol) { - var item = sol[k] - var result = compile(item, 1) - compilationResult[result.key] = result - result = compile(item, 0) - compilationResult[result.key] = result +gatherCompilationResults(function (error, data) { + if (error) { + console.log(error) + process.exit(1) + } else { + replaceSolCompiler(data) } - return compilationResult +}) + +function gatherCompilationResults (callback) { + var compilationResult = {} + fs.readdir('./test-browser/tests', 'utf8', function (error, data) { + if (error) { + console.log(error) + process.exit(1) + } else { + data.map(function (item, i) { + var testDef = require('../test-browser/tests/' + item) + for (var k in testDef) { + if (k === '@Sources') { + var source = testDef[k]() + var result = compile(source, 1) + compilationResult[result.key] = result + result = compile(source, 0) + compilationResult[result.key] = result + } + } + }) + + callback(null, compilationResult) + } + }) } function compile (source, optimization) { diff --git a/test-browser/helpers/contracts.js b/test-browser/helpers/contracts.js index fea2d475d2..3de784c283 100644 --- a/test-browser/helpers/contracts.js +++ b/test-browser/helpers/contracts.js @@ -1,25 +1,27 @@ 'use strict' module.exports = { - checkCompiledContracts: function (browser, compiled, callback) { - browser.execute(function () { - var contracts = document.querySelectorAll('.udapp .contract') - var ret = [] - for (var k in contracts) { - var el = contracts[k] - if (el.querySelector) { - ret.push({ - name: el.querySelector('.title').innerText.replace(el.querySelector('.size').innerText, '').replace(/(\t)|(\r)|(\n)/g, '') // IE/firefox add \r\n - }) - } - } - return ret - }, [''], function (result) { - browser.assert.equal(result.value.length, compiled.length) - result.value.map(function (item, i) { - browser.assert.equal(item.name, compiled[i]) + checkCompiledContracts: checkCompiledContracts, + testContracts: testContracts +} + +function checkCompiledContracts (browser, compiled, callback) { + browser.elements('css selector', '.udapp .contract .title', function (elements) { + console.log(JSON.stringify(elements)) + elements.value.map(function (item, i) { + browser.elementIdText(item.ELEMENT, function (text) { + browser.assert.equal(text.value.split('\n')[0], compiled[i]) }) - callback() }) - } + callback() + }) +} + +function testContracts (browser, contractCode, compiledContractNames, callback) { + browser + .clearValue('#input textarea') + .click('.newFile') + .setValue('#input textarea', contractCode, function () {}) + .waitForElementPresent('.contract .create', 3000000) + checkCompiledContracts(browser, compiledContractNames, callback) } diff --git a/test-browser/mockcompiler/requests.js b/test-browser/mockcompiler/requests.js deleted file mode 100644 index 40997e5e3a..0000000000 --- a/test-browser/mockcompiler/requests.js +++ /dev/null @@ -1,79 +0,0 @@ -'use strict' - -module.exports = { - 'testSimpleContract': { - 'sources': { - 'Untitled': 'contract test1 {} contract test2 {}' - } - }, - 'ballot': { - 'sources': { - 'Untitled': `pragma solidity ^0.4.0 -contract Ballot { - - struct Voter { - uint weight - bool voted - uint8 vote - address delegate - } - struct Proposal { - uint voteCount - } - - address chairperson - mapping(address => Voter) voters - Proposal[] proposals - - /// Create a new ballot with $(_numProposals) different proposals. - function Ballot(uint8 _numProposals) { - chairperson = msg.sender - voters[chairperson].weight = 1 - proposals.length = _numProposals - } - - /// Give $(voter) the right to vote on this ballot. - /// May only be called by $(chairperson). - function giveRightToVote(address voter) { - if (msg.sender != chairperson || voters[voter].voted) return - voters[voter].weight = 1 - } - - /// Delegate your vote to the voter $(to). - function delegate(address to) { - Voter sender = voters[msg.sender] // assigns reference - if (sender.voted) return - while (voters[to].delegate != address(0) && voters[to].delegate != msg.sender) - to = voters[to].delegate - if (to == msg.sender) return - sender.voted = true - sender.delegate = to - Voter delegate = voters[to] - if (delegate.voted) - proposals[delegate.vote].voteCount += sender.weight - else - delegate.weight += sender.weight - } - - /// Give a single vote to proposal $(proposal). - function vote(uint8 proposal) { - Voter sender = voters[msg.sender] - if (sender.voted || proposal >= proposals.length) return - sender.voted = true - sender.vote = proposal - proposals[proposal].voteCount += sender.weight - } - - function winningProposal() constant returns (uint8 winningProposal) { - uint256 winningVoteCount = 0 - for (uint8 proposal = 0; proposal < proposals.length; proposal++) - if (proposals[proposal].voteCount > winningVoteCount) { - winningVoteCount = proposals[proposal].voteCount - winningProposal = proposal - } - } -} -` - } - } -} diff --git a/test-browser/tests/ballot.js b/test-browser/tests/ballot.js index 3985b367e2..8925630660 100644 --- a/test-browser/tests/ballot.js +++ b/test-browser/tests/ballot.js @@ -1,11 +1,19 @@ 'use strict' +var contractHelper = require('../helpers/contracts') +var examples = require('../../src/app/example-contracts') -var testData = require('../mockcompiler/requests') -// var contractHelper = require('../helpers/contracts') +var sources = { + 'sources': { + 'Untitled': examples.ballot.content + } +} module.exports = { + '@Sources': function () { + return sources + }, 'Ballot': function (browser) { - runTests(browser, testData) + runTests(browser) } } @@ -13,23 +21,7 @@ function runTests (browser, testData) { browser .url('http://127.0.0.1:8080/#version=builtin') .waitForElementVisible('.newFile', 10000) - browser.assert.notEqual(testData, null) -// TODO add Ballot tests. -> setValue('#input textarea', ... ) is not working properly with that contract. -/* - testBallot(browser, testData.ballot.sources.Untitled, function () { + contractHelper.testContracts(browser, sources.sources.Untitled.replace(/(\n)/g, ' '), ['Ballot'], function () { browser.end() - }); -*/ -} - -/* -function testBallot (browser, contract, callback) { - browser - .click('.newFile') - .clearValue('#input textarea') - .setValue('#input textarea', contract, function () { - browser.pause('10000') - contractHelper.checkCompiledContracts(browser, ['Ballot'], callback) - }) + }) } -*/ diff --git a/test-browser/tests/simpleContract.js b/test-browser/tests/simpleContract.js index cb7d126b81..e92a607fcb 100644 --- a/test-browser/tests/simpleContract.js +++ b/test-browser/tests/simpleContract.js @@ -1,29 +1,26 @@ 'use strict' - -var testData = require('../mockcompiler/requests') var contractHelper = require('../helpers/contracts') +var sources = { + 'sources': { + 'Untitled': 'contract test1 {} contract test2 {}' + } +} + module.exports = { + '@Sources': function () { + return sources + }, 'Simple Contract': function (browser) { - runTests(browser, testData) + runTests(browser) } } -function runTests (browser, testData) { +function runTests (browser) { browser .url('http://127.0.0.1:8080/#version=builtin') .waitForElementVisible('.newFile', 10000) - browser.assert.notEqual(testData, null) - testSimpleContract(browser, testData.testSimpleContract.sources.Untitled, function () { + contractHelper.testContracts(browser, sources.sources.Untitled, ['test1', 'test2'], function () { browser.end() }) } - -function testSimpleContract (browser, contract, callback) { - browser - .click('.newFile') - .clearValue('#input textarea') - .setValue('#input textarea', contract) - .pause('5000') - contractHelper.checkCompiledContracts(browser, ['test1', 'test2'], callback) -} From 27f989ef2b180ef45e3269d3a36d951f6aa61ef8 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 26 Oct 2016 14:57:27 +0200 Subject: [PATCH 2/5] readd ; to Ballot --- src/app/example-contracts.js | 62 ++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/app/example-contracts.js b/src/app/example-contracts.js index ac5a9dbf06..23458924a9 100644 --- a/src/app/example-contracts.js +++ b/src/app/example-contracts.js @@ -1,67 +1,67 @@ 'use strict' -var ballot = `pragma solidity ^0.4.0 +var ballot = `pragma solidity ^0.4.0; contract Ballot { struct Voter { - uint weight - bool voted - uint8 vote - address delegate + uint weight; + bool voted; + uint8 vote; + address delegate; } struct Proposal { - uint voteCount + uint voteCount; } - address chairperson - mapping(address => Voter) voters - Proposal[] proposals + address chairperson; + mapping(address => Voter) voters; + Proposal[] proposals; /// Create a new ballot with $(_numProposals) different proposals. function Ballot(uint8 _numProposals) { - chairperson = msg.sender - voters[chairperson].weight = 1 - proposals.length = _numProposals + chairperson = msg.sender; + voters[chairperson].weight = 1; + proposals.length = _numProposals; } /// Give $(voter) the right to vote on this ballot. /// May only be called by $(chairperson). function giveRightToVote(address voter) { - if (msg.sender != chairperson || voters[voter].voted) return - voters[voter].weight = 1 + if (msg.sender != chairperson || voters[voter].voted) return; + voters[voter].weight = 1; } /// Delegate your vote to the voter $(to). function delegate(address to) { - Voter sender = voters[msg.sender] // assigns reference - if (sender.voted) return + Voter sender = voters[msg.sender]; // assigns reference + if (sender.voted) return; while (voters[to].delegate != address(0) && voters[to].delegate != msg.sender) - to = voters[to].delegate - if (to == msg.sender) return - sender.voted = true - sender.delegate = to - Voter delegate = voters[to] + to = voters[to].delegate; + if (to == msg.sender) return; + sender.voted = true; + sender.delegate = to; + Voter delegate = voters[to]; if (delegate.voted) - proposals[delegate.vote].voteCount += sender.weight + proposals[delegate.vote].voteCount += sender.weight; else - delegate.weight += sender.weight + delegate.weight += sender.weight; } /// Give a single vote to proposal $(proposal). function vote(uint8 proposal) { - Voter sender = voters[msg.sender] - if (sender.voted || proposal >= proposals.length) return - sender.voted = true - sender.vote = proposal - proposals[proposal].voteCount += sender.weight + Voter sender = voters[msg.sender]; + if (sender.voted || proposal >= proposals.length) return; + sender.voted = true; + sender.vote = proposal; + proposals[proposal].voteCount += sender.weight; } function winningProposal() constant returns (uint8 winningProposal) { - uint256 winningVoteCount = 0 + uint256 winningVoteCount = 0; for (uint8 proposal = 0; proposal < proposals.length; proposal++) if (proposals[proposal].voteCount > winningVoteCount) { - winningVoteCount = proposals[proposal].voteCount - winningProposal = proposal + winningVoteCount = proposals[proposal].voteCount; + winningProposal = proposal; } } }` From 0832642dd900bd06e18994addab2f85f1910618c Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 26 Oct 2016 15:08:08 +0200 Subject: [PATCH 3/5] move \n replacement --- test-browser/helpers/contracts.js | 2 +- test-browser/tests/ballot.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test-browser/helpers/contracts.js b/test-browser/helpers/contracts.js index 3de784c283..31571614e3 100644 --- a/test-browser/helpers/contracts.js +++ b/test-browser/helpers/contracts.js @@ -21,7 +21,7 @@ function testContracts (browser, contractCode, compiledContractNames, callback) browser .clearValue('#input textarea') .click('.newFile') - .setValue('#input textarea', contractCode, function () {}) + .setValue('#input textarea', contractCode.replace(/(\n)/g, ' '), function () {}) .waitForElementPresent('.contract .create', 3000000) checkCompiledContracts(browser, compiledContractNames, callback) } diff --git a/test-browser/tests/ballot.js b/test-browser/tests/ballot.js index 8925630660..f5d2e32767 100644 --- a/test-browser/tests/ballot.js +++ b/test-browser/tests/ballot.js @@ -21,7 +21,7 @@ function runTests (browser, testData) { browser .url('http://127.0.0.1:8080/#version=builtin') .waitForElementVisible('.newFile', 10000) - contractHelper.testContracts(browser, sources.sources.Untitled.replace(/(\n)/g, ' '), ['Ballot'], function () { + contractHelper.testContracts(browser, sources.sources.Untitled, ['Ballot'], function () { browser.end() }) } From 4d6a2e45124e055ff51e03190d8d1d10f76e1468 Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 27 Oct 2016 11:21:25 +0200 Subject: [PATCH 4/5] inject script before tests to prepare testing --- src/app/editor.js | 1 + test-browser/helpers/applytestmode.js | 7 +++++++ test-browser/helpers/contracts.js | 8 ++++---- test-browser/helpers/init.js | 7 +++++++ test-browser/tests/ballot.js | 5 ++++- test-browser/tests/debugger.js | 5 ++++- test-browser/tests/new-file-test.js | 5 ++++- test-browser/tests/simpleContract.js | 5 ++++- test-browser/tests/smoke-test.js | 6 +++++- 9 files changed, 40 insertions(+), 9 deletions(-) create mode 100644 test-browser/helpers/applytestmode.js create mode 100644 test-browser/helpers/init.js diff --git a/src/app/editor.js b/src/app/editor.js index 32309a2c5d..e8f6f14042 100644 --- a/src/app/editor.js +++ b/src/app/editor.js @@ -12,6 +12,7 @@ function Editor (loadingFromGist, storage) { var SOL_CACHE_FILE = null var editor = ace.edit('input') + document.getElementById('input').editor = editor var sessions = {} var sourceAnnotations = [] diff --git a/test-browser/helpers/applytestmode.js b/test-browser/helpers/applytestmode.js new file mode 100644 index 0000000000..5d35b5b51e --- /dev/null +++ b/test-browser/helpers/applytestmode.js @@ -0,0 +1,7 @@ +/** + * This script is injected by NightWatch just before starting test + * + */ +console.log('applying test mode') +document.getElementById('input').editor.setBehavioursEnabled(false) +console.log('test mode applied') diff --git a/test-browser/helpers/contracts.js b/test-browser/helpers/contracts.js index 31571614e3..4ddc9592d5 100644 --- a/test-browser/helpers/contracts.js +++ b/test-browser/helpers/contracts.js @@ -19,9 +19,9 @@ function checkCompiledContracts (browser, compiled, callback) { function testContracts (browser, contractCode, compiledContractNames, callback) { browser - .clearValue('#input textarea') - .click('.newFile') - .setValue('#input textarea', contractCode.replace(/(\n)/g, ' '), function () {}) - .waitForElementPresent('.contract .create', 3000000) + .clearValue('#input textarea') + .click('.newFile') + .setValue('#input textarea', contractCode, function () {}) + .waitForElementPresent('.contract .create', 3000000) checkCompiledContracts(browser, compiledContractNames, callback) } diff --git a/test-browser/helpers/init.js b/test-browser/helpers/init.js new file mode 100644 index 0000000000..314daa61e8 --- /dev/null +++ b/test-browser/helpers/init.js @@ -0,0 +1,7 @@ +module.exports = function (browser, callback) { + browser + .url('http://127.0.0.1:8080/#version=builtin') + .injectScript('test-browser/helpers/applytestmode.js', function () { + callback() + }) +} diff --git a/test-browser/tests/ballot.js b/test-browser/tests/ballot.js index f5d2e32767..3dcf5a4393 100644 --- a/test-browser/tests/ballot.js +++ b/test-browser/tests/ballot.js @@ -1,6 +1,7 @@ 'use strict' var contractHelper = require('../helpers/contracts') var examples = require('../../src/app/example-contracts') +var init = require('../helpers/init') var sources = { 'sources': { @@ -9,6 +10,9 @@ var sources = { } module.exports = { + before: function (browser, done) { + init(browser, done) + }, '@Sources': function () { return sources }, @@ -19,7 +23,6 @@ module.exports = { function runTests (browser, testData) { browser - .url('http://127.0.0.1:8080/#version=builtin') .waitForElementVisible('.newFile', 10000) contractHelper.testContracts(browser, sources.sources.Untitled, ['Ballot'], function () { browser.end() diff --git a/test-browser/tests/debugger.js b/test-browser/tests/debugger.js index 80daaaf3b6..280f0de69e 100644 --- a/test-browser/tests/debugger.js +++ b/test-browser/tests/debugger.js @@ -1,9 +1,12 @@ 'use strict' +var init = require('../helpers/init') module.exports = { + before: function (browser, done) { + init(browser, done) + }, 'Debugger Render': function (browser) { browser - .url('http://127.0.0.1:8080/#version=builtin') .waitForElementPresent('#debugger', 10000) .waitForElementPresent('#debugger #slider', 10000) .end() diff --git a/test-browser/tests/new-file-test.js b/test-browser/tests/new-file-test.js index 5438adfaa3..6d33faa57b 100644 --- a/test-browser/tests/new-file-test.js +++ b/test-browser/tests/new-file-test.js @@ -1,9 +1,12 @@ 'use strict' +var init = require('../helpers/init') module.exports = { + before: function (browser, done) { + init(browser, done) + }, 'New file test': function (browser) { browser - .url('http://127.0.0.1:8080/#version=builtin') .waitForElementVisible('.newFile', 10000) .click('.newFile') .pause('10000') diff --git a/test-browser/tests/simpleContract.js b/test-browser/tests/simpleContract.js index e92a607fcb..ea0669a51d 100644 --- a/test-browser/tests/simpleContract.js +++ b/test-browser/tests/simpleContract.js @@ -1,5 +1,6 @@ 'use strict' var contractHelper = require('../helpers/contracts') +var init = require('../helpers/init') var sources = { 'sources': { @@ -8,6 +9,9 @@ var sources = { } module.exports = { + before: function (browser, done) { + init(browser, done) + }, '@Sources': function () { return sources }, @@ -18,7 +22,6 @@ module.exports = { function runTests (browser) { browser - .url('http://127.0.0.1:8080/#version=builtin') .waitForElementVisible('.newFile', 10000) contractHelper.testContracts(browser, sources.sources.Untitled, ['test1', 'test2'], function () { browser.end() diff --git a/test-browser/tests/smoke-test.js b/test-browser/tests/smoke-test.js index d56f8d0cd6..6b75bf2736 100644 --- a/test-browser/tests/smoke-test.js +++ b/test-browser/tests/smoke-test.js @@ -1,9 +1,13 @@ 'use strict' +var init = require('../helpers/init') module.exports = { + before: function (browser, done) { + browser + init(browser, done) + }, 'Smoke test': function (browser) { browser - .url('http://127.0.0.1:8080/#version=builtin') .waitForElementVisible('#righthand-panel', 10000) .pause('10000') .assert.containsText('#righthand-panel', 'Solidity version') From 613e1602dab86778c85eedbd53f29aec54f746fc Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 27 Oct 2016 12:14:05 +0200 Subject: [PATCH 5/5] add comment + misc --- ci/makeMockCompiler.js | 18 ++++++++---------- src/app/editor.js | 2 +- test-browser/helpers/applytestmode.js | 2 +- test-browser/helpers/contracts.js | 3 +-- test-browser/tests/ballot.js | 2 +- test-browser/tests/simpleContract.js | 2 +- 6 files changed, 13 insertions(+), 16 deletions(-) diff --git a/ci/makeMockCompiler.js b/ci/makeMockCompiler.js index 365c26f048..3ced9b3084 100644 --- a/ci/makeMockCompiler.js +++ b/ci/makeMockCompiler.js @@ -16,21 +16,19 @@ gatherCompilationResults(function (error, data) { function gatherCompilationResults (callback) { var compilationResult = {} - fs.readdir('./test-browser/tests', 'utf8', function (error, data) { + fs.readdir('./test-browser/tests', 'utf8', function (error, filenames) { if (error) { console.log(error) process.exit(1) } else { - data.map(function (item, i) { + filenames.map(function (item, i) { var testDef = require('../test-browser/tests/' + item) - for (var k in testDef) { - if (k === '@Sources') { - var source = testDef[k]() - var result = compile(source, 1) - compilationResult[result.key] = result - result = compile(source, 0) - compilationResult[result.key] = result - } + if ('@sources' in testDef) { + var source = testDef['@sources']() + var result = compile(source, 1) + compilationResult[result.key] = result + result = compile(source, 0) + compilationResult[result.key] = result } }) diff --git a/src/app/editor.js b/src/app/editor.js index e8f6f14042..97e1a99af0 100644 --- a/src/app/editor.js +++ b/src/app/editor.js @@ -12,7 +12,7 @@ function Editor (loadingFromGist, storage) { var SOL_CACHE_FILE = null var editor = ace.edit('input') - document.getElementById('input').editor = editor + document.getElementById('input').editor = editor // required to access the editor during tests var sessions = {} var sourceAnnotations = [] diff --git a/test-browser/helpers/applytestmode.js b/test-browser/helpers/applytestmode.js index 5d35b5b51e..89366fd7d5 100644 --- a/test-browser/helpers/applytestmode.js +++ b/test-browser/helpers/applytestmode.js @@ -3,5 +3,5 @@ * */ console.log('applying test mode') -document.getElementById('input').editor.setBehavioursEnabled(false) +document.getElementById('input').editor.setBehavioursEnabled(false) // disable bracket auto-match (i.e. automatic injection of closing brackets and other things), so we can enter raw source code. console.log('test mode applied') diff --git a/test-browser/helpers/contracts.js b/test-browser/helpers/contracts.js index 4ddc9592d5..e4a71bdc69 100644 --- a/test-browser/helpers/contracts.js +++ b/test-browser/helpers/contracts.js @@ -7,7 +7,6 @@ module.exports = { function checkCompiledContracts (browser, compiled, callback) { browser.elements('css selector', '.udapp .contract .title', function (elements) { - console.log(JSON.stringify(elements)) elements.value.map(function (item, i) { browser.elementIdText(item.ELEMENT, function (text) { browser.assert.equal(text.value.split('\n')[0], compiled[i]) @@ -22,6 +21,6 @@ function testContracts (browser, contractCode, compiledContractNames, callback) .clearValue('#input textarea') .click('.newFile') .setValue('#input textarea', contractCode, function () {}) - .waitForElementPresent('.contract .create', 3000000) + .waitForElementPresent('.contract .create', 2000) checkCompiledContracts(browser, compiledContractNames, callback) } diff --git a/test-browser/tests/ballot.js b/test-browser/tests/ballot.js index 3dcf5a4393..b6ca5b0154 100644 --- a/test-browser/tests/ballot.js +++ b/test-browser/tests/ballot.js @@ -13,7 +13,7 @@ module.exports = { before: function (browser, done) { init(browser, done) }, - '@Sources': function () { + '@sources': function () { return sources }, 'Ballot': function (browser) { diff --git a/test-browser/tests/simpleContract.js b/test-browser/tests/simpleContract.js index ea0669a51d..d9c089938d 100644 --- a/test-browser/tests/simpleContract.js +++ b/test-browser/tests/simpleContract.js @@ -12,7 +12,7 @@ module.exports = { before: function (browser, done) { init(browser, done) }, - '@Sources': function () { + '@sources': function () { return sources }, 'Simple Contract': function (browser) {