Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 474
Picci Avatar asked Jul 22 '18 08:07

Picci


1 Answers

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', {...});
like image 177
Picci Avatar answered Nov 20 '22 15:11

Picci