1

セレクタでコントロールからカスタムを取得しましたapp-date-picker。それはControlValueAccessorを実装します。私はバインディングの両方の方向をテストしMyPageためのユニットテストを書くことをしようとしている角2 - ネストされたカスタムフォームコントロールへのユニットテストのバインド

<app-date-picker class="address__from-date" [(ngModel)]="fromDate"></app-date-picker> 

:私は介して、このカスタムフォームコントロールを含むMyPageと呼ばれるコンポーネントを持っています。私は、例えば、うまく他のフォームフィールドのためにこれを行っている:私は私のカスタムフォームのコントロールのためにこれを行うにしようとすると

it('should bind zip code', fakeAsync(() => { 
    const formControl = element.query(By.css('.address__zip-code input')).nativeElement; 

    // model -> view 
    component.zipCode = 76777; 
    fixture.detectChanges(); 
    tick(); 

    expect(formControl.value).toEqual('76777'); 

    // view -> model 
    formControl.value = '89556'; 
    formControl.dispatchEvent(new Event('input')); 

    expect(component.zipCode).toEqual(89556); 
})); 

私の問題が発生します。これまでのところ、私は唯一の結合の一つの方向をテストすることができ、そして、それはちょうどひどいですng-reflect-modelの使用、必要とされていてもよう:

it('should bind from-date', fakeAsync(() => { 
    const formControl = element.query(By.css('.address__from-date app-date-picker')).nativeElement; 

    // model -> view 
    component.fromDate = '01/2017'; 
    fixture.detectChanges(); 
    tick(); 

    expect(formControl.attributes['ng-reflect-model'].value).toEqual('01/2017'); 

    // view -> model 
    // Not sure what to do here either 
})); 

これを行うことについて移動する良い方法はありますか?私がしたい:私はフォームコントロールにそれを有線知っているように、

  1. ng-reflect-*
を使用する必要はありませ
  • 正しく、MyPage単体テストから結合の両方の方向をテストすることができ

    その他の注意事項:

    MyPage成分はfromDate(およびzipCode)フィールドと、標準的な構成要素です。

    カスタムフォームフィールドが正しくControlValueAccessorを実装し、ngModelを介して結合され、それ自体、dateフィールドを持っており、内部<input>を使用しています:

    <input [(ngModel)]="date" type="date"> 
    

    DatePickerComponent

    @Component({ 
        selector: 'app-date-picker', 
        templateUrl: './date-picker.component.html', 
        styleUrls: ['./date-picker.component.scss'], 
        providers: [{ 
        provide: NG_VALUE_ACCESSOR, 
        useExisting: forwardRef(() => DatePickerComponent), 
        multi: true 
        }] 
    }) 
    export class DatePickerComponent implements ControlValueAccessor { 
    
        private propagateChange = (_: any) => {}; 
    
        private _date: string; 
        get date(): string { 
        return this._date; 
        } 
    
        @Input() 
        set date(value: string) { 
        this._date = value; 
        this.propagateChange(value); 
        } 
    
        writeValue(newValue: any) { 
        if (newValue !== undefined) { 
         this.date = newValue; 
        } 
        } 
    
        registerOnChange(fn: any) { 
        this.propagateChange = fn; 
        } 
    
        registerOnTouched(fn: any) { 
        // Not used 
        } 
    } 
    

    UPDATE 8/10/2017

    これまでのところ、私は@ViewChildで欲しいものに近い得ている:

    @Component(...) 
    MyPageComponent { 
    @ViewChild('fromDate') fromDatePicker: DatePickerComponent; 
    ... 
    } 
    

    MyPageテンプレートになる(テンプレート参照変数#fromDateに注意してください):

    <app-date-picker #fromDate class="address__from-date" [(ngModel)]="fromDate"> 
    </app-date-picker> 
    

    その後、テストは次のようになります。

    it('should bind from-date', fakeAsync(() => { 
        // model -> view 
        component.info.fromDate = '01/2017'; 
        fixture.detectChanges(); 
        tick(); 
    
        expect(component.fromDatePicker.date).toEqual('01/2017'); 
    
        // view -> model 
        component.fromDatePicker.date = '02/2017'; 
    
        expect(component.info.fromDate).toEqual('02/2017'); 
    })); 
    

    誰かがもっと良い方法を知っていますか?これは最適ではないが、これは今のところ私を得る。

  • 答えて

    1

    最後に、ng-reflect-*@ViewChildの両方を避けるため、私は満足しています。 .nativeElementに電話する代わりに.componentInstanceに電話することができます。その後、テストは単純に次のようになります。

    it('should bind from-date', fakeAsync(() => { 
        const formControl = element.query(By.css('.address__from-date app-date-picker')).componentInstance; 
    
        // model -> view 
        component.fromDate = '01/2017'; 
        fixture.detectChanges(); 
        tick(); 
    
        expect(formControl.date).toEqual('01/2017'); 
    
        // view -> model 
        formControl.date = '02/2017'; 
    
        expect(component.fromDate).toEqual('02/2017'); 
    })); 
    

    誰もがよりよい解決策を持っている場合、私はまだオープンだが、私は今の答えとしてこれをマークします。誰もがこれに就くのを助けることを願っています!

    関連する問題