Skip to content

Commit

Permalink
Merge pull request #489 from LiskHQ/103-integration-test-login-page
Browse files Browse the repository at this point in the history
Integration test for login page - Subtask #103
  • Loading branch information
reyraa committed Mar 1, 2018
2 parents 39278e7 + f0df398 commit 58534fd
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 15 deletions.
137 changes: 126 additions & 11 deletions test/integration/login.test.js
@@ -1,20 +1,135 @@
import { step } from 'mocha-steps';
import thunk from 'redux-thunk';
import { expect } from 'chai';
import { mount } from 'enzyme';
import { stub, spy } from 'sinon';

import * as accountAPI from '../../src/utils/api/account';
import * as delegateAPI from '../../src/utils/api/delegate';
import * as netHash from '../../src/utils/api/nethash';
import { prepareStore, renderWithRouter } from '../utils/applicationInit';
import accountReducer from '../../src/store/reducers/account';
import peersReducer from '../../src/store/reducers/peers';
import settingsReducer from '../../src/store/reducers/settings';
import savedAccountsReducer from '../../src/store/reducers/savedAccounts';
import loginMiddleware from '../../src/store/middlewares/login';
import accountMiddleware from '../../src/store/middlewares/account';
import peerMiddleware from '../../src/store/middlewares/peers';
import { activePeerSet } from '../../src/actions/peers';
import * as toasterActions from '../../src/actions/toaster';
import Login from './../../src/components/login';
import accounts from '../constants/accounts';
import GenericStepDefinition from '../utils/genericStepDefinition';

describe('@integration: Login', () => {
let wrapper;
let helper;
// const requestToActivePeerStub = stub(peers, 'requestToActivePeer');
let accountAPIStub;
let delegateAPIStub;
let netHashAPIStub;
let localStorageStub;
let errorToastDisplayedSpy;
const localhostUrl = 'http://localhost:4218';
const errorMessage = 'Unable to connect to the node';
const { passphrase } = accounts.genesis;

afterEach(() => {
wrapper.update();
});

const createStore = () => (
prepareStore({
account: accountReducer,
peers: peersReducer,
savedAccounts: savedAccountsReducer,
settings: settingsReducer,
}, [
thunk,
accountMiddleware,
loginMiddleware,
peerMiddleware,
])
);

const restoreStubs = () => {
// requestToActivePeerStub.restore();
localStorageStub.restore();
accountAPIStub.restore();
delegateAPIStub.restore();
netHashAPIStub.restore();
errorToastDisplayedSpy.restore();
};

const stubApisDefaultScenario = () => {
netHashAPIStub = stub(netHash, 'getNethash').returnsPromise().rejects();
localStorageStub = stub(localStorage, 'getItem');
localStorageStub.withArgs('accounts').returns(JSON.stringify([{}, {}]));
localStorageStub.withArgs('showNetwork').returns(JSON.stringify(true));
accountAPIStub = stub(accountAPI, 'getAccount');
accountAPIStub.returnsPromise().resolves({
address: '6307319849853921018L',
unconfirmedBalance: '10190054753073',
balance: '10190054753073',
publicKey: '8ab0b8b0e663d49c8aaf3a8a6d75a46b477455f9d25ac92898461164c31758ee',
unconfirmedSignature: 0,
secondSignature: 0,
secondPublicKey: null,
multisignatures: [],
u_multisignatures: [],
});
delegateAPIStub = stub(delegateAPI, 'getDelegate').returnsPromise().rejects();
errorToastDisplayedSpy = spy(toasterActions, 'errorToastDisplayed');
};

const stubApisScenarioInvalidNode = () => {
localStorageStub = stub(localStorage, 'getItem');
localStorageStub.withArgs('accounts').returns(JSON.stringify([{}, {}]));
localStorageStub.withArgs('showNetwork').returns(JSON.stringify(true));
netHashAPIStub = stub(netHash, 'getNethash').returnsPromise().rejects();
accountAPIStub = stub(accountAPI, 'getAccount').returnsPromise().rejects();
delegateAPIStub = stub(delegateAPI, 'getDelegate').returnsPromise().rejects();
errorToastDisplayedSpy = spy(toasterActions, 'errorToastDisplayed');
};

class Helper extends GenericStepDefinition {
// eslint-disable-next-line class-methods-use-this
checkIfInRoute() {
expect(this.store.getState().account).to.have.all.keys('passphrase', 'publicKey', 'address', 'delegate',
'isDelegate', 'expireTime', 'u_multisignatures', 'multisignatures', 'unconfirmedBalance',
'secondSignature', 'secondPublicKey', 'balance', 'unconfirmedSignature');
restoreStubs();
}

// eslint-disable-next-line class-methods-use-this
checkIfErrorToastFired() {
expect(errorToastDisplayedSpy).to.have.been.calledWith({ label: errorMessage });
restoreStubs();
}
}

const setupStep = (stubApis) => {
const store = createStore();
stubApis();
wrapper = mount(renderWithRouter(Login, store, { location: { search: '' } }), { activePeerSet });
helper = new Helper(wrapper, store);
};

describe('Scenario: should allow to login', () => {
step('Given I\'m on login page');
step('When I fill in "wagon stock borrow episode laundry kitten salute link globe zero feed marble" to "passphrase" field');
step('And I click "login button"');
step('Then I should be logged in');
step('Given I\'m on login page', () => setupStep(stubApisDefaultScenario));
step(`When I fill "${passphrase}" into "passphrase" field`,
() => helper.fillInputField(passphrase, 'passphrase'));
step('And I click "login button"', () => helper.submitForm());
step('Then I should be logged in', () => helper.checkIfInRoute());
});

describe('Scenario: should show toast when trying to connect to an unavailable custom node', () => {
step('Given I\'m on login page');
step('When I fill in "wagon stock borrow episode laundry kitten salute link globe zero feed marble" to "passphrase" field');
step('And I select option no. 3 from "network" select');
step('And I clear "address" field');
step('And I fill in "http://localhost:4218" to "address" field');
step('And I click "login button"');
step('Then I should see text "Unable to connect to the node" in "toast" element');
step('Given I\'m on login page', () => setupStep(stubApisScenarioInvalidNode));
step(`When I fill "${passphrase}" into "passphrase" field`, () => helper.fillInputField(passphrase, 'passphrase'));
step('And I select option no. 3 from "network" select', () => helper.selectOptionItem(3, 'network'));
step('And I clear "address" field', () => helper.fillInputField('', 'address'));
step(`And I fill in "${localhostUrl}" to "address" field`, () => helper.fillInputField(localhostUrl, 'address'));
step('And I click "login button"', () => helper.submitForm());
step(`Then I should see text ${errorMessage} in "toast" element`, () => helper.checkIfErrorToastFired());
});
});
35 changes: 31 additions & 4 deletions test/utils/genericStepDefinition.js
Expand Up @@ -42,16 +42,43 @@ export default class GenericStepDefinition {
haveTextOf(query, text) {
expect(this.wrapper.find(query)).to.have.text(text);
}

/**
*
* @param {String} value - The value to fill in input
* @param {String} field - space separated class name of the input, without the initial dot
*/
fillInputField(value, field) {
this.wrapper.find(`.${field} input`).first().simulate('change', { target: { value } });
const selector = `.${field.replace(/ /g, '-')} input`;
this.wrapper.find(selector).first().simulate('change', { target: { value } });
}
/**
*
* @param {String} value - The index of option in the list to click on
* @param {String} field - space separated class name of the input, without the initial dot
*/
selectOptionItem(optionIndex, field) {
const selector = `.${field.replace(/ /g, '-')} ul li`;
this.wrapper.find(selector).at(parseInt(optionIndex, 10) - 1).simulate('click');
}

submitForm() {
this.wrapper.find('form').simulate('submit', {});
}

/**
*
* @param {String} expectedPublicKey - Valid publicKey
*/
shouldBeLoggedInAs(expectedPublicKey) {
expect(this.store.getState().account.publicKey).to.equal(expectedPublicKey);
}

shouldSeeCountInstancesOf(count, query) {
expect(this.wrapper.find(query)).to.have.lengthOf(count);
/**
*
* @param {Number} count - Valid publicKey
* @param {String} selector - Valid css selector
*/
shouldSeeCountInstancesOf(count, selector) {
expect(this.wrapper.find(selector)).to.have.lengthOf(count);
}
}

0 comments on commit 58534fd

Please sign in to comment.