Skip to content

Commit c0cbdad

Browse files
committed
fix(cdk/testing): simulate focusin/focusout events
Fixes that our fake fallback focus events weren't dispatching `focusin` and `focusout` events as well. Fixes #23757.
1 parent 92863cc commit c0cbdad

File tree

1 file changed

+18
-3
lines changed

1 file changed

+18
-3
lines changed

src/cdk/testing/testbed/fake-events/element-focus.ts

+18-3
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,31 @@
99
import {dispatchFakeEvent} from './dispatch-events';
1010

1111
function triggerFocusChange(element: HTMLElement, event: 'focus' | 'blur') {
12+
const hasFocus = document.activeElement === element;
13+
14+
if ((event === 'focus' && hasFocus) || (event === 'blur' && !hasFocus)) {
15+
return;
16+
}
17+
1218
let eventFired = false;
1319
const handler = () => (eventFired = true);
1420
element.addEventListener(event, handler);
1521
element[event]();
1622
element.removeEventListener(event, handler);
23+
24+
// Some browsers won't move focus if the browser window is blurred while other will move it
25+
// asynchronously. If that is the case, we fake the event sequence as a fallback.
1726
if (!eventFired) {
18-
dispatchFakeEvent(element, event);
27+
simulateFocusSequence(element, event);
1928
}
2029
}
2130

31+
/** Simulates the full event sequence for a focus event. */
32+
function simulateFocusSequence(element: HTMLElement, event: 'focus' | 'blur') {
33+
dispatchFakeEvent(element, event);
34+
dispatchFakeEvent(element, event === 'focus' ? 'focusin' : 'focusout');
35+
}
36+
2237
/**
2338
* Patches an elements focus and blur methods to emit events consistently and predictably.
2439
* This is necessary, because some browsers can call the focus handlers asynchronously,
@@ -28,8 +43,8 @@ function triggerFocusChange(element: HTMLElement, event: 'focus' | 'blur') {
2843
// TODO: Check if this element focus patching is still needed for local testing,
2944
// where browser is not necessarily focused.
3045
export function patchElementFocus(element: HTMLElement) {
31-
element.focus = () => dispatchFakeEvent(element, 'focus');
32-
element.blur = () => dispatchFakeEvent(element, 'blur');
46+
element.focus = () => simulateFocusSequence(element, 'focus');
47+
element.blur = () => simulateFocusSequence(element, 'blur');
3348
}
3449

3550
/** @docs-private */

0 commit comments

Comments
 (0)