def long_press_action(marionette, wait_for_condition, expected): testAction = marionette.absolute_url("testAction.html") marionette.navigate(testAction) button = marionette.find_element(By.ID, "button1") action = Actions(marionette) action.long_press(button, 5).perform() wait_for_condition_else_raise(marionette, wait_for_condition, expected, "return document.getElementById('button1').innerHTML;")
def send(self, string): self.switch_to_keyboard() for val in string: if ord(val) > 127: # this would get the right key to long press and switch to the right keyboard middle_key_val = self._find_key_for_longpress(val.encode("UTF-8")) self._switch_to_correct_layout(middle_key_val) # find the key to long press and press it to get the extended characters list middle_key = self.marionette.find_element(*self._key_locator(middle_key_val)) action = Actions(self.marionette) action.press(middle_key).wait(1).perform() # find the targeted extended key to send key = Wait(self.marionette).until(expected.element_present(*self._key_locator(val))) Wait(self.marionette).until(expected.element_displayed(key)) action.move(key).release().perform() else: # after switching to correct keyboard, tap/click if the key is there self._switch_to_correct_layout(val) self._tap(val) # when we tap on '@' the layout switches to the default keyboard - Bug 996332 if val == "@": Wait(self.marionette).until(lambda m: self._layout_page == 0) self.apps.switch_to_displayed_app()
def wait(marionette, wait_for_condition, expected): testAction = marionette.absolute_url("testAction.html") marionette.navigate(testAction) action = Actions(marionette) button = marionette.find_element("id", "button1") action.press(button).wait().release().perform() wait_for_condition_else_raise(marionette, wait_for_condition, expected, "return document.getElementById('button1').innerHTML;")
def chain_flick(marionette, wait_for_condition, expected1, expected2): testAction = marionette.absolute_url("testAction.html") marionette.navigate(testAction) button = marionette.find_element(By.ID, "button1") action = Actions(marionette) action.flick(button, 0, 0, 0, 200).perform() wait_for_condition_else_raise(marionette, wait_for_condition, expected1,"return document.getElementById('button1').innerHTML;") wait_for_condition_else_raise(marionette, wait_for_condition, expected2,"return document.getElementById('buttonFlick').innerHTML;")
def context_menu(marionette, wait_for_condition, expected1, expected2): testAction = marionette.absolute_url("testAction.html") marionette.navigate(testAction) button = marionette.find_element(By.ID, "button1") action = Actions(marionette) action.press(button).wait(5).perform() wait_for_condition_else_raise(marionette, wait_for_condition, expected1, "return document.getElementById('button1').innerHTML;") action.release().perform() wait_for_condition_else_raise(marionette, wait_for_condition, expected2, "return document.getElementById('button1').innerHTML;")
def move_element_offset(marionette, wait_for_condition, expected1, expected2): testAction = marionette.absolute_url("testAction.html") marionette.navigate(testAction) ele = marionette.find_element(By.ID, "button1") action = Actions(marionette) action.press(ele).move_by_offset(0,150).move_by_offset(0, 150).release() action.perform() wait_for_condition_else_raise(marionette, wait_for_condition, expected1, "return document.getElementById('button1').innerHTML;") wait_for_condition_else_raise(marionette, wait_for_condition, expected2, "return document.getElementById('button2').innerHTML;")
def _flick_to_image(self, direction): image = self.marionette.find_element(*self._current_image_locator) action = Actions(self.marionette) x_start = (image.size['width'] / 100) * (direction == 'next' and 90 or 10) x_end = (image.size['width'] / 100) * (direction == 'next' and 10 or 90) y_start = image.size['height'] / 4 y_end = image.size['height'] / 4 action.flick(image, x_start, y_start, x_end, y_end, 200).perform() Wait(self.marionette).until( lambda m: abs(image.location['x']) >= image.size['width'])
def move_seek_slider(self, offset): scale = self.marionette.find_element(*self._video_seek_head_locator) finger = Actions(self.marionette) finger.press(scale) finger.move_by_offset(offset, 0) finger.release() finger.perform()
def chain(marionette, wait_for_condition, expected1, expected2): testAction = marionette.absolute_url("testAction.html") marionette.navigate(testAction) marionette.timeout.implicit = 15 action = Actions(marionette) button1 = marionette.find_element(By.ID, "button1") action.press(button1).perform() button2 = marionette.find_element(By.ID, "delayed") wait_for_condition_else_raise(marionette, wait_for_condition, expected1, "return document.getElementById('button1').innerHTML;") action.move(button2).release().perform() wait_for_condition_else_raise(marionette, wait_for_condition, expected2, "return document.getElementById('delayed').innerHTML;")
def move_slider(self, slider, dir_x): scale = self.marionette.find_element(*slider) finger = Actions(self.marionette) finger.press(scale) finger.move_by_offset(dir_x, 0) finger.release() finger.perform() time.sleep(2)
def long_press_on_xy_action(marionette, wait_for_condition, expected): testAction = marionette.absolute_url("testAction.html") marionette.navigate(testAction) html = marionette.find_element(By.TAG_NAME, "html") button = marionette.find_element(By.ID, "button1") action = Actions(marionette) # Press the center of the button with respect to html. x = button.rect['x'] + button.rect['width'] / 2.0 y = button.rect['y'] + button.rect['height'] / 2.0 action.long_press(html, 5, x, y).perform() wait_for_condition_else_raise(marionette, wait_for_condition, expected, "return document.getElementById('button1').innerHTML;")
def switch_keyboard_language(self, lang_code): # TODO At the moment this doesn't work because the UI has changed # An attempted repair ran into https://bugzilla.mozilla.org/show_bug.cgi?id=779284 (Modal dialog) keyboard_language_locator = (By.CSS_SELECTOR, ".keyboard-row button[data-keyboard='%s']" % lang_code) self.switch_to_keyboard() language_key = self.marionette.find_element(*self._language_key_locator) action = Actions(self.marionette) action.press(language_key).wait(1).perform() target_kb_layout = self.marionette.find_element(*keyboard_language_locator) action.move(target_kb_layout).release().perform() self.apps.switch_to_displayed_app()
def _flick_to_image(self, direction): image = self.marionette.find_element(*self._current_image_locator) action = Actions(self.marionette) x_start = (image.size['width'] / 100) * (direction == 'next' and 90 or 10) x_end = (image.size['width'] / 100) * (direction == 'next' and 10 or 90) y_start = image.size['height'] / 4 y_end = image.size['height'] / 4 action.flick(image, x_start, y_start, x_end, y_end, 200).perform() Wait(self.marionette).until( lambda m: abs(image.location['x']) >= image.size['width']) # Workaround for bug 1161441, the transitionend event is not firing in this # case with a Marionette flick action, as opposed to a manual flick action self.marionette.execute_script(""" arguments[0].dispatchEvent(new CustomEvent("transitionend")); """, [self.current_image_frame])
def press_release(marionette, times, wait_for_condition, expected): testAction = marionette.absolute_url("testAction.html") marionette.navigate(testAction) action = Actions(marionette) button = marionette.find_element(By.ID, "button1") action.press(button).release() # Insert wait between each press and release chain. for _ in range(times-1): action.wait(0.1) action.press(button).release() action.perform() wait_for_condition_else_raise(marionette, wait_for_condition, expected, "return document.getElementById('button1').innerHTML;")
def test_run(self): # Launch messages app. self.messages.launch() # Create and send a new test message. self.messages.create_and_send_sms([self.phone_number], self.test_msg) send_time = self.messages.last_sent_message_timestamp() msg = self.messages.wait_for_message(send_time=send_time) self.messages.check_last_message_contents(self.test_msg) # Tap on edit mode. edit_btn = self.UTILS.element.getElement(DOM.Messages.edit_messages_icon, "Edit button") edit_btn.tap() select_btn = self.UTILS.element.getElement(DOM.Messages.edit_msgs_select_btn, "Select button") select_btn.tap() # Long press the email link. _link = msg.find_element("tag name", "a") self.actions = Actions(self.marionette) self.actions.long_press(_link, 2).perform() # Check the email address is not a link in edit mode. self.UTILS.element.waitForNotElements(DOM.Messages.header_create_new_contact_btn, "Create new contact button")
def __init__(self, p_parent): self.apps = p_parent.apps self.data_layer = p_parent.data_layer self.parent = p_parent self.marionette = p_parent.marionette self.UTILS = p_parent.UTILS self.actions = Actions(self.marionette)
def setUp(self): # 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)
def setUp(self): MarionetteTestCase.setUp(self) if self.marionette.session_capabilities["platformName"] == "darwin": self.mod_key = Keys.META else: self.mod_key = Keys.CONTROL self.action = Actions(self.marionette)
def setUp(self): MarionetteTestCase.setUp(self) if self.marionette.session_capabilities['platformName'] == 'DARWIN': self.mod_key = Keys.META else: self.mod_key = Keys.CONTROL self.action = Actions(self.marionette)
class test_main(GaiaTestCase): def setUp(self): # Set up child objects... GaiaTestCase.setUp(self) self.UTILS = UTILS(self) self.messages = Messages(self) self.actions = Actions(self.marionette) # Establish which phone number to use. self.phone_number = self.UTILS.general.get_config_variable("phone_number", "custom") self.incoming_sms_num = self.UTILS.general.get_config_variable("sms_platform_numbers", "common").split(',') self.UTILS.reporting.logComment("Sending sms to telephone number " + self.phone_number) self.data_layer.delete_all_sms() def tearDown(self): self.UTILS.reporting.reportResults() GaiaTestCase.tearDown(self) def test_run(self): self.UTILS.statusbar.clearAllStatusBarNotifs() timestamp = " {}".format(time.time()) sms_message = "0123456789" * 5 + timestamp self.UTILS.reporting.logComment("Message length sent: {}".format((len(sms_message)))) self.UTILS.messages.create_incoming_sms(self.phone_number, sms_message) self.UTILS.statusbar.wait_for_notification_toaster_detail(timestamp, timeout=120) title = self.UTILS.statusbar.wait_for_notification_toaster_with_titles(self.incoming_sms_num, timeout=5) self.UTILS.statusbar.click_on_notification_title(title, DOM.Messages.frame_locator) # Open sms option with longtap on it self.UTILS.reporting.logResult("info", "Open sms option with longtap on it") sms = self.messages.last_message_in_this_thread() body = self.marionette.find_element(*DOM.Messages.last_message_body, id=sms.id) self.actions.long_press(body, 2).perform() # Press cancel button self.UTILS.reporting.logResult("info", "Clicking cancel button") time.sleep(2) cancel_btn = self.UTILS.element.getElement(DOM.Messages.cancel_btn_msg_opt, "Cancel button is displayed") self.UTILS.reporting.debug("*** Cancel button: {} text: {}".format(cancel_btn, cancel_btn.text)) self.UTILS.element.simulateClick(cancel_btn)
class test_main(GaiaTestCase): def setUp(self): # Set up child objects... GaiaTestCase.setUp(self) self.UTILS = UTILS(self) self.messages = Messages(self) self.contacts = Contacts(self) self.phone_number = self.UTILS.general.get_config_variable("phone_number", "custom") self.emailAddy = self.UTILS.general.get_config_variable("gmail_1_email", "common") self.test_msg = "Hello {} old bean at {}.".format(self.emailAddy, time.time()) def tearDown(self): self.UTILS.reporting.reportResults() GaiaTestCase.tearDown(self) def test_run(self): # Launch messages app. self.messages.launch() # Create and send a new test message. self.messages.create_and_send_sms([self.phone_number], self.test_msg) send_time = self.messages.last_sent_message_timestamp() msg = self.messages.wait_for_message(send_time=send_time) self.messages.check_last_message_contents(self.test_msg) # Tap on edit mode. edit_btn = self.UTILS.element.getElement(DOM.Messages.edit_messages_icon, "Edit button") edit_btn.tap() select_btn = self.UTILS.element.getElement(DOM.Messages.edit_msgs_select_btn, "Select button") select_btn.tap() # Long press the email link. _link = msg.find_element("tag name", "a") self.actions = Actions(self.marionette) self.actions.long_press(_link, 2).perform() # Check the email address is not a link in edit mode. self.UTILS.element.waitForNotElements(DOM.Messages.header_create_new_contact_btn, "Create new contact button")
class test_main(GaiaTestCase): def __init__(self, *args, **kwargs): kwargs['restart'] = True super(test_main, self).__init__(*args, **kwargs) def setUp(self): # Set up child objects... GaiaTestCase.setUp(self) self.UTILS = UTILS(self) self.settings = Settings(self) self.EME = EverythingMe(self) self.actions = Actions(self.marionette) try: self.apps.set_permission('Homescreen', 'geolocation', 'deny') self.apps.set_permission('Smart Collections', 'geolocation', 'deny') except: self.UTILS.reporting.logComment("Unable to automatically set geolocation permission.") def tearDown(self): # Restart device to restore collections self.device.restart_b2g() GaiaTestCase.setUp(self) self.UTILS.reporting.reportResults() GaiaTestCase.tearDown(self) def test_run(self): self.UTILS.iframe.switchToFrame(*DOM.Home.frame_locator) categories = self.UTILS.element.getElements(DOM.EME.all_collections, "All collections") for cat in categories: name = self.marionette.find_element('css selector', 'span.title', cat.id).text self.UTILS.reporting.debug("** Removing collection: {}".format(name)) self.actions.long_press(cat, 2).perform() delete_btn = ("xpath", DOM.Home.app_delete_icon_xpath.format(name)) delete_button = self.UTILS.element.getElement(delete_btn, "Delete button", False, 30, True) delete_button.tap() delete = self.UTILS.element.getElement(DOM.Home.app_confirm_delete, "Confirm app delete button") delete.tap() self.UTILS.element.waitForNotElements(DOM.EME.all_collections, "All collections", timeout=10)
def _flick_to_month(self, direction): """Flick current monthly calendar to next or previous month. @param direction: flick to next month if direction='next', else flick to previous month """ action = Actions(self.marionette) month = self.marionette.find_element( *self._current_monthly_calendar_locator) month_year = self.current_month_year x_start = (month.size['width'] / 100) * (direction == 'next' and 90 or 10) x_end = (month.size['width'] / 100) * (direction == 'next' and 10 or 90) y_start = month.size['height'] / 4 y_end = month.size['height'] / 4 action.flick(month, x_start, y_start, x_end, y_end, 200).perform() Wait(self.marionette).until(lambda m: self.current_month_year != month_year)
def setUp(self): # Code to execute before a tests are run. MarionetteTestCase.setUp(self) self.actions = Actions(self.marionette) # The carets to be tested. self.carets_tested_pref = None # The carets to be disabled in this test suite. self.carets_disabled_pref = None
def setUp(self): # Code to execute before a test is being run. super(CommonCaretTestCase, self).setUp() self.actions = Actions(self.marionette) # The caret to be tested. self.caret_tested_pref = None # The caret to be disabled in this test suite. self.caret_disabled_pref = None self.caret_timeout_ms_pref = None
def setUp(self): MarionetteTestCase.setUp(self) if self.marionette.session_capabilities['platformName'] == 'DARWIN': self.mod_key = Keys.META else: self.mod_key = Keys.CONTROL test_html = self.marionette.absolute_url("javascriptPage.html") self.marionette.navigate(test_html) self.reporter_element = self.marionette.find_element("id", "keyReporter") self.reporter_element.click() self.key_action = Actions(self.marionette)
def setUp(self): # Code to execute before every test is running. 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)
def setUp(self): # Code to execute before a tests are run. super(AccessibleCaretSelectionModeTestCase, self).setUp() self.carets_tested_pref = 'layout.accessiblecaret.enabled' self.prefs = { 'layout.word_select.eat_space_to_next_word': False, 'layout.accessiblecaret.use_long_tap_injector': False, self.carets_tested_pref: True, } self.marionette.set_prefs(self.prefs) self.actions = Actions(self.marionette)
def setUp(self): # Code to execute before every test is running. super(AccessibleCaretCursorModeTestCase, self).setUp() self.caret_tested_pref = 'layout.accessiblecaret.enabled' self.caret_timeout_ms_pref = 'layout.accessiblecaret.timeout_ms' self.prefs = { self.caret_tested_pref: True, self.caret_timeout_ms_pref: 0, } self.marionette.set_prefs(self.prefs) self.actions = Actions(self.marionette)
def setUp(self): super(TestKeyActions, self).setUp() if self.marionette.session_capabilities["platformName"] == "darwin": self.mod_key = Keys.META else: self.mod_key = Keys.CONTROL test_html = self.marionette.absolute_url("javascriptPage.html") self.marionette.navigate(test_html) self.reporter_element = self.marionette.find_element(By.ID, "keyReporter") self.reporter_element.click() self.key_action = Actions(self.marionette)
class element(object): def __init__(self, parent): self.parent = parent self.marionette = parent.marionette self.actions = Actions(self.marionette) def getElement(self, elem, msg, is_displayed=True, timeout=5, stop_on_error=True): """ Returns an element, or False it it's not found """ x = self.getElements(elem, msg, is_displayed, timeout, stop_on_error) if x: # We're expecting ONE element back (it has different methods if it's one). return x[0] else: return False def getElements(self, elem, msg, is_displayed=True, timeout=5, stop_on_error=True): """ Returns a list of matching elements, or False if none are found """ boolEl = self.waitForElements(elem, msg, is_displayed, timeout, stop_on_error) if boolEl: el = self.marionette.find_elements(*elem) return el else: return False def headerCheck(self, value): """ Returns the header that matches a string. NOTE: ALL headers in this iframe return true for ".is_displayed()"! """ is_ok = False try: self.parent.parent.wait_for_element_present(*DOM.GLOBAL.app_head, timeout=1) headerNames = self.marionette.find_elements(*DOM.GLOBAL.app_head) for i in headerNames: if i.text == value: if i.is_displayed(): is_ok = True break except: is_ok = False self.parent.test.test(is_ok, "Header is \"" + value + "\".") return is_ok def move_scroller(self, scroller, forward=True): """Move the scroller one item forward or backwards. """ x_pos = scroller.size['width'] / 2 y_start = scroller.size['height'] / 2 y_end = -scroller.size['height'] if forward else scroller.size['height'] self.actions.flick(scroller, x_pos, y_start, x_pos, y_end, 100) self.actions.perform() def set_scroller_val(self, scroller_elem, number): """ Set the numeric value of a scroller (only works with numbers right now). """ current_value = int(scroller_elem.find_element(*DOM.GLOBAL.scroller_curr_val).text) # Now flick the scroller as many times as required n = int(number) while n != current_value: # Do we need to go forwards or backwards? if n > int(current_value): self.move_scroller(scroller_elem, True) if n < int(current_value): self.move_scroller(scroller_elem, False) # Get the new 'current_value'. current_value = int(scroller_elem.find_element(*DOM.GLOBAL.scroller_curr_val).text) # From gaiatest Clock -> regions -> alarm.py def _flick_menu_up(self, locator): self.parent.parent.wait_for_element_displayed(*self._current_element(*locator), timeout=2) current_element = self.marionette.find_element(*self._current_element(*locator)) next_element = self.marionette.find_element(*self._next_element(*locator)) # TODO: update this with more accurate Actions action = Actions(self.marionette) action.press(next_element) action.move(current_element) action.release() action.perform() def _flick_menu_down(self, locator): self.parent.parent.wait_for_element_displayed(*self._current_element(*locator), timeout=2) current_element = self.marionette.find_element(*self._current_element(*locator)) next_element = self.marionette.find_element(*self._next_element(*locator)) # TODO: update this with more accurate Actions action = Actions(self.marionette) action.press(current_element) action.move(next_element) action.release() action.perform() def _current_element(self, method, target): self.parent.reporting.debug("*** Finding current element for target {}".format(target)) return (method, '{}.picker-unit.selected'.format(target)) def _next_element(self, method, target): self.parent.reporting.debug("*** Finding next element for target {}".format(target)) return (method, '{}.picker-unit.selected + div'.format(target)) def simulateClick(self, element): self.marionette.execute_script(""" /** * Helper method to simulate clicks on iFrames which is not currently * working in the Marionette JS Runner. * @param {Marionette.Element} element The element to simulate the click on. **/ var event = new MouseEvent('click', { 'view': window, 'bubbles': true, 'cancelable': true }); arguments[0].dispatchEvent(event); """, script_args=[element]) def simulateClickAtPos(self, element, posX, posY): self.parent.reporting.logResult('info', 'Simulating click....') self.marionette.execute_script(""" /** * Helper method to simulate clicks on iFrames which is not currently * working in the Marionette JS Runner. * @param {Marionette.Element} element The element to simulate the click on. **/ var event = document.createEvent('MouseEvents'); event.initMouseEvent( 'click', true, true, window, 0, 0, 0, arguments[1], arguments[2], false, false, false, false, 0, null ); arguments[0].dispatchEvent(event); """, script_args=[element, posX, posY]) def waitForElements(self, elem, msg, is_displayed=True, timeout=5, stop_on_error=True): """ Waits for an element to be displayed and captures the error if not """ is_ok = True msg = u"" + msg try: if is_displayed: msg = u"{} displayed within {} seconds.|{}".format(msg, timeout, elem) self.parent.parent.wait_for_element_displayed(*elem, timeout=timeout) else: msg = u"{} present within {} seconds.|{}".format(msg, timeout, elem) self.parent.parent.wait_for_element_present(*elem, timeout=timeout) except Exception: is_ok = False self.parent.test.test(is_ok, msg, stop_on_error) return is_ok def waitForNotElements(self, elem, msg, is_displayed=True, timeout=5, stop_on_error=True): """ Waits for an element to be displayed and captures the error if not """ is_ok = True try: if is_displayed: msg = "{} no longer displayed within {} seconds.|{}".format(msg, timeout, elem) self.parent.parent.wait_for_element_not_displayed(*elem, timeout=timeout) else: msg = "{} no longer present within {} seconds.|{}".format(msg, timeout, elem) self.parent.parent.wait_for_element_not_present(*elem, timeout=timeout) except: is_ok = False self.parent.test.test(is_ok, msg, stop_on_error) return is_ok def getElementByXpath(self, path): """ Use this function when normal getElement did not work """ return self.marionette.execute_script(""" return document.evaluate(arguments[0], document, null, 9, null).singleNodeValue; """, script_args=[path]) def getParent(self, element): """ Gets the element's parent. Can be called recursively """ return self.marionette.execute_script(""" return arguments[0].parentNode; """, script_args=[element]) def getChildren(self, element): """ Gets the element's children """ return self.marionette.execute_script(""" return arguments[0].children; """, script_args=[element]) def find_nested(self, context, css_selector): return self.marionette.execute_script(""" return arguments[0].querySelector(arguments[1]) """, script_args=[context, css_selector]) def get_css_value(self, element, css_property): """ Gets the value of a certain css property. """ return self.marionette.execute_script(""" function getStyle (el, styleProp) { if (el.currentStyle) var y = x.currentStyle[styleProp]; else if (window.getComputedStyle) var y = document.defaultView.getComputedStyle(el,null) .getPropertyValue(styleProp); return y; } return getStyle(arguments[0], arguments[1]) """, script_args=[element, css_property]) def is_ellipsis_active(self, element): """ Checks whether a certain element is really ellipsed when its content overflows its width """ return self.marionette.execute_script(""" function isEllipsisActive(element) { return (element.offsetWidth < element.scrollWidth); } return isEllipsisActive(arguments[0]) """, script_args=[element]) def scroll_into_view(self, element): self.marionette.execute_script(""" arguments[0].scrollIntoView(); """, script_args=[element]) def perform_action_over_element(self, locator, action, position=None): script = """ var _locatorMap = { "id": document.getElementById, "class name": document.getElementsByClassName, "css selector": document.querySelector, "xpath": function () { return document.evaluate(arguments[0], document, null, 9, null).singleNodeValue }, "tag name": document.getElementsByTagName }; // TODO - Add more events here var _actionMap = { "click": new MouseEvent('click', { 'view': window, 'bubbles': true, 'cancelable': true }), //HTMLElement.prototype.click } var location_method = arguments[0][0]; var locator = arguments[0][1]; var action = arguments[1]; var position = arguments[2]; if (position) { var element = _locatorMap[location_method].call(document, locator)[position]; } else { if ((locator === "class name") || (locator === "tag name")) { var e = 'JavaScriptException: InvalidParametersException: ' var msg = 'If using "class name" or "tag name", it is mandatory to specify a position' throw e + msg } var element = _locatorMap[location_method].call(document, locator); } if (element) { if (_actionMap.hasOwnProperty(action)) { element.dispatchEvent(_actionMap[action]) } else { var e = 'JavaScriptException: InvalidParametersException: ' var msg = 'Specified action <' + action + '> not supported'; throw e + msg } } """ self.marionette.execute_script(script, script_args=[list(locator), action, position])
def setUp(self): # Code to execute before a tests are run. MarionetteTestCase.setUp(self) self.actions = Actions(self.marionette)
def long_tap_to_install(self): Actions(self.marionette).long_press(self.root_element, 2).perform()
def _tap_page_switching_key(self, val): locator = (self._page_switching_key_locator[0], self._page_switching_key_locator[1] % val) key = Wait(self.marionette).until(expected.element_present(*locator)) Wait(self.marionette).until(expected.element_displayed(key)) Actions(self.marionette).press(key).release().perform()
class Dialer(object): """Object representing the Dialer application. """ def __init__(self, p_parent): self.apps = p_parent.apps self.data_layer = p_parent.data_layer self.parent = p_parent self.marionette = p_parent.marionette self.UTILS = p_parent.UTILS self.actions = Actions(self.marionette) self.app_name = "Phone" def launch(self): """ Launch the app It's called a different name (Phone) to the everyone knows it as, so hardcode it! """ self.app = self.apps.launch(self.app_name) self.UTILS.element.waitForNotElements(DOM.GLOBAL.loading_overlay, self.__class__.__name__ + " app - loading overlay") return self.app def _cancel_addNumberToContact(self): self.UTILS.iframe.switchToFrame(*DOM.Contacts.frame_locator) self.UTILS.element.waitForElements( ("xpath", "//h1[text()='{}']".format(_("Contacts"))), "'Select contact' header") self.UTILS.element.getElement(DOM.Dialer.contact_list_header, "Header").tap(25, 25) def _complete_addNumberToContact(self, p_num, p_name): """ Finishes the process of adding a number to an existing contact (used bu addThisNumberToContact() etc...).<br> Handles switching frames etc... and finishes with you back in the dialer. """ self.UTILS.iframe.switchToFrame(*DOM.Contacts.frame_locator) self.UTILS.element.waitForElements( ("xpath", "//h1[text()='{}']".format(_("Contacts"))), "'Select contact' header") y = self.UTILS.element.getElements(DOM.Contacts.view_all_contact_list, "All contacts list") boolOK = False for i in y: if p_name in i.text: self.UTILS.reporting.logResult("info", "Contact '{}' found in all contacts.".format(p_num)) i.tap() boolOK = True break self.UTILS.test.test(boolOK, "Succesfully selected contact from list.") self.UTILS.element.waitForElements(DOM.Contacts.edit_contact_header, "'Edit contact' header") # Test for an input field for number_<x> contaiing our number. self.UTILS.element.waitForElements(("xpath", DOM.Contacts.phone_field_xpath.format(p_num)), "Phone field containing {}".format(p_num)) # Hit 'update' to save the changes to this contact. done_button = self.UTILS.element.getElement(DOM.Contacts.edit_update_button, "'Update' button") done_button.tap() # Verify that the contacts app is closed and we are returned to the call log. self.marionette.switch_to_frame() self.UTILS.element.waitForNotElements(("xpath", "//iframe[contains(@{}, '{}')]". format(DOM.Contacts.frame_locator[0], DOM.Contacts.frame_locator[1])), "COntacts frame") self.UTILS.iframe.switchToFrame(*DOM.Dialer.frame_locator) def addThisNumberToContact(self, p_name): # Adds the current number to existing contact. x = self.UTILS.element.getElement(DOM.Dialer.phone_number, "Phone number field", False) dialer_num = x.get_attribute("value") x = self.UTILS.element.getElement(DOM.Dialer.add_to_contacts_button, "Add to contacts button") x.tap() x = self.UTILS.element.getElement(DOM.Dialer.add_to_existing_contact_btn, "Add to existing contact button") x.tap() self._complete_addNumberToContact(dialer_num, p_name) def callLog_createContact(self, entry, p_open_call_log=True): """ Creates a new contact from the call log (only as far as the contacts app opening). If p_open_call_log is set to False it will assume you are already in the call log. """ if p_open_call_log: self.open_call_log() self.callLog_long_tap(entry) self.callLog_long_tap_select_action( DOM.Dialer.call_log_numtap_create_new, "Create new contact button", call_info=True) self.UTILS.iframe.switchToFrame(*DOM.Contacts.frame_locator) self.UTILS.element.waitForElements(DOM.Contacts.add_contact_header, "'Add contact' header") def callLog_addToContact(self, phone_number, contact_name, p_open_call_log=True, cancel_process=False): """ Adds this number in the call log to an existing contact (and returns you to the call log). If p_open_call_log is set to False it will assume you are already in the call log. """ if p_open_call_log: self.open_call_log() self.callLog_long_tap(phone_number) time.sleep(1) self.callLog_long_tap_select_action( DOM.Dialer.call_log_numtap_add_to_existing, "Add to existing contact button", call_info=True) if cancel_process: self._cancel_addNumberToContact() else: self._complete_addNumberToContact(phone_number, contact_name) def callLog_long_tap(self, phone_number): entry = self.UTILS.element.getElement(("xpath", DOM.Dialer.call_log_number_xpath.format(phone_number)), "The call log for number {}".format(phone_number)) self.actions.long_press(entry, 3).perform() def callLog_long_tap_select_action(self, locator, msg="Option chosen", call_info=True): if call_info: call_info = self.UTILS.element.getElement(DOM.Dialer.call_log_numtap_call_info, "Call information button") call_info.tap() option = self.UTILS.element.getElement(locator, msg, True, 10) option.tap() def callLog_call(self, p_num): own_num = self.UTILS.general.get_config_variable("phone_number", "custom") # Calls a number from the call log. try: self.parent.wait_for_element_displayed(*DOM.Dialer.call_log_filter, timeout=1) except: self.open_call_log() entry = self.UTILS.element.getElement(("xpath", DOM.Dialer.call_log_number_xpath.format(p_num)), "The call log for number {}".format(p_num)) entry.tap() if own_num == p_num: time.sleep(2) # self.marionette.switch_to_frame() x = self.UTILS.element.getElement(DOM.Dialer.call_busy_button_ok, "OK button (callLog_call)") x.tap() else: time.sleep(1) self.UTILS.iframe.switchToFrame(*DOM.Dialer.frame_locator_calling) self.UTILS.element.waitForElements(("xpath", DOM.Dialer.outgoing_call_numberXP.format(p_num)), "Outgoing call found with number matching {}".format(p_num)) def callLog_clearAll(self): """ Wipes all entries from the call log. """ try: self.parent.wait_for_element_displayed(*DOM.Dialer.call_log_filter, timeout=1) except: self.open_call_log() try: self.parent.wait_for_element_displayed(*DOM.Dialer.call_log_no_calls_msg, timeout=1) except: self.UTILS.reporting.logResult("info", "Some numbers are in the call log here - removing them ...") edit_btn = self.UTILS.element.getElement(DOM.Dialer.call_log_edit_btn, "Edit button") edit_btn.tap() """Here something weird is happening, since the form where this button should appear, remains hidden. Thus, when we try to get the button, it won't appear. Then, we have have to use raw JavaScript in order to obtain the button and click on it.""" self.parent.wait_for_element_present(*DOM.Dialer.call_log_edit_selAll, timeout=10) self.marionette.execute_script("document.getElementById('{}').click();". format(DOM.Dialer.call_log_edit_selAll[1])) self.parent.wait_for_element_present(*DOM.Dialer.call_log_edit_delete, timeout=2) self.marionette.execute_script("document.getElementById('{}').click();". format(DOM.Dialer.call_log_edit_delete[1])) confirm_delete = self.UTILS.element.getElement(DOM.Dialer.call_log_confirm_delete, "Confirm button") confirm_delete.tap() self.UTILS.element.waitForElements(DOM.Dialer.call_log_no_calls_msg, "'No calls ...' message") def callLog_clearSome(self, p_entryNumbers): """ Wipes entries from the call log, using p_entryNumbers as an array of numbers. For example: callLog_clearSome([1,2,3]) will remove the first 3. <br><b>NOTE:</b> the first item is 1, <i>not</i> 0. """ try: self.parent.wait_for_element_displayed(*DOM.Dialer.call_log_filter, timeout=1) except: self.open_call_log() boolLIST = True try: self.parent.wait_for_element_displayed(*DOM.Dialer.call_log_no_calls_msg, timeout=1) boolLIST = False except: pass if boolLIST: """ At the moment, the 'edit' div looks like it's not displayed, so Marionette can't tap it. For this reason I'm using JS to click() instead. """ self.UTILS.reporting.logResult("info", "Some numbers are in the call log here - removing them ...") x = self.UTILS.element.getElement(DOM.Dialer.call_log_edit_btn, "Edit button") x.tap() """ The edit mode doens't seem to be 'displayed', so we have to work around that at the moment. """ time.sleep(2) self.parent.wait_for_element_present(*DOM.Dialer.call_log_edit_header, timeout=2) _els = ("xpath", "//ol[@class='log-group']//li") x = self.UTILS.element.getElements(_els, "Call log items", False) _precount = len(x) self.UTILS.reporting.logResult("info", "{} items found.".format(_precount)) for i in p_entryNumbers: if i != 0: _precount = _precount - 1 x[i - 1].tap() self.parent.wait_for_element_present(*DOM.Dialer.call_log_edit_delete, timeout=2) self.marionette.execute_script("document.getElementById('{}').click();". format(DOM.Dialer.call_log_edit_delete[1])) # Click on Delete button delete_btn = self.UTILS.element.getElement(DOM.GLOBAL.confirm_form_delete_btn, "Confirm delete") delete_btn.tap() try: _postcount = self.UTILS.element.getElements(_els, "Call log items", False) _postcount = len(_postcount) except: _postcount = 0 self.UTILS.test.test(_postcount == _precount, "{} numbers are left after deletion (there are {}).".format(_precount, _postcount)) def tap_on_call_button(self): call_number_button = self.UTILS.element.getElement(DOM.Dialer.call_number_button, "Call number button") self.UTILS.element.simulateClick(call_number_button) def call_this_number(self): """ Calls the current number. """ self.tap_on_call_button() self.UTILS.iframe.switchToFrame(*DOM.Dialer.frame_locator_calling) self.UTILS.element.waitForElements(DOM.Dialer.outgoing_call_locator, "Outgoing call locator", True, 5) def call_this_number_and_hangup(self, delay): self.call_this_number() time.sleep(delay) self.hangUp() def get_and_accept_fdn_warning(self, phone_number): # Check warning message self.UTILS.element.waitForElements(DOM.Settings.fdn_warning_header, "Waiting for FDN warning header", True, 10) self.UTILS.element.waitForElements(DOM.Settings.fdn_warning_body, "Waiting for FDN warning body") body = self.marionette.find_element(*DOM.Settings.fdn_warning_body) self.UTILS.reporting.log_to_file("body.text: {} msg: {}".format(body.text, DOM.Dialer.fdn_warning_msg. format(phone_number))) self.UTILS.test.test(body.text == DOM.Dialer.fdn_warning_msg.format(phone_number), "Correct FDN warning message") ok_btn = self.UTILS.element.getElement(DOM.Settings.fdn_warning_ok, "OK button") ok_btn.tap() def createContactFromThisNum(self): """ Creates a new contact from the number currently in the dialer (doesn't fill in the contact details). """ self.UTILS.iframe.switchToFrame(*DOM.Dialer.frame_locator) add_btn = self.UTILS.element.getElement(DOM.Dialer.add_to_contacts_button, "Add to contacts button") add_btn.tap() create_btn = self.UTILS.element.getElement(DOM.Dialer.create_new_contact_btn, "Create new contact button") create_btn.tap() # Switch to the contacts frame. self.UTILS.iframe.switchToFrame(*DOM.Contacts.frame_locator) def createMultipleCallLogEntries(self, phone_number, entries_number): """ Put a number in the call log multiple times (done by manipulating the device time). Leaves you in the call log. """ today = datetime.datetime.today() for i in range(entries_number): delta = datetime.timedelta(days=i) new_date = today - delta self.UTILS.date_and_time.setTimeToSpecific(p_day=new_date.day, p_month=new_date.month) self.enterNumber(phone_number) self.call_this_number_and_hangup(delay=7) # This needs to be done bcs sometimes (50%) the Dialer app crushes after hanging up self.apps.kill_all() time.sleep(2) self.launch() def enterNumber(self, number, validate=True): """ Enters a number into the dialer using the keypad. """ try: self.parent.wait_for_element_displayed(*DOM.Dialer.phone_number, timeout=1) except: keypad_selector = self.UTILS.element.getElement(DOM.Dialer.option_bar_keypad, "Keypad option selector") keypad_selector.tap() self.UTILS.element.waitForElements(DOM.Dialer.phone_number, "Phone number area") for i in str(number): if i == "+": plus_symbol = self.UTILS.element.getElement(("xpath", DOM.Dialer.dialer_button_xpath.format(0)), "keypad symbol '+'") self.actions.long_press(plus_symbol, 2).perform() else: number_symbol = self.UTILS.element.getElement(("xpath", DOM.Dialer.dialer_button_xpath.format(i)), "keypad number {}".format(i)) number_symbol.tap() # Verify that the number field contains the expected number. if validate: dialed_num = self.marionette.execute_script("return window.wrappedJSObject.KeypadManager._phoneNumber") self.UTILS.reporting.debug(u"** Dialer_num entered: [{}]".format(dialed_num)) self.UTILS.test.test( str(number) in dialed_num, u"Dialed number matches the original number".format(number, dialed_num)) def clear_dialer(self): """ Deletes a single number from the dialer """ try: self.parent.wait_for_element_displayed(*DOM.Dialer.keypad_delete) delete = self.marionette.find_element(*DOM.Dialer.keypad_delete) delete.tap() except: return def clear_dialer_all(self): """ Clears all dialer input area """ try: self.parent.wait_for_element_displayed(*DOM.Dialer.keypad_delete) delete = self.marionette.find_element(*DOM.Dialer.keypad_delete) self.actions.long_press(delete, 3).perform() except: return def answer(self): self.marionette.switch_to_frame() elDef = ("xpath", "//iframe[contains(@{}, '{}')]". format(DOM.Dialer.frame_locator_calling[0], DOM.Dialer.frame_locator_calling[1])) self.parent.wait_for_element_displayed(*elDef, timeout=60) frame_calling = self.marionette.find_element(*elDef) if frame_calling: self.UTILS.iframe.switchToFrame(*DOM.Dialer.frame_locator_calling) self.parent.wait_for_element_displayed(*DOM.Dialer.answer_callButton, timeout=1) answer = self.marionette.find_element(*DOM.Dialer.answer_callButton) if answer: answer.tap() def answer_and_hangup(self, delay=5): self.answer() time.sleep(delay) self.parent.wait_for_element_displayed(*DOM.Dialer.hangup_bar_locator, timeout=1) hangup = self.marionette.find_element(*DOM.Dialer.hangup_bar_locator) if hangup: hangup.tap() else: try: self.parent.data_layer.kill_active_call() except: self.UTILS.reporting.logResult("info", "Exception when killing active call via data_layer") pass def hangUp(self): """ Hangs up (assuming we're in the 'calling' frame). """ self.marionette.switch_to_frame() try: self.parent.wait_for_element_displayed(*DOM.Dialer.frame_locator_calling) self.UTILS.iframe.switchToFrame(*DOM.Dialer.frame_locator_calling) self.marionette.find_element(*DOM.Dialer.hangup_bar_locator).tap() self.apps.switch_to_displayed_app() except: self.apps.switch_to_displayed_app() self.parent.wait_for_element_displayed(*DOM.Dialer.call_busy_button_ok, timeout=5) ok_btn = self.marionette.find_element(*DOM.Dialer.call_busy_button_ok) ok_btn.tap() def open_call_log(self): """ Opens the call log. """ x = self.UTILS.element.getElement(DOM.Dialer.option_bar_call_log, "Call log button") x.tap() time.sleep(2) def wait_for_incoming_call(self, phone_number, timeout=30): self.marionette.switch_to_frame() try: self.parent.wait_for_element_displayed(*DOM.Dialer.call_screen_locator, timeout=60) frame = self.marionette.find_element(*DOM.Dialer.call_screen_frame_locator) self.marionette.switch_to_frame(frame) elem = ("xpath", DOM.Dialer.outgoing_call_numberXP.format(phone_number)) self.UTILS.element.waitForElements( elem, "Phone number [{}] is displayed in call_screen frame".format(phone_number)) except: self.UTILS.test.test(False, "No incoming call received", True) def resume_hidden_call(self): self.marionette.switch_to_frame() self.UTILS.statusbar.displayStatusBar() attention = self.marionette.find_element('id', 'attention-window-notifications-container') attention.tap() self.UTILS.iframe.switchToFrame(*DOM.Dialer.frame_locator_calling)
def send_message(self, to_user, message, wait_load=0.5): # Make firefox go to the users page. self.client.navigate("https://www.messenger.com/t/{}".format(to_user)) # Give a little bit of time to load. time.sleep(wait_load) for letter in message: # Make the typing look realistic. keep_down = random.uniform(0.005, 0.010) wait_time = keep_down + random.uniform(0.02, 0.05) # Send off the action action = Actions(self.client) if letter != '\n': action.key_down(letter).wait(keep_down).key_up(letter) else: # Handle multi line messages. action.key_down(Keys.SHIFT).key_down(Keys.ENTER)\ .wait(keep_down).key_up(Keys.SHIFT).key_up(Keys.ENTER) action.perform() # wait for it to complete. time.sleep(wait_time) # Send message. action.key_down('\n').wait(keep_down).key_up('\n') action.perform()
def edge_scroll(marionette, frame, direction, dist, release=True): """edge scroll - performs task switching action. direction = 'LtoR' or 'RtoL' (finger movement direction) dist = percentage of horizontal distance travel, max is 1.0 release = if set to False, the Action object will be returned so the user can complete the release action""" start_x = 0 dist_travelled = 0 time_increment = 0.01 if dist > 1: dist = 1 if direction == 'LtoR': start_x = 0 elif direction == 'RtoL': start_x = frame.rect['width'] dist *= -1 # travel opposite direction limit = dist * frame.rect['width'] dist_unit = limit * time_increment assert isinstance(marionette, object) action = Actions(marionette) action.press(frame, start_x, frame.rect['height'] / 2) # press either the left or right edge while abs(dist_travelled) < abs(limit): action.move_by_offset(dist_unit, 0) action.wait(time_increment) dist_travelled += dist_unit if release: action.release() action.perform() time.sleep( 2 ) # compensate for the time taken for edge scroll to bring another app to active return action
class AccessibleCaretSelectionModeTestCase(MarionetteTestCase): '''Test cases for AccessibleCaret under selection mode.''' # Element IDs. _input_id = 'input' _input_padding_id = 'input-padding' _textarea_id = 'textarea' _textarea2_id = 'textarea2' _textarea_one_line_id = 'textarea-one-line' _textarea_rtl_id = 'textarea-rtl' _contenteditable_id = 'contenteditable' _contenteditable2_id = 'contenteditable2' _content_id = 'content' _content2_id = 'content2' _non_selectable_id = 'non-selectable' # Test html files. _selection_html = 'test_carets_selection.html' _multipleline_html = 'test_carets_multipleline.html' _multiplerange_html = 'test_carets_multiplerange.html' _longtext_html = 'test_carets_longtext.html' _iframe_html = 'test_carets_iframe.html' _display_none_html = 'test_carets_display_none.html' def setUp(self): # 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, 'layout.accessiblecaret.use_long_tap_injector': False, self.carets_tested_pref: True, } self.marionette.set_prefs(self.prefs) self.actions = Actions(self.marionette) 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 words = tokens[1::2] # collect word at even indices if ordinal >= len(words): raise IndexError('Only %d words in text, but got ordinal %d' % (len(words), ordinal)) # Cursor position of the targeting word is behind the the first # character in the word. For example, offset to 'def' in 'abc def' is # between 'd' and 'e'. offset = len(spaces[0]) + 1 offset += sum(len(words[i]) + len(spaces[i + 1]) for i in range(ordinal)) return offset def test_word_offset(self): text = ' ' * 3 + 'abc' + ' ' * 3 + 'def' self.assertTrue(self.word_offset(text, 0), 4) self.assertTrue(self.word_offset(text, 1), 10) with self.assertRaises(IndexError): self.word_offset(text, 2) def word_location(self, el, ordinal): '''Get the location (x, y) of the ordinal-th word in el. The ordinal starts from 0. Note: this function has a side effect which changes focus to the target element el. ''' sel = SelectionManager(el) offset = self.word_offset(sel.content, ordinal) # Move the blinking cursor to the word. el.tap() 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. ''' return self.marionette.execute_script(''' let rect = arguments[0].getBoundingClientRect(); return {x: rect.x, y:rect.y, width: rect.width, height: rect.height}; ''', script_args=[el]) def long_press_on_location(self, el, x=None, y=None): '''Long press the location (x, y) to select a word. If no (x, y) are given, it will be targeted at the center of the element. On Windows, those spaces after the word will also be selected. This function sends synthesized eMouseLongTap to gecko. ''' rect = self.rect_relative_to_window(el) target_x = rect['x'] + (x if x is not None else rect['width'] // 2) target_y = rect['y'] + (y if y is not None else rect['height'] // 2) self.marionette.execute_script(''' let Ci = Components.interfaces; let utils = window.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIDOMWindowUtils); utils.sendTouchEventToWindow('touchstart', [0], [arguments[0]], [arguments[1]], [1], [1], [0], [1], 1, 0); utils.sendMouseEventToWindow('mouselongtap', arguments[0], arguments[1], 0, 1, 0); utils.sendTouchEventToWindow('touchend', [0], [arguments[0]], [arguments[1]], [1], [1], [0], [1], 1, 0); ''', script_args=[target_x, target_y], sandbox='system') def long_press_on_word(self, el, wordOrdinal): x, y = self.word_location(el, wordOrdinal) self.long_press_on_location(el, x, y) def to_unix_line_ending(self, s): """Changes all Windows/Mac line endings in s to UNIX line endings.""" return s.replace('\r\n', '\n').replace('\r', '\n') @parameterized(_input_id, el_id=_input_id) @parameterized(_textarea_id, el_id=_textarea_id) @parameterized(_textarea_rtl_id, el_id=_textarea_rtl_id) @parameterized(_contenteditable_id, el_id=_contenteditable_id) @parameterized(_content_id, el_id=_content_id) def test_long_press_to_select_a_word(self, el_id): self.open_test_html(self._selection_html) el = self.marionette.find_element(By.ID, el_id) self._test_long_press_to_select_a_word(el) def _test_long_press_to_select_a_word(self, el): sel = SelectionManager(el) original_content = sel.content words = original_content.split() self.assertTrue(len(words) >= 2, 'Expect at least two words in the content.') target_content = words[0] # Goal: Select the first word. self.long_press_on_word(el, 0) # Ignore extra spaces selected after the word. self.assertEqual(target_content, sel.selected_content) @parameterized(_input_id, el_id=_input_id) @parameterized(_textarea_id, el_id=_textarea_id) @parameterized(_textarea_rtl_id, el_id=_textarea_rtl_id) @parameterized(_contenteditable_id, el_id=_contenteditable_id) @parameterized(_content_id, el_id=_content_id) def test_drag_carets(self, el_id): self.open_test_html(self._selection_html) el = self.marionette.find_element(By.ID, el_id) 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 carets at the end of the content for later # use. el.tap() sel.select_all() 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.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) @parameterized(_textarea_id, el_id=_textarea_id) @parameterized(_textarea_rtl_id, el_id=_textarea_rtl_id) @parameterized(_contenteditable_id, el_id=_contenteditable_id) @parameterized(_content_id, el_id=_content_id) def test_minimum_select_one_character(self, el_id): self.open_test_html(self._selection_html) el = self.marionette.find_element(By.ID, el_id) self._test_minimum_select_one_character(el) @parameterized(_textarea2_id, el_id=_textarea2_id) @parameterized(_contenteditable2_id, el_id=_contenteditable2_id) @parameterized(_content2_id, el_id=_content2_id) def test_minimum_select_one_character2(self, el_id): self.open_test_html(self._multipleline_html) el = self.marionette.find_element(By.ID, el_id) 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 carets at the end of the content for later # use. sel.select_all() 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.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.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) @parameterized(_input_id + '_to_' + _content_id, el1_id=_input_id, el2_id=_content_id) @parameterized(_textarea_id + '_to_' + _input_id, el1_id=_textarea_id, el2_id=_input_id) @parameterized(_textarea_id + '_to_' + _contenteditable_id, el1_id=_textarea_id, el2_id=_contenteditable_id) @parameterized(_textarea_id + '_to_' + _content_id, el1_id=_textarea_id, el2_id=_content_id) @parameterized(_contenteditable_id + '_to_' + _input_id, el1_id=_contenteditable_id, el2_id=_input_id) @parameterized(_contenteditable_id + '_to_' + _textarea_id, el1_id=_contenteditable_id, el2_id=_textarea_id) @parameterized(_contenteditable_id + '_to_' + _content_id, el1_id=_contenteditable_id, el2_id=_content_id) @parameterized(_content_id + '_to_' + _input_id, el1_id=_content_id, el2_id=_input_id) @parameterized(_content_id + '_to_' + _textarea_id, el1_id=_content_id, el2_id=_textarea_id) @parameterized(_content_id + '_to_' + _contenteditable_id, el1_id=_content_id, el2_id=_contenteditable_id) def test_long_press_changes_focus_from(self, el1_id, el2_id): '''Test the focus could be changed from el1 to el2 by long press. If the focus is changed to e2 successfully, the carets should appear and could be dragged. ''' # Goal: Tap to focus el1, and then select the first character on # el2. # We want to collect the location of the first word in el2 here # since self.word_location() has the side effect which would # change the focus. self.open_test_html(self._selection_html) el1 = self.marionette.find_element(By.ID, el1_id) el2 = self.marionette.find_element(By.ID, el2_id) x, y = self.word_location(el2, 0) el1.tap() self._test_minimum_select_one_character(el2, x=x, y=y) @parameterized(_input_id, el_id=_input_id) @parameterized(_textarea_id, el_id=_textarea_id) @parameterized(_textarea_rtl_id, el_id=_textarea_rtl_id) @parameterized(_contenteditable_id, el_id=_contenteditable_id) def test_focus_not_changed_by_long_press_on_non_selectable(self, el_id): self.open_test_html(self._selection_html) el = self.marionette.find_element(By.ID, el_id) non_selectable = self.marionette.find_element(By.ID, self._non_selectable_id) # Goal: Focus remains on the editable element el after long pressing on # the non-selectable element. sel = SelectionManager(el) self.long_press_on_word(el, 0) self.long_press_on_location(non_selectable) active_sel = SelectionManager(self.marionette.get_active_element()) self.assertEqual(sel.content, active_sel.content) @parameterized(_input_id, el_id=_input_id) @parameterized(_textarea_id, el_id=_textarea_id) @parameterized(_textarea_rtl_id, el_id=_textarea_rtl_id) @parameterized(_contenteditable_id, el_id=_contenteditable_id) @parameterized(_content_id, el_id=_content_id) def test_handle_tilt_when_carets_overlap_each_other(self, el_id): '''Test tilt handling when carets overlap to each other. Let the two carets overlap each other. If they are set to tilted successfully, tapping the tilted carets should not cause the selection to be collapsed and the carets should be draggable. ''' self.open_test_html(self._selection_html) el = self.marionette.find_element(By.ID, el_id) 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 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.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.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 el.tap(left_caret_left_edge_x + 2, caret3_y) right_caret_right_edge_x = (caret4_x + caret_margin_left + tilt_right_margin_left + caret_width) 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): '''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(self._multiplerange_html) 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.second_caret_location() self.long_press_on_word(sel6, 0) 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.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.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.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(self._multiplerange_html) 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.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.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 def test_caret_position_after_changing_orientation_of_device(self): '''Bug 1094072 If positions of carets are updated correctly, they should be draggable. ''' self.open_test_html(self._longtext_html) 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.carets_location() self.marionette.set_orientation('landscape') (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') self.assertEqual(self.to_unix_line_ending(sel.selected_content), 'o') def test_select_word_inside_an_iframe(self): '''Bug 1088552 The scroll offset in iframe should be taken into consideration properly. In this test, we scroll content in the iframe to the bottom to cause a huge offset. If we use the right coordinate system, selection should work. Otherwise, it would be hard to trigger select word. ''' self.open_test_html(self._iframe_html) iframe = self.marionette.find_element(By.ID, 'frame') # switch to inner iframe and scroll to the bottom self.marionette.switch_to_frame(iframe) self.marionette.execute_script( 'document.getElementById("bd").scrollTop += 999') # long press to select bottom text body = self.marionette.find_element(By.ID, 'bd') sel = SelectionManager(body) self._bottomtext = self.marionette.find_element(By.ID, 'bottomtext') self.long_press_on_location(self._bottomtext) self.assertNotEqual(self.to_unix_line_ending(sel.selected_content), '') def test_carets_initialized_in_display_none(self): '''Test AccessibleCaretEventHub is properly initialized on a <html> with display: none. ''' self.open_test_html(self._display_none_html) html = self.marionette.find_element(By.ID, 'html') content = self.marionette.find_element(By.ID, 'content') # Remove 'display: none' from <html> self.marionette.execute_script( 'arguments[0].style.display = "unset";', script_args=[html] ) # If AccessibleCaretEventHub is initialized successfully, select a word # should work. self._test_long_press_to_select_a_word(content) def test_long_press_to_select_when_partial_visible_word_is_selected(self): self.open_test_html(self._selection_html) el = self.marionette.find_element(By.ID, self._input_id) sel = SelectionManager(el) # To successfully select the second word while the first word is being # selected, use sufficient spaces between 'a' and 'b' to avoid the # second caret covers on the second word. original_content = 'aaaaaaaa bbbbbbbb' el.clear() el.send_keys(original_content) words = original_content.split() # We cannot use self.long_press_on_word() directly since it has will # change the cursor position which affects this test. We have to store # the position of word 0 and word 1 before long-pressing to select the # word. word0_x, word0_y = self.word_location(el, 0) word1_x, word1_y = self.word_location(el, 1) self.long_press_on_location(el, word0_x, word0_y) self.assertEqual(words[0], sel.selected_content) self.long_press_on_location(el, word1_x, word1_y) 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.carets_location() self.actions.flick(el, caret2_x, caret2_y, caret1_x, caret1_y).perform() self.assertEqual(words[0][0], sel.selected_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_carets_not_jump_when_dragging_to_editable_content_boundary(self, el_id): self.open_test_html(self._selection_html) el = self.marionette.find_element(By.ID, el_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 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() 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)
class TestMouseAction(MarionetteTestCase): def setUp(self): MarionetteTestCase.setUp(self) if self.marionette.session_capabilities["platformName"] == "darwin": self.mod_key = Keys.META else: self.mod_key = Keys.CONTROL self.action = Actions(self.marionette) def test_click_action(self): test_html = self.marionette.absolute_url("test.html") self.marionette.navigate(test_html) link = self.marionette.find_element(By.ID, "mozLink") self.action.click(link).perform() self.assertEqual( "Clicked", self.marionette.execute_script( "return document.getElementById('mozLink').innerHTML")) def test_clicking_element_out_of_view_succeeds(self): # The action based click doesn"t check for visibility. test_html = self.marionette.absolute_url("hidden.html") self.marionette.navigate(test_html) el = self.marionette.find_element(By.ID, "child") self.action.click(el).perform() def test_double_click_action(self): test_html = self.marionette.absolute_url("double_click.html") self.marionette.navigate(test_html) el = self.marionette.find_element(By.ID, "one-word-div") self.action.double_click(el).perform() el.send_keys(self.mod_key + "c") rel = self.marionette.find_element(By.ID, "input-field") rel.send_keys(self.mod_key + "v") self.assertEqual("zyxw", rel.get_property("value")) def test_context_click_action(self): test_html = self.marionette.absolute_url("javascriptPage.html") self.marionette.navigate(test_html) click_el = self.marionette.find_element(By.ID, "resultContainer") def context_menu_state(): with self.marionette.using_context("chrome"): cm_el = self.marionette.find_element(By.ID, "contentAreaContextMenu") return cm_el.get_property("state") self.assertEqual("closed", context_menu_state()) self.action.context_click(click_el).perform() self.wait_for_condition(lambda _: context_menu_state() == "open") with self.marionette.using_context("chrome"): self.marionette.find_element(By.ID, "main-window").send_keys(Keys.ESCAPE) self.wait_for_condition(lambda _: context_menu_state() == "closed") def test_middle_click_action(self): test_html = self.marionette.absolute_url("clicks.html") self.marionette.navigate(test_html) self.marionette.find_element(By.ID, "addbuttonlistener").click() el = self.marionette.find_element(By.ID, "showbutton") self.action.middle_click(el).perform() self.wait_for_condition(lambda _: el.get_property("innerHTML") == "1") def test_chrome_click(self): self.marionette.navigate("about:blank") data_uri = "data:text/html,<html></html>" with self.marionette.using_context("chrome"): urlbar = self.marionette.find_element(By.ID, "urlbar") urlbar.send_keys(data_uri) go_button = self.marionette.find_element(By.ID, "urlbar-go-button") self.action.click(go_button).perform() self.wait_for_condition(lambda mn: mn.get_url() == data_uri) def test_chrome_double_click(self): self.marionette.navigate("about:blank") test_word = "quux" with self.marionette.using_context("chrome"): urlbar = self.marionette.find_element(By.ID, "urlbar") self.assertEqual("", urlbar.get_property("value")) urlbar.send_keys(test_word) self.assertEqual(urlbar.get_property("value"), test_word) (self.action.double_click(urlbar).perform().key_down( self.mod_key).key_down("x").perform()) self.assertEqual(urlbar.get_property("value"), "") def test_chrome_context_click_action(self): self.marionette.set_context("chrome") def context_menu_state(): cm_el = self.marionette.find_element(By.ID, "tabContextMenu") return cm_el.get_property("state") currtab = self.marionette.execute_script("return gBrowser.selectedTab") self.assertEqual("closed", context_menu_state()) self.action.context_click(currtab).perform() self.wait_for_condition(lambda _: context_menu_state() == "open") (self.marionette.find_element(By.ID, "main-window").send_keys(Keys.ESCAPE)) self.wait_for_condition(lambda _: context_menu_state() == "closed")
class TestKeyActions(WindowManagerMixin, MarionetteTestCase): def setUp(self): super(TestKeyActions, self).setUp() if self.marionette.session_capabilities["platformName"] == "darwin": self.mod_key = Keys.META else: self.mod_key = Keys.CONTROL test_html = self.marionette.absolute_url("javascriptPage.html") self.marionette.navigate(test_html) self.reporter_element = self.marionette.find_element( By.ID, "keyReporter") self.reporter_element.click() self.key_action = Actions(self.marionette) @property def key_reporter_value(self): return self.reporter_element.get_property("value") def test_key_action_basic_input(self): self.key_action.key_down("a").key_down("b").key_down("c").perform() self.assertEqual(self.key_reporter_value, "abc") def test_upcase_input(self): (self.key_action.key_down(Keys.SHIFT).key_down("a").key_up( Keys.SHIFT).key_down("b").key_down("c").perform()) self.assertEqual(self.key_reporter_value, "Abc") def test_replace_input(self): self.key_action.key_down("a").key_down("b").key_down("c").perform() self.assertEqual(self.key_reporter_value, "abc") (self.key_action.key_down(self.mod_key).key_down("a").key_up( self.mod_key).key_down("x").perform()) self.assertEqual(self.key_reporter_value, "x") def test_clear_input(self): self.key_action.key_down("a").key_down("b").key_down("c").perform() self.assertEqual(self.key_reporter_value, "abc") (self.key_action.key_down( self.mod_key).key_down("a").key_down("x").perform()) self.assertEqual(self.key_reporter_value, "") self.key_action.key_down("a").key_down("b").key_down("c").perform() self.assertEqual(self.key_reporter_value, "abc") def test_input_with_wait(self): self.key_action.key_down("a").key_down("b").key_down("c").perform() (self.key_action.key_down( self.mod_key).key_down("a").wait(.5).key_down("x").perform()) self.assertEqual(self.key_reporter_value, "") @skip_if_mobile("Interacting with chrome windows not available for Fennec") def test_open_in_new_window_shortcut(self): def open_window_with_action(): el = self.marionette.find_element(By.ID, "updatediv") # Ensure that the element is in the current view port because press() doesn't # handle that inside the action chain (bug 1295538). self.marionette.execute_script('arguments[0].scrollIntoView()', script_args=[el]) (self.key_action.key_down(Keys.SHIFT).press(el).release().key_up( Keys.SHIFT).perform()) new_window = self.open_window(trigger=open_window_with_action) self.marionette.switch_to_window(new_window) self.marionette.close_chrome_window() self.marionette.switch_to_window(self.start_window) self.assertEqual(self.key_reporter_value, "")
class TestKeyActions(MarionetteTestCase): def setUp(self): MarionetteTestCase.setUp(self) if self.marionette.session_capabilities["platformName"] == "darwin": self.mod_key = Keys.META else: self.mod_key = Keys.CONTROL test_html = self.marionette.absolute_url("javascriptPage.html") self.marionette.navigate(test_html) self.reporter_element = self.marionette.find_element( By.ID, "keyReporter") self.reporter_element.click() self.key_action = Actions(self.marionette) @property def key_reporter_value(self): return self.reporter_element.get_property("value") def test_key_action_basic_input(self): self.key_action.key_down("a").key_down("b").key_down("c").perform() self.assertEqual(self.key_reporter_value, "abc") def test_upcase_input(self): (self.key_action.key_down(Keys.SHIFT).key_down("a").key_up( Keys.SHIFT).key_down("b").key_down("c").perform()) self.assertEqual(self.key_reporter_value, "Abc") def test_replace_input(self): self.key_action.key_down("a").key_down("b").key_down("c").perform() self.assertEqual(self.key_reporter_value, "abc") (self.key_action.key_down(self.mod_key).key_down("a").key_up( self.mod_key).key_down("x").perform()) self.assertEqual(self.key_reporter_value, "x") def test_clear_input(self): self.key_action.key_down("a").key_down("b").key_down("c").perform() self.assertEqual(self.key_reporter_value, "abc") (self.key_action.key_down( self.mod_key).key_down("a").key_down("x").perform()) self.assertEqual(self.key_reporter_value, "") self.key_action.key_down("a").key_down("b").key_down("c").perform() self.assertEqual(self.key_reporter_value, "abc") def test_input_with_wait(self): self.key_action.key_down("a").key_down("b").key_down("c").perform() (self.key_action.key_down( self.mod_key).key_down("a").wait(.5).key_down("x").perform()) self.assertEqual(self.key_reporter_value, "") def test_open_in_new_window_shortcut(self): el = self.marionette.find_element(By.ID, "updatediv") start_win = self.marionette.current_chrome_window_handle (self.key_action.key_down(Keys.SHIFT).press(el).release().key_up( Keys.SHIFT).perform()) self.wait_for_condition( lambda mn: len(self.marionette.window_handles) == 2) chrome_window_handles = self.marionette.chrome_window_handles chrome_window_handles.remove(start_win) [new_win] = chrome_window_handles self.marionette.switch_to_window(new_win) self.marionette.close() self.marionette.switch_to_window(start_win) self.assertEqual(self.key_reporter_value, "")
class EverythingMe(object): def __init__(self, p_parent): self.apps = p_parent.apps self.data_layer = p_parent.data_layer self.parent = p_parent self.marionette = p_parent.marionette self.UTILS = p_parent.UTILS self.actions = Actions(self.marionette) def launch(self): self.apps.kill_all() # If EME has already been launched, then the DOM has changed. self.UTILS.reporting.logResult("info", "Launching Everything ME.") boolOK = False try: self.parent.wait_for_element_displayed(*DOM.EME.start_eme_icon, timeout=1) x = self.marionette.find_element(*DOM.EME.start_eme_icon) x.tap() boolOK = True except: self.UTILS.reporting.logResult("info", "Everything ME is already 'running', so just waking it up ...") self._relaunch() try: self.parent.wait_for_element_displayed(*DOM.EME.groups, timeout=3) except: self._relaunch() boolOK = True self.UTILS.test.test(boolOK, "EME Starting up ...") def _relaunch(self): """ Private function to re-launch. This gets complicated: 1. el.tap() and el.click() only work *sometimes*, so use the keyboard to relaunch. 2. Sometimes the messges app randomly launches instead of evme! """ x = self.marionette.find_element(*DOM.EME.search_field) x.send_keys("waking up evme") x = self.marionette.find_element(*DOM.EME.search_clear) x.tap() def add_app_to_homescreen(self, name): """ Pick an app from the apps listed in this group. """ x = self.UTILS.element.getElementByXpath(DOM.EME.app_to_install.format(name)) app_name = x.text self.UTILS.reporting.logResult("debug", "icon displayed: {}".format(x.is_displayed())) time.sleep(2) self.UTILS.test.test(app_name == name, "" + app_name + "'is the correct app", True) self.actions.long_press(x, 2).perform() x = self.UTILS.element.getElement(DOM.EME.add_to_homescreen_btn, "Add app to homescreen button") x.tap() time.sleep(2) return True def add_group(self, group): """ Adds a group to EME (assumes you're already in the EME group screen). """ self.UTILS.reporting.logResult("info", "(Adding group '" + group + "'.)") # Click the 'More' icon. x = self.UTILS.element.getElement(DOM.EME.add_group_button, "'More' icon") x.tap() # Wait for the 'loading' spinner to go away (can take a while!). self.UTILS.element.waitForNotElements(DOM.EME.loading_groups_message, "'Loading' message", True, 120) # Chose an item from the groups list... self.UTILS.general.selectFromSystemDialog(group) # Verify the new group is in the groups list. x = self.UTILS.element.getElements(DOM.EME.groups, "Groups") boolOK = False for i in x: if i.get_attribute("data-query") == group: boolOK = True break self.UTILS.test.test(boolOK, "New group '" + group + "' is now present in the EME groups.") return boolOK def add_multiple_groups(self, group_array=False): """ Adds multiple groups based on an array of numbers (defaults to all available groups). <br><br> For example: add_multiple_groups([0,1,2,3,8,11]) ... or just: add_multiple_groups() """ x = self.UTILS.element.getElement(DOM.EME.add_group_button, "'More' icon") x.tap() self.UTILS.element.waitForNotElements(DOM.EME.loading_groups_message, "'Loading' message", True, 120) # Switch to group selector (in top level iframe). self.marionette.switch_to_frame() # for checking later list_names = [] elements = self.UTILS.element.getElements(DOM.GLOBAL.modal_valueSel_list, "Groups list", False) for i in range(len(elements)): if i > 0: # Keep shuffling the groups into view so they can be tapped. self.actions.press(elements[i]).move(elements[i - 1]).wait(0.5).release().perform() elements = self.marionette.find_elements(*DOM.GLOBAL.modal_valueSel_list) # Only select it if it's the list, or there is no list. select_elements = False if group_array: if len(group_array) == len(list_names): # # We've done all of them - stop looping! break if i in group_array: select_elements = True else: select_elements = True if select_elements: tmp_name = elements[i].find_element("tag name", "span").text self.UTILS.reporting.logResult("info", "Selecting '{}' ...".format(tmp_name)) list_names.append(tmp_name) elements[i].tap() # Sometimes the first tap does nothing for some reason. if not elements[i].get_attribute("aria-checked"): elements[i].tap() # Click the OK button. x = self.UTILS.element.getElement(DOM.GLOBAL.modal_valueSel_ok, "OK button") try: # Sometimes it's one, sometimes the other ... x.tap() x.click() except: pass time.sleep(1) # Checkk all the items we expect are now loaded in evme. self.UTILS.iframe.switchToFrame(*DOM.Home.frame_locator) time.sleep(5) for name in list_names: ok = False # Reload the groups (silently or we'll have loads of these messages!). try: x = self.marionette.find_elements(*DOM.EME.groups) except: break for i in x: group_name = i.get_attribute("data-query") if group_name == name: ok = True break self.UTILS.test.test(ok, "'{}' is now among the groups.".format(name)) def install_app(self, category, name, expect_btn=True): """Try to install an application. Try to install the application with the given name in the given category. expect_btn determines if we expect the "Add to Home Screen" button in the bookmark page. Returns True if the application was successfully installed. """ self.pick_group(category) self.UTILS.iframe.switchToFrame(*DOM.EME.frame_locator) app_name = self.UTILS.element.getElementByXpath(DOM.EME.app_to_install.format(name)).text # Add the app to the homescreen. self.add_app_to_homescreen(app_name) self.UTILS.iframe.switchToFrame(*DOM.EME.bookmark_frame_locator) time.sleep(4) result = False # We expect the application to be installed, so find the Add to Home Screen button and tap it if expect_btn: add_btn = self.UTILS.element.getElement(DOM.EME.add_to_homescreen_done_btn, "Add bookmark to Home Screen Button") add_btn.tap() result = True else: # We expect the application is already installed, so find the proper header title = self.UTILS.element.getElement(DOM.EME.edit_bookmark_header, "Edit link header") self.UTILS.test.test(title, "Title '{}' found".format(title.text)) return result def launch_from_group(self, app_name): """ Function to launch an app directly from an EME group. """ x = self.UTILS.element.getElement(("xpath", "//li[@data-name='{}']".format(app_name)), "Icon for app '{}'".format(app_name), False) try: x.tap() except: # App is not visible, so I need to move it into view first. _id = x.get_attribute("_id") self.marionette.execute_script("document.getElementById('{}').scrollIntoView();".format(_id)) x.tap() time.sleep(1) self.UTILS.element.waitForNotElements(DOM.EME.launched_activity_bar, "Activity notifier", True, 30) x = self.UTILS.debug.screenShotOnErr() self.UTILS.reporting.logResult("info", "Screenshot of app running:", x) def pick_group(self, name): """ Pick a group from the main icons. """ screenshot = self.UTILS.debug.screenShotOnErr() self.UTILS.reporting.logResult("info", "<b>Choosing group '{}' from here ...</b>".format(name), screenshot) ok = False self.UTILS.reporting.info("searching for element: {}".format(DOM.Home.app_icon_css_selector.format(name))) icon = self.marionette.find_element('css selector', DOM.Home.app_icon_css_selector.format(name)) self.UTILS.reporting.logResult("debug", "icon displayed: {}".format(icon.is_displayed())) icon.tap() try: self.UTILS.iframe.switchToFrame(*DOM.EME.frame_locator) self.parent.wait_for_element_displayed(*DOM.EME.apps_not_installed, timeout=20) self.UTILS.reporting.logResult("info", "(Apps for group {} were displayed.)".format(name)) ok = True except Exception as e: self.UTILS.reporting.debug("*** Error getting apps not installed: {}".format(e)) screenshot = self.UTILS.debug.screenShotOnErr() self.UTILS.reporting.logResult("info", "(<b>NOTE:</b>Apps for group {} were not displayed.)|{}|{}".\ format(name, screenshot[0], screenshot[1])) return ok def remove_groups(self, group_array): """ Removes groups from the EME group page. group_array is an array of group names (default = all groups) For example: remove_groups(["Games","Local"]) """ """ Put the groups into edit mode. Sometimes this takes a while to happen, so increase the length of time you press the icon until it works! """ ok = False x = self.marionette.find_element('xpath', DOM.Home.app_icon_css_selector.format(group_array[0])) self.actions.press(x).wait(3).release() try: actions.perform() except: pass try: x = self.UTILS.element.getElement(("xpath", DOM.Home.app_delete_icon_xpath.format(group_array[0])), "Delete button", False, 5, True) if x.is_displayed(): ok = True except: pass time.sleep(2) self.UTILS.test.test(ok, "Enabled EDIT mode.") x = self.UTILS.debug.screenShotOnErr() self.UTILS.reporting.logResult("info", "Screenshot of app in EDIT mode:", x) # Remove all groups in the array. removed = 0 group_cnt = len(group_array) self.UTILS.reporting.logResult("info", "Removing {} groups".format(group_cnt)) self.UTILS.reporting.logResult("info", "Removing groups: {}".format(group_array)) for group_specified in group_array: # Remove it. self.marionette.find_element('xpath', DOM.Home.app_icon_css_selector.format(group_specified)) y = self.UTILS.element.getElement(("xpath", DOM.Home.app_delete_icon_xpath.format(group_specified)), "Delete button", False, 5, True) y.tap() delete = self.UTILS.element.getElement(DOM.Home.app_confirm_delete, "Confirm app delete button") delete.tap() removed = removed + 1 self.UTILS.reporting.logResult("info", "Removed group '{}' ...".format(group_specified)) self.UTILS.reporting.logResult("info", "Removed {} groups".format(removed)) if removed == group_cnt: break # Turn off edit mode. self.UTILS.reporting.logResult("info", "Disabling edit mode ...") self.UTILS.home.touchHomeButton() def search_for_app(self, name): """ Uses the search field to find the app (waits for the result to appear etc...).<br> Returns the element for the icon (or False if it's not found). """ x = self.UTILS.element.getElement(DOM.EME.search_field, "Search field") x.clear() x.send_keys(name) x.click() time.sleep(5) # Can take a few seconds to appear, so try a few times (about 1 min). for retry in range(10): x = self.UTILS.debug.screenShotOnErr() self.UTILS.reporting.logResult("debug", "Looking for '{}' - attempt {} ...".format(name, retry), x) x = self.UTILS.element.getElements(DOM.EME.search_suggestions, "Search suggestions") ok = False for i in x: i_name = i.get_attribute("data-suggestion") if i_name: i_name = i_name.lower() i_name = i_name.replace("[", "") i_name = i_name.replace("]", "") is_in = False for i2 in name.lower().split(): self.UTILS.reporting.logResult("debug", "Is '{}' in '{}'?".format(i2, i_name)) if i2 not in i_name: is_in = False break else: is_in = True if is_in: i.tap() ok = True break if ok: break time.sleep(6) self.UTILS.test.test(ok, "Found '%s' in suggestions." % name) ok = True try: elem = ("xpath", DOM.EME.search_result_icon_xpath.format(name)) self.parent.wait_for_element_displayed(*elem, timeout=60) x = self.marionette.find_element(*elem) return x except: ok = False return ok
def wait(self, seconds: int): actions = Actions(self.marionette) actions.wait(seconds).perform()
class SelectionCaretsTest(MarionetteTestCase): _long_press_time = 1 # 1 second _input_selector = (By.ID, 'input') _textarea_selector = (By.ID, 'textarea') _textarea_rtl_selector = (By.ID, 'textarea_rtl') _contenteditable_selector = (By.ID, 'contenteditable') _content_selector = (By.ID, 'content') _textarea2_selector = (By.ID, 'textarea2') _contenteditable2_selector = (By.ID, 'contenteditable2') _content2_selector = (By.ID, 'content2') def setUp(self): # Code to execute before a tests are run. MarionetteTestCase.setUp(self) self.actions = Actions(self.marionette) def openTestHtml(self, enabled=True): '''Open html for testing and locate elements, and enable/disable touch caret.''' self.marionette.execute_async_script( 'SpecialPowers.pushPrefEnv({"set": [["selectioncaret.enabled", %s]]}, marionetteScriptFinished);' % ('true' if enabled else 'false')) test_html = self.marionette.absolute_url('test_selectioncarets.html') self.marionette.navigate(test_html) self._input = self.marionette.find_element(*self._input_selector) self._textarea = self.marionette.find_element(*self._textarea_selector) self._textarea_rtl = self.marionette.find_element( *self._textarea_rtl_selector) self._contenteditable = self.marionette.find_element( *self._contenteditable_selector) self._content = self.marionette.find_element(*self._content_selector) def openTestHtml2(self, enabled=True): '''Open html for testing and locate elements, and enable/disable touch caret.''' self.marionette.execute_script( 'SpecialPowers.setBoolPref("selectioncaret.enabled", %s);' % ('true' if enabled else 'false')) test_html2 = self.marionette.absolute_url( 'test_selectioncarets_multipleline.html') self.marionette.navigate(test_html2) self._textarea2 = self.marionette.find_element( *self._textarea2_selector) self._contenteditable2 = self.marionette.find_element( *self._contenteditable2_selector) self._content2 = self.marionette.find_element(*self._content2_selector) def _first_word_location(self, el): '''Get the location (x, y) of the first word in el. Note: this function has a side effect which changes focus to the target element el. ''' sel = SelectionManager(el) # Move caret behind the first character to get the location of the first # word. el.tap() sel.move_caret_to_front() sel.move_caret_by_offset(1) return sel.caret_location() def _long_press_to_select(self, el, x, y): '''Long press the location (x, y) to select a word. SelectionCarets should appear. On Windows, those spaces after the word will also be selected. ''' long_press_without_contextmenu(self.marionette, el, self._long_press_time, x, y) def _test_long_press_to_select_a_word(self, el, assertFunc): sel = SelectionManager(el) original_content = sel.content words = original_content.split() self.assertTrue( len(words) >= 2, 'Expect at least two words in the content.') target_content = words[0] # Goal: Select the first word. x, y = self._first_word_location(el) self._long_press_to_select(el, x, y) # Ignore extra spaces selected after the word. assertFunc(target_content, sel.selected_content.rstrip()) def _test_move_selection_carets(self, el, assertFunc): 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. el.tap() sel.select_all() (_, _), (end_caret_x, end_caret_y) = sel.selection_carets_location() x, y = self._first_word_location(el) self._long_press_to_select(el, x, y) # Move the right caret to the end of the content. (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location() self.actions.flick(el, caret2_x, caret2_y, end_caret_x, end_caret_y).perform() # Move the left caret to the previous position of the right caret. self.actions.flick(el, caret1_x, caret1_y, caret2_x, caret2_y).perform() # Ignore extra spaces at the beginning of the content in comparison. assertFunc(target_content.lstrip(), sel.selected_content.lstrip()) def _test_minimum_select_one_character(self, el, assertFunc, 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. sel.select_all() (_, _), (end_caret_x, end_caret_y) = sel.selection_carets_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._first_word_location(el) self._long_press_to_select(el, x, y) # Move the right caret to the end of the content. (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location() self.actions.flick(el, caret2_x, caret2_y, end_caret_x, end_caret_y).perform() # Move the right caret to the position of the left caret. (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location() self.actions.flick(el, caret2_x, caret2_y, caret1_x, caret1_y).perform() assertFunc(target_content, sel.selected_content) def _test_focus_obtained_by_long_press(self, el1, el2): '''Test the focus could be changed from el1 to el2 by long press. If the focus is changed to e2 successfully, SelectionCarets should appear and could be dragged. ''' # Goal: Tap to focus el1, and then select the first character on # el2. # We want to collect the location of the first word in el2 here # since self._first_word_location() has the side effect which would # change the focus. x, y = self._first_word_location(el2) el1.tap() self._test_minimum_select_one_character(el2, self.assertEqual, x=x, y=y) def _test_handle_tilt_when_carets_overlap_to_each_other( self, el, assertFunc): '''Test tilt handling when carets overlap to each other. Let SelectionCarets overlap to each other. If SelectionCarets are set to tilted successfully, tapping the tilted carets should not cause the selection to be collapsed and the carets should be draggable. ''' 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 the first word. x, y = self._first_word_location(el) self._long_press_to_select(el, x, y) target_content = sel.selected_content # Move the left caret to the position of the right caret to trigger # carets overlapping. (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_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() # The following values are from ua.css. caret_width = 44 caret_margin_left = -23 tilt_right_margin_left = 18 tilt_left_margin_left = -17 left_caret_left_edge_x = caret3_x + caret_margin_left + tilt_left_margin_left el.tap(ceil(left_caret_left_edge_x), caret3_y) right_caret_right_edge_x = (caret4_x + caret_margin_left + tilt_right_margin_left + caret_width) el.tap(floor(right_caret_right_edge_x), caret4_y) # Drag the left caret back to the initial selection, the first word. self.actions.flick(el, caret3_x, caret3_y, caret1_x, caret1_y).perform() assertFunc(target_content, sel.selected_content) ######################################################################## # <input> test cases with selection carets enabled ######################################################################## def test_input_long_press_to_select_a_word(self): self.openTestHtml(enabled=True) self._test_long_press_to_select_a_word(self._input, self.assertEqual) def test_input_move_selection_carets(self): self.openTestHtml(enabled=True) self._test_move_selection_carets(self._input, self.assertEqual) def test_input_minimum_select_one_character(self): self.openTestHtml(enabled=True) self._test_minimum_select_one_character(self._input, self.assertEqual) def test_input_focus_obtained_by_long_press_from_textarea(self): self.openTestHtml(enabled=True) self._test_focus_obtained_by_long_press(self._textarea, self._input) def test_input_focus_obtained_by_long_press_from_contenteditable(self): self.openTestHtml(enabled=True) self._test_focus_obtained_by_long_press(self._contenteditable, self._input) def test_input_focus_obtained_by_long_press_from_content_non_editable( self): self.openTestHtml(enabled=True) self._test_focus_obtained_by_long_press(self._content, self._input) def test_input_handle_tilt_when_carets_overlap_to_each_other(self): self.openTestHtml(enabled=True) self._test_handle_tilt_when_carets_overlap_to_each_other( self._input, self.assertEqual) ######################################################################## # <input> test cases with selection carets disabled ######################################################################## def test_input_long_press_to_select_a_word_disabled(self): self.openTestHtml(enabled=False) self._test_long_press_to_select_a_word(self._input, self.assertNotEqual) def test_input_move_selection_carets_disabled(self): self.openTestHtml(enabled=False) self._test_move_selection_carets(self._input, self.assertNotEqual) ######################################################################## # <textarea> test cases with selection carets enabled ######################################################################## def test_textarea_long_press_to_select_a_word(self): self.openTestHtml(enabled=True) self._test_long_press_to_select_a_word(self._textarea, self.assertEqual) def test_textarea_move_selection_carets(self): self.openTestHtml(enabled=True) self._test_move_selection_carets(self._textarea, self.assertEqual) def test_textarea_minimum_select_one_character(self): self.openTestHtml(enabled=True) self._test_minimum_select_one_character(self._textarea, self.assertEqual) def test_textarea_focus_obtained_by_long_press_from_input(self): self.openTestHtml(enabled=True) self._test_focus_obtained_by_long_press(self._input, self._textarea) def test_textarea_focus_obtained_by_long_press_from_contenteditable(self): self.openTestHtml(enabled=True) self._test_focus_obtained_by_long_press(self._contenteditable, self._textarea) def test_textarea_focus_obtained_by_long_press_from_content_non_editable( self): self.openTestHtml(enabled=True) self._test_focus_obtained_by_long_press(self._content, self._textarea) def test_textarea_handle_tilt_when_carets_overlap_to_each_other(self): self.openTestHtml(enabled=True) self._test_handle_tilt_when_carets_overlap_to_each_other( self._textarea, self.assertEqual) ######################################################################## # <textarea> test cases with selection carets disabled ######################################################################## def test_textarea_long_press_to_select_a_word_disabled(self): self.openTestHtml(enabled=False) self._test_long_press_to_select_a_word(self._textarea, self.assertNotEqual) def test_textarea_move_selection_carets_disable(self): self.openTestHtml(enabled=False) self._test_move_selection_carets(self._textarea, self.assertNotEqual) ######################################################################## # <textarea> right-to-left test cases with selection carets enabled ######################################################################## def test_textarea_rtl_long_press_to_select_a_word(self): self.openTestHtml(enabled=True) self._test_long_press_to_select_a_word(self._textarea_rtl, self.assertEqual) def test_textarea_rtl_move_selection_carets(self): self.openTestHtml(enabled=True) self._test_move_selection_carets(self._textarea_rtl, self.assertEqual) def test_textarea_rtl_minimum_select_one_character(self): self.openTestHtml(enabled=True) self._test_minimum_select_one_character(self._textarea_rtl, self.assertEqual) ######################################################################## # <textarea> right-to-left test cases with selection carets disabled ######################################################################## def test_textarea_rtl_long_press_to_select_a_word_disabled(self): self.openTestHtml(enabled=False) self._test_long_press_to_select_a_word(self._textarea_rtl, self.assertNotEqual) def test_textarea_rtl_move_selection_carets_disabled(self): self.openTestHtml(enabled=False) self._test_move_selection_carets(self._textarea_rtl, self.assertNotEqual) ######################################################################## # <div> contenteditable test cases with selection carets enabled ######################################################################## def test_contenteditable_long_press_to_select_a_word(self): self.openTestHtml(enabled=True) self._test_long_press_to_select_a_word(self._contenteditable, self.assertEqual) def test_contenteditable_move_selection_carets(self): self.openTestHtml(enabled=True) self._test_move_selection_carets(self._contenteditable, self.assertEqual) def test_contenteditable_minimum_select_one_character(self): self.openTestHtml(enabled=True) self._test_minimum_select_one_character(self._contenteditable, self.assertEqual) def test_contenteditable_focus_obtained_by_long_press_from_input(self): self.openTestHtml(enabled=True) self._test_focus_obtained_by_long_press(self._input, self._contenteditable) def test_contenteditable_focus_obtained_by_long_press_from_textarea(self): self.openTestHtml(enabled=True) self._test_focus_obtained_by_long_press(self._textarea, self._contenteditable) def test_contenteditable_focus_obtained_by_long_press_from_content_non_editable( self): self.openTestHtml(enabled=True) self._test_focus_obtained_by_long_press(self._content, self._contenteditable) def test_contenteditable_handle_tilt_when_carets_overlap_to_each_other( self): self.openTestHtml(enabled=True) self._test_handle_tilt_when_carets_overlap_to_each_other( self._contenteditable, self.assertEqual) ######################################################################## # <div> contenteditable test cases with selection carets disabled ######################################################################## def test_contenteditable_long_press_to_select_a_word_disabled(self): self.openTestHtml(enabled=False) self._test_long_press_to_select_a_word(self._contenteditable, self.assertNotEqual) def test_contenteditable_move_selection_carets_disabled(self): self.openTestHtml(enabled=False) self._test_move_selection_carets(self._contenteditable, self.assertNotEqual) ######################################################################## # <div> non-editable test cases with selection carets enabled ######################################################################## def test_content_non_editable_long_press_to_select_a_word(self): self.openTestHtml(enabled=True) self._test_long_press_to_select_a_word(self._content, self.assertEqual) def test_content_non_editable_move_selection_carets(self): self.openTestHtml(enabled=True) self._test_move_selection_carets(self._content, self.assertEqual) def test_content_non_editable_minimum_select_one_character_by_selection( self): self.openTestHtml(enabled=True) self._test_minimum_select_one_character(self._content, self.assertEqual) def test_content_non_editable_focus_obtained_by_long_press_from_input( self): self.openTestHtml(enabled=True) self._test_focus_obtained_by_long_press(self._input, self._content) def test_content_non_editable_focus_obtained_by_long_press_from_textarea( self): self.openTestHtml(enabled=True) self._test_focus_obtained_by_long_press(self._textarea, self._content) def test_content_non_editable_focus_obtained_by_long_press_from_contenteditable( self): self.openTestHtml(enabled=True) self._test_focus_obtained_by_long_press(self._contenteditable, self._content) def test_content_non_editable_handle_tilt_when_carets_overlap_to_each_other( self): self.openTestHtml(enabled=True) self._test_handle_tilt_when_carets_overlap_to_each_other( self._content, self.assertEqual) ######################################################################## # <textarea> (multi-lines) test cases with selection carets enabled ######################################################################## def test_textarea2_minimum_select_one_character(self): self.openTestHtml2(enabled=True) self._test_minimum_select_one_character(self._textarea2, self.assertEqual) ######################################################################## # <div> contenteditable2 (multi-lines) test cases with selection carets enabled ######################################################################## def test_contenteditable2_minimum_select_one_character(self): self.openTestHtml2(enabled=True) self._test_minimum_select_one_character(self._contenteditable2, self.assertEqual) ######################################################################## # <div> non-editable2 (multi-lines) test cases with selection carets enabled ######################################################################## def test_content_non_editable2_minimum_select_one_character(self): self.openTestHtml2(enabled=True) self._test_minimum_select_one_character(self._content2, self.assertEqual)
def test_no_press(self): testAction = self.marionette.absolute_url("testAction.html") self.marionette.navigate(testAction) action = Actions(self.marionette) action.release() self.assertRaises(MarionetteException, action.perform)
class AccessibleCaretCursorModeTestCase(MarionetteTestCase): '''Test cases for AccessibleCaret under cursor mode. We call the blinking cursor (nsCaret) as cursor, and call AccessibleCaret as caret for short. ''' # Element IDs. _input_id = 'input' _input_padding_id = 'input-padding' _textarea_id = 'textarea' _textarea_one_line_id = 'textarea-one-line' _contenteditable_id = 'contenteditable' # Test html files. _cursor_html = 'layout/test_carets_cursor.html' def setUp(self): # Code to execute before every test is running. 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) 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): self.open_test_html(self._cursor_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 first caret (x, y) at position 1 and 2. el.tap() 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 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.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) sel = SelectionManager(el) content_to_add = '!' target_content = sel.content + content_to_add # Tap the front of the input to make first caret appear. el.tap() 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.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) sel = SelectionManager(el) content_to_add = '!' target_content = content_to_add + sel.content # Get first caret location at the front. el.tap() sel.move_cursor_to_front() dest_x, dest_y = sel.first_caret_location() # 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_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.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 el.tap() 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.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 not be inserted at the front of the <input>. el.send_keys(content_to_add) 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_when_dragging_to_editable_content_boundary(self, el_id): self.open_test_html(self._cursor_html) el = self.marionette.find_element(By.ID, el_id) sel = SelectionManager(el) content_to_add = '!' non_target_content = sel.content + content_to_add # Goal: the cursor position is not changed after dragging the caret down # 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.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) el = self.marionette.find_element(By.ID, el_id) sel = SelectionManager(el) content_to_add = '!' non_target_content = content_to_add + sel.content # 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() 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 # Goal: the cursor position can be changed by dragging the caret from # the front to the end of the content. # Tap to make the cursor appear. before_image_1 = self.marionette.find_element(By.ID, 'before-image-1') before_image_1.tap() # Tap the front of the content to make first caret appear. 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.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' target_content = content_to_add_1 + content_to_add_2 + sel.content # Goal: the cursor position can be changed by dragging the caret from # the end of the content to the front br element. Because we cannot get # caret location if it's on a br element, we need to get the first caret # location then adding the new lines. # Get first caret location at the front. el.tap() sel.move_cursor_to_front() dest_x, dest_y = sel.first_caret_location() # Append new line to the front of the content. el.send_keys(content_to_add_2); # Tap to make first caret appear. el.tap() 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.assertEqual(target_content, sel.content)
def double_tap_image(self): image = self.marionette.find_element(*self._current_image_locator) action = Actions(self.marionette) action.double_tap(image) action.perform()
class CommonCaretsTestCase(object): '''Common test cases for a selection with a two carets. To run these test cases, a subclass must inherit from both this class and MarionetteTestCase. ''' def setUp(self): # Code to execute before a tests are run. super(CommonCaretsTestCase, self).setUp() self.actions = Actions(self.marionette) def open_test_html(self): 'Open html for testing and locate elements.' test_html = self.marionette.absolute_url('test_selectioncarets.html') self.marionette.navigate(test_html) self._input = self.marionette.find_element(By.ID, 'input') self._textarea = self.marionette.find_element(By.ID, 'textarea') self._textarea_rtl = self.marionette.find_element(By.ID, 'textarea_rtl') self._contenteditable = self.marionette.find_element(By.ID, 'contenteditable') self._content = self.marionette.find_element(By.ID, 'content') self._non_selectable = self.marionette.find_element(By.ID, 'non_selectable') def open_test_html2(self): 'Open html for testing and locate elements.' test_html2 = self.marionette.absolute_url('test_selectioncarets_multipleline.html') self.marionette.navigate(test_html2) self._textarea2 = self.marionette.find_element(By.ID, 'textarea2') self._contenteditable2 = self.marionette.find_element(By.ID, 'contenteditable2') self._content2 = self.marionette.find_element(By.ID, 'content2') def open_test_html_multirange(self): 'Open html for testing non-editable support.' test_html = self.marionette.absolute_url('test_selectioncarets_multiplerange.html') self.marionette.navigate(test_html) self._body = self.marionette.find_element(By.ID, 'bd') self._sel1 = self.marionette.find_element(By.ID, 'sel1') self._sel2 = self.marionette.find_element(By.ID, 'sel2') self._sel3 = self.marionette.find_element(By.ID, 'sel3') self._sel4 = self.marionette.find_element(By.ID, 'sel4') self._sel6 = self.marionette.find_element(By.ID, 'sel6') self._nonsel1 = self.marionette.find_element(By.ID, 'nonsel1') def open_test_html_long_text(self): 'Open html for testing long text.' test_html = self.marionette.absolute_url('test_selectioncarets_longtext.html') self.marionette.navigate(test_html) self._body = self.marionette.find_element(By.ID, 'bd') self._longtext = self.marionette.find_element(By.ID, 'longtext') def open_test_html_iframe(self): 'Open html for testing iframe.' test_html = self.marionette.absolute_url('test_selectioncarets_iframe.html') self.marionette.navigate(test_html) self._iframe = self.marionette.find_element(By.ID, 'frame') 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 words = tokens[1::2] # collect word at even indices if ordinal >= len(words): raise IndexError('Only %d words in text, but got ordinal %d' % (len(words), ordinal)) # Cursor position of the targeting word is behind the the first # character in the word. For example, offset to 'def' in 'abc def' is # between 'd' and 'e'. offset = len(spaces[0]) + 1 offset += sum(len(words[i]) + len(spaces[i + 1]) for i in range(ordinal)) return offset def test_word_offset(self): text = ' ' * 3 + 'abc' + ' ' * 3 + 'def' self.assertTrue(self.word_offset(text, 0), 4) self.assertTrue(self.word_offset(text, 1), 10) with self.assertRaises(IndexError): self.word_offset(text, 2) def word_location(self, el, ordinal): '''Get the location (x, y) of the ordinal-th word in el. The ordinal starts from 0. Note: this function has a side effect which changes focus to the target element el. ''' sel = SelectionManager(el) offset = self.word_offset(sel.content, ordinal) # Move caret to the word. el.tap() sel.move_caret_to_front() sel.move_caret_by_offset(offset) x, y = sel.caret_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. ''' return self.marionette.execute_script(''' let rect = arguments[0].getBoundingClientRect(); return {x: rect.x, y:rect.y, width: rect.width, height: rect.height}; ''', script_args=[el]) def long_press_on_location(self, el, x=None, y=None): '''Long press the location (x, y) to select a word. If no (x, y) are given, it will be targeted at the center of the element. On Windows, those spaces after the word will also be selected. This function sends synthesized eMouseLongTap to gecko. ''' rect = self.rect_relative_to_window(el) target_x = rect['x'] + (x if x is not None else rect['width'] // 2) target_y = rect['y'] + (y if y is not None else rect['height'] // 2) self.marionette.execute_script(''' let Ci = Components.interfaces; let utils = window.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIDOMWindowUtils); utils.sendTouchEventToWindow('touchstart', [0], [arguments[0]], [arguments[1]], [1], [1], [0], [1], 1, 0); utils.sendMouseEventToWindow('mouselongtap', arguments[0], arguments[1], 0, 1, 0); utils.sendTouchEventToWindow('touchend', [0], [arguments[0]], [arguments[1]], [1], [1], [0], [1], 1, 0); ''', script_args=[target_x, target_y], sandbox='system') def long_press_on_word(self, el, wordOrdinal): x, y = self.word_location(el, wordOrdinal) self.long_press_on_location(el, x, y) def to_unix_line_ending(self, s): """Changes all Windows/Mac line endings in s to UNIX line endings.""" return s.replace('\r\n', '\n').replace('\r', '\n') def _test_long_press_to_select_a_word(self, el, assertFunc): sel = SelectionManager(el) original_content = sel.content words = original_content.split() self.assertTrue(len(words) >= 2, 'Expect at least two words in the content.') target_content = words[0] # Goal: Select the first word. self.long_press_on_word(el, 0) # Ignore extra spaces selected after the word. assertFunc(target_content, sel.selected_content) def _test_move_selection_carets(self, el, assertFunc): 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. el.tap() sel.select_all() (_, _), (end_caret_x, end_caret_y) = sel.selection_carets_location() self.long_press_on_word(el, 0) # Move the right caret to the end of the content. (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location() self.actions.flick(el, caret2_x, caret2_y, end_caret_x, end_caret_y).perform() # Move the left caret to the previous position of the right caret. self.actions.flick(el, caret1_x, caret1_y, caret2_x, caret2_y).perform() assertFunc(target_content, sel.selected_content) def _test_minimum_select_one_character(self, el, assertFunc, 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. sel.select_all() (_, _), (end_caret_x, end_caret_y) = sel.selection_carets_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) # Move the right caret to the end of the content. (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location() self.actions.flick(el, caret2_x, caret2_y, end_caret_x, end_caret_y).perform() # Move the right caret to the position of the left caret. (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location() self.actions.flick(el, caret2_x, caret2_y, caret1_x, caret1_y).perform() assertFunc(target_content, sel.selected_content) def _test_focus_obtained_by_long_press(self, el1, el2): '''Test the focus could be changed from el1 to el2 by long press. If the focus is changed to e2 successfully, SelectionCarets should appear and could be dragged. ''' # Goal: Tap to focus el1, and then select the first character on # el2. # We want to collect the location of the first word in el2 here # since self.word_location() has the side effect which would # change the focus. x, y = self.word_location(el2, 0) el1.tap() self._test_minimum_select_one_character(el2, self.assertEqual, x=x, y=y) def _test_focus_not_being_changed_by_long_press_on_non_selectable(self, el): # Goal: Focus remains on the editable element el after long pressing on # the non-selectable element. sel = SelectionManager(el) self.long_press_on_word(el, 0) self.long_press_on_location(self._non_selectable) active_sel = SelectionManager(self.marionette.get_active_element()) self.assertEqual(sel.content, active_sel.content) def _test_handle_tilt_when_carets_overlap_to_each_other(self, el, assertFunc): '''Test tilt handling when carets overlap to each other. Let SelectionCarets overlap to each other. If SelectionCarets are set to tilted successfully, tapping the tilted carets should not cause the selection to be collapsed and the carets should be draggable. ''' 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 the first word. self.long_press_on_word(el, 0) target_content = sel.selected_content # Move the left caret to the position of the right caret to trigger # carets overlapping. (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_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() # The following values are from ua.css and all.js if self.carets_tested_pref == 'selectioncaret.enabled': caret_width = 44 caret_margin_left = -23 tilt_right_margin_left = 18 tilt_left_margin_left = -17 elif self.carets_tested_pref == 'layout.accessiblecaret.enabled': 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 el.tap(left_caret_left_edge_x + 2, caret3_y) right_caret_right_edge_x = (caret4_x + caret_margin_left + tilt_right_margin_left + caret_width) el.tap(right_caret_right_edge_x - 2, caret4_y) # Drag the left caret back to the initial selection, the first word. self.actions.flick(el, caret3_x, caret3_y, caret1_x, caret1_y).perform() assertFunc(target_content, sel.selected_content) def test_long_press_to_select_non_selectable_word(self): '''Testing long press on non selectable field. We should not select anything when long press on non selectable fields.''' self.open_test_html_multirange() halfY = self._nonsel1.size['height'] / 2 self.long_press_on_location(self._nonsel1, 0, halfY) sel = SelectionManager(self._nonsel1) range_count = sel.range_count() self.assertEqual(range_count, 0) 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.''' self.open_test_html_multirange() # Select target element and get target caret location self.long_press_on_word(self._sel4, 3) sel = SelectionManager(self._body) (_, _), (end_caret_x, end_caret_y) = sel.selection_carets_location() self.long_press_on_word(self._sel6, 0) (_, _), (end_caret2_x, end_caret2_y) = sel.selection_carets_location() # Select start element self.long_press_on_word(self._sel3, 3) # Drag end caret to target location (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location() self.actions.flick(self._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() self.actions.flick(self._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() self.actions.flick(self._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() # Select the first word in the second line self.long_press_on_word(self._sel2, 0) sel = SelectionManager(self._body) (start_caret_x, start_caret_y), (end_caret_x, end_caret_y) = sel.selection_carets_location() # Select target word in the first line self.long_press_on_word(self._sel1, 2) # Drag end caret to the beginning of the second line (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location() self.actions.flick(self._body, caret2_x, caret2_y, start_caret_x, start_caret_y).perform() # Drag end caret back to the target word self.actions.flick(self._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 def test_caret_position_after_changing_orientation_of_device(self): '''Bug 1094072 If positions of carets are updated correctly, they should be draggable. ''' self.open_test_html_long_text() # Select word in portrait mode, then change to landscape mode self.marionette.set_orientation('portrait') self.long_press_on_word(self._longtext, 12) sel = SelectionManager(self._body) (p_start_caret_x, p_start_caret_y), (p_end_caret_x, p_end_caret_y) = sel.selection_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() # Drag end caret to the start caret to change the selected content self.actions.flick(self._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') self.assertEqual(self.to_unix_line_ending(sel.selected_content), 'o') def test_select_word_inside_an_iframe(self): '''Bug 1088552 The scroll offset in iframe should be taken into consideration properly. In this test, we scroll content in the iframe to the bottom to cause a huge offset. If we use the right coordinate system, selection should work. Otherwise, it would be hard to trigger select word. ''' self.open_test_html_iframe() # switch to inner iframe and scroll to the bottom self.marionette.switch_to_frame(self._iframe) self.marionette.execute_script( 'document.getElementById("bd").scrollTop += 999') # long press to select bottom text self._body = self.marionette.find_element(By.ID, 'bd') sel = SelectionManager(self._body) self._bottomtext = self.marionette.find_element(By.ID, 'bottomtext') self.long_press_on_location(self._bottomtext) self.assertNotEqual(self.to_unix_line_ending(sel.selected_content), '') ######################################################################## # <input> test cases with selection carets enabled ######################################################################## def test_input_long_press_to_select_a_word(self): self.open_test_html() self._test_long_press_to_select_a_word(self._input, self.assertEqual) def test_input_move_selection_carets(self): self.open_test_html() self._test_move_selection_carets(self._input, self.assertEqual) def test_input_minimum_select_one_character(self): self.open_test_html() self._test_minimum_select_one_character(self._input, self.assertEqual) def test_input_focus_obtained_by_long_press_from_textarea(self): self.open_test_html() self._test_focus_obtained_by_long_press(self._textarea, self._input) def test_input_focus_obtained_by_long_press_from_contenteditable(self): self.open_test_html() self._test_focus_obtained_by_long_press(self._contenteditable, self._input) def test_input_focus_obtained_by_long_press_from_content_non_editable(self): self.open_test_html() self._test_focus_obtained_by_long_press(self._content, self._input) def test_input_handle_tilt_when_carets_overlap_to_each_other(self): self.open_test_html() self._test_handle_tilt_when_carets_overlap_to_each_other(self._input, self.assertEqual) def test_input_focus_not_changed_by_long_press_on_non_selectable(self): self.open_test_html() self._test_focus_not_being_changed_by_long_press_on_non_selectable(self._input) ######################################################################## # <input> test cases with selection carets disabled ######################################################################## def test_input_long_press_to_select_a_word_disabled(self): with self.marionette.using_prefs({self.carets_tested_pref: False}): self.open_test_html() self._test_long_press_to_select_a_word(self._input, self.assertNotEqual) def test_input_move_selection_carets_disabled(self): with self.marionette.using_prefs({self.carets_tested_pref: False}): self.open_test_html() self._test_move_selection_carets(self._input, self.assertNotEqual) ######################################################################## # <textarea> test cases with selection carets enabled ######################################################################## def test_textarea_long_press_to_select_a_word(self): self.open_test_html() self._test_long_press_to_select_a_word(self._textarea, self.assertEqual) def test_textarea_move_selection_carets(self): self.open_test_html() self._test_move_selection_carets(self._textarea, self.assertEqual) def test_textarea_minimum_select_one_character(self): self.open_test_html() self._test_minimum_select_one_character(self._textarea, self.assertEqual) def test_textarea_focus_obtained_by_long_press_from_input(self): self.open_test_html() self._test_focus_obtained_by_long_press(self._input, self._textarea) def test_textarea_focus_obtained_by_long_press_from_contenteditable(self): self.open_test_html() self._test_focus_obtained_by_long_press(self._contenteditable, self._textarea) def test_textarea_focus_obtained_by_long_press_from_content_non_editable(self): self.open_test_html() self._test_focus_obtained_by_long_press(self._content, self._textarea) def test_textarea_handle_tilt_when_carets_overlap_to_each_other(self): self.open_test_html() self._test_handle_tilt_when_carets_overlap_to_each_other(self._textarea, self.assertEqual) def test_textarea_focus_not_changed_by_long_press_on_non_selectable(self): self.open_test_html() self._test_focus_not_being_changed_by_long_press_on_non_selectable(self._textarea) ######################################################################## # <textarea> test cases with selection carets disabled ######################################################################## def test_textarea_long_press_to_select_a_word_disabled(self): with self.marionette.using_prefs({self.carets_tested_pref: False}): self.open_test_html() self._test_long_press_to_select_a_word(self._textarea, self.assertNotEqual) def test_textarea_move_selection_carets_disable(self): with self.marionette.using_prefs({self.carets_tested_pref: False}): self.open_test_html() self._test_move_selection_carets(self._textarea, self.assertNotEqual) ######################################################################## # <textarea> right-to-left test cases with selection carets enabled ######################################################################## def test_textarea_rtl_long_press_to_select_a_word(self): self.open_test_html() self._test_long_press_to_select_a_word(self._textarea_rtl, self.assertEqual) def test_textarea_rtl_move_selection_carets(self): self.open_test_html() self._test_move_selection_carets(self._textarea_rtl, self.assertEqual) def test_textarea_rtl_minimum_select_one_character(self): self.open_test_html() self._test_minimum_select_one_character(self._textarea_rtl, self.assertEqual) def test_textarea_rtl_focus_not_changed_by_long_press_on_non_selectable(self): self.open_test_html() self._test_focus_not_being_changed_by_long_press_on_non_selectable(self._textarea_rtl) ######################################################################## # <textarea> right-to-left test cases with selection carets disabled ######################################################################## def test_textarea_rtl_long_press_to_select_a_word_disabled(self): with self.marionette.using_prefs({self.carets_tested_pref: False}): self.open_test_html() self._test_long_press_to_select_a_word(self._textarea_rtl, self.assertNotEqual) def test_textarea_rtl_move_selection_carets_disabled(self): with self.marionette.using_prefs({self.carets_tested_pref: False}): self.open_test_html() self._test_move_selection_carets(self._textarea_rtl, self.assertNotEqual) ######################################################################## # <div> contenteditable test cases with selection carets enabled ######################################################################## def test_contenteditable_long_press_to_select_a_word(self): self.open_test_html() self._test_long_press_to_select_a_word(self._contenteditable, self.assertEqual) def test_contenteditable_move_selection_carets(self): self.open_test_html() self._test_move_selection_carets(self._contenteditable, self.assertEqual) def test_contenteditable_minimum_select_one_character(self): self.open_test_html() self._test_minimum_select_one_character(self._contenteditable, self.assertEqual) def test_contenteditable_focus_obtained_by_long_press_from_input(self): self.open_test_html() self._test_focus_obtained_by_long_press(self._input, self._contenteditable) def test_contenteditable_focus_obtained_by_long_press_from_textarea(self): self.open_test_html() self._test_focus_obtained_by_long_press(self._textarea, self._contenteditable) def test_contenteditable_focus_obtained_by_long_press_from_content_non_editable(self): self.open_test_html() self._test_focus_obtained_by_long_press(self._content, self._contenteditable) def test_contenteditable_handle_tilt_when_carets_overlap_to_each_other(self): self.open_test_html() self._test_handle_tilt_when_carets_overlap_to_each_other(self._contenteditable, self.assertEqual) def test_contenteditable_focus_not_changed_by_long_press_on_non_selectable(self): self.open_test_html() self._test_focus_not_being_changed_by_long_press_on_non_selectable(self._contenteditable) ######################################################################## # <div> contenteditable test cases with selection carets disabled ######################################################################## def test_contenteditable_long_press_to_select_a_word_disabled(self): with self.marionette.using_prefs({self.carets_tested_pref: False}): self.open_test_html() self._test_long_press_to_select_a_word(self._contenteditable, self.assertNotEqual) def test_contenteditable_move_selection_carets_disabled(self): with self.marionette.using_prefs({self.carets_tested_pref: False}): self.open_test_html() self._test_move_selection_carets(self._contenteditable, self.assertNotEqual) ######################################################################## # <div> non-editable test cases with selection carets enabled ######################################################################## def test_content_non_editable_long_press_to_select_a_word(self): self.open_test_html() self._test_long_press_to_select_a_word(self._content, self.assertEqual) def test_content_non_editable_move_selection_carets(self): self.open_test_html() self._test_move_selection_carets(self._content, self.assertEqual) def test_content_non_editable_minimum_select_one_character_by_selection(self): self.open_test_html() self._test_minimum_select_one_character(self._content, self.assertEqual) def test_content_non_editable_focus_obtained_by_long_press_from_input(self): self.open_test_html() self._test_focus_obtained_by_long_press(self._input, self._content) def test_content_non_editable_focus_obtained_by_long_press_from_textarea(self): self.open_test_html() self._test_focus_obtained_by_long_press(self._textarea, self._content) def test_content_non_editable_focus_obtained_by_long_press_from_contenteditable(self): self.open_test_html() self._test_focus_obtained_by_long_press(self._contenteditable, self._content) def test_content_non_editable_handle_tilt_when_carets_overlap_to_each_other(self): self.open_test_html() self._test_handle_tilt_when_carets_overlap_to_each_other(self._content, self.assertEqual) ######################################################################## # <textarea> (multi-lines) test cases with selection carets enabled ######################################################################## def test_textarea2_minimum_select_one_character(self): self.open_test_html2() self._test_minimum_select_one_character(self._textarea2, self.assertEqual) ######################################################################## # <div> contenteditable2 (multi-lines) test cases with selection carets enabled ######################################################################## def test_contenteditable2_minimum_select_one_character(self): self.open_test_html2() self._test_minimum_select_one_character(self._contenteditable2, self.assertEqual) ######################################################################## # <div> non-editable2 (multi-lines) test cases with selection carets enabled ######################################################################## def test_content_non_editable2_minimum_select_one_character(self): self.open_test_html2() self._test_minimum_select_one_character(self._content2, self.assertEqual)
class TestKeyActions(WindowManagerMixin, MarionetteTestCase): def setUp(self): super(TestKeyActions, self).setUp() if self.marionette.session_capabilities["platformName"] == "darwin": self.mod_key = Keys.META else: self.mod_key = Keys.CONTROL test_html = self.marionette.absolute_url("keyboard.html") self.marionette.navigate(test_html) self.reporter_element = self.marionette.find_element( By.ID, "keyReporter") self.reporter_element.click() self.key_action = Actions(self.marionette) @property def key_reporter_value(self): return self.reporter_element.get_property("value") def test_key_action_basic_input(self): self.key_action.key_down("a").key_down("b").key_down("c").perform() self.assertEqual(self.key_reporter_value, "abc") def test_upcase_input(self): (self.key_action.key_down(Keys.SHIFT).key_down("a").key_up( Keys.SHIFT).key_down("b").key_down("c").perform()) self.assertEqual(self.key_reporter_value, "Abc") def test_replace_input(self): self.key_action.key_down("a").key_down("b").key_down("c").perform() self.assertEqual(self.key_reporter_value, "abc") (self.key_action.key_down(self.mod_key).key_down("a").key_up( self.mod_key).key_down("x").perform()) self.assertEqual(self.key_reporter_value, "x") def test_clear_input(self): self.key_action.key_down("a").key_down("b").key_down("c").perform() self.assertEqual(self.key_reporter_value, "abc") (self.key_action.key_down( self.mod_key).key_down("a").key_down("x").perform()) self.assertEqual(self.key_reporter_value, "") self.key_action.key_down("a").key_down("b").key_down("c").perform() self.assertEqual(self.key_reporter_value, "abc") def test_input_with_wait(self): self.key_action.key_down("a").key_down("b").key_down("c").perform() (self.key_action.key_down( self.mod_key).key_down("a").wait(.5).key_down("x").perform()) self.assertEqual(self.key_reporter_value, "") @skip_if_mobile("Interacting with chrome windows not available for Fennec") def test_open_in_new_window_shortcut(self): def open_window_with_action(): el = self.marionette.find_element(By.TAG_NAME, "a") (self.key_action.key_down(Keys.SHIFT).press(el).release().key_up( Keys.SHIFT).perform()) self.marionette.navigate(inline("<a href='#'>Click</a>")) new_window = self.open_window(trigger=open_window_with_action) self.marionette.switch_to_window(new_window) self.marionette.close_chrome_window() self.marionette.switch_to_window(self.start_window)
class TestMouseAction(MarionetteTestCase): def setUp(self): MarionetteTestCase.setUp(self) if self.marionette.session_capabilities['platformName'] == 'DARWIN': self.mod_key = Keys.META else: self.mod_key = Keys.CONTROL self.action = Actions(self.marionette) def test_click_action(self): test_html = self.marionette.absolute_url("test.html") self.marionette.navigate(test_html) link = self.marionette.find_element(By.ID, "mozLink") self.action.click(link).perform() self.assertEqual("Clicked", self.marionette.execute_script("return document.getElementById('mozLink').innerHTML;")) def test_clicking_element_out_of_view_succeeds(self): # The action based click doesn't check for visibility. test_html = self.marionette.absolute_url('hidden.html') self.marionette.navigate(test_html) el = self.marionette.find_element(By.ID, 'child') self.action.click(el).perform() def test_double_click_action(self): test_html = self.marionette.absolute_url("javascriptPage.html") self.marionette.navigate(test_html) el = self.marionette.find_element(By.ID, 'displayed') # The first click just brings the element into view so text selection # works as expected. (A different test page could be used to isolate # this element and make sure it's always in view) el.click() self.action.double_click(el).perform() el.send_keys(self.mod_key + 'c') rel = self.marionette.find_element("id", "keyReporter") rel.send_keys(self.mod_key + 'v') self.assertEqual(rel.get_attribute('value'), 'Displayed') def test_context_click_action(self): test_html = self.marionette.absolute_url("javascriptPage.html") self.marionette.navigate(test_html) click_el = self.marionette.find_element(By.ID, 'resultContainer') def context_menu_state(): with self.marionette.using_context('chrome'): cm_el = self.marionette.find_element(By.ID, 'contentAreaContextMenu') return cm_el.get_attribute('state') self.assertEqual('closed', context_menu_state()) self.action.context_click(click_el).perform() self.wait_for_condition(lambda _: context_menu_state() == 'open') with self.marionette.using_context('chrome'): (self.marionette.find_element(By.ID, 'main-window') .send_keys(Keys.ESCAPE)) self.wait_for_condition(lambda _: context_menu_state() == 'closed') def test_middle_click_action(self): test_html = self.marionette.absolute_url("clicks.html") self.marionette.navigate(test_html) self.marionette.find_element(By.ID, "addbuttonlistener").click() el = self.marionette.find_element(By.ID, "showbutton") self.action.middle_click(el).perform() self.wait_for_condition( lambda _: el.get_attribute('innerHTML') == '1') def test_chrome_click(self): self.marionette.navigate("about:blank") data_uri = "data:text/html,<html></html>" with self.marionette.using_context('chrome'): urlbar = self.marionette.find_element(By.ID, "urlbar") urlbar.send_keys(data_uri) go_button = self.marionette.find_element(By.ID, "urlbar-go-button") self.action.click(go_button).perform() self.wait_for_condition(lambda mn: mn.get_url() == data_uri) def test_chrome_double_click(self): self.marionette.navigate("about:blank") test_word = "quux" with self.marionette.using_context('chrome'): urlbar = self.marionette.find_element(By.ID, "urlbar") self.assertEqual(urlbar.get_attribute('value'), '') urlbar.send_keys(test_word) self.assertEqual(urlbar.get_attribute('value'), test_word) (self.action.double_click(urlbar).perform() .key_down(self.mod_key) .key_down('x').perform()) self.assertEqual(urlbar.get_attribute('value'), '') def test_chrome_context_click_action(self): self.marionette.set_context('chrome') def context_menu_state(): cm_el = self.marionette.find_element(By.ID, 'tabContextMenu') return cm_el.get_attribute('state') currtab = self.marionette.execute_script("return gBrowser.selectedTab") self.assertEqual('closed', context_menu_state()) self.action.context_click(currtab).perform() self.wait_for_condition(lambda _: context_menu_state() == 'open') (self.marionette.find_element(By.ID, 'main-window') .send_keys(Keys.ESCAPE)) self.wait_for_condition(lambda _: context_menu_state() == 'closed')
def clear_phone_number(self): delete_button = self.marionette.find_element( *self._keypad_delete_locator) Actions(self.marionette).long_press(delete_button, 1).perform()
def __init__(self, parent): self.parent = parent self.marionette = parent.marionette self.actions = Actions(self.marionette)
class CommonCaretTestCase(object): '''Common test cases for a collapsed selection with a single caret. To run these test cases, a subclass must inherit from both this class and MarionetteTestCase. ''' def setUp(self): # Code to execute before a test is being run. super(CommonCaretTestCase, self).setUp() self.actions = Actions(self.marionette) def timeout_ms(self): 'Return touch caret expiration time in milliseconds.' return self.marionette.get_pref(self.caret_timeout_ms_pref) def open_test_html(self): 'Open html for testing and locate elements.' test_html = self.marionette.absolute_url('test_touchcaret.html') self.marionette.navigate(test_html) self._input = self.marionette.find_element(By.ID, 'input') self._textarea = self.marionette.find_element(By.ID, 'textarea') self._contenteditable = self.marionette.find_element( By.ID, 'contenteditable') def _test_move_caret_to_the_right_by_one_character(self, el, assertFunc): 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. 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() # Tap the front of the input to make touch caret appear. el.tap(caret0_x, caret0_y) # Move touch caret self.actions.flick(el, touch_caret0_x, touch_caret0_y, touch_caret1_x, touch_caret1_y).perform() self.actions.key_down(content_to_add).key_up(content_to_add).perform() assertFunc(target_content, sel.content) def _test_move_caret_to_end_by_dragging_touch_caret_to_bottom_right_corner( self, el, assertFunc): sel = SelectionManager(el) content_to_add = '!' target_content = sel.content + content_to_add # Tap the front of the input to make touch caret appear. el.tap() sel.move_caret_to_front() el.tap(*sel.caret_location()) # Move touch caret to the bottom-right corner of the element. src_x, src_y = sel.touch_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() assertFunc(target_content, sel.content) def _test_move_caret_to_front_by_dragging_touch_caret_to_front_of_content( self, el, assertFunc): sel = SelectionManager(el) content_to_add = '!' target_content = content_to_add + sel.content # Get touch caret location at the front. el.tap() sel.move_caret_to_front() dest_x, dest_y = sel.touch_caret_location() # Tap to make touch 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() # Move touch 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() assertFunc(target_content, sel.content) def _test_touch_caret_timeout_by_dragging_it_to_top_left_corner_after_timout( self, el, assertFunc): sel = SelectionManager(el) content_to_add = '!' non_target_content = content_to_add + sel.content # Get touch caret expiration time in millisecond, and convert it to second. timeout = self.timeout_ms() / 1000.0 # 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 # 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()) # Wait until touch caret disappears, then pretend to move it to the # top-left corner of the input box. src_x, src_y = sel.touch_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() assertFunc(non_target_content, sel.content) def _test_touch_caret_hides_after_receiving_wheel_event( self, el, assertFunc): sel = SelectionManager(el) content_to_add = '!' non_target_content = content_to_add + sel.content # Tap to make touch 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()) # Send an arbitrary scroll-down-10px wheel event to the center of the # input box to hide touch caret. Then pretend to move it to the top-left # corner of the input box. src_x, src_y = sel.touch_caret_location() dest_x, dest_y = 0, 0 el_center_x, el_center_y = el.rect['x'], el.rect['y'] self.marionette.execute_script(''' var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor) .getInterface(Components.interfaces.nsIDOMWindowUtils); utils.sendWheelEvent(arguments[0], arguments[1], 0, 10, 0, WheelEvent.DOM_DELTA_PIXEL, 0, 0, 0, 0); ''', script_args=[el_center_x, el_center_y], sandbox='system') 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() assertFunc(non_target_content, sel.content) def _test_caret_not_appear_when_typing_in_scrollable_content( self, el, assertFunc): sel = SelectionManager(el) content_to_add = '!' target_content = sel.content + string.ascii_letters + content_to_add el.tap() sel.move_caret_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() 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) assertFunc(target_content, sel.content) ######################################################################## # <input> test cases with touch caret enabled ######################################################################## def test_input_move_caret_to_the_right_by_one_character(self): self.open_test_html() self._test_move_caret_to_the_right_by_one_character( self._input, self.assertEqual) def test_input_move_caret_to_end_by_dragging_touch_caret_to_bottom_right_corner( self): self.open_test_html() self._test_move_caret_to_end_by_dragging_touch_caret_to_bottom_right_corner( self._input, self.assertEqual) def test_input_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner( self): self.open_test_html() self._test_move_caret_to_front_by_dragging_touch_caret_to_front_of_content( self._input, self.assertEqual) def test_input_caret_not_appear_when_typing_in_scrollable_content(self): self.open_test_html() self._test_caret_not_appear_when_typing_in_scrollable_content( self._input, self.assertEqual) def test_input_touch_caret_timeout(self): with self.marionette.using_prefs({self.caret_timeout_ms_pref: 1000}): self.open_test_html() self._test_touch_caret_timeout_by_dragging_it_to_top_left_corner_after_timout( self._input, self.assertNotEqual) ######################################################################## # <input> test cases with touch caret disabled ######################################################################## def test_input_move_caret_to_the_right_by_one_character_disabled(self): with self.marionette.using_prefs({self.caret_tested_pref: False}): self.open_test_html() self._test_move_caret_to_the_right_by_one_character( self._input, self.assertNotEqual) def test_input_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner_disabled( self): with self.marionette.using_prefs({self.caret_tested_pref: False}): self.open_test_html() self._test_move_caret_to_front_by_dragging_touch_caret_to_front_of_content( self._input, self.assertNotEqual) ######################################################################## # <textarea> test cases with touch caret enabled ######################################################################## def test_textarea_move_caret_to_the_right_by_one_character(self): self.open_test_html() self._test_move_caret_to_the_right_by_one_character( self._textarea, self.assertEqual) def test_textarea_move_caret_to_end_by_dragging_touch_caret_to_bottom_right_corner( self): self.open_test_html() self._test_move_caret_to_end_by_dragging_touch_caret_to_bottom_right_corner( self._textarea, self.assertEqual) def test_textarea_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner( self): self.open_test_html() self._test_move_caret_to_front_by_dragging_touch_caret_to_front_of_content( self._textarea, self.assertEqual) def test_textarea_touch_caret_timeout(self): with self.marionette.using_prefs({self.caret_timeout_ms_pref: 1000}): self.open_test_html() self._test_touch_caret_timeout_by_dragging_it_to_top_left_corner_after_timout( self._textarea, self.assertNotEqual) ######################################################################## # <textarea> test cases with touch caret disabled ######################################################################## def test_textarea_move_caret_to_the_right_by_one_character_disabled(self): with self.marionette.using_prefs({self.caret_tested_pref: False}): self.open_test_html() self._test_move_caret_to_the_right_by_one_character( self._textarea, self.assertNotEqual) def test_textarea_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner_disabled( self): with self.marionette.using_prefs({self.caret_tested_pref: False}): self.open_test_html() self._test_move_caret_to_front_by_dragging_touch_caret_to_front_of_content( self._textarea, self.assertNotEqual) ######################################################################## # <div> contenteditable test cases with touch caret enabled ######################################################################## def test_contenteditable_move_caret_to_the_right_by_one_character(self): self.open_test_html() self._test_move_caret_to_the_right_by_one_character( self._contenteditable, self.assertEqual) def test_contenteditable_move_caret_to_end_by_dragging_touch_caret_to_bottom_right_corner( self): self.open_test_html() self._test_move_caret_to_end_by_dragging_touch_caret_to_bottom_right_corner( self._contenteditable, self.assertEqual) def test_contenteditable_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner( self): self.open_test_html() self._test_move_caret_to_front_by_dragging_touch_caret_to_front_of_content( self._contenteditable, self.assertEqual) def test_contenteditable_touch_caret_timeout(self): with self.marionette.using_prefs({self.caret_timeout_ms_pref: 1000}): self.open_test_html() self._test_touch_caret_timeout_by_dragging_it_to_top_left_corner_after_timout( self._contenteditable, self.assertNotEqual) ######################################################################## # <div> contenteditable test cases with touch caret disabled ######################################################################## def test_contenteditable_move_caret_to_the_right_by_one_character_disabled( self): with self.marionette.using_prefs({self.caret_tested_pref: False}): self.open_test_html() self._test_move_caret_to_the_right_by_one_character( self._contenteditable, self.assertNotEqual) def test_contenteditable_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner_disabled( self): with self.marionette.using_prefs({self.caret_tested_pref: False}): self.open_test_html() self._test_move_caret_to_front_by_dragging_touch_caret_to_front_of_content( self._contenteditable, self.assertNotEqual)
def setUp(self): # Code to execute before a test is being run. super(CommonCaretTestCase, self).setUp() self.actions = Actions(self.marionette)
class TouchCaretTest(MarionetteTestCase): _input_selector = (By.ID, 'input') _textarea_selector = (By.ID, 'textarea') _contenteditable_selector = (By.ID, 'contenteditable') _large_expiration_time = 3000 * 20 # 60 seconds def setUp(self): # Code to execute before a test is being run. MarionetteTestCase.setUp(self) self.actions = Actions(self.marionette) self.original_expiration_time = self.expiration_time def tearDown(self): # Code to execute after a test is being run. self.expiration_time = self.original_expiration_time MarionetteTestCase.tearDown(self) @property def expiration_time(self): 'Return touch caret expiration time in milliseconds.' return self.marionette.execute_script( 'return SpecialPowers.getIntPref("touchcaret.expiration.time");') @expiration_time.setter def expiration_time(self, expiration_time): 'Set touch caret expiration time in milliseconds.' self.marionette.execute_script( 'SpecialPowers.setIntPref("touchcaret.expiration.time", arguments[0]);', script_args=[expiration_time]) def openTestHtml(self, enabled=True, expiration_time=None): '''Open html for testing and locate elements, enable/disable touch caret, and set touch caret expiration time in milliseconds). ''' self.marionette.execute_async_script( 'SpecialPowers.pushPrefEnv({"set": [["touchcaret.enabled", %s]]}, marionetteScriptFinished);' % ('true' if enabled else 'false')) # Set a larger expiration time to avoid intermittent test failures. if expiration_time is not None: self.expiration_time = expiration_time test_html = self.marionette.absolute_url('test_touchcaret.html') self.marionette.navigate(test_html) self._input = self.marionette.find_element(*self._input_selector) self._textarea = self.marionette.find_element(*self._textarea_selector) self._contenteditable = self.marionette.find_element(*self._contenteditable_selector) def _test_move_caret_to_the_right_by_one_character(self, el, assertFunc): 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. 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() # Tap the front of the input to make touch caret appear. el.tap(caret0_x, caret0_y) # Move touch caret self.actions.flick(el, touch_caret0_x, touch_caret0_y, touch_caret1_x, touch_caret1_y).perform() el.send_keys(content_to_add) assertFunc(target_content, sel.content) def _test_move_caret_to_end_by_dragging_touch_caret_to_bottom_right_corner(self, el, assertFunc): sel = SelectionManager(el) content_to_add = '!' target_content = sel.content + content_to_add # Tap the front of the input to make touch caret appear. el.tap() sel.move_caret_to_front() el.tap(*sel.caret_location()) # Move touch caret to the bottom-right corner of the element. src_x, src_y = sel.touch_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() el.send_keys(content_to_add) assertFunc(target_content, sel.content) def _test_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner(self, el, assertFunc): sel = SelectionManager(el) content_to_add = '!' target_content = content_to_add + sel.content # Tap to make touch 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()) # Move touch caret to the top-left corner of the input box. src_x, src_y = sel.touch_caret_location() dest_x, dest_y = 0, 0 self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform() el.send_keys(content_to_add) assertFunc(target_content, sel.content) def _test_touch_caret_timeout_by_dragging_it_to_top_left_corner_after_timout(self, el, assertFunc): sel = SelectionManager(el) content_to_add = '!' non_target_content = content_to_add + sel.content # Get touch caret expiration time in millisecond, and convert it to second. timeout = self.expiration_time / 1000.0 # Tap to make touch 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()) # Wait until touch caret disappears, then pretend to move it to the # top-left corner of the input box. src_x, src_y = sel.touch_caret_location() dest_x, dest_y = 0, 0 self.actions.wait(timeout).flick(el, src_x, src_y, dest_x, dest_y).perform() el.send_keys(content_to_add) assertFunc(non_target_content, sel.content) def _test_touch_caret_hides_after_receiving_wheel_event(self, el, assertFunc): sel = SelectionManager(el) content_to_add = '!' non_target_content = content_to_add + sel.content # Tap to make touch 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()) # Send an arbitrary scroll-down-10px wheel event to the center of the # input box to hide touch caret. Then pretend to move it to the top-left # corner of the input box. src_x, src_y = sel.touch_caret_location() dest_x, dest_y = 0, 0 el_center_x, el_center_y = el.rect['x'], el.rect['y'] self.marionette.execute_script( '''var utils = SpecialPowers.getDOMWindowUtils(window); utils.sendWheelEvent(arguments[0], arguments[1], 0, 10, 0, WheelEvent.DOM_DELTA_PIXEL, 0, 0, 0, 0);''', script_args=[el_center_x, el_center_y] ) self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform() el.send_keys(content_to_add) assertFunc(non_target_content, sel.content) ######################################################################## # <input> test cases with touch caret enabled ######################################################################## def test_input_move_caret_to_the_right_by_one_character(self): self.openTestHtml(enabled=True, expiration_time=self._large_expiration_time) self._test_move_caret_to_the_right_by_one_character(self._input, self.assertEqual) def test_input_move_caret_to_end_by_dragging_touch_caret_to_bottom_right_corner(self): self.openTestHtml(enabled=True, expiration_time=self._large_expiration_time) self._test_move_caret_to_end_by_dragging_touch_caret_to_bottom_right_corner(self._input, self.assertEqual) def test_input_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner(self): self.openTestHtml(enabled=True, expiration_time=self._large_expiration_time) self._test_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner(self._input, self.assertEqual) def test_input_touch_caret_timeout(self): self.openTestHtml(enabled=True) self._test_touch_caret_timeout_by_dragging_it_to_top_left_corner_after_timout(self._input, self.assertNotEqual) def test_input_touch_caret_hides_after_receiving_wheel_event(self): self.openTestHtml(enabled=True, expiration_time=0) self._test_touch_caret_hides_after_receiving_wheel_event(self._input, self.assertNotEqual) ######################################################################## # <input> test cases with touch caret disabled ######################################################################## def test_input_move_caret_to_the_right_by_one_character_disabled(self): self.openTestHtml(enabled=False) self._test_move_caret_to_the_right_by_one_character(self._input, self.assertNotEqual) def test_input_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner_disabled(self): self.openTestHtml(enabled=False) self._test_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner(self._input, self.assertNotEqual) ######################################################################## # <textarea> test cases with touch caret enabled ######################################################################## def test_textarea_move_caret_to_the_right_by_one_character(self): self.openTestHtml(enabled=True, expiration_time=self._large_expiration_time) self._test_move_caret_to_the_right_by_one_character(self._textarea, self.assertEqual) def test_textarea_move_caret_to_end_by_dragging_touch_caret_to_bottom_right_corner(self): self.openTestHtml(enabled=True, expiration_time=self._large_expiration_time) self._test_move_caret_to_end_by_dragging_touch_caret_to_bottom_right_corner(self._textarea, self.assertEqual) def test_textarea_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner(self): self.openTestHtml(enabled=True, expiration_time=self._large_expiration_time) self._test_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner(self._textarea, self.assertEqual) def test_textarea_touch_caret_timeout(self): self.openTestHtml(enabled=True) self._test_touch_caret_timeout_by_dragging_it_to_top_left_corner_after_timout(self._textarea, self.assertNotEqual) def test_textarea_touch_caret_hides_after_receiving_wheel_event(self): self.openTestHtml(enabled=True, expiration_time=0) self._test_touch_caret_hides_after_receiving_wheel_event(self._textarea, self.assertNotEqual) ######################################################################## # <textarea> test cases with touch caret disabled ######################################################################## def test_textarea_move_caret_to_the_right_by_one_character_disabled(self): self.openTestHtml(enabled=False) self._test_move_caret_to_the_right_by_one_character(self._textarea, self.assertNotEqual) def test_textarea_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner_disabled(self): self.openTestHtml(enabled=False) self._test_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner(self._textarea, self.assertNotEqual) ######################################################################## # <div> contenteditable test cases with touch caret enabled ######################################################################## def test_contenteditable_move_caret_to_the_right_by_one_character(self): self.openTestHtml(enabled=True, expiration_time=self._large_expiration_time) self._test_move_caret_to_the_right_by_one_character(self._contenteditable, self.assertEqual) def test_contenteditable_move_caret_to_end_by_dragging_touch_caret_to_bottom_right_corner(self): self.openTestHtml(enabled=True, expiration_time=self._large_expiration_time) self._test_move_caret_to_end_by_dragging_touch_caret_to_bottom_right_corner(self._contenteditable, self.assertEqual) def test_contenteditable_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner(self): self.openTestHtml(enabled=True, expiration_time=self._large_expiration_time) self._test_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner(self._contenteditable, self.assertEqual) def test_contenteditable_touch_caret_timeout(self): self.openTestHtml(enabled=True) self._test_touch_caret_timeout_by_dragging_it_to_top_left_corner_after_timout(self._contenteditable, self.assertNotEqual) def test_contenteditable_touch_caret_hides_after_receiving_wheel_event(self): self.openTestHtml(enabled=True, expiration_time=0) self._test_touch_caret_hides_after_receiving_wheel_event(self._contenteditable, self.assertNotEqual) ######################################################################## # <div> contenteditable test cases with touch caret disabled ######################################################################## def test_contenteditable_move_caret_to_the_right_by_one_character_disabled(self): self.openTestHtml(enabled=False) self._test_move_caret_to_the_right_by_one_character(self._contenteditable, self.assertNotEqual) def test_contenteditable_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner_disabled(self): self.openTestHtml(enabled=False) self._test_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner(self._contenteditable, self.assertNotEqual)
class SelectionCaretsMultipleRangeTest(MarionetteTestCase): _long_press_time = 1 # 1 second def setUp(self): # Code to execute before a tests are run. MarionetteTestCase.setUp(self) self.actions = Actions(self.marionette) def openTestHtml(self, enabled=True): # Open html for testing and enable selectioncaret and # non-editable support self.marionette.execute_script( 'SpecialPowers.setBoolPref("selectioncaret.enabled", %s);' % ('true' if enabled else 'false')) self.marionette.execute_script( 'SpecialPowers.setBoolPref("selectioncaret.noneditable", %s);' % ('true' if enabled else 'false')) test_html = self.marionette.absolute_url('test_selectioncarets_multiplerange.html') self.marionette.navigate(test_html) self._body = self.marionette.find_element(By.ID, 'bd') self._sel1 = self.marionette.find_element(By.ID, 'sel1') self._sel2 = self.marionette.find_element(By.ID, 'sel2') self._sel3 = self.marionette.find_element(By.ID, 'sel3') self._sel4 = self.marionette.find_element(By.ID, 'sel4') self._sel6 = self.marionette.find_element(By.ID, 'sel6') self._nonsel1 = self.marionette.find_element(By.ID, 'nonsel1') def _long_press_to_select_word(self, el, wordOrdinal): sel = SelectionManager(el) original_content = sel.content words = original_content.split() self.assertTrue(wordOrdinal < len(words), 'Expect at least %d words in the content.' % wordOrdinal) # Calc offset offset = 0 for i in range(wordOrdinal): offset += (len(words[i]) + 1) # Move caret inside the word. el.tap() sel.move_caret_to_front() sel.move_caret_by_offset(offset) x, y = sel.caret_location() # Long press the caret position. Selection carets should appear, and the # word will be selected. On Windows, those spaces after the word # will also be selected. long_press_without_contextmenu(self.marionette, el, self._long_press_time, x, y) def _to_unix_line_ending(self, s): """Changes all Windows/Mac line endings in s to UNIX line endings.""" return s.replace('\r\n', '\n').replace('\r', '\n') def test_long_press_to_select_non_selectable_word(self): '''Testing long press on non selectable field. We should not select anything when long press on non selectable fields.''' self.openTestHtml(enabled=True) halfY = self._nonsel1.size['height'] / 2 long_press_without_contextmenu(self.marionette, self._nonsel1, self._long_press_time, 0, halfY) sel = SelectionManager(self._nonsel1) range_count = sel.range_count() self.assertEqual(range_count, 0) 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.''' self.openTestHtml(enabled=True) # Select target element and get target caret location self._long_press_to_select_word(self._sel4, 3) sel = SelectionManager(self._body) (_, _), (end_caret_x, end_caret_y) = sel.selection_carets_location() self._long_press_to_select_word(self._sel6, 0) (_, _), (end_caret2_x, end_caret2_y) = sel.selection_carets_location() # Select start element self._long_press_to_select_word(self._sel3, 3) # Drag end caret to target location (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location() self.actions.flick(self._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() self.actions.flick(self._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') 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.openTestHtml(enabled=True) # Select the first word in the second line self._long_press_to_select_word(self._sel2, 0) sel = SelectionManager(self._body) (start_caret_x, start_caret_y), (end_caret_x, end_caret_y) = sel.selection_carets_location() # Select target word in the first line self._long_press_to_select_word(self._sel1, 2) # Drag end caret to the beginning of the second line (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location() self.actions.flick(self._body, caret2_x, caret2_y, start_caret_x, start_caret_y).perform() # Drag end caret back to the target word self.actions.flick(self._body, start_caret_x, start_caret_y, caret2_x, caret2_y).perform() self.assertEqual(self._to_unix_line_ending(sel.selected_content.strip()), 'select')
def setUp(self): # Code to execute before a test is being run. MarionetteTestCase.setUp(self) self.actions = Actions(self.marionette) self.original_expiration_time = self.expiration_time
class Gallery(object): def __init__(self, parent): self.apps = parent.apps self.data_layer = parent.data_layer self.parent = parent self.marionette = parent.marionette self.UTILS = parent.UTILS self.actions = Actions(self.marionette) def launch(self): self.app = self.apps.launch(self.__class__.__name__) self.UTILS.element.waitForNotElements( DOM.GLOBAL.loading_overlay, self.__class__.__name__ + " app - loading overlay") self.UTILS.element.waitForNotElements(DOM.Gallery.loading_bar, "Loading bar", True, 10) return self.app def convert_str_to_seconds(self, the_string): """ Converts a str of the form "aa:bb" into seconds """ processed = time.strptime(the_string, '%M:%S') return (int( datetime.timedelta(minutes=processed.tm_min, seconds=processed.tm_sec).total_seconds())) def check_video_length(self, expected_duration, margin=2): """ This method asserts that the video has the desired duration @param int expected_duration specifies the video duration in seconds """ # Play the video and get total duration self.play_current_video() video_length = self.UTILS.element.getElement( DOM.Gallery.preview_current_video_duration, "Video length") real_duration = self.convert_str_to_seconds(video_length.text) # Note: we give 1 second margin in case the things went a little bit slower when recording the video interval = range(expected_duration - margin, expected_duration + margin + 1, 1) self.UTILS.test.test(real_duration in interval, "Duration matches") def click_on_thumbnail_at_position(self, position, preview=True): """ Clicks on a thumbnail at a certain position from the gallery. @param boolean preview specifies whether we have to check for the preview screen or not """ self.parent.wait_for_element_displayed(*DOM.Gallery.thumbnail_items) thumb_list = self.marionette.find_elements( *DOM.Gallery.thumbnail_items) time.sleep(1) thumb = thumb_list[position] thumb.tap() self.UTILS.element.waitForNotElements(DOM.Gallery.thumbnail_items, "Thumbnail list", True, 10) if preview: self.UTILS.element.waitForElements(DOM.Gallery.preview, "Thumbnail preview", True, 10) def _click_on_thumb_external(self, position, frame_to_change): """ Private method which handles image selection and image cropping @param int position thumbnail to click @param tuple frame_to_change frame to switch once the image has been cropped """ time.sleep(1) self.click_on_thumbnail_at_position(position, preview=False) time.sleep(2) crop = self.UTILS.element.getElement(DOM.Gallery.crop_done, "Crop Done") crop.tap() self.UTILS.iframe.switchToFrame(*frame_to_change) def click_on_thumbnail_at_position_mms(self, position): """ Clicks a thumbnail from the gallery in order to attach it to a MMS """ self._click_on_thumb_external(position, DOM.Messages.frame_locator) def click_on_thumbnail_at_position_email(self, position): """ Clicks a thumbnail from the gallery in order to attach it to an email """ self._click_on_thumb_external(position, DOM.Email.frame_locator) def delete_thumbnails(self, num_array): """ Deletes the thumbnails listed in num_array (following an index starting at number 0) The list must be numeric, i.e "delete_thumbnails([0,1,2])". """ # Get the amount of thumbnails we currently have. before_thumbcount = self.get_number_of_thumbnails() delete_thumbcount = len(num_array) target_thumbcount = before_thumbcount - delete_thumbcount select_mode_btn = self.UTILS.element.getElement( DOM.Gallery.thumbnail_select_mode, "Select button") select_mode_btn.tap() # Select the target ones thumbs = self.UTILS.element.getElements(DOM.Gallery.thumbnail_items, "Thumbnails") for position in num_array: thumbs[position].tap() selected = self.UTILS.element.getElement( DOM.Gallery.thumbnail_number_selected, "Number selected header") self.UTILS.test.test( str(delete_thumbcount) in selected.text, "Right number of thumbs selected") trash_btn = self.UTILS.element.getElement( DOM.Gallery.thumbnail_trash_icon, "Trash icon") trash_btn.tap() confirm = self.UTILS.element.getElement(DOM.GLOBAL.modal_confirm_ok, "Delete") confirm.tap() if target_thumbcount < 1: self.UTILS.element.waitForElements( DOM.Gallery.no_thumbnails_message, "Message saying there are no thumbnails", False, 5) else: # Come out of 'select' mode. exit_select_mode_header = self.UTILS.element.getElement( DOM.Gallery.exit_select_mode_header, "Exit select mode button") exit_select_mode_header.tap(25, 25) current_thumbs = self.get_number_of_thumbnails() self.UTILS.test.test(current_thumbs == target_thumbcount, "After deleting [{}] pics, we have the expected number: {}".\ format(delete_thumbcount, target_thumbcount)) def get_gallery_items(self): """ Returns a list of gallery item objects, with RAW info (date, metadata, size...) """ self.UTILS.element.waitForElements(DOM.Gallery.thumbnail_items, "Thumbnails", True, 20, False) return self.marionette.execute_script( "return window.wrappedJSObject.files;") def play_current_video(self): """ Plays the video that has previously been loaded (by pressing its thumbnail first), then press a play button. """ play_btn = self.UTILS.element.getElement( DOM.Gallery.preview_current_video_play, "Video play button") time.sleep(1) play_btn.tap() self.UTILS.element.waitForElements( DOM.Gallery.preview_current_video_pause, "Pause button", True, 20, False) def get_number_of_thumbnails(self): """ Returns the number of thumbnails. """ try: self.parent.wait_for_element_displayed( *DOM.Gallery.thumbnail_items) return len( self.marionette.find_elements(*DOM.Gallery.thumbnail_items)) except: return 0 def wait_for_thumbnails_number(self, number, timeout=10): """ Waits untils @number thumbnails are present in the thumbnails screen """ msg = "Waiting until we have the expected number of thumbnails" self.parent.wait_for_condition(lambda m: len( m.find_elements(*DOM.Gallery.thumbnail_items)) == number, timeout=timeout, message=msg) def swipe_between_gallery_items(self, steps): """ Swipes over the gallery items (the preview screen must be displayed) a certain number of steps Important: there is no way of checking that the image is being shown each time we swipe, """ current_frame = self.apps.displayed_app.frame x_start = current_frame.size['width'] x_end = x_start // 4 y_start = current_frame.size['height'] // 2 for i in range(steps): self.actions.flick(current_frame, x_start, y_start, x_end, y_start, duration=600).perform() time.sleep(1)
class Calendar(object): def __init__(self, parent): self.apps = parent.apps self.data_layer = parent.data_layer self.parent = parent self.marionette = parent.marionette self.UTILS = parent.UTILS self.actions = Actions(self.marionette) def launch(self): self.app = self.apps.launch(self.__class__.__name__) self.UTILS.element.waitForNotElements( DOM.GLOBAL.loading_overlay, self.__class__.__name__ + " app - loading overlay") return self.app def moveDayViewBy(self, num): """ Switches to week view, then moves 'p_num' weeks in the future or past (if the p_num is positive or negative) relative to today. """ self.UTILS.reporting.logResult( "info", "<b>Adjusting day view by {} screens ...</b>".format(num)) self.setView("day") self.setView("today") if num == 0: return """ Set the y-coordinate offset, depending on which direction we need to flick the display. """ numMoves = num if numMoves > 0: _moveEl = 1 else: _moveEl = 2 numMoves = numMoves * -1 # Now move to the desired screen. for i in range(numMoves): # Flick the screen to move it (tricky to find the element we can flick!). _el = self.marionette.find_elements(*DOM.Calendar.dview_events) _num = 0 for i in range(len(_el)): if _el[i].is_displayed(): _num = i break x_pos1 = 0 x_pos2 = 0 if _moveEl == 1: x_pos1 = _el[_num].size["width"] if _moveEl == 2: x_pos2 = _el[_num].size["width"] self.actions.flick(_el[_num], x_pos1, 0, x_pos2, 0).perform() time.sleep(0.3) # Check this is the expected day. _new_epoch = int(time.time()) + (num * 24 * 60 * 60) _new_now = self.UTILS.date_and_time.getDateTimeFromEpochSecs( _new_epoch) _expected_str = "{} {}, {}".format(_new_now.month_name[:3], _new_now.mday, _new_now.day_name) x = self.UTILS.element.getElement(DOM.Calendar.current_view_header, "Current view header") self.UTILS.test.test( x.text == _expected_str, "Header is '<b>%s</b>' (it was '%s')." % (_expected_str, x.text)) x = self.UTILS.debug.screenShotOnErr() self.UTILS.reporting.logResult( "info", "Day view screen after moving {} pages: ".format(num), x) def getEventPreview(self, p_view, p_hour24, p_title, p_location=False): """ Return object for an event in month / week or day view. The tag identifiers aren't consistent, so set them here. <type>: (<event preview identifier>, <event title identifier>) """ event_view = { "month": (DOM.Calendar.view_events_block_m % p_hour24, DOM.Calendar.view_events_title_month), "week": (DOM.Calendar.view_events_block_w % p_hour24, DOM.Calendar.view_events_title_week), "day": (DOM.Calendar.view_events_block_d % p_hour24, DOM.Calendar.view_events_title_day) } viewStr = event_view[p_view] """ Switch to the desired view. For the life of me I can't get 'wait_for_element' ... to work in day view, so I'm just waiting a few seconds then checking with .is_displayed() instead. """ self.setView(p_view) time.sleep(2) # Start by getting the parent element objects, which could contain event details. event_objects = self.UTILS.element.getElements( ('xpath', viewStr[0]), "'" + p_view + "' event details list", False, 20, False) if not event_objects: return False if len(event_objects) <= 0: return False for event_object in event_objects: if p_title in event_object.text: return event_object # If we get to here we failed to return the element we're after. return False def createEvent(self): x = self.UTILS.element.getElement(DOM.Calendar.add_event_btn, "Add event button") x.tap() title = ("xpath", "//input[@name='title']") where = ("xpath", "//input[@name='location']") # allday checkbox, True False (use tap()) allday = ("xpath", "//li[@class='allday']") x = self.UTILS.element.getElement(title, "Title", True, 10) x.send_keys("hello title") x = self.UTILS.element.getElement(where, "Where") x.send_keys("hello where") x = self.UTILS.element.getElement(allday, "All day") x.tap() self.marionette.execute_script( "document.getElementById('start-date-locale').click()") def changeDay(self, numDays, viewType): """ Changes the calendar day to a different day relative to 'today' - <b>uses the month view to do this, then switches back to whichever view you want (month, week, day)</b>.<br> <b>numDays</b> is a number (can be negative to go back, i.e. -5,-2,1,3,5 etc...).<br> <b>viewType</b> is the calendar view to return to (today / day / week / month)<br> Returns a modified DateTime object from <i>UTILS.getDateTimeFromEpochSecs()</i>. """ self.setView("month") self.setView("today") now_secs = time.time() now_diff = int(now_secs) + (86400 * numDays) now_today = self.UTILS.date_and_time.getDateTimeFromEpochSecs(now_secs) new_today = self.UTILS.date_and_time.getDateTimeFromEpochSecs(now_diff) # Switch to month view and tap this day, then switch back to our view. if now_today.mon != new_today.mon: x = new_today.mon - now_today.mon self.moveMonthViewBy(x) el_id_str = "d-%s-%s-%s" % (new_today.year, new_today.mon - 1, new_today.mday) x = self.UTILS.element.getElement( ("xpath", "//li[@data-date='{}']".format(el_id_str)), "Cell for day {}/{}/{}".format(new_today.mday, new_today.mon, new_today.year)) x.tap() self.setView(viewType.lower()) return new_today def moveMonthViewBy(self, num): """ Switches to month view, then moves 'num' months in the future or past (if the num is positive or negative) relative to today. """ self.UTILS.reporting.logResult( "info", "<b>Adjusting month view by {} months ...</b>".format(num)) self.setView("month") self.setView("today") if num == 0: return """ Set the y-coordinate offset, depending on which direction we need to flick the display. """ numMoves = num x2 = 0 if numMoves > 0: el_num = -1 x2 = -500 if numMoves < 0: el_num = 0 x2 = 500 numMoves = numMoves * -1 now = time.localtime(int(time.time())) month = now.tm_mon year = now.tm_year for i in range(numMoves): # Flick the display to show the date we're aiming for. el = self.marionette.find_elements( *DOM.Calendar.mview_first_row_for_flick)[el_num] self.actions.flick(el, 0, 0, x2, 0).perform() # Increment the month and year so we keep track of what's expected. if num < 0: month = month - 1 else: month = month + 1 if month <= 0: month = 12 year = year - 1 elif month >= 13: month = 1 year = year + 1 time.sleep(0.3) # Work out what the header should now be. month_names = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ] expect = "{} {}".format(month_names[month - 1], year) actual = self.UTILS.element.getElement( DOM.Calendar.current_view_header, "Header").text self.UTILS.test.test( expect.lower() in actual.lower(), "Expecting header to contain '{}' (received '{}')".format( expect, actual)) def moveWeekViewBy(self, num): """ Switches to week view, then moves 'num' weeks in the future or past (if the num is positive or negative) relative to today. """ self.UTILS.reporting.logResult( "info", "<b>Adjusting week view by {} screens ...</b>".format(num)) self.setView("week") self.setView("today") if num == 0: return """ Set the y-coordinate offset, depending on which direction we need to flick the display. """ numMoves = num x2 = 0 if numMoves > 0: el = -1 x2 = -500 if numMoves < 0: el = 0 x2 = 500 numMoves = numMoves * -1 """ Keep track of how many days we're adjusting the display by (so we can check we're looking at the correct display at the end). """ days_offset = 0 now_epoch = int(time.time()) now = self.UTILS.date_and_time.getDateTimeFromEpochSecs(now_epoch) now_str = "{} {}".format(now.day_name[:3].upper(), now.mday) displayed_days = self.UTILS.element.getElements( DOM.Calendar.wview_active_days, "Active days") startpos = 0 for i in range(len(displayed_days)): x = displayed_days[i].text if x: if now_str in x: startpos = i - 1 break if num < 0: days_offset = startpos else: days_offset = len(displayed_days) - startpos - 2 # Now move to the desired screen. for i in range(numMoves): # Flick the screen to move it. self.actions.flick(displayed_days[el], 0, 0, x2, 0).perform() # Get the count of days we're adjusting (so we can check later). displayed_days = self.UTILS.element.getElements( DOM.Calendar.wview_active_days, "Active days") days_offset = days_offset + len(displayed_days) time.sleep(0.3) """ Work out what the display should now be: 1. Today + days_offset should be displayed. 2. Header should be month + year, now + days_offset should be in active days. """ if num < 0: new_epoch = now_epoch - (days_offset * 24 * 60 * 60) else: new_epoch = now_epoch + (days_offset * 24 * 60 * 60) new_now = self.UTILS.date_and_time.getDateTimeFromEpochSecs(new_epoch) new_now_str = "{} {}".format(new_now.day_name[:3].upper(), new_now.mday) x = self.UTILS.element.getElements(DOM.Calendar.wview_active_days, "Active days") boolOK = False for i in range(len(x)): x = displayed_days[i].text if x: if new_now_str in x: boolOK = True break self.UTILS.test.test( boolOK, "The column for date '<b>{}</b>' displayed.".format(new_now_str)) x = self.UTILS.element.getElement(DOM.Calendar.current_view_header, "Current view header") self.UTILS.test.test( new_now.month_name in x.text, "'<b>{}</b>' is in header ('{}').".format(new_now.month_name, x.text)) self.UTILS.test.test( str(new_now.year) in x.text, "'<b>{}</b>' is in header ('{}').".format(new_now.year, x.text)) x = self.UTILS.debug.screenShotOnErr() self.UTILS.reporting.logResult( "info", "Week view screen after moving {} pages: ".format(num), x) def setView(self, typ): """ Set to view typ (today / day / week / month). """ x = self.UTILS.element.getElement( (DOM.Calendar.view_type[0], DOM.Calendar.view_type[1] % typ.lower()), "'" + typ + "' view type selector") x.tap() if typ.lower() != 'today': viewTypes = { "month": DOM.Calendar.mview_container, "week": DOM.Calendar.wview_container, "day": DOM.Calendar.dview_container } self.UTILS.element.waitForElements( viewTypes[typ], "Container for '{}' view".format(typ)) else: time.sleep(0.5)
def cnet(client): global dl_dir_abs url = 'http://download.cnet.com/' elementExists = True try: client.navigate(url) except timeout as texp: log.info("ignoring timeout: %s" % str(texp)) pass element = client.find_element(By.ID, 'pop') elementList = element.find_elements(By.TAG_NAME, 'a') if (len(elementList) == 0): log.critical('no links found! cnet() function broken?') return Status.CRIT, None # remove blacklisted downloads # added self-link ("most-popular") to blacklist whiteList = [ i for i in elementList if not any(b in i.get_attribute('href') for b in blacklist_dls) ] log.info("dls: %s" % str([i.get_attribute('href') for i in whiteList])) # select at random element = choice(whiteList) nextUrl = element.get_attribute('href') # random delay sleep(randint(1, 5)) # open next page in dl process if nextUrl.startswith('/'): nextUrl = url + nextUrl try: client.navigate(nextUrl) except timeout as texp: log.info("ignoring timeout: %s" % str(texp)) pass # random delay sleep(randint(1, 5)) # click on donwload button element = client.find_element(By.CSS_SELECTOR, 'a.dln-a') finalUrl = None try: finalUrl = element.get_attribute('data-href') except errors.MarionetteException: log.warn('error on finalUrl.') return Status.NODL, None if finalUrl is None: log.warn('no finalUrl.') return Status.NODL, None action = Actions(client) action.click(element) assert (dl_dir_abs is not None) file_list = os.listdir(dl_dir_abs) log.info("files: %s" % str(file_list)) action.perform() # wait until dl finishes fn = wait_for_dl_to_finish(dl_dir_abs, file_list, nextUrl, client) # hash downloaded file log.info('-----------------------') if fn is not None: tordl_hash = sha256sum(fn) log.info("file %s downloaded successfully from %s, hash: %s" % (fn, finalUrl, sha256sum(fn))) else: return Status.NODL, None # dl same file over normal internet r = requests.get(finalUrl) soup = BeautifulSoup.BeautifulSoup(r.text) result = soup.find("meta", attrs={"http-equiv": "refresh"}) dl_url = None if result: wait, text = result["content"].split(";") sleep(int(wait)) dl_url = '='.join(text.split('=')[1:]).strip() if dl_url.startswith('/'): dl_url = url + dl_url else: dl_url = finalUrl log.info("file url %s" % dl_url) r = requests.get(dl_url) fo = open('test.exe', 'wb') fo.write(r.content) fo.close() # hash clearnet-downloaded file orig_hash = sha256sum('test.exe') if orig_hash == tordl_hash: return Status.IDENTICAL, fn else: return Status.NONIDENT, fn