-
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(menu-select): add menu select widget (#2316)
* feat(widgets): add menuSelect widget * feat(dev): add example menuSelect * doc(menu): minor fixes * doc(menuSelect): write documentation about menuSelect widget * feat(connectMenu): falsy values remove filter * refactor(MenuSelect): use falsy value to remove refined value * test(menuSelect): test widget & component * fix(connectMenu): correctly cache returned `refine` fn * fix(MenuSelect): templatesProps * refactor(connectMenu): dont re-instanciate a fn at every render * refactor(connectMenu): rename to `this._refine`
- Loading branch information
Maxime Janton
authored and
Alex S
committed
Sep 20, 2017
1 parent
89da104
commit 680f9bd
Showing
11 changed files
with
490 additions
and
3 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 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,53 @@ | ||
import React, { Component } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
|
||
import Template from './Template'; | ||
import autoHideContainerHOC from '../decorators/autoHideContainer.js'; | ||
import headerFooterHOC from '../decorators/headerFooter.js'; | ||
|
||
class MenuSelect extends Component { | ||
static propTypes = { | ||
cssClasses: PropTypes.shape({ | ||
select: PropTypes.string, | ||
option: PropTypes.string, | ||
}), | ||
items: PropTypes.array.isRequired, | ||
refine: PropTypes.func.isRequired, | ||
templateProps: PropTypes.object.isRequired, | ||
}; | ||
|
||
handleSelectChange = ({ target: { value } }) => { | ||
this.props.refine(value); | ||
}; | ||
|
||
render() { | ||
const { cssClasses, templateProps, items } = this.props; | ||
const { value: selectedValue } = items.find(item => item.isRefined) || { | ||
value: '', | ||
}; | ||
|
||
return ( | ||
<select | ||
className={cssClasses.select} | ||
value={selectedValue} | ||
onChange={this.handleSelectChange} | ||
> | ||
<option value="" className={cssClasses.option}> | ||
<Template templateKey="seeAllOption" {...templateProps} /> | ||
</option> | ||
|
||
{items.map(item => | ||
<option | ||
key={item.value} | ||
value={item.value} | ||
className={cssClasses.option} | ||
> | ||
<Template data={item} templateKey="item" {...templateProps} /> | ||
</option> | ||
)} | ||
</select> | ||
); | ||
} | ||
} | ||
|
||
export default autoHideContainerHOC(headerFooterHOC(MenuSelect)); |
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,33 @@ | ||
import React from 'react'; | ||
import MenuSelect from '../MenuSelect'; | ||
import renderer from 'react-test-renderer'; | ||
|
||
import defaultTemplates from '../../widgets/menu-select/defaultTemplates'; | ||
|
||
describe('MenuSelect', () => { | ||
it('should render <MenuSelect /> with items', () => { | ||
const props = { | ||
items: [{ value: 'foo', label: 'foo' }, { value: 'bar', label: 'bar' }], | ||
refine: () => {}, | ||
templateProps: { templates: defaultTemplates }, | ||
shouldAutoHideContainer: false, | ||
}; | ||
const tree = renderer.create(<MenuSelect {...props} />).toJSON(); | ||
expect(tree).toMatchSnapshot(); | ||
}); | ||
|
||
it('should render with custom css classes', () => { | ||
const props = { | ||
items: [{ value: 'foo', label: 'foo' }, { value: 'bar', label: 'bar' }], | ||
refine: () => {}, | ||
templateProps: { templates: defaultTemplates }, | ||
shouldAutoHideContainer: false, | ||
cssClasses: { | ||
select: 'foo', | ||
option: 'bar', | ||
}, | ||
}; | ||
const tree = renderer.create(<MenuSelect {...props} />).toJSON(); | ||
expect(tree).toMatchSnapshot(); | ||
}); | ||
}); |
123 changes: 123 additions & 0 deletions
123
src/components/__tests__/__snapshots__/MenuSelect-test.js.snap
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,123 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`MenuSelect should render <MenuSelect /> with items 1`] = ` | ||
<div | ||
style={ | ||
Object { | ||
"display": "", | ||
} | ||
} | ||
> | ||
<div | ||
className="ais-root" | ||
> | ||
<div | ||
className="ais-body" | ||
> | ||
<select | ||
className={undefined} | ||
onChange={[Function]} | ||
value="" | ||
> | ||
<option | ||
className={undefined} | ||
value="" | ||
> | ||
<div | ||
dangerouslySetInnerHTML={ | ||
Object { | ||
"__html": "See all", | ||
} | ||
} | ||
/> | ||
</option> | ||
<option | ||
className={undefined} | ||
value="foo" | ||
> | ||
<div | ||
dangerouslySetInnerHTML={ | ||
Object { | ||
"__html": "foo ()", | ||
} | ||
} | ||
/> | ||
</option> | ||
<option | ||
className={undefined} | ||
value="bar" | ||
> | ||
<div | ||
dangerouslySetInnerHTML={ | ||
Object { | ||
"__html": "bar ()", | ||
} | ||
} | ||
/> | ||
</option> | ||
</select> | ||
</div> | ||
</div> | ||
</div> | ||
`; | ||
|
||
exports[`MenuSelect should render with custom css classes 1`] = ` | ||
<div | ||
style={ | ||
Object { | ||
"display": "", | ||
} | ||
} | ||
> | ||
<div | ||
className="ais-root" | ||
> | ||
<div | ||
className="ais-body" | ||
> | ||
<select | ||
className="foo" | ||
onChange={[Function]} | ||
value="" | ||
> | ||
<option | ||
className="bar" | ||
value="" | ||
> | ||
<div | ||
dangerouslySetInnerHTML={ | ||
Object { | ||
"__html": "See all", | ||
} | ||
} | ||
/> | ||
</option> | ||
<option | ||
className="bar" | ||
value="foo" | ||
> | ||
<div | ||
dangerouslySetInnerHTML={ | ||
Object { | ||
"__html": "foo ()", | ||
} | ||
} | ||
/> | ||
</option> | ||
<option | ||
className="bar" | ||
value="bar" | ||
> | ||
<div | ||
dangerouslySetInnerHTML={ | ||
Object { | ||
"__html": "bar ()", | ||
} | ||
} | ||
/> | ||
</option> | ||
</select> | ||
</div> | ||
</div> | ||
</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
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
48 changes: 48 additions & 0 deletions
48
src/widgets/menu-select/__tests__/__snapshots__/menu-select-test.js.snap
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,48 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`menuSelect render correctly 1`] = ` | ||
<HeaderFooter-AutoHide | ||
canRefine={true} | ||
cssClasses={ | ||
Object { | ||
"footer": "ais-menu-select--footer", | ||
"header": "ais-menu-select--header", | ||
"option": "ais-menu-select--option", | ||
"root": "ais-menu-select", | ||
"select": "ais-menu-select--footer", | ||
} | ||
} | ||
items={ | ||
Array [ | ||
Object { | ||
"label": "foo", | ||
"value": undefined, | ||
}, | ||
Object { | ||
"label": "bar", | ||
"value": undefined, | ||
}, | ||
] | ||
} | ||
refine={[Function]} | ||
shouldAutoHideContainer={false} | ||
templateProps={ | ||
Object { | ||
"templates": Object { | ||
"footer": "", | ||
"header": "", | ||
"item": "{{label}} ({{#helpers.formatNumber}}{{count}}{{/helpers.formatNumber}})", | ||
"seeAllOption": "See all", | ||
}, | ||
"templatesConfig": undefined, | ||
"transformData": undefined, | ||
"useCustomCompileOptions": Object { | ||
"footer": false, | ||
"header": false, | ||
"item": false, | ||
"seeAllOption": false, | ||
}, | ||
} | ||
} | ||
/> | ||
`; |
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 sinon from 'sinon'; | ||
|
||
import menuSelect from '../menu-select'; | ||
|
||
describe('menuSelect', () => { | ||
it('throws an exception when no attributeName', () => { | ||
const container = document.createElement('div'); | ||
expect(menuSelect.bind(null, { container })).toThrow(/^Usage/); | ||
}); | ||
|
||
it('throws an exception when no container', () => { | ||
const attributeName = 'categories'; | ||
expect(menuSelect.bind(null, { attributeName })).toThrow(/^Usage/); | ||
}); | ||
|
||
it('render correctly', () => { | ||
const data = { data: [{ name: 'foo' }, { name: 'bar' }] }; | ||
const results = { getFacetValues: sinon.spy(() => data) }; | ||
const state = { toggleRefinement: sinon.spy() }; | ||
const helper = { | ||
toggleRefinement: sinon.stub().returnsThis(), | ||
search: sinon.spy(), | ||
state, | ||
}; | ||
const createURL = () => '#'; | ||
const ReactDOM = { render: sinon.spy() }; | ||
menuSelect.__Rewire__('ReactDOM', ReactDOM); | ||
const widget = menuSelect({ | ||
container: document.createElement('div'), | ||
attributeName: 'test', | ||
}); | ||
const instantSearchInstance = { templatesConfig: undefined }; | ||
widget.init({ helper, createURL, instantSearchInstance }); | ||
widget.render({ results, createURL, state }); | ||
expect(ReactDOM.render.firstCall.args[0]).toMatchSnapshot(); | ||
menuSelect.__ResetDependency__('ReactDOM'); | ||
}); | ||
}); |
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,8 @@ | ||
/* eslint-disable max-len */ | ||
export default { | ||
header: '', | ||
item: | ||
'{{label}} ({{#helpers.formatNumber}}{{count}}{{/helpers.formatNumber}})', | ||
footer: '', | ||
seeAllOption: 'See all', | ||
}; |
Oops, something went wrong.