UNPKG

ohayolibs

Version:

Ohayo is a set of essential modules for ohayojp.

145 lines (125 loc) 5.31 kB
import { Platform } from '@angular/cdk/platform'; import { DOCUMENT } from '@angular/common'; import { Injector, StaticProvider } from '@angular/core'; import { ScrollService } from './scroll.service'; describe('Service: Scroll', () => { const topOfPageElem = {} as Element; let injector: Injector; let doc: any; let window: any; let scrollService: ScrollService; class MockElement { getBoundingClientRect = jasmine.createSpy('Element getBoundingClientRect').and.returnValue({ top: 0 }); scrollIntoView = jasmine.createSpy('Element scrollIntoView'); scrollTo = jasmine.createSpy('Element scrollTo'); } class MockDocument { body = new MockElement(); getElementById = jasmine.createSpy('Document getElementById').and.returnValue(topOfPageElem); querySelector = jasmine.createSpy('Document querySelector'); defaultView: any = null; } describe('[default]', () => { class MockWindow { scrollBy(): void {} scrollTo(): void {} } beforeEach(() => { const providers = [ { provide: ScrollService, useClass: ScrollService, deps: [DOCUMENT, Platform] }, { provide: Platform, useValue: { isBrowser: true } }, { provide: DOCUMENT, useClass: MockDocument, deps: [] }, ] as StaticProvider[]; injector = Injector.create({ providers }); doc = injector.get(DOCUMENT) as any; doc.defaultView = new MockWindow(); window = doc.defaultView; scrollService = injector.get(ScrollService); spyOn(window, 'scrollBy'); spyOn(window, 'scrollTo'); }); describe('#getScrollPosition', () => { it('with HTMLElement', () => { const element: Element = new MockElement() as any; element.scrollLeft = 10; element.scrollTop = 11; const position = scrollService.getScrollPosition(element); expect(position[0]).toBe(10); expect(position[1]).toBe(11); }); it('with Window', () => { window.pageXOffset = 10; window.pageYOffset = 11; const position = scrollService.getScrollPosition(); expect(position[0]).toBe(10); expect(position[1]).toBe(11); }); }); describe('#scrollToPosition', () => { it('with HTMLElement', () => { const element: Element = new MockElement() as any; scrollService.scrollToPosition(element, [10, 11]); expect(element.scrollTo).toHaveBeenCalledWith(10, 11); }); it('with Window', () => { scrollService.scrollToPosition(null, [10, 11]); expect(window.scrollTo).toHaveBeenCalledWith(10, 11); }); }); describe('#scrollToElement', () => { it('should scroll to element', () => { const element: Element = new MockElement() as any; scrollService.scrollToElement(element); expect(element.scrollIntoView).toHaveBeenCalled(); expect(window.scrollBy).toHaveBeenCalledWith(0, 0); }); it('should not scroll more than necessary (e.g. for elements close to the bottom)', () => { const element: Element = new MockElement() as any; const getBoundingClientRect = element.getBoundingClientRect as jasmine.Spy; const topOffset = 0; getBoundingClientRect.and.returnValue({ top: topOffset + 100 }); scrollService.scrollToElement(element); expect(element.scrollIntoView).toHaveBeenCalledTimes(1); expect(window.scrollBy).toHaveBeenCalledWith(0, 100); getBoundingClientRect.and.returnValue({ top: topOffset - 10 }); scrollService.scrollToElement(element); expect(element.scrollIntoView).toHaveBeenCalledTimes(2); expect(window.scrollBy).toHaveBeenCalledWith(0, -10); }); it('should scroll all the way to the top if close enough', () => { const element: Element = new MockElement() as any; (window as any).pageYOffset = 25; scrollService.scrollToElement(element); expect(element.scrollIntoView).toHaveBeenCalled(); expect(window.scrollBy).toHaveBeenCalledWith(0, 0); (window.scrollBy as jasmine.Spy).calls.reset(); (window as any).pageYOffset = 15; scrollService.scrollToElement(element); expect(element.scrollIntoView).toHaveBeenCalled(); expect(window.scrollBy).toHaveBeenCalledWith(0, 0); expect(window.scrollBy).toHaveBeenCalledWith(0, -15); }); it('should scroll to top if no element', () => { scrollService.scrollToElement(null); expect(window.scrollBy).toHaveBeenCalledWith(0, 0); }); it('should only use scrollIntoView', () => { doc.defaultView.scrollBy = null; const element: Element = new MockElement() as any; scrollService.scrollToElement(element); expect(element.scrollIntoView).toHaveBeenCalled(); expect(element.getBoundingClientRect).not.toHaveBeenCalled(); }); }); describe('#scrollToTop', () => { it('should scroll to top', () => { scrollService.scrollToTop(); expect(window.scrollBy).toHaveBeenCalledWith(0, 0); }); it('should scroll to top of offset 10 pixels', () => { scrollService.scrollToTop(10); expect(window.scrollBy).toHaveBeenCalledWith(0, -10); }); }); }); });