Испытание угловой директивы с опровержением - PullRequest
0 голосов
/ 26 марта 2019

я написал директиву debounce для моего поля поиска, чтобы предотвратить слишком много вызовов / обработки бэкэндом. Работает как положено. Однако я не могу написать спецификацию для него. Я надеюсь, что некоторые из вас, ребята, могут мне помочь :) Если вы хотите попробовать это, я создал вантуз здесь . В настоящий момент я предполагаю, что директива инициализирована не так, как ожидалось.

Моя директива

import { NgModel } from '@angular/forms';
import { fromEvent } from 'rxjs';
import { debounceTime, map } from 'rxjs/operators';

@Directive({selector: '[debounce]'})
export class DebounceDirective implements OnInit {
  @Input() delay: number = 300;

  constructor(private elementRef: ElementRef, private model: NgModel) {
  }

  public ngOnInit(): void {
    const eventStream = fromEvent(this.elementRef.nativeElement, 'keyup').pipe(
      map(() => {
        return this.model.value;
      }),
      debounceTime(this.delay));

    this.model.viewToModelUpdate = () => {
    };

    eventStream.subscribe(input => {
      this.model.viewModel = input;
      this.model.update.emit(input);
    });
  }
}

Мои характеристики

import { DebounceDirective } from '@modules/shared/directives/debounce.directive';
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { Component, DebugElement, ViewChild } from '@angular/core';
import { By } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';

@Component({
  template: '<input type="text" name="test" debounce [delay]="500" [(ngModel)]="value" (ngModelChange)="test()">'
})
class DebounceDirectiveTestingComponent {
  @ViewChild(DebounceDirective) directive: DebounceDirective;
  public value: string = '';

  public test() {
  }
}

describe('Directive: Debounce', () => {
  let component: DebounceDirectiveTestingComponent;
  let fixture: ComponentFixture<DebounceDirectiveTestingComponent>;
  let inputEl: DebugElement;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [FormsModule],
      declarations: [DebounceDirective, DebounceDirectiveTestingComponent]
    }).compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(DebounceDirectiveTestingComponent);
    component = fixture.componentInstance;
    inputEl = fixture.debugElement.query(By.css('input'));
    fixture.detectChanges();
  });

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

  it('should emit values after 500 msec debounce', fakeAsync(() => {
    const directiveEl = fixture.debugElement.query(By.directive(DebounceDirective));
    spyOn(component, 'test').and.stub();
    spyOn(component.directive, 'ngOnInit').and.callThrough();

    fixture.detectChanges();

    expect(directiveEl).toBeDefined();
    expect(component.directive.ngOnInit).toHaveBeenCalled();
    expect(component.directive.delay).toBe(500);

    inputEl.nativeElement.value = 'test';
    inputEl.nativeElement.dispatchEvent(new Event('keyup'));

    fixture.detectChanges();

    expect(component.value).toBe('');

    tick(500);
    fixture.detectChanges();

    expect(component.test).toHaveBeenCalled();
    expect(component.value).toBe('test');
  }));
});

1 Ответ

1 голос
/ 28 марта 2019

Как предложено @trollr, я публикую решение, которое сработало как ответ: изменение типа события с события 'keyup' на событие 'input'.

В директиве:

const eventStream = fromEvent(this.elementRef.nativeElement, 'input').pipe(

И в тесте:

inputEl.nativeElement.dispatchEvent(new Event('input'));

Эти изменения, наряду с комментированием первого вызова fixture.detectChanges(), решили проблему.

Вот StackBlitz показывает все пройденные тесты.

...