From c0f5d9c12c22ee79c09fa5d4a237707bbf461d71 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Sat, 29 Aug 2020 20:20:45 +0200 Subject: [PATCH] Finished migrating servers module to TS --- src/common/MenuLayout.tsx | 10 +--- src/servers/EditServer.js | 38 ------------- src/servers/EditServer.tsx | 32 +++++++++++ src/servers/ServersDropdown.js | 55 ------------------- src/servers/ServersDropdown.tsx | 49 +++++++++++++++++ src/servers/helpers/withSelectedServer.tsx | 30 +++++----- ...EditServer.test.js => EditServer.test.tsx} | 28 ++++++---- ...pdown.test.js => ServersDropdown.test.tsx} | 30 +++++----- 8 files changed, 130 insertions(+), 142 deletions(-) delete mode 100644 src/servers/EditServer.js create mode 100644 src/servers/EditServer.tsx delete mode 100644 src/servers/ServersDropdown.js create mode 100644 src/servers/ServersDropdown.tsx rename test/servers/{EditServer.test.js => EditServer.test.tsx} (60%) rename test/servers/{ServersDropdown.test.js => ServersDropdown.test.tsx} (53%) diff --git a/src/common/MenuLayout.tsx b/src/common/MenuLayout.tsx index 79b5a043..07553820 100644 --- a/src/common/MenuLayout.tsx +++ b/src/common/MenuLayout.tsx @@ -1,5 +1,5 @@ import React, { FC, useEffect } from 'react'; -import { Route, RouteChildrenProps, Switch } from 'react-router-dom'; +import { Route, Switch } from 'react-router-dom'; import { EventData, Swipeable } from 'react-swipeable'; import { faBars as burgerIcon } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; @@ -7,15 +7,11 @@ import classNames from 'classnames'; import { withSelectedServer } from '../servers/helpers/withSelectedServer'; import { useToggle } from '../utils/helpers/hooks'; import { versionMatch } from '../utils/helpers/version'; -import { isReachableServer, SelectedServer } from '../servers/data'; +import { isReachableServer } from '../servers/data'; import NotFound from './NotFound'; import { AsideMenuProps } from './AsideMenu'; import './MenuLayout.scss'; -interface MenuLayoutProps extends RouteChildrenProps { - selectedServer: SelectedServer; -} - const MenuLayout = ( TagsList: FC, ShortUrls: FC, @@ -25,7 +21,7 @@ const MenuLayout = ( TagVisits: FC, ShlinkVersions: FC, ServerError: FC, -) => withSelectedServer(({ location, selectedServer }: MenuLayoutProps) => { +) => withSelectedServer(({ location, selectedServer }) => { const [ sidebarVisible, toggleSidebar, showSidebar, hideSidebar ] = useToggle(); useEffect(() => hideSidebar(), [ location ]); diff --git a/src/servers/EditServer.js b/src/servers/EditServer.js deleted file mode 100644 index 33560631..00000000 --- a/src/servers/EditServer.js +++ /dev/null @@ -1,38 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { Button } from 'reactstrap'; -import NoMenuLayout from '../common/NoMenuLayout'; -import { ServerForm } from './helpers/ServerForm'; -import { withSelectedServer } from './helpers/withSelectedServer'; -import { serverType } from './prop-types'; - -const propTypes = { - editServer: PropTypes.func, - selectedServer: serverType, - history: PropTypes.shape({ - push: PropTypes.func, - goBack: PropTypes.func, - }), -}; - -export const EditServer = (ServerError) => { - const EditServerComp = ({ editServer, selectedServer, history: { push, goBack } }) => { - const handleSubmit = (serverData) => { - editServer(selectedServer.id, serverData); - push(`/server/${selectedServer.id}/list-short-urls/1`); - }; - - return ( - - - - - - - ); - }; - - EditServerComp.propTypes = propTypes; - - return withSelectedServer(EditServerComp, ServerError); -}; diff --git a/src/servers/EditServer.tsx b/src/servers/EditServer.tsx new file mode 100644 index 00000000..7aa28b6c --- /dev/null +++ b/src/servers/EditServer.tsx @@ -0,0 +1,32 @@ +import React, { FC } from 'react'; +import { Button } from 'reactstrap'; +import NoMenuLayout from '../common/NoMenuLayout'; +import { ServerForm } from './helpers/ServerForm'; +import { withSelectedServer } from './helpers/withSelectedServer'; +import { isServerWithId, ServerData } from './data'; + +interface EditServerProps { + editServer: (serverId: string, serverData: ServerData) => void; +} + +export const EditServer = (ServerError: FC) => withSelectedServer(( + { editServer, selectedServer, history: { push, goBack } }, +) => { + if (!isServerWithId(selectedServer)) { + return null; + } + + const handleSubmit = (serverData: ServerData) => { + editServer(selectedServer.id, serverData); + push(`/server/${selectedServer.id}/list-short-urls/1`); + }; + + return ( + + + + + + + ); +}, ServerError); diff --git a/src/servers/ServersDropdown.js b/src/servers/ServersDropdown.js deleted file mode 100644 index c4200e5d..00000000 --- a/src/servers/ServersDropdown.js +++ /dev/null @@ -1,55 +0,0 @@ -import { isEmpty, values } from 'ramda'; -import React from 'react'; -import { DropdownItem, DropdownMenu, DropdownToggle, UncontrolledDropdown } from 'reactstrap'; -import PropTypes from 'prop-types'; -import { Link } from 'react-router-dom'; -import { serverType } from './prop-types'; - -const propTypes = { - servers: PropTypes.object, - selectedServer: serverType, -}; - -const ServersDropdown = (serversExporter) => { - const ServersDropdownComp = ({ servers, selectedServer }) => { - const serversList = values(servers); - - const renderServers = () => { - if (isEmpty(serversList)) { - return Add a server first...; - } - - return ( - - {serversList.map(({ name, id }) => ( - - {name} - - ))} - - serversExporter.exportServers()}> - Export servers - - - ); - }; - - return ( - - Servers - {renderServers()} - - ); - }; - - ServersDropdownComp.propTypes = propTypes; - - return ServersDropdownComp; -}; - -export default ServersDropdown; diff --git a/src/servers/ServersDropdown.tsx b/src/servers/ServersDropdown.tsx new file mode 100644 index 00000000..80be5e61 --- /dev/null +++ b/src/servers/ServersDropdown.tsx @@ -0,0 +1,49 @@ +import { isEmpty, values } from 'ramda'; +import React from 'react'; +import { DropdownItem, DropdownMenu, DropdownToggle, UncontrolledDropdown } from 'reactstrap'; +import { Link } from 'react-router-dom'; +import ServersExporter from './services/ServersExporter'; +import { isServerWithId, SelectedServer, ServersMap } from './data'; + +export interface ServersDropdownProps { + servers: ServersMap; + selectedServer: SelectedServer; +} + +const ServersDropdown = (serversExporter: ServersExporter) => ({ servers, selectedServer }: ServersDropdownProps) => { + const serversList = values(servers); + + const renderServers = () => { + if (isEmpty(serversList)) { + return Add a server first...; + } + + return ( + + {serversList.map(({ name, id }) => ( + + {name} + + ))} + + serversExporter.exportServers()}> + Export servers + + + ); + }; + + return ( + + Servers + {renderServers()} + + ); +}; + +export default ServersDropdown; diff --git a/src/servers/helpers/withSelectedServer.tsx b/src/servers/helpers/withSelectedServer.tsx index f308d6e0..41f8a45c 100644 --- a/src/servers/helpers/withSelectedServer.tsx +++ b/src/servers/helpers/withSelectedServer.tsx @@ -8,22 +8,22 @@ interface WithSelectedServerProps extends RouteChildrenProps<{ serverId: string selectedServer: SelectedServer; } -export const withSelectedServer = (WrappedComponent: FC, ServerError: FC) => ( - props: WithSelectedServerProps, -) => { - const { selectServer, selectedServer, match } = props; +export function withSelectedServer(WrappedComponent: FC, ServerError: FC) { + return (props: WithSelectedServerProps & T) => { + const { selectServer, selectedServer, match } = props; - useEffect(() => { - match?.params?.serverId && selectServer(match?.params.serverId); - }, [ match?.params.serverId ]); + useEffect(() => { + match?.params?.serverId && selectServer(match?.params.serverId); + }, [ match?.params.serverId ]); - if (!selectedServer) { - return ; - } + if (!selectedServer) { + return ; + } - if (isNotFoundServer(selectedServer)) { - return ; - } + if (isNotFoundServer(selectedServer)) { + return ; + } - return ; -}; + return ; + }; +} diff --git a/test/servers/EditServer.test.js b/test/servers/EditServer.test.tsx similarity index 60% rename from test/servers/EditServer.test.js rename to test/servers/EditServer.test.tsx index 366dd24f..844b4e5b 100644 --- a/test/servers/EditServer.test.js +++ b/test/servers/EditServer.test.tsx @@ -1,22 +1,27 @@ import React from 'react'; -import { mount } from 'enzyme'; +import { mount, ReactWrapper } from 'enzyme'; +import { Mock } from 'ts-mockery'; +import { History, Location } from 'history'; +import { match } from 'react-router'; // eslint-disable-line @typescript-eslint/no-unused-vars import { EditServer as editServerConstruct } from '../../src/servers/EditServer'; import { ServerForm } from '../../src/servers/helpers/ServerForm'; +import { ReachableServer } from '../../src/servers/data'; describe('', () => { - let wrapper; + let wrapper: ReactWrapper; const ServerError = jest.fn(); const editServerMock = jest.fn(); - const historyMock = { push: jest.fn() }; - const match = { + const push = jest.fn(); + const historyMock = Mock.of({ push }); + const match = Mock.of>({ params: { serverId: 'abc123' }, - }; - const selectedServer = { + }); + const selectedServer = Mock.of({ id: 'abc123', name: 'name', url: 'url', apiKey: 'apiKey', - }; + }); beforeEach(() => { const EditServer = editServerConstruct(ServerError); @@ -26,16 +31,15 @@ describe('', () => { editServer={editServerMock} history={historyMock} match={match} + location={Mock.all()} selectedServer={selectedServer} selectServer={jest.fn()} />, ); }); - afterEach(() => { - jest.resetAllMocks(); - wrapper && wrapper.unmount(); - }); + afterEach(jest.resetAllMocks); + afterEach(() => wrapper?.unmount()); it('renders components', () => { expect(wrapper.find(ServerForm)).toHaveLength(1); @@ -47,6 +51,6 @@ describe('', () => { form.simulate('submit', {}); expect(editServerMock).toHaveBeenCalledTimes(1); - expect(historyMock.push).toHaveBeenCalledTimes(1); + expect(push).toHaveBeenCalledTimes(1); }); }); diff --git a/test/servers/ServersDropdown.test.js b/test/servers/ServersDropdown.test.tsx similarity index 53% rename from test/servers/ServersDropdown.test.js rename to test/servers/ServersDropdown.test.tsx index f2e6bd51..dd6a8c63 100644 --- a/test/servers/ServersDropdown.test.js +++ b/test/servers/ServersDropdown.test.tsx @@ -1,24 +1,24 @@ -import { identity, values } from 'ramda'; -import React from 'react'; -import { shallow } from 'enzyme'; +import { values } from 'ramda'; +import { Mock } from 'ts-mockery'; +import React, { FC } from 'react'; +import { shallow, ShallowWrapper } from 'enzyme'; import { DropdownItem, DropdownToggle } from 'reactstrap'; -import serversDropdownCreator from '../../src/servers/ServersDropdown'; +import serversDropdownCreator, { ServersDropdownProps } from '../../src/servers/ServersDropdown'; +import { ServerWithId } from '../../src/servers/data'; +import ServersExporter from '../../src/servers/services/ServersExporter'; describe('', () => { - let wrapped; - let ServersDropdown; + let wrapped: ShallowWrapper; + let ServersDropdown: FC; const servers = { - '1a': { name: 'foo', id: 1 }, - '2b': { name: 'bar', id: 2 }, - '3c': { name: 'baz', id: 3 }, - }; - const history = { - push: jest.fn(), + '1a': Mock.of({ name: 'foo', id: '1a' }), + '2b': Mock.of({ name: 'bar', id: '2b' }), + '3c': Mock.of({ name: 'baz', id: '3c' }), }; beforeEach(() => { - ServersDropdown = serversDropdownCreator({}); - wrapped = shallow(); + ServersDropdown = serversDropdownCreator(Mock.of()); + wrapped = shallow(); }); afterEach(() => wrapped.unmount()); @@ -37,7 +37,7 @@ describe('', () => { it('shows a message when no servers exist yet', () => { wrapped = shallow( - , + , ); const item = wrapped.find(DropdownItem);