Skip to content

Commit

Permalink
feat(link): add prop for react router link
Browse files Browse the repository at this point in the history
  • Loading branch information
theetrain committed Aug 17, 2017
1 parent 05c88e8 commit b4e2e6d
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 20 deletions.
22 changes: 14 additions & 8 deletions src/components/Link/Link.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import React from 'react'
import PropTypes from 'prop-types'

import { Link as ReactRouterLink } from 'react-router-dom'

import ChevronLink from './ChevronLink/ChevronLink'
import ButtonLink from './ButtonLink/ButtonLink'
import safeRest from '../../safeRest'
import { warn } from '../../warn'

import styles from './Link.modules.scss'

Expand All @@ -14,26 +13,32 @@ const getClassName = invert => (invert ? styles.inverted : styles.base)
/**
* <span class="docs--badge green">new!</span> <span class="docs--badge purple">v0.21.0</span>
*/
const Link = ({ invert, children, ...rest }) => (
React.createElement(
rest.to ? ReactRouterLink : 'a',
const Link = ({ reactRouterLinkComponent, invert, children, ...rest }) => {
if (!(reactRouterLinkComponent && rest.to)) {
warn('Link', 'The props `reactRouterLinkComponent` and `to` must be used together.')
}
return React.createElement(
reactRouterLinkComponent || 'a',
{
...safeRest(rest),
className: getClassName(invert)
},
children
)
)
}
Link.propTypes = {
/**
* Target URL (if using 'reactRouterLinkComponent')
*/
to: PropTypes.string,
/**
* Target URL.
*/
href: PropTypes.string,
/**
* React router component.
* React Router Link component.
*/
router: PropTypes.element,
reactRouterLinkComponent: PropTypes.func,
/**
* Whether to invert the component styles.
*/
Expand All @@ -46,6 +51,7 @@ Link.propTypes = {
Link.defaultProps = {
to: null,
href: null,
reactRouterLinkComponent: null,
invert: false
}

Expand Down
4 changes: 4 additions & 0 deletions src/components/Link/Link.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@ const PurpleBlock = require('../__docs__/PurpleBlock').default;
<Link href="https://www.telus.com" invert>Go to TELUS.com</Link>
</PurpleBlock>
```

### React Router Links (for SPAs)

When using Link with React Router, you must pass in the React Router Link component as a prop.
33 changes: 21 additions & 12 deletions src/components/Link/__tests__/Link.spec.jsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import React from 'react'
import { shallow } from 'enzyme'
import toJson from 'enzyme-to-json'

import { MemoryRouter } from 'react-router-dom'
import { warn } from '../../../warn'

import Link from '../Link'

jest.mock('../../../warn', () => (
{ warn: jest.fn() }
))

describe('Link', () => {
const doShallow = (overrides = {}) => shallow(
<Link {...overrides}>Go home</Link>
)
const doShallowWithRouter = (overrides = {}) => shallow(
<MemoryRouter>
<Link {...overrides}>Go home</Link>
</MemoryRouter>
)

it('renders', () => {
const link = doShallow()
Expand All @@ -29,12 +27,23 @@ describe('Link', () => {
expect(link).toHaveProp('href', 'http://telus.com')
})

it('is a React Router Link when using the to attribute', () => {
const link = doShallowWithRouter({ to: '/about' })
it('renders a react router link element when passed as a prop', () => {
const MyLink = () => <span />
const link = doShallow({ reactRouterLinkComponent: MyLink })

expect(link).toMatchSelector('MyLink')
})

it('must use `reactRouterLinkComponent` and `to` props together', () => {
const MyLink = () => <span />
let link = doShallow({ reactRouterLinkComponent: MyLink })

expect(warn).toHaveBeenCalled()

link = doShallow({ to: '/about' })

const reactRouterLink = link.find('Router').dive().dive()
expect(reactRouterLink).toMatchSelector('Link')
expect(reactRouterLink).toHaveProp('to', '/about')
expect(link).toHaveProp('to')
expect(warn).toHaveBeenCalled()
})

it('can be inverted', () => {
Expand Down

0 comments on commit b4e2e6d

Please sign in to comment.