fix(custom-modules): null beim Aendern ablehnen, Ladefehler statt 404, Fehlertexte, Seitenleiste eingeklappt
- PATCH mit null fuer name/url/category ergibt 400 statt 500 - Modulansicht unterscheidet Ladefehler von "nicht gefunden" - Formular/Loeschdialog nennen 403 und 400 eigens - eingeklappte Seitenleiste folgt der Gruppenreihenfolge der ausgeklappten - neue Eintraege sind mit "Eigene Module" vorbelegt - Verwaltung zeigt bei Ladefehler nicht zusaetzlich "keine Eintraege" Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,8 +8,18 @@ vi.mock('next/navigation', () => ({
|
||||
}));
|
||||
|
||||
vi.mock('next/link', () => ({
|
||||
default: ({ children, href, className }: { children: React.ReactNode; href: string; className?: string }) => (
|
||||
<a href={href} className={className}>{children}</a>
|
||||
default: ({
|
||||
children,
|
||||
href,
|
||||
className,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
href: string;
|
||||
className?: string;
|
||||
}) => (
|
||||
<a href={href} className={className}>
|
||||
{children}
|
||||
</a>
|
||||
),
|
||||
}));
|
||||
|
||||
@@ -100,9 +110,7 @@ const mockActiveModules = [
|
||||
function stubFetch() {
|
||||
vi.stubGlobal(
|
||||
'fetch',
|
||||
vi.fn(() =>
|
||||
Promise.resolve({ ok: true, json: () => Promise.resolve(mockActiveModules) }),
|
||||
),
|
||||
vi.fn(() => Promise.resolve({ ok: true, json: () => Promise.resolve(mockActiveModules) })),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -316,7 +324,9 @@ describe('Sidebar', () => {
|
||||
expect(screen.getByText('Mein Wiki')).toBeInTheDocument();
|
||||
});
|
||||
const groups = Array.from(
|
||||
screen.getByRole('group', { name: 'Kategorien' }).querySelectorAll(':scope > ul > li > button span.truncate'),
|
||||
screen
|
||||
.getByRole('group', { name: 'Kategorien' })
|
||||
.querySelectorAll(':scope > ul > li > button span.truncate'),
|
||||
).map((n) => n.textContent);
|
||||
expect(groups.at(-1)).toBe('custom-modules');
|
||||
expect(groups).toContain('fleet');
|
||||
@@ -340,12 +350,40 @@ describe('Sidebar', () => {
|
||||
render(<Sidebar />);
|
||||
|
||||
const hrefs = () =>
|
||||
Array.from(document.querySelectorAll('aside ul.border-t a')).map((a) => a.getAttribute('href'));
|
||||
Array.from(document.querySelectorAll('aside ul.border-t a')).map((a) =>
|
||||
a.getAttribute('href'),
|
||||
);
|
||||
await waitFor(() => {
|
||||
expect(hrefs()).toContain('/modules/custom/cm-1');
|
||||
});
|
||||
expect(hrefs().at(-1)).toBe('/modules/custom/cm-1');
|
||||
expect(hrefs().indexOf('/modules/custom/cm-2')).toBeLessThan(hrefs().indexOf('/modules/custom/cm-1'));
|
||||
expect(hrefs().indexOf('/modules/custom/cm-2')).toBeLessThan(
|
||||
hrefs().indexOf('/modules/custom/cm-1'),
|
||||
);
|
||||
});
|
||||
|
||||
it('eingeklappt dieselbe Gruppenfolge wie ausgeklappt (eigenes Modul bei seiner Kategorie)', async () => {
|
||||
mockCustomModules = [
|
||||
customModule({ id: 'cm-1', category: 'Domain-Tools', name: 'Mein Tool' }),
|
||||
customModule({ id: 'cm-2', category: 'custom-modules', name: 'Mein Wiki' }),
|
||||
];
|
||||
mockSidebarCollapsed(true);
|
||||
const Sidebar = await importSidebar();
|
||||
render(<Sidebar />);
|
||||
|
||||
const hrefs = () =>
|
||||
Array.from(document.querySelectorAll('aside ul.border-t a')).map((a) =>
|
||||
a.getAttribute('href'),
|
||||
);
|
||||
await waitFor(() => {
|
||||
expect(hrefs()).toContain('/modules/custom/cm-2');
|
||||
});
|
||||
expect(hrefs()).toEqual([
|
||||
'/modules/Domain-Tools/domaincheck',
|
||||
'/modules/custom/cm-1',
|
||||
'/modules/Utilities/converter',
|
||||
'/modules/custom/cm-2',
|
||||
]);
|
||||
});
|
||||
|
||||
it('eingebaute Module stehen innerhalb einer Kategorie vor eigenen', async () => {
|
||||
@@ -360,7 +398,10 @@ describe('Sidebar', () => {
|
||||
.getByText('Domain-Tools')
|
||||
.closest('li')
|
||||
?.querySelectorAll('a span.truncate');
|
||||
expect(Array.from(items ?? []).map((n) => n.textContent)).toEqual(['Domaincheck', 'Aaa Eigenes']);
|
||||
expect(Array.from(items ?? []).map((n) => n.textContent)).toEqual([
|
||||
'Domaincheck',
|
||||
'Aaa Eigenes',
|
||||
]);
|
||||
});
|
||||
|
||||
it('auf /modules/custom/<id> traegt genau dieser Eintrag die Auswahlmarke', async () => {
|
||||
@@ -379,7 +420,10 @@ describe('Sidebar', () => {
|
||||
screen.getByText('Anderes').closest('a')?.querySelector('[data-testid="nav-selection-pill"]'),
|
||||
).toBeNull();
|
||||
expect(
|
||||
screen.getByText('Domaincheck').closest('a')?.querySelector('[data-testid="nav-selection-pill"]'),
|
||||
screen
|
||||
.getByText('Domaincheck')
|
||||
.closest('a')
|
||||
?.querySelector('[data-testid="nav-selection-pill"]'),
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user