B. Thiele
B. Thiele

Reputation: 46

How to run a Karma jasmine test that runs the focus() - method of an HTMLElement in the background?

The Goal

I want to test a component that handles an editor and its input. This component has a FormControl and a FocusMonitor. Specific values should only be updated if the component private focused field is set to true. The FocusMonitor updates the private focused field of the component.

I run the test with Karma Jasmine 4.0.1.

The Problem:

When i select (focus) the ChromeBrowser running the test, the test succeeds. If i just start the test via a terminal input and let it run in the background -while working on something else - the test failes.

The failure happens because the FocusMonitor Observable does not emit an event when i dont actively select the window with the running test-browser.

The Code

Inside the component

focusMonitor.monitor(elementRef.nativeElement, true).subscribe(origin => {
            this.focused = !!origin;
            this.someUpdateAlgorithm();
        });


//somewhere inside the component. This ward keeps off unwanted changes via the model.

if (!this.focused) {
    return;
}



Inside the component.spec

fit('should change value of input control', () => {
            fixture.debugElement.query(By.css('input')).nativeElement.focus();
            model.setValue(3);
            const inputText = getCurrentDisplayValue();
            expect(inputText).toBe('3');
        });

Results

Expected results:

Case: actively selecting the window running the test-browser (Chrome)

expect(inputText).toBe('3'); //successfull inputText === '3'

Case: running the test-browser (Chrome) minimized (in the background)

expect(inputText).toBe('3'); //successfull inputText === '3'

Actual results:

Case: actively selecting the window running the test-browser (Chrome)

expect(inputText).toBe('3'); //successfull inputText === '3'

Case: running the test-browser (Chrome) minimized (in the background)

expect(inputText).toBe('3'); //failed inputText === ''

Upvotes: 1

Views: 1744

Answers (1)

Desty
Desty

Reputation: 2775

To make your test independent from the environment you can mock the FocusMonitor:

describe('YourComponent', () => {
  let focusMonitorObservable: Subject<string>;

  beforeEach(async(() => {
    const fmSpy = jasmine.createSpyObj('FocusMonitor', ['monitor']);
    TestBed.configureTestingModule({
      // ...
      providers: [
        { provide: FocusMonitor, useValue: fmSpy },
      ]
    })
    .compileComponents();
    focusMonitorSpy = TestBed.get(FocusMonitor);
    focusMonitorObservable = new Subject<string>();
    focusMonitorSpy.monitor.and.returnValue(focusMonitorObservable);
  }));

  it('should change value of input control', () => {
    focusMonitorObservable.next('mouse'); // emulating the focus change
    model.setValue(3);
    const inputText = getCurrentDisplayValue();
    expect(inputText).toBe('3');
  });
});

Upvotes: 1

Related Questions