Home > other >  Angular test - enable button when form becomes valid
Angular test - enable button when form becomes valid

Time:06-16

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  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!

CodePudding user response:

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.

CodePudding user response:

You need to add ReactiveFormsModule in app.module like

import { FormsModule, ReactiveFormsModule } from '@angular/forms';

and add in import

FormsModule, ReactiveFormsModule

I just tried on stackblitz, and it works.

  • Related