Update tests to use vi instead of jest

This commit is contained in:
Alejandro Celaya 2023-05-27 11:57:26 +02:00
parent e2cbb2713a
commit 07fcb4e016
117 changed files with 3699 additions and 325 deletions

View file

@ -1,18 +1,18 @@
import { fromAny, fromPartial } from '@total-typescript/shoehorn';
const createLinkMock = () => ({
setAttribute: jest.fn(),
click: jest.fn(),
setAttribute: vi.fn(),
click: vi.fn(),
style: {},
});
export const appendChild = jest.fn();
export const appendChild = vi.fn();
export const removeChild = jest.fn();
export const removeChild = vi.fn();
export const windowMock = fromPartial<Window>({
document: fromAny({
createElement: jest.fn(createLinkMock),
createElement: vi.fn(createLinkMock),
body: { appendChild, removeChild },
}),
});

View file

@ -7,8 +7,8 @@ import type { ShortUrl, ShortUrlsOrder } from '../../../src/short-urls/data';
import type { OptionalString } from '../../../src/utils/utils';
describe('ShlinkApiClient', () => {
const fetchJson = jest.fn().mockResolvedValue({});
const fetchEmpty = jest.fn().mockResolvedValue(undefined);
const fetchJson = vi.fn().mockResolvedValue({});
const fetchEmpty = vi.fn().mockResolvedValue(undefined);
const httpClient = fromPartial<HttpClient>({ fetchJson, fetchEmpty });
const buildApiClient = () => new ShlinkApiClient(httpClient, '', '');
const shortCodesWithDomainCombinations: [string, OptionalString][] = [
@ -17,7 +17,7 @@ describe('ShlinkApiClient', () => {
['abc123', 'example.com'],
];
beforeEach(jest.clearAllMocks);
beforeEach(vi.clearAllMocks);
describe('listShortUrls', () => {
const expectedList = ['foo', 'bar'];

View file

@ -32,7 +32,7 @@ describe('<App />', () => {
);
};
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('renders children components', () => {
setUp();

View file

@ -3,11 +3,11 @@ import { AppUpdateBanner } from '../../src/common/AppUpdateBanner';
import { renderWithEvents } from '../__helpers__/setUpTest';
describe('<AppUpdateBanner />', () => {
const toggle = jest.fn();
const forceUpdate = jest.fn();
const toggle = vi.fn();
const forceUpdate = vi.fn();
const setUp = () => renderWithEvents(<AppUpdateBanner isOpen toggle={toggle} forceUpdate={forceUpdate} />);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('renders initial state', () => {
setUp();

View file

@ -1,6 +1,6 @@
import { render, screen } from '@testing-library/react';
import { fromPartial } from '@total-typescript/shoehorn';
import { MemoryRouter } from 'react-router-dom';
import { MemoryRouter } from 'react-router';
import { AsideMenu as createAsideMenu } from '../../src/common/AsideMenu';
describe('<AsideMenu />', () => {

View file

@ -8,17 +8,17 @@ const ComponentWithError = () => {
};
describe('<ErrorHandler />', () => {
const reload = jest.fn();
const reload = vi.fn();
const window = fromPartial<Window>({
location: { reload },
});
const cons = fromPartial<Console>({ error: jest.fn() });
const cons = fromPartial<Console>({ error: vi.fn() });
const ErrorHandler = createErrorHandler(window, cons);
beforeEach(() => {
jest.spyOn(console, 'error').mockImplementation(() => {}); // Silence react errors
vi.spyOn(console, 'error').mockImplementation(() => {}); // Silence react errors
});
afterEach(jest.resetAllMocks);
afterEach(vi.resetAllMocks);
it('renders children when no error has occurred', () => {
render(<ErrorHandler children={<span>Foo</span>} />);

View file

@ -1,6 +1,6 @@
import { render, screen } from '@testing-library/react';
import { fromPartial } from '@total-typescript/shoehorn';
import { MemoryRouter } from 'react-router-dom';
import { MemoryRouter } from 'react-router';
import { Home } from '../../src/common/Home';
import type { ServersMap, ServerWithId } from '../../src/servers/data';

View file

@ -6,7 +6,7 @@ import { MenuLayout as createMenuLayout } from '../../src/common/MenuLayout';
import type { NonReachableServer, NotFoundServer, SelectedServer } from '../../src/servers/data';
import type { SemVer } from '../../src/utils/helpers/version';
jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useParams: jest.fn() }));
vi.mock('react-router-dom', async () => ({ ...(await vi.importActual<any>('react-router-dom')), useParams: vi.fn() }));
describe('<MenuLayout />', () => {
const MenuLayout = createMenuLayout(
@ -31,9 +31,9 @@ describe('<MenuLayout />', () => {
return render(
<Router location={history.location} navigator={history}>
<MenuLayout
sidebarNotPresent={jest.fn()}
sidebarPresent={jest.fn()}
selectServer={jest.fn()}
sidebarNotPresent={vi.fn()}
sidebarPresent={vi.fn()}
selectServer={vi.fn()}
selectedServer={selectedServer}
/>
</Router>,
@ -44,7 +44,7 @@ describe('<MenuLayout />', () => {
(useParams as any).mockReturnValue({ serverId: 'abc123' });
});
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('shows loading indicator while loading server', () => {
setUp(null);

View file

@ -1,5 +1,5 @@
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import { MemoryRouter } from 'react-router';
import { NotFound } from '../../src/common/NotFound';
describe('<NotFound />', () => {

View file

@ -1,5 +1,5 @@
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import { MemoryRouter } from 'react-router';
import { ScrollToTop } from '../../src/common/ScrollToTop';
describe('<ScrollToTop />', () => {

View file

@ -4,7 +4,7 @@ import { ELLIPSIS } from '../../src/utils/helpers/pagination';
describe('<SimplePaginator />', () => {
const setUp = (pagesCount: number, currentPage = 1) => render(
<SimplePaginator pagesCount={pagesCount} currentPage={currentPage} setCurrentPage={jest.fn()} />,
<SimplePaginator pagesCount={pagesCount} currentPage={currentPage} setCurrentPage={vi.fn()} />,
);
it.each([-3, -2, 0, 1])('renders empty when the amount of pages is smaller than 2', (pagesCount) => {

View file

@ -1,10 +1,10 @@
import { HttpClient } from '../../../src/common/services/HttpClient';
describe('HttpClient', () => {
const fetch = jest.fn();
const fetch = vi.fn();
const httpClient = new HttpClient(fetch);
beforeEach(jest.clearAllMocks);
beforeEach(vi.clearAllMocks);
describe('fetchJson', () => {
it('throws json on success', async () => {

View file

@ -4,12 +4,12 @@ import { ImageDownloader } from '../../../src/common/services/ImageDownloader';
import { windowMock } from '../../__mocks__/Window.mock';
describe('ImageDownloader', () => {
const fetchBlob = jest.fn();
const fetchBlob = vi.fn();
const httpClient = fromPartial<HttpClient>({ fetchBlob });
let imageDownloader: ImageDownloader;
beforeEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
(global as any).URL = { createObjectURL: () => '' };
imageDownloader = new ImageDownloader(httpClient, windowMock);

View file

@ -4,10 +4,10 @@ import type { NormalizedVisit } from '../../../src/visits/types';
import { windowMock } from '../../__mocks__/Window.mock';
describe('ReportExporter', () => {
const jsonToCsv = jest.fn();
const jsonToCsv = vi.fn();
let exporter: ReportExporter;
beforeEach(jest.clearAllMocks);
beforeEach(vi.clearAllMocks);
beforeEach(() => {
(global as any).Blob = class Blob {};
(global as any).URL = { createObjectURL: () => '' };

View file

@ -22,8 +22,8 @@ describe('<DomainRow />', () => {
domain={domain}
defaultRedirects={defaultRedirects}
selectedServer={fromPartial({})}
editDomainRedirects={jest.fn()}
checkDomainHealth={jest.fn()}
editDomainRedirects={vi.fn()}
checkDomainHealth={vi.fn()}
/>
</tbody>
</table>,

View file

@ -13,10 +13,10 @@ describe('<DomainSelector />', () => {
],
});
const setUp = (value = '') => renderWithEvents(
<DomainSelector value={value} domainsList={domainsList} listDomains={jest.fn()} onChange={jest.fn()} />,
<DomainSelector value={value} domainsList={domainsList} listDomains={vi.fn()} onChange={vi.fn()} />,
);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it.each([
['', 'Domain', 'domains-dropdown__toggle-btn'],

View file

@ -7,20 +7,20 @@ import type { DomainsList } from '../../src/domains/reducers/domainsList';
import { renderWithEvents } from '../__helpers__/setUpTest';
describe('<ManageDomains />', () => {
const listDomains = jest.fn();
const filterDomains = jest.fn();
const listDomains = vi.fn();
const filterDomains = vi.fn();
const setUp = (domainsList: DomainsList) => renderWithEvents(
<ManageDomains
listDomains={listDomains}
filterDomains={filterDomains}
editDomainRedirects={jest.fn()}
checkDomainHealth={jest.fn()}
editDomainRedirects={vi.fn()}
checkDomainHealth={vi.fn()}
domainsList={domainsList}
selectedServer={fromPartial({})}
/>,
);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('shows loading message while domains are loading', () => {
setUp(fromPartial({ loading: true, filteredDomains: [] }));

View file

@ -8,7 +8,7 @@ import type { SemVer } from '../../../src/utils/helpers/version';
import { renderWithEvents } from '../../__helpers__/setUpTest';
describe('<DomainDropdown />', () => {
const editDomainRedirects = jest.fn().mockResolvedValue(undefined);
const editDomainRedirects = vi.fn().mockResolvedValue(undefined);
const setUp = (domain?: Domain, selectedServer?: SelectedServer) => renderWithEvents(
<MemoryRouter>
<DomainDropdown
@ -19,7 +19,7 @@ describe('<DomainDropdown />', () => {
</MemoryRouter>,
);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('renders expected menu items', () => {
setUp();

View file

@ -5,12 +5,12 @@ import { DomainStatusIcon } from '../../../src/domains/helpers/DomainStatusIcon'
import { renderWithEvents } from '../../__helpers__/setUpTest';
describe('<DomainStatusIcon />', () => {
const matchMedia = jest.fn().mockReturnValue(fromPartial<MediaQueryList>({ matches: false }));
const matchMedia = vi.fn().mockReturnValue(fromPartial<MediaQueryList>({ matches: false }));
const setUp = (status: DomainStatus) => renderWithEvents(
<DomainStatusIcon status={status} matchMedia={matchMedia} />,
);
beforeEach(jest.clearAllMocks);
beforeEach(vi.clearAllMocks);
it.each([
['validating' as DomainStatus],

View file

@ -5,8 +5,8 @@ import { EditDomainRedirectsModal } from '../../../src/domains/helpers/EditDomai
import { renderWithEvents } from '../../__helpers__/setUpTest';
describe('<EditDomainRedirectsModal />', () => {
const editDomainRedirects = jest.fn().mockResolvedValue(undefined);
const toggle = jest.fn();
const editDomainRedirects = vi.fn().mockResolvedValue(undefined);
const toggle = vi.fn();
const domain = fromPartial<ShlinkDomain>({
domain: 'foo.com',
redirects: {
@ -17,7 +17,7 @@ describe('<EditDomainRedirectsModal />', () => {
<EditDomainRedirectsModal domain={domain} isOpen toggle={toggle} editDomainRedirects={editDomainRedirects} />,
);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('renders domain in header', () => {
setUp();

View file

@ -1,4 +1,92 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`<DomainStatusIcon /> > renders expected icon and tooltip when status is not validating 1`] = `
<svg
aria-hidden="true"
class="svg-inline--fa fa-circle-notch fa-spin fa-fw "
data-icon="circle-notch"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M222.7 32.1c5 16.9-4.6 34.8-21.5 39.8C121.8 95.6 64 169.1 64 256c0 106 86 192 192 192s192-86 192-192c0-86.9-57.8-160.4-137.1-184.1c-16.9-5-26.6-22.9-21.5-39.8s22.9-26.6 39.8-21.5C434.9 42.1 512 140 512 256c0 141.4-114.6 256-256 256S0 397.4 0 256C0 140 77.1 42.1 182.9 10.6c16.9-5 34.8 4.6 39.8 21.5z"
fill="currentColor"
/>
</svg>
`;
exports[`<DomainStatusIcon /> > renders expected icon and tooltip when status is not validating 2`] = `
<span>
<svg
aria-hidden="true"
class="svg-inline--fa fa-xmark fa-fw text-danger"
data-icon="xmark"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 320 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M310.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L160 210.7 54.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L114.7 256 9.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 301.3 265.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L205.3 256 310.6 150.6z"
fill="currentColor"
/>
</svg>
</span>
`;
exports[`<DomainStatusIcon /> > renders expected icon and tooltip when status is not validating 3`] = `
<span>
<svg
aria-hidden="true"
class="svg-inline--fa fa-check fa-fw text-muted"
data-icon="check"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M470.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L192 338.7 425.4 105.4c12.5-12.5 32.8-12.5 45.3 0z"
fill="currentColor"
/>
</svg>
</span>
`;
exports[`<DomainStatusIcon /> > renders proper tooltip based on state 1`] = `
<div
class="tooltip-inner"
role="tooltip"
>
<span>
Oops! There is some missing configuration, and short URLs shared with this domain will not work.
<br />
Check the
<a
href="https://slnk.to/multi-domain-docs"
rel="noopener noreferrer"
target="_blank"
>
documentation
</a>
in order to find out what is missing.
</span>
</div>
`;
exports[`<DomainStatusIcon /> > renders proper tooltip based on state 2`] = `
<div
class="tooltip-inner"
role="tooltip"
>
Congratulations! This domain is properly configured.
</div>
`;
exports[`<DomainStatusIcon /> renders expected icon and tooltip when status is not validating 1`] = `
<svg

View file

@ -4,14 +4,14 @@ import type { ShlinkDomainRedirects } from '../../../src/api/types';
import { editDomainRedirects } from '../../../src/domains/reducers/domainRedirects';
describe('domainRedirectsReducer', () => {
beforeEach(jest.clearAllMocks);
beforeEach(vi.clearAllMocks);
describe('editDomainRedirects', () => {
const domain = 'example.com';
const redirects = fromPartial<ShlinkDomainRedirects>({});
const dispatch = jest.fn();
const getState = jest.fn();
const editDomainRedirectsCall = jest.fn();
const dispatch = vi.fn();
const getState = vi.fn();
const editDomainRedirectsCall = vi.fn();
const buildShlinkApiClient = () => fromPartial<ShlinkApiClient>({ editDomainRedirects: editDomainRedirectsCall });
const editDomainRedirectsAction = editDomainRedirects(buildShlinkApiClient);

View file

@ -13,10 +13,10 @@ import {
} from '../../../src/domains/reducers/domainsList';
describe('domainsListReducer', () => {
const dispatch = jest.fn();
const getState = jest.fn();
const listDomains = jest.fn();
const health = jest.fn();
const dispatch = vi.fn();
const getState = vi.fn();
const listDomains = vi.fn();
const health = vi.fn();
const buildShlinkApiClient = () => fromPartial<ShlinkApiClient>({ listDomains, health });
const filteredDomains: Domain[] = [
fromPartial({ domain: 'foo', status: 'validating' }),
@ -30,7 +30,7 @@ describe('domainsListReducer', () => {
editDomainRedirectsThunk,
);
beforeEach(jest.clearAllMocks);
beforeEach(vi.clearAllMocks);
describe('reducer', () => {
it('returns loading on LIST_DOMAINS_START', () => {

View file

@ -4,14 +4,14 @@ import { identity } from 'ramda';
import { bindToMercureTopic } from '../../../src/mercure/helpers';
import type { MercureInfo } from '../../../src/mercure/reducers/mercureInfo';
jest.mock('event-source-polyfill');
vi.mock('event-source-polyfill');
describe('helpers', () => {
afterEach(jest.resetAllMocks);
afterEach(vi.resetAllMocks);
describe('bindToMercureTopic', () => {
const onMessage = jest.fn();
const onTokenExpired = jest.fn();
const onMessage = vi.fn();
const onTokenExpired = vi.fn();
it.each([
[fromPartial<MercureInfo>({ loading: true, error: false, mercureHubUrl: 'foo' })],

View file

@ -8,11 +8,11 @@ describe('mercureInfoReducer', () => {
mercureHubUrl: 'http://example.com/.well-known/mercure',
token: 'abc.123.def',
};
const getMercureInfo = jest.fn();
const getMercureInfo = vi.fn();
const buildShlinkApiClient = () => fromPartial<ShlinkApiClient>({ mercureInfo: getMercureInfo });
const { loadMercureInfo, reducer } = mercureInfoReducerCreator(buildShlinkApiClient);
beforeEach(jest.resetAllMocks);
beforeEach(vi.resetAllMocks);
describe('reducer', () => {
it('returns loading on GET_MERCURE_INFO_START', () => {
@ -37,8 +37,8 @@ describe('mercureInfoReducer', () => {
});
describe('loadMercureInfo', () => {
const dispatch = jest.fn();
const createGetStateMock = (enabled: boolean): GetState => jest.fn().mockReturnValue({
const dispatch = vi.fn();
const createGetStateMock = (enabled: boolean): GetState => vi.fn().mockReturnValue({
settings: {
realTimeUpdates: { enabled },
},

View file

@ -5,17 +5,20 @@ import { CreateServer as createCreateServer } from '../../src/servers/CreateServ
import type { ServerWithId } from '../../src/servers/data';
import { renderWithEvents } from '../__helpers__/setUpTest';
jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useNavigate: jest.fn() }));
vi.mock('react-router-dom', async () => ({
...(await vi.importActual<any>('react-router-dom')),
useNavigate: vi.fn(),
}));
describe('<CreateServer />', () => {
const createServersMock = jest.fn();
const navigate = jest.fn();
const createServersMock = vi.fn();
const navigate = vi.fn();
const servers = { foo: fromPartial<ServerWithId>({ url: 'https://existing_url.com', apiKey: 'existing_api_key' }) };
const setUp = (serversImported = false, importFailed = false) => {
(useNavigate as any).mockReturnValue(navigate);
let callCount = 0;
const useTimeoutToggle = jest.fn().mockImplementation(() => {
const useTimeoutToggle = vi.fn().mockImplementation(() => {
const result = [callCount % 2 === 0 ? serversImported : importFailed, () => null];
callCount += 1;
return result;
@ -25,7 +28,7 @@ describe('<CreateServer />', () => {
return renderWithEvents(<CreateServer createServers={createServersMock} servers={servers} />);
};
beforeEach(jest.clearAllMocks);
beforeEach(vi.clearAllMocks);
it('shows success message when imported is true', () => {
setUp(true);

View file

@ -5,11 +5,14 @@ import { DeleteServerModal } from '../../src/servers/DeleteServerModal';
import { renderWithEvents } from '../__helpers__/setUpTest';
import { TestModalWrapper } from '../__helpers__/TestModalWrapper';
jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useNavigate: jest.fn() }));
vi.mock('react-router-dom', async () => ({
...(await vi.importActual<any>('react-router-dom')),
useNavigate: vi.fn(),
}));
describe('<DeleteServerModal />', () => {
const deleteServerMock = jest.fn();
const navigate = jest.fn();
const deleteServerMock = vi.fn();
const navigate = vi.fn();
const serverName = 'the_server_name';
const setUp = () => {
(useNavigate as any).mockReturnValue(navigate);
@ -27,7 +30,7 @@ describe('<DeleteServerModal />', () => {
);
};
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('renders a modal window', () => {
setUp();

View file

@ -5,12 +5,15 @@ import type { ReachableServer, SelectedServer } from '../../src/servers/data';
import { EditServer as editServerConstruct } from '../../src/servers/EditServer';
import { renderWithEvents } from '../__helpers__/setUpTest';
jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useNavigate: jest.fn() }));
vi.mock('react-router-dom', async () => ({
...(await vi.importActual<any>('react-router-dom')),
useNavigate: vi.fn(),
}));
describe('<EditServer />', () => {
const ServerError = jest.fn();
const editServerMock = jest.fn();
const navigate = jest.fn();
const ServerError = vi.fn();
const editServerMock = vi.fn();
const navigate = vi.fn();
const defaultSelectedServer = fromPartial<ReachableServer>({
id: 'abc123',
name: 'the_name',
@ -20,7 +23,7 @@ describe('<EditServer />', () => {
const EditServer = editServerConstruct(ServerError);
const setUp = (selectedServer: SelectedServer = defaultSelectedServer) => renderWithEvents(
<MemoryRouter>
<EditServer editServer={editServerMock} selectedServer={selectedServer} selectServer={jest.fn()} />
<EditServer editServer={editServerMock} selectedServer={selectedServer} selectServer={vi.fn()} />
</MemoryRouter>,
);
@ -28,7 +31,7 @@ describe('<EditServer />', () => {
(useNavigate as any).mockReturnValue(navigate);
});
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('renders nothing if selected server is not reachable', () => {
setUp(fromPartial<SelectedServer>({}));

View file

@ -7,9 +7,9 @@ import type { ServersExporter } from '../../src/servers/services/ServersExporter
import { renderWithEvents } from '../__helpers__/setUpTest';
describe('<ManageServers />', () => {
const exportServers = jest.fn();
const exportServers = vi.fn();
const serversExporter = fromPartial<ServersExporter>({ exportServers });
const useTimeoutToggle = jest.fn().mockReturnValue([false, jest.fn()]);
const useTimeoutToggle = vi.fn().mockReturnValue([false, vi.fn()]);
const ManageServers = createManageServers(
serversExporter,
() => <span>ImportServersBtn</span>,
@ -23,7 +23,7 @@ describe('<ManageServers />', () => {
<MemoryRouter><ManageServers servers={servers} /></MemoryRouter>,
);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('shows search field which allows searching servers, affecting te amount of rendered rows', async () => {
const { user } = setUp({
@ -85,7 +85,7 @@ describe('<ManageServers />', () => {
});
it.each([[true], [false]])('shows an error message if an error occurs while importing servers', (hasError) => {
useTimeoutToggle.mockReturnValue([hasError, jest.fn()]);
useTimeoutToggle.mockReturnValue([hasError, vi.fn()]);
setUp({ foo: createServerMock('foo') });

View file

@ -9,7 +9,7 @@ describe('<ManageServersRowDropdown />', () => {
const ManageServersRowDropdown = createManageServersRowDropdown(
({ isOpen }) => <span>DeleteServerModal {isOpen ? '[OPEN]' : '[CLOSED]'}</span>,
);
const setAutoConnect = jest.fn();
const setAutoConnect = vi.fn();
const setUp = (autoConnect = false) => {
const server = fromPartial<ServerWithId>({ id: 'abc123', autoConnect });
return renderWithEvents(
@ -19,7 +19,7 @@ describe('<ManageServersRowDropdown />', () => {
);
};
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('renders expected amount of dropdown items', async () => {
const { user } = setUp();

View file

@ -9,9 +9,9 @@ import { renderWithEvents } from '../__helpers__/setUpTest';
describe('<Overview />', () => {
const ShortUrlsTable = () => <>ShortUrlsTable</>;
const CreateShortUrl = () => <>CreateShortUrl</>;
const listShortUrls = jest.fn();
const listTags = jest.fn();
const loadVisitsOverview = jest.fn();
const listShortUrls = vi.fn();
const listTags = vi.fn();
const loadVisitsOverview = vi.fn();
const Overview = overviewCreator(ShortUrlsTable, CreateShortUrl);
const shortUrls = {
pagination: { totalItems: 83710 },
@ -31,8 +31,8 @@ describe('<Overview />', () => {
orphanVisits: { total: 28, bots: 15, nonBots: 13 },
})}
selectedServer={fromPartial({ id: serverId })}
createNewVisits={jest.fn()}
loadMercureInfo={jest.fn()}
createNewVisits={vi.fn()}
loadMercureInfo={vi.fn()}
mercureInfo={fromPartial<MercureInfo>({})}
settings={fromPartial({ visits: { excludeBots } })}
/>

View file

@ -1,4 +1,59 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`<DeleteServerButton /> > renders expected content 1`] = `
<span>
<span
class="button"
>
Foo bar
</span>
</span>
`;
exports[`<DeleteServerButton /> > renders expected content 2`] = `
<span>
<span
class="button"
>
baz
</span>
</span>
`;
exports[`<DeleteServerButton /> > renders expected content 3`] = `
<span>
<span
class="button"
>
something
</span>
</span>
`;
exports[`<DeleteServerButton /> > renders expected content 4`] = `
<span>
<svg
aria-hidden="true"
class="svg-inline--fa fa-circle-minus fa-fw "
data-icon="circle-minus"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M256 512c141.4 0 256-114.6 256-256S397.4 0 256 0S0 114.6 0 256S114.6 512 256 512zM184 232H328c13.3 0 24 10.7 24 24s-10.7 24-24 24H184c-13.3 0-24-10.7-24-24s10.7-24 24-24z"
fill="currentColor"
/>
</svg>
<span
class="button"
>
Remove this server
</span>
</span>
`;
exports[`<DeleteServerButton /> renders expected content 1`] = `
<span>

View file

@ -1,4 +1,101 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`<ManageServersRow /> > renders auto-connect icon only if server is autoConnect 1`] = `
<div>
<table>
<tbody>
<tr
class="responsive-table__row"
>
<td
class="responsive-table__cell"
data-th="Auto-connect"
>
<svg
aria-hidden="true"
class="svg-inline--fa fa-check text-primary"
data-icon="check"
data-prefix="fas"
focusable="false"
id="autoConnectIcon"
role="img"
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M470.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L192 338.7 425.4 105.4c12.5-12.5 32.8-12.5 45.3 0z"
fill="currentColor"
/>
</svg>
</td>
<th
class="responsive-table__cell"
data-th="Name"
>
<a
href="/server/abc"
>
My server
</a>
</th>
<td
class="responsive-table__cell"
data-th="Base URL"
>
https://example.com
</td>
<td
class="responsive-table__cell text-end"
>
<span>
ManageServersRowDropdown
</span>
</td>
</tr>
</tbody>
</table>
</div>
`;
exports[`<ManageServersRow /> > renders auto-connect icon only if server is autoConnect 2`] = `
<div>
<table>
<tbody>
<tr
class="responsive-table__row"
>
<td
class="responsive-table__cell"
data-th="Auto-connect"
/>
<th
class="responsive-table__cell"
data-th="Name"
>
<a
href="/server/abc"
>
My server
</a>
</th>
<td
class="responsive-table__cell"
data-th="Base URL"
>
https://example.com
</td>
<td
class="responsive-table__cell text-end"
>
<span>
ManageServersRowDropdown
</span>
</td>
</tr>
</tbody>
</table>
</div>
`;
exports[`<ManageServersRow /> renders auto-connect icon only if server is autoConnect 1`] = `
<div>

View file

@ -5,14 +5,14 @@ import { DuplicatedServersModal } from '../../../src/servers/helpers/DuplicatedS
import { renderWithEvents } from '../../__helpers__/setUpTest';
describe('<DuplicatedServersModal />', () => {
const onDiscard = jest.fn();
const onSave = jest.fn();
const onDiscard = vi.fn();
const onSave = vi.fn();
const setUp = (duplicatedServers: ServerData[] = []) => renderWithEvents(
<DuplicatedServersModal isOpen duplicatedServers={duplicatedServers} onDiscard={onDiscard} onSave={onSave} />,
);
const mockServer = (data: Partial<ServerData> = {}) => fromPartial<ServerData>(data);
beforeEach(jest.clearAllMocks);
beforeEach(vi.clearAllMocks);
it.each([
[[], 0],

View file

@ -10,9 +10,9 @@ import type { ServersImporter } from '../../../src/servers/services/ServersImpor
import { renderWithEvents } from '../../__helpers__/setUpTest';
describe('<ImportServersBtn />', () => {
const onImportMock = jest.fn();
const createServersMock = jest.fn();
const importServersFromFile = jest.fn().mockResolvedValue([]);
const onImportMock = vi.fn();
const createServersMock = vi.fn();
const importServersFromFile = vi.fn().mockResolvedValue([]);
const serversImporterMock = fromPartial<ServersImporter>({ importServersFromFile });
const ImportServersBtn = createImportServersBtn(serversImporterMock);
const setUp = (props: Partial<ImportServersBtnProps> = {}, servers: ServersMap = {}) => renderWithEvents(
@ -24,7 +24,7 @@ describe('<ImportServersBtn />', () => {
/>,
);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('shows tooltip on button hover', async () => {
const { user } = setUp();

View file

@ -2,10 +2,10 @@ import { fireEvent, render, screen } from '@testing-library/react';
import { ServerForm } from '../../../src/servers/helpers/ServerForm';
describe('<ServerForm />', () => {
const onSubmit = jest.fn();
const onSubmit = vi.fn();
const setUp = () => render(<ServerForm onSubmit={onSubmit}>Something</ServerForm>);
afterEach(jest.resetAllMocks);
afterEach(vi.resetAllMocks);
it('renders components', () => {
setUp();
@ -18,7 +18,7 @@ describe('<ServerForm />', () => {
setUp();
expect(onSubmit).not.toHaveBeenCalled();
fireEvent.submit(screen.getByRole('form'), { preventDefault: jest.fn() });
fireEvent.submit(screen.getByRole('form'), { preventDefault: vi.fn() });
expect(onSubmit).toHaveBeenCalled();
});
});

View file

@ -3,11 +3,11 @@ import type { HttpClient } from '../../../src/common/services/HttpClient';
import { fetchServers } from '../../../src/servers/reducers/remoteServers';
describe('remoteServersReducer', () => {
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
describe('fetchServers', () => {
const dispatch = jest.fn();
const fetchJson = jest.fn();
const dispatch = vi.fn();
const fetchJson = vi.fn();
const httpClient = fromPartial<HttpClient>({ fetchJson });
it.each([
@ -81,7 +81,7 @@ describe('remoteServersReducer', () => {
fetchJson.mockResolvedValue(mockedValue);
const doFetchServers = fetchServers(httpClient);
await doFetchServers()(dispatch, jest.fn(), {});
await doFetchServers()(dispatch, vi.fn(), {});
expect(dispatch).toHaveBeenCalledTimes(3);
expect(dispatch).toHaveBeenNthCalledWith(2, expect.objectContaining({ payload: expectedNewServers }));

View file

@ -13,13 +13,13 @@ import {
} from '../../../src/servers/reducers/selectedServer';
describe('selectedServerReducer', () => {
const dispatch = jest.fn();
const health = jest.fn();
const buildApiClient = jest.fn().mockReturnValue(fromPartial<ShlinkApiClient>({ health }));
const dispatch = vi.fn();
const health = vi.fn();
const buildApiClient = vi.fn().mockReturnValue(fromPartial<ShlinkApiClient>({ health }));
const selectServer = selectServerCreator(buildApiClient);
const { reducer } = selectedServerReducerCreator(selectServer);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
describe('reducer', () => {
it('returns default when action is RESET_SELECTED_SERVER', () =>
@ -33,7 +33,7 @@ describe('selectedServerReducer', () => {
describe('selectServer', () => {
const version = '1.19.0';
const createGetStateMock = (id: string) => jest.fn().mockReturnValue({
const createGetStateMock = (id: string) => vi.fn().mockReturnValue({
servers: {
[id]: { id },
},
@ -77,7 +77,7 @@ describe('selectedServerReducer', () => {
it('dispatches error when server is not found', async () => {
const id = uuid();
const getState = jest.fn(() => fromPartial<ShlinkState>({ servers: {} }));
const getState = vi.fn(() => fromPartial<ShlinkState>({ servers: {} }));
const expectedSelectedServer: NotFoundServer = { serverNotFound: true };
await selectServer(id)(dispatch, getState, {});
@ -89,8 +89,8 @@ describe('selectedServerReducer', () => {
});
describe('selectServerListener', () => {
const getState = jest.fn(() => ({}));
const loadMercureInfo = jest.fn();
const getState = vi.fn(() => ({}));
const loadMercureInfo = vi.fn();
const { middleware } = selectServerListener(selectServer, loadMercureInfo);
it.each([
@ -98,7 +98,7 @@ describe('selectedServerReducer', () => {
[fromPartial<NotFoundServer>({ serverNotFound: true }), 0],
[fromPartial<NonReachableServer>({ serverNotReachable: true }), 0],
])('dispatches loadMercureInfo when provided server is reachable', (payload, expectedCalls) => {
middleware({ dispatch, getState })(jest.fn())({
middleware({ dispatch, getState })(vi.fn())({
payload,
type: selectServer.fulfilled.toString(),
});
@ -108,7 +108,7 @@ describe('selectedServerReducer', () => {
});
it('does not dispatch loadMercureInfo when action is not of the proper type', () => {
middleware({ dispatch, getState })(jest.fn())({
middleware({ dispatch, getState })(vi.fn())({
payload: fromPartial<ReachableServer>({ version: '1.2.3' }),
type: 'something_else',
});

View file

@ -15,7 +15,7 @@ describe('serversReducer', () => {
def456: fromPartial({ id: 'def456' }),
};
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
describe('reducer', () => {
it('returns edited server when action is EDIT_SERVER', () =>

View file

@ -5,7 +5,7 @@ import { appendChild, removeChild, windowMock } from '../../__mocks__/Window.moc
describe('ServersExporter', () => {
const storageMock = fromPartial<LocalStorage>({
get: jest.fn(() => ({
get: vi.fn(() => ({
abc123: {
id: 'abc123',
name: 'foo',
@ -18,16 +18,16 @@ describe('ServersExporter', () => {
},
} as any)),
});
const erroneousToCsv = jest.fn(() => {
const erroneousToCsv = vi.fn(() => {
throw new Error('');
});
const createCsvjsonMock = (throwError = false) => (throwError ? erroneousToCsv : jest.fn(() => ''));
const createCsvjsonMock = (throwError = false) => (throwError ? erroneousToCsv : vi.fn(() => ''));
beforeEach(jest.clearAllMocks);
beforeEach(vi.clearAllMocks);
describe('exportServers', () => {
let originalConsole: Console;
const error = jest.fn();
const error = vi.fn();
beforeEach(() => {
originalConsole = global.console;

View file

@ -4,8 +4,8 @@ import { ServersImporter } from '../../../src/servers/services/ServersImporter';
describe('ServersImporter', () => {
const servers: RegularServer[] = [fromPartial<RegularServer>({}), fromPartial<RegularServer>({})];
const csvjsonMock = jest.fn().mockResolvedValue(servers);
const readAsText = jest.fn();
const csvjsonMock = vi.fn().mockResolvedValue(servers);
const readAsText = vi.fn();
const fileReaderMock = fromPartial<FileReader>({
readAsText,
addEventListener: ((_eventName: string, listener: (e: ProgressEvent<FileReader>) => void) => listener(
@ -14,7 +14,7 @@ describe('ServersImporter', () => {
});
const importer = new ServersImporter(csvjsonMock, () => fileReaderMock);
beforeEach(jest.clearAllMocks);
beforeEach(vi.clearAllMocks);
describe('importServersFromFile', () => {
it('rejects with error if no file was provided', async () => {

View file

@ -7,8 +7,8 @@ import type {
import { renderWithEvents } from '../__helpers__/setUpTest';
describe('<RealTimeUpdatesSettings />', () => {
const toggleRealTimeUpdates = jest.fn();
const setRealTimeUpdatesInterval = jest.fn();
const toggleRealTimeUpdates = vi.fn();
const setRealTimeUpdatesInterval = vi.fn();
const setUp = (realTimeUpdates: Partial<RealTimeUpdatesSettingsOptions> = {}) => renderWithEvents(
<RealTimeUpdatesSettings
settings={fromPartial({ realTimeUpdates })}
@ -17,7 +17,7 @@ describe('<RealTimeUpdatesSettings />', () => {
/>,
);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('renders enabled real time updates as expected', () => {
setUp({ enabled: true });

View file

@ -5,7 +5,7 @@ import { ShortUrlCreationSettings } from '../../src/settings/ShortUrlCreationSet
import { renderWithEvents } from '../__helpers__/setUpTest';
describe('<ShortUrlCreationSettings />', () => {
const setShortUrlCreationSettings = jest.fn();
const setShortUrlCreationSettings = vi.fn();
const setUp = (shortUrlCreation?: ShortUrlsSettings) => renderWithEvents(
<ShortUrlCreationSettings
settings={fromPartial({ shortUrlCreation })}
@ -13,7 +13,7 @@ describe('<ShortUrlCreationSettings />', () => {
/>,
);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it.each([
[{ validateUrls: true }, true],

View file

@ -6,12 +6,12 @@ import type { ShortUrlsOrder } from '../../src/short-urls/data';
import { renderWithEvents } from '../__helpers__/setUpTest';
describe('<ShortUrlsListSettings />', () => {
const setSettings = jest.fn();
const setSettings = vi.fn();
const setUp = (shortUrlsList?: ShortUrlsSettings) => renderWithEvents(
<ShortUrlsListSettings settings={fromPartial({ shortUrlsList })} setShortUrlsListSettings={setSettings} />,
);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it.each([
[undefined, 'Order by: Created at - DESC'],

View file

@ -6,12 +6,12 @@ import type { TagsOrder } from '../../src/tags/data/TagsListChildrenProps';
import { renderWithEvents } from '../__helpers__/setUpTest';
describe('<TagsSettings />', () => {
const setTagsSettings = jest.fn();
const setTagsSettings = vi.fn();
const setUp = (tags?: TagsSettingsOptions) => renderWithEvents(
<TagsSettings settings={fromPartial({ tags })} setTagsSettings={setTagsSettings} />,
);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('renders expected amount of groups', () => {
setUp();

View file

@ -6,12 +6,12 @@ import type { Theme } from '../../src/utils/theme';
import { renderWithEvents } from '../__helpers__/setUpTest';
describe('<UserInterfaceSettings />', () => {
const setUiSettings = jest.fn();
const setUiSettings = vi.fn();
const setUp = (ui?: UiSettings) => renderWithEvents(
<UserInterfaceSettings settings={fromPartial({ ui })} setUiSettings={setUiSettings} />,
);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it.each([
[{ theme: 'dark' as Theme }, true],

View file

@ -5,12 +5,12 @@ import { VisitsSettings } from '../../src/settings/VisitsSettings';
import { renderWithEvents } from '../__helpers__/setUpTest';
describe('<VisitsSettings />', () => {
const setVisitsSettings = jest.fn();
const setVisitsSettings = vi.fn();
const setUp = (settings: Partial<Settings> = {}) => renderWithEvents(
<VisitsSettings settings={fromPartial(settings)} setVisitsSettings={setVisitsSettings} />,
);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('renders expected components', () => {
setUp();

View file

@ -1,4 +1,58 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`<UserInterfaceSettings /> > shows different icons based on theme 1`] = `
<svg
aria-hidden="true"
class="svg-inline--fa fa-moon user-interface__theme-icon"
data-icon="moon"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 384 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M223.5 32C100 32 0 132.3 0 256S100 480 223.5 480c60.6 0 115.5-24.2 155.8-63.4c5-4.9 6.3-12.5 3.1-18.7s-10.1-9.7-17-8.5c-9.8 1.7-19.8 2.6-30.1 2.6c-96.9 0-175.5-78.8-175.5-176c0-65.8 36-123.1 89.3-153.3c6.1-3.5 9.2-10.5 7.7-17.3s-7.3-11.9-14.3-12.5c-6.3-.5-12.6-.8-19-.8z"
fill="currentColor"
/>
</svg>
`;
exports[`<UserInterfaceSettings /> > shows different icons based on theme 2`] = `
<svg
aria-hidden="true"
class="svg-inline--fa fa-sun user-interface__theme-icon"
data-icon="sun"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M361.5 1.2c5 2.1 8.6 6.6 9.6 11.9L391 121l107.9 19.8c5.3 1 9.8 4.6 11.9 9.6s1.5 10.7-1.6 15.2L446.9 256l62.3 90.3c3.1 4.5 3.7 10.2 1.6 15.2s-6.6 8.6-11.9 9.6L391 391 371.1 498.9c-1 5.3-4.6 9.8-9.6 11.9s-10.7 1.5-15.2-1.6L256 446.9l-90.3 62.3c-4.5 3.1-10.2 3.7-15.2 1.6s-8.6-6.6-9.6-11.9L121 391 13.1 371.1c-5.3-1-9.8-4.6-11.9-9.6s-1.5-10.7 1.6-15.2L65.1 256 2.8 165.7c-3.1-4.5-3.7-10.2-1.6-15.2s6.6-8.6 11.9-9.6L121 121 140.9 13.1c1-5.3 4.6-9.8 9.6-11.9s10.7-1.5 15.2 1.6L256 65.1 346.3 2.8c4.5-3.1 10.2-3.7 15.2-1.6zM160 256a96 96 0 1 1 192 0 96 96 0 1 1 -192 0zm224 0a128 128 0 1 0 -256 0 128 128 0 1 0 256 0z"
fill="currentColor"
/>
</svg>
`;
exports[`<UserInterfaceSettings /> > shows different icons based on theme 3`] = `
<svg
aria-hidden="true"
class="svg-inline--fa fa-sun user-interface__theme-icon"
data-icon="sun"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M361.5 1.2c5 2.1 8.6 6.6 9.6 11.9L391 121l107.9 19.8c5.3 1 9.8 4.6 11.9 9.6s1.5 10.7-1.6 15.2L446.9 256l62.3 90.3c3.1 4.5 3.7 10.2 1.6 15.2s-6.6 8.6-11.9 9.6L391 391 371.1 498.9c-1 5.3-4.6 9.8-9.6 11.9s-10.7 1.5-15.2-1.6L256 446.9l-90.3 62.3c-4.5 3.1-10.2 3.7-15.2 1.6s-8.6-6.6-9.6-11.9L121 391 13.1 371.1c-5.3-1-9.8-4.6-11.9-9.6s-1.5-10.7 1.6-15.2L65.1 256 2.8 165.7c-3.1-4.5-3.7-10.2-1.6-15.2s6.6-8.6 11.9-9.6L121 121 140.9 13.1c1-5.3 4.6-9.8 9.6-11.9s10.7-1.5 15.2 1.6L256 65.1 346.3 2.8c4.5-3.1 10.2-3.7 15.2-1.6zM160 256a96 96 0 1 1 192 0 96 96 0 1 1 -192 0zm224 0a128 128 0 1 0 -256 0 128 128 0 1 0 256 0z"
fill="currentColor"
/>
</svg>
`;
exports[`<UserInterfaceSettings /> shows different icons based on theme 1`] = `
<svg

View file

@ -8,7 +8,7 @@ describe('<CreateShortUrl />', () => {
const CreateShortUrlResult = () => <span>CreateShortUrlResult</span>;
const shortUrlCreation = { validateUrls: true };
const shortUrlCreationResult = fromPartial<ShortUrlCreation>({});
const createShortUrl = jest.fn(async () => Promise.resolve());
const createShortUrl = vi.fn(async () => Promise.resolve());
const CreateShortUrl = createShortUrlsCreator(ShortUrlForm, CreateShortUrlResult);
const setUp = () => render(
<CreateShortUrl

View file

@ -15,8 +15,8 @@ describe('<EditShortUrl />', () => {
selectedServer={null}
shortUrlDetail={fromPartial(detail)}
shortUrlEdition={fromPartial(edition)}
getShortUrlDetail={jest.fn()}
editShortUrl={jest.fn(async () => Promise.resolve())}
getShortUrlDetail={vi.fn()}
editShortUrl={vi.fn(async () => Promise.resolve())}
/>
</MemoryRouter>,
);

View file

@ -10,7 +10,7 @@ import type { OptionalString } from '../../src/utils/utils';
import { renderWithEvents } from '../__helpers__/setUpTest';
describe('<ShortUrlForm />', () => {
const createShortUrl = jest.fn(async () => Promise.resolve());
const createShortUrl = vi.fn(async () => Promise.resolve());
const ShortUrlForm = createShortUrlForm(() => <span>TagsSelector</span>, () => <span>DomainSelector</span>);
const setUp = (selectedServer: SelectedServer = null, mode: Mode = 'create', title?: OptionalString) =>
renderWithEvents(
@ -23,7 +23,7 @@ describe('<ShortUrlForm />', () => {
/>,
);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it.each([
[

View file

@ -8,17 +8,17 @@ import { formatDate } from '../../src/utils/helpers/date';
import type { DateRange } from '../../src/utils/helpers/dateIntervals';
import { renderWithEvents } from '../__helpers__/setUpTest';
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useParams: jest.fn().mockReturnValue({ serverId: '1' }),
useNavigate: jest.fn(),
useLocation: jest.fn().mockReturnValue({}),
vi.mock('react-router-dom', async () => ({
...(await vi.importActual<any>('react-router-dom')),
useParams: vi.fn().mockReturnValue({ serverId: '1' }),
useNavigate: vi.fn(),
useLocation: vi.fn().mockReturnValue({}),
}));
describe('<ShortUrlsFilteringBar />', () => {
const ShortUrlsFilteringBar = filteringBarCreator(() => <>ExportShortUrlsBtn</>, () => <>TagsSelector</>);
const navigate = jest.fn();
const handleOrderBy = jest.fn();
const navigate = vi.fn();
const handleOrderBy = vi.fn();
const now = new Date();
const setUp = (search = '', selectedServer?: SelectedServer) => {
(useLocation as any).mockReturnValue({ search });
@ -36,7 +36,7 @@ describe('<ShortUrlsFilteringBar />', () => {
);
};
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('renders expected children components', () => {
setUp();

View file

@ -10,17 +10,17 @@ import type { ShortUrlsTableType } from '../../src/short-urls/ShortUrlsTable';
import type { SemVer } from '../../src/utils/helpers/version';
import { renderWithEvents } from '../__helpers__/setUpTest';
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useNavigate: jest.fn().mockReturnValue(jest.fn()),
useLocation: jest.fn().mockReturnValue({ search: '?tags=test%20tag&search=example.com' }),
vi.mock('react-router-dom', async () => ({
...(await vi.importActual<any>('react-router-dom')),
useNavigate: vi.fn().mockReturnValue(vi.fn()),
useLocation: vi.fn().mockReturnValue({ search: '?tags=test%20tag&search=example.com' }),
}));
describe('<ShortUrlsList />', () => {
const ShortUrlsTable: ShortUrlsTableType = ({ onTagClick }) => <span onClick={() => onTagClick?.('foo')}>ShortUrlsTable</span>;
const ShortUrlsFilteringBar = () => <span>ShortUrlsFilteringBar</span>;
const listShortUrlsMock = jest.fn();
const navigate = jest.fn();
const listShortUrlsMock = vi.fn();
const navigate = vi.fn();
const shortUrlsList = fromPartial<ShortUrlsListModel>({
shortUrls: {
data: [
@ -51,7 +51,7 @@ describe('<ShortUrlsList />', () => {
(useNavigate as any).mockReturnValue(navigate);
});
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('wraps expected components', () => {
setUp();

View file

@ -9,13 +9,13 @@ import { renderWithEvents } from '../__helpers__/setUpTest';
describe('<ShortUrlsTable />', () => {
const shortUrlsList = fromPartial<ShortUrlsList>({});
const orderByColumn = jest.fn();
const orderByColumn = vi.fn();
const ShortUrlsTable = shortUrlsTableCreator(() => <span>ShortUrlsRow</span>);
const setUp = (server: SelectedServer = null) => renderWithEvents(
<ShortUrlsTable shortUrlsList={shortUrlsList} selectedServer={server} orderByColumn={() => orderByColumn} />,
);
afterEach(jest.resetAllMocks);
afterEach(vi.resetAllMocks);
it('should render inner table by default', () => {
setUp();

View file

@ -6,14 +6,14 @@ import type { TimeoutToggle } from '../../../src/utils/helpers/hooks';
import { renderWithEvents } from '../../__helpers__/setUpTest';
describe('<CreateShortUrlResult />', () => {
const copyToClipboard = jest.fn();
const useTimeoutToggle = jest.fn(() => [false, copyToClipboard]) as TimeoutToggle;
const copyToClipboard = vi.fn();
const useTimeoutToggle = vi.fn(() => [false, copyToClipboard]) as TimeoutToggle;
const CreateShortUrlResult = createResult(useTimeoutToggle);
const setUp = (creation: ShortUrlCreation) => renderWithEvents(
<CreateShortUrlResult resetCreateShortUrl={() => {}} creation={creation} />,
);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('renders an error when error is true', () => {
setUp({ error: true, saved: false, saving: false });

View file

@ -14,8 +14,8 @@ describe('<DeleteShortUrlModal />', () => {
shortCode: 'abc123',
longUrl: 'https://long-domain.com/foo/bar',
});
const deleteShortUrl = jest.fn().mockResolvedValue(undefined);
const shortUrlDeleted = jest.fn();
const deleteShortUrl = vi.fn().mockResolvedValue(undefined);
const shortUrlDeleted = vi.fn();
const setUp = (shortUrlDeletion: Partial<ShortUrlDeletion>) => renderWithEvents(
<TestModalWrapper
renderModal={(args) => (
@ -25,13 +25,13 @@ describe('<DeleteShortUrlModal />', () => {
shortUrlDeletion={fromPartial(shortUrlDeletion)}
deleteShortUrl={deleteShortUrl}
shortUrlDeleted={shortUrlDeleted}
resetDeleteShortUrl={jest.fn()}
resetDeleteShortUrl={vi.fn()}
/>
)}
/>,
);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('shows generic error when non-threshold error occurs', () => {
setUp({

View file

@ -8,9 +8,9 @@ import { ExportShortUrlsBtn as createExportShortUrlsBtn } from '../../../src/sho
import { renderWithEvents } from '../../__helpers__/setUpTest';
describe('<ExportShortUrlsBtn />', () => {
const listShortUrls = jest.fn();
const buildShlinkApiClient = jest.fn().mockReturnValue({ listShortUrls });
const exportShortUrls = jest.fn();
const listShortUrls = vi.fn();
const buildShlinkApiClient = vi.fn().mockReturnValue({ listShortUrls });
const exportShortUrls = vi.fn();
const reportExporter = fromPartial<ReportExporter>({ exportShortUrls });
const ExportShortUrlsBtn = createExportShortUrlsBtn(buildShlinkApiClient, reportExporter);
const setUp = (amount?: number, selectedServer?: SelectedServer) => renderWithEvents(
@ -19,7 +19,7 @@ describe('<ExportShortUrlsBtn />', () => {
</MemoryRouter>,
);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it.each([
[undefined, '0'],

View file

@ -5,7 +5,7 @@ import type { SemVer } from '../../../src/utils/helpers/version';
import { renderWithEvents } from '../../__helpers__/setUpTest';
describe('<QrCodeModal />', () => {
const saveImage = jest.fn().mockReturnValue(Promise.resolve());
const saveImage = vi.fn().mockReturnValue(Promise.resolve());
const QrCodeModal = createQrCodeModal(fromPartial({ saveImage }));
const shortUrl = 'https://s.test/abc123';
const setUp = (version: SemVer = '2.8.0') => renderWithEvents(
@ -17,7 +17,7 @@ describe('<QrCodeModal />', () => {
/>,
);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('shows an external link to the URL in the header', () => {
setUp();

View file

@ -4,7 +4,7 @@ import { renderWithEvents } from '../../__helpers__/setUpTest';
describe('<ShortUrlsFilterDropdown />', () => {
const setUp = (supportsDisabledFiltering: boolean) => renderWithEvents(
<ShortUrlsFilterDropdown onChange={jest.fn()} supportsDisabledFiltering={supportsDisabledFiltering} />,
<ShortUrlsFilterDropdown onChange={vi.fn()} supportsDisabledFiltering={supportsDisabledFiltering} />,
);
it.each([

View file

@ -20,14 +20,14 @@ interface SetUpOptions {
settings?: Partial<Settings>;
}
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useLocation: jest.fn().mockReturnValue({}),
vi.mock('react-router-dom', async () => ({
...(await vi.importActual<any>('react-router-dom')),
useLocation: vi.fn().mockReturnValue({}),
}));
describe('<ShortUrlsRow />', () => {
const timeoutToggle = jest.fn(() => true);
const useTimeoutToggle = jest.fn(() => [false, timeoutToggle]) as TimeoutToggle;
const timeoutToggle = vi.fn(() => true);
const useTimeoutToggle = vi.fn(() => [false, timeoutToggle]) as TimeoutToggle;
const server = fromPartial<ReachableServer>({ url: 'https://s.test' });
const shortUrl: ShortUrl = {
shortCode: 'abc123',

View file

@ -1,4 +1,148 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`<ShortUrlsRow /> > displays expected status icon 1`] = `
<svg
aria-hidden="true"
class="svg-inline--fa fa-calendar-xmark text-danger"
data-icon="calendar-xmark"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 448 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M128 0c17.7 0 32 14.3 32 32V64H288V32c0-17.7 14.3-32 32-32s32 14.3 32 32V64h48c26.5 0 48 21.5 48 48v48H0V112C0 85.5 21.5 64 48 64H96V32c0-17.7 14.3-32 32-32zM0 192H448V464c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V192zM305 305c9.4-9.4 9.4-24.6 0-33.9s-24.6-9.4-33.9 0l-47 47-47-47c-9.4-9.4-24.6-9.4-33.9 0s-9.4 24.6 0 33.9l47 47-47 47c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l47-47 47 47c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9l-47-47 47-47z"
fill="currentColor"
/>
</svg>
`;
exports[`<ShortUrlsRow /> > displays expected status icon 2`] = `
<svg
aria-hidden="true"
class="svg-inline--fa fa-calendar-xmark text-warning"
data-icon="calendar-xmark"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 448 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M128 0c17.7 0 32 14.3 32 32V64H288V32c0-17.7 14.3-32 32-32s32 14.3 32 32V64h48c26.5 0 48 21.5 48 48v48H0V112C0 85.5 21.5 64 48 64H96V32c0-17.7 14.3-32 32-32zM0 192H448V464c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V192zM305 305c9.4-9.4 9.4-24.6 0-33.9s-24.6-9.4-33.9 0l-47 47-47-47c-9.4-9.4-24.6-9.4-33.9 0s-9.4 24.6 0 33.9l47 47-47 47c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l47-47 47 47c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9l-47-47 47-47z"
fill="currentColor"
/>
</svg>
`;
exports[`<ShortUrlsRow /> > displays expected status icon 3`] = `
<svg
aria-hidden="true"
class="svg-inline--fa fa-link-slash text-danger"
data-icon="link-slash"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 640 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L489.3 358.2l90.5-90.5c56.5-56.5 56.5-148 0-204.5c-50-50-128.8-56.5-186.3-15.4l-1.6 1.1c-14.4 10.3-17.7 30.3-7.4 44.6s30.3 17.7 44.6 7.4l1.6-1.1c32.1-22.9 76-19.3 103.8 8.6c31.5 31.5 31.5 82.5 0 114l-96 96-31.9-25C430.9 239.6 420.1 175.1 377 132c-52.2-52.3-134.5-56.2-191.3-11.7L38.8 5.1zM239 162c30.1-14.9 67.7-9.9 92.8 15.3c20 20 27.5 48.3 21.7 74.5L239 162zM406.6 416.4L220.9 270c-2.1 39.8 12.2 80.1 42.2 110c38.9 38.9 94.4 51 143.6 36.3zm-290-228.5L60.2 244.3c-56.5 56.5-56.5 148 0 204.5c50 50 128.8 56.5 186.3 15.4l1.6-1.1c14.4-10.3 17.7-30.3 7.4-44.6s-30.3-17.7-44.6-7.4l-1.6 1.1c-32.1 22.9-76 19.3-103.8-8.6C74 372 74 321 105.5 289.5l61.8-61.8-50.6-39.9z"
fill="currentColor"
/>
</svg>
`;
exports[`<ShortUrlsRow /> > displays expected status icon 4`] = `
<svg
aria-hidden="true"
class="svg-inline--fa fa-link-slash text-danger"
data-icon="link-slash"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 640 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L489.3 358.2l90.5-90.5c56.5-56.5 56.5-148 0-204.5c-50-50-128.8-56.5-186.3-15.4l-1.6 1.1c-14.4 10.3-17.7 30.3-7.4 44.6s30.3 17.7 44.6 7.4l1.6-1.1c32.1-22.9 76-19.3 103.8 8.6c31.5 31.5 31.5 82.5 0 114l-96 96-31.9-25C430.9 239.6 420.1 175.1 377 132c-52.2-52.3-134.5-56.2-191.3-11.7L38.8 5.1zM239 162c30.1-14.9 67.7-9.9 92.8 15.3c20 20 27.5 48.3 21.7 74.5L239 162zM406.6 416.4L220.9 270c-2.1 39.8 12.2 80.1 42.2 110c38.9 38.9 94.4 51 143.6 36.3zm-290-228.5L60.2 244.3c-56.5 56.5-56.5 148 0 204.5c50 50 128.8 56.5 186.3 15.4l1.6-1.1c14.4-10.3 17.7-30.3 7.4-44.6s-30.3-17.7-44.6-7.4l-1.6 1.1c-32.1 22.9-76 19.3-103.8-8.6C74 372 74 321 105.5 289.5l61.8-61.8-50.6-39.9z"
fill="currentColor"
/>
</svg>
`;
exports[`<ShortUrlsRow /> > displays expected status icon 5`] = `
<svg
aria-hidden="true"
class="svg-inline--fa fa-calendar-xmark text-danger"
data-icon="calendar-xmark"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 448 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M128 0c17.7 0 32 14.3 32 32V64H288V32c0-17.7 14.3-32 32-32s32 14.3 32 32V64h48c26.5 0 48 21.5 48 48v48H0V112C0 85.5 21.5 64 48 64H96V32c0-17.7 14.3-32 32-32zM0 192H448V464c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V192zM305 305c9.4-9.4 9.4-24.6 0-33.9s-24.6-9.4-33.9 0l-47 47-47-47c-9.4-9.4-24.6-9.4-33.9 0s-9.4 24.6 0 33.9l47 47-47 47c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l47-47 47 47c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9l-47-47 47-47z"
fill="currentColor"
/>
</svg>
`;
exports[`<ShortUrlsRow /> > displays expected status icon 6`] = `
<svg
aria-hidden="true"
class="svg-inline--fa fa-check text-primary"
data-icon="check"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M470.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L192 338.7 425.4 105.4c12.5-12.5 32.8-12.5 45.3 0z"
fill="currentColor"
/>
</svg>
`;
exports[`<ShortUrlsRow /> > displays expected status icon 7`] = `
<svg
aria-hidden="true"
class="svg-inline--fa fa-check text-primary"
data-icon="check"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M470.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L192 338.7 425.4 105.4c12.5-12.5 32.8-12.5 45.3 0z"
fill="currentColor"
/>
</svg>
`;
exports[`<ShortUrlsRow /> > displays expected status icon 8`] = `
<svg
aria-hidden="true"
class="svg-inline--fa fa-check text-primary"
data-icon="check"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M470.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L192 338.7 425.4 105.4c12.5-12.5 32.8-12.5 45.3 0z"
fill="currentColor"
/>
</svg>
`;
exports[`<ShortUrlsRow /> displays expected status icon 1`] = `
<svg

View file

@ -5,12 +5,12 @@ import { renderWithEvents } from '../../../__helpers__/setUpTest';
describe('<QrErrorCorrectionDropdown />', () => {
const initialErrorCorrection: QrErrorCorrection = 'Q';
const setErrorCorrection = jest.fn();
const setErrorCorrection = vi.fn();
const setUp = () => renderWithEvents(
<QrErrorCorrectionDropdown errorCorrection={initialErrorCorrection} setErrorCorrection={setErrorCorrection} />,
);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('renders initial state', async () => {
const { user } = setUp();

View file

@ -5,10 +5,10 @@ import { renderWithEvents } from '../../../__helpers__/setUpTest';
describe('<QrFormatDropdown />', () => {
const initialFormat: QrCodeFormat = 'svg';
const setFormat = jest.fn();
const setFormat = vi.fn();
const setUp = () => renderWithEvents(<QrFormatDropdown format={initialFormat} setFormat={setFormat} />);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('renders initial state', async () => {
const { user } = setUp();

View file

@ -9,12 +9,12 @@ import {
describe('shortUrlCreationReducer', () => {
const shortUrl = fromPartial<ShortUrl>({});
const createShortUrlCall = jest.fn();
const createShortUrlCall = vi.fn();
const buildShlinkApiClient = () => fromPartial<ShlinkApiClient>({ createShortUrl: createShortUrlCall });
const createShortUrl = createShortUrlCreator(buildShlinkApiClient);
const { reducer, resetCreateShortUrl } = shortUrlCreationReducerCreator(createShortUrl);
afterEach(jest.resetAllMocks);
afterEach(vi.resetAllMocks);
describe('reducer', () => {
it('returns loading on CREATE_SHORT_URL_START', () => {
@ -52,7 +52,7 @@ describe('shortUrlCreationReducer', () => {
});
describe('createShortUrl', () => {
const dispatch = jest.fn();
const dispatch = vi.fn();
const getState = () => fromPartial<ShlinkState>({});
it('calls API on success', async () => {

View file

@ -7,12 +7,12 @@ import {
} from '../../../src/short-urls/reducers/shortUrlDeletion';
describe('shortUrlDeletionReducer', () => {
const deleteShortUrlCall = jest.fn();
const deleteShortUrlCall = vi.fn();
const buildShlinkApiClient = () => fromPartial<ShlinkApiClient>({ deleteShortUrl: deleteShortUrlCall });
const deleteShortUrl = deleteShortUrlCreator(buildShlinkApiClient);
const { reducer, resetDeleteShortUrl } = shortUrlDeletionReducerCreator(deleteShortUrl);
beforeEach(jest.clearAllMocks);
beforeEach(vi.clearAllMocks);
describe('reducer', () => {
it('returns loading on DELETE_SHORT_URL_START', () =>
@ -56,8 +56,8 @@ describe('shortUrlDeletionReducer', () => {
});
describe('deleteShortUrl', () => {
const dispatch = jest.fn();
const getState = jest.fn().mockReturnValue({ selectedServer: {} });
const dispatch = vi.fn();
const getState = vi.fn().mockReturnValue({ selectedServer: {} });
it.each(
[[undefined], [null], ['example.com']],

View file

@ -6,11 +6,11 @@ import { shortUrlDetailReducerCreator } from '../../../src/short-urls/reducers/s
import type { ShortUrlsList } from '../../../src/short-urls/reducers/shortUrlsList';
describe('shortUrlDetailReducer', () => {
const getShortUrlCall = jest.fn();
const getShortUrlCall = vi.fn();
const buildShlinkApiClient = () => fromPartial<ShlinkApiClient>({ getShortUrl: getShortUrlCall });
const { reducer, getShortUrlDetail } = shortUrlDetailReducerCreator(buildShlinkApiClient);
beforeEach(jest.clearAllMocks);
beforeEach(vi.clearAllMocks);
describe('reducer', () => {
it('returns loading on GET_SHORT_URL_DETAIL_START', () => {
@ -41,7 +41,7 @@ describe('shortUrlDetailReducer', () => {
});
describe('getShortUrlDetail', () => {
const dispatchMock = jest.fn();
const dispatchMock = vi.fn();
const buildGetState = (shortUrlsList?: ShortUrlsList) => () => fromPartial<ShlinkState>({ shortUrlsList });
it.each([

View file

@ -11,12 +11,12 @@ describe('shortUrlEditionReducer', () => {
const longUrl = 'https://shlink.io';
const shortCode = 'abc123';
const shortUrl = fromPartial<ShortUrl>({ longUrl, shortCode });
const updateShortUrl = jest.fn().mockResolvedValue(shortUrl);
const buildShlinkApiClient = jest.fn().mockReturnValue({ updateShortUrl });
const updateShortUrl = vi.fn().mockResolvedValue(shortUrl);
const buildShlinkApiClient = vi.fn().mockReturnValue({ updateShortUrl });
const editShortUrl = editShortUrlCreator(buildShlinkApiClient);
const { reducer } = shortUrlEditionReducerCreator(editShortUrl);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
describe('reducer', () => {
it('returns loading on EDIT_SHORT_URL_START', () => {
@ -46,12 +46,12 @@ describe('shortUrlEditionReducer', () => {
});
describe('editShortUrl', () => {
const dispatch = jest.fn();
const dispatch = vi.fn();
const createGetState = (selectedServer: SelectedServer = null) => () => fromPartial<ShlinkState>({
selectedServer,
});
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it.each([[undefined], [null], ['example.com']])('dispatches short URL on success', async (domain) => {
await editShortUrl({ shortCode, domain, data: { longUrl } })(dispatch, createGetState(), {});

View file

@ -14,14 +14,14 @@ import type { CreateVisit } from '../../../src/visits/types';
describe('shortUrlsListReducer', () => {
const shortCode = 'abc123';
const listShortUrlsMock = jest.fn();
const listShortUrlsMock = vi.fn();
const buildShlinkApiClient = () => fromPartial<ShlinkApiClient>({ listShortUrls: listShortUrlsMock });
const listShortUrls = listShortUrlsCreator(buildShlinkApiClient);
const editShortUrl = editShortUrlCreator(buildShlinkApiClient);
const createShortUrl = createShortUrlCreator(buildShlinkApiClient);
const { reducer } = shortUrlsListReducerCreator(listShortUrls, editShortUrl, createShortUrl);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
describe('reducer', () => {
it('returns loading on LIST_SHORT_URLS_START', () =>
@ -188,8 +188,8 @@ describe('shortUrlsListReducer', () => {
});
describe('listShortUrls', () => {
const dispatch = jest.fn();
const getState = jest.fn().mockReturnValue({ selectedServer: {} });
const dispatch = vi.fn();
const getState = vi.fn().mockReturnValue({ selectedServer: {} });
it('dispatches proper actions if API client request succeeds', async () => {
listShortUrlsMock.mockResolvedValue({});

View file

@ -8,7 +8,7 @@ import { TagsList as createTagsList } from '../../src/tags/TagsList';
import { renderWithEvents } from '../__helpers__/setUpTest';
describe('<TagsList />', () => {
const filterTags = jest.fn();
const filterTags = vi.fn();
const TagsListComp = createTagsList(({ sortedTags }) => <>TagsTable ({sortedTags.map((t) => t.visits).join(',')})</>);
const setUp = (tagsList: Partial<TagsList>, excludeBots = false) => renderWithEvents(
<TagsListComp
@ -21,7 +21,7 @@ describe('<TagsList />', () => {
/>,
);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('shows a loading message when tags are being loaded', () => {
setUp({ loading: true });

View file

@ -5,10 +5,13 @@ import { TagsTable as createTagsTable } from '../../src/tags/TagsTable';
import { rangeOf } from '../../src/utils/utils';
import { renderWithEvents } from '../__helpers__/setUpTest';
jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useLocation: jest.fn() }));
vi.mock('react-router-dom', async () => ({
...(await vi.importActual<any>('react-router-dom')),
useLocation: vi.fn(),
}));
describe('<TagsTable />', () => {
const orderByColumn = jest.fn();
const orderByColumn = vi.fn();
const TagsTable = createTagsTable(({ tag }) => <tr><td>TagsTableRow [{tag.tag}]</td></tr>);
const tags = (amount: number) => rangeOf(amount, (i) => `tag_${i}`);
const setUp = (sortedTags: string[] = [], search = '') => {
@ -23,7 +26,7 @@ describe('<TagsTable />', () => {
);
};
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('renders empty result if there are no tags', () => {
setUp();

View file

@ -5,20 +5,20 @@ import { renderWithEvents } from '../../__helpers__/setUpTest';
describe('<DeleteTagConfirmModal />', () => {
const tag = 'nodejs';
const deleteTag = jest.fn();
const toggle = jest.fn();
const deleteTag = vi.fn();
const toggle = vi.fn();
const setUp = (tagDelete: TagDeletion) => renderWithEvents(
<DeleteTagConfirmModal
tag={tag}
toggle={toggle}
isOpen
deleteTag={deleteTag}
tagDeleted={jest.fn()}
tagDeleted={vi.fn()}
tagDelete={tagDelete}
/>,
);
afterEach(jest.resetAllMocks);
afterEach(vi.resetAllMocks);
it('asks confirmation for provided tag to be deleted', () => {
setUp({ error: false, deleted: false, deleting: false });

View file

@ -5,17 +5,17 @@ import type { TagEdition } from '../../../src/tags/reducers/tagEdit';
import { renderWithEvents } from '../../__helpers__/setUpTest';
describe('<EditTagModal />', () => {
const EditTagModal = createEditTagModal(fromPartial({ getColorForKey: jest.fn(() => 'green') }));
const editTag = jest.fn().mockReturnValue(Promise.resolve());
const toggle = jest.fn();
const EditTagModal = createEditTagModal(fromPartial({ getColorForKey: vi.fn(() => 'green') }));
const editTag = vi.fn().mockReturnValue(Promise.resolve());
const toggle = vi.fn();
const setUp = (tagEdit: Partial<TagEdition> = {}) => {
const edition = fromPartial<TagEdition>(tagEdit);
return renderWithEvents(
<EditTagModal isOpen tag="foo" tagEdit={edition} editTag={editTag} tagEdited={jest.fn()} toggle={toggle} />,
<EditTagModal isOpen tag="foo" tagEdit={edition} editTag={editTag} tagEdited={vi.fn()} toggle={toggle} />,
);
};
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('allows modal to be toggled with different mechanisms', async () => {
const { user } = setUp();

View file

@ -20,10 +20,10 @@ const hexToRgb = (hex: string) => {
};
describe('<Tag />', () => {
const onClick = jest.fn();
const onClose = jest.fn();
const isColorLightForKey = jest.fn(() => false);
const getColorForKey = jest.fn(() => MAIN_COLOR);
const onClick = vi.fn();
const onClose = vi.fn();
const isColorLightForKey = vi.fn(() => false);
const getColorForKey = vi.fn(() => MAIN_COLOR);
const colorGenerator = fromPartial<ColorGenerator>({ getColorForKey, isColorLightForKey });
const setUp = (text: string, clearable?: boolean, children?: ReactNode) => renderWithEvents(
<Tag text={text} clearable={clearable} colorGenerator={colorGenerator} onClick={onClick} onClose={onClose}>
@ -31,7 +31,7 @@ describe('<Tag />', () => {
</Tag>,
);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it.each([
[true],

View file

@ -6,7 +6,7 @@ import { renderWithEvents } from '../../__helpers__/setUpTest';
import { colorGeneratorMock } from '../../utils/services/__mocks__/ColorGenerator.mock';
describe('<TagsSelector />', () => {
const onChange = jest.fn();
const onChange = vi.fn();
const TagsSelector = createTagsSelector(colorGeneratorMock);
const tags = ['foo', 'bar'];
const tagsList = fromPartial<TagsList>({ tags: [...tags, 'baz'] });
@ -15,12 +15,12 @@ describe('<TagsSelector />', () => {
selectedTags={tags}
tagsList={tagsList}
settings={fromPartial({})}
listTags={jest.fn()}
listTags={vi.fn()}
onChange={onChange}
/>,
);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('has an input for tags', () => {
setUp();

View file

@ -4,11 +4,11 @@ import type { ShlinkState } from '../../../src/container/types';
import { tagDeleted, tagDeleteReducerCreator } from '../../../src/tags/reducers/tagDelete';
describe('tagDeleteReducer', () => {
const deleteTagsCall = jest.fn();
const deleteTagsCall = vi.fn();
const buildShlinkApiClient = () => fromPartial<ShlinkApiClient>({ deleteTags: deleteTagsCall });
const { reducer, deleteTag } = tagDeleteReducerCreator(buildShlinkApiClient);
beforeEach(jest.clearAllMocks);
beforeEach(vi.clearAllMocks);
describe('reducer', () => {
it('returns loading on DELETE_TAG_START', () => {
@ -43,7 +43,7 @@ describe('tagDeleteReducer', () => {
});
describe('deleteTag', () => {
const dispatch = jest.fn();
const dispatch = vi.fn();
const getState = () => fromPartial<ShlinkState>({});
it('calls API on success', async () => {

View file

@ -8,9 +8,9 @@ describe('tagEditReducer', () => {
const oldName = 'foo';
const newName = 'bar';
const color = '#ff0000';
const editTagCall = jest.fn();
const editTagCall = vi.fn();
const buildShlinkApiClient = () => fromPartial<ShlinkApiClient>({ editTag: editTagCall });
const colorGenerator = fromPartial<ColorGenerator>({ setColorForKey: jest.fn() });
const colorGenerator = fromPartial<ColorGenerator>({ setColorForKey: vi.fn() });
const editTag = editTagCreator(buildShlinkApiClient, colorGenerator);
const { reducer } = tagEditReducerCreator(editTag);
@ -50,10 +50,10 @@ describe('tagEditReducer', () => {
});
describe('editTag', () => {
const dispatch = jest.fn();
const dispatch = vi.fn();
const getState = () => fromPartial<ShlinkState>({});
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('calls API on success', async () => {
editTagCall.mockResolvedValue(undefined);

View file

@ -16,12 +16,12 @@ import type { CreateVisit } from '../../../src/visits/types';
describe('tagsListReducer', () => {
const state = (props: Partial<TagsList>) => fromPartial<TagsList>(props);
const buildShlinkApiClient = jest.fn();
const buildShlinkApiClient = vi.fn();
const listTags = listTagsCreator(buildShlinkApiClient, true);
const createShortUrl = createShortUrlCreator(buildShlinkApiClient);
const { reducer } = tagsListReducerCreator(listTags, createShortUrl);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
describe('reducer', () => {
it('returns loading on LIST_TAGS_START', () => {
@ -196,9 +196,9 @@ describe('tagsListReducer', () => {
});
describe('listTags', () => {
const dispatch = jest.fn();
const getState = jest.fn(() => fromPartial<ShlinkState>({}));
const listTagsMock = jest.fn();
const dispatch = vi.fn();
const getState = vi.fn(() => fromPartial<ShlinkState>({}));
const listTagsMock = vi.fn();
const assertNoAction = async (tagsList: TagsList) => {
getState.mockReturnValue(fromPartial<ShlinkState>({ tagsList }));

View file

@ -24,7 +24,7 @@ describe('<Checkbox />', () => {
});
it.each([[true], [false]])('changes checked status on input change', async (checked) => {
const onChange = jest.fn();
const onChange = vi.fn();
const { user } = renderWithEvents(<Checkbox onChange={onChange} checked={checked}>Foo</Checkbox>);
expect(onChange).not.toHaveBeenCalled();

View file

@ -2,10 +2,10 @@ import { CopyToClipboardIcon } from '../../src/utils/CopyToClipboardIcon';
import { renderWithEvents } from '../__helpers__/setUpTest';
describe('<CopyToClipboardIcon />', () => {
const onCopy = jest.fn();
const onCopy = vi.fn();
const setUp = (text = 'foo') => renderWithEvents(<CopyToClipboardIcon text={text} onCopy={onCopy} />);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('wraps expected components', () => {
const { container } = setUp();

View file

@ -6,7 +6,7 @@ import { renderWithEvents } from '../__helpers__/setUpTest';
describe('<DropdownBtnMenu />', () => {
const setUp = (props: Partial<DropdownBtnMenuProps> = {}) => renderWithEvents(
<DropdownBtnMenu {...fromPartial<DropdownBtnMenuProps>({ toggle: jest.fn(), ...props })}>
<DropdownBtnMenu {...fromPartial<DropdownBtnMenuProps>({ toggle: vi.fn(), ...props })}>
the children
</DropdownBtnMenu>,
);

View file

@ -12,7 +12,7 @@ describe('<OrderingDropdown />', () => {
baz: 'Hello World',
};
const setUp = (props: Partial<OrderingDropdownProps> = {}) => renderWithEvents(
<OrderingDropdown items={items} order={{}} onChange={jest.fn()} {...props} />,
<OrderingDropdown items={items} order={{}} onChange={vi.fn()} {...props} />,
);
const setUpWithDisplayedMenu = async (props: Partial<OrderingDropdownProps> = {}) => {
const result = setUp(props);
@ -65,7 +65,7 @@ describe('<OrderingDropdown />', () => {
])(
'triggers change with proper params depending on clicked item and initial state',
async (initialOrder, expectedNewField, expectedNewDir) => {
const onChange = jest.fn();
const onChange = vi.fn();
const { user } = await setUpWithDisplayedMenu({ onChange, order: initialOrder });
await user.click(screen.getAllByRole('menuitem')[0]);
@ -76,7 +76,7 @@ describe('<OrderingDropdown />', () => {
);
it('clears selection when last item is clicked', async () => {
const onChange = jest.fn();
const onChange = vi.fn();
const { user } = await setUpWithDisplayedMenu({ onChange, order: { field: 'baz', dir: 'ASC' } });
await user.click(screen.getAllByRole('menuitem')[3]);

View file

@ -3,7 +3,7 @@ import { PaginationDropdown } from '../../src/utils/PaginationDropdown';
import { renderWithEvents } from '../__helpers__/setUpTest';
describe('<PaginationDropdown />', () => {
const setValue = jest.fn();
const setValue = vi.fn();
const setUp = async () => {
const result = renderWithEvents(<PaginationDropdown ranges={[10, 50, 100, 200]} value={50} setValue={setValue} />);
const { user } = result;
@ -13,7 +13,7 @@ describe('<PaginationDropdown />', () => {
return result;
};
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('renders expected amount of items', async () => {
await setUp();

View file

@ -1,4 +1,24 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`<CopyToClipboardIcon /> > wraps expected components 1`] = `
<div>
<svg
aria-hidden="true"
class="svg-inline--fa fa-clone ms-2 copy-to-clipboard-icon"
data-icon="clone"
data-prefix="far"
focusable="false"
role="img"
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M64 464H288c8.8 0 16-7.2 16-16V384h48v64c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V224c0-35.3 28.7-64 64-64h64v48H64c-8.8 0-16 7.2-16 16V448c0 8.8 7.2 16 16 16zM224 304H448c8.8 0 16-7.2 16-16V64c0-8.8-7.2-16-16-16H224c-8.8 0-16 7.2-16 16V288c0 8.8 7.2 16 16 16zm-64-16V64c0-35.3 28.7-64 64-64H448c35.3 0 64 28.7 64 64V288c0 35.3-28.7 64-64 64H224c-35.3 0-64-28.7-64-64z"
fill="currentColor"
/>
</svg>
</div>
`;
exports[`<CopyToClipboardIcon /> wraps expected components 1`] = `
<div>

View file

@ -1,4 +1,22 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`<ExportBtn /> > renders expected icon 1`] = `
<svg
aria-hidden="true"
class="svg-inline--fa fa-file-csv "
data-icon="file-csv"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 384 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M64 0C28.7 0 0 28.7 0 64V448c0 35.3 28.7 64 64 64H320c35.3 0 64-28.7 64-64V160H256c-17.7 0-32-14.3-32-32V0H64zM256 0V128H384L256 0zM80 224H96c22.1 0 40 17.9 40 40v8c0 8.8-7.2 16-16 16s-16-7.2-16-16v-8c0-4.4-3.6-8-8-8H80c-4.4 0-8 3.6-8 8v80c0 4.4 3.6 8 8 8H96c4.4 0 8-3.6 8-8v-8c0-8.8 7.2-16 16-16s16 7.2 16 16v8c0 22.1-17.9 40-40 40H80c-22.1 0-40-17.9-40-40V264c0-22.1 17.9-40 40-40zm72 46.4c0-25.6 20.8-46.4 46.4-46.4H216c8.8 0 16 7.2 16 16s-7.2 16-16 16H198.4c-7.9 0-14.4 6.4-14.4 14.4c0 5.2 2.8 9.9 7.2 12.5l25.4 14.5c14.4 8.3 23.4 23.6 23.4 40.3c0 25.6-20.8 46.4-46.4 46.4H168c-8.8 0-16-7.2-16-16s7.2-16 16-16h25.6c7.9 0 14.4-6.4 14.4-14.4c0-5.2-2.8-9.9-7.2-12.5l-25.4-14.5C160.9 302.4 152 287 152 270.4zM280 240v31.6c0 23 5.5 45.6 16 66c10.5-20.3 16-42.9 16-66V240c0-8.8 7.2-16 16-16s16 7.2 16 16v31.6c0 34.7-10.3 68.7-29.6 97.6l-5.1 7.7c-3 4.5-8 7.1-13.3 7.1s-10.3-2.7-13.3-7.1l-5.1-7.7c-19.3-28.9-29.6-62.9-29.6-97.6V240c0-8.8 7.2-16 16-16s16 7.2 16 16z"
fill="currentColor"
/>
</svg>
`;
exports[`<ExportBtn /> renders expected icon 1`] = `
<svg

View file

@ -1,4 +1,88 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`<IconInput /> > displays provided icon 1`] = `
<div>
<div
class="icon-input-container"
>
<input
class="icon-input-container__input form-control"
type="text"
/>
<svg
aria-hidden="true"
class="svg-inline--fa fa-calendar fa-fw icon-input-container__icon"
data-icon="calendar"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 448 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M96 32V64H48C21.5 64 0 85.5 0 112v48H448V112c0-26.5-21.5-48-48-48H352V32c0-17.7-14.3-32-32-32s-32 14.3-32 32V64H160V32c0-17.7-14.3-32-32-32S96 14.3 96 32zM448 192H0V464c0 26.5 21.5 48 48 48H400c26.5 0 48-21.5 48-48V192z"
fill="currentColor"
/>
</svg>
</div>
</div>
`;
exports[`<IconInput /> > displays provided icon 2`] = `
<div>
<div
class="icon-input-container"
>
<input
class="icon-input-container__input form-control"
type="text"
/>
<svg
aria-hidden="true"
class="svg-inline--fa fa-apple-whole fa-fw icon-input-container__icon"
data-icon="apple-whole"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 448 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M224 112c-8.8 0-16-7.2-16-16V80c0-44.2 35.8-80 80-80h16c8.8 0 16 7.2 16 16V32c0 44.2-35.8 80-80 80H224zM0 288c0-76.3 35.7-160 112-160c27.3 0 59.7 10.3 82.7 19.3c18.8 7.3 39.9 7.3 58.7 0c22.9-8.9 55.4-19.3 82.7-19.3c76.3 0 112 83.7 112 160c0 128-80 224-160 224c-16.5 0-38.1-6.6-51.5-11.3c-8.1-2.8-16.9-2.8-25 0c-13.4 4.7-35 11.3-51.5 11.3C80 512 0 416 0 288z"
fill="currentColor"
/>
</svg>
</div>
</div>
`;
exports[`<IconInput /> > displays provided icon 3`] = `
<div>
<div
class="icon-input-container"
>
<input
class="icon-input-container__input form-control"
type="text"
/>
<svg
aria-hidden="true"
class="svg-inline--fa fa-table fa-fw icon-input-container__icon"
data-icon="table"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M64 256V160H224v96H64zm0 64H224v96H64V320zm224 96V320H448v96H288zM448 256H288V160H448v96zM64 32C28.7 32 0 60.7 0 96V416c0 35.3 28.7 64 64 64H448c35.3 0 64-28.7 64-64V96c0-35.3-28.7-64-64-64H64z"
fill="currentColor"
/>
</svg>
</div>
</div>
`;
exports[`<IconInput /> displays provided icon 1`] = `
<div>

View file

@ -6,7 +6,7 @@ import { DATE_INTERVALS, rangeOrIntervalToString } from '../../../src/utils/help
import { renderWithEvents } from '../../__helpers__/setUpTest';
describe('<DateIntervalDropdownItems />', () => {
const onChange = jest.fn();
const onChange = vi.fn();
const setUp = async () => {
const { user, ...renderResult } = renderWithEvents(
<DropdownBtn text="text">
@ -20,7 +20,7 @@ describe('<DateIntervalDropdownItems />', () => {
return { user, ...renderResult };
};
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('renders expected amount of items', async () => {
await setUp();

View file

@ -6,7 +6,7 @@ import { renderWithEvents } from '../../__helpers__/setUpTest';
describe('<DateIntervalSelector />', () => {
const activeInterval: DateInterval = 'last7Days';
const onChange = jest.fn();
const onChange = vi.fn();
const setUp = () => renderWithEvents(
<DateIntervalSelector allText="All text" active={activeInterval} onChange={onChange} />,
);

View file

@ -3,13 +3,13 @@ import { DateRangeRow } from '../../../src/utils/dates/DateRangeRow';
import { renderWithEvents } from '../../__helpers__/setUpTest';
describe('<DateRangeRow />', () => {
const onEndDateChange = jest.fn();
const onStartDateChange = jest.fn();
const onEndDateChange = vi.fn();
const onStartDateChange = vi.fn();
const setUp = () => renderWithEvents(
<DateRangeRow onEndDateChange={onEndDateChange} onStartDateChange={onStartDateChange} />,
);
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('renders two date inputs', () => {
setUp();

View file

@ -6,7 +6,7 @@ import type { DateInterval } from '../../../src/utils/helpers/dateIntervals';
import { renderWithEvents } from '../../__helpers__/setUpTest';
describe('<DateRangeSelector />', () => {
const onDatesChange = jest.fn();
const onDatesChange = vi.fn();
const setUp = async (props: Partial<DateRangeSelectorProps> = {}) => {
const result = renderWithEvents(
<DateRangeSelector
@ -22,7 +22,7 @@ describe('<DateRangeSelector />', () => {
return result;
};
afterEach(jest.clearAllMocks);
afterEach(vi.clearAllMocks);
it('renders proper amount of items', async () => {
const { container } = await setUp();

View file

@ -6,12 +6,12 @@ import { MAIN_COLOR } from '../../../src/utils/theme';
describe('ColorGenerator', () => {
let colorGenerator: ColorGenerator;
const storageMock = fromPartial<LocalStorage>({
set: jest.fn(),
get: jest.fn(),
set: vi.fn(),
get: vi.fn(),
});
beforeEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
colorGenerator = new ColorGenerator(storageMock);
});

View file

@ -2,13 +2,13 @@ import { fromPartial } from '@total-typescript/shoehorn';
import { LocalStorage } from '../../../src/utils/services/LocalStorage';
describe('LocalStorage', () => {
const getItem = jest.fn((key) => (key === 'shlink.foo' ? JSON.stringify({ foo: 'bar' }) : null));
const setItem = jest.fn();
const getItem = vi.fn((key) => (key === 'shlink.foo' ? JSON.stringify({ foo: 'bar' }) : null));
const setItem = vi.fn();
const localStorageMock = fromPartial<Storage>({ getItem, setItem });
let storage: LocalStorage;
beforeEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
storage = new LocalStorage(localStorageMock);
});

View file

@ -2,7 +2,7 @@ import { fromPartial } from '@total-typescript/shoehorn';
import type { ColorGenerator } from '../../../../src/utils/services/ColorGenerator';
export const colorGeneratorMock = fromPartial<ColorGenerator>({
getColorForKey: jest.fn(() => 'red'),
setColorForKey: jest.fn(),
isColorLightForKey: jest.fn(() => false),
getColorForKey: vi.fn(() => 'red'),
setColorForKey: vi.fn(),
isColorLightForKey: vi.fn(() => false),
});

View file

@ -1,4 +1,40 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`<TableOrderIcon /> > renders an icon when all conditions are met 1`] = `
<svg
aria-hidden="true"
class="svg-inline--fa fa-caret-down ms-1"
data-icon="caret-down"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 320 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M137.4 374.6c12.5 12.5 32.8 12.5 45.3 0l128-128c9.2-9.2 11.9-22.9 6.9-34.9s-16.6-19.8-29.6-19.8L32 192c-12.9 0-24.6 7.8-29.6 19.8s-2.2 25.7 6.9 34.9l128 128z"
fill="currentColor"
/>
</svg>
`;
exports[`<TableOrderIcon /> > renders an icon when all conditions are met 2`] = `
<svg
aria-hidden="true"
class="svg-inline--fa fa-caret-up ms-1"
data-icon="caret-up"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 320 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M182.6 137.4c-12.5-12.5-32.8-12.5-45.3 0l-128 128c-9.2 9.2-11.9 22.9-6.9 34.9s16.6 19.8 29.6 19.8H288c12.9 0 24.6-7.8 29.6-19.8s2.2-25.7-6.9-34.9l-128-128z"
fill="currentColor"
/>
</svg>
`;
exports[`<TableOrderIcon /> renders an icon when all conditions are met 1`] = `
<svg

View file

@ -7,15 +7,15 @@ import { DomainVisits as createDomainVisits } from '../../src/visits/DomainVisit
import type { DomainVisits } from '../../src/visits/reducers/domainVisits';
import { renderWithEvents } from '../__helpers__/setUpTest';
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useParams: jest.fn().mockReturnValue({ domain: 'foo.com_DEFAULT' }),
vi.mock('react-router-dom', async () => ({
...(await vi.importActual<any>('react-router-dom')),
useParams: vi.fn().mockReturnValue({ domain: 'foo.com_DEFAULT' }),
}));
describe('<DomainVisits />', () => {
const exportVisits = jest.fn();
const getDomainVisits = jest.fn();
const cancelGetDomainVisits = jest.fn();
const exportVisits = vi.fn();
const getDomainVisits = vi.fn();
const cancelGetDomainVisits = vi.fn();
const domainVisits = fromPartial<DomainVisits>({ visits: [{ date: formatISO(new Date()) }] });
const DomainVisits = createDomainVisits(fromPartial({ exportVisits }));
const setUp = () => renderWithEvents(

View file

@ -8,9 +8,9 @@ import type { VisitsInfo } from '../../src/visits/reducers/types';
import { renderWithEvents } from '../__helpers__/setUpTest';
describe('<NonOrphanVisits />', () => {
const exportVisits = jest.fn();
const getNonOrphanVisits = jest.fn();
const cancelGetNonOrphanVisits = jest.fn();
const exportVisits = vi.fn();
const getNonOrphanVisits = vi.fn();
const cancelGetNonOrphanVisits = vi.fn();
const nonOrphanVisits = fromPartial<VisitsInfo>({ visits: [{ date: formatISO(new Date()) }] });
const NonOrphanVisits = createNonOrphanVisits(fromPartial({ exportVisits }));
const setUp = () => renderWithEvents(

View file

@ -8,8 +8,8 @@ import type { VisitsInfo } from '../../src/visits/reducers/types';
import { renderWithEvents } from '../__helpers__/setUpTest';
describe('<OrphanVisits />', () => {
const getOrphanVisits = jest.fn();
const exportVisits = jest.fn();
const getOrphanVisits = vi.fn();
const exportVisits = vi.fn();
const orphanVisits = fromPartial<VisitsInfo>({ visits: [{ date: formatISO(new Date()) }] });
const OrphanVisits = createOrphanVisits(fromPartial({ exportVisits }));
const setUp = () => renderWithEvents(
@ -18,7 +18,7 @@ describe('<OrphanVisits />', () => {
{...fromPartial<MercureBoundProps>({ mercureInfo: {} })}
getOrphanVisits={getOrphanVisits}
orphanVisits={orphanVisits}
cancelGetOrphanVisits={jest.fn()}
cancelGetOrphanVisits={vi.fn()}
settings={fromPartial({})}
/>
</MemoryRouter>,

View file

@ -10,8 +10,8 @@ import { ShortUrlVisits as createShortUrlVisits } from '../../src/visits/ShortUr
import { renderWithEvents } from '../__helpers__/setUpTest';
describe('<ShortUrlVisits />', () => {
const getShortUrlVisitsMock = jest.fn();
const exportVisits = jest.fn();
const getShortUrlVisitsMock = vi.fn();
const exportVisits = vi.fn();
const shortUrlVisits = fromPartial<ShortUrlVisitsState>({ visits: [{ date: formatISO(new Date()) }] });
const ShortUrlVisits = createShortUrlVisits(fromPartial({ exportVisits }));
const setUp = () => renderWithEvents(

View file

@ -12,7 +12,7 @@ describe('<ShortUrlVisitsHeader />', () => {
const shortUrlVisits = fromPartial<ShortUrlVisits>({
visits: [{}, {}, {}],
});
const goBack = jest.fn();
const goBack = vi.fn();
const setUp = (title?: string | null) => {
const shortUrlDetail = fromPartial<ShortUrlDetail>({
shortUrl: {

View file

@ -1,21 +1,21 @@
import { screen } from '@testing-library/react';
import { fromPartial } from '@total-typescript/shoehorn';
import { formatISO } from 'date-fns';
import { MemoryRouter } from 'react-router-dom';
import { MemoryRouter } from 'react-router';
import type { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
import type { TagVisits as TagVisitsStats } from '../../src/visits/reducers/tagVisits';
import type { TagVisitsProps } from '../../src/visits/TagVisits';
import { TagVisits as createTagVisits } from '../../src/visits/TagVisits';
import { renderWithEvents } from '../__helpers__/setUpTest';
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useParams: jest.fn().mockReturnValue({ tag: 'foo' }),
vi.mock('react-router-dom', async () => ({
...(await vi.importActual<any>('react-router-dom')),
useParams: vi.fn().mockReturnValue({ tag: 'foo' }),
}));
describe('<TagVisits />', () => {
const getTagVisitsMock = jest.fn();
const exportVisits = jest.fn();
const getTagVisitsMock = vi.fn();
const exportVisits = vi.fn();
const tagVisits = fromPartial<TagVisitsStats>({ visits: [{ date: formatISO(new Date()) }] });
const TagVisits = createTagVisits(
fromPartial({ isColorLightForKey: () => false, getColorForKey: () => 'red' }),

View file

@ -9,7 +9,7 @@ describe('<TagVisitsHeader />', () => {
tag: 'foo',
visits: [{}, {}, {}, {}],
});
const goBack = jest.fn();
const goBack = vi.fn();
const colorGenerator = fromPartial<ColorGenerator>({ isColorLightForKey: () => false, getColorForKey: () => 'red' });
const setUp = () => render(<TagVisitsHeader tagVisits={tagVisits} goBack={goBack} colorGenerator={colorGenerator} />);

Some files were not shown because too many files have changed in this diff Show more