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

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>


Solution 1:[1]

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.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1