UNPKG

@kadconsulting/dry

Version:
126 lines 6.77 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import RepeatableForm from './RepeatableForm'; // Mock child components jest.mock('../index', () => ({ Accordion: ({ children, parentContent, onDelete, onOpenStateChange, initialOpenState, }) => (_jsxs("div", { "data-testid": 'accordion', "data-open": initialOpenState, children: [_jsx("div", { children: parentContent }), _jsx("button", { onClick: () => onOpenStateChange(!initialOpenState), children: "Toggle" }), _jsx("button", { onClick: onDelete, children: "Delete" }), initialOpenState && children] })), TextInput: ({ Label, value, onChange, inputType }) => (_jsx("input", { type: inputType, placeholder: Label, value: value, onChange: onChange, "data-testid": `input-${Label}` })), Textarea: ({ label, value, onChange }) => (_jsx("textarea", { placeholder: label, value: value, onChange: onChange, "data-testid": `textarea-${label}` })), Button: ({ children, onClick, buttonType }) => (_jsx("button", { onClick: onClick, "data-button-type": buttonType, children: children })), })); const defaultFields = [ { name: 'name', label: 'Name', type: 'text' }, { name: 'description', label: 'Description', type: 'textarea' }, { name: 'quantity', label: 'Quantity', type: 'number' }, ]; const defaultProps = { fields: defaultFields, initialState: [ { name: 'Initial Entry', description: 'Initial Description', quantity: '1', }, ], onStateChange: jest.fn(), }; describe('RepeatableForm', () => { beforeEach(() => { jest.clearAllMocks(); }); it('renders with initial state', () => { render(_jsx(RepeatableForm, { ...defaultProps })); expect(screen.getByText('Entry 1')).toBeInTheDocument(); expect(screen.getByTestId('input-Name')).toHaveValue('Initial Entry'); expect(screen.getByTestId('textarea-Description')).toHaveValue('Initial Description'); expect(screen.getByTestId('input-Quantity')).toHaveValue('1'); }); it('adds a new entry when "Add New Entry" is clicked', async () => { render(_jsx(RepeatableForm, { ...defaultProps })); await userEvent.click(screen.getByText('Add New Entry')); expect(screen.getAllByTestId('accordion')).toHaveLength(2); expect(screen.getByText('Entry 2')).toBeInTheDocument(); }); it('removes an entry when delete button is clicked', async () => { render(_jsx(RepeatableForm, { ...defaultProps })); await userEvent.click(screen.getByText('Add New Entry')); expect(screen.getAllByTestId('accordion')).toHaveLength(2); await userEvent.click(screen.getAllByText('Delete')[0]); expect(screen.getAllByTestId('accordion')).toHaveLength(1); }); it('updates form state when input changes', async () => { const onStateChange = jest.fn(); render(_jsx(RepeatableForm, { ...defaultProps, onStateChange: onStateChange })); await userEvent.type(screen.getByTestId('input-Name'), ' Updated'); expect(onStateChange).toHaveBeenCalledWith([ { name: 'Initial Entry Updated', description: 'Initial Description', quantity: '1', }, ]); }); it('handles different input types correctly', async () => { render(_jsx(RepeatableForm, { ...defaultProps })); await userEvent.type(screen.getByTestId('input-Quantity'), '5'); expect(screen.getByTestId('input-Quantity')).toHaveValue('15'); }); it('toggles accordion open/close state', async () => { render(_jsx(RepeatableForm, { ...defaultProps })); const accordion = screen.getByTestId('accordion'); expect(accordion).toHaveAttribute('data-open', 'true'); await userEvent.click(screen.getByText('Toggle')); expect(accordion).toHaveAttribute('data-open', 'false'); }); it('opens newly added entry and closes others', async () => { render(_jsx(RepeatableForm, { ...defaultProps })); await userEvent.click(screen.getByText('Add New Entry')); const accordions = screen.getAllByTestId('accordion'); expect(accordions[0]).toHaveAttribute('data-open', 'false'); expect(accordions[1]).toHaveAttribute('data-open', 'true'); }); it('maintains state correctly after multiple add/remove operations', async () => { const onStateChange = jest.fn(); render(_jsx(RepeatableForm, { ...defaultProps, onStateChange: onStateChange })); await userEvent.click(screen.getByText('Add New Entry')); await userEvent.click(screen.getByText('Add New Entry')); await userEvent.click(screen.getAllByText('Delete')[1]); expect(screen.getAllByTestId('accordion')).toHaveLength(2); expect(onStateChange).toHaveBeenCalledTimes(3); }); it('handles empty initial state', () => { render(_jsx(RepeatableForm, { ...defaultProps, initialState: [] })); expect(screen.queryByTestId('accordion')).not.toBeInTheDocument(); }); it('renders with correct CSS classes and inline styles', () => { const { container } = render(_jsx(RepeatableForm, { ...defaultProps, className: 'custom-class', style: { marginTop: '10px' } })); const formElement = container.firstChild; expect(formElement).toHaveClass('dry-repeatableform'); expect(formElement).toHaveClass('custom-class'); expect(formElement).toHaveStyle('margin-top: 10px'); }); it('calls onStateChange with correct data structure when adding new entry', async () => { const onStateChange = jest.fn(); render(_jsx(RepeatableForm, { ...defaultProps, onStateChange: onStateChange })); await userEvent.click(screen.getByText('Add New Entry')); expect(onStateChange).toHaveBeenCalledWith([ { name: 'Initial Entry', description: 'Initial Description', quantity: '1', }, { name: '', description: '', quantity: '' }, ]); }); it('passes any downstream data-* attribute(s)', () => { const testValue = 'test-value'; render(_jsx(RepeatableForm, { ...defaultProps, "data-test": testValue })); expect(screen.getByTestId('accordion')).toHaveAttribute('data-test', testValue); }); it('supports downstream @testing-library `screen.getByTestId`', () => { render(_jsx(RepeatableForm, { ...defaultProps, "data-testid": 'test-id' })); expect(screen.getByTestId('test-id')).toBeInTheDocument(); }); }); //# sourceMappingURL=RepeatableForm.test.js.map