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:
		
							parent
							
								
									602a4429cc
								
							
						
					
					
						commit
						ddeb06d9cc
					
				| @ -21,7 +21,7 @@ const TEST_ENV = process.env.NODE_ENV === 'test'; | |||||||
| 
 | 
 | ||||||
| export function createIdentityImg (address, scale = 8) { | export function createIdentityImg (address, scale = 8) { | ||||||
|   return TEST_ENV |   return TEST_ENV | ||||||
|     ? '' |     ? 'test-createIdentityImg' | ||||||
|     : blockies({ |     : blockies({ | ||||||
|       seed: (address || '').toLowerCase(), |       seed: (address || '').toLowerCase(), | ||||||
|       size: 8, |       size: 8, | ||||||
|  | |||||||
| @ -15,6 +15,7 @@ | |||||||
| // along with Parity.  If not, see <http://www.gnu.org/licenses/>.
 | // along with Parity.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
| 
 | 
 | ||||||
| import React, { Component, PropTypes } from 'react'; | import React, { Component, PropTypes } from 'react'; | ||||||
|  | import { FormattedMessage } from 'react-intl'; | ||||||
| import { connect } from 'react-redux'; | import { connect } from 'react-redux'; | ||||||
| import { bindActionCreators } from 'redux'; | import { bindActionCreators } from 'redux'; | ||||||
| 
 | 
 | ||||||
| @ -39,7 +40,12 @@ class BlockStatus extends Component { | |||||||
|     if (!syncing) { |     if (!syncing) { | ||||||
|       return ( |       return ( | ||||||
|         <div className={ styles.blockNumber }> |         <div className={ styles.blockNumber }> | ||||||
|           { blockNumber.toFormat() } best block |           <FormattedMessage | ||||||
|  |             id='ui.blockStatus.bestBlock' | ||||||
|  |             defaultMessage='{blockNumber} best block' | ||||||
|  |             values={ { | ||||||
|  |               blockNumber: blockNumber.toFormat() | ||||||
|  |             } } /> | ||||||
|         </div> |         </div> | ||||||
|       ); |       ); | ||||||
|     } |     } | ||||||
| @ -47,26 +53,45 @@ class BlockStatus extends Component { | |||||||
|     if (syncing.warpChunksAmount && syncing.warpChunksProcessed && !syncing.warpChunksAmount.eq(syncing.warpChunksProcessed)) { |     if (syncing.warpChunksAmount && syncing.warpChunksProcessed && !syncing.warpChunksAmount.eq(syncing.warpChunksProcessed)) { | ||||||
|       return ( |       return ( | ||||||
|         <div className={ styles.syncStatus }> |         <div className={ styles.syncStatus }> | ||||||
|           { syncing.warpChunksProcessed.mul(100).div(syncing.warpChunksAmount).toFormat(2) }% warp restore |           <FormattedMessage | ||||||
|  |             id='ui.blockStatus.warpRestore' | ||||||
|  |             defaultMessage='{percentage}% warp restore' | ||||||
|  |             values={ { | ||||||
|  |               percentage: syncing.warpChunksProcessed.mul(100).div(syncing.warpChunksAmount).toFormat(2) | ||||||
|  |             } } /> | ||||||
|         </div> |         </div> | ||||||
|       ); |       ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     let syncStatus = null; | ||||||
|     let warpStatus = null; |     let warpStatus = null; | ||||||
| 
 | 
 | ||||||
|  |     if (syncing.currentBlock && syncing.highestBlock) { | ||||||
|  |       syncStatus = ( | ||||||
|  |         <span> | ||||||
|  |           <FormattedMessage | ||||||
|  |             id='ui.blockStatus.syncStatus' | ||||||
|  |             defaultMessage='{currentBlock}/{highestBlock} syncing' | ||||||
|  |             values={ { | ||||||
|  |               currentBlock: syncing.currentBlock.toFormat(), | ||||||
|  |               highestBlock: syncing.highestBlock.toFormat() | ||||||
|  |             } } /> | ||||||
|  |         </span> | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     if (syncing.blockGap) { |     if (syncing.blockGap) { | ||||||
|       const [first, last] = syncing.blockGap; |       const [first, last] = syncing.blockGap; | ||||||
| 
 | 
 | ||||||
|       warpStatus = ( |       warpStatus = ( | ||||||
|         <span>, { first.mul(100).div(last).toFormat(2) }% historic</span> |         <span> | ||||||
|       ); |           <FormattedMessage | ||||||
|     } |             id='ui.blockStatus.warpStatus' | ||||||
| 
 |             defaultMessage=', {percentage}% historic' | ||||||
|     let syncStatus = null; |             values={ { | ||||||
| 
 |               percentage: first.mul(100).div(last).toFormat(2) | ||||||
|     if (syncing && syncing.currentBlock && syncing.highestBlock) { |             } } /> | ||||||
|       syncStatus = ( |         </span> | ||||||
|         <span>{ syncing.currentBlock.toFormat() }/{ syncing.highestBlock.toFormat() } syncing</span> |  | ||||||
|       ); |       ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										94
									
								
								js/src/ui/BlockStatus/blockStatus.spec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								js/src/ui/BlockStatus/blockStatus.spec.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,94 @@ | |||||||
|  | // 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 BlockStatus from './'; | ||||||
|  | 
 | ||||||
|  | let component; | ||||||
|  | 
 | ||||||
|  | function createRedux (syncing = false, blockNumber = new BigNumber(123)) { | ||||||
|  |   return { | ||||||
|  |     dispatch: sinon.stub(), | ||||||
|  |     subscribe: sinon.stub(), | ||||||
|  |     getState: () => { | ||||||
|  |       return { | ||||||
|  |         nodeStatus: { | ||||||
|  |           blockNumber, | ||||||
|  |           syncing | ||||||
|  |         } | ||||||
|  |       }; | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function render (reduxStore = createRedux(), props) { | ||||||
|  |   component = shallow( | ||||||
|  |     <BlockStatus { ...props } />, | ||||||
|  |     { context: { store: reduxStore } } | ||||||
|  |   ).find('BlockStatus').shallow(); | ||||||
|  | 
 | ||||||
|  |   return component; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | describe('ui/BlockStatus', () => { | ||||||
|  |   it('renders defaults', () => { | ||||||
|  |     expect(render()).to.be.ok; | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('renders null with no blockNumber', () => { | ||||||
|  |     expect(render(createRedux(false, null)).find('div')).to.have.length(0); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('renders only the best block when syncing === false', () => { | ||||||
|  |     const messages = render().find('FormattedMessage'); | ||||||
|  | 
 | ||||||
|  |     expect(messages).to.have.length(1); | ||||||
|  |     expect(messages).to.have.id('ui.blockStatus.bestBlock'); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('renders only the warp restore status when restoring', () => { | ||||||
|  |     const messages = render(createRedux({ | ||||||
|  |       warpChunksAmount: new BigNumber(100), | ||||||
|  |       warpChunksProcessed: new BigNumber(5) | ||||||
|  |     })).find('FormattedMessage'); | ||||||
|  | 
 | ||||||
|  |     expect(messages).to.have.length(1); | ||||||
|  |     expect(messages).to.have.id('ui.blockStatus.warpRestore'); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('renders the current/highest when syncing', () => { | ||||||
|  |     const messages = render(createRedux({ | ||||||
|  |       currentBlock: new BigNumber(123), | ||||||
|  |       highestBlock: new BigNumber(456) | ||||||
|  |     })).find('FormattedMessage'); | ||||||
|  | 
 | ||||||
|  |     expect(messages).to.have.length(1); | ||||||
|  |     expect(messages).to.have.id('ui.blockStatus.syncStatus'); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('renders warp blockGap when catching up', () => { | ||||||
|  |     const messages = render(createRedux({ | ||||||
|  |       blockGap: [new BigNumber(123), new BigNumber(456)] | ||||||
|  |     })).find('FormattedMessage'); | ||||||
|  | 
 | ||||||
|  |     expect(messages).to.have.length(1); | ||||||
|  |     expect(messages).to.have.id('ui.blockStatus.warpStatus'); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
| @ -19,7 +19,11 @@ import { shallow } from 'enzyme'; | |||||||
| 
 | 
 | ||||||
| import Button from './button'; | import Button from './button'; | ||||||
| 
 | 
 | ||||||
| function renderShallow (props) { | function render (props = {}) { | ||||||
|  |   if (props && props.label === undefined) { | ||||||
|  |     props.label = 'test'; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   return shallow( |   return shallow( | ||||||
|     <Button { ...props } /> |     <Button { ...props } /> | ||||||
|   ); |   ); | ||||||
| @ -28,11 +32,11 @@ function renderShallow (props) { | |||||||
| describe('ui/Button', () => { | describe('ui/Button', () => { | ||||||
|   describe('rendering', () => { |   describe('rendering', () => { | ||||||
|     it('renders defaults', () => { |     it('renders defaults', () => { | ||||||
|       expect(renderShallow()).to.be.ok; |       expect(render()).to.be.ok; | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('renders with the specified className', () => { |     it('renders with the specified className', () => { | ||||||
|       expect(renderShallow({ className: 'testClass' })).to.have.className('testClass'); |       expect(render({ className: 'testClass' })).to.have.className('testClass'); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
| }); | }); | ||||||
|  | |||||||
| @ -15,16 +15,27 @@ | |||||||
| // along with Parity.  If not, see <http://www.gnu.org/licenses/>.
 | // along with Parity.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
| 
 | 
 | ||||||
| import React, { Component, PropTypes } from 'react'; | import React, { Component, PropTypes } from 'react'; | ||||||
| import ActionDone from 'material-ui/svg-icons/action/done'; | import { FormattedMessage } from 'react-intl'; | ||||||
| import ContentClear from 'material-ui/svg-icons/content/clear'; |  | ||||||
| 
 | 
 | ||||||
| import { nodeOrStringProptype } from '~/util/proptypes'; | import { nodeOrStringProptype } from '~/util/proptypes'; | ||||||
| 
 | 
 | ||||||
| import Button from '../Button'; | import Button from '../Button'; | ||||||
| import Modal from '../Modal'; | import Modal from '../Modal'; | ||||||
|  | import { CancelIcon, CheckIcon } from '../Icons'; | ||||||
| 
 | 
 | ||||||
| import styles from './confirmDialog.css'; | import styles from './confirmDialog.css'; | ||||||
| 
 | 
 | ||||||
|  | const DEFAULT_NO = ( | ||||||
|  |   <FormattedMessage | ||||||
|  |     id='ui.confirmDialog.no' | ||||||
|  |     defaultMessage='no' /> | ||||||
|  | ); | ||||||
|  | const DEFAULT_YES = ( | ||||||
|  |   <FormattedMessage | ||||||
|  |     id='ui.confirmDialog.yes' | ||||||
|  |     defaultMessage='yes' /> | ||||||
|  | ); | ||||||
|  | 
 | ||||||
| export default class ConfirmDialog extends Component { | export default class ConfirmDialog extends Component { | ||||||
|   static propTypes = { |   static propTypes = { | ||||||
|     children: PropTypes.node.isRequired, |     children: PropTypes.node.isRequired, | ||||||
| @ -33,10 +44,10 @@ export default class ConfirmDialog extends Component { | |||||||
|     iconDeny: PropTypes.node, |     iconDeny: PropTypes.node, | ||||||
|     labelConfirm: PropTypes.string, |     labelConfirm: PropTypes.string, | ||||||
|     labelDeny: PropTypes.string, |     labelDeny: PropTypes.string, | ||||||
|     title: nodeOrStringProptype().isRequired, |  | ||||||
|     visible: PropTypes.bool.isRequired, |  | ||||||
|     onConfirm: PropTypes.func.isRequired, |     onConfirm: PropTypes.func.isRequired, | ||||||
|     onDeny: PropTypes.func.isRequired |     onDeny: PropTypes.func.isRequired, | ||||||
|  |     title: nodeOrStringProptype().isRequired, | ||||||
|  |     visible: PropTypes.bool.isRequired | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
| @ -60,12 +71,12 @@ export default class ConfirmDialog extends Component { | |||||||
| 
 | 
 | ||||||
|     return [ |     return [ | ||||||
|       <Button |       <Button | ||||||
|         label={ labelDeny || 'no' } |         icon={ iconDeny || <CancelIcon /> } | ||||||
|         icon={ iconDeny || <ContentClear /> } |         label={ labelDeny || DEFAULT_NO } | ||||||
|         onClick={ onDeny } />, |         onClick={ onDeny } />, | ||||||
|       <Button |       <Button | ||||||
|         label={ labelConfirm || 'yes' } |         icon={ iconConfirm || <CheckIcon /> } | ||||||
|         icon={ iconConfirm || <ActionDone /> } |         label={ labelConfirm || DEFAULT_YES } | ||||||
|         onClick={ onConfirm } /> |         onClick={ onConfirm } /> | ||||||
|     ]; |     ]; | ||||||
|   } |   } | ||||||
|  | |||||||
							
								
								
									
										157
									
								
								js/src/ui/ConfirmDialog/confirmDialog.spec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								js/src/ui/ConfirmDialog/confirmDialog.spec.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,157 @@ | |||||||
|  | // 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 { shallow } from 'enzyme'; | ||||||
|  | import React, { PropTypes } from 'react'; | ||||||
|  | import sinon from 'sinon'; | ||||||
|  | 
 | ||||||
|  | import muiTheme from '../Theme'; | ||||||
|  | 
 | ||||||
|  | import ConfirmDialog from './'; | ||||||
|  | 
 | ||||||
|  | let component; | ||||||
|  | let instance; | ||||||
|  | let onConfirm; | ||||||
|  | let onDeny; | ||||||
|  | 
 | ||||||
|  | function createRedux () { | ||||||
|  |   return { | ||||||
|  |     dispatch: sinon.stub(), | ||||||
|  |     subscribe: sinon.stub(), | ||||||
|  |     getState: () => { | ||||||
|  |       return { | ||||||
|  |         settings: { | ||||||
|  |           backgroundSeed: 'xyz' | ||||||
|  |         } | ||||||
|  |       }; | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function render (props = {}) { | ||||||
|  |   onConfirm = sinon.stub(); | ||||||
|  |   onDeny = sinon.stub(); | ||||||
|  | 
 | ||||||
|  |   if (props.visible === undefined) { | ||||||
|  |     props.visible = true; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   const baseComponent = shallow( | ||||||
|  |     <ConfirmDialog | ||||||
|  |       { ...props } | ||||||
|  |       title='test title' | ||||||
|  |       onConfirm={ onConfirm } | ||||||
|  |       onDeny={ onDeny }> | ||||||
|  |       <div id='testContent'> | ||||||
|  |         some test content | ||||||
|  |       </div> | ||||||
|  |     </ConfirmDialog> | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  |   instance = baseComponent.instance(); | ||||||
|  |   component = baseComponent.find('Connect(Modal)').shallow({ | ||||||
|  |     childContextTypes: { | ||||||
|  |       muiTheme: PropTypes.object, | ||||||
|  |       store: PropTypes.object | ||||||
|  |     }, | ||||||
|  |     context: { | ||||||
|  |       muiTheme, | ||||||
|  |       store: createRedux() | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   return component; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | describe('ui/ConfirmDialog', () => { | ||||||
|  |   it('renders defaults', () => { | ||||||
|  |     expect(render()).to.be.ok; | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('renders the body as provided', () => { | ||||||
|  |     expect(render().find('div[id="testContent"]').text()).to.equal('some test content'); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   describe('properties', () => { | ||||||
|  |     let props; | ||||||
|  | 
 | ||||||
|  |     beforeEach(() => { | ||||||
|  |       props = render().props(); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     it('passes the actions', () => { | ||||||
|  |       expect(props.actions).to.deep.equal(instance.renderActions()); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     it('passes title', () => { | ||||||
|  |       expect(props.title).to.equal('test title'); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     it('passes visiblity flag', () => { | ||||||
|  |       expect(props.visible).to.be.true; | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   describe('renderActions', () => { | ||||||
|  |     describe('defaults', () => { | ||||||
|  |       let buttons; | ||||||
|  | 
 | ||||||
|  |       beforeEach(() => { | ||||||
|  |         render(); | ||||||
|  |         buttons = instance.renderActions(); | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |       it('renders with supplied onConfim/onDeny callbacks', () => { | ||||||
|  |         expect(buttons[0].props.onClick).to.deep.equal(onDeny); | ||||||
|  |         expect(buttons[1].props.onClick).to.deep.equal(onConfirm); | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |       it('renders default labels', () => { | ||||||
|  |         expect(buttons[0].props.label.props.id).to.equal('ui.confirmDialog.no'); | ||||||
|  |         expect(buttons[1].props.label.props.id).to.equal('ui.confirmDialog.yes'); | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |       it('renders default icons', () => { | ||||||
|  |         expect(buttons[0].props.icon.type.displayName).to.equal('ContentClear'); | ||||||
|  |         expect(buttons[1].props.icon.type.displayName).to.equal('NavigationCheck'); | ||||||
|  |       }); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     describe('overrides', () => { | ||||||
|  |       let buttons; | ||||||
|  | 
 | ||||||
|  |       beforeEach(() => { | ||||||
|  |         render({ | ||||||
|  |           labelConfirm: 'labelConfirm', | ||||||
|  |           labelDeny: 'labelDeny', | ||||||
|  |           iconConfirm: 'iconConfirm', | ||||||
|  |           iconDeny: 'iconDeny' | ||||||
|  |         }); | ||||||
|  |         buttons = instance.renderActions(); | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |       it('renders supplied labels', () => { | ||||||
|  |         expect(buttons[0].props.label).to.equal('labelDeny'); | ||||||
|  |         expect(buttons[1].props.label).to.equal('labelConfirm'); | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |       it('renders supplied icons', () => { | ||||||
|  |         expect(buttons[0].props.icon).to.equal('iconDeny'); | ||||||
|  |         expect(buttons[1].props.icon).to.equal('iconConfirm'); | ||||||
|  |       }); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
| @ -19,7 +19,7 @@ import { shallow } from 'enzyme'; | |||||||
| 
 | 
 | ||||||
| import Container from './container'; | import Container from './container'; | ||||||
| 
 | 
 | ||||||
| function renderShallow (props) { | function render (props) { | ||||||
|   return shallow( |   return shallow( | ||||||
|     <Container { ...props } /> |     <Container { ...props } /> | ||||||
|   ); |   ); | ||||||
| @ -28,11 +28,24 @@ function renderShallow (props) { | |||||||
| describe('ui/Container', () => { | describe('ui/Container', () => { | ||||||
|   describe('rendering', () => { |   describe('rendering', () => { | ||||||
|     it('renders defaults', () => { |     it('renders defaults', () => { | ||||||
|       expect(renderShallow()).to.be.ok; |       expect(render()).to.be.ok; | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('renders with the specified className', () => { |     it('renders with the specified className', () => { | ||||||
|       expect(renderShallow({ className: 'testClass' })).to.have.className('testClass'); |       expect(render({ className: 'testClass' })).to.have.className('testClass'); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   describe('sections', () => { | ||||||
|  |     it('renders the Card', () => { | ||||||
|  |       expect(render().find('Card')).to.have.length(1); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     it('renders the Title', () => { | ||||||
|  |       const title = render({ title: 'title' }).find('Title'); | ||||||
|  | 
 | ||||||
|  |       expect(title).to.have.length(1); | ||||||
|  |       expect(title.props().title).to.equal('title'); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
| }); | }); | ||||||
|  | |||||||
| @ -29,6 +29,7 @@ const api = { | |||||||
| 
 | 
 | ||||||
| const store = { | const store = { | ||||||
|   estimated: '123', |   estimated: '123', | ||||||
|  |   histogram: {}, | ||||||
|   priceDefault: '456', |   priceDefault: '456', | ||||||
|   totalValue: '789', |   totalValue: '789', | ||||||
|   setGas: sinon.stub(), |   setGas: sinon.stub(), | ||||||
|  | |||||||
| @ -34,8 +34,8 @@ class IdentityIcon extends Component { | |||||||
|     button: PropTypes.bool, |     button: PropTypes.bool, | ||||||
|     center: PropTypes.bool, |     center: PropTypes.bool, | ||||||
|     className: PropTypes.string, |     className: PropTypes.string, | ||||||
|     inline: PropTypes.bool, |  | ||||||
|     images: PropTypes.object.isRequired, |     images: PropTypes.object.isRequired, | ||||||
|  |     inline: PropTypes.bool, | ||||||
|     padded: PropTypes.bool, |     padded: PropTypes.bool, | ||||||
|     tiny: PropTypes.bool |     tiny: PropTypes.bool | ||||||
|   } |   } | ||||||
|  | |||||||
							
								
								
									
										120
									
								
								js/src/ui/IdentityIcon/identityIcon.spec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								js/src/ui/IdentityIcon/identityIcon.spec.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,120 @@ | |||||||
|  | // 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 { mount } from 'enzyme'; | ||||||
|  | import React, { PropTypes } from 'react'; | ||||||
|  | import sinon from 'sinon'; | ||||||
|  | 
 | ||||||
|  | import muiTheme from '../Theme'; | ||||||
|  | 
 | ||||||
|  | import IdentityIcon from './'; | ||||||
|  | 
 | ||||||
|  | const ADDRESS0 = '0x0000000000000000000000000000000000000000'; | ||||||
|  | const ADDRESS1 = '0x0123456789012345678901234567890123456789'; | ||||||
|  | const ADDRESS2 = '0x9876543210987654321098765432109876543210'; | ||||||
|  | 
 | ||||||
|  | let component; | ||||||
|  | 
 | ||||||
|  | function createApi () { | ||||||
|  |   return { | ||||||
|  |     dappsUrl: 'dappsUrl/' | ||||||
|  |   }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function createRedux () { | ||||||
|  |   return { | ||||||
|  |     dispatch: sinon.stub(), | ||||||
|  |     subscribe: sinon.stub(), | ||||||
|  |     getState: () => { | ||||||
|  |       return { | ||||||
|  |         images: { | ||||||
|  |           [ADDRESS2]: 'reduxImage' | ||||||
|  |         } | ||||||
|  |       }; | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function render (props = {}) { | ||||||
|  |   if (props && props.address === undefined) { | ||||||
|  |     props.address = ADDRESS1; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   component = mount( | ||||||
|  |     <IdentityIcon { ...props } />, | ||||||
|  |     { | ||||||
|  |       childContextTypes: { | ||||||
|  |         api: PropTypes.object, | ||||||
|  |         muiTheme: PropTypes.object | ||||||
|  |       }, | ||||||
|  |       context: { | ||||||
|  |         api: createApi(), | ||||||
|  |         muiTheme, | ||||||
|  |         store: createRedux() | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  |   return component; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | describe('ui/IdentityIcon', () => { | ||||||
|  |   it('renders defaults', () => { | ||||||
|  |     expect(render()).to.be.ok; | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   describe('images', () => { | ||||||
|  |     it('renders an <img> with address specified', () => { | ||||||
|  |       const img = render().find('img'); | ||||||
|  | 
 | ||||||
|  |       expect(img).to.have.length(1); | ||||||
|  |       expect(img.props().src).to.equal('test-createIdentityImg'); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     it('renders an <img> with redux source when available', () => { | ||||||
|  |       const img = render({ address: ADDRESS2 }).find('img'); | ||||||
|  | 
 | ||||||
|  |       expect(img).to.have.length(1); | ||||||
|  |       expect(img.props().src).to.equal('dappsUrl/reduxImage'); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     it('renders an <ContractIcon> with no address specified', () => { | ||||||
|  |       expect(render({ address: null }).find('ActionCode')).to.have.length(1); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     it('renders an <CancelIcon> with 0x00..00 address specified', () => { | ||||||
|  |       expect(render({ address: ADDRESS0 }).find('ContentClear')).to.have.length(1); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   describe('sizes', () => { | ||||||
|  |     it('renders 56px by default', () => { | ||||||
|  |       expect(render().find('img').props().width).to.equal('56px'); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     it('renders 16px for tiny', () => { | ||||||
|  |       expect(render({ tiny: true }).find('img').props().width).to.equal('16px'); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     it('renders 24px for button', () => { | ||||||
|  |       expect(render({ button: true }).find('img').props().width).to.equal('24px'); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     it('renders 32px for inline', () => { | ||||||
|  |       expect(render({ inline: true }).find('img').props().width).to.equal('32px'); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
| @ -15,13 +15,23 @@ | |||||||
| // along with Parity.  If not, see <http://www.gnu.org/licenses/>.
 | // along with Parity.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
| 
 | 
 | ||||||
| import React, { Component, PropTypes } from 'react'; | import React, { Component, PropTypes } from 'react'; | ||||||
|  | import { FormattedMessage } from 'react-intl'; | ||||||
| import { connect } from 'react-redux'; | import { connect } from 'react-redux'; | ||||||
| import { bindActionCreators } from 'redux'; | import { bindActionCreators } from 'redux'; | ||||||
| 
 | 
 | ||||||
| import { isNullAddress } from '~/util/validation'; | import { isNullAddress } from '~/util/validation'; | ||||||
| import ShortenedHash from '../ShortenedHash'; | import ShortenedHash from '../ShortenedHash'; | ||||||
| 
 | 
 | ||||||
| const defaultName = 'UNNAMED'; | const defaultName = ( | ||||||
|  |   <FormattedMessage | ||||||
|  |     id='ui.identityName.unnamed' | ||||||
|  |     defaultMessage='UNNAMED' /> | ||||||
|  | ); | ||||||
|  | const defaultNameNull = ( | ||||||
|  |   <FormattedMessage | ||||||
|  |     id='ui.identityName.null' | ||||||
|  |     defaultMessage='NULL' /> | ||||||
|  | ); | ||||||
| 
 | 
 | ||||||
| class IdentityName extends Component { | class IdentityName extends Component { | ||||||
|   static propTypes = { |   static propTypes = { | ||||||
| @ -43,7 +53,7 @@ class IdentityName extends Component { | |||||||
|       return null; |       return null; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     const nullName = isNullAddress(address) ? 'null' : null; |     const nullName = isNullAddress(address) ? defaultNameNull : null; | ||||||
|     const addressFallback = nullName || (shorten ? (<ShortenedHash data={ address } />) : address); |     const addressFallback = nullName || (shorten ? (<ShortenedHash data={ address } />) : address); | ||||||
|     const fallback = unknown ? defaultName : addressFallback; |     const fallback = unknown ? defaultName : addressFallback; | ||||||
|     const isUuid = account && account.name === account.uuid; |     const isUuid = account && account.name === account.uuid; | ||||||
|  | |||||||
| @ -14,8 +14,10 @@ | |||||||
| // You should have received a copy of the GNU General Public License
 | // You should have received a copy of the GNU General Public License
 | ||||||
| // along with Parity.  If not, see <http://www.gnu.org/licenses/>.
 | // along with Parity.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
| 
 | 
 | ||||||
| import React from 'react'; |  | ||||||
| import { mount } from 'enzyme'; | import { mount } from 'enzyme'; | ||||||
|  | import React from 'react'; | ||||||
|  | import { IntlProvider } from 'react-intl'; | ||||||
|  | 
 | ||||||
| import sinon from 'sinon'; | import sinon from 'sinon'; | ||||||
| 
 | 
 | ||||||
| import IdentityName from './identityName'; | import IdentityName from './identityName'; | ||||||
| @ -44,9 +46,11 @@ const STORE = { | |||||||
| 
 | 
 | ||||||
| function render (props) { | function render (props) { | ||||||
|   return mount( |   return mount( | ||||||
|     <IdentityName |     <IntlProvider locale='en'> | ||||||
|       store={ STORE } |       <IdentityName | ||||||
|       { ...props } /> |         store={ STORE } | ||||||
|  |         { ...props } /> | ||||||
|  |     </IntlProvider> | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -74,7 +78,7 @@ describe('ui/IdentityName', () => { | |||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       it('renders 0x000...000 as null', () => { |       it('renders 0x000...000 as null', () => { | ||||||
|         expect(render({ address: ADDR_NULL }).text()).to.equal('null'); |         expect(render({ address: ADDR_NULL }).text()).to.equal('NULL'); | ||||||
|       }); |       }); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
|  | |||||||
| @ -16,6 +16,7 @@ | |||||||
| 
 | 
 | ||||||
| import BigNumber from 'bignumber.js'; | import BigNumber from 'bignumber.js'; | ||||||
| import React, { Component, PropTypes } from 'react'; | import React, { Component, PropTypes } from 'react'; | ||||||
|  | import { FormattedMessage } from 'react-intl'; | ||||||
| import { connect } from 'react-redux'; | import { connect } from 'react-redux'; | ||||||
| import { bindActionCreators } from 'redux'; | import { bindActionCreators } from 'redux'; | ||||||
| import { LinearProgress } from 'material-ui'; | import { LinearProgress } from 'material-ui'; | ||||||
| @ -33,8 +34,8 @@ class TxHash extends Component { | |||||||
|   static propTypes = { |   static propTypes = { | ||||||
|     hash: PropTypes.string.isRequired, |     hash: PropTypes.string.isRequired, | ||||||
|     isTest: PropTypes.bool, |     isTest: PropTypes.bool, | ||||||
|     summary: PropTypes.bool, |     maxConfirmations: PropTypes.number, | ||||||
|     maxConfirmations: PropTypes.number |     summary: PropTypes.bool | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   static defaultProps = { |   static defaultProps = { | ||||||
| @ -43,14 +44,14 @@ class TxHash extends Component { | |||||||
| 
 | 
 | ||||||
|   state = { |   state = { | ||||||
|     blockNumber: new BigNumber(0), |     blockNumber: new BigNumber(0), | ||||||
|     transaction: null, |     subscriptionId: null, | ||||||
|     subscriptionId: null |     transaction: null | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   componentDidMount () { |   componentDidMount () { | ||||||
|     const { api } = this.context; |     const { api } = this.context; | ||||||
| 
 | 
 | ||||||
|     api.subscribe('eth_blockNumber', this.onBlockNumber).then((subscriptionId) => { |     return api.subscribe('eth_blockNumber', this.onBlockNumber).then((subscriptionId) => { | ||||||
|       this.setState({ subscriptionId }); |       this.setState({ subscriptionId }); | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| @ -59,28 +60,28 @@ class TxHash extends Component { | |||||||
|     const { api } = this.context; |     const { api } = this.context; | ||||||
|     const { subscriptionId } = this.state; |     const { subscriptionId } = this.state; | ||||||
| 
 | 
 | ||||||
|     api.unsubscribe(subscriptionId); |     return api.unsubscribe(subscriptionId); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { hash, isTest, summary } = this.props; |     const { hash, isTest, summary } = this.props; | ||||||
| 
 | 
 | ||||||
|     const link = ( |     const hashLink = ( | ||||||
|       <a href={ txLink(hash, isTest) } target='_blank'> |       <a href={ txLink(hash, isTest) } target='_blank'> | ||||||
|         <ShortenedHash data={ hash } /> |         <ShortenedHash data={ hash } /> | ||||||
|       </a> |       </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 ( |     return ( | ||||||
|       <div> |       <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() } |         { this.renderConfirmations() } | ||||||
|       </div> |       </div> | ||||||
|     ); |     ); | ||||||
| @ -98,20 +99,22 @@ class TxHash extends Component { | |||||||
|             color='white' |             color='white' | ||||||
|             mode='indeterminate' |             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> |         </div> | ||||||
|       ); |       ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     const confirmations = blockNumber.minus(transaction.blockNumber).plus(1); |     const confirmations = blockNumber.minus(transaction.blockNumber).plus(1); | ||||||
|     const value = Math.min(confirmations.toNumber(), maxConfirmations); |     const value = Math.min(confirmations.toNumber(), maxConfirmations); | ||||||
|     let count; | 
 | ||||||
|     if (confirmations.gt(maxConfirmations)) { |     let count = confirmations.toFormat(0); | ||||||
|       count = confirmations.toFormat(0); |     if (confirmations.lte(maxConfirmations)) { | ||||||
|     } else { |       count = `${count}/${maxConfirmations}`; | ||||||
|       count = confirmations.toFormat(0) + `/${maxConfirmations}`; |  | ||||||
|     } |     } | ||||||
|     const unit = value === 1 ? 'confirmation' : 'confirmations'; |  | ||||||
| 
 | 
 | ||||||
|     return ( |     return ( | ||||||
|       <div className={ styles.confirm }> |       <div className={ styles.confirm }> | ||||||
| @ -121,10 +124,17 @@ class TxHash extends Component { | |||||||
|           max={ maxConfirmations } |           max={ maxConfirmations } | ||||||
|           value={ value } |           value={ value } | ||||||
|           color='white' |           color='white' | ||||||
|           mode='determinate' |           mode='determinate' /> | ||||||
|         /> |  | ||||||
|         <div className={ styles.progressinfo }> |         <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> | ||||||
|       </div> |       </div> | ||||||
|     ); |     ); | ||||||
| @ -138,15 +148,17 @@ class TxHash extends Component { | |||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     this.setState({ blockNumber }); |     return api.eth | ||||||
| 
 |  | ||||||
|     api.eth |  | ||||||
|       .getTransactionReceipt(hash) |       .getTransactionReceipt(hash) | ||||||
|       .then((transaction) => { |       .then((transaction) => { | ||||||
|         this.setState({ transaction }); |         this.setState({ | ||||||
|  |           blockNumber, | ||||||
|  |           transaction | ||||||
|  |         }); | ||||||
|       }) |       }) | ||||||
|       .catch((error) => { |       .catch((error) => { | ||||||
|         console.warn('onBlockNumber', 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'); | ||||||
|  |       }); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
| @ -25,7 +25,7 @@ import TxRow from './txRow'; | |||||||
| 
 | 
 | ||||||
| const api = new Api({ execute: sinon.stub() }); | const api = new Api({ execute: sinon.stub() }); | ||||||
| 
 | 
 | ||||||
| function renderShallow (props) { | function render (props) { | ||||||
|   return shallow( |   return shallow( | ||||||
|     <TxRow |     <TxRow | ||||||
|       { ...props } />, |       { ...props } />, | ||||||
| @ -33,7 +33,7 @@ function renderShallow (props) { | |||||||
|   ); |   ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| describe('ui/TxRow', () => { | describe('ui/TxList/TxRow', () => { | ||||||
|   describe('rendering', () => { |   describe('rendering', () => { | ||||||
|     it('renders defaults', () => { |     it('renders defaults', () => { | ||||||
|       const block = { |       const block = { | ||||||
| @ -45,7 +45,7 @@ describe('ui/TxRow', () => { | |||||||
|         value: new BigNumber(1) |         value: new BigNumber(1) | ||||||
|       }; |       }; | ||||||
| 
 | 
 | ||||||
|       expect(renderShallow({ block, tx })).to.be.ok; |       expect(render({ address: '0x123', block, isTest: true, tx })).to.be.ok; | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
| }); | }); | ||||||
|  | |||||||
| @ -36,7 +36,7 @@ const STORE = { | |||||||
|   } |   } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| function renderShallow (props) { | function render (props) { | ||||||
|   return shallow( |   return shallow( | ||||||
|     <TxList |     <TxList | ||||||
|       store={ STORE } |       store={ STORE } | ||||||
| @ -48,7 +48,7 @@ function renderShallow (props) { | |||||||
| describe('ui/TxList', () => { | describe('ui/TxList', () => { | ||||||
|   describe('rendering', () => { |   describe('rendering', () => { | ||||||
|     it('renders defaults', () => { |     it('renders defaults', () => { | ||||||
|       expect(renderShallow()).to.be.ok; |       expect(render({ address: '0x123', hashes: [] })).to.be.ok; | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
| }); | }); | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user