rmcsharry
rmcsharry

Reputation: 5562

Angular 9 testing with Jest - why does this mat-checkbox test fail?

I have a reset function in my component that resets all child checkboxes:

  @ViewChildren('checkBoxes') checkBoxes: QueryList<MatCheckbox>;

  /**
   * Mark all checkboxes as unchecked
   */
  reset() {
    this.checkBoxes.forEach((checkbox: MatCheckbox) => {
      console.log('i am being called' + checkbox.checked);
      checkbox.checked = false;
    });
  }

This is the test:

  it('should uncheck all checkboxes when reset is called', fakeAsync(() => {
    const checkboxInput = fixture.debugElement.query(
      By.css('.mat-checkbox-input')
    );
    const el = checkboxInput.nativeElement;
    el.click();
    component.reset();
    fixture.detectChanges();
    expect(el.checked).toBe(false);
  }));

I can see from the console.log that the reset function is called and the checkbox is true. But at the point the expect runs, it is still true when it should be false.

I tried adding a tick() after the reset() call, but it made no difference.

UPDATE

I found this question, which is almost identical except they are changing the checkbox binding property on the component inside the test directly. But anyway I tried this:

  it('should uncheck all checkboxes when reset is called', async(() => {
    const checkboxInput = fixture.debugElement.query(
      By.css('.mat-checkbox-input')
    );
    const el = checkboxInput.nativeElement;
    el.click();
    component.reset();
    fixture.detectChanges();
    fixture.whenStable().then(() => {
      expect(el.checked).toBe(false);
    });
  }));

but that also fails.

Upvotes: 0

Views: 801

Answers (1)

rmcsharry
rmcsharry

Reputation: 5562

The issue is one of timing, so the test needs to detectChanges twice.

So this works:

  it('should uncheck all checkboxes when reset is called', () => {
    const checkboxInput = fixture.debugElement.query(
      By.css('.mat-checkbox-input')
    );
    const el = checkboxInput.nativeElement;
    el.click();
    fixture.detectChanges();
    component.reset();
    fixture.detectChanges();
    expect(el.checked).toBe(false);
  });

As does this:

  it('should uncheck all checkboxes when reset is called', async(() => {
    const checkboxInput = fixture.debugElement.query(
      By.css('.mat-checkbox-input')
    );
    const el = checkboxInput.nativeElement;
    el.click();
    fixture.detectChanges();
    component.reset();
    fixture.detectChanges();
    fixture.whenStable().then(() => {
      expect(el.checked).toBe(false);
    });
  }));

Upvotes: 1

Related Questions