Skip to content

Commit

Permalink
fix(Accordion): Use empty SelectableContext to prevent dropdown from …
Browse files Browse the repository at this point in the history
…closing accordion (#5201)
  • Loading branch information
kyletsang committed Aug 12, 2020
1 parent e5a1833 commit 62a9d8b
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 4 deletions.
11 changes: 8 additions & 3 deletions src/AccordionCollapse.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import PropTypes from 'prop-types';

import Collapse, { CollapseProps } from './Collapse';
import AccordionContext from './AccordionContext';
import SelectableContext from './SelectableContext';
import { BsPrefixRefForwardingComponent } from './helpers';

export interface AccordionCollapseProps
Expand All @@ -29,10 +30,14 @@ const AccordionCollapse: AccordionCollapse = React.forwardRef<typeof Collapse>(
({ children, eventKey, ...props }: AccordionCollapseProps, ref) => {
const contextEventKey = useContext(AccordionContext);

// Empty SelectableContext is to prevent elements in the collapse
// from collapsing the accordion when clicked.
return (
<Collapse ref={ref} in={contextEventKey === eventKey} {...props}>
<div>{React.Children.only(children)}</div>
</Collapse>
<SelectableContext.Provider value={null}>
<Collapse ref={ref} in={contextEventKey === eventKey} {...props}>
<div>{React.Children.only(children)}</div>
</Collapse>
</SelectableContext.Provider>
);
},
) as any;
Expand Down
92 changes: 92 additions & 0 deletions test/AccordionSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import { mount } from 'enzyme';

import Accordion from '../src/Accordion';
import Card from '../src/Card';
import Dropdown from '../src/Dropdown';
import ListGroup from '../src/ListGroup';
import Nav from '../src/Nav';

describe('<Accordion>', () => {
it('should output a div', () => {
Expand Down Expand Up @@ -73,4 +76,93 @@ describe('<Accordion>', () => {
// https://testing-library.com/docs/dom-testing-library/api-async#waitforelement
collapses.at(1).getDOMNode().className.should.include('collapsing');
});

// https://github.com/react-bootstrap/react-bootstrap/issues/4176
it('Should not close accordion when child dropdown clicked', () => {
const wrapper = mount(
<Accordion defaultActiveKey="0">
<Card>
<Card.Header>
<Accordion.Toggle eventKey="0" />
</Card.Header>
<Accordion.Collapse eventKey="0">
<Card.Body>
<Dropdown show>
<Dropdown.Toggle id="dropdown-test">
Dropdown Button
</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Item href="#">Action</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
</Card.Body>
</Accordion.Collapse>
</Card>
</Accordion>,
);

wrapper.find('DropdownItem').simulate('click');

wrapper
.find('AccordionCollapse')
.at(0)
.getDOMNode()
.className.should.include('show');
});

it('Should not close accordion when child ListGroup clicked', () => {
const wrapper = mount(
<Accordion defaultActiveKey="0">
<Card>
<Card.Header>
<Accordion.Toggle eventKey="0" />
</Card.Header>
<Accordion.Collapse eventKey="0">
<div>
<ListGroup defaultActiveKey="#link1">
<ListGroup.Item action href="#link1">
Link 1
</ListGroup.Item>
</ListGroup>
</div>
</Accordion.Collapse>
</Card>
</Accordion>,
);

wrapper.find('ListGroupItem').simulate('click');

wrapper
.find('AccordionCollapse')
.at(0)
.getDOMNode()
.className.should.include('show');
});

it('Should not close accordion when child Nav clicked', () => {
const wrapper = mount(
<Accordion defaultActiveKey="0">
<Card>
<Card.Header>
<Accordion.Toggle eventKey="0" />
</Card.Header>
<Accordion.Collapse eventKey="0">
<Nav activeKey="/home">
<Nav.Item>
<Nav.Link href="#">Active</Nav.Link>
</Nav.Item>
</Nav>
</Accordion.Collapse>
</Card>
</Accordion>,
);

wrapper.find('NavLink').simulate('click');

wrapper
.find('AccordionCollapse')
.at(0)
.getDOMNode()
.className.should.include('show');
});
});
19 changes: 18 additions & 1 deletion test/NavSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React from 'react';
import Card from '../src/Card';
import Nav from '../src/Nav';
import Navbar from '../src/Navbar';
import NavDropdown from '../src/NavDropdown';
import { shouldWarn } from './helpers';

describe('<Nav>', () => {
Expand Down Expand Up @@ -84,7 +85,7 @@ describe('<Nav>', () => {
).assertSingle('div.card-header-pills');
});

it('should call on select when item is selected', (done) => {
it('should call onSelect when a Nav.Link is selected', (done) => {
function handleSelect(key) {
assert.equal(key, '2');
done();
Expand All @@ -103,6 +104,22 @@ describe('<Nav>', () => {
.simulate('click');
});

it('should call onSelect when a NavDropdown.Item is selected', () => {
const onSelectSpy = sinon.spy();

mount(
<Nav onSelect={onSelectSpy}>
<NavDropdown title="Dropdown" id="nav-dropdown-test" renderMenuOnMount>
<NavDropdown.Item eventKey={1}>Dropdown item</NavDropdown.Item>
</NavDropdown>
</Nav>,
)
.find('DropdownItem')
.simulate('click');

onSelectSpy.should.have.been.calledOnce;
});

it('should set the correct item active by href', () => {
mount(
<Nav defaultActiveKey="#item1">
Expand Down

0 comments on commit 62a9d8b

Please sign in to comment.