Migrated to TS first component where some dependency was being injected

This commit is contained in:
Alejandro Celaya 2020-08-22 11:20:27 +02:00
parent eefea0c37b
commit 39663ba936
6 changed files with 68 additions and 59 deletions

10
package-lock.json generated
View file

@ -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",

View file

@ -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",

View file

@ -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 (
<React.Fragment>
<button
type="button"
className="btn btn-outline-secondary mr-2"
id="importBtn"
onClick={() => ref.current.click()}
>
Import from file
</button>
<UncontrolledTooltip placement="top" target="importBtn">
You can create servers by importing a CSV file with columns <b>name</b>, <b>apiKey</b> and <b>url</b>.
</UncontrolledTooltip>
<input type="file" accept="text/csv" className="create-server__csv-select" ref={ref} onChange={onChange} />
</React.Fragment>
);
};
ImportServersBtnComp.propTypes = propTypes;
return ImportServersBtnComp;
};
export default ImportServersBtn;

View file

@ -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<T> = RefObject<T> | MutableRefObject<T>;
interface ImportServersBtnProps {
createServers: (servers: Server[]) => void;
fileRef: Ref<HTMLInputElement>;
onImport?: () => void;
}
const ImportServersBtn = ({ importServersFromFile }: ServersImporter) => (
{ createServers, fileRef, onImport = () => {} }: ImportServersBtnProps,
) => {
const ref = fileRef ?? useRef<HTMLInputElement>();
const onChange = async ({ target }: ChangeEvent<HTMLInputElement>) =>
importServersFromFile(target.files?.[0])
.then(createServers)
.then(onImport)
.then(() => {
// Reset input after processing file
(target as { value: string | null }).value = null;
});
return (
<React.Fragment>
<button
type="button"
className="btn btn-outline-secondary mr-2"
id="importBtn"
onClick={() => ref.current?.click()}
>
Import from file
</button>
<UncontrolledTooltip placement="top" target="importBtn">
You can create servers by importing a CSV file with columns <b>name</b>, <b>apiKey</b> and <b>url</b>.
</UncontrolledTooltip>
<input type="file" accept="text/csv" className="create-server__csv-select" ref={ref} onChange={onChange} />
</React.Fragment>
);
};
export default ImportServersBtn;

View file

@ -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<RegularServer[]> => {
public importServersFromFile = async (file?: File | null): Promise<RegularServer[]> => {
if (!file || file.type !== CSV_MIME_TYPE) {
throw new Error('No file provided or file is not a CSV');
}

View file

@ -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('<ImportServersBtn />', () => {
let wrapper;
let wrapper: ShallowWrapper;
const onImportMock = jest.fn();
const createServersMock = jest.fn();
const serversImporterMock = {
const serversImporterMock = Mock.of<ServersImporter>({
importServersFromFile: jest.fn().mockResolvedValue([]),
};
});
const click = jest.fn();
const fileRef = {
current: { click: jest.fn() },
current: Mock.of<HTMLInputElement>({ click }),
};
beforeEach(() => {
onImportMock.mockReset();
createServersMock.mockReset();
serversImporterMock.importServersFromFile.mockClear();
fileRef.current.click.mockReset();
jest.clearAllMocks();
const ImportServersBtn = importServersBtnConstruct(serversImporterMock);
@ -39,7 +39,7 @@ describe('<ImportServersBtn />', () => {
btn.simulate('click');
expect(fileRef.current.click).toHaveBeenCalledTimes(1);
expect(click).toHaveBeenCalledTimes(1);
});
it('imports servers when file input changes', (done) => {