7416a925a6
- Kopfzeile bekommt Einhaengepunkt header-center-slot; auf / entfaellt der Text Startseite - DashboardTabs rendert per createPortal dorthin, eigene Zeile ueber dem Raster entfaellt - eingelassene Spur mit erhabenem aktivem Reiter, waagrecht scrollbar mit weicher Randausblendung - role=tablist/tab, Pfeiltasten/Pos1/Ende, sichtbarer Fokusring, aktiver Reiter wird ins Bild gescrollt - Plus-Knopf ausserhalb der Spur, Loeschdialog am Dokumentkoerper, Ziehhinweis als sr-only/Tooltip Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
435 lines
17 KiB
TypeScript
435 lines
17 KiB
TypeScript
import { cleanup, fireEvent, render, screen, within } from '@testing-library/react';
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
/**
|
|
* Mock next-intl mit einfacher `{param}`-Ersetzung — anders als das
|
|
* schlichtere Muster in `widget-catalog-modal.test.tsx` (das Parameter
|
|
* ignoriert), weil Test 8 unten die eingesetzte Reiterbezeichnung im
|
|
* Loeschdialog prueft.
|
|
*/
|
|
vi.mock('next-intl', () => ({
|
|
useTranslations: (namespace: string) => (key: string, params?: Record<string, string>) => {
|
|
const translations: Record<string, Record<string, string>> = {
|
|
widgets: {
|
|
'tabs.navLabel': 'Dashboard-Reiter',
|
|
'tabs.add': 'Dashboard hinzufügen',
|
|
'tabs.renameButtonLabel': 'Dashboard umbenennen',
|
|
'tabs.renameInputLabel': 'Name des Dashboards',
|
|
'tabs.deleteButtonLabel': 'Dashboard löschen',
|
|
'tabs.deleteDialogTitle': 'Dashboard löschen',
|
|
'tabs.deleteDialogBody': 'Möchten Sie das Dashboard „{name}“ wirklich löschen?',
|
|
'tabs.dragHint': 'Ziehen Sie einen Reiter, um ihn zum Standard zu machen.',
|
|
},
|
|
common: {
|
|
cancel: 'Abbrechen',
|
|
delete: 'Löschen',
|
|
},
|
|
};
|
|
let text = translations[namespace]?.[key] ?? key;
|
|
if (params) {
|
|
for (const [k, v] of Object.entries(params)) {
|
|
text = text.replace(`{${k}}`, v);
|
|
}
|
|
}
|
|
return text;
|
|
},
|
|
}));
|
|
|
|
import { DashboardTabs } from './dashboard-tabs';
|
|
|
|
const DASHBOARDS = [
|
|
{ id: 'd1', name: 'Dashboard', position: 0 },
|
|
{ id: 'd2', name: 'Dashboard 2', position: 1 },
|
|
];
|
|
|
|
const THREE_DASHBOARDS = [
|
|
{ id: 'd1', name: 'Dashboard', position: 0 },
|
|
{ id: 'd2', name: 'Dashboard 2', position: 1 },
|
|
{ id: 'd3', name: 'Dashboard 3', position: 2 },
|
|
];
|
|
|
|
/**
|
|
* Stubbt `getBoundingClientRect` fuer JEDEN Reiter-Wrapper so, dass Reiter i
|
|
* (nach seiner AKTUELLEN Stelle im DOM, `data-tab-index`) die Spanne von
|
|
* i·100 bis i·100+100 belegt — echte Masse liefert jsdom hier nicht (Plan-
|
|
* Vorgabe, Task 4). Die Zeigerpositionen der Tests unten rechnen gegen
|
|
* genau diese Spannen.
|
|
*/
|
|
function stubTabRects() {
|
|
vi.spyOn(HTMLDivElement.prototype, 'getBoundingClientRect').mockImplementation(function (
|
|
this: HTMLDivElement,
|
|
) {
|
|
const idx = Number(this.dataset.tabIndex ?? '0');
|
|
return {
|
|
x: idx * 100,
|
|
y: 0,
|
|
left: idx * 100,
|
|
top: 0,
|
|
right: idx * 100 + 100,
|
|
bottom: 32,
|
|
width: 100,
|
|
height: 32,
|
|
toJSON() {
|
|
return {};
|
|
},
|
|
} as DOMRect;
|
|
});
|
|
}
|
|
|
|
function defaultProps(overrides: Partial<Parameters<typeof DashboardTabs>[0]> = {}) {
|
|
return {
|
|
dashboards: DASHBOARDS,
|
|
activeDashboardId: 'd1',
|
|
isEditMode: false,
|
|
onSelect: vi.fn(),
|
|
onCreate: vi.fn(),
|
|
onRename: vi.fn(),
|
|
onDelete: vi.fn(),
|
|
onReorder: vi.fn(),
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
// Seit quick-260924-h7x rendert die Leiste per Portal in den Einhaengepunkt
|
|
// der Kopfzeile — der Test legt ihn so an, wie `header.tsx` ihn rendert.
|
|
beforeEach(() => {
|
|
const slot = document.createElement('div');
|
|
slot.id = 'header-center-slot';
|
|
document.body.appendChild(slot);
|
|
});
|
|
|
|
afterEach(() => {
|
|
cleanup();
|
|
document.getElementById('header-center-slot')?.remove();
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
describe('DashboardTabs (quick-260923-ad9, Task 3)', () => {
|
|
it('Test 1: rendert jeden Reiter mit seinem Namen', () => {
|
|
render(<DashboardTabs {...defaultProps()} />);
|
|
|
|
expect(screen.getByRole('tab', { name: 'Dashboard' })).toBeInTheDocument();
|
|
expect(screen.getByRole('tab', { name: 'Dashboard 2' })).toBeInTheDocument();
|
|
});
|
|
|
|
it('Test 2: ein Klick auf einen Reiter ruft onSelect mit dessen Kennung auf', () => {
|
|
const onSelect = vi.fn();
|
|
render(<DashboardTabs {...defaultProps({ onSelect })} />);
|
|
|
|
fireEvent.click(screen.getByRole('tab', { name: 'Dashboard 2' }));
|
|
|
|
expect(onSelect).toHaveBeenCalledWith('d2');
|
|
});
|
|
|
|
it('Test 3: der aktive Reiter traegt aria-selected=true, der andere false', () => {
|
|
render(<DashboardTabs {...defaultProps()} />);
|
|
|
|
expect(screen.getByRole('tab', { name: 'Dashboard' })).toHaveAttribute('aria-selected', 'true');
|
|
expect(screen.getByRole('tab', { name: 'Dashboard 2' })).toHaveAttribute(
|
|
'aria-selected',
|
|
'false',
|
|
);
|
|
});
|
|
|
|
it('Test 4: ausserhalb des Bearbeitungsmodus gibt es weder Umbenennen- noch Loeschen- noch Hinzufuegen-Knoepfe', () => {
|
|
render(<DashboardTabs {...defaultProps({ isEditMode: false })} />);
|
|
|
|
expect(screen.queryByLabelText('Dashboard umbenennen')).not.toBeInTheDocument();
|
|
expect(screen.queryByLabelText('Dashboard löschen')).not.toBeInTheDocument();
|
|
expect(screen.queryByLabelText('Dashboard hinzufügen')).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('Test 5: im Bearbeitungsmodus mit mehreren Reitern sind Loeschen-Knoepfe und ein Hinzufuegen-Knopf da', () => {
|
|
render(<DashboardTabs {...defaultProps({ isEditMode: true })} />);
|
|
|
|
expect(screen.getAllByLabelText('Dashboard löschen')).toHaveLength(2);
|
|
expect(screen.getByLabelText('Dashboard hinzufügen')).toBeInTheDocument();
|
|
});
|
|
|
|
it('Test 6: beim letzten verbleibenden Reiter wird Loeschen gar nicht erst angeboten', () => {
|
|
render(<DashboardTabs {...defaultProps({ dashboards: [DASHBOARDS[0]], isEditMode: true })} />);
|
|
|
|
expect(screen.queryByLabelText('Dashboard löschen')).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('Test 7: der Hinzufuegen-Knopf ruft onCreate auf', () => {
|
|
const onCreate = vi.fn();
|
|
render(<DashboardTabs {...defaultProps({ isEditMode: true, onCreate })} />);
|
|
|
|
fireEvent.click(screen.getByLabelText('Dashboard hinzufügen'));
|
|
|
|
expect(onCreate).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('Test 8: Umbenennen-Knopf des AKTIVEN Reiters verwandelt den Namen in ein Eingabefeld; Enter uebernimmt beschnitten', () => {
|
|
const onRename = vi.fn();
|
|
render(<DashboardTabs {...defaultProps({ isEditMode: true, onRename })} />);
|
|
|
|
fireEvent.click(screen.getByLabelText('Dashboard umbenennen'));
|
|
const input = screen.getByLabelText('Name des Dashboards');
|
|
fireEvent.change(input, { target: { value: ' Finanzen ' } });
|
|
fireEvent.keyDown(input, { key: 'Enter' });
|
|
|
|
expect(onRename).toHaveBeenCalledWith('d1', 'Finanzen');
|
|
});
|
|
|
|
it('Test 9: Escape verwirft die Umbenennung, ohne onRename aufzurufen', () => {
|
|
const onRename = vi.fn();
|
|
render(<DashboardTabs {...defaultProps({ isEditMode: true, onRename })} />);
|
|
|
|
fireEvent.click(screen.getByLabelText('Dashboard umbenennen'));
|
|
const input = screen.getByLabelText('Name des Dashboards');
|
|
fireEvent.change(input, { target: { value: 'Verworfen' } });
|
|
fireEvent.keyDown(input, { key: 'Escape' });
|
|
|
|
expect(onRename).not.toHaveBeenCalled();
|
|
expect(screen.getByRole('tab', { name: 'Dashboard' })).toBeInTheDocument();
|
|
});
|
|
|
|
it('Test 10: der Umbenennen-Knopf steht nur beim AKTIVEN Reiter, nicht bei den anderen', () => {
|
|
render(<DashboardTabs {...defaultProps({ isEditMode: true })} />);
|
|
|
|
expect(screen.getAllByLabelText('Dashboard umbenennen')).toHaveLength(1);
|
|
});
|
|
|
|
it('Test 11: Loeschen fragt mit dem Namen des Reiters zurueck; Bestaetigen ruft onDelete auf', () => {
|
|
const onDelete = vi.fn();
|
|
render(<DashboardTabs {...defaultProps({ isEditMode: true, onDelete })} />);
|
|
|
|
fireEvent.click(screen.getAllByLabelText('Dashboard löschen')[1]);
|
|
const dialog = screen.getByRole('alertdialog');
|
|
expect(dialog).toHaveTextContent('Dashboard 2');
|
|
|
|
fireEvent.click(within(dialog).getByRole('button', { name: 'Löschen' }));
|
|
|
|
expect(onDelete).toHaveBeenCalledWith('d2');
|
|
});
|
|
|
|
it('Test 12: Abbrechen im Loeschdialog ruft onDelete NICHT auf', () => {
|
|
const onDelete = vi.fn();
|
|
render(<DashboardTabs {...defaultProps({ isEditMode: true, onDelete })} />);
|
|
|
|
fireEvent.click(screen.getAllByLabelText('Dashboard löschen')[0]);
|
|
const dialog = screen.getByRole('alertdialog');
|
|
fireEvent.click(within(dialog).getByRole('button', { name: 'Abbrechen' }));
|
|
|
|
expect(onDelete).not.toHaveBeenCalled();
|
|
expect(screen.queryByRole('alertdialog')).not.toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
describe('DashboardTabs — Ziehen zum Umsortieren (quick-260923-ad9, Task 4)', () => {
|
|
it('Test 13: Druecken und Loslassen OHNE nennenswerte Bewegung sendet KEINE neue Reihenfolge (der nachfolgende Klick waehlt weiterhin)', () => {
|
|
stubTabRects();
|
|
const onReorder = vi.fn();
|
|
const onSelect = vi.fn();
|
|
render(<DashboardTabs {...defaultProps({ onReorder, onSelect })} />);
|
|
const tab = screen.getByTestId('dashboard-tab-d2');
|
|
|
|
fireEvent.pointerDown(tab, { clientX: 150, pointerId: 1, button: 0 });
|
|
fireEvent.pointerUp(tab, { clientX: 150, pointerId: 1 });
|
|
|
|
expect(onReorder).not.toHaveBeenCalled();
|
|
|
|
fireEvent.click(screen.getByRole('tab', { name: 'Dashboard 2' }));
|
|
expect(onSelect).toHaveBeenCalledWith('d2');
|
|
});
|
|
|
|
it('Test 14: Druecken, mehr als die Schwelle nach RECHTS bewegen und loslassen verschiebt den Reiter hinter seinen rechten Nachbarn', () => {
|
|
stubTabRects();
|
|
const onReorder = vi.fn();
|
|
render(<DashboardTabs {...defaultProps({ dashboards: DASHBOARDS, onReorder })} />);
|
|
const tab = screen.getByTestId('dashboard-tab-d1'); // Spanne 0..100
|
|
|
|
fireEvent.pointerDown(tab, { clientX: 10, pointerId: 1, button: 0 });
|
|
// ueber die Schwelle hinaus, weit rechts von d2s Mittelpunkt (150)
|
|
fireEvent.pointerMove(tab, { clientX: 180, pointerId: 1 });
|
|
fireEvent.pointerUp(tab, { clientX: 180, pointerId: 1 });
|
|
|
|
expect(onReorder).toHaveBeenCalledWith(['d2', 'd1']);
|
|
});
|
|
|
|
it('Test 15: dasselbe nach LINKS verschiebt vor den linken Nachbarn', () => {
|
|
stubTabRects();
|
|
const onReorder = vi.fn();
|
|
render(<DashboardTabs {...defaultProps({ dashboards: DASHBOARDS, onReorder })} />);
|
|
const tab = screen.getByTestId('dashboard-tab-d2'); // Spanne 100..200
|
|
|
|
fireEvent.pointerDown(tab, { clientX: 150, pointerId: 1, button: 0 });
|
|
// weit links von d1s Mittelpunkt (50)
|
|
fireEvent.pointerMove(tab, { clientX: 10, pointerId: 1 });
|
|
fireEvent.pointerUp(tab, { clientX: 10, pointerId: 1 });
|
|
|
|
expect(onReorder).toHaveBeenCalledWith(['d2', 'd1']);
|
|
});
|
|
|
|
it('Test 16: waehrend des Ziehens zeigt die Leiste die Vorschau-Reihenfolge; Abbruch des Zeigers verwirft sie, ohne zu senden', () => {
|
|
stubTabRects();
|
|
const onReorder = vi.fn();
|
|
render(<DashboardTabs {...defaultProps({ dashboards: DASHBOARDS, onReorder })} />);
|
|
const tab = screen.getByTestId('dashboard-tab-d1');
|
|
|
|
fireEvent.pointerDown(tab, { clientX: 10, pointerId: 1, button: 0 });
|
|
fireEvent.pointerMove(tab, { clientX: 180, pointerId: 1 });
|
|
|
|
// Vorschau: d2 steht jetzt vor d1 im DOM.
|
|
const buttons = screen
|
|
.getAllByRole('tab')
|
|
.filter((b) => b.textContent === 'Dashboard' || b.textContent === 'Dashboard 2');
|
|
expect(buttons.map((b) => b.textContent)).toEqual(['Dashboard 2', 'Dashboard']);
|
|
|
|
fireEvent.pointerCancel(tab, { pointerId: 1 });
|
|
|
|
expect(onReorder).not.toHaveBeenCalled();
|
|
const buttonsAfterCancel = screen
|
|
.getAllByRole('tab')
|
|
.filter((b) => b.textContent === 'Dashboard' || b.textContent === 'Dashboard 2');
|
|
expect(buttonsAfterCancel.map((b) => b.textContent)).toEqual(['Dashboard', 'Dashboard 2']);
|
|
});
|
|
|
|
it('Test 17: ein Ziehen, das den ersten Reiter verdraengt, macht den vorgezogenen Reiter zum ersten in der gesendeten Liste', () => {
|
|
stubTabRects();
|
|
const onReorder = vi.fn();
|
|
render(<DashboardTabs {...defaultProps({ dashboards: THREE_DASHBOARDS, onReorder })} />);
|
|
const tab = screen.getByTestId('dashboard-tab-d3'); // Spanne 200..300
|
|
|
|
fireEvent.pointerDown(tab, { clientX: 250, pointerId: 1, button: 0 });
|
|
// weit links von d1s Mittelpunkt (50) -> wird der neue Erste
|
|
fireEvent.pointerMove(tab, { clientX: 5, pointerId: 1 });
|
|
fireEvent.pointerUp(tab, { clientX: 5, pointerId: 1 });
|
|
|
|
expect(onReorder).toHaveBeenCalledWith(['d3', 'd1', 'd2']);
|
|
});
|
|
|
|
it('Test 18: der aktive Reiter bleibt beim Ziehen aktiv, auch wenn er seine Position wechselt', () => {
|
|
stubTabRects();
|
|
render(
|
|
<DashboardTabs
|
|
{...defaultProps({ dashboards: DASHBOARDS, activeDashboardId: 'd1', onReorder: vi.fn() })}
|
|
/>,
|
|
);
|
|
const tab = screen.getByTestId('dashboard-tab-d1');
|
|
|
|
fireEvent.pointerDown(tab, { clientX: 10, pointerId: 1, button: 0 });
|
|
fireEvent.pointerMove(tab, { clientX: 180, pointerId: 1 });
|
|
|
|
expect(screen.getByRole('tab', { name: 'Dashboard' })).toHaveAttribute('aria-selected', 'true');
|
|
});
|
|
|
|
it('Test 19: nach einem echten Ziehen unterdrueckt der naechste Klick die Auswahl EINMAL, danach funktioniert Klicken wieder normal', () => {
|
|
stubTabRects();
|
|
const onSelect = vi.fn();
|
|
const onReorder = vi.fn();
|
|
render(<DashboardTabs {...defaultProps({ dashboards: DASHBOARDS, onSelect, onReorder })} />);
|
|
const tab = screen.getByTestId('dashboard-tab-d1');
|
|
|
|
fireEvent.pointerDown(tab, { clientX: 10, pointerId: 1, button: 0 });
|
|
fireEvent.pointerMove(tab, { clientX: 180, pointerId: 1 });
|
|
fireEvent.pointerUp(tab, { clientX: 180, pointerId: 1 });
|
|
expect(onReorder).toHaveBeenCalledTimes(1);
|
|
|
|
// Ein echter Browser wuerde nach dem Ziehen noch einen "click" nachreichen.
|
|
fireEvent.click(screen.getByRole('tab', { name: 'Dashboard' }));
|
|
expect(onSelect).not.toHaveBeenCalled();
|
|
|
|
fireEvent.click(screen.getByRole('tab', { name: 'Dashboard' }));
|
|
expect(onSelect).toHaveBeenCalledWith('d1');
|
|
});
|
|
|
|
it('Test 20: der Hinweistext zum Ziehen steht bei mehr als einem Reiter, aber nicht bei genau einem', () => {
|
|
const { rerender } = render(<DashboardTabs {...defaultProps({ dashboards: DASHBOARDS })} />);
|
|
expect(
|
|
screen.getByText('Ziehen Sie einen Reiter, um ihn zum Standard zu machen.'),
|
|
).toBeInTheDocument();
|
|
|
|
rerender(<DashboardTabs {...defaultProps({ dashboards: [DASHBOARDS[0]] })} />);
|
|
expect(
|
|
screen.queryByText('Ziehen Sie einen Reiter, um ihn zum Standard zu machen.'),
|
|
).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('Test 21: Ziehen ist auch AUSSERHALB des Bearbeitungsmodus moeglich (D-09)', () => {
|
|
stubTabRects();
|
|
const onReorder = vi.fn();
|
|
render(
|
|
<DashboardTabs {...defaultProps({ dashboards: DASHBOARDS, isEditMode: false, onReorder })} />,
|
|
);
|
|
const tab = screen.getByTestId('dashboard-tab-d1');
|
|
|
|
fireEvent.pointerDown(tab, { clientX: 10, pointerId: 1, button: 0 });
|
|
fireEvent.pointerMove(tab, { clientX: 180, pointerId: 1 });
|
|
fireEvent.pointerUp(tab, { clientX: 180, pointerId: 1 });
|
|
|
|
expect(onReorder).toHaveBeenCalledWith(['d2', 'd1']);
|
|
});
|
|
});
|
|
|
|
describe('DashboardTabs — in der Kopfzeile (quick-260924-h7x)', () => {
|
|
it('Test 22: rendert in den Einhaengepunkt der Kopfzeile, nicht an Ort und Stelle', () => {
|
|
const { container } = render(<DashboardTabs {...defaultProps()} />);
|
|
|
|
const slot = document.getElementById('header-center-slot') as HTMLElement;
|
|
expect(within(slot).getByRole('navigation', { name: 'Dashboard-Reiter' })).toBeInTheDocument();
|
|
expect(within(slot).getByRole('tablist')).toBeInTheDocument();
|
|
expect(container).toBeEmptyDOMElement();
|
|
});
|
|
|
|
it('Test 23: ohne Einhaengepunkt rendert die Leiste gar nichts', () => {
|
|
document.getElementById('header-center-slot')?.remove();
|
|
render(<DashboardTabs {...defaultProps()} />);
|
|
|
|
expect(screen.queryByRole('tablist')).not.toBeInTheDocument();
|
|
expect(screen.queryByRole('tab')).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('Test 24: Pfeiltasten wandern zwischen den Reitern (mit Umlauf), ohne zu waehlen; nur der aktive ist per Tab erreichbar', () => {
|
|
const onSelect = vi.fn();
|
|
render(<DashboardTabs {...defaultProps({ dashboards: THREE_DASHBOARDS, onSelect })} />);
|
|
const [t1, t2, t3] = screen.getAllByRole('tab');
|
|
|
|
expect(t1).toHaveAttribute('tabindex', '0');
|
|
expect(t2).toHaveAttribute('tabindex', '-1');
|
|
expect(t3).toHaveAttribute('tabindex', '-1');
|
|
|
|
t1.focus();
|
|
fireEvent.keyDown(t1, { key: 'ArrowRight' });
|
|
expect(t2).toHaveFocus();
|
|
fireEvent.keyDown(t2, { key: 'ArrowRight' });
|
|
expect(t3).toHaveFocus();
|
|
fireEvent.keyDown(t3, { key: 'ArrowRight' });
|
|
expect(t1).toHaveFocus();
|
|
fireEvent.keyDown(t1, { key: 'ArrowLeft' });
|
|
expect(t3).toHaveFocus();
|
|
fireEvent.keyDown(t3, { key: 'Home' });
|
|
expect(t1).toHaveFocus();
|
|
fireEvent.keyDown(t1, { key: 'End' });
|
|
expect(t3).toHaveFocus();
|
|
|
|
expect(onSelect).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('Test 25: genau ein Reiter — der Umschalter steht trotzdem, im Bearbeitungsmodus nur mit „+“ daneben', () => {
|
|
render(<DashboardTabs {...defaultProps({ dashboards: [DASHBOARDS[0]], isEditMode: true })} />);
|
|
|
|
expect(screen.getByRole('tab', { name: 'Dashboard' })).toBeInTheDocument();
|
|
expect(screen.getByLabelText('Dashboard hinzufügen')).toBeInTheDocument();
|
|
expect(screen.queryByLabelText('Dashboard löschen')).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('Test 26: „+“ sitzt ausserhalb der scrollenden Spur und bleibt so immer sichtbar', () => {
|
|
render(<DashboardTabs {...defaultProps({ isEditMode: true })} />);
|
|
|
|
const tablist = screen.getByRole('tablist');
|
|
expect(tablist).not.toContainElement(screen.getByLabelText('Dashboard hinzufügen'));
|
|
});
|
|
|
|
it('Test 27: der Loeschdialog haengt am Dokumentkoerper, nicht in der Kopfzeile', () => {
|
|
render(<DashboardTabs {...defaultProps({ isEditMode: true })} />);
|
|
|
|
fireEvent.click(screen.getAllByLabelText('Dashboard löschen')[0]);
|
|
const dialog = screen.getByRole('alertdialog');
|
|
const slot = document.getElementById('header-center-slot') as HTMLElement;
|
|
expect(slot).not.toContainElement(dialog);
|
|
});
|
|
});
|