Added babel plugins to support latest TS functionalities

This commit is contained in:
Alejandro Celaya 2020-08-22 11:00:11 +02:00
parent d65a6ba970
commit eefea0c37b
9 changed files with 4014 additions and 1123 deletions

5
csvjson.d.ts vendored Normal file
View file

@ -0,0 +1,5 @@
declare module 'csvjson' {
export declare class CsvJson {
public toObject<T>(content: string): T[];
}
}

4967
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -68,6 +68,8 @@
},
"devDependencies": {
"@babel/core": "^7.6.2",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4",
"@babel/plugin-proposal-optional-chaining": "^7.11.0",
"@shlinkio/eslint-config-js-coding-standard": "~1.1.0",
"@stryker-mutator/core": "^3.2.4",
"@stryker-mutator/javascript-mutator": "^3.2.4",
@ -84,7 +86,7 @@
"adm-zip": "^0.4.13",
"autoprefixer": "^9.6.3",
"babel-core": "7.0.0-bridge.0",
"babel-jest": "^24.9.0",
"babel-jest": "^26.3.0",
"babel-loader": "^8.0.6",
"babel-plugin-named-asset-import": "^0.3.4",
"babel-preset-react-app": "^9.0.2",
@ -104,9 +106,9 @@
"fs-extra": "^8.1.0",
"html-webpack-plugin": "^4.0.0-beta.8",
"identity-obj-proxy": "^3.0.0",
"jest": "^24.9.0",
"jest": "^26.4.1",
"jest-pnp-resolver": "^1.2.1",
"jest-resolve": "^24.9.0",
"jest-resolve": "^26.4.0",
"mini-css-extract-plugin": "^0.8.0",
"node-sass": "^4.12.0",
"object-assign": "^4.1.1",
@ -134,6 +136,7 @@
"sw-precache-webpack-plugin": "^0.11.5",
"terser-webpack-plugin": "^2.1.2",
"ts-jest": "^26.0.0",
"ts-mockery": "^1.2.0",
"typescript": "^3.9.3",
"url-loader": "^2.2.0",
"webpack": "^4.41.0",
@ -145,6 +148,10 @@
"babel": {
"presets": [
"react-app"
],
"plugins": [
"@babel/plugin-proposal-optional-chaining",
"@babel/plugin-proposal-nullish-coalescing-operator"
]
},
"browserslist": [

15
src/servers/data/index.ts Normal file
View file

@ -0,0 +1,15 @@
export interface RegularServer {
id: string;
name: string;
url: string;
apiKey: string;
version?: string;
printableVersion?: string;
serverNotReachable?: boolean;
}
interface NotFoundServer {
serverNotFound: true;
}
export type Server = RegularServer | NotFoundServer;

View file

@ -1,23 +0,0 @@
export default class ServersImporter {
constructor(csvjson) {
this.csvjson = csvjson;
}
importServersFromFile = (file) => {
if (!file || file.type !== 'text/csv') {
return Promise.reject('No file provided or file is not a CSV');
}
const reader = new FileReader();
return new Promise((resolve) => {
reader.addEventListener('loadend', (e) => {
const content = e.target.result;
const servers = this.csvjson.toObject(content);
resolve(servers);
});
reader.readAsText(file);
});
};
}

View file

@ -0,0 +1,26 @@
import { CsvJson } from 'csvjson';
import { RegularServer } from '../data';
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[]> => {
if (!file || file.type !== CSV_MIME_TYPE) {
throw new Error('No file provided or file is not a CSV');
}
const reader = this.fileReaderFactory();
return new Promise((resolve) => {
reader.addEventListener('loadend', (e: ProgressEvent<FileReader>) => {
const content = e.target?.result?.toString() ?? '';
const servers = this.csvjson.toObject<RegularServer>(content);
resolve(servers);
});
reader.readAsText(file);
});
};
}

View file

@ -41,7 +41,8 @@ const provideServices = (bottle, connect, withRouter) => {
// Services
bottle.constant('csvjson', csvjson);
bottle.service('ServersImporter', ServersImporter, 'csvjson');
bottle.constant('fileReaderFactory', () => new FileReader());
bottle.service('ServersImporter', ServersImporter, 'csvjson', 'fileReaderFactory');
bottle.service('ServersExporter', ServersExporter, 'Storage', 'window', 'csvjson');
// Actions

View file

@ -1,46 +0,0 @@
import ServersImporter from '../../../src/servers/services/ServersImporter';
describe('ServersImporter', () => {
const servers = [{ name: 'foo' }, { name: 'bar' }];
const csvjsonMock = {
toObject: jest.fn(() => servers),
};
const importer = new ServersImporter(csvjsonMock);
beforeEach(() => csvjsonMock.toObject.mockClear());
describe('importServersFromFile', () => {
it('rejects with error if no file was provided', async () => {
try {
await importer.importServersFromFile();
} catch (e) {
expect(e).toEqual('No file provided or file is not a CSV');
}
});
it('rejects with error if provided file is not a CSV', async () => {
try {
await importer.importServersFromFile({ type: 'text/html' });
} catch (e) {
expect(e).toEqual('No file provided or file is not a CSV');
}
});
it('reads file when a CSV is provided', async () => {
const readAsText = jest.fn(() => '');
global.FileReader = class FileReader {
constructor() {
this.readAsText = readAsText;
this.addEventListener = (eventName, listener) =>
listener({ target: { result: '' } });
}
};
await importer.importServersFromFile({ type: 'text/csv' });
expect(readAsText).toHaveBeenCalledTimes(1);
expect(csvjsonMock.toObject).toHaveBeenCalledTimes(1);
});
});
});

View file

@ -0,0 +1,39 @@
import { Mock } from 'ts-mockery';
import ServersImporter from '../../../src/servers/services/ServersImporter';
import { RegularServer } from '../../../src/servers/data';
describe('ServersImporter', () => {
const servers: RegularServer[] = [ Mock.all<RegularServer>(), Mock.all<RegularServer>() ];
const csvjsonMock = {
toObject: jest.fn().mockReturnValue(servers),
};
const readAsText = jest.fn();
const fileReaderMock = Mock.of<FileReader>({
readAsText,
addEventListener: (_eventName: string, listener: Function) => listener({ target: { result: '' } }),
});
const importer = new ServersImporter(csvjsonMock, () => fileReaderMock);
beforeEach(jest.clearAllMocks);
describe('importServersFromFile', () => {
it('rejects with error if no file was provided', async () => {
await expect(importer.importServersFromFile()).rejects.toEqual(
new Error('No file provided or file is not a CSV'),
);
});
it('rejects with error if provided file is not a CSV', async () => {
await expect(importer.importServersFromFile(Mock.of<File>({ type: 'text/html' }))).rejects.toEqual(
new Error('No file provided or file is not a CSV'),
);
});
it('reads file when a CSV is provided', async () => {
await importer.importServersFromFile(Mock.of<File>({ type: 'text/csv' }));
expect(readAsText).toHaveBeenCalledTimes(1);
expect(csvjsonMock.toObject).toHaveBeenCalledTimes(1);
});
});
});