Bug 1534584 Part 2 - Remove legacy_actions from AccessibleCaret tests. r=whimboo
authorTing-Yu Lin <tlin@mozilla.com>
Mon, 25 Mar 2019 20:28:44 +0000
changeset 466026 aad29c67d0ad810a4de5dac7bd8728e5d5b56d36
parent 466025 6d8c85e1f976c8ea68fc501cd144bfa717abe299
child 466027 f9ec1b53fd9f918c471ebda7f898ae33e2cc34e9
push id81388
push useraethanyc@gmail.com
push dateTue, 26 Mar 2019 00:44:12 +0000
treeherderautoland@aad29c67d0ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswhimboo
bugs1534584
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1534584 Part 2 - Remove legacy_actions from AccessibleCaret tests. r=whimboo - Re-implement flick() and send_keys() required by AccessibleCaret tests. - Delete skip_if_not_rotatable() because it's unused. - Change the dragging distance from 50px to 40px in test_carets_not_jump_when_dragging_to_editable_content_boundary and test_caret_not_jump_to_front_when_dragging_up_to_editable_content_boundary to avoid MoveTargetOutOfBoundsException. Changing the distance doesn't alter the meaning of the tests. Differential Revision: https://phabricator.services.mozilla.com/D24311
layout/base/tests/marionette/selection.py
layout/base/tests/marionette/test_accessiblecaret_cursor_mode.py
layout/base/tests/marionette/test_accessiblecaret_selection_mode.py
--- a/layout/base/tests/marionette/selection.py
+++ b/layout/base/tests/marionette/selection.py
@@ -1,15 +1,75 @@
 # -*- coding: utf-8 -*-
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from __future__ import absolute_import
 
+from marionette_driver.marionette import Actions
+
+
+class CaretActions(Actions):
+    def __init__(self, marionette):
+        super(CaretActions, self).__init__(marionette)
+        self._reset_action_chain()
+
+    def _reset_action_chain(self):
+        self.mouse_chain = self.sequence("pointer", "pointer_id", {"pointerType": "mouse"})
+        self.key_chain = self.sequence("key", "keyboard_id")
+
+    def flick(self, element, x1, y1, x2, y2, duration=200):
+        """Perform a flick gesture on the target element.
+
+        :param element: The element to perform the flick gesture on.
+        :param x1: Starting x-coordinate of flick, relative to the top left
+                   corner of the element.
+        :param y1: Starting y-coordinate of flick, relative to the top left
+                   corner of the element.
+        :param x2: Ending x-coordinate of flick, relative to the top left
+                   corner of the element.
+        :param y2: Ending y-coordinate of flick, relative to the top left
+                   corner of the element.
+
+        """
+        rect = element.rect
+        el_x, el_y = rect['x'], rect['y']
+
+        # Add element's (x, y) to make the coordinate relative to the viewport.
+        from_x, from_y = int(el_x + x1), int(el_y + y1)
+        to_x, to_y = int(el_x + x2), int(el_y + y2)
+
+        self.mouse_chain.pointer_move(from_x, from_y) \
+                        .pointer_down() \
+                        .pointer_move(to_x, to_y, duration=duration) \
+                        .pointer_up()
+        return self
+
+    def send_keys(self, keys):
+        """Perform a keyDown and keyUp action for each character in `keys`.
+
+        :param keys: String of keys to perform key actions with.
+
+        """
+        self.key_chain.send_keys(keys)
+        return self
+
+    def perform(self):
+        """Perform the action chain built so far to the server side for execution
+        and clears the current chain of actions.
+
+        Warning: This method performs all the mouse actions before all the key
+        actions!
+
+        """
+        self.mouse_chain.perform()
+        self.key_chain.perform()
+        self._reset_action_chain()
+
 
 class SelectionManager(object):
     '''Interface for manipulating the selection and carets of the element.
 
     We call the blinking cursor (nsCaret) as cursor, and call AccessibleCaret as
     caret for short.
 
     Simple usage example:
--- a/layout/base/tests/marionette/test_accessiblecaret_cursor_mode.py
+++ b/layout/base/tests/marionette/test_accessiblecaret_cursor_mode.py
@@ -6,20 +6,20 @@
 import string
 import sys
 import os
 
 # Add this directory to the import path.
 sys.path.append(os.path.dirname(__file__))
 
 from selection import (
+    CaretActions,
     SelectionManager,
 )
 from marionette_driver.by import By
-from marionette_driver.legacy_actions import Actions
 from marionette_harness.marionette_test import (
     MarionetteTestCase,
     parameterized,
 )
 
 
 class AccessibleCaretCursorModeTestCase(MarionetteTestCase):
     '''Test cases for AccessibleCaret under cursor mode.
@@ -43,17 +43,21 @@ class AccessibleCaretCursorModeTestCase(
         super(AccessibleCaretCursorModeTestCase, self).setUp()
         self.caret_tested_pref = 'layout.accessiblecaret.enabled'
         self.hide_carets_for_mouse = 'layout.accessiblecaret.hide_carets_for_mouse_input'
         self.prefs = {
             self.caret_tested_pref: True,
             self.hide_carets_for_mouse: False,
         }
         self.marionette.set_prefs(self.prefs)
-        self.actions = Actions(self.marionette)
+        self.actions = CaretActions(self.marionette)
+
+    def tearDown(self):
+        self.marionette.actions.release()
+        super(AccessibleCaretCursorModeTestCase, self).tearDown()
 
     def open_test_html(self, test_html):
         self.marionette.navigate(self.marionette.absolute_url(test_html))
 
     @parameterized(_input_id, el_id=_input_id)
     @parameterized(_textarea_id, el_id=_textarea_id)
     @parameterized(_contenteditable_id, el_id=_contenteditable_id)
     def test_move_cursor_to_the_right_by_one_character(self, el_id):
@@ -74,17 +78,17 @@ class AccessibleCaretCursorModeTestCase(
 
         # Tap the front of the input to make first caret appear.
         el.tap(cursor0_x, cursor0_y)
 
         # Move first caret.
         self.actions.flick(el, first_caret0_x, first_caret0_y,
                            first_caret1_x, first_caret1_y).perform()
 
-        self.actions.key_down(content_to_add).key_up(content_to_add).perform()
+        self.actions.send_keys(content_to_add).perform()
         self.assertEqual(target_content, sel.content)
 
     @parameterized(_input_id, el_id=_input_id)
     @parameterized(_textarea_id, el_id=_textarea_id)
     @parameterized(_contenteditable_id, el_id=_contenteditable_id)
     def test_move_cursor_to_end_by_dragging_caret_to_bottom_right_corner(self, el_id):
         self.open_test_html(self._cursor_html)
         el = self.marionette.find_element(By.ID, el_id)
@@ -97,17 +101,17 @@ class AccessibleCaretCursorModeTestCase(
         sel.move_cursor_to_front()
         el.tap(*sel.cursor_location())
 
         # Move first caret to the bottom-right corner of the element.
         src_x, src_y = sel.first_caret_location()
         dest_x, dest_y = el.rect['width'], el.rect['height']
         self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform()
 
-        self.actions.key_down(content_to_add).key_up(content_to_add).perform()
+        self.actions.send_keys(content_to_add).perform()
         self.assertEqual(target_content, sel.content)
 
     @parameterized(_input_id, el_id=_input_id)
     @parameterized(_textarea_id, el_id=_textarea_id)
     @parameterized(_contenteditable_id, el_id=_contenteditable_id)
     def test_move_cursor_to_front_by_dragging_caret_to_front(self, el_id):
         self.open_test_html(self._cursor_html)
         el = self.marionette.find_element(By.ID, el_id)
@@ -127,17 +131,17 @@ class AccessibleCaretCursorModeTestCase(
         sel.move_cursor_to_end()
         sel.move_cursor_by_offset(1, backward=True)
         el.tap(*sel.cursor_location())
         src_x, src_y = sel.first_caret_location()
 
         # Move first caret to the front of the input box.
         self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform()
 
-        self.actions.key_down(content_to_add).key_up(content_to_add).perform()
+        self.actions.send_keys(content_to_add).perform()
         self.assertEqual(target_content, sel.content)
 
     def test_caret_not_appear_when_typing_in_scrollable_content(self):
         self.open_test_html(self._cursor_html)
         el = self.marionette.find_element(By.ID, self._input_id)
         sel = SelectionManager(el)
         content_to_add = '!'
         non_target_content = content_to_add + sel.content + string.ascii_letters
@@ -176,17 +180,17 @@ class AccessibleCaretCursorModeTestCase(
         # on the Y-axis.
         el.tap()
         sel.move_cursor_to_front()
         el.tap(*sel.cursor_location())
         x, y = sel.first_caret_location()
 
         # Drag the caret down by 50px, and insert '!'.
         self.actions.flick(el, x, y, x, y + 50).perform()
-        self.actions.key_down(content_to_add).key_up(content_to_add).perform()
+        self.actions.send_keys(content_to_add).perform()
         self.assertNotEqual(non_target_content, sel.content)
 
     @parameterized(_input_id, el_id=_input_id)
     @parameterized(_input_padding_id, el_id=_input_padding_id)
     @parameterized(_textarea_one_line_id, el_id=_textarea_one_line_id)
     @parameterized(_contenteditable_id, el_id=_contenteditable_id)
     def test_caret_not_jump_to_front_when_dragging_up_to_editable_content_boundary(self, el_id):
         self.open_test_html(self._cursor_html)
@@ -198,19 +202,19 @@ class AccessibleCaretCursorModeTestCase(
         # Goal: the cursor position is not changed after dragging the caret down
         # on the Y-axis.
         el.tap()
         sel.move_cursor_to_end()
         sel.move_cursor_by_offset(1, backward=True)
         el.tap(*sel.cursor_location())
         x, y = sel.first_caret_location()
 
-        # Drag the caret up by 50px, and insert '!'.
-        self.actions.flick(el, x, y, x, y - 50).perform()
-        self.actions.key_down(content_to_add).key_up(content_to_add).perform()
+        # Drag the caret up by 40px, and insert '!'.
+        self.actions.flick(el, x, y, x, y - 40).perform()
+        self.actions.send_keys(content_to_add).perform()
         self.assertNotEqual(non_target_content, sel.content)
 
     def test_drag_caret_from_front_to_end_across_columns(self):
         self.open_test_html('layout/test_carets_columns.html')
         el = self.marionette.find_element(By.ID, 'columns-inner')
         sel = SelectionManager(el)
         content_to_add = '!'
         target_content = sel.content + content_to_add
@@ -226,17 +230,17 @@ class AccessibleCaretCursorModeTestCase(
         sel.move_cursor_to_front()
         el.tap(*sel.cursor_location())
         src_x, src_y = sel.first_caret_location()
         dest_x, dest_y = el.rect['width'], el.rect['height']
 
         # Drag the first caret to the bottom-right corner of the element.
         self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform()
 
-        self.actions.key_down(content_to_add).key_up(content_to_add).perform()
+        self.actions.send_keys(content_to_add).perform()
         self.assertEqual(target_content, sel.content)
 
     def test_move_cursor_to_front_by_dragging_caret_to_front_br_element(self):
         self.open_test_html(self._cursor_html)
         el = self.marionette.find_element(By.ID, self._contenteditable_id)
         sel = SelectionManager(el)
         content_to_add_1 = '!'
         content_to_add_2 = '\n\n'
@@ -260,10 +264,10 @@ class AccessibleCaretCursorModeTestCase(
         sel.move_cursor_to_end()
         sel.move_cursor_by_offset(1, backward=True)
         el.tap(*sel.cursor_location())
         src_x, src_y = sel.first_caret_location()
 
         # Move first caret to the front of the input box.
         self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform()
 
-        self.actions.key_down(content_to_add_1).key_up(content_to_add_1).perform()
+        self.actions.send_keys(content_to_add_1).perform()
         self.assertEqual(target_content, sel.content)
--- a/layout/base/tests/marionette/test_accessiblecaret_selection_mode.py
+++ b/layout/base/tests/marionette/test_accessiblecaret_selection_mode.py
@@ -6,35 +6,26 @@
 import re
 import sys
 import os
 
 # Add this directory to the import path.
 sys.path.append(os.path.dirname(__file__))
 
 from selection import (
+    CaretActions,
     SelectionManager,
 )
 from marionette_driver.by import By
-from marionette_driver.legacy_actions import Actions
 from marionette_harness.marionette_test import (
     MarionetteTestCase,
     SkipTest,
     parameterized
 )
 
-
-def skip_if_not_rotatable(target):
-    def wrapper(self, *args, **kwargs):
-        if not self.marionette.session_capabilities.get('rotatable'):
-            raise SkipTest('skipping due to device not rotatable')
-        return target(self, *args, **kwargs)
-    return wrapper
-
-
 class AccessibleCaretSelectionModeTestCase(MarionetteTestCase):
     '''Test cases for AccessibleCaret under selection mode.'''
     # Element IDs.
     _input_id = 'input'
     _input_padding_id = 'input-padding'
     _input_size_id = 'input-size'
     _textarea_id = 'textarea'
     _textarea2_id = 'textarea2'
@@ -59,17 +50,21 @@ class AccessibleCaretSelectionModeTestCa
         # Code to execute before every test is running.
         super(AccessibleCaretSelectionModeTestCase, self).setUp()
         self.carets_tested_pref = 'layout.accessiblecaret.enabled'
         self.prefs = {
             'layout.word_select.eat_space_to_next_word': False,
             self.carets_tested_pref: True,
         }
         self.marionette.set_prefs(self.prefs)
-        self.actions = Actions(self.marionette)
+        self.actions = CaretActions(self.marionette)
+
+    def tearDown(self):
+        self.marionette.actions.release()
+        super(AccessibleCaretSelectionModeTestCase, self).tearDown()
 
     def open_test_html(self, test_html):
         self.marionette.navigate(self.marionette.absolute_url(test_html))
 
     def word_offset(self, text, ordinal):
         'Get the character offset of the ordinal-th word in text.'
         tokens = re.split(r'(\S+)', text)         # both words and spaces
         spaces = tokens[0::2]                     # collect spaces at odd indices
@@ -587,18 +582,18 @@ class AccessibleCaretSelectionModeTestCa
 
         # Goal: the selection is not changed after dragging the caret on the
         # Y-axis.
         target_content = words[1]
 
         self.long_press_on_word(el, 1)
         (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location()
 
-        # Drag the first caret up by 50px.
-        self.actions.flick(el, caret1_x, caret1_y, caret1_x, caret1_y - 50).perform()
+        # Drag the first caret up by 40px.
+        self.actions.flick(el, caret1_x, caret1_y, caret1_x, caret1_y - 40).perform()
         self.assertEqual(target_content, sel.selected_content)
 
         # Drag the second caret down by 50px.
         self.actions.flick(el, caret2_x, caret2_y, caret2_x, caret2_y + 50).perform()
         self.assertEqual(target_content, sel.selected_content)
 
     def test_carets_should_not_appear_when_long_pressing_svg_shapes(self):
         self.open_test_html(self._svg_shapes_html)