import { describe, it, expect, vi, afterEach } from 'vitest'; import { cleanup, render } from 'vitest-browser-svelte'; import { page, userEvent } from 'vitest/browser'; import CommentMessage from './CommentMessage.svelte'; import type { FlatMessage } from '$lib/types'; afterEach(cleanup); const baseMsg: FlatMessage = { id: 'msg-1', authorId: 'user-1', authorName: 'Anna Müller', content: 'Hello world', createdAt: new Date(Date.now() - 5 * 60_000).toISOString(), updatedAt: new Date(Date.now() - 5 * 60_000).toISOString() }; function defaultProps(overrides: Partial[1]> = {}) { return { message: baseMsg, isOwn: false, isEditing: false, editText: '', onEdit: vi.fn(), onDelete: vi.fn(), onEditTextChange: vi.fn(), onEditKeydown: vi.fn(), ...overrides }; } describe('CommentMessage', () => { it('renders author name', async () => { render(CommentMessage, defaultProps()); await expect.element(page.getByText('Anna Müller')).toBeInTheDocument(); }); it('renders initials in avatar', async () => { render(CommentMessage, defaultProps()); await expect.element(page.getByText('AM')).toBeInTheDocument(); }); it('renders message body', async () => { render(CommentMessage, defaultProps()); await expect.element(page.getByText('Hello world')).toBeInTheDocument(); }); it('renders quoted section when content contains a quote', async () => { render( CommentMessage, defaultProps({ message: { ...baseMsg, content: '> "Interesting passage"\n\nMy reply' } }) ); await expect.element(page.getByText(/Interesting passage/)).toBeInTheDocument(); await expect.element(page.getByText('My reply')).toBeInTheDocument(); }); it('does not show delete button for messages not owned by current user', async () => { render(CommentMessage, defaultProps({ isOwn: false })); await expect.element(page.getByRole('button')).not.toBeInTheDocument(); }); it('shows delete button for own messages', async () => { render(CommentMessage, defaultProps({ isOwn: true })); await expect.element(page.getByRole('button')).toBeInTheDocument(); }); it('calls onDelete when delete button is clicked', async () => { const onDelete = vi.fn(); render(CommentMessage, defaultProps({ isOwn: true, onDelete })); await userEvent.click(page.getByRole('button')); expect(onDelete).toHaveBeenCalled(); }); it('shows edit textarea when isEditing is true', async () => { render( CommentMessage, defaultProps({ isOwn: true, isEditing: true, editText: 'current edit text' }) ); const textarea = page.getByRole('textbox'); await expect.element(textarea).toBeInTheDocument(); await expect.element(textarea).toHaveValue('current edit text'); }); });