单元测试指令 HostListener 不起作用

Posted

技术标签:

【中文标题】单元测试指令 HostListener 不起作用【英文标题】:Unit testing directive HostListener not working 【发布时间】:2018-07-03 18:00:53 【问题描述】:

我正在尝试对一些在前端完美运行的功能进行单元测试,但单元测试似乎没有成功。

以下是我当前的单元测试,它还没有完全完成。我只是想在进行更复杂的检查之前让基本测试正常工作。

@Component(
  template : '<input appInputFilter filterType="alphanumericOnly" type="text" minlength="2">'
)
class TestComponent 



describe('InputFilterDirective', () => 

  let comp: TestComponent;
  let fixture: ComponentFixture<TestComponent>;
  let de: DebugElement;
 // const el: htmlElement;

  beforeEach(() => 
    TestBed.configureTestingModule(
      declarations : [InputFilterDirective, TestComponent]
    );

    fixture = TestBed.createComponent(TestComponent);

    comp = fixture.componentInstance;

    de = fixture.debugElement.query(By.directive(InputFilterDirective));
  );

  it('should create instance of inputFilter', () => 
    expect(comp).toBeTruthy();
    expect(de).toBeDefined();
  );

  it('should only allow onlyNumbers', async(() => 

    fixture.detectChanges();


    const keyEvent = new KeyboardEvent('keydown', 'code': 'KeyQ');
    const input = de.nativeElement as HTMLInputElement;
    input.dispatchEvent(keyEvent);
    expect(input.value).toEqual('q');


    expect(true).toBeTruthy();
  ));
);

这是我的完整指令:

 import  Directive, ElementRef, HostListener, Input   from '@angular/core';

@Directive(
  selector: '[appInputFilter]',

)
export class InputFilterDirective 

  private el : any;
  private specialKeys : Array<string> = ['Backspace', 'Tab', 'End', 'Home'];

  @Input() public filterType : any;

  constructor(el: ElementRef) 
    this.el = el;
   

   @HostListener('keydown', ['$event'])
   onKeyDown(event: KeyboardEvent) 

    if (this.specialKeys.indexOf(event.key) !== -1) 
      return;
    

    switch (this.filterType) 
      case 'onlyNumber':
        this.appFilter(event, new RegExp(/\D/g));
      break;
      case 'alphanumericOnly':
        this.appFilter(event, new RegExp(/\W/g));
      break;
      case 'alphabeticAndSpecial':
        this.appFilter(event, new RegExp(/[^a-zA-Z'-]/));
      break;
      case 'ipAddress':
        this.appFilter(event, new RegExp(/[^0-9.]/g));
      break;
    
   ;

  appFilter(event: KeyboardEvent, regex: RegExp) 
    const current: string = this.el.nativeElement.value;
    const next: string = current.concat(event.key);

    if (next && String(next).match(regex)) 
      event.preventDefault();
    
  ;

补充说明:

我尝试了许多不同的 KeyEvent,例如 type key: '1' 等。 我已将单元测试作为异步和非异步运行。 关于其他人如何尝试对 HostListener 进行单元测试,我遵循了许多不同的堆栈溢出说明,不幸的是,这对我来说根本不起作用,我不知道为什么。

非常感谢您的帮助,就像我说这是一个简单的测试,您会在测试组件中注意到我正在使用过滤器来过滤字母数字(您可以在指令代码中查看)

我也反对听“preventDefault”来证明这个测试,所以如果问题是我如何检测变化,那么请告诉我,我不介意调整。

【问题讨论】:

【参考方案1】:

我很幸运在指令元素上使用了triggerEventHandler。例如,

it('should add "c2d-dropzone-active" class to element when dragenter has occurred', async done => 
  fixture.detectChanges();
  const el: any = element.query(By.directive(C2dDropzoneDirective));
  expect(el.nativeElement.className).not.toContain('c2d-dropzone-active');
  el.triggerEventHandler('dragenter', mockEvent);
  fixture.detectChanges();
  await fixture.whenStable();
  expect(el.nativeElement.className).toContain('c2d-dropzone-active');
  done();
);

【讨论】:

以上是关于单元测试指令 HostListener 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

phpunit xml配置颜色指令不起作用

指令绑定在规范文件中不起作用

如果它来自指令,是不是可以点击按钮

尽管单元测试正常运行,但 Authtoken 迁移不起作用

指定端口时,Spring Boot Actuator 端点的单元测试不起作用

监听指令主机上的输入值变化