diff --git a/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyTruncateIntegration.test.tsx b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyTruncateIntegration.test.tsx new file mode 100644 index 00000000000..d6554557cf9 --- /dev/null +++ b/packages/react-core/src/components/ClipboardCopy/__tests__/ClipboardCopyTruncateIntegration.test.tsx @@ -0,0 +1,32 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { ClipboardCopy, ClipboardCopyVariant } from '../ClipboardCopy'; + +// This test file uses the real Truncate component for integration testing, instead of a mock + +test('Tooltip appears on keyboard focus when using inline-compact variant with truncation', async () => { + const user = userEvent.setup(); + const longText = 'This is a very long piece of content that should be truncated when the container is too small'; + + render( + + {longText} + + ); + + expect(screen.queryByText(longText)).not.toBeInTheDocument(); + expect(screen.queryByRole('tooltip')).not.toBeInTheDocument(); + + await user.tab(); + + const clipboardCopy = screen.getByTestId('clipboard-copy'); + expect(clipboardCopy).toHaveFocus(); + + const tooltip = screen.getByRole('tooltip'); + expect(tooltip).toBeInTheDocument(); + expect(tooltip).toHaveTextContent(longText); +}); diff --git a/packages/react-core/src/components/Truncate/Truncate.tsx b/packages/react-core/src/components/Truncate/Truncate.tsx index a4c9306330b..9a8d00da11d 100644 --- a/packages/react-core/src/components/Truncate/Truncate.tsx +++ b/packages/react-core/src/components/Truncate/Truncate.tsx @@ -4,6 +4,7 @@ import { css } from '@patternfly/react-styles'; import { Tooltip, TooltipPosition, TooltipProps } from '../Tooltip'; import { getReferenceElement } from '../../helpers'; import { getResizeObserver } from '../../helpers/resizeObserver'; +import { debounce } from '../../helpers/util'; export enum TruncatePosition { start = 'start', @@ -130,12 +131,12 @@ const TruncateBase: React.FunctionComponent = ({ const totalTextWidth = calculateTotalTextWidth(textElement, trailingNumChars, content); const textWidth = position === 'middle' ? totalTextWidth : textElement.scrollWidth; - const handleResize = () => { + const debouncedHandleResize = debounce(() => { const parentWidth = getActualWidth(parentElement); setIsTruncated(textWidth >= parentWidth); - }; + }, 500); - const observer = getResizeObserver(parentElement, handleResize); + const observer = getResizeObserver(parentElement, debouncedHandleResize); return () => { observer(); @@ -147,7 +148,7 @@ const TruncateBase: React.FunctionComponent = ({ if (shouldRenderByMaxChars) { setIsTruncated(content.length > maxCharsDisplayed); } - }, [shouldRenderByMaxChars]); + }, [shouldRenderByMaxChars, content.length, maxCharsDisplayed]); useEffect(() => { setShouldRenderByMaxChars(maxCharsDisplayed > 0); diff --git a/packages/react-core/src/components/Truncate/__tests__/Truncate.test.tsx b/packages/react-core/src/components/Truncate/__tests__/Truncate.test.tsx index ba899283509..f4dbf10435b 100644 --- a/packages/react-core/src/components/Truncate/__tests__/Truncate.test.tsx +++ b/packages/react-core/src/components/Truncate/__tests__/Truncate.test.tsx @@ -1,12 +1,12 @@ -import { render, screen, within } from '@testing-library/react'; -import { Truncate, TruncatePosition } from '../Truncate'; +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} + Test {content} {`position: ${position}`} {children} @@ -242,3 +242,21 @@ describe('Truncation with maxCharsDisplayed', () => { 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(); +}); diff --git a/packages/react-core/src/components/Truncate/__tests__/__snapshots__/Truncate.test.tsx.snap b/packages/react-core/src/components/Truncate/__tests__/__snapshots__/Truncate.test.tsx.snap index b4dd9550d7c..3ef40ffb16c 100644 --- a/packages/react-core/src/components/Truncate/__tests__/__snapshots__/Truncate.test.tsx.snap +++ b/packages/react-core/src/components/Truncate/__tests__/__snapshots__/Truncate.test.tsx.snap @@ -5,9 +5,7 @@ exports[`Truncation with maxCharsDisplayed Matches snapshot with default positio - + Test Test truncation content @@ -43,9 +41,7 @@ exports[`renders default truncation 1`] = ` - + Test Vestibulum interdum risus et enim faucibus, sit amet molestie est accumsan. @@ -70,9 +66,7 @@ exports[`renders start truncation with at start and end 1`] = ` - + Test Vestibulum interdum risus et enim faucibus, sit amet molestie est accumsan.
{`position: ${position}`}
@@ -43,9 +41,7 @@ exports[`renders default truncation 1`] = `
@@ -70,9 +66,7 @@ exports[`renders start truncation with at start and end 1`] = `