forked from tarekskr/Dapp
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Includes refactoring of some components for clarity.
- Loading branch information
1 parent
5f60a28
commit de46d40
Showing
8 changed files
with
241 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,67 +1,37 @@ | ||
import { Form, Icon, Input, Tooltip } from 'antd'; | ||
import { Form, Input } from 'antd'; | ||
import React from 'react'; | ||
|
||
import store from '../../store'; | ||
|
||
const FormItem = Form.Item; | ||
|
||
const ethAddressValidator = (rule, value, callback) => { | ||
const web3 = store.getState().web3.web3Instance; | ||
|
||
if (!web3) { | ||
callback(); | ||
} else { | ||
callback(web3.isAddress(value) ? undefined : 'Invalid ETH address'); | ||
} | ||
}; | ||
|
||
const Hint = (props) => (<Tooltip title={props.hint} ><Icon type="question-circle-o" /></Tooltip>); | ||
|
||
const fieldSettingsByName = { | ||
marketContractAddress: { | ||
label: 'MARKET Contract Address', | ||
initialValue: '0x12345678123456781234567812345678', | ||
rules: [ | ||
{ | ||
required: true, message: 'Please enter MARKET contract address', | ||
}, | ||
{ | ||
validator: ethAddressValidator | ||
} | ||
], | ||
extra: 'Please enter deployed and whitelisted MARKET contract address', | ||
|
||
component: () => (<Input />) | ||
}, | ||
}; | ||
const getFieldSettings = (validators) => ({ | ||
rules: [ | ||
{ | ||
required: true, message: 'Please enter MARKET contract address', | ||
}, | ||
{ | ||
validator: validators.ethAddressValidator | ||
} | ||
] | ||
}); | ||
|
||
function FindContractField(props) { | ||
const { name, form, initialValue, showHint } = props; | ||
const { name, form, validators } = props; | ||
const { getFieldDecorator } = form; | ||
|
||
const fieldSettings = fieldSettingsByName[name]; | ||
const fieldSettings = getFieldSettings(validators); | ||
|
||
const rules = typeof fieldSettings.rules === 'function' ? fieldSettings.rules(form) : fieldSettings.rules; | ||
const label = (<span>{fieldSettings.label} {showHint && <Hint hint={fieldSettings.extra}/>}</span>); | ||
const rules = fieldSettings.rules; | ||
const label = 'MARKET Contract Address'; | ||
|
||
return ( | ||
<FormItem | ||
label={label} | ||
label={(<span>{label}</span>)} | ||
> | ||
|
||
{getFieldDecorator(name, { | ||
initialValue, | ||
rules, | ||
})( | ||
fieldSettings.component({ | ||
form, | ||
fieldSettings, | ||
showHint | ||
}) | ||
)} | ||
})(<Input />)} | ||
</FormItem> | ||
); | ||
} | ||
|
||
export const FieldSettings = fieldSettingsByName; | ||
export default FindContractField; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
export default function createFormValidators(web3) { | ||
return { | ||
ethAddressValidator(rule, value, callback) { | ||
if (!web3) { | ||
callback(); | ||
} else { | ||
callback(web3.isAddress(value) ? undefined : 'Invalid ETH address'); | ||
} | ||
} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import React from 'react'; | ||
import { mount } from 'enzyme'; | ||
|
||
import FindContractField from '../../../src/components/FindContract/FindContractField'; | ||
|
||
describe('FindContractField', () => { | ||
let name, form, validators; | ||
beforeEach(() => { | ||
name = 'marketContractAddress'; | ||
form = { | ||
getFieldDecorator(name, params) { | ||
return component => component; | ||
} | ||
}; | ||
validators = { | ||
ethAddressValidator(rule, value, callback) {} | ||
}; | ||
}); | ||
|
||
it('should render FindContractField successfully', () => { | ||
const props = { | ||
name, form, validators | ||
}; | ||
mount(<FindContractField {...props}/>); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,147 @@ | ||
import React from 'react'; | ||
import { Form } from 'antd'; | ||
import { List } from 'antd'; | ||
import { expect } from 'chai'; | ||
import { shallow } from 'enzyme'; | ||
import { mount } from 'enzyme'; | ||
import sinon from 'sinon'; | ||
|
||
import FindContractForm from '../../../src/components/FindContract/FindContractForm'; | ||
|
||
function validAddressFields() { | ||
return { | ||
marketContractAddress: { value: '0xf204a4ef082f5c04bb89f7d5e6568b796096735a' } | ||
}; | ||
} | ||
|
||
describe('FindContractForm', () => { | ||
let findContractForm; | ||
let wrappedFormRef; | ||
let onFindContractSpy; | ||
let successMessageSpy; | ||
let errorMessageSpy; | ||
|
||
beforeEach(() => { | ||
onFindContractSpy = sinon.spy(); | ||
errorMessageSpy = sinon.spy(); | ||
successMessageSpy = sinon.spy(); | ||
|
||
const props = { | ||
location: {}, | ||
onFindContract: onFindContractSpy | ||
contract: [], | ||
showErrorMessage: errorMessageSpy, | ||
showSuccessMessage: successMessageSpy, | ||
onFindContract: onFindContractSpy, | ||
validators: { ethAddressValidator: (rule, value, callback) => callback() }, | ||
wrappedComponentRef: (inst) => wrappedFormRef = inst | ||
}; | ||
findContractForm = shallow(<FindContractForm {...props}/>); | ||
findContractForm = mount(<FindContractForm {...props}/>); | ||
}); | ||
|
||
it('should findContract when props.onFindContract is invoked', () => { | ||
findContractForm.setProps({ | ||
marketContractAddress: { | ||
marketContractAddress: "0x12345678123456781234567812345678" | ||
marketContractAddress: '0x12345678123456781234567812345678' | ||
} | ||
}); | ||
findContractForm.props().onFindContract({}); | ||
expect(onFindContractSpy).to.have.property('callCount', 1); | ||
}); | ||
|
||
it('should not show List if contract is empty', () => { | ||
findContractForm.setProps({ | ||
contract: [] | ||
}); | ||
expect(findContractForm.find(List)).to.have.length(0); | ||
}); | ||
|
||
it('should show List if contract is not empty', () => { | ||
findContractForm.setProps({ | ||
contract: [{ | ||
name: 'key', | ||
value: '0x12345678123456781234567812345678' | ||
}] | ||
}); | ||
expect(findContractForm.find(List)).to.have.length(1); | ||
}); | ||
|
||
it('should enable submit button if component is not loading and no errors', () => { | ||
// no errors are set by default on the form | ||
findContractForm.setProps({ | ||
loading: false | ||
}); | ||
|
||
const submitButton = findContractForm.find('.submit-button').first(); | ||
expect(submitButton.prop('disabled')).to.equal(false); | ||
}); | ||
|
||
it('should disable submit button when loading', () => { | ||
findContractForm.setProps({ | ||
loading: true | ||
}); | ||
|
||
const submitButton = findContractForm.find('.submit-button').first(); | ||
|
||
expect(submitButton.prop('disabled')).to.equal(true); | ||
}); | ||
|
||
it('should disable submit if fields have errors', () => { | ||
wrappedFormRef.props.form.setFields({ marketContractAddress: { | ||
value: '', | ||
errors: [ new Error('Market Address is required.') ] | ||
} }); | ||
|
||
findContractForm.setProps({ | ||
loading: false | ||
}); | ||
|
||
const submitButton = findContractForm.find('.submit-button').first(); | ||
|
||
expect(submitButton.prop('disabled')).to.equal(true); | ||
}); | ||
|
||
it('should reset form when .reset-button is clicked', () => { | ||
const defaultFieldValues = wrappedFormRef.props.form.getFieldsValue(); | ||
wrappedFormRef.props.form.setFields(validAddressFields()); | ||
findContractForm.setProps({ | ||
loading: false | ||
}); | ||
|
||
const resetButton = findContractForm.find('.reset-button').first(); | ||
resetButton.simulate('click', { preventDefault() {} }); | ||
|
||
const valuesAfterReset = wrappedFormRef.props.form.getFieldsValue(); | ||
expect(valuesAfterReset).to.deep.equals(defaultFieldValues); | ||
}); | ||
|
||
it('should call onFindContract() with form values when submitted', () => { | ||
wrappedFormRef.props.form.setFields(validAddressFields()); | ||
|
||
findContractForm.find(Form).first().simulate('submit', { preventDefault() {} }); | ||
expect(onFindContractSpy).to.have.property('callCount', 1); | ||
}); | ||
|
||
it('should not call onFindContract() when form is invalid.', () => { | ||
wrappedFormRef.props.form.setFields({ marketContractAddress: { | ||
value: '', | ||
errors: [ new Error('Market Address is required.') ] | ||
} }); | ||
|
||
findContractForm.find(Form).first().simulate('submit', { preventDefault() {} }); | ||
expect(onFindContractSpy).to.have.property('callCount', 0); | ||
}); | ||
|
||
it('should showSuccessMessage when contract is found', () => { | ||
findContractForm.setProps({ error: null, loading: true, contract: [] }); | ||
expect(successMessageSpy).to.have.property('callCount', 0); | ||
findContractForm.setProps({ error: null, loading: false, contract: { | ||
key: '0x00000' | ||
} }); | ||
expect(successMessageSpy).to.have.property('callCount', 1); | ||
}); | ||
|
||
it('should showErrorMessage is error is set', () => { | ||
findContractForm.setProps({ error: null, loading: true}); | ||
expect(errorMessageSpy).to.have.property('callCount', 0); | ||
findContractForm.setProps({ error: 'Error occured', loading: false }); | ||
expect(errorMessageSpy).to.have.property('callCount', 1); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import React from 'react'; | ||
import ReactDOM from 'react-dom'; | ||
|
||
import FindContractSuccess from '../../../src/components/FindContract/FindContractSuccess'; | ||
|
||
describe('FindContractForm', () => { | ||
|
||
it('should render without crashing', () => { | ||
const div = document.createElement('div'); | ||
ReactDOM.render(<FindContractSuccess contract={{key: 'Key'}}/>, div); | ||
}); | ||
|
||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { expect } from 'chai'; | ||
import sinon from 'sinon'; | ||
|
||
import FormValidators from '../../../src/util/forms/Validators'; | ||
|
||
describe('FormValidators', () => { | ||
|
||
describe('ethAddressValidator', () => { | ||
it('should invoke callback() with no argument if web3 is not provided', () => { | ||
const callbackSpy = sinon.spy(); | ||
|
||
FormValidators().ethAddressValidator({}, '', callbackSpy); | ||
|
||
expect(callbackSpy).to.have.property('callCount', 1); | ||
expect(callbackSpy.getCall(0).args[0]).to.equal(undefined); // valid | ||
}); | ||
|
||
it('should invoke callback() with message if address is invalid', () => { | ||
const callbackSpy = sinon.spy(); | ||
const mockWeb3 = { isAddress: (any) => false }; | ||
|
||
FormValidators(mockWeb3).ethAddressValidator({}, '0xdf', callbackSpy); | ||
|
||
expect(callbackSpy).to.have.property('callCount', 1); | ||
expect(callbackSpy.getCall(0).args[0]).to.equal('Invalid ETH address'); // invalid | ||
}); | ||
|
||
it('should invoke callback() with no argument if address is valid', () => { | ||
const callbackSpy = sinon.spy(); | ||
const mockWeb3 = { isAddress: (any) => true }; | ||
|
||
FormValidators(mockWeb3).ethAddressValidator({}, '0x00003', callbackSpy); | ||
|
||
expect(callbackSpy).to.have.property('callCount', 1); | ||
expect(callbackSpy.getCall(0).args[0]).to.equal(undefined); // valid | ||
}); | ||
}); | ||
}); |