fix(aio): make `ScrollSpy` respond quicker to `scroll` events

Fixes ##17220
This commit is contained in:
Georgios Kalpakas 2017-06-06 18:58:59 +03:00 committed by Alex Rickabaugh
parent 3a121a621f
commit bfdd3398f6
2 changed files with 27 additions and 25 deletions

View File

@ -300,6 +300,7 @@ describe('ScrollSpyService', () => {
}); });
describe('window resize events', () => { describe('window resize events', () => {
const RESIZE_EVENT_DELAY = 300;
let onResizeSpy: jasmine.Spy; let onResizeSpy: jasmine.Spy;
beforeEach(() => { beforeEach(() => {
@ -317,7 +318,7 @@ describe('ScrollSpyService', () => {
window.dispatchEvent(new Event('resize')); window.dispatchEvent(new Event('resize'));
expect(onResizeSpy).not.toHaveBeenCalled(); expect(onResizeSpy).not.toHaveBeenCalled();
tick(300); tick(RESIZE_EVENT_DELAY);
expect(onResizeSpy).toHaveBeenCalled(); expect(onResizeSpy).toHaveBeenCalled();
})); }));
@ -327,58 +328,59 @@ describe('ScrollSpyService', () => {
onResizeSpy.calls.reset(); onResizeSpy.calls.reset();
window.dispatchEvent(new Event('resize')); window.dispatchEvent(new Event('resize'));
tick(300); tick(RESIZE_EVENT_DELAY);
expect(onResizeSpy).toHaveBeenCalled(); expect(onResizeSpy).toHaveBeenCalled();
info1.unspy(); info1.unspy();
onResizeSpy.calls.reset(); onResizeSpy.calls.reset();
window.dispatchEvent(new Event('resize')); window.dispatchEvent(new Event('resize'));
tick(300); tick(RESIZE_EVENT_DELAY);
expect(onResizeSpy).toHaveBeenCalled(); expect(onResizeSpy).toHaveBeenCalled();
info2.unspy(); info2.unspy();
onResizeSpy.calls.reset(); onResizeSpy.calls.reset();
window.dispatchEvent(new Event('resize')); window.dispatchEvent(new Event('resize'));
tick(300); tick(RESIZE_EVENT_DELAY);
expect(onResizeSpy).not.toHaveBeenCalled(); expect(onResizeSpy).not.toHaveBeenCalled();
})); }));
it('should only fire every 300ms', fakeAsync(() => { it(`should only fire every ${RESIZE_EVENT_DELAY}ms`, fakeAsync(() => {
scrollSpyService.spyOn([]); scrollSpyService.spyOn([]);
onResizeSpy.calls.reset(); onResizeSpy.calls.reset();
window.dispatchEvent(new Event('resize')); window.dispatchEvent(new Event('resize'));
tick(100); tick(RESIZE_EVENT_DELAY - 2);
expect(onResizeSpy).not.toHaveBeenCalled(); expect(onResizeSpy).not.toHaveBeenCalled();
window.dispatchEvent(new Event('resize')); window.dispatchEvent(new Event('resize'));
tick(100); tick(1);
expect(onResizeSpy).not.toHaveBeenCalled(); expect(onResizeSpy).not.toHaveBeenCalled();
window.dispatchEvent(new Event('resize')); window.dispatchEvent(new Event('resize'));
tick(100); tick(1);
expect(onResizeSpy).toHaveBeenCalledTimes(1); expect(onResizeSpy).toHaveBeenCalledTimes(1);
onResizeSpy.calls.reset(); onResizeSpy.calls.reset();
tick(150); tick(RESIZE_EVENT_DELAY / 2);
window.dispatchEvent(new Event('resize')); window.dispatchEvent(new Event('resize'));
tick(100); tick(RESIZE_EVENT_DELAY - 2);
expect(onResizeSpy).not.toHaveBeenCalled(); expect(onResizeSpy).not.toHaveBeenCalled();
window.dispatchEvent(new Event('resize')); window.dispatchEvent(new Event('resize'));
tick(100); tick(1);
expect(onResizeSpy).not.toHaveBeenCalled(); expect(onResizeSpy).not.toHaveBeenCalled();
window.dispatchEvent(new Event('resize')); window.dispatchEvent(new Event('resize'));
tick(100); tick(1);
expect(onResizeSpy).toHaveBeenCalledTimes(1); expect(onResizeSpy).toHaveBeenCalledTimes(1);
})); }));
}); });
describe('window scroll events', () => { describe('window scroll events', () => {
const SCROLL_EVENT_DELAY = 10;
let onScrollSpy: jasmine.Spy; let onScrollSpy: jasmine.Spy;
beforeEach(() => { beforeEach(() => {
@ -395,7 +397,7 @@ describe('ScrollSpyService', () => {
window.dispatchEvent(new Event('scroll')); window.dispatchEvent(new Event('scroll'));
expect(onScrollSpy).not.toHaveBeenCalled(); expect(onScrollSpy).not.toHaveBeenCalled();
tick(300); tick(SCROLL_EVENT_DELAY);
expect(onScrollSpy).toHaveBeenCalled(); expect(onScrollSpy).toHaveBeenCalled();
})); }));
@ -404,52 +406,52 @@ describe('ScrollSpyService', () => {
const info2 = scrollSpyService.spyOn([]); const info2 = scrollSpyService.spyOn([]);
window.dispatchEvent(new Event('scroll')); window.dispatchEvent(new Event('scroll'));
tick(300); tick(SCROLL_EVENT_DELAY);
expect(onScrollSpy).toHaveBeenCalled(); expect(onScrollSpy).toHaveBeenCalled();
info1.unspy(); info1.unspy();
onScrollSpy.calls.reset(); onScrollSpy.calls.reset();
window.dispatchEvent(new Event('scroll')); window.dispatchEvent(new Event('scroll'));
tick(300); tick(SCROLL_EVENT_DELAY);
expect(onScrollSpy).toHaveBeenCalled(); expect(onScrollSpy).toHaveBeenCalled();
info2.unspy(); info2.unspy();
onScrollSpy.calls.reset(); onScrollSpy.calls.reset();
window.dispatchEvent(new Event('scroll')); window.dispatchEvent(new Event('scroll'));
tick(300); tick(SCROLL_EVENT_DELAY);
expect(onScrollSpy).not.toHaveBeenCalled(); expect(onScrollSpy).not.toHaveBeenCalled();
})); }));
it('should only fire every 300ms', fakeAsync(() => { it(`should only fire every ${SCROLL_EVENT_DELAY}ms`, fakeAsync(() => {
scrollSpyService.spyOn([]); scrollSpyService.spyOn([]);
window.dispatchEvent(new Event('scroll')); window.dispatchEvent(new Event('scroll'));
tick(100); tick(SCROLL_EVENT_DELAY - 2);
expect(onScrollSpy).not.toHaveBeenCalled(); expect(onScrollSpy).not.toHaveBeenCalled();
window.dispatchEvent(new Event('scroll')); window.dispatchEvent(new Event('scroll'));
tick(100); tick(1);
expect(onScrollSpy).not.toHaveBeenCalled(); expect(onScrollSpy).not.toHaveBeenCalled();
window.dispatchEvent(new Event('scroll')); window.dispatchEvent(new Event('scroll'));
tick(100); tick(1);
expect(onScrollSpy).toHaveBeenCalledTimes(1); expect(onScrollSpy).toHaveBeenCalledTimes(1);
onScrollSpy.calls.reset(); onScrollSpy.calls.reset();
tick(150); tick(SCROLL_EVENT_DELAY / 2);
window.dispatchEvent(new Event('scroll')); window.dispatchEvent(new Event('scroll'));
tick(100); tick(SCROLL_EVENT_DELAY - 2);
expect(onScrollSpy).not.toHaveBeenCalled(); expect(onScrollSpy).not.toHaveBeenCalled();
window.dispatchEvent(new Event('scroll')); window.dispatchEvent(new Event('scroll'));
tick(100); tick(1);
expect(onScrollSpy).not.toHaveBeenCalled(); expect(onScrollSpy).not.toHaveBeenCalled();
window.dispatchEvent(new Event('scroll')); window.dispatchEvent(new Event('scroll'));
tick(100); tick(1);
expect(onScrollSpy).toHaveBeenCalledTimes(1); expect(onScrollSpy).toHaveBeenCalledTimes(1);
})); }));
}); });

View File

@ -124,7 +124,7 @@ export class ScrollSpyService {
private spiedElementGroups: ScrollSpiedElementGroup[] = []; private spiedElementGroups: ScrollSpiedElementGroup[] = [];
private onStopListening = new Subject(); private onStopListening = new Subject();
private resizeEvents = Observable.fromEvent(window, 'resize').auditTime(300).takeUntil(this.onStopListening); private resizeEvents = Observable.fromEvent(window, 'resize').auditTime(300).takeUntil(this.onStopListening);
private scrollEvents = Observable.fromEvent(window, 'scroll').auditTime(300).takeUntil(this.onStopListening); private scrollEvents = Observable.fromEvent(window, 'scroll').auditTime(10).takeUntil(this.onStopListening);
private lastContentHeight: number; private lastContentHeight: number;
private lastMaxScrollTop: number; private lastMaxScrollTop: number;