Testing btn click with Jasmine, getting "Cannot read properties of null (reading 'click')"

Viewed 271

I'm testing the functionality of two button clicks and whether or not a modal opens as a result.

I've done several variations of testing these clicks in Jasmine, and I'm not sure how to pinpoint the cause of this error, or how to mitigate it:

TypeError: Cannot read properties of null (reading 'click')

component.spec.ts

describe('MyComponent', () => {
  let component: MyComponent;
  let fixture: ComponentFixture<MyComponent>;

  beforeEach(() => {
    fixture = TestBed.createComponent(MyComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  fit('can promote', () => {
    // ARRANGE
    // spyOn(component, 'doPromoteMethod'); // no changes if uncommented

    const dialog = TestBed.inject(MatDialog) as jasmine.SpyObj<MatDialog>;
    const dialogRef = TestBed.inject(MatDialogRef) as jasmine.SpyObj<MatDialogRef<any>>;
    dialog.open.and.returnValue(dialogRef);
    dialogRef.afterClosed.and.returnValue(of());

    queryParams$.next({});

    // ACT
    // 1st click evt: Ellipsis menu click (opens dropdown) //
    const ellipsisBtn: HTMLButtonElement = fixture.nativeElement.parentNode.querySelector('[data-atm="actions"]');
    ellipsisBtn.click();
    fixture.detectChanges();

    // 2nd click evt: Btn click //
    const promoteBtn: HTMLButtonElement = fixture.nativeElement.parentNode.querySelector('[data-atm="promote"]');
    promoteBtn.click();
    fixture.detectChanges();

    fixture.whenStable();

    // ASSERT
    expect(dialog.open).toHaveBeenCalled;
  });

});


component.html

<ng-container matColumnDef="action">
   <th mat-header-cell *matHeaderCellDef=""></th>
     <td mat-cell *matCellDef="let promotion">
       <button mat-icon-button
           class="ellipsis-btn"
           data-atm="actions"
           [matMenuTriggerFor]="menu"
           [matMenuTriggerData]="{ 'promotion': promotion }"
           role="menubar">
           <img src="/assets/icon/ellipsis-menu.svg" />
        </button>
      </td>
</ng-container>

<mat-menu class="promotion-menu" #menu="matMenu">
  <ng-template matMenuContent let-promotion="promotion">
    <div class="promotion-menu">
      <button *ngIf="shouldAllowPromotion(promotion)" mat-menu-item data-atm="promote" (click)="doPromoteMethod(promotion)">Do promotion</button>
    </div>
  </ng-template>
</mat-menu>
1 Answers

I don't see you mocking out shouldAllowPromotion anywhere. It's likely that method is returning falsy and therefore isn't rendering the button you need.

Related