![](/img/trans.png)
[英]Angular 2+ scroll with HostListener or window.pageYOffset?
[英]HostListener scroll testing in Angular 5
如何在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');
}
}
}
工作正常,但我不知道如何測試。
我發現了該怎么做! 您需要將窗口注入到使用它的位置,以便在測試期間可以對其進行模擬。
首先,您必須創建一個文件(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}
]
})
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.