按照本指南https://angular.io/docs/ts/latest/cookbook/form-validation.html#!#custom-validation编写自定义角度(Angular 2.0.0)验证。
@Directive({
selector: '[ngModel][emailValidator]',
providers: [{provide: NG_VALIDATORS, useExisting: EmailValidatorDirective, multi: true}]
})
export class EmailValidatorDirective implements Validator
现在我正在尝试将单元测试添加到我的自定义验证指令中。
beforeEach(() => {
fixture = TestBed.createComponent(EmailComponent);
component = fixture.componentInstance;
de = fixture.debugElement;
el = de.nativeElement;
component = de.componentInstance;
emailField = de.query(By.css('input')).nativeElement;
});
我正在访问所有这些对象,但没有人知道我输入的有效性。有没有人知道如何在单元测试中访问输入的NgControl,或者我如何检查有效/无效(自定义验证)输入字段。
答案 0 :(得分:9)
您需要做的是获取具有NgForm
的注射器。我花了一段时间才搞清楚。我认为你可以从debugElement
得到它,但看起来你需要从它的孩子 1 获得它。
let form: NgForm = fixture.debugElement.children[0].injector.get(NgForm);
您可以使用
从表单组中获取单个控件let emailControl = form.control.get('email');
expect(emailControl.valid).toBe(true);
或者您只需检查表单中的特定错误
即可expect(form.control.hasError('emailInvalid', ['email'])).toBe(true);
以下是完整的测试
import { Component, forwardRef, Directive } from '@angular/core';
import { TestBed, getTestBed, async } from '@angular/core/testing';
import { FormsModule, NG_VALIDATORS, Validator, AbstractControl, NgForm } from '@angular/forms';
import { dispatchEvent } from '@angular/platform-browser/testing/browser_util';
import { By } from '@angular/platform-browser';
@Directive({
selector: '[ngModel][validEmail]',
providers: [
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => EmailValidatorDirective),
multi: true
}
]
})
class EmailValidatorDirective implements Validator {
validate(c: AbstractControl): { [key: string]: any } {
if (c.value !== 'peeskillet@stackoverflow.com') {
return { notPeeskillet: true };
}
return null;
}
}
@Component({
template: `
<form>
<input name="email" [ngModel]="email" validEmail />
</form>
`
})
class TestComponent {
email;
}
describe('component: TestComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [FormsModule],
declarations: [TestComponent, EmailValidatorDirective]
});
});
it('should validate', async(() => {
let fixture = TestBed.createComponent(TestComponent);
let comp = fixture.componentInstance;
let debug = fixture.debugElement;
let input = debug.query(By.css('[name=email]'));
fixture.detectChanges();
fixture.whenStable().then(() => {
input.nativeElement.value = 'bad@email.com';
dispatchEvent(input.nativeElement, 'input');
fixture.detectChanges();
let form: NgForm = debug.children[0].injector.get(NgForm);
let control = form.control.get('email');
expect(control.hasError('notPeeskillet')).toBe(true);
expect(form.control.valid).toEqual(false);
expect(form.control.hasError('notPeeskillet', ['email'])).toEqual(true);
input.nativeElement.value = 'peeskillet@stackoverflow.com';
dispatchEvent(input.nativeElement, 'input');
fixture.detectChanges();
expect(control.hasError('notPeeskillet')).toBe(false);
expect(form.control.valid).toEqual(true);
expect(form.control.hasError('notPeeskillet', ['email'])).toEqual(false);
});
}));
});
答案 1 :(得分:0)
以上最佳答案对我不起作用,但我能够通过以下方式测试我的自定义验证器:
const associateRateControl = component.distributionSettingsForm.controls['associateRate'];
associateRateControl.setValue('plus ultra');
fixture.detectChanges();
expect(component.distributionSettingsForm.hasError('noCatalog')).toEqual(true);
答案 2 :(得分:0)
有关该主题的另一个提示。
Paul Samsotha answer我认为这是正确的并且非常有帮助,但是TBH不需要导入任何库。我们可以使用nativeElement
dispatchEvent
,使我们的生活更加轻松。
beforeEach(() => {
const input = fixture.debugElement.query(By.css("input")).nativeElement;
fixture.detectChanges();
input.value = "test";
input.dispatchEvent(new Event("input"));
fixture.detectChanges();
});
it("should display the password strength indicator", () => {
const form = fixture.componentInstance.myMarvelousForm;
expect(form.dirty).toBeTruthy();
});