如何在Angular 5中测试滚动? 如何在测试中模拟窗口?
这是我的代码:
import { Directive, ElementRef, HostListener } from '@angular/core';
@Directive({
selector: '[escElementPreventOverlap]'
})
export class ElementPreventOverlapDirective {
private offsetTop: number;
private scrollTop: number;
constructor(private element: ElementRef) {
}
@HostListener('window:scroll', ['$event'])
@HostListener('window:resize', ['$event'])
event(event) {
this.offsetTop= this.element.nativeElement.parentElement.offsetTop + this.element.nativeElement.parentElement.offsetHeight;
this.scrollTop= document.documentElement.scrollTop + window.innerHeight;
if (this.scrollTop> this.offsetTop) {
this.element.nativeElement.classList.remove('fixed');
} else {
this.element.nativeElement.classList.add('fixed');
}
}
}
工作正常,但我无法弄清楚如何测试它。
答案 0 :(得分:3)
我发现了怎么做!您需要将窗口注入您正在使用它的位置,以便在测试期间可以模拟它。
首先你必须创建一个文件(options.ts),写一下:
import { InjectionToken } from '@angular/core';
export const N_DOCUMENT = new InjectionToken<Document>('DocumentToken');
export const N_WINDOW = new InjectionToken<Window>('WindowToken');
其次,您必须在指令/组件中注入窗口:
import { Directive, ElementRef, HostListener, Inject } from '@angular/core';
import { N_WINDOW, N_DOCUMENT } from '../options';
@Directive({
selector: '[appElement]'
})
export class ElementDirective {
parentOffsetTopWithHeight: number;
documentScrollTopWithHeight: number;
constructor(public element: ElementRef, @Inject(N_WINDOW) window, @Inject(N_DOCUMENT) document) {
}
@HostListener('window:scroll', ['$event'])
scroll(event) {...}
}
第三,你可以在这样的测试中使用它:
import { ElementRef } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { ElementDirective } from '../element.directive';
import { N_WINDOW, N_DOCUMENT } from '../options';
class ElementRefMock extends ElementRef {
nativeElement = {
parentElement: {
offsetTop: 1200,
offsetHeight: 200,
},
classList: {
list: [],
add (className) {
if (this.list.indexOf(className) === -1) {
this.list.push(className);
}
},
remove (className) {
const classIndex = this.list.indexOf(className);
if (classIndex !== -1) {
this.list.splice(classIndex, 1);
}
},
contains (className) {
return this.list.indexOf(className) !== -1;
}
}
};
setNativeElement(nativeElement) {
this.nativeElement = nativeElement;
}
}
describe('ElementDirective', () => {
let directive: ElementDirective;
const elemDom = document.createElement('div');
const elementRef = new ElementRefMock(elemDom);
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
{provide: N_WINDOW, useValue: window},
{provide: N_DOCUMENT, useValue: document}
],
});
directive = new ElementDirective(elementRef, window, document);
});
it('should create an instance', () => {
expect(directive).toBeTruthy();
});
describe('scroll', () => {
it('should add class position-fixed', () => {
spyOnProperty(window, 'innerHeight', 'get').and.returnValue(1000);
spyOnProperty(document.documentElement, 'scrollTop', 'get').and.returnValue(100);
directive.scroll(<any>{});
expect(directive.element.nativeElement.classList.contains('position-fixed')).toBe(true);
});
});
第四,你必须在你的module.ts中添加提供者到NgModule:
import { DOCUMENT } from '@angular/common';
import { N_WINDOW, N_DOCUMENT } from '../options';
export function nWindowFactory() {
return window;
}
@NgModule({
...
providers: [
{provide: N_WINDOW, useFactory: nWindowFactory},
{provide: N_DOCUMENT, useExisting: DOCUMENT}
]
})