Загрузка данных
import { fireEvent, render, screen } from '@testing-library/react';
import { ReactNode } from 'react';
import SplitDropdown from './index';
interface MockDropdownProps {
position?: string;
buttonClassName?: string;
renderTrigger: (params: {
isOpen: boolean;
onToggle: () => void;
}) => ReactNode;
children?: ReactNode;
}
interface MockButtonProps {
className?: string;
pressed?: boolean;
onClick?: () => void;
label?: ReactNode;
}
interface MockTooltipProps {
children?: ReactNode;
tooltipClassName?: string;
showMessageOnFocus?: boolean;
label?: string;
}
jest.mock('../Dropdown', () => {
const { useState } = jest.requireActual<typeof import('react')>('react');
return {
Dropdown: ({
position,
buttonClassName,
renderTrigger,
children,
}: MockDropdownProps) => {
const [isOpen, setIsOpen] = useState(false);
return (
<div
data-testid="dropdown"
data-position={position}
data-button-class-name={buttonClassName}
>
{renderTrigger({
isOpen,
onToggle: () => setIsOpen((value) => !value),
})}
{isOpen && <div data-testid="dropdown-content">{children}</div>}
</div>
);
},
};
});
jest.mock('@src/components/Button', () => ({
Button: ({
className,
pressed,
onClick,
label,
}: MockButtonProps) => (
<button
type="button"
className={className}
data-pressed={String(Boolean(pressed))}
onClick={onClick}
>
{label}
</button>
),
}));
jest.mock('@src/components/Tooltip', () => ({
Tooltip: ({
children,
tooltipClassName,
showMessageOnFocus,
label,
}: MockTooltipProps) => (
<div
data-testid="tooltip"
data-tooltip-class-name={tooltipClassName}
data-show-message-on-focus={String(showMessageOnFocus)}
data-label={label}
>
{children}
</div>
),
}));
jest.mock('@src/components/Icon/SmallChevronLeft', () => ({
__esModule: true,
default: () => <span data-testid="default-menu-content">Chevron</span>,
}));
describe('SplitDropdown', () => {
it('должен использовать значения по умолчанию в закрытом состоянии', () => {
render(
<SplitDropdown mainContent={<span>Основная кнопка</span>}>
<div>Содержимое меню</div>
</SplitDropdown>,
);
const dropdown = screen.getByTestId('dropdown');
const buttons = screen.getAllByRole('button');
const tooltips = screen.getAllByTestId('tooltip');
expect(dropdown).toHaveAttribute('data-position', 'right');
expect(buttons[0]).toHaveAttribute('data-pressed', 'false');
expect(buttons[1]).toHaveAttribute('data-pressed', 'false');
expect(tooltips[0]).toHaveAttribute(
'data-show-message-on-focus',
'true',
);
expect(tooltips[1]).toHaveAttribute(
'data-show-message-on-focus',
'true',
);
expect(screen.getByTestId('default-menu-content')).toBeInTheDocument();
expect(screen.queryByTestId('dropdown-content')).not.toBeInTheDocument();
});
it('должен устанавливать pressed для основной кнопки через mainButtonPressed', () => {
render(
<SplitDropdown
mainButtonPressed
mainContent={<span>Основная кнопка</span>}
>
<div>Содержимое меню</div>
</SplitDropdown>,
);
const buttons = screen.getAllByRole('button');
expect(buttons[0]).toHaveAttribute('data-pressed', 'true');
expect(buttons[1]).toHaveAttribute('data-pressed', 'false');
});
it('должен переводить обе кнопки в pressed состояние при открытии меню', () => {
render(
<SplitDropdown mainContent={<span>Основная кнопка</span>}>
<div>Содержимое меню</div>
</SplitDropdown>,
);
fireEvent.click(screen.getAllByRole('button')[1]);
const buttons = screen.getAllByRole('button');
const tooltips = screen.getAllByTestId('tooltip');
expect(buttons[0]).toHaveAttribute('data-pressed', 'true');
expect(buttons[1]).toHaveAttribute('data-pressed', 'true');
expect(
screen.getByText('Основная кнопка').closest('.dropdown'),
).toHaveClass('open');
expect(tooltips[0]).toHaveAttribute(
'data-show-message-on-focus',
'false',
);
expect(tooltips[1]).toHaveAttribute(
'data-show-message-on-focus',
'false',
);
expect(screen.getByTestId('dropdown-content')).toHaveTextContent(
'Содержимое меню',
);
});
it('должен вызывать обработчик основной кнопки', () => {
const onMainClick = jest.fn();
render(
<SplitDropdown
mainContent={<span>Основная кнопка</span>}
onMainClick={onMainClick}
>
<div>Содержимое меню</div>
</SplitDropdown>,
);
fireEvent.click(screen.getAllByRole('button')[0]);
expect(onMainClick).toHaveBeenCalledTimes(1);
});
it('должен передавать классы основной кнопке и тултипам', () => {
render(
<SplitDropdown
mainContent={<span>Основная кнопка</span>}
mainButtonClassName="main-button-class"
tooltipClassName="tooltip-class"
>
<div>Содержимое меню</div>
</SplitDropdown>,
);
const buttons = screen.getAllByRole('button');
const tooltips = screen.getAllByTestId('tooltip');
expect(buttons[0]).toHaveClass('main-button-class');
expect(buttons[1]).toHaveClass('menu_button');
expect(tooltips[0]).toHaveAttribute(
'data-tooltip-class-name',
'tooltip__main tooltip-class',
);
expect(tooltips[1]).toHaveAttribute(
'data-tooltip-class-name',
'tooltip-class',
);
});
});