Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

trouble unit testing reactive form fields in angular

I'm learning Angular 2 and unit testing using @angular/cli 1.0.0-beta.30 and had a bit of success testing one aspect of a form field's validity, but not all. I'm using an inline template in my component for the time being to remove a layer of complexity for now (a form template in a separate file introduces asynchronicity, correct?).

The ngOnInit() defines a name property that includes the validators for "required" and "minLength". Currently an empty form field will correctly trigger the "required" validator but not the "minLength" validator. The name.errors array in the test does not contain any reference to required at all, name.errors['minLength'] returns undefined. Does minLength need to be handled asynchronously? I'm having trouble finding docs or examples that fit my problem.

// signup-form.component.ts
...
export class SignupFormComponent implements OnInit {

    user: FormGroup;

    constructor(private fb: FormBuilder) {
    }

    ngOnInit() {
        this.user = this.fb.group({
            name: ['', [Validators.required, Validators.minLength(2)]],
            account: this.fb.group({
                email: ['', Validators.required, Validators.pattern("[^ @]*@[^ @]*")],
                confirm: ['', Validators.required]
            })
        })
    }

    onSubmit({ value, valid }: { value: User, valid: boolean }) {
        console.log(value, valid);
    }

}

My test

// signup-form.component.spec.ts
import { SignupFormComponent } from './signup-form.component';

describe('SignupFormComponent', () => {
    let component: SignupFormComponent;
    let fixture: ComponentFixture<SignupFormComponent>;

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            declarations: [SignupFormComponent],
            imports: [
                ReactiveFormsModule,
                FormsModule
            ]
        })
            .compileComponents();
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(SignupFormComponent);
        component = fixture.componentInstance;
        component.ngOnInit();
        fixture.detectChanges();
    });

    it('should create', () => {
        expect(component).toBeTruthy();
    });

    it('form invalid when empty', () => {
        expect(component.user.valid).toBeFalsy();
    });

    it('name field validity', () => {
        let name = component.user.controls['name'];
        expect(name.valid).toBeFalsy();

        let errors = {};
        name.setValue("");
        errors = name.errors || {};
        expect(errors['required']).toBeTruthy(); // this works
        expect(errors['minLength']).toBeTruthy(); // this fails, "undefined"
    });

});
like image 778
Gene Higgins Avatar asked Feb 09 '17 18:02

Gene Higgins


People also ask

What will happen if we're configure TestBed after calling createComponent?

Do not re-configure TestBed after calling createComponent . The createComponent method freezes the current TestBed definition, closing it to further configuration.

What is Reactiveformsmodule in Angular?

A directive which installs the MinValidator for any formControlName , formControl , or control with ngModel that also has a min attribute. NgControlStatus. Directive automatically applied to Angular form controls that sets CSS classes based on control status. NgControlStatusGroup.


2 Answers

Answering your question

The name.errors['minLength'] returns undefined, Does minLength need to be handled asynchronously?

You can just check the form for a specific error

expect(form.control.hasError('emailInvalid', ['email'])).toBe(true);

Below is a complete test

// signup-form.component.spec.ts
import { SignupFormComponent } from './signup-form.component';

describe('SignupFormComponent', () => {
    let component: SignupFormComponent;
    let fixture: ComponentFixture<SignupFormComponent>;

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            declarations: [SignupFormComponent],
            imports: [
                ReactiveFormsModule,
                FormsModule
            ]
        })
            .compileComponents();
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(SignupFormComponent);
        component = fixture.componentInstance;
        component.ngOnInit();
        fixture.detectChanges();
    });

    it('should create', () => {
        expect(component).toBeTruthy();
    });

    it('form invalid when empty', () => {
        expect(component.user.valid).toBeFalsy();
    });

    it('name field validity', () => {
        let name = component.user.controls['name'];
        expect(name.valid).toBeFalsy();

        name.setValue("");
        expect(name.hasError('required')).toBeTruthy();

        name.setValue("A");
        expect(name.hasError('minLength')).toBeTruthy();
    });

});
like image 182
Vishal Hasnani Avatar answered Nov 10 '22 06:11

Vishal Hasnani


expect(name.hasError('minlength', ['minlength'])).toEqual(false);

Try this it worked for me

like image 39
anirudh talluri Avatar answered Nov 10 '22 06:11

anirudh talluri