Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Fixed bool dropdown in contract execution #3823

Merged
merged 8 commits into from Dec 12, 2016
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 26 additions & 5 deletions js/src/api/util/identity.js
@@ -1,9 +1,30 @@
// 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 blockies from 'blockies';

// jsdom doesn't have all the browser features, blockies fail
const TEST_ENV = process.env.NODE_ENV === 'test';

export function createIdentityImg (address, scale = 8) {
return blockies({
seed: (address || '').toLowerCase(),
size: 8,
scale
}).toDataURL();
return TEST_ENV
? ''
: blockies({
seed: (address || '').toLowerCase(),
size: 8,
scale
}).toDataURL();
}
18 changes: 9 additions & 9 deletions js/src/modals/ExecuteContract/DetailsStep/detailsStep.js
Expand Up @@ -58,23 +58,23 @@ export default class DetailsStep extends Component {
<Form>
{ this.renderWarning() }
<AddressSelect
label='from account'
hint='the account to transact with'
value={ fromAddress }
error={ fromAddressError }
accounts={ accounts }
balances={ balances }
onChange={ onFromAddressChange } />
error={ fromAddressError }
hint='the account to transact with'
label='from account'
onChange={ onFromAddressChange }
value={ fromAddress } />
{ this.renderFunctionSelect() }
{ this.renderParameters() }
<div className={ styles.columns }>
<div>
<Input
label='transaction value (in ETH)'
hint='the amount to send to with the transaction'
value={ amount }
error={ amountError }
onSubmit={ onAmountChange } />
hint='the amount to send to with the transaction'
label='transaction value (in ETH)'
onSubmit={ onAmountChange }
value={ amount } />
</div>
<div>
<Checkbox
Expand Down
83 changes: 83 additions & 0 deletions js/src/modals/ExecuteContract/DetailsStep/detailsStep.spec.js
@@ -0,0 +1,83 @@
// 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 from 'react';
import sinon from 'sinon';

import { ContextProvider, muiTheme } from '~/ui';

import DetailsStep from './';

import { CONTRACT } from '../executeContract.test.js';

let component;
let onAmountChange;
let onClose;
let onFromAddressChange;
let onFuncChange;
let onGasEditClick;
let onValueChange;

function render (props) {
onAmountChange = sinon.stub();
onClose = sinon.stub();
onFromAddressChange = sinon.stub();
onFuncChange = sinon.stub();
onGasEditClick = sinon.stub();
onValueChange = sinon.stub();

component = mount(
<ContextProvider api={ {} } muiTheme={ muiTheme } store={ {} }>
<DetailsStep
{ ...props }
contract={ CONTRACT }
onAmountChange={ onAmountChange }
onClose={ onClose }
onFromAddressChange={ onFromAddressChange }
onFuncChange={ onFuncChange }
onGasEditClick={ onGasEditClick }
onValueChange={ onValueChange } />
</ContextProvider>
);

return component;
}

describe('modals/ExecuteContract/DetailsStep', () => {
it('renders', () => {
expect(render({ accounts: {}, values: [ true ], valuesError: [ null ] })).to.be.ok;
});

describe('parameter values', () => {
beforeEach(() => {
render({
accounts: {},
func: CONTRACT.functions[0],
values: [ false ],
valuesError: [ null ]
});
});

describe('bool parameters', () => {
it('toggles from false to true', () => {
component.find('DropDownMenu').last().simulate('change', { target: { value: 'true' } });

expect(onValueChange).to.have.been.calledWith(null, 0, true);
});
});
});
});
20 changes: 8 additions & 12 deletions js/src/modals/ExecuteContract/executeContract.js
Expand Up @@ -25,6 +25,7 @@ import ContentClear from 'material-ui/svg-icons/content/clear';
import NavigationArrowBack from 'material-ui/svg-icons/navigation/arrow-back';
import NavigationArrowForward from 'material-ui/svg-icons/navigation/arrow-forward';

import { toWei } from '~/api/util/wei';
import { BusyStep, Button, CompletedStep, GasPriceEditor, IdentityIcon, Modal, TxHash } from '~/ui';
import { MAX_GAS_ESTIMATION } from '~/util/constants';
import { validateAddress, validateUint } from '~/util/validation';
Expand Down Expand Up @@ -56,12 +57,12 @@ class ExecuteContract extends Component {
}

static propTypes = {
isTest: PropTypes.bool,
fromAddress: PropTypes.string,
accounts: PropTypes.object,
balances: PropTypes.object,
contract: PropTypes.object,
contract: PropTypes.object.isRequired,
fromAddress: PropTypes.string,
gasLimit: PropTypes.object.isRequired,
isTest: PropTypes.bool,
onClose: PropTypes.func.isRequired,
onFromAddressChange: PropTypes.func.isRequired
}
Expand All @@ -77,11 +78,11 @@ class ExecuteContract extends Component {
funcError: null,
gasEdit: false,
rejected: false,
step: STEP_DETAILS,
sending: false,
step: STEP_DETAILS,
txhash: null,
values: [],
valuesError: [],
txhash: null
valuesError: []
}

componentDidMount () {
Expand Down Expand Up @@ -255,10 +256,6 @@ class ExecuteContract extends Component {
valueError = validateAddress(_value).addressError;
break;

case 'bool':
value = _value === 'true';
break;

case 'uint':
valueError = validateUint(_value).valueError;
break;
Expand All @@ -278,13 +275,12 @@ class ExecuteContract extends Component {
}

estimateGas = (_fromAddress) => {
const { api } = this.context;
const { fromAddress } = this.props;
const { amount, func, values } = this.state;
const options = {
gas: MAX_GAS_ESTIMATION,
from: _fromAddress || fromAddress,
value: api.util.toWei(amount || 0)
value: toWei(amount || 0)
};

if (!func) {
Expand Down
69 changes: 69 additions & 0 deletions js/src/modals/ExecuteContract/executeContract.spec.js
@@ -0,0 +1,69 @@
// 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 from 'react';
import sinon from 'sinon';

import ExecuteContract from './';

import { CONTRACT, STORE } from './executeContract.test.js';

let component;
let onClose;
let onFromAddressChange;

function render (props) {
onClose = sinon.stub();
onFromAddressChange = sinon.stub();

component = shallow(
<ExecuteContract
{ ...props }
contract={ CONTRACT }
onClose={ onClose }
onFromAddressChange={ onFromAddressChange } />,
{ context: { api: {}, store: STORE } }
).find('ExecuteContract').shallow();

return component;
}

describe('modals/ExecuteContract/DetailsStep', () => {
it('renders', () => {
expect(render({ accounts: {} })).to.be.ok;
});

describe('instance functions', () => {
beforeEach(() => {
render({
accounts: {}
});
});

describe('onValueChange', () => {
it('toggles boolean from false to true', () => {
component.setState({
func: CONTRACT.functions[0],
values: [false]
});
component.instance().onValueChange(null, 0, true);

expect(component.state().values).to.deep.equal([true]);
});
});
});
});
64 changes: 64 additions & 0 deletions js/src/modals/ExecuteContract/executeContract.test.js
@@ -0,0 +1,64 @@
// 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 sinon from 'sinon';

const CONTRACT = {
functions: [
{
name: 'test_a',
signature: 'test_a',
estimateGas: sinon.stub().resolves(new BigNumber(123)),
inputs: [
{
name: 'test_bool',
kind: {
type: 'bool'
}
}
],
abi: {
inputs: [
{
name: 'test_bool',
type: 'bool'
}
]
}
}
]
};

const STORE = {
dispatch: sinon.stub(),
subscribe: sinon.stub(),
getState: () => {
return {
balances: {
balances: {}
},
nodeStatus: {
gasLimit: new BigNumber(123)
}
};
}
};

export {
CONTRACT,
STORE
};
14 changes: 7 additions & 7 deletions js/src/ui/Form/Select/select.js
Expand Up @@ -46,26 +46,26 @@ export default class Select extends Component {
}

render () {
const { disabled, error, label, hint, value, children, className, onBlur, onChange, onKeyDown } = this.props;
const { children, className, disabled, error, hint, label, onBlur, onChange, onKeyDown, value } = this.props;

return (
<SelectField
className={ className }
autoComplete='off'
className={ className }
disabled={ disabled }
errorText={ error }
floatingLabelFixed
floatingLabelText={ label }
fullWidth
hintText={ hint }
name={ NAME_ID }
id={ NAME_ID }
underlineDisabledStyle={ UNDERLINE_DISABLED }
underlineStyle={ UNDERLINE_NORMAL }
value={ value }
name={ NAME_ID }
onBlur={ onBlur }
onChange={ onChange }
onKeyDown={ onKeyDown }>
onKeyDown={ onKeyDown }
underlineDisabledStyle={ UNDERLINE_DISABLED }
underlineStyle={ UNDERLINE_NORMAL }
value={ value }>
{ children }
</SelectField>
);
Expand Down