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();
});
});