Created ShortUrlsRow test

This commit is contained in:
Alejandro Celaya 2019-01-13 09:49:02 +01:00
parent 1aa1d29d97
commit 30b4cb4068
7 changed files with 120 additions and 18 deletions

View file

@ -14,7 +14,7 @@ import './ShortUrlsList.scss';
const SORTABLE_FIELDS = { const SORTABLE_FIELDS = {
dateCreated: 'Created at', dateCreated: 'Created at',
shortCode: 'Short URL', shortCode: 'Short URL',
originalUrl: 'Long URL', longUrl: 'Long URL',
visits: 'Visits', visits: 'Visits',
}; };
@ -142,9 +142,9 @@ const ShortUrlsList = (ShortUrlsRow) => class ShortUrlsList extends React.Compon
</th> </th>
<th <th
className="short-urls-list__header-cell short-urls-list__header-cell--with-action" className="short-urls-list__header-cell short-urls-list__header-cell--with-action"
onClick={this.orderByColumn('originalUrl')} onClick={this.orderByColumn('longUrl')}
> >
{this.renderOrderIcon('originalUrl')} {this.renderOrderIcon('longUrl')}
Long URL Long URL
</th> </th>
<th className="short-urls-list__header-cell">Tags</th> <th className="short-urls-list__header-cell">Tags</th>

View file

@ -43,7 +43,6 @@ const ShortUrlsRow = (
render() { render() {
const { shortUrl, selectedServer } = this.props; const { shortUrl, selectedServer } = this.props;
const completeShortUrl = !selectedServer ? shortUrl.shortCode : `${selectedServer.url}/${shortUrl.shortCode}`;
return ( return (
<tr className="short-urls-row"> <tr className="short-urls-row">
@ -51,10 +50,10 @@ const ShortUrlsRow = (
<Moment format="YYYY-MM-DD HH:mm">{shortUrl.dateCreated}</Moment> <Moment format="YYYY-MM-DD HH:mm">{shortUrl.dateCreated}</Moment>
</td> </td>
<td className="short-urls-row__cell" data-th="Short URL: "> <td className="short-urls-row__cell" data-th="Short URL: ">
<ExternalLink href={completeShortUrl}>{completeShortUrl}</ExternalLink> <ExternalLink href={shortUrl.shortUrl} />
</td> </td>
<td className="short-urls-row__cell short-urls-row__cell--break" data-th="Long URL: "> <td className="short-urls-row__cell short-urls-row__cell--break" data-th="Long URL: ">
<ExternalLink href={shortUrl.originalUrl}>{shortUrl.originalUrl}</ExternalLink> <ExternalLink href={shortUrl.longUrl} />
</td> </td>
<td className="short-urls-row__cell" data-th="Tags: ">{this.renderTags(shortUrl.tags)}</td> <td className="short-urls-row__cell" data-th="Tags: ">{this.renderTags(shortUrl.tags)}</td>
<td className="short-urls-row__cell text-md-right" data-th="Visits: ">{shortUrl.visitsCount}</td> <td className="short-urls-row__cell text-md-right" data-th="Visits: ">{shortUrl.visitsCount}</td>
@ -66,7 +65,6 @@ const ShortUrlsRow = (
Copied short URL! Copied short URL!
</small> </small>
<ShortUrlsRowMenu <ShortUrlsRowMenu
completeShortUrl={completeShortUrl}
selectedServer={selectedServer} selectedServer={selectedServer}
shortUrl={shortUrl} shortUrl={shortUrl}
onCopyToClipboard={() => stateFlagTimeout(this.setState.bind(this), 'copiedToClipboard')} onCopyToClipboard={() => stateFlagTimeout(this.setState.bind(this), 'copiedToClipboard')}

View file

@ -20,7 +20,6 @@ import './ShortUrlsRowMenu.scss';
const ShortUrlsRowMenu = (DeleteShortUrlModal, EditTagsModal) => class ShortUrlsRowMenu extends React.Component { const ShortUrlsRowMenu = (DeleteShortUrlModal, EditTagsModal) => class ShortUrlsRowMenu extends React.Component {
static propTypes = { static propTypes = {
completeShortUrl: PropTypes.string,
onCopyToClipboard: PropTypes.func, onCopyToClipboard: PropTypes.func,
selectedServer: serverType, selectedServer: serverType,
shortUrl: shortUrlType, shortUrl: shortUrlType,
@ -36,7 +35,8 @@ const ShortUrlsRowMenu = (DeleteShortUrlModal, EditTagsModal) => class ShortUrls
toggle = () => this.setState(({ isOpen }) => ({ isOpen: !isOpen })); toggle = () => this.setState(({ isOpen }) => ({ isOpen: !isOpen }));
render() { render() {
const { completeShortUrl, onCopyToClipboard, selectedServer, shortUrl } = this.props; const { onCopyToClipboard, selectedServer, shortUrl } = this.props;
const completeShortUrl = shortUrl && shortUrl.shortUrl ? shortUrl.shortUrl : '';
const serverId = selectedServer ? selectedServer.id : ''; const serverId = selectedServer ? selectedServer.id : '';
const toggleModal = (prop) => () => this.setState((prevState) => ({ [prop]: !prevState[prop] })); const toggleModal = (prop) => () => this.setState((prevState) => ({ [prop]: !prevState[prop] }));
const toggleQrCode = toggleModal('isQrModalOpen'); const toggleQrCode = toggleModal('isQrModalOpen');

View file

@ -10,9 +10,10 @@ export const LIST_SHORT_URLS = 'shlink/shortUrlsList/LIST_SHORT_URLS';
/* eslint-enable padding-line-between-statements, newline-after-var */ /* eslint-enable padding-line-between-statements, newline-after-var */
export const shortUrlType = PropTypes.shape({ export const shortUrlType = PropTypes.shape({
tags: PropTypes.arrayOf(PropTypes.string),
shortCode: PropTypes.string, shortCode: PropTypes.string,
originalUrl: PropTypes.string, shortUrl: PropTypes.string,
longUrl: PropTypes.string,
tags: PropTypes.arrayOf(PropTypes.string),
}); });
const initialState = { const initialState = {

View file

@ -34,13 +34,7 @@ export function VisitsHeader({ shortUrlDetail, shortUrlVisits }) {
Visit stats for <ExternalLink href={shortLink} /> Visit stats for <ExternalLink href={shortLink} />
</h2> </h2>
<hr /> <hr />
{shortUrl.dateCreated && ( <div>Created: {renderDate()}</div>
<div>
Created:
&nbsp;
{renderDate()}
</div>
)}
<div> <div>
Long URL: Long URL:
&nbsp; &nbsp;

View file

@ -0,0 +1,108 @@
import React from 'react';
import { shallow } from 'enzyme';
import moment from 'moment';
import Moment from 'react-moment';
import { assoc, toString } from 'ramda';
import * as sinon from 'sinon';
import createShortUrlsRow from '../../../src/short-urls/helpers/ShortUrlsRow';
import ExternalLink from '../../../src/utils/ExternalLink';
import Tag from '../../../src/tags/helpers/Tag';
describe('<ShortUrlsRow />', () => {
let wrapper;
const mockFunction = () => '';
const ShortUrlsRowMenu = mockFunction;
const stateFlagTimeout = sinon.spy();
const colorGenerator = {
getColorForKey: mockFunction,
setColorForKey: mockFunction,
};
const server = {
url: 'https://doma.in',
};
const shortUrl = {
shortCode: 'abc123',
shortUrl: 'http://doma.in/abc123',
longUrl: 'http://foo.com/bar',
dateCreated: moment('2018-05-23 18:30:41').format(),
tags: [ 'nodejs', 'reactjs' ],
visitsCount: 45,
};
beforeEach(() => {
const ShortUrlsRow = createShortUrlsRow(ShortUrlsRowMenu, colorGenerator, stateFlagTimeout);
wrapper = shallow(
<ShortUrlsRow shortUrlsListParams={{}} refreshList={mockFunction} selecrtedServer={server} shortUrl={shortUrl} />
);
});
afterEach(() => wrapper.unmount());
it('renders date in first column', () => {
const col = wrapper.find('td').first();
const moment = col.find(Moment);
expect(moment.html()).toContain('>2018-05-23 18:30</time>');
});
it('renders short URL in second row', () => {
const col = wrapper.find('td').at(1);
const link = col.find(ExternalLink);
expect(link.prop('href')).toEqual(shortUrl.shortUrl);
});
it('renders long URL in third row', () => {
const col = wrapper.find('td').at(2); // eslint-disable-line no-magic-numbers
const link = col.find(ExternalLink);
expect(link.prop('href')).toEqual(shortUrl.longUrl);
});
describe('renders list of tags in fourth row', () => {
it('with tags', () => {
const col = wrapper.find('td').at(3); // eslint-disable-line no-magic-numbers
const tags = col.find(Tag);
expect(tags).toHaveLength(shortUrl.tags.length);
shortUrl.tags.forEach((tagValue, index) => {
const tag = tags.at(index);
expect(tag.prop('text')).toEqual(tagValue);
});
});
it('without tags', () => {
wrapper.setProps({ shortUrl: assoc('tags', [], shortUrl) });
const col = wrapper.find('td').at(3); // eslint-disable-line no-magic-numbers
expect(col.text()).toContain('No tags');
});
});
it('renders visits count in fifth row', () => {
const col = wrapper.find('td').at(4); // eslint-disable-line no-magic-numbers
expect(col.text()).toEqual(toString(shortUrl.visitsCount));
});
it('updates state when copied to clipboard', () => {
const col = wrapper.find('td').at(5); // eslint-disable-line no-magic-numbers
const menu = col.find(ShortUrlsRowMenu);
expect(menu).toHaveLength(1);
expect(stateFlagTimeout.called).toEqual(false);
menu.simulate('copyToClipboard');
expect(stateFlagTimeout.calledOnce).toEqual(true);
});
it('shows copy hint when state prop is true', () => {
// eslint-disable-next-line no-magic-numbers
const isHidden = () => wrapper.find('td').at(5).find('.short-urls-row__copy-hint').prop('hidden');
expect(isHidden()).toEqual(true);
wrapper.setState({ copiedToClipboard: true });
expect(isHidden()).toEqual(false);
});
});

View file

@ -8,6 +8,7 @@ describe('<VisitsHeader />', () => {
let wrapper; let wrapper;
const shortUrlDetail = { const shortUrlDetail = {
shortUrl: { shortUrl: {
shortUrl: 'https://doma.in/abc123',
longUrl: 'https://foo.bar/bar/foo', longUrl: 'https://foo.bar/bar/foo',
dateCreated: '2018-01-01T10:00:00+01:00', dateCreated: '2018-01-01T10:00:00+01:00',
}, },