Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve test coverage of second passphrase - Close #564 #598

Merged
merged 4 commits into from
Mar 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,6 @@ module.exports = function (config) {
'src/components/multiStep/index.js',
'src/components/passphrase/create/index.js',
'src/components/passphrase/createSecond/index.js',
'src/components/passphrase/ConfirmSecond/confirmSecond.js',
'src/components/passphrase/ConfirmSecond/index.js',
'src/components/passphrase/safekeeping/index.js',
'src/components/secondPassphrase/secondPassphrase.js',
'src/components/toolbox/sliderCheckbox/index.js',
Expand Down
6 changes: 4 additions & 2 deletions src/components/passphrase/ConfirmSecond/confirmSecond.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,10 @@ class confirmSecond extends React.Component {
</h2>
</TransitionWrapper>
<TransitionWrapper current={this.state.step} step='pending'>
<div><FontIcon className={styles.pendingIcon} value="logo-icon"></FontIcon></div>
<div id='pendingContainer'><FontIcon className={styles.pendingIcon} value="logo-icon"></FontIcon></div>
</TransitionWrapper>
<TransitionWrapper current={this.state.step} step='done'>
<article className={styles.resultContainer}>
<article className={`${styles.resultContainer} doneContainer`}>
<FontIcon className={styles.headerIcon} value="checkmark"></FontIcon>
<h2 className={styles.resultHeader}>
{t('Success!')}
Expand All @@ -97,11 +97,13 @@ class confirmSecond extends React.Component {
onChange={this.onChange.bind(this, 'passphrase')}
columns={{ xs: 6, sm: 4, md: 2 }}
isFocused={true}
className='passphraseInput'
/>
<footer>
<Button
label={this.props.t('Unlock account')}
theme={styles}
className={'unlock'}
onClick={this.login.bind(this, 'passphrase')}
disabled={!passphraseIsValid(this.state.passphrase)}
/>
Expand Down
110 changes: 110 additions & 0 deletions src/components/passphrase/ConfirmSecond/confirmSecond.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import React from 'react';
import { expect } from 'chai';
import PropTypes from 'prop-types';
import { mount } from 'enzyme';
import { spy, useFakeTimers } from 'sinon';
import configureStore from 'redux-mock-store';
import ConfirmSecond from './confirmSecond';
import i18n from '../../../i18n';
import accounts from '../../../../test/constants/accounts';


describe('SecondPassphrase: Confirmation', () => {
const props = {
t: key => key,
hidden: false,
finalCallback: spy(),
account: accounts.delegate,
};
const account = accounts.delegate;
const fakeStore = configureStore();
const store = fakeStore({
account,
});
let wrapper;
let clock;

const options = {
context: { i18n, store },
childContextTypes: {
i18n: PropTypes.object.isRequired,
store: PropTypes.object.isRequired,
},
};
beforeEach(() => {
clock = useFakeTimers({
toFake: ['setTimeout', 'clearTimeout', 'Date', 'setInterval'],
});
});

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

it('should hide the component when hidden is equal to true', () => {
wrapper = mount(<ConfirmSecond {...props} hidden={true} />, options);
const className = wrapper.find('section').props().className;
expect(className).to.include('hidden');
});

it('shows login step when user is not login', () => {
wrapper = mount(<ConfirmSecond {...props} account={{ passphrase: null }} />, options);
clock.tick(501);
wrapper.update();
const className = wrapper.find('h2').at(0).props().className;
expect(className).to.include('slideIn');
});

it('should unlock button become enable when passphrase is entered', () => {
const newAccount = Object.assign({}, accounts.delegate, { passphrase: null });
wrapper = mount(<ConfirmSecond {...props} account={newAccount} />, options);
clock.tick(501);
wrapper.update();
expect(wrapper.find('button.unlock')).to.be.disabled();
const temp = wrapper.find('Input.passphraseInput input').at(0);
temp.simulate('change', { target: { value: accounts.delegate.passphrase } });
wrapper.update();
expect(wrapper.find('button.unlock')).to.not.be.disabled();
wrapper.find('button.unlock').simulate('click');
clock.tick(501);
wrapper.update();
const className = wrapper.find('h2').at(1).props().className;
expect(className).to.include('slideIn');
});

it('shows confirmation step when user is login', () => {
wrapper = mount(<ConfirmSecond {...props} />, options);
clock.tick(501);
wrapper.update();
const className = wrapper.find('h2').at(1).props().className;
expect(className).to.include('slideIn');
});

it('should show pending mode when SliderCheckbox is checked', () => {
wrapper = mount(<ConfirmSecond {...props} />, options);
wrapper.find('SliderCheckbox').at(0).find('input[type="checkbox"]')
.simulate('change', { target: { checked: true } });
clock.tick(501);
wrapper.update();
const className = wrapper.find('#pendingContainer').props().className;
expect(className).to.include('slideIn');
expect(props.finalCallback).to.have.been.calledWith();
});

it('should show the final Step when secondSecret is set', () => {
wrapper = mount(<ConfirmSecond {...props} />, options);
wrapper.find('SliderCheckbox').at(0).find('input[type="checkbox"]')
.simulate('change', { target: { checked: true } });
clock.tick(501);
wrapper.update();
expect(props.finalCallback).to.have.been.calledWith();
wrapper.setProps({ account: {
passphrase: accounts.passphrase,
secondSignature: 1,
} });
clock.tick(501);
wrapper.update();
const className = wrapper.find('.doneContainer').props().className;
expect(className).to.include('slideIn');
});
});
40 changes: 40 additions & 0 deletions src/components/passphrase/ConfirmSecond/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react';
import { expect } from 'chai';
import PropTypes from 'prop-types';
import { mount } from 'enzyme';
import { MemoryRouter as Router } from 'react-router-dom';
import { Provider } from 'react-redux';
import configureStore from 'redux-mock-store';
import ConfirmationHOC from './index';
import ConfirmSecond from './confirmSecond';
import i18n from '../../../i18n';
import accounts from '../../../../test/constants/accounts';


describe('SecondPassphrase: ConfirmationHOC', () => {
const account = accounts.delegate;
const fakeStore = configureStore();
const store = fakeStore({
account,
});
let wrapper;

const options = {
context: { i18n, store },
childContextTypes: {
i18n: PropTypes.object.isRequired,
store: PropTypes.object.isRequired,
},
};
beforeEach(() => {
wrapper = mount(<Router>
<Provider store={store}>
<ConfirmationHOC hidden={true} />
</Provider>
</Router>, options);
});

it('should contain ConfirmSecond', () => {
expect(wrapper.find(ConfirmSecond)).to.have.lengthOf(1);
});
});
48 changes: 48 additions & 0 deletions src/components/passphrase/createSecond/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React from 'react';
import { expect } from 'chai';
import PropTypes from 'prop-types';
import { mount } from 'enzyme';
import simulant from 'simulant';
import configureStore from 'redux-mock-store';
import CreateSecond from './index';
import i18n from '../../../i18n';
import accounts from '../../../../test/constants/accounts';


describe('Passphrase: Create', () => {
const props = {
t: key => key,
prevStep: () => {},
nextStep: () => {},
};
const account = accounts.delegate;
const fakeStore = configureStore();
const store = fakeStore({
account,
});

const options = {
// attachTo: document.body,
context: { i18n, store },
childContextTypes: {
i18n: PropTypes.object.isRequired,
store: PropTypes.object.isRequired,
},
};

it('shows ProgressBar components', () => {
const wrapper = mount(<CreateSecond {...props} />, options);
expect(wrapper.find('ProgressBar')).to.have.lengthOf(1);
});

it.skip('shows at least some progress on mousemove', () => {
options.attachTo = document.body;
const wrapper = mount(<CreateSecond {...props} agent='Chrome'/>, options);
for (let i = 0; i < 100; i++) {
simulant.fire(document.body, 'mousemove', {
pageX: 100 * i, pageY: 100 * i,
});
}
expect(wrapper.find('ProgressBar').props().value).to.be.at.least(1);
});
});
4 changes: 0 additions & 4 deletions src/components/secondPassphrase/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { connect } from 'react-redux';
import { translate } from 'react-i18next';
import { withRouter } from 'react-router';
import { dialogDisplayed } from '../../actions/dialog';
import { secondPassphraseRegistered } from '../../actions/account';
import SecondPassphrase from './secondPassphrase';

Expand All @@ -10,12 +9,9 @@ import SecondPassphrase from './secondPassphrase';
*/
const mapStateToProps = state => ({
account: state.account,
passphrase: state.account.passphrase,
peers: state.peers,
});

const mapDispatchToProps = dispatch => ({
setActiveDialog: data => dispatch(dialogDisplayed(data)),
registerSecondPassphrase: data => dispatch(secondPassphraseRegistered(data)),
});

Expand Down
4 changes: 0 additions & 4 deletions src/components/secondPassphrase/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@ import SecondPassphraseHOC from './index';

describe('SecondPassphraseHOC', () => {
let wrapper;
const peers = {};
const account = { secondSignature: 1 };
const store = configureMockStore([])({
peers,
account,
});

Expand All @@ -34,9 +32,7 @@ describe('SecondPassphraseHOC', () => {

it('should mount SecondPassphrase with appropriate properties', () => {
const props = wrapper.find('SecondPassphrase').props();
expect(props.peers).to.be.equal(peers);
expect(props.account).to.be.equal(account);
expect(typeof props.setActiveDialog).to.be.equal('function');
expect(typeof props.registerSecondPassphrase).to.be.equal('function');
});
});