tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_accessiblecaret_cursor_mode.py (11659B)


      1 # -*- coding: utf-8 -*-
      2 # This Source Code Form is subject to the terms of the Mozilla Public
      3 # License, v. 2.0. If a copy of the MPL was not distributed with this
      4 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
      5 
      6 import string
      7 import sys
      8 import os
      9 
     10 # Add this directory to the import path.
     11 sys.path.append(os.path.dirname(__file__))
     12 
     13 from selection import (
     14    CaretActions,
     15    SelectionManager,
     16 )
     17 from marionette_driver.by import By
     18 from marionette_harness.marionette_test import (
     19    MarionetteTestCase,
     20    parameterized,
     21 )
     22 
     23 
     24 class AccessibleCaretCursorModeTestCase(MarionetteTestCase):
     25    """Test cases for AccessibleCaret under cursor mode.
     26 
     27    We call the blinking cursor (nsCaret) as cursor, and call AccessibleCaret as
     28    caret for short.
     29 
     30    """
     31 
     32    # Element IDs.
     33    _input_id = "input"
     34    _input_padding_id = "input-padding"
     35    _textarea_id = "textarea"
     36    _textarea_one_line_id = "textarea-one-line"
     37    _contenteditable_id = "contenteditable"
     38 
     39    # Test html files.
     40    _cursor_html = "layout/test_carets_cursor.html"
     41 
     42    def setUp(self):
     43        # Code to execute before every test is running.
     44        super(AccessibleCaretCursorModeTestCase, self).setUp()
     45        self.caret_tested_pref = "layout.accessiblecaret.enabled"
     46        self.hide_carets_for_mouse = (
     47            "layout.accessiblecaret.hide_carets_for_mouse_input"
     48        )
     49        self.prefs = {
     50            self.caret_tested_pref: True,
     51            self.hide_carets_for_mouse: False,
     52            # To disable transition, or the caret may not be the desired
     53            # location yet, we cannot press a caret successfully.
     54            "layout.accessiblecaret.transition-duration": "0.0",
     55            # Enabled hapticfeedback on all platforms. The tests shouldn't crash
     56            # on platforms without hapticfeedback support.
     57            "layout.accessiblecaret.hapticfeedback": True,
     58        }
     59        self.marionette.set_prefs(self.prefs)
     60        self.actions = CaretActions(self.marionette)
     61 
     62    def tearDown(self):
     63        self.marionette.actions.release()
     64        super(AccessibleCaretCursorModeTestCase, self).tearDown()
     65 
     66    def open_test_html(self, test_html):
     67        self.marionette.navigate(self.marionette.absolute_url(test_html))
     68 
     69    @parameterized(_input_id, el_id=_input_id)
     70    @parameterized(_textarea_id, el_id=_textarea_id)
     71    @parameterized(_contenteditable_id, el_id=_contenteditable_id)
     72    def test_move_cursor_to_the_right_by_one_character(self, el_id):
     73        self.open_test_html(self._cursor_html)
     74        el = self.marionette.find_element(By.ID, el_id)
     75        sel = SelectionManager(el)
     76        content_to_add = "!"
     77        target_content = sel.content
     78        target_content = target_content[:1] + content_to_add + target_content[1:]
     79 
     80        # Get first caret (x, y) at position 1 and 2.
     81        self.actions.click(element=el).perform()
     82        sel.move_cursor_to_front()
     83        cursor0_x, cursor0_y = sel.cursor_location()
     84        first_caret0_x, first_caret0_y = sel.first_caret_location()
     85        sel.move_cursor_by_offset(1)
     86        first_caret1_x, first_caret1_y = sel.first_caret_location()
     87 
     88        # Click the front of the input to make first caret appear.
     89        self.actions.move(el, cursor0_x, cursor0_y).click().perform()
     90 
     91        # Move first caret.
     92        self.actions.flick(
     93            el, first_caret0_x, first_caret0_y, first_caret1_x, first_caret1_y
     94        ).perform()
     95 
     96        self.actions.send_keys(content_to_add).perform()
     97        self.assertEqual(target_content, sel.content)
     98 
     99    @parameterized(_input_id, el_id=_input_id)
    100    @parameterized(_textarea_id, el_id=_textarea_id)
    101    @parameterized(_contenteditable_id, el_id=_contenteditable_id)
    102    def test_move_cursor_to_end_by_dragging_caret_to_bottom_right_corner(self, el_id):
    103        self.open_test_html(self._cursor_html)
    104        el = self.marionette.find_element(By.ID, el_id)
    105        sel = SelectionManager(el)
    106        content_to_add = "!"
    107        target_content = sel.content + content_to_add
    108 
    109        # Click the front of the input to make first caret appear.
    110        self.actions.click(element=el).perform()
    111        sel.move_cursor_to_front()
    112        self.actions.move(el, *sel.cursor_location()).click().perform()
    113 
    114        # Move first caret to the bottom-right corner of the element.
    115        src_x, src_y = sel.first_caret_location()
    116        dest_x, dest_y = el.rect["width"], el.rect["height"]
    117        self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform()
    118 
    119        self.actions.send_keys(content_to_add).perform()
    120        self.assertEqual(target_content, sel.content)
    121 
    122    @parameterized(_input_id, el_id=_input_id)
    123    @parameterized(_textarea_id, el_id=_textarea_id)
    124    @parameterized(_contenteditable_id, el_id=_contenteditable_id)
    125    def test_move_cursor_to_front_by_dragging_caret_to_front(self, el_id):
    126        self.open_test_html(self._cursor_html)
    127        el = self.marionette.find_element(By.ID, el_id)
    128        sel = SelectionManager(el)
    129        content_to_add = "!"
    130        target_content = content_to_add + sel.content
    131 
    132        # Get first caret location at the front.
    133        self.actions.click(element=el).perform()
    134        sel.move_cursor_to_front()
    135        dest_x, dest_y = sel.first_caret_location()
    136 
    137        # Click to make first caret appear.
    138        self.actions.click(element=el).perform()
    139        sel.move_cursor_to_end()
    140        self.actions.move(el, *sel.cursor_location()).click().perform()
    141        src_x, src_y = sel.first_caret_location()
    142 
    143        # Move first caret to the front of the input box.
    144        self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform()
    145 
    146        self.actions.send_keys(content_to_add).perform()
    147        self.assertEqual(target_content, sel.content)
    148 
    149    def test_caret_not_appear_when_typing_in_scrollable_content(self):
    150        self.open_test_html(self._cursor_html)
    151        el = self.marionette.find_element(By.ID, self._input_id)
    152        sel = SelectionManager(el)
    153        content_to_add = "!"
    154        non_target_content = content_to_add + sel.content + string.ascii_letters
    155 
    156        self.actions.click(element=el).perform()
    157        sel.move_cursor_to_end()
    158 
    159        # Insert a long string to the end of the <input>, which triggers
    160        # ScrollPositionChanged event.
    161        el.send_keys(string.ascii_letters)
    162 
    163        # The caret should not be visible. If it does appear wrongly due to the
    164        # ScrollPositionChanged event, we can drag it to the front of the
    165        # <input> to change the cursor position.
    166        src_x, src_y = sel.first_caret_location()
    167        dest_x, dest_y = 0, 0
    168        self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform()
    169 
    170        # The content should not be inserted at the front of the <input>.
    171        el.send_keys(content_to_add)
    172 
    173        self.assertNotEqual(non_target_content, sel.content)
    174 
    175    @parameterized(_input_id, el_id=_input_id)
    176    @parameterized(_input_padding_id, el_id=_input_padding_id)
    177    @parameterized(_textarea_one_line_id, el_id=_textarea_one_line_id)
    178    @parameterized(_contenteditable_id, el_id=_contenteditable_id)
    179    def test_caret_not_jump_when_dragging_to_editable_content_boundary(self, el_id):
    180        self.open_test_html(self._cursor_html)
    181        el = self.marionette.find_element(By.ID, el_id)
    182        sel = SelectionManager(el)
    183        content_to_add = "!"
    184        non_target_content = sel.content + content_to_add
    185 
    186        # Goal: the cursor position is not changed after dragging the caret down
    187        # on the Y-axis.
    188        self.actions.click(element=el).perform()
    189        sel.move_cursor_to_front()
    190        self.actions.move(el, *sel.cursor_location()).click().perform()
    191        x, y = sel.first_caret_location()
    192 
    193        # Drag the caret down by 50px, and insert '!'.
    194        self.actions.flick(el, x, y, x, y + 50).perform()
    195        self.actions.send_keys(content_to_add).perform()
    196        self.assertNotEqual(non_target_content, sel.content)
    197 
    198    @parameterized(_input_id, el_id=_input_id)
    199    @parameterized(_input_padding_id, el_id=_input_padding_id)
    200    @parameterized(_textarea_one_line_id, el_id=_textarea_one_line_id)
    201    @parameterized(_contenteditable_id, el_id=_contenteditable_id)
    202    def test_caret_not_jump_to_front_when_dragging_up_to_editable_content_boundary(
    203        self, el_id
    204    ):
    205        self.open_test_html(self._cursor_html)
    206        el = self.marionette.find_element(By.ID, el_id)
    207        sel = SelectionManager(el)
    208        content_to_add = "!"
    209        non_target_content = content_to_add + sel.content
    210 
    211        # Goal: the cursor position is not changed after dragging the caret down
    212        # on the Y-axis.
    213        self.actions.click(element=el).perform()
    214        sel.move_cursor_to_end()
    215        self.actions.move(el, *sel.cursor_location()).click().perform()
    216        x, y = sel.first_caret_location()
    217 
    218        # Drag the caret up by 40px, and insert '!'.
    219        self.actions.flick(el, x, y, x, y - 40).perform()
    220        self.actions.send_keys(content_to_add).perform()
    221        self.assertNotEqual(non_target_content, sel.content)
    222 
    223    def test_drag_caret_from_front_to_end_across_columns(self):
    224        self.open_test_html("layout/test_carets_columns.html")
    225        el = self.marionette.find_element(By.ID, "columns")
    226        sel = SelectionManager(el)
    227        content_to_add = "!"
    228        target_content = sel.content + content_to_add
    229 
    230        # Goal: the cursor position can be changed by dragging the caret from
    231        # the front to the end of the content.
    232 
    233        # Click to make the cursor appear.
    234        before_image_1 = self.marionette.find_element(By.ID, "before-image-1")
    235        self.actions.click(element=before_image_1).perform()
    236 
    237        # Click the front of the content to make first caret appear.
    238        sel.move_cursor_to_front()
    239        self.actions.move(el, *sel.cursor_location()).click().perform()
    240        src_x, src_y = sel.first_caret_location()
    241        dest_x, dest_y = el.rect["width"], el.rect["height"]
    242 
    243        # Drag the first caret to the bottom-right corner of the element.
    244        self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform()
    245 
    246        self.actions.send_keys(content_to_add).perform()
    247        self.assertEqual(target_content, sel.content)
    248 
    249    def test_move_cursor_to_front_by_dragging_caret_to_front_br_element(self):
    250        self.open_test_html(self._cursor_html)
    251        el = self.marionette.find_element(By.ID, self._contenteditable_id)
    252        sel = SelectionManager(el)
    253        content_to_add_1 = "!"
    254        content_to_add_2 = "\n\n"
    255        target_content = content_to_add_1 + content_to_add_2 + sel.content
    256 
    257        # Goal: the cursor position can be changed by dragging the caret from
    258        # the end of the content to the front br element. Because we cannot get
    259        # caret location if it's on a br element, we need to get the first caret
    260        # location then adding the new lines.
    261 
    262        # Get first caret location at the front.
    263        self.actions.click(element=el).perform()
    264        sel.move_cursor_to_front()
    265        dest_x, dest_y = sel.first_caret_location()
    266 
    267        # Append new line to the front of the content.
    268        el.send_keys(content_to_add_2)
    269 
    270        # Click to make first caret appear.
    271        self.actions.click(element=el).perform()
    272        sel.move_cursor_to_end()
    273        self.actions.move(el, *sel.cursor_location()).click().perform()
    274        src_x, src_y = sel.first_caret_location()
    275 
    276        # Move first caret to the front of the input box.
    277        self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform()
    278 
    279        self.actions.send_keys(content_to_add_1).perform()
    280        self.assertEqual(target_content, sel.content)