text: # Copyright (c) 2012 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.
  import os
  
  from telemetry.page import page as page_module
  from telemetry.page.actions import scroll
  from telemetry.test import tab_test_case
  
  class ScrollActionTest(tab_test_case.TabTestCase):
    def CreateAndNavigateToPageFromUnittestDataDir(
      self, filename, page_attributes):
      unittest_data_dir = os.path.join(os.path.dirname(__file__),
                                       '..', '..', '..', 'unittest_data')
      self._browser.SetHTTPServerDirectories(unittest_data_dir)
      page = page_module.Page(
        self._browser.http_server.UrlOf(filename),
        None, # In this test, we don't need a page set.
        attributes=page_attributes)
  
      self._tab.Navigate(page.url)
      self._tab.WaitForDocumentReadyStateToBeComplete()
  
      return page
  
    def testScrollAction(self):
      page = self.CreateAndNavigateToPageFromUnittestDataDir(
          "blank.html",
          page_attributes={"smoothness": {
            "action": "scroll"
            }})
      # Make page bigger than window so it's scrollable.
      self._tab.ExecuteJavaScript("""document.body.style.height =
                                (2 * window.innerHeight + 1) + 'px';""")
  
      self.assertEquals(
          self._tab.EvaluateJavaScript('document.body.scrollTop'), 0)
  
      i = scroll.ScrollAction()
      i.WillRunAction(page, self._tab)
  
      self._tab.ExecuteJavaScript("""
          window.__scrollAction.beginMeasuringHook = function() {
              window.__didBeginMeasuring = true;
          };
          window.__scrollAction.endMeasuringHook = function() {
              window.__didEndMeasuring = true;
          };""")
      i.RunAction(page, self._tab, None)
  
      self.assertTrue(self._tab.EvaluateJavaScript('window.__didBeginMeasuring'))
      self.assertTrue(self._tab.EvaluateJavaScript('window.__didEndMeasuring'))
  
      # Allow for roundoff error in scaled viewport.
      scroll_position = self._tab.EvaluateJavaScript(
          'document.body.scrollTop + window.innerHeight')
      scroll_height = self._tab.EvaluateJavaScript('document.body.scrollHeight')
      difference = scroll_position - scroll_height
      self.assertTrue(abs(difference) <= 1)
  
    def testBoundingClientRect(self):
      self.CreateAndNavigateToPageFromUnittestDataDir('blank.html', {})
      with open(
        os.path.join(os.path.dirname(__file__),
                     'scroll.js')) as f:
        js = f.read()
        self._tab.ExecuteJavaScript(js)
  
      # Verify that the rect returned by getBoundingVisibleRect() in
      # scroll.js is completely contained within the viewport. Scroll
      # events dispatched by the benchmarks use the center of this rect
      # as their location, and this location needs to be within the
      # viewport bounds to correctly decide between main-thread and
      # impl-thread scroll. If the scrollable area were not clipped
      # to the viewport bounds, then the instance used here (the scrollable
      # area being more than twice as tall as the viewport) would
      # result in a scroll location outside of the viewport bounds.
      self._tab.ExecuteJavaScript("""document.body.style.height =
                             (2 * window.innerHeight + 1) + 'px';""")
  
      rect_bottom = int(self._tab.EvaluateJavaScript("""
          __ScrollAction_GetBoundingVisibleRect(document.body).top +
          __ScrollAction_GetBoundingVisibleRect(document.body).height"""))
      rect_right = int(self._tab.EvaluateJavaScript("""
          __ScrollAction_GetBoundingVisibleRect(document.body).left +
          __ScrollAction_GetBoundingVisibleRect(document.body).width"""))
      viewport_width = int(self._tab.EvaluateJavaScript('window.innerWidth'))
      viewport_height = int(self._tab.EvaluateJavaScript('window.innerHeight'))
  
      self.assertTrue(rect_bottom <= viewport_height)
      self.assertTrue(rect_right <= viewport_width)
  