简体   繁体   中英

How to unit test an Hostlistener onChange event in a directive in angular?

I created an directive to allow only numbers for a input field and I want to cover this directive with unit test. But I don't know how to cover the @HostListener('input') onChange() part of my code.

The directive:

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

@Directive({
  selector: '[onlyNumbers]'
})

export class OnlyNumbersDirective {
  @Input() onlyNumbers: boolean | undefined;
  
  constructor(private el: ElementRef, private renderer2: Renderer2) {
  }
  
  @HostListener('input') onChange() {
    if(this.onlyNumbers) {
      const { value } = this.el.nativeElement;
      this.renderer2.setProperty(this.el.nativeElement, 'value', value.replace(/[^0-9]/g, ''));
    }
  }
}

Unit test which I tried:

import { TestBed, ComponentFixture } from '@angular/core/testing';
import { OnlyNumbersDirective } from './onlyNumbers.directive';
import { Component, Input, OnInit} from '@angular/core';

// Create component to test
@Component({
  template: `<input type="text" [ngModel]="value" [onlyNumbers]="enableNumbers"/>`
})
class TestComponent implements OnInit {
    @Input() enableNumbers = true;
    @Input() value : any;

    ngOnInit() {
        this.enableNumbers = true;
        this.value = '123a'
    }
}

describe('OnlyNumbersDirective', () => {
  let component: TestComponent;
  let fixture: ComponentFixture<TestComponent>;

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [
        TestComponent,
        OnlyNumbersDirective
      ]
    });

    fixture = TestBed.createComponent(TestComponent);
    component = fixture.componentInstance;
  });

  it('should create component', () => {
    expect(component).toBeDefined();
  });

  it('should allow numbers only', () => {
    const debugEl: HTMLElement = fixture.debugElement.nativeElement;
    const input: HTMLElement = debugEl.querySelector('input');

    fixture.detectChanges();

    expect(input.value).toBe('123');
  });
});

How can I cover the @HostListener('input') onChange() part with Jasmine/Karma in Angular?

Try something like this:

it('should do xyz', () => {
  const input = fixture.debugElement.nativeElement.querySelector('input');
  input.dispatchEvent(new Event('change', {target: {value: 'value of input goes here'}} as any)); // try adding as any here
  fixture.detectChanges();
  fixture.whenStable().then(() => {
    expect(1).toBe(1); // dummy assertion here but you can put your assertions here.
  });
});

Fixed by creating a component inside the unit test and by using the directive directly with this created component.

it('should allow numbers only', () => {
    const event = new Event('input', {} as any);

    const component = TestBed.createComponent(NameComponent);
    input = component.debugElement.query(By.directive(NameDirective));
    component.detectChanges();
    input.nativeElement.value = '1a';

    input.nativeElement.dispatchEvent(event);

    expect(input.nativeElement.value).toBe('1');
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM