import { browser , by , element , ElementFinder } from 'protractor' ; import { ILocation , ISize } from 'selenium-webdriver' ; declare var window ; describe ( 'autosize cdk-virtual-scroll' , ( ) => { let viewport ; describe ( 'with uniform items' , ( ) => { beforeEach ( ( ) => { browser . get ( '/virtual-scroll' ) ; viewport = element ( by . css ( '.demo-virtual-scroll-uniform-size cdk-virtual-scroll-viewport' ) ) ; } ) ; it ( 'should scroll down slowly' , async ( ) => { await browser . executeAsyncScript ( smoothScrollViewportTo , viewport , 2000 ) ; const offScreen = element ( by . css ( '.demo-virtual-scroll-uniform-size [data-index="39"]' ) ) ; const onScreen = element ( by . css ( '.demo-virtual-scroll-uniform-size [data-index="40"]' ) ) ; expect ( await isVisibleInViewport ( offScreen , viewport ) ) . toBe ( false ) ; expect ( await isVisibleInViewport ( onScreen , viewport ) ) . toBe ( true ) ; } ) ; it ( 'should jump scroll position down and slowly scroll back up' , async ( ) => { await browser . executeAsyncScript ( scrollViewportTo , viewport , 2000 ) ; const offScreen = element ( by . css ( '.demo-virtual-scroll-uniform-size [data-index="39"]' ) ) ; const onScreen = element ( by . css ( '.demo-virtual-scroll-uniform-size [data-index="40"]' ) ) ; expect ( await isVisibleInViewport ( offScreen , viewport ) ) . toBe ( false ) ; expect ( await isVisibleInViewport ( onScreen , viewport ) ) . toBe ( true ) ; await browser . executeAsyncScript ( smoothScrollViewportTo , viewport , 0 ) ; const first = element ( by . css ( '.demo-virtual-scroll-uniform-size [data-index="0"]' ) ) ; expect ( await isVisibleInViewport ( first , viewport ) ) . toBe ( true ) ; } ) ; } ) ; describe ( 'with variable size' , ( ) => { beforeEach ( ( ) => { browser . get ( '/virtual-scroll' ) ; viewport = element ( by . css ( '.demo-virtual-scroll-variable-size cdk-virtual-scroll-viewport' ) ) ; } ) ; it ( 'should scroll down slowly' , async ( ) => { await browser . executeAsyncScript ( smoothScrollViewportTo , viewport , 2000 ) ; const offScreen = element ( by . css ( '.demo-virtual-scroll-variable-size [data-index="19"]' ) ) ; const onScreen = element ( by . css ( '.demo-virtual-scroll-variable-size [data-index="20"]' ) ) ; expect ( await isVisibleInViewport ( offScreen , viewport ) ) . toBe ( false ) ; expect ( await isVisibleInViewport ( onScreen , viewport ) ) . toBe ( true ) ; } ) ; it ( 'should jump scroll position down and slowly scroll back up' , async ( ) => { await browser . executeAsyncScript ( scrollViewportTo , viewport , 2000 ) ; const offScreen = element ( by . css ( '.demo-virtual-scroll-variable-size [data-index="18"]' ) ) ; const onScreen = element ( by . css ( '.demo-virtual-scroll-variable-size [data-index="19"]' ) ) ; expect ( await isVisibleInViewport ( offScreen , viewport ) ) . toBe ( false ) ; expect ( await isVisibleInViewport ( onScreen , viewport ) ) . toBe ( true ) ; await browser . executeAsyncScript ( smoothScrollViewportTo , viewport , 0 ) ; const first = element ( by . css ( '.demo-virtual-scroll-variable-size [data-index="0"]' ) ) ; expect ( await isVisibleInViewport ( first , viewport ) ) . toBe ( true ) ; } ) ; } ) ; } ) ; /** Checks if the given element is visible in the given viewport. */ async function isVisibleInViewport ( el , viewport ) { if ( ! await el . isPresent ( ) || ! await el . isDisplayed ( ) || ! await viewport . isPresent ( ) || ! await viewport . isDisplayed ( ) ) { return false ; } const viewportRect = getRect ( await viewport . getLocation ( ) , await viewport . getSize ( ) ) ; const elRect = getRect ( await el . getLocation ( ) , await el . getSize ( ) ) ; return elRect . left < viewportRect . right && elRect . right > viewportRect . left && elRect . top < viewportRect . bottom && elRect . bottom > viewportRect . top ; } /** Gets the rect for an element given its location ans size. */ function getRect ( location , size ) { return { top : location . y , left : location . x , bottom : location . y + size . height , right : location . x + size . width } ; } /** Immediately scrolls the viewport to the given offset. */ function scrollViewportTo ( viewportEl , offset , done ) { viewportEl . scrollTop = offset ; window . requestAnimationFrame ( ( ) => done ( ) ) ; } /** Smoothly scrolls the viewport to the given offset, 25px at a time. */ function smoothScrollViewportTo ( viewportEl , offset , done ) { let promise = Promise . resolve ( ) ; let curOffset = viewportEl . scrollTop ; do { const co = curOffset += Math . min ( 25 , Math . max ( - 25 , offset - curOffset ) ) ; promise = promise . then ( ( ) => new Promise < void > ( resolve => { viewportEl . scrollTop = co ; window . requestAnimationFrame ( ( ) => resolve ( ) ) ; } ) ) ; } while ( curOffset != offset ) ; promise . then ( ( ) => done ( ) ) ; }