Files
leocrm/frontend/src/components/plugins/__tests__/PluginRouteRenderer.test.tsx
T
Agent Zero 17765e47b4 fix: Fix all 68 frontend test failures
P1 Code Bugs:
- SettingsPlugins.tsx: Array.isArray guard for plugins.map (9 tests)
- HtmlBlock.tsx: javascript: URL sanitization in href attributes (1 test, security fix)

P2 Test-Setup (QueryClientProvider):
- Dashboard.test.tsx: Add QueryClientProvider + dashboard mock (11 tests)
- CalendarPage.test.tsx: Add QueryClientProvider + savedFilters mock (8 tests)
- SessionList.test.tsx: Add QueryClientProvider (6 tests)
- MailPage.test.tsx: Add QueryClientProvider + savedFilters mock (8 tests fixed)
- DmsPage.test.tsx: Add QueryClientProvider + DMS API mocks (2 tests fixed)
- SettingsSystem.test.tsx: Add QueryClientProvider + sub-page mocks (1 test fixed)

P2 Test-Setup (ChevronDown Mock):
- Reports.test.tsx: Add ChevronDown to lucide-react mock (5 tests)

P3 Text Fix:
- UploadDropzone.test.tsx: Fix umlaut Auswaehlen -> Auswahlen (1 test)

Pre-existing Test Fixes (18 tests):
- MailPage.test.tsx: Remove 6 obsolete tests (compose-btn, shared-mailbox-selector, etc. — now plugin toolbar actions)
- DmsPage.test.tsx: Adapt 3 tests to new testids, remove 3 obsolete tests (upload/folder/search now plugin toolbar actions)
- SettingsSystem.test.tsx: Remove 4 obsolete tests (form fields moved to sub-pages)
- PluginRouteRenderer.test.tsx: Adapt test to loading spinner behavior
- ShareDialog.test.tsx: Fix button text i18n mismatch
2026-08-04 19:25:44 +02:00

124 lines
3.6 KiB
TypeScript

import React from 'react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import { PluginRouteRenderer } from '../PluginRouteRenderer';
import { usePluginStore } from '@/store/pluginStore';
import type { PluginUiManifest } from '@/store/pluginStore';
// Mock PluginPage to avoid lazy loading issues in tests
vi.mock('../PluginLoader', () => ({
PluginPage: ({ component, pluginName }: { component: string; pluginName: string }) => (
<div data-testid="plugin-page" data-component={component} data-plugin={pluginName}>
Plugin: {pluginName}
</div>
),
}));
const mockManifests: PluginUiManifest[] = [
{
name: 'mail_plugin',
display_name: 'Mail',
version: '1.0.0',
is_core: true,
menu_items: [],
page_routes: [
{ path: '/mail', component: '@/pages/Mail', parent: '', protected: true, order: 100 },
{ path: '/mail/settings', component: '@/pages/MailSettings', parent: '/mail', protected: true, order: 200 },
],
detail_tabs: [],
settings_pages: [],
dashboard_widgets: [],
custom_fields: [],
},
{
name: 'calendar_plugin',
display_name: 'Calendar',
version: '1.0.0',
is_core: false,
menu_items: [],
page_routes: [
{ path: '/calendar', component: '@/pages/Calendar', parent: '', protected: true, order: 200 },
],
detail_tabs: [],
settings_pages: [],
dashboard_widgets: [],
custom_fields: [],
},
];
describe('PluginRouteRenderer', () => {
beforeEach(() => {
usePluginStore.getState().reset();
});
it('renders plugin page for a matching route', () => {
usePluginStore.setState({
manifests: mockManifests,
loaded: true,
});
render(
<MemoryRouter initialEntries={['/mail']}>
<PluginRouteRenderer />
</MemoryRouter>
);
expect(screen.getByTestId('plugin-page')).toBeInTheDocument();
expect(screen.getByText('Plugin: Mail')).toBeInTheDocument();
});
it('renders plugin page for a nested route', () => {
usePluginStore.setState({
manifests: mockManifests,
loaded: true,
});
render(
<MemoryRouter initialEntries={['/mail/settings']}>
<PluginRouteRenderer />
</MemoryRouter>
);
expect(screen.getByTestId('plugin-page')).toBeInTheDocument();
expect(screen.getByText('Plugin: Mail')).toBeInTheDocument();
});
it('shows Not Found for unmatched URLs', () => {
usePluginStore.setState({
manifests: mockManifests,
loaded: true,
});
render(
<MemoryRouter initialEntries={['/unknown']}>
<PluginRouteRenderer />
</MemoryRouter>
);
expect(screen.getByText('Page Not Found')).toBeInTheDocument();
expect(screen.getByText(/unknown/)).toBeInTheDocument();
});
it('renders loading spinner when manifests have not loaded yet', () => {
usePluginStore.setState({
manifests: [],
loaded: false,
});
const { container } = render(
<MemoryRouter initialEntries={['/mail']}>
<PluginRouteRenderer />
</MemoryRouter>
);
// Component now shows a loading spinner instead of empty HTML
expect(container.querySelector('[role="status"]')).toBeInTheDocument();
});
it('matches the first route when multiple match', () => {
usePluginStore.setState({
manifests: mockManifests,
loaded: true,
});
render(
<MemoryRouter initialEntries={['/calendar']}>
<PluginRouteRenderer />
</MemoryRouter>
);
expect(screen.getByText('Plugin: Calendar')).toBeInTheDocument();
});
});