How do I check if my element has been focused in a unit test in angular 4?
Asked Answered
W

3

17

I have following function to unit test. I have taken element which is text box with view child in component and in testing I need to test whether my text box got focused or not after setTimeout() was called.

 @ViewChild('searchInput') searchInput: ElementRef;
function A(show) {
        const self = this;
        if (show) {
            this.xyz= true;
            setTimeout(function () {
                self.searchInput.nativeElement.focus();
            }, 0);
        } else {
            self.xyz= false;
            self.abc = '';
        }
    }

Here is my test case that I am trying:

it('textbox get focus toggleSearch', async(() => {
        let el: DebugElement;

        component.toggleSearch(true);
        el = fixture.debugElement.query(By.css('#search-input-theme'));
        let native: HTMLElement = el.nativeElement;
        spyOn(native,'focus');
        fixture.whenStable().then(() => {
            expect(native.focus).toHaveBeenCalled();
        });
    }));
Weighin answered 22/6, 2017 at 9:53 Comment(0)
G
15

maybe something like this:

const input = de.query(By.css("your_field_selector")).nativeElement;
const focusElement = de.query(By.css(":focus")).nativeElement;
expect(focusElement).toBe(input);

Luis

Glycerite answered 11/7, 2017 at 10:57 Comment(0)
C
8

Luis Abreu's answer worked for me as not only I wanted to spy that the focus method was called but that the focus was set on the right element on the view. Here's an example:

describe('Email input focus', () => {
  beforeEach(() => {
    spyOn(comp.emailField.nativeElement, 'focus');
    comp.ngAfterViewInit();
  });

  it('Should call the focus event', () => {
    expect(comp.emailField.nativeElement.focus).toHaveBeenCalled();
  });

  it('Should be focused on the view', () => {
    fixture.detectChanges();
    const emailInput = de.query(By.css('#email')).nativeElement;
    const focusedElement = de.query(By.css(':focus')).nativeElement;
    expect(focusedElement).toBe(emailInput);
  });
});
Carabin answered 10/10, 2017 at 16:42 Comment(0)
R
3

You can query directly on native element and use a unique selector

const input = fixture.nativeElement.querySelector('#your-input-id:focus');
expect(input).toBeTruthy();
Rapport answered 18/5, 2019 at 10:10 Comment(2)
This only seems to work if the browser window has focus also, so it ends up a bit flakey.Dizen
workaround to ignore focus issues in jasmine: const focused = () => fixture.nativeElement.querySelector(':focus'); button.nativeElement.focus(); if (focused() !== button.nativeElement) { pending('Requires browser focus'); return; }Dizen

© 2022 - 2024 — McMap. All rights reserved.