Skip to content

Commit

Permalink
[fixed] Breadcrumb and BreadcrumbItem components
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexKVal committed Sep 25, 2015
1 parent 3c710f9 commit 28750e6
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 147 deletions.
6 changes: 2 additions & 4 deletions docs/src/ComponentsPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -550,9 +550,7 @@ const ComponentsPage = React.createClass({
<ReactPlayground codeText={Samples.Breadcrumb} />

<h3><Anchor id="breadcrumbs-props">Props</Anchor></h3>

<h4><Anchor id="breadcrumbs-props-breadcrumb">Breadcrumb</Anchor></h4>
<PropTable component="Breadcrumb"/>
<p><code>Breadcrumb</code> component itself doesn't have any specific public properties</p>

<h4><Anchor id="breadcrumbs-props-breadcrumbItem">BreadcrumbItem</Anchor></h4>
<PropTable component="BreadcrumbItem"/>
Expand Down Expand Up @@ -964,7 +962,7 @@ const ComponentsPage = React.createClass({
<NavItem href="#progress" key={8}>Progress bars</NavItem>
<NavItem href="#navs" key={9}>Navs</NavItem>
<NavItem href="#navbars" key={10}>Navbars</NavItem>
<NavItem href="#breadcrumbs" key={29}>Breadcrumbs</NavItem>
<NavItem href="#breadcrumbs" key={30}>Breadcrumbs</NavItem>
<NavItem href="#tabs" key={11}>Tabs</NavItem>
<NavItem href="#pager" key={12}>Pager</NavItem>
<NavItem href="#pagination" key={13}>Pagination</NavItem>
Expand Down
24 changes: 13 additions & 11 deletions src/Breadcrumb.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import React, { cloneElement } from 'react';
import classNames from 'classnames';
import BootstrapMixin from './BootstrapMixin';
import ValidComponentChildren from './utils/ValidComponentChildren';

const Breadcrumb = React.createClass({
mixins: [BootstrapMixin],
propTypes: {
/**
* bootstrap className
* @private
*/
bsClass: React.PropTypes.string
},

getDefaultProps() {
return {
Expand All @@ -13,24 +18,21 @@ const Breadcrumb = React.createClass({
},

render() {
const classes = this.getBsClassSet();
const { className, ...props } = this.props;

return (
<ol {...props} role="navigation" aria-label="breadcrumbs" className={classNames(className, classes)}>
<ol
{...props}
role="navigation"
aria-label="breadcrumbs"
className={classNames(className, this.props.bsClass)}>
{ValidComponentChildren.map(this.props.children, this.renderBreadcrumbItem)}
</ol>
);
},

renderBreadcrumbItem(child, index) {
return cloneElement(
child,
{
key: child.key ? child.key : index,
navItem: true
}
);
return cloneElement( child, { key: child.key ? child.key : index } );
}
});

Expand Down
46 changes: 28 additions & 18 deletions src/BreadcrumbItem.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,59 @@
import React from 'react';
import classNames from 'classnames';
import BootstrapMixin from './BootstrapMixin';
import SafeAnchor from './SafeAnchor';
import warning from 'react/lib/warning';

const BreadcrumbItem = React.createClass({
mixins: [BootstrapMixin],

propTypes: {
id: React.PropTypes.string,
active: React.PropTypes.bool,
linkId: React.PropTypes.string,
/**
* HTML id for the wrapper `li` element
*/
id: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.number
]),
/**
* HTML id for the inner `a` element
*/
linkId: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.number
]),
/**
* `href` attribute for the inner `a` element
*/
href: React.PropTypes.string,
/**
* `title` attribute for the inner `a` element
*/
title: React.PropTypes.node,
/**
* `target` attribute for the inner `a` element
*/
target: React.PropTypes.string
},

getDefaultProps() {
return {
active: false,
};
},

render() {
warning(!(this.props.href && this.props.active), '[react-bootstrap] href and active properties cannot be set at the same time');

const {
className,
id,
active,
linkId,
children,
href,
title,
target,
...props } = this.props;
const classes = { active };

const linkProps = {
href,
title,
target,
id: linkId
};

const active = href === undefined || href === null;

return (
<li id={id} className={classNames(props.className, classes)}>
<li id={id} className={classNames(className, { active })}>
{
active ?
<span {...props}>
Expand Down
1 change: 0 additions & 1 deletion src/styleMaps.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
const styleMaps = {
CLASSES: {
'alert': 'alert',
'breadcrumb': 'breadcrumb',
'button': 'btn',
'button-group': 'btn-group',
'button-toolbar': 'btn-toolbar',
Expand Down
79 changes: 42 additions & 37 deletions test/BreadcrumbItemSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,120 +2,125 @@ import React from 'react';
import ReactTestUtils from 'react/lib/ReactTestUtils';
import BreadcrumbItem from '../src/BreadcrumbItem';

describe('BreadcrumbItem', function () {
it('Should add active class', function () {
describe('BreadcrumbItem', () => {
it('Should not add `active` class with `href` attribute set', () => {
let instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem active>
Active Crumb
<BreadcrumbItem href='#'>
Crumb
</BreadcrumbItem>
);

assert.ok(ReactTestUtils.findRenderedDOMComponentWithClass(instance, 'active'));
let liNode = React.findDOMNode(instance);
assert.notInclude(liNode.className, 'active');
});

it('Should not add active class', function () {
it('Should render `a` as inner element when is not active', () => {
let instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem>
<BreadcrumbItem href='#'>
Crumb
</BreadcrumbItem>
);

let liNode = React.findDOMNode(instance);
assert.notInclude(liNode.className, 'active');
assert.ok(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a'));
});

it('Should add custom classes', function () {
it('Should add `active` class when `href` attribute is not set.', () => {
let instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem className="custom-one custom-two" active>
<BreadcrumbItem>
Active Crumb
</BreadcrumbItem>
);

let liNode = React.findDOMNode(ReactTestUtils.findRenderedDOMComponentWithClass(instance, 'active'));
assert.ok(ReactTestUtils.findRenderedDOMComponentWithClass(instance, 'active'));
});

let classes = liNode.className;
assert.include(classes, 'active');
assert.include(classes, 'custom-one');
assert.include(classes, 'custom-two');
it('Should render `span` as inner element when is active', () => {
let instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem>
Crumb
</BreadcrumbItem>
);

assert.ok(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'span'));
});

it('Should spread props onto an active item', function() {
it('Should add custom classes onto `li` wrapper element', () => {
let instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem herpa='derpa' active>
<BreadcrumbItem className="custom-one custom-two">
Active Crumb
</BreadcrumbItem>
);

let spanNode = ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'span');
let liNode = React.findDOMNode(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'li'));

spanNode.props.herpa.should.equal('derpa');
let classes = liNode.className;
assert.include(classes, 'custom-one');
assert.include(classes, 'custom-two');
});

it('Should spread props onto anchor', function(done) {
it('Should spread additional props onto inner element', (done) => {
const handleClick = () => {
done();
};

let instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem href='#' onClick={handleClick} herpa='derpa'>
Crumb 1
<BreadcrumbItem href='#' onClick={handleClick}>
Crumb
</BreadcrumbItem>
);

let anchorNode = ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a');
ReactTestUtils.Simulate.click(anchorNode);

anchorNode.props.herpa.should.equal('derpa');
});

it('Should add id for li element', function() {
it('Should apply id onto `li` wrapper element via `id` property', () => {
let instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem href='#' id='test-li-id'>
Crumb 1
Crumb
</BreadcrumbItem>
);

let liNode = React.findDOMNode(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'li'));
assert.equal(liNode.id, 'test-li-id');
});

it('Should add linkId', function() {
it('Should apply id onto `a` inner alement via `linkId` property', () => {
let instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem href='#' linkId='test-link-id'>
Crumb 1
Crumb
</BreadcrumbItem>
);

let linkNode = React.findDOMNode(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a'));
assert.equal(linkNode.id, 'test-link-id');
});

it('Should add href', function() {
it('Should apply `href` property onto `a` innder element', () => {
let instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem href='http://getbootstrap.com/components/#breadcrumbs'>
Crumb 1
Crumb
</BreadcrumbItem>
);

let linkNode = React.findDOMNode(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a'));
assert.equal(linkNode.href, 'http://getbootstrap.com/components/#breadcrumbs');
});

it('Should have a title', function() {
it('Should apply `title` property onto `a` innder element', () => {
let instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem title='test-title' href='http://getbootstrap.com/components/#breadcrumbs'>
Crumb 1
Crumb
</BreadcrumbItem>
);

let linkNode = React.findDOMNode(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a'));
assert.equal(linkNode.title, 'test-title');
});

it('Should not add anchor properties to li', function() {
it('Should not apply properties for inner `anchor` onto `li` wrapper element', () => {
let instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem title='test-title' href='/hi'>
Crumb 1
Crumb
</BreadcrumbItem>
);

Expand All @@ -124,10 +129,10 @@ describe('BreadcrumbItem', function () {
assert.notOk(liNode.hasAttribute('title'));
});

it('Should set target attribute on anchor', function () {
it('Should set `target` attribute on `anchor`', () => {
let instance = ReactTestUtils.renderIntoDocument(
<BreadcrumbItem target='_blank' href='http://getbootstrap.com/components/#breadcrumbs'>
Crumb 1
Crumb
</BreadcrumbItem>
);

Expand Down

0 comments on commit 28750e6

Please sign in to comment.