Problem: I want to test a directive which is supposed to change an element's styling after an 'window:scroll' event but don't know how to trigger the event
The Directive:
@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;
}
}
}
What I tried:
@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(....);
});
});
});
Within my test I tried to create a component with a template that has a div with that directive. What I am not able to do is trigger the scroll-event because I have to direct access to the directive and can not call the "addScrollTrigger"-function, can I?
Here is the solution:
@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(....);
});
});
});