-
-
Notifications
You must be signed in to change notification settings - Fork 184
Description
I'm submitting a...
[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report
[ ] Performance issue
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request
[ ] Other... Please describe:
Current behavior
When using jest, calls to SpectatorHost.focus()
do dispatch a (fake) focus
event, but the current implementation prevents automatic blur
events from occurring, and also causes the toBeFocused()
matcher to not work. This is due to the call to patchElementFocus()
in DomSpectator.focus()
, which overwrites valid and more useful jsdom focus()
methods with versions that don't work as well.
The following test shows the issue, and a workaround:
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { createHostFactory, SpectatorHost } from '@ngneat/spectator/jest';
@Component({
selector: 'ui-test-focus',
template: `<button id="button1" (focus)="countFocus('button1')" (blur)="countBlur('button1')">Button1</button>
<button id="button2" (focus)="countFocus('button2')" (blur)="countBlur('button2')">Button2</button>`,
changeDetection: ChangeDetectionStrategy.OnPush,
host: {
'[attr.tabindex]': '0',
'(focus)': 'countFocus("ui-test-focus")',
'(blur)': 'countBlur("ui-test-focus")'
}
})
export class TestFocusComponent {
private readonly focusCounts = new Map<string, number>();
private readonly blurCounts = new Map<string, number>();
public countFocus(id: string) {
this.focusCounts.set(id, this.focusCount(id) + 1);
}
public countBlur(id: string) {
this.blurCounts.set(id, this.blurCount(id) + 1);
}
public focusCount(id: string): number {
return this.focusCounts.get(id) ?? 0;
}
public blurCount(id: string): number {
return this.blurCounts.get(id) ?? 0;
}
}
describe('Spectator focus() in jest', () => {
const createHost = createHostFactory(TestFocusComponent);
let host: SpectatorHost<TestFocusComponent>;
beforeEach(() => {
host = createHost('<ui-test-focus></ui-test-focus>');
})
it('SpectatorHost.focus() in jest does not track active element', () => {
host.focus('#button1');
// FAILS
expect(host.query('#button1')).toBeFocused();
});
it('HTMLElement.focus() in jest tracks the active element', () => {
(host.query('#button1') as HTMLElement).focus();
// passes
expect(host.query('#button1')).toBeFocused();
});
it('SpectatorHost.focus() in jest does not cause blur events', () => {
host.focus();
host.focus('#button1');
host.focus('#button2');
// FAILS: blur counts are not present
expect(host.component.focusCount('ui-test-focus')).toBe(1);
expect(host.component.blurCount('ui-test-focus')).toBe(1);
expect(host.component.focusCount('button1')).toBe(1);
expect(host.component.blurCount('button1')).toBe(1);
expect(host.component.focusCount('button2')).toBe(1);
expect(host.component.blurCount('button2')).toBe(0);
});
it('HTMLElement.focus() in jest does cause blur events', () => {
host.element.focus();
(host.query('#button1') as HTMLElement).focus();
(host.query('#button2') as HTMLElement).focus();
// passes
expect(host.component.focusCount('ui-test-focus')).toBe(1);
expect(host.component.blurCount('ui-test-focus')).toBe(1);
expect(host.component.focusCount('button1')).toBe(1);
expect(host.component.blurCount('button1')).toBe(1);
expect(host.component.focusCount('button2')).toBe(1);
expect(host.component.blurCount('button2')).toBe(0);
});
});
Expected behavior
I think the best fix would be to remove patchElementFocus()
from all platforms, but I'm not 100% sure why it's there (the comment says something about IE 11). My thinking in recommending this is that we want to test browser or platform capabilities as much as possible (eg if running karma on IE11, I would want the browser implementation to be used, b/c I'm testing browser compatibility).
Alternatively, patchElementFocus()
could be left as is for non-jest, and overridden for jest only, and only patch the focus()
and blur()
methods when they're not present.
Minimal reproduction of the problem with instructions
git clone [email protected]:johncrim/jest-spectator-bugs.git
yarn
yarn test
What is the motivation / use case for changing the behavior?
Make host.focus()
work as expected.
Environment
jest: 26.6.3
spectator: 6.1.2
$ ng version
Angular CLI: 11.0.3
Node: 15.3.0
OS: win32 x64
Angular: 11.0.3
... animations, cli, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router
Ivy Workspace:
Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1100.3
@angular-devkit/build-angular 0.1100.3
@angular-devkit/core 11.0.3
@angular-devkit/schematics 11.0.3
@schematics/angular 11.0.3
@schematics/update 0.1100.3
ng-packagr 11.0.3
rxjs 6.6.3
typescript 4.0.5
Browser:
- [ ] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX
For Tooling issues:
- Node version: XX
- Platform: Windows
Others: