Skip to content

Commit 5187d62

Browse files
authored
Merge pull request #1063 from lumapps/chore/fix-tooltip-escape-handler
chore(tooltip): fix escape key handler only when open
2 parents 87ebe1c + 5991f7f commit 5187d62

File tree

2 files changed

+33
-36
lines changed

2 files changed

+33
-36
lines changed

packages/lumx-react/src/components/tooltip/Tooltip.test.tsx

Lines changed: 32 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
11
import React from 'react';
22

33
import { Button } from '@lumx/react';
4-
import { act, render, waitFor } from '@testing-library/react';
5-
import {
6-
findByClassName,
7-
getByClassName,
8-
queryAllByTagName,
9-
queryByClassName,
10-
} from '@lumx/react/testing/utils/queries';
4+
import { screen, render, waitFor } from '@testing-library/react';
5+
import { queryAllByTagName, queryByClassName } from '@lumx/react/testing/utils/queries';
116
import { commonTestsSuiteRTL } from '@lumx/react/testing/utils';
127
import userEvent from '@testing-library/user-event';
138

@@ -16,23 +11,19 @@ import { Tooltip, TooltipProps } from './Tooltip';
1611
const CLASSNAME = Tooltip.className as string;
1712

1813
jest.mock('uid', () => ({ uid: () => 'uid' }));
14+
// Skip delays
15+
jest.mock('@lumx/react/constants', () => ({
16+
...jest.requireActual('@lumx/react/constants'),
17+
TOOLTIP_HOVER_DELAY: { open: 0, close: 0 },
18+
}));
1919

2020
/**
2121
* Mounts the component and returns common DOM elements / data needed in multiple tests further down.
2222
*/
2323
const setup = async (propsOverride: Partial<TooltipProps> = {}) => {
24-
const props: any = { forceOpen: true, ...propsOverride };
25-
// Hack to remove act() warning in console
26-
await (act as any)(() =>
27-
Promise.resolve(
28-
render(
29-
<Tooltip label="Tooltip" {...props}>
30-
{props.children || 'Anchor'}
31-
</Tooltip>,
32-
),
33-
),
34-
);
35-
const tooltip = queryByClassName(document.body, CLASSNAME);
24+
const props: any = { forceOpen: true, label: 'Tooltip label', children: 'Anchor', ...propsOverride };
25+
render(<Tooltip {...props} />);
26+
const tooltip = screen.queryByRole('tooltip', { name: props.label });
3627
const anchorWrapper = queryByClassName(document.body, 'lumx-tooltip-anchor-wrapper');
3728
return { props, tooltip, anchorWrapper };
3829
};
@@ -67,7 +58,7 @@ describe(`<${Tooltip.displayName}>`, () => {
6758
});
6859
expect(tooltip).toBeInTheDocument();
6960
expect(anchorWrapper).not.toBeInTheDocument();
70-
const button = queryByClassName(document.body, Button.className as string);
61+
const button = screen.queryByRole('button', { name: 'Anchor' });
7162
expect(button).toHaveAttribute('aria-describedby', tooltip?.id);
7263
});
7364

@@ -80,7 +71,7 @@ describe(`<${Tooltip.displayName}>`, () => {
8071
expect(tooltip).toBeInTheDocument();
8172
expect(anchorWrapper).toBeInTheDocument();
8273
expect(anchorWrapper).toHaveAttribute('aria-describedby', tooltip?.id);
83-
const button = queryByClassName(document.body, Button.className as string);
74+
const button = screen.queryByRole('button', { name: 'Anchor' });
8475
expect(button?.parentElement).toBe(anchorWrapper);
8576
});
8677

@@ -108,11 +99,11 @@ describe(`<${Tooltip.displayName}>`, () => {
10899
expect(tooltip).not.toBeInTheDocument();
109100

110101
// Hover anchor button
111-
const button = getByClassName(document.body, Button.className as string);
102+
const button = screen.getByRole('button', { name: 'Anchor' });
112103
await userEvent.hover(button);
113104

114105
// Tooltip opened
115-
tooltip = await findByClassName(document.body, CLASSNAME);
106+
tooltip = await screen.findByRole('tooltip', { name: 'Tooltip label' });
116107
expect(tooltip).toBeInTheDocument();
117108
expect(button).toHaveAttribute('aria-describedby', tooltip?.id);
118109

@@ -135,11 +126,11 @@ describe(`<${Tooltip.displayName}>`, () => {
135126
expect(tooltip).not.toBeInTheDocument();
136127

137128
// Hover anchor button
138-
const button = getByClassName(document.body, Button.className as string);
129+
const button = screen.getByRole('button', { name: 'Anchor' });
139130
await userEvent.hover(button);
140131

141132
// Tooltip opened
142-
tooltip = await findByClassName(document.body, CLASSNAME);
133+
tooltip = await screen.findByRole('tooltip', { name: 'Tooltip label' });
143134
expect(tooltip).toBeInTheDocument();
144135
expect(button).toHaveAttribute('aria-describedby', tooltip?.id);
145136

@@ -157,7 +148,7 @@ describe(`<${Tooltip.displayName}>`, () => {
157148
});
158149
});
159150

160-
it('should activate on anchor focus', async () => {
151+
it('should activate on anchor focus and close on escape', async () => {
161152
let { tooltip } = await setup({
162153
label: 'Tooltip label',
163154
children: <Button>Anchor</Button>,
@@ -168,21 +159,27 @@ describe(`<${Tooltip.displayName}>`, () => {
168159

169160
// Focus anchor button
170161
await userEvent.tab();
171-
const button = getByClassName(document.body, Button.className as string);
162+
const button = screen.getByRole('button', { name: 'Anchor' });
172163
expect(button).toHaveFocus();
173164

174165
// Tooltip opened
175-
tooltip = await findByClassName(document.body, CLASSNAME);
166+
tooltip = await screen.findByRole('tooltip', { name: 'Tooltip label' });
176167
expect(tooltip).toBeInTheDocument();
177168
expect(button).toHaveAttribute('aria-describedby', tooltip?.id);
178169

179-
// Focus next element
180-
userEvent.tab();
181-
await waitFor(() => {
182-
expect(button).not.toHaveFocus();
183-
// Tooltip closed
184-
expect(tooltip).not.toBeInTheDocument();
185-
});
170+
// Focus next element => close tooltip
171+
await userEvent.tab();
172+
expect(button).not.toHaveFocus();
173+
expect(tooltip).not.toBeInTheDocument();
174+
175+
// Focus again
176+
await userEvent.tab({ shift: true });
177+
tooltip = await screen.findByRole('tooltip', { name: 'Tooltip label' });
178+
expect(tooltip).toBeInTheDocument();
179+
180+
// Escape pressed => close tooltip
181+
await userEvent.keyboard('{Escape}');
182+
expect(tooltip).not.toBeInTheDocument();
186183
});
187184
});
188185

packages/lumx-react/src/components/tooltip/useTooltipOpen.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export function useTooltipOpen(delay: number | undefined, anchorElement: HTMLEle
1717

1818
// Global close on escape
1919
const [closeCallback, setCloseCallback] = useState<undefined | (() => void)>(undefined);
20-
useCallbackOnEscape(closeCallback);
20+
useCallbackOnEscape(isOpen ? closeCallback : undefined);
2121

2222
useEffect(() => {
2323
if (!anchorElement) {

0 commit comments

Comments
 (0)