Finished migrating ll short-url helpers to TS

This commit is contained in:
Alejandro Celaya
2020-08-30 09:59:14 +02:00
parent c0f5d9c12c
commit 4b33d39d44
30 changed files with 483 additions and 499 deletions

View File

@@ -1,28 +1,31 @@
import React from 'react';
import { shallow } from 'enzyme';
import { shallow, ShallowWrapper } from 'enzyme';
import { identity } from 'ramda';
import { CopyToClipboard } from 'react-copy-to-clipboard';
import CopyToClipboard from 'react-copy-to-clipboard';
import { Tooltip } from 'reactstrap';
import { Mock } from 'ts-mockery';
import createCreateShortUrlResult from '../../../src/short-urls/helpers/CreateShortUrlResult';
import { ShortUrl } from '../../../src/short-urls/data';
import { StateFlagTimeout } from '../../../src/utils/helpers/hooks';
describe('<CreateShortUrlResult />', () => {
let wrapper;
let wrapper: ShallowWrapper;
const copyToClipboard = jest.fn();
const useStateFlagTimeout = jest.fn(() => [ false, copyToClipboard ]);
const useStateFlagTimeout = jest.fn(() => [ false, copyToClipboard ]) as StateFlagTimeout;
const CreateShortUrlResult = createCreateShortUrlResult(useStateFlagTimeout);
const createWrapper = (result, error = false) => {
wrapper = shallow(<CreateShortUrlResult resetCreateShortUrl={identity} result={result} error={error} />);
const createWrapper = (result: ShortUrl | null = null, error = false) => {
wrapper = shallow(
<CreateShortUrlResult resetCreateShortUrl={identity} result={result} error={error} saving={false} />,
);
return wrapper;
};
afterEach(() => {
jest.clearAllMocks();
wrapper && wrapper.unmount();
});
afterEach(jest.clearAllMocks);
afterEach(() => wrapper?.unmount());
it('renders an error when error is true', () => {
const wrapper = createWrapper({}, true);
const wrapper = createWrapper(Mock.all<ShortUrl>(), true);
const errorCard = wrapper.find('.bg-danger');
expect(errorCard).toHaveLength(1);
@@ -36,7 +39,7 @@ describe('<CreateShortUrlResult />', () => {
});
it('renders a result message when result is provided', () => {
const wrapper = createWrapper({ shortUrl: 'https://doma.in/abc123' });
const wrapper = createWrapper(Mock.of<ShortUrl>({ shortUrl: 'https://doma.in/abc123' }));
expect(wrapper.html()).toContain('<b>Great!</b> The short URL is <b>https://doma.in/abc123</b>');
expect(wrapper.find(CopyToClipboard)).toHaveLength(1);
@@ -44,7 +47,7 @@ describe('<CreateShortUrlResult />', () => {
});
it('Invokes tooltip timeout when copy to clipboard button is clicked', () => {
const wrapper = createWrapper({ shortUrl: 'https://doma.in/abc123' });
const wrapper = createWrapper(Mock.of<ShortUrl>({ shortUrl: 'https://doma.in/abc123' }));
const copyBtn = wrapper.find(CopyToClipboard);
expect(copyToClipboard).not.toHaveBeenCalled();

View File

@@ -1,27 +1,31 @@
import React from 'react';
import { shallow } from 'enzyme';
import { shallow, ShallowWrapper } from 'enzyme';
import { Modal } from 'reactstrap';
import { Mock } from 'ts-mockery';
import createEditTagsModal from '../../../src/short-urls/helpers/EditTagsModal';
import { ShortUrl } from '../../../src/short-urls/data';
import { ShortUrlTags } from '../../../src/short-urls/reducers/shortUrlTags';
import { OptionalString } from '../../../src/utils/utils';
describe('<EditTagsModal />', () => {
let wrapper;
let wrapper: ShallowWrapper;
const shortCode = 'abc123';
const TagsSelector = () => '';
const editShortUrlTags = jest.fn(() => Promise.resolve());
const TagsSelector = () => null;
const editShortUrlTags = jest.fn(async () => Promise.resolve());
const resetShortUrlsTags = jest.fn();
const toggle = jest.fn();
const createWrapper = (shortUrlTags, domain) => {
const createWrapper = (shortUrlTags: ShortUrlTags, domain?: OptionalString) => {
const EditTagsModal = createEditTagsModal(TagsSelector);
wrapper = shallow(
<EditTagsModal
isOpen={true}
shortUrl={{
shortUrl={Mock.of<ShortUrl>({
tags: [],
shortCode,
domain,
originalUrl: 'https://long-domain.com/foo/bar',
}}
longUrl: 'https://long-domain.com/foo/bar',
})}
shortUrlTags={shortUrlTags}
toggle={toggle}
editShortUrlTags={editShortUrlTags}
@@ -32,10 +36,8 @@ describe('<EditTagsModal />', () => {
return wrapper;
};
afterEach(() => {
wrapper && wrapper.unmount();
jest.clearAllMocks();
});
afterEach(() => wrapper?.unmount());
afterEach(jest.clearAllMocks);
it('renders tags selector and save button when loaded', () => {
const wrapper = createWrapper({
@@ -64,7 +66,12 @@ describe('<EditTagsModal />', () => {
expect(saveBtn.text()).toEqual('Saving tags...');
});
it.each([[ undefined ], [ null ], [ 'example.com' ]])('saves tags when save button is clicked', (domain, done) => {
it.each([
[ undefined ],
[ null ],
[ 'example.com' ],
// @ts-expect-error
])('saves tags when save button is clicked', (domain: OptionalString, done: jest.DoneCallback) => {
const wrapper = createWrapper({
shortCode,
tags: [],

View File

@@ -1,14 +1,16 @@
import React from 'react';
import { shallow } from 'enzyme';
import { shallow, ShallowWrapper } from 'enzyme';
import { ExternalLink } from 'react-external-link';
import { Mock } from 'ts-mockery';
import PreviewModal from '../../../src/short-urls/helpers/PreviewModal';
import { ShortUrl } from '../../../src/short-urls/data';
describe('<PreviewModal />', () => {
let wrapper;
const url = 'https://doma.in/abc123';
let wrapper: ShallowWrapper;
const shortUrl = 'https://doma.in/abc123';
beforeEach(() => {
wrapper = shallow(<PreviewModal url={url} />);
wrapper = shallow(<PreviewModal shortUrl={Mock.of<ShortUrl>({ shortUrl })} isOpen={true} toggle={() => {}} />);
});
afterEach(() => wrapper.unmount());
@@ -16,13 +18,13 @@ describe('<PreviewModal />', () => {
const externalLink = wrapper.find(ExternalLink);
expect(externalLink).toHaveLength(1);
expect(externalLink.prop('href')).toEqual(url);
expect(externalLink.prop('href')).toEqual(shortUrl);
});
it('displays an image with the preview of the URL', () => {
const img = wrapper.find('img');
expect(img).toHaveLength(1);
expect(img.prop('src')).toEqual(`${url}/preview`);
expect(img.prop('src')).toEqual(`${shortUrl}/preview`);
});
});

View File

@@ -1,14 +1,16 @@
import React from 'react';
import { shallow } from 'enzyme';
import { shallow, ShallowWrapper } from 'enzyme';
import { ExternalLink } from 'react-external-link';
import { Mock } from 'ts-mockery';
import QrCodeModal from '../../../src/short-urls/helpers/QrCodeModal';
import { ShortUrl } from '../../../src/short-urls/data';
describe('<QrCodeModal />', () => {
let wrapper;
const url = 'https://doma.in/abc123';
let wrapper: ShallowWrapper;
const shortUrl = 'https://doma.in/abc123';
beforeEach(() => {
wrapper = shallow(<QrCodeModal url={url} />);
wrapper = shallow(<QrCodeModal shortUrl={Mock.of<ShortUrl>({ shortUrl })} isOpen={true} toggle={() => {}} />);
});
afterEach(() => wrapper.unmount());
@@ -16,13 +18,13 @@ describe('<QrCodeModal />', () => {
const externalLink = wrapper.find(ExternalLink);
expect(externalLink).toHaveLength(1);
expect(externalLink.prop('href')).toEqual(url);
expect(externalLink.prop('href')).toEqual(shortUrl);
});
it('displays an image with the QR code of the URL', () => {
const img = wrapper.find('img');
expect(img).toHaveLength(1);
expect(img.prop('src')).toEqual(`${url}/qr-code`);
expect(img.prop('src')).toEqual(`${shortUrl}/qr-code`);
});
});

View File

@@ -1,22 +1,24 @@
import React from 'react';
import { shallow } from 'enzyme';
import { shallow, ShallowWrapper } from 'enzyme';
import { UncontrolledTooltip } from 'reactstrap';
import { Mock } from 'ts-mockery';
import ShortUrlVisitsCount from '../../../src/short-urls/helpers/ShortUrlVisitsCount';
import { ShortUrl } from '../../../src/short-urls/data';
describe('<ShortUrlVisitsCount />', () => {
let wrapper;
let wrapper: ShallowWrapper;
const createWrapper = (visitsCount, shortUrl) => {
const createWrapper = (visitsCount: number, shortUrl: ShortUrl) => {
wrapper = shallow(<ShortUrlVisitsCount visitsCount={visitsCount} shortUrl={shortUrl} />);
return wrapper;
};
afterEach(() => wrapper && wrapper.unmount());
afterEach(() => wrapper?.unmount());
it.each([ undefined, {}])('just returns visits when no maxVisits is provided', (meta) => {
const visitsCount = 45;
const wrapper = createWrapper(visitsCount, { meta });
const wrapper = createWrapper(visitsCount, Mock.of<ShortUrl>({ meta }));
const maxVisitsHelper = wrapper.find('.short-urls-visits-count__max-visits-control');
const maxVisitsTooltip = wrapper.find(UncontrolledTooltip);
@@ -31,7 +33,7 @@ describe('<ShortUrlVisitsCount />', () => {
const visitsCount = 45;
const maxVisits = 500;
const meta = { maxVisits };
const wrapper = createWrapper(visitsCount, { meta });
const wrapper = createWrapper(visitsCount, Mock.of<ShortUrl>({ meta }));
const maxVisitsHelper = wrapper.find('.short-urls-visits-count__max-visits-control');
const maxVisitsTooltip = wrapper.find(UncontrolledTooltip);

View File

@@ -1,40 +1,51 @@
import React from 'react';
import { shallow } from 'enzyme';
import { shallow, ShallowWrapper } from 'enzyme';
import moment from 'moment';
import Moment from 'react-moment';
import { assoc, toString } from 'ramda';
import { Mock } from 'ts-mockery';
import { ExternalLink } from 'react-external-link';
import { CopyToClipboard } from 'react-copy-to-clipboard';
import CopyToClipboard from 'react-copy-to-clipboard';
import createShortUrlsRow from '../../../src/short-urls/helpers/ShortUrlsRow';
import Tag from '../../../src/tags/helpers/Tag';
import ColorGenerator from '../../../src/utils/services/ColorGenerator';
import { StateFlagTimeout } from '../../../src/utils/helpers/hooks';
import { ShortUrl } from '../../../src/short-urls/data';
import { ReachableServer } from '../../../src/servers/data';
describe('<ShortUrlsRow />', () => {
let wrapper;
const mockFunction = () => '';
let wrapper: ShallowWrapper;
const mockFunction = () => null;
const ShortUrlsRowMenu = mockFunction;
const stateFlagTimeout = jest.fn(() => true);
const useStateFlagTimeout = jest.fn(() => [ false, stateFlagTimeout ]);
const colorGenerator = {
getColorForKey: mockFunction,
setColorForKey: mockFunction,
};
const server = {
const useStateFlagTimeout = jest.fn(() => [ false, stateFlagTimeout ]) as StateFlagTimeout;
const colorGenerator = Mock.of<ColorGenerator>({
getColorForKey: jest.fn(),
setColorForKey: jest.fn(),
});
const server = Mock.of<ReachableServer>({
url: 'https://doma.in',
};
const shortUrl = {
});
const shortUrl: 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,
domain: null,
meta: {
validSince: null,
validUntil: null,
maxVisits: null,
},
};
beforeEach(() => {
const ShortUrlsRow = createShortUrlsRow(ShortUrlsRowMenu, colorGenerator, useStateFlagTimeout);
wrapper = shallow(
<ShortUrlsRow shortUrlsListParams={{}} refreshList={mockFunction} selecrtedServer={server} shortUrl={shortUrl} />,
<ShortUrlsRow shortUrlsListParams={{}} refreshList={mockFunction} selectedServer={server} shortUrl={shortUrl} />,
);
});
afterEach(() => wrapper.unmount());

View File

@@ -1,43 +1,39 @@
import React from 'react';
import { shallow } from 'enzyme';
import { shallow, ShallowWrapper } from 'enzyme';
import { ButtonDropdown, DropdownItem } from 'reactstrap';
import { Mock } from 'ts-mockery';
import createShortUrlsRowMenu from '../../../src/short-urls/helpers/ShortUrlsRowMenu';
import PreviewModal from '../../../src/short-urls/helpers/PreviewModal';
import QrCodeModal from '../../../src/short-urls/helpers/QrCodeModal';
import { ReachableServer } from '../../../src/servers/data';
import { ShortUrl } from '../../../src/short-urls/data';
describe('<ShortUrlsRowMenu />', () => {
let wrapper;
const DeleteShortUrlModal = () => '';
const EditTagsModal = () => '';
const EditMetaModal = () => '';
const EditShortUrlModal = () => '';
const onCopyToClipboard = jest.fn();
const selectedServer = { id: 'abc123' };
const shortUrl = {
let wrapper: ShallowWrapper;
const DeleteShortUrlModal = () => null;
const EditTagsModal = () => null;
const EditMetaModal = () => null;
const EditShortUrlModal = () => null;
const selectedServer = Mock.of<ReachableServer>({ id: 'abc123' });
const shortUrl = Mock.of<ShortUrl>({
shortCode: 'abc123',
shortUrl: 'https://doma.in/abc123',
};
});
const createWrapper = () => {
const ShortUrlsRowMenu = createShortUrlsRowMenu(
DeleteShortUrlModal,
EditTagsModal,
EditMetaModal,
EditShortUrlModal,
() => '',
() => null,
);
wrapper = shallow(
<ShortUrlsRowMenu
selectedServer={selectedServer}
shortUrl={shortUrl}
onCopyToClipboard={onCopyToClipboard}
/>,
);
wrapper = shallow(<ShortUrlsRowMenu selectedServer={selectedServer} shortUrl={shortUrl} />);
return wrapper;
};
afterEach(() => wrapper && wrapper.unmount());
afterEach(() => wrapper?.unmount());
it('renders modal windows', () => {
const wrapper = createWrapper();
@@ -62,8 +58,8 @@ describe('<ShortUrlsRowMenu />', () => {
expect(items.find('[divider]')).toHaveLength(1);
});
describe('toggles state when toggling modal windows', () => {
const assert = (modalComponent) => {
describe('toggles state when toggling modals or the dropdown', () => {
const assert = (modalComponent: Function) => {
const wrapper = createWrapper();
expect(wrapper.find(modalComponent).prop('isOpen')).toEqual(false);
@@ -76,13 +72,6 @@ describe('<ShortUrlsRowMenu />', () => {
it('PreviewModal', () => assert(PreviewModal));
it('QrCodeModal', () => assert(QrCodeModal));
it('EditShortUrlModal', () => assert(EditShortUrlModal));
});
it('toggles dropdown state when toggling dropdown', () => {
const wrapper = createWrapper();
expect(wrapper.find(ButtonDropdown).prop('isOpen')).toEqual(false);
wrapper.find(ButtonDropdown).prop('toggle')();
expect(wrapper.find(ButtonDropdown).prop('isOpen')).toEqual(true);
it('EditShortUrlModal', () => assert(ButtonDropdown));
});
});

View File

@@ -1,21 +1,25 @@
import React from 'react';
import { shallow } from 'enzyme';
import { shallow, ShallowWrapper } from 'enzyme';
import { Link } from 'react-router-dom';
import { Mock } from 'ts-mockery';
import VisitStatsLink from '../../../src/short-urls/helpers/VisitStatsLink';
import { NotFoundServer, ReachableServer } from '../../../src/servers/data';
import { ShortUrl } from '../../../src/short-urls/data';
describe('<VisitStatsLink />', () => {
let wrapper;
let wrapper: ShallowWrapper;
afterEach(() => wrapper && wrapper.unmount());
afterEach(() => wrapper?.unmount());
it.each([
[ undefined, undefined ],
[ null, null ],
[{}, null ],
[{}, undefined ],
[ null, {}],
[ undefined, {}],
])('only renders a plan span when either server or short URL are not set', (selectedServer, shortUrl) => {
[ Mock.of<ReachableServer>({ id: '1' }), null ],
[ Mock.of<ReachableServer>({ id: '1' }), undefined ],
[ Mock.of<NotFoundServer>(), Mock.all<ShortUrl>() ],
[ null, Mock.all<ShortUrl>() ],
[ undefined, Mock.all<ShortUrl>() ],
])('only renders a plain span when either server or short URL are not set', (selectedServer, shortUrl) => {
wrapper = shallow(<VisitStatsLink selectedServer={selectedServer} shortUrl={shortUrl}>Something</VisitStatsLink>);
const link = wrapper.find(Link);
@@ -24,10 +28,14 @@ describe('<VisitStatsLink />', () => {
});
it.each([
[{ id: '1' }, { shortCode: 'abc123' }, '/server/1/short-code/abc123/visits' ],
[
{ id: '3' },
{ shortCode: 'def456', domain: 'example.com' },
Mock.of<ReachableServer>({ id: '1' }),
Mock.of<ShortUrl>({ shortCode: 'abc123' }),
'/server/1/short-code/abc123/visits',
],
[
Mock.of<ReachableServer>({ id: '3' }),
Mock.of<ShortUrl>({ shortCode: 'def456', domain: 'example.com' }),
'/server/3/short-code/def456/visits?domain=example.com',
],
])('renders link with expected query when', (selectedServer, shortUrl, expectedLink) => {