mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
118 lines
5.3 KiB
TypeScript
118 lines
5.3 KiB
TypeScript
|
|
import {browser, by, element, ElementFinder} from 'protractor';
|
||
|
|
import {ILocation, ISize} from 'selenium-webdriver';
|
||
|
|
|
||
|
|
declare var window: any;
|
||
|
|
|
||
|
|
|
||
|
|
describe('autosize cdk-virtual-scroll', () => {
|
||
|
|
let viewport: ElementFinder;
|
||
|
|
|
||
|
|
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 () => {
|
||
|
|
// The estimate of the total content size is exactly correct, so we wind up scrolled to the
|
||
|
|
// same place as if we slowly scrolled down.
|
||
|
|
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);
|
||
|
|
|
||
|
|
// As we slowly scroll back up we should wind up back at the start of the content.
|
||
|
|
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 () => {
|
||
|
|
// The estimate of the total content size is slightly different than the actual, so we don't
|
||
|
|
// wind up in the same spot as if we scrolled slowly down.
|
||
|
|
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);
|
||
|
|
|
||
|
|
// As we slowly scroll back up we should wind up back at the start of the content. As we
|
||
|
|
// scroll the error from when we jumped the scroll position should be slowly corrected.
|
||
|
|
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: ElementFinder, viewport: ElementFinder): Promise<boolean> {
|
||
|
|
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: ILocation, size: ISize):
|
||
|
|
{top: number, left: number, bottom: number, right: number} {
|
||
|
|
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: any, offset: number, done: () => void) {
|
||
|
|
viewportEl.scrollTop = offset;
|
||
|
|
window.requestAnimationFrame(() => done());
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/** Smoothly scrolls the viewport to the given offset, 25px at a time. */
|
||
|
|
function smoothScrollViewportTo(viewportEl: any, offset: number, done: () => void) {
|
||
|
|
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());
|
||
|
|
}
|