trouble unit testing reactive form fields in angular
Solution 1
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();
});
});
Solution 2
expect(name.hasError('minlength', ['minlength'])).toEqual(false);
Try this it worked for me
Solution 3
I believe it's because the validation key you're looking for is "minlength" non-camelCase, note the lower-case "l". I have personally run into this oddly named error property.
Gene Higgins
Updated on October 20, 2020Comments
-
Gene Higgins over 3 years
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 aname
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. Thename.errors
array in the test does not contain any reference to required at all,name.errors['minLength']
returnsundefined
. 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" }); });