mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2024-12-23 17:40:23 +03:00
Merge pull request #825 from acelaya-forks/feature/shoehorn
Introduce shoehorn as a possible replacement for ts-mockery
This commit is contained in:
commit
22905a2efc
108 changed files with 701 additions and 782 deletions
27
package-lock.json
generated
27
package-lock.json
generated
|
@ -60,6 +60,7 @@
|
||||||
"@testing-library/jest-dom": "^5.16.5",
|
"@testing-library/jest-dom": "^5.16.5",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^13.4.0",
|
||||||
"@testing-library/user-event": "^14.4.3",
|
"@testing-library/user-event": "^14.4.3",
|
||||||
|
"@total-typescript/shoehorn": "^0.1.0",
|
||||||
"@types/jest": "^29.2.4",
|
"@types/jest": "^29.2.4",
|
||||||
"@types/json2csv": "^5.0.3",
|
"@types/json2csv": "^5.0.3",
|
||||||
"@types/leaflet": "^1.9.0",
|
"@types/leaflet": "^1.9.0",
|
||||||
|
@ -84,7 +85,6 @@
|
||||||
"resize-observer-polyfill": "^1.5.1",
|
"resize-observer-polyfill": "^1.5.1",
|
||||||
"sass": "^1.57.1",
|
"sass": "^1.57.1",
|
||||||
"stylelint": "^14.16.0",
|
"stylelint": "^14.16.0",
|
||||||
"ts-mockery": "^1.2.0",
|
|
||||||
"typescript": "^5.0.2",
|
"typescript": "^5.0.2",
|
||||||
"vite": "^4.2.0",
|
"vite": "^4.2.0",
|
||||||
"vite-plugin-pwa": "^0.14.4"
|
"vite-plugin-pwa": "^0.14.4"
|
||||||
|
@ -3563,6 +3563,12 @@
|
||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@total-typescript/shoehorn": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@total-typescript/shoehorn/-/shoehorn-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-XKig6hXxWnUh0fsW3LR2vxpxwLlPFokfOSR0riHKA9uXvdHDfwOOPdAOi4U/YNKLmgYUu/plUfnF3yiAAz1+Zg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@types/aria-query": {
|
"node_modules/@types/aria-query": {
|
||||||
"version": "4.2.2",
|
"version": "4.2.2",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
@ -11895,14 +11901,6 @@
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ts-mockery": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"peerDependencies": {
|
|
||||||
"typescript": ">= 2.8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ts-toolbelt": {
|
"node_modules/ts-toolbelt": {
|
||||||
"version": "6.15.5",
|
"version": "6.15.5",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
@ -14987,6 +14985,12 @@
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@total-typescript/shoehorn": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@total-typescript/shoehorn/-/shoehorn-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-XKig6hXxWnUh0fsW3LR2vxpxwLlPFokfOSR0riHKA9uXvdHDfwOOPdAOi4U/YNKLmgYUu/plUfnF3yiAAz1+Zg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/aria-query": {
|
"@types/aria-query": {
|
||||||
"version": "4.2.2",
|
"version": "4.2.2",
|
||||||
"dev": true
|
"dev": true
|
||||||
|
@ -20275,11 +20279,6 @@
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"ts-mockery": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {}
|
|
||||||
},
|
|
||||||
"ts-toolbelt": {
|
"ts-toolbelt": {
|
||||||
"version": "6.15.5",
|
"version": "6.15.5",
|
||||||
"dev": true
|
"dev": true
|
||||||
|
|
|
@ -77,6 +77,7 @@
|
||||||
"@testing-library/jest-dom": "^5.16.5",
|
"@testing-library/jest-dom": "^5.16.5",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^13.4.0",
|
||||||
"@testing-library/user-event": "^14.4.3",
|
"@testing-library/user-event": "^14.4.3",
|
||||||
|
"@total-typescript/shoehorn": "^0.1.0",
|
||||||
"@types/jest": "^29.2.4",
|
"@types/jest": "^29.2.4",
|
||||||
"@types/json2csv": "^5.0.3",
|
"@types/json2csv": "^5.0.3",
|
||||||
"@types/leaflet": "^1.9.0",
|
"@types/leaflet": "^1.9.0",
|
||||||
|
@ -101,7 +102,6 @@
|
||||||
"resize-observer-polyfill": "^1.5.1",
|
"resize-observer-polyfill": "^1.5.1",
|
||||||
"sass": "^1.57.1",
|
"sass": "^1.57.1",
|
||||||
"stylelint": "^14.16.0",
|
"stylelint": "^14.16.0",
|
||||||
"ts-mockery": "^1.2.0",
|
|
||||||
"typescript": "^5.0.2",
|
"typescript": "^5.0.2",
|
||||||
"vite": "^4.2.0",
|
"vite": "^4.2.0",
|
||||||
"vite-plugin-pwa": "^0.14.4"
|
"vite-plugin-pwa": "^0.14.4"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromAny, fromPartial } from '@total-typescript/shoehorn';
|
||||||
|
|
||||||
const createLinkMock = () => ({
|
const createLinkMock = () => ({
|
||||||
setAttribute: jest.fn(),
|
setAttribute: jest.fn(),
|
||||||
|
@ -10,9 +10,9 @@ export const appendChild = jest.fn();
|
||||||
|
|
||||||
export const removeChild = jest.fn();
|
export const removeChild = jest.fn();
|
||||||
|
|
||||||
export const windowMock = Mock.of<Window>({
|
export const windowMock = fromPartial<Window>({
|
||||||
document: {
|
document: fromAny({
|
||||||
createElement: jest.fn(createLinkMock),
|
createElement: jest.fn(createLinkMock),
|
||||||
body: { appendChild, removeChild },
|
body: { appendChild, removeChild },
|
||||||
},
|
}),
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShlinkApiErrorProps } from '../../src/api/ShlinkApiError';
|
import type { ShlinkApiErrorProps } from '../../src/api/ShlinkApiError';
|
||||||
import { ShlinkApiError } from '../../src/api/ShlinkApiError';
|
import { ShlinkApiError } from '../../src/api/ShlinkApiError';
|
||||||
import type { InvalidArgumentError, ProblemDetailsError } from '../../src/api/types/errors';
|
import type { InvalidArgumentError, ProblemDetailsError } from '../../src/api/types/errors';
|
||||||
|
@ -10,8 +10,8 @@ describe('<ShlinkApiError />', () => {
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[undefined, 'the fallback', 'the fallback'],
|
[undefined, 'the fallback', 'the fallback'],
|
||||||
[Mock.all<ProblemDetailsError>(), 'the fallback', 'the fallback'],
|
[fromPartial<ProblemDetailsError>({}), 'the fallback', 'the fallback'],
|
||||||
[Mock.of<ProblemDetailsError>({ detail: 'the detail' }), 'the fallback', 'the detail'],
|
[fromPartial<ProblemDetailsError>({ detail: 'the detail' }), 'the fallback', 'the detail'],
|
||||||
])('renders proper message', (errorData, fallbackMessage, expectedMessage) => {
|
])('renders proper message', (errorData, fallbackMessage, expectedMessage) => {
|
||||||
const { container } = setUp({ errorData, fallbackMessage });
|
const { container } = setUp({ errorData, fallbackMessage });
|
||||||
|
|
||||||
|
@ -21,9 +21,9 @@ describe('<ShlinkApiError />', () => {
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[undefined, 0],
|
[undefined, 0],
|
||||||
[Mock.all<ProblemDetailsError>(), 0],
|
[fromPartial<ProblemDetailsError>({}), 0],
|
||||||
[Mock.of<InvalidArgumentError>({ type: ErrorTypeV2.INVALID_ARGUMENT, invalidElements: [] }), 1],
|
[fromPartial<InvalidArgumentError>({ type: ErrorTypeV2.INVALID_ARGUMENT, invalidElements: [] }), 1],
|
||||||
[Mock.of<InvalidArgumentError>({ type: ErrorTypeV3.INVALID_ARGUMENT, invalidElements: [] }), 1],
|
[fromPartial<InvalidArgumentError>({ type: ErrorTypeV3.INVALID_ARGUMENT, invalidElements: [] }), 1],
|
||||||
])('renders list of invalid elements when provided error is an InvalidError', (errorData, expectedElementsCount) => {
|
])('renders list of invalid elements when provided error is an InvalidError', (errorData, expectedElementsCount) => {
|
||||||
setUp({ errorData });
|
setUp({ errorData });
|
||||||
expect(screen.queryAllByText(/^Invalid elements/)).toHaveLength(expectedElementsCount);
|
expect(screen.queryAllByText(/^Invalid elements/)).toHaveLength(expectedElementsCount);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
||||||
import type { ShlinkDomain, ShlinkVisits, ShlinkVisitsOverview } from '../../../src/api/types';
|
import type { ShlinkDomain, ShlinkVisits, ShlinkVisitsOverview } from '../../../src/api/types';
|
||||||
import { ErrorTypeV2, ErrorTypeV3 } from '../../../src/api/types/errors';
|
import { ErrorTypeV2, ErrorTypeV3 } from '../../../src/api/types/errors';
|
||||||
|
@ -9,7 +9,7 @@ import type { OptionalString } from '../../../src/utils/utils';
|
||||||
describe('ShlinkApiClient', () => {
|
describe('ShlinkApiClient', () => {
|
||||||
const fetchJson = jest.fn().mockResolvedValue({});
|
const fetchJson = jest.fn().mockResolvedValue({});
|
||||||
const fetchEmpty = jest.fn().mockResolvedValue(undefined);
|
const fetchEmpty = jest.fn().mockResolvedValue(undefined);
|
||||||
const httpClient = Mock.of<HttpClient>({ fetchJson, fetchEmpty });
|
const httpClient = fromPartial<HttpClient>({ fetchJson, fetchEmpty });
|
||||||
const buildApiClient = () => new ShlinkApiClient(httpClient, '', '');
|
const buildApiClient = () => new ShlinkApiClient(httpClient, '', '');
|
||||||
const shortCodesWithDomainCombinations: [string, OptionalString][] = [
|
const shortCodesWithDomainCombinations: [string, OptionalString][] = [
|
||||||
['abc123', null],
|
['abc123', null],
|
||||||
|
@ -177,7 +177,7 @@ describe('ShlinkApiClient', () => {
|
||||||
maxVisits: 50,
|
maxVisits: 50,
|
||||||
validSince: '2025-01-01T10:00:00+01:00',
|
validSince: '2025-01-01T10:00:00+01:00',
|
||||||
};
|
};
|
||||||
const expectedResp = Mock.of<ShortUrl>();
|
const expectedResp = fromPartial<ShortUrl>({});
|
||||||
fetchJson.mockResolvedValue(expectedResp);
|
fetchJson.mockResolvedValue(expectedResp);
|
||||||
const { updateShortUrl } = buildApiClient();
|
const { updateShortUrl } = buildApiClient();
|
||||||
const expectedQuery = domain ? `?domain=${domain}` : '';
|
const expectedQuery = domain ? `?domain=${domain}` : '';
|
||||||
|
@ -311,7 +311,7 @@ describe('ShlinkApiClient', () => {
|
||||||
|
|
||||||
describe('listDomains', () => {
|
describe('listDomains', () => {
|
||||||
it('returns domains', async () => {
|
it('returns domains', async () => {
|
||||||
const expectedData = { data: [Mock.all<ShlinkDomain>(), Mock.all<ShlinkDomain>()] };
|
const expectedData = { data: [fromPartial<ShlinkDomain>({}), fromPartial<ShlinkDomain>({})] };
|
||||||
fetchJson.mockResolvedValue({ domains: expectedData });
|
fetchJson.mockResolvedValue({ domains: expectedData });
|
||||||
const { listDomains } = buildApiClient();
|
const { listDomains } = buildApiClient();
|
||||||
|
|
||||||
|
@ -324,7 +324,7 @@ describe('ShlinkApiClient', () => {
|
||||||
|
|
||||||
describe('getVisitsOverview', () => {
|
describe('getVisitsOverview', () => {
|
||||||
it('returns visits overview', async () => {
|
it('returns visits overview', async () => {
|
||||||
const expectedData = Mock.all<ShlinkVisitsOverview>();
|
const expectedData = fromPartial<ShlinkVisitsOverview>({});
|
||||||
fetchJson.mockResolvedValue({ visits: expectedData });
|
fetchJson.mockResolvedValue({ visits: expectedData });
|
||||||
const { getVisitsOverview } = buildApiClient();
|
const { getVisitsOverview } = buildApiClient();
|
||||||
|
|
||||||
|
@ -337,7 +337,7 @@ describe('ShlinkApiClient', () => {
|
||||||
|
|
||||||
describe('getOrphanVisits', () => {
|
describe('getOrphanVisits', () => {
|
||||||
it('returns orphan visits', async () => {
|
it('returns orphan visits', async () => {
|
||||||
fetchJson.mockResolvedValue({ visits: Mock.of<ShlinkVisits>({ data: [] }) });
|
fetchJson.mockResolvedValue({ visits: fromPartial<ShlinkVisits>({ data: [] }) });
|
||||||
const { getOrphanVisits } = buildApiClient();
|
const { getOrphanVisits } = buildApiClient();
|
||||||
|
|
||||||
const result = await getOrphanVisits();
|
const result = await getOrphanVisits();
|
||||||
|
@ -349,7 +349,7 @@ describe('ShlinkApiClient', () => {
|
||||||
|
|
||||||
describe('getNonOrphanVisits', () => {
|
describe('getNonOrphanVisits', () => {
|
||||||
it('returns non-orphan visits', async () => {
|
it('returns non-orphan visits', async () => {
|
||||||
fetchJson.mockResolvedValue({ visits: Mock.of<ShlinkVisits>({ data: [] }) });
|
fetchJson.mockResolvedValue({ visits: fromPartial<ShlinkVisits>({ data: [] }) });
|
||||||
const { getNonOrphanVisits } = buildApiClient();
|
const { getNonOrphanVisits } = buildApiClient();
|
||||||
|
|
||||||
const result = await getNonOrphanVisits();
|
const result = await getNonOrphanVisits();
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { buildShlinkApiClient } from '../../../src/api/services/ShlinkApiClientBuilder';
|
import { buildShlinkApiClient } from '../../../src/api/services/ShlinkApiClientBuilder';
|
||||||
import type { HttpClient } from '../../../src/common/services/HttpClient';
|
|
||||||
import type { ShlinkState } from '../../../src/container/types';
|
|
||||||
import type { ReachableServer, SelectedServer } from '../../../src/servers/data';
|
import type { ReachableServer, SelectedServer } from '../../../src/servers/data';
|
||||||
|
|
||||||
describe('ShlinkApiClientBuilder', () => {
|
describe('ShlinkApiClientBuilder', () => {
|
||||||
const server = (data: Partial<ReachableServer>) => Mock.of<ReachableServer>(data);
|
const server = fromPartial<ReachableServer>;
|
||||||
|
|
||||||
const createBuilder = () => {
|
const createBuilder = () => {
|
||||||
const builder = buildShlinkApiClient(Mock.of<HttpClient>());
|
const builder = buildShlinkApiClient(fromPartial({}));
|
||||||
return (selectedServer: SelectedServer) => builder(() => Mock.of<ShlinkState>({ selectedServer }));
|
return (selectedServer: SelectedServer) => builder(() => fromPartial({ selectedServer }));
|
||||||
};
|
};
|
||||||
|
|
||||||
it('creates new instances when provided params are different', async () => {
|
it('creates new instances when provided params are different', async () => {
|
||||||
|
@ -42,7 +40,7 @@ describe('ShlinkApiClientBuilder', () => {
|
||||||
it('does not fetch from state when provided param is already selected server', () => {
|
it('does not fetch from state when provided param is already selected server', () => {
|
||||||
const url = 'url';
|
const url = 'url';
|
||||||
const apiKey = 'apiKey';
|
const apiKey = 'apiKey';
|
||||||
const apiClient = buildShlinkApiClient(Mock.of<HttpClient>())(server({ url, apiKey }));
|
const apiClient = buildShlinkApiClient(fromPartial({}))(server({ url, apiKey }));
|
||||||
|
|
||||||
expect(apiClient['baseUrl']).toEqual(url); // eslint-disable-line @typescript-eslint/dot-notation
|
expect(apiClient['baseUrl']).toEqual(url); // eslint-disable-line @typescript-eslint/dot-notation
|
||||||
expect(apiClient['apiKey']).toEqual(apiKey); // eslint-disable-line @typescript-eslint/dot-notation
|
expect(apiClient['apiKey']).toEqual(apiKey); // eslint-disable-line @typescript-eslint/dot-notation
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { createMemoryHistory } from 'history';
|
import { createMemoryHistory } from 'history';
|
||||||
import { Router } from 'react-router-dom';
|
import { Router } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import { App as createApp } from '../../src/app/App';
|
import { App as createApp } from '../../src/app/App';
|
||||||
import type { Settings } from '../../src/settings/reducers/settings';
|
|
||||||
|
|
||||||
describe('<App />', () => {
|
describe('<App />', () => {
|
||||||
const App = createApp(
|
const App = createApp(
|
||||||
|
@ -25,7 +24,7 @@ describe('<App />', () => {
|
||||||
<App
|
<App
|
||||||
fetchServers={() => {}}
|
fetchServers={() => {}}
|
||||||
servers={{}}
|
servers={{}}
|
||||||
settings={Mock.all<Settings>()}
|
settings={fromPartial({})}
|
||||||
appUpdated
|
appUpdated
|
||||||
resetAppUpdate={() => {}}
|
resetAppUpdate={() => {}}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import { AsideMenu as createAsideMenu } from '../../src/common/AsideMenu';
|
import { AsideMenu as createAsideMenu } from '../../src/common/AsideMenu';
|
||||||
import type { ReachableServer } from '../../src/servers/data';
|
|
||||||
|
|
||||||
describe('<AsideMenu />', () => {
|
describe('<AsideMenu />', () => {
|
||||||
const AsideMenu = createAsideMenu(() => <>DeleteServerButton</>);
|
const AsideMenu = createAsideMenu(() => <>DeleteServerButton</>);
|
||||||
const setUp = (id: string | false = 'abc123') => render(
|
const setUp = (id: string | false = 'abc123') => render(
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<AsideMenu selectedServer={Mock.of<ReachableServer>({ id: id || undefined, version: '2.8.0' })} />
|
<AsideMenu selectedServer={fromPartial({ id: id || undefined, version: '2.8.0' })} />
|
||||||
</MemoryRouter>,
|
</MemoryRouter>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { ErrorHandler as createErrorHandler } from '../../src/common/ErrorHandler';
|
import { ErrorHandler as createErrorHandler } from '../../src/common/ErrorHandler';
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
|
|
||||||
|
@ -9,10 +9,10 @@ const ComponentWithError = () => {
|
||||||
|
|
||||||
describe('<ErrorHandler />', () => {
|
describe('<ErrorHandler />', () => {
|
||||||
const reload = jest.fn();
|
const reload = jest.fn();
|
||||||
const window = Mock.of<Window>({
|
const window = fromPartial<Window>({
|
||||||
location: { reload },
|
location: { reload },
|
||||||
});
|
});
|
||||||
const cons = Mock.of<Console>({ error: jest.fn() });
|
const cons = fromPartial<Console>({ error: jest.fn() });
|
||||||
const ErrorHandler = createErrorHandler(window, cons);
|
const ErrorHandler = createErrorHandler(window, cons);
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import { Home } from '../../src/common/Home';
|
import { Home } from '../../src/common/Home';
|
||||||
import type { ServersMap, ServerWithId } from '../../src/servers/data';
|
import type { ServersMap, ServerWithId } from '../../src/servers/data';
|
||||||
|
|
||||||
|
@ -19,9 +19,9 @@ describe('<Home />', () => {
|
||||||
it.each([
|
it.each([
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
'1a': Mock.of<ServerWithId>({ name: 'foo', id: '1' }),
|
'1a': fromPartial<ServerWithId>({ name: 'foo', id: '1' }),
|
||||||
'2b': Mock.of<ServerWithId>({ name: 'bar', id: '2' }),
|
'2b': fromPartial<ServerWithId>({ name: 'bar', id: '2' }),
|
||||||
'3c': Mock.of<ServerWithId>({ name: 'baz', id: '3' }),
|
'3c': fromPartial<ServerWithId>({ name: 'baz', id: '3' }),
|
||||||
},
|
},
|
||||||
3,
|
3,
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { createMemoryHistory } from 'history';
|
import { createMemoryHistory } from 'history';
|
||||||
import { Router, useParams } from 'react-router-dom';
|
import { Router, useParams } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import { MenuLayout as createMenuLayout } from '../../src/common/MenuLayout';
|
import { MenuLayout as createMenuLayout } from '../../src/common/MenuLayout';
|
||||||
import type { NonReachableServer, NotFoundServer, ReachableServer, SelectedServer } from '../../src/servers/data';
|
import type { NonReachableServer, NotFoundServer, SelectedServer } from '../../src/servers/data';
|
||||||
import type { SemVer } from '../../src/utils/helpers/version';
|
import type { SemVer } from '../../src/utils/helpers/version';
|
||||||
|
|
||||||
jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useParams: jest.fn() }));
|
jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useParams: jest.fn() }));
|
||||||
|
@ -54,8 +54,8 @@ describe('<MenuLayout />', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[Mock.of<NotFoundServer>({ serverNotFound: true })],
|
[fromPartial<NotFoundServer>({ serverNotFound: true })],
|
||||||
[Mock.of<NonReachableServer>({ serverNotReachable: true })],
|
[fromPartial<NonReachableServer>({ serverNotReachable: true })],
|
||||||
])('shows error for non reachable servers', (selectedServer) => {
|
])('shows error for non reachable servers', (selectedServer) => {
|
||||||
setUp(selectedServer);
|
setUp(selectedServer);
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ describe('<MenuLayout />', () => {
|
||||||
])(
|
])(
|
||||||
'renders expected component based on location and server version',
|
'renders expected component based on location and server version',
|
||||||
(version, currentPath, expectedContent) => {
|
(version, currentPath, expectedContent) => {
|
||||||
setUp(Mock.of<ReachableServer>({ version }), currentPath);
|
setUp(fromPartial({ version }), currentPath);
|
||||||
expect(screen.getByText(expectedContent)).toBeInTheDocument();
|
expect(screen.getByText(expectedContent)).toBeInTheDocument();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShlinkVersionsProps } from '../../src/common/ShlinkVersions';
|
import type { ShlinkVersionsProps } from '../../src/common/ShlinkVersions';
|
||||||
import { ShlinkVersions } from '../../src/common/ShlinkVersions';
|
import { ShlinkVersions } from '../../src/common/ShlinkVersions';
|
||||||
import type { NonReachableServer, NotFoundServer, ReachableServer } from '../../src/servers/data';
|
import type { NonReachableServer, NotFoundServer, ReachableServer } from '../../src/servers/data';
|
||||||
|
@ -8,11 +8,11 @@ describe('<ShlinkVersions />', () => {
|
||||||
const setUp = (props: ShlinkVersionsProps) => render(<ShlinkVersions {...props} />);
|
const setUp = (props: ShlinkVersionsProps) => render(<ShlinkVersions {...props} />);
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
['1.2.3', Mock.of<ReachableServer>({ version: '1.0.0', printableVersion: 'foo' }), 'v1.2.3', 'foo'],
|
['1.2.3', fromPartial<ReachableServer>({ version: '1.0.0', printableVersion: 'foo' }), 'v1.2.3', 'foo'],
|
||||||
['foo', Mock.of<ReachableServer>({ version: '1.0.0', printableVersion: '1.2.3' }), 'latest', '1.2.3'],
|
['foo', fromPartial<ReachableServer>({ version: '1.0.0', printableVersion: '1.2.3' }), 'latest', '1.2.3'],
|
||||||
['latest', Mock.of<ReachableServer>({ version: '1.0.0', printableVersion: 'latest' }), 'latest', 'latest'],
|
['latest', fromPartial<ReachableServer>({ version: '1.0.0', printableVersion: 'latest' }), 'latest', 'latest'],
|
||||||
['5.5.0', Mock.of<ReachableServer>({ version: '1.0.0', printableVersion: '0.2.8' }), 'v5.5.0', '0.2.8'],
|
['5.5.0', fromPartial<ReachableServer>({ version: '1.0.0', printableVersion: '0.2.8' }), 'v5.5.0', '0.2.8'],
|
||||||
['not-semver', Mock.of<ReachableServer>({ version: '1.0.0', printableVersion: 'some' }), 'latest', 'some'],
|
['not-semver', fromPartial<ReachableServer>({ version: '1.0.0', printableVersion: 'some' }), 'latest', 'some'],
|
||||||
])(
|
])(
|
||||||
'displays expected versions when selected server is reachable',
|
'displays expected versions when selected server is reachable',
|
||||||
(clientVersion, selectedServer, expectedClientVersion, expectedServerVersion) => {
|
(clientVersion, selectedServer, expectedClientVersion, expectedServerVersion) => {
|
||||||
|
@ -34,8 +34,8 @@ describe('<ShlinkVersions />', () => {
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
['1.2.3', null],
|
['1.2.3', null],
|
||||||
['1.2.3', Mock.of<NotFoundServer>({ serverNotFound: true })],
|
['1.2.3', fromPartial<NotFoundServer>({ serverNotFound: true })],
|
||||||
['1.2.3', Mock.of<NonReachableServer>({ serverNotReachable: true })],
|
['1.2.3', fromPartial<NonReachableServer>({ serverNotReachable: true })],
|
||||||
])('displays only client version when selected server is not reachable', (clientVersion, selectedServer) => {
|
])('displays only client version when selected server is not reachable', (clientVersion, selectedServer) => {
|
||||||
setUp({ clientVersion, selectedServer });
|
setUp({ clientVersion, selectedServer });
|
||||||
const links = screen.getAllByRole('link');
|
const links = screen.getAllByRole('link');
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
import { render } from '@testing-library/react';
|
import { render } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { Sidebar } from '../../src/common/reducers/sidebar';
|
import type { Sidebar } from '../../src/common/reducers/sidebar';
|
||||||
import { ShlinkVersionsContainer } from '../../src/common/ShlinkVersionsContainer';
|
import { ShlinkVersionsContainer } from '../../src/common/ShlinkVersionsContainer';
|
||||||
import type { SelectedServer } from '../../src/servers/data';
|
|
||||||
|
|
||||||
describe('<ShlinkVersionsContainer />', () => {
|
describe('<ShlinkVersionsContainer />', () => {
|
||||||
const setUp = (sidebar: Sidebar) => render(
|
const setUp = (sidebar: Sidebar) => render(
|
||||||
<ShlinkVersionsContainer selectedServer={Mock.all<SelectedServer>()} sidebar={sidebar} />,
|
<ShlinkVersionsContainer selectedServer={fromPartial({})} sidebar={sidebar} />,
|
||||||
);
|
);
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { HttpClient } from '../../../src/common/services/HttpClient';
|
import type { HttpClient } from '../../../src/common/services/HttpClient';
|
||||||
import { ImageDownloader } from '../../../src/common/services/ImageDownloader';
|
import { ImageDownloader } from '../../../src/common/services/ImageDownloader';
|
||||||
import { windowMock } from '../../__mocks__/Window.mock';
|
import { windowMock } from '../../__mocks__/Window.mock';
|
||||||
|
|
||||||
describe('ImageDownloader', () => {
|
describe('ImageDownloader', () => {
|
||||||
const fetchBlob = jest.fn();
|
const fetchBlob = jest.fn();
|
||||||
const httpClient = Mock.of<HttpClient>({ fetchBlob });
|
const httpClient = fromPartial<HttpClient>({ fetchBlob });
|
||||||
let imageDownloader: ImageDownloader;
|
let imageDownloader: ImageDownloader;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShlinkDomainRedirects } from '../../src/api/types';
|
import type { ShlinkDomainRedirects } from '../../src/api/types';
|
||||||
import type { Domain } from '../../src/domains/data';
|
import type { Domain } from '../../src/domains/data';
|
||||||
import { DomainRow } from '../../src/domains/DomainRow';
|
import { DomainRow } from '../../src/domains/DomainRow';
|
||||||
import type { SelectedServer } from '../../src/servers/data';
|
|
||||||
|
|
||||||
describe('<DomainRow />', () => {
|
describe('<DomainRow />', () => {
|
||||||
const redirectsCombinations = [
|
const redirectsCombinations = [
|
||||||
[Mock.of<ShlinkDomainRedirects>({ baseUrlRedirect: 'foo' })],
|
[fromPartial<ShlinkDomainRedirects>({ baseUrlRedirect: 'foo' })],
|
||||||
[Mock.of<ShlinkDomainRedirects>({ invalidShortUrlRedirect: 'bar' })],
|
[fromPartial<ShlinkDomainRedirects>({ invalidShortUrlRedirect: 'bar' })],
|
||||||
[Mock.of<ShlinkDomainRedirects>({ baseUrlRedirect: 'baz', regular404Redirect: 'foo' })],
|
[fromPartial<ShlinkDomainRedirects>({ baseUrlRedirect: 'baz', regular404Redirect: 'foo' })],
|
||||||
[
|
[
|
||||||
Mock.of<ShlinkDomainRedirects>(
|
fromPartial<ShlinkDomainRedirects>(
|
||||||
{ baseUrlRedirect: 'baz', regular404Redirect: 'bar', invalidShortUrlRedirect: 'foo' },
|
{ baseUrlRedirect: 'baz', regular404Redirect: 'bar', invalidShortUrlRedirect: 'foo' },
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -22,7 +21,7 @@ describe('<DomainRow />', () => {
|
||||||
<DomainRow
|
<DomainRow
|
||||||
domain={domain}
|
domain={domain}
|
||||||
defaultRedirects={defaultRedirects}
|
defaultRedirects={defaultRedirects}
|
||||||
selectedServer={Mock.all<SelectedServer>()}
|
selectedServer={fromPartial({})}
|
||||||
editDomainRedirects={jest.fn()}
|
editDomainRedirects={jest.fn()}
|
||||||
checkDomainHealth={jest.fn()}
|
checkDomainHealth={jest.fn()}
|
||||||
/>
|
/>
|
||||||
|
@ -31,7 +30,7 @@ describe('<DomainRow />', () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
it.each(redirectsCombinations)('shows expected redirects', (redirects) => {
|
it.each(redirectsCombinations)('shows expected redirects', (redirects) => {
|
||||||
setUp(Mock.of<Domain>({ domain: '', isDefault: true, redirects }));
|
setUp(fromPartial({ domain: '', isDefault: true, redirects }));
|
||||||
const cells = screen.getAllByRole('cell');
|
const cells = screen.getAllByRole('cell');
|
||||||
|
|
||||||
redirects?.baseUrlRedirect && expect(cells[1]).toHaveTextContent(redirects.baseUrlRedirect);
|
redirects?.baseUrlRedirect && expect(cells[1]).toHaveTextContent(redirects.baseUrlRedirect);
|
||||||
|
@ -42,9 +41,9 @@ describe('<DomainRow />', () => {
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[undefined],
|
[undefined],
|
||||||
[Mock.of<ShlinkDomainRedirects>()],
|
[fromPartial<ShlinkDomainRedirects>({})],
|
||||||
])('shows expected "no redirects"', (redirects) => {
|
])('shows expected "no redirects"', (redirects) => {
|
||||||
setUp(Mock.of<Domain>({ domain: '', isDefault: true, redirects }));
|
setUp(fromPartial({ domain: '', isDefault: true, redirects }));
|
||||||
const cells = screen.getAllByRole('cell');
|
const cells = screen.getAllByRole('cell');
|
||||||
|
|
||||||
expect(cells[1]).toHaveTextContent('No redirect');
|
expect(cells[1]).toHaveTextContent('No redirect');
|
||||||
|
@ -54,7 +53,7 @@ describe('<DomainRow />', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each(redirectsCombinations)('shows expected fallback redirects', (fallbackRedirects) => {
|
it.each(redirectsCombinations)('shows expected fallback redirects', (fallbackRedirects) => {
|
||||||
setUp(Mock.of<Domain>({ domain: '', isDefault: true }), fallbackRedirects);
|
setUp(fromPartial({ domain: '', isDefault: true }), fallbackRedirects);
|
||||||
const cells = screen.getAllByRole('cell');
|
const cells = screen.getAllByRole('cell');
|
||||||
|
|
||||||
fallbackRedirects?.baseUrlRedirect && expect(cells[1]).toHaveTextContent(
|
fallbackRedirects?.baseUrlRedirect && expect(cells[1]).toHaveTextContent(
|
||||||
|
@ -69,7 +68,7 @@ describe('<DomainRow />', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([[true], [false]])('shows icon on default domain only', (isDefault) => {
|
it.each([[true], [false]])('shows icon on default domain only', (isDefault) => {
|
||||||
const { container } = setUp(Mock.of<Domain>({ domain: '', isDefault }));
|
const { container } = setUp(fromPartial({ domain: '', isDefault }));
|
||||||
|
|
||||||
if (isDefault) {
|
if (isDefault) {
|
||||||
expect(container.querySelector('#defaultDomainIcon')).toBeInTheDocument();
|
expect(container.querySelector('#defaultDomainIcon')).toBeInTheDocument();
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
import { screen, waitFor } from '@testing-library/react';
|
import { screen, waitFor } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShlinkDomain } from '../../src/api/types';
|
|
||||||
import { DomainSelector } from '../../src/domains/DomainSelector';
|
import { DomainSelector } from '../../src/domains/DomainSelector';
|
||||||
import type { DomainsList } from '../../src/domains/reducers/domainsList';
|
import type { DomainsList } from '../../src/domains/reducers/domainsList';
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
|
|
||||||
describe('<DomainSelector />', () => {
|
describe('<DomainSelector />', () => {
|
||||||
const domainsList = Mock.of<DomainsList>({
|
const domainsList = fromPartial<DomainsList>({
|
||||||
domains: [
|
domains: [
|
||||||
Mock.of<ShlinkDomain>({ domain: 'default.com', isDefault: true }),
|
fromPartial({ domain: 'default.com', isDefault: true }),
|
||||||
Mock.of<ShlinkDomain>({ domain: 'foo.com' }),
|
fromPartial({ domain: 'foo.com' }),
|
||||||
Mock.of<ShlinkDomain>({ domain: 'bar.com' }),
|
fromPartial({ domain: 'bar.com' }),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
const setUp = (value = '') => renderWithEvents(
|
const setUp = (value = '') => renderWithEvents(
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import { screen, waitFor } from '@testing-library/react';
|
import { screen, waitFor } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShlinkDomain } from '../../src/api/types';
|
import type { ShlinkDomain } from '../../src/api/types';
|
||||||
import type { ProblemDetailsError } from '../../src/api/types/errors';
|
import type { ProblemDetailsError } from '../../src/api/types/errors';
|
||||||
import { ManageDomains } from '../../src/domains/ManageDomains';
|
import { ManageDomains } from '../../src/domains/ManageDomains';
|
||||||
import type { DomainsList } from '../../src/domains/reducers/domainsList';
|
import type { DomainsList } from '../../src/domains/reducers/domainsList';
|
||||||
import type { SelectedServer } from '../../src/servers/data';
|
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
|
|
||||||
describe('<ManageDomains />', () => {
|
describe('<ManageDomains />', () => {
|
||||||
|
@ -17,14 +16,14 @@ describe('<ManageDomains />', () => {
|
||||||
editDomainRedirects={jest.fn()}
|
editDomainRedirects={jest.fn()}
|
||||||
checkDomainHealth={jest.fn()}
|
checkDomainHealth={jest.fn()}
|
||||||
domainsList={domainsList}
|
domainsList={domainsList}
|
||||||
selectedServer={Mock.all<SelectedServer>()}
|
selectedServer={fromPartial({})}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
afterEach(jest.clearAllMocks);
|
afterEach(jest.clearAllMocks);
|
||||||
|
|
||||||
it('shows loading message while domains are loading', () => {
|
it('shows loading message while domains are loading', () => {
|
||||||
setUp(Mock.of<DomainsList>({ loading: true, filteredDomains: [] }));
|
setUp(fromPartial({ loading: true, filteredDomains: [] }));
|
||||||
|
|
||||||
expect(screen.getByText('Loading...')).toBeInTheDocument();
|
expect(screen.getByText('Loading...')).toBeInTheDocument();
|
||||||
expect(screen.queryByText('Error loading domains :(')).not.toBeInTheDocument();
|
expect(screen.queryByText('Error loading domains :(')).not.toBeInTheDocument();
|
||||||
|
@ -32,17 +31,17 @@ describe('<ManageDomains />', () => {
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[undefined, 'Error loading domains :('],
|
[undefined, 'Error loading domains :('],
|
||||||
[Mock.of<ProblemDetailsError>(), 'Error loading domains :('],
|
[fromPartial<ProblemDetailsError>({}), 'Error loading domains :('],
|
||||||
[Mock.of<ProblemDetailsError>({ detail: 'Foo error!!' }), 'Foo error!!'],
|
[fromPartial<ProblemDetailsError>({ detail: 'Foo error!!' }), 'Foo error!!'],
|
||||||
])('shows error result when domains loading fails', (errorData, expectedErrorMessage) => {
|
])('shows error result when domains loading fails', (errorData, expectedErrorMessage) => {
|
||||||
setUp(Mock.of<DomainsList>({ loading: false, error: true, errorData, filteredDomains: [] }));
|
setUp(fromPartial({ loading: false, error: true, errorData, filteredDomains: [] }));
|
||||||
|
|
||||||
expect(screen.queryByText('Loading...')).not.toBeInTheDocument();
|
expect(screen.queryByText('Loading...')).not.toBeInTheDocument();
|
||||||
expect(screen.getByText(expectedErrorMessage)).toBeInTheDocument();
|
expect(screen.getByText(expectedErrorMessage)).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('filters domains when SearchField changes', async () => {
|
it('filters domains when SearchField changes', async () => {
|
||||||
const { user } = setUp(Mock.of<DomainsList>({ loading: false, error: false, filteredDomains: [] }));
|
const { user } = setUp(fromPartial({ loading: false, error: false, filteredDomains: [] }));
|
||||||
|
|
||||||
expect(filterDomains).not.toHaveBeenCalled();
|
expect(filterDomains).not.toHaveBeenCalled();
|
||||||
await user.type(screen.getByPlaceholderText('Search...'), 'Foo');
|
await user.type(screen.getByPlaceholderText('Search...'), 'Foo');
|
||||||
|
@ -50,19 +49,19 @@ describe('<ManageDomains />', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shows expected headers and one row when list of domains is empty', () => {
|
it('shows expected headers and one row when list of domains is empty', () => {
|
||||||
setUp(Mock.of<DomainsList>({ loading: false, error: false, filteredDomains: [] }));
|
setUp(fromPartial({ loading: false, error: false, filteredDomains: [] }));
|
||||||
|
|
||||||
expect(screen.getAllByRole('columnheader')).toHaveLength(7);
|
expect(screen.getAllByRole('columnheader')).toHaveLength(7);
|
||||||
expect(screen.getByText('No results found')).toBeInTheDocument();
|
expect(screen.getByText('No results found')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('has many rows if multiple domains are provided', () => {
|
it('has many rows if multiple domains are provided', () => {
|
||||||
const filteredDomains = [
|
const filteredDomains: ShlinkDomain[] = [
|
||||||
Mock.of<ShlinkDomain>({ domain: 'foo' }),
|
fromPartial({ domain: 'foo' }),
|
||||||
Mock.of<ShlinkDomain>({ domain: 'bar' }),
|
fromPartial({ domain: 'bar' }),
|
||||||
Mock.of<ShlinkDomain>({ domain: 'baz' }),
|
fromPartial({ domain: 'baz' }),
|
||||||
];
|
];
|
||||||
setUp(Mock.of<DomainsList>({ loading: false, error: false, filteredDomains }));
|
setUp(fromPartial({ loading: false, error: false, filteredDomains }));
|
||||||
|
|
||||||
expect(screen.getAllByRole('row')).toHaveLength(filteredDomains.length + 1);
|
expect(screen.getAllByRole('row')).toHaveLength(filteredDomains.length + 1);
|
||||||
expect(screen.getByText('foo')).toBeInTheDocument();
|
expect(screen.getByText('foo')).toBeInTheDocument();
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { screen, waitForElementToBeRemoved } from '@testing-library/react';
|
import { screen, waitForElementToBeRemoved } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { Domain } from '../../../src/domains/data';
|
import type { Domain } from '../../../src/domains/data';
|
||||||
import { DomainDropdown } from '../../../src/domains/helpers/DomainDropdown';
|
import { DomainDropdown } from '../../../src/domains/helpers/DomainDropdown';
|
||||||
import type { ReachableServer, SelectedServer } from '../../../src/servers/data';
|
import type { SelectedServer } from '../../../src/servers/data';
|
||||||
import type { SemVer } from '../../../src/utils/helpers/version';
|
import type { SemVer } from '../../../src/utils/helpers/version';
|
||||||
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
||||||
|
|
||||||
|
@ -12,8 +12,8 @@ describe('<DomainDropdown />', () => {
|
||||||
const setUp = (domain?: Domain, selectedServer?: SelectedServer) => renderWithEvents(
|
const setUp = (domain?: Domain, selectedServer?: SelectedServer) => renderWithEvents(
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<DomainDropdown
|
<DomainDropdown
|
||||||
domain={domain ?? Mock.all<Domain>()}
|
domain={domain ?? fromPartial({})}
|
||||||
selectedServer={selectedServer ?? Mock.all<SelectedServer>()}
|
selectedServer={selectedServer ?? fromPartial({})}
|
||||||
editDomainRedirects={editDomainRedirects}
|
editDomainRedirects={editDomainRedirects}
|
||||||
/>
|
/>
|
||||||
</MemoryRouter>,
|
</MemoryRouter>,
|
||||||
|
@ -33,8 +33,8 @@ describe('<DomainDropdown />', () => {
|
||||||
[false, ''],
|
[false, ''],
|
||||||
])('points first link to the proper section', (isDefault, expectedLink) => {
|
])('points first link to the proper section', (isDefault, expectedLink) => {
|
||||||
setUp(
|
setUp(
|
||||||
Mock.of<Domain>({ domain: 'foo.com', isDefault }),
|
fromPartial({ domain: 'foo.com', isDefault }),
|
||||||
Mock.of<ReachableServer>({ version: '3.1.0', id: '123' }),
|
fromPartial({ version: '3.1.0', id: '123' }),
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(screen.getByText('Visit stats')).toHaveAttribute('href', `/server/123/domain/foo.com${expectedLink}/visits`);
|
expect(screen.getByText('Visit stats')).toHaveAttribute('href', `/server/123/domain/foo.com${expectedLink}/visits`);
|
||||||
|
@ -46,8 +46,8 @@ describe('<DomainDropdown />', () => {
|
||||||
[false, '2.9.0' as SemVer, true],
|
[false, '2.9.0' as SemVer, true],
|
||||||
])('allows editing certain the domains', (isDefault, serverVersion, canBeEdited) => {
|
])('allows editing certain the domains', (isDefault, serverVersion, canBeEdited) => {
|
||||||
setUp(
|
setUp(
|
||||||
Mock.of<Domain>({ domain: 'foo.com', isDefault }),
|
fromPartial({ domain: 'foo.com', isDefault }),
|
||||||
Mock.of<ReachableServer>({ version: serverVersion, id: '123' }),
|
fromPartial({ version: serverVersion, id: '123' }),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (canBeEdited) {
|
if (canBeEdited) {
|
||||||
|
@ -62,7 +62,7 @@ describe('<DomainDropdown />', () => {
|
||||||
['bar.org'],
|
['bar.org'],
|
||||||
['baz.net'],
|
['baz.net'],
|
||||||
])('displays modal when editing redirects', async (domain) => {
|
])('displays modal when editing redirects', async (domain) => {
|
||||||
const { user } = setUp(Mock.of<Domain>({ domain, isDefault: false }));
|
const { user } = setUp(fromPartial({ domain, isDefault: false }));
|
||||||
|
|
||||||
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
|
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
|
||||||
expect(screen.queryByRole('form')).not.toBeInTheDocument();
|
expect(screen.queryByRole('form')).not.toBeInTheDocument();
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { DomainStatus } from '../../../src/domains/data';
|
import type { DomainStatus } from '../../../src/domains/data';
|
||||||
import { DomainStatusIcon } from '../../../src/domains/helpers/DomainStatusIcon';
|
import { DomainStatusIcon } from '../../../src/domains/helpers/DomainStatusIcon';
|
||||||
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
||||||
|
|
||||||
describe('<DomainStatusIcon />', () => {
|
describe('<DomainStatusIcon />', () => {
|
||||||
const matchMedia = jest.fn().mockReturnValue(Mock.of<MediaQueryList>({ matches: false }));
|
const matchMedia = jest.fn().mockReturnValue(fromPartial<MediaQueryList>({ matches: false }));
|
||||||
const setUp = (status: DomainStatus) => renderWithEvents(
|
const setUp = (status: DomainStatus) => renderWithEvents(
|
||||||
<DomainStatusIcon status={status} matchMedia={matchMedia} />,
|
<DomainStatusIcon status={status} matchMedia={matchMedia} />,
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { fireEvent, screen, waitFor } from '@testing-library/react';
|
import { fireEvent, screen, waitFor } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShlinkDomain } from '../../../src/api/types';
|
import type { ShlinkDomain } from '../../../src/api/types';
|
||||||
import { EditDomainRedirectsModal } from '../../../src/domains/helpers/EditDomainRedirectsModal';
|
import { EditDomainRedirectsModal } from '../../../src/domains/helpers/EditDomainRedirectsModal';
|
||||||
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
||||||
|
@ -7,7 +7,7 @@ import { renderWithEvents } from '../../__helpers__/setUpTest';
|
||||||
describe('<EditDomainRedirectsModal />', () => {
|
describe('<EditDomainRedirectsModal />', () => {
|
||||||
const editDomainRedirects = jest.fn().mockResolvedValue(undefined);
|
const editDomainRedirects = jest.fn().mockResolvedValue(undefined);
|
||||||
const toggle = jest.fn();
|
const toggle = jest.fn();
|
||||||
const domain = Mock.of<ShlinkDomain>({
|
const domain = fromPartial<ShlinkDomain>({
|
||||||
domain: 'foo.com',
|
domain: 'foo.com',
|
||||||
redirects: {
|
redirects: {
|
||||||
baseUrlRedirect: 'baz',
|
baseUrlRedirect: 'baz',
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
||||||
import type { ShlinkDomainRedirects } from '../../../src/api/types';
|
import type { ShlinkDomainRedirects } from '../../../src/api/types';
|
||||||
import type { EditDomainRedirects } from '../../../src/domains/reducers/domainRedirects';
|
|
||||||
import { editDomainRedirects } from '../../../src/domains/reducers/domainRedirects';
|
import { editDomainRedirects } from '../../../src/domains/reducers/domainRedirects';
|
||||||
|
|
||||||
describe('domainRedirectsReducer', () => {
|
describe('domainRedirectsReducer', () => {
|
||||||
|
@ -9,17 +8,17 @@ describe('domainRedirectsReducer', () => {
|
||||||
|
|
||||||
describe('editDomainRedirects', () => {
|
describe('editDomainRedirects', () => {
|
||||||
const domain = 'example.com';
|
const domain = 'example.com';
|
||||||
const redirects = Mock.all<ShlinkDomainRedirects>();
|
const redirects = fromPartial<ShlinkDomainRedirects>({});
|
||||||
const dispatch = jest.fn();
|
const dispatch = jest.fn();
|
||||||
const getState = jest.fn();
|
const getState = jest.fn();
|
||||||
const editDomainRedirectsCall = jest.fn();
|
const editDomainRedirectsCall = jest.fn();
|
||||||
const buildShlinkApiClient = () => Mock.of<ShlinkApiClient>({ editDomainRedirects: editDomainRedirectsCall });
|
const buildShlinkApiClient = () => fromPartial<ShlinkApiClient>({ editDomainRedirects: editDomainRedirectsCall });
|
||||||
const editDomainRedirectsAction = editDomainRedirects(buildShlinkApiClient);
|
const editDomainRedirectsAction = editDomainRedirects(buildShlinkApiClient);
|
||||||
|
|
||||||
it('dispatches domain and redirects once loaded', async () => {
|
it('dispatches domain and redirects once loaded', async () => {
|
||||||
editDomainRedirectsCall.mockResolvedValue(redirects);
|
editDomainRedirectsCall.mockResolvedValue(redirects);
|
||||||
|
|
||||||
await editDomainRedirectsAction(Mock.of<EditDomainRedirects>({ domain }))(dispatch, getState, {});
|
await editDomainRedirectsAction(fromPartial({ domain }))(dispatch, getState, {});
|
||||||
|
|
||||||
expect(dispatch).toHaveBeenCalledTimes(2);
|
expect(dispatch).toHaveBeenCalledTimes(2);
|
||||||
expect(dispatch).toHaveBeenLastCalledWith(expect.objectContaining({
|
expect(dispatch).toHaveBeenLastCalledWith(expect.objectContaining({
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
||||||
import type { ShlinkDomainRedirects } from '../../../src/api/types';
|
import type { ShlinkDomainRedirects } from '../../../src/api/types';
|
||||||
import { parseApiError } from '../../../src/api/utils';
|
import { parseApiError } from '../../../src/api/utils';
|
||||||
|
@ -6,26 +6,23 @@ import type { ShlinkState } from '../../../src/container/types';
|
||||||
import type { Domain } from '../../../src/domains/data';
|
import type { Domain } from '../../../src/domains/data';
|
||||||
import type { EditDomainRedirects } from '../../../src/domains/reducers/domainRedirects';
|
import type { EditDomainRedirects } from '../../../src/domains/reducers/domainRedirects';
|
||||||
import { editDomainRedirects } from '../../../src/domains/reducers/domainRedirects';
|
import { editDomainRedirects } from '../../../src/domains/reducers/domainRedirects';
|
||||||
import type {
|
|
||||||
DomainsList } from '../../../src/domains/reducers/domainsList';
|
|
||||||
import {
|
import {
|
||||||
domainsListReducerCreator,
|
domainsListReducerCreator,
|
||||||
replaceRedirectsOnDomain,
|
replaceRedirectsOnDomain,
|
||||||
replaceStatusOnDomain,
|
replaceStatusOnDomain,
|
||||||
} from '../../../src/domains/reducers/domainsList';
|
} from '../../../src/domains/reducers/domainsList';
|
||||||
import type { SelectedServer, ServerData } from '../../../src/servers/data';
|
|
||||||
|
|
||||||
describe('domainsListReducer', () => {
|
describe('domainsListReducer', () => {
|
||||||
const dispatch = jest.fn();
|
const dispatch = jest.fn();
|
||||||
const getState = jest.fn();
|
const getState = jest.fn();
|
||||||
const listDomains = jest.fn();
|
const listDomains = jest.fn();
|
||||||
const health = jest.fn();
|
const health = jest.fn();
|
||||||
const buildShlinkApiClient = () => Mock.of<ShlinkApiClient>({ listDomains, health });
|
const buildShlinkApiClient = () => fromPartial<ShlinkApiClient>({ listDomains, health });
|
||||||
const filteredDomains = [
|
const filteredDomains: Domain[] = [
|
||||||
Mock.of<Domain>({ domain: 'foo', status: 'validating' }),
|
fromPartial({ domain: 'foo', status: 'validating' }),
|
||||||
Mock.of<Domain>({ domain: 'Boo', status: 'validating' }),
|
fromPartial({ domain: 'Boo', status: 'validating' }),
|
||||||
];
|
];
|
||||||
const domains = [...filteredDomains, Mock.of<Domain>({ domain: 'bar', status: 'validating' })];
|
const domains: Domain[] = [...filteredDomains, fromPartial({ domain: 'bar', status: 'validating' })];
|
||||||
const error = { type: 'NOT_FOUND', status: 404 } as unknown as Error;
|
const error = { type: 'NOT_FOUND', status: 404 } as unknown as Error;
|
||||||
const editDomainRedirectsThunk = editDomainRedirects(buildShlinkApiClient);
|
const editDomainRedirectsThunk = editDomainRedirects(buildShlinkApiClient);
|
||||||
const { reducer, listDomains: listDomainsAction, checkDomainHealth, filterDomains } = domainsListReducerCreator(
|
const { reducer, listDomains: listDomainsAction, checkDomainHealth, filterDomains } = domainsListReducerCreator(
|
||||||
|
@ -55,7 +52,7 @@ describe('domainsListReducer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('filters domains on FILTER_DOMAINS', () => {
|
it('filters domains on FILTER_DOMAINS', () => {
|
||||||
expect(reducer(Mock.of<DomainsList>({ domains }), filterDomains('oO'))).toEqual({ domains, filteredDomains });
|
expect(reducer(fromPartial({ domains }), filterDomains('oO'))).toEqual({ domains, filteredDomains });
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
|
@ -71,7 +68,7 @@ describe('domainsListReducer', () => {
|
||||||
const editDomainRedirects: EditDomainRedirects = { domain, redirects };
|
const editDomainRedirects: EditDomainRedirects = { domain, redirects };
|
||||||
|
|
||||||
expect(reducer(
|
expect(reducer(
|
||||||
Mock.of<DomainsList>({ domains, filteredDomains }),
|
fromPartial({ domains, filteredDomains }),
|
||||||
editDomainRedirectsThunk.fulfilled(editDomainRedirects, '', editDomainRedirects),
|
editDomainRedirectsThunk.fulfilled(editDomainRedirects, '', editDomainRedirects),
|
||||||
)).toEqual({
|
)).toEqual({
|
||||||
domains: domains.map(replaceRedirectsOnDomain(editDomainRedirects)),
|
domains: domains.map(replaceRedirectsOnDomain(editDomainRedirects)),
|
||||||
|
@ -85,7 +82,7 @@ describe('domainsListReducer', () => {
|
||||||
['does_not_exist'],
|
['does_not_exist'],
|
||||||
])('replaces status on proper domain on VALIDATE_DOMAIN', (domain) => {
|
])('replaces status on proper domain on VALIDATE_DOMAIN', (domain) => {
|
||||||
expect(reducer(
|
expect(reducer(
|
||||||
Mock.of<DomainsList>({ domains, filteredDomains }),
|
fromPartial({ domains, filteredDomains }),
|
||||||
checkDomainHealth.fulfilled({ domain, status: 'valid' }, '', ''),
|
checkDomainHealth.fulfilled({ domain, status: 'valid' }, '', ''),
|
||||||
)).toEqual({
|
)).toEqual({
|
||||||
domains: domains.map(replaceStatusOnDomain(domain, 'valid')),
|
domains: domains.map(replaceStatusOnDomain(domain, 'valid')),
|
||||||
|
@ -122,8 +119,8 @@ describe('domainsListReducer', () => {
|
||||||
const domain = 'example.com';
|
const domain = 'example.com';
|
||||||
|
|
||||||
it('dispatches invalid status when selected server does not have all required data', async () => {
|
it('dispatches invalid status when selected server does not have all required data', async () => {
|
||||||
getState.mockReturnValue(Mock.of<ShlinkState>({
|
getState.mockReturnValue(fromPartial<ShlinkState>({
|
||||||
selectedServer: Mock.all<SelectedServer>(),
|
selectedServer: {},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
await checkDomainHealth(domain)(dispatch, getState, {});
|
await checkDomainHealth(domain)(dispatch, getState, {});
|
||||||
|
@ -136,11 +133,11 @@ describe('domainsListReducer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('dispatches invalid status when health endpoint returns an error', async () => {
|
it('dispatches invalid status when health endpoint returns an error', async () => {
|
||||||
getState.mockReturnValue(Mock.of<ShlinkState>({
|
getState.mockReturnValue(fromPartial<ShlinkState>({
|
||||||
selectedServer: Mock.of<ServerData>({
|
selectedServer: {
|
||||||
url: 'https://myerver.com',
|
url: 'https://myerver.com',
|
||||||
apiKey: '123',
|
apiKey: '123',
|
||||||
}),
|
},
|
||||||
}));
|
}));
|
||||||
health.mockRejectedValue({});
|
health.mockRejectedValue({});
|
||||||
|
|
||||||
|
@ -160,11 +157,11 @@ describe('domainsListReducer', () => {
|
||||||
healthStatus,
|
healthStatus,
|
||||||
expectedStatus,
|
expectedStatus,
|
||||||
) => {
|
) => {
|
||||||
getState.mockReturnValue(Mock.of<ShlinkState>({
|
getState.mockReturnValue(fromPartial<ShlinkState>({
|
||||||
selectedServer: Mock.of<ServerData>({
|
selectedServer: {
|
||||||
url: 'https://myerver.com',
|
url: 'https://myerver.com',
|
||||||
apiKey: '123',
|
apiKey: '123',
|
||||||
}),
|
},
|
||||||
}));
|
}));
|
||||||
health.mockResolvedValue({ status: healthStatus });
|
health.mockResolvedValue({ status: healthStatus });
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { EventSourcePolyfill } from 'event-source-polyfill';
|
import { EventSourcePolyfill } from 'event-source-polyfill';
|
||||||
import { identity } from 'ramda';
|
import { identity } from 'ramda';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import { bindToMercureTopic } from '../../../src/mercure/helpers';
|
import { bindToMercureTopic } from '../../../src/mercure/helpers';
|
||||||
import type { MercureInfo } from '../../../src/mercure/reducers/mercureInfo';
|
import type { MercureInfo } from '../../../src/mercure/reducers/mercureInfo';
|
||||||
|
|
||||||
|
@ -14,11 +14,11 @@ describe('helpers', () => {
|
||||||
const onTokenExpired = jest.fn();
|
const onTokenExpired = jest.fn();
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[Mock.of<MercureInfo>({ loading: true, error: false, mercureHubUrl: 'foo' })],
|
[fromPartial<MercureInfo>({ loading: true, error: false, mercureHubUrl: 'foo' })],
|
||||||
[Mock.of<MercureInfo>({ loading: false, error: true, mercureHubUrl: 'foo' })],
|
[fromPartial<MercureInfo>({ loading: false, error: true, mercureHubUrl: 'foo' })],
|
||||||
[Mock.of<MercureInfo>({ loading: true, error: true, mercureHubUrl: 'foo' })],
|
[fromPartial<MercureInfo>({ loading: true, error: true, mercureHubUrl: 'foo' })],
|
||||||
[Mock.of<MercureInfo>({ loading: false, error: false, mercureHubUrl: undefined })],
|
[fromPartial<MercureInfo>({ loading: false, error: false, mercureHubUrl: undefined })],
|
||||||
[Mock.of<MercureInfo>({ loading: true, error: true, mercureHubUrl: undefined })],
|
[fromPartial<MercureInfo>({ loading: true, error: true, mercureHubUrl: undefined })],
|
||||||
])('does not bind an EventSource when loading, error or no hub URL', (mercureInfo) => {
|
])('does not bind an EventSource when loading, error or no hub URL', (mercureInfo) => {
|
||||||
bindToMercureTopic(mercureInfo, [''], identity, () => {});
|
bindToMercureTopic(mercureInfo, [''], identity, () => {});
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
||||||
import type { GetState } from '../../../src/container/types';
|
import type { GetState } from '../../../src/container/types';
|
||||||
import { mercureInfoReducerCreator } from '../../../src/mercure/reducers/mercureInfo';
|
import { mercureInfoReducerCreator } from '../../../src/mercure/reducers/mercureInfo';
|
||||||
|
@ -9,7 +9,7 @@ describe('mercureInfoReducer', () => {
|
||||||
token: 'abc.123.def',
|
token: 'abc.123.def',
|
||||||
};
|
};
|
||||||
const getMercureInfo = jest.fn();
|
const getMercureInfo = jest.fn();
|
||||||
const buildShlinkApiClient = () => Mock.of<ShlinkApiClient>({ mercureInfo: getMercureInfo });
|
const buildShlinkApiClient = () => fromPartial<ShlinkApiClient>({ mercureInfo: getMercureInfo });
|
||||||
const { loadMercureInfo, reducer } = mercureInfoReducerCreator(buildShlinkApiClient);
|
const { loadMercureInfo, reducer } = mercureInfoReducerCreator(buildShlinkApiClient);
|
||||||
|
|
||||||
beforeEach(jest.resetAllMocks);
|
beforeEach(jest.resetAllMocks);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { fireEvent, screen, waitFor } from '@testing-library/react';
|
import { fireEvent, screen, waitFor } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import { CreateServer as createCreateServer } from '../../src/servers/CreateServer';
|
import { CreateServer as createCreateServer } from '../../src/servers/CreateServer';
|
||||||
import type { ServerWithId } from '../../src/servers/data';
|
import type { ServerWithId } from '../../src/servers/data';
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
|
@ -10,7 +10,7 @@ jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom')
|
||||||
describe('<CreateServer />', () => {
|
describe('<CreateServer />', () => {
|
||||||
const createServersMock = jest.fn();
|
const createServersMock = jest.fn();
|
||||||
const navigate = jest.fn();
|
const navigate = jest.fn();
|
||||||
const servers = { foo: Mock.of<ServerWithId>({ url: 'https://existing_url.com', apiKey: 'existing_api_key' }) };
|
const servers = { foo: fromPartial<ServerWithId>({ url: 'https://existing_url.com', apiKey: 'existing_api_key' }) };
|
||||||
const setUp = (serversImported = false, importFailed = false) => {
|
const setUp = (serversImported = false, importFailed = false) => {
|
||||||
(useNavigate as any).mockReturnValue(navigate);
|
(useNavigate as any).mockReturnValue(navigate);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { screen, waitFor } from '@testing-library/react';
|
import { screen, waitFor } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { ServerWithId } from '../../src/servers/data';
|
|
||||||
import { DeleteServerButton as createDeleteServerButton } from '../../src/servers/DeleteServerButton';
|
import { DeleteServerButton as createDeleteServerButton } from '../../src/servers/DeleteServerButton';
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
|
|
||||||
|
@ -10,7 +9,7 @@ describe('<DeleteServerButton />', () => {
|
||||||
({ isOpen }) => <>DeleteServerModal {isOpen ? '[Open]' : '[Closed]'}</>,
|
({ isOpen }) => <>DeleteServerModal {isOpen ? '[Open]' : '[Closed]'}</>,
|
||||||
);
|
);
|
||||||
const setUp = (children?: ReactNode) => renderWithEvents(
|
const setUp = (children?: ReactNode) => renderWithEvents(
|
||||||
<DeleteServerButton server={Mock.all<ServerWithId>()} textClassName="button">{children}</DeleteServerButton>,
|
<DeleteServerButton server={fromPartial({})} textClassName="button">{children}</DeleteServerButton>,
|
||||||
);
|
);
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { screen, waitFor } from '@testing-library/react';
|
import { screen, waitFor } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { ServerWithId } from '../../src/servers/data';
|
|
||||||
import { DeleteServerModal } from '../../src/servers/DeleteServerModal';
|
import { DeleteServerModal } from '../../src/servers/DeleteServerModal';
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
import { TestModalWrapper } from '../__helpers__/TestModalWrapper';
|
import { TestModalWrapper } from '../__helpers__/TestModalWrapper';
|
||||||
|
@ -20,7 +19,7 @@ describe('<DeleteServerModal />', () => {
|
||||||
renderModal={(args) => (
|
renderModal={(args) => (
|
||||||
<DeleteServerModal
|
<DeleteServerModal
|
||||||
{...args}
|
{...args}
|
||||||
server={Mock.of<ServerWithId>({ name: serverName })}
|
server={fromPartial({ name: serverName })}
|
||||||
deleteServer={deleteServerMock}
|
deleteServer={deleteServerMock}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { fireEvent, screen } from '@testing-library/react';
|
import { fireEvent, screen } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { MemoryRouter, useNavigate } from 'react-router-dom';
|
import { MemoryRouter, useNavigate } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { ReachableServer, SelectedServer } from '../../src/servers/data';
|
import type { ReachableServer, SelectedServer } from '../../src/servers/data';
|
||||||
import { EditServer as editServerConstruct } from '../../src/servers/EditServer';
|
import { EditServer as editServerConstruct } from '../../src/servers/EditServer';
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
|
@ -11,7 +11,7 @@ describe('<EditServer />', () => {
|
||||||
const ServerError = jest.fn();
|
const ServerError = jest.fn();
|
||||||
const editServerMock = jest.fn();
|
const editServerMock = jest.fn();
|
||||||
const navigate = jest.fn();
|
const navigate = jest.fn();
|
||||||
const defaultSelectedServer = Mock.of<ReachableServer>({
|
const defaultSelectedServer = fromPartial<ReachableServer>({
|
||||||
id: 'abc123',
|
id: 'abc123',
|
||||||
name: 'the_name',
|
name: 'the_name',
|
||||||
url: 'the_url',
|
url: 'the_url',
|
||||||
|
@ -31,7 +31,7 @@ describe('<EditServer />', () => {
|
||||||
afterEach(jest.clearAllMocks);
|
afterEach(jest.clearAllMocks);
|
||||||
|
|
||||||
it('renders nothing if selected server is not reachable', () => {
|
it('renders nothing if selected server is not reachable', () => {
|
||||||
setUp(Mock.all<SelectedServer>());
|
setUp(fromPartial<SelectedServer>({}));
|
||||||
|
|
||||||
expect(screen.queryByText('Edit')).not.toBeInTheDocument();
|
expect(screen.queryByText('Edit')).not.toBeInTheDocument();
|
||||||
expect(screen.queryByText('Cancel')).not.toBeInTheDocument();
|
expect(screen.queryByText('Cancel')).not.toBeInTheDocument();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { screen, waitFor } from '@testing-library/react';
|
import { screen, waitFor } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { ServersMap, ServerWithId } from '../../src/servers/data';
|
import type { ServersMap, ServerWithId } from '../../src/servers/data';
|
||||||
import { ManageServers as createManageServers } from '../../src/servers/ManageServers';
|
import { ManageServers as createManageServers } from '../../src/servers/ManageServers';
|
||||||
import type { ServersExporter } from '../../src/servers/services/ServersExporter';
|
import type { ServersExporter } from '../../src/servers/services/ServersExporter';
|
||||||
|
@ -8,7 +8,7 @@ import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
|
|
||||||
describe('<ManageServers />', () => {
|
describe('<ManageServers />', () => {
|
||||||
const exportServers = jest.fn();
|
const exportServers = jest.fn();
|
||||||
const serversExporter = Mock.of<ServersExporter>({ exportServers });
|
const serversExporter = fromPartial<ServersExporter>({ exportServers });
|
||||||
const useTimeoutToggle = jest.fn().mockReturnValue([false, jest.fn()]);
|
const useTimeoutToggle = jest.fn().mockReturnValue([false, jest.fn()]);
|
||||||
const ManageServers = createManageServers(
|
const ManageServers = createManageServers(
|
||||||
serversExporter,
|
serversExporter,
|
||||||
|
@ -16,7 +16,7 @@ describe('<ManageServers />', () => {
|
||||||
useTimeoutToggle,
|
useTimeoutToggle,
|
||||||
({ hasAutoConnect }) => <tr><td>ManageServersRow {hasAutoConnect ? '[YES]' : '[NO]'}</td></tr>,
|
({ hasAutoConnect }) => <tr><td>ManageServersRow {hasAutoConnect ? '[YES]' : '[NO]'}</td></tr>,
|
||||||
);
|
);
|
||||||
const createServerMock = (value: string, autoConnect = false) => Mock.of<ServerWithId>(
|
const createServerMock = (value: string, autoConnect = false) => fromPartial<ServerWithId>(
|
||||||
{ id: value, name: value, url: value, autoConnect },
|
{ id: value, name: value, url: value, autoConnect },
|
||||||
);
|
);
|
||||||
const setUp = (servers: ServersMap = {}) => renderWithEvents(
|
const setUp = (servers: ServersMap = {}) => renderWithEvents(
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { ServerWithId } from '../../src/servers/data';
|
import type { ServerWithId } from '../../src/servers/data';
|
||||||
import { ManageServersRowDropdown as createManageServersRowDropdown } from '../../src/servers/ManageServersRowDropdown';
|
import { ManageServersRowDropdown as createManageServersRowDropdown } from '../../src/servers/ManageServersRowDropdown';
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
|
@ -11,7 +11,7 @@ describe('<ManageServersRowDropdown />', () => {
|
||||||
);
|
);
|
||||||
const setAutoConnect = jest.fn();
|
const setAutoConnect = jest.fn();
|
||||||
const setUp = (autoConnect = false) => {
|
const setUp = (autoConnect = false) => {
|
||||||
const server = Mock.of<ServerWithId>({ id: 'abc123', autoConnect });
|
const server = fromPartial<ServerWithId>({ id: 'abc123', autoConnect });
|
||||||
return renderWithEvents(
|
return renderWithEvents(
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<ManageServersRowDropdown setAutoConnect={setAutoConnect} server={server} />
|
<ManageServersRowDropdown setAutoConnect={setAutoConnect} server={server} />
|
||||||
|
|
|
@ -1,14 +1,9 @@
|
||||||
import { screen, waitFor } from '@testing-library/react';
|
import { screen, waitFor } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { MercureInfo } from '../../src/mercure/reducers/mercureInfo';
|
import type { MercureInfo } from '../../src/mercure/reducers/mercureInfo';
|
||||||
import type { ReachableServer } from '../../src/servers/data';
|
|
||||||
import { Overview as overviewCreator } from '../../src/servers/Overview';
|
import { Overview as overviewCreator } from '../../src/servers/Overview';
|
||||||
import type { Settings } from '../../src/settings/reducers/settings';
|
|
||||||
import type { ShortUrlsList as ShortUrlsListState } from '../../src/short-urls/reducers/shortUrlsList';
|
|
||||||
import type { TagsList } from '../../src/tags/reducers/tagsList';
|
|
||||||
import { prettify } from '../../src/utils/helpers/numbers';
|
import { prettify } from '../../src/utils/helpers/numbers';
|
||||||
import type { VisitsOverview } from '../../src/visits/reducers/visitsOverview';
|
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
|
|
||||||
describe('<Overview />', () => {
|
describe('<Overview />', () => {
|
||||||
|
@ -28,18 +23,18 @@ describe('<Overview />', () => {
|
||||||
listShortUrls={listShortUrls}
|
listShortUrls={listShortUrls}
|
||||||
listTags={listTags}
|
listTags={listTags}
|
||||||
loadVisitsOverview={loadVisitsOverview}
|
loadVisitsOverview={loadVisitsOverview}
|
||||||
shortUrlsList={Mock.of<ShortUrlsListState>({ loading, shortUrls })}
|
shortUrlsList={fromPartial({ loading, shortUrls })}
|
||||||
tagsList={Mock.of<TagsList>({ loading, tags: ['foo', 'bar', 'baz'] })}
|
tagsList={fromPartial({ loading, tags: ['foo', 'bar', 'baz'] })}
|
||||||
visitsOverview={Mock.of<VisitsOverview>({
|
visitsOverview={fromPartial({
|
||||||
loading,
|
loading,
|
||||||
nonOrphanVisits: { total: 3456, bots: 1000, nonBots: 2456 },
|
nonOrphanVisits: { total: 3456, bots: 1000, nonBots: 2456 },
|
||||||
orphanVisits: { total: 28, bots: 15, nonBots: 13 },
|
orphanVisits: { total: 28, bots: 15, nonBots: 13 },
|
||||||
})}
|
})}
|
||||||
selectedServer={Mock.of<ReachableServer>({ id: serverId })}
|
selectedServer={fromPartial({ id: serverId })}
|
||||||
createNewVisits={jest.fn()}
|
createNewVisits={jest.fn()}
|
||||||
loadMercureInfo={jest.fn()}
|
loadMercureInfo={jest.fn()}
|
||||||
mercureInfo={Mock.all<MercureInfo>()}
|
mercureInfo={fromPartial<MercureInfo>({})}
|
||||||
settings={Mock.of<Settings>({ visits: { excludeBots } })}
|
settings={fromPartial({ visits: { excludeBots } })}
|
||||||
/>
|
/>
|
||||||
</MemoryRouter>,
|
</MemoryRouter>,
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { values } from 'ramda';
|
import { values } from 'ramda';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
import type { ServersMap } from '../../src/servers/data';
|
||||||
import type { ServersMap, ServerWithId } from '../../src/servers/data';
|
|
||||||
import { ServersDropdown } from '../../src/servers/ServersDropdown';
|
import { ServersDropdown } from '../../src/servers/ServersDropdown';
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
|
|
||||||
describe('<ServersDropdown />', () => {
|
describe('<ServersDropdown />', () => {
|
||||||
const fallbackServers: ServersMap = {
|
const fallbackServers: ServersMap = {
|
||||||
'1a': Mock.of<ServerWithId>({ name: 'foo', id: '1a' }),
|
'1a': fromPartial({ name: 'foo', id: '1a' }),
|
||||||
'2b': Mock.of<ServerWithId>({ name: 'bar', id: '2b' }),
|
'2b': fromPartial({ name: 'bar', id: '2b' }),
|
||||||
'3c': Mock.of<ServerWithId>({ name: 'baz', id: '3c' }),
|
'3c': fromPartial({ name: 'baz', id: '3c' }),
|
||||||
};
|
};
|
||||||
const setUp = (servers: ServersMap = fallbackServers) => renderWithEvents(
|
const setUp = (servers: ServersMap = fallbackServers) => renderWithEvents(
|
||||||
<MemoryRouter><ServersDropdown servers={servers} selectedServer={null} /></MemoryRouter>,
|
<MemoryRouter><ServersDropdown servers={servers} selectedServer={null} /></MemoryRouter>,
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { ServerWithId } from '../../src/servers/data';
|
import type { ServerWithId } from '../../src/servers/data';
|
||||||
import { ServersListGroup } from '../../src/servers/ServersListGroup';
|
import { ServersListGroup } from '../../src/servers/ServersListGroup';
|
||||||
|
|
||||||
describe('<ServersListGroup />', () => {
|
describe('<ServersListGroup />', () => {
|
||||||
const servers = [
|
const servers: ServerWithId[] = [
|
||||||
Mock.of<ServerWithId>({ name: 'foo', id: '123' }),
|
fromPartial({ name: 'foo', id: '123' }),
|
||||||
Mock.of<ServerWithId>({ name: 'bar', id: '456' }),
|
fromPartial({ name: 'bar', id: '456' }),
|
||||||
];
|
];
|
||||||
const setUp = (params: { servers?: ServerWithId[]; withChildren?: boolean; embedded?: boolean }) => {
|
const setUp = (params: { servers?: ServerWithId[]; withChildren?: boolean; embedded?: boolean }) => {
|
||||||
const { servers = [], withChildren = true, embedded } = params;
|
const { servers = [], withChildren = true, embedded } = params;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ServerData } from '../../../src/servers/data';
|
import type { ServerData } from '../../../src/servers/data';
|
||||||
import { DuplicatedServersModal } from '../../../src/servers/helpers/DuplicatedServersModal';
|
import { DuplicatedServersModal } from '../../../src/servers/helpers/DuplicatedServersModal';
|
||||||
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
||||||
|
@ -10,15 +10,16 @@ describe('<DuplicatedServersModal />', () => {
|
||||||
const setUp = (duplicatedServers: ServerData[] = []) => renderWithEvents(
|
const setUp = (duplicatedServers: ServerData[] = []) => renderWithEvents(
|
||||||
<DuplicatedServersModal isOpen duplicatedServers={duplicatedServers} onDiscard={onDiscard} onSave={onSave} />,
|
<DuplicatedServersModal isOpen duplicatedServers={duplicatedServers} onDiscard={onDiscard} onSave={onSave} />,
|
||||||
);
|
);
|
||||||
|
const mockServer = (data: Partial<ServerData> = {}) => fromPartial<ServerData>(data);
|
||||||
|
|
||||||
beforeEach(jest.clearAllMocks);
|
beforeEach(jest.clearAllMocks);
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[[], 0],
|
[[], 0],
|
||||||
[[Mock.all<ServerData>()], 2],
|
[[mockServer()], 2],
|
||||||
[[Mock.all<ServerData>(), Mock.all<ServerData>()], 2],
|
[[mockServer(), mockServer()], 2],
|
||||||
[[Mock.all<ServerData>(), Mock.all<ServerData>(), Mock.all<ServerData>()], 3],
|
[[mockServer(), mockServer(), mockServer()], 3],
|
||||||
[[Mock.all<ServerData>(), Mock.all<ServerData>(), Mock.all<ServerData>(), Mock.all<ServerData>()], 4],
|
[[mockServer(), mockServer(), mockServer(), mockServer()], 4],
|
||||||
])('renders expected amount of items', (duplicatedServers, expectedItems) => {
|
])('renders expected amount of items', (duplicatedServers, expectedItems) => {
|
||||||
setUp(duplicatedServers);
|
setUp(duplicatedServers);
|
||||||
expect(screen.queryAllByRole('listitem')).toHaveLength(expectedItems);
|
expect(screen.queryAllByRole('listitem')).toHaveLength(expectedItems);
|
||||||
|
@ -26,7 +27,7 @@ describe('<DuplicatedServersModal />', () => {
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[
|
[
|
||||||
[Mock.all<ServerData>()],
|
[mockServer()],
|
||||||
{
|
{
|
||||||
header: 'Duplicated server',
|
header: 'Duplicated server',
|
||||||
firstParagraph: 'There is already a server with:',
|
firstParagraph: 'There is already a server with:',
|
||||||
|
@ -35,7 +36,7 @@ describe('<DuplicatedServersModal />', () => {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
[Mock.all<ServerData>(), Mock.all<ServerData>()],
|
[mockServer(), mockServer()],
|
||||||
{
|
{
|
||||||
header: 'Duplicated servers',
|
header: 'Duplicated servers',
|
||||||
firstParagraph: 'The next servers already exist:',
|
firstParagraph: 'The next servers already exist:',
|
||||||
|
@ -54,10 +55,10 @@ describe('<DuplicatedServersModal />', () => {
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[[]],
|
[[]],
|
||||||
[[Mock.of<ServerData>({ url: 'url', apiKey: 'apiKey' })]],
|
[[mockServer({ url: 'url', apiKey: 'apiKey' })]],
|
||||||
[[
|
[[
|
||||||
Mock.of<ServerData>({ url: 'url_1', apiKey: 'apiKey_1' }),
|
mockServer({ url: 'url_1', apiKey: 'apiKey_1' }),
|
||||||
Mock.of<ServerData>({ url: 'url_2', apiKey: 'apiKey_2' }),
|
mockServer({ url: 'url_2', apiKey: 'apiKey_2' }),
|
||||||
]],
|
]],
|
||||||
])('displays provided server data', (duplicatedServers) => {
|
])('displays provided server data', (duplicatedServers) => {
|
||||||
setUp(duplicatedServers);
|
setUp(duplicatedServers);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { fireEvent, screen, waitFor } from '@testing-library/react';
|
import { fireEvent, screen, waitFor } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ServersMap, ServerWithId } from '../../../src/servers/data';
|
import type { ServersMap, ServerWithId } from '../../../src/servers/data';
|
||||||
import type {
|
import type {
|
||||||
ImportServersBtnProps } from '../../../src/servers/helpers/ImportServersBtn';
|
ImportServersBtnProps } from '../../../src/servers/helpers/ImportServersBtn';
|
||||||
|
@ -13,7 +13,7 @@ describe('<ImportServersBtn />', () => {
|
||||||
const onImportMock = jest.fn();
|
const onImportMock = jest.fn();
|
||||||
const createServersMock = jest.fn();
|
const createServersMock = jest.fn();
|
||||||
const importServersFromFile = jest.fn().mockResolvedValue([]);
|
const importServersFromFile = jest.fn().mockResolvedValue([]);
|
||||||
const serversImporterMock = Mock.of<ServersImporter>({ importServersFromFile });
|
const serversImporterMock = fromPartial<ServersImporter>({ importServersFromFile });
|
||||||
const ImportServersBtn = createImportServersBtn(serversImporterMock);
|
const ImportServersBtn = createImportServersBtn(serversImporterMock);
|
||||||
const setUp = (props: Partial<ImportServersBtnProps> = {}, servers: ServersMap = {}) => renderWithEvents(
|
const setUp = (props: Partial<ImportServersBtnProps> = {}, servers: ServersMap = {}) => renderWithEvents(
|
||||||
<ImportServersBtn
|
<ImportServersBtn
|
||||||
|
@ -67,8 +67,8 @@ describe('<ImportServersBtn />', () => {
|
||||||
['Save anyway', true],
|
['Save anyway', true],
|
||||||
['Discard', false],
|
['Discard', false],
|
||||||
])('creates expected servers depending on selected option in modal', async (btnName, savesDuplicatedServers) => {
|
])('creates expected servers depending on selected option in modal', async (btnName, savesDuplicatedServers) => {
|
||||||
const existingServer = Mock.of<ServerWithId>({ id: 'abc', url: 'existingUrl', apiKey: 'existingApiKey' });
|
const existingServer = fromPartial<ServerWithId>({ id: 'abc', url: 'existingUrl', apiKey: 'existingApiKey' });
|
||||||
const newServer = Mock.of<ServerWithId>({ url: 'newUrl', apiKey: 'newApiKey' });
|
const newServer = fromPartial<ServerWithId>({ url: 'newUrl', apiKey: 'newApiKey' });
|
||||||
const { container, user } = setUp({}, { abc: existingServer });
|
const { container, user } = setUp({}, { abc: existingServer });
|
||||||
const input = container.querySelector('[type=file]');
|
const input = container.querySelector('[type=file]');
|
||||||
importServersFromFile.mockResolvedValue([existingServer, newServer]);
|
importServersFromFile.mockResolvedValue([existingServer, newServer]);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { NonReachableServer, NotFoundServer } from '../../../src/servers/data';
|
import type { NonReachableServer, NotFoundServer } from '../../../src/servers/data';
|
||||||
import { ServerError as createServerError } from '../../../src/servers/helpers/ServerError';
|
import { ServerError as createServerError } from '../../../src/servers/helpers/ServerError';
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ describe('<ServerError />', () => {
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[
|
[
|
||||||
Mock.all<NotFoundServer>(),
|
fromPartial<NotFoundServer>({}),
|
||||||
{
|
{
|
||||||
found: ['Could not find this Shlink server.'],
|
found: ['Could not find this Shlink server.'],
|
||||||
notFound: [
|
notFound: [
|
||||||
|
@ -20,7 +20,7 @@ describe('<ServerError />', () => {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
Mock.of<NonReachableServer>({ id: 'abc123' }),
|
fromPartial<NonReachableServer>({ id: 'abc123' }),
|
||||||
{
|
{
|
||||||
found: [
|
found: [
|
||||||
'Oops! Could not connect to this Shlink server.',
|
'Oops! Could not connect to this Shlink server.',
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { HttpClient } from '../../../src/common/services/HttpClient';
|
import type { HttpClient } from '../../../src/common/services/HttpClient';
|
||||||
import { fetchServers } from '../../../src/servers/reducers/remoteServers';
|
import { fetchServers } from '../../../src/servers/reducers/remoteServers';
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ describe('remoteServersReducer', () => {
|
||||||
describe('fetchServers', () => {
|
describe('fetchServers', () => {
|
||||||
const dispatch = jest.fn();
|
const dispatch = jest.fn();
|
||||||
const fetchJson = jest.fn();
|
const fetchJson = jest.fn();
|
||||||
const httpClient = Mock.of<HttpClient>({ fetchJson });
|
const httpClient = fromPartial<HttpClient>({ fetchJson });
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[
|
[
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { v4 as uuid } from 'uuid';
|
import { v4 as uuid } from 'uuid';
|
||||||
import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
||||||
import type { ShlinkState } from '../../../src/container/types';
|
import type { ShlinkState } from '../../../src/container/types';
|
||||||
|
@ -15,7 +15,7 @@ import {
|
||||||
describe('selectedServerReducer', () => {
|
describe('selectedServerReducer', () => {
|
||||||
const dispatch = jest.fn();
|
const dispatch = jest.fn();
|
||||||
const health = jest.fn();
|
const health = jest.fn();
|
||||||
const buildApiClient = jest.fn().mockReturnValue(Mock.of<ShlinkApiClient>({ health }));
|
const buildApiClient = jest.fn().mockReturnValue(fromPartial<ShlinkApiClient>({ health }));
|
||||||
const selectServer = selectServerCreator(buildApiClient);
|
const selectServer = selectServerCreator(buildApiClient);
|
||||||
const { reducer } = selectedServerReducerCreator(selectServer);
|
const { reducer } = selectedServerReducerCreator(selectServer);
|
||||||
|
|
||||||
|
@ -26,8 +26,7 @@ describe('selectedServerReducer', () => {
|
||||||
expect(reducer(null, resetSelectedServer())).toBeNull());
|
expect(reducer(null, resetSelectedServer())).toBeNull());
|
||||||
|
|
||||||
it('returns selected server when action is SELECT_SERVER', () => {
|
it('returns selected server when action is SELECT_SERVER', () => {
|
||||||
const payload = Mock.of<RegularServer>({ id: 'abc123' });
|
const payload = fromPartial<RegularServer>({ id: 'abc123' });
|
||||||
|
|
||||||
expect(reducer(null, selectServer.fulfilled(payload, '', ''))).toEqual(payload);
|
expect(reducer(null, selectServer.fulfilled(payload, '', ''))).toEqual(payload);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -66,7 +65,7 @@ describe('selectedServerReducer', () => {
|
||||||
it('dispatches error when health endpoint fails', async () => {
|
it('dispatches error when health endpoint fails', async () => {
|
||||||
const id = uuid();
|
const id = uuid();
|
||||||
const getState = createGetStateMock(id);
|
const getState = createGetStateMock(id);
|
||||||
const expectedSelectedServer = Mock.of<NonReachableServer>({ id, serverNotReachable: true });
|
const expectedSelectedServer = fromPartial<NonReachableServer>({ id, serverNotReachable: true });
|
||||||
|
|
||||||
health.mockRejectedValue({});
|
health.mockRejectedValue({});
|
||||||
|
|
||||||
|
@ -78,7 +77,7 @@ describe('selectedServerReducer', () => {
|
||||||
|
|
||||||
it('dispatches error when server is not found', async () => {
|
it('dispatches error when server is not found', async () => {
|
||||||
const id = uuid();
|
const id = uuid();
|
||||||
const getState = jest.fn(() => Mock.of<ShlinkState>({ servers: {} }));
|
const getState = jest.fn(() => fromPartial<ShlinkState>({ servers: {} }));
|
||||||
const expectedSelectedServer: NotFoundServer = { serverNotFound: true };
|
const expectedSelectedServer: NotFoundServer = { serverNotFound: true };
|
||||||
|
|
||||||
await selectServer(id)(dispatch, getState, {});
|
await selectServer(id)(dispatch, getState, {});
|
||||||
|
@ -95,9 +94,9 @@ describe('selectedServerReducer', () => {
|
||||||
const { middleware } = selectServerListener(selectServer, loadMercureInfo);
|
const { middleware } = selectServerListener(selectServer, loadMercureInfo);
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[Mock.of<ReachableServer>({ version: '1.2.3' }), 1],
|
[fromPartial<ReachableServer>({ version: '1.2.3' }), 1],
|
||||||
[Mock.of<NotFoundServer>({ serverNotFound: true }), 0],
|
[fromPartial<NotFoundServer>({ serverNotFound: true }), 0],
|
||||||
[Mock.of<NonReachableServer>({ serverNotReachable: true }), 0],
|
[fromPartial<NonReachableServer>({ serverNotReachable: true }), 0],
|
||||||
])('dispatches loadMercureInfo when provided server is reachable', (payload, expectedCalls) => {
|
])('dispatches loadMercureInfo when provided server is reachable', (payload, expectedCalls) => {
|
||||||
middleware({ dispatch, getState })(jest.fn())({
|
middleware({ dispatch, getState })(jest.fn())({
|
||||||
payload,
|
payload,
|
||||||
|
@ -110,7 +109,7 @@ describe('selectedServerReducer', () => {
|
||||||
|
|
||||||
it('does not dispatch loadMercureInfo when action is not of the proper type', () => {
|
it('does not dispatch loadMercureInfo when action is not of the proper type', () => {
|
||||||
middleware({ dispatch, getState })(jest.fn())({
|
middleware({ dispatch, getState })(jest.fn())({
|
||||||
payload: Mock.of<ReachableServer>({ version: '1.2.3' }),
|
payload: fromPartial<ReachableServer>({ version: '1.2.3' }),
|
||||||
type: 'something_else',
|
type: 'something_else',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { dissoc, values } from 'ramda';
|
import { dissoc, values } from 'ramda';
|
||||||
import { Mock } from 'ts-mockery';
|
import type { RegularServer, ServersMap, ServerWithId } from '../../../src/servers/data';
|
||||||
import type { RegularServer, ServerWithId } from '../../../src/servers/data';
|
|
||||||
import {
|
import {
|
||||||
createServers,
|
createServers,
|
||||||
deleteServer,
|
deleteServer,
|
||||||
|
@ -10,9 +10,9 @@ import {
|
||||||
} from '../../../src/servers/reducers/servers';
|
} from '../../../src/servers/reducers/servers';
|
||||||
|
|
||||||
describe('serversReducer', () => {
|
describe('serversReducer', () => {
|
||||||
const list = {
|
const list: ServersMap = {
|
||||||
abc123: Mock.of<RegularServer>({ id: 'abc123' }),
|
abc123: fromPartial({ id: 'abc123' }),
|
||||||
def456: Mock.of<RegularServer>({ id: 'def456' }),
|
def456: fromPartial({ id: 'def456' }),
|
||||||
};
|
};
|
||||||
|
|
||||||
afterEach(jest.clearAllMocks);
|
afterEach(jest.clearAllMocks);
|
||||||
|
@ -31,12 +31,12 @@ describe('serversReducer', () => {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('removes server when action is DELETE_SERVER', () =>
|
it('removes server when action is DELETE_SERVER', () =>
|
||||||
expect(serversReducer(list, deleteServer(Mock.of<ServerWithId>({ id: 'abc123' })))).toEqual({
|
expect(serversReducer(list, deleteServer(fromPartial<ServerWithId>({ id: 'abc123' })))).toEqual({
|
||||||
def456: { id: 'def456' },
|
def456: { id: 'def456' },
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('appends server when action is CREATE_SERVERS', () =>
|
it('appends server when action is CREATE_SERVERS', () =>
|
||||||
expect(serversReducer(list, createServers([Mock.of<ServerWithId>({ id: 'ghi789' })]))).toEqual({
|
expect(serversReducer(list, createServers([fromPartial<ServerWithId>({ id: 'ghi789' })]))).toEqual({
|
||||||
abc123: { id: 'abc123' },
|
abc123: { id: 'abc123' },
|
||||||
def456: { id: 'def456' },
|
def456: { id: 'def456' },
|
||||||
ghi789: { id: 'ghi789' },
|
ghi789: { id: 'ghi789' },
|
||||||
|
@ -46,7 +46,7 @@ describe('serversReducer', () => {
|
||||||
[true],
|
[true],
|
||||||
[false],
|
[false],
|
||||||
])('returns state as it is when trying to set auto-connect on invalid server', (autoConnect) =>
|
])('returns state as it is when trying to set auto-connect on invalid server', (autoConnect) =>
|
||||||
expect(serversReducer(list, setAutoConnect(Mock.of<ServerWithId>({ id: 'invalid' }), autoConnect))).toEqual({
|
expect(serversReducer(list, setAutoConnect(fromPartial<ServerWithId>({ id: 'invalid' }), autoConnect))).toEqual({
|
||||||
abc123: { id: 'abc123' },
|
abc123: { id: 'abc123' },
|
||||||
def456: { id: 'def456' },
|
def456: { id: 'def456' },
|
||||||
}));
|
}));
|
||||||
|
@ -59,7 +59,7 @@ describe('serversReducer', () => {
|
||||||
|
|
||||||
expect(serversReducer(
|
expect(serversReducer(
|
||||||
listWithDisabledAutoConnect,
|
listWithDisabledAutoConnect,
|
||||||
setAutoConnect(Mock.of<ServerWithId>({ id: 'abc123' }), false),
|
setAutoConnect(fromPartial<ServerWithId>({ id: 'abc123' }), false),
|
||||||
)).toEqual({
|
)).toEqual({
|
||||||
abc123: { id: 'abc123', autoConnect: false },
|
abc123: { id: 'abc123', autoConnect: false },
|
||||||
def456: { id: 'def456' },
|
def456: { id: 'def456' },
|
||||||
|
@ -74,7 +74,7 @@ describe('serversReducer', () => {
|
||||||
|
|
||||||
expect(serversReducer(
|
expect(serversReducer(
|
||||||
listWithEnabledAutoConnect,
|
listWithEnabledAutoConnect,
|
||||||
setAutoConnect(Mock.of<ServerWithId>({ id: 'def456' }), true),
|
setAutoConnect(fromPartial<ServerWithId>({ id: 'def456' }), true),
|
||||||
)).toEqual({
|
)).toEqual({
|
||||||
abc123: { id: 'abc123', autoConnect: false },
|
abc123: { id: 'abc123', autoConnect: false },
|
||||||
def456: { id: 'def456', autoConnect: true },
|
def456: { id: 'def456', autoConnect: true },
|
||||||
|
@ -94,7 +94,7 @@ describe('serversReducer', () => {
|
||||||
|
|
||||||
describe('deleteServer', () => {
|
describe('deleteServer', () => {
|
||||||
it('returns expected action', () => {
|
it('returns expected action', () => {
|
||||||
const serverToDelete = Mock.of<RegularServer>({ id: 'abc123' });
|
const serverToDelete = fromPartial<RegularServer>({ id: 'abc123' });
|
||||||
const { payload } = deleteServer(serverToDelete);
|
const { payload } = deleteServer(serverToDelete);
|
||||||
|
|
||||||
expect(payload).toEqual({ id: 'abc123' });
|
expect(payload).toEqual({ id: 'abc123' });
|
||||||
|
@ -122,7 +122,7 @@ describe('serversReducer', () => {
|
||||||
[true],
|
[true],
|
||||||
[false],
|
[false],
|
||||||
])('returns expected action', (autoConnect) => {
|
])('returns expected action', (autoConnect) => {
|
||||||
const serverToEdit = Mock.of<RegularServer>({ id: 'abc123' });
|
const serverToEdit = fromPartial<RegularServer>({ id: 'abc123' });
|
||||||
const { payload } = setAutoConnect(serverToEdit, autoConnect);
|
const { payload } = setAutoConnect(serverToEdit, autoConnect);
|
||||||
|
|
||||||
expect(payload).toEqual({ serverId: 'abc123', autoConnect });
|
expect(payload).toEqual({ serverId: 'abc123', autoConnect });
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { ServersExporter } from '../../../src/servers/services/ServersExporter';
|
import { ServersExporter } from '../../../src/servers/services/ServersExporter';
|
||||||
import type { LocalStorage } from '../../../src/utils/services/LocalStorage';
|
import type { LocalStorage } from '../../../src/utils/services/LocalStorage';
|
||||||
import { appendChild, removeChild, windowMock } from '../../__mocks__/Window.mock';
|
import { appendChild, removeChild, windowMock } from '../../__mocks__/Window.mock';
|
||||||
|
|
||||||
describe('ServersExporter', () => {
|
describe('ServersExporter', () => {
|
||||||
const storageMock = Mock.of<LocalStorage>({
|
const storageMock = fromPartial<LocalStorage>({
|
||||||
get: jest.fn(() => ({
|
get: jest.fn(() => ({
|
||||||
abc123: {
|
abc123: {
|
||||||
id: 'abc123',
|
id: 'abc123',
|
||||||
|
@ -16,7 +16,7 @@ describe('ServersExporter', () => {
|
||||||
name: 'bar',
|
name: 'bar',
|
||||||
autoConnect: false,
|
autoConnect: false,
|
||||||
},
|
},
|
||||||
})),
|
} as any)),
|
||||||
});
|
});
|
||||||
const erroneousToCsv = jest.fn(() => {
|
const erroneousToCsv = jest.fn(() => {
|
||||||
throw new Error('');
|
throw new Error('');
|
||||||
|
@ -31,7 +31,7 @@ describe('ServersExporter', () => {
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
originalConsole = global.console;
|
originalConsole = global.console;
|
||||||
global.console = Mock.of<Console>({ error });
|
global.console = fromPartial<Console>({ error });
|
||||||
(global as any).Blob = class Blob {};
|
(global as any).Blob = class Blob {};
|
||||||
(global as any).URL = { createObjectURL: () => '' };
|
(global as any).URL = { createObjectURL: () => '' };
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { RegularServer } from '../../../src/servers/data';
|
import type { RegularServer } from '../../../src/servers/data';
|
||||||
import { ServersImporter } from '../../../src/servers/services/ServersImporter';
|
import { ServersImporter } from '../../../src/servers/services/ServersImporter';
|
||||||
|
|
||||||
describe('ServersImporter', () => {
|
describe('ServersImporter', () => {
|
||||||
const servers: RegularServer[] = [Mock.all<RegularServer>(), Mock.all<RegularServer>()];
|
const servers: RegularServer[] = [fromPartial<RegularServer>({}), fromPartial<RegularServer>({})];
|
||||||
const csvjsonMock = jest.fn().mockResolvedValue(servers);
|
const csvjsonMock = jest.fn().mockResolvedValue(servers);
|
||||||
const readAsText = jest.fn();
|
const readAsText = jest.fn();
|
||||||
const fileReaderMock = Mock.of<FileReader>({
|
const fileReaderMock = fromPartial<FileReader>({
|
||||||
readAsText,
|
readAsText,
|
||||||
addEventListener: (_eventName: string, listener: (e: ProgressEvent<FileReader>) => void) => listener(
|
addEventListener: ((_eventName: string, listener: (e: ProgressEvent<FileReader>) => void) => listener(
|
||||||
Mock.of<ProgressEvent<FileReader>>({ target: { result: '' } }),
|
fromPartial({ target: { result: '' } }),
|
||||||
),
|
)) as any,
|
||||||
});
|
});
|
||||||
const importer = new ServersImporter(csvjsonMock, () => fileReaderMock);
|
const importer = new ServersImporter(csvjsonMock, () => fileReaderMock);
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ describe('ServersImporter', () => {
|
||||||
|
|
||||||
csvjsonMock.mockRejectedValue(expectedError);
|
csvjsonMock.mockRejectedValue(expectedError);
|
||||||
|
|
||||||
await expect(importer.importServersFromFile(Mock.of<File>({ type: 'text/html' }))).rejects.toEqual(expectedError);
|
await expect(importer.importServersFromFile(fromPartial({ type: 'text/html' }))).rejects.toEqual(expectedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
|
@ -57,7 +57,7 @@ describe('ServersImporter', () => {
|
||||||
])('rejects with error if provided file does not parse to valid list of servers', async (parsedObject) => {
|
])('rejects with error if provided file does not parse to valid list of servers', async (parsedObject) => {
|
||||||
csvjsonMock.mockResolvedValue(parsedObject);
|
csvjsonMock.mockResolvedValue(parsedObject);
|
||||||
|
|
||||||
await expect(importer.importServersFromFile(Mock.of<File>({ type: 'text/html' }))).rejects.toEqual(
|
await expect(importer.importServersFromFile(fromPartial({ type: 'text/html' }))).rejects.toEqual(
|
||||||
new Error('Provided file does not have the right format.'),
|
new Error('Provided file does not have the right format.'),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -78,7 +78,7 @@ describe('ServersImporter', () => {
|
||||||
|
|
||||||
csvjsonMock.mockResolvedValue(expectedServers);
|
csvjsonMock.mockResolvedValue(expectedServers);
|
||||||
|
|
||||||
const result = await importer.importServersFromFile(Mock.all<File>());
|
const result = await importer.importServersFromFile(fromPartial({}));
|
||||||
|
|
||||||
expect(result).toEqual(expectedServers);
|
expect(result).toEqual(expectedServers);
|
||||||
expect(readAsText).toHaveBeenCalledTimes(1);
|
expect(readAsText).toHaveBeenCalledTimes(1);
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { RealTimeUpdatesSettings } from '../../src/settings/RealTimeUpdatesSettings';
|
import { RealTimeUpdatesSettings } from '../../src/settings/RealTimeUpdatesSettings';
|
||||||
import type {
|
import type {
|
||||||
RealTimeUpdatesSettings as RealTimeUpdatesSettingsOptions,
|
RealTimeUpdatesSettings as RealTimeUpdatesSettingsOptions,
|
||||||
Settings,
|
|
||||||
} from '../../src/settings/reducers/settings';
|
} from '../../src/settings/reducers/settings';
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
|
|
||||||
|
@ -12,7 +11,7 @@ describe('<RealTimeUpdatesSettings />', () => {
|
||||||
const setRealTimeUpdatesInterval = jest.fn();
|
const setRealTimeUpdatesInterval = jest.fn();
|
||||||
const setUp = (realTimeUpdates: Partial<RealTimeUpdatesSettingsOptions> = {}) => renderWithEvents(
|
const setUp = (realTimeUpdates: Partial<RealTimeUpdatesSettingsOptions> = {}) => renderWithEvents(
|
||||||
<RealTimeUpdatesSettings
|
<RealTimeUpdatesSettings
|
||||||
settings={Mock.of<Settings>({ realTimeUpdates })}
|
settings={fromPartial({ realTimeUpdates })}
|
||||||
toggleRealTimeUpdates={toggleRealTimeUpdates}
|
toggleRealTimeUpdates={toggleRealTimeUpdates}
|
||||||
setRealTimeUpdatesInterval={setRealTimeUpdatesInterval}
|
setRealTimeUpdatesInterval={setRealTimeUpdatesInterval}
|
||||||
/>,
|
/>,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { Settings, ShortUrlCreationSettings as ShortUrlsSettings } from '../../src/settings/reducers/settings';
|
import type { ShortUrlCreationSettings as ShortUrlsSettings } from '../../src/settings/reducers/settings';
|
||||||
import { ShortUrlCreationSettings } from '../../src/settings/ShortUrlCreationSettings';
|
import { ShortUrlCreationSettings } from '../../src/settings/ShortUrlCreationSettings';
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ describe('<ShortUrlCreationSettings />', () => {
|
||||||
const setShortUrlCreationSettings = jest.fn();
|
const setShortUrlCreationSettings = jest.fn();
|
||||||
const setUp = (shortUrlCreation?: ShortUrlsSettings) => renderWithEvents(
|
const setUp = (shortUrlCreation?: ShortUrlsSettings) => renderWithEvents(
|
||||||
<ShortUrlCreationSettings
|
<ShortUrlCreationSettings
|
||||||
settings={Mock.of<Settings>({ shortUrlCreation })}
|
settings={fromPartial({ shortUrlCreation })}
|
||||||
setShortUrlCreationSettings={setShortUrlCreationSettings}
|
setShortUrlCreationSettings={setShortUrlCreationSettings}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { Settings, ShortUrlsListSettings as ShortUrlsSettings } from '../../src/settings/reducers/settings';
|
import type { ShortUrlsListSettings as ShortUrlsSettings } from '../../src/settings/reducers/settings';
|
||||||
import { ShortUrlsListSettings } from '../../src/settings/ShortUrlsListSettings';
|
import { ShortUrlsListSettings } from '../../src/settings/ShortUrlsListSettings';
|
||||||
import type { ShortUrlsOrder } from '../../src/short-urls/data';
|
import type { ShortUrlsOrder } from '../../src/short-urls/data';
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
|
@ -8,7 +8,7 @@ import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
describe('<ShortUrlsListSettings />', () => {
|
describe('<ShortUrlsListSettings />', () => {
|
||||||
const setSettings = jest.fn();
|
const setSettings = jest.fn();
|
||||||
const setUp = (shortUrlsList?: ShortUrlsSettings) => renderWithEvents(
|
const setUp = (shortUrlsList?: ShortUrlsSettings) => renderWithEvents(
|
||||||
<ShortUrlsListSettings settings={Mock.of<Settings>({ shortUrlsList })} setShortUrlsListSettings={setSettings} />,
|
<ShortUrlsListSettings settings={fromPartial({ shortUrlsList })} setShortUrlsListSettings={setSettings} />,
|
||||||
);
|
);
|
||||||
|
|
||||||
afterEach(jest.clearAllMocks);
|
afterEach(jest.clearAllMocks);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { Settings, TagsSettings as TagsSettingsOptions } from '../../src/settings/reducers/settings';
|
import type { TagsSettings as TagsSettingsOptions } from '../../src/settings/reducers/settings';
|
||||||
import { TagsSettings } from '../../src/settings/TagsSettings';
|
import { TagsSettings } from '../../src/settings/TagsSettings';
|
||||||
import type { TagsOrder } from '../../src/tags/data/TagsListChildrenProps';
|
import type { TagsOrder } from '../../src/tags/data/TagsListChildrenProps';
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
|
@ -8,7 +8,7 @@ import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
describe('<TagsSettings />', () => {
|
describe('<TagsSettings />', () => {
|
||||||
const setTagsSettings = jest.fn();
|
const setTagsSettings = jest.fn();
|
||||||
const setUp = (tags?: TagsSettingsOptions) => renderWithEvents(
|
const setUp = (tags?: TagsSettingsOptions) => renderWithEvents(
|
||||||
<TagsSettings settings={Mock.of<Settings>({ tags })} setTagsSettings={setTagsSettings} />,
|
<TagsSettings settings={fromPartial({ tags })} setTagsSettings={setTagsSettings} />,
|
||||||
);
|
);
|
||||||
|
|
||||||
afterEach(jest.clearAllMocks);
|
afterEach(jest.clearAllMocks);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { Settings, UiSettings } from '../../src/settings/reducers/settings';
|
import type { UiSettings } from '../../src/settings/reducers/settings';
|
||||||
import { UserInterfaceSettings } from '../../src/settings/UserInterfaceSettings';
|
import { UserInterfaceSettings } from '../../src/settings/UserInterfaceSettings';
|
||||||
import type { Theme } from '../../src/utils/theme';
|
import type { Theme } from '../../src/utils/theme';
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
|
@ -8,7 +8,7 @@ import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
describe('<UserInterfaceSettings />', () => {
|
describe('<UserInterfaceSettings />', () => {
|
||||||
const setUiSettings = jest.fn();
|
const setUiSettings = jest.fn();
|
||||||
const setUp = (ui?: UiSettings) => renderWithEvents(
|
const setUp = (ui?: UiSettings) => renderWithEvents(
|
||||||
<UserInterfaceSettings settings={Mock.of<Settings>({ ui })} setUiSettings={setUiSettings} />,
|
<UserInterfaceSettings settings={fromPartial({ ui })} setUiSettings={setUiSettings} />,
|
||||||
);
|
);
|
||||||
|
|
||||||
afterEach(jest.clearAllMocks);
|
afterEach(jest.clearAllMocks);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { Settings } from '../../src/settings/reducers/settings';
|
import type { Settings } from '../../src/settings/reducers/settings';
|
||||||
import { VisitsSettings } from '../../src/settings/VisitsSettings';
|
import { VisitsSettings } from '../../src/settings/VisitsSettings';
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
|
@ -7,7 +7,7 @@ import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
describe('<VisitsSettings />', () => {
|
describe('<VisitsSettings />', () => {
|
||||||
const setVisitsSettings = jest.fn();
|
const setVisitsSettings = jest.fn();
|
||||||
const setUp = (settings: Partial<Settings> = {}) => renderWithEvents(
|
const setUp = (settings: Partial<Settings> = {}) => renderWithEvents(
|
||||||
<VisitsSettings settings={Mock.of<Settings>(settings)} setVisitsSettings={setVisitsSettings} />,
|
<VisitsSettings settings={fromPartial(settings)} setVisitsSettings={setVisitsSettings} />,
|
||||||
);
|
);
|
||||||
|
|
||||||
afterEach(jest.clearAllMocks);
|
afterEach(jest.clearAllMocks);
|
||||||
|
@ -21,10 +21,10 @@ describe('<VisitsSettings />', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[Mock.all<Settings>(), 'Last 30 days'],
|
[fromPartial<Settings>({}), 'Last 30 days'],
|
||||||
[Mock.of<Settings>({ visits: {} }), 'Last 30 days'],
|
[fromPartial<Settings>({ visits: {} }), 'Last 30 days'],
|
||||||
[
|
[
|
||||||
Mock.of<Settings>({
|
fromPartial<Settings>({
|
||||||
visits: {
|
visits: {
|
||||||
defaultInterval: 'last7Days',
|
defaultInterval: 'last7Days',
|
||||||
},
|
},
|
||||||
|
@ -32,7 +32,7 @@ describe('<VisitsSettings />', () => {
|
||||||
'Last 7 days',
|
'Last 7 days',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
Mock.of<Settings>({
|
fromPartial<Settings>({
|
||||||
visits: {
|
visits: {
|
||||||
defaultInterval: 'today',
|
defaultInterval: 'today',
|
||||||
},
|
},
|
||||||
|
@ -63,17 +63,17 @@ describe('<VisitsSettings />', () => {
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[
|
[
|
||||||
Mock.all<Settings>(),
|
fromPartial<Settings>({}),
|
||||||
/The visits coming from potential bots will be included.$/,
|
/The visits coming from potential bots will be included.$/,
|
||||||
/The visits coming from potential bots will be excluded.$/,
|
/The visits coming from potential bots will be excluded.$/,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
Mock.of<Settings>({ visits: { excludeBots: false } }),
|
fromPartial<Settings>({ visits: { excludeBots: false } }),
|
||||||
/The visits coming from potential bots will be included.$/,
|
/The visits coming from potential bots will be included.$/,
|
||||||
/The visits coming from potential bots will be excluded.$/,
|
/The visits coming from potential bots will be excluded.$/,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
Mock.of<Settings>({ visits: { excludeBots: true } }),
|
fromPartial<Settings>({ visits: { excludeBots: true } }),
|
||||||
/The visits coming from potential bots will be excluded.$/,
|
/The visits coming from potential bots will be excluded.$/,
|
||||||
/The visits coming from potential bots will be included.$/,
|
/The visits coming from potential bots will be included.$/,
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShlinkState } from '../../../src/container/types';
|
import type { ShlinkState } from '../../../src/container/types';
|
||||||
import { migrateDeprecatedSettings } from '../../../src/settings/helpers';
|
import { migrateDeprecatedSettings } from '../../../src/settings/helpers';
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ describe('settings-helpers', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('updates settings as expected', () => {
|
it('updates settings as expected', () => {
|
||||||
const state = Mock.of<ShlinkState>({
|
const state = fromPartial<ShlinkState>({
|
||||||
settings: {
|
settings: {
|
||||||
visits: {
|
visits: {
|
||||||
defaultInterval: 'last180days' as any,
|
defaultInterval: 'last180days' as any,
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { Settings } from '../../src/settings/reducers/settings';
|
|
||||||
import { CreateShortUrl as createShortUrlsCreator } from '../../src/short-urls/CreateShortUrl';
|
import { CreateShortUrl as createShortUrlsCreator } from '../../src/short-urls/CreateShortUrl';
|
||||||
import type { ShortUrlCreation } from '../../src/short-urls/reducers/shortUrlCreation';
|
import type { ShortUrlCreation } from '../../src/short-urls/reducers/shortUrlCreation';
|
||||||
|
|
||||||
|
@ -8,7 +7,7 @@ describe('<CreateShortUrl />', () => {
|
||||||
const ShortUrlForm = () => <span>ShortUrlForm</span>;
|
const ShortUrlForm = () => <span>ShortUrlForm</span>;
|
||||||
const CreateShortUrlResult = () => <span>CreateShortUrlResult</span>;
|
const CreateShortUrlResult = () => <span>CreateShortUrlResult</span>;
|
||||||
const shortUrlCreation = { validateUrls: true };
|
const shortUrlCreation = { validateUrls: true };
|
||||||
const shortUrlCreationResult = Mock.all<ShortUrlCreation>();
|
const shortUrlCreationResult = fromPartial<ShortUrlCreation>({});
|
||||||
const createShortUrl = jest.fn(async () => Promise.resolve());
|
const createShortUrl = jest.fn(async () => Promise.resolve());
|
||||||
const CreateShortUrl = createShortUrlsCreator(ShortUrlForm, CreateShortUrlResult);
|
const CreateShortUrl = createShortUrlsCreator(ShortUrlForm, CreateShortUrlResult);
|
||||||
const setUp = () => render(
|
const setUp = () => render(
|
||||||
|
@ -17,7 +16,7 @@ describe('<CreateShortUrl />', () => {
|
||||||
createShortUrl={createShortUrl}
|
createShortUrl={createShortUrl}
|
||||||
selectedServer={null}
|
selectedServer={null}
|
||||||
resetCreateShortUrl={() => {}}
|
resetCreateShortUrl={() => {}}
|
||||||
settings={Mock.of<Settings>({ shortUrlCreation })}
|
settings={fromPartial({ shortUrlCreation })}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { Settings } from '../../src/settings/reducers/settings';
|
|
||||||
import type { ShortUrl } from '../../src/short-urls/data';
|
|
||||||
import { EditShortUrl as createEditShortUrl } from '../../src/short-urls/EditShortUrl';
|
import { EditShortUrl as createEditShortUrl } from '../../src/short-urls/EditShortUrl';
|
||||||
import type { ShortUrlDetail } from '../../src/short-urls/reducers/shortUrlDetail';
|
import type { ShortUrlDetail } from '../../src/short-urls/reducers/shortUrlDetail';
|
||||||
import type { ShortUrlEdition } from '../../src/short-urls/reducers/shortUrlEdition';
|
import type { ShortUrlEdition } from '../../src/short-urls/reducers/shortUrlEdition';
|
||||||
|
@ -13,10 +11,10 @@ describe('<EditShortUrl />', () => {
|
||||||
const setUp = (detail: Partial<ShortUrlDetail> = {}, edition: Partial<ShortUrlEdition> = {}) => render(
|
const setUp = (detail: Partial<ShortUrlDetail> = {}, edition: Partial<ShortUrlEdition> = {}) => render(
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<EditShortUrl
|
<EditShortUrl
|
||||||
settings={Mock.of<Settings>({ shortUrlCreation })}
|
settings={fromPartial({ shortUrlCreation })}
|
||||||
selectedServer={null}
|
selectedServer={null}
|
||||||
shortUrlDetail={Mock.of<ShortUrlDetail>(detail)}
|
shortUrlDetail={fromPartial(detail)}
|
||||||
shortUrlEdition={Mock.of<ShortUrlEdition>(edition)}
|
shortUrlEdition={fromPartial(edition)}
|
||||||
getShortUrlDetail={jest.fn()}
|
getShortUrlDetail={jest.fn()}
|
||||||
editShortUrl={jest.fn(async () => Promise.resolve())}
|
editShortUrl={jest.fn(async () => Promise.resolve())}
|
||||||
/>
|
/>
|
||||||
|
@ -38,7 +36,7 @@ describe('<EditShortUrl />', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders form when detail properly loads', () => {
|
it('renders form when detail properly loads', () => {
|
||||||
setUp({ shortUrl: Mock.of<ShortUrl>({ meta: {} }) });
|
setUp({ shortUrl: fromPartial({ meta: {} }) });
|
||||||
|
|
||||||
expect(screen.getByText('ShortUrlForm')).toBeInTheDocument();
|
expect(screen.getByText('ShortUrlForm')).toBeInTheDocument();
|
||||||
expect(screen.queryByText('Loading...')).not.toBeInTheDocument();
|
expect(screen.queryByText('Loading...')).not.toBeInTheDocument();
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { ShlinkPaginator } from '../../src/api/types';
|
import type { ShlinkPaginator } from '../../src/api/types';
|
||||||
import { Paginator } from '../../src/short-urls/Paginator';
|
import { Paginator } from '../../src/short-urls/Paginator';
|
||||||
import { ELLIPSIS } from '../../src/utils/helpers/pagination';
|
import { ELLIPSIS } from '../../src/utils/helpers/pagination';
|
||||||
|
|
||||||
describe('<Paginator />', () => {
|
describe('<Paginator />', () => {
|
||||||
const buildPaginator = (pagesCount?: number) => Mock.of<ShlinkPaginator>({ pagesCount, currentPage: 1 });
|
const buildPaginator = (pagesCount?: number) => fromPartial<ShlinkPaginator>({ pagesCount, currentPage: 1 });
|
||||||
const setUp = (paginator?: ShlinkPaginator, currentQueryString?: string) => render(
|
const setUp = (paginator?: ShlinkPaginator, currentQueryString?: string) => render(
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<Paginator serverId="abc123" paginator={paginator} currentQueryString={currentQueryString} />
|
<Paginator serverId="abc123" paginator={paginator} currentQueryString={currentQueryString} />
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
import type { UserEvent } from '@testing-library/user-event/setup/setup';
|
import type { UserEvent } from '@testing-library/user-event/setup/setup';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { formatISO } from 'date-fns';
|
import { formatISO } from 'date-fns';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { ReachableServer, SelectedServer } from '../../src/servers/data';
|
import type { ReachableServer, SelectedServer } from '../../src/servers/data';
|
||||||
import type { Mode } from '../../src/short-urls/ShortUrlForm';
|
import type { Mode } from '../../src/short-urls/ShortUrlForm';
|
||||||
import { ShortUrlForm as createShortUrlForm } from '../../src/short-urls/ShortUrlForm';
|
import { ShortUrlForm as createShortUrlForm } from '../../src/short-urls/ShortUrlForm';
|
||||||
|
@ -51,7 +51,7 @@ describe('<ShortUrlForm />', () => {
|
||||||
ios: 'https://ios.com',
|
ios: 'https://ios.com',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Mock.of<ReachableServer>({ version: '3.5.0' }),
|
fromPartial<ReachableServer>({ version: '3.5.0' }),
|
||||||
],
|
],
|
||||||
])('saves short URL with data set in form controls', async (extraFields, extraExpectedValues, selectedServer) => {
|
])('saves short URL with data set in form controls', async (extraFields, extraExpectedValues, selectedServer) => {
|
||||||
const { user } = setUp(selectedServer);
|
const { user } = setUp(selectedServer);
|
||||||
|
@ -102,7 +102,7 @@ describe('<ShortUrlForm />', () => {
|
||||||
[undefined, false, undefined],
|
[undefined, false, undefined],
|
||||||
['old title', false, null],
|
['old title', false, null],
|
||||||
])('sends expected title based on original and new values', async (originalTitle, withNewTitle, expectedSentTitle) => {
|
])('sends expected title based on original and new values', async (originalTitle, withNewTitle, expectedSentTitle) => {
|
||||||
const { user } = setUp(Mock.of<ReachableServer>({ version: '2.6.0' }), 'create', originalTitle);
|
const { user } = setUp(fromPartial({ version: '2.6.0' }), 'create', originalTitle);
|
||||||
|
|
||||||
await user.type(screen.getByPlaceholderText('URL to be shortened'), 'https://long-domain.com/foo/bar');
|
await user.type(screen.getByPlaceholderText('URL to be shortened'), 'https://long-domain.com/foo/bar');
|
||||||
await user.clear(screen.getByPlaceholderText('Title'));
|
await user.clear(screen.getByPlaceholderText('Title'));
|
||||||
|
@ -117,10 +117,10 @@ describe('<ShortUrlForm />', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[Mock.of<ReachableServer>({ version: '3.0.0' }), false],
|
[fromPartial<ReachableServer>({ version: '3.0.0' }), false],
|
||||||
[Mock.of<ReachableServer>({ version: '3.4.0' }), false],
|
[fromPartial<ReachableServer>({ version: '3.4.0' }), false],
|
||||||
[Mock.of<ReachableServer>({ version: '3.5.0' }), true],
|
[fromPartial<ReachableServer>({ version: '3.5.0' }), true],
|
||||||
[Mock.of<ReachableServer>({ version: '3.6.0' }), true],
|
[fromPartial<ReachableServer>({ version: '3.6.0' }), true],
|
||||||
])('shows device-specific long URLs only for servers supporting it', (selectedServer, fieldsExist) => {
|
])('shows device-specific long URLs only for servers supporting it', (selectedServer, fieldsExist) => {
|
||||||
setUp(selectedServer);
|
setUp(selectedServer);
|
||||||
const placeholders = ['Android-specific redirection', 'iOS-specific redirection', 'Desktop-specific redirection'];
|
const placeholders = ['Android-specific redirection', 'iOS-specific redirection', 'Desktop-specific redirection'];
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import { screen, waitFor } from '@testing-library/react';
|
import { screen, waitFor } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { endOfDay, formatISO, startOfDay } from 'date-fns';
|
import { endOfDay, formatISO, startOfDay } from 'date-fns';
|
||||||
import { MemoryRouter, useLocation, useNavigate } from 'react-router-dom';
|
import { MemoryRouter, useLocation, useNavigate } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { ReachableServer, SelectedServer } from '../../src/servers/data';
|
import type { ReachableServer, SelectedServer } from '../../src/servers/data';
|
||||||
import type { Settings } from '../../src/settings/reducers/settings';
|
|
||||||
import { ShortUrlsFilteringBar as filteringBarCreator } from '../../src/short-urls/ShortUrlsFilteringBar';
|
import { ShortUrlsFilteringBar as filteringBarCreator } from '../../src/short-urls/ShortUrlsFilteringBar';
|
||||||
import { formatDate } from '../../src/utils/helpers/date';
|
import { formatDate } from '../../src/utils/helpers/date';
|
||||||
import type { DateRange } from '../../src/utils/helpers/dateIntervals';
|
import type { DateRange } from '../../src/utils/helpers/dateIntervals';
|
||||||
|
@ -28,10 +27,10 @@ describe('<ShortUrlsFilteringBar />', () => {
|
||||||
return renderWithEvents(
|
return renderWithEvents(
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<ShortUrlsFilteringBar
|
<ShortUrlsFilteringBar
|
||||||
selectedServer={selectedServer ?? Mock.all<SelectedServer>()}
|
selectedServer={selectedServer ?? fromPartial({})}
|
||||||
order={{}}
|
order={{}}
|
||||||
handleOrderBy={handleOrderBy}
|
handleOrderBy={handleOrderBy}
|
||||||
settings={Mock.of<Settings>({ visits: {} })}
|
settings={fromPartial({ visits: {} })}
|
||||||
/>
|
/>
|
||||||
</MemoryRouter>,
|
</MemoryRouter>,
|
||||||
);
|
);
|
||||||
|
@ -74,12 +73,12 @@ describe('<ShortUrlsFilteringBar />', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
['tags=foo,bar,baz', Mock.of<ReachableServer>({ version: '3.0.0' }), true],
|
['tags=foo,bar,baz', fromPartial<ReachableServer>({ version: '3.0.0' }), true],
|
||||||
['tags=foo,bar', Mock.of<ReachableServer>({ version: '3.1.0' }), true],
|
['tags=foo,bar', fromPartial<ReachableServer>({ version: '3.1.0' }), true],
|
||||||
['tags=foo', Mock.of<ReachableServer>({ version: '3.0.0' }), false],
|
['tags=foo', fromPartial<ReachableServer>({ version: '3.0.0' }), false],
|
||||||
['', Mock.of<ReachableServer>({ version: '3.0.0' }), false],
|
['', fromPartial<ReachableServer>({ version: '3.0.0' }), false],
|
||||||
['tags=foo,bar,baz', Mock.of<ReachableServer>({ version: '2.10.0' }), false],
|
['tags=foo,bar,baz', fromPartial<ReachableServer>({ version: '2.10.0' }), false],
|
||||||
['', Mock.of<ReachableServer>({ version: '2.10.0' }), false],
|
['', fromPartial<ReachableServer>({ version: '2.10.0' }), false],
|
||||||
])(
|
])(
|
||||||
'renders tags mode toggle if the server supports it and there is more than one tag selected',
|
'renders tags mode toggle if the server supports it and there is more than one tag selected',
|
||||||
(search, selectedServer, shouldHaveComponent) => {
|
(search, selectedServer, shouldHaveComponent) => {
|
||||||
|
@ -98,7 +97,7 @@ describe('<ShortUrlsFilteringBar />', () => {
|
||||||
['&tagsMode=all', 'With all the tags.'],
|
['&tagsMode=all', 'With all the tags.'],
|
||||||
['&tagsMode=any', 'With any of the tags.'],
|
['&tagsMode=any', 'With any of the tags.'],
|
||||||
])('expected tags mode tooltip title', async (initialTagsMode, expectedToggleText) => {
|
])('expected tags mode tooltip title', async (initialTagsMode, expectedToggleText) => {
|
||||||
const { user } = setUp(`tags=foo,bar${initialTagsMode}`, Mock.of<ReachableServer>({ version: '3.0.0' }));
|
const { user } = setUp(`tags=foo,bar${initialTagsMode}`, fromPartial({ version: '3.0.0' }));
|
||||||
|
|
||||||
await user.hover(screen.getByLabelText('Change tags mode'));
|
await user.hover(screen.getByLabelText('Change tags mode'));
|
||||||
expect(await screen.findByRole('tooltip')).toHaveTextContent(expectedToggleText);
|
expect(await screen.findByRole('tooltip')).toHaveTextContent(expectedToggleText);
|
||||||
|
@ -109,7 +108,7 @@ describe('<ShortUrlsFilteringBar />', () => {
|
||||||
['&tagsMode=all', 'tagsMode=any'],
|
['&tagsMode=all', 'tagsMode=any'],
|
||||||
['&tagsMode=any', 'tagsMode=all'],
|
['&tagsMode=any', 'tagsMode=all'],
|
||||||
])('redirects to first page when tags mode changes', async (initialTagsMode, expectedRedirectTagsMode) => {
|
])('redirects to first page when tags mode changes', async (initialTagsMode, expectedRedirectTagsMode) => {
|
||||||
const { user } = setUp(`tags=foo,bar${initialTagsMode}`, Mock.of<ReachableServer>({ version: '3.0.0' }));
|
const { user } = setUp(`tags=foo,bar${initialTagsMode}`, fromPartial({ version: '3.0.0' }));
|
||||||
|
|
||||||
expect(navigate).not.toHaveBeenCalled();
|
expect(navigate).not.toHaveBeenCalled();
|
||||||
await user.click(screen.getByLabelText('Change tags mode'));
|
await user.click(screen.getByLabelText('Change tags mode'));
|
||||||
|
@ -127,7 +126,7 @@ describe('<ShortUrlsFilteringBar />', () => {
|
||||||
['excludePastValidUntil=false', /Exclude enabled in the past/, 'excludePastValidUntil=true'],
|
['excludePastValidUntil=false', /Exclude enabled in the past/, 'excludePastValidUntil=true'],
|
||||||
['excludePastValidUntil=true', /Exclude enabled in the past/, 'excludePastValidUntil=false'],
|
['excludePastValidUntil=true', /Exclude enabled in the past/, 'excludePastValidUntil=false'],
|
||||||
])('allows to toggle filters through filtering dropdown', async (search, menuItemName, expectedQuery) => {
|
])('allows to toggle filters through filtering dropdown', async (search, menuItemName, expectedQuery) => {
|
||||||
const { user } = setUp(search, Mock.of<ReachableServer>({ version: '3.4.0' }));
|
const { user } = setUp(search, fromPartial({ version: '3.4.0' }));
|
||||||
const toggleFilter = async (name: RegExp) => {
|
const toggleFilter = async (name: RegExp) => {
|
||||||
await user.click(screen.getByRole('button', { name: 'Filters' }));
|
await user.click(screen.getByRole('button', { name: 'Filters' }));
|
||||||
await waitFor(() => screen.findByRole('menu'));
|
await waitFor(() => screen.findByRole('menu'));
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { MemoryRouter, useNavigate } from 'react-router-dom';
|
import { MemoryRouter, useNavigate } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
|
import type { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
|
||||||
import type { ReachableServer } from '../../src/servers/data';
|
|
||||||
import type { Settings } from '../../src/settings/reducers/settings';
|
import type { Settings } from '../../src/settings/reducers/settings';
|
||||||
import type { ShortUrl, ShortUrlsOrder } from '../../src/short-urls/data';
|
import type { ShortUrlsOrder } from '../../src/short-urls/data';
|
||||||
import type { ShortUrlsList as ShortUrlsListModel } from '../../src/short-urls/reducers/shortUrlsList';
|
import type { ShortUrlsList as ShortUrlsListModel } from '../../src/short-urls/reducers/shortUrlsList';
|
||||||
import { ShortUrlsList as createShortUrlsList } from '../../src/short-urls/ShortUrlsList';
|
import { ShortUrlsList as createShortUrlsList } from '../../src/short-urls/ShortUrlsList';
|
||||||
import type { ShortUrlsTableType } from '../../src/short-urls/ShortUrlsTable';
|
import type { ShortUrlsTableType } from '../../src/short-urls/ShortUrlsTable';
|
||||||
|
@ -22,15 +21,15 @@ describe('<ShortUrlsList />', () => {
|
||||||
const ShortUrlsFilteringBar = () => <span>ShortUrlsFilteringBar</span>;
|
const ShortUrlsFilteringBar = () => <span>ShortUrlsFilteringBar</span>;
|
||||||
const listShortUrlsMock = jest.fn();
|
const listShortUrlsMock = jest.fn();
|
||||||
const navigate = jest.fn();
|
const navigate = jest.fn();
|
||||||
const shortUrlsList = Mock.of<ShortUrlsListModel>({
|
const shortUrlsList = fromPartial<ShortUrlsListModel>({
|
||||||
shortUrls: {
|
shortUrls: {
|
||||||
data: [
|
data: [
|
||||||
Mock.of<ShortUrl>({
|
{
|
||||||
shortCode: 'testShortCode',
|
shortCode: 'testShortCode',
|
||||||
shortUrl: 'https://www.example.com/testShortUrl',
|
shortUrl: 'https://www.example.com/testShortUrl',
|
||||||
longUrl: 'https://www.example.com/testLongUrl',
|
longUrl: 'https://www.example.com/testLongUrl',
|
||||||
tags: ['test tag'],
|
tags: ['test tag'],
|
||||||
}),
|
},
|
||||||
],
|
],
|
||||||
pagination: { pagesCount: 3 },
|
pagination: { pagesCount: 3 },
|
||||||
},
|
},
|
||||||
|
@ -39,11 +38,11 @@ describe('<ShortUrlsList />', () => {
|
||||||
const setUp = (settings: Partial<Settings> = {}, version: SemVer = '3.0.0') => renderWithEvents(
|
const setUp = (settings: Partial<Settings> = {}, version: SemVer = '3.0.0') => renderWithEvents(
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<ShortUrlsList
|
<ShortUrlsList
|
||||||
{...Mock.of<MercureBoundProps>({ mercureInfo: { loading: true } })}
|
{...fromPartial<MercureBoundProps>({ mercureInfo: { loading: true } })}
|
||||||
listShortUrls={listShortUrlsMock}
|
listShortUrls={listShortUrlsMock}
|
||||||
shortUrlsList={shortUrlsList}
|
shortUrlsList={shortUrlsList}
|
||||||
selectedServer={Mock.of<ReachableServer>({ id: '1', version })}
|
selectedServer={fromPartial({ id: '1', version })}
|
||||||
settings={Mock.of<Settings>(settings)}
|
settings={fromPartial(settings)}
|
||||||
/>
|
/>
|
||||||
</MemoryRouter>,
|
</MemoryRouter>,
|
||||||
);
|
);
|
||||||
|
@ -81,9 +80,9 @@ describe('<ShortUrlsList />', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[Mock.of<ShortUrlsOrder>({ field: 'visits', dir: 'ASC' }), 'visits', 'ASC'],
|
[fromPartial<ShortUrlsOrder>({ field: 'visits', dir: 'ASC' }), 'visits', 'ASC'],
|
||||||
[Mock.of<ShortUrlsOrder>({ field: 'title', dir: 'DESC' }), 'title', 'DESC'],
|
[fromPartial<ShortUrlsOrder>({ field: 'title', dir: 'DESC' }), 'title', 'DESC'],
|
||||||
[Mock.all<ShortUrlsOrder>(), undefined, undefined],
|
[fromPartial<ShortUrlsOrder>({}), undefined, undefined],
|
||||||
])('has expected initial ordering based on settings', (defaultOrdering, field, dir) => {
|
])('has expected initial ordering based on settings', (defaultOrdering, field, dir) => {
|
||||||
setUp({ shortUrlsList: { defaultOrdering } });
|
setUp({ shortUrlsList: { defaultOrdering } });
|
||||||
expect(listShortUrlsMock).toHaveBeenCalledWith(expect.objectContaining({
|
expect(listShortUrlsMock).toHaveBeenCalledWith(expect.objectContaining({
|
||||||
|
@ -92,23 +91,23 @@ describe('<ShortUrlsList />', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[Mock.of<Settings>({
|
[fromPartial<Settings>({
|
||||||
shortUrlsList: {
|
shortUrlsList: {
|
||||||
defaultOrdering: { field: 'visits', dir: 'ASC' },
|
defaultOrdering: { field: 'visits', dir: 'ASC' },
|
||||||
},
|
},
|
||||||
}), '3.3.0' as SemVer, { field: 'visits', dir: 'ASC' }],
|
}), '3.3.0' as SemVer, { field: 'visits', dir: 'ASC' }],
|
||||||
[Mock.of<Settings>({
|
[fromPartial<Settings>({
|
||||||
shortUrlsList: {
|
shortUrlsList: {
|
||||||
defaultOrdering: { field: 'visits', dir: 'ASC' },
|
defaultOrdering: { field: 'visits', dir: 'ASC' },
|
||||||
},
|
},
|
||||||
visits: { excludeBots: true },
|
visits: { excludeBots: true },
|
||||||
}), '3.3.0' as SemVer, { field: 'visits', dir: 'ASC' }],
|
}), '3.3.0' as SemVer, { field: 'visits', dir: 'ASC' }],
|
||||||
[Mock.of<Settings>({
|
[fromPartial<Settings>({
|
||||||
shortUrlsList: {
|
shortUrlsList: {
|
||||||
defaultOrdering: { field: 'visits', dir: 'ASC' },
|
defaultOrdering: { field: 'visits', dir: 'ASC' },
|
||||||
},
|
},
|
||||||
}), '3.4.0' as SemVer, { field: 'visits', dir: 'ASC' }],
|
}), '3.4.0' as SemVer, { field: 'visits', dir: 'ASC' }],
|
||||||
[Mock.of<Settings>({
|
[fromPartial<Settings>({
|
||||||
shortUrlsList: {
|
shortUrlsList: {
|
||||||
defaultOrdering: { field: 'visits', dir: 'ASC' },
|
defaultOrdering: { field: 'visits', dir: 'ASC' },
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { fireEvent, screen } from '@testing-library/react';
|
import { fireEvent, screen } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ReachableServer, SelectedServer } from '../../src/servers/data';
|
import type { SelectedServer } from '../../src/servers/data';
|
||||||
import type { ShortUrlsOrderableFields } from '../../src/short-urls/data';
|
import type { ShortUrlsOrderableFields } from '../../src/short-urls/data';
|
||||||
import { SHORT_URLS_ORDERABLE_FIELDS } from '../../src/short-urls/data';
|
import { SHORT_URLS_ORDERABLE_FIELDS } from '../../src/short-urls/data';
|
||||||
import type { ShortUrlsList } from '../../src/short-urls/reducers/shortUrlsList';
|
import type { ShortUrlsList } from '../../src/short-urls/reducers/shortUrlsList';
|
||||||
|
@ -8,7 +8,7 @@ import { ShortUrlsTable as shortUrlsTableCreator } from '../../src/short-urls/Sh
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
|
|
||||||
describe('<ShortUrlsTable />', () => {
|
describe('<ShortUrlsTable />', () => {
|
||||||
const shortUrlsList = Mock.all<ShortUrlsList>();
|
const shortUrlsList = fromPartial<ShortUrlsList>({});
|
||||||
const orderByColumn = jest.fn();
|
const orderByColumn = jest.fn();
|
||||||
const ShortUrlsTable = shortUrlsTableCreator(() => <span>ShortUrlsRow</span>);
|
const ShortUrlsTable = shortUrlsTableCreator(() => <span>ShortUrlsRow</span>);
|
||||||
const setUp = (server: SelectedServer = null) => renderWithEvents(
|
const setUp = (server: SelectedServer = null) => renderWithEvents(
|
||||||
|
@ -56,7 +56,7 @@ describe('<ShortUrlsTable />', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render composed title column', () => {
|
it('should render composed title column', () => {
|
||||||
setUp(Mock.of<ReachableServer>({ version: '2.0.0' }));
|
setUp(fromPartial({ version: '2.0.0' }));
|
||||||
|
|
||||||
const { innerHTML } = screen.getAllByRole('columnheader')[2];
|
const { innerHTML } = screen.getAllByRole('columnheader')[2];
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShortUrl } from '../../../src/short-urls/data';
|
|
||||||
import { CreateShortUrlResult as createResult } from '../../../src/short-urls/helpers/CreateShortUrlResult';
|
import { CreateShortUrlResult as createResult } from '../../../src/short-urls/helpers/CreateShortUrlResult';
|
||||||
import type { ShortUrlCreation } from '../../../src/short-urls/reducers/shortUrlCreation';
|
import type { ShortUrlCreation } from '../../../src/short-urls/reducers/shortUrlCreation';
|
||||||
import type { TimeoutToggle } from '../../../src/utils/helpers/hooks';
|
import type { TimeoutToggle } from '../../../src/utils/helpers/hooks';
|
||||||
|
@ -28,14 +27,14 @@ describe('<CreateShortUrlResult />', () => {
|
||||||
|
|
||||||
it('renders a result message when result is provided', () => {
|
it('renders a result message when result is provided', () => {
|
||||||
setUp(
|
setUp(
|
||||||
{ result: Mock.of<ShortUrl>({ shortUrl: 'https://s.test/abc123' }), saving: false, saved: true, error: false },
|
{ result: fromPartial({ shortUrl: 'https://s.test/abc123' }), saving: false, saved: true, error: false },
|
||||||
);
|
);
|
||||||
expect(screen.getByText(/The short URL is/)).toHaveTextContent('Great! The short URL is https://s.test/abc123');
|
expect(screen.getByText(/The short URL is/)).toHaveTextContent('Great! The short URL is https://s.test/abc123');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Invokes tooltip timeout when copy to clipboard button is clicked', async () => {
|
it('Invokes tooltip timeout when copy to clipboard button is clicked', async () => {
|
||||||
const { user } = setUp(
|
const { user } = setUp(
|
||||||
{ result: Mock.of<ShortUrl>({ shortUrl: 'https://s.test/abc123' }), saving: false, saved: true, error: false },
|
{ result: fromPartial({ shortUrl: 'https://s.test/abc123' }), saving: false, saved: true, error: false },
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(copyToClipboard).not.toHaveBeenCalled();
|
expect(copyToClipboard).not.toHaveBeenCalled();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { screen, waitFor } from '@testing-library/react';
|
import { screen, waitFor } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { InvalidShortUrlDeletion, ProblemDetailsError } from '../../../src/api/types/errors';
|
import type { InvalidShortUrlDeletion } from '../../../src/api/types/errors';
|
||||||
import { ErrorTypeV2, ErrorTypeV3 } from '../../../src/api/types/errors';
|
import { ErrorTypeV2, ErrorTypeV3 } from '../../../src/api/types/errors';
|
||||||
import type { ShortUrl } from '../../../src/short-urls/data';
|
import type { ShortUrl } from '../../../src/short-urls/data';
|
||||||
import { DeleteShortUrlModal } from '../../../src/short-urls/helpers/DeleteShortUrlModal';
|
import { DeleteShortUrlModal } from '../../../src/short-urls/helpers/DeleteShortUrlModal';
|
||||||
|
@ -9,7 +9,7 @@ import { renderWithEvents } from '../../__helpers__/setUpTest';
|
||||||
import { TestModalWrapper } from '../../__helpers__/TestModalWrapper';
|
import { TestModalWrapper } from '../../__helpers__/TestModalWrapper';
|
||||||
|
|
||||||
describe('<DeleteShortUrlModal />', () => {
|
describe('<DeleteShortUrlModal />', () => {
|
||||||
const shortUrl = Mock.of<ShortUrl>({
|
const shortUrl = fromPartial<ShortUrl>({
|
||||||
tags: [],
|
tags: [],
|
||||||
shortCode: 'abc123',
|
shortCode: 'abc123',
|
||||||
longUrl: 'https://long-domain.com/foo/bar',
|
longUrl: 'https://long-domain.com/foo/bar',
|
||||||
|
@ -22,7 +22,7 @@ describe('<DeleteShortUrlModal />', () => {
|
||||||
<DeleteShortUrlModal
|
<DeleteShortUrlModal
|
||||||
{...args}
|
{...args}
|
||||||
shortUrl={shortUrl}
|
shortUrl={shortUrl}
|
||||||
shortUrlDeletion={Mock.of<ShortUrlDeletion>(shortUrlDeletion)}
|
shortUrlDeletion={fromPartial(shortUrlDeletion)}
|
||||||
deleteShortUrl={deleteShortUrl}
|
deleteShortUrl={deleteShortUrl}
|
||||||
shortUrlDeleted={shortUrlDeleted}
|
shortUrlDeleted={shortUrlDeleted}
|
||||||
resetDeleteShortUrl={jest.fn()}
|
resetDeleteShortUrl={jest.fn()}
|
||||||
|
@ -38,7 +38,7 @@ describe('<DeleteShortUrlModal />', () => {
|
||||||
loading: false,
|
loading: false,
|
||||||
error: true,
|
error: true,
|
||||||
shortCode: 'abc123',
|
shortCode: 'abc123',
|
||||||
errorData: Mock.of<ProblemDetailsError>({ type: 'OTHER_ERROR' }),
|
errorData: fromPartial({ type: 'OTHER_ERROR' }),
|
||||||
});
|
});
|
||||||
expect(screen.getByText('Something went wrong while deleting the URL :(').parentElement).not.toHaveClass(
|
expect(screen.getByText('Something went wrong while deleting the URL :(').parentElement).not.toHaveClass(
|
||||||
'bg-warning',
|
'bg-warning',
|
||||||
|
@ -46,8 +46,8 @@ describe('<DeleteShortUrlModal />', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[Mock.of<InvalidShortUrlDeletion>({ type: ErrorTypeV3.INVALID_SHORT_URL_DELETION })],
|
[fromPartial<InvalidShortUrlDeletion>({ type: ErrorTypeV3.INVALID_SHORT_URL_DELETION })],
|
||||||
[Mock.of<InvalidShortUrlDeletion>({ type: ErrorTypeV2.INVALID_SHORT_URL_DELETION })],
|
[fromPartial<InvalidShortUrlDeletion>({ type: ErrorTypeV2.INVALID_SHORT_URL_DELETION })],
|
||||||
])('shows specific error when threshold error occurs', (errorData) => {
|
])('shows specific error when threshold error occurs', (errorData) => {
|
||||||
setUp({ loading: false, error: true, shortCode: 'abc123', errorData });
|
setUp({ loading: false, error: true, shortCode: 'abc123', errorData });
|
||||||
expect(screen.getByText('Something went wrong while deleting the URL :(').parentElement).toHaveClass('bg-warning');
|
expect(screen.getByText('Something went wrong while deleting the URL :(').parentElement).toHaveClass('bg-warning');
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { ReportExporter } from '../../../src/common/services/ReportExporter';
|
import type { ReportExporter } from '../../../src/common/services/ReportExporter';
|
||||||
import type { NotFoundServer, ReachableServer, SelectedServer } from '../../../src/servers/data';
|
import type { NotFoundServer, SelectedServer } from '../../../src/servers/data';
|
||||||
import { ExportShortUrlsBtn as createExportShortUrlsBtn } from '../../../src/short-urls/helpers/ExportShortUrlsBtn';
|
import { ExportShortUrlsBtn as createExportShortUrlsBtn } from '../../../src/short-urls/helpers/ExportShortUrlsBtn';
|
||||||
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
||||||
|
|
||||||
|
@ -10,11 +10,11 @@ describe('<ExportShortUrlsBtn />', () => {
|
||||||
const listShortUrls = jest.fn();
|
const listShortUrls = jest.fn();
|
||||||
const buildShlinkApiClient = jest.fn().mockReturnValue({ listShortUrls });
|
const buildShlinkApiClient = jest.fn().mockReturnValue({ listShortUrls });
|
||||||
const exportShortUrls = jest.fn();
|
const exportShortUrls = jest.fn();
|
||||||
const reportExporter = Mock.of<ReportExporter>({ exportShortUrls });
|
const reportExporter = fromPartial<ReportExporter>({ exportShortUrls });
|
||||||
const ExportShortUrlsBtn = createExportShortUrlsBtn(buildShlinkApiClient, reportExporter);
|
const ExportShortUrlsBtn = createExportShortUrlsBtn(buildShlinkApiClient, reportExporter);
|
||||||
const setUp = (amount?: number, selectedServer?: SelectedServer) => renderWithEvents(
|
const setUp = (amount?: number, selectedServer?: SelectedServer) => renderWithEvents(
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<ExportShortUrlsBtn selectedServer={selectedServer ?? Mock.all<SelectedServer>()} amount={amount} />
|
<ExportShortUrlsBtn selectedServer={selectedServer ?? fromPartial({})} amount={amount} />
|
||||||
</MemoryRouter>,
|
</MemoryRouter>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ describe('<ExportShortUrlsBtn />', () => {
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[null],
|
[null],
|
||||||
[Mock.of<NotFoundServer>()],
|
[fromPartial<NotFoundServer>({})],
|
||||||
])('does nothing on click if selected server is not reachable', async (selectedServer) => {
|
])('does nothing on click if selected server is not reachable', async (selectedServer) => {
|
||||||
const { user } = setUp(0, selectedServer);
|
const { user } = setUp(0, selectedServer);
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ describe('<ExportShortUrlsBtn />', () => {
|
||||||
[385, 20],
|
[385, 20],
|
||||||
])('loads proper amount of pages based on the amount of results', async (amount, expectedPageLoads) => {
|
])('loads proper amount of pages based on the amount of results', async (amount, expectedPageLoads) => {
|
||||||
listShortUrls.mockResolvedValue({ data: [] });
|
listShortUrls.mockResolvedValue({ data: [] });
|
||||||
const { user } = setUp(amount, Mock.of<ReachableServer>({ id: '123' }));
|
const { user } = setUp(amount, fromPartial({ id: '123' }));
|
||||||
|
|
||||||
await user.click(screen.getByRole('button'));
|
await user.click(screen.getByRole('button'));
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,18 @@
|
||||||
import { fireEvent, screen } from '@testing-library/react';
|
import { fireEvent, screen } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ImageDownloader } from '../../../src/common/services/ImageDownloader';
|
|
||||||
import type { ReachableServer } from '../../../src/servers/data';
|
|
||||||
import type { ShortUrl } from '../../../src/short-urls/data';
|
|
||||||
import { QrCodeModal as createQrCodeModal } from '../../../src/short-urls/helpers/QrCodeModal';
|
import { QrCodeModal as createQrCodeModal } from '../../../src/short-urls/helpers/QrCodeModal';
|
||||||
import type { SemVer } from '../../../src/utils/helpers/version';
|
import type { SemVer } from '../../../src/utils/helpers/version';
|
||||||
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
||||||
|
|
||||||
describe('<QrCodeModal />', () => {
|
describe('<QrCodeModal />', () => {
|
||||||
const saveImage = jest.fn().mockReturnValue(Promise.resolve());
|
const saveImage = jest.fn().mockReturnValue(Promise.resolve());
|
||||||
const QrCodeModal = createQrCodeModal(Mock.of<ImageDownloader>({ saveImage }));
|
const QrCodeModal = createQrCodeModal(fromPartial({ saveImage }));
|
||||||
const shortUrl = 'https://s.test/abc123';
|
const shortUrl = 'https://s.test/abc123';
|
||||||
const setUp = (version: SemVer = '2.8.0') => renderWithEvents(
|
const setUp = (version: SemVer = '2.8.0') => renderWithEvents(
|
||||||
<QrCodeModal
|
<QrCodeModal
|
||||||
isOpen
|
isOpen
|
||||||
shortUrl={Mock.of<ShortUrl>({ shortUrl })}
|
shortUrl={fromPartial({ shortUrl })}
|
||||||
selectedServer={Mock.of<ReachableServer>({ version })}
|
selectedServer={fromPartial({ version })}
|
||||||
toggle={() => {}}
|
toggle={() => {}}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { NotFoundServer, ReachableServer } from '../../../src/servers/data';
|
import type { NotFoundServer, ReachableServer } from '../../../src/servers/data';
|
||||||
import type { ShortUrl } from '../../../src/short-urls/data';
|
import type { ShortUrl } from '../../../src/short-urls/data';
|
||||||
import type { LinkSuffix } from '../../../src/short-urls/helpers/ShortUrlDetailLink';
|
import type { LinkSuffix } from '../../../src/short-urls/helpers/ShortUrlDetailLink';
|
||||||
|
@ -10,11 +10,11 @@ describe('<ShortUrlDetailLink />', () => {
|
||||||
it.each([
|
it.each([
|
||||||
[undefined, undefined],
|
[undefined, undefined],
|
||||||
[null, null],
|
[null, null],
|
||||||
[Mock.of<ReachableServer>({ id: '1' }), null],
|
[fromPartial<ReachableServer>({ id: '1' }), null],
|
||||||
[Mock.of<ReachableServer>({ id: '1' }), undefined],
|
[fromPartial<ReachableServer>({ id: '1' }), undefined],
|
||||||
[Mock.of<NotFoundServer>(), Mock.all<ShortUrl>()],
|
[fromPartial<NotFoundServer>({}), fromPartial<ShortUrl>({})],
|
||||||
[null, Mock.all<ShortUrl>()],
|
[null, fromPartial<ShortUrl>({})],
|
||||||
[undefined, Mock.all<ShortUrl>()],
|
[undefined, fromPartial<ShortUrl>({})],
|
||||||
])('only renders a plain span when either server or short URL are not set', (selectedServer, shortUrl) => {
|
])('only renders a plain span when either server or short URL are not set', (selectedServer, shortUrl) => {
|
||||||
render(
|
render(
|
||||||
<ShortUrlDetailLink selectedServer={selectedServer} shortUrl={shortUrl} suffix="visits">
|
<ShortUrlDetailLink selectedServer={selectedServer} shortUrl={shortUrl} suffix="visits">
|
||||||
|
@ -28,26 +28,26 @@ describe('<ShortUrlDetailLink />', () => {
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[
|
[
|
||||||
Mock.of<ReachableServer>({ id: '1' }),
|
fromPartial<ReachableServer>({ id: '1' }),
|
||||||
Mock.of<ShortUrl>({ shortCode: 'abc123' }),
|
fromPartial<ShortUrl>({ shortCode: 'abc123' }),
|
||||||
'visits' as LinkSuffix,
|
'visits' as LinkSuffix,
|
||||||
'/server/1/short-code/abc123/visits',
|
'/server/1/short-code/abc123/visits',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
Mock.of<ReachableServer>({ id: '3' }),
|
fromPartial<ReachableServer>({ id: '3' }),
|
||||||
Mock.of<ShortUrl>({ shortCode: 'def456', domain: 'example.com' }),
|
fromPartial<ShortUrl>({ shortCode: 'def456', domain: 'example.com' }),
|
||||||
'visits' as LinkSuffix,
|
'visits' as LinkSuffix,
|
||||||
'/server/3/short-code/def456/visits?domain=example.com',
|
'/server/3/short-code/def456/visits?domain=example.com',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
Mock.of<ReachableServer>({ id: '1' }),
|
fromPartial<ReachableServer>({ id: '1' }),
|
||||||
Mock.of<ShortUrl>({ shortCode: 'abc123' }),
|
fromPartial<ShortUrl>({ shortCode: 'abc123' }),
|
||||||
'edit' as LinkSuffix,
|
'edit' as LinkSuffix,
|
||||||
'/server/1/short-code/abc123/edit',
|
'/server/1/short-code/abc123/edit',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
Mock.of<ReachableServer>({ id: '3' }),
|
fromPartial<ReachableServer>({ id: '3' }),
|
||||||
Mock.of<ShortUrl>({ shortCode: 'def456', domain: 'example.com' }),
|
fromPartial<ShortUrl>({ shortCode: 'def456', domain: 'example.com' }),
|
||||||
'edit' as LinkSuffix,
|
'edit' as LinkSuffix,
|
||||||
'/server/3/short-code/def456/edit?domain=example.com',
|
'/server/3/short-code/def456/edit?domain=example.com',
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { render, screen, waitFor } from '@testing-library/react';
|
import { render, screen, waitFor } from '@testing-library/react';
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShlinkVisitsSummary } from '../../../src/api/types';
|
import type { ShlinkVisitsSummary } from '../../../src/api/types';
|
||||||
import type { ShortUrl, ShortUrlMeta } from '../../../src/short-urls/data';
|
import type { ShortUrl, ShortUrlMeta } from '../../../src/short-urls/data';
|
||||||
import { ShortUrlStatus } from '../../../src/short-urls/helpers/ShortUrlStatus';
|
import { ShortUrlStatus } from '../../../src/short-urls/helpers/ShortUrlStatus';
|
||||||
|
@ -13,35 +13,35 @@ describe('<ShortUrlStatus />', () => {
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[
|
[
|
||||||
Mock.of<ShortUrlMeta>({ validSince: '2099-01-01T10:30:15' }),
|
fromPartial<ShortUrlMeta>({ validSince: '2099-01-01T10:30:15' }),
|
||||||
{},
|
{},
|
||||||
'This short URL will start working on 2099-01-01 10:30.',
|
'This short URL will start working on 2099-01-01 10:30.',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
Mock.of<ShortUrlMeta>({ validUntil: '2020-01-01T10:30:15' }),
|
fromPartial<ShortUrlMeta>({ validUntil: '2020-01-01T10:30:15' }),
|
||||||
{},
|
{},
|
||||||
'This short URL cannot be visited since 2020-01-01 10:30.',
|
'This short URL cannot be visited since 2020-01-01 10:30.',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
Mock.of<ShortUrlMeta>({ maxVisits: 10 }),
|
fromPartial<ShortUrlMeta>({ maxVisits: 10 }),
|
||||||
Mock.of<ShlinkVisitsSummary>({ total: 10 }),
|
fromPartial<ShlinkVisitsSummary>({ total: 10 }),
|
||||||
'This short URL cannot be currently visited because it has reached the maximum amount of 10 visits.',
|
'This short URL cannot be currently visited because it has reached the maximum amount of 10 visits.',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
Mock.of<ShortUrlMeta>({ maxVisits: 1 }),
|
fromPartial<ShortUrlMeta>({ maxVisits: 1 }),
|
||||||
Mock.of<ShlinkVisitsSummary>({ total: 1 }),
|
fromPartial<ShlinkVisitsSummary>({ total: 1 }),
|
||||||
'This short URL cannot be currently visited because it has reached the maximum amount of 1 visit.',
|
'This short URL cannot be currently visited because it has reached the maximum amount of 1 visit.',
|
||||||
],
|
],
|
||||||
[{}, {}, 'This short URL can be visited normally.'],
|
[{}, {}, 'This short URL can be visited normally.'],
|
||||||
[Mock.of<ShortUrlMeta>({ validUntil: '2099-01-01T10:30:15' }), {}, 'This short URL can be visited normally.'],
|
[fromPartial<ShortUrlMeta>({ validUntil: '2099-01-01T10:30:15' }), {}, 'This short URL can be visited normally.'],
|
||||||
[Mock.of<ShortUrlMeta>({ validSince: '2020-01-01T10:30:15' }), {}, 'This short URL can be visited normally.'],
|
[fromPartial<ShortUrlMeta>({ validSince: '2020-01-01T10:30:15' }), {}, 'This short URL can be visited normally.'],
|
||||||
[
|
[
|
||||||
Mock.of<ShortUrlMeta>({ maxVisits: 10 }),
|
fromPartial<ShortUrlMeta>({ maxVisits: 10 }),
|
||||||
Mock.of<ShlinkVisitsSummary>({ total: 1 }),
|
fromPartial<ShlinkVisitsSummary>({ total: 1 }),
|
||||||
'This short URL can be visited normally.',
|
'This short URL can be visited normally.',
|
||||||
],
|
],
|
||||||
])('shows expected tooltip', async (meta, visitsSummary, expectedTooltip) => {
|
])('shows expected tooltip', async (meta, visitsSummary, expectedTooltip) => {
|
||||||
const { user } = setUp(Mock.of<ShortUrl>({ meta, visitsSummary }));
|
const { user } = setUp(fromPartial({ meta, visitsSummary }));
|
||||||
|
|
||||||
await user.hover(screen.getByRole('img', { hidden: true }));
|
await user.hover(screen.getByRole('img', { hidden: true }));
|
||||||
await waitFor(() => expect(screen.getByRole('tooltip')).toHaveTextContent(expectedTooltip));
|
await waitFor(() => expect(screen.getByRole('tooltip')).toHaveTextContent(expectedTooltip));
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { render, screen, waitFor } from '@testing-library/react';
|
import { render, screen, waitFor } from '@testing-library/react';
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShortUrl } from '../../../src/short-urls/data';
|
import type { ShortUrl } from '../../../src/short-urls/data';
|
||||||
import { ShortUrlVisitsCount } from '../../../src/short-urls/helpers/ShortUrlVisitsCount';
|
import { ShortUrlVisitsCount } from '../../../src/short-urls/helpers/ShortUrlVisitsCount';
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ describe('<ShortUrlVisitsCount />', () => {
|
||||||
|
|
||||||
it.each([undefined, {}])('just returns visits when no limits are provided', (meta) => {
|
it.each([undefined, {}])('just returns visits when no limits are provided', (meta) => {
|
||||||
const visitsCount = 45;
|
const visitsCount = 45;
|
||||||
const { container } = setUp(visitsCount, Mock.of<ShortUrl>({ meta }));
|
const { container } = setUp(visitsCount, fromPartial({ meta }));
|
||||||
|
|
||||||
expect(container.firstChild).toHaveTextContent(`${visitsCount}`);
|
expect(container.firstChild).toHaveTextContent(`${visitsCount}`);
|
||||||
expect(container.querySelector('.short-urls-visits-count__max-visits-control')).not.toBeInTheDocument();
|
expect(container.querySelector('.short-urls-visits-count__max-visits-control')).not.toBeInTheDocument();
|
||||||
|
@ -24,7 +24,7 @@ describe('<ShortUrlVisitsCount />', () => {
|
||||||
const visitsCount = 45;
|
const visitsCount = 45;
|
||||||
const maxVisits = 500;
|
const maxVisits = 500;
|
||||||
const meta = { maxVisits };
|
const meta = { maxVisits };
|
||||||
const { container } = setUp(visitsCount, Mock.of<ShortUrl>({ meta }));
|
const { container } = setUp(visitsCount, fromPartial({ meta }));
|
||||||
|
|
||||||
expect(container.firstChild).toHaveTextContent(`/ ${maxVisits}`);
|
expect(container.firstChild).toHaveTextContent(`/ ${maxVisits}`);
|
||||||
});
|
});
|
||||||
|
@ -44,7 +44,7 @@ describe('<ShortUrlVisitsCount />', () => {
|
||||||
'This short URL will not accept visits after 2023-05-05 15:30',
|
'This short URL will not accept visits after 2023-05-05 15:30',
|
||||||
], { validSince: '2023-01-01T10:00:00', validUntil: '2023-05-05T15:30:30', maxVisits: 100 }],
|
], { validSince: '2023-01-01T10:00:00', validUntil: '2023-05-05T15:30:30', maxVisits: 100 }],
|
||||||
])('displays proper amount of tooltip list items', async (expectedListItems, meta) => {
|
])('displays proper amount of tooltip list items', async (expectedListItems, meta) => {
|
||||||
const { user } = setUp(100, Mock.of<ShortUrl>({ meta }));
|
const { user } = setUp(100, fromPartial({ meta }));
|
||||||
|
|
||||||
await user.hover(screen.getByRole('img', { hidden: true }));
|
await user.hover(screen.getByRole('img', { hidden: true }));
|
||||||
await waitFor(() => expect(screen.getByRole('list')));
|
await waitFor(() => expect(screen.getByRole('list')));
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { addDays, formatISO, subDays } from 'date-fns';
|
import { addDays, formatISO, subDays } from 'date-fns';
|
||||||
import { last } from 'ramda';
|
import { last } from 'ramda';
|
||||||
import { MemoryRouter, useLocation } from 'react-router-dom';
|
import { MemoryRouter, useLocation } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { ReachableServer } from '../../../src/servers/data';
|
import type { ReachableServer } from '../../../src/servers/data';
|
||||||
import type { Settings } from '../../../src/settings/reducers/settings';
|
import type { Settings } from '../../../src/settings/reducers/settings';
|
||||||
import type { ShortUrl, ShortUrlMeta } from '../../../src/short-urls/data';
|
import type { ShortUrl, ShortUrlMeta } from '../../../src/short-urls/data';
|
||||||
|
@ -28,7 +28,7 @@ jest.mock('react-router-dom', () => ({
|
||||||
describe('<ShortUrlsRow />', () => {
|
describe('<ShortUrlsRow />', () => {
|
||||||
const timeoutToggle = jest.fn(() => true);
|
const timeoutToggle = jest.fn(() => true);
|
||||||
const useTimeoutToggle = jest.fn(() => [false, timeoutToggle]) as TimeoutToggle;
|
const useTimeoutToggle = jest.fn(() => [false, timeoutToggle]) as TimeoutToggle;
|
||||||
const server = Mock.of<ReachableServer>({ url: 'https://s.test' });
|
const server = fromPartial<ReachableServer>({ url: 'https://s.test' });
|
||||||
const shortUrl: ShortUrl = {
|
const shortUrl: ShortUrl = {
|
||||||
shortCode: 'abc123',
|
shortCode: 'abc123',
|
||||||
shortUrl: 'https://s.test/abc123',
|
shortUrl: 'https://s.test/abc123',
|
||||||
|
@ -60,7 +60,7 @@ describe('<ShortUrlsRow />', () => {
|
||||||
selectedServer={server}
|
selectedServer={server}
|
||||||
shortUrl={{ ...shortUrl, title, tags, meta: { ...shortUrl.meta, ...meta } }}
|
shortUrl={{ ...shortUrl, title, tags, meta: { ...shortUrl.meta, ...meta } }}
|
||||||
onTagClick={() => null}
|
onTagClick={() => null}
|
||||||
settings={Mock.of<Settings>(settings)}
|
settings={fromPartial(settings)}
|
||||||
/>
|
/>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -118,13 +118,13 @@ describe('<ShortUrlsRow />', () => {
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[{}, '', shortUrl.visitsSummary?.total],
|
[{}, '', shortUrl.visitsSummary?.total],
|
||||||
[Mock.of<Settings>({ visits: { excludeBots: false } }), '', shortUrl.visitsSummary?.total],
|
[fromPartial<Settings>({ visits: { excludeBots: false } }), '', shortUrl.visitsSummary?.total],
|
||||||
[Mock.of<Settings>({ visits: { excludeBots: true } }), '', shortUrl.visitsSummary?.nonBots],
|
[fromPartial<Settings>({ visits: { excludeBots: true } }), '', shortUrl.visitsSummary?.nonBots],
|
||||||
[Mock.of<Settings>({ visits: { excludeBots: false } }), 'excludeBots=true', shortUrl.visitsSummary?.nonBots],
|
[fromPartial<Settings>({ visits: { excludeBots: false } }), 'excludeBots=true', shortUrl.visitsSummary?.nonBots],
|
||||||
[Mock.of<Settings>({ visits: { excludeBots: true } }), 'excludeBots=true', shortUrl.visitsSummary?.nonBots],
|
[fromPartial<Settings>({ visits: { excludeBots: true } }), 'excludeBots=true', shortUrl.visitsSummary?.nonBots],
|
||||||
[{}, 'excludeBots=true', shortUrl.visitsSummary?.nonBots],
|
[{}, 'excludeBots=true', shortUrl.visitsSummary?.nonBots],
|
||||||
[Mock.of<Settings>({ visits: { excludeBots: true } }), 'excludeBots=false', shortUrl.visitsSummary?.total],
|
[fromPartial<Settings>({ visits: { excludeBots: true } }), 'excludeBots=false', shortUrl.visitsSummary?.total],
|
||||||
[Mock.of<Settings>({ visits: { excludeBots: false } }), 'excludeBots=false', shortUrl.visitsSummary?.total],
|
[fromPartial<Settings>({ visits: { excludeBots: false } }), 'excludeBots=false', shortUrl.visitsSummary?.total],
|
||||||
[{}, 'excludeBots=false', shortUrl.visitsSummary?.total],
|
[{}, 'excludeBots=false', shortUrl.visitsSummary?.total],
|
||||||
])('renders visits count in fifth row', (settings, search, expectedAmount) => {
|
])('renders visits count in fifth row', (settings, search, expectedAmount) => {
|
||||||
setUp({ settings }, search);
|
setUp({ settings }, search);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { ReachableServer } from '../../../src/servers/data';
|
import type { ReachableServer } from '../../../src/servers/data';
|
||||||
import type { ShortUrl } from '../../../src/short-urls/data';
|
import type { ShortUrl } from '../../../src/short-urls/data';
|
||||||
import { ShortUrlsRowMenu as createShortUrlsRowMenu } from '../../../src/short-urls/helpers/ShortUrlsRowMenu';
|
import { ShortUrlsRowMenu as createShortUrlsRowMenu } from '../../../src/short-urls/helpers/ShortUrlsRowMenu';
|
||||||
|
@ -8,8 +8,8 @@ import { renderWithEvents } from '../../__helpers__/setUpTest';
|
||||||
|
|
||||||
describe('<ShortUrlsRowMenu />', () => {
|
describe('<ShortUrlsRowMenu />', () => {
|
||||||
const ShortUrlsRowMenu = createShortUrlsRowMenu(() => <i>DeleteShortUrlModal</i>, () => <i>QrCodeModal</i>);
|
const ShortUrlsRowMenu = createShortUrlsRowMenu(() => <i>DeleteShortUrlModal</i>, () => <i>QrCodeModal</i>);
|
||||||
const selectedServer = Mock.of<ReachableServer>({ id: 'abc123' });
|
const selectedServer = fromPartial<ReachableServer>({ id: 'abc123' });
|
||||||
const shortUrl = Mock.of<ShortUrl>({
|
const shortUrl = fromPartial<ShortUrl>({
|
||||||
shortCode: 'abc123',
|
shortCode: 'abc123',
|
||||||
shortUrl: 'https://s.test/abc123',
|
shortUrl: 'https://s.test/abc123',
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShortUrl } from '../../../src/short-urls/data';
|
import type { ShortUrl } from '../../../src/short-urls/data';
|
||||||
import { shortUrlDataFromShortUrl, urlDecodeShortCode, urlEncodeShortCode } from '../../../src/short-urls/helpers';
|
import { shortUrlDataFromShortUrl, urlDecodeShortCode, urlEncodeShortCode } from '../../../src/short-urls/helpers';
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ describe('helpers', () => {
|
||||||
[undefined, { validateUrls: true }, { longUrl: '', validateUrl: true }],
|
[undefined, { validateUrls: true }, { longUrl: '', validateUrl: true }],
|
||||||
[undefined, undefined, { longUrl: '', validateUrl: false }],
|
[undefined, undefined, { longUrl: '', validateUrl: false }],
|
||||||
[
|
[
|
||||||
Mock.of<ShortUrl>({ meta: {} }),
|
fromPartial<ShortUrl>({ meta: {} }),
|
||||||
{ validateUrls: false },
|
{ validateUrls: false },
|
||||||
{
|
{
|
||||||
longUrl: undefined,
|
longUrl: undefined,
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
||||||
import type { ShlinkState } from '../../../src/container/types';
|
import type { ShlinkState } from '../../../src/container/types';
|
||||||
import type { ShortUrl, ShortUrlData } from '../../../src/short-urls/data';
|
import type { ShortUrl } from '../../../src/short-urls/data';
|
||||||
import {
|
import {
|
||||||
createShortUrl as createShortUrlCreator,
|
createShortUrl as createShortUrlCreator,
|
||||||
shortUrlCreationReducerCreator,
|
shortUrlCreationReducerCreator,
|
||||||
} from '../../../src/short-urls/reducers/shortUrlCreation';
|
} from '../../../src/short-urls/reducers/shortUrlCreation';
|
||||||
|
|
||||||
describe('shortUrlCreationReducer', () => {
|
describe('shortUrlCreationReducer', () => {
|
||||||
const shortUrl = Mock.of<ShortUrl>();
|
const shortUrl = fromPartial<ShortUrl>({});
|
||||||
const createShortUrlCall = jest.fn();
|
const createShortUrlCall = jest.fn();
|
||||||
const buildShlinkApiClient = () => Mock.of<ShlinkApiClient>({ createShortUrl: createShortUrlCall });
|
const buildShlinkApiClient = () => fromPartial<ShlinkApiClient>({ createShortUrl: createShortUrlCall });
|
||||||
const createShortUrl = createShortUrlCreator(buildShlinkApiClient);
|
const createShortUrl = createShortUrlCreator(buildShlinkApiClient);
|
||||||
const { reducer, resetCreateShortUrl } = shortUrlCreationReducerCreator(createShortUrl);
|
const { reducer, resetCreateShortUrl } = shortUrlCreationReducerCreator(createShortUrl);
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ describe('shortUrlCreationReducer', () => {
|
||||||
|
|
||||||
describe('reducer', () => {
|
describe('reducer', () => {
|
||||||
it('returns loading on CREATE_SHORT_URL_START', () => {
|
it('returns loading on CREATE_SHORT_URL_START', () => {
|
||||||
expect(reducer(undefined, createShortUrl.pending('', Mock.all<ShortUrlData>()))).toEqual({
|
expect(reducer(undefined, createShortUrl.pending('', fromPartial({})))).toEqual({
|
||||||
saving: true,
|
saving: true,
|
||||||
saved: false,
|
saved: false,
|
||||||
error: false,
|
error: false,
|
||||||
|
@ -26,7 +26,7 @@ describe('shortUrlCreationReducer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns error on CREATE_SHORT_URL_ERROR', () => {
|
it('returns error on CREATE_SHORT_URL_ERROR', () => {
|
||||||
expect(reducer(undefined, createShortUrl.rejected(null, '', Mock.all<ShortUrlData>()))).toEqual({
|
expect(reducer(undefined, createShortUrl.rejected(null, '', fromPartial({})))).toEqual({
|
||||||
saving: false,
|
saving: false,
|
||||||
saved: false,
|
saved: false,
|
||||||
error: true,
|
error: true,
|
||||||
|
@ -34,7 +34,7 @@ describe('shortUrlCreationReducer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns result on CREATE_SHORT_URL', () => {
|
it('returns result on CREATE_SHORT_URL', () => {
|
||||||
expect(reducer(undefined, createShortUrl.fulfilled(shortUrl, '', Mock.all<ShortUrlData>()))).toEqual({
|
expect(reducer(undefined, createShortUrl.fulfilled(shortUrl, '', fromPartial({})))).toEqual({
|
||||||
result: shortUrl,
|
result: shortUrl,
|
||||||
saving: false,
|
saving: false,
|
||||||
saved: true,
|
saved: true,
|
||||||
|
@ -53,7 +53,7 @@ describe('shortUrlCreationReducer', () => {
|
||||||
|
|
||||||
describe('createShortUrl', () => {
|
describe('createShortUrl', () => {
|
||||||
const dispatch = jest.fn();
|
const dispatch = jest.fn();
|
||||||
const getState = () => Mock.all<ShlinkState>();
|
const getState = () => fromPartial<ShlinkState>({});
|
||||||
|
|
||||||
it('calls API on success', async () => {
|
it('calls API on success', async () => {
|
||||||
createShortUrlCall.mockResolvedValue(shortUrl);
|
createShortUrlCall.mockResolvedValue(shortUrl);
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
||||||
import type { ProblemDetailsError } from '../../../src/api/types/errors';
|
import type { ProblemDetailsError } from '../../../src/api/types/errors';
|
||||||
import {
|
import {
|
||||||
deleteShortUrl as deleteShortUrlCretor,
|
deleteShortUrl as deleteShortUrlCreator,
|
||||||
shortUrlDeletionReducerCreator,
|
shortUrlDeletionReducerCreator,
|
||||||
} from '../../../src/short-urls/reducers/shortUrlDeletion';
|
} from '../../../src/short-urls/reducers/shortUrlDeletion';
|
||||||
|
|
||||||
describe('shortUrlDeletionReducer', () => {
|
describe('shortUrlDeletionReducer', () => {
|
||||||
const deleteShortUrlCall = jest.fn();
|
const deleteShortUrlCall = jest.fn();
|
||||||
const buildShlinkApiClient = () => Mock.of<ShlinkApiClient>({ deleteShortUrl: deleteShortUrlCall });
|
const buildShlinkApiClient = () => fromPartial<ShlinkApiClient>({ deleteShortUrl: deleteShortUrlCall });
|
||||||
const deleteShortUrl = deleteShortUrlCretor(buildShlinkApiClient);
|
const deleteShortUrl = deleteShortUrlCreator(buildShlinkApiClient);
|
||||||
const { reducer, resetDeleteShortUrl } = shortUrlDeletionReducerCreator(deleteShortUrl);
|
const { reducer, resetDeleteShortUrl } = shortUrlDeletionReducerCreator(deleteShortUrl);
|
||||||
|
|
||||||
beforeEach(jest.clearAllMocks);
|
beforeEach(jest.clearAllMocks);
|
||||||
|
@ -40,7 +40,9 @@ describe('shortUrlDeletionReducer', () => {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('returns errorData on DELETE_SHORT_URL_ERROR', () => {
|
it('returns errorData on DELETE_SHORT_URL_ERROR', () => {
|
||||||
const errorData = Mock.of<ProblemDetailsError>({ type: 'bar', detail: 'detail', title: 'title', status: 400 });
|
const errorData = fromPartial<ProblemDetailsError>(
|
||||||
|
{ type: 'bar', detail: 'detail', title: 'title', status: 400 },
|
||||||
|
);
|
||||||
const error = errorData as unknown as Error;
|
const error = errorData as unknown as Error;
|
||||||
|
|
||||||
expect(reducer(undefined, deleteShortUrl.rejected(error, '', { shortCode: '' }))).toEqual({
|
expect(reducer(undefined, deleteShortUrl.rejected(error, '', { shortCode: '' }))).toEqual({
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
||||||
import type { ShlinkState } from '../../../src/container/types';
|
import type { ShlinkState } from '../../../src/container/types';
|
||||||
import type { ShortUrl } from '../../../src/short-urls/data';
|
import type { ShortUrl } from '../../../src/short-urls/data';
|
||||||
|
@ -7,7 +7,7 @@ import type { ShortUrlsList } from '../../../src/short-urls/reducers/shortUrlsLi
|
||||||
|
|
||||||
describe('shortUrlDetailReducer', () => {
|
describe('shortUrlDetailReducer', () => {
|
||||||
const getShortUrlCall = jest.fn();
|
const getShortUrlCall = jest.fn();
|
||||||
const buildShlinkApiClient = () => Mock.of<ShlinkApiClient>({ getShortUrl: getShortUrlCall });
|
const buildShlinkApiClient = () => fromPartial<ShlinkApiClient>({ getShortUrl: getShortUrlCall });
|
||||||
const { reducer, getShortUrlDetail } = shortUrlDetailReducerCreator(buildShlinkApiClient);
|
const { reducer, getShortUrlDetail } = shortUrlDetailReducerCreator(buildShlinkApiClient);
|
||||||
|
|
||||||
beforeEach(jest.clearAllMocks);
|
beforeEach(jest.clearAllMocks);
|
||||||
|
@ -27,7 +27,7 @@ describe('shortUrlDetailReducer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('return short URL on GET_SHORT_URL_DETAIL', () => {
|
it('return short URL on GET_SHORT_URL_DETAIL', () => {
|
||||||
const actionShortUrl = Mock.of<ShortUrl>({ longUrl: 'foo', shortCode: 'bar' });
|
const actionShortUrl = fromPartial<ShortUrl>({ longUrl: 'foo', shortCode: 'bar' });
|
||||||
const state = reducer(
|
const state = reducer(
|
||||||
{ loading: true, error: false },
|
{ loading: true, error: false },
|
||||||
getShortUrlDetail.fulfilled(actionShortUrl, '', { shortCode: '' }),
|
getShortUrlDetail.fulfilled(actionShortUrl, '', { shortCode: '' }),
|
||||||
|
@ -42,25 +42,25 @@ describe('shortUrlDetailReducer', () => {
|
||||||
|
|
||||||
describe('getShortUrlDetail', () => {
|
describe('getShortUrlDetail', () => {
|
||||||
const dispatchMock = jest.fn();
|
const dispatchMock = jest.fn();
|
||||||
const buildGetState = (shortUrlsList?: ShortUrlsList) => () => Mock.of<ShlinkState>({ shortUrlsList });
|
const buildGetState = (shortUrlsList?: ShortUrlsList) => () => fromPartial<ShlinkState>({ shortUrlsList });
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[undefined],
|
[undefined],
|
||||||
[Mock.all<ShortUrlsList>()],
|
[fromPartial<ShortUrlsList>({})],
|
||||||
[
|
[
|
||||||
Mock.of<ShortUrlsList>({
|
fromPartial<ShortUrlsList>({
|
||||||
shortUrls: { data: [] },
|
shortUrls: { data: [] },
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
Mock.of<ShortUrlsList>({
|
fromPartial<ShortUrlsList>({
|
||||||
shortUrls: {
|
shortUrls: {
|
||||||
data: [Mock.of<ShortUrl>({ shortCode: 'this_will_not_match' })],
|
data: [{ shortCode: 'this_will_not_match' }],
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
])('performs API call when short URL is not found in local state', async (shortUrlsList?: ShortUrlsList) => {
|
])('performs API call when short URL is not found in local state', async (shortUrlsList?: ShortUrlsList) => {
|
||||||
const resolvedShortUrl = Mock.of<ShortUrl>({ longUrl: 'foo', shortCode: 'abc123' });
|
const resolvedShortUrl = fromPartial<ShortUrl>({ longUrl: 'foo', shortCode: 'abc123' });
|
||||||
getShortUrlCall.mockResolvedValue(resolvedShortUrl);
|
getShortUrlCall.mockResolvedValue(resolvedShortUrl);
|
||||||
|
|
||||||
await getShortUrlDetail({ shortCode: 'abc123', domain: '' })(dispatchMock, buildGetState(shortUrlsList), {});
|
await getShortUrlDetail({ shortCode: 'abc123', domain: '' })(dispatchMock, buildGetState(shortUrlsList), {});
|
||||||
|
@ -71,12 +71,12 @@ describe('shortUrlDetailReducer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('avoids API calls when short URL is found in local state', async () => {
|
it('avoids API calls when short URL is found in local state', async () => {
|
||||||
const foundShortUrl = Mock.of<ShortUrl>({ longUrl: 'foo', shortCode: 'abc123' });
|
const foundShortUrl = fromPartial<ShortUrl>({ longUrl: 'foo', shortCode: 'abc123' });
|
||||||
getShortUrlCall.mockResolvedValue(Mock.all<ShortUrl>());
|
getShortUrlCall.mockResolvedValue(fromPartial<ShortUrl>({}));
|
||||||
|
|
||||||
await getShortUrlDetail(foundShortUrl)(
|
await getShortUrlDetail(foundShortUrl)(
|
||||||
dispatchMock,
|
dispatchMock,
|
||||||
buildGetState(Mock.of<ShortUrlsList>({
|
buildGetState(fromPartial({
|
||||||
shortUrls: {
|
shortUrls: {
|
||||||
data: [foundShortUrl],
|
data: [foundShortUrl],
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShlinkState } from '../../../src/container/types';
|
import type { ShlinkState } from '../../../src/container/types';
|
||||||
import type { SelectedServer } from '../../../src/servers/data';
|
import type { SelectedServer } from '../../../src/servers/data';
|
||||||
import type { ShortUrl } from '../../../src/short-urls/data';
|
import type { ShortUrl } from '../../../src/short-urls/data';
|
||||||
import type { EditShortUrl } from '../../../src/short-urls/reducers/shortUrlEdition';
|
|
||||||
import {
|
import {
|
||||||
editShortUrl as editShortUrlCreator,
|
editShortUrl as editShortUrlCreator,
|
||||||
shortUrlEditionReducerCreator,
|
shortUrlEditionReducerCreator,
|
||||||
|
@ -11,7 +10,7 @@ import {
|
||||||
describe('shortUrlEditionReducer', () => {
|
describe('shortUrlEditionReducer', () => {
|
||||||
const longUrl = 'https://shlink.io';
|
const longUrl = 'https://shlink.io';
|
||||||
const shortCode = 'abc123';
|
const shortCode = 'abc123';
|
||||||
const shortUrl = Mock.of<ShortUrl>({ longUrl, shortCode });
|
const shortUrl = fromPartial<ShortUrl>({ longUrl, shortCode });
|
||||||
const updateShortUrl = jest.fn().mockResolvedValue(shortUrl);
|
const updateShortUrl = jest.fn().mockResolvedValue(shortUrl);
|
||||||
const buildShlinkApiClient = jest.fn().mockReturnValue({ updateShortUrl });
|
const buildShlinkApiClient = jest.fn().mockReturnValue({ updateShortUrl });
|
||||||
const editShortUrl = editShortUrlCreator(buildShlinkApiClient);
|
const editShortUrl = editShortUrlCreator(buildShlinkApiClient);
|
||||||
|
@ -21,7 +20,7 @@ describe('shortUrlEditionReducer', () => {
|
||||||
|
|
||||||
describe('reducer', () => {
|
describe('reducer', () => {
|
||||||
it('returns loading on EDIT_SHORT_URL_START', () => {
|
it('returns loading on EDIT_SHORT_URL_START', () => {
|
||||||
expect(reducer(undefined, editShortUrl.pending('', Mock.all<EditShortUrl>()))).toEqual({
|
expect(reducer(undefined, editShortUrl.pending('', fromPartial({})))).toEqual({
|
||||||
saving: true,
|
saving: true,
|
||||||
saved: false,
|
saved: false,
|
||||||
error: false,
|
error: false,
|
||||||
|
@ -29,7 +28,7 @@ describe('shortUrlEditionReducer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns error on EDIT_SHORT_URL_ERROR', () => {
|
it('returns error on EDIT_SHORT_URL_ERROR', () => {
|
||||||
expect(reducer(undefined, editShortUrl.rejected(null, '', Mock.all<EditShortUrl>()))).toEqual({
|
expect(reducer(undefined, editShortUrl.rejected(null, '', fromPartial({})))).toEqual({
|
||||||
saving: false,
|
saving: false,
|
||||||
saved: false,
|
saved: false,
|
||||||
error: true,
|
error: true,
|
||||||
|
@ -37,7 +36,7 @@ describe('shortUrlEditionReducer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns provided tags and shortCode on SHORT_URL_EDITED', () => {
|
it('returns provided tags and shortCode on SHORT_URL_EDITED', () => {
|
||||||
expect(reducer(undefined, editShortUrl.fulfilled(shortUrl, '', Mock.all<EditShortUrl>()))).toEqual({
|
expect(reducer(undefined, editShortUrl.fulfilled(shortUrl, '', fromPartial({})))).toEqual({
|
||||||
shortUrl,
|
shortUrl,
|
||||||
saving: false,
|
saving: false,
|
||||||
saved: true,
|
saved: true,
|
||||||
|
@ -48,7 +47,9 @@ describe('shortUrlEditionReducer', () => {
|
||||||
|
|
||||||
describe('editShortUrl', () => {
|
describe('editShortUrl', () => {
|
||||||
const dispatch = jest.fn();
|
const dispatch = jest.fn();
|
||||||
const createGetState = (selectedServer: SelectedServer = null) => () => Mock.of<ShlinkState>({ selectedServer });
|
const createGetState = (selectedServer: SelectedServer = null) => () => fromPartial<ShlinkState>({
|
||||||
|
selectedServer,
|
||||||
|
});
|
||||||
|
|
||||||
afterEach(jest.clearAllMocks);
|
afterEach(jest.clearAllMocks);
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
||||||
import type { ShlinkPaginator, ShlinkShortUrlsResponse } from '../../../src/api/types';
|
import type { ShlinkShortUrlsResponse } from '../../../src/api/types';
|
||||||
import type { ShortUrl, ShortUrlData } from '../../../src/short-urls/data';
|
import type { ShortUrl } from '../../../src/short-urls/data';
|
||||||
import { createShortUrl as createShortUrlCreator } from '../../../src/short-urls/reducers/shortUrlCreation';
|
import { createShortUrl as createShortUrlCreator } from '../../../src/short-urls/reducers/shortUrlCreation';
|
||||||
import { shortUrlDeleted } from '../../../src/short-urls/reducers/shortUrlDeletion';
|
import { shortUrlDeleted } from '../../../src/short-urls/reducers/shortUrlDeletion';
|
||||||
import type { EditShortUrl } from '../../../src/short-urls/reducers/shortUrlEdition';
|
|
||||||
import { editShortUrl as editShortUrlCreator } from '../../../src/short-urls/reducers/shortUrlEdition';
|
import { editShortUrl as editShortUrlCreator } from '../../../src/short-urls/reducers/shortUrlEdition';
|
||||||
import {
|
import {
|
||||||
listShortUrls as listShortUrlsCreator,
|
listShortUrls as listShortUrlsCreator,
|
||||||
|
@ -16,7 +15,7 @@ import type { CreateVisit } from '../../../src/visits/types';
|
||||||
describe('shortUrlsListReducer', () => {
|
describe('shortUrlsListReducer', () => {
|
||||||
const shortCode = 'abc123';
|
const shortCode = 'abc123';
|
||||||
const listShortUrlsMock = jest.fn();
|
const listShortUrlsMock = jest.fn();
|
||||||
const buildShlinkApiClient = () => Mock.of<ShlinkApiClient>({ listShortUrls: listShortUrlsMock });
|
const buildShlinkApiClient = () => fromPartial<ShlinkApiClient>({ listShortUrls: listShortUrlsMock });
|
||||||
const listShortUrls = listShortUrlsCreator(buildShlinkApiClient);
|
const listShortUrls = listShortUrlsCreator(buildShlinkApiClient);
|
||||||
const editShortUrl = editShortUrlCreator(buildShlinkApiClient);
|
const editShortUrl = editShortUrlCreator(buildShlinkApiClient);
|
||||||
const createShortUrl = createShortUrlCreator(buildShlinkApiClient);
|
const createShortUrl = createShortUrlCreator(buildShlinkApiClient);
|
||||||
|
@ -32,7 +31,7 @@ describe('shortUrlsListReducer', () => {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('returns short URLs on LIST_SHORT_URLS', () =>
|
it('returns short URLs on LIST_SHORT_URLS', () =>
|
||||||
expect(reducer(undefined, listShortUrls.fulfilled(Mock.of<ShlinkShortUrlsResponse>({ data: [] }), ''))).toEqual({
|
expect(reducer(undefined, listShortUrls.fulfilled(fromPartial({ data: [] }), ''))).toEqual({
|
||||||
shortUrls: { data: [] },
|
shortUrls: { data: [] },
|
||||||
loading: false,
|
loading: false,
|
||||||
error: false,
|
error: false,
|
||||||
|
@ -46,21 +45,19 @@ describe('shortUrlsListReducer', () => {
|
||||||
|
|
||||||
it('removes matching URL and reduces total on SHORT_URL_DELETED', () => {
|
it('removes matching URL and reduces total on SHORT_URL_DELETED', () => {
|
||||||
const state = {
|
const state = {
|
||||||
shortUrls: Mock.of<ShlinkShortUrlsResponse>({
|
shortUrls: fromPartial<ShlinkShortUrlsResponse>({
|
||||||
data: [
|
data: [
|
||||||
Mock.of<ShortUrl>({ shortCode }),
|
{ shortCode },
|
||||||
Mock.of<ShortUrl>({ shortCode, domain: 'example.com' }),
|
{ shortCode, domain: 'example.com' },
|
||||||
Mock.of<ShortUrl>({ shortCode: 'foo' }),
|
{ shortCode: 'foo' },
|
||||||
],
|
],
|
||||||
pagination: Mock.of<ShlinkPaginator>({
|
pagination: { totalItems: 10 },
|
||||||
totalItems: 10,
|
|
||||||
}),
|
|
||||||
}),
|
}),
|
||||||
loading: false,
|
loading: false,
|
||||||
error: false,
|
error: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(reducer(state, shortUrlDeleted(Mock.of<ShortUrl>({ shortCode })))).toEqual({
|
expect(reducer(state, shortUrlDeleted(fromPartial({ shortCode })))).toEqual({
|
||||||
shortUrls: {
|
shortUrls: {
|
||||||
data: [{ shortCode, domain: 'example.com' }, { shortCode: 'foo' }],
|
data: [{ shortCode, domain: 'example.com' }, { shortCode: 'foo' }],
|
||||||
pagination: { totalItems: 9 },
|
pagination: { totalItems: 9 },
|
||||||
|
@ -70,7 +67,7 @@ describe('shortUrlsListReducer', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const createNewShortUrlVisit = (visitsCount: number) => Mock.of<CreateVisit>({
|
const createNewShortUrlVisit = (visitsCount: number) => fromPartial<CreateVisit>({
|
||||||
shortUrl: { shortCode: 'abc123', visitsCount },
|
shortUrl: { shortCode: 'abc123', visitsCount },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -81,11 +78,11 @@ describe('shortUrlsListReducer', () => {
|
||||||
[[], 10],
|
[[], 10],
|
||||||
])('updates visits count on CREATE_VISITS', (createdVisits, expectedCount) => {
|
])('updates visits count on CREATE_VISITS', (createdVisits, expectedCount) => {
|
||||||
const state = {
|
const state = {
|
||||||
shortUrls: Mock.of<ShlinkShortUrlsResponse>({
|
shortUrls: fromPartial<ShlinkShortUrlsResponse>({
|
||||||
data: [
|
data: [
|
||||||
Mock.of<ShortUrl>({ shortCode, domain: 'example.com', visitsCount: 5 }),
|
{ shortCode, domain: 'example.com', visitsCount: 5 },
|
||||||
Mock.of<ShortUrl>({ shortCode, visitsCount: 10 }),
|
{ shortCode, visitsCount: 10 },
|
||||||
Mock.of<ShortUrl>({ shortCode: 'foo', visitsCount: 8 }),
|
{ shortCode: 'foo', visitsCount: 8 },
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
loading: false,
|
loading: false,
|
||||||
|
@ -108,48 +105,46 @@ describe('shortUrlsListReducer', () => {
|
||||||
it.each([
|
it.each([
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
Mock.of<ShortUrl>({ shortCode }),
|
fromPartial<ShortUrl>({ shortCode }),
|
||||||
Mock.of<ShortUrl>({ shortCode, domain: 'example.com' }),
|
fromPartial<ShortUrl>({ shortCode, domain: 'example.com' }),
|
||||||
Mock.of<ShortUrl>({ shortCode: 'foo' }),
|
fromPartial<ShortUrl>({ shortCode: 'foo' }),
|
||||||
],
|
],
|
||||||
[{ shortCode: 'newOne' }, { shortCode }, { shortCode, domain: 'example.com' }, { shortCode: 'foo' }],
|
[{ shortCode: 'newOne' }, { shortCode }, { shortCode, domain: 'example.com' }, { shortCode: 'foo' }],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
Mock.of<ShortUrl>({ shortCode }),
|
fromPartial<ShortUrl>({ shortCode }),
|
||||||
Mock.of<ShortUrl>({ shortCode: 'code' }),
|
fromPartial<ShortUrl>({ shortCode: 'code' }),
|
||||||
Mock.of<ShortUrl>({ shortCode: 'foo' }),
|
fromPartial<ShortUrl>({ shortCode: 'foo' }),
|
||||||
Mock.of<ShortUrl>({ shortCode: 'bar' }),
|
fromPartial<ShortUrl>({ shortCode: 'bar' }),
|
||||||
Mock.of<ShortUrl>({ shortCode: 'baz' }),
|
fromPartial<ShortUrl>({ shortCode: 'baz' }),
|
||||||
],
|
],
|
||||||
[{ shortCode: 'newOne' }, { shortCode }, { shortCode: 'code' }, { shortCode: 'foo' }, { shortCode: 'bar' }],
|
[{ shortCode: 'newOne' }, { shortCode }, { shortCode: 'code' }, { shortCode: 'foo' }, { shortCode: 'bar' }],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
Mock.of<ShortUrl>({ shortCode }),
|
fromPartial<ShortUrl>({ shortCode }),
|
||||||
Mock.of<ShortUrl>({ shortCode: 'code' }),
|
fromPartial<ShortUrl>({ shortCode: 'code' }),
|
||||||
Mock.of<ShortUrl>({ shortCode: 'foo' }),
|
fromPartial<ShortUrl>({ shortCode: 'foo' }),
|
||||||
Mock.of<ShortUrl>({ shortCode: 'bar' }),
|
fromPartial<ShortUrl>({ shortCode: 'bar' }),
|
||||||
Mock.of<ShortUrl>({ shortCode: 'baz1' }),
|
fromPartial<ShortUrl>({ shortCode: 'baz1' }),
|
||||||
Mock.of<ShortUrl>({ shortCode: 'baz2' }),
|
fromPartial<ShortUrl>({ shortCode: 'baz2' }),
|
||||||
Mock.of<ShortUrl>({ shortCode: 'baz3' }),
|
fromPartial<ShortUrl>({ shortCode: 'baz3' }),
|
||||||
],
|
],
|
||||||
[{ shortCode: 'newOne' }, { shortCode }, { shortCode: 'code' }, { shortCode: 'foo' }, { shortCode: 'bar' }],
|
[{ shortCode: 'newOne' }, { shortCode }, { shortCode: 'code' }, { shortCode: 'foo' }, { shortCode: 'bar' }],
|
||||||
],
|
],
|
||||||
])('prepends new short URL and increases total on CREATE_SHORT_URL', (data, expectedData) => {
|
])('prepends new short URL and increases total on CREATE_SHORT_URL', (data, expectedData) => {
|
||||||
const newShortUrl = Mock.of<ShortUrl>({ shortCode: 'newOne' });
|
const newShortUrl = fromPartial<ShortUrl>({ shortCode: 'newOne' });
|
||||||
const state = {
|
const state = {
|
||||||
shortUrls: Mock.of<ShlinkShortUrlsResponse>({
|
shortUrls: fromPartial<ShlinkShortUrlsResponse>({
|
||||||
data,
|
data,
|
||||||
pagination: Mock.of<ShlinkPaginator>({
|
pagination: { totalItems: 15 },
|
||||||
totalItems: 15,
|
|
||||||
}),
|
|
||||||
}),
|
}),
|
||||||
loading: false,
|
loading: false,
|
||||||
error: false,
|
error: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(reducer(state, createShortUrl.fulfilled(newShortUrl, '', Mock.all<ShortUrlData>()))).toEqual({
|
expect(reducer(state, createShortUrl.fulfilled(newShortUrl, '', fromPartial({})))).toEqual({
|
||||||
shortUrls: {
|
shortUrls: {
|
||||||
data: expectedData,
|
data: expectedData,
|
||||||
pagination: { totalItems: 16 },
|
pagination: { totalItems: 16 },
|
||||||
|
@ -161,16 +156,16 @@ describe('shortUrlsListReducer', () => {
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
((): [ShortUrl, ShortUrl[], ShortUrl[]] => {
|
((): [ShortUrl, ShortUrl[], ShortUrl[]] => {
|
||||||
const editedShortUrl = Mock.of<ShortUrl>({ shortCode: 'notMatching' });
|
const editedShortUrl = fromPartial<ShortUrl>({ shortCode: 'notMatching' });
|
||||||
const list = [Mock.of<ShortUrl>({ shortCode: 'foo' }), Mock.of<ShortUrl>({ shortCode: 'bar' })];
|
const list: ShortUrl[] = [fromPartial({ shortCode: 'foo' }), fromPartial({ shortCode: 'bar' })];
|
||||||
|
|
||||||
return [editedShortUrl, list, list];
|
return [editedShortUrl, list, list];
|
||||||
})(),
|
})(),
|
||||||
((): [ShortUrl, ShortUrl[], ShortUrl[]] => {
|
((): [ShortUrl, ShortUrl[], ShortUrl[]] => {
|
||||||
const editedShortUrl = Mock.of<ShortUrl>({ shortCode: 'matching', longUrl: 'new_one' });
|
const editedShortUrl = fromPartial<ShortUrl>({ shortCode: 'matching', longUrl: 'new_one' });
|
||||||
const list = [
|
const list: ShortUrl[] = [
|
||||||
Mock.of<ShortUrl>({ shortCode: 'matching', longUrl: 'old_one' }),
|
fromPartial({ shortCode: 'matching', longUrl: 'old_one' }),
|
||||||
Mock.of<ShortUrl>({ shortCode: 'bar' }),
|
fromPartial({ shortCode: 'bar' }),
|
||||||
];
|
];
|
||||||
const expectedList = [editedShortUrl, list[1]];
|
const expectedList = [editedShortUrl, list[1]];
|
||||||
|
|
||||||
|
@ -178,17 +173,15 @@ describe('shortUrlsListReducer', () => {
|
||||||
})(),
|
})(),
|
||||||
])('updates matching short URL on SHORT_URL_EDITED', (editedShortUrl, initialList, expectedList) => {
|
])('updates matching short URL on SHORT_URL_EDITED', (editedShortUrl, initialList, expectedList) => {
|
||||||
const state = {
|
const state = {
|
||||||
shortUrls: Mock.of<ShlinkShortUrlsResponse>({
|
shortUrls: fromPartial<ShlinkShortUrlsResponse>({
|
||||||
data: initialList,
|
data: initialList,
|
||||||
pagination: Mock.of<ShlinkPaginator>({
|
pagination: { totalItems: 15 },
|
||||||
totalItems: 15,
|
|
||||||
}),
|
|
||||||
}),
|
}),
|
||||||
loading: false,
|
loading: false,
|
||||||
error: false,
|
error: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = reducer(state, editShortUrl.fulfilled(editedShortUrl, '', Mock.of<EditShortUrl>()));
|
const result = reducer(state, editShortUrl.fulfilled(editedShortUrl, '', fromPartial({})));
|
||||||
|
|
||||||
expect(result.shortUrls?.data).toEqual(expectedList);
|
expect(result.shortUrls?.data).toEqual(expectedList);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import { screen, waitFor } from '@testing-library/react';
|
import { screen, waitFor } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { identity } from 'ramda';
|
import { identity } from 'ramda';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
|
import type { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
|
||||||
import type { Settings } from '../../src/settings/reducers/settings';
|
|
||||||
import type { TagsList } from '../../src/tags/reducers/tagsList';
|
import type { TagsList } from '../../src/tags/reducers/tagsList';
|
||||||
import type { TagsListProps } from '../../src/tags/TagsList';
|
import type { TagsListProps } from '../../src/tags/TagsList';
|
||||||
import { TagsList as createTagsList } from '../../src/tags/TagsList';
|
import { TagsList as createTagsList } from '../../src/tags/TagsList';
|
||||||
|
@ -13,12 +12,12 @@ describe('<TagsList />', () => {
|
||||||
const TagsListComp = createTagsList(({ sortedTags }) => <>TagsTable ({sortedTags.map((t) => t.visits).join(',')})</>);
|
const TagsListComp = createTagsList(({ sortedTags }) => <>TagsTable ({sortedTags.map((t) => t.visits).join(',')})</>);
|
||||||
const setUp = (tagsList: Partial<TagsList>, excludeBots = false) => renderWithEvents(
|
const setUp = (tagsList: Partial<TagsList>, excludeBots = false) => renderWithEvents(
|
||||||
<TagsListComp
|
<TagsListComp
|
||||||
{...Mock.all<TagsListProps>()}
|
{...fromPartial<TagsListProps>({})}
|
||||||
{...Mock.of<MercureBoundProps>({ mercureInfo: {} })}
|
{...fromPartial<MercureBoundProps>({ mercureInfo: {} })}
|
||||||
forceListTags={identity}
|
forceListTags={identity}
|
||||||
filterTags={filterTags}
|
filterTags={filterTags}
|
||||||
tagsList={Mock.of<TagsList>(tagsList)}
|
tagsList={fromPartial(tagsList)}
|
||||||
settings={Mock.of<Settings>({ visits: { excludeBots } })}
|
settings={fromPartial({ visits: { excludeBots } })}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { SelectedServer } from '../../src/servers/data';
|
|
||||||
import type { SimplifiedTag } from '../../src/tags/data';
|
|
||||||
import { TagsTable as createTagsTable } from '../../src/tags/TagsTable';
|
import { TagsTable as createTagsTable } from '../../src/tags/TagsTable';
|
||||||
import { rangeOf } from '../../src/utils/utils';
|
import { rangeOf } from '../../src/utils/utils';
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
|
@ -17,8 +15,8 @@ describe('<TagsTable />', () => {
|
||||||
(useLocation as any).mockReturnValue({ search });
|
(useLocation as any).mockReturnValue({ search });
|
||||||
return renderWithEvents(
|
return renderWithEvents(
|
||||||
<TagsTable
|
<TagsTable
|
||||||
sortedTags={sortedTags.map((tag) => Mock.of<SimplifiedTag>({ tag }))}
|
sortedTags={sortedTags.map((tag) => fromPartial({ tag }))}
|
||||||
selectedServer={Mock.all<SelectedServer>()}
|
selectedServer={fromPartial({})}
|
||||||
currentOrder={{}}
|
currentOrder={{}}
|
||||||
orderByColumn={() => orderByColumn}
|
orderByColumn={() => orderByColumn}
|
||||||
/>,
|
/>,
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { ReachableServer } from '../../src/servers/data';
|
|
||||||
import { TagsTableRow as createTagsTableRow } from '../../src/tags/TagsTableRow';
|
import { TagsTableRow as createTagsTableRow } from '../../src/tags/TagsTableRow';
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
import { colorGeneratorMock } from '../utils/services/__mocks__/ColorGenerator.mock';
|
import { colorGeneratorMock } from '../utils/services/__mocks__/ColorGenerator.mock';
|
||||||
|
@ -18,7 +17,7 @@ describe('<TagsTableRow />', () => {
|
||||||
<tbody>
|
<tbody>
|
||||||
<TagsTableRow
|
<TagsTableRow
|
||||||
tag={{ tag: 'foo&bar', visits: tagStats?.visits ?? 0, shortUrls: tagStats?.shortUrls ?? 0 }}
|
tag={{ tag: 'foo&bar', visits: tagStats?.visits ?? 0, shortUrls: tagStats?.shortUrls ?? 0 }}
|
||||||
selectedServer={Mock.of<ReachableServer>({ id: 'abc123' })}
|
selectedServer={fromPartial({ id: 'abc123' })}
|
||||||
/>
|
/>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
import { screen, waitFor } from '@testing-library/react';
|
import { screen, waitFor } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ProblemDetailsError } from '../../../src/api/types/errors';
|
|
||||||
import { EditTagModal as createEditTagModal } from '../../../src/tags/helpers/EditTagModal';
|
import { EditTagModal as createEditTagModal } from '../../../src/tags/helpers/EditTagModal';
|
||||||
import type { TagEdition } from '../../../src/tags/reducers/tagEdit';
|
import type { TagEdition } from '../../../src/tags/reducers/tagEdit';
|
||||||
import type { ColorGenerator } from '../../../src/utils/services/ColorGenerator';
|
|
||||||
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
||||||
|
|
||||||
describe('<EditTagModal />', () => {
|
describe('<EditTagModal />', () => {
|
||||||
const EditTagModal = createEditTagModal(Mock.of<ColorGenerator>({ getColorForKey: jest.fn(() => 'green') }));
|
const EditTagModal = createEditTagModal(fromPartial({ getColorForKey: jest.fn(() => 'green') }));
|
||||||
const editTag = jest.fn().mockReturnValue(Promise.resolve());
|
const editTag = jest.fn().mockReturnValue(Promise.resolve());
|
||||||
const toggle = jest.fn();
|
const toggle = jest.fn();
|
||||||
const setUp = (tagEdit: Partial<TagEdition> = {}) => {
|
const setUp = (tagEdit: Partial<TagEdition> = {}) => {
|
||||||
const edition = Mock.of<TagEdition>(tagEdit);
|
const edition = fromPartial<TagEdition>(tagEdit);
|
||||||
return renderWithEvents(
|
return renderWithEvents(
|
||||||
<EditTagModal isOpen tag="foo" tagEdit={edition} editTag={editTag} tagEdited={jest.fn()} toggle={toggle} />,
|
<EditTagModal isOpen tag="foo" tagEdit={edition} editTag={editTag} tagEdited={jest.fn()} toggle={toggle} />,
|
||||||
);
|
);
|
||||||
|
@ -43,7 +41,7 @@ describe('<EditTagModal />', () => {
|
||||||
[true, 1],
|
[true, 1],
|
||||||
[false, 0],
|
[false, 0],
|
||||||
])('displays error result in case of error', (error, expectedResultCount) => {
|
])('displays error result in case of error', (error, expectedResultCount) => {
|
||||||
setUp({ error, errorData: Mock.all<ProblemDetailsError>() });
|
setUp({ error, errorData: fromPartial({}) });
|
||||||
expect(screen.queryAllByText('Something went wrong while editing the tag :(')).toHaveLength(expectedResultCount);
|
expect(screen.queryAllByText('Something went wrong while editing the tag :(')).toHaveLength(expectedResultCount);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import { Tag } from '../../../src/tags/helpers/Tag';
|
import { Tag } from '../../../src/tags/helpers/Tag';
|
||||||
import type { ColorGenerator } from '../../../src/utils/services/ColorGenerator';
|
import type { ColorGenerator } from '../../../src/utils/services/ColorGenerator';
|
||||||
import { MAIN_COLOR } from '../../../src/utils/theme';
|
import { MAIN_COLOR } from '../../../src/utils/theme';
|
||||||
|
@ -24,7 +24,7 @@ describe('<Tag />', () => {
|
||||||
const onClose = jest.fn();
|
const onClose = jest.fn();
|
||||||
const isColorLightForKey = jest.fn(() => false);
|
const isColorLightForKey = jest.fn(() => false);
|
||||||
const getColorForKey = jest.fn(() => MAIN_COLOR);
|
const getColorForKey = jest.fn(() => MAIN_COLOR);
|
||||||
const colorGenerator = Mock.of<ColorGenerator>({ getColorForKey, isColorLightForKey });
|
const colorGenerator = fromPartial<ColorGenerator>({ getColorForKey, isColorLightForKey });
|
||||||
const setUp = (text: string, clearable?: boolean, children?: ReactNode) => renderWithEvents(
|
const setUp = (text: string, clearable?: boolean, children?: ReactNode) => renderWithEvents(
|
||||||
<Tag text={text} clearable={clearable} colorGenerator={colorGenerator} onClick={onClick} onClose={onClose}>
|
<Tag text={text} clearable={clearable} colorGenerator={colorGenerator} onClick={onClick} onClose={onClose}>
|
||||||
{children}
|
{children}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { Settings } from '../../../src/settings/reducers/settings';
|
|
||||||
import { TagsSelector as createTagsSelector } from '../../../src/tags/helpers/TagsSelector';
|
import { TagsSelector as createTagsSelector } from '../../../src/tags/helpers/TagsSelector';
|
||||||
import type { TagsList } from '../../../src/tags/reducers/tagsList';
|
import type { TagsList } from '../../../src/tags/reducers/tagsList';
|
||||||
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
||||||
|
@ -10,12 +9,12 @@ describe('<TagsSelector />', () => {
|
||||||
const onChange = jest.fn();
|
const onChange = jest.fn();
|
||||||
const TagsSelector = createTagsSelector(colorGeneratorMock);
|
const TagsSelector = createTagsSelector(colorGeneratorMock);
|
||||||
const tags = ['foo', 'bar'];
|
const tags = ['foo', 'bar'];
|
||||||
const tagsList = Mock.of<TagsList>({ tags: [...tags, 'baz'] });
|
const tagsList = fromPartial<TagsList>({ tags: [...tags, 'baz'] });
|
||||||
const setUp = () => renderWithEvents(
|
const setUp = () => renderWithEvents(
|
||||||
<TagsSelector
|
<TagsSelector
|
||||||
selectedTags={tags}
|
selectedTags={tags}
|
||||||
tagsList={tagsList}
|
tagsList={tagsList}
|
||||||
settings={Mock.all<Settings>()}
|
settings={fromPartial({})}
|
||||||
listTags={jest.fn()}
|
listTags={jest.fn()}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
/>,
|
/>,
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
||||||
import type { ShlinkState } from '../../../src/container/types';
|
import type { ShlinkState } from '../../../src/container/types';
|
||||||
import { tagDeleted, tagDeleteReducerCreator } from '../../../src/tags/reducers/tagDelete';
|
import { tagDeleted, tagDeleteReducerCreator } from '../../../src/tags/reducers/tagDelete';
|
||||||
|
|
||||||
describe('tagDeleteReducer', () => {
|
describe('tagDeleteReducer', () => {
|
||||||
const deleteTagsCall = jest.fn();
|
const deleteTagsCall = jest.fn();
|
||||||
const buildShlinkApiClient = () => Mock.of<ShlinkApiClient>({ deleteTags: deleteTagsCall });
|
const buildShlinkApiClient = () => fromPartial<ShlinkApiClient>({ deleteTags: deleteTagsCall });
|
||||||
const { reducer, deleteTag } = tagDeleteReducerCreator(buildShlinkApiClient);
|
const { reducer, deleteTag } = tagDeleteReducerCreator(buildShlinkApiClient);
|
||||||
|
|
||||||
beforeEach(jest.clearAllMocks);
|
beforeEach(jest.clearAllMocks);
|
||||||
|
@ -44,7 +44,7 @@ describe('tagDeleteReducer', () => {
|
||||||
|
|
||||||
describe('deleteTag', () => {
|
describe('deleteTag', () => {
|
||||||
const dispatch = jest.fn();
|
const dispatch = jest.fn();
|
||||||
const getState = () => Mock.all<ShlinkState>();
|
const getState = () => fromPartial<ShlinkState>({});
|
||||||
|
|
||||||
it('calls API on success', async () => {
|
it('calls API on success', async () => {
|
||||||
const tag = 'foo';
|
const tag = 'foo';
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
||||||
import type { ShlinkState } from '../../../src/container/types';
|
import type { ShlinkState } from '../../../src/container/types';
|
||||||
import type { EditTag } from '../../../src/tags/reducers/tagEdit';
|
|
||||||
import { editTag as editTagCreator, tagEdited, tagEditReducerCreator } from '../../../src/tags/reducers/tagEdit';
|
import { editTag as editTagCreator, tagEdited, tagEditReducerCreator } from '../../../src/tags/reducers/tagEdit';
|
||||||
import type { ColorGenerator } from '../../../src/utils/services/ColorGenerator';
|
import type { ColorGenerator } from '../../../src/utils/services/ColorGenerator';
|
||||||
|
|
||||||
|
@ -10,14 +9,14 @@ describe('tagEditReducer', () => {
|
||||||
const newName = 'bar';
|
const newName = 'bar';
|
||||||
const color = '#ff0000';
|
const color = '#ff0000';
|
||||||
const editTagCall = jest.fn();
|
const editTagCall = jest.fn();
|
||||||
const buildShlinkApiClient = () => Mock.of<ShlinkApiClient>({ editTag: editTagCall });
|
const buildShlinkApiClient = () => fromPartial<ShlinkApiClient>({ editTag: editTagCall });
|
||||||
const colorGenerator = Mock.of<ColorGenerator>({ setColorForKey: jest.fn() });
|
const colorGenerator = fromPartial<ColorGenerator>({ setColorForKey: jest.fn() });
|
||||||
const editTag = editTagCreator(buildShlinkApiClient, colorGenerator);
|
const editTag = editTagCreator(buildShlinkApiClient, colorGenerator);
|
||||||
const { reducer } = tagEditReducerCreator(editTag);
|
const { reducer } = tagEditReducerCreator(editTag);
|
||||||
|
|
||||||
describe('reducer', () => {
|
describe('reducer', () => {
|
||||||
it('returns loading on EDIT_TAG_START', () => {
|
it('returns loading on EDIT_TAG_START', () => {
|
||||||
expect(reducer(undefined, editTag.pending('', Mock.all<EditTag>()))).toEqual({
|
expect(reducer(undefined, editTag.pending('', fromPartial({})))).toEqual({
|
||||||
editing: true,
|
editing: true,
|
||||||
edited: false,
|
edited: false,
|
||||||
error: false,
|
error: false,
|
||||||
|
@ -25,7 +24,7 @@ describe('tagEditReducer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns error on EDIT_TAG_ERROR', () => {
|
it('returns error on EDIT_TAG_ERROR', () => {
|
||||||
expect(reducer(undefined, editTag.rejected(null, '', Mock.all<EditTag>()))).toEqual({
|
expect(reducer(undefined, editTag.rejected(null, '', fromPartial({})))).toEqual({
|
||||||
editing: false,
|
editing: false,
|
||||||
edited: false,
|
edited: false,
|
||||||
error: true,
|
error: true,
|
||||||
|
@ -33,7 +32,7 @@ describe('tagEditReducer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns tag names on EDIT_TAG', () => {
|
it('returns tag names on EDIT_TAG', () => {
|
||||||
expect(reducer(undefined, editTag.fulfilled({ oldName, newName, color }, '', Mock.all<EditTag>()))).toEqual({
|
expect(reducer(undefined, editTag.fulfilled({ oldName, newName, color }, '', fromPartial({})))).toEqual({
|
||||||
editing: false,
|
editing: false,
|
||||||
edited: true,
|
edited: true,
|
||||||
error: false,
|
error: false,
|
||||||
|
@ -52,7 +51,7 @@ describe('tagEditReducer', () => {
|
||||||
|
|
||||||
describe('editTag', () => {
|
describe('editTag', () => {
|
||||||
const dispatch = jest.fn();
|
const dispatch = jest.fn();
|
||||||
const getState = () => Mock.of<ShlinkState>();
|
const getState = () => fromPartial<ShlinkState>({});
|
||||||
|
|
||||||
afterEach(jest.clearAllMocks);
|
afterEach(jest.clearAllMocks);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShlinkState } from '../../../src/container/types';
|
import type { ShlinkState } from '../../../src/container/types';
|
||||||
import type { ShortUrl, ShortUrlData } from '../../../src/short-urls/data';
|
import type { ShortUrl } from '../../../src/short-urls/data';
|
||||||
import { createShortUrl as createShortUrlCreator } from '../../../src/short-urls/reducers/shortUrlCreation';
|
import { createShortUrl as createShortUrlCreator } from '../../../src/short-urls/reducers/shortUrlCreation';
|
||||||
import { tagDeleted } from '../../../src/tags/reducers/tagDelete';
|
import { tagDeleted } from '../../../src/tags/reducers/tagDelete';
|
||||||
import { tagEdited } from '../../../src/tags/reducers/tagEdit';
|
import { tagEdited } from '../../../src/tags/reducers/tagEdit';
|
||||||
|
@ -12,10 +12,10 @@ import {
|
||||||
tagsListReducerCreator,
|
tagsListReducerCreator,
|
||||||
} from '../../../src/tags/reducers/tagsList';
|
} from '../../../src/tags/reducers/tagsList';
|
||||||
import { createNewVisits } from '../../../src/visits/reducers/visitCreation';
|
import { createNewVisits } from '../../../src/visits/reducers/visitCreation';
|
||||||
import type { CreateVisit, Visit } from '../../../src/visits/types';
|
import type { CreateVisit } from '../../../src/visits/types';
|
||||||
|
|
||||||
describe('tagsListReducer', () => {
|
describe('tagsListReducer', () => {
|
||||||
const state = (props: Partial<TagsList>) => Mock.of<TagsList>(props);
|
const state = (props: Partial<TagsList>) => fromPartial<TagsList>(props);
|
||||||
const buildShlinkApiClient = jest.fn();
|
const buildShlinkApiClient = jest.fn();
|
||||||
const listTags = listTagsCreator(buildShlinkApiClient, true);
|
const listTags = listTagsCreator(buildShlinkApiClient, true);
|
||||||
const createShortUrl = createShortUrlCreator(buildShlinkApiClient);
|
const createShortUrl = createShortUrlCreator(buildShlinkApiClient);
|
||||||
|
@ -41,7 +41,7 @@ describe('tagsListReducer', () => {
|
||||||
it('returns provided tags as filtered and regular tags on LIST_TAGS', () => {
|
it('returns provided tags as filtered and regular tags on LIST_TAGS', () => {
|
||||||
const tags = ['foo', 'bar', 'baz'];
|
const tags = ['foo', 'bar', 'baz'];
|
||||||
|
|
||||||
expect(reducer(undefined, listTags.fulfilled(Mock.of<TagsList>({ tags }), ''))).toEqual({
|
expect(reducer(undefined, listTags.fulfilled(fromPartial({ tags }), ''))).toEqual({
|
||||||
tags,
|
tags,
|
||||||
filteredTags: tags,
|
filteredTags: tags,
|
||||||
loading: false,
|
loading: false,
|
||||||
|
@ -114,30 +114,30 @@ describe('tagsListReducer', () => {
|
||||||
[['new', 'tag'], ['foo', 'bar', 'baz', 'foo2', 'fo', 'new', 'tag']],
|
[['new', 'tag'], ['foo', 'bar', 'baz', 'foo2', 'fo', 'new', 'tag']],
|
||||||
])('appends new short URL\'s tags to the list of tags on CREATE_SHORT_URL', (shortUrlTags, expectedTags) => {
|
])('appends new short URL\'s tags to the list of tags on CREATE_SHORT_URL', (shortUrlTags, expectedTags) => {
|
||||||
const tags = ['foo', 'bar', 'baz', 'foo2', 'fo'];
|
const tags = ['foo', 'bar', 'baz', 'foo2', 'fo'];
|
||||||
const payload = Mock.of<ShortUrl>({ tags: shortUrlTags });
|
const payload = fromPartial<ShortUrl>({ tags: shortUrlTags });
|
||||||
|
|
||||||
expect(reducer(state({ tags }), createShortUrl.fulfilled(payload, '', Mock.of<ShortUrlData>()))).toEqual({
|
expect(reducer(state({ tags }), createShortUrl.fulfilled(payload, '', fromPartial({})))).toEqual({
|
||||||
tags: expectedTags,
|
tags: expectedTags,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('increases amounts when visits are created', () => {
|
it('increases amounts when visits are created', () => {
|
||||||
const createdVisits = [
|
const createdVisits: CreateVisit[] = [
|
||||||
Mock.of<CreateVisit>({
|
fromPartial({
|
||||||
shortUrl: Mock.of<ShortUrl>({ tags: ['foo', 'bar'] }),
|
shortUrl: { tags: ['foo', 'bar'] },
|
||||||
visit: Mock.of<Visit>({ potentialBot: true }),
|
visit: { potentialBot: true },
|
||||||
}),
|
}),
|
||||||
Mock.of<CreateVisit>({
|
fromPartial({
|
||||||
shortUrl: Mock.of<ShortUrl>({ tags: ['foo', 'bar'] }),
|
shortUrl: { tags: ['foo', 'bar'] },
|
||||||
visit: Mock.all<Visit>(),
|
visit: {},
|
||||||
}),
|
}),
|
||||||
Mock.of<CreateVisit>({
|
fromPartial({
|
||||||
shortUrl: Mock.of<ShortUrl>({ tags: ['bar'] }),
|
shortUrl: { tags: ['bar'] },
|
||||||
visit: Mock.all<Visit>(),
|
visit: {},
|
||||||
}),
|
}),
|
||||||
Mock.of<CreateVisit>({
|
fromPartial({
|
||||||
shortUrl: Mock.of<ShortUrl>({ tags: ['baz'] }),
|
shortUrl: { tags: ['baz'] },
|
||||||
visit: Mock.of<Visit>({ potentialBot: true }),
|
visit: { potentialBot: true },
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
const tagStats = (total: number) => ({
|
const tagStats = (total: number) => ({
|
||||||
|
@ -197,11 +197,11 @@ describe('tagsListReducer', () => {
|
||||||
|
|
||||||
describe('listTags', () => {
|
describe('listTags', () => {
|
||||||
const dispatch = jest.fn();
|
const dispatch = jest.fn();
|
||||||
const getState = jest.fn(() => Mock.all<ShlinkState>());
|
const getState = jest.fn(() => fromPartial<ShlinkState>({}));
|
||||||
const listTagsMock = jest.fn();
|
const listTagsMock = jest.fn();
|
||||||
|
|
||||||
const assertNoAction = async (tagsList: TagsList) => {
|
const assertNoAction = async (tagsList: TagsList) => {
|
||||||
getState.mockReturnValue(Mock.of<ShlinkState>({ tagsList }));
|
getState.mockReturnValue(fromPartial<ShlinkState>({ tagsList }));
|
||||||
|
|
||||||
await listTagsCreator(buildShlinkApiClient, false)()(dispatch, getState, {});
|
await listTagsCreator(buildShlinkApiClient, false)()(dispatch, getState, {});
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { DropdownBtnMenuProps } from '../../src/utils/DropdownBtnMenu';
|
import type { DropdownBtnMenuProps } from '../../src/utils/DropdownBtnMenu';
|
||||||
import { DropdownBtnMenu } from '../../src/utils/DropdownBtnMenu';
|
import { DropdownBtnMenu } from '../../src/utils/DropdownBtnMenu';
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
|
|
||||||
describe('<DropdownBtnMenu />', () => {
|
describe('<DropdownBtnMenu />', () => {
|
||||||
const setUp = (props: Partial<DropdownBtnMenuProps> = {}) => renderWithEvents(
|
const setUp = (props: Partial<DropdownBtnMenuProps> = {}) => renderWithEvents(
|
||||||
<DropdownBtnMenu {...Mock.of<DropdownBtnMenuProps>({ toggle: jest.fn(), ...props })}>the children</DropdownBtnMenu>,
|
<DropdownBtnMenu {...fromPartial<DropdownBtnMenuProps>({ toggle: jest.fn(), ...props })}>
|
||||||
|
the children
|
||||||
|
</DropdownBtnMenu>,
|
||||||
);
|
);
|
||||||
|
|
||||||
it('renders expected components', () => {
|
it('renders expected components', () => {
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { screen, waitFor } from '@testing-library/react';
|
import { screen, waitFor } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { parseISO } from 'date-fns';
|
import { parseISO } from 'date-fns';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { DateInputProps } from '../../../src/utils/dates/DateInput';
|
import type { DateInputProps } from '../../../src/utils/dates/DateInput';
|
||||||
import { DateInput } from '../../../src/utils/dates/DateInput';
|
import { DateInput } from '../../../src/utils/dates/DateInput';
|
||||||
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
||||||
|
|
||||||
describe('<DateInput />', () => {
|
describe('<DateInput />', () => {
|
||||||
const setUp = (props: Partial<DateInputProps> = {}) => renderWithEvents(
|
const setUp = (props: Partial<DateInputProps> = {}) => renderWithEvents(
|
||||||
<DateInput {...Mock.of<DateInputProps>(props)} />,
|
<DateInput {...fromPartial<DateInputProps>(props)} />,
|
||||||
);
|
);
|
||||||
|
|
||||||
it('shows calendar icon when input is not clearable', () => {
|
it('shows calendar icon when input is not clearable', () => {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { screen, waitFor } from '@testing-library/react';
|
import { screen, waitFor } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { DateRangeSelectorProps } from '../../../src/utils/dates/DateRangeSelector';
|
import type { DateRangeSelectorProps } from '../../../src/utils/dates/DateRangeSelector';
|
||||||
import { DateRangeSelector } from '../../../src/utils/dates/DateRangeSelector';
|
import { DateRangeSelector } from '../../../src/utils/dates/DateRangeSelector';
|
||||||
import type { DateInterval } from '../../../src/utils/helpers/dateIntervals';
|
import type { DateInterval } from '../../../src/utils/helpers/dateIntervals';
|
||||||
|
@ -10,7 +10,7 @@ describe('<DateRangeSelector />', () => {
|
||||||
const setUp = async (props: Partial<DateRangeSelectorProps> = {}) => {
|
const setUp = async (props: Partial<DateRangeSelectorProps> = {}) => {
|
||||||
const result = renderWithEvents(
|
const result = renderWithEvents(
|
||||||
<DateRangeSelector
|
<DateRangeSelector
|
||||||
{...Mock.of<DateRangeSelectorProps>(props)}
|
{...fromPartial<DateRangeSelectorProps>(props)}
|
||||||
defaultText="Default text"
|
defaultText="Default text"
|
||||||
onDatesChange={onDatesChange}
|
onDatesChange={onDatesChange}
|
||||||
/>,
|
/>,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { SemVer, Versions } from '../../../src/utils/helpers/version';
|
import type { SemVer, Versions } from '../../../src/utils/helpers/version';
|
||||||
import { versionMatch } from '../../../src/utils/helpers/version';
|
import { versionMatch } from '../../../src/utils/helpers/version';
|
||||||
import type { Empty } from '../../../src/utils/utils';
|
import type { Empty } from '../../../src/utils/utils';
|
||||||
|
@ -6,19 +6,19 @@ import type { Empty } from '../../../src/utils/utils';
|
||||||
describe('version', () => {
|
describe('version', () => {
|
||||||
describe('versionMatch', () => {
|
describe('versionMatch', () => {
|
||||||
it.each([
|
it.each([
|
||||||
[undefined, Mock.all<Versions>(), false],
|
[undefined, fromPartial<Versions>({}), false],
|
||||||
[null, Mock.all<Versions>(), false],
|
[null, fromPartial<Versions>({}), false],
|
||||||
['' as Empty, Mock.all<Versions>(), false],
|
['' as Empty, fromPartial<Versions>({}), false],
|
||||||
[[], Mock.all<Versions>(), false],
|
[[], fromPartial<Versions>({}), false],
|
||||||
['2.8.3' as SemVer, Mock.all<Versions>(), true],
|
['2.8.3' as SemVer, fromPartial<Versions>({}), true],
|
||||||
['2.8.3' as SemVer, Mock.of<Versions>({ minVersion: '2.0.0' }), true],
|
['2.8.3' as SemVer, fromPartial<Versions>({ minVersion: '2.0.0' }), true],
|
||||||
['2.0.0' as SemVer, Mock.of<Versions>({ minVersion: '2.0.0' }), true],
|
['2.0.0' as SemVer, fromPartial<Versions>({ minVersion: '2.0.0' }), true],
|
||||||
['1.8.0' as SemVer, Mock.of<Versions>({ maxVersion: '1.8.0' }), true],
|
['1.8.0' as SemVer, fromPartial<Versions>({ maxVersion: '1.8.0' }), true],
|
||||||
['1.7.1' as SemVer, Mock.of<Versions>({ maxVersion: '1.8.0' }), true],
|
['1.7.1' as SemVer, fromPartial<Versions>({ maxVersion: '1.8.0' }), true],
|
||||||
['1.7.3' as SemVer, Mock.of<Versions>({ minVersion: '1.7.0', maxVersion: '1.8.0' }), true],
|
['1.7.3' as SemVer, fromPartial<Versions>({ minVersion: '1.7.0', maxVersion: '1.8.0' }), true],
|
||||||
['1.8.3' as SemVer, Mock.of<Versions>({ minVersion: '2.0.0' }), false],
|
['1.8.3' as SemVer, fromPartial<Versions>({ minVersion: '2.0.0' }), false],
|
||||||
['1.8.3' as SemVer, Mock.of<Versions>({ maxVersion: '1.8.0' }), false],
|
['1.8.3' as SemVer, fromPartial<Versions>({ maxVersion: '1.8.0' }), false],
|
||||||
['1.8.3' as SemVer, Mock.of<Versions>({ minVersion: '1.7.0', maxVersion: '1.8.0' }), false],
|
['1.8.3' as SemVer, fromPartial<Versions>({ minVersion: '1.7.0', maxVersion: '1.8.0' }), false],
|
||||||
])('properly matches versions based on what is provided', (version, versionConstraints, expected) => {
|
])('properly matches versions based on what is provided', (version, versionConstraints, expected) => {
|
||||||
expect(versionMatch(version, versionConstraints)).toEqual(expected);
|
expect(versionMatch(version, versionConstraints)).toEqual(expected);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { ColorGenerator } from '../../../src/utils/services/ColorGenerator';
|
import { ColorGenerator } from '../../../src/utils/services/ColorGenerator';
|
||||||
import type { LocalStorage } from '../../../src/utils/services/LocalStorage';
|
import type { LocalStorage } from '../../../src/utils/services/LocalStorage';
|
||||||
import { MAIN_COLOR } from '../../../src/utils/theme';
|
import { MAIN_COLOR } from '../../../src/utils/theme';
|
||||||
|
|
||||||
describe('ColorGenerator', () => {
|
describe('ColorGenerator', () => {
|
||||||
let colorGenerator: ColorGenerator;
|
let colorGenerator: ColorGenerator;
|
||||||
const storageMock = Mock.of<LocalStorage>({
|
const storageMock = fromPartial<LocalStorage>({
|
||||||
set: jest.fn(),
|
set: jest.fn(),
|
||||||
get: jest.fn(),
|
get: jest.fn(),
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { LocalStorage } from '../../../src/utils/services/LocalStorage';
|
import { LocalStorage } from '../../../src/utils/services/LocalStorage';
|
||||||
|
|
||||||
describe('LocalStorage', () => {
|
describe('LocalStorage', () => {
|
||||||
const getItem = jest.fn((key) => (key === 'shlink.foo' ? JSON.stringify({ foo: 'bar' }) : null));
|
const getItem = jest.fn((key) => (key === 'shlink.foo' ? JSON.stringify({ foo: 'bar' }) : null));
|
||||||
const setItem = jest.fn();
|
const setItem = jest.fn();
|
||||||
const localStorageMock = Mock.of<Storage>({ getItem, setItem });
|
const localStorageMock = fromPartial<Storage>({ getItem, setItem });
|
||||||
let storage: LocalStorage;
|
let storage: LocalStorage;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ColorGenerator } from '../../../../src/utils/services/ColorGenerator';
|
import type { ColorGenerator } from '../../../../src/utils/services/ColorGenerator';
|
||||||
|
|
||||||
export const colorGeneratorMock = Mock.of<ColorGenerator>({
|
export const colorGeneratorMock = fromPartial<ColorGenerator>({
|
||||||
getColorForKey: jest.fn(() => 'red'),
|
getColorForKey: jest.fn(() => 'red'),
|
||||||
setColorForKey: jest.fn(),
|
setColorForKey: jest.fn(),
|
||||||
isColorLightForKey: jest.fn(() => false),
|
isColorLightForKey: jest.fn(() => false),
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { formatISO } from 'date-fns';
|
import { formatISO } from 'date-fns';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { ReportExporter } from '../../src/common/services/ReportExporter';
|
|
||||||
import type { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
|
import type { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
|
||||||
import type { Settings } from '../../src/settings/reducers/settings';
|
|
||||||
import { DomainVisits as createDomainVisits } from '../../src/visits/DomainVisits';
|
import { DomainVisits as createDomainVisits } from '../../src/visits/DomainVisits';
|
||||||
import type { DomainVisits } from '../../src/visits/reducers/domainVisits';
|
import type { DomainVisits } from '../../src/visits/reducers/domainVisits';
|
||||||
import type { Visit } from '../../src/visits/types';
|
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
|
|
||||||
jest.mock('react-router-dom', () => ({
|
jest.mock('react-router-dom', () => ({
|
||||||
|
@ -19,16 +16,16 @@ describe('<DomainVisits />', () => {
|
||||||
const exportVisits = jest.fn();
|
const exportVisits = jest.fn();
|
||||||
const getDomainVisits = jest.fn();
|
const getDomainVisits = jest.fn();
|
||||||
const cancelGetDomainVisits = jest.fn();
|
const cancelGetDomainVisits = jest.fn();
|
||||||
const domainVisits = Mock.of<DomainVisits>({ visits: [Mock.of<Visit>({ date: formatISO(new Date()) })] });
|
const domainVisits = fromPartial<DomainVisits>({ visits: [{ date: formatISO(new Date()) }] });
|
||||||
const DomainVisits = createDomainVisits(Mock.of<ReportExporter>({ exportVisits }));
|
const DomainVisits = createDomainVisits(fromPartial({ exportVisits }));
|
||||||
const setUp = () => renderWithEvents(
|
const setUp = () => renderWithEvents(
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<DomainVisits
|
<DomainVisits
|
||||||
{...Mock.of<MercureBoundProps>({ mercureInfo: {} })}
|
{...fromPartial<MercureBoundProps>({ mercureInfo: {} })}
|
||||||
getDomainVisits={getDomainVisits}
|
getDomainVisits={getDomainVisits}
|
||||||
cancelGetDomainVisits={cancelGetDomainVisits}
|
cancelGetDomainVisits={cancelGetDomainVisits}
|
||||||
domainVisits={domainVisits}
|
domainVisits={domainVisits}
|
||||||
settings={Mock.all<Settings>()}
|
settings={fromPartial({})}
|
||||||
/>
|
/>
|
||||||
</MemoryRouter>,
|
</MemoryRouter>,
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,29 +1,26 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { formatISO } from 'date-fns';
|
import { formatISO } from 'date-fns';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { ReportExporter } from '../../src/common/services/ReportExporter';
|
|
||||||
import type { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
|
import type { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
|
||||||
import type { Settings } from '../../src/settings/reducers/settings';
|
|
||||||
import { NonOrphanVisits as createNonOrphanVisits } from '../../src/visits/NonOrphanVisits';
|
import { NonOrphanVisits as createNonOrphanVisits } from '../../src/visits/NonOrphanVisits';
|
||||||
import type { VisitsInfo } from '../../src/visits/reducers/types';
|
import type { VisitsInfo } from '../../src/visits/reducers/types';
|
||||||
import type { Visit } from '../../src/visits/types';
|
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
|
|
||||||
describe('<NonOrphanVisits />', () => {
|
describe('<NonOrphanVisits />', () => {
|
||||||
const exportVisits = jest.fn();
|
const exportVisits = jest.fn();
|
||||||
const getNonOrphanVisits = jest.fn();
|
const getNonOrphanVisits = jest.fn();
|
||||||
const cancelGetNonOrphanVisits = jest.fn();
|
const cancelGetNonOrphanVisits = jest.fn();
|
||||||
const nonOrphanVisits = Mock.of<VisitsInfo>({ visits: [Mock.of<Visit>({ date: formatISO(new Date()) })] });
|
const nonOrphanVisits = fromPartial<VisitsInfo>({ visits: [{ date: formatISO(new Date()) }] });
|
||||||
const NonOrphanVisits = createNonOrphanVisits(Mock.of<ReportExporter>({ exportVisits }));
|
const NonOrphanVisits = createNonOrphanVisits(fromPartial({ exportVisits }));
|
||||||
const setUp = () => renderWithEvents(
|
const setUp = () => renderWithEvents(
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<NonOrphanVisits
|
<NonOrphanVisits
|
||||||
{...Mock.of<MercureBoundProps>({ mercureInfo: {} })}
|
{...fromPartial<MercureBoundProps>({ mercureInfo: {} })}
|
||||||
getNonOrphanVisits={getNonOrphanVisits}
|
getNonOrphanVisits={getNonOrphanVisits}
|
||||||
cancelGetNonOrphanVisits={cancelGetNonOrphanVisits}
|
cancelGetNonOrphanVisits={cancelGetNonOrphanVisits}
|
||||||
nonOrphanVisits={nonOrphanVisits}
|
nonOrphanVisits={nonOrphanVisits}
|
||||||
settings={Mock.all<Settings>()}
|
settings={fromPartial({})}
|
||||||
/>
|
/>
|
||||||
</MemoryRouter>,
|
</MemoryRouter>,
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,28 +1,25 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { formatISO } from 'date-fns';
|
import { formatISO } from 'date-fns';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { ReportExporter } from '../../src/common/services/ReportExporter';
|
|
||||||
import type { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
|
import type { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
|
||||||
import type { Settings } from '../../src/settings/reducers/settings';
|
|
||||||
import { OrphanVisits as createOrphanVisits } from '../../src/visits/OrphanVisits';
|
import { OrphanVisits as createOrphanVisits } from '../../src/visits/OrphanVisits';
|
||||||
import type { VisitsInfo } from '../../src/visits/reducers/types';
|
import type { VisitsInfo } from '../../src/visits/reducers/types';
|
||||||
import type { Visit } from '../../src/visits/types';
|
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
|
|
||||||
describe('<OrphanVisits />', () => {
|
describe('<OrphanVisits />', () => {
|
||||||
const getOrphanVisits = jest.fn();
|
const getOrphanVisits = jest.fn();
|
||||||
const exportVisits = jest.fn();
|
const exportVisits = jest.fn();
|
||||||
const orphanVisits = Mock.of<VisitsInfo>({ visits: [Mock.of<Visit>({ date: formatISO(new Date()) })] });
|
const orphanVisits = fromPartial<VisitsInfo>({ visits: [{ date: formatISO(new Date()) }] });
|
||||||
const OrphanVisits = createOrphanVisits(Mock.of<ReportExporter>({ exportVisits }));
|
const OrphanVisits = createOrphanVisits(fromPartial({ exportVisits }));
|
||||||
const setUp = () => renderWithEvents(
|
const setUp = () => renderWithEvents(
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<OrphanVisits
|
<OrphanVisits
|
||||||
{...Mock.of<MercureBoundProps>({ mercureInfo: {} })}
|
{...fromPartial<MercureBoundProps>({ mercureInfo: {} })}
|
||||||
getOrphanVisits={getOrphanVisits}
|
getOrphanVisits={getOrphanVisits}
|
||||||
orphanVisits={orphanVisits}
|
orphanVisits={orphanVisits}
|
||||||
cancelGetOrphanVisits={jest.fn()}
|
cancelGetOrphanVisits={jest.fn()}
|
||||||
settings={Mock.all<Settings>()}
|
settings={fromPartial({})}
|
||||||
/>
|
/>
|
||||||
</MemoryRouter>,
|
</MemoryRouter>,
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,33 +1,29 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { formatISO } from 'date-fns';
|
import { formatISO } from 'date-fns';
|
||||||
import { identity } from 'ramda';
|
import { identity } from 'ramda';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { ReportExporter } from '../../src/common/services/ReportExporter';
|
|
||||||
import type { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
|
import type { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
|
||||||
import type { Settings } from '../../src/settings/reducers/settings';
|
|
||||||
import type { ShortUrlDetail } from '../../src/short-urls/reducers/shortUrlDetail';
|
|
||||||
import type { ShortUrlVisits as ShortUrlVisitsState } from '../../src/visits/reducers/shortUrlVisits';
|
import type { ShortUrlVisits as ShortUrlVisitsState } from '../../src/visits/reducers/shortUrlVisits';
|
||||||
import type { ShortUrlVisitsProps } from '../../src/visits/ShortUrlVisits';
|
import type { ShortUrlVisitsProps } from '../../src/visits/ShortUrlVisits';
|
||||||
import { ShortUrlVisits as createShortUrlVisits } from '../../src/visits/ShortUrlVisits';
|
import { ShortUrlVisits as createShortUrlVisits } from '../../src/visits/ShortUrlVisits';
|
||||||
import type { Visit } from '../../src/visits/types';
|
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
|
|
||||||
describe('<ShortUrlVisits />', () => {
|
describe('<ShortUrlVisits />', () => {
|
||||||
const getShortUrlVisitsMock = jest.fn();
|
const getShortUrlVisitsMock = jest.fn();
|
||||||
const exportVisits = jest.fn();
|
const exportVisits = jest.fn();
|
||||||
const shortUrlVisits = Mock.of<ShortUrlVisitsState>({ visits: [Mock.of<Visit>({ date: formatISO(new Date()) })] });
|
const shortUrlVisits = fromPartial<ShortUrlVisitsState>({ visits: [{ date: formatISO(new Date()) }] });
|
||||||
const ShortUrlVisits = createShortUrlVisits(Mock.of<ReportExporter>({ exportVisits }));
|
const ShortUrlVisits = createShortUrlVisits(fromPartial({ exportVisits }));
|
||||||
const setUp = () => renderWithEvents(
|
const setUp = () => renderWithEvents(
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<ShortUrlVisits
|
<ShortUrlVisits
|
||||||
{...Mock.all<ShortUrlVisitsProps>()}
|
{...fromPartial<ShortUrlVisitsProps>({})}
|
||||||
{...Mock.of<MercureBoundProps>({ mercureInfo: {} })}
|
{...fromPartial<MercureBoundProps>({ mercureInfo: {} })}
|
||||||
getShortUrlDetail={identity}
|
getShortUrlDetail={identity}
|
||||||
getShortUrlVisits={getShortUrlVisitsMock}
|
getShortUrlVisits={getShortUrlVisitsMock}
|
||||||
shortUrlVisits={shortUrlVisits}
|
shortUrlVisits={shortUrlVisits}
|
||||||
shortUrlDetail={Mock.all<ShortUrlDetail>()}
|
shortUrlDetail={fromPartial({})}
|
||||||
settings={Mock.all<Settings>()}
|
settings={fromPartial({})}
|
||||||
cancelGetShortUrlVisits={() => {}}
|
cancelGetShortUrlVisits={() => {}}
|
||||||
/>
|
/>
|
||||||
</MemoryRouter>,
|
</MemoryRouter>,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { screen, waitFor } from '@testing-library/react';
|
import { screen, waitFor } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { formatDistance, parseISO } from 'date-fns';
|
import { formatDistance, parseISO } from 'date-fns';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { ShortUrlDetail } from '../../src/short-urls/reducers/shortUrlDetail';
|
import type { ShortUrlDetail } from '../../src/short-urls/reducers/shortUrlDetail';
|
||||||
import type { ShortUrlVisits } from '../../src/visits/reducers/shortUrlVisits';
|
import type { ShortUrlVisits } from '../../src/visits/reducers/shortUrlVisits';
|
||||||
import { ShortUrlVisitsHeader } from '../../src/visits/ShortUrlVisitsHeader';
|
import { ShortUrlVisitsHeader } from '../../src/visits/ShortUrlVisitsHeader';
|
||||||
|
@ -9,12 +9,12 @@ import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
describe('<ShortUrlVisitsHeader />', () => {
|
describe('<ShortUrlVisitsHeader />', () => {
|
||||||
const dateCreated = '2018-01-01T10:00:00+00:00';
|
const dateCreated = '2018-01-01T10:00:00+00:00';
|
||||||
const longUrl = 'https://foo.bar/bar/foo';
|
const longUrl = 'https://foo.bar/bar/foo';
|
||||||
const shortUrlVisits = Mock.of<ShortUrlVisits>({
|
const shortUrlVisits = fromPartial<ShortUrlVisits>({
|
||||||
visits: [{}, {}, {}],
|
visits: [{}, {}, {}],
|
||||||
});
|
});
|
||||||
const goBack = jest.fn();
|
const goBack = jest.fn();
|
||||||
const setUp = (title?: string | null) => {
|
const setUp = (title?: string | null) => {
|
||||||
const shortUrlDetail = Mock.of<ShortUrlDetail>({
|
const shortUrlDetail = fromPartial<ShortUrlDetail>({
|
||||||
shortUrl: {
|
shortUrl: {
|
||||||
shortUrl: 'https://s.test/abc123',
|
shortUrl: 'https://s.test/abc123',
|
||||||
longUrl,
|
longUrl,
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { formatISO } from 'date-fns';
|
import { formatISO } from 'date-fns';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { ReportExporter } from '../../src/common/services/ReportExporter';
|
|
||||||
import type { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
|
import type { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
|
||||||
import type { Settings } from '../../src/settings/reducers/settings';
|
|
||||||
import type { ColorGenerator } from '../../src/utils/services/ColorGenerator';
|
|
||||||
import type { TagVisits as TagVisitsStats } from '../../src/visits/reducers/tagVisits';
|
import type { TagVisits as TagVisitsStats } from '../../src/visits/reducers/tagVisits';
|
||||||
import type { TagVisitsProps } from '../../src/visits/TagVisits';
|
import type { TagVisitsProps } from '../../src/visits/TagVisits';
|
||||||
import { TagVisits as createTagVisits } from '../../src/visits/TagVisits';
|
import { TagVisits as createTagVisits } from '../../src/visits/TagVisits';
|
||||||
import type { Visit } from '../../src/visits/types';
|
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
|
|
||||||
jest.mock('react-router-dom', () => ({
|
jest.mock('react-router-dom', () => ({
|
||||||
|
@ -20,19 +16,19 @@ jest.mock('react-router-dom', () => ({
|
||||||
describe('<TagVisits />', () => {
|
describe('<TagVisits />', () => {
|
||||||
const getTagVisitsMock = jest.fn();
|
const getTagVisitsMock = jest.fn();
|
||||||
const exportVisits = jest.fn();
|
const exportVisits = jest.fn();
|
||||||
const tagVisits = Mock.of<TagVisitsStats>({ visits: [Mock.of<Visit>({ date: formatISO(new Date()) })] });
|
const tagVisits = fromPartial<TagVisitsStats>({ visits: [{ date: formatISO(new Date()) }] });
|
||||||
const TagVisits = createTagVisits(
|
const TagVisits = createTagVisits(
|
||||||
Mock.of<ColorGenerator>({ isColorLightForKey: () => false, getColorForKey: () => 'red' }),
|
fromPartial({ isColorLightForKey: () => false, getColorForKey: () => 'red' }),
|
||||||
Mock.of<ReportExporter>({ exportVisits }),
|
fromPartial({ exportVisits }),
|
||||||
);
|
);
|
||||||
const setUp = () => renderWithEvents(
|
const setUp = () => renderWithEvents(
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<TagVisits
|
<TagVisits
|
||||||
{...Mock.all<TagVisitsProps>()}
|
{...fromPartial<TagVisitsProps>({})}
|
||||||
{...Mock.of<MercureBoundProps>({ mercureInfo: {} })}
|
{...fromPartial<MercureBoundProps>({ mercureInfo: {} })}
|
||||||
getTagVisits={getTagVisitsMock}
|
getTagVisits={getTagVisitsMock}
|
||||||
tagVisits={tagVisits}
|
tagVisits={tagVisits}
|
||||||
settings={Mock.all<Settings>()}
|
settings={fromPartial({})}
|
||||||
cancelGetTagVisits={() => {}}
|
cancelGetTagVisits={() => {}}
|
||||||
/>
|
/>
|
||||||
</MemoryRouter>,
|
</MemoryRouter>,
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ColorGenerator } from '../../src/utils/services/ColorGenerator';
|
import type { ColorGenerator } from '../../src/utils/services/ColorGenerator';
|
||||||
import type { TagVisits } from '../../src/visits/reducers/tagVisits';
|
import type { TagVisits } from '../../src/visits/reducers/tagVisits';
|
||||||
import { TagVisitsHeader } from '../../src/visits/TagVisitsHeader';
|
import { TagVisitsHeader } from '../../src/visits/TagVisitsHeader';
|
||||||
|
|
||||||
describe('<TagVisitsHeader />', () => {
|
describe('<TagVisitsHeader />', () => {
|
||||||
const tagVisits = Mock.of<TagVisits>({
|
const tagVisits = fromPartial<TagVisits>({
|
||||||
tag: 'foo',
|
tag: 'foo',
|
||||||
visits: [{}, {}, {}, {}],
|
visits: [{}, {}, {}, {}],
|
||||||
});
|
});
|
||||||
const goBack = jest.fn();
|
const goBack = jest.fn();
|
||||||
const colorGenerator = Mock.of<ColorGenerator>({ isColorLightForKey: () => false, getColorForKey: () => 'red' });
|
const colorGenerator = fromPartial<ColorGenerator>({ isColorLightForKey: () => false, getColorForKey: () => 'red' });
|
||||||
const setUp = () => render(<TagVisitsHeader tagVisits={tagVisits} goBack={goBack} colorGenerator={colorGenerator} />);
|
const setUp = () => render(<TagVisitsHeader tagVisits={tagVisits} goBack={goBack} colorGenerator={colorGenerator} />);
|
||||||
|
|
||||||
it('shows expected visits', () => {
|
it('shows expected visits', () => {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { Visit } from '../../src/visits/types';
|
import type { Visit } from '../../src/visits/types';
|
||||||
import { VisitsHeader } from '../../src/visits/VisitsHeader';
|
import { VisitsHeader } from '../../src/visits/VisitsHeader';
|
||||||
|
|
||||||
describe('<VisitsHeader />', () => {
|
describe('<VisitsHeader />', () => {
|
||||||
const visits = [Mock.all<Visit>(), Mock.all<Visit>(), Mock.all<Visit>()];
|
const visits: Visit[] = [fromPartial({}), fromPartial({}), fromPartial({})];
|
||||||
const title = 'My header title';
|
const title = 'My header title';
|
||||||
const goBack = jest.fn();
|
const goBack = jest.fn();
|
||||||
const setUp = () => render(<VisitsHeader visits={visits} goBack={goBack} title={title} />);
|
const setUp = () => render(<VisitsHeader visits={visits} goBack={goBack} title={title} />);
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import { screen, waitFor } from '@testing-library/react';
|
import { screen, waitFor } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { createMemoryHistory } from 'history';
|
import { createMemoryHistory } from 'history';
|
||||||
import { Router } from 'react-router-dom';
|
import { Router } from 'react-router-dom';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { Settings } from '../../src/settings/reducers/settings';
|
|
||||||
import { rangeOf } from '../../src/utils/utils';
|
import { rangeOf } from '../../src/utils/utils';
|
||||||
import type { VisitsInfo } from '../../src/visits/reducers/types';
|
import type { VisitsInfo } from '../../src/visits/reducers/types';
|
||||||
import type { Visit } from '../../src/visits/types';
|
import type { Visit } from '../../src/visits/types';
|
||||||
|
@ -10,7 +9,7 @@ import { VisitsStats } from '../../src/visits/VisitsStats';
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
|
|
||||||
describe('<VisitsStats />', () => {
|
describe('<VisitsStats />', () => {
|
||||||
const visits = rangeOf(3, () => Mock.of<Visit>({ date: '2020-01-01' }));
|
const visits = rangeOf(3, () => fromPartial<Visit>({ date: '2020-01-01' }));
|
||||||
const getVisitsMock = jest.fn();
|
const getVisitsMock = jest.fn();
|
||||||
const exportCsv = jest.fn();
|
const exportCsv = jest.fn();
|
||||||
const setUp = (visitsInfo: Partial<VisitsInfo>, activeRoute = '/by-time') => {
|
const setUp = (visitsInfo: Partial<VisitsInfo>, activeRoute = '/by-time') => {
|
||||||
|
@ -23,9 +22,9 @@ describe('<VisitsStats />', () => {
|
||||||
<Router location={history.location} navigator={history}>
|
<Router location={history.location} navigator={history}>
|
||||||
<VisitsStats
|
<VisitsStats
|
||||||
getVisits={getVisitsMock}
|
getVisits={getVisitsMock}
|
||||||
visitsInfo={Mock.of<VisitsInfo>(visitsInfo)}
|
visitsInfo={fromPartial(visitsInfo)}
|
||||||
cancelGetVisits={() => {}}
|
cancelGetVisits={() => {}}
|
||||||
settings={Mock.all<Settings>()}
|
settings={fromPartial({})}
|
||||||
exportCsv={exportCsv}
|
exportCsv={exportCsv}
|
||||||
/>
|
/>
|
||||||
</Router>,
|
</Router>,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { screen, waitFor } from '@testing-library/react';
|
import { screen, waitFor } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { rangeOf } from '../../src/utils/utils';
|
import { rangeOf } from '../../src/utils/utils';
|
||||||
import type { NormalizedVisit } from '../../src/visits/types';
|
import type { NormalizedVisit } from '../../src/visits/types';
|
||||||
import type { VisitsTableProps } from '../../src/visits/VisitsTable';
|
import type { VisitsTableProps } from '../../src/visits/VisitsTable';
|
||||||
|
@ -7,7 +7,7 @@ import { VisitsTable } from '../../src/visits/VisitsTable';
|
||||||
import { renderWithEvents } from '../__helpers__/setUpTest';
|
import { renderWithEvents } from '../__helpers__/setUpTest';
|
||||||
|
|
||||||
describe('<VisitsTable />', () => {
|
describe('<VisitsTable />', () => {
|
||||||
const matchMedia = () => Mock.of<MediaQueryList>({ matches: false });
|
const matchMedia = () => fromPartial<MediaQueryList>({ matches: false });
|
||||||
const setSelectedVisits = jest.fn();
|
const setSelectedVisits = jest.fn();
|
||||||
const setUpFactory = (props: Partial<VisitsTableProps> = {}) => renderWithEvents(
|
const setUpFactory = (props: Partial<VisitsTableProps> = {}) => renderWithEvents(
|
||||||
<VisitsTable
|
<VisitsTable
|
||||||
|
@ -23,8 +23,8 @@ describe('<VisitsTable />', () => {
|
||||||
const setUpForOrphanVisits = (isOrphanVisits: boolean) => setUpFactory({ isOrphanVisits });
|
const setUpForOrphanVisits = (isOrphanVisits: boolean) => setUpFactory({ isOrphanVisits });
|
||||||
const setUpWithBots = () => setUpFactory({
|
const setUpWithBots = () => setUpFactory({
|
||||||
visits: [
|
visits: [
|
||||||
Mock.of<NormalizedVisit>({ potentialBot: false, date: '2022-05-05' }),
|
fromPartial({ potentialBot: false, date: '2022-05-05' }),
|
||||||
Mock.of<NormalizedVisit>({ potentialBot: true, date: '2022-05-05' }),
|
fromPartial({ potentialBot: true, date: '2022-05-05' }),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ describe('<VisitsTable />', () => {
|
||||||
[115, 7, 2], // This one will have ellipsis
|
[115, 7, 2], // This one will have ellipsis
|
||||||
])('renders the expected amount of pages', (visitsCount, expectedAmountOfPageItems, expectedDisabledItems) => {
|
])('renders the expected amount of pages', (visitsCount, expectedAmountOfPageItems, expectedDisabledItems) => {
|
||||||
const { container } = setUp(
|
const { container } = setUp(
|
||||||
rangeOf(visitsCount, () => Mock.of<NormalizedVisit>({ browser: '', date: '2022-01-01', referer: '' })),
|
rangeOf(visitsCount, () => fromPartial<NormalizedVisit>({ browser: '', date: '2022-01-01', referer: '' })),
|
||||||
);
|
);
|
||||||
expect(container.querySelectorAll('.page-item')).toHaveLength(expectedAmountOfPageItems);
|
expect(container.querySelectorAll('.page-item')).toHaveLength(expectedAmountOfPageItems);
|
||||||
expect(container.querySelectorAll('.disabled')).toHaveLength(expectedDisabledItems);
|
expect(container.querySelectorAll('.disabled')).toHaveLength(expectedDisabledItems);
|
||||||
|
@ -58,7 +58,7 @@ describe('<VisitsTable />', () => {
|
||||||
rangeOf(20, (value) => [value]),
|
rangeOf(20, (value) => [value]),
|
||||||
)('does not render footer when there is only one page to render', (visitsCount) => {
|
)('does not render footer when there is only one page to render', (visitsCount) => {
|
||||||
const { container } = setUp(
|
const { container } = setUp(
|
||||||
rangeOf(visitsCount, () => Mock.of<NormalizedVisit>({ browser: '', date: '2022-01-01', referer: '' })),
|
rangeOf(visitsCount, () => fromPartial<NormalizedVisit>({ browser: '', date: '2022-01-01', referer: '' })),
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(container.querySelector('tfoot')).not.toBeInTheDocument();
|
expect(container.querySelector('tfoot')).not.toBeInTheDocument();
|
||||||
|
@ -66,7 +66,7 @@ describe('<VisitsTable />', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('selected rows are highlighted', async () => {
|
it('selected rows are highlighted', async () => {
|
||||||
const visits = rangeOf(10, () => Mock.of<NormalizedVisit>({ browser: '', date: '2022-01-01', referer: '' }));
|
const visits = rangeOf(10, () => fromPartial<NormalizedVisit>({ browser: '', date: '2022-01-01', referer: '' }));
|
||||||
const { container, user } = setUp(visits, [visits[1], visits[2]]);
|
const { container, user } = setUp(visits, [visits[1], visits[2]]);
|
||||||
|
|
||||||
// Initial situation
|
// Initial situation
|
||||||
|
@ -86,7 +86,7 @@ describe('<VisitsTable />', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('orders visits when column is clicked', async () => {
|
it('orders visits when column is clicked', async () => {
|
||||||
const { user } = setUp(rangeOf(9, (index) => Mock.of<NormalizedVisit>({
|
const { user } = setUp(rangeOf(9, (index) => fromPartial<NormalizedVisit>({
|
||||||
browser: '',
|
browser: '',
|
||||||
date: `2022-01-0${10 - index}`,
|
date: `2022-01-0${10 - index}`,
|
||||||
referer: `${index}`,
|
referer: `${index}`,
|
||||||
|
@ -108,8 +108,8 @@ describe('<VisitsTable />', () => {
|
||||||
|
|
||||||
it('filters list when writing in search box', async () => {
|
it('filters list when writing in search box', async () => {
|
||||||
const { user } = setUp([
|
const { user } = setUp([
|
||||||
...rangeOf(7, () => Mock.of<NormalizedVisit>({ browser: 'aaa', date: '2022-01-01', referer: 'aaa' })),
|
...rangeOf(7, () => fromPartial<NormalizedVisit>({ browser: 'aaa', date: '2022-01-01', referer: 'aaa' })),
|
||||||
...rangeOf(2, () => Mock.of<NormalizedVisit>({ browser: 'bbb', date: '2022-01-01', referer: 'bbb' })),
|
...rangeOf(2, () => fromPartial<NormalizedVisit>({ browser: 'bbb', date: '2022-01-01', referer: 'bbb' })),
|
||||||
]);
|
]);
|
||||||
const searchField = screen.getByPlaceholderText('Search...');
|
const searchField = screen.getByPlaceholderText('Search...');
|
||||||
const searchText = async (text: string) => {
|
const searchText = async (text: string) => {
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { Chart, ChartDataset } from 'chart.js';
|
import type { Chart, ChartDataset } from 'chart.js';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import { DoughnutChartLegend } from '../../../src/visits/charts/DoughnutChartLegend';
|
import { DoughnutChartLegend } from '../../../src/visits/charts/DoughnutChartLegend';
|
||||||
|
|
||||||
describe('<DoughnutChartLegend />', () => {
|
describe('<DoughnutChartLegend />', () => {
|
||||||
const labels = ['foo', 'bar', 'baz', 'foo2', 'bar2'];
|
const labels = ['foo', 'bar', 'baz', 'foo2', 'bar2'];
|
||||||
const colors = ['green', 'blue', 'yellow'];
|
const colors = ['green', 'blue', 'yellow'];
|
||||||
const defaultColor = 'red';
|
const defaultColor = 'red';
|
||||||
const datasets = [Mock.of<ChartDataset>({ backgroundColor: colors })];
|
const datasets = [fromPartial<ChartDataset>({ backgroundColor: colors })];
|
||||||
const chart = Mock.of<Chart>({
|
const chart = fromPartial<Chart>({
|
||||||
config: {
|
config: {
|
||||||
data: { labels, datasets },
|
data: { labels, datasets },
|
||||||
options: { defaultColor } as any,
|
options: { defaultColor } as any,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { formatISO, subDays, subMonths, subYears } from 'date-fns';
|
import { formatISO, subDays, subMonths, subYears } from 'date-fns';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import { LineChartCard } from '../../../src/visits/charts/LineChartCard';
|
import { LineChartCard } from '../../../src/visits/charts/LineChartCard';
|
||||||
import type { NormalizedVisit } from '../../../src/visits/types';
|
import type { NormalizedVisit } from '../../../src/visits/types';
|
||||||
import { setUpCanvas } from '../../__helpers__/setUpTest';
|
import { setUpCanvas } from '../../__helpers__/setUpTest';
|
||||||
|
@ -29,7 +29,7 @@ describe('<LineChartCard />', () => {
|
||||||
visits,
|
visits,
|
||||||
expectedActiveIndex,
|
expectedActiveIndex,
|
||||||
) => {
|
) => {
|
||||||
const { user } = setUp(visits.map((visit) => Mock.of<NormalizedVisit>(visit)));
|
const { user } = setUp(visits.map((visit) => fromPartial(visit)));
|
||||||
|
|
||||||
await user.click(screen.getByRole('button', { name: /Group by/ }));
|
await user.click(screen.getByRole('button', { name: /Group by/ }));
|
||||||
|
|
||||||
|
@ -46,8 +46,8 @@ describe('<LineChartCard />', () => {
|
||||||
it.each([
|
it.each([
|
||||||
[undefined, undefined],
|
[undefined, undefined],
|
||||||
[[], []],
|
[[], []],
|
||||||
[[Mock.of<NormalizedVisit>({ date: '2016-04-01' })], []],
|
[[fromPartial<NormalizedVisit>({ date: '2016-04-01' })], []],
|
||||||
[[Mock.of<NormalizedVisit>({ date: '2016-04-01' })], [Mock.of<NormalizedVisit>({ date: '2016-04-01' })]],
|
[[fromPartial<NormalizedVisit>({ date: '2016-04-01' })], [fromPartial<NormalizedVisit>({ date: '2016-04-01' })]],
|
||||||
])('renders chart with expected data', (visits, highlightedVisits) => {
|
])('renders chart with expected data', (visits, highlightedVisits) => {
|
||||||
const { events } = setUp(visits, highlightedVisits);
|
const { events } = setUp(visits, highlightedVisits);
|
||||||
|
|
||||||
|
@ -57,8 +57,8 @@ describe('<LineChartCard />', () => {
|
||||||
|
|
||||||
it('includes stats for visits with no dates if selected', async () => {
|
it('includes stats for visits with no dates if selected', async () => {
|
||||||
const { getEvents, user } = setUp([
|
const { getEvents, user } = setUp([
|
||||||
Mock.of<NormalizedVisit>({ date: '2016-04-01' }),
|
fromPartial({ date: '2016-04-01' }),
|
||||||
Mock.of<NormalizedVisit>({ date: '2016-01-01' }),
|
fromPartial({ date: '2016-01-01' }),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const eventsBefore = getEvents();
|
const eventsBefore = getEvents();
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import { screen, waitFor } from '@testing-library/react';
|
import { screen, waitFor } from '@testing-library/react';
|
||||||
import { Mock } from 'ts-mockery';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { OpenMapModalBtn } from '../../../src/visits/helpers/OpenMapModalBtn';
|
import { OpenMapModalBtn } from '../../../src/visits/helpers/OpenMapModalBtn';
|
||||||
import type { CityStats } from '../../../src/visits/types';
|
import type { CityStats } from '../../../src/visits/types';
|
||||||
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
||||||
|
|
||||||
describe('<OpenMapModalBtn />', () => {
|
describe('<OpenMapModalBtn />', () => {
|
||||||
const title = 'Foo';
|
const title = 'Foo';
|
||||||
const locations = [
|
const locations: CityStats[] = [
|
||||||
Mock.of<CityStats>({ cityName: 'foo', count: 30, latLong: [5, 5] }),
|
fromPartial({ cityName: 'foo', count: 30, latLong: [5, 5] }),
|
||||||
Mock.of<CityStats>({ cityName: 'bar', count: 45, latLong: [88, 88] }),
|
fromPartial({ cityName: 'bar', count: 45, latLong: [88, 88] }),
|
||||||
];
|
];
|
||||||
const setUp = (activeCities?: string[]) => renderWithEvents(
|
const setUp = (activeCities?: string[]) => renderWithEvents(
|
||||||
<OpenMapModalBtn modalTitle={title} locations={locations} activeCities={activeCities} />,
|
<OpenMapModalBtn modalTitle={title} locations={locations} activeCities={activeCities} />,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { addDays, formatISO, subDays } from 'date-fns';
|
import { addDays, formatISO, subDays } from 'date-fns';
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
import type { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
||||||
import type { ShlinkVisits } from '../../../src/api/types';
|
import type { ShlinkVisits } from '../../../src/api/types';
|
||||||
import type { ShlinkState } from '../../../src/container/types';
|
import type { ShlinkState } from '../../../src/container/types';
|
||||||
|
@ -16,25 +16,25 @@ import {
|
||||||
getDomainVisits as getDomainVisitsCreator,
|
getDomainVisits as getDomainVisitsCreator,
|
||||||
} from '../../../src/visits/reducers/domainVisits';
|
} from '../../../src/visits/reducers/domainVisits';
|
||||||
import { createNewVisits } from '../../../src/visits/reducers/visitCreation';
|
import { createNewVisits } from '../../../src/visits/reducers/visitCreation';
|
||||||
import type { CreateVisit, Visit } from '../../../src/visits/types';
|
import type { Visit } from '../../../src/visits/types';
|
||||||
|
|
||||||
describe('domainVisitsReducer', () => {
|
describe('domainVisitsReducer', () => {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const visitsMocks = rangeOf(2, () => Mock.all<Visit>());
|
const visitsMocks = rangeOf(2, () => fromPartial<Visit>({}));
|
||||||
const getDomainVisitsCall = jest.fn();
|
const getDomainVisitsCall = jest.fn();
|
||||||
const buildApiClientMock = () => Mock.of<ShlinkApiClient>({ getDomainVisits: getDomainVisitsCall });
|
const buildApiClientMock = () => fromPartial<ShlinkApiClient>({ getDomainVisits: getDomainVisitsCall });
|
||||||
const getDomainVisits = getDomainVisitsCreator(buildApiClientMock);
|
const getDomainVisits = getDomainVisitsCreator(buildApiClientMock);
|
||||||
const { reducer, cancelGetVisits: cancelGetDomainVisits } = domainVisitsReducerCreator(getDomainVisits);
|
const { reducer, cancelGetVisits: cancelGetDomainVisits } = domainVisitsReducerCreator(getDomainVisits);
|
||||||
|
|
||||||
beforeEach(jest.clearAllMocks);
|
beforeEach(jest.clearAllMocks);
|
||||||
|
|
||||||
describe('reducer', () => {
|
describe('reducer', () => {
|
||||||
const buildState = (data: Partial<DomainVisits>) => Mock.of<DomainVisits>(data);
|
const buildState = (data: Partial<DomainVisits>) => fromPartial<DomainVisits>(data);
|
||||||
|
|
||||||
it('returns loading on GET_DOMAIN_VISITS_START', () => {
|
it('returns loading on GET_DOMAIN_VISITS_START', () => {
|
||||||
const { loading } = reducer(
|
const { loading } = reducer(
|
||||||
buildState({ loading: false }),
|
buildState({ loading: false }),
|
||||||
getDomainVisits.pending('', Mock.all<LoadDomainVisits>()),
|
getDomainVisits.pending('', fromPartial<LoadDomainVisits>({})),
|
||||||
);
|
);
|
||||||
expect(loading).toEqual(true);
|
expect(loading).toEqual(true);
|
||||||
});
|
});
|
||||||
|
@ -52,7 +52,7 @@ describe('domainVisitsReducer', () => {
|
||||||
it('stops loading and returns error on GET_DOMAIN_VISITS_ERROR', () => {
|
it('stops loading and returns error on GET_DOMAIN_VISITS_ERROR', () => {
|
||||||
const state = reducer(
|
const state = reducer(
|
||||||
buildState({ loading: true, error: false }),
|
buildState({ loading: true, error: false }),
|
||||||
getDomainVisits.rejected(null, '', Mock.all<LoadDomainVisits>()),
|
getDomainVisits.rejected(null, '', fromPartial({})),
|
||||||
);
|
);
|
||||||
const { loading, error } = state;
|
const { loading, error } = state;
|
||||||
|
|
||||||
|
@ -61,10 +61,10 @@ describe('domainVisitsReducer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('return visits on GET_DOMAIN_VISITS', () => {
|
it('return visits on GET_DOMAIN_VISITS', () => {
|
||||||
const actionVisits = [Mock.all<Visit>(), Mock.all<Visit>()];
|
const actionVisits: Visit[] = [fromPartial({}), fromPartial({})];
|
||||||
const { loading, error, visits } = reducer(
|
const { loading, error, visits } = reducer(
|
||||||
buildState({ loading: true, error: false }),
|
buildState({ loading: true, error: false }),
|
||||||
getDomainVisits.fulfilled({ visits: actionVisits }, '', Mock.all<LoadDomainVisits>()),
|
getDomainVisits.fulfilled({ visits: actionVisits }, '', fromPartial({})),
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(loading).toEqual(false);
|
expect(loading).toEqual(false);
|
||||||
|
@ -75,10 +75,10 @@ describe('domainVisitsReducer', () => {
|
||||||
it.each([
|
it.each([
|
||||||
[{ domain: 'foo.com' }, 'foo.com', visitsMocks.length + 1],
|
[{ domain: 'foo.com' }, 'foo.com', visitsMocks.length + 1],
|
||||||
[{ domain: 'bar.com' }, 'foo.com', visitsMocks.length],
|
[{ domain: 'bar.com' }, 'foo.com', visitsMocks.length],
|
||||||
[Mock.of<DomainVisits>({ domain: 'foo.com' }), 'foo.com', visitsMocks.length + 1],
|
[fromPartial<DomainVisits>({ domain: 'foo.com' }), 'foo.com', visitsMocks.length + 1],
|
||||||
[Mock.of<DomainVisits>({ domain: DEFAULT_DOMAIN }), null, visitsMocks.length + 1],
|
[fromPartial<DomainVisits>({ domain: DEFAULT_DOMAIN }), null, visitsMocks.length + 1],
|
||||||
[
|
[
|
||||||
Mock.of<DomainVisits>({
|
fromPartial<DomainVisits>({
|
||||||
domain: 'foo.com',
|
domain: 'foo.com',
|
||||||
query: { endDate: formatIsoDate(subDays(now, 1)) ?? undefined },
|
query: { endDate: formatIsoDate(subDays(now, 1)) ?? undefined },
|
||||||
}),
|
}),
|
||||||
|
@ -86,7 +86,7 @@ describe('domainVisitsReducer', () => {
|
||||||
visitsMocks.length,
|
visitsMocks.length,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
Mock.of<DomainVisits>({
|
fromPartial<DomainVisits>({
|
||||||
domain: 'foo.com',
|
domain: 'foo.com',
|
||||||
query: { startDate: formatIsoDate(addDays(now, 1)) ?? undefined },
|
query: { startDate: formatIsoDate(addDays(now, 1)) ?? undefined },
|
||||||
}),
|
}),
|
||||||
|
@ -94,7 +94,7 @@ describe('domainVisitsReducer', () => {
|
||||||
visitsMocks.length,
|
visitsMocks.length,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
Mock.of<DomainVisits>({
|
fromPartial<DomainVisits>({
|
||||||
domain: 'foo.com',
|
domain: 'foo.com',
|
||||||
query: {
|
query: {
|
||||||
startDate: formatIsoDate(subDays(now, 5)) ?? undefined,
|
startDate: formatIsoDate(subDays(now, 5)) ?? undefined,
|
||||||
|
@ -105,7 +105,7 @@ describe('domainVisitsReducer', () => {
|
||||||
visitsMocks.length,
|
visitsMocks.length,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
Mock.of<DomainVisits>({
|
fromPartial<DomainVisits>({
|
||||||
domain: 'foo.com',
|
domain: 'foo.com',
|
||||||
query: {
|
query: {
|
||||||
startDate: formatIsoDate(subDays(now, 5)) ?? undefined,
|
startDate: formatIsoDate(subDays(now, 5)) ?? undefined,
|
||||||
|
@ -116,7 +116,7 @@ describe('domainVisitsReducer', () => {
|
||||||
visitsMocks.length + 1,
|
visitsMocks.length + 1,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
Mock.of<DomainVisits>({
|
fromPartial<DomainVisits>({
|
||||||
domain: 'bar.com',
|
domain: 'bar.com',
|
||||||
query: {
|
query: {
|
||||||
startDate: formatIsoDate(subDays(now, 5)) ?? undefined,
|
startDate: formatIsoDate(subDays(now, 5)) ?? undefined,
|
||||||
|
@ -127,9 +127,9 @@ describe('domainVisitsReducer', () => {
|
||||||
visitsMocks.length,
|
visitsMocks.length,
|
||||||
],
|
],
|
||||||
])('prepends new visits on CREATE_VISIT', (state, shortUrlDomain, expectedVisits) => {
|
])('prepends new visits on CREATE_VISIT', (state, shortUrlDomain, expectedVisits) => {
|
||||||
const shortUrl = Mock.of<ShortUrl>({ domain: shortUrlDomain });
|
const shortUrl = fromPartial<ShortUrl>({ domain: shortUrlDomain });
|
||||||
const { visits } = reducer(buildState({ ...state, visits: visitsMocks }), createNewVisits([
|
const { visits } = reducer(buildState({ ...state, visits: visitsMocks }), createNewVisits([
|
||||||
Mock.of<CreateVisit>({ shortUrl, visit: { date: formatIsoDate(now) ?? undefined } }),
|
fromPartial({ shortUrl, visit: { date: formatIsoDate(now) ?? undefined } }),
|
||||||
]));
|
]));
|
||||||
|
|
||||||
expect(visits).toHaveLength(expectedVisits);
|
expect(visits).toHaveLength(expectedVisits);
|
||||||
|
@ -153,7 +153,7 @@ describe('domainVisitsReducer', () => {
|
||||||
|
|
||||||
describe('getDomainVisits', () => {
|
describe('getDomainVisits', () => {
|
||||||
const dispatchMock = jest.fn();
|
const dispatchMock = jest.fn();
|
||||||
const getState = () => Mock.of<ShlinkState>({
|
const getState = () => fromPartial<ShlinkState>({
|
||||||
domainVisits: { cancelLoad: false },
|
domainVisits: { cancelLoad: false },
|
||||||
});
|
});
|
||||||
const domain = 'foo.com';
|
const domain = 'foo.com';
|
||||||
|
@ -183,12 +183,12 @@ describe('domainVisitsReducer', () => {
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[
|
[
|
||||||
[Mock.of<Visit>({ date: formatISO(subDays(now, 20)) })],
|
[fromPartial<Visit>({ date: formatISO(subDays(now, 20)) })],
|
||||||
getDomainVisits.fallbackToInterval('last30Days'),
|
getDomainVisits.fallbackToInterval('last30Days'),
|
||||||
3,
|
3,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
[Mock.of<Visit>({ date: formatISO(subDays(now, 100)) })],
|
[fromPartial<Visit>({ date: formatISO(subDays(now, 100)) })],
|
||||||
getDomainVisits.fallbackToInterval('last180Days'),
|
getDomainVisits.fallbackToInterval('last180Days'),
|
||||||
3,
|
3,
|
||||||
],
|
],
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue