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 #601 from LiskHQ/531-unit-test-coverage
Browse files Browse the repository at this point in the history
Review and improve React unit test coverage - Closes #531
  • Loading branch information
slaweet authored Aug 16, 2017
2 parents 5d30348 + 88dc089 commit 3a44735
Show file tree
Hide file tree
Showing 27 changed files with 537 additions and 59 deletions.
2 changes: 1 addition & 1 deletion karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ module.exports = function (config) {
colors: true,
logLevel: config.LOG_INFO,
autoWatch: false,
browsers: ['Chrome'],
browsers: ['ChromeHeadless'],
singleRun: true,
browserNoActivityTimeout: 60000,
browserDisconnectTolerance: 3,
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@
"imports-loader": "=0.6.5",
"js-nacl": "=1.2.2",
"json-loader": "=0.5.4",
"karma": "^1.7.0",
"karma": "=1.7.0",
"karma-chai": "=0.1.0",
"karma-chrome-launcher": "^2.2.0",
"karma-chrome-launcher": "=2.2.0",
"karma-coverage": "=1.1.1",
"karma-jenkins-reporter": "0.0.2",
"karma-mocha": "=1.3.0",
Expand Down
57 changes: 30 additions & 27 deletions src/components/account/account.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import chai, { expect } from 'chai';
import sinon from 'sinon';
import sinonChai from 'sinon-chai';
import { shallow, mount } from 'enzyme';
import { Provider } from 'react-redux';
Expand All @@ -10,45 +11,47 @@ import ClickToSend from '../send/clickToSend';
chai.use(sinonChai);

describe('Account', () => {
// Mocking store
const onActivePeerUpdated = () => {};
const peers = {
status: {
online: false,
},
data: {
currentPeer: 'localhost',
port: 4000,
options: {
name: 'Custom Node',
let props;

beforeEach(() => {
props = {
onActivePeerUpdated: sinon.spy(),
peers: {
status: {
online: false,
},
data: {
currentPeer: 'localhost',
port: 4000,
options: {
name: 'Custom Node',
},
},
},
account: {
isDelegate: false,
address: '16313739661670634666L',
username: 'lisk-nano',
balance: 1e8,
},
},
};
const testAccount = {
isDelegate: false,
address: '16313739661670634666L',
username: 'lisk-nano',
balance: 1e8,
};
};
});

it(' should render 3 article tags', () => {
const wrapper = shallow(<Account account={testAccount} peers={peers}
onActivePeerUpdated={onActivePeerUpdated} />);
it('should render 3 article tags', () => {
const wrapper = shallow(<Account {...props} />);
expect(wrapper.find('article')).to.have.lengthOf(3);
});

it('depicts being online when peers.status.online is true', () => {
const onlinePeers = Object.assign({}, peers, { status: { online: true } });
const wrapper = shallow(<Account account={testAccount} peers={onlinePeers}
onActivePeerUpdated={onActivePeerUpdated} />);
props.peers.status.online = true;
const wrapper = shallow(<Account {...props} />);
const expectedValue = 'check';
expect(wrapper.find('.material-icons').text()).to.be.equal(expectedValue);
});

it('should render balance with ClickToSend component', () => {
const wrapper = mount(<Provider store={store}>
<Account account={testAccount} peers={peers}
onActivePeerUpdated={onActivePeerUpdated} />
<Account {...props} />
</Provider>);
expect(wrapper.find('.balance').find(ClickToSend)).to.have.lengthOf(1);
});
Expand Down
33 changes: 31 additions & 2 deletions src/components/account/index.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import React from 'react';
import { expect } from 'chai';
import { mount } from 'enzyme';
import sinon from 'sinon';
import * as accountActions from '../../actions/account';
import * as transactionsActions from '../../actions/transactions';
import * as peersActions from '../../actions/peers';
import Account from './index';
import AccountComponent from './account';

Expand Down Expand Up @@ -38,12 +42,37 @@ describe('Account', () => {
context: { store },
// childContextTypes: { store: PropTypes.object.isRequired },
};
let props;

it('should mount AccountComponent with appropriate properties', () => {
beforeEach(() => {
const mountedAccount = mount(<Account/>, options);
const props = mountedAccount.find(AccountComponent).props();
props = mountedAccount.find(AccountComponent).props();
});

it('should mount AccountComponent with appropriate properties', () => {
expect(props.peers).to.be.equal(peers);
expect(props.account).to.be.equal(account);
expect(typeof props.onActivePeerUpdated).to.be.equal('function');
});

it('should bind activePeerUpdate action to AccountComponent props.onActivePeerUpdated', () => {
const actionsSpy = sinon.spy(peersActions, 'activePeerUpdate');
props.onActivePeerUpdated({});
expect(actionsSpy).to.be.calledWith();
actionsSpy.restore();
});

it('should bind accountUpdated action to AccountComponent props.onAccountUpdated', () => {
const actionsSpy = sinon.spy(accountActions, 'accountUpdated');
props.onAccountUpdated({});
expect(actionsSpy).to.be.calledWith();
actionsSpy.restore();
});

it('should bind transactionsUpdated action to AccountComponent props.onTransactionsUpdated', () => {
const actionsSpy = sinon.spy(transactionsActions, 'transactionsUpdated');
props.onTransactionsUpdated({});
expect(actionsSpy).to.be.calledWith();
actionsSpy.restore();
});
});
53 changes: 42 additions & 11 deletions src/components/forging/forgingComponent.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,42 @@ import React from 'react';
import chai, { expect } from 'chai';
import sinonChai from 'sinon-chai';
import { mount } from 'enzyme';
import sinon from 'sinon';
import ForgingComponent from './forgingComponent';
import * as forgingApi from '../../utils/api/forging';

chai.use(sinonChai);


describe('ForgingComponent', () => {
let wrapper;
const props = {
account: {
delegate: {},
isDelegate: true,
},
peers: {},
statistics: {},
forgedBlocks: [],
loadStats: () => {},
loadForgedBlocks: () => {},
};
let props;
let forginApiMock;

beforeEach(() => {
props = {
account: {
delegate: {},
isDelegate: true,
},
peers: {},
statistics: {},
forgedBlocks: [],
onForgingStatsUpdate: sinon.spy(),
onForgedBlocksLoaded: sinon.spy(),
};

forginApiMock = sinon.mock(forgingApi);
forginApiMock.expects('getForgedStats').atLeast(5).resolves({ success: true });
forginApiMock.expects('getForgedBlocks').resolves({ success: true, blocks: [] });

wrapper = mount(<ForgingComponent {...props} />);
});

afterEach(() => {
forginApiMock.restore();
});

it('should render ForgingTitle', () => {
expect(wrapper.find('ForgingTitle')).to.have.lengthOf(1);
});
Expand All @@ -40,4 +53,22 @@ describe('ForgingComponent', () => {
it('should render ForgedBlocks', () => {
expect(wrapper.find('ForgedBlocks')).to.have.lengthOf(1);
});

it('should render only a "not delegate" message if !props.account.isDelegate', () => {
props.account.isDelegate = false;
wrapper = mount(<ForgingComponent {...props} />);

expect(wrapper.find('ForgedBlocks')).to.have.lengthOf(0);
expect(wrapper.find('DelegateStats')).to.have.lengthOf(0);
expect(wrapper.find('p')).to.have.lengthOf(1);
});

// TODO: make these tests work
it.skip('should call props.onForgingStatsUpdate', () => {
expect(props.onForgingStatsUpdate).to.have.been.calledWith();
});

it.skip('should call props.onForgedBlocksLoaded', () => {
expect(props.onForgedBlocksLoaded).to.have.been.calledWith();
});
});
24 changes: 23 additions & 1 deletion src/components/forging/index.test.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import React from 'react';
import chai, { expect } from 'chai';
import sinonChai from 'sinon-chai';
import sinon from 'sinon';
import { mount } from 'enzyme';
import { Provider } from 'react-redux';
import configureMockStore from 'redux-mock-store';
import * as forgingActions from '../../actions/forging';
import Forging from './';
import store from '../../store';

chai.use(sinonChai);

Expand All @@ -13,10 +15,30 @@ describe('Forging', () => {
let wrapper;

beforeEach(() => {
const store = configureMockStore([])({
account: {},
peers: {},
forging: {
statistics: {},
forgedBlocks: [],
},
});
wrapper = mount(<Provider store={store}><Forging /></Provider>);
});

it('should render ForgingComponent', () => {
expect(wrapper.find('ForgingComponent')).to.have.lengthOf(1);
});

it('should bind updateForgedBlocks action to ForgingComponent props.onForgedBlocksLoaded', () => {
const actionsSpy = sinon.spy(forgingActions, 'updateForgedBlocks');
wrapper.find('ForgingComponent').props().onForgedBlocksLoaded([]);
expect(actionsSpy).to.be.calledWith();
});

it('should bind updateForgingStats action to ForgingComponent props.onForgingStatsUpdate', () => {
const actionsSpy = sinon.spy(forgingActions, 'updateForgingStats');
wrapper.find('ForgingComponent').props().onForgingStatsUpdate({});
expect(actionsSpy).to.be.calledWith();
});
});
36 changes: 36 additions & 0 deletions src/components/header/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from 'react';
import { expect } from 'chai';
import { mount } from 'enzyme';
import { Provider } from 'react-redux';
import sinon from 'sinon';
import * as accountActions from '../../actions/account';
import * as dialogActions from '../../actions/dialog';
import Header from './index';
import store from '../../store';


describe('Header', () => {
let wrapper;

beforeEach(() => {
wrapper = mount(<Provider store={store}><Header /></Provider>);
});

it('should render HeaderElement', () => {
expect(wrapper.find('HeaderElement')).to.have.lengthOf(1);
});

it('should bind accountLoggedOut action to HeaderElement props.logOut', () => {
const actionsSpy = sinon.spy(accountActions, 'accountLoggedOut');
wrapper.find('HeaderElement').props().logOut({});
expect(actionsSpy).to.be.calledWith();
actionsSpy.restore();
});

it('should bind dialogDisplayed action to HeaderElement props.setActiveDialog', () => {
const actionsSpy = sinon.spy(dialogActions, 'dialogDisplayed');
wrapper.find('HeaderElement').props().setActiveDialog({});
expect(actionsSpy).to.be.calledWith();
actionsSpy.restore();
});
});
19 changes: 18 additions & 1 deletion src/components/login/loginForm.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ describe('LoginForm', () => {
address: '16313739661670634666L',
username: 'lisk-nano',
};

const store = {
dispatch: () => {},
subscribe: () => {},
Expand All @@ -47,4 +46,22 @@ describe('LoginForm', () => {
expect(props.account).to.be.equal(account);
expect(typeof props.activePeerSet).to.be.equal('function');
});

describe('activePeerSet', () => {
it('should return a dispatch object', () => {
const mountedAccount = mount(<Router><LoginForm/></Router>, options);
const props = mountedAccount.find(LoginFormComponent).props();
const data = props.activePeerSet(peers.data);
expect(data).to.deep.equal(undefined);
});
});

describe('setActiveDialog', () => {
it('should return a dispatch object', () => {
const mountedAccount = mount(<Router><LoginForm/></Router>, options);
const props = mountedAccount.find(LoginFormComponent).props();
const data = props.setActiveDialog({});
expect(data).to.deep.equal(undefined);
});
});
});
4 changes: 3 additions & 1 deletion src/components/login/loginFormComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import networksRaw from './networks';
import Passphrase from '../passphrase';
import styles from './login.css';

// ignore else in coverage as it is hard to test and not our business logic
/* istanbul ignore else */
if (global._bitcore) delete global._bitcore;

/**
Expand Down Expand Up @@ -113,7 +115,7 @@ class LoginFormComponent extends React.Component {
/>
{
this.state.network === 2 &&
<Input type='text' label='Node address' name='address'
<Input type='text' label='Node address' name='address' className='address'
value={this.state.address} error={this.state.addressValidity}
onChange={this.validateUrl.bind(this)} />
}
Expand Down
Loading

0 comments on commit 3a44735

Please sign in to comment.