UI component updates (#4010)
* Update blockStatus & test results * IdentityIcon rendering tests for #3950 * Update IdentityName with external messages * Expand to cover basic layout sections * ConfirmDialog rendering tests * TxHash expansion & tests * Cleanup ui/*.spec.js PropType warnings * Use react-intl plural for confirmation/confirmations (verified manually)
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
|
||||
import BigNumber from 'bignumber.js';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { LinearProgress } from 'material-ui';
|
||||
@@ -33,8 +34,8 @@ class TxHash extends Component {
|
||||
static propTypes = {
|
||||
hash: PropTypes.string.isRequired,
|
||||
isTest: PropTypes.bool,
|
||||
summary: PropTypes.bool,
|
||||
maxConfirmations: PropTypes.number
|
||||
maxConfirmations: PropTypes.number,
|
||||
summary: PropTypes.bool
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
@@ -43,14 +44,14 @@ class TxHash extends Component {
|
||||
|
||||
state = {
|
||||
blockNumber: new BigNumber(0),
|
||||
transaction: null,
|
||||
subscriptionId: null
|
||||
subscriptionId: null,
|
||||
transaction: null
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
const { api } = this.context;
|
||||
|
||||
api.subscribe('eth_blockNumber', this.onBlockNumber).then((subscriptionId) => {
|
||||
return api.subscribe('eth_blockNumber', this.onBlockNumber).then((subscriptionId) => {
|
||||
this.setState({ subscriptionId });
|
||||
});
|
||||
}
|
||||
@@ -59,28 +60,28 @@ class TxHash extends Component {
|
||||
const { api } = this.context;
|
||||
const { subscriptionId } = this.state;
|
||||
|
||||
api.unsubscribe(subscriptionId);
|
||||
return api.unsubscribe(subscriptionId);
|
||||
}
|
||||
|
||||
render () {
|
||||
const { hash, isTest, summary } = this.props;
|
||||
|
||||
const link = (
|
||||
const hashLink = (
|
||||
<a href={ txLink(hash, isTest) } target='_blank'>
|
||||
<ShortenedHash data={ hash } />
|
||||
</a>
|
||||
);
|
||||
|
||||
let header = (
|
||||
<p>The transaction has been posted to the network, with a hash of { link }.</p>
|
||||
);
|
||||
if (summary) {
|
||||
header = (<p>{ link }</p>);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{ header }
|
||||
<p>{
|
||||
summary
|
||||
? hashLink
|
||||
: <FormattedMessage
|
||||
id='ui.txHash.posted'
|
||||
defaultMessage='The transaction has been posted to the network with a hash of {hashLink}'
|
||||
values={ { hashLink } } />
|
||||
}</p>
|
||||
{ this.renderConfirmations() }
|
||||
</div>
|
||||
);
|
||||
@@ -98,20 +99,22 @@ class TxHash extends Component {
|
||||
color='white'
|
||||
mode='indeterminate'
|
||||
/>
|
||||
<div className={ styles.progressinfo }>waiting for confirmations</div>
|
||||
<div className={ styles.progressinfo }>
|
||||
<FormattedMessage
|
||||
id='ui.txHash.waiting'
|
||||
defaultMessage='waiting for confirmations' />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const confirmations = blockNumber.minus(transaction.blockNumber).plus(1);
|
||||
const value = Math.min(confirmations.toNumber(), maxConfirmations);
|
||||
let count;
|
||||
if (confirmations.gt(maxConfirmations)) {
|
||||
count = confirmations.toFormat(0);
|
||||
} else {
|
||||
count = confirmations.toFormat(0) + `/${maxConfirmations}`;
|
||||
|
||||
let count = confirmations.toFormat(0);
|
||||
if (confirmations.lte(maxConfirmations)) {
|
||||
count = `${count}/${maxConfirmations}`;
|
||||
}
|
||||
const unit = value === 1 ? 'confirmation' : 'confirmations';
|
||||
|
||||
return (
|
||||
<div className={ styles.confirm }>
|
||||
@@ -121,10 +124,17 @@ class TxHash extends Component {
|
||||
max={ maxConfirmations }
|
||||
value={ value }
|
||||
color='white'
|
||||
mode='determinate'
|
||||
/>
|
||||
mode='determinate' />
|
||||
<div className={ styles.progressinfo }>
|
||||
<abbr title={ `block #${blockNumber.toFormat(0)}` }>{ count } { unit }</abbr>
|
||||
<abbr title={ `block #${blockNumber.toFormat(0)}` }>
|
||||
<FormattedMessage
|
||||
id='ui.txHash.confirmations'
|
||||
defaultMessage='{count} {value, plural, one {confirmation} other {confirmations}}'
|
||||
values={ {
|
||||
count,
|
||||
value
|
||||
} } />
|
||||
</abbr>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -138,15 +148,17 @@ class TxHash extends Component {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({ blockNumber });
|
||||
|
||||
api.eth
|
||||
return api.eth
|
||||
.getTransactionReceipt(hash)
|
||||
.then((transaction) => {
|
||||
this.setState({ transaction });
|
||||
this.setState({
|
||||
blockNumber,
|
||||
transaction
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.warn('onBlockNumber', error);
|
||||
this.setState({ blockNumber });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
132
js/src/ui/TxHash/txHash.spec.js
Normal file
132
js/src/ui/TxHash/txHash.spec.js
Normal file
@@ -0,0 +1,132 @@
|
||||
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { shallow } from 'enzyme';
|
||||
import React from 'react';
|
||||
import sinon from 'sinon';
|
||||
|
||||
import TxHash from './';
|
||||
|
||||
const TXHASH = '0xabcdef123454321abcdef';
|
||||
|
||||
let api;
|
||||
let blockNumber;
|
||||
let callback;
|
||||
let component;
|
||||
let instance;
|
||||
|
||||
function createApi () {
|
||||
blockNumber = new BigNumber(100);
|
||||
api = {
|
||||
eth: {
|
||||
getTransactionReceipt: (hash) => {
|
||||
return Promise.resolve({
|
||||
blockNumber: new BigNumber(100),
|
||||
hash
|
||||
});
|
||||
}
|
||||
},
|
||||
nextBlock: (increment = 1) => {
|
||||
blockNumber = blockNumber.plus(increment);
|
||||
return callback(null, blockNumber);
|
||||
},
|
||||
subscribe: (type, _callback) => {
|
||||
callback = _callback;
|
||||
return callback(null, blockNumber).then(() => {
|
||||
return Promise.resolve(1);
|
||||
});
|
||||
},
|
||||
unsubscribe: sinon.stub().resolves(true)
|
||||
};
|
||||
|
||||
return api;
|
||||
}
|
||||
|
||||
function createRedux () {
|
||||
return {
|
||||
dispatch: sinon.stub(),
|
||||
subscribe: sinon.stub(),
|
||||
getState: () => {
|
||||
return {
|
||||
nodeStatus: { isTest: true }
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function render (props) {
|
||||
const baseComponent = shallow(
|
||||
<TxHash
|
||||
hash={ TXHASH }
|
||||
{ ...props } />,
|
||||
{ context: { store: createRedux() } }
|
||||
);
|
||||
component = baseComponent.find('TxHash').shallow({ context: { api: createApi() } });
|
||||
instance = component.instance();
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
describe('ui/TxHash', () => {
|
||||
beforeEach(() => {
|
||||
render();
|
||||
});
|
||||
|
||||
it('renders defaults', () => {
|
||||
expect(component).to.be.ok;
|
||||
});
|
||||
|
||||
it('renders the summary', () => {
|
||||
expect(component.find('p').find('FormattedMessage').props().id).to.equal('ui.txHash.posted');
|
||||
});
|
||||
|
||||
describe('renderConfirmations', () => {
|
||||
describe('with no transaction retrieved', () => {
|
||||
let child;
|
||||
|
||||
beforeEach(() => {
|
||||
child = shallow(instance.renderConfirmations());
|
||||
});
|
||||
|
||||
it('renders indeterminate progressbar', () => {
|
||||
expect(child.find('LinearProgress[mode="indeterminate"]')).to.have.length(1);
|
||||
});
|
||||
|
||||
it('renders waiting text', () => {
|
||||
expect(child.find('FormattedMessage').props().id).to.equal('ui.txHash.waiting');
|
||||
});
|
||||
});
|
||||
|
||||
describe('with transaction retrieved', () => {
|
||||
let child;
|
||||
|
||||
beforeEach(() => {
|
||||
return instance.componentDidMount().then(() => {
|
||||
child = shallow(instance.renderConfirmations());
|
||||
});
|
||||
});
|
||||
|
||||
it('renders determinate progressbar', () => {
|
||||
expect(child.find('LinearProgress[mode="determinate"]')).to.have.length(1);
|
||||
});
|
||||
|
||||
it('renders confirmation text', () => {
|
||||
expect(child.find('FormattedMessage').props().id).to.equal('ui.txHash.confirmations');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user