So it seems that there are some asynchronous tasks that need to complete (we await fixture.whenStable and then we need to call fixture.detectChanges(). This is one of the reasons why I use reactive forms almost always because it is much easier to test. You can test them just by the TypeScript code alone and you don’t have to look at the HTML at all.

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AppComponent } from './app.component';
import { DebugElement } from '@angular/core';
import { By } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';

describe('AppComponent', () => {
  let component: AppComponent;
  let fixture: ComponentFixture<AppComponent>;
  let el: DebugElement;
  let button: HTMLButtonElement;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [AppComponent],
      imports: [FormsModule]
    }).compileComponents();
  }));
  beforeEach(async () => {
    fixture = TestBed.createComponent(AppComponent);
    component = fixture.componentInstance;
    el = fixture.debugElement;
    fixture.detectChanges();
  });

  describe('submit button', () => {
    it('should be disabled by default', async () => {
      await fixture.whenStable(); // wait for all asynchronous tasks to complete
      fixture.detectChanges(); // call detectChanges again
      button = fixture.debugElement.query(By.css('button')).nativeElement;
      expect(button.disabled).toBe(true);
    });
  });
});

Things to note:

1.) Every time you call fixture.detectChanges, you need a new reference to fixture.debugElement.query... because the view changes every time you call fixture.detectChanges. If we were to keep using el like you have in the beforeEach, you would have an old reference to how the HTML looked like.

2.) You don’t need to import CommonModule in Angular unit tests.

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top