diff --git a/frontend/src/lib/timeline/EventNote.svelte b/frontend/src/lib/timeline/EventNote.svelte new file mode 100644 index 00000000..96672d78 --- /dev/null +++ b/frontend/src/lib/timeline/EventNote.svelte @@ -0,0 +1,47 @@ + + +{#if hasContent} +
+

+ {description} +

+ {#if clamped || expanded} + + {/if} +
+{/if} diff --git a/frontend/src/lib/timeline/event-note.svelte.spec.ts b/frontend/src/lib/timeline/event-note.svelte.spec.ts new file mode 100644 index 00000000..80124e47 --- /dev/null +++ b/frontend/src/lib/timeline/event-note.svelte.spec.ts @@ -0,0 +1,74 @@ +import { describe, it, expect, afterEach } from 'vitest'; +import { cleanup, render } from 'vitest-browser-svelte'; +import { tick } from 'svelte'; +import * as m from '$lib/paraglide/messages.js'; +import EventNote from './EventNote.svelte'; + +afterEach(() => cleanup()); + +const LONG_NOTE = Array.from({ length: 15 }, (_, i) => `Zeile ${i + 1}`).join('\n'); + +describe('EventNote (REQ-002–008)', () => { + it('escapesHtml — renders XSS payload as inert text, no injected element (REQ-002)', () => { + render(EventNote, { description: '' }); + // The literal string should appear as text content + expect(document.body.textContent).toContain(''); + // No injected