Angular 2 自定义验证单元测试

标签 angular typescript angular2-directives angular2-forms angular2-testing

我正在按照本指南编写自定义 Angular (Angular 2.0.0)验证 https://angular.io/docs/ts/latest/cookbook/form-validation.html#!#custom-validation .

@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,或者我如何检查有效/无效(自定义验证)输入字段。

最佳答案

您需要做的是获取具有 NgForm 的注入(inject)器。我花了一段时间才弄明白。我以为您可以直接从 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 - Found it in the source code tests

关于Angular 2 自定义验证单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39910017/

相关文章:

angular - 扩展基类与在 Typescript 中注入(inject)它

javascript - 在分配之前使用变量 'value'

angular - 尝试使用嵌套组件时 promise 未捕获的异常

用于将数字格式化并打印为正数的 Angular HTML 代码(不带减号)

html - Angular 2 Azure 媒体服务视频播放

angular - 如何在 ngStyle 中使用 Use Mixin $Variable?

html - 以 Angular 6动态添加div容器

javascript - Nodemon -w 保持启动,但不运行服务器

css - Angular 2 : Detect changes in browser width and update model

javascript - 如何在 ng-2 Material <md-input> 字段中 trim 输入开头的空格