Skip to content

Commit 358885d

Browse files
authored
Merge pull request #134 from primer/underline-nav-fixes
UnderlineNav fixes
2 parents c9dd551 + 7f511ca commit 358885d

File tree

8 files changed

+2855
-2851
lines changed

8 files changed

+2855
-2851
lines changed

package-lock.json

Lines changed: 2824 additions & 2824 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/UnderlineNav.js

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import React from 'react'
22
import PropTypes from 'prop-types'
33
import classnames from 'classnames'
4-
import UnderlineNavLink from './UnderlineNavLink'
54
import {mapWhitespaceProps} from './props'
65

76
export const ITEM_CLASS = 'UnderlineNav-item no-underline'
@@ -13,25 +12,28 @@ export default function UnderlineNav(props) {
1312
const classes = classnames(className, 'UnderlineNav', align && `UnderlineNav--${align}`, full && 'UnderlineNav--full')
1413

1514
const mappedChildren = React.Children.map(children, child => {
16-
if (child.type === UnderlineNavLink) {
15+
if (child.type.displayName === 'UnderlineNavLink') {
1716
return child
1817
}
1918

20-
const {className = '', selected} = child.props
19+
let {className = ''} = child.props
2120
const newProps = {}
21+
2222
// add the ITEM_CLASS to all children without one
2323
if (!className || !className.includes(ITEM_CLASS)) {
24-
newProps.className = classnames(ITEM_CLASS, className)
24+
className = classnames(ITEM_CLASS, className)
2525
}
26-
if (selected === true && !className.includes(SELECTED_CLASS)) {
27-
newProps.className = classnames(newProps.className || className, SELECTED_CLASS)
26+
27+
if (child.props.selected === true && !className.includes(SELECTED_CLASS)) {
28+
className = classnames(className, SELECTED_CLASS)
2829
}
30+
2931
// if this is a react-router NavLink (duck typing!),
3032
// set activeClassName={SELECTED_CLASS}
3133
if (child.type.name === 'NavLink') {
3234
newProps.activeClassName = SELECTED_CLASS
3335
}
34-
return React.cloneElement(child, newProps)
36+
return React.cloneElement(child, {className, ...newProps})
3537
})
3638

3739
return (

src/UnderlineNavLink.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ export default function UnderlineNavLink(props) {
1616
)
1717
}
1818

19+
UnderlineNavLink.displayName = 'UnderlineNavLink'
20+
1921
UnderlineNavLink.defaultProps = {
2022
tag: 'a'
2123
}

src/__tests__/CircleBadge.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
/* eslint-disable jsx-a11y/alt-text */
22
import React from 'react'
33
import CircleBadge from '../CircleBadge'
4-
import {render, renderClasses, mount} from '../utils/testing'
5-
6-
const rendersClass = (node, klass) => renderClasses(node).includes(klass)
4+
import {render, rendersClass, mount} from '../utils/testing'
75

86
const imgOutput = <img className="CircleBadge-icon" alt="" src="primer.jpg" />
97
const imgInput = <img alt="" src="primer.jpg" />

src/__tests__/CircleOcticon.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react'
22
import CircleOcticon from '../CircleOcticon'
3-
import {render, renderClasses} from '../utils/testing'
3+
import {render, rendersClass} from '../utils/testing'
44
import {Check} from '@githubprimer/octicons-react'
55

66
describe('CircleOcticon', () => {
@@ -9,23 +9,23 @@ describe('CircleOcticon', () => {
99
})
1010

1111
it('adds the "circle" class', () => {
12-
expect(renderClasses(<CircleOcticon icon={Check} />).includes('circle')).toBe(true)
12+
expect(rendersClass(<CircleOcticon icon={Check} />, 'circle')).toBe(true)
1313
})
1414

1515
it('does not add a bg class by default', () => {
1616
expect(render(<CircleOcticon icon={Check} />).props.className).not.toMatch(/\bbg-/)
1717
})
1818

1919
it('adds the appropriate bg class for the "bg" prop', () => {
20-
expect(renderClasses(<CircleOcticon icon={Check} bg="red" />).includes('bg-red')).toBe(true)
20+
expect(rendersClass(<CircleOcticon icon={Check} bg="red" />, 'bg-red')).toBe(true)
2121
})
2222

2323
it('does not add a text class by default', () => {
2424
expect(render(<CircleOcticon icon={Check} />).props.className).not.toMatch(/\btext-/)
2525
})
2626

2727
it('adds the appropriate text class for the "color" prop', () => {
28-
expect(renderClasses(<CircleOcticon icon={Check} color="red" />).includes('text-red')).toBe(true)
28+
expect(rendersClass(<CircleOcticon icon={Check} color="red" />, 'text-red')).toBe(true)
2929
})
3030

3131
it('has a default size', () => {

src/__tests__/Tooltip.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react'
22
import Tooltip from '../Tooltip'
3-
import {render, renderClasses} from '../utils/testing'
3+
import {render, renderClasses, rendersClass} from '../utils/testing'
44

55
describe('Tooltip', () => {
66
it('renders a <span> with the "tooltipped" class', () => {
@@ -9,27 +9,27 @@ describe('Tooltip', () => {
99
})
1010

1111
it('respects the "align" prop', () => {
12-
expect(renderClasses(<Tooltip align="ne" />).includes('tooltipped-align-ne-2')).toBe(true)
13-
expect(renderClasses(<Tooltip align="se" />).includes('tooltipped-align-se-2')).toBe(true)
14-
expect(renderClasses(<Tooltip align="nw" />).includes('tooltipped-align-nw-2')).toBe(true)
15-
expect(renderClasses(<Tooltip align="sw" />).includes('tooltipped-align-sw-2')).toBe(true)
12+
expect(rendersClass(<Tooltip align="ne" />, 'tooltipped-align-ne-2')).toBe(true)
13+
expect(rendersClass(<Tooltip align="se" />, 'tooltipped-align-se-2')).toBe(true)
14+
expect(rendersClass(<Tooltip align="nw" />, 'tooltipped-align-nw-2')).toBe(true)
15+
expect(rendersClass(<Tooltip align="sw" />, 'tooltipped-align-sw-2')).toBe(true)
1616
})
1717

1818
it('respects the "direction" prop', () => {
1919
for (const direction of Tooltip.directions) {
20-
expect(renderClasses(<Tooltip direction={direction} />).includes(`tooltipped-${direction}`)).toBe(true)
20+
expect(rendersClass(<Tooltip direction={direction} />, `tooltipped-${direction}`)).toBe(true)
2121
}
2222
})
2323

2424
it('respects the "noDelay" prop', () => {
25-
expect(renderClasses(<Tooltip noDelay />).includes(`tooltipped-no-delay`)).toBe(true)
25+
expect(rendersClass(<Tooltip noDelay />, 'tooltipped-no-delay')).toBe(true)
2626
})
2727

2828
it('respects the "text" prop', () => {
2929
expect(render(<Tooltip text="hi" />).props['aria-label']).toEqual('hi')
3030
})
3131

3232
it('respects the "wrap" prop', () => {
33-
expect(renderClasses(<Tooltip wrap />).includes('tooltipped-multiline')).toBe(true)
33+
expect(rendersClass(<Tooltip wrap />, 'tooltipped-multiline')).toBe(true)
3434
})
3535
})

src/__tests__/UnderlineNav.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ import React from 'react'
22
import PropTypes from 'prop-types'
33
import UnderlineNav, {ITEM_CLASS, SELECTED_CLASS} from '../UnderlineNav'
44
import UnderlineNavLink from '../UnderlineNavLink'
5-
import {mount, render, renderClasses} from '../utils/testing'
6-
7-
const rendersClass = (node, klass) => renderClasses(node).includes(klass)
5+
import {mount, render, rendersClass} from '../utils/testing'
86

97
describe('Caret', () => {
108
it('renders a <nav>', () => {

src/utils/testing.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ import Adapter from 'enzyme-adapter-react-16'
44

55
enzyme.configure({adapter: new Adapter()})
66

7+
export function mount(component) {
8+
return enzyme.mount(component)
9+
}
10+
711
/**
812
* Render the component (a React.createElement() or JSX expression)
913
* into its intermediate object representation with 'type',
@@ -35,6 +39,6 @@ export function renderClasses(component) {
3539
return className ? className.trim().split(' ') : []
3640
}
3741

38-
export function mount(component) {
39-
return enzyme.mount(component)
42+
export function rendersClass(node, klass) {
43+
return renderClasses(node).includes(klass)
4044
}

0 commit comments

Comments
 (0)