How to test event emitted from Child to Parent which are in declarations[] in Jasmine, Angular

102 Views Asked by At

I have a large .spec file that is used as an integration test of the (let's call it) MainComponent. The declarations contain multiple child components and their child components. I am concerned with 2 components that communicate using EventEmitter. When user clicks a button in ChildComponent the event gets emitted and triggers a function inside ParentComponent.

I'm trying to mock the ParentComponent but when the test executes, it goes down the default path of ParentComponent.

I can't show the whole file but this is what the spec does:

describe('main component Spec', () => {
    let fixture: ComponentFixture<MainComponent>;

    let mainComponent: MainComponent;

    const parentComponentSpyObj = jasmine.createSpyObj('ParentComponent', ['onEventReceived']);

    beforeEach(waitForAsync(() => {
        TestBed.configureTestingModule({
            declarations: [
                ParentComponent,
                ChildComponent
            ],
            schemas: [CUSTOM_ELEMENTS_SCHEMA],
            imports: [FlexLayoutModule],
            providers: [
                { provide: ParentComponent, useValue: parentComponentSpyObj },
            ]
        }).compileComponents();
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(MainComponent);
        mainComponent = fixture.componentInstance;
        fixture.detectChanges();
    });

    it(`Should call onEventReceived of ParentComponent when child button is pressed`, () => {
        // Given
        const childComponentButton = fixture.debugElement.nativeElement.querySelector('#button');

        // When
        childComponentButton.click();
        fixture.detectChanges();

        // Then
        expect(parentComponentSpyObj.onEventReceived).toHaveBeenCalledTimes(1);
    });

});

The test fails with message - Expected parentComponentSpyObj.onEventReceived to have been called once. It was called 0 times.

1

There are 1 best solutions below

0
MikeTab On

Could you pass an example of your parentComponentSpyObj? Inside of it, there should reside all funcion and variable mocks (with empty returns or empty observables). It looks like the event emitter mock is not created properly, so the test is not able to read the call. Maybe thats the reason.

It could be something like this:

import { Component } from '@angular/core';

@Component({
  selector: 'app-parent',
  template: `
    <h2>Parent Component</h2>
    <app-mock-child (eventEmitter)="handleEvent($event)"></app-mock-child>
  `,
})
export class ParentComponent {
  // Function to be called when the event is emitted
  handleEvent(data: string): void {
    return; // or return an observable: return of({ }):
  }
}

Hope it helps