mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2025-01-03 14:57:22 +03:00
Added babel plugins to support latest TS functionalities
This commit is contained in:
parent
d65a6ba970
commit
eefea0c37b
9 changed files with 4014 additions and 1123 deletions
5
csvjson.d.ts
vendored
Normal file
5
csvjson.d.ts
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
declare module 'csvjson' {
|
||||||
|
export declare class CsvJson {
|
||||||
|
public toObject<T>(content: string): T[];
|
||||||
|
}
|
||||||
|
}
|
4967
package-lock.json
generated
4967
package-lock.json
generated
File diff suppressed because it is too large
Load diff
13
package.json
13
package.json
|
@ -68,6 +68,8 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.6.2",
|
"@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",
|
"@shlinkio/eslint-config-js-coding-standard": "~1.1.0",
|
||||||
"@stryker-mutator/core": "^3.2.4",
|
"@stryker-mutator/core": "^3.2.4",
|
||||||
"@stryker-mutator/javascript-mutator": "^3.2.4",
|
"@stryker-mutator/javascript-mutator": "^3.2.4",
|
||||||
|
@ -84,7 +86,7 @@
|
||||||
"adm-zip": "^0.4.13",
|
"adm-zip": "^0.4.13",
|
||||||
"autoprefixer": "^9.6.3",
|
"autoprefixer": "^9.6.3",
|
||||||
"babel-core": "7.0.0-bridge.0",
|
"babel-core": "7.0.0-bridge.0",
|
||||||
"babel-jest": "^24.9.0",
|
"babel-jest": "^26.3.0",
|
||||||
"babel-loader": "^8.0.6",
|
"babel-loader": "^8.0.6",
|
||||||
"babel-plugin-named-asset-import": "^0.3.4",
|
"babel-plugin-named-asset-import": "^0.3.4",
|
||||||
"babel-preset-react-app": "^9.0.2",
|
"babel-preset-react-app": "^9.0.2",
|
||||||
|
@ -104,9 +106,9 @@
|
||||||
"fs-extra": "^8.1.0",
|
"fs-extra": "^8.1.0",
|
||||||
"html-webpack-plugin": "^4.0.0-beta.8",
|
"html-webpack-plugin": "^4.0.0-beta.8",
|
||||||
"identity-obj-proxy": "^3.0.0",
|
"identity-obj-proxy": "^3.0.0",
|
||||||
"jest": "^24.9.0",
|
"jest": "^26.4.1",
|
||||||
"jest-pnp-resolver": "^1.2.1",
|
"jest-pnp-resolver": "^1.2.1",
|
||||||
"jest-resolve": "^24.9.0",
|
"jest-resolve": "^26.4.0",
|
||||||
"mini-css-extract-plugin": "^0.8.0",
|
"mini-css-extract-plugin": "^0.8.0",
|
||||||
"node-sass": "^4.12.0",
|
"node-sass": "^4.12.0",
|
||||||
"object-assign": "^4.1.1",
|
"object-assign": "^4.1.1",
|
||||||
|
@ -134,6 +136,7 @@
|
||||||
"sw-precache-webpack-plugin": "^0.11.5",
|
"sw-precache-webpack-plugin": "^0.11.5",
|
||||||
"terser-webpack-plugin": "^2.1.2",
|
"terser-webpack-plugin": "^2.1.2",
|
||||||
"ts-jest": "^26.0.0",
|
"ts-jest": "^26.0.0",
|
||||||
|
"ts-mockery": "^1.2.0",
|
||||||
"typescript": "^3.9.3",
|
"typescript": "^3.9.3",
|
||||||
"url-loader": "^2.2.0",
|
"url-loader": "^2.2.0",
|
||||||
"webpack": "^4.41.0",
|
"webpack": "^4.41.0",
|
||||||
|
@ -145,6 +148,10 @@
|
||||||
"babel": {
|
"babel": {
|
||||||
"presets": [
|
"presets": [
|
||||||
"react-app"
|
"react-app"
|
||||||
|
],
|
||||||
|
"plugins": [
|
||||||
|
"@babel/plugin-proposal-optional-chaining",
|
||||||
|
"@babel/plugin-proposal-nullish-coalescing-operator"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
|
|
15
src/servers/data/index.ts
Normal file
15
src/servers/data/index.ts
Normal 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;
|
|
@ -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);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
26
src/servers/services/ServersImporter.ts
Normal file
26
src/servers/services/ServersImporter.ts
Normal 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);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
|
@ -41,7 +41,8 @@ const provideServices = (bottle, connect, withRouter) => {
|
||||||
|
|
||||||
// Services
|
// Services
|
||||||
bottle.constant('csvjson', csvjson);
|
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');
|
bottle.service('ServersExporter', ServersExporter, 'Storage', 'window', 'csvjson');
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
|
@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
39
test/servers/services/ServersImporter.test.ts
Normal file
39
test/servers/services/ServersImporter.test.ts
Normal 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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in a new issue