我在搜索字段中写了一个反跳指令,以防止过多的后端调用/处理。它按预期工作。但是我无法为此编写规格。我希望你们中的一些人可以帮助我:)如果您想尝试一下,我制造了一个here塞子。目前,我认为该指令未按预期初始化。
我的指令
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');
}));
});
答案 0 :(得分:1)
正如@trollr所建议的那样,我发布的解决方案可以作为答案:将事件的类型从“ keyup”事件更改为“ input”事件。
在指令中:
const eventStream = fromEvent(this.elementRef.nativeElement, 'input').pipe(
在测试中:
inputEl.nativeElement.dispatchEvent(new Event('input'));
这些更改以及注释掉对fixture.detectChanges()
的首次调用已解决了该问题。
这是StackBlitz,显示所有测试通过。
编码愉快!