Unverified Commit c408b0db by Jae Bradley Committed by GitHub

Merge pull request #67 from edx/hyperlink-component

Hyperlink Component
parents 24610182 4c9f71c9
...@@ -133,6 +133,54 @@ exports[`Storyshots Dropdown basic usage 1`] = ` ...@@ -133,6 +133,54 @@ exports[`Storyshots Dropdown basic usage 1`] = `
</div> </div>
`; `;
exports[`Storyshots HyperLink minimal usage 1`] = `
<a
href="https://en.wikipedia.org/wiki/Hyperlink"
onClick={[Function]}
target="_self"
>
edX.org
</a>
`;
exports[`Storyshots HyperLink with blank target 1`] = `
<a
href="https://www.edx.org"
onClick={[Function]}
target="_blank"
>
edX.org
<span>
<span
aria-hidden={false}
aria-label="Opens in a new window"
className="fa fa-external-link"
title="Opens in a new window"
/>
</span>
</a>
`;
exports[`Storyshots HyperLink with onClick 1`] = `
<a
href="https://www.edx.org"
onClick={[Function]}
target="_blank"
>
edX.org
<span>
<span
aria-hidden={false}
aria-label="Opens in a new window"
className="fa fa-external-link"
title="Opens in a new window"
/>
</span>
</a>
`;
exports[`Storyshots InputSelect basic usage 1`] = ` exports[`Storyshots InputSelect basic usage 1`] = `
<div <div
className="form-group" className="form-group"
......
{ {
"name": "@edx/paragon", "name": "@edx/paragon",
"version": "1.1.6", "version": "1.1.7",
"description": "Accessible, responsive UI component library based on Bootstrap.", "description": "Accessible, responsive UI component library based on Bootstrap.",
"main": "src/index.js", "main": "src/index.js",
"author": "arizzitano", "author": "arizzitano",
......
/* eslint-disable import/no-extraneous-dependencies, no-console */
import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { setConsoleOptions } from '@storybook/addon-console';
import Hyperlink from './index';
setConsoleOptions({
panelExclude: ['warn', 'error'],
});
const onClick = (event) => {
console.log(`onClick fired for ${event.target}`);
action('HyperLink Click');
};
storiesOf('HyperLink', module)
.add('minimal usage', () => (
<Hyperlink
destination={'https://en.wikipedia.org/wiki/Hyperlink'}
content={'edX.org'}
/>
))
.add('with blank target', () => (
<Hyperlink
destination={'https://www.edx.org'}
content={'edX.org'}
target={'_blank'}
/>
))
.add('with onClick', () => (
<Hyperlink
destination={'https://www.edx.org'}
content={'edX.org'}
target={'_blank'}
onClick={onClick}
/>
));
/* eslint-disable import/no-extraneous-dependencies */
import React from 'react';
import { shallow, mount } from 'enzyme';
import classNames from 'classnames';
import FontAwesomeStyles from 'font-awesome/css/font-awesome.min.css';
import Hyperlink from './index';
const content = 'content';
const destination = 'destination';
const onClick = () => {};
const props = {
content,
destination,
onClick,
};
const externalLinkAlternativeText = 'externalLinkAlternativeText';
const externalLinkTitle = 'externalLinktTitle';
const externalLinkProps = {
target: '_blank',
externalLinkAlternativeText,
externalLinkTitle,
...props,
};
describe('correct rendering', () => {
it('renders Hyperlink', () => {
const wrapper = shallow(<Hyperlink {...props} />);
expect(wrapper.type()).toEqual('a');
expect(wrapper).toHaveLength(1);
expect(wrapper.prop('children')).toEqual([content, undefined]);
expect(wrapper.prop('href')).toEqual(destination);
expect(wrapper.prop('target')).toEqual('_self');
expect(wrapper.prop('onClick')).toEqual(onClick);
expect(wrapper.find('span')).toHaveLength(0);
expect(wrapper.find('i')).toHaveLength(0);
});
it('renders external Hyperlink', () => {
const wrapper = mount(<Hyperlink {...externalLinkProps} />);
expect(wrapper.find('span')).toHaveLength(2);
const icon = wrapper.find('span').at(1);
expect(icon.prop('aria-hidden')).toEqual(false);
expect(icon.prop('className'))
.toEqual(classNames(FontAwesomeStyles.fa, FontAwesomeStyles['fa-external-link']));
expect(icon.prop('aria-label')).toEqual(externalLinkAlternativeText);
expect(icon.prop('title')).toEqual(externalLinkTitle);
});
});
describe('event handlers are triggered correctly', () => {
let spy;
beforeEach(() => { spy = jest.fn(); });
it('should fire onClick', () => {
const wrapper = mount(<Hyperlink {...props} onClick={spy} />);
expect(spy).toHaveBeenCalledTimes(0);
wrapper.simulate('click');
expect(spy).toHaveBeenCalledTimes(1);
});
});
import React from 'react';
import classNames from 'classnames';
import FontAwesomeStyles from 'font-awesome/css/font-awesome.min.css';
import PropTypes from 'prop-types';
import isRequiredIf from 'react-proptype-conditional-require';
function Hyperlink(props) {
const {
destination,
content,
target,
onClick,
externalLinkAlternativeText,
externalLinkTitle,
...other
} = props;
let externalLinkIcon;
if (target === '_blank') {
externalLinkIcon = (
// Space between content and icon
<span>{' '}
<span
className={classNames(FontAwesomeStyles.fa, FontAwesomeStyles['fa-external-link'])}
aria-hidden={false}
aria-label={externalLinkAlternativeText}
title={externalLinkTitle}
/>
</span>
);
}
return (
<a
href={destination}
target={target}
onClick={onClick}
{...other}
>{content}{externalLinkIcon}
</a>
);
}
Hyperlink.defaultProps = {
target: '_self',
onClick: () => {},
externalLinkAlternativeText: 'Opens in a new window',
externalLinkTitle: 'Opens in a new window',
};
Hyperlink.propTypes = {
destination: PropTypes.string.isRequired,
content: PropTypes.string.isRequired,
target: PropTypes.string,
onClick: PropTypes.func,
externalLinkAlternativeText: isRequiredIf(PropTypes.string, props => props.target === '_blank'),
externalLinkTitle: isRequiredIf(PropTypes.string, props => props.target === '_blank'),
};
export default Hyperlink;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment