问题描述
问题:我想测试一个指令,该指令应该在'window:scroll'事件后更改元素的样式,但不知道如何触发该事件
指令:
@Directive({
selector: '[directiveSelector]',})
export class Directive {
private breakpointOffset: number;
private fixed = false;
constructor(
private readonly elementRef: ElementRef,) {}
ngAfterViewInit() {
//fix the element when scrollTop reaches past element's offsetTop
this.breakpointOffset = this.elementRef.nativeElement.offsetTop;
}
@HostListener('window:scroll')
addScrollTrigger() {
if (!this.fixed && window.pageYOffset > this.breakpointOffset) {
this.elementRef.nativeElement.setAttribute(
'style','position: fixed;
);
this.fixed = true;
}
if (this.fixed && window.pageYOffset <= this.breakpointOffset) {
this.elementRef.nativeElement.setAttribute('style','');
this.fixed = false;
}
}
}
我尝试过的事情:
@Component({
template: ` <div #container directive></div> `,})
class TestComponent {
@ViewChild('container') container: ElementRef;
}
describe('Directive',() => {
let fixture: ComponentFixture<TestComponent>;
let component: TestComponent;
beforeEach(async(() => {
Testbed.configureTestingModule({
declarations: [TestComponent,Directive],}).compileComponents();
fixture = Testbed.createComponent(TestComponent);
component = fixture.componentInstance;
}));
describe('addScrollTrigger',() => {
it('sets fixed style',() => {
//Trigger scroll event?
expect(component.container.nativeElement.styles).toEqual(....);
});
});
});
在我的测试中,我尝试使用带有带有该指令的div的模板创建组件。我无法执行的操作是触发滚动事件,因为我必须直接访问该指令并且不能调用“ addScrollTrigger”功能,可以吗?
解决方法
这是解决方案:
@Component({
template: ` <div #container directive></div> `,})
class TestComponent {
@ViewChild('container',{ static: true }) container: ElementRef;
}
describe('Directive',() => {
let fixture: ComponentFixture<TestComponent>;
let component: TestComponent;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [TestComponent,Directive],}).compileComponents();
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
// mocking the offsetParent
Object.defineProperty(HTMLElement.prototype,'offsetParent',{
get: function () {
return { offsetTop: 100 };
},});
// mocking the offsetTop
Object.defineProperty(HTMLElement.prototype,'offsetTop',{
get: function () {
return 50;
},});
fixture.detectChanges();
}));
describe('addScrollTrigger',() => {
it('sets fixed style',() => {
//Trigger window scroll event
window.dispatchEvent(new Event('scroll'));
fixture.detectChanges();
expect(component.container.nativeElement.styles).toEqual(....);
});
});
});