Skip to content
This repository has been archived by the owner on Apr 15, 2019. It is now read-only.

Commit

Permalink
Merge pull request #53 from LiskHQ/41_end-to-end-tests
Browse files Browse the repository at this point in the history
Adding end to end tests - Closes #41
  • Loading branch information
karmacoma authored Mar 15, 2017
2 parents 0d248cf + 5f2391c commit 6d7bcb7
Show file tree
Hide file tree
Showing 7 changed files with 257 additions and 10 deletions.
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,45 @@ Build package for Linux.
npm run dist:linux
```

## Run end-to-end tests

### Setup

To setup protractor as described on http://www.protractortest.org/#/ run:

```
npm install -g protractor
webdriver-manager update
webdriver-manager start
```

Setup a lisk test node to run on localhost:4000 as described in https://github.com/LiskHQ/lisk#tests

Make sure that the Lisk version of the node matches version in https://github.com/LiskHQ/lisk-nano/blob/development/src/app/services/peers/peer.js#L16

Make sure there are some transactions on the master account so we can test they display correctly:
```
for i in {1..20}
do
curl -k -H "Content-Type: application/json" -X PUT -d '{"secret":"wagon stock borrow episode laundry kitten salute link globe zero feed marble","amount":'"$i"',"recipientId":"537318935439898807L"}' http://localhost:4000/api/transactions; echo ''
done
```

### Run

Start the development version of lisk-nano:

```
cd src
npm run dev
```

Run the protractor tests:

```
protractor spec/conf.js
```

## Authors

Ricardo Ferro <[email protected]>
Expand Down
9 changes: 5 additions & 4 deletions src/app/components/login/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ app.component('login', {
if (distance > 60 || ev.isTrigger) {
for (let p = 0; p < steps; p++) {
let pos;
const available = used.filter(u => u);
const available = used.map((u, i) => (!u ? i : null)).filter(u => u !== null);

if (!available.length) {
used = used.map(() => 0);
Expand Down Expand Up @@ -169,9 +169,10 @@ app.component('login', {
}

devTestAccount() {
this.input_passphrase = this.$cookies.get('passphrase');
if (this.input_passphrase) {
this.$timeout(this.go.bind(this), 100);
const passphrase = this.$cookies.get('passphrase');
if (passphrase) {
this.input_passphrase = passphrase;
this.$timeout(this.go.bind(this), 10);
}
}

Expand Down
1 change: 1 addition & 0 deletions src/app/components/main/main.less
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ main {
}

.logout {
margin-right: 0;
}

md-content {
Expand Down
6 changes: 4 additions & 2 deletions src/app/components/transactions/transactions.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ app.component('transactions', {
this.loaded = false;
this.transactions = [];

this.reset();
this.update();
this.$scope.$watch('account', () => {
this.reset();
this.update();
});

this.$scope.$on('peerUpdate', () => {
this.reset();
Expand Down
10 changes: 6 additions & 4 deletions src/app/services/peers/peers.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import './peer';

const UPDATE_INTERVAL_CHECK = 10000;

app.factory('$peers', ($peer, $timeout, $cookies) => {
app.factory('$peers', ($peer, $timeout, $cookies, $location) => {
class $peers {
constructor() {
this.stack = {
Expand All @@ -23,6 +23,9 @@ app.factory('$peers', ($peer, $timeout, $cookies) => {
testnet: [
new $peer({ host: 'testnet.lisk.io', port: null, ssl: true }),
],
localhost: [
new $peer({ host: 'localhost:4000', port: null, ssl: false }),
],
};

this.check();
Expand All @@ -37,10 +40,9 @@ app.factory('$peers', ($peer, $timeout, $cookies) => {
}

setActive() {
const peerStack = $location.search().peerStack || $cookies.get('peerStack') || 'official';
this.active = _.chain([])
.concat($cookies.get('peerStack') === 'testnet' ?
this.stack.testnet : this.stack.official,
this.stack.public)
.concat(this.stack[peerStack], this.stack.public)
.sample()
.value();

Expand Down
7 changes: 7 additions & 0 deletions src/spec/conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
exports.config = {
seleniumAddress: 'http://localhost:4444/wd/hub',
specs: ['spec.js'],
capabilities: {
browserName: 'chrome'
}
};
195 changes: 195 additions & 0 deletions src/spec/spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
var masterAccount = {
passphrase: 'wagon stock borrow episode laundry kitten salute link globe zero feed marble',
address: '16313739661670634666L',
};

var delegateAccount = {
passphrase: 'recipe bomb asset salon coil symbol tiger engine assist pact pumpkin visit',
address: '537318935439898807L',
};

var emptyAccount = {
passphrase: 'stay undo beyond powder sand laptop grow gloom apology hamster primary arrive',
address: '5932438298200837883L',
};

var EC = protractor.ExpectedConditions;
var waitTime = 5000;

describe('Lisk Nano functionality', function() {
it('should allow to login', testLogin);
it('should allow to logout', testLogout);
it('should show address', testAddress);
it('should show peer', testPeer);
it('should allow to change peer', testChangePeer);
it('should show balance', testShowBalance);
it('should allow to send transaction when enough funds and correct address form', testSend);
it('should not allow to send transaction when not enough funds', testSendWithNotEnoughFunds);
it('should not allow to send transaction when invalid address', testSendWithInvalidAddress);
it('should show transactions', testShowTransactions);
it('should allow to load more transactions', testLoadMoreTransactions);
it('should allow to create a new account', testNewAccount);
});

function testLogin() {
login(masterAccount);
checkIsLoggedIn();
}

function checkIsLoggedIn() {
waitForElemAndCheckItsText('.logout', 'LOGOUT');
}

function testLogout() {
login(masterAccount);

logout();
waitForElemAndCheckItsText('.md-button.md-primary.md-raised', 'LOGIN');
}

function testNewAccount() {
launchApp();

element(by.css('.md-button.md-primary')).click();
for (var i = 0; i < 250; i++) {
browser.actions()
.mouseMove(element(by.css('body')), {
x: Math.floor(Math.random() * 1000),
y: Math.floor(Math.random() * 1000),
}).perform();
browser.sleep(5);
}

waitForElemAndCheckItsText('.dialog-save h2', 'Save your passphrase in a safe place!');

element(by.css('.dialog-save textarea.passphrase')).getText().then(function(passphrase) {
expect(passphrase).toBeDefined();
var passphraseWords = passphrase.split(' ');
expect(passphraseWords.length).toEqual(12);
var nextButton = element.all(by.css('.dialog-save .md-button.md-ink-ripple')).get(1);
nextButton.click();

element(by.css('.dialog-save p.passphrase span')).getText().then(function(firstPartOfPassphrase) {
var missingWordIndex = firstPartOfPassphrase.length ?
firstPartOfPassphrase.split(' ').length :
0;
element(by.css('.dialog-save input')).sendKeys(passphraseWords[missingWordIndex]);
var okButton = element.all(by.css('.dialog-save .md-button.md-ink-ripple')).get(2);
okButton.click();

checkIsLoggedIn();
});
});
}

function testAddress() {
login(masterAccount);
waitForElemAndCheckItsText('.address', masterAccount.address);
}

function testPeer() {
login(masterAccount);
waitForElemAndCheckItsText('.peer md-select-value .md-text', 'localhost:4000');
}

function testChangePeer() {
login(masterAccount);

var peerElem = element(by.css('.peer md-select-value'));
browser.wait(EC.presenceOf(peerElem), waitTime);
peerElem.click();

var optionElem = element(by.css('md-select-menu md-optgroup md-option'));
browser.wait(EC.presenceOf(optionElem), waitTime);
optionElem.click();

waitForElemAndCheckItsText('.peer md-select-value .md-text', 'node01.lisk.io');
}

function testShowBalance() {
login(masterAccount);

var balanceElem = element(by.css('lsk.balance'));
browser.wait(EC.presenceOf(balanceElem), waitTime);
expect(balanceElem.getText()).toMatch(/\d+\.\d+ LSK/);
}

function testSend() {
send(masterAccount, delegateAccount.address, 1.1);
checkSendConfirmation();
logout();

send(delegateAccount, masterAccount.address, 1);
checkSendConfirmation();
}

function testSendWithNotEnoughFunds() {
send(emptyAccount, delegateAccount.address, 10000);
checkErrorMessage('Insufficient funds');
}

function testSendWithInvalidAddress() {
send(masterAccount, emptyAccount.address.substr(0, 10), 1);
checkErrorMessage('Invalid');
}

function testShowTransactions() {
login(masterAccount);
waitForElemAndCheckItsText('transactions .title', 'Transactions');
expect(element.all(by.css('transactions table tbody tr')).count()).toEqual(10);
}

function testLoadMoreTransactions() {
login(masterAccount);

var moreButton = element(by.css('transactions button.more'));
browser.wait(EC.presenceOf(moreButton), waitTime);
moreButton.click();

expect(element.all(by.css('transactions table tbody tr')).count()).toEqual(20);
}

function checkErrorMessage(message) {
waitForElemAndCheckItsText('send .md-input-message-animation', message);
}

function waitForElemAndCheckItsText(selector, text) {
var elem = element(by.css(selector));
browser.wait(EC.presenceOf(elem), waitTime);
expect(elem.getText()).toEqual(text);
}

function send(fromAccount, toAddress, amount) {
login(fromAccount);
var sendElem = element(by.css('send'));
browser.wait(EC.presenceOf(sendElem), waitTime);
element(by.css('send input[name="recipient"]')).sendKeys(toAddress);
element(by.css('send input[name="amount"]')).sendKeys("" + amount);
var sendButton = element(by.css('send button.md-primary'));
browser.wait(EC.presenceOf(sendButton), waitTime);
sendButton.click();
}

function checkSendConfirmation() {
waitForElemAndCheckItsText('md-dialog h2', 'Success');
var okButton = element(by.css('md-dialog .md-button.md-ink-ripple'));
okButton.click();
browser.sleep(500);
}

function launchApp() {
browser.ignoreSynchronization = true;
browser.get('http://localhost:8080#?peerStack=localhost');
}

function logout() {
var logoutButton = element(by.css('.logout'));
browser.wait(EC.presenceOf(logoutButton), waitTime);
logoutButton.click();
}

function login(account) {
launchApp();
element(by.css('input[type="password"]')).sendKeys(account.passphrase);
element(by.css('.md-button.md-primary.md-raised')).click();
}

0 comments on commit 6d7bcb7

Please sign in to comment.