Angular test – enable button when form becomes valid

I have such a form in my App, with a required field, and a button that becomes enabled once the field is not empty.

upload.component.html

<form [formGroup]="uploadForm" (ngSubmit)="Submit()">
                    <mat-form-field class="full-width" appearance="outline">
                      <mat-label translate>enter-name</mat-label>
                      <input matInput formControlName="name">
                    </mat-form-field>
<button mat-raised-button  [disabled]="!uploadForm.valid">Send</button>
</form>

And upload.component.ts:

  ngOnInit() {
    this.uploadForm = new FormGroup({
       'name': new FormControl('', Validators.required),
      );
   }

I want to test this case.

Trying this, upload.component.spec.ts:

   it('should be ok', waitForAsync(() => {
                let fixture = TestBed.createComponent(DashboardComponent);
                fixture.detectChanges();
                fixture.whenStable().then(() => {
                  let input = fixture.debugElement.nativeElement.querySelector('[matInput]');
                  input.value = 'someValue';
                  input.dispatchEvent(new Event('input'));
     expect(fixture.debugElement.nativeElement.querySelector('button').disabled).toBeFalsy();
                    });
        }));

Doesn’t work.

Can anyone please help me with the syntax?

Thanks!

>Solution :

I think you’re missing a fixture.detectChanges() since the model changed. Try this:

it('should be ok', waitForAsync(() => {
                let fixture = TestBed.createComponent(DashboardComponent);
                fixture.detectChanges();
                fixture.whenStable().then(() => {
                  let input = fixture.debugElement.nativeElement.querySelector('[matInput]');
                  input.value = 'someValue';
                  input.dispatchEvent(new Event('input'));
                  // !! need another fixture.whenStable since some aspects of a form are asynchronous
                   fixture.whenStable().then(() => {
                    // !! add a fixture.detectChanges() since the model changed
                   fixture.detectChanges();
                   
expect(fixture.debugElement.nativeElement.querySelector('button').disabled).toBeFalsy();
                });
                  
             });
        }));

That being said, the good thing about ReactiveForms is that you don’t need to mess around with the view. You can just play with the form and get what you want.

Something like this:

it('should be ok', () => {
   // !! first fixture.detectChanges() calls ngOnInit
   fixture.detectChanges();
   // !! change the model directly
   component.uploadForm.get('name').setValue('someValue');
   // !! update the view with fixture.detectChanges()
   fixture.detectChanges();
   expect(fixture.debugElement.nativeElement.querySelector('button').disabled).toBeFalsy();
  
});

I think a test like that ^ is much easier to write.

Leave a Reply