-
Notifications
You must be signed in to change notification settings - Fork 516
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(priceRanges): Add BEM classes and tests
Fixes #387 BREAKING CHANGE: `ais-price-ranges--range` are now named `ais-price-ranges--item` and are wrapped in a `ais-price-ranges--list`. I've moved the bottom form into it's own PriceRangesForm component, along with its own tests. I've fixed a minor typo where the component was internally named PriceRange (without the final __s__). I factorize some logic form the render in individual methods and manage to individually test them. This was not an easy task. I had to mock the default `render` (so it does nothing) before instanciating the component. Then, I was able to call each inner method individually. This requires to stub prototype methods in beforeEach, then restore them in afterEach. I've added a few helper methods, this can surely be simplified again but this gives nice granularity in testing. I've renamed the `range` items to `item` and wrapped them in a `list`. I've also added classes to all elements we add (`label`, `separator`, etc). I've removed the empty `span`s.
- Loading branch information
1 parent
09e8f7f
commit ad58d7a
Showing
12 changed files
with
650 additions
and
273 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
This file was deleted.
Oops, something went wrong.
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,97 @@ | ||
var React = require('react'); | ||
|
||
var Template = require('../Template'); | ||
var PriceRangesForm = require('./PriceRangesForm'); | ||
var cx = require('classnames'); | ||
|
||
class PriceRanges extends React.Component { | ||
getForm() { | ||
return ( | ||
<PriceRangesForm | ||
cssClasses={this.props.cssClasses} | ||
labels={this.props.labels} | ||
refine={this.refine.bind(this)} | ||
/> | ||
); | ||
} | ||
|
||
getURLFromFacetValue(facetValue) { | ||
if (!this.props.createURL) { | ||
return '#'; | ||
} | ||
return this.props.createURL(facetValue.from, facetValue.to, facetValue.isRefined); | ||
} | ||
|
||
getItemFromFacetValue(facetValue) { | ||
let cssClassItem = cx( | ||
this.props.cssClasses.item, | ||
{[this.props.cssClasses.active]: facetValue.isRefined} | ||
); | ||
let url = this.getURLFromFacetValue(facetValue); | ||
let key = facetValue.from + '_' + facetValue.to; | ||
let handleClick = this.refine.bind(this, facetValue.from, facetValue.to); | ||
return ( | ||
<div className={cssClassItem} key={key}> | ||
<a | ||
className={this.props.cssClasses.link} | ||
href={url} | ||
onClick={handleClick} | ||
> | ||
<Template data={facetValue} templateKey="item" {...this.props.templateProps} /> | ||
</a> | ||
</div> | ||
); | ||
} | ||
|
||
refine(from, to, event) { | ||
event.preventDefault(); | ||
this.setState({ | ||
formFromValue: null, | ||
formToValue: null | ||
}); | ||
this.props.refine(from, to); | ||
} | ||
|
||
render() { | ||
let form = this.getForm(); | ||
return ( | ||
<div> | ||
<div className={this.props.cssClasses.list}> | ||
{this.props.facetValues.map(facetValue => { | ||
return this.getItemFromFacetValue(facetValue); | ||
})} | ||
</div> | ||
{form} | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
PriceRanges.propTypes = { | ||
createURL: React.PropTypes.func.isRequired, | ||
cssClasses: React.PropTypes.shape({ | ||
active: React.PropTypes.string, | ||
button: React.PropTypes.string, | ||
form: React.PropTypes.string, | ||
input: React.PropTypes.string, | ||
item: React.PropTypes.string, | ||
label: React.PropTypes.string, | ||
link: React.PropTypes.string, | ||
list: React.PropTypes.string, | ||
separator: React.PropTypes.string | ||
}), | ||
facetValues: React.PropTypes.array, | ||
labels: React.PropTypes.shape({ | ||
button: React.PropTypes.string, | ||
currency: React.PropTypes.string, | ||
to: React.PropTypes.string | ||
}), | ||
refine: React.PropTypes.func.isRequired, | ||
templateProps: React.PropTypes.object.isRequired | ||
}; | ||
|
||
PriceRanges.defaultProps = { | ||
cssClasses: {} | ||
}; | ||
|
||
module.exports = PriceRanges; |
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,59 @@ | ||
var React = require('react'); | ||
|
||
class PriceRangesForm extends React.Component { | ||
getInput(type) { | ||
return ( | ||
<label className={this.props.cssClasses.label}> | ||
<span className={this.props.cssClasses.currency}>{this.props.labels.currency} </span> | ||
<input className={this.props.cssClasses.input} ref={type} type="number" /> | ||
</label> | ||
); | ||
} | ||
|
||
handleSubmit(event) { | ||
let from = +this.refs.from.value || undefined; | ||
let to = +this.refs.to.value || undefined; | ||
this.props.refine(from, to, event); | ||
} | ||
|
||
render() { | ||
let fromInput = this.getInput('from'); | ||
let toInput = this.getInput('to'); | ||
let onSubmit = this.handleSubmit.bind(this); | ||
return ( | ||
<form className={this.props.cssClasses.form} onSubmit={onSubmit} ref="form"> | ||
{fromInput} | ||
<span className={this.props.cssClasses.separator}> {this.props.labels.separator} </span> | ||
{toInput} | ||
<button className={this.props.cssClasses.button} type="submit">{this.props.labels.button}</button> | ||
</form> | ||
); | ||
} | ||
} | ||
|
||
PriceRangesForm.propTypes = { | ||
cssClasses: React.PropTypes.shape({ | ||
button: React.PropTypes.string, | ||
currency: React.PropTypes.string, | ||
form: React.PropTypes.string, | ||
input: React.PropTypes.string, | ||
label: React.PropTypes.string, | ||
separator: React.PropTypes.string | ||
}), | ||
labels: React.PropTypes.shape({ | ||
button: React.PropTypes.string, | ||
currency: React.PropTypes.string, | ||
separator: React.PropTypes.string | ||
}), | ||
refine: React.PropTypes.func.isRequired | ||
}; | ||
|
||
|
||
PriceRangesForm.defaultProps = { | ||
cssClasses: {}, | ||
labels: {} | ||
}; | ||
|
||
|
||
module.exports = PriceRangesForm; | ||
|
Oops, something went wrong.