1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5/** 6 * @suppress {checkTypes} 7 * 8 * @fileoverview 9 * Browser test for the scenario below: 10 * 1. Resize the client window to various sizes and verify the existence of 11 * horizontal and/or vertical scroll-bars. 12 * 2. TODO(jamiewalch): Connect to a host and toggle various combinations of 13 * scale and resize; repeat test 1. 14 * 3. TODO(jamiewalch): Disconnect; repeat test 1. 15 */ 16 17'use strict'; 18 19/** @constructor */ 20browserTest.Scrollbars = function() { 21 this.scroller_ = document.getElementById('scroller'); 22 this.SCROLLBAR_WIDTH_ = 16; 23 this.BORDER_WIDTH_ = 1; 24 25 // The top border is already accounted for by getBoundingClientRect, but 26 // the bottom border is not. 27 var marker = document.getElementById('bottom-marker'); 28 this.CONTENT_HEIGHT_ = 29 marker.getBoundingClientRect().top + this.BORDER_WIDTH_; 30 31 // The width of the content is computed from the width of a <section> (690px) 32 // plus the margin of the "inset" class (20px). There's no easy way to get 33 // that without hard-coding it. In fact, this is a bit simplistic because 34 // the horizontal space required by the header depends on the length of the 35 // product name. 36 this.CONTENT_WIDTH_ = 690 + 20 + 2 * this.BORDER_WIDTH_; 37 38}; 39 40 41browserTest.Scrollbars.prototype.run = function(data) { 42 if (!base.isAppsV2()) { 43 browserTest.fail( 44 'Scroll-bar testing requires resizing the app window, which can ' + 45 'only be done programmatically in apps v2.'); 46 } 47 48 // Verify that scrollbars are added/removed correctly on the home screen. 49 this.verifyHomeScreenScrollbars_() 50 .then(browserTest.pass, browserTest.fail); 51}; 52 53 54/** 55 * Verify the test cases for the home-screen. 56 */ 57browserTest.Scrollbars.prototype.verifyHomeScreenScrollbars_ = function() { 58 // Note that, due to crbug.com/240772, if the window already has 59 // scroll-bars, they will not be removed if the window size is 60 // increased by less than the scroll-bar width. We work around that 61 // when connected to a host because we know how big the content is 62 // (in fact, testing this work-around is the main motivation for 63 // writing this test), but it's not worth it for the home screen, 64 // so make the window large not to require scrollbars before each test. 65 var tooWide = this.CONTENT_WIDTH_ + 100; 66 var tooTall = this.CONTENT_HEIGHT_ + 100; 67 var removeScrollbars = this.resize_.bind(this, tooWide, tooTall); 68 69 // Verify there are no scroll-bars if the window is as big as it needs 70 // to be. 71 return removeScrollbars() 72 .then(this.resizeAndVerifyScroll_( 73 this.CONTENT_WIDTH_, 74 this.CONTENT_HEIGHT_, 75 false, false)) 76 77 // Verify there is a vertical scroll-bar if the window is shorter than it 78 // needs to be. 79 .then(removeScrollbars) 80 .then(this.resizeAndVerifyScroll_.bind( 81 this, 82 this.CONTENT_WIDTH_ + this.SCROLLBAR_WIDTH_, 83 this.CONTENT_HEIGHT_ - 1, 84 false, true)) 85 86 // Verify there is a horizontal scroll-bar if the window is narrow than it 87 // needs to be. 88 .then(removeScrollbars) 89 .then(this.resizeAndVerifyScroll_.bind( 90 this, 91 this.CONTENT_WIDTH_ - 1, 92 this.CONTENT_HEIGHT_ + this.SCROLLBAR_WIDTH_, 93 true, false)) 94 95 // Verify there are both horizontal and vertical scroll-bars, even if one 96 // is only needed as a result of the space occupied by the other. 97 .then(removeScrollbars) 98 .then(this.resizeAndVerifyScroll_.bind( 99 this, 100 this.CONTENT_WIDTH_, 101 this.CONTENT_HEIGHT_ - 1, 102 true, true)) 103 .then(removeScrollbars) 104 .then(this.resizeAndVerifyScroll_.bind( 105 this, 106 this.CONTENT_WIDTH_ - 1, 107 this.CONTENT_HEIGHT_, 108 true, true)) 109 110 // Verify there are both horizontal and vertical scroll-bars, if both are 111 // required independently. 112 .then(removeScrollbars) 113 .then(this.resizeAndVerifyScroll_.bind( 114 this, 115 this.CONTENT_WIDTH_ - 1, 116 this.CONTENT_HEIGHT_ - 1, 117 true, true)); 118}; 119 120 121/** 122 * Returns whether or not horizontal and vertical scroll-bars are expected 123 * and visible. To do this, it performs a hit-test close to the right and 124 * bottom edges of the scroller <div>; since the content of that <div> fills 125 * it completely, the hit-test will return the content unless there is a 126 * scroll-bar visible on the corresponding edge, in which case it will return 127 * the scroller <div> itself. 128 * 129 * @private 130 */ 131browserTest.Scrollbars.prototype.getScrollbarState_ = function() { 132 var rect = this.scroller_.getBoundingClientRect(); 133 var rightElement = document.elementFromPoint( 134 rect.right - 1, (rect.top + rect.bottom) / 2); 135 var bottomElement = document.elementFromPoint( 136 (rect.left + rect.right) / 2, rect.bottom - 1); 137 return { 138 horizontal: bottomElement === this.scroller_, 139 vertical: rightElement === this.scroller_ 140 }; 141}; 142 143 144/** 145 * Returns a promise that resolves if the scroll-bar state is as expected, or 146 * rejects otherwise. 147 * 148 * @private 149 */ 150browserTest.Scrollbars.prototype.verifyScrollbarState_ = 151 function(horizontalExpected, verticalExpected) { 152 var scrollbarState = this.getScrollbarState_(); 153 if (scrollbarState.horizontal && !horizontalExpected) { 154 return Promise.reject(new Error( 155 'Horizontal scrollbar present but not expected.')); 156 } else if (!scrollbarState.horizontal && horizontalExpected) { 157 return Promise.reject(new Error( 158 'Horizontal scrollbar expected but not present.')); 159 } else if (scrollbarState.vertical && !verticalExpected) { 160 return Promise.reject(new Error( 161 'Vertical scrollbar present but not expected.')); 162 } else if (!scrollbarState.vertical && verticalExpected) { 163 return Promise.reject(new Error( 164 'Vertical scrollbar expected but not present.')); 165 } 166 return Promise.resolve(); 167}; 168 169 170/** 171 * @private 172 * @return {Promise} A promise that will be fulfilled when the window has 173 * been resized and it's safe to test scroll-bar visibility. 174 */ 175browserTest.Scrollbars.prototype.resize_ = function(width, height) { 176 var win = chrome.app.window.current(); 177 win.resizeTo(width, height); 178 // Chrome takes a while to update the scroll-bars, so don't resolve 179 // immediately. Waiting for the onBoundsChanged event would be cleaner, 180 // but isn't reliable. 181 return base.Promise.sleep(500); 182}; 183 184 185/** 186 * @private 187 * @return {Promise} A promise that will be fulfilled when the window has 188 * been resized and it's safe to test scroll-bar visibility. 189 */ 190browserTest.Scrollbars.prototype.resizeAndVerifyScroll_ = 191 function(width, height, horizontalExpected, verticalExpected) { 192 return this.resize_(width, height).then( 193 this.verifyScrollbarState_.bind( 194 this, horizontalExpected, verticalExpected)); 195}; 196