fix(notification): replace view-all anchor with button to prevent iframe navigation #552

Merged
marcel merged 5 commits from feat/issue-545-notification-dropdown-iframe-fix into main 2026-05-12 18:56:14 +02:00
2 changed files with 24 additions and 10 deletions
Showing only changes of commit 8ccc9aba1a - Show all commits

View File

@@ -13,8 +13,7 @@ type Props = {
let { notifications, onMarkRead, onMarkAllRead, onClose }: Props = $props(); let { notifications, onMarkRead, onMarkAllRead, onClose }: Props = $props();
function handleViewAll(e: MouseEvent) { function handleViewAll() {
e.preventDefault();
onClose(); onClose();
goto('/aktivitaeten'); goto('/aktivitaeten');
} }
@@ -134,12 +133,12 @@ function handleViewAll(e: MouseEvent) {
{/if} {/if}
<div class="border-t border-line px-4 py-2"> <div class="border-t border-line px-4 py-2">
<a <button
href="/aktivitaeten" type="button"
onclick={handleViewAll} onclick={handleViewAll}
class="text-xs font-medium text-ink-2 transition-colors hover:text-ink" class="text-xs font-medium text-ink-2 transition-colors hover:text-ink"
> >
{m.chronik_view_all()} {m.chronik_view_all()}
</a> </button>
</div> </div>
</div> </div>

View File

@@ -6,7 +6,10 @@ import NotificationDropdown from './NotificationDropdown.svelte';
vi.mock('$app/navigation', () => ({ goto: vi.fn() })); vi.mock('$app/navigation', () => ({ goto: vi.fn() }));
afterEach(cleanup); afterEach(() => {
cleanup();
vi.clearAllMocks();
});
const makeNotification = (overrides: Record<string, unknown> = {}) => ({ const makeNotification = (overrides: Record<string, unknown> = {}) => ({
id: 'n1', id: 'n1',
@@ -156,7 +159,7 @@ describe('NotificationDropdown', () => {
expect(onMarkAllRead).toHaveBeenCalledOnce(); expect(onMarkAllRead).toHaveBeenCalledOnce();
}); });
it('calls onClose when the view-all link is clicked', async () => { it('calls onClose when the view-all button is clicked', async () => {
const onClose = vi.fn(); const onClose = vi.fn();
render(NotificationDropdown, { render(NotificationDropdown, {
props: { props: {
@@ -167,11 +170,23 @@ describe('NotificationDropdown', () => {
} }
}); });
const viewAllLink = page.getByRole('link', { name: /alle aktivitäten|view all/i }); await page.getByRole('button', { name: /alle aktivitäten|view all/i }).click();
await expect.element(viewAllLink).toHaveAttribute('href', '/aktivitaeten');
await viewAllLink.click();
expect(onClose).toHaveBeenCalledOnce(); expect(onClose).toHaveBeenCalledOnce();
});
it('navigates to /aktivitaeten when the view-all button is clicked', async () => {
render(NotificationDropdown, {
props: {
notifications: [],
onMarkRead: () => {},
onMarkAllRead: () => {},
onClose: () => {}
}
});
await page.getByRole('button', { name: /alle aktivitäten|view all/i }).click();
expect(goto).toHaveBeenCalledWith('/aktivitaeten'); expect(goto).toHaveBeenCalledWith('/aktivitaeten');
}); });