diff --git a/package-lock.json b/package-lock.json
index 3c9c4b58..f1535a30 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3410,6 +3410,16 @@
"@types/react-router": "*"
}
},
+ "@types/reactstrap": {
+ "version": "8.5.1",
+ "resolved": "https://registry.npmjs.org/@types/reactstrap/-/reactstrap-8.5.1.tgz",
+ "integrity": "sha512-oEedcEGoX8EqDymsjrjzTnmaf3FuDY9qKLZMA9cH1ZkkqBc2V4i2sJ6ssXEod+GHQ5XH2r52uvbMkjEkjEZHDQ==",
+ "dev": true,
+ "requires": {
+ "@types/react": "*",
+ "popper.js": "^1.14.1"
+ }
+ },
"@types/stack-utils": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz",
diff --git a/package.json b/package.json
index 6d8d8aea..e84df9f7 100644
--- a/package.json
+++ b/package.json
@@ -83,6 +83,7 @@
"@types/react-dom": "^16.9.8",
"@types/react-redux": "^7.1.9",
"@types/react-router-dom": "^5.1.5",
+ "@types/reactstrap": "^8.5.1",
"adm-zip": "^0.4.13",
"autoprefixer": "^9.6.3",
"babel-core": "7.0.0-bridge.0",
diff --git a/src/servers/helpers/ImportServersBtn.js b/src/servers/helpers/ImportServersBtn.js
deleted file mode 100644
index 7bde4df7..00000000
--- a/src/servers/helpers/ImportServersBtn.js
+++ /dev/null
@@ -1,48 +0,0 @@
-import React, { useRef } from 'react';
-import { UncontrolledTooltip } from 'reactstrap';
-import PropTypes from 'prop-types';
-
-const propTypes = {
- onImport: PropTypes.func,
- createServers: PropTypes.func,
- fileRef: PropTypes.oneOfType([ PropTypes.object, PropTypes.node ]),
-};
-
-// FIXME Replace with typescript: (ServersImporter)
-const ImportServersBtn = ({ importServersFromFile }) => {
- const ImportServersBtnComp = ({ createServers, fileRef, onImport = () => '' }) => {
- const ref = fileRef || useRef();
- const onChange = ({ target }) =>
- importServersFromFile(target.files[0])
- .then(createServers)
- .then(onImport)
- .then(() => {
- // Reset input after processing file
- target.value = null;
- });
-
- return (
-
-
-
- You can create servers by importing a CSV file with columns name, apiKey and url.
-
-
-
-
- );
- };
-
- ImportServersBtnComp.propTypes = propTypes;
-
- return ImportServersBtnComp;
-};
-
-export default ImportServersBtn;
diff --git a/src/servers/helpers/ImportServersBtn.tsx b/src/servers/helpers/ImportServersBtn.tsx
new file mode 100644
index 00000000..e77d69d2
--- /dev/null
+++ b/src/servers/helpers/ImportServersBtn.tsx
@@ -0,0 +1,46 @@
+import React, { useRef, RefObject, ChangeEvent, MutableRefObject } from 'react';
+import { UncontrolledTooltip } from 'reactstrap';
+import ServersImporter from '../services/ServersImporter';
+import { Server } from '../data';
+
+type Ref = RefObject | MutableRefObject;
+
+interface ImportServersBtnProps {
+ createServers: (servers: Server[]) => void;
+ fileRef: Ref;
+ onImport?: () => void;
+}
+
+const ImportServersBtn = ({ importServersFromFile }: ServersImporter) => (
+ { createServers, fileRef, onImport = () => {} }: ImportServersBtnProps,
+) => {
+ const ref = fileRef ?? useRef();
+ const onChange = async ({ target }: ChangeEvent) =>
+ importServersFromFile(target.files?.[0])
+ .then(createServers)
+ .then(onImport)
+ .then(() => {
+ // Reset input after processing file
+ (target as { value: string | null }).value = null;
+ });
+
+ return (
+
+
+
+ You can create servers by importing a CSV file with columns name, apiKey and url.
+
+
+
+
+ );
+};
+
+export default ImportServersBtn;
diff --git a/src/servers/services/ServersImporter.ts b/src/servers/services/ServersImporter.ts
index d65be66b..17ab38e3 100644
--- a/src/servers/services/ServersImporter.ts
+++ b/src/servers/services/ServersImporter.ts
@@ -6,7 +6,7 @@ const CSV_MIME_TYPE = 'text/csv';
export default class ServersImporter {
public constructor(private readonly csvjson: CsvJson, private readonly fileReaderFactory: () => FileReader) {}
- public importServersFromFile = async (file?: File): Promise => {
+ public importServersFromFile = async (file?: File | null): Promise => {
if (!file || file.type !== CSV_MIME_TYPE) {
throw new Error('No file provided or file is not a CSV');
}
diff --git a/test/servers/helpers/ImportServersBtn.test.js b/test/servers/helpers/ImportServersBtn.test.tsx
similarity index 78%
rename from test/servers/helpers/ImportServersBtn.test.js
rename to test/servers/helpers/ImportServersBtn.test.tsx
index fc203d28..7f373fbb 100644
--- a/test/servers/helpers/ImportServersBtn.test.js
+++ b/test/servers/helpers/ImportServersBtn.test.tsx
@@ -1,24 +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 importServersBtnConstruct from '../../../src/servers/helpers/ImportServersBtn';
+import ServersImporter from '../../../src/servers/services/ServersImporter';
describe('', () => {
- let wrapper;
+ let wrapper: ShallowWrapper;
const onImportMock = jest.fn();
const createServersMock = jest.fn();
- const serversImporterMock = {
+ const serversImporterMock = Mock.of({
importServersFromFile: jest.fn().mockResolvedValue([]),
- };
+ });
+ const click = jest.fn();
const fileRef = {
- current: { click: jest.fn() },
+ current: Mock.of({ click }),
};
beforeEach(() => {
- onImportMock.mockReset();
- createServersMock.mockReset();
- serversImporterMock.importServersFromFile.mockClear();
- fileRef.current.click.mockReset();
+ jest.clearAllMocks();
const ImportServersBtn = importServersBtnConstruct(serversImporterMock);
@@ -39,7 +39,7 @@ describe('', () => {
btn.simulate('click');
- expect(fileRef.current.click).toHaveBeenCalledTimes(1);
+ expect(click).toHaveBeenCalledTimes(1);
});
it('imports servers when file input changes', (done) => {