Do not inject components into other components

This commit is contained in:
Alejandro Celaya
2025-11-15 11:46:19 +01:00
parent dad3990c23
commit d10bea50bc
17 changed files with 156 additions and 197 deletions

View File

@@ -2,25 +2,25 @@ import type { HttpClient } from '@shlinkio/shlink-js-sdk';
import { act, screen } from '@testing-library/react';
import { fromPartial } from '@total-typescript/shoehorn';
import { MemoryRouter } from 'react-router';
import { AppFactory } from '../../src/app/App';
import { App } from '../../src/app/App';
import { ContainerProvider } from '../../src/container/context';
import type { ServerWithId } from '../../src/servers/data';
import { checkAccessibility } from '../__helpers__/accessibility';
import { renderWithStore } from '../__helpers__/setUpTest';
vi.mock(import('../../src/common/ShlinkWebComponentContainer'), () => ({
ShlinkWebComponentContainer: () => <span>ShlinkWebComponentContainer</span>,
}));
describe('<App />', () => {
const App = AppFactory(
fromPartial({
Home: () => <>Home</>,
ShlinkWebComponentContainer: () => <>ShlinkWebComponentContainer</>,
CreateServer: () => <>CreateServer</>,
ManageServers: () => <>ManageServers</>,
}),
);
const setUp = async (activeRoute = '/') => act(() => renderWithStore(
<MemoryRouter initialEntries={[{ pathname: activeRoute }]}>
<ContainerProvider
value={fromPartial({ HttpClient: fromPartial<HttpClient>({}), buildShlinkApiClient: vi.fn() })}
value={fromPartial({
HttpClient: fromPartial<HttpClient>({}),
buildShlinkApiClient: vi.fn(),
useTimeoutToggle: vi.fn().mockReturnValue([false, vi.fn()]),
})}
>
<App />
</ContainerProvider>
@@ -42,8 +42,8 @@ describe('<App />', () => {
it.each([
['/settings/general', 'User interface'],
['/settings/short-urls', 'Short URLs form'],
['/manage-servers', 'ManageServers'],
['/server/create', 'CreateServer'],
['/manage-servers', 'Add a server'],
['/server/create', 'Add new server'],
['/server/abc123/edit', 'Edit "abc123 server"'],
['/server/def456/edit', 'Edit "def456 server"'],
['/server/abc123/foo', 'ShlinkWebComponentContainer'],

View File

@@ -2,6 +2,7 @@ import { screen } from '@testing-library/react';
import { fromPartial } from '@total-typescript/shoehorn';
import { MemoryRouter } from 'react-router';
import { Home } from '../../src/common/Home';
import { ContainerProvider } from '../../src/container/context';
import type { ServersMap, ServerWithId } from '../../src/servers/data';
import { checkAccessibility } from '../__helpers__/accessibility';
import { renderWithStore } from '../__helpers__/setUpTest';
@@ -9,7 +10,9 @@ import { renderWithStore } from '../__helpers__/setUpTest';
describe('<Home />', () => {
const setUp = (servers: ServersMap = {}) => renderWithStore(
<MemoryRouter>
<Home />
<ContainerProvider value={fromPartial({ buildShlinkApiClient: vi.fn() })}>
<Home />
</ContainerProvider>
</MemoryRouter>,
{
initialState: { servers },

View File

@@ -1,7 +1,7 @@
import { screen } from '@testing-library/react';
import { fromPartial } from '@total-typescript/shoehorn';
import { MemoryRouter } from 'react-router';
import { ShlinkWebComponentContainerFactory } from '../../src/common/ShlinkWebComponentContainer';
import { ShlinkWebComponentContainer } from '../../src/common/ShlinkWebComponentContainer';
import { ContainerProvider } from '../../src/container/context';
import type { NonReachableServer, NotFoundServer, SelectedServer } from '../../src/servers/data';
import { checkAccessibility } from '../__helpers__/accessibility';
@@ -14,13 +14,12 @@ vi.mock('@shlinkio/shlink-web-component', () => ({
}));
describe('<ShlinkWebComponentContainer />', () => {
const ShlinkWebComponentContainer = ShlinkWebComponentContainerFactory(fromPartial({
buildShlinkApiClient: vi.fn().mockReturnValue(fromPartial({})),
TagColorsStorage: fromPartial({}),
}));
const setUp = (selectedServer: SelectedServer) => renderWithStore(
<MemoryRouter>
<ContainerProvider value={fromPartial({ buildShlinkApiClient: vi.fn() })}>
<ContainerProvider value={fromPartial({
buildShlinkApiClient: vi.fn(),
TagColorsStorage: fromPartial({}),
})}>
<ShlinkWebComponentContainer />
</ContainerProvider>
</MemoryRouter>,

View File

@@ -2,7 +2,8 @@ import { fireEvent, screen, waitFor } from '@testing-library/react';
import { fromPartial } from '@total-typescript/shoehorn';
import { createMemoryHistory } from 'history';
import { Router } from 'react-router';
import { CreateServerFactory } from '../../src/servers/CreateServer';
import { ContainerProvider } from '../../src/container/context';
import { CreateServer } from '../../src/servers/CreateServer';
import type { ServersMap } from '../../src/servers/data';
import { checkAccessibility } from '../__helpers__/accessibility';
import { renderWithStore } from '../__helpers__/setUpTest';
@@ -24,17 +25,19 @@ describe('<CreateServer />', () => {
callCount += 1;
return result;
});
const CreateServer = CreateServerFactory(fromPartial({
ImportServersBtn: () => <>ImportServersBtn</>,
useTimeoutToggle,
}));
const history = createMemoryHistory({ initialEntries: ['/foo', '/bar'] });
return {
history,
...renderWithStore(
<Router location={history.location} navigator={history}>
<CreateServer />
<ContainerProvider value={fromPartial({
ImportServersBtn: () => <>ImportServersBtn</>,
useTimeoutToggle,
buildShlinkApiClient: vi.fn(),
})}>
<CreateServer />
</ContainerProvider>
</Router>,
{
initialState: { servers },
@@ -64,11 +67,6 @@ describe('<CreateServer />', () => {
expect(screen.getByText('The servers could not be imported. Make sure the format is correct.')).toBeInTheDocument();
});
it('shows import button when no servers exist yet', () => {
setUp({ servers: {} });
expect(screen.queryByText('ImportServersBtn')).toBeInTheDocument();
});
it('creates server data when form is submitted', async () => {
const { user, history, store } = setUp();
const expectedServerId = 'the_name-the_url.com';

View File

@@ -1,8 +1,9 @@
import { screen, waitFor } from '@testing-library/react';
import { fromPartial } from '@total-typescript/shoehorn';
import { MemoryRouter } from 'react-router';
import { ContainerProvider } from '../../src/container/context';
import type { ServersMap, ServerWithId } from '../../src/servers/data';
import { ManageServersFactory } from '../../src/servers/ManageServers';
import { ManageServers } from '../../src/servers/ManageServers';
import type { ServersExporter } from '../../src/servers/services/ServersExporter';
import { checkAccessibility } from '../__helpers__/accessibility';
import { renderWithStore } from '../__helpers__/setUpTest';
@@ -11,16 +12,20 @@ describe('<ManageServers />', () => {
const exportServers = vi.fn();
const serversExporter = fromPartial<ServersExporter>({ exportServers });
const useTimeoutToggle = vi.fn().mockReturnValue([false, vi.fn()]);
const ManageServers = ManageServersFactory(fromPartial({
ServersExporter: serversExporter,
ImportServersBtn: () => <span>ImportServersBtn</span>,
useTimeoutToggle,
}));
const createServerMock = (value: string, autoConnect = false) => fromPartial<ServerWithId>(
{ id: value, name: value, url: value, autoConnect },
);
const setUp = (servers: ServersMap = {}) => renderWithStore(
<MemoryRouter><ManageServers /></MemoryRouter>,
<MemoryRouter>
<ContainerProvider value={fromPartial({
ServersExporter: serversExporter,
ImportServersBtn: () => <span>ImportServersBtn</span>,
useTimeoutToggle,
buildShlinkApiClient: vi.fn(),
})}>
<ManageServers />
</ContainerProvider>
</MemoryRouter>,
{
initialState: { servers },
},

View File

@@ -1,9 +1,9 @@
import { screen, waitFor } from '@testing-library/react';
import { fromPartial } from '@total-typescript/shoehorn';
import { ContainerProvider } from '../../../src/container/context';
import type { ServerData, ServersMap, ServerWithId } from '../../../src/servers/data';
import type {
ImportServersBtnProps } from '../../../src/servers/helpers/ImportServersBtn';
import { ImportServersBtnFactory } from '../../../src/servers/helpers/ImportServersBtn';
import type { ImportServersBtnProps } from '../../../src/servers/helpers/ImportServersBtn';
import { ImportServersBtn } from '../../../src/servers/helpers/ImportServersBtn';
import type { ServersImporter } from '../../../src/servers/services/ServersImporter';
import { checkAccessibility } from '../../__helpers__/accessibility';
import { renderWithStore } from '../../__helpers__/setUpTest';
@@ -13,9 +13,10 @@ describe('<ImportServersBtn />', () => {
const onImportMock = vi.fn();
const importServersFromFile = vi.fn().mockResolvedValue([]);
const serversImporterMock = fromPartial<ServersImporter>({ importServersFromFile });
const ImportServersBtn = ImportServersBtnFactory(fromPartial({ ServersImporter: serversImporterMock }));
const setUp = (props: Partial<ImportServersBtnProps> = {}, servers: ServersMap = {}) => renderWithStore(
<ImportServersBtn {...props} onImport={onImportMock} />,
<ContainerProvider value={fromPartial({ ServersImporter: serversImporterMock })}>
<ImportServersBtn {...props} onImport={onImportMock} />
</ContainerProvider>,
{
initialState: { servers },
},