web-dev-qa-db-ja.com

Angular 2カスタム検証ユニットテスト

このガイドに従って、カスタムの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にアクセスする方法、または有効/無効(カスタム検証)入力フィールドを確認する方法を誰かが知っていますか?.

5

あなたがする必要があるのは、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 !== '[email protected]') {
      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 = '[email protected]';
      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 = '[email protected]';
      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ソースコードテストで見つかりました

11
Paul Samsotha

上記のベストアンサーは私にはうまくいきませんでしたが、次の方法でカスタムバリデーターをテストすることができました:

const associateRateControl = component.distributionSettingsForm.controls['associateRate'];
associateRateControl.setValue('plus ultra');
fixture.detectChanges();
expect(component.distributionSettingsForm.hasError('noCatalog')).toEqual(true);
2
Cameron Vogler