fix(notification): add role=link and touch target to view-all button
Some checks failed
CI / Backend Unit Tests (push) Successful in 4m15s
CI / fail2ban Regex (push) Successful in 39s
CI / Compose Bucket Idempotency (push) Failing after 11s
CI / OCR Service Tests (pull_request) Successful in 17s
CI / Backend Unit Tests (pull_request) Successful in 4m17s
CI / Unit & Component Tests (push) Failing after 1m48s
CI / OCR Service Tests (push) Successful in 17s
CI / Unit & Component Tests (pull_request) Failing after 2m3s
CI / fail2ban Regex (pull_request) Successful in 40s
CI / Compose Bucket Idempotency (pull_request) Failing after 11s

- role="link" restores screen reader link semantics (Leonie blocker)
- min-h-[44px] px-1 meets WCAG 2.2 §2.5.8 and our 44×48px target size
- Comment in handleViewAll explains close-before-navigate ordering
- Tests updated to getByRole('link') + new call-order assertion

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-05-12 16:51:28 +02:00
parent 3005782a75
commit bc2dd3a98a
2 changed files with 25 additions and 6 deletions

View File

@@ -159,7 +159,7 @@ describe('NotificationDropdown', () => {
expect(onMarkAllRead).toHaveBeenCalledOnce();
});
it('calls onClose when the view-all button is clicked', async () => {
it('calls onClose when the view-all link is clicked', async () => {
const onClose = vi.fn();
render(NotificationDropdown, {
props: {
@@ -170,12 +170,12 @@ describe('NotificationDropdown', () => {
}
});
await page.getByRole('button', { name: /alle aktivitäten|view all/i }).click();
await page.getByRole('link', { name: /alle aktivitäten|view all/i }).click();
expect(onClose).toHaveBeenCalledOnce();
});
it('navigates to /aktivitaeten when the view-all button is clicked', async () => {
it('navigates to /aktivitaeten when the view-all link is clicked', async () => {
render(NotificationDropdown, {
props: {
notifications: [],
@@ -185,11 +185,29 @@ describe('NotificationDropdown', () => {
}
});
await page.getByRole('button', { name: /alle aktivitäten|view all/i }).click();
await page.getByRole('link', { name: /alle aktivitäten|view all/i }).click();
expect(goto).toHaveBeenCalledWith('/aktivitaeten');
});
it('calls onClose before navigating to /aktivitaeten', async () => {
const callOrder: string[] = [];
const onClose = vi.fn(() => callOrder.push('close'));
(goto as ReturnType<typeof vi.fn>).mockImplementation(() => callOrder.push('goto'));
render(NotificationDropdown, {
props: {
notifications: [],
onMarkRead: () => {},
onMarkAllRead: () => {},
onClose
}
});
await page.getByRole('link', { name: /alle aktivitäten|view all/i }).click();
expect(callOrder).toEqual(['close', 'goto']);
});
it('renders MENTION items with the mention verb text', async () => {
render(NotificationDropdown, {
props: {