Angular jasmine test not able to trigger Observable created with fromEvent rxjs operator
Asked Answered
E

1

9

I have a simple case. The standard AppComponent of an Angular app contains a ChildComponent which is defined in its own module ChildModule.

The template of ChildComponent is very simple

<div class="child" (click)="testClick($event)"></div>

ChildComponent has an even simpler testClick(event) method that just logs a message on the console.

testClick(event) {
    console.log(event);
}

Now I want to build a test on AppComponent simulating a click on ChildComponent.

This is the code of the test

describe('AppComponent', () => {
  let fixture: ComponentFixture<AppComponent>;
  let app: AppComponent;
  let child: DebugElement;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [ ChildModule ],
      declarations: [
        AppComponent
      ],
    }).compileComponents();
  }));
  beforeEach(() => {
    fixture = TestBed.createComponent(AppComponent);
    app = fixture.debugElement.componentInstance;
    child = fixture.debugElement.query(By.css('.child'));
    fixture.detectChanges();
  });

  it(`should create the child'`, async(() => {
    expect(child).toBeTruthy();
  }));

  it(`clicks on the child and the relative Observable emits`, async(() => {
    setTimeout(() => {
      child.triggerEventHandler('click', 'clicked');
    }, 100);

  }));

});

The tests work and in particular the second test prints the clicked message on the console, as expected.

Now I complicate a bit ChildComponent. I want to create an Observable on the click event using the fromEvent operator and ViewChild.

So the code becomes

export class ChildComponent implements AfterViewInit {
  @ViewChild('child') private childElement: ElementRef;

  ngAfterViewInit() {
    const testClick$ = fromEvent(this.childElement.nativeElement, 'click');
    testClick$.subscribe(d => console.log('test click in child', d));
  }
}

I launch the development server with ng serve and I see 2 messages printed on the console, one by the testClick method and one by the subscription of the testClick$ Observable.

If I run now the same tests as before, I expect to see also the same two messages printed on the console. On the contrary I see only the message printed by the testClick method. The message of the subscription, i.e. 'test click in child', does not appear, which means that the Observable testClick$ does not emit when child.triggerEventHandler('click', 'clicked'); is executed.

How can I make Observables created with fromEvent work in jasmine tests? What am I doing wrong?

Erastianism answered 22/7, 2018 at 8:43 Comment(1)
Shouldn't you mock the fromEvent method ? cuz testing whether fromEvent works or not should not be your unit test's responsibility. You should assume fromEvent will always work cuz it is coming from an external library.Anion
E
7

Eventually I found a way to fire events that can be used within the fromEvent function of RxJs.

The solution has been inspired by this post.

The idea is that in order to be able to create an event stream from a DOM event you have to use the method dispatchEvent on the native element wrapped by the DebugElement.

So, rather than doing

child.triggerEventHandler('click', 'clicked');

you have to use something like

child.nativeElement.dispatchEvent(new MouseEvent('click', {...});
Erastianism answered 4/8, 2018 at 6:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.