diff --git a/src/components/atoms/Button.tsx b/src/components/atoms/Button.tsx new file mode 100644 index 0000000..400e80f --- /dev/null +++ b/src/components/atoms/Button.tsx @@ -0,0 +1,21 @@ +'use client'; +import React from 'react'; +import { Button as MuiButton } from '@mui/material'; +import { ButtonProps } from '@components/atoms/Button'; + +const Button: React.FC<ButtonProps> = ({ + label, + variant = 'contained', + color = 'primary', + size = 'medium', + onClick, + ...props +}: ButtonProps) => { + return ( + <MuiButton variant={variant} color={color} size={size} onClick={onClick} {...props}> + {label} + </MuiButton> + ); +}; + +export default Button; \ No newline at end of file diff --git a/src/types/Button.types.d.ts b/src/types/Button.types.d.ts new file mode 100644 index 0000000..493f3cb --- /dev/null +++ b/src/types/Button.types.d.ts @@ -0,0 +1,12 @@ +declare module '@components/atoms/Button' { + import { FC } from 'react'; + import { ButtonProps as MuiButtonProps } from '@mui/material/Button'; + + export interface ButtonProps extends Omit<MuiButtonProps, 'color'> { + label: string; + color?: 'inherit' | 'primary' | 'secondary' | 'success' | 'error' | 'info' | 'warning'; + } + + const Button: FC<ButtonProps>; + export default Button; +} \ No newline at end of file diff --git a/tests/components/atoms/Button.test.tsx b/tests/components/atoms/Button.test.tsx new file mode 100644 index 0000000..ba688e5 --- /dev/null +++ b/tests/components/atoms/Button.test.tsx @@ -0,0 +1,85 @@ +import React from 'react'; +import { render, screen, fireEvent } from '@testing-library/react'; +import Button from '../../../src/components/atoms/Button'; +import { Button as MuiButton } from '@mui/material'; +import '@testing-library/jest-dom'; + +jest.mock('@mui/material', () => ({ + Button: jest.fn().mockImplementation(({ children, ...props }) => ( + <button {...props}>{children}</button> + )), +})); + +describe('Button component', () => { + const defaultProps = { + label: 'Test Button', + variant: 'contained' as const, + color: 'primary' as const, + size: 'medium' as const, + onClick: jest.fn(), + }; + + beforeEach(() => { + (MuiButton as jest.Mock).mockClear(); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should render the button with correct label', () => { + render(<Button {...defaultProps} />); + expect(screen.getByText('Test Button')).toBeInTheDocument(); + }); + + it('should pass the correct variant prop to MuiButton', () => { + render(<Button {...defaultProps} variant="outlined" />); + expect(MuiButton).toHaveBeenCalledWith( + expect.objectContaining({ variant: 'outlined' }), + expect.anything() + ); + }); + + it('should pass the correct color prop to MuiButton', () => { + render(<Button {...defaultProps} color="secondary" />); + expect(MuiButton).toHaveBeenCalledWith( + expect.objectContaining({ color: 'secondary' }), + expect.anything() + ); + }); + + it('should pass the correct size prop to MuiButton', () => { + render(<Button {...defaultProps} size="small" />); + expect(MuiButton).toHaveBeenCalledWith( + expect.objectContaining({ size: 'small' }), + expect.anything() + ); + }); + + it('should call onClick when the button is clicked', () => { + render(<Button {...defaultProps} />); + fireEvent.click(screen.getByText('Test Button')); + expect(defaultProps.onClick).toHaveBeenCalledTimes(1); + }); + + it('should use default values when no props are provided', () => { + render(<Button label="Default Button" />); + expect(MuiButton).toHaveBeenCalledWith( + expect.objectContaining({ + variant: 'contained', + color: 'primary', + size: 'medium', + }), + expect.anything() + ); + expect(screen.getByText('Default Button')).toBeInTheDocument(); + }); + + it('should pass additional props to MuiButton', () => { + render(<Button {...defaultProps} disabled />); + expect(MuiButton).toHaveBeenCalledWith( + expect.objectContaining({ disabled: true }), + expect.anything() + ); + }); +}); \ No newline at end of file