【问题标题】:Angular 2 Testing ngModel workflowAngular 2 测试 ngModel 工作流程
【发布时间】:2018-03-18 08:13:16
【问题描述】:

这是我的问题:

我有一个自定义组件,它有一个模板,里面有一个 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 假定的值。我真的不知道如何解决这个问题。 谢谢大家的帮助!

--- 编辑 --- 至少我可以在我的组件视图中对&lt;select&gt; 进行 html 引用并“以编程方式”更改其值,但我认为有更好的方法。

【问题讨论】:

    标签: javascript angular unit-testing typescript


    【解决方案1】:

    试试这个:

    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;
      }
    
    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-22
      相关资源
      最近更新 更多