Add the accordion component + tests (fixes #170)

This commit is contained in:
Stuart Colville 2015-07-08 18:19:09 +01:00
Родитель 55ff8d379c
Коммит ce92cf7169
2 изменённых файлов: 168 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,101 @@
'use strict';
/*eslint react/no-multi-comp: 0 */
var React = require('react');
var cx = require('classnames');
var Accordion = React.createClass({
displayName: 'Accordion',
propTypes: {
children: React.PropTypes.array,
},
getInitialState: function() {
var sections = [];
React.Children.forEach(this.props.children, function() {
sections.push({isActive: false});
});
sections[0].isActive = true;
return {
sections: sections,
};
},
activate: function(sectionIdx, e) {
if (e.target.getAttribute('data-activate') !== null) {
e.preventDefault();
var sections = this.state.sections;
sections.forEach(function(section, idx) {
section.isActive = (sectionIdx === idx);
});
this.setState({sections: sections});
}
},
render: function() {
var that = this;
var children = React.Children.map(this.props.children, function(child, idx){
return React.cloneElement(child, {
activate: that.activate.bind(that, idx),
isActive: that.state.sections[idx].isActive,
});
});
return (
<div className="accordion" ref="accordion">
{children}
</div>
);
},
});
var AccordionSection = React.createClass({
displayName: 'AccordionSection',
propTypes: {
activate: React.PropTypes.function,
children: React.PropTypes.array,
isActive: React.PropTypes.bool,
},
render: function() {
var classes = cx(
'ac-section', {'active': this.props.isActive});
return (
<section onClick={this.props.activate}
className={classes}>
{this.props.children}
</section>
);
},
});
var AccordionContent = React.createClass({
displayName: 'AccordionContent',
propTypes: {
children: React.PropTypes.array,
},
render: function() {
return (
<div className="ac-content">
{this.props.children}
</div>
);
},
});
module.exports = {
Accordion: Accordion,
AccordionContent: AccordionContent,
AccordionSection: AccordionSection,
};

67
tests/test.accordion.jsx Normal file
Просмотреть файл

@ -0,0 +1,67 @@
'use strict';
var React = require('react');
var TestUtils = require('react/lib/ReactTestUtils');
var helpers = require('./helpers');
var {Accordion,
AccordionContent,
AccordionSection} = require('components/accordion');
describe('Accordion', function() {
beforeEach(function() {
this.Accordion = TestUtils.renderIntoDocument(
<Accordion>
<AccordionSection>
<h2>Section 1</h2>
<button className="button1" data-activate>Click this</button>
<AccordionContent>
<p>Section 1 content</p>
</AccordionContent>
</AccordionSection>
<AccordionSection>
<h2>Section 2</h2>
<button className="button2" data-activate>Click this</button>
<AccordionContent>
<p>Section 2 content</p>
</AccordionContent>
</AccordionSection>
<AccordionSection>
<h2>Section 3</h2>
<button className="button3">Click this</button>
<p>Section 3 content</p>
</AccordionSection>
</Accordion>
);
});
it('should initialize with first section visible', function() {
var sections = helpers.findAllByClass(this.Accordion, 'ac-section');
assert.include(sections[0].getDOMNode().getAttribute('class'), 'active');
assert.notInclude(sections[1].getDOMNode().getAttribute('class'), 'active');
assert.notInclude(sections[2].getDOMNode().getAttribute('class'), 'active');
});
it('should show section 2 on click', function() {
var button2 = helpers.findByClass(this.Accordion, 'button2');
TestUtils.Simulate.click(button2.getDOMNode());
var sections = helpers.findAllByClass(this.Accordion, 'ac-section');
assert.notInclude(sections[0].getDOMNode().getAttribute('class'), 'active');
assert.include(sections[1].getDOMNode().getAttribute('class'), 'active');
assert.notInclude(sections[2].getDOMNode().getAttribute('class'), 'active');
});
it('clicking button in section3 should be a noop', function() {
var button3 = helpers.findByClass(this.Accordion, 'button3');
TestUtils.Simulate.click(button3.getDOMNode());
var sections = helpers.findAllByClass(this.Accordion, 'ac-section');
assert.include(sections[0].getDOMNode().getAttribute('class'), 'active');
assert.notInclude(sections[1].getDOMNode().getAttribute('class'), 'active');
assert.notInclude(sections[2].getDOMNode().getAttribute('class'), 'active');
});
});