// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. /** * @suppress {checkTypes} * * @fileoverview * Browser test for the scenario below: * 1. Resize the client window to various sizes and verify the existence of * horizontal and/or vertical scroll-bars. * 2. TODO(jamiewalch): Connect to a host and toggle various combinations of * scale and resize; repeat test 1. * 3. TODO(jamiewalch): Disconnect; repeat test 1. */ 'use strict'; /** @constructor */ browserTest.Scrollbars = function() { this.scroller_ = document.getElementById('scroller'); this.SCROLLBAR_WIDTH_ = 16; this.BORDER_WIDTH_ = 1; // The top border is already accounted for by getBoundingClientRect, but // the bottom border is not. var marker = document.getElementById('bottom-marker'); this.CONTENT_HEIGHT_ = marker.getBoundingClientRect().top + this.BORDER_WIDTH_; // The width of the content is computed from the width of a
(690px) // plus the margin of the "inset" class (20px). There's no easy way to get // that without hard-coding it. In fact, this is a bit simplistic because // the horizontal space required by the header depends on the length of the // product name. this.CONTENT_WIDTH_ = 690 + 20 + 2 * this.BORDER_WIDTH_; }; browserTest.Scrollbars.prototype.run = function(data) { if (!base.isAppsV2()) { browserTest.fail( 'Scroll-bar testing requires resizing the app window, which can ' + 'only be done programmatically in apps v2.'); } // Verify that scrollbars are added/removed correctly on the home screen. this.verifyHomeScreenScrollbars_() .then(browserTest.pass, browserTest.fail); }; /** * Verify the test cases for the home-screen. * @return {Promise} */ browserTest.Scrollbars.prototype.verifyHomeScreenScrollbars_ = function() { // Note that, due to crbug.com/240772, if the window already has // scroll-bars, they will not be removed if the window size is // increased by less than the scroll-bar width. We work around that // when connected to a host because we know how big the content is // (in fact, testing this work-around is the main motivation for // writing this test), but it's not worth it for the home screen, // so make the window large not to require scrollbars before each test. var tooWide = this.CONTENT_WIDTH_ + 100; var tooTall = this.CONTENT_HEIGHT_ + 100; var removeScrollbars = this.resize_.bind(this, tooWide, tooTall); // Verify there are no scroll-bars if the window is as big as it needs // to be. return removeScrollbars() .then(this.resizeAndVerifyScroll_( this.CONTENT_WIDTH_, this.CONTENT_HEIGHT_, false, false)) // Verify there is a vertical scroll-bar if the window is shorter than it // needs to be. .then(removeScrollbars) .then(this.resizeAndVerifyScroll_.bind( this, this.CONTENT_WIDTH_ + this.SCROLLBAR_WIDTH_, this.CONTENT_HEIGHT_ - 1, false, true)) // Verify there is a horizontal scroll-bar if the window is narrow than it // needs to be. .then(removeScrollbars) .then(this.resizeAndVerifyScroll_.bind( this, this.CONTENT_WIDTH_ - 1, this.CONTENT_HEIGHT_ + this.SCROLLBAR_WIDTH_, true, false)) // Verify there are both horizontal and vertical scroll-bars, even if one // is only needed as a result of the space occupied by the other. .then(removeScrollbars) .then(this.resizeAndVerifyScroll_.bind( this, this.CONTENT_WIDTH_, this.CONTENT_HEIGHT_ - 1, true, true)) .then(removeScrollbars) .then(this.resizeAndVerifyScroll_.bind( this, this.CONTENT_WIDTH_ - 1, this.CONTENT_HEIGHT_, true, true)) // Verify there are both horizontal and vertical scroll-bars, if both are // required independently. .then(removeScrollbars) .then(this.resizeAndVerifyScroll_.bind( this, this.CONTENT_WIDTH_ - 1, this.CONTENT_HEIGHT_ - 1, true, true)); }; /** * Returns whether or not horizontal and vertical scroll-bars are expected * and visible. To do this, it performs a hit-test close to the right and * bottom edges of the scroller
; since the content of that
fills * it completely, the hit-test will return the content unless there is a * scroll-bar visible on the corresponding edge, in which case it will return * the scroller
itself. * * @return {{horizontal: boolean, vertical:boolean}} * @private */ browserTest.Scrollbars.prototype.getScrollbarState_ = function() { var rect = this.scroller_.getBoundingClientRect(); var rightElement = document.elementFromPoint( rect.right - 1, (rect.top + rect.bottom) / 2); var bottomElement = document.elementFromPoint( (rect.left + rect.right) / 2, rect.bottom - 1); return { horizontal: bottomElement === this.scroller_, vertical: rightElement === this.scroller_ }; }; /** * Returns a promise that resolves if the scroll-bar state is as expected, or * rejects otherwise. * * @param {boolean} horizontalExpected * @param {boolean} verticalExpected * @return {Promise} * @private */ browserTest.Scrollbars.prototype.verifyScrollbarState_ = function(horizontalExpected, verticalExpected) { var scrollbarState = this.getScrollbarState_(); if (scrollbarState.horizontal && !horizontalExpected) { return Promise.reject(new Error( 'Horizontal scrollbar present but not expected.')); } else if (!scrollbarState.horizontal && horizontalExpected) { return Promise.reject(new Error( 'Horizontal scrollbar expected but not present.')); } else if (scrollbarState.vertical && !verticalExpected) { return Promise.reject(new Error( 'Vertical scrollbar present but not expected.')); } else if (!scrollbarState.vertical && verticalExpected) { return Promise.reject(new Error( 'Vertical scrollbar expected but not present.')); } return Promise.resolve(); }; /** * @param {number} width * @param {number} height * @return {Promise} A promise that will be fulfilled when the window has * been resized and it's safe to test scroll-bar visibility. * @private */ browserTest.Scrollbars.prototype.resize_ = function(width, height) { var win = chrome.app.window.current(); win.outerBounds.width = width; win.outerBounds.height = height; // Chrome takes a while to update the scroll-bars, so don't resolve // immediately. Waiting for the onBoundsChanged event would be cleaner, // but isn't reliable. return base.Promise.sleep(500); }; /** * @param {number} width * @param {number} height * @param {boolean} horizontalExpected * @param {boolean} verticalExpected * @return {Promise} A promise that will be fulfilled when the window has * been resized and it's safe to test scroll-bar visibility. * @private */ browserTest.Scrollbars.prototype.resizeAndVerifyScroll_ = function(width, height, horizontalExpected, verticalExpected) { return this.resize_(width, height).then( this.verifyScrollbarState_.bind( this, horizontalExpected, verticalExpected)); };