import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { Truncate } from '../Truncate';
import styles from '@patternfly/react-styles/css/components/Truncate/truncate';
import '@testing-library/jest-dom';
jest.mock('../../Tooltip', () => ({
Tooltip: ({ content, position, children, triggerRef, ...props }) => (
Test {content}
{`position: ${position}`}
{children}
)
}));
global.ResizeObserver = jest.fn().mockImplementation(() => ({
observe: jest.fn(),
unobserve: jest.fn(),
disconnect: jest.fn()
}));
test('Renders with span wrapper by default', () => {
render();
expect(screen.getByTestId('test-id').tagName).toBe('SPAN');
});
test('Renders with anchor wrapper when href prop is passed', () => {
render();
expect(screen.getByRole('link')).toHaveTextContent('Link content');
});
test('Passes href to anchor when href prop is passed', () => {
render();
expect(screen.getByRole('link')).toHaveAttribute('href', '#home');
});
test(`renders with class ${styles.truncate}`, () => {
render();
const test = screen.getByLabelText('test-id');
expect(test).toHaveClass(styles.truncate, { exact: true });
});
test('renders with custom class name passed via prop', () => {
render();
const test = screen.getByLabelText('test-id');
expect(test).toHaveClass('custom-classname');
});
test('renders truncate with empty content', () => {
render();
const test = screen.getByLabelText('test-id');
expect(test).toHaveTextContent('');
});
test('renders truncate with content', () => {
render();
const test = screen.getByLabelText('test-id');
expect(test).toHaveTextContent('Test');
});
test(`only renders ${styles.truncateStart} with default position`, () => {
render();
const start = screen.getByText('Testing truncate content');
expect(start).toHaveClass(styles.truncateStart);
expect(start).not.toHaveClass(styles.truncateEnd);
});
test('renders default truncation', () => {
const { asFragment } = render(
);
expect(asFragment()).toMatchSnapshot();
});
// If this snapshot fails and the output text doesn't seem like it's changed, it most likely
// is due to the HTML entity isn't rendering correctly.
test('renders start truncation with at start and end', () => {
const { asFragment } = render(
);
expect(asFragment()).toMatchSnapshot();
});
test('renders middle truncation', () => {
render(
);
const start = screen.getByText('Vestibulum interdum risus et enim faucibus, sit amet molestie est ac');
expect(start).toHaveClass(styles.truncateStart);
const end = screen.getByText('cumsan.');
expect(end).toHaveClass(styles.truncateEnd);
});
test('renders different content when trailingNumChars is passed with middle truncate', () => {
render(
);
const start = screen.getByText('Vestibulum interdum risus et enim faucibus, sit amet molestie est accums');
expect(start).toHaveClass(styles.truncateStart);
const end = screen.getByText('an.');
expect(end).toHaveClass(styles.truncateEnd);
});
test('renders full content when trailingNumChars exceeds the length of the original string using middle truncate', () => {
render(
);
const start = screen.getByText('Vestibulum interdum risus et enim faucibus, sit amet molestie est accumsan.');
expect(start).toHaveClass(styles.truncateStart);
expect(start).not.toHaveClass(styles.truncateEnd);
});
test('renders tooltip position', () => {
render();
const input = screen.getByText('position: top');
expect(input).toBeVisible();
});
test('renders tooltip content', () => {
render();
const input = screen.getByText('Test Another Tooltip');
expect(input).toBeVisible();
});
test('Renders with additional tooltip props spread', () => {
render();
expect(screen.getByTestId('Tooltip-mock')).toHaveAttribute('distance', '32');
});
test('renders with inherited element props spread to the component', () => {
render();
expect(screen.getByTestId('test-id')).toHaveAccessibleName('labelling-id');
});
describe('Truncation with maxCharsDisplayed', () => {
test(`Does not render with class ${styles.modifiers.fixed} when maxCharsDisplayed is 0`, () => {
render();
expect(screen.getByTestId('truncate-component')).not.toHaveClass(styles.modifiers.fixed);
});
test(`Renders with class ${styles.modifiers.fixed} when maxCharsDisplayed is greater than 0`, () => {
render();
expect(screen.getByTestId('truncate-component')).toHaveClass(styles.modifiers.fixed);
});
test('Renders with hidden truncated content at end by default when maxCharsDisplayed is passed', () => {
render();
expect(screen.getByText('Defaul')).toHaveClass(`${styles.truncate}__text`, { exact: true });
expect(screen.getByText('t end position content truncated')).toHaveClass('pf-v6-screen-reader');
});
test('Renders with hidden truncated content at middle position when maxCharsDisplayed is passed and position="middle"', () => {
render();
expect(screen.getByText('Middl')).toHaveClass(`${styles.truncate}__text`, { exact: true });
expect(screen.getByText('e position contents being trun')).toHaveClass('pf-v6-screen-reader');
expect(screen.getByText('cated')).toHaveClass(`${styles.truncate}__text`, { exact: true });
});
test('Renders with hidden truncated content at start when maxCharsDisplayed is passed and position="start"', () => {
render();
expect(screen.getByText('Start position content tru')).toHaveClass('pf-v6-screen-reader');
expect(screen.getByText('ncated')).toHaveClass(`${styles.truncate}__text`, { exact: true });
});
test('Renders full content when maxCharsDisplayed exceeds the length of the content', () => {
render();
expect(screen.getByText('This full content is rendered')).toHaveClass(`${styles.truncate}__text`, { exact: true });
});
test('Renders ellipsis as omission content by default', () => {
render();
expect(screen.getByText('\u2026')).toHaveClass(`${styles.truncate}__omission`, { exact: true });
expect(screen.getByText('\u2026')).toHaveAttribute('aria-hidden', 'true');
});
test('Renders custom omission content when omissionContent is passed', () => {
render();
expect(screen.getByText('---')).toHaveClass(`${styles.truncate}__omission`, { exact: true });
expect(screen.getByText('---')).toHaveAttribute('aria-hidden', 'true');
});
test('Does not render omission content when maxCharsDisplayed exceeds the length of the content ', () => {
render();
expect(screen.queryByText('\u2026')).not.toBeInTheDocument();
});
test('Matches snapshot with default position', () => {
const { asFragment } = render();
expect(asFragment()).toMatchSnapshot();
});
});
test('Tooltip appears on keyboard focus when external triggerRef is provided (ClipboardCopy regression test)', () => {
const mockTriggerRef = { current: document.createElement('div') };
render(
);
// Simulate keyboard focus on the external trigger element
fireEvent.focus(mockTriggerRef.current);
// The tooltip should be present and visible
const tooltip = screen.getByTestId('Tooltip-mock');
expect(tooltip).toBeInTheDocument();
});