使用ngModelChange

时间:2017-09-19 20:55:51

标签: angular angular-unit-test

我有一个我应用于输入的PhoneMask指令,它将删除非数字字符并根据我设置的掩码格式化数字(例如1234567890的输入将被格式化为{{ 1}})。面具本身有效,但我想为它编写一个单元测试,我在确定如何做到这一点时遇到了问题。

PhoneMask指令:

(123) 456-7890

PhoneMask测试/规范:

import {Directive, ElementRef, EventEmitter, Output} from '@angular/core';
import {NgControl} from '@angular/forms';

@Directive({
  selector: '[PhoneMask]',
  host: {
    '(ngModelChange)': 'onInputChange($event)'
  }
})
export class PhoneMaskDirective {

  @Output() rawChange: EventEmitter<string> = new EventEmitter<string>();

  constructor(public model: NgControl, private el: ElementRef) {
  }

  onInputChange(inputValue) {
    const selectionStart = this.el.nativeElement.selectionStart;
    const [rawNumber, cursor] = this.getRawNumberAndCursor(inputValue, selectionStart);
    const [formattedNumber, formattedCursor] = this.getFormattedNumberAndCursor(rawNumber, cursor);

    // Set input to formatted value
    this.model.valueAccessor.writeValue(formattedNumber);
    // Set cursor in the right spot
    this.el.nativeElement.selectionStart = this.el.nativeElement.selectionEnd = formattedCursor;

    this.rawChange.emit(rawNumber);

  }

  getRawNumberAndCursor(text: string, cursorPos: number): [string, number] {
    let rawNumber = '';
    let rawPos = cursorPos;
    for (let i = 0, len = text.length; i < len; i++) {
      if (/\d/.test(text[i])) {
        rawNumber += text[i];
      } else if (i < cursorPos) {
        rawPos--;
      }
    }
    return [rawNumber, rawPos];
  }

  getFormattedNumberAndCursor(numberVal: string, cursorPos: number): [string, number] {
    let formattedNumber = '';
    if (numberVal.length == 0) {
      formattedNumber = '';
    } else if (numberVal.length <= 3) {
      formattedNumber = numberVal.replace(/^(\d{0,3})/, '($1)');
    } else if (numberVal.length <= 6) {
      formattedNumber = numberVal.replace(/^(\d{0,3})(\d{0,3})/, '($1) $2');
    } else if (numberVal.length <= 10) {
      formattedNumber = numberVal.replace(/^(\d{0,3})(\d{0,3})(.*)/, '($1) $2-$3');
    } else {
      formattedNumber = numberVal.replace(/^(\d{0,3})(\d{0,3})(\d{0,4})(.*)/, '($1) $2-$3 $4');
    }
    for (let i = 0; i < cursorPos; i++) {
      if (/\D/.test(formattedNumber[i])) {
        cursorPos++;
      }
    }
    return [formattedNumber, cursorPos];
  }
}

在测试中,我希望import {PhoneMaskDirective} from './phone-mask.directive'; import {Component} from '@angular/core'; import {TestBed} from '@angular/core/testing'; import {By} from '@angular/platform-browser'; import {FormsModule} from '@angular/forms'; @Component({ template: ` <input PhoneMask [(ngModel)]="phone"/> ` }) class TestPhoneMaskDirectiveComponent { } describe('PhoneMaskDirective', () => { let fixture; let theInput; beforeEach(async () => { fixture = TestBed.configureTestingModule({ imports: [FormsModule], declarations: [PhoneMaskDirective, TestPhoneMaskDirectiveComponent], }) .createComponent(TestPhoneMaskDirectiveComponent); fixture.detectChanges(); theInput = fixture.debugElement.query(By.directive(PhoneMaskDirective)); }); it('should find one instance of the directive', () => { expect(theInput).toBeTruthy(); }); it('should handle input of non-numeric characters', async () => { fixture.detectChanges(); let element = theInput.nativeElement; element.value = 'bob123'; element.dispatchEvent(new Event('input', {bubbles: true, cancelable: true})); fixture.detectChanges(); fixture.whenStable().then(() => { expect(fixture.componentInstance.phone).toEqual('(123)'); }); }); }); 的输入结果为bob123。但是,当我运行测试时,我得到(123)的失败结果。

我尝试了Expected 'bob123' to equal '(123)'.async以及fakeAsyncdetectChanges()调用的各种组合,甚至用{{1来包装最终期望值}}。输入的valueAccessor更新后,如何访问模型的值?

0 个答案:

没有答案