# Copyright 2020 The Cobalt Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Tests events for an extended sequence of pointer moves and clicks."""

# This test generates an extended sequence of pointer move and click events,
# and verifies the corresponding sequence of pointer, mouse, and click events
# dispatched to the HTML elements. The test includes use of pointer capture and
# use of preventDefault() and stopPropagation() on the events, as well as event
# bubbling.

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import _env  # pylint: disable=unused-import,g-bad-import-order

import traceback

from cobalt.black_box_tests import black_box_tests
from cobalt.black_box_tests.threaded_web_server import ThreadedWebServer
from selenium.webdriver.common.action_chains import ActionChains

# Time to sleep after a mouse move to give the device time to process it and
# to avoid collapsing with subsequent move events.
_SLEEP_AFTER_MOVE_TIME = 0.5


def find_element_by_id(runner, id_selector):
  return runner.webdriver.find_elements_by_css_selector('#' + id_selector)[0]


class PointerTest(black_box_tests.BlackBoxTestCase):
  """Tests pointer and mouse event."""

  def test_simple(self):

    try:
      with ThreadedWebServer(
          binding_address=self.GetBindingAddress()) as server:
        url = server.GetURL(file_name='testdata/pointer_test.html')

        with self.CreateCobaltRunner(url=url) as runner:
          print('JS Test Setup WaitForJSTestsSetup')
          runner.WaitForJSTestsSetup()
          print('JS Test Setup')
          self.assertTrue(runner.webdriver)

          top_one = find_element_by_id(runner, 'top_one')
          top_two = find_element_by_id(runner, 'top_two')
          top_three = find_element_by_id(runner, 'top_three')
          top_four = find_element_by_id(runner, 'top_four')
          top_five = find_element_by_id(runner, 'top_five')
          top_six = find_element_by_id(runner, 'top_six')

          bottom_one = find_element_by_id(runner, 'bottom_one')
          bottom_two = find_element_by_id(runner, 'bottom_two')
          bottom_three = find_element_by_id(runner, 'bottom_three')
          bottom_four = find_element_by_id(runner, 'bottom_four')
          bottom_five = find_element_by_id(runner, 'bottom_five')
          bottom_six = find_element_by_id(runner, 'bottom_six')

          # Perform mouse actions with ActionChains.
          #   https://www.selenium.dev/selenium/docs/api/py/webdriver/selenium.webdriver.common.action_chains.html#module-selenium.webdriver.common.action_chains
          actions = ActionChains(runner.webdriver)
          actions.move_to_element(top_one).pause(_SLEEP_AFTER_MOVE_TIME)
          actions.move_to_element(top_two).pause(_SLEEP_AFTER_MOVE_TIME)
          actions.move_to_element_with_offset(top_two, 10,
                                              10).pause(_SLEEP_AFTER_MOVE_TIME)
          actions.move_to_element_with_offset(top_two, 0,
                                              0).pause(_SLEEP_AFTER_MOVE_TIME)
          actions.move_to_element_with_offset(top_two, -10,
                                              0).pause(_SLEEP_AFTER_MOVE_TIME)
          actions.click(top_three)
          actions.click_and_hold(top_four)
          actions.release(top_five)
          actions.move_to_element(top_six).pause(_SLEEP_AFTER_MOVE_TIME)
          actions.move_to_element(bottom_six).pause(_SLEEP_AFTER_MOVE_TIME)
          actions.click(bottom_five)
          actions.click_and_hold(bottom_four)
          actions.release(bottom_three)
          actions.move_to_element(bottom_two).pause(_SLEEP_AFTER_MOVE_TIME)
          actions.move_to_element(bottom_one).pause(_SLEEP_AFTER_MOVE_TIME)
          actions.perform()

          find_element_by_id(runner, 'end').click()
          self.assertTrue(runner.JSTestsSucceeded())
    except:  # pylint: disable=bare-except
      traceback.print_exc()
      # Consider an exception being thrown as a test failure.
      self.assertTrue(False)
    finally:
      print('Cleaning up.')
