Skip to main content

uui-unit-testing

Helps write unit tests for UUI components using Jest, jsdom, and @epam/uui-test-utils. Use when writing unit tests for UUI components, updating snapshots, running Jest tests, or working with test utilities.

설치로 이동

소스 정보

저장소
epam/UUI
최근 소스 활동
2026년 3월 4일 09:47
감지된 SKILL.md 언어
영어
스타
248
포크
79

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
uui-unit-testing
description
Helps write unit tests for UUI components using Jest, jsdom, and @epam/uui-test-utils. Use when writing unit tests for UUI components, updating snapshots, running Jest tests, or working with test utilities.
# UUI Unit Testing UUI uses Jest with jsdom for unit testing React components. Tests are located in `__tests__` folders within each package. ## Test File Location Test files follow the pattern: `**/__tests__/**/*.test.{js,ts,tsx}` **Examples:** - `uui/components/buttons/__tests__/Button.test.tsx` - `uui/components/inputs/__tests__/NumericInput.test.tsx` - `uui-core/src/hooks/__tests__/useVirtualList.test.tsx` ## Test Commands **Run all tests:** ```bash yarn test ``` **Run tests in watch mode:** ```bash yarn test-watch ``` **Run a single test file:** ```bash yarn test -- --testPathPattern="Button" ``` Use `--testPathPattern` to match file path, or `--testNamePattern="should render"` to match test names. **Update snapshots:** ```bash yarn test-update ``` **Generate test coverage report:** ```bash yarn test-report ``` Coverage report saves to `.reports/unit-tests` folder. **TypeScript type checking:** ```bash yarn test-typecheck ``` **Windows workaround:** If encountering test errors on Windows, use reduced worker count: ```bash yarn test --maxWorkers=2 --testTimeout=10000 ``` You can increase `maxWorkers` up to 4 if needed. ## Using @epam/uui-test-utils The `@epam/uui-test-utils` package provides helpers for testing UUI components with proper context. ### Key Exports | Export | Purpose | |--------|---------| | `renderSnapshotWithContextAsync` | Render with UUI context, returns `DocumentFragment` for snapshots | | `renderWithContextAsync` | Render with UUI context for interaction testing | | `renderHookWithContextAsync` | Test custom hooks with UUI context | | `setupComponentForTest` | Setup component with mocks and `setProps` helper | | `screen` | Re-exported from `@testing-library/react` | | `userEvent` | Re-exported from `@testing-library/user-event` | | `fireEvent` | Re-exported from `@testing-library/react` | | `SvgMock` | Mock for SVG icon imports in snapshots | | `mockReactPortalsForSnapshots` | Mock portals for snapshot tests | | `delay`, `delayAct` | Async timing utilities for tests | ### renderSnapshotWithContextAsync Renders component with UUI context and returns a `DocumentFragment` (via `asFragment()`) for snapshot matching: ```typescript import { renderSnapshotWithContextAsync } from '@epam/uui-test-utils'; import { NumericInput } from '../NumericInput'; it('should be rendered with minimum props', async () => { const tree = await renderSnapshotWithContextAsync( <NumericInput value={null} onValueChange={jest.fn} min={0} max={50} /> ); expect(tree).toMatchSnapshot(); }); ``` ### setupComponentForTest Use for testing **controlled components** (e.g. `value` + `onValueChange`). Provides `setProps` to update props without unmounting, and `mocks` for callback assertions. Call `context.current.setProperty(name, value)` in callback mocks to simulate controlled updates: ```typescript import { setupComponentForTest, screen, fireEvent } from '@epam/uui-test-utils'; import { TextInput } from '@epam/uui'; interface TestComponentProps { value?: string; onValueChange?: (value: string) => void; } const { mocks, setProps } = await setupComponentForTest<TestComponentProps>( (context) => ({ value: 'initial', onValueChange: jest.fn().mockImplementation((newValue) => { context.current.setProperty('value', newValue); }), }), (props) => <TextInput value={props.value} onValueChange={props.onValueChange} />, ); const input = screen.queryByRole('textbox'); fireEvent.change(input, { target: { value: 'updated' } }); expect(mocks.onValueChange).toHaveBeenLastCalledWith('updated'); setProps({ value: 'external' }); // Update props without unmounting ``` ### renderHookWithContextAsync Renders a hook with UUI context. Returns `{ result, rerender, unmount, svc }`: - **result** — current hook return value (use `result.current`) - **svc** — UUI services (api, modals, router, etc.) for mocking or assertions - **rerender**, **unmount** — same as `renderHook` from Testing Library ```typescript import { renderHookWithContextAsync, act } from '@epam/uui-test-utils'; it('should use DataSource view', async () => { const dataSource = useArrayDataSource({ items: [...], getId: (i) => i.id }, []); const { result, svc } = await renderHookWithContextAsync(() => dataSource.useView({}, () => {}, {}) ); const rows = result.current.getVisibleRows(); expect(rows).toHaveLength(5); // svc.api, svc.uuiModals, etc. available for mocks }); it('should test custom hook with services', async () => { const { result, svc } = await renderHookWithContextAsync(useMyHook); act(() => result.current.doSomething()); expect(svc.uuiAnalytics.sendEvent).toHaveBeenCalled(); }); ``` ### renderWithContextAsync Renders component with UUI context for interaction testing: ```typescript import { renderWithContextAsync, screen, userEvent } from '@epam/uui-test-utils'; import { Tag } from '../Tag'; it('should call onClear callback', async () => { const onClearMock = jest.fn(); await renderWithContextAsync( <Tag caption="Test badge" onClear={onClearMock} /> ); const clearButton = await screen.findByRole('button', { name: /remove tag/i }); await userEvent.click(clearButton); expect(onClearMock).toHaveBeenCalled(); }); ``` ## Test Structure ### Basic Snapshot Test ```typescript import React from 'react'; import { ComponentName } from '../ComponentName'; import { renderSnapshotWithContextAsync } from '@epam/uui-test-utils'; describe('ComponentName', () => { describe('snapshots', () => { it('should be rendered with minimum props', async () => { const tree = await renderSnapshotWithContextAsync(<ComponentName />); expect(tree).toMatchSnapshot(); }); it('should be rendered with maximum props', async () => { const tree = await renderSnapshotWithContextAsync( <ComponentName prop1="value1" prop2="value2" /> ); expect(tree).toMatchSnapshot(); }); }); }); ``` ### Interaction Test ```typescript import { renderWithContextAsync, screen, userEvent } from '@epam/uui-test-utils'; it('should handle user interaction', async () => { const onActionMock = jest.fn(); await renderWithContextAsync( <ComponentName onAction={onActionMock} /> ); const button = await screen.findByRole('button'); await userEvent.click(button); expect(onActionMock).toHaveBeenCalled(); }); ``` ## Snapshot Update Workflow When UI changes require snapshot updates: 1. **Run tests** to see which snapshots fail: ```bash yarn test ``` 2. **Review changes** - verify the visual changes are intentional 3. **Update snapshots**: ```bash yarn test-update ``` 4. **Commit updated snapshots** along with component changes **Important:** Always review snapshot diffs before updating. Snapshots should reflect intentional UI changes, not accidental regressions. ## Test Environment - **Test framework:** Jest - **Test environment:** jsdom (for React components), node (for build scripts) - **Test utilities:** `@epam/uui-test-utils` for component testing helpers ## Test Coverage Test coverage is collected from: - `uui-core` - `uui-components` - `uui` - `epam-promo` - `epam-electric` - `loveship` Run `yarn test-report` to generate coverage reports. ## Common Patterns ### Mocking Portals for Snapshots Use the built-in helper instead of manual mocking: ```typescript import { mockReactPortalsForSnapshots, renderSnapshotWithContextAsync } from '@epam/uui-test-utils'; describe('ComponentWithPortal', () => { mockReactPortalsForSnapshots(); it('should render correctly', async () => { const tree = await renderSnapshotWithContextAsync(<MyModal />); expect(tree).toMatchSnapshot(); }); }); ``` ### Testing with Icons Use `SvgMock` from test utils for icon props in snapshots: ```typescript import { SvgMock, renderSnapshotWithContextAsync } from '@epam/uui-test-utils'; it('should render with icon', async () => { const tree = await renderSnapshotWithContextAsync( <Component icon={ SvgMock } /> ); expect(tree).toMatchSnapshot(); }); ``` For specific icon imports (when behavior depends on the icon): ```typescript // @ts-expect-error import { ReactComponent as CalendarIcon } from '@epam-assets/icons/action-calendar-fill.svg'; ``` ## Best Practices 1. **Add tests for bug fixes** - Prevent regressions 2. **Add tests for new functionality** - Ensure components work as expected 3. **Update snapshots when UI changes** - Keep snapshots current 4. **Run full test suite before committing** - `yarn test` 5. **Use descriptive test names** - Make failures easy to understand 6. **Test user interactions** - Not just rendering, but behavior ## References - Test utilities: `@epam/uui-test-utils` package - Example snapshot test: `uui/components/inputs/__tests__/NumericInput.test.tsx` - Example interaction test: `uui/components/widgets/__tests__/Tag.test.tsx` - Example setupComponentForTest: `app/src/docs/_examples/testing/__tests__/testComponent.test.tsx` - Example renderHookWithContextAsync: `uui-core/src/data/forms/__tests__/useForm.test.tsx` - Testing documentation: https://uui.epam.com/documents?id=testing-getting-started&mode=doc&isSkin=null&category=testing
GitHub에서 보기