From 38ef9ef99f431aa63d7549b6eea2ce2071078969 Mon Sep 17 00:00:00 2001 From: ssanekmix Date: Wed, 15 Apr 2026 18:57:48 +0300 Subject: [PATCH] YH-1863: add tests for the ProgressBar component --- .../ui/ProgressBar/ProgressBar.skeleton.tsx | 12 +- .../ui/ProgressBar/ProgressBar.test.tsx | 125 ++++++++++++++++++ src/shared/ui/ProgressBar/ProgressBar.tsx | 14 +- src/shared/ui/ProgressBar/constants.ts | 7 + 4 files changed, 154 insertions(+), 4 deletions(-) create mode 100644 src/shared/ui/ProgressBar/ProgressBar.test.tsx create mode 100644 src/shared/ui/ProgressBar/constants.ts diff --git a/src/shared/ui/ProgressBar/ProgressBar.skeleton.tsx b/src/shared/ui/ProgressBar/ProgressBar.skeleton.tsx index 19e0f7b3b..e29a0eb7b 100644 --- a/src/shared/ui/ProgressBar/ProgressBar.skeleton.tsx +++ b/src/shared/ui/ProgressBar/ProgressBar.skeleton.tsx @@ -1,14 +1,22 @@ import { Skeleton } from '@/shared/ui/Skeleton'; import { TextSkeleton } from '@/shared/ui/Text'; +import { progressBarTestIds } from './constants'; import { ProgressBarProps } from './ProgressBar'; import styles from './ProgressBar.module.css'; export const ProgressBarSkeleton = ({ label, className, variant = 'small' }: ProgressBarProps) => { return ( -
+
- {label && } + {label && ( + + )}
); }; diff --git a/src/shared/ui/ProgressBar/ProgressBar.test.tsx b/src/shared/ui/ProgressBar/ProgressBar.test.tsx new file mode 100644 index 000000000..99d3c19f9 --- /dev/null +++ b/src/shared/ui/ProgressBar/ProgressBar.test.tsx @@ -0,0 +1,125 @@ +import { render, screen } from '@testing-library/react'; + +import { progressBarTestIds } from './constants'; +import { ProgressBar } from './ProgressBar'; +import { ProgressBarSkeleton } from './ProgressBar.skeleton'; + +describe('ProgressBar label', () => { + test('renders label when label prop is passed', () => { + render(); + + const label = screen.getByTestId(progressBarTestIds.label); + + expect(label).toBeInTheDocument(); + expect(label).toHaveTextContent('Label'); + }); + + test('does not render label when label prop is not passed', () => { + render(); + + expect(screen.queryByTestId(progressBarTestIds.label)).toBeNull(); + }); +}); + +describe('ProgressBar progress', () => { + test('renders progress element with correct value and max', () => { + render(); + + const progress = screen.getByTestId(progressBarTestIds.progress); + + expect(progress).toBeInTheDocument(); + expect(progress).toHaveAttribute('value', '1'); + expect(progress).toHaveAttribute('max', '10'); + }); + + test('does not apply color class when color prop is not passed', () => { + render(); + + const progress = screen.getByTestId(progressBarTestIds.progress); + + expect(progress).toHaveClass('progress-bar-small'); + expect(progress.className).not.toMatch(/progress-bar-(green|yellow|red)/); + }); + + test('applies green color class when color prop is "green"', () => { + render(); + + const progress = screen.getByTestId(progressBarTestIds.progress); + + expect(progress).toBeInTheDocument(); + expect(progress).toHaveClass('progress-bar-green'); + }); +}); + +describe('ProgressBar variant', () => { + test('renders small variant when variant prop is not passed', () => { + render(); + + const progress = screen.getByTestId(progressBarTestIds.progress); + const label = screen.getByTestId(progressBarTestIds.label); + + expect(progress).toBeInTheDocument(); + expect(label).toBeInTheDocument(); + + expect(progress).toHaveClass('progress-bar-small'); + expect(label).toHaveClass('label-small'); + }); + + test('applies medium variant classes when variant prop is "medium"', () => { + render(); + + const progress = screen.getByTestId(progressBarTestIds.progress); + + expect(progress).toBeInTheDocument(); + + expect(progress).toHaveClass('progress-bar-medium'); + }); + + test('applies large variant classes when variant prop is "large"', () => { + render(); + + const progress = screen.getByTestId(progressBarTestIds.progress); + const label = screen.getByTestId(progressBarTestIds.label); + + expect(progress).toBeInTheDocument(); + expect(label).toBeInTheDocument(); + + expect(progress).toHaveClass('progress-bar-large'); + expect(label).toHaveClass('label-large'); + }); +}); + +describe('ProgressBar', () => { + test('applies custom classname to wrapper', () => { + render(); + + const wrapper = screen.getByTestId(progressBarTestIds.wrapper); + + expect(wrapper).toBeInTheDocument(); + expect(wrapper).toHaveClass('custom-class'); + }); +}); + +describe('ProgressBarSkeleton', () => { + test('renders progress bar skeleton', () => { + render(); + + const skeleton = screen.getByTestId(progressBarTestIds.skeleton); + + expect(skeleton).toBeInTheDocument(); + }); + + test('renders text skeleton when label prop is passed', () => { + render(); + + const textSkeleton = screen.getByTestId(progressBarTestIds.textSkeleton); + + expect(textSkeleton).toBeInTheDocument(); + }); + + test('does not render text skeleton when label prop is not passed', () => { + render(); + + expect(screen.queryByTestId(progressBarTestIds.textSkeleton)).toBeNull(); + }); +}); diff --git a/src/shared/ui/ProgressBar/ProgressBar.tsx b/src/shared/ui/ProgressBar/ProgressBar.tsx index 87967b8bd..f47caf1ce 100644 --- a/src/shared/ui/ProgressBar/ProgressBar.tsx +++ b/src/shared/ui/ProgressBar/ProgressBar.tsx @@ -2,6 +2,7 @@ import classNames from 'classnames'; import { Text } from '@/shared/ui/Text'; +import { progressBarTestIds } from './constants'; import styles from './ProgressBar.module.css'; export type ProgressBarVariant = 'small' | 'large' | 'medium'; @@ -25,7 +26,10 @@ export const ProgressBar = ({ color, }: ProgressBarProps) => { return ( -
+
{label && ( - + {label} )} diff --git a/src/shared/ui/ProgressBar/constants.ts b/src/shared/ui/ProgressBar/constants.ts new file mode 100644 index 000000000..fb24f982b --- /dev/null +++ b/src/shared/ui/ProgressBar/constants.ts @@ -0,0 +1,7 @@ +export const progressBarTestIds = { + wrapper: 'ProgressBarWrapper', + progress: 'ProgressBarProgress', + label: 'ProgressBarLabel', + skeleton: 'ProgressBarSkeleton', + textSkeleton: 'ProgressBarTextSkeleton', +};