test(260924-i8v): RED fuer Titel und Serverauswahl der Proxmox-Kachel
- Auswahl-Bauteil: Reihenfolge nach position, Produktwort, Aufraeumen geloeschter Kennungen - Einstellungsformular: Laden, Fehler, Leer, onChange fuer Titel und Auswahl - Einstellungsbereich: Zweig proxmox mit Titel-Zusatz in der Kopfzeile - Kachel im Bearbeitungsmodus: entprellter Titel, Auswahl statt Liste, schliesst beim Verlassen Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,12 @@
|
||||
import { act, cleanup, render as rtlRender, screen, waitFor, within } from '@testing-library/react';
|
||||
import {
|
||||
act,
|
||||
cleanup,
|
||||
fireEvent,
|
||||
render as rtlRender,
|
||||
screen,
|
||||
waitFor,
|
||||
within,
|
||||
} from '@testing-library/react';
|
||||
import { NextIntlClientProvider } from 'next-intl';
|
||||
import type { ReactElement } from 'react';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
@@ -37,6 +45,11 @@ vi.mock('next/link', () => ({
|
||||
),
|
||||
}));
|
||||
|
||||
const mockUpdateWidgetConfig = vi.fn();
|
||||
vi.mock('@/lib/dashboard-api', () => ({
|
||||
updateWidgetConfig: (...args: unknown[]) => mockUpdateWidgetConfig(...args),
|
||||
}));
|
||||
|
||||
function mockUser(user: { role: 'SUPER_ADMIN' | 'ADMIN' | 'USER' } | null) {
|
||||
mockAuthStore.mockImplementation((selector: (state: { user: typeof user }) => unknown) =>
|
||||
selector({ user }),
|
||||
@@ -521,3 +534,109 @@ describe('ProxmoxWidget: Minutentakt (quick-260924-i8v, Aufgabe 2)', () => {
|
||||
expect(screen.queryByText('Die Serverliste konnte nicht geladen werden.')).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('ProxmoxWidget: Bearbeitungsmodus mit Titel und Serverauswahl (quick-260924-i8v, Aufgabe 3)', () => {
|
||||
beforeEach(() => {
|
||||
mockUpdateWidgetConfig.mockResolvedValue(undefined);
|
||||
});
|
||||
|
||||
it('Titelfeld speichert entprellt nach 1500 ms per updateWidgetConfig({ title })', async () => {
|
||||
mockListServers.mockResolvedValue([makeServer('ok')]);
|
||||
await renderWidget({ isEditMode: true, config: { title: 'Alt' } });
|
||||
await screen.findByTestId('proxmox-summary');
|
||||
|
||||
const input = screen.getByLabelText('Titel') as HTMLInputElement;
|
||||
expect(input.value).toBe('Alt');
|
||||
expect(input).toHaveAttribute('placeholder', 'Titel (optional)');
|
||||
expect(input).toHaveClass('widgetNoDrag');
|
||||
|
||||
vi.useFakeTimers({ toFake: ['setTimeout', 'clearTimeout'] });
|
||||
try {
|
||||
fireEvent.change(input, { target: { value: 'N' } });
|
||||
fireEvent.change(input, { target: { value: 'Neu' } });
|
||||
vi.advanceTimersByTime(1499);
|
||||
expect(mockUpdateWidgetConfig).not.toHaveBeenCalled();
|
||||
vi.advanceTimersByTime(1);
|
||||
expect(mockUpdateWidgetConfig).toHaveBeenCalledTimes(1);
|
||||
expect(mockUpdateWidgetConfig).toHaveBeenCalledWith('w-1', { title: 'Neu' });
|
||||
} finally {
|
||||
vi.useRealTimers();
|
||||
}
|
||||
});
|
||||
|
||||
it('im Bearbeitungsmodus steht die Kopfzeile auch ohne Titel, mit Abstand zur Griffleiste', async () => {
|
||||
mockListServers.mockResolvedValue([makeServer('ok')]);
|
||||
const { container } = await renderWidget({ isEditMode: true });
|
||||
await screen.findByTestId('proxmox-summary');
|
||||
|
||||
expect(screen.getByLabelText('Titel')).toBeInTheDocument();
|
||||
expect(screen.queryByRole('heading')).toBeNull();
|
||||
expect(container.querySelector('[data-testid="proxmox-widget"]')).toHaveClass('pt-5');
|
||||
});
|
||||
|
||||
it('„Server auswählen“ oeffnet die Auswahl an Stelle der Liste; eine Aenderung speichert sofort und filtert', async () => {
|
||||
mockListServers.mockResolvedValue([
|
||||
makeServer('ok', { id: 'a', name: 'pve-a', position: 0 }),
|
||||
makeServer('down', { id: 'b', name: 'pve-b', position: 1 }),
|
||||
]);
|
||||
await renderWidget({ isEditMode: true });
|
||||
expect(await screen.findByTestId('proxmox-summary')).toHaveTextContent('1 nicht erreichbar');
|
||||
|
||||
const toggle = screen.getByRole('button', { name: 'Server auswählen' });
|
||||
expect(toggle).toHaveAttribute('aria-expanded', 'false');
|
||||
expect(toggle).toHaveAttribute('data-no-drag');
|
||||
fireEvent.click(toggle);
|
||||
expect(toggle).toHaveAttribute('aria-expanded', 'true');
|
||||
|
||||
expect(screen.queryByTestId('proxmox-list')).toBeNull();
|
||||
const group = screen.getByRole('group', { name: 'Angezeigte Server' });
|
||||
expect(group.closest('.widgetNoDrag')).not.toBeNull();
|
||||
|
||||
fireEvent.click(screen.getByRole('checkbox', { name: /pve-a/ }));
|
||||
|
||||
expect(mockUpdateWidgetConfig).toHaveBeenCalledWith('w-1', { serverIds: ['a'] });
|
||||
expect(screen.getByTestId('proxmox-summary')).toHaveTextContent('Alles in Ordnung');
|
||||
// Kein zusaetzlicher Abruf fuer die Auswahl
|
||||
expect(mockListServers).toHaveBeenCalledTimes(1);
|
||||
expect(mockPollServer).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('die Auswahl bekommt die ungefilterte Liste', async () => {
|
||||
mockListServers.mockResolvedValue([
|
||||
makeServer('ok', { id: 'a', name: 'pve-a' }),
|
||||
makeServer('ok', { id: 'b', name: 'pve-b' }),
|
||||
]);
|
||||
await renderWidget({ isEditMode: true, config: { serverIds: ['a'] } });
|
||||
await screen.findByTestId('proxmox-summary');
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Server auswählen' }));
|
||||
|
||||
expect(screen.getByRole('checkbox', { name: /pve-a/ })).toBeChecked();
|
||||
expect(screen.getByRole('checkbox', { name: /pve-b/ })).not.toBeChecked();
|
||||
});
|
||||
|
||||
it('Verlassen des Bearbeitungsmodus schliesst die Auswahl', async () => {
|
||||
mockListServers.mockResolvedValue([makeServer('ok')]);
|
||||
const { ProxmoxWidget } = await import('./proxmox-widget');
|
||||
const ui = (isEditMode: boolean) => (
|
||||
<NextIntlClientProvider locale="de" messages={de} timeZone="Europe/Berlin">
|
||||
<ProxmoxWidget instanceId="w-1" config={{}} isEditMode={isEditMode} />
|
||||
</NextIntlClientProvider>
|
||||
);
|
||||
const { rerender } = rtlRender(ui(true));
|
||||
await screen.findByTestId('proxmox-summary');
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Server auswählen' }));
|
||||
expect(screen.getByRole('group', { name: 'Angezeigte Server' })).toBeInTheDocument();
|
||||
|
||||
rerender(ui(false));
|
||||
expect(screen.queryByRole('group', { name: 'Angezeigte Server' })).toBeNull();
|
||||
expect(screen.getByTestId('proxmox-list')).toBeInTheDocument();
|
||||
|
||||
rerender(ui(true));
|
||||
expect(screen.getByRole('button', { name: 'Server auswählen' })).toHaveAttribute(
|
||||
'aria-expanded',
|
||||
'false',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user