2017-10-06 121 views
2

這是我的問題:Angular 2測試ngModel工作流程

我有一個自定義組件,其中有一個ngModel內的模板。

import { Component, Input, forwardRef } from '@angular/core'; 
 
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; 
 

 
const listaMesi = [ 
 
    { 
 
    value: '01', 
 
    text: 'Gennaio' 
 
    }, { 
 
    value: '02', 
 
    text: 'Febbraio' 
 
    }, { 
 
    value: '03', 
 
    text: 'Marzo' 
 
    }, { 
 
    value: '04', 
 
    text: 'Aprile' 
 
    }, { 
 
    value: '05', 
 
    text: 'Maggio' 
 
    }, { 
 
    value: '06', 
 
    text: 'Giugno' 
 
    }, { 
 
    value: '07', 
 
    text: 'Luglio' 
 
    }, { 
 
    value: '08', 
 
    text: 'Agosto' 
 
    }, { 
 
    value: '09', 
 
    text: 'Settembre' 
 
    }, { 
 
    value: '10', 
 
    text: 'Ottobre' 
 
    }, { 
 
    value: '11', 
 
    text: 'Novembre' 
 
    }, { 
 
    value: '12', 
 
    text: 'Dicembre' 
 
    } 
 
] 
 

 
const annoCorrente = new Date().getFullYear(); 
 

 
@Component({ 
 
    selector: 'seg-month-picker', 
 
    templateUrl: './month-picker.component.html', 
 
    styleUrls: ['./month-picker.component.scss'], 
 
    providers: [{ 
 
    provide: NG_VALUE_ACCESSOR, 
 
    useExisting: forwardRef(() => MonthPickerComponent), 
 
    multi: true 
 
    }] 
 
}) 
 
export class MonthPickerComponent implements ControlValueAccessor { 
 

 
    private propagateChange: Function; 
 
    private checkedValue: string; 
 
    private isDisabled = true; 
 
    public meseSelezionato: string; 
 
    public annoSelezionato: string; 
 
    public yearList = []; 
 
    public monthList = listaMesi; 
 

 
    private _min: string; 
 
    private _max: string; 
 
    @Input() set min(value: string) { 
 
    this._min = value; 
 
    if (value) { 
 
     const [ year, month ] = value.split('-'); 
 
     const maxYear = this._max ? +this._max.slice(0, 4) : annoCorrente; 
 
     this.yearList = Array.from({ length: maxYear + 1 - +year }).map((_, index) => +year + index); 
 
    } 
 
    } 
 
    get min() { 
 
    return this._min; 
 
    } 
 

 
    @Input() set max(value: string) { 
 
    this._max = value; 
 
    if (value) { 
 
     const [ maxYear, month ] = value.split('-'); 
 
     const year = this._min ? +this.min.slice(0, 4) : annoCorrente; 
 
     this.yearList = Array.from({length: +maxYear - year + 1}).map((_, index) => year + index); 
 
    } 
 
    } 
 
    get max() { 
 
    return this._max; 
 
    } 
 

 
    updateYear(year: string) { 
 
    this.annoSelezionato = year; 
 
    this.updateValue(); 
 
    } 
 

 
    updateMonth(month: string) { 
 
    this.meseSelezionato = month; 
 
    this.updateValue(); 
 
    } 
 

 
    updateValue() { 
 
    if (this.annoSelezionato && this.meseSelezionato && this.propagateChange) { 
 
     this.propagateChange(`${this.annoSelezionato}-${this.meseSelezionato}`); 
 
    } 
 
    } 
 

 
    writeValue(yearMonth: string): void { 
 
    const [ year, month ] = yearMonth.split('-'); 
 
    this.annoSelezionato = year; 
 
    this.meseSelezionato = month; 
 
    } 
 

 
    registerOnChange(fn: Function): void { 
 
    this.propagateChange = fn; 
 
    } 
 

 
    registerOnTouched(fn: Function): void { } 
 

 
    setDisabledState(isDisabled: boolean): void { 
 
    this.isDisabled = isDisabled; 
 
    } 
 

 
}
<div> 
 
    <select id="anno" name="anno" [ngModel]="annoSelezionato" (ngModelChange)="updateYear($event)"> 
 
    <option *ngFor="let anno of yearList" [value]="anno.value">{{anno.value}}</option> 
 
    </select> 
 
    <select id="mese" name="mese" [ngModel]="meseSelezionato" (ngModelChange)="updateMonth($event)"> 
 
    <option *ngFor="let mese of monthList" [value]="mese.value">{{mese.text}}</option> 
 
    </select> 
 
</div>

的問題是:我如何跟蹤ngModule在我的單元測試變化?我會粘貼我的單元測試,這是不工作;我試着@viewChild(),但我肯定有錯誤。

import { Component, ViewChild } from '@angular/core'; 
 
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 
 
import { FormsModule } from '@angular/forms'; 
 

 
import { MonthPickerComponent } from './month-picker.component'; 
 

 
@Component({ 
 
    selector: 'seg-month-picker', 
 
    template: `<seg-month-picker>` 
 
}) 
 
export class TestComponent { 
 
    @ViewChild(MonthPickerComponent) picker; 
 
} 
 

 
function getComponent(): Promise<TestComponent> { 
 
    const fixture = TestBed 
 
    .createComponent(TestComponent); 
 

 
    fixture.detectChanges(); 
 

 
    return fixture.whenStable().then(() => fixture.componentInstance); 
 
} 
 

 

 

 
describe('MonthPickerComponent', async() => { 
 
    let component: MonthPickerComponent; 
 
    let fixture: ComponentFixture<MonthPickerComponent>; 
 
    let element: HTMLElement; 
 
    const mockedComponent = await getComponent(); 
 

 
    beforeEach(async(() => { 
 
    TestBed.configureTestingModule({ 
 
     declarations: [MonthPickerComponent, mockedComponent], 
 
     imports: [FormsModule] 
 
    }) 
 
    .compileComponents(); 
 
    })); 
 

 
    beforeEach(() => { 
 
    fixture = TestBed.createComponent(MonthPickerComponent); 
 
    component = fixture.componentInstance; 
 
    fixture.detectChanges(); 
 
    }); 
 

 
    it('should be created',() => { 
 
    expect(component).toBeTruthy(); 
 
    }); 
 

 
    describe('setMin',() => { 
 
    it('deve impostare la lista di anni in base al minimo dato',() => { 
 
     component.min = '2014-03'; 
 
     fixture.detectChanges(); 
 
     expect(component.yearList).toEqual([2014, 2015, 2016, 2017]); 
 
    }) 
 
    }); 
 

 
    describe('getMin',() => { 
 
    it('deve restituire l\'anno minimo della lista',() => { 
 
     component.min = '2014-03'; 
 
     fixture.detectChanges(); 
 
     const result = component.min; 
 
     expect(result).toBe('2014-03'); 
 
    }); 
 
    it('deve restituire null se non ho un valore minimo',() => { 
 
     component.min = undefined; 
 
     fixture.detectChanges(); 
 
     const result = component.min; 
 
     expect(result).toBe(undefined); 
 
    }) 
 
    }); 
 

 
    describe('setMax',() => { 
 
    it('deve restituire la lista di anni in base al massimo dato',() => { 
 
     component.max = '2018-01'; 
 
     fixture.detectChanges(); 
 
     expect(component.yearList).toEqual([2017, 2018]); 
 
    }); 
 
    it('deve restituire la lista di anni in base al range dato',() => { 
 
     component.max = '2018-01'; 
 
     component.min = '2014-01'; 
 
     fixture.detectChanges(); 
 
     expect(component.yearList).toEqual([2014, 2015, 2016, 2017, 2018]); 
 
    }); 
 
    }); 
 

 
    describe('getMax',() => { 
 
    it('deve restituire l\'anno massimo della lista',() => { 
 
     component.max = '2018-01'; 
 
     fixture.detectChanges(); 
 
     const result = component.max; 
 
     expect(result).toBe('2018-01'); 
 
    }); 
 
    it('deve restituire null se non ho un valore massimo',() => { 
 
     component.max = undefined; 
 
     fixture.detectChanges(); 
 
     const result = component.max; 
 
     expect(result).toBe(undefined); 
 
    }); 
 
    }); 
 

 
    describe('writeValue',() => { 
 
    fit('deve modificare il valore all\'ngModel del componente', async() => { 
 
     console.log(mockedComponent.picker); 
 
     mockedComponent.picker.writeValue('2016-03'); 
 
     fixture.detectChanges(); 
 
     const result = component.max; 
 
     expect(result).toBe('2018-01'); 
 
    }); 
 
    it('deve restituire null se non ho un valore massimo',() => { 
 
     component.max = undefined; 
 
     fixture.detectChanges(); 
 
     const result = component.max; 
 
     expect(result).toBe(undefined); 
 
    }); 
 
    }); 
 

 
});

的問題是,我必須測試writeValue()功能和從組件控制器的其他跟蹤哪些值的ngModel假定。我不知道如何解決這個問題。 感謝您的幫助!

---編輯--- 至少我可以在我的組件視圖中採用HTML引用<select>並更改它的值'編程',但我認爲有一個更好的方法。

回答

0

試試這個:

import { Component, Input, forwardRef } from '@angular/core'; 
 
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; 
 

 
const listaMesi = [ 
 
    { 
 
    value: '01', 
 
    text: 'Gennaio' 
 
    }, { 
 
    value: '02', 
 
    text: 'Febbraio' 
 
    }, { 
 
    value: '03', 
 
    text: 'Marzo' 
 
    }, { 
 
    value: '04', 
 
    text: 'Aprile' 
 
    }, { 
 
    value: '05', 
 
    text: 'Maggio' 
 
    }, { 
 
    value: '06', 
 
    text: 'Giugno' 
 
    }, { 
 
    value: '07', 
 
    text: 'Luglio' 
 
    }, { 
 
    value: '08', 
 
    text: 'Agosto' 
 
    }, { 
 
    value: '09', 
 
    text: 'Settembre' 
 
    }, { 
 
    value: '10', 
 
    text: 'Ottobre' 
 
    }, { 
 
    value: '11', 
 
    text: 'Novembre' 
 
    }, { 
 
    value: '12', 
 
    text: 'Dicembre' 
 
    } 
 
] 
 

 
const annoCorrente = new Date().getFullYear(); 
 

 
@Component({ 
 
    selector: 'seg-month-picker', 
 
    templateUrl: './month-picker.component.html', 
 
    styleUrls: ['./month-picker.component.scss'], 
 
    providers: [{ 
 
    provide: NG_VALUE_ACCESSOR, 
 
    useExisting: forwardRef(() => MonthPickerComponent), 
 
    multi: true 
 
    }] 
 
}) 
 
export class MonthPickerComponent implements ControlValueAccessor { 
 

 
    private propagateChange: Function; 
 
    private checkedValue: string; 
 
    private isDisabled = true; 
 
    public meseSelezionato: string; 
 
    public annoSelezionato: string; 
 
    public yearList = []; 
 
    public monthList = listaMesi; 
 

 
    private _min: string; 
 
    private _max: string; 
 
    @Input() set min(value: string) { 
 
    this._min = value; 
 
    if (value) { 
 
     const [ year, month ] = value.split('-'); 
 
     const maxYear = this._max ? +this._max.slice(0, 4) : annoCorrente; 
 
     this.yearList = Array.from({ length: maxYear + 1 - +year }).map((_, index) => +year + index); 
 
    } 
 
    } 
 
    get min() { 
 
    return this._min; 
 
    } 
 

 
    @Input() set max(value: string) { 
 
    this._max = value; 
 
    if (value) { 
 
     const [ maxYear, month ] = value.split('-'); 
 
     const year = this._min ? +this.min.slice(0, 4) : annoCorrente; 
 
     this.yearList = Array.from({length: +maxYear - year + 1}).map((_, index) => year + index); 
 
    } 
 
    } 
 
    get max() { 
 
    return this._max; 
 
    } 
 

 
    updateYear(year: string) { 
 
    this.annoSelezionato = year; 
 
    this.updateValue(); 
 
    } 
 

 
    updateMonth(month: string) { 
 
    this.meseSelezionato = month; 
 
    this.updateValue(); 
 
    } 
 

 
    updateValue() { 
 
    if (this.annoSelezionato && this.meseSelezionato && this.propagateChange) { 
 
     this.propagateChange(`${this.annoSelezionato}-${this.meseSelezionato}`); 
 
    } 
 
    } 
 

 
    writeValue(yearMonth: string): void { 
 
    const [ year, month ] = yearMonth.split('-'); 
 
    this.annoSelezionato = year; 
 
    this.meseSelezionato = month; 
 
    } 
 

 
    registerOnChange(fn: Function): void { 
 
    this.propagateChange = fn; 
 
    } 
 

 
    registerOnTouched(fn: Function): void { } 
 

 
    setDisabledState(isDisabled: boolean): void { 
 
    this.isDisabled = isDisabled; 
 
    } 
 

 
}