mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2024-12-23 17:40:23 +03:00
Merge pull request #513 from acelaya-forks/feature/update-test-deps
Feature/update test deps
This commit is contained in:
commit
16d2e437b6
20 changed files with 3690 additions and 11648 deletions
15060
package-lock.json
generated
15060
package-lock.json
generated
File diff suppressed because it is too large
Load diff
20
package.json
20
package.json
|
@ -69,13 +69,13 @@
|
||||||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.8",
|
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.8",
|
||||||
"@babel/plugin-proposal-optional-chaining": "^7.13.8",
|
"@babel/plugin-proposal-optional-chaining": "^7.13.8",
|
||||||
"@shlinkio/eslint-config-js-coding-standard": "~1.2.2",
|
"@shlinkio/eslint-config-js-coding-standard": "~1.2.2",
|
||||||
"@stryker-mutator/core": "^5.0.0",
|
"@stryker-mutator/core": "^5.4.1",
|
||||||
"@stryker-mutator/jest-runner": "^5.0.0",
|
"@stryker-mutator/jest-runner": "^5.4.1",
|
||||||
"@stryker-mutator/typescript-checker": "^5.0.0",
|
"@stryker-mutator/typescript-checker": "^5.4.1",
|
||||||
"@svgr/webpack": "^5.5.0",
|
"@svgr/webpack": "^5.5.0",
|
||||||
"@types/classnames": "^2.2.11",
|
"@types/classnames": "^2.2.11",
|
||||||
"@types/enzyme": "^3.10.10",
|
"@types/enzyme": "^3.10.10",
|
||||||
"@types/jest": "^26.0.20",
|
"@types/jest": "^27.0.2",
|
||||||
"@types/leaflet": "^1.5.23",
|
"@types/leaflet": "^1.5.23",
|
||||||
"@types/qs": "^6.9.5",
|
"@types/qs": "^6.9.5",
|
||||||
"@types/ramda": "^0.27.38",
|
"@types/ramda": "^0.27.38",
|
||||||
|
@ -93,14 +93,14 @@
|
||||||
"adm-zip": "^0.4.16",
|
"adm-zip": "^0.4.16",
|
||||||
"autoprefixer": "^10.0.2",
|
"autoprefixer": "^10.0.2",
|
||||||
"babel-core": "7.0.0-bridge.0",
|
"babel-core": "7.0.0-bridge.0",
|
||||||
"babel-jest": "^26.6.3",
|
"babel-jest": "^27.3.1",
|
||||||
"babel-loader": "^8.2.1",
|
"babel-loader": "^8.2.1",
|
||||||
"babel-plugin-named-asset-import": "^0.3.7",
|
"babel-plugin-named-asset-import": "^0.3.7",
|
||||||
"babel-preset-react-app": "^10.0.0",
|
"babel-preset-react-app": "^10.0.0",
|
||||||
"babel-runtime": "^6.26.0",
|
"babel-runtime": "^6.26.0",
|
||||||
"bfj": "^7.0.2",
|
"bfj": "^7.0.2",
|
||||||
"case-sensitive-paths-webpack-plugin": "^2.3.0",
|
"case-sensitive-paths-webpack-plugin": "^2.3.0",
|
||||||
"chalk": "^4.1.0",
|
"chalk": "^4.1.2",
|
||||||
"css-loader": "^5.0.1",
|
"css-loader": "^5.0.1",
|
||||||
"dart-sass": "^1.25.0",
|
"dart-sass": "^1.25.0",
|
||||||
"dotenv": "^8.2.0",
|
"dotenv": "^8.2.0",
|
||||||
|
@ -113,9 +113,9 @@
|
||||||
"fs-extra": "^9.0.1",
|
"fs-extra": "^9.0.1",
|
||||||
"html-webpack-plugin": "^4.5.0",
|
"html-webpack-plugin": "^4.5.0",
|
||||||
"identity-obj-proxy": "^3.0.0",
|
"identity-obj-proxy": "^3.0.0",
|
||||||
"jest": "^26.6.3",
|
"jest": "^27.3.1",
|
||||||
"jest-pnp-resolver": "^1.2.2",
|
"jest-pnp-resolver": "^1.2.2",
|
||||||
"jest-resolve": "^26.6.2",
|
"jest-resolve": "^27.3.1",
|
||||||
"mini-css-extract-plugin": "^1.3.1",
|
"mini-css-extract-plugin": "^1.3.1",
|
||||||
"object-assign": "^4.1.1",
|
"object-assign": "^4.1.1",
|
||||||
"optimize-css-assets-webpack-plugin": "^5.0.4",
|
"optimize-css-assets-webpack-plugin": "^5.0.4",
|
||||||
|
@ -141,9 +141,9 @@
|
||||||
"stylelint-scss": "^3.18.0",
|
"stylelint-scss": "^3.18.0",
|
||||||
"sw-precache-webpack-plugin": "^1.0.0",
|
"sw-precache-webpack-plugin": "^1.0.0",
|
||||||
"terser-webpack-plugin": "^4.2.3",
|
"terser-webpack-plugin": "^4.2.3",
|
||||||
"ts-jest": "^26.5.2",
|
"ts-jest": "^27.0.7",
|
||||||
"ts-mockery": "^1.2.0",
|
"ts-mockery": "^1.2.0",
|
||||||
"typescript": "^4.2.2",
|
"typescript": "^4.4.4",
|
||||||
"url-loader": "^4.1.1",
|
"url-loader": "^4.1.1",
|
||||||
"webpack": "^4.44.2",
|
"webpack": "^4.44.2",
|
||||||
"webpack-dev-server": "^3.11.0",
|
"webpack-dev-server": "^3.11.0",
|
||||||
|
|
|
@ -125,7 +125,7 @@ export default class ShlinkApiClient {
|
||||||
data: body,
|
data: body,
|
||||||
paramsSerializer: stringifyQuery,
|
paramsSerializer: stringifyQuery,
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e: any) {
|
||||||
const { response } = e;
|
const { response } = e;
|
||||||
|
|
||||||
// Due to a bug on all previous Shlink versions, requests to non-matching URLs will always result on a CORS error
|
// Due to a bug on all previous Shlink versions, requests to non-matching URLs will always result on a CORS error
|
||||||
|
|
|
@ -27,7 +27,7 @@ export const editDomainRedirects = (buildShlinkApiClient: ShlinkApiClientBuilder
|
||||||
const redirects = await editDomainRedirects({ domain, ...domainRedirects });
|
const redirects = await editDomainRedirects({ domain, ...domainRedirects });
|
||||||
|
|
||||||
dispatch<EditDomainRedirectsAction>({ type: EDIT_DOMAIN_REDIRECTS, domain, redirects });
|
dispatch<EditDomainRedirectsAction>({ type: EDIT_DOMAIN_REDIRECTS, domain, redirects });
|
||||||
} catch (e) {
|
} catch (e: any) {
|
||||||
dispatch<ApiErrorAction>({ type: EDIT_DOMAIN_REDIRECTS_ERROR, errorData: parseApiError(e) });
|
dispatch<ApiErrorAction>({ type: EDIT_DOMAIN_REDIRECTS_ERROR, errorData: parseApiError(e) });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -71,7 +71,7 @@ export const listDomains = (buildShlinkApiClient: ShlinkApiClientBuilder) => ()
|
||||||
const domains = await listDomains();
|
const domains = await listDomains();
|
||||||
|
|
||||||
dispatch<ListDomainsAction>({ type: LIST_DOMAINS, domains });
|
dispatch<ListDomainsAction>({ type: LIST_DOMAINS, domains });
|
||||||
} catch (e) {
|
} catch (e: any) {
|
||||||
dispatch<ApiErrorAction>({ type: LIST_DOMAINS_ERROR, errorData: parseApiError(e) });
|
dispatch<ApiErrorAction>({ type: LIST_DOMAINS_ERROR, errorData: parseApiError(e) });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { useRef, RefObject, ChangeEvent, MutableRefObject, FC } from 'react';
|
import { useRef, RefObject, ChangeEvent, MutableRefObject, FC } from 'react';
|
||||||
import { Button, UncontrolledTooltip } from 'reactstrap';
|
import { Button, UncontrolledTooltip } from 'reactstrap';
|
||||||
|
import { pipe } from 'ramda';
|
||||||
import { faFileUpload as importIcon } from '@fortawesome/free-solid-svg-icons';
|
import { faFileUpload as importIcon } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import ServersImporter from '../services/ServersImporter';
|
import ServersImporter from '../services/ServersImporter';
|
||||||
|
@ -32,8 +33,7 @@ const ImportServersBtn = ({ importServersFromFile }: ServersImporter): FC<Import
|
||||||
const ref = fileRef ?? useRef<HTMLInputElement>();
|
const ref = fileRef ?? useRef<HTMLInputElement>();
|
||||||
const onChange = async ({ target }: ChangeEvent<HTMLInputElement>) =>
|
const onChange = async ({ target }: ChangeEvent<HTMLInputElement>) =>
|
||||||
importServersFromFile(target.files?.[0])
|
importServersFromFile(target.files?.[0])
|
||||||
.then(createServers)
|
.then(pipe(createServers, onImport))
|
||||||
.then(onImport)
|
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Reset input after processing file
|
// Reset input after processing file
|
||||||
(target as { value: string | null }).value = null;
|
(target as { value: string | null }).value = null;
|
||||||
|
|
|
@ -2,24 +2,17 @@ import { pipe, prop } from 'ramda';
|
||||||
import { AxiosInstance } from 'axios';
|
import { AxiosInstance } from 'axios';
|
||||||
import { Dispatch } from 'redux';
|
import { Dispatch } from 'redux';
|
||||||
import { homepage } from '../../../package.json';
|
import { homepage } from '../../../package.json';
|
||||||
import { ServerData } from '../data';
|
import { hasServerData, ServerData } from '../data';
|
||||||
import { createServers } from './servers';
|
import { createServers } from './servers';
|
||||||
|
|
||||||
const responseToServersList = pipe(
|
const responseToServersList = pipe(
|
||||||
prop<any, any>('data'),
|
prop<any, any>('data'),
|
||||||
(data: any): ServerData[] => {
|
(data: any): ServerData[] => Array.isArray(data) ? data.filter(hasServerData) : [],
|
||||||
if (!Array.isArray(data)) {
|
|
||||||
throw new Error('Value is not an array');
|
|
||||||
}
|
|
||||||
|
|
||||||
return data as ServerData[];
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
export const fetchServers = ({ get }: AxiosInstance) => () => async (dispatch: Dispatch) => {
|
export const fetchServers = ({ get }: AxiosInstance) => () => async (dispatch: Dispatch) => {
|
||||||
const remoteList = await get(`${homepage}/servers.json`)
|
const resp = await get(`${homepage}/servers.json`);
|
||||||
.then(responseToServersList)
|
const remoteList = responseToServersList(resp);
|
||||||
.catch(() => []);
|
|
||||||
|
|
||||||
dispatch(createServers(remoteList));
|
dispatch(createServers(remoteList));
|
||||||
};
|
};
|
||||||
|
|
|
@ -49,7 +49,7 @@ export const createShortUrl = (buildShlinkApiClient: ShlinkApiClientBuilder) =>
|
||||||
const result = await createShortUrl(data);
|
const result = await createShortUrl(data);
|
||||||
|
|
||||||
dispatch<CreateShortUrlAction>({ type: CREATE_SHORT_URL, result });
|
dispatch<CreateShortUrlAction>({ type: CREATE_SHORT_URL, result });
|
||||||
} catch (e) {
|
} catch (e: any) {
|
||||||
dispatch<ApiErrorAction>({ type: CREATE_SHORT_URL_ERROR, errorData: parseApiError(e) });
|
dispatch<ApiErrorAction>({ type: CREATE_SHORT_URL_ERROR, errorData: parseApiError(e) });
|
||||||
|
|
||||||
throw e;
|
throw e;
|
||||||
|
|
|
@ -48,7 +48,7 @@ export const deleteShortUrl = (buildShlinkApiClient: ShlinkApiClientBuilder) =>
|
||||||
try {
|
try {
|
||||||
await deleteShortUrl(shortCode, domain);
|
await deleteShortUrl(shortCode, domain);
|
||||||
dispatch<DeleteShortUrlAction>({ type: SHORT_URL_DELETED, shortCode, domain });
|
dispatch<DeleteShortUrlAction>({ type: SHORT_URL_DELETED, shortCode, domain });
|
||||||
} catch (e) {
|
} catch (e: any) {
|
||||||
dispatch<ApiErrorAction>({ type: DELETE_SHORT_URL_ERROR, errorData: parseApiError(e) });
|
dispatch<ApiErrorAction>({ type: DELETE_SHORT_URL_ERROR, errorData: parseApiError(e) });
|
||||||
|
|
||||||
throw e;
|
throw e;
|
||||||
|
|
|
@ -50,7 +50,7 @@ export const getShortUrlDetail = (buildShlinkApiClient: ShlinkApiClientBuilder)
|
||||||
) ?? await buildShlinkApiClient(getState).getShortUrl(shortCode, domain);
|
) ?? await buildShlinkApiClient(getState).getShortUrl(shortCode, domain);
|
||||||
|
|
||||||
dispatch<ShortUrlDetailAction>({ shortUrl, type: GET_SHORT_URL_DETAIL });
|
dispatch<ShortUrlDetailAction>({ shortUrl, type: GET_SHORT_URL_DETAIL });
|
||||||
} catch (e) {
|
} catch (e: any) {
|
||||||
dispatch<ApiErrorAction>({ type: GET_SHORT_URL_DETAIL_ERROR, errorData: parseApiError(e) });
|
dispatch<ApiErrorAction>({ type: GET_SHORT_URL_DETAIL_ERROR, errorData: parseApiError(e) });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -55,7 +55,7 @@ export const editShortUrl = (buildShlinkApiClient: ShlinkApiClientBuilder) => (
|
||||||
]);
|
]);
|
||||||
|
|
||||||
dispatch<ShortUrlEditedAction>({ shortUrl, type: SHORT_URL_EDITED });
|
dispatch<ShortUrlEditedAction>({ shortUrl, type: SHORT_URL_EDITED });
|
||||||
} catch (e) {
|
} catch (e: any) {
|
||||||
dispatch<ApiErrorAction>({ type: EDIT_SHORT_URL_ERROR, errorData: parseApiError(e) });
|
dispatch<ApiErrorAction>({ type: EDIT_SHORT_URL_ERROR, errorData: parseApiError(e) });
|
||||||
|
|
||||||
throw e;
|
throw e;
|
||||||
|
|
|
@ -44,7 +44,7 @@ export const deleteTag = (buildShlinkApiClient: ShlinkApiClientBuilder) => (tag:
|
||||||
try {
|
try {
|
||||||
await deleteTags([ tag ]);
|
await deleteTags([ tag ]);
|
||||||
dispatch({ type: DELETE_TAG });
|
dispatch({ type: DELETE_TAG });
|
||||||
} catch (e) {
|
} catch (e: any) {
|
||||||
dispatch<ApiErrorAction>({ type: DELETE_TAG_ERROR, errorData: parseApiError(e) });
|
dispatch<ApiErrorAction>({ type: DELETE_TAG_ERROR, errorData: parseApiError(e) });
|
||||||
|
|
||||||
throw e;
|
throw e;
|
||||||
|
|
|
@ -59,7 +59,7 @@ export const editTag = (buildShlinkApiClient: ShlinkApiClientBuilder, colorGener
|
||||||
await editTag(oldName, newName);
|
await editTag(oldName, newName);
|
||||||
colorGenerator.setColorForKey(newName, color);
|
colorGenerator.setColorForKey(newName, color);
|
||||||
dispatch({ type: EDIT_TAG, oldName, newName });
|
dispatch({ type: EDIT_TAG, oldName, newName });
|
||||||
} catch (e) {
|
} catch (e: any) {
|
||||||
dispatch<ApiErrorAction>({ type: EDIT_TAG_ERROR, errorData: parseApiError(e) });
|
dispatch<ApiErrorAction>({ type: EDIT_TAG_ERROR, errorData: parseApiError(e) });
|
||||||
|
|
||||||
throw e;
|
throw e;
|
||||||
|
|
|
@ -126,7 +126,7 @@ export const listTags = (buildShlinkApiClient: ShlinkApiClientBuilder, force = t
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
dispatch<ListTagsAction>({ tags, stats: processedStats, type: LIST_TAGS });
|
dispatch<ListTagsAction>({ tags, stats: processedStats, type: LIST_TAGS });
|
||||||
} catch (e) {
|
} catch (e: any) {
|
||||||
dispatch<ApiErrorAction>({ type: LIST_TAGS_ERROR, errorData: parseApiError(e) });
|
dispatch<ApiErrorAction>({ type: LIST_TAGS_ERROR, errorData: parseApiError(e) });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -72,7 +72,7 @@ export const getVisitsWithLoader = async <T extends Action<string> & { visits: V
|
||||||
const visits = await loadVisits();
|
const visits = await loadVisits();
|
||||||
|
|
||||||
dispatch({ ...extraFinishActionData, visits, type: actionMap.finish });
|
dispatch({ ...extraFinishActionData, visits, type: actionMap.finish });
|
||||||
} catch (e) {
|
} catch (e: any) {
|
||||||
dispatch<ApiErrorAction>({ type: actionMap.error, errorData: parseApiError(e) });
|
dispatch<ApiErrorAction>({ type: actionMap.error, errorData: parseApiError(e) });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,9 +9,8 @@ describe('<ImportServersBtn />', () => {
|
||||||
let wrapper: ShallowWrapper;
|
let wrapper: ShallowWrapper;
|
||||||
const onImportMock = jest.fn();
|
const onImportMock = jest.fn();
|
||||||
const createServersMock = jest.fn();
|
const createServersMock = jest.fn();
|
||||||
const serversImporterMock = Mock.of<ServersImporter>({
|
const importServersFromFile = jest.fn().mockResolvedValue([]);
|
||||||
importServersFromFile: jest.fn().mockResolvedValue([]),
|
const serversImporterMock = Mock.of<ServersImporter>({ importServersFromFile });
|
||||||
});
|
|
||||||
const click = jest.fn();
|
const click = jest.fn();
|
||||||
const fileRef = {
|
const fileRef = {
|
||||||
current: Mock.of<HTMLInputElement>({ click }),
|
current: Mock.of<HTMLInputElement>({ click }),
|
||||||
|
@ -76,17 +75,14 @@ describe('<ImportServersBtn />', () => {
|
||||||
expect(click).toHaveBeenCalledTimes(1);
|
expect(click).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('imports servers when file input changes', (done) => {
|
it('imports servers when file input changes', async () => {
|
||||||
const wrapper = createWrapper();
|
const wrapper = createWrapper();
|
||||||
const file = wrapper.find('.import-servers-btn__csv-select');
|
const file = wrapper.find('.import-servers-btn__csv-select');
|
||||||
|
|
||||||
file.simulate('change', { target: { files: [ '' ] } });
|
await file.simulate('change', { target: { files: [ '' ] } }); // eslint-disable-line @typescript-eslint/await-thenable
|
||||||
|
|
||||||
setImmediate(() => {
|
expect(importServersFromFile).toHaveBeenCalledTimes(1);
|
||||||
expect(serversImporterMock.importServersFromFile).toHaveBeenCalledTimes(1);
|
|
||||||
expect(createServersMock).toHaveBeenCalledTimes(1);
|
expect(createServersMock).toHaveBeenCalledTimes(1);
|
||||||
expect(onImportMock).toHaveBeenCalledTimes(1);
|
expect(onImportMock).toHaveBeenCalledTimes(1);
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { fetchServers } from '../../../src/servers/reducers/remoteServers';
|
||||||
import { CREATE_SERVERS } from '../../../src/servers/reducers/servers';
|
import { CREATE_SERVERS } from '../../../src/servers/reducers/servers';
|
||||||
|
|
||||||
describe('remoteServersReducer', () => {
|
describe('remoteServersReducer', () => {
|
||||||
afterEach(jest.resetAllMocks);
|
afterEach(jest.clearAllMocks);
|
||||||
|
|
||||||
describe('fetchServers', () => {
|
describe('fetchServers', () => {
|
||||||
const get = jest.fn();
|
const get = jest.fn();
|
||||||
|
@ -13,7 +13,7 @@ describe('remoteServersReducer', () => {
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[
|
[
|
||||||
Promise.resolve({
|
{
|
||||||
data: [
|
data: [
|
||||||
{
|
{
|
||||||
id: '111',
|
id: '111',
|
||||||
|
@ -28,7 +28,7 @@ describe('remoteServersReducer', () => {
|
||||||
apiKey: '7a531c75-134e-4d5c-86e0-a71b7167b57a',
|
apiKey: '7a531c75-134e-4d5c-86e0-a71b7167b57a',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
},
|
||||||
{
|
{
|
||||||
111: {
|
111: {
|
||||||
id: '111',
|
id: '111',
|
||||||
|
@ -44,14 +44,50 @@ describe('remoteServersReducer', () => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[ Promise.resolve('<html></html>'), {}],
|
[
|
||||||
[ Promise.reject({}), {}],
|
{
|
||||||
])('tries to fetch servers from remote', async (mockedValue, expectedList) => {
|
data: [
|
||||||
get.mockReturnValue(mockedValue);
|
{
|
||||||
|
id: '111',
|
||||||
|
name: 'acel.me from servers.json',
|
||||||
|
url: 'https://acel.me',
|
||||||
|
apiKey: '07fb8a96-8059-4094-a24c-80a7d5e7e9b0',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '222',
|
||||||
|
name: 'Invalid',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '333',
|
||||||
|
name: 'Local from servers.json',
|
||||||
|
url: 'http://localhost:8000',
|
||||||
|
apiKey: '7a531c75-134e-4d5c-86e0-a71b7167b57a',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
111: {
|
||||||
|
id: '111',
|
||||||
|
name: 'acel.me from servers.json',
|
||||||
|
url: 'https://acel.me',
|
||||||
|
apiKey: '07fb8a96-8059-4094-a24c-80a7d5e7e9b0',
|
||||||
|
},
|
||||||
|
333: {
|
||||||
|
id: '333',
|
||||||
|
name: 'Local from servers.json',
|
||||||
|
url: 'http://localhost:8000',
|
||||||
|
apiKey: '7a531c75-134e-4d5c-86e0-a71b7167b57a',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[ '<html></html>', {}],
|
||||||
|
[{}, {}],
|
||||||
|
])('tries to fetch servers from remote', async (mockedValue, expectedNewServers) => {
|
||||||
|
get.mockResolvedValue(mockedValue);
|
||||||
|
|
||||||
await fetchServers(axios)()(dispatch);
|
await fetchServers(axios)()(dispatch);
|
||||||
|
|
||||||
expect(dispatch).toHaveBeenCalledWith({ type: CREATE_SERVERS, newServers: expectedList });
|
expect(dispatch).toHaveBeenCalledWith({ type: CREATE_SERVERS, newServers: expectedNewServers });
|
||||||
expect(get).toHaveBeenCalledTimes(1);
|
expect(get).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -59,41 +59,29 @@ describe('<DeleteShortUrlModal />', () => {
|
||||||
expect(submit.html()).toContain('Deleting...');
|
expect(submit.html()).toContain('Deleting...');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('enables submit button when proper short code is provided', (done) => {
|
it('enables submit button when proper short code is provided', () => {
|
||||||
const shortCode = 'abc123';
|
const shortCode = 'abc123';
|
||||||
const wrapper = createWrapper({
|
const wrapper = createWrapper({
|
||||||
loading: false,
|
loading: false,
|
||||||
error: false,
|
error: false,
|
||||||
shortCode,
|
shortCode,
|
||||||
});
|
});
|
||||||
const input = wrapper.find('.form-control');
|
|
||||||
|
|
||||||
input.simulate('change', { target: { value: shortCode } });
|
expect(wrapper.find('.btn-danger').prop('disabled')).toEqual(true);
|
||||||
setImmediate(() => {
|
wrapper.find('.form-control').simulate('change', { target: { value: shortCode } });
|
||||||
const submit = wrapper.find('.btn-danger');
|
expect(wrapper.find('.btn-danger').prop('disabled')).toEqual(false);
|
||||||
|
|
||||||
expect(submit.prop('disabled')).toEqual(false);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('tries to delete short URL when form is submit', (done) => {
|
it('tries to delete short URL when form is submit', () => {
|
||||||
const shortCode = 'abc123';
|
const shortCode = 'abc123';
|
||||||
const wrapper = createWrapper({
|
const wrapper = createWrapper({
|
||||||
loading: false,
|
loading: false,
|
||||||
error: false,
|
error: false,
|
||||||
shortCode,
|
shortCode,
|
||||||
});
|
});
|
||||||
const input = wrapper.find('.form-control');
|
|
||||||
|
|
||||||
input.simulate('change', { target: { value: shortCode } });
|
|
||||||
setImmediate(() => {
|
|
||||||
const form = wrapper.find('form');
|
|
||||||
|
|
||||||
expect(deleteShortUrl).not.toHaveBeenCalled();
|
expect(deleteShortUrl).not.toHaveBeenCalled();
|
||||||
form.simulate('submit', { preventDefault: identity });
|
wrapper.find('form').simulate('submit', { preventDefault: identity });
|
||||||
expect(deleteShortUrl).toHaveBeenCalledTimes(1);
|
expect(deleteShortUrl).toHaveBeenCalledTimes(1);
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -40,32 +40,30 @@ describe('<SortableBarChartCard />', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('renders properly ordered stats when ordering is set', () => {
|
describe('renders properly ordered stats when ordering is set', () => {
|
||||||
let assert: (sortName: string, sortDir: OrderDir, keys: string[], values: number[], done: Function) => void;
|
let assert: (sortName: string, sortDir: OrderDir, keys: string[], values: number[]) => void;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const wrapper = createWrapper();
|
const wrapper = createWrapper();
|
||||||
const dropdown = wrapper.renderProp('title' as never)().find(SortingDropdown);
|
const dropdown = wrapper.renderProp('title' as never)().find(SortingDropdown);
|
||||||
|
|
||||||
assert = (sortName: string, sortDir: OrderDir, keys: string[], values: number[], done: Function) => {
|
assert = (sortName: string, sortDir: OrderDir, keys: string[], values: number[]) => {
|
||||||
dropdown.prop('onChange')(sortName, sortDir);
|
dropdown.prop('onChange')(sortName, sortDir);
|
||||||
setImmediate(() => {
|
|
||||||
const stats = wrapper.find(HorizontalBarChart).prop('stats');
|
const stats = wrapper.find(HorizontalBarChart).prop('stats');
|
||||||
|
|
||||||
expect(Object.keys(stats)).toEqual(keys);
|
expect(Object.keys(stats)).toEqual(keys);
|
||||||
expect(Object.values(stats)).toEqual(values);
|
expect(Object.values(stats)).toEqual(values);
|
||||||
done();
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
it('name - ASC', (done) => assert('name', 'ASC', [ 'Bar', 'Foo' ], [ 50, 100 ], done));
|
it('name - ASC', () => assert('name', 'ASC', [ 'Bar', 'Foo' ], [ 50, 100 ]));
|
||||||
it('name - DESC', (done) => assert('name', 'DESC', [ 'Foo', 'Bar' ], [ 100, 50 ], done));
|
it('name - DESC', () => assert('name', 'DESC', [ 'Foo', 'Bar' ], [ 100, 50 ]));
|
||||||
it('value - ASC', (done) => assert('value', 'ASC', [ 'Bar', 'Foo' ], [ 50, 100 ], done));
|
it('value - ASC', () => assert('value', 'ASC', [ 'Bar', 'Foo' ], [ 50, 100 ]));
|
||||||
it('value - DESC', (done) => assert('value', 'DESC', [ 'Foo', 'Bar' ], [ 100, 50 ], done));
|
it('value - DESC', () => assert('value', 'DESC', [ 'Foo', 'Bar' ], [ 100, 50 ]));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('renders properly paginated stats when pagination is set', () => {
|
describe('renders properly paginated stats when pagination is set', () => {
|
||||||
let assert: (itemsPerPage: number, expectedStats: string[], done: Function) => void;
|
let assert: (itemsPerPage: number, expectedStats: string[]) => void;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const wrapper = createWrapper(true, range(1, 159).reduce<Stats>((accum, value) => {
|
const wrapper = createWrapper(true, range(1, 159).reduce<Stats>((accum, value) => {
|
||||||
|
@ -75,23 +73,21 @@ describe('<SortableBarChartCard />', () => {
|
||||||
}, {}));
|
}, {}));
|
||||||
const dropdown = wrapper.renderProp('title' as never)().find(PaginationDropdown);
|
const dropdown = wrapper.renderProp('title' as never)().find(PaginationDropdown);
|
||||||
|
|
||||||
assert = (itemsPerPage: number, expectedStats: string[], done: Function) => {
|
assert = (itemsPerPage: number, expectedStats: string[]) => {
|
||||||
dropdown.prop('setValue')(itemsPerPage);
|
dropdown.prop('setValue')(itemsPerPage);
|
||||||
setImmediate(() => {
|
|
||||||
const stats = wrapper.find(HorizontalBarChart).prop('stats');
|
const stats = wrapper.find(HorizontalBarChart).prop('stats');
|
||||||
|
|
||||||
expect(Object.keys(stats)).toEqual(expectedStats);
|
expect(Object.keys(stats)).toEqual(expectedStats);
|
||||||
done();
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const buildExpected = (size: number): string[] => [ 'Foo', 'Bar', ...rangeOf(size - 2, (i) => `key_${i}`) ];
|
const buildExpected = (size: number): string[] => [ 'Foo', 'Bar', ...rangeOf(size - 2, (i) => `key_${i}`) ];
|
||||||
|
|
||||||
it('50 items per page', (done) => assert(50, buildExpected(50), done));
|
it('50 items per page', () => assert(50, buildExpected(50)));
|
||||||
it('100 items per page', (done) => assert(100, buildExpected(100), done));
|
it('100 items per page', () => assert(100, buildExpected(100)));
|
||||||
it('200 items per page', (done) => assert(200, buildExpected(160), done));
|
it('200 items per page', () => assert(200, buildExpected(160)));
|
||||||
it('500 items per page', (done) => assert(500, buildExpected(160), done));
|
it('500 items per page', () => assert(500, buildExpected(160)));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders extra header content', () => {
|
it('renders extra header content', () => {
|
||||||
|
|
|
@ -33,33 +33,21 @@ describe('<OpenMapModalBtn />', () => {
|
||||||
expect(modal).toHaveLength(1);
|
expect(modal).toHaveLength(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('opens dropdown instead of modal when a list of active cities has been provided', (done) => {
|
it('opens dropdown instead of modal when a list of active cities has been provided', () => {
|
||||||
const wrapper = createWrapper([ 'bar' ]);
|
const wrapper = createWrapper([ 'bar' ]);
|
||||||
const button = wrapper.find('.open-map-modal-btn__btn');
|
|
||||||
|
|
||||||
button.simulate('click');
|
wrapper.find('.open-map-modal-btn__btn').simulate('click');
|
||||||
|
|
||||||
setImmediate(() => {
|
expect(wrapper.find(Dropdown).prop('isOpen')).toEqual(true);
|
||||||
const dropdown = wrapper.find(Dropdown);
|
expect(wrapper.find(MapModal).prop('isOpen')).toEqual(false);
|
||||||
const modal = wrapper.find(MapModal);
|
|
||||||
|
|
||||||
expect(dropdown.prop('isOpen')).toEqual(true);
|
|
||||||
expect(modal.prop('isOpen')).toEqual(false);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('filters out non-active cities from list of locations', (done) => {
|
it('filters out non-active cities from list of locations', () => {
|
||||||
const wrapper = createWrapper([ 'bar' ]);
|
const wrapper = createWrapper([ 'bar' ]);
|
||||||
const button = wrapper.find('.open-map-modal-btn__btn');
|
|
||||||
|
|
||||||
button.simulate('click');
|
wrapper.find('.open-map-modal-btn__btn').simulate('click');
|
||||||
setImmediate(() => {
|
wrapper.find(Dropdown).find(DropdownItem).at(1).simulate('click');
|
||||||
const dropdown = wrapper.find(Dropdown);
|
|
||||||
const item = dropdown.find(DropdownItem).at(1);
|
|
||||||
|
|
||||||
item.simulate('click');
|
|
||||||
setImmediate(() => {
|
|
||||||
const modal = wrapper.find(MapModal);
|
const modal = wrapper.find(MapModal);
|
||||||
|
|
||||||
expect(modal.prop('title')).toEqual(title);
|
expect(modal.prop('title')).toEqual(title);
|
||||||
|
@ -69,8 +57,5 @@ describe('<OpenMapModalBtn />', () => {
|
||||||
count: 45,
|
count: 45,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue