diff --git a/src/components/Box/index.tsx b/src/components/Box/index.tsx index ed1874e0..86a36645 100644 --- a/src/components/Box/index.tsx +++ b/src/components/Box/index.tsx @@ -1,27 +1,29 @@ -import React from 'react'; +import React, { ComponentProps, ElementType } from 'react'; import cx from 'classnames'; import type { BaseProps, SizeType } from '../types'; import styles from './Box.module.scss'; +import Component, { CommonComponentProps } from '../Component'; -export interface BoxProps { - readonly elevation?: SizeType; - readonly stroke?: SizeType; - readonly gutter?: SizeType; - readonly gutterX?: SizeType; - readonly gutterY?: SizeType; -} +export type BoxProps = { + elevation?: SizeType; + stroke?: SizeType; + gutter?: SizeType; + gutterX?: SizeType; + gutterY?: SizeType; +} & CommonComponentProps; -const Box = ({ +const Box = ({ + as, className, - as: Component = 'div', testId = 'Box', elevation = 'none', gutter = 'none', gutterX = 'none', gutterY = 'none', - ...restProps -}: BaseProps & BoxProps) => ( + ...props +}: BoxProps) => ( ); diff --git a/src/components/Component/Component.spec.tsx b/src/components/Component/Component.spec.tsx new file mode 100644 index 00000000..6dbc4a42 --- /dev/null +++ b/src/components/Component/Component.spec.tsx @@ -0,0 +1,51 @@ +import React from 'react'; +import { describe, expect, test, afterEach } from 'vitest'; +import { cleanup, render, screen } from '@testing-library/react'; + +import Component from './index'; + +const setup = (Component: React.ReactElement) => render(Component); + +afterEach(cleanup); + +describe('Component', () => { + describe('as prop', () => { + test('it falls back to div', () => { + setup(Hello world); + expect(screen.getByTestId('Component').nodeName).toBe('DIV'); + }); + + test('it works with HTML element', () => { + setup(Hello world); + expect(screen.getByTestId('Component').nodeName).toBe('BUTTON'); + expect(screen.getByRole('button')).toBeTruthy(); + }); + + test('it works with React component', () => { + const TestComponent = ({ status }: { status: string }) => ( +

test {status}

+ ); + setup(); + expect(screen.getByText('test info')).toBeTruthy(); + }); + }); + + describe('testId prop', () => { + test('it works with default testId', () => { + setup(Hello world); + expect(screen.getByTestId('Component')).toBeTruthy(); + }); + + test('it works with specified testId', () => { + setup(Hello world); + expect(screen.getByTestId('TestId')).toBeTruthy(); + }); + }); + + test('it works with className', () => { + setup(Hello world); + expect( + screen.getByTestId('Component').classList.contains('test') + ).toBeTruthy(); + }); +}); diff --git a/src/components/Component/index.tsx b/src/components/Component/index.tsx new file mode 100644 index 00000000..df43872d --- /dev/null +++ b/src/components/Component/index.tsx @@ -0,0 +1,26 @@ +import React, { ComponentPropsWithoutRef, ElementType, ReactNode } from 'react'; + +export type CommonComponentProps = { + as?: T; + children?: ReactNode; + className?: string; + testId?: string; +}; + +const Component = ({ + as, + children, + testId = 'Component', + ...props +}: CommonComponentProps & + Omit, keyof CommonComponentProps>) => { + const PolymorphicComponent = as || 'div'; + return ( + + {children} + + ); +}; + +Component.displayName = 'Component'; +export default Component;