From a98c2ab7b5b95f8a90808f2e355d7253e4eae122 Mon Sep 17 00:00:00 2001 From: ishaan bhalla Date: Tue, 8 Oct 2024 16:32:57 -0700 Subject: [PATCH] feat!: add switch atomic component - Added Switch.tsx and Switch.types.d.ts. - Wrapped MuiSwitch in new Switch component - Added test suite for switch, Switch.test.tsx --- src/components/atoms/Switch.tsx | 34 ++++++++ src/types/Switch.types.d.ts | 28 ++++++ tests/components/atoms/Switch.test.tsx | 114 +++++++++++++++++++++++++ 3 files changed, 176 insertions(+) create mode 100644 src/components/atoms/Switch.tsx create mode 100644 src/types/Switch.types.d.ts create mode 100644 tests/components/atoms/Switch.test.tsx diff --git a/src/components/atoms/Switch.tsx b/src/components/atoms/Switch.tsx new file mode 100644 index 0000000..413890b --- /dev/null +++ b/src/components/atoms/Switch.tsx @@ -0,0 +1,34 @@ +'use client'; + +import { Switch as MuiSwitch } from '@mui/material'; +import React from 'react'; +import { SwitchProps } from '@components/atoms/Switch'; + +const Switch: React.FC = ({ + checked = false, + onChange, + color = 'primary', + size = 'medium', + disabled = false, + sx = {}, + ariaLabel = '', + tabIndex = 0, + inputProps = {}, + ...props +}) => { + return ( + + ); +}; + +export default Switch; diff --git a/src/types/Switch.types.d.ts b/src/types/Switch.types.d.ts new file mode 100644 index 0000000..cab0c13 --- /dev/null +++ b/src/types/Switch.types.d.ts @@ -0,0 +1,28 @@ +declare module '@components/atoms/Switch' { + import { SxProps, Theme } from '@mui/system'; + import { FC } from 'react'; + import { SwitchProps as MuiSwitchProps } from '@mui/material/Switch'; + + export interface SwitchProps extends Omit { + checked?: boolean; + color?: + | 'primary' + | 'secondary' + | 'error' + | 'info' + | 'success' + | 'warning' + | 'default'; + disabled?: boolean; + onChange?: MuiSwitchProps['onChange']; + size?: 'small' | 'medium'; + sx?: SxProps; + value?: unknown; + ariaLabel?: string; + tabIndex?: number; + inputProps?: MuiSwitchProps['inputProps']; + } + + const Switch: FC; + export default Switch; +} diff --git a/tests/components/atoms/Switch.test.tsx b/tests/components/atoms/Switch.test.tsx new file mode 100644 index 0000000..a719270 --- /dev/null +++ b/tests/components/atoms/Switch.test.tsx @@ -0,0 +1,114 @@ +import '@testing-library/jest-dom'; +import { fireEvent, render, screen } from '@testing-library/react'; +import { Switch as MuiSwitch } from '@mui/material'; +import React from 'react'; +import Switch from '../../../src/components/atoms/Switch'; + +jest.mock('@mui/material', () => ({ + Switch: jest + .fn() + .mockImplementation(({ inputProps, ...props }) => ( + + )), +})); + +describe('Switch component', () => { + const defaultProps = { + checked: false, + onChange: jest.fn(), + color: 'primary' as const, + size: 'medium' as const, + disabled: false, + ariaLabel: 'Test Switch', + }; + + beforeEach(() => { + (MuiSwitch as jest.Mock).mockClear(); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should render the switch', () => { + render(); + expect(screen.getByRole('checkbox')).toBeInTheDocument(); + }); + + it('should have the correct checked state', () => { + render(); + expect(screen.getByRole('checkbox')).toBeChecked(); + }); + + it('should call onChange when toggled', () => { + render(); + fireEvent.click(screen.getByRole('checkbox')); + expect(defaultProps.onChange).toHaveBeenCalledTimes(1); + }); + + it('should pass the correct color prop to MuiSwitch', () => { + render(); + expect(MuiSwitch).toHaveBeenCalledWith( + expect.objectContaining({ color: 'secondary' }), + expect.anything() + ); + }); + + it('should pass the correct size prop to MuiSwitch', () => { + render(); + expect(MuiSwitch).toHaveBeenCalledWith( + expect.objectContaining({ size: 'small' }), + expect.anything() + ); + }); + + it('should be disabled when the disabled prop is true', () => { + render(); + expect(screen.getByRole('checkbox')).toBeDisabled(); + }); + + it('should apply the correct aria-label', () => { + render(); + expect(screen.getByRole('checkbox')).toHaveAttribute( + 'aria-label', + 'Custom Aria Label' + ); + }); + + it('should set the correct tabIndex on the input', () => { + render(); + expect(screen.getByRole('checkbox')).toHaveAttribute('tabindex', '-1'); + }); + + it('should apply sx prop to MuiSwitch', () => { + const sx = { margin: 2 }; + render(); + expect(MuiSwitch).toHaveBeenCalledWith( + expect.objectContaining({ + sx: expect.objectContaining({ + margin: 2, + }), + }), + expect.anything() + ); + }); + + it('should pass additional inputProps to the input element', () => { + const inputProps = { 'data-testid': 'custom-switch' }; + render(); + expect(screen.getByTestId('custom-switch')).toBeInTheDocument(); + }); + + it('should use default values when no props are provided', () => { + render(); + expect(MuiSwitch).toHaveBeenCalledWith( + expect.objectContaining({ + checked: false, + color: 'primary', + size: 'medium', + disabled: false, + }), + expect.anything() + ); + }); +});