Skip to content

Commit c4e2adc

Browse files
committed
safer impl
1 parent d2ce883 commit c4e2adc

File tree

4 files changed

+19
-11
lines changed

4 files changed

+19
-11
lines changed

build-tools/jest/setup.js

-8
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,4 @@ if (typeof window !== 'undefined') {
66
require('@testing-library/jest-dom/extend-expect');
77
const { cleanup } = require('@testing-library/react');
88
afterEach(cleanup);
9-
10-
// Autosuggest input blur handler uses document.hasFocus() to optimize user experience when focus leaves the page.
11-
// In JSDOM the hasFocus() always returns false which differs from the in-browser experience, so setting it to true using mock.
12-
// See: https://github.com/jsdom/jsdom/issues/3794
13-
beforeEach(() => {
14-
// eslint-disable-next-line no-undef
15-
jest.spyOn(window.document, 'hasFocus').mockImplementation(() => true);
16-
});
179
}

src/autosuggest/__tests__/autosuggest.test.tsx

+10-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { KeyCode } from '@cloudscape-design/test-utils-core/utils';
88

99
import '../../__a11y__/to-validate-a11y';
1010
import Autosuggest, { AutosuggestProps } from '../../../lib/components/autosuggest';
11+
import { documentHasFocus } from '../../../lib/components/internal/utils/dom';
1112
import createWrapper from '../../../lib/components/test-utils/dom';
1213

1314
import itemStyles from '../../../lib/components/internal/components/selectable-item/styles.css.js';
@@ -43,8 +44,15 @@ jest.mock('@cloudscape-design/component-toolkit/internal', () => {
4344
warnOnce: jest.fn(),
4445
};
4546
});
47+
48+
jest.mock('../../../lib/components/internal/utils/dom', () => ({
49+
...jest.requireActual('../../../lib/components/internal/utils/dom'),
50+
documentHasFocus: jest.fn(() => true),
51+
}));
52+
4653
beforeEach(() => {
47-
(warnOnce as any).mockClear();
54+
(warnOnce as jest.Mock).mockClear();
55+
(documentHasFocus as jest.Mock).mockClear();
4856
});
4957

5058
test('renders correct labels when focused', () => {
@@ -131,7 +139,7 @@ test('should close dropdown on blur when document is in focus', () => {
131139
});
132140

133141
test('should not close dropdown on blur when document is not in focus', () => {
134-
jest.spyOn(document, 'hasFocus').mockImplementation(() => false);
142+
(documentHasFocus as jest.Mock).mockImplementation(() => false);
135143

136144
const { wrapper } = renderAutosuggest(<Autosuggest enteredTextLabel={v => v} value="1" options={defaultOptions} />);
137145
wrapper.findNativeInput().focus();

src/internal/components/autosuggest-input/index.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { FormFieldValidationControlProps, useFormFieldContext } from '../../cont
1818
import { BaseKeyDetail, fireCancelableEvent, fireNonCancelableEvent, NonCancelableEventHandler } from '../../events';
1919
import { InternalBaseComponentProps } from '../../hooks/use-base-component';
2020
import { KeyCode } from '../../keycode';
21+
import { documentHasFocus } from '../../utils/dom';
2122
import { nodeBelongs } from '../../utils/node-belongs';
2223
import Dropdown from '../dropdown';
2324
import { ExpandToViewport } from '../dropdown/interfaces';
@@ -132,7 +133,7 @@ const AutosuggestInput = React.forwardRef(
132133
const handleBlur = () => {
133134
// When the document in not in focus it means the focus moved outside the page. In that case the dropdown shall stay open
134135
// so that when the user comes back it does not re-open unexpectedly when the focus is restored by the browser.
135-
if (!document.hasFocus()) {
136+
if (!documentHasFocus()) {
136137
return;
137138
}
138139
if (!preventCloseOnBlurRef.current) {

src/internal/utils/dom.ts

+7
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,10 @@ export function isSVGElement(target: unknown): target is SVGElement {
128128
typeof target.ownerSVGElement === 'object')
129129
);
130130
}
131+
132+
export function documentHasFocus() {
133+
// In JSDOM the hasFocus() always returns false which differs from the in-browser experience, see: https://github.com/jsdom/jsdom/issues/3794.
134+
// Thus, when detecting JSDOM environment we return true here explicitly for the tests to work expectedly.
135+
const isJSDOM = typeof navigator !== 'undefined' && navigator.userAgent.includes('jsdom');
136+
return isJSDOM || document.hasFocus();
137+
}

0 commit comments

Comments
 (0)