From 4446e808753b0dcdee9bee73e1e533b65c70abab Mon Sep 17 00:00:00 2001 From: Marcel Date: Wed, 15 Apr 2026 12:46:04 +0200 Subject: [PATCH] test(actions): add defaultPrevented coverage for clickOutside (#195) The action already checks event.defaultPrevented before dispatching clickoutside, but that branch had no test. Add the missing case and add a one-line comment explaining why capture phase is used. Co-Authored-By: Claude Sonnet 4.6 --- frontend/src/lib/actions/clickOutside.svelte.spec.ts | 12 ++++++++++++ frontend/src/lib/actions/clickOutside.ts | 1 + 2 files changed, 13 insertions(+) diff --git a/frontend/src/lib/actions/clickOutside.svelte.spec.ts b/frontend/src/lib/actions/clickOutside.svelte.spec.ts index 81917cb0..1616b463 100644 --- a/frontend/src/lib/actions/clickOutside.svelte.spec.ts +++ b/frontend/src/lib/actions/clickOutside.svelte.spec.ts @@ -51,6 +51,18 @@ describe('clickOutside action', () => { expect(fired).toBe(false); }); + it('does not dispatch clickoutside when event.defaultPrevented is true', () => { + const node = makeNode(); + const outside = makeNode(); + let fired = false; + node.addEventListener('clickoutside', () => (fired = true)); + clickOutside(node); + const event = new MouseEvent('click', { bubbles: true, cancelable: true }); + event.preventDefault(); + outside.dispatchEvent(event); + expect(fired).toBe(false); + }); + it('removes the listener on destroy', () => { const node = makeNode(); const outside = makeNode(); diff --git a/frontend/src/lib/actions/clickOutside.ts b/frontend/src/lib/actions/clickOutside.ts index ef7fc3a2..018b4736 100644 --- a/frontend/src/lib/actions/clickOutside.ts +++ b/frontend/src/lib/actions/clickOutside.ts @@ -5,6 +5,7 @@ export function clickOutside(node: HTMLElement): { destroy: () => void } { } } + // Capture phase (true) ensures this fires before any child stopPropagation() calls. document.addEventListener('click', handleClick, true); return {