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',
+};