Jest/React Testing Library (RTL) 호환 API를 제공하는 경량 테스트 러너 패키지입니다.
npm install @fix-my/test-runnerJest/React Testing Library (RTL) 호환 API를 제공하는 경량 테스트 러너 패키지입니다.
- Jest 호환 API: describe, it, expect 등 익숙한 인터페이스
- RTL 스타일 쿼리: screen.getByText(), screen.getByRole() 등
- 풍부한 DOM 매처: toBeInTheDocument(), toBeVisible(), toHaveTextContent() 등
- 듀얼 환경 지원: Node.js VM과 브라우저 모두에서 실행 가능
- TypeScript 지원: 완전한 타입 정의 포함
``bash`
npm install @fix-my/test-runner
`typescript
import { render, screen, expect, describe, it, cleanup } from '@fix-my/test-runner';
describe('Button Component', () => {
afterEach(() => {
cleanup();
});
it('renders with correct text', () => {
render();
const button = screen.getByText('Click me');
expect(button).toBeInTheDocument();
expect(button).toBeVisible();
});
it('displays loading state', async () => {
render();
const spinner = await screen.findByRole('img', { timeout: 1000 });
expect(spinner).toBeInTheDocument();
});
});
`
#### describe(name, fn)
테스트 그룹을 정의합니다.
`typescript`
describe('User Form', () => {
// 테스트들...
});
#### it(name, fn) / test(name, fn)
개별 테스트 케이스를 정의합니다.
`typescript`
it('validates email format', () => {
// 테스트 로직...
});
#### render(element)
React 엘리먼트를 DOM에 렌더링합니다.
`typescript`
const { container, unmount, rerender } = render(
반환값:
- container: 렌더링된 컨테이너 엘리먼트unmount()
- : 컴포넌트를 DOM에서 제거rerender(newElement)
- : 새 props로 리렌더링
#### cleanup()
모든 렌더링된 컴포넌트를 정리합니다.
`typescript`
afterEach(() => {
cleanup();
});
#### Query Types
| Query | Returns | Throws | Use Case |
|-------|---------|--------|----------|
| getBy* | Element | Yes | 엘리먼트가 있어야 할 때 |queryBy*
| | Element \| null | No | 엘리먼트가 없을 수 있을 때 |findBy*
| | Promise<Element> | Yes | 비동기 엘리먼트 |
#### Available Queries
`typescript
// 텍스트로 찾기
screen.getByText('Hello');
screen.getByText(/hello/i);
screen.queryByText('Optional');
await screen.findByText('Loading...');
// ARIA role로 찾기
screen.getByRole('button');
screen.getByRole('heading');
// data-testid로 찾기
screen.getByTestId('submit-button');
// 라벨로 찾기 (aria-label 포함)
screen.getByLabelText('Username');
screen.getByLabelText('Close dialog'); // aria-label
// placeholder로 찾기
screen.getByPlaceholderText('Enter email');
`
#### Options
`typescript
// 부분 매칭
screen.getByText('Hello', { exact: false });
// 타임아웃 (findBy*)
await screen.findByText('Loaded', { timeout: 5000 });
`
#### DOM Presence
`typescript`
expect(element).toBeInTheDocument();
expect(element).toBeVisible();
expect(element).toBeEmpty();
#### Attributes & Content
`typescript`
expect(element).toHaveTextContent('Hello');
expect(element).toHaveTextContent(/hello/i);
expect(element).toHaveClass('active');
expect(element).toHaveClass('btn', 'primary');
expect(element).toHaveAttribute('disabled');
expect(element).toHaveAttribute('href', '/home');
#### Form Elements
`typescript`
expect(input).toHaveValue('test@email.com');
expect(checkbox).toBeChecked();
expect(button).toBeDisabled();
expect(input).toHaveFocus();
#### Styles
`typescript`
expect(element).toHaveStyle({ display: 'flex' });
expect(element).toHaveStyle({ color: 'red', fontSize: '16px' });
#### Hierarchy
`typescript`
expect(parent).toContainElement(child);
expect(element).toContainHTML('text');
#### Negation
`typescript`
expect(element).not.toBeInTheDocument();
expect(element).not.toBeVisible();
expect(button).not.toBeDisabled();
#### waitFor(callback, options?)
조건이 충족될 때까지 대기합니다.
`typescript`
await waitFor(() => {
expect(screen.getByText('Loaded')).toBeInTheDocument();
}, { timeout: 5000, interval: 100 });
#### act(callback)
React 상태 업데이트를 동기화합니다.
`typescript`
await act(async () => {
button.click();
});
`typescript`
expect(value).toBe(expected);
expect(value).toBeTruthy();
expect(value).toBeFalsy();
expect(array).toContain(item);
expect(number).toBeGreaterThan(other);
expect(number).toBeLessThan(other);
기존 테스트에서 자동 렌더링을 사용했다면:
`typescript
import { setCompatMode, registerApp, render } from '@fix-my/test-runner';
// 레거시 모드 활성화
setCompatMode('auto');
registerApp(App);
// 인자 없이 render 호출
render();
`
`typescript
import { render, screen } from '@fix-my/test-runner';
// RTL 스타일
render(
const button = screen.getByText('Click');
`
`typescript
import { runTestsInVM } from '@fix-my/test-runner';
const bundledCode = '...'; // 번들된 테스트 코드
const result = await runTestsInVM(bundledCode);
console.log(result.passed); // true/false
console.log(result.results); // 개별 테스트 결과
`
쿼리 실패 시 유용한 에러 메시지를 제공합니다:
`
Unable to find element with text: "Missing Text"
Tip: Use findByText for async elements
``
- Chrome (최신)
- Firefox (최신)
- Safari (최신)
- Edge (최신)
참고: IE11은 지원하지 않습니다. React 18+ 필요.
MIT