My goal was to experiment with a simple AutoScrollDirective.
@Directive({
selector: '[appAutoScroll]',
})
export class AutoScrollDirective implements AfterViewInit {
constructor(private element: ElementRef<HTMLElement>) {}
@Input()
delay = 100;
ngAfterViewInit(): void {
setTimeout(
() => this.element.nativeElement.scrollIntoView({ behavior: 'smooth', block: 'start', inline: 'nearest' }),
this.delay
);
}
}
Upon closer inspection, I noticed that it utilizes a setTimeout. I pondered whether this could be handled more effectively with a fakeAsync approach.
@Component({
template: `<div appAutoScroll></div>`,
})
class TestAutoScrollDirectiveComponent implements AfterViewInit {
ngAfterViewInit(): void {}
}
describe('AutoScrollDirective', () => {
let fixture: ComponentFixture<TestAutoScrollDirectiveComponent>;
let component: TestAutoScrollDirectiveComponent;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [AutoScrollDirective, TestAutoScrollDirectiveComponent],
imports: [BrowserDynamicTestingModule],
});
fixture = TestBed.createComponent(TestAutoScrollDirectiveComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should call scrollIntoView of the element', fakeAsync(() => {
const scrollIntoViewMock = jest.fn();
HTMLElement.prototype.scrollIntoView = scrollIntoViewMock;
component.ngAfterViewInit();
tick();
expect(scrollIntoViewMock).toHaveBeenCalled();
}));
});
However, I encountered a hurdle where the function within the setTimeout is never triggered. Despite my attempts at debugging, the issue persists as it appears to reach ngAfterViewInit and invoke setTimeout but no action is taken.
Edit:
In an effort to resolve this, I explored the solution provided in this post. While it serves as a temporary workaround, I am open to suggestions for a more optimal resolution.