diff --git a/frontend/src/lib/shared/discussion/MentionEditor.svelte.test.ts b/frontend/src/lib/shared/discussion/MentionEditor.svelte.test.ts index e4077e2c..8d9081a9 100644 --- a/frontend/src/lib/shared/discussion/MentionEditor.svelte.test.ts +++ b/frontend/src/lib/shared/discussion/MentionEditor.svelte.test.ts @@ -222,4 +222,71 @@ describe('MentionEditor', () => { const popup = document.querySelector('[role="listbox"]'); expect(popup).not.toBeNull(); }); + + it('selects a user via mousedown click and fills the textarea', async () => { + render(MentionEditor, { + props: { value: '', mentionCandidates: [] } + }); + + const ta = document.querySelector('textarea') as HTMLTextAreaElement; + ta.focus(); + ta.value = '@An'; + ta.selectionStart = 3; + ta.selectionEnd = 3; + ta.dispatchEvent(new Event('input', { bubbles: true })); + await new Promise((r) => setTimeout(r, 350)); + + const firstOption = document.querySelector('[role="option"]') as HTMLElement; + firstOption?.dispatchEvent(new MouseEvent('mousedown', { bubbles: true })); + + await new Promise((r) => setTimeout(r, 50)); + // After select, popup is closed + const popup = document.querySelector('[role="listbox"]'); + expect(popup).toBeNull(); + }); + + it('selects via Enter when results are present', async () => { + render(MentionEditor, { + props: { value: '', mentionCandidates: [] } + }); + + const ta = document.querySelector('textarea') as HTMLTextAreaElement; + ta.focus(); + ta.value = '@An'; + ta.selectionStart = 3; + ta.selectionEnd = 3; + ta.dispatchEvent(new Event('input', { bubbles: true })); + await new Promise((r) => setTimeout(r, 350)); + + // Move highlight to first result with ArrowDown then Enter + ta.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true })); + await new Promise((r) => setTimeout(r, 30)); + ta.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true })); + await new Promise((r) => setTimeout(r, 50)); + + // Popup closed after select + const popup = document.querySelector('[role="listbox"]'); + expect(popup).toBeNull(); + }); + + it('handles fetch network throw gracefully', async () => { + fetchSpy.mockImplementationOnce(async () => { + throw new Error('network down'); + }); + + render(MentionEditor, { + props: { value: '', mentionCandidates: [] } + }); + + const ta = document.querySelector('textarea') as HTMLTextAreaElement; + ta.focus(); + ta.value = '@An'; + ta.selectionStart = 3; + ta.selectionEnd = 3; + ta.dispatchEvent(new Event('input', { bubbles: true })); + + await new Promise((r) => setTimeout(r, 350)); + // Empty popup label after thrown fetch + await expect.element(page.getByText(/keine nutzer gefunden/i)).toBeVisible(); + }); });