diff --git a/src/components/atoms/Checkbox.tsx b/src/components/atoms/Checkbox.tsx new file mode 100644 index 0000000..5306331 --- /dev/null +++ b/src/components/atoms/Checkbox.tsx @@ -0,0 +1,42 @@ +'use client'; +import { FormControlLabel, Checkbox as MuiCheckbox } from '@mui/material'; +import { CheckboxProps } from '@components/atoms/Checkbox'; +import React from 'react'; + +const Checkbox: React.FC = ({ + label, + checked, + onChange, + color = 'primary', + disabled = false, + size = 'medium', + indeterminate = false, + labelPlacement = 'end', + required = false, + tabIndex, + ariaLabel, + ...props +}: CheckboxProps) => { + return ( + + } + label={label} + labelPlacement={labelPlacement} + /> + ); +}; + +export default Checkbox; diff --git a/src/types/Checkbox.types.d.ts b/src/types/Checkbox.types.d.ts new file mode 100644 index 0000000..6632aeb --- /dev/null +++ b/src/types/Checkbox.types.d.ts @@ -0,0 +1,17 @@ +declare module '@components/atoms/Checkbox' { + import { FC } from 'react'; + import { CheckboxProps as MuiCheckboxProps } from '@mui/material/Checkbox'; + + export interface CheckboxProps extends Omit { + label: string; + checked: boolean; + onChange: (event: React.ChangeEvent) => void; + labelPlacement?: 'end' | 'start' | 'top' | 'bottom'; + required?: boolean; + tabIndex?: number; + ariaLabel?: string; + } + + const Checkbox: FC; + export default Checkbox; +} diff --git a/tests/components/atoms/Checkbox.test.tsx b/tests/components/atoms/Checkbox.test.tsx new file mode 100644 index 0000000..97fd18b --- /dev/null +++ b/tests/components/atoms/Checkbox.test.tsx @@ -0,0 +1,75 @@ +import '@testing-library/jest-dom'; +import { fireEvent, render, screen } from '@testing-library/react'; +import Checkbox from '../../../src/components/atoms/Checkbox'; +import React from 'react'; + +describe('Checkbox component', () => { + const defaultProps = { + label: 'Test Checkbox', + checked: false, + onChange: jest.fn(), + }; + + it('should render the checkbox with the correct label', () => { + render(); + expect(screen.getByLabelText('Test Checkbox')).toBeInTheDocument(); + }); + + it('should pass the correct checked state to the checkbox', () => { + const { rerender } = render(); + const checkbox = screen.getByRole('checkbox') as HTMLInputElement; + expect(checkbox.checked).toBe(false); + + rerender(); + expect(checkbox.checked).toBe(true); + }); + + it('should call onChange when the checkbox is clicked', () => { + render(); + const checkbox = screen.getByRole('checkbox'); + fireEvent.click(checkbox); + expect(defaultProps.onChange).toHaveBeenCalledTimes(1); + }); + + it('should apply the correct color', () => { + render(); + const checkboxWrapper = screen.getByRole('checkbox').parentElement; + expect(checkboxWrapper).toHaveClass('MuiCheckbox-colorSecondary'); + }); + + it('should render the checkbox as required', () => { + render(); + const checkbox = screen.getByRole('checkbox'); + expect(checkbox).toBeRequired(); + }); + + it('should handle labelPlacement correctly', () => { + const { rerender } = render( + + ); + const checkboxLabelEnd = screen.getByText('Test Checkbox'); + expect(checkboxLabelEnd).toBeInTheDocument(); + + rerender(); + const checkboxLabelStart = screen.getByText('Test Checkbox'); + expect(checkboxLabelStart).toBeInTheDocument(); + }); + + it('should apply aria-label correctly for accessibility', () => { + render(); + const checkbox = screen.getByLabelText('Test Checkbox Aria Label'); + expect(checkbox).toBeInTheDocument(); + }); + + it('should be disabled when the disabled prop is true', () => { + render(); + const checkbox = screen.getByRole('checkbox') as HTMLInputElement; + expect(checkbox.disabled).toBe(true); + }); + + it('should apply the correct tabIndex', () => { + render(); + const checkbox = screen.getByRole('checkbox'); + expect(checkbox).toHaveAttribute('tabIndex', '2'); + }); +});