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

Adding more tests for register component - Closes #839 #848

Merged
merged 6 commits into from
Oct 10, 2017
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
44 changes: 10 additions & 34 deletions src/components/login/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import getNetworks from './networks';
import PassphraseInput from '../passphraseInput';
import styles from './login.css';
import env from '../../constants/env';
import networks from '../../constants/networks';
import LanguageDropdown from '../languageDropdown';
import RelativeLink from '../relativeLink';
import { validateUrl, getLoginData } from '../../utils/login';

/**
* The container component containing login
Expand All @@ -21,11 +23,11 @@ class Login extends React.Component {
this.state = {
passphrase: '',
address: '',
network: 0,
network: networks.mainnet,
};

this.validators = {
address: this.validateUrl,
address: validateUrl,
passphrase: this.validatePassphrase.bind(this),
};
}
Expand Down Expand Up @@ -55,7 +57,7 @@ class Login extends React.Component {

onLoginSubmission(passphrase) {
const network = Object.assign({}, getNetworks()[this.state.network]);
if (this.state.network === 2) {
if (this.state.network === networks.customNode) {
network.address = this.state.address;
}

Expand All @@ -77,30 +79,6 @@ class Login extends React.Component {
return referrerRoute;
}

// eslint-disable-next-line class-methods-use-this
validateUrl(value) {
const addHttp = (url) => {
const reg = /^(?:f|ht)tps?:\/\//i;
return reg.test(url) ? url : `http://${url}`;
};

const errorMessage = 'URL is invalid';

const isValidLocalhost = url => url.hostname === 'localhost' && url.port.length > 1;
const isValidRemote = url => /(([a-z\d]([a-z\d-]*[a-z\d])*)\.)+[a-z]{2,}|((\d{1,3}\.){3}\d{1,3})/.test(url.hostname);

let addressValidity = '';
try {
const url = new URL(addHttp(value));
addressValidity = url && (isValidRemote(url) || isValidLocalhost(url)) ? '' : errorMessage;
} catch (e) {
addressValidity = errorMessage;
}

const data = { address: value, addressValidity };
return data;
}

// eslint-disable-next-line class-methods-use-this
validatePassphrase(value, error) {
const data = { passphrase: value };
Expand All @@ -117,12 +95,10 @@ class Login extends React.Component {
}

devPreFill() {
const address = localStorage.getItem('address') || '';
const passphrase = localStorage.getItem('passphrase') || '';
const network = parseInt(localStorage.getItem('network'), 10) || 0;
const { networkIndex, address, passphrase } = getLoginData();

this.setState({
network,
network: networkIndex,
...this.validators.address(address),
...this.validators.passphrase(passphrase),
});
Expand All @@ -146,7 +122,7 @@ class Login extends React.Component {
if (savedAccounts && savedAccounts.length > 0 && !this.props.account.afterLogout) {
this.account = savedAccounts[0];
const network = Object.assign({}, getNetworks()[this.account.network]);
if (this.account.network === 2) {
if (this.account.network === networks.customNode) {
network.address = this.account.address;
}

Expand Down Expand Up @@ -177,7 +153,7 @@ class Login extends React.Component {
className={`${styles.network} network`}
/>
{
this.state.network === 2 &&
this.state.network === networks.customNode &&
<Input type='text'
label={this.props.t('Node address')}
name='address'
Expand All @@ -202,7 +178,7 @@ class Login extends React.Component {
<Button label={this.props.t('Login')} primary raised
className='login-button'
type='submit'
disabled={(this.state.network === 2 && this.state.addressValidity !== '') ||
disabled={(this.state.network === networks.customNode && this.state.addressValidity !== '') ||
this.state.passphraseValidity !== ''} />
</div>
</footer>
Expand Down
55 changes: 10 additions & 45 deletions src/components/login/login.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ describe('Login', () => {
},
lifecycleExperimental: true,
};
props.spyActivePeerSet = spy(props.activePeerSet);

describe('Generals', () => {
beforeEach(() => {
Expand All @@ -72,30 +71,30 @@ describe('Login', () => {
props.account = { address: 'dummy' };

it('calls this.props.history.replace(\'/main/transactions\')', () => {
wrapper = shallow(<Router><Login {...props}/></Router>, options);
wrapper = shallow(<Login {...props}/>, options);
wrapper.setProps(props);
expect(props.history.replace).to.have.been.calledWith('/main/transactions');
});

it.skip('calls this.props.history.replace with referrer address', () => {
wrapper = shallow(<Router><Login {...props}/></Router>, options);
it('calls this.props.history.replace with referrer address', () => {
wrapper = shallow(<Login {...props}/>, options);
props.history.replace.reset();
history.location.search = '?referrer=/main/voting';
wrapper.setProps({ history });
expect(props.history.replace).to.have.been.calledWith('/main/voting');
});

it.skip('call this.props.history.replace with "/main/transaction" if referrer address is "/main/forging" and account.isDelegate === false', () => {
it('call this.props.history.replace with "/main/transaction" if referrer address is "/main/forging" and account.isDelegate === false', () => {
history.location.search = '';
wrapper = shallow(<Router><Login {...props}/></Router>, options);
wrapper = shallow(<Login {...props}/>, options);
history.location.search = '?referrer=/main/forging';
account.isDelegate = false;
props.history.replace.reset();
wrapper.setProps({ history, account });
expect(props.history.replace).to.have.been.calledWith('/main/transactions');
});

it.skip('calls localStorage.setItem(\'address\', address) if this.state.address', () => {
it('calls localStorage.setItem(\'address\', address) if this.state.address', () => {
const spyFn = spy(localStorage, 'setItem');
wrapper = shallow(<Login {...props}/>, options);
wrapper.setState({ address });
Expand All @@ -107,42 +106,6 @@ describe('Login', () => {
});
});

describe('validateUrl', () => {
beforeEach('', () => {
wrapper = shallow(<Login {...props}/>, options);
});

it('should set address and addressValidity="" for a valid address', () => {
const validURL = 'http://localhost:8080';
const data = wrapper.instance().validateUrl(validURL);
const expectedData = {
address: validURL,
addressValidity: '',
};
expect(data).to.deep.equal(expectedData);
});

it('should set address and addressValidity correctly event without http', () => {
const validURL = '127.0.0.1:8080';
const data = wrapper.instance().validateUrl(validURL);
const expectedData = {
address: validURL,
addressValidity: '',
};
expect(data).to.deep.equal(expectedData);
});

it('should set address and addressValidity="URL is invalid" for a valid address', () => {
const validURL = 'http:localhost:8080';
const data = wrapper.instance().validateUrl(validURL);
const expectedData = {
address: validURL,
addressValidity: 'URL is invalid',
};
expect(data).to.deep.equal(expectedData);
});
});

describe('changeHandler', () => {
it('call setState with matching data', () => {
wrapper = shallow(<Login {...props}/>, options);
Expand All @@ -155,10 +118,12 @@ describe('Login', () => {
});

describe('onLoginSubmission', () => {
it.skip('it should call activePeerSet', () => {
it('it should call activePeerSet', () => {
const spyActivePeerSet = spy(props, 'activePeerSet');

wrapper = shallow(<Login {...props}/>, options);
wrapper.instance().onLoginSubmission();
expect(wrapper.props().spyActivePeerSet).to.have.been.calledWith();
expect(spyActivePeerSet).to.have.been.calledWith();
});
});
});
38 changes: 9 additions & 29 deletions src/components/register/register.js
Original file line number Diff line number Diff line change
@@ -1,43 +1,23 @@
import React from 'react';
import Passphrase from '../passphrase';
import networks from '../../constants/networks';
import getNetworks from '../login/networks';
import { validateUrl, getLoginData } from '../../utils/login';

const Register = ({
activePeerSet, closeDialog, t,
}) => {
const validateUrl = (value) => {
const addHttp = (url) => {
const reg = /^(?:f|ht)tps?:\/\//i;
return reg.test(url) ? url : `http://${url}`;
};

const errorMessage = 'URL is invalid';

const isValidLocalhost = url => url.hostname === 'localhost' && url.port.length > 1;
const isValidRemote = url => /(([a-z\d]([a-z\d-]*[a-z\d])*)\.)+[a-z]{2,}|((\d{1,3}\.){3}\d{1,3})/.test(url.hostname);

let addressValidity = '';
try {
const url = new URL(addHttp(value));
addressValidity = url && (isValidRemote(url) || isValidLocalhost(url)) ? '' : errorMessage;
} catch (e) {
addressValidity = errorMessage;
}
const onLoginSubmission = (passphrase) => {
const { networkIndex, address } = getLoginData();

return addressValidity === '';
};
let index = networkIndex;

const onLoginSubmission = (passphrase) => {
let NetworkIndex = parseInt(localStorage.getItem('network'), 10) || 0;
const address = localStorage.getItem('address') || '';
if (!NetworkIndex || (NetworkIndex === 2 && !validateUrl(address))) {
NetworkIndex = 0;
if (!index || (index === networks.customNode && validateUrl(address).addressValidity !== '')) {
index = networks.mainnet;
}

const network = Object.assign({}, getNetworks()[NetworkIndex]);
if (NetworkIndex === 2) {
network.address = address;
}
const network = Object.assign({}, getNetworks()[index]);
if (index === networks.customNode) { network.address = address; }

// set active peer
activePeerSet({
Expand Down
60 changes: 58 additions & 2 deletions src/components/register/register.test.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import React from 'react';
import { expect } from 'chai';
import { mount } from 'enzyme';
import { spy } from 'sinon';
import { spy, stub } from 'sinon';
import PropTypes from 'prop-types';
import configureMockStore from 'redux-mock-store';
import i18n from '../../i18n';
import networks from '../../constants/networks';
import Register from './register';
import getNetworks from '../login/networks';
import * as Utils from '../../utils/login';


describe('Register', () => {
let wrapper;
let loginData;
const peers = { data: {} };
const account = {};
const store = configureMockStore([])({
Expand All @@ -33,6 +37,11 @@ describe('Register', () => {

beforeEach(() => {
wrapper = mount(<Register {...prop} />, options);
loginData = stub(Utils, 'getLoginData');
});

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

it('renders Passphrase component', () => {
Expand All @@ -50,9 +59,56 @@ describe('Register', () => {

it('should call activePeerSet if props.onPassGenerated is called', () => {
const props = wrapper.find('Passphrase').props();

loginData.returns({ address: 'some address', networkIndex: networks.mainnet });

props.onPassGenerated('sample passphrase');
expect(prop.activePeerSet).to.have.been.calledWith({
network: getNetworks()[networks.mainnet],
passphrase: 'sample passphrase',
});
});

it('should call activePeerSet with testnet if network index is testnet', () => {
const props = wrapper.find('Passphrase').props();

loginData.returns({ address: 'invalid address', networkIndex: networks.testnet });

props.onPassGenerated('sample passphrase');
expect(loginData).to.have.been.calledWith();

expect(prop.activePeerSet).to.have.been.calledWith({
network: getNetworks()[networks.testnet],
passphrase: 'sample passphrase',
});
});

it('should call activePeerSet with mainnet if network index is custom node and address is invalid', () => {
const props = wrapper.find('Passphrase').props();

loginData.returns({ address: 'invalid address', networkIndex: networks.customNode });

props.onPassGenerated('sample passphrase');
expect(loginData).to.have.been.calledWith();

expect(prop.activePeerSet).to.have.been.calledWith({
network: getNetworks()[networks.mainnet],
passphrase: 'sample passphrase',
});
});

it('should call activePeerSet with custom node if network index is custom node and address is valid', () => {
const props = wrapper.find('Passphrase').props();

loginData.returns({ address: '127.0.0.1:8080', networkIndex: networks.customNode });

props.onPassGenerated('sample passphrase');
expect(loginData).to.have.been.calledWith();

const network = getNetworks()[networks.customNode];
network.address = '127.0.0.1:8080';
expect(prop.activePeerSet).to.have.been.calledWith({
network: getNetworks()[0],
network,
passphrase: 'sample passphrase',
});
});
Expand Down
7 changes: 7 additions & 0 deletions src/constants/networks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const networks = {
mainnet: 0,
testnet: 1,
customNode: 2,
};

export default networks;
31 changes: 31 additions & 0 deletions src/utils/login.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const validateUrl = (value) => {
const addHttp = (url) => {
const reg = /^(?:f|ht)tps?:\/\//i;
return reg.test(url) ? url : `http://${url}`;
};

const errorMessage = 'URL is invalid';

const isValidLocalhost = url => url.hostname === 'localhost' && url.port.length > 1;
const isValidRemote = url => /(([a-z\d]([a-z\d-]*[a-z\d])*)\.)+[a-z]{2,}|((\d{1,3}\.){3}\d{1,3})/.test(url.hostname);

let addressValidity = '';
try {
const url = new URL(addHttp(value));
addressValidity = url && (isValidRemote(url) || isValidLocalhost(url)) ? '' : errorMessage;
} catch (e) {
addressValidity = errorMessage;
}

return { address: value, addressValidity };
};

const getLoginData = () => {
const address = localStorage.getItem('address') || '';
const passphrase = localStorage.getItem('passphrase') || '';
const networkIndex = parseInt(localStorage.getItem('network'), 10) || 0;

return { address, networkIndex, passphrase };
};

export { validateUrl, getLoginData };
Loading