title: Angular Form is not valid even after all form fields are valid
body: <p>I m trying to solve one <strong>Angular form validation</strong> <em>Hands on</em>, for that i made the below form, this form is passing all the test cases except one, looks like the problem is with testing file(app.component.spec.ts) that is <strong>readable only</strong> <a href="https://stackblitz.com/edit/angular-f1be3c?file=src%2Fapp%2Fapp.component.ts" rel="nofollow noreferrer">working Demo</a> of the handson shows form status as <strong>VALID.</strong> but it fails testing</p>
  
  <p><em>I am stuck with this handson form last two days.<strong>Your help is cordially appreciated</strong>.</em></p>
  
  <p>-------------------[read only]app.component.spec.ts----------</p>
  
  <pre><code>import { AppComponent } from './app.component';
  import { ReactiveFormsModule, FormControl, AbstractControl, FormGroup } from '@angular/forms';
  import { By } from '@angular/platform-browser';
  import { asNativeElements, DebugElement } from '@angular/core';
  
  describe('AppComponent', () =&gt; {
    let component: AppComponent;
    let fixture: ComponentFixture&lt;AppComponent&gt;;
  
    beforeEach(async(() =&gt; {
      TestBed.configureTestingModule({
        imports: [ReactiveFormsModule],
        declarations: [AppComponent]
      })
      .compileComponents();
  
      fixture = TestBed.createComponent(AppComponent);
      component = fixture.componentInstance;
    }));
  
    // it('should create the component', () =&gt; {
    //   expect(component).toBeTruthy();
    // });
  
    it('form should be invalid when empty', () =&gt; {
      expect(component.contactForm.invalid).toBeTruthy();
    });
  
    it('form should be valid on entering required fields', () =&gt; {
      fixture.detectChanges(); // ngOninit()
      component.name.setValue('david');
      component.phone.setValue('9999999999');
  
      expect(component.contactForm.valid).toBeTruthy();
    });
  
    describe('#name', () =&gt; {
      let name: AbstractControl;
  
      beforeEach(() =&gt; {
        name = component.contactForm.controls['name'];
      });
  
      it('should be invalid if empty', () =&gt; {
        expect(name.invalid).toBeTruthy();
      });
  
      it('should be a "required" field', () =&gt; {
        expect(name.errors['required']).toBeTruthy();
      });
  
      it('should be valid if some value is present', fakeAsync(() =&gt; {
        name.setValue('david');
        expect(name.valid).toBeTruthy();
      }));
    });
  
    describe('#phone', () =&gt; {
      let phone: AbstractControl;
      beforeEach(() =&gt; {
        phone = component.contactForm.controls['phone'];
      });
  
      it('should be invalid if empty', () =&gt; {
        expect(phone.invalid).toBeTruthy();
      });
  
      it('should have "required" validation', () =&gt; {
        expect(phone.errors['required']).toBeTruthy();
      });
  
      it('should accept only numbers(pattern validation)', () =&gt; {
        phone.setValue('abc');
        expect(phone.errors['pattern']).toBeTruthy();
      });
  
      it('should have 10 digits(minlength &amp; maxlength validation)', () =&gt; {
        phone.setValue('123');
        expect(phone.errors['minlength']).toBeTruthy();
        phone.setValue('12333333333');
        expect(phone.errors['maxlength']).toBeTruthy();
      });
    });
  
    describe('#address - zip', () =&gt; {
      let address;
      let zip;
      beforeEach(() =&gt; {
        address = component.contactForm.controls['address'] as FormGroup ;
        zip = address.controls['zip'] ;
        fixture.detectChanges(); // ngOnInit()
      });
      it('should be a number', fakeAsync(() =&gt; {
        zip.setValue('abc');
        expect(zip.errors['pattern']).toBeTruthy();
        zip.setValue('123456');
        fixture.detectChanges();
        expect(zip.valid).toBeTruthy();
      }));
      it('should have 6 digits exactly', () =&gt; {
        // enter 3 digits and check for minlength validation
        zip.setValue('123');
        expect(zip.errors['minlength']).toBeTruthy();
  
        // enter 7 digits and check for maxlength validation
        zip.setValue('1234567');
        fixture.detectChanges(); // update changes, angular will not do for you automatically
        expect(zip.errors['maxlength']).toBeTruthy();
      });
    });
  });
  </code></pre>
  
  <p>Here is the test error</p>
  
  <pre><code>AppComponent
   ✖ form should be valid on entering required fields
     HeadlessChrome 75.0.3770 (Linux 0.0.0)
    Expected false to be truthy.
      at UserContext. (src/app/app.component.spec.ts:35:41)
      at ZoneDelegate.invoke (node_modules/zone.js/dist/zone-evergreen.js:359:1)
      at ProxyZoneSpec.push../node_modules/zone.js/dist/zone-testing.js.ProxyZoneSpec.onInvoke 
   (node_modules/zone.js/dist/zone-testing.js:308:1)
         at ZoneDelegate.invoke (node_modules/zone.js/dist/zone-evergreen.js:358:1)
  </code></pre>