import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { describe, it, expect, vi } from 'vitest';
import { Tooltip, TooltipTrigger, TooltipContent } from './tooltip';
import React from 'react';
// Mocking Portal
vi.mock('@radix-ui/react-tooltip', async () => {
const actual = await vi.importActual('@radix-ui/react-tooltip');
return {
...actual,
Portal: ({ children }: { children: React.ReactNode }) => (
{children}
),
};
});
describe('Tooltip', () => {
it('renders correctly', () => {
render(
Hover me
Tooltip info
);
expect(screen.getByText('Hover me')).toBeInTheDocument();
});
it('shows content when open is true', () => {
render(
Hover me
Tooltip info
);
expect(screen.getAllByText('Tooltip info')[0]).toBeInTheDocument();
});
it('shows content on hover and hides it on unhover', async () => {
const user = userEvent.setup();
render(
// `disableHoverableContent` skips Radix's "pointer grace area" transition,
// which otherwise only closes once a follow-up pointermove is detected
// outside the trigger/content polygon (not simulated by userEvent.unhover).
Hover me
Tooltip info
);
expect(screen.queryByText('Tooltip info')).not.toBeInTheDocument();
const trigger = screen.getByText('Hover me');
await user.hover(trigger);
await waitFor(() => {
expect(screen.getAllByText('Tooltip info')[0]).toBeInTheDocument();
});
await user.unhover(trigger);
await waitFor(() => {
expect(screen.queryByText('Tooltip info')).not.toBeInTheDocument();
});
});
it('shows content on focus and hides it on Escape', async () => {
const user = userEvent.setup();
render(
Focus me
Tooltip info
);
expect(screen.queryByText('Tooltip info')).not.toBeInTheDocument();
await user.tab();
await waitFor(() => {
expect(screen.getAllByText('Tooltip info')[0]).toBeInTheDocument();
});
await user.keyboard('{Escape}');
await waitFor(() => {
expect(screen.queryByText('Tooltip info')).not.toBeInTheDocument();
});
});
});