import { describe, it, expect, vi, afterEach } from 'vitest'; import '@testing-library/jest-dom/vitest'; import { render, cleanup, fireEvent } from '@solidjs/testing-library'; import { FeedbackBar } from './feedback-bar'; afterEach(cleanup); describe('FeedbackBar', () => { it('shows the prompt and rating buttons in the ask phase', () => { const { getByText, getByLabelText } = render(() => ); expect(getByText('Helpful?')).toBeInTheDocument(); expect(getByLabelText('Helpful')).toBeInTheDocument(); expect(getByLabelText('Not helpful')).toBeInTheDocument(); }); it('fires onFeedback immediately and confirms in place (no detail by default)', () => { const onFeedback = vi.fn(); const { getByLabelText, getByText, queryByLabelText } = render(() => ( )); fireEvent.click(getByLabelText('Helpful')); expect(onFeedback).toHaveBeenCalledWith('helpful'); // Confirms in place — does not disappear; the prompt is replaced by thanks. expect(getByText('Thanks for your feedback')).toBeInTheDocument(); expect(queryByLabelText('Helpful')).not.toBeInTheDocument(); }); it('a not-helpful vote goes straight to thanks when collectDetail is off', () => { const { getByLabelText, getByText, queryByText } = render(() => ); fireEvent.click(getByLabelText('Not helpful')); expect(getByText('Thanks for your feedback')).toBeInTheDocument(); expect(queryByText('What went wrong?')).not.toBeInTheDocument(); }); it('opens the detail form on a not-helpful vote when collectDetail is set', () => { const onFeedback = vi.fn(); const { getByLabelText, getByText } = render(() => ( )); fireEvent.click(getByLabelText('Not helpful')); // Vote still recorded immediately, AND the detail form appears. expect(onFeedback).toHaveBeenCalledWith('not-helpful'); expect(getByText('What went wrong?')).toBeInTheDocument(); expect(getByText('Inaccurate')).toBeInTheDocument(); }); it('a helpful vote skips the detail form even when collectDetail is set', () => { const { getByLabelText, getByText, queryByText } = render(() => ( )); fireEvent.click(getByLabelText('Helpful')); expect(getByText('Thanks for your feedback')).toBeInTheDocument(); expect(queryByText('What went wrong?')).not.toBeInTheDocument(); }); it('submits the detail form with the selected category and comment', () => { const onSubmitDetail = vi.fn(); const { getByLabelText, getByText, getByPlaceholderText } = render(() => ( )); fireEvent.click(getByLabelText('Not helpful')); fireEvent.click(getByText('Inaccurate')); fireEvent.input(getByPlaceholderText('Tell us more (optional)'), { target: { value: 'wrong answer' } }); fireEvent.click(getByText('Submit')); expect(onSubmitDetail).toHaveBeenCalledWith({ value: 'not-helpful', category: 'Inaccurate', comment: 'wrong answer', }); expect(getByText('Thanks for your feedback')).toBeInTheDocument(); }); it('Skip dismisses the detail form to thanks without firing onSubmitDetail', () => { const onSubmitDetail = vi.fn(); const { getByLabelText, getByText } = render(() => ( )); fireEvent.click(getByLabelText('Not helpful')); fireEvent.click(getByText('Skip')); expect(onSubmitDetail).not.toHaveBeenCalled(); expect(getByText('Thanks for your feedback')).toBeInTheDocument(); }); it('fires onClose when dismissed from the ask phase', () => { const onClose = vi.fn(); const { getByLabelText } = render(() => ); fireEvent.click(getByLabelText('Close')); expect(onClose).toHaveBeenCalled(); }); it('honors a custom thanksMessage', () => { const { getByLabelText, getByText } = render(() => ( )); fireEvent.click(getByLabelText('Helpful')); expect(getByText('Got it — thank you!')).toBeInTheDocument(); }); });