mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
feat(overlay): add scroll blocking strategy (#4500)
Adds the `BlockScrollStrategy` which, when activated, will prevent the user from scrolling. For now it is only used in the dialog. Relates to #4093.
This commit is contained in:
committed by
Jeremy Elbourn
parent
0666207527
commit
6842046979
@@ -0,0 +1,134 @@
|
||||
import {browser, Key, element, by} from 'protractor';
|
||||
import {screenshot} from '../../screenshot';
|
||||
import {getScrollPosition} from '../../util/query';
|
||||
|
||||
|
||||
describe('scroll blocking', () => {
|
||||
beforeEach(() => browser.get('/block-scroll-strategy'));
|
||||
afterEach(() => clickOn('disable'));
|
||||
|
||||
it('should not be able to scroll programmatically along the x axis', async (done) => {
|
||||
scrollPage(0, 100);
|
||||
expect((await getScrollPosition()).y).toBe(100, 'Expected the page to be scrollable.');
|
||||
|
||||
clickOn('enable');
|
||||
scrollPage(0, 200);
|
||||
expect((await getScrollPosition()).y).toBe(100, 'Expected the page not to be scrollable.');
|
||||
|
||||
clickOn('disable');
|
||||
scrollPage(0, 300);
|
||||
expect((await getScrollPosition()).y).toBe(300, 'Exected page to be scrollable again.');
|
||||
|
||||
screenshot();
|
||||
done();
|
||||
});
|
||||
|
||||
it('should not be able to scroll programmatically along the y axis', async (done) => {
|
||||
scrollPage(100, 0);
|
||||
expect((await getScrollPosition()).x).toBe(100, 'Expected the page to be scrollable.');
|
||||
|
||||
clickOn('enable');
|
||||
scrollPage(200, 0);
|
||||
expect((await getScrollPosition()).x).toBe(100, 'Expected the page not to be scrollable.');
|
||||
|
||||
clickOn('disable');
|
||||
scrollPage(300, 0);
|
||||
expect((await getScrollPosition()).x).toBe(300, 'Exected page to be scrollable again.');
|
||||
|
||||
screenshot();
|
||||
done();
|
||||
});
|
||||
|
||||
it('should not be able to scroll via the keyboard along the y axis', async (done) => {
|
||||
const body = element(by.tagName('body'));
|
||||
|
||||
scrollPage(0, 100);
|
||||
expect((await getScrollPosition()).y).toBe(100, 'Expected the page to be scrollable.');
|
||||
|
||||
clickOn('enable');
|
||||
await body.sendKeys(Key.ARROW_DOWN);
|
||||
await body.sendKeys(Key.ARROW_DOWN);
|
||||
await body.sendKeys(Key.ARROW_DOWN);
|
||||
expect((await getScrollPosition()).y).toBe(100, 'Expected the page not to be scrollable.');
|
||||
|
||||
clickOn('disable');
|
||||
await body.sendKeys(Key.ARROW_DOWN);
|
||||
await body.sendKeys(Key.ARROW_DOWN);
|
||||
await body.sendKeys(Key.ARROW_DOWN);
|
||||
expect((await getScrollPosition()).y)
|
||||
.toBeGreaterThan(100, 'Expected the page to be scrollable again.');
|
||||
|
||||
screenshot();
|
||||
done();
|
||||
});
|
||||
|
||||
it('should not be able to scroll via the keyboard along the x axis', async (done) => {
|
||||
const body = element(by.tagName('body'));
|
||||
|
||||
scrollPage(100, 0);
|
||||
expect((await getScrollPosition()).x).toBe(100, 'Expected the page to be scrollable.');
|
||||
|
||||
clickOn('enable');
|
||||
await body.sendKeys(Key.ARROW_RIGHT);
|
||||
await body.sendKeys(Key.ARROW_RIGHT);
|
||||
await body.sendKeys(Key.ARROW_RIGHT);
|
||||
expect((await getScrollPosition()).x).toBe(100, 'Expected the page not to be scrollable.');
|
||||
|
||||
clickOn('disable');
|
||||
await body.sendKeys(Key.ARROW_RIGHT);
|
||||
await body.sendKeys(Key.ARROW_RIGHT);
|
||||
await body.sendKeys(Key.ARROW_RIGHT);
|
||||
expect((await getScrollPosition()).x)
|
||||
.toBeGreaterThan(100, 'Expected the page to be scrollable again.');
|
||||
|
||||
screenshot();
|
||||
done();
|
||||
});
|
||||
|
||||
it('should not be able to scroll the page after reaching the end of an element along the y axis',
|
||||
async (done) => {
|
||||
const scroller = element(by.id('scroller'));
|
||||
|
||||
browser.executeScript(`document.getElementById('scroller').scrollTop = 200;`);
|
||||
scrollPage(0, 100);
|
||||
expect((await getScrollPosition()).y).toBe(100, 'Expected the page to be scrollable.');
|
||||
|
||||
clickOn('enable');
|
||||
scroller.sendKeys(Key.ARROW_DOWN);
|
||||
scroller.sendKeys(Key.ARROW_DOWN);
|
||||
scroller.sendKeys(Key.ARROW_DOWN);
|
||||
expect((await getScrollPosition()).y).toBe(100, 'Expected the page not to have scrolled.');
|
||||
|
||||
screenshot();
|
||||
done();
|
||||
});
|
||||
|
||||
it('should not be able to scroll the page after reaching the end of an element along the x axis',
|
||||
async (done) => {
|
||||
const scroller = element(by.id('scroller'));
|
||||
|
||||
browser.executeScript(`document.getElementById('scroller').scrollLeft = 200;`);
|
||||
scrollPage(100, 0);
|
||||
expect((await getScrollPosition()).x).toBe(100, 'Expected the page to be scrollable.');
|
||||
|
||||
clickOn('enable');
|
||||
scroller.sendKeys(Key.ARROW_RIGHT);
|
||||
scroller.sendKeys(Key.ARROW_RIGHT);
|
||||
scroller.sendKeys(Key.ARROW_RIGHT);
|
||||
expect((await getScrollPosition()).x).toBe(100, 'Expected the page not to have scrolled.');
|
||||
|
||||
screenshot();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
// Clicks on a button programmatically. Note that we can't use Protractor's `.click`, because
|
||||
// it performs a real click, which will scroll the button into view.
|
||||
function clickOn(id: string) {
|
||||
browser.executeScript(`document.getElementById('${id}').click()`);
|
||||
}
|
||||
|
||||
// Scrolls the page to the specified coordinates.
|
||||
function scrollPage(x: number, y: number) {
|
||||
return browser.executeScript(`window.scrollTo(${x}, ${y});`);
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"inlineSources": true,
|
||||
"lib": ["es2015"],
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"noEmitOnError": true,
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ export function expectFocusOn(element: FinderResult, expected = true): void {
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that an element has a certan location.
|
||||
* Asserts that an element has a certain location.
|
||||
*/
|
||||
export function expectLocation(element: FinderResult, {x, y}: Point): void {
|
||||
getElement(element).getLocation().then((location: Point) => {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {ElementFinder, by, element, ProtractorBy, browser} from 'protractor';
|
||||
import {Point} from './actions';
|
||||
|
||||
/**
|
||||
* Normalizes either turning a selector into an
|
||||
@@ -15,4 +16,21 @@ export function waitForElement(selector: string) {
|
||||
return browser.isElementPresent(by.css(selector) as ProtractorBy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the current scroll position of the page.
|
||||
*/
|
||||
export async function getScrollPosition(): Promise<Point> {
|
||||
const snippet = `
|
||||
var documentRect = document.documentElement.getBoundingClientRect();
|
||||
var x = -documentRect.left || document.body.scrollLeft || window.scrollX ||
|
||||
document.documentElement.scrollLeft || 0;
|
||||
var y = -documentRect.top || document.body.scrollTop || window.scrollY ||
|
||||
document.documentElement.scrollTop || 0;
|
||||
|
||||
return {x: x, y: y};
|
||||
`;
|
||||
|
||||
return await browser.executeScript<Point>(snippet);
|
||||
}
|
||||
|
||||
export type FinderResult = ElementFinder | string;
|
||||
|
||||
Reference in New Issue
Block a user