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);