代码之家  ›  专栏  ›  技术社区  ›  Nimish goel

具有@输入属性的单元测试angular 4指令

  •  3
  • Nimish goel  · 技术社区  · 6 年前

    我有个指示 AllowOnlyNumbers 应用于输入类型文本框。

    <input                         
                        [AllowOnlyNumbers]=true
                        [maxLength]= 'yearlyFieldMaxLength'
                        type="tel"
                        name="totalAnnualIncome"
                        formControlName="totalAnnualIncome"
                        [(ngModel)]="yearlyIncomeAmt"
                        (focus)="onFocusEnableToolTip('TotalAnnualIncome')" 
                        (focusout)="onFocusOutDisableToolTip('TotalAnnualIncome')" 
                         minlength="2"
                         autocomplete="off"/>
    

    一个非常简单的指令限制用户只在文本框中输入数字。

    import { Directive, HostListener, Input } from '@angular/core';
    
    @Directive({
      selector: '[AllowOnlyNumbers]'
    })
    
    /**
     * @method AllowOnlyNumbers
     * @desc This directive restricts the keyboard entry to numbers only.
     * Users can enter numbers and can use backspace, tab,enter, escape, end, home, left, right and del keys.
     * Usage: <input type = "text" [AllowOnlyNumbers] = true />
     */
    
    export class AllowOnlyNumbers {
    
      constructor() { }
    
      @Input() AllowOnlyNumbers: boolean;
      /**
       * @methodspace AllowOnlyNumbers
       * @method onKeyDown
       * @desc It restricts the keyboard entry to numbers only.
       * @argument event
       * @returns returns only digit
       *
       */
      @HostListener('keydown', ['$event']) onKeyDown(event) {
        const e = event as KeyboardEvent;
        if (this.AllowOnlyNumbers) {
          // Allow: 8=Backspace, 9= Tab, 13=CR, 27=ESC, 35=END, 36=HOME, 37=Left, 39=Right, 46=DEL
          if ([8, 9, 13, 27, 35, 36, 37, 39, 46].indexOf(e.keyCode) !== -1) {
            return;
          }
    
          // Ensure that it is a number and stop the keypress
          if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
            e.preventDefault();
          }
        }
      }
    }
    

    现在,当使用jasmine编写单元测试用例时,我无法设置 @Input() AllowOnlyNumbers 属性为true。这始终是未定义的。 下面是我的UT文件。(注意:正在触发Keydown事件)

    import {ComponentFixture, TestBed} from '@angular/core/testing';
    import { AllowOnlyNumbers } from './allow-only-numbers.directive';
    import { Component, DebugElement, NO_ERRORS_SCHEMA } from '@angular/core';
    import { By } from '@angular/platform-browser';
    
    @Component({
      template: `<input [AllowOnlyNumbers]= true type="text" name="totalAnnualIncome"  />`
    })
    // tslint:disable-next-line:no-unnecessary-class
    class TestAllowOnlyNumbersComponent {
     //  allowNumbers = true;
    }
    fdescribe('Directive: AllowOnlyNumbers', () => {
      let component: TestAllowOnlyNumbersComponent;
      let fixture: ComponentFixture<TestAllowOnlyNumbersComponent>;
      let inputEl: DebugElement;
      let linkDes;
      let routerLinks;
    
      beforeEach(() => {
        TestBed.configureTestingModule({
          declarations: [TestAllowOnlyNumbersComponent, AllowOnlyNumbers],
          schemas:      [ NO_ERRORS_SCHEMA ]
        });
        fixture = TestBed.createComponent(TestAllowOnlyNumbersComponent);
        component = fixture.componentInstance;
        inputEl = fixture.debugElement.query(By.css('input[name="totalAnnualIncome"]'));
      });
    
      it('keydown input', () => {
        inputEl.triggerEventHandler('keydown', {});
        fixture.detectChanges();
        expect(true).toBe(true);
      });
    
    });
    

    我正在使用 this link 作为参考。我无法设置 @输入()AllowOnlyNumber 属性为true。这始终是未定义的。

    1 回复  |  直到 6 年前
        1
  •  7
  •   Mateusz    6 年前

    您的问题答案:

    应该是这样的 [AllowOnlyNumbers]="true" [AllowOnlyNumbers]= true 在里面 TestAllowOnlyNumbersComponent

    你实际上在做的是 [AllowOnlyNumbers]= 它不会为指令的输入赋值。

    你也应该搬家 fixture.detectChanges() triggerEventHandler 要触发初始值绑定,或者更好的做法是在 beforeEach

      beforeEach(() => {
        ...
        fixture.detectChanges();
      });
    
      it('keydown input', () => {
        inputEl.triggerEventHandler('keydown', {});
        expect(true).toBe(true);
      });
    

    关于您的指令的其他注释:

    我想你应该替换 keyCode 具有 key 在你的指令中 键代码 已弃用 https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent 。 我认为更改应该很容易,在您的指令中,您只需读取键字符串和基于该值的代码 const code = e.key.charCodeAt()

    然后,我将创建以下测试,以测试本例中的一个键“F”键:

      it('keydown input', () => {
        const event = new KeyboardEvent('keydown', { key: 'F' });
        inputEl.nativeElement.dispatchEvent(event);
        expect(event.defaultPrevented).toBe(true);
      });
    

    我想在指令中进行更改时,这可能会起作用。