import { Node } from 'prosemirror-model'; import { describe, expect, it } from 'vitest'; import { docToHtml } from './html'; import { docToMarkdown, markdownToDoc } from './markdown'; import { extractMentionUserIds } from './mentions'; import { docToPlainText } from './plain-text'; import { editorSchema } from './schema'; function firstMention(doc: Node): Node | null { let found: Node | null = null; doc.descendants((node) => { if (!found && node.type.name === 'mention') found = node; }); return found; } describe('@username mention (issue #150)', () => { it('parses @username to a mention node and round-trips', () => { const doc = markdownToDoc('Hallo @nadia, schau mal.'); const node = firstMention(doc); expect(node).not.toBeNull(); expect(node!.attrs.username).toBe('nadia'); expect(node!.attrs.userId).toBe(''); expect(docToMarkdown(doc)).toContain('@nadia'); }); it('leaves e-mail addresses untouched', () => { const doc = markdownToDoc('Schreib an stefan@example.org bitte.'); expect(firstMention(doc)).toBeNull(); expect(docToMarkdown(doc)).toContain('stefan@example.org'); }); it('renders HTML with the username and optional user id', () => { const doc = markdownToDoc('Ping @zoraya-shahin!'); expect(docToHtml(doc)).toContain('class="dt-mention" data-mention="zoraya-shahin"'); expect(docToHtml(doc)).toContain('@zoraya-shahin'); }); it('appears in the plain text for search', () => { expect(docToPlainText(markdownToDoc('Frag @nadia.'))).toContain('@nadia'); }); it('extracts only resolved user ids', () => { const doc = Node.fromJSON(editorSchema, { type: 'doc', content: [ { type: 'paragraph', content: [ { type: 'mention', attrs: { userId: 'u-1', username: 'nadia' } }, { type: 'text', text: ' und ' }, { type: 'mention', attrs: { userId: '', username: 'import-only' } }, { type: 'text', text: ' und nochmal ' }, { type: 'mention', attrs: { userId: 'u-1', username: 'nadia' } }, ], }, ], }); expect(extractMentionUserIds(doc)).toEqual(['u-1']); }); });