diff --git a/frontend/src/lib/shared/discussion/CommentMessage.svelte.test.ts b/frontend/src/lib/shared/discussion/CommentMessage.svelte.test.ts new file mode 100644 index 00000000..e5c00c67 --- /dev/null +++ b/frontend/src/lib/shared/discussion/CommentMessage.svelte.test.ts @@ -0,0 +1,93 @@ +import { describe, it, expect, vi, afterEach } from 'vitest'; +import { cleanup, render } from 'vitest-browser-svelte'; +import { page } from 'vitest/browser'; +import CommentMessage from './CommentMessage.svelte'; + +afterEach(cleanup); + +const baseMessage = (overrides: Record = {}) => ({ + id: 'm1', + authorId: 'u1', + authorName: 'Anna Schmidt', + content: 'Tolle Geschichte!', + createdAt: '2026-04-15T10:00:00Z', + updatedAt: '2026-04-15T10:00:00Z', + mentionDTOs: [] as unknown[], + ...overrides +}); + +const baseProps = (overrides: Record = {}) => ({ + message: baseMessage(), + isOwn: false, + isEditing: false, + editText: '', + onEdit: () => {}, + onDelete: () => {}, + onEditTextChange: () => {}, + onEditKeydown: () => {}, + ...overrides +}); + +describe('CommentMessage', () => { + it('renders the author name and avatar initials', async () => { + render(CommentMessage, { props: baseProps() }); + + await expect.element(page.getByText('Anna Schmidt')).toBeVisible(); + await expect.element(page.getByText('AS')).toBeVisible(); + }); + + it('renders the comment body', async () => { + render(CommentMessage, { props: baseProps() }); + + await expect.element(page.getByText('Tolle Geschichte!')).toBeVisible(); + }); + + it('shows the edited label when updatedAt > createdAt', async () => { + render(CommentMessage, { + props: baseProps({ + message: baseMessage({ + createdAt: '2026-04-15T10:00:00Z', + updatedAt: '2026-04-15T11:00:00Z' + }) + }) + }); + + await expect.element(page.getByText('(Bearbeitet)')).toBeVisible(); + }); + + it('hides the edited label when updatedAt equals createdAt', async () => { + render(CommentMessage, { props: baseProps() }); + + await expect.element(page.getByText('(Bearbeitet)')).not.toBeInTheDocument(); + }); + + it('shows the textarea when in edit mode', async () => { + render(CommentMessage, { + props: baseProps({ isOwn: true, isEditing: true, editText: 'Editing content' }) + }); + + const textarea = document.querySelector('textarea') as HTMLTextAreaElement; + expect(textarea.value).toBe('Editing content'); + }); + + it('shows the delete button only when isOwn is true', async () => { + render(CommentMessage, { props: baseProps({ isOwn: true }) }); + + await expect.element(page.getByRole('button', { name: /löschen anna schmidt/i })).toBeVisible(); + }); + + it('hides the delete button when isOwn is false', async () => { + render(CommentMessage, { props: baseProps() }); + + await expect.element(page.getByRole('button', { name: /löschen/i })).not.toBeInTheDocument(); + }); + + it('calls onDelete when the delete button is clicked', async () => { + const onDelete = vi.fn(); + render(CommentMessage, { props: baseProps({ isOwn: true, onDelete }) }); + + await page.getByRole('button', { name: /löschen anna schmidt/i }).click(); + + expect(onDelete).toHaveBeenCalledOnce(); + }); +});