-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat!: add switch atomic component (#13)
- Added Switch.tsx and Switch.types.d.ts. - Wrapped MuiSwitch in new Switch component - Added test suite for switch, Switch.test.tsx Co-authored-by: ishaan bhalla <[email protected]>
- Loading branch information
Showing
3 changed files
with
176 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<SwitchProps> = ({ | ||
checked = false, | ||
onChange, | ||
color = 'primary', | ||
size = 'medium', | ||
disabled = false, | ||
sx = {}, | ||
ariaLabel = '', | ||
tabIndex = 0, | ||
inputProps = {}, | ||
...props | ||
}) => { | ||
return ( | ||
<MuiSwitch | ||
checked={checked} | ||
color={color} | ||
disabled={disabled} | ||
inputProps={{ 'aria-label': ariaLabel, ...inputProps }} | ||
onChange={onChange} | ||
size={size} | ||
sx={sx} | ||
tabIndex={tabIndex} | ||
{...props} | ||
/> | ||
); | ||
}; | ||
|
||
export default Switch; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<MuiSwitchProps, 'color'> { | ||
checked?: boolean; | ||
color?: | ||
| 'primary' | ||
| 'secondary' | ||
| 'error' | ||
| 'info' | ||
| 'success' | ||
| 'warning' | ||
| 'default'; | ||
disabled?: boolean; | ||
onChange?: MuiSwitchProps['onChange']; | ||
size?: 'small' | 'medium'; | ||
sx?: SxProps<Theme>; | ||
value?: unknown; | ||
ariaLabel?: string; | ||
tabIndex?: number; | ||
inputProps?: MuiSwitchProps['inputProps']; | ||
} | ||
|
||
const Switch: FC<SwitchProps>; | ||
export default Switch; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 }) => ( | ||
<input type="checkbox" {...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(<Switch {...defaultProps} />); | ||
expect(screen.getByRole('checkbox')).toBeInTheDocument(); | ||
}); | ||
|
||
it('should have the correct checked state', () => { | ||
render(<Switch {...defaultProps} checked={true} />); | ||
expect(screen.getByRole('checkbox')).toBeChecked(); | ||
}); | ||
|
||
it('should call onChange when toggled', () => { | ||
render(<Switch {...defaultProps} />); | ||
fireEvent.click(screen.getByRole('checkbox')); | ||
expect(defaultProps.onChange).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it('should pass the correct color prop to MuiSwitch', () => { | ||
render(<Switch {...defaultProps} color="secondary" />); | ||
expect(MuiSwitch).toHaveBeenCalledWith( | ||
expect.objectContaining({ color: 'secondary' }), | ||
expect.anything() | ||
); | ||
}); | ||
|
||
it('should pass the correct size prop to MuiSwitch', () => { | ||
render(<Switch {...defaultProps} size="small" />); | ||
expect(MuiSwitch).toHaveBeenCalledWith( | ||
expect.objectContaining({ size: 'small' }), | ||
expect.anything() | ||
); | ||
}); | ||
|
||
it('should be disabled when the disabled prop is true', () => { | ||
render(<Switch {...defaultProps} disabled={true} />); | ||
expect(screen.getByRole('checkbox')).toBeDisabled(); | ||
}); | ||
|
||
it('should apply the correct aria-label', () => { | ||
render(<Switch {...defaultProps} ariaLabel="Custom Aria Label" />); | ||
expect(screen.getByRole('checkbox')).toHaveAttribute( | ||
'aria-label', | ||
'Custom Aria Label' | ||
); | ||
}); | ||
|
||
it('should set the correct tabIndex on the input', () => { | ||
render(<Switch {...defaultProps} tabIndex={-1} />); | ||
expect(screen.getByRole('checkbox')).toHaveAttribute('tabindex', '-1'); | ||
}); | ||
|
||
it('should apply sx prop to MuiSwitch', () => { | ||
const sx = { margin: 2 }; | ||
render(<Switch {...defaultProps} sx={sx} />); | ||
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(<Switch {...defaultProps} inputProps={inputProps} />); | ||
expect(screen.getByTestId('custom-switch')).toBeInTheDocument(); | ||
}); | ||
|
||
it('should use default values when no props are provided', () => { | ||
render(<Switch onChange={jest.fn()} />); | ||
expect(MuiSwitch).toHaveBeenCalledWith( | ||
expect.objectContaining({ | ||
checked: false, | ||
color: 'primary', | ||
size: 'medium', | ||
disabled: false, | ||
}), | ||
expect.anything() | ||
); | ||
}); | ||
}); |