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.tsxuui/components/inputs/__tests__/NumericInput.test.tsxuui-core/src/hooks/__tests__/useVirtualList.test.tsx
Test Commands
Run all tests:
yarn test
Run tests in watch mode:
yarn test-watch
Run a single test file:
yarn test -- --testPathPattern="Button"
Use --testPathPattern to match file path, or --testNamePattern="should render" to match test names.
Update snapshots:
yarn test-update
Generate test coverage report:
yarn test-report
Coverage report saves to .reports/unit-tests folder.
TypeScript type checking:
yarn test-typecheck
Windows workaround: If encountering test errors on Windows, use reduced worker count:
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:
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:
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
renderHookfrom Testing Library
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:
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
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
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:
Run tests to see which snapshots fail:
yarn testReview changes - verify the visual changes are intentional
Update snapshots:
yarn test-updateCommit 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-utilsfor component testing helpers
Test Coverage
Test coverage is collected from:
uui-coreuui-componentsuuiepam-promoepam-electricloveship
Run yarn test-report to generate coverage reports.
Common Patterns
Mocking Portals for Snapshots
Use the built-in helper instead of manual mocking:
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:
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):
// @ts-expect-error
import { ReactComponent as CalendarIcon } from '@epam-assets/icons/action-calendar-fill.svg';
Best Practices
- Add tests for bug fixes - Prevent regressions
- Add tests for new functionality - Ensure components work as expected
- Update snapshots when UI changes - Keep snapshots current
- Run full test suite before committing -
yarn test - Use descriptive test names - Make failures easy to understand
- Test user interactions - Not just rendering, but behavior
References
- Test utilities:
@epam/uui-test-utilspackage - 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