author | Ting-Yu Lin <tlin@mozilla.com> |
Tue, 08 Mar 2016 22:45:47 +0800 | |
changeset 287426 | ba096724ac7ce2bed4741b3b68668e924552db61 |
parent 287425 | c0fdb08d2254c5c75e7173233f4d2decabf23738 |
child 287427 | c575320f1d603d726cabb777d522e12b647018d8 |
push id | 30068 |
push user | cbook@mozilla.com |
push date | Wed, 09 Mar 2016 10:46:58 +0000 |
treeherder | mozilla-central@af7c0cb0798f [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | mtseng |
bugs | 1253989 |
milestone | 48.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
|
--- a/layout/base/tests/marionette/test_accessiblecaret_cursor_mode.py +++ b/layout/base/tests/marionette/test_accessiblecaret_cursor_mode.py @@ -46,82 +46,82 @@ class AccessibleCaretCursorModeTestCase( def test_move_cursor_to_the_right_by_one_character(self, el_id): self.open_test_html() el = self.marionette.find_element(By.ID, el_id) sel = SelectionManager(el) content_to_add = '!' target_content = sel.content target_content = target_content[:1] + content_to_add + target_content[1:] - # Get touch caret (x, y) at position 1 and 2. + # Get first caret (x, y) at position 1 and 2. el.tap() - sel.move_caret_to_front() - caret0_x, caret0_y = sel.caret_location() - touch_caret0_x, touch_caret0_y = sel.touch_caret_location() - sel.move_caret_by_offset(1) - touch_caret1_x, touch_caret1_y = sel.touch_caret_location() + sel.move_cursor_to_front() + cursor0_x, cursor0_y = sel.cursor_location() + first_caret0_x, first_caret0_y = sel.first_caret_location() + sel.move_cursor_by_offset(1) + first_caret1_x, first_caret1_y = sel.first_caret_location() - # Tap the front of the input to make touch caret appear. - el.tap(caret0_x, caret0_y) + # Tap the front of the input to make first caret appear. + el.tap(cursor0_x, cursor0_y) - # Move touch caret - self.actions.flick(el, touch_caret0_x, touch_caret0_y, - touch_caret1_x, touch_caret1_y).perform() + # 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.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() el = self.marionette.find_element(By.ID, el_id) sel = SelectionManager(el) content_to_add = '!' target_content = sel.content + content_to_add - # Tap the front of the input to make touch caret appear. + # Tap the front of the input to make first caret appear. el.tap() - sel.move_caret_to_front() - el.tap(*sel.caret_location()) + sel.move_cursor_to_front() + el.tap(*sel.cursor_location()) - # Move touch caret to the bottom-right corner of the element. - src_x, src_y = sel.touch_caret_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.size['width'], el.size['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.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() el = self.marionette.find_element(By.ID, el_id) sel = SelectionManager(el) content_to_add = '!' target_content = content_to_add + sel.content - # Get touch caret location at the front. + # Get first caret location at the front. el.tap() - sel.move_caret_to_front() - dest_x, dest_y = sel.touch_caret_location() + sel.move_cursor_to_front() + dest_x, dest_y = sel.first_caret_location() - # Tap to make touch caret appear. Note: it's strange that when the caret + # Tap to make first caret appear. Note: it's strange that when the caret # is at the end, the rect of the caret in <textarea> cannot be obtained. # A bug perhaps. el.tap() - sel.move_caret_to_end() - sel.move_caret_by_offset(1, backward=True) - el.tap(*sel.caret_location()) - src_x, src_y = sel.touch_caret_location() + 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 touch caret to the front of the input box. + # 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.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) @@ -134,51 +134,51 @@ class AccessibleCaretCursorModeTestCase( # Set caret timeout to be 1 second. timeout = 1 self.marionette.set_pref(self.caret_timeout_ms_pref, timeout * 1000) # Set a 3x timeout margin to prevent intermittent test failures. timeout *= 3 - # Tap to make touch caret appear. Note: it's strange that when the caret + # Tap to make first caret appear. Note: it's strange that when the caret # is at the end, the rect of the caret in <textarea> cannot be obtained. # A bug perhaps. el.tap() - sel.move_caret_to_end() - sel.move_caret_by_offset(1, backward=True) - el.tap(*sel.caret_location()) + sel.move_cursor_to_end() + sel.move_cursor_by_offset(1, backward=True) + el.tap(*sel.cursor_location()) - # Wait until touch caret disappears, then pretend to move it to the + # Wait until first caret disappears, then pretend to move it to the # top-left corner of the input box. - src_x, src_y = sel.touch_caret_location() + src_x, src_y = sel.first_caret_location() dest_x, dest_y = 0, 0 self.actions.wait(timeout).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.assertNotEqual(non_target_content, sel.content) def test_caret_not_appear_when_typing_in_scrollable_content(self): self.open_test_html() el = self.marionette.find_element(By.ID, self._input_id) sel = SelectionManager(el) content_to_add = '!' target_content = sel.content + string.ascii_letters + content_to_add el.tap() - sel.move_caret_to_end() + sel.move_cursor_to_end() # Insert a long string to the end of the <input>, which triggers # ScrollPositionChanged event. el.send_keys(string.ascii_letters) # The caret should not be visible. If it does appear wrongly due to the # ScrollPositionChanged event, we can drag it to the front of the # <input> to change the cursor position. - src_x, src_y = sel.touch_caret_location() + src_x, src_y = sel.first_caret_location() dest_x, dest_y = 0, 0 self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform() # The content should be inserted at the end of the <input>. el.send_keys(content_to_add) self.assertEqual(target_content, sel.content) @@ -187,16 +187,16 @@ class AccessibleCaretCursorModeTestCase( el = self.marionette.find_element(By.ID, self._input_id) sel = SelectionManager(el) content_to_add = '!' non_target_content = sel.content + content_to_add # Goal: the cursor position does not being changed after dragging the # caret down on the Y-axis. el.tap() - sel.move_caret_to_front() - el.tap(*sel.caret_location()) - x, y = sel.touch_caret_location() + 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.assertNotEqual(non_target_content, sel.content)
--- a/layout/base/tests/marionette/test_accessiblecaret_selection_mode.py +++ b/layout/base/tests/marionette/test_accessiblecaret_selection_mode.py @@ -91,19 +91,19 @@ class AccessibleCaretSelectionModeTestCa target element el. ''' sel = SelectionManager(el) offset = self.word_offset(sel.content, ordinal) # Move the blinking cursor to the word. el.tap() - sel.move_caret_to_front() - sel.move_caret_by_offset(offset) - x, y = sel.caret_location() + sel.move_cursor_to_front() + sel.move_cursor_by_offset(offset) + x, y = sel.cursor_location() return x, y def rect_relative_to_window(self, el): '''Get element's bounding rectangle. This function is similar to el.rect, but the coordinate is relative to the top left corner of the window instead of the document. @@ -183,26 +183,26 @@ class AccessibleCaretSelectionModeTestCa sel = SelectionManager(el) original_content = sel.content words = original_content.split() self.assertTrue(len(words) >= 1, 'Expect at least one word in the content.') # Goal: Select all text after the first word. target_content = original_content[len(words[0]):] - # Get the location of the selection carets at the end of the content for - # later use. + # Get the location of the carets at the end of the content for later + # use. el.tap() sel.select_all() - (_, _), (end_caret_x, end_caret_y) = sel.selection_carets_location() + end_caret_x, end_caret_y = sel.second_caret_location() self.long_press_on_word(el, 0) # Drag the second caret to the end of the content. - (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location() + (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location() self.actions.flick(el, caret2_x, caret2_y, end_caret_x, end_caret_y).perform() # Drag the first caret to the previous position of the second caret. self.actions.flick(el, caret1_x, caret1_y, caret2_x, caret2_y).perform() self.assertEqual(target_content, sel.selected_content) @parameterized(_input_id, el_id=_input_id) @@ -224,39 +224,39 @@ class AccessibleCaretSelectionModeTestCa self._test_minimum_select_one_character(el) def _test_minimum_select_one_character(self, el, x=None, y=None): sel = SelectionManager(el) original_content = sel.content words = original_content.split() self.assertTrue(len(words) >= 1, 'Expect at least one word in the content.') - # Get the location of the selection carets at the end of the content for - # later use. + # Get the location of the carets at the end of the content for later + # use. sel.select_all() - (_, _), (end_caret_x, end_caret_y) = sel.selection_carets_location() + end_caret_x, end_caret_y = sel.second_caret_location() el.tap() # Goal: Select the first character. target_content = original_content[0] if x and y: # If we got x and y from the arguments, use it as a hint of the # location of the first word pass else: x, y = self.word_location(el, 0) self.long_press_on_location(el, x, y) # Drag the second caret to the end of the content. - (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location() + (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location() self.actions.flick(el, caret2_x, caret2_y, end_caret_x, end_caret_y).perform() # Drag the second caret to the position of the first caret. - (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location() + (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location() self.actions.flick(el, caret2_x, caret2_y, caret1_x, caret1_y).perform() self.assertEqual(target_content, sel.selected_content) @parameterized(_input_id + '_to_' + _textarea_id, el1_id=_input_id, el2_id=_textarea_id) @parameterized(_input_id + '_to_' + _contenteditable_id, el1_id=_input_id, el2_id=_contenteditable_id) @@ -338,24 +338,24 @@ class AccessibleCaretSelectionModeTestCa self.assertTrue(len(words) >= 1, 'Expect at least one word in the content.') # Goal: Select the first word. self.long_press_on_word(el, 0) target_content = sel.selected_content # Drag the first caret to the position of the second caret to trigger # carets overlapping. - (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location() + (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location() self.actions.flick(el, caret1_x, caret1_y, caret2_x, caret2_y).perform() # We make two hit tests targeting the left edge of the left tilted caret # and the right edge of the right tilted caret. If either of the hits is # missed, selection would be collapsed and both carets should not be # draggable. - (caret3_x, caret3_y), (caret4_x, caret4_y) = sel.selection_carets_location() + (caret3_x, caret3_y), (caret4_x, caret4_y) = sel.carets_location() # The following values are from ua.css and all.js caret_width = float(self.marionette.get_pref('layout.accessiblecaret.width')) caret_margin_left = float(self.marionette.get_pref('layout.accessiblecaret.margin-left')) tilt_right_margin_left = 0.41 * caret_width tilt_left_margin_left = -0.39 * caret_width left_caret_left_edge_x = caret3_x + caret_margin_left + tilt_left_margin_left @@ -366,72 +366,75 @@ class AccessibleCaretSelectionModeTestCa el.tap(right_caret_right_edge_x - 2, caret4_y) # Drag the first caret back to the initial selection, the first word. self.actions.flick(el, caret3_x, caret3_y, caret1_x, caret1_y).perform() self.assertEqual(target_content, sel.selected_content) def test_drag_caret_over_non_selectable_field(self): - '''Testing drag caret over non selectable field. - So that the selected content should exclude non selectable field and - end selection caret should appear in last range's position.''' + '''Test dragging the caret over a non-selectable field. + + The selected content should exclude non-selectable elements and the + second caret should appear in last range's position. + + ''' self.open_test_html_multirange() body = self.marionette.find_element(By.ID, 'bd') sel3 = self.marionette.find_element(By.ID, 'sel3') sel4 = self.marionette.find_element(By.ID, 'sel4') sel6 = self.marionette.find_element(By.ID, 'sel6') # Select target element and get target caret location self.long_press_on_word(sel4, 3) sel = SelectionManager(body) - (_, _), (end_caret_x, end_caret_y) = sel.selection_carets_location() + end_caret_x, end_caret_y = sel.second_caret_location() self.long_press_on_word(sel6, 0) - (_, _), (end_caret2_x, end_caret2_y) = sel.selection_carets_location() + end_caret2_x, end_caret2_y = sel.second_caret_location() # Select start element self.long_press_on_word(sel3, 3) # Drag end caret to target location - (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location() + (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location() self.actions.flick(body, caret2_x, caret2_y, end_caret_x, end_caret_y, 1).perform() self.assertEqual(self.to_unix_line_ending(sel.selected_content.strip()), 'this 3\nuser can select this') - (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location() + (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location() self.actions.flick(body, caret2_x, caret2_y, end_caret2_x, end_caret2_y, 1).perform() self.assertEqual(self.to_unix_line_ending(sel.selected_content.strip()), 'this 3\nuser can select this 4\nuser can select this 5\nuser') # Drag first caret to target location - (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location() + (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location() self.actions.flick(body, caret1_x, caret1_y, end_caret_x, end_caret_y, 1).perform() self.assertEqual(self.to_unix_line_ending(sel.selected_content.strip()), '4\nuser can select this 5\nuser') def test_drag_caret_to_beginning_of_a_line(self): '''Bug 1094056 Test caret visibility when caret is dragged to beginning of a line ''' self.open_test_html_multirange() body = self.marionette.find_element(By.ID, 'bd') sel1 = self.marionette.find_element(By.ID, 'sel1') sel2 = self.marionette.find_element(By.ID, 'sel2') # Select the first word in the second line self.long_press_on_word(sel2, 0) sel = SelectionManager(body) - (start_caret_x, start_caret_y), (end_caret_x, end_caret_y) = sel.selection_carets_location() + (start_caret_x, start_caret_y), (end_caret_x, end_caret_y) = sel.carets_location() # Select target word in the first line self.long_press_on_word(sel1, 2) # Drag end caret to the beginning of the second line - (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location() + (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location() self.actions.flick(body, caret2_x, caret2_y, start_caret_x, start_caret_y).perform() # Drag end caret back to the target word self.actions.flick(body, start_caret_x, start_caret_y, caret2_x, caret2_y).perform() self.assertEqual(self.to_unix_line_ending(sel.selected_content), 'select') @skip_if_not_rotatable @@ -444,19 +447,19 @@ class AccessibleCaretSelectionModeTestCa body = self.marionette.find_element(By.ID, 'bd') longtext = self.marionette.find_element(By.ID, 'longtext') # Select word in portrait mode, then change to landscape mode self.marionette.set_orientation('portrait') self.long_press_on_word(longtext, 12) sel = SelectionManager(body) - (p_start_caret_x, p_start_caret_y), (p_end_caret_x, p_end_caret_y) = sel.selection_carets_location() + (p_start_caret_x, p_start_caret_y), (p_end_caret_x, p_end_caret_y) = sel.carets_location() self.marionette.set_orientation('landscape') - (l_start_caret_x, l_start_caret_y), (l_end_caret_x, l_end_caret_y) = sel.selection_carets_location() + (l_start_caret_x, l_start_caret_y), (l_end_caret_x, l_end_caret_y) = sel.carets_location() # Drag end caret to the start caret to change the selected content self.actions.flick(body, l_end_caret_x, l_end_caret_y, l_start_caret_x, l_start_caret_y).perform() # Change orientation back to portrait mode to prevent affecting # other tests self.marionette.set_orientation('portrait') @@ -534,34 +537,34 @@ class AccessibleCaretSelectionModeTestCa self.assertEqual(words[1], sel.selected_content) self.long_press_on_location(el, word0_x, word0_y) self.assertEqual(words[0], sel.selected_content) # If the second carets is visible, it can be dragged to the position of # the first caret. After that, selection will contain only the first # character. - (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location() + (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location() self.actions.flick(el, caret2_x, caret2_y, caret1_x, caret1_y).perform() self.assertEqual(words[0][0], sel.selected_content) def test_carets_do_not_jump_when_dragging_to_editable_content_boundary(self): self.open_test_html() el = self.marionette.find_element(By.ID, self._input_id) sel = SelectionManager(el) original_content = sel.content words = original_content.split() self.assertTrue(len(words) >= 3, 'Expect at least three words in the content.') # Goal: the selection does not being changed after dragging the caret # on the Y-axis only. target_content = words[1] self.long_press_on_word(el, 1) - (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location() + (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() self.assertEqual(target_content, sel.selected_content) # Drag the first 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)
--- a/testing/marionette/client/marionette_driver/selection.py +++ b/testing/marionette/client/marionette_driver/selection.py @@ -2,16 +2,19 @@ # 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/. 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: :: element = marionette.find_element('id', 'input') sel = SelectionManager(element) sel.move_caret_to_front() @@ -36,45 +39,45 @@ class SelectionManager(object): ''' if self._input_or_textarea(): # We must unwrap sel so that DOMRect could be returned to Python # side. return '''var sel = arguments[0].editor.selection;''' else: return '''var sel = window.getSelection();''' - def move_caret_by_offset(self, offset, backward=False): - '''Move caret in the element by character offset. + def move_cursor_by_offset(self, offset, backward=False): + '''Move cursor in the element by character offset. - :param offset: Move the caret to the direction by offset characters. + :param offset: Move the cursor to the direction by offset characters. :param backward: Optional, True to move backward; Default to False to move forward. ''' cmd = self.js_selection_cmd() + ''' for (let i = 0; i < %d; ++i) { sel.modify("move", "%s", "character"); } ''' % (offset, 'backward' if backward else 'forward') self.element.marionette.execute_script( cmd, script_args=[self.element], sandbox='system') - def move_caret_to_front(self): - '''Move caret in the element to the front of the content.''' + def move_cursor_to_front(self): + '''Move cursor in the element to the front of the content.''' if self._input_or_textarea(): cmd = '''arguments[0].setSelectionRange(0, 0);''' else: cmd = '''var sel = window.getSelection(); sel.collapse(arguments[0].firstChild, 0);''' self.element.marionette.execute_script(cmd, script_args=[self.element]) - def move_caret_to_end(self): - '''Move caret in the element to the end of the content.''' + def move_cursor_to_end(self): + '''Move cursor in the element to the end of the content.''' if self._input_or_textarea(): cmd = '''var len = arguments[0].value.length; arguments[0].setSelectionRange(len, len);''' else: cmd = '''var sel = window.getSelection(); sel.collapse(arguments[0].lastChild, arguments[0].lastChild.length);''' self.element.marionette.execute_script(cmd, script_args=[self.element]) @@ -148,43 +151,52 @@ class SelectionManager(object): Return a tuple containing two pairs of (x, y) coordinates of the start and end of the selection. The coordinates are relative to the top left-hand corner of the element. Both ltr and rtl direction are considered. ''' return self._selection_location_helper('center') - def selection_carets_location(self): - '''Return a pair of the two selection carets' location. + def carets_location(self): + '''Return a pair of the two carets' location. Return a tuple containing two pairs of (x, y) coordinates of the two - selection carets' tip. The coordinates are relative to the top left-hand - corner of the element. Both ltr and rtl direction are considered. + carets' tip. The coordinates are relative to the top left-hand corner of + the element. Both ltr and rtl direction are considered. ''' return self._selection_location_helper('caret') - def caret_location(self): - '''Return caret's center location within the element. + def cursor_location(self): + '''Return the blanking cursor's center location within the element. - Return (x, y) coordinates of the caret's center relative to the top + Return (x, y) coordinates of the cursor's center relative to the top left-hand corner of the element. ''' return self._selection_location_helper('center')[0] - def touch_caret_location(self): - '''Return touch caret's location (based on current caret location). + def first_caret_location(self): + '''Return the first caret's location. - Return (x, y) coordinates of the touch caret's tip relative to the top + Return (x, y) coordinates of the first caret's tip relative to the top left-hand corner of the element. ''' - return self._selection_location_helper('caret')[0] + return self.carets_location()[0] + + def second_caret_location(self): + '''Return the second caret's location. + + Return (x, y) coordinates of the second caret's tip relative to the top + left-hand corner of the element. + + ''' + return self.carets_location()[1] def select_all(self): '''Select all the content in the element.''' if self._input_or_textarea(): cmd = '''var len = arguments[0].value.length; arguments[0].focus(); arguments[0].setSelectionRange(0, len);''' else: