parent
e19f89f162
commit
86df54067f
4 changed files with 168 additions and 0 deletions
@ -0,0 +1,60 @@ |
|||||||
|
import './properties-form.scss'; |
||||||
|
import { h, Component } from 'preact'; |
||||||
|
|
||||||
|
class PropertiesForm extends Component { |
||||||
|
|
||||||
|
render() { |
||||||
|
let types = this.props.types; |
||||||
|
let value = this.props.value; |
||||||
|
if (!value) { |
||||||
|
value = {}; |
||||||
|
} |
||||||
|
|
||||||
|
return <div className='form-properties-form'> |
||||||
|
{ |
||||||
|
Object.keys(types).map((name) => { |
||||||
|
let type = types[name]; |
||||||
|
let inputType = null; |
||||||
|
if (type === 'string') { |
||||||
|
inputType = 'text'; |
||||||
|
} else if (type === 'number') { |
||||||
|
inputType = 'number'; |
||||||
|
} else if (type === 'boolean') { |
||||||
|
inputType = 'checkbox'; |
||||||
|
} |
||||||
|
return <div key={name} className='form-properties-form-row'> |
||||||
|
<label> |
||||||
|
<span className='column-name'>{name}</span> |
||||||
|
<input type={inputType} name={name} |
||||||
|
className='column-input' |
||||||
|
value={value[name] ? value[name] : ''} |
||||||
|
onChange={this.bindValue.bind(this)} |
||||||
|
checked={value[name]} |
||||||
|
/> |
||||||
|
</label> |
||||||
|
</div>; |
||||||
|
}) |
||||||
|
} |
||||||
|
</div>; |
||||||
|
} |
||||||
|
|
||||||
|
bindValue(e) { |
||||||
|
if (!this.props.onChange) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
let name = e.target.name; |
||||||
|
let next = Object.assign({}, this.props.value); |
||||||
|
if (e.target.type.toLowerCase() === 'checkbox') { |
||||||
|
next[name] = e.target.checked; |
||||||
|
} else if (e.target.type.toLowerCase() === 'number') { |
||||||
|
next[name] = Number(e.target.value); |
||||||
|
} else { |
||||||
|
next[name] = e.target.value; |
||||||
|
} |
||||||
|
|
||||||
|
this.props.onChange(next); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
export default PropertiesForm; |
@ -0,0 +1,12 @@ |
|||||||
|
.form-properties-form { |
||||||
|
&-row { |
||||||
|
.column-name { |
||||||
|
display: inline-block; |
||||||
|
min-width: 5rem; |
||||||
|
font-weight: bold; |
||||||
|
} |
||||||
|
.column-input { |
||||||
|
line-height: 2.2rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,86 @@ |
|||||||
|
import { expect } from 'chai'; |
||||||
|
import { h, render } from 'preact'; |
||||||
|
import PropertiesForm from 'settings/components/form/properties-form' |
||||||
|
|
||||||
|
describe("settings/form/PropertiesForm", () => { |
||||||
|
beforeEach(() => { |
||||||
|
document.body.innerHTML = ''; |
||||||
|
}); |
||||||
|
|
||||||
|
describe('render', () => { |
||||||
|
it('renders PropertiesForm', () => { |
||||||
|
let types = { |
||||||
|
mystr: 'string', |
||||||
|
mynum: 'number', |
||||||
|
mybool: 'boolean', |
||||||
|
empty: 'string', |
||||||
|
} |
||||||
|
let value = { |
||||||
|
mystr: 'abc', |
||||||
|
mynum: 123, |
||||||
|
mybool: true, |
||||||
|
}; |
||||||
|
render(<PropertiesForm types={types} value={value} />, document.body); |
||||||
|
|
||||||
|
let strInput = document.querySelector('input[name=mystr]'); |
||||||
|
let numInput = document.querySelector('input[name=mynum]'); |
||||||
|
let boolInput = document.querySelector('input[name=mybool]'); |
||||||
|
let emptyInput = document.querySelector('input[name=empty]'); |
||||||
|
|
||||||
|
expect(strInput.type).to.equals('text'); |
||||||
|
expect(strInput.value).to.equal('abc'); |
||||||
|
expect(numInput.type).to.equals('number'); |
||||||
|
expect(numInput.value).to.equal('123'); |
||||||
|
expect(boolInput.type).to.equals('checkbox'); |
||||||
|
expect(boolInput.checked).to.be.true; |
||||||
|
expect(emptyInput.type).to.equals('text'); |
||||||
|
expect(emptyInput.value).to.be.empty; |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
describe('onChange', () => { |
||||||
|
it('invokes onChange event on text changed', (done) => { |
||||||
|
render(<PropertiesForm |
||||||
|
types={{ 'myvalue': 'string' }} |
||||||
|
value={{ 'myvalue': 'abc' }} |
||||||
|
onChange={value => { |
||||||
|
expect(value).to.have.property('myvalue', 'abcd'); |
||||||
|
done(); |
||||||
|
}} |
||||||
|
/>, document.body); |
||||||
|
|
||||||
|
let input = document.querySelector('input[name=myvalue]'); |
||||||
|
input.value = 'abcd' |
||||||
|
input.dispatchEvent(new Event('change')) |
||||||
|
}); |
||||||
|
|
||||||
|
it('invokes onChange event on number changeed', (done) => { |
||||||
|
render(<PropertiesForm |
||||||
|
types={{ 'myvalue': 'number' }} |
||||||
|
value={{ '': 123 }} |
||||||
|
onChange={value => { |
||||||
|
expect(value).to.have.property('myvalue', 1234); |
||||||
|
done(); |
||||||
|
}} |
||||||
|
/>, document.body); |
||||||
|
|
||||||
|
let input = document.querySelector('input[name=myvalue]'); |
||||||
|
input.value = '1234' |
||||||
|
input.dispatchEvent(new Event('change')) |
||||||
|
}); |
||||||
|
|
||||||
|
it('invokes onChange event on checkbox changed', (done) => { |
||||||
|
render(<PropertiesForm |
||||||
|
types={{ 'myvalue': 'boolean' }} |
||||||
|
value={{ 'myvalue': false }} |
||||||
|
onChange={value => { |
||||||
|
expect(value).to.have.property('myvalue', true); |
||||||
|
done(); |
||||||
|
}} |
||||||
|
/>, document.body); |
||||||
|
|
||||||
|
let input = document.querySelector('input[name=myvalue]'); |
||||||
|
input.click(); |
||||||
|
}); |
||||||
|
}); |
||||||
|
}); |
Reference in new issue