diff --git a/__tests__/components/dialogs/answer-modal.test.tsx b/__tests__/components/dialogs/answer-modal.test.tsx
new file mode 100644
index 0000000..26aad0f
--- /dev/null
+++ b/__tests__/components/dialogs/answer-modal.test.tsx
@@ -0,0 +1,104 @@
+// @vitest-environment jsdom
+import { describe, it, expect, vi, beforeEach } from 'vitest'
+import { render, screen, fireEvent, waitFor } from '@testing-library/react'
+import React from 'react'
+
+vi.mock('@/actions/questions', () => ({
+ answerQuestion: vi.fn(),
+}))
+vi.mock('sonner', () => ({ toast: { success: vi.fn(), error: vi.fn() } }))
+vi.mock('@/stores/notifications-store', () => ({
+ useNotificationsStore: {
+ getState: () => ({ remove: vi.fn() }),
+ },
+}))
+vi.mock('next/link', () => ({
+ default: ({ href, children }: { href: string; children: React.ReactNode }) => (
+ {children}
+ ),
+}))
+
+import { AnswerModal } from '@/components/notifications/answer-modal'
+import { answerQuestion } from '@/actions/questions'
+import { toast } from 'sonner'
+import type { NotificationQuestion } from '@/stores/notifications-store'
+
+const mockAnswerQuestion = answerQuestion as ReturnType
+const mockToast = toast as unknown as {
+ success: ReturnType
+ error: ReturnType
+}
+
+const QUESTION: NotificationQuestion = {
+ kind: 'idea',
+ id: 'q-1',
+ product_id: 'prod-1',
+ idea_id: 'idea-1',
+ idea_code: 'IDEA-42',
+ idea_title: 'Mijn Idee',
+ question: 'Wat denk jij?',
+ options: ['Optie A', 'Optie B'],
+ created_at: '2026-01-01T00:00:00Z',
+ expires_at: '2026-12-31T00:00:00Z',
+}
+
+beforeEach(() => {
+ vi.clearAllMocks()
+})
+
+describe('AnswerModal — met opties', () => {
+ it('toont optieknoppen, textarea en Verstuur-knop', () => {
+ render()
+ expect(screen.getByRole('button', { name: 'Optie A' })).toBeTruthy()
+ expect(screen.getByRole('button', { name: 'Optie B' })).toBeTruthy()
+ expect(screen.getByLabelText(/Antwoord op Claude/)).toBeTruthy()
+ expect(screen.getByRole('button', { name: 'Verstuur' })).toBeTruthy()
+ })
+
+ it('roept answerQuestion aan met optiewaarde bij klik op optieknop', async () => {
+ mockAnswerQuestion.mockResolvedValue({ ok: true })
+ render()
+
+ fireEvent.click(screen.getByRole('button', { name: 'Optie A' }))
+
+ await waitFor(() => {
+ expect(mockAnswerQuestion).toHaveBeenCalledWith('q-1', 'Optie A')
+ })
+ })
+
+ it('roept answerQuestion aan met getypte tekst bij klik op Verstuur', async () => {
+ mockAnswerQuestion.mockResolvedValue({ ok: true })
+ render()
+
+ fireEvent.change(screen.getByLabelText(/Antwoord op Claude/), {
+ target: { value: 'Mijn eigen antwoord' },
+ })
+ fireEvent.click(screen.getByRole('button', { name: 'Verstuur' }))
+
+ await waitFor(() => {
+ expect(mockAnswerQuestion).toHaveBeenCalledWith('q-1', 'Mijn eigen antwoord')
+ })
+ })
+
+ it('Verstuur-knop is disabled zolang het tekstveld leeg is', () => {
+ render()
+ expect(screen.getByRole('button', { name: 'Verstuur' })).toHaveProperty('disabled', true)
+ })
+})
+
+describe('AnswerModal — demo-modus', () => {
+ it('textarea is disabled en Verstuur is disabled bij isDemo=true', () => {
+ render()
+ expect(screen.getByLabelText(/Antwoord op Claude/)).toHaveProperty('disabled', true)
+ expect(screen.getByRole('button', { name: 'Verstuur' })).toHaveProperty('disabled', true)
+ })
+})
+
+describe('AnswerModal — geen vraag', () => {
+ it('rendert niets wanneer question null is', () => {
+ const { container } = render(
+ ,
+ )
+ expect(container.firstChild).toBeNull()
+ })
+})