Skip to content

Commit

Permalink
feat!: add checkbox atomic component (#11)
Browse files Browse the repository at this point in the history
* feat!: add checkbox atomic component

- Added Checkbox.tsx and Checkbox.types.d.ts.
  - Wrapped MuiCheckbox and FormControlLabel in new Checkbox component.
- Added test suite for checkbox, Checkbox.test.tsx.

* style: fix linter errors for checkbox atom

---------

Co-authored-by: ishaan bhalla <[email protected]>
  • Loading branch information
ishaan000 and ishaan bhalla authored Oct 21, 2024
1 parent a605ffd commit 51f535f
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 0 deletions.
42 changes: 42 additions & 0 deletions src/components/atoms/Checkbox.tsx
Original file line number Diff line number Diff line change
@@ -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<CheckboxProps> = ({
label,
checked,
onChange,
color = 'primary',
disabled = false,
size = 'medium',
indeterminate = false,
labelPlacement = 'end',
required = false,
tabIndex,
ariaLabel,
...props
}: CheckboxProps) => {
return (
<FormControlLabel
control={
<MuiCheckbox
aria-label={ariaLabel}
checked={checked}
color={color}
disabled={disabled}
indeterminate={indeterminate}
onChange={onChange}
required={required}
size={size}
tabIndex={tabIndex}
{...props}
/>
}
label={label}
labelPlacement={labelPlacement}
/>
);
};

export default Checkbox;
17 changes: 17 additions & 0 deletions src/types/Checkbox.types.d.ts
Original file line number Diff line number Diff line change
@@ -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<MuiCheckboxProps, 'onChange'> {
label: string;
checked: boolean;
onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
labelPlacement?: 'end' | 'start' | 'top' | 'bottom';
required?: boolean;
tabIndex?: number;
ariaLabel?: string;
}

const Checkbox: FC<CheckboxProps>;
export default Checkbox;
}
75 changes: 75 additions & 0 deletions tests/components/atoms/Checkbox.test.tsx
Original file line number Diff line number Diff line change
@@ -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(<Checkbox {...defaultProps} />);
expect(screen.getByLabelText('Test Checkbox')).toBeInTheDocument();
});

it('should pass the correct checked state to the checkbox', () => {
const { rerender } = render(<Checkbox {...defaultProps} checked={false} />);
const checkbox = screen.getByRole('checkbox') as HTMLInputElement;
expect(checkbox.checked).toBe(false);

rerender(<Checkbox {...defaultProps} checked={true} />);
expect(checkbox.checked).toBe(true);
});

it('should call onChange when the checkbox is clicked', () => {
render(<Checkbox {...defaultProps} />);
const checkbox = screen.getByRole('checkbox');
fireEvent.click(checkbox);
expect(defaultProps.onChange).toHaveBeenCalledTimes(1);
});

it('should apply the correct color', () => {
render(<Checkbox {...defaultProps} color="secondary" />);
const checkboxWrapper = screen.getByRole('checkbox').parentElement;
expect(checkboxWrapper).toHaveClass('MuiCheckbox-colorSecondary');
});

it('should render the checkbox as required', () => {
render(<Checkbox {...defaultProps} required />);
const checkbox = screen.getByRole('checkbox');
expect(checkbox).toBeRequired();
});

it('should handle labelPlacement correctly', () => {
const { rerender } = render(
<Checkbox {...defaultProps} labelPlacement="end" />
);
const checkboxLabelEnd = screen.getByText('Test Checkbox');
expect(checkboxLabelEnd).toBeInTheDocument();

rerender(<Checkbox {...defaultProps} labelPlacement="start" />);
const checkboxLabelStart = screen.getByText('Test Checkbox');
expect(checkboxLabelStart).toBeInTheDocument();
});

it('should apply aria-label correctly for accessibility', () => {
render(<Checkbox {...defaultProps} ariaLabel="Test Checkbox Aria Label" />);
const checkbox = screen.getByLabelText('Test Checkbox Aria Label');
expect(checkbox).toBeInTheDocument();
});

it('should be disabled when the disabled prop is true', () => {
render(<Checkbox {...defaultProps} disabled />);
const checkbox = screen.getByRole('checkbox') as HTMLInputElement;
expect(checkbox.disabled).toBe(true);
});

it('should apply the correct tabIndex', () => {
render(<Checkbox {...defaultProps} tabIndex={2} />);
const checkbox = screen.getByRole('checkbox');
expect(checkbox).toHaveAttribute('tabIndex', '2');
});
});

0 comments on commit 51f535f

Please sign in to comment.